roger 发表于 2021-2-4 23:38:25

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]
查看完整版本: UPX对pe文件(x64)的加壳过程