
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).
GIGABYTE H510M K V2(H510MKV2.F3) BIOS 이미지의 정적 리버스 엔지니어링: PI-spec SMM Core 메모리 할당자에 대한 전체 UEFI 펌웨어 볼륨 추출 분석과 GIGABYTE/Binarly가 2025년에 공개한 4가지 SMM 메모리 손상 취약점(CVE-2025-7026 CVE-2025-7027 CVE-2025-7028 CVE-2025-7029)에 대한 표적 탐색.
상태: 4개 CVE 중 1개(CVE-2025-7027)의 존재가 확인됨. 나머지 3개는 접근 가능한 전체 펌웨어를 적극적으로 검색했지만 발견되지 않았음 — 그 의미와 한계에 대한 정확한 설명은 미확인 CVE를 참조하세요.
이 문서는 n-day 연구이지 0-day 공개가 아닙니다. 여기서 언급된 4개 CVE는 모두 이 연구가 시작되기 이전에 이미 GIGABYTE에 의해 공개적으로 공개·패치되었고(패치 펌웨어는 2025-06-12부터 배포 시작), Binarly와 CERT/CC가 CVE를 지정하고 문서화한 것들입니다. 이 저장소의 어떤 내용도 새로운 취약점 발견이 아닙니다 — 이는 이전에 공개되고 이전에 패치된 버그 클래스가 특정 공개 다운로드 가능 BIOS 빌드에 존재하는지 여부를 확인하는 독립적인 정적 분석 검증입니다.
uefi-firmware-parser) — SMM/DXE 볼륨에서 356개의 FFS 파일을 열거했으며, 그중 302개는 추출 가능한 PE32/TE 이미지를 갖고 있었습니다.PiSmmCore(PI-spec SMM Core)를 분리하여 완전히 리버스 엔지니어링했으며, 하드코딩된 "sphd"/"tail" 가드 시그니처를 통해 실제 SMM 풀/페이지 할당자(SmmAllocatePool/SmmFreePool/SmmAllocatePages/SmmFreePages 내부)를 확인하고 이름을 명명했습니다 — EDK2 오픈소스 MdeModulePkg/Core/PiSmmCore/Pool.c와 정확히 일치합니다.GenericComponentSmmEntry에서 정확히 일치하는 취약한 코드 경로를 발견하고 추적했습니다: NVRAM 변수(SetupXtuBufferAddress)가 검증 없이 GetVariable()로 읽혀 SW SMI 를 통해 도달 가능한 쓰기 포인터로 직접 사용됩니다 — 이는 Binarly의 공개 근본 원인 설명과 하나하나 일치합니다.uefi_firmware(uefi-firmware-parser -e)가 BIOS 이미지를 재귀적으로 풀었습니다: Intel Flash Descriptor 영역 → 펌웨어 볼륨 → FFS 파일 → 섹션 순서로, 발견된 모든 LZMA/Tiano 압축 펌웨어 볼륨을 해제했습니다..ui(드라이버 표시 이름) 섹션과 .pe/.te 이미지 섹션을 가진 모든 FFS 파일을 <DriverName>__<GUID8>.<pe32|te> 이름의 독립형 PE32+/TE 바이너리로 복사했습니다.ida-pro-mcp / idalib 헤드리스 워커 인터페이스 경유). 모듈당 데이터베이스 하나씩. 자동 분석 + Hex-Rays만 사용했으며, 이 환경에서는 FLIRT 시그니처나 EDK2 타입 라이브러리를 사용할 수 없었습니다(아래 한계로 기록됨).BIOS 이미지에는 4개의 Intel Flash Descriptor 영역이 포함되어 있으며, region-bios만 GIGABYTE/OEM 코드를 담고 있습니다(region-me.fd, region-gbe.fd, region-pdr.fd는 Intel Management Engine / GbE / 디스크립터 펌웨어로, 별도 구성 요소이며 범위 밖이라 탐색하지 않았습니다).
region-bios 내에서 4개의 펌웨어 볼륨이 발견되어 추출되었습니다:
4개 모두 추출하여 마커 검색을 수행했습니다(미확인 CVE 참조).
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
4개 모두의 공통점: 소프트웨어 SMI 핸들러가 레지스터 또는 NVRAM에서 비롯된 값을 메모리 포인터로 신뢰하되, 그 값이 실제로 SMRAM 외부에 있는지 검증하지 않아서 링-0(관리자/루트) 공격자가 일반적인 SW SMI 트리거를 SMM 권한(링 -2)의 임의 읽기/쓰기로 바꿀 수 있습니다 — 완전한 펌웨어 손상, Secure Boot 우회, OS 아래에서의 지속성 확보로 이어집니다.
취약점이 아니라 배경 조사입니다 — 보안 버그를 조사하기 전에 도구 체인(추출 → PE 분리 → IDA/Hex-Rays → 수동 RE)이 실제로 소스로 검증 가능한 진짜 EDK2 내부 구조를 복구할 수 있음을 입증함으로써 나머지 작업의 기반을 마련했습니다.
PiSmmCore(GUID e94f54cd-81eb-47ed-aec3-856f5dc157a9)는 PI-spec SMM Core로, SmmAllocatePool/SmmFreePool/SmmAllocatePages/SmmFreePages와 SMI 핸들러 디스패치 테이블을 소유합니다.
호출 체인(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)은 진짜 EDK2 MdeModulePkg/Core/PiSmmCore/Pool.c 할당자로 확인되었습니다: 리터럴 ASCII 시그니처 "sphd"(SMM_POOL_HEAD_SIGNATURE)와 "tail"(SMM_POOL_TAIL_SIGNATURE)을 하드코딩하고 있는데, 이는 오픈소스 구현의 정확한 매직 상수입니다. 0x800바이트 이하의 요청은 크기 클래스 자유 목록 서브할당자를 거치고, 더 큰 요청은 페이지 자유 목록을 탐색한 후 반환된 청크를 헤드/테일 가드 시그니처로 감쌉니다. 해제 측 대응 함수(SmmInternalFreePool_sphd_tail)는 메모리를 자유 목록에 반환하기 전에 동일한 시그니처를 검증합니다.
모든 이름 변경은 smm_modules/PiSmmCore.pe32.i64에 반영되어 있습니다 — IDA에서 Hex-Rays로 열어 직접 확인할 수 있습니다.
모듈: GenericComponentSmmEntry (GUID 9caa3071-3459-4c5b-bbf0-ee68fe4dd46d)
파일: smm_modules_all/GenericComponentSmmEntry__9caa3071.pe32 (+ 분석된 .i64)
추출된 모든 모듈(51개의 Smm* 이름 모듈, 그다음 메인 볼륨의 302개 전체, 그리고 보조 볼륨들)을 대상으로 Binarly의 CVE-2025-7027 분석 보고서가 인용한 정확한 NVRAM 변수 이름인 SetupXtuBufferAddress를 바이트/문자열 스캔했습니다. GenericComponentSmmEntry 내부에서 UTF-16LE 문자열로 일치했습니다(그리고 DXE 대응 모듈인 GenericComponentDxeEntry에서도 일치하는데, 아마도 이 변수를 설정/노출하는 모듈일 것입니다).
1. GetXtuBufferAddress_FromNvram (0x1F270) — gRT->GetVariable(L"SetupXtuBufferAddress" &Guid NULL &Size=8 &OutBuffer)를 호출합니다(런타임 서비스 스타일 테이블의 오프셋 +72 = GetVariable). 이 NVRAM 변수에 저장된 원시 8바이트 값을 반환합니다 — 그 값이 실제로 무엇인지에 대한 검증은 없습니다.
2. SUSPECTED_CVE_2025_7027_UnvalidatedXtuPtrWrite (0x18400) — 위 함수를 호출하여 v3(NVRAM에서 비롯된 "주소")를 얻은 다음, 자체 입력 구조체 a1[3]에서 가져온 횟수에 의해 제한된 루프를 돌며 다음을 수행합니다:
*(WORD *)(v3 + 2 * v7 + 12) = v9; // v3 = raw NVRAM value v9 = attacker-influenced data
v3는 쓰기 대상으로 사용되기 전에 실제로 경계 내에 있고 SMRAM이 아닌 주소인지 결코 검사되지 않습니다. SetupXtuBufferAddress는 일반적인(이 빌드에서는 SMM 잠금이 아닌) NVRAM 변수이므로, 링-0 공격자는 SMI를 트리거하기 전에 SetVariable()로 원하는 주소(예: SMRAM 주소 또는 민감한 커널/하이퍼바이저 구조체)를 설정할 수 있으며, 이를 통해 제어된 SMM 권한의 write-what-where가 발생합니다.
3. ComponentDispatch_KeymapOrXtu (0x18590) — 디스패치 콜백입니다: 내부 구성 요소 데이터베이스에서 구성 요소 유형 바이트를 가져와 type == 1이면 위의 취약한 함수를 호출합니다. type 0은 SetupVar_SafeKeymapWrite_bounded(0x18234)로 이동하는데, 이 함수는 대조적으로 실제 Setup NVRAM 변수에 대해 적절한 크기-대-용량 경계 검사를 수행합니다. 바로 이 대조 때문에 XTU 경로가 검증되지 않은 이상한 경로로 두드러집니다.
4. sub_18698 — ComponentDispatch_KeymapOrXtu를 디스패치 값 **0xB2(10진수 178)**에 등록합니다 — Binarly의 권고문이 이 버그 클래스에 대해 명명한 바로 그 SwSmiInputValue 0xB2입니다. 이로써 소프트웨어 SMI 트리거 포트가 취약한 디스패치 경로에 직접 연결됩니다.
SetupXtuBufferAddress) — 그대로 일치.0xB2).RBX 레지스터가 ComponentDispatch_KeymapOrXtu/a1[3]에 도달하는 구성 요소 선택 입력을 어떻게 공급하는지 — 는 원시 CPU 세이브 스테이트 읽기까지 완전히 추적되지 않았습니다. 그러려면 등록된 0xB2 값을 디스패치하는 코드를 따라 GenericComponentSmmEntry의 등록된 콜백을 호출하기 전까지 한 번 더 추적하는 작업이 필요합니다.이것은 CVE에 설명된 취약한 패턴이 이 BIOS 빌드에 존재한다는 정적 분석 확인이지, 작동하는 익스플로잇이나 PoC가 아닙니다. SMRAM 내용, 세이브 스테이트 레이아웃, 런타임 동작은 검증되지 않았습니다.
이 세 CVE에 대해 Binarly의 공개 분석 보고서에 언급된 모든 마커 — $DB$, 2DB$, SwSmi, OcHeader, FuncBlock, CommandRcx0, ReadFlash, WriteFlash, EraseFlash, GetFlashInfo — 를 리터럴 바이트 시퀀스와 (해당하는 경우) UTF-16LE 문자열로 모두 다음 대상에서 검색했습니다:
flash.fd 이미지.all_modules/).extra_volumes_modules/).f641_pei_modules/).이 마커들은 어디에서도 발견되지 않았습니다. SetupXtuBufferAddress(CVE-2025-7027)와 일반적인 OverClock UI 텍스트 문자열(무관한 BIOS 설정 메뉴 레이블)만 일치했습니다.
SetupXtuBufferAddress는 GetVariable()에 전달되는 실제 NVRAM 변수 이름이므로 리터럴 문자열로 나타나야만 했습니다 — 이 문자열은 기능상 필수입니다. 반면 CommandRcx0, OcHeader, FuncBlock은 Binarly가 리버스 엔지니어링한 익명/스트립된 함수에 대해 붙인 자체 내부 레이블처럼 보이며, 바이너리에 내장된 식별자가 아닙니다. 이것들이 문자열로 없다는 사실은 기본 코드의 존재 여부에 대해 아무것도 증명하지 못합니다. 반면 $DB$/2DB$ 매직 상수는 존재한다면 바이트 수준 일치로 나타났을 것입니다(컴파일된 비교 문자열에서 즉시 피연산자로 나타나거나 그렇지 않거나 둘 중 하나입니다). 이것들의 부재는 다소 더 의미가 있지만 여전히 결정적이지는 않습니다(다른 즉시값 인코딩, 모델별 펌웨어 변형, 또는 약간 다른 검사 순서 모두 원시 부분 문자열 스캔을 회피할 수 있습니다).
FlashSmiSmm(GUID 6c289241-...)과 FlashDriverSmm(GUID 0c375a90-...)이 가장 유력한 후보입니다 — 이름이 ReadFlash/WriteFlash/EraseFlash/GetFlashInfo와 거의 정확히 일치합니다. 둘 다 추출되어 자동 분석되었지만(smm_modules_all/의 .i64 데이터베이스, Hex-Rays 사용 준비 완료) 수동 추적은 되지 않았습니다 — 각각 174개와 243개의 함수로 구성되어 있고 구분 가능한 정적 마커가 없어서, CVE-2025-7027에 수행한 것과 같은 수동 디스패처 추적이 필요합니다(SW SMI 0xB2에 해당하는 등록을 찾아 함수 포인터 테이블 디스패치까지 추적하고, 테이블 포인터가 검증되는지 확인).OcHeader). 좋은 후보: GenericComponentSmmEntry 자체(이 모듈에서 이미 검증되지 않은 포인터 버그의 근원임이 입증됨), , , , — 아직 수동 추적되지 않았습니다.이 중 어느 것도 이번 패스에서 완료되지 않았습니다 — '확인했고 이상 없다'고 조용히 암시하기보다는 그 공백이 드러나도록 여기에 명시적으로 표시했습니다.
이 보드(또는 이 권고문이 적용되는 240개 이상의 GIGABYTE 모델 중 하나)를 소유하고 있다면: GIGABYTE 지원 사이트에서 현재 BIOS로 업데이트하세요. GIGABYTE는 2025-06-12부터 패치된 펌웨어를 배포하기 시작했습니다. 여기서 분석한 빌드(H510MKV2.F3, 2023-12-20 날짜)는 그보다 약 18개월 앞선 것으로, 패치되지 않은 상태와 일치합니다. 이는 이론적인 권장 사항이 아닙니다 — 이 연구는 CVE-2025-7027의 실제 취약한 코드 경로가 이 특정 빌드에 존재함을 발견했습니다.
.til)를 사용할 수 없어서 SMM 시스템 테이블(gSmst)/비공개 데이터 구조체 필드를 Hex-Rays가 자동 매핑하지 못했습니다. 분석의 일부 구조체 오프셋 해석은 적용된 타입 정보가 아닌 수동 추적에 기반합니다.region-me.fd, region-gbe.fd, region-pdr.fd(Intel ME / GbE / 디스크립터 영역)는 탐색하지 않았습니다 — 범위 밖입니다(GIGABYTE/OEM SMM 코드가 아닌 별도의 펌웨어 구성 요소).| 보드 | GIGABYTE H510M K V2 (H510MKV2) |
| BIOS 파일 | H510MKV2.F3 |
| 파일 크기 | 16777216바이트(16MB) |
| 파일 날짜 | 2023-12-20 |
| MD5 | a9bca8aeb55061824af1c3eedfb5c846 |
| SHA-256 | 934a935e5faba8d2cea4e1d51e9edb6aed86b32f412d0da5bae602bd9fd8f9f3 |
| 칩셋 | Intel H510 |
| 벤더 패치 사용 가능 시점 | 2025-06-12(이 빌드는 그보다 약 18개월 앞선 것입니다) |
0xB2| 볼륨(컨테이너 FFS GUID) | 내용 | 추출된 파일 수 |
|---|
file-9e21fd93-... → volume-ee4e5898-... | 메인 DXE/SMM 드라이버 볼륨 — 모든 Smm* 드라이버, 플랫폼 DXE 드라이버 | 302 |
file-f641ac56-... → volume-ee4e5898-... | 위 볼륨의 중복/PEI 단계 복사본(더 작은 하위 집합: PiSmmCommunicationPei, IT8728FSmmFeaturesPei 등) | 22 |
file-3417f275-... → volume-3417f275-... | 초기 PEI/DXE 부팅 초기화 볼륨(DxeIpl, FspS3Notify ...) | 21(이미지 포함 2개) |
file-05ca020b-... → volume-05ca020b-... | 작은 보조 볼륨, 실행 가능한 이미지 없음 | 2 |
| CVE | Binarly ID | CVSS | 공개 근본 원인 요약 |
|---|
| CVE-2025-7026 | BRLY-2025-008 | 8.2 | Binarly가 CommandRcx0라고 부르는 함수 내부에서 SW SMI 핸들러(SwSmiInputValue 0xB2)가 RBX 레지스터를 검증되지 않은 포인터로 신뢰합니다. *RBX가 '$DB$'/'2DB$'와 일치하면 핸들러는 임의 SMRAM 쓰기를 수행합니다. |
| CVE-2025-7027 | BRLY-2025-009 | 8.2 | 이중 포인터 역참조: 검증되지 않은 NVRAM 변수(SetupXtuBufferAddress)와 공격자가 제어하는 RBX 파생 포인터가 결합되어 → 임의 SMRAM 쓰기가 발생합니다. |
| CVE-2025-7028 | BRLY-2025-010 | 8.2 | RBX/RCX에서 파생된 함수 포인터 구조체(FuncBlock)에 대한 검증 부재로, ReadFlash/WriteFlash/EraseFlash/GetFlashInfo를 통해 도달 가능합니다. |
| CVE-2025-7029 | BRLY-2025-011 | 8.2 | 전원/열(오버클럭) 구성 로직에서 검증되지 않은 RBX 사용이 공격자 영향 하의 OcHeader 포인터를 제어하여 → 임의 SMRAM 쓰기가 발생합니다. |
PowerMgmtSmmRealTimePowerSmmThermalFanCtrSmmPpamPlatformSmm$DB$/2DB$ 시그니처 검사). Binarly의 보고서에 따르면 SwSmiInputValue 0xB2가 최소한 CVE-2025-7026과 CVE-2025-7027에서 공유되고, 이 덤프에서 0xB2가 GenericComponentSmmEntry의 실제 활발히 사용되는 디스패치 값임이 입증되었으므로, 다음 단계는 메인 볼륨에서 0xB2에 대해 콜백을 등록하는 모든 드라이버(이미 찾은 것 하나만이 아니라)를 열거하고 각각에 대해 검증되지 않은 포인터 + 매직 값 패턴이 있는지 확인하는 것입니다.