Detecting Strange Parent-Child Relationships (Parent PID Spoofing) with ETW and SilkETW

Parent PID spoofing, also known as PPID spoofing, is a sophisticated defense evasion technique (MITRE ATT&CK T1134.004) where attackers create a new process, such as cmd.exe, but make it appear as if it was launched by a legitimate process like spoolsv.exe. This method helps adversaries evade process-monitoring tools and detection rules. In this guide, we’ll explore how this attack works, demonstrate it step-by-step, and reveal how to detect it using Event Tracing for Windows (ETW) for reliable kernel-level insights. Whether you’re a blue team defender or a security researcher, understanding PPID spoofing detection is crucial for strengthening your Windows security posture.

What is Parent PID Spoofing?

Parent PID spoofing allows attackers to manipulate the parent process identifier (PPID) during process creation, thwarting tools that rely on process tree analysis. By spoofing a trusted parent like the Print Spooler service (spoolsv.exe), malicious processes blend into normal system activity. This evasion tactic is commonly used in advanced persistent threats (APTs) to avoid detection by endpoint detection and response (EDR) solutions.

Why does this matter? Standard tools like Sysmon may report the spoofed parent, leading to false negatives in your detection rules. To catch it, we need deeper visibility from ETW’s Microsoft-Windows-Kernel-Process provider, which captures the true calling process.

Prerequisites for the Demo :

1. Download the compiled SilkETW

2. Download the psgetsystem project.

3. Sysmon (Configuration):

If your system doesn’t have sysmon installed and configured then follow this article – Sysmon Explained.

  • In the Sysmon configuration file, ensure ImageLoad events are excluded:
  • <ImageLoad onmatch=”exclude” />
  • After the changes update the sysmon with new config file.
  • sysmon64.exe -c updatedconfig

Executing the Parent PID Spoofing Attack

To demonstrate PPID spoofing, we’ll use the psgetsystem project’s psgetsys.ps1 script, which leverages Windows APIs via C# code to create processes with a spoofed parent.

Why is psgetsys.ps1 necessary?

You can’t just type a command to spoof a parent PID. This technique requires using specific Windows APIs to manipulate process creation. The psgetsys.ps1 script cleverly packages this complex C# code into a .NET class called MyProcess.

When we load this script, it compiles and registers this MyProcess class in our PowerShell session, giving us access to a new method: CreateProcessFromParent. This is the specialized tool we need to perform the attack.

Part 1: Start PowerShell with Execution Policy Bypass

First, we need to set up our “attacker” terminal. We’ll start PowerShell as an Administrator and bypass the execution policy to allow our script to run.

powershell -ep bypass

Verify the execution policy:

Get-ExecutionPolicy -List

