2020年1月21日 星期二

Android 動態解殼研究(三) - 動態解殼

在探討Dex(Dalvik Executable)檔案格式和加殼的方式之後,我們接下來是此篇的主菜,是關於Dex加殼後並自動化的提取解殼程式碼,這樣可以有效的節省人工分析的時間,那我們廢話不多說,直接進入主題。

一、Android Dex Runtime

除了VMP加殼,其餘的加殼方式我們都可以透過Android Framework來將它提取出來,不過我們必須知道Android是如何運行Dex程式碼。

1. DexFileParse 開始解析Dex檔。

2. dvmDefineClass 初始化Class資料。

3. dexReadClassDataMethod讀取Method資料、dexReadClassDataHeader讀取Header資料、dexReadClassDataField讀取Field資料。

4. loadMethodFromDex準備加載Method的程式碼。

5. dexGetCode加載Method的程式碼

6. dvmCallMethodV、dvmCallMethodA、dvmInvokeMethod調用Method程式。

7. dvmInterpret是運行時透過Just in time來解譯它(一次性將程式碼全部解譯)。

8. dvmInterpretPortable是透過Portable來解譯它(邊運行邊解譯)。

看來Android在運行Dex程式碼牽扯的程式碼非常的廣且複雜,其實主要就是區分為Dex檔案的讀取(紅色方框)和加載記憶體並運行它(藍色方框)。那麼我們的解殼程式要放在哪裡呢 ? 因為Android有分Just in time或Portable,那麼Portable的主要程式碼是透過Java所撰寫的,比較容易移植我們的解殼程式,也符合我們的需求,因此可以將解殼程式放置在這裡處理。



二、解殼時機

我們在解殼時,要如何知道我們要解哪隻程式呀 ? 我們可以從packages.list的檔案提取程式的名稱、UID和路徑,這樣就能讓解殼程式知道要解哪隻程式了。


三、odex (optimize Dalvik VM Executors)

動態解殼時,可能不會那麼順利,從記憶體上提取出來的Dex檔,有被Android系統優化過,檔案格式會變成odex,所以透過Jadx反編譯會解譯失敗,需要利用baksmali讓odex轉成Dex檔。



商用加殼軟體


一、360 (Qihoo360)

這是360的試用版加殼(加固)功能,順帶一提,它還會針對onCreate做VMP加殼,不過除了onCreate的程式碼,其餘都可以成功提取。



二、360加殼後的Dex

從加殼後的程式碼判斷,大部分的程式碼都被混淆,JNI也被加殼,可能解密演算法在JNI裡面,如果要手動分析解殼,需要花一段時間了解它。



三、騰訊 (tencent)

騰訊的加殼也類似360,值得一提的是它有一些Anti-Debugger的機制,不過試用版並沒有VMP,所以可以完整的提取程式碼。



四、騰訊加殼後的Dex

跟360一樣,加殼後裡面都是亂七八糟的混淆,解密演算法一樣可能在JNI,另外它還有偵測Xposed這套工具(可以Hooking Method、Field等等的功能),並防止App被監控和分析。



動態解殼


一、編譯動態解殼程式

當撰寫好動態解殼程式後,需要透過make libdvm編譯它,完成後的輸出檔案(libdvm.so),使用adb push指令覆蓋原系統上的libdvm.so檔案。



二、原始碼

這是還沒被加殼的原始碼,我們可以觀察被360和騰訊加殼後,動態解殼的差異。



三、動態解殼(360)

動態解殼後,可以觀察到主程式已被還原回來,不過除了主程式還有一些360的程式碼在上面(com.qihoo.xxx、com.stub.xxx),可能是它在加殼時有改動原本的Dex檔,另外可以看到onCreate被改成native的宣告(JNI函式宣告),從動態解殼印出的資訊可以知道,在調用onCreate時,會透過JNI的形式去呼叫它。



四、動態解殼(騰訊)

我們這次換觀察騰訊解殼後的狀態,跟360比較,它並沒有對原始的Dex有任何的改動,因此動態解殼完後,相當的乾淨。