根据”so劫持”过360加固详细分析
參考:https://bbs.pediy.com/thread-223699.htm
http://blog.csdn.net/luoshengyang/article/details/8923483
?
前幾日看到大神寫的 https://bbs.pediy.com/thread-223699.htm這篇博客感覺受益匪淺,但是其中有一些自己的理解想跟大家一起分享,算不上原創,希望各位大俠不要嘲笑。共同學習。
一:思路分析:
一個經過360加固的APK的運行過程應該為圖中左邊所示,在以上這種so劫持的思路為:第一步通過hook loadlibrary方法先加載自己的so,即:libhook.so
第二步在libhook.so中再加載libjiagu.so,并執行其中的JNI_Onload方法,完成最后的解釋。
這樣做有個最大的好處是:就是在libhook.so中通過hook 注冊函數dvmUseJNIBridge()得到oncreate函數的地址,更好的進一步分析360的虛擬解釋函數。因為360殼比較復雜,前面有一堆的解密等操作,這樣做可以直接切入要害。
二、此思路能否過反調試?
1.原作者這種巧妙的運用sleep(9),不以調試模式啟動,等在sleep(9)的時候直接附加,這個時候360在JNI_Onload中的反調試已經運行完了,所以不會觸發反調試。
2.以下這種是在以調試模式啟動的時候過反調試的基本操作:
首先看Dalvik虛擬機JNI方法的注冊過程分析,通過老羅的分析博客,(老羅的分析真的很到位,此處盜用老羅的圖)可以大致知道運行圖如下:
因此來說在整個so劫持的關于JNI方法注冊大致是如下:
從中我們可以看出要想在調試運行過程中在new_dvmUseJNIBridge()函數處下斷點,必然是要觸發反調試,接下里就是想辦法過掉反調試。
三、過反調試
首先等APP加載起來在 LoadSo_InitJni()函數處,下斷點,等運行到如圖所示的時候F7進去分析如下,就進入了熟悉的libjiagu.so的JNI_Onload函數里面。
第一處反調試:rtld_db_dlactivity函數
作用功能發揮:
從linker通過符號表,找到函數rtld_db_dlactivity對應的模塊中的地址(這里直接使用了簡單的遍歷符號表Sym結構的方式),然后返回。如果地址里面的值不為0則會調用raise函數發送一個結束進程的信號終止程序。
rtld_db_dlactivity函數:
這個函數實則默認情況下為空函數,這里的值應該為0,而當有調試器時,這里會被改為斷點指令,0xDE10實則為thumb指令的斷點。函數的功能是用于處理一些調試器的特殊情況的。比如調試器對模塊的某個地址進行下斷,但這個地址實際不存在,得在模塊加載后才存在等的特殊情況下的函數。起的作用就是類似于協商解決特殊問題。
方法一:在樂固中也會調用raise函數進行進程的終止,可以通過在這個函數處下斷點,然后,對這個函數中的函數體做響應的操作,無論在哪調用或者怎么調用,都不會使得反調試起作用,但是在360中我們知道第一處的反調試也是會通過調用這個函數,但是我在實驗的過程中發現,等把raise函數體改變以后,整個程序不能跑,因此看來只能一步一步的往下跟。。
方法二:
思考:因為從上面可以知道要通過linker找到函數對應的模塊地址,首先肯定會通過mmap函數把linker映射到內存中,因此首先在mmap函數處下斷點,等到調用時返回就OK。
方法三:
由于在360加固中的核心的函數libjiagu.so中的核心分支點為:case 31和33,并且在31處中的BLX ?LR來執行不同的函數,在此處下斷點,看R0的返回值。
如圖所示,對應的直接把將DE 10修改為nop指令 C0 46或者00 00,就OK了,過掉第一處反調試。
第二處反調試:TracePid
對于TracePid的檢測,此處LR的值為strtol,將其返回值修改為0,
我這里是由于把系統內核的TracePid進行了修改,因此會出現:以下R0是0.
第三處反調試:端口的檢測
對于端口的檢測,這個好過,直接在剛開始調試的時候通過“./xyy -p7359”把端口換掉就可以了。
第四處反調試:
這個一看就是對于時間前后差值就行檢測,如下圖所示:
F5以后更為明顯:
那么這個也好辦,在time函數處下斷點讓它每次返回的值都為0就可以了。這樣就繞過了檢測。
這樣就基本過完了所有的反調試,接著往下分析。
通過uncompress函數解壓第二個so文件并解密找到對應的JNI_Onload函數,主要作用就是動態注冊那些被native的函數,這不是本文的重點。
當然這里也可以不用手動過反調試,對反調試中的一些關鍵函數進行HOOK,比如time函數,返回0等,也可以過掉。
四、尋找核心解釋函數
接著就該被Hook的注冊函數dvmUseJNIBridge()發揮作用的時候。接著F9就到了
由于注冊的函數有很多,因此直接在sleep(9)之后下斷點,就可以。
到了關鍵函數處,通過“ALT+G”修改為Thumb指令,再通過P鍵就可以出來指令。
作者這里是通過一種很巧妙的方法,通過觀察運行的過程中的log輸出來判斷核心函數地方,是個很聰明的做法。很值得借鑒。可以很容易的得到偏移值為
debbug offest=0x3b534。
在分析這個虛擬解釋函數之前首先要dump出除onCreate函數以外的dex文件。
1.可以通過分析圖中那個關鍵函數在dex解密完,就可以在HEX區域看到。
2.通過memcpy函數下斷點得到。
3.通過主動調用dvmDefineClass進行加載。
以上都可以dump到dex。
如圖所示dex2jar后,接著分析onCreate函數的虛擬解釋過程。
?
五、理解虛擬解釋函數過程
具體過程如下:作者已經在他的帖子中說的很到位了,這塊簡單貼幾個圖。
首先是每個樣本的key不一樣,在這個樣本中的key值為:3232;
通過R4值得到如下的虛擬指令為:
07 12 75 18 71 32 F2 22? 2B 0C 31 32 35 32 CC 33
01 33 93 22 E6 0C 32 32? BE 30 93 12 EE 0A 13 32
87 32
接著就是讀取虛擬指令首先是與key進行異或運算得到中間值1;再與0xFF進行與運算得到中間值2,再與0X5C相加得到表中的分支,最后找分支進行解釋運算。如下圖所示。
以下是找到分支以后進行比較找相關的解釋函數進行解釋。
在這個樣本中就是如下圖所示的規則:
六、還原&總結:
還原:
、
對于每個不同的APP經過360加固以后,虛擬指令、中間值1、中間值2可能都不相同,但是每個指令的對應的表的分支是一樣的,比如在這里面就是74對應著invoke-super Smali指令。
因此我們可以選擇一個寫上所有的Smali指令的APP經過360加固進行分析找出真實的指令與表的分支的對應映射表,對于一個待逆向的APP,只需要提取出對應的分支就可以根據映射表得到真實的指令,完成還原。
總結:
360加固保這種加固做到了dex的虛擬化,但是由于無論中間的過程怎么復雜的變換,加上Android中Smali指令數量不是很大,總是會有表中的分支與真實指令之間的一個對應關系。總是可以想辦法進行還原,如果想加強,我覺得是不是可以采用“多虛擬的思想”里面有多套map表,每次隨機選擇運行,并且360反調試有點過于集中,可以在每套map表的邏輯轉換中插入一些反調試,以上純粹YY,希望各位大俠不要嘲笑。
?
原文地址:?https://bbs.pediy.com/thread-223796.htm
總結
以上是生活随笔為你收集整理的根据”so劫持”过360加固详细分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Xposed注入实现分析及免重启定制
- 下一篇: python︱HTML网页解析Beaut