当前位置: 首页 > news >正文

深入glibc源码:图解_dl_fixup如何解析动态链接函数(附ret2dlresolve利用原理)

深入glibc源码:图解_dl_fixup如何解析动态链接函数

在Linux系统的动态链接机制中,_dl_fixup函数扮演着至关重要的角色。本文将带您深入glibc-2.23源码,通过图解方式剖析这个关键函数的运作原理,并揭示其与ret2dlresolve攻击技术的内在联系。

1. 动态链接基础架构

动态链接是现代操作系统实现代码共享的核心机制。当一个程序调用动态链接库中的函数时,系统不会立即加载该函数的实际代码,而是采用"延迟绑定"(Lazy Binding)技术,在函数第一次被调用时才进行解析和加载。

这种机制依赖于几个关键数据结构:

  • PLT(Procedure Linkage Table):程序链接表,包含跳转到GOT的指令
  • GOT(Global Offset Table):全局偏移表,存储函数地址
  • .rel.plt:重定位表,记录需要重定位的函数信息
  • .dynsym:动态符号表,存储符号信息
  • .dynstr:动态字符串表,存储函数名等字符串

当程序第一次调用动态链接函数时,会经历以下流程:

  1. 跳转到PLT表对应条目
  2. PLT条目跳转到GOT中存储的地址
  3. 第一次调用时,GOT指向PLT中的下一条指令
  4. 该指令将重定位参数压栈并跳转到PLT[0]
  5. PLT[0]将link_map压栈并跳转到_dl_runtime_resolve

2. _dl_fixup函数源码解析

_dl_fixup是动态链接解析的核心函数,位于glibc的dl-runtime.c文件中。让我们逐段分析其实现:

