LunaHook-mirror/LunaHook/engine32/System4x.cpp
恍兮惚兮 6a43cd5b86 pch
2024-05-06 23:31:54 +08:00

1760 lines
79 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"System4x.h"
/**
* jichi 12/26/2013: Rance hook
*
* ランス01 光をもとめて: /HSN4:-14@5506A9
* - addr: 5572265 (0x5596a9)
* - off: 4
* - split: 4294967272 (0xffffffe8 = -0x18)
* - type: 1041 (0x411)
*
* the above code has the same pattern except int3.
* 005506a9 |. e8 f2fb1600 call Rance01.006c02a0 ; hook here
* 005506ae |. 83c4 0c add esp,0xc
* 005506b1 |. 5f pop edi
* 005506b2 |. 5e pop esi
* 005506b3 |. b0 01 mov al,0x1
* 005506b5 |. 5b pop ebx
* 005506b6 \. c2 0400 retn 0x4
* 005506b9 cc int3
*
* ランス・クエス<E382A8> /hsn4:-14@42e08a
* 0042e08a |. e8 91ed1f00 call Ranceque.0062ce20 ; hook here
* 0042e08f |. 83c4 0c add esp,0xc
* 0042e092 |. 5f pop edi
* 0042e093 |. 5e pop esi
* 0042e094 |. b0 01 mov al,0x1
* 0042e096 |. 5b pop ebx
* 0042e097 \. c2 0400 retn 0x4
* 0042e09a cc int3
*
* 5/7/2015 イブニクル version 1.0.1
* The hooked function is no longer get called after loading AliceRunPatch.dll.
* The hooked function is below.
* See also ATcode: http://capita.tistory.com/m/post/256
* 005C40AE CC INT3
* 005C40AF CC INT3
* 005C40B0 53 PUSH EBX
* 005C40B1 8B5C24 08 MOV EBX,DWORD PTR SS:[ESP+0x8]
* 005C40B5 56 PUSH ESI
* 005C40B6 57 PUSH EDI
* 005C40B7 8B7B 10 MOV EDI,DWORD PTR DS:[EBX+0x10]
* 005C40BA 8BF0 MOV ESI,EAX
* 005C40BC 47 INC EDI
* 005C40BD 3B7E 0C CMP EDI,DWORD PTR DS:[ESI+0xC]
* 005C40C0 76 0F JBE SHORT .005C40D1
* 005C40C2 E8 79F8FFFF CALL .005C3940
* 005C40C7 84C0 TEST AL,AL
* 005C40C9 75 06 JNZ SHORT .005C40D1
* 005C40CB 5F POP EDI
* 005C40CC 5E POP ESI
* 005C40CD 5B POP EBX
* 005C40CE C2 0400 RETN 0x4
* 005C40D1 837B 14 10 CMP DWORD PTR DS:[EBX+0x14],0x10
* 005C40D5 72 02 JB SHORT .005C40D9
* 005C40D7 8B1B MOV EBX,DWORD PTR DS:[EBX]
* 005C40D9 837E 0C 00 CMP DWORD PTR DS:[ESI+0xC],0x0
* 005C40DD 75 15 JNZ SHORT .005C40F4
* 005C40DF 57 PUSH EDI
* 005C40E0 33C0 XOR EAX,EAX
* 005C40E2 53 PUSH EBX
* 005C40E3 50 PUSH EAX
* 005C40E4 E8 B7400D00 CALL .006981A0
* 005C40E9 83C4 0C ADD ESP,0xC
* 005C40EC 5F POP EDI
* 005C40ED 5E POP ESI
* 005C40EE B0 01 MOV AL,0x1
* 005C40F0 5B POP EBX
* 005C40F1 C2 0400 RETN 0x4
* 005C40F4 8B46 08 MOV EAX,DWORD PTR DS:[ESI+0x8]
* 005C40F7 57 PUSH EDI
* 005C40F8 53 PUSH EBX
* 005C40F9 50 PUSH EAX
* 005C40FA E8 A1400D00 CALL .006981A0 ; jichi: call here
* 005C40FF 83C4 0C ADD ESP,0xC
* 005C4102 5F POP EDI
* 005C4103 5E POP ESI
* 005C4104 B0 01 MOV AL,0x1
* 005C4106 5B POP EBX
* 005C4107 C2 0400 RETN 0x4
* 005C410A CC INT3
* 005C410B CC INT3
* 005C410C CC INT3 *
*/
static bool InsertSystem43OldHook(ULONG startAddress, ULONG stopAddress, LPCSTR hookName)
{
// i.e. 83c40c5f5eb0015bc20400cccc without leading 0xe8
//const BYTE ins[] = { // 005506a9 |. e8 f2fb1600 call rance01.006c02a0 ; hook here
// 0x83,0xc4, 0x0c, // 005506ae |. 83c4 0c add esp,0xc
// 0x5f, // 005506b1 |. 5f pop edi
// 0x5e, // 005506b2 |. 5e pop esi
// 0xb0, 0x01, // 005506b3 |. b0 01 mov al,0x1
// 0x5b, // 005506b5 |. 5b pop ebx
// 0xc2, 0x04,0x00, // 005506b6 \. c2 0400 retn 0x4
// 0xcc, 0xcc // patching a few int3 to make sure that this is at the end of the code block
//};
//enum { addr_offset = -5 }; // the function call before the ins
//ULONG addr = processStartAddress; //- sizeof(ins);
////addr = 0x5506a9;
//enum { near_call = 0xe8 }; // intra-module function call
//do {
// //addr += sizeof(ins); // so that each time return diff address -- not needed
// ULONG range = min(processStopAddress - addr, MAX_REL_ADDR);
// addr = MemDbg::findBytes(ins, sizeof(ins), addr, addr + range);
// if (!addr) {
// //ITH_MSG(L"failed");
// ConsoleOutput("System43: pattern not found");
// return false;
// }
// addr += addr_offset;
//} while(near_call != *(BYTE *)addr); // function call
//GROWL_DWORD(addr);
// i.e. 83c40c5f5eb0015bc20400cccc without leading 0xe8
const BYTE bytes[] = {
0xe8, XX4, // 005506a9 |. e8 f2fb1600 call rance01.006c02a0 ; hook here
0x83,0xc4, 0x0c, // 005506ae |. 83c4 0c add esp,0xc
XX, // 005506b1 |. 5f pop edi ; Artikash 2/9/2019 change these to wildcards: Evenicle 2 has the pops and moves switched order
XX, // 005506b2 |. 5e pop esi
XX, XX, // 005506b3 |. b0 01 mov al,0x1
0x5b, // 005506b5 |. 5b pop ebx
0xc2, 0x04,0x00, // 005506b6 \. c2 0400 retn 0x4
0xcc, 0xcc // patching a few int3 to make sure that this is at the end of the code block
};
enum { addr_offset = 0 };
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
//GROWL_DWORD(addr);
if (!addr) {
ConsoleOutput("System43: pattern not found");
return false;
}
HookParam hp;
hp.address = addr + addr_offset;
hp.offset=get_stack(1);
hp.split = get_reg(regs::esp);
hp.type = NO_CONTEXT|USING_SPLIT|USING_STRING|EMBED_ABLE|EMBED_BEFORE_SIMPLE|EMBED_AFTER_NEW|EMBED_DYNA_SJIS;
ConsoleOutput("INSERT System43");
ConsoleOutput("System43: disable GDI hooks"); // disable hooking to TextOutA, which is cached
return NewHook(hp, hookName);
}
/** 5/13/2015 Add new hook for System43 engine that has no garbage threads and can detect character name
* Sample game: Evenicle
* See: http://capita.tistory.com/m/post/256
*
* 004EEA6C CC INT3
* 004EEA6D CC INT3
* 004EEA6E CC INT3
* 004EEA6F CC INT3
* 004EEA70 6A FF PUSH -0x1
* 004EEA72 68 E8267000 PUSH .007026E8
* 004EEA77 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
* 004EEA7D 50 PUSH EAX
* 004EEA7E 83EC 20 SUB ESP,0x20
* 004EEA81 A1 DCC47700 MOV EAX,DWORD PTR DS:[0x77C4DC]
* 004EEA86 33C4 XOR EAX,ESP
* 004EEA88 894424 1C MOV DWORD PTR SS:[ESP+0x1C],EAX
* 004EEA8C 53 PUSH EBX
* 004EEA8D 55 PUSH EBP
* 004EEA8E 56 PUSH ESI
* 004EEA8F 57 PUSH EDI
* 004EEA90 A1 DCC47700 MOV EAX,DWORD PTR DS:[0x77C4DC]
* 004EEA95 33C4 XOR EAX,ESP
* 004EEA97 50 PUSH EAX
* 004EEA98 8D4424 34 LEA EAX,DWORD PTR SS:[ESP+0x34]
* 004EEA9C 64:A3 00000000 MOV DWORD PTR FS:[0],EAX
* 004EEAA2 8B4424 44 MOV EAX,DWORD PTR SS:[ESP+0x44]
* 004EEAA6 8BF1 MOV ESI,ECX
* 004EEAA8 E8 8346FBFF CALL .004A3130
* 004EEAAD 8BE8 MOV EBP,EAX
* 004EEAAF 33DB XOR EBX,EBX
* 004EEAB1 3BEB CMP EBP,EBX
* 004EEAB3 75 07 JNZ SHORT .004EEABC
* 004EEAB5 32C0 XOR AL,AL
* 004EEAB7 E9 92000000 JMP .004EEB4E
* 004EEABC 8B06 MOV EAX,DWORD PTR DS:[ESI]
* 004EEABE 8B10 MOV EDX,DWORD PTR DS:[EAX]
* 004EEAC0 8BCE MOV ECX,ESI
* 004EEAC2 FFD2 CALL EDX
* 004EEAC4 8BC8 MOV ECX,EAX
* 004EEAC6 C74424 28 0F0000>MOV DWORD PTR SS:[ESP+0x28],0xF
* 004EEACE 895C24 24 MOV DWORD PTR SS:[ESP+0x24],EBX
* 004EEAD2 885C24 14 MOV BYTE PTR SS:[ESP+0x14],BL
* 004EEAD6 8D71 01 LEA ESI,DWORD PTR DS:[ECX+0x1]
* 004EEAD9 8DA424 00000000 LEA ESP,DWORD PTR SS:[ESP]
* 004EEAE0 8A11 MOV DL,BYTE PTR DS:[ECX]
* 004EEAE2 41 INC ECX
* 004EEAE3 3AD3 CMP DL,BL
* 004EEAE5 ^75 F9 JNZ SHORT .004EEAE0
* 004EEAE7 2BCE SUB ECX,ESI
* 004EEAE9 50 PUSH EAX
* 004EEAEA 8BF9 MOV EDI,ECX
* 004EEAEC 8D7424 18 LEA ESI,DWORD PTR SS:[ESP+0x18]
* 004EEAF0 E8 CB27F1FF CALL .004012C0
* 004EEAF5 8B7C24 48 MOV EDI,DWORD PTR SS:[ESP+0x48]
* 004EEAF9 895C24 3C MOV DWORD PTR SS:[ESP+0x3C],EBX
* 004EEAFD 8B75 3C MOV ESI,DWORD PTR SS:[EBP+0x3C]
* 004EEB00 E8 1B4A0100 CALL .00503520
* 004EEB05 8BF8 MOV EDI,EAX
* 004EEB07 8DB7 E4000000 LEA ESI,DWORD PTR DS:[EDI+0xE4]
* 004EEB0D 8D4424 14 LEA EAX,DWORD PTR SS:[ESP+0x14]
* 004EEB11 8BD6 MOV EDX,ESI
* 004EEB13 E8 985CF1FF CALL .004047B0
* 004EEB18 BD 10000000 MOV EBP,0x10
* 004EEB1D 84C0 TEST AL,AL
* 004EEB1F 75 18 JNZ SHORT .004EEB39
* 004EEB21 895E 10 MOV DWORD PTR DS:[ESI+0x10],EBX
* 004EEB24 396E 14 CMP DWORD PTR DS:[ESI+0x14],EBP
* 004EEB27 72 02 JB SHORT .004EEB2B
* 004EEB29 8B36 MOV ESI,DWORD PTR DS:[ESI]
* 004EEB2B 8D4424 14 LEA EAX,DWORD PTR SS:[ESP+0x14]
* 004EEB2F 50 PUSH EAX
* 004EEB30 8BCF MOV ECX,EDI
* 004EEB32 881E MOV BYTE PTR DS:[ESI],BL
* 004EEB34 E8 67CB0100 CALL .0050B6A0 ; jichi: ATcode modified here, text is on the top of the stack
* 004EEB39 396C24 28 CMP DWORD PTR SS:[ESP+0x28],EBP
* 004EEB3D 72 0D JB SHORT .004EEB4C
* 004EEB3F 8B4C24 14 MOV ECX,DWORD PTR SS:[ESP+0x14]
* 004EEB43 51 PUSH ECX
* 004EEB44 E8 42DC1900 CALL .0068C78B
* 004EEB49 83C4 04 ADD ESP,0x4
* 004EEB4C B0 01 MOV AL,0x1
* 004EEB4E 8B4C24 34 MOV ECX,DWORD PTR SS:[ESP+0x34]
* 004EEB52 64:890D 00000000 MOV DWORD PTR FS:[0],ECX
* 004EEB59 59 POP ECX
* 004EEB5A 5F POP EDI
* 004EEB5B 5E POP ESI
* 004EEB5C 5D POP EBP
* 004EEB5D 5B POP EBX
* 004EEB5E 8B4C24 1C MOV ECX,DWORD PTR SS:[ESP+0x1C]
* 004EEB62 33CC XOR ECX,ESP
* 004EEB64 E8 9CD61900 CALL .0068C205
* 004EEB69 83C4 2C ADD ESP,0x2C
* 004EEB6C C3 RETN
* 004EEB6D CC INT3
* 004EEB6E CC INT3
*
* Actual binary patch for Evenicle exe: http://capita.tistory.com/m/post/256
* {005E393B(EB), 004EEB34(E9 13 B6 21 00), 005C71E0(E9 48 2F 14 00), 005B6494(E9 10 3D 15 00), 0070A10F(90 90 90 90 90 E8 F7 9F EB FF E9 C7 D0 EB FF 90 90 90 90 90 E8 78 15 E0 FF E9 0C 4A DE FF 50 8B 87 B0 00 00 00 66 81 38 84 00 75 0E 83 78 EA 5B 75 08 E8 A2 00 00 00 58 EB C6 58 EB C8 50 52 BA E0 0B 7A 00 60 89 D7 8B 74 E4 28 B9 06 00 00 00 F3 A5 61 8B 44 E4 08 8B 40 10 85 C0 74 29 8B 44 E4 08 8B 40 14 83 F8 0F 75 08 89 54 E4 08 5A 58 EB 9D 8D 42 20 60 89 C7 8B 32 8B 4A 14 83 C1 09 F3 A4 61 89 02 EB E3 5A 58 EB 89 90 90 90 90 90 E8 6C 9F EB FF E9 F0 C2 EA FF 50 8B 44 E4 04 83 78 0C 01 76 31 8B 87 84 02 00 00 66 83 78 FC 46 75 24 83 78 F8 22 74 16 83 78 F8 13 75 18 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 E8 06 00 00 00 58 EB B5 58 EB B7 60 8B 74 E4 28 BF E0 0B 7A 00 89 7C E4 28 B9 0C 00 00 00 F3 A5 61 C3)}
*
* ATcode: FORCEFONT(5),ENCODEKOR,FONT(Malgun Gothic,-13),HOOK(0x0070A10F,TRANS([[ESP]+0x8],LEN([ESP]+0XC),PTRCHEAT),RETNPOS(COPY)),HOOK(0x0070A11E,TRANS([ESP],SMSTR(IGNORE)),RETNPOS(COPY)),HOOK(0x0070A19A,TRANS([[ESP]+0x8],LEN([ESP]+0XC),PTRCHEAT),RETNPOS(COPY))
* FilterCode: DenyWord{CUT(2)},FixLine{},KoFilter{},DumpText{},CustomDic{CDic},CustomScript{Write,Pass(-1),Cache}
*
* The second hooked address pointed to the text address.
* The logic here is simplify buffer the read text, and replace the text by zero
* Then translate/paint them together.
* Several variables near the text address is used to check if the text is finished or not.
*
* Function immediately before patched code:
* 0070A09E CC INT3
* 0070A09F CC INT3
* 0070A0A0 6A FF PUSH -0x1
* 0070A0A2 68 358A7000 PUSH .00708A35
* 0070A0A7 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
* 0070A0AD 50 PUSH EAX
* 0070A0AE 51 PUSH ECX
* 0070A0AF 56 PUSH ESI
* 0070A0B0 A1 DCC47700 MOV EAX,DWORD PTR DS:[0x77C4DC]
* 0070A0B5 33C4 XOR EAX,ESP
* 0070A0B7 50 PUSH EAX
* 0070A0B8 8D4424 0C LEA EAX,DWORD PTR SS:[ESP+0xC]
* 0070A0BC 64:A3 00000000 MOV DWORD PTR FS:[0],EAX
* 0070A0C2 C74424 14 000000>MOV DWORD PTR SS:[ESP+0x14],0x0
* 0070A0CA A1 54D17900 MOV EAX,DWORD PTR DS:[0x79D154]
* 0070A0CF 8B08 MOV ECX,DWORD PTR DS:[EAX]
* 0070A0D1 50 PUSH EAX
* 0070A0D2 51 PUSH ECX
* 0070A0D3 8D7424 10 LEA ESI,DWORD PTR SS:[ESP+0x10]
* 0070A0D7 E8 6416F8FF CALL .0068B740
* 0070A0DC A1 54D17900 MOV EAX,DWORD PTR DS:[0x79D154]
* 0070A0E1 50 PUSH EAX
* 0070A0E2 E8 A426F8FF CALL .0068C78B
* 0070A0E7 83C4 04 ADD ESP,0x4
* 0070A0EA 8B4C24 0C MOV ECX,DWORD PTR SS:[ESP+0xC]
* 0070A0EE 64:890D 00000000 MOV DWORD PTR FS:[0],ECX
* 0070A0F5 59 POP ECX
* 0070A0F6 5E POP ESI
* 0070A0F7 83C4 10 ADD ESP,0x10
* 0070A0FA C3 RETN
* 0070A0FB C705 C4C17900 64>MOV DWORD PTR DS:[0x79C1C4],.0070B664
* 0070A105 B9 C4C17900 MOV ECX,.0079C1C4
* 0070A10A ^E9 0722F8FF JMP .0068C316
*
* Patched code:
* 0070A10F 90 NOP ; jichi: ATcode hooked here
* 0070A110 90 NOP
* 0070A111 90 NOP
* 0070A112 90 NOP
* 0070A113 90 NOP
* 0070A114 E8 F79FEBFF CALL .005C4110
* 0070A119 ^E9 C7D0EBFF JMP .005C71E5
* 0070A11E 90 NOP
* 0070A11F 90 NOP
* 0070A120 90 NOP
* 0070A121 90 NOP
* 0070A122 90 NOP
* 0070A123 E8 7815E0FF CALL .0050B6A0 ; jichi: call the original function for hookpoint #2
* 0070A128 ^E9 0C4ADEFF JMP .004EEB39 ; jichi: come back to hookpoint#2
* 0070A12D 50 PUSH EAX ; jichi: this is for hookpoint #3, translate the text before send it to paint
* 0070A12E 8B87 B0000000 MOV EAX,DWORD PTR DS:[EDI+0xB0]
* 0070A134 66:8138 8400 CMP WORD PTR DS:[EAX],0x84
* 0070A139 75 0E JNZ SHORT .0070A149
* 0070A13B 8378 EA 5B CMP DWORD PTR DS:[EAX-0x16],0x5B
* 0070A13F 75 08 JNZ SHORT .0070A149
* 0070A141 E8 A2000000 CALL .0070A1E8
* 0070A146 58 POP EAX
* 0070A147 ^EB C6 JMP SHORT .0070A10F
* 0070A149 58 POP EAX
* 0070A14A ^EB C8 JMP SHORT .0070A114
* 0070A14C 50 PUSH EAX ; jichi: hookpoint#2 jmp here, text address is in [esp]
* 0070A14D 52 PUSH EDX
* 0070A14E BA E00B7A00 MOV EDX,.007A0BE0 ; jichi: 007A0BE0 points to unused zeroed memory
* 0070A153 60 PUSHAD ; jichi esp -= 0x20, now, esp[0x28] is text address, esp[0x24] = eax, and esp[0x20] = edx
* 0070A154 89D7 MOV EDI,EDX ; set 007A0BE0 as the target buffer to save text, edx is never modified
* 0070A156 8B74E4 28 MOV ESI,DWORD PTR SS:[ESP+0x28] ; set source text as target
* 0070A15A B9 06000000 MOV ECX,0x6 ; move for 6 bytes
* 0070A15F F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
* 0070A161 61 POPAD ; finished saving text, now [esp] is old edx, esp[0x4] is old eax, esp[0x8] is old text address
* 0070A162 8B44E4 08 MOV EAX,DWORD PTR SS:[ESP+0x8] ; eax = original text address
* 0070A166 8B40 10 MOV EAX,DWORD PTR DS:[EAX+0x10] ; eax = text[0x10]
* 0070A169 85C0 TEST EAX,EAX ; if end of text,
* 0070A16B 74 29 JE SHORT .0070A196 ; jump if eax is zero, comeback to hookpoint and ignore it
* 0070A16D 8B44E4 08 MOV EAX,DWORD PTR SS:[ESP+0x8] ; otherwise, if eax is not zero
* 0070A171 8B40 14 MOV EAX,DWORD PTR DS:[EAX+0x14] ; eax = text[0x14]
* 0070A174 83F8 0F CMP EAX,0xF ; jichi: compare text[0x14] with 0xf
* 0070A177 75 08 JNZ SHORT .0070A181 ; jump if not zero leaving text not modified, other continue and modify the text
* 0070A179 8954E4 08 MOV DWORD PTR SS:[ESP+0x8],EDX ; override esp+8 with edx, i.e. override text address by new text address and do translation
* 0070A17D 5A POP EDX
* 0070A17E 58 POP EAX ; jichi: restore edx and eax, now esp is back to normal. [esp] is the new text address
* 0070A17F ^EB 9D JMP SHORT .0070A11E ; jichi: jump to the top of the hooked place (nop) and do translation before coming back
* 0070A181 8D42 20 LEA EAX,DWORD PTR DS:[EDX+0x20] ; text is not modified, esp[0x8] is the text address, edx is the modified buffer, eax = buffer[0x20] address
* 0070A184 60 PUSHAD ; jichi: esp[0x28] is now the text address
* 0070A185 89C7 MOV EDI,EAX ; jichi: edx[0x20] is the target
* 0070A187 8B32 MOV ESI,DWORD PTR DS:[EDX] ; jichi: edx is the source
* 0070A189 8B4A 14 MOV ECX,DWORD PTR DS:[EDX+0x14]
* 0070A18C 83C1 09 ADD ECX,0x9 ; move for [edx+0x14]+0x9 time
* 0070A18F F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] ; jichi: shift text by 0x14 dword ptr
* 0070A191 61 POPAD ; jichi: now esp[0x8] is the text address
* 0070A192 8902 MOV DWORD PTR DS:[EDX],EAX ; eax is the new text address (edx+0x20), move the address to beginning of buffer ([edx]), i.e. edx is pointed to zero memory now
* 0070A194 ^EB E3 JMP SHORT .0070A179 ; come bback to modify the text address
* 0070A196 5A POP EDX
* 0070A197 58 POP EAX
* 0070A198 ^EB 89 JMP SHORT .0070A123 ; jichi: come back to call
* 0070A19A 90 NOP
* 0070A19B 90 NOP
* 0070A19C 90 NOP
* 0070A19D 90 NOP
* 0070A19E 90 NOP
* 0070A19F E8 6C9FEBFF CALL .005C4110
* 0070A1A4 ^E9 F0C2EAFF JMP .005B6499
* 0070A1A9 50 PUSH EAX ; jichi: from hookpoint #4
* 0070A1AA 8B44E4 04 MOV EAX,DWORD PTR SS:[ESP+0x4] ; jichi: move top of the old stack address to eax
* 0070A1AE 8378 0C 01 CMP DWORD PTR DS:[EAX+0xC],0x1
* 0070A1B2 76 31 JBE SHORT .0070A1E5 ; jichi: jump to leave if text[0xc] <= 0x1
* 0070A1B4 8B87 84020000 MOV EAX,DWORD PTR DS:[EDI+0x284]
* 0070A1BA 66:8378 FC 46 CMP WORD PTR DS:[EAX-0x4],0x46
* 0070A1BF 75 24 JNZ SHORT .0070A1E5
* 0070A1C1 8378 F8 22 CMP DWORD PTR DS:[EAX-0x8],0x22
* 0070A1C5 74 16 JE SHORT .0070A1DD
* 0070A1C7 8378 F8 13 CMP DWORD PTR DS:[EAX-0x8],0x13
* 0070A1CB 75 18 JNZ SHORT .0070A1E5
* 0070A1CD 90 NOP
* 0070A1CE 90 NOP
* 0070A1CF 90 NOP
* 0070A1D0 90 NOP
* 0070A1D1 90 NOP
* 0070A1D2 90 NOP
* 0070A1D3 90 NOP
* 0070A1D4 90 NOP
* 0070A1D5 90 NOP
* 0070A1D6 90 NOP
* 0070A1D7 90 NOP
* 0070A1D8 90 NOP
* 0070A1D9 90 NOP
* 0070A1DA 90 NOP
* 0070A1DB 90 NOP
* 0070A1DC 90 NOP
* 0070A1DD E8 06000000 CALL .0070A1E8
* 0070A1E2 58 POP EAX
* 0070A1E3 ^EB B5 JMP SHORT .0070A19A
* 0070A1E5 58 POP EAX
* 0070A1E6 ^EB B7 JMP SHORT .0070A19F
* 0070A1E8 60 PUSHAD
* 0070A1E9 8B74E4 28 MOV ESI,DWORD PTR SS:[ESP+0x28]
* 0070A1ED BF E00B7A00 MOV EDI,.007A0BE0
* 0070A1F2 897CE4 28 MOV DWORD PTR SS:[ESP+0x28],EDI
* 0070A1F6 B9 0C000000 MOV ECX,0xC
* 0070A1FB F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
* 0070A1FD 61 POPAD
* 0070A1FE C3 RETN
* 0070A1FF 0000 ADD BYTE PTR DS:[EAX],AL
* 0070A201 0000 ADD BYTE PTR DS:[EAX],AL
* 0070A203 0000 ADD BYTE PTR DS:[EAX],AL
*
* Modified places:
*
* 005E391C CC INT3
* 005E391D CC INT3
* 005E391E CC INT3
* 005E391F CC INT3
* 005E3920 55 PUSH EBP
* 005E3921 8BEC MOV EBP,ESP
* 005E3923 83E4 C0 AND ESP,0xFFFFFFC0
* 005E3926 83EC 34 SUB ESP,0x34
* 005E3929 53 PUSH EBX
* 005E392A 8B5D 08 MOV EBX,DWORD PTR SS:[EBP+0x8]
* 005E392D 817B 04 00010000 CMP DWORD PTR DS:[EBX+0x4],0x100
* 005E3934 56 PUSH ESI
* 005E3935 57 PUSH EDI
* 005E3936 8B7D 0C MOV EDI,DWORD PTR SS:[EBP+0xC]
* 005E3939 8BF0 MOV ESI,EAX
* 005E393B EB 67 JMP SHORT .005E39A4 ; jichi: here modified point#1, change to always jump to 5e39a4, when enabled it will change font size
* 005E393D 8D4424 28 LEA EAX,DWORD PTR SS:[ESP+0x28]
* 005E3941 50 PUSH EAX
* 005E3942 8D4C24 30 LEA ECX,DWORD PTR SS:[ESP+0x30]
*
* 004EEA6E CC INT3
* 004EEA6F CC INT3
* 004EEA70 6A FF PUSH -0x1
* 004EEA72 68 E8267000 PUSH .007026E8
* 004EEA77 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
* 004EEA7D 50 PUSH EAX
* 004EEA7E 83EC 20 SUB ESP,0x20
* 004EEA81 A1 DCC47700 MOV EAX,DWORD PTR DS:[0x77C4DC]
* 004EEA86 33C4 XOR EAX,ESP
* 004EEA88 894424 1C MOV DWORD PTR SS:[ESP+0x1C],EAX
* 004EEA8C 53 PUSH EBX
* 004EEA8D 55 PUSH EBP
* 004EEA8E 56 PUSH ESI
* 004EEA8F 57 PUSH EDI
* 004EEA90 A1 DCC47700 MOV EAX,DWORD PTR DS:[0x77C4DC]
* 004EEA95 33C4 XOR EAX,ESP
* 004EEA97 50 PUSH EAX
* 004EEA98 8D4424 34 LEA EAX,DWORD PTR SS:[ESP+0x34]
* 004EEA9C 64:A3 00000000 MOV DWORD PTR FS:[0],EAX
* 004EEAA2 8B4424 44 MOV EAX,DWORD PTR SS:[ESP+0x44]
* 004EEAA6 8BF1 MOV ESI,ECX
* 004EEAA8 E8 8346FBFF CALL .004A3130
* 004EEAAD 8BE8 MOV EBP,EAX
* 004EEAAF 33DB XOR EBX,EBX
* 004EEAB1 3BEB CMP EBP,EBX
* 004EEAB3 75 07 JNZ SHORT .004EEABC
* 004EEAB5 32C0 XOR AL,AL
* 004EEAB7 E9 92000000 JMP .004EEB4E
* 004EEABC 8B06 MOV EAX,DWORD PTR DS:[ESI]
* 004EEABE 8B10 MOV EDX,DWORD PTR DS:[EAX]
* 004EEAC0 8BCE MOV ECX,ESI
* 004EEAC2 FFD2 CALL EDX
* 004EEAC4 8BC8 MOV ECX,EAX
* 004EEAC6 C74424 28 0F0000>MOV DWORD PTR SS:[ESP+0x28],0xF
* 004EEACE 895C24 24 MOV DWORD PTR SS:[ESP+0x24],EBX
* 004EEAD2 885C24 14 MOV BYTE PTR SS:[ESP+0x14],BL
* 004EEAD6 8D71 01 LEA ESI,DWORD PTR DS:[ECX+0x1]
* 004EEAD9 8DA424 00000000 LEA ESP,DWORD PTR SS:[ESP]
* 004EEAE0 8A11 MOV DL,BYTE PTR DS:[ECX]
* 004EEAE2 41 INC ECX
* 004EEAE3 3AD3 CMP DL,BL
* 004EEAE5 ^75 F9 JNZ SHORT .004EEAE0
* 004EEAE7 2BCE SUB ECX,ESI
* 004EEAE9 50 PUSH EAX
* 004EEAEA 8BF9 MOV EDI,ECX
* 004EEAEC 8D7424 18 LEA ESI,DWORD PTR SS:[ESP+0x18]
* 004EEAF0 E8 CB27F1FF CALL .004012C0
* 004EEAF5 8B7C24 48 MOV EDI,DWORD PTR SS:[ESP+0x48]
* 004EEAF9 895C24 3C MOV DWORD PTR SS:[ESP+0x3C],EBX
* 004EEAFD 8B75 3C MOV ESI,DWORD PTR SS:[EBP+0x3C]
* 004EEB00 E8 1B4A0100 CALL .00503520
* 004EEB05 8BF8 MOV EDI,EAX
* 004EEB07 8DB7 E4000000 LEA ESI,DWORD PTR DS:[EDI+0xE4]
* 004EEB0D 8D4424 14 LEA EAX,DWORD PTR SS:[ESP+0x14]
* 004EEB11 8BD6 MOV EDX,ESI
* 004EEB13 E8 985CF1FF CALL .004047B0
* 004EEB18 BD 10000000 MOV EBP,0x10
* 004EEB1D 84C0 TEST AL,AL
* 004EEB1F 75 18 JNZ SHORT .004EEB39
* 004EEB21 895E 10 MOV DWORD PTR DS:[ESI+0x10],EBX
* 004EEB24 396E 14 CMP DWORD PTR DS:[ESI+0x14],EBP
* 004EEB27 72 02 JB SHORT .004EEB2B
* 004EEB29 8B36 MOV ESI,DWORD PTR DS:[ESI]
* 004EEB2B 8D4424 14 LEA EAX,DWORD PTR SS:[ESP+0x14]
* 004EEB2F 50 PUSH EAX
* 004EEB30 8BCF MOV ECX,EDI
* 004EEB32 881E MOV BYTE PTR DS:[ESI],BL
* 004EEB34 E9 13B62100 JMP .0070A14C ; jichi: here hookpoint#2, name is modified here, scenario and names are here accessed char by char on the top of the stack
* 004EEB39 396C24 28 CMP DWORD PTR SS:[ESP+0x28],EBP
* 004EEB3D 72 0D JB SHORT .004EEB4C
* 004EEB3F 8B4C24 14 MOV ECX,DWORD PTR SS:[ESP+0x14]
* 004EEB43 51 PUSH ECX
* 004EEB44 E8 42DC1900 CALL .0068C78B
* 004EEB49 83C4 04 ADD ESP,0x4
* 004EEB4C B0 01 MOV AL,0x1
* 004EEB4E 8B4C24 34 MOV ECX,DWORD PTR SS:[ESP+0x34]
* 004EEB52 64:890D 00000000 MOV DWORD PTR FS:[0],ECX
* 004EEB59 59 POP ECX
* 004EEB5A 5F POP EDI
* 004EEB5B 5E POP ESI
* 004EEB5C 5D POP EBP
* 004EEB5D 5B POP EBX
* 004EEB5E 8B4C24 1C MOV ECX,DWORD PTR SS:[ESP+0x1C]
* 004EEB62 33CC XOR ECX,ESP
* 004EEB64 E8 9CD61900 CALL .0068C205
* 004EEB69 83C4 2C ADD ESP,0x2C
* 004EEB6C C3 RETN
* 004EEB6D CC INT3
* 004EEB6E CC INT3
*
* 005C70EE CC INT3
* 005C70EF CC INT3
* 005C70F0 83EC 18 SUB ESP,0x18
* 005C70F3 A1 DCC47700 MOV EAX,DWORD PTR DS:[0x77C4DC]
* 005C70F8 33C4 XOR EAX,ESP
* 005C70FA 894424 14 MOV DWORD PTR SS:[ESP+0x14],EAX
* 005C70FE 53 PUSH EBX
* 005C70FF 8B5C24 20 MOV EBX,DWORD PTR SS:[ESP+0x20]
* 005C7103 55 PUSH EBP
* 005C7104 8B6C24 2C MOV EBP,DWORD PTR SS:[ESP+0x2C]
* 005C7108 8B45 1C MOV EAX,DWORD PTR SS:[EBP+0x1C]
* 005C710B 56 PUSH ESI
* 005C710C 8BF2 MOV ESI,EDX
* 005C710E 57 PUSH EDI
* 005C710F 8BF9 MOV EDI,ECX
* 005C7111 897424 10 MOV DWORD PTR SS:[ESP+0x10],ESI
* 005C7115 83F8 44 CMP EAX,0x44
* 005C7118 77 7A JA SHORT .005C7194
* 005C711A 0FB680 7C735C00 MOVZX EAX,BYTE PTR DS:[EAX+0x5C737C]
* 005C7121 FF2485 60735C00 JMP DWORD PTR DS:[EAX*4+0x5C7360]
* 005C7128 8B4B 0C MOV ECX,DWORD PTR DS:[EBX+0xC]
* 005C712B 8B4424 30 MOV EAX,DWORD PTR SS:[ESP+0x30]
* 005C712F C1E9 02 SHR ECX,0x2
* 005C7132 3BC1 CMP EAX,ECX
* 005C7134 73 5E JNB SHORT .005C7194
* 005C7136 837B 0C 00 CMP DWORD PTR DS:[EBX+0xC],0x0
* 005C713A 75 1C JNZ SHORT .005C7158
* 005C713C 33DB XOR EBX,EBX
* 005C713E 5F POP EDI
* 005C713F 893483 MOV DWORD PTR DS:[EBX+EAX*4],ESI
* 005C7142 5E POP ESI
* 005C7143 5D POP EBP
* 005C7144 B0 01 MOV AL,0x1
* 005C7146 5B POP EBX
* 005C7147 8B4C24 14 MOV ECX,DWORD PTR SS:[ESP+0x14]
* 005C714B 33CC XOR ECX,ESP
* 005C714D E8 B3500C00 CALL .0068C205
* 005C7152 83C4 18 ADD ESP,0x18
* 005C7155 C2 0C00 RETN 0xC
* 005C7158 8B5B 08 MOV EBX,DWORD PTR DS:[EBX+0x8]
* 005C715B 5F POP EDI
* 005C715C 893483 MOV DWORD PTR DS:[EBX+EAX*4],ESI
* 005C715F 5E POP ESI
* 005C7160 5D POP EBP
* 005C7161 B0 01 MOV AL,0x1
* 005C7163 5B POP EBX
* 005C7164 8B4C24 14 MOV ECX,DWORD PTR SS:[ESP+0x14]
* 005C7168 33CC XOR ECX,ESP
* 005C716A E8 96500C00 CALL .0068C205
* 005C716F 83C4 18 ADD ESP,0x18
* 005C7172 C2 0C00 RETN 0xC
* 005C7175 F3:0F104424 10 MOVSS XMM0,DWORD PTR SS:[ESP+0x10]
* 005C717B 51 PUSH ECX
* 005C717C 8B4C24 34 MOV ECX,DWORD PTR SS:[ESP+0x34]
* 005C7180 8BC3 MOV EAX,EBX
* 005C7182 F3:0F110424 MOVSS DWORD PTR SS:[ESP],XMM0
* 005C7187 E8 14C7FFFF CALL .005C38A0
* 005C718C 84C0 TEST AL,AL
* 005C718E 0F85 B2010000 JNZ .005C7346
* 005C7194 5F POP EDI
* 005C7195 5E POP ESI
* 005C7196 5D POP EBP
* 005C7197 32C0 XOR AL,AL
* 005C7199 5B POP EBX
* 005C719A 8B4C24 14 MOV ECX,DWORD PTR SS:[ESP+0x14]
* 005C719E 33CC XOR ECX,ESP
* 005C71A0 E8 60500C00 CALL .0068C205
* 005C71A5 83C4 18 ADD ESP,0x18
* 005C71A8 C2 0C00 RETN 0xC
* 005C71AB 8B4C24 30 MOV ECX,DWORD PTR SS:[ESP+0x30]
* 005C71AF 8D5424 10 LEA EDX,DWORD PTR SS:[ESP+0x10]
* 005C71B3 52 PUSH EDX
* 005C71B4 8BC3 MOV EAX,EBX
* 005C71B6 E8 25C7FFFF CALL .005C38E0
* 005C71BB 84C0 TEST AL,AL
* 005C71BD ^74 D5 JE SHORT .005C7194
* 005C71BF 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+0x10]
* 005C71C3 8BC7 MOV EAX,EDI
* 005C71C5 E8 D6F0FFFF CALL .005C62A0
* 005C71CA 8BD8 MOV EBX,EAX
* 005C71CC 8BCE MOV ECX,ESI
* 005C71CE 8BC7 MOV EAX,EDI
* 005C71D0 E8 CBF0FFFF CALL .005C62A0
* 005C71D5 85DB TEST EBX,EBX
* 005C71D7 ^74 BB JE SHORT .005C7194
* 005C71D9 85C0 TEST EAX,EAX
* 005C71DB ^74 B7 JE SHORT .005C7194
* 005C71DD 50 PUSH EAX
* 005C71DE 8BC3 MOV EAX,EBX
* 005C71E0 E8 2BCFFFFF CALL .005C4110 ; original function call
* //005C71E0 E9 482F1400 JMP .0070A12D ; jichi: here hookpoint#3, text is modified here, text in [[esp]+0x8]], length in [esp]+0xc
* 005C71E5 ^EB A5 JMP SHORT .005C718C
* 005C71E7 8B47 08 MOV EAX,DWORD PTR DS:[EDI+0x8]
* 005C71EA 8B4F 0C MOV ECX,DWORD PTR DS:[EDI+0xC]
* 005C71ED 2BC8 SUB ECX,EAX
* 005C71EF C1F9 02 SAR ECX,0x2
* 005C71F2 3BF1 CMP ESI,ECX
* 005C71F4 ^73 9E JNB SHORT .005C7194
* 005C71F6 8B34B0 MOV ESI,DWORD PTR DS:[EAX+ESI*4]
* 005C71F9 85F6 TEST ESI,ESI
* 005C71FB ^74 97 JE SHORT .005C7194
*
* 005B640E CC INT3
* 005B640F CC INT3
* 005B6410 53 PUSH EBX
* 005B6411 56 PUSH ESI
* 005B6412 B9 FCFFFFFF MOV ECX,-0x4
* 005B6417 57 PUSH EDI
* 005B6418 8BF8 MOV EDI,EAX
* 005B641A 018F B0020000 ADD DWORD PTR DS:[EDI+0x2B0],ECX
* 005B6420 8B87 B0020000 MOV EAX,DWORD PTR DS:[EDI+0x2B0]
* 005B6426 8B30 MOV ESI,DWORD PTR DS:[EAX]
* 005B6428 018F B0020000 ADD DWORD PTR DS:[EDI+0x2B0],ECX
* 005B642E 8B87 B0020000 MOV EAX,DWORD PTR DS:[EDI+0x2B0]
* 005B6434 8B08 MOV ECX,DWORD PTR DS:[EAX]
* 005B6436 8B87 E0010000 MOV EAX,DWORD PTR DS:[EDI+0x1E0]
* 005B643C 2B87 DC010000 SUB EAX,DWORD PTR DS:[EDI+0x1DC]
* 005B6442 C1F8 02 SAR EAX,0x2
* 005B6445 3BF0 CMP ESI,EAX
* 005B6447 73 0D JNB SHORT .005B6456
* 005B6449 8B87 DC010000 MOV EAX,DWORD PTR DS:[EDI+0x1DC]
* 005B644F 8B14B0 MOV EDX,DWORD PTR DS:[EAX+ESI*4]
* 005B6452 85D2 TEST EDX,EDX
* 005B6454 75 13 JNZ SHORT .005B6469
* 005B6456 68 70757200 PUSH .00727570
* 005B645B 8BCF MOV ECX,EDI
* 005B645D E8 AEC9FFFF CALL .005B2E10
* 005B6462 83C4 04 ADD ESP,0x4
* 005B6465 5F POP EDI
* 005B6466 5E POP ESI
* 005B6467 5B POP EBX
* 005B6468 C3 RETN
* 005B6469 8B9F E0010000 MOV EBX,DWORD PTR DS:[EDI+0x1E0]
* 005B646F 2BD8 SUB EBX,EAX
* 005B6471 C1FB 02 SAR EBX,0x2
* 005B6474 3BCB CMP ECX,EBX
* 005B6476 73 07 JNB SHORT .005B647F
* 005B6478 8B0488 MOV EAX,DWORD PTR DS:[EAX+ECX*4]
* 005B647B 85C0 TEST EAX,EAX
* 005B647D 75 14 JNZ SHORT .005B6493
* 005B647F 51 PUSH ECX
* 005B6480 68 A0757200 PUSH .007275A0
* 005B6485 8BCF MOV ECX,EDI
* 005B6487 E8 84C9FFFF CALL .005B2E10
* 005B648C 83C4 08 ADD ESP,0x8
* 005B648F 5F POP EDI
* 005B6490 5E POP ESI
* 005B6491 5B POP EBX
* 005B6492 C3 RETN
* 005B6493 52 PUSH EDX
* 005B6494 E8 77DC0000 CALL .005C4110
* //005B6494 E9 103D1500 JMP .0070A1A9 ; jichi: here hookpoint#4
* 005B6499 84C0 TEST AL,AL
* 005B649B 75 16 JNZ SHORT .005B64B3
* 005B649D 68 D4757200 PUSH .007275D4
* 005B64A2 B9 F0757200 MOV ECX,.007275F0 ; ASCII "S_ASSIGN"
* 005B64A7 E8 84C8FFFF CALL .005B2D30
* 005B64AC 83C4 04 ADD ESP,0x4
* 005B64AF 5F POP EDI
* 005B64B0 5E POP ESI
* 005B64B1 5B POP EBX
* 005B64B2 C3 RETN
* 005B64B3 8B8F B0020000 MOV ECX,DWORD PTR DS:[EDI+0x2B0]
* 005B64B9 8931 MOV DWORD PTR DS:[ECX],ESI
* 005B64BB 8387 B0020000 04 ADD DWORD PTR DS:[EDI+0x2B0],0x4
* 005B64C2 5F POP EDI
* 005B64C3 5E POP ESI
* 005B64C4 5B POP EBX
* 005B64C5 C3 RETN
* 005B64C6 CC INT3
* 005B64C7 CC INT3
* 005B64C8 CC INT3
*
* Slightly modified #4 in AliceRunPatch.dll
* 101B6C10 5B POP EBX
* 101B6C11 59 POP ECX
* 101B6C12 C3 RETN
* 101B6C13 52 PUSH EDX
* 101B6C14 8BC1 MOV EAX,ECX
* 101B6C16 E9 4E7D1600 JMP .1031E969 ; jichi: hook here
* 101B6C1B 84C0 TEST AL,AL
* 101B6C1D 75 18 JNZ SHORT .101B6C37
* 101B6C1F 68 FCB53310 PUSH .1033B5FC
* 101B6C24 B9 18B63310 MOV ECX,.1033B618 ; ASCII "S_ASSIGN"
* 101B6C29 E8 92B8FFFF CALL .101B24C0
* 101B6C2E 83C4 04 ADD ESP,0x4
* 101B6C31 5F POP EDI
* 101B6C32 5E POP ESI
* 101B6C33 5D POP EBP
* 101B6C34 5B POP EBX
* 101B6C35 59 POP ECX
* 101B6C36 C3 RETN
* 101B6C37 53 PUSH EBX
* 101B6C38 56 PUSH ESI
* 101B6C39 E8 E29C0100 CALL .101D0920
* 101B6C3E 5F POP EDI
* 101B6C3F 5E POP ESI
* 101B6C40 5D POP EBP
* 101B6C41 5B POP EBX
* 101B6C42 59 POP ECX
* 101B6C43 C3 RETN
* 101B6C44 CC INT3
* 101B6C45 CC INT3
* 101B6C46 CC INT3
*
* The function get called to paint string of names for hookpoint #2, text in arg1:
* 0050B69E CC INT3
* 0050B69F CC INT3
* 0050B6A0 55 PUSH EBP
* 0050B6A1 8BEC MOV EBP,ESP
* 0050B6A3 83E4 F8 AND ESP,0xFFFFFFF8
* 0050B6A6 6A FF PUSH -0x1
* 0050B6A8 68 F8277000 PUSH .007027F8
* 0050B6AD 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
* 0050B6B3 50 PUSH EAX
* 0050B6B4 83EC 18 SUB ESP,0x18
* 0050B6B7 53 PUSH EBX
* 0050B6B8 56 PUSH ESI
* 0050B6B9 57 PUSH EDI
* 0050B6BA A1 DCC47700 MOV EAX,DWORD PTR DS:[0x77C4DC]
* 0050B6BF 33C4 XOR EAX,ESP
* 0050B6C1 50 PUSH EAX
* 0050B6C2 8D4424 28 LEA EAX,DWORD PTR SS:[ESP+0x28]
* 0050B6C6 64:A3 00000000 MOV DWORD PTR FS:[0],EAX
* 0050B6CC 8BF9 MOV EDI,ECX
* 0050B6CE 57 PUSH EDI
* 0050B6CF E8 5CEAFFFF CALL .0050A130
* 0050B6D4 8B45 08 MOV EAX,DWORD PTR SS:[EBP+0x8]
* 0050B6D7 6A FF PUSH -0x1
* 0050B6D9 33DB XOR EBX,EBX
* 0050B6DB 53 PUSH EBX
* 0050B6DC 8DB7 E4000000 LEA ESI,DWORD PTR DS:[EDI+0xE4]
* 0050B6E2 50 PUSH EAX
* 0050B6E3 E8 886BEFFF CALL .00402270
* 0050B6E8 895C24 14 MOV DWORD PTR SS:[ESP+0x14],EBX
* 0050B6EC 895C24 18 MOV DWORD PTR SS:[ESP+0x18],EBX
* 0050B6F0 895C24 1C MOV DWORD PTR SS:[ESP+0x1C],EBX
* 0050B6F4 56 PUSH ESI
* 0050B6F5 8D4C24 18 LEA ECX,DWORD PTR SS:[ESP+0x18]
* 0050B6F9 51 PUSH ECX
* 0050B6FA 57 PUSH EDI
* 0050B6FB 895C24 3C MOV DWORD PTR SS:[ESP+0x3C],EBX
* 0050B6FF E8 6C290000 CALL .0050E070
* 0050B704 8D5424 14 LEA EDX,DWORD PTR SS:[ESP+0x14]
* 0050B708 8BCF MOV ECX,EDI
* 0050B70A E8 B1010000 CALL .0050B8C0
* 0050B70F 8B7424 14 MOV ESI,DWORD PTR SS:[ESP+0x14]
* 0050B713 C687 E0000000 01 MOV BYTE PTR DS:[EDI+0xE0],0x1
* 0050B71A 3BF3 CMP ESI,EBX
* 0050B71C 74 14 JE SHORT .0050B732
* 0050B71E 8B7C24 18 MOV EDI,DWORD PTR SS:[ESP+0x18]
* 0050B722 8BC6 MOV EAX,ESI
* 0050B724 E8 7751F0FF CALL .004108A0
* 0050B729 56 PUSH ESI
* 0050B72A E8 5C101800 CALL .0068C78B
* 0050B72F 83C4 04 ADD ESP,0x4
* 0050B732 8B4C24 28 MOV ECX,DWORD PTR SS:[ESP+0x28]
* 0050B736 64:890D 00000000 MOV DWORD PTR FS:[0],ECX
* 0050B73D 59 POP ECX
* 0050B73E 5F POP EDI
* 0050B73F 5E POP ESI
* 0050B740 5B POP EBX
* 0050B741 8BE5 MOV ESP,EBP
* 0050B743 5D POP EBP
* 0050B744 C2 0400 RETN 0x4
* 0050B747 CC INT3
* 0050B748 CC INT3
* 0050B749 CC INT3
* 0050B74A CC INT3
* 0050B74B CC INT3
* 0050B74C CC INT3
*
* Function get called for hookpoint #3, text in [arg1+0x10], length in arg1+0xc, only for scenario, function call is looped
* 005C410D CC INT3
* 005C410E CC INT3
* 005C410F CC INT3
* 005C4110 53 PUSH EBX
* 005C4111 8B5C24 08 MOV EBX,DWORD PTR SS:[ESP+0x8]
* 005C4115 837B 0C 00 CMP DWORD PTR DS:[EBX+0xC],0x0
* 005C4119 56 PUSH ESI
* 005C411A 57 PUSH EDI
* 005C411B 8BF0 MOV ESI,EAX
* 005C411D 74 07 JE SHORT .005C4126
* 005C411F 8B43 08 MOV EAX,DWORD PTR DS:[EBX+0x8]
* 005C4122 85C0 TEST EAX,EAX
* 005C4124 75 04 JNZ SHORT .005C412A
* 005C4126 33C0 XOR EAX,EAX
* 005C4128 EB 0F JMP SHORT .005C4139
* 005C412A 8D50 01 LEA EDX,DWORD PTR DS:[EAX+0x1]
* 005C412D 8D49 00 LEA ECX,DWORD PTR DS:[ECX]
* 005C4130 8A08 MOV CL,BYTE PTR DS:[EAX]
* 005C4132 40 INC EAX
* 005C4133 84C9 TEST CL,CL
* 005C4135 ^75 F9 JNZ SHORT .005C4130
* 005C4137 2BC2 SUB EAX,EDX
* 005C4139 8D78 01 LEA EDI,DWORD PTR DS:[EAX+0x1]
* 005C413C 3B7E 0C CMP EDI,DWORD PTR DS:[ESI+0xC]
* 005C413F 76 0F JBE SHORT .005C4150
* 005C4141 E8 FAF7FFFF CALL .005C3940
* 005C4146 84C0 TEST AL,AL
* 005C4148 75 06 JNZ SHORT .005C4150
* 005C414A 5F POP EDI
* 005C414B 5E POP ESI
* 005C414C 5B POP EBX
* 005C414D C2 0400 RETN 0x4
* 005C4150 837B 0C 00 CMP DWORD PTR DS:[EBX+0xC],0x0
* 005C4154 75 04 JNZ SHORT .005C415A
* 005C4156 33C9 XOR ECX,ECX
* 005C4158 EB 03 JMP SHORT .005C415D
* 005C415A 8B4B 08 MOV ECX,DWORD PTR DS:[EBX+0x8]
* 005C415D 837E 0C 00 CMP DWORD PTR DS:[ESI+0xC],0x0
* 005C4161 75 15 JNZ SHORT .005C4178
* 005C4163 57 PUSH EDI
* 005C4164 33C0 XOR EAX,EAX
* 005C4166 51 PUSH ECX
* 005C4167 50 PUSH EAX
* 005C4168 E8 33400D00 CALL .006981A0
* 005C416D 83C4 0C ADD ESP,0xC
* 005C4170 5F POP EDI
* 005C4171 5E POP ESI
* 005C4172 B0 01 MOV AL,0x1
* 005C4174 5B POP EBX
* 005C4175 C2 0400 RETN 0x4
* 005C4178 8B46 08 MOV EAX,DWORD PTR DS:[ESI+0x8]
* 005C417B 57 PUSH EDI
* 005C417C 51 PUSH ECX
* 005C417D 50 PUSH EAX
* 005C417E E8 1D400D00 CALL .006981A0
* 005C4183 83C4 0C ADD ESP,0xC
* 005C4186 5F POP EDI
* 005C4187 5E POP ESI
* 005C4188 B0 01 MOV AL,0x1
* 005C418A 5B POP EBX
* 005C418B C2 0400 RETN 0x4
* 005C418E CC INT3
*/
static bool InsertSystem43NewHook(ULONG startAddress, ULONG stopAddress, LPCSTR hookName)
{
const BYTE bytes[] = {
0xe8, XX4, // 004eeb34 e8 67cb0100 call .0050b6a0 ; jichi: hook here, text on the top of the stack
0x39,0x6c,0x24, 0x28, // 004eeb39 396c24 28 cmp dword ptr ss:[esp+0x28],ebp
0x72, 0x0d, // 004eeb3d 72 0d jb short .004eeb4c
0x8b,0x4c,0x24, 0x14, // 004eeb3f 8b4c24 14 mov ecx,dword ptr ss:[esp+0x14]
0x51, // 004eeb43 51 push ecx
0xe8 //, XX4, // 004eeb44 e8 42dc1900 call .0068c78b
};
enum { addr_offset = 0 };
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
//GROWL_DWORD(addr);
if (!addr) {
ConsoleOutput("System43+: pattern not found");
return false;
}
//addr = *(DWORD *)(addr+1) + addr + 5; // change to hook to the actual address of function being called
HookParam hp;
hp.address = addr;
hp.type = NO_CONTEXT|USING_STRING|USING_SPLIT|SPLIT_INDIRECT;
//hp.type = NO_CONTEXT|USING_STRING|FIXING_SPLIT;
hp.split_index = 0x10; // use [[esp]+0x10] to differentiate name and thread
// Only name can be modified here, where the value of split is 0x6, and text in 0x2
ConsoleOutput("INSERT System43+");
ConsoleOutput("System43+: disable GDI hooks"); // disable hooking to TextOutA, which is cached
return NewHook(hp, hookName);
}
bool System43New2Filter(LPVOID data, size_t *size, HookParam *)
{
auto text = reinterpret_cast<LPSTR>(data);
auto len = reinterpret_cast<size_t *>(size);
CharReplacer(text, len, '\n', ' ');
if (cpp_strnstr(text, "${", *len)) {
StringFilterBetween(text, len, "${", 3, "}", 1);
}
return true;
}
bool InsertSystem43New2Hook()
{
/*
* Sample games:
* https://vndb.org/r84067
*/
const BYTE bytes[] = {
0xC7, 0x46, 0x10, XX4, // mov [esi+10],00000000
0x72, 0x02, // jb dohnadohna.exe+1BFA7E
0x8B, 0x36, // mov esi,[esi]
0x8B, 0x4C, 0x24, 0x14, // mov ecx,[esp+14]
0x57, // push edi
0xC6, 0x06, 0x00 // mov byte ptr [esi],00 << hook here
};
enum { addr_offset = sizeof(bytes) - 3 };
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
if (!addr) {
ConsoleOutput("System43new: pattern not found");
return false;
}
HookParam hp;
hp.address = addr + addr_offset;
hp.offset=get_reg(regs::edx);
hp.split = get_reg(regs::esp);
hp.type = NO_CONTEXT | USING_STRING | USING_SPLIT;
hp.filter_fun = System43New2Filter;
ConsoleOutput("INSERT System43new");
return NewHook(hp, "System43new");
}
bool InsertSystem43Hook()
{
if (InsertSystem43New2Hook())
return true;
//bool patched = Util::CheckFile(L"AliceRunPatch.dll");
bool patched = ::GetModuleHandleA("AliceRunPatch.dll");
// Insert new hook first
bool ok = InsertSystem43OldHook(processStartAddress, processStopAddress, patched ? "AliceRunPatch43" : "System43");
ok = InsertSystem43NewHook(processStartAddress, processStopAddress, "System43+") || ok;
return ok;
}
namespace { // unnamed
struct TextArgument // first argument of the scenario hook
{
ULONG *unknown[2];
LPCSTR text;
int size; // text data size including '\0', length = size - 1
int capacity;
ULONG split;
bool isValid() const
{
return size <= capacity && size >= 4 && text && ::strlen(text) + 1 == size // skip translating single text
//&& !Util::allAscii(text)
&& (UINT8)text[0] > 127 && (UINT8)text[size - 3] > 127 // skip text beginning / ending with ascii
&& !::strstr(text, "\x81\x5e"); // ""
}
};
enum : UINT64 { djb2_hash0 = 5381 };
inline UINT64 djb2(const UINT8 *str, UINT64 hash = djb2_hash0)
{
UINT8 c;
while ((c = *str++))
hash = ((hash << 5) + hash) + c; // hash * 33 + c
return hash;
}inline UINT64 djb2_n2(const char* str, size_t len, UINT64 hash = djb2_hash0)
{
while (len--)
hash = ((hash << 5) + hash) + (*str++); // hash * 33 + c
return hash;
}
inline UINT64 hashByteArraySTD(const std::string& b, UINT64 h = djb2_hash0)
{
return djb2_n2(b.c_str(), b.size(), h);
}
inline UINT64 hashCharArray(const void *lp)
{ return djb2(reinterpret_cast<const UINT8 *>(lp)); }
namespace ScenarioHook {
namespace Private {
bool isOtherText(LPCSTR text)
{
static const char *s[] = {
"\x82\xa2\x82\xa2\x82\xa6" /* いいえ */
, "\x82\xcd\x82\xa2" /* はい */
};
for (int i = 0; i < sizeof(s)/sizeof(*s); i++)
if (::strcmp(text, s[i]) == 0)
return true;
return false;
}
TextArgument *arg_,
argValue_;
/**
* Sample game: Rance03
*
* Caller that related to load/save, which is the only caller get kept:
* 005C68A7 8B86 74010000 MOV EAX,DWORD PTR DS:[ESI+0x174]
* 005C68AD 8B1CA8 MOV EBX,DWORD PTR DS:[EAX+EBP*4]
* 005C68B0 85DB TEST EBX,EBX
* 005C68B2 74 63 JE SHORT Rance03T.005C6917
* 005C68B4 8B86 78010000 MOV EAX,DWORD PTR DS:[ESI+0x178]
* 005C68BA 2B86 74010000 SUB EAX,DWORD PTR DS:[ESI+0x174]
* 005C68C0 C1F8 02 SAR EAX,0x2
* 005C68C3 3BD0 CMP EDX,EAX
* 005C68C5 73 3C JNB SHORT Rance03T.005C6903
* 005C68C7 8B86 74010000 MOV EAX,DWORD PTR DS:[ESI+0x174]
* 005C68CD 8B0C90 MOV ECX,DWORD PTR DS:[EAX+EDX*4]
* 005C68D0 85C9 TEST ECX,ECX
* 005C68D2 74 2F JE SHORT Rance03T.005C6903
* 005C68D4 53 PUSH EBX
* 005C68D5 -E9 26976B09 JMP 09C80000 ; jichi: called
* 005C68DA 84C0 TEST AL,AL
* 005C68DC 75 18 JNZ SHORT Rance03T.005C68F6
* 005C68DE 68 94726E00 PUSH Rance03T.006E7294
* 005C68E3 68 00736E00 PUSH Rance03T.006E7300 ; ASCII "S_ASSIGN"
* 005C68E8 56 PUSH ESI
* 005C68E9 E8 12BBFFFF CALL Rance03T.005C2400
* 005C68EE 83C4 0C ADD ESP,0xC
* 005C68F1 5F POP EDI
* 005C68F2 5E POP ESI
*
* Caller of the scenario thread:
*
* 005D6F80 ^74 BE JE SHORT Rance03T.005D6F40
* 005D6F82 85C0 TEST EAX,EAX
* 005D6F84 ^74 BA JE SHORT Rance03T.005D6F40
* 005D6F86 50 PUSH EAX
* 005D6F87 8BCF MOV ECX,EDI
* 005D6F89 -E9 72907009 JMP 09CE0000 ; jichi: called here
* 005D6F8E ^EB A8 JMP SHORT Rance03T.005D6F38
* 005D6F90 8B46 0C MOV EAX,DWORD PTR DS:[ESI+0xC]
* 005D6F93 2B46 08 SUB EAX,DWORD PTR DS:[ESI+0x8]
* 005D6F96 C1F8 02 SAR EAX,0x2
* 005D6F99 3BD8 CMP EBX,EAX
* 005D6F9B ^73 A3 JNB SHORT Rance03T.005D6F40
* 005D6F9D 8B46 08 MOV EAX,DWORD PTR DS:[ESI+0x8]
* 005D6FA0 8B1C98 MOV EBX,DWORD PTR DS:[EAX+EBX*4]
*/
std::unordered_set<uint64_t> hashes_;
void hookafter2(hook_stack*s,void* data, size_t len){
auto newData =std::string((char*)data,len);
static std::string data_;
data_ = newData;
auto arg = (TextArgument *)s->stack[0]; // arg1
arg_ = arg;
argValue_ = *arg;
arg->text = data_.c_str();
arg->size = data_.size() + 1;
arg->capacity = arg->size;
hashes_.insert(hashCharArray(arg->text));
}
bool hookBefore(hook_stack*s,void* data, size_t* len1,uintptr_t*role)
{
static std::string data_; // persistent storage, which makes this function not thread-safe
//auto split = s->stack[5]; // parent function return address
//auto split = s->stack[10]; // parent's parent function return address
//auto split = *(DWORD *)(s->ecx + 0x10);
auto split = *(DWORD *)(s->ecx + 0x34);
//auto split = *(DWORD *)(s->ecx + 0x48);
// 005C68DA 84C0 TEST AL,AL
//if (*(WORD *)retaddr == 0xc084) // otherwise system text will be translated
// return true;
//if (*(WORD *)retaddr != 0xc084) // only translate one caller
// return true;
// 005D6F8E ^EB A8 JMP SHORT Rance03T.005D6F38
//if (*(WORD *)retaddr != 0xa8eb) // this function has 7 callers, and only one is kept
// return true;
if (split > 0xff || split && split < 0xf)
return false;
auto arg = (TextArgument *)s->stack[0]; // arg1
if (!arg || !arg->isValid()
|| hashes_.find(hashCharArray(arg->text)) != hashes_.end())
return false;
if (arg->size < 0xf && split > 0 && !isOtherText(arg->text))
return false;
//auto sig = Engine::hashThreadSignature(role, split);
//auto role = Engine::OtherRole;
* role = Engine::OtherRole;
if (!isOtherText(arg->text)) {
if (split == 0 && arg->size <= 0x10)
*role = Engine::NameRole;
else if (split >= 2 && split <= 0x14 && split != 3 && split != 0xb || split == 0x22)
*role = Engine::ScenarioRole;
}
write_string_overwrite(data,len1,arg->text);
return true;
}
bool hookAfter(hook_stack*s,void* data, size_t* len1,uintptr_t*role)
{
if (arg_) {
*arg_ = argValue_;
arg_ = nullptr;
}
return false;
}
} // namespace Private
/**
* Sample game: Rance03
*
* Function that is similar to memcpy, found by debugging where game text get modified:
*
* 0069D84F CC INT3
* 0069D850 57 PUSH EDI
* 0069D851 56 PUSH ESI
* 0069D852 8B7424 10 MOV ESI,DWORD PTR SS:[ESP+0x10]
* 0069D856 8B4C24 14 MOV ECX,DWORD PTR SS:[ESP+0x14]
* 0069D85A 8B7C24 0C MOV EDI,DWORD PTR SS:[ESP+0xC]
* 0069D85E 8BC1 MOV EAX,ECX
* 0069D860 8BD1 MOV EDX,ECX
* 0069D862 03C6 ADD EAX,ESI
* 0069D864 3BFE CMP EDI,ESI
* 0069D866 76 08 JBE SHORT Rance03T.0069D870
* 0069D868 3BF8 CMP EDI,EAX
* 0069D86A 0F82 68030000 JB Rance03T.0069DBD8
* 0069D870 0FBA25 5CC97500 >BT DWORD PTR DS:[0x75C95C],0x1
* 0069D878 73 07 JNB SHORT Rance03T.0069D881
* 0069D87A F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
* 0069D87C E9 17030000 JMP Rance03T.0069DB98
* 0069D881 81F9 80000000 CMP ECX,0x80
* 0069D887 0F82 CE010000 JB Rance03T.0069DA5B
* 0069D88D 8BC7 MOV EAX,EDI
* 0069D88F 33C6 XOR EAX,ESI
* 0069D891 A9 0F000000 TEST EAX,0xF
* 0069D896 75 0E JNZ SHORT Rance03T.0069D8A6
* 0069D898 0FBA25 10A47400 >BT DWORD PTR DS:[0x74A410],0x1
* 0069D8A0 0F82 DA040000 JB Rance03T.0069DD80
* 0069D8A6 0FBA25 5CC97500 >BT DWORD PTR DS:[0x75C95C],0x0
* 0069D8AE 0F83 A7010000 JNB Rance03T.0069DA5B
* 0069D8B4 F7C7 03000000 TEST EDI,0x3
* 0069D8BA 0F85 B8010000 JNZ Rance03T.0069DA78
* 0069D8C0 F7C6 03000000 TEST ESI,0x3
* 0069D8C6 0F85 97010000 JNZ Rance03T.0069DA63
* 0069D8CC 0FBAE7 02 BT EDI,0x2
* 0069D8D0 73 0D JNB SHORT Rance03T.0069D8DF
* 0069D8D2 8B06 MOV EAX,DWORD PTR DS:[ESI]
* 0069D8D4 83E9 04 SUB ECX,0x4
* 0069D8D7 8D76 04 LEA ESI,DWORD PTR DS:[ESI+0x4]
* 0069D8DA 8907 MOV DWORD PTR DS:[EDI],EAX
* 0069D8DC 8D7F 04 LEA EDI,DWORD PTR DS:[EDI+0x4]
* 0069D8DF 0FBAE7 03 BT EDI,0x3
* 0069D8E3 73 11 JNB SHORT Rance03T.0069D8F6
* 0069D8E5 F3: PREFIX REP: ; Superfluous prefix
* 0069D8E6 0F7E0E MOVD DWORD PTR DS:[ESI],MM1
* 0069D8E9 83E9 08 SUB ECX,0x8
* 0069D8EC 8D76 08 LEA ESI,DWORD PTR DS:[ESI+0x8]
* 0069D8EF 66:0FD6 ??? ; Unknown command
* 0069D8F2 -0F8D 7F08F7C6 JGE C760E177
* 0069D8F8 07 POP ES ; Modification of segment register
* 0069D8F9 0000 ADD BYTE PTR DS:[EAX],AL
* 0069D8FB 007463 0F ADD BYTE PTR DS:[EBX+0xF],DH
* 0069D8FF BA E6030F83 MOV EDX,0x830F03E6
* 0069D904 B2 00 MOV DL,0x0
* 0069D906 0000 ADD BYTE PTR DS:[EAX],AL
* 0069D908 66:0F6F4E F4 MOVQ MM1,QWORD PTR DS:[ESI-0xC]
* 0069D90D 8D76 F4 LEA ESI,DWORD PTR DS:[ESI-0xC]
* 0069D910 66:0F6F5E 10 MOVQ MM3,QWORD PTR DS:[ESI+0x10]
* 0069D915 83E9 30 SUB ECX,0x30
* 0069D918 66:0F6F46 20 MOVQ MM0,QWORD PTR DS:[ESI+0x20]
* 0069D91D 66:0F6F6E 30 MOVQ MM5,QWORD PTR DS:[ESI+0x30]
* 0069D922 8D76 30 LEA ESI,DWORD PTR DS:[ESI+0x30]
* 0069D925 83F9 30 CMP ECX,0x30
* 0069D928 66:0F6FD3 MOVQ MM2,MM3
* 0069D92C 66:0F3A ??? ; Unknown command
* 0069D92F 0FD90C66 PSUBUSW MM1,QWORD PTR DS:[ESI]
* 0069D933 0F7F1F MOVQ QWORD PTR DS:[EDI],MM3
* 0069D936 66:0F6FE0 MOVQ MM4,MM0
* 0069D93A 66:0F3A ??? ; Unknown command
* 0069D93D 0FC20C66 0F CMPPS XMM1,DQWORD PTR DS:[ESI],0xF
* 0069D942 7F 47 JG SHORT Rance03T.0069D98B
* 0069D944 1066 0F ADC BYTE PTR DS:[ESI+0xF],AH
* 0069D947 6F OUTS DX,DWORD PTR ES:[EDI] ; I/O command
* 0069D948 CD 66 INT 0x66
* 0069D94A 0F3A ??? ; Unknown command
* 0069D94C 0FEC0C66 PADDSB MM1,QWORD PTR DS:[ESI]
* 0069D950 0F7F6F 20 MOVQ QWORD PTR DS:[EDI+0x20],MM5
* 0069D954 8D7F 30 LEA EDI,DWORD PTR DS:[EDI+0x30]
* 0069D957 ^7D B7 JGE SHORT Rance03T.0069D910
* 0069D959 8D76 0C LEA ESI,DWORD PTR DS:[ESI+0xC]
* 0069D95C E9 AF000000 JMP Rance03T.0069DA10
* 0069D961 66:0F6F4E F8 MOVQ MM1,QWORD PTR DS:[ESI-0x8]
* 0069D966 8D76 F8 LEA ESI,DWORD PTR DS:[ESI-0x8]
* 0069D969 8D49 00 LEA ECX,DWORD PTR DS:[ECX]
* 0069D96C 66:0F6F5E 10 MOVQ MM3,QWORD PTR DS:[ESI+0x10]
* 0069D971 83E9 30 SUB ECX,0x30
* 0069D974 66:0F6F46 20 MOVQ MM0,QWORD PTR DS:[ESI+0x20]
* 0069D979 66:0F6F6E 30 MOVQ MM5,QWORD PTR DS:[ESI+0x30]
* 0069D97E 8D76 30 LEA ESI,DWORD PTR DS:[ESI+0x30]
* 0069D981 83F9 30 CMP ECX,0x30
* 0069D984 66:0F6FD3 MOVQ MM2,MM3
* 0069D988 66:0F3A ??? ; Unknown command
* 0069D98B 0FD908 PSUBUSW MM1,QWORD PTR DS:[EAX]
* 0069D98E 66:0F7F1F MOVQ QWORD PTR DS:[EDI],MM3
* 0069D992 66:0F6FE0 MOVQ MM4,MM0
* 0069D996 66:0F3A ??? ; Unknown command
* 0069D999 0FC208 66 CMPPS XMM1,DQWORD PTR DS:[EAX],0x66
* 0069D99D 0F7F47 10 MOVQ QWORD PTR DS:[EDI+0x10],MM0
* 0069D9A1 66:0F6FCD MOVQ MM1,MM5
* 0069D9A5 66:0F3A ??? ; Unknown command
* 0069D9A8 0FEC08 PADDSB MM1,QWORD PTR DS:[EAX]
* 0069D9AB 66:0F7F6F 20 MOVQ QWORD PTR DS:[EDI+0x20],MM5
* 0069D9B0 8D7F 30 LEA EDI,DWORD PTR DS:[EDI+0x30]
* 0069D9B3 ^7D B7 JGE SHORT Rance03T.0069D96C
* 0069D9B5 8D76 08 LEA ESI,DWORD PTR DS:[ESI+0x8]
* 0069D9B8 EB 56 JMP SHORT Rance03T.0069DA10
* 0069D9BA 66:0F6F4E FC MOVQ MM1,QWORD PTR DS:[ESI-0x4]
* 0069D9BF 8D76 FC LEA ESI,DWORD PTR DS:[ESI-0x4]
* 0069D9C2 8BFF MOV EDI,EDI
* 0069D9C4 66:0F6F5E 10 MOVQ MM3,QWORD PTR DS:[ESI+0x10]
* 0069D9C9 83E9 30 SUB ECX,0x30
* 0069D9CC 66:0F6F46 20 MOVQ MM0,QWORD PTR DS:[ESI+0x20]
* 0069D9D1 66:0F6F6E 30 MOVQ MM5,QWORD PTR DS:[ESI+0x30]
* 0069D9D6 8D76 30 LEA ESI,DWORD PTR DS:[ESI+0x30]
* 0069D9D9 83F9 30 CMP ECX,0x30
* 0069D9DC 66:0F6FD3 MOVQ MM2,MM3
* 0069D9E0 66:0F3A ??? ; Unknown command
* 0069D9E3 0FD90466 PSUBUSW MM0,QWORD PTR DS:[ESI]
* 0069D9E7 0F7F1F MOVQ QWORD PTR DS:[EDI],MM3
* 0069D9EA 66:0F6FE0 MOVQ MM4,MM0
* 0069D9EE 66:0F3A ??? ; Unknown command
* 0069D9F1 0FC20466 0F CMPPS XMM0,DQWORD PTR DS:[ESI],0xF
* 0069D9F6 7F 47 JG SHORT Rance03T.0069DA3F
* 0069D9F8 1066 0F ADC BYTE PTR DS:[ESI+0xF],AH
* 0069D9FB 6F OUTS DX,DWORD PTR ES:[EDI] ; I/O command
* 0069D9FC CD 66 INT 0x66
* 0069D9FE 0F3A ??? ; Unknown command
* 0069DA00 0FEC0466 PADDSB MM0,QWORD PTR DS:[ESI]
* 0069DA04 0F7F6F 20 MOVQ QWORD PTR DS:[EDI+0x20],MM5
* 0069DA08 8D7F 30 LEA EDI,DWORD PTR DS:[EDI+0x30]
* 0069DA0B ^7D B7 JGE SHORT Rance03T.0069D9C4
* 0069DA0D 8D76 04 LEA ESI,DWORD PTR DS:[ESI+0x4]
* 0069DA10 83F9 10 CMP ECX,0x10
* 0069DA13 7C 13 JL SHORT Rance03T.0069DA28
* 0069DA15 F3: PREFIX REP: ; Superfluous prefix
* 0069DA16 0F6F0E MOVQ MM1,QWORD PTR DS:[ESI]
* 0069DA19 83E9 10 SUB ECX,0x10
* 0069DA1C 8D76 10 LEA ESI,DWORD PTR DS:[ESI+0x10]
* 0069DA1F 66:0F7F0F MOVQ QWORD PTR DS:[EDI],MM1
* 0069DA23 8D7F 10 LEA EDI,DWORD PTR DS:[EDI+0x10]
* 0069DA26 ^EB E8 JMP SHORT Rance03T.0069DA10
* 0069DA28 0FBAE1 02 BT ECX,0x2
* 0069DA2C 73 0D JNB SHORT Rance03T.0069DA3B
* 0069DA2E 8B06 MOV EAX,DWORD PTR DS:[ESI]
* 0069DA30 83E9 04 SUB ECX,0x4
* 0069DA33 8D76 04 LEA ESI,DWORD PTR DS:[ESI+0x4]
* 0069DA36 8907 MOV DWORD PTR DS:[EDI],EAX
* 0069DA38 8D7F 04 LEA EDI,DWORD PTR DS:[EDI+0x4]
* 0069DA3B 0FBAE1 03 BT ECX,0x3
* 0069DA3F 73 11 JNB SHORT Rance03T.0069DA52
* 0069DA41 F3: PREFIX REP: ; Superfluous prefix
* 0069DA42 0F7E0E MOVD DWORD PTR DS:[ESI],MM1
* 0069DA45 83E9 08 SUB ECX,0x8
* 0069DA48 8D76 08 LEA ESI,DWORD PTR DS:[ESI+0x8]
* 0069DA4B 66:0FD6 ??? ; Unknown command
* 0069DA4E -0F8D 7F088B04 JGE 04F4E2D3
* 0069DA54 8D88 DB6900FF LEA ECX,DWORD PTR DS:[EAX+0xFF0069DB]
* 0069DA5A ^E0 F7 LOOPDNE SHORT Rance03T.0069DA53
* 0069DA5C C703 00000075 MOV DWORD PTR DS:[EBX],0x75000000
* 0069DA62 15 C1E90283 ADC EAX,0x8302E9C1
* 0069DA67 E2 03 LOOPD SHORT Rance03T.0069DA6C
* 0069DA69 83F9 08 CMP ECX,0x8
* 0069DA6C 72 2A JB SHORT Rance03T.0069DA98
* 0069DA6E F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI>
* 0069DA70 FF2495 88DB6900 JMP DWORD PTR DS:[EDX*4+0x69DB88]
* 0069DA77 90 NOP
*
* 0012F810 0B4D3F30
* 0012F814 06128970
* 0012F818 005D3E12 RETURN to Rance03T.005D3E12 from Rance03T.0069D850
* 0012F81C 06160B98 ; jichi: target text
* 0012F820 07F8CA80 ; jichi: source text
* 0012F824 00000017 ; jichi: size including \0
* 0012F828 00384460
* 0012F82C 00384240
* 0012F830 0B4D3F30
* 0012F834 005C68DA RETURN to Rance03T.005C68DA from Rance03T.005D3D90
* 0012F838 0B4D3F30
* 0012F83C 0012FAA8
* 0012F840 00384240
* 0012F844 0012F85C
* 0012F848 0012FF18
* 0012F84C 005C1693 RETURN to Rance03T.005C1693 from Rance03T.005C6870
* 0012F850 0012FAA8
* 0012F854 00384240
* 0012F858 0000000F
* 0012F85C /0012FF3C
*
* Actual hooked function:
* 005D3D8B CC INT3
* 005D3D8C CC INT3
* 005D3D8D CC INT3
* 005D3D8E CC INT3
* 005D3D8F CC INT3
* 005D3D90 53 PUSH EBX
* 005D3D91 56 PUSH ESI
* 005D3D92 8B7424 0C MOV ESI,DWORD PTR SS:[ESP+0xC]
* 005D3D96 57 PUSH EDI
* 005D3D97 8BF9 MOV EDI,ECX
* 005D3D99 837E 0C 00 CMP DWORD PTR DS:[ESI+0xC],0x0
* 005D3D9D 74 1C JE SHORT Rance03T.005D3DBB
* 005D3D9F 8B56 08 MOV EDX,DWORD PTR DS:[ESI+0x8]
* 005D3DA2 85D2 TEST EDX,EDX
* 005D3DA4 74 15 JE SHORT Rance03T.005D3DBB
* 005D3DA6 8D4A 01 LEA ECX,DWORD PTR DS:[EDX+0x1]
* 005D3DA9 8DA424 00000000 LEA ESP,DWORD PTR SS:[ESP]
* 005D3DB0 8A02 MOV AL,BYTE PTR DS:[EDX]
* 005D3DB2 42 INC EDX
* 005D3DB3 84C0 TEST AL,AL
* 005D3DB5 ^75 F9 JNZ SHORT Rance03T.005D3DB0
* 005D3DB7 2BD1 SUB EDX,ECX
* 005D3DB9 EB 02 JMP SHORT Rance03T.005D3DBD
* 005D3DBB 33D2 XOR EDX,EDX
* 005D3DBD 8D5A 01 LEA EBX,DWORD PTR DS:[EDX+0x1]
* 005D3DC0 3B5F 0C CMP EBX,DWORD PTR DS:[EDI+0xC]
* 005D3DC3 76 1A JBE SHORT Rance03T.005D3DDF
* 005D3DC5 53 PUSH EBX
* 005D3DC6 8D4F 04 LEA ECX,DWORD PTR DS:[EDI+0x4]
* 005D3DC9 C747 0C 00000000 MOV DWORD PTR DS:[EDI+0xC],0x0
* 005D3DD0 E8 DB700700 CALL Rance03T.0064AEB0
* 005D3DD5 84C0 TEST AL,AL
* 005D3DD7 75 06 JNZ SHORT Rance03T.005D3DDF
* 005D3DD9 5F POP EDI
* 005D3DDA 5E POP ESI
* 005D3DDB 5B POP EBX
* 005D3DDC C2 0400 RETN 0x4
* 005D3DDF 837E 0C 00 CMP DWORD PTR DS:[ESI+0xC],0x0
* 005D3DE3 75 04 JNZ SHORT Rance03T.005D3DE9
* 005D3DE5 33C9 XOR ECX,ECX
* 005D3DE7 EB 03 JMP SHORT Rance03T.005D3DEC
* 005D3DE9 8B4E 08 MOV ECX,DWORD PTR DS:[ESI+0x8]
* 005D3DEC 837F 0C 00 CMP DWORD PTR DS:[EDI+0xC],0x0
* 005D3DF0 75 15 JNZ SHORT Rance03T.005D3E07
* 005D3DF2 53 PUSH EBX
* 005D3DF3 33C0 XOR EAX,EAX
* 005D3DF5 51 PUSH ECX
* 005D3DF6 50 PUSH EAX
* 005D3DF7 E8 549A0C00 CALL Rance03T.0069D850
* 005D3DFC 83C4 0C ADD ESP,0xC
* 005D3DFF B0 01 MOV AL,0x1
* 005D3E01 5F POP EDI
* 005D3E02 5E POP ESI
* 005D3E03 5B POP EBX
* 005D3E04 C2 0400 RETN 0x4
* 005D3E07 8B47 08 MOV EAX,DWORD PTR DS:[EDI+0x8]
* 005D3E0A 53 PUSH EBX
* 005D3E0B 51 PUSH ECX
* 005D3E0C 50 PUSH EAX
* 005D3E0D -E9 EEC1A201 JMP 02000000 ; jichi: called here
* 005D3E12 83C4 0C ADD ESP,0xC
* 005D3E15 B0 01 MOV AL,0x1
* 005D3E17 5F POP EDI
* 005D3E18 5E POP ESI
* 005D3E19 5B POP EBX
* 005D3E1A C2 0400 RETN 0x4
* 005D3E1D CC INT3
* 005D3E1E CC INT3
* 005D3E1F CC INT3
*
* Arg1 of this function:
* 07B743F8 90 7A 70 00 F4 87 70 00 70 0E 27 08 1B 00 00 00 諏p.p.p'...
* 07B74408 20 00 00 00 02 00 00 00 01 00 00 00 CC 7F 2D 00 .........フ-.
* 07B74418 B3 52 41 00 FF FF FF FF EC 87 70 00 10 E3 1D 08 ウRA.・p.
*
* Caller that preserved:
* 005C68A7 8B86 74010000 MOV EAX,DWORD PTR DS:[ESI+0x174]
* 005C68AD 8B1CA8 MOV EBX,DWORD PTR DS:[EAX+EBP*4]
* 005C68B0 85DB TEST EBX,EBX
* 005C68B2 74 63 JE SHORT Rance03T.005C6917
* 005C68B4 8B86 78010000 MOV EAX,DWORD PTR DS:[ESI+0x178]
* 005C68BA 2B86 74010000 SUB EAX,DWORD PTR DS:[ESI+0x174]
* 005C68C0 C1F8 02 SAR EAX,0x2
* 005C68C3 3BD0 CMP EDX,EAX
* 005C68C5 73 3C JNB SHORT Rance03T.005C6903
* 005C68C7 8B86 74010000 MOV EAX,DWORD PTR DS:[ESI+0x174]
* 005C68CD 8B0C90 MOV ECX,DWORD PTR DS:[EAX+EDX*4]
* 005C68D0 85C9 TEST ECX,ECX
* 005C68D2 74 2F JE SHORT Rance03T.005C6903
* 005C68D4 53 PUSH EBX
* 005C68D5 E8 B6D40000 CALL Rance03T.005D3D90 ; jichi: called
* 005C68DA 84C0 TEST AL,AL ; jichi: retaddr
* 005C68DC 75 18 JNZ SHORT Rance03T.005C68F6
* 005C68DE 68 94726E00 PUSH Rance03T.006E7294
* 005C68E3 68 00736E00 PUSH Rance03T.006E7300 ; ASCII "S_ASSIGN"
* 005C68E8 56 PUSH ESI
* 005C68E9 E8 12BBFFFF CALL Rance03T.005C2400
* 005C68EE 83C4 0C ADD ESP,0xC
* 005C68F1 5F POP EDI
* 005C68F2 5E POP ESI
*/
bool attach(ULONG startAddress, ULONG stopAddress)
{
const uint8_t bytes[] = {
0x53, // 005D3D90 53 PUSH EBX
0x56, // 005D3D91 56 PUSH ESI
0x8B,0x74,0x24, 0x0C, // 005D3D92 8B7424 0C MOV ESI,DWORD PTR SS:[ESP+0xC]
0x57, // 005D3D96 57 PUSH EDI
0x8B,0xF9, // 005D3D97 8BF9 MOV EDI,ECX
0x83,0x7E, 0x0C, 0x00, // 005D3D99 837E 0C 00 CMP DWORD PTR DS:[ESI+0xC],0x0
0x74, 0x1C, // 005D3D9D 74 1C JE SHORT Rance03T.005D3DBB
0x8B,0x56, 0x08, // 005D3D9F 8B56 08 MOV EDX,DWORD PTR DS:[ESI+0x8]
0x85,0xD2, // 005D3DA2 85D2 TEST EDX,EDX
0x74, 0x15, // 005D3DA4 74 15 JE SHORT Rance03T.005D3DBB
0x8D,0x4A, 0x01, // 005D3DA6 8D4A 01 LEA ECX,DWORD PTR DS:[EDX+0x1]
0x8D,0xA4,0x24, 0x00,0x00,0x00,0x00, // 005D3DA9 8DA424 00000000 LEA ESP,DWORD PTR SS:[ESP]
0x8A,0x02, // 005D3DB0 8A02 MOV AL,BYTE PTR DS:[EDX]
0x42, // 005D3DB2 42 INC EDX
0x84,0xC0 // 005D3DB3 84C0 TEST AL,AL
};
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
if (!addr)
return false;
//addr = MemDbg::findEnclosingAlignedFunction(addr);
//if (!addr)
// return false;
//addr = 0x005D3D90;
//return winhook::hook_before(addr, Private::hookBefore);
int count = 0;
auto fun = [&count](ULONG addr) -> bool {
auto retaddr = addr + 5;
// 005C68DA 84C0 TEST AL,AL
if (*(WORD *)retaddr == 0xc084)
//auto before = std::bind(Private::hookBefore, addr + 5, std::placeholders::_1);
count +=1;
HookParam hp;
hp.address=addr;
hp.type=EMBED_ABLE|EMBED_DYNA_SJIS;
hp.hook_before=Private::hookBefore;
hp.hook_after=Private::hookafter2;
auto succ=NewHook(hp,"EmbedSysmtem44");
hp.address=addr+5;
hp.hook_before=Private::hookAfter;
succ|=NewHook(hp,"EmbedSysmtem44");
return succ; // replace all functions
};
MemDbg::iterNearCallAddress(fun, addr, startAddress, stopAddress);
return count;
}
} // namespace ScenarioHook
} // unnamed namespace
bool attachSystem44(ULONG startAddress, ULONG stopAddress)
{ return ScenarioHook::attach(startAddress, stopAddress); }
namespace { // unnamed
// - Search -
ULONG searchScenarioAddress(ULONG startAddress, ULONG stopAddress)
{
const uint8_t bytes[] = {
0xe8, XX4, // 005c71e0 e8 2bcfffff call .005c4110 ; original function call
0xeb, 0xa5, // 005c71e5 ^eb a5 jmp short .005c718c
0x8b,0x47, 0x08, // 005c71e7 8b47 08 mov eax,dword ptr ds:[edi+0x8]
0x8b,0x4f, 0x0c // 005c71ea 8b4f 0c mov ecx,dword ptr ds:[edi+0xc]
};
return MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
}
ULONG searchNameAddress(ULONG startAddress, ULONG stopAddress)
{
const uint8_t bytes[] = {
0xe8, XX4, // 004eeb34 e8 67cb0100 call .0050b6a0 ; jichi: hook here
0x39,0x6c,0x24, 0x28, // 004eeb39 396c24 28 cmp dword ptr ss:[esp+0x28],ebp
0x72, 0x0d, // 004eeb3d 72 0d jb short .004eeb4c
0x8b,0x4c,0x24, 0x14, // 004eeb3f 8b4c24 14 mov ecx,dword ptr ss:[esp+0x14]
0x51, // 004eeb43 51 push ecx
0xe8 //, XX4, // 004eeb44 e8 42dc1900 call .0068c78b
};
return MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
}
ULONG searchOtherAddress(ULONG startAddress, ULONG stopAddress)
{
const char *pattern = "S_ASSIGN";
const uint8_t bytes[] = {
//0xc3, // 005b6492 c3 retn
//0x52, // 005b6493 52 push edx
0xe8, XX4, // 005b6494 e8 77dc0000 call .005c4110 ; jichi: hook here
0x84,0xc0, // 005b6499 84c0 test al,al
0x75, XX, // 005b649b 75 16 jnz short .005b64b3
0x68, XX4, // 005b649d 68 d4757200 push .007275d4
0xb9 //, XX4, // 005b64a2 b9 f0757200 mov ecx,.007275f0 ; ascii "S_ASSIGN"
//0xe8, XX4 // 005b64a7 e8 84c8ffff call .005b2d30
};
for (ULONG addr = startAddress; addr < stopAddress;) {
addr = MemDbg::findBytes(bytes, sizeof(bytes), addr, stopAddress);
if (!addr)
return 0;
addr += sizeof(bytes);
DWORD ecx = *(DWORD *)addr;
if (::strcmp((LPCSTR)ecx, pattern) == 0)
return addr - sizeof(bytes);
};
return 0;
}
// - Hook -
struct TextHookBase
{
struct TextArgument // first argument of the scenario hook
{
DWORD unknown1,
unknown2;
LPCSTR text;
DWORD size; // text data size, length = size - 1
//DWORD split; // not a good split to distinguish translable text out
};
bool enabled_,
editable_; // for debugging only, whether text is not read-only
std::string buffer_; // persistent storage, which makes this function not thread-safe
TextArgument *arg_; // last argument
LPCSTR text_; // last text
DWORD size_; // last size
TextHookBase()
: enabled_(true)
, editable_(true)
, arg_(nullptr)
, text_(nullptr)
, size_(0)
{}
};
class ScenarioHook43 : protected TextHookBase
{
public:
bool hookBefore(hook_stack*s,void* data, size_t* len,uintptr_t*role)
{
// See ATcode patch:
// 0070A12E 8B87 B0000000 MOV EAX,DWORD PTR DS:[EDI+0xB0]
// 0070A134 66:8138 8400 CMP WORD PTR DS:[EAX],0x84
// 0070A139 75 0E JNZ SHORT .0070A149
// 0070A13B 8378 EA 5B CMP DWORD PTR DS:[EAX-0x16],0x5B
// 0070A13F 75 08 JNZ SHORT .0070A149
DWORD split = *(WORD *)(s->edi + 0xb0);
if (split && split != 0x27f2) // new System43 after Evenicle
return false;
if (!split) { // old System43 before Evenicle where edi split is zero
split = s->stack[1];
if (split != 0x84)
return false;
// Stack structure observed from 武想少女隊
// 0012F4BC 07EAFD48 ; text address
// 0012F4C0 000002EC ; use this value as split
// 0012F4C4 00000011
// 0012F4C8 0012F510
// 0012F4CC 00000012
// 0012F4D0 00001BAA
// 0012F4D4 00000012
// 0012F4D8 06D2E24C
// 0012F4DC 00581125 RETURN to .00581125 from .0057DC30
//if (s->stack[1] != 0x84)
// return true;
//if (s->stack[2] != 0x3)
// return true;
}
auto arg = (TextArgument *)s->stack[0]; // top of the stack
LPCSTR text = arg->text;
if (arg->size <= 1 || !text || !*text || all_ascii(text))
return false;
*role = Engine::ScenarioRole ;
return write_string_overwrite(data,len,text);
}
bool hookAfter(hook_stack*s,void* data, size_t* len,uintptr_t*role)
{
if (arg_) {
arg_->text = text_;
arg_->size = size_;
arg_ = nullptr;
}
return true;
}
};
class OtherHook43 : protected TextHookBase
{
public:
bool hookBefore(hook_stack*s,void* data, size_t* len,uintptr_t*role)
{
if (!enabled_)
return false;
DWORD splitBase = *(DWORD *)(s->edi + 0x284); // [edi + 0x284]
if (!Engine::isAddressReadable(splitBase)) {
enabled_ = false;
return false;
}
DWORD split1 = *(WORD *)(splitBase - 0x4), // word [[edi + 0x284] - 0x4]
split2 = *(WORD *)(splitBase - 0x8); // word [[edi + 0x284] - 0x8]
enum : WORD { OtherSplit = 0x46 }; // 0x440046 if use dword split
if (split1 != OtherSplit || split2 <= 2) // split internal system messages
return false;
auto arg = (TextArgument *)s->stack[0]; // top of the stack
// auto g = EngineController::instance();
LPCSTR text = arg->text;
if (arg->size <= 1 || !text || !*text || all_ascii(text))
return false;
return write_string_overwrite(data,len,text);
}
bool hookAfter(hook_stack*s,void* data, size_t* len,uintptr_t*role)
{
if (arg_) {
arg_->text = text_;
arg_->size = size_;
arg_ = nullptr;
}
return false;
}
};
// Text with fixed size
bool fixedTextHook(hook_stack*s,void* data, size_t* len,uintptr_t*role)
{
enum { FixedSize = 0x10 };
struct FixedArgument // first argument of the name hook
{
char text[FixedSize]; // 0x10
DWORD type, // [[esp]+0x10]
type2; // [[esp]+0x14]
};
auto arg = (FixedArgument *)s->stack[0];
if (arg->type2 != 0xf) // non 0xf is garbage text
return false;
char *text = arg->text;
if (!text || !*text || all_ascii(text))
return false;
* role;
long sig;
if (arg->type == 0x6 || arg->type == 0xc) {
*role = Engine::NameRole;
} else if (::strlen(text) <= 2) // skip translating very short other text
return false;
else {
*role = Engine::OtherRole;
}
return write_string_overwrite(data,len,text);
}
} // unnamed namespace
bool attachSystem43(ULONG startAddress, ULONG stopAddress)
{
//太麻煩 放棄。
return false;
{
//ULONG addr = 0x005c71e0;
ULONG addr = ::searchScenarioAddress(startAddress, stopAddress);
if (!addr)
return false;
/* static auto h = new ScenarioHook43; // never deleted
if (!winhook::hook_both(addr,
std::bind(&ScenarioHook43::hookBefore, h, _1),
std::bind(&ScenarioHook43::hookAfter, h, _1)))
return false;
*/
}
/*
if (ULONG addr = ::searchOtherAddress(startAddress, stopAddress)) {
static auto h = new OtherHook; // never deleted
if (!winhook::hook_both(addr,
std::bind(&OtherHook43::hookBefore, h, _1),
std::bind(&OtherHook43::hookAfter, h, _1)))
DOUT("other text NOT FOUND");
else
DOUT("other text address" << QString::number(addr, 16));
}
if (ULONG addr = ::searchNameAddress(startAddress, stopAddress)) {
if (winhook::hook_before(addr, ::fixedTextHook))
DOUT("name text address" << QString::number(addr, 16));
else
DOUT("name text NOT FOUND");
}
*/
//HijackManager::instance()->attachFunction((ULONG)::MultiByteToWideChar);
return true;
}
namespace{
bool system4X(ULONG startAddress, ULONG stopAddress){
if (attachSystem43(startAddress, stopAddress)) {
return true;
} else if (attachSystem44(startAddress, stopAddress)) {
return true;
} else
return false;
}
}
namespace{
bool System42Filter(LPVOID data, size_t *size, HookParam *)
{
auto text = reinterpret_cast<LPSTR>(data);
auto len = reinterpret_cast<size_t *>(size);
if (*len == 1)
return false;
if (all_ascii(text, *len)) {
CharReplacer(text, len, '`', ' ');
CharReplacer(text, len, '\x7D', '-');
}
return true;
}
bool InsertSystem42Hook() {
/*
* Sample games:
* https://vndb.org/v1427
*/
const BYTE bytes[] = {
0x8B, 0x46, 0x04, // mov eax,[esi+04]
0x57, // push edi
0x52, // push edx
0x50, // push eax
0xE8, XX4 // call Sys42VM.DLL+4B5B0
};
HMODULE module = GetModuleHandleW(L"Sys42VM.dll");
auto [minAddress, maxAddress] = Util::QueryModuleLimits(module);
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), minAddress, maxAddress);
if (!addr)
return false;
HookParam hp;
hp.address = addr;
hp.offset=get_reg(regs::edx);
hp.split =get_reg(regs::esp);
hp.type = NO_CONTEXT | USING_STRING | USING_SPLIT;
hp.filter_fun = System42Filter;
ConsoleOutput("INSERT System42");
return NewHook(hp, "System42");
}
}
bool System4x::attach_function() {
if (Util::CheckFile(L"DLL/Sys42VM.dll"))
if (InsertSystem42Hook())
return true;
auto _=system4X(processStartAddress,processStopAddress);
return InsertSystem43Hook()||_;
}