传统的利用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