ret2resolve深入分析—以x86、x64视角
字数 1980 2025-08-24 07:48:34

ret2resolve技术深入分析 - x86与x64架构视角

基本概念

ret2resolve是一种利用动态链接机制中延迟绑定特性的攻击技术。让我们通过一个简单例子来理解基本概念:

#include <stdio.h>
int main() {
    puts("Hello Pwn\n");
    return 0;
}
// 编译命令: gcc -m32 -fno-stack-protector -no-pie -s hellopwn.c

动态链接关键机制

  1. 延迟绑定(Lazy Binding): 函数在第一次调用时才进行解析和绑定
  2. _dl_runtime_resolve: 负责解析函数地址的核心例程,签名: _dl_runtime_resolve(link_map, reloc_arg)

关键数据结构

1. .dynamic节区

包含动态链接需要的信息,重点关注三项:

  • DT_STRTAB: 指向.dynstr节区
  • DT_SYMTAB: 指向.dynsym节区
  • DT_JMPREL: 指向.rel.plt节区

2. .dynstr节区

字符串表,包含动态链接用到的字符串(包括函数名),每个以0结尾。

3. .dynsym节区

符号表(结构体数组),记录符号信息。关键结构体:

typedef struct {
    Elf32_Word st_name;  // 符号名在.dynstr中的偏移
    Elf32_Addr st_value;
    Elf32_Word st_size;
    unsigned char st_info;  // 对于导入函数符号,值为0x12
    unsigned char st_other;
    Elf32_Section st_shndx;
} Elf32_Sym;

4. .rel.plt节区

重定位表(结构体数组),每个结构体对应一个导入函数:

typedef struct {
    Elf32_Addr r_offset;  // 指向GOT表的指针
    Elf32_Word r_info;    // 符号在.dynsym中的下标(右移8位)
} Elf32_Rel;

_dl_runtime_resolve工作流程

  1. 访问.dynamic,获取.dynsym、.dynstr、.rel.plt指针
  2. .rel.plt + reloc_arg获取当前函数的重定位表项指针(rel)
  3. rel->r_info >> 8作为.dynsym下标,获取符号表项指针(sym)
  4. .dynstr + sym->st_name得到符号名字符串指针
  5. 在动态库中查找函数地址,写入*rel->r_offset(GOT表)
  6. 调用该函数

x86架构利用技术

利用方式1:修改.dynamic节区(No RELRO)

适用条件: .dynamic节区可写(No RELRO保护)

攻击思路:

  1. 修改.dynamic中的.dynstr指针,指向可控区域
  2. 在可控区域伪造函数名字符串(如将"free"改为"system")
  3. 触发目标函数调用

示例攻击步骤:

  1. 在bss段伪造.dynstr结构
  2. 计算free和system字符串的偏移差异
  3. 通过堆溢出修改.dynamic中的strtab指针
  4. 触发free调用实际执行system

利用方式2:控制reloc_arg(Partial RELRO)

适用条件: .dynamic不可写(Partial RELRO)

攻击思路:

  1. 控制_dl_runtime_resolve的reloc_arg参数
  2. 使.rel.plt + reloc_arg指向可控区域
  3. 伪造重定位表项(Elf32_Rel)
  4. 通过r_info控制符号表项
  5. 伪造符号名字符串

关键技术点:

  1. 伪造的r_info构造: (index << 8) | 0x7,其中index是伪造符号表项的下标
  2. 符号表项对齐: Elf32_Sym结构体大小为0x10,需要对齐
  3. st_name计算: 伪造字符串地址 - .dynstr基址

完整攻击链:

  1. 栈迁移到bss段
  2. 第一次read: 将payload写入bss
  3. 构造伪造的rel和sym结构
  4. 调用plt[0]触发_dl_runtime_resolve
  5. 通过伪造结构最终执行system("/bin/sh")

x64架构利用技术

x64架构利用原理与x86类似,但有以下差异:

  1. 参数通过寄存器传递,不需要栈迁移
  2. 可利用的ROP gadget更多样
  3. 结构体大小和对齐方式不同

典型攻击步骤:

  1. 第一次read: 将"/bin/sh"和伪造的.dynstr写入bss
  2. 第二次read: 修改.dynamic中的dynstr指针
  3. 调用plt[0]触发_dl_fixup
  4. 通过伪造的dynstr使解析结果为system

关键点:

  • plt[0]调用后的参数1是link_map,参数2(reloc_arg)需要控制
  • 对于已解析过的函数,需要重新触发解析过程

防御与绕过

常见防御机制

  1. Full RELRO: 使.dynamic节区只读
  2. 栈保护(Stack Canary)
  3. ASLR

可能的绕过方式

  1. 信息泄露结合ret2resolve
  2. 利用其他可写区域伪造结构
  3. 多阶段攻击组合

