Detecting Parent Process Spoofing using KrabsETW
This blog post covers how to build a simple PoC program that will use the KrabsETW library to subscribe to an ETW provider in order to detect parent process spoofing.
Last updated
This blog post covers how to build a simple PoC program that will use the KrabsETW library to subscribe to an ETW provider in order to detect parent process spoofing.
Last updated
Parent-child relationships are a valuable telemetry source for blue teams and security products to identify potentially malicious process chains. For example, the parent-child relationship of winword.exe
launching powershell.exe
or cmd.exe
is often monitored as it can be indicative of office macro execution which is commonly used as an initial access technique by commodity malware and APTs alike.
The scrutiny of parent-child relationships relating to commonly abused windows programs had led to attackers looking for ways to obscure or break these relationships. As such there are plenty tools and resources available online to allow for parent process spoofing, and the technique has also been included as a feature in Cobalt Strike since version 3.8.
The rest of this blog post details how to use ETW providers to provide a detection mechanism for parent PID spoofing. This is not a new detection technique, it is just my own experimentation of the technique discussed in the original detection blog post by F-Secure Countercept.
Event Tracing for Windows (ETW) is a tracing facility that allows a user log and consume events from various applications and APIs. During the course of their normal operation, windows applications and APIs (providers) will log information to ETW "feeds" which can then be subscribed to by consumers, who can then parse and act on the ingested information.
Given the stability, realtime nature, and visibility that ETW offers, it has quickly been adopted by blue teams and security products as a rich telemetry source. EDR products will commonly subscribe to ETW "feeds" to enrich in their detection capabilities, enabling greater visibility into memory related events, registry events, and more. To simplify the process of subscribing to ETW feeds, Microsoft released a C++ library called KrabsETW which provides a very simple way of subscribing to single or multiple ETW feeds.
As detailed in the Countercept blog post, the Microsoft-Windows-Kernel-Provider ETW provider offers a powerful method of detection for parent PID spoofing. This kernel provider provides real-time information about windows processes, including various information such as the process ID of a created process, the parent process ID, the process image name, etc.
To explore what other information is available from this provider we can easily subscribe to this feed using the KrabsETW library:
As the Microsoft-Windows-Kernel-Process is a kernel trace, subscribing requires admin rights. In this case I used PsExec to spawn a SYSTEM shell before executing the compiled binary.
As explained in an excellent blog post by Pavel Yosifovich there is no dependency between a child and a parent process in any way. The 'mapping' between a process and its parent is not enforced and can be altered from user-land. For example, via the lpStartupInfo structure when calling CreateProcessA.
The parent process ID that is displayed from our current PoC code will match the parent specified in the lpStartupInfo structure. This means that it will display the spoofed parent and not the real parent. Fortunately the Microsoft-Windows-Kernel-Provider ETW provider allows us to see the creator process for each new process that is created, the creator "process ID" is not affected by changes to the lpStartupInfo structure and therefore presents a detection opportunity for us.
We can access the "creator process" ID from the record EventHeader for events provided by the Microsoft-Windows-Kernel-Provider ETW provider. The EventHeader is basically just a wrapper around the actual ETW record and contains various pieces of information relating to how the event was created. One of these pieces of information is the ProcessID of the process that has spawned the new process, in other words this is the real parent process ID that will be unaffected by PPID spoofing techniques.
Now that we have all of the pieces of the puzzle, we can extend our previous PoC code to detect a common examples of parent PID spoofing:
As the Microsoft-Windows-Kernel-Process is a kernel trace, subscribing requires admin rights. In this case I used PsExec to spawn a SYSTEM shell before executing the compiled binary.