UPX解壳的一部分分析

Posted by marginal on 2021-07-18
Estimated Reading Time 5 Minutes
Words 1.2k In Total
Viewed Times

UPX loader分析

0x00 引用

https://bbs.ichunqiu.com/forum.php?mod=viewthread&tid=19345&highlight=UPX

https://bbs.pediy.com/thread-258222.htm#msg_header_h2_4

https://www.chinapyg.com/thread-76768-1-1.html

https://www.52pojie.cn/thread-294773-1-1.html

0x01 用ida进行调试

先用ida打开,可以看到两个分区upx0,upx1,直接静态调试太难了,上动态调试,(UPX1:00EBB870下断点)

0x02 地址入栈

1
2
3
4
5
6
7
8
9
10
11
UPX1:00EBB871 mov   esi, offset dword_EB9000  对esi edi初始化,分别装入upx1

UPX1:00EBB876 lea edi, [esi-8000h] ,upx0地址

UPX1:00EBB87C push edi

UPX1:00EBB87D or ebp, 0FFFFFFFFh

UPX1:00EBB880 jmp short loc_EBB892

UPX1:00EBB880 ;

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
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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
UPX1:00EBB882 align 8

UPX1:00EBB888

UPX1:00EBB888 loc_EBB888:

UPX1:00EBB888 mov al, [esi] 复制upx1到upx0

UPX1:00EBB88A inc esi

UPX1:00EBB88B mov [edi], al

UPX1:00EBB88D inc edi

UPX1:00EBB88E

UPX1:00EBB88E loc_EBB88E:

UPX1:00EBB88E

UPX1:00EBB88E add ebx, ebx

UPX1:00EBB890 jnz short loc_EBB899 若ebx为0不跳转,循环结束

UPX1:00EBB892 (ebx已经失效,需要重新读入)

UPX1:00EBB892 loc_EBB892:

UPX1:00EBB892 mov ebx, [esi] 读取esi地址对应内容放入ebx.

UPX1:00EBB894 sub esi, 0FFFFFFFCh ebx控制upx1复制到upx0循环

UPX1:00EBB897 adc ebx, ebx 的进行同时esi地址加4,已经

UPX1:00EBB899 读入的ebx不能作为内容复制到

UPX1:00EBB899 loc_EBB899: upx0

UPX1:00EBB899 jb short loc_EBB888 联系00EBB88E的add命令来判断

UPX1:00EBB89B mov eax, 1 upx1复制到upx0是否继续进行

UPX1:00EBB8A0

UPX1:00EBB8A0 loc_EBB8A0:

UPX1:00EBB8A0

UPX1:00EBB8A0 add ebx, ebx

UPX1:00EBB8A2 jnz short loc_EBB8AB 同00EBB890若ebx=0失效需要

UPX1:00EBB8A4 mov ebx, [esi] 重新读入

UPX1:00EBB8A6 sub esi, 0FFFFFFFCh

UPX1:00EBB8A9 adc ebx, ebx

UPX1:00EBB8AB

UPX1:00EBB8AB loc_EBB8AB:

UPX1:00EBB8AB adc eax, eax

UPX1:00EBB8AD add ebx, ebx

UPX1:00EBB8AF jnb short loc_EBB8A0

UPX1:00EBB8B1 jnz short loc_EBB8BC

UPX1:00EBB8B3 mov ebx, [esi] 还是在判断ebx是否需要重新读入

UPX1:00EBB8B5 sub esi, 0FFFFFFFCh

UPX1:00EBB8B8 adc ebx, ebx

UPX1:00EBB8BA jnb short loc_EBB8A0

UPX1:00EBB8BC

UPX1:00EBB8BC loc_EBB8BC:

UPX1:00EBB8BC xor ecx, ecx

UPX1:00EBB8BE sub eax, 3

UPX1:00EBB8C1 jb short loc_EBB8D0

UPX1:00EBB8C3 shl eax, 8

UPX1:00EBB8C6 mov al, [esi] 读入esi地址对应内容来

UPX1:00EBB8C8 inc esi 判断解密是否完成

UPX1:00EBB8C9 xor eax, 0FFFFFFFFh

UPX1:00EBB8CC jz short loc_EBB942

UPX1:00EBB8CE mov ebp, eax 得到ebp对后面upx自复制

UPX1:00EBB8D0 产生影响(偏移量)

UPX1:00EBB8D0 loc_EBB8D0:

UPX1:00EBB8D0 add ebx, ebx

UPX1:00EBB8D2 jnz short loc_EBB8DB

UPX1:00EBB8D4 mov ebx, [esi] 读取upx1的数据到ebx

UPX1:00EBB8D6 sub esi, 0FFFFFFFCh

UPX1:00EBB8D9 adc ebx, ebx

UPX1:00EBB8DB

UPX1:00EBB8DB loc_EBB8DB:

