mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-23 22:05:36 +08:00
698 lines
30 KiB
C++
698 lines
30 KiB
C++
#include"Minori.h"
|
||
#include"util/textunion.h"
|
||
|
||
|
||
bool Minori1EngFilter(LPVOID data, size_t* size, HookParam*)
|
||
{
|
||
auto text = reinterpret_cast<LPSTR>(data);
|
||
auto len = reinterpret_cast<size_t*>(size);
|
||
StringCharReplacer(text, len, "\\n", 2, ' ');
|
||
StringFilter(text, len, "\\a", 2);
|
||
StringFilter(text, len, "\\v", 2);
|
||
CharReplacer(text, len, '\xC4', '-');
|
||
CharReplacer(text, len, '\x93', '"');
|
||
CharReplacer(text, len, '\x94', '"');
|
||
CharReplacer(text, len, '\x92', '\'');
|
||
StringCharReplacer(text, len, "\\I", 2, '\'');
|
||
StringCharReplacer(text, len, "\\P", 2, '\'');
|
||
|
||
return true;
|
||
}
|
||
|
||
bool Minori1JapFilter(LPVOID data, size_t* size, HookParam*)
|
||
{
|
||
auto text = reinterpret_cast<LPSTR>(data);
|
||
auto len = reinterpret_cast<size_t*>(size);
|
||
StringFilter(text, len, "\\a", 2);
|
||
StringFilter(text, len, "\\v", 2);
|
||
StringFilter(text, len, "\\N", 2);
|
||
|
||
if (cpp_strnstr(text, "{", *len)) {
|
||
StringFilterBetween(text, len, "{", 1, "}", 1);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool InsertMinori1Hook()
|
||
{
|
||
|
||
/*
|
||
* Sample games:
|
||
* https://vndb.org/v19644
|
||
* https://vndb.org/v12562
|
||
*/
|
||
const BYTE bytes[] = {
|
||
0x84, 0xC0, // test al,al << hook here
|
||
0x0F, 0x85, XX4, // jne trinoline_en_AA.exe+243E1
|
||
0x68, XX4, // push trinoline_en_AA.exe+118BF8 << alt eng hook
|
||
0x33, 0xFF // xor edi,edi
|
||
};
|
||
enum { alt_addr_offset = 8 };
|
||
|
||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
||
if (!addr) {
|
||
ConsoleOutput("Minori1: pattern not found");
|
||
return false;
|
||
}
|
||
|
||
HookParam hp;
|
||
hp.address = addr;
|
||
hp.offset =get_reg(regs::edx);
|
||
hp.codepage = 932;
|
||
hp.type = USING_STRING;
|
||
hp.filter_fun = Minori1JapFilter;
|
||
ConsoleOutput(" INSERT Minori1");
|
||
auto succ=NewHook(hp, "Minori1");
|
||
|
||
hp.address = addr + alt_addr_offset;
|
||
hp.filter_fun = Minori1EngFilter;
|
||
ConsoleOutput(" INSERT Minori1eng");
|
||
succ|=NewHook(hp, "Minori1eng");
|
||
|
||
return succ;
|
||
}
|
||
|
||
bool Minori2Filter(LPVOID data, size_t* size, HookParam*)
|
||
{
|
||
auto text = reinterpret_cast<LPSTR>(data);
|
||
auto len = reinterpret_cast<size_t*>(size);
|
||
StringCharReplacer(text, len, "\\n", 2, ' ');
|
||
|
||
if (cpp_strnstr(text, "{", *len)) {
|
||
StringFilterBetween(text, len, "{", 1, "}", 1);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool InsertMinori2Hook()
|
||
{
|
||
|
||
/*
|
||
* Sample games:
|
||
* https://vndb.org/v35
|
||
*/
|
||
const BYTE bytes[] = {
|
||
0x80, 0x38, 0x00, // cmp byte ptr [eax],00 << hook here
|
||
0x0F, 0x84, XX4, // je WindRP.exe+2832A
|
||
0xB8, 0x20, 0x03, 0x00, 0x00, // mov eax,00000320
|
||
0x89, 0x44, 0x24, 0x10, // mov [esp+10],eax
|
||
0x89, 0x44, 0x24, 0x14, // mov [esp+14],eax
|
||
0x8B, 0x47, 0x20 // mov eax,[edi+20]
|
||
};
|
||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
||
if (!addr) {
|
||
ConsoleOutput("Minori2: pattern not found");
|
||
return false;
|
||
}
|
||
|
||
ConsoleOutput(" INSERT Minori2");
|
||
HookParam hp;
|
||
hp.address = addr;
|
||
hp.offset=get_reg(regs::eax);
|
||
hp.type = USING_STRING;
|
||
hp.filter_fun = Minori2Filter;
|
||
ConsoleOutput(" INSERT Minori2");
|
||
ConsoleOutput("Minori2: Please, set text to max speed");
|
||
return NewHook(hp, "Minori2");
|
||
}
|
||
|
||
bool InsertMinoriHooks()
|
||
{
|
||
return InsertMinori1Hook() || InsertMinori2Hook();
|
||
}
|
||
|
||
namespace { // unnamed
|
||
namespace ScenarioHook {
|
||
namespace Private {
|
||
/**
|
||
* Sample game: 12の月のイヴ
|
||
* Remove \tag and leading #.
|
||
*/
|
||
LPCSTR trim(LPCSTR text, int *size)
|
||
{
|
||
int length = *size;
|
||
// handle prefix
|
||
while (text[0] == '#' || text[0] == '@') {
|
||
text++;
|
||
length--;
|
||
}
|
||
while (text[0] == '\\' && ::isalpha(text[1])) {
|
||
text += 2;
|
||
length -= 2;
|
||
}
|
||
// handle suffix
|
||
while (length >= 2 && text[length - 2] == '\\' && ::isalpha(text[length - 1]))
|
||
length -= 2;
|
||
*size = length;
|
||
return text;
|
||
}
|
||
|
||
/**
|
||
* Sample game: ソレヨリノ前奏詩
|
||
*
|
||
* 013BEFAE CC INT3
|
||
* 013BEFAF CC INT3
|
||
* 013BEFB0 55 PUSH EBP
|
||
* 013BEFB1 8BEC MOV EBP,ESP
|
||
* 013BEFB3 6A FF PUSH -0x1
|
||
* 013BEFB5 68 78654401 PUSH yorino_t.01446578
|
||
* 013BEFBA 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
|
||
* 013BEFC0 50 PUSH EAX
|
||
* 013BEFC1 64:8925 00000000 MOV DWORD PTR FS:[0],ESP
|
||
* 013BEFC8 83EC 54 SUB ESP,0x54
|
||
* 013BEFCB 53 PUSH EBX
|
||
* 013BEFCC 8B5D 08 MOV EBX,DWORD PTR SS:[EBP+0x8]
|
||
* 013BEFCF 56 PUSH ESI
|
||
* 013BEFD0 57 PUSH EDI
|
||
* 013BEFD1 8BF3 MOV ESI,EBX
|
||
* 013BEFD3 E8 68FFFFFF CALL yorino_t.013BEF40
|
||
* 013BEFD8 8883 6C2A0000 MOV BYTE PTR DS:[EBX+0x2A6C],AL
|
||
* 013BEFDE 8B45 14 MOV EAX,DWORD PTR SS:[EBP+0x14]
|
||
* 013BEFE1 33F6 XOR ESI,ESI
|
||
* 013BEFE3 56 PUSH ESI
|
||
* 013BEFE4 50 PUSH EAX
|
||
* 013BEFE5 BF 0F000000 MOV EDI,0xF
|
||
* 013BEFEA 83C8 FF OR EAX,0xFFFFFFFF
|
||
* 013BEFED 8D4D BC LEA ECX,DWORD PTR SS:[EBP-0x44]
|
||
* 013BEFF0 897D D0 MOV DWORD PTR SS:[EBP-0x30],EDI
|
||
* 013BEFF3 8975 CC MOV DWORD PTR SS:[EBP-0x34],ESI
|
||
* 013BEFF6 C645 BC 00 MOV BYTE PTR SS:[EBP-0x44],0x0
|
||
* 013BEFFA E8 313AFAFF CALL yorino_t.01362A30 ; jichi: name call
|
||
* 013BEFFF 8B4D 18 MOV ECX,DWORD PTR SS:[EBP+0x18]
|
||
* 013BF002 56 PUSH ESI
|
||
* 013BF003 8975 FC MOV DWORD PTR SS:[EBP-0x4],ESI
|
||
* 013BF006 51 PUSH ECX
|
||
* 013BF007 83C8 FF OR EAX,0xFFFFFFFF
|
||
* 013BF00A 8D4D D8 LEA ECX,DWORD PTR SS:[EBP-0x28]
|
||
* 013BF00D 897D EC MOV DWORD PTR SS:[EBP-0x14],EDI
|
||
* 013BF010 8975 E8 MOV DWORD PTR SS:[EBP-0x18],ESI
|
||
* 013BF013 C645 D8 00 MOV BYTE PTR SS:[EBP-0x28],0x0
|
||
* 013BF017 E8 143AFAFF CALL yorino_t.01362A30 ; jichi: scenario call
|
||
* 013BF01C C645 FC 01 MOV BYTE PTR SS:[EBP-0x4],0x1
|
||
* 013BF020 8B8B 7C2A0000 MOV ECX,DWORD PTR DS:[EBX+0x2A7C]
|
||
* 013BF026 3BCE CMP ECX,ESI
|
||
* 013BF028 74 1C JE SHORT yorino_t.013BF046
|
||
* 013BF02A 8B11 MOV EDX,DWORD PTR DS:[ECX]
|
||
* 013BF02C 8B52 0C MOV EDX,DWORD PTR DS:[EDX+0xC]
|
||
* 013BF02F 8D45 BC LEA EAX,DWORD PTR SS:[EBP-0x44]
|
||
* 013BF032 50 PUSH EAX
|
||
* 013BF033 FFD2 CALL EDX
|
||
* 013BF035 8B8B 7C2A0000 MOV ECX,DWORD PTR DS:[EBX+0x2A7C]
|
||
* 013BF03B 8B01 MOV EAX,DWORD PTR DS:[ECX]
|
||
* 013BF03D 8B40 0C MOV EAX,DWORD PTR DS:[EAX+0xC]
|
||
* 013BF040 8D55 D8 LEA EDX,DWORD PTR SS:[EBP-0x28]
|
||
* 013BF043 52 PUSH EDX
|
||
* 013BF044 FFD0 CALL EAX
|
||
* 013BF046 8B8B 1C130000 MOV ECX,DWORD PTR DS:[EBX+0x131C]
|
||
* 013BF04C 8B7D 0C MOV EDI,DWORD PTR SS:[EBP+0xC]
|
||
* 013BF04F 3BCF CMP ECX,EDI
|
||
* 013BF051 0F95C0 SETNE AL
|
||
* 013BF054 C683 411A0000 00 MOV BYTE PTR DS:[EBX+0x1A41],0x0
|
||
* 013BF05B 8845 08 MOV BYTE PTR SS:[EBP+0x8],AL
|
||
* 013BF05E 84C0 TEST AL,AL
|
||
* 013BF060 74 15 JE SHORT yorino_t.013BF077
|
||
* 013BF062 3BCE CMP ECX,ESI
|
||
* 013BF064 7C 11 JL SHORT yorino_t.013BF077
|
||
* 013BF066 8BB3 0C1A0000 MOV ESI,DWORD PTR DS:[EBX+0x1A0C]
|
||
* 013BF06C 85F6 TEST ESI,ESI
|
||
* 013BF06E 74 05 JE SHORT yorino_t.013BF075
|
||
* 013BF070 E8 8B500100 CALL yorino_t.013D4100
|
||
* 013BF075 33F6 XOR ESI,ESI
|
||
* 013BF077 56 PUSH ESI
|
||
* 013BF078 8D4D D8 LEA ECX,DWORD PTR SS:[EBP-0x28]
|
||
* 013BF07B 51 PUSH ECX
|
||
* 013BF07C 8D8B 00130000 LEA ECX,DWORD PTR DS:[EBX+0x1300]
|
||
* 013BF082 83C8 FF OR EAX,0xFFFFFFFF
|
||
* 013BF085 E8 A639FAFF CALL yorino_t.01362A30
|
||
* 013BF08A 56 PUSH ESI
|
||
* 013BF08B 8D55 BC LEA EDX,DWORD PTR SS:[EBP-0x44]
|
||
* 013BF08E 52 PUSH EDX
|
||
* 013BF08F 8D8B 20130000 LEA ECX,DWORD PTR DS:[EBX+0x1320]
|
||
* 013BF095 83C8 FF OR EAX,0xFFFFFFFF
|
||
* 013BF098 89BB 1C130000 MOV DWORD PTR DS:[EBX+0x131C],EDI
|
||
* 013BF09E E8 8D39FAFF CALL yorino_t.01362A30
|
||
* 013BF0A3 8B45 10 MOV EAX,DWORD PTR SS:[EBP+0x10]
|
||
* 013BF0A6 56 PUSH ESI
|
||
* 013BF0A7 50 PUSH EAX
|
||
* 013BF0A8 8D8B 3C130000 LEA ECX,DWORD PTR DS:[EBX+0x133C]
|
||
* 013BF0AE 83C8 FF OR EAX,0xFFFFFFFF
|
||
* 013BF0B1 E8 7A39FAFF CALL yorino_t.01362A30
|
||
* 013BF0B6 8B15 00A74B01 MOV EDX,DWORD PTR DS:[0x14BA700] ; yorino_t.0146603C
|
||
* 013BF0BC 8B82 CC000000 MOV EAX,DWORD PTR DS:[EDX+0xCC]
|
||
* 013BF0C2 B9 00A74B01 MOV ECX,yorino_t.014BA700
|
||
* 013BF0C7 FFD0 CALL EAX
|
||
* 013BF0C9 3BC6 CMP EAX,ESI
|
||
* 013BF0CB 7E 15 JLE SHORT yorino_t.013BF0E2
|
||
* 013BF0CD 3983 CC290000 CMP DWORD PTR DS:[EBX+0x29CC],EAX
|
||
* 013BF0D3 7C 0D JL SHORT yorino_t.013BF0E2
|
||
* 013BF0D5 8BCB MOV ECX,EBX
|
||
* 013BF0D7 E8 14650000 CALL yorino_t.013C55F0
|
||
* 013BF0DC 89B3 CC290000 MOV DWORD PTR DS:[EBX+0x29CC],ESI
|
||
* 013BF0E2 8A45 1C MOV AL,BYTE PTR SS:[EBP+0x1C]
|
||
* 013BF0E5 8883 421A0000 MOV BYTE PTR DS:[EBX+0x1A42],AL
|
||
* 013BF0EB 84C0 TEST AL,AL
|
||
* 013BF0ED 75 1F JNZ SHORT yorino_t.013BF10E
|
||
* 013BF0EF 83BB A0120000 02 CMP DWORD PTR DS:[EBX+0x12A0],0x2
|
||
* 013BF0F6 75 16 JNZ SHORT yorino_t.013BF10E
|
||
* 013BF0F8 89B3 A0120000 MOV DWORD PTR DS:[EBX+0x12A0],ESI
|
||
* 013BF0FE 8B15 00A74B01 MOV EDX,DWORD PTR DS:[0x14BA700] ; yorino_t.0146603C
|
||
* 013BF104 8B42 2C MOV EAX,DWORD PTR DS:[EDX+0x2C]
|
||
* 013BF107 B9 00A74B01 MOV ECX,yorino_t.014BA700
|
||
* 013BF10C FFD0 CALL EAX
|
||
* 013BF10E 8B45 08 MOV EAX,DWORD PTR SS:[EBP+0x8]
|
||
* 013BF111 8B53 10 MOV EDX,DWORD PTR DS:[EBX+0x10]
|
||
* 013BF114 8B52 3C MOV EDX,DWORD PTR DS:[EDX+0x3C]
|
||
* 013BF117 6A 00 PUSH 0x0
|
||
* 013BF119 6A 01 PUSH 0x1
|
||
* 013BF11B 50 PUSH EAX
|
||
* 013BF11C 8D4D D8 LEA ECX,DWORD PTR SS:[EBP-0x28]
|
||
* 013BF11F 51 PUSH ECX
|
||
* 013BF120 8D45 BC LEA EAX,DWORD PTR SS:[EBP-0x44]
|
||
* 013BF123 50 PUSH EAX
|
||
* 013BF124 8D4B 10 LEA ECX,DWORD PTR DS:[EBX+0x10]
|
||
* 013BF127 FFD2 CALL EDX
|
||
* 013BF129 8B43 10 MOV EAX,DWORD PTR DS:[EBX+0x10]
|
||
* 013BF12C 8BB3 0C1A0000 MOV ESI,DWORD PTR DS:[EBX+0x1A0C]
|
||
* 013BF132 8945 1C MOV DWORD PTR SS:[EBP+0x1C],EAX
|
||
* 013BF135 8B83 141A0000 MOV EAX,DWORD PTR DS:[EBX+0x1A14]
|
||
* 013BF13B E8 204B0100 CALL yorino_t.013D3C60
|
||
* 013BF140 8B55 1C MOV EDX,DWORD PTR SS:[EBP+0x1C]
|
||
* 013BF143 50 PUSH EAX
|
||
* 013BF144 8B42 4C MOV EAX,DWORD PTR DS:[EDX+0x4C]
|
||
* 013BF147 8BCF MOV ECX,EDI
|
||
* 013BF149 51 PUSH ECX
|
||
* 013BF14A 8D4B 10 LEA ECX,DWORD PTR DS:[EBX+0x10]
|
||
* 013BF14D FFD0 CALL EAX
|
||
* 013BF14F 8B53 10 MOV EDX,DWORD PTR DS:[EBX+0x10]
|
||
* 013BF152 8B42 78 MOV EAX,DWORD PTR DS:[EDX+0x78]
|
||
* 013BF155 8D4B 10 LEA ECX,DWORD PTR DS:[EBX+0x10]
|
||
* 013BF158 FFD0 CALL EAX
|
||
* 013BF15A 8BF3 MOV ESI,EBX
|
||
* 013BF15C 8983 64130000 MOV DWORD PTR DS:[EBX+0x1364],EAX
|
||
* 013BF162 E8 B9B0FFFF CALL yorino_t.013BA220
|
||
* 013BF167 84C0 TEST AL,AL
|
||
* 013BF169 74 6D JE SHORT yorino_t.013BF1D8
|
||
* 013BF16B 8B53 10 MOV EDX,DWORD PTR DS:[EBX+0x10]
|
||
* 013BF16E 8B42 40 MOV EAX,DWORD PTR DS:[EDX+0x40]
|
||
* 013BF171 6A 00 PUSH 0x0
|
||
* 013BF173 6A 01 PUSH 0x1
|
||
* 013BF175 8D4B 10 LEA ECX,DWORD PTR DS:[EBX+0x10]
|
||
* 013BF178 FFD0 CALL EAX
|
||
* 013BF17A E8 C1FDFFFF CALL yorino_t.013BEF40
|
||
* 013BF17F 33C9 XOR ECX,ECX
|
||
* 013BF181 8BFB MOV EDI,EBX
|
||
* 013BF183 E8 C8B8FFFF CALL yorino_t.013BAA50
|
||
* 013BF188 33FF XOR EDI,EDI
|
||
* 013BF18A 89BB 181A0000 MOV DWORD PTR DS:[EBX+0x1A18],EDI
|
||
* 013BF190 E8 3BF0FFFF CALL yorino_t.013BE1D0
|
||
* 013BF195 68 78CB4401 PUSH yorino_t.0144CB78
|
||
* 013BF19A 8D75 A0 LEA ESI,DWORD PTR SS:[EBP-0x60]
|
||
* 013BF19D C745 B4 0F000000 MOV DWORD PTR SS:[EBP-0x4C],0xF
|
||
* 013BF1A4 897D B0 MOV DWORD PTR SS:[EBP-0x50],EDI
|
||
* 013BF1A7 C645 A0 00 MOV BYTE PTR SS:[EBP-0x60],0x0
|
||
* 013BF1AB E8 A065FAFF CALL yorino_t.01365750
|
||
* 013BF1B0 C645 FC 02 MOV BYTE PTR SS:[EBP-0x4],0x2
|
||
* 013BF1B4 8B53 10 MOV EDX,DWORD PTR DS:[EBX+0x10]
|
||
* 013BF1B7 8B52 6C MOV EDX,DWORD PTR DS:[EDX+0x6C]
|
||
* 013BF1BA 8D4B 10 LEA ECX,DWORD PTR DS:[EBX+0x10]
|
||
* 013BF1BD 6A 01 PUSH 0x1
|
||
* 013BF1BF 8BC6 MOV EAX,ESI
|
||
* 013BF1C1 50 PUSH EAX
|
||
* 013BF1C2 FFD2 CALL EDX
|
||
* 013BF1C4 837D B4 10 CMP DWORD PTR SS:[EBP-0x4C],0x10
|
||
* 013BF1C8 72 56 JB SHORT yorino_t.013BF220
|
||
* 013BF1CA 8B45 A0 MOV EAX,DWORD PTR SS:[EBP-0x60]
|
||
* 013BF1CD 50 PUSH EAX
|
||
* 013BF1CE E8 28B50500 CALL yorino_t.0141A6FB
|
||
* 013BF1D3 83C4 04 ADD ESP,0x4
|
||
* 013BF1D6 EB 48 JMP SHORT yorino_t.013BF220
|
||
* 013BF1D8 8B7D 10 MOV EDI,DWORD PTR SS:[EBP+0x10]
|
||
* 013BF1DB C783 181A0000 04>MOV DWORD PTR DS:[EBX+0x1A18],0x4
|
||
* 013BF1E5 837F 10 00 CMP DWORD PTR DS:[EDI+0x10],0x0
|
||
* 013BF1E9 C705 64514801 00>MOV DWORD PTR DS:[0x1485164],0x0
|
||
* 013BF1F3 76 2B JBE SHORT yorino_t.013BF220
|
||
* 013BF1F5 8BF3 MOV ESI,EBX
|
||
* 013BF1F7 E8 D4EFFFFF CALL yorino_t.013BE1D0
|
||
* 013BF1FC 8B15 00A74B01 MOV EDX,DWORD PTR DS:[0x14BA700] ; yorino_t.0146603C
|
||
* 013BF202 8B82 8C000000 MOV EAX,DWORD PTR DS:[EDX+0x8C]
|
||
* 013BF208 B9 00A74B01 MOV ECX,yorino_t.014BA700
|
||
* 013BF20D FFD0 CALL EAX
|
||
* 013BF20F 84C0 TEST AL,AL
|
||
* 013BF211 75 0D JNZ SHORT yorino_t.013BF220
|
||
* 013BF213 837F 10 00 CMP DWORD PTR DS:[EDI+0x10],0x0
|
||
* 013BF217 76 07 JBE SHORT yorino_t.013BF220
|
||
* 013BF219 57 PUSH EDI
|
||
* 013BF21A 53 PUSH EBX
|
||
* 013BF21B E8 A0EAFFFF CALL yorino_t.013BDCC0
|
||
* 013BF220 BE 10000000 MOV ESI,0x10
|
||
* 013BF225 C683 C8290000 00 MOV BYTE PTR DS:[EBX+0x29C8],0x0
|
||
* 013BF22C 3975 EC CMP DWORD PTR SS:[EBP-0x14],ESI
|
||
* 013BF22F 72 0C JB SHORT yorino_t.013BF23D
|
||
* 013BF231 8B4D D8 MOV ECX,DWORD PTR SS:[EBP-0x28]
|
||
* 013BF234 51 PUSH ECX
|
||
* 013BF235 E8 C1B40500 CALL yorino_t.0141A6FB
|
||
* 013BF23A 83C4 04 ADD ESP,0x4
|
||
* 013BF23D 3975 D0 CMP DWORD PTR SS:[EBP-0x30],ESI
|
||
* 013BF240 5F POP EDI
|
||
* 013BF241 5E POP ESI
|
||
* 013BF242 C745 EC 0F000000 MOV DWORD PTR SS:[EBP-0x14],0xF
|
||
* 013BF249 C745 E8 00000000 MOV DWORD PTR SS:[EBP-0x18],0x0
|
||
* 013BF250 C645 D8 00 MOV BYTE PTR SS:[EBP-0x28],0x0
|
||
* 013BF254 5B POP EBX
|
||
* 013BF255 72 0C JB SHORT yorino_t.013BF263
|
||
* 013BF257 8B55 BC MOV EDX,DWORD PTR SS:[EBP-0x44]
|
||
* 013BF25A 52 PUSH EDX
|
||
* 013BF25B E8 9BB40500 CALL yorino_t.0141A6FB
|
||
* 013BF260 83C4 04 ADD ESP,0x4
|
||
* 013BF263 8B4D F4 MOV ECX,DWORD PTR SS:[EBP-0xC]
|
||
* 013BF266 64:890D 00000000 MOV DWORD PTR FS:[0],ECX
|
||
* 013BF26D 8BE5 MOV ESP,EBP
|
||
* 013BF26F 5D POP EBP
|
||
* 013BF270 C2 1800 RETN 0x18
|
||
* 013BF273 CC INT3
|
||
* 013BF274 CC INT3
|
||
* 013BF275 CC INT3
|
||
* 013BF276 CC INT3
|
||
* 013BF277 CC INT3
|
||
* 013BF278 CC INT3
|
||
* 013BF279 CC INT3
|
||
* 013BF27A CC INT3
|
||
* 013BF27B CC INT3
|
||
* 013BF27C CC INT3
|
||
* 013BF27D CC INT3
|
||
* 013BF27E CC INT3
|
||
* 013BF27F CC INT3
|
||
*
|
||
* Sample text:
|
||
* 00C3091C 57 48 49 54 45 2E 70 6E 67 00 00 00 00 00 00 00 WHITE.png.......
|
||
* 00C3092C 09 00 00 00 0F 00 00 00 00 00 00 00 00 00 00 00 ...............
|
||
*/
|
||
TextUnionA *arg_,
|
||
argValue_;
|
||
std::unordered_map<uintptr_t,int>addr_role;
|
||
bool hookBeforehookBefore(hook_stack*s,void* data1, size_t* len,uintptr_t*role)
|
||
{
|
||
static std::string data_;
|
||
//auto arg = (TextUnionA *)s->ecx;
|
||
auto arg = (TextUnionA *)s->stack[0]; // arg1
|
||
if (!arg || !arg->isValid())
|
||
return false;
|
||
auto text = arg->getText();
|
||
if (all_ascii(text))
|
||
return false;
|
||
int size = arg->size,
|
||
trimmedSize = size;
|
||
auto trimmedText = trim(text, &trimmedSize);
|
||
if (!trimmedSize || !*trimmedText)
|
||
return false;
|
||
//auto sig = Engine::hashThreadSignature(role, retaddr);
|
||
std::string oldData(trimmedText, trimmedSize);
|
||
auto retaddr=s->stack[0];
|
||
*role=addr_role[retaddr];
|
||
if (*role == Engine::NameRole)
|
||
strReplace(oldData,"\x81\x40", ""); // remove spaces in the middle of names
|
||
|
||
write_string_overwrite(data1,len,oldData);
|
||
return true;
|
||
|
||
}
|
||
void hookafter(hook_stack*s,void* data1, size_t len){
|
||
std::string newData = std::string((LPSTR)data1,len);
|
||
auto arg = (TextUnionA *)s->stack[0]; // arg1
|
||
auto text = arg->getText();
|
||
int size = arg->size,
|
||
trimmedSize = size;
|
||
auto trimmedText = trim(text, &trimmedSize);
|
||
int prefixSize = trimmedText - text,
|
||
suffixSize = size - prefixSize - trimmedSize;
|
||
if (prefixSize)
|
||
newData.insert(0,std::string(text, prefixSize));
|
||
if (suffixSize)
|
||
newData.append(trimmedText + trimmedSize, suffixSize);
|
||
arg_ = arg;
|
||
argValue_ = *arg;
|
||
static std::string data_;
|
||
data_ = newData;
|
||
arg->setText(data_);
|
||
}
|
||
bool hookAfter(hook_stack*s,void* data1, size_t* len,uintptr_t*role)
|
||
{
|
||
if (arg_) {
|
||
*arg_ = argValue_;
|
||
arg_ = nullptr;
|
||
}
|
||
return 0;
|
||
}
|
||
} // namespace Private
|
||
|
||
/**
|
||
* Sample game: ソレヨリノ前奏詩
|
||
* arg1 is source, ecx is target.
|
||
*
|
||
* 01052A2D CC INT3
|
||
* 01052A2E CC INT3
|
||
* 01052A2F CC INT3
|
||
* 01052A30 55 PUSH EBP
|
||
* 01052A31 8BEC MOV EBP,ESP
|
||
* 01052A33 53 PUSH EBX
|
||
* 01052A34 8B5D 0C MOV EBX,DWORD PTR SS:[EBP+0xC]
|
||
* 01052A37 56 PUSH ESI
|
||
* 01052A38 8BF1 MOV ESI,ECX ; jichi: ecx is target address?
|
||
* 01052A3A 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+0x8]
|
||
* 01052A3D 57 PUSH EDI
|
||
* 01052A3E 8B79 10 MOV EDI,DWORD PTR DS:[ECX+0x10] ; jichi: source size
|
||
* 01052A41 3BFB CMP EDI,EBX
|
||
* 01052A43 73 0A JNB SHORT yorino_t.01052A4F
|
||
* 01052A45 68 88CA1301 PUSH yorino_t.0113CA88 ; ASCII "invalid string position"
|
||
* 01052A4A E8 337C0B00 CALL yorino_t.0110A682
|
||
* 01052A4F 2BFB SUB EDI,EBX
|
||
* 01052A51 3BC7 CMP EAX,EDI
|
||
* 01052A53 0F42F8 CMOVB EDI,EAX
|
||
* 01052A56 3BF1 CMP ESI,ECX
|
||
* 01052A58 75 1D JNZ SHORT yorino_t.01052A77
|
||
* 01052A5A 8D0C1F LEA ECX,DWORD PTR DS:[EDI+EBX]
|
||
* 01052A5D 83C8 FF OR EAX,0xFFFFFFFF
|
||
* 01052A60 E8 EBFCFFFF CALL yorino_t.01052750
|
||
* 01052A65 8BC3 MOV EAX,EBX
|
||
* 01052A67 33C9 XOR ECX,ECX
|
||
* 01052A69 E8 E2FCFFFF CALL yorino_t.01052750
|
||
* 01052A6E 5F POP EDI
|
||
* 01052A6F 8BC6 MOV EAX,ESI
|
||
* 01052A71 5E POP ESI
|
||
* 01052A72 5B POP EBX
|
||
* 01052A73 5D POP EBP
|
||
* 01052A74 C2 0800 RETN 0x8
|
||
* 01052A77 83FF FE CMP EDI,-0x2
|
||
* 01052A7A 76 0A JBE SHORT yorino_t.01052A86
|
||
* 01052A7C 68 B4CA1301 PUSH yorino_t.0113CAB4 ; ASCII "string too long"
|
||
* 01052A81 E8 AF7B0B00 CALL yorino_t.0110A635
|
||
* 01052A86 8B46 14 MOV EAX,DWORD PTR DS:[ESI+0x14]
|
||
* 01052A89 3BC7 CMP EAX,EDI
|
||
* 01052A8B 73 27 JNB SHORT yorino_t.01052AB4
|
||
* 01052A8D 8B46 10 MOV EAX,DWORD PTR DS:[ESI+0x10]
|
||
* 01052A90 50 PUSH EAX
|
||
* 01052A91 57 PUSH EDI
|
||
* 01052A92 56 PUSH ESI
|
||
* 01052A93 E8 88FDFFFF CALL yorino_t.01052820
|
||
* 01052A98 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+0x8]
|
||
* 01052A9B 85FF TEST EDI,EDI
|
||
* 01052A9D 74 68 JE SHORT yorino_t.01052B07
|
||
* 01052A9F B8 10000000 MOV EAX,0x10
|
||
* 01052AA4 3941 14 CMP DWORD PTR DS:[ECX+0x14],EAX
|
||
* 01052AA7 72 02 JB SHORT yorino_t.01052AAB
|
||
* 01052AA9 8B09 MOV ECX,DWORD PTR DS:[ECX]
|
||
* 01052AAB 3946 14 CMP DWORD PTR DS:[ESI+0x14],EAX
|
||
* 01052AAE 72 2A JB SHORT yorino_t.01052ADA
|
||
* 01052AB0 8B06 MOV EAX,DWORD PTR DS:[ESI]
|
||
* 01052AB2 EB 28 JMP SHORT yorino_t.01052ADC
|
||
* 01052AB4 85FF TEST EDI,EDI
|
||
* 01052AB6 ^75 E7 JNZ SHORT yorino_t.01052A9F
|
||
* 01052AB8 897E 10 MOV DWORD PTR DS:[ESI+0x10],EDI
|
||
* 01052ABB 83F8 10 CMP EAX,0x10
|
||
* 01052ABE 72 0E JB SHORT yorino_t.01052ACE
|
||
* 01052AC0 8B06 MOV EAX,DWORD PTR DS:[ESI]
|
||
* 01052AC2 5F POP EDI
|
||
* 01052AC3 C600 00 MOV BYTE PTR DS:[EAX],0x0
|
||
* 01052AC6 8BC6 MOV EAX,ESI
|
||
* 01052AC8 5E POP ESI
|
||
* 01052AC9 5B POP EBX
|
||
* 01052ACA 5D POP EBP
|
||
* 01052ACB C2 0800 RETN 0x8
|
||
* 01052ACE 5F POP EDI
|
||
* 01052ACF 8BC6 MOV EAX,ESI
|
||
* 01052AD1 5E POP ESI
|
||
* 01052AD2 C600 00 MOV BYTE PTR DS:[EAX],0x0
|
||
* 01052AD5 5B POP EBX
|
||
* 01052AD6 5D POP EBP
|
||
* 01052AD7 C2 0800 RETN 0x8
|
||
* 01052ADA 8BC6 MOV EAX,ESI ; jichi: esi is target address
|
||
* 01052ADC 57 PUSH EDI ; jichi: source size
|
||
* 01052ADD 03CB ADD ECX,EBX
|
||
* 01052ADF 51 PUSH ECX ; jichi: source
|
||
* 01052AE0 50 PUSH EAX ; jichi: target
|
||
* 01052AE1 E8 9AC80B00 CALL yorino_t.0110F380 ; jichi: called here
|
||
* 01052AE6 83C4 0C ADD ESP,0xC
|
||
* 01052AE9 837E 14 10 CMP DWORD PTR DS:[ESI+0x14],0x10
|
||
* 01052AED 897E 10 MOV DWORD PTR DS:[ESI+0x10],EDI
|
||
* 01052AF0 72 0F JB SHORT yorino_t.01052B01
|
||
* 01052AF2 8B06 MOV EAX,DWORD PTR DS:[ESI]
|
||
* 01052AF4 C60438 00 MOV BYTE PTR DS:[EAX+EDI],0x0
|
||
* 01052AF8 5F POP EDI
|
||
* 01052AF9 8BC6 MOV EAX,ESI
|
||
* 01052AFB 5E POP ESI
|
||
* 01052AFC 5B POP EBX
|
||
* 01052AFD 5D POP EBP
|
||
* 01052AFE C2 0800 RETN 0x8
|
||
* 01052B01 8BC6 MOV EAX,ESI
|
||
* 01052B03 C60438 00 MOV BYTE PTR DS:[EAX+EDI],0x0
|
||
* 01052B07 5F POP EDI
|
||
* 01052B08 8BC6 MOV EAX,ESI
|
||
* 01052B0A 5E POP ESI
|
||
* 01052B0B 5B POP EBX
|
||
* 01052B0C 5D POP EBP
|
||
* 01052B0D C2 0800 RETN 0x8
|
||
* 01052B10 6A 00 PUSH 0x0
|
||
* 01052B12 50 PUSH EAX
|
||
* 01052B13 C746 14 0F000000 MOV DWORD PTR DS:[ESI+0x14],0xF
|
||
* 01052B1A C746 10 00000000 MOV DWORD PTR DS:[ESI+0x10],0x0
|
||
* 01052B21 83C8 FF OR EAX,0xFFFFFFFF
|
||
* 01052B24 8BCE MOV ECX,ESI
|
||
* 01052B26 C606 00 MOV BYTE PTR DS:[ESI],0x0
|
||
* 01052B29 E8 02FFFFFF CALL yorino_t.01052A30
|
||
* 01052B2E 8BC6 MOV EAX,ESI
|
||
* 01052B30 C3 RETN
|
||
* 01052B31 CC INT3
|
||
* 01052B32 CC INT3
|
||
* 01052B33 CC INT3
|
||
* 01052B34 CC INT3
|
||
* 01052B35 CC INT3
|
||
* 01052B36 CC INT3
|
||
* 01052B37 CC INT3
|
||
* 01052B38 CC INT3
|
||
* 01052B39 CC INT3
|
||
* 01052B3A CC INT3
|
||
* 01052B3B CC INT3
|
||
* 01052B3C CC INT3
|
||
*
|
||
* 005CF5C4 01C17D68
|
||
* 005CF5C8 00000026
|
||
* 005CF5CC /005CF5EC
|
||
* 005CF5D0 |00172AE6 RETURN to yorino_t.00172AE6 from yorino_t.0022F380
|
||
* 005CF5D4 |01C154F0 ; jichi: target text
|
||
* 005CF5D8 |01C15608 ; jcihi: source text
|
||
* 005CF5DC |00000026 ; jichi: source size
|
||
* 005CF5E0 |00000082 ; jichi: capacity? not sure
|
||
* 005CF5E4 |00000000
|
||
* 005CF5E8 |01C16A68
|
||
* 005CF5EC ]005CF668
|
||
* 005CF5F0 |001CF08A RETURN to yorino_t.001CF08A from yorino_t.00172A30
|
||
* 005CF5F4 |005CF640
|
||
* 005CF5F8 |00000000
|
||
* 005CF5FC |01C19500
|
||
*/
|
||
bool attach(ULONG startAddress, ULONG stopAddress)
|
||
{
|
||
const uint8_t bytes[] = {
|
||
0x8b,0xc6, // 01052ada 8bc6 mov eax,esi ; jichi: esi is target address
|
||
0x57, // 01052adc 57 push edi ; jichi: source size
|
||
0x03,0xcb, // 01052add 03cb add ecx,ebx
|
||
0x51, // 01052adf 51 push ecx ; jichi: source
|
||
0x50 // 01052ae0 50 push eax ; jichi: target
|
||
//0xe8, XX4, // 01052ae1 e8 9ac80b00 call yorino_t.0110f380 ; jichi: called here
|
||
//0x83,0xc4, 0x0c // 01052ae6 83c4 0c add esp,0xc
|
||
};
|
||
//enum { addr_offset = sizeof(bytes) - 8 };
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
|
||
if (!addr)
|
||
return false;
|
||
addr = MemDbg::findEnclosingAlignedFunction(addr);
|
||
if (!addr)
|
||
return false;
|
||
//return winhook::hook_before(addr, Private::hookBefore);
|
||
|
||
bool count = false;
|
||
auto fun = [&count](ULONG addr) -> bool {
|
||
// Sample game: ソレヨリノ前奏詩
|
||
// 013BEFFA E8 313AFAFF CALL yorino_t.01362A30 ; jichi: name call
|
||
// 013BEFFF 8B4D 18 MOV ECX,DWORD PTR SS:[EBP+0x18]
|
||
// 013BF002 56 PUSH ESI
|
||
// 013BF003 8975 FC MOV DWORD PTR SS:[EBP-0x4],ESI
|
||
// 013BF006 51 PUSH ECX
|
||
// 013BF007 83C8 FF OR EAX,0xFFFFFFFF
|
||
// 013BF00A 8D4D D8 LEA ECX,DWORD PTR SS:[EBP-0x28]
|
||
// 013BF00D 897D EC MOV DWORD PTR SS:[EBP-0x14],EDI
|
||
// 013BF010 8975 E8 MOV DWORD PTR SS:[EBP-0x18],ESI
|
||
// 013BF013 C645 D8 00 MOV BYTE PTR SS:[EBP-0x28],0x0
|
||
// 013BF017 E8 143AFAFF CALL yorino_t.01362A30 ; jichi: scenario call
|
||
// 013BF01C C645 FC 01 MOV BYTE PTR SS:[EBP-0x4],0x1
|
||
// 013BF020 8B8B 7C2A0000 MOV ECX,DWORD PTR DS:[EBX+0x2A7C]
|
||
// 013BF026 3BCE CMP ECX,ESI
|
||
//
|
||
// Bad scenario to skip:
|
||
//
|
||
// 0035A9A3 C745 E4 0F000000 MOV DWORD PTR SS:[EBP-0x1C],0xF
|
||
// 0035A9AA C745 E0 00000000 MOV DWORD PTR SS:[EBP-0x20],0x0
|
||
// 0035A9B1 C645 D0 00 MOV BYTE PTR SS:[EBP-0x30],0x0
|
||
// 0035A9B5 -E9 4656D001 JMP 02060000 ; jichi: here
|
||
// 0035A9BA C645 FC 01 MOV BYTE PTR SS:[EBP-0x4],0x1
|
||
// 0035A9BE 8B7D E0 MOV EDI,DWORD PTR SS:[EBP-0x20]
|
||
// 0035A9C1 83FF 01 CMP EDI,0x1
|
||
// 0035A9C4 0F86 B0000000 JBE .0035AA7A
|
||
auto retaddr = addr + 5;
|
||
auto role = Engine::OtherRole;
|
||
switch (*(DWORD *)retaddr) {
|
||
case 0x56184d8b:
|
||
// 013BEFFF 8B4D 18 MOV ECX,DWORD PTR SS:[EBP+0x18]
|
||
// 013BF002 56 PUSH ESI
|
||
role = Engine::NameRole;
|
||
break;
|
||
case 0x01fc45c6: // 013BF01C C645 FC 01 MOV BYTE PTR SS:[EBP-0x4],0x1
|
||
if (*(DWORD *)(retaddr - 5 - sizeof(DWORD)) == 0x00D845C6) { // previous instruction
|
||
role = Engine::ScenarioRole;
|
||
break;
|
||
}
|
||
default: return true;
|
||
}
|
||
Private::addr_role[retaddr]=role;
|
||
{
|
||
HookParam hp;
|
||
hp.address=addr;
|
||
hp.hook_before=Private::hookBeforehookBefore;
|
||
hp.hook_after=Private::hookafter;
|
||
hp.type=EMBED_ABLE|USING_STRING|EMBED_DYNA_SJIS;
|
||
hp.hook_font=F_GetGlyphOutlineA;
|
||
hp.filter_fun=[](void* data, size_t* len, HookParam* hp){
|
||
|
||
write_string_overwrite(data,len,std::regex_replace(std::string((char*)data,*len), std::regex("\\{.*?\\}"), ""));
|
||
return true;
|
||
|
||
};
|
||
count|=NewHook(hp,"EmbedMinori");
|
||
}
|
||
{
|
||
HookParam hp;
|
||
hp.address=addr+5;
|
||
hp.hook_before=Private::hookAfter;
|
||
hp.hook_after=Private::hookafter;
|
||
hp.type=EMBED_ABLE|HOOK_EMPTY;
|
||
count|=NewHook(hp,"EmbedMinori");
|
||
}
|
||
return true; // replace all functions
|
||
};
|
||
MemDbg::iterNearCallAddress(fun, addr, startAddress, stopAddress);
|
||
|
||
return count;
|
||
}
|
||
|
||
} // namespace ScenarioHook
|
||
|
||
} // unnamed namespace
|
||
|
||
bool Minori::attach_function() {
|
||
bool embed=ScenarioHook::attach(processStartAddress,processStopAddress);
|
||
return InsertMinoriHooks()||embed;
|
||
}
|