王冠 楊松松
摘要:SPI范圍保護(hù)寄存器是UEFI固件常用的一種保護(hù)機(jī)制。提出了一種篡改SPI范圍保護(hù)寄存器值的方法,利用該方法可以實現(xiàn)SMM漏洞攻擊。闡述了SPI范圍保護(hù)寄存器原理,研究了SPI范圍保護(hù)寄存器修改理論,實現(xiàn)對計算機(jī)SPI范圍保護(hù)寄存器值的篡改。實驗結(jié)果表明,任何采用SPI范圍保護(hù)機(jī)制的固件均有可能采用這種方式進(jìn)行破壞。
關(guān)鍵詞:SPI范圍保護(hù)寄存器;UEFI漏洞;閃存寫保護(hù)
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是一組固化在計算機(jī)主板ROM芯片上的程序,主要負(fù)責(zé)初始化硬件和操作系統(tǒng)預(yù)啟動處理[1]。BIOS還負(fù)責(zé)配置和實例化系統(tǒng)管理模式(System Management Mode,SMM),這是一種x86平臺上具有高度特權(quán)的執(zhí)行模式[2]。任何控制BIOS的惡意軟件都可將任意代碼放入SMM中。因此,很有必要保護(hù)BIOS安全。UEFI是新一代BIOS接口規(guī)范[3]。為保護(hù)UEFI固件,Intel提出了多種保護(hù)機(jī)制,包括BIOS_CNTL寄存器保護(hù)機(jī)制、SPI范圍保護(hù)寄存器機(jī)制(PR0-PR4,簡稱“PRx”)以及BootGuard保護(hù)機(jī)制。大多數(shù)計算機(jī)都使用SPI范圍保護(hù)寄存器機(jī)制保護(hù)固件,防止隨意對閃存進(jìn)行編程操作。
1?UEFI啟動關(guān)鍵點分析
1.1?S3恢復(fù)引導(dǎo)路徑
S3恢復(fù)引導(dǎo)路徑是一種不同于UEFI框架正常引導(dǎo)路徑的引導(dǎo)方式,是S3模式下的一種引導(dǎo)路徑[4]。通過這個路徑,UEFI框架從閃存中獲取有關(guān)平臺配置的預(yù)存數(shù)據(jù),并在跳轉(zhuǎn)到操作系統(tǒng)的喚醒向量之前配置平臺。
S3模式就是Suspend to Ram(簡稱STR)模式,是6種ACPI電源管理模式中的一種[5]。利用該模式,可以在保存系統(tǒng)關(guān)鍵信息的情況下節(jié)省電源。在這種模式下,系統(tǒng)可將轉(zhuǎn)到S3模式前的重要信息存儲到內(nèi)存中,而且電源能持續(xù)為內(nèi)存等系統(tǒng)設(shè)備供電,以防數(shù)據(jù)丟失。當(dāng)打開電源開關(guān)時系統(tǒng)啟動,可很快從內(nèi)存中讀取數(shù)據(jù)并返回到S3之前的狀態(tài)。由于是對內(nèi)存進(jìn)行讀取,因此恢復(fù)狀態(tài)的速度很快。
1.2?UEFI引導(dǎo)腳本
UEFI引導(dǎo)腳本是一種在ACPI S3睡眠模式下保存平臺狀態(tài)的數(shù)據(jù)結(jié)構(gòu)[6]。為保護(hù)計算機(jī)固件,UEFI規(guī)范引入了一種稱為SMM LockBox的機(jī)制,將引導(dǎo)腳本存儲在系統(tǒng)管理RAM(SMRAM)中,起到保護(hù)引導(dǎo)腳作用。
在S3恢復(fù)引導(dǎo)路徑中,框架需要在PEI和DXE階段恢復(fù)配置。由于DXE階段承載服務(wù)眾多,因此為了提高性能,需要避免S3恢復(fù)引導(dǎo)路徑中的DXE階段。為達(dá)到這個目的,UEFI框架在正常啟動期間構(gòu)建引導(dǎo)腳本。各種芯片組驅(qū)動程序?qū) / O、PCI、內(nèi)存、系統(tǒng)管理總線(SMBus),以及恢復(fù)芯片組和處理器配置所必需的其它特定操作或程序信息記錄在引導(dǎo)腳本中。在S3恢復(fù)引導(dǎo)路徑期間,引導(dǎo)腳本引擎解析腳本,恢復(fù)系統(tǒng)配置。
引導(dǎo)腳本可訪問I / O、內(nèi)存和PCI配置空間,還可執(zhí)行特定的微處理器指令。在觸發(fā) S3 模式掛起—恢復(fù)動作的情況下,通過更改這個數(shù)據(jù)結(jié)構(gòu)覆蓋SPI范圍保護(hù)寄存器的值。
1.3?SPI范圍保護(hù)寄存器機(jī)制
SPI范圍保護(hù)寄存器機(jī)制是Intel提供的一種保護(hù)主板閃存中BIOS固件不被隨意覆寫的機(jī)制,其包含PR0—PR4寄存器(簡稱“PRx”寄存器)。該機(jī)制通過設(shè)置PR0—PR4寄存器值來規(guī)定受保護(hù)的目標(biāo)區(qū)域地址,在保護(hù)狀態(tài)下,受保護(hù)目標(biāo)區(qū)域不可被寫入、擦除或讀取。當(dāng)PR0—PR4寄存器值都為0時,SPI范圍保護(hù)機(jī)制失效[7]。
PR0—PR4寄存器的地址范圍為0x3800—0x39ff,單個寄存器長度為32位。每個寄存器除內(nèi)存地址不同外,讀寫權(quán)限、默認(rèn)值、大小都是相同的。其中,第0~12位表示保護(hù)范圍基址,指定受保護(hù)范圍下限。13~14位是保留位,第15位是讀使能保護(hù)位,當(dāng)該位被設(shè)置時,表示該寄存器中的基址和限制字段有效,禁止對它們之間的地址進(jìn)行讀取操作。第16~18位表示保護(hù)范圍限制位,指定受保護(hù)范圍的上限。第29~30位是保留位。第31位表示寫保護(hù)使能位,當(dāng)該位被設(shè)置時,表示該寄存器中的基址和限制字段有效,禁止對它們之間的地址進(jìn)行寫入和擦除操作。該位被清除時,基址和限制字段被忽略。
SPI范圍保護(hù)寄存器通過SPI根復(fù)合寄存器塊(RCRB)的SPI Host Interface內(nèi)存映射寄存器進(jìn)行配置。根復(fù)合寄存器塊是一組用于配置根聯(lián)合體設(shè)備的寄存器組。根聯(lián)合體設(shè)備是一種將處理器和內(nèi)存子系統(tǒng)連接到由一個或多個交換設(shè)備組成的PCI Express交換結(jié)構(gòu)。不同芯片組的根復(fù)合寄存器塊地址不同,可通過讀取位于LPC橋接器件的PCI配置空間內(nèi)偏移量為0xf0的根復(fù)合基址寄存器,確定根復(fù)合寄存器塊地址。
2?破壞SPI范圍保護(hù)寄存器機(jī)制
UEFI正常引導(dǎo)路徑即UEFI框架引導(dǎo)系統(tǒng)正常啟動過程。在該路徑中,UEFI框架構(gòu)建UEFI引導(dǎo)腳本,將包括SPI范圍保護(hù)寄存器值在內(nèi)的信息保存到閃存中。當(dāng)系統(tǒng)進(jìn)入到S3睡眠模式時,UEFI引導(dǎo)腳本通過SMM LockBox機(jī)制保存到SMRAM中;系統(tǒng)從S3睡眠模式喚醒時,引導(dǎo)腳本引擎解析引導(dǎo)腳本文件,將系統(tǒng)配置恢復(fù)到S3睡眠模式前狀態(tài)。如果在進(jìn)入S3睡眠模式期間更改UEFI引導(dǎo)腳本中SPI范圍保護(hù)寄存器的值,當(dāng)系統(tǒng)被喚醒時,SPI范圍保護(hù)寄存器的值就會被UEFI引導(dǎo)腳本中的記錄覆蓋,從而實現(xiàn)對SPI范圍保護(hù)寄存器值的篡改。
為使用引導(dǎo)腳本,需要知道SMM LockBox驅(qū)動程序如何將其存儲到SMRAM中,因此需對SMM LockBox驅(qū)動程序進(jìn)行逆向工程。從逆向源碼中獲得UEFI引導(dǎo)腳本地址后,根據(jù)該地址對UEFI引導(dǎo)腳本中SPI范圍保護(hù)寄存器的值進(jìn)行修改,最后觸發(fā)S3睡眠模式掛起,恢復(fù)篡改SPI范圍保護(hù)寄存器的值。
2.1?逆向S3恢復(fù)引導(dǎo)路徑
在不同結(jié)構(gòu)中,固件中的SMMLockBox驅(qū)動程序具有相同的LockBoxGUID(bd445d79-b7ad-4f04-9ad8-29bd2040eb3c)。因此,將實驗機(jī)固件加載到UEFITool中,然后搜索該GUID。UEFI Tool是一種可以確定SMMLockBox驅(qū)動程序位置的可視化工具[8],如圖1所示。
利用UEFITool找到實現(xiàn)SMMLockBox功能的DXE驅(qū)動程序,將其轉(zhuǎn)儲到磁盤中,加載到IDAPro并反編譯PE鏡像的入口函數(shù)。sub_77C()函數(shù)對 SMM LockBox 執(zhí)行初始化:
int?__fastcall sub_77C(EFI_HANDLE ImageHandle)
{
...
v1 = gBS->LocateProtocol(&gEfiSmmBaseProtocolGuid, 0,&SmmBaseProtocol);
v2 = 0;
if (v1 >= 0)
{
// 確定驅(qū)動程序是否被加載到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()注冊為回調(diào)函數(shù)
SmmBaseProtocol->RegisterCallback(SmmBaseProtocol,0xF9E9662B,sub_674, v4);
}
…
}
從代碼可知,驅(qū)動代碼利用EFI_SMM_BASE_PROTOCOL的InSmm()函數(shù)確定它如何加載驅(qū)動。SMM回調(diào)注冊則使用EFI_SMM_BASE_PROTOCOL的RegisterCallback()函數(shù)實現(xiàn)。調(diào)用EFI_SMM_SYSTEM_TABLE.SmmAllocatePages()函數(shù)完成為SMM LockBox數(shù)據(jù)列表條目分配內(nèi)存的工作,用于存儲引導(dǎo)腳本的副本,該地址來自 SMM 回調(diào)輸入。EFI_SMM_SYSTEM_TABLE.SmmAllocatePool()函數(shù)用于存儲引導(dǎo)腳本地址、大小以及 “LOCKBOXD”簽名等。
通過SMMLockBoxGUID和配置表開頭的常量簽名“LOCKB_64”,可以找到帶有雙鏈表頭的指針UEFISMM配置表,利用轉(zhuǎn)儲工具獲得SMRAM轉(zhuǎn)儲,如圖2所示。
從目標(biāo)機(jī)的SMRAM內(nèi)容轉(zhuǎn)儲結(jié)果可以看出轉(zhuǎn)儲成功。將轉(zhuǎn)儲結(jié)果加載到IDA中,從中可得到配置表信息。通過“SMST”簽名可在SMRAM中找到EFI_SMM_SYSTEM_TABLE。在EFI_SMM_SYSTEM_TABLE結(jié)尾,可發(fā)現(xiàn)UEFISMM配置表和指向EFI_CONFIGURATION_TABLE結(jié)構(gòu)數(shù)組的指針,地址為0xad34cdc8的列表中包含“LOCKBOXD”簽名的引導(dǎo)腳本信息結(jié)構(gòu),并可知道引導(dǎo)腳本的SMRAM副本位于0xad1c1000的地址,長度為0×7e12字節(jié)。
2.2?篡改SPI范圍保護(hù)寄存器的值
通過引導(dǎo)腳本位置對存儲在 SMM LockBox 中的引導(dǎo)腳本進(jìn)行讀和寫操作,從而修改PRx寄存器的值達(dá)到破壞SPI范圍保護(hù)機(jī)制的目的。首先,需要通過GUID查找EFI_CONFIGURATION_TABLE的VendorTable。函數(shù)smst_addr()可用于通過表頭簽名來查找EFI_SMM_SYSTEM_TABLE的地址。利用該地址找到VendorTable后,可以編寫定位UEFISMM配置表函數(shù)并解析它的數(shù)據(jù),確定啟動腳本表副本在SMRAM中存儲的位置。接著利用該函數(shù)可看到目標(biāo)計算機(jī)固件引導(dǎo)腳本的十六進(jìn)制轉(zhuǎn)儲。在該表最后可看到PR0-PR4寄存器的值(黃色代表寄存器,綠色代表寄存器的值),如圖3所示。
從轉(zhuǎn)儲結(jié)果得到PRx寄存器的值,利用disable()函數(shù)將PR0-PR4寄存器的值設(shè)置為零:
for (int i = 0; i < 5; i += 1)
{
if (addr == pr_regs[i].addr)
{
val = 0;
// 將PRx寄存器的值設(shè)置為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;
}
}
然后調(diào)用s3_sleep_with_timeout()函數(shù)觸發(fā)掛起-恢復(fù)動作,同時修改腳本文件表。最后,S3復(fù)位后再一次讀取PR0-PR4值,檢查PRx閃存寫保護(hù)是否被成功禁用。
{
if (s3_sleep_with_timeout(10) == 0)
{
// 得到當(dāng)前PRx 寄存器的值
if (pr_get(target, &rcrb_addr,
&pr0_val, &pr1_val, &pr2_val, &pr3_val,
&pr4_val) != 0)
{
goto _end;
}
// 檢查SPI保護(hù)是否被設(shè)置
if (pr0_val == 0 && pr1_val == 0 && pr2_val == 0 &&
pr3_val == 0 && pr4_val == 0)
{
ret = 0;
}
}
2.3?S3睡眠模式喚醒系統(tǒng)
最后,需要從S3睡眠模式喚醒Windows操作平臺。首先要判斷目標(biāo)計算機(jī)是否支持S3睡眠狀態(tài)。利用SetSuspendState()函數(shù)判斷電腦是否進(jìn)入睡眠狀態(tài),如果判斷為真,再利用SetWaitableTimer()Win32API函數(shù)中的fResume參數(shù),通過改變定時器狀態(tài)使系統(tǒng)退出睡眠狀態(tài)。
2.4?結(jié)果檢測
利用Intel開發(fā)的安全評估框架CHIPSEC對目標(biāo)計算機(jī)的寄存器初始狀態(tài)進(jìn)行檢測,得到結(jié)果如圖4所示。
從檢測結(jié)果可以看出,目標(biāo)計算機(jī)運(yùn)行正常,SPI范圍保護(hù)寄存器值不都為0,保護(hù)機(jī)制正常。
下面運(yùn)行本文中提出的方法程序檢驗是否破壞了SPI范圍保護(hù)機(jī)制,如圖5所示。
從程序結(jié)果中可知,PRx的閃存寫保護(hù)功能被禁止。
運(yùn)行CHIPSEC并驗證PR0-PR4寄存器值是否得到了修改,如圖6所示。
從結(jié)果可以看到,PR0-PR4的值都變?yōu)?。通過與寄存器初始狀態(tài)進(jìn)行對比,寄存器的值確實被篡改,證明本文提出方法的正確性。
3?結(jié)語
本文提出了一種篡改SPI范圍保護(hù)寄存器值的方法,實現(xiàn)對SMRAM中UEFI引導(dǎo)腳本中記錄的SPI范圍保護(hù)寄存器值的篡改。利用代碼實現(xiàn)S3睡眠模式的掛起—恢復(fù)動作,從而將寄存器值設(shè)置為0,達(dá)到了破壞該保護(hù)機(jī)制的目的。這種修改寄存器值旁路SPI范圍保護(hù)機(jī)制的方式,適用于絕大多數(shù)采用這種安全機(jī)制的計算機(jī)。分析可知,PRx寄存器值的設(shè)置方式是這種旁路攻擊的切入點。因此,需要對寄存器的設(shè)置過程加以保護(hù),才能避免攻擊者隨意對寄存器的值進(jìn)行修改。
參考文獻(xiàn):
[1]?房強(qiáng).基于固件文件系統(tǒng)的UEFI安全機(jī)制研究[D].成都:電子科技大學(xué),2016.
[2]?楊旭,駱祖瑩,韓銀和.基于Cache內(nèi)容替換的系統(tǒng)管理模式漏洞檢測方法[D].北京:北京師范大學(xué),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標(biāo)準(zhǔn)的龍芯3A平臺系統(tǒng)功耗分析[J].計算機(jī)工程與設(shè)計,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.