Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@NeoCat
Created December 25, 2011 13:48
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save NeoCat/1519275 to your computer and use it in GitHub Desktop.
Save NeoCat/1519275 to your computer and use it in GitHub Desktop.
Hook hidden symbol call (x86_64)
#include "LibHook.h"
#include <stdio.h>
#include <unistd.h>
int brk_hook(void *addr)
{
int ret = brk(addr);
printf("brk(%p) => %d\n", addr, ret);
return ret;
}
HookInstaller(brk, brk_hook);
#include <string.h>
#include <dlfcn.h>
#include <err.h>
#include <errno.h>
#include <sys/mman.h>
#define LIB_PATH "libc.so.6"
template <class RET, class... ARGV>
class LibHook {
public:
typedef RET rtype;
typedef RET(*ftype)(ARGV...);
protected:
void *handle, *func;
ftype hook;
unsigned char origcode[14], jumpcode[14];
public:
LibHook(const char *libpath, const char *funcname, ftype hook) : hook(hook) {
handle = dlopen(libpath, RTLD_NOW);
if (!handle) err(1, "dlopen failed");
func = dlsym(handle, funcname);
if (!func) err(1, "dlshm failed");
unsigned long addr = (unsigned long)hook;
memcpy(origcode, func, sizeof(origcode));
memcpy(jumpcode, (unsigned char[]){0xff,0x25,0,0,0,0}, 6); //jmp *(%rip)
memcpy(jumpcode+6, &addr, sizeof(addr));
addr = (unsigned long)func;
mprotect((void*)(addr & ~0xfff), (addr & 0xfff) < 4096-14 ? 4096 : 8192,
PROT_WRITE|PROT_READ|PROT_EXEC);
}
~LibHook() {
unsigned long addr = (unsigned long)func;
mprotect((void*)(addr & ~0xfff), (addr & 0xfff) < 4096-14 ? 4096 : 8192,
PROT_READ|PROT_EXEC);
dlclose(handle);
}
void setAutoRemove(ftype hook) {
unsigned long addr = (unsigned long)hook;
memcpy(jumpcode+6, &addr, sizeof(addr));
}
void install() {
memcpy(func, jumpcode, sizeof(jumpcode));
}
void uninstall() {
memcpy(func, origcode, sizeof(origcode));
}
// remove jump to call original func within the hook
RET _autoRemoveHook(ARGV... args) {
uninstall();
RET ret = hook(args...);
install();
return ret;
}
template <LibHook* obj>
static RET autoRemoveHook(ARGV... args) {
return obj->_autoRemoveHook(args...);
}
};
template <class RET, class... ARGS>
LibHook<RET,ARGS...> _resolve_ftype(RET(*f)(ARGS...))
{
throw "This function must not be called.";
return LibHook<RET,ARGS...>();
}
#define HookInstaller(func, hfunc) \
namespace NSHook_##func { \
typedef decltype(_resolve_ftype(func)) HookT; \
HookT hook(LIB_PATH, #func, hfunc); \
struct Installer { \
Installer() { \
hook.setAutoRemove( \
HookT::autoRemoveHook<&hook>); \
hook.install(); \
} \
} installer; \
};
all: hook_brk.so malloc_test
LD_PRELOAD=./hook_brk.so ./malloc_test
malloc_test: malloc_test.c
gcc malloc_test.c -o malloc_test
hook_brk.so: hook_brk.cpp LibHook.h
$(CXX) -fPIC -shared -o hook_brk.so hook_brk.cpp -std=c++0x -ldl
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
free(malloc(256<<10));
free(malloc(256<<10));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment