diff --git a/hooking/HookFunction.cpp b/hooking/HookFunction.cpp index f1cb882..49d5b0e 100644 --- a/hooking/HookFunction.cpp +++ b/hooking/HookFunction.cpp @@ -9,35 +9,28 @@ static HookFunctionBase* g_hookFunctions; -void HookFunctionBase::Register() -{ - m_next = g_hookFunctions; - g_hookFunctions = this; +void HookFunctionBase::Register() { + m_next = g_hookFunctions; + g_hookFunctions = this; } -void HookFunctionBase::RunAll() -{ - for (auto func = g_hookFunctions; func; func = func->m_next) - { - func->Run(); - } +void HookFunctionBase::RunAll() { + for (auto func = g_hookFunctions; func; func = func->m_next) { + func->Run(); + } } static RuntimeHookFunction* g_runtimeHookFunctions; -void RuntimeHookFunction::Register() -{ - m_next = g_runtimeHookFunctions; - g_runtimeHookFunctions = this; +void RuntimeHookFunction::Register() { + m_next = g_runtimeHookFunctions; + g_runtimeHookFunctions = this; } -void RuntimeHookFunction::Run(const char* key) -{ - for (auto func = g_runtimeHookFunctions; func; func = func->m_next) - { - if (func->m_key == key) - { - func->m_function(); - } - } +void RuntimeHookFunction::Run(const char* key) { + for (auto func = g_runtimeHookFunctions; func; func = func->m_next) { + if (func->m_key == key) { + func->m_function(); + } + } } \ No newline at end of file diff --git a/hooking/HookFunction.h b/hooking/HookFunction.h index 283d202..3dd72c9 100644 --- a/hooking/HookFunction.h +++ b/hooking/HookFunction.h @@ -13,57 +13,44 @@ // Initialization function that will be called after the game is loaded. // -class HookFunctionBase -{ -private: - HookFunctionBase* m_next; +class HookFunctionBase { + private: + HookFunctionBase* m_next; -public: - HookFunctionBase() - { - Register(); - } + public: + HookFunctionBase() { Register(); } - virtual void Run() = 0; + virtual void Run() = 0; - static void RunAll(); - void Register(); + static void RunAll(); + void Register(); }; -class HookFunction : public HookFunctionBase -{ -private: - void(*m_function)(); +class HookFunction : public HookFunctionBase { + private: + void (*m_function)(); -public: - HookFunction(void(*function)()) - { - m_function = function; - } + public: + HookFunction(void (*function)()) { m_function = function; } - virtual void Run() - { - m_function(); - } + virtual void Run() { m_function(); } }; -class RuntimeHookFunction -{ -private: - void(*m_function)(); - std::string m_key; +class RuntimeHookFunction { + private: + void (*m_function)(); + std::string m_key; - RuntimeHookFunction* m_next; + RuntimeHookFunction* m_next; -public: - RuntimeHookFunction(const char* key, void(*function)()) - { - m_key = key; - m_function = function; + public: + RuntimeHookFunction(const char* key, void (*function)()) { + m_key = key; + m_function = function; - Register(); - } + Register(); + } - static void Run(const char* key); - void Register(); + static void Run(const char* key); + void Register(); }; \ No newline at end of file diff --git a/hooking/Hooking.FuncCalls.h b/hooking/Hooking.FuncCalls.h index 212872a..eb7940d 100644 --- a/hooking/Hooking.FuncCalls.h +++ b/hooking/Hooking.FuncCalls.h @@ -10,153 +10,145 @@ #include #include -namespace hook -{ -struct passed -{ - template passed(T...) {} +namespace hook { +struct passed { + template + passed(T...) {} }; -class CallStubEx : public jitasm::Frontend -{ -private: - void* m_callback; - void* m_userData; +class CallStubEx : public jitasm::Frontend { + private: + void* m_callback; + void* m_userData; - size_t m_argumentSize; + size_t m_argumentSize; -public: - CallStubEx() - { + public: + CallStubEx() {} - } + inline void SetCallback(void* cb, void* userData) { + m_callback = cb; + m_userData = userData; + } - inline void SetCallback(void* cb, void* userData) { m_callback = cb; m_userData = userData; } + inline void SetArgumentSize(size_t size) { m_argumentSize = size; } - inline void SetArgumentSize(size_t size) { m_argumentSize = size; } + virtual void InternalMain() { + int argStart = 4; - virtual void InternalMain() - { - int argStart = 4; + pushad(); + argStart += 8 * sizeof(uintptr_t); - pushad(); - argStart += 8 * sizeof(uintptr_t); + push((uintptr_t)m_userData); + argStart += 4; - push((uintptr_t)m_userData); - argStart += 4; + sub(esp, m_argumentSize); + argStart += m_argumentSize; - sub(esp, m_argumentSize); - argStart += m_argumentSize; + lea(esi, dword_ptr[esp]); + add(esi, argStart); - lea(esi, dword_ptr[esp]); - add(esi, argStart); + lea(edi, dword_ptr[esp]); - lea(edi, dword_ptr[esp]); + push(ecx); + mov(ecx, m_argumentSize); - push(ecx); - mov(ecx, m_argumentSize); + rep_movsb(); - rep_movsb(); + pop(ecx); - pop(ecx); + mov(eax, (uintptr_t)m_callback); + call(eax); - mov(eax, (uintptr_t)m_callback); - call(eax); + popad(); - popad(); + ret(m_argumentSize); + } - ret(m_argumentSize); - } + void Inject(uintptr_t address) { + auto assembly = new FunctionAssembly(*this); - void Inject(uintptr_t address) - { - auto assembly = new FunctionAssembly(*this); + int origAddress = *(int*)(address + 1); + origAddress += 5; + origAddress += address; - int origAddress = *(int*)(address + 1); - origAddress += 5; - origAddress += address; - - // and patch - put(address + 1, (uintptr_t)assembly->GetCode() - (uintptr_t)get_adjusted(address) - 5); - } + // and patch + put(address + 1, (uintptr_t)assembly->GetCode() - + (uintptr_t)get_adjusted(address) - 5); + } }; -template -struct thiscall -{ - typedef std::function TOrigFunc; - typedef TRet(__thiscall* TOrigCB)(void*, Args...); - typedef std::function THookFunc; +template +struct thiscall { + typedef std::function TOrigFunc; + typedef TRet(__thiscall* TOrigCB)(void*, Args...); + typedef std::function THookFunc; -private: - struct hookdata - { - THookFunc hookFunc; - TOrigCB origCB; - }; + private: + struct hookdata { + THookFunc hookFunc; + TOrigCB origCB; + }; - static TRet __thiscall InternalHook(void* class_, Args... args, hookdata* hookDataPtr) - { - hookdata* data = static_cast(hookDataPtr); + static TRet __thiscall InternalHook(void* class_, + Args... args, + hookdata* hookDataPtr) { + hookdata* data = static_cast(hookDataPtr); - return data->hookFunc((TClass*)class_, args...); - } + return data->hookFunc((TClass*)class_, args...); + } -public: - static void inject(uintptr_t address, THookFunc hookFunc) - { - auto hookData = new hookdata; - hookData->hookFunc = hookFunc; + public: + static void inject(uintptr_t address, THookFunc hookFunc) { + auto hookData = new hookdata; + hookData->hookFunc = hookFunc; - size_t argSize = 0; + size_t argSize = 0; - passed{ ([&] - { - int size = min(sizeof(Args), sizeof(uintptr_t)); + passed{( + [&] { + int size = min(sizeof(Args), sizeof(uintptr_t)); - argSize += size; - }(), 1)... }; + argSize += size; + }(), + 1)...}; - CallStubEx callStub; - callStub.SetCallback((void*)InternalHook, hookData); - callStub.SetArgumentSize(argSize); + CallStubEx callStub; + callStub.SetCallback((void*)InternalHook, hookData); + callStub.SetArgumentSize(argSize); - callStub.Inject(address); - } + callStub.Inject(address); + } }; -template -struct thiscall -{ - typedef std::function TOrigFunc; - typedef TRet(__thiscall* TOrigCB)(void*); - typedef std::function THookFunc; - -private: - struct hookdata - { - THookFunc hookFunc; - TOrigCB origCB; - }; - - static TRet __thiscall InternalHook(void* class_, hookdata* hookDataPtr) - { - hookdata* data = static_cast(hookDataPtr); - - return data->hookFunc((TClass*)class_); - } - -public: - static void inject(uintptr_t address, THookFunc hookFunc) - { - auto hookData = new hookdata; - hookData->hookFunc = hookFunc; - - CallStubEx callStub; - callStub.SetCallback((void*)InternalHook, hookData); - callStub.SetArgumentSize(0); - - callStub.Inject(address); - } +template +struct thiscall { + typedef std::function TOrigFunc; + typedef TRet(__thiscall* TOrigCB)(void*); + typedef std::function THookFunc; + + private: + struct hookdata { + THookFunc hookFunc; + TOrigCB origCB; + }; + + static TRet __thiscall InternalHook(void* class_, hookdata* hookDataPtr) { + hookdata* data = static_cast(hookDataPtr); + + return data->hookFunc((TClass*)class_); + } + + public: + static void inject(uintptr_t address, THookFunc hookFunc) { + auto hookData = new hookdata; + hookData->hookFunc = hookFunc; + + CallStubEx callStub; + callStub.SetCallback((void*)InternalHook, hookData); + callStub.SetArgumentSize(0); + + callStub.Inject(address); + } }; } \ No newline at end of file diff --git a/hooking/Hooking.Invoke.h b/hooking/Hooking.Invoke.h index d3c6b45..2ec192c 100644 --- a/hooking/Hooking.Invoke.h +++ b/hooking/Hooking.Invoke.h @@ -9,108 +9,76 @@ #include "HookFunction.h" -namespace hook -{ - namespace details - { - class function_stub_base - { - protected: - void* m_functionAddress; - - public: - inline void SetFunctionAddress(void* address) - { - m_functionAddress = address; - } - }; - - class StubInitFunction : public HookFunctionBase - { - private: - void*(*m_function)(); - - function_stub_base* m_stub; - - public: - StubInitFunction(function_stub_base* stub, void*(*function)()) - { - m_function = function; - m_stub = stub; - } - - virtual void Run() - { - m_stub->SetFunctionAddress(m_function()); - } - }; - - template - class thiscall_stub_ : public function_stub_base - { - private: - StubInitFunction m_hookFunction; - - public: - thiscall_stub_(void*(*getter)()) - : m_hookFunction(this, getter) - { - - } - - inline TRet operator()(Args... args) - { - return reinterpret_cast(m_functionAddress)(args...); - } - }; - - template - class cdecl_stub_ : public function_stub_base - { - private: - StubInitFunction m_hookFunction; - - public: - cdecl_stub_(void*(*getter)()) - : m_hookFunction(this, getter) - { - - } - - inline TRet operator()(Args... args) - { - return reinterpret_cast(m_functionAddress)(args...); - } - }; - } - - template - class thiscall_stub {}; - - template - class thiscall_stub - : public details::thiscall_stub_ - { - public: - thiscall_stub(void*(*getter)()) - : thiscall_stub_(getter) - { - - } - }; - - template - class cdecl_stub {}; - - template - class cdecl_stub - : public details::cdecl_stub_ < TRet, Args... > - { - public: - cdecl_stub(void*(*getter)()) - : cdecl_stub_(getter) - { - - } - }; +namespace hook { +namespace details { +class function_stub_base { + protected: + void* m_functionAddress; + + public: + inline void SetFunctionAddress(void* address) { m_functionAddress = address; } +}; + +class StubInitFunction : public HookFunctionBase { + private: + void* (*m_function)(); + + function_stub_base* m_stub; + + public: + StubInitFunction(function_stub_base* stub, void* (*function)()) { + m_function = function; + m_stub = stub; + } + + virtual void Run() { m_stub->SetFunctionAddress(m_function()); } +}; + +template +class thiscall_stub_ : public function_stub_base { + private: + StubInitFunction m_hookFunction; + + public: + thiscall_stub_(void* (*getter)()) : m_hookFunction(this, getter) {} + + inline TRet operator()(Args... args) { + return reinterpret_cast(m_functionAddress)( + args...); + } +}; + +template +class cdecl_stub_ : public function_stub_base { + private: + StubInitFunction m_hookFunction; + + public: + cdecl_stub_(void* (*getter)()) : m_hookFunction(this, getter) {} + + inline TRet operator()(Args... args) { + return reinterpret_cast(m_functionAddress)( + args...); + } +}; +} + +template +class thiscall_stub {}; + +template +class thiscall_stub + : public details::thiscall_stub_ { + public: + thiscall_stub(void* (*getter)()) : thiscall_stub_(getter) {} +}; + +template +class cdecl_stub {}; + +template +class cdecl_stub : public details::cdecl_stub_ { + public: + cdecl_stub(void* (*getter)()) : cdecl_stub_(getter) {} +}; } \ No newline at end of file diff --git a/hooking/Hooking.cpp b/hooking/Hooking.cpp index fdc175a..d34195a 100644 --- a/hooking/Hooking.cpp +++ b/hooking/Hooking.cpp @@ -7,112 +7,116 @@ #include "Hooking.h" -namespace hook -{ +namespace hook { - uintptr_t baseAddress; - // Size of each memory block. (= page size of VirtualAlloc) - const uint64_t MEMORY_BLOCK_SIZE = 0x1000; +uintptr_t baseAddress; +// Size of each memory block. (= page size of VirtualAlloc) +const uint64_t MEMORY_BLOCK_SIZE = 0x1000; - // Max range for seeking a memory block. (= 1024MB) - const uint64_t MAX_MEMORY_RANGE = 0x40000000; +// Max range for seeking a memory block. (= 1024MB) +const uint64_t MAX_MEMORY_RANGE = 0x40000000; #ifndef _M_AMD64 - void inject_hook::inject() - { - inject_hook_frontend fe(this); - m_assembly = std::make_shared(fe); - - put(m_address, 0xE9); - put(m_address + 1, (uintptr_t)m_assembly->GetCode() - (uintptr_t)get_adjusted(m_address) - 5); - } - - void inject_hook::injectCall() - { - inject_hook_frontend fe(this); - m_assembly = std::make_shared(fe); - - put(m_address, 0xE8); - put(m_address + 1, (uintptr_t)m_assembly->GetCode() - (uintptr_t)get_adjusted(m_address) - 5); - } +void inject_hook::inject() { + inject_hook_frontend fe(this); + m_assembly = std::make_shared(fe); + + put(m_address, 0xE9); + put(m_address + 1, (uintptr_t)m_assembly->GetCode() - + (uintptr_t)get_adjusted(m_address) - 5); +} + +void inject_hook::injectCall() { + inject_hook_frontend fe(this); + m_assembly = std::make_shared(fe); + + put(m_address, 0xE8); + put(m_address + 1, (uintptr_t)m_assembly->GetCode() - + (uintptr_t)get_adjusted(m_address) - 5); +} #else - // code from minhook - static LPVOID FindPrevFreeRegion(LPVOID pAddress, LPVOID pMinAddr, DWORD dwAllocationGranularity) { - ULONG_PTR tryAddr = (ULONG_PTR)pAddress; +// code from minhook +static LPVOID FindPrevFreeRegion(LPVOID pAddress, + LPVOID pMinAddr, + DWORD dwAllocationGranularity) { + ULONG_PTR tryAddr = (ULONG_PTR)pAddress; - // Round down to the next allocation granularity. - tryAddr -= tryAddr % dwAllocationGranularity; + // Round down to the next allocation granularity. + tryAddr -= tryAddr % dwAllocationGranularity; - // Start from the previous allocation granularity multiply. - tryAddr -= dwAllocationGranularity; + // Start from the previous allocation granularity multiply. + tryAddr -= dwAllocationGranularity; - while (tryAddr >= (ULONG_PTR)pMinAddr) { - MEMORY_BASIC_INFORMATION mbi; - if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == 0) - break; - - if (mbi.State == MEM_FREE) - return (LPVOID)tryAddr; + while (tryAddr >= (ULONG_PTR)pMinAddr) { + MEMORY_BASIC_INFORMATION mbi; + if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == + 0) + break; - if ((ULONG_PTR)mbi.AllocationBase < dwAllocationGranularity) - break; + if (mbi.State == MEM_FREE) + return (LPVOID)tryAddr; - tryAddr = (ULONG_PTR)mbi.AllocationBase - dwAllocationGranularity; - } + if ((ULONG_PTR)mbi.AllocationBase < dwAllocationGranularity) + break; - return NULL; + tryAddr = (ULONG_PTR)mbi.AllocationBase - dwAllocationGranularity; } - void* AllocateFunctionStub(void* origin, void* function, int type) - { - static void* g_currentStub = nullptr; + return NULL; +} - if (!g_currentStub) { - ULONG_PTR minAddr; - ULONG_PTR maxAddr; +void* AllocateFunctionStub(void* origin, void* function, int type) { + static void* g_currentStub = nullptr; - SYSTEM_INFO si; - GetSystemInfo(&si); - minAddr = (ULONG_PTR)si.lpMinimumApplicationAddress; - maxAddr = (ULONG_PTR)si.lpMaximumApplicationAddress; + if (!g_currentStub) { + ULONG_PTR minAddr; + ULONG_PTR maxAddr; - if ((ULONG_PTR)origin > MAX_MEMORY_RANGE && minAddr < (ULONG_PTR)origin - MAX_MEMORY_RANGE) - minAddr = (ULONG_PTR)origin - MAX_MEMORY_RANGE; + SYSTEM_INFO si; + GetSystemInfo(&si); + minAddr = (ULONG_PTR)si.lpMinimumApplicationAddress; + maxAddr = (ULONG_PTR)si.lpMaximumApplicationAddress; - if (maxAddr > (ULONG_PTR)origin + MAX_MEMORY_RANGE) - maxAddr = (ULONG_PTR)origin + MAX_MEMORY_RANGE; + if ((ULONG_PTR)origin > MAX_MEMORY_RANGE && + minAddr < (ULONG_PTR)origin - MAX_MEMORY_RANGE) + minAddr = (ULONG_PTR)origin - MAX_MEMORY_RANGE; + if (maxAddr > (ULONG_PTR)origin + MAX_MEMORY_RANGE) + maxAddr = (ULONG_PTR)origin + MAX_MEMORY_RANGE; - LPVOID pAlloc = origin; + LPVOID pAlloc = origin; - while ((ULONG_PTR)pAlloc >= minAddr) { - pAlloc = FindPrevFreeRegion(pAlloc, (LPVOID)minAddr, si.dwAllocationGranularity); - if (pAlloc == NULL) - break; + while ((ULONG_PTR)pAlloc >= minAddr) { + pAlloc = FindPrevFreeRegion(pAlloc, (LPVOID)minAddr, + si.dwAllocationGranularity); + if (pAlloc == NULL) + break; - g_currentStub = VirtualAlloc( - pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - if (g_currentStub != NULL) - break; - } + g_currentStub = + VirtualAlloc(pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, + PAGE_EXECUTE_READWRITE); + if (g_currentStub != NULL) + break; } - if (!g_currentStub) return nullptr; + } + if (!g_currentStub) + return nullptr; - char* code = (char*)g_currentStub; + char* code = (char*)g_currentStub; - *(uint8_t*)code = 0x48; - *(uint8_t*)(code + 1) = 0xb8 | type; + *(uint8_t*)code = 0x48; + *(uint8_t*)(code + 1) = 0xb8 | type; - *(uint64_t*)(code + 2) = (uint64_t)function; + *(uint64_t*)(code + 2) = (uint64_t)function; - *(uint16_t*)(code + 10) = 0xE0FF | (type << 8); + *(uint16_t*)(code + 10) = 0xE0FF | (type << 8); - *(uint64_t*)(code + 12) = 0xCCCCCCCCCCCCCCCC; + *(uint64_t*)(code + 12) = 0xCCCCCCCCCCCCCCCC; - g_currentStub = (void*)((uint64_t)g_currentStub + 20); + g_currentStub = (void*)((uint64_t)g_currentStub + 20); - return code; - } + return code; +} #endif } \ No newline at end of file diff --git a/hooking/Hooking.h b/hooking/Hooking.h index f128a15..f31849c 100644 --- a/hooking/Hooking.h +++ b/hooking/Hooking.h @@ -13,355 +13,319 @@ #include #include -namespace hook -{ +namespace hook { // for link /DYNAMICBASE executables extern uintptr_t baseAddress; // sets the base address difference based on an obtained pointer -inline void set_base(uintptr_t address) -{ - baseAddress = address; +inline void set_base(uintptr_t address) { + baseAddress = address; } // sets the base to the process main base -inline void set_base() -{ - set_base((uintptr_t)GetModuleHandle(NULL)); +inline void set_base() { + set_base((uintptr_t)GetModuleHandle(NULL)); } // adjusts the address passed to the base as set above -template +template inline void adjust_base(T& address) { //*(uintptr_t*)&address += baseAddressDifference; } // returns the adjusted address to the stated base -template +template inline uintptr_t get_adjusted(T address) { return address; } -struct pass -{ - template pass(T...) {} +struct pass { + template + pass(T...) {} }; #pragma region assembly generator -class FunctionAssembly -{ -private: - void* m_code; +class FunctionAssembly { + private: + void* m_code; -public: - inline FunctionAssembly(jitasm::Frontend& frontend) - { - frontend.Assemble(); + public: + inline FunctionAssembly(jitasm::Frontend& frontend) { + frontend.Assemble(); - void* code; - code = VirtualAlloc(0, frontend.GetCodeSize(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + void* code; + code = VirtualAlloc(0, frontend.GetCodeSize(), MEM_COMMIT | MEM_RESERVE, + PAGE_EXECUTE_READWRITE); - memcpy(code, frontend.GetCode(), frontend.GetCodeSize()); + memcpy(code, frontend.GetCode(), frontend.GetCodeSize()); - m_code = code; - } + m_code = code; + } - inline ~FunctionAssembly() - { - VirtualFree(m_code, 0, MEM_RELEASE); - } + inline ~FunctionAssembly() { VirtualFree(m_code, 0, MEM_RELEASE); } - inline void* GetCode() - { - return m_code; - } + inline void* GetCode() { return m_code; } }; #pragma endregion -template -inline void put(AddressType address, ValueType value) -{ - adjust_base(address); +template +inline void put(AddressType address, ValueType value) { + adjust_base(address); - memcpy((void*)address, &value, sizeof(value)); + memcpy((void*)address, &value, sizeof(value)); } -template -inline void putVP(AddressType address, ValueType value) -{ - adjust_base(address); +template +inline void putVP(AddressType address, ValueType value) { + adjust_base(address); - DWORD oldProtect; - VirtualProtect((void*)address, sizeof(value), PAGE_EXECUTE_READWRITE, &oldProtect); + DWORD oldProtect; + VirtualProtect((void*)address, sizeof(value), PAGE_EXECUTE_READWRITE, + &oldProtect); - memcpy((void*)address, &value, sizeof(value)); + memcpy((void*)address, &value, sizeof(value)); - VirtualProtect((void*)address, sizeof(value), oldProtect, &oldProtect); + VirtualProtect((void*)address, sizeof(value), oldProtect, &oldProtect); } -template -inline void nop(AddressType address, size_t length) -{ - adjust_base(address); +template +inline void nop(AddressType address, size_t length) { + adjust_base(address); DWORD oldProtect; VirtualProtect((void*)address, length, PAGE_EXECUTE_READWRITE, &oldProtect); - memset((void*)address, 0x90, length); + memset((void*)address, 0x90, length); VirtualProtect((void*)address, length, oldProtect, &oldProtect); } -template -inline void return_function(AddressType address, uint16_t stackSize = 0) -{ - if (stackSize == 0) - { - put(address, 0xC3); - } - else - { - put(address, 0xC2); - put((uintptr_t)address + 1, stackSize); - } +template +inline void return_function(AddressType address, uint16_t stackSize = 0) { + if (stackSize == 0) { + put(address, 0xC3); + } else { + put(address, 0xC2); + put((uintptr_t)address + 1, stackSize); + } } -template -inline T* getRVA(uintptr_t rva) -{ +template +inline T* getRVA(uintptr_t rva) { #ifdef _M_IX86 - return (T*)(baseAddress + rva); + return (T*)(baseAddress + rva); #elif defined(_M_AMD64) - return (T*)(baseAddress + rva); + return (T*)(baseAddress + rva); #endif } -namespace -{ - template - inline bool iat_matches_ordinal(uintptr_t* nameTableEntry, TOrdinal ordinal) - { - - } +namespace { +template +inline bool iat_matches_ordinal(uintptr_t* nameTableEntry, TOrdinal ordinal) {} - template<> - inline bool iat_matches_ordinal(uintptr_t* nameTableEntry, int ordinal) - { - if (IMAGE_SNAP_BY_ORDINAL(*nameTableEntry)) - { - return IMAGE_ORDINAL(*nameTableEntry) == ordinal; - } +template <> +inline bool iat_matches_ordinal(uintptr_t* nameTableEntry, int ordinal) { + if (IMAGE_SNAP_BY_ORDINAL(*nameTableEntry)) { + return IMAGE_ORDINAL(*nameTableEntry) == ordinal; + } - return false; - } + return false; +} - template<> - inline bool iat_matches_ordinal(uintptr_t* nameTableEntry, const char* ordinal) - { - if (!IMAGE_SNAP_BY_ORDINAL(*nameTableEntry)) - { - auto import = getRVA(*nameTableEntry); +template <> +inline bool iat_matches_ordinal(uintptr_t* nameTableEntry, + const char* ordinal) { + if (!IMAGE_SNAP_BY_ORDINAL(*nameTableEntry)) { + auto import = getRVA(*nameTableEntry); - return !_stricmp(import->Name, ordinal); - } + return !_stricmp(import->Name, ordinal); + } - return false; - } + return false; +} } -template -void iat(const char* moduleName, T function, TOrdinal ordinal) -{ +template +void iat(const char* moduleName, T function, TOrdinal ordinal) { #ifdef _M_IX86 - IMAGE_DOS_HEADER* imageHeader = (IMAGE_DOS_HEADER*)(baseAddress); + IMAGE_DOS_HEADER* imageHeader = (IMAGE_DOS_HEADER*)(baseAddress); #elif defined(_M_AMD64) - IMAGE_DOS_HEADER* imageHeader = (IMAGE_DOS_HEADER*)(baseAddress); + IMAGE_DOS_HEADER* imageHeader = (IMAGE_DOS_HEADER*)(baseAddress); #endif - IMAGE_NT_HEADERS* ntHeader = getRVA(imageHeader->e_lfanew); + IMAGE_NT_HEADERS* ntHeader = getRVA(imageHeader->e_lfanew); - IMAGE_IMPORT_DESCRIPTOR* descriptor = getRVA(ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + IMAGE_IMPORT_DESCRIPTOR* descriptor = getRVA( + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] + .VirtualAddress); - while (descriptor->Name) - { - const char* name = getRVA(descriptor->Name); + while (descriptor->Name) { + const char* name = getRVA(descriptor->Name); - if (_stricmp(name, moduleName)) - { - descriptor++; + if (_stricmp(name, moduleName)) { + descriptor++; - continue; - } + continue; + } - auto nameTableEntry = getRVA(descriptor->OriginalFirstThunk); - auto addressTableEntry = getRVA(descriptor->FirstThunk); + auto nameTableEntry = getRVA(descriptor->OriginalFirstThunk); + auto addressTableEntry = getRVA(descriptor->FirstThunk); - while (*nameTableEntry) - { - if (iat_matches_ordinal(nameTableEntry, ordinal)) - { - *addressTableEntry = (uintptr_t)function; - return; - } + while (*nameTableEntry) { + if (iat_matches_ordinal(nameTableEntry, ordinal)) { + *addressTableEntry = (uintptr_t)function; + return; + } - nameTableEntry++; - addressTableEntry++; - } + nameTableEntry++; + addressTableEntry++; + } - return; - } + return; + } } #ifndef _M_AMD64 // a context for the hook function to party on -struct HookContext -{ - uint32_t m_jumpRet; - uint32_t m_edi, m_esi, m_ebp, m_esp, m_ebx, m_edx, m_ecx, m_eax; // matches pushad format +struct HookContext { + uint32_t m_jumpRet; + uint32_t m_edi, m_esi, m_ebp, m_esp, m_ebx, m_edx, m_ecx, + m_eax; // matches pushad format }; -class inject_hook -{ -friend struct inject_hook_frontend; +class inject_hook { + friend struct inject_hook_frontend; -private: - HookContext* m_curContext; - std::shared_ptr m_assembly; - uintptr_t m_address; + private: + HookContext* m_curContext; + std::shared_ptr m_assembly; + uintptr_t m_address; -public: - // return value type container - typedef int ReturnType; + public: + // return value type container + typedef int ReturnType; -private: - // set context and run - ReturnType do_run(HookContext* context) - { - m_curContext = context; + private: + // set context and run + ReturnType do_run(HookContext* context) { + m_curContext = context; - return run(); - } + return run(); + } -protected: - // return type values for use in return; + protected: + // return type values for use in return; - // return without jumping anywhere - inline ReturnType DoNowt() - { - return ReturnType(0); - } + // return without jumping anywhere + inline ReturnType DoNowt() { return ReturnType(0); } - // jump to this place after the hook - inline ReturnType JumpTo(uint32_t address) - { - m_curContext->m_eax = address; + // jump to this place after the hook + inline ReturnType JumpTo(uint32_t address) { + m_curContext->m_eax = address; - return ReturnType(1); - } + return ReturnType(1); + } - // accessors for context registers - inline uint32_t Eax() { return m_curContext->m_eax; } - inline void Eax(uint32_t a) { m_curContext->m_eax = a; } + // accessors for context registers + inline uint32_t Eax() { return m_curContext->m_eax; } + inline void Eax(uint32_t a) { m_curContext->m_eax = a; } - inline uint32_t Ebx() { return m_curContext->m_ebx; } - inline void Ebx(uint32_t a) { m_curContext->m_ebx = a; } + inline uint32_t Ebx() { return m_curContext->m_ebx; } + inline void Ebx(uint32_t a) { m_curContext->m_ebx = a; } - inline uint32_t Ecx() { return m_curContext->m_ecx; } - inline void Ecx(uint32_t a) { m_curContext->m_ecx = a; } + inline uint32_t Ecx() { return m_curContext->m_ecx; } + inline void Ecx(uint32_t a) { m_curContext->m_ecx = a; } - inline uint32_t Edx() { return m_curContext->m_edx; } - inline void Edx(uint32_t a) { m_curContext->m_edx = a; } + inline uint32_t Edx() { return m_curContext->m_edx; } + inline void Edx(uint32_t a) { m_curContext->m_edx = a; } - inline uint32_t Esi() { return m_curContext->m_esi; } - inline void Esi(uint32_t a) { m_curContext->m_esi = a; } + inline uint32_t Esi() { return m_curContext->m_esi; } + inline void Esi(uint32_t a) { m_curContext->m_esi = a; } - inline uint32_t Edi() { return m_curContext->m_edi; } - inline void Edi(uint32_t a) { m_curContext->m_edi = a; } + inline uint32_t Edi() { return m_curContext->m_edi; } + inline void Edi(uint32_t a) { m_curContext->m_edi = a; } - inline uint32_t Esp() { return m_curContext->m_esp; } - inline void Esp(uint32_t a) { m_curContext->m_esp = a; } + inline uint32_t Esp() { return m_curContext->m_esp; } + inline void Esp(uint32_t a) { m_curContext->m_esp = a; } - inline uint32_t Ebp() { return m_curContext->m_ebp; } - inline void Ebp(uint32_t a) { m_curContext->m_ebp = a; } + inline uint32_t Ebp() { return m_curContext->m_ebp; } + inline void Ebp(uint32_t a) { m_curContext->m_ebp = a; } -public: - virtual ReturnType run() = 0; + public: + virtual ReturnType run() = 0; - inject_hook(uint32_t address) - { - m_address = address; - } + inject_hook(uint32_t address) { m_address = address; } - void inject(); - void injectCall(); + void inject(); + void injectCall(); }; -struct inject_hook_frontend : jitasm::Frontend -{ -private: - inject_hook* m_hook; +struct inject_hook_frontend : jitasm::Frontend { + private: + inject_hook* m_hook; - static inject_hook::ReturnType CallHookFunction(inject_hook* hook, HookContext* context) - { - return hook->do_run(context); - } + static inject_hook::ReturnType CallHookFunction(inject_hook* hook, + HookContext* context) { + return hook->do_run(context); + } -public: - inject_hook_frontend(inject_hook* hook) - { - m_hook = hook; - } + public: + inject_hook_frontend(inject_hook* hook) { m_hook = hook; } - void InternalMain() - { - // set up the context stack frame - pushad(); // registers - sub(esp, 4); // jump target area - mov(dword_ptr[esp], 0); + void InternalMain() { + // set up the context stack frame + pushad(); // registers + sub(esp, 4); // jump target area + mov(dword_ptr[esp], 0); - // load the context address into eax - lea(eax, dword_ptr[esp]); + // load the context address into eax + lea(eax, dword_ptr[esp]); - // push eax (second argument to our call) - push(eax); + // push eax (second argument to our call) + push(eax); - // push the (softcoded, heh) hook function - push((uint32_t)m_hook); + // push the (softcoded, heh) hook function + push((uint32_t)m_hook); - // call the call stub - mov(eax, (uint32_t)CallHookFunction); - call(eax); + // call the call stub + mov(eax, (uint32_t)CallHookFunction); + call(eax); - // remove garbage from the stack - add(esp, 8); + // remove garbage from the stack + add(esp, 8); - // do we want to jump somewhere? - test(eax, eax); - jnz("actuallyJump"); + // do we want to jump somewhere? + test(eax, eax); + jnz("actuallyJump"); - // guess not, remove jump target area and popad - add(esp, 4); - popad(); + // guess not, remove jump target area and popad + add(esp, 4); + popad(); - // get esp back from the context bit - mov(esp, dword_ptr[esp - 20]); + // get esp back from the context bit + mov(esp, dword_ptr[esp - 20]); - ret(); + ret(); - L("actuallyJump"); + L("actuallyJump"); - add(esp, 4); - popad(); + add(esp, 4); + popad(); - mov(esp, dword_ptr[esp - 20]); - - AppendInstr(jitasm::I_CALL, 0xFF, 0, jitasm::Imm8(4), R(eax)); - } -}; + mov(esp, dword_ptr[esp - 20]); -#define DEFINE_INJECT_HOOK(hookName, hookAddress) class _zz_inject_hook_##hookName : public hook::inject_hook { public: _zz_inject_hook_##hookName(uint32_t address) : hook::inject_hook(address) {}; ReturnType run(); }; \ - static _zz_inject_hook_##hookName hookName(hookAddress); \ - _zz_inject_hook_##hookName::ReturnType _zz_inject_hook_##hookName::run() + AppendInstr(jitasm::I_CALL, 0xFF, 0, jitasm::Imm8(4), R(eax)); + } +}; +#define DEFINE_INJECT_HOOK(hookName, hookAddress) \ + class _zz_inject_hook_##hookName : public hook::inject_hook { \ + public: \ + _zz_inject_hook_##hookName(uint32_t address) \ + : hook::inject_hook(address){}; \ + ReturnType run(); \ + }; \ + static _zz_inject_hook_##hookName hookName(hookAddress); \ + _zz_inject_hook_##hookName::ReturnType _zz_inject_hook_##hookName::run() #if 0 struct AsmHookStub : jitasm::Frontend @@ -416,205 +380,189 @@ struct AsmHookStub : jitasm::Frontend }; #endif -template -inline void jump(AT address, T func) -{ - put(address, 0xE9); - put((uintptr_t)address + 1, (intptr_t)func - address - 5); +template +inline void jump(AT address, T func) { + put(address, 0xE9); + put((uintptr_t)address + 1, (intptr_t)func - address - 5); } -template -inline void call(AT address, T func) -{ - put(address, 0xE8); - put((uintptr_t)address + 1, (intptr_t)func - (intptr_t)get_adjusted(address) - 5); +template +inline void call(AT address, T func) { + put(address, 0xE8); + put((uintptr_t)address + 1, + (intptr_t)func - (intptr_t)get_adjusted(address) - 5); } -template -inline T get_call(T address) -{ - intptr_t target = *(uintptr_t*)(get_adjusted(address) + 1); - target += (get_adjusted(address) + 5); +template +inline T get_call(T address) { + intptr_t target = *(uintptr_t*)(get_adjusted(address) + 1); + target += (get_adjusted(address) + 5); - return (T)target; + return (T)target; } -template -inline void set_call(TTarget* target, T address) -{ - *(T*)target = get_call(address); +template +inline void set_call(TTarget* target, T address) { + *(T*)target = get_call(address); } -namespace vp -{ - template - inline void jump(AT address, T func) - { - putVP(address, 0xE9); - putVP((uintptr_t)address + 1, (intptr_t)func - (intptr_t)get_adjusted(address) - 5); - } +namespace vp { +template +inline void jump(AT address, T func) { + putVP(address, 0xE9); + putVP((uintptr_t)address + 1, + (intptr_t)func - (intptr_t)get_adjusted(address) - 5); +} - template - inline void call(AT address, T func) - { - putVP(address, 0xE8); - putVP((uintptr_t)address + 1, (intptr_t)func - (intptr_t)get_adjusted(address) - 5); - } +template +inline void call(AT address, T func) { + putVP(address, 0xE8); + putVP((uintptr_t)address + 1, + (intptr_t)func - (intptr_t)get_adjusted(address) - 5); +} } -#pragma region inject call: call stub -template -struct CallStub : jitasm::function> -{ -private: - void* m_target; +#pragma region inject call : call stub +template +struct CallStub : jitasm::function> { + private: + void* m_target; -public: - CallStub(void* target) - : m_target(target) - { - } + public: + CallStub(void* target) : m_target(target) {} - void main() - { - uint32_t stackOffset = 0; - uint32_t argOffset = sizeof(uintptr_t) * 2; // as frame pointers are also kept here - uint32_t argCleanup = 0; + void main() { + uint32_t stackOffset = 0; + uint32_t argOffset = + sizeof(uintptr_t) * 2; // as frame pointers are also kept here + uint32_t argCleanup = 0; - pass{([&] - { - int size = min(sizeof(Args), sizeof(uintptr_t)); + pass{( + [&] { + int size = min(sizeof(Args), sizeof(uintptr_t)); - argOffset += size; - }(), 1)...}; + argOffset += size; + }(), + 1)...}; - // as this is the end, and the last argument isn't past the end - argOffset -= 4; - - pass{([&] - { - mov(eax, dword_ptr[esp + stackOffset + argOffset]); - push(eax); + // as this is the end, and the last argument isn't past the end + argOffset -= 4; - int size = max(sizeof(Args), sizeof(uintptr_t)); + pass{( + [&] { + mov(eax, dword_ptr[esp + stackOffset + argOffset]); + push(eax); - stackOffset += size; - argCleanup += size; - argOffset -= size; - }(), 1)...}; + int size = max(sizeof(Args), sizeof(uintptr_t)); - mov(eax, (uintptr_t)m_target); - call(eax); + stackOffset += size; + argCleanup += size; + argOffset -= size; + }(), + 1)...}; - add(esp, argCleanup); - } + mov(eax, (uintptr_t)m_target); + call(eax); + + add(esp, argCleanup); + } }; #pragma endregion #pragma region inject call -template -class inject_call -{ -private: - R (*m_origAddress)(Args...); +template +class inject_call { + private: + R (*m_origAddress)(Args...); - uintptr_t m_address; + uintptr_t m_address; - std::shared_ptr m_assembly; + std::shared_ptr m_assembly; -public: - inject_call(uintptr_t address) - { - if (*(uint8_t*)address != 0xE8) - { - FatalError("inject_call attempted on something that was not a call. Are you sure you have a compatible version of the game executable? You might need to try poking the guru."); - } + public: + inject_call(uintptr_t address) { + if (*(uint8_t*)address != 0xE8) { + FatalError( + "inject_call attempted on something that was not a call. Are you " + "sure you have a compatible version of the game executable? You " + "might need to try poking the guru."); + } - m_address = address; - } + m_address = address; + } - void inject(R (*target)(Args...)) - { - CallStub stub(target); - - m_assembly = std::make_shared(stub); + void inject(R (*target)(Args...)) { + CallStub stub(target); - // store original - int origAddress = *(int*)(m_address + 1); - origAddress += 5; - origAddress += m_address; + m_assembly = std::make_shared(stub); - m_origAddress = (R(*)(Args...))origAddress; + // store original + int origAddress = *(int*)(m_address + 1); + origAddress += 5; + origAddress += m_address; - // and patch - put(m_address + 1, (uintptr_t)m_assembly->GetCode() - (uintptr_t)get_adjusted(m_address) - 5); - } + m_origAddress = (R (*)(Args...))origAddress; - R call() - { - return ((R(*)())m_origAddress)(); - } + // and patch + put(m_address + 1, (uintptr_t)m_assembly->GetCode() - + (uintptr_t)get_adjusted(m_address) - 5); + } - R call(Args... args) - { - return m_origAddress(args...); - } + R call() { return ((R (*)())m_origAddress)(); } + + R call(Args... args) { return m_origAddress(args...); } }; #pragma endregion #else void* AllocateFunctionStub(void* origin, void* ptr, int type = 0); -template -inline void jump(AT address, T func) -{ +template +inline void jump(AT address, T func) { LPVOID funcStub = AllocateFunctionStub((void*)address, (void*)func); - putVP(address, 0xE9); - putVP((uintptr_t)address + 1, (intptr_t)funcStub- (intptr_t)get_adjusted(address) - 5); + putVP(address, 0xE9); + putVP((uintptr_t)address + 1, + (intptr_t)funcStub - (intptr_t)get_adjusted(address) - 5); } -template -inline void call(AT address, T func) -{ - LPVOID funcStub = AllocateFunctionStub((void*)address, (void*)func); +template +inline void call(AT address, T func) { + LPVOID funcStub = AllocateFunctionStub((void*)address, (void*)func); putVP(address, 0xE8); - putVP((uintptr_t)address + 1, (intptr_t)funcStub - (intptr_t)get_adjusted(address) - 5); + putVP((uintptr_t)address + 1, + (intptr_t)funcStub - (intptr_t)get_adjusted(address) - 5); } -template -inline void call_rcx(AT address, T func) -{ - LPVOID funcStub = AllocateFunctionStub((void*)address, (void*)func, 1); +template +inline void call_rcx(AT address, T func) { + LPVOID funcStub = AllocateFunctionStub((void*)address, (void*)func, 1); - put(address, 0xE8); - put((uintptr_t)address + 1, (intptr_t)funcStub - (intptr_t)get_adjusted(address) - 5); + put(address, 0xE8); + put((uintptr_t)address + 1, + (intptr_t)funcStub - (intptr_t)get_adjusted(address) - 5); } -template -inline T get_call(T address) -{ - intptr_t target = *(int32_t*)(get_adjusted(address) + 1); - target += (get_adjusted(address) + 5); +template +inline T get_call(T address) { + intptr_t target = *(int32_t*)(get_adjusted(address) + 1); + target += (get_adjusted(address) + 5); - return (T)target; + return (T)target; } -template -inline void set_call(TTarget* target, T address) -{ - *(T*)target = get_call(address); +template +inline void set_call(TTarget* target, T address) { + *(T*)target = get_call(address); } -inline uintptr_t get_member_internal(void* function) -{ - return *(uintptr_t*)function; +inline uintptr_t get_member_internal(void* function) { + return *(uintptr_t*)function; } -template -inline uintptr_t get_member(T function) -{ - return ((uintptr_t(*)(T))get_member_internal)(function); +template +inline uintptr_t get_member(T function) { + return ((uintptr_t (*)(T))get_member_internal)(function); } #endif } diff --git a/main.cc b/main.cc index 8b72523..d679c2e 100644 --- a/main.cc +++ b/main.cc @@ -14,7 +14,7 @@ CRTTISystem* rtti_system = nullptr; void* native_globals_function_map = nullptr; CGame** global_game = nullptr; -//void DumpEnums() { +// void DumpEnums() { // std::wofstream log_file; // log_file.open("global_enums_log.txt"); // @@ -28,7 +28,9 @@ CGame** global_game = nullptr; // auto enum_ = *(CEnum**)(enums.base_pointer + i); // if (!enum_) continue; //|| !enum_->source_script) continue; // -// log_file << "enum " << enum_->name.AsChar() << " // " << std::dec << enum_->names_count << " " << std::dec << enum_->flags << " " << enum_->source_script << std::endl; +// log_file << "enum " << enum_->name.AsChar() << " // " << std::dec << +// enum_->names_count << " " << std::dec << enum_->flags << " " << +// enum_->source_script << std::endl; // log_file << "{" << std::endl; // for (size_t i = 0; i < enum_->names_count; i++) { // CName name; @@ -36,7 +38,8 @@ CGame** global_game = nullptr; // if (name.pool_index) { // int value; // enum_->FindValue(name, value); -// log_file << " " << name.AsChar() << " = " << value << "," << std::endl; +// log_file << " " << name.AsChar() << " = " << value << "," << +// std::endl; // } // } // log_file << std::endl << "}" << std::endl; @@ -45,7 +48,7 @@ CGame** global_game = nullptr; // log_file.close(); //} // -//std::wostream& operator<<(std::wostream& stream, const wchar_t* string) { +// std::wostream& operator<<(std::wostream& stream, const wchar_t* string) { // if (string == nullptr) return stream; // // std::wstring test(string); @@ -62,7 +65,8 @@ CGame** global_game = nullptr; // // pos = test.find(L"array:2,0,array:2,0,"); // if (pos != -1) { -// test.replace(pos, std::wstring(L"array:2,0,array:2,0,").length(), L"C2dArray"); +// test.replace(pos, std::wstring(L"array:2,0,array:2,0,").length(), +// L"C2dArray"); // } // // pos = test.find(L"array:2,0,"); @@ -75,7 +79,7 @@ CGame** global_game = nullptr; // return stream; //} // -//void DumpGlobalFunctions() { +// void DumpGlobalFunctions() { // std::wofstream log_file; // log_file.open("global_functions_log.txt"); // @@ -188,58 +192,77 @@ CGame** global_game = nullptr; // log_file.close(); //} // -typedef bool(*OnViewportInputType) (void* thisptr, void* viewport, EInputKey input_key, EInputAction input_action, float tick); +typedef bool (*OnViewportInputType)(void* thisptr, + void* viewport, + EInputKey input_key, + EInputAction input_action, + float tick); OnViewportInputType OnViewportInputDebugConsole = nullptr; -bool OnViewportInputDebugAlwaysHook(void* thisptr, void* viewport, EInputKey input_key, EInputAction input_action, float tick) { - if ((*global_game)->ProcessFreeCameraInput(input_key, input_action, tick)) return true; +bool OnViewportInputDebugAlwaysHook(void* thisptr, + void* viewport, + EInputKey input_key, + EInputAction input_action, + float tick) { + if ((*global_game)->ProcessFreeCameraInput(input_key, input_action, tick)) + return true; if (input_key == IK_F2 && input_action == IACT_Release) { input_key = IK_Tilde; input_action = IACT_Press; } - return OnViewportInputDebugConsole(*global_debug_console, viewport, input_key, input_action, tick); + return OnViewportInputDebugConsole(*global_debug_console, viewport, input_key, + input_action, tick); } // -//void funcLogHook(struct CObject *a1, struct CScriptStackFrame *a2, void *a3) { +// void funcLogHook(struct CObject *a1, struct CScriptStackFrame *a2, void *a3) +// { // OutputDebugStringW(L"test log"); //} // -//uint64_t* GetFunctionAddress(CFunction* function) { -// return (uint64_t*)((uint64_t)native_globals_function_map + (8 * function->registration_offset)); +// uint64_t* GetFunctionAddress(CFunction* function) { +// return (uint64_t*)((uint64_t)native_globals_function_map + (8 * +// function->registration_offset)); //} // -//void ReplaceFunction(const char* name, uint64_t address) { +// void ReplaceFunction(const char* name, uint64_t address) { // auto function = rtti_system->FindGlobalFunction(CName(name)); // // if (function) { // auto function_address = GetFunctionAddress(function); // // std::wstringstream message; -// message << "ReplaceFunction: " << name << " " << std::hex << function << " " << " " << std::hex << function_address; +// message << "ReplaceFunction: " << name << " " << std::hex << function << " +// " << " " << std::hex << function_address; // OutputDebugStringW(message.str().c_str()); // // *function_address = address; // } //} // -//static void ScriptWarn(void* thisptr, CScriptFileContext* file_context, TString* message) { +// static void ScriptWarn(void* thisptr, CScriptFileContext* file_context, +// TString* message) { // std::wofstream log_file; // log_file.open("script_compilation.log", std::ios_base::app); -// log_file << "warn " << file_context->file_name.buffer_address << ":" << file_context->line_number << " " << message->buffer_address << std::endl; +// log_file << "warn " << file_context->file_name.buffer_address << ":" << +// file_context->line_number << " " << message->buffer_address << std::endl; // log_file.close(); // -// std::wcout << "warn " << file_context->file_name.buffer_address << ":" << file_context->line_number << " " << message->buffer_address << std::endl; +// std::wcout << "warn " << file_context->file_name.buffer_address << ":" << +// file_context->line_number << " " << message->buffer_address << std::endl; //} // -//static void ScriptError(void* thisptr, CScriptFileContext* file_context, TString* message) { +// static void ScriptError(void* thisptr, CScriptFileContext* file_context, +// TString* message) { // std::wofstream log_file; // log_file.open("script_compilation.log", std::ios_base::app); -// log_file << "ERROR " << file_context->file_name.buffer_address << ":" << file_context->line_number << " " << message->buffer_address << std::endl; +// log_file << "ERROR " << file_context->file_name.buffer_address << ":" << +// file_context->line_number << " " << message->buffer_address << std::endl; // log_file.close(); // -// std::wcerr << "ERROR " << file_context->file_name.buffer_address << ":" << file_context->line_number << " " << message->buffer_address << std::endl; +// std::wcerr << "ERROR " << file_context->file_name.buffer_address << ":" << +// file_context->line_number << " " << message->buffer_address << std::endl; //} std::wstring GetExecutablePath() { @@ -266,46 +289,62 @@ std::vector GetAllFileNamesFromFolder(std::wstring folder) { return names; } -static bool (__thiscall *OrginalBaseEngine_InitializeScripts)(void*); +static bool(__thiscall* OrginalBaseEngine_InitializeScripts)(void*); static bool BaseEngine_InitializeScripts(void* rcx, void* rdx) { std::wcout << "BaseEngine_InitializeScripts" << std::endl; - //CRTTISerializer serializer; - //TString path(L"cookedfinal.redscripts"); + // CRTTISerializer serializer; + // TString path(L"cookedfinal.redscripts"); - //if (serializer.LoadScriptData(&path, false)) { + // if (serializer.LoadScriptData(&path, false)) { // std::wcout << L"Loaded scriptplugin: cookedfinal.redscripts" << std::endl; //}; return OrginalBaseEngine_InitializeScripts(rcx); } -DWORD WINAPI InitializeHook(void* arguments) { +DWORD WINAPI InitializeHook(void* arguments) { hook::set_base(); HookFunction::RunAll(); - global_game = hook::pattern("48 8B 05 ? ? ? ? 48 8D 4C 24 ? C6 44 24").count(1).get(0).extract(3); - global_debug_console = hook::pattern("48 89 05 ? ? ? ? EB 07 48 89 35 ? ? ? ? 48 8B 97").count(1).get(0).extract(3); + global_game = hook::pattern("48 8B 05 ? ? ? ? 48 8D 4C 24 ? C6 44 24") + .count(1) + .get(0) + .extract(3); + global_debug_console = + hook::pattern("48 89 05 ? ? ? ? EB 07 48 89 35 ? ? ? ? 48 8B 97") + .count(1) + .get(0) + .extract(3); while (*global_game == nullptr || *global_debug_console == nullptr) { Sleep(500); } - OnViewportInputDebugConsole = hook::pattern("48 83 EC 28 48 8B 05 ? ? ? ? 0F B6 90").count(1).get(0).get(0); - rtti_system = *hook::pattern("48 8B 0D ? ? ? ? 48 8B 5C 24 ? 48 83 C4 30").count(1).get(0).extract(3); - //native_globals_function_map = hook::pattern("4C 8D 0D ? ? ? ? 49 89 14 C1").count(1).get(0).extract(3); - //FileManager* file_manager = hook::pattern("48 8B 0D ? ? ? ? 48 8D 55 A0 41 B8").count(1).get(0).extract(3); + OnViewportInputDebugConsole = + hook::pattern("48 83 EC 28 48 8B 05 ? ? ? ? 0F B6 90") + .count(1) + .get(0) + .get(0); + rtti_system = *hook::pattern("48 8B 0D ? ? ? ? 48 8B 5C 24 ? 48 83 C4 30") + .count(1) + .get(0) + .extract(3); + // native_globals_function_map = hook::pattern("4C 8D 0D ? ? ? ? 49 89 14 + // C1").count(1).get(0).extract(3); + // FileManager* file_manager = hook::pattern("48 8B 0D ? ? ? ? 48 8D 55 A0 41 + // B8").count(1).get(0).extract(3); game_hook = new utils::VtableHook(*global_game); game_hook->HookMethod(OnViewportInputDebugAlwaysHook, 133); - //auto exe_path = GetExecutablePath(); - //exe_path += L"\\scriptplugins\\"; + // auto exe_path = GetExecutablePath(); + // exe_path += L"\\scriptplugins\\"; - //auto plugin_names = GetAllFileNamesFromFolder(exe_path); + // auto plugin_names = GetAllFileNamesFromFolder(exe_path); - //for (auto name : plugin_names) { + // for (auto name : plugin_names) { // if (name.find(L".redscriptsplugin") == std::string::npos) continue; // auto full_path = (L"..\\..\\bin\\x64\\scriptplugins\\" + name); @@ -317,27 +356,27 @@ DWORD WINAPI InitializeHook(void* arguments) { // }; //} - //DumpGlobalFunctions(); + // DumpGlobalFunctions(); - //DumpEnums(); + // DumpEnums(); - //ReplaceFunction("Log", (uint64_t)&funcLogHook); - //ReplaceFunction("LogChannel", (uint64_t)&funcLogHook); - //ReplaceFunction("Trace", (uint64_t)&funcLogHook); - //ReplaceFunction("DebugBreak", (uint64_t)&funcLogHook); + // ReplaceFunction("Log", (uint64_t)&funcLogHook); + // ReplaceFunction("LogChannel", (uint64_t)&funcLogHook); + // ReplaceFunction("Trace", (uint64_t)&funcLogHook); + // ReplaceFunction("DebugBreak", (uint64_t)&funcLogHook); return 1; } void FinalizeHook() { - if (game_hook) delete game_hook; + if (game_hook) + delete game_hook; } int WINAPI DllMain(HINSTANCE instance, DWORD reason, PVOID reserved) { if (reason == DLL_PROCESS_ATTACH) { thread = CreateThread(nullptr, 0, InitializeHook, 0, 0, nullptr); - } - else if (reason == DLL_PROCESS_DETACH) { + } else if (reason == DLL_PROCESS_DETACH) { FinalizeHook(); WaitForSingleObject(thread, INFINITE); CloseHandle(thread); diff --git a/vtable/vmthooks.cc b/vtable/vmthooks.cc index 4ba9cd0..e29c75c 100644 --- a/vtable/vmthooks.cc +++ b/vtable/vmthooks.cc @@ -2,53 +2,58 @@ #include "vmthooks.h" namespace utils { - uint CountFuncs(void** vmt) { - // Query memory and as long as the pointer lands in - // PAGE_EXECUTE_READ or PAGE_EXECUTE_READWRITE memory - // assume this is a valid function pointer. - MEMORY_BASIC_INFORMATION mem; - int i = -1; - do { - i++; VirtualQuery(vmt[i], &mem, sizeof(MEMORY_BASIC_INFORMATION)); - } while (mem.Protect == PAGE_EXECUTE_READ || - mem.Protect == PAGE_EXECUTE_READWRITE); - return i; - } - uint CountFuncs(void* begin, void* end, void** vmt) { - int i = -1; - do { - i++; - } while ( begin < vmt[i] && vmt[i ]< end ); - return i; - } - int FindFunc(void** vmt, void* func, uint vfuncs) { - if ( !vfuncs ) vfuncs = CountFuncs( vmt ); - for ( uint i = 0; i < vfuncs; i++ ) { - if (vmt[i] == func) { - return i; - } +uint CountFuncs(void** vmt) { + // Query memory and as long as the pointer lands in + // PAGE_EXECUTE_READ or PAGE_EXECUTE_READWRITE memory + // assume this is a valid function pointer. + MEMORY_BASIC_INFORMATION mem; + int i = -1; + do { + i++; + VirtualQuery(vmt[i], &mem, sizeof(MEMORY_BASIC_INFORMATION)); + } while (mem.Protect == PAGE_EXECUTE_READ || + mem.Protect == PAGE_EXECUTE_READWRITE); + return i; +} +uint CountFuncs(void* begin, void* end, void** vmt) { + int i = -1; + do { + i++; + } while (begin < vmt[i] && vmt[i] < end); + return i; +} +int FindFunc(void** vmt, void* func, uint vfuncs) { + if (!vfuncs) + vfuncs = CountFuncs(vmt); + for (uint i = 0; i < vfuncs; i++) { + if (vmt[i] == func) { + return i; } - return -1; } + return -1; +} - VtableHook::VtableHook(void* inst, size_t offset, uint vfuncs) { - vtable_ = make_ptr(inst, offset); - old_vtable_ = *vtable_; - // Count vfuncs ourself if needed - if ( !vfuncs ) vfuncs = CountFuncs( old_vtable_ ); - vtable_function_count_ = vfuncs; +VtableHook::VtableHook(void* inst, size_t offset, uint vfuncs) { + vtable_ = make_ptr(inst, offset); + old_vtable_ = *vtable_; + // Count vfuncs ourself if needed + if (!vfuncs) + vfuncs = CountFuncs(old_vtable_); + vtable_function_count_ = vfuncs; - _array = reinterpret_cast(malloc((vfuncs+3)*sizeof(void*) )); - // Initialize RTTI pointer (should there be one) - _array[2] = old_vtable_[-1]; - // Copy over the other vfuncs - for (uint i = 0; i < vfuncs; ++i ) _array[i+3] = old_vtable_[i]; - // Hook it - *vtable_ = _array+3; - } - VtableHook::~VtableHook() { - if (vtable_) Unhook(); - free(_array); - } + _array = reinterpret_cast(malloc((vfuncs + 3) * sizeof(void*))); + // Initialize RTTI pointer (should there be one) + _array[2] = old_vtable_[-1]; + // Copy over the other vfuncs + for (uint i = 0; i < vfuncs; ++i) + _array[i + 3] = old_vtable_[i]; + // Hook it + *vtable_ = _array + 3; +} +VtableHook::~VtableHook() { + if (vtable_) + Unhook(); + free(_array); +} } // namespace utils diff --git a/vtable/vmthooks.h b/vtable/vmthooks.h index 9704231..4958187 100644 --- a/vtable/vmthooks.h +++ b/vtable/vmthooks.h @@ -5,88 +5,85 @@ #include namespace utils { - typedef unsigned int uint; - typedef size_t int_ptr; - template< typename T > inline T make_ptr(void* ptr, int_ptr offset) { - return reinterpret_cast((size_t)ptr + offset); - } - inline void**& getvtable(void* inst, int_ptr offset = 0) { - return *reinterpret_cast( (size_t)inst + offset ); - } +typedef unsigned int uint; +typedef size_t int_ptr; +template +inline T make_ptr(void* ptr, int_ptr offset) { + return reinterpret_cast((size_t)ptr + offset); +} +inline void**& getvtable(void* inst, int_ptr offset = 0) { + return *reinterpret_cast((size_t)inst + offset); +} - // Find the number of vfuncs in a vtable - uint CountFuncs(void** pVMT); - uint CountFuncs(void* begin, void* end, void** pVMT); +// Find the number of vfuncs in a vtable +uint CountFuncs(void** pVMT); +uint CountFuncs(void* begin, void* end, void** pVMT); - // Find the index for a vfunc, result is negative if not found - int FindFunc(void** pVMT, void* pFunc, uint vfuncs = 0); +// Find the index for a vfunc, result is negative if not found +int FindFunc(void** pVMT, void* pFunc, uint vfuncs = 0); - // ---------------------------------------------------------------- - // Class: VMTManager - // ---------------------------------------------------------------- - // Hooks virtual functions by replacing the vtable pointer from an instance. - class VtableHook { - // Forbid copy constructing and assignment. - VtableHook(const VtableHook&); - VtableHook& operator= (const VtableHook&); +// ---------------------------------------------------------------- +// Class: VMTManager +// ---------------------------------------------------------------- +// Hooks virtual functions by replacing the vtable pointer from an instance. +class VtableHook { + // Forbid copy constructing and assignment. + VtableHook(const VtableHook&); + VtableHook& operator=(const VtableHook&); - public: - VtableHook(void* inst, size_t offset = 0, uint vfuncs = 0); - ~VtableHook(); + public: + VtableHook(void* inst, size_t offset = 0, uint vfuncs = 0); + ~VtableHook(); - // Hooks a function by index. - inline void HookMethod(void* newfunc, size_t index) { - assert(index < vtable_function_count_); - _array[index+3] = newfunc; - } - // Unhooks a function by index. - inline void UnhookMethod(size_t index) { - assert(index < vtable_function_count_); - _array[index+3] = old_vtable_[index]; - } + // Hooks a function by index. + inline void HookMethod(void* newfunc, size_t index) { + assert(index < vtable_function_count_); + _array[index + 3] = newfunc; + } + // Unhooks a function by index. + inline void UnhookMethod(size_t index) { + assert(index < vtable_function_count_); + _array[index + 3] = old_vtable_[index]; + } - // Manage the hooks. - inline void Unhook() { *vtable_ = old_vtable_; } - inline void Rehook() { *vtable_ = _array + 3; } - inline bool Hooked() const { return *vtable_ != old_vtable_; } - inline void EraseHooks() { - for (uint i = 0; i < vtable_function_count_; ++i) { - _array[i+3] = vtable_[i]; - } - } - inline uint NumFuncs() const { - return vtable_function_count_; + // Manage the hooks. + inline void Unhook() { *vtable_ = old_vtable_; } + inline void Rehook() { *vtable_ = _array + 3; } + inline bool Hooked() const { return *vtable_ != old_vtable_; } + inline void EraseHooks() { + for (uint i = 0; i < vtable_function_count_; ++i) { + _array[i + 3] = vtable_[i]; } + } + inline uint NumFuncs() const { return vtable_function_count_; } - // If the instance is somehow destroyed - // before you get a chance to unhook it - // or destruct this hook object, call this. - // It'll prevent the destructor from crashing. - inline void Poof() { vtable_ = nullptr; } + // If the instance is somehow destroyed + // before you get a chance to unhook it + // or destruct this hook object, call this. + // It'll prevent the destructor from crashing. + inline void Poof() { vtable_ = nullptr; } - // Get the original function. - // Use a function prototype - // for the template argument to make it very easy to call this function. - // Example syntax: - // hook.GetMethod( 12 )( inst, arg ); - template< typename Fn > - inline Fn GetMethod(size_t index) const { - assert(index < vtable_function_count_); - return (Fn) old_vtable_[ index ]; - } + // Get the original function. + // Use a function prototype + // for the template argument to make it very easy to call this function. + // Example syntax: + // hook.GetMethod( 12 )( inst, arg ); + template + inline Fn GetMethod(size_t index) const { + assert(index < vtable_function_count_); + return (Fn)old_vtable_[index]; + } - protected: - inline void _set_guard(size_t S) { - _array[1] = reinterpret_cast(S); - } - inline size_t _get_guard() const { return (size_t) _array[1]; } - inline void _set_backptr(void* ptr ) { _array[0] = ptr; } - inline void* _get_backptr() const { return _array[0]; } + protected: + inline void _set_guard(size_t S) { _array[1] = reinterpret_cast(S); } + inline size_t _get_guard() const { return (size_t)_array[1]; } + inline void _set_backptr(void* ptr) { _array[0] = ptr; } + inline void* _get_backptr() const { return _array[0]; } - private: - void*** vtable_; - void** old_vtable_; - void** _array; - uint vtable_function_count_; - }; + private: + void*** vtable_; + void** old_vtable_; + void** _array; + uint vtable_function_count_; +}; } // namespace utils diff --git a/witcher3-classes.h b/witcher3-classes.h index 1d5d576..8d624d9 100644 --- a/witcher3-classes.h +++ b/witcher3-classes.h @@ -26,7 +26,7 @@ enum { // Sir_Kane PropFlag_Out = 0x200, PropFlag_Optional = 0x400, PropFlag_Compatible = 0x2000, // IsExported - PropFlag_Import = 0x4000, // Native + PropFlag_Import = 0x4000, // Native PropFlag_Saved = 0x8000, PropFlag_Private = 0x10000, PropFlag_Protected = 0x20000, diff --git a/witcher3-enums.h b/witcher3-enums.h index 1987ee0..d1995dc 100644 --- a/witcher3-enums.h +++ b/witcher3-enums.h @@ -7,7 +7,7 @@ enum EInputAction { IACT_Axis = 3 }; -enum EInputKey { // 261 +enum EInputKey { // 261 IK_None = 0, IK_LeftMouse = 1, IK_RightMouse = 2,