threat hunting

Detecting T1548 Abuse Elevation Control Mechanism

Detect abuse of elevation control mechanisms including UAC bypass, sudo exploitation, and setuid/setgid manipulation by monitoring registry modifications, process elevation flags, and unusual parent-child process relationships.

elevation-controlmitre-t1548privilege-escalationthreat-huntinguac-bypasswindows-security
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

When to Use

  • When hunting for privilege escalation via UAC bypass in Windows environments
  • After threat intelligence indicates use of UAC bypass exploits by active threat groups
  • When investigating how attackers achieved administrative access without triggering UAC prompts
  • During security assessments to validate UAC bypass detection coverage
  • When monitoring for setuid/setgid abuse on Linux systems

Prerequisites

  • Sysmon Event ID 1 with command-line and parent process logging
  • Windows Security Event ID 4688 with process tracking
  • Registry auditing for UAC-related keys (HKCU\Software\Classes)
  • Sysmon Event ID 12/13 (Registry key/value modification)
  • EDR with elevation monitoring capabilities

Workflow

  1. Monitor UAC Registry Modifications: Many UAC bypasses modify registry keys under HKCU\Software\Classes\ms-settings\shell\open\command or HKCU\Software\Classes\mscfile\shell\open\command. Track Sysmon Events 12/13 for these changes.
  2. Detect Auto-Elevating Process Abuse: Certain Windows binaries auto-elevate without UAC prompts (fodhelper.exe, computerdefaults.exe, eventvwr.exe). Hunt for these being launched by non-standard parent processes.
  3. Track Process Integrity Level Changes: Monitor for processes escalating from medium to high integrity level without corresponding UAC consent events.
  4. Hunt for Elevated Process Spawning: Detect when auto-elevating processes spawn unexpected children (cmd.exe, powershell.exe) -- indicating UAC bypass exploitation.
  5. Monitor Linux Elevation Abuse: Track sudo misconfiguration exploitation, setuid binary abuse, and capability manipulation.
  6. Correlate with Privilege Escalation Chain: Map elevation abuse to the broader attack chain, identifying what was done with escalated privileges.

Key Concepts

Concept Description
T1548.002 Bypass User Account Control
T1548.001 Setuid and Setgid (Linux)
T1548.003 Sudo and Sudo Caching
T1548.004 Elevated Execution with Prompt (macOS)
UAC Auto-Elevation Windows binaries that elevate without prompt
fodhelper.exe Common UAC bypass vector via registry hijack
eventvwr.exe MSC file handler UAC bypass
Integrity Level Windows process trust level (Low/Medium/High/System)

Detection Queries

Splunk -- UAC Bypass via Registry Modification

index=sysmon (EventCode=12 OR EventCode=13)
| where match(TargetObject, "(?i)HKCU\\\\Software\\\\Classes\\\\(ms-settings|mscfile|exefile|Folder)\\\\shell\\\\open\\\\command")
| table _time Computer User EventCode TargetObject Details Image

Splunk -- Auto-Elevating Process Abuse

index=sysmon EventCode=1
| where match(Image, "(?i)(fodhelper|computerdefaults|eventvwr|sdclt|slui|cmstp)\.exe$")
| where NOT match(ParentImage, "(?i)(explorer|svchost|services)\.exe$")
| table _time Computer User Image CommandLine ParentImage ParentCommandLine

KQL -- UAC Bypass Detection

DeviceRegistryEvents
| where Timestamp > ago(7d)
| where RegistryKey has_any ("ms-settings\\shell\\open\\command", "mscfile\\shell\\open\\command")
| where ActionType == "RegistryValueSet"
| project Timestamp, DeviceName, RegistryKey, RegistryValueData, InitiatingProcessFileName

Sigma Rule

title: UAC Bypass via Registry Modification
status: stable
logsource:
    product: windows
    category: registry_set
