網秦安全盾 原理分析

我是小三發表於2014-11-18

環境:
手機: 中興 u887
系統 android2.3.5
偵錯程式: IDA pro 6.5

一:加固前後對比
加固前 classes.dex 大小如下:

加固後 classes.dex 大小如下:

那原來的 classes.dex 去那兒了呢?我們再來對比下資源目錄下都多了些什麼?
加固前的:

加固後的: 

Lib 目錄:

加固後:

比較發現多了些檔案,具體這些檔案有什麼用請看下面分析。

二:java 層概述
1.通過反編譯看,從 AndroidManifest.xml 檔案中的 application 項可以看出殼的入口為:

2.簡單分析 com.nqshield.NqApplication 類都做了些什麼?
.不能反編譯成 java 程式碼,直接看 smali 程式碼吧。
在 NqApplication 類 method protected attachBaseContext(Landroid/content/Context;)V
中都分別呼叫了這些函式:
3..invoke-static{p0},Lcom/nqshield/Common;->loadXShellLib(Landroid/content/Cont
ext)V
從名字可以看出是載入 so 庫,並註冊 JNI 函式。
通過分析 JNI 方法註冊到 Dalvik 虛擬機器的過程,可以得到 java 層 native 函式與 so 層函式
對應的關係為:
native nq10 -> b9df1ce797fd03603fd7137afff2957
native nq11 -> eb5993d402df42eac47e82555b7ae31
native nq12 -> fa3f3a501e8754e88bed48c128ef90
native nq13 -> abc020d3ee6fbc05ab1ed6b4da7252d
native nq14 -> e300588cc034bcbaa7d61
(*如有不清楚如何分析這個過程的可以參考學習羅昇陽 的文章)
4..invoke-static{p0},Lcom/nqshield/Common;->CopyBinaryFile(Landroid/content/Con
text;)V
該函式是將 assets 資料夾中的 DexToLoad.apk 與 nqdata 拷貝到/data/data+包名/.cache
目錄中,然後呼叫 nq10 函式,(該函式會在下面分析)。
5..invoke-static{p0},Lcom/nqshield/jniExport;->getDexClassLoader(Landroid/conte
nt/Context;)Ljava/lang/ClassLoader;
該函式通過呼叫 DEXClassLoader 完成對加密的/data/data+包名/.cache/DexToLoad.apk 的
動態載入,記憶體中解密 DexToLoad.apk 並組合 odex, 完成動態載入。 (詳細過程看 so 層分
析) 。
類似下面的樣子:

6.invoke-virtual{v0,p0,v1,v2},Lcom/nqshield/jniExport;->nq12(Landroid/content/C
ontext;Ljava/lang/ClassLoader;I)V
傳入 getDexClassLoader 返回值。
7.invoke-virtual{v0,v1,v2},Lcom/nqshield/jniExport;->nq13(Ljava/lang/String;I)V
so 層分析
8.最後在.method public onCreate()V 中呼叫
invoke-virtual {v0, v1, v2}, Lcom/nqshield/jniExport;->nq14(Ljava/lang/String;I)V
三:so 層分析:
1.通過 readelf -S libnqshield.so 檢視 so 資訊,發現 INIT_ARRAY 不為空,

用 IDA 開啟 so,G 到 INIT_ARRAY 中的地址去看看.

對應 so 函式名被混淆了,動態分析發現這些函式都是解密字串用的,根據傳進的數字解
密相應的字元。

下面是傳入要解密的字串。

110 代表解密後的字元為: nq10
115 代表解密後的字元為: (Ljava/lang/String;Ljava/lang/String;I)V
111 代表解密後的字元為:nq11
等等...以此類推
2.JNI_OnLoad 中都做了些什麼?
第一個函式 fork 一個子程式,並建立一個執行緒,執行緒函式如下所示

