路子聰,徐開勇,郭 松,肖警續
(信息工程大學,鄭州 450000)
Android是基于Linux內核的開源操作系統,操作系統的安全性是Android安全體系中非常重要的一部分。內核是操作系統中最重要的組成部分,目前,針對Android系統內核的攻擊日益增多。對于Android系統內核而言,它的安全威脅一方面是繼承Linux 系統本身的漏洞,另一方面是由于Android系統本身不夠完善[1]。有些學者對Android內核漏洞進行挖掘[2],但由于Android生態系統的復雜性,內核漏洞的修補通常需要很長的周期,這意味著內核防御技術對于Android來說至關重要。Android4.3版本之前,安全模型部分是基于應用沙盒的概念,系統可以為每個應用程序提供一個自己的沙盒并分配一個獨有的UID(User IDentification),使每個應用在自己的沙盒中運行來保證應用的資源獨立存儲。Shabtai 等[3]提出將安全增強型 Linux(Security-Enhanced Linux, SELinux) 植入到Android 平臺中,限制應用對系統資源的訪問,增強Android 系統安全。從Android 4.3 版起,SELinux開始用于進一步定義 Android 應用沙盒的邊界。雖然SEAndroid(Security-Enhanced Android)對基于應用程序的攻擊有很好的防御效果,然而SEAndroid卻依賴于操作系統內核完整性的假設。如果Linux內核受到威脅(或許還有未知的漏洞),則Android安全機制的SE (Security-Enhanced)可能被禁用并且效果不佳[4]。
有學者對在移動平臺上增強Android系統內核的安全性進行了研究。針對Android設備大部分使用ARM處理器,利用ARM的安全擴展TrustZone[5]可以用來保護系統[4,6-10],盡管TrustZone是基于硬件進行數據保護,但其攔截能力的局限性使得它不適合作域內反思和域內保護。這就是Hypervision[4]在操作系統上作出顯著改變的原因,但其在模式切換的消耗大,導致有一定局限性。
利用硬件輔助虛擬化技術可以用來保護系統安全[11],許多研究人員利用虛擬化技術來保護ARM平臺上的系統安全。使用ARM上的虛擬化擴展,提出了Xen on ARM[12]、KVM(Kernel-based Virtual Machine) for ARM[13]等hypervisor;但是, Xen和KVM需要一個主機系統來處理一些重要的中斷,這導致可信計算基 (Trusted Computing Base,TCB)包含主機系統的代碼庫,而系統的TCB越大就越脆弱,并且由于它們對性能影響較大不滿足移動設備低功耗便捷的要求。L4Android[14]對每個場合的Android系統進行隔離,但對系統的攻擊仍無法阻止。DroidVisor[15]對內核的靜態關鍵對象進行完整性保護,并對進程和模塊進行rootkit檢測,但它無法檢測對動態的熵池資源進行修改的rootkit。
針對以上問題,本文提出了一種利用ARM硬件輔助虛擬化的Android內核動態完整性度量 (Dynamic Integrity Measurement of Android,DIMDroid)方案。通過在任意時刻對Android內核的各種重要資源的值和數據結構進行動態完整性度量來保證Android內核的安全性。
要完成對Android內核進行完整性度量的目標,結合相關因素和面臨的問題要考慮到以下幾個方面的挑戰:
1)度量模塊的位置。如果度量模塊與Android內核位于同一特權層,則進入Android內核的攻擊可能會對度量模塊造成一定威脅,所以要設置好度量模塊的位置以解決度量模塊與被度量Android內核的隔離問題。
2)度量對象的選取與重構。度量對象必須能表達當前Android內核的完整性信息,同時在Android內核外部對其實施動態度量,所以存在度量層與被度量內核之間的語義鴻溝問題。通過在度量層對選取的Android內核度量對象進行重構來解決該問題。
3)度量模塊自身的安全性。對Android內核進行動態度量,首先要保證度量功能模塊自身的安全啟動并保證在運行時不受到在Android中獲得root權限的惡意代碼的攻擊。
DIMDroid設計利用了ARM平臺的虛擬化技術,為了便于理解,將簡單介紹ARM平臺上的虛擬化技術的相關背景。
最近的ARMv7-A架構在ARM處理器上引入了虛擬化擴展。具體來說,引入了一種稱為hyp模式的新處理器模式,它比現有的非安全狀態中的svc模式擁有更高的特權級別。Android操作系統和應用程序可以不經過任何修改就能分別運行在現有的svc模式和usr模式下。具有虛擬化擴展和安全擴展的ARM處理器的架構如圖1所示。

