Introduction

This chapter illustrates the most common self-protection techniques that viruses use to survive as log as possible even on systems that are protected with a generic solution, such as a computer virus monitoring program. Developing defense systems against computer viruses without giving consideration to these techniques is a sure path to failure.

Tunneling Viruses

Memory resident viruses often use a tunneling technique to get around behaviour blocker systems. Resident tunneling viruses attempt to be the first on a call chain of interrupts, installing themselves in front of other resident applications, to call interrupts directly at the entry point of their original handler. In this way, control gets to the virus first, and the virus proceeds to execute the original handler to bypass antivirus monitoring programs.

Memory Scanning for Original Handler

On a DOS PC for example, it is possible to scan the entire physhical memory for interrupt handler addresses, allowing the virus to keep a short piece of instruction sequence in its body to search for the original entry point of interrupts, such as INT 21h or INT 13h (see the interruptions code table in the references for additional information).

After the virus has obtained the address of INT 21h, it can hook the interrupt by placing a JMP instruction onto the front of the INT 21h routine. Calling the original handler bypasses the interrupt change and might be incompatible with installed software. For example, if there’s a disk-encryption system installed, such viruses might be able to bypass the encryption driver and cause a crash.

Tracing with Debug Interfaces

The idea is to hook INT 1, turn the trace flag of the processor ON and run a harmless interrupt call. INT 1 will be called each time an instruction is executed, and the virus code can trace the code path until it arrives at the particular handler, such as INT 21h. Then, the virus saves the address of the handler and is ready to use it or hook it at that location, bypassing any installed behaviour blockers.

Code emulation based tunneling

A safe alternative to the preceding method is to use a code emulator that mimics the processor well enough to trace the execution path to the desired function entry point without using the debug interfaces at all.

Accessing the disk using I/O ports

A common technique of copy protection schemes is to obtain access to the hard drive and diskettes by talking directly to the device using I/O ports. Not only is this confusing to the defender, but it provides the ability to access the disk on a low enough layer to avoid using regular interrupts or APIs to access the disk. Furthermore, it is possible to do tricks with port commands that interrupt calls and other APIs would not allow.

Just like copy protection, computer viruses with such methods can be incompatible among systems. Thus the virus is simply less infectious than viruses that infect on a higher level.

Using undocumented functions

Other viruses simply use undocumented APIs to get access to original handlers. As I mentioned previously, gaining knowledge of undocumented interfaces and file formats is among the great challenge facing serious computer antivirus researchers.

A large part of Microsoft operating systems is not documented, including the native API and important parts of the kernel APIs. This makes virus code analysis and virus detection much more complicated.

Armored viruses

The term armored was coined to describe computer viruses that make it even more difficult to detect and analyse their functions quickly. We’ll take a look at different techniques that viruses implement in order to stop analyst or slowing them down.

Antidisassebly

Computer viruses written in assembly language are challenging to understand because they often use tricks that normal programs never or very rarely use. To prevent such analysis, virus writers deploy techniques to trick such solutions. The greatest attack on disassemblers are simple variations of code obfuscation techniques such as encryption, polymorphism and metamorphism.

Encrypted data

One of the most obvious way to avoid disassembling is to use encrypted data in the virus code. When the virus is loaded into the disassembler, the virus code will reference encrypted snippets, which you need to decrypt one by one to understand what the virus does.

Code obfuscation

Another possibility for the attacker to challenge disassembling is to use some sort of self-modifying code. When the code is examined in the disassembler, it might not be easy to read or it might contain useless long and difficult pieces of code that have nothing to do with the virus itself.

Opcode mixing based code obfuscation

This technique might confuse an heuristic analyzer simply because it changes some opcodes between them, making tha analysis much more complicated since after disassembling it, it doesn’t make any sense. Luckly, recent disassemblers are smart enough to recognise this behaviour and quickly adjust the opcodes into their correct order and value.

Using checksum to compare strings

Many viruses use some sort of checksum to avoid using any string matching in code. The code is straightforward to read, but you can get extremily confused about its meaning.

Antidebugging

Attackers can use a number of tricks as antidebuggers features. The attacker’s goal is to prevent you from using a debugger easily. Because hardware supports debugging, the antidebug feature can be rather platform-specific so several of these methods are incompatible with certain systems.

PEB structure

Process Environment Block (PEB) is a data structure which resides in the user space of each process, and contains data about the related process. It is designed to be accessed by the WinAPI modules, but access is not limited exclusively to them.

BeingDebugged field

The easiest implementation technique is to chech the value of the BeingDebugged field at the PEB structure.

ProcessHeap flag

A flag under PEB that shows if the first heap memory space of the process was created in debug mode.

Residue in the system

