Table of Contents
Previous Section Next Section

11.6. Heuristic Analysis of 32-Bit Windows Viruses

Heuristic analysis has proved to be a successful way to detect new viruses. The biggest disadvantage of heuristic analyzerbased scanners is that they often find false positives, which is not cost-effective for users. In some ways, however, the heuristic analyzer is a real benefit.

For instance, a modern scanner cannot survive without a heuristic scanner for macro viruses24. In the case of binary viruses, heuristic scanning also can be very effective, but the actual risk for a false positive is often higher than that of good macro heuristics.

The capabilities of a heuristic analyzer must be reduced to a level where the number of possible false positives is not particularly high, while the scanner is still able to catch a reasonable number of new viruses. This is not an easy task. Heuristic scanning does not exist in a vacuum. Heuristics are very closely related to a good understanding of the actual infection techniques of a particular virus type. Different virus types require completely different rules on which the heuristic analyzer logic can be built.

Obviously, heuristic analyzers designed to catch DOS viruses or boot viruses are useless in detecting modern Win32 viruses. This section is an introduction to some of the ideas behind the heuristics of Windows viruses25.

The usual method of binary heuristics is to emulate the program execution and look for suspicious code combinations. The following sections introduce some heuristic flags which, for the most part, are not based on code emulation, but which describe particular structural problems unlikely to happen in PE programs compiled with a 32-bit compiler (such as Microsoft, Borland, or Watcom programs). Although not very advanced, structural checking is an effective way to detect even polymorphic viruses such as W95/Marburg or W95/HPS.

Shapes of programs can be used to detect a virus heuristically if they look suspicious enough.


These characteristics are also very useful as filters for algorithmic detection.

11.6.1. Code Execution Starts in the Last Section

The PE format has a very important advantage: Different functional areas, such as code data areas, are separated logically into sections. If you look back to the infection techniques described in Chapter 4, "Classification of Infection Strategies," you will see that most Win32 viruses change the entry point of the application to point to the last section of the program instead of the .text (CODE) section. By default, the linker merges all the object code into the .text section. It is possible to create several code sections, but this does not happen by default compiling, and most Win32 applications will never have such a structure. It looks very suspicious if the entry point of the PE image does not point to the code section.

11.6.2. Suspicious Section Characteristics

All sections have a characteristic that describes certain attributes and that holds a set of flags indicating the section's attributes. The code section has an executable flag but does not need writeable attributes because the data is separated. Very often the virus section does not have executable characteristics but has writeable only or both executable and writeable. Both of these cases must be considered suspicious. Some viruses fail to set the characteristic field and leave the field at 0. That is also suspicious.

11.6.3. Virtual Size Is Incorrect in PE Header

The SizeOfImage is not rounded up to the closest section alignment value by most Windows 95 viruses. Windows 95's loader allows this to happen; Windows NT's does not. It is suspicious enough, therefore, if the SizeOfImage field is incorrect. However, this also could happen as a result of incorrect disinfection.

11.6.4. Possible "Gap" Between Sections

Some viruses, such as W95/Boza and W95/Memorial, round the file size up to the nearest file alignment before adding a new section to it, in a way very similar to DOS EXE infectors. However, the virus does not describe this size difference as in the last section header of the original program. For Windows NT's loader, the image looks like it has a gap in its raw data and is therefore not considered a valid image. Many Windows 95 viruses have this bug, making it a good heuristic flag.

11.6.5. Suspicious Code Redirection

Some viruses do not modify the entry-point field of the code. Instead, they put a jump (JMP) to the entry-point code area to point to a different section. It is very suspicious to detect that the code execution chain jumps out from the main code section to some other section close to the entry point of the program.

11.6.6. Suspicious Code Section Name

It is suspicious if a section that normally does not contain code, such as .reloc, .debug, and so on, gets control. Code executed in such sections must be flagged.

11.6.7. Possible Header Infection

If the entry point of a PE program does not point into any of the sections but points to the area after the PE header and before the first section's raw data, then the PE file is probably infected with a header infector. This is an extremely useful heuristic to detect W95/CIH-style virus infections and virus-corrupted executables.

11.6.8. Suspicious Imports from KERNEL32.DLL by Ordinal

Some Win95 viruses patch the import table of the infected application and add ordinal valuebased imports to it. Imports by ordinal from KERNEL32.DLL should be suspicious, but some Windows 95 programmers do not understand that there is no guarantee that a program that imports from system DLLs by ordinals will work in a different Windows 95 release, and these programmers still use them. In any case, it is suspicious if GetProcAddress() or GetModuleHandleA() functions are imported by ordinal values.

