趙利軍 董莎莎 張沙石
(陸軍工程大學軍事理論創新與作戰實驗中心 江蘇 徐州 221000)
隨著嵌入式設備的廣泛使用,如何攻克嵌入式設備成為當前網絡空間作戰中的關鍵環節,為了能繼續持有攻擊主機的訪問特權,惡意程序必須較好地隱藏自己不被檢測工具發現。作為一種高級的隱藏技術,近幾年PC機上的陷門攻擊技術——Bootkit技術,得到了廣泛使用和發展。Bootkit技術是一種更高級的Rootkit技術,兩者的不同之處在于Bootkit將存儲位置從文件系統變為硬件存儲,并且在操作系統加載之前啟動。Rootkit修改操作系統內核,重裝系統可將其清除。Bootkit在加載操作系統之前啟動,因此獨立于任何操作系統。與傳統的Rootkit技術主要是在系統啟動時提升權限不同,Bootkit通過篡改內核及操作系統引導過程隱藏自身。
2007年研究人員IceLord(網名)發布的公開資料是可以找到的第一個Windows環境下的BIOS Rootkit[1]。由此,針對BIOS的陷門設計從一個技術構想變成了程序實體。同一年,Nitin Kumar和Vipin Kumar在Black Hat大會上呈現了一種名為Vbootkit的Bootkit攻擊技術,并成功突破Windows Vista系統。Vbootkit能夠篡改引導向量獲取執行權限,繞過啟動管理器的簽名機制。通過Hook Windows Vista系統啟動文件入侵操作系統內核[2]。在2008年,Wenbin Zhen等[3]發布了Tophet.a,一款基于篡改OSLoader的Bootkit技術。該技術可使攻擊者獲取系統控制權并通過篡改boot.ini文件中的語法格式將控制權轉換到攻擊者的驅動。同年的Black Hat大會上,C.Miller通過嗅探MacBook電池中內建的電量控制器經I2C收到的數據,對電池的嵌入式微控制器固件進行修改,可以使電池過度發熱甚至起火,并能夠在獲得微控制器的控制權后對系統進行配置[4]。Lee等[5]提出了劫持ARM Linux嵌入式設備的方法,該方法借鑒通用計算機下的Linux系統常用劫持方案,將系統調用表或者系統調用函數進行修改,并指向自己的惡意代碼,從而實現控制流的轉移,達到劫持目的。在文獻[6]中闡述了破解Netgear NTV300電視機頂盒的方法。文中作者dump下Netgear NTV300中的固件映像,通過Binwalk解析固件組成、使用的壓縮算法等,并使用IDA的靜態分析功能,最終實現了對該設備的漏洞注入和遠程控制。2013年,Ang Cui等[7]介紹了惠普HP-RFU(遠程固件升級)激光打印機固件修改漏洞,通過打印含有特殊命令的文檔來隱蔽地修改打印機的固件,進而獲得該打印機的控制權,并采用靜態分析方法對其中使用的第三方庫分析發現超過80.4%的固件程序存在zlib漏洞。文獻[8]對惠普RFU漏洞進行了驗證,攻擊者通過MS Office Word、Adobe PostScript等標準的打印文檔向任意打印機中注入惡意代碼和命令,使用這種攻擊途徑可以向打印機發送修改后的固件。2015年,李成林[9]針對目前主流殺毒軟件對KiFastCallEntry掛鉤提出了躲避方案,提出了改進型SSDT掛鉤,該方法不再直接修改SSDT分發表里的函數入口地址,而是在函數體的內部進行修改。2016年,馮培鈞等[10]在“一種新型 Linux 內核級 Rootkit 設計與實現”一文中設計并實現了一種新型Linux內核級Rootkit,該Rootkit能夠實現后門提權、進程隱藏及文件隱藏等功能,并能繞過當前主流的Rootkit檢測工具的檢測。2017年,李揚等[11]提出一種基于硬件虛擬化的內核Rootkit技術,該技術利用Intel VT-x硬件虛擬化技術將客戶系統(Guest OS)遷移到VMM之上運行實現Rootkit。
但是,對于一個新的嵌入式設備,多數的陷門設計技術都難以在有限的時間內設計出來,設計的陷門通用性也較差,無法部署到不同目標設備上。為此,本文通過研究嵌入式設備的啟動過程,建立涵蓋不同啟動流程異同點的、陷門模板化設計框架,為設計具有一定程度通用性的陷門提供依據。
嵌入式設備的軟硬件結構特點及啟動過程的差異性嚴重影響陷門的設計效率,人們可以針對不同設備,進行分析和設計符合需求的陷門。但本文嘗試引入陷門設計的模板化框架,旨在為提煉出一種具有一定程度通用性的、適用于主流嵌入式設備的陷門設計提供方便。
首先,我們對各種不同的嵌入式設備啟動流程進行分析,歸納它們的相同點與差異性,建立統一的啟動流程。
存儲芯片不同會造成Bootloader引導的差異;Bootloader不同會造成內核啟動流程的差異;不同內核加載過程也存在較大差異;不同文件系統掛載的機制也有區別。啟動流程分析主要是對這些差異性進行總結和歸納。
Bootloader的啟動過程可以是單個階段的,也可劃分為多個階段,嵌入式設備下一般為二階段的啟動過程,分Stage1和Stage2兩部分啟動。二階段的Bootloader啟動流程如圖1所示。

