Friday, February 21, 2014

Monitoring Windows OS scheduling events in a noninvasive way with Hardware Virtualization technology (Anti-Rootkit)

A rootkit is a stealthy type of software, typically malicious, designed to hide the existence of itself or certain processes/programs from normal methods of detection and enable continued privileged access to a computer. However, even though the malicious process/program can be invisible to users, internally it must have to get time slices for running, otherwise if it has no chance to get scheduled by CPU, such an existence is meaningless for malware author. 

This article provides a solution to detect the malware and inspect its behaviors by monitoring each OS thread scheduling event.

This article is organized into two parts: 1) explain Windows scheduling things and related data structures; 2) then explain how to get notified in underlying VMM software without any changes to guest Windows OS.

Windows thread scheduling

Thread (rather than Process) is the fundamental schedulable entity in the Windows operating system. It is represented by a _ETHREAD structure that includes a _KTHREAD structure. For every thread in the system there is an ETHREAD structure, including threads in the System Idle Process. The ETHREAD.Tcb field (Thread Control Block)/KTHREAD is used to store information related to thread scheduling. Every process stores a list of ETHREAD structures, representing all the threads running in that process, in the TheadListHead field of the _EPROCESS structure.

In a SMP system, each processor (CPU) has a unique KPCR (Kernel Processor Control Region) structure, which contains per-CPU information shared by the kernel and the HAL. In this structure, there is a Prcb field, contains an embedded KPRCB structure that represents the Kernel Processor Control Block. And in this KPRCB structure, there is a field CurrentThread that pointers to the KTHREAD of current running thread on this processor. 

Here is the interesting thing, before scheduling to a particular thread for running, the OS scheduler will update the pointer field CurrentThread with that corresponding KTHEAD structure. Besides, in a 32bit Windows OS, the KPCR of the current CPU is always accessible at FS:[0] in kernel, while in a x64 Windows OS it is always at GS:[0] in kernel space.  Here below illustrates the relationship:

As long as we get the address of KTHREAD structure of particular thread, we can also get the address of ETHREAD structure, because the KTHRAD is embedded in (not pointed by) the ETHREAD structure, and KTHREAD is the first field of ETHREAD, the address of ETHREAD and KTHREAD is the same for a particular thread. Besides, we can also get the address of EPROCESS information structure by KTHEAD->Process for the process which that running thread belongs to. 

Once we get this process information, we can analyze it and check if it is a hidden malicious process for example by analyzing this process signatures. 

So now the question is how to get notified before a particular thread gets scheduled to run? The second part below explains one of implementations.

Monitoring thread scheduling events with debug register.

In order to monitor the changes to the field "PKTHREAD CurrentThread" in _KPRCB structure, one of approaches is presented in my previous blog for Debug Register usages. We can set the address of that field into one of DR0~DR3 registers, and configure the hardware breakpoint condition as WRITE triggering. Whenever the OS scheduler updates that field, a #DB exception will be generated by processor. If such an exception is configured by VMM to generate a VMexit, then the corresponding VMM exit handler will be invoked to handle this event. 

Now, the problem is how to get the address of that field "PKTHREAD CurrentThread". See the picture above, originally we must have to retrieve the segment base address for FS segment or GS segment. Fortunately, we can directly read the guest FS_BASE_MSR (one of Model Specific Registers, the index is 0xC0000100) on 32bit OS and GS_BASE_MSR (0xC0000101) on 64bit OS to get that base address value. After getting this address value, we can walk through the KPCR and KPRCB structure to get the address of that field "PKTHREAD CurrentThread". 

However, this solution might be only for academic/research or education purposes because it has some limitations, for example, all the data structures (KPCR, KPRCB, THREAD, ETHREAD) might be changed from OS version to version so it is not to walk through the data structure for all OS versions, it also may have compatibility issue with 3rd party software debugger because it must have to use one of debug registers, performance overhead might also be a problem because whenever a thread scheduling event occurs, there will be a #DB exception triggered. 

<The End>

No comments:

Post a Comment