AntiForensics techniques : Process hiding in Kernel Mode

Olivier Chatail Etude - Recherche, Forensics

Introduction

This article is the first iteration of a series introducing several malware techniques for both persistence and propagation.

Most of these techniques were discovered and disclosed several years ago by security researchers. The aim of this approach is to build a knowledge base on these technique’s system and forensics aspects.
Along with the article a proof of concept code can be retrieved on the CERT’s Github.
The knowledge base will be continuously improved with field experience of Devoteam CERT’s analysts.
This first article will treat the following aspects of DKOM process hiding :

  • Windows processes
  • Hiding with Direct Kernel Object Modification
  • Proof of concept
  • RAM detection with Volatility

This concept, introduced at a Black Hat USA’s talk in 2004, has been (and is still) employed by several kernel rootkits such as the famous FU-rootkit, developed by Jamie Butler (author of the talk).

Windows processes

The Windows kernel makes use of the EPROCESS structures to handle processes.

These are opaque structures: barely documented by Microsoft and not detailed by standard programming headers.

MSDN reference:EPROCESS (Windows Driver)

They can still be analysed via kernel debugging, using KD:

Retrieving an EPROCESS pointer with kd

Listing EPROCESS fields with kd

The structure has 207 fields in this example (Windows 10 64 bits).

Only three of them are relevant to explain the technique:

PID in kd

Executable name : ImageFileName.

A LIST_ENTRY structure : ActiveProcessLinks.

This list contains two links: Flink and Blink.

These links are interesting because they point to two other LIST_ENTRY structures belonging to the next process (Forwardlink) and previous process (Backlink).

ActiveProcessLinks example for three processes

All processes in a Windows system refer to each other via pointers in their ActiveProcessLinks structures. They make up a double chained list used by tools such as taskmgr.exe (task manager) or some SysInternals tools (e.g. procexp.exe).

Depiction of the inter-processes links

The double chained list is periodically checked to update processes display.

Hiding processes using Direct Kernel Object Modification

The DKOM technique hides a process unlinking  its own ActiveProcessLinks and linking the “previous” and “next” processes directly to each other.

Graphical representation of a DKOM attack

Getting the process (smss.exe in the example figure) out of the double chained list makes it invisible from tools relying on this list to display processes.

Unlinking a process does not affect its execution flow. The scheduler allocates computing time to threads unitarily, not to processes.

When modifying the malicious process’ ActiveProcessList, its Blink and Flink are modified to refer to their own structure. This is done to avoid any problem at the process’ exit. If Blink or Flink refers to an old or invalid memory address the kernel might raise an exception when trying to update the “neighbor” processes.

Double circular list of processes, hiding PID 64

 

Implementation

Comment on the Proof of Concept (first version)

The code on the CERT’s Github is a test driver, it was realized from a Windows example using the Kernel-Mode Driver Framework.

The driver configuration initialization was hooked using WDF_DRIVER_CONFIG_INIT().
The hook searches a process whose ImageFileName field is virus.exe and hides it using the DKOM technique.

This driver is not a functional Rookit (only tries to hide a process once at installation) and is only meant as an educational example.

The code makes heavy use of hardcoded memory offsets tested on Windows 10 64 bits (up to date on January 2nd, 2017). They are used to access directly EPROCESS fields and will probably not work at all on other Windows releases.

Figure 7 –Relevant EPROCESS MEMORY OFFSETS

Offsets shown above can be found in the first KD screen captures in the Windows Processes section.

The code can be easily improved, using more stable ways of accessing these fields and providing a user land control interface.

EPROCESS fields access and edition

The Windows API does not provide EPROCESS structure definition but pointers to these structures can be retrieved using API calls.

The function used in the PoC is PsGetCurrentProcess()which returns a pointer to the current process’ EPROCESS structure. In this driver’s execution context it returns a pointer to the System process’ structure. Once an EPROCESS structure is located, a search function is called in order to go through the EPROCESS’ circular list looking for the virus.exe ImageFileName.

Proof of Concept main routine

If the search returns an EPROCESS structure, then its ActiveProcessLinks are modified to hide it. This is achieved via in-memory manipulation of the EPROCESS structures.

DKOM hiding function

Relevance and current operating system protection

The PoC generated driver has been submitted to the https://nodistribute.com/ platform to check for Antivirus awareness.

Result of the PoC binary analysis

No antivirus considered the binary as harmful, which is not surprising considering the code simplicity and very low amount of system calls.

