传统的利用return-to-plt+ROP来绕过ASLR + DEP的技术需要知道库中函数的偏移地址,而在没有libc库的情况下可以使用Return-to-dl-resolve技术来达到动态获得库函数地址的目的,关于dl-resolve的技术细节请点击阅读原文了解详情。
编译程序并且打开系统的ASLR:
程序是一个简单的缓冲区溢出,可以覆盖返回地址,在DEP的保护下,我们可以使用ROP技术来执行代码,为了绕过ASLR,这里使用了return-to-plt技术。
调用write@plt的代码如下:
函数的plt其实地址可以用objdump -d -j.plt bof读出:
栈的布局如下:
运行:
看到write@plt被成功调用打出了我们想要的字符串。
接下来改一下ROP,将直接调用write@plt改为将reloc_offset放在栈中,直接跳到0x8048300执行:
看到write@plt的reloc_offset为0x18,修改代码为:
运行:
接下来要建立假的Elf32_Rel结构体,原来第一个结构体的位置为:
这里我们可插入一个非常大的reloc_offset,把结构体位置定位到我们可以控制的区域,选择区域为base_stage+28,reloc_offset = (base_stage+28) - addr_relplt,在指定区域插入伪造的结构体,先看看原来的write的结构体:
构造为:
后半段改为:
这样同样能调用write:
我们知道在找到Elf32_Rel结构体后,会通过r_info >> 8得到Elf32_Sym结构体的位置
write的r_info >> 8 = 4,所以在SYMTAB[4],也就是0x80481cc + 64:
我们可以把结构体放在base_stage + 36处,原结构体为:
所以构造为:
还要修改Elf32_Rel结构体中的r_info,保证:
所以base_stage + 36需要加padding,使得为0x10的倍数,计算得到这里正好符合padding的要求,可以不需要padding,修改后为:
结果一样:
我们知道Elf32_Sym结构体第一项是函数名称字符串在STRTAB中的偏移:
只需要修改st_name字段,直接在Elf32_Sym结构体后加字符串即可:
结果:
只要把write\x00改为system\x00,然后修改对应的参数就可以了,完整的脚本:
运行:
这样就在不知道库中函数偏移的情况下调用了system。
参考来源: ROP stager + Return-to-dl-resolveによるASLR+DEP回避
*本文作者:pwdme,转载请注明来自 FreeBuf.COM