圖1 Bootloader啟動流程
導致Bootloader啟動方式差異的因素還有內核掛載文件系統機制的差異。以Linux內核為例,Linux內核中包含兩種掛載早期根文件系統的機制,即initrd機制和initramfs機制。
initrd是一個功能完備的小型根文件系統,是一種啟動早期用戶空間處理流程的老式方法,它通常包含一些指令,用于在系統引導完成之前加載一些特定的設備驅動程序。為了使用initrd的功能,大多數架構的引導加載程序會將initrd鏡像傳遞給內核。常見的場景是,引導加載程序先將壓縮過的內核鏡像加載到內存中,接著將initrd鏡像加載到另一段可用內存中。如圖2所示。

圖2 initrd機制啟動流程
在這個過程中,引導加載程序負責在將控制權轉交給內核之前,將initrd鏡像的地址傳遞給內核。具體的機制取決于架構、引導加載程序和平臺的實現。然而,內核必須知道initrd鏡像的位置才能夠加載它。當內核引導時,它首先會檢測內核命令行中是否包含root=參數并指定一個ramdisk(比如root=/dev/ram0)。然后,將這個壓縮的二進制文件從內存中的指定位置復制到一個合適的內核ramdisk中,并掛載它作為根文件系統。與PC機上Linux內核會卸載initrd,嘗試掛載另一個文件系統作為其根文件系統不同,這類系統中唯一的根文件系統就是ramdisk,在整個系統初始化完成后,initrd就會成為最終的根文件系統。
與initrd是一種基于RAM的塊設備不同,initramfs是一種基于RAM的內存文件系統。initramfs在編譯內核的同時被編譯,并與內核連接成一個文件。在引導階段它與內核同時被Bootloader加載到RAM中。而initrd是另外單獨編譯生成的,是一個獨立的文件,它由Bootloader單獨加載到RAM中內核空間外的地址。其啟動過程如圖3所示。

圖3 initramfs機制啟動流程
不同機制下根文件系統的掛載方式不同,如圖4所示。

圖4 根文件系統掛載方式示意圖
根據上述分析的Bootloader啟動流程和內核掛載文件系統機制的差異,對啟動流程的共性和特性進行歸納,得到Linux內核嵌入式設備啟動流程的一般化描述,如圖5所示。

