研究联想固件时遇到的一系列问题,虽然以失败告终,但也累积了不少经验。
NVRAM
- RTC lock: 0x8BD
- BIOS Lock: 0x8BE
- Debug Interface lock: 0x5B4
- Protection Range Registers (FPRR): 0xEBA (disabled 0x0)
- Intel Bios Guard Support: 0x1037
- Allow Flashing BIOS to a Previous Version: 0xF35 (yes 0x1 no 0x0)
- Secure Erase mode:0x4a6
- Force Secure Erase: 0x4a7
- One Of: Flash Support, VarStoreInfo (VarOffset/VarName): 0x12D, VarStore: 0x1, QuestionId: 0xA31, Size: 1, Min: 0x0, Max 0x3, Step: 0x0 {05 91 EA 0D E9 0D 31 0A 01 00 2D 01 10 10 00 03 00} One Of Option: Driver default, Value (8 bit): 0x0 (default) {09 07 EE 0D 10 00 00} One Of Option: Disabled, Value (8 bit): 0x2 {09 07 04 00 00 00 02} One Of Option: Enabled, Value (8 bit): 0x3 {09 07 03 00 00 00 03}
- One Of: Flash Support, VarStoreInfo (VarOffset/VarName): 0x197, VarStore: 0x1, QuestionId: 0xA58, Size: 1, Min: 0x0, Max 0x3, Step: 0x0 {05 91 EB 0D E9 0D 58 0A 01 00 97 01 10 10 00 03 00} One Of Option: Driver default, Value (8 bit): 0x0 (default) {09 07 EE 0D 10 00 00} One Of Option: Disabled, Value (8 bit): 0x2 {09 07 04 00 00 00 02} One Of Option: Enabled, Value (8 bit): 0x3 {09 07 03 00 00 00 03}
- One Of: Flash Support, VarStoreInfo (VarOffset/VarName): 0x201, VarStore: 0x1, QuestionId: 0xA7F, Size: 1, Min: 0x0, Max 0x3, Step: 0x0 {05 91 EC 0D E9 0D 7F 0A 01 00 01 02 10 10 00 03 00} One Of Option: Driver default, Value (8 bit): 0x0 (default) {09 07 EE 0D 10 00 00} One Of Option: Disabled, Value (8 bit): 0x2 {09 07 04 00 00 00 02} One Of Option: Enabled, Value (8 bit): 0x3 {09 07 03 00 00 00 03}
- One Of: Flash Support, VarStoreInfo (VarOffset/VarName): 0x26B, VarStore: 0x1, QuestionId: 0xAA6, Size: 1, Min: 0x0, Max 0x3, Step: 0x0 {05 91 ED 0D E9 0D A6 0A 01 00 6B 02 10 10 00 03 00} One Of Option: Driver default, Value (8 bit): 0x0 (default) {09 07 EE 0D 10 00 00} One Of Option: Disabled, Value (8 bit): 0x2 {09 07 04 00 00 00 02} One Of Option: Enabled, Value (8 bit): 0x3 {09 07 03 00 00 00 03} –
- SPD Write Disable: 0xeb8 (true: 0x1, false: 0x0)
- Me FW Image Re-Flash: 0x6a0(enabled: 0x1)
刷写
AFUWIN需加/capsule选项刷写,之后会进bios页面更新,但用修改后的固件则过不了ID检测
- 改写入程序,BIOS ID检测绕过
chipsec检查保护位
FLOCKDN位开启
$ chipsec_main -m common.spi_lock
[x][ =======================================================================
[x][ Module: SPI Flash Controller Configuration Locks
[x][ =======================================================================
[*] HSFS = 0x3F00E800 << Hardware Sequencing Flash Status Register (SPIBAR + 0x4)
[00] FDONE = 0 << Flash Cycle Done
[01] FCERR = 0 << Flash Cycle Error
[02] AEL = 0 << Access Error Log
[05] SCIP = 0 << SPI cycle in progress
[11] WRSDIS = 1 << Write status disable
[12] PR34LKD = 0 << PRR3 PRR4 Lock-Down
[13] FDOPSS = 1 << Flash Descriptor Override Pin-Strap Status
[14] FDV = 1 << Flash Descriptor Valid
[15] FLOCKDN = 1 << Flash Configuration Lock-Down
[16] FGO = 0 << Flash cycle go
[17] FCYCLE = 0 << Flash Cycle Type
[21] WET = 0 << Write Enable Type
[24] FDBC = 3F << Flash Data Byte Count
[31] FSMIE = 0 << Flash SPI SMI# Enable
[+] SPI write status disable set.
[+] SPI Flash Controller configuration is locked
[+] PASSED: SPI Flash Controller locked correctly.
BLE、SMM_BWP位开启,PR0、PR1寄存器开启
$ chipsec_main -m common.bios_wp
[x][ =======================================================================
[x][ Module: BIOS Region Write Protection
[x][ =======================================================================
[*] BC = 0x00000AAA << BIOS Control (b:d.f 00:31.5 + 0xDC)
[00] BIOSWE = 0 << BIOS Write Enable
[01] BLE = 1 << BIOS Lock Enable
[02] SRC = 2 << SPI Read Configuration
[04] TSS = 0 << Top Swap Status
[05] SMM_BWP = 1 << SMM BIOS Write Protection
[06] BBS = 0 << Boot BIOS Strap
[07] BILD = 1 << BIOS Interface Lock Down
[+] BIOS region write protection is enabled (writes restricted to SMM)
[*] BIOS Region: Base = 0x00200000, Limit = 0x007FFFFF
SPI Protected Ranges
------------------------------------------------------------
PRx (offset) | Value | Base | Limit | WP? | RP?
------------------------------------------------------------
PR0 (84) | 87DE0740 | 00740000 | 007DEFFF | 1 | 0
PR1 (88) | 87FF07FC | 007FC000 | 007FFFFF | 1 | 0
PR2 (8C) | 00000000 | 00000000 | 00000000 | 0 | 0
PR3 (90) | 00000000 | 00000000 | 00000000 | 0 | 0
PR4 (94) | 00000000 | 00000000 | 00000000 | 0 | 0
[!] SPI protected ranges write-protect parts of BIOS region (other parts of BIOS can be modified)
[+] PASSED: BIOS is write protected
检查s3启动表:
$ sudo python3 chipsec_main.py -m common.uefi.s3bootscript
[*] running module: chipsec.modules.common.uefi.s3bootscript
[x][ =======================================================================
[x][ Module: S3 Resume Boot-Script Protections
[x][ =======================================================================
[*] SMRAM: Base = 0x00000000CD000000, Limit = 0x00000000CD7FFFFF, Size = 0x00800000
[+] Didn't find any S3 boot-scripts in EFI variables
[!] WARNING: S3 Boot-Script was not found. Firmware may be using other ways to store/locate it, or OS might be blocking access.
找不到s3启动表的EFI变量,用s3漏洞来绕过的方法不可行。
检查TSEGME
寄存器,已锁定:
C:\Users\admin\Desktop\chipsec-master>python chipsec_main.py -m smm_dma
################################################################
## ##
## CHIPSEC: Platform Hardware Security Assessment Framework ##
## ##
################################################################
[CHIPSEC] Version 1.4.8
[CHIPSEC] Arguments: -m smm_dma
WARNING: *******************************************************************
WARNING: Chipsec should only be used on test systems!
WARNING: It should not be installed/deployed on production end-user systems.
WARNING: See WARNING.txt
WARNING: *******************************************************************
[CHIPSEC] API mode: using CHIPSEC kernel module API
[CHIPSEC] OS : Windows 10 10.0.19041 AMD64
[CHIPSEC] Python : 2.7.14 (64-bit)
[CHIPSEC] Helper : Win32Helper (\??\C:\Users\admin\Desktop\chipsec-master\chipsec\helper\win\win7_amd64\chipsec_hlpr.sys)
[CHIPSEC] Platform: Desktop 7th Generation Core Processor (Kabylake S)
[CHIPSEC] VID: 8086
[CHIPSEC] DID: 591F
[CHIPSEC] RID: 05
[CHIPSEC] PCH : Intel B250 (200 series) PCH
[CHIPSEC] VID: 8086
[CHIPSEC] DID: A2C8
[CHIPSEC] RID: 00
[+] loaded chipsec.modules.smm_dma
[*] running loaded modules ..
[*] running module: chipsec.modules.smm_dma
[x][ =======================================================================
[x][ Module: SMM TSEG Range Configuration Check
[x][ =======================================================================
[*] TSEG : 0x00000000CD000000 - 0x00000000CD7FFFFF (size = 0x00800000)
[*] SMRR range: 0x00000000CD000000 - 0x00000000CD7FFFFF (size = 0x00800000)
[*] checking TSEG range configuration..
[+] TSEG range covers entire SMRAM
[+] TSEG range is locked
[+] PASSED: TSEG is properly configured. SMRAM is protected from DMA attacks
检查SMRR寄存器,用于保护SMRAM Cache缓存攻击的寄存器已锁定:
C:\Users\admin\Desktop\chipsec-master>python chipsec_main.py -m common.smrr
################################################################
## ##
## CHIPSEC: Platform Hardware Security Assessment Framework ##
## ##
################################################################
[CHIPSEC] Version 1.4.8
[CHIPSEC] Arguments: -m common.smrr
WARNING: *******************************************************************
WARNING: Chipsec should only be used on test systems!
WARNING: It should not be installed/deployed on production end-user systems.
WARNING: See WARNING.txt
WARNING: *******************************************************************
[CHIPSEC] API mode: using CHIPSEC kernel module API
[CHIPSEC] OS : Windows 10 10.0.19041 AMD64
[CHIPSEC] Python : 2.7.14 (64-bit)
[CHIPSEC] Helper : Win32Helper (\??\C:\Users\admin\Desktop\chipsec-master\chipsec\helper\win\win7_amd64\chipsec_hlpr.sys)
[CHIPSEC] Platform: Desktop 7th Generation Core Processor (Kabylake S)
[CHIPSEC] VID: 8086
[CHIPSEC] DID: 591F
[CHIPSEC] RID: 05
[CHIPSEC] PCH : Intel B250 (200 series) PCH
[CHIPSEC] VID: 8086
[CHIPSEC] DID: A2C8
[CHIPSEC] RID: 00
[+] loaded chipsec.modules.common.smrr
[*] running loaded modules ..
[*] running module: chipsec.modules.common.smrr
[x][ =======================================================================
[x][ Module: CPU SMM Cache Poisoning / System Management Range Registers
[x][ =======================================================================
[+] OK. SMRR range protection is supported
[*] Checking SMRR range base programming..
[*] IA32_SMRR_PHYSBASE = 0xCD000006 << SMRR Base Address MSR (MSR 0x1F2)
[00] Type = 6 << SMRR memory type
[12] PhysBase = CD000 << SMRR physical base address
[*] SMRR range base: 0x00000000CD000000
[*] SMRR range memory type is Writeback (WB)
[+] OK so far. SMRR range base is programmed
[*] Checking SMRR range mask programming..
[*] IA32_SMRR_PHYSMASK = 0xFF800800 << SMRR Range Mask MSR (MSR 0x1F3)
[11] Valid = 1 << SMRR valid
[12] PhysMask = FF800 << SMRR address range mask
[*] SMRR range mask: 0x00000000FF800000
[+] OK so far. SMRR range is enabled
[*] Verifying that SMRR range base & mask are the same on all logical CPUs..
[CPU0] SMRR_PHYSBASE = 00000000CD000006, SMRR_PHYSMASK = 00000000FF800800
[CPU1] SMRR_PHYSBASE = 00000000CD000006, SMRR_PHYSMASK = 00000000FF800800
[CPU2] SMRR_PHYSBASE = 00000000CD000006, SMRR_PHYSMASK = 00000000FF800800
[CPU3] SMRR_PHYSBASE = 00000000CD000006, SMRR_PHYSMASK = 00000000FF800800
[+] OK so far. SMRR range base/mask match on all logical CPUs
[*] Trying to read memory at SMRR base 0xCD000000..
[+] PASSED: SMRR reads are blocked in non-SMM mode
[+] PASSED: SMRR protection against cache attack is properly configured
SMM_Code_Chk_En控制位检查,该功能已开启,无法执行SMRAM区域外的代码:C:\Users\admin\Desktop\chipsec-1.8.5>python chipsec_main.py -m common.smm_code_chk
################################################################
## ##
## CHIPSEC: Platform Hardware Security Assessment Framework ##
## ##
################################################################
[CHIPSEC] Version 1.8.5
[CHIPSEC] Arguments: -m common.smm_code_chk
WARNING: *******************************************************************
WARNING: Chipsec should only be used on test systems!
WARNING: It should not be installed/deployed on production end-user systems.
WARNING: See WARNING.txt
WARNING: *******************************************************************
[CHIPSEC] API mode: using CHIPSEC kernel module API
[CHIPSEC] OS : Windows 10 10.0.19044 AMD64
[CHIPSEC] Python : 3.9.6 (64-bit)
[CHIPSEC] Helper : Win32Helper (\??\C:\Users\admin\Desktop\chipsec-1.8.5\chipsec\helper\win\win7_amd64\chipsec_hlpr.sys)
[CHIPSEC] Platform: Desktop 7th Generation Core Processor (Kabylake S)
[CHIPSEC] VID: 8086
[CHIPSEC] DID: 591F
[CHIPSEC] RID: 05
[CHIPSEC] PCH : Intel B250 (200 series) PCH
[CHIPSEC] VID: 8086
[CHIPSEC] DID: A2C8
[CHIPSEC] RID: 00
[+] loaded chipsec.modules.common.smm_code_chk
[*] running loaded modules ..
[*] running module: chipsec.modules.common.smm_code_chk
[x][ =======================================================================
[x][ Module: SMM_Code_Chk_En (SMM Call-Out) Protection
[x][ =======================================================================
[*] MSR_SMM_FEATURE_CONTROL = 0x00000005 << Enhanced SMM Feature Control (MSR 0x4E0 Thread 0x0)
[00] LOCK = 1 << Lock bit
[02] SMM_Code_Chk_En = 1 << Prevents SMM from executing code outside the ranges defined by the SMRR
[*] MSR_SMM_FEATURE_CONTROL = 0x00000005 << Enhanced SMM Feature Control (MSR 0x4E0 Thread 0x1)
[00] LOCK = 1 << Lock bit
[02] SMM_Code_Chk_En = 1 << Prevents SMM from executing code outside the ranges defined by the SMRR
[*] MSR_SMM_FEATURE_CONTROL = 0x00000005 << Enhanced SMM Feature Control (MSR 0x4E0 Thread 0x2)
[00] LOCK = 1 << Lock bit
[02] SMM_Code_Chk_En = 1 << Prevents SMM from executing code outside the ranges defined by the SMRR
[*] MSR_SMM_FEATURE_CONTROL = 0x00000005 << Enhanced SMM Feature Control (MSR 0x4E0 Thread 0x3)
[00] LOCK = 1 << Lock bit
[02] SMM_Code_Chk_En = 1 << Prevents SMM from executing code outside the ranges defined by the SMRR
[+] PASSED: SMM_Code_Chk_En is enabled and locked down
AFUWIN v5.09 逆向破解
解锁GAN参数
看了下,afuwin似乎自带gan参数可以刷写所有区域,但正常版本会有个判断,无法使用gan参数:
把比较后return 0的代码nop掉,直接进入下一步,就可以解锁gan参数了:
但是还有一层secure flash rom验证:
Secure flash rom verify绕过
在判断secure flash是否开启后,会将capsule加载到secure mem中,并进行验证:
load_to_secure_mem_Verify()有几个返回值,返回非0则验证失败:
把这几个返回值改为0即可绕过校验:
刷写成功,但还有一层启动校验,导致系统起不来了:
编程器修复
用CH341A编程器,选择W25Q64BV芯片,可读写
capsule参数逆向
用gan参数刷写不可行,再来看看capsule参数吧
capsule参数执行会mount ESP分区:
并把固件复制到ESP分区下:
尝试在它重启刷新前,把RECOVERY.CAP替换成我们的ROM,然后再重启。
但主板启动时会报警(连续4声蜂鸣)拒绝刷写替换后的ROM。
Lenovo 510-08IKL中找到的vulnerable
NvmeSmm.efi
ERROR (low_smram_corruption.py): SMI Func: SmiHandler (0x9C0) considered vulnerable: might be abused to corrupt the lower portion of SMRAM
这个是假阳性,前面有检查CommBuffer->field_8
的大小不大于0x10个字节:
AMTLockUsbKBD.efi
ERROR (low_smram_corruption.py): SMI Func: SmiHandler (0x344) considered vulnerable: might be abused to corrupt the lower portion of SMRAM
这个也是假阳性,只是传递了CommBuffer
和CommBufferSize
参数,没有给尝试写入通信缓冲区。
- 534D0040.efi
ERROR (setvar_infoleak.py): Function sub_F14 discloses up to 4457 SMRAM bytes while calling SetVariable() on b'Setup'
ERROR (setvar_infoleak.py): Function sub_F14 discloses up to 4457 SMRAM bytes while calling SetVariable() on b'Setup'
ERROR (setvar_infoleak.py): Function sub_F14 discloses up to 4457 SMRAM bytes while calling SetVariable() on b'Setup'
ERROR (setvar_infoleak.py): Function sub_F14 discloses up to 4457 SMRAM bytes while calling SetVariable() on b'Setup'
ERROR (setvar_infoleak.py): Function sub_F14 discloses up to 4457 SMRAM bytes while calling SetVariable() on b'Setup'
ERROR (setvar_infoleak.py): Function sub_3878 discloses up to 32 SMRAM bytes while calling SetVariable() on b'Ep'
这里固定读取Setup变量的大小为4472个字节,可作为利用点。
WMISwSmi.efi
ERROR (efiXplorer.py): efiXplorer detected get_variable_buffer_overflow at ['0x2a54']
在0x2a54的地址上找到了一个GetVariable()
函数调用的缓冲区溢出:
GetVariable()
的函数定义:
typedef
EFI_STATUS
GetVariable (
IN CHAR16 *VariableName, //A Null-terminated string that is the name of
//the vendor’s variable.
IN EFI_GUID *VendorGuid, //A unique identifier for the vendor.
//Type EFI_GUID is defined in the EFI_BOOT_SERVICES.InstallProtocolInterface() function description.
OUT UINT32 *Attributes OPTIONAL, //If not NULL, a pointer to the memory location to return the //attributes bitmask for the variable.
//If not NULL, then Attributes is set on output both when
//EFI_SUCCESS and when EFI_BUFFER_TOO_SMALL is returned.
IN OUT UINTN *DataSize, //On input, the size in bytes of the return Data buffer.
//On output the size of data returned in Data.
OUT VOID *Data OPTIONAL //The buffer to return the contents of the variable.
//May be NULL with a zero DataSize in order to determine the size buffer needed.
);
返回码:
Data
缓冲区可以为0,用于确定Buffer所需的大小。如果数据缓冲区太小,无法保存变量的内容,则返回错误EFI_BUFFER_TOO_SMALL
,并将缓冲区大小设置为所需数据的大小。
调用GetVariable
获取AMITSESETUP_GUID中定义的WMIAcpiMemAddr
变量的值,首先调用来确定Buffer所需的大小:
v10 = gRT_0->GetVariable(aWmiacpimemaddr, &AMITSESETUP_GUID, 0i64, &DataSize, 0i64);
如返回值不为EFI_BUFFER_TOO_SMALL
,或传入GETVAR_Data
参数后返回值大于等于0则继续操作:
GETVAR_Data
为全局变量,且在调用前进行过初始化:
lenovo 510-08IKL SMIFuzz
用chipsec触发所有可能的SW SMI handlers:
@echo off
for /l %%a in (0,1,255) do (
python chipsec_util.py smi 0 %%a 0)
执行完54号正在执行55号的时候系统就挂起了:
SMM驱动程序使用EFI_SMM_SW_DISPATCH2_PROTOCOL
协议的Register()
函数来注册SW SMI handlers,下面是EDK2中的定义:
#define EFI_SMM_SW_DISPATCH2_PROTOCOL_GUID EFI_MM_SW_DISPATCH_PROTOCOL_GUID
typedef struct _EFI_SMM_SW_DISPATCH2_PROTOCOL EFI_SMM_SW_DISPATCH2_PROTOCOL;
/**
Register a child SMI source dispatch function for the specified software SMI.
This service registers a function (DispatchFunction) which will be called when the software
SMI source specified by RegisterContext->SwSmiCpuIndex is detected. On return,
DispatchHandle contains a unique handle which may be used later to unregister the function
using UnRegister().
@param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.
@param[in] DispatchFunction Function to register for handler when the specified software
SMI is generated.
@param[in, out] RegisterContext Pointer to the dispatch function's context.
The caller fills this context in before calling
the register function to indicate to the register
function which Software SMI input value the
dispatch function should be invoked for.
@param[out] DispatchHandle Handle generated by the dispatcher to track the
function instance.
@retval EFI_SUCCESS The dispatch function has been successfully
registered and the SMI source has been enabled.
@retval EFI_DEVICE_ERROR The SW driver was unable to enable the SMI source.
@retval EFI_INVALID_PARAMETER RegisterContext is invalid. The SW SMI input value
is not within a valid range or is already in use.
@retval EFI_OUT_OF_RESOURCES There is not enough memory (system or SMM) to manage this
child.
@retval EFI_OUT_OF_RESOURCES A unique software SMI value could not be assigned
for this dispatch.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_SMM_SW_REGISTER2)(
IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This,
IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
IN OUT EFI_SMM_SW_REGISTER_CONTEXT *RegisterContext,
OUT EFI_HANDLE *DispatchHandle
);
/**
Unregister a child SMI source dispatch function for the specified software SMI.
This service removes the handler associated with DispatchHandle so that it will no longer be
called in response to a software SMI.
@param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.
@param[in] DispatchHandle Handle of dispatch function to deregister.
@retval EFI_SUCCESS The dispatch function has been successfully unregistered.
@retval EFI_INVALID_PARAMETER The DispatchHandle was not valid.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_SMM_SW_UNREGISTER2)(
IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This,
IN EFI_HANDLE DispatchHandle
);
///
/// Interface structure for the SMM Software SMI Dispatch Protocol.
///
/// The EFI_SMM_SW_DISPATCH2_PROTOCOL provides the ability to install child handlers for the
/// given software. These handlers will respond to software interrupts, and the maximum software
/// interrupt in the EFI_SMM_SW_REGISTER_CONTEXT is denoted by MaximumSwiValue.
///
struct _EFI_SMM_SW_DISPATCH2_PROTOCOL {
EFI_SMM_SW_REGISTER2 Register;
EFI_SMM_SW_UNREGISTER2 UnRegister;
///
/// A read-only field that describes the maximum value that can be used in the
/// EFI_SMM_SW_DISPATCH2_PROTOCOL.Register() service.
///
UINTN MaximumSwiValue;
};
extern EFI_GUID gEfiSmmSwDispatch2ProtocolGuid;
EFI_MM_SW_DISPATCH_PROTOCOL_GUID
为:
#define EFI_MM_SW_DISPATCH_PROTOCOL_GUID \
{ \
0x18a3c6dc, 0x5eea, 0x48c8, {0xa1, 0xc1, 0xb5, 0x33, 0x89, 0xf9, 0x89, 0x99 } \
}
UEFITool中能找到一堆调用了该GUID的驱动程序:
只能一个个地看,找导致崩溃的55号SMI handler了
SMM Call Out误报
MicrocodeUpdate.efi
这里如果它要释放的Buffer是在SMRAM则会调用gSmst->SmmFreePool()
,否则调用gBs->FreePool()
不能将其判定为CallOut
SmbiosDmiEdit.efi
调用了gRT_0->Getvariable()
,乍一看似乎是CallOut,但实际上不是。它调用了位于SMRAM中的UEFI配置表EFI_SMM_RUNTIME_SERVICES_TABLE
,重新映射了全局指针RuntimeService
,其功能与EFI_RUNTIME_SERVICES_TABLE
相同,可用于SMI handlers中:
所以这也是个误报。
OemSmi.efi
同上理由,是误报:
近期评论