圖1 ARM處理器的架構
ARM虛擬化擴展使用兩階段頁表轉換來更好地控制客戶的虛擬內存。Stage-1頁表由客戶操作系統維護,客戶操作系統可利用Stage-1頁表將客戶虛擬地址(Virtual Address,VA)轉換為中間物理地址(Intermediate Physical Address,IPA)。將IPA轉換為物理地址(Physical Address,PA)的Stage-2頁表由虛擬機管理程序維護,并且對客戶操作系統保持透明。ARM 虛擬化擴展必須與大物理地址擴展和安全擴展同時使用。如表1所示大物理地址擴展的bit[7:6]為Stage-2的訪問權限位HAP[2:1],通過對Stage-2頁表項(Page Table Entry,PTE)中屬性位的適當配置,客戶操作系統的內存訪問將處于管理程序的控制之下。

表1 Stage-2訪問權限控制
為了實現對Android內核的動態度量,利用ARM平臺下的硬件輔助虛擬化技術,設計了如圖2所示的DIMDroid體系架構。DIMDroid主要實現了度量模塊與Android內核的隔離,利用度量代理對Android內核中的度量對象進行重構和動態度量。此外,還通過基于硬件的信任鏈啟動保護和基于內存隔離的運行時保護來對DIMDroid自身安全進行保證。