detection:
    selection:
        TargetObject|contains:
            - '\ms-settings\shell\open\command'
            - '\mscfile\shell\open\command'
            - '\exefile\shell\open\command'
    condition: selection
level: high
tags:
    - attack.privilege_escalation
    - attack.t1548.002

Common Scenarios

  1. fodhelper.exe Registry Hijack: Attacker sets HKCU\Software\Classes\ms-settings\shell\open\command to a malicious executable, then launches fodhelper.exe which auto-elevates and executes the hijacked command.
  2. eventvwr.exe MSC Bypass: Modifying HKCU\Software\Classes\mscfile\shell\open\command to intercept Event Viewer's auto-elevation behavior.
  3. sdclt.exe Bypass: Leveraging the Windows Backup utility's auto-elevation to execute arbitrary commands.
  4. CMSTP.exe INF Bypass: Using Connection Manager Profile Installer with a malicious INF file to bypass UAC via /s /ni flags.
  5. DLL Hijacking in Auto-Elevate: Placing malicious DLLs in search paths of auto-elevating executables.

Output Format

Hunt ID: TH-UAC-[DATE]-[SEQ]
Host: [Hostname]
Bypass Method: [Registry hijack/DLL hijack/Token manipulation]
Auto-Elevate Binary: [fodhelper.exe/eventvwr.exe/etc.]
Registry Key Modified: [Full registry path]
Payload Executed: [Command or binary path]
User Context: [Account]
Risk Level: [Critical/High/Medium]
ATT&CK Technique: [T1548.00x]
Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 3

api-reference.md2.5 KB

API Reference: T1548 Abuse Elevation Control Mechanism

MITRE ATT&CK T1548 Sub-Techniques

Sub-technique Name Platform
T1548.001 Setuid and Setgid Linux/macOS
T1548.002 Bypass User Account Control Windows
T1548.003 Sudo and Sudo Caching Linux/macOS
T1548.004 Elevated Execution with Prompt macOS

UAC Bypass — Auto-Elevate Binaries

Known Auto-Elevate Targets

Binary Bypass Method
fodhelper.exe Registry key hijack
computerdefaults.exe ms-settings handler
eventvwr.exe mscfile handler
sdclt.exe App paths hijack
wsreset.exe Bypasses defender
cmstp.exe INF file execution

Registry Keys for UAC Bypass

HKCU\Software\Classes\ms-settings\Shell\Open\command
HKCU\Software\Classes\mscfile\Shell\Open\command

Windows UAC Configuration

Check UAC Level

Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
# EnableLUA = 1 (UAC enabled)
# ConsentPromptBehaviorAdmin = 0-5

ConsentPromptBehaviorAdmin Values

Value Behavior
0 Elevate without prompting
1 Prompt for credentials on secure desktop
2 Prompt for consent on secure desktop
5 Prompt for consent (default)

Linux Privilege Escalation

sudo Configuration Check

sudo -l                    # List allowed commands
cat /etc/sudoers           # Full sudoers file
visudo -c                  # Validate syntax

Find SUID Binaries

find / -perm -4000 -type f 2>/dev/null
find / -perm -2000 -type f 2>/dev/null   # SGID

GTFOBins Sudo Escapes

Binary Escape
vim sudo vim -c ':!/bin/bash'
find sudo find . -exec /bin/bash \;
python sudo python -c 'import os; os.system("/bin/bash")'
nmap sudo nmap --interactive (old versions)

Sysmon Detection Rules

Event 13 — Registry Value Set

<RegistryEvent onmatch="include">
  <TargetObject condition="contains">ms-settings\Shell\Open\command</TargetObject>
  <TargetObject condition="contains">mscfile\Shell\Open\command</TargetObject>
</RegistryEvent>

Sigma Rule — UAC Bypass

title: UAC Bypass via Fodhelper
logsource:
    product: windows
    category: registry_set
detection:
    selection:
        TargetObject|contains: 'ms-settings\Shell\Open\command'
    condition: selection
level: critical
standards.md2.0 KB

