diff --git a/GUI/host/host.cc b/GUI/host/host.cc index a497ca3..28825a3 100644 --- a/GUI/host/host.cc +++ b/GUI/host/host.cc @@ -234,7 +234,7 @@ namespace Host WaitForSingleObject(pr.sectionMutex, 0); const TextHook* hooks = (const TextHook*)pr.sectionMap; for (int i = 0; i < MAX_HOOK; ++i) - if (hooks[i].hp.address == addr) + if (hooks[i].hp.insertion_address == addr) ret = hooks[i].hp; ReleaseMutex(pr.sectionMutex); return ret; @@ -252,7 +252,7 @@ namespace Host WaitForSingleObject(pr.sectionMutex, 0); const TextHook* hooks = (const TextHook*)pr.sectionMap; for (int i = 0; i < MAX_HOOK; ++i) - if (hooks[i].hp.address == addr) + if (hooks[i].hp.insertion_address == addr) { buffer.resize(hooks[i].name_length); ReadProcessMemory(pr.processHandle, hooks[i].hook_name, buffer.data(), hooks[i].name_length, nullptr); diff --git a/GUI/mainwindow.cpp b/GUI/mainwindow.cpp index c493544..0d30f01 100644 --- a/GUI/mainwindow.cpp +++ b/GUI/mainwindow.cpp @@ -157,7 +157,7 @@ std::unordered_map MainWindow::GetInfoForExtensions(TextTh QVector MainWindow::GetAllHooks(DWORD processId) { - QSet addresses; + QSet addresses; QVector hooks; for (int i = 0; i < ttCombo->count(); ++i) { @@ -208,13 +208,13 @@ void MainWindow::on_unhookButton_clicked() QStringList hookList; for (auto hook : hooks) hookList.push_back( - QString::fromStdWString(Host::GetHookName(GetSelectedProcessId(), hook.address)) + + QString::fromStdWString(Host::GetHookName(GetSelectedProcessId(), hook.insertion_address)) + ": " + GenerateCode(hook, GetSelectedProcessId()) ); bool ok; QString hook = QInputDialog::getItem(this, "Unhook", "Which hook to remove?", hookList, 0, false, &ok); - if (ok) Host::RemoveHook(GetSelectedProcessId(), hooks.at(hookList.indexOf(hook)).address); + if (ok) Host::RemoveHook(GetSelectedProcessId(), hooks.at(hookList.indexOf(hook)).insertion_address); } void MainWindow::on_saveButton_clicked() diff --git a/GUI/misc.cpp b/GUI/misc.cpp index 545a4c9..4ec1247 100644 --- a/GUI/misc.cpp +++ b/GUI/misc.cpp @@ -1,7 +1,7 @@ #include "misc.h" #include "const.h" -#include #include +#include QString GetFullModuleName(DWORD processId, HMODULE module) { @@ -32,18 +32,12 @@ QMultiHash GetAllProcesses() namespace { - DWORD Hash(QString module) - { - module = module.toLower(); - DWORD hash = 0; - for (auto i : module) hash = _rotr(hash, 7) + i.unicode(); - return hash; - } - std::optional ParseRCode(QString RCode) { HookParam hp = {}; hp.type |= DIRECT_READ; + + // {S|Q|V} switch (RCode.at(0).unicode()) { case L'S': @@ -58,25 +52,32 @@ namespace return {}; } RCode.remove(0, 1); - if (RCode.at(0).unicode() == L'0') RCode.remove(0, 1); - QRegExp stringGap("^\\*(\\-?[\\dA-F]+)"); - if (stringGap.indexIn(RCode) != -1) + + // [*deref_offset|0] + if (RCode.at(0).unicode() == L'0') RCode.remove(0, 1); // Legacy + QRegularExpressionMatch deref = QRegularExpression("^\\*(\\-?[[:xdigit:]]+)").match(RCode); + if (deref.hasMatch()) { - hp.index = stringGap.cap(1).toInt(nullptr, 16); - RCode.remove(0, stringGap.cap(0).length()); hp.type |= DATA_INDIRECT; + hp.index = deref.captured(1).toInt(nullptr, 16); + RCode.remove(0, deref.captured(0).length()); } + if (RCode.at(0).unicode() != L'@') return {}; RCode.remove(0, 1); - QRegExp address("[\\dA-F]+$"); - if (address.indexIn(RCode) == -1) return {}; - hp.address = address.cap(0).toULongLong(nullptr, 16); + + // @addr + QRegularExpressionMatch address = QRegularExpression("^@([[:xdigit:]]+)$").match(RCode); + if (!address.hasMatch()) return {}; + hp.address = address.captured(1).toULongLong(nullptr, 16); return hp; } std::optional ParseHCode(QString HCode) { HookParam hp = {}; + + // {A|B|W|S|Q|V} switch (HCode.at(0).unicode()) { case L'S': @@ -103,139 +104,141 @@ namespace return {}; } HCode.remove(0, 1); + + // [N] if (HCode.at(0).unicode() == L'N') { hp.type |= NO_CONTEXT; HCode.remove(0, 1); } - QRegExp dataOffset("^\\-?[\\dA-F]+"); - if (dataOffset.indexIn(HCode) == -1) return {}; - hp.offset = dataOffset.cap(0).toInt(nullptr, 16); - HCode.remove(0, dataOffset.cap(0).length()); - QRegExp dataIndirect("^\\*(\\-?[\\dA-F]+)"); - if (dataIndirect.indexIn(HCode) != -1) + + // data_offset + QRegularExpressionMatch dataOffset = QRegularExpression("^\\-?[[:xdigit:]]+").match(HCode); + if (!dataOffset.hasMatch()) return {}; + hp.offset = dataOffset.captured(0).toInt(nullptr, 16); + HCode.remove(0, dataOffset.captured(0).length()); + + // [*deref_offset1] + QRegularExpressionMatch deref1 = QRegularExpression("^\\*(\\-?[[:xdigit:]]+)").match(HCode); + if (deref1.hasMatch()) { hp.type |= DATA_INDIRECT; - hp.index = dataIndirect.cap(1).toInt(nullptr, 16); - HCode.remove(0, dataIndirect.cap(0).length()); + hp.index = deref1.captured(1).toInt(nullptr, 16); + HCode.remove(0, deref1.captured(0).length()); } - QRegExp split("^\\:(\\-?[\\dA-F]+)"); - if (split.indexIn(HCode) != -1) + + // [:split_offset[*deref_offset2]] + QRegularExpressionMatch splitOffset = QRegularExpression("^\\:(\\-?[[:xdigit:]]+)").match(HCode); + if (splitOffset.hasMatch()) { hp.type |= USING_SPLIT; - hp.split = split.cap(1).toInt(nullptr, 16); - HCode.remove(0, split.cap(0).length()); - QRegExp splitIndirect("^\\*(\\-?[\\dA-F]+)"); - if (splitIndirect.indexIn(HCode) != -1) + hp.split = splitOffset.captured(1).toInt(nullptr, 16); + HCode.remove(0, splitOffset.captured(0).length()); + + QRegularExpressionMatch deref2 = QRegularExpression("^\\*(\\-?[[:xdigit:]]+)").match(HCode); + if (deref2.hasMatch()) { hp.type |= SPLIT_INDIRECT; - hp.split_index = splitIndirect.cap(1).toInt(nullptr, 16); - HCode.remove(0, splitIndirect.cap(0).length()); + hp.split_index = deref2.captured(1).toInt(nullptr, 16); + HCode.remove(0, deref2.captured(0).length()); } } - if (HCode.at(0).unicode() != L'@') return {}; - HCode.remove(0, 1); - QRegExp address("^([\\dA-F]+):?"); - if (address.indexIn(HCode) == -1) return {}; - hp.address = address.cap(1).toULongLong(nullptr, 16); - HCode.remove(address.cap(0)); - if (HCode.length()) + + // @addr[:module[:func]] + QStringList addressPieces = HCode.split(":"); + QRegularExpressionMatch address = QRegularExpression("^@([[:xdigit:]]+)$").match(addressPieces.at(0)); + if (!address.hasMatch()) return {}; + hp.address = address.captured(1).toULongLong(nullptr, 16); + if (addressPieces.size() > 1) { hp.type |= MODULE_OFFSET; - hp.module = Hash(HCode); + wcscpy_s(hp.module, addressPieces.at(1).toStdWString().c_str()); } - if (hp.offset < 0) - hp.offset -= 4; - if (hp.split < 0) - hp.split -= 4; + if (addressPieces.size() > 2) + { + hp.type |= FUNCTION_OFFSET; + strcpy_s(hp.function, addressPieces.at(2).toStdString().c_str()); + } + + // ITH has registers offset by 4 vs AGTH: need this to correct + if (hp.offset < 0) hp.offset -= 4; + if (hp.split < 0) hp.split -= 4; + return hp; } QString GenerateHCode(HookParam hp, DWORD processId) { - QString code = "/H"; + QString HCode = "/H"; + QTextStream codeBuilder(&HCode); + codeBuilder.setIntegerBase(16); + codeBuilder.setNumberFlags(QTextStream::UppercaseDigits); + if (hp.type & USING_UNICODE) { - if (hp.type & USING_STRING) - code += "Q"; - else - code += "W"; + if (hp.type & USING_STRING) codeBuilder << "Q"; + else codeBuilder << "W"; } else { - if (hp.type & USING_UTF8) - code += "V"; - else if (hp.type & USING_STRING) - code += "S"; - else if (hp.type & BIG_ENDIAN) - code += "A"; - else - code += "B"; + if (hp.type & USING_UTF8) codeBuilder << "V"; + else if (hp.type & USING_STRING) codeBuilder << "S"; + else if (hp.type & BIG_ENDIAN) codeBuilder << "A"; + else codeBuilder << "B"; } - if (hp.type & NO_CONTEXT) - code += "N"; + if (hp.type & NO_CONTEXT) codeBuilder << "N"; + if (hp.offset < 0) hp.offset += 4; if (hp.split < 0) hp.split += 4; - if (hp.offset < 0) - code += "-" + QString::number(-hp.offset, 16); - else - code += QString::number(hp.offset, 16); - if (hp.type & DATA_INDIRECT) + + codeBuilder << hp.offset; + if (hp.type & DATA_INDIRECT) codeBuilder << "*" << hp.index; + if (hp.type & USING_SPLIT) codeBuilder << ":" << hp.split; + if (hp.type & SPLIT_INDIRECT) codeBuilder << "*" << hp.split_index; + + // Attempt to make the address relative + if (!(hp.type & MODULE_OFFSET)) { - if (hp.index < 0) - code += "*-" + QString::number(-hp.index, 16); - else - code += "*" + QString::number(hp.index, 16); + HANDLE processHandle; + if (!(processHandle = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId))) goto fin; + MEMORY_BASIC_INFORMATION info; + if (!VirtualQueryEx(processHandle, (LPCVOID)hp.address, &info, sizeof(info))) goto fin; + QString moduleName = GetModuleName(processId, (HMODULE)info.AllocationBase); + if (moduleName.size() == 0) goto fin; + hp.type |= MODULE_OFFSET; + hp.address -= (uint64_t)info.AllocationBase; + wcscpy_s(hp.module, moduleName.toStdWString().c_str()); } - if (hp.type & USING_SPLIT) - { - if (hp.split < 0) - code += ":-" + QString::number(-hp.split, 16); - else - code += ":" + QString::number(hp.split, 16); - } - if (hp.type & SPLIT_INDIRECT) - { - if (hp.split_index < 0) - code += "*-" + QString::number(-hp.split_index, 16); - else - code += "*" + QString::number(hp.split_index, 16); - } - code += "@"; - QString badCode = (code + QString::number(hp.address, 16)).toUpper(); - HANDLE processHandle; - if (!(processHandle = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId))) return badCode; - MEMORY_BASIC_INFORMATION info; - if (!VirtualQueryEx(processHandle, (LPCVOID)hp.address, &info, sizeof(info))) return badCode; - QString moduleName = GetModuleName(processId, (HMODULE)info.AllocationBase); - if (moduleName.size() == 0) return badCode; - code += QString::number(hp.address - (DWORD)info.AllocationBase, 16) + ":"; - code = code.toUpper(); - code += moduleName; - return code; + + fin: + codeBuilder << "@" << hp.address; + if (hp.type & MODULE_OFFSET) codeBuilder << ":" << QString::fromWCharArray(hp.module); + if (hp.type & FUNCTION_OFFSET) codeBuilder << ":" << hp.function; + + return HCode; } QString GenerateRCode(HookParam hp) { - QString code = "/R"; - if (hp.type & USING_UNICODE) - code += "Q"; - else if (hp.type & USING_UTF8) - code += "V"; - else - code += "S"; - if (hp.type & DATA_INDIRECT) - code += "*" + QString::number(hp.index, 16); - //code += QString::number(hp.offset, 16); - code += "@"; - code += QString::number(hp.address, 16); - return code.toUpper(); + QString RCode = "/R"; + QTextStream codeBuilder(&RCode); + codeBuilder.setIntegerBase(16); + codeBuilder.setNumberFlags(QTextStream::UppercaseDigits); + + if (hp.type & USING_UNICODE) codeBuilder << "Q"; + else if (hp.type & USING_UTF8) codeBuilder << "V"; + else codeBuilder << "S"; + + if (hp.type & DATA_INDIRECT) codeBuilder << "*" << hp.index; + + codeBuilder << "@" << hp.address; + + return RCode; } } std::optional ParseCode(QString code) { - code = code.toUpper(); if (code.startsWith("/H")) return ParseHCode(code.remove(0, 2)); else if (code.startsWith("/R")) return ParseRCode(code.remove(0, 2)); else return {}; diff --git a/GUI/misc.h b/GUI/misc.h index 685e278..7c701a8 100644 --- a/GUI/misc.h +++ b/GUI/misc.h @@ -13,7 +13,7 @@ QString GenerateCode(HookParam hp, DWORD processId); static QString CodeInfoDump = "Enter hook code\r\n\ -/H{A|B|W|S|Q|V}[N]data_offset[*deref_offset1][:split_offset[*deref_offset2]]@addr[:module]\r\n\ +/H{A|B|W|S|Q|V}[N]data_offset[*deref_offset1][:split_offset[*deref_offset2]]@addr[:module[:func]]\r\n\ OR\r\n\ Enter read code\r\n\ /R{S|Q|V}[*deref_offset|0]@addr\r\n\ diff --git a/include/const.h b/include/const.h index 501be38..8010f30 100644 --- a/include/const.h +++ b/include/const.h @@ -4,7 +4,7 @@ // 8/23/2013 jichi // Branch: ITH/common.h, rev 128 -enum { MESSAGE_SIZE = 500, PIPE_BUFFER_SIZE = 0x1000, SHIFT_JIS = 932, MAX_THREAD_COUNT }; +enum { MESSAGE_SIZE = 500, PIPE_BUFFER_SIZE = 0x1000, SHIFT_JIS = 932, MAX_THREAD_COUNT = 250, MAX_MODULE_SIZE = 120 }; // jichi 375/2014: Add offset of pusha/pushad // http://faydoc.tripod.com/cpu/pushad.htm @@ -50,8 +50,8 @@ enum HookParamType : unsigned long DATA_INDIRECT = 0x8, USING_SPLIT = 0x10, // aware of split time? SPLIT_INDIRECT = 0x20, - MODULE_OFFSET = 0x40, // do hash module, and the address is relative to module - //FUNCTION_OFFSET = 0x80, // do hash function, and the address is relative to funccion + MODULE_OFFSET = 0x40, // address is relative to module + FUNCTION_OFFSET = 0x80, // address is relative to function USING_UTF8 = 0x100, NO_CONTEXT = 0x400, HOOK_EMPTY = 0x800, diff --git a/include/types.h b/include/types.h index 8cbc503..98d6349 100644 --- a/include/types.h +++ b/include/types.h @@ -11,12 +11,14 @@ struct HookParam typedef bool(*filter_fun_t)(LPVOID str, DWORD *len, HookParam *hp, BYTE index); // jichi 10/24/2014: Add filter function. Return true if skip the text typedef bool(*hook_fun_t)(DWORD esp, HookParam *hp); // jichi 10/24/2014: Add generic hook function, return false if stop execution. - uint64_t address; // absolute or relative address + uint64_t insertion_address; // absolute address + uint64_t address; // absolute or relative address (not changed by TextHook) int offset, // offset of the data in the memory index, // deref_offset1 split, // offset of the split character split_index; // deref_offset2 - DWORD module; // hash of the module + wchar_t module[MAX_MODULE_SIZE]; + char function[MAX_MODULE_SIZE]; DWORD type; // flags WORD length_offset; // index of the string length DWORD user_value; // 7/20/2014: jichi additional parameters for PSP games @@ -24,8 +26,6 @@ struct HookParam text_fun_t text_fun; filter_fun_t filter_fun; hook_fun_t hook_fun; - - HANDLE readerHandle; // Artikash 8/4/2018: handle for reader thread }; struct ThreadParam // From hook, used internally by host as well diff --git a/vnrhook/hijack/texthook.cc b/vnrhook/hijack/texthook.cc index 4ab5d6a..4bdd36f 100644 --- a/vnrhook/hijack/texthook.cc +++ b/vnrhook/hijack/texthook.cc @@ -40,29 +40,6 @@ namespace { // unnamed 0xe9 // jmp @original }; - DWORD Hash(std::wstring module) - { - DWORD hash = 0; - for (auto i : module) hash = _rotr(hash, 7) + i; - return hash; - } - - //copy original instruction - //jmp back - DWORD GetModuleBase(DWORD hash) - { - HMODULE allModules[1000]; - DWORD size; - EnumProcessModules(GetCurrentProcess(), allModules, sizeof(allModules), &size); - wchar_t name[MAX_PATH]; - for (int i = 0; i < size / sizeof(HMODULE); ++i) - { - GetModuleFileNameW(allModules[i], name, MAX_PATH); - _wcslwr(name); - if (Hash(wcsrchr(name, L'\\') + 1) == hash) return (DWORD)allModules[i]; - } - return 0; - } __declspec(naked) // jichi 10/2/2013: No prolog and epilog int ProcessHook(DWORD dwDataBase, DWORD dwRetn, TextHook *hook) // Use SEH to ensure normal execution even bad hook inserted. @@ -76,6 +53,7 @@ namespace { // unnamed retn // jichi 12/13/2013: return near, see: http://stackoverflow.com/questions/1396909/ret-retn-retf-how-to-use-them } } + #else const BYTE common_hook[] = { 0x9c, // push rflags @@ -160,7 +138,7 @@ DWORD TextHook::UnsafeSend(DWORD dwDataBase, DWORD dwRetn) BYTE pbData[PIPE_BUFFER_SIZE]; DWORD dwType = hp.type; - dwAddr = hp.address; + dwAddr = hp.insertion_address; /** jichi 12/24/2014 * @param addr function address @@ -254,19 +232,19 @@ bool TextHook::InsertHookCode() bool TextHook::UnsafeInsertHookCode() { - if (hp.module && (hp.type & MODULE_OFFSET)) // Map hook offset to real address. - { - if (DWORD base = GetModuleBase(hp.module)) hp.address += base; + 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)) hp.insertion_address += (uint64_t)function; + else return ConsoleOutput("Textractor: UnsafeInsertHookCode: FAILED: function not present"), false; + else if (HMODULE moduleBase = GetModuleHandleW(hp.module)) hp.insertion_address += (uint64_t)moduleBase; else return ConsoleOutput("Textractor: UnsafeInsertHookCode: FAILED: module not present"), false; - hp.type &= ~MODULE_OFFSET; - } BYTE* original; insert: - if (MH_STATUS err = MH_CreateHook((void*)hp.address, (void*)trampoline, (void**)&original)) + if (MH_STATUS err = MH_CreateHook((void*)hp.insertion_address, (void*)trampoline, (void**)&original)) if (err == MH_ERROR_ALREADY_CREATED) { - RemoveHook(hp.address); + RemoveHook(hp.insertion_address); goto insert; // FIXME: i'm too lazy to do this properly right now... } else @@ -293,7 +271,7 @@ bool TextHook::UnsafeInsertHookCode() //memcpy(trampoline + 46, &sendPtr, sizeof(sendPtr)); //memcpy(trampoline + sizeof(common_hook) - 8, &original, sizeof(void*)); - if (MH_EnableHook((void*)hp.address) != MH_OK) return false; + if (MH_EnableHook((void*)hp.insertion_address) != MH_OK) return false; return true; } @@ -305,15 +283,15 @@ DWORD WINAPI ReaderThread(LPVOID hookPtr) BYTE buffer[PIPE_BUFFER_SIZE] = {}; unsigned int changeCount = 0; int dataLen = 0; - const void* currentAddress = (void*)hook->hp.address; + const void* currentAddress = (void*)hook->hp.insertion_address; while (true) { - if (!IthGetMemoryRange((void*)hook->hp.address, nullptr, nullptr)) + if (!IthGetMemoryRange((void*)hook->hp.insertion_address, nullptr, nullptr)) { ConsoleOutput("Textractor: can't read desired address"); break; } - if (hook->hp.type & DATA_INDIRECT) currentAddress = *((char**)hook->hp.address + hook->hp.index); + if (hook->hp.type & DATA_INDIRECT) currentAddress = *((char**)hook->hp.insertion_address + hook->hp.index); if (!IthGetMemoryRange(currentAddress, nullptr, nullptr)) { ConsoleOutput("Textractor: can't read desired address"); @@ -336,7 +314,7 @@ DWORD WINAPI ReaderThread(LPVOID hookPtr) else dataLen = strlen((const char*)currentAddress); - *(ThreadParam*)buffer = { GetCurrentProcessId(), hook->hp.address, 0, 0 }; + *(ThreadParam*)buffer = { GetCurrentProcessId(), hook->hp.insertion_address, 0, 0 }; memcpy(buffer + sizeof(ThreadParam), currentAddress, dataLen + 1); DWORD unused; WriteFile(::hookPipe, buffer, dataLen + sizeof(ThreadParam), &unused, nullptr); @@ -349,7 +327,7 @@ DWORD WINAPI ReaderThread(LPVOID hookPtr) bool TextHook::InsertReadCode() { //RemoveHook(hp.address); // Artikash 8/25/2018: clear existing - hp.readerHandle = CreateThread(nullptr, 0, ReaderThread, this, 0, nullptr); + readerHandle = CreateThread(nullptr, 0, ReaderThread, this, 0, nullptr); return true; } @@ -357,6 +335,7 @@ void TextHook::InitHook(const HookParam &h, LPCSTR name, WORD set_flag) { WaitForSingleObject(hmMutex, 0); hp = h; + hp.insertion_address = hp.address; hp.type |= set_flag; if (name && name != hook_name) SetHookName(name); ReleaseMutex(hmMutex); @@ -364,14 +343,14 @@ void TextHook::InitHook(const HookParam &h, LPCSTR name, WORD set_flag) void TextHook::RemoveHookCode() { - MH_DisableHook((void*)hp.address); - MH_RemoveHook((void*)hp.address); + MH_DisableHook((void*)hp.insertion_address); + MH_RemoveHook((void*)hp.insertion_address); } void TextHook::RemoveReadCode() { - TerminateThread(hp.readerHandle, 0); - CloseHandle(hp.readerHandle); + TerminateThread(readerHandle, 0); + CloseHandle(readerHandle); } void TextHook::ClearHook() @@ -380,7 +359,7 @@ void TextHook::ClearHook() if (hook_name) ConsoleOutput(("Textractor: removing hook: " + std::string(hook_name)).c_str()); if (hp.type & DIRECT_READ) RemoveReadCode(); else RemoveHookCode(); - NotifyHookRemove(hp.address); + NotifyHookRemove(hp.insertion_address); if (hook_name) delete[] hook_name; memset(this, 0, sizeof(TextHook)); // jichi 11/30/2013: This is the original code of ITH ReleaseMutex(hmMutex); diff --git a/vnrhook/hijack/texthook.h b/vnrhook/hijack/texthook.h index b5d6a49..6f3d666 100644 --- a/vnrhook/hijack/texthook.h +++ b/vnrhook/hijack/texthook.h @@ -30,6 +30,7 @@ public: LPSTR hook_name; int name_length; BYTE trampoline[120]; + HANDLE readerHandle; bool InsertHook(); void InitHook(const HookParam &hp, LPCSTR name = 0, WORD set_flag = 0); diff --git a/vnrhook/main.cc b/vnrhook/main.cc index d12140c..2f6a4a4 100644 --- a/vnrhook/main.cc +++ b/vnrhook/main.cc @@ -49,7 +49,7 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID) { ::running = false; MH_Uninitialize(); - for (TextHook *man = ::hookman; man < ::hookman + MAX_HOOK; man++) if (man->hp.address) man->ClearHook(); + for (TextHook *man = ::hookman; man < ::hookman + MAX_HOOK; man++) if (man->hp.insertion_address) man->ClearHook(); //if (ith_has_section) UnmapViewOfFile(::hookman); @@ -83,7 +83,7 @@ void NewHook(const HookParam &hp, LPCSTR lpname, DWORD flag) void RemoveHook(uint64_t addr) { for (int i = 0; i < MAX_HOOK; i++) - if (abs((long long)(::hookman[i].hp.address - addr)) < 9) + if (abs((long long)(::hookman[i].hp.insertion_address - addr)) < 9) { ::hookman[i].ClearHook(); return;