馬曉凱 楊哲慜
(復(fù)旦大學(xué)軟件學(xué)院 上海 201203)
基于安卓系統(tǒng)的代碼隱藏類規(guī)避技術(shù)檢測(cè)框架
馬曉凱 楊哲慜
(復(fù)旦大學(xué)軟件學(xué)院 上海 201203)
隨著惡意軟件檢測(cè)和分析技術(shù)的發(fā)展,大量惡意軟件采用規(guī)避技術(shù)來(lái)對(duì)抗安全分析。其中,代碼隱藏類規(guī)避技術(shù)將應(yīng)用代碼對(duì)靜態(tài)分析隱藏起來(lái),使分析結(jié)果錯(cuò)誤或缺失。爆炸式增長(zhǎng)的惡意軟件數(shù)量要求了對(duì)代碼隱藏類規(guī)避技術(shù)的自動(dòng)化檢測(cè)。通過(guò)對(duì)142個(gè)惡意樣本進(jìn)行人工分析,總結(jié)出一種代碼隱藏類規(guī)避技術(shù)的檢測(cè)方法,并實(shí)現(xiàn)了一個(gè)通用的自動(dòng)化檢測(cè)框架。使用檢測(cè)框架在第三方應(yīng)用市場(chǎng)2 278個(gè)樣本上進(jìn)行了實(shí)驗(yàn),發(fā)現(xiàn)有34.9%的樣本使用了代碼隱藏類規(guī)避技術(shù)。
安卓 規(guī)避技術(shù) 靜態(tài)分析 動(dòng)態(tài)分析
以移動(dòng)操作系統(tǒng)為平臺(tái),開發(fā)者可以開發(fā)應(yīng)用來(lái)擴(kuò)展移動(dòng)設(shè)備的功能。在眾多移動(dòng)操作系統(tǒng)中,安卓系統(tǒng)由于其開放性最受廠商和用戶的青睞,占據(jù)了移動(dòng)操作系統(tǒng)86.8%的市場(chǎng)份額[1]。與此同時(shí),基于安卓系統(tǒng)的第三方應(yīng)用數(shù)量正呈飛速增長(zhǎng),僅以Google官方應(yīng)用市場(chǎng)Google Play為例,其應(yīng)用數(shù)量已超過(guò)260萬(wàn)個(gè)[2],且仍處于飛速增長(zhǎng)中。
移動(dòng)設(shè)備中含有大量的用戶隱私數(shù)據(jù),出于保護(hù)用戶隱私的目的,安全分析人員利用程序分析方法來(lái)分析應(yīng)用程序行為,識(shí)別惡意軟件。程序分析技術(shù)主要包含靜態(tài)和動(dòng)態(tài)程序分析兩類。其中,靜態(tài)分析相較于動(dòng)態(tài)分析有代碼覆蓋全、分析效率高的優(yōu)點(diǎn),是目前可用于大規(guī)模檢測(cè)分析的重要手段。
然而,無(wú)論是正常應(yīng)用開發(fā)者還是惡意軟件作者都具有規(guī)避軟件檢測(cè)的需求。其中,正常應(yīng)用需要對(duì)抗逆向工程,保護(hù)軟件核心代碼。而惡意軟件作者通過(guò)規(guī)避分析檢測(cè),可以延長(zhǎng)其惡意代碼的生命周期。此類規(guī)避分析技術(shù)的方法通常被稱為規(guī)避技術(shù)。其中,代碼隱藏類規(guī)避技術(shù)作為一類主要的規(guī)避分析方法,通過(guò)把代碼對(duì)靜態(tài)分析隱藏起來(lái),使分析結(jié)果錯(cuò)誤或缺失,降低了分析的準(zhǔn)確度。
代碼隱藏類規(guī)避技術(shù)包括動(dòng)態(tài)代碼加載技術(shù)、代碼自修復(fù)技術(shù)和垃圾代碼插入技術(shù)三種。動(dòng)態(tài)代碼加載技術(shù)和代碼自修復(fù)技術(shù)由于將程序關(guān)鍵代碼隱藏起來(lái),使得靜態(tài)分析在中間環(huán)節(jié)生成的圖不完整或錯(cuò)誤,導(dǎo)致對(duì)樣本的誤判。垃圾代碼插入技術(shù)會(huì)在靜態(tài)分析的詞法、語(yǔ)法分析階段對(duì)分析工具產(chǎn)生干擾,如果分析工具的實(shí)現(xiàn)沒有完整地考慮垃圾代碼插入技術(shù)所帶來(lái)的威脅,就會(huì)有在運(yùn)行時(shí)崩潰的風(fēng)險(xiǎn)。這三種規(guī)避分析的技術(shù)都具有隱藏程序關(guān)鍵代碼,從而使靜態(tài)程序分析方法無(wú)法完整分析應(yīng)用程序邏輯的能力。
為了解決代碼隱藏類規(guī)避技術(shù)給靜態(tài)分析帶來(lái)的不利現(xiàn)狀,我們提出了通用的自動(dòng)化檢測(cè)框架。該框架通過(guò)自動(dòng)化識(shí)別規(guī)避檢測(cè)技術(shù)的應(yīng)用,并以警報(bào)的方式提醒分析人員,以輔助分析人員早期發(fā)現(xiàn)具有規(guī)避行為的惡意軟件。
我們對(duì)142個(gè)惡意樣本進(jìn)行了人工分析,歸納了其中代碼隱藏類規(guī)避技術(shù)的使用模式,并提出了一個(gè)通用的自動(dòng)化檢測(cè)框架。我們的檢測(cè)框架利用安卓系統(tǒng)中Dalvik虛擬機(jī)代碼加載和執(zhí)行的模型,使用主動(dòng)觸發(fā)類加載和初始化的方法促使代碼的加載和修復(fù)。我們修改了安卓系統(tǒng)中Dalvik虛擬機(jī)和libc的源代碼,對(duì)樣本中加載和修復(fù)代碼的行為進(jìn)行監(jiān)控,可以有效地識(shí)別出樣本是否有隱藏代碼的行為。
我們從中國(guó)第三方應(yīng)用市場(chǎng)應(yīng)用寶[3]中收集了2 278個(gè)樣本,并對(duì)其進(jìn)行了自動(dòng)化分析。實(shí)驗(yàn)表明,檢測(cè)框架成功分析了2 247個(gè)樣本,識(shí)別出794個(gè)使用了代碼隱藏類規(guī)避技術(shù)的樣本。
1.1 DEX文件
由Dalvik虛擬機(jī)解釋執(zhí)行的字節(jié)碼也被稱作DEX字節(jié)碼(Dalvik Executable Bytecode)[4],由DEX字節(jié)碼所組成的DEX文件是運(yùn)行于安卓系統(tǒng)Dalvik虛擬機(jī)中的可執(zhí)行文件,也是安卓應(yīng)用程序的核心所在。在這一部分,我們簡(jiǎn)要地介紹DEX文件。
安卓應(yīng)用通常由Java語(yǔ)言寫成,從Java源代碼到DEX文件的基本映射關(guān)系如圖1所示。Java編譯器將Java源代碼編譯成.class文件,然后dx工具將.class文件轉(zhuǎn)換為.dex文件,.dex文件是.class文件在安卓系統(tǒng)中的優(yōu)化。
圖1 從Java源文件到生成DEX文件的基本映射關(guān)系
DEX文件從整體上看是個(gè)索引結(jié)構(gòu),包含了文件頭、常量池、類屬性表、方法表、類定義表和數(shù)據(jù)段等部分。文件頭包含了魔數(shù)、校驗(yàn)值、其他各部分的索引和長(zhǎng)度等。常量池、類屬性表、方法表和類定義表描述了字符串常量、類的屬性、類的方法和類的定義等信息。類名、方法名、常量字符串等都存儲(chǔ)在非冗余的常量池中,這樣能夠充分地減少存儲(chǔ)空間。數(shù)據(jù)段包含了所有的類定義和字節(jié)碼。一段完整的類方法,其代碼必定包含了如表1所列的所有字段。
表1 類方法代碼的必含字段
代碼隱藏類規(guī)避技術(shù)通常會(huì)修改DEX文件,來(lái)對(duì)靜態(tài)分析產(chǎn)生干擾。較為高級(jí)的代碼隱藏類規(guī)避技術(shù)往往會(huì)修改表1中所描述的字段。例如:1) 將debugInfoOff的值修改為非法值,使分析工具運(yùn)行錯(cuò)誤;2) 向insns內(nèi)填充一些空指令和非法指令,使分析工具無(wú)法處理該部分代碼。
1.2 代碼隱藏類規(guī)避技術(shù)
在安卓系統(tǒng)中,代碼隱藏類規(guī)避技術(shù)通過(guò)修改APK安裝包中的DEX文件,將程序的核心代碼對(duì)靜態(tài)分析隱藏起來(lái),使靜態(tài)分析的結(jié)果錯(cuò)誤或缺失,從而達(dá)到保護(hù)核心代碼、隱藏程序行為的目的。代碼隱藏類規(guī)避技術(shù)包括動(dòng)態(tài)代碼加載技術(shù)、代碼自修復(fù)技術(shù)和垃圾代碼插入技術(shù)三種技術(shù)。
動(dòng)態(tài)代碼加載技術(shù)是指進(jìn)程在運(yùn)行時(shí)額外加載代碼執(zhí)行的技術(shù)。利用了額外加載的特性,開發(fā)者通常會(huì)將需要保護(hù)的代碼加密,在運(yùn)行時(shí)解密,并通過(guò)隱蔽的手段來(lái)加載解密后的代碼。也就是說(shuō),動(dòng)態(tài)代碼加載的過(guò)程可以分為獲取、解密、加載和執(zhí)行四個(gè)階段。應(yīng)用程序可以通過(guò)網(wǎng)絡(luò)或者讀取本地文件的方式來(lái)獲取加密后的代碼,而解密和加載的過(guò)程可以不接觸文件系統(tǒng),完全在內(nèi)存中執(zhí)行,從而提高了安全分析的難度。更復(fù)雜的情況是,加載的代碼可以分為幾段,不同段代碼的加載可以以不同的方式觸發(fā)。
代碼自修復(fù)技術(shù)的程序會(huì)在進(jìn)程執(zhí)行的過(guò)程中動(dòng)態(tài)修改內(nèi)存中的代碼,這意味著即使分析人員在程序啟動(dòng)和執(zhí)行過(guò)程中所觀察到的是同一塊代碼,其內(nèi)容也可能有所不同。對(duì)靜態(tài)分析來(lái)說(shuō),代碼自修復(fù)技術(shù)隱藏了部分“真實(shí)”的代碼,其分析結(jié)果會(huì)有所缺失。如果開發(fā)者將被隱藏的代碼替換為無(wú)關(guān)的程序行為,靜態(tài)分析還會(huì)被誤導(dǎo)。
圖2展示了一段字節(jié)碼在修改前與修改后的狀態(tài)。在該示例中,某個(gè)類的interceptSMS()方法被填充為空指令nop,即不做任何工作。當(dāng)應(yīng)用程序啟動(dòng)后,在Application.oncreate()等程序入口處會(huì)修改interceptSMS()方法的代碼,將代碼替換為監(jiān)聽短信接收通知的代碼。這樣,程序在運(yùn)行過(guò)程中通過(guò)修改自身代碼的行為就可以將其惡意行為偽裝起來(lái),從而導(dǎo)致靜態(tài)分析對(duì)樣本的誤判。
圖2 程序在運(yùn)行過(guò)程中修改自己的代碼
垃圾代碼插入技術(shù)通過(guò)向代碼的特定位置插入垃圾字節(jié),使反匯編工具生成錯(cuò)誤信息,從而對(duì)靜態(tài)分析產(chǎn)生干擾。插入垃圾代碼的位置因不同分析工具所使用算法的不同而不同,而插入的代碼必然是不能執(zhí)行的無(wú)效代碼,否則會(huì)導(dǎo)致未知的執(zhí)行結(jié)果。通常的做法是在插入的垃圾代碼之前添加一條無(wú)條件跳轉(zhuǎn)指令。
總而言之,代碼隱藏類規(guī)避技術(shù)通常會(huì)給靜態(tài)分析帶來(lái)困擾,有時(shí)甚至使其失效。垃圾代碼插入技術(shù)會(huì)在靜態(tài)分析的詞法、語(yǔ)法分析階段對(duì)分析工具產(chǎn)生干擾,越是對(duì)DEX完整性和規(guī)范性有要求的工具越有可能會(huì)運(yùn)行失敗。動(dòng)態(tài)代碼加載技術(shù)和代碼自修復(fù)技術(shù)會(huì)使靜態(tài)分析生成不完整或錯(cuò)誤的圖,從而導(dǎo)致分析結(jié)果不準(zhǔn)確。較為高級(jí)的商用代碼保護(hù)方案會(huì)將原始安裝包中所有的DEX字節(jié)碼加密起來(lái),而解密、加載和修復(fù)的邏輯則完全放在了使用混淆技術(shù)的本地代碼中。在這種情況下,靜態(tài)分析由于沒有實(shí)際運(yùn)行程序,不可能接觸到被保護(hù)的代碼,從而完全無(wú)法得知程序的原始行為。
1.3 相關(guān)工作
在安卓平臺(tái)上,對(duì)規(guī)避技術(shù)的研究呈現(xiàn)方興未艾之勢(shì)。Strazzere在文獻(xiàn)[5]和文獻(xiàn)[6]中介紹了對(duì)抗靜態(tài)分析和動(dòng)態(tài)分析的代碼保護(hù)技術(shù)。Vidas等[7]總結(jié)了一系列檢測(cè)安卓應(yīng)用是否運(yùn)行于虛擬環(huán)境的方法,即對(duì)抗模擬器或?qū)固摂M機(jī)技術(shù)。
在代碼隱藏類規(guī)避技術(shù)方面,Yu[8]和Strazzere[9]等對(duì)商用代碼保護(hù)方案的特征做了一些假設(shè),并以這些假設(shè)為基礎(chǔ)來(lái)定位DEX字節(jié)碼。然而隨著代碼保護(hù)方案的發(fā)展,這些方法已經(jīng)失效。DexHunter[10]和AppSpear[11]分別針對(duì)商用代碼保護(hù)方案提出了提取隱藏代碼方法。DexHunter通過(guò)主動(dòng)觸發(fā)類加載和初始化進(jìn)而對(duì)代碼進(jìn)行內(nèi)存轉(zhuǎn)儲(chǔ)來(lái)提取被隱藏的代碼。這種提取隱藏代碼的方式只針對(duì)特定幾種商用代碼保護(hù)方案,無(wú)法全面有效地定位隱藏代碼,方法不夠通用。AppSpear修改了Dalvik虛擬機(jī)的解釋器,將解釋執(zhí)行到的相關(guān)代碼轉(zhuǎn)儲(chǔ)到文件中,這種方法存在代碼覆蓋率不夠全的問題。Harvester[12]提出了通過(guò)在Dalvik虛擬機(jī)中對(duì)字節(jié)碼做切片運(yùn)行來(lái)提取應(yīng)用運(yùn)行時(shí)信息的自動(dòng)化分析方法,該方法可以在一定程度上對(duì)抗規(guī)避技術(shù),但對(duì)本地代碼中的規(guī)避行為效果不明顯。
本文所提出的框架目的在于對(duì)安卓應(yīng)用中的隱藏代碼進(jìn)行檢測(cè),可以準(zhǔn)確全面地定位有效代碼,具有較強(qiáng)的通用性,并且能應(yīng)用于自動(dòng)化分析。
為了研究代碼隱藏類規(guī)避技術(shù)的使用模式,并提出針對(duì)隱藏代碼的檢測(cè)框架,我們?nèi)斯し治隽艘慌鷲阂鈽颖?。樣本的收集時(shí)間為2015年08月01日至2015年08月03日,共計(jì)10 827個(gè)。經(jīng)由第三方檢測(cè)引擎標(biāo)注,這些樣本可以劃分到107個(gè)家族,170個(gè)變種中去。考慮到同一變種的樣本非常相似,我們?cè)诿總€(gè)變種中隨機(jī)選取了1個(gè)樣本進(jìn)行人工分析。
在170個(gè)樣本中:有7個(gè)樣本無(wú)法安裝,這包括6個(gè)沒有有效自簽名證書的樣本和1個(gè)為無(wú)效APK文件的樣本;有15個(gè)樣本沒有Activity或者Service等程序入口,無(wú)法啟動(dòng)運(yùn)行,以插件的形式存在;有6個(gè)樣本由于兼容性或其他問題,在程序啟動(dòng)后崩潰或退出。這28個(gè)樣本均為無(wú)效樣本,所以沒有對(duì)其做進(jìn)一步分析。對(duì)剩下的142個(gè)樣本的分析結(jié)果如表2所示。
表2 惡意樣本的人工分析
在剩下的142個(gè)樣本中,經(jīng)人工分析,我們發(fā)現(xiàn)有42個(gè)樣本使用了動(dòng)態(tài)代碼加載技術(shù),有2個(gè)樣本使用了代碼自修復(fù)技術(shù),有6個(gè)樣本使用了垃圾代碼插入技術(shù)。同時(shí),使用代碼自修復(fù)技術(shù)的2個(gè)樣本也使用了垃圾代碼插入技術(shù)。剩下的94個(gè)樣本未發(fā)現(xiàn)使用本文所述的代碼隱藏類規(guī)避技術(shù)。我們對(duì)這142個(gè)樣本進(jìn)行了標(biāo)注,以用來(lái)在實(shí)驗(yàn)環(huán)節(jié)驗(yàn)證隱藏代碼檢測(cè)框架的準(zhǔn)確性。
我們對(duì)142個(gè)樣本進(jìn)行了人工分析,總結(jié)出一種代碼隱藏類規(guī)避技術(shù)的檢測(cè)方法,并實(shí)現(xiàn)了一個(gè)通用的自動(dòng)化檢測(cè)框架。其架構(gòu)如圖3所示,整個(gè)框架處理流程包括預(yù)處理、動(dòng)態(tài)分析、后端處理三個(gè)階段??蚣艿妮斎霝锳PK樣本和日志,同時(shí)日志也是框架的產(chǎn)出結(jié)果。
圖3 檢測(cè)框架架構(gòu)
3.1 預(yù)處理
在分析樣本之前,必須能在日志中唯一地確定樣本。我們把APK文件作為分析樣本,使用文件的MD5和SHA1值來(lái)唯一確定樣本文件。在安卓應(yīng)用中,包(package)名和版本可以唯一確定其發(fā)布版本,因此我們也記錄APK文件的包名、版本號(hào)、版本名稱。
當(dāng)對(duì)樣本進(jìn)行動(dòng)態(tài)分析時(shí),需要將其安裝到安卓模擬器中并啟動(dòng)它的Main Activity使其運(yùn)行。因此,我們還需要提取樣本的Main Activity名稱。除此以外,使用同一代碼保護(hù)方案的樣本往往具有統(tǒng)一的Application名稱。因此,我們將這一字段記錄下來(lái),以便于對(duì)日志做進(jìn)一步分析。
對(duì)于與安卓應(yīng)用相關(guān)的信息,使用安卓SDK中的aapt工具進(jìn)行提取。工具aapt的全名為Android Asset Packaging Tool,即安卓資源打包工具,在SDK的build-tools目錄下。該工具可以查看,創(chuàng)建,更新ZIP格式的文檔附件(zip, jar,apk)。這里使用aapt來(lái)提取樣本中的信息是因?yàn)閍apt工具的代碼實(shí)現(xiàn)與安卓系統(tǒng)相同,因而能夠成功安裝并運(yùn)行的應(yīng)用都可以用aapt工具進(jìn)行分析,aapt工具具有良好的兼容性。
在提取了安卓應(yīng)用的相關(guān)信息后,還需要將樣本APK文件進(jìn)行解壓縮,以用來(lái)在后端處理階段對(duì)安裝包中的文件進(jìn)行處理。
3.2 動(dòng)態(tài)分析
我們修改了安卓系統(tǒng)源碼中Dalvik虛擬機(jī)和libc部分的代碼,編譯成安卓模擬器作為動(dòng)態(tài)分析的環(huán)境??紤]到APK版本的兼容性,我們使用了較低版本的安卓系統(tǒng)源碼,其版本號(hào)為4.4.4。為了保證樣本之間互不影響,每一次啟動(dòng)的安卓模擬器鏡像都是預(yù)先配置好的鏡像的一份拷貝。我們修改的Dalvik虛擬機(jī)和libc會(huì)在分析時(shí)記錄下樣本的運(yùn)行時(shí)信息,并將其寫入到日志中。
3.2.1 主動(dòng)觸發(fā)類加載和初始化
動(dòng)態(tài)分析可以分為以符號(hào)執(zhí)行為代表的白盒測(cè)試和基于真實(shí)分析環(huán)境和虛擬分析環(huán)境的黑盒測(cè)試。一般來(lái)說(shuō),動(dòng)態(tài)分析都期望被分析的程序盡可能多地執(zhí)行代碼路徑來(lái)保證分析有足夠的代碼覆蓋率。在基于虛擬機(jī)環(huán)境的自動(dòng)化分析環(huán)境中,一種較為流行的保證代碼覆蓋率的方法是以隨機(jī)模擬事件的方式來(lái)驅(qū)動(dòng)代碼的執(zhí)行,如AppsPlayground[13]。安卓SDK也提供了名為MonkeyRunner[14]的類似的自動(dòng)化測(cè)試工具。
然而,在分析惡意樣本時(shí)我們發(fā)現(xiàn),有大量樣本在啟動(dòng)之后會(huì)直接退出用戶界面并駐留在后臺(tái)運(yùn)行。在這種情況下,如果采用隨機(jī)模擬事件的方式來(lái)驅(qū)動(dòng)程序的執(zhí)行,可能會(huì)啟動(dòng)系統(tǒng)內(nèi)的其他應(yīng)用,甚至導(dǎo)致內(nèi)存不足,Activity Manager殺死當(dāng)前需要分析的進(jìn)程。與一般動(dòng)態(tài)分析中行為分析不同的是,分析框架的目的是盡可能地觸發(fā)進(jìn)程中代碼的加載和修復(fù),而不是執(zhí)行完所有的代碼路徑,我們使用了主動(dòng)觸發(fā)類加載和初始化的方法來(lái)保證分析有足夠的代碼覆蓋率,這一方法由DexHunter[10]提出,我們做了部分改進(jìn)。
我們的方法是:監(jiān)控Dalvik虛擬機(jī)中加載DEX字節(jié)碼的過(guò)程,每當(dāng)有一段DEX字節(jié)碼被加載時(shí)就啟動(dòng)一個(gè)新的線程。圖11展示了該線程接下來(lái)的執(zhí)行流程。新創(chuàng)建的線程會(huì)先睡眠一段時(shí)間,然后根據(jù)DEX文件的索引結(jié)構(gòu)查找該DEX文件中所有類的名字,用類名作為參數(shù)調(diào)用相關(guān)API來(lái)觸發(fā)Dalvik虛擬機(jī)對(duì)類的加載。這里啟動(dòng)一個(gè)新的線程并睡眠一段時(shí)間是為了保證程序不會(huì)運(yùn)行崩潰。因?yàn)楫?dāng)類加載的順序與預(yù)先設(shè)定的執(zhí)行順序不一致時(shí),類的部分屬性會(huì)初始化為與預(yù)期不同的值,從而使主線程拋出未捕獲的異常,導(dǎo)致進(jìn)程崩潰。而當(dāng)起動(dòng)一個(gè)新的線程并睡眠一段時(shí)間后,主線程的初始化工作已經(jīng)完成,這時(shí)新啟動(dòng)的線程就可以通過(guò)強(qiáng)制捕獲所有拋出異常的方式來(lái)保證類的加載,并不會(huì)對(duì)主線程的執(zhí)行造成影響。
基于以下結(jié)論,該方法能夠起到良好的效果:1) Dalvik虛擬機(jī)對(duì)代碼的加載是以類為基本單位的,當(dāng)虛擬機(jī)加載一個(gè)類的時(shí)候,會(huì)驗(yàn)證該類所有方法的代碼,并將該類進(jìn)行初始化,也就是創(chuàng)建一個(gè)類對(duì)象;2) 對(duì)隱藏代碼的加載和修復(fù)往往會(huì)出現(xiàn)在程序的入口和類的初始化方法
3.2.2 修改的DVM
對(duì)Dalvik虛擬機(jī)的修改主要用來(lái)記錄進(jìn)程中類對(duì)象的加載過(guò)程,以用來(lái)判斷樣本是否使用了動(dòng)態(tài)代碼加載技術(shù)。
對(duì)于動(dòng)態(tài)代碼加載技術(shù),檢測(cè)方法的基本思想是:Dalvik虛擬機(jī)是一個(gè)解釋執(zhí)行模型,其解釋器引用到的DEX字節(jié)碼一定是有效代碼。為了詳細(xì)地闡述這一思想,首先需要解釋一下Dalvik虛擬機(jī)中類對(duì)象和DEX文件在內(nèi)存中的關(guān)聯(lián)關(guān)系,如圖4所示。
圖4 Dalvik虛擬機(jī)中類對(duì)象和DEX文件間的關(guān)聯(lián)
Dalvik虛擬機(jī)中維護(hù)著一張表,表里保存著當(dāng)前所有已加載的類對(duì)象,即ClassObject。ClassObject對(duì)應(yīng)于java.lang.Class的對(duì)象,每個(gè)類只有一個(gè),只有當(dāng)類被加載時(shí)才會(huì)創(chuàng)建。ClassObject中保存著該類所有方法的指針。DexFile是DEX文件在內(nèi)存中的映射。由于DEX文件是索引結(jié)構(gòu),不能直接維護(hù)所有的類對(duì)象和方法對(duì)象,虛擬機(jī)會(huì)為每一個(gè)DexFile維護(hù)一個(gè)名為DvmDex的對(duì)象,ClassObject對(duì)其對(duì)應(yīng)的DexFile的引用是間接的,即通過(guò)指向一個(gè)DvmDex對(duì)象來(lái)尋找其對(duì)應(yīng)的DexFile對(duì)象。
Dalvik虛擬機(jī)維護(hù)這樣一種對(duì)象關(guān)系與其代碼加載機(jī)制有關(guān),其對(duì)代碼的加載遵循Java虛擬機(jī)中類加載的默認(rèn)委派機(jī)制。即啟動(dòng)類加載器由虛擬機(jī)的本地代碼實(shí)現(xiàn),負(fù)責(zé)對(duì)Java核心類的加載。擴(kuò)展類加載器同樣由虛擬機(jī)實(shí)現(xiàn),負(fù)責(zé)對(duì)虛擬機(jī)代碼庫(kù)中非核心代碼的加載。應(yīng)用程序類加載器是虛擬機(jī)提供給應(yīng)用的默認(rèn)類加載器,負(fù)責(zé)加載開發(fā)者實(shí)現(xiàn)的代碼。除此之外,開發(fā)者還可以自行實(shí)現(xiàn)自定義類加載器,來(lái)加載私有的代碼。一個(gè)類的加載是從下到上以委派的模式加載的。即虛擬機(jī)先調(diào)用與當(dāng)前類關(guān)聯(lián)的類加載器,查找所需要加載類的代碼,如果找不到則向上一級(jí)委派。上一級(jí)類加載器重復(fù)這一過(guò)程,直到執(zhí)行到啟動(dòng)類加載器。如果啟動(dòng)類加載器也無(wú)法加載類的代碼,就會(huì)拋出ClassNotFoundException。在Dalvik虛擬機(jī)中,一個(gè)類加載器往往關(guān)聯(lián)著幾個(gè)DEX文件。
在Dalvik虛擬機(jī)中,當(dāng)有一個(gè)DEX文件被加載時(shí),就會(huì)創(chuàng)建一個(gè)DexFile對(duì)象來(lái)維護(hù)DEX文件的索引結(jié)構(gòu)。然后,虛擬機(jī)會(huì)為該DexFile對(duì)象創(chuàng)建一個(gè)DvmDex對(duì)象以用來(lái)維護(hù)類、方法等內(nèi)存中的對(duì)象。當(dāng)虛擬機(jī)解釋執(zhí)行時(shí),它會(huì)通過(guò)全局表來(lái)來(lái)查找方法所在的類,即ClassObject。如果類不存在,則通過(guò)委派加載機(jī)制依次查找到途經(jīng)類加載器所關(guān)聯(lián)的DexFile對(duì)象,直至找到所需的類。當(dāng)把該類加載和初始化后,虛擬機(jī)通過(guò)ClassObject所引用的Method找到對(duì)應(yīng)的字節(jié)碼,并開始解釋執(zhí)行。
如果開發(fā)者想要對(duì)代碼進(jìn)行保護(hù),那么他們可以實(shí)現(xiàn)私有的類加載器,或者通過(guò)硬編碼等方式調(diào)用Dalvik虛擬機(jī)的代碼,從而繞過(guò)Dalvik虛擬機(jī)所提供的調(diào)用接口。更高級(jí)的規(guī)避方法是將代碼分段,在進(jìn)程執(zhí)行的過(guò)程中修改Dalvik虛擬機(jī)對(duì)象的引用指針,如將ClassObject的pDvmDex改為空指針,或?qū)ethod的pInstructions指向一塊堆內(nèi)的地址,這時(shí)ClassObject與DvmDex所指向的Method對(duì)象必然不一致,從而對(duì)分析人員造成困擾。
然而,Dalvik虛擬機(jī)是一種解釋執(zhí)行模型,其解釋器引用到的代碼一定是有效代碼,否則將導(dǎo)致程序行為異常。在解釋器運(yùn)行的過(guò)程中,總是通過(guò)Dalvik虛擬機(jī)所維護(hù)的已加載類表來(lái)尋找對(duì)應(yīng)的ClassObject,通過(guò)解引用其指向的方法代碼來(lái)解釋執(zhí)行。由于進(jìn)程的執(zhí)行流程是無(wú)法預(yù)判的,所以可以認(rèn)為ClassObject所引用的代碼是進(jìn)程加載和恢復(fù)的原始代碼。我們將所有的ClassObject和與之相關(guān)的對(duì)象記錄到日志中,在后端處理階段對(duì)其進(jìn)行分析。
3.2.3 修改的libc
通過(guò)對(duì)使用了代碼自修復(fù)技術(shù)的惡意樣本進(jìn)行人工分析,我們發(fā)現(xiàn)了代碼自修復(fù)技術(shù)的使用模式:Dalvik虛擬機(jī)是一種解釋執(zhí)行模型,其解釋執(zhí)行的DEX文件映射在內(nèi)存中的頁(yè)屬性是只讀的。進(jìn)程為了修改DEX字節(jié)碼,會(huì)調(diào)用系統(tǒng)調(diào)用中的mprotect()函數(shù)來(lái)修改DEX字節(jié)碼在內(nèi)存中的頁(yè)保護(hù)屬性,然后通過(guò)內(nèi)存拷貝的方式來(lái)修改DEX字節(jié)碼,最后調(diào)用再mprotect()函數(shù)將其內(nèi)存頁(yè)保護(hù)屬性改為原值。
為了分析樣本中代碼自修復(fù)技術(shù)的使用情況,我們?cè)诜治隹蚣苤袑?duì)libc中mprotect()函數(shù)的調(diào)用情況進(jìn)行了監(jiān)控,每當(dāng)進(jìn)程調(diào)用mprotect()函數(shù)修改內(nèi)存頁(yè)為可寫時(shí),分析框架就將其調(diào)用參數(shù)的起始地址和終止地址記錄到日志中。同時(shí),當(dāng)進(jìn)程執(zhí)行一段時(shí)間后,分析框架將進(jìn)程的內(nèi)存布局從/proc/self/maps文件輸出到日志中。/proc/self/maps的內(nèi)存布局如下所示:
4003a000-40049000 r-xp 00000000 b3:15 138 /system/bin/linker
40049000-4004a000 r-p 0000e000 b3:15 138 /system/bin/linker
4004a000-4004b000 rw-p 0000f000 b3:15 138 /system/bin/linker
...
40055000-40075000 r-xp 00000000 b3:15 749 /system/lib/libc.so
40075000-40077000 rwxp 00020000 b3:15 749 /system/lib/libc.so
40077000-4009c000 r-xp 00022000 b3:15 749 /system/lib/libc.so
...
41555000-41883000 rw-p 00000000 00:04 6911 /dev/ashmem/dalvik-zygote (deleted)
...
6eae7000-6ec54000 r-p 00000000 b3:17 185112 /data/dalvik-cache/system@framework.jar
...
747d7000-747d8000 r-s 00009000 b3:17 48292 /data/app/com.example-1.apk@classes.dex
...
如app_process、linker以及l(fā)ibc.so等可執(zhí)行文件在內(nèi)存中會(huì)映射為三段,分別具有可執(zhí)行、只讀、讀寫的屬性,對(duì)應(yīng)于.text、.rodata、.data/.bss字段。形如/dev/ashmem/xxxxxx (deleted)的是匿名共享內(nèi)存Ashmem,經(jīng)由Binder進(jìn)行進(jìn)程間通信后將內(nèi)存銷毀。形如system@framework.jar為系統(tǒng)提供的Java代碼庫(kù)。/data/app/com.example-1.apk@classes.dex為第三方應(yīng)用的DEX文件在內(nèi)存中的映射,其屬性為只讀。我們需要監(jiān)控的即是對(duì)/data/app/com.example-1.apk@classes.dex所要進(jìn)行的修改。
3.3 后端處理
后端處理以動(dòng)態(tài)分析輸出的日志為輸入,將代碼隱藏類規(guī)避技術(shù)的檢測(cè)結(jié)果作為輸出寫到日志中。
為了判斷樣本是否使用了動(dòng)態(tài)代碼加載技術(shù),一種取巧的做法是遍歷日志中記錄的所有的ClassObject,并統(tǒng)計(jì)其中不同的DvmDex的個(gè)數(shù)。如果DvmDex的個(gè)數(shù)超過(guò)1個(gè),即使其值為空,也仍然使用了動(dòng)態(tài)代碼加載技術(shù)。此外,我們還在日志中記錄了pDvmDex運(yùn)行時(shí)的值,有效代碼是否在ClassObject間接引用的DexFile內(nèi)存塊中等運(yùn)行時(shí)數(shù)據(jù)來(lái)進(jìn)行驗(yàn)證。
通過(guò)比較日志中調(diào)用mprotect()函數(shù)修改的內(nèi)存與內(nèi)存布局中DEX文件映射區(qū)域是否有重合,即可得知進(jìn)程在運(yùn)行的過(guò)程中是否有修改DEX字節(jié)碼的意圖,從而可以判斷樣本是否使用了代碼自修復(fù)技術(shù)。
為了判斷樣本是否使用了垃圾代碼插入技術(shù),最直觀的方法是使用反匯編工具直接對(duì)APK文件的DEX字節(jié)碼進(jìn)行處理,通過(guò)分析工具輸出的日志來(lái)判斷樣本的代碼是否合乎規(guī)范。在這里,我們使用了baksmali[15]作為分析框架的反匯編的工具,版本號(hào)是2.1.2。當(dāng)baksmali在處理DEX文件時(shí),如果發(fā)現(xiàn)文件不符合規(guī)范或者代碼指令非法,即會(huì)輸出錯(cuò)誤信息。
在表3中列出了經(jīng)過(guò)后端處理階段后,對(duì)一個(gè)樣本的分析結(jié)果的所有字段。不符合規(guī)范或者代碼指令非法,即會(huì)輸出錯(cuò)誤信息。
表3 檢測(cè)結(jié)果的所有字段
在動(dòng)態(tài)分析的過(guò)程中,應(yīng)用可能會(huì)在運(yùn)行很長(zhǎng)一段時(shí)間后仍然沒有記錄足夠的數(shù)據(jù)。比如樣本需要聯(lián)網(wǎng)下載文件,但是分析時(shí)的網(wǎng)絡(luò)狀況不是很好。這時(shí),應(yīng)將當(dāng)前正在運(yùn)行的安卓模擬器關(guān)閉,并將分析任務(wù)加入到任務(wù)隊(duì)列中等待重新分配。因此我們記錄了動(dòng)態(tài)分析的起始時(shí)間和終止時(shí)間。除此以外,我們還記錄了樣本分析的最終狀態(tài),這些狀態(tài)可能是:分析成功、安裝失敗、應(yīng)用無(wú)法啟動(dòng)、進(jìn)程自動(dòng)退出或崩潰,分析超時(shí)。導(dǎo)致安裝失敗的原因可能是APK文件不符合規(guī)范,沒有有效的自簽名證書,或者工具對(duì)樣本的信息提取不夠完整。應(yīng)用無(wú)法啟動(dòng)的原因可能是應(yīng)用沒有Main Activity或者分析工具無(wú)法提取出樣本的Main Activity名稱。除此之外,我們還會(huì)以輪詢的方式查看進(jìn)程是否在穩(wěn)定運(yùn)行,如果不是,則程序有可能已經(jīng)退出或者運(yùn)行崩潰。
為了評(píng)估分析方法的準(zhǔn)確性,我們收集了兩組實(shí)驗(yàn)樣本。
第一組樣本為第三節(jié)所述的人工標(biāo)注的142個(gè)惡意樣本,收集時(shí)間為2015年08月01日至08月03日。
第二組樣本共計(jì)2 278個(gè),于2016年05月12日在中國(guó)第三方應(yīng)用市場(chǎng)應(yīng)用寶中收集。我們?cè)趹?yīng)用寶官方劃分的購(gòu)物、閱讀、新聞、視頻、旅游、工具、社交、音樂、美化、攝影、理財(cái)、系統(tǒng)、生活、出行、安全、教育、健康、娛樂、兒童、辦公和通信21個(gè)分類中,將所有的推薦應(yīng)用進(jìn)行了抓取。這些應(yīng)用在官方網(wǎng)站中按照下載量、打分等因素排序,是該應(yīng)用市場(chǎng)中最流行的應(yīng)用??紤]到游戲應(yīng)用對(duì)安卓模擬器的兼容性較差,我們未對(duì)游戲類應(yīng)用進(jìn)行抓取。
我們的實(shí)驗(yàn)平臺(tái)為64位Linux系統(tǒng),內(nèi)核版本3.16.0。處理器為40核,CPU頻率2.2 Hz,物理內(nèi)存大小128 GB。動(dòng)態(tài)分析采用的安卓系統(tǒng)源碼版本為4.4.4。
4.1 標(biāo)注樣本的自動(dòng)化分析
我們將檢測(cè)框架應(yīng)用于人工標(biāo)注的142個(gè)樣本中,以評(píng)估檢測(cè)方法的準(zhǔn)確性。對(duì)人工標(biāo)注樣本的自動(dòng)化分析結(jié)果如表4所示。
表4 人工標(biāo)注樣本的自動(dòng)化分析結(jié)果
實(shí)驗(yàn)結(jié)果顯示,在42個(gè)標(biāo)注為使用了動(dòng)態(tài)代碼加載技術(shù)的樣本中,檢測(cè)框架識(shí)別出了36個(gè),使用了代碼自修復(fù)技術(shù)的2個(gè)樣本和垃圾代碼插入技術(shù)的6個(gè)樣本全部能識(shí)別出來(lái)。在未識(shí)別的6個(gè)樣本中,有1個(gè)樣本需要用戶登錄才能觸發(fā)對(duì)隱藏代碼的加載,其他5個(gè)樣本會(huì)在啟動(dòng)階段判斷是否在安卓模擬器中運(yùn)行,如果是,則立即退出。這5個(gè)樣本有對(duì)抗模擬器的意圖。
4.2 第三方市場(chǎng)應(yīng)用的自動(dòng)化分析
我們對(duì)2 278個(gè)第三方市場(chǎng)應(yīng)用樣本進(jìn)行了自動(dòng)化分析,其結(jié)果如表5所示。
表5 第三方市場(chǎng)中樣本的自動(dòng)化分析結(jié)果
在2 278個(gè)樣本中:有4個(gè)樣本無(wú)法安裝到安卓模擬器中,經(jīng)分析發(fā)現(xiàn)這4個(gè)樣本依賴于Google Maps框架,而我們的定制版安卓模擬器中沒有Google 服務(wù)框架;有25個(gè)樣本使用了較新的安卓SDK,我們的工具在預(yù)處理階段無(wú)法提取其完整信息,動(dòng)態(tài)分析不能繼續(xù)進(jìn)行;有2個(gè)樣本由于兼容性問題在進(jìn)程啟動(dòng)后崩潰或退出。
在剩下的2 247個(gè)樣本中:有773個(gè)樣本使用了動(dòng)態(tài)代碼加載技術(shù);有0個(gè)樣本使用了代碼自修復(fù)技術(shù);有23個(gè)樣本使用了垃圾代碼插入技術(shù)。其中,有2個(gè)樣本同時(shí)使用了動(dòng)態(tài)代碼加載和垃圾代碼插入技術(shù),剩下的1 453個(gè)樣本未發(fā)現(xiàn)使用本文所述的三種規(guī)避技術(shù)。
在2 247個(gè)樣本中未發(fā)現(xiàn)任何一個(gè)樣本使用了代碼自修復(fù)技術(shù)是出人意料的。在Going Native[16]中指出,調(diào)用mprotect()對(duì)DEX代碼做修改的樣本無(wú)一例外地使用了apkprotect這一早期代碼保護(hù)工具。我們對(duì)2 247個(gè)樣本中的文件進(jìn)行了靜態(tài)掃描,發(fā)現(xiàn)確實(shí)沒有任何一個(gè)樣本使用了apkprotect工具,一個(gè)可能的原因是該工具已經(jīng)不再對(duì)外提供服務(wù)了。判定樣本是否使用了apkprotect工具可以基于以下特征:1) 在APK文件中有l(wèi)ibapkprotect.so這一本地代碼文件;2) DEX文件中有apkprotect這樣一個(gè)類,該類在初始化階段會(huì)加載libapkprotect.so。
如表6所示,我們?cè)?73個(gè)檢測(cè)為使用了動(dòng)態(tài)代碼加載技術(shù)的樣本中隨機(jī)選取了50個(gè)樣本進(jìn)行人工驗(yàn)證,發(fā)現(xiàn)這50個(gè)樣本確實(shí)全部使用了動(dòng)態(tài)代碼加載技術(shù)。檢測(cè)為使用了垃圾代碼插入技術(shù)的23個(gè)樣本全部進(jìn)行了人工驗(yàn)證,未發(fā)現(xiàn)有錯(cuò)誤的檢測(cè)結(jié)果。在1 453個(gè)未檢出使用了代碼隱藏類規(guī)避技術(shù)的樣本中,選取了50個(gè)樣本進(jìn)行人工驗(yàn)證,發(fā)現(xiàn)有1個(gè)樣本由于安卓模擬器中地理位置信息不符合實(shí)際情況未觸發(fā)動(dòng)態(tài)代碼加載的過(guò)程。
表6 第三方市場(chǎng)樣本分析結(jié)果的人工驗(yàn)證
動(dòng)態(tài)代碼加載技術(shù)在推薦應(yīng)用中有33.9%的普及率,略高于人工分析的惡意樣本中29.6%的比率。雖然兩者的良惡性質(zhì)、抓取時(shí)間皆不相同,但是比率較為接近,說(shuō)明了動(dòng)態(tài)代碼加載技術(shù)在良性、惡性樣本中都有著顯著的普及率。
通過(guò)對(duì)使用了動(dòng)態(tài)代碼加載技術(shù)的樣本進(jìn)行日志分析,我們發(fā)現(xiàn)有287個(gè)樣本的Dalvik虛擬機(jī)內(nèi)存對(duì)象引用不正確,在使用動(dòng)態(tài)代碼加載技術(shù)的樣本中比例達(dá)到了37.1%。這說(shuō)明樣本有隱藏其規(guī)避行為的意圖,其動(dòng)態(tài)代碼加載的過(guò)程具有隱蔽性。需要指出的是,這里所列的數(shù)據(jù)是真實(shí)情況的下界。
相反地,代碼自修復(fù)技術(shù)粒度粗、隱蔽性弱,垃圾代碼插入技術(shù)只能稍微提高安全分析的門檻,相較于動(dòng)態(tài)代碼加載技術(shù),其使用比例較低。這體現(xiàn)了規(guī)避技術(shù)的發(fā)展是一個(gè)對(duì)抗的過(guò)程,其在技術(shù)實(shí)現(xiàn)上越來(lái)越復(fù)雜且隱蔽。
通過(guò)對(duì)142個(gè)惡意樣本進(jìn)行人工分析,本文提出了一個(gè)通用的自動(dòng)化檢測(cè)框架,可用于識(shí)別樣本是否使用了代碼隱藏類規(guī)避技術(shù)。該檢測(cè)框架將代碼隱藏類規(guī)避技術(shù)的模式統(tǒng)一起來(lái),利用安卓系統(tǒng)中Dalvik虛擬機(jī)的代碼加載和執(zhí)行模型,對(duì)樣本加載和修改代碼的行為進(jìn)行監(jiān)控,可以全面有效地定位隱藏代碼,可應(yīng)用于自動(dòng)化分析。實(shí)驗(yàn)表明,該檢測(cè)框架有著較高的準(zhǔn)確率。
[1] Smartphone OS market share[OL]. 2016. http://www.idc.com/promo/smartphone-market-share/os.
[2] Android statistics: number of android applications[OL]. 2016. https://www.appbrain.com/stats/number-of-android-apps.
[3] Myapp mobile application market[OL]. 2016. http://sj.qq.com.
[4] Dalvik Execuatble Format[OL]. 2016. https://source.android.com/devices/tech/dalvik/dex-format.html.
[5] Strazzere T. Dex education: Practicing safe dex[M]. Black Hat, USA, 2012.
[6] Strazzere T. Dex education 201: anti-emulation[M]. HITCON, 2013.
[7] Vidas T, Christin N. Evading android runtime analysis via sandbox detection[C]//Proceedings of the 9th ACM symposium on Information, computer and communications security. ACM, 2014:447-458.
[8] Rowland Yu. Android Packers: Facing the challenges, Building solutions[C]//Proc. of the 24th Virus Bulletin International Conference, 2014.
[9] Strazzere T, Sawyer J. Android Hacker Protection Level 0 DEF CON 22[Z].2014.
[10] Zhang Y, Luo X, Yin H. Dexhunter: toward extracting hidden code from packed android applications[M]//European Symposium on Research in Computer Security. Springer International Publishing, 2015:293-311.
[11] Yang W B, Zhang Y Y, Li J R, et al. AppSpear: Bytecode Decrypting and DEX Reassembling for Packed Android Malware[M]//Research in Attacks, Intrusions, and Defenses. Springer International Publishing, 2015.
[12] Rasthofer S, Arzt S, Miltenberger M, et al. Harvesting runtime values in android applications that feature anti-analysis techniques[C]//Proceedings of the Annual Symposium on Network and Distributed System Security (NDSS). 2016.
[13] Rastogi V, Chen Y, Enck W. AppsPlayground: automatic security analysis of smartphone applications[C]//Proceedings of the third ACM conference on Data and application security and privacy. ACM, 2013:209-220.
[14] MonkeyRunner[OL]. 2016. https://developer.android.com/studio/test/monkeyrunner/index.html.
[15] Smali and baksmali: Dalvik bytecode toolkit[OL]. 2016. https://github.com/JesusFreke/smali.
[16] Afonso V, Bianchi A, Fratantonio Y, et al. Going native: Using a large-scale analysis of android apps to create a practical native-code sandboxing policy[OL]//Proceedings of the Annual Symposium on Network and Distributed System Security (NDSS), 2016.
ADETECTIONFRAMEWORKOFCODE-HIDINGEVASIONTECHNIQUEBASEDONANDROIDSYSTEM
Ma Xiaokai Yang Zhemin
M(SoftwareSchool,FudanUniversity,Shanghai201203,China)
With the development of malware detection and analysis techniques, a large number of malwares use evasion techniques to fight against security analysis. Among these evasion techniques, code-hiding evasion techniques hide application code from static analysis, thus cause analysis results wrong or incomplete. The explosive growth of malware required automated detection of code-hiding evasion techniques. Through manual analysis of 142 malicious samples, this paper summarized an approach for detecting code-hiding evasion techniques and implemented a generic automated detection framework. We use the detection framework to do experiments on 2 278 samples in a third party applications market, and find that 34.9% samples use code-hiding evasion techniques.
Android Evasion technique Static analysis Dynamic analysis
2017-07-10。馬曉凱,碩士,主研領(lǐng)域:移動(dòng)安全,規(guī)避技術(shù)。楊哲慜,博士。
TP311
A
10.3969/j.issn.1000-386x.2017.11.058