LunaHook-mirror/LunaHook/engine32/AOS.cpp
2024-02-07 20:59:24 +08:00

279 lines
10 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"AOS.h"
/**
* jichi 4/1/2014: Insert AOS hook
* About 彩斤<E5BDA9>: http://erogetrailers.com/brand/165
* About AOS: http://asmodean.reverse.net/pages/exaos.html
*
* Sample games:
*
* [140228] [Sugar Pot] 恋する少女と想<E381A8>キセキ V1.00 H-CODE by <20>쿿
* - /HB8*0@3C2F0:恋する少女と想<E381A8>キセキ.exe
* - /HBC*0@3C190:恋する少女と想<E381A8>キセキ.exe
*
* [120224] [Sugar Pot] ヂ<>ツキ
*
* LiLiM games
*
* /HB8*0@3C2F0:恋する少女と想<E381A8>キセ
* - addr: 246512 = 0x3c2f0
* - length_offset: 1
* - module: 1814017450
* - off: 8
* - type: 72 = 0x48
*
* 00e3c2ed cc int3
* 00e3c2ee cc int3
* 00e3c2ef cc int3
* 00e3c2f0 /$ 51 push ecx ; jichi: hook here, function starts
* 00e3c2f1 |. a1 0c64eb00 mov eax,dword ptr ds:[0xeb640c]
* 00e3c2f6 |. 8b0d 7846eb00 mov ecx,dword ptr ds:[0xeb4678]
* 00e3c2fc |. 53 push ebx
* 00e3c2fd |. 55 push ebp
* 00e3c2fe |. 8b6c24 10 mov ebp,dword ptr ss:[esp+0x10]
* 00e3c302 |. 56 push esi
* 00e3c303 |. 8b35 c446eb00 mov esi,dword ptr ds:[0xeb46c4]
* 00e3c309 |. 57 push edi
* 00e3c30a |. 0fb63d c746eb00 movzx edi,byte ptr ds:[0xeb46c7]
* 00e3c311 |. 81e6 ffffff00 and esi,0xffffff
* 00e3c317 |. 894424 18 mov dword ptr ss:[esp+0x18],eax
* 00e3c31b |. 85ff test edi,edi
* 00e3c31d |. 74 6b je short 恋する<E38199>00e3c38a
* 00e3c31f |. 8bd9 mov ebx,ecx
* 00e3c321 |. 85db test ebx,ebx
* 00e3c323 |. 74 17 je short 恋する<E38199>00e3c33c
* 00e3c325 |. 8b4b 28 mov ecx,dword ptr ds:[ebx+0x28]
* 00e3c328 |. 56 push esi ; /color
* 00e3c329 |. 51 push ecx ; |hdc
* 00e3c32a |. ff15 3c40e800 call dword ptr ds:[<&gdi32.SetTextColor>>; \settextcolor
* 00e3c330 |. 89b3 c8000000 mov dword ptr ds:[ebx+0xc8],esi
* 00e3c336 |. 8b0d 7846eb00 mov ecx,dword ptr ds:[0xeb4678]
* 00e3c33c |> 0fbf55 1c movsx edx,word ptr ss:[ebp+0x1c]
* 00e3c340 |. 0fbf45 0a movsx eax,word ptr ss:[ebp+0xa]
* 00e3c344 |. 0fbf75 1a movsx esi,word ptr ss:[ebp+0x1a]
* 00e3c348 |. 03d7 add edx,edi
* 00e3c34a |. 03c2 add eax,edx
* 00e3c34c |. 0fbf55 08 movsx edx,word ptr ss:[ebp+0x8]
* 00e3c350 |. 03f7 add esi,edi
* 00e3c352 |. 03d6 add edx,esi
* 00e3c354 |. 85c9 test ecx,ecx
* 00e3c356 |. 74 32 je short 恋する<E38199>00e3c38a
*/
bool InsertAOS1Hook()
{
// jichi 4/2/2014: The starting of this function is different from ヂ<>ツキ
// So, use a pattern in the middle of the function instead.
//
//const BYTE bytes[] = {
// 0x51, // 00e3c2f0 /$ 51 push ecx ; jichi: hook here, function begins
// 0xa1, 0x0c,0x64,0xeb,0x00, // 00e3c2f1 |. a1 0c64eb00 mov eax,dword ptr ds:[0xeb640c]
// 0x8b,0x0d, 0x78,0x46,0xeb,0x00, // 00e3c2f6 |. 8b0d 7846eb00 mov ecx,dword ptr ds:[0xeb4678]
// 0x53, // 00e3c2fc |. 53 push ebx
// 0x55, // 00e3c2fd |. 55 push ebp
// 0x8b,0x6c,0x24, 0x10, // 00e3c2fe |. 8b6c24 10 mov ebp,dword ptr ss:[esp+0x10]
// 0x56, // 00e3c302 |. 56 push esi
// 0x8b,0x35, 0xc4,0x46,0xeb,0x00, // 00e3c303 |. 8b35 c446eb00 mov esi,dword ptr ds:[0xeb46c4]
// 0x57, // 00e3c309 |. 57 push edi
// 0x0f,0xb6,0x3d, 0xc7,0x46,0xeb,0x00, // 00e3c30a |. 0fb63d c746eb00 movzx edi,byte ptr ds:[0xeb46c7]
// 0x81,0xe6, 0xff,0xff,0xff,0x00 // 00e3c311 |. 81e6 ffffff00 and esi,0xffffff
//};
//enum { addr_offset = 0 };
const BYTE bytes[] = {
0x0f,0xbf,0x55, 0x1c, // 00e3c33c |> 0fbf55 1c movsx edx,word ptr ss:[ebp+0x1c]
0x0f,0xbf,0x45, 0x0a, // 00e3c340 |. 0fbf45 0a movsx eax,word ptr ss:[ebp+0xa]
0x0f,0xbf,0x75, 0x1a, // 00e3c344 |. 0fbf75 1a movsx esi,word ptr ss:[ebp+0x1a]
0x03,0xd7, // 00e3c348 |. 03d7 add edx,edi
0x03,0xc2, // 00e3c34a |. 03c2 add eax,edx
0x0f,0xbf,0x55, 0x08, // 00e3c34c |. 0fbf55 08 movsx edx,word ptr ss:[ebp+0x8]
0x03,0xf7, // 00e3c350 |. 03f7 add esi,edi
0x03,0xd6, // 00e3c352 |. 03d6 add edx,esi
0x85,0xc9 // 00e3c354 |. 85c9 test ecx,ecx
};
enum { addr_offset = 0x00e3c2f0 - 0x00e3c33c }; // distance to the beginning of the function, which is 0x51 (push ecx)
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
//GROWL(reladdr);
if (!addr) {
ConsoleOutput("AOS1: pattern not found");
return false;
}
addr += addr_offset;
//GROWL(addr);
enum { push_ecx = 0x51 }; // beginning of the function
if (*(BYTE *)addr != push_ecx) {
ConsoleOutput("AOS1: beginning of the function not found");
return false;
}
HookParam hp;
hp.address = addr;
hp.offset=get_stack(2);
hp.type = DATA_INDIRECT;
ConsoleOutput("INSERT AOS1");
return NewHook(hp, "AOS1");
}
bool InsertAOS2Hook()
{
const BYTE bytes[] = {
0x51, // 00C4E7E0 /$ 51 PUSH ECX ; mireado: hook here, function begins
0x33,0xc0, // 00C4E7E1 |. 33C0 XOR EAX,EAX
0x53, // 00C4E7E3 |. 53 PUSH EBX
0x55, // 00C4E7E4 |. 55 PUSH EBP
0x8b,0x2d//, XX4, // 00C4E7E5 |. 8B2D 40A3CF00 MOV EBP,DWORD PTR DS:[0CFA340] ; mireado: some time changing 40A3CF00 => 40A3C000
//0x89,0x07, // 00C4E7EB |. 8907 MOV DWORD PTR DS:[EDI],EAX
//0x89,0x47, 0x04 // 00C4E7ED |. 8947 04 MOV DWORD PTR DS:[EDI+4],EAX
//0x56, // 00C4E7F0 |. 56 PUSH ESI
//0x8b,0x75, 0x44 // 00C4E7F1 |. 8B75 44 MOV ESI,DWORD PTR SS:[EBP+44]
};
enum { addr_offset = 0 }; // distance to the beginning of the function, which is 0x51 (push ecx)
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
//GROWL(reladdr);
if (!addr) {
ConsoleOutput("AOS2: pattern not found");
return false;
}
addr += addr_offset;
//GROWL(addr);
enum { push_ecx = 0x51 }; // beginning of the function
if (*(BYTE *)addr != push_ecx) {
ConsoleOutput("AOS2: beginning of the function not found");
return false;
}
HookParam hp;
hp.address = addr;
hp.offset=get_stack(2);
hp.type = DATA_INDIRECT;
ConsoleOutput("INSERT AOS2");
return NewHook(hp, "AOS2");
}
bool InsertAOSHook()
{ return InsertAOS1Hook() || InsertAOS2Hook();}
namespace{
DWORD calladdr(DWORD addr){
if(addr==0)return 0;
BYTE callop[] = { 0xe8 };
addr = reverseFindBytes(callop, sizeof(callop), addr - 0x20, addr);
if (addr == 0)return 0;
auto calladdr = *(int*)((char*)addr + 1);
ConsoleOutput("calladdr %p", calladdr);
addr = calladdr + addr + 5;
ConsoleOutput("funcaddr %p", addr);
if (*(BYTE*)((BYTE*)addr - 1) != 0xcc)return 0;
return addr;
}
DWORD lastcall(){
auto entry=Util::FindImportEntry(processStartAddress,(DWORD)TextOutA);
if(entry==0)return 0;
BYTE bytes[]={0xFF,0x15,XX4};
memcpy(bytes+2,&entry,4);
auto addr = reverseFindBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
if(addr==0)return 0;
addr = MemDbg::findEnclosingAlignedFunction(addr);
return addr;
}
}
regs mov_reg_ebpoffset(int reg) {
switch (reg) {
case 0x4B:
return regs::ebx;
case 0x48:
return regs::eax;
case 0x49:
return regs::ecx;
case 0x4a:
return regs::edx;
case 0x4c:
return regs::ebp;
case 0x4d:
return regs::esp;
case 0x4e:
return regs::esi;
case 0x4f:
return regs::edi;
default:
return regs::invalid;
}
}
bool AOS_EX() {
BYTE aos_shared_bytes1[] = {
0x3c,XX,
0x74,XX,
0x3c,XX,
0x74,XX,
0x3c,XX,
0x74,XX,
0x3c,XX,
0x74,XX,
0x3c,XX,
0x74,XX,
};
BYTE aos_shared_bytes2[] = {
0x80,0xfb,XX,
0x74,XX,
0x80,0xfb,XX,
0x74,XX,
0x80,0xfb,XX,
0x74,XX,
0x80,0xfb,XX,
0x74,XX
};
std::vector<DWORD>addrs;
addrs.push_back(calladdr(MemDbg::findBytes(aos_shared_bytes1, sizeof(aos_shared_bytes1), processStartAddress, processStopAddress)));
addrs.push_back(calladdr(MemDbg::findBytes(aos_shared_bytes2, sizeof(aos_shared_bytes2), processStartAddress, processStopAddress)));
addrs.push_back(lastcall());
for(auto addr: addrs){
if (addr == 0)continue;
auto reg = mov_reg_ebpoffset(*(BYTE*)((BYTE*)addr + 5));
int off;
if (reg!=regs::invalid){
//usercall
off=get_reg(reg);
}
else if(((*(WORD*)addr))==0xec83) {
//姫様LOVEライフ
//也是usercall但是第二个参数是栈上。
off=get_stack(1);
}
else{
//螺旋遡行のディストピア -The infinite set of alternative version- 官方中文
BYTE sig[]={0x89,0x55,0xFC};
if(MemDbg::findBytes(sig, sizeof(sig), addr, addr+0x20)){
off=get_reg(regs::edx);
}
else{
//cdecl;
off=get_stack(2);
}
}
HookParam hp;
hp.address = addr;
hp.offset = off;
hp.type = NO_CONTEXT | DATA_INDIRECT;
hp.index = 0;
return NewHook(hp, "AOS_EX");
}
return false;
}
bool AOS::attach_function() {
bool b1=InsertAOSHook();
bool b3=AOS_EX();
return b1||b3;
}