LD_PRELOAD is a way to intercept system calls issued from glibc and interact with them: modifying args, changing return values, completely exchanging implementations, etc
Some misc. things I learned about implementing preload hooks from C++:
- remember to wrap the calls with extern “C” to prevent function mangling from CPP
- try not to use cout inside preload functions without initializing std::iostream
- you can use c++ overloading instead of C var args, which is cool!
- LD_PRELOAD doesn’t necessarily cover all function invocations (f.e. system calls not invoked via glibc) - ptrace does a better job here
- if you get undefined symbol errors during linking, it could be that you compiled with gcc instead of g++!
- if your hooks aren’t being run, try implementing the 64 version: i.e. open64() vs open()
- openat() may or may not be a systemcall - it likely calls open() or open64()
An example preload in CPY
#ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include <dlfcn.h> #include <stdio.h> #include <stdlib.h> // we use extern C to prevent symbol mangling for usage in LD_PRELOAD extern "C": static void _libhook_init() __attribute__((constructor)) static void _libhook_init(): printf("INIT HOOK\n") int open(const char *pathname, int flags, mode_t mode=0): static int(*func_open)(const char *, int, mode_t) = NULL if(!func_open) func_open =(int(*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "open") printf("OPENING PATH %s\n", pathname) return func_open(pathname, flags, mode)