;加壳主函数的源码,来自软件加密解密技术内幕
;此代码是在源代码的基础上加上了自己的注释
1 hFile DD ;文件句柄
2 PeImageSize DD ;PE文件装入的内存地址
3 MapOfFile DD ;将文件
4 PeHeadBase DD ;待加壳程序在MapOfFile中的PE头的位置
5 PeImageBase DD ;PeImageBase映像基址
6 FileAlignment DD ;文件对齐值
7 SectionAlignment DD ;区块对齐值
8 MapOfSData DD ;附加数据装入的内存地址
9 ;******************************************************
10 MapOfImpProt DD ;加密输入表装入的内存地址
11 MapOfImpProtUsed DD ;保存加密过的输入表的大小
12 ;******************************************************
13 FirstResADDR DD ;第一个资源的地址
14 ;加壳函数代码分析
15 __asm{
16 Protect PROC
17 LOCAL ReadBuffer :DWORD ;缓冲区
18 LOCAL NumberOfBytesRW :DWORD ;计数
19 ;保存各个寄存器的值
20 pushad
21 ;如果备份文件被选中,创建备份。
22 .if IsCreateBak==1h
23 invoke CreateBakFile,ADDR FileName
24 ;备份是否成功的提示
25 .if eax!=0
26 invoke AddLine,ADDR M_MakeBakRight
27 .else
28 invoke AddLine,ADDR M_MakeBakWrong
29 .endif
30 .endif
31 ;使用CreateFile函数打开待加壳文件
32 invoke CreateFile,ADDR FileName, GENERIC_READ+GENERIC_WRITE, FILE_SHARE_READ+FILE_SHARE_WRITE,0, 3, FILE_ATTRIBUTE_NORMAL,NULL
33 cmp eax,INVALID_HANDLE_VALUE
34 jz OpenFileErr2
35 mov hFile,eax
36 mov ReadBuffer,0
37 ;定位到eflew字段,读出PEHeader给eax,esi,ReadBuffer
38 invoke SetFilePointer, hFile, 3ch, NULL, FILE_BEGIN
39 invoke ReadFile, hFile, ADDR ReadBuffer, 4, ADDR NumberOfBytesRW, NULL
40 mov eax,ReadBuffer
41 mov esi,eax
42 ;**********取文件映象大小,申请内存
43 add eax,50h;PEHeader+50h-->PEsizeofimage
44 invoke SetFilePointer, hFile, eax, NULL, FILE_BEGIN
45 invoke ReadFile, hFile, ADDR PeImageSize, 4, ADDR NumberOfBytesRW, NULL;PeImageSize==sizeofimage
46 ;申请内存MapOfFile读入
47 invoke VirtualAlloc, NULL, PeImageSize, MEM_COMMIT, PAGE_READWRITE
48 test eax,eax
49 jz VirtualAllocErr
50 mov MapOfFile, eax
51 ;**********取PE头大小,读入PE头
52 mov eax,esi
53 add eax,54h ;PEHeader+50h-->SizeOfHeaders
54 invoke SetFilePointer, hFile, eax, NULL, FILE_BEGIN
55 invoke ReadFile, hFile, ADDR ReadBuffer, 4, ADDR NumberOfBytesRW, NULL
56 ;读入PE头到MapOfFile
57 invoke SetFilePointer, hFile, 0, NULL, FILE_BEGIN
58 invoke ReadFile, hFile, MapOfFile, ReadBuffer, ADDR NumberOfBytesRW, NULL
59 ;**************
60 mov eax,MapOfFile
61 add eax,esi
62 mov PeHeadBase,eax ;在MapOfFile中PE头的地址
63 ;**********取PE文件的一些信息
64 mov edi,PeHeadBase
65 assume edi : ptr IMAGE_NT_HEADERS
66 mov eax,dword ptr [edi].OptionalHeader.ImageBase
67 mov PeImageBase,eax ;PeImageBase映像基址
68 ;**********读入各个区块,并对区块资料取整****
69 mov edi,PeHeadBase
70 assume edi : ptr IMAGE_NT_HEADERS
71 mov eax,dword ptr [edi].OptionalHeader.FileAlignment
72 mov FileAlignment,eax
73 .if IsFileAlignment200 == 1
74 mov FileAlignment,200h
75 mov dword ptr [edi].OptionalHeader.FileAlignment,200h
76 .endif
77 mov eax,dword ptr [edi].OptionalHeader.SectionAlignment
78 mov SectionAlignment,eax
79 movzx ecx,word ptr [edi].FileHeader.NumberOfSections
80 movzx esi,word ptr [edi].FileHeader.SizeOfOptionalHeader
81 add esi,edi
82 add esi,18h
83 mov SecTableBase,esi
84 LoadSections: ;到了这里整个PE文件都在内存里了,后面要做的就是对他修改(专业术语加壳)
85 push ecx
86 mov eax,dword ptr [esi+14h] ;区块文件偏移
87 invoke SetFilePointer, hFile, eax, NULL, FILE_BEGIN
88 mov ecx,dword ptr [esi+0ch] ;区块映象偏移
89 add ecx,MapOfFile
90 mov ebx,dword ptr [esi+10h] ;区块文件大小
91 invoke ReadFile, hFile, ecx, ebx, ADDR NumberOfBytesRW, NULL
92 mov ebx,dword ptr [esi+08h] ;区块映象大小
93 invoke GetIntegral,ebx,SectionAlignment
94 mov dword ptr [esi+08h],eax
95 add esi,28h
96 pop ecx
97 loop LoadSections ;循环读入区块
98 invoke AddLine,ADDR M_ReadFileOK
99 invoke GetIntegral,PeImageSize,SectionAlignment;调用了取整函数
100 ;************取整*********
101 ;如果原来的文件PeImageSize为0x1370
102 ;(内存)对齐值为0x1000,那么需要0x2000的大小的文件(内存)
103 ;现在改为0x200,那么取整即至少需要0x1400大小的空间
104 mov PeImageSize,eax
105 mov dword ptr [edi].OptionalHeader.SizeOfImage,eax
106 ;************保留额外数据吗?
107 ;另行申请了一块内存保存附加数据
108 mov eax,IsSaveSData
109 .if eax == 1
110 invoke GetFileSize, hFile, 0 ;得到文件大小
111 sub esi,28h ;最后一个区块
112 sub eax,dword ptr [esi+14h] ;区块文件偏移
113 sub eax,dword ptr [esi+10h] ;区块文件大小
114 .if eax != 0 ;如果等于0即到了文件尾,无附加数据
115 cdq
116 .if edx == 0
117 mov edi,eax
118 invoke VirtualAlloc, NULL, edi, MEM_COMMIT, PAGE_READWRITE
119 mov MapOfSData,eax ;MapOfSData 装载附加数据申请的内存
120 invoke ReadFile, hFile, MapOfSData, edi, ADDR NumberOfBytesRW, NULL
121 mov eax,NumberOfBytesRW
122 mov MapOfSDataUsed,eax ;MapOfSDataUsed附加数据的大小
123 invoke AddLine,ADDR M_SaveSDataOK
124 .else
125 invoke AddLine,ADDR M_HaveNoSData
126 .endif
127 .else
128 invoke AddLine,ADDR M_HaveNoSData
129 .endif
130 .endif
131 invoke CloseHandle,hFile
132 ;***********去处重定位数据*********
133 .if IsNoRelocation == 1
134 invoke ClsRelocation ;函数分析完毕
135 .endif
136 ;***********特殊代码加密***********这里还没看哩!
137 .if IsCodeProt==1
138 invoke VirtualAlloc, NULL, 5000h, MEM_COMMIT, PAGE_READWRITE
139 .if eax==0
140 jmp VirtualAllocErr
141 .endif
142 mov MapOfCodeProt,eax
143 invoke ProtCode
144 add eax,8h
145 mov MapOfCodeProtUsed,eax ;最后加一段空白,以示结束
146 invoke AddLine,ADDR M_CodeProtIsOver
147 .endif
148 ;************输入表加密***********
149 ;关于输入表加密的目的:1,破坏原输入表,换个形式存储。
150 ;2HookAPI,不写入函数(MSGBOX)真正的地址,而是跳转到我们设计好的外壳程序中,然后在我们的程序中调到真正函数地址(MSGBOX)
151 .if IsProtImpTable==1
152 invoke VirtualAlloc, NULL, 0a000h, MEM_COMMIT, PAGE_READWRITE
153 .if eax==0
154 jmp VirtualAllocErr
155 .endif
156 mov MapOfImpProt,eax ;MapOfImpProt 变量是输入表变换用的BUFFER
157 invoke MoveImpTable ;函数分析完毕
158 mov MapOfImpProtUsed,eax
159 invoke ClsImpTable ;
160 invoke AddLine,ADDR M_ImpTableProtIsOver
161 .endif
162 ;***********压缩资源******************
163 .if IsPackRes ==1
164 invoke FindFirstResADDR
165 mov FirstResADDR,eax ;最前面的资源的存放偏移
166 invoke VirtualAlloc, NULL, 5000h, MEM_COMMIT, PAGE_READWRITE
167 .if eax==0
168 jmp VirtualAllocErr
169 .endif
170 mov MapOfPackRes,eax
171 mov MapOfPackResUsed,0h
172 invoke MoveRes,3h,MapOfPackRes,MapOfPackResUsed
173 mov MapOfPackResUsed,eax
174 invoke MoveRes,0eh,MapOfPackRes,MapOfPackResUsed
175 mov MapOfPackResUsed,eax
176 invoke MoveRes,10h,MapOfPackRes,MapOfPackResUsed
177 mov MapOfPackResUsed,eax
178 invoke AddLine,ADDR M_PackResIsOver
179 .endif
180 ;***********合并区段**********
181 .if IsMergeSection ==1
182 invoke MergeSection
183 invoke AddLine,ADDR M_MergeSectionIsOver
184 .endif
185 ;***********压缩***************
186 invoke VirtualAlloc, NULL, 100000h, MEM_COMMIT, PAGE_READWRITE
187 .if eax==0
188 jmp VirtualAllocErr
189 .endif
190 mov lpPackBuffer,eax
191 invoke CreateFile,ADDR FileName, GENERIC_READ+GENERIC_WRITE, FILE_SHARE_READ+FILE_SHARE_WRITE,0,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL
192 mov hFile,eax
193 ;因为还要压缩写入外壳部分和重写文件头,所以上面两个函数不放在PackFile里
194 invoke PackFile
195 ;*************处理外壳并写入******
196 invoke VirtualAlloc, NULL, 20000h, MEM_COMMIT, PAGE_READWRITE
197 .if eax==0
198 jmp VirtualAllocErr
199 .endif
200 mov MapOfShell,eax
201 invoke DisposeShell
202 mov MapOfShellUsed,eax
203 push eax
204 mov ebx,esp
205 invoke WriteFile, hFile,MapOfShell ,MapOfShellUsed,ebx, NULL
206 add esp,4h
207 ;*******清空段名吗?*****************
208 .if IsClsSecName == 1
209 invoke ClsSectionName
210 .endif
211 ;***********重写文件头**************
212 invoke SetFilePointer, hFile, 0h, NULL, FILE_BEGIN
213 mov esi,PeHeadBase
214 assume esi : ptr IMAGE_NT_HEADERS
215 mov ebx,PeHeadSize
216 invoke WriteFile, hFile,MapOfFile ,ebx,ADDR NumberOfBytesRW, NULL
217 ;***********写入额外代码************
218 invoke SetFilePointer, hFile, 0h, NULL, FILE_END
219 invoke WriteFile, hFile,MapOfSData,MapOfSDataUsed,ADDR NumberOfBytesRW, NULL
220 ;***********加密完成,清理***********
221 invoke CloseHandle,hFile
222 invoke VirtualFree, lpPackBuffer, 0, MEM_RELEASE ;释放压缩缓冲
223 invoke VirtualFree, MapOfFile, 0, MEM_RELEASE
224 .if MapOfCodeProt != 0
225 invoke VirtualFree, MapOfCodeProt, 0, MEM_RELEASE
226 .endif
227 .if MapOfImpProt != 0
228 invoke VirtualFree, MapOfImpProt, 0, MEM_RELEASE
229 .endif
230 .if MapOfPackRes != 0
231 invoke VirtualFree, MapOfPackRes, 0, MEM_RELEASE
232 .endif
233 .if MapOfSData != 0
234 invoke VirtualFree, MapOfSData, 0, MEM_RELEASE
235 .endif
236 lea edi,hFile
237 mov ecx,FileDataEnd-hFile
238 xor eax,eax
239 rep stosb
240 popad
241 ret
242 OpenFileErr2:
243 invoke AddLine,ADDR M_FileOpenErr
244 popad
245 xor eax,eax
246 ret
247 VirtualAllocErr:
248 invoke AddLine,ADDR M_VirtualAllocErr
249 popad
250 xor eax,eax
251 ret
252 ProtTheFi
253 };