diff --git a/GUI/host/hookcode.cpp b/GUI/host/hookcode.cpp index 1b02273..e1118dc 100644 --- a/GUI/host/hookcode.cpp +++ b/GUI/host/hookcode.cpp @@ -88,7 +88,7 @@ namespace } HCode.erase(0, 1); - if ((hp.type & USING_STRING)) + if (hp.type & USING_STRING) { if (HCode[0] == L'F') { @@ -247,7 +247,7 @@ namespace if (hp.type & SPLIT_INDIRECT) HCode += L'*' + HexString(hp.split_index); // Attempt to make the address relative - if (processId && !(hp.type & MODULE_OFFSET)) + if (processId && !(hp.type & (MODULE_OFFSET | VIRTUALIZED))) if (AutoHandle<> process = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId)) if (MEMORY_BASIC_INFORMATION info = {}; VirtualQueryEx(process, (LPCVOID)hp.address, &info, sizeof(info))) if (auto moduleName = GetModuleFilename(processId, (HMODULE)info.AllocationBase)) diff --git a/include/const.h b/include/const.h index 4bc9ca8..64681b2 100644 --- a/include/const.h +++ b/include/const.h @@ -31,4 +31,5 @@ enum HookParamType : unsigned HOOK_ENGINE = 0x8000, HOOK_ADDITIONAL = 0x10000, KNOWN_UNSTABLE = 0x20000, + VIRTUALIZED = 0x40000, }; diff --git a/texthook/hookfinder.cc b/texthook/hookfinder.cc index a5988d5..4fda5b8 100644 --- a/texthook/hookfinder.cc +++ b/texthook/hookfinder.cc @@ -241,7 +241,8 @@ void SearchForHooks(SearchParam spUser) HookParam hp = {}; hp.offset = records[i].offset; hp.type = USING_UNICODE | USING_STRING; - hp.address = records[i].address; + if (devirtualizeAddress && (hp.address = devirtualizeAddress((void*)records[i].address))) hp.type |= VIRTUALIZED; + else hp.address = records[i].address; hp.padding = records[i].padding; hp.codepage = sp.codepage; if (sp.hookPostProcessor) sp.hookPostProcessor(hp); diff --git a/texthook/main.cc b/texthook/main.cc index 91f159a..3aca6a3 100644 --- a/texthook/main.cc +++ b/texthook/main.cc @@ -13,6 +13,8 @@ extern const char* PIPE_CONNECTED; extern const char* INSERTING_HOOK; extern const char* REMOVING_HOOK; +extern const char* FUNC_MISSING; +extern const char* MODULE_MISSING; extern const char* HOOK_FAILED; extern const char* TOO_MANY_HOOKS; @@ -132,6 +134,16 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID) MH_Initialize(); + if (HMODULE addressVirtualizer = GetModuleHandleW(L"hooker.dll")) + { + static auto virtualizeAddress = GetProcAddress(addressVirtualizer, "virtualize_address"), devirtualizeAddress = GetProcAddress(addressVirtualizer, "devirtualize_address"); + if (virtualizeAddress && devirtualizeAddress) + { + ::virtualizeAddress = [](uint32_t virtualAddress) { return std::unique_ptr>(((void** (*)(uint32_t))virtualizeAddress)(virtualAddress)); }; + ::devirtualizeAddress = (uint32_t(*)(void*))devirtualizeAddress; + } + } + CloseHandle(CreateThread(nullptr, 0, Pipe, nullptr, 0, nullptr)); // Using std::thread here = deadlock } break; @@ -145,19 +157,36 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID) return TRUE; } -void NewHook(HookParam hp, LPCSTR lpname, DWORD flag) +void NewHookImpl(HookParam hp, uint64_t address, void* realAddress, LPCSTR lpname, DWORD flag) { if (++currentHook >= MAX_HOOK) return ConsoleOutput(TOO_MANY_HOOKS); if (lpname && *lpname) strncpy_s(hp.name, lpname, HOOK_NAME_SIZE - 1); ConsoleOutput(INSERTING_HOOK, hp.name); RemoveHook(hp.address, 0); - if (!(*hooks)[currentHook].Insert(hp, flag)) + if (!(*hooks)[currentHook].Insert(hp, address, realAddress, flag)) { ConsoleOutput(HOOK_FAILED); (*hooks)[currentHook].Clear(); } } +void NewHook(HookParam hp, LPCSTR lpname, DWORD flag) +{ + auto address = hp.address; + if (hp.type & MODULE_OFFSET) // Map hook offset to real address + if (hp.type & FUNCTION_OFFSET) + if (FARPROC function = GetProcAddress(GetModuleHandleW(hp.module), hp.function)) address += (uint64_t)function; + else return ConsoleOutput(FUNC_MISSING); + else if (HMODULE moduleBase = GetModuleHandleW(hp.module)) address += (uint64_t)moduleBase; + else return ConsoleOutput(MODULE_MISSING); + if (auto realAddresses = virtualizeAddress && address < UINT32_MAX ? virtualizeAddress(address) : nullptr) + { + hp.type |= VIRTUALIZED; + for (int i = 0; realAddresses[i]; ++i) NewHookImpl(hp, address, realAddresses[i], lpname, flag); + } + else NewHookImpl(hp, address, (void*)address, lpname, flag); +} + void RemoveHook(uint64_t addr, int maxOffset) { for (auto& hook : *hooks) if (abs((long long)(hook.address - addr)) <= maxOffset) return hook.Clear(); diff --git a/texthook/main.h b/texthook/main.h index f801a52..b9d8984 100644 --- a/texthook/main.h +++ b/texthook/main.h @@ -15,6 +15,10 @@ void RemoveHook(uint64_t addr, int maxOffset = 9); inline SearchParam spDefault; +inline void UniversalFree(LPVOID address) { HeapFree(GetProcessHeap(), 0, address); } +inline std::unique_ptr>(*virtualizeAddress)(uint32_t virtualAddress) = nullptr; +inline uint32_t(*devirtualizeAddress)(void* realAddress) = nullptr; + extern "C" // minhook library { enum MH_STATUS diff --git a/texthook/texthook.cc b/texthook/texthook.cc index d2dceb7..a198ef4 100644 --- a/texthook/texthook.cc +++ b/texthook/texthook.cc @@ -7,8 +7,6 @@ #include "main.h" #include "ithsys/ithsys.h" -extern const char* FUNC_MISSING; -extern const char* MODULE_MISSING; extern const char* GARBAGE_MEMORY; extern const char* SEND_ERROR; extern const char* READ_ERROR; @@ -98,14 +96,15 @@ namespace { // unnamed // - TextHook methods - -bool TextHook::Insert(HookParam hp, DWORD set_flag) +bool TextHook::Insert(HookParam hp, uint64_t address, void* realAddress, 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; + this->address = address; + this->location = realAddress; } if (hp.type & DIRECT_READ) return InsertReadCode(); return InsertHookCode(); @@ -209,13 +208,6 @@ bool TextHook::InsertHookCode() { // jichi 9/17/2013: might raise 0xC0000005 AccessViolationException on win7 // Artikash 10/30/2018: No, I think that's impossible now that I moved to minhook - if (hp.type & MODULE_OFFSET) // Map hook offset to real address - if (hp.type & FUNCTION_OFFSET) - if (FARPROC function = GetProcAddress(GetModuleHandleW(hp.module), hp.function)) address += (uint64_t)function; - else return ConsoleOutput(FUNC_MISSING), false; - else if (HMODULE moduleBase = GetModuleHandleW(hp.module)) address += (uint64_t)moduleBase; - else return ConsoleOutput(MODULE_MISSING), false; - VirtualProtect(location, 10, PAGE_EXECUTE_READWRITE, DUMMY); void* original; MH_STATUS error; diff --git a/texthook/texthook.h b/texthook/texthook.h index f0b9ccd..0cb618c 100644 --- a/texthook/texthook.h +++ b/texthook/texthook.h @@ -25,13 +25,9 @@ class TextHook { public: HookParam hp; - union - { - uint64_t address; - void* location; - }; // Absolute address + uint64_t address; // Absolute address - bool Insert(HookParam hp, DWORD set_flag); + bool Insert(HookParam hp, uint64_t address, void* realAddress, DWORD set_flag); void Clear(); private: @@ -45,6 +41,7 @@ private: void RemoveReadCode(); volatile DWORD useCount; + void* location; HANDLE readerThread, readerEvent; bool err; BYTE trampoline[x64 ? 140 : 40];