南京大学 操作系统 (JYY) 学习笔记:动态链接的黑魔法与内存入侵 (Dynamic Linking)
写在前面这是本系列的第十一篇。在前几讲中我们已经知道进程从execve的初始状态开始可以通过mmap改变地址空间通过fork创建新进程。只要有 ELF 可执行文件把它的PT_LOAD数据段正确映射到内存里程序就能跑起来就像我们的 Funny Little Executable 实验。但本讲要面对一个更庞大的工程问题当开发者希望把库函数如 libc和应用程序“分离”开但又希望在运行时能随时调用库函数该怎么办课前补课静态链接 vs 动态链接静态链接库 (.a / .lib):就像是一个提前打包好的工具箱。当你写程序时编译器会把你需要的加法、减法等功能代码**直接死死地“拷贝”**到你的最终可执行文件ELF里。程序变大了但它完全独立不需要依赖外界。动态链接库 (.so / .dll):就好比是一个放在外面广场上的“共享工具箱”。程序里只留一张欠条符号表。当程序真正运行起来时操作系统再去找到这个共享库在运行时把它们拼在一起。就像租用工具随用随借。动态链接机制与为什么需要它我们熟悉的 Windows 下的.dll或者 Linux 下的.so(Shared Object)都是动态链接的产物。为什么要“拆解”应用程序早期的时候游戏如果需要用到d3dx9_xxx.dll里的功能就会把整个库静态链接进游戏本体。结果每个游戏都复制了一份庞大的图形库硬盘和内存瞬间爆炸。1. 实现运行库和应用代码分离 (应用间共享)每个 C 程序都需要glibc。如果使用动态链接整个操作系统内存里只需要一个 libc 的物理副本成百上千个进程同时共享它。运行库和应用程序可以独立升级互不干扰。2. 大型项目的工程分解比如庞大的 Android 源码改一行代码如果需要重新链接生成 2GB 的大文件程序员会疯掉的。拆分成libjvm.so,libart.so每次只编译更新那个.so文件即可。可以用ldd和file命令来观察rootLAPTOP-GT06V0GS:~# ldd /bin/lslinux-vdso.so.1(0x00007ffe950d8000)libc.so.6/lib/x86_64-linux-gnu/libc.so.6(0x00007f829a846000)... rootLAPTOP-GT06V0GS:~# file /lib/x86_64-linux-gnu/libselinux.so.1/lib/x86_64-linux-gnu/libselinux.so.1: ELF64-bit LSB shared object, dynamically linked...动态链接的阴暗面供应链攻击与依赖地狱任何技术都有代价。库的依赖本质上也是一种代码克隆甚至把风险也克隆了过来。xz-utils (liblzma) 投毒事件 (CVE-2024-3094):震惊全球的安全事件黑客 JiaT75 潜伏开源社区长达三年获取信任成为维护者后巧妙绕开 fuzz 测试向基础压缩库投毒。导致全球依赖这个.so的 Linux 系统的 SSHD 均面临后门风险。如果 Linux 全是静态链接的呢如果不用动态链接一旦libc出了安全漏洞你需要把全系统几万个应用程序全部重新编译链接一次这是不可能完成的任务。Dependency Hell (依赖地狱):A 依赖 B 的 v1 版本C 依赖 B 的 v2 版本而你的项目同时依赖 A 和 C。当这种依赖嵌套成网状时版本冲突和不兼容更新就会让人彻底崩溃。感谢动态链接库虽然有坑但如果没有它现代计算机世界早就崩塌了。揭秘底层引擎mmap 和虚拟内存一个极其狂野的实验我们构造一个包含 100MB 无用代码 (nop指令) 的巨型共享库libbloat.so。然后同时启动1000个动态链接了这个库的进程问题系统的物理内存会被消耗 100MB 还是 100GB如果是 100GB电脑瞬间死机宕机。答案只消耗 100MB共享库加载的真相 (没有魔法)你执行./a.out时第一条被执行的指令根本不在你的代码里它是操作系统通过读取 ELF 文件头的INTERP(Interpreter) 段去调用了动态链接器如/lib64/ld-linux-x86-64.so.2。链接器使用mmap系统调用把libc等共享库映射到内存中。核心魔法只读方式mmap同一个文件物理内存中只有一份真实的副本。1000 个进程的页表全都指向同一块物理内存。操作系统的内存 Tricks地址空间表面上看是“若干连续的内存段”实际全是操作系统用分页机制虚构出来的幻象延迟加载 (Lazy Allocation):不到万不得已触发 Page Fault绝不给进程分配真物理内存。写时复制 (Copy-on-Write, COW):fork()时父子进程共享内存。只有当某一方试图写入时操作系统才紧急复制一份Page fault 时写者复制一份。内存去重 (Memory Deduplication):操作系统在后台悄悄扫描内存如果发现有两页内容完全一样的只读页就悄悄合并它们内存压缩与 Swapping:扫描发现某些内存页很久没人用了Cold pages就把它压缩或者扔到硬盘交换区里。实现动态链接GOT 与 PLT 的诞生如果把动态链接交给你来设计你会怎么做方案1加载时重定位 (libc.o)把程序和库一起搬进内存加载时暴力修改所有引用了库函数的地址。缺点极慢链接器需要解析成千上万个根本不会被运行的符号并且修改代码会导致代码页无法被多个进程共享因为每个进程加载的基地址不同。方案2位置无关代码 (Position-Independent Code, PIC)这就对了我们需要映射同一个libc.so并且无论它被加载到哪个虚拟地址代码都必须能正常运行。A Layer of Indirection (引入一个间接层)难题main调用了.so库里的printf但printf在运行时的地址是未知的。我们该用什么汇编指令跳过去编译器的选择 1全部查表跳转。每次调用都多查一次内存表。对于极其高频的函数性能损失不可忍受。编译器的选择 2全部直接跳转。但 x86 的call指令只支持 4 字节的相对偏移而libc.so可能被映射到了离当前代码十万八千里远的高位地址偏移量超出了 32 位极限根本跳不过去伟大的发明PLT 与 GOT为了兼顾性能和位置无关计算机先驱们发明了组合拳GOT (Global Offset Table - 全局偏移表):这本质上是一个存放指针的数组放在.data数据段里。加载时动态链接器把真正的printf物理地址填进这个数组。PLT (Procedure Linkage Table - 过程链接表):在可执行文件的代码段里“合成”一段跳板代码蹦床printfplt: jmp *GOT_PRINTF_OFFSET(%rip)调用流程你的代码call printfplt$ \rightarrow $ 跳转到蹦床 $ \rightarrow $ 蹦床去 GOT 表里读取真正的绝对地址 $ \rightarrow $ 跳进libc.so对于全局变量extern int x怎么办不能用间接跳转指令了。编译器一旦开启了-fPIC就会强制为所有的外部变量增加一层间接寻址必须去 GOT 表里拿一遍指针再解引用。这必然带来一定的性能损耗。终极黑魔法LD_PRELOAD计算机世界里没有黑魔法所有的“外挂”都有迹可循。LD_PRELOAD是 Linux 动态链接器提供的一个环境变量。它允许你强行指定一个动态链接库使其在程序启动时被最高优先级加载。LD_PRELOAD./mylib.so ./a.out它是怎么实现拦截Hook的因为动态链接器在解析符号比如找malloc在哪时是按照顺序查找的。如果你的mylib.so里也写了一个叫malloc的函数链接器找到它之后就不会再往下找glibc里的malloc了这样你就在不修改原本a.out代码的情况下成功劫持并替换了它的系统底层函数。rootLAPTOP-GT06V0GS:/mnt/d/CSLab/osCourse/lec11/ldpreload# ./test_programTesting malloc/free hooks...# 成功的拦截程序每一次申请内存都被我们预先加载的恶意/监控代码记录了下来Allocated100bytes at 0x55ba218c86b0 Allocated200bytes at 0x55ba218c8720Take-away Messages (总结)找到正确的思路我们就能在复杂的机制中找到主干在动态链接的例子里我们理解了为了实现位置无关和代码共享先驱们创造了 ELF 中的GOT(Global Offset Table) 和PLT(Procedure Linkage Table)。而正是这种动态寻址机制赋予了我们利用LD_PRELOAD进行函数 Hook 的极客能力。

