From 20956f6412393f598689f223f45a8c5274bc9365 Mon Sep 17 00:00:00 2001 From: Akash Mozumdar Date: Wed, 12 Sep 2018 23:50:02 -0400 Subject: [PATCH] update hook for v8 runtime/javascript/tyranobuilder --- vnrhook/engine/engine.cc | 136 ++++++++++++++++++++++++++------------- vnrhook/engine/engine.h | 2 +- vnrhook/engine/match.cc | 4 +- 3 files changed, 94 insertions(+), 48 deletions(-) diff --git a/vnrhook/engine/engine.cc b/vnrhook/engine/engine.cc index 5acace4..36cd949 100644 --- a/vnrhook/engine/engine.cc +++ b/vnrhook/engine/engine.cc @@ -10163,60 +10163,106 @@ bool InsertNexton1Hook() /** * Artikash 7/15/2018: Insert Tyranobuilder hook * Sample game: https://vndb.org/v22252: /HWN-8:-1C@233A54:yuika_t.exe - Issue with hook: many garbage text threads. Maybe use another split? - - yuika_t.v8::Locker::IsLocked+2B57 - 56 - push esi - yuika_t.v8::Locker::IsLocked+2B58 - 8B F3 - mov esi,ebx - yuika_t.v8::Locker::IsLocked+2B5A - 33 C0 - xor eax,eax - yuika_t.v8::Locker::IsLocked+2B5C - 2B F7 - sub esi,edi - yuika_t.v8::Locker::IsLocked+2B5E - 33 D2 - xor edx,edx - yuika_t.v8::Locker::IsLocked+2B60 - 46 - inc esi - yuika_t.v8::Locker::IsLocked+2B61 - D1 EE - shr esi,1 - yuika_t.v8::Locker::IsLocked+2B63 - 3B FB - cmp edi,ebx - yuika_t.v8::Locker::IsLocked+2B65 - 0F47 F0 - cmova esi,eax - yuika_t.v8::Locker::IsLocked+2B68 - 85 F6 - test esi,esi - yuika_t.v8::Locker::IsLocked+2B6A - 74 15 - je yuika_t.v8::Locker::IsLocked+2B81 - yuika_t.v8::Locker::IsLocked+2B6C - 8B 45 0C - mov eax,[ebp+0C] - yuika_t.v8::Locker::IsLocked+2B6F - 2B F8 - sub edi,eax - yuika_t.v8::Locker::IsLocked+2B71 - 66 8B 08 - mov cx,[eax]; Moves a wchar into ecx. - yuika_t.v8::Locker::IsLocked+2B74 - 8D 40 02 - lea eax,[eax+02]; Hook here! - yuika_t.v8::Locker::IsLocked+2B77 - 42 - inc edx - yuika_t.v8::Locker::IsLocked+2B78 - 66 89 4C 07 FE - mov [edi+eax-02],cx - yuika_t.v8::Locker::IsLocked+2B7D - 3B D6 - cmp edx,esi; esi holds string length. best split I can find but not ideal... - yuika_t.v8::Locker::IsLocked+2B7F - 72 F0 - jb yuika_t.v8::Locker::IsLocked+2B71 - yuika_t.v8::Locker::IsLocked+2B81 - 5E - pop esi - yuika_t.v8::Locker::IsLocked+2B82 - 5F - pop edi - yuika_t.v8::Locker::IsLocked+2B83 - 5B - pop ebx - yuika_t.v8::Locker::IsLocked+2B84 - 5D - pop ebp - yuika_t.v8::Locker::IsLocked+2B85 - C3 - ret - - +* Artikash 9/11/2018: This is more than just Tyranobuilder. It's actually a hook for the V8 JavaScript runtime +* Sample game: https://www.freem.ne.jp/win/game/9672: /HQ8@2317A0:Prison.exe This new hook seems more reliable +* Issue with hook: many garbage text threads. Maybe use another split? +* +* yuika_t.v8::Locker::IsLocked+2B57 - 56 - push esi +* yuika_t.v8::Locker::IsLocked+2B58 - 8B F3 - mov esi,ebx +* yuika_t.v8::Locker::IsLocked+2B5A - 33 C0 - xor eax,eax +* yuika_t.v8::Locker::IsLocked+2B5C - 2B F7 - sub esi,edi +* yuika_t.v8::Locker::IsLocked+2B5E - 33 D2 - xor edx,edx +* yuika_t.v8::Locker::IsLocked+2B60 - 46 - inc esi +* yuika_t.v8::Locker::IsLocked+2B61 - D1 EE - shr esi,1 +* yuika_t.v8::Locker::IsLocked+2B63 - 3B FB - cmp edi,ebx +* yuika_t.v8::Locker::IsLocked+2B65 - 0F47 F0 - cmova esi,eax +* yuika_t.v8::Locker::IsLocked+2B68 - 85 F6 - test esi,esi +* yuika_t.v8::Locker::IsLocked+2B6A - 74 15 - je yuika_t.v8::Locker::IsLocked+2B81 +* yuika_t.v8::Locker::IsLocked+2B6C - 8B 45 0C - mov eax,[ebp+0C] +* yuika_t.v8::Locker::IsLocked+2B6F - 2B F8 - sub edi,eax +* yuika_t.v8::Locker::IsLocked+2B71 - 66 8B 08 - mov cx,[eax]; Moves a wchar into ecx. +* yuika_t.v8::Locker::IsLocked+2B74 - 8D 40 02 - lea eax,[eax+02]; Hook here! +* yuika_t.v8::Locker::IsLocked+2B77 - 42 - inc edx +* yuika_t.v8::Locker::IsLocked+2B78 - 66 89 4C 07 FE - mov [edi+eax-02],cx +* yuika_t.v8::Locker::IsLocked+2B7D - 3B D6 - cmp edx,esi; esi holds string length. best split I can find but not ideal... +* yuika_t.v8::Locker::IsLocked+2B7F - 72 F0 - jb yuika_t.v8::Locker::IsLocked+2B71 +* yuika_t.v8::Locker::IsLocked+2B81 - 5E - pop esi +* yuika_t.v8::Locker::IsLocked+2B82 - 5F - pop edi +* yuika_t.v8::Locker::IsLocked+2B83 - 5B - pop ebx +* yuika_t.v8::Locker::IsLocked+2B84 - 5D - pop ebp +* yuika_t.v8::Locker::IsLocked+2B85 - C3 - ret +* +* Prison.v8::Locker::IsLocked+2B30 - 55 - push ebp +* Prison.v8::Locker::IsLocked+2B31 - 8B EC - mov ebp,esp +* Prison.v8::Locker::IsLocked+2B33 - 8B 45 10 - mov eax,[ebp+10] +* Prison.v8::Locker::IsLocked+2B36 - 53 - push ebx +* Prison.v8::Locker::IsLocked+2B37 - 57 - push edi +* Prison.v8::Locker::IsLocked+2B38 - 8B 7D 08 - mov edi,[ebp+08] +* Prison.v8::Locker::IsLocked+2B3B - 8D 0C 00 - lea ecx,[eax+eax] +* Prison.v8::Locker::IsLocked+2B3E - 8D 1C 39 - lea ebx,[ecx+edi] +* Prison.v8::Locker::IsLocked+2B41 - 83 F8 20 - cmp eax,20 { 32 } +* Prison.v8::Locker::IsLocked+2B44 - 7C 11 - jl Prison.v8::Locker::IsLocked+2B57 +* Prison.v8::Locker::IsLocked+2B46 - 51 - push ecx +* Prison.v8::Locker::IsLocked+2B47 - FF 75 0C - push [ebp+0C] +* Prison.v8::Locker::IsLocked+2B4A - 57 - push edi +* Prison.v8::Locker::IsLocked+2B4B - E8 10DBFFFF - call Prison.v8::Locker::IsLocked+660 +* Prison.v8::Locker::IsLocked+2B50 - 83 C4 0C - add esp,0C { 12 } +* Prison.v8::Locker::IsLocked+2B53 - 5F - pop edi +* Prison.v8::Locker::IsLocked+2B54 - 5B - pop ebx +* Prison.v8::Locker::IsLocked+2B55 - 5D - pop ebp +* Prison.v8::Locker::IsLocked+2B56 - C3 - ret +* Prison.v8::Locker::IsLocked+2B57 - 56 - push esi +* Prison.v8::Locker::IsLocked+2B58 - 8B F3 - mov esi,ebx +* Prison.v8::Locker::IsLocked+2B5A - 33 C0 - xor eax,eax +* Prison.v8::Locker::IsLocked+2B5C - 2B F7 - sub esi,edi +* Prison.v8::Locker::IsLocked+2B5E - 33 D2 - xor edx,edx +* Prison.v8::Locker::IsLocked+2B60 - 46 - inc esi +* Prison.v8::Locker::IsLocked+2B61 - D1 EE - shr esi,1 +* Prison.v8::Locker::IsLocked+2B63 - 3B FB - cmp edi,ebx +* Prison.v8::Locker::IsLocked+2B65 - 0F47 F0 - cmova esi,eax +* Prison.v8::Locker::IsLocked+2B68 - 85 F6 - test esi,esi +* Prison.v8::Locker::IsLocked+2B6A - 74 15 - je Prison.v8::Locker::IsLocked+2B81 +* Prison.v8::Locker::IsLocked+2B6C - 8B 45 0C - mov eax,[ebp+0C] +* Prison.v8::Locker::IsLocked+2B6F - 2B F8 - sub edi,eax +* Prison.v8::Locker::IsLocked+2B71 - 66 8B 08 - mov cx,[eax] +* Prison.v8::Locker::IsLocked+2B74 - 8D 40 02 - lea eax,[eax+02] +* Prison.v8::Locker::IsLocked+2B77 - 42 - inc edx +* Prison.v8::Locker::IsLocked+2B78 - 66 89 4C 07 FE - mov [edi+eax-02],cx +* Prison.v8::Locker::IsLocked+2B7D - 3B D6 - cmp edx,esi +* Prison.v8::Locker::IsLocked+2B7F - 72 F0 - jb Prison.v8::Locker::IsLocked+2B71 +* Prison.v8::Locker::IsLocked+2B81 - 5E - pop esi +* Prison.v8::Locker::IsLocked+2B82 - 5F - pop edi +* Prison.v8::Locker::IsLocked+2B83 - 5B - pop ebx +* Prison.v8::Locker::IsLocked+2B84 - 5D - pop ebp +* Prison.v8::Locker::IsLocked+2B85 - C3 - ret */ -bool InsertTyranobuilderHook() +bool InsertV8Hook() { const BYTE bytes[] = { 0x2b, 0xf8, // sub edi,edx 0x66, 0x8b, 0x08, // mov cx,[eax] - 0x8d, 0x40, 0x02 // lea eax,[eax + 02]; Hook here! + 0x8d, 0x40, 0x02 // lea eax,[eax + 02] }; //DWORD addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress); - DWORD addr = Util::SearchMemory(bytes, sizeof(bytes)); - if (!addr) - { - ConsoleOutput("NextHooker: Tyranobuilder: pattern not found"); - return false; - } - HookParam hp = {}; - hp.address = addr + 5; - hp.type = USING_UNICODE | NO_CONTEXT | USING_SPLIT; - hp.length_offset = 1; - hp.offset = pusha_ecx_off - 4; - hp.split = pusha_esi_off - 4; + if(DWORD addr = Util::SearchMemory(bytes, sizeof(bytes))) + if (DWORD func = MemDbg::findEnclosingFunctionAfterInt3(addr)) + { + HookParam hp = {}; + hp.address = func; + hp.type = USING_UNICODE | USING_STRING /*| USING_SPLIT*/; + hp.length_offset = 3; // wow, this actually is useful + hp.offset = 8; + hp.split = 0xc; + + ConsoleOutput("NextHooker: INSERT JavaScript (V8)"); + NewHook(hp, "JavaScript"); + return true; + } + + ConsoleOutput("NextHooker: JavaScript: failed to find hook address"); + return false; - ConsoleOutput("NextHooker: INSERT Tyranobuilder"); - NewHook(hp, "Tyranobuilder"); - return true; } /** diff --git a/vnrhook/engine/engine.h b/vnrhook/engine/engine.h index 0f3643e..ac8f1c7 100644 --- a/vnrhook/engine/engine.h +++ b/vnrhook/engine/engine.h @@ -150,7 +150,7 @@ bool InsertTanukiHook(); // Tanuki: *.tak bool InsertTaskforce2Hook(); // Taskforce2.exe bool InsertTencoHook(); // Tenco: Check.mdx bool InsertTriangleHook(); // Triangle: Execle.exe -bool InsertTyranobuilderHook(); // Tyranobuilder: has libuv +bool InsertV8Hook(); // Tyranobuilder: has libuv bool InsertUnicornHook(); // Gsen18: *.szs|Data/*.szs bool InsertWillPlusHook(); // WillPlus: Rio.arc bool InsertWolfHook(); // Wolf: Data.wolf diff --git a/vnrhook/engine/match.cc b/vnrhook/engine/match.cc index 17f2743..43e028d 100644 --- a/vnrhook/engine/match.cc +++ b/vnrhook/engine/match.cc @@ -550,10 +550,10 @@ bool DetermineEngineOther() return true; } - // Artikash 7/16/2018: Uses node/libuv: likely Tyranobuilder - sample game https://vndb.org/v22975 + // Artikash 7/16/2018: Uses node/libuv: likely v8 - sample game https://vndb.org/v22975 if (GetProcAddress(GetModuleHandleW(nullptr), "uv_uptime") || GetModuleHandleW(L"node.dll")) { - InsertTyranobuilderHook(); + InsertV8Hook(); return true; }