頂象企業版加固逆向分析

首先看一下頂象對於這種自身的虛擬源碼保護是怎麼說明的?

 

結合免費版分析可以猜測是這樣的加固流程:

1.   首先進行免費版轉換把dex中對應的方法通過JNI反射轉換爲cpp文件(當然這裏企業版比免費版轉換的方法要多,免費版中的內部類MainActivity$1就沒有進行轉換);

2.   然後就是獨有工具鏈的編譯,猜測很有可能是基於LLVM的自定義編譯;

3.   進行虛擬化保護,生成相對的VMdata和對應的Handler解釋器,最後每次通過dispatcher來讀取VMdata完成解釋。

 

一、分析篇:

1.So脫殼:

根據上一次的免費版分析知道頂象中so的保護採用的變形的UPX加殼。

在linker執行完第一個init函數,也就是upx的loader函數後開始dump.

在偏移值爲274E處下斷點:

 

 

 

根據base和Size dump出來

dump下來接着修復。

通過對Load和dynamic進行簡單修復後基本上所有的函數,靜態都可以看到了,

如圖所示:

 

2.直接分析:

靜態分析:

這裏面要抓住幾個核心的問題,一是核心代碼的虛擬指令,二是虛擬安全運行環境.

OK,開始吧!在IDA中打開分析看到JNI_Onload、oncreate、wanwan01、wanwan02、wanwan0、Testloop等這些函數基本上是遵從一個規則那就是:

 

 

 

所以可以猜想的是這幾個函數是構成那個虛擬運行環境的重點函數,也是我們分析的重點。

進入sub_43B0這個函數以後發現如下:

經過簡單分析以後發現

 

 

 

在F5看僞代碼以後發現:是一個控制流平展圖,裏面的case總共有250個左右,但是隻有50多個,200個左右沒有顯示,大致猜測加固原理如下:

在加固處理的時候對dex native化形成的cpp文件進行語法分析,或者就是上面所說的形成了中間二進制文件,然後根據這些二進制文件的特徵來形成了50個左右“Handler”。(總共是253個“Handler”,這裏只用到50個),每次解釋的時候讀取這個虛擬指令集合。然後調用相應的Handler來進一步的進行解釋完成。

動態調試分析:

 

 

 

如上圖所示爲去虛擬指令的一個過程。下圖是每次調用執行完返回的一個過程。

 

下面感覺是維護一個地址表:

 

並且在調試過程中發現case94、case 249、case107、case222、case197這些Handler的內容是一樣的,或許是一些無用的垃圾指令。

 

在調試中如下圖所示會發現有大量的重複的虛擬指令,並且對應的Handler也沒有具體的語義。如下圖所示:

 

 

 

因此轉換思路,從JNI一些系統函數入手:

3.間接分析:

轉換思路,HOOK 這些JNI 接口函數,比如Findclass,GetMethodID函數,或者是找到這些函數地址然後進行向上引用來發現其中的Handler和對應的虛擬指令。

通過對之前免費版的加固分析,我們這裏只重點關注兩個重點函數Findclass,GetMethodID;

發現FindClass的地址爲:41520778 ;GetMethodID的地址爲:4151FC58並且在手機不重啓的情況下這個地址是不變的。

因此接着分析:

 

 

 

同樣的繼續F9執行發現每次都是停留在116這個case中,這個時候才明白真正的扮演dispatcher的角色是這條分支。

 

-..$..$-.$--.$-..-$..$.-$-.$--. 這個偏移裏面保存就是各個類和方法名的一些字符串

同樣的繼續F9執行可以看出:又是執行ExceptionCheck這個系統函數。

 

 

 

可以看出這個過程執行的不就是在上一次免費版中sub_2170函數,如下圖所示:

 

 

 

對於反射執行中只要理清了這些系統函數的一個調用過程基本就可以搞清楚基本邏輯了,接下來就不用分析了,基本上case 116這條分支執行的就是類似把如下的這些sub_XX函數走完一遍:

 

 

 

上面拿onCreate含有Android SDK的函數作爲重點分析例子,接下來一個JAVA SDK的也就是Testloop這個方法:

 

 

 

通過上面的分析發現也是case 116這條Handler,基本可以逆推出反射執行的所有流程和框架,這裏不再進行演示。

因爲在上一個so沒保護的APP中核心分支是210,並且所對應的“虛擬指令”也是不同的,這可能就是頂象所說的每臺設備的虛擬指令均不相同。

從以上可以說明在同一個APP中核心的分支是一樣的,不同的APP的“虛擬指令”是不同的並且核心分支也是不一樣的。

對於含有Android SDK 或者java SDK的反射分析基本就到這了,其實可以藉助於HOOK JNI接口函數,然後進行log輸出,根據log的輸出以及結合以上的分析更好的理解整個反射執行的基本流程,從而嘗試着手動進行還原。

二、總結篇

優點:

1.首先這種編譯虛擬方法可以完美的解決平臺兼容性問題,不像基於指令虛擬,需要很多的適配。

2.真正的做到了邏輯的隱藏並且確實每個加固的APP的“虛擬指令”和對應重要case分支不一樣。

3.通過對生成的cpp進行控制流混淆,並且在裏面加入垃圾分支,增加了正面分析的難度。

Dex保護方面:

java層先做了一層java2cpp的翻譯,之後才走虛機機保護。即cpp2vmp的過程。由於java2cpp的過程中需要藉助於JNI的一些接口,因此間接去找核心的關鍵點。

Cpp保護方面:

Cpp層直接就是DX單獨提供的私有的NDK編譯工具,直接在編譯過程中進行虛擬加固保護,很強。就不能借助上面的邏輯了,需要正面分析。

三、最後

本身年前分析的,還沒有完全分析清楚,年後有許多別的事情,沒時間,分享給大家,希望大家一起交流學習。

DX加固做的真的很強大,在每一個步驟上的處理要想做到完善完美難度都很大!

 

至於樣本如果想研究分析的可以發郵件:[email protected]

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章