Android逆向隨筆之遇見MultiDex
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://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
來自:http://drops.wiki/index.php/2016/10/26/android-multidex/