How to dynamically interpose C functions from Python on Linux (without LD_PRELOAD)?

2.5k views Asked by At

How do I, at run-time (no LD_PRELOAD), intercept/hook a C function like fopen() on Linux, a la Detours for Windows? I'd like to do this from Python (hence, I'm assuming that the program is already running a CPython VM) and also reroute to Python code. I'm fine with just hooking shared library functions. I'd also like to do this without having to change the way the program is run.

One idea is to roll my own tool based on ptrace(), or on rewriting code found with dlsym() or in the PLT, and targeting ctypes-generated C-callable functions, but I thought I'd ask here first. Thanks.

2

There are 2 answers

3
aaron On

google-perftools has their own implementation of Detour under src/windows/preamble_patcher* . This is windows-only at the moment, but I don't see any reason it wouldn't work on any x86 machine except for the fact that it uses win32 functions to look up symbol addresses.

A quick scan of the code and I see these win32 functions used, all of which have linux versions:

  • GetModuleHandle/GetProcAddress : get the function address. dlsym can do this.
  • VirtualProtect : to allow modification of the assembly. mprotect.
  • GetCurrentProcess: getpid
  • FlushInstructionCache (apparently a nop according to the comments)

It doesn't seem too hard to get this compiled and linked into python, but I'd send a message to the perftools devs and see what they think.

0
Coren On

You'll find from one of ltrace developer a way to do this. See this post, which includes a full patch in order to catch dynamically loaded library. In order to call it from python, you'll probably need to make a C module.