1. 程式人生 > >Android IDA So的動態除錯大法

Android IDA So的動態除錯大法

     今天已是國慶的第五天,白天去武館訓練過後,晚上回來品一杯西湖龍井,更一篇部落格,一來幫助需要之人,二來加深自己的理解。

下面就說關於在IDA中Android so的動態除錯的問題以及在so的三個層次下斷點的操作。

問題篇:

1.動態除錯的作用以及與我們常說的脫殼區別之處?

2.IDA的下斷點除錯的原理?

3.有無反除錯的步驟區別?以及原理?

4.反除錯與反附加的區別?

5.IDA動態除錯so時有哪三個層次?以及如何下斷點?

注意:so的動態除錯與脫殼在步驟上有很多的相似之處,關於脫殼在後面會詳細介紹加殼以及脫殼的發展歷程。

解答原理篇:

第一個問題

曰:動態除錯作用有二:

其一:dump記憶體,即:找準時機dump出解密後的正確檔案;

其二:檢視每一步狀態,進一步分析出正確的邏輯;

脫殼只是我們在除錯系統級別的.so檔案後,找準時機dump出正確而真實的.so檔案,而動態除錯只不過是手動脫殼的一種表現方式。

第二個問題

曰:(由於師哥說面試時喜歡問,此處列出來)

下斷點原理:

由於下斷點有硬體斷點和軟體斷點,我們在這裡只說IDA中的軟體斷點原理:

 X86系列處理器提供了一條專門用來支援除錯的指令,即INT 3,這條指令的目的就是使CPU中斷(break)到偵錯程式,以供除錯者對執行現場進行各種分析。

當我們在IDA中對程式碼的某一行設定斷點時,即:F2,偵錯程式會先把這裡的本來指令的第一個位元組儲存起來,然後寫入一條INT 3指令,因為INT 3指令的機器碼為11001100b(0xCC)當執行到這的時候CPU會捕獲一條異常,轉去處理異常,CPU會保留上上下文環境,然後中斷到偵錯程式,大多數偵錯程式的做法是在被除錯程式中斷到偵錯程式時,會先將所有斷點位置被替換為INT 3的指令恢復成原來的指令,然後再把控制權交給使用者。這樣我們就可以愉快的開始除錯了。如下圖所示也是寫偵錯程式的原理圖:


第三個問題

:先說無反除錯:

1.adb push d:\android_server(IDA的dbgsrv目錄下)  /data/local/tmp/android_server(這個目錄其實可以隨便放,有的反除錯會檢測這)

2.adb shell 

3.su(一定要有root許可權)

4.cd /data/local/tmp

5.chmod 777 android_server(執行許可權要給)

6.再開一個cmd
adb forward tcp:23946 tcp:23946(埠轉發,除錯手機上的某個程序要有協議支援通訊)

7.開啟待除錯的應用程式,就可以愉快的除錯了

再來說有反除錯:

在很多情況下我們遇到的是有反除錯並且用上面的步驟,附加進去以後直接就退出了,這樣的例子數不勝數,那就是反除錯惹的貨。

這時候我們就要改變除錯戰略了

在上文的基礎上:

1.啟動android_server;

2.埠轉發adb forward tcp:23946 tcp:23946

3.adb shell am start -D -n 包名/類名

(說明:以啟動模式啟動,是停在載入so檔案之前,報名在AndroidMainfest檔案中可以找到)

4.開啟IDA,附加上對應的程序之後,設定IDA中的load so的時機,在debug options中設定一下,後面會有實戰部分;

5.adb forward tcp:8700 jdwp:程序號;(jdwp是後面jdb偵錯程式的協議,轉換到待除錯的指定的應用程式);

6.jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8700(jdb進行附加);

7.可以愉快的下斷點,開始除錯了;

第四個問題

:反除錯就是阻止你進行動態除錯所採用的一種手段,在下一篇中會進行具體的講解反除錯的手段,以及解決反除錯的辦法。