圖2 DIMDroid體系架構
其中,DIMDroid的度量模塊置于hyp模式下(以下簡稱度量層)。Android操作系統控制第一階段頁表,DIMDroid控制第二階段頁表,進行第二階段地址轉換的頁表對Android 操作系統是透明的。DIMDroid通過Stage-2頁表將其和度量代理模塊設置為內核不可訪問并將其聲明為直接內存訪問 (Direct Memory Access,DMA)緩沖區,保證DIMDroid能夠從Android內核外部進行系統運行時的完整性度量,解決了度量模塊與被度量系統的隔離問題,降低了度量軟件模塊遭受攻擊的可能性。
基準庫提供度量的基準值,其中的主要內容為靜態度量對象的Hash值與除子集約束對象外的動態度量的約束值,同時采用對基準值進行AES(Advanced Encryption Standard)加密保證基準值的安全性,為了防止AES密鑰的泄露,將其存儲在Trustzone中。基準庫是在系統啟動時構建的,此時的系統由Trustzone保證了基于硬件的可信鏈且不聯網,即基準庫的構建是在系統可信條件下進行的,同時避免其受到網絡攻擊。
DIMDroid的度量代理模塊位于svc模式下,通過System.map文件獲取度量對象的虛擬地址并將其傳給度量模塊,并在度量層下進行度量對象的語義重構并進行完整性分析。
為了使度量對象全面描述Android內核運行時的完整性,本文從Android內核的組成運行原理和內核惡意軟件的攻擊面等方面確定系統運行中度量對象的選取。
在分析加載Android操作系統內核的各種關鍵組成元素后,發現例如基本只讀數據段、內核代碼段、系統調用表、中斷描述符表、異常向量表、內核模塊代碼等數據結構在Android系統運行中是靜態不變的,一旦發現這些數據結構被篡改、發生變化,系統就不會以預期的方式運行。例如kbeast、enyelkm等rootkit可以篡改中斷處理函數和系統調用表中的表項來執行惡意代碼,因此這些靜態數據結構的完整性在Android系統運行過程中至關重要。
與此同時,例如Android內核中進程鏈表、模塊鏈表、初始化數據段、熵池資源等數據結構在Android系統運行過程中是動態變化的。考慮到某些直接對象操作(Direct Kernel Object Manipulation,DKOM)的rootkit,它們可以對某個模塊從模塊鏈表隱藏或者對某個進程從進程鏈表中隱藏,例如對ps、top等系統服務程序篡改或者進行文件替換,當監控軟件或程序調用這些服務程序查看進程信息時過濾掉了惡意軟件想要隱藏的進程,從而實現惡意軟件對內核的攻擊,但在這些內核數據結構動態變化中它們滿足一定的特征約束。例如,Android內核中的進程滿足running_list?all-tasks,即在運行鏈表running_list中的元素全都包含在進程鏈表all-tasks中,或者all-tasks==ps-tasks,即所有的進程都應該可以用ps系統服務程序觀測到;adore-ng和wipemod等rootkit可以實現惡意模塊隱藏和惡意進程隱藏,即不滿足進程鏈表或模塊鏈表的子集特征約束; Android內核使用偽隨機數生成器(Pseudo Random Number Generator,PRNG)生成其他安全關鍵應用程序所需隨機數,為了確保PRNG生成的數字是偽隨機的,每次使用攪拌函數更新熵池的內容字節從熵池中提取,攪拌函數使用的多項式系數為在struct poolinfo數據結構的整數字段,這些整數字段的取值滿足一定的邊界約束,具體來說poolinfo.tap1∈{26, 103}, poolinfo.tap2∈{20, 76},poolinfo.tap3∈{14, 51},poolinfo.tap4∈{7, 25},poolinfo.tap5==1 等。
根據這些數據結構動態變化的特征,本文可將它們分為四種約束:固定長度約束、固定取值約束、子集約束和邊界約束,如系統的最大線程數max_threads屬于固定取值約束,進程、模塊等屬于子集約束,熵池結構屬于邊界約束等。
通過以上分析在Android系統運行過程中,內核度量對象包括靜態度量對象和動態度量對象兩大類。
如果將度量軟件直接置于Android內核中,則與Android內核運行在同一個特權級,易受到惡意軟件的攻擊。而將度量軟件置于hyp模式下,實現了度量軟件與被度量的Android內核的分離,但hyp模式下的度量模塊獲取到的信息為底層的二進制信息,無法獲取內核級的語義信息。因此,分析之前需要根據內核結構知識和底層的二進制信息在度量層進行度量對象的重構。
首先,由于Android內核是基于Linux內核的,可以通過內核提供的system.map 文件獲取度量對象的虛擬地址,system.map 文件保存了成千上萬個內核導出符號和其對應的虛擬地址。其中也包括本文在上一節分析得到的度量對象及其虛擬地址,例如內核代碼段地址、初始化數據段地址、異常向量表虛擬地址、系統調用表虛擬地址、init進程地址等。由這些虛擬地址經過兩階段地址轉換過程可以得到度量對象的物理地址,根據Android內核存儲這些度量對象的方式(如鏈表、數組、樹等),度量對象的類型和各個字段的偏移可以在度量層重構這些度量對象,方便對其進行分析。
其中經過兩階段地址轉換得到的物理地址為該度量對象在物理設備中的起始地址,度量對象的類型為系統定義的鏈表、整型、長整型或者結構體等,度量對象中字段的偏移為該字段相對于結構體起始地址的偏移量。具體分析過程如下:
輸入 度量對象的虛擬地址Va、中間地址Ipa、起始物理地址Pa、度量對象的類型定義SC[]、字段偏移量FS[]、內核符號表文件System.map;
輸出 靜態對象列表SML[]或動態對象列表DML []。
Va[]=Request_Proxy (System.map);
while (Va[i]!=0)
Ttbr=Read_Guest_TTBR();
Ipa=Translate_Stage1_Guest(Ttbr, Va);
Pa=Translate_Stage2(Ipa);
if (Va[i]∈codesection|datasection|IDT
|System_call|others)
//靜態度量對象重構
ML[]=getcode(Pa,SC[i]);
//內核代碼段
ML[]=getdata(Pa,SC[i]);
//只讀數據段
ML[]=getSys_call(Pa,SC[i]);
//系統調用表
ML[]=getIDT(Pa,SC[i]);
//中斷向量表
ML[]=getOthers (Pa,SC[i]);
//異常向量表、全局描述符表等其他靜態對象
return SML[i];
else if (Va[i]∈init_task|module_set|others)
//動態度量對象重構
ML[]=getTask(Pa,SC[i],FS[i]);
//進程
ML[]=getMoudle(Pa,SC[i],FS[i]);
//模塊
ML[]=getOthers(Pa,SC[i],FS[i]);
//文件、線程數等其他動態對象
return DML[i];
end if
end while
由于內核代碼、內核初始化數據、系統調用表和中斷向量表等靜態度量對象的內容是連續分布的,根據虛擬地址很容易得到,故重構分析過程相對單一,本文不再詳細介紹,重點討論動態度量對象的重構分析方法。下面以分析Android系統的進程為例說明度量對象的重構分析的基本思想。
如圖3所示,單個進程的信息存儲在該進程的任務結構task_struct中,Android內核中的所有進程通過一個雙向循環鏈表all-tasks來前后鏈接,單個進程的信息存儲在進程結構體task_struct中。為了獲取全部進程信息,需要某個進程的信息,0號進程init_task是系統所有進程的父進程,即進程鏈表的鏈表頭。通過在 system.map 文件查詢標識為init_task的符號,找到數據結構 init_task 的虛擬地址Va,經過兩階段地址轉換獲取的物理地址Pa即為init_task對應task_struct結構的首地址,根據字段類型定義與地址偏移量就可獲得例如pid、comm和tasks等對應的語義內容,存入pi[],pi[]即為在度量層重構的該進程信息,再以該tasks字段的值為下一個 task_struct 的虛擬地址繼續循環該過程,直到發現某個進程 tasks 的值和init_task 的虛擬地址值相同時停止該過程,由于系統的進程鏈表是一個循環鏈表,可知當循環結束時已經遍歷到了其余所有進程。

