Advisory ID:
BRLY-DVA-2025-006

Multiple SMM memory corruption vulnerabilities in SMM module on Dell device (SMRAM write)

July 8, 2025
Severity:
High
CVSS Score
8.2
Public Disclosure Date:
July 8, 2025
CVE ID:

Summary

BINARLY REsearch team has discovered multiple memory corruption vulnerabilities in Dell device firmware that could allow a potential attacker to write fixed or predictable data to an attacker-controlled address.
Vendors Affected Icon

Vendors Affected

Dell
Affected Products icon

Affected Products

Multiple

Potential Impact

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

Vulnerability Information

  • BINARLY internal vulnerability identifier: BRLY-DVA-2025-006
  • Dell PSIRT assigned CVE identifier: CVE-2025-36600
  • CVSS v3.1: 8.2 High AV:L/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H

Affected firmware with confirmed impact by BINARLY team

Device name Firmware version OEM Module name FW SHA256
Dell Latitude 12 7214 1.48.0 (2024-12-10) Dell MicrocodeUpdate 9ea9d1ff75d96f95cd7f0a652e82933de7dad6473d3975ec66dcdfe4fd8291de

Vulnerability description

Let's consider the module 4e6c9eacce454b937a69d9022a2693e9f237cac8ee6354d197141df58503f43e.

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)
{
  EFI_STATUS Status;
  SMI_UC_DWORD_REGS *Regs;
  UINT8 FuncIndex;
  SMI_UC_DWORD_REGS *Buffer;

  Buffer = 0;
  if ( !gInit )
  {
    gInit = 1;
    gInitError = InitMicrocodeVariables() == 0;
  }
  Status = gEfiSmmCpuProtocol->ReadSaveState(
             gEfiSmmCpuProtocol,
             4,
             EFI_SMM_SAVE_STATE_REGISTER_RSI,
             CommBuffer->SwSmiCpuIndex,
             &Buffer);
  if ( Status == EFI_SUCCESS )
  {
    // validation takes place, but the validation function
    // is not sufficient
    Status = ValidateBuffer(Buffer, 44);
    if ( Status == EFI_SUCCESS )
    {
      if ( LOWORD(Regs->EAX) == 0xD042 )
      {
        FuncIndex = Regs->EBX; // SMRAM write
        Regs->EFLAGS &= ~1; // SMRAM write
        LOWORD(Buffer->EAX) = 0;
        if ( gInitError || FuncIndex >= 4 )
        {
          Buffer->EFLAGS |= 1; // SMRAM write
          LOWORD(Buffer->EAX) = 0x8600; // SMRAM write
        }
        else
        {
          (gMicrocodeUpdateAPI[FuncIndex])(Buffer);
        }
      }
      return EFI_SUCCESS;
    }
  }
  return Status;
}

As we can see from the pseudocode, Buffer is an attacker-controlled pointer (obtained via EFI_SMM_SAVE_STATE_REGISTER_RSI). Buffer has a size of 44 (0x2C) and is validated with the ValidateBuffer function:

EFI_STATUS ValidateBuffer(UINT64 Buffer, UINTN Size)
{
  if ( Buffer >= gSmramRegionStart && Buffer < gSmramRegionEnd
    || Buffer + Size >= gSmramRegionStart && Buffer + Size < gSmramRegionEnd )
  {
    return EFI_ACCESS_DENIED;
  }
  else
  {
    return EFI_SUCCESS;
  }
}

Where gSmramRegionStart and gSmramRegionEnd variables initialized in the following function:

EFI_STATUS Main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS NUMPAD "+" TO EXPAND]

  SmramMap = 0;
  SmramMapSize = 0;
  if ( !InitMicrocodeVariables() )
    return EFI_UNSUPPORTED;
  gSmst->SmmLocateProtocol(&EFI_SMM_SW_DISPATCH2_PROTOCOL_GUID, 0, &EfiSmmSwDispatch2Protocol);
  gSmst->SmmLocateProtocol(&EFI_SMM_CPU_PROTOCOL_GUID, 0, &gEfiSmmCpuProtocol);
  RegisterContext.SwSmiInputValue = 0x44;
  EfiSmmSwDispatch2Protocol->Register(EfiSmmSwDispatch2Protocol, SwSmiHandler, &RegisterContext, DispatchHandle);
  gBS->LocateProtocol(&EFI_SMM_ACCESS2_PROTOCOL_GUID, 0, &gEfiSmmAccess2Protocol);
  if ( gEfiSmmAccess2Protocol->GetCapabilities(gEfiSmmAccess2Protocol, &SmramMapSize, 0) == EFI_BUFFER_TOO_SMALL )
  {
    SmramMap = SmmAllocatePool(EfiRuntimeServicesData, SmramMapSize);
    (gEfiSmmAccess2Protocol->GetCapabilities)(gEfiSmmAccess2Protocol, &SmramMapSize, SmramMap);
  }
  Current = SmramMap;
  if ( SmramMap < (SmramMap + SmramMapSize) )
  {
    while ( Current->CpuStart <= 0x100000 )
    {
      if ( ++Current >= (SmramMap + SmramMapSize) )
        goto _Free;
    }
    CpuStart = Current->CpuStart;
    PhysicalSize = Current->PhysicalSize;

    // start address and end address for one SMRAM region
    gSmramRegionStart = CpuStart;
    gSmramRegionEnd = PhysicalSize + CpuStart;
  }
_Free:
  Free(SmramMap);
  return 0;
}

Given the functionality implemented in the ValidateBuffer function, it will only validate Buffer against one SMRAM region whereas it is possible to have multiple SMRAM regions, for example, on our test system:

  • SMRAM: 0x0000000048000000 - 0x000000004BFFFFFF (Size = 0x04000000)
  • First region: 0x0000000048000000 - 0x0000000048001000

This leaves the attacker with the ability to specify a Buffer that passes the check but is still in 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, 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
}

In the WriteUpdateData and ReadUpdateData functions, nested pointers are validated with the same unsafe ValidateBuffer function.

Patch

The updated firmware version uses the secure gAmiSmmBufferValidationProtocol->ValidateMemoryBuffer() function instead of the insecure ValidateBuffer() function:

Status = gEfiSmmCpuProtocol->ReadSaveState(
            gEfiSmmCpuProtocol,
            4,
            EFI_SMM_SAVE_STATE_REGISTER_RSI,
            CommBuffer->SwSmiCpuIndex,
            &Buffer);
if ( Status == EFI_SUCCESS )
{
  if ( gAmiSmmBufferValidationProtocol )
  {
    Status = (gAmiSmmBufferValidationProtocol->ValidateMemoryBuffer)(Buffer, 44);
    if ( Status == EFI_SUCCESS )

Disclosure timeline

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.

Disclosure Activity Date
Dell PSIRT is notified 2025-04-08
Dell PSIRT is confirmed issue 2025-05-01
Dell PSIRT assigned CVE number 2025-07-07
Dell PSIRT provide patch release 2025-07-07
BINARLY public disclosure 2025-07-08

Acknowledgements

BINARLY REsearch team

Tags
Dell
Firmware
UEFI
FWHunt
See if you are impacted now with our Firmware Vulnerability Scanner