Possible Virus Attacks Against Integrity Programs

and How to Prevent Them


Vesselin Bontchev, research associate
Virus Test Center, University of Hamburg
Vogt–Koelln–Strasse 30, 2000 Hamburg 54, Germany
bontchev@fbihh.informatik.uni-hamburg.de

Abstract: With the advent of the polymorphic viruses it is becoming obvious that the virus–specific scanners have exhausted themselves. Currently one of the most powerful methods to detect viruses is the so–called integrity programs. They will certainly be used more frequently in the future. Yet, they are also not a universal anti–virus protection tool. In the current paper we shall try to show the different ways in which viruses could attack integrity checking programs. When appropriate, we shall also demonstrate what can be done against these attacks.

Download this paper as an ASCII text file

Table of Contents

1. Introduction

1.1. Scanners

1.2. Monitors

1.3. Integrity Checking Programs

2. Possible Virus Attacks Against the Integrity Checking Programs

2.1. Stealth Viruses and Fast Infectors

2.2. Companion Viruses

2.2.1. Regular Companions

2.2.2. PATH Companions

2.2.3. Alias Companions

2.3. Infection of Unusual Objects

2.4. The DOS File Fragmentation Attack

2.5. Deleting the Database of Checksums

2.6. Diskette–Only Infectors

2.7. Infecting Only Modifiable Objects

2.8. Slow Viruses

2.9. A Combined Attack

3. Conclusion

4. References


1. Introduction

There are three main kinds of anti–virus programs [McAfee]. Essentially these are scanners, monitors and integrity checkers.

Back to the Table of Contents

1.1. Scanners

Scanners are programs that scan the executable objects (files and boot sectors) for the presence of code sequences that are present in the known viruses. Currently, these are the most popular and the most widely used kind of anti–virus programs. There are some variations of the scanning technique, like virus removal programs (programs that can "repair" the infected objects by removing the virus from them), resident scanners (programs that are constantly active in memory and scan every file before it is executed), virus identifiers (programs that can recognize the particular virus variant exactly by keeping some kind of map of the non–modifiable parts of the virus body and their checksums), heuristic analyzers (programs that scan for particular sequences of instructions that perform some virus–like functions), and so on.

The reason why this kind of anti–virus program is so widely used nowadays is because they are relatively easy to maintain. This is especially true for the programs which just report the infection by a known virus variant, without attempting exact identification or removal. They consist mainly of a searching engine and a database of code sequences (often called virus signatures or scan strings) that are present in the known viruses. When a new virus appears, the author of the scanner needs just to pick a good signature (which is present in each copy of the virus and in the same time is unlikely to be found in any legitimate program) and to add it to the scanner's database. Often this can be done very quickly and without a detailed disassembly and understanding of the particular virus.

Furthermore, scanning of any new software is the only way to detect viruses before they have the chance to get executed. Having in mind that in most operating systems for personal computers the program being executed has the full rights to access and/or modify any memory location (including the operating system itself), it is preferable that the infected programs do not get any chance to be executed.

Finally, even if the computer is protected by another (not virus–specific) defense, a scanner will still be needed. The reason is that when the non virus–specific defense detects a virus–like behaviour, the user usually wants to identify the particular virus, which is attacking the system—for instance, to figure out the possible side–effects or intentional damage, or at least to identify all infected objects.

Unfortunately, the scanners have several very serious drawbacks.

The main one is that they must be constantly kept up–to–date. Since they can detect only the known viruses, any new virus presents a danger, because it can bypass a scanner–only based protection. In fact, an old scanner is worse than no protection at all—since it provides a false sense of security.

Simultaneously, it is very difficult to keep a scanner up–to–date. In order to produce an update, which can detect a particular new virus, the author of the scanner must obtain a sample of the virus, disassemble it, understand it, pick a good scan string that is characteristic for this virus and is unlikely to cause a false positive alarm, incorporate this string in the scanner, and ship the update to the users. This can take quite a lot of time. And new viruses are created every day—with a current rate of up to 100 per month. Very few anti–virus producers are able to keep up–to–date with such a production rate. One can even argue that the scanners are somehow responsible for the existence of so many virus variants. Indeed, since it is so easy to modify a virus in order to avoid a particular scanner, lots of "wannabe" virus writers are doing it.

However, the fact that the scanners are obsolete as a single line of defense against the computer viruses, became obvious only with the appearance of the polymorphic viruses. These are viruses, which use a variable encryption scheme to encode their body and which even modify the small decryption routine, so that the virus looks differently in each infected file. It is impossible to pick a simple sequence of bytes that will be present in all infected files and use it as a scan string. Such sequence simply does not exist. Some polymorphic viruses can be detected using a wildcard scan string, but more and more viruses appear today, which cannot be detected even if the scan string is allowed to contain wildcard bytes...

