6.1.20 pwn 33C3CTF2016 babyfengshui
题目复现
$ file babyfengshui
babyfengshui: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=cecdaee24200fe5bbd3d34b30404961ca49067c6, stripped
$ checksec -f babyfengshui
RELRO STACK CANARY NX PIE RPATH RUNPATH FORTIFY Fortified Fortifiable FILE
Partial RELRO Canary found NX enabled No PIE No RPATH No RUNPATH Yes 0 3 babyfengshui
$ strings libc-2.19.so | grep "GNU C"
GNU C Library (Debian GLIBC 2.19-18+deb8u6) stable release version 2.19, by Roland McGrath et al.
Compiled by GNU CC version 4.8.4.32 位程序,开启了 canary 和 NX。
在 Ubuntu-14.04 上玩一下,添加 user 和显示 user:
$ ./babyfengshui
0: Add a user
1: Delete a user
2: Display a user
3: Update a user description
4: Exit
Action: 0
size of description: 10 # description 最大长度(desc_size)
name: AAAA
text length: 5 # description 实际长度(text_size)
text: aaaa
0: Add a user
1: Delete a user
2: Display a user
3: Update a user description
4: Exit
Action: 2
index: 0
name: AAAA
description: aaaa对于 description 的调整只能在最大长度的范围内,否则程序退出:
题目解析
Add a user
函数首先分配一个 description 的最大空间,然后分配 user 结构体空间,并将 user 放到 store 数组中,最后调用更新 description 的函数。
user 结构体和 store 数组如下:
store 放在 0x804b080,当前 user 个数 user_num 放在 0x804b069。
Delete a user
删除的过程将 description 和 user 依次释放,并将 store[i] 置为 0。
但是 user->desc 没有被置为 0,user_num 也没有减 1,似乎可能导致 UAF,但不知道怎么用。
Display a user
函数首先判断 store[i] 是否存在,如果是,就打印出 name 和 description。
Update a user description
该函数读入新的 text_size,并使用 (store[i]->desc + test_size) < (store[i] - 4) 的条件来防止堆溢出,最后读入新的 description。
然而这种检查方式是有问题的,它基于 description 正好位于 user 前面这种设定。根据我们对堆分配器的理解,这个设定不一定成立,它们之间可能会包含其他已分配的堆块,从而绕过检查。
漏洞利用
所以我们首先添加两个 user,用于绕过检查。第 3 个 user 存放 "/bin/sh"。然后删掉第 1 个 user,并创建一个 description 很长的 user,其长度是第 1 个 user 的 description 长度加上 user 结构体长度。这时候检查就绕过了,我们可以在添加新 user 的时候修改 description 大小,造成堆溢出,并修改第 2 个 user 的 user->desc 为 free@got.plt,从而泄漏出 libc 地址。得到 system 地址后,此时修改第 2 个 user 的 description,其实是修改 free 的 GOT,所以我们将其改成 system@got.plt。最后删除第 3 个 user,触发 system('/bin/sh'),得到 shell。
开启 ASLR。Bingo!!!
exploit
完整的 exp 如下:
参考资料
Last updated
Was this helpful?