implement communication with emulator for virtual addresses

This commit is contained in:
Akash Mozumdar 2020-09-08 22:19:33 -06:00
parent 93238e13ed
commit 94f5e5983e
7 changed files with 46 additions and 22 deletions

View File

@ -88,7 +88,7 @@ namespace
} }
HCode.erase(0, 1); HCode.erase(0, 1);
if ((hp.type & USING_STRING)) if (hp.type & USING_STRING)
{ {
if (HCode[0] == L'F') if (HCode[0] == L'F')
{ {
@ -247,7 +247,7 @@ namespace
if (hp.type & SPLIT_INDIRECT) HCode += L'*' + HexString(hp.split_index); if (hp.type & SPLIT_INDIRECT) HCode += L'*' + HexString(hp.split_index);
// Attempt to make the address relative // 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 (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 (MEMORY_BASIC_INFORMATION info = {}; VirtualQueryEx(process, (LPCVOID)hp.address, &info, sizeof(info)))
if (auto moduleName = GetModuleFilename(processId, (HMODULE)info.AllocationBase)) if (auto moduleName = GetModuleFilename(processId, (HMODULE)info.AllocationBase))

View File

@ -31,4 +31,5 @@ enum HookParamType : unsigned
HOOK_ENGINE = 0x8000, HOOK_ENGINE = 0x8000,
HOOK_ADDITIONAL = 0x10000, HOOK_ADDITIONAL = 0x10000,
KNOWN_UNSTABLE = 0x20000, KNOWN_UNSTABLE = 0x20000,
VIRTUALIZED = 0x40000,
}; };

View File

@ -241,7 +241,8 @@ void SearchForHooks(SearchParam spUser)
HookParam hp = {}; HookParam hp = {};
hp.offset = records[i].offset; hp.offset = records[i].offset;
hp.type = USING_UNICODE | USING_STRING; 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.padding = records[i].padding;
hp.codepage = sp.codepage; hp.codepage = sp.codepage;
if (sp.hookPostProcessor) sp.hookPostProcessor(hp); if (sp.hookPostProcessor) sp.hookPostProcessor(hp);

View File

@ -13,6 +13,8 @@
extern const char* PIPE_CONNECTED; extern const char* PIPE_CONNECTED;
extern const char* INSERTING_HOOK; extern const char* INSERTING_HOOK;
extern const char* REMOVING_HOOK; extern const char* REMOVING_HOOK;
extern const char* FUNC_MISSING;
extern const char* MODULE_MISSING;
extern const char* HOOK_FAILED; extern const char* HOOK_FAILED;
extern const char* TOO_MANY_HOOKS; extern const char* TOO_MANY_HOOKS;
@ -132,6 +134,16 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID)
MH_Initialize(); 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*[], Functor<UniversalFree>>(((void** (*)(uint32_t))virtualizeAddress)(virtualAddress)); };
::devirtualizeAddress = (uint32_t(*)(void*))devirtualizeAddress;
}
}
CloseHandle(CreateThread(nullptr, 0, Pipe, nullptr, 0, nullptr)); // Using std::thread here = deadlock CloseHandle(CreateThread(nullptr, 0, Pipe, nullptr, 0, nullptr)); // Using std::thread here = deadlock
} }
break; break;
@ -145,19 +157,36 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID)
return TRUE; 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 (++currentHook >= MAX_HOOK) return ConsoleOutput(TOO_MANY_HOOKS);
if (lpname && *lpname) strncpy_s(hp.name, lpname, HOOK_NAME_SIZE - 1); if (lpname && *lpname) strncpy_s(hp.name, lpname, HOOK_NAME_SIZE - 1);
ConsoleOutput(INSERTING_HOOK, hp.name); ConsoleOutput(INSERTING_HOOK, hp.name);
RemoveHook(hp.address, 0); RemoveHook(hp.address, 0);
if (!(*hooks)[currentHook].Insert(hp, flag)) if (!(*hooks)[currentHook].Insert(hp, address, realAddress, flag))
{ {
ConsoleOutput(HOOK_FAILED); ConsoleOutput(HOOK_FAILED);
(*hooks)[currentHook].Clear(); (*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) void RemoveHook(uint64_t addr, int maxOffset)
{ {
for (auto& hook : *hooks) if (abs((long long)(hook.address - addr)) <= maxOffset) return hook.Clear(); for (auto& hook : *hooks) if (abs((long long)(hook.address - addr)) <= maxOffset) return hook.Clear();

View File

@ -15,6 +15,10 @@ void RemoveHook(uint64_t addr, int maxOffset = 9);
inline SearchParam spDefault; inline SearchParam spDefault;
inline void UniversalFree(LPVOID address) { HeapFree(GetProcessHeap(), 0, address); }
inline std::unique_ptr<void*[], Functor<UniversalFree>>(*virtualizeAddress)(uint32_t virtualAddress) = nullptr;
inline uint32_t(*devirtualizeAddress)(void* realAddress) = nullptr;
extern "C" // minhook library extern "C" // minhook library
{ {
enum MH_STATUS enum MH_STATUS

View File

@ -7,8 +7,6 @@
#include "main.h" #include "main.h"
#include "ithsys/ithsys.h" #include "ithsys/ithsys.h"
extern const char* FUNC_MISSING;
extern const char* MODULE_MISSING;
extern const char* GARBAGE_MEMORY; extern const char* GARBAGE_MEMORY;
extern const char* SEND_ERROR; extern const char* SEND_ERROR;
extern const char* READ_ERROR; extern const char* READ_ERROR;
@ -98,14 +96,15 @@ namespace { // unnamed
// - TextHook methods - // - 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); std::scoped_lock lock(viewMutex);
hp.type |= set_flag; hp.type |= set_flag;
if (hp.type & USING_UTF8) hp.codepage = CP_UTF8; if (hp.type & USING_UTF8) hp.codepage = CP_UTF8;
this->hp = hp; this->hp = hp;
address = hp.address; this->address = address;
this->location = realAddress;
} }
if (hp.type & DIRECT_READ) return InsertReadCode(); if (hp.type & DIRECT_READ) return InsertReadCode();
return InsertHookCode(); return InsertHookCode();
@ -209,13 +208,6 @@ bool TextHook::InsertHookCode()
{ {
// jichi 9/17/2013: might raise 0xC0000005 AccessViolationException on win7 // 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 // 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); VirtualProtect(location, 10, PAGE_EXECUTE_READWRITE, DUMMY);
void* original; void* original;
MH_STATUS error; MH_STATUS error;

View File

@ -25,13 +25,9 @@ class TextHook
{ {
public: public:
HookParam hp; HookParam hp;
union uint64_t address; // Absolute address
{
uint64_t address;
void* location;
}; // Absolute address
bool Insert(HookParam hp, DWORD set_flag); bool Insert(HookParam hp, uint64_t address, void* realAddress, DWORD set_flag);
void Clear(); void Clear();
private: private:
@ -45,6 +41,7 @@ private:
void RemoveReadCode(); void RemoveReadCode();
volatile DWORD useCount; volatile DWORD useCount;
void* location;
HANDLE readerThread, readerEvent; HANDLE readerThread, readerEvent;
bool err; bool err;
BYTE trampoline[x64 ? 140 : 40]; BYTE trampoline[x64 ? 140 : 40];