0% found this document useful (0 votes)
102 views93 pages

Insomnihack Presentation

The document discusses breaking secure boot using System Management Mode (SMM). It provides an overview of SMM, including its high privileges, System Management RAM (SMRAM), and System Management Interrupts (SMIs). It then discusses two vulnerabilities related to unvalidated nested pointers in SMM handler communication buffers that could allow exploitation of SMRAM. Finally, it describes the automated tool Brick that was used to find these and other SMM vulnerabilities by statically analyzing SMM code.

Uploaded by

Kafoor
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
102 views93 pages

Insomnihack Presentation

The document discusses breaking secure boot using System Management Mode (SMM). It provides an overview of SMM, including its high privileges, System Management RAM (SMRAM), and System Management Interrupts (SMIs). It then discusses two vulnerabilities related to unvalidated nested pointers in SMM handler communication buffers that could allow exploitation of SMRAM. Finally, it describes the automated tool Brick that was used to find these and other SMM vulnerabilities by statically analyzing SMM code.

Uploaded by

Kafoor
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 93

Breaking Secure Boot

with SMM

Assaf Carlsbad, Itai Liba

[email protected] [email protected]

@assaf_carlsbad @liba2k
1
Agenda

A whirlwind tour SMM Vulnerabilities


01 of SMM 02 And how to hunt them
automatically

SMM Exploitation Mitigations


03 CVE-2021-0157 & CVE-2021-
0158
04
01
A whirlwind tour
of SMM
SMM, SMRAM, SMIs
and other curses…
What is SMM?
● System Management Mode
● A dedicated CPU mode for
firmware handling low-level
system-wide functions
● Highly privileged

Venturing into the x86’s System Management


Mode
SMM Privileges
● Ring “-2”
○ Full access to physical memory
(subvert OS/hypervisor)

○ Reflash the BIOS (persistence)

○ Completely transparent (stealth)

● Nowadays: attempts to de-privilege


SMM

https://medium.com/swlh/negative-rings-in-
intel-architecture-the-security-threats-youve-
probably-never-heard-of-d725a4b6f831
SMRAM
● System Management RAM
● Isolated address space
● Contains:
○ SMM binaries

○ SMM stack & heap

○ SMM Save State

○ CPU tables (IDT/GDT/Page Table)

https://edk2-docs.gitbook.io/a-tour-beyond-bios-memory-protection-in-uefi-bios/memory-protection-in-smm
SMRAM
● Can only be read and written from SMM
○ Chipset provides mechanism to close and lock SMRAM
○ Attempts to access SMRAM from outside of SMM will be discarded
SMIs
● System Management Interrupt
● Causes transition into SMM
○ One “master” SMI Handler

○ Firmware can register additional sub-


handlers

● In UEFI:
○ Handlers are installed by calling
SmiHandlerRegister

○ Each handler is identified by a GUID


Software SMIs
● Can be invoked by SW with ring
0 privileges
SMM_CORE_PRIVATE_DATA
○ SMM equivalent of a syscall
Comm Buffer Comm Buffer Pointer
● Caller packs a communication
buffer in normal RAM: Handler GUID
Length
○ GUID identifying the handler Data
(variable
○ Arguments for the handler length)

● Writes address of Comm Buffer


to SMM_CORE_PRIVATE_DATA
Software SMIs
● Write I/O port 0xB2 (APMC)

https://nixhacker.com/digging-into-smm/
Software SMIs

The CommBuffer and its respective size


are fetched from gSmmCorePrivate

The SMI handler with the GUID found in


the header is invoked

11
Software SMIs

Actual handler is invoked and can access


all caller-supplied arguments via the
CommBuffer parameter

12
02
SMM Vulnerabilities
And how to automatically
uncover them
Attacking SMM
● Main attack surface are software SMIs
○ Can be triggered in a controlled fashion
○ Contents of the Comm Buffer are attacker controlled

● Confused-deputy attack to:


○ Hijack SMM code flow
○ Disclosing SMRAM contents
○ Corrupting SMRAM contents
CommBuffer nested pointers

https://github.com/tianocore-
docs/Docs/raw/master/White_Papers/A_Tour_Beyond_BIOS_Secure_SMM_Communication.pdf
Unsanitized nested pointers

First byte is the OpCode field.


Valid values are { 0, 2, 3 }

default clause writes a status


variable to the memory location
pointed to by CommBuffer + 1

16
Phys Mem

Exploiting nested
pointer issues SMI SMRAM
Handler
Phys Mem

Exploiting nested
pointer issues SMI SMRAM
Handler

OpCode
Write Comm
Address Buffer
Phys Mem

Exploiting nested
pointer issues SMI SMRAM
Handler

OpCode
Comm
Address Buffer
Phys Mem

Exploiting nested
pointer issues SMI SMRAM
Handler

