IDA6.6遠端除錯Android應用程式的一點總結
阿新 • • 發佈:2019-01-04
新接觸Android安全,一直在逃避總結,因為懶。。。雖然網上有大把的資料,但是很多都是轉載,格式什麼的亂七八糟的,對於有嚴重潔癖的我不能忍。現在剛接觸,以後經常用到的東西,還是總結一下加深印象吧,省得總忘,好記性不如爛筆頭。
具體環境的搭建這些基礎的東西這裡就不再說了,JDK,SDK,NDK,IDA這些東西如果還沒裝的話就先別看這個了。還有就是手機要root,百度一鍵root就可以,會有su檔案。
但是要除錯一個APK需要有點準備工作,摘自:http://www.kanxue.com/bbs/showthread.php?p=1291716
根據android的官方文件,如果要除錯一個App裡面的dex程式碼,必須滿足以下兩個條件中的任何一個:
1) App的AndroidManifest.xml中Application標籤包含屬性android:debuggable=true
2) /default.prop中ro.debuggable的值為1
由於正常的軟體釋出時都不會把android:debuggable設定為true,所以要達成條件1)需要對app進行重新打包,這不僅每次分析一個App都重複操作,而且很多軟體會對自身進行校驗,重打包後執行會被檢測到,所以想辦法滿足第2)個條件是個一勞永逸的辦法,我實際使用的方法就是滿足第二個條件。由於default.prop是儲存在boot.img的ramdisk中,這部分每次重新啟動都會重新從rom中載入,所以要到目的必須修改boot.img中的ramdisk並重新刷到裝置中。我測試使用的裝置為Nexus 7,修改步驟如下:
a) 從Google官方網站下載到boot.img,
b) 使用工具(abootimg,gunzip, cpio)把boot.img完全解開,獲取到default.prop
c) 修改default.prop
d) 把修改後的檔案重新打包成boot_new.img
e) 使用fastboot工具把boot_new.img刷入裝置(fastboot flash boot boot_new.img)
圖1 修改後的default.prop內容
要除錯一個Android應用程式,要麼是除錯Java層程式碼,要麼是除錯Native層程式碼。但是根據程式執行的情況不同,除錯的方法有的適用有的不適用。比如我最近在除錯一個程式,我要除錯Native層的程式碼,但是等到程式起來以後Native層的程式碼就已經執行過去了,沒辦法斷下來。
下面我介紹幾種網上常用的除錯方法,以後隨著除錯水平的逐步深入,我會繼續完善。
在介紹除錯方法之前首先要把IDA的除錯通道配置一下,這個步驟只有在除錯Native層程式碼的時候需要,有點類似於gdb和gdbserver。
- 首先把IDA資料夾中dbgsrv目錄下的android_server檔案push到手機的/data/local/tmp目錄下,當然這個目錄可以自己選。
- 然後在終端中adb shell登陸到手機的shell環境,獲取root許可權以後,chmod 655 android_server修改執行許可權,然後執行之
圖1
- 下一步在電腦啟動一個終端,然後輸入命令:adb forward tcp:23946 tcp:23946
- 搞定。
假設現在已經有一個Android應用程式了,我這邊測試用的程式名字是DynamicLoad.apk,這個程式包括Java層程式碼和Native層程式碼,Native層程式碼封裝成一個so庫,名字是libmyloader.so。
一、除錯Native層的程式碼
方法1,除錯Native層非啟動執行的程式碼
所謂Native層非啟動執行的程式碼,就是說程式在啟動的時候並不會執行到的程式碼,這樣程式啟動以後再用IDA去attach到程式,然後找地方下斷,就可以除錯想要除錯的程式碼了。這是最簡單的方法,簡單來說就是安裝並啟動應用,然後IDA attach就可以了,但是隻能除錯Native層的程式碼。步驟如下:
- 最簡單的一種方法,安裝程式到手機上,啟動程式,然後開啟IDA,點選Debugger->Attach->Remote ARMLinux/Android debugger
圖2
- 會彈出下面的對話方塊,HostName就填localhost就可以了,表示是本機。
圖3
- 點選確定以後,會彈出一個視窗,裡面列出了手機上所有的可以attach的程序。
圖4
- 找到你要除錯的程序,然後點選OK。會彈出一個Searching for crypto constants,這個非常耗時,而且貌似沒有用,直接Cancel取消掉就行了。
圖5
- 到此IDA就已經attach到你要除錯的程式了,但是要怎麼除錯自己的程式碼呢?首先是要找到自己程式碼的位置,在IDA中按快捷鍵ctrl+s,會列出載入到記憶體的所有段的資訊,包括對應的so庫,及對應的地址和型別等問題。
圖6
- Search到你要除錯的so,如上圖我找到我的庫libmyloader.so,會有三個,看型別可以看到三個分別是CODE,CONST,DATA,記下型別為CODE的那個庫的起始地址,我這裡是0x732A2000。
- 起始地址已經有了,下一步就要找到你要除錯的程式碼在你的so裡面的偏移了。
- 首先要搞到libmyloader.so,這個直接把DynamicLoad.apk解壓出來就可以搞到,apk檔案實際就是zip檔案嘛。然後另起一個IDA例項,開啟libmyloader.so,在左邊Function name欄裡Alt+t搜尋你想要除錯的程式碼所在的函式名字
圖7
- 找到以後雙擊,游標就跳轉到函式的起始程式碼位置了,然後找到你想要下斷的程式碼的偏移量,我這裡假設是00002510,將這個數加上上面記錄的so庫在記憶體的起始地址732A2000,得到0x732A4510,這個地址就是你要下斷的程式碼在手機記憶體中的地址。
- 現在回到前一個IDA,也就是已經attach到手機應用的那個IDA,按g,會彈出一個對話方塊讓你輸入Jump address,把上一步計算出的位置輸入進去,點選OK。就會跳轉到目標位置了,然後按F2下斷,再按F9開始執行。
- 後面就是你操作你的程式,當它執行到你下斷的程式碼時,IDA這邊就會斷下來,然後就可以去幹各種事情了
方法2,除錯Native層啟動執行程式碼
Native層啟動執行程式碼就是我在文章開頭的時候說的那種情況,在程式啟動的時候Native層的程式碼就運行了,那麼適用方法1的話就不行了,在IDA attach到程序之前程式碼就已經執行過了。另外還有一種情況就是現在很多APP都經過類似愛加密和梆梆等處理過,有反除錯的功能,程序會去檢測自己有沒有被其他程序除錯,IDA一attach上程序就自動退出了。這時候就要在程序啟動最開始的時候就斷下來,然後繞過它的檢測部分。具體方法如下:- 首先要以除錯模式來啟動APP,在電腦的終端中輸入命令:adb shell am start -D -n com.example.dynamicload/com.example.dynamicload.MainActivity
- 手機上程式會啟動,並顯示Waiting For Debugger。這個時候程序雖然啟動了,但APP還沒有執行。
- 下一步就可以按照方法1的步驟attach到這個程序上,這時IDA會中斷在某個位置,然後IDA需要設定一下Debugger->debugger options,如下圖:
圖8
- 點選OK後按F9執行APP,然後在電腦的終端中輸入命令:jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8600,命令的具體意義我也不太明白,但猜想應該是一個除錯命令,告訴程序繼續執行。注意,執行此命令時必須保證DDMS是開啟的,否則除錯埠是關閉的,命令執行就會失敗。
圖9
- 上面命令中後面那個port=8600不是固定的,你要開啟DDMS看一下這個程序對應的埠多少。
圖10
- 這時候IDA就自動斷下來了,有時候它會彈出下面這個對話方塊提示找不到so。沒關係,只要在Destination中輸入so的絕對路徑就OK了。
圖11
- 下面的關鍵就是找到要下斷的地方,因為是要除錯Native程式碼,所以入口肯定是JNI_OnLoad函數了,這也是我們首先要下斷的地方。但是怎麼找到這個函式的記憶體地址呢?首先呼叫這個函式的地方肯定在libdvm.so中,所以我們肯定要在這個庫裡面下斷,相信看過方法1你肯定知道libdvm.so的起始地址怎麼獲得,然後就剩下找到下斷的程式碼在libdvm.so裡面的偏移量了,我的方法是把手機裡面的libdvm.so pull出來,然後另起一個新的IDA,在裡面搜尋JNI_OnLoad函式,找到呼叫它的地方,記下偏移,然後加上libdvm.so的起始地址,在得到的地址上下斷,F9執行,就斷下來了。
- 這時候你自己的so(我這裡是libmyloader.so)已經載入到記憶體裡,但是還沒有執行,下一步就在你自己的so裡面再找位置下斷除錯就可以了,具體不再贅述了,方法1裡面很詳細。