• Stars
    star
    133
  • Rank 272,600 (Top 6 %)
  • Language
  • License
    MIT License
  • Created almost 4 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

The report and the exploit of CVE-2021-26943, the kernel-to-SMM local privilege escalation vulnerability in ASUS UX360CA BIOS version 303.

SmmExploit

This is a report and an exploit of CVE-2021-26943, the kernel-to-SMM local privilege escalation vulnerability in ASUS UX360CA BIOS version 303. The issue was fixed in the version 304.

Issue Description

Summary

UX360CA BIOS version 303 has 3 vulnerable modules that allow an attacker with the ring0 privilege to overwrite nearly arbitrary physical memory including SMRAM and execute arbitrary code in SMM.

Those modules can be identified as follows:

Name GUID SHA256
UsbRt 04EAAAA1-29A1-11D7-8838-00500473D4EB 8A3DEAFD0A688DD4360A65C98E434180152EB43EB2C913C663F13D5709776781
SdioSmm EA343100-1A37-4239-A3CB-B92240B935CF 4578E1E147D846BB925DF881A2A0A3C3F1E6CD2AE033A8B0F769E5EB42783A0A
NvmeSmm E5E2C9D9-5BF5-497E-8860-94F81A09ADE0 A9C762B13FC9C4156603D674C6DAEBC4369520D95ACB1D0FA976078D6F7F1003

Those modules are from AMI (BIOS vendor) and may present in other OEM's BIOS.

Vulnerabilities

The vulnerable modules and corresponding SMIs are: UsbRt (0x31), SdioSmm (0x40), and NvmeSmm (0x42). All of those SMI handlers read physical memory address 0x40E to get an address to work on and write one byte to the address in case of error, even if it is SMRAM.

For example, SdioSmm's SMI handler looks as follows:

EFI_STATUS
EFIAPI
SdioSmm_SwSmi_40h(
  EFI_HANDLE  DispatchHandle,
  CONST VOID  *Context,
  VOID        *CommBuffer,
  UINTN       *CommBufferSize
  )
{
  // ...
  struct_v0 *userControlled = *(0x10 * MEMORY[0x40E] + 0x104);
  if ( EFI_ERROR(ValidateBufferIsOutsideSmram(userControlled, sizeof(struct_v0)))
    || userControlled->Offset0_FunctionCode >= 4 )
  {
    userControlled->Offset2 = 7;
  }
  else
  {
    // ...
  }
  return EFI_SUCCESS;
}

This issue appears to be identical with INTEL-SA-00057, which is greatly described as Aptiocalypsis. The BIOS version 303 for UX360CA, however, does not include fixes for them.

Exploitation

This allows an attacker with write access to physical memory and the OUT instruction (ie, the ring0 privileges) to overwrite contents of SMRAM with the following steps:

  1. Make sure physical address 0x40e is zero (which is most likely the case already)
  2. Write an address of SMRAM, say 0x88400000, at physical address 0x104
  3. Issue the SMI 0x40
  4. 0x88400000+2 is updated with 0x7.

This can be used to achieve arbitrary code execution in SMM as follows:

  1. Find the address of the System Management Service Table (SMST) in SMRAM, with the below steps:
    1. Get a physical address range for UEFI runtime code from the contents of the .Raw value in HKLM\HARDWARE\RESOURCEMAP\System Resources\Loader Reserved
    2. Find the address of SMM_CORE_PRIVATE_DATA by scanning the 'smmc' signature from the address range.
    3. SMM_CORE_PRIVATE_DATA has the pointer to the SMST at offset 30h
  2. Overwrite the pointer to the SmmLocateProtocol function at offset d0h of the SMST using the above write primitive. The value is updated to 0x07070707.
  3. Write shellcode at physical memory 0x07070707
  4. Trigger another SMI that calls the Smst->SmmLocateProtocol, such as SMI 0xdf. The shellcode at 0x07070707 is executed in SMM.

Arbitrary code execution in SMM would let an attacker bypass security measures by kernel and hypervisor such as HVCI as demonstrated in another SMM vulnerability report and establish persistence by updating contents of the SPI flash (BIOS).

Proof of Concept (PoC)

The attached demo project demonstrates successful exploitation and dumps contents of MSRs that are only accessible in SMM and the physical address of the EPTP. It also modifies Hyper-V hypervisor's CPUID VM-exit handling code to return an altered hypervisor vendor string.

The PoC is tested on Windows build 18362.1256, with and without HVCI enabled.

Recoding of successful exploitation can be found at YouTube. Demo.png

Test Instructions

  1. Open the demo.sln in Visual Studio 2019
  2. Build the solution for Debug or Release build
  3. Copy the compiled demo.sys into the target system (say, C:\users\user\desktop\demo.sys)