圖5 嵌入式Linux啟動流程
圖中①與①2代表啟動過程中不同的執行路徑,其中①表示不同設備之間啟動過程中的共性階段,①2表示不同設備之間啟動過程的差異性階段。同理,②與②2、③與③2、④與④2分別代表不同設備系統啟動過程中不同的執行路徑。
Linux系統啟動流程中,將涉及陷門模塊設計的執行階段劃分出來,隔離成黑盒,得到粗粒度的Linux啟動流程,如圖6所示。

圖6 隔離涉及陷門模塊設計執行階段后的啟動流程圖
圖6中,黑盒1和黑盒2屬于引導代碼級陷門組件模塊。黑盒3屬于內核級陷門組件模塊,黑盒4為文件系統級陷門組件模塊。其中,除黑盒1外,其他黑盒內部均存在路徑分支,陷門的設計需要依據設備的實際執行路徑進行考慮。建立的嵌入式Linux啟動模型如圖7所示。

圖7 嵌入式Linux啟動模型
由于Bootloader Stage2、加載initrd、內核自解壓與搬移、解壓與搬移initrd操作在某些設備啟動過程中不存在,因而用虛線框表示。陷門設計時,這些階段對應的陷門組件需要依據實際設備的啟動過程和陷門需求進行組合。
高級語言中模板是根據參數類型生成函數和類的機制(有時稱為“參數決定類型”)。通過使用模板,可以只設計一個類來處理多種類型的數據,而不必為每一種類型分別創建類。借鑒高級語言中模板函數、模板類等思想,提出陷門模板化技術。
陷門模板可以比作一個生成陷門攻擊代碼的“模子”,是對適用于某一類型設備(功能相同、結構相似)的攻擊方式的抽象化概括,一個陷門模板允許根據具體的設備分析結果填寫某些參數,將模板實例化成針對某個特定設備的陷門。陷門模板化設計方法能夠實現部分環節的自動化、減少人工工作量,從一定程度上降低了陷門開發的難度,提高了陷門設計的效率。結合啟動模型,模板化陷門設計框架如圖8所示。