UPX1:00EBB8DB adc ecx, ecx

UPX1:00EBB8DD add ebx, ebx

UPX1:00EBB8DF jnz short loc_EBB8E8

UPX1:00EBB8E1 mov ebx, [esi]

UPX1:00EBB8E3 sub esi, 0FFFFFFFCh

UPX1:00EBB8E6 adc ebx, ebx

UPX1:00EBB8E8

UPX1:00EBB8E8 loc_EBB8E8:

UPX1:00EBB8E8 adc ecx, ecx

UPX1:00EBB8EA jnz short loc_EBB90C

UPX1:00EBB8EC inc ecx

UPX1:00EBB8ED

UPX1:00EBB8ED loc_EBB8ED:

UPX1:00EBB8ED

UPX1:00EBB8ED add ebx, ebx ebx控制ecx值,

UPX1:00EBB8EF jnz short loc_EBB8F8

UPX1:00EBB8F1 mov ebx, [esi]

UPX1:00EBB8F3 sub esi, 0FFFFFFFCh

UPX1:00EBB8F6 adc ebx, ebx

UPX1:00EBB8F8

UPX1:00EBB8F8 loc_EBB8F8:

UPX1:00EBB8F8 adc ecx, ecx ecx翻倍加CF

UPX1:00EBB8FA add ebx, ebx ebx判断循环是否继续

UPX1:00EBB8FC jnb short loc_EBB8ED

UPX1:00EBB8FE jnz short loc_EBB909

UPX1:00EBB900 mov ebx, [esi]

UPX1:00EBB902 sub esi, 0FFFFFFFCh

UPX1:00EBB905 adc ebx, ebx

UPX1:00EBB907 jnb short loc_EBB8ED

UPX1:00EBB909

UPX1:00EBB909 loc_EBB909:

UPX1:00EBB909 add ecx, 2

UPX1:00EBB90C

UPX1:00EBB90C loc_EBB90C:

UPX1:00EBB90C cmp ebp, 0FFFFF300h

UPX1:00EBB912 adc ecx, 1

UPX1:00EBB915 lea edx, [edi+ebp] ebp为向前偏移量,upx0复制

UPX1:00EBB918 cmp ebp, 0FFFFFFFCh 内容的开始地址

UPX1:00EBB91B jbe short loc_EBB92C 判断两种不同的upx0自复制方式

UPX1:00EBB91D ebp小于-4则用第二种

UPX1:00EBB91D loc_EBB91D:

UPX1:00EBB91D mov al, [edx] 第一种upx0内容复制过程

UPX1:00EBB91F inc edx

UPX1:00EBB920 mov [edi], al

UPX1:00EBB922 inc edi

UPX1:00EBB923 dec ecx ecx表示复制的次数,减少

UPX1:00EBB924 jnz short loc_EBB91D 为0则跳出循环

UPX1:00EBB926 jmp loc_EBB88E 向前跳转到upx1复制到upx0

UPX1:00EBB926 ; 语句的位置(先进行ebx判断)

UPX1:00EBB92B align 4

UPX1:00EBB92C

UPX1:00EBB92C loc_EBB92C:

UPX1:00EBB92C

UPX1:00EBB92C mov eax, [edx] 第二种upx0内容复制过程

UPX1:00EBB92E add edx, 4 ecx判断是否跳出循环每次

UPX1:00EBB931 mov [edi], eax 减4减溢出了则跳出循环

UPX1:00EBB933 add edi, 4

UPX1:00EBB936 sub ecx, 4

UPX1:00EBB939 ja short loc_EBB92C

UPX1:00EBB93B add edi, ecx 复制多了,地址前移,后面
复制覆盖前面复制多的
UPX1:00EBB93D jmp loc_EBB88E 跳回去进行upx1复制到upx0

这里带有0FFFFFFFCh的语句附近基本上都是读取upx1的内容到ebx,然后esi中的地址加4(读到ebx的内容不能作为upx0的内容要跳过它)0FFFFFFFFCh那一条是为了使地址加4

0x04 总结

upx的解码方式分为两种一种是将upx1的数据复制到upx0,第二种是将upx0自复制,这种自复制有两种,区别是一次循环复制的多少,第二种的明显效率更高,但是第一种可以单字节复制更适用,通过ebp来判断偏移,可以将upx0任意内容进行复制,ebx则是用来控制upx1复制到upx0的关键,是从upx1读入再进行运算,ecx是控制自复制的关键,是loader代码运算得到(ebx运算时CF改变和控制ecx运算循环会影响ecx),最后ebx xor (异或)ffffffff判断是否跳出循环。

可以看出,ebx是最关键的循环判断变量,而这个变量来源于upx1中,这应该是在加壳的时候就已经设置好位置和大小的

采用将重复的数据以循环写出的方式来减少空间储存(以一个来重复写出多个,这样就只用储存一个和重复条件,达到压缩的目的)


如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !