hardware firmware security

Detecting Secure Boot Bypass

Detect bootkits such as BlackLotus and Bootkitty and Secure Boot bypass via DBX and binary checks.

blacklotusbootkitchipsecdbx-revocationfirmware-integrityhardware-firmware-securitysecure-bootuefi
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

Legal Notice: Firmware and Secure Boot assessment must only be performed on systems you own or are explicitly authorized to test. CHIPSEC's write/modify modes and EFI variable manipulation can brick hardware. Run destructive checks only in a lab. This skill is for defensive verification and authorized assessment.

Overview

UEFI Secure Boot is the firmware-enforced trust chain that only permits boot components signed by keys in the platform's allow-list (db) and not present in the revocation list (dbx). Bootkits defeat this layer to gain pre-OS, persistent, kernel-level control that survives OS reinstalls and disk wipes. BlackLotus (2023) was the first publicly observed UEFI bootkit to bypass Secure Boot on fully patched Windows 11, abusing CVE-2022-21894 ("baton drop") in a vulnerable, signed Windows boot manager to neutralize Secure Boot and disable BitLocker, HVCI, and Defender. Bootkitty (2024) was the first PoC UEFI bootkit targeting Linux. Microsoft's CVE-2023-24932 addressed a related Secure Boot bypass that required a phased dbx (revocation) rollout because revoking the vulnerable boot managers can render systems unbootable if applied carelessly.

The core defensive insight is that patching the OS is not sufficient — the platform remains exploitable until the vulnerable, signed binaries are revoked in dbx. Detection therefore combines: (1) confirming Secure Boot is actually enabled, (2) verifying dbx is current and contains the relevant revocations, (3) checking the integrity and protection of Secure Boot EFI variables with CHIPSEC, (4) hashing on-disk EFI boot binaries and comparing them against the revocation list and known-bad sets, and (5) inspecting firmware/ESP for bootkit artifacts. This skill provides a cross-platform (Linux + Windows) workflow using mokutil, efi-readvar/dbxtool, chipsec, sbverify/pesign, and Windows Confirm-SecureBootUEFI / Get-SecureBootUEFI.

When to Use

  • Verifying that an estate's Secure Boot configuration is enabled, locked, and current after the CVE-2023-24932 / BlackLotus advisories.
  • Hunting for UEFI bootkit indicators on a suspected-compromised endpoint.
  • Validating that dbx revocations (e.g., vulnerable Windows boot managers, Kaspersky/other vulnerable bootloaders) have actually applied across the fleet.
  • Auditing firmware integrity and Secure Boot variable protections during a hardware security assessment.
  • Building a recurring measured/baseline check for boot-chain tampering.

Prerequisites

  • Root/administrator on the target (firmware reads require privilege).
  • Linux tooling:
    sudo apt install mokutil efitools sbsigntool dbxtool      # Debian/Ubuntu
    sudo dnf install mokutil efitools sbsigntools dbxtool     # Fedora/RHEL
  • CHIPSEC (run from a live USB or controlled host; loads a kernel driver):
    pip install chipsec        # or build from https://github.com/chipsec/chipsec
  • Windows tooling: PowerShell (built-in Confirm-SecureBootUEFI, Get-SecureBootUEFI), and optionally the UEFI dbx update package from Microsoft.
  • The current dbxupdate files from https://uefi.org/revocationlistfile to compare against.

Objectives

  • Confirm Secure Boot is enabled and in user (not setup) mode.
  • Enumerate db, dbx, KEK, and PK contents and assess freshness of dbx.
  • Verify the relevant CVE revocations are present in dbx.
  • Validate Secure Boot EFI variables are authenticated and protected (CHIPSEC).
  • Hash ESP boot binaries and check them against dbx and known-bad hash sets.
  • Identify bootkit artifacts and report exploitable gaps with remediation.

MITRE ATT&CK Mapping

Technique ID Technique Name Relevance
T1542.003 Pre-OS Boot: Bootkit Core technique — bootkit subverts the boot chain below the OS.
T1542 Pre-OS Boot Parent technique covering firmware/boot-component tampering.
T1542.001 Pre-OS Boot: System Firmware Adjacent: firmware modification used to persist or weaken Secure Boot.
T1014 Rootkit Bootkits provide rootkit-level concealment and persistence.
T1562.001 Impair Defenses: Disable or Modify Tools BlackLotus disables BitLocker/HVCI/Defender after bypassing Secure Boot.

Workflow

1. Confirm Secure Boot state (Linux)

A disabled or setup-mode platform offers no protection.

