http://resources.infosecinstitute.com/tdss4-part-3/ Introduction
In this final article in this series, we will describe the process of loading the bootkit previously discussed in “TDSS part 1: the x64 Dollar Question” and “TDSS part 2: Ifs and Bots”.
First of all we explain briefly how the normal boot process is handled
on different systems, presenting only the minimum information necessary
to understand the overall process. Then we show how the bootkit exploits
certain features of the boot process so as to get itself loaded.
Booting BIOS firmware
When the computer is switched on, the BIOS (Basic Input/Output
System) firmware is loaded into memory and performs initialization and
POST (Power On Self Test). Then it looks for a bootable disk drive and
reads its very first sector, the boot sector. The sector contains the
disk’s partition table and code responsible for further handling of the
boot process: these together are referred to as the MBR (Master Boot
Record). The MBR code reads the partition table, looks for an active
partition and loads its first sector (VBR, Volume Boot Record), which
contains file system-specific boot code. Up to this point the boot
process is the same for both Windows Vista family operating systems
(Windows Vista, Windows Server 2008, and Windows 7) and pre-Windows
Vista operating systems (Windows 2000, Windows XP, Windows Server 2003)
but thereafter it’s handled differently. We’ll describe the boot process
for each class of operating systems in separate subsections.
Booting OS’s prior to Windows Vista
The VBR contains code that reads ntldr (an application loading
kernel, nt loader) from the root directory of the hard drive into memory
and transfers control to it. Ntldr consists of two parts:
- 16-bit real-mode code performing initialization and interfacing with BIOS services;
- 32-bit PE image (osloader.exe) handling the boot process.
As soon as ntldr starts to execute it switches the processor into
protected mode, loads the embedded PE image (osloader.exe) and transfers
control to it. Osloader.exe is responsible for reading configuration
information (boot.ini file, system hive), gathering information about
hardware in the system (this feature is implemented in a separate module
ntdetect.com), and loading the appropriate version of the kernel and
its dependencies, which are described in the table below with more
detail given in Figure 1.
Module name
|
Description
|
hall.dll
|
hardware abstraction layer
|
bootvid.dll
|
the module responsible for displaying graphical images during boot time
|
kdcom.dll
|
the module implementing the debugger interface through the serial port |
Figure 1 – Dependencies of ntoskrnl.exe
In addition, osloader.exe loads the file system driver and boot start
drivers. Although the code of osloader.exe is executed in protected
mode, it still relies on BIOS services to perform IO operations to and
from hard drive and console (in the case of IDE disks). To be able to
call BIOS services which are executed in the 16-bit real mode execution
environment, osloader.exe briefly switches the processor into real mode,
executes a BIOS service and after that switches the processor back to
protected mode. We’ll see later how the bootkit exploits this feature.
When all these operations are completed,
osloader.exe proceeds with calling the entry point of the kernel image —
KiSystemStartup. The last element to mention plays an important role in
the process of loading the bootkit — during the kernel initialization
the exported function KdDebuggerInitialize1 from kdcom.dll library is
called in order to initialize the debugging facilities of the system.
Figure 2– Boot process of a pre-Windows Vista OS
Booting Post Windows XP
In the case of operating systems of the Windows Vista family (Windows
Vista, Windows 7, Windows Server 2008) the boot process is rather
different to that of earlier OS versions. First of all, the code stored
in the VBR loads bootmgr instead of loading ntldr — bootmgr is a boot
time application introduced for the first time in Windows Vista OS for
compatibility with the UEFI (Unified Extensible Firmware Interface:
http://www.uefi.org/) specification. Essentially, bootmgr has a similar
structure to ntldr: that is, it consists of a 16-bit stub and a 32-bit
PE image. The stub is executed in the real-mode execution environment
and is responsible for switching the processor into 32-bit protected
mode, as well as providing an interface for invoking 16-bit real mode
BIOS services (as ntdlr does).
Bootmgr reads the BCD (boot configuration
data) and then proceeds with loading either winload.exe or winresume.exe
(to restore the state of the hibernating system). Winload.exe is
similar in functionality to osloader.exe (embedded PE image in ntldr)
and performs initialization of the system based on parameters provided
in BCD, before transferring control to the kernel image:
- loads system hive;
- initializes code integrity policy;
- loads kernel and its dependencies (hal.dll, bootvid.dll, kdcom.dll);
- loads file system driver for root partition;
- loads boot start drivers;
- transfers control to the kernel’s entry point.
Kernel-mode code integrity policy
determines the way the system checks the integrity of all the modules
loaded into kernel-mode address space, including system modules loaded
at boot time. Kernel-mode integrity policy is controlled by the
following BCD options:
BCD options
|
Description
|
BcdLibraryBoolean_DisableIntegrityCheck |
disables kernel-mode code integrity checks |
BcdOSLoaderBoolean_WinPEMode
|
instructs kernel to be loaded in pre-installation mode, disabling kernel-mode code integrity checks as a byproduct |
BcdLibraryBoolean_AllowPrereleaseSignatures
|
enables test signing
|
Thus, if one of the first two options in BCD is set, then kernel-mode code integrity checks will be disabled.
When all the necessary modules are loaded winload.exe proceeds with
transferring control to kernel’s entry point. As is the case with
Windows operating systems prior to Windows Vista, the code performing
kernel initialization calls the exported function KdDebuggerInitialize1
from the kdcom.dll library to initialize the debugging facilities of the
system.
Figure 3 – Boot process of post Windows Vista OS
Loading the bootkit
Here we describe how the bootkit is loaded in the system with respect
to the boot process described in the corresponding subsections.
When the system is started, the BIOS reads the infected MBR into
memory end executes its code, thereby loading the first part of the
bootkit. The infected MBR locates the bootkit’s file system at the end
of the bootable hard drive, and loads and executes a file with the name
“ldr16″, which contains code responsible for hooking the BIOS 13th
interrupt handler (disk service) and restoring the original MBR. This is
stored in the file called “mbr” in the hidden file system (see figure
21).
Figure 4 – Hooking Int 13h Handler and Restoring Original MBR
When the control is transferred to the original MBR, the boot process
continues as described in the previous sections while the bootkit is
resident in memory, and controls all the IO operations to/from the hard
drive. The most interesting part of “ldr16″ lies in the new Int 13h
handler.
The code reading data from the hard drive during the boot process
relies on the BIOS service, specifically, interrupt 13h, which is
intercepted by the bootkit: thus, the bootkit is able to counterfeit any
data read from the hard drive during the boot process. The bootkit
takes advantage of the opportunity by replacing kdcom.dll with a file
“ldr32″ or “ldr64″ (depending on the bit capacity of the operating
system) from the hidden file system, substituting its content in the
memory buffer during the read operation. “ldr32″ and “ldr64″ are
essentially the same, functionally, except that “ldr32″ is a 32-bit DLL
and “ldr64″ is a 64-bit DLL. Both of these modules export the same
symbols as the original kdcom.dll library to conform to the requirements
of the interface used to communicate between ntoskrnl.exe and the
serial debugger.
Figure 5 – Export Table of ldr32 (ldr64)
All the exported functions from the malicious kdcom.dll do nothing
but return 0, with the exception of KdDebuggerInitialize1 which, as you
will remember, is called by ntoskrnl.exe during the kernel
initialization. This function actually contains code loading the
bootkit’s driver into the system in the following ways:
- It registers CreateThreadNotifyRoutine by calling the PsSetCreateThreadNotifyRoutine system routine;
- When CreateThreadNotifyRoutine is executed it creates a
DRIVER_OBJECT object and waits until the driver stack for the hard disk
device has been built;
- Once the disk class driver is loaded, the bootkit is able to access
data stored on hard drive, so it loads its kernel-mode driver from the
file with name “drv32″ or “drv64″ (according to the OS bit capacity)
from the hidden file system and calls the driver’s entry point.
Replacing original “kdcom.dll” with a malicious DLL allows the
bootkit to achieve two aims: to load the bootkit’s driver, and to
disable kernel-mode debugging facilities.
In order to replace the original kdcom.dll with the malicious DLL, it
is necessary on operating systems from Windows Vista onwards to disable
kernel-mode code integrity checks: otherwise winload.exe will refuse to
continue the boot process, and will report an error. The bootkit turns
off code integrity checks by instructing winload.exe to load the kernel
in pre-installation mode. This is achieved when bootmgr reads BCD from
the hard drive by replacing BcdLibraryBoolean_EmsEnabled (encoded as
16000020 in BCD) element with BcdOSLoaderBoolean_WinPEMode (encoded as
26000022 in BCD) in the same way as it spoofs kdcom.dll:
Figure 6 – Enabling Preinstallation Mode
BcdLibraryBoolean_EmsEnabled is an inheritable object indicating
whether global emergency management services redirection should be
enabled, and is set to “true” by default. The bootkit turns on
pre-installation mode for a while and disables it by corrupting the
/MININT string option in the winload.exe image while reading winload.exe
image from the hard drive:
Figure 7 – Subverting the /MININT Option
Winload.exe uses the /MININT option to notify the kernel that
pre-installation mode is enabled. As a result of these manipulations,
the kernel receives an invalid IN/MINT option and continues
initialization normally, as if pre-installation mode wasn’t enabled. The
process of loading the bootkit on the Windows Vista operating system is
shown in figure 25.
Figure 8 – Process of Loading the Bootkit in Windows Vista OS
Bypassing kernel-mode driver signature check
For the 64-bit version of Microsoft Windows Vista and later,
kernel-mode code signing policy requires that all kernel-mode drivers
must be signed, otherwise the driver won’t be loaded. Until now that was
the major obstacle to creating a fully operational kernel-mode rootkit
for 64-bit operating systems.
The bootkit takes quite an efficient approach to bypassing this
policy. It penetrates into kernel-mode address space at the earliest
stage of system initialization and loads its drivers without using any
of the facilities provided by the operating system. In other words it
performs the following steps:
- reads the driver image from the hidden file system;
- allocates memory buffer in kernel-mode address space for the driver;
- applies relocations and properly initializes import address tables;
- executes driver’s entry point;
- the driver’s code creates an object of type DRIVER_OBJECT by calling the undocumented function IoCreateDriver.
After these steps the rootkit’s driver is loaded into kernel-mode address space and is fully operational.
Booting UEFI Firmware
If the system’s firmware is compliant with the UEFI specification,
the boot process is handled differently to the way in which BIOS
firmware handles it. When the system starts up, the firmware stored in
NVRAM reads BCD which is also located in NVRAM, and based on the
available options, proceeds to execute winload.exe or winresume.exe. As
we can see here, the MBR code is not executed at all, while BCD is read
from nonvolatile RAM but not from the disk, so the bootkit fails to load
on systems with such firmware.
Conclusion
In this research we focused on the most interesting and exceptional
features of the Win32/Olmarik bootkit. Special attention was paid to the
bootkit functionality which appeared in TDL4 and enabled it to begin
its launch process before the OS is loaded, as well as its ability to
load an unsigned kernel-mode driver — even on systems with kernel-mode
code signing policy enabled — and bypassing kernel-mode patch protection
mechanisms. These characteristics all make TDL4’s a prominent player on
the malware scene.
Appendix: Network activity log from ESET TDL4 tracking system
21/02/2011 20:50:06 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=https://01n02n4cx00.com/command|noname|40379|0|0.03|0.15|5.1 2600 SP3.0|en-us|iexplore|0|0|57989841,P2=(null),P3=00C3FEB4,P4=00C3FEA8,P5=(null),P6=noname
21/02/2011 20:50:29 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=NO,FILEDLL=NO
21/02/2011 20:57:06 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=http://z0g7yalil0.com/clk=2.1&bid=noname&aid=40379&sid=0&rd=0,P2=Accept-Language: en-us,P3=00C7FE14,P4=00C7FE10,P5=(null),P6=(null)
21/02/2011 20:57:07 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=C:\tdl4\21_02_2011_20_57_007_buf.txt,FILEDLL=NO
21/02/2011 21:00:29 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=https://01n20n4cx00.com/command|noname|40379|0|0.03|0.15|5.1 2600 SP3.0|en-us|iexplore|0|0|57989841,P2=(null),P3=00C3FEB4,P4=00C3FEA8,P5=(null),P6=noname
21/02/2011 21:00:52 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=NO,FILEDLL=NO
21/02/2011 21:08:45 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=http://z0g7yalil0.com/clk=2.1&bid=noname&aid=40379&sid=0&rd=0,P2=Accept-Language: en-us,P3=00C7FE14,P4=00C7FE10,P5=(null),P6=(null)
21/02/2011 21:08:45 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=C:\tdl4\21_02_2011_21_08_045_buf.txt,FILEDLL=NO
21/02/2011 21:10:52 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=https://1l1i16b0.com/command|noname|40379|0|0.03|0.15|5.1 2600 SP3.0|en-us|iexplore|0|0|57989841,P2=(null),P3=00C3FEB4,P4=00C3FEA8,P5=(null),P6=noname
21/02/2011 21:11:16 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=NO,FILEDLL=NO
21/02/2011 21:21:16 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=https://zz87ihfda88.com/command|noname|40379|0|0.03|0.15|5.1 2600 SP3.0|en-us|iexplore|0|0|57989841,P2=(null),P3=00C3FEB4,P4=00C3FEA8,P5=(null),P6=noname
21/02/2011 21:21:18 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=NO,FILEDLL=NO
21/02/2011 21:31:18 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=https://xx87lhfda88.com/command|noname|40379|0|0.03|0.15|5.1 2600 SP3.0|en-us|iexplore|0|0|57989841,P2=(null),P3=00C3FEB4,P4=00C3FEA8,P5=(null),P6=noname
21/02/2011 21:31:41 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=NO,FILEDLL=NO
21/02/2011 21:36:16 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=http://z0g7yalil0.com/clk=2.1&bid=noname&aid=40379&sid=0&rd=0,P2=Accept-Language: en-us,P3=00C7FE14,P4=00C7FE10,P5=(null),P6=(null)
21/02/2011 21:36:16 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=C:\tdl4\21_02_2011_21_36_016_buf.txt,FILEDLL=NO
21/02/2011 21:41:41 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=https://zz87lhfda88.com/command|noname|40379|0|0.03|0.15|5.1 2600 SP3.0|en-us|iexplore|0|0|57989841,P2=(null),P3=00C3FEB4,P4=00C3FEA8,P5=(null),P6=noname
21/02/2011 21:41:44 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=NO,FILEDLL=NO
21/02/2011 21:51:44 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=https://01n02n4cx00.com/command|noname|40379|0|0.03|0.15|5.1 2600 SP3.0|en-us|iexplore|0|0|57989841,P2=(null),P3=00C3FEB4,P4=00C3FEA8,P5=(null),P6=noname
21/02/2011 21:52:09 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=NO,FILEDLL=NO
21/02/2011 21:55:27 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=http://z0g7yalil0.com/clk=2.1&bid=noname&aid=40379&sid=0&rd=0,P2=Accept-Language: en-us,P3=00C7FE14,P4=00C7FE10,P5=(null),P6=(null)
21/02/2011 21:55:29 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=C:\tdl4\21_02_2011_21_55_029_buf.txt,FILEDLL=NO
21/02/2011 22:02:09 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=https://1l1i16b0.com/command|noname|40379|0|0.03|0.15|5.1 2600 SP3.0|en-us|iexplore|0|0|57989841,P2=(null),P3=00C3FEB4,P4=00C3FEA8,P5=(null),P6=noname
21/02/2011 22:02:32 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=NO,FILEDLL=NO
21/02/2011 22:12:32 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=https://zz87ihfda88.com/command|noname|40379|0|0.03|0.15|5.1 2600 SP3.0|en-us|iexplore|0|0|57989841,P2=(null),P3=00C3FEB4,P4=00C3FEA8,P5=(null),P6=noname
21/02/2011 22:12:35 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=NO,FILEDLL=NO
21/02/2011 22:16:55 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=http://z0g7yalil0.com/clk=2.1&bid=noname&aid=40379&sid=0&rd=0,P2=Accept-Language: en-us,P3=00C7FE14,P4=00C7FE10,P5=(null),P6=(null)
21/02/2011 22:16:56 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=C:\tdl4\21_02_2011_22_16_056_buf.txt,FILEDLL=NO
21/02/2011 22:22:35 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=https://10n02n4cx00.com/command|noname|40379|0|0.03|0.15|5.1 2600 SP3.0|en-us|iexplore|0|0|57989841,P2=(null),P3=00C3FEB4,P4=00C3FEA8,P5=(null),P6=noname
21/02/2011 22:22:57 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=NO,FILEDLL=NO
21/02/2011 22:29:27 SEND: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,P1=http://z0g7yalil0.com/clk=2.1&bid=noname&aid=40379&sid=0&rd=0,P2=Accept-Language: en-us,P3=00C7FE14,P4=00C7FE10,P5=(null),P6=(null)
21/02/2011 22:29:27 RECV: PID=820,MODULE=C:\WINDOWS\System32\svchost.exe,FILEBUFFER=C:\tdl4\21_02_2011_22_29_027_buf.txt,FILEDLL=NO
Incoming search terms:
|