A library providing pretty macros for replacing code at given address, adding detours, or adding trampolines. Keeps track of code modifications, is able to undo them. Supports hot-patching/hot-un-patching at any point in program lifecycle. Integrates nicely with DLL Hotpach Daemon.
Supports Linux and Windows, works with x86 32-bit libraries.
A few samples. Descriptions can be found in the only API header file - patchmem.h
:
PATCH_MEM(0x8cea20, 2, "pop eax");
TRAMPOLINE(0x8d456c, 5, "mov ecx, 0x%x; call org", &g_some_hooked_data);
static void * __thiscall (*ca_login_action)(void *thisptr) = (void*)0x552ea0;
static void * __thiscall hooked_login_action(void *thisptr) {
// prepare something
void *ret = ca_login_action(thisptr); // call the original code
// do something with ret
return ret;
}
TRAMPOLINE_FN(&ca_login_action, 7, hooked_login_action);
All of the above macros expand to static gcc constructors, which add necessary patch information to a patchmem-internal list. The patches can be then applied with patch_mem_static_init()
and then potentially un-applied with patch_mem_static_deinit()
.
patch_mem_static_deinit()
is only meant for hot-reloading the library. It suspends all other threads, checks if any of them are executing the patched code, un-suspends them if needed, repeats up to a few times until it succeeds, then un-patches the code. A suggested practice is to call patch_mem_static_deinit()
from some public deinit
function that's only called by the hot-patcher.
Depends on Keystone Engine to assemble x86 asm at runtime. This assembly could be done at build time, but then this library wouldn't allow for such a nice syntax.
Patchmem comes with a Makefile to build it as a separate library.
Simply:
$ make
With a single function call to patch_mem_static_persist()
it can be made to never unload itself. This comes useful for quicker hot-reloading the target library, since the patchmem & the keystone dependency won't need to be reloaded.
But it's also straightforward to integrate patchmem directly into the target library.
To build and run the tests (Linux only):
$ make tests