LunaHook-mirror/LunaHook/engine32/Tamamo.cpp
恍兮惚兮 eb123790e6 refactor
2024-03-21 18:29:50 +08:00

353 lines
15 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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"Tamamo.h"
/** jichi 8/23/2015 Tamamo
* Sample game: 閃光の騎士 ~カリスティアナイト~ Ver1.03
*
* Debugging method: insert hw breakpoint to the text in memory
*
* 006107A6 76 08 JBE SHORT .006107B0
* 006107A8 3BF8 CMP EDI,EAX
* 006107AA 0F82 68030000 JB .00610B18
* 006107B0 0FBA25 F88E7300 01 BT DWORD PTR DS:[0x738EF8],0x1
* 006107B8 73 07 JNB SHORT .006107C1
* 006107BA F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] ; jichi: accessed here
* 006107BC E9 17030000 JMP .00610AD8
* 006107C1 81F9 80000000 CMP ECX,0x80
* 006107C7 0F82 CE010000 JB .0061099B
* 006107CD 8BC7 MOV EAX,EDI
* 006107CF 33C6 XOR EAX,ESI
* 006107D1 A9 0F000000 TEST EAX,0xF
* 006107D6 75 0E JNZ SHORT .006107E6
*
* 0012FD7C 0012FE1C
* 0012FD80 00000059
* 0012FD84 0051C298 RETURN to .0051C298 from .00610790
* 0012FD88 0207E490 ; jichi: target
* 0012FD8C 0C0BE768 ; jichi: source text
* 0012FD90 00000059 ; jichi: source size
* 0012FD94 002A7C58
* 0012FD98 0C1E7338
* 0012FD9C 0012FE1C
* 0012FDA0 /0012FDC0 ; jichi: split
* 0012FDA4 |0056A83F RETURN to .0056A83F from .0051C1C0
* 0012FDA8 |0C1E733C
* 0012FDAC |00000000
* 0012FDB0 |FFFFFFFF
* 0012FDB4 |020EDAD0
* 0012FDB8 |0220CC28
* 0012FDBC |020EDAD0
* 0012FDC0 ]0012FE44
* 0012FDC4 |0055EF84 RETURN to .0055EF84 from .0056A7B0
* 0012FDC8 |0012FE1C
* 0012FDCC |ED1BC1C5
* 0012FDD0 |020EDAD0
* 0012FDD4 |002998A8
* 0012FDD8 |020EDAD0
*
* Hooked call:
* 0051C283 5D POP EBP
* 0051C284 C2 0C00 RETN 0xC
* 0051C287 8BD6 MOV EDX,ESI
* 0051C289 85FF TEST EDI,EDI
* 0051C28B 74 0E JE SHORT .0051C29B
* 0051C28D 57 PUSH EDI
* 0051C28E 8D040B LEA EAX,DWORD PTR DS:[EBX+ECX]
* 0051C291 50 PUSH EAX
* 0051C292 52 PUSH EDX
* 0051C293 E8 F8440F00 CALL .00610790 ; jichi: copy invoked here
* 0051C298 83C4 0C ADD ESP,0xC
* 0051C29B 837E 14 10 CMP DWORD PTR DS:[ESI+0x14],0x10
* 0051C29F 897E 10 MOV DWORD PTR DS:[ESI+0x10],EDI
* 0051C2A2 72 0F JB SHORT .0051C2B3
* 0051C2A4 8B06 MOV EAX,DWORD PTR DS:[ESI]
* 0051C2A6 C60438 00 MOV BYTE PTR DS:[EAX+EDI],0x0
* 0051C2AA 8BC6 MOV EAX,ESI
* 0051C2AC 5F POP EDI
* 0051C2AD 5E POP ESI
* 0051C2AE 5B POP EBX
* 0051C2AF 5D POP EBP
* 0051C2B0 C2 0C00 RETN 0xC
* 0051C2B3 8BC6 MOV EAX,ESI
*
* Sample text with new lines:
*
* 0C0BE748 70 00 69 00 2E 00 64 00 6C 00 6C 00 00 00 6C 00 p.i...d.l.l...l.
* 0C0BE758 00 00 00 00 0F 00 00 00 8B 91 3F 66 00 00 00 88 .......拒?f...・
* 0C0BE768 83 4E 83 8B 83 67 83 93 81 75 8E 84 82 C9 82 CD クルトン「私には
* 0C0BE778 95 90 91 95 82 AA 82 C2 82 A2 82 C4 82 A2 82 DC 武装がついていま
* 0C0BE788 82 B9 82 F1 82 A9 82 E7 81 41 0D 0A 81 40 8D 55 せんから、.. 攻
* 0C0BE798 82 DF 82 C4 82 B1 82 E7 82 EA 82 BD 82 E7 82 D0 めてこられたらひ
* 0C0BE7A8 82 C6 82 BD 82 DC 82 E8 82 E0 82 A0 82 E8 82 DC とたまりもありま
* 0C0BE7B8 82 B9 82 F1 81 76 3C 65 3E 00 3E 00 3E 00 00 00 せん」<e>.>.>...
* 0C0BE7C8 9E 91 3F 66 99 82 00 88 83 53 83 8D 81 5B 83 93 梠?f凾.・Sローン
* 0C0BE7D8 8C 5A 81 75 82 D6 82 D6 81 42 95 D4 82 B5 82 C4 兄「へへ。返して
* 0C0BE7E8 82 D9 82 B5 82 AF 82 E8 82 E1 82 C2 82 A2 82 C4 ほしけりゃついて
* 0C0BE7F8 82 AB 82 C8 81 42 83 49 83 8C 82 B3 82 DC 82 CC きな。オレさまの
*
* Sample game: 冒険者の町を作ろう!2 Ver1.01
*
* 0068028B CC INT3
* 0068028C CC INT3
* 0068028D CC INT3
* 0068028E CC INT3
* 0068028F CC INT3
* 00680290 55 PUSH EBP
* 00680291 8BEC MOV EBP,ESP
* 00680293 57 PUSH EDI
* 00680294 56 PUSH ESI
* 00680295 8B75 0C MOV ESI,DWORD PTR SS:[EBP+0xC]
* 00680298 8B4D 10 MOV ECX,DWORD PTR SS:[EBP+0x10]
* 0068029B 8B7D 08 MOV EDI,DWORD PTR SS:[EBP+0x8]
* 0068029E 8BC1 MOV EAX,ECX
* 006802A0 8BD1 MOV EDX,ECX
* 006802A2 03C6 ADD EAX,ESI
* 006802A4 3BFE CMP EDI,ESI
* 006802A6 76 08 JBE SHORT .006802B0
* 006802A8 3BF8 CMP EDI,EAX
* 006802AA 0F82 A4010000 JB .00680454
* 006802B0 81F9 00010000 CMP ECX,0x100
* 006802B6 72 1F JB SHORT .006802D7
* 006802B8 833D 64FB8C00 00 CMP DWORD PTR DS:[0x8CFB64],0x0
* 006802BF 74 16 JE SHORT .006802D7
* 006802C1 57 PUSH EDI
* 006802C2 56 PUSH ESI
* 006802C3 83E7 0F AND EDI,0xF
* 006802C6 83E6 0F AND ESI,0xF
* 006802C9 3BFE CMP EDI,ESI
* 006802CB 5E POP ESI
* 006802CC 5F POP EDI
* 006802CD 75 08 JNZ SHORT .006802D7
* 006802CF 5E POP ESI
* 006802D0 5F POP EDI
* 006802D1 5D POP EBP
* 006802D2 E9 FC090100 JMP .00690CD3
* 006802D7 F7C7 03000000 TEST EDI,0x3
* 006802DD 75 15 JNZ SHORT .006802F4
* 006802DF C1E9 02 SHR ECX,0x2
* 006802E2 83E2 03 AND EDX,0x3
* 006802E5 83F9 08 CMP ECX,0x8
* 006802E8 72 2A JB SHORT .00680314
* 006802EA F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] jichi: here
* 006802EC FF2495 04046800 JMP DWORD PTR DS:[EDX*4+0x680404]
* 006802F3 90 NOP
* 006802F4 8BC7 MOV EAX,EDI
* 006802F6 BA 03000000 MOV EDX,0x3
* 006802FB 83E9 04 SUB ECX,0x4
* 006802FE 72 0C JB SHORT .0068030C
* 00680300 83E0 03 AND EAX,0x3
* 00680303 03C8 ADD ECX,EAX
* 00680305 FF2485 18036800 JMP DWORD PTR DS:[EAX*4+0x680318]
* 0068030C FF248D 14046800 JMP DWORD PTR DS:[ECX*4+0x680414]
* 00680313 90 NOP
* 00680314 FF248D 98036800 JMP DWORD PTR DS:[ECX*4+0x680398]
* 0068031B 90 NOP
* 0068031C 2803 SUB BYTE PTR DS:[EBX],AL
* 0068031E 68 00540368 PUSH 0x68035400
* 00680323 0078 03 ADD BYTE PTR DS:[EAX+0x3],BH
* 00680326 68 0023D18A PUSH 0x8AD12300
* 0068032B 06 PUSH ES
* 0068032C 8807 MOV BYTE PTR DS:[EDI],AL
* 0068032E 8A46 01 MOV AL,BYTE PTR DS:[ESI+0x1]
* 00680331 8847 01 MOV BYTE PTR DS:[EDI+0x1],AL
* 00680334 8A46 02 MOV AL,BYTE PTR DS:[ESI+0x2]
*
* 0067FA4F 8BC6 MOV EAX,ESI
* 0067FA51 EB 45 JMP SHORT .0067FA98
* 0067FA53 397D 10 CMP DWORD PTR SS:[EBP+0x10],EDI
* 0067FA56 74 16 JE SHORT .0067FA6E
* 0067FA58 3975 0C CMP DWORD PTR SS:[EBP+0xC],ESI
* 0067FA5B 72 11 JB SHORT .0067FA6E
* 0067FA5D 56 PUSH ESI
* 0067FA5E FF75 10 PUSH DWORD PTR SS:[EBP+0x10]
* 0067FA61 FF75 08 PUSH DWORD PTR SS:[EBP+0x8]
* 0067FA64 E8 27080000 CALL .00680290 ; jichi: copy invoked here
* 0067FA69 83C4 0C ADD ESP,0xC
* 0067FA6C ^EB C1 JMP SHORT .0067FA2F
* 0067FA6E FF75 0C PUSH DWORD PTR SS:[EBP+0xC]
* 0067FA71 57 PUSH EDI
* 0067FA72 FF75 08 PUSH DWORD PTR SS:[EBP+0x8]
*
* 0012FC04 00000059
* 0012FC08 00000000
* 0012FC0C /0012FC28
* 0012FC10 |0067FA69 RETURN to .0067FA69 from .00680290
* 0012FC14 |072CEF78 ; jichi: target text
* 0012FC18 |07261840 ; jichi: source text
* 0012FC1C |00000059 ; jichi: source size
* 0012FC20 |FFFFFFFE
* 0012FC24 |00000000
* 0012FC28 ]0012FC40 ; jichi: split
* 0012FC2C |00404E58 RETURN to .00404E58 from .0067FA1F
* 0012FC30 |072CEF78 ; jichi: target text
* 0012FC34 |0000005F ; jichi: target capacity
* 0012FC38 |07261840 ; jichi: source text
* 0012FC3C |00000059 ; jichi: source size
* 0012FC40 ]0012FC58
* 0012FC44 |00404E38 RETURN to .00404E38 from .00404E40
* 0012FC48 |072CEF78
* 0012FC4C |0000005F
* 0012FC50 |07261840
* 0012FC54 |00000059
* 0012FC58 ]0012FC78
* 0012FC5C |00404B06 RETURN to .00404B06 from .00404E20
* 0012FC60 |072CEF78
* 0012FC64 |0000005F
* 0012FC68 |07261840
* 0012FC6C |00000059
* 0012FC70 |00000000
* 0012FC74 |0012FD30
* 0012FC78 ]0012FC98
* 0012FC7C |004025FE RETURN to .004025FE from .00404AE0
* 0012FC80 |072CEF78
* 0012FC84 |0000005F
* 0012FC88 |07261840
* 0012FC8C |00000059
* 0012FC90 |0012FD30
* 0012FC94 |00000059
* 0012FC98 ]0012FCB0
* 0012FC9C |0040254B RETURN to .0040254B from .00402560
* 0012FCA0 |074B6EA4
* 0012FCA4 |00000000
* 0012FCA8 |FFFFFFFF
*
* 07261840 83 4A 83 43 81 75 82 A0 82 C6 82 CD 82 B1 82 EA カイ「あとはこれ
* 07261850 82 C9 81 41 91 BA 92 B7 82 CC 83 54 83 43 83 93 に、村長のサイン
* 07261860 82 C6 88 F3 8A D3 82 F0 81 63 81 63 82 C1 82 C6 と印鑑を……っと
* 07261870 81 42 0D 0A 81 40 82 6E 82 6A 81 41 82 AB 82 E5 。.. OK、きょ
* 07261880 82 A4 82 CC 83 66 83 58 83 4E 83 8F 81 5B 83 4E うのデスクワーク
* 07261890 8F 49 97 B9 81 76 3C 65 3E 00 81 76 3C 65 3E 00 終了」<e>.」<e>.
* 072618A0 98 DD 95 48 00 40 00 88 83 4A 83 43 81 75 81 63 俤菱.@.・Jイ「…
* 072618B0 81 63 82 A4 82 F1 81 41 82 BB 82 A4 82 B5 82 E6 …うん、そうしよ
*/
namespace { // unnamed
bool TamamoFilter(LPVOID data, size_t *size, HookParam *)
{
LPSTR text = (LPSTR)data;
if (::memchr(text, '<', *size))
StringFilter(text, reinterpret_cast<size_t *>(size), "<e>", 3);
StringFilter(text, reinterpret_cast<size_t *>(size), "\x0d\x0a\x81\x40", 4); // remove \n before space
StringFilterBetween(text,size,"<",1,">",1);
StringFilterBetween(text,size,"{",1,"}",1);
return true;
}
void SpecialHookTamamo(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
{
auto text = (LPCSTR)stack->stack[1]; // arg2
auto size = stack->stack[2]; // arg3
if (0 < size && size < VNR_TEXT_CAPACITY && size == ::strlen(text) && !all_ascii(text)) {
*data = (DWORD)text;
//*len = argof(esp_base, 3 - 1);
*len = size;
//*split = argof(8 - 1, esp_base); // use parent return address as split
//*split = argof(7 - 1, esp_base); // use the address just before parent retaddr
*split = stack->stack[5];
//if (hp.split)
// *split = *(DWORD *)(esp_base + hp.split);
}
}
} // unnamed namespace
bool InsertTamamoHook()
{
ULONG addr = 0;
{ // for new games
const BYTE bytes[] = {
0x8b,0xd6, // 0051c287 8bd6 mov edx,esi
0x85,0xff, // 0051c289 85ff test edi,edi
0x74, 0x0e, // 0051c28b 74 0e je short .0051c29b
0x57, // 0051c28d 57 push edi
0x8d,0x04,0x0b, // 0051c28e 8d040b lea eax,dword ptr ds:[ebx+ecx]
0x50, // 0051c291 50 push eax
0x52, // 0051c292 52 push edx
0xe8 //f8440f00 // 0051c293 e8 f8440f00 call .00610790 ; jichi: copy invoked here
};
enum { addr_offset = sizeof(bytes) - 1 };
addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
if (addr) {
addr += addr_offset;
ConsoleOutput("Tamamo: pattern for new version found");
}
}
if (!addr) { // for old games
const BYTE bytes[] = {
0x72, 0x11, // 0067fa5b 72 11 jb short .0067fa6e
0x56, // 0067fa5d 56 push esi
0xff,0x75, 0x10, // 0067fa5e ff75 10 push dword ptr ss:[ebp+0x10]
0xff,0x75, 0x08, // 0067fa61 ff75 08 push dword ptr ss:[ebp+0x8]
0xe8 // 27080000 // 0067fa64 e8 27080000 call .00680290 ; jichi: copy invoked here
};
enum { addr_offset = sizeof(bytes) - 1 };
addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
if (addr) {
addr += addr_offset;
ConsoleOutput("Tamamo: pattern for old version found");
}
}
if (!addr) {
ConsoleOutput("Tamamo: pattern not found");
return false;
}
HookParam hp;
hp.address = addr;
hp.text_fun = SpecialHookTamamo;
hp.filter_fun = TamamoFilter;
hp.type = USING_STRING|USING_SPLIT|NO_CONTEXT;
ConsoleOutput("INSERT Tamamo");
return NewHook(hp, "Tamamo");
}
namespace{
bool Tamamogettext(LPVOID data, size_t *size, HookParam *)
{
auto s=std::string((char*)data,*size);
s=std::regex_replace(s, std::regex("\\{#(.*?)\\}"), "");
s = std::regex_replace(s, std::regex("<(.*?)>"), "");
s = std::regex_replace(s, std::regex("(.*)\x81u([\\s\\S]*?)\x81v(.*)"), "\x81u$2\x81v"); //「 」
s = std::regex_replace(s, std::regex("(.*)\x81i([\\s\\S]*?)\x81j(.*)"), "\x81i$2\x81j"); //
return write_string_overwrite(data,size,s);
}
bool Tamamogetname(LPVOID data, size_t *size, HookParam *)
{
auto s=std::string((char*)data,*size);
s=std::regex_replace(s, std::regex("\\{#(.*?)\\}"), "");
s = std::regex_replace(s, std::regex("<(.*?)>"), "");
if(s.find("\x81u")!=s.npos && s.find("\x81v")!=s.npos)
s = std::regex_replace(s, std::regex("(.*)\x81u([\\s\\S]*?)\x81v(.*)"), "$1"); //「 」
else if (s.find("\x81i")!=s.npos && s.find("\x81j")!=s.npos)
s = std::regex_replace(s, std::regex("(.*)\x81i([\\s\\S]*?)\x81j(.*)"), "$1"); //
else return false;
return write_string_overwrite(data,size,s);
}
bool tamamo3(){
//閃光の騎士 ~カリスティアナイト~
char face[]="face_%s_%s.png";
auto addr = MemDbg::findBytes(face, sizeof(face), processStartAddress, processStopAddress);
if(addr==0)return false;
bool ok=false;
BYTE bytes[]={0x68,XX4};
memcpy(bytes+1,&addr,4);
for(auto addr:Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, processStartAddress, processStopAddress)){
addr = MemDbg::findEnclosingAlignedFunction(addr);
if (!addr) continue;
HookParam hp;
hp.address = addr ;
hp.offset=get_stack(1);
hp.type = USING_STRING;
hp.filter_fun=Tamamogettext;
ok|=NewHook(hp, "tamamo_text");
hp.address = addr+5 ;
hp.offset=get_stack(3);
hp.filter_fun=Tamamogetname;
ok|=NewHook(hp, "tamamo_name");
}
return ok;
}
}
bool Tamamo::attach_function() {
bool aa=tamamo3();
return InsertTamamoHook()||aa;
}