1. 程式人生 > >IDA 調試 Android 方法及簡單的脫殼實現

IDA 調試 Android 方法及簡單的脫殼實現

all fun cati chm std function sso .apk 代碼位置

IDA 調試 Android 方法及簡單的脫殼實現

標簽: android原創逆向調試dalvik 技術分享 分類:

目錄(?)[+]

本文參考了一些網絡文章,對大大們的技術分享表示感謝。小弟剛剛開始深入去搞Android的逆向不久,寫一下學習筆記,希望能拋磚引玉,給新手同學們帶來方便。文筆比較爛,這不重要,重要的是按自己思路整理出來的資料以後自己看起來快一些。文中如有不對的地方還請留言指正。

前置環境

JDK,IDA PRO,Android NDK,Android Killer,JEB,Root並開啟開發者模式USB調試的手機

動態啟動調試

Android Killer 反編譯 x.apk,取出 classes.dex Dalvik文件,記錄包名和啟動類名。
技術分享

修改 AndroidManifest.xml 文件,在<application>標簽裏添加屬性 android:debuggable="true" 這一步越早修改越好,防止忘記改。

可以查看一下AndroidManifest.xml 他們的對應關系,加深理解。

技術分享

用AndroidKiller 重新編譯修改過的x_fix.apk。

adb install x_fix.apk 安裝到手機
將 IDA 安裝目錄 dbgsrv 目錄下的 android_server 文件拷入手機
adb push dbgsrv\android_server /data/data/android_server
接著執行
adb shell chmod 655 /data/data/android_server添加可執行權限
adb shell /data/data/android_server 將其運行起來
技術分享
在實際環境中可能會遇到上圖中的一些錯誤,圖中也給出了解決方法。
需要額外說明的是,當 adb root 失敗時,需要在手機中安裝一下“超級adbd”打開應用選擇啟用超級adbd ,再執行adb root 就可以了。
運行後可以看到 Listening on port #23946 … 字樣就說明 server 運行成功了,並且已經打開了手機端的 23946 端口等待接收命令。
為了方便PC端IDA 連接調試手機,可以在本機做端口轉發。另起一個cmd,輸入:
adb forward tcp:23946 tcp:23946

將之前保存出的 classes.dex 托入 IDA。在IDA菜單中選擇 【Debugger】-> 【Debugger Options…】添加以下選項
技術分享


再點擊 Set specific options,添加adb 路徑及剛剛保存的包名和入口名,如圖

技術分享

【Debugger】-> 【Process Options…】的配置如圖

技術分享
接下來就可以按IDA上的啟動鍵,啟動手機端的APP進行調試了,如圖
技術分享
你可以在【View】->【open subviews】->【functions】調出函數列表,再配合Android killer 或 JEB 分析的代碼位置進行下斷調試了。

動態附加調試

正常流程

技術分享
技術分享
在手機端運行程序後,按上圖的步驟直接附加就可以了。


如果出現 Bogus or irresponsive remote server 的錯誤提示

修改 SELinux安全策略限制
adb shell su -c setenforce 0


再重新運行 android_server 重新轉發,再試。

反調試/解密函數運行前進行動態調試

很多程序加入了反調試機制,或者是偽dex文件在程序運行時解密真正的dex文件以殼的方式保護APP。針對此兩種方法可采用在程序運行前掛起程序,再用IDA掛載,在關鍵位置下斷,來破解類此防護。
舉一個網上的例子。
下載 ori.apk 按之前的操作記錄包名等,加入Debug屬性,安裝到手機
運行調試啟動命令
adb shell am start –D –n loading.androidmanual/loading.androidmanual.BeginningActivity
這時程序會被掛起,等待調試器接入。
用IDA 載入,調試選項如下
技術分享
加載時可記錄一下該應用的pid 之後會用到,忘記記錄也沒關系,附加後在IDA 的輸出log裏可以找到pid的信息
技術分享
運行 adb forward tcp:7788 jdwp:977 命令,轉發要調試的進程到端口7788(隨便寫),
運行 jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=7788 使用jdb 載入調試。
此時程序處於阻塞狀態,沒關系,返回IDA,在Modules窗口查找libdvm.so,雙擊進入Module: libdvm.so 窗口,查找_Z21dvmDexFileOpenPartialPKviPP6DvmDex 函數,雙擊定位過去,在函數頭部下斷。
技術分享
因為要Load Dex 文件都要經過此函數就像 LoadLibrary同樣的道理。
接下來點擊IDA繼續運行程序就會在此斷點斷下來。
技術分享
R0 寄存器中的地址就是 Dex 的起始地址。點擊旁邊的回車圖標跳轉到相應的位置。在 View-PC 窗口中右鍵,選擇Jump in a new hex window 可以更好的觀察內存中的信息
技術分享
這就是殼中釋放出來的程序真正的dex文件了。根據Dex 文件結構,我們知道從起始位置偏移0x20字節是這個文件的大小,在這裏也就是 0x0FAEB4。有了起始位置和文件大小就可以Dump了。我們直接寫IDA 的腳本來dump。【file】->【Script Command…】。輸入以下代碼:

[cpp] view plain copy
  1. auto fp, dexAddress ,endAddr;
  2. dexAddress = 0x54d4c41c; //起始地址
  3. endAddr = 0x54E472D0; //結束地址=起始地址+文件大小
  4. fp = fopen("d:\\dump.dex", "wb"); //打開文件
  5. for (; dexAddress < endAddr; dexAddress++) //循環寫入
  6. fputc(Byte(dexAddress), fp);
  7. fclose(fp);

技術分享

Dex文件保存後就可以丟進JEB進行分析了……


如果是反調試機制,那麽就從一開始加載的so文件入手進行分析。同樣用IDA掛載起來

按照上面的步驟找到JNI_OnLoad函數並下斷,F9運行起來後就可以跟蹤分析了。

IDA 調試 Android 方法及簡單的脫殼實現