?

Android應用Smali代碼混淆研究

2021-08-02 03:35邱子楊
計算機技術與發展 2021年7期
關鍵詞:數據流攻擊者字典

邱子楊,付 雄

(南京郵電大學 計算機學院,江蘇 南京 210003)

0 引 言

根據2016年第一季度統計報告指出[1],Android設備所占市場份額為76.4%。但同時根據《騰訊移動安全實驗室2016年上半年手機安全報告》指出[2],2016年上半年新増安卓惡意應用安裝包918萬個,是2014年全年新增惡意應用包的9.15倍,感染用戶數量已經超過2億,同比去年增長了42%。安卓用戶群體的高比例以及惡意應用軟件的激增使得安卓應用軟件的安全防護技術日漸重要。

攻擊者一般會通過對安卓應用程序進行反編譯并篡改代碼再對其進行重新打包并且重新簽名來進行惡意行為的攻擊。當攻擊者攻擊一個安卓應用程序文件時,并不會直接反匯編去分析其smali代碼[3],因為smali代碼過于復雜,難以讀閱,而他們往往會把可執行文件apk反編譯成java源碼,然后從java源碼中獲取到關鍵代碼的位置,然后再去對應的smali代碼位置進行篡改[4],然后重新打包,重新簽名就可以得到一個被纂改過的安卓應用程序。

因此,防止Android應用程序逆向分析是非常重要的。在以往的研究中,Enck等列出了Android系統的安全性分析方法[5],分析了Android系統的安全性模型并解釋其復雜性。Felt和Fahl等[6-7]詳細說明了Android系統的安全性。Bernhard等[8]開發了Bauhaus,基于軟件安全技術和代碼分析技術的Android系統源代碼分析工具,并通過案例研究從安全認證和許可機制的角度分析了Android系統實施中的不一致信息。

牛豪飛[9]實現一套在ART模式下的安卓應用保護方案。通過對Android平臺的體系結構、安全機制以及常見靜態和動態攻擊的分析,提出了動態和靜態兩個方向的安卓安全防御方案。尉惠敏[10]提出了一套基于Hook文件的自修改方案,可以應對大部分攻擊手段。其加密粒度更小,加密精度更準確。實現了So動態庫中函數運行前解密運行后加密,保證任何時刻So動態庫都不是完整的明文。是一種針對于Hook攻擊的動態防御機制。

對于Java層面的安卓應用加固,彭守鎮[11]提出了基于資源文件的加密方式。對反編譯后的dex文件進行加密混淆處理,對資源文件進行加殼處理,從而預防apk被反編譯篡改,增強打包難度。呂苗苗[12]提出基于Java的安卓應用代碼混淆技術。通過抽離安卓軟件中的code_item代碼,將其進行混淆然后形成混淆代碼索引表,同時在So中進行封裝。最后采取JNI機制注冊封裝后的代碼,生成特定的執行環境。從而做到對安卓應用代碼的混淆加固。

對于smali層面的安卓加固,鄭琪等人[13]通過插入多余的控制流和壓扁控制流對控制流進行混淆以對安卓應用進行防御。并從功能、性能兩個方面做出了評價。劉方圓等人[14]同樣在smali層面對安卓應用加固進行研究,其主要是對寄存器的值加以混淆以及通過不透明謂詞對控制流進行混淆,并且在強度、彈性、開銷進行的技術評價。吳林[15]提出了基于Dalvik字節碼指令的混淆技術,從數據流和控制流兩個層面對apk進行混淆。

綜合現有的工作,大部分的工作都是針對于Android應用程序中源碼級別Java代碼的混淆,對于Android應用程序中smali級別的代碼的安全性分析還是比較缺少。對于Java源代碼層面的混淆目前主要是控制流和標識符混淆兩個方面,可是大部分情況下廠商并不可能直接提供源碼給安全公司,這樣的話這種保護就無法發揮其作用。對于現有的smali層面的研究,主要圍繞數據流和邏輯流進行混淆[16-18],且混淆方式并不考慮對原來安卓應用的額外消耗,且混淆方式單一,缺乏動態性。

針對上述代碼混淆技術出現的問題,文中提出了smali代碼的混淆保護方法,在除去數據流和控制流兩個層面之外,又增加了邏輯流層面的混淆,并且對于數據流和控制流消耗方面也做了優化和把控,其主要貢獻如下:

(1)設計實現smali代碼混淆系統,不需要提供源碼,但能對抗攻擊者的攻擊。

(2)針對之前研究的混淆方式,提出新的混淆方式邏輯流混淆用來加強混淆強度。

(3)實驗與評價。用這種方法保護后的應用程序可以抵抗靜態分析,并使反編譯后的代碼出錯。同時,還評估了其對時間和空間性能的影響,以證明該方法的有效性。

1 混淆框架綜述

文中提出的混淆方式不同于Java策略方向的安全加固,不需要源碼但是完全可以對抗惡意攻擊,通過對Android應用程序代碼中間產物smali代碼的混淆,使得攻擊者無法獲取正確的邏輯代碼。

下面簡要介紹該方法的混淆過程(見圖1):

圖1 混淆方法過程

step1:反編譯待保護的apk文件;

step2:遍歷所有smali文件,通過數據流混淆模塊進行混淆;

step3:遍歷所有smali文件,通過控制流混淆模塊進行混淆;

step4:遍歷所有smali文件,通過邏輯流混淆模塊進行混淆;

step5:將編譯后的文件重新打包為apk文件;

2 加密策略

在數據流混淆模塊中,對數據通過加密策略進行混淆,為了不影響源程序的性能,且盡量縮短加密過程但對數據能起到混淆的作用,所以文中提出了一種基于字典的簡易加密方式。但由于字典加密算法有較大風險,字典一旦被破解或盜取就面臨數據泄露的風險,所以又通過RSA對字典進行加密存儲在服務器端,且字典是由系統隨機生成的,所以不同Apk的數據加密方式是不同的,減少被破解的風險。下面介紹字典的生成和傳輸過程。

step1:生成兩個數組A,B,其大小為26,且每個數組依次存放0-25數字;

step2:打亂A數組和B數組的內容,即為字典D;

step3:使用混淆系統中的私鑰對A與B進行加密存儲,生成加密字典RSA(D);

step4:混淆系統發送字典RSA(D),給需要加密的apk端,apk端通過公鑰解密得到字典D;

step5:使用字典D進行加密。

在上述過程中,小寫字母x對應的密文為A[index_x],其中index_x=ascii(x)-0;ascii(x)為x對應的ascii的碼值。同樣大寫字母X對應的密文為B[index_X],其中index_X=ascii(X)-0;ascii(X)為x對應的ascii的碼值。

3 混淆策略

Collberg等人[19]提出了代碼混淆的概念,提出了代碼混淆的基本定義,給出了第一個代碼混淆算法,將代碼混淆分為外形混淆、控制混淆、數據混淆和預防混淆,通過強度、執行代價、彈性來評估有效性。代碼混淆其實就是一種代碼功能一致性的轉化,會保留與之前代碼一致的有效性,通過某種混淆轉換,使得變換后的程序在具有相同功能的前提下更難分析[20]。如果程序和具有一致的可觀測行為,則稱其為混淆轉換。

代碼混淆的基本原理如圖2所示,整體上說混淆方式主要有靜態混淆和動態混淆兩個方式。靜態混淆有控制流混淆、數據流混淆等,動態混淆是通過自定義的混淆器來達到運行過程中動態的進行混淆以及解混淆的方法。

2017年,彩云社區在進行居民情況調查時,了解到楊家的事。李敬益打算啃啃硬骨頭,牽頭調解試試看。他把楊家七個兄妹都找來,挨個了解了下他們的想法;再把老太太的兩個兄弟請來,“兩個舅舅一來,講了句公道話,‘都是一家人,現在就剩下你們媽媽了,也得考慮考慮她?!崩罹匆媛犕?,心里大概有了數,這一家人的目光總圍著商鋪轉,如果按著以往的思路往下走,只討論商鋪的歸屬,這矛盾怕是難解。得轉換個思路,綜合考慮、綜合盤算。

圖2 smali代碼混淆原理示意圖

smali代碼混淆:

(1)基于字典加密的數據流混淆。

在Dalvik虛擬機中,由于字符串是通過明文形式顯示賦值給寄存器,然后再由具體操作在寄存器內取字符串的具體值,這樣就會造成代碼暴露的危險性。所以可以將字符串進行加密處理,對數據進行混淆,增加代碼閱讀難度,降低破解代碼邏輯風險。