The only possible way to detect such viruses is to understand their mutation engine in detail. Then one has to construct an algorithmic "scanning engine" specific to the particular virus. However, this is a very time–consuming and effort–expensive task, so many of the existing scanners have problems with the polymorphic viruses. And we are going to see more such viruses in the future. The Bulgarian virus writer known under the handle Dark Avenger has even released a "mutating engine"—a tool for building extremely polymorphic viruses... Very few scanners are able to detect the viruses, which are using it, with 100% reliability.

One last drawback of the scanners is that scanning for lots of viruses can be very time–consuming. The number of currently existing viruses is about 1,600 and is expected to reach 3,000 at the end of 1992. Indeed, some scanners use clever scanning methods like fixed–point scanning, top–and–tail scanning, hashing and so on. The detailed description of these methods is outside the scope of this paper, but as has been proven in [Cohen90], scanning is not cost–effective in the long run, despite the scanning method used.

Back to the Table of Contents

1.2. Monitors

The monitoring programs (sometimes called behaviour blockers) are memory resident programs, which constantly monitor some functions of the operating system. Those are the functions that are considered to be dangerous and indicative for virus–like behaviour. Such functions include modifying an executable file, direct access of the disk bypassing the operating system, and so on. When a program tries to use such a function, the monitoring program intercepts it and either denies it completely or asks the user for confirmation.

Unlike the scanners, the monitors are not virus–specific and therefore need not to be constantly updated. Unfortunately, they have other very serious drawbacks—drawbacks that make them even weaker than the scanners as an anti–virus defense and almost unusable nowadays.

The most serious drawback of the monitors is that they can be easily bypassed by the so–called tunneling viruses. The reason for this is the total lack of memory protection in most operating systems for personal computers. Any program that is being executed (including the virus) has full access to read and/or modify any area of the computer's memory—including the parts belonging to the operating system. Therefore, any monitoring program can be disabled because the virus could simply patch it in memory. There are other clever techniques as interrupt tracing, DOS scanning, and so on, which allow the viruses to find the original handlers of any operating system function. Afterwards, this function can be called directly, thus bypassing any monitoring programs, which have attempted to intercept it.

Another drawback of the monitoring programs is that they try to detect a virus by its behaviour. This is essentially impossible in the general case, as proven in [Cohen84]. Therefore, they cause many false alarms—since the functions that are expected to be used by the computer viruses usually have pretty legitimate use by normal programs. And if the user gets used to the false alarms, s/he will be likely to oversee a real one.

The monitoring programs are also completely useless against the slow viruses, described later in this paper.

Back to the Table of Contents

1.3. Integrity Checking Programs

According to Dr. Fred Cohen's definition [Cohen84], a computer virus is a program that can 'infect' other programs by modifying them to include a possibly evolved copy of itself. Therefore, in order to be a virus, a program must be able to infect. And, in order to infect, the program must cause modifications to the programs that are infected. Therefore, a program, which can detect that the other executable objects have been modified, will be able to detect the infection. Such programs are usually called integrity checkers.

The integrity checkers compute some kind of checksum of the executable code in a computer system and store it in a database. The checksums are re–computed periodically and compared with the stored originals. Several authors point out that in order to avoid forging attempts from the part of the virus, the checksums must be cryptographically strong. This can be achieved by using some kind of trap–door one–way function, which is algorithmically difficult to be inverted. Such functions include DES, MD4, MD5, and so on. But, as has been shown by [Radai], this is not mandatory. A simple CRC is sufficient, if implemented correctly.

There are several kinds of integrity checkers. The most widely used ones are the off–line integrity checkers, which are run to check the integrity of all the executable code on a computer system. Another kind are the integrity modules, which can be attached (with the help of a special program) to the executable files, so that when started the latter will check their own integrity. Unfortunately, this is not a good idea, since not all executable objects can be "immunized" this way. Additionally, the "immunization" itself can be easily bypassed by stealth viruses, as described later in this paper. The third kind of integrity software are the integrity shells. They are resident programs, similar to the resident scanners, that check the integrity of an object only at the moment when this object is about to be executed. These are the least widespread anti–virus programs nowadays, but the specialists predict them a bright future [Cohen90].

The integrity checking programs are not virus–specific and therefore do not need constant updating like the scanners. They do not try to block virus replication attempts like the monitoring programs and therefore cannot be bypassed by the tunneling viruses. In fact, as demonstrated by [Cohen90], they are currently the most cost–effective and sound line of defense against computer viruses.

They also have some drawbacks. For instance, they cannot prevent an infection—they are able only to detect and report it after the fact. Second, they must be installed on a virus–free system, otherwise they will compute and store the checksums of already infected objects. Therefore, they must be used in a combination with a scanner at least before installation. This is needed, in order to ensure that the system they are being installed on is virus–free. Third, they are prone to false positive alarms. Since they detect changes, not viruses, any change in the programs (like updating the software with a new version), is likely to trigger the alarm. Sometimes this can be avoided or at least reduced by using some intelligent heuristics and educating the users. Fourth, while the integrity checkers are able to detect the virus spread and identify the newly infected objects, they usually cannot determine the initially infected object, i.e., the source of the infection.

