Multiple SMM memory corruption vulnerabilities in SMM module on HP device (SMRAM write).
BINARLY REsearch team has discovered multiple memory corruption vulnerabilities in HP device firmware that could allow a potential attacker to write fixed or predictable data to an attacker-controlled address.
Image preview
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.
Image preview
Vulnerability Information
- BINARLY internal vulnerability identifier: BRLY-DVA-2025-012
- HP PSIRT assigned CVE identifier: CVE-2025-10451
- HP advisory: https://support.hp.com/us-en/document/ish_14547790-14547813-16/hpsbhf04103
- Insyde advisory: SA-2025009
- CVSS v3.1: 8.2 High AV:L/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H
Image preview
Affected firmware
| Device name | Unpacked firmware SHA256 | Firmware version | OEM | IBV | Module name | Module GUID | Module SHA256 | Module kind |
|---|---|---|---|---|---|---|---|---|
hp-15-db0000-laptop-pc | b1053252e03c608b69c142554393b014d0695d9b698bfef6216f5b85d6021ce5 | F.45 Rev.A (2024-12-10) | HP | Insyde | H19Int15CallbackSmm | 0cbe278d-bd94-477d-9381-34bd2dba1c53 | 2beee5386dc06e953c7c5261b2d68d3480c0d5b6ac587a05d0a29a1150332bb3 | SmmModule |
hp-340-g4-notebook-pc | 934fda8d6bd175fa20b0bda6d23ed0f1b73798bb18ad0c8102a1cbc7cb4869bb | F.71 Rev.A (2024-10-18) | HP | Insyde | H19Int15CallbackSmm | 0cbe278d-bd94-477d-9381-34bd2dba1c53 | fa41eedbd293230d04be18ef2b11c5abdcc8a9ed0f3eeca1f5253e4e514795c7 | SmmModule |
hp-envy-13-ba0000-laptop-pc-series | c25a9f3b1283b436d2d3ad7e06aab1a56141c273cae79baf012db241f50b4290 | F.29 Rev.A (2023-10-27) | HP | Insyde | H19Int15CallbackSmm | 0cbe278d-bd94-477d-9381-34bd2dba1c53 | 90e2162c317e907242eae34b8ae897903b02212c2b2cc761b5a4f61e601b7603 | SmmModule |
hp-envy-15-ed0000-x360-convertible-laptop-pc-series | 0e78b595762a26885a55fbcd42bb81289025094511fdba2cab409d45ef4b8980 | F.29 Rev.A (2023-10-27) | HP | Insyde | H19Int15CallbackSmm | 0cbe278d-bd94-477d-9381-34bd2dba1c53 | 90e2162c317e907242eae34b8ae897903b02212c2b2cc761b5a4f61e601b7603 | SmmModule |
Image preview
Vulnerability description
Let's consider the module 2beee5386dc06e953c7c5261b2d68d3480c0d5b6ac587a05d0a29a1150332bb3.
The pseudocode of the vulnerable function at 0x780 is shown below:
EFI_STATUS SwSmiHandler(
EFI_HANDLE DispatchHandle,
const void *Context,
EFI_SMM_SW_CONTEXT *CommBuffer,
UINTN *CommBufferSize)
{
HP_SERVICE *HpService;
UINTN CpuIndex;
EFI_STATUS Status;
void *BufferCopy;
bool NotFound;
UINT32 RaxRegister;
UINT32 RsiRegister;
EFI_SMM_CPU_PROTOCOL *EfiSmmCpuProtocol;
HpService = gHpService;
CpuIndex = 0;
if ( !gHpService )
{
gSmst->SmmLocateProtocol(&HP_SERVICE_GUID, 0, &gHpService);
HpService = gHpService;
if ( !gHpService )
return 0;
}
if ( !HpService->OfcSmmDriverProtocol )
{
gSmst->SmmLocateProtocol(&OFC_SMM_DRIVER_PROTOCOL_GUID, 0, &HpService->OfcSmmDriverProtocol);
HpService = gHpService;
}
if ( !HpService || !HpService->OfcSmmDriverProtocol )
return 0;
Status = CheckValueFromProtocol(gBufferFromInterface);
if ( !EFI_ERROR(Status) )
{
BufferCopy = AllocateAndCopy(0x2E8, gBufferFromInterface);
if ( !BufferCopy )
BufferCopy = gBufferFromInterface;
Status = gSmst->SmmLocateProtocol(&EFI_SMM_CPU_PROTOCOL_GUID, 0, &EfiSmmCpuProtocol);
if ( !EFI_ERROR(Status) )
{
NotFound = gSmst->NumberOfCpus == 0;
if ( gSmst->NumberOfCpus )
{
do
{
EfiSmmCpuProtocol->ReadSaveState(
EfiSmmCpuProtocol,
4,
EFI_SMM_SAVE_STATE_REGISTER_RAX,
CpuIndex,
&RaxRegister);
if ( RaxRegister == *(*(gHpService + 55) + 517) )
break;
++CpuIndex;
}
while ( CpuIndex < gSmst->NumberOfCpus );
NotFound = CpuIndex == gSmst->NumberOfCpus;
}
if ( NotFound )
return EFI_NOT_FOUND;
EfiSmmCpuProtocol->ReadSaveState(EfiSmmCpuProtocol, 4, EFI_SMM_SAVE_STATE_REGISTER_RSI, CpuIndex, &RsiRegister);
switch ( *RsiRegister )
{
case 0x5F11:
Command5F11(RsiRegister);
break;
case 0x5F12:
if ( (*(gHpService + 6) & 0x20) != 0 )
return 0;
Command5F12(RsiRegister, BufferCopy);
break;
case 0x5F13:
Command5F13(RsiRegister);
break;
default:
if ( *RsiRegister == 0x9999 && *(RsiRegister + 4) == 0xDEAD )
CommandDefault(RsiRegister, BufferCopy);
break;
}
if ( BufferCopy != gBufferFromInterface )
{
CopyMem(gBufferFromInterface, BufferCopy, 0x2E8);
Free(BufferCopy);
}
return 0;
}
}
return Status;
}
As we can see from the pseudocode, RsiRegister is controlled by the attacker as it's equal to the RSI value obtained with gEfiSmmCpuProtocol->ReadSaveState. Depending on the *(UINT16 *)RsiRegister, the following functions can be called with the RsiRegister parameter:
- Command5F11
- Command5F12
- Command5F13
Additionally, with *RsiRegister == 0x9999 && *(RsiRegister + 4) == 0xDEAD, the CommandDefault function will be called.
Each of the above functions contains arbitrary write operations to the buffer pointed to by RsiRegister.
Each of the functions are called such that the first parameter is controllable by the attacker. This parameter has the following format:
00000000 struct COMM_BUFFER_PARAM
00000000 {
00000000 UINT32 Result;
00000004 UINT32 Value4;
00000008 UINT32 Value8;
0000000C UINT32 ValueC;
00000010 UINT32 Value10;
00000014 UINT32 Value14;
00000018 UINT32 Value18;
0000001C UINT32 Value1C;
00000020 UINT32 Value20;
00000024 UINT32 Value24;
00000028 };
As we can see in the example of the Command5F12 function, the write operations to this buffer are performed without prior validation of the pointer for overlapping with SMRAM:
void Command5F12(COMM_BUFFER_PARAM *Param, void *Buffer)
{
UINT32 Value18;
UINT32 Res;
if ( Param->ValueC == '_HPQ' )
{
Param->Value18 |= 1; // SMRAM write
Value18 = Param->Value18;
if ( Buffer )
{
if ( *(Buffer + 683) == 1 )
Param->Value4 |= 1; // SMRAM write
else
Param->Value4 &= ~1; // SMRAM write
Res = Value18 & 0xFFFFFFFE;
}
else
{
Res = Value18 | 1;
}
Param->Value18 = Res; // SMRAM write
}
}
Image preview
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 |
|---|---|
HP PSIRT is notified | 2025-04-08 |
HP PSIRT is confirmed issue | 2025-08-20 |
Insyde advisory is published | 2025-12-09 |
HP PSIRT provide patch release | 2026-03-24 |
BINARLY public disclosure date | 2026-03-25 |
Image preview
Acknowledgements
Image preview
See if you are impacted now with our Firmware Vulnerability Scanner
Find Vulnerabilities, Generate SBOMs & CBOMs