
Static reverse-engineering of a GIGABYTE H510M K V2 (`H510MKV2.F3`) BIOS image: full UEFI firmware-volume extraction analysis of the PI-spec SMM Core memory allocator and a targeted hunt for the four SMM memory-corruption vulnerabilities GIGABYTE/Binarly disclosed in 2025 (CVE-2025-7026 CVE-2025-7027 CVE-2025-7028 CVE-2025-7029).
Reverse-engineering statico di un'immagine BIOS GIGABYTE H510M K V2 (H510MKV2.F3): analisi completa, tramite estrazione dei firmware volume UEFI, dell'allocatore di memoria del SMM Core di specifica PI e una ricerca mirata delle quattro vulnerabilità di corruzione della memoria SMM divulgate da GIGABYTE/Binarly nel 2025 (CVE-2025-7026 CVE-2025-7027 CVE-2025-7028 CVE-2025-7029).
Stato: 1 delle 4 CVE confermata presente (CVE-2025-7027). Le altre 3 sono state attivamente cercate nell'intero firmware accessibile e non trovate — vedi CVE non confermate per capire esattamente cosa questo significa e cosa non significa.
Questa è una ricerca n-day, non una divulgazione 0-day. Tutte e quattro le CVE qui menzionate erano già state divulgate pubblicamente e corrette da GIGABYTE (il firmware corretto ha iniziato a essere distribuito il 2025-06-12), con CVE assegnate e documentate da Binarly e CERT/CC prima dell'inizio di questa ricerca. Nulla in questo repository è una nuova scoperta di vulnerabilità — è una verifica indipendente tramite analisi statica per stabilire se le classi di bug precedentemente divulgate e corrette siano presenti in una specifica build BIOS scaricabile pubblicamente.
uefi-firmware-parser) — 356 file FFS enumerati nel volume SMM/DXE; 302 con un'immagine PE32/TE estraibile.PiSmmCore (il SMM Core di specifica PI), confermando e dando un nome al vero allocatore di pool/pagine SMM (interni di SmmAllocatePool/SmmFreePool/SmmAllocatePages/SmmFreePages) tramite le sue firme di guardia hard-coded "sphd"/"tail" — una corrispondenza esatta con l'open-source MdeModulePkg/Core/PiSmmCore/Pool.c di EDK2.GenericComponentSmmEntry: una variabile NVRAM (SetupXtuBufferAddress) viene letta tramite senza alcuna validazione e usata direttamente come puntatore di scrittura raggiungibile via SW SMI — corrisponde punto per punto alla descrizione pubblica della causa radice di Binarly.uefi_firmware (uefi-firmware-parser -e) ha decomposto ricorsivamente l'immagine BIOS: regioni Intel Flash Descriptor → firmware volume → file FFS → sezioni, decomprimendo ogni firmware volume compresso LZMA/Tiano trovato..ui (nome visualizzato del driver) e una sezione immagine .pe/.te è stato copiato come binario PE32+/TE autonomo denominato <DriverName>__<GUID8>.<pe32|te>.ida-pro-mcp / idalib) con il decompilatore Hex-Rays, un database per modulo. Solo auto-analisi + Hex-Rays — in questo ambiente non erano disponibili firme FLIRT né librerie di tipi EDK2 (segnalato come limitazione più avanti).L'immagine BIOS contiene quattro regioni Intel Flash Descriptor; solo region-bios contiene codice GIGABYTE/OEM (region-me.fd region-gbe.fd region-pdr.fd sono firmware Intel Management Engine / GbE / descriptor — componenti separati, fuori ambito, non esplorati).
All'interno di region-bios sono stati trovati ed estratti quattro firmware volume:
Tutti e quattro sono stati estratti e sottoposti a scansione dei marker (vedi CVE non confermate).
SMM/
├── README.md this file
├── CVE_ANALYSIS.md full technical deep-dive (code-level detail confidence notes)
├── flash.fd copy of the extracted 16MB BIOS image
├── regions/ raw recursive extraction (every FV/FFS/section as produced by uefi_firmware)
├── smm_modules/ PiSmmCore isolated + fully analyzed (.pe32 + Hex-Rays .i64 renames applied)
├── smm_modules_all/ all 51 `Smm*`-named drivers as standalone PE32/TE + manifest.txt
│ (4 extra ones PiSmmCpuDxeSmm SmmAccess SmmControl SmmLockBox
│ FlashSmiSmm FlashDriverSmm have auto-analyzed .i64 databases)
├── all_modules/ every extractable module from the main DXE/SMM volume (302 not just Smm*-named)
├── extra_volumes_modules/ modules from the two smaller auxiliary firmware volumes
└── f641_pei_modules/ modules from the duplicate PEI-phase volume copy
Filo conduttore comune a tutte e quattro: un handler Software SMI considera attendibile un registro o un valore proveniente dalla NVRAM come puntatore in memoria senza validare che si trovi effettivamente al di fuori della SMRAM, consentendo a un attaccante ring-0 (Amministratore/root) di trasformare un normale trigger SW SMI in una lettura/scrittura arbitraria con privilegi SMM (ring -2) — compromissione completa del firmware, bypass di Secure Boot e persistenza al di sotto del sistema operativo.
Non è una vulnerabilità — è ricerca di base che ha dato fondamento al resto del lavoro dimostrando che la toolchain (estrazione → isolamento PE → IDA/Hex-Rays → RE manuale) recupera effettivamente interni EDK2 reali e verificabili contro il codice sorgente, prima di essere puntata sui bug di sicurezza.
PiSmmCore (GUID e94f54cd-81eb-47ed-aec3-856f5dc157a9) è il SMM Core di specifica PI: è responsabile di SmmAllocatePool/SmmFreePool/SmmAllocatePages/SmmFreePages e della tabella di dispatch degli handler SMI.
Catena di chiamate (indirizzi all'interno di smm_modules/PiSmmCore.pe32.i64):
_ModuleEntryPoint (0x1184)
-> SmmCoreEntryPointHelper (0x14D4) writes the "SMST" table signature
-> SmmInternalAllocatePool_wrapper (0x95EC)
-> InternalAllocPoolByIndex_sphd_tail (0x57A8) <- the allocator
-> SmmAllocateZeroedPool (0x961C) alloc + zero wrapper
SmmFreePool_wrapper (0x9714)
-> SmmIsBufferInsideSmram (0x95A8) decides SMRAM-resident vs not
-> SmmInternalFreePool_sphd_tail (0x591C) validates sphd/tail frees
-> InternalFreePages (0x6A2C) page-granularity free + coalesce
InternalFindFreePages (0x6820) page-granularity alloc (mirror of InternalFreePages)
InternalAllocPoolByIndex_sphd_tail (0x57A8) è confermato come il vero allocatore EDK2 di MdeModulePkg/Core/PiSmmCore/Pool.c: contiene hard-coded le firme ASCII letterali "sphd" (SMM_POOL_HEAD_SIGNATURE) e "tail" (SMM_POOL_TAIL_SIGNATURE) — le stesse costanti magiche dell'implementazione open-source. Le richieste ≤ 0x800 byte passano attraverso un sub-allocatore a free-list per classi di dimensione; le richieste più grandi percorrono una free-list a pagine e avvolgono il chunk restituito con firme di guardia head/tail. La controparte sul lato free (SmmInternalFreePool_sphd_tail) valida le stesse firme prima di restituire la memoria alla free-list.
Tutte le rinomine sono incorporate in smm_modules/PiSmmCore.pe32.i64 — aprilo in IDA con Hex-Rays per ispezionarle direttamente.
Modulo: GenericComponentSmmEntry (GUID 9caa3071-3459-4c5b-bbf0-ee68fe4dd46d)
File: smm_modules_all/GenericComponentSmmEntry__9caa3071.pe32 (+ .i64 analizzato)
Ogni modulo estratto (prima i 51 con nome Smm*, poi tutti i 302 nel volume principale, poi i volumi ausiliari) è stato sottoposto a scansione byte/stringhe per SetupXtuBufferAddress — il nome esatto della variabile NVRAM citato nell'advisory di Binarly su CVE-2025-7027. Ha corrisposto come stringa UTF-16LE all'interno di GenericComponentSmmEntry (e della sua controparte DXE GenericComponentDxeEntry, che presumibilmente la imposta/espone).
1. GetXtuBufferAddress_FromNvram (0x1F270) — chiama gRT->GetVariable(L"SetupXtuBufferAddress" &Guid NULL &Size=8 &OutBuffer) (offset +72 nella tabella in stile runtime-services = GetVariable). Restituisce il valore grezzo di 8 byte memorizzato in questa variabile NVRAM — nessuna validazione di cosa sia effettivamente quel valore.
2. SUSPECTED_CVE_2025_7027_UnvalidatedXtuPtrWrite (0x18400) — chiama la funzione precedente per ottenere v3 (l'"indirizzo" proveniente dalla NVRAM) e poi esegue un ciclo (limitato da un conteggio tratto dalla propria struttura di input a1[3]) che fa:
*(WORD *)(v3 + 2 * v7 + 12) = v9; // v3 = raw NVRAM value v9 = attacker-influenced data
v3 non viene mai verificato come indirizzo reale, nei limiti e al di fuori della SMRAM prima di essere usato come destinazione di scrittura. SetupXtuBufferAddress è una normale variabile NVRAM (non bloccata SMM in questa build) — un attaccante ring-0 può impostarla con SetVariable() a qualsiasi indirizzo scelga (es. un indirizzo SMRAM o una struttura sensibile di kernel/hypervisor) prima di attivare la SMI, producendo un write-what-where controllato con privilegi SMM.
3. ComponentDispatch_KeymapOrXtu (0x18590) — la callback di dispatch: recupera un byte di tipo componente da un database interno di componenti e, se type == 1, chiama la funzione vulnerabile sopra. Il tipo 0 passa a SetupVar_SafeKeymapWrite_bounded (0x18234) che — per contrasto — fa un corretto controllo dei limiti dimensione-vs-capacità su una variabile NVRAM Setup reale. È proprio questo contrasto a far risaltare il percorso XTU come quello anomalo e non verificato.
4. sub_18698 — registra ComponentDispatch_KeymapOrXtu sul valore di dispatch 0xB2 (178 decimale) — l'esatto SwSmiInputValue 0xB2 che l'advisory di Binarly indica per questa classe di bug. Questo collega direttamente la porta di trigger della software-SMI al percorso di dispatch vulnerabile.
SetupXtuBufferAddress) — alla lettera.0xB2).RBX all'ingresso della SMI alimenti l'input di selezione del componente che raggiunge ComponentDispatch_KeymapOrXtu/a1[3] — non è stato tracciato fino alla lettura grezza del CPU save-state. Servirebbe un altro passaggio attraverso qualunque cosa esegua il dispatch sul valore registrato 0xB2 prima di chiamare la callback registrata di GenericComponentSmmEntry.Questa è una conferma tramite analisi statica che il pattern vulnerabile descritto nella CVE è presente in questa build BIOS — non un exploit funzionante o un PoC. Nessun contenuto SMRAM, layout del save-state o comportamento runtime è stato verificato.
Ogni marker citato negli advisory pubblici di Binarly per queste tre CVE — $DB$ 2DB$ SwSmi OcHeader FuncBlock CommandRcx0 ReadFlash WriteFlash EraseFlash GetFlashInfo — è stato cercato sia come sequenza di byte letterale sia (dove applicabile) come stringa UTF-16LE in:
flash.fd.all_modules/).extra_volumes_modules/).f641_pei_modules/).Nessuno di questi marker è stato trovato da nessuna parte. Solo SetupXtuBufferAddress (CVE-2025-7027) e stringhe di testo UI generiche OverClock (non correlate — etichette del menu Setup del BIOS) hanno corrisposto.
SetupXtuBufferAddress doveva apparire come stringa letterale perché è un nome reale di variabile NVRAM passato a GetVariable() — la stringa è funzionalmente necessaria. CommandRcx0 OcHeader e FuncBlock, al contrario, sembrano etichette interne di Binarly per funzioni anonime/strippate che hanno reverse-engineerato, non identificatori incorporati nel binario. La loro assenza come stringhe non prova nulla sull'esistenza o meno del codice sottostante. Le costanti magiche $DB$/2DB$ apparirebbero come corrispondenza a livello di byte se presenti (apparirebbero come operando immediato nel confronto compilato oppure no) — la loro assenza è un po' più significativa ma comunque non conclusiva (una codifica diversa dell'immediato, una variante firmware per modello o un ordine dei controlli leggermente diverso potrebbero tutti eludere una scansione di sottostringhe grezza).
FlashSmiSmm (GUID 6c289241-...)
e FlashDriverSmm (GUID 0c375a90-...) sono i candidati più forti — i
loro nomi corrispondono quasi esattamente a
ReadFlash/WriteFlash/EraseFlash/GetFlashInfo. Entrambi sono stati
estratti e auto-analizzati (database .i64 in smm_modules_all/ pronti
per Hex-Rays) ma non tracciati manualmente — si tratta di 174 e 243
funzioni rispettivamente, senza marker statici distintivi, che richiedono
lo stesso tipo di tracciamento manuale del dispatcher fatto per
CVE-2025-7027 (trovare la registrazione equivalente allo SW SMI 0xB2,
seguirla fino a un dispatch su tabella di puntatori a funzione, verificare
se il puntatore alla tabella è validato).OcHeader power/thermal). Buoni candidati:
stesso (già dimostrata fonte di un bug di
puntatore non verificato in questo stesso modulo)
— nessuno ancora
tracciato manualmente.Niente di tutto questo è stato completato in questo passaggio — è segnalato esplicitamente qui affinché il divario sia visibile, invece di lasciare intendere silenziosamente che sia "controllato e pulito".
Se possiedi questa scheda (o uno qualsiasi dei 240+ modelli GIGABYTE coperti da questo advisory): aggiorna al BIOS corrente dal sito di supporto GIGABYTE. GIGABYTE ha iniziato a distribuire il firmware corretto a partire dal 2025-06-12; la build analizzata qui (H510MKV2.F3 datata 2023-12-20) la precede di circa 18 mesi ed è coerente con una versione non corretta. Non è una raccomandazione teorica — questa ricerca ha trovato il percorso di codice vulnerabile effettivo per CVE-2025-7027 presente in questa specifica build.
.til), quindi i campi della SMM System Table (gSmst)/delle strutture private-data non hanno potuto essere mappati automaticamente da Hex-Rays; alcune interpretazioni degli offset di struttura nell'analisi si basano su tracciamento manuale piuttosto che su informazioni di tipo applicate.region-me.fd region-gbe.fd region-pdr.fd (regioni Intel ME / GbE / descriptor) non sono state esplorate — fuori ambito (componenti firmware separati, non codice SMM GIGABYTE/OEM).CVE_ANALYSIS.md per l'approfondimento tecnico completo a livello di codice che questo README riassume.| Scheda | GIGABYTE H510M K V2 (H510MKV2) |
| File BIOS | H510MKV2.F3 |
| Dimensione file | 16777216 bytes (16 MB) |
| Data file | 2023-12-20 |
| MD5 | a9bca8aeb55061824af1c3eedfb5c846 |
| SHA-256 | 934a935e5faba8d2cea4e1d51e9edb6aed86b32f412d0da5bae602bd9fd8f9f3 |
| Chipset | Intel H510 |
| Patch del vendor disponibile dal | 2025-06-12 (questa build la precede di ~18 mesi) |
GetVariable()0xB2| Volume (GUID container FFS) | Contenuti | File estratti |
|---|
file-9e21fd93-... → volume-ee4e5898-... | Volume principale dei driver DXE/SMM — tutti i driver Smm* e i driver DXE di piattaforma | 302 |
file-f641ac56-... → volume-ee4e5898-... | Copia duplicata/di fase PEI del precedente (sottoinsieme più piccolo: PiSmmCommunicationPei IT8728FSmmFeaturesPei ecc.) | 22 |
file-3417f275-... → volume-3417f275-... | Volume di early bring-up PEI/DXE (DxeIpl FspS3Notify ...) | 21 (2 con immagini) |
file-05ca020b-... → volume-05ca020b-... | Piccolo volume ausiliario senza immagini eseguibili | 2 |
| CVE | Binarly ID | CVSS | Sintesi pubblica della causa radice |
|---|
| CVE-2025-7026 | BRLY-2025-008 | 8.2 | L'handler SW SMI (SwSmiInputValue 0xB2) considera attendibile il registro RBX come puntatore non verificato all'interno di una funzione che Binarly chiama CommandRcx0; se *RBX corrisponde a '$DB$'/'2DB$' l'handler esegue una scrittura arbitraria in SMRAM. |
| CVE-2025-7027 | BRLY-2025-009 | 8.2 | Doppia dereferenziazione di puntatore: una variabile NVRAM non validata (SetupXtuBufferAddress) combinata con un puntatore derivato da RBX controllato dall'attaccante → scrittura arbitraria in SMRAM. |
| CVE-2025-7028 | BRLY-2025-010 | 8.2 | Mancanza di validazione delle strutture di puntatori a funzione (FuncBlock) derivate da RBX/RCX, raggiungibili tramite ReadFlash/WriteFlash/EraseFlash/GetFlashInfo. |
| CVE-2025-7029 | BRLY-2025-011 | 8.2 | Uso non verificato di RBX che controlla un puntatore OcHeader influenzabile dall'attaccante nella logica di configurazione power/thermal (overclock) → scrittura arbitraria in SMRAM. |
GenericComponentSmmEntryPowerMgmtSmmRealTimePowerSmmThermalFanCtrSmmPpamPlatformSmm$DB$/2DB$). Poiché SwSmiInputValue 0xB2 è condiviso almeno tra CVE-2025-7026 e CVE-2025-7027 secondo gli
advisory di Binarly, e questo dump ha dimostrato che 0xB2 è un valore
di dispatch reale e attivamente usato in GenericComponentSmmEntry, il
passo successivo è enumerare ogni driver nel volume principale che
registra una callback su 0xB2 (non solo quello già trovato) e
controllare ciascuno per un pattern di puntatore non verificato più
valore magico.