歡迎來到 黑吧安全網 聚焦網絡安全前沿資訊,精華內容,交流技術心得!

開發一個基于Dalvik字節碼的相似性檢測引擎,比較同一款Android應用程序的不同版本之間的代碼差異(一)

來源:本站整理 作者:佚名 時間:2019-06-17 TAG: 我要投稿

Dalvik是Google公司自己設計用于Android平臺的虛擬機,Dalvik虛擬機是Google等廠商合作開發的Android移動設備平臺的核心組成部分之一。它可以支持已轉換為 .dex(即Dalvik Executable)格式的Java應用程序的運行,.dex格式是專為Dalvik設計的一種壓縮格式,適合內存和處理器速度有限的系統。Dalvik 經過優化,允許在有限的內存中同時運行多個虛擬機的實例,并且 [1]  每一個Dalvik 應用作為一個獨立的Linux 進程執行。獨立的進程可以防止在虛擬機崩潰的時候所有程序都被關閉。很長時間以來,Dalvik虛擬機一直被用戶指責為拖慢安卓系統運行速度不如IOS的根源。2014年6月25日,Android L 正式亮相于召開的谷歌I/O大會,Android L 改動幅度較大,谷歌將直接刪除Dalvik,代替它的是傳聞已久的ART。
我會在這篇文章中,為你介紹如何對比同一款Android應用程序的不同版本之間的代碼迭代情況。簡單來說,就是通過Android應用程序中的相似性檢測。
《針對Dalvik字節碼的相似性檢測引擎,比較同一款Android應用程序的不同版本之間的代碼差異》這篇文章我們計劃分2部分來講解,在本文中,只介紹如何利用Quarkslab公司開發的diff引擎。第二部分除了介紹一個用例:URl欺騙漏洞(CVE-2019-10875) ,我們還會介紹如何將Redex與diff工具相結合,檢測被混淆處理的應用程序中到底發生了哪些修改?
背景知識
相似性檢測并不是一個新概念,并且已經被一些學術論文以及BinDiff,Diaphora,YaDiff等工具所驗證。
相似性檢測這個概念可以用于各個目的,比如在一個集合中識別一個函數,或者在APK中檢測一個庫或第三方SDK。在本文的示例中,我們的目標是從APK的兩個不同版本中提取的兩組類或方法中發現被修改過的代碼。
diff的檢測結果可以用于檢測漏洞的修補情況,基于先前的分析對混淆的代碼(比如Proguard輸出的代碼)進行逆向分析。
實現diff引擎時遇到的挑戰
與匯編代碼不同,Dalvik指令集非常冗長,而且字節碼的結構使分析變得更容易。例如,在Dalvik字節碼中,訪問方法字符串很簡單,而在本機代碼中,我們必須處理重定位等問題。
但是,Android應用程序變得越來越大,會導致采用多個.dex文件。我們需要克服的第一個挑戰是有效地處理應用程序的多DEX結構。第二個挑戰是實現一個可擴展的diff引擎,該引擎支持大量要比較的對象。在常見的Android應用程序中,嵌入數萬個類是相當普遍的。
解決辦法
利用DEX格式和Dalvik指令集帶來的一些特殊功能,來設計和構建針對Android應用程序的diff引擎。
首先,為了準確理解diff引擎的實現,我們需要介紹它的用途。 diff引擎可以將兩組類(來自兩個APK)作為輸入對象,并輸出對應的匹配列表。每個匹配列表都包含有相似性值,該值越趨近于1,類就越相似。當距離嚴格等于1時,我們假設它是完全匹配的。這意味著這兩個匹配的類看起來完全一樣。這是一個至關重要的參考,因為如果我們能弄清楚類有多相似,那么我們就能分析檢測到的變化情況。
現在讓我們來介紹diff引擎的內部結構,從技術上講,它包括三個主要階段,使我們能夠快速有效地比較兩組類:第一階段將類劃分為簇,第二階段執行粗略比較,而最后一個階段執行準確的比較。
在運行這些階段之前,我們可以選擇減少發送給diff引擎的類的輸入集,以提高性能。這一步非常重要,因為它會顯著影響diff引擎的運行。如果diff引擎將更快,更有可能精準地找到其中的差異。換句話說,發送給diff引擎的類的輸入集越少越好。例如,可以按如下方式減少類的集合:
v1, v2 = load("v1.apk"), load("v2.apk")
classes_v1 = filter(v1.classes, CONDITION)
classes_v2 = filter(v2.classes, CONDITION)
diff_result = diff(classes_v1, classes_v2)
準備階段:過濾類
由于應用程序常常嵌入一大堆外部模塊和第三方SDK,因此類的數量可能非常巨大。例如,Twitter應用程序包含36352個類,但只有10078個位于包名com.twitter.android中。但是,大多數情況下,在檢測Android應用程序時,逆向分析程序只關注特定的部分或包。這意味著許多類根本不在被分析的范圍中。在這種情況下,將所有類別作為一個廣泛的類別進行比較是沒有意義的。此外,根據應用程序的大小,比較太多的類將更加耗費資源和時間。由于Dalvik的設計和它從Java借用的模塊化模型,這些功能通常已經分成不同的包,并且這些信息可以從DEX文件中被檢索到。
因此,利用包是減少輸入集的好方法,因為內部包結構不太可能在不同版本之間發生根本變化。比如,在本文的示例中我們只處理包com.android.app.signup和com.android.app.webapi中的類。請注意,所有嵌套包(如com.android.app.webapi.ping)都未在此處表示。

根據包名過濾類
第1階段:聚類方法(Clustering)
此時,我們已經選擇了兩組類——A類和B類,來對它們進行比較。現在進入diff引擎的內部,將類分成幾個組。這些組稱為簇(cluster),并根據類所在的包構建。如果類PingRequest和PingResponse都是com.android.app.webapi.ping的一部分,它們將被放置在同一個簇中。盡管如此,它們不會同時出現在com.android.app.webapi.picture和com.android.app.webapi.ads中的SendPictureRequest和AdsResponse。 然后,來自集合A的每個簇根據其包名,將它們鏈接到集合B中的相應簇。兩個簇就構成了我們所說的池(pool)。

簇類和創建池之后的結果
通過處理類池,我們就可以進行規模化的比較,這大大減少了比較的總體數量,并實現了并行性計算。
但是,這個階段不是強制進行的,可以在特定情況下被跳過。
第2階段:批量比較
在優化和減少比較集之后,我們可以開始比較每個池中的類。然而,有些池可能仍然非常大,并且可能包含數千個類的集群。因此,我們需要一種有效的方法來處理這個問題。為了解決這個問題,我們從應用于近似重復檢測的技術(例如用于查找重復頁面的Google網絡爬蟲)中獲取了靈感,更確切地說,我們應用了基于SimHash的算法。

[1] [2] [3]  下一頁

【聲明】:黑吧安全網(http://www.pcpbjo.tw)登載此文出于傳遞更多信息之目的,并不代表本站贊同其觀點和對其真實性負責,僅適于網絡安全技術愛好者學習研究使用,學習中請遵循國家相關法律法規。如有問題請聯系我們,聯系郵箱[email protected],我們會在最短的時間內進行處理。
  • 最新更新
    • 相關閱讀
      • 本類熱門
        • 最近下載
        云南快乐十分前三电视