分类: 网络与安全
2011-08-19 17:21:46
In our previous article, “”, we looked at the distribution and installation mechanisms used by TDL4. For the second part of the series, we look in more depth at the internals of the malware, starting with the user-mode implementation of the bootkit’s bot functionality.
1 The BotTDL4 injects two modules into processes in the system, cmd.dll and cmd64.dll, as described in corresponding subsections below. Firstly, though, we look at the configuration file cfg.ini, which stores configuration information within the hidden file system. The general structure of the file is essentially the same as in the TDL3/TDL3+ rootkit but includes some additions and modifications:
According to cfg.ini, cmd.dll is injected into each 32-bit process in the system in which the kernel32.dll library is loaded. However, it is actually only able to operate inside processes where the executable names contain the following substrings:
svchost.exe started with netsvcs parameter |
explo |
firefox |
chrome |
Opera |
safari |
netsc |
avant |
browser |
mozill |
wuaclt |
cmd.dll might perform a number of tasks:
All the communication between the bot and C&C is carried over the HTTP/HTTPS protocols. There are several types of C&C servers with which the bot can communicate:
Types of C&C servers | Description |
command servers (“srv” key in cfg.ini) | intended to send commands to bots |
pservers ( “psrv” key in cfg.ini) | intended to send URLs that should be opened in browser |
click servers (“csrv” key in cfg.ini); | intended to send URLs with which the clicker should work |
wservers (“wsrv” key in cfg.ini) | intended to substitute result of search providers |
kservers (“ksrv” key in cfg.ini | used to inject malicious “iframes” into HTML documents. |
The data transmitted to and from C&C over HTTP/HTTPS are encrypted with the RC4 cipher, where the C&C server host name is used as the key, and are then encoded with BASE64 encoding (as shown in figure 1). In addition to the encryption, in some cases the data are mangled after encoding. Strings generated according to certain rules (described in the appendix) are prepended and appended to the data. This last measure is intended to avoid detection by IDS (Intrusion Detection Systems).
Figure 1 – The Format of Requests to the C&C Server
1.2.1 Communication with command serversThe bot periodically requests commands from C&C servers. The configuration file contains parameters that determine how frequently the bot should connect to these servers:
Parameters | Description |
knt | Stores the time when the command servers were last accessed (in seconds since the year 1970) |
delay | time interval expressed in seconds between requests to the list of command servers |
retry | time interval in seconds between requests to command server within the list |
The request to a command server prior to encryption and encoding looks like this:
Parameters | Description |
bid | bot identifier (assigned by C&C or “noname” by default) |
aid | affiliate identifier |
sid | affiliate sub account identifier |
tdl_ver | version of the bootkit (0.03) |
bot_ver | version of cmd.dll/cmd64.dll (0.169) |
os_ver | version of operating system (5.1 2600 SP3.0) |
locale | current locale of the system |
browser | default browser of a user |
tdl_build | build date of the bootkit |
tdl_install | install date of the bootkit |
rnd | random number |
The command server replies with a list of commands separated by semicolons. Each command is formatted as follows
where command_name can be either cmd or name of an executable in the hidden file system of the bootkit. method_name can take the following values:
Command | Description |
DownloadCrypted | download encrypted binary, decrypt it (RC4 cipher with bot_id as a key),and if its name has “.dll” extension then load it into address space of the current process |
DownloadCrypted2 | download encrypted binary, decrypt it (RC4 cipher with custom key), and if its name has “.dll” extension then load it into address space of the current process |
DownloadAndExecute | download executable and run it in a new process |
DownloadCryptedAndExecute | download encrypted executable, decrypt it (RC4 cipher with bot_id as a key) and run it in a new process |
DownloadCryptedAndExecute2 | download encrypted executable, decrypt it (RC4 cipher with custom key) and run it in a new process |
Download | download executable and load it into address space of the current process |
ConfigWrite | write a string in cfg.ini |
SetName | assign name to the bot |
Name of exported function | Name of exported function from command_name executable to call |
The method parameters can be of the following types:
Here is an example of a set of commands received from the C&C:
C&C commands | Example of parameters |
cmd.ConfigWrite | (‘cmd’,'delay’,’7200′) |
cmd.ConfigWrite | (‘cmd’,'srv’,'com/;com/;com/;com/;com/’) |
cmd.ConfigWrite | (‘cmd’,'wsrv’,'com/;com/;com/;com/;com/’) |
cmd.ConfigWrite | (‘cmd’,'psrv’,'com/’) |
cmd.ConfigWrite | (‘cmd’,'csrv’,'com/’) |
cmd.DownloadCrypted | (‘’,'cmd.dll’) |
cmd.DownloadCrypted | (‘’,'bckfg.tmp’) |
cmd.DownloadAndExecute | (‘’) |
Once every 10 minutes the bot scans the “[tasks]” section of the configuration file to retrieve tasks for execution. The tasks are encoded as follows
Tasks | Description | |
file_name | name of the file in the hidden file system or random number | |
task_code | 1 | download binary from URL determined by para2, and decrypt with para1 key (if specified) |
2 | download binary from URL determined by para2, and decrypt with para1 key (if specified), then run as standalone application | |
3 | delete file with file_name name | |
retry_count | maximum number of attempts to execute the task. Each attempt this value is decremented and when reaches zero the task is deleted | |
para1, para2 | parameters of the task |
The module cmd.dll implements clicker functionality. It requests links from the servers listed under csrv key in cfg.ini file by using the URLs formatted as:
where bot_id, aff_id, sub_id, install_date have the same meaning as the corresponding values in communication with command server. The request is encoded and mangled. As a reply cmd.dll receives list of the values:
Parameters | Description |
x_url | target URL |
x_ref | Referrer |
dword_1,dword_2 | unsigned integers specifying delay between receiving data from click servers and going to target URL |
The clicker’s engine is implemented by means of the “WebBrowser” ActiveX control. For this purpose cmd.dll creates a window class with the name “svchost”. For each URL received from the click-servers the bot creates a window of class “svchost” with the name “svchost-XX”, where XX corresponds to the current thread ID passing target URL as lpParam to the CreateWindowEx function.
Figure 2 – Creating a New WIndow for Clicker
When the WindowProc function of the registered window class receives a WM_CREATE message, it creates the “WebBrowser” ActiveX control in the window and sets up properties: Silent – False, Visible – True. Then it navigates to the target URL by calling the Navigate method defined in the IWebBrowser2 interface with the following flags:
Then the clicker waits for the NavigateCoplete2 event, signifying that at least part of the document has been received from the server, and that the document viewer has been created. At this point the clicker compares the current URL with the one requested and if they match (i.e. the request has not been redirected) it emulates surfing the web:
In order to intercept and modify the data exchanged over the network the bot hooks several functions from the Microsoft Windows Socket Provider mswsock.dll:
By hooking the WSPSend routine the bot is able to intercept all the outgoing network traffic generated by the process into which cmd.dll is injected. Prior to forwarding the intercepted data to the destination host, the bot looks for the “windowsupdate” string in the data buffer. If it finds the string, then it immediately returns the error WSAENETRESET (normally signifying that the connection has been broken due to the remote host resetting), thereby disabling the Windows Update service.
Otherwise it calls the original WSPSend routine and if the operation has been completed successfully, it parses the outgoing data buffer to determine whether this is an HTTP request. If so it gets the following parameters from the header:
Depending on the values these parameters may take, and information stored in additional files in the hidden files system, the bot performs the following actions:
All these operations are performed in the WSPSend hook and stored in the binary tree data structure to be used in the WSPRecv hook.
WSPRecvIn the WSPRecv hook the bot actually replaces the data obtained from the destination with information it generates in WSPSend hook.
WSPCloseSocketIn the WSPCloseSocket hook the bot releases all the resources allocated to handling and interception of data for a specific connection.
1.3 Cmd64.dllCmd64.dll is the payload to be injected into 64-bit processes only. It is a limited version of cmd.dll and its functionality is restricted to communications with command servers and executing tasks (without hooking mswsock.dll and clicker). These communications functions, however, are fully equivalent to the corresponding functions in cmd.dll.
1.4 TDL4 TrackerDuring our investigation of the malware, a TDL4 tracking system has been implemented which monitors and logs all the communication between the bot and C&C servers. The system is able to intercept and decrypt all kinds of messages, even those transmitted over HTTPS, which allows us to gain access to all commands, updates and additional downloaded modules. The output of the system is presented as an appendix to the third article in this series: “TDSS: Bootkit on the Other Foot.” However, here is an example of the kind of detail it shows.
In this section we describe the kernel-mode components of the bootkit, namely, drv32.sys and drv64.sys, which correspond to the x86 and x64 operating systems. The kernel-mode drivers constitute the most important part of the bootkit and execute the following tasks:
In general the x86 and x64 binaries of the TDL4 are quite similar, and indeed are compiled from a single set of source files. Unlike the TDL3/TDL3+ kernel-mode component, which is stored in the hidden file system as a piece of code (independent of the base address), TDL4′s kernel-mode components are valid PE images.
2.1 Self-defense 2.1.1 Kernel-mode hooksThe bootkit conceals its presence in the system by setting up hooks to the storage miniport driver, in the same way as its predecessor TDL3/TDL3+. The hooks enable the bootkit to intercept read/write requests to the hard drive and thereby counterfeit data being read or written.
Figure 3 represents the relationship between the miniport device object and its corresponding driver object after the bootkit sets up the hooks which modify the StartIo field of the target device’s driver object and the DriverObject field of the target device object. The bootkit also excludes the target device from the driver object’s linked list.
After these manipulations, all the requests addressed to the miniport device object are dispatched by the corresponding handlers of the bootkit’s driver object. The bootkit controls the following areas of the hard drive:
Figure 3 – The Bootkit’s Kernel-mode Hooks
The bootkit contains code that performs additional checks to prevent the malware from being detected, deactivated or removed. When the bootkit’s driver is loaded and properly initialized it queues WORK_QUEU_ITEM which performs the following tasks at one-second intervals:
The bootkit also takes care of cleaning up the traces it left during the loading of the bootkit at boot time (see the final article in this series, “TDSS: Bootkit on the Other Foot). Specifically:
In order to covertly store its malicious components, the bootkit implements a hidden file system. The general structure of the file system remains the same as in the case of TDL3/TDL3+: the bootkit reserves some space at the end of the hard drive, regardless whether this space is being used by operating system.
The bootkit’s file system is maintained by a set of device objects. Here we can see a volume device object representing a logical volume (partition) hosting TDL4′s files, and a so called physical device object responsible for handling IO requests from the bootkit’s payload. These two device objects are connected with each other by means of a volume parameter block – a special system structure linking a volume device object with the corresponding physical device object. This enhancement appeared for the first time when the TDL3+ version of the rootkit was released.
Figure 4 – TDL4 File System Device Relationship
As we can see from the figure above, the volume device object is created as a device object belonging to the \Driver\PnpManager driver object, so that all the requests are handled by this driver. In order to conceal the volume, the bootkit removes the device object from PnpManager’s device object linked list.
The hidden file system is configured so that TDL4′s components access files stored on it using the following paths:
– for user-mode components
and
– for kernel-mode components.
Here we can see that TDL4 appends 8 random hexadecimal digits to the volume device object, and these are generated on loading of the bootkit. If this condition is not met, a STATUS_OBJECT_NAME_INVALID error code is returned.
2.2.1 TDL4 file system layoutTDL4 uses the same technique for allocating space on a hard drive for its file system as its predecessor; namely, it starts at the last but one sector of the hard drive and grows towards start of the disk space.
Figure 5 – Location of the Hidden File System on Disk
There are some changes in the layout of the file system compared to the TDL3 file system layout. Each block of the file system has the following format:
Here is the format of the root directory:
The bootkit protects the contents of its file system by encrypting its blocks. As with TDL3 it uses the RC4 encryption algorithm, which is a stream cipher with varying key length. Unlike TDL3, where the “tdl” string is used as a key, TDL4 uses the 32-bit integer LBA of the sector block being encrypted. (You may recall that TDL3+ encrypts its file system by XORing contents with a single byte incremented with each XOR operation).
2.3 Injecting payload into processesThe way TDL4 injects its payload into processes in the system hasn’t changed significantly since the previous version of the rootkit, but as it wasn’t described in our report on TDL3 (), we are going to address it here.
To track creation of a new process in the system, TDL4 registers the LoadImageNotificationRoutine and waits until the “kernel32.dll” system library is mapped into memory. Once that happens, the bootkit obtains the addresses of exported symbols LoadLibraryEx, GetProcAddress, VirtualFree and queues a special kernel-mode APC ,which in turn queues a work item performing injection of the payload. The work item executing in the context of the “System” process attaches itself to the target process by calling the KeStackAttachProcess system routine. When the address space of the process is switched to that of the target process, the bootkit maps payload to it and applies relocations. The next step is to allocate a buffer in the user-mode address space of the process and fill it with the path to the payload, and code initializing the import address table and calling the payload’s entry point. When this is done the bootkit queues the user-mode APC executing user-mode code.
To be precise the user-mode code initializes the import address table of the executable and calls its entry point, passing as parameters the following values:
If the entry point returns zero then the code frees memory allocated for the payload image and overwrites the path to the payload in the user-mode buffer with zeros.
The following figure illustrates the overall process.
Figure 6 – Process of Injecting Payload into Processes in the System
2.4 Comparison with TDL3/TDL3+Compared to its predecessors (TDL3 and TDL3+) there are some significant changes in the kernel-mode components of the bootkit which affect the following aspects of its work: kernel-mode code layout, surviving a reboot, self-defense against removal from the system, and supported platforms. These points are summarized in the table below.
Comparison of TDL kernel-mode components
TDL3/TDL3+ | TDL4 | |
Kernel-mode code representation | Base independent piece of code in hidden file system | PE image in the hidden file system |
Surviving after reboot | Infecting disk miniport/random kernel-mode driver | Infecting MBR of the disk |
Self-defense | Kernel-mode hooks, registry monitoring | Kernel-mode hooks, MBR monitoring |
Injecting payload into processes in the system | tdlcmd.dll | cmd.dll/cmd64.dll |
x64 support | - | + (drv64) |
In the of the series, we will discuss the normal boot process and how the bootkit exploits it.
Appendix: Mangling algorithm in python