Multiple SMM memory corruption vulnerabilities in SMM module on Gigabyte device (SMRAM write).
BINARLY REsearch team has discovered multiple memory corruption vulnerabilities in Gigabyte 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-010
- CERT/CC assigned CVE identifier: CVE-2025-7028
- CERT/CC assigned case number: VU#746790
- 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 |
|---|---|---|---|---|---|---|---|---|
GA-IMB1900N | c6426601186ec6cfd64654dd655fcedab5efbcc3add51d09a555dfbe8e7b9b10 | F2a (2024-08-16) | Gigabyte | AMI | SmiFlash | bc327dbd-b982-4f55-9f79-056ad7e987c5 | 290fde7f0f7f3c1a39a4345a99cea4165b74e7c63e3f46590610664fcf49f359 | SmmModule |
GA-IMB1900TN | 07158a13572e086f57a01ec34eb5c464ea900d6fc7a5e19d28b1eedd1360f5ce | F2c (2024-08-16) | Gigabyte | AMI | SmiFlash | bc327dbd-b982-4f55-9f79-056ad7e987c5 | 3d66d929765b38e5bafe60982b47df311a62164d8a94dee4aeb26a02bfeed8ee | SmmModule |
GA-J1800M-D2P-IN | 87ad2f85cd12296635693946c777c3405a0d0af941438ebf137fa55cc01e81e2 | F2c (2024-08-16) | Gigabyte | AMI | SmiFlash | bc327dbd-b982-4f55-9f79-056ad7e987c5 | 6245aa4a170fcfbb5e06fda5d47b1a21ecfdd3a4561f6a50cd05927e0d7cd772 | SmmModule |
GA-J1800M-D3P | de9e05598ef4e6ba7341933d345d66bcde75f95ace0a5d7e18342d4b8d792329 | F4b (2023-11-06) | Gigabyte | AMI | SmiFlash | bc327dbd-b982-4f55-9f79-056ad7e987c5 | a88dfdc714d06f28df715be4393d85937db75e147deed619923958d8217c3bc9 | SmmModule |
GA-J1800N-D2PH | 1af8bc531173b84c524a7c6f1d2bf2d1e5b8586c7bf98d177f28a8e4c5e68d74 | F2c (2024-08-15) | Gigabyte | AMI | SmiFlash | bc327dbd-b982-4f55-9f79-056ad7e987c5 | aa3d9a2eeb85416900535791c68664dd165b539c24b0998502e846b43a0fe941 | SmmModule |
GA-J1800N-D2P | 03bdb61ee4e98eec179e36cca5560153a289576feb46d834d086bf3bed21cdbb | F3g (2024-08-16) | Gigabyte | AMI | SmiFlash | bc327dbd-b982-4f55-9f79-056ad7e987c5 | 1cad28f623e467ae2cfeeb98d84f7e03805aba6e8ea0ebef4405ff94acb93693 | SmmModule |
GA-J1900M-D2P | 90a5286ccb5a22fe1f600d5a53c9997e2389f77d984ba7fe1a121797c9c3f813 | F4b (2024-08-15) | Gigabyte | AMI | SmiFlash | bc327dbd-b982-4f55-9f79-056ad7e987c5 | 3cb73286a10ad2fd5905aeff13e9f58a37d6b3a4c06e8988830d4a9a51d076b9 | SmmModule |
GA-J1900N-D3V | 8458ba542367cc665d6de863d34928cc180951a2a2320158cb05df5f46e701ed | F9a (2024-08-15) | Gigabyte | AMI | SmiFlash | bc327dbd-b982-4f55-9f79-056ad7e987c5 | 786e42c315cde9ed785eafbac01d002b6fd524576b30bfd83ee258d95794e153 | SmmModule |
J4005N D2P | 6e7c6b1f660994efbb989999503766cce931aba36ba24a31b03d9c3592d0da8e | F4a (2024-08-01) | Gigabyte | AMI | SmiFlash | bc327dbd-b982-4f55-9f79-056ad7e987c5 | 8d4da1a52de2d7d3b002af2dbc05452e9b78305fc21f1fcc0adf6cd7dc8fd0b2 | SmmModule |
Image preview
Vulnerability description
Let's consider the module 290fde7f0f7f3c1a39a4345a99cea4165b74e7c63e3f46590610664fcf49f359.
The pseudocode of the vulnerable function at 0x1A50 is shown below (SwSmiInputValue: 0x20):
EFI_STATUS SwSmiHandler(
EFI_HANDLE DispatchHandle,
const void *Context,
EFI_SMM_SW_CONTEXT *CommBuffer,
UINTN *CommBufferSize)
{
UINTN SwSmiCpuIndex;
UINT8 CommandPort;
EFI_STATUS Status;
UINT64 Data;
void (*SMIFlashPreHandlerFunc)(UINT64, FUNC_BLOCK *);
FUNC_BLOCK *FuncBlock;
UINTN PreHandlerFuncIndex;
UINT64 Rem0;
UINT64 Rem1;
void (*SMIFlashEndHandlerFunc)();
UINTN Index;
void (*SMIFlashPreUpdateFunc)();
UINTN FlashPreUpdateFuncIndex;
void (*SMIFlashPreHandlerFunc0)(UINT64, FUNC_BLOCK *);
UINTN PostHandlerFuncIndex;
UINT32 RbxRegister;
UINT32 RcxRegister;
RcxRegister = 0;
RbxRegister = 0;
if ( !CommBuffer )
return 0;
if ( !CommBufferSize )
return 0;
SwSmiCpuIndex = CommBuffer->SwSmiCpuIndex;
CommandPort = CommBuffer->CommandPort;
if ( CommBuffer->SwSmiCpuIndex == -1 )
return 0;
gEfiSmmCpuProtocol->ReadSaveState(
gEfiSmmCpuProtocol,
4,
EFI_SMM_SAVE_STATE_REGISTER_RBX,
CommBuffer->SwSmiCpuIndex,
&RbxRegister);
Status = gEfiSmmCpuProtocol->ReadSaveState(
gEfiSmmCpuProtocol,
4,
EFI_SMM_SAVE_STATE_REGISTER_RCX,
SwSmiCpuIndex,
&RcxRegister);
Data = RbxRegister;
SMIFlashHandlerFunc0 = gSMIFlashHandlerFuncs[0];
// FuncBlock is attacker controlled and unchecked pointer
FuncBlock = (RbxRegister + (RcxRegister << 32));
PreHandlerFuncIndex = 0;
// SMIFlashPreHandlerFuncs is empty
while...
Rem0 = CommandPort - 32;
switch ( CommandPort )
{
case SMIFLASH_ENABLE_FLASH:
SMIFlashPreUpdateFunc = gSMIFlashPreUpdateFuncs[0];
FlashPreUpdateFuncIndex = 0;
while ( SMIFlashPreUpdateFunc )
{
SMIFlashPreUpdateFunc();
SMIFlashPreUpdateFunc = *(&gSMIFlashPreUpdateFuncs[1] + FlashPreUpdateFuncIndex++);
}
(gAmiSmmFlashProtocol->DeviceWriteEnable)(Rem0);
break;
case SMIFLASH_READ_FLASH:
// vulnerable function
ReadFlash(FuncBlock);
break;
case SMIFLASH_ERASE_FLASH:
// vulnerable function
EraseFlash(FuncBlock);
break;
case SMIFLASH_WRITE_FLASH:
// vulnerable function
WriteFlash(FuncBlock);
break;
default:
Rem1 = CommandPort - SMIFLASH_DISABLE_FLASH;
if ( CommandPort == SMIFLASH_DISABLE_FLASH )
{
SMIFlashEndHandlerFunc = gSMIFlashEndHandlerFuncs[0];
Index = 0;
while ( SMIFlashEndHandlerFunc )
{
SMIFlashEndHandlerFunc();
SMIFlashEndHandlerFunc = *(&gSMIFlashEndHandlerFuncs[1] + Index++);
}
gAmiSmmFlashProtocol->DeviceWriteDisable();
}
else if ( CommandPort == SMIFLASH_GET_FLASH_INFO )
{
// vulnerable function
GetFlashInfo((INFO_BLOCK *)FuncBlock);
}
break;
}
// gSMIFlashHandlerFuncs is empty
SMIFlashHandlerFunc1 = gSMIFlashHandlerFuncs[1];
PostHandlerFuncIndex = 0;
while...
return Status;
}
As we can see from the pseudocode, FuncBlock is controlled by the attacker. Depending on the CommandPort (which is also controlled by the attacker), the following functions can be called with the FuncBlock parameter:
- ReadFlash
- EraseFlash
- WriteFlash
- GetFlashInfo
All of the above functions contain write operations to a FuncBlock buffer (which may point to SMRAM since it is not checked).
ReadFlash
EFI_STATUS ReadFlash(FUNC_BLOCK *FuncBlock)
{
EFI_STATUS Status;
// SMRAM write via Read API function as FuncBlock->BufAddr nested pointer is not checked
Status = (gAmiSmmFlashProtocol->Read)(FuncBlock->BlockAddr - 0x500000, FuncBlock->BlockSize, FuncBlock->BufAddr);
// SMRAM write
FuncBlock->ErrorCode = EFI_ERROR(Status) != 0;
return Status;
}
The ReadFlash allows an attacker to corrupt SMRAM in 2 ways:
- using
gAmiSmmFlashProtocol->ReadwhenFuncBlock->BufAddrpoints to SMRAM - using write to
FuncBlock->ErrorCodewhenFuncBlockpoints to SMRAM
EraseFlash
EFI_STATUS EraseFlash(FUNC_BLOCK *FuncBlock)
{
EFI_STATUS Status;
UINT64 FlashAddress;
FlashAddress = FuncBlock->BlockAddr - g500000h;
LODWORD(FlashAddress) = FlashAddress & 0xFFFFF000;
Status = (gAmiSmmFlashProtocol->Erase)(FlashAddress, 0x1000);
// SMRAM write
FuncBlock->ErrorCode = EFI_ERROR(Status) != 0;
return Status;
}
The EraseFlash allows an attacker to corrupt SMRAM using write to FuncBlock->ErrorCode when FuncBlock points to SMRAM.
WriteFlash
EFI_STATUS WriteFlash(FUNC_BLOCK *FuncBlock)
{
EFI_STATUS Status; // rax
// SMRAM read via Write API function as FuncBlock->BufAddr nested pointer is not checked,
// allowing an attacker to write SMRAM content to flash and then read it from there
Status = (gAmiSmmFlashProtocol->Write)(FuncBlock->BlockAddr - g500000h, FuncBlock->BlockSize, FuncBlock->BufAddr);
// SMRAM write
FuncBlock->ErrorCode = EFI_ERROR(Status) != 0;
return Status;
}
The WriteFlash allows an attacker to corrupt SMRAM using write to FuncBlock->ErrorCode when FuncBlock points to SMRAM.
This function also allows the content of the SMRAM to be dumped using gAmiSmmFlashProtocol->Write if FuncBlock->BufAddr points to SMRAM (allowing an attacker to write SMRAM content to flash and then read it from there).
GetFlashInfo
EFI_STATUS GetFlashInfo(INFO_BLOCK *InfoBlock)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS NUMPAD "+" TO EXPAND]
__outbyte(0x80, 0x25);
Size = InfoBlock->Length - 0x10;
InfoBlock->Version = 0xB; // SMRAM write
Block = &InfoBlock->Blocks;
InfoBlock->Implemented = 0; // SMRAM write
InfoBlock->BiosRomSize = 0; // SMRAM write
*&InfoBlock->BaseBlockSize = 0; // SMRAM write
InfoBlock->TotalBlocks = 0x500; // SMRAM write
if ( Size < 0x2D00 )
{
InfoBlock->Implemented = 1; // SMRAM write
return 0;
}
Status = gSmst->SmmAllocatePool(EfiRuntimeServicesData, 2 * gNumberOfRomLayout, &StartBlock);
if ( !EFI_ERROR(Status) )
{
Status = gSmst->SmmAllocatePool(EfiRuntimeServicesData, 2 * gNumberOfRomLayout, &EndBlock);
if ( !EFI_ERROR(Status) )
{
NumberOfRomLayout = gNumberOfRomLayout;
Index = 0;
if ( gNumberOfRomLayout )
{
BlockIndex = 0;
do
{
++Index;
Res = RomLayout[BlockIndex].Offset >> 12;
StartBlock[BlockIndex] = Res;
EndBlock[BlockIndex] = Res + (RomLayout[BlockIndex].Size >> 12) - 1;
NumberOfRomLayout = gNumberOfRomLayout;
BlockIndex = Index;
}
while ( Index < gNumberOfRomLayout );
}
Start = StartBlock;
End = EndBlock;
NcbType = gNumberOfNcb + 0x7F;
for ( i = 0; i < 0x500; ++i )
{
Block->BlockSize = 4096; // SMRAM write
Element = 0;
Block->StartAddress = i << 12; // SMRAM write
if ( NumberOfRomLayout )
{
ElementIndex = 0;
while ( i < Start[ElementIndex] || i > End[ElementIndex] )
{
ElementIndex = ++Element;
if ( Element >= NumberOfRomLayout )
goto _Next;
}
Block->Type = RomLayout[Element].Type;// SMRAM write
}
...
}
}
return Status;
}
The GetFlashInfo allows an attacker to corrupt SMRAM using writes to InfoBlock it points to SMRAM.
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 |
|---|---|
CERT/CC is notified | 2025-04-15 |
Gigabyte confirmed issue | 2025-06-12 |
CERT/CC assigned CVE number | 2025-07-02 |
BINARLY public disclosure date | 2025-07-10 |
Image preview
Acknowledgements
Image preview
See if you are impacted now with our Firmware Vulnerability Scanner
Find Vulnerabilities, Generate SBOMs & CBOMs