ret2dl_resolve从原理到实践
字数 1232 2025-08-24 23:51:13

ret2dl_resolve技术从原理到实践

1. 技术概述

ret2dl_resolve是一种利用ELF文件动态链接机制的攻击技术,通过伪造动态链接过程中使用的数据结构,实现任意函数解析和调用的攻击方法。这种技术在缺乏libc地址泄露的情况下特别有用。

2. ELF文件结构基础

2.1 关键段(Section)

  • .dynsym: 动态符号表,包含ELF_Sym结构数组
  • .rel.plt/.rela.plt: 函数重定位表,包含ELF_Rel/ELF_Rela结构数组
  • .dynstr: 动态字符串表,包含函数名称字符串
  • .got.plt: 全局偏移表,存储函数地址

2.2 关键数据结构

ELF_Sym结构 (符号表项)

typedef struct {
    Elf32_Word st_name;   // 符号名在.dynstr中的偏移
    Elf32_Addr st_value;  // 符号值(解析后为函数地址)
    Elf32_Word st_size;   // 符号大小
    unsigned char st_info; // 符号类型和绑定信息
    unsigned char st_other; // 符号可见性
    Elf32_Section st_shndx; // 段索引
} Elf32_Sym;

ELF_Rel结构 (重定位项)

typedef struct {
    Elf32_Addr r_offset;  // 重定位地址(通常是GOT条目)
    Elf32_Word r_info;    // 符号索引和重定位类型
} Elf32_Rel;

3. 动态链接机制解析

3.1 惰性加载(Lazy Binding)流程

  1. 首次调用函数时,GOT条目指向PLT中的解析代码
  2. PLT代码将重定位索引(reloc_index)压栈
  3. 跳转到PLT[0]执行
  4. PLT[0]将link_map对象(GOT[1])压栈
  5. 跳转到_dl_runtime_resolve(GOT[2])

3.2 _dl_runtime_resolve解析过程

  1. 根据reloc_index在.rel.plt中找到ELF_Rel结构
  2. 从ELF_Rel的r_info中提取符号索引
  3. 在.dynsym中找到对应的ELF_Sym结构
  4. 从ELF_Sym的st_name在.dynstr中找到函数名
  5. 解析函数地址并写入GOT条目
  6. 跳转到解析后的函数

4. 攻击原理

通过伪造上述解析过程中使用的数据结构,可以欺骗动态链接器解析任意函数:

  1. 伪造.rel.plt条目,指向伪造的ELF_Sym结构
  2. 伪造ELF_Sym结构,指向伪造的函数名
  3. 伪造.dynstr内容,包含目标函数名(如"system")

5. 攻击实践

5.1 x86平台攻击示例

攻击步骤:

  1. 栈迁移到可控区域(如.bss段)
  2. 伪造重定位结构
  3. 伪造符号表结构
  4. 伪造字符串表
  5. 调用PLT[0]触发解析

关键代码:

# 伪造重定位项
fake_reloc = p32(alarm_got) + p32(r_info)  # 重定位到alarm的GOT,但伪造符号信息

# 伪造符号表项
fake_sym = p32(st_name) + p32(0) + p32(0) + p32(0x12)

# 栈布局
payload += p32(plt_0)              # 触发解析
payload += p32(index_offset)       # 伪造的重定位索引
payload += 'a'*4                   # 返回地址(不重要)
payload += p32(control_base + 0x50) # 参数地址

5.2 x64平台差异

  1. 使用.rela.plt而非.rel.plt
  2. ELF_Rela结构多了一个r_addend字段
  3. 需要设置link_map为0(或泄露真实地址)
  4. 参数传递通过寄存器而非栈

使用roputils简化攻击:

rop = ROP('./binary')
addr_bss = rop.section('.bss')
payload = rop.retfill(offset)
payload += rop.call(read_plt, 0, addr_bss, 0x100)
payload += rop.dl_resolve_call(addr_bss+0x20, addr_bss)

6. 防御措施

  1. FULL RELRO: 在程序启动时解析所有符号,使GOT只读
  2. 栈保护: 防止栈溢出和栈迁移
  3. 地址随机化: 增加伪造数据结构的难度

7. 工具使用

推荐使用roputils等工具简化攻击构造:

buf2 = rop.string('/bin/sh')
buf2 += rop.fill(20, buf2)
buf2 += rop.dl_resolve_data(addr_bss+20, 'system')
buf3 = 'A'*44 + rop.dl_resolve_call(addr_bss+20, addr_bss)

8. 总结

ret2dl_resolve是一种强大的攻击技术,它利用了动态链接器的信任机制。理解其原理不仅有助于攻击,也能帮助设计更好的防御措施。在实际应用中,需要结合具体ELF文件结构和保护机制进行调整。

ret2dl_ resolve技术从原理到实践 1. 技术概述 ret2dl_ resolve是一种利用ELF文件动态链接机制的攻击技术,通过伪造动态链接过程中使用的数据结构,实现任意函数解析和调用的攻击方法。这种技术在缺乏libc地址泄露的情况下特别有用。 2. ELF文件结构基础 2.1 关键段(Section) .dynsym : 动态符号表,包含ELF_ Sym结构数组 .rel.plt / .rela.plt : 函数重定位表,包含ELF_ Rel/ELF_ Rela结构数组 .dynstr : 动态字符串表,包含函数名称字符串 .got.plt : 全局偏移表,存储函数地址 2.2 关键数据结构 ELF_ Sym结构 (符号表项) ELF_ Rel结构 (重定位项) 3. 动态链接机制解析 3.1 惰性加载(Lazy Binding)流程 首次调用函数时,GOT条目指向PLT中的解析代码 PLT代码将重定位索引(reloc_ index)压栈 跳转到PLT[ 0 ]执行 PLT[ 0]将link_ map对象(GOT[ 1 ])压栈 跳转到_ dl_ runtime_ resolve(GOT[ 2 ]) 3.2 _ dl_ runtime_ resolve解析过程 根据reloc_ index在.rel.plt中找到ELF_ Rel结构 从ELF_ Rel的r_ info中提取符号索引 在.dynsym中找到对应的ELF_ Sym结构 从ELF_ Sym的st_ name在.dynstr中找到函数名 解析函数地址并写入GOT条目 跳转到解析后的函数 4. 攻击原理 通过伪造上述解析过程中使用的数据结构,可以欺骗动态链接器解析任意函数: 伪造.rel.plt条目,指向伪造的ELF_ Sym结构 伪造ELF_ Sym结构,指向伪造的函数名 伪造.dynstr内容,包含目标函数名(如"system") 5. 攻击实践 5.1 x86平台攻击示例 攻击步骤: 栈迁移到可控区域(如.bss段) 伪造重定位结构 伪造符号表结构 伪造字符串表 调用PLT[ 0 ]触发解析 关键代码: 5.2 x64平台差异 使用.rela.plt而非.rel.plt ELF_ Rela结构多了一个r_ addend字段 需要设置link_ map为0(或泄露真实地址) 参数传递通过寄存器而非栈 使用roputils简化攻击: 6. 防御措施 FULL RELRO: 在程序启动时解析所有符号,使GOT只读 栈保护: 防止栈溢出和栈迁移 地址随机化: 增加伪造数据结构的难度 7. 工具使用 推荐使用roputils等工具简化攻击构造: 8. 总结 ret2dl_ resolve是一种强大的攻击技术,它利用了动态链接器的信任机制。理解其原理不仅有助于攻击,也能帮助设计更好的防御措施。在实际应用中,需要结合具体ELF文件结构和保护机制进行调整。