Handler inspects OpCode


field

OpCode
Comm
Address Buffer
Phys Mem

Exploiting nested
pointer issues SMI SMRAM
Handler

An invalid opcode
values will force the
handler to fallback
into the default case
OpCode: 4
Comm
Address Buffer
Phys Mem

Exploiting nested
pointer issues SMI SMRAM
Handler

Handler inspects
Address field to
know where to
write the status
OpCode: 4
Comm
Address Buffer
Phys Mem

Exploiting nested
pointer issues SMI SMRAM
Handler

SMRAM corruption
at attacker
controlled address
OpCode: 4
Comm
Address Buffer
Handlers should call
BOOLEAN EFIAPI


SmmIsBufferOutsideSmmValid(
IN EFI_PHYSICAL_ADDRESS Buffer,
IN UINT64 Length)
to make sure nested pointers do not
overlap with SMRAM


24
Using Brick to automatically hunt
SMM bugs
● Brick is an automated, static
analysis tool for hunting SMM
vulnerabilities

● Based on IDA

● Produced 13 CVEs so far

● https://github.com/Sentinel-One/brick
Using Brick to automatically hunt
● SMM
Brick is an automated, static bugs
analysis tool for
hunting SMM vulnerabilities

● Based on IDA

● Produced 7 CVEs so far, 6 are still going


through the disclosure pipeline

26
Interpreting Results

How did Brick get to


this conclusion?

27
Phase 0
Phase 1 - Preprocessor

Importing protocol definitions from


EDK2 and EDK2-platforms

github.com/tianocore/edk2
github.com/tianocore/edk2-platforms
UEFI Protocols
● Allow inter-module communication
● Producers publish protocols using SmmInstallProtocolInterface
● Each protocol is composed out of a:
○ GUID
○ Interface (usually a vtable)
UEFI Protocols
● Consumers utilize existing protocols via SmmLocateProtocol
○ Passes the GUID of the protocol
○ Receives the associated interface pointer in response

● Afterwards, use the interface pointer to invoke functions implemented


by the protocol
Phase 1 - Preprocessor

Importing protocol definitions from


EDK2 and EDK2-platforms

github.com/tianocore/edk2
github.com/tianocore/edk2-platforms

PCH_SPI_PROTOCOL
Phase 2 - efiXplorer
● https://github.com/binarly-io/efiXplorer
Phase 2 - efiXplorer

Discovering SMI
handlers
Phase 2 - efiXplorer

Identifying SMM
services
Phase 2 - efiXplorer

Identifying UEFI GUIDs


Phase 2 - efiXplorer

Assigning types to
interface pointers
Phase 2 - efiXplorer
Identifying SMI
handlers
EFI_SMM_ACCESS2_PROTOCOL
● Controls visibility of SMRAM
● Exposes methods to Open, Close, and Lock SMRAM
GetCapabilities()
● Let’s the caller know where SMRAM is located
● Returns an array of structures of type EFI_SMRAM_DESCRIPTOR
EFI_SMRAM_DESCRIPTOR
● Each descriptor holds information
about one SMRAM region
○ Address
○ Size
○ State
○ Attributes

● Used internally by
SmmIsBufferOutsideSmmValid
to determine if the buffer is safe
Phase 3 - Postprocessor
Phase 3 - Postprocessor

Marking global
EFI_SMRAM_DESCRIPTORs
Phase 4 - REconstructing the
Comm Buffer
● https://github.com/REhints/HexRaysCodeXplorer
Phase 4 - REconstructing the
Comm Buffer
Phase 4 - REconstructing the
Comm Buffer

Found nested
pointers
Phase 4 - REconstructing the
Comm Buffer

CommBuffer fields are


passed as pointers
Phase 5 - Resolving
SmmIsBufferOutsideSmmValid
Phase 5 - Resolving
SmmIsBufferOutsideSmmValid

References
EFI_SMRAM_DESCRIPTOR
Phase 5 - Resolving
SmmIsBufferOutsideSmmValid

Receives two integer


arguments
Phase 5 - Resolving
SmmIsBufferOutsideSmmValid

Returns BOOLEAN
Phase 5 - Resolving
SmmIsBufferOutsideSmmValid

Match found!
Phase 6 - Checking usage

Only xref to
SmmIsBufferOutsideSmmValid
Conclusion

● Brick managed to find an SMI handler:


○ That can be invoked from a non-SMM context
○ Operates on attacker-controllable pointers nested within the
Communication Buffer
○ But does not leverage SmmIsBufferOutsideSmmValid()
to sanitize them before use

● Likely to be a vulnerability
03
Exploiting SMM
Vulnerabilties
CVE-2021-0157 & CVE-2021-
0158
Exploitation Overview

From vulnerability From write primitive to


01 to arbitrary write 02 arbitrary read primitive
primitive

