You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过LD_PRELOAD定位调用openat系统调用的待拦截函数?

定位LD_PRELOAD需拦截的openat相关函数

首先得明确一个关键差异:strace追踪的是内核态的系统调用,而LD_PRELOAD只能拦截用户态动态链接的库函数。你之前试的openat、openat64等函数没生效,大概率是因为程序实际调用的不是这些公开的libc封装函数,或者甚至直接绕过libc用syscall指令调用了openat。

下面是不用逐个排查的高效定位方法:

1. 用ltrace追踪用户态函数调用(最直接)

ltrace专门追踪用户态的库函数调用,能直接告诉你程序实际调用了哪个函数来发起openat操作,完全不用猜。执行:

ltrace -f /sbin/depmod 3.10.0-693.17.1.el7.x86_64

输出里会清晰显示类似openat(AT_FDCWD, "/some/path", O_RDONLY|O_CLOEXEC) = 3的行,这里的openat就是你需要拦截的函数名——如果显示的是其他名字(比如__openat、__openat64_2),直接拦截那个名字就行。

2. 分析程序的PLT(过程链接表)

PLT里记录了程序所有需要动态链接的外部函数,是LD_PRELOAD能拦截的唯一目标集合。用objdump或readelf查看:

# 用objdump看PLT里的open相关函数
objdump -R /sbin/depmod | grep -i open

# 或者用readelf看动态符号表
readelf -s /sbin/depmod | grep -i open

输出里的符号就是程序实际会调用的动态函数,比如如果看到__openat64,那就是你要拦截的目标——之前用readelf -p .dynstr可能漏看了,因为.dynstr是字符串表,而动态符号表(-s参数)更准确。

3. 检查是否直接调用syscall(绕过libc)

有些程序为了性能,会直接用汇编指令调用syscall,不经过libc的封装函数。这种情况下LD_PRELOAD的普通函数拦截无效,你需要:

  1. 先确认是否存在直接syscall:
# x86_64下openat的syscall号是257,搜索对应的指令
objdump -d /sbin/depmod | grep -A2 -B2 0xf7  # 0xf7是syscall号257的十六进制
  1. 如果确实是直接syscall,你可以尝试拦截syscall函数本身(如果程序用了libc的syscall()封装),或者改用ptrace工具、内核模块来拦截系统调用。

4. 确认程序是否为动态链接

如果/sbin/depmod是静态链接的,LD_PRELOAD完全不起作用——先执行file /sbin/depmod确认:

file /sbin/depmod

如果输出显示statically linked,那你得换其他拦截方式了(比如ptrace、eBPF)。


内容的提问来源于stack exchange,提问作者Mark Galeck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:12:16