相关新闻

Windows RTMP直播服务器终极指南:5分钟快速搭建专业流媒体平台

Windows RTMP直播服务器终极指南:5分钟快速搭建专业流媒体平台

Windows RTMP直播服务器终极指南:5分钟快速搭建专业流媒体平台 【免费下载链接】nginx-rtmp-win32 Nginx-rtmp-module Windows builds. 项目地址: https://gitcode.com/gh_mirrors/ng/nginx-rtmp-win32 想在Windows系统上快速搭建一个专业的RTMP直播服务器吗…

2026/7/29 20:00:35 阅读更多 →
消息队列选型对比:RabbitMQ、Kafka 与 Redis Stream 的适用边界

消息队列选型对比:RabbitMQ、Kafka 与 Redis Stream 的适用边界

消息队列选型对比:RabbitMQ、Kafka 与 Redis Stream 的适用边界 一、深度引言与场景痛点:一条消息延迟了 10 秒,用户以为系统坏了 7 月在刷题系统中实现了一个"AI 题解生成"的异步功能:用户提交题目后,系统将…

2026/7/29 20:00:35 阅读更多 →
宠物商城托运一体化搭建,宠物档案绑定商品物流全流程

宠物商城托运一体化搭建,宠物档案绑定商品物流全流程

宠物商城托运一体化搭建,宠物档案绑定商品物流全流程当下宠物服务类小程序与平台逐步从单一用品售卖、单一托运服务,转向商城购物、活体托运、宠物档案管理一体化的综合运营模式。很多宠物平台在实际搭建中,普遍存在宠物档案、商城订单、托运…

