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

370 lines
14 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"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 スク水不要<E4B88D> /HA4@4AD140
* 18 ななちも<E381A1>とぁ<E381A8>しょ: /HA4@5104A0
* 19 発惁<E799BA>んこぁ<E38193><E38181> /HA4@51D720
* 20 わたし<E3819F>たまごさ<E38194> /HA4@4968E0
* 21 修学旡<E5ADA6>夜更かし<E3818B> /HA4@49DC00
* 22 おぼえたてキヂ<E382AD>: /HA4@49DDB0
* 23 ちっさい巫女さんSOS: /HA4@4B4AA0
* 24 はじめてのお<E381AE>ろやさん: /HA4@4B5600
* 25 はきわすれ愛好<E6849B> /HA4@57E360
* 26 朝っぱらから発惮<E799BA><E683AE> /HA4@57E360
* 27 となり<E381AA>ヴァンパイア: /HA4@5593B0
* 28 麦わら帽子と水辺の妖精: /HA4@5593B0
* 29 海と温泉と夏休み: /HA4@6DE8E0
* 30 駏<>子屋さん繁盛<E7B981> /HA4@6DEC90
* 31 浴衣の下<E381AE><20>神社で発見<E799BA><EFBFBD>パン少女 /HA4@6DEC90
* 32 プ<>ルのじか<E38198>スク水不要<E4B88D>: /HA4@62AE10
* 33 妹のお泊まり<E381BE> /HA4@6087A0
* 34 薝<>少女: /HA4@6087A0
* 35 あや<E38182>Princess Intermezzo: /HA4@609BF0
*
* SG01 男湯<E794B7>: /HA4@6087A0
*
* c71 真<>の大晦日CD: /HA4@516b50
* c78 sol-fa-soft真夏<E79C9F>お気楽CD: /HA4@6DEC90
*
* Example: 35 あや<E38182>Princess Intermezzo: /HA4@609BF0
* - addr: 6331376 = 0x609bf0
* - length_offset: 1
* - off: 4
* - type: 4
*
* ASCII: あや<E38182> 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 あや<E38182>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 あや<E38182>00609c3b
* 00609c1c |. 3b5f 40 cmp ebx,dword ptr ds:[edi+0x40]
* 00609c1f |. 75 1a jnz short あや<E38182>00609c3b
* 00609c21 |. 837f 44 00 cmp dword ptr ds:[edi+0x44],0x0
* 00609c25 |. 74 14 je short あや<E38182>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: こいな<E38184>小田舎で初恋x中出しセクシャルライ<E383A9>, 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: 祝福<E7A59D><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");
}