在傳統加密方式中,常用的加密方式為對稱加密和非對稱加密,但其加密方式繁瑣且性能消耗大,但是混淆方法中,對原有程序的影響越小則混淆方法是越有效的,所以文中采用基于字典的加密方式來簡化加解密過程,減少對原有程序的影響。這種加密方式即隨機生成a-z以及A-Z唯一對應的字典密文后進行加密。數據流混淆過程如算法1所示。

算法1:數據流混淆。

輸入:待保護應用反編譯之后的smali文件。

輸出:數據流混淆之后是smali文件。

1.設smali文件集合為F=(f1,f2,…,fn),其中fi表示第i個smali文件。

2.遍歷集合F,逐行讀取fi文件。

3.設行內容為fij,記錄加密位置pm=j(當fij滿足正則s*const-strings+(v|p)(d),s+”(.*)”),添加到集合Pi中。

4.設字典加密算法為D(x),遍歷集合Pi,獲取加密字符串s=D(fipm),替換fipm=s。

5.遍歷集合F,輸出。

6. end

算法1只是對如下指令const-string v0, “InjectLog”進行簡單的修改,并且由于加密算法是基于字典進行加密,所以并不會修改字符串長度,且解密過程是基于字典式的,所以查詢密鑰對應原文的時間復雜度為O(1),并不會對系統性能產生很大的消耗,也不會對系統文件大小產生改變,但是能在一定程度上抵抗逆向工具的逆過程,是一種低消耗、高性能的數據流混淆方式。

圖3為數據流混淆后的結果。

圖3 數據流混淆

可以看出,有意義的字符串全部被更換為了無意義的字符串,這樣就使得攻擊者無法從字面獲取程序的意義從而進行邏輯分析,很大程度上增加了邏輯分析的難度。

(2)低消耗控制流混淆。

算法2:控制流混淆。

輸入:待保護應用反編譯之后的smali文件。

輸出:控制流混淆之后是smali文件。

1.設smali文件集合為F=(f1,f2,…,fn),其中fi表示第i個smali文件。

2.設存儲方法的集合為Map集合,M=(mi,ci),其中mi表示方法的全限定名稱,ci表示mi被調用的次數。

3.遍歷集合F,逐行讀取fi,如果當前調用了方法mi,檢測Map是否存在(mi,ci),如果存在則ci++,否則添加一個新元素(mi,ci)(其中ci=1)到Map中,并且維持方法總量C=C+ci(C初始值為0)。

5.重新遍歷集合F,逐行讀取fi,如果當前調用的方法mi∈P,則執行控制流混淆器D(x),混淆結果s=D(mi),替換fi=s。

6.遍歷集合F,輸出。

7. end

控制流混淆相對于數據流混淆來說,是更有效的混淆方式,其原理是在程序的某些地方添加一些常用的控制switch、if等來隱藏原程序中真正的控制流程,從而阻止反編譯攻擊。并且在smali語法中,控制流語法復雜程度遠遠高于Java源代碼,其是通過跳轉指令來實現對代碼的邏輯控制,所以加入一些無效控制流或者修改一些控制流,可以很大程度混淆代碼,降低代碼的可讀性。

文中提出的低消耗控制流多注入的混淆方式,首先確定插入位置,確定插入位置的方式是將方法被調用次數作為依據,超過閾值的,將其被調用的位置確定為待插入位置。

控制流混淆不會對原有命令做修改混淆,而是在原有命令上增加無效控制流,比如常用的if分支,switch分支,這增加了原有程序的復雜性,給攻擊者分析smali代碼增加了難度。

圖4為控制流混淆的結果。

圖4 控制流混淆

可以看出,混淆后之前的簡單邏輯被加大了復雜度,出現了分支,從而干擾攻擊者的邏輯分析,增大了分析難度。

(3)邏輯流混淆。

對數據流混淆和控制流混淆來說,如果攻擊者通過數據分析獲取加密規則并且攻擊者對smali語言十分熟悉,這種情況下,數據流混淆和控制流混淆會顯得蒼白。

為加大混淆力度,文中提出一種新的混淆方式—邏輯流混淆,邏輯流是指程序的執行過程。

