This chapter examines one of the stealthiest bootkits and advanced VBR Infection ever seen in the wild: the Win32/ Gapz bootkit. We’ll cover its technical characteristics and functionality, beginning with the dropper and bootkit components and moving on to the user-mode payload.
In our experience, Gapz is the most complex bootkit ever analyzed. Every feature of its design and implementation—its elaborate dropper, advanced bootkit infection, and extended rootkit functionality—ensures that Gapz is able to infect and persist on victims’ computers and stay under the radar for a long time.
Gapz is installed onto the victim’s system by a dropper that exploits multiple local privilege escalation vulnerabilities and implements an unusual technique for bypassing Host Intrusion Prevention Systems (HIPS).
After successfully penetrating the victim’s system, the dropper installs the bootkit, which has a very small footprint and is hard to spot on the infected system. The bootkit loads malicious code that implements the Gapz rootkit functionality into kernel mode.
The rootkit functionality is very rich, comprising a custom TCP/IP network stack, advanced hooking engine, crypto library, and payload injection engine.
This chapter takes a deep dive into each of these powerful features.
The Gapz Dropper
Gapz is installed onto the target system by an elaborate dropper. There are several variations of the Gapz dropper, all containing a similar payload, which we’ll cover later in “Gapz Rootkit Functionality” on page 191. The difference between the droppers lies in the bootkit technique and the number of local privilege escalation (LPE) vulnerabilities they each exploit.
The first instance of Gapz discovered in the wild was Win32/Gapz.C, in April 2012.1 This variation of the dropper employed an MBR-based bootkit—the same technique covered in Chapter 7 for the TDL4 bootkit—to persist on a victim’s computer. What made Win32/Gapz.C remarkable was that it contained a lot of verbose strings for debugging and testing and that its early distribution was very limited. This suggests that the first versions of Gapz weren’t intended for mass distribution but rather were test versions to debug the malware’s functionality.
Related Article:IPL Bootkits :Rovnix and Carberp-by Blackhat Pakistan 2023
The second variation, Win32/Gapz.B, didn’t install a bootkit on the targeted system at all. To persist on the victim’s system, Gapz simply installed a malicious kernel-mode driver. However, this approach wouldn’t work on Microsoft Windows 64-bit platforms due to the lack of a valid digital signature for the kernel-mode driver, limiting this modification to Microsoft Windows 32-bit operating systems only.
The last known and the most interesting iteration of the dropper, Win32/Gapz.
A, is the version we’ll focus on in this chapter. This version came with a VBR bootkit. In the rest of the chapter, we will simply use “Gapz” to refer to Win32/Gapz.A. Table 12-1 summarizes the different versions of the dropper.
The detection name column lists the Gapz variation adopted by the antivirus industry. The entries in the compilation date column are taken from the Gapz droppers’ PE header, which is believed to be an accurate timestamp. The Bootkit technique column shows what kind of bootkit the dropper employs.
Finally, the LPE exploits column lists a number of LPE vulnerabilities exploited by Gapz droppers in order to get administrator privileges on the victim systems. The COM elevation vulnerability is used to bypass the User Account Control (UAC) security feature in order to inject code into a system process that is whitelisted for UAC. The CVE-2011-3402 vulnerability relates to the TrueType font–parsing functionality implemented in the win32k.sys module. The CVE-2010-4398 vulnerability is due to a stackbased buffer overflow in the RtlQueryRegistryValues routine, also located in the win32k.sys module. The CVE-2011-2005 vulnerability, located in the afd.sys (ancillary function driver) module, allows attackers to overwrite data in kernel-mode address space.
All of the variations of the Gapz dropper listed in Table 12-1 contain the same payload.
Before examining the Gapz dropper more closely, let’s recap what it needs in order to silently and successfully install Gapz onto the system.
First, the dropper requires administrative privileges to access the hard drive and modify MBR/VBR/IPL data. If the dropper’s user account lacks administrator privileges, it must raise its privileges by exploiting LPE vulnerabilities in the system.
Second, it needs to bypass security software, such as antivirus programs, personal firewalls, and Host Intrusion Prevention Systems. To stay under the radar, Gapz uses advanced tools and methods, including obfuscation, antidebugging, and antiemulation techniques. In addition to these methods, the Gapz dropper employs a unique and rather interesting technique to bypass HIPS, as discussed later in the chapter.
Taking these obstacles into account, these are the steps the Gapz dropper performs to successfully infect a system:
1. Inject itself into explorer.exe to bypass HIPS (as discussed in “Bypassing HIPS” on page 181).
2. Exploit an LPE vulnerability in the targeted system to elevate its user privileges. 3. Install the bootkit onto the system.
Also Read:evolution of MBR and VBR
When the unpacked dropper is loaded into the IDA Pro disassembler, its export address table will look something like Figure 12-1. The export address table shows all the symbols exported from the binary and nicely sums up the steps in the dropper execution algorithm.
There are three routines exported by the binary: one main entry point and two routines with randomly generated names. Each routine has its own purpose:
start Injects the dropper into the explorer.exe address space
icmnf Exploits LPE vulnerabilities in the system to elevate privileges
isyspf Infects the victim’s machine
Figure 12-1 also shows the exported symbol gpi. This symbol points to a shared memory in the dropper image, used by the preceding routines to inject the dropper into the explorer.exe process.
Figure 12-2 depicts these stages. The main entry point doesn’t infect the system with the Gapz bookit. Instead it executes the start routine to inject the dropper into explorer.exe in order to bypass detection by security software. Once the dropper is injected, it attempts to acquire administrator privileges by exploiting LPE vulnerabilities in the system with the icmnf routine. Once the dropper gains the required privileges, it executes the isyspf routine to infect the hard drive with the bootkit.
Let’s take a closer look at the process of injecting the dropper and bypassing HIPS.
Computer viruses have many methods of camouflaging themselves as
benign software to avoid attracting the attention of security software. The
TDL3 rootkit we discussed in Chapter 1 employs another interesting technique for bypassing HIPS, which abused AddPrintProvidor/AddPrintProvider
system APIs to stay under the radar. These API functions are used to load
custom modules into a trusted system process, spoolsvc.exe, that is responsible for printing support on Windows systems. The AddPrintProvidor (sic)
routine, an executable module used to install a local print provider onto
the system, is frequently excluded from the list of items monitored by security software. TDL3 simply creates an executable file with malicious code and loads it into spoolsvc.exe by running AddPrintProvidor. Once the routine is executed, the malicious code runs within the trusted system process, allowing TDL3 to attack without worrying about being detected.
Gapz also injects its code into a trusted system process in order to bypass HIPS, but it uses an elaborate nonstandard method, the core aim of which is to inject shellcode that loads and executes the malicious image into the explorer process. These are the steps the dropper takes:
1. Open one of the shared sections from \BaseNamedObjects mapped into the explorer.exe address space (see Listing 12-1) and write shellcode into this section. The \BaseNamedObjects directory in the Windows Object Manager namespace contains names of mutex, event, semaphore, and section objects.
2. After writing the shellcode, search for the window Shell_TrayWnd. This window corresponds to the Windows taskbar. Gapz targets this window in particular because it is created and managed by explorer.exe and is very likely available in the system.
3. Call the Win32 API function GetWindowLong to get the address of the routine related to the Shell_TrayWnd window handler.
4. Call the Win32 API function SetWindowLong to modify the address of the routine related to the Shell_TrayWnd window handler.
5. Call SendNotifyMessage to trigger the execution of the shellcode in the explorer.exe address space.
The section objects are used to share part of a certain process’s memory with other processes; in other words, they represent a section of memory that can be shared across the system processes. Listing 12-1 shows the section objects in \BaseNamedObjects for which the malware looks in step 1. These section objects correspond to system sections—that is, they are created by the operating system and contain system data. Gapz iterates through the list of section objects and opens them to check whether they exist in the system. If a section object exists in the system, the dropper stops iterating and returns a handle for the corresponding section.
The malware uses 336 (0x150) bytes u of the space at the end of the section to write the shellcode. To ensure the shellcode executes correctly, the malware also provides the addresses of some API routines used during the injection process: CloseHandle, MapViewOfFile, OpenFileMappingA, CreateThread, and SetWindowLongA v. The shellcode will use these routines to load the Gapz dropper into the explorer.exe memory space.
Gapz executes the shellcode using the return-oriented programming (ROP) technique. ROP takes advantage of the fact that in x86 and x64 architectures, the ret instruction can be used to return control to the parent routine after execution of a child subroutine. The ret instruction assumes that the address to which control is returned is on the top of the stack, so it pops the return address from the stack and transfers control to that address. By executing a ret instruction to gain control of the stack, an attacker can execute arbitrary code.
The reason Gapz uses the ROP technique to execute its shellcode is that the memory corresponding to the shared section object may not be executable, so an attempt to execute instructions from there will generate an exception. To overcome this limitation, the malware uses a small ROP program that’s executed before the shellcode. The ROP program allocates some executable memory inside the target process, copies the shellcode into this buffer, and executes it from there.
Gapz finds the gadget for triggering the shellcode in the routine ConstructTargetBuffer w. In the case of 32-bit systems, Gapz uses the system routine ntdll!KiUserApcDispatcher to transfer control to the ROP program.
Modifying the Shell_TrayWnd Procedure
Once it has written the shellcode to the section object and found all the necessary ROP gadgets, the malware proceeds to the next step: modifying the Shell_TrayWnd window procedure. This procedure is responsible for handling all the events and messages that occur and are sent to the window. Whenever the window is resized or moved, a button is pressed, and so on, the Shell_TrayWnd routine is called by the system to notify and update the window. The system specifies the address of the window procedure at the time of the window’s creation.
The Gapz dropper retrieves the address of the original window procedure, in order to return to it after injection, by executing the GetWindowLongA x routine. This routine is used to get window parameters and takes two arguments: the window handle and an index of the parameter to be retrieved. As you can see, Gapz calls the routine with the index parameter 0, indicating the address of the original Shell_TrayWnd window procedure. The malware stores this value in the memory buffer in order to restore the original address after injection.
Next, the malware executes the SetWindowLongA routine y to modify the address of the Shell_TrayWnd window procedure to the address of the ntdll!KiUserApcDispatcher system routine. By redirecting to an address within the system module and not the shellcode itself, Gapz further protects itself against detection by security software. At this point, the shellcode is ready to be executed.
Executing the Shellcode
Gapz triggers the execution of the shellcode by using the SendNotifyMessageA API z to send a message to the Shell_TrayWnd window, passing control to the window procedure. As explained in the previous section, after the address of the window procedure is modified, the new address points to the KiUserApcDispatcher routine. This eventually results in control being transferred to the shellcode mapped within the explorer.exe process address space, as shown in Listing 12-3. file that corresponds to the dropper into the address space of explorer.exe (u and v). Then it creates a thread w in the explorer.exe process to execute the mapped image and restores the original index value that was changed by the SetWindowLongA WinAPI function x. The newly created thread runs the next part of the dropper, escalating its privileges. Once the dropper obtains sufficient privileges, it attempts to infect the system, which is when the bootkit feature comes into play.
Infecting the System with the Gapz Bootkit
Gapz uses two distinct variations of infection technique: one targeting the MBR of the bootable hard drive and the other targeting the VBR of the active partition. The bootkit functionality of both versions, however, is pretty much the same. The MBR version aims to persist on a victim’s computer by modifying MBR code in a similar way to the TDL4 bootkit. The VBR version uses subtler and stealthier techniques to infect the victim’s system, and as mentioned, that’s the one we’ll focus on here.
We briefly touched on the Gapz bootkit technique in Chapter 7, and now we’ll elaborate on the implementation details. The infection method Gapz uses is one of the stealthiest ever seen in the wild, modifying only a few bytes of the VBR and making it very hard for security software to detect it.
Reviewing the BIOS Parameter
Block The main target of the malware is the BIOS parameter block (BPB) data structure located in the VBR (see Chapter 5 for more details). This structure contains information about the filesystem volume located on the partition and has a crucial role in the boot process. The BPB layout differs across various filesystems (FAT, NTFS, and so on), but we will focus on NTFS. The contents of the BPB structure for NTFS are shown in Listing 12-4 (this is excerpted from Listing 5-3 for convenience).
As you may recall from Chapter 5, the HiddenSectors field u, located at offset 14 from the beginning of the structure, determines the location of the IPL on the hard drive (see Figure 12-3). The VBR code uses HiddenSectors to find the IPL on the disk and execute it .
Infecting the VBR
Gapz hijacks the control flow at system bootup by manipulating the HiddenSectors field value inside the BPB. When infecting a computer, Gapz writes the bootkit body before the very first partition if there is enough space or after the last partition otherwise, and it modifies the HiddenSectors field to point to the start of the rootkit body on the hard drive rather than to the legitimate IPL code (see Figure 12-4). As a result, during the next bootup, the VBR code loads and executes the Gapz bootkit code from the end of the hard drive.
What makes this technique particularly clever is that it modifies only 4 bytes of the VBR data, considerably less than other bootkits. For instance, TDL4 modifies the MBR code, which is 446 bytes; Olmasco changes an entry in the MBR partition table, which is 16 bytes; and Rovnix alters IPL code that takes up 15 sectors, or 7,680 bytes.
Gapz appeared in 2012, at a time when the security industry had caught up with modern bootkits and MBR, VBR, and IPL code monitoring had already become normal practice. However, by altering the HiddenSectors field of the BPB, Gapz pushed bootkit infection techniques one step further and left the security industry behind. Before Gapz, it wasn’t common for security software to inspect the BPB’s fields for anomalies. It took some time for the security industry to get wise to its novel infection method and develop solutions.
Another thing that sets Gapz apart is that the contents of the field HiddenSectors aren’t fixed for BPB structures—they can differ from one system to another. The value of HiddenSectors depends largely on the partition scheme of the hard drive. In general, security software cannot determine whether a system is infected or not using just the HiddenSectors value; it must perform a deeper analysis of the actual code located at the offset.
Figure 12-5 displays the contents of the VBR taken from a real system infected with Gapz. The BPB is located at offset 11 and the HiddenSectors field, holding the value 0x00000800, is highlighted.
To be able to detect Gapz, the security software must analyze the data located at offset 0x00000800 from the beginning of the hard drive. This is where the malicious bootloader is located.
Loading the Malicious Kernel-Mode Driver
As with many modern bootkits, the main purpose of the Gapz bootkit code is to compromise the operating system by loading malicious code into kernelmode address space. Once the Gapz bootkit code receives control, it proceeds with the regular routine of patching OS boot components, as described in previous chapters.
Once executed, the bootkit code hooks the INT 13h handler in order to monitor data being read from the hard drive. Then it loads the original IPL code from the hard drive and executes it to resume the boot process. Figure 12-6 shows the boot process in a system infected with Gapz.
After hooking INT 13h u, the malware monitors data read from the hard drive and looks for the bootmgr module, which in turn patches in memory in order to hook the Archx86TransferTo32BitApplicationAsm (Archx86TransferTo64BitApplicationAsm for x64 Windows platforms) routine v. This routine transfers control from bootmgr to the entry point of winload.exe. The hook is used to patch the winload.exe module.
Once the hook in bootmgr is triggered, winload.exe is already in memory and the malware can patch it. The bootkit hooks the OslArchTransferToKernel routine w in the winload.exe module. As discussed in the previous chapter, Rovnix also started by hooking the INT 13h handler, patching bootmgr, and hooking OslArchTransferToKernel. But, unlike Gapz, in the next step Rovnix compromised the kernel by patching the kernel KiSystemStartup routine.
Gapz, on the other hand, hooks another routine in the kernel image: IoInitSystem x. The purpose of this routine is to complete the kernel initialization by initializing different OS subsystems and calling the entry points of the boot start drivers. Once IoInitSystem is executed, the malicious hook is triggered, restoring the patched bytes of the IoInitSystem routine and overwriting IoInitSystem’s return address on the stack with an address to the malicious code. The Gapz bootkit then releases control back to the IoInitSystem routine.
Upon completion of the routine, control is transferred back to the malicious code. After IoInitSystem executes, the kernel is properly initialized, and the bootkit can use the services it provides to access the hard drive, allocate memory, create threads, and more. Next, the malware reads the rest of the bootkit code from the hard drive, creates a system thread, and, finally, returns control to the kernel. Once the malicious kernel-mode code is executed in the kernel-mode address space, the bootkit’s job is finished y.
Gapz Rootkit Functionality
In this section, we’ll focus on the rootkit functionality of the malware, the most interesting aspect of Gapz after its bootkit functionality. We’ll refer to the Gapz rootkit functionality as the kernel-mode module since it isn’t a valid kernel-mode driver, in the sense that it isn’t a PE image at all. Rather, it’s laid out as position-independent code consisting of several blocks, each of which implements specific functionality of the malware to complete a certain task. The purpose of the kernel-mode module is to secretly and silently inject a payload into the system processes.
One of the most interesting aspects of the Gapz kernel-mode module is that it implements a custom TCP/IP network stack to communicate with C&C servers; it uses a crypto library with custom implementations of such crypto primitives as RC4, MD5, SHA1, AES, and BASE64, to protect its configuration data and C&C communication channel. And, as with any other complex threat, it implements hidden storage to secretly store its user-mode payload and configuration information. Gapz also includes a powerful hooking engine with a built-in disassembler to set up persistent and stealthy hooks. In the rest of this section, we will consider these and more aspects of the Gapz kernel-mode module in detail.
The Gapz kernel-mode module isn’t a conventional PE image but rather is composed of a set of blocks with position-independent code (PIC), which doesn’t use absolute addresses to reference data. Therefore, its memory buffer may be located at any valid virtual address in a process’s address space. Each block serves a specific purpose. A block is preceded by a header describing its size and position in the module and some constants used to calculate the addresses of the routines implemented within that block.
The header starts with the integer constant ProcBase u, used to calculate the offsets of the routines implemented in a basic block. NextBlockOffset v specifies the offset of the next block within the module, allowing Gapz to enumerate all the blocks in the kernel-mode module. BlockInitialization w contains the offset from the beginning of the block to the block initialization routine, executed at the kernel-mode module initialization. This routine initializes all the necessary data structures specific to the corresponding block and should be executed before any other function implemented in the block.
Gapz uses a global structure that holds all the data related to its kernelmode code: addresses of the implemented routines, pointers to allocated buffers, and so on. This structure allows Gapz to determine the addresses of all the routines implemented in the position-independent code blocks and then execute them
. The position-independent code references the global structure using the hexadecimal constant 0xBBBBBBBB (for an x86 module). At the very beginning of the malicious kernel-mode code execution, Gapz allocates a memory buffer for the global structure. Then it uses the BlockInitialization routine to run through the code implemented in each block and substitute a pointer to the global structure for every occurrence of 0xBBBBBBBB.
The disassembly of the OpenRegKey routine implemented in the kernelmode module looks something like Listing 12-6. Again, the constant 0xBBBBBBBB is used to refer to the address of the global context, but during execution, this constant is replaced with the actual address of the global structure in memory so that the code will execute correctly.
kernel-mode module that starts the execution of the module, initializes the other code blocks, sets up hooks, and initiates communication with C&C servers.
Like most bootkits, Gapz implements hidden storage to store its payload and configuration information securely. The image of the hidden filesystem is located in a file on the hard drive at \??\C:\System Volume Information\ where X signifies hexadecimal numbers generated based on configuration information. The layout of the hidden storage is a FAT32 filesystem. Figure 12-7 shows an example of the content of the \usr\overlord hidden storage directory. You can see three files stored in the directory: overlord32.dll, overlord64 .dll, and conf.z. The first two files correspond to the user-mode payload to be injected into system processes. The third file, conf.z, contains configuration data.
To encrypt and decrypt each sector of the hidden storage, Gapz utilizes a custom implementation of the Advanced Encryption Standard algorithm with a key length of 256 bits in cipher block chaining (CBC) mode. Gapz uses the number of the first sector u being encrypted or decrypted as the initialization value (IV) for CBC mode, as shown in Listing 12-7. Then the IV for every sector that follows is incremented by 1 v. Even though the same key is used to encrypt every sector of the hard drive, using different IVs for different sectors results in different ciphertexts each time.
Self-Defense Against Antimalware Software
To protect itself from being removed from the system, Gapz hooks two routines on the hard disk miniport driver: IRP_MJ_INTERNAL_DEVICE_CONTROL and IRP_MJ_DEVICE_CONTROL. In the hooks the malware is interested only in the following requests.
These hooks protect the infected VBR or MBR and the Gapz image on the hard drive from being read and overwritten.
Unlike TDL4, Olmasco, and Rovnix, which overwrite the pointer to the handlers in the DRIVER_OBJECT structure, Gapz uses splicing: that is, it patches the handlers’ code itself. In Listing 12-8, you can see the hooked routine of the scsiport.sys driver image in memory. In this example, scsiport.sys is a disk miniport driver that implements the IOCTL_SCSI_XXX and IOCTL_ATA_XXX request handlers, and it is the main target of the Gapz hooks.
The snippet in Listing 12-9 shows code from the hooking routine that analyzes the instructions of the handler to find the best location to set up the hook. It checks the operation codes of the instructions 0x90 (corresponding to nop) and 0x8B/0x89 (corresponding to mov edi, edi). These instructions may signify that the target routine belongs to a hot-patchable image and thus may be potentially patched by the OS. This way, the malware knows to skip these instructions when placing the hook.
To perform this analysis, Gapz implements the hacker disassembler engine, which is available for both x86 and x64 platforms. This allows the malware to obtain not only the length of the instructions but also other features, such as the operation code of the instruction and its operands.
The Gapz kernel-mode module injects the payload into the user-mode address space as follows:
1. Read the configuration information to determine which payload modules should be injected into specific processes and then read those modules from hidden storage.
2. Allocate a memory buffer in the address space of the target process in which to keep the payload image.
3. Create and run a thread in the target process to run the loader code; the thread maps the payload image, initializes the IAT, and fixes relocations.
The \sys directory within the hidden filesystem contains a configuration file specifying which payload modules should be injected into specific processes. The name of the configuration file is derived from the hidden filesystem AES encryption key via a SHA1 hashing algorithm. The configuration file consists of a header and a number of entries, each of which describes a target process, as shown in Figure 12-8.
The module overlord32.dll (overlord64.dll for 64-bit process) is injected into the svchost.exe processes in the system. The purpose of the overlord32.dll module is to execute the Gapz commands issued by the malicious kernelmode code. These executed commands might perform the following tasks:
• Gather information about all the network adapters installed in the system and their properties.
• Gather information on the presence of particular software in the system.
• Check the internet connection by trying to reach http://www.update .microsoft.com.
• Send and receive data from a remote host using Windows sockets.
• Get the system time from http://www.time.windows.com.
• Get the host IP address when given its domain name (via Win32 API gethostbyname).
• Get the Windows shell (by means of querying the “shell” value of the Software\Microsoft\Windows NT\CurrentVersion\Winlogon registry key).
The results of those commands are then transmitted back to the kernel mode. Figure 12-9 shows an example of some configuration information extracted from the hidden storage on the infected system.
You can see the two modules—overlord32.dll and overlord64.dll— intended for injection into the svchost.exe processes on x86- and x64-bit systems, respectively.
Once a payload module and a target process have been identified, Gapz allocates a memory buffer in the target process address space and copies the payload module into it. Then the malware creates a thread in the target process to run the loader code. If the operating system is Windows Vista or higher, Gapz can create a new thread by simply executing the system routine NtCreateThreadEx.
In pre-Vista operating systems (such as Windows XP or Server 2003), things are a bit more complicated because the NtCreateThreadEx routine is not exported by the OS kernel. In these cases, Gapz reimplements some of the NtCreateThreadEx functionality in the kernel-mode module and follows these steps:
1. Manually allocate the stack that will hold the new thread.
2. Initialize the thread’s context and thread environment block (TEB).
3. Create a thread structure by executing the undocumented routine NtCreateThread.
4. Register a newly created thread in the client/server runtime subsystem (CSRSS) if necessary.
5. Execute the new thread.
The loader code is responsible for mapping the payload into a process’s address space and is executed in user mode. Depending on the payload type, there are different implementations for the loader code, as shown in Figure 12-10. For payload modules implemented as DLL libraries, there are two loaders: a DLL loader and a command executer. For payload modules implemented as EXE modules, there are also two loaders.
DLL Loader Code
The Gapz DLL loader routine is responsible for loading and unloading DLLs. It maps an executable image into the user-mode address space of the target process, initializes its IAT, fixes relocations, and executes the following export routines depending on whether the payload is loaded or unloaded:
Export routine #1 (loading payload) Initializes the loaded payload
Export routine #2 (unloading payload) Deinitializes the loaded payload .
Figure 12-11 shows the payload module overlord32.dll.
Figure 12-12 illustrates the routine. When unloading the payload, Gapz executes export routine #2 and frees memory used to hold the payload image. When loading the payload, Gapz performs all the necessary steps to map the image into the address space of the process and then execute export routine #1.
Command Executer Code
The command executor routine is responsible for executing commands as instructed by the loaded payload DLL module. This routine merely calls export routine #3 (Figure 12-11) of the payload and passes all the necessary parameters to its handler.
EXE Loader Code
The two remaining loader routines are used to run downloaded executables in the infected system. The first implementation runs the executable payload from the TEMP directory: the image is saved into the TEMP directory and the CreateProcess API is executed, as indicated in Figure 12-13.
The second implementation runs the payload by creating a suspended legitimate process, then overwriting the legitimate process image with the malicious image; after that, the process is resumed, as illustrated in Figure 12-14.
The second method of loading the executable payload is stealthier and less prone to detection than the first. While the first method simply runs the payload without any precautions, the second method creates a process with a legitimate executable first and only then replaces the original image with the malicious payload. This may trick the security software into allowing the payload to execute.
Payload Communication Interface
In order to communicate with the injected payload, Gapz implements a specific interface in quite an unusual way: by impersonating the handler of the payload requests in the null.sys driver. This technique is shown in Figure 12-15.
The malware first sets the DriverUnload field u of the DRIVER_OBJECT structure corresponding to the \Device\Null device object to 0 (storing a pointer to the handler that will be executed when the OS unloads the driver) and hooks the original DriverUnload routine.
Then it overwrites the address of the IRP_MJ_DEVICE_CONTROL handler in the DRIVER_OBJECT with the address of the hooked DriverUnload routine v. The hook checks the parameters of the IRP_MJ_DEVICE_CONTROL request to determine whether the request was initiated by the payload. If so, the payload interface handler is called instead of the original IRP_MJ_DEVICE_CONTROL handler w.
The payload opens a handle to the NULL device u. This is a system device, so the operation shouldn’t draw the attention of any security software. Once the payload obtains the handle, it communicates with the kernel-mode module using the DeviceIoControl system API v.
Custom Network Protocol Stack
The bootkit communicates with C&C servers over the HTTP protocol, whose main purpose is to request and download the payload and report back the bot status. The malware enforces encryption to protect the confidentiality of the messages being exchanged and to check the authenticity of the message source in order to prevent subversion by commands from fake C&C servers.
The most striking feature of the network communication is the way in which it is implemented. There are two ways the malware sends a message to the C&C server: by using the user-mode payload module (overlord32.dll or overlord64.dll) or using a custom kernel-mode TCP/IP protocol stack implementation. This network communication scheme is shown in Figure 12-16.
The user-mode payload, overlord32.dll or overlord64.dll, sends the message to the C&C server using a Windows socket implementation. The custom implementation of the TCP/IP protocol stack relies on the miniport adapter driver. Normally, network communication requests pass through the network driver stack, and at different layers of the stack they may be inspected by security software drivers. According to Microsoft’s Network Driver Interface Specification (NDIS), the miniport driver is the lowest driver in the network driver stack, so by sending network I/O packets directly to the miniport device object, Gapz can bypass all the intermediate drivers and avoid inspection (see Figure 12-17).
Gapz obtains a pointer to the structure describing the miniport adapter by manually inspecting the NDIS library (ndis.sys) code. The routine responsible for handling NDIS miniport adapters is implemented in block #8 of the kernel-mode module.
This approach allows Gapz to use the socket interface to communicate with the C&C server without being noticed. The architecture of the Gapz network subsystem is summarized in Figure 12-18.
As you can see, the Gapz network architecture implements most layers of the Open Systems Interconnection (OSI) model: data link, transport, and application. To send and receive network packets to and from the physical device object that represents the network interface card, Gapz uses a corresponding interface available in the system (provided by the network card driver). However, all the work related to creating and parsing network frames is entirely implemented in the malware’s custom network stack.
As you’ve seen, Gapz is complex malware with a very elaborate implementation and one of the most remarkably covert bootkits due to its VBR infection technique. No previously known bootkit can boast such a simultaneously elegant and subtle infection approach. Its discovery forced the security industry to step up its bootkit detection approaches and dig deeper into MBR/VBR scanning, looking not only at MBR/VBR code modifications but also at parameters and data structures that were previously considered out of scope.