Abstract
In previous posts we looked at kernel drivers and hardware-assisted virtualization. Both of those worlds live inside the operating system, or just beneath it. But there is a layer that precedes all of that: firmware.
This post is a practical introduction to UEFI, EFI, and SMM. We will go through the main concepts, explain why they matter for offensive and defensive security, and close with a small but complete PoC: an SMM driver running in OVMF, plus an EFI application that generates a controlled Software SMI.
We are not exploiting a real vulnerability. The goal here is to understand the moving pieces, recognize the attack surface, and have working code that demonstrates the full path from a UEFI application down to an SMM handler.
All techniques and concepts are documented here strictly for academic and research purposes.
1. From Kernel To Firmware: Why Look Below The Operating System
In previous posts, we have explored highly privileged areas of the system: kernel drivers, hypervisors, protected memory, hooks, callbacks, and the ecosystem where attackers and defenders operate close to the operating system core.
But there is an even earlier layer.
Before ntoskrnl.exe exists, before Linux initializes its kernel, before a hypervisor such as Hyper-V, KVM, or VMware starts managing the machine, a significant amount of code has already executed. That code lives in firmware.
On modern PCs, that firmware implements UEFI: the Unified Extensible Firmware Interface. UEFI initializes the platform, discovers devices, prepares tables such as ACPI, mounts the EFI System Partition, loads bootloaders, and eventually transfers control to the operating system.
From an offensive and defensive security perspective, this matters for three reasons:
- UEFI executes before the operating system.
- Some of its code can remain relevant after boot.
- Certain parts of the firmware run in modes more privileged than the kernel itself.
In kernel research we usually talk about Ring 0. In virtualization we sometimes talk about Ring -1. In x86 firmware there is another important concept: SMM, System Management Mode, often informally referred to as Ring -2.
This post is a practical introduction to that world.
2. BIOS, EFI, And UEFI: What Runs Before The Kernel
For many years, PC boot was dominated by the classic BIOS model: firmware running in real mode, BIOS interrupts, reading the first disk sector, executing the MBR, and gradually jumping into the operating system bootloader. Simple, effective, and very old.
UEFI changes that model significantly.
UEFI is not just “a modern BIOS with a graphical menu”. It is a full specification defining services, protocols, drivers, applications, persistent variables, boot mechanisms, and a pre-OS execution environment.
In UEFI we find components such as:
- PE/COFF executables, broadly similar in format to Windows binaries.
- EFI drivers loaded by the firmware during platform initialization.
- EFI applications, such as a UEFI Shell or a bootloader.
- Boot Services, available before
ExitBootServices(). - Runtime Services, still available after the OS has started.
- Persistent UEFI variables stored in NVRAM.
- Protocols used to abstract devices and services.
- Secure Boot, used to cryptographically validate boot components.
One clarification worth making early: EFI was the original name associated with Intel. UEFI is the standardized evolution maintained by the UEFI Forum. In practice, we say UEFI when referring to modern firmware, and EFI when referring to concrete binaries, partitions, applications, or interfaces: BOOTX64.EFI, EFI System Partition, EFI variables, and so on.
Another key point: UEFI is extensible. Firmware can load modules, install protocols, and execute arbitrary applications. That extensibility is powerful, but it also increases the attack surface considerably.
3. The UEFI Boot Flow: From SEC To BDS
EFI implementations usually follow the architecture defined by PI, the Platform Initialization specification. We do not need every detail, but the main phases are worth understanding.
3.1. SEC: Security Phase
SEC is one of the first phases executed after reset. Its job is to establish a minimal execution environment: setting up a temporary stack in CPU cache, initializing a few registers, and passing control forward. At this point DRAM may not be initialized and there are no high-level firmware services.
3.2. PEI: Pre-EFI Initialization
PEI initializes basic platform resources: memory, CPU, chipset, and other essential components. This phase also builds HOBs, Hand-Off Blocks, which carry information into later phases. Memory initialization happens here.
3.3. DXE: Driver Execution Environment
DXE is the most interesting phase for security research. This is where most UEFI drivers are loaded. These drivers install protocols, detect devices, prepare services, and build much of the environment later used by the boot manager.
Important modules live in DXE: storage drivers, network drivers, graphics drivers, variable services, ACPI support, SMM infrastructure, and more. The attack surface here is substantial.
3.4. BDS: Boot Device Selection
BDS decides what to boot. It can show a boot menu, load a UEFI Shell, start BOOTX64.EFI from the EFI System Partition, or launch a bootloader registered in UEFI variables.
3.5. TSL And Runtime
TSL, Transient System Load, is the phase where the OS bootloader becomes the main actor. Then comes ExitBootServices(): the OS claims ownership of the machine, and UEFI stops providing Boot Services.
But not everything disappears. Runtime Services, ACPI tables, UEFI variables, and certain memory regions remain relevant after this point.
And SMM remains even lower, outside the normal control of the operating system.
4. EFI Drivers, Applications, And UEFI Services
One idea that can be confusing at first is that UEFI is not a monolithic firmware blob. It has modules.
An EFI binary can be an application, a DXE driver, an SMM driver, a bootloader, a shell, and so on. These binaries typically use the PE/COFF format and execute inside the environment defined by UEFI. If you are familiar with Windows binary analysis, the format will feel somewhat familiar.
An EFI application can print to the UEFI console, read files from a FAT partition, locate protocols, access UEFI variables, load other binaries, and call firmware services. An EFI driver can install protocols, manage devices, provide abstractions to other modules, and expose services consumed by later components.
In our PoC we use two pieces:
SimpleSmmHook.efi: an SMM driver that registers a handler inside SMRAM.SmiTriggerApp.efi: a UEFI application that generates a Software SMI from the UEFI Shell.
The application does not exploit anything. It uses a legitimate interface, EFI_SMM_CONTROL2_PROTOCOL, which allows generating an SMI activation from the UEFI environment. We will come back to both of these in the PoC section.
5. Secure Boot, Measured Boot, And The EFI System Partition
Before going deeper into SMM, three UEFI security concepts are worth covering, because they frequently appear in both defensive and offensive contexts.
5.1. EFI System Partition
The EFI System Partition (ESP) is normally a FAT-formatted partition containing bootloaders and other boot-related components. On Windows systems it often contains paths such as:
\EFI\Microsoft\Boot\bootmgfw.efi
A generic fallback path is also common:
\EFI\BOOT\BOOTX64.EFI
From an offensive point of view, the ESP is attractive because its contents can run before the operating system. From a defensive point of view, it is a critical area that should be monitored and its integrity verified.
5.2. Secure Boot
Secure Boot attempts to ensure that firmware only loads signed and authorized binaries. It relies on databases of trusted keys, allowed hashes, and revoked components. The general idea is to prevent attackers from modifying the bootloader or inserting unauthorized components into the boot chain.
But Secure Boot is not a silver bullet. It depends on a correctly configured trust chain, up-to-date revocations, firmware without exploitable bugs, and signed components that are themselves secure. A vulnerability in a signed bootloader can render Secure Boot ineffective even on fully patched systems.
BlackLotus is an important example. It demonstrated the real-world impact of abusing a vulnerability in the boot chain (CVE-2022-21894) to bypass Secure Boot in Windows scenarios.
5.3. Measured Boot
Measured Boot does not necessarily block the boot process. Instead, it measures components and extends those measurements into the TPM. Those measurements can later be used for auditing, attestation, or detection.
In modern defensive architectures, Secure Boot and Measured Boot complement each other: Secure Boot prevents unauthorized modifications, while Measured Boot leaves verifiable evidence of what was loaded. Both can be undermined if the firmware layer itself is compromised.
6. System Management Mode: “Ring -2”
SMM, System Management Mode, is a special execution mode in x86 processors. Intel documents it as part of the processor system programming environment.
The original purpose of SMM was not malware or rootkits. It was system management: power management, thermal control, legacy emulation, platform events, hardware control, OEM-specific functionality, and low-level coordination independent of the operating system.
SMM is entered through a System Management Interrupt, or SMI.
When an SMI arrives, the CPU interrupts whatever it is doing, saves state, enters SMM, and executes code from a protected memory region called SMRAM. When the handler finishes, it executes RSM (Resume from System Management Mode) and returns to the previous context.
From the operating system’s point of view, this is nearly invisible. The kernel does not “decide” to enter SMM. It also does not directly control what the SMM handler does. The kernel is simply paused, the SMM handler executes, and then execution resumes as if nothing happened.
That is why SMM is often called “Ring -2”:
| Privilege Level | Description |
|---|---|
| Ring 3 | User mode |
| Ring 0 | Kernel |
| Ring -1 | Hypervisor (VMX root) |
| Ring -2 | SMM |
This is not formal Intel terminology, but it communicates the idea well: SMM sits below the kernel and outside its normal protection model.
7. SMRAM, SMI, And SMI Handlers
To understand SMM practically, there are three key pieces to keep in mind.
7.1. SMRAM
SMRAM is the memory used by SMM code and data. On modern platforms, it is commonly backed by regions such as TSEG, a reserved physical memory area protected by the chipset.
When SMRAM is properly locked, the operating system should not be able to read or write it. That protection is critical. If an attacker running at Ring 0 could modify SMRAM contents, they could install extremely privileged and persistent code that survives both OS reboots and most security tooling.
The firmware typically opens SMRAM during initialization, loads the SMM core and SMM drivers, and then closes and locks the region. In our OVMF logs, this flow is directly visible:
SMM IPL opened SMRAM window
SMM IPL loading SMM Core at SMRAM address ...
SMM IPL closed SMRAM window
SMM IPL locked SMRAM window
Once locked, legitimate access to SMRAM only happens through the SMI mechanism itself.
7.2. SMI
An SMI can come from several sources: writes to specific I/O ports, chipset events, power events, timers, access to certain resources, or signals generated by firmware or platform logic.
In our lab, we use a Software SMI. On Q35/OVMF, SmmControl2Dxe writes to APM ports:
0xB3 -> data byte
0xB2 -> command byte
The write to the control port 0xB2 causes the CPU to enter SMM. In our case:
0xB3 = 0x5A (data)
0xB2 = 0x99 (command)
This is a standard, documented mechanism. We are not abusing anything. We are using the protocol exactly as it is designed to work.
7.3. SMI Handlers
An SMI handler is code registered to execute when an SMI, or a specific class of SMM event, occurs. In real firmware, SMM handlers process specific requests: variable services, flash operations, ACPI events, power management, and similar platform-level tasks.
Security issues appear when those handlers:
- Trust data controlled by the operating system without validation.
- Access buffers outside SMRAM without checking memory ranges.
- Expose read/write primitives to untrusted callers.
- Allow modification of SPI flash, critical variables, or protected regions.
- Contain race conditions or TOCTOU bugs.
- Fail to lock SMRAM or chipset registers correctly after initialization.
A bug in an SMI handler can turn a kernel-level vulnerability into code execution inside SMM. That is a significant escalation.
8. Why SMM Matters For Security
SMM matters because it breaks several assumptions we usually make when working at kernel level.
When we are at Ring 0, we tend to think we control the whole machine. But SMM sits outside that model. It can interrupt the kernel, execute its own code, and return without the OS having any complete view of what happened.
8.1. From A Defensive Perspective
SMM is part of the platform root of trust. If firmware or SMM handlers are compromised, the operating system is booting on top of a compromised foundation. Even the most capable kernel EDR is operating in degraded conditions when firmware is controlled by an adversary.
Forensics also becomes more difficult. Traditional tooling inspects disk, OS memory, processes, drivers, or hypervisors. Firmware and SMRAM require different techniques and often specialized hardware.
8.2. From An Offensive Perspective
SMM is attractive because:
- It executes with the highest privilege available on the platform.
- It is isolated from the operating system.
- It can observe or alter platform state without the OS being aware.
- It can survive OS reinstallations when combined with firmware persistence.
- It can interfere with mechanisms such as Secure Boot if the right components are compromised.
This does not mean “SMM is insecure by design”. It means SMM is a critical area where bugs have extremely high impact. A single exploitable SMI handler can be the difference between a Ring 0 vulnerability and a full platform compromise.
9. Bootkits, Firmware Implants, And Modern Attacks
The UEFI world is not just academic theory. In recent years we have seen both research and real-world malware targeting this layer.
9.1. UEFI Bootkits
A UEFI bootkit tries to execute before the operating system. It may modify the boot chain, load malicious components early, alter security settings, or prepare hooks that survive into the kernel boot process.
BlackLotus is one of the best-known examples. It was publicly analyzed as a UEFI bootkit abusing CVE-2022-21894 to bypass Secure Boot on fully patched Windows systems. The pattern it demonstrates is what matters for understanding this class of attack:
- The attacker gains execution before the kernel.
- They manipulate the boot chain at a privileged point.
- They disable or weaken security controls.
- They load later-stage payloads with timing and privilege advantages that persist across reboots.
9.2. Vulnerabilities In UEFI Parsers
Modern firmware contains far more code than people often expect: image parsers, networking stacks, file systems, drivers, protocols, and UI components. That complexity is attack surface.
LogoFAIL, researched by Binarly, showed how image and logo parsers embedded in firmware could become attack surface during boot. This is notable because it challenges the common assumption that firmware is only minimal hardware initialization code. In practice, many implementations include complex components with their own parser bugs, format handling, and allocator interactions.
9.3. SMM Bugs
SMM appears frequently in firmware advisories. Many bugs follow the same pattern:
- An SMI handler receives a pointer from untrusted memory (controlled by the OS).
- The handler does not validate whether the buffer points into SMRAM or into OS memory.
- An attacker with Ring 0 privileges prepares malicious data at that address.
- The handler writes somewhere it should not.
- The attacker obtains corruption or execution inside SMM.
The usual defensive pattern is: validate every buffer, check memory ranges against known-safe regions, use dedicated SMM communication buffers, lock SMRAM correctly after initialization, and keep SMM logic as minimal as possible.
9.4. Firmware Implants
A firmware implant targets persistence below the disk. If it is written into SPI flash or another persistent firmware component, reinstalling the operating system may not be sufficient to remove it.
This is why high-security environments care about controlled firmware updates, attestation, SPI flash write protections, Boot Guard, Secure Boot configuration hygiene, firmware inventory tracking, ESP monitoring, and Measured Boot log analysis.
10. Our PoC: Triggering A Software SMI In OVMF
The goal of the PoC is intentionally simple: show, in a controlled environment, that we can load an SMM driver inside OVMF and trigger a Software SMI from an EFI application. We are not exploiting a vulnerability, adding persistence, or touching physical firmware. Everything runs in QEMU with OVMF.
The full path looks like this:
10.1. The SMM Driver: SimpleSmmHook.efi
The SMM driver registers a root SMI handler that filters on the APM ports used by OVMF/Q35. Using a root handler initially produced a lot of noise because it can observe many SMM entries, not only our target event. The final version adds explicit port filtering.
The entry point registers the handler through EFI_SMM_BASE2_PROTOCOL and then reads the APM ports from inside the SMM handler to confirm the match:
EFI_STATUS
EFIAPI
SimpleSmmHookEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE* SystemTable
)
{
EFI_STATUS status;
DEBUG( ( DEBUG_INFO, "[SimpleSmmHook] EntryPoint reached, registering APM-port filtered root SMI handler\n" ) );
status = gSmst->SmiHandlerRegister(
SimpleSwSmiHandler,
NULL,
&mDispatchHandle
);
if ( EFI_ERROR( status ) ) {
DEBUG( ( DEBUG_ERROR, "[SimpleSmmHook] SmiHandlerRegister failed: %r\n", status ) );
return status;
}
DEBUG( (
DEBUG_INFO,
"[SimpleSmmHook] Registered filtered root SMI handler for SW SMI 0x%x on ports 0x%x/0x%x\n",
( UINT32 )SIMPLE_SW_SMI_VALUE,
( UINT32 )SIMPLE_SMI_PORT,
( UINT32 )SIMPLE_DATA_PORT
) );
return EFI_SUCCESS;
}The handler itself reads the APM command and data ports from inside SMM and checks against our expected values:
EFI_STATUS
EFIAPI
SimpleSwSmiHandler (
IN EFI_HANDLE DispatchHandle,
IN CONST VOID* RegisterContext,
IN OUT VOID* CommBuffer,
IN OUT UINTN* CommBufferSize
)
{
UINT8 command;
UINT8 data;
if ( !IsOurSwSmi( &command, &data ) )
return EFI_SUCCESS;
++mHitCount;
DEBUG( (
DEBUG_INFO,
"[SimpleSmmHook] Matched SW SMI: count=%u command=0x%x data=0x%x DispatchHandle=%p Context=%p\n",
( UINT32 )mHitCount,
( UINT32 )command,
( UINT32 )data,
DispatchHandle,
RegisterContext
) );
if ( ( CommBuffer != NULL ) && ( CommBufferSize != NULL ) )
DEBUG( ( DEBUG_INFO, "[SimpleSmmHook] CommBuffer=%p Size=%u\n", CommBuffer, ( UINT32 )( *CommBufferSize ) ) );
return EFI_SUCCESS;
}10.2. The EFI Application: SmiTriggerApp.efi
The application runs from the UEFI Shell and uses EFI_SMM_CONTROL2_PROTOCOL to generate the Software SMI. This is the legitimate, documented interface for doing exactly this:
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE* SystemTable
)
{
EFI_STATUS status;
EFI_SMM_CONTROL2_PROTOCOL* smmControl2;
UINT8 command;
UINT8 data;
status = gBS->LocateProtocol(
&gEfiSmmControl2ProtocolGuid,
NULL,
( VOID** )&smmControl2
);
if ( EFI_ERROR( status ) ) {
Print( L"SmiTriggerApp: EFI_SMM_CONTROL2_PROTOCOL is not available: %r\n", status );
return status;
}
command = SIMPLE_SW_SMI_VALUE;
data = SIMPLE_SMI_DATA;
IoWrite8( SIMPLE_DATA_PORT, 0 );
Print( L"SmiTriggerApp: Trigger SW SMI 0x%02x data=0x%02x\n", command, data );
DEBUG ((DEBUG_INFO, "[SmiTriggerApp] Trigger SW SMI 0x%x data=0x%x\n", command, data));
status = smmControl2->Trigger( smmControl2, &command, &data, FALSE, 0 );
if ( EFI_ERROR( status ) ) {
Print( L"SmiTriggerApp: Trigger() failed: %r\n", status );
return status;
}
IoWrite8( SIMPLE_DATA_PORT, 0 );
status = smmControl2->Clear( smmControl2, FALSE );
if ( EFI_ERROR( status ) ) {
Print( L"SmiTriggerApp: Clear() failed: %r\n", status );
return status;
}
Print( L"SmiTriggerApp: SW SMI sent\n" );
return EFI_SUCCESS;
}10.3. The Result
The final output in debug.log is clean and confirms the full path:
Loading SMM driver at 0x0007FFD2000 EntryPoint=0x0007FFD3420 SimpleSmmHook.efi
[SimpleSmmHook] EntryPoint reached, registering APM-port filtered root SMI handler
[SimpleSmmHook] Registered filtered root SMI handler for SW SMI 0x99 on ports 0xB2/0xB3
[SmiTriggerApp] Trigger SW SMI 0x99 data=0x5A
[SimpleSmmHook] Matched SW SMI: count=1 command=0x99 data=0x5A DispatchHandle=7FFE6798 Context=0
What that confirms:
- The firmware loaded our SMM driver and executed its entry point inside SMRAM.
- The driver ran inside the SMM environment and registered its handler.
- The EFI application generated a Software SMI through the documented protocol.
- OVMF translated that request into writes to the APM ports (0xB2/0xB3).
- Our SMM handler received and correctly matched the event.
The full path is closed.
11. Conclusions
UEFI and SMM are fundamental layers for understanding modern x86 platform security.
If you come from kernel research, the key idea is this: the kernel is not the first privileged code that runs, and it is not necessarily the most privileged code from the platform’s point of view. UEFI prepares the world before the operating system. SMM can interrupt it afterwards. SMRAM protects code the OS cannot touch directly. Secure Boot tries to build a chain of trust from firmware up. Measured Boot tries to leave verifiable evidence of what was loaded. Bootkits try to abuse this early and privileged terrain to gain persistence, stealth, or control.
Our PoC is small, but it closes the full path:
EFI app → SmmControl2 → Software SMI → SMM handler → debug log
As a starting point, that is enough to open the door to more advanced topics:
- Reversing DXE and SMM modules from real firmware images.
- Firmware analysis with EDK II and UEFITool.
- Auditing SMI handlers for buffer confusion and SMRAM overlap bugs.
- Secure Boot internals and key database management.
- ESP-based persistence and detection.
- Firmware implants and SPI flash write protection bypass.
- TPM measurements and attestation flows.
- Platform hardening: Boot Guard, SPI write locks, SMRAM lock verification.
UEFI can look intimidating at first because it mixes architecture, firmware, binary formats, hardware, cryptography, and operating systems. But piece by piece, it connects well with what we already know from kernel and hypervisor research.
We are just going one layer deeper.
12. References
- UEFI Forum Specifications
- UEFI Platform Initialization Specification — MM Overview
- Intel 64 and IA-32 Architectures Software Developer Manuals
- TianoCore EDK II
- OVMF Overview
- Microsoft: Guidance for investigating attacks using CVE-2022-21894, the BlackLotus campaign
- ESET: BlackLotus UEFI bootkit analysis
- Binarly: LogoFAIL research
- System Management Mode (SMM) Security — UEFI Forum whitepaper
You can find the full source code for this PoC in this GitHub repository.
— Redaa.