inotify 是一種檔案系統的變化通知機制,如檔案增加、刪除等事件可以立刻讓使用者態得知,
int wd = inotify_add_watch (fd, path, mask); 用於新增一個 watch
fd 是 inotify_init() 返回的檔案描述符, path 是被監視的目標的路徑名(即檔名或目
錄名), mask 是事件掩碼, 在標頭檔案 linux/inotify.h 中定義了每一位代表的事件。可以
使用同樣的方式來修改事件掩碼,即改變希望被通知的 inotify 事件。Wd 是 watch 描述
符。
在 arch-arm\usr\include\linux\ inotify.h 標頭檔案中定如下:
#define IN_OPEN 0x00000020
,根據執行緒函式可以看出它是監視/proc/pid/maps 的開啟事件.
(*不明白的可以點這裡 http://blog.csdn.net/myarrow/article/details/7096460)

我猜測這個執行緒的功能可能是做反注入用的。
2.解密字串
傳入數字 79 代表解密後的字元為: com/nqshield/jniExport
3.註冊 JNI 函式
對應關係
native nq10 -> b9df1ce797fd03603fd7137afff2957
native nq11 -> eb5993d402df42eac47e82555b7ae31
native nq12 -> fa3f3a501e8754e88bed48c128ef90
native nq13 -> abc020d3ee6fbc05ab1ed6b4da7252d
native nq14 -> e300588cc034bcbaa7d61
4.下面對這幾個函式進行分析
nq10 函式在 java 層 CopyBinaryFile 函式中被呼叫到,我們在 so 中對
b9df1ce797fd03603fd7137afff2957 函式下斷點,動態分析看它都做了些什麼?
函式裡面呼叫了 result = initEnv(a5, "DexToLoad.dex", "DexToLoad.apk", &s);
進入該函式分析,該函式對 libdvm.so 與 libnativehelper.so 中的操作檔案等一些函式進
行 hook 如下圖:

我 們 分 別 對 這 幾 個 hook 函式 (myopen,myread 等 ) 下 好 斷 點 , 當 java 層 調 用
getDexClassLoader 函式時會走到這些 hook 函式中,b9df1ce797fd03603fd7137afff2957
函式就分析完成了。
5.java 層的 CopyBinaryFile 函式執行完後就要執行 getDexClassLoader 函式了,該函式是
呼叫 DexClassesLoader 動態載入 DexToLoad.apk,繼續動態走,斷在 myopenh 函式中,該函式
會判斷是不是開啟 DexToLoad.apk 檔案,如果是就會建立一個 DexToLoad.apk.zip 檔案。
接著來到 myopen 函式中,判斷是否開啟 DexToLoad.apk,如果是會呼叫函式 access 判斷
/data/data/yiqi.bazi/.cache/DexToLoad.apk 是否存在,存在就開啟它並將其讀取到指定
記憶體,然後解密,如下圖:

6.組合生成 ODEX:
下會根據 ODEX 結構圖進行組合:

(*該圖來自 “ Android 軟體安全與逆向分析” 一書,如有對該結構不明白的地方可以
去閱讀這本書,書裡有詳細講解)。
首先使用 zlib 函式 inflateInit2_與 inflate 對上面解密出來的 DexToLoad.apk 資料從
classes.dex 標誌後進行解壓得到 dex 資料, 在 inflateEnd 處下斷 F9 執行, 如果要脫殼的
話,這個時候是最佳的 dump 時機,可得到完整的 Dex 資料。(組合完後會對 dex 做些手腳)接
下來會按照上圖 odex 結構圖進行組合,
在解壓出來的 dex 前寫入 ODEX 檔案頭如下圖所示:

開啟/data/dalvik-cache/mnt@asec@yiqi.bazi-1@pkg.apk@classes.dex 讀取依賴庫到 dex
後面,如下圖:

開啟/data/data/yiqi.bazi/.cache/nqdata 讀取輔助資料到依賴庫後面,如下圖:

組合完後就是 vm 載入過程了。
7. 接著 java 層呼叫 nq12 nq13 nq14 函式
反射呼叫 LoadedApk.mApplication, LoadedApk.mClassLoader,
ActivityThread.mInitialApplication,
ActivityThread.mAllApplications 等值,將其重新
指向目標 Application 和 ClassLoader。確保系統
稍後構造元件時能正確的載入到目標類。
三: 到此分析完成,最後,將控制權給目標 Application。

完。

樣本及文件下載

http://yunpan.cn/cA3U6hctfwfj3 (提取碼:9b1e)

相關文章