Binarly Advisories


Binarly Advisories

[BRLY-2022-032] The stack memory leak vulnerability in DXE driver.


BINARLY efiXplorer team has discovered a stack memory leak vulnerability that allows a potencial attacker to write stack memory to NVRAM variable.

Vulnerability Information

Affected Lenovo firmwares with confirmed impact by Binarly team

Fimware Module name Module SHA256 File GUID
N3HET53W/$0AN3H00.FL1 PersistenceConfigDxe d4a34f30e64e7eea479bc55d9173eb91c9c4e6c8203b318a12877758e2a34f3b 27A95D13-15FB-4A2E-91E2-C784BF0D20D3

Potential impact

An attacker with local privileged access can exploit this vulnerability to read the contents of the stack and use this information to exploit other vulnerabilities in DXE. A malicious code installed as a result of the vulnerability exploitation in a DXE driver could survive across an operating system (OS) boot process and runtime or modify NVRAM area on SPI flash storage (to gain persistence on target platform). Additionally, this vulnerability potentially could be used by threat actors to bypass OS security mechanisms (modify privileged memory or runtime variables), influence on the OS boot process, and in some cases would allow an attacker to hook or modify EFI Runtime services.

Vulnerability description

The vulnerable function located at offet 0x2570 in the binary. The pseudocode of the vulnerable function is shown below:

__int64 __fastcall EventNotifier()
  __int64 result;
  EFI_SET_VARIABLE SetVariable_1;
  __int64 DataSize;
  unsigned int Attributes;
  __int64 UnknownProtocolInterface;
  __int16 LenovoAbtStatusValue[7];
  char LenovoSecurityConfig[139];

  result = LocateProtocol(&gProtocolGuid, &gDataSegmentBase);
  if ( (result & 0x8000000000000000) == 0 )
    DataSize = 0x8B;
    result = (gRT->GetVariable)(
    if ( (result & 0x8000000000000000) == 0 )
      SetVariable = gRT->SetVariable;
      LenovoSecurityConfig[38] = 1;
      if ( ((SetVariable)(
              LenovoSecurityConfig) & 0x8000000000000000) == 0 )
        (*(UnknownProtocolInterface + 0x10))(); // aa5978d6-4fba-4827-b776-9a11fc8cce4c
      GetVariable = gRT->GetVariable;
      DataSize = 14;
      if ( ((GetVariable)(L"LenovoAbtStatus", &unk_4030, &Attributes, &DataSize, LenovoAbtStatusValue) & 0x8000000000000000) != 0 )
        sub_28A8(LenovoAbtStatusValue, 14);
        LenovoAbtStatusValue[2] = 0x100;
        LenovoAbtStatusValue[0] = 1;
        sub_28A8(&LenovoAbtStatusValue[3], 7);
      SetVariable_1 = gRT->SetVariable;
      LOBYTE(LenovoAbtStatusValue[2]) = 1;
      return (SetVariable_1)(L"LenovoAbtStatus", &unk_4030, Attributes, DataSize, LenovoAbtStatusValue);
  return result;

As we can see from the pseudocode, for the LenovoAbtStatus variable gRT->SetVariable() service is called with the DataSize value, which can be overwritten inside the gRT->GetVariable() service.

Thus, a potential attacker can write X - 14 bytes from the stack to NVRAM if writes any buffer of length X > 14 to the LenovoAbtStatus NVRAM variable.

In order to fix this vulnerability, the DataSize variable must be initialized before gRT->SetVariable().

Disclosure timeline

This vulnerability is subject to a 90 day disclosure deadline. After 90 days elapsed or a patch has been made broadly available (whichever is earlier), the vulnerability report will become visible to the public.

Disclosure Activity Date (YYYY-mm-dd)
Lenovo PSIRT is notified 2022-10-24
Lenovo PSIRT confirmed reported issue 2022-12-16
Lenovo PSIRT assigned CVE number 2022-12-27
Lenovo PSIRT provide patch release 2023-01-03
BINARLY public disclosure date 2023-01-09


BINARLY efiXplorer team

Tag list
Back to overview