mokutil --sb-state                       # "SecureBoot enabled" expected
bootctl status | grep -i "secure boot"   # systemd-boot view
# 6 = enabled+user mode on the EFI SecureBoot/SetupMode vars:
od -An -t u1 /sys/firmware/efi/efivars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c

2. Confirm Secure Boot state (Windows)

Confirm-SecureBootUEFI        # $true if enabled
# Inspect the raw dbx variable from Windows:
[System.BitConverter]::ToString((Get-SecureBootUEFI dbx).bytes) | Out-File dbx.hex

3. Enumerate the Secure Boot databases

List db (allowed), dbx (revoked), KEK, and PK.

efi-readvar                      # dumps PK, KEK, db, dbx
efi-readvar -v dbx -o dbx.esl    # export dbx to a file for offline analysis
mokutil --list-enrolled          # MOK (shim) enrolled keys
mokutil --db                     # platform db entries via shim

4. Assess dbx freshness and applied revocations

Compare on-system dbx to the current official UEFI revocation list.

dbxtool --list                                   # current dbx entries + count
# Download latest dbxupdate from uefi.org/revocationlistfile, then:
dbxtool --dbx ./DBXUpdate.bin --apply --dry-run  # show what WOULD be added (no write)

A low dbx entry count or absence of recent revocations indicates the platform is behind and likely still vulnerable to known bypasses.

5. Check Secure Boot variable protection with CHIPSEC

Verify the SB key variables are authenticated and not freely writable.

# Verify Secure Boot is enabled and the SB variables are properly protected:
sudo chipsec_main -m common.secureboot.variables
 
# Check S3 resume boot-script protections (an SMM/firmware bypass vector):
sudo chipsec_main -m common.uefi.s3bootscript
 
# Dump SPI flash for offline firmware diffing:
sudo chipsec_util spi dump rom.bin

6. Hash ESP boot binaries and check signatures

Verify bootloaders are signed and not present in dbx.

# Locate and hash EFI boot binaries
find /boot/efi -iname '*.efi' -exec sha256sum {} \;
# Validate a binary's signature against the platform db
sbverify --list /boot/efi/EFI/BOOT/bootx64.efi
sbverify --cert /etc/secureboot/db.crt /boot/efi/EFI/Microsoft/Boot/bootmgfw.efi
# pesign equivalent on RHEL-family:
pesign -S -i /boot/efi/EFI/BOOT/bootx64.efi

7. Cross-check against known-bad bootkit hashes

Compare collected hashes to revocation/known-bad sets (e.g., LoFP / vendor advisories).

# Example: confirm a binary's SHA-256 is NOT one of the revoked CVE-2022-21894 boot managers
sha256sum /boot/efi/EFI/Microsoft/Boot/bootmgfw.efi
# Compare against the hash list extracted from the latest dbxupdate / advisory.

8. Inspect for bootkit artifacts

Look for unauthorized ESP modifications and self-deployment markers.

# Unexpected files / recently modified binaries on the ESP
ls -laR /boot/efi/EFI/
find /boot/efi -newermt "-30 days" -iname '*.efi'
# On Windows, examine the EFI partition for rogue \EFI\Microsoft\Boot entries.

9. Validate measured-boot evidence (optional pivot)

If a TPM is present, current PCR[7] reflects Secure Boot policy; deviations corroborate tampering.

tpm2_pcrread sha256:7        # Secure Boot policy PCR

10. Run the bundled assessment helper

agent.py collects SB state, dbx counts, ESP binary hashes, and CHIPSEC results into one report.

sudo python scripts/agent.py --check-chipsec --output secureboot_report.json

Tools and Resources

Tool Purpose Source
mokutil Secure Boot state and enrolled keys (Linux) https://github.com/lcp/mokutil
efitools (efi-readvar) Dump PK/KEK/db/dbx https://git.kernel.org/pub/scm/linux/kernel/git/jejb/efitools.git
dbxtool Inspect and apply dbx updates https://github.com/rhboot/dbxtool
CHIPSEC Firmware / Secure Boot variable assessment https://github.com/chipsec/chipsec
sbsigntool / pesign EFI binary signature verification https://github.com/jejb/sbsigntools
UEFI Revocation List Official dbx update files https://uefi.org/revocationlistfile
Microsoft KB CVE-2023-24932 Secure Boot bypass guidance https://support.microsoft.com/topic/kb5025885
ESET BlackLotus analysis Bootkit technical writeup https://www.welivesecurity.com/2023/03/01/blacklotus-uefi-bootkit-myth-confirmed/