反附加,在這塊重要的是說jdb的反附加,很多情況下jdb會附加不上,就是會出現“無法附加到目標的VM”這樣的問題那是因為在每個應用程式下,有這個android:debuggable="true"才能除錯,因為篇幅問題,照樣會在下一篇中會針對反附加尋找目前所有解決辦法。

第五個問題:

曰:我們知道在so的載入時候有個這個過程:

.init->->.init array->->JNI_Onload->->java_com_XXX;

還有我們在脫殼的過程中會在一些系統級的.so中下斷點比如:fopen,fget,dvmdexfileopen,等等

而.init以及.init_array一般會作為殼的入口地方,那我們索性叫它外殼級的.so檔案

這裡歸納為三類:

應用級別的:java_com_XXX;

外殼級別的:JNI_Onload,.init,.init_array;

系統級別的:fopen,fget,dvmdexfileopen;

對於在應用級別的和系統級別的就不說了比較簡單容易理解,這裡也是在實現篇中會重點說的,看到上面的.so的載入執行過程我們知道如果說反除錯放在外殼級別的.so檔案的話我們就會遇程式在應用級核心函式一下斷點就退出的尷尬,事實上多數的反除錯會放在這,那麼過反除錯就必須要在這些地方下斷點,那麼我們就重點的說如何在.init_array和JNI_Onload處理下斷點。

實現篇:

這裡我們會拿阿里有一年的比賽樣本,會放在附件中。

在JNI_Onload處下斷點方法一:(雙開定位)

1.啟動android_server;

2.埠轉發以及除錯模式啟動:如圖所示:

3.開啟IDA,設定


4.附加上對應的程序進去之後如圖:


5.這一步很重要在Debugger option下面選擇這三個選項(讓在load so的每個介面處停下來)


6.jdwp協議埠轉發


7.jdb附加


8.F9執行,忽略提示框;這時候執行到linker處,如圖:


9.這時候找JNI_Onload的絕對地址:

基地址+相對地址;

基地址為:ctrl+s顯示為:


相對地址,用IDA靜態分析libcrack.so可得到相對地止:


絕對地址為:4151E000+1B9C=4151FB9C

按下“G”鍵輸入4151FB9C

如圖所示:按下F2下好斷點,再按F9執行到斷點處就可以愉快的除錯了


在JNI_Onload處下斷點方法二:(簡單好用)

1.首先把要分析的libcrackme.so檔案拉進IDA裡面在要下斷點的JNI_Onload處下好斷點如圖所示:


2.啟動android_server與上面一樣;

3.埠轉發以及除錯模式啟動:如圖所示


4.先設定一下Debugger 如圖所示


5.IDA進行附加程序回到之前靜態分析libcrackme.so的IDA介面單擊Debugger -> Process options 配置除錯資訊,這裡只需配置hostname為localhost,其餘的保持預設設定即可


6.單擊Debugger -> Attach to process進行附加程序


7.jdwp轉發(當然開啟DDMS就不需要這一步了)jdb附加


8.F9執行一路取消就OK,得到如圖所示:


是不是很簡單??

在.iniy_array處下斷點(與上面方法二雷同)

得到的結果是:


OK,搞定


在JNI_Onload處下斷點方法三:(適合於脫殼的時候)

1.可以根據看原始碼,對應不同版本的系統原始碼就會發現一點,如下在vm/Native.cpp路徑下:


2.我們逆向去看,首先把系統中的libdvm.so a db pull出來,拉到IDA中去分析;

找到JNI_Onload處進行分析:F5可以看到,首先V20進行“JNI_Onload”符號查詢,同時在V23有對V20的呼叫,


回到ARM指令處可以看到如下:


0x50008就是偏移處,這個時候我們就開始下斷:

載入上要除錯的APK以後,找到libdvm.so的基址,然後加上50008,下斷點。如果看不到彙編,那就P一下,下斷點,這個比較適合於脫殼的時候。