0x00. 写在前面
Return to dl-resolve是一种新的rop攻击方式,出自USENIX Security 2015上的一篇论文How the ELF Ruined Christmas。前段时间,学习了return to dl-resolve 方法,并且分别在32位应用和64位应用上实践了一番。网上有很多文章讲解return to dl-resolve的原理,现记录下我的学习心得,如有不对的地方,欢迎斧正。
0x01. dl-resolve解析原理
return to dl-resolve 主要是利用Linux glibc的延迟绑定技术(Lazy binding)。Linux下glibc库函数在第一次被调用的时候,才会去寻找函数的真正地址然后进行绑定。在这一过程中,主要由过程链接表(PLT)提供跳转到解析函数的胶水代码,然后将函数的真正地址回填到函数的全局偏移表中,再将控制权交给需要解析的函数。
首先,了解一下在动态链接过程中需要的辅助信息:重定位表(.rel.plt和.rel.dyn)、全局偏移表(.got和.got.plt)、动态链接符号表(.dyn.sym)、动态链接字符串表(.dyn.str)。
1) 重定位表
重定位表中.rel.plt用于函数重定位,.rel.dyn用于变量重定位。函数重定位表的主要作用是提供函数在动态链接符号表以及全局偏移表中的位置。具体的,函数重定位表表项为地址解析函数提供一个参数(r_info的前24位),定位需要解析的函数;为重定位入口提供一个偏移地址,定位函数地址的保存位置(r_offset),即函数的全局偏移表值(.got.plt)。重定位表的定义如下:
typedef struct
{
Elf32_Addr r_offset; /* Address */
Elf32_Word r_info; /* Relocation type and symbol index */
} Elf32_Rel;
typedef struct
{
Elf64_Addr r_offset; /* Address */
Elf64_Xword r_info; /* Relocation type and symbol index */
Elf64_Sxword r_addend; /* Addend */
} Elf64_Rela;
2) 全局偏移表
全局偏移表中.got 保存全局变量偏移表,.got.plt 保存全局函数偏移表。全局函数偏移表主要保存了函数在内存中的实际地址,刚开始全局函数便宜表中存放的是:过程链接表PLT中该函数胶水代码中的第二条指令地址。在函数解析之后,才存放了函数的真正地址。以XMAN中32位ELF level4中的read@plt为例:
~/workspace/pwn/jarvisoj/xman$ objdump -d -j.plt level4
level4: file format elf32-i386
Disassembly of section .plt:
08048300 <read@plt-0x10>:
08048300: ff 35 04 a0 04 08 pushl 0x804a004
08048306: ff 25 08 a0 04 08 jmp *0x804a008
0804830c: 00 00 add %al,(%eax)
...
08048310 <read@plt>:
08048310: ff 25 0c a0 04 08 jmp *0x804a00c
08048316: 68 00 00 00 00 push $