由于smali源代碼所有的邏輯必然都是與APP本身執行過程有關的,所以當攻擊者進行反編譯之后,對smali源代碼,在短時間內很有可能分析出APP執行過程從而對APP的安全造成危害。為了提高安全性,文中提出了一種邏輯流混淆的思想,讓攻擊者在短時間內無法分析出APP的邏輯流,或者讓其分析無效的邏輯流。

邏輯流混淆的具體做法是在APP邏輯流某一節點處添加不影響APP邏輯流和數據流的自定義邏輯流,不僅加大APP邏輯流的復雜程度,也由于無關邏輯流的加入,使得攻擊者對于APP執行過程的分析并不都是有效的,進而增加APP的安全性。對于自定義的邏輯流,如果過于復雜會增加APP對系統的消耗,過于簡單又對混淆加固起不到很大作用,所以選擇合適的自定義邏輯流是尤為重要的??刂屏骰煜^程如算法3所示。

算法3:邏輯流混淆。

輸入:待保護應用反編譯之后的smali文件。

輸出:控制流混淆之后是smali文件。

1.設smali文件集合為F=(f1,f2,…,fn),其中fi表示第i個smali文件。

2.構建邏輯流圖T=(t1,t2,…,tn),其中ti為樹節點,也就是調用的方法,其中T表示樹的層次遍歷序列,且T是一棵有序樹。

3.選擇邏輯流節點,這里采用隨機選取的方式,調用邏輯流混淆器D(x),結果t=D(ti),替換ti=t。

4.遍歷集合F,輸出。

5. end

圖5為邏輯流混淆的結果。

圖5 邏輯流混淆

可以看出,之前的邏輯前后不只是單純的一個邏輯的執行,而是被加上了多余的邏輯,而這些多余的邏輯是邏輯流混淆模塊自定義的,與程序本身邏輯流無關,也不會影響程序邏輯流的執行。這樣的混淆既做到了安全加固,增大攻擊者分析難度,也不會影響源程序的執行,且由圖可看出相對數據流混淆和控制流混淆,復雜度更高。

4 評價標準

4.1 強 度

4.2 執行代價

混淆程序Pr'相對于原始程序Pr由于混淆產生的額外開銷,通過執行代價來度量。

執行代價的定義如下:

表1 執行代價度量

4.3 彈 性

彈性用來度量混淆程序的抵抗攻擊程度,是指針對于反混淆程序的攻擊,主要包括反混淆程序運行時的時間和空間代價以及攻擊者編寫反混淆程序的代價。

彈性定義如下:

規定T是對Pr的一個單項的混淆變化當且僅當從原始程序Pr除去某些信息后無法通過混淆后的程序Pr'恢復出Pr。

5 有效性分析

5.1 強度分析

對于文中提出的smali代碼混淆方法從數據流、控制流、邏輯流三個層面進行混淆。在數據流混淆方面,將constr指定中存儲的字符串進行加密存儲,這種方法使得逆向分析獲取的字符串值是錯誤的,實驗結果如圖3所示。在控制流混淆方面,在關鍵函數調用指令和返回值獲取指令中間插入不透明謂詞,使得攻擊者無法獲得正確的控制流程,逆向工具逆向結果圖4所示。在此基礎上文中還提出了新的混淆方式,即邏輯流混淆方式,因為APP在逆向之后所有的邏輯流都是和APP本身運行有關的,所以引入邏輯流混淆,才進行一些無用邏輯的處理和調用。逆向工具逆向結果如圖5所示,當攻擊者利用逆向工具去逆向分析時,結果不僅僅是APP的邏輯流還有加入混淆的邏輯流。

5.2 開銷分析

對不同的混淆方式分別進行時間開銷的分析。對于數據流層面的混淆只是簡單的加密混淆對時間開銷必然沒有影響。對于控制流混淆,插入的無效控制流時間復雜度都為O(1),并且控制流個數的插入也是有限的,所以并沒有影響原程序的復雜度。對于邏輯流混淆,插入的新邏輯流的時間復雜度均為O(1),這在可以容忍的范圍之內。對于空間開銷來說,由于混淆僅僅是針對關鍵函數進行指令轉換、插入定量的無效控制流、修改控制流,以及插入定量的空間復雜度為O(1)的邏輯流,因此,smali代碼的混淆方法對于程序空間開銷來說影響較小。

