HITCTF的reverse方向总体都不难,由于是WIn32并且没有考察ollvm,主要考察方向有shellcode、动态加载、字符串混淆、花指令、驱动IO控制等一系列偏向于RW的技巧和知识点。这些知识点出现在很多流行恶意代码中,例如ransomware。
笔者稍微有一点恶意代码分析的经验,对本题目在比赛时已经还原的八九不离十,然而在最后一分钟判断奇偶时出现头昏行为把A、C判断为奇数导致没有提交flag。最后遗憾的没有苟到前十。但是题目本身已经吃透了,在这里把本题目的flag获取过程详细的给出,供参考。
一如既往,本Writeup会延续以前Writeup的风格,将按照解题的思路和顺序,对题目的考察点详细解释,可用于新手入门,但是会显得比较冗长。已经有基础的师傅可以略看,因为大部分时间我都在解释我如何看到这一点和解释我的解题思路
可以看到提示字符串并不符合,这可能是个假输出,或者就是在哪里对字符串进行了修改。另外,我们注意到在退出程序的时候程序有延迟,并不是丝滑的点击关闭按钮程序就退出了,而是程序需要等一两秒才退出。这引起了我们的怀疑,记在小本本上。
这个函数中包含了两个可疑的部分。图中标出了。分别是对参数的偏移和解引用。这种操作一般代表这个参数是一个结构体指针。但是目前还没有确认这是什么指针,先记在小本本上。接下来是一个SM3的常量。SM3是中华人民共和国政府采用的一种密码散列函数标准,由国家密码管理局于2010年12月17日发布。本质上SM3是一种密码散列函数,可以粗浅的理解为一种类似于SHA-2的算法。
于是这个函数sub_4011F0
就是我们一会儿要关注的一个点。我们接着继续查看main
函数,在尾部看到最后一个函数sub_401320
在这里我们看到了老朋友sub_4011F0
,证实了上面的猜测。
接下来,我们注意到下面的switch
块中存在两个常量。熟悉Windows开发的同学应该对这两个异常的十六进制值比较熟悉,它们分别是断点和拒绝访问错误。为什么题目在这里安置了这两个异常作为if的条件并且在其中安插了很像debug_maze
题目名中maze所指的迷宫的操作呢?我们也把这个东西记在小本本上。
别急,到这里有经验的师傅还会检查TLS函数。TLS 回调函数的调用运行要先于 EP 代码的执行。它是各线程独立的数据存储空间,可修改进程的全局/静态数据。换句话说,TLS将在OEP之前执行。按下Ctrl+E
,查看entry point
,果然在其中看到了TLS函数的身影
这里也出现了IsDebuggerPresent
函数的调用,但是简单的看一看逻辑就会发现,这里的F5结果中第25行的判断要求不存在调试器方才执行里面的代码。这就比较奇怪了。查看里面的函数,注意到函数sub_401D40
经常被调用,于是我们跟踪进去,查看其逻辑。
这个地址看上去像是一个字符串。但是我们还未知道字符串的内容是什么。后一个函数接收两个参数,而传递给他的参数第一个为&unk_4258B8 + 1
,第二个参数为这个字符串的第一个字符。跟踪到函数内可以看到函数的逻辑是异或加密
1
2
3
4
5
6
7
8
9
10
11
12
int
__cdecl sub_401D10(_BYTE
*
a1, char a2)
{
int
result;
/
/
eax
do
{
*
a1
+
+
^
=
a2;
result
=
(unsigned __int8)
*
a1;
}
while
(
*
a1 );
return
result;
}
From Hex, XOR - CyberChefXOR({'option':'Hex','string':'0x7f'},'Standard',false)&input=N0YgMTggMTYgMDkgMUEgNUYgMTIgMUEgNUYgMDYgMTAgMEEgMEQgNUYgMTkgMTMgMUUgMTggNDUgN0YgMDAgMDAgMDAgMDA)
很好,我们看到了程序的输出字符串,这个函数改名为dec_xored
。后面紧跟的函数sub_4016C0
就是printf
函数(根据里面的va_start
标志),同样的,sub_401730
是scanf
。另一个函数sub_401D70
,经过类似的简要分析知道他是一个加密函数。用于在解密字符串后以任意密钥加密字符串,来防止内存搜索。
其中调用了函数_loaddll
。字面意义上看,这似乎是一个调用动态链接库的函数。跟踪查看函数中调用了ExitProcess
,因此可以知道这个函数和退出进程有关。我们暂时不管他。
因此这很可能是一个类似于GetProcAddress
函数的地址转换机构。但是如果我们按照dword_426388 := 9
的初始值执行分析,就会发现总是会出发访问异常。验证这一函数的结构体的方法,是使用vs对应的编译一个程序出来
在其函数中也存在这一函数,而上下文中并不存在跳转,并且在TLS到OEP中都不存在自修改trick,因此我们可以认定,这个代码很可能出错了。但是运行时并没有出现这一错误,调试器也没有遇到这一问题,Windows也没有遇到这一问题,那么只有可能是我们的复现出错了。
有人问有没有可能是某处的SEH
或者VEH
(一种异常处理机制)?答案是否定的。先观察我们漏掉的“系统函数”_CRT_INIT
,只有在.text:004017B4
处调用的_CRT_INIT
中初始化了SEH链。在.text:00D3396F
中调用了一个sub_40F960
,这个函数是一个数组调用函数(CALL_LIST
)即对调用输入的参数。在其第一个参数unk_41E128
的第二个offset sub_401000
中调用了sub_403150
,对byte_426B90
进行了大量的赋值。这个变量也在刚才我们说到的异常分析函数中出现了。
其参数为0,代表传递给系统默认的错误处理句柄。稍有VS工程逆向经验的师傅都清楚,start
中的诸多操作都很干净,这些异常是为了防止栈溢出的操作。感兴趣的同学可以自己编译一个vs项目做实验,笔者使用VS2022任意编译的项目的起始代码和题目的代码相差无几。下面给出笔者编译的代码(包含了vs自动生成的符号表)
返回值被存储在eax
里,而这个返回值本应该是一个if
选择结构,这里因为可以执行编译前运算,IDA自动把不会触发的分支省略了,即右半边的loc_4011D1
。这里的汇编代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.text:
004011BD
58
pop eax
.text:
004011BE
58
pop eax
.text:
004011BF
33
C0 xor eax, eax
.text:
004011C1
83
F0
03
xor eax,
3
.text:
004011C4
E8
00
00
00
00
call $
+
5
.text:
004011C9
F7 E0 mul eax
.text:
004011CB
83
F8
51
cmp
eax,
51h
;
'Q'
.text:
004011CE
74
01
jz short loc_4011D1
.text:
004011D0
C3 retn
.text:
004011D1
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
.text:
004011D1
.text:
004011D1
loc_4011D1: ; CODE XREF: sub_401170
+
5E
↑j
.text:
004011D1
83
E8
21
sub eax,
21h
;
'!'
.text:
004011D4
64
8B
00
mov eax, fs:[eax]
.text:
004011D7
8B
40
0C
mov eax, [eax
+
0Ch
]
.text:
004011DA
8B
40
0C
mov eax, [eax
+
0Ch
]
.text:
004011DD
8B
00
mov eax, [eax]
.text:
004011DF
8B
00
mov eax, [eax]
.text:
004011E1
8B
40
18
mov eax, [eax
+
18h
]
.text:
004011E4
5D
pop ebp
.text:
004011E5
C3 retn
其中出现了一个指令:call $+5
,这是一个经典的反分析trick。在《恶意代码分析实战》第15章“对抗反汇编”第15.4.3节“滥用返回指针”中详细解释了这一花指令的原理
对于我们这里的花指令,call $+5
会执行mul eax
两次,一次由call跳转,然后call结束时返回到mul eax
顺序执行,因此正确的执行结果是eax == 51h
,满足jz
的条件,从而通过PEB获取了kernel32.dll
基址
后面部分的是SM3加密,这个加密我们可以轻易地知道这段代码实现了GetProcAddress
的机制,也就是通过将函数的名称做数字签名,依次与传入的第二个参数进行比较,从而简介获取函数地址。有兴趣的师傅可以自己手动实现一个SM3代码,这里给出一个参考
我的方法是通过绕过IsDebuggerPresent
的方法动态调试,或者叫任意执行到这个函数,然后看eax对应的函数结构判断函数。通过判断,能够轻易地给出各种函数的名称,换句话说,导入表。下面给出一个示例
题目在未被调试的环境下创建了子进程,并使用DEBUG_ONLY_THIS_PROCESS | DEBUG_PROCESS
启动。这样会使子进程进入被调试状态,将其事件全部发送给父进程,父进程接收子进程线程的异常,处理并观察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
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
.text:
00D31A38
60
pusha
.text:
00D31A39
B9
01
00
00
00
mov ecx,
1
.text:
00D31A3E
C1 E1
03
shl ecx,
3
.text:
00D31A41
B8
02
00
00
00
mov eax,
2
.text:
00D31A46
BB
09
00
00
00
mov ebx,
9
.text:
00D31A4B
33
D2 xor edx, edx
.text:
00D31A4D
8B
12
mov edx, [edx]
.text:
00D31A4F
B9
01
00
00
00
mov ecx,
1
.text:
00D31A54
D1 E1 shl ecx,
1
.text:
00D31A56
B8
04
00
00
00
mov eax,
4
.text:
00D31A5B
CC
int
3
; Trap to Debugger
.text:
00D31A5C
B9
01
00
00
00
mov ecx,
1
.text:
00D31A61
C1 E1
02
shl ecx,
2
.text:
00D31A64
B8
00
00
00
00
mov eax,
0
.text:
00D31A69
CC
int
3
; Trap to Debugger
.text:
00D31A6A
B9
01
00
00
00
mov ecx,
1
.text:
00D31A6F
D1 E1 shl ecx,
1
.text:
00D31A71
B8
00
00
00
00
mov eax,
0
.text:
00D31A76
BB FF FF FF FF mov ebx,
0FFFFFFFFh
.text:
00D31A7B
33
D2 xor edx, edx
.text:
00D31A7D
8B
12
mov edx, [edx]
.text:
00D31A7F
B9
01
00
00
00
mov ecx,
1
.text:
00D31A84
C1 E1
04
shl ecx,
4
.text:
00D31A87
B8
00
00
00
00
mov eax,
0
.text:
00D31A8C
BB
06
00
00
00
mov ebx,
6
.text:
00D31A91
CC
int
3
; Trap to Debugger
.text:
00D31A92
B9
01
00
00
00
mov ecx,
1
.text:
00D31A97
B8
00
00
00
00
mov eax,
0
.text:
00D31A9C
BB
05
00
00
00
mov ebx,
5
.text:
00D31AA1
33
D2 xor edx, edx
.text:
00D31AA3
8B
12
mov edx, [edx]
.text:
00D31AA5
B9
01
00
00
00
mov ecx,
1
.text:
00D31AAA
C1 E1
03
shl ecx,
3
.text:
00D31AAD
B8
01
00
00
00
mov eax,
1
.text:
00D31AB2
BB
00
00
00
00
mov ebx,
0
.text:
00D31AB7
33
D2 xor edx, edx
.text:
00D31AB9
8B
12
mov edx, [edx]
.text:
00D31ABB
B9
01
00
00
00
mov ecx,
1
.text:
00D31AC0
C1 E1
04
shl ecx,
4
.text:
00D31AC3
B8
01
00
00
00
mov eax,
1
.text:
00D31AC8
BB
02
00
00
00
mov ebx,
2
.text:
00D31ACD
33
D2 xor edx, edx
.text:
00D31ACF
8B
12
mov edx, [edx]
.text:
00D31AD1
B9
01
00
00
00
mov ecx,
1
.text:
00D31AD6
B8
02
00
00
00
mov eax,
2
.text:
00D31ADB
CC
int
3
; Trap to Debugger
.text:
00D31ADC
B9
01
00
00
00
mov ecx,
1
.text:
00D31AE1
D1 E1 shl ecx,
1
.text:
00D31AE3
B8
04
00
00
00
mov eax,
4
.text:
00D31AE8
BB FF FF FF FF mov ebx,
0FFFFFFFFh
.text:
00D31AED
33
D2 xor edx, edx
.text:
00D31AEF
8B
12
mov edx, [edx]
.text:
00D31AF1
B9
01
00
00
00
mov ecx,
1
.text:
00D31AF6
C1 E1
05
shl ecx,
5
.text:
00D31AF9
B8
0F
00
00
00
mov eax,
0Fh
.text:
00D31AFE
33
D2 xor edx, edx
.text:
00D31B00
8B
12
mov edx, [edx]
.text:
00D31B02
B9
01
00
00
00
mov ecx,
1
.text:
00D31B07
B8
00
00
00
00
mov eax,
0
.text:
00D31B0C
BB
06
00
00
00
mov ebx,
6
.text:
00D31B11
33
D2 xor edx, edx
.text:
00D31B13
8B
12
mov edx, [edx]
.text:
00D31B15
B9
01
00
00
00
mov ecx,
1
.text:
00D31B1A
D1 E1 shl ecx,
1
.text:
00D31B1C
B8
00
00
00
00
mov eax,
0
.text:
00D31B21
BB
01
00
00
00
mov ebx,
1
.text:
00D31B26
33
D2 xor edx, edx
.text:
00D31B28
8B
12
mov edx, [edx]
.text:
00D31B2A
B9
01
00
00
00
mov ecx,
1
.text:
00D31B2F
C1 E1
03
shl ecx,
3
.text:
00D31B32
B8
01
00
00
00
mov eax,
1
.text:
00D31B37
BB
00
00
00
00
mov ebx,
0
.text:
00D31B3C
33
D2 xor edx, edx
.text:
00D31B3E
8B
12
mov edx, [edx]
.text:
00D31B40
B9
01
00
00
00
mov ecx,
1
.text:
00D31B45
C1 E1
04
shl ecx,
4
.text:
00D31B48
B8
01
00
00
00
mov eax,
1
.text:
00D31B4D
BB
02
00
00
00
mov ebx,
2
.text:
00D31B52
33
D2 xor edx, edx
.text:
00D31B54
8B
12
mov edx, [edx]
.text:
00D31B56
B9
01
00
00
00
mov ecx,
1
.text:
00D31B5B
B8
02
00
00
00
mov eax,
2
.text:
00D31B60
CC
int
3
; Trap to Debugger
.text:
00D31B61
B9
01
00
00
00
mov ecx,
1
.text:
00D31B66
D1 E1 shl ecx,
1
.text:
00D31B68
B8
05
00
00
00
mov eax,
5
.text:
00D31B6D
BB
01
00
00
00
mov ebx,
1
.text:
00D31B72
33
D2 xor edx, edx
.text:
00D31B74
8B
12
mov edx, [edx]
.text:
00D31B76
B9
01
00
00
00
mov ecx,
1
.text:
00D31B7B
C1 E1
05
shl ecx,
5
.text:
00D31B7E
B8
08
00
00
00
mov eax,
8
.text:
00D31B83
33
D2 xor edx, edx
.text:
00D31B85
8B
12
mov edx, [edx]
.text:
00D31B87
B9
01
00
00
00
mov ecx,
1
.text:
00D31B8C
B8
00
00
00
00
mov eax,
0
.text:
00D31B91
BB
06
00
00
00
mov ebx,
6
.text:
00D31B96
33
D2 xor edx, edx
.text:
00D31B98
8B
12
mov edx, [edx]
.text:
00D31B9A
B9
01
00
00
00
mov ecx,
1
.text:
00D31B9F
D1 E1 shl ecx,
1
.text:
00D31BA1
B8
00
00
00
00
mov eax,
0
.text:
00D31BA6
BB FF FF FF FF mov ebx,
0FFFFFFFFh
.text:
00D31BAB
33
D2 xor edx, edx
.text:
00D31BAD
8B
12
mov edx, [edx]
.text:
00D31BAF
B9
01
00
00
00
mov ecx,
1
.text:
00D31BB4
C1 E1
03
shl ecx,
3
.text:
00D31BB7
B8
01
00
00
00
mov eax,
1
.text:
00D31BBC
BB
00
00
00
00
mov ebx,
0
.text:
00D31BC1
33
D2 xor edx, edx
.text:
00D31BC3
8B
12
mov edx, [edx]
.text:
00D31BC5
B9
01
00
00
00
mov ecx,
1
.text:
00D31BCA
C1 E1
04
shl ecx,
4
.text:
00D31BCD
B8
01
00
00
00
mov eax,
1
.text:
00D31BD2
BB
02
00
00
00
mov ebx,
2
.text:
00D31BD7
33
D2 xor edx, edx
.text:
00D31BD9
8B
12
mov edx, [edx]
.text:
00D31BDB
B9
01
00
00
00
mov ecx,
1
.text:
00D31BE0
B8
02
00
00
00
mov eax,
2
.text:
00D31BE5
CC
int
3
; Trap to Debugger
.text:
00D31BE6
B9
01
00
00
00
mov ecx,
1
.text:
00D31BEB
D1 E1 shl ecx,
1
.text:
00D31BED
B8
04
00
00
00
mov eax,
4
.text:
00D31BF2
BB
01
00
00
00
mov ebx,
1
.text:
00D31BF7
33
D2 xor edx, edx
.text:
00D31BF9
8B
12
mov edx, [edx]
.text:
00D31BFB
B9
01
00
00
00
mov ecx,
1
.text:
00D31C00
C1 E1
05
shl ecx,
5
.text:
00D31C03
B8
01
00
00
00
mov eax,
1
.text:
00D31C08
33
D2 xor edx, edx
.text:
00D31C0A
8B
12
mov edx, [edx]
.text:
00D31C0C
B9
01
00
00
00
mov ecx,
1
.text:
00D31C11
C1 E1
05
shl ecx,
5
.text:
00D31C14
CC
int
3
; Trap to Debugger
.text:
00D31C15
B9
01
00
00
00
mov ecx,
1
.text:
00D31C1A
D1 E1 shl ecx,
1
.text:
00D31C1C
B8
09
00
00
00
mov eax,
9
.text:
00D31C21
BB
01
00
00
00
mov ebx,
1
.text:
00D31C26
33
D2 xor edx, edx
.text:
00D31C28
8B
12
mov edx, [edx]
.text:
00D31C2A
B9
01
00
00
00
mov ecx,
1
.text:
00D31C2F
C1 E1
03
shl ecx,
3
.text:
00D31C32
CC
int
3
; Trap to Debugger
.text:
00D31C33
61
popa
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
ins
=
[
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'3'
,
'mov'
,
'eax'
,
'2'
,
'mov'
,
'ebx'
,
'9'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'1'
,
'mov'
,
'eax'
,
'4'
,
'int'
,
'3'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'2'
,
'mov'
,
'eax'
,
'0'
,
'int'
,
'3'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'1'
,
'mov'
,
'eax'
,
'0'
,
'mov'
,
'ebx'
,
'-1'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'4'
,
'mov'
,
'eax'
,
'0'
,
'mov'
,
'ebx'
,
'6'
,
'int'
,
'3'
,
'mov'
,
'ecx'
,
'1'
,
'mov'
,
'eax'
,
'0'
,
'mov'
,
'ebx'
,
'5'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'3'
,
'mov'
,
'eax'
,
'1'
,
'mov'
,
'ebx'
,
'0'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'4'
,
'mov'
,
'eax'
,
'1'
,
'mov'
,
'ebx'
,
'2'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'mov'
,
'eax'
,
'2'
,
'int'
,
'3'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'1'
,
'mov'
,
'eax'
,
'4'
,
'mov'
,
'ebx'
,
'-1'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'5'
,
'mov'
,
'eax'
,
'15'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'mov'
,
'eax'
,
'0'
,
'mov'
,
'ebx'
,
'6'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'1'
,
'mov'
,
'eax'
,
'0'
,
'mov'
,
'ebx'
,
'1'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'3'
,
'mov'
,
'eax'
,
'1'
,
'mov'
,
'ebx'
,
'0'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'4'
,
'mov'
,
'eax'
,
'1'
,
'mov'
,
'ebx'
,
'2'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'mov'
,
'eax'
,
'2'
,
'int'
,
'3'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'1'
,
'mov'
,
'eax'
,
'5'
,
'mov'
,
'ebx'
,
'1'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'5'
,
'mov'
,
'eax'
,
'8'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'mov'
,
'eax'
,
'0'
,
'mov'
,
'ebx'
,
'6'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'1'
,
'mov'
,
'eax'
,
'0'
,
'mov'
,
'ebx'
,
'-1'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'3'
,
'mov'
,
'eax'
,
'1'
,
'mov'
,
'ebx'
,
'0'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'4'
,
'mov'
,
'eax'
,
'1'
,
'mov'
,
'ebx'
,
'2'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'mov'
,
'eax'
,
'2'
,
'int'
,
'3'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'1'
,
'mov'
,
'eax'
,
'4'
,
'mov'
,
'ebx'
,
'1'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'5'
,
'mov'
,
'eax'
,
'1'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'5'
,
'int'
,
'3'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'1'
,
'mov'
,
'eax'
,
'9'
,
'mov'
,
'ebx'
,
'1'
,
'xor'
,
'edx'
,
'edx'
,
'mov'
,
'edx'
,
'[edx]'
,
'mov'
,
'ecx'
,
'1'
,
'shl'
,
'ecx'
,
'3'
,
'int'
,
'3'
,
'popa'
,
]
def
ROL(i,index):
tmp
=
bin
(i)[
2
:].rjust(
8
,
"0"
)
for
_
in
range
(index):
tmp
=
tmp[
1
:]
+
tmp[
0
]
return
int
(tmp,
2
)
CONTEXT
=
{
'eax'
:
0
,
'ebx'
:
0
,
'ecx'
:
0
,
'edx'
:
0
}
round
=
0
eip
=
0
while
True
:
if
(ins[eip]
=
=
'mov'
):
if
(ins[eip
+
2
][
0
]
=
=
'['
):
if
(CONTEXT[
'ecx'
]
=
=
1
):
print
(
'sub_D33570('
+
str
(CONTEXT[
'eax'
])
+
', '
+
str
(CONTEXT[
'ebx'
])
+
');'
)
elif
(CONTEXT[
'ecx'
]
=
=
2
):
print
(
'sub_D335B0('
+
str
(CONTEXT[
'eax'
])
+
', '
+
str
(CONTEXT[
'ebx'
])
+
');'
)
elif
(CONTEXT[
'ecx'
]
=
=
4
):
print
(
'sub_D335E0('
+
str
(CONTEXT[
'eax'
])
+
', '
+
str
(CONTEXT[
'ebx'
])
+
');'
)
elif
(CONTEXT[
'ecx'
]
=
=
8
):
print
(
'sub_D33610('
+
str
(CONTEXT[
'eax'
])
+
', '
+
str
(CONTEXT[
'ebx'
])
+
');'
)
elif
(CONTEXT[
'ecx'
]
=
=
16
):
print
(
'sub_D33640('
+
str
(CONTEXT[
'eax'
])
+
', '
+
str
(CONTEXT[
'ebx'
])
+
');'
)
elif
(CONTEXT[
'ecx'
]
=
=
32
):
print
(
'sub_D33680('
+
str
(CONTEXT[
'eax'
])
+
');'
)
else
:
CONTEXT[ins[eip
+
1
]]
=
int
(ins[eip
+
2
])
elif
(ins[eip]
=
=
'shl'
):
CONTEXT[ins[eip
+
1
]]
=
CONTEXT[ins[eip
+
1
]] <<
int
(ins[eip
+
2
])
elif
(ins[eip]
=
=
'xor'
):
CONTEXT[ins[eip
+
1
]]
=
CONTEXT[ins[eip
+
1
]] ^ CONTEXT[ins[eip
+
2
]]
elif
(ins[eip]
=
=
'int'
):
eip
=
eip
-
1
if
(CONTEXT[
'ecx'
]
=
=
1
):
print
(
'sub_D336A0('
+
str
(CONTEXT[
'eax'
])
+
');'
)
elif
(CONTEXT[
'ecx'
]
=
=
2
):
print
(
'sub_D336D0('
+
str
(CONTEXT[
'eax'
])
+
');'
)
elif
(CONTEXT[
'ecx'
]
=
=
4
):
print
(
'sub_D33720('
+
str
(CONTEXT[
'eax'
])
+
');'
)
elif
(CONTEXT[
'ecx'
]
=
=
8
):
print
(
'CorrectOutput();'
)
elif
(CONTEXT[
'ecx'
]
=
=
16
):
print
(
'sub_D33800('
+
str
(CONTEXT[
'eax'
])
+
', '
+
str
(CONTEXT[
'ebx'
])
+
');'
)
elif
(CONTEXT[
'ecx'
]
=
=
32
):
print
(
'WrongOutput();'
)
elif
(ins[eip]
=
=
'popa'
):
eip
=
-
3
round
=
round
+
1
if
(
round
=
=
19
):
break
eip
=
eip
+
3
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
sub_D33610(
2
,
9
);
sub_D336D0(
4
);
sub_D33720(
0
);
sub_D335B0(
0
,
-
1
);
sub_D33800(
0
,
6
);
sub_D33570(
0
,
5
);
sub_D33610(
1
,
0
);
sub_D33640(
1
,
2
);
sub_D336A0(
2
);
sub_D335B0(
4
,
-
1
);
sub_D33680(
15
);
sub_D33570(
0
,
6
);
sub_D335B0(
0
,
1
);
sub_D33610(
1
,
0
);
sub_D33640(
1
,
2
);
sub_D336A0(
2
);
sub_D335B0(
5
,
1
);
sub_D33680(
8
);
sub_D33570(
0
,
6
);
sub_D335B0(
0
,
-
1
);
sub_D33610(
1
,
0
);
sub_D33640(
1
,
2
);
sub_D336A0(
2
);
sub_D335B0(
4
,
1
);
sub_D33680(
1
);
WrongOutput();
sub_D335B0(
9
,
1
);
CorrectOutput();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
EXCEPTION_BREAKPOINT
case
1u
:sub_D336A0(_eax);
case
2u
:sub_D336D0(_eax);
case
4u
:sub_D33720(_eax);
case
8u
:_CorrectOutput();
case
0x10u
:sub_D33800(_eax, _ebx);
case
0x20u
:_WrongOutput();
EXCEPTION_ACCESS_VIOLATION
case
1u
:sub_D33570(_eax, _ebx);
case
2u
:sub_D335B0(_eax, _ebx);
case
4u
:sub_D335E0(_eax, _ebx);
case
8u
:sub_D33610(_eax, _ebx);
case
0x10u
:
cmp
(_eax, _ebx);
case
0x20u
:sub_D33680(_eax);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
EXCEPTION_BREAKPOINT
case
1u
:jnz(_eax);
case
2u
:push(_eax);
case
4u
:pop(_eax);
case
8u
:_CorrectOutput();
case
0x10u
:mul(_eax, _ebx);
case
0x20u
:_WrongOutput();
EXCEPTION_ACCESS_VIOLATION
case
1u
:add(_eax, _ebx);
case
2u
:addn(_eax, _ebx);
/
/
直接访存
case
4u
:store(_eax, _ebx);
case
8u
:load(_eax, _ebx);
case
0x10u
:
cmp
(_eax, _ebx);
case
0x20u
:jmp(_eax);
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
load(
2
,
9
);
push(
4
);
pop(
0
);
addn(
0
,
-
1
);
mul(
0
,
6
);
add(
0
,
5
);
load(
1
,
0
);
cmp
(
1
,
2
);
jnz(
2
);
addn(
4
,
-
1
);
jmp(
15
);
add(
0
,
6
);
addn(
0
,
1
);
load(
1
,
0
);
cmp
(
1
,
2
);
jnz(
2
);
addn(
5
,
1
);
jmp(
8
);
add(
0
,
6
);
addn(
0
,
-
1
);
load(
1
,
0
);
cmp
(
1
,
2
);
jnz(
2
);
addn(
4
,
1
);
jmp(
1
);
WrongOutput();
addn(
9
,
1
);
CorrectOutput();
分析上面的执行流,可以知道这个执行流的逻辑极其简单。其从byte_426B90
中读取数据并寻找这个数据,判断迷宫。换句话说可以认为,输入的数据首先要在byte_426B90
的范围内,如果数据和迷宫的字节相同,则往那个方向走一步。如果没有就报错,如果走错了也报错。byte_426B90
的初始化是一个迷宫。走迷宫的规则在TLS函数里,其规则很简单,只需要依据奇数走迷宫即可。
而我们被处理的输入,在.text:00401346
的memmove(&unk_426C58, &Str1, 0x13u);
被放置在unk_426C58
中,这个变量其实是byte_426B90
的第0xC8
位置。(0xC8
同时也是dword_427B90[9]
的值)。迷宫有dword_427B90[6] = 12
行,初始位置坐标为(5,0)
(dword_427B90[4] = 5;dword_427B90[5] = 0;
)