Developing Breaking
03 arbitrary code 04 SecureBoot
execution
Vulnerable function
● Here we are looking at an SMI handler
of SpiSmmStub module from a Dell
UEFI BIOS.
● This SMI handler uses the
PCH_SPI_PROTOCOL to read, write
and erase the SPI flash.
● Parameters from all the operations
come from the Comm Buffer without
any validation.
● Writing directly to the flash is possible,
but we might break BootGuard.
Write primitive
● The FlashRead function is used
to read a buffer from the flash to
memory.
● We can supply any address in the
flash and a size and the data
from the flash will be written to
the Buffer pointer without
SMI Comm
validating the location. Handler Buffer
● It can be used to overwrite
SMRAM
SMRAM
Write primitive
● The FlashRead function is used
to read a buffer from the flash to
memory.
● We can supply any address in the
flash and a size and the data
from the flash will be written to
the Buffer pointer without
SMI Comm
validating the location. Handler Buffer
● It can be used to overwrite
SMRAM
SMRAM
Write primitive
We can read a block from the
flash to a buffer we have read
permission to.

SMI Flash
Handler Block

SMRAM
Write primitive
Byte value
● We can use the flash block
0x00 0x01 0x02 ......... 0xFF
to generate a dictionary
mapping byte value to
0x50 0x32 0xC1 ......... 0xB2
flash offsets.
● Now we can use the Flash Offset
dictionary to write any
value to any memory
location.
Flash Block
Read primitive - SMM_CORE_PRIVATE_DATA

● We found a way to get from write to


read primitive by registering our own
SMI handler.
● SMI handlers are kept in a global
linked list in the PiSmmCore UEFI
module.
● The PiSmmCore base address is
exposed to OS, in the same
SMM_CORE_PRIVATE_DATA
structure used for issuing the SMIs.
Read primitive - Adding an handler
● The linked list head is a
global variable
(mSmiEntryList) of
PiSmmCore with the fixed
offset from the base
address.
● We can add our own handler
by overwriting the pointer to
the first entry.
Manual creation of SMI entry
SMI_ENTRY SMI_ENTRY SMI_ENTRY

PiSmmCore.efi

mSmiEntryList
SMI_HANDLER SMI_HANDLER SMI_HANDLER

Handler(
EFI_HANDLE
DispatchHandle,
void *Context,
void *CommBuffer,
UINTN
*CommBufferSize
SMRAM )
Manual creation of SMI entry
SMI_ENTRY SMI_ENTRY SMI_ENTRY

PiSmmCore.efi

mSmiEntryList Create fake SMI_ENTRY


SMI_HANDLER SMI_HANDLER
SMI_HANDLER in normal RAM

NewHandler( Handler(
EFI_HANDLE EFI_HANDLE
DispatchHandle, DispatchHandle,
void *Context, void *Context,
void *CommBuffer, void *CommBuffer,
Normal UINTN UINTN
RAM *CommBufferSize
)SMRAM
*CommBufferSize
)
Manual creation of SMI entry
SMI_ENTRY SMI_ENTRY SMI_ENTRY

PiSmmCore.efi

mSmiEntryList Overwrite the list head


SMI_HANDLER SMI_HANDLER
SMI_HANDLER with the write primitive

NewHandler( Handler(
EFI_HANDLE EFI_HANDLE
DispatchHandle, DispatchHandle,
void *Context, void *Context,
void *CommBuffer, void *CommBuffer,
Normal UINTN UINTN
RAM *CommBufferSize
)SMRAM
*CommBufferSize
)
Read primitive - Adding an handler
● In modern systems SMM code must reside in SMRAM
due to the use of the SMM_CODE_CHECK mitigation.
That means that the handler we will add must point
to a function in SMRAM.
● We need to find a function or a ROP gadget we can
use for copying SMRAM to accessible memory.
● We are looking for a memcpy like function in
PiSmmCore that can use with our limited control
over the arguments.
Read primitive - finding a function to use
● We’ve found a function
that:
○ Only takes one
argument
○ Calls memcpy to copy
16 bytes
○ Source and destination
addresses are derived
from the argument
Read primitive - finding a function to use

SMI_ENTRY

SMI_HANDLER
Craft a structure
Extra
that will satisfy both
arguments for the SMI dispatcher
leakFunction
and this function.