圖3 在度量層對內核進程視圖重構
與此同時,調度程序使用一個名為run-list的鏈表來調度進程以執行,采用與分析進程鏈表一樣的方法分析runqueues結構體,將此時在CPU上運行隊列上所有就緒進程信息存入pr[],將得到的pi[]與pr[]存入DML[]。
因為在系統中的進程需要滿足running_list?all-tasks的約束關系,分析過程中則重點分析pr[]中的進程及其字段的元素是否全部包含在pi[]中。若滿足該約束,即進程滿足子集約束,此時進程無篡改。反之,系統進程被篡改,記錄篡改日志并報告系統隱藏的進程。
DIMDroid的度量步驟如下:
1)DIMDroid在度量時間點時刻進行一次完整性度量。度量點的選取采用隨機化時間算法得到,保證系統度量的隨機性。完整性度量首先在度量層進行度量對象的重構。具體來說,DIMDroid通過度量代理模塊獲取度量對象的虛擬地址,度量代理模塊訪問Linux內核提供的System.map文件獲取度量對象的虛擬地址VA。然后,將該虛擬地址傳遞給度量模塊后,由度量模塊使用被度量系統的第一階段頁表結構獲取VA對應的中間物理地址IPA;接著度量模塊利用DIMDroid控制的第二階段頁表結構獲取IPA對應的物理地址PA;最后,根據度量對象的物理地址、類型定義與各個字段的偏移重構該度量對象。
2)判斷度量對象為靜態對象或者動態對象并對其進行完整性度量分析。若為靜態對象的度量需要進行Hash后進行AES加密與基準庫的基準值進行一致性比對,本文采用安全哈希算法 (Secure Hash Algorithm,SHA1)來計算對象的Hash值。動態對象的度量根據其相應的約束進行區分驗證。若動態對象需要滿足例如進程、模塊等的子集約束,則需要同時構建兩個集合列表,例如驗證進程的完整性時構建pi[]與pr[]集合列表,通過這兩個列表是否滿足子集約束判斷該動態對象的完整性;如果動態對象滿足的約束為其他約束,則需將該度量動態對象鏈表長度或者相關內容與基準庫中存儲的固定長度約束值、固定取值約束值或者取值邊界范圍進行對比判斷該動態對象的完整性。若度量對象滿足對應的約束,報告系統的完整性;若不滿足則及時報告系統對應關鍵內核對象的篡改情況并記錄日志中。
DIMDroid的完整性度量的基本過程如圖4所示。
DIMDroid處于hyp模式中,在普通區域對資源擁有最高的訪問權限,對處于svc模式中的Android內核進行動態度量,因此,DIMDroid自身的安全至關重要。DIMDroid建立基于硬件的信任鏈啟動保護和基于內存隔離的運行時保護,同時,DIMDroid使用簡單易懂的度量策略,方便進行形式化驗證。

