mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-24 14:25:37 +08:00
353 lines
15 KiB
C++
353 lines
15 KiB
C++
#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;
|
||
}
|