A machine that contains debugging functionalities can be identified without special efforts since the debugger will always leave a trace over the machine.

Registry keys

Besides the obvious registry locations that most applications write themselves, there is a registry key that is set to the debugger program that should run when an error occurs.

FindWindow API function

As the function name says, it identifies open windows on the screen. A virus writer could simply check if for example common debuggers are present on the screen and crash the virus.

Identifying breakpoints

A breakpoint is probably the most important feature of a debugger; it enables the researcher to stop the execution of a program at a certain point of code.

Instruction scanning

A debugger’s breakpoint is implemented by inserting INT 3h, which means that the software interrupt with the parameter 3. A malware can scan itself to find this assembly instruction.

Calculate code checksum or hash

Malware can calculate a checksum or has of itself in runtime to determine if it was patched or if a breakpoint has been added to it.

Antiheuristics

Heuristic analysis can detect unknown viruses and closely related variants of existing viruses using static and dynamic methods. Static heuristic relies on file format and common code fragment analysis, while dynamic heuristic uses code emulation to mimic the processor and the operating system environment and detect suspicious operations as the code is running in the virtual machine of the scanner.

PE file infection techniques

Many PE viruses add a new section or append to the last section of PE files. Even today, many viruses can be detected with the simplest possible PE file heuristic. The heuristic checks to see if the entry point of the PE file points into the last section of the application.

This heuristic can cause false positives, but additional checks can confirm wheter the file is likely compressed (which in most of the cases triggers the false positive alarm).

More than one virus section

Several Win32 viruses append not only to one section but to many section at a time. Because the entry point of the application will be changed to point into the new .text section of the virus, the heuristic is fooled. Furthermore, the virus will maintain a very high compatibility factor with most Win32 systems.

Entry point obscuring techniques

Various Win32 viruses apply a very effective antiheuristic infection method known as the entry-point obscuring or inserting technique. As expected, virus writers implemented inserting polymorphic viruses to evade detection by heuristic scanners. To date, the entry point obscuring method is the most advanced technique of virus writers.

No API string usage

A very effective antiheuristic/antidisassembly trick appears in various modern viruses. A virus doesn’t use any API strings to access particular APIs from the Win32 set. A set of suspicious API strings will appear in nonencrypted viruses and can be easily obtained by using the strings command on the virus.

Antiemulation techniques

Virus writers realized that some scanners use emulation for detecting Win32 viruses and started to create attacks specifically made against the strongest component of the scanner: the emulator.

Using the Coprocessor (FPU) instructions

Some virus writers realized the power of emulators and looked for weaknesses and quickly realized that coprocessor emulation was not implemented. In fact, most emulators skipped coprocessor instructions until recently, whereas most processors that are currently used, support coprocessor instructions by default.

Using undocumented CPU instructions

Althoug there are not too many undocumented Intel processor instructions, there are a few. Some emulators’ implementation of these instructions might differ subtly from the processor’s so that a virus could detect when it’s executing under emulation. However, if the size of the actual opcode is not perfectly calculated, the dynamic heuristic scanner misses the virus detection.

Long loops

Computer viruses also attempt to use long loops to defeat generic decryptors that use emulation. The loop is often polymorphic, but in some cases an overly long loop takes place to calculate a decryption key that is passed to the polymorphic decryptor. Thus, the emulation of the virus code becomes extremely slow.

Antigoat viruses

Computer virus researchers typically build goat files to better understand the infection strategy of a particular virus. The infection of goat files helps virus analysis because it visually separates known file content from the virus body. The goat files typically contain NOP instructions and return to the operating system without any special functionality.

Antigoat viruses use heuristic rules to detect possibile goat files but simply looking at their size: the virus won’t infect a file that has a small size or if it contains a lot of NOP instructions.

Aggressive retroviruses

A retrovirus is a computer virus that specifically tries to bypass or hinder the operation of an antivurs, personal firewall or other security programs.

There are many possible ways for an attacker to achieve this because most Windows users work with their computers as a user with administrative privileges.

Retroviruses have the potential to make way for other computer viruses that are otherwise known and easy for the antivirus software to handle. Therefore, virus writers routinely reverse engineer antivirus products to learn tricks that can be used in retro attacks. For example, aggressive retroviruses often do the following actions upon execution:

  • Disable or kill the antivirus programs in memory and/or on the disk
  • Disable or bypass behavior-blocking products
  • Bypass or kill personal firewall software
  • Delete the integrity-checking database files
  • Detect the execution of antivirus software and perform damage
References
  1. The Art of Computer Virus Research and Defense, Chapter 6
  2. Interrupt handlers
  3. Interrupt codes
  4. Process Environment Block
  5. Common antidebugging techniques