PPID Spoofing — Forging the Process Tree

Why the Process Tree Matters

One of the simplest and most effective forms of malicious behavior detection is analysis of parent-child relationships between processes. EDRs and SIEMs build rules around what is "normal" for a process tree:

  • winword.exe should never spawn cmd.exe directly

  • explorer.exe is the expected parent of interactive applications

  • lsass.exe should not have children

  • powershell.exe spawned by mshta.exe is highly suspicious

When an attacker executes cmd.exe after exploiting an Office document, the system records WINWORD.EXE (PID 1234) → cmd.exe (PID 5678) — a trivially suspicious relationship.

PPID Spoofing (parent process ID forgery) allows creating a process with an arbitrary PPID, making it appear to have been spawned by any legitimate process — explorer.exe, svchost.exe, or any other.

┌──────────────────────────────────────────────────────────────────────┐
│              Process Tree: Real vs. Spoofed                          │
│                                                                      │
│  WITHOUT PPID SPOOFING:                                              │
│  explorer.exe (1234)                                                 │
│  └── WINWORD.EXE (5678)                                              │
│      └── powershell.exe (9012)  ← SUSPICIOUS — child of Word        │
│          └── mimikatz.exe (1111)                                     │
│                                                                      │
│  WITH PPID SPOOFING:                                                 │
│  explorer.exe (1234)                                                 │
│  ├── WINWORD.EXE (5678)         ← real parent (invisible to EDR)   │
│  └── powershell.exe (9012)  ← appears as legitimate child of        │
│      └── mimikatz.exe (1111)      explorer                           │
│                                                                      │
│  The EDR sees PowerShell as a legitimate child of explorer.         │
└──────────────────────────────────────────────────────────────────────┘

The Mechanism: UpdateProcThreadAttribute

The CreateProcess API accepts an extended attributes structure (LPPROC_THREAD_ATTRIBUTE_LIST) that allows, among other things, specifying an alternative "parent process handle" via PROC_THREAD_ATTRIBUTE_PARENT_PROCESS.

When this attribute is set, the kernel registers the child process with the PPID of the process referenced by the handle — not with the PPID of the process that called CreateProcess.


Implementation


Combining PPID Spoofing with Other Techniques

In practice, PPID Spoofing is almost always combined with other evasion techniques:

With Shellcode Injection

With Command Line Spoofing

Beyond the PPID, we can also forge the command line of the process (visible in the PEB). This is done by writing directly to the PEB after process creation:


Limitations and Modern Detections


References

  • Elastic, "How PPID Spoofing Works" — elastic.co/security-labs (2020)

  • ired.team, "Parent PID Spoofing" — ired.team/offensive-security

  • MITRE ATT&CK, "T1134.004 — Parent PID Spoofing" — attack.mitre.org

  • Pentest Laboratories, "Spawning Processes with PPID Spoofing" — pentestlab.blog (2020)

  • Will Burgess, "Detecting Parent Process Spoofing" — blog.f-secure.com (2019)

  • Sysmon documentation, "Process Create (Event ID 1)" — docs.microsoft.com

  • Red Team Notes, "PPID Spoofing in Cobalt Strike" — www.redteamnotes.com

Last updated