Skip to content
λmaldev wiki/
pagesParent PID Spoofing
T1134.004WindowsC / C++WinAPI

Parent PID Spoofing

updated 2026-08-046 min readthehackersbrain
Authorized use only. This material is published for detection engineering, malware analysis and authorized red-team engagements. Running these techniques against systems you do not own or have written permission to test is illegal.

Overview

Windows records the parent process ID (PPID) of every new process in the kernel’s EPROCESS structure. Many behavioural detections fire on anomalous parent-child pairs: cmd.exe spawned by winword.exe, or powershell.exe spawned by something that isn’t explorer.exe or a legitimate shell. PPID spoofing forges the recorded parent, making the child appear to have been spawned by a trusted process.

The mechanism is legitimate Windows API: PROC_THREAD_ATTRIBUTE_PARENT_PROCESS was added so that tools like Task Manager and services can create processes that inherit a specific parent’s environment. Attackers re-purpose it to pick a parent whose presence in the lineage looks natural.

Note.

PPID spoofing fools tooling that reads the ParentProcessId field from the WMI or Sysmon process creation event. It does not fool ETW-TI, which records the actual creating process separately from the declared parent. An EDR with ETW-TI can see both values.

The call chain

  1. 1
    OpenProcess(PROCESS_CREATE_PROCESS) on target parent
    Obtain a handle to the process we want to appear as the parent.
  2. 2
    InitializeProcThreadAttributeList
    Allocate an extended attribute list for CreateProcessW.
  3. 3
    UpdateProcThreadAttribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS)
    Insert the spoofed parent handle into the attribute list.
  4. 4
    CreateProcessW with EXTENDED_STARTUPINFO_PRESENT
    The kernel records the spoofed PID as the parent in the EPROCESS structure.

Reference implementation

ppid_spoof.cC
#include <windows.h>

// Spawn cmd.exe under a spoofed explorer.exe parent
void spoof_parent(DWORD target_ppid) {
  // 1. get a handle with PROCESS_CREATE_PROCESS access
  HANDLE h_parent = OpenProcess(PROCESS_CREATE_PROCESS, FALSE, target_ppid);
  if (!h_parent) return;

  // 2. build an extended attribute list with the parent override
  SIZE_T attr_size = 0;
  InitializeProcThreadAttributeList(NULL, 1, 0, &attr_size);
  LPPROC_THREAD_ATTRIBUTE_LIST attr =
      (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, attr_size);
  InitializeProcThreadAttributeList(attr, 1, 0, &attr_size);

  UpdateProcThreadAttribute(attr, 0,
      PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
      &h_parent, sizeof(HANDLE), NULL, NULL);

  // 3. create the child — Sysmon/WMI will record target_ppid as parent
  STARTUPINFOEXW si = { sizeof si };
  si.lpAttributeList = attr;
  PROCESS_INFORMATION pi = {0};

  CreateProcessW(L"C:\\Windows\\System32\\cmd.exe",
                 NULL, NULL, NULL, FALSE,
                 CREATE_NEW_CONSOLE | EXTENDED_STARTUPINFO_PRESENT,
                 NULL, NULL, &si.StartupInfo, &pi);

  // cleanup
  CloseHandle(pi.hThread);
  CloseHandle(pi.hProcess);
  DeleteProcThreadAttributeList(attr);
  HeapFree(GetProcessHeap(), 0, attr);
  CloseHandle(h_parent);
}

Common spoofed parents

Target parent Why it looks natural
explorer.exe Spawns user applications on logon; expected parent for GUI tools
svchost.exe -k netsvcs Services running from svchost spawn other helpers
WmiPrvSE.exe WMI consumers legitimately spawn processes here
msiexec.exe Installer processes frequently spawn sub-installers
userinit.exe Logon helper; spawns explorer and user-defined shells

Pick the parent whose natural children most closely resemble what you are spawning. A cmd.exe under explorer.exe is uninteresting; a cmd.exe under msiexec.exe is slightly more suspicious because installation sessions should be short-lived.

Combining with other techniques

The most complete parent-child deception combines three primitives:

  1. PPID spoofing — the child shows the right recorded parent
  2. Token impersonation — the child inherits a token matching that parent’s user
  3. Process hollowing — the child’s image path matches the declared parent’s expected children

Each layer defeats a different detection heuristic independently. Together they produce a process that passes parent-child checks, token checks, and image-path checks simultaneously.

Detection

SYSMON EID 1
Process creation where the recorded ParentProcessId has a different image path than the actual spawning process.
ETW-TI
The real creating process (not the spoofed parent) is recorded in the kernel-side process creation event.
BEHAVIOURAL
Explorer.exe or svchost.exe appearing as parent of a process that explorer or svchost would never spawn.
MEMORY SCAN
Cross-referencing PEB.InheritedAddressSpace and the real parent's VAD tree detects the mismatch.

The definitive detection compares two values that ETW-TI exposes: the ParentProcessId field in the process creation event, and the handle that the creating process passed as PROC_THREAD_ATTRIBUTE_PARENT_PROCESS. When they disagree, spoofing occurred. Very few endpoint tools expose this comparison today — it requires an ETW-TI consumer, not just Sysmon.

Was this page useful?edit this page ↗