2026/7/29 19:59:34 阅读更多 →

最新新闻

Java反混淆终极指南:如何使用Java-Deobfuscator轻松还原被混淆的代码

Java反混淆终极指南:如何使用Java-Deobfuscator轻松还原被混淆的代码

Java反混淆终极指南:如何使用Java-Deobfuscator轻松还原被混淆的代码 【免费下载链接】deobfuscator The real deal 项目地址: https://gitcode.com/gh_mirrors/de/deobfuscator Java-Deobfuscator是一款功能强大的Java反混淆工具,专门用于对抗市…

2026/7/29 20:13:39 阅读更多 →
猫抓插件终极指南:零门槛掌握免费网页资源嗅探

猫抓插件终极指南:零门槛掌握免费网页资源嗅探

猫抓插件终极指南:零门槛掌握免费网页资源嗅探 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 还在为无法下载网页上的视频、音频而烦恼…

2026/7/29 20:13:39 阅读更多 →
猫抓浏览器插件:5分钟掌握免费资源嗅探的终极技巧

猫抓浏览器插件:5分钟掌握免费资源嗅探的终极技巧

猫抓浏览器插件:5分钟掌握免费资源嗅探的终极技巧 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 猫抓浏览器插件是一款强大的免费资源…

2026/7/29 20:13:39 阅读更多 →
信号与系统:从傅里叶变换到数字滤波,掌握信息处理的底层逻辑

信号与系统:从傅里叶变换到数字滤波,掌握信息处理的底层逻辑

1. 从“信号”与“系统”的日常误解谈起如果你问一个非电子或通信专业的朋友,听到“信号与系统”这个词会想到什么,大概率会得到“手机信号”、“Wi-Fi信号”或者“操作系统”这类答案。这很正常,因为“信号”和“系统”这两个词在我们的日常…

2026/7/29 20:13:39 阅读更多 →
FFXVIFix终极指南:免费解锁《最终幻想16》超宽屏与帧率限制的完整解决方案

FFXVIFix终极指南:免费解锁《最终幻想16》超宽屏与帧率限制的完整解决方案

FFXVIFix终极指南:免费解锁《最终幻想16》超宽屏与帧率限制的完整解决方案 【免费下载链接】FFXVIFix Migrated to https://codeberg.org/Lyall/FFXVIFix 项目地址: https://gitcode.com/gh_mirrors/ff/FFXVIFix 还在为《最终幻想16》的画面限制而烦恼吗&…

2026/7/29 20:13:39 阅读更多 →
如何快速上手LiveCodeBench?从安装到首次评估的完整教程

如何快速上手LiveCodeBench?从安装到首次评估的完整教程

如何快速上手LiveCodeBench?从安装到首次评估的完整教程 【免费下载链接】LiveCodeBench Official repository for the paper "LiveCodeBench: Holistic and Contamination Free Evaluation of Large Language Models for Code" 项目地址: https://gitc…

2026/7/29 20:12:38 阅读更多 →

日新闻

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

一、本文介绍 🔥本文在RT-DETR多模态融合目标检测中引入RLAB残差线性注意力模块,可在不同模态特征交互阶段进行多次残差细化,使可见光、红外等特征在尺度、语义和空间位置上更好对齐;随后将细化特征与解码器输出拼接并生成Q、K、V,通过线性注意力自适应强化关键通道、目…

2026/7/29 0:00:23 阅读更多 →
AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础

AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础

AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础 在上一期「AI编程系列」中,我们学习了如何构建一个基础的 AI 问答系统,通过简单的输入输出让模型回应问题。但现实世界中的 AI 应用往往需要处理更复杂的场景:…

2026/7/29 0:00:23 阅读更多 →
AI智能体开发实战:从工具调用到企业级部署

AI智能体开发实战:从工具调用到企业级部署

1. 从被动问答到主动执行:AI Agent的范式转变过去两年,大语言模型最显著的应用形态是聊天机器人——用户提问,AI回答。但真正的生产力革命发生在2023年下半年:当AI学会主动调用工具完成任务时,生产力工具的历史被彻底改…

2026/7/29 0:00:23 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/28 12:04:22 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/29 15:00:03 阅读更多 →

月新闻