Despite the drawbacks mentioned, the integrity checking programs are the currently most powerful line of defense against computer viruses and are likely to be used more widely in the future. Therefore, we should expect that new viruses will appear, which will target the integrity programs in the same way as the polymorphic viruses are targeting the scanners and the tunneling viruses are targeting the monitors. Let's see what kinds of attacks are possible against the integrity checking programs and how these programs can be improved to avoid them.

Back to the Table of Contents

2. Possible Virus Attacks Against the Integrity Checking Programs

Back to the Table of Contents

2.1. Stealth Viruses and Fast Infectors

The first generic attack against both the scanners and the integrity checkers came with the appearance of the stealth viruses. When such a virus is active in memory, it intercepts the access requests to the infected objects. It then modifies their results in such a way, that these objects look as if they are not infected.

The first stealth virus was Brain—a boot sector infector. Writing a stealth file infector is much more difficult, since a lot more things have to be considered by the virus writer. However, such viruses are perfectly possible and several of them already exist. The first fully stealth file infector was the Bulgarian virus Number of the Beast. Currently there are also semi–stealth viruses—viruses which only hide the increase of the file size after infection. However, they are not of particular interest, since they cannot defeat most intelligent integrity checking programs.

If a fully stealth virus is active in the computer memory during the integrity check, all infected objects will look as non–infected, or in fact not modified. Therefore, the integrity checking program will not report anything unusual.

Also, if the stealth virus is also a fast infector (a virus, which infects files not only when they are executed, but also when they are accessed for whatever reason), the process of computing the checksum of every file will cause its infection. The reason for this is that the files must be opened and read (therefore—accessed) in order their checksum to be computed. This will provide the virus (if it is present in the memory and active) with the possibility to infect them. And all currently known stealth viruses are fast infectors as well.

The only remedy to this is to ensure that no virus is active in the computer memory during the integrity check. There is only one 100% foolproof way to do this—to cold boot the computer that is about to be checked from a non–infected write–protected system diskette. This way we can make both the stealth and the fast infecting viruses obsolete—since they will not be active in the memory during the check and will have no way to play their subverting tricks.

Unfortunately, the usage described above of an anti–virus program is often considered inconvenient by most users. In fact, most users never use the program this way. That is why, most integrity checking programs usually have different levels of safety and only the most secure one requires the user to boot from a system diskette. The intelligent integrity checkers can even keep track of how often the most secure mode has been used and to remind the user if s/he does not use it often enough.

There is yet another possibility, which gets more and more widely used lately. It consists of using the so–called anti–stealth techniques. These techniques are, in fact, very similar to the tricks that the tunneling viruses use to bypass the monitoring programs. The integrity checkers that use anti–stealth techniques try to bypass the stealth viruses much in the same way as the tunneling viruses try to bypass the monitors. Such techniques are often very useful, but they must not be abused. It is important to emphasize that they are not fool–proof, due to the complete lack of memory protection in the operating systems for personal computers. Usually it is possible to circumvent them by using just a combination of the known stealth techniques.

If a program wants to bypass the stealth viruses reliably, it must access the disk sector by sector, using direct calls to the ROM BIOS (not interrupts!). It must bypass the whole operating system and interpret the disk structure itself. Even then, great care has to be taken to avoid some pitfalls that can be used by a clever stealth virus. However, if the program does all this, it will become very incompatible—with any kind of disks accessed through an installable device driver. At first sight this may not look like a great restriction, but such disks include SCSI disks, hardcards, CD–ROMs, networked drives, encrypted partitions (e.g., with the program DiskReet from the Norton Utilities package), compressed disks (e.g., with Stacker, SuperStor, DoubleDisk), special large partitions (e.g., created by Disk Manager), SUBSTed and JOINed disks, and so on. A virus writer can safely ignore this—his creation will spread widely enough even if it does not infect such disks. However, an anti–virus program can never permit itself to be so widely incompatible, or it simply will not be used. Therefore, the integrity checking programs that use anti–stealth techniques must turn the tricks off at least in the cases mentioned above.

Therefore, the users should be aware that any claims of the sort of "our program is able to bypass any stealth virus" are nothing more than marketing tricks. They should be taken with a pinch of salt.

Remember: the only 100% foolproof anti–stealth technique is to cold booting the computer from a non–infected write–protected system diskette, to ensure that no virus is present in memory.

A third way to avoid the stealth viruses is described in [Cohen91]. It consists of taking a snapshot of a clean state of the system (including the boot sectors, the operating system, the device drivers, the command interpreter, the startup files, and even the memory structure and the contents of the registers of the CPU). Each time the system is rebooted, it is fist restored to that known clean state. This way, we can make sure that no virus is active in memory at that time. This method is very useful and convenient especially against boot sector viruses. It is significantly less convenient if it is implemented completely—especially in environments when the system startup configuration is changed relatively often.

Back to the Table of Contents

2.2. Companion Viruses

