[原创]ROP高级用法之ret2_dl_runtime_resolve
简介
我们知道在Linux中如果程序想要调用其他动态链接库的函数,必须要在程序加载的时候动态链接;在一个程序运行过程中,可能很多函数在程序执行完时都不会用到,比如一些错误处理函数或者一些用户很少用到的功能模块;所以ELF采用一种叫做延迟绑定(Lazy Binding)的做法,基本思想就是当函数第一次被调用的时候才进行绑定(符号查找、重定位等);
而在Linux 中是利用_dl_runtime_resolve(link_map_obj, reloc_index)函数来对动态链接的函数进行重定位的;
_dl_runtime_resolve函数具体运行模式
首先总的来说一下_dl_runtime_resolve函数如何使程序第一次调用一个函数:
- 首先用link_map访问.dynamic,分别取出.dynstr、 .dynsym、 .rel.plt的地址;
- .rel.plt + 参数reloc_index,求出当前函数的重定位表项Elf32_Rel的指针,记作rel;
- rel->r_info >> 8作为.dynsym的下标,求出当前函数的符号表项Elf32_Sym的指针,记作sym;
- .dynstr + sym->st_name得出符号名字符串指针;
- 在动态链接库查找这个函数的地址,并且把地址赋值给*rel->r_offset,即GOT表;
- 最后调用这个函数;
现在我们通过一个实例来解释上面的过程:
任意打开一个ELF程序,这里我用XDCTF2015的pwn200中的strlen函数为例来看Linux中程序如何第一次调用一个函数;
在0x8048588下断点;
0x8048579 <main+90> call setbuf@plt <0x8048390>
0x804857e <main+95> add esp, 0x10
0x8048581 <main+98> sub esp, 0xc
0x8048584 <main+101> lea eax, [ebp - 0x6c]
0x8048587 <main+104> push eax
? 0x8048588 <main+105> call strlen@plt <0x80483b0>
s: 0xffffbd8c ?— 'Welcome to XDCTF2015~!\n'
0x804858d <main+110> add esp, 0x10
0x8048590 <main+113> sub esp, 4
0x8048593 <main+116> push eax
0x8048594 <main+117> lea eax, [ebp - 0x6c]
0x8048597 <main+120> push eax
然后si进入call strlen@plt;
0x80483b0 <strlen@plt> jmp dword ptr [_GLOBAL_OFFSET_TABLE_+20] <0x804a014>
0x80483b6 <strlen@plt+6> push 0x10 //参数n
0x80483bb <strlen@plt+11> jmp 0x8048380
↓
0x8048380 push dword ptr [_GLOBAL_OFFSET_TABLE_+4] <0x804a004>
0x8048386 jmp dword ptr [0x804a008] <0xf7fead80>
↓
0xf7fead80 <_dl_runtime_resolve> push eax
0xf7fead81 <_dl_runtime_resolve+1> push ecx
0xf7fead82 <_dl_runtime_resolve+2> push edx
我们看到程序没有直接转到strlen函数,而是跳转到了_dl_runtime_resolve函数;并且push了两个参数:
push 0x10 //参数n push dword ptr [_GLOBAL_OFFSET_TABLE_+4]<0x804a004>
刚好是_dl_runtime_resolve(link_map_obj, reloc_index)需要的参数;其中0x804a004就是link_map指针,然后0x10就是reloc_index;
注意:上传附件及图片大小不得大于30M。
⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。
复制成功