On the target system,

  1. Disable secure boot from BIOS, and reboot
  2. Enable the test signing mode, and reboot
    > bcdedit /set testsigning on
    
  3. Create the service to load the demo.sys
    > sc create demo type= kernel binPath= C:\users\user\desktop\demo.sys
    
  4. Start DebugView and enable "Capture Kernel" from the "Capture" menu.
  5. Start the demo
    > sc start demo
    
  6. If successful, DebugView will show values of SMM related MSRs.
    [+] ReportSmramRange: TSEG implied SMRAM: 0x88400000 - 0x88800000
    [-] ReportSmramRange: Exception occurred while accessing SMRR MSR : c0000096
    [+] FindSystemManagementServiceTable: SMM core found at 0x87f1b390 in RT Code
    [+] FindSystemManagementServiceTable: SMST found at 0x887fa710 in SMRAM
    [+] ExploitSmm: Patched SMST->SmmLocateProtocol in SMRAM
    [+] ExploitSmm: Placed SMM shell code
    [+] ExploitSmm: Triggered SMM exploit
    [+] DumpSmmExploitOuput: IA32_SMBASE             = 0x887cd000
    [+] DumpSmmExploitOuput: MSR_SMM_FEATURE_CONTROL = 0x1
    [+] DumpSmmExploitOuput: MSR_SMM_MCA_CAP         = 0xc00000000000000
    [+] DumpSmmExploitOuput: EPT pointer             = 0x10a72001e
    [+] DumpSmmExploitOuput: Patched Hv address      = 0x1004382f0
    [+] ExploitSmm: Successfully executed shell code in SMM. Failing DriverEntry to unload itself
    DriverEntry failed 0xc0000120 for driver \REGISTRY\MACHINE\SYSTEM\ControlSet001\Services\demo
    
  7. If Hyper-V is running and code modification was successful, CPUID 0x4000000 will return the modified hypervisor vendor string Hv Tampered!.
    > CheckHvVendor.exe
    Executing CPUID(0x40000000) on CPU 0
    Result: Hv Tampered!
    Executing CPUID(0x40000000) on CPU 1
    Result: Hv Tampered!
    Executing CPUID(0x40000000) on CPU 2
    Result: Hv Tampered!
    Executing CPUID(0x40000000) on CPU 3
    Result: Hv Tampered!
    

Resolution

The fix is to avoid using the user-controlled contents at all when it points inside SMRAM, as shown below.

{
  // ...
  struct_v0 *userControlled = *(0x10 * MEMORY[0x40E] + 0x104);
  if (!EFI_ERROR(ValidateBufferIsOutsideSmram(userControlled, sizeof(struct_v0))))
  {
    if (userControlled->Offset0_FunctionCode < 7 )
    {
      // ...
    }
    else
    {
      userControlled->Offset2 = 7;
    }
  }
  return EFI_SUCCESS;
}

Considerations

Missing protection for hypervisor

The fix perfectly follows the current industry best practice and prevents the confused deputy attack that leads to SMRAM corruption.

Notice that it does not take account of hypervisor memory regions, however. An attacker with knowledge of the physical memory address where the hypervisor is loaded or uses could still request the SMI to overwrite hypervisor code or data and achieve the hypervisor corruption.

This is a prevalent, long-existed, and even design-level issue.

Lack of defense-in-depth

The reported issues were resolved, but there were some problems in terms of exercising the defense-in-depth strategy.

For example, the SMM page table is identity-mapping with full readable, writable, and executable permissions, and the SMM_Code_Chk_En feature was unavailable. Those made exploitation trivial. I also notice SMM communication buffer is not verified with SmmIsBufferOutsideSmmValid() as found in EDK2, although I did not find an exploitable SMI.

I believe those are common issues across OEMs and many BIOS versions. I call out that if you are on old models from any OEMs, that BIOS is unlikely as secure as you might wish even with their latest BIOS versions.

Improvements

Those problems will not go away anytime very soon, but I am excited to see that the industry is working on an architectural resolution by reducing the SMM privileges. Here is some of those work and articles you can check out:

Timeline

Here is some highlights.

  • 2020-12-31 - I reported the vulnerability
  • 2021-01-05 - ASUS acknowledged the report
  • 2021-01-18 - ASUS sent me the fixed version of BIOS for testing
  • 2021-01-20 - I confirmed the fix and replied back
  • 2021-01-25 - ASUS acknowledged my reply
  • 2021-03-21 - ASUS publicized the fix, version 304
  • 2021-03-29 - ASUS issued an advisory entry for CVE-2021-26943

Finally, big thanks to the ASUS teams for keeping the communication loop close and transparent❀ The overall process was not fast but rather frustration-free.

More Repositories

1

HyperPlatform

Intel VT-x based hypervisor aiming to provide a thin VM-exit filtering platform on Windows.
C++
1,519
star
2

DdiMon

Monitoring and controlling kernel API calls with stealth hook using EPT
C++
1,146
star
3

Hypervisor-101-in-Rust

The materials of "Hypervisor 101 in Rust", a one-day long course, to quickly learn hardware-assisted virtualization technology and its application for high-performance fuzzing on Intel/AMD processors.
Rust
981
star
4

MiniVisorPkg

The research UEFI hypervisor that supports booting an operating system.
C
546
star
5

SimpleSvmHook

SimpleSvmHook is a research purpose hypervisor for Windows on AMD processors.
C++
351
star
6

