GWCTF2019_babyvm

[GWCTF 2019]babyvm

ida64打开

image-20221220114220125

输出后进入初始化函数

image-20221220114251602

猜测大概是虚拟机,进一步分析

image-20221220114340803

有四个寄存器

image-20221220114358175

然后是check函数,提示暂且不管

找到opcode就可以写脚本了

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
op = [
0xF5, 0xF1, 0xE1, 0x00, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
0x20, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x01, 0x00, 0x00, 0x00,
0xF2, 0xF1, 0xE4, 0x21, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02,
0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x22, 0x00, 0x00, 0x00,
0xF1, 0xE1, 0x03, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x23,
0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00, 0x00, 0xF2,
0xF1, 0xE4, 0x24, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00,
0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x25, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x26, 0x00,
0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00, 0x00, 0xF2, 0xF1,
0xE4, 0x27, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08, 0x00, 0x00,
0x00, 0xF2, 0xF1, 0xE4, 0x28, 0x00, 0x00, 0x00, 0xF1, 0xE1,
0x09, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x29, 0x00, 0x00,
0x00, 0xF1, 0xE1, 0x0A, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
0x2A, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0B, 0x00, 0x00, 0x00,
0xF2, 0xF1, 0xE4, 0x2B, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0C,
0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2C, 0x00, 0x00, 0x00,
0xF1, 0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2D,
0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00, 0xF2,
0xF1, 0xE4, 0x2E, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0F, 0x00,
0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2F, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x10, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x30, 0x00,
0x00, 0x00, 0xF1, 0xE1, 0x11, 0x00, 0x00, 0x00, 0xF2, 0xF1,
0xE4, 0x31, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x12, 0x00, 0x00,
0x00, 0xF2, 0xF1, 0xE4, 0x32, 0x00, 0x00, 0x00, 0xF1, 0xE1,
0x13, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x33, 0x00, 0x00,
0x00, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0xF1,
0xE1, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x01, 0x00, 0x00,
0x00, 0xF2, 0xF1, 0xE4, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE1,
0x01, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x02, 0x00, 0x00, 0x00,
0xF2, 0xF1, 0xE4, 0x01, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02,
0x00, 0x00, 0x00, 0xF1, 0xE2, 0x03, 0x00, 0x00, 0x00, 0xF2,
0xF1, 0xE4, 0x02, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x03, 0x00,
0x00, 0x00, 0xF1, 0xE2, 0x04, 0x00, 0x00, 0x00, 0xF2, 0xF1,
0xE4, 0x03, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00,
0x00, 0xF1, 0xE2, 0x05, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
0x04, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00, 0x00, 0x00,
0xF1, 0xE2, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x05,
0x00, 0x00, 0x00, 0xF1, 0xE1, 0x06, 0x00, 0x00, 0x00, 0xF1,
0xE2, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x08, 0x00, 0x00,
0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6, 0xF7, 0xF1,
0xE4, 0x06, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00,
0x00, 0xF1, 0xE2, 0x08, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x09,
0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6,
0xF7, 0xF1, 0xE4, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08,
0x00, 0x00, 0x00, 0xF1, 0xE2, 0x09, 0x00, 0x00, 0x00, 0xF1,
0xE3, 0x0A, 0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00,
0x00, 0xF6, 0xF7, 0xF1, 0xE4, 0x08, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x13, 0x00, 0x00,
0x00, 0xF8, 0xF1, 0xE4, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE7,
0x13, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00,
0xF1, 0xE2, 0x12, 0x00, 0x00, 0x00, 0xF8, 0xF1, 0xE4, 0x0E,
0x00, 0x00, 0x00, 0xF1, 0xE7, 0x12, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x11, 0x00, 0x00,
0x00, 0xF8, 0xF1, 0xE4, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE7,
0x11, 0x00, 0x00, 0x00, 0xF4
]

reg = [0]*4