Validation Criteria

  • Secure Boot confirmed enabled and in user mode on the target.
  • PK/KEK/db/dbx enumerated and exported for analysis.
  • dbx compared against the current official UEFI revocation list.
  • CVE-2022-21894 / CVE-2023-24932 revocations confirmed present (or gap flagged).
  • CHIPSEC secureboot.variables and s3bootscript modules run.
  • ESP boot binaries hashed and signature-verified.
  • Hashes cross-checked against known-bad / revoked sets.
  • ESP inspected for unauthorized or recently modified binaries.
  • Findings documented with remediation (dbx update / firmware update) per host.
Source materials

References and resources

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

References 2

api-reference.md2.2 KB

Command Reference

mokutil (Linux Secure Boot state)

Command Description
mokutil --sb-state Report whether Secure Boot is enabled.
mokutil --list-enrolled List enrolled MOK (Machine Owner Keys).
mokutil --db Show platform db entries (via shim).
mokutil --dbx Show dbx (revoked) entries via shim.

efitools

Command Description
efi-readvar Dump PK, KEK, db, dbx.
efi-readvar -v dbx -o dbx.esl Export dbx to an EFI signature list file.

dbxtool

Command Description
dbxtool --list List current dbx entries and count.
dbxtool --dbx DBXUpdate.bin --apply --dry-run Show revocations a given update would add (no write).
dbxtool --dbx DBXUpdate.bin --apply Apply a dbx update (write — caution).

CHIPSEC

Command Description
chipsec_main -m common.secureboot.variables Verify SB key variables are authenticated/protected.
chipsec_main -m common.secureboot.variables -a modify Attempt to write/corrupt SB vars (destructive test).
chipsec_main -m common.uefi.s3bootscript Check S3 resume boot-script protections.
chipsec_util spi dump rom.bin Dump SPI flash for offline analysis.

Signature verification

Command Description
sbverify --list <file.efi> List signatures on an EFI binary.
sbverify --cert db.crt <file.efi> Verify a binary against a db cert.
pesign -S -i <file.efi> Show signatures (RHEL family).

Windows PowerShell

Cmdlet Description
Confirm-SecureBootUEFI Returns $true if Secure Boot is enabled.
Get-SecureBootUEFI dbx Retrieve the raw dbx variable bytes.
Get-SecureBootUEFI db Retrieve the allowed-signatures database.

TPM corroboration

Command Description
tpm2_pcrread sha256:7 Read PCR[7] (Secure Boot policy measurement).

Key references

standards.md1.5 KB

Standards and Framework Mapping

MITRE ATT&CK

ID Name Rationale
T1542.003 Pre-OS Boot: Bootkit Core technique — bootkit subverts the boot chain below the OS to persist.
T1542 Pre-OS Boot Parent technique for firmware/boot-component tampering.
T1542.001 Pre-OS Boot: System Firmware Firmware modification used to weaken or bypass Secure Boot.
T1014 Rootkit Bootkits deliver rootkit-level stealth and persistence.
T1562.001 Impair Defenses: Disable or Modify Tools Post-bypass, BlackLotus disables BitLocker/HVCI/Defender.

NIST Cybersecurity Framework 2.0

ID Name Rationale
DE.CM-01 Networks and network services are monitored to find potentially adverse events Applied here to boot-chain/firmware integrity monitoring — verifying Secure Boot, dbx, and EFI binaries surfaces tampering.

Supporting Standards and References

  • CVE-2022-21894 (Baton Drop). Vulnerable signed Windows boot manager abused by BlackLotus to bypass Secure Boot.
  • CVE-2023-24932. Secure Boot Security Feature Bypass; remediated via phased dbx revocation rollout (Microsoft KB5025885).
  • NSA UEFI Secure Boot Customization guidance. Hardening and verification of the UEFI Secure Boot trust chain.
  • NIST SP 800-147 / 800-193 — Platform Firmware Resiliency. Protection, detection, and recovery requirements for firmware integrity.
  • UEFI Specification — Secure Boot (db/dbx/KEK/PK). Authoritative source for the variable model checked in this skill.

Scripts 1

agent.py5.1 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""
Secure Boot bypass / bootkit detection helper (Linux + Windows-aware).

Collects:
  - Secure Boot enabled state
  - dbx (revocation list) entry count and freshness signal
  - SHA-256 hashes of EFI boot binaries on the ESP
  - CHIPSEC secureboot.variables result (optional, requires root + chipsec)