总结

ret2resolve技术通过操纵动态链接过程中的数据结构,实现在不知道libc地址的情况下完成攻击。理解这项技术需要深入掌握ELF文件格式和动态链接机制,特别是:

  1. .dynamic、.dynstr、.dynsym、.rel.plt等节区的结构和关系
  2. _dl_runtime_resolve的工作流程
  3. 如何构造伪造的数据结构来"欺骗"动态链接器

这项技术在CTF比赛中常见于没有信息泄露但存在溢出漏洞的题目中,是二进制漏洞利用中的重要技术之一。

ret2resolve技术深入分析 - x86与x64架构视角 基本概念 ret2resolve是一种利用动态链接机制中延迟绑定特性的攻击技术。让我们通过一个简单例子来理解基本概念: 动态链接关键机制 延迟绑定(Lazy Binding) : 函数在第一次调用时才进行解析和绑定 _ dl_ runtime_ resolve : 负责解析函数地址的核心例程,签名: _dl_runtime_resolve(link_map, reloc_arg) 关键数据结构 1. .dynamic节区 包含动态链接需要的信息,重点关注三项: DT_ STRTAB: 指向.dynstr节区 DT_ SYMTAB: 指向.dynsym节区 DT_ JMPREL: 指向.rel.plt节区 2. .dynstr节区 字符串表,包含动态链接用到的字符串(包括函数名),每个以0结尾。 3. .dynsym节区 符号表(结构体数组),记录符号信息。关键结构体: 4. .rel.plt节区 重定位表(结构体数组),每个结构体对应一个导入函数: _ dl_ runtime_ resolve工作流程 访问.dynamic,获取.dynsym、.dynstr、.rel.plt指针 .rel.plt + reloc_arg 获取当前函数的重定位表项指针(rel) rel->r_info >> 8 作为.dynsym下标,获取符号表项指针(sym) .dynstr + sym->st_name 得到符号名字符串指针 在动态库中查找函数地址,写入 *rel->r_offset (GOT表) 调用该函数 x86架构利用技术 利用方式1:修改.dynamic节区(No RELRO) 适用条件 : .dynamic节区可写(No RELRO保护) 攻击思路 : 修改.dynamic中的.dynstr指针,指向可控区域 在可控区域伪造函数名字符串(如将"free"改为"system") 触发目标函数调用 示例攻击步骤 : 在bss段伪造.dynstr结构 计算free和system字符串的偏移差异 通过堆溢出修改.dynamic中的strtab指针 触发free调用实际执行system 利用方式2:控制reloc_ arg(Partial RELRO) 适用条件 : .dynamic不可写(Partial RELRO) 攻击思路 : 控制_ dl_ runtime_ resolve的reloc_ arg参数 使.rel.plt + reloc_ arg指向可控区域 伪造重定位表项(Elf32_ Rel) 通过r_ info控制符号表项 伪造符号名字符串 关键技术点 : 伪造的r_ info构造: (index << 8) | 0x7 ,其中index是伪造符号表项的下标 符号表项对齐: Elf32_ Sym结构体大小为0x10,需要对齐 st_ name计算: 伪造字符串地址 - .dynstr基址 完整攻击链 : 栈迁移到bss段 第一次read: 将payload写入bss 构造伪造的rel和sym结构 调用plt[ 0]触发_ dl_ runtime_ resolve 通过伪造结构最终执行system("/bin/sh") x64架构利用技术 x64架构利用原理与x86类似,但有以下差异: 参数通过寄存器传递,不需要栈迁移 可利用的ROP gadget更多样 结构体大小和对齐方式不同 典型攻击步骤 : 第一次read: 将"/bin/sh"和伪造的.dynstr写入bss 第二次read: 修改.dynamic中的dynstr指针 调用plt[ 0]触发_ dl_ fixup 通过伪造的dynstr使解析结果为system 关键点 : plt[ 0]调用后的参数1是link_ map,参数2(reloc_ arg)需要控制 对于已解析过的函数,需要重新触发解析过程 防御与绕过 常见防御机制 Full RELRO: 使.dynamic节区只读 栈保护(Stack Canary) ASLR 可能的绕过方式 信息泄露结合ret2resolve 利用其他可写区域伪造结构 多阶段攻击组合 总结 ret2resolve技术通过操纵动态链接过程中的数据结构,实现在不知道libc地址的情况下完成攻击。理解这项技术需要深入掌握ELF文件格式和动态链接机制,特别是: .dynamic、.dynstr、.dynsym、.rel.plt等节区的结构和关系 _ dl_ runtime_ resolve的工作流程 如何构造伪造的数据结构来"欺骗"动态链接器 这项技术在CTF比赛中常见于没有信息泄露但存在溢出漏洞的题目中,是二进制漏洞利用中的重要技术之一。