圖8 模板化陷門設計框架
整個陷門模板分為BootLoader級組件、內核級組件和文件系統級組件,分別對應引導階段、內核啟動階段、文件系統掛載階段的操作。其中文件系統級組件可單獨實現陷門攻擊,也可與其他兩個組件配合使用。陷門模板留有拼接各組件的配置接口,可根據實際對目標設備的分析結果進行擴展。每個組件也以可配置的形式存在,可根據陷門設計需求實例化為某個特定功能的組件。
陷門功能組件中又分別存在不同部件,不同部件功能也相對獨立,部件間一般需要互相配合完成特定功能。部件內部也留有“個性化”的配置接口,可根據對實際設備的分析填寫相應的參數。特別說明路徑選擇部件主要負責根據設備啟動階段的判別信息,選擇陷門設計所需的部件。
本文提出的模板化陷門設計框架適用于跨平臺的陷門設計。根據陷門框架設計的陷門模板如下所示:
# Trapdoor Paramaters Start #
Para0, 0x12345678
Para1, 0x12345678
……
Paran, 0x12345678
# Trapdoor Paramaters End#
# Bootloader Stage Trapdoor Start #
……
# Kernel Stage Trapdoor Start #
……
# Trapdoor Start #
……
# Trapdoor End #
# Kernel Stage Trapdoor End #
# Bootloader Stage Trapdoor End #
陷門模板代碼的開頭為各模塊可配置的參數區。陷門代碼的實體部分是一個嵌套的實現過程,與陷門代碼逐級感染設備的流程想匹配。陷門最外層為最先執行的陷門代碼模塊,即引導級陷門代碼模塊。第二層為內核級陷門代碼模塊。最里層為陷門實際需要完成的功能模塊,如網絡劫持、文件下載、破壞設備等,可根據實際設備選擇。每一層的執行任務完成后都會由下一層負責清理上一層陷門代碼執行留下的痕跡,達到陷門隱蔽的效果。
從陷門設計框架可知,陷門結構也可能只由文件系統級陷門模塊和陷門實際功能模塊組成。由前面提出的可重構陷門設計方法可知陷門結構中各模塊的組合以及各模塊內部不同部件的組成,都可根據實際需求進行調整。
陷門功能需要匯編語言實現,因此陷門模板的實現只適用于某個特定架構。以ARM架構為例,闡述陷門模板具體實現。由于完整代碼太長,將陷門模板的實現過程進行分塊說明。
陷門模板中的可配置參數保留區分為全局參數區和局部參數區。全局參數區主要是一些執行各模塊時必須配置的參數,如Bootloader級模塊和內核級模塊必須配置內核鏡像加載的起始地址及結束地址。局部參數區主要用作陷門各模塊內部件執行時的參數配置,如Bootloader級模塊陷門寄生加載部件需要配置陷門加載的地址和大小、碎片重組部件需要配置碎片數目和各碎片加載的地址及大小??膳渲脜祬^的實現如下:
# 全局參數區 #
.equ Para0, 0x30008000
//內核加載到內存的起始地址
.equ Para1, 0x30008128
//內核壓縮數據起始地址
.equ Para2, 0x12345678
……
.equ Paran, 0x12345678
# Bootloader Stage Trapdoor Start #
# 局部參數區 #
MSAK_Parameter:
.word 0xefefefea
//陷門起始地址
.word 0xefefefeb
//陷門結束地址
……
RecoverPara_MSAK:
//陷門控制流劫持可能覆蓋引某條關鍵指令
.word 0xefefeff1
//將需要恢復的指令保存于此
.word 0x00080000
……
“程序?!笔潜4婧突謴拖蓍T劫持控制流后破壞的設備運行時上下文信息的區域,一般位于每個陷門模塊和模塊部件的開頭和結尾處。具體實現如下:
# 程序棧 #
b SelfDefinationStack
.word 0x11111111
.word 0x00001110
……
.word 0x0000111f
.word 0x00001120
SelfDefinationStack:
str r0, [pc, #-76]
//pc-76為程序棧的第一個數據地址
str r1, [pc, #-76]
……
str r14, [pc, #-76]
mrs r0, cpsr
str r0, [pc, #-80]
mrs r0, spsr
str r0, [pc, #-84]
……
RelocationStack:
ldr r0, RelocationStack
//獲取程序棧的位置
sub r0, pc, r0
sub r0, r0, #0xc
ldr r14, SelfDefinationStack
add r14, r14, r0
ldr r0, [r14, #-4]
//恢復保存的寄存器數據
msr spsr, r0
ldr r0, [r14, #-8]
msr cpsr, r0
ldr r14, [r14, #-12
……
ldr r0, [r14, #-68]
ldr r1, [r14, #-64]
數據池不僅可以用來存儲下一個模塊的代碼和數據,也可作為當前模塊需要傳遞給下一個模塊的數據保存區。數據池的實現較為簡單,但是陷門模板設計中不可或缺的重要部分,具體形式如下:
B Lable:
Data_Buffer:
.word 0x11111111
.word 0x11111111
.word 0x11111111
……
.ascii
"xffx5fx2dxe9x00x60x0fxe1x40x00x2dxe9x00x60x4fxe1x40......"
Lable: ……
其中第一部分為模塊間傳遞的數據區,.ascii 為某個shellcode形式的陷門模塊。
由于嵌入式設備“客制化”的生產模式,大多數情況下難以在給定的時間內設計出針對一個新的嵌入式設備的陷門,設計的陷門通用性也較差,無法部署到不同目標設備上。本文通過研究嵌入式設備的啟動過程,建立涵蓋不同啟動流程異同點的,搭建了陷門模板化設計框架,最后通過勢力說明了陷門模板的設計方法。本文提出了框架為設計具有一定程度通用性的陷門提供了依據。