mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-12-30 23:14:12 +08:00
248 lines
8.0 KiB
C++
248 lines
8.0 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);
|
|||
|
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();
|
|||
|
}
|