The integrity checking programs detect modifications of the executable files. Therefore, to avoid detection, the viruses could try not to modify the files themselves. For instance, they could try to change their execution path instead. The particular implementation is operating system dependent; in our examples we shall assume mainly MS–DOS.

When the user enters the name of a file to be executed from the command line, the command interpreter first looks for a file with the same name as the one entered by the user and a .COM extension. Only if such file is not found, the command interpreter tries the .EXE and .BAT extensions (in this order) and if none is found, the same search (in the same order) is performed in every directory listed in the PATH variable. Only if no file that has any of these three extensions is found, the command interpreter outputs the well–known "Bad command or filename" message.

Back to the Table of Contents

2.2.1. Regular Companions

The search procedure described above can be used by a virus. It can locate a file with an .EXE extension and put the virus body in the same directory and with the same file name as the file being "infected" but with a .COM extension. This way the virus will make sure that the next time the user enters the name of the main file from the command line, the virus will be executed instead. It can then perform its task (e.g., "infect" in this way other file(s)) and pass control to the main file by executing it directly (the Exec function call does not perform any PATH or file extension search—it is done only by the command interpreter).

Such viruses already exist. They are called regular companion viruses or more simply "companions". The first one was the relatively unknown Bulgarian virus, called TP_Worm. Nowadays several other such viruses exist. Some of them are memory resident, and some even employ a limited range of stealth tricks.

Such viruses are usually not considered particularly dangerous. The reason is that they tend to spread only inside a particular computer system. Since people do not often execute files from floppy disks or include the floppy disk drives in their paths, these viruses have almost no chance to spread between computers.

Unfortunately, relying on this might be dangerous. It is perfectly possible to design and implement a well–spreading companion virus. Such a virus will be memory resident. It will place its copies and mark them as hidden. (The files with the Hidden attribute set still can be executed—unlike the files with the System attribute set). Then, it could intercept the FindFirst and FindNext functions of the operating system and "hide" the presence of this file, even if a file manager that can show the hidden files is used. The virus could even be a fast infector—it could infect (i.e., create its copy in a hidden COM file) not only when EXE files are executed, but also when they are copied. This way it will have more chances to spread to floppy disks and from them—to other computers.

The companion viruses are a particularly dangerous form of virus attack in some environments, like Novell NetWare. Under Novell NetWare it is possible to mark some executable files as ExecuteOnly. This will make them unreachable for any kind of access (except execution) by anyone, including the supervisor. Once set, this attribute cannot be reset any more. The only thing that can be done is to delete the file—and even this can be done only by the supervisor. If the directory that contains .EXE files protected in this way has access rights, which allow file creation and/or renaming, a companion virus could spoof the protected file by creating in the same directory a file with the same name and a .COM extension. If the effective access rights of the newly created files permit that, the virus could even set its attributes to ExecuteOnly, thus preventing even the supervisor from detecting the attack. This kind of attack has been first described in [Cohen92].

In the attack described above, it is obvious that not only the ExecuteOnly attribute is unable to stop the virus spread, but it also effectively prevents the supervisor from performing regular backups and integrity checks, and therefore noticing the attack. And, from a MS–DOS workstation, this attribute does not effectively prevent read access to the files, protected by it. Indeed, the attacker could use a LoadOverlay function call, in order to get a copy of the file in the memory of the local workstation. Once the executable image is there, it could be stored in a local file, examined, etc. The EXE files present some difficulties to this approach, since the LoadOveraly function will perform the necessary relocation and the image of the file in memory will not be an exact copy of the file. However, this could be easily bypassed, by loading the file twice at different memory segments and using the difference between the two loaded images to construct an EXE header and an equivalent set of relocation items.

With the appearance of more modern command interpreters, other kinds of companion spoofing became possible. Even with COMMAND.COM it is possible to spoof a BAT file by a COM or EXE companion much in the same way as an EXE file can be spoofed by a COM companion. With 4DOS used as command interpreter a new kind of executable extension is introduced—the BTM files, which are searched for after the EXE files but before the BAT files in the execution path. Therefore, under 4DOS a BAT file can be spoofed by a BTM, an EXE, or a COM companion. 4DOS also allows the user to define new executable extensions by setting special environment variables. All files with these extensions can be spoofed by either BAT, or BTM, or EXE, or COM companions. A clever virus could randomly generate companions of the possible extension range, in order to reduce the possibility of being detected.

What can be done against this kind of attack? It is relatively trivial to make the integrity checking programs aware of it. They just need to inspect every directory for files with the same name but with different executable extensions and to alarm the user if such files are found. Some care must be taken to handle the new extensions as with the 4DOS example above. For this purpose the integrity checkers must provide the user the possibility to define all the executable extensions that have to be checked. Also, s/he must have the possibility to indicate the search order of these extensions (e.g., COM -> EXE -> BTM -> BAT -> ZIP).

Back to the Table of Contents

2.2.2. PATH Companions