Standards and References - T1548 Elevation Control Abuse

MITRE ATT&CK Sub-Techniques

Sub-Technique Platform Description
T1548.001 Linux/macOS Setuid and Setgid binary abuse
T1548.002 Windows Bypass User Account Control
T1548.003 Linux/macOS Sudo and Sudo Caching
T1548.004 macOS Elevated Execution with Prompt

Known UAC Bypass Methods (60+ documented)

Method Binary Registry Key Detection
fodhelper fodhelper.exe ms-settings\shell\open\command Registry + process creation
eventvwr eventvwr.exe mscfile\shell\open\command Registry + process creation
sdclt sdclt.exe exefile\shell\open\command Registry + process creation
computerdefaults computerdefaults.exe ms-settings\shell\open\command Registry + process creation
CMSTP cmstp.exe N/A (INF file) Process creation with /s /ni
slui slui.exe exefile\shell\open\command Registry + process creation
DiskCleanup cleanmgr.exe Environment variable hijack Environment + process

UAC-Related Registry Keys to Monitor

Registry Key Purpose
HKCU\Software\Classes\ms-settings\shell\open\command fodhelper/computerdefaults bypass
HKCU\Software\Classes\mscfile\shell\open\command eventvwr bypass
HKCU\Software\Classes\exefile\shell\open\command sdclt/slui bypass
HKCU\Software\Classes\Folder\shell\open\command Folder handler bypass
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA UAC disable
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\ConsentPromptBehaviorAdmin UAC level

Detection Events

Source Event ID Description
Sysmon 1 Auto-elevate process creation
Sysmon 12 Registry key creation (UAC keys)
Sysmon 13 Registry value modification
Security 4688 Process creation with elevation
Security 4657 Registry value modification audit
workflows.md1.8 KB

Detailed Hunting Workflow - T1548 Elevation Control Abuse

Phase 1: Registry-Based UAC Bypass Detection

Step 1.1 - Monitor UAC Registry Keys

index=sysmon (EventCode=12 OR EventCode=13)
| where match(TargetObject, "(?i)(ms-settings|mscfile|exefile|Folder)\\\\shell\\\\open\\\\command")
| table _time Computer User Image TargetObject Details EventCode

Step 1.2 - Detect UAC Policy Changes

index=sysmon EventCode=13
| where match(TargetObject, "(?i)Policies\\\\System\\\\(EnableLUA|ConsentPromptBehaviorAdmin)")
| table _time Computer User Image TargetObject Details

Phase 2: Auto-Elevating Process Chain Detection

Step 2.1 - Suspicious Auto-Elevate Launches

index=sysmon EventCode=1
| where match(Image, "(?i)(fodhelper|computerdefaults|eventvwr|sdclt|slui)\.exe$")
| where NOT match(ParentImage, "(?i)(explorer\.exe|svchost\.exe)$")
| stats count by Image ParentImage Computer User

Step 2.2 - Children of Auto-Elevate Processes

index=sysmon EventCode=1
| where match(ParentImage, "(?i)(fodhelper|computerdefaults|eventvwr|sdclt|slui)\.exe$")
| where match(Image, "(?i)(cmd|powershell|wscript|cscript|mshta)\.exe$")
| table _time Computer Image CommandLine ParentImage User

Phase 3: Linux Elevation Abuse

Step 3.1 - Setuid Binary Hunting

find / -perm -4000 -type f 2>/dev/null
find / -perm -2000 -type f 2>/dev/null

Step 3.2 - Sudo Abuse Detection

index=linux sourcetype=syslog
| where match(_raw, "(?i)sudo.*COMMAND=")
| where NOT match(_raw, "(?i)(apt-get|yum|systemctl|service)")
| table _time host user command

Phase 4: Response

  1. Revert malicious registry modifications
  2. Investigate what was executed with elevated privileges
  3. Set UAC to highest level (Always Notify)
  4. Deploy ASR rules against UAC bypasses
  5. Monitor for repeated escalation attempts

