首页
社区
课程
招聘
[原创] 看雪·2024 KCTF 大赛 第六题 异星文明 WriteUP
发表于: 2024-9-7 23:24 391

[原创] 看雪·2024 KCTF 大赛 第六题 异星文明 WriteUP

2024-9-7 23:24
391

看雪·2024 KCTF 大赛 第六题 异星文明 WriteUP

一、开篇

趁着周末,来补一下KCTF的WriteUP~

镇楼图

二、初步分析

拿到题目后,稍作调试分析,可以发现程序实现了一个虚拟机,逐步分发指令来执行。在使用 x64dbg 进行分析时,我们可以 dump 出完整的指令流。

部分指令流

三、分析过程

在分析程序时,我们可以找到一个内置字符串:

welcome_to_fzbz,my_name_is_sbzx!

通过进一步分析,我们可以发现程序主要由几个大循环组成。逆向算法后可以得知,程序的验证机制是:先对用户名和内置字符串的一部分进行异或操作,然后将结果与序列号一起传入算法进行计算,要求最终解密的结果与内置值相匹配。下面是用 Python 实现的核心算法的逆运算代码。

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
stack = [0] * 6  # 假设有6个元素的栈,实际长度可能更长
stack[5] = 0x2C7A627A #0x1B3F534C
stack[4] = 0
stack[3] = 0  # 对应 rsp+0x0C
stack[2] = 0x21787A62  # 对应 rsp+0x08
stack[1] = 0x735F7369  # 对应 rsp+0x04
stack[0] = 0x665F6F74 #0x561C5E43
 