Instead of putting its body in a file in the same directory, but with an extension that is searched earlier than the original one, a virus could simply put its body in a file with any executable extension, but in a directory that comes earlier in the PATH variable than the directory of the original file. This will have the same effect—when the user types the name of the file, the virus will be executed first. Such viruses are called PATH companions.

This trick is less operating system dependent, since relatively many operating systems with hierarchical file structure have the concept of the PATH variable, while the multiple executable extensions exist mainly in a few weird OSes like VMS or MS–DOS. Under Unix, of instance, the PATH trick is quite popular, but mainly for creating trojan horses, not viruses.

Again, this attack presents a significantly more considerable danger in a Novell Netware environment. A PATH companion virus could infect all executable files in all directories—regardless how well they are protected. It is sufficient that at least one writeable directory exists—e.g., the user's home directory. The virus could insert the name of the writeable directory at the beginning of the PATH variable and create copies of its body in it with names, designed to spoof the executable files in the protected directories. Even if no writeable directory on the server exists, the virus could use a directory on the local workstation instead. Indeed, the infection will exist only from the point of view of the user being attacked—it will not be able to spread between users. Nevertheless, the attack provides enough dangerous possibilities.

What can be done to prevent such viruses? Well, basically the same that is done to prevent the regular companions. However, this time the whole file system must be searched for files with the same name and different executable extensions. This often uses too much memory and is too time–expensive, especially if the file system includes all networked drives.

An intelligent shortcut is to store the contents of the PATH variable used by the user and check only the directories in it. An even more intelligent approach consists of parsing the contents of the user's AUTOEXEC.BAT file and fetching the contents of the PATH variable from there, optionally allowing the user to change it (e.g., to add more directories to be checked). This approach is even more useful when the user boots from a diskette and the normal contents of the PATH variable is not available. And, as we tried to emphasize in the previous section, this is the only safe way to use an integrity checking program.

Still, this shortcut does not work against a PATH companion, which modifies the PATH variable in memory, in order to make it include the special directory, which contains the virus body. Again, this modification cannot be prevented, because of the lack of memory protection in the operating system. It could, however, be detected by some kind of resident integrity checking program (i.e., an integrity shell).

Back to the Table of Contents

2.2.3. Alias Companions

The latest additions to the MS–DOS operating system, namely 4DOS and the DOSKEY program, allow the user to define command–line macros, called aliases. The commands defined in them will be executed before any file with executable extension. This, of course, opens a gaping hole for alias–based viruses—viruses that install an alias to spoof a particular executable file (regardless of its extension). Fortunately, such viruses, while possible in theory, do not represent a significant danger. They would be very much system–dependent and the alias technique is not widely used and standardized. However, the approach should be considered, since a virus could use it as an alternative way of spreading (besides a more "conventional" way of infection).

Since the alias technique is not standardized, it is less easy to look for and prevent this kind of attack. A 4DOS–based approach could be to parse the AUTOEXEC.BAT file for the ALIAS command and also check all files that contain aliases (they are used by this command). A DOSKEY–aware approach is more difficult.

Back to the Table of Contents

2.3. Infection of Unusual Objects

The alias companions are a particular case of a more general approach—to infect unusual objects, that are unlikely to be checked by an integrity program. We shall try to list some possibilities.

According to the von Neumann's principle, there is no strict difference between executable code and data. One man's code is another man's data and vice versa. The source code of a program is considered to be a program by the humans, but is treated as data by the editors and the compilers. Therefore it can be infected by a source–code virus. At first glance it seems rather unlikely that such a virus will remain undetected. Still, finding the offending code in a 10,000–line C program could be quite troublesome. Especially if the code is designed in the style of the "Obfuscated C Contest". A very good example of source code tampering that leaves no traces is described in [Thompson].

Some more examples include:

All these attacks are not dangerous by themselves, since any virus that depends only on them is not likely to spread very far. However, they can be used in a combination with the conventional methods. Therefore, they should be detected, otherwise some copies of the virus risk to survive the disinfection and to cause a second epidemy. This could be quite expensive...

What can be done against these attacks? Most of them are only of theoretical interest nowadays, so it is useless to force regular integrity checking of everything that could be infected in theory. However, the integrity programs must be designed to be flexible enough and to provide the user the possibility to define what files have to be checked (and how often) him/herself. Also, there should be a possibility to check the integrity of all files present on the system—including those that are supposed to contain only non–executable (and non–interpretable) data. The latter is a good practice not only against viruses but also against other kinds of integrity corruption.

Back to the Table of Contents

2.4. The DOS File Fragmentation Attack

This kind of attack has been described in [Kabay]. It is specific to MS–DOS.

The operating system is contained in two files (IO.SYS and MSDOS.SYS or IBMBIO.COM and IBMSYS.COM), which are loaded during the bootstrap process. However, at boot time there is no operating system to interpret the contents of the disk as a file system. Therefore, the first of these files is loaded in memory not as a file, but as consecutive sectors. In the same time, the integrity checking programs usually treat the operating system files as regular files and check them in the normal way. A virus could use this discrepancy to infect the system and remain undetected by the integrity checking software.

