Step 260. Windows Privilege Escalation, Fully Conquered — Doors of Services, Tokens, and Settings

Step 260. Windows Privilege Escalation, Fully Conquered — Doors of Services, Tokens, and Settings

Level 3 — Real-World CTF & Advanced Offensive Skills | Difficulty ★★★★☆ | Estimated time: 4 hours

Prerequisites: Step 125’s Linux privilege escalation concepts (misconfigurations vs. exploits) and Step 259’s Linux pattern checklist. Comfortable with basic PowerShell commands.

  • What you need: A Windows PC (the one you’re using right now is fine). Every command today is read-only, so you measure on your actual PC — you might even discover real vulnerable patterns on your own machine. The winPEAS body and attack scenes are presented as output examples.
  • ⚠️ All exercises in this chapter are for your own lab and legal platforms only. Applying them to unauthorized systems is a crime.

If Linux escalation was the world of SUID, sudo, and cron, Windows is a different ecosystem — services, token privileges, and registry settings are the stage. But the skeleton of the thinking is the same. Step 259’s question — "can a low privilege change what a high privilege executes?" — works on Windows too. Today you complete the Windows edition of the checklist by diagnosing the four flagship patterns yourself on your own PC: service binary permissions, Unquoted Service Path, AlwaysInstallElevated, and SeImpersonatePrivilege.


1. Learning Objectives

By the end of this chapter, you will be able to:

  • Read whoami /priv output and understand what SeImpersonatePrivilege means
  • Enumerate services’ executable paths and accounts with Get-CimInstance Win32_Service
  • Find Unquoted Service Paths and judge whether they’re exploitable
  • Read permission notations like (F) and (RX) in icacls output
  • Check both registry locations for AlwaysInstallElevated
  • Know how to prioritize what winPEAS output shows

2. Background Knowledge — Today’s Tools and Concepts

Today’s Tools at a Glance

Category Details
Language/environment Windows PowerShell (read-only measurements) + winPEAS and attack scenes as output examples
Today’s commands whoami /priv, Get-Service, Get-CimInstance Win32_Service, icacls, registry queries
Concepts needed Service accounts (LocalSystem), token privileges, Unquoted Service Path, AlwaysInstallElevated, the Potato family
Today’s deliverable Windows privesc checklist v1 + a diagnostic record of your own PC

2-1. Who Is Windows’ "root"? — SYSTEM and Services

Windows’ highest-privilege account is SYSTEM (precisely, NT AUTHORITY\SYSTEM). And the thing that handles "work administrators run automatically" on Windows is not cron — it’s services. A service runs as the account written in the StartName field of Get-CimInstance Win32_Service, and many services have LocalSystem there.

So Windows escalation’s core question translates like this — "can I change the executable or path of a service running as SYSTEM?" Exactly the same question as Linux’s "can I modify a script that root’s cron runs?"

2-2. Tokens and Privileges — Reading whoami /priv

Every principal that logs into Windows receives an ID card called an access token. This card lists group memberships along with privileges — and whoami /priv shows exactly that list.

Among dozens of privileges, the name attackers look for is SeImpersonatePrivilege ("permission to impersonate another principal"). This privilege was designed so service accounts (IIS’s iis apppool\defaultapppool, NT SERVICE\..., etc.) could work on behalf of clients, but if you get a shell holding this privilege, Potato-family attacks (PrintSpoofer, GodPotato, etc.) can "impersonate" and steal SYSTEM’s identity. You got a single web shell and that account held this privilege — that is the most common plot of Windows escalation.

2-3. Unquoted Service Path — The Trap of Spaces and Quotes

Suppose a service’s executable path is registered in the registry like this:

C:\Program Files (x86)\Vendor\Product Name\Service.exe

With no quotes. Windows reads this string by chopping it at each space from the front, looking for an executable at each cut point:

  1. C:\Program.exe → if not found
  2. C:\Program Files (x86)\Vendor\Product.exe → if not found
  3. C:\Program Files (x86)\Vendor\Product Name\Service.exe → finally executed

So if an attacker plants a file named something like Product.exe in a writable folder at one of the intermediate cut points, it executes with SYSTEM privileges at the next service restart. Finding "services whose path contains spaces but has no quotes" is this pattern’s discovery step, and in 3-3 you diagnose your own PC directly.

