LunaHook-mirror/LunaHook/engine32/Ryokucha.cpp

370 lines
14 KiB
C++
Raw Normal View History

2024-02-07 20:59:24 +08:00
#include"Ryokucha.h"
#include"ntxpundef.h"
static void SpecialHookRyokucha(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
{
for (DWORD i = 1; i < 5; i++) {
DWORD j = stack->stack[i];
if ((j >> 16) == 0 && (j >> 8)) {
hp->offset = i << 2;
*data = j;
*len = 2;
//hp->type &= ~EXTERN_HOOK;
hp->text_fun = nullptr;
return;
}
}
*len = 0;
}
bool InsertRyokuchaDynamicHook(LPVOID addr, uintptr_t frame, uintptr_t stack)
{
if (addr != ::GetGlyphOutlineA)
return false;
auto tib = (NT_TIB*)__readfsdword(0);
auto exception = tib->ExceptionList;
for (int i = 0; i < 1; i++) {
exception = exception->Next;
}
auto handler=(DWORD)exception->Handler;
auto ptr=*(DWORD*)((DWORD)exception+0xC);
auto insert_addr=ptr+*(DWORD*)(ptr-4);
auto flag=(*(DWORD*)(insert_addr+3)==handler);
if (flag) {
HookParam hp;
hp.address = insert_addr;
hp.text_fun = SpecialHookRyokucha;
hp.type = CODEC_ANSI_BE|USING_CHAR;
ConsoleOutput("INSERT StudioRyokucha");
return NewHook(hp, "StudioRyokucha");
}
//else ConsoleOutput("Unknown Ryokucha engine.");
ConsoleOutput("StudioRyokucha: failed");
return true;
}
void InsertRyokuchaHook()
{
//ConsoleOutput("Probably Ryokucha. Wait for text.");
trigger_fun = InsertRyokuchaDynamicHook;
ConsoleOutput("TRIGGER Ryokucha");
}
/**
* jichi 1/10/2014: Rai7 puk
* See: http://www.hongfire.com/forum/showthread.php/421909-%E3%80%90Space-Warfare-Sim%E3%80%91Rai-7-PUK/page10
* See: www.hongfire.com/forum/showthread.php/421909-%E3%80%90Space-Warfare-Sim%E3%80%91Rai-7-PUK/page19
*
* Version: R7P3-13v2(131220).rar, pass: sstm http://pan.baidu.com/share/home?uk=3727185265#category/type=0
* /HS0@409524
*/
//bool InsertRai7Hook()
//{
//}
/**
* jichi 10/1/2013: sol-fa-soft
* See (tryguy): http://www.hongfire.com/forum/printthread.php?t=36807&pp=10&page=639
*
* @tryguy
* [sol-fa-soft]
* 17 <EFBFBD> /HA4@4AD140
* 18 <EFBFBD><EFBFBD>: /HA4@5104A0
* 19 <EFBFBD><EFBFBD><EFBFBD> /HA4@51D720
* 20 <EFBFBD><EFBFBD> /HA4@4968E0
* 21 <EFBFBD><EFBFBD> /HA4@49DC00
* 22 <EFBFBD>: /HA4@49DDB0
* 23 SOS: /HA4@4B4AA0
* 24 <EFBFBD>: /HA4@4B5600
* 25 <EFBFBD> /HA4@57E360
* 26 <EFBFBD><EFBFBD> /HA4@57E360
* 27 <EFBFBD>: /HA4@5593B0
* 28 : /HA4@5593B0
* 29 : /HA4@6DE8E0
* 30 <EFBFBD><EFBFBD> /HA4@6DEC90
* 31 <EFBFBD> <EFBFBD><EFBFBD><EFBFBD> /HA4@6DEC90
* 32 <EFBFBD><EFBFBD><EFBFBD>: /HA4@62AE10
* 33 <EFBFBD> /HA4@6087A0
* 34 <EFBFBD>: /HA4@6087A0
* 35 <EFBFBD>Princess Intermezzo: /HA4@609BF0
*
* SG01 <EFBFBD>: /HA4@6087A0
*
* c71 <EFBFBD>CD: /HA4@516b50
* c78 sol-fa-soft真夏<EFBFBD>CD: /HA4@6DEC90
*
* Example: 35 <EFBFBD>Princess Intermezzo: /HA4@609BF0
* - addr: 6331376 = 0x609bf0
* - length_offset: 1
* - off: 4
* - type: 4
*
* ASCII: <EFBFBD> addr_offset = -50
* Function starts
* 00609bef /> cc int3
* 00609bf0 /> 55 push ebp
* 00609bf1 |. 8bec mov ebp,esp
* 00609bf3 |. 64:a1 00000000 mov eax,dword ptr fs:[0]
* 00609bf9 |. 6a ff push -0x1
* 00609bfb |. 68 e1266300 push <EFBFBD>006326e1
* 00609c00 |. 50 push eax
* 00609c01 |. 64:8925 000000>mov dword ptr fs:[0],esp
* 00609c08 |. 81ec 80000000 sub esp,0x80
* 00609c0e |. 53 push ebx
* 00609c0f |. 8b5d 08 mov ebx,dword ptr ss:[ebp+0x8]
* 00609c12 |. 57 push edi
* 00609c13 |. 8bf9 mov edi,ecx
* 00609c15 |. 8b07 mov eax,dword ptr ds:[edi]
* 00609c17 |. 83f8 02 cmp eax,0x2
* 00609c1a |. 75 1f jnz short <EFBFBD>00609c3b
* 00609c1c |. 3b5f 40 cmp ebx,dword ptr ds:[edi+0x40]
* 00609c1f |. 75 1a jnz short <EFBFBD>00609c3b
* 00609c21 |. 837f 44 00 cmp dword ptr ds:[edi+0x44],0x0
* 00609c25 |. 74 14 je short <EFBFBD>00609c3b
* 00609c27 |. 5f pop edi
* 00609c28 |. b0 01 mov al,0x1
* 00609c2a |. 5b pop ebx
* 00609c2b |. 8b4d f4 mov ecx,dword ptr ss:[ebp-0xc]
* 00609c2e |. 64:890d 000000>mov dword ptr fs:[0],ecx
* 00609c35 |. 8be5 mov esp,ebp
* 00609c37 |. 5d pop ebp
* 00609c38 |. c2 0400 retn 0x4
* Function stops
*
* WideChar: <EFBFBD>x中出しセクシャルライ<EFBFBD>, addr_offset = -53
* 0040653a cc int3
* 0040653b cc int3
* 0040653c cc int3
* 0040653d cc int3
* 0040653e cc int3
* 0040653f cc int3
* 00406540 > 55 push ebp
* 00406541 . 8bec mov ebp,esp
* 00406543 . 64:a1 00000000 mov eax,dword ptr fs:[0]
* 00406549 . 6a ff push -0x1
* 0040654b . 68 f1584300 push erondo01.004358f1
* 00406550 . 50 push eax
* 00406551 . 64:8925 000000>mov dword ptr fs:[0],esp
* 00406558 . 83ec 6c sub esp,0x6c
* 0040655b . 53 push ebx
* 0040655c . 8bd9 mov ebx,ecx
* 0040655e . 57 push edi
* 0040655f . 8b03 mov eax,dword ptr ds:[ebx]
* 00406561 . 8b7d 08 mov edi,dword ptr ss:[ebp+0x8]
* 00406564 . 83f8 02 cmp eax,0x2
* 00406567 . 75 1f jnz short erondo01.00406588
* 00406569 . 3b7b 3c cmp edi,dword ptr ds:[ebx+0x3c]
* 0040656c . 75 1a jnz short erondo01.00406588
* 0040656e . 837b 40 00 cmp dword ptr ds:[ebx+0x40],0x0
* 00406572 . 74 14 je short erondo01.00406588
* 00406574 . 5f pop edi
* 00406575 . b0 01 mov al,0x1
* 00406577 . 5b pop ebx
* 00406578 . 8b4d f4 mov ecx,dword ptr ss:[ebp-0xc]
* 0040657b . 64:890d 000000>mov dword ptr fs:[0],ecx
* 00406582 . 8be5 mov esp,ebp
* 00406584 . 5d pop ebp
* 00406585 . c2 0400 retn 0x4
*
* WideChar: <EFBFBD><EFBFBD>, addr_offset = -50,
* FIXME: how to know if it is UTF16? This game has /H code, though:
*
* /HA-4@94D62:shukufuku_main.exe
*
* 011d619e cc int3
* 011d619f cc int3
* 011d61a0 55 push ebp
* 011d61a1 8bec mov ebp,esp
* 011d61a3 64:a1 00000000 mov eax,dword ptr fs:[0]
* 011d61a9 6a ff push -0x1
* 011d61ab 68 d1811f01 push .011f81d1
* 011d61b0 50 push eax
* 011d61b1 64:8925 00000000 mov dword ptr fs:[0],esp
* 011d61b8 81ec 80000000 sub esp,0x80
* 011d61be 53 push ebx
* 011d61bf 8b5d 08 mov ebx,dword ptr ss:[ebp+0x8]
* 011d61c2 57 push edi
* 011d61c3 8bf9 mov edi,ecx
* 011d61c5 8b07 mov eax,dword ptr ds:[edi]
* 011d61c7 83f8 02 cmp eax,0x2
* 011d61ca 75 1f jnz short .011d61eb
* 011d61cc 3b5f 40 cmp ebx,dword ptr ds:[edi+0x40]
* 011d61cf 75 1a jnz short .011d61eb
* 011d61d1 837f 44 00 cmp dword ptr ds:[edi+0x44],0x0
* 011d61d5 74 14 je short .011d61eb
* 011d61d7 5f pop edi
* 011d61d8 b0 01 mov al,0x1
* 011d61da 5b pop ebx
* 011d61db 8b4d f4 mov ecx,dword ptr ss:[ebp-0xc]
* 011d61de 64:890d 00000000 mov dword ptr fs:[0],ecx
* 011d61e5 8be5 mov esp,ebp
* 011d61e7 5d pop ebp
* 011d61e8 c2 0400 retn 0x4
*/
bool InsertScenarioPlayerHook()
{
PcHooks::hookOtherPcFunctions();
//const BYTE bytes[] = {
// 0x53, // 00609c0e |. 53 push ebx
// 0x8b,0x5d,0x08, // 00609c0f |. 8b5d 08 mov ebx,dword ptr ss:[ebp+0x8]
// 0x57, // 00609c12 |. 57 push edi
// 0x8b,0xf9, // 00609c13 |. 8bf9 mov edi,ecx
// 0x8b,0x07, // 00609c15 |. 8b07 mov eax,dword ptr ds:[edi]
// 0x83,0xf8, 0x02, // 00609c17 |. 83f8 02 cmp eax,0x2
// 0x75, 0x1f, // 00609c1a |. 75 1f jnz short あや<E38182>00609c3b
// 0x3b,0x5f, 0x40, // 00609c1c |. 3b5f 40 cmp ebx,dword ptr ds:[edi+0x40]
// 0x75, 0x1a, // 00609c1f |. 75 1a jnz short あや<E38182>00609c3b
// 0x83,0x7f, 0x44, 0x00, // 00609c21 |. 837f 44 00 cmp dword ptr ds:[edi+0x44],0x0
// 0x74, 0x14, // 00609c25 |. 74 14 je short あや<E38182>00609c3b
//};
//enum { addr_offset = 0x00609bf0 - 0x00609c0e }; // distance to the beginning of the function
const BYTE bytes[] = {
0x74, 0x14, // 00609c25 |. 74 14 je short あや<E38182>00609c3b
0x5f, // 00609c27 |. 5f pop edi
0xb0, 0x01, // 00609c28 |. b0 01 mov al,0x1
0x5b, // 00609c2a |. 5b pop ebx
0x8b,0x4d, 0xf4 // 00609c2b |. 8b4d f4 mov ecx,dword ptr ss:[ebp-0xc]
};
enum { // distance to the beginning of the function
addr_offset_A = 0x00609bf0 - 0x00609c25 // -53
, addr_offset_W = 0x00406540 - 0x00406572 // -50
};
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
ULONG start = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
if (!start) {
ConsoleOutput("ScenarioPlayer: pattern not found");
return false;
}
DWORD addr = MemDbg::findEnclosingAlignedFunction(start, 80); // range is around 50, use 80
enum : BYTE { push_ebp = 0x55 }; // 011d4c80 /$ 55 push ebp
if (!addr || *(BYTE *)addr != push_ebp) {
ConsoleOutput("ScenarioPlayer: pattern found but the function offset is invalid");
return false;
}
auto succ=false;
HookParam hp;
hp.address = addr;
hp.offset=get_stack(1);
if (
(addr - start == addr_offset_W)||
(
(Util::FindImportEntry(processStartAddress,(DWORD)GetGlyphOutlineA)==0)&&
(Util::FindImportEntry(processStartAddress,(DWORD)TextOutA)==0)&&
(Util::FindImportEntry(processStartAddress,(DWORD)ExtTextOutA)==0)&&
(Util::FindImportEntry(processStartAddress,(DWORD)GetTextExtentPoint32A)==0)
//祝福の鐘の音は、桜色の風と共に
)
) {
// Artikash 8/18/2018: can't figure out how to tell apart which hook is needed, so alert user
// (The method used to tell the hooks apart previously fails on https://vndb.org/v19713)
hp.type = CODEC_UTF16;
ConsoleOutput("INSERT ScenarioPlayerW");
succ=NewHook(hp, "ScenarioPlayerW");
} else {
hp.type = CODEC_ANSI_BE; // 4
ConsoleOutput("INSERT ScenarioPlayerA");
succ=NewHook(hp, "ScenarioPlayerA");
}
ConsoleOutput("Text encoding might be wrong: try changing it if this hook finds garbage!");
return succ;
}
bool InsertScenarioPlayerHookx() {
//夏彩恋呗
//为避免和engine中的冲突进行一次xref
const BYTE bytes[] = {
0xC1,0xE8,0x02,0x25,0x01,0xFF,0xFF,0xFF,0x89,0x45,XX
};
auto addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
ConsoleOutput("%p", addr);
if (addr == 0)return false;
addr = MemDbg::findEnclosingAlignedFunction(addr);
ConsoleOutput("%p", addr);
if (addr == 0)return false;
auto addrs = findxref_reverse_checkcallop(addr, addr - 0x1000, addr, 0xe9);
if (addrs.size() != 1)return false;
addr = addrs[0];
addr = MemDbg::findEnclosingAlignedFunction(addr);
if (addr == 0)return false;
HookParam hp;
hp.address = addr;
hp.offset=get_stack(1);
hp.type = CODEC_UTF16;
return NewHook(hp, "sutajioryokutyaW");
}
namespace{
bool Iyashikei(){
//癒し系ソープ嬢ヒロさん
const BYTE bytes[] = {
0x6A,0xFF,
0x68,XX4,
0x64,0xA1,0x00,0x00,0x00,0x00,
0x50,
0x83,0xEC,0x08,
0x56,
0xA1,0x08,0x6E,0x6B,0x00,
0x33,0xC4,
0x50,
0x8D,0x44,0x24,XX,
0x64,0xA3,0x00,0x00,0x00,0x00,
0x8B,0xF1,
0x8B,0x44,0x24,XX,
0x50,
0x8D,0x4C,0x24,XX,
0x51,
0x8B,0xCE,
0xE8,XX4
};
auto addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
if(addr==0)return false;
HookParam hp;
hp.address = addr;
hp.offset=get_stack(1);
hp.type = CODEC_ANSI_BE;
return NewHook(hp, "Iyashikei");
}
}
bool InsertScenarioPlayerHook_all(){
bool b1= InsertScenarioPlayerHook();
bool b2=InsertScenarioPlayerHookx();
return b1||b2||Iyashikei();
}
bool Ryokucha::attach_function() {
InsertRyokuchaHook();
if (Util::CheckFile(L"*.iar") && Util::CheckFile(L"*.sec5")) // jichi 9/27/2014: For new Ryokucha games
InsertScenarioPlayerHook_all();
return true;
}
bool ScenarioPlayer_last::attach_function() {
return InsertScenarioPlayerHook_all();
}
bool Ryokucha2::attach_function() {
//夏日
const BYTE bytes[] = {
0x8b,XX2,0x2b,0xd1,0xc1,0xfa,0x02,0x3b,0xd0,0x76
};
auto addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
ConsoleOutput("%p", addr);
if (addr == 0)return false;
addr = MemDbg::findEnclosingAlignedFunction(addr);
ConsoleOutput("%p", addr);
if (addr == 0)return false;
HookParam hp;
hp.address = addr;
hp.offset =get_stack(6);
hp.type = USING_STRING;
hp.filter_fun = [](void* data, size_t* len, HookParam* hp) {
std::string s = std::string(reinterpret_cast<char*>(data), *len);
if (s[0] == '#')return false;
return true;
};
return NewHook(hp, "sutajioryokutya");
}