11.6.9. Import Address Table Is Patched

If the import table of the application has GetProcAddress() and GetModuleHandleA() API imports and imports these two APIs by ordinal at the same time, then the import table is patched for sure. This is suspicious.

11.6.10. Multiple PE Headers

When a PE application has more than one PE header, the file must be considered suspicious because the PE header contains many nonused or constant fields. This is the case if the lfanew field points to the second half of the program and it is possible to find another PE header near the beginning of the file. (See Chapter 4 for more details on the lfanew-style infection.)

11.6.11. Multiple Windows Headers and Suspicious KERNEL32.DLL Imports

Structural analysis can detect prepending viruses by searching for multiple new executable headers, such as 16-bit NE and 32-bit PE. This can be done by checking whether the real image size is bigger than the actual representation of the code size as described in the header. As long as the virus does not encrypt the original header information at the end of the program, the multiple Windows headers can be detected. Additionally, the import table must be checked for a combination of API imports. If there are KERNEL32.DLL imports for a combination of GetModuleHandle(), Sleep(), FindFirstFile(), FindNextFile(), MoveFile(), GetWindowsDirectory(), WinExec(), DeleteFile(), WriteFile(), CreateFile(), MoveFile(), CreateProcess(), the application is probably infected with a prepender virus.

11.6.12. Suspicious Relocations

This is a code-related flag. If the code contains instructions that can be used to determine the actual start address of the virus code, it should be flagged. For instance, a CALL instruction detected for the next possible offset is suspicious. Many Win95 viruses use the form of E80000's (CALL next address) 32-bit equivalent form E800000000, similar to DOS virus implementations.

11.6.13. Kernel Look-Up

Code that operates with hard-coded pointers to certain system areas, such as the KERNEL32.DLL or the VMM's memory area, is suspicious. Such viruses often search for the PE\0\0 mark at the same time in their code, which should also be detected.

During program emulation, an application accessing a range of memory can be flagged. For example, a direct code sequence to implement a GetProcAddress() functionality is common both in computer viruses and in exploit code. Direct access to ranges of memory that belong to the KERNEL32.DLL header area is very common in the start-up code of computer virusesbut atypical in normal programs.

11.6.14. Kernel Inconsistency

The consistency of KERNEL32.DLL can be checked by using one API from IMAGEHLP.DLL, such as CheckSumMappedFile() or MapFileAndCheckSum().

In this way, viruses that infect KERNEL32.DLL but do not recalculate the checksum field for it (such as W95/Lorez, W95/Yourn) can be detected easily.

11.6.15. Loading a Section into the VMM Address Space

Unfortunately, it is possible to load a section into the ring 0 memory area under Windows 9x systems. The Virtual Machine Manager (VMM) memory area starts at address 0xC0001000. At 0xC0000000 there is a page that is not used. A few viruses, such as the W95/MarkJ.825 virus, get a hold of this unused page. The virus adds a new section header into the section table of the host program. This new section specifies the virtual address of the section that will point to 0xC0000000 of memory. The system loader allocates this page automatically when the infected application is executed. In turn, the virus code enjoys kernel-mode execution. The system loader could easily refuse this page allocation, but Windows 9x's implementations do not contain such a feature. Therefore, it must be considered suspicious when any section's virtual address points into the VMM area.

11.6.16. Incorrect Size of Code in Header

Most viruses do not touch the SizeOfCode field of the PE header when adding a new executable section. If the recalculated size of all code sections is not the same as in the header, there is a chance that new executable sections have been patched into the executable.

11.6.17. Examples of Suspicious Flag Combinations

Listing 11.14 gives examples of the preceding flags in real viruses such as W32/Cabanas, W95/Anxiety, W95/Marburg, and W95/SGWW.

Listing 11.14. First-Generation Win32 Heuristics
-Execution starts in last section
-Suspicious code section characteristics
-Suspicious code redirection
Possibly infected with an unknown Win32 virus (Level: 5)
-Execution starts in last section
-Suspicious code section characteristics
-Virtual size is incorrect in header
-Suspicious code section name
Possibly infected with an unknown Win32 virus (Level: 6)

-Execution starts in last section
-Suspicious code section characteristics
-Virtual size is incorrect in header
-Suspicious code redirection
-Suspicious code section name
Possibly infected with an unknown Win32 virus (Level: 8)

-Execution starts in last section
-Suspicious code section characteristics
-Virtual size is incorrect in header
-Suspicious relocation
-Suspicious code section name
-Using KERNEL32 address directly and looking for PE00
  Possibly infected with an unknown Win32 virus (Level: 9)

    Table of Contents
    Previous Section Next Section