SWPUCTF 2022 新生赛wasm
pre
首先安装wabt
0x01
1
./wasm-decompile wasm.wasm wasm.dcmp
option 也可以使用wasm2wat,wasm2c 生成其他文件 不好审计效果好像都不太友好
0x02
进入wasm.dcmp找到关键函数check
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
function assembly_index_check(a:int):int {
var b:int;
var e:int;
lib_memory_stack_pointer = lib_memory_stack_pointer - 8;
stack_check();
label B_a:
lib_memory_stack_pointer[0]:long = 0L;
e =
{
if (lib_array_Array_i32_get_length(a) != 38) { //长度为38
e = 0;
lib_memory_stack_pointer = lib_memory_stack_pointer + 8;
return e;
label B_d:
unreachable;
}
lib_memory_stack_pointer[0]:int =
(b = lib_array_Array_i32_slice(a, 7, -1)); // 数组slice b = a[7:-1]
var c:int = 0;
loop L_f {
var d:int = c < lib_array_Array_i32_get_length(b); // 循环30次
if (d) {
assembly_index_reverse(b); // 数组倒转
assembly_index_rotate(b, 1); // 数组 >> 1
//这里可以看出,其实数组反转一次,数组循环右移一位,此时在反转一次,此时相当于原数组(第一次反转前)左移一次
// 所以偶数次 实际就是不变
label B_h:
c = c + 1;
continue L_f;
}
}
// 相当于执行assembly_index_lp(b[0:10])和assembly_index_rp(b[10:30])
label B_e:
if (assembly_index_lp({
e = lib_array_Array_i32_slice(b, 0, 10);
lib_memory_stack_pointer[1]:int = e;
e;
label B_i:
})) {
assembly_index_rp(
{
e = lib_array_Array_i32_slice(b, 10, lib_builtins_i32_MAX_VALUE);
lib_memory_stack_pointer[1]:int = e;
e;
label B_k:
})
} else {
0
}
label B_b:
}
lib_memory_stack_pointer = lib_memory_stack_pointer + 8;
return e;
}
所以我们只需要查看assembly_index_lp和assembly_index_rp这两个函数即可
首先看assembly_index_lp
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
function assembly_index_lp(a:int):int {
return
if (if (if (if (if (if (if (if (if (lib_array_Array_i32_get(a, 0) + lib_array_Array_i32_get(a, 5) ==
lib_array_Array_i32_get(a, 1) + lib_array_Array_i32_get(a, 9)) {
lib_array_Array_i32_get(a, 0) + lib_array_Array_i32_get(a, 1) +
lib_array_Array_i32_get(a, 2) +
lib_array_Array_i32_get(a, 3) +
lib_array_Array_i32_get(a, 4) +
lib_array_Array_i32_get(a, 5) +
lib_array_Array_i32_get(a, 6) +
lib_array_Array_i32_get(a, 7) +
lib_array_Array_i32_get(a, 8) +
lib_array_Array_i32_get(a, 9) ==
1022
} else {
0
}) {
lib_array_Array_i32_get(a, 7) - lib_array_Array_i32_get(a, 8) == 10
} else {
0
}) {
lib_array_Array_i32_get(a, 3) + lib_array_Array_i32_get(a, 2) +
lib_array_Array_i32_get(a, 1) ==
330
} else {
0
}) {
lib_array_Array_i32_get(a, 5) * lib_array_Array_i32_get(a, 6) *
lib_array_Array_i32_get(a, 8) ==
617500
} else {
0
}) {
lib_array_Array_i32_get(a, 6) * 2 ==
lib_array_Array_i32_get(a, 3) + 15
} else {
0
}) {
lib_array_Array_i32_get(a, 7) ==
lib_array_Array_i32_get(a, 5) + lib_array_Array_i32_get(a, 4) -
lib_array_Array_i32_get(a, 2) +
3
} else {
0
}) {
lib_array_Array_i32_get(a, 8) + lib_array_Array_i32_get(a, 4) == 209
} else {
0
}) {
lib_array_Array_i32_get(a, 1) + lib_array_Array_i32_get(a, 8) +
lib_array_Array_i32_get(a, 9) -
lib_array_Array_i32_get(a, 4) ==
204
} else {
0
}) {
lib_array_Array_i32_get(a, 0) * lib_array_Array_i32_get(a, 1) *
lib_array_Array_i32_get(a, 2) ==
1350628
} else {
0
}
emm看起来想是一堆方程,那就解吧,当时手头没有纸笔,只能被迫用z3了
数学大佬可以手动解出orz
好了数组前10位已经搞定,下面来看数组后20位
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
function assembly_index_rp(a:int):int {
var c:int;
var e:int;
lib_memory_stack_pointer = lib_memory_stack_pointer - 4;
stack_check();
label B_a:
lib_memory_stack_pointer[0]:int = 0;
e =
{
lib_memory_stack_pointer[0]:int =
(c = lib_rt_newArray(20, 2, 3, 528)); // 长度20的数组
var b:int = 0;
loop L_d {
var d:int = b < lib_array_Array_i32_get_length(a); // 获取长度
if (d) {
if (lib_array_Array_i32_get(c, b) == (lib_array_Array_i32_get(a, b) ^ 2)) {
lib_array_Array_i32_set(c, b, lib_array_Array_i32_get(a, b))
} else {
e = 0;
lib_memory_stack_pointer = lib_memory_stack_pointer + 4;
return e;
label B_h:
unreachable;
}
label B_f:
b = b + 1;
continue L_d;
}
}
label B_c:
1;
label B_b:
}
lib_memory_stack_pointer = lib_memory_stack_pointer + 4;
return e;
}
这里看到c数组^2就是b数组 c数组到底是什么需要细看lib_rt_newArray
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function lib_rt_newArray(a:int, b:int, c:int, d:int):int {
var f:int;
lib_memory_stack_pointer = lib_memory_stack_pointer - 4;
stack_check();
label B_a:
lib_memory_stack_pointer[0]:int = 0;
var h:int =
{
var e:int = a << b;
lib_memory_stack_pointer[0]:int = (f = lib_rt_newBuffer(e, 0, d)); //lib_rt_newBuffer(len,?,src)
var g:{ a:int, b:int, c:int, d:int } = lib_rt_itcms_new(16, c); //lib_rt_itcms_new(rtsize,rtid)
g.a = f; // buffer
lib_rt_itcms_link(g, f, 0);
g.b = f; //link?
g.c = e;
g.d = a; //长度
g;
label B_b:
}
lib_memory_stack_pointer = lib_memory_stack_pointer + 4;
return h;
}
可以看到在528之后的20字节,填充了c,在数据区找到了相应的数据
1
2
3
4
5
6
7
8
9
10
data d_lPvjcliqdmpmwpumpi(offset: 508) =
"l\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00P\00\00\00v\00\00\00j\00"
"\00\00c\00\00\00l\00\00\00i\00\00\00q\00\00\00]\00\00\00d\00\00\00m\00"
"\00\00p\00\00\00]\00\00\00{\00\00\00m\00\00\00w\00\00\00p\00\00\00]\00"
"\00\00u\00\00\00m\00\00\00p\00\00\00i\00\00\00\00\00\00\00\00\00\00\00"
"\00\00\00\00";
data d_Objectalreadypinned(offset: 620) =
"<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00*\00\00\00O\00b\00j\00e\00"
"c\00t\00 \00a\00l\00r\00e\00a\00d\00y\00 \00p\00i\00n\00n\00e\00d\00\00"
"\00";
528之后的实际字符串为’vjcliq]dmp]{mwp]umpi’ 好了分析结束
0x03
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
from z3 import *
from pwn import *
a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 =BitVecs('a0 a1 a2 a3 a4 a5 a6 a7 a8 a9',32)
s = Solver()
s.add(a0 < 128)
s.add(a1 < 128)
s.add(a2 < 128)
s.add(a3 < 128)
s.add(a4 < 128)
s.add(a5 < 128)
s.add(a6 < 128)
s.add(a7 < 128)
s.add(a8 < 128)
s.add(a9 < 128)
s.add(a0 > 0)
s.add(a1 > 0)
s.add(a3 > 0)
s.add(a4 > 0)
s.add(a5 > 0)
s.add(a6 > 0)
s.add(a7 > 0)
s.add(a8 > 0)
s.add(a9 > 0)
s.add(a0 + a5 == a1 + a9)
s.add(a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 == 1022)
s.add(a7 - a8 == 10)
s.add(a3 + a2 + a1 == 330)
s.add(a5 * a6 * a8 == 617500)
s.add(a6 * 2 == a3 + 15)
s.add(a7 == a5 + a4 - a2 + 3)
s.add(a8 + a4 == 209)
s.add(a1 + a8 + a9 - a4 == 204)
s.add(a0 * a1 * a2 == 1350628)
check = s.check()
print(check)
model = s.model()
print(model)
flag = 'vvasm_And_' # maybe you should parse model
# print(flag)
ss = 'vjcliq]dmp]{mwp]umpi'
b = xor(ss,2)
ss = str(b,encoding='ascii')
flag += ss
for i in range(30):
flag = flag[::-1]
# print(flag)
flag = flag[-1] + flag[:-1]
# print(flag)
print(flag)
0x04
flag = vvasm_And_thanks_for_your_work
This post is licensed under CC BY 4.0 by the author.