n/a
An attacker can exploit this vulnerability to elevate privileges from ring 0 to ring -2, execute arbitrary code in System Management Mode - an environment more privileged than operating system (OS) and completely isolated from it. Running arbitrary code in SMM additionally bypasses SMM-based SPI flash protections against modifications, which can help an attacker to install a firmware backdoor/implant into BIOS. Such a malicious firmware code in BIOS could persist across operating system re-installs. Additionally, this vulnerability potentially could be used by malicious actors to bypass security mechanisms provided by UEFI firmware (for example, Secure Boot and some types of memory isolation for hypervisors).
This vulnerability was detected by the Deep Vulnerability Analysis (DVA) component from Binarly Platform
For supported affected platforms, Dell has addressed this vulnerability in DSA-2024-125. All reported platforms have been determined to be End of Support Life.
Let's consider the vulnerability on the example of a module with SHA256 0f6348134c2b14cef0753708f3a088ddb72d56852133c76fc29b50623a7493b9. The pseudocode of the vulnerable function is presented below:
__int64 __fastcall SwSmiHandler(
        EFI_HANDLE DispatchHandle,
        const void *Context,
        UINTN *CommBuffer,
        UINTN *CommBufferSize)
{
  __int64 DellWmiSharedMem; // rax
  __int64 v5; // rdi
  int v7; // ecx
  int v8; // r9d
  unsigned int v9; // r8d
  unsigned int v10; // edx
  UINTN CpuIndex; // rbx
  char *v12; // rax
  __int64 v13; // r9
  char *v14; // rcx
  __int128 v15; // xmm1
  __int128 v16; // xmm0
  __int128 v17; // xmm1
  __int128 v18; // xmm0
  __int128 v19; // xmm1
  __int128 v20; // xmm0
  __int128 v21; // xmm1
  __int64 Status; // rax
  __int64 v23; // rax
  _DWORD *Ptr; // rcx
  unsigned int Data; // [rsp+30h] [rbp-D0h] BYREF
  EFI_GUID VendorGuid; // [rsp+38h] [rbp-C8h] BYREF
  UINTN DataSize; // [rsp+48h] [rbp-B8h] BYREF
  char v28; // [rsp+50h] [rbp-B0h] BYREF
  int Buffer; // [rsp+220h] [rbp+120h] BYREF
  unsigned int v30; // [rsp+224h] [rbp+124h] BYREF
  unsigned int v31; // [rsp+228h] [rbp+128h] BYREF
  int v32[9]; // [rsp+22Ch] [rbp+12Ch] BYREF
  char v33[464]; // [rsp+250h] [rbp+150h] BYREF
  _DWORD v34[3]; // [rsp+420h] [rbp+320h] BYREF
  unsigned int v35; // [rsp+42Ch] [rbp+32Ch] BYREF
  DellWmiSharedMem = gDellWmiSharedMem;
  v5 = 0;
  DataSize = 0;
  Data = 0;
  VendorGuid.Data1 = 0x8CC2B3F1;
  *&VendorGuid.Data2 = 0x4784EC41;
  *VendorGuid.Data4 = 0x5D4C4884;
  *&VendorGuid.Data4[4] = 0x91471358;
  if ( (gDellWmiSharedMem
     || ((DataSize = 4,
          (gRT->GetVariable(L"DELL_WMI_SHARED_MEM", &VendorGuid, 0, &DataSize, &Data) & 0x8000000000000000) != 0)
       ? (DellWmiSharedMem = gDellWmiSharedMem)
       : (DellWmiSharedMem = Data, gDellWmiSharedMem = Data),
         DellWmiSharedMem))
    && *DellWmiSharedMem == 'DWMI' )
  {
    if ( *(DellWmiSharedMem + 20) )
    {
      v7 = Buffer;
    }
    else
    {
      v7 = *(DellWmiSharedMem + 24);
      Buffer = v7;
    }
    if ( (*(DellWmiSharedMem + 20) & 0xFF00) != 0 )
    {
      v8 = v32[0];
    }
    else
    {
      v8 = *(DellWmiSharedMem + 28);
      v32[0] = v8;
    }
    if ( (*(DellWmiSharedMem + 20) & 0xFF0000) != 0 )
    {
      v9 = v30;
    }
    else
    {
      v9 = *(DellWmiSharedMem + 32);
      v30 = v9;
    }
    if ( (*(DellWmiSharedMem + 20) & 0xFF000000) != 0 )
    {
      v10 = v31;
    }
    else
    {
      v10 = *(DellWmiSharedMem + 36);
      v31 = v10;
    }
    if ( *(DellWmiSharedMem + 20) )
      v7 = DellWmiSharedMem + 48;
    Buffer = v7;
    if ( (*(DellWmiSharedMem + 20) & 0xFF00) != 0 )
      v8 = DellWmiSharedMem + 48;
    v32[0] = v8;
    CpuIndex = DataSize;
    if ( (*(DellWmiSharedMem + 20) & 0xFF0000) != 0 )
      v9 = DellWmiSharedMem + 48;
    v30 = v9;
    if ( (*(DellWmiSharedMem + 20) & 0xFF000000) != 0 )
    {
      v10 = DellWmiSharedMem + 48;
      v31 = DellWmiSharedMem + 48;
    }
  }
  else
  {
    CpuIndex = *CommBuffer;
    gEfiSmmCpuProtocol->ReadSaveState(gEfiSmmCpuProtocol, 4, EFI_SMM_SAVE_STATE_REGISTER_RAX, CpuIndex, &Buffer);
    gEfiSmmCpuProtocol->ReadSaveState(gEfiSmmCpuProtocol, 4, EFI_SMM_SAVE_STATE_REGISTER_RBX, CpuIndex, v32);
    gEfiSmmCpuProtocol->ReadSaveState(gEfiSmmCpuProtocol, 4, EFI_SMM_SAVE_STATE_REGISTER_RCX, CpuIndex, &v30);
    gEfiSmmCpuProtocol->ReadSaveState(gEfiSmmCpuProtocol, 4, EFI_SMM_SAVE_STATE_REGISTER_RDX, CpuIndex, &v31);
    v10 = v31;
    v9 = v30;
  }
  v12 = v33;
  v13 = 4;
  v14 = &v28;
  do
  {
    v15 = *(v14 + 1);
    *v12 = *v14;
    v16 = *(v14 + 2);
    *(v12 + 1) = v15;
    v17 = *(v14 + 3);
    *(v12 + 2) = v16;
    v18 = *(v14 + 4);
    *(v12 + 3) = v17;
    v19 = *(v14 + 5);
    *(v12 + 4) = v18;
    v20 = *(v14 + 6);
    *(v12 + 5) = v19;
    v21 = *(v14 + 7);
    v14 += 128;
    *(v12 + 6) = v20;
    v12 += 128;
    *(v12 - 1) = v21;
    --v13;
  }
  while ( v13 );
  if ( !v10 )
    goto LABEL_34;
  if ( !gAmiSmmBufferValidationProtocol )
    return EFI_ACCESS_DENIED;
  Status = (gAmiSmmBufferValidationProtocol->ValidateMemoryBuffer)(v10, v9);
  if ( Status >= 0 )
  {
LABEL_34:
    if ( gFuncTable[0] != -1 )
    {
      v23 = 0LL;
      while ( gFuncTable[v23 + 1] != LOBYTE(v34[0])
           || gFuncTable[v23] != 1
           && (gFuncTable[v23 + 2] != BYTE1(v34[0])
            || gFuncTable[v23] != 2
            && (gFuncTable[v23 + 3] != v35 || gFuncTable[v23] != 3 && gFuncTable[v23 + 4] != BYTE1(v35))) )
      {
        ++v5;
        v23 = 13 * v5;
        if ( gFuncTable[13 * v5] == -1 )
          return 0;
      }
      (*&gFuncTable[13 * v5 + 5])(v33, v34[0], v35, *(v34 + 1));
      Ptr = gDellWmiSharedMem;
      if ( *gDellWmiSharedMem == 'DWMI' )
      {
        *gDellWmiSharedMem = 0;
        Ptr[6] = v34[0];                        // unchecked write (SMRAM corruption)
        Ptr[7] = v35;                           // unchecked write (SMRAM corruption)
        Ptr[8] = v34[1];                        // unchecked write (SMRAM corruption)
        Ptr[9] = v34[2];                        // unchecked write (SMRAM corruption)
      }
      else
      {
        if ( v34[0] != Buffer )
          gEfiSmmCpuProtocol->WriteSaveState(gEfiSmmCpuProtocol, 4, EFI_SMM_SAVE_STATE_REGISTER_RAX, CpuIndex, v34);
        if ( v35 != v32[0] )
          gEfiSmmCpuProtocol->WriteSaveState(gEfiSmmCpuProtocol, 4, EFI_SMM_SAVE_STATE_REGISTER_RBX, CpuIndex, &v35);
        if ( v34[1] != v30 )
          gEfiSmmCpuProtocol->WriteSaveState(
            gEfiSmmCpuProtocol,
            4,
            EFI_SMM_SAVE_STATE_REGISTER_RCX,
            CpuIndex,
            &v34[1]);
        if ( v34[2] != v31 )
          gEfiSmmCpuProtocol->WriteSaveState(
            gEfiSmmCpuProtocol,
            4,
            EFI_SMM_SAVE_STATE_REGISTER_RDX,
            CpuIndex,
            &v34[2]);
      }
    }
    return 0;
  }
  return Status;
}The GetVariable call initializes gDellWmiSharedMem with the value stored in the DELL_WMI_SHARED_MEM NVRAM variable. Since the DELL_WMI_SHARED_MEM NVRAM variable is controlled by an attacker, they can perform an arbitrary write operation here:
Ptr[6] = v34[0];                        // unchecked write (SMRAM corruption)
Ptr[7] = v35;                           // unchecked write (SMRAM corruption)
Ptr[8] = v34[1];                        // unchecked write (SMRAM corruption)
Ptr[9] = v34[2];                        // unchecked write (SMRAM corruption)as Ptr is initialized from gDellWmiSharedMem.
In order to fix this vulnerability, all user-controllable offsets and pointers should be checked with SmmIsBufferOutsideSmmValid() or analogues before any write attempt.
This bug is subject to a 90 day disclosure deadline. After 90 days elapsed or a patch has been made broadly available (whichever is earlier), the bug report will become visible to the public.
BINARLY REsearch team