2-4. AlwaysInstallElevated — A Mistake in Two Registry Locations

Windows installer packages (.msi) are supposed to require administrator rights. But if AlwaysInstallElevated = 1 is set simultaneously in two placesHKLM and HKCU‘s SOFTWARE\Policies\Microsoft\Windows\Installer — then even a .msi launched by a regular user installs with SYSTEM privileges. This setting, left for administrative convenience, means to an attacker "build a malicious msi and double-click it for SYSTEM." Checking takes a single read command — measured in 3-5.

2-5. winPEAS — Automated Enumeration for Windows

winPEAS is the Windows edition of the same project (PEASS-ng) as Step 126’s linPEAS. It sweeps hundreds of items at once — service permissions, Unquoted Paths, AlwaysInstallElevated, saved credentials, missing patches — and highlights them. The principle is the same as linPEAS: the tool collects; the human confirms. One Windows-specific caution: the winPEAS executable and Potato-family tools get caught by Defender (antivirus). Turn it off in the lab for practice, and thinking about "why it gets caught" (signatures of known attack tools) is real-world instinct.


3. Follow Along

Every command today is read-only — you can run them safely on your actual Windows PC. Open PowerShell and follow along. Measurements were taken 2026-09-09 on Windows PowerShell 5.1 (account and PC names altered).

3-1. My Privilege ID Card — whoami /priv

whoami
whoami /priv

Output (measured 2026-09-09):

labpc\student
PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                          State
============================= ==================================== ========
SeShutdownPrivilege           Shut down the system                 Disabled
SeChangeNotifyPrivilege       Bypass traverse checking             Enabled
SeUndockPrivilege             Remove computer from docking station Disabled
SeIncreaseWorkingSetPrivilege Increase a process working set       Disabled
SeTimeZonePrivilege           Change the time zone                 Disabled

How to read it: Only five, and decisively, SeImpersonatePrivilege is absent — this is a regular user’s normal state. When you get a web shell or service shell in a lab and this privilege shows up in the list, that is the signal to "consider the Potato family." Also check: the first line of whoami /groups is usually Mandatory Label\Medium Mandatory Level — meaning "I am a regular user at medium integrity level" (measured 2026-09-09).

3-2. The Service Map — Who Runs as SYSTEM

Get-Service | Where-Object {$_.Status -eq 'Running'} | Select-Object -First 5
Get-CimInstance Win32_Service | Select-Object -First 3 Name, State, StartName, PathName | Format-List

Output (measured 2026-09-09, excerpt):

Status   Name              DisplayName
------   ----              -----------
Running  Appinfo           Application Information
Running  AudioEndpointBu... Windows Audio Endpoint Builder
Running  Audiosrv          Windows Audio
...
Name      : ADPSvc
State     : Stopped
StartName : NT AUTHORITY\LocalService
PathName  : C:\WINDOWS\system32\svchost.exe -k LocalServiceAndNoImpersonation -p
...

How to read it: The four fields of Win32_Service are all of service diagnosis — Name (the name), State (running?), StartName (as which privilege? — LocalSystem is a jackpot candidate), PathName (executes what?). It’s the list of "what high privileges run automatically," the counterpart of Linux’s cat /etc/crontab. Note: on machines with Git Bash installed, whoami inside PowerShell may resolve to Git’s version and fail with /usr/bin/whoami: extra operand '/priv' (measured 2026-09-09) — in that case type the full path, C:\Windows\System32\whoami.exe.

3-3. Diagnosing Unquoted Service Paths — Searching on My Own PC

Get-CimInstance Win32_Service | Where-Object {
    $_.PathName -match '^[A-Za-z]:\\[^"].* .*\.exe' -and $_.PathName -notmatch '^"'
} | Select-Object Name, State, StartName, PathName | Format-List

The condition is "paths that don’t start with a quote (-notmatch '^"'), contain a space (.* .*), and end in exe." Output (measured 2026-09-09 — two were actually found):

Name     : HncUpdateService_2020
State    : Running
StartMode: Auto
StartName: LocalSystem
PathName : C:\Program Files (x86)\HNC\Office 2020\HncUtils\Service\HncUpdateService.exe

