CVE-2025-33043
An attacker could exploit this vulnerability to elevate privileges from ring 0 to ring -2 and execute arbitrary code in System Management Mode, an environment more privileged than and completely isolated from the operating system (OS). Running arbitrary code in SMM also bypasses SMM-based SPI flash protections against modification, which can help an attacker to install a firmware backdoor/implant. Such malicious code in the firmware could persist through operating system reinstallations. In addition, this vulnerability could potentially be used by malicious actors to bypass security mechanisms provided by UEFI firmware, such as Secure Boot and some types of memory isolation for hypervisors.
This vulnerability was detected by the Deep Vulnerability Analysis (DVA) component from Binarly Platform
Let's consider the module 2b228b2a38932e2250f24ae04e626709026d12f0a52f5a5b86089dabc6221109.
The pseudocode of the vulnerable function is shown below:
EFI_STATUS SwSmiHandler(
EFI_HANDLE DispatchHandle,
const void *Context,
EFI_SMM_SW_CONTEXT *CommBuffer,
UINTN *CommBufferSize)
{
UINT8 FuncIndex;
SMI_UC_DWORD_REGS *Buffer;
Buffer = 0;
if ( !gInit )
{
gInit = 1;
gInitError = InitMicrocodeVariables() == 0;
}
gEfiSmmCpuProtocol->ReadSaveState(
gEfiSmmCpuProtocol,
4,
EFI_SMM_SAVE_STATE_REGISTER_RSI,
CommBuffer->SwSmiCpuIndex,
&Buffer);
if ( LOWORD(Buffer->EAX) == 0xD042 )
{
FuncIndex = Buffer->EBX;
Buffer->EFLAGS &= ~1; // SMRAM write
LOWORD(Buffer->EAX) = 0; // SMRAM write
if ( gInitError || FuncIndex >= 4 )
{
Buffer->EFLAGS |= 1; // SMRAM write
LOWORD(Buffer->EAX) = 0x8600; // SMRAM write
}
else
{
(gMicrocodeUpdateAPI[FuncIndex])(Buffer);
}
}
return EFI_SUCCESS;
}
As we can see from the pseudocode, Buffer
is an attacker-controlled pointer (obtained via EFI_SMM_SAVE_STATE_REGISTER_RSI
). Buffer is not validated against overlapping with SMRAM.
Buffer
has the following structure:
00000000 struct SMI_UC_DWORD_REGS
00000000 {
00000000 UINT32 EAX;
00000004 UINT32 EBX;
00000008 UINT32 ECX;
0000000C UINT32 EDX;
00000010 UINT32 ESI;
00000014 UINT32 EDI;
00000018 UINT32 EFLAGS;
0000001C UINT16 ES;
0000001E UINT16 CS;
00000020 UINT16 SS;
00000022 UINT16 DS;
00000024 UINT16 FS;
00000026 UINT16 GS;
00000028 UINT32 EBP;
0000002C };
If LOWORD(Buffer->EAX)
is equal to 0xD042
, unvalidated writes will occur in SwSmiHandler
function and in functions from gMicrocodeUpdateAPI table:
.data:0000000000006518 gMicrocodeUpdateAPI dq offset PresenceTest
.data:0000000000006518 ; DATA XREF: SwSmiHandler+8B↑o
.data:0000000000006518 ; SwSmiHandler+92↑r
.data:0000000000006520 dq offset WriteUpdateData
.data:0000000000006528 dq offset UpdateControl
.data:0000000000006530 dq offset ReadUpdateData
UINT64 PresenceTest(SMI_UC_DWORD_REGS *Regs)
{
UINT64 NumMcodeBlks;
// Regs is attacker-controlled
NumMcodeBlks = gNumMcodeBlks;
qmemcpy(&Regs->EBX, "ETNIPEPL", 8); // SMRAM write
LOWORD(Regs->ESI) = NumMcodeBlks; // SMRAM write
Regs->EDX = 1; // SMRAM write
return NumMcodeBlks;
}
void UpdateControl(SMI_UC_DWORD_REGS *Regs)
{
// Regs is attacker-controlled
LOBYTE(Regs->EBX) = 1; // SMRAM write
}
The check if ( LOWORD(Buffer->EAX) == 0xD042 )
makes it harder to exploit, but does not mitigate the vulnerability, since an attacker can at least write code at the location of the check itself:
.text:000000000000208E 41 BB 42 D0 00 mov r11d, 0D042h
.text:000000000000208E 00
.text:0000000000002094 66 44 39 18 cmp [rax], r11w
This vulnerability is subject to a 90 day disclosure period. After 90 days or when a patch has been made generally available (whichever comes first) the advisory will be publicly disclosed.
BINARLY REsearch team