5.3 彈性分析

被混淆的程序,在數據流層面其字符串的值被加密混淆,在控制流層面進行的混淆,如圖4所示,增加了程序的控制流復雜度;除此之外,對于邏輯流進行混淆,如圖5所示,增加了許多無關程序的邏輯流,加強了程序的復雜度??梢钥闯鑫闹械拇a混淆方法具有較好的彈性。

6 實驗結果

如圖1所示,文中設計并實現了一個smali混淆系統,能夠有效地抵抗逆向分析。

實驗環境:Android7.0紅米Note,Idea開發環境。測試用例說明如表2所示。

表2 測試用例說明

測試用例:本節采用四個自主編寫的Android應用程序作為測試用例,這四種應用程序是具有代表性的,完全可以表明混淆方法的有效性。

文中從兩個方面分析smali混淆系統的性能,一方面是通過應用程序保護方法的有效性來評估應用程序保護方法的質量,另一方面通過保護前后應用程序的性能消耗變化評估其質量。對于有效性,之前已經在強度、開銷、彈性進行了分析,接下來對性能消耗變化作根據四個測試用例的實驗結果進行分析,主要從三個方面分析性能消耗:保護前后的代碼長度變化,時間開銷變化和空間開銷變化。

由于移動設備往往在內存和處理器方面是受限的,所以應用程序的大小以及APP啟動時間很重要,這關乎到用戶體驗問題。因此對代碼長度變化以及啟動時間進行定量分析以此來證明smali混淆系統的有效性。

如表3所示,混淆程序相比于原始程序代碼長度并沒有顯著變化,主要原因如下:

表3 代碼長度和開銷

(1)對const-str中的字符串只是加密等長替換,所以對代碼長度不會有影響;

(2)只是簡單的指令替換;

(3)測試用例的代碼長度本身比較小,滿足混淆操作的指令并不多;

(4)邏輯流混淆插入的部分的邏輯,是新增的邏輯,由于新增邏輯本身并不大,所以對代碼長度和內存消耗也并不是很大。

為了更直觀地體現混淆操作對應用程序的影響并不大,另外比較了應用程序混淆前后啟動時間的變化(見表4)。

表4 啟動時間變化

4個應用程序在第一次啟動時,啟動時間在混淆前后有明顯的變化,分析原因可能是以下原因造成的:

(1)dex文件類加載器的替換;

(2)混淆方法的查找。但是在第一次啟動之后,可以發現啟動時間在混淆前后基本沒有變化。

7 結束語

針對Android應用程序容易被反編譯篡改smali源碼并重新打包重新簽名的問題,提出了一種smali代碼混淆的應用程序保護方法,不同于常規的Android應用程序保護,是針對于smali層面做的防護,無需獲得源碼即可進行混淆,并且在常規的數據流和控制流層面使用了新的算法。在數據流層面采用快速加解密的字典式對其進行混淆,在控制流層面,選取特定的位置進行混淆,并且控制流的插入會選取輕量級消耗的控制流,從而減少對程序開銷的影響。文中在此基礎上還提出了新的混淆層面邏輯流混淆,相對于數據流和控制流來說混淆強度更大,擴展性更強,這使得對Android應用程序的防御有很大的提升。同時也從強度、開銷、彈性三個方面對smali代碼混淆方法進行了分析,也從代碼長度和啟動時間定量進行了分析,實驗結果表明,smali代碼混淆方法是有效的。

總之,提出的smali代碼混淆對于解決Android安全性被破壞的問題有一定意義,但是對于自定義的邏輯流沒有進行很好的選擇,導致開銷上有一定影響。因此下一步工作將針對邏輯流進行優化,以更好地保護代碼并且減少消耗。

猜你喜歡
數據流攻擊者字典
優先級驅動的泛化航電網絡實時性能分析
基于貝葉斯博弈的防御資源調配模型研究
數據流和波形診斷技術在發動機故障診斷中的應用
字典的由來
數據流安全查詢技術綜述
正面迎接批判
正面迎接批判
大頭熊的字典
利用數據流進行電控故障診斷的案例分析
正版字典
91香蕉高清国产线观看免费-97夜夜澡人人爽人人喊a-99久久久无码国产精品9-国产亚洲日韩欧美综合