0x00. payload构造思路
前面我们已经大致介绍了dl-resolve如何进行函数地址的解析。
主要步骤是:通过函数的function@plt,将reloc_arg参数压栈。再跳转到过程链接表的开始PLT[0],将link_map地址压栈。然后调用_dl_runtime_resolve(link_map, reloc_arg)解析函数的地址,并写回到函数的全局偏移表(.got.plt)中,最后返回到需要解析的函数中。在_dl_runtime_resolve中调用_dl_fixup函数,主要的操作是:通过参数reloc_arg确定重定位表中该函数的重定位表项;再通过该重定位表项的r_info字段,在动态链接符号表中确定该函数的符号表项,以及类型,并进行一些检查。再由动态链接符号表项的st_name在动态链接字符串表中确定函数名称。
payload构造:
如果我们伪造reloc_arg,使该函数的重定位表项位于我们可控制的位置;再伪造重定位表项(即r_offset和r_info),可使该函数的动态链接符号表表项位于我们可控制的位置;然后,伪造动态链接符号表表项(即st_name、st_value、st_size、st_info、st_other、st_shndx),主要是st_name的值,使该函数动态链接字符串表表项位于我们控制的位置;最后,伪造动态链接字符串表表项值为我们想要解析的函数名,就可以了。
0x01. 32位应用的payload构造
下面以XMAN level4中的32位ELF为例,介绍32位应用payload的构造过程,该ELF有个明显的栈溢出漏洞。
首先,通过栈溢出向bss段写入我们精心构造的payload,一般选择bss段偏移为0x400的位置(.bss+0x400)写入。该payload包含解析函数的地址入口、返回值、需要解析函数的参数、伪造的重定位表项、动态链接符号表表项、动态链接字符串表表项、以及函数的参数值。然后,通过平衡堆栈,将程序的执行流交给解析函数。
32位应用 payload的主要构成如下:
payload1: 利用漏洞进行读操作,将数据写入bss区。
___________________________________________________________________________________________________________
| 'A' * offset | read_plt | p_p_p_ret | 0 | base_stage | 100 | p_ebp_ret | base_stage | leave_ret |
|--------------|-------------|-----------|-------|------------|------|-----------|------------|------------|
| 溢出填充 |返回地址