The virus could place its body over the first cluster occupied by the first DOS file. Then it should allocate a new cluster (from the free disk space), store the original contents of the first cluster there, and fix the FAT chain in such a way, that the newly allocated cluster is re–linked at the beginning of the file. The old first cluster (which now contains the virus body) is removed from the chain of clusters allocated for this file and is marked somehow as used—for instance by marking it as bad, or by "hiding" it using the stealth approach.

A program which now computes the checksum of the file by considering it to be a normal file will be fooled to believe that the file has not been changed—since the logical structure and the contents of the clusters allocated to this file has not been changed indeed. However, the location of the file on the disk will be different and this will cause the virus body to be loaded at boot time. It could then install itself in memory, intercept some controls, then load the original first cluster and transfer control to it.

To avoid this kind of attack, the integrity checking software must be aware of it and treat the two hidden DOS files in a special way. It should not only check their contents as files, but also their position as sectors on the hard disk. This is relatively trivial to be achieved, but it is amazing how few producers of integrity checking software know about this kind of attack at all.

Back to the Table of Contents

2.5. Deleting the Database of Checksums

A very trivial, but surprisingly successful attack a virus could perform consists of just locating the database, where the integrity checking program stores the checksums of the executable objects and simply deleting it. When the file containing the database suddenly disappears, many integrity checkers will consider that they are going to be installed for the first time on this system. They will then begin duly to checksum all executable objects again and to rebuild the database of checksums. Some of the existing integrity checkers are doing this even without requesting confirmation from the user. Unfortunately, this means that the new database will contain checksums of the already infected objects...

Such viruses already exist. One of them (Peach) targets the database of checksums, created by Central Point Anti–Virus. Another virus (Tequila) simply removes the 10–byte checksum, attached to the executable files by McAfee Associates' VirusScan (it attaches such checksums to the executable files when it is run with the /AV option). Yet another virus (Groove), targets a whole set of integrity programs. It looks for the files with the default names of the database of checksums that these programs create, and simply deletes them.

Protection against this kind of attack is relatively simple. The integrity checking programs must not automatically assume that they should run in installation mode, if no database of checksums is available. They must be installed with a separate installation program instead. Also, they must provide a flexible way to the user to select the name of the file, where the database of checksums is to be stored. They also must allow the user freely to rename the program that performs the integrity check, to prevent the virus from doing some cheap tricks, like examining the two startup files (CONFIG.SYS and AUTOEXEC.BAT), in order to find the exact name of the file with the checksums.

On the other side, the users must know that the only safe place for the database that contains the checksums of the executable objects is off–line, on a write–protected floppy, out of the reach of any virus.

Back to the Table of Contents

2.6. Diskette–Only Infectors

Usually the integrity checking programs are used to watch the integrity of the hard disks only. They do not try to compute checksums of the executable objects on the floppy disks, because the floppy disks are often modified, exchanged between computer systems, and so on.

Therefore, a virus that infects only floppy disks will not be detected by such an integrity program. And indeed, most of the currently available integrity checking products are unable to detect such old and well–known viruses like Brain and VirDem [Solomon].

Some people claim that a diskette–only infector is not a very viable and dangerous virus. However, the Brain virus has proved that the former is not true. This diskette–only infector was so widespread, that we are still unable to eradicate it completely. As to the latter, consider a virus, which infects only floppy disks, but slightly corrupts data files on the hard disks. The corruption is not likely to be discovered soon, even in the hard disk is protected by an integrity checking system—because the integrity checking programs usually do not check the data files (it will take a lot of time to check all data files, and most of them are often modified anyway). Since the file corruption occurs slowly, it is likely that the already corrupted files will be transferred in the backups, thus making the restoration of the system impossible. A virus with such a destructive payload already exists (the Nomenklatura virus). One only needs to combine its payload with a diskette–only infector, like Brain.

Back to the Table of Contents

2.7. Infecting Only Modifiable Objects

There is a class of executable files, which cause a lot of troubles to the integrity checking software. Those are the programs that modify their image in the files—for instance, to store some configuration data. Regardless that designing such programs is widely considered as a bad practice, self–modifiable programs exist, are widely used, and are likely to be continued to be created in the future. Such programs include e.g., Borland's SideKick and Turbo PASCAL, McAfee's VirusScan, the program SETVER, which comes with DOS 5.0, and others.

Since these programs often modify themselves, they will trigger the integrity checking programs, because the latter are designed to detect modifications. To avoid such false positives, most of the integrity checking packages allow the user to create a set of exceptions—a list of executable objects that are to be excluded from the integrity control.

However, a virus could use this security hole, look for the most popular self–modifying programs (by searching the whole file system, or just by examining the two startup files), and to infect only them. If such a self–modifying program is executed during the startup, this will provide the virus with the excellent possibility to spread, yet it will remain undetected by the integrity checking software. Even if the regular integrity check detects the modification, the user is likely not to pay attention to the alarm, since it is well known that the program, which has triggered the alarm is self–modifying.

