Target: Intel S1200 Motherboard EFI Flash Image Tool: IDA Pro with efiXplorer plugin Date: 2026-03-01 Analyst: Claude (automated reverse engineering via IDA Pro MCP + idasql)
- Executive Summary
- Methodology
- Flash Image Overview
- SMM Module Inventory
- SMI Handler Discovery
- Vulnerability Analysis
- Clean Handler Analysis
- Design Concerns
- Appendix A: Protocol GUID Reference
- Appendix B: SMRAM Validation Function Analysis
This report documents a comprehensive audit of SMM (System Management Mode) SMI (System Management Interrupt) handlers in an Intel S1200 motherboard UEFI flash image. The analysis was conducted through automated reverse engineering using IDA Pro with efiXplorer plugin, leveraging both the ida-pro-mcp and idasql MCP servers for decompilation, disassembly, cross-reference analysis, and SQL-based bulk queries.
| ID | Severity | Module | Description |
|---|---|---|---|
| V1 | CRITICAL | SmiVariable (0xEF) | Embedded pointers from NVS buffer not validated against SMRAM before dereference in commands 6 and 7 |
| V2 | CRITICAL | SmiVariable (0xEF) | Password verification function sub_1F29D8 validates wrong memory region after reading from user-controlled pointer |
| V3 | MEDIUM | SmiVariable (0xEF) | Variable name pointer validated with only 2-byte check in SetVariable path; password pointer uses broken V2 path |
| V4 | LOW | SmiVariable (0xEF) | Variable name string iteration precedes (broken) SMRAM validation in GetVariable path |
The most impactful finding is the combination of V1 + V2: the SmiVariable handler (SW SMI# 0xEF) commands 6 and 7 allow an OS-level attacker to read up to 30 bytes from arbitrary physical addresses (including SMRAM) by crafting malicious pointer values in the ACPI NVS shared memory buffer. The SMRAM validation function (sub_1F3680) exists and is correctly implemented, but it is either not called for embedded pointers (V1) or called on the wrong memory region after the data has already been read (V2).
All remaining SW SMI handlers (SmmPlatform 0xF0/0xF1/0x9F, PowerMgmtSmm 0x27/0x28, TcgSmm, TrEESmm) were found to be clean - they either process only hardcoded values, operate on hardware registers directly, or read exclusively from protected UEFI variables.
- IDA Pro + efiXplorer: Binary loaded with efiXplorer plugin for automatic UEFI module identification, GUID labeling, and protocol resolution
- ida-pro-mcp (mrexodia): Used for targeted operations - function decompilation, disassembly, cross-references, global variable reads, memory reads
- idasql (allthingsida): Used for bulk analysis - SQL queries across function tables, name tables, string tables to discover SMM modules and handler patterns
- Analysis flow:
- Identified all SMM module entry points via
idasqlfunction name queries - Decompiled each entry point to find initialization functions
- Decompiled initialization functions to identify dispatch protocol usage
- Read 16-byte GUID values at protocol reference addresses to identify dispatch types
- Mapped callback functions to their dispatch types and context values (SW SMI numbers, IO ports, SX states)
- Decompiled all SW SMI handler callbacks for vulnerability analysis
- Disassembled critical validation functions where decompiler output was incorrect
- Identified all SMM module entry points via
- Callout vulnerabilities: SMI handler calling code outside SMRAM via function pointers
- TOCTOU (Time-of-check to time-of-use): Using pointers from shared memory without proper validation ordering
- Confused deputy / Arbitrary read: Reading from attacker-controlled addresses within SMRAM
- Arbitrary write: Writing to attacker-controlled addresses
- CommBuffer/NVS validation: Missing or incomplete validation of shared memory pointers
- Pointer injection: Embedded pointers within comm structures not validated against SMRAM
- Integer overflow: In size/address calculations for buffer validation
- Missing authentication: Operations without proper access control
The Intel S1200 EFI flash image contains 3 redundant copies of each firmware volume. All analysis references the primary (first) copy of each module. The image contains approximately 30 SMM driver modules loaded into SMRAM during the DXE/SMM initialization phase.
| Module | Address | Role |
|---|---|---|
| PiSmmIpl | 0x961600 |
SMM Initial Program Loader - loads SMM core |
| PiSmmCore | 0x964990 |
SMM core dispatcher - manages handler registration |
| PiSmmCpuDxeSmm | 0x96D9C0 |
CPU-specific SMM support (save state, entry point) |
| CpuIo2Smm | 0x9762F0 |
CPU I/O protocol for SMM |
| SmmLockBox | 0x97E320 |
Secure storage for sleep/resume data |
| SmmCommunicationBuffer | 0x96A280 |
SMM communication buffer management |
| PiSmmCommunicationSmm | 0x980360 |
SMM communication protocol |
The following table lists all unique SMM driver modules discovered in the flash image:
| # | Module Name | Primary Address | GUID Suffix | Registers Handlers |
|---|---|---|---|---|
| 1 | PchSmiDispatcher | 0x56D0A0 |
F3B06B78 | Yes - Root dispatcher |
| 2 | SmmPlatform | 0xA26A60 |
03475173 | Yes - SW, SX, PowerButton |
| 3 | SmiVariable | 0x1F25C0 |
1D5839DD | Yes - SW |
| 4 | PowerMgmtSmm | 0x5535D0 |
A2907927 | Yes - SW, IoTrap, SX |
| 5 | TcgSmm | 0x629430 |
B95D4333 | Yes - SW (dynamic) |
| 6 | TrEESmm | 0x622470 |
ADBBC8B6 | Yes - SW (dynamic) |
| 7 | PchInitSmm | 0x584B60 |
5B37FC53 | Yes - IoTrap, USB, SX |
| 8 | SaLateInitSmm | 0x549460 |
2633DE85 | Yes - IoTrap |
| 9 | SmmNmiButton | 0x42F610 |
A9D8513C | Yes - NMI/PowerButton |
| 10 | KbcEmulSMM | 0xA8A2A0 |
AAB28A80 | Yes - USB, Custom |
| 11 | HeciSmm | 0x590290 |
B4D62061 | Yes - Protocol-based |
| 12 | VariableSmm | 0x2B89E0 |
8CE124A5 | Yes - Root SMI |
| 13 | SmiFlashSigned | 0x3F8680 |
462AA0C9 | Yes - SmmCommunicate |
| 14 | VariableSmmRuntimeDxe | 0x1EF600 |
0BC0045A | Yes - SmmCommunicate |
| 15 | SmmFaultTolerantWriteDxe | 0x293330 |
1C4FAE01 | Yes - ProtocolNotify |
| 16 | FwBlockServiceSmm | 0x2883B0 |
1866FC64 | No - Service provider |
| 17 | PchSpiSmm | 0x5812E0 |
C553AE2C | No - SPI protocol |
| 18 | PchSmbusSmm | 0x57F2B0 |
F89F9DDD | No - SMBus protocol |
| 19 | SmmGenericIpmi | 0x1985D0 |
17716E7A | Likely - decompilation failed |
| 20 | SmmErrorLog | 0xA432D8 |
6B839725 | No - Error logging |
| 21 | PepBccdSmm | 0xA292D0 |
EC6D8D3B | No - Config reader |
| 22 | SmmAccess | 0x53B2A0 |
AFE99BFB | No - SMRAM access control |
| 23 | SmmControl | 0x5749D0 |
F8F03F1C | No - SMI generation |
| 24 | ReportStatusCodeRouterSmm | 0x18F2E0 |
413900D4 | No - Status code routing |
| 25 | StatusCodeHandlerSmm | 0x1905C0 |
395FCBD0 | No - Status code handler |
| 26 | PlatformStatusCodeHandlerSmm | 0x1D1A80 |
A6EDB8A5 | No - Platform status codes |
| 27 | SmiVariableInstallInt15Dxe | 0x2FF2E0 |
3C3A9F65 | No - DXE-side helper |
| 28 | BdatAccessHandler | 0x5502D0 |
589F5B04 | Separate analysis needed |
Protocol GUID: EFI_SMM_SW_DISPATCH2_PROTOCOL_GUID = {18A3C6DC-5EEA-48C8-A1C1-B53389F98999}
| SW SMI# | Decimal | Module | Callback Function | Registration Site | Description |
|---|---|---|---|---|---|
| 0xF0 | 240 | SmmPlatform | sub_A26BA4 |
sub_A273EC+0x226 |
Platform sleep preparation - PCI config save/restore |
| 0xF1 | 241 | SmmPlatform | sub_A26ED0 |
sub_A273EC+0x24D |
Platform wake restoration - PCI config restore |
| 0x9F | 159 | SmmPlatform | sub_A27810 |
sub_A273EC+0x276 |
Stub handler (returns 0 immediately) |
| 0xEF | 239 | SmiVariable | sub_1F2EDC |
sub_1F28E8+0xBA |
UEFI Variable access SMI - complex multi-command handler |
| 0x28 | 40 | PowerMgmtSmm | 0x553D34 (inline) |
sub_553774+0x102 |
Power management MSR read (0x1AA) |
| 0x27 | 39 | PowerMgmtSmm | sub_553BC4 |
sub_553BE0+0x15C |
Power management - MSR save/restore trigger |
| Dynamic | -1 | TcgSmm | sub_629574 |
sub_629A78+0x78 |
TCG/TPM 1.2 Physical Presence handler |
| Dynamic | -1 | TcgSmm | sub_6297FC |
sub_629A78+0xAE |
TCG/TPM 1.2 Memory Override Request Control |
| Dynamic | -1 | TrEESmm | sub_6225B4 |
sub_622AA4+0x7C |
TrEE/TPM 2.0 Physical Presence handler |
| Dynamic | -1 | TrEESmm | sub_622818 |
sub_622AA4+0xAE |
TrEE/TPM 2.0 Memory Override Request Control |
Note: "Dynamic" SW SMI numbers are allocated at runtime by the dispatch protocol (registered with value -1). The actual SW SMI# is assigned by PchSmiDispatcher and returned to the caller. TcgSmm and TrEESmm validate TPM presence via GUID-based checks before registering.
Protocol GUID: EFI_SMM_SX_DISPATCH2_PROTOCOL_GUID = {456D2859-A84B-4E47-A2EE-3276D886997D}
| SX State | Module | Callback Function | Description |
|---|---|---|---|
| S3 (Suspend-to-RAM) | PowerMgmtSmm | unk_5543C8 |
CPU power state save for S3 |
| S4 (Suspend-to-Disk) | SmmPlatform | sub_A2710C |
Platform state save for S4 |
| S5 (Soft-Off) | SmmPlatform | sub_A27148 |
Platform shutdown preparation |
Protocol GUID: EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL_GUID = {58DC368D-7BFA-4E77-ABBC-0E29418DF930}
| IO Port | Width | Module | Callback | Description |
|---|---|---|---|---|
| 0x4000 | 1 byte | PowerMgmtSmm | sub_5539BC |
ACPI power management IO trap |
| 0x4000 | 2 bytes | PowerMgmtSmm | sub_5541EC |
ACPI power management IO trap |
| 0x4000 | 2 bytes | SaLateInitSmm | sub_5495D8 |
System Agent IO trap |
| Types 3-5 | - | PchInitSmm | sub_584CD8 |
PCH IO trap handlers (loop registered) |
Protocol GUID: EFI_SMM_USB_DISPATCH2_PROTOCOL_GUID = {EB346B97-975F-4A9F-8B22-F8E92BB3D569}
| Module | Callback | Context | Description |
|---|---|---|---|
| PchInitSmm | sub_585284 |
Port 0x10061 | USB legacy keyboard/mouse SMI |
| KbcEmulSMM | off_A8C1F8 (vtable) |
- | PS/2 keyboard controller emulation via USB |
Protocol GUID (Power Button): EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL_GUID = {1B1183FA-1823-46A7-8872-9C578755409D}
| Module | Callback | Type | Description |
|---|---|---|---|
| SmmPlatform | sub_A272E8 |
PowerButtonEntry (0) | Power button press handler |
| SmmNmiButton | sub_42F824 |
NMI Dispatch | NMI button handler (path A) |
| SmmNmiButton | sub_42F8E8 |
Alt Dispatch (type 2) | NMI button handler (path B) |
Registered via gSmst->SmiHandlerRegister (no specific dispatch protocol):
| Module | Callback | Description |
|---|---|---|
| PchSmiDispatcher | sub_56DA84 |
Root hardware SMI handler - dispatches to all child protocols |
| PowerMgmtSmm | sub_554004 / sub_553FA8 |
Conditional HW SMI (CPU feature dependent) |
| VariableSmm | off_2972D8, off_2972F8 |
SMM variable service handlers |
| PchInitSmm | nullsub_93 |
Placeholder/stub handler |
| Module | Mechanism | Description |
|---|---|---|
| SmiFlashSigned | SmmCommunicate buffer | Signed BIOS flash update (buffer at 0xA00000) |
| VariableSmmRuntimeDxe | SmmCommunicate | DXE-to-SMM bridge for GetVariable/SetVariable |
| HeciSmm | Protocol install | HECI/Intel ME communication (9 protocol methods) |
| SmmFaultTolerantWriteDxe | ProtocolNotify | Fault-tolerant flash write support |
All vulnerabilities were found in the SmiVariable module (SW SMI# 0xEF, handler sub_1F2EDC at 0x1F2EDC).
The SmiVariable handler uses an ACPI NVS shared memory buffer for communication with the OS:
OS (Ring 0) SMM (Ring -2)
============ ==============
1. Write command struct to NVS buf
2. Write to IO port 0xB2 (SW SMI)
3. Read NVS address via IO ports 0x26/0x27
4. Dispatch on command byte (NVS[1])
5. Process command using NVS fields
6. Write status to NVS status field
7. Read result from NVS buf
The handler supports 10+ commands dispatched via BYTE1(NVS[0]):
| Cmd | Function | Description |
|---|---|---|
| 1 | GetVariable | Read UEFI variable |
| 2 | SetVariable | Write UEFI variable |
| 3 | SetVariable (named) | Write variable with name/GUID from NVS |
| 4 | GetHiiDB | Read HII database pointer |
| 6 | Password check (single) | Verify/set single password |
| 7 | Password check (triple) | Verify/set admin + user + new password |
| 8 | Password status | Check password authentication status |
| 9 | Setup lock | Lock setup with password verification |
| 10 | Setup unlock | Unlock setup with password verification |
Severity: CRITICAL
CWE: CWE-125 (Out-of-bounds Read), CWE-20 (Improper Input Validation)
Location: sub_1F2EDC at 0x1F301D (case 7) and 0x1F309A (case 6)
In commands 6 and 7, the handler reads 32-bit pointer values from the ACPI NVS shared memory buffer and passes them directly to the password verification function sub_1F29D8 without validating them against SMRAM ranges.
; Read three pointers from attacker-controlled NVS buffer
0x1F301D: mov r15d, [rdi+4] ; pointer from NVS+4 (attacker-controlled)
0x1F3021: mov r12d, [rdi] ; pointer from NVS+0 (attacker-controlled)
0x1F3024: mov esi, [rdi+8] ; pointer from NVS+8 (attacker-controlled)
; Validate NVS structure itself - does NOT validate embedded pointers
0x1F3027: mov edx, 0Ch
0x1F302C: mov rcx, rdi ; address = NVS buffer base
0x1F302F: call sub_1F3680 ; SmmIsBufferOutsideSmmValid(NVS, 12) - OK but insufficient
; Use UNVALIDATED pointer directly
0x1F3049: mov rcx, rsi ; rcx = pointer from NVS+8 (NOT validated!)
0x1F304C: call sub_1F29D8 ; Dereferences rcx as password string pointer
; Use second UNVALIDATED pointer
0x1F305B: mov rcx, r15 ; rcx = pointer from NVS+4 (NOT validated!)
0x1F305E: call sub_1F29D8 ; Dereferences rcx
; Use third UNVALIDATED pointer
0x1F307A: mov rcx, r12 ; rcx = pointer from NVS+0 (NOT validated!)
0x1F307D: call sub_1F29D8 ; Dereferences rcx0x1F309A: mov ebx, [rdi+4] ; size/flags from NVS+4
0x1F309D: mov esi, [rdi] ; pointer from NVS+0 (attacker-controlled)
0x1F309F: mov edx, 8
0x1F30A4: mov rcx, rdi
0x1F30A7: call sub_1F3680 ; Validates NVS structure only
0x1F30B6: mov ecx, ebx ; NVS+4 used as flags (not a pointer issue)
0x1F30B8: call sub_1F29D8
0x1F30D8: mov rcx, rsi ; UNVALIDATED pointer from NVS+0!
0x1F30DB: call sub_1F29D8 ; Dereferences rsi as password stringCases 1 and 2 correctly validate embedded pointers:
; Case 2 - CORRECT validation of embedded pointer
0x1F3114: mov ecx, [rdi+10h] ; data buffer pointer from NVS
0x1F3117: mov rdx, [rbp+var_10] ; data size from NVS
0x1F311B: call sub_1F3680 ; Validates data buffer against SMRAM - CORRECTAn OS-level attacker can:
- Set pointer fields in NVS buffer to point into SMRAM (TSEG, typically below 4GB)
- Trigger SW SMI# 0xEF with command 6 or 7
- The handler reads up to 30 bytes from each SMRAM pointer (bounded by the loop in
sub_1F29D8) - Read data is hashed and compared against stored password hashes
- The pass/fail result is written back to the NVS status field
- This creates an SMRAM content oracle exploitable through differential analysis
Severity: CRITICAL
CWE: CWE-125 (Out-of-bounds Read), CWE-367 (TOCTOU Race Condition)
Location: sub_1F29D8 at 0x1F29D8
The password verification function sub_1F29D8 contains a call to the SMRAM validation function sub_1F3680, but it:
- Reads data from the user-controlled pointer before any validation
- Validates the wrong memory region (past the end of the read data)
// sub_1F29D8 - Password verification
signed __int64 sub_1F29D8(__int16 *a1, char a2)
{
if (a1) { // a1 = attacker-controlled pointer
v7 = a1;
v8 = 0;
do {
v9 = *v7; // READ from unvalidated pointer!
v8 += 2; // Track bytes read
++v7; // Advance pointer
} while (v9 && v8 < 0x1E); // Read up to 30 bytes
// BROKEN: validates [v7, v7+v8) = [END_of_string, END+length)
// SHOULD validate [a1, a1+v8) = [START_of_string, START+length)
if (!sub_1F3680(v7, v8))
return EFI_INVALID_PARAMETER;
}
// Data already read - proceeds to hash and compare
sub_1F3498(a1, hash_buffer, &hash_len); // Hash the read data
// ... compare against stored password hashes ...
}After the read loop:
v7=a1 + N(pointer past end of string, where N = characters read)v8=2 * N(total bytes read)
The validation sub_1F3680(v7, v8) checks the region [a1+N, a1+N+2N) which is past the data that was already read. The correct call should be sub_1F3680(a1, v8) to validate the original buffer.
This bug means that even if V1 were fixed (i.e., cases 6/7 called sub_1F3680 before passing pointers to sub_1F29D8), the internal validation within sub_1F29D8 itself is broken and would not prevent SMRAM reads. The two bugs are independently exploitable but together represent a defense-in-depth failure.
Severity: MEDIUM
CWE: CWE-20 (Improper Input Validation)
Location: sub_1F2BE0 at 0x1F2BE0 (called from case 3)
Case 3 of the SmiVariable handler calls sub_1F2BE0 which handles named SetVariable operations. The function reads pointers from the NVS buffer and performs validation, but the variable name pointer check is insufficient:
// sub_1F2BE0 pseudocode
v1 = (WORD *)*(uint32 *)(a1 + 16); // variable name pointer from NVS
v2 = (int16 *)*(uint32 *)(a1 + 32); // password pointer from NVS
if (!sub_1F3680(a1, 36) // NVS struct: CORRECT
|| !sub_1F3680(*(uint32*)(a1+28), *(uint32*)(a1+24)) // data buffer: CORRECT
|| !sub_1F3680(*(uint32*)(a1+16) + 2, 2)) // name ptr+2: ONLY 2 BYTES!
return EFI_INVALID_PARAMETER;The third validation only checks 2 bytes starting at name_pointer+2, not the full variable name string. A name string pointing into SMRAM would only have bytes 2-3 validated, while bytes 0-1 and 4+ are read without validation.
Additionally, the password pointer v2 (from NVS+32) is passed to sub_1F29D8 which has the broken validation (V2).
- Partial SMRAM read via variable name string comparison
- Password pointer goes through broken V2 validation path
- Mitigated by the fact that the name must match a whitelist for direct SetVariable, but the comparison itself reads from the unvalidated pointer
Severity: LOW
CWE: CWE-125 (Out-of-bounds Read)
Location: sub_1F2EDC case 1 at 0x1F3176
In case 1 (GetVariable), after validating the NVS structure and data buffer, the handler iterates through the variable name string from a NVS-embedded pointer:
0x1F3176: movzx eax, word ptr [rcx] ; Read WCHAR from name pointer
0x1F3179: add rdx, 2
0x1F317D: add rcx, 2
0x1F3181: test ax, ax ; Check for null terminator
0x1F3184: jz validated
0x1F3186: mov eax, cs:dword_1F4280 ; Max length bound (256 bytes)
0x1F318C: cmp rdx, rax
0x1F318F: jb loop
0x1F3191: call sub_1F3680 ; Post-iteration validationThe name string is read character by character (up to 256 bytes) before the post-read validation. The post-read validation uses the same broken pattern as V2 (validates end of string, not start). However, case 1 does separately validate the data buffer pointer, making this a lower-severity issue than V1.
The following SW SMI handlers were audited and found to contain no vulnerabilities:
- Function: Platform sleep preparation
- Analysis: Exclusively performs PCI configuration space reads/writes (bus 0, device 31) and MMIO writes (0xE00F8094). All values are hardcoded constants or read from hardware registers. No user-controlled input is processed. Registers a protocol notify via
gSmst->SmiHandlerRegisterat the end. - Verdict: Safe - hardware-only operations with no attack surface
- Function: Platform wake restoration
- Analysis: Simple PCI config space write to restore register values saved by 0xF0 handler. 6 lines of effective code.
- Verdict: Safe - minimal code, no user input
- Function: Dead/stub handler
- Analysis: Function body is
return 0;- a registered but unused handler. - Verdict: Safe - no-op
- Function: MSR save/restore trigger
- Analysis: Calls
sub_553E68which iterates over all CPU cores usinggSmst->SmmStartupThisApto execute an MSR save function. The save function (dword_553B3C->sub_553D80) reads specific MSR values (0xCE, 0x1AA, and processor-specific MSRs) and stores them in a fixed SMRAM array. No user input. - Verdict: Safe - internal MSR operations only
- Function: MSR read
- Analysis: Inline code starting with
mov ecx, 0x1AA; rdmsr. Reads a single MSR. No user input. - Verdict: Safe - single MSR read
- Function: TCG/TPM 1.2 Physical Presence request processing
- Analysis: All input comes from UEFI variables (
PhysicalPresence,PhysicalPresenceFlags) viaSmmVariable->GetVariable. The handler validates TPM presence via a 16-byte GUID check (0x46E84F198B01E5B6/0xCC901B67531C93AB) before registration. Command validation uses explicit range checks and bitmask operations. No shared memory or CommBuffer processing. - Verdict: Safe - variable-only I/O with proper command validation
- Function: TCG MemoryOverwriteRequestControl
- Analysis: Reads/writes only the
MemoryOverwriteRequestControlUEFI variable. Simple logic: reads current value, conditionally clears bit 0, writes back. - Verdict: Safe - minimal variable-only logic
- Function: TrEE/TPM 2.0 Physical Presence request processing
- Analysis: Structurally identical to TcgSmm's Physical Presence handler but operates on
TrEEPhysicalPresenceandTrEEPhysicalPresenceFlagsvariables. Uses a different TPM 2.0 GUID check (0x408CC2C3286BF25A/0x17738B75E625B4B3). - Verdict: Safe - same pattern as TcgSmm
- Function: TrEE MemoryOverwriteRequestControl
- Analysis: Identical logic to TcgSmm MOR handler, different variable GUID.
- Verdict: Safe
These are not exploitable vulnerabilities but represent security-relevant design decisions:
Commands 6, 7, 8, 9, and 10 in SmiVariable are gated by password verification (sub_1F29D8). However:
- There is no brute-force lockout mechanism - unlimited attempts are possible
- If the "Password" UEFI variable is unset (factory default), the empty-password comparison path in
sub_1F29D8may succeed, making the vulnerable code paths reachable without any authentication - The password hash comparison uses a simple scheme (no salting visible in the code)
Both TPM handlers trust the PhysicalPresence / TrEEPhysicalPresence variables to contain the pending TPM operation. If these variables are not protected by VARIABLE_POLICY or VARIABLE_LOCK, an OS-level attacker could:
- Set a pending TPM Clear operation
- Trigger a reboot
- The firmware would execute the TPM Clear on next boot
This is a known UEFI design concern and may be mitigated by platform-specific variable locking in other modules.
The 0xF0 handler performs:
- MMIO write:
0xE00F8094 &= 0xFFFFFFD0(PCIe root complex register) - Multiple PCI config space modifications on bus 0, device 31
- Installs a protocol via
SmiHandlerRegister
If triggered at an unexpected time (outside of a genuine sleep transition), this could cause platform instability. The handler does not verify that a legitimate sleep transition is in progress.
The SmmErrorLog module contains a full Windows build path string:
c:\work7\spcsdgrnripcr\Build\GreenlowPcPkg\RELEASE_VS2013x86\X64\
GreenlowPlatPkg\Ras\Smm\SmmErrorLog\SmmErrorLog\DEBUG\AutoGen.c
This reveals:
- Internal project name: "GreenlowPcPkg" (Intel Greenlow platform)
- Build system: Visual Studio 2013 x86 cross-compiler
- Build configuration: RELEASE (though DEBUG AutoGen.c is referenced)
- Internal directory structure
| GUID | Protocol | Used By |
|---|---|---|
18A3C6DC-5EEA-48C8-A1C1-B53389F98999 |
EFI_SMM_SW_DISPATCH2_PROTOCOL | SmmPlatform, SmiVariable, PowerMgmtSmm, TcgSmm, TrEESmm |
456D2859-A84B-4E47-A2EE-3276D886997D |
EFI_SMM_SX_DISPATCH2_PROTOCOL | SmmPlatform, PowerMgmtSmm, PchInitSmm |
58DC368D-7BFA-4E77-ABBC-0E29418DF930 |
EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL | PowerMgmtSmm, SaLateInitSmm, PchInitSmm, PchSmiDispatcher |
EB346B97-975F-4A9F-8B22-F8E92BB3D569 |
EFI_SMM_USB_DISPATCH2_PROTOCOL | PchInitSmm, KbcEmulSMM, PchSmiDispatcher |
1B1183FA-1823-46A7-8872-9C578755409D |
EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL | SmmPlatform |
514D2AFD-2096-4283-9DA6-700CD27DC7A5 |
PCH-specific dispatch protocol | PchSmiDispatcher (installed), PchInitSmm (consumed) |
9E71D609-6D24-47FD-B572-6140F8D9C2A4 |
PCH-specific dispatch protocol (GPI/TCO) | PchSmiDispatcher (installed) |
D52BB2B2-F022-49EC-86D2-7A293A7A054B |
PCH-specific dispatch protocol | PchSmiDispatcher (installed) |
3E7D2B56-3F47-42AA-8F6B-22F519818DAB |
PCH-specific dispatch protocol | PchSmiDispatcher (installed) |
83339EF7-9392-4716-8D3A-D1FC67CD55DB |
PCH-specific dispatch protocol | PchSmiDispatcher (installed) |
E6A81BBF-873D-47FD-B6BE-61B3E5720993 |
PCH-specific dispatch protocol | PchSmiDispatcher (installed) |
B3C14FF3-BAE8-456C-8631-27FE0CEB340C |
PCH-specific dispatch protocol (ICHN-like) | PchSmiDispatcher (installed) |
89843C0B-5701-4FF6-A473-65759904F735 |
Unknown (SmmReadyToLock related?) | SmmPlatform |
Location: 0x1F3680 (SmiVariable module)
Prototype: bool sub_1F3680(uint64_t address, uint64_t size)
The decompiler incorrectly renders this function as return !a2 && !a1. The actual logic from disassembly:
1. Overflow check:
- If size > max_address: REJECT
- If address > max_address: REJECT
- If size > 0 AND address > (max_address - size + 1): REJECT (integer overflow protection)
2. SMRAM range check (loop over SMRAM descriptors at qword_1F4418):
For each SMRAM range [base, base+length):
- If base > address: check if base < (address + size) -> REJECT (buffer extends into SMRAM)
- If address >= base AND address < (base + length): REJECT (buffer starts in SMRAM)
3. Page-table validation (if byte_1F4284 is set):
- Iterates page table entries at qword_1F4408
- Validates buffer falls within a legitimate mapped region
- Entry size from qword_1F4430, count from qword_1F4438
4. If all checks pass: return TRUE (buffer is valid/safe)
Otherwise: return FALSE (buffer overlaps SMRAM or is invalid)
Assessment: The function itself is correctly implemented. The vulnerabilities arise from:
- Not calling it on embedded pointers (V1)
- Calling it with wrong arguments after the data is already read (V2)
- Calling it with insufficient size (V3)
End of Report