In this report we would like to point out how the rootkit infects a system, how it operates and what kind of anti-reversing and anti-debugging techniques are in place. We will use several tools:
- ExeInfo PE
- IDA Entropy Plugin
- SysInternals Suite
- IDA Pro
- Immunity Debugger
It s not a Problem, if you don’t know these tools. We will explain their application to this malware analysis bit by bit. So, let’s start!
Two files were dropped – the first one was installed under HKLM\Software\Microsoft\Windows\CurrentVersion\Run. A second one was installed as a new userinit.exe provider to inject itself into csrss.exe just after a successful login attempt.
So, let s check a first file:
|Create Date (GMT)||2013-05-13 17:40:20|
The file named “defplogon.exe” was dropped and installed under HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run. This registry place is commonly used to autostart user-mode programs (like your favorite Instant Messaging applications). Thus, it’s also quite common for malware authors to use it as well. The trojan is binded together with Hyper Terminal binary to pump its size and steal manifest information. Binary pumping is a technique used by malware coders to increase the executable size in order to make it less suspicious.
By using Exeinfo PE by A.S.L, we were able to identify, that the executable binary was not packed and was compiled with MS Visual C++ 6.0/7.0:
Next, we gathered more information about this sample by checking PE header. We focused on: import and export tables, nuances inside Optional Header (like anti-debugging/anti-reversing tricks), section names, and the resource directory.
The following screenshot generated by CFF Explorer shows two additional non-standard sections named .data2 and .data3:
Optional header information seems legit. Address of EP points to the right section so far and the chosen subsystem looks like a normal, harmless Windows GUI application:
Also IAT looks pretty generic, so we assume that malware performs dynamic library loading using LoadLibrary() or something equivalent:
After these steps we wanted to get more information about the binary itself: Does it contain plaintext strings, maybe some private keys or interesting encrypted content? We used IDA Entropy Plugin to detect file entropy level:
To understand these results, we used the following assumptions:
4.941 – 5.258
Packed / encrypted executable
It’s good to remember that some simple encryption schemes – like ROT13 or XOR with a static key – do not provide bigger entropy levels (> 6.667). But first things first.
It’s obvious that .data2 and .data3 are not standard PE/COFF sections. Why do .data2 and .data3 have entropy levels equal to zero? Its easy to find out, we just need to provide graphs of these sections:
.data2 entropy graph:
It seems that these two sections were added by mistake and are not used in the whole malware.
After the initial PE file assessment we wanted to understand how this binary communicates with C&C, whether it contains some uber anti-reversing/anti-debugging strategies and its main purpose. We followed the malware analysis method first proposed by Lenny Zeltser (http://zeltser.com/reverse-malware/reverse-malware-cheat-sheet.html), but limited it to our current needs (just behavioral analysis):
- setup fresh VM with vulnerable Windows XP SP2 installation
- install all necessary tools including:
- SysInternals Suite (http://www.sysinternals.org)
- Capture-BAT (https://www.honeynet.org/node/315)
- API Monitor (https://www.rohitab.com/apimonitor)
- RegShot (http://sourceforge.net/projects/regshot/)
- WireShark (https://wireshark.org/)
- configure and run monitoring tools
- execute malware within the controlled environment
- gather results
- cleanup the environment
We configured API Monitor to monitor API calls performed by a malware sample using Remote Thread (Extended) method:
a. it tries to open a file handle to d:\s412412l (suspicious, perhaps some debug code):
b. it calls LoadIconW() several time (perhaps some problems with obfuscation engine):
c. it performs some anti-debugging trickery using NtQueryInformationProcess() to search for ProcessDebugPort and if its found, it dies trying to start a default error handler:
API Monitor had just given us superficial information. We then moved to the next phase of the behavioral analysis using a Capture-BAT tool developed by Honeynet. It works as a driver in the kernel space and is able to monitor most low-level stuff. We started it using the following command line which allows us to monitor file and network operations:
As we can see from this screenshot, the malware injects itself into the csrss.exe process, then terminates the parent thread. Next, it adds itself as a new userinit.exe provider and further adds a new registry value under HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\5\16CD25DD. The final step is to remove the original binary.
So, right now we have a good piece of information – however we lack information about network activity. To perform such analysis we used Capture-BAT’s generated PCAP file and Wireshark to observe all potential anomalies.
First it tries to access dyntic.com domain. The domain itself is currently down.
Right now we gathered information about domain names. Next, we would like to check for covert channel and packets content.
This malware uses normal HTTP and uses HTTP POST to deliver messages. It calls /smp/inx.php script which replies with a small GIF file:
As we can see, it pushes 004015D0 on the stack. Later it calls ret instruction. Ret transfers program control to return the address located on the top of the stack. Basic Return-Orientated Programming, hum?
In the body of the callback function we can see familiar calls to CreateFileA() with “d:\\s412412l” as an argument:
Next, it tries to open a specific mutex (6A57BEED). This mutex is created by the malware itself and is used to notify malware that the system is already infected, so another instance won’t infect it one more time:
This code looks like it is just a junk code which does nothing – registers are pushed using pushad and restored later using popad instruction after everything.
Several instructions later, just after the junk code, we can find another generic stuff: memory allocations, Resource Directory traversal, dropping artifact into previously allocated heap buffer. Boring. Let’s focus on the actual decryption function:
After returning from the decryption function we can observe that the malware dumps decrypted code directly into the memory and by using UnmapViewOfFile() it tries to change memory mappings on itself (this behavior is used to bypass some static AV scanners):
After a short analysis it looks like its a complete PE executable where it transfers the code execution. Here we stopped with this analysis and dropped memory area with a new PE executable, which we saved on disk as “new_sample.exe”.
Create Date (GMT)
By utilizing Exeinfo PE by A.S.L once again, we were able to identify, that the binary was compiled with Borland Delphi and is perhaps not protected by any external packer and/or protector:
Next, we gathered more information about this sample by checking PE header. We focused on: import and export tables, nuances inside Optional Header (like anti-debugging/anti-reversing tricks), section names, and resource directory.
Import Address Table looks a bit suspicious for a GUI application, because it contains only one entry to kernel32.dll and no direct links to GUI libraries (like GDI32.dll or USER32.dll):
By analyzing optional header we did not find anything uncommon from executable standards:
We can also see six section names generated by a Borland Delphi compiler:
The code begins with calls to some null function (null function is a function which does nothing but returns from its body) followed by a CreateThread():
which calls VirtualProtect() to change the protection of a memory region located at 00401D70 to PAGE_READWRITE. This memory contains preallocated buffer which is used by a next function.
When VirtualProtect() returns, the code lands in the routine which performs XOR operation on binary data to decode strings from the memory:
As we can see from above screenshot, several interesting strings occur in this small memory dump, most noticeable are those directly associated with registry and DLL files.
Another thing which can be also found on previous screenshot are command line arguments -autorun and -update.
But let’s focus on the main functionality. Several instructions later, we can observe a quite common behavior these days – acquisition of SeDebugPrivilege token. Malware does this to protect itself from various tools which help to remove malware from infected system. Tools like rootkit detectors commonly make use of this privilege to help locate and/or remove stubborn malware. By acquiring SeDebugPrivilege by the malware, these tools usually fail to run. Below is the screenshot which shows the whole process:
Next we can see some basic check which tries to figure out, if the current running process was executed under WoW64:
If the resulting value is positive, then the code takes another code path. But lets leave it for now – something interesting can be spotted here. The code loads ntdll.dll using LoadLibrary(), creates a file mapping in the memory, changes the page permission to PAGE_EXECUTE_READWRITE and finally it unmaps this memory file view:
This memory area is of course later used by a malware to execute malicious code by exchanging the original image with a decrypted one.
After finishing the previous operation the code once again checks for a specific mutex (in order to stop infecting the same system over and over again):
Later, another routine is used to check if the string “userinit.exe” can be found in the pathname. If so, it was executed just after WinLogon, so that it’s able to inject itself into “csrss.exe” process and to perform more anti-reversing tricks. But let’s talk about this a bit later. In order to bypass this check we simply modified the stack variable which points to userinit.exe string into new_sample.exe so the check can be bypassed.
Following by a call to CreateProcessA():
In order to debug this instance we changed new_sample.exe into notepad.exe, because later it is used as a template PE to unpack the rest of the executable.
Unfortunately here, we spotted some problem with Immunity Debugger. Our favorite debugger simply could not recognize memory maps of notepad.exe (yes, we attached it to the new notepad.exe process), so the analysis engine couldn’t work:
However, in order to keep everything simple we have found another way (implemented by the malware author :)).
Let’s go back a bit. What if the code could not find userinit.exe (or new_sample.exe in our case) in the pathname? The answer is straightforward – it will try to find and inject code into csrss.exe process in order to monitor and control system behavior. The function responsible for process searching is located at 0040162C:
First it creates a process list snapshot using CreateToolhelp32Snapshot() function, then it traverses this list starting with Process32First() by using Process32Next(). When it’s found the resulting PID is returned in EAX register. In order to move forward with analysis we change the resulting value stored in EAX into PID of notepad.exe started by another instance of Immunity Debugger (in our case PID value is 1748).
The code then performs a memory allocation within notepad.exe namespace using VirtualAllocEx() and injects string (“–” + pathname) using WriteProcessMemory():
After the successful injection we land in another function which this time performs more allocations and more injection (how come you can ask ;-). If everything is in place, it creates a new thread within notepad.exe process using CreateRemoteThread():
Immediately after returning from CreateRemoteThread() another instance of Immunity Debugger caught a new thread creation:
So we continued with our analysis using second debugger instance.
Here, Immunity Debugger has access to previously generated analysis database, so certain API functions are in place. We just need to understand what kind of information are gathered from infected machine, how botnet operates and what (if any) API functions are hooked (to monitor activity).
The code starts with dynamic loading of all the necessary libraries. Next it jumps into the function which decrypts strings in the memory. The decrypted strings can be seen on the screenshot below:
Several instructions later we can observe a call to the function which decrypts C&C DNS names in the memory. The resulting string array is shown below:
In this post report we went further with the trojan analysis – how it operates, how it injects itself into strategic system points and what kind of anti-reversing and anti-debugging techniques it uses. In the next report we will write more about the rootkit functionality.
Cheers and Happy Reversing!