Emits a JSON report and a human-readable summary. Read-only by default.
Authorized assessment use only; run from a trusted/live environment.
"""
import argparse
import glob
import hashlib
import json
import os
import platform
import shutil
import subprocess
import sys
from pathlib import Path

ESP_PATHS = ["/boot/efi/EFI", "/boot/EFI", "/efi/EFI"]


def run(cmd: list[str], timeout: int = 300) -> tuple[int, str, str]:
    try:
        p = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
        return p.returncode, p.stdout, p.stderr
    except FileNotFoundError:
        return 127, "", f"not found: {cmd[0]}"
    except subprocess.SubprocessError as exc:
        return 1, "", str(exc)


def secure_boot_state() -> dict:
    state = {"platform": platform.system()}
    if platform.system() == "Linux":
        if shutil.which("mokutil"):
            rc, out, _ = run(["mokutil", "--sb-state"])
            state["mokutil_sb_state"] = out.strip() or "unknown"
            state["enabled"] = "enabled" in out.lower()
        else:
            # Fall back to reading the EFI variable directly
            var = glob.glob("/sys/firmware/efi/efivars/SecureBoot-*")
            if var:
                try:
                    data = Path(var[0]).read_bytes()
                    state["enabled"] = bool(data and data[-1] == 1)
                    state["efivar_raw"] = data.hex()
                except OSError as exc:
                    state["error"] = f"efivar read failed: {exc}"
            else:
                state["error"] = "no mokutil and no SecureBoot efivar"
    elif platform.system() == "Windows":
        rc, out, err = run(
            ["powershell", "-NoProfile", "-Command", "Confirm-SecureBootUEFI"]
        )
        state["confirm_secureboot"] = out.strip()
        state["enabled"] = out.strip().lower() == "true"
    return state


def dbx_status() -> dict:
    info = {}
    if shutil.which("dbxtool"):
        rc, out, err = run(["dbxtool", "--list"])
        # Each revocation is one line; count non-empty lines as an approximation
        lines = [l for l in out.splitlines() if l.strip()]
        info["dbxtool_entries"] = len(lines)
        info["sample"] = lines[:5]
        if len(lines) < 50:
            info["warning"] = "low dbx entry count; platform may be behind on revocations"
    elif shutil.which("efi-readvar"):
        rc, out, err = run(["efi-readvar", "-v", "dbx"])
        info["efi_readvar_dbx_excerpt"] = out[:800]
    else:
        info["error"] = "neither dbxtool nor efi-readvar available"
    return info


def hash_esp_binaries() -> list[dict]:
    results = []
    base = next((p for p in ESP_PATHS if os.path.isdir(p)), None)
    if not base:
        return [{"error": "no ESP path found (run as root with EFI mounted)"}]
    for path in Path(base).rglob("*.efi"):
        try:
            digest = hashlib.sha256(path.read_bytes()).hexdigest()
            results.append({"file": str(path), "sha256": digest, "size": path.stat().st_size})
        except OSError as exc:
            results.append({"file": str(path), "error": str(exc)})
    return results


def chipsec_secureboot() -> dict:
    if not shutil.which("chipsec_main"):
        return {"error": "chipsec_main not installed"}
    rc, out, err = run(["chipsec_main", "-m", "common.secureboot.variables"], timeout=600)
    verdict = "PASSED" if "PASSED" in out else "FAILED" if "FAILED" in out else "UNKNOWN"
    return {"verdict": verdict, "tail": out[-1200:]}


def main() -> int:
    ap = argparse.ArgumentParser(description="Secure Boot / bootkit assessment")
    ap.add_argument("--check-chipsec", action="store_true", help="Run CHIPSEC secureboot module (root)")
    ap.add_argument("--output", help="Write JSON report")
    args = ap.parse_args()

    if platform.system() == "Linux" and os.geteuid() != 0:
        print("[warn] not running as root; some checks may be incomplete", file=sys.stderr)

    report = {
        "secure_boot": secure_boot_state(),
        "dbx": dbx_status(),
        "esp_binaries": hash_esp_binaries(),
    }
    if args.check_chipsec:
        report["chipsec_secureboot_variables"] = chipsec_secureboot()

    sb = report["secure_boot"]
    print(f"[+] Secure Boot enabled: {sb.get('enabled')}")
    if not sb.get("enabled"):
        print("[!] Secure Boot is NOT enabled — platform is unprotected against bootkits")
    if "warning" in report["dbx"]:
        print(f"[!] dbx: {report['dbx']['warning']}")
    print(f"[+] {len([b for b in report['esp_binaries'] if 'sha256' in b])} EFI binaries hashed")
    if args.check_chipsec:
        print(f"[+] CHIPSEC secureboot.variables: {report['chipsec_secureboot_variables'].get('verdict')}")

    if args.output:
        Path(args.output).write_text(json.dumps(report, indent=2), encoding="utf-8")
        print(f"[+] report written to {args.output}")
    return 0


if __name__ == "__main__":
    sys.exit(main())
Keep exploring