Despite its apparent stealth, the technique is not stable on all Windows releases.

A protection for Windows 64 bits called PatchGuard can detect the previously mentioned manipulations.

PatchGuard, also referred to as Kernel Patch Protection (KPP), was introduced in Windows XP 64 bits and Windows Server 2003 SP1 in 2005.

This mechanism, very lightly documented by Microsoft, checks kernel structures integrity in order to avoid patching and hooking from a kernel land driver.

KPP verifies kernel structures on a random frequency; tens of minutes can separate two checks. When an anomaly is detected a 0x109 – CRITICAL_STRUCTURE_CORRUPTION kernel error is raised, brutally stopping system’s execution.

KPP does not really block this technique’s execution then but simply shuts down the OS.

Since this technique aims to provide stealthiness, the regular display of Blue Screens disrupts its effectiveness.

The protection has only been implemented in 64 bits versions of Windows, leaving 32 bits systems vulnerable. Nowadays, most recent installations are 64 bits; hence they somewhat protect against this threat.

Even with KPP, this technique should not be ignored because:

  • It can be encountered in incident response on 32 bits system.
  • Attacks against PatchGuard exist from kernel mode drivers (still an active research area).

 

In-memory detection with Volatility

Whereas it could be tricky to detect the technique using tools live on an infected host, it is easily detected within a memory capture.

Indeed, many monitoring / system tools (e.g. SysInternals Microsoft suite) are based on the double chained list for processes enumeration.

To demonstrate this concept the PoC has been executed on a host running Windows 10 Professional version 14393.

Example with Process Explorer, VMMap, ListDlls and Handle64, executed on the PoC system

Invisible process for Process Explorer

Invisible process for VMMap

No detected references to DLLs and handles

 

The process is invisible for several tools. However, the process is running and its system events can be caught by the Process Monitor.

Discovering virus.exe activity with Process Monitor

In the real world rootkits can modify and hijack a great number of system functionalities, making most live detection way harder. It is recommended to investigate offline on a RAM dump with an adapted framework such as Volatility.

 

The previously mentioned Windows version is supported by Volatility 2.6 with the Win10x64_14393 profile.

Windows’ version used for the tests

The memory dump was realized with Winpmem, a tool distributed by the Google’s Rekall project.

Memory dump with Winpmem

In Winpmem output, the drivers names are listed and we can notice the PoC binary (here called 2017_remote_helloworld).

PoC driver listed by Winpmem

Once the memory capture process is completed, the investigation can start.

Volatility has several plugins to analyze running processes in a dump, a quick comparison can be realized this way:

Execution of different processes’ analysis plugins

Only psscan and psxview found our hidden process.

Hidden process detection by psscan & psxview

These plugins’ documentation helps us understand why some of them found the process and why some did not.

pslist – detects processes checking the double chained list

pstree -uses the same technique, simply displays results differently

psscan – scans memory for _POOL_HEADER structures (pools of memory pages) to identify associated processes

psxview – combination of several techniques, one by column:

  • pslist as described above
  • psscan as described above
  • thrdproc thread scan, retrieves the _KTHREAD list used by the scheduler (which cannot be modified without disrupting the process execution) and search it for associated _EPROCESS objects.
  • pspcid
  • csrss The csrss.exe process maintains an independent list of processes which can be retrieved in its memory
  • session
  • deskthrd

Within these plugins, psxview is the quickest way to analyze running processes, it gives users a great cover of different detection techniques.

We know that the hidden process is called virus.exe and has the PID 4952, further investigation is now possible with Volatility.

The PID cannot be used directly by Volatility plugins in this “hidden” case, the process memory offset must be specified instead.

Failing to retrieves process handles with PID

The memory offset (P stands for Physical) can be used instead of the PID for most Volatility plugins.

With this information it is possible to get many items, for example :

  • Open handles to system’s resources (files, registry keys…)

Finding open handles using process’ memory offset

  • The process command line

Recovery of the process’ command line

The driver/rootkit can also be recovered from the memory dump

 

References

Direct Kernel Object Manipulation. Jamie Butler, Black Hat 2004.
The Rootkit Arsenal, Escape and Evasion in the dark Corners of the System. Bill Blunden, 2013.
FU rootkit source code, Jamie Butler.
FUTo rootkit source code, Peter Silberman.
Windows Internals, Mark Russinovich, David A. Solomon, Alex Ionescu, 2012.
Microsoft Developer Network, https://msdn.microsoft.com/

 

 

Olivier CHATAIL