Scripts 2

agent.py6.7 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for detecting T1548 Abuse Elevation Control Mechanism (UAC bypass, sudo abuse)."""

import argparse
import json
import os
import re
import subprocess
import sys
from datetime import datetime, timezone


UAC_BYPASS_BINARIES = [
    "fodhelper.exe", "computerdefaults.exe", "eventvwr.exe",
    "sdclt.exe", "slui.exe", "cmstp.exe", "mmc.exe",
    "wsreset.exe", "changepk.exe", "dism.exe",
]

UAC_BYPASS_REGISTRY_KEYS = [
    r"HKCU\Software\Classes\ms-settings\Shell\Open\command",
    r"HKCU\Software\Classes\mscfile\Shell\Open\command",
    r"HKCU\Software\Classes\exefile\Shell\Open\command",
    r"HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths",
]

SUDO_ABUSE_PATTERNS = [
    r"sudo\s+-u\s+\#-1",
    r"sudo\s+.*NOPASSWD",
    r"sudo\s+.*env_reset.*env_keep",
    r"sudo\s+\S+\s+/bin/bash",
    r"sudo\s+find\s+.*-exec",
    r"sudo\s+vim\s+-c\s+.*!",
    r"sudo\s+python\s+-c",
]


def check_uac_bypass_registry():
    """Check for UAC bypass registry modifications."""
    findings = []
    if sys.platform != "win32":
        return findings
    for key in UAC_BYPASS_REGISTRY_KEYS:
        try:
            result = subprocess.check_output(
                ["reg", "query", key], text=True, errors="replace", timeout=5
            )
            if result.strip() and "ERROR" not in result:
                findings.append({
                    "type": "uac_registry",
                    "key": key,
                    "value": result.strip()[:200],
                    "severity": "HIGH",
                })
        except subprocess.SubprocessError:
            pass
    return findings


def check_uac_bypass_processes():
    """Check Sysmon logs for auto-elevate binary abuse."""
    findings = []
    if sys.platform != "win32":
        return findings
    ps_cmd = (
        "Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational';"
        "Id=1} -MaxEvents 500 "
        "| Where-Object {$_.Properties[4].Value -match '"
        + "|".join(UAC_BYPASS_BINARIES)
        + "'} | Select-Object TimeCreated,"
        "@{N='Image';E={$_.Properties[4].Value}},"
        "@{N='CommandLine';E={$_.Properties[10].Value}},"
        "@{N='ParentImage';E={$_.Properties[20].Value}} "
        "| ConvertTo-Json"
    )
    try:
        result = subprocess.check_output(
            ["powershell", "-NoProfile", "-Command", ps_cmd],
            text=True, errors="replace", timeout=30
        )
        data = json.loads(result) if result.strip() else []
        if not isinstance(data, list):
            data = [data]
        for evt in data:
            parent = (evt.get("ParentImage", "") or "").lower()
            if "explorer.exe" not in parent and "svchost.exe" not in parent:
                findings.append({
                    "type": "uac_auto_elevate",
                    "time": evt.get("TimeCreated", ""),
                    "image": evt.get("Image", ""),
                    "parent": evt.get("ParentImage", ""),
                    "commandline": evt.get("CommandLine", "")[:200],
                })
    except (subprocess.SubprocessError, json.JSONDecodeError):
        pass
    return findings


def check_linux_sudo_abuse():
    """Check auth logs for sudo abuse patterns."""
    findings = []
    if sys.platform == "win32":
        return findings
    log_paths = ["/var/log/auth.log", "/var/log/secure"]
    for log_path in log_paths:
        if not os.path.isfile(log_path):
            continue
        try:
            with open(log_path, "r", errors="replace") as f:
                for line in f:
                    if "sudo" not in line.lower():
                        continue
                    for pat in SUDO_ABUSE_PATTERNS:
                        if re.search(pat, line, re.IGNORECASE):
                            findings.append({
                                "type": "sudo_abuse",
                                "log": log_path,
                                "line": line.strip()[:200],
                                "pattern": pat,
                            })
        except PermissionError:
            pass

    try:
        result = subprocess.check_output(
            ["sudo", "-l", "-n"], text=True, errors="replace", timeout=5
        )
        if "NOPASSWD" in result:
            for line in result.splitlines():
                if "NOPASSWD" in line:
                    findings.append({
                        "type": "nopasswd_sudo",
                        "rule": line.strip(),
                        "severity": "MEDIUM",
                    })
    except subprocess.SubprocessError:
        pass
    return findings


def check_setuid_binaries():
    """Find SUID/SGID binaries that could be abused for elevation."""
    findings = []
    if sys.platform == "win32":
        return findings
    try:
        result = subprocess.check_output(
            ["find", "/", "-perm", "-4000", "-type", "f"],
            text=True, errors="replace", timeout=30, stderr=subprocess.DEVNULL
        )
        known_suid = {"/usr/bin/sudo", "/usr/bin/passwd", "/usr/bin/su",
                      "/usr/bin/mount", "/usr/bin/umount", "/usr/bin/ping"}
        for line in result.strip().splitlines():
            path = line.strip()
            if path and path not in known_suid:
                findings.append({"type": "unusual_suid", "path": path})
    except subprocess.SubprocessError:
        pass
    return findings


def main():
    parser = argparse.ArgumentParser(
        description="Detect T1548 Abuse Elevation Control Mechanism"
    )
    parser.add_argument("--output", "-o", help="Output JSON report")
    parser.add_argument("--verbose", "-v", action="store_true")
    args = parser.parse_args()

    print("[*] T1548 Elevation Abuse Detection Agent")
    report = {"timestamp": datetime.now(timezone.utc).isoformat(), "findings": {}}

    if sys.platform == "win32":
        reg = check_uac_bypass_registry()
        procs = check_uac_bypass_processes()
        report["findings"]["uac_registry"] = reg
        report["findings"]["uac_processes"] = procs
        print(f"[*] UAC registry: {len(reg)}, UAC process: {len(procs)}")
    else:
        sudo = check_linux_sudo_abuse()
        suid = check_setuid_binaries()
        report["findings"]["sudo_abuse"] = sudo
        report["findings"]["suid_binaries"] = suid
        print(f"[*] Sudo abuse: {len(sudo)}, SUID binaries: {len(suid)}")

    total = sum(len(v) if isinstance(v, list) else 0 for v in report["findings"].values())
    report["risk_level"] = "CRITICAL" if total >= 5 else "HIGH" if total >= 2 else "MEDIUM" if total > 0 else "LOW"

    if args.output:
        with open(args.output, "w") as f:
            json.dump(report, f, indent=2)
        print(f"[*] Report saved to {args.output}")
    else:
        print(json.dumps(report, indent=2))


if __name__ == "__main__":
    main()
process.py4.7 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""
T1548 Elevation Control Abuse Detection Script
Detects UAC bypass attempts via registry modifications, auto-elevating
process abuse, and unusual privilege escalation patterns.
"""