Normal
SMRAM
RAM
Dumping SMRAM
● Now we can trigger the SMI repeatedly and read 16 bytes at a time.
● Every time updating the address in the struct to point to the next
16 byte chunk.
Execute primitive
● SMM code only run from SMRAM. Code segments and
non-writable and Data segments are non-executable.
● Do we need to find ROP chain to change page
permissions? No!
Execute primitive
● We can find a gadget to
disable the WP bit in
CR0.
● Then overwrite existing
SMM code with a
shellcode and jump
there.
Execute primitive - ROP
● We find ROP gadgets in the SMRAM dump we got.
● Performing the stack pivot is very complex and
documented in the GitHub repo containing the POC.
Disable Secure Boot - Why?
● Bootkits are trending now, but most of the recent
publications target old systems.
● On new systems BootGuard prevents SPI Flash
implants and Secure boot prevents unsigned “OS
loader” implants.
● Disabling Secure Boot allows installation of bootkits
to the UEFI partition and loading them before the OS
loader.
SecureBoot UEFI variables
● On this system there are two EFI variables for controlling secure boot.
○ SecureBootEnable let the user set SecureBoot On/Off in the BIOS
setup. It is not accessible during runtime.
SecureBoot UEFI variables
● SecureBootMode lets the user choose between DeployedMode and
AuditMode
○ DeployedMode enforces SecureBoot.
○ AuditMode verifies the signature but doesn’t prevent the module
from loading.
● SecureBootMode is accessible during runtime, but is write protected.
Disable Secure Boot - How?
● To bypass the SecureBootMode
write protection we can use the
SmmVariableSetVariable
function.
● The SmmVariableSetVariable
function disables the write
protection check before setting
the variable.
● Since SMM is considered
privileged, it’s allowed to change
write protected variables.
Disable Secure Boot - How?
● We can set it to AuditMode to enable loading of unsigned loaders.
● We can set it to an invalid value, that will have the added benefit of
preventing the user from changing the value in the BIOS setup back to
DeployedMode.

Demo time
Reporting the bug
● We’ve reported the bug to Dell.
● Dell informed us that the bug is in Intel’s BIOS Reference Code.
● We’ve reported the bug to Intel.
● Intel acknowledges with two CVEs: CVE-2021-0157 & CVE-2021-0158
Reporting the bug
● Intel asked for extra time before the disclosure, to allow all the vendors
time to update their BIOS.
● This bug affects many Intel products.
Exploitation tools and techniques
● Using Chipsec on Linux or Windows is great for UEFI exploration, but
when exploiting vulnerabilities it’s very limiting since you have to boot
into an OS every time.
● We can use EFI shell, it boots very quickly.
● EFI Shell supports executing a shell script at startup. This is very useful
for automation.
● However EFI Shell waits 5 second before executing the shell script.
● We’ve found it useful to recompile EFI shell with no delay.
● This allows for quicker execution of automation.
MicroPython in EFI shell
● We can use chipsec from EFI shell, but we’ve found it even quicker to
use MicroPython.
● There is a MicroPython implementation for EFI shell in the edk2-
staging repo. But it doesn't have a quick way to deal with large
memory buffers.
● We’ve added support for reading and writing using python’s bytes
data type . It can be found in my GitHub repo:
https://github.com/liba2k/edk2-
staging/tree/MicroPythonTestFramework
MicroPython code using a protocol
PeachPy - Assembly in MicroPython
● PeachPy is a small assembler for
python, that was easy enough to port
to MicroPython.
https://github.com/Maratyszcza/Peac
hPy
● Here we can see an example of
PeachPy assembling a small
shellcode.
● The shellcode variable is using the
added python bytes memory type ‘A’.
PCILeech
● While working on exploitation, before restoring
normal execution we need a way to return
information from SMM before the computer
hangs.
● We were writing information to an hardcoded
physical address and using a USB3380 board with
PCILeech from another computer to read it.
● https://github.com/ufrisk/pcileech
● https://mfactors.com/usb3380-evb-usb3380-
evaluation-board/
There are always problems
04
Mitigations
Intel Boot Guard
● Intel Boot Guard is a relatively new technology that complements
Secure Boot
● Works by moving the root of trust to the PCH
● Caused us to abandon the SPI flash implant approach
Intel Runtime BIOS Resilience
● New SMM mitigations on Intel vPro platforms:
○ The new mitigations Include CR0 lock, which would have
prevented us from writing on SMM code segment.

https://www.intel.com/content/dam/www/central-
libraries/us/en/documents/drtm-based-computing-
SMM Info Leaks
● Multiple SMRAM addresses
are exposed to the OS (ring0)
via the
SMM_CORE_PRIVATE_DATA
structure.
● While by design, they help
the exploitation of SMM
vulnerabilities.
● We think it can be avoided by
a small number of changes in
EDK2.
SMI_ENTRY Linked List verification
● In our exploit, we add an handler
by overwriting the first member
pointer in the SMI_ENTRY linked
list.
● The new SMI_ENTRY is stored in
normal RAM.
● The code assumes all entries are
in SMRAM, but does not validate
this assumption.
SMI_ENTRY Linked List verification
● To mitigate this, we
just need to make
sure all entries are in
SMRAM prior to using
them.
● Trying to push this fix
into EDK2.
Thank
you!
Any questions

You might also like