
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).
Rétro-ingénierie statique d'une image BIOS GIGABYTE H510M K V2 (H510MKV2.F3) : extraction complète des volumes de firmware UEFI, analyse de l'allocateur mémoire du noyau SMM conforme à la spécification PI et recherche ciblée des quatre vulnérabilités de corruption mémoire SMM divulguées par GIGABYTE/Binarly en 2025 (CVE-2025-7026, CVE-2025-7027, CVE-2025-7028, CVE-2025-7029).
Statut : 1 CVE sur 4 confirmée comme présente (CVE-2025-7027). Les 3 autres ont été activement recherchées dans l'ensemble du firmware accessible et n'ont pas été trouvées — voir CVE non confirmées pour comprendre précisément ce que cela signifie et ne signifie pas.
Cette recherche est de type n-day, pas une divulgation de 0-day. Les quatre CVE référencées ici ont déjà été divulguées publiquement et corrigées par GIGABYTE (les firmwares corrigés ont commencé à être distribués le 2025-06-12), ont reçu leurs identifiants CVE et ont été documentées par Binarly et le CERT/CC avant le début de cette recherche. Rien dans ce dépôt ne constitue une découverte de vulnérabilité — il s'agit d'une vérification indépendante par analyse statique de la présence ou non des classes de bugs précédemment divulguées et corrigées dans une version spécifique du BIOS téléchargeable publiquement.
uefi-firmware-parser) — 356 fichiers FFS énumérés dans le volume SMM/DXE, dont 302 avec une image PE32/TE extractible.PiSmmCore (le noyau SMM conforme à la spécification PI), confirmant et nommant le véritable allocateur de pools/pages SMM (internes de SmmAllocatePool/SmmFreePool/SmmAllocatePages/SmmFreePages) via ses signatures de garde codées en dur "sphd"/"tail" — une correspondance exacte avec le code open-source EDK2 MdeModulePkg/Core/PiSmmCore/Pool.c.GenericComponentSmmEntry : une variable NVRAM (SetupXtuBufferAddress) est récupérée via sans aucune validation et utilisée directement comme pointeur d'écriture accessible via le SMI logiciel — cela correspond point par point à la description publique de la cause racine de Binarly.uefi_firmware (uefi-firmware-parser -e) a dépaqueté récursivement l'image BIOS : régions du descripteur de flash Intel → volumes de firmware → fichiers FFS → sections, en décompressant chaque volume de firmware compressé LZMA/Tiano trouvé..ui (nom d'affichage du driver) et une section d'image .pe/.te a été copié sous forme de binaire PE32+/TE autonome nommé <DriverName>__<GUID8>.<pe32|te>.ida-pro-mcp / idalib) avec le décompilateur Hex-Rays, une base de données par module. Auto-analyse + Hex-Rays uniquement — aucune signature FLIRT ni bibliothèque de types EDK2 n'était disponible dans cet environnement (mentionné comme limite ci-dessous).L'image BIOS contient quatre régions du descripteur de flash Intel ; seule region-bios contient du code GIGABYTE/OEM (region-me.fd, region-gbe.fd, region-pdr.fd sont des firmwares du moteur de gestion Intel / GbE / descripteur — des composants séparés hors périmètre, non explorés).
Quatre volumes de firmware ont été trouvés et extraits dans region-bios :
Les quatre ont été extraits et soumis au balayage de marqueurs (voir CVE non confirmées).
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
Le point commun des quatre : un gestionnaire de SMI logiciel fait confiance à un registre ou à une valeur issue de la NVRAM comme pointeur mémoire sans valider qu'il se trouve réellement en dehors de la SMRAM, permettant à un attaquant ring-0 (Administrateur/root) de transformer un déclenchement de SMI logiciel normal en lecture/écriture arbitraire privilégiée SMM (ring -2) — compromission totale du firmware, contournement du Secure Boot et persistance sous le système d'exploitation.
Ce n'est pas une vulnérabilité — c'est une recherche de fond qui a assis le reste du travail en prouvant que la chaîne d'outils (extraction → isolation des PE → IDA/Hex-Rays → rétro-ingénierie manuelle) récupère réellement des internes EDK2 authentiques vérifiables à la source, avant d'être orientée vers les bugs de sécurité.
PiSmmCore (GUID e94f54cd-81eb-47ed-aec3-856f5dc157a9) est le noyau SMM conforme à la spécification PI : il possède SmmAllocatePool/SmmFreePool/SmmAllocatePages/SmmFreePages ainsi que la table de répartition des gestionnaires SMI.
Chaîne d'appels (adresses dans 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) est confirmé comme étant le véritable allocateur EDK2 MdeModulePkg/Core/PiSmmCore/Pool.c : il code en dur les signatures ASCII littérales "sphd" (SMM_POOL_HEAD_SIGNATURE) et "tail" (SMM_POOL_TAIL_SIGNATURE) — exactement les constantes magiques de l'implémentation open-source. Les requêtes ≤ 0x800 octets passent par un sous-allocateur à liste libre par classes de taille ; les requêtes plus grandes parcourent une liste libre de pages et enveloppent le bloc retourné avec les signatures de garde tête/queue. La contrepartie côté libération (SmmInternalFreePool_sphd_tail) valide les mêmes signatures avant de rendre la mémoire à la liste libre.
Tous les renommages sont intégrés dans smm_modules/PiSmmCore.pe32.i64 — ouvrez-le dans IDA avec Hex-Rays pour l'inspecter directement.
Module : GenericComponentSmmEntry (GUID 9caa3071-3459-4c5b-bbf0-ee68fe4dd46d)
Fichier : smm_modules_all/GenericComponentSmmEntry__9caa3071.pe32 (+ .i64 analysé)
Chaque module extrait (les 51 nommés Smm*, puis les 302 du volume principal, puis les volumes auxiliaires) a été balayé au niveau octet/chaîne pour SetupXtuBufferAddress — le nom exact de la variable NVRAM cité par la publication de Binarly sur la CVE-2025-7027. La correspondance a été trouvée sous forme de chaîne UTF-16LE dans GenericComponentSmmEntry (et dans son homologue DXE GenericComponentDxeEntry, qui la définit/l'expose vraisemblablement).
1. GetXtuBufferAddress_FromNvram (0x1F270) — appelle gRT->GetVariable(L"SetupXtuBufferAddress" &Guid NULL &Size=8 &OutBuffer) (décalage +72 dans la table de style services d'exécution = GetVariable). Renvoie la valeur brute de 8 octets stockée dans cette variable NVRAM — aucune validation de ce que cette valeur représente réellement.
2. SUSPECTED_CVE_2025_7027_UnvalidatedXtuPtrWrite (0x18400) — appelle la fonction ci-dessus pour obtenir v3 (l'« adresse » issue de la NVRAM) puis boucle (bornée par un compteur tiré de sa propre structure d'entrée a1[3]) en exécutant :
*(WORD *)(v3 + 2 * v7 + 12) = v9; // v3 = raw NVRAM value v9 = attacker-influenced data
v3 n'est jamais vérifié comme étant une adresse réelle, dans les limites et hors SMRAM avant d'être utilisé comme cible d'écriture. SetupXtuBufferAddress est une variable NVRAM normale (non verrouillée SMM dans cette version) — un attaquant ring-0 peut lui appliquer SetVariable() avec n'importe quelle adresse de son choix (par exemple une adresse SMRAM ou une structure sensible du noyau/hyperviseur) avant de déclencher le SMI, produisant ainsi une écriture write-what-where contrôlée avec privilèges SMM.
3. ComponentDispatch_KeymapOrXtu (0x18590) — le callback de répartition : récupère un octet de type de composant dans une base de données interne de composants et, si type == 1, appelle la fonction vulnérable ci-dessus. Le type 0 passe par SetupVar_SafeKeymapWrite_bounded (0x18234) qui, par contraste, effectue bien une vérification appropriée des limites taille-vs-capacité sur une véritable variable NVRAM Setup. C'est ce contraste qui fait ressortir le chemin XTU comme étant le cas anormal non vérifié.
4. sub_18698 — enregistre ComponentDispatch_KeymapOrXtu pour la valeur de répartition 0xB2 (178 en décimal) — exactement le SwSmiInputValue 0xB2 que l'avis de Binarly nomme pour cette classe de bugs. Cela relie directement le port de déclenchement du SMI logiciel au chemin de répartition vulnérable.
SetupXtuBufferAddress) — textuelle.0xB2).RBX à l'entrée du SMI alimente l'entrée de sélection de composant qui atteint ComponentDispatch_KeymapOrXtu/a1[3] — n'a pas été tracé jusqu'à la lecture brute du save-state du CPU. Cela nécessiterait une passe supplémentaire à travers ce qui répartit la valeur 0xB2 enregistrée avant d'appeler le callback enregistré de GenericComponentSmmEntry.Il s'agit d'une confirmation par analyse statique que le motif vulnérable décrit dans la CVE est présent dans cette version du BIOS — pas d'un exploit fonctionnel ni d'un PoC. Aucun contenu SMRAM, aucune disposition du save-state ni aucun comportement d'exécution n'a été vérifié.
Chaque marqueur nommé dans les publications publiques de Binarly pour ces trois CVE — $DB$, 2DB$, SwSmi, OcHeader, FuncBlock, CommandRcx0, ReadFlash, WriteFlash, EraseFlash, GetFlashInfo — a été recherché à la fois comme séquence d'octets littérale et (le cas échéant) comme chaîne UTF-16LE dans :
flash.fd.all_modules/).extra_volumes_modules/).f641_pei_modules/).Aucun de ces marqueurs n'a été trouvé où que ce soit. Seuls SetupXtuBufferAddress (CVE-2025-7027) et des chaînes génériques de texte d'interface OverClock (sans rapport — des libellés de menu de configuration du BIOS) ont correspondu.
SetupXtuBufferAddress devait apparaître comme chaîne littérale car c'est un véritable nom de variable NVRAM passé à GetVariable() — la chaîne est fonctionnellement requise. CommandRcx0, OcHeader et FuncBlock, en revanche, ressemblent à des étiquettes internes propres à Binarly pour des fonctions anonymes/dépouillées qu'ils ont rétro-conçues, et non à des identifiants intégrés au binaire. Leur absence sous forme de chaînes ne prouve rien quant à l'existence du code sous-jacent. Les constantes magiques $DB$/2DB$, elles, apparaîtraient sous forme de correspondance au niveau octet si elles étaient présentes (elles apparaîtraient comme opérande immédiat dans la comparaison compilée, ou pas) — leur absence est un peu plus significative mais reste non concluante (un encodage d'immédiat différent, une variante de firmware propre à un modèle ou un ordre de vérification légèrement différent pourraient tous échapper à un balayage de sous-chaîne brut).
FlashSmiSmm (GUID 6c289241-...) et FlashDriverSmm (GUID 0c375a90-...) sont les candidats les plus solides — leurs noms correspondent presque exactement à ReadFlash/WriteFlash/EraseFlash/GetFlashInfo. Les deux ont été extraits et auto-analysés (bases de données .i64 prêtes pour Hex-Rays dans smm_modules_all/) mais pas tracés manuellement — il s'agit respectivement de 174 et 243 fonctions, sans marqueurs statiques distinctifs, ce qui exigerait le même type de traçage manuel du répartiteur que celui effectué pour la CVE-2025-7027 (trouver l'enregistrement équivalent au SMI logiciel 0xB2, le suivre jusqu'à une répartition par table de pointeurs de fonction, vérifier si le pointeur de table est validé).OcHeader électrique/thermique). Bons candidats : lui-même (déjà prouvé comme source d'un bug de pointeur non vérifié dans ce module précis), , , , — aucun n'a encore été tracé manuellement.Rien de tout cela n'a été achevé dans cette passe — c'est signalé ici explicitement pour que la lacune soit visible plutôt que de laisser entendre silencieusement que tout a été « vérifié et propre ».
Si vous possédez cette carte (ou l'un des 240+ modèles GIGABYTE couverts par cet avis) : mettez à jour vers le BIOS actuel depuis le site de support de GIGABYTE. GIGABYTE a commencé à distribuer des firmwares corrigés le 2025-06-12 ; la version analysée ici (H510MKV2.F3 datée du 2023-12-20) la précède d'environ 18 mois et est cohérente avec une version non corrigée. Ce n'est pas une recommandation théorique — cette recherche a trouvé le chemin de code vulnérable réel de la CVE-2025-7027 présent dans cette version spécifique.
.til) n'était disponible dans cet environnement d'analyse, de sorte que les champs de la table système SMM (gSmst) et des structures de données privées n'ont pas pu être automatiquement mappés par Hex-Rays ; certaines interprétations de décalages de structures dans l'analyse reposent sur un traçage manuel plutôt que sur des informations de types appliquées.region-me.fd, region-gbe.fd, region-pdr.fd (régions du moteur de gestion Intel / GbE / descripteur) n'ont pas été explorées — hors périmètre (composants de firmware séparés, pas du code SMM GIGABYTE/OEM).CVE_ANALYSIS.md pour l'analyse technique complète au niveau du code que ce README résume.| Carte | GIGABYTE H510M K V2 (H510MKV2) |
| Fichier BIOS | H510MKV2.F3 |
| Taille du fichier | 16777216 octets (16 Mo) |
| Date du fichier | 2023-12-20 |
| MD5 | a9bca8aeb55061824af1c3eedfb5c846 |
| SHA-256 | 934a935e5faba8d2cea4e1d51e9edb6aed86b32f412d0da5bae602bd9fd8f9f3 |
| Chipset | Intel H510 |
| Correctif constructeur disponible depuis | 2025-06-12 (cette version le précède d'environ 18 mois) |
GetVariable()0xB2| Volume (GUID du conteneur FFS) | Contenu | Fichiers extraits |
|---|
file-9e21fd93-... → volume-ee4e5898-... | Volume principal des drivers DXE/SMM — tous les drivers Smm*, drivers DXE de la plateforme | 302 |
file-f641ac56-... → volume-ee4e5898-... | Copie en double/phase PEI du volume ci-dessus (sous-ensemble plus petit : PiSmmCommunicationPei, IT8728FSmmFeaturesPei, etc.) | 22 |
file-3417f275-... → volume-3417f275-... | Volume d'amorçage PEI/DXE précoce (DxeIpl, FspS3Notify, ...) | 21 (2 avec images) |
file-05ca020b-... → volume-05ca020b-... | Petit volume auxiliaire, aucune image exécutable | 2 |
| CVE | Identifiant Binarly | CVSS | Résumé public de la cause racine |
|---|
| CVE-2025-7026 | BRLY-2025-008 | 8.2 | Le gestionnaire de SMI logiciel (SwSmiInputValue 0xB2) fait confiance au registre RBX comme pointeur non vérifié dans une fonction que Binarly appelle CommandRcx0 ; si *RBX correspond à '$DB$'/'2DB$', le gestionnaire effectue une écriture SMRAM arbitraire. |
| CVE-2025-7027 | BRLY-2025-009 | 8.2 | Double déréférencement de pointeur : une variable NVRAM non validée (SetupXtuBufferAddress) combinée à un pointeur dérivé de RBX contrôlé par l'attaquant → écriture SMRAM arbitraire. |
| CVE-2025-7028 | BRLY-2025-010 | 8.2 | Absence de validation des structures de pointeurs de fonction (FuncBlock) dérivées de RBX/RCX, accessibles via ReadFlash/WriteFlash/EraseFlash/GetFlashInfo. |
| CVE-2025-7029 | BRLY-2025-011 | 8.2 | Utilisation non vérifiée de RBX contrôlant un pointeur OcHeader influencé par l'attaquant dans la logique de configuration électrique/thermique (overclocking) → écriture SMRAM arbitraire. |
GenericComponentSmmEntryPowerMgmtSmmRealTimePowerSmmThermalFanCtrSmmPpamPlatformSmm$DB$/2DB$). Comme SwSmiInputValue 0xB2 est partagé entre au moins les CVE-2025-7026 et CVE-2025-7027 selon les publications de Binarly, et que ce dump a prouvé que 0xB2 est une valeur de répartition réelle et activement utilisée dans GenericComponentSmmEntry, la prochaine étape consiste à énumérer chaque driver du volume principal qui enregistre un callback sur 0xB2 (pas seulement celui déjà trouvé) et à vérifier pour chacun un motif de pointeur non vérifié plus valeur magique.