What can be done against this kind of attack? Well, improving the integrity checking software cannot help very much. The best solution is not to use any self–modifying programs at all. If the users firmly decide to stop using this kind of software (just like they decided to stop using programs that apply some kind of copy protection scheme), maybe the software producers will turn to a better programming practice. Self–modification of the executable objects can and should be avoided. This will close a security hole, which can be exploited by computer viruses.

Back to the Table of Contents

2.8. Slow Viruses

The slow viruses are a natural extension of the idea to infect only floppy disks, or only objects, which are known to often modify themselves.

These viruses represent probably the greatest danger to the integrity checking software. We call them "slow" viruses as opposed to the fast infectors, because they are rather selective regarding the objects they decide to infect. Their spread lacks the spectacular speed of the superfast infectors like Dir II, but they can remain undiscovered for much longer time and spread wider in the long run.

The slow viruses use one intrinsic flaw of the integrity checking software. The integrity checking programs do not detect viruses—they detect modifications. Whether the modifications are caused by a virus or not is left to the user to decide. The slow viruses choose to infect programs only in these cases when the latter are created or modified by the user. This usually occurs when a file is copied or re–compiled. If an integrity checker is run after a slow virus has infected its victim, the user will get a report that a new executable file has appeared or that an old one has been modified. However, this is unlikely to cause any suspicions, since the new (or modified) file is copied there (or recompiled) by the user him/herself.

Such viruses already exist. The first of them was the Bulgarian virus Darth Vader. This virus infects only COM files, only when they are written to, and only when they contain a large enough block of zeroes to hold the virus body. The virus uses the fact that during the execution of the COPY command, MS–DOS copies the COM files in one pass—since they are known not to exceed 64 Kb. Therefore, the virus is certain to find the whole file in memory by intercepting the Write request and looking where the address of the buffer to be written points to. It then tries to locate a sufficiently large block of zeroes in this buffer, copies itself there and adjusts the first three bytes of the buffer to contain an instruction that will transfer control to the virus body. This is all; the virus even does not bother to write to the infected files itself. It knows that DOS will do it itself when executing the COPY command.

Surprisingly, the virus has not been created as an attack against the integrity checking software (although it evades all integrity checking programs very successfully). The initial idea of its author was to bypass the monitoring programs. His reasoning was that since they are monitoring the modification of the executable files, a safe way to evade them will be to infect only when the user requests modification of these files (via the WriteHandle request) him/herself. And indeed, the virus successfully evades these programs. It can even "bypass" the diskette write protection tabs—since when the user copies a COM file to a diskette the write protection tab is removed. The virus achieves this without even having a critical error handler—it just does not need one.

Another virus of this kind is the Bulgarian virus Compiler. This one has been designed probably against the programmers, since it infects mainly when a program is re–compiled—when the size of the file (the virus infects only EXE files) is modified. However, in most environments this does not occur very often, so the virus is unlikely to spread very widely. Besides, it is a multi–partite virus, which infects the master boot record and at least this will be detected by the integrity checking software—if it is installed before the virus (i.e., on a clean system).

The last virus that successfully evades the integrity checkers is of Russian origin and is known under the name StarShip. It is rather common in Russia. It has been probably designed especially as an attack against the integrity checking software. The virus contains several interesting tricks: it installs itself in the video memory, infects the hard disk by modifying only three bytes in the partition table data, is polymorphic, multi–partite, uses the stealth technology, and so on.

A detailed description of this virus is outside the scope of this paper. It is sufficient to say that when an infected file is executed, the virus creates a fake partition in the master boot record, by modifying the parameters of the active one. When the computer is rebooted, the virus is loaded and receives control. It relocates itself to the video memory, then transfers control to the boot sector of the original DOS partition. While the virus is active in memory, it infects all executable files in drives A: and B: (the floppy disk drives) when they are created or modified.

If an integrity checker is installed on the computer before the virus attacks it, the attack will be discovered (because it modifies the master boot record). However, if the computer is already infected when the integrity program is installed, the latter will not be able to detect the further spread of the virus. And the virus spreads rather well—mainly when the executable files are copied to floppies. In fact, the virus tries to maximize the number of infected machines, instead of the number of infected executable objects—a common characteristic of the slow viruses, which is likely to be used more frequently in the future.

This particular virus does not present a significant danger to the West, because it is incompatible with most of the modern hardware and software platforms: monochrome video cards (including monochrome VGAs), MS–DOS with version higher than 3.30, large hard disk partitions (above than 32 Mb) and so on. It also contains a quite visible audio–visual payload, which is unlikely to remain unnoticed for a long time.

However, all the viruses described above present a dangerous trend—ideas, which if combined can make the life very difficult to the integrity checking software.

What can be done against the slow viruses? Very little, having in mind that they exploit an intrinsic flaw of the integrity checking programs... A possible solution is a careful implementation of integrity shells as proposed in [Cohen89].