_dl_fixup (struct link_map *l, ElfW(Word) reloc_arg) { // 获取符号表地址 const ElfW(Sym) *const symtab = (const void *) D_PTR (l, l_info[DT_SYMTAB]); // 获取字符串表地址 const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]); // 计算重定位项地址 const PLTREL *const reloc = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset); // 获取符号表项 const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)]; // 检查重定位类型 assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);

这段代码展示了_dl_fixup如何通过link_map结构访问各种关键数据结构。其中:

  • l_info数组存储了动态段的各种信息
  • DT_JMPREL指向.rel.plt
  • DT_SYMTAB指向.dynsym
  • DT_STRTAB指向.dynstr

函数接着进行符号查找:

if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0) { // 复杂查找路径 result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope, version, ELF_RTYPE_CLASS_PLT, flags, NULL); value = DL_FIXUP_MAKE_VALUE (result, sym ? (LOOKUP_VALUE_ADDRESS (result) + sym->st_value) : 0); } else { // 简化查找路径 value = DL_FIXUP_MAKE_VALUE (l, l->l_addr + sym->st_value); result = l; }

最后,函数将解析得到的地址写入GOT表:

// 写入GOT表 return elf_machine_fixup_plt (l, result, reloc, rel_addr, value);

3. 关键数据结构详解

理解_dl_fixup需要熟悉几个核心数据结构:

3.1 Elf32_Rel结构体

32位系统下的重定位项结构:

typedef struct { Elf32_Addr r_offset; // 需要重定位的地址 Elf32_Word r_info; // 符号索引和重定位类型 } Elf32_Rel;
  • r_offset:指向GOT表中需要修改的位置
  • r_info:低8位表示重定位类型,高24位表示符号表索引

3.2 Elf32_Sym结构体

符号表项结构:

typedef struct { Elf32_Word st_name; // 符号名在字符串表中的偏移 Elf32_Addr st_value; // 符号值 Elf32_Word st_size; // 符号大小 unsigned char st_info;// 符号类型和绑定属性 unsigned char st_other;// 符号可见性 Elf32_Section st_shndx;// 节区索引 } Elf32_Sym;

3.3 link_map结构

link_map是动态链接器的核心数据结构,包含模块的加载信息和各种表的指针:

struct link_map { ElfW(Addr) l_addr; // 模块加载基址 char *l_name; // 模块名称 ElfW(Dyn) *l_ld; // 动态段指针 struct link_map *l_next, *l_prev; // 链表指针 // 更多字段... };

4. ret2dlresolve攻击原理

ret2dlresolve攻击正是基于对_dl_fixup函数解析过程的理解。攻击者通过伪造关键数据结构,"欺骗"动态链接器解析并执行任意函数。

攻击步骤通常包括:

  1. 控制reloc_arg:使重定位项指向可控内存区域
  2. 伪造Elf32_Rel结构:控制r_info指向伪造的符号表项
  3. 伪造Elf32_Sym结构:控制st_name指向伪造的字符串
  4. 伪造函数名字符串:将目标函数名(如"system")写入内存

下表展示了正常解析与攻击伪造的对比:

步骤正常解析ret2dlresolve攻击
重定位项.rel.plt中的合法项伪造的Elf32_Rel结构
符号表项.dynsym中的合法项伪造的Elf32_Sym结构
字符串.dynstr中的函数名伪造的字符串(如"system")

5. 64位系统的特殊考量

64位系统下的ret2dlresolve攻击面临额外挑战:

  1. 数据结构差异

    • 重定位项使用Elf64_Rela结构,包含64位字段和addend
    • 符号表项大小为24字节
  2. 额外验证

    if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL) { const ElfW(Half) *vernum = (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]); ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff; // ... }

    这段代码会检查符号版本信息,如果伪造的符号表索引过大,可能导致越界访问。

解决方案通常包括:

  • 设置st_other不为0,跳过版本检查
  • 精心构造伪造数据,使索引值合法

6. 防御措施与绕过技术

现代系统采用了多种防护措施对抗ret2dlresolve攻击:

  1. RELRO保护

    • No RELRO:.dynamic等段可写,攻击最简单
    • Partial RELRO:部分段只读,增加攻击难度
    • Full RELRO:所有段在启动时解析并设为只读
  2. 绕过技术

    • 对于Partial RELRO,可以伪造整个link_map结构
    • 利用已解析函数的GOT条目作为伪造的符号表
# 示例:伪造link_map的Python代码片段 def fake_linkmap(fake_addr, known_got, offset): linkmap = p64(offset & (2**64-1)) # l_addr linkmap += p64(0) # 填充 linkmap += p64(fake_addr + 0x18) # DT_JMPREL指针 # 更多伪造数据... return linkmap

7. 实际应用与思考

理解_dl_fixup不仅有助于安全研究,还能加深对动态链接机制的认识。在实际应用中,我们需要注意:

  1. 内存布局:精心安排伪造数据的内存位置
  2. 对齐要求:符号表项需要16字节对齐(32位)或24字节对齐(64位)
  3. 参数控制:确保函数调用时的参数正确传递

通过深入分析glibc源码和动态链接过程,我们不仅能掌握ret2dlresolve攻击技术,更能理解Linux系统底层的工作机制。这种从原理到实践的认知路径,正是安全研究最具价值的部分。

http://www.rkmt.cn/news/1466001.html

相关文章:

  • 零基础入门:在快马平台上手YOLOv8目标检测第一课
  • 告别卡顿与闪退:Quartus II 13.1在Win10/Win11下的稳定运行与性能优化配置全攻略
  • MATLAB行星齿轮动力学仿真脚本:含ode45求解器与完整系统建模函数
  • 别再只调参了!遗传算法解VRP时,这3个编码细节才是性能关键
  • MinerU2.5 Pro技术解析:1.2B参数SOTA PDF解析模型,完整部署教程(Transformers/vLLM/SGLang/Docker)
  • 给Jetson Nano B01换颗‘中国心’:手把手教你配置清华源并安装Python全家桶
  • C#上位机开发笔记:封装一个稳定可靠的欧姆龙NX PLC通信类库(附源码)
  • 用NodeMCU和Blinker自制万能红外遥控器,手把手教你让旧家电秒变智能(附完整代码)
  • Anaconda安装后必做的三件事:验证、配环境变量、创建你的第一个Python 3.8虚拟空间
  • 别再死磕D-H参数了!用Matlab Robotic Toolbox 10.4快速复现一个四轴机械臂(附完整代码)
  • LLM投毒:大模型数据层精准攻击与七道防御体系
  • 保姆级教程:用ROS和MAVROS搞定PX4 Offboard模式(附避坑指南)
  • 正统传承视角下的汕头高端私房菜核心技术标准拆解 - 奔跑123
  • 从漏洞原理到安全加固:手把手带你分析并修复ActiveMQ 5.x的Fileserver漏洞
  • 从自动驾驶到商品推荐:聊聊Smooth L1 Loss为何成了YOLO、Faster R-CNN的‘心头好’
  • MCP会成为AI时代的新中间件吗?
  • 挑选好用的固体饮料贴牌公司可以参考哪些参考依据?
  • 2026上海浦东可长短租的服务公寓!商务家庭租住全能适配 - 资讯速览
  • 真空脱泡搅拌机常见问题解答(2026最新专家版) - 资讯速览
  • 2026贵阳近郊烧烤山庄与团建聚餐一站式服务深度指南 - 企业名录优选推荐
  • HFSS新手避坑指南:手把手教你搞定威尔金森功分器仿真(附参数文件)
  • 从云端到边缘:基于土星云SE110S的智能视频分析轻量化部署方案(下)
  • 2026杭州室内游玩乐园新地标TOP5|室内浪漫避雨避晒,城市秘境成热门首选 - 资讯速览
  • HR系统选型第一步不是看产品,是做这件事|90%的人顺序搞反了
  • 2026年宜宾高县水上赛事完全选购指南 - 企业名录优选推荐
  • 提升学历,为什么一定要选正规函授站?本部、中介、函授站到底差在哪? - 奔跑123
  • 从0到1:打造99.99%高可用在线CRM系统的技术架构与实践
  • Web渗透之SQL注入-文件读写-木马植入
  • 告别百度地图API!用JTS+GeoTools搞定Java空间几何计算(含坐标系转换避坑)
  • MuleSoft+LLM企业级AI编排实战:语义集成与生产级防护