圖4 DIMDroid的完整性度量過程
在實現中,本文使用加載時完整性檢測來建立基于硬件的信任鏈。也就是說,TrustZone首先驗證bootloader的完整性,然后由bootloader驗證內核映像的完整性。DIMDroid所需的數據對象和資源為內核初始化的一部分,且在內核啟動任何進程之前完成其初始化。在DIMDroid初始化結束時,通過配置Stage-2頁面表,使其自身與內核隔離,以便內核在此之后不再擁有對DIMDroid的訪問控制權限。該過程實現的細節如圖5所示,灰色部分為系統的TCB。
步驟1 DIMDroid被組裝到內核映象中并由bootloader加載。在TrustZone驗證bootloader的完整性后,bootloader進入非安全狀態中的hyp模式,將壓縮的映象加載到內存中。
步驟2 設置hyp向量基址寄存器(HYP Vector Based Address Register, HVBAR)為異常向量。切換到svc模式中,解壓內核映象并啟動內核初始化。內核完成自己的地址空間設置后,準備好分離DIMDroid所需的所有資源。
步驟3 通過Trustzone安全保護技術驗證DIMDroid在內核中的度量代理模塊后加載該模塊。具體來說,內核分配一個連續的物理內存區域作為DIMDroid的內存空間,例如存儲Stage-2頁表、DIMDroid的代碼和數據部分。內核將未壓縮的DIMDroid復制到分配的區域中,并使用具有三級翻譯的長描述符轉換表格式來配置定義從IPA到PA的標識映射的Stage-2頁表。 Stage-2頁面表不映射由內核為DIMDroid及其度量代理模塊事先分配的內存區域。盡管如此,由于當前的ARM虛擬化擴展不支持I/O虛擬化,惡意內核可能會發起DMA攻擊來侵入虛擬機管理程序空間。為了避免由于內核對該區域的良性訪問(例如由于內存管理)而導致的異常,該區域被聲明為DMA緩沖區,以致未損壞的內核不會試圖釋放或訪問它。
步驟4 發出一個hypervisor調用進入hyp模式。DIMDroid通過將HCR.VM設置為0x1來啟用Stage-2轉換,并將虛擬化轉換表基址寄存器(Virtualization Translation Table Base Register, VTTBR)設置為物理地址步驟3中由內核事先設置的Stage-2頁表的根。
步驟5 設置HVBAR為異常向量返回到svc模式,恢復內核初始化。從此時起,所有的內核和用戶空間代碼執行都使用兩級地址轉換,因此,內核被排除在運行時TCB之外,大大降低了TCB的大小。DIMDroid能夠通過Stage-2頁面表在運行時從內核中保護自己。