SimpleSvm

A minimalistic educational hypervisor for Windows on AMD processors.
C++
317
star
7

PgResarch

PatchGuard Research
C++
288
star
8

ExploitCapcom

This is a standalone exploit for a vulnerable feature in Capcom.sys
C++
280
star
9

MemoryMon

Detecting execution of kernel memory where is not backed by any image file
C++
252
star
10

DotNetHooking

Sample use cases of the .NET native code hooking technique
C#
201
star
11

barevisor

A bare minimum hypervisor on AMD and Intel processors for learners.
Rust
189
star
12

scripts_for_RE

Python scripts for reverse engineering.
Python
178
star
13

GuardMon

Hypervisor based tool for monitoring system register accesses.
C++
140
star
14

UefiVarMonitor

The runtime DXE driver monitoring access to the UEFI variables by hooking the runtime service table.
C
136
star
15

hvext

The Windbg extension that implements commands helpful to study Hyper-V on Intel processors.
JavaScript
126
star
16

EopMon

Elevation of privilege detector based on HyperPlatform
C++
117
star
17

Sushi

a Japanese food keeps you sane
C++
117
star
18

findpg

Windbg extension to find PatchGuard pages
C++
116
star
19

UEFI-BIOS-Security

Security Camp 2021 & GCC 2022
111
star
20

WinIoCtlDecoder

IDA Plugin which decodes Windows Device I/O control code into DeviceType, FunctionCode, AccessType and MethodType.
Python
106
star
21

FU_Hypervisor

A hypervisor hiding user-mode memory using EPT
C
104
star
22

WPBT-Builder

The simple UEFI application to create a Windows Platform Binary Table (WPBT) from the UEFI shell.
C
100
star
23

HelloSmm

This is an instruction to run your own SMM code.
C
100
star
24

DebugLogger

A software driver that lets you log kernel-mode debug output into a file on Windows.
C++
97
star
25

Hello-VT-rp

A simple hypervisor demonstrating the use of the Intel VT-rp (redirect protection) technology.
Rust
91
star
26

kraft_dinner

Tool to dump UEFI runtime drivers implementing runtime services for Windows
C
90
star
27

HelloAmdHvPkg

HelloAmdHvPkg is a type-1 research hypervisor for AMD processors.
C
86
star
28

CVE-2023-36427

Report and exploit of CVE-2023-36427
C++
86
star
29

Scavenger

A minifilter driver preserves all modified and deleted files.
C
77
star
30

RemoteWriteMonitor

A tool to help malware analysts tell that the sample is injecting code into other process.
C++
74
star
31

meow

nyā
C++
70
star
32

HelloIommuPkg

The sample DXE runtime driver demonstrating how to program DMA remapping.
C
57
star
33

DumpVTable

Generates a Python script to give public interface names in an ActiveX file to an IDB file.
C++
47
star
34

DrvLoader

A command line tool to load and unload a device driver.
C++
42
star
35

CVE-2022-25949

A years-old exploit of a local EoP vulnerability in Kingsoft Antivirus KWatch Driver version 2009.3.17.77.
C++
35
star
36

cs_driver

A sample project for using Capstone from a driver in Visual Studio 2015
C
34
star
37

CVE-2024-21305

Report and exploit of CVE-2024-21305.
C++
30
star
38

CVE-2014-0816

CVE-2014-0816
C++
24
star
39

tandasat.github.io

HTML
17
star
40

hyperplatform_log_parser

User-mode program parsing logs created by HyperPlatform
C++
17
star
41

ProjectLoadTimeMonitor

The Visual Studio extension that measures load time of each project when a solution file is opened.
C#
16
star
42

recon2024_demo

Provides commands to read from and write to arbitrary kernel-mode memory for users with the Administrator privilege. HVCI compatible. No test signing mode is required.
C++
14
star
43

CheckSDL

A tool evaluates security configurations of a given PE based on SDL without source code
C++
12
star
44

ListWorkItems

Lists work items being queued currently.
C++
12
star
45

DeviceOpener

A command line tool to check if a specified device is accessible.
C++
10
star
46

List-UEFI-Configuration-Tables

List UEFI Configuration Tables
Rust
10
star
47

windbg_init

Windbg Init Script
9
star
48

ScopedResource

Scoped Resource - Generic RAII Wrapper for the Standard Library by Peter Sommerlad and Andrew L. Sandoval
C++
8
star
49

win32_debugout

Shows debug strings on DebubView from an attached process by win32_remote.exe.
C++
8
star
50

ping_vmm

A user-mode program knocking at HyperPlatform's "backdoor"
C++
7
star
51

SecRuntimeSample

A sample usege of SecRuntime.dll on Windows Phone
C++
4
star
52

blog

Ruby
4
star
53

CopyFiles

Copy files onto the IsolatedStorage so that you can download them using IsoStoreSpy.
C#
3
star
54

mylight

Using LED of Samsung Galaxy Ace S5830
Java
2
star
55

tandasat

2
star
56

shared

Manages files that are shared with multiple boxes.
Vim Script
1
star