绕过BIOS/UEFI固件写保护写入SPI闪存

针对Bootkit:LoJax或MosaicRegressor和TrickBot等开始进行固件感染方式的病毒逐渐增多而作笔记整理。
对主板上的SPI闪存芯片中存储的UEFI固件的所有请求都将通过SPI控制器,该控制器是Intel平台上的Platform Controller Hub(PCH)的一部分。可以通过PCI设备驱动访问PCI总线配置空间可以获取PCH的值。

用I/O命令访问PCI总线配置空间

系统中的CPU是通过PCI设备的设备号以及配置空间中的寄存器编号来访问配置空间寄存器的。

PCI有三个相互独立的物理地址空间:设备存储器地址空间、I/O地址空间和配置空间。
配置空间是PCI所特有的一个物理空间。由于PCI支持设备即插即用,所以PCI设备不占用固定的内存地址空间或I/O地址空间,而是由操作系统决定其映射的基址。系统加电时,BIOS检测PCI总线,确定所有连接在PCI总线上的设备以及它们的配置要求,并进行系统配置。所以,所有的PCI设备必须实现配置空间,从而能够实现参数的自动配置,实现真正的即插即用。
要访问PCI总线设备的配置空间,必须先查找该设备。查找的基本根据是各PCI设备的配置空间里都存有特定的设备号(Device ID)及销售商号(Vendor ID),它们占用配置空间的00h地址。而查找的目的是获得该设备的总线号和设备号。查找的基本过程如下:用I/O命令写配置空间的地址寄存器(CONFIG_ADDRESS)CF8h,使其最高位为1,总线号及设备为0,功能号及寄存器号为0,即往I/O端口CF8h80000000h;然后用I/O命令读取配置空间的数据寄存器(CONFIG_DATA)CFCh。如果该寄存器值与该PCI设备的Device ID及Vendor ID不相符,则依次递增设备号/总线号,重复上述操作直到找到该设备为止。如果查完所有的设备号/总线号(1~5)仍不能找到该设备,则应当考虑硬件上的问题。对于多功能设备,只要设备配置寄存器相应的功能号值,其余步骤与单功能设备一样。

CONFIG_ADDRESS寄存器格式:
31 位: Enabled位。
23:16 位: 总线编号。
15:11 位: 设备编号。
10: 8 位:功能编号。
7: 2 位:配置空间寄存器编号。
1: 0 位:恒为“00”。这是因为CF8h、CFCh端口是32位端口。
在这里插入图片描述
如查找设备号为9054h,销售商号为10b5的单功能PCI设备,用VC++6.0编写的程序如下:

char bus;
char device;
 unsigned int ioa0,iod;
 int scan( )
 {
    
    
 bus=0;device=0;
 for(char i=0;i<5;i++) {
    
    
 for(char j=0;j<32;j++) {
    
    
 bus=i; device=j;
 ioa0=0x80000000+bus*0x10000
 +(device*8)*0x100;
 _outpd(0xcf8,ioa0);
 iod=_inpd(0xcfc);
 if (iod0= =0x905410b5) return 0;
 }
 }
 retrn -1
 }

调用子程序scan( ),如果返回值为-1,则没有找到该PCI设备。如果返回值为0,则找到了该PCI设备。该设备的总线号和设备号分别在全局变量bus和device中,利用这两个变量即可轻易对该设备的配置空间进行访问,从而得到分配的资源信息。

处理器系统资源分为IO资源和MMIO资源两种,因此PCI/PCIe空间地址对应也有两种。

参考文献
PCI配置空间简介
https://www.cnblogs.com/wangshide/archive/2012/05/10/2495150.html
《Windows开发技术详解》第16章-PCI设备驱动

BIOS控制寄存器BIOS_CNTL