pos = 0
code = op[pos]
while(code != 0xf4):
code = op[pos]
if code == 0Xf1:
tmp = op[pos+1]
x = op[pos+2]
if tmp == 0xe1:
print("reg[0] = flag[%d]" % x)
elif tmp == 0xe2:
print("reg[1] = flag[%d]" % x)
elif tmp == 0xe3:
print("reg[2] = flag[%d]" % x)
elif tmp == 0xe4:
print("flag[%d] = reg[0]" % x)
elif tmp == 0xe5:
print("reg[3] = flag[%d]" % x)
elif tmp == 0xe7:
print("flag[%d] = reg[1]" % x)
pos += 6
elif code == 0xf2:
print("reg[0] ^= reg[1]")
pos += 1
elif code == 0xf5:
print("check_len == 21")
pos += 1
elif code == 0xf7:
print("reg[0] *= reg[3]")
pos += 1
elif code == 0xf8:
print("reg[0], reg[1] = reg[1], reg[0]")
pos += 1
elif code == 0xf6:
print("reg[0] = reg[2] + 2 * reg[1] + 3 * reg[0]")
pos += 1
else:
pos += 1

跑出来的结果

image-20221220114520954

21位,每一位都异或上reg[1],但是reg[1]并未找到输入,选择爆破

最大值不会超过128

1
2
3
4
5
6
enc = "Fz{aM{aM|}fMt~suM !!"
for x in range(128):
l = ""
for i in range(len(enc)):
l += chr((ord(enc[i])^x)&0xff)
print(l)

image-20221220114657917

不出意外,假flag,毕竟这个也没21位,只有20位

首先根据提示

image-20221220114916393

发现这个opcode其实是分两段的,以0xF4为结尾\

重写脚本

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
op = [
0xF5, 0xF1,
0xE1, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x01, 0x00, 0x00,
0x00, 0xF2, 0xF1, 0xE4, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE1,
0x01, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x02, 0x00, 0x00, 0x00,
0xF2, 0xF1, 0xE4, 0x01, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02,
0x00, 0x00, 0x00, 0xF1, 0xE2, 0x03, 0x00, 0x00, 0x00, 0xF2,
0xF1, 0xE4, 0x02, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x03, 0x00,
0x00, 0x00, 0xF1, 0xE2, 0x04, 0x00, 0x00, 0x00, 0xF2, 0xF1,
0xE4, 0x03, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00,
0x00, 0xF1, 0xE2, 0x05, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
0x04, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00, 0x00, 0x00,
0xF1, 0xE2, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x05,
0x00, 0x00, 0x00, 0xF1, 0xE1, 0x06, 0x00, 0x00, 0x00, 0xF1,
0xE2, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x08, 0x00, 0x00,
0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6, 0xF7, 0xF1,
0xE4, 0x06, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00,
0x00, 0xF1, 0xE2, 0x08, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x09,
0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6,
0xF7, 0xF1, 0xE4, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08,
0x00, 0x00, 0x00, 0xF1, 0xE2, 0x09, 0x00, 0x00, 0x00, 0xF1,
0xE3, 0x0A, 0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00,
0x00, 0xF6, 0xF7, 0xF1, 0xE4, 0x08, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x13, 0x00, 0x00,
0x00, 0xF8, 0xF1, 0xE4, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE7,
0x13, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00,
0xF1, 0xE2, 0x12, 0x00, 0x00, 0x00, 0xF8, 0xF1, 0xE4, 0x0E,
0x00, 0x00, 0x00, 0xF1, 0xE7, 0x12, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x11, 0x00, 0x00,
0x00, 0xF8, 0xF1, 0xE4, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE7,
0x11, 0x00, 0x00, 0x00, 0xF4
]

reg = [0]*4

