Command line analysis
On this page
Command lines reveal intent. Adversaries use native scripting environments to do real work while looking like legitimate processes. Effective analysis means actually decoding what ran, then weighing it against execution context.
What to look for: inspection
Common obfuscation Obfuscation Making code, commands or data hard to read or detect: encoding, string splitting, variable expansion, packing. Attackers use it to slip past detection; vendors use it legitimately to protect code. Deobfuscate before judging: decode, expand and unpack, then read what the command or script actually does. patterns (ATT&CK T1027.010, Command Obfuscation). Base64-encoded PowerShell PowerShell Microsoft's shell and scripting language: Windows PowerShell 5.1 on .NET Framework, cross-platform PowerShell 7 on .NET. The most abused interpreter on Windows (ATT&CK T1059.001). Triage tells: -EncodedCommand or -enc (Base64 of UTF-16LE text), -NoProfile, -WindowStyle Hidden, IEX with a download cradle, and an Office or browser parent. Script Block Logging (Event ID 4104) records de-obfuscated script content. launchers are standard output from post-exploitation frameworks such as Cobalt Strike Cobalt Strike Commercial adversary-simulation framework (sold by Fortra) whose cracked copies were heavily abused by APTs, ransomware gangs and commodity malware: Beacon C2, fileless injection, lateral movement, credential harvesting. Historically delivered by loaders such as TrickBot and BazarLoader (both retired around 2022). Fortra reports an 80% drop in unauthorized copies after a 2023 court order won with Microsoft and Health-ISAC and the June 2024 Operation Morpheus takedown of 593 servers, and actors increasingly use alternatives such as Sliver. Beacon's sleep/jitter check-in pattern is still the reference beaconing signature. and BC Security’s Empire; caret and substring tricks are catalogued in Daniel Bohannon’s Invoke-DOSfuscation research (2018):
Base64 encoding
powershell.exe -EncodedCommand <long-base64-string>The encoded blob hides the actual command from plain-text matching. The decode workflow below turns it back into readable intent.
Caret insertion
cmd.exe /c e^ch^o “Hello”cmd strips the escape carets before execution, so the command runs normally while breaking naive substring signatures. Interior quotes (w”h”oami) work the same way. Parsing tip: carets survive only in the cmd.exe line itself. Read the child process’s command line, which arrives with the carets already stripped.
Variable expansion
$env:COMSPECUses environment variables to mask binary references. cmd can even assemble strings from variable substrings (%COMSPEC:~-7,1% extracts a single letter), so the payload never appears literally.
Adversaries also abuse trusted system binaries (ATT&CK T1218, System Binary Proxy Execution): LOLBins LOLBins Living Off the Land Binaries: trusted, signed system executables (certutil, rundll32, mshta) weaponized so the malicious part is the argument line, not the file on disk. The evasion face of the Living Off The Land technique covered under Execution. such as certutil.exe for downloads, regsvr32.exe for DLL execution, bitsadmin.exe for transfers. These blend in because the binary is signed, trusted, and present on every host, which defeats allowlisting and hash-based detection. They are not footprint-free: downloaded files land on disk (certutil can also leave entries under CryptnetUrlCache), BITS jobs appear in the Microsoft-Windows-Bits-Client/Operational log and the QMGR job database, and the command line itself is usually the strongest artifact. The LOLBAS project (lolbas-project.github.io) catalogs Windows examples; GTFOBins and LOOBins cover Linux/Unix and macOS.
Paste-and-run (ClickFix)
A fake CAPTCHA, browser error or “verification” page tells the user to paste a command into the Run dialog (Win+R), a terminal, or File Explorer’s address bar (ATT&CK T1204.004, Malicious Copy and Paste). Look for explorer.exe launching powershell.exe, mshta.exe or curl.exe with a URL, seconds after a browser visit, often with flags such as -w h and iex(irm …). Run-dialog variants leave the pasted command as a new value under HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU. The user ran it themselves, so no exploit or attachment appears in the tree.
Educational, not operational
The examples in this chapter are illustrative. We deliberately do not show fully working invocation strings. Analysts need to recognize the shape of adversary technique, not have a copy-pasteable cookbook. Decoding what an attacker already ran is defensive analysis, and everything below stays on that side of the line. If you need to test detections, use isolated lab environments and sanctioned red-team tools.
The decode workflow
The single most common parsing task this page exists for: an alert hands you powershell.exe -nop -w hidden -enc SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQA... and the verdict depends on what that blob says. It is encoding, not encryption. There is no key. It decodes locally in seconds, if you know the one gotcha.
Check whether Windows already decoded it
If PowerShell Script Block Logging is enabled (or the block tripped PowerShell’s automatic logging of suspicious script blocks, which runs even when full logging is off), Event 4104 in Microsoft-Windows-PowerShell/Operational holds the decoded text of every layer, joined by ScriptBlockId. Module logging (4103), AMSI telemetry in your EDR, and transcription files can hold it too. Pull that first; decode by hand only when it is absent, and record which you used. The old powershell -version 2 downgrade that evaded these controls is gone on hosts where Microsoft has removed PowerShell 2.0.
Extract the blob
Copy the Base64 string out of the alert into a local decoder. Never paste it into a terminal that could execute it, and never run the command to “see what it does.” CyberChef, which runs entirely client-side in the browser (use the downloadable offline build for sensitive cases), is the standard tool.
Decode Base64, then interpret as UTF-16LE
This is the gotcha that trips every junior once: -EncodedCommand takes Base64 of UTF-16LE text, because that is what Windows means by “Unicode.” Decode it as UTF-8 and you get the characters interleaved with null bytes (I·E·X· ·(·N·e·w), which some tools render as gibberish or CJK characters. In CyberChef the recipe is From Base64 followed by Decode Text (UTF-16LE). If your output has a space or dot between every letter, you skipped the second step.
Read the result, and expect another layer
The example blob above opens with IEX (New-Object …: the classic download-and-execute-in-memory cradle. Real payloads often nest: the decoded text itself calls FromBase64String plus a Gzip or Deflate decompress, then IEX again. Keep unwinding layers in the decoder until you reach readable intent, and record each layer in your notes.
Treat what falls out as hot
URLs, domains, and IPs inside the decoded payload are live attacker infrastructure until proven otherwise. Do not browse them to check. They are IOCs: record them, look them up in threat intelligence Threat Intelligence Evidence-based knowledge about existing or emerging threats, including context, mechanisms, indicators, implications, and actionable advice (after Gartner's widely cited definition). It is consumed at strategic, operational, and tactical levels. Before acting on it, weigh the source's reliability, the information's credibility (the Admiralty code is one common scheme), and its age. , and pivot on them in the network telemetry.
The flags do not spell themselves out
PowerShell accepts abbreviated parameter prefixes: -e, -en, and -enc all resolve to -EncodedCommand, even though -ExecutionPolicy shares the -e prefix. A detection or a triage search that string-matches the full flag name misses every abbreviated form, which is exactly why attackers abbreviate. Parse by meaning, not by literal string. Normalize before you match: PowerShell also accepts / and Unicode dashes such as the en dash as the parameter prefix (/enc, –enc), and abbreviated values (-w h). A search for “-enc” misses all of them.
-EncodedCommand-e, -en, -enc, -ecPayload is Base64 of UTF-16LE. Decode it.-NoProfile-nopSkips profile scripts for a clean, fast, unmonitored-feeling start. Common in automation and in attacks alike.-WindowStyle Hidden-w hidden, -win hNo visible window. Legitimate scheduled scripts use it; so does nearly all malware.-NonInteractive-noniNo prompt back to a human. Expected from services, notable from a user session.-ExecutionPolicy Bypass-ep bypass, -exec bypassDisables script-execution restrictions for this process. Not an exploit (the policy is not a security boundary), but a strong tell of unmanaged script execution.No single flag is a verdict. -nop -w hidden -enc together on a workstation, spawned from an Office process, is a very different sentence than the same flags in a signed vendor scheduled task. The combination plus the context decides, and the decoded payload settles it.
When there is no command line to parse
Sometimes the alert’s command-line field is simply empty. The most common reason is not evasion; it is configuration. Windows Security Event 4688 records process creations, but its CommandLine field populates only when the “Include command line in process creation events” policy is enabled, and it is off by default. If it was never turned on, every historical event is blank and there is no retroactive fix. 4688 itself has a prerequisite too: the Audit Process Creation subcategory, also off by default, so on an unconfigured host there is no 4688 at all. When both are on, command lines can carry passwords and tokens: redact them before pasting into tickets or chat.
Know your source
Security 4688 without the policy: no command line. Sysmon Sysmon Microsoft Sysinternals service that writes detailed endpoint telemetry (process creation with command lines, network connections, driver and DLL loads, file-time changes) to the Windows event log for SIEM ingestion. Now also a built-in optional feature on Windows 11 and Server 2025 (rendered messages are localized, so parse the XML); Sysmon for Linux exists too. Event ID 1: full command line, parent, and hashes by default. EDR process telemetry: almost always captures it. Which source feeds your console determines what you can parse.
An empty field is a fact about telemetry
Record “command line not captured (4688 policy disabled)” rather than “no command line,” and pivot to the sources that do have it. Absence of the field is a visibility gap, not evidence the process ran without arguments.
Annotated sample: a 4688 with the command line missing
Trimmed and fictional; the field names are real.
<EventData>
<Data Name="SubjectUserName">jdoe</Data>
<Data Name="SubjectLogonId">0x3e7a21</Data>
<Data Name="NewProcessId">0x1fc0</Data>
<Data Name="NewProcessName">C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Data>
<Data Name="TokenElevationType">%%1938</Data>
<Data Name="ProcessId">0x1d4c</Data>
<Data Name="CommandLine"></Data>
<Data Name="ParentProcessName">C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE</Data>
<Data Name="MandatoryLabel">S-1-16-8192</Data>
</EventData>CommandLineis present and empty: the event schema has the field, the policy did not fill it. Record it as not captured, then pull the same process from Sysmon Event ID 1 or the EDR by host, PID and start time.- The IDs are hexadecimal.
NewProcessId0x1fc0 is PID 8128, the new process.ProcessId0x1d4c (PID 7500) is the creator, not the new process, which is the field juniors swap most often. TokenElevationType%%1938is a limited (UAC-filtered) token;%%1937is elevated, and%%1936is a full token with UAC off or the built-in administrator.MandatoryLabelS-1-16-8192 is Medium integrity.SubjectLogonIdties the creation to the logon session in the matching 4624.
Execution context
The same command can be benign or malicious depending on context. Four contextual signals matter most:
NT AUTHORITY\SYSTEM vs. a standard user. A SYSTEM-context process whose lineage leads back to a user’s interactive session suggests privilege escalation; installers handed off to the Windows Installer service are the common benign exception.
Outside business hours vs. scheduled maintenance window. Cross-reference with change tickets and the user’s known patterns.
cmd.exe spawned by outlook.exe is suspicious. The same command from Task Scheduler is usually legitimate.
C:\Windows\Temp, %TEMP% and C:\Users\Public deserve a second look. %APPDATA% and %LOCALAPPDATA% are mixed: per-user installs such as OneDrive and VS Code live there legitimately, so check the software inventory before reading location as intent. C:\Program Files is expected.
Example: PowerShell under an Office chain
Outlook → Word → PowerShell signals a macro in an opened attachment: the macro runs inside Word (or Excel), which becomes PowerShell’s parent, with Outlook one level above. That is less common now that Office blocks macros in internet-sourced files by default, so check whether the file carried the Mark of the Web and how the block was bypassed (unblocked by the user, saved to a Trusted Location, or delivered in a container that strips the mark). PowerShell spawned directly by outlook.exe is rarer and high-signal: it points at Outlook-based persistence (a malicious rule, a custom form, a folder Home Page, or the Outlook VBA project; ATT&CK T1137) or an exploit of Outlook itself. What you would check next:
- The attachment that was opened, and whether it carried the Mark of the Web.
- The script’s command line Command Line In SOC analysis, the argument string a process was launched with. Often the load-bearing forensic field on an EDR alert because it reveals what the process was actually told to do. for download cradle patterns.
- Outbound network activity from PowerShell in the next 60 seconds.
- For a direct outlook.exe parent: the mailbox’s rules, custom forms, folder Home Page settings, and the
VbaProject.OTMfile. - Whether the user’s mailbox shows similar emails to other recipients.
The same PowerShell command from Task Scheduler during a maintenance window is almost certainly legitimate. Same command, different parent, different verdict.
Beyond PowerShell and cmd
The same analysis transfers off Windows; only the vocabulary changes.
macOS and Linux pipes. curl … | sh and echo <base64> | base64 -d | bash are the download cradle and the encoded command of the Unix world. osascript -e running AppleScript from a non-interactive parent is the macOS counterpart of an Office macro spawning a shell. Two shapes dominate current macOS stealer intrusions (AMOS, MacSync, Odyssey): osascript drawing a fake system password prompt (display dialog … with hidden answer), and a user pasting a curl | bash or base64 one-liner into Terminal from a fake “verification” page.
Vendor-standard noise to recognize. Electron apps launch helpers with flags like —type=utility or —type=renderer. The command line in Case B of the Alert worked example (a macOS developer workstation running the Cursor IDE) is exactly this shape: long, odd-looking, and vendor-standard. Knowing the legitimate shapes is what keeps them from eating triage time.
Pattern recognition
Build mental patterns for atypical use of common binaries. These are the shapes you want to recognize before reading the command in detail.
Unusual LOLBin invocations. rundll32.exe, mshta.exe, regsvr32.exe invoked outside their normal contexts, and wmic.exe (legacy: removed from current Windows 11 builds in 2026; on modern hosts expect the same WMI abuse via Get-CimInstance / Invoke-CimMethod, or wmiprvse.exe as the parent).
Framework flags. The combinations in the flag table above, especially -nop -w hidden -enc together.
Indirect execution. A trusted binary loading attacker-controlled content from a remote location. The binary is legitimate. The payload is not.
Check yourself
An alert shows powershell.exe /w 1 /enc SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQA… with explorer.exe as its parent, twenty seconds after the user’s browser loaded an unfamiliar page. Parse it before you open the answer: what do the flags mean, what is the first source you check for the payload, and what does the parent tell you?
One way to answer
/w 1 is -WindowStyle Hidden (1 is the numeric value for Hidden) and /enc is -EncodedCommand, both with the / prefix a search for “-enc” would miss. Check Event 4104 for the decoded script blocks first; if it is absent, decode by hand (Base64, then UTF-16LE), and the opening IEX (New-Object says a download cradle follows. A browser visit followed by explorer.exe launching PowerShell is the paste-and-run (ClickFix) shape: look for a new RunMRU value, and treat the URL inside the payload as live infrastructure.
Key takeaway
Command line analysis Command Line Analysis Reading a process's command line for what it was told to do: the binary, its flags, encoded or obfuscated arguments, and the paths and URLs it names. See Command Line, and command-line parsing for the method. is where parsing Parsing Breaking a raw alert, log line, or command string into its component fields so each can be examined on its own: the user, the host, the action, the time. In triage, parsing the alert is the first move; the details that decide a verdict live in the fields, not in the alert name. Alert parsing and log parsing are the same move applied to different inputs. becomes investigation. The decode workflow turns an encoded blob into readable intent, the flag table keeps abbreviations from hiding it, and the 4688 gap reminds you to know what your telemetry actually captured. What the command says, weighed against its context, anchors everything downstream.
Next up
Process relationships
Parent-child chains and lineage reconstruction. Macro execution, persistence, hollowing, token theft.
Read process relationshipsTechnical details verified . Product names, defaults and retention change; check your own tenant.