Back to Blog
Detecting Process Argument Spoofing: Telemetry Gaps, PEB Auditing, and Kernel Tracing
PublishedAugust 26, 202610 min readAdvanced

Detecting Process Argument Spoofing: Telemetry Gaps, PEB Auditing, and Kernel Tracing

An in-depth technical analysis of how adversaries manipulate process parameters within the Process Environment Block (PEB) to bypass command-line logging, along with strategies for surfacing this tradecraft using kernel callbacks and ETW.

Cyber SecurityDetection EngineeringEndpoint SecurityWindows InternalsTelemetry
Written byAbdul Muqeet Tabraiz

Security Operations Centers (SOCs) and threat detection engines rely heavily on process creation telemetry. When a process spawns, security analysts look at the command-line arguments to determine intent—checking for encoded PowerShell scripts, suspicious flags passed to native binaries, or obfuscated execution strings.

However, relying solely on command-line logging assumes that the recorded string accurately reflects what the process executed. Process argument spoofing breaks this assumption. By manipulating user-mode memory structures during process initialization, an adversary can force standard security auditing mechanisms—such as Windows Event ID 4688 or Sysmon Event ID 1—to log a benign command line while the process actually executes malicious arguments.

Understanding how argument spoofing works under the hood requires stepping into Windows process initialization internals, examining where different logging mechanisms source their data, and identifying telemetry mismatches to build robust detections.


How Process Argument Spoofing Works

Process argument spoofing takes advantage of the separation between how the Windows kernel initializes a process and how process arguments are stored in user-mode memory.

Process Environment Block (PEB) Mechanics

When a Win32 process is created (via APIs like CreateProcessW), the execution eventually routes down to NtCreateUserProcess or NtCreateProcessEx in ntdll.dll.

During process creation, the subsystem allocates the Process Environment Block (PEB) in the target process’s virtual memory address space. Within the PEB, the ProcessParameters member points to an RTL_USER_PROCESS_PARAMETERS structure. This structure holds environmental variables, current directory info, and critically, the CommandLine member, which is represented as a UNICODE_STRING.

