C++在Linux下怎么使用LD_PRELOAD机制实现动态链接库函数拦截与劫持

秋强小哥_6382

秋强小哥_6382

2026-10-28

513人浏览

原创

LD_PRELOAD是Linux动态链接器的环境变量,用于优先加载指定共享库以拦截动态链接函数;它可拦截malloc、open、read、printf等PLT调用的libc函数,但无法拦截内联函数(如优化后的strlen)或启动期函数(如__libc_start_main)。

c++在linux下怎么使用ld_preload机制实现动态链接库函数拦截与劫持

LD_PRELOAD 是什么,它能拦截哪些函数

LD_PRELOAD 是 Linux 动态链接器(ld-linux.so)的一个环境变量,它让系统在加载主程序依赖的共享库之前,先加载你指定的共享库。只要这个预加载的库导出了与目标函数同名、同签名的符号,运行时就会优先使用你的实现——这就是“劫持”的本质。

它只能拦截通过 PLT(Procedure Linkage Table)调用的动态链接函数,也就是那些在 libc 或其他 .so 中定义、且未被编译器内联或静态链接的函数。像 malloc、open、read、printf 这类标准 C 库函数基本都符合;但 strlen 在某些优化级别下可能被内联,__libc_start_main 这类启动期函数则无法用 LD_PRELOAD 直接覆盖。

  • 必须是动态链接的可执行文件(file ./a.out 输出含 “dynamically linked”)
  • 不能拦截 static inline 函数或编译时已确定地址的调用
  • 不能劫持自身所在库中定义的函数(除非用 dlsym(RTLD_NEXT, ...) 手动跳转)

写一个能被 LD_PRELOAD 加载的拦截库

关键不是“重写所有逻辑”,而是“导出同名函数 + 正确调用原函数”。不调用原实现就容易导致程序崩溃(比如拦截 malloc 却不分配内存)。

最安全的方式是用 dlsym(RTLD_NEXT, "func_name") 获取原始函数地址。RTLD_NEXT 表示“在当前库之后的下一个匹配符号”,这能避开自循环调用。

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>

// 声明原函数类型,必须和 libc 一致
static ssize_t (*real_read)(int fd, void *buf, size_t count) = NULL;

ssize_t read(int fd, void *buf, size_t count) {
    if (!real_read) {
        real_read = (ssize_t (*)(int, void*, size_t)) dlsym(RTLD_NEXT, "read");
    }
    // 可加日志、过滤、修改参数等
    fprintf(stderr, "[intercept] read(%d, %p, %zu)\n", fd, buf, count);
    return real_read(fd, buf, count);
}</stdio.h></dlfcn.h>
  • 必须加 #define _GNU_SOURCE,否则 RTLD_NEXT 不可见
  • 函数签名要完全一致(包括 const/volatile、返回值、参数类型),否则 ABI 错误会导致段错误
  • 不要在 init 函数里提前调用 dlsym,因为此时其他库可能还没加载完;延迟到第一次调用时解析更稳妥

编译、加载与验证的完整流程

编译时不能加 -pie 或 -fPIE(除非你明确处理位置无关代码),但现代发行版默认启用 PIE,所以最好显式关掉:gcc -shared -fPIC -o libintercept.so intercept.c -ldl。

加载方式很简单:

Obsidian (Linux)
Obsidian (Linux)

操作 Obsidian 库(纯 Markdown 笔记),并通过 notesmd-cli 实现自动化。

下载
LD_PRELOAD=./libintercept.so ./your_program

验证是否生效,看输出或用 strace -e trace=read ./your_program 对比前后行为;也可以在拦截函数里写入日志到文件(注意避免递归调用 write 或 fputs 导致死锁)。

  • 如果提示 cannot open shared object file,检查路径是否正确、是否漏了 ./(LD_PRELOAD 不搜索当前目录)
  • 如果程序直接 segfault,大概率是函数签名不匹配,或在 dlsym 返回 NULL 后没判空就调用
  • 用 ldd ./your_program 确认它是动态链接的;用 objdump -T ./your_program | grep read 看是否真有 PLT 条目

绕过拦截、防止被劫持的常见手段

不是所有程序都欢迎被 LD_PRELOAD 劫持。一些敏感程序(如 sudo、ssh)会主动清空环境变量或调用 prctl(PR_SET_NO_NEW_PRIVS) 后禁用 LD_PRELOAD。

更隐蔽的对抗方式包括:用 setuid 程序在启动时自动 unset LD_PRELOAD;或者用 AT_SECURE 标志(由内核设置)让动态链接器忽略该变量。

如果你控制目标程序源码,可用以下方式规避被劫持:

  • 编译时加 -Wl,-z,noexecstack,-z,relro,-z,now 并启用 hardening,虽不直接禁用 LD_PRELOAD,但提高利用门槛
  • 对关键函数用 __attribute__((visibility("hidden"))) 或链接脚本隐藏符号(仅影响你自己写的库)
  • 用 syscall(SYS_read, ...) 绕过 libc 封装(但失去 portability 和缓冲区优化)

真正难搞的是那些既没 setuid 又没加固、还重度依赖 libc 的服务进程——它们最容易成为 LD_PRELOAD 劫持的目标,也最容易因拦截逻辑缺陷而崩掉。写拦截库时,别只想着“我能改什么”,得多想“我改错后它会怎么挂”。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++ c++编程 c++安全 linux

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.14

2268

9

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

1039

6

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

447

5

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

327

5

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

426

5

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

600

5

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.21

1429

9

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

2024.03.22

1237

7

c++和c语言学习顺序推荐
c++和c语言学习顺序推荐

对于初学者,建议先学习C语言,掌握编程基础后再转入C++,便于理解面向对象编程概念。有编程经验者可直接学习C++,快速接触高级编程技术。想了解更多c++和c语言的相关内容,可以阅读本专题下面的文章。

2024.03.25

1325

9

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习