Advanced Win2k rootkit Detection Technology
(Perform Path Analysis)
Original article: http://www.blackhat.com/presentations/bh-usa-03/bh-us-03-rutkowski/bh-us-03-rutkowski-paper.pdf
Author: Jan Krzysztof rutkoski
Translation: mslug
(For details about the format, refer to the original image .)
Abstract: This article describes a new technology for detecting the kernel and user-level rootkit. this technology uses the single-step execution mode of the processor to determine the number of commands executed in the system kernel and DLL to detect rootkit and backdoor. it also discusses its code implementation in Win2k.
-- Background knowledge
An important question in the field of computer security is how to determine whether a given host has been intruded. The following two tasks have become very difficult:
1. Attackers can exploit unknown vulnerabilities to access the system.
2. after entering the system, intruders can install rootkit and webshells to hide themselves (for example, hiding processes, communication channels, files, etc ). this article will focus on rootkit detection in the Win2k system.
-- Problems in traditional rootkit Detection Technology
Traditional rootkit detection programs (which we often see in UNIX systems) can only detect known rootkit (which makes it look like an anti-virus program) or scan for some internal-core storage. for example, Linux has some tools to scan the syscall table in the kernel. this is obviously not good, because there are many rootkits that do not change syscall table, and similar rootkits can be developed in Win2k.
Should the detection program still scan the kernel code space? In this way, we have a tripwire running in kernel mode. but this is not good enough, because in most operating systems, we can write kernel-level rootkit that does not change SST (syscall table) or code. there are many function pointers that can be hooked in the system (for example, see [2]).
In my opinion, the storage scan technology will never end rootkit detection, mainly because we cannot determine the specific monitoring storage area.
How can we detect intruders in our system?
First, we divide the technology used in rootkit into two categories:
* You can hide an object (such as a running process) and
* Change the kernel execution path (for example, hook up the kernel functions that are responsible for enumeration of active processes) to achieve the same purpose.
-- Modify the rootkit of the System Data Structure
There are not many rootkits. interesting examples include Fu rootkit (see [3]). You can hide a process by deleting the process object on the psactiveprocesslist chain in the kernel. zwquerysysteminformation and other functions cannot discover these hidden processes. but at the same time, because the windows thread DISPATCHER (dispatcher, schedcher) uses another data structure, these "hidden" processes can still run (allocated to CPU usage time ). the Windows Thread dispatcher uses the following three data structures (Note 1:
* Pkidispatcherreadylisthead
* Pkiwaitinlisthead
* Pkiwaitoutlisthead
The last two threads are in the "Waiting" status. They are slightly different, but they are not important to us.
From the above information, we can find a method to detect hidden processes and read the data structure used by the thread dispatcher, instead of psactiveprocesslist.
When detecting rootkit, we should try to touch the underlying kernel data structure.
Note that it is impossible to delete the process to be hidden from the chain used by the thread dispatcher, because the hidden process will not be allocated the CPU usage time.
-- Change the rootkit of the execution path
This type of rootkit is widely used. they achieve the goal by modifying or adding commands in the kernel or system DLL. the problem with detecting this type of rootkit is that we don't know where the rootkit has made those changes. it can hook up the functions in the DLL, the system service table, change the content of the kernel function or modify some strange function pointers in the kernel.
-- Execution Path Analysis)
EPA is concerned with the fact that if an intruder hides some objects by modifying the execution path, the system will run some redundant commands when calling some typical system and library functions.
For example, if an intruder modifies zwquerydirectoryfile () and zwquerysysteminformation () to hide files and processes, these system functions will execute more commands than clean systems. whether the intruders hook up or add JMP commands to the Code, or any other method. the reason why the command is added is that the rootkit must perform its tasks (in this example, the files and processes are hidden ).
However, Windows 2000 kernel is a very complex program. Even in a clean system, some system functions run different numbers of commands each time. however, we can use statistics to solve this problem. but first, we need a method to determine the number of commands ......
-- Instruction counter implementation
The single-step execution mode is a good feature of Intel processors. We can use it to count commands. when the processor is in this mode, the system generates a debug exception (# dB) every time a command is executed ). to enter this mode, you need to set the TF bit in the eflags register (see [6]).
When the int command is executed, the processor automatically clears the TF bit and switches the permission. this means that if you want to count commands in kernel mode, you must set the TF bit at the beginning of the interrupt handler. because we will determine the number of commands in some system services, and it will be very effective to hook the interrupt vector 0x2e, that is, the system service calling door in Windows 2000.
However, the number of commands running at ring3 should also be measured because rootkit in user mode exists. you only need to set the TF bit once in user mode. The processor automatically restores the bit when it returns from the kernel.
The above counting method is implemented through the kernel drive. 2. After the driver is loaded, connect IDT 0x1 and 0x2e. to interact with user-level programs. A user-level program calls a specific system to switch the counter.
-- Some Tests
We can use the method described in the previous section to determine the number of commands executed in any system service.
For example, to check whether someone tries to hide any file, we can start a simple test:
Pfstart ();
Findfirstfile ("C: // winnt // system32 // drivers", & findfiledata );
Int res = pfstop ();
If rootkit hides any file, the number of commands executed is greater than that of the clean system.
If you run this test for hundreds of times and calculate the average number of executed commands, we will find that this value is very uncertain. considering the complexity of Win2k, this is not surprising. however, for our purposes, this phenomenon is unacceptable. however, if we use a bar chart to show the frequency distribution of the obtained values, we will find an obvious high frequency. the values shown in 4 and 5 remain unchanged even when the system load is large. it is hard to explain this surprising phenomenon, probably because after hundreds of calls to the same system service in a loop, the buffer related to the system service will be filled with a fixed value.
Suppose someone has installed the rootkit of the hidden file. If we repeat the test and draw the corresponding bar chart, we will find that the frequency is shifted to the right, because the rootkit needs to hide the file.
In the current code implementation, only a few tests were conducted, including typical services such as file system reading, enumeration process, enumeration registry entry, and socket reading.
These tests will effectively detect the famous ntrootkit (see [1]) or the recently popular hacker defender (see [4]), including its own webshells, there are also many other backdoors. but some better backdoors should be detected and some new tests should be added.
-- False alarm and execution Path Tracking
Although the detection of high frequency helps us to deal with the uncertainty of the system, sometimes we find that the value obtained from the test has a small difference, generally not greater than 20.
Sometimes this is a very serious problem, because we cannot determine that the extra commands mean being infiltrated or just a normal error.
To solve this problem, we use the execution path record mode. compared with the single EPA mode, the system adds a record of the execution path (including the address and running command). First, the system records the normal execution path, the diff file will be generated for each operation in the future (comparison between the normal system and the current system ).
We should use a good anti-compiler to analyze the differences to determine if they are suspicious. Figure 6 is an example of a diff file.
The current diff file only records the instruction address. Different results of the two tests may be saved as PE files in the future and analyzed using tools such as IDA.
-- Detect changes in "offset-in-the-code"
Imagine a rootkit, which is basically the same as the Fu rootkit (see [3]) mentioned above, but not removed from the psactiveprocesslist, but from the data structure used by the dispatcher. I said that would not be possible, because the hidden process will not allocate the running time ......
However, rootkit can also change the data structure address (offset) used in the dispatcher code. In other words, it is used to use different linked lists. however, only the dispatcher uses this "new" linked list, while the system still uses the "old" linked list elsewhere ...... (see figure 7 ).
Although this technology will not change the number of executed commands, we can still detect it, but we need to further improve the existing tool. This function is not yet implemented yet, but it should not be very difficult.
-- Defense against EPA
We can think of some methods that can cheat the EPA detection tools. First, we can divide them into two types.
1. spoofing for specific tools
2. General attacks against EPA Technologies
First, we will consider general attack methods and how to prevent such attacks. Then we will discuss attacks against specific tools and how to prevent them through polymorphism.
-- General attacks against EPA Technologies
First, a malicious program can hook up IDT Entry 1 containing the debug handler address, so that the number of running commands will be suspended. when it completes the work, restore the IDT Entry 1. in this way, the number of commands executed in the rootkit will not be recorded.
We can use intel's error register to prevent such attacks. the IDT Entry 1 can be written using the dr0 and DR1 registers. to prevent rootkit from writing JMP commands to the beginning of the debugging handler, read protection is also required. in other words, we do not want rootkit to find the address of the debugging handler. however, reading protection for the IDT entry is not feasible, and the system will display a blue screen. but there is a simple solution, that is, adding an additional layer. see Figure 9.
There is also an attack method. When rootkit is running, it clears the TF bit and restores the TF bit when the malicious operation is completed, in this way, the detection tool can only find that the number of running commands is slightly different from that of the normal system.
In addition, the rootkit can also check the TF bit. If it finds it to be tracked, no malicious operation is performed. this behavior does not affect the normal operation of rootkit, because only the process being detected is set to TF bit.
We can prevent this attack. We should note that before running every system command, we will run our troubleshooting program. The following is a simple pre-defense method:
If the debugging handler finds that the previous running command is pushf (push the eflags Register into the stack), run the following operation.
And [esp], 0 xfffffeff;
And clear the TF bit. Similarly, if the next command is popf (the value for loading eflags from the stack), run the following operation.
Or [esp], 0x100;
And set the TF bit. In this way, the rootkit cannot change the TF bit.
This prevention is almost enough, but not enough. rootkit can still be traced in the following ways:
Settfbit ();
If (checktfbit ()! = 1 ){
// We are traced!
}
Therefore, we need to modify the anti-detection operations so that it can record whether the TF bit has been changed by Rootkit (such as adding a tfbitset variable ).
Popf/pushf is not the only command to access the eflags register. Other commands such as iret/INT can also be [NOTE 2]. Therefore, detection of these commands must be added.
The protection part of the eglags Register has not been implemented yet. Part of the reason is that this type of attack can be found through analysis of the diff file, but the corresponding code will be added later.
-- Attacks against specific tools
If an attacker knows everything about a specific detection tool, there are many spoofing methods. For example, he can change the variable that saves the number of commands.
However, these attacks are highly targeted. If there are many different (or not a single version) EPA-type tools, such attacks will not be effective.
Of course, we still hope to prevent such attacks. The powerful multi-state code generator may be the only method. When the Administrator installs the detection tool, it will generate a unique kernel driver and test program.
The multi-state code generator is not implemented yet.
-- Related work
As described at the beginning of this article, I have not found any methods for detecting rootkit, not based on storage scanning.
The EPA technology is not limited by OS. in Linux, I have also implemented a related tool. In parameter 5, we have detailed the tool and simple code implementation.
References
[1] Greg Hoglund, et al, rootkit home, telnet: // rootkit.com,
[2] Palmers, sub proc_root quando sumus, phrack magazine, issue 58,200 1.
[3] fuzen_op, Fu rootkit, telnet: // rootkit.com,
Holy Father, hacker defender home, http://rootkit.host.sk,
[5] Jan rutkoski, execution path analysis, phrack magazine, issue 59,200 2.
[6] IA-32 intel architecture software developer's manual, vol1-3.
Note 1: I believe these three linked lists contain all the threads in the system, but further research is required.
NOTE 2: All commands that interact with the eflags register are listed on parameter 6.