import json
import csv
import argparse
import datetime
import re
from pathlib import Path

UAC_REGISTRY_PATTERNS = [
    r"(?i)ms-settings\\shell\\open\\command",
    r"(?i)mscfile\\shell\\open\\command",
    r"(?i)exefile\\shell\\open\\command",
    r"(?i)Folder\\shell\\open\\command",
    r"(?i)Policies\\System\\EnableLUA",
    r"(?i)Policies\\System\\ConsentPromptBehaviorAdmin",
]

AUTO_ELEVATE_BINARIES = {
    "fodhelper.exe", "computerdefaults.exe", "eventvwr.exe",
    "sdclt.exe", "slui.exe", "cmstp.exe", "cleanmgr.exe",
}

EXPECTED_PARENTS = {"explorer.exe", "svchost.exe", "services.exe", "winlogon.exe"}


def parse_events(input_path: str) -> list[dict]:
    path = Path(input_path)
    events = []
    if path.suffix == ".json":
        with open(path, "r", encoding="utf-8") as f:
            data = json.load(f)
            events = data if isinstance(data, list) else data.get("events", [])
    elif path.suffix == ".csv":
        with open(path, "r", encoding="utf-8-sig") as f:
            events = [dict(row) for row in csv.DictReader(f)]
    return events


