UPX对pe文件(x64)的加壳过程
[*]压缩前1,将原pe文件按内存展开方式读入ibuf缓冲区,在区块数据后面拼接处理过的原导入表数数组oimport、重定位表orelocs等数据;2,清空区块数据中的调试目录Debug Directory、清空拷贝到oresources中的不压缩资源数据、重定位地址VA转换成相对rvamin的偏移并清空原重定位表;应该是为了提升压缩率3,自定义的导入表结构:
1
2
3
4
5
6
7
8
9
typedef struct _oimport{//要恢复的导入表数组oimport
DWORD rva_dllname; // +00 dll名称在新资源表oresources中的rva 0表示结束
DWORD rva_iat; // +04 iat的rva
//之后是函数数组
BYTE type; // +08 类型 1表示之后是dll函数名称 0xff之后函数序号 0xfe之后kernel32的函数名称rva 0表示当前dll不再有函数导入
//根据不同的type之后可能是字符串、2字节的函数序号、4字节的rva
//下一个dll
}
4,自定义的重定位表,没有采用相对于每个块VirtualAddress的位移,而是使用相对前一个要处理的重定位地址的偏移
[*]upx压缩
1,Dos头、文件头原样输出,在头部最后添加了upx版本信息;
1
2
3
4
5
6
7
p->doPack(fo);
void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh,
unsigned subsystem_mask, upx_uint64_t default_imagebase,
bool last_section_rsrc_only)
readSectionHeaders(objs, sizeof(ih)); //读取节表 节表紧接在NtHeader之后
handleStub(fi,fo,pe_offset); //DosHeader、 DosStub等 NtHeader.OptionalHeader 之前的数据不做处理 直接输出
unsigned overlaystart = readSections(objs, ih.imagesize, ih.filealign, ih.datasize); //读入所有区块数据到ibuf
2,将ibuf中从rvamin开始的数据压缩到obuf,保存到upx1开始的位置; 3,紧接着的是壳代码loader,并作为新的oep; 4,生成新线程局部存储otls;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void PeFile::processTls1(Interval *iv,
typename tls_traits<LEXX>::cb_value_t imagebase,
unsigned imagesize)
//判断有多少个回调函数
//保存重定位表中涉及tls的数据(在datastart与dataend之间)到临时结构tlsiv
//如果原tls有回调函数,这里需要在otls最后预留2个位置用于存储回调函数tls_handler_offset和表示结束0填充回调函数
//原tls目录整体保存到otls
//将原TLS数据模板(datastart与dataend之间)的内容复制到ols
//将原tls的AddressOfIndex字段设置为0
void PeFile::processTls2(Reloc *rel,const Interval *iv,unsigned newaddr,
typename tls_traits<LEXX>::cb_value_t imagebase)
//x32需要修正rel->add(tls_handler_offset + tls_handler_offset_reloc, reloc_type); x64不需要。应该是跟tls_handler的代码有关(待验证)
//因为tls使用的是VA不是RVA,将otls的前几个数据都加入到新的重定位表
//将tlsiv中涉及的需要修改的重定位数据添加到新的重定位表
//修正原tls的数据模板(datastart、dataend)的VA地址
//如果原tls有回调,将tls_handler_offset和0填充到otls最后的位置,将otls的callbacks修正为指向otls中tls_handler_offset正确的VA
//因为tls使用的是VA不是RVA,将修正后的VA都要加入的新的重定位表
5,生成新资源表oresources(程序默认图标等资源不能压缩);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void PeFile::processResources(Resource *res)//处理资源
res->init(ibuf.subref("bad res %#x", vaddr, 1));
start = res;
root = head = current = NULL;//root指向根节点 head用于串联叶子节点 current用于遍历叶子节点
dsize = ssize = 0;//dsize记录所有1-4级节点数据长度 ssize记录涉及到的unicode strings字符串占用长度
root = convert(start,NULL,0);//从数组的最后1个元素向前遍历,所以head指向第一个叶子节点
for (soresources = res->dirsize(); res->next(); soresources += 4 + res->size()); //遍历所有叶子节点取资源+dsize+ssize 一起赋值给soresources(即soresources为所有资源数据总长度)
if (opt->win32_pe.compress_icons == 2)
//取出第一个有图标的图标组中所有图标的id 格式3/id,(如"3/1,3/2,3/3,3/4")
//遍历所有叶子节点
//刚刚取出的第一个有图标的图标组及其下id对应的图标不压缩 其他的图标组及图标都压缩
//0x10版本信息 RT_VERSION 不压缩
//0x18MANIFEST元数据文件 不压缩
//将不压缩的资源数据拷贝到ores中,清空其在ibuf中的数据
//设置soresources为 未压缩资源+dsize+ssize
void PeFile::callProcessResources(Resource &res, unsigned &ic)
void PeFile::processResources(Resource *res,unsigned newaddr)
//遍历叶子节点 将newoffset加上新的根元素地址
upx_byte *p = res->build();//构建新的资源目录项
build(root,bpos,spos,0);//bpos存储节点数据的偏移 spos存储涉及到的unicode strings字符串的偏移
//将新的资源目录项拷贝到oresources的开始位置
//设置新资源目录表的RVA和sizesoresources为size
6,生成新导入表oimpdlls;
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
const unsigned dllstrings = processImports(); //处理导入表
//不理解"*UND*"、 "*ZSTART" 等section的作用? (size为0)
unsigned PeFile::processImports0(ord_mask_t ord_mask)
//获取导入表涉及多少个dll
//对dll进行排序
ilinker = new ImportLinker(sizeof(LEXX)); //*UND* *ZSTART Dzero Zzero
//addStubImports(); //将kernel32的 LoadLibraryA GetProcAddress ExitProcess VirtualProtect 添加到导入表
//每个dll取1个函数 添加到导入表到ilinker (kernel32使用ordinals引入的全部添加)
soimpdlls = ilinker->build();//soimpdlls新导入表长度 建立的output用来存储新的导入表数据
qsort(sections, nsections, sizeof (Section*), ImportLinker::compare); //排序
addLoader(sections->name); //将section->input复制到output 设置section的offset字段 使用next串联section
//Dgbgehggbhagjdddccogegmgm advapi32.dll size:20
//Dgdgpgngdhegmdddccogegmgm comctl32.dll
//...
//Dhfhdgfhcdddccogegmgm user32.dll
//Dhfhihegigfgngfcogegmgm uxtheme.dll
//Dzero
//EgbgehggbhagjdddccogegmgmIfcgfghedgmgphdgfelgfhj advapi32.dll RegCloseKey size:8
//EgbgehggbhagjdddccogegmgmKfi advapi32.dll X //X相当于填充0
//EgdgpgngdhegmdddccogegmgmIejgngbghgfemgjhdhefpeehcgbhh comctl32.dll ImageList_Draw
//EgdgpgngdhegmdddccogegmgmKfi comctl32.dll X
//...
//EhfhihegigfgngfcogegmgmIejhdebhahafegigfgngfge uxtheme.dll IsAppThemed
//EhfhihegigfgngfcogegmgmKfi uxtheme.dll X
//Fgbgehggbhagjdddccogegmgm advapi32.dll size:dll名称长度+1
//Fgdgpgngdhegmdddccogegmgm comctl32.dll
//...
//Fhfhihegigfgngfcogegmgm uxtheme.dll
//GgbgehggbhagjdddccogegmgmLfcgfghedgmgphdgfelgfhj advapi32.dll RegCloseKey size:2
//GgbgehggbhagjdddccogegmgmLfcgfghedgmgphdgfelgfhjX size:11
//...
//Zzero
void PeFile::processImports2(unsigned myimport, unsigned)
ilinker->relocate_import(myimport);
oimpdlls = ilinker->getLoader(&len);//新的导入表 len返回新导入表长度 output赋值给oimpdlls
[*]执行壳代码loader
1,将obuf中的数据解压到从upx0开始的位置; 2,根据解压后oimport的数据使用kernel32中的LoadLibraryA和GetProcAddress初始化原iat; 3,根据orelocs修正重定位数据; 4,去除upx0、upx1区段的可写属性; 5,跳转到真实oep继续执行
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
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
UPX1:000000013FE23B20 public start
UPX1:000000013FE23B20 start proc near
UPX1:000000013FE23B20 push rbx
UPX1:000000013FE23B21 push rsi
UPX1:000000013FE23B22 push rdi
UPX1:000000013FE23B23 push rbp
UPX1:000000013FE23B24 lea rsi, upx1_obuf; rsi指向upx1的VA 即压缩后的数据obuf
UPX1:000000013FE23B2B lea rdi, ; rdi指向upx0的VA
UPX1:000000013FE23B32 push rdi
UPX1:000000013FE23B33 xor ebx, ebx
UPX1:000000013FE23B35 xor ecx, ecx
UPX1:000000013FE23B37 or rbp, 0FFFFFFFFFFFFFFFFh
UPX1:000000013FE23B3B call loader_stub ; 栈参数rdi指向upx0的VA
UPX1:000000013FE23B3B start endp ; sp-analysis failed ; 寄存器
UPX1:000000013FE23B3B ; ebx=0
UPX1:000000013FE23B3B ; ecx=0
UPX1:000000013FE23B3B ; rsi指向upx1的VA 即压缩后的数据obuf
UPX1:000000013FE23B3B ; cld让方向标志位DF=0,std让DF=1
UPX1:000000013FE23B40
UPX1:000000013FE23B40 ; =============== S U B R O U T I N E =======================================
UPX1:000000013FE23B40
UPX1:000000013FE23B40 ; ebx左移1位如果为0
UPX1:000000013FE23B40 ;取esi处的Dword给ebx
UPX1:000000013FE23B40 ;rsi减-4
UPX1:000000013FE23B40 ;ebx带进位左移1位
UPX1:000000013FE23B40 ;从rsi处取1个字节给dl
UPX1:000000013FE23B40
UPX1:000000013FE23B40 get_ebx2_if0_rsi4ebx_rsi5dl proc near
UPX1:000000013FE23B40 add ebx, ebx
UPX1:000000013FE23B42 jz short loc_13FE23B46
UPX1:000000013FE23B44 rep retn
UPX1:000000013FE23B46 ; ---------------------------------------------------------------------------
UPX1:000000013FE23B46
UPX1:000000013FE23B46 loc_13FE23B46: ; CODE XREF: get_ebx2_if0_rsi4ebx_rsi5dl+2↑j
UPX1:000000013FE23B46 mov ebx,
UPX1:000000013FE23B48 sub rsi, 0FFFFFFFFFFFFFFFCh
UPX1:000000013FE23B4C adc ebx, ebx
UPX1:000000013FE23B4E mov dl,
UPX1:000000013FE23B50 rep retn
UPX1:000000013FE23B50 get_ebx2_if0_rsi4ebx_rsi5dl endp
UPX1:000000013FE23B50
UPX1:000000013FE23B52
UPX1:000000013FE23B52 ; =============== S U B R O U T I N E =======================================
UPX1:000000013FE23B52
UPX1:000000013FE23B52 ; 从rdi+rbp处开始复制ecx个字节到rdi处
UPX1:000000013FE23B52
UPX1:000000013FE23B52 copy2_rdi_from_rdirbp_ecx proc near ; CODE XREF: loader_stub+A3↓p
UPX1:000000013FE23B52 lea rax,
UPX1:000000013FE23B56 cmp ecx, 5
UPX1:000000013FE23B59 mov dl,
UPX1:000000013FE23B5B jbe short loc_13FE23B7E
UPX1:000000013FE23B5D cmp rbp, 0FFFFFFFFFFFFFFFCh
UPX1:000000013FE23B61 ja short loc_13FE23B7E
UPX1:000000013FE23B63 sub ecx, 4
UPX1:000000013FE23B66
UPX1:000000013FE23B66 loc_13FE23B66: ; CODE XREF: copy2_rdi_from_rdirbp_ecx+23↓j
UPX1:000000013FE23B66 mov edx,
UPX1:000000013FE23B68 add rax, 4
UPX1:000000013FE23B6C sub ecx, 4
UPX1:000000013FE23B6F mov , edx
UPX1:000000013FE23B71 lea rdi,
UPX1:000000013FE23B75 jnb short loc_13FE23B66
UPX1:000000013FE23B77 add ecx, 4
UPX1:000000013FE23B7A mov dl,
UPX1:000000013FE23B7C jz short locret_13FE23B8E
UPX1:000000013FE23B7E
UPX1:000000013FE23B7E loc_13FE23B7E: ; CODE XREF: copy2_rdi_from_rdirbp_ecx+9↑j
UPX1:000000013FE23B7E ; copy2_rdi_from_rdirbp_ecx+F↑j ...
UPX1:000000013FE23B7E inc rax
UPX1:000000013FE23B81 mov , dl
UPX1:000000013FE23B83 sub ecx, 1
UPX1:000000013FE23B86 mov dl,
UPX1:000000013FE23B88 lea rdi,
UPX1:000000013FE23B8C jnz short loc_13FE23B7E
UPX1:000000013FE23B8E
UPX1:000000013FE23B8E locret_13FE23B8E: ; CODE XREF: copy2_rdi_from_rdirbp_ecx+2A↑j
UPX1:000000013FE23B8E rep retn
UPX1:000000013FE23B8E copy2_rdi_from_rdirbp_ecx endp
UPX1:000000013FE23B8E
UPX1:000000013FE23B90
UPX1:000000013FE23B90 ; =============== S U B R O U T I N E =======================================
UPX1:000000013FE23B90
UPX1:000000013FE23B90 ; 栈参数rdi指向upx0的VA
UPX1:000000013FE23B90 ; 寄存器
UPX1:000000013FE23B90 ; ebx=0
UPX1:000000013FE23B90 ; ecx=0
UPX1:000000013FE23B90 ; rsi指向upx1的VA 即压缩后的数据obuf
UPX1:000000013FE23B90
UPX1:000000013FE23B90 loader_stub proc near ; CODE XREF: start+1B↑p
UPX1:000000013FE23B90
UPX1:000000013FE23B90 var_50 = byte ptr -50h
UPX1:000000013FE23B90 arg_0 = byte ptr8
UPX1:000000013FE23B90
UPX1:000000013FE23B90 get_ebx2_if0_rsi4ebx_rsi5dl = r11
UPX1:000000013FE23B90 cld
UPX1:000000013FE23B91 pop get_ebx2_if0_rsi4ebx_rsi5dl ; 返回地址 0x140053B40
UPX1:000000013FE23B93 jmp short loc_13FE23B9D
UPX1:000000013FE23B95 ; ---------------------------------------------------------------------------
UPX1:000000013FE23B95
UPX1:000000013FE23B95 loc_13FE23B95: ; CODE XREF: loader_stub:loc_13FE23BAD↓j
UPX1:000000013FE23B95 inc rsi
UPX1:000000013FE23B98 mov , dl ; 复制dl中的1字节数据到rdi指向的upx0
UPX1:000000013FE23B9A inc rdi ; rsi、rdi指向下一个待处理数据
UPX1:000000013FE23B9D
UPX1:000000013FE23B9D loc_13FE23B9D: ; CODE XREF: loader_stub+3↑j
UPX1:000000013FE23B9D ; loader_stub+A8↓j
UPX1:000000013FE23B9D mov dl,
UPX1:000000013FE23B9F add ebx, ebx ; 如果ebx不是0,从rsi处取1字节到dl,ebx左移1位
UPX1:000000013FE23BA1 jnz short loc_13FE23BAD ; ebx不是0跳转
UPX1:000000013FE23BA3 mov ebx, ; 如果ebx是0,重新从rsi处取Dword到ebx
UPX1:000000013FE23BA5 sub rsi, 0FFFFFFFFFFFFFFFCh ; rsi减-4
UPX1:000000013FE23BA9 adc ebx, ebx ; ebx带进位左移1位
UPX1:000000013FE23BAB mov dl, ; 从rsi处取1字节到dl
UPX1:000000013FE23BAD
UPX1:000000013FE23BAD loc_13FE23BAD: ; CODE XREF: loader_stub+11↑j
UPX1:000000013FE23BAD jb short loc_13FE23B95 ; 判断CF进位标志位,为1时跳转
UPX1:000000013FE23BAF lea eax,
UPX1:000000013FE23BB2 jmp short loc_13FE23BBB
UPX1:000000013FE23BB4 ; ---------------------------------------------------------------------------
UPX1:000000013FE23BB4
UPX1:000000013FE23BB4 loc_13FE23BB4: ; CODE XREF: loader_stub:loc_13FE23BCE↓j
UPX1:000000013FE23BB4 dec eax
UPX1:000000013FE23BB6 call get_ebx2_if0_rsi4ebx_rsi5dl
UPX1:000000013FE23BB9 adc eax, eax
UPX1:000000013FE23BBB
UPX1:000000013FE23BBB loc_13FE23BBB: ; CODE XREF: loader_stub+22↑j
UPX1:000000013FE23BBB call get_ebx2_if0_rsi4ebx_rsi5dl
UPX1:000000013FE23BBE adc eax, eax
UPX1:000000013FE23BC0 add ebx, ebx
UPX1:000000013FE23BC2 jnz short loc_13FE23BCE
UPX1:000000013FE23BC4 mov ebx,
UPX1:000000013FE23BC6 sub rsi, 0FFFFFFFFFFFFFFFCh
UPX1:000000013FE23BCA adc ebx, ebx
UPX1:000000013FE23BCC mov dl,
UPX1:000000013FE23BCE
UPX1:000000013FE23BCE loc_13FE23BCE: ; CODE XREF: loader_stub+32↑j
UPX1:000000013FE23BCE jnb short loc_13FE23BB4
UPX1:000000013FE23BD0 sub eax, 3
UPX1:000000013FE23BD3 jb short loc_13FE23BEE
UPX1:000000013FE23BD5 shl eax, 8
UPX1:000000013FE23BD8 movzx edx, dl
UPX1:000000013FE23BDB or eax, edx
UPX1:000000013FE23BDD inc rsi
UPX1:000000013FE23BE0 xor eax, 0FFFFFFFFh
UPX1:000000013FE23BE3 jz short loc_13FE23C3D ; 区块数据解压完成,准备开始处理导入表、重定位表等
UPX1:000000013FE23BE5 sar eax, 1
UPX1:000000013FE23BE7 movsxdrbp, eax
UPX1:000000013FE23BEA jb short loc_13FE23C24
UPX1:000000013FE23BEC jmp short loc_13FE23BFC
UPX1:000000013FE23BEE ; ---------------------------------------------------------------------------
UPX1:000000013FE23BEE
UPX1:000000013FE23BEE loc_13FE23BEE: ; CODE XREF: loader_stub+43↑j
UPX1:000000013FE23BEE add ebx, ebx
UPX1:000000013FE23BF0 jnz short loc_13FE23BFA
UPX1:000000013FE23BF2 mov ebx,
UPX1:000000013FE23BF4 sub rsi, 0FFFFFFFFFFFFFFFCh
UPX1:000000013FE23BF8 adc ebx, ebx
UPX1:000000013FE23BFA
UPX1:000000013FE23BFA loc_13FE23BFA: ; CODE XREF: loader_stub+60↑j
UPX1:000000013FE23BFA jb short loc_13FE23C24
UPX1:000000013FE23BFC
UPX1:000000013FE23BFC loc_13FE23BFC: ; CODE XREF: loader_stub+5C↑j
UPX1:000000013FE23BFC inc ecx
UPX1:000000013FE23BFE add ebx, ebx
UPX1:000000013FE23C00 jnz short loc_13FE23C0A
UPX1:000000013FE23C02 mov ebx,
UPX1:000000013FE23C04 sub rsi, 0FFFFFFFFFFFFFFFCh
UPX1:000000013FE23C08 adc ebx, ebx
UPX1:000000013FE23C0A
UPX1:000000013FE23C0A loc_13FE23C0A: ; CODE XREF: loader_stub+70↑j
UPX1:000000013FE23C0A jb short loc_13FE23C24
UPX1:000000013FE23C0C
UPX1:000000013FE23C0C loc_13FE23C0C: ; CODE XREF: loader_stub:loc_13FE23C1D↓j
UPX1:000000013FE23C0C call get_ebx2_if0_rsi4ebx_rsi5dl
UPX1:000000013FE23C0F adc ecx, ecx
UPX1:000000013FE23C11 add ebx, ebx
UPX1:000000013FE23C13 jnz short loc_13FE23C1D
UPX1:000000013FE23C15 mov ebx,
UPX1:000000013FE23C17 sub rsi, 0FFFFFFFFFFFFFFFCh
UPX1:000000013FE23C1B adc ebx, ebx
UPX1:000000013FE23C1D
UPX1:000000013FE23C1D loc_13FE23C1D: ; CODE XREF: loader_stub+83↑j
UPX1:000000013FE23C1D jnb short loc_13FE23C0C
UPX1:000000013FE23C1F add ecx, 2
UPX1:000000013FE23C22 jmp short loc_13FE23C29
UPX1:000000013FE23C24 ; ---------------------------------------------------------------------------
UPX1:000000013FE23C24
UPX1:000000013FE23C24 loc_13FE23C24: ; CODE XREF: loader_stub+5A↑j
UPX1:000000013FE23C24 ; loader_stub:loc_13FE23BFA↑j ...
UPX1:000000013FE23C24 call get_ebx2_if0_rsi4ebx_rsi5dl
UPX1:000000013FE23C27 adc ecx, ecx
UPX1:000000013FE23C29
UPX1:000000013FE23C29 loc_13FE23C29: ; CODE XREF: loader_stub+92↑j
UPX1:000000013FE23C29 cmp rbp, 0FFFFFFFFFFFFFB00h
UPX1:000000013FE23C30 adc ecx, 2
UPX1:000000013FE23C33 call copy2_rdi_from_rdirbp_ecx ; 从rdi+rbp处开始复制ecx个字节到rdi处
UPX1:000000013FE23C38 jmp loc_13FE23B9D
UPX1:000000013FE23C3D ; ---------------------------------------------------------------------------
UPX1:000000013FE23C3D
UPX1:000000013FE23C3D loc_13FE23C3D: ; CODE XREF: loader_stub+53↑j
UPX1:000000013FE23C3D pop rsi
UPX1:000000013FE23C3E sub rsp, 28h
UPX1:000000013FE23C42 lea rdi, ; rdi指向要恢复的导入表数组oimport
UPX1:000000013FE23C49
UPX1:000000013FE23C49 loc_13FE23C49: ; CODE XREF: loader_stub+E0↓j
UPX1:000000013FE23C49 mov eax, ; dll名称rva,0表示dll结束
UPX1:000000013FE23C4B or eax, eax
UPX1:000000013FE23C4D jz short loc_13FE23CA5 ; 完成原exe的iat的初始化
UPX1:000000013FE23C4F mov ebx, ; iat的rva
UPX1:000000013FE23C52 lea rcx, ; 获得dll名称
UPX1:000000013FE23C5A add rbx, rsi ; iat的va
UPX1:000000013FE23C5D add rdi, 8
UPX1:000000013FE23C61 call large qword ptr cs:13FE2CD38h ; kernel32_LoadLibraryA
UPX1:000000013FE23C67 xchg rax, rbp ; 将dll句柄保存到rbp
UPX1:000000013FE23C69
UPX1:000000013FE23C69 loc_13FE23C69: ; CODE XREF: loader_stub+10D↓j
UPX1:000000013FE23C69 mov al, ; 取之后函数的类型
UPX1:000000013FE23C69 ; 1表示之后是dll函数名称
UPX1:000000013FE23C69 ; 0xff之后函数序号
UPX1:000000013FE23C69 ; 0xfe之后kernel32的函数名称rva
UPX1:000000013FE23C6B inc rdi
UPX1:000000013FE23C6E or al, al
UPX1:000000013FE23C70 jz short loc_13FE23C49 ; 类型为0,表示函数结束
UPX1:000000013FE23C72 jns short loc_13FE23C7E
UPX1:000000013FE23C74 movzx rdx, word ptr ; rdx=函数序号
UPX1:000000013FE23C78 add rdi, 2
UPX1:000000013FE23C7C jmp short loc_13FE23C88 ; rcx=dll句柄
UPX1:000000013FE23C7E ; ---------------------------------------------------------------------------
UPX1:000000013FE23C7E
UPX1:000000013FE23C7E loc_13FE23C7E: ; CODE XREF: loader_stub+E2↑j
UPX1:000000013FE23C7E mov rcx, rdi
UPX1:000000013FE23C81 mov rdx, rdi
UPX1:000000013FE23C84 dec eax
UPX1:000000013FE23C86 repne scasb ; rdx=函数名称
UPX1:000000013FE23C88
UPX1:000000013FE23C88 loc_13FE23C88: ; CODE XREF: loader_stub+EC↑j
UPX1:000000013FE23C88 mov rcx, rbp ; rcx=dll句柄
UPX1:000000013FE23C8B call large qword ptr cs:13FE2CD48h ; kernel32_GetProcAddress
UPX1:000000013FE23C91 or rax, rax ; 函数地址
UPX1:000000013FE23C94 jz short loc_13FE23C9F ; 获取函数地址失败,则程序退出
UPX1:000000013FE23C96 mov , rax ; 保存iat
UPX1:000000013FE23C99 add rbx, 8
UPX1:000000013FE23C9D jmp short loc_13FE23C69 ; 取之后函数的类型
UPX1:000000013FE23C9D ; 1表示之后是dll函数名称
UPX1:000000013FE23C9D ; 0xff之后函数序号
UPX1:000000013FE23C9D ; 0xfe之后kernel32的函数名称rva
UPX1:000000013FE23C9F ; ---------------------------------------------------------------------------
UPX1:000000013FE23C9F
UPX1:000000013FE23C9F loc_13FE23C9F: ; CODE XREF: loader_stub+104↑j
UPX1:000000013FE23C9F jmp large qword ptr cs:13FE2CD40h ; ntdll_RtlExitUserProcess
UPX1:000000013FE23CA5 ; ---------------------------------------------------------------------------
UPX1:000000013FE23CA5
UPX1:000000013FE23CA5 loc_13FE23CA5: ; CODE XREF: loader_stub+BD↑j
UPX1:000000013FE23CA5 add rsp, 28h
UPX1:000000013FE23CA9 add rdi, 4 ; rdi指向处理后的原重定位表orelocs
UPX1:000000013FE23CAD lea rbx, ; rbx是重定位基址,指向upx0-4
UPX1:000000013FE23CB1
UPX1:000000013FE23CB1 loc_13FE23CB1: ; CODE XREF: loader_stub+13F↓j
UPX1:000000013FE23CB1 xor eax, eax
UPX1:000000013FE23CB3 mov al, ; 取1字节的oc
UPX1:000000013FE23CB5 inc rdi
UPX1:000000013FE23CB8 or eax, eax
UPX1:000000013FE23CBA jz short loc_13FE23CE9 ; 0表示处理结束
UPX1:000000013FE23CBC cmp al, 0EFh
UPX1:000000013FE23CBE ja short loc_13FE23CD1 ; oc>=0xF0
UPX1:000000013FE23CC0
UPX1:000000013FE23CC0 loc_13FE23CC0: ; CODE XREF: loader_stub+14F↓j
UPX1:000000013FE23CC0 ; loader_stub+157↓j
UPX1:000000013FE23CC0 add rbx, rax ; rax是相对偏移,rbx为当前需要修复的重定位va
UPX1:000000013FE23CC3 mov rax,
UPX1:000000013FE23CC6 bswap rax
UPX1:000000013FE23CC9 add rax, rsi ; rax转化成va
UPX1:000000013FE23CCC mov , rax
UPX1:000000013FE23CCF jmp short loc_13FE23CB1
UPX1:000000013FE23CD1 ; ---------------------------------------------------------------------------
UPX1:000000013FE23CD1
UPX1:000000013FE23CD1 loc_13FE23CD1: ; CODE XREF: loader_stub+12E↑j
UPX1:000000013FE23CD1 and al, 0Fh ; oc>=0xF0
UPX1:000000013FE23CD3 shl eax, 10h
UPX1:000000013FE23CD6 mov ax, ; 再取2字节
UPX1:000000013FE23CD9 add rdi, 2
UPX1:000000013FE23CDD or eax, eax
UPX1:000000013FE23CDF jnz short loc_13FE23CC0 ; rax是相对偏移,rbx为当前需要修复的重定位va
UPX1:000000013FE23CE1 mov eax, ; 刚取的2字节为0,说明后4字节为真实偏移
UPX1:000000013FE23CE3 add rdi, 4
UPX1:000000013FE23CE7 jmp short loc_13FE23CC0 ; rax是相对偏移,rbx为当前需要修复的重定位va
UPX1:000000013FE23CE9 ; ---------------------------------------------------------------------------
UPX1:000000013FE23CE9
UPX1:000000013FE23CE9 loc_13FE23CE9: ; CODE XREF: loader_stub+12A↑j
UPX1:000000013FE23CE9 mov rbp, large cs:13FE2CD50h ; kernel32_VirtualProtect
UPX1:000000013FE23CF0 lea rdi,
UPX1:000000013FE23CF7 mov ebx, 1000h
UPX1:000000013FE23CFC push rax
UPX1:000000013FE23CFD mov r9, rsp ; 保存原保护方式
UPX1:000000013FE23D00 mov r8d, 4 ; 保护方式 4 PAGE_READWRITE
UPX1:000000013FE23D06 mov rdx, rbx ; 大小
UPX1:000000013FE23D09 mov rcx, rdi ; 起始地址
UPX1:000000013FE23D0C sub rsp, 20h
UPX1:000000013FE23D10 call rbp ; kernel32_VirtualProtect
UPX1:000000013FE23D12 lea rax,
UPX1:000000013FE23D19 and byte ptr , 7Fh ; 去除upx0区段的可写属性
UPX1:000000013FE23D1C and byte ptr , 7Fh ; 去除upx1区段的可写属性
UPX1:000000013FE23D20 lea r9,
UPX1:000000013FE23D25 mov r8, ; 恢复原保护方式
UPX1:000000013FE23D28 mov rdx, rbx
UPX1:000000013FE23D2B mov rcx, rdi
UPX1:000000013FE23D2E call rbp ; kernel32_VirtualProtect
UPX1:000000013FE23D30 add rsp, 28h
UPX1:000000013FE23D34 pop rbp
UPX1:000000013FE23D35 pop rdi
UPX1:000000013FE23D36 pop rsi
UPX1:000000013FE23D37 pop rbx
UPX1:000000013FE23D38 lea rax,
UPX1:000000013FE23D3D
UPX1:000000013FE23D3D loc_13FE23D3D: ; CODE XREF: loader_stub+1B2↓j
UPX1:000000013FE23D3D push 0 ; 平衡栈
UPX1:000000013FE23D3F cmp rsp, rax
UPX1:000000013FE23D42 jnz short loc_13FE23D3D ; 平衡栈
UPX1:000000013FE23D44 sub rsp, 0FFFFFFFFFFFFFF80h
UPX1:000000013FE23D48 jmp oep_real ; 壳代码执行完毕,跳转到原oep继续执行
UPX1:000000013FE23D48 loader_stub endp ; sp-analysis failed
页:
[1]