Name     : TCWSCSVC
State    : Running
StartMode: Auto
StartName: LocalSystem
PathName : C:\Program Files (x86)\EPS\Lib\SupportTC\TCWSLocalServer.exe

How to read it: The pattern’s shape is perfect — no quotes, spaces present (Office 2020, etc.), and even LocalSystem + auto-start + currently running. So for the first service, Windows searches like this — C:\Program Files (x86)\HNC\Office.exe → not found → proceeds to ...\HncUtils\Service\.... But a candidate is only a candidate (Step 126’s principle). Exploitability is decided by the next question — "can I create Office.exe in the C:\Program Files (x86)\HNC\ folder?" Which leads straight to the permission check in the next section.

3-4. icacls — Judging Candidate Validity

icacls "C:\Program Files (x86)\HNC\Office 2020\HncUtils\Service\HncUpdateService.exe"
icacls "C:\Program Files (x86)\EPS\Lib"

Output (measured 2026-09-09, key lines):

... HncUpdateService.exe NT AUTHORITY\SYSTEM:(I)(F)
                         BUILTIN\Administrators:(I)(F)
                         BUILTIN\Users:(I)(RX)
                         ...
Successfully processed 1 files; Failed processing 0 files
C:\Program Files (x86)\EPS\Lib NT SERVICE\TrustedInstaller:(I)(F)
                               NT AUTHORITY\SYSTEM:(I)(F)
                               BUILTIN\Administrators:(I)(F)
                               BUILTIN\Users:(I)(RX)
                               ...

How to read it: icacls permission abbreviations — (F) Full Control, (RX) Read & Execute, (W) Write, (I) inherited. BUILTIN\Users — i.e., regular users — have only (RX) everywhere. No write access, so both candidates get a "dead" verdict. Regular users can change neither the executables nor the intermediate folders. This is the most important harvest of today’s measurement — finding a pattern’s shape on a real PC and judging it dead via permissions is one complete diagnostic set. On a lab’s vulnerable machine, this is the spot where BUILTIN\Users:(F) or (W) stands — that single letter is the escalation path.

3-5. AlwaysInstallElevated — Checking Two Registry Locations

Get-ItemProperty "HKCU:\SOFTWARE\Policies\Microsoft\Windows\Installer" -ErrorAction SilentlyContinue
Get-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Installer" -ErrorAction SilentlyContinue

Output (measured 2026-09-09):

(Neither key exists — returns with no output)

How to read it: If the key itself doesn’t exist, it’s the same as the value being 0 — the normal, non-vulnerable state. This setting is dangerous only when both HKLM and HKCU have AlwaysInstallElevated = 1 — one side alone doesn’t count. In labs you’ll also often check with reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated (a different way to read the same value).

3-6. winPEAS — Output Example

winPEAS isn’t installed in this environment (installing it would get it caught by Defender), so follow the lab flow as an output example:

# On a lab machine (output example)
.\winPEASx64.exe quiet fastinfo > peas.txt
══════════╣ Services Information ╠══════════
[+] Interesting Services -non Microsoft-
    HncUpdateService_2020 (HNC)[C:\Program Files (x86)\...\HncUpdateService.exe]
    - Unquoted and Space detected!         ← red highlight: Unquoted Service Path candidate
══════════╣ Registry: AlwaysInstallElevated ╠══════════
    HKCU: 1, HKLM: 1                       ← red highlight: both 1 = vulnerable
══════════╣ Token privileges ╠══════════
    SeImpersonatePrivilege: Enabled        ← red highlight: Potato-family candidate

How to read it: The three patterns you diagnosed manually today are highlighted as exactly the same items in winPEAS. Automation is only "omission prevention"; the judgment criteria (write permissions in icacls, both registry values at 1, presence of the privilege) are exactly what you learned by hand. And remember the final gate — the act of replacing a service binary or planting an msi is lab-only, and it’s normal for those files to trip Defender’s signatures.


4. Missions & Exercises

