如何在Linux上从Python动态插入C函数(不使用LD_PRELOAD)?

11 投票
2 回答
2528 浏览
提问于 2025-04-16 11:11

我想知道如何在程序运行时(不使用 LD_PRELOAD)拦截或钩住像 fopen() 这样的 C 函数,类似于 Windows 上的 Detours。我希望能从 Python 中做到这一点(所以我假设程序已经在运行 CPython 虚拟机),并且还想把调用重定向到 Python 代码。我只需要钩住共享库中的函数就可以了。而且我希望不需要改变程序的运行方式。

一个想法是基于 ptrace() 自己做一个工具,或者通过 dlsym() 找到的代码进行重写,或者在 PLT 中进行重写,目标是 ctypes 生成的可以被 C 调用的函数,但我想先在这里问问大家。谢谢。

2 个回答

2

你可以从ltrace的开发者那里找到一种方法来实现这个功能。可以查看这篇文章,里面有一个完整的补丁,可以用来捕捉动态加载的库。为了从Python中调用这个功能,你可能需要制作一个C语言模块。

2

google-perftools 有自己实现的 Detour,具体代码在 src/windows/preamble_patcher* 这个地方。目前这个实现只适用于 Windows 系统,不过我觉得在其他 x86 机器上也能用,唯一的问题是它用了一些 Windows 特有的函数来查找符号地址。

我简单看了一下代码,发现用了以下几个 Windows 函数,而这些函数在 Linux 上也有对应的版本:

  • GetModuleHandle/GetProcAddress:用来获取函数地址。在 Linux 中可以用 dlsym 来实现。
  • VirtualProtect:用来修改汇编代码。在 Linux 中可以用 mprotect。
  • GetCurrentProcess:在 Linux 中可以用 getpid。
  • FlushInstructionCache(根据评论来看,这个似乎是个无操作的命令)。

把这个编译并链接到 Python 中似乎并不太难,不过我建议还是发个消息给 perftools 的开发者,问问他们的看法。

撰写回答