圖5 加載DIMDroid過程
本文實現了DIMDroid原型,實驗環境是使用Intel Core i5- 3210M CPU @ 2.50 GHz處理器和8 GB主內存的PC上的Linux Ubuntu。在這個平臺上,本文搭載了ARM FastModels(ARM,2011),FastModels是精確、靈活的ARM IP的程序員視圖模型,允許芯片可用之前開發諸如驅動程序、固件、操作系統和應用程序等軟件,它可以全控制模擬,包括分析、調試和跟蹤ARM IP。本文使用FastModels搭載支持ARM虛擬化擴展的Cortex-A15x1處理器模擬平板電腦,在平板電腦中運行植入DIMDroid的Android5.0進行功能測試和性能測試,功能測試的目的在于檢測強制訪問控制機制能否有效執行,性能測試的目的在于測試系統的性能損耗。
本實驗針對現有Android系統的rootkit進行測試,在5個rootkit中:前兩個修改了syscall_table子程序的若干字節來實現攻擊;第三個修改了系統的異常向量表;第四個使用了inline hook技術攔截了proc_lookup 函數,執行惡意代碼實現模塊和進程隱藏;第五個對Android系統的熵池資源進行攻擊,使得用于從池中提取字節的算法部分無效。
DroidVisor[15]也是利用硬件虛擬化對Android內核進行監控,使用DIMDroid與DroidVisor來對運行中的Android內核進行動態度量,結果如表2所示。
由度量結果可以看出,無論是針對系統調用表、中斷調用表一類的內核靜態度量對象篡改還是對進程鏈表、熵池資源等動態度量對象修改的rootkit都可以被檢測出來,DIMDroid度量方法能夠有效執行。DroidVisor不能夠檢測到rootkit 5是因為沒有對Android內核的動態的熵池資源作完整性保護,DIMDroid可以利用熵池資源須滿足的邊界約束對rootkit 5進行檢測。

表2 Android系統內核遭受rootkit攻擊后的度量
為了判斷DIMDroid方法對Android系統的性能影響,本文采用了安兔兔測評(AnTuTu Benchmark)軟件,它是專門給Android設備手機、平板電腦評分的專業軟件。比較使用與未使用DIMDroid度量的性能指標來進行測試,性能指標主要選取幾個現階段主流的選項:RAM速度、CPU浮點計算性能和CPU整型計算性能。使用安兔兔軟件測試DIMDroid度量內核100次,并取平均值。性能損耗比率為采用DIMDroid度量的性能指標項分值與未采用DIMDroid度量該指標項分值之差占未采用該指標項的百分比,結果如表3所示。

表3 使用安兔兔測試DIMDroid結果
由于本文實驗在FastModels上進行測試,不能精確地模擬ARM處理器,但可以得到性能損耗比率。由表3可知,使用DIMDroid與未使用DIMDroid相比有一定性能損耗,但在可接受范圍內,說明此方法對保證Android內核動態完整性有一定借鑒意義。
本文介紹了一種在ARM硬件虛擬化上利用動態度量來保護Android內核實時完整性的方法DIMDroid。該方法通過分析Android內核的運行機制和被攻擊對象得出了內核中哪些元素影響了Android內核的完整性,并在hyp層對內核中的度量對象進行重構后分析內核的完整性;與傳統方法不同,本文的方法是可信的,因為它與度量的Android內核進行了隔離,并通過基于硬件的信任鏈啟動保護和基于內存隔離的運行時防護來保證DIMDroid自身的安全。本文的實驗表明,通過與其他保護方法結果的比較表明,DIMDroid在Android完整性驗證上的綜合性能更好,但DIMDroid沒有突破一些攻擊,例如有些攻擊不對內核關鍵數據結構進行篡改實現權限提升、修改控制流等。接下來將通過對內核級的rootkit進行數據特征分析,進而完善DIMDroid度量內核完整性的準確性。