Part 2: Prepare & load psgetsys.ps1 (compile C# into session)

Next, we navigate to our script’s directory and “dot-source” it. This command loads the script into our current session and then compiles the embedded C# code (stored in a variable called $mycode) if the MyProcess class isn’t already registered.

# Change to the script directory
cd C:\Users\admin\Desktop\psgetsystem-master
# Dot-source the script and compile the C# code
. .\psgetsys.ps1;
if (-not ("MyProcess" -as [type])) { Add-Type -TypeDefinition $mycode }

This registers the MyProcess class with the CreateProcessFromParent method.

Part 3: Find the parent process PID (example: spoolsv)

Now, we need to pick our “victim” parent. We’ll choose the Print Spooler service, spoolsv.exe, because it’s a high-privilege system process that is almost always running. Open Process Hacker (or Task Manager) and locate spoolsv.exe. Note the PID value shown in Process Hacker.

Alternative PowerShell command will show PIDs for spoolsv processes:

Get-Process -Name spoolsv | Select-Object Id, ProcessName

Example Output:

IdProcessName
2168spoolsv

Note the PID (e.g., 2168). You might see different PID.

With our spoofed parent’s PID (2168), we can execute the attack. We’ll use our special MyProcess class to launch cmd.exe, passing it the PID of spoolsv.exe.

Part 4: Start SilkETW to capture ETW Events (Kernel Process Events)

This is where we need a more powerful microscope. Event Tracing for Windows (ETW) provides a stream of low-level, kernel-rich events. Attackers can’t easily tamper with this data. We’ll use a tool called SilkETW to capture the specific events we need.

This is a two-terminal operation.

In PowerShell Terminal 1 (Listener):

We start SilkETW and tell it to listen for Microsoft-Windows-Kernel-Process events (which include process creation) and save them to a JSON file.

cd "C:\Users\admin\Desktop\v8\SilkETW"
.\SilkETW.exe -t user -pn Microsoft-Windows-Kernel-Process -ot file -p C:\Users\admin\Desktop\etw.json

-pn Microsoft-Windows-Kernel-Process

  • -pn stands for Provider Name.
  • You are telling SilkETW to listen only to the events published by the Microsoft-Windows-Kernel-Process provider. This provider is a built-in part of Windows that records kernel-level data about process and thread lifecycles (creations, deletions, etc.).

In Powershell Terminal 2 (Attacker):

Find the PID of this second PowerShell window.

$PID
# Example Output: 6252

Note the PID of the second powershell.

Execute the spoof Attack: Create a new process using the parent PID (spoolsv.exe).

# [MyProcess]::CreateProcessFromParent(<Target Parent PID>, <Process to Launch>, <Args>)
[MyProcess]::CreateProcessFromParent(2168, "C:\Windows\System32\cmd.exe", "")

Child PID: The output gives us the new cmd.exe PID: 6524.

Back in Terminal 1: Press Ctrl+C to stop SilkETW and let it finish writing the log file.

Part 5: Analyzing the ETW Log

We now have all the pieces:

  • spoolsv.exe PID (Spoofed Parent): 2168
  • PowerShell PID (Real Parent): 6252
  • cmd.exe PID (Child): 6524

Open etw.json in a text editor. Search for “by parent”, or directly for the parent PID (2168 or “2,168”).

You should find an entry like this:

ProcessID: 6252, ProcessName: powershell,
FormattedMessage: 6,524 process started by parent 2,168

Here is the key part of that log entry:

{
  "ProcessID": 6252,
  "ProcessName": "powershell",
  "EventName": "ProcessStart/Start",
  "XmlEventData": {
    "FormattedMessage": "Process 6,524 started at time... by parent 2,168...",
    "ParentProcessID": "2,168",
    "ProcessID": "6,524",
    "PID": "6252"
  }
}

Let’s break this down. This single log entry is our smoking gun.

  • “ProcessID”: 6252 and “ProcessName”: “powershell”: This is the process that generated the event. This is the true parent, our attacker powershell.exe.
  • “FormattedMessage”: “Process 6,524 started … by parent 2,168”: This is the event’s message. It shows that cmd.exe (PID 6524) was started, and it claims its parent is spoolsv.exe (PID 2168).

This discrepancy is the detection.

The process that called for the creation (ProcessID: 6252) is different from the parent it reported (ParentProcessID: 2,168). This is a high-fidelity indicator of Parent PID Spoofing. The kernel is telling us, “Hey, PowerShell process 6252 just created a new process, but it told me to list process 2168 as the parent.”

Part 6: The Deception: Why Sysmon Logs Can Be Misleading

Let’s put on our blue team hat and check our Sysmon logs. Sysmon is a fantastic tool, and we’d expect its Event ID 1 (Process Creation) log to catch this.

And it does… sort of.

When we find the creation event for our new cmd.exe, we’ll see that Sysmon reports the cmd’s  ParentProcessId as 2168. To Sysmon, and any tool relying on standard process information, it looks like spoolsv.exe just launched a command prompt.

This is the success of the evasion. Our powershell.exe (the real parent) is nowhere to be seen in this log. If our detection rules are based purely on “Look for cmd.exe spawning from powershell.exe,” we would have missed this completely.

Why standard logs can be deceptive

Tools like Sysmon log the parent process claimed by the creating process. If an attacker spoofs the parent, Sysmon’s Event ID 1 will show the spoofed PID. Humans and automated rules that rely only on this information can be misled.

Because of this, detecting spoofing requires correlating multiple telemetry sources, including kernel-level event streams that record the actual caller.

Sysmon Log:

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="Microsoft-Windows-Sysmon" Guid="{5770385f-c22a-43e0-bf4c-06f5698ffbd9}" /> 
    <EventID>1</EventID> 
    <Version>5</Version> 
    <Level>4</Level> 
    <Task>1</Task> 
    <Opcode>0</Opcode> 
    <Keywords>0x8000000000000000</Keywords> 
    <TimeCreated SystemTime="2025-09-23T04:16:01.555Z" /> 
    <EventRecordID>3442037</EventRecordID> 
    <Correlation /> 
    <Execution ProcessID="3512" ThreadID="4432" /> 
    <Channel>Microsoft-Windows-Sysmon/Operational</Channel> 
    <Computer>SIEM2</Computer> 
    <Security UserID="S-1-5-18" /> 
  </System>
  <EventData>
    <Data Name="RuleName">-</Data> 
    <Data Name="UtcTime">2025-09-23 04:16:01.555</Data> 
    <Data Name="ProcessGuid">{3a380209-9dc8-6908-8a01-000000005900}</Data> 
    <Data Name="ProcessId">6524</Data> 
    <Data Name="Image">C:\Windows\System32\cmd.exe</Data> 
    <Data Name="FileVersion">10.0.19041.4355 (WinBuild.160101.0800)</Data> 
    <Data Name="Description">Windows Command Processor</Data> 
    <Data Name="Product">Microsoft® Windows® Operating System</Data> 
    <Data Name="Company">Microsoft Corporation</Data> 
    <Data Name="OriginalFileName">Cmd.Exe</Data> 
    <Data Name="CommandLine">"C:\Windows\System32\cmd.exe"</Data> 
    <Data Name="CurrentDirectory">C:\Windows\system32\</Data> 
    <Data Name="User">NT AUTHORITY\SYSTEM</Data> 
    <Data Name="LogonGuid">{3a380209-9c11-6908-e703-000000000000}</Data> 
    <Data Name="LogonId">0x3e7</Data> 
    <Data Name="TerminalSessionId">1</Data> 
    <Data Name="IntegrityLevel">System</Data> 
    <Data Name="Hashes">MD5=2B40C98ED0F7A1D3B091A3E8353132DC,SHA256=BADF4752413CB0CBDC03FB95820CA167F0CDC63B597CCDB5EF43111180E088B0,IMPHASH=272245E2988E1E430500B852C4FB5E18</Data> 
    <Data Name="ParentProcessGuid">{3a380209-9c14-6908-3b00-000000005900}</Data> 
    <Data Name="ParentProcessId">2168</Data> 
    <Data Name="ParentImage">C:\Windows\System32\spoolsv.exe</Data> 
    <Data Name="ParentCommandLine">C:\Windows\System32\spoolsv.exe</Data> 
    <Data Name="ParentUser">NT AUTHORITY\SYSTEM</Data> 
  </EventData>
</Event>

Parent PID Spoofing Explained:

This attack is effective because it creates a conflict between what monitoring tools see and what actually happens. The diagram below breaks this down: it compares the “Deception View” (what Sysmon reports) with the “Reality View” (what ETW captures), pinpointing the exact mismatch we can use for detection.

Parent PID Spoofing Explained

Figure: ETW reveals the true calling process, unmasking the false parent-child relationship seen in standard log (Sysmon).

Why ETW is More Reliable for Detection

  • Kernel providers record the actual caller at a lower level than user-mode APIs.

  • Manipulating kernel ETW data in-flight is non-trivial for attackers (higher complexity and risk).

  • When available, ETW correlation dramatically reduces false negatives and false positives.

Key Takeaways

  1. Don’t Trust, Verify: Parent-child relationships in tools like Sysmon or Task Manager are not infallible. They report the intended parent, which an attacker can spoof.
  2. Evasion is About Deception: This technique is designed to fool automated analysis and human analysts who are looking for simple, suspicious process trees.
  3. Kernel-Level is Ground Truth: To catch this, you need visibility from a deeper level. ETW’s Microsoft-Windows-Kernel-Process provider captures the actual process making the API call, unmasking the masquerade.

By correlating the true source of the event (the ProcessID in the ETW log) with the claimed parent (the ParentProcessID), we can confidently identify this advanced evasion technique.

Conclusion

Parent-PID spoofing is effective at tricking user-land process views, but you can unmask it by correlating kernel-level ETW process creation events with standard process logs. Treat kernel telemetry as ground truth and use correlation rules to turn this technique from a blind spot into a reliable detection signal. Understanding and cataloging specific adversary tradecraft like this is a core component of an effective Cyber Threat Intelligence (CTI) program.