Mission — Windows Privesc Checklist v1 + My PC Diagnostic Report

  1. Run every command from 3-1 to 3-5 on your PC and save the outputs
  2. Attach an icacls verdict (valid/dead) to each candidate found in the Unquoted Service Path search — if none, record "confirmed none"
  3. Organize the four patterns (service binary permissions, Unquoted Path, AlwaysInstallElevated, SeImpersonatePrivilege) into a table of ① discovery command ② exploitability condition ③ why it’s dangerous, creating win-privesc-checklist-v1.md
  4. Place it next to Step 259’s Linux checklist and write a paragraph comparing "common question / different commands"
  5. (If you have a lab) Confirm one real escalation path on a vulnerable Windows machine and keep before/after whoami as evidence

Exercises

Q1. If whoami /priv shows SeImpersonatePrivilege, which attack family should you consider, and what is this privilege’s original purpose?

Q2. Using the 3-3/3-4 measurements as evidence, explain a case where an Unquoted Service Path is "vulnerable in shape but judged dead."

Q3. What registry condition must hold for AlwaysInstallElevated to become dangerous, and what file format is the attack material in that case?

Q4. From the perspective of "what high privileges execute," explain why service diagnosis must always check Win32_Service‘s StartName.


5. Model Answers & Completion Criteria

Mission Model Answer

A completed example of checklist v1:

Pattern Discovery command Exploitability condition Why it’s dangerous
Service executable Get-CimInstance Win32_Service + icacls Users have (F) or (W) Replace what a SYSTEM service executes
Unquoted Path Regex filter (3-3) Intermediate folder writable Plant an exe at a space cut point → SYSTEM execution
AlwaysInstallElevated HKLM & HKCU registry queries Both set to 1 An msi installs as SYSTEM
Token privilege whoami /priv Holds SeImpersonatePrivilege Impersonate SYSTEM via the Potato family

An example conclusion of the PC diagnostic report (section 3 measurements): "Found 2 Unquoted candidates (HncUpdateService_2020, TCWSCSVC) — both LocalSystem and auto-start, but Users permissions are only (RX), so dead. AlwaysInstallElevated keys absent (normal). My account lacks SeImpersonatePrivilege (normal)."

How to verify: ① Does the report separate "discovery" from "verdict" — ending at candidate discovery is incomplete. ② Do dead verdicts carry icacls output as evidence? ③ Does the comparison paragraph with the Linux checklist contain the common question "can a low privilege change what a high privilege executes?"

Exercise Answers

A1. Consider the Potato family (PrintSpoofer, GodPotato, etc.) — attacks that trick a SYSTEM process into letting its token be "impersonated." The original purpose is a legitimate feature letting a service account temporarily borrow the identity of a connecting client to do work with that client’s rights. That’s why this privilege is commonly found on service-account shells, and why it’s the standard path from web shell → SYSTEM.

A2. Even if the path has spaces and no quotes (the shape), it fails if the attacker lacks write permission on the intermediate cut-point folders where a file would be planted. In 3-3, two services were found as LocalSystem Unquoted Paths, but 3-4’s icacls showed BUILTIN\Users:(I)(RX) — read and execute only — so Office.exe couldn’t be planted and both were judged dead. The two stages, shape discovery → permission verdict, must always come together.

A3. Both HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer and HKCU\... must have AlwaysInstallElevated = 1. The attack material is a .msi installer package — in labs you build a reverse-shell msi with msfvenom and run it, and the installer executes its contents with SYSTEM privileges. If the keys are absent as in the 3-5 measurement, that’s the same as value 0: the normal state.

A4. Because the privilege you gain by replacing or manipulating a service is that service’s run-as account privilege. If StartName is LocalSystem, success means the highest privilege, but if it’s LocalService or a domain user, you stop at that privilege. Unless the premise "what high privileges execute" is confirmed in the StartName field, even a writable executable may be worth nothing for escalation — that’s why the judgment order is StartName → PathName → icacls.

Completion Criteria Checklist

  • [ ] Checked whoami /priv for SeImpersonatePrivilege and understand its meaning
  • [ ] Can read the four fields of Get-CimInstance Win32_Service (Name/State/StartName/PathName)
  • [ ] Ran the Unquoted Service Path search command myself
  • [ ] Can distinguish (F) from (RX) in icacls output and judge valid/dead
  • [ ] Know the "both locations set to 1" condition of AlwaysInstallElevated
  • [ ] Can explain winPEAS’s role and Defender detection
  • [ ] Mission: completed win-privesc-checklist-v1.md and my PC diagnostic report

