一般來說,很多APK的校驗代碼,都會在程序運行的時候自動加載一些動態so庫,然后執行這些庫中的校驗代碼。所以為了能夠通過程序的校驗,我們必須在執行這些函數之前下斷點——理想的方法就是在JNI_OnLoad入口函數下斷點。
在2.3.3模擬器中詳細步驟如下:
①在控制台輸入adb shell 進入手機,然后使用 am start -D -n 包名/類名,以等待調試的模式啟動APK應用;
這里需要說明的是 “包名/類名”的書寫方法:
# am start -D -n {包(package)名}/{包名}.{活動(activity)名稱}
程序的入口類可以從每個應用的AndroidManifest.xml的文件中得到,以計算器(calculator)為例,它的
<manifest xmlns:android="http://schemas.android.com/apk/res/android" …
package="com.android.calculator2" …>…
由此計算器(calculator)的啟動方法為:# am start -D -n com.android.calculator2/com.android.calculator2.Calculator
對於HelloActivity這個示例工程,AndroidManifest.xml如下所示:
<manifest …
package="com.example.android.helloactivity" …>
由此它的啟動方法為:
# am start -D -n com.example.android.helloactivity/com.example.android.helloactivity.HelloActivity
②使用adb將IDA(我的是6.1)中的android_server 傳入手機的/data/local/tmp目錄中:
adb push android_server /data/local/tmp
# 再賦予權限
adb shell
cd /data/local/tmp
chmod 777 android_server
#運行android_server
./android_server
③另起一個cmd窗口,使用命令 adb forward tcp:23946 tcp:23946 進行窗口轉發
④啟動IDA主程序,點擊菜單 Debugger->Attach->Remote ArmLinux/Android debugger ,打開調試程序對話框,在hostname一欄輸入localhost,
點擊ok,然后在IDA彈出的窗口中,選擇自己要附加的進程后點擊OK 即可。
⑤點擊菜單Debugger->Debugger Opitions 在彈出的Debugger setup窗口的Events中選擇 stop on thread start/exit 以及 stop on library load/unload,再點擊OK退出。通過此操作可以設置程序在創建新線程和加載so時自動中斷。
⑥通過DDMS獲取相應進程的端口號,然后使用jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=XXXX(DDMS查詢到的端口號);
⑦連接成功后,按F9后手機上的“waiting for debugger"提示會自動消失,這個時候應該已經斷在新線程,或者加載so處了。
⑧現在就可以在IDA中按下快捷鍵CTRL + S來查看要調試的so是否已經加載了,如果沒有就F9,直到加載了為止;如果已經有了,就記下該so的start位置,然后另開一個ida分析.so庫,找到JNI_ONLOAD的偏移地址,那么該JNI_OnLoad函數在進程中的真實地址就是so.start + JNI_OnLoad_Offset。
這里需要說明的是:有可能在快捷鍵CTRL + S跳出的窗口中有兩個同名的so,我們應當選擇權限為RX的這個,RX一般是代碼段,RW一般是數據段。
得到真實地址后,在IDA中按下快捷鍵G跳轉到這個地址,然后按下快捷鍵F2就完成在JNI_OnLoad函數入口處下斷點了。