
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).
Ingeniería inversa estática de una imagen de BIOS GIGABYTE H510M K V2 (H510MKV2.F3): extracción completa de volúmenes de firmware UEFI, análisis del asignador de memoria del núcleo SMM de la especificación PI y una búsqueda dirigida de las cuatro vulnerabilidades de corrupción de memoria SMM que GIGABYTE/Binarly divulgaron en 2025 (CVE-2025-7026, CVE-2025-7027, CVE-2025-7028, CVE-2025-7029).
Estado: 1 de 4 CVE confirmados como presentes (CVE-2025-7027). Los otros 3 se buscaron activamente en todo el firmware accesible y no se encontraron; consulte CVE no confirmados para saber exactamente qué significa y qué no significa esto.
Esta es una investigación de n-day, no una divulgación de 0-day. Los cuatro CVE referenciados aquí ya habían sido divulgados públicamente y parcheados por GIGABYTE (el firmware parcheado comenzó a distribuirse el 2025-06-12), con CVE asignados y documentados por Binarly y CERT/CC antes de que comenzara esta investigación. Nada en este repositorio es un nuevo descubrimiento de vulnerabilidades: es una verificación independiente mediante análisis estático de si las clases de errores previamente divulgadas y previamente parcheadas están presentes en una compilación de BIOS específica y descargable públicamente.
uefi-firmware-parser): 356 archivos FFS enumerados en el volumen SMM/DXE,
302 con una imagen PE32/TE extraíble.PiSmmCore (el núcleo SMM de la especificación PI),
confirmando y nombrando el verdadero asignador de pool/páginas SMM
(la implementación interna de SmmAllocatePool/SmmFreePool/SmmAllocatePages/SmmFreePages)
mediante sus firmas de guarda "sphd"/"tail" codificadas de forma fija: una
coincidencia exacta con el código abierto MdeModulePkg/Core/PiSmmCore/Pool.c de EDK2.GenericComponentSmmEntry: una variable NVRAM
(SetupXtuBufferAddress) se obtiene mediante sin validación
y se usa directamente como puntero de escritura alcanzable a través de SW SMI ; esto
coincide punto por punto con la descripción pública de la causa raíz de Binarly.uefi_firmware
(uefi-firmware-parser -e) desempaquetó recursivamente la imagen de BIOS:
regiones del Intel Flash Descriptor → volúmenes de firmware → archivos FFS → secciones,
descomprimiendo todos los volúmenes de firmware comprimidos con LZMA/Tiano que encontró..ui (nombre de visualización
del driver) y una sección de imagen .pe/.te se copió como un binario
PE32+/TE independiente llamado <DriverName>__<GUID8>.<pe32|te>.ida-pro-mcp / idalib) con el descompilador
Hex-Rays, una base de datos por módulo. Solo autoanálisis + Hex-Rays; no
había firmas FLIRT ni bibliotecas de tipos EDK2 disponibles en este
entorno (se indica como limitación más abajo).La imagen de BIOS contiene cuatro regiones del Intel Flash Descriptor; solo
region-bios contiene código de GIGABYTE/OEM (region-me.fd, region-gbe.fd
y region-pdr.fd son firmware del Intel Management Engine / GbE / descriptor:
componentes separados, fuera de alcance y no explorados).
Dentro de region-bios se encontraron y extrajeron cuatro volúmenes de firmware:
Los cuatro se extrajeron y se escanearon en busca de marcadores (consulte CVE no confirmados).
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
Hilo común en los cuatro: un manejador de Software SMI confía en un registro o en un valor proveniente de NVRAM como puntero a memoria sin validar que realmente se encuentre fuera de SMRAM, lo que permite a un atacante de ring-0 (Administrador/root) convertir un disparo normal de SW SMI en una lectura/escritura arbitraria con privilegios SMM (ring -2): compromiso total del firmware, bypass de Secure Boot y persistencia por debajo del SO.
No es una vulnerabilidad: es una investigación de antecedentes que fundamentó el resto del trabajo al demostrar que la cadena de herramientas (extracción → aislamiento de PE → IDA/Hex-Rays → ingeniería inversa manual) realmente recupera internals genuinos de EDK2 verificables contra el código fuente, antes de apuntarla a errores de seguridad.
PiSmmCore (GUID e94f54cd-81eb-47ed-aec3-856f5dc157a9) es el núcleo SMM de la especificación PI:
es el responsable de SmmAllocatePool/SmmFreePool/SmmAllocatePages/SmmFreePages
y de la tabla de despacho de manejadores de SMI.
Cadena de llamadas (direcciones dentro de 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á confirmado como el asignador genuino
MdeModulePkg/Core/PiSmmCore/Pool.c de EDK2: codifica de forma fija las
firmas ASCII literales "sphd" (SMM_POOL_HEAD_SIGNATURE) y "tail"
(SMM_POOL_TAIL_SIGNATURE): las constantes mágicas exactas de la implementación
de código abierto. Las solicitudes ≤ 0x800 bytes pasan por un subasignador de lista libre
por clases de tamaño; las solicitudes más grandes recorren una lista libre de páginas y envuelven
el bloque devuelto con firmas de guarda de cabecera/cola. La contraparte del lado de liberación
(SmmInternalFreePool_sphd_tail) valida las mismas firmas antes
de devolver la memoria a la lista libre.
Todos los renombrados están incorporados en smm_modules/PiSmmCore.pe32.i64: ábralo en IDA
con Hex-Rays para inspeccionarlo directamente.
Módulo: GenericComponentSmmEntry (GUID 9caa3071-3459-4c5b-bbf0-ee68fe4dd46d)
Archivo: smm_modules_all/GenericComponentSmmEntry__9caa3071.pe32 (+ .i64 analizado)
Todos los módulos extraídos (51 con nombre Smm*, luego los 302 del volumen principal
y después los volúmenes auxiliares) se escanearon a nivel de bytes/cadenas en busca de
SetupXtuBufferAddress, el nombre exacto de la variable NVRAM que cita el informe de Binarly
sobre CVE-2025-7027. Coincidió como una cadena UTF-16LE dentro de GenericComponentSmmEntry
(y su contraparte DXE GenericComponentDxeEntry, que presuntamente la establece/expone).
1. GetXtuBufferAddress_FromNvram (0x1F270): llama a
gRT->GetVariable(L"SetupXtuBufferAddress" &Guid NULL &Size=8 &OutBuffer)
(desplazamiento +72 en la tabla de estilo runtime-services = GetVariable). Devuelve
el valor bruto de 8 bytes almacenado en esta variable NVRAM: sin validación de qué
es realmente ese valor.
2. SUSPECTED_CVE_2025_7027_UnvalidatedXtuPtrWrite (0x18400): llama a la
función anterior para obtener v3 (la "dirección" proveniente de NVRAM) y luego itera (acotado por un
conteo tomado de su propia estructura de entrada a1[3]) haciendo:
*(WORD *)(v3 + 2 * v7 + 12) = v9; // v3 = raw NVRAM value v9 = attacker-influenced data
v3 nunca se verifica que sea una dirección real, dentro de límites y fuera de SMRAM, antes de
usarse como destino de escritura. SetupXtuBufferAddress es una variable NVRAM normal
(no bloqueada por SMM en esta compilación); un atacante de ring-0 puede
hacerle SetVariable() con cualquier dirección que elija (por ejemplo, una dirección de SMRAM o una
estructura sensible del kernel/hypervisor) antes de disparar el SMI, produciendo
un write-what-where controlado con privilegios SMM.
3. ComponentDispatch_KeymapOrXtu (0x18590): el callback de despacho:
obtiene un byte de tipo de componente de una base de datos interna de componentes y, si
tipo == 1, llama a la función vulnerable anterior. El tipo 0 va a
SetupVar_SafeKeymapWrite_bounded (0x18234) que, en contraste, sí
hace una verificación adecuada de límites tamaño-vs-capacidad contra una variable Setup real de NVRAM.
Ese contraste es lo que hace que la ruta XTU destaque como la anomalía sin verificar.
4. sub_18698: registra ComponentDispatch_KeymapOrXtu contra el
valor de despacho 0xB2 (178 decimal): exactamente el SwSmiInputValue 0xB2
que el aviso de Binarly nombra para esta clase de errores. Esto vincula el puerto de disparo
del software-SMI directamente con la ruta de despacho vulnerable.
SetupXtuBufferAddress), textual.0xB2).RBX
en la entrada del SMI alimenta la entrada de selección de componente que llega a
ComponentDispatch_KeymapOrXtu/a1[3], no se rastreó hasta
la lectura bruta del save-state de la CPU. Eso requeriría una pasada más por
lo que despache sobre el valor registrado 0xB2 antes de llamar al
callback registrado de GenericComponentSmmEntry.Esta es una confirmación por análisis estático de que el patrón vulnerable descrito en el CVE está presente en esta compilación de BIOS: no un exploit o PoC funcional. No se verificaron los contenidos de SMRAM, el diseño del save-state ni el comportamiento en tiempo de ejecución.
Todos los marcadores mencionados en los informes públicos de Binarly para estos tres CVE
($DB$, 2DB$, SwSmi, OcHeader, FuncBlock, CommandRcx0, ReadFlash,
WriteFlash, EraseFlash, GetFlashInfo) se buscaron tanto como secuencia de bytes
literal como, cuando correspondía, como cadena UTF-16LE en:
flash.fd de 16 MB.all_modules/).extra_volumes_modules/).f641_pei_modules/).Ninguno de estos marcadores se encontró en ningún lugar. Solo SetupXtuBufferAddress
(CVE-2025-7027) y las cadenas genéricas de texto de UI OverClock (no relacionadas:
etiquetas de menú de configuración del BIOS) coincidieron.
SetupXtuBufferAddress tenía que aparecer como una cadena literal porque es un
nombre real de variable NVRAM que se pasa a GetVariable(): la cadena es
funcionalmente necesaria. CommandRcx0, OcHeader y FuncBlock, en
cambio, parecen ser etiquetas internas propias de Binarly para funciones anónimas/sin símbolos
a las que se les hizo ingeniería inversa, no identificadores incrustados en el binario.
Su ausencia como cadenas no prueba nada sobre si el código subyacente existe. Las constantes
mágicas $DB$/2DB$ sí aparecerían como coincidencia a nivel de byte si estuvieran presentes
(aparecerían como operando inmediato en la comparación compilada, o no); su
ausencia es algo más significativa, pero sigue sin ser concluyente (una codificación inmediata distinta,
una variante de firmware por modelo o un orden de verificación ligeramente diferente podrían evadir
un escaneo bruto de subcadenas).
FlashSmiSmm (GUID 6c289241-...)
y FlashDriverSmm (GUID 0c375a90-...) son los candidatos más fuertes:
sus nombres se alinean casi exactamente con ReadFlash/WriteFlash/EraseFlash/GetFlashInfo.
Ambos se extrajeron y autoanalizaron (bases de datos .i64 en
smm_modules_all/, listas para Hex-Rays), pero no se rastrearon manualmente: son
174 y 243 funciones respectivamente, sin marcadores estáticos distintivos,
lo que requiere el mismo tipo de rastreo manual del despachador que se hizo para
CVE-2025-7027 (encontrar el registro equivalente a SW SMI 0xB2, seguirlo
hasta un despacho de tabla de punteros a función y comprobar si el puntero de la tabla está validado).OcHeader de energía/térmica). Buenos candidatos:
el propio (ya demostrado como fuente de un
error de puntero sin verificar en este mismo módulo), ,
, , : ninguno rastreado
manualmente todavía.Nada de esto se completó en esta pasada; se señala aquí explícitamente para que la brecha sea visible en lugar de implicar silenciosamente que está "verificado y limpio".
Si es propietario de esta placa (o de cualquiera de los más de 240 modelos de GIGABYTE cubiertos por
este aviso): actualice al BIOS actual desde el sitio de soporte de GIGABYTE.
GIGABYTE comenzó a distribuir firmware parcheado el 2025-06-12; la compilación analizada aquí
(H510MKV2.F3, con fecha 2023-12-20) es anterior a eso en aproximadamente 18 meses y es
consistente con no estar parcheada. Esto no es una recomendación teórica:
esta investigación encontró la ruta de código vulnerable real de CVE-2025-7027
presente en esta compilación específica.
.til) EDK2/UEFI disponible en este
entorno de análisis, por lo que los campos de la tabla del sistema SMM (gSmst) y de las
estructuras de datos privadas no pudieron mapearse automáticamente con Hex-Rays; algunas
interpretaciones de desplazamientos de estructuras en el análisis se basan en rastreo manual
en lugar de información de tipos aplicada.region-me.fd, region-gbe.fd y region-pdr.fd (regiones del descriptor / Intel ME / GbE)
no se exploraron: fuera de alcance (componentes de firmware separados,
no código SMM de GIGABYTE/OEM).CVE_ANALYSIS.md para ver el análisis técnico completo
a nivel de código que este README resume.| Placa | GIGABYTE H510M K V2 (H510MKV2) |
| Archivo de BIOS | H510MKV2.F3 |
| Tamaño del archivo | 16777216 bytes (16 MB) |
| Fecha del archivo | 2023-12-20 |
| MD5 | a9bca8aeb55061824af1c3eedfb5c846 |
| SHA-256 | 934a935e5faba8d2cea4e1d51e9edb6aed86b32f412d0da5bae602bd9fd8f9f3 |
| Chipset | Intel H510 |
| Parche del proveedor disponible desde | 2025-06-12 (esta compilación es anterior por ~18 meses) |
GetVariable()0xB2| Volumen (GUID de contenedor FFS) | Contenido | Archivos extraídos |
|---|
file-9e21fd93-... → volume-ee4e5898-... | Volumen principal de drivers DXE/SMM: todos los drivers Smm*, drivers DXE de plataforma | 302 |
file-f641ac56-... → volume-ee4e5898-... | Copia duplicada/de fase PEI de lo anterior (subconjunto más pequeño: PiSmmCommunicationPei, IT8728FSmmFeaturesPei, etc.) | 22 |
file-3417f275-... → volume-3417f275-... | Volumen de puesta en marcha temprana PEI/DXE (DxeIpl, FspS3Notify, ...) | 21 (2 con imágenes) |
file-05ca020b-... → volume-05ca020b-... | Volumen auxiliar pequeño, sin imágenes ejecutables | 2 |
| CVE | ID de Binarly | CVSS | Resumen público de la causa raíz |
|---|
| CVE-2025-7026 | BRLY-2025-008 | 8.2 | El manejador de SW SMI (SwSmiInputValue 0xB2) confía en el registro RBX como un puntero sin verificar dentro de una función que Binarly llama CommandRcx0; si *RBX coincide con '$DB$'/'2DB$', el manejador realiza una escritura arbitraria en SMRAM. |
| CVE-2025-7027 | BRLY-2025-009 | 8.2 | Doble desreferencia de puntero: una variable NVRAM no validada (SetupXtuBufferAddress) combinada con un puntero derivado de RBX y controlado por el atacante → escritura arbitraria en SMRAM. |
| CVE-2025-7028 | BRLY-2025-010 | 8.2 | Falta de validación de las estructuras de punteros a función (FuncBlock) derivadas de RBX/RCX, alcanzables a través de ReadFlash/WriteFlash/EraseFlash/GetFlashInfo. |
| CVE-2025-7029 | BRLY-2025-011 | 8.2 | Uso sin verificar de RBX que controla un puntero OcHeader influenciable por el atacante en la lógica de configuración de energía/térmica (overclock) → escritura arbitraria en SMRAM. |
GenericComponentSmmEntryPowerMgmtSmmRealTimePowerSmmThermalFanCtrSmmPpamPlatformSmm$DB$/2DB$). Dado que SwSmiInputValue 0xB2 es compartido por al menos CVE-2025-7026 y CVE-2025-7027 según
los informes de Binarly, y este volcado demostró que 0xB2 es un valor de despacho real y usado
activamente en GenericComponentSmmEntry, el siguiente paso es enumerar
todos los drivers del volumen principal que registran un callback contra
0xB2 (no solo el ya encontrado) y comprobar cada uno en busca de un
patrón de puntero sin verificar más valor mágico.