typedef struct _RTL_USER_PROCESS_PARAMETERS {
    ULONG                   MaximumLength;
    ULONG                   Length;
    ULONG                   Flags;
    ULONG                   DebugFlags;
    PVOID                   ConsoleHandle;
    ULONG                   ConsoleFlags;
    PVOID                   StandardInput;
    PVOID                   StandardOutput;
    PVOID                   StandardError;
    CURDIR                  CurrentDirectory;
    UNICODE_STRING          DllPath;
    UNICODE_STRING          ImagePathName;
    UNICODE_STRING          CommandLine; // <--- Target for spoofing
    PVOID                   Environment;
    ...
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;

The UNICODE_STRING structure contains a Buffer pointer pointing to a null-terminated UTF-16 string containing the actual command-line arguments:

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING;

The Spoofing Lifecycle

Because the PEB resides in user-mode memory (R3), a process with appropriate permissions (or a parent process creating a child) can read and write to this structure using ReadProcessMemory and WriteProcessMemory.

An adversary executes argument spoofing using a specific sequence:

  1. Create Process in Suspended State: The host process calls CreateProcessW with the CREATE_SUSPENDED flag set, passing a benign command-line string (e.g., powershell.exe -Help or a long string of dummy spaces).
  2. Locate Target PEB: The host process calls NtQueryInformationProcess with ProcessBasicInformation to obtain the remote process’s PEB base address.
  3. Read Process Parameters Pointer: The host reads the ProcessParameters pointer offset from the remote PEB.
  4. Overwrite Command-Line Memory:
    • Variant A (Overwriting Buffer Text): The adversary overwrites the memory address pointed to by CommandLine.Buffer in the remote process with the malicious command line (e.g., powershell.exe -e aW52b2tlLXdlYnJlcXVlc3Q...).
    • Variant B (Modifying Length Fields): The process is created with dummy benign arguments padded to a large length (MaximumLength). The adversary writes the real malicious command into the buffer and adjusts CommandLine.Length to only match the length of the new string.
  5. Resume Process: The main thread of the target process is resumed via ResumeThread.
[Attacker Process]

   ├──> 1. CreateProcessW("powershell.exe -Help", CREATE_SUSPENDED) 
   │       └──> Kernel fires PsSetCreateProcessNotifyRoutineEx
   │            └──> Logs: "powershell.exe -Help" (Benign captured)

   ├──> 2. WriteProcessMemory(Target PEB->ProcessParameters->CommandLine, "powershell.exe -enc <payload>")

   └──> 3. ResumeThread()
           └──> PowerShell executes: -enc <payload>

When the target process starts running, it parses its command-line parameters by referencing its own PEB (RTL_USER_PROCESS_PARAMETERS). It sees and executes the malicious payload. However, security logs captured the initial benign string.


Telemetry Architecture and Visibility Gaps

To detect or mitigate argument spoofing, you must understand where different security controls collect process command-line data.

1. Windows Event ID 4688 and Sysmon Event ID 1

Windows Security Event 4688 (Process Creation) and Sysmon Event ID 1 collect process creation details from kernel notification routines—specifically PsSetCreateProcessNotifyRoutineEx.

When NtCreateUserProcess transitions into kernel mode, the kernel captures the parameters passed in user mode at the exact moment of creation to construct the PPS_CREATE_NOTIFY_INFO structure provided to driver callbacks.

  • The Gap: Because kernel callbacks execute during the initial setup of the process (before thread execution begins), PsSetCreateProcessNotifyRoutineEx captures the original string passed to CreateProcessW (powershell.exe -Help). The subsequent patch via WriteProcessMemory occurs after the kernel notification callback has already completed. As a result, standard Windows Audit logging (EID 4688) logs the dummy string and remains completely blind to the post-creation edit.

2. Live PEB Inspection & Dynamic Sampling

Security tools or forensic utilities (like Process Explorer, Task Manager, or basic EDR polling modules) inspect running processes by reading their PEB dynamically in user space.

  • The Gap: If an EDR dynamically inspects the PEB of a running process well after thread execution has resumed, it will read the patched, malicious command line from CommandLine.Buffer.
  • The Discrepancy: This creates an architectural gap between point-in-time creation logs (kernel callbacks) and runtime memory inspection (dynamic PEB reading).

3. ETW Threat Intelligence (ETW-Ti)

Microsoft Threat Intelligence ETW provider (Microsoft-Windows-Threat-Intelligence) operates in the kernel and instruments sensitive calls, including remote process memory writes (NtWriteVirtualMemory) and thread context manipulations (NtSetContextThread).

  • The Advantage: ETW-Ti allows security products registered as Protected Processes Light (PPL) to trace when one process writes to the memory address space of an un-linked or suspended target process, specifically targeting PEB parameter offsets.

Detection Engineering Strategies

Detecting argument spoofing requires leveraging telemetry that compares the state of the command line at process birth against the state of the command line during thread execution or monitoring the API actions that enable the manipulation.

Strategy 1: Identifying Memory Write Patterns to Remote PEB

When Process A creates Process B suspended, reads Process B’s PEB, and writes to Process B’s memory before calling ResumeThread, this leaves a clear cross-process access footprint.

Look for telemetry showing:

  1. ProcessCreate event where TargetProcess is created suspended or initial thread creation is delayed.
  2. TargetProcess memory opened with access rights PROCESS_VM_WRITE | PROCESS_VM_OPERATION (Access Mask 0x0030 or higher like 0x1F0FFF).
  3. Execution of NtWriteVirtualMemory where the destination address resides within the memory region allocated for RTL_USER_PROCESS_PARAMETERS.

Using Sysmon Process Access logs (Event ID 10), look for unusual parent processes requesting write permissions into child processes:

<Sysmon>
  <EventData>
    <Data Name="SourceImage">C:\Users\User\AppData\Local\Temp\loader.exe</Data>
    <Data Name="TargetImage">C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Data>
    <Data Name="GrantedAccess">0x1F0FFF</Data> <!-- PROCESS_ALL_ACCESS -->
    <Data Name="CallTrace">
      C:\Windows\SYSTEM32\ntdll.dll+9d044|
      C:\Windows\System32\KERNELBASE.dll+2c11a|
      C:\Users\User\AppData\Local\Temp\loader.exe+12a4
    </Data>
  </EventData>
</Sysmon>

Note: While GrantedAccess 0x1F0FFF or 0x0030 is common for legitimate parent/child processes (like debuggers or installer engines), it is abnormal for non-standard binaries to open PowerShell or cmd.exe with write permissions immediately after creation.

Strategy 2: Dual Telemetry Comparison (Creation Log vs. ETW Trace)

A robust way to surface argument spoofing in EDR telemetry is comparing the command line logged by the kernel process notification routine against the command line logged by trace providers executing inside user-mode components or dynamic ETW tracing.

Microsoft-Windows-Kernel-Process (Provider GUID: {22FB2CD6-0E7B-422B-A0C7-2FAD560E1CE6}) emits process start events. When correlated against modern EDR memory inspection logs, an alert should fire if:

$$\text{Command Line}{\text{Creation Routine}} \neq \text{Command Line}{\text{Runtime PEB Inspection}}$$

Example KQL Query (EDR Telemetry Mismatch)

Assuming your EDR ingests both process creation events (kernel callback) and periodic process memory snapshot logs:

// Step 1: Filter process creation events capturing original creation command line
let ProcessCreations = 
    DeviceProcessEvents
    | where TimeGenerated > ago(1d)
    | project ProcessId, DeviceId, FileName, OriginalCommandLine = ProcessCommandLine, AccountName, InitiatingProcessFileName;
// Step 2: Filter dynamic PEB / Process memory audit events
let MemoryAudits = 
    DeviceProcessMemorySnapshots // Hypothetical EDR dynamic PEB snapshot table
    | where TimeGenerated > ago(1d)
    | project ProcessId, DeviceId, RuntimeCommandLine = ProcessCommandLine;
// Step 3: Join on ProcessId and DeviceId and compare strings
ProcessCreations
| join kind=inner (MemoryAudits) on ProcessId, DeviceId
| where OriginalCommandLine != RuntimeCommandLine
| project TimeGenerated, DeviceId, ProcessId, FileName, InitiatingProcessFileName, OriginalCommandLine, RuntimeCommandLine

If OriginalCommandLine is powershell.exe -Help or contains padding (e.g., powershell.exe ), but RuntimeCommandLine contains powershell.exe -nop -w hidden -enc..., argument spoofing has occurred.

Strategy 3: Detecting Command-Line Padding Traps

Adversaries often exploit string buffer length fields. They pass a long dummy string (e.g., powershell.exe followed by 500 spaces) to allocate a large buffer in RTL_USER_PROCESS_PARAMETERS.CommandLine.MaximumLength. They then overwrite the buffer with a shorter command line.

If logging engines fail to strip or handle null terminators or trailing whitespace correctly, the raw log in EID 4688 will show excessive whitespace.

Detection logic can target high ratios of whitespace padding within process creation command lines:

title: Suspicious Process Command-Line Whitespace Padding
id: 5f988f11-0e12-421f-a78d-123456789abc
status: experimental
description: Detects command-line arguments containing excessive whitespace padding, which is indicative of process argument spoofing.
logsource:
  category: process_creation
  product: windows
detection:
  selection:
    CommandLine|contains:
      - '                                ' # 32+ consecutive spaces
  condition: selection
falsepositives:
  - Rare legacy applications with malformed arguments
level: high

Operational Considerations and False Positives

Building detections for argument spoofing introduces engineering trade-offs that detection teams must account for.

Legitimate PEB Modification

Not all command-line modifications are malicious:

  1. Chromium-based Applications: Browsers like Google Chrome and Microsoft Edge frequently spawn helper processes that adjust their internal parameter representation or drop flags in memory after initialization for security or process naming purposes.
  2. Database Engines & Middleware: Applications such as Oracle DB, Microsoft SQL Server wrappers, or Java application servers sometimes mask sensitivity at runtime (e.g., blanking out cleartext passwords passed via parameters) by writing zeroes over their own PEB parameter buffers.
  3. Application Security Wrappers: DRM tools, legacy enterprise wrappers, and performance monitoring agents may modify child process memory to insert tracing flags.

Performance Limitations of PEB Verification

Performing real-time dynamic PEB inspection across every newly created process introduces overhead.

  • Polling Cost: Constantly inspecting the virtual address space of all short-lived processes (e.g., script invocations, conhost.exe, cmd.exe) forces high CPU usage and context switches.
  • Race Condition Risks: If an EDR attempts to read target PEB memory while the thread is actively modifying its parameters, the telemetry engine might read corrupted or incomplete pointers, triggering access violations (0xC0000005) if not handled within a structured exception handler (__try / __except).

To effectively defend against argument spoofing without degrading system performance:

  1. Implement Parent-Child Lineage Rules over Command-Line Rules: Do not rely exclusively on command-line text for detection. An unexpected execution of powershell.exe or cmd.exe spawned by non-standard parent processes (e.g., spoolsv.exe, sqlserver.exe, w3wp.exe) should alert regardless of whether the logged command line appears benign (powershell.exe -Help).
  2. Leverage ETW-Ti via modern EDR Solutions: Ensure your EDR vendor utilizes kernel-level telemetry (ETW-Ti) to flag cross-process memory modifications involving process parameters (RTL_USER_PROCESS_PARAMETERS), particularly when targets are launched in a suspended state (CREATE_SUSPENDED).
  3. Audit Suspicious PROCESS_VM_WRITE Access Masks: Monitor Sysmon Event ID 10 or equivalent telemetry for untrusted processes requesting write access to core system binaries (powershell.exe, cmd.exe, wmic.exe, mshta.exe).
  4. Harden Endpoint Process Creation Policies: Enforce Application Control policies (AppLocker or Windows Defender Application Control) to restrict unauthorized binaries from executing, preventing the initial adversary loader from running on the host.

Conclusion

Process argument spoofing highlights a fundamental truth in defensive telemetry: what an endpoint event log captures is entirely dependent on where and when the event provider reads memory.

Adversaries exploit the gap between kernel-level creation notifications and post-creation user-mode memory modifications. By understanding these internals, detection engineers can move past reliance on static command-line string matching, building layered detections that inspect process access rights, parent-child context, and telemetry mismatches.