


【摘 要】Android的大量應(yīng)用給移動(dòng)終端用戶帶來了豐富的體驗(yàn),但其存在的大量盜版應(yīng)用卻嚴(yán)重?fù)p害了開發(fā)者的權(quán)益。本文在分析Android應(yīng)用結(jié)構(gòu)的基礎(chǔ)上,總結(jié)現(xiàn)有的Android應(yīng)用保護(hù)技術(shù),如代碼混淆技術(shù)、動(dòng)態(tài)加載技術(shù)、軟件水印技術(shù)等。
【關(guān)鍵詞】Android 軟件保護(hù) 代碼混淆 動(dòng)態(tài)加載 軟件水印
【中圖分類號(hào)】TP311 【文獻(xiàn)標(biāo)識(shí)碼】A 【文章編號(hào)】1674-4810(2015)35-0097-03
由于Android具有開源和免費(fèi)的特點(diǎn),得到了大量移動(dòng)終端制造商的支持,各種各樣的Android應(yīng)用層出不窮。在應(yīng)用數(shù)量不斷增長(zhǎng)的同時(shí),盜版應(yīng)用的數(shù)量也隨之增加。為了阻止應(yīng)用被破解或篡改,多種保護(hù)Android應(yīng)用的方法也應(yīng)運(yùn)而生,本文主要對(duì)現(xiàn)有的Android應(yīng)用保護(hù)技術(shù)進(jìn)行歸納總結(jié)。
一 Android應(yīng)用結(jié)構(gòu)
Android系統(tǒng)的結(jié)構(gòu)如圖1所示,應(yīng)用程序的執(zhí)行主要依賴于Android的核心庫(Libraries)和Dalvik虛擬機(jī)。
圖1 Android系統(tǒng)結(jié)構(gòu)
由于PC平臺(tái)的Java虛擬機(jī)不適合移動(dòng)終端,因此Google公司為Android平臺(tái)設(shè)計(jì)了Dalvik虛擬機(jī)。它是Android應(yīng)用程序的最終運(yùn)行環(huán)境。除了本地庫代碼可以直接在底層運(yùn)行外,應(yīng)用程序的其他部分都被編譯為Dalvik字節(jié)碼在Dalvik虛擬機(jī)上運(yùn)行。Java程序經(jīng)過編譯后會(huì)生成Android平臺(tái)特有的dex(Dalvik Executable)文件,它是一種專為Dalvik虛擬機(jī)設(shè)計(jì)的壓縮文件格式,適合處理器頻率和內(nèi)存容量有限的移動(dòng)終端。
為了給用戶提供更好的操作體驗(yàn),Android應(yīng)用除了dex文件外還包括其他一些文件或文件目錄,如用于存儲(chǔ)簽名信息的META-INF目錄,用于存儲(chǔ)資源文件的res目錄,用于存儲(chǔ)本地代碼的lib目錄和二進(jìn)制資源文件resources.arsc等。這些文件會(huì)在Android應(yīng)用程序發(fā)布前,和dex文件一同打包成完整的apk(Android Package)文件。
二 Android應(yīng)用保護(hù)技術(shù)
一般來說,攻擊者對(duì)Android應(yīng)用的破解主要經(jīng)過以下幾個(gè)步驟:首先是對(duì)應(yīng)用的反編譯,通過反編譯的代碼分析程序的執(zhí)行流程,從中找到破解應(yīng)用的突破口;其次,如果對(duì)應(yīng)用的反編譯效果不理想,攻擊者會(huì)轉(zhuǎn)向?qū)?yīng)用的跟蹤調(diào)試,嘗試在跟蹤的過程中發(fā)現(xiàn)程序的某些關(guān)鍵數(shù)據(jù)或代碼;最后,如果完成了對(duì)Android應(yīng)用的破解,攻擊者會(huì)對(duì)應(yīng)用進(jìn)行重新打包,生成新的apk文件。為了阻止攻擊者對(duì)軟件的破解,可以采取以下幾種方法對(duì)軟件進(jìn)行保護(hù)。
1.代碼混淆技術(shù)
代碼混淆的目的是將程序轉(zhuǎn)化為語義相同但語句不同的版本。經(jīng)過混淆的代碼可以明顯加大分析代碼語義的難度,因此非常適合防范針對(duì)程序的反編譯攻擊。由于Android應(yīng)用主要使用Java語言進(jìn)行開發(fā),可以通過混淆Java源代碼,或混淆編譯后的字節(jié)碼來實(shí)現(xiàn)阻止攻擊者分析程序語義的目的。目前代碼混淆主要有以下幾種:
第一,詞法混淆和數(shù)據(jù)混淆。詞法混淆是改變或去除函數(shù)名或變量名原有含義的一種混淆方法,而數(shù)據(jù)混淆是對(duì)變量或數(shù)據(jù)結(jié)構(gòu)進(jìn)行分割或合并的一種混淆方法。De AR提出一種通過交換程序中的變量名、函數(shù)名和類名的詞法混淆方法,這種方法的特點(diǎn)是不僅可以去除程序中的詞法信息,而且可以進(jìn)行逆向混淆。Chan提出了一種對(duì)標(biāo)識(shí)符進(jìn)行修改和重用的詞法混淆算法。這種方法不是直接對(duì)標(biāo)識(shí)符重命名,而是盡可能重用已有的標(biāo)識(shí)符。經(jīng)過這種方法混淆的程序,其中存在大量名稱相似的標(biāo)識(shí)符,攻擊者很難從中分析出函數(shù)或變量原有的含義。Collberg總結(jié)了多種數(shù)據(jù)混淆的方案,如多變量(或數(shù)組)的合并、單變量(或數(shù)組)的拆解、靜態(tài)字符串的動(dòng)態(tài)生成等。這些方法的目的都是去除原始代碼中的有意義信息,增加攻擊者理解代碼的難度。
第二,類混淆和布局混淆。Sosonkin等人提出了類合并和類拆分兩種混淆方法。顧名思義,類合并是將原有類中的變量和函數(shù)進(jìn)行組合后生成新類,而類拆分則是將一個(gè)完整的類拆分成多個(gè)相互關(guān)聯(lián)的小類。無論是類合并還是類拆分,都會(huì)改變?cè)蓄愔g的調(diào)用或繼承關(guān)系,人為地增加代碼分析的難度。
布局混淆主要采用刪除調(diào)試、注釋信息、改變數(shù)據(jù)的分布順序?qū)Τ绦蜻M(jìn)行混淆。由于在編寫程序時(shí)往往會(huì)留下大量的注釋信息,而邏輯上相關(guān)的數(shù)據(jù)往往也會(huì)被程序員放置在物理上相鄰的位置,這些都會(huì)成為攻擊者分析程序的線索。為了清除這些有可能被攻擊者利用的信息,Collberg提出了一些布局混淆的方法,如改變實(shí)例變量、方法或數(shù)組的順序等。
第三,控制流混淆。程序的控制流信息是一種非常重要的程序結(jié)構(gòu)信息。如果攻擊者重構(gòu)出程序的控制流信息,不僅可以了解程序的工作流程,而且還可以很容易地對(duì)程序的執(zhí)行過程進(jìn)行篡改。因此,必須使用某種方法對(duì)于程序的控制流信息進(jìn)行修改,使其變得難以理解,從而增加攻擊者破解的難度。
對(duì)于控制流信息的修改,一般采用控制流混淆技術(shù),具體有以下幾種方法:一是通過內(nèi)聯(lián)、外聯(lián)變換改變代碼的組織結(jié)構(gòu)。例如,合并函數(shù)或使用增加額外參數(shù)的辦法來控制函數(shù)的執(zhí)行次序。這種方法改變了原有代碼中函數(shù)的調(diào)用順序和執(zhí)行次數(shù),也稱為控制聚合混淆。二是對(duì)原有代碼的執(zhí)行方向進(jìn)行調(diào)整。例如,原有代碼中的增序循環(huán)可以轉(zhuǎn)變?yōu)橄喾吹慕敌蜓h(huán)。這種方法不會(huì)改變程序的執(zhí)行,但攻擊者卻會(huì)產(chǎn)生迷惑,因此也稱為控制順序混淆。三是通過“壓扁”“平整”控制流,改變?cè)谐绦虻姆种мD(zhuǎn)移結(jié)構(gòu)。例如,將多個(gè)IF…ELSE分支整合成一個(gè)多分支的switch結(jié)構(gòu)。這種方法將原本清晰的條件分支轉(zhuǎn)變?yōu)榛逎y懂的分支結(jié)構(gòu),從而增加了分析的難度,因此也稱為Dispatcher混淆。四是通過增加無效代碼、Goto語句等,偽造額外的控制流,不僅消耗攻擊者的分析時(shí)間,也可以令某些反編譯軟件失效,這種方法也稱為控制計(jì)算混淆。
2.動(dòng)態(tài)加載技術(shù)
動(dòng)態(tài)加載是一種在PC平臺(tái)得到廣泛應(yīng)用的代碼保護(hù)技術(shù)。它的實(shí)現(xiàn)原理是將原始程序嵌套在另一個(gè)可執(zhí)行程序中,將該可執(zhí)行程序變成原始程序的“外殼”。動(dòng)態(tài)加載的原理如圖2所示。
圖2 動(dòng)態(tài)加載原理
當(dāng)用戶運(yùn)行增加了“外殼”的可執(zhí)行程序時(shí),首先被執(zhí)行的是“外殼”代碼,它會(huì)將原始程序從數(shù)據(jù)段中解密出來,釋放到內(nèi)存或文件系統(tǒng)中,然后根據(jù)一定的條件(如驗(yàn)證用戶身份是否合法)決定是否將運(yùn)行權(quán)交給原始程序。如果攻擊者對(duì)增加了“外殼”的可執(zhí)行文件進(jìn)行反編譯,只能得到“外殼”代碼的反編譯結(jié)果,無法窺探到原始程序的代碼。
對(duì)Android應(yīng)用的動(dòng)態(tài)加載保護(hù)可以通過使用Java類加載器和Jni調(diào)用本地代碼實(shí)現(xiàn)。如果使用Java類加載器,那么需要生成“外殼”程序的dex文件,并將原始程序的dex文件作為數(shù)據(jù)嵌入“外殼”程序的數(shù)據(jù)段中,形成圖3所示的結(jié)構(gòu)。
Dex Header
Checksum
Signature
File_size
……
Loader代碼
加密壓縮后的原始dex代碼
圖3 加殼后的dex文件
當(dāng)“外殼”程序開始執(zhí)行后,它會(huì)將數(shù)據(jù)段中的原始dex文件進(jìn)行恢復(fù),存放在文件系統(tǒng)中,然后通過DexClassLoader加載運(yùn)行原始的dex文件。該方法實(shí)現(xiàn)簡(jiǎn)單,但需要將原始dex文件釋放到文件系統(tǒng)中,存在一定的安全隱患。
為了克服將原始dex文件釋放到文件系統(tǒng)中的缺點(diǎn),Patrick提出了一種利用Jni調(diào)用openDexFile(byte[ ])函數(shù)來實(shí)現(xiàn)加載dex文件的方法。由于該方法可通過一個(gè)字節(jié)數(shù)組來傳遞 dex文件,原始dex文件可以直接釋放到內(nèi)存中,無須寫入文件系統(tǒng),因此避免了文件泄露的危險(xiǎn)。
3.軟件水印技術(shù)
軟件水印是一種把程序的版權(quán)信息和用戶身份信息嵌入到程序中,或利用程序本身的一些特征(如代碼結(jié)構(gòu)、調(diào)用關(guān)系等)來識(shí)別盜版軟件的技術(shù)。由于Android應(yīng)用在被攻擊者破解后,往往會(huì)被重新打包發(fā)布,因此目前針對(duì)Android應(yīng)用的軟件水印保護(hù)研究主要集中在如何檢測(cè)應(yīng)用的相似度,從而檢測(cè)出被重新打包的盜版應(yīng)用。
Wu Zhou以Dalvik字節(jié)碼中的操作符和操作數(shù)作為應(yīng)用的特征,設(shè)計(jì)了一種應(yīng)用相似度檢測(cè)系統(tǒng)。該系統(tǒng)利用模糊散列技術(shù),分別提取原始程序和目標(biāo)程序的特征,然后依據(jù)特征值的近似程度作為檢測(cè)的結(jié)果。
為了提高檢測(cè)的準(zhǔn)確度,Jonathan將較難被篡改的程序依賴關(guān)系圖PDG(Program Dependency Graph)作為程序的特征,提出了一種基于PDG的相似度檢測(cè)系統(tǒng),并通過實(shí)驗(yàn)證明該方法的有效性。
4.反跟蹤調(diào)試技術(shù)
跟蹤調(diào)試軟件是程序設(shè)計(jì)人員發(fā)現(xiàn)程序中潛在錯(cuò)誤的重要工具,但攻擊者同樣可以使用跟蹤調(diào)試軟件來記錄程序的執(zhí)行過程、內(nèi)存訪問和文件讀寫數(shù)據(jù),從中查找分析程序執(zhí)行中的關(guān)鍵部分,從而對(duì)程序進(jìn)行破解。為了讓攻擊者得不到程序執(zhí)行時(shí)的信息,可以使用以下的方法阻止跟蹤調(diào)試軟件對(duì)程序進(jìn)行動(dòng)態(tài)跟蹤。
第一,時(shí)間差異法。時(shí)間差異法主要是通過在代碼的任意兩端插入獲取當(dāng)前時(shí)間的函數(shù),通過計(jì)算兩端時(shí)間的差值,來判斷是否有調(diào)試器附著在本程序進(jìn)程上。如果程序沒有被調(diào)試器附著,那么程序的執(zhí)行速度完全取決于CPU的運(yùn)算速度,在代碼任意兩端設(shè)置的時(shí)間函數(shù)所計(jì)算出的時(shí)間差應(yīng)該是一個(gè)很小的、固定的值。但是,如果程序被調(diào)試器附著后,攻擊者往往會(huì)對(duì)程序進(jìn)行單步執(zhí)行跟蹤,從而觀察、分析程序的執(zhí)行過程,這樣一來勢(shì)必造成時(shí)間差的大幅增加。因此,可以通過編寫代碼,在需要保護(hù)的代碼兩端設(shè)置計(jì)時(shí)函數(shù)并設(shè)置閾值。如果計(jì)時(shí)函數(shù)計(jì)算出的時(shí)間差超過閾值,則說明程序很有可能被調(diào)試器附著,可以采取終止程序等手段來阻止攻擊者的跟蹤調(diào)試。
第二,父進(jìn)程判別法。調(diào)試器可以通過兩種方法對(duì)目標(biāo)程序進(jìn)行調(diào)試,一種是在目標(biāo)程序運(yùn)行后,附著在目標(biāo)程序上對(duì)其進(jìn)行跟蹤,另一種是首先運(yùn)行調(diào)試器程序,繼而由調(diào)試器程序啟動(dòng)目標(biāo)程序,將目標(biāo)程序作為調(diào)試器程序的子進(jìn)程,進(jìn)行跟蹤調(diào)試。子進(jìn)程可以通過操作系統(tǒng)提供的函數(shù)來獲得父進(jìn)程的PID(Process Identifier),這是該進(jìn)程在系統(tǒng)中獨(dú)一無二的標(biāo)識(shí)信息。通過PID,子進(jìn)程還可以進(jìn)一步獲得父進(jìn)程的其他信息,如進(jìn)程映像名稱。子進(jìn)程可以將獲得的父進(jìn)程映像名稱與流行的調(diào)試器映像名稱進(jìn)行對(duì)比,從而判斷自己是否處于被調(diào)試器加載啟動(dòng)的狀態(tài)。
在Android平臺(tái)中,一個(gè)進(jìn)程可以通過函數(shù)getppid獲得其父進(jìn)程的PID。如果該程序是由NDK編寫,那么該程序的父進(jìn)程應(yīng)該與該程序所在的APK包同名。如果程序判斷兩者不同,則程序極有可能是作為某種調(diào)試器的子進(jìn)程,此時(shí)程序可以采取停止運(yùn)行來對(duì)抗調(diào)試。
三 總結(jié)及展望
如何防止攻擊者對(duì)軟件進(jìn)行破壞或盜版一直是信息安全領(lǐng)域的研究熱點(diǎn),本文選擇Android應(yīng)用作為研究目標(biāo),分析了Android應(yīng)用開發(fā)的結(jié)構(gòu),闡述了幾種常見的Android應(yīng)用保護(hù)技術(shù),對(duì)這些技術(shù)的特點(diǎn)和適用范圍進(jìn)行了總結(jié)。利用這些技術(shù),開發(fā)人員可以不同程度地延緩或阻止攻擊者對(duì)應(yīng)用的破解,保護(hù)自身的合法權(quán)益。
參考文獻(xiàn)
[1]史揚(yáng)、曹立明、王小平.混淆算法研究綜述[J].同濟(jì)大學(xué)學(xué)報(bào)(自然科學(xué)版),2005(6)
[2]王一賓、陳意云.代碼迷惑技術(shù)研究進(jìn)展[J].吉林大學(xué)學(xué)報(bào)(信息科學(xué)版),2008(4)
[3]羅宏、蔣劍琴、曾慶凱.用于軟件保護(hù)的代碼混淆技術(shù)[J].計(jì)算機(jī)工程,2006(11)
[4]王建民、余志偉、王朝坤等.Java程序混淆技術(shù)綜述[J].計(jì)算機(jī)學(xué)報(bào),2011(9)
[5]趙躍華、郭玉杰.面向?qū)ο蟮目刂屏鬓D(zhuǎn)換方法[J].計(jì)算機(jī)工程與設(shè)計(jì),2010(20)
[6]張鵬、牛少彰.Android平臺(tái)軟件保護(hù)技術(shù)[J].中國電子商情(通信市場(chǎng)),2014(1)
[7]張立和、楊義先、鈕心忻等.軟件水印綜述[J].軟件學(xué)報(bào),2003(2)
[8]吳世忠、郭濤、董國偉等.軟件漏洞分析技術(shù)進(jìn)展[J].清華大學(xué)學(xué)報(bào)(自然科學(xué)版),2012(10)
[9]王浩宇、王仲禹、郭耀等.基于代碼克隆檢測(cè)技術(shù)的Android應(yīng)用重打包檢測(cè)[J].中國科學(xué)(信息科學(xué)),2014(1)
〔責(zé)任編輯:龐遠(yuǎn)燕、汪二款〕