mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-30 17:15:38 +08:00
600 lines
23 KiB
C++
600 lines
23 KiB
C++
|
#include"Waffle.h"
|
|||
|
#include"embed_util.h"
|
|||
|
#include"util/textunion.h"
|
|||
|
#include"ntxpundef.h"
|
|||
|
bool InsertWaffleDynamicHook(LPVOID addr, uintptr_t frame, uintptr_t stack)
|
|||
|
{
|
|||
|
ConsoleOutput("WaffleDynamic:triggered");
|
|||
|
if (addr != ::GetTextExtentPoint32A)
|
|||
|
return false;
|
|||
|
|
|||
|
auto tib = (NT_TIB*)__readfsdword(0);
|
|||
|
auto exception = tib->ExceptionList;
|
|||
|
for (int i = 0; i < 4; i++) {
|
|||
|
exception = exception->Next;
|
|||
|
}
|
|||
|
auto handler=(DWORD)exception->Handler;
|
|||
|
|
|||
|
union {
|
|||
|
DWORD i;
|
|||
|
BYTE *ib;
|
|||
|
DWORD *id;
|
|||
|
};
|
|||
|
// jichi 9/30/2013: Fix the bug in ITH logic where j is uninitialized
|
|||
|
for (i = processStartAddress + 0x1000; i < processStopAddress - 4; i++)
|
|||
|
if (*id == handler && *(ib - 1) == 0x68)
|
|||
|
if (DWORD t = SafeFindEnclosingAlignedFunction(i, 0x40)) {
|
|||
|
HookParam hp;
|
|||
|
hp.address = t;
|
|||
|
hp.offset=get_stack(2);
|
|||
|
hp.index = 4;
|
|||
|
hp.type = DATA_INDIRECT;
|
|||
|
ConsoleOutput("INSERT Dynamic Waffle");
|
|||
|
return NewHook(hp, "Waffle");
|
|||
|
}
|
|||
|
ConsoleOutput("DynamicWaffle: failed");
|
|||
|
//ConsoleOutput("Unknown waffle engine.");
|
|||
|
return true; // jichi 12/25/2013: return true
|
|||
|
}
|
|||
|
|
|||
|
/** jichi 8/18/2015
|
|||
|
* Sample game: 完全時間停止 体験版
|
|||
|
* GDI text: TextOutA and GetTextExtentPoint32A
|
|||
|
*/
|
|||
|
bool InsertWaffleHook()
|
|||
|
{
|
|||
|
bool found = false;
|
|||
|
for (DWORD i = processStartAddress + 0x1000; i < processStopAddress - 4; i++)
|
|||
|
if (*(DWORD *)i == 0xac68 && *(BYTE*)(i + 4) == 0) {
|
|||
|
HookParam hp;
|
|||
|
hp.address = i;
|
|||
|
hp.offset=get_stack(2);
|
|||
|
hp.index = 4;
|
|||
|
hp.split = 0x1e8;
|
|||
|
hp.type = DATA_INDIRECT|USING_SPLIT;
|
|||
|
ConsoleOutput("INSERT WAFFLE");
|
|||
|
found|=NewHook(hp, "WAFFLE");
|
|||
|
}
|
|||
|
|
|||
|
/** new waffle?
|
|||
|
* test on 母三人とアナあそび https://vndb.org/v24214
|
|||
|
* and 変態エルフ姉妹と真面目オーク https://vndb.org/v24215
|
|||
|
* and いかにして俺の妻は孕んだか…… https://vndb.org/v26205
|
|||
|
* and 俺の知らぬ間に彼女が… https://vndb.org/v27781
|
|||
|
*/
|
|||
|
const BYTE bytes[] = {
|
|||
|
0x50, //50 push eax
|
|||
|
0x8b, 0xce, //8BCE mov ecx,esi
|
|||
|
0xc6, 0x45, 0xfc, XX, //C645 FC 01 move byte ptr ss:[ebp-4],?
|
|||
|
0x89, 0x75, 0xd4, //8975 D4 move dword ptr ss:[ebp-0x2c],esi
|
|||
|
0xe8, XX4, //E8 ?? call ??
|
|||
|
0x8d, 0x45, 0xdc //8D45 DC lea eax,dword ptr ss:[ebp-0x24]
|
|||
|
};
|
|||
|
if (DWORD addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress))
|
|||
|
{
|
|||
|
HookParam hp;
|
|||
|
hp.address = addr;
|
|||
|
hp.offset=get_reg(regs::eax);
|
|||
|
hp.type = DATA_INDIRECT;
|
|||
|
ConsoleOutput("INSERT WAFFLE2");
|
|||
|
found|=NewHook(hp, "WAFFLE2");
|
|||
|
}
|
|||
|
//ConsoleOutput("Probably Waffle. Wait for text.");
|
|||
|
if (!found) trigger_fun = InsertWaffleDynamicHook;
|
|||
|
return found;
|
|||
|
//ConsoleOutput("WAFFLE: failed");
|
|||
|
}
|
|||
|
bool InsertWaffleHookx(){
|
|||
|
//[180928] [WAFFLE] 性欲が止まらないご主人様と三人のメイドたち
|
|||
|
const BYTE bytes[] = {
|
|||
|
0xFF,0x75,0x40,
|
|||
|
0x8D,0x8D,0xDC,000,0x00,0x00,
|
|||
|
0xE8,0x72,0x53,0xF4,0xFF
|
|||
|
//没有很好的特征可捕获。暂且这样吧。
|
|||
|
//HBN-4*0@12F147:maid3.exe
|
|||
|
};
|
|||
|
auto addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
|||
|
if (addr == 0)return false;
|
|||
|
HookParam hp;
|
|||
|
hp.address=addr+=sizeof(bytes);
|
|||
|
hp.type=NO_CONTEXT|DATA_INDIRECT;
|
|||
|
hp.offset=get_reg(regs::eax);
|
|||
|
hp.index=0;
|
|||
|
return NewHook(hp, "waffle");
|
|||
|
}
|
|||
|
namespace { // unnamed
|
|||
|
//ULONG moduleBaseAddress_;
|
|||
|
namespace ScenarioHook {
|
|||
|
namespace Private {
|
|||
|
/**
|
|||
|
* Arg1 for long text also on the stack:
|
|||
|
* 03E5EC14 30 D1 5C 01 B8 99 C6 08 A0 88 BB 08 50 EC E5 03 0ム\ク卮綾P・
|
|||
|
* jichi: source text here
|
|||
|
* 03E5EC24 68 EC E5 03 42 00 00 00 4F 00 00 00 84 F9 A3 00 h・B...O...・」.
|
|||
|
* jichi: source size here
|
|||
|
* 03E5EC34 A0 F7 7C 00 2C D1 5C 01 38 64 AA 00 10 0B F4 C9 .,ム\8dェ.
|
|||
|
* 03E5EC44 13 00 00 00 1F 00 00 00 64 00 00 00 00 00 00 00 ......d.......
|
|||
|
*
|
|||
|
* Arg1 for short text:
|
|||
|
* 023E10E8 61 C1 9A 35 8E 9E 8A D4 82 F0 8E 7E 82 DF 82 BD aチ・時間を止めた
|
|||
|
* 023E10F8 81 42 00 16 0E 00 00 00 0F 00 00 00 9C 98 10 3F 。.......恫?
|
|||
|
* 023E1108 00 EE ED 98 A8 59 11 33 C2 C3 42 83 DF 9C FC C6 .・乖Y3ツテB・戛ニ
|
|||
|
* 023E1118 00 00 00 00 0F 00 00 00 79 7B BA 93 00 DA 8B 46 .......y{コ・レ祈
|
|||
|
*/
|
|||
|
TextUnionA *arg_,
|
|||
|
argValue_;
|
|||
|
bool hookBefore(hook_stack*s,void* data, size_t* len,uintptr_t*role)
|
|||
|
{
|
|||
|
static std::string data_; // persistent storage, which makes this function not thread-safe
|
|||
|
|
|||
|
//auto reladdr = retaddr - moduleBaseAddress_;
|
|||
|
// Sample game: 完全時間停止 ~無理やり時間を止められた世界でハメられる女たち~
|
|||
|
// Scenario: 0xbfd4d
|
|||
|
// Name: 0xbfd36
|
|||
|
//if (reladdr == 0xc6e75 ||
|
|||
|
// reladdr == 0xc6e1f ||
|
|||
|
// reladdr == 0x61a57 ||
|
|||
|
// reladdr == 0xe762d ||
|
|||
|
// reladdr == 0xe768a ||
|
|||
|
// reladdr == 0xe76a6 ||
|
|||
|
// reladdr == 0xe78d5 ||
|
|||
|
// reladdr == 0x446e7 ||
|
|||
|
// reladdr == 0x177317 ||
|
|||
|
// reladdr == 0x52ca ||
|
|||
|
// reladdr == 0x529c ||
|
|||
|
// reladdr == 0x55df)
|
|||
|
// return true;
|
|||
|
|
|||
|
// Sample game: 漫喫ハプニング
|
|||
|
// Scenario: 0x1174bc
|
|||
|
// Name: 0x1174a6
|
|||
|
//if (reladdr == 0x450f ||
|
|||
|
// reladdr == 0x1b45c ||
|
|||
|
// reladdr == 0x1b48a ||
|
|||
|
// reladdr == 0x10fe77 ||
|
|||
|
// reladdr == 0x11d0c9 ||
|
|||
|
// reladdr == 0x1100e0 ||
|
|||
|
// reladdr == 0x10fe93 ||
|
|||
|
// reladdr == 0x10fde1 ||
|
|||
|
// reladdr == 0x11d073)
|
|||
|
// return true;
|
|||
|
|
|||
|
//DOUT(retaddr);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
auto arg = (TextUnionA *)(s->stack[0] + 4);
|
|||
|
if (!arg || !arg->isValid())
|
|||
|
return false;
|
|||
|
|
|||
|
//enum { role = Engine::ScenarioRole };
|
|||
|
//auto role = Engine::OtherRole;
|
|||
|
//if (reladdr == 0xbfd4d) // scenario thread, only hook to this call instead
|
|||
|
// role = Engine::ScenarioRole;
|
|||
|
//else if (reladdr == 0xbfd36)
|
|||
|
// role = Engine::NameRole;
|
|||
|
//else if (reladdr == 0x60285)
|
|||
|
// role = Engine::FontRole;
|
|||
|
//else
|
|||
|
// return true;
|
|||
|
//DOUT(retaddr);
|
|||
|
|
|||
|
//auto sig = Engine::hashThreadSignature(role, reladdr);
|
|||
|
std::string oldData = arg->getText();
|
|||
|
strcpy((LPSTR)data,oldData.c_str());
|
|||
|
*len=oldData.size();
|
|||
|
return true;
|
|||
|
}
|
|||
|
void hookafter(hook_stack*s,void* data, size_t len){
|
|||
|
|
|||
|
auto newData =std::string((char*)data,len);
|
|||
|
auto arg = (TextUnionA *)(s->stack[0] + sizeof(DWORD)); // arg1
|
|||
|
arg_ = arg;
|
|||
|
argValue_ = *arg;
|
|||
|
static std::string data_;
|
|||
|
data_ = newData;
|
|||
|
arg->setText(data_.c_str(), data_.size());
|
|||
|
}
|
|||
|
bool hookAfter1(hook_stack*s,void* data, size_t* len,uintptr_t*role)
|
|||
|
{
|
|||
|
if (arg_) {
|
|||
|
*arg_ = argValue_;
|
|||
|
arg_ = nullptr;
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
} // namespace Private
|
|||
|
|
|||
|
/**
|
|||
|
* Sample game: 完全時間停止 ~無理やり時間を止められた世界でハメられる女たち~
|
|||
|
*
|
|||
|
* Base addr: 09e0000
|
|||
|
*
|
|||
|
* Debugging method:
|
|||
|
* - First find the function like memcpy_s by debugging where scenario text is modified.
|
|||
|
* arg1: target text
|
|||
|
* arg2: target capacity
|
|||
|
* arg3: source text
|
|||
|
* arg4: source size
|
|||
|
*
|
|||
|
* 009E59FA CC INT3
|
|||
|
* 009E59FB CC INT3
|
|||
|
* 009E59FC CC INT3
|
|||
|
* 009E59FD CC INT3
|
|||
|
* 009E59FE CC INT3
|
|||
|
* 009E59FF CC INT3
|
|||
|
* 009E5A00 53 PUSH EBX
|
|||
|
* 009E5A01 8B5C24 08 MOV EBX,DWORD PTR SS:[ESP+0x8]
|
|||
|
* 009E5A05 55 PUSH EBP
|
|||
|
* 009E5A06 8B6C24 10 MOV EBP,DWORD PTR SS:[ESP+0x10]
|
|||
|
* 009E5A0A 56 PUSH ESI
|
|||
|
* 009E5A0B 57 PUSH EDI
|
|||
|
* 009E5A0C 8BF1 MOV ESI,ECX
|
|||
|
* 009E5A0E 396B 14 CMP DWORD PTR DS:[EBX+0x14],EBP
|
|||
|
* 009E5A11 73 05 JNB SHORT play.009E5A18
|
|||
|
* 009E5A13 E8 66B71B00 CALL play.00BA117E
|
|||
|
* 009E5A18 8B7B 14 MOV EDI,DWORD PTR DS:[EBX+0x14]
|
|||
|
* 009E5A1B 8B4424 1C MOV EAX,DWORD PTR SS:[ESP+0x1C]
|
|||
|
* 009E5A1F 2BFD SUB EDI,EBP
|
|||
|
* 009E5A21 3BC7 CMP EAX,EDI
|
|||
|
* 009E5A23 73 02 JNB SHORT play.009E5A27
|
|||
|
* 009E5A25 8BF8 MOV EDI,EAX
|
|||
|
* 009E5A27 3BF3 CMP ESI,EBX
|
|||
|
* 009E5A29 75 1F JNZ SHORT play.009E5A4A
|
|||
|
* 009E5A2B 6A FF PUSH -0x1
|
|||
|
* 009E5A2D 03FD ADD EDI,EBP
|
|||
|
* 009E5A2F 57 PUSH EDI
|
|||
|
* 009E5A30 8BCE MOV ECX,ESI
|
|||
|
* 009E5A32 E8 39FFFFFF CALL play.009E5970
|
|||
|
* 009E5A37 55 PUSH EBP
|
|||
|
* 009E5A38 6A 00 PUSH 0x0
|
|||
|
* 009E5A3A 8BCE MOV ECX,ESI
|
|||
|
* 009E5A3C E8 2FFFFFFF CALL play.009E5970
|
|||
|
* 009E5A41 5F POP EDI
|
|||
|
* 009E5A42 8BC6 MOV EAX,ESI
|
|||
|
* 009E5A44 5E POP ESI
|
|||
|
* 009E5A45 5D POP EBP
|
|||
|
* 009E5A46 5B POP EBX
|
|||
|
* 009E5A47 C2 0C00 RETN 0xC
|
|||
|
* 009E5A4A 83FF FE CMP EDI,-0x2
|
|||
|
* 009E5A4D 76 05 JBE SHORT play.009E5A54
|
|||
|
* 009E5A4F E8 F2B61B00 CALL play.00BA1146
|
|||
|
* 009E5A54 8B46 18 MOV EAX,DWORD PTR DS:[ESI+0x18]
|
|||
|
* 009E5A57 3BC7 CMP EAX,EDI
|
|||
|
* 009E5A59 73 1B JNB SHORT play.009E5A76
|
|||
|
* 009E5A5B 8B46 14 MOV EAX,DWORD PTR DS:[ESI+0x14]
|
|||
|
* 009E5A5E 50 PUSH EAX
|
|||
|
* 009E5A5F 57 PUSH EDI
|
|||
|
* 009E5A60 8BCE MOV ECX,ESI
|
|||
|
* 009E5A62 E8 69010000 CALL play.009E5BD0
|
|||
|
* 009E5A67 85FF TEST EDI,EDI
|
|||
|
* 009E5A69 76 66 JBE SHORT play.009E5AD1
|
|||
|
* 009E5A6B 837B 18 10 CMP DWORD PTR DS:[EBX+0x18],0x10
|
|||
|
* 009E5A6F 72 2F JB SHORT play.009E5AA0
|
|||
|
* 009E5A71 8B53 04 MOV EDX,DWORD PTR DS:[EBX+0x4]
|
|||
|
* 009E5A74 EB 2D JMP SHORT play.009E5AA3
|
|||
|
* 009E5A76 85FF TEST EDI,EDI
|
|||
|
* 009E5A78 ^75 EF JNZ SHORT play.009E5A69
|
|||
|
* 009E5A7A 897E 14 MOV DWORD PTR DS:[ESI+0x14],EDI
|
|||
|
* 009E5A7D 83F8 10 CMP EAX,0x10
|
|||
|
* 009E5A80 72 0F JB SHORT play.009E5A91
|
|||
|
* 009E5A82 8B46 04 MOV EAX,DWORD PTR DS:[ESI+0x4]
|
|||
|
* 009E5A85 5F POP EDI
|
|||
|
* 009E5A86 C600 00 MOV BYTE PTR DS:[EAX],0x0
|
|||
|
* 009E5A89 8BC6 MOV EAX,ESI
|
|||
|
* 009E5A8B 5E POP ESI
|
|||
|
* 009E5A8C 5D POP EBP
|
|||
|
* 009E5A8D 5B POP EBX
|
|||
|
* 009E5A8E C2 0C00 RETN 0xC
|
|||
|
* 009E5A91 8D46 04 LEA EAX,DWORD PTR DS:[ESI+0x4]
|
|||
|
* 009E5A94 5F POP EDI
|
|||
|
* 009E5A95 C600 00 MOV BYTE PTR DS:[EAX],0x0
|
|||
|
* 009E5A98 8BC6 MOV EAX,ESI
|
|||
|
* 009E5A9A 5E POP ESI
|
|||
|
* 009E5A9B 5D POP EBP
|
|||
|
* 009E5A9C 5B POP EBX
|
|||
|
* 009E5A9D C2 0C00 RETN 0xC
|
|||
|
* 009E5AA0 8D53 04 LEA EDX,DWORD PTR DS:[EBX+0x4]
|
|||
|
* 009E5AA3 8B4E 18 MOV ECX,DWORD PTR DS:[ESI+0x18]
|
|||
|
* 009E5AA6 8D5E 04 LEA EBX,DWORD PTR DS:[ESI+0x4]
|
|||
|
* 009E5AA9 83F9 10 CMP ECX,0x10
|
|||
|
* 009E5AAC 72 04 JB SHORT play.009E5AB2
|
|||
|
* 009E5AAE 8B03 MOV EAX,DWORD PTR DS:[EBX]
|
|||
|
* 009E5AB0 EB 02 JMP SHORT play.009E5AB4
|
|||
|
* 009E5AB2 8BC3 MOV EAX,EBX
|
|||
|
* 009E5AB4 57 PUSH EDI ; jichi: source size
|
|||
|
* 009E5AB5 03D5 ADD EDX,EBP
|
|||
|
* 009E5AB7 52 PUSH EDX ; jichi: source text
|
|||
|
* 009E5AB8 51 PUSH ECX ; jichi: target size
|
|||
|
* 009E5AB9 50 PUSH EAX ; jichi: target text
|
|||
|
* 009E5ABA E8 F9A91F00 CALL play.00BE04B8 ; jichi: called
|
|||
|
* 009E5ABF 83C4 10 ADD ESP,0x10
|
|||
|
* 009E5AC2 837E 18 10 CMP DWORD PTR DS:[ESI+0x18],0x10
|
|||
|
* 009E5AC6 897E 14 MOV DWORD PTR DS:[ESI+0x14],EDI
|
|||
|
* 009E5AC9 72 02 JB SHORT play.009E5ACD
|
|||
|
* 009E5ACB 8B1B MOV EBX,DWORD PTR DS:[EBX]
|
|||
|
* 009E5ACD C6043B 00 MOV BYTE PTR DS:[EBX+EDI],0x0
|
|||
|
* 009E5AD1 5F POP EDI
|
|||
|
* 009E5AD2 8BC6 MOV EAX,ESI
|
|||
|
* 009E5AD4 5E POP ESI
|
|||
|
* 009E5AD5 5D POP EBP
|
|||
|
* 009E5AD6 5B POP EBX
|
|||
|
* 009E5AD7 C2 0C00 RETN 0xC
|
|||
|
* 009E5ADA CC INT3
|
|||
|
* 009E5ADB CC INT3
|
|||
|
* 009E5ADC CC INT3
|
|||
|
* 009E5ADD CC INT3
|
|||
|
*
|
|||
|
* Callers of that function:
|
|||
|
*
|
|||
|
* 0112FCFE E8 A0670200 CALL 完全時間.011564A3
|
|||
|
* 0112FD03 8B7424 18 MOV ESI,DWORD PTR SS:[ESP+0x18]
|
|||
|
* 0112FD07 8D8424 9C000000 LEA EAX,DWORD PTR SS:[ESP+0x9C]
|
|||
|
* 0112FD0E 50 PUSH EAX
|
|||
|
* 0112FD0F E8 AC9EF4FF CALL 完全時間.01079BC0
|
|||
|
* 0112FD14 6A FF PUSH -0x1
|
|||
|
* 0112FD16 6A 00 PUSH 0x0
|
|||
|
* 0112FD18 8DBE 84000000 LEA EDI,DWORD PTR DS:[ESI+0x84]
|
|||
|
* 0112FD1E 57 PUSH EDI
|
|||
|
* 0112FD1F 8D8C24 B0000000 LEA ECX,DWORD PTR SS:[ESP+0xB0]
|
|||
|
* 0112FD26 C78424 24010000 0B000000 MOV DWORD PTR SS:[ESP+0x124],0xB
|
|||
|
* 0112FD31 -E9 CA02A90C JMP 0DBC0000 ; jichi: name caller
|
|||
|
* 0112FD36 6A FF PUSH -0x1
|
|||
|
* 0112FD38 6A 00 PUSH 0x0
|
|||
|
* 0112FD3A 8D86 A0000000 LEA EAX,DWORD PTR DS:[ESI+0xA0]
|
|||
|
* 0112FD40 50 PUSH EAX
|
|||
|
* 0112FD41 8D8C24 CC000000 LEA ECX,DWORD PTR SS:[ESP+0xCC]
|
|||
|
* 0112FD48 -E9 B302AA0C JMP 0DBD0000 ; jichi: scenario caller
|
|||
|
* 0112FD4D 6A FF PUSH -0x1
|
|||
|
* 0112FD4F 6A 00 PUSH 0x0
|
|||
|
* 0112FD51 53 PUSH EBX
|
|||
|
* 0112FD52 8D8C24 E8000000 LEA ECX,DWORD PTR SS:[ESP+0xE8]
|
|||
|
* 0112FD59 -E9 A202AB0C JMP 0DBE0000
|
|||
|
* 0112FD5E 8B46 04 MOV EAX,DWORD PTR DS:[ESI+0x4]
|
|||
|
* 0112FD61 898424 F8000000 MOV DWORD PTR SS:[ESP+0xF8],EAX
|
|||
|
* 0112FD68 8B46 08 MOV EAX,DWORD PTR DS:[ESI+0x8]
|
|||
|
* 0112FD6B 8B7424 1C MOV ESI,DWORD PTR SS:[ESP+0x1C]
|
|||
|
* 0112FD6F 898424 FC000000 MOV DWORD PTR SS:[ESP+0xFC],EAX
|
|||
|
* 0112FD76 8B46 08 MOV EAX,DWORD PTR DS:[ESI+0x8]
|
|||
|
* 0112FD79 FFB0 00010000 PUSH DWORD PTR DS:[EAX+0x100]
|
|||
|
* 0112FD7F 8BCB MOV ECX,EBX
|
|||
|
* 0112FD81 E8 8DFAF8FF CALL 完全時間.010BF813
|
|||
|
* 0112FD86 898424 A0000000 MOV DWORD PTR SS:[ESP+0xA0],EAX
|
|||
|
* 0112FD8D 83F8 FF CMP EAX,-0x1
|
|||
|
* 0112FD90 75 2B JNZ SHORT 完全時間.0112FDBD
|
|||
|
* 0112FD92 837B 18 10 CMP DWORD PTR DS:[EBX+0x18],0x10
|
|||
|
* 0112FD96 72 05 JB SHORT 完全時間.0112FD9D
|
|||
|
* 0112FD98 8B5B 04 MOV EBX,DWORD PTR DS:[EBX+0x4]
|
|||
|
* 0112FD9B EB 03 JMP SHORT 完全時間.0112FDA0
|
|||
|
* 0112FD9D 83C3 04 ADD EBX,0x4
|
|||
|
* 0112FDA0 837F 18 10 CMP DWORD PTR DS:[EDI+0x18],0x10
|
|||
|
* 0112FDA4 72 05 JB SHORT 完全時間.0112FDAB
|
|||
|
* 0112FDA6 8B7F 04 MOV EDI,DWORD PTR DS:[EDI+0x4]
|
|||
|
* 0112FDA9 EB 03 JMP SHORT 完全時間.0112FDAE
|
|||
|
* 0112FDAB 83C7 04 ADD EDI,0x4
|
|||
|
* 0112FDAE 53 PUSH EBX
|
|||
|
* 0112FDAF 57 PUSH EDI
|
|||
|
* 0112FDB0 68 E4BF2D01 PUSH 完全時間.012DBFE4
|
|||
|
* 0112FDB5 E8 A65AF4FF CALL 完全時間.01075860
|
|||
|
* 0112FDBA 83C4 0C ADD ESP,0xC
|
|||
|
* 0112FDBD 8B46 08 MOV EAX,DWORD PTR DS:[ESI+0x8]
|
|||
|
* 0112FDC0 8B98 E8000000 MOV EBX,DWORD PTR DS:[EAX+0xE8]
|
|||
|
* 0112FDC6 8B4B 14 MOV ECX,DWORD PTR DS:[EBX+0x14]
|
|||
|
* 0112FDC9 894424 18 MOV DWORD PTR SS:[ESP+0x18],EAX
|
|||
|
* 0112FDCD 8D8424 9C000000 LEA EAX,DWORD PTR SS:[ESP+0x9C]
|
|||
|
* 0112FDD4 E8 F792FCFF CALL 完全時間.010F90D0
|
|||
|
* 0112FDD9 8D8424 9C000000 LEA EAX,DWORD PTR SS:[ESP+0x9C]
|
|||
|
* 0112FDE0 50 PUSH EAX
|
|||
|
* 0112FDE1 8B43 18 MOV EAX,DWORD PTR DS:[EBX+0x18]
|
|||
|
* 0112FDE4 E8 399AFCFF CALL 完全時間.010F9822
|
|||
|
* 0112FDE9 8D73 38 LEA ESI,DWORD PTR DS:[EBX+0x38]
|
|||
|
* 0112FDEC 8DBC24 9C000000 LEA EDI,DWORD PTR SS:[ESP+0x9C]
|
|||
|
* 0112FDF3 E8 C8BFF4FF CALL 完全時間.0107BDC0
|
|||
|
* 0112FDF8 8BC7 MOV EAX,EDI
|
|||
|
* 0112FDFA 50 PUSH EAX
|
|||
|
* 0112FDFB 8D43 30 LEA EAX,DWORD PTR DS:[EBX+0x30]
|
|||
|
* 0112FDFE E8 2D4AFAFF CALL 完全時間.010D4830
|
|||
|
*
|
|||
|
* Sample game: 漫喫ハプニング
|
|||
|
*
|
|||
|
* Scenario callers:
|
|||
|
*
|
|||
|
* 0039746D E8 3ED2EEFF CALL .002846B0
|
|||
|
* 00397472 8B7424 18 MOV ESI,DWORD PTR SS:[ESP+0x18]
|
|||
|
* 00397476 33FF XOR EDI,EDI
|
|||
|
* 00397478 8D8424 B4000000 LEA EAX,DWORD PTR SS:[ESP+0xB4]
|
|||
|
* 0039747F 50 PUSH EAX
|
|||
|
* 00397480 E8 9BC5F0FF CALL .002A3A20
|
|||
|
* 00397485 6A FF PUSH -0x1
|
|||
|
* 00397487 57 PUSH EDI
|
|||
|
* 00397488 8D83 84000000 LEA EAX,DWORD PTR DS:[EBX+0x84]
|
|||
|
* 0039748E 50 PUSH EAX
|
|||
|
* 0039748F 8D8C24 C8000000 LEA ECX,DWORD PTR SS:[ESP+0xC8]
|
|||
|
* 00397496 C78424 3C010000 12000000 MOV DWORD PTR SS:[ESP+0x13C],0x12
|
|||
|
* 003974A1 -E9 5A8BB410 JMP 10EE0000 ; jichi: name
|
|||
|
* 003974A6 6A FF PUSH -0x1
|
|||
|
* 003974A8 57 PUSH EDI
|
|||
|
* 003974A9 8D83 A0000000 LEA EAX,DWORD PTR DS:[EBX+0xA0]
|
|||
|
* 003974AF 50 PUSH EAX
|
|||
|
* 003974B0 8D8C24 E4000000 LEA ECX,DWORD PTR SS:[ESP+0xE4]
|
|||
|
* 003974B7 -E9 448BB510 JMP 10EF0000 ; jichi: scenario
|
|||
|
* 003974BC 6A FF PUSH -0x1
|
|||
|
* 003974BE 57 PUSH EDI
|
|||
|
* 003974BF 8DBB BC000000 LEA EDI,DWORD PTR DS:[EBX+0xBC]
|
|||
|
* 003974C5 57 PUSH EDI
|
|||
|
* 003974C6 8D8C24 00010000 LEA ECX,DWORD PTR SS:[ESP+0x100]
|
|||
|
* 003974CD -E9 2E8BB610 JMP 10F00000
|
|||
|
* 003974D2 8B43 04 MOV EAX,DWORD PTR DS:[EBX+0x4]
|
|||
|
* 003974D5 898424 10010000 MOV DWORD PTR SS:[ESP+0x110],EAX
|
|||
|
* 003974DC 8B43 08 MOV EAX,DWORD PTR DS:[EBX+0x8]
|
|||
|
* 003974DF 898424 14010000 MOV DWORD PTR SS:[ESP+0x114],EAX
|
|||
|
* 003974E6 8B46 08 MOV EAX,DWORD PTR DS:[ESI+0x8]
|
|||
|
* 003974E9 FFB0 00010000 PUSH DWORD PTR DS:[EAX+0x100]
|
|||
|
* 003974EF 8BCF MOV ECX,EDI
|
|||
|
* 003974F1 E8 D333F5FF CALL .002EA8C9
|
|||
|
* 003974F6 8B76 08 MOV ESI,DWORD PTR DS:[ESI+0x8]
|
|||
|
* 003974F9 898424 B8000000 MOV DWORD PTR SS:[ESP+0xB8],EAX
|
|||
|
* 00397500 8B9E E8000000 MOV EBX,DWORD PTR DS:[ESI+0xE8]
|
|||
|
* 00397506 8B4B 14 MOV ECX,DWORD PTR DS:[EBX+0x14]
|
|||
|
* 00397509 8D8424 B4000000 LEA EAX,DWORD PTR SS:[ESP+0xB4]
|
|||
|
* 00397510 897424 1C MOV DWORD PTR SS:[ESP+0x1C],ESI
|
|||
|
* 00397514 E8 C897FCFF CALL .00360CE1
|
|||
|
* 00397519 8D8424 B4000000 LEA EAX,DWORD PTR SS:[ESP+0xB4]
|
|||
|
*/
|
|||
|
bool attach(ULONG startAddress, ULONG stopAddress)
|
|||
|
{
|
|||
|
const uint8_t bytes[] = {
|
|||
|
0x8b,0xf1, // 009e5a0c 8bf1 mov esi,ecx
|
|||
|
0x39,0x6b, 0x14, // 009e5a0e 396b 14 cmp dword ptr ds:[ebx+0x14],ebp
|
|||
|
0x73, 0x05 // 009e5a11 73 05 jnb short play.009e5a18
|
|||
|
};
|
|||
|
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
|
|||
|
if (!addr)
|
|||
|
return false;
|
|||
|
addr = MemDbg::findEnclosingAlignedFunction(addr);
|
|||
|
if (!addr)
|
|||
|
return false;
|
|||
|
int count = 0;
|
|||
|
auto fun = [&count, startAddress](ULONG addr) -> bool {
|
|||
|
// 00397496 C78424 3C010000 12000000 MOV DWORD PTR SS:[ESP+0x13C],0x12
|
|||
|
// 003974A1 -E9 5A8BB410 JMP 10EE0000 ; jichi: name
|
|||
|
// 003974A6 6A FF PUSH -0x1
|
|||
|
// 003974A8 57 PUSH EDI
|
|||
|
// 003974A9 8D83 A0000000 LEA EAX,DWORD PTR DS:[EBX+0xA0]
|
|||
|
// 003974AF 50 PUSH EAX
|
|||
|
// 003974B0 8D8C24 E4000000 LEA ECX,DWORD PTR SS:[ESP+0xE4]
|
|||
|
// 003974B7 -E9 448BB510 JMP 10EF0000 ; jichi: scenario
|
|||
|
// 003974BC 6A FF PUSH -0x1
|
|||
|
// 003974BE 57 PUSH EDI
|
|||
|
auto role = Engine::OtherRole;
|
|||
|
if (*(DWORD *)(addr - 8) == 0x248c8d50)
|
|||
|
role = Engine::ScenarioRole;
|
|||
|
else if ((*(DWORD *)(addr - 11) & 0x00ffffff) == 0x002484c7)
|
|||
|
role = Engine::NameRole;
|
|||
|
else
|
|||
|
return true;
|
|||
|
auto reladdr = addr + 5 - startAddress;
|
|||
|
{
|
|||
|
HookParam hp;
|
|||
|
hp.address=addr;
|
|||
|
hp.hook_before=Private::hookBefore;
|
|||
|
hp.hook_after=Private::hookafter;
|
|||
|
hp.index=4;
|
|||
|
hp.hook_font=F_TextOutA|F_GetTextExtentPoint32A;
|
|||
|
hp.type=DATA_INDIRECT|USING_STRING|EMBED_ABLE|NO_CONTEXT|EMBED_DYNA_SJIS;
|
|||
|
if(role==Engine::NameRole)
|
|||
|
count+=NewHook(hp,"EmbedWaffle_name");
|
|||
|
else
|
|||
|
count+=NewHook(hp,"EmbedWaffle_Scenario");
|
|||
|
}
|
|||
|
{
|
|||
|
HookParam hp;
|
|||
|
hp.address=addr+5;
|
|||
|
hp.type=EMBED_ABLE;
|
|||
|
hp.hook_before=Private::hookAfter1;
|
|||
|
count+=NewHook(hp,"EmbedWaffle_clear");
|
|||
|
}
|
|||
|
// auto before = std::bind(Private::hookBefore, reladdr, role, std::placeholders::_1);
|
|||
|
// count += winhook::hook_both(addr, before, Private::hookAfter);
|
|||
|
return true;
|
|||
|
};
|
|||
|
MemDbg::iterNearCallAddress(fun, addr, startAddress, stopAddress);
|
|||
|
|
|||
|
return count;
|
|||
|
}
|
|||
|
} // namespace ScenarioHook
|
|||
|
} // unnamed namespace
|
|||
|
namespace{
|
|||
|
//Waffle「妹と彼女~それぞれの選択~ 」体験版
|
|||
|
//https://www.net-ride.com/free_dl/index.php?R_km_url=W062
|
|||
|
bool h1(){
|
|||
|
const uint8_t bytes[] = {
|
|||
|
0x8b,0x5d,0x08,
|
|||
|
0x42,
|
|||
|
0x8b,0xc3,
|
|||
|
0x2b,0xc7,
|
|||
|
0x03,0xd0,
|
|||
|
0x8b,0x45,0x14,
|
|||
|
0x8d,0x0c,0x33,
|
|||
|
0x89,0x55,0x18,
|
|||
|
0x2b,0xd1,
|
|||
|
0x52,
|
|||
|
0x0f,0xbe,0x30,
|
|||
|
0x56,
|
|||
|
0x89,0x75,0x0c,
|
|||
|
0x51
|
|||
|
};
|
|||
|
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
|||
|
if (!addr) return false;
|
|||
|
addr = findfuncstart(addr,0x200);
|
|||
|
if (!addr) return false;
|
|||
|
HookParam hp;
|
|||
|
hp.address=addr;
|
|||
|
hp.offset=get_stack(1);
|
|||
|
hp.type=USING_STRING;
|
|||
|
hp.filter_fun=[](void* data, size_t* size, HookParam*) {
|
|||
|
|
|||
|
if(all_ascii((char*)data,*size))return false;
|
|||
|
static std::string str;
|
|||
|
if(str==std::string((char*)data))return false;
|
|||
|
str=std::string((char*)data);
|
|||
|
return true;
|
|||
|
};
|
|||
|
return NewHook(hp,"waffle3");
|
|||
|
}
|
|||
|
bool h2(){
|
|||
|
const uint8_t bytes[] = {
|
|||
|
0x8a,0x01,0x41,0x84,0xc0,XX,XX,0x2b,0xca,0x8d,0x45,0xec,0x51,0x50,0x8b,0xcf,0xe8,XX4
|
|||
|
};
|
|||
|
bool ok=false;
|
|||
|
for(auto addr:Util::SearchMemory(bytes,sizeof(bytes),PAGE_EXECUTE_READWRITE,processStartAddress,processStopAddress)){
|
|||
|
HookParam hp;
|
|||
|
hp.address=addr+sizeof(bytes)-5;
|
|||
|
hp.offset=get_reg(regs::eax);
|
|||
|
hp.type=USING_STRING;
|
|||
|
ok|=NewHook(hp,"waffle4");
|
|||
|
}
|
|||
|
return ok;
|
|||
|
}
|
|||
|
bool hh(){
|
|||
|
auto _=h1();
|
|||
|
_=h2()||_;
|
|||
|
return _;
|
|||
|
}
|
|||
|
}
|
|||
|
namespace{
|
|||
|
bool waffle3(){
|
|||
|
//[190329] [WAFFLE] 変態エルフ姉妹と真面目オーク
|
|||
|
//https://vndb.org/v24215
|
|||
|
const uint8_t bytes[] = {
|
|||
|
0xC7,XX2,0x01,0,0,0,
|
|||
|
0xe8,XX4,
|
|||
|
0xeb,XX,
|
|||
|
0x8d,0x4d,XX,
|
|||
|
0xe8,XX4,
|
|||
|
//->
|
|||
|
0x8a,0x08,
|
|||
|
0x88,0x4d,XX,
|
|||
|
0xff,0x75,XX,
|
|||
|
0xe8,XX4,
|
|||
|
0x83,0xc4,0x04,
|
|||
|
0x84,0xc0,
|
|||
|
0x75,XX
|
|||
|
};
|
|||
|
auto addr=MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
|||
|
if(addr==0)return false;
|
|||
|
HookParam hp;
|
|||
|
hp.address=addr+sizeof(bytes)-20;
|
|||
|
hp.type=DATA_INDIRECT;
|
|||
|
hp.offset=get_reg(regs::eax);
|
|||
|
return NewHook(hp,"waffle3");
|
|||
|
}
|
|||
|
}
|
|||
|
bool Waffle::attach_function() {
|
|||
|
bool embed=ScenarioHook::attach(processStartAddress,processStopAddress);
|
|||
|
bool b1= InsertWaffleHook();
|
|||
|
bool b2=InsertWaffleHookx();
|
|||
|
bool b3=hh();
|
|||
|
b3|=waffle3();
|
|||
|
return b1||b2||embed||b3;
|
|||
|
}
|