2024-02-07 20:59:24 +08:00

270 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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();
}