
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 estática de uma imagem de BIOS GIGABYTE H510M K V2 (H510MKV2.F3): extração completa e análise dos volumes de firmware UEFI, do alocador de memória do SMM Core da especificação PI, e uma busca direcionada às quatro vulnerabilidades de corrupção de memória SMM divulgadas pela GIGABYTE/Binarly em 2025 (CVE-2025-7026, CVE-2025-7027, CVE-2025-7028, CVE-2025-7029).
Estado: 1 de 4 CVEs confirmada como presente (CVE-2025-7027). As outras 3 foram ativamente procuradas em todo o firmware acessível e não foram encontradas — consulte CVEs não confirmadas para ver exatamente o que isso significa e o que não significa.
Esta é uma pesquisa n-day, não uma divulgação de 0-day. Todas as quatro CVEs referidas aqui já foram divulgadas publicamente e corrigidas pela GIGABYTE (o firmware corrigido começou a ser distribuído em 2025-06-12), com CVEs atribuídas e documentadas pela Binarly e pelo CERT/CC antes de esta pesquisa começar. Nada neste repositório é uma descoberta de vulnerabilidade nova — é uma verificação independente de análise estática para determinar se as classes de bug anteriormente divulgadas e corrigidas estão presentes numa compilação de BIOS específica e publicamente descarregável.
uefi-firmware-parser) — 356 ficheiros FFS enumerados no volume SMM/DXE, 302 com uma imagem PE32/TE extraível.PiSmmCore (o SMM Core da especificação PI), confirmando e identificando o verdadeiro alocador de pool/páginas SMM (internals de SmmAllocatePool/SmmFreePool/SmmAllocatePages/SmmFreePages) através das suas assinaturas de guarda embutidas "sphd"/"tail" — uma correspondência exata com o MdeModulePkg/Core/PiSmmCore/Pool.c open-source do EDK2.GenericComponentSmmEntry: uma variável NVRAM (SetupXtuBufferAddress) é obtida via sem validação e usada diretamente como ponteiro de escrita acessível através do SW SMI — isto corresponde ponto por ponto à descrição pública da causa raiz da Binarly.uefi_firmware (uefi-firmware-parser -e) desempacotou recursivamente a imagem de BIOS: regiões do Intel Flash Descriptor → volumes de firmware → ficheiros FFS → secções, descomprimindo todos os volumes de firmware comprimidos com LZMA/Tiano que encontrou..ui (nome de apresentação do driver) e uma secção de imagem .pe/.te foram copiados como binários PE32+/TE autónomos nomeados <DriverName>__<GUID8>.<pe32|te>.ida-pro-mcp / idalib) com o descompilador Hex-Rays, uma base de dados por módulo. Apenas auto-análise + Hex-Rays; não havia assinaturas FLIRT nem bibliotecas de tipos EDK2 disponíveis neste ambiente (assinalado como limitação abaixo).A imagem de BIOS contém quatro regiões do Intel Flash Descriptor; apenas region-bios contém código GIGABYTE/OEM (region-me.fd, region-gbe.fd, region-pdr.fd são firmware do Intel Management Engine / GbE / descritor — componentes separados, fora do âmbito, não explorados).
Dentro de region-bios foram encontrados e extraídos quatro volumes de firmware:
Os quatro foram extraídos e submetidos à pesquisa de marcadores (consulte CVEs não confirmadas).
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
Fio condutor comum às quatro: um handler de SMI por software confia num registo ou num valor vindo da NVRAM como ponteiro para memória sem validar que este se encontra realmente fora da SMRAM, permitindo que um atacante ring-0 (Administrador/root) transforme um acionamento normal de SW SMI numa leitura/escrita arbitrária com privilégios SMM (ring -2) — comprometimento total do firmware, bypass do Secure Boot e persistência abaixo do sistema operativo.
Não é uma vulnerabilidade — é pesquisa de contexto que fundamentou o resto do trabalho ao provar que a cadeia de ferramentas (extração → isolamento de PE → IDA/Hex-Rays → RE manual) recupera de facto detalhes internos genuínos do EDK2 verificáveis na fonte, antes de ser apontada a bugs de segurança.
O PiSmmCore (GUID e94f54cd-81eb-47ed-aec3-856f5dc157a9) é o SMM Core da especificação PI: é o dono de SmmAllocatePool/SmmFreePool/SmmAllocatePages/SmmFreePages e da tabela de dispatch dos handlers de SMI.
Cadeia de chamadas (endereços 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)
O InternalAllocPoolByIndex_sphd_tail (0x57A8) está confirmado como o alocador genuíno do EDK2 MdeModulePkg/Core/PiSmmCore/Pool.c: embute as assinaturas ASCII literais "sphd" (SMM_POOL_HEAD_SIGNATURE) e "tail" (SMM_POOL_TAIL_SIGNATURE) — exatamente as constantes mágicas da implementação open-source. Pedidos ≤ 0x800 bytes passam por um subalocador de lista livre por classes de tamanho; pedidos maiores percorrem uma lista livre de páginas e envolvem o bloco devolvido com assinaturas de guarda head/tail. A contraparte do lado da libertação (SmmInternalFreePool_sphd_tail) valida as mesmas assinaturas antes de devolver a memória à lista livre.
Todas as renomeações estão gravadas em smm_modules/PiSmmCore.pe32.i64 — abra-o no IDA com Hex-Rays para o inspecionar diretamente.
Módulo: GenericComponentSmmEntry (GUID 9caa3071-3459-4c5b-bbf0-ee68fe4dd46d)
Ficheiro: smm_modules_all/GenericComponentSmmEntry__9caa3071.pe32 (+ .i64 analisado)
Todos os módulos extraídos (51 com nome Smm*, depois todos os 302 do volume principal e, por fim, os volumes auxiliares) foram submetidos a uma varredura de bytes/strings à procura de SetupXtuBufferAddress — exatamente o nome da variável NVRAM citado no writeup da CVE-2025-7027 da Binarly. A correspondência apareceu como string UTF-16LE dentro de GenericComponentSmmEntry (e da sua contraparte DXE GenericComponentDxeEntry, que presumivelmente a define/expõe).
1. GetXtuBufferAddress_FromNvram (0x1F270) — chama gRT->GetVariable(L"SetupXtuBufferAddress" &Guid NULL &Size=8 &OutBuffer) (offset +72 na tabela estilo runtime-services = GetVariable). Devolve o valor bruto de 8 bytes armazenado nesta variável NVRAM — sem validação daquilo que esse valor realmente é.
2. SUSPECTED_CVE_2025_7027_UnvalidatedXtuPtrWrite (0x18400) — chama a função anterior para obter v3 (o "endereço" vindo da NVRAM) e depois itera (limitado por uma contagem obtida da sua própria estrutura de entrada a1[3]) fazendo:
*(WORD *)(v3 + 2 * v7 + 12) = v9; // v3 = raw NVRAM value v9 = attacker-influenced data
O v3 nunca é verificado como um endereço real, dentro dos limites e fora da SMRAM, antes de ser usado como alvo de escrita. SetupXtuBufferAddress é uma variável NVRAM normal (não bloqueada por SMM nesta compilação) — um atacante ring-0 pode fazer SetVariable() para qualquer endereço que escolher (por exemplo, um endereço de SMRAM ou uma estrutura sensível do kernel/hypervisor) antes de acionar o SMI, produzindo um write-what-where controlado com privilégios SMM.
3. ComponentDispatch_KeymapOrXtu (0x18590) — o callback de dispatch: obtém um byte de tipo de componente de uma base de dados interna de componentes e, se type == 1, chama a função vulnerável acima. O tipo 0 vai para SetupVar_SafeKeymapWrite_bounded (0x18234), que — por contraste — faz uma verificação adequada de limites tamanho-vs-capacidade contra uma variável NVRAM Setup real. Esse contraste é o que faz o caminho XTU destacar-se como o anómalo não validado.
4. sub_18698 — regista ComponentDispatch_KeymapOrXtu para o valor de dispatch 0xB2 (178 decimal) — exatamente o SwSmiInputValue 0xB2 que o aviso da Binarly nomeia para esta classe de bug. Isto liga diretamente a porta de acionamento do software-SMI ao caminho de dispatch vulnerável.
SetupXtuBufferAddress), palavra por palavra.0xB2).RBX na entrada do SMI alimenta a entrada de seleção de componente que chega a ComponentDispatch_KeymapOrXtu/a1[3] — não foi rastreado até à leitura bruta do CPU-save-state. Isso exigiria mais uma passagem por tudo o que faz dispatch do valor 0xB2 registado antes de chamar o callback registado do GenericComponentSmmEntry.Isto é a confirmação por análise estática de que o padrão vulnerável descrito na CVE está presente nesta compilação de BIOS — não é um exploit funcional nem um PoC. Não foram verificados conteúdos de SMRAM, layout de save-state nem comportamento em tempo de execução.
Todos os marcadores mencionados nos writeups públicos da Binarly para estas três CVEs — $DB$, 2DB$, SwSmi, OcHeader, FuncBlock, CommandRcx0, ReadFlash, WriteFlash, EraseFlash, GetFlashInfo — foram procurados tanto como sequência literal de bytes como (quando aplicável) string UTF-16LE em:
flash.fd.all_modules/).extra_volumes_modules/).f641_pei_modules/).Nenhum destes marcadores foi encontrado em lado nenhum. Apenas SetupXtuBufferAddress (CVE-2025-7027) e strings genéricas de texto de interface OverClock (rótulos de menu do BIOS Setup, sem relação) tiveram correspondência.
O SetupXtuBufferAddress tinha de aparecer como string literal porque é um nome real de variável NVRAM passado a GetVariable() — a string é funcionalmente necessária. CommandRcx0, OcHeader e FuncBlock, por contraste, parecem ser rótulos internos da própria Binarly para funções anónimas/com símbolos removidos que eles fizeram reverse-engineering — não identificadores embutidos no binário. A sua ausência como strings não prova nada sobre se o código subjacente existe. As constantes mágicas $DB$/2DB$ apareceriam como correspondência ao nível de bytes se estivessem presentes (apareceriam como um operando imediato na string de comparação compilada, ou não) — a sua ausência é um pouco mais significativa, mas ainda assim não conclusiva (uma codificação imediata diferente, uma variante de firmware por modelo ou uma ordem de verificação ligeiramente diferente poderiam todas escapar a uma varredura bruta de substrings).
FlashSmiSmm (GUID 6c289241-...) e FlashDriverSmm (GUID 0c375a90-...) são os candidatos mais fortes — os seus nomes alinham quase exatamente com ReadFlash/WriteFlash/EraseFlash/GetFlashInfo. Ambos foram extraídos e auto-analisados (bases de dados .i64 em smm_modules_all/, prontas para Hex-Rays), mas não foram rastreados manualmente — são 174 e 243 funções, respetivamente, sem marcadores estáticos distintivos, exigindo o mesmo tipo de rastreamento manual de dispatcher feito para a CVE-2025-7027 (encontrar o registo equivalente ao SW SMI 0xB2, segui-lo até a um dispatch de tabela de ponteiros de função e verificar se o ponteiro da tabela é validado).OcHeader de energia/térmica). Bons candidatos: o próprio (já provado como fonte de um bug de ponteiro não validado neste mesmo módulo), , , , — nenhum rastreado manualmente ainda.Nada disto foi concluído nesta passagem — fica assinalado aqui explicitamente para que a lacuna seja visível, em vez de ser silenciosamente subentendido que está "verificado e limpo".
Se tem esta placa (ou qualquer um dos mais de 240 modelos GIGABYTE abrangidos por este aviso): atualize para o BIOS atual a partir do site de suporte da GIGABYTE. A GIGABYTE começou a distribuir firmware corrigido em 2025-06-12; a compilação aqui analisada (H510MKV2.F3 datada de 2023-12-20) é anterior a essa data em cerca de 18 meses e é consistente com uma versão não corrigida. Isto não é uma recomendação teórica — esta pesquisa encontrou o caminho de código vulnerável real da CVE-2025-7027 presente nesta compilação específica.
.til) disponível neste ambiente de análise, pelo que os campos da SMM System Table (gSmst)/estruturas de dados privados não puderam ser mapeados automaticamente pelo Hex-Rays; algumas interpretações de offsets de estruturas na análise baseiam-se em rastreamento manual, não em informação de tipos aplicada.region-me.fd, region-gbe.fd, region-pdr.fd (regiões Intel ME / GbE / descritor) não foram exploradas — fora do âmbito (componentes de firmware separados, não código SMM GIGABYTE/OEM).CVE_ANALYSIS.md para o mergulho técnico completo ao nível do código que este README resume.| Placa | GIGABYTE H510M K V2 (H510MKV2) |
| Ficheiro de BIOS | H510MKV2.F3 |
| Tamanho do ficheiro | 16777216 bytes (16 MB) |
| Data do ficheiro | 2023-12-20 |
| MD5 | a9bca8aeb55061824af1c3eedfb5c846 |
| SHA-256 | 934a935e5faba8d2cea4e1d51e9edb6aed86b32f412d0da5bae602bd9fd8f9f3 |
| Chipset | Intel H510 |
| Patch do fornecedor disponível desde | 2025-06-12 (esta compilação é anterior a essa data em ~18 meses) |
GetVariable()0xB2| Volume (contentor GUID de FFS) | Conteúdo | Ficheiros extraídos |
|---|
file-9e21fd93-... → volume-ee4e5898-... | Volume principal de drivers DXE/SMM — todos os drivers Smm*, drivers DXE de plataforma | 302 |
file-f641ac56-... → volume-ee4e5898-... | Cópia duplicada/fase PEI do anterior (subconjunto mais pequeno: PiSmmCommunicationPei, IT8728FSmmFeaturesPei etc.) | 22 |
file-3417f275-... → volume-3417f275-... | Volume de arranque PEI/DXE inicial (DxeIpl, FspS3Notify ...) | 21 (2 com imagens) |
file-05ca020b-... → volume-05ca020b-... | Pequeno volume auxiliar sem imagens executáveis | 2 |
| CVE | ID Binarly | CVSS | Resumo público da causa raiz |
|---|
| CVE-2025-7026 | BRLY-2025-008 | 8.2 | O handler de SW SMI (SwSmiInputValue 0xB2) confia no registo RBX como ponteiro não validado dentro de uma função que a Binarly chama CommandRcx0; se *RBX corresponder a '$DB$'/'2DB$', o handler realiza uma escrita arbitrária em SMRAM. |
| CVE-2025-7027 | BRLY-2025-009 | 8.2 | Duplo desreferenciamento de ponteiro: uma variável NVRAM não validada (SetupXtuBufferAddress) combinada com um ponteiro derivado de RBX controlado pelo atacante → escrita arbitrária em SMRAM. |
| CVE-2025-7028 | BRLY-2025-010 | 8.2 | Falta de validação de estruturas de ponteiros de função (FuncBlock) derivadas de RBX/RCX, alcançáveis através de ReadFlash/WriteFlash/EraseFlash/GetFlashInfo. |
| CVE-2025-7029 | BRLY-2025-011 | 8.2 | Utilização não validada de RBX controla um ponteiro OcHeader influenciado pelo atacante na lógica de configuração de energia/térmica (overclock) → escrita arbitrária em SMRAM. |
GenericComponentSmmEntryPowerMgmtSmmRealTimePowerSmmThermalFanCtrSmmPpamPlatformSmm$DB$/2DB$). Como SwSmiInputValue 0xB2 é partilhado entre pelo menos a CVE-2025-7026 e a CVE-2025-7027, segundo os writeups da Binarly, e esta extração provou que 0xB2 é um valor de dispatch real e ativamente usado em GenericComponentSmmEntry, o próximo passo é enumerar todos os drivers do volume principal que registam um callback para 0xB2 (não apenas o que já foi encontrado) e verificar cada um quanto a um padrão de ponteiro não validado + valor mágico.