mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-12-26 13:14:13 +08:00
211 lines
7.1 KiB
C++
211 lines
7.1 KiB
C++
#include "Reallive.h"
|
|
|
|
/********************************************************************************************
|
|
Reallive hook:
|
|
Process name is reallive.exe or reallive*.exe.
|
|
|
|
Technique to find Reallive hook is quite different from 2 above.
|
|
Usually Reallive engine has a font caching issue. This time we wait
|
|
until the first call to GetGlyphOutlineA. Reallive engine usually set
|
|
up stack frames so we can just refer to EBP to find function entry.
|
|
|
|
********************************************************************************************/
|
|
/** jichi 5/13/2015
|
|
* RealLive does not work for 水着少女と媚薬アイス from 裸足少女
|
|
* 012da80f cc int3
|
|
* 012da810 55 push ebp ; jichi: change to hook here
|
|
* 012da811 8bec mov ebp,esp
|
|
* 012da813 83ec 10 sub esp,0x10 ; jichi: hook here by default
|
|
* 012da816 53 push ebx
|
|
* 012da817 56 push esi
|
|
* 012da818 57 push edi
|
|
* 012da819 8b7d 18 mov edi,dword ptr ss:[ebp+0x18]
|
|
* 012da81c 81ff 5c810000 cmp edi,0x815c
|
|
* 012da822 75 0a jnz short reallive.012da82e
|
|
* 012da824 c745 18 9f840000 mov dword ptr ss:[ebp+0x18],0x849f
|
|
* 012da82b 8b7d 18 mov edi,dword ptr ss:[ebp+0x18]
|
|
* 012da82e b8 9041e301 mov eax,reallive.01e34190
|
|
* 012da833 b9 18a49001 mov ecx,reallive.0190a418
|
|
* 012da838 e8 a38d0000 call reallive.012e35e0
|
|
* 012da83d 85c0 test eax,eax
|
|
* 012da83f 74 14 je short reallive.012da855
|
|
* 012da841 e8 6addffff call reallive.012d85b0
|
|
* 012da846 ba 9041e301 mov edx,reallive.01e34190
|
|
* 012da84b b8 18a49001 mov eax,reallive.0190a418
|
|
* 012da850 e8 ab7c0000 call reallive.012e2500
|
|
* 012da855 8d45 f0 lea eax,dword ptr ss:[ebp-0x10]
|
|
* 012da858 50 push eax
|
|
* 012da859 8d4d f4 lea ecx,dword ptr ss:[ebp-0xc]
|
|
* 012da85c 51 push ecx
|
|
* 012da85d 8d55 fc lea edx,dword ptr ss:[ebp-0x4]
|
|
* 012da860 52 push edx
|
|
* 012da861 8d45 f8 lea eax,dword ptr ss:[ebp-0x8]
|
|
* 012da864 50 push eax
|
|
* 012da865 8bc7 mov eax,edi
|
|
* 012da867 e8 54dfffff call reallive.012d87c0
|
|
* 012da86c 8bf0 mov esi,eax
|
|
* 012da86e 83c4 10 add esp,0x10
|
|
* 012da871 85f6 test esi,esi
|
|
* 012da873 75 4b jnz short reallive.012da8c0
|
|
* 012da875 8d4d f4 lea ecx,dword ptr ss:[ebp-0xc]
|
|
* 012da878 51 push ecx
|
|
* 012da879 57 push edi
|
|
* 012da87a 8d4d f0 lea ecx,dword ptr ss:[ebp-0x10]
|
|
* 012da87d e8 cef0ffff call reallive.012d9950
|
|
* 012da882 8bf0 mov esi,eax
|
|
* 012da884 83c4 08 add esp,0x8
|
|
* 012da887 85f6 test esi,esi
|
|
*/
|
|
static bool InsertRealliveDynamicHook(LPVOID addr, hook_stack *stack)
|
|
{
|
|
if (addr != ::GetGlyphOutlineA)
|
|
return false;
|
|
// jichi 5/13/2015: Find the enclosing caller of GetGlyphOutlineA
|
|
if (DWORD i = stack->ebp)
|
|
{
|
|
i = *(DWORD *)(i + 4);
|
|
for (DWORD j = i; j > i - 0x100; j--)
|
|
if (*(WORD *)j == 0xec83)
|
|
{ // jichi 7/26/2014: function starts
|
|
// 012da80f cc int3
|
|
// 012da810 55 push ebp ; jichi: change to hook here
|
|
// 012da811 8bec mov ebp,esp
|
|
// 012da813 83ec 10 sub esp,0x10 ; jichi: hook here by default
|
|
if (*(DWORD *)(j - 3) == 0x83ec8b55)
|
|
j -= 3;
|
|
|
|
HookParam hp;
|
|
hp.address = j;
|
|
hp.offset = get_stack(5);
|
|
hp.split = get_reg(regs::esp);
|
|
hp.type = CODEC_ANSI_BE | USING_SPLIT;
|
|
// GROWL_DWORD(hp.address);
|
|
|
|
// RegisterEngineType(ENGINE_REALLIVE);
|
|
ConsoleOutput("RealLive: disable GDI hooks");
|
|
|
|
return NewHook(hp, "RealLive");
|
|
}
|
|
}
|
|
return true; // jichi 12/25/2013: return true
|
|
}
|
|
void InsertRealliveHook()
|
|
{
|
|
// ConsoleOutput("Probably Reallive. Wait for text.");
|
|
ConsoleOutput("TRIGGER Reallive");
|
|
trigger_fun = InsertRealliveDynamicHook;
|
|
}
|
|
|
|
bool RlBabelFilter(LPVOID data, size_t *size, HookParam *)
|
|
{
|
|
auto text = reinterpret_cast<LPSTR>(data);
|
|
auto len = reinterpret_cast<size_t *>(size);
|
|
|
|
if (text[0] == '\x01')
|
|
{
|
|
StringFilterBetween(text, len, "\x01", 1, "\x02", 1); // remove names
|
|
}
|
|
|
|
CharReplacer(text, len, '\x08', '"');
|
|
CharReplacer(text, len, '\x09', '\'');
|
|
CharReplacer(text, len, '\x0A', '\'');
|
|
CharFilter(text, len, '\x1F'); // remove color
|
|
StringReplacer(text, len, "\x89\x85", 2, "\x81\x63", 2); // "\x89\x85"-> shift-JIS"…"
|
|
StringReplacer(text, len, "\x89\x97", 2, "--", 2);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool InsertRlBabelHook()
|
|
{
|
|
|
|
/*
|
|
* Sample games:
|
|
* https://vndb.org/r78318
|
|
*/
|
|
const BYTE bytes[] = {
|
|
0xCC, // int 3
|
|
0x55, // push ebp <- hook here
|
|
0x8B, 0xEC, // mov ebp,esp
|
|
0x83, 0xEC, 0x20, // sub esp,20
|
|
0xC7, 0x45, 0xFC, XX4 // mov [ebp-04],rlBabel.DLL+16804
|
|
};
|
|
|
|
HMODULE module = GetModuleHandleW(L"rlBabel.dll");
|
|
if (!module)
|
|
return false;
|
|
auto [minAddress, maxAddress] = Util::QueryModuleLimits(module);
|
|
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), minAddress, maxAddress);
|
|
if (!addr)
|
|
return false;
|
|
|
|
HookParam hp;
|
|
hp.address = addr + 1;
|
|
hp.offset = get_reg(regs::eax);
|
|
hp.type = USING_STRING;
|
|
hp.filter_fun = RlBabelFilter;
|
|
ConsoleOutput("INSERT RealLive Babel");
|
|
return NewHook(hp, "RealLive Babel");
|
|
}
|
|
namespace
|
|
{
|
|
bool clannad_en_steam()
|
|
{
|
|
// if ( v12 == 33116 || v12 == 33951 || v12 == 33962 )
|
|
BYTE sig[] = {
|
|
0x81, 0xFE, 0x5C, 0x81, 0x00, 0x00,
|
|
0x74, 0x10,
|
|
0x81, 0xFE, 0x9F, 0x84, 0x00, 0x00,
|
|
0x74, 0x08,
|
|
0x81, 0xFE, 0xAA, 0x84, 0x00, 0x00,
|
|
0x75, XX};
|
|
ULONG addr = MemDbg::findBytes(sig, sizeof(sig), processStartAddress, processStopAddress);
|
|
if (!addr)
|
|
return false;
|
|
|
|
HookParam hp;
|
|
hp.address = addr;
|
|
hp.offset = get_reg(regs::esi);
|
|
hp.type = USING_CHAR | CODEC_ANSI_LE;
|
|
return NewHook(hp, "RealLiveX");
|
|
}
|
|
}
|
|
bool Reallive::attach_function()
|
|
{
|
|
InsertRealliveHook();
|
|
InsertRlBabelHook() || clannad_en_steam();
|
|
return true;
|
|
}
|
|
|
|
bool avg3216d::attach_function()
|
|
{
|
|
BYTE pattern1[] = {
|
|
//clang-format off
|
|
0x3c, 0x81, XX2,
|
|
0x3c, 0x9f, XX2,
|
|
0x3c, 0xe0, XX2,
|
|
0x3c, 0xfc, XX2,
|
|
//clang-format on
|
|
};
|
|
BYTE pattern2[] = {
|
|
0x8b, 0x75, 0x08,
|
|
0x8a, 0x06,
|
|
0x3c, 0x81,
|
|
0x75, XX,
|
|
0x80, 0x7e, 0x01, 0x7a};
|
|
auto addr = MemDbg::findBytes(pattern2, sizeof(pattern2), processStartAddress, processStopAddress);
|
|
if (addr == 0)
|
|
return false;
|
|
addr = MemDbg::findEnclosingAlignedFunction(addr);
|
|
if (addr == 0)
|
|
return false;
|
|
auto check = MemDbg::findBytes(pattern1, sizeof(pattern1), addr, addr + 0x200);
|
|
if (check == 0)
|
|
return false;
|
|
HookParam hp;
|
|
hp.address = addr;
|
|
hp.offset = get_stack(1);
|
|
hp.type = NO_CONTEXT | DATA_INDIRECT;
|
|
// GROWL_DWORD(hp.address);
|
|
return NewHook(hp, "avg3216d");
|
|
} |