linux - 如何找出LD_PRELOAD要拦截哪些函数?

标签 linux elf ld-preload

我正在尝试使用LD_PRELOAD机制拦截所有使用库comm.so调用系统调用openat的动态加载函数。

考虑以下 /sbin/depmod 命令的使用:

#strace -f /sbin/depmod 3.10.0-693.17.1.el7.x86_64

(...)

openat(AT_FDCWD, "/lib/modules/3.10.0-693.17.1.el7.x86_64", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3

我想拦截调用此openat系统调用的函数。

如何找出该功能是什么? openat(可能是别名)和任何其他类似的函数都不起作用 - 没有任何内容被拦截。

我尝试使用此命令来查找我的命令正在使用哪些动态加载的函数:

#readelf -p .dynstr /sbin/depmod 

这会打印出一些 .so 库,因此我递归地对它们使用了 readelf 。在递归结束时,我有以下包含 openat 的函数列表:

openat
openat64
open_by_handle_at
__openat64_2

这些都不起作用 - 它们不会拦截返回文件描述符 3 的调用。

好的,那么如何找出我还需要拦截哪些其他函数呢?我是否必须一一递归地遍历 readelf 命令显示的所有函数(有很多)?

最佳答案

可以在不使用 openat 函数的情况下调用 openat 系统调用(或任何其他系统调用,请参阅 syscalls(2) 获取列表)来自标准库;可以从 ld-linux(8) 调用它(处理 LD_PRELOAD)。在我的 Debian/Sid 系统上,动态链接器 /lib/ld-linux.so.2 正在使用 openat 系统调用(例如尝试 strace/bin/true),当然它使用自己的 openopenat 函数(不是 libc.so 中的函数)。

任何系统调用都可以(原则上)通过直接机器代码(例如一些适当的SYSENTER机器指令)或通过一些间接syscall(2)来调用。 (并且在这两种情况下都不会使用 openat C 函数)。也许参见Linux Assembly HowTo了解更多和 Linux x86 ABI规范。

如果你想拦截所有这些(包括那些由ld-linux完成的,这很奇怪),你需要使用ptrace(2)以类似于 strace(1) 的方式使用 PTRACE_SYSCALL 。此时您将能够获取程序计数器和调用堆栈。

如果您关心以下文件和文件描述符,另请考虑 inotify(7)设施。

如果您使用gdb(在没有DWARF调试信息的程序上使用它可能会很痛苦),您可以 use catch syscall (在 gdb 中使用 ptrace PTRACE_SYSCALL 的方法)找出(并且可能“中断”)每个原始系统调用。

顺便说一句,可能有一些C standard libraries使用 openat 系统调用(或在其他地方使用 openat)来实现他们的 open C 函数。通过研究特定 libc.so 的源代码进行检查(可能是 GNU glibc ,也可能是 musl-libc )。

关于linux - 如何找出LD_PRELOAD要拦截哪些函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49314057/

相关文章:

c - 在 C 中隐藏函数

linux - 使用 Linux 发行版时在 Windows 下隐藏文件/文件夹

linux - nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) 即使在使用端口 80 终止进程之后

linux - rlwrap 中的 LD_PRELOAD?

c - .data + .bss的ELF二次加载段地址

arm - 为什么在 ARM 二进制文件上显示 readelf 奇数入口点地址?

c - 为什么 LD_PRELOAD 与系统调用一起工作?

python - 我如何在 Python 中的两个不同进程之间共享一个串口

linux - Unix 和 Linux/proc PID 系统

c - 如何将 ELF 可执行文件转换为 C 代码?生成的 C 代码不需要是人类可读的