# Effective Parenting - detecting LRPC-based parent PID spoofing

WMI's Win32_Process::Create ETW event logs client-supplied ClientProcessId and ClientMachine, letting attackers spoof parent PID and IsLocal to evade provenance detection.

- Payout: Research
- Severity: medium
- Program: Microsoft
- Write-up by: John Uhlmann
- Disclosed: 2023-03-29
- Write-up quality: 8/10
- Original: https://www.elastic.co/security-labs/threat-command/effective-parenting-detecting-lrpc-based-parent-pid-spoofing
- Library page: https://bugbountylibrary.com/r/blog%3Aelastic-co-security-labs-threat-command-effective-parenting-detecting-lrpc-based-parent-pid-spoofing
- Tags: area:os domain:desktop impact:integrity kind:research platform:threat-intel sev:medium tech:windows technique:chained technique:reverse-engineering technique:source-review vuln:info-disclosure vuln:misconfiguration

**Target:** WMI Core Service (wbemcore) and WMI client (wbemprox) over LRPC
**Root cause:** The WMI client passes ClientProcessId, ClientProcessCreationTime, ClientMachine and ClientMachineFQDN to the WMI Core via IWbemLoginClientIDEx::SetClientInfo; the server blindly logs these client-controlled values in Microsoft-Windows-WMI-Activity event 23 without verifying them against the actual RPC caller.
**Steps:**
1. Observe that Microsoft-Windows-WMI-Activity event 23 includes ClientProcessId, but the event is written by svchost.exe (Winmgmt), not WmiPrvSE.exe.
2. Breakpoint PublishWin32ProcessCreation and InspectWin32ProcessCreateExecution; trace ClientProcessId to CWbemNamespace::Initialize.
3. Trace the call path to IWbemLevel1Login::NTLMLogin and IWbemLoginClientIDEx::SetClientInfo, called by wbemprox!SetClientIdentity.
4. Patch the WMI client with WinDbg: `bp wbemprox!SetClientIdentity+0xff "eu @rdx \"SPOOFED....\"; gc"` and `bp wbemprox!SetClientIdentity+0x1c4 "r r9=0n1337; eu @r8 \"SPOOFED.COM\"; gc"`.
5. Trigger `([wmiclass]"ROOT\CIMv2:Win32_Process").Create("calc.exe")` and capture ETW with SilkETW to confirm the spoofed values appear in event 23.
**How found:** Started from the observation that COM/WMI-based process creation lacks parent-process telemetry (red arrows in the process tree). Investigated whether ETW ActivityId could generically correlate LRPC server calls to clients; found kernel ETW events always log a zero ActivityId and RPC servers use worker thread pools that break per-thread ActivityId propagation. Pivoted to reverse-engineering how Microsoft populates ClientProcessId in WMI event 23, using Sealighter stack traces and Ghidra decompilation of wbemcore, then traced the value back to the client via IWbemLoginClientIDEx.
**Exploitation:** An adversary with code execution on the host calls Win32_Process::Create via WMI (or a COM ShellExecute interface) to spawn a child process; by patching or hooking SetClientIdentity they supply a fake ClientProcessId and ClientMachine, so the resulting WMI-Activity event 23 attributes the spawn to an innocuous parent and marks IsLocal true, breaking EDR process-tree provenance.
**Escalation:** A remote attacker can pass ClientMachine equal to the local hostname so the event logs IsLocal=true, disguising lateral movement as local execution.
**Insight:** When a telemetry field looks authoritative because a trusted server or kernel wrote the event, trace where the value actually originates: WMI's ClientProcessId is copied from client-supplied SetClientInfo data, so any 'provenance' field in an RPC-based event should be treated as attacker-controlled unless the server independently derives it from the RPC caller identity.

## Proof of concept (copied exactly from the original report)

**WinDbg patches spoofing WMI client identity**

```
windbg> bp wbemprox!SetClientIdentity+0xff "eu @rdx \"SPOOFED....\"; gc"
windbg> bp wbemprox!SetClientIdentity+0x1c4 "r r9=0n1337; eu @r8 \"SPOOFED.COM\"; gc"
PS> ([wmiclass]"ROOT\CIMv2:Win32_Process").Create("calc.exe")
```

**ETW WriteTransfer call with NULL ActivityId**

```
`EtwEventWriteTransfer` (RegHandle, EventDescriptor, NULL, NULL, UserDataCount, UserData);
```

**WMI event 23 schema with ClientProcessId**

```
`task_023` (UnicodeString CorrelationId, UInt32 GroupOperationId, UInt32 OperationId, UnicodeString Commandline, UInt32 CreatedProcessId, UInt64 CreatedProcessCreationTime, UnicodeString ClientMachine, UnicodeString ClientMachineFQDN, UnicodeString User, UInt32 ClientProcessId, UInt64 ClientProcessCreationTime, Boolean IsLocal)
```

