Android逆向隨筆之遇見MultiDex

MZ2013 8年前發布 | 18K 次閱讀 安卓開發 Android開發 移動開發

0x00 Who is Multidex

很多大廠的Android App因為業務量大,引用庫多導致其apk包的中的類于方法劇增.這樣就有可能出現因為方法數過多導致編譯失敗的情況.產生這個問題的主因是dex文件格式的限制.一個DEX文件中method個數采用使用原生類型short來索引文件中的方法,也就是4個字節共計最多表達65536個method,field/class的個數也均有此限制。對于DEX文件,則是將工程所需全部class文件合并且壓縮到一個DEX文件期間,也就是Android打包的DEX過程中,單個DEX文件可被引用的方法總數被限制為65536.

為解決這個問題,谷歌推出了Multidex技術,簡單來說就是將一個apk中的dex文件拆分成多個分主次先后加載,當然在這之前業界已經開始使用插件化來弱化此類問題.現在市面上也有很多Multidex和插件化兩種方案都使用的app.

Multidex會給逆向工程師帶來如下麻煩:

1.常見工具靜態分析的類和方法不全

2.靜態分析工具因為交叉引用的問題導致反編譯失敗或崩潰

3.動態調試中無法下斷點

4.hook的時候找不到制定的類和方法

0x01 merge multidex

在逆向apk中經常會遇到一些類丟失,反編譯崩潰的情況.如果這時候去觀察apk壓縮包會發現其中有超過一個dex,上圖中就有兩個dex.那么這個app分析起來就不會很輕松了,因為這個叫dex分包的技術直接意味著你要面對超過65536個java方法.而這篇文章主要就是講解筆者在遇到這種情況的時候一些應對手法.

如果你的dex2jar版本為v2.1之前的版本,那么dex2jar就會默認轉化第一個dex文件而忽略其他dex文件. 52f26c6 2.1版本開始支持multidex,直接執行

d2j-dex2jar.sh the-apk-witch-mutidex.apk

就可以轉化所有dex文件到一個jar包中.

在dex2jar更新v2.1之前筆者是用的一個比較”耿直”的方法解決這個問題,因為dex的method數量有限但是jar包對method是沒有特別限制的,所以我寫了一個腳本將apk中多個dex先轉化為jar文件之后解壓縮最后合并打包壓縮,同樣可以得到完全的反編譯文件.

Android逆向中出鏡率較高的jeb在早期版本v1.x也同樣有類似尷尬的問題,只默認反編譯第一個dex文件.但是到v2.2也開始支持multidex采用merge的方式解決多個dex的反編譯問題.也就是在jeb2.2之后就可以無障礙的在multidex中使用交叉引用功能了.

在很長一段時間使用jeb1.5的時候解決這個問題的辦法同樣也也merge多個dex的smali代碼,因為要回編譯至dex所以就無法突然65K方法數的限制,那么就要想辦法對multidex進行瘦身.大數據情況下我們只關心其自有代碼,對其依賴庫往往是帶過的(大多數情況是和配置文件中application或者入口Activity同路徑的代碼).這里就需要選擇一個較小的dex去識別去除一些依賴庫和第三方sdk比如android support / google gson,然后抽取另外的dex的主包smali代碼合并到較小的dex中.最后回編譯至dex拖入jeb1.5中就可以正常分析了.

0x02 attach multidex 

在multidex的測試過程中還會出現一種情況,就是使用xposed hook其方法的時候,如果方法位于默認dex中是可以的正常hook,但是如果方法位于dex分包中xposed就會報錯提示所要hook的方法所在類無法找到.

要分析這個問題的原因以及解決辦法,就要先了解multidex的載入過程以及xposed的hook時機.

dex分包加載大致流程如下,可以得出分包是滯后主包不少時間加載的:

1.檢測是否有分包需要安裝,系統是否支持multidex

2.從apk中解壓出分包

3.通過反射將分包注入到當前classloader

而xposed為了能讓module及時載入執行所以得盡快調用handleLoadPackage(),所以此時獲取的context的classloader中只要默認dex主的包的類.

因此我們得想法得到完整的上下文context,比較明顯的獲取完整context的hook時機有如下兩處:

MultiDex.install()

MultiDexApplication.attachBaseContext()

而xposed的作者建議是選擇android.app.Application.attach(),因為attachBaseContext是有概率被重寫的不穩定.所以選擇方法內調用了attachBaseContext的Application.attach().

示例代碼如下

分析到這里就可以想到一些加殼后的app無法正常hook也可能是類似原因可以用同樣的方法解決(這里前提當然是能脫殼看到代碼且殼沒對hook做對抗,如果有對抗還是脫了之后回打包比較穩妥.).下圖這個殼同樣也佐證了attachBaseContext被重寫的可能,直接hook被重寫的attachBaseContext也是可行的.

0x03refer

https://developer.android.com/studio/build/multidex.html#about

http://souly.cn/%E6%8A%80%E6%9C%AF%E5%8D%9A%E6%96%87/2016/02/25/android%E5%88%86%E5%8C%85%E5%8E%9F%E7%90%86/

http://bbs.pediy.com/showthread.php?t=212332

https://github.com/pxb1988/dex2jar

https://github.com/rovo89/XposedBridge/issues/30#issuecomment-68488797

http://tech.meituan.com/mt-android-auto-split-dex.html

https://android.googlesource.com/platform/frameworks/multidex/+/master/library/src/android/support/multidex

 

 

來自:http://drops.wiki/index.php/2016/10/26/android-multidex/

 

 本文由用戶 MZ2013 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!