def detect_elevation_abuse(events: list[dict]) -> list[dict]:
    findings = []
    for event in events:
        event_code = str(event.get("EventCode", event.get("EventID", "")))
        computer = event.get("Computer", event.get("host", ""))
        timestamp = event.get("UtcTime", event.get("_time", ""))
        user = event.get("User", event.get("user", ""))

        if event_code in ("12", "13"):
            target_obj = event.get("TargetObject", "")
            details = event.get("Details", "")
            image = event.get("Image", "")
            for pattern in UAC_REGISTRY_PATTERNS:
                if re.search(pattern, target_obj):
                    findings.append({
                        "timestamp": timestamp, "computer": computer, "user": user,
                        "detection_type": "UAC_Registry_Modification",
                        "registry_key": target_obj, "value": details,
                        "modifying_process": image,
                        "severity": "CRITICAL", "technique": "T1548.002",
                    })
                    break

        elif event_code == "1":
            image = event.get("Image", "")
            parent = event.get("ParentImage", "")
            cmdline = event.get("CommandLine", "")
            image_name = image.split("\\")[-1].lower() if image else ""
            parent_name = parent.split("\\")[-1].lower() if parent else ""

            if image_name in AUTO_ELEVATE_BINARIES and parent_name not in EXPECTED_PARENTS:
                findings.append({
                    "timestamp": timestamp, "computer": computer, "user": user,
                    "detection_type": "Auto_Elevate_Abuse",
                    "auto_elevate_binary": image, "parent_process": parent,
                    "command_line": cmdline,
                    "severity": "HIGH", "technique": "T1548.002",
                })

            if parent_name in AUTO_ELEVATE_BINARIES and image_name in {"cmd.exe", "powershell.exe", "wscript.exe", "cscript.exe", "mshta.exe"}:
                findings.append({
                    "timestamp": timestamp, "computer": computer, "user": user,
                    "detection_type": "Elevated_Child_Process",
                    "child_process": image, "auto_elevate_parent": parent,
                    "command_line": cmdline,
                    "severity": "CRITICAL", "technique": "T1548.002",
                })

    return sorted(findings, key=lambda x: {"CRITICAL": 0, "HIGH": 1, "MEDIUM": 2}.get(x["severity"], 3))


def run_hunt(input_path: str, output_dir: str) -> None:
    print(f"[*] T1548 Elevation Control Abuse Hunt - {datetime.datetime.now().isoformat()}")
    events = parse_events(input_path)
    findings = detect_elevation_abuse(events)
    print(f"[!] Elevation abuse detections: {len(findings)}")

    output_path = Path(output_dir)
    output_path.mkdir(parents=True, exist_ok=True)
    with open(output_path / "elevation_abuse_findings.json", "w", encoding="utf-8") as f:
        json.dump({"hunt_id": f"TH-UAC-{datetime.date.today().isoformat()}",
                    "findings": findings}, f, indent=2)
    print(f"[+] Results written to {output_dir}")


def main():
    parser = argparse.ArgumentParser(description="T1548 Elevation Control Abuse Detection")
    parser.add_argument("--input", "-i", required=True)
    parser.add_argument("--output", "-o", default="./elevation_hunt_output")
    args = parser.parse_args()
    run_hunt(args.input, args.output)


if __name__ == "__main__":
    main()

Assets 1

template.mdtext/markdown · 1.0 KB
Keep exploring