跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

如何排查Linux系统中通过LD_PRELOAD植入的系统调用拦截

排查LD_PRELOAD拦截需四步:一查环境变量是否设置;二溯来源(用户/系统/容器/systemd);三析so库导出函数及依赖;四验生效性(区分setuid限制、检查/proc/pid/environ和/etc/ld.so.preload)。 排查 LD_PRELOAD 植入的系统调用拦截,关键不是“有没有设”,而是“谁设的、设给谁、设了什么、是否生效”。它不留下明显进程或文件痕迹,但会在动态链接阶段悄然介入。下面分四步直击核心。 一、确认当前环境是否存在 LD_PRELOAD 设置 这是最快速的第一筛。很多报错(如
LD_PRELOAD cannot be preloaded
)就源于此变量残留: 运行
echo $LD_PRELOAD
查看是否非空;若输出路径,记下该 .so 文件名和路径 检查是否被子 shell 或服务继承:在新终端中执行同一命令,对比结果 注意空格和引号干扰——有时变量值含多余空格或未闭合引号,也会导致加载失败但不报错 二、追溯 LD_PRELOAD 的来源位置 变量可能来自多个层级,需逐层排查: Docker Desktop(linux) 当前 Docker 最新稳定版本之一,主要针对稳定性和兼容性进行了修复优化,适合生产环境与日常开发使用。该版本继续强化 AI 开发支持、容器日志管理以及 Docker Engine 的安全能力,对 Windows/macOS/Linux 平台兼容性进行了进一步优化。 下载 用户级配置:搜索
~/.bashrc
、
~/.bash_profile
、
~/.zshrc
、
~/.profile
中的
export LD_PRELOAD=
或
unset LD_PRELOAD
后又重新赋值的情况 系统级配置:检查
/etc/environment
、
/etc/profile
、
/etc/profile.d/*.sh
,尤其留意由 CUDA、NVIDIA 驱动、安全审计工具或监控 agent 自动写入的脚本 容器与编排环境:Docker 启动时用
--env LD_PRELOAD=...
;Kubernetes Pod 的
env:
字段或 initContainer 中可能硬编码该变量 systemd 服务:对可疑服务运行
systemctl show --property=Environment
,查看是否注入了 LD_PRELOAD 三、分析预加载库的行为特征 即使找到 .so 文件,也不能只看文件名。要验证它是否真在拦截系统调用: 用
file
和
readelf -h
确认架构匹配(如 x86_64 程序不能加载 i386 so) 用
nm -D /path/to/libxxx.so | grep -E "(open|read|write|exec|fork|malloc)"
查看是否导出常见被 hook 函数 用
ldd /path/to/libxxx.so
看它自身是否依赖异常库(如链接了
libprocesshider.so
这类已知隐藏工具) 临时启用 strace 观察:启动一个简单程序并加 LD_PRELOAD,再运行
strace -e trace=openat,open,execve -f ./your_program 2>&1 | grep -E "(open|exec)"
,比对函数调用前后行为变化 四、检测运行时是否实际生效 LD_PRELOAD 对 setuid 程序(如
sudo
、
passwd
)默认无效,glibc 会主动清空该变量。因此需区分场景: 对普通用户程序:用
cat /proc/$(pidof your_program)/environ | tr '\0' '\n' | grep LD_PRELOAD
确认进程内变量真实值 检查是否被绕过:运行
ls -l /usr/bin/sudo
,若权限含
s
(如
-rwsr-xr-x
),说明 LD_PRELOAD 在该进程里必然失效 全局生效的真正后门是
/etc/ld.so.preload
—— 它无需环境变量,所有动态链接程序都会加载。用
lsattr /etc/ld.so.preload
和
stat /etc/ld.so.preload
检查是否被篡改或锁定 若怀疑隐蔽 hook,可对比
ps aux
与
ls /proc/[0-9]* 2>/dev/null | cut -d'/' -f3 | sort -u
的 PID 差异,缺失的 PID 可能被 LD_PRELOAD + readdir hook 隐藏

相关文章