BIOS 控制寄存器(BIOS_CNTL)中包含的三个字段的值:
一、BIOS写入启用(BIOSWE)
二、BIOS锁定启用(BLE)
三、SMM BIOS写保护禁用(SMM_BWP)。
BIOS锁定启用(BLE),该功能启用时会将BIOSWE位锁定为0。 但是,在现实情况中这种保护机制非常脆弱,当有请求将BIOSWE位设置为1时,BIOSWE先会被设置为1,这种方式问题很大。 首先,需要固件开发人员专门构建一个SMI处理程序,如果没有,则BLE位无用。 其次,存在竞态条件漏洞时,即使SMI处理程序正常运行,也可能允许完全绕过此机制。要利用此漏洞,攻击者需要启动一个线程,该线程将BIOSWE连续设置为1,而另一个线程将数据写入SPI闪存。

为了解决此问题,通过BIOS_CNTL配置的新保护机制已经得到应用。它是在英特尔芯片组的平台控制器中心(PCH)系列中引入的。如果其配置位已设置,则仅当所有内核在系统管理模式(SMM)中运行且BIOSWE设置为1时,SMM BIOS写保护禁用(SMM_BWP)才能允许BIOS固件是可写的。这种机制能够有效保护系统免受竞态条件漏洞的影响。但是,与BLE的情况一样,SMM_BWP需由固件激活。因此,未能正确配置这些机制的固件会使系统面临未经授权写入BIOS区域的风险。

Sednit团队中的ReWriter_binary.exe读取BIOS控制寄存器的内容以选择正确的路径。它首先检查BIOSWE是否已设置。如果是,则进入写入阶段。如果禁用BIOSWE,它将检查BLE位的值。如果未设置,则会翻转BIOSWE位并开始覆写已修改的固件。如果设置了BLE,则确保禁用SMM_BWP并利用上述竞态条件。如果SMM_BWP位置1,则失败。

在这里插入图片描述

攻击者如何感染UEFI固件?

攻击者可以通过多种方式感染固件,但下面列出了最常见/最明显的方法:
一、修改未签名的UEFI选项ROM,这些ROM可能无法根据配置进行验证
二、添加/修改DXE驱动程序
三、替换/修改引导管理器(使用回退引导管理器)
四、修改回退引导加载程序EFI/BOOT/bootx64.EFI
五、添加辅助引导加载程序
六、绕过SPI写保护并设置敏感内存位以禁用保护

从具有根权限的用户空间,使用签名旁路插入内核代码,使用硬件抽象层接口访问系统管理模式。然后找到一种绕过SPI保护的方法,直接写入上面列出的一个早期启动阶段。

读写SPI闪存

Sednit的ReWriter_read.exe会检索SPI闪存上的BIOS区域基地址及其大小。该信息包含在SPI主机接口寄存器“BIOS Flash Primary Region”中。所有SPI主机接口寄存器都在根复合寄存器块(RCRB)中进行存储器映射,其基址可以通过读取正确的PCI配置寄存器来检索。一旦获得BIOS区域基址和大小信息后,转储工具就会读取SPI闪存的相关内容并将其写入磁盘上的文件。SPI读取顺序如下图:
在这里插入图片描述

这些操作将重复执行直到从SPI闪存读取所有数据为止。然后,ReWriter_read验证转储镜像的大小。它将解析镜像Flash描述符以获取BIOS、千兆以太网(GbE)和管理引擎(ME)区域的内存范围。添加这三个区域的大小允许转储工具计算SPI闪存中完整内容的大小。如果镜像尺寸等于通过读取BIOS Flash主区域寄存器获得的尺寸信息,镜像被认为有效。

UEFI镜像中的数据使用固件文件系统(FFS)以卷的形式存储。顾名思义,它是专门为存储固件镜像而定制的文件系统。卷包含由GUID标识文件。每个文件通常由多个部分组成,其中一个部分包含真实的PE/COFF可执行文件,即UEFI镜像。使用UEFITool可以看到相关信息。SPI写入顺序如下图:
在这里插入图片描述

参考文献

一枚“野生”UEFI rootkit的分析报告
https://www.freebuf.com/news/185828.html
PCI配置空间简介
https://www.cnblogs.com/wangshide/archive/2012/05/10/2495150.html
Windows开发技术详解》第16章PCI设备驱动

猜你喜欢

转载自blog.csdn.net/qq_43312649/article/details/111179517