Command Line and Environment
A command line is what a process was told when it started, the program followed by its arguments, such as a script to run or a service group to host. Two copies matter, one in the creation records written as the process starts and one in the process's own memory, where it can be rewritten later. The environment variables sit beside it and shape what the process loads and where it looks. Normal is the known command line for each Windows process, and an environment inherited from its parent. Read both copies, and treat any difference between them as a lead.
What It Is
A command line is the text a program is started with. It is the path of the program, then its arguments, the extra words that tell it what to do.
- Why Windows Needs It
- One program can do many jobs, so it needs to be told which. Notepad opens the file named after it, and each svchost.exe copy hosts the group of services named after -k.
- An Everyday Example
- When Notepad is started to open notes.txt, its command line reads notepad.exe C:\
Users\ alice\ notes. txt. Windows records that text as the process starts, and keeps a copy in the process's own memory.
notepad.exeThe ProgramC:\The File to OpenUsers\ alice\ notes.txt
svchost.exeThe Program-k DcomLaunchThe Group of Services to Host-pAn Option
- Kept by the Kernel
- The kernel keeps the image name and the path the process started from, so a memory image tool can set them beside the PEB's copy.
- In the Process's Own Memory
- The command line and environment sit in the PEB, in the process's own memory, which code in it can rewrite.
Two Copies of the Command Line
The creation records (event 4688 in the Security log with command line auditing on, Sysmon event 1, DeviceProcessEvents) keep the command line the process started with. The PEB holds the copy it has now, which Get-CimInstance, Windows.Memory.ProcessInfo and windows.cmdline read.
A process's PEB copy can be rewritten after it starts, so either copy alone can mislead. The arguments a sensor logged at creation may not be the ones the process acted on. A difference between the two is the lead, and what the process then did (its files, connections and children) shows which one it followed.
windows.malware.pebmasquerade adds two flags for a PEB path or command line whose recorded length disagrees with its text. The stable source fills them in swapped order, so read them as a pair.
Normal
ws-017,
| Name | Command Line |
|---|---|
wscript.exe | wscript.exe C:\ |
Suspicious
ws-017,
| Name | Command Line |
|---|---|
wscript.exe | wscript.exe C:\ |
| Command LineDiffers from the creation record: the two copies of a command line normally match. Odd Command Lines | |
The Environment
Environment variables are named settings a process inherits from its parent, such as PATH, the list of folders Windows searches for programs. No record of process creation keeps them, so only live collection (Windows.Memory.ProcessInfo, Windows.Detection.EnvironmentVariables) and windows.envars in a memory image show them.
windows.envars with its silent option hides the variables that come from the system and user environment in the Registry. That leaves the variables set while the process runs, where an odd one stands out.
Variables worth reading, and what normal is
| Variable | Normal | Worth a Look |
|---|---|---|
COMSPEC | C:\ | Any other program |
COR_ENABLE_PROFILING and COR_PROFILER | Unset, or set by a profiling or monitoring tool you know | Set to 1 with a profiler you cannot explain, as its DLL loads into every .NET program that inherits it |
COMPlus_ETWEnabled | Unset | Set in a .NET program, whose own Event Tracing for Windows reports may then be missing |
PATH | System and user folders from the Registry | A folder a user can write to, ahead of the Windows folders |
What Normal Looks Like
On a healthy machine this part looks like this.
- Windows' own processes start with known command lines. Each process page gives one, and every svchost.exe names its -k group.
- A child inherits its parent's environment by default, and most variables come from the system and user environment in the Registry.
- COMSPEC points to cmd.exe under C:\Windows, which Velociraptor treats as normal and anything else as worth a look.
- A process's creation record and its PEB's copy normally read the same.
Why It Matters
The command line turns a name into an action, naming the script, the DLL or the address. A copy in memory that disagrees with the creation record is a finding in itself.
Normal and Suspicious
A clean machine sits beside a suspicious one, and the pointer marks where to look.
Normal
A clean Windows 11 install
| Name | Parent | Command Line |
|---|---|---|
services.exe | wininit.exe | Not stated |
svchost.exe | services.exe | svchost.exe -k Dcom |
Suspicious
ws-042,
| Name | Parent | Command Line |
|---|---|---|
updsvc64.exe | services.exe | C:\ |
scvhost.exe | updsvc64.exe | C:\ |
| Command LineNo arguments after its path: a genuine svchost.exe names the service group it loads with -k. Odd Command Lines | ||
What a Malicious Example Shows
Each card is what malicious use of this part looks like, and where it shows.
- A command line in memory that differs from the one recorded when the process started.Where it shows: windows.cmdline or Windows.
Memory. Process Info against event 4688 in the Security log, Sysmon event 1 or Device Process Events, and windows. malware. pebmasquerade's flags. - An encoded or obfuscated PowerShell command line.Where it shows: The text of Sysmon event 1 or Security event 4688. Event 4104 in the PowerShell Operational log, with script block logging on, shows the script blocks decoded.
- COR_ENABLE_PROFILING set to 1 with a COR_PROFILER value in a process's environment.Where it shows: Windows.
Detection. Environment Variables or windows.envars, and the profiler DLL then shows in the module list. - COMPlus_ETWEnabled set in the environment of a .NET program.Where it shows: Windows.
Detection. Environment Variables or windows.envars. - A PATH whose first folder is one a user can write to.Where it shows: windows.envars or Windows.
Memory. Process Info, showing an unusual first folder in the process's PATH.
Live and in Memory
Each question has the tools that answer it on a running machine, and in a memory image, a copy of its memory saved to a file.
A creation record keeps the command line a process started with, while live tools and windows.cmdline read the copy in the PEB, the process's own memory. A process can rewrite that copy after it starts, so read both and treat a difference as a lead. Console buffers and PowerShell's script block log add what was typed and what a script really ran.
What was it started with, and what does it hold now?
On a Running Machine
Device(documentation, opens in a new tab)Logs and Records A Defender XDR table. It holds the records Defender for Endpoint keeps of what happened on each machine, and you search it with KQL. ProcessCommandLine as the process started, and InitiatingProcessCommandLine for the process that started it.Process Events - Get-CimInstance Win32_Process (documentation, opens in a new tab)Live Machine A PowerShell command built into Windows. Asked for Win32_Process, it lists each process with its parent and command line.
Get-CimInstance -ClassName Win32_ProcessWin32_Process's CommandLine, read from the process as it is now. Windows.(documentation, opens in a new tab)Live Machine A Velociraptor artifact. It is a ready-made question Velociraptor asks of running machines, named from general to specific. Each process's PEB read directly across many machines, with its command line, image path and environment.Memory. Process Info
In a Memory Image
windows.cmdline(documentation, opens in a new tab)Memory Image A Volatility 3 plugin. It is one check run on a saved copy of a Windows machine's memory. cmdline means command line. Each process's command line as its PEB held it at the moment of capture.windows.pstree(documentation, opens in a new tab)Memory Image A Volatility 3 plugin. It is one check run on a saved copy of a Windows machine's memory. pstree means process tree. Prints the PEB's command line and path beside the kernel's audit path, so the two can be read together.
Was the PEB rewritten after the process started?
On a Running Machine
Device(documentation, opens in a new tab)Logs and Records A Defender XDR table. It holds the records Defender for Endpoint keeps of what happened on each machine, and you search it with KQL. The command line recorded at creation, to set against what the process shows now.Process Events
In a Memory Image
windows.(documentation, opens in a new tab)Memory Image A Volatility 3 plugin from its malware group. It checks a memory image for code that hides, or code put into a process. Sets the kernel's image name and audit path beside the PEB's path, with two flags for a recorded length that disagrees with the text. Read the flags together.malware. pebmasquerade
What was typed at a prompt?
On a Running Machine
Windows.(documentation, opens in a new tab)Live Machine A Velociraptor artifact. It is a ready-made question Velociraptor asks of running machines, named from general to specific. Dumps the memory of chosen processes, consoles among them, for an offline search of what they held. Agree it with whoever runs the response first.Triage. High Value Memory
In a Memory Image
windows.consoles(documentation, opens in a new tab)Memory Image A Volatility 3 plugin. It is one check run on a saved copy of a Windows machine's memory. Console buffers held by conhost.exe, with the commands typed and the output still on screen.windows.cmdscan(documentation, opens in a new tab)Memory Image A Volatility 3 plugin. It is one check run on a saved copy of a Windows machine's memory. cmdscan means command scan. Command history lists found in memory.
Which environment variables does it run with?
On a Running Machine
Windows.(documentation, opens in a new tab)Live Machine A Velociraptor artifact. It is a ready-made question Velociraptor asks of running machines, named from general to specific. Processes carrying the variables you name, across many machines.Detection. Environment Variables
In a Memory Image
windows.envars(documentation, opens in a new tab)Memory Image A Volatility 3 plugin. It is one check run on a saved copy of a Windows machine's memory. envars means environment variables. Each process's environment variables, from its PEB.
A command line is kept in several places, each written at a different moment and switched on in a different way. Read them side by side when the copies disagree.
Where each copy of a command line lives
| Record or Place | Field That Holds It | When It Is Written | What to Watch For |
|---|---|---|---|
| Event 4688 in the Security log | Process Command Line | At creation, only when the policy Include command line in process creation events is on | Anyone who can read the Security log reads every argument, passwords typed into a command included |
| Sysmon event 1 | CommandLine and Parent | At creation, with the parent's own command line | Nothing after the start, so a later change to the PEB is not recorded |
| Device | Process | At creation | The same, what the process started with |
| Event 4104 in the PowerShell Operational log | The text of each script block | As PowerShell processes each script block, with script block logging on | What an encoded command really ran. PowerShell 7 writes to its own log |
| The PEB, live or in memory | Win32_Process's CommandLine, or windows.cmdline | Read at the moment you look | Can be rewritten after the start, and is gone once the process exits |
What It Misses
Every way of looking has gaps, so cover these from another source.
- A command line shows what a process was told to do, not what it did. What a script ran needs event 4104 in the PowerShell Operational log, or the script file itself.
- Event 4688 in the Security log records no command line unless the policy Include command line in process creation events is on. The PEB copy is gone once a process exits.
False Positives
These look odd but are normal, so rule them out before you act.
- Administrators, legitimate scripts and applications run encoded PowerShell too, so judge the parent, the account and the decoded script, not the encoding alone.
Red Flags It Explains
Each red flag below is confirmed by reading this part.
- Wrong Parent Read the command lines of the child and its parent, which say what the shell was told to run, if anything.
- Odd Command Lines Read the command line from the creation record, in event 4688 in the Security log with its command line policy, Sysmon event 1 or DeviceProcessEvents. It shows how the process was started.
- Parent Process Spoofing Read what the new process ran and what its real creator was doing. The false parent hides who started it, not what it did.
- Abused Built-In and Admin Tools Read the full command line from the creation record (4688 with command line auditing, Sysmon event 1 or DeviceProcessEvents). It shows what the tool loads or fetches, from where, and whether arguments are missing.
Checks That Use It
These checks read this part as one of their steps.
Sources
- Microsoft Learn: event 4688, a new process has been created (opens in a new tab)
- Microsoft Learn: command line process auditing (opens in a new tab)
- Microsoft Learn: about_Logging_Windows (script block logging) (opens in a new tab)
- Microsoft Learn: Win32_Process class (opens in a new tab)
- Microsoft Learn: CreateProcessW function (opens in a new tab)
- Microsoft Learn: RTL_USER_PROCESS_PARAMETERS structure (opens in a new tab)
- Microsoft Learn: environment variables (opens in a new tab)
- Microsoft Learn: setting up a profiling environment (.NET Framework) (opens in a new tab)
- Microsoft Learn: DeviceProcessEvents table (opens in a new tab)
- Microsoft Sysinternals: Sysmon (opens in a new tab)
- Velociraptor: Windows.Memory.ProcessInfo (opens in a new tab)
- Velociraptor: Windows.Detection.EnvironmentVariables (opens in a new tab)
- Velociraptor exchange: Windows.Triage.HighValueMemory (opens in a new tab)
- Volatility 3: windows.cmdline (opens in a new tab)
- Volatility 3: windows.envars (opens in a new tab)
- Volatility 3 source: envars.py (opens in a new tab)
- Volatility 3: windows.consoles (opens in a new tab)
- Volatility 3: windows.cmdscan (opens in a new tab)
- Volatility 3: windows.malware.pebmasquerade (opens in a new tab)
- Volatility 3 source: pebmasquerade.py (opens in a new tab)
- Volatility 3: windows.pstree (opens in a new tab)
- Splunk Security Content: encoded PowerShell command analytic (opens in a new tab)
MITRE ATT&CK is a free public catalogue of the techniques attackers use. Each technique has an ID, such as T1055 for Process Injection, so defenders can name the same behaviour the same way. Reading this part helps find these techniques.
- T1564.010 (opens in a new tab) Hide Artifacts: Process Argument Spoofing
- T1059.001 (opens in a new tab) Command and Scripting Interpreter: PowerShell
- T1027.010 (opens in a new tab) Obfuscated Files or Information: Command Obfuscation
- T1574.012 (opens in a new tab) Hijack Execution Flow: COR_PROFILER
- T1685 (opens in a new tab) Disable or Modify Tools
- T1574.007 (opens in a new tab) Hijack Execution Flow: Path Interception by PATH Environment Variable