mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-30 17:15:38 +08:00
252 lines
8.2 KiB
C++
252 lines
8.2 KiB
C++
#include"Atelier.h"
|
||
/********************************************************************************************
|
||
AtelierKaguya hook:
|
||
Game folder contains message.dat. Used by AtelierKaguya games.
|
||
Usually has font caching issue with TextOutA.
|
||
Game engine uses EBP to set up stack frame so we can easily trace back.
|
||
Keep step out until it's in main game module. We notice that either register or
|
||
stack contains string pointer before call instruction. But it's not quite stable.
|
||
In-depth analysis of the called function indicates that there's a loop traverses
|
||
the string one character by one. We can set a hook there.
|
||
This search process is too complex so I just make use of some characteristic
|
||
instruction(add esi,0x40) to locate the right point.
|
||
********************************************************************************************/
|
||
bool InsertAtelierHook()
|
||
{
|
||
PcHooks::hookOtherPcFunctions(); // lstrlenA gives good hook too
|
||
//SafeFillRange(processName, &base, &size);
|
||
//size=size-base;
|
||
//DWORD sig = 0x40c683; // add esi,0x40
|
||
//i=processStartAddress+SearchPattern(processStartAddress,processStopAddress-processStartAddress,&sig,3);
|
||
DWORD i;
|
||
for (i = processStartAddress; i < processStopAddress - 4; i++) {
|
||
DWORD sig = *(DWORD *)i & 0xffffff;
|
||
if (0x40c683 == sig) // add esi,0x40
|
||
break;
|
||
}
|
||
if (i < processStopAddress - 4)
|
||
for (DWORD j=i-0x200; i>j; i--)
|
||
if (*(DWORD *)i == 0xff6acccc) { // find the function entry
|
||
HookParam hp;
|
||
hp.address = i+2;
|
||
hp.offset=get_stack(2);
|
||
hp.split = get_reg(regs::esp);
|
||
hp.type = USING_SPLIT;
|
||
ConsoleOutput("INSERT Aterlier KAGUYA");
|
||
|
||
//RegisterEngineType(ENGINE_ATELIER);
|
||
return NewHook(hp, "Atelier KAGUYA");
|
||
}
|
||
|
||
ConsoleOutput("Aterlier: failed");
|
||
return false;
|
||
//ConsoleOutput("Unknown Atelier KAGUYA engine.");
|
||
}
|
||
|
||
bool InsertAtelierKaguya2Hook()
|
||
{
|
||
|
||
/*
|
||
* Sample games:
|
||
* https://vndb.org/v22713
|
||
* https://vndb.org/v31685
|
||
* https://vndb.org/v37081
|
||
*/
|
||
const BYTE bytes[] = {
|
||
0x51, // push ecx << hook here
|
||
0x50, // push eax
|
||
0xE8, XX4, // call Start.exe+114307
|
||
0x83, 0xC4, 0x08, // add esp,08
|
||
0x85, 0xC0, // test eax,eax
|
||
0x78, 0xA1 // js Start.exe+48947
|
||
};
|
||
|
||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
||
if (!addr) {
|
||
ConsoleOutput("Atelier KAGUYA2: pattern not found");
|
||
return false;
|
||
}
|
||
|
||
HookParam hp;
|
||
hp.address = addr;
|
||
hp.offset=get_reg(regs::eax);
|
||
hp.type = USING_STRING|EMBED_AFTER_OVERWRITE|EMBED_BEFORE_SIMPLE|EMBED_ABLE|EMBED_DYNA_SJIS;
|
||
hp.hook_font=F_TextOutA;
|
||
hp.filter_fun = NewLineCharToSpaceFilterA;
|
||
ConsoleOutput("INSERT Atelier KAGUYA2");
|
||
|
||
return NewHook(hp, "Atelier KAGUYA2");
|
||
}
|
||
|
||
bool InsertAtelierKaguya3Hook()
|
||
{
|
||
|
||
/*
|
||
* Sample games:
|
||
* https://vndb.org/v10082
|
||
*/
|
||
const BYTE bytes[] = {
|
||
0x55, // push ebp << hook here
|
||
0x8B, 0xEC, // mov ebp,esp
|
||
0x6A, 0xFF, // push -01
|
||
0x68, 0x80, 0xB9, 0x4D, 0x00, // push Start.exe+DB980
|
||
0x64, 0xA1, XX4, // mov eax,fs:[00000000]
|
||
0x50, // push eax
|
||
0x51, // push ecx
|
||
0x81, 0xEC, 0xAC, 0x00, 0x00, 0x00 // sub esp,000000AC
|
||
};
|
||
|
||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
||
if (!addr) {
|
||
ConsoleOutput("Atelier KAGUYA3: pattern not found");
|
||
return false;
|
||
}
|
||
|
||
HookParam hp;
|
||
hp.address = addr;
|
||
hp.offset=get_reg(regs::eax);
|
||
hp.type = USING_STRING;
|
||
hp.filter_fun = NewLineCharToSpaceFilterA;
|
||
ConsoleOutput("INSERT Atelier KAGUYA3");
|
||
|
||
return NewHook(hp, "Atelier KAGUYA3");
|
||
}
|
||
|
||
bool InsertAtelierKaguya4Hook()
|
||
{
|
||
|
||
/*
|
||
* Sample games:
|
||
* https://vndb.org/v14705
|
||
*/
|
||
const BYTE bytes[] = {
|
||
0xE8, 0x90, 0xA8, 0xFF, 0xFF, // call Start.exe+18380
|
||
0x89, 0x45, 0xF8, // mov [ebp-08],eax
|
||
0x8B, 0x4D, 0x10, // mov ecx,[ebp+10]
|
||
0x51, // push ecx
|
||
0x8B, 0x55, 0x0C, // mov edx,[ebp+0C]
|
||
0x52, // push edx
|
||
0x8B, 0x45, 0x08, // mov eax,[ebp+08]
|
||
0x50 // push eax << hook here
|
||
};
|
||
enum { addr_offset = sizeof(bytes) - 1 };
|
||
|
||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
||
if (!addr) {
|
||
ConsoleOutput("Atelier KAGUYA4: pattern not found");
|
||
return false;
|
||
}
|
||
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.offset=get_reg(regs::eax);
|
||
hp.type = USING_STRING;
|
||
hp.filter_fun = NewLineCharToSpaceFilterA;
|
||
ConsoleOutput("INSERT Atelier KAGUYA4");
|
||
|
||
return NewHook(hp, "Atelier KAGUYA4");
|
||
}
|
||
|
||
bool InsertAtelierKaguya5Hook()
|
||
{
|
||
|
||
/*
|
||
* Sample games:
|
||
* https://vndb.org/v11224
|
||
*/
|
||
const BYTE bytes[] = {
|
||
0xC2, 0x04, 0x00, // ret 0004
|
||
0x55, // push ebp << hook here
|
||
0x8B, 0xEC, // mov ebp,esp
|
||
0x6A, 0xFF, // push -01
|
||
0x68, XX4, // push Start.exe+DA680
|
||
0x64, 0xA1, 0x00, 0x00, 0x00, 0x00, // mov eax,fs:[00000000]
|
||
0x50, // push eax
|
||
0x51, // push ecx
|
||
};
|
||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
||
if (!addr) {
|
||
ConsoleOutput("Atelier KAGUYA5: pattern not found");
|
||
return false;
|
||
}
|
||
|
||
HookParam hp;
|
||
hp.address = addr + 3;
|
||
hp.offset=get_reg(regs::eax);
|
||
hp.type = USING_STRING;
|
||
hp.filter_fun = NewLineCharToSpaceFilterA;
|
||
ConsoleOutput("INSERT Atelier KAGUYA5");
|
||
|
||
return NewHook(hp, "Atelier KAGUYA5");
|
||
}
|
||
bool InsertAtelierKaguyaX()
|
||
{
|
||
//エロティ課 誘惑研修はじまるよ~ しごいちゃうから覚悟なさい!
|
||
const BYTE bytes[] = {
|
||
0x3D,0xF0,0x41,0x00,0x00,
|
||
0x75
|
||
};
|
||
|
||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
||
if (!addr) return false;
|
||
|
||
addr = findfuncstart(addr,0x1000);
|
||
if (!addr) return false;
|
||
HookParam hp;
|
||
hp.address = addr;
|
||
hp.offset=get_stack(1);
|
||
hp.type = USING_STRING;
|
||
|
||
return NewHook(hp, "Atelier KAGUYA3");
|
||
}
|
||
bool Atelier::attach_function() {
|
||
|
||
return InsertAtelierHook() || InsertAtelierKaguya2Hook() ||InsertAtelierKaguyaX()|| InsertAtelierKaguya3Hook() || InsertAtelierKaguya4Hook() || InsertAtelierKaguya5Hook();
|
||
}
|
||
|
||
|
||
bool Atelier2attach_function(){
|
||
//https://vndb.org/v304
|
||
//ダンジョンクルセイダーズ~TALES OF DEMON EATER~
|
||
const BYTE bytes[] = {
|
||
0x83 ,0xFE ,0x34 ,
|
||
0xF6 ,XX ,
|
||
0x88 ,XX,0x24 ,0x29 ,
|
||
0x7D
|
||
};
|
||
|
||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
||
if (!addr) return false;
|
||
|
||
HookParam hp;
|
||
hp.address = addr+sizeof(bytes)-1;
|
||
hp.offset = get_stack(10);
|
||
hp.type=USING_CHAR|NO_CONTEXT;
|
||
//NO_CONTEXT:
|
||
//牝奴隷 ~犯された放課後~
|
||
//https://vndb.org/v4351会把每行单独分开。
|
||
return NewHook(hp, "Atelier KAGUYA3");
|
||
}
|
||
|
||
|
||
bool Atelier2attach_function2(){
|
||
//https://vndb.org/v7264
|
||
//禁断の病棟 特殊精神科医 遊佐惣介の診察記録
|
||
auto addr=MemDbg::findCallerAddressAfterInt3((ULONG)TextOutA,processStartAddress,processStopAddress);
|
||
if(addr==0)return 0;
|
||
HookParam hp;
|
||
hp.address = addr;
|
||
hp.offset=get_stack(3);
|
||
hp.type=USING_STRING|DATA_INDIRECT;
|
||
|
||
return NewHook(hp, "Atelier KAGUYA");
|
||
}
|
||
bool Atelier2::attach_function(){
|
||
return Atelier2attach_function()||Atelier2attach_function2();
|
||
} |