pos = 0
code = op[pos]
while(code != 0xf4):
code = op[pos]
if code == 0Xf1:
tmp = op[pos+1]
x = op[pos+2]
if tmp == 0xe1:
print("reg[0] = flag[%d]" % x)
elif tmp == 0xe2:
print("reg[1] = flag[%d]" % x)
elif tmp == 0xe3:
print("reg[2] = flag[%d]" % x)
elif tmp == 0xe4:
print("flag[%d] = reg[0]" % x)
elif tmp == 0xe5:
print("reg[3] = flag[%d]" % x)
elif tmp == 0xe7:
print("flag[%d] = reg[1]" % x)
pos += 6
elif code == 0xf2:
print("reg[0] ^= reg[1]")
pos += 1
elif code == 0xf5:
print("check_len == 21")
pos += 1
elif code == 0xf7:
print("reg[0] *= reg[3]")
pos += 1
elif code == 0xf8:
print("reg[0], reg[1] = reg[1], reg[0]")
pos += 1
elif code == 0xf6:
print("reg[0] = reg[2] + 2 * reg[1] + 3 * reg[0]")
pos += 1
else:
pos += 1

分层还是相当明显的

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
check_len == 21
reg[0] = flag[0]
reg[1] = flag[1]
reg[0] ^= reg[1]
flag[0] = reg[0]

reg[0] = flag[1]
reg[1] = flag[2]
reg[0] ^= reg[1]
flag[1] = reg[0]

reg[0] = flag[2]
reg[1] = flag[3]
reg[0] ^= reg[1]
flag[2] = reg[0]

reg[0] = flag[3]
reg[1] = flag[4]
reg[0] ^= reg[1]
flag[3] = reg[0]

reg[0] = flag[4]
reg[1] = flag[5]
reg[0] ^= reg[1]
flag[4] = reg[0]

reg[0] = flag[5]
reg[1] = flag[6]
reg[0] ^= reg[1]
flag[5] = reg[0]

reg[0] = flag[6]
reg[1] = flag[7]
reg[2] = flag[8]
reg[3] = flag[12]
reg[0] = reg[2] + 2 * reg[1] + 3 * reg[0]
reg[0] *= reg[3]
flag[6] = reg[0]

reg[0] = flag[7]
reg[1] = flag[8]
reg[2] = flag[9]
reg[3] = flag[12]
reg[0] = reg[2] + 2 * reg[1] + 3 * reg[0]
reg[0] *= reg[3]
flag[7] = reg[0]

reg[0] = flag[8]
reg[1] = flag[9]
reg[2] = flag[10]
reg[3] = flag[12]
reg[0] = reg[2] + 2 * reg[1] + 3 * reg[0]
reg[0] *= reg[3]
flag[8] = reg[0]

reg[0] = flag[13]
reg[1] = flag[19]
reg[0], reg[1] = reg[1], reg[0]
flag[13] = reg[0]
flag[19] = reg[1]

reg[0] = flag[14]
reg[1] = flag[18]
reg[0], reg[1] = reg[1], reg[0]
flag[14] = reg[0]
flag[18] = reg[1]

reg[0] = flag[15]
reg[1] = flag[17]
reg[0], reg[1] = reg[1], reg[0]
flag[15] = reg[0]
flag[17] = reg[1]

然后对输出交叉引用找到真flag

image-20221220120845852

写脚本

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
flag = [
0x69, 0x45, 0x2A, 0x37, 0x09, 0x17, 0xC5, 0x0B,
0x5C, 0x72, 0x33, 0x76, 0x33, 0x21, 0x74, 0x31,
0x5F, 0x33, 0x73, 0x72, 0x0c
]

flag[13], flag[19] = flag[19], flag[13]
flag[14], flag[18] = flag[18], flag[14]
flag[15], flag[17] = flag[17], flag[15]

for i in range(33, 128):
if ((i * 3 + flag[9] * 2 + flag[10]) * flag[12]) & 0xff == flag[8]:
flag[8] = i
break

for i in range(33, 128):
if ((i * 3 + flag[8] * 2 + flag[9]) * flag[12]) & 0xff == flag[7]:
flag[7] = i
break

for i in range(33, 128):
if ((i * 3 + flag[7] * 2 + flag[8]) * flag[12]) & 0xff == flag[6]:
flag[6] = i
break

for i in range(5, -1, -1):
flag[i] ^= flag[i+1]

for i in flag:
print(chr(i & 0xff), end="")
1
flag{Y0u_hav3_r3v3rs3_1t!}