eax = 0
ecx = 0
edx = 0
for _ in range(0x1f):
    eax = stack[5# mov eax, dword ptr ss:[rsp+0x14]
    ecx = stack[0# mov ecx, dword ptr ss:[rsp]
    ecx += eax  # add ecx, eax
 
    ecx &= 0xffffffff
     
    stack[0] = ecx  # mov dword ptr ss:[rsp], eax (via ecx)
    print(stack[0])
 
stack[1] ^= stack[0]
stack[2] ^= stack[0]
 
while stack[4] < 0x1F:
    eax = stack[1# mov eax, dword ptr ss:[rsp+0x04]
    eax <<= 4  # shl eax, 0x04
 
    eax &= 0xffffffff
     
    ecx = stack[0# mov ecx, dword ptr ss:[rsp]
    ecx >>= 16  # shr ecx, 0x10
    ecx &= 0xFF  # and ecx, 0xFF
     
    eax += ecx  # add eax, ecx
 
    eax &= 0xffffffff
     
    ecx = stack[0# mov ecx, dword ptr ss:[rsp]
    edx = stack[1# mov edx, dword ptr ss:[rsp+0x04]
    edx += ecx  # add edx, ecx
 
    edx &= 0xffffffff
     
    ecx = edx  # mov ecx, edx
    eax ^= ecx  # xor eax, ecx
     
    ecx = stack[1# mov ecx, dword ptr ss:[rsp+0x04]
    ecx >>= 5  # shr ecx, 0x05
     
    edx = stack[0# mov edx, dword ptr ss:[rsp]
    edx >>= 8  # shr edx, 0x08
    edx &= 0xFF  # and edx, 0xFF
     
    ecx += edx  # add ecx, edx
 
    ecx &= 0xffffffff
 
    eax ^= ecx  # xor eax, ecx
     
    ecx = stack[2# mov ecx, dword ptr ss:[rsp+0x08]
    ecx -= eax  # add ecx, eax
 
    ecx &= 0xffffffff
     
    stack[2] = ecx  # mov dword ptr ss:[rsp+0x08], eax (via ecx)
 
    eax = stack[5# mov eax, dword ptr ss:[rsp+0x14]
    ecx = stack[0# mov ecx, dword ptr ss:[rsp]
    ecx -= eax  # add ecx, eax
 
    ecx &= 0xffffffff
     
    stack[0] = ecx  # mov dword ptr ss:[rsp], eax (via ecx)
 
    eax = stack[2# mov eax, dword ptr ss:[rsp+0x08]
    eax <<= 4  # shl eax, 0x04
 
    eax &= 0xffffffff
     
    ecx = stack[0# mov ecx, dword ptr ss:[rsp]
    ecx >>= 24  # shr ecx, 0x18
    ecx &= 0xFF  # and ecx, 0xFF
     
    eax += ecx  # add eax, ecx
 
    eax &= 0xffffffff
     
    ecx = stack[0# mov ecx, dword ptr ss:[rsp]
    edx = stack[2# mov edx, dword ptr ss:[rsp+0x08]
    edx += ecx  # add edx, ecx
 
    edx &= 0xffffffff
     
    ecx = edx  # mov ecx, edx
    eax ^= ecx  # xor eax, ecx
     
    ecx = stack[2# mov ecx, dword ptr ss:[rsp+0x08]
    ecx >>= 5  # shr ecx, 0x05
     
    edx = stack[0# mov edx, dword ptr ss:[rsp]
    edx &= 0xFF  # and edx, 0xFF
     
    ecx += edx  # add ecx, edx
 
    ecx &= 0xffffffff
 
    eax ^= ecx  # xor eax, ecx
     
    ecx = stack[1# mov ecx, dword ptr ss:[rsp+0x04]
    ecx -= eax  # add ecx, eax
 
    ecx &= 0xffffffff
     
    stack[1] = ecx  # mov dword ptr ss:[rsp+0x04], eax (via ecx)
     
    eax = stack[4# mov eax, dword ptr ss:[rsp+0x10]
    eax += 1  # inc eax
     
    stack[4] = eax  # mov dword ptr ss:[rsp+0x10], eax
 
print(hex(stack[0]))
print(hex(stack[1]))
print(hex(stack[2]))
print(hex(stack[3]))
print(hex(stack[5]))
 
stack[5] = 0x5F656D6F #0x67575959
stack[4] = 0
stack[3] = 0
stack[0] = 0x2538263C #0x5A5F2142
 
eax = 0
ecx = 0
edx = 0
for _ in range(0x1f):
    eax = stack[5# mov eax, dword ptr ss:[rsp+0x14]
    ecx = stack[0# mov ecx, dword ptr ss:[rsp]
    ecx += eax  # add ecx, eax
 
    ecx &= 0xffffffff
 
    stack[0] = ecx  # mov dword ptr ss:[rsp], eax
 
stack[1] ^= stack[0]
stack[2] ^= stack[0]
 
while stack[3] < 0x1F:
    eax = stack[1# mov eax, dword ptr ss:[rsp+0x04]
    eax <<= 6  # shl eax, 0x06
 
    eax &= 0xffffffff
 
    ecx = (stack[0] >> 24) & 0xFF  # shr ecx, 0x18; and ecx, 0xFF
    eax += ecx  # add eax, ecx
 
    eax &= 0xffffffff
 
    edx = stack[1] + stack[0# add edx, ecx; add edx, ecx
 
    edx &= 0xffffffff
 
    eax ^= edx  # xor eax, ecx
 
    # shr ecx, 0x03; shr edx, 0x10; add ecx, edx
    ecx = (stack[1] >> 3) + ((stack[0] >> 16) & 0xFF)
    eax ^= ecx  # xor eax, ecx
 
    # add ecx, eax; mov ecx, dword ptr ss:[rsp+0x08]; add ecx, eax
    ecx = stack[2] - eax
 
    ecx &= 0xffffffff
 
    stack[2] = ecx  # mov dword ptr ss:[rsp+0x08], eax
 
    eax = stack[5# mov eax, dword ptr ss:[rsp+0x14]
    ecx = stack[0# mov ecx, dword ptr ss:[rsp]
    ecx -= eax  # add ecx, eax
 
    ecx &= 0xffffffff
 
    stack[0] = ecx  # mov dword ptr ss:[rsp], eax
 
    eax = stack[2# mov eax, dword ptr ss:[rsp+0x08]
    eax <<= 6  # shl eax, 0x06
 
    eax &= 0xffffffff
 
    ecx = stack[0# mov ecx, dword ptr ss:[rsp]
    ecx &= 0xFF  # and ecx, 0xFF
    eax += ecx  # add eax, ecx
 
    eax &= 0xffffffff
 
    # add edx, ecx; mov edx, dword ptr ss:[rsp+0x08]; add edx, ecx
    edx = stack[2] + stack[0]
 
    edx &= 0xffffffff
 
    eax ^= edx  # xor eax, ecx
 
    # shr ecx, 0x03; shr edx, 0x08; add ecx, edx
    ecx = (stack[2] >> 3) + ((stack[0] >> 8) & 0xFF)
    eax ^= ecx  # xor eax, ecx
 
    # add ecx, eax; mov ecx, dword ptr ss:[rsp+0x04]; add ecx, eax
    ecx = stack[1] - eax
 
    ecx &= 0xffffffff
 
    stack[1] = ecx  # mov dword ptr ss:[rsp+0x04], eax
 
    stack[3] += 1  # inc eax; mov dword ptr ss:[rsp+0x0C], eax
 
 
print(hex(stack[0]))
print(hex(stack[1]))
print(hex(stack[2]))
print(hex(stack[3]))
print(hex(stack[5]))

四、总结

到这里,我们通过替换stack数组里的值,即可得到完整的KCTF用户名的注册码了。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//