From bc01179626bd6b35718f57c394afc12d7fd7d48c Mon Sep 17 00:00:00 2001 From: Akash Mozumdar Date: Tue, 17 Mar 2020 13:53:46 -0600 Subject: [PATCH] multiple mono hooks and fix crash --- texthook/engine/engine.cc | 11 ++--------- texthook/engine/engine.h | 9 --------- texthook/engine/match.cc | 17 ++++++++++++----- texthook/engine/match.h | 4 +--- texthook/engine/match64.cc | 6 ++---- texthook/texthook.cc | 26 ++++++++++---------------- texthook/texthook.h | 9 ++++++++- 7 files changed, 35 insertions(+), 47 deletions(-) diff --git a/texthook/engine/engine.cc b/texthook/engine/engine.cc index d4636b9..99075f5 100644 --- a/texthook/engine/engine.cc +++ b/texthook/engine/engine.cc @@ -2244,7 +2244,6 @@ void InsertRealliveHook() //ConsoleOutput("Probably Reallive. Wait for text."); ConsoleOutput("vnreng: TRIGGER Reallive"); trigger_fun = InsertRealliveDynamicHook; - SetTrigger(); } namespace { // unnamed @@ -5804,7 +5803,6 @@ bool InsertShinaHook() { int ver = GetShinaRioVersion(); if (ver >= 50) { - SetTrigger(); //trigger_fun = StackSearchingTrigger; trigger_fun = [](LPVOID funcAddr, DWORD, DWORD stack) { @@ -6003,7 +6001,6 @@ void InsertWaffleHook() } //ConsoleOutput("Probably Waffle. Wait for text."); trigger_fun = InsertWaffleDynamicHook; - SetTrigger(); //ConsoleOutput("vnreng:WAFFLE: failed"); } @@ -8595,7 +8592,6 @@ bool InsertSystemAoiDynamic() ConsoleOutput("vnreng: DYNAMIC SystemAoi"); //ConsoleOutput("Probably SoftHouseChara. Wait for text."); trigger_fun = InsertSystemAoiDynamicHook; - SetTrigger(); return true; } @@ -8882,7 +8878,6 @@ void InsertIronGameSystemHook() { //ConsoleOutput("Probably IronGameSystem. Wait for text."); trigger_fun = InsertIGSDynamicHook; - SetTrigger(); ConsoleOutput("vnreng: TRIGGER IronGameSystem"); } @@ -9519,7 +9514,6 @@ void InsertRyokuchaHook() { //ConsoleOutput("Probably Ryokucha. Wait for text."); trigger_fun = InsertRyokuchaDynamicHook; - SetTrigger(); ConsoleOutput("vnreng: TRIGGER Ryokucha"); } @@ -16719,7 +16713,7 @@ void InsertMonoHook(HMODULE h) if (!getDomain || !getName || !getJitInfo) goto failed; static auto domain = getDomain(); if (!domain) goto failed; - ConsoleOutput("Textractor: Mono Dynamic ENTER (hook = %s)", loadedConfig ? loadedConfig : "brute force"); + ConsoleOutput("Textractor: Mono Dynamic ENTER (hooks = %s)", loadedConfig ? loadedConfig : "brute force"); const BYTE prolog[] = { 0x55, 0x8b, 0xec }; for (auto addr : Util::SearchMemory(prolog, sizeof(prolog), PAGE_EXECUTE_READWRITE)) { @@ -16729,7 +16723,7 @@ void InsertMonoHook(HMODULE h) { if (getJitInfo(domain, addr)) if (char* name = getName(addr)) - if ((!loadedConfig && strstr(name, "string:") && !strstr(name, "string:mem")) || (loadedConfig && strstr(name, loadedConfig))) + if (ShouldMonoHook(name)) { HookParam hp = {}; hp.address = addr; @@ -16758,7 +16752,6 @@ void InsertMonoHook(HMODULE h) ConsoleOutput("Textractor: Mono Dynamic failed"); return true; }; - SetTrigger(); } /** jichi 12/26/2014 Mono diff --git a/texthook/engine/engine.h b/texthook/engine/engine.h index 1d55603..0f9f4a2 100644 --- a/texthook/engine/engine.h +++ b/texthook/engine/engine.h @@ -16,15 +16,6 @@ extern wchar_t *processName, // cached processPath[MAX_PATH]; // cached inline const char *requestedEngine = nullptr, *loadedConfig = nullptr; -// Artikash 6/17/2019 TODO: These have the wrong values on x64 -/** jichi 12/24/2014 - * @param addr function address - * @param frame real address of the function, supposed to be the same as addr - * @param stack address of current stack - 4 - * @return If success, which is reverted - */ -inline bool (*trigger_fun)(LPVOID addr, DWORD frame, DWORD stack); - bool InsertMonoHooks(); // Mono // Wii engines diff --git a/texthook/engine/match.cc b/texthook/engine/match.cc index 7643153..8f18c1a 100644 --- a/texthook/engine/match.cc +++ b/texthook/engine/match.cc @@ -33,11 +33,6 @@ namespace Engine return found; } - DWORD InsertDynamicHook(LPVOID addr, DWORD frame, DWORD stack) - { - return trigger_fun ? !trigger_fun(addr, frame, stack) : 0; - } - void Hijack() { static auto _ = [] @@ -56,6 +51,7 @@ namespace Engine ConsoleOutput("Textractor: Engine = %s", requestedEngine = configFileData + 7); } else loadedConfig = configFileData; + if (loadedConfig && !*loadedConfig) loadedConfig = nullptr; } processStartAddress = processStopAddress = (uintptr_t)GetModuleHandleW(nullptr); @@ -74,4 +70,15 @@ namespace Engine return NULL; }(); } + + bool ShouldMonoHook(const char* name) + { + if (!loadedConfig) return strstr(name, "string:") && !strstr(name, "string:mem"); + for (const char* hook = loadedConfig; hook; hook = strchr(hook + 1, '\t')) + for (auto start = name; *start; ++start) + for (int i = 0; ; ++i) + if (start[i] != hook[i + 1]) break; + else if (!hook[i + 2] || hook[i + 2] == '\t') return true; + return false; + } } diff --git a/texthook/engine/match.h b/texthook/engine/match.h index b37e8a3..cb870f4 100644 --- a/texthook/engine/match.h +++ b/texthook/engine/match.h @@ -13,10 +13,8 @@ namespace Engine { // jichi 10/21/2014: Return whether found the engine void Hijack(); -void terminate(); -// jichi 10/21/2014: Return 0 if failed -DWORD InsertDynamicHook(LPVOID addr, DWORD frame, DWORD stack); +bool ShouldMonoHook(const char* name); } // namespace Engine diff --git a/texthook/engine/match64.cc b/texthook/engine/match64.cc index fc61a31..a390d16 100644 --- a/texthook/engine/match64.cc +++ b/texthook/engine/match64.cc @@ -80,7 +80,7 @@ namespace Engine if (!getDomain || !getName || !getJitInfo) goto failed; static auto domain = getDomain(); if (!domain) goto failed; - ConsoleOutput("Textractor: Mono Dynamic ENTER (hook = %s)", loadedConfig ? loadedConfig : "brute force"); + ConsoleOutput("Textractor: Mono Dynamic ENTER (hooks = %s)", loadedConfig ? loadedConfig : "brute force"); const BYTE prolog1[] = { 0x55, 0x48, 0x8b, 0xec }; const BYTE prolog2[] = { 0x48, 0x83, 0xec }; for (auto [prolog, size] : Array{ { prolog1, sizeof(prolog1) }, { prolog2, sizeof(prolog2) } }) @@ -92,8 +92,7 @@ namespace Engine { if (getJitInfo(domain, addr)) if (char* name = getName(addr)) - if ((!loadedConfig && strstr(name, "string:") && strstr(name, "+ 0x0") && !strstr(name, "string:mem")) || - loadedConfig && strstr(name, loadedConfig) && strstr(name, "+ 0x0")) + if (strstr(name, "0x0") && ShouldMonoHook(name)) { HookParam hp = {}; hp.address = addr; @@ -126,7 +125,6 @@ namespace Engine ConsoleOutput("Textractor: Mono Dynamic failed"); return true; }; - SetTrigger(); return ret; } diff --git a/texthook/texthook.cc b/texthook/texthook.cc index a41a399..a5ee808 100644 --- a/texthook/texthook.cc +++ b/texthook/texthook.cc @@ -5,7 +5,6 @@ #include "texthook.h" #include "main.h" -#include "engine/match.h" #include "ithsys/ithsys.h" extern const char* FUNC_MISSING; @@ -93,27 +92,22 @@ namespace { // unnamed int this_offset = 50, send_offset = 60, original_offset = 126; #endif - bool trigger = false; - enum { TEXT_BUFFER_SIZE = PIPE_BUFFER_SIZE - sizeof(ThreadParam) }; } // unnamed namespace -void SetTrigger() -{ - trigger = true; -} - // - TextHook methods - bool TextHook::Insert(HookParam hp, DWORD set_flag) { - std::scoped_lock lock(viewMutex); - hp.type |= set_flag; - if (hp.type & USING_UTF8) hp.codepage = CP_UTF8; - this->hp = hp; - address = hp.address; + { + std::scoped_lock lock(viewMutex); + hp.type |= set_flag; + if (hp.type & USING_UTF8) hp.codepage = CP_UTF8; + this->hp = hp; + address = hp.address; + } if (hp.type & DIRECT_READ) return InsertReadCode(); - else return InsertHookCode(); + return InsertHookCode(); } // jichi 5/11/2014: @@ -123,7 +117,8 @@ void TextHook::Send(uintptr_t dwDataBase) _InterlockedIncrement(&useCount); __try { - if (trigger) trigger = Engine::InsertDynamicHook(location, *(DWORD *)(dwDataBase - 0x1c), *(DWORD *)(dwDataBase - 0x18)); + if (auto current_trigger_fun = trigger_fun.exchange(nullptr)) + if (!current_trigger_fun(location, *(DWORD*)(dwDataBase - 0x1c), *(DWORD*)(dwDataBase - 0x18))) trigger_fun = current_trigger_fun; #ifndef _WIN64 DWORD dwCount = 0, @@ -131,7 +126,6 @@ void TextHook::Send(uintptr_t dwDataBase) dwDataIn = *(DWORD*)(dwDataBase + hp.offset), // default values dwRetn = *(DWORD*)dwDataBase; // first value on stack (if hooked start of function, this is return address) - // jichi 10/24/2014: generic hook function if (hp.hook_fun && !hp.hook_fun(dwDataBase, &hp)) hp.hook_fun = nullptr; diff --git a/texthook/texthook.h b/texthook/texthook.h index c609174..75c70ca 100644 --- a/texthook/texthook.h +++ b/texthook/texthook.h @@ -10,7 +10,14 @@ #include "common.h" #include "types.h" -void SetTrigger(); +// Artikash 6/17/2019 TODO: These have the wrong values on x64 +/** jichi 12/24/2014 + * @param addr function address + * @param frame real address of the function, supposed to be the same as addr + * @param stack address of current stack - 4 + * @return If success, which is reverted + */ +inline std::atomic trigger_fun = nullptr; // jichi 9/25/2013: This class will be used by NtMapViewOfSectionfor // interprocedure communication, where constructor/destructor will NOT work.