Hotpatching

This commit is contained in:
Guus Waals 2025-06-01 16:22:06 +08:00
parent e3c19e890f
commit 4092af3513
2 changed files with 36 additions and 10 deletions

View File

@ -96,6 +96,7 @@ function(setup_target TARGET DBG_MODE)
COMMAND ${gh_tool} -d${CMAKE_CURRENT_SOURCE_DIR}/gh.db COMMAND ${gh_tool} -d${CMAKE_CURRENT_SOURCE_DIR}/gh.db
hooks -o ${CMAKE_CURRENT_BINARY_DIR}/hooks.def hooks -o ${CMAKE_CURRENT_BINARY_DIR}/hooks.def
) )
target_include_directories(${TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_sources(${TARGET} PRIVATE target_sources(${TARGET} PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/hooks.def ${CMAKE_CURRENT_BINARY_DIR}/hooks.def

View File

@ -3,14 +3,21 @@
#include <windows.h> #include <windows.h>
#include <DbgHelp.h> #include <DbgHelp.h>
#include <memoryapi.h> #include <memoryapi.h>
#include <hooker.h>
#define GH_BASE_ADDR 0x00400000 #define GH_BASE_ADDR 0x00400000
static uintptr_t g_gh_translationOffset{}; static uintptr_t g_gh_translationOffset{};
extern "C" {
#define HOOK(addr, name) void name(void *);
#include "hooks.def"
#undef HOOK
}
struct R3Bin { struct R3Bin {
R3Bin() { loadOriginal(); } R3Bin() { loadOriginal(); }
void loadOriginal() { void loadOriginal() {
SPDLOG_DEBUG("Loading original binary"); SPDLOG_DEBUG("Loading original binary");
@ -27,12 +34,15 @@ struct R3Bin {
uintptr_t(module) - GH_BASE_ADDR; uintptr_t(module) - GH_BASE_ADDR;
// Now we have to relocate the module to the new base address // Now we have to relocate the module to the new base address
relocateModule(module); relocateModule();
patchFunctions();
} }
inline void relocate(HMODULE module, void* instr, void* from, void* originalPointee) { inline void relocate(void *instr, void *from,
void* relocated_addr = (void*)(uintptr_t(from) + translationOffset); void *originalPointee) {
void* relocated_to = (void*)(uintptr_t(originalPointee) + translationOffset); void *relocated_addr = (void *)(uintptr_t(from) + translationOffset);
void *relocated_to =
(void *)(uintptr_t(originalPointee) + translationOffset);
void *checkRead{}; void *checkRead{};
SIZE_T numRead{}; SIZE_T numRead{};
ReadProcessMemory(GetCurrentProcess(), relocated_addr, &checkRead, ReadProcessMemory(GetCurrentProcess(), relocated_addr, &checkRead,
@ -40,12 +50,14 @@ struct R3Bin {
if (numRead != 4 || checkRead != originalPointee) { if (numRead != 4 || checkRead != originalPointee) {
throw std::logic_error("Invalid relocation"); throw std::logic_error("Invalid relocation");
} }
WriteProcessMemory(GetCurrentProcess(), relocated_addr, &relocated_to, sizeof(relocated_to), NULL); WriteProcessMemory(GetCurrentProcess(), relocated_addr, &relocated_to,
sizeof(relocated_to), NULL);
} }
void relocateModule(HMODULE module) { void relocateModule() {
#define REL(instr, from, originalPointee) relocate(module, (void*)(instr), (void*)(from), (void*)(originalPointee)); #define REL(instr, from, originalPointee) \
#include "relocations.def" relocate((void *)(instr), (void *)(from), (void *)(originalPointee));
#include "relocations.def"
} }
// Translate address relative from the original image base address // Translate address relative from the original image base address
@ -148,6 +160,19 @@ struct R3Bin {
} }
} }
// Fixes up the target address (RVA) to jump into the patched function
void patchFunction(void *at, void *new_addr, const char *name) {
SPDLOG_DEBUG("Patching function {} at {}", name, at);
void *resolved = translateAddress(at);
if (!hooker_write_jmp(resolved, new_addr))
throw std::runtime_error(fmt::format(
"Failed to patch function {} at {} (RVA: {})", name, resolved, at));
}
void patchFunctions() {
#define HOOK(addr, name) patchFunction((void*)addr, &name, #name);
#include "hooks.def"
}
HINSTANCE module; HINSTANCE module;
uintptr_t translationOffset; uintptr_t translationOffset;