The idea is to have a resident program, which checks the integrity of the programs before they are executed. However, the program also keeps the so–called dependency paths and checks the integrity of all files the currently executed program depends on. This may include overlays called by the program, macro files, data files that it uses and so on. When the user copies a program, the integrity shell remembers that the copy depends on the original and checks the integrity of both when either of them is executed. (It also checks whether the two match.) The case of the virus that infects only when executable objects are copied to diskettes can be solved by having the integrity shell check that the copy and the original match immediately after the copying process.

Unfortunately, implementing the above conception can be very time–expensive. If the program loading takes too much time because all its dependency files have to be checked too, the user is likely to turn the protection off.

Back to the Table of Contents

2.9. A Combined Attack

Almost all the attacks described above have been "tried" by the virus writers, by implementing them in some virus—at least to demonstrate that it is possible and "can be done". However, most of these viruses have been "demonstration–only" and not able to spread widely. Let's try to imagine what can be done by just combining the different kinds of attack listed above. This (imaginary) virus will be a slow infector, so we shall name it Kuang [Gibson]. Since it combines only the currently known infection techniques, it is just a matter of time before such viruses begin to appear. The reader is invited to try to figure out him/herself how well such virus will spread and how well prepared is the line of anti–virus defense that s/he currently uses against such viruses.

Kuang comes with an infected utility that you get from a BBS or a public archive site, from the boot sector of a data–only diskette that you have forgotten in your boot drive, or from a shrink–(re)wrapped commercial package produced by a company that decides to save some money on the quality assurance procedures. When you execute it, it installs itself in memory in such a way that comparing the listings of MEM/DEBUG before and after the RAM infection will not show any differences. This is possible by installing the virus in some holes in the operating system (like the Tiny virus), in the video memory (like the StarShip virus), and some other places.

After it becomes active, Kuang does not infect anything at once. If you now turn your system off, it will be gone—until the next time you execute the infected utility. However, it carefully watches for any executable object being modified and infects it. Since it is a multi–partite virus, it is able to infect almost anything—boot and master boot sectors, COM and EXE files, overlays, device drivers (like the SVC 6.0 virus), .OBJ files, libraries... The only condition is that some modification is performed with the object—that is, a Create or Write occurs to it (like the Darth Vader, StarShip and Compiler viruses do).

The virus will spread slowly—mostly when the user copies files or formats diskettes. When infecting the files, Kuang uses multiple infection strategies. It tries not to modify the intended file size—if the file contains a block of zeroes (or even of any single byte that is repeated over and over), the virus uses this area to put its body (like the Phoenix and Squisher viruses do). If an EXE file has a sufficiently large EXE header, the virus compresses the relocation items (like the Phoenix.2000 virus does) in order to free space for its body.

Kuang watches for a file with an archive extension (ARC, ARJ, HYP, LHZ, PAK, ZIP, or ZOO) for being opened. When this happens, the virus changes its behaviour. It becomes a fast infector—it begins to infect all executable files (executable in the broad sense, including .OBJ files and libraries) when they are opened (not only when they are modified) and to disinfect them when they are closed (unless they are newly created). This behaviour remains until the archive file is closed. This will ensure that all files being archived will go into the archive infected and all files extracted from the archive will be infected too.

During the infection/disinfection of the files during archiving as described above, the virus uses the tunneling technology (like the Frodo virus) to avoid the possibly present monitoring programs. (This technique is not needed during the normal slow infection, since then the user will not be surprised by a message that a file is about to be modified—because it was the user him/herself who initiated the modification.)

Furthermore, while active in memory, Kuang uses the stealth technology (like the Number of the Beast virus), in order to prevent from being detected by simply comparing the copy of the file with the original or by using the /V switch of the COPY command.

Just in case somebody detects it, Kuang uses armouring tricks (like the Whale or Fish viruses), in order to make the code more difficult to disassemble, debug, and understand.

Additionally, it uses a polymorphic technique, comparable with the one used in the V2Px viruses, or in Dark Avenger's Mutating Engine (MtE), so that even when detected and disassembled, it will be extremely difficult to produce a scanner that will be able to locate and recognize it with 100% reliability...

Finally, the virus can be made to be Novell NetWare–aware and to exploit any security holes in the settings of the directory and file rights. As described in [Cohen92], under Novell NetWare it is not trivial to setup all the protection rights and attributes in a way that will make virus spread impossible. There are many LANs out there, which are not configured in a secure way. Therefore, a clever virus should be able to exploit this.

Back to the Table of Contents

3. Conclusion

The integrity checking software is the currently strongest line of defense against computer viruses. However, there are several possible ways in which this software can be attacked by them. Therefore, extreme care should be taken by the producers of such software to avoid the possible pitfalls. In the same time, there is a need for good integrity testing tools, which will permit the users to test the quality of the integrity checking software themselves. There is also a need for a good set of heuristics that will permit the integrity program to decide reliably whether a modified executable object is really infected or not.

Back to the Table of Contents

4. References

Back to the Table of Contents