LunaHook-mirror/LunaHook/engine32/Rejet.cpp

270 lines
13 KiB
C++
Raw Permalink Normal View History

2024-02-07 20:59:24 +08:00
#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 "<br>"
*
* - 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();
}