6.1.26 pwn 34C3CTF2017 300
题目复现
$ file 300
300: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=5f43b102f0fe3f3dd770637f1d244384f6b2a1c9, not stripped
$ checksec -f 300
RELRO STACK CANARY NX PIE RPATH RUNPATH FORTIFY Fortified Fortifiable FILE
Full RELRO Canary found NX enabled PIE enabled No RPATH No RUNPATH Yes 0 2 300
$ strings libc-2.24.so | grep "GNU C"
GNU C Library (Ubuntu GLIBC 2.24-9ubuntu2.2) stable release version 2.24, by Roland McGrath et al.
Compiled by GNU CC version 6.3.0 20170406.64 位程序 ,开启了 canary、NX 和 PIE,默认开启 ASLR。
在 Ubuntu16.10 上玩一下:
) alloc
2) write
3) print
4) free
1 <-- alloc 1
slot? (0-9)
1
1) alloc
2) write
3) print
4) free
2
slot? (0-9)
1 <-- write 1
AAAAAAAAAAAAAAAA
1) alloc
2) write
3) print
4) free
4 <-- free 1
slot? (0-9)
1
1) alloc
2) write
3) print
4) free
2 <-- write 1
slot? (0-9)
1
BBBBBBBB
1) alloc
2) write
3) print
4) free
3 <-- print 1
slot? (0-9)
1
BBBBBBBB
AAAAAAA
1) alloc
2) write
3) print
4) free
3 <-- print 2
slot? (0-9)
2
Segmentation fault (core dumped)很清晰的 4 个功能:alloc、write、print 和 free。通过尝试似乎就发现了问题,free 的时候没有将指针置空,导致 UAF。读入的字符串末尾没有加 \x00 导致信息泄露。最后如果 print 一个还没有 alloc 的 slot,则出现段错误。
题目解析
main
从 main 函数中我们知道,程序的所有操作都是基于 slot。
alloc
该函数固定分配 0x300 的空间,然后根据 slot 将返回地址放到从 0x202040 开始的数组 allocs 中。
write
该函数读入最多 0x300 个字符到 slot 对应的空间中。没有在字符串末尾加 \x00,可能导致信息泄露。
print
该函数用于打印 slot 对应空间中的字符串。
free
该函数用于释放 slot 对应的空间,但是却没有将 allocs[slot] 指针置空,导致 UAF,或者 double-free。
漏洞利用
从上面我们可以看到,程序的各项操作都基于 slot,对 allocs[slot] 指向的内存空间进行操作,但没有对 allocs[slot] 是否为空,或者其指向的内存是否为被释放的状态,都没有做任何检查,这也是之前发生段错误的原因。
leak
首先利用 unsorted bin 可以泄露出 libc 和 heap 的地址。分配 5 个 chunk 的原因是为了避免 \x00 截断(heap 基地址的低位 0x00)。然后释放掉 1 和 3 即可。
house of orange
这一步就比较复杂了。因为程序只允许分配 0x300 大小的 chunk,而我们知道 house-of-orange 需要大小为 0x60 的 chunk(放入 smallbins[5])。由于我们可以具有修改 free chunk 的能力,所以可以修改 unsorted bin 里 chunk 的 bk 指针指向伪造的 fake chunk,以将其链接到 unsorted bin 中。接下来的第一次 malloc 将修改 unsorted_bin->TAIL->bk 将指向 fake chunk,而第二次 malloc 的时候,由于大小不合适,fake chunk 就会被整理回 smallbins[5]:
对于 vtable 的利用,上一节我们使用了 _IO_str_overflow 函数,这次我们就用 _IO_wstr_finish 函数。具体怎么用请查看章节 4.13。
值得注意的是 fp->_wide_data 指向了 fake chunk,所以就相当于我们复用了这一块空间,fp->_IO_write_end 的地方也是就是 fp->wide_data->buf_base。
接下来利用 unsorted bin attack 修改 _IO_list_all 指向 &unsorted_bin-0x10,而偏移 0x60 的地方就是 _IO_list_all->_chain,即 smallbins[5],指向了 fake chunk。
pwn
最后触发异常处理,malloc_printerr -> __libc_message -> __GI_abort -> _IO_flush_all_lockp -> __GI__IO_str_finish,获得 shell。
开启 ASLR,Bingo!!!
exploit
完整的 exp 如下:
参考资料
Last updated
Was this helpful?