Improved YukaSystem engine hook

This commit is contained in:
Blu3train 2023-08-20 19:03:31 +02:00
parent f3fbe04409
commit fc7a0c5a48
3 changed files with 122 additions and 3 deletions

View File

@ -13272,6 +13272,7 @@ bool InsertNeXASHook()
* 004010ef cc int3 * 004010ef cc int3
*/ */
/*
// Ignore image and music file names // Ignore image and music file names
// Sample text: "Voice\tou00012.ogg""運命論って云うのかなあ……神さまを信じてる人が多かったからだろうね、何があっても、それ<E3819D>神さまが<E381BE><EFBFBD>ちに与えられた試練なんだって、そ぀<E3819D>ってたみたい。勿論、今でもそ぀<E3819D><E38180>てあ<E381A6>人はぁ<E381AF>ぱぁ<E381B1>るん<E3828B>けど<E38191> // Sample text: "Voice\tou00012.ogg""運命論って云うのかなあ……神さまを信じてる人が多かったからだろうね、何があっても、それ<E3819D>神さまが<E381BE><EFBFBD>ちに与えられた試練なんだって、そ぀<E3819D>ってたみたい。勿論、今でもそ぀<E3819D><E38180>てあ<E381A6>人はぁ<E381AF>ぱぁ<E381B1>るん<E3828B>けど<E38191>
// Though the input string is UTF-8, it should be ASCII compatible. // Though the input string is UTF-8, it should be ASCII compatible.
@ -13333,6 +13334,124 @@ bool InsertYukaSystem2Hook()
NewHook(hp, "YukaSystem2"); NewHook(hp, "YukaSystem2");
return true; return true;
} }
*/
bool YukaSystem2Filter(LPVOID data, DWORD *size, HookParam *, BYTE)
{
auto text = reinterpret_cast<LPSTR>(data);
auto len = reinterpret_cast<size_t *>(size);
// Try to identify if the first two characters are urf-8
if (*len < 3) return false;
for (int i=0; i<*len; i++)
if (text[i] > 0 && (text[i]!='@' && text[i]!='r' && text[i]!='(' && text[i]!=',' && text[i]!=')' && text[i]!=' '))
return false; //ascii uses only 7 bits. Skip "@r(,) "
//Check characters (3 bytes) for utf-8
if (*len < 4) {
if (text[0]<'\xe2' || text[0]>'\xef') return false;
}
else
if (text[0]<'\xe2' || text[0]>'\xef' || text[3]<'\xe2' || text[3]>'\xef') return false;
if (cpp_strnstr(text, "@r(", *len)) {
StringFilter(text, len, "@r(", 3);
StringFilterBetween(text, len, ",", 1, ")", 1);
}
return true;
}
bool InsertYukaSystem2Hook()
{
//mod by Blu3train
/*
* Sample games:
* https://vndb.org/v14760
*/
const BYTE bytes[] = {
0x55, // 004010e0 /$ 55 push ebp ; jichi; hook here
0x8b,0xec, // 004010e1 |. 8bec mov ebp,esp
0x8b,0x45, 0x08, // 004010e3 |. 8b45 08 mov eax,dword ptr ss:[ebp+0x8] ; jichi: ebp+0x8 = arg2
0x8b,0x4d, 0x0c, // 004010e6 |. 8b4d 0c mov ecx,dword ptr ss:[ebp+0xc]
0x8a,0x11, // 004010e9 |. 8a11 mov dl,byte ptr ds:[ecx]
0x88,0x10, // 004010eb |. 8810 mov byte ptr ds:[eax],dl ; jichi: eax is the address to text
0x5d, // 004010ed |. 5d pop ebp
0xc3 // 004010ee \. c3 retn
};
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
//GROWL_DWORD(addr); // supposed to be 0x4010e0
if (!addr) {
ConsoleOutput("vnreng:YukaSystem2: pattern not found");
return false;
}
HookParam hp = {};
hp.address = addr;
hp.offset = 1 * 4; //arg 1
hp.split = 2 * 4; //arg 2
hp.type = NO_CONTEXT | USING_STRING | USING_UTF8 | USING_SPLIT; // UTF-8, though
hp.filter_fun = YukaSystem2Filter;
ConsoleOutput("vnreng: INSERT YukaSystem2");
NewHook(hp, "YukaSystem2");
return true;
}
bool YukaSystem1Filter(LPVOID data, DWORD *size, HookParam *, BYTE)
{
auto text = reinterpret_cast<LPSTR>(data);
auto len = reinterpret_cast<size_t *>(size);
if (*len == 0) return false;
// if acii add a space at the end of the sentence overwriting null terminator
if (*len >=2 && text[*len-2]>0)
text[(*len)++] = ' ';
if (cpp_strnstr(text, "@r(", *len)) {
StringFilterBetween(text, len, "@r(", 3, ")", 1); // @r(2,はと)
}
return true;
}
bool InsertYukaSystem1Hook()
{
//mod by Blu3train
/*
* Sample games:
* https://vndb.org/r71601
* https://vndb.org/v7507
*/
const BYTE bytes[] = {
0x80, 0x3D, XX4, 0x01, // cmp byte ptr [kimihime.exe+16809C],01 << hook here
0x75, 0x11, // jne kimihime.exe+42D74
0xB9, XX4, // mov ecx,kimihime.exe+C7F8C
0xC6, 0x05, XX4, 0x00 // mov byte ptr [kimihime.exe+1516C5],00
};
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
if (!addr) {
ConsoleOutput("vnreng:YukaSystem1: pattern not found");
return false;
}
HookParam hp = {};
hp.address = addr;
hp.offset = pusha_eax_off - 4;
hp.type = USING_STRING | KNOWN_UNSTABLE;
hp.filter_fun = YukaSystem1Filter;
ConsoleOutput("vnreng: INSERT YukaSystem1");
NewHook(hp, "YukaSystem1");
return true;
}
bool InsertYukaSystemHooks()
{ return InsertYukaSystem1Hook() || InsertYukaSystem2Hook();}
/** jichi 8/2/2014 2RM /** jichi 8/2/2014 2RM
* Sample games: * Sample games:

View File

@ -154,7 +154,7 @@ bool InsertV8Hook(HMODULE module); // V8 JavaScript runtime: has mangled v8::Str
bool InsertUnicornHook(); // Gsen18: *.szs|Data/*.szs bool InsertUnicornHook(); // Gsen18: *.szs|Data/*.szs
bool InsertWillPlusHook(); // WillPlus: Rio.arc bool InsertWillPlusHook(); // WillPlus: Rio.arc
bool InsertWolfHook(); // Wolf: Data.wolf bool InsertWolfHook(); // Wolf: Data.wolf
bool InsertYukaSystem2Hook(); // YukaSystem2: *.ykc bool InsertYukaSystemHooks(); // YukaSystem2: *.ykc
bool InsertYurisHook(); // YU-RIS: *.ypf bool InsertYurisHook(); // YU-RIS: *.ypf
void InsertBrunsHook(); // Bruns: bruns.exe void InsertBrunsHook(); // Bruns: bruns.exe

View File

@ -410,8 +410,8 @@ bool DetermineEngineByFile4()
} }
if (Util::CheckFile(L"*.ykc")) { // jichi 7/15/2014: YukaSystem1 is not supported, though if (Util::CheckFile(L"*.ykc")) { // jichi 7/15/2014: YukaSystem1 is not supported, though
//ConsoleOutput("vnreng: IGNORE YKC:Feng/HookSoft(SMEE)"); //ConsoleOutput("vnreng: IGNORE YKC:Feng/HookSoft(SMEE)");
InsertYukaSystem2Hook(); if (InsertYukaSystemHooks())
return true; return true;
} }
if (Util::CheckFile(L"model\\*.hed")) { // jichi 9/8/2014: EXP if (Util::CheckFile(L"model\\*.hed")) { // jichi 9/8/2014: EXP
InsertExpHook(); InsertExpHook();