T1059.001

PowerShell

Windows

What it is

PowerShell is Microsoft's built-in scripting and automation shell, present on every modern Windows system by default. That ubiquity is exactly why it's one of the most heavily abused execution mechanisms in real intrusions: an attacker doesn't need to drop a custom tool that might get flagged by antivirus, they can just run PowerShell, a program every Windows machine already trusts and every administrator already uses constantly.

What separates malicious PowerShell use from the thousands of legitimate administrative scripts running on any given day isn't the interpreter itself, it's how it's invoked. Encoded commands (Base64-wrapped, passed via `-EncodedCommand`), heavy obfuscation (string concatenation, backtick escapes, character substitution), and unusual parent-process chains are the real signal, not "PowerShell ran" on its own.

How adversaries use it

Once an attacker has any form of code execution, PowerShell is often the very next step, used to download additional tools, run reconnaissance commands, or establish persistence, all without writing a traditional executable to disk. Encoding the command is a deliberate evasion choice: a Base64-wrapped one-liner is unreadable at a glance in a process list or a security alert, and it defeats simple keyword-matching that looks for plaintext strings like "downloadstring" or "invoke-expression."

This is exactly what PowerShell Script Block Logging exists to defeat. Windows decodes an encoded command internally before it actually executes, and Script Block Logging captures that decoded content, not just the obfuscated wrapper. So the obfuscation genuinely hides the command from a casual glance at a process list, but it does not hide it from this specific log source, which is why 4104 matters so much more here than the command line alone.

Detect it in Elastic

Data source: Sysmon Event ID 1 for the powershell.exe launch, its encoded command line and parent-process fields, joined by process ID to the Event 4104 script blocks that decode it

Key fields

Sysmon Event ID 1 (event.code: "1") captures the full process creation record, most importantly process.command_line, which is where an encoded PowerShell invocation actually shows up (look for `-enc`, `-EncodedCommand`, or a long Base64-looking string), plus process.parent.name to check what launched it. PowerShell's own Script Block Logging, Event ID 4104 (event.code: "4104"), is the field that actually defeats the obfuscation: powershell.file.script_block_text contains the decoded, human-readable script content, since Windows logs it after decoding, not the encoded blob a process-creation event alone would show.

Example event

{
  "host": {
    "name": "WKSTN02"
  },
  "event": {
    "code": "1",
    "action": "start"
  },
  "process": {
    "name": "powershell.exe",
    "command_line": "powershell.exe -enc SQBuAHYAbwBrAGUALQ..."
  }
}

Prebuilt Elastic rule: Suspicious Windows Powershell Arguments

Hunt guidance

Start with the process-creation event, filtering event.code: "1" and process.name: "powershell.exe" for command lines containing encoding flags or unusually long argument strings. That tells you *that* something suspicious ran, but the encoded command line itself won't tell you what it actually does.

That's what the 4104 event is for. Pull the script-block event correlating to the same process (matched by host and time window, or process.entity_id where available) and read powershell.file.script_block_text directly. Because Windows decodes the command before logging it there, this is the one place obfuscation genuinely doesn't work, no manual Base64 decoding required, no need to reverse the attacker's evasion technique yourself.

Ruling out legitimate activity

Encoded and obfuscated PowerShell isn't inherently malicious. Legitimate software deployment tools, scheduled maintenance scripts, and some security products themselves routinely use `-EncodedCommand` to safely pass complex scripts through the command line without worrying about quoting or escaping issues.

The distinguishing signal is context: an encoded command launched from a known, expected administrative source (a deployment tool, a scheduled task running under a service account) at a routine time is very different from the same pattern launched from an unexpected parent process, by an interactive user account, at an unusual hour. The decoded script content itself, visible in the 4104 event, is often the clearest signal of all, since a legitimate deployment script reads very differently from one that immediately reaches out to download and execute something.

References

Practice it

1 scenario in this catalog covers T1059.001. We don't name it — identifying the technique is part of what a scenario grades. Explore the dashboard →