Hotpatching
This commit is contained in:
parent
e3c19e890f
commit
4092af3513
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue