#include"Rejet.h" namespace { // unnamed Rejet /** * jichi 12/22/2013: Rejet * See (CaoNiMaGeBi): http://www.hongfire.com/forum/printthread.php?t=36807&pp=40&page=172 * See (CaoNiMaGeBi): http://tieba.baidu.com/p/2506179113 * Pattern: 2bce8bf8 * 2bce sub ecx,esi ; hook here * 8bf8 mov eds,eax * 8bd1 mov edx,ecx * * Examples: * - Type1: ドットカレシ-We're 8bit Lovers!: /HBN-4*0@A5332:DotKareshi.exe * length_offset: 1 * off: 0xfffffff8 (-0x8) * type: 1096 (0x448) * * processStartAddress = 10e0000 (variant) * hook_addr = processStartAddress + reladdr = 0xe55332 * 01185311 . FFF0 PUSH EAX ; beginning of a new function * 01185313 . 0FC111 XADD DWORD PTR DS:[ECX],EDX * 01185316 . 4A DEC EDX * 01185317 . 85D2 TEST EDX,EDX * 01185319 . 0F8F 45020000 JG DotKares.01185564 * 0118531F . 8B08 MOV ECX,DWORD PTR DS:[EAX] * 01185321 . 8B11 MOV EDX,DWORD PTR DS:[ECX] * 01185323 . 50 PUSH EAX * 01185324 . 8B42 04 MOV EAX,DWORD PTR DS:[EDX+0x4] * 01185327 . FFD0 CALL EAX * 01185329 . E9 36020000 JMP DotKares.01185564 * 0118532E . 8B7424 20 MOV ESI,DWORD PTR SS:[ESP+0x20] * 01185332 . E8 99A9FBFF CALL DotKares.0113FCD0 ; hook here * 01185337 . 8BF0 MOV ESI,EAX * 01185339 . 8D4C24 14 LEA ECX,DWORD PTR SS:[ESP+0x14] * 0118533D . 3BF7 CMP ESI,EDI * 0118533F . 0F84 1A020000 JE DotKares.0118555F * 01185345 . 51 PUSH ECX ; /Arg2 * 01185346 . 68 E4FE5501 PUSH DotKares.0155FEE4 ; |Arg1 = 0155FEE4 * 0118534B . E8 1023F9FF CALL DotKares.01117660 ; \DotKares.00377660 * 01185350 . 83C4 08 ADD ESP,0x8 * 01185353 . 84C0 TEST AL,AL * * - Type2: ドットカレシ-We're 8bit Lovers! II: /HBN-8*0@A7AF9:dotkareshi.exe * off: 4294967284 (0xfffffff4 = -0xc) * length_offset: 1 * type: 1096 (0x448) * * processStartAddress: 0x12b0000 * * 01357ad2 . fff0 push eax ; beginning of a new function * 01357ad4 . 0fc111 xadd dword ptr ds:[ecx],edx * 01357ad7 . 4a dec edx * 01357ad8 . 85d2 test edx,edx * 01357ada . 7f 0a jg short dotkares.01357ae6 * 01357adc . 8b08 mov ecx,dword ptr ds:[eax] * 01357ade . 8b11 mov edx,dword ptr ds:[ecx] * 01357ae0 . 50 push eax * 01357ae1 . 8b42 04 mov eax,dword ptr ds:[edx+0x4] * 01357ae4 . ffd0 call eax * 01357ae6 > 8b4c24 14 mov ecx,dword ptr ss:[esp+0x14] * 01357aea . 33ff xor edi,edi * 01357aec . 3979 f4 cmp dword ptr ds:[ecx-0xc],edi * 01357aef . 0f84 1e020000 je dotkares.01357d13 * 01357af5 . 8b7424 20 mov esi,dword ptr ss:[esp+0x20] * 01357af9 . e8 7283fbff call dotkares.0130fe70 ; jichi: hook here * 01357afe . 8bf0 mov esi,eax * 01357b00 . 3bf7 cmp esi,edi * 01357b02 . 0f84 0b020000 je dotkares.01357d13 * 01357b08 . 8d5424 14 lea edx,dword ptr ss:[esp+0x14] * 01357b0c . 52 push edx ; /arg2 * 01357b0d . 68 cc9f7501 push dotkares.01759fcc ; |arg1 = 01759fcc * 01357b12 . e8 e9f9f8ff call dotkares.012e7500 ; \dotkares.012c7500 * 01357b17 . 83c4 08 add esp,0x8 * 01357b1a . 84c0 test al,al * 01357b1c . 74 1d je short dotkares.01357b3b * 01357b1e . 8d46 64 lea eax,dword ptr ds:[esi+0x64] * 01357b21 . e8 bad0f8ff call dotkares.012e4be0 * 01357b26 . 68 28a17501 push dotkares.0175a128 ; /arg1 = 0175a128 ascii "
" * * - Type2: Tiny×MACHINEGUN: /HBN-8*0@4CEB8:TinyMachinegun.exe * processStartAddress: 0x12f0000 * There are two possible places to hook * * 0133cea0 . fff0 push eax ; beginning of a new function * 0133cea2 . 0fc111 xadd dword ptr ds:[ecx],edx * 0133cea5 . 4a dec edx * 0133cea6 . 85d2 test edx,edx * 0133cea8 . 7f 0a jg short tinymach.0133ceb4 * 0133ceaa . 8b08 mov ecx,dword ptr ds:[eax] * 0133ceac . 8b11 mov edx,dword ptr ds:[ecx] * 0133ceae . 50 push eax * 0133ceaf . 8b42 04 mov eax,dword ptr ds:[edx+0x4] * 0133ceb2 . ffd0 call eax * 0133ceb4 > 8b4c24 14 mov ecx,dword ptr ss:[esp+0x14] * 0133ceb8 . 33db xor ebx,ebx ; jichi: hook here * 0133ceba . 3959 f4 cmp dword ptr ds:[ecx-0xc],ebx * 0133cebd . 0f84 d4010000 je tinymach.0133d097 * 0133cec3 . 8b7424 20 mov esi,dword ptr ss:[esp+0x20] * 0133cec7 . e8 f4f90100 call tinymach.0135c8c0 ; jichi: or hook here * 0133cecc . 8bf0 mov esi,eax * 0133cece . 3bf3 cmp esi,ebx * 0133ced0 . 0f84 c1010000 je tinymach.0133d097 * 0133ced6 . 8d5424 14 lea edx,dword ptr ss:[esp+0x14] * 0133ceda . 52 push edx ; /arg2 * 0133cedb . 68 44847d01 push tinymach.017d8444 ; |arg1 = 017d8444 * 0133cee0 . e8 eb5bfdff call tinymach.01312ad0 ; \tinymach.011b2ad0 * * - Type 3: 剣が君: /HBN-8*0@B357D:KenGaKimi.exe * * 01113550 . fff0 push eax * 01113552 . 0fc111 xadd dword ptr ds:[ecx],edx * 01113555 . 4a dec edx * 01113556 . 85d2 test edx,edx * 01113558 . 7f 0a jg short kengakim.01113564 * 0111355a . 8b08 mov ecx,dword ptr ds:[eax] * 0111355c . 8b11 mov edx,dword ptr ds:[ecx] * 0111355e . 50 push eax * 0111355f . 8b42 04 mov eax,dword ptr ds:[edx+0x4] * 01113562 . ffd0 call eax * 01113564 8b4c24 14 mov ecx,dword ptr ss:[esp+0x14] * 01113568 33ff xor edi,edi * 0111356a 3979 f4 cmp dword ptr ds:[ecx-0xc],edi * 0111356d 0f84 09020000 je kengakim.0111377c * 01113573 8d5424 14 lea edx,dword ptr ss:[esp+0x14] * 01113577 52 push edx * 01113578 68 dc6a5401 push kengakim.01546adc * 0111357d e8 3eaff6ff call kengakim.0107e4c0 ; hook here */ bool FindRejetHook(LPCVOID pattern, DWORD pattern_size, DWORD hook_off, DWORD hook_offset, LPCSTR hook_name = "Rejet") { // Offset to the function call from the beginning of the function //enum { addr_offset = 0x21 }; // Type1: hex(0x01185332-0x01185311) //const BYTE pattern[] = { // Type1: Function start // 0xff,0xf0, // 01185311 . fff0 push eax ; beginning of a new function // 0x0f,0xc1,0x11, // 01185313 . 0fc111 xadd dword ptr ds:[ecx],edx // 0x4a, // 01185316 . 4a dec edx // 0x85,0xd2, // 01185317 . 85d2 test edx,edx // 0x0f,0x8f // 01185319 . 0f8f 45020000 jg DotKares.01185564 //}; //GROWL_DWORD(processStartAddress); ULONG addr = processStartAddress; //- sizeof(pattern); do { //addr += sizeof(pattern); // ++ so that each time return diff address ULONG range = min(processStopAddress - addr, MAX_REL_ADDR); addr = MemDbg::findBytes(pattern, pattern_size, addr, addr + range); if (!addr) { //ITH_MSG(L"failed"); ConsoleOutput("Rejet: pattern not found"); return false; } addr += hook_off; //GROWL_DWORD(addr); //GROWL_DWORD(*(DWORD *)(addr-3)); //const BYTE hook_ins[] = { // /*0x8b,*/0x74,0x24, 0x20, // mov esi,dword ptr ss:[esp+0x20] // 0xe8 //??,??,??,??, 01357af9 e8 7283fbff call DotKares.0130fe70 ; jichi: hook here //}; } while(0xe8202474 != *(DWORD *)(addr - 3)); ConsoleOutput("INSERT Rejet"); HookParam hp; hp.address = addr; //- 0xf; hp.type = NO_CONTEXT|DATA_INDIRECT|FIXING_SPLIT; hp.offset = hook_offset; return NewHook(hp, hook_name); } bool InsertRejetHook1() // This type of hook has varied hook address { const BYTE bytes[] = { // Type1: Function start 0xff,0xf0, // 01185311 . fff0 push eax ; beginning of a new function 0x0f,0xc1,0x11, // 01185313 . 0fc111 xadd dword ptr ds:[ecx],edx 0x4a, // 01185316 . 4a dec edx 0x85,0xd2, // 01185317 . 85d2 test edx,edx 0x0f,0x8f // 01185319 . 0f8f 45020000 jg DotKares.01185564 }; // Offset to the function call from the beginning of the function enum { addr_offset = 0x21 }; // Type1: hex(0x01185332-0x01185311) enum { hook_offset = -0x8 }; // hook parameter return FindRejetHook(bytes, sizeof(bytes), addr_offset, hook_offset); } bool InsertRejetHook2() // This type of hook has static hook address { const BYTE bytes[] = { // Type2 Function start 0xff,0xf0, // 01357ad2 fff0 push eax 0x0f,0xc1,0x11, // 01357ad4 0fc111 xadd dword ptr ds:[ecx],edx 0x4a, // 01357ad7 4a dec edx 0x85,0xd2, // 01357ad8 85d2 test edx,edx 0x7f, 0x0a, // 01357ada 7f 0a jg short DotKares.01357ae6 0x8b,0x08, // 01357adc 8b08 mov ecx,dword ptr ds:[eax] 0x8b,0x11, // 01357ade 8b11 mov edx,dword ptr ds:[ecx] 0x50, // 01357ae0 50 push eax 0x8b,0x42, 0x04, // 01357ae1 8b42 04 mov eax,dword ptr ds:[edx+0x4] 0xff,0xd0, // 01357ae4 ffd0 call eax 0x8b,0x4c,0x24, 0x14 // 01357ae6 8b4c24 14 mov ecx,dword ptr ss:[esp+0x14] }; // Offset to the function call from the beginning of the function enum { addr_offset = 0x27 }; // Type2: hex(0x0133CEC7-0x0133CEA0) = hex(0x01357af9-0x1357ad2) enum { hook_offset = -0xc }; // hook parameter return FindRejetHook(bytes, sizeof(bytes), addr_offset, hook_offset); } bool InsertRejetHook3() // jichi 12/28/2013: add for 剣が君 { // The following pattern is the same as type2 const BYTE bytes[] = { // Type2 Function start 0xff,0xf0, // 01357ad2 fff0 push eax 0x0f,0xc1,0x11, // 01357ad4 0fc111 xadd dword ptr ds:[ecx],edx 0x4a, // 01357ad7 4a dec edx 0x85,0xd2, // 01357ad8 85d2 test edx,edx 0x7f, 0x0a, // 01357ada 7f 0a jg short DotKares.01357ae6 0x8b,0x08, // 01357adc 8b08 mov ecx,dword ptr ds:[eax] 0x8b,0x11, // 01357ade 8b11 mov edx,dword ptr ds:[ecx] 0x50, // 01357ae0 50 push eax 0x8b,0x42, 0x04, // 01357ae1 8b42 04 mov eax,dword ptr ds:[edx+0x4] 0xff,0xd0, // 01357ae4 ffd0 call eax 0x8b,0x4c,0x24, 0x14 // 01357ae6 8b4c24 14 mov ecx,dword ptr ss:[esp+0x14] }; // Offset to the function call from the beginning of the function //enum { addr_offset = 0x27 }; // Type2: hex(0x0133CEC7-0x0133CEA0) = hex(0x01357af9-0x1357ad2) enum { hook_offset = -0xc }; // hook parameter ULONG addr = processStartAddress; //- sizeof(bytes); while (true) { //addr += sizeof(bytes); // ++ so that each time return diff address ULONG range = min(processStopAddress - addr, MAX_REL_ADDR); addr = MemDbg::findBytes(bytes, sizeof(bytes), addr, addr + range); if (!addr) { //ITH_MSG(L"failed"); ConsoleOutput("Rejet: pattern not found"); return false; } addr += sizeof(bytes); // Push and call at once, i.e. push (0x68) and call (0xe8) // 01185345 52 push edx // 01185346 . 68 e4fe5501 push dotkares.0155fee4 ; |arg1 = 0155fee4 // 0118534b . e8 1023f9ff call dotkares.01117660 ; \dotkares.00377660 enum { start = 0x10, stop = 0x50 }; // Different from FindRejetHook DWORD i; for (i = start; i < stop; i++) if (*(WORD *)(addr + i - 1) == 0x6852 && *(BYTE *)(addr + i + 5) == 0xe8) // 0118534B-01185346 break; if (i < stop) { addr += i; break; } } //while(0xe8202474 != *(DWORD *)(addr - 3)); //GROWL_DWORD(addr - processStartAddress); // = 0xb3578 for 剣が君 ConsoleOutput("INSERT Rejet"); // The same as type2 HookParam hp; hp.address = addr; //- 0xf; hp.type = NO_CONTEXT|DATA_INDIRECT|FIXING_SPLIT; hp.offset = hook_offset; return NewHook(hp, "Rejet"); } } // unnamed Rejet bool InsertRejetHook() { return InsertRejetHook2() || InsertRejetHook1() || InsertRejetHook3(); } // insert hook2 first, since 2's pattern seems to be more unique bool Rejet::attach_function() { return InsertRejetHook(); }