王冠 杨松松
摘要:SPI范围保护寄存器是UEFI固件常用的一种保护机制。提出了一种篡改SPI范围保护寄存器值的方法,利用该方法可以实现SMM漏洞攻击。阐述了SPI范围保护寄存器原理,研究了SPI范围保护寄存器修改理论,实现对计算机SPI范围保护寄存器值的篡改。实验结果表明,任何采用SPI范围保护机制的固件均有可能采用这种方式进行破坏。
关键词:SPI范围保护寄存器;UEFI漏洞;闪存写保护
Research on SPI Protected Ranges vulnerability
WANG Guan1,2,YANG Song song1,2
(1.College of Computer,Beijing University of Technology;
2.Key Laboratory of Trustworthy Computing in Beijing, Beijing 100124,China)
Abstract:SPI range protection register is a common protection mechanism for UEFI firmware. In this paper, a method of tampering with SPI range protection register value is proposed, which can realize SMM copper leak attack. This paper also expounds the principle of SPI range protection register, studies the modification theory of SPI range protection register, and realizes tampering with the value of computer SPI range protection register. The experimental results show that any firmware using SPI scope protection mechanism may be destroyed in this way.
Key Words:SPI protected ranges;UEFI vulnerability;flash write protection
0 引言
BIOS是一组固化在计算机主板ROM芯片上的程序,主要负责初始化硬件和操作系统预启动处理[1]。BIOS还负责配置和实例化系统管理模式(System Management Mode,SMM),这是一种x86平台上具有高度特权的执行模式[2]。任何控制BIOS的恶意软件都可将任意代码放入SMM中。因此,很有必要保护BIOS安全。UEFI是新一代BIOS接口规范[3]。为保护UEFI固件,Intel提出了多种保护机制,包括BIOS_CNTL寄存器保护机制、SPI范围保护寄存器机制(PR0-PR4,简称“PRx”)以及BootGuard保护机制。大多数计算机都使用SPI范围保护寄存器机制保护固件,防止随意对闪存进行编程操作。
1 UEFI启动关键点分析
1.1 S3恢复引导路径
S3恢复引导路径是一种不同于UEFI框架正常引导路径的引导方式,是S3模式下的一种引导路径[4]。通过这个路径,UEFI框架从闪存中获取有关平台配置的预存数据,并在跳转到操作系统的唤醒向量之前配置平台。
S3模式就是Suspend to Ram(简称STR)模式,是6种ACPI电源管理模式中的一种[5]。利用该模式,可以在保存系统关键信息的情况下节省电源。在这种模式下,系统可将转到S3模式前的重要信息存储到内存中,而且电源能持续为内存等系统设备供电,以防数据丢失。当打开电源开关时系统启动,可很快从内存中读取数据并返回到S3之前的状态。由于是对内存进行读取,因此恢复状态的速度很快。
1.2 UEFI引导脚本
UEFI引导脚本是一种在ACPI S3睡眠模式下保存平台状态的数据结构[6]。为保护计算机固件,UEFI规范引入了一种称为SMM LockBox的机制,将引导脚本存储在系统管理RAM(SMRAM)中,起到保护引导脚作用。
在S3恢复引导路径中,框架需要在PEI和DXE阶段恢复配置。由于DXE阶段承载服务众多,因此为了提高性能,需要避免S3恢复引导路径中的DXE阶段。为达到这个目的,UEFI框架在正常启动期间构建引导脚本。各种芯片组驱动程序将I / O、PCI、内存、系统管理总线(SMBus),以及恢复芯片组和处理器配置所必需的其它特定操作或程序信息记录在引导脚本中。在S3恢复引导路径期间,引导脚本引擎解析脚本,恢复系统配置。
引导脚本可访问I / O、内存和PCI配置空间,还可执行特定的微处理器指令。在觸发 S3 模式挂起—恢复动作的情况下,通过更改这个数据结构覆盖SPI范围保护寄存器的值。
1.3 SPI范围保护寄存器机制
SPI范围保护寄存器机制是Intel提供的一种保护主板闪存中BIOS固件不被随意覆写的机制,其包含PR0—PR4寄存器(简称“PRx”寄存器)。该机制通过设置PR0—PR4寄存器值来规定受保护的目标区域地址,在保护状态下,受保护目标区域不可被写入、擦除或读取。当PR0—PR4寄存器值都为0时,SPI范围保护机制失效[7]。
PR0—PR4寄存器的地址范围为0x3800—0x39ff,单个寄存器长度为32位。每个寄存器除内存地址不同外,读写权限、默认值、大小都是相同的。其中,第0~12位表示保护范围基址,指定受保护范围下限。13~14位是保留位,第15位是读使能保护位,当该位被设置时,表示该寄存器中的基址和限制字段有效,禁止对它们之间的地址进行读取操作。第16~18位表示保护范围限制位,指定受保护范围的上限。第29~30位是保留位。第31位表示写保护使能位,当该位被设置时,表示该寄存器中的基址和限制字段有效,禁止对它们之间的地址进行写入和擦除操作。该位被清除时,基址和限制字段被忽略。
SPI范围保护寄存器通过SPI根复合寄存器块(RCRB)的SPI Host Interface内存映射寄存器进行配置。根复合寄存器块是一组用于配置根联合体设备的寄存器组。根联合体设备是一种将处理器和内存子系统连接到由一个或多个交换设备组成的PCI Express交换结构。不同芯片组的根复合寄存器块地址不同,可通过读取位于LPC桥接器件的PCI配置空间内偏移量为0xf0的根复合基址寄存器,确定根复合寄存器块地址。
2 破坏SPI范围保护寄存器机制
UEFI正常引导路径即UEFI框架引导系统正常启动过程。在该路径中,UEFI框架构建UEFI引导脚本,将包括SPI范围保护寄存器值在内的信息保存到闪存中。当系统进入到S3睡眠模式时,UEFI引导脚本通过SMM LockBox机制保存到SMRAM中;系统从S3睡眠模式唤醒时,引导脚本引擎解析引导脚本文件,将系统配置恢复到S3睡眠模式前状态。如果在进入S3睡眠模式期间更改UEFI引导脚本中SPI范围保护寄存器的值,当系统被唤醒时,SPI范围保护寄存器的值就会被UEFI引导脚本中的记录覆盖,从而实现对SPI范围保护寄存器值的篡改。
为使用引导脚本,需要知道SMM LockBox驱动程序如何将其存储到SMRAM中,因此需对SMM LockBox驱动程序进行逆向工程。从逆向源码中获得UEFI引导脚本地址后,根据该地址对UEFI引导脚本中SPI范围保护寄存器的值进行修改,最后触发S3睡眠模式挂起,恢复篡改SPI范围保护寄存器的值。
2.1 逆向S3恢复引导路径
在不同结构中,固件中的SMMLockBox驱动程序具有相同的LockBoxGUID(bd445d79-b7ad-4f04-9ad8-29bd2040eb3c)。因此,将实验机固件加载到UEFITool中,然后搜索该GUID。UEFI Tool是一种可以确定SMMLockBox驱动程序位置的可视化工具[8],如图1所示。
利用UEFITool找到实现SMMLockBox功能的DXE驱动程序,将其转储到磁盘中,加载到IDAPro并反编译PE镜像的入口函数。sub_77C()函数对 SMM LockBox 执行初始化:
int __fastcall sub_77C(EFI_HANDLE ImageHandle)
{
...
v1 = gBS->LocateProtocol(&gEfiSmmBaseProtocolGuid, 0,&SmmBaseProtocol);
v2 = 0;
if (v1 >= 0)
{
// 确定驱动程序是否被加载到SMRAM
SmmBaseProtocol->InSmm(SmmBaseProtocol, &v10);
if (v10)
{
// 找到EFI_SMM_SYSTEM_TABLE
SmmBaseProtocol->GetSmstLocation(SmmBaseProtocol,&gSMST);
gRT->SetVariable(L"Smst",gEfiSmmLockBoxCommunicationGuid, 3);
// 找到EFI_SMM_ACCESS_PROTOCOL
gBS->LocateProtocol(&gEfiSmmAccessProtocolGuid, 0,&SmmAccessProtocol);
…
// 得到SMRAM 地址
SmmAccessProtocol->GetCapabilities(SmmAccessProtocol,&v11, 0);
gSMST->SmmAllocatePool(6, v11, &qword_F68);
…
// 把sub_674()注冊为回调函数
SmmBaseProtocol->RegisterCallback(SmmBaseProtocol,0xF9E9662B,sub_674, v4);
}
…
}
从代码可知,驱动代码利用EFI_SMM_BASE_PROTOCOL的InSmm()函数确定它如何加载驱动。SMM回调注册则使用EFI_SMM_BASE_PROTOCOL的RegisterCallback()函数实现。调用EFI_SMM_SYSTEM_TABLE.SmmAllocatePages()函数完成为SMM LockBox数据列表条目分配内存的工作,用于存储引导脚本的副本,该地址来自 SMM 回调输入。EFI_SMM_SYSTEM_TABLE.SmmAllocatePool()函数用于存储引导脚本地址、大小以及 “LOCKBOXD”签名等。
通过SMMLockBoxGUID和配置表开头的常量签名“LOCKB_64”,可以找到带有双链表头的指针UEFISMM配置表,利用转储工具获得SMRAM转储,如图2所示。
从目标机的SMRAM内容转储结果可以看出转储成功。将转储结果加载到IDA中,从中可得到配置表信息。通过“SMST”签名可在SMRAM中找到EFI_SMM_SYSTEM_TABLE。在EFI_SMM_SYSTEM_TABLE结尾,可发现UEFISMM配置表和指向EFI_CONFIGURATION_TABLE结构数组的指针,地址为0xad34cdc8的列表中包含“LOCKBOXD”签名的引导脚本信息结构,并可知道引导脚本的SMRAM副本位于0xad1c1000的地址,长度为0×7e12字节。
2.2 篡改SPI范圍保护寄存器的值
通过引导脚本位置对存储在 SMM LockBox 中的引导脚本进行读和写操作,从而修改PRx寄存器的值达到破坏SPI范围保护机制的目的。首先,需要通过GUID查找EFI_CONFIGURATION_TABLE的VendorTable。函数smst_addr()可用于通过表头签名来查找EFI_SMM_SYSTEM_TABLE的地址。利用该地址找到VendorTable后,可以编写定位UEFISMM配置表函数并解析它的数据,确定启动脚本表副本在SMRAM中存储的位置。接着利用该函数可看到目标计算机固件引导脚本的十六进制转储。在该表最后可看到PR0-PR4寄存器的值(黄色代表寄存器,绿色代表寄存器的值),如图3所示。
从转储结果得到PRx寄存器的值,利用disable()函数将PR0-PR4寄存器的值设置为零:
for (int i = 0; i < 5; i += 1)
{
if (addr == pr_regs[i].addr)
{
val = 0;
// 将PRx寄存器的值设置为0
if (phys_mem_write(target, (void *)(bootscript_addr + ptr +0x11),
sizeof(unsigned int), (unsigned char *)&val,NULL) == 0)
{
entries_patched += 1;
}
if (!pr_regs[i].found)
{
registers_found += 1;
}
pr_regs[i].found = true;
break;
}
}
然后调用s3_sleep_with_timeout()函数触发挂起-恢复动作,同时修改脚本文件表。最后,S3复位后再一次读取PR0-PR4值,检查PRx闪存写保护是否被成功禁用。
{
if (s3_sleep_with_timeout(10) == 0)
{
// 得到当前PRx 寄存器的值
if (pr_get(target, &rcrb_addr,
&pr0_val, &pr1_val, &pr2_val, &pr3_val,
&pr4_val) != 0)
{
goto _end;
}
// 检查SPI保护是否被设置
if (pr0_val == 0 && pr1_val == 0 && pr2_val == 0 &&
pr3_val == 0 && pr4_val == 0)
{
ret = 0;
}
}
2.3 S3睡眠模式唤醒系统
最后,需要从S3睡眠模式唤醒Windows操作平台。首先要判断目标计算机是否支持S3睡眠状态。利用SetSuspendState()函数判断电脑是否进入睡眠状态,如果判断为真,再利用SetWaitableTimer()Win32API函数中的fResume参数,通过改变定时器状态使系统退出睡眠状态。
2.4 结果检测
利用Intel开发的安全评估框架CHIPSEC对目标计算机的寄存器初始状态进行检测,得到结果如图4所示。
从检测结果可以看出,目标计算机运行正常,SPI范围保护寄存器值不都为0,保护机制正常。
下面运行本文中提出的方法程序检验是否破坏了SPI范围保护机制,如图5所示。
从程序结果中可知,PRx的闪存写保护功能被禁止。
运行CHIPSEC并验证PR0-PR4寄存器值是否得到了修改,如图6所示。
从结果可以看到,PR0-PR4的值都变为0。通过与寄存器初始状态进行对比,寄存器的值确实被篡改,证明本文提出方法的正确性。
3 结语
本文提出了一种篡改SPI范围保护寄存器值的方法,实现对SMRAM中UEFI引导脚本中记录的SPI范围保护寄存器值的篡改。利用代码实现S3睡眠模式的挂起—恢复动作,从而将寄存器值设置为0,达到了破坏该保护机制的目的。这种修改寄存器值旁路SPI范围保护机制的方式,适用于绝大多数采用这种安全机制的计算机。分析可知,PRx寄存器值的设置方式是这种旁路攻击的切入点。因此,需要对寄存器的设置过程加以保护,才能避免攻击者随意对寄存器的值进行修改。
参考文献:
[1] 房强.基于固件文件系统的UEFI安全机制研究[D].成都:电子科技大学,2016.
[2] 杨旭,骆祖莹,韩银和.基于Cache内容替换的系统管理模式漏洞检测方法[D].北京:北京师范大学,2011.
[3] UNIFIED EXTENSIBLE FIRMWARE INTERFACE FORUM.Version2.4 Errata. [EB/OL].http:∥www.uefi. org/node/670/download/f776d13e2ee21d3e8d3659e0e 024f7c5.
[4] INTEL. Platform innovation framework for EFI S3 resume boot path specification[EB/OL].www.intel.com/content/dam/doc/reference guide/efi s3 resume boot path specification.pdf
[5] 顾丽红,吴少刚.基于ACPI标准的龙芯3A平台系统功耗分析[J].计算机工程与设计,2016,37(9):2 5.
[6] INTEL. Platform innovation framework for EFI boot script specification[EB/OL]. https:∥www.intel.com/content/dam/doc/guide/efi boot script specification v091.pdf
[7] INTEL. 6 series chipset and C200 series chipset[EB/OL]. http:∥www.intel.com/content/www/us/en/chipsets/6 chipset c200 chipset datasheet.html
[8] SOFTPEDIA. UEFITool.[EB/OL].http:∥www.softpedia.com/get/System/System Miscellaneous/UEFITool.shtml.