6. Common Pitfalls & Fixes

Wall 1. whoami /priv throws an "extra operand" error

Symptom (measured 2026-09-09):

/usr/bin/whoami: extra operand '/priv'
Try '/usr/bin/whoami --help' for more information.

Cause: On PCs with Git Bash etc. installed, the Unix version of whoami gets picked up first in PATH — Unix whoami has no /priv option.

Fix: Call it with the full path — C:\Windows\System32\whoami.exe /priv. In PowerShell, the form & C:\Windows\System32\whoami.exe /priv is reliable.

Wall 2. Found an Unquoted Path but don’t know what to do next

Symptom: You found a candidate and your hands stop.

Cause: The judgment procedure between "discovery" and "exploitable" is missing.

Fix: Memorize the order sheet — ① make the list of space cut points from PathName (e.g., ...\HNC\Office.exe) → ② run icacls on each cut point’s folder → ③ if any cut point has (F)/(W) for Users/your groups, it’s valid; otherwise record it dead. Up to ③ is one cycle.

Wall 3. winPEAS disappears right after downloading

Symptom: The downloaded exe vanishes before it even runs.

Cause: Defender real-time protection quarantined it instantly via signatures of known attack tools — normal behavior.

Fix: On lab VMs, proceed after "Windows Security → Virus & threat protection → turn off real-time protection" (lab only). And think one step further — in the real world, your tools getting caught means detection is alive, which is why professional penetration tests lean more on manual commands (today’s read-only diagnostics). Reading antivirus not as an "obstacle" but as "the baseline of detection" is the mature perspective.

Wall 4. Registry queries flash red errors

Symptom: Get-ItemProperty shows a red error that the path can’t be found.

Cause: The key doesn’t exist — that means not vulnerable, not command failure.

Fix: Append -ErrorAction SilentlyContinue and it passes quietly (see the 3-5 commands). Record "absent" as a normal judgment result, not an error — enumeration is also the work of confirming what isn’t there (Step 126).

Wall 5. I thought SYSTEM was the top, but I hear there’s something above it

Symptom: A name called TrustedInstaller shows up ahead of SYSTEM in icacls (it’s in the 3-4 output too).

Cause: Windows has TrustedInstaller (the Windows component installation service), a principal above SYSTEM, and some system files are owned by it.

Fix: At this stage, just know it exists. What practical judgment needs is only "does my group (Users etc.) have write?" — the SYSTEM/TrustedInstaller hierarchy is a story for after escalation. Don’t complicate your judgment criteria.


7. Summary

Today’s Concepts

Concept One-line description
SYSTEM (LocalSystem) Windows’ highest privilege — the target point of service escalation
Access token / privileges The permission list written on the login ID card — whoami /priv
SeImpersonatePrivilege The "impersonation" privilege — the seed of Potato-family escalation
Unquoted Service Path An unquoted path with spaces — plant an exe at an intermediate cut point
AlwaysInstallElevated If both HKLM and HKCU are 1, an msi installs as SYSTEM
winPEAS Automated enumeration for Windows — collects candidates; humans judge

Today’s Commands

Command What it does
whoami /priv My token’s privilege list
whoami /groups Check groups and integrity level
Get-CimInstance Win32_Service Map of services’ accounts and paths
icacls path Judge file/folder permissions ((F)/(RX))
Get-ItemProperty HKLM:\...\Installer Check AlwaysInstallElevated
.\winPEASx64.exe Automated enumeration (lab only, output example)

The Instinct That Matters More Than Commands

Linux and Windows differ in commands; the question is one — "can a low privilege change what a high privilege executes?" crontab merely became Win32_Service, and ls -l became icacls. And today’s measurement showed another instinct — Unquoted Path candidates turn up commonly even on real PCs, but most die at the permission check. A vulnerability is not a "shape" but the product of "shape × permissions." Finding, then judging — that two-beat rhythm is the rhythm of escalation recon.


Once every box is checked, Step 260 is complete. Click the checkbox in the sidebar to save your progress.