Android安全交流群:478084054
0x00序
第一次嘗試脫dex殼,樣本是在“愛加密”官網上免費加固的,非商業版。
本文只是做些簡單的筆記,給像我一樣的逆向新手們提供點思路,高手們不要見笑。
0x01加固包和原包對比
加固后的classes.dex文件變大了,脫到JEB里面發現多了一些殼代碼和一些垃圾類(jpvbhn、cioub、flsye…)。
原包中,很多類方法的指令被抽空了,如下面的onCreate。
將assets目錄下的libexec.so脫到IDA中,發現個別方法被加密,并且用了o-llvm進行混淆編譯。導出表中的那些x、y開頭的變量就是o-llvm在編譯過程中,添加混淆控制流(-bcf)時創建的。
ptrace注入,從內存中dump出來一個libexec.so,看一下字符串表:
在字符串表中看到一些關鍵詞(dvmResolveClass.c、HOOK:%s() write dex!),瞎猜愛加密可能是抽取dex中的方法指令,然后hook dalvik/art關鍵函數,在運行時加載該類時再解密指令。所以用DexHunter試一下。
https://github.com/zyq8709/DexHunter
ps:從字符串表也可以看到,愛加密為了“防模擬器”,判斷了好多系統屬性(ro.product.model、ro.product.device…)。
0x02:利用DexHunter還原dex
DexHunter的大致原理是在某dex的第一個類被加載時,遍歷該dex文件的所有的class_def_item,主動加載所有的class(調用dvmDefineClass),并初始化(調用dvmIsClassInitialized和dvmInitClass),讓殼自己完成方法指令的解密,然后再做必要修復并dump。
編譯帶DexHunter的dalvik,刷機之后試了一下,在脫殼過程中apk進程死了。
愛加密有點意思,應該是在libexec.so或libexecmain.so被加載之后,在native代碼中判斷了“/data/”目錄下是否存在dexname文件(這也算DexHunter的一個特征),如果有則自退。
修改DexHunter源碼,把dexname這個文件名改掉:
再試一次,還是掛了,這次貌似是調用com.cioub類的clinit方法導致的。
看一下com.cioub類的clinit方法的實現就明白了,上文中提到的那些垃圾類(jpvbhn、cioub、flsye…)都是愛加密為了“防DexHunter”添加的。
先用笨方法解決一下,通過一個名單文件,將這些“防DexHunter”類pass掉。
再試一次,脫出了whole.dex,這實際是一個odex文件,利用baksmali和smali將其轉換為dex文件,拖到JEB中看一下:
之前被抽空的onCreate方法成功還原了,去掉那些垃圾類和shell代碼應該就差不多了。
0x03后序
1、使用DexHunter脫完之后,如果還有方法沒有還原,那加固廠商可能做了函數級加解密,在方法調用時再解密方法指令。
2、定位native方法指令在內存中的位置
這3個native方法是愛加密加固之后的3個核心方法,但libexec.so的JNI_Onload貌似加密了,并且導出函數的名字也混淆了(采用RegisterNative動態注冊),找出對應的native函數有點費勁。
可以在dvmCallJNIMethod函數中加點log,其實這個函數中本來有log,只不過注掉了。放開的時候,要進行一下過濾,否則打出的日志太多會淹沒其它有用的信息。
3、愛加密應該已經有解釋器殼了,猜測愛加密商業版以后可能會是“類抽取+解釋器殼”的形式,因為所有指令都解釋執行的話,應該會對效率影響較大,所以二者結合是個不錯的選擇。