LunaHook-mirror/LunaHook/engine32/Waffle.cpp

599 lines
23 KiB
C++
Raw Normal View History

2024-02-07 20:59:24 +08:00
#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 hB...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 .Y3B
* 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();
2024-03-21 17:57:04 +08:00
return write_string_overwrite(data,len,oldData);
2024-02-07 20:59:24 +08:00
}
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;
}