非常詳細的android so庫逆向調試教程
前言
好久沒有寫博客瞭,最近的精力全放在逆向上面。目前也隻是略懂皮毛。
android java層的逆向比較簡單,主要就是脫殼 、反編譯源碼,通過xposed進行hook。
接下來介紹一下,如何去調試hook native層的源碼,也就是hook so文件。
應用環境準備
首先,為瞭方便學習,一上來就hook第三方app難度極大,因此我們自己來創建一個native的項目,自己來hook自己的項目作為學習的練手點。
創建默認的native application
打開as,選擇File -> new project -> naive c++ 創建包含c++的原生工程。
默認的native工程,幫我們實現瞭stringFromJNI方法,那我們就來探索如何hook這個stringFromJNI,並修改他的值。
修改stringFromJNI方法,便於調試
as默認實現的stringFromJNI隻有在Activity onCreate的時候調用,為瞭便於調試,我們增加一個點擊事件,每次點擊重新調用,並且返回一個隨機的值。
java代碼增加如下方法:
binding.sampleText.setOnClickListener { Log.e("MainActivity", "stringFromJNI") binding.sampleText.text = stringFromJNI() }
修改native-lib.cpp代碼:
#include <jni.h> #include <string> using namespace std; int max1(int num1, int num2); #define random(x) rand()%(x) extern "C" JNIEXPORT jstring JNICALL Java_com_noober_naticeapplication_MainActivity_stringFromJNI( JNIEnv* env, jobject /* this */) { int result = max1(random(100), random(100)); string hello = "Hello from C++"; string hello2 = hello.append(to_string(result)); return env->NewStringUTF(hello2.c_str()); } int max1(int num1, int num2) { // 局部變量聲明 int result; if (num1 > num2) result = num1; else result = num2; return result; }
修改的代碼很簡單,相信不會 c++ 的同學也看得懂,就是隨機輸入兩個數,取其中小的那一位拼接在“Hello from C++”後面,並返回。主要目的是讓我們每次點擊的時候,返回內容可以動態。
修改androidManifest文件
在application中增加下面兩行代碼:
android:extractNativeLibs="true" android:debuggable="true"
android:debuggable: 讓我們可以對apk進行調試,如果是第三方已經打包好瞭app,我們需要對其manifest文件進行修改,增加這行代碼,然後進行重打包,否則無法進行so的調試。
android:extractNativeLibs: 很多人在進行調試的時候發現ida pro一切正常,但是卻一直沒有加載我們的libnative
-lib.so, 是因為缺少這行代碼。如果不加,可能會使so直接自身的base.apk進行加載,導致ida pro無法識別。
修改CMakeLists.txt
在cmakelists中增加下面代碼。so文件生成路徑,這樣編譯之後就可以在main-cpp-jniLibs目錄下找到生產的so文件。
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/jniLibs/${ANDROID_ABI})
編譯運行,獲取so
上述工作做好之後,直接編譯運行,同時會生成4個so文件,我們取手機運行時對應使用的那個so進行hook。
我這邊使用的是arm64-v8a目錄下的libnative-lib.so。
hook環境準備
- 系統:windows 10 64位
- 工具ida pro 7.5
- java8環境
- android sdk tools和adb工具
- arm64-v8a目錄下的libnative-lib.so
- android 真機
使用ida pro進行hook
adb與手機的準備
1、首先找到ida pro的dbgsrv文件夾,裡面有很多server文件
64代表的含義是64位,否則就是32位,我們根據我們需要調試的so的指令集進行選擇。因為我這邊調試的是arm64-v8a,這裡我們就選擇android_server64的文件。連接真機後,打開cmd,輸入以下指令:
adb push "\\Mac\Home\Desktop\IDA PRO 7.5 (x86, x64, ARM, ARM64)\dbgsrv\android_server64" /data/local/tmp
2、如果是真機,則需要輸入su,模擬器不需要
#真機 su
3、修改權限
chmod 777 /data/local/tmp/android_server64
4、運行
/data/local/tmp/android_server64
5、新打開一個cmd,在本地執行adb 做端口轉發
adb forward tcp:23946 tcp:23946
ida pro的工作準備
1、打開ida pro,因為我們的so是64位的,所以打開ida64.exe。點擊new,選擇libnative-lib.so。
2、選擇debugger-select debugger
3、選擇Remote ARM Linux/Android debugger
4、點擊debugger-Debugger options
勾選Suspend on process entry point ,也就是在斷點處進行掛起暫停
5、點擊debugger-Process options
填寫hostname為localhost
6、找到exports標簽,ctrl+f,搜索java關鍵字,找到我們要hook的函數。
7、雙擊打開,按F5,進行反匯編操作。這樣就可以看到反匯編之後的c ++代碼瞭。然後我們隨便加上斷點進行調試。
8、執行adb命令,進入調試狀態,也就是打開我們要調試的app的啟動activity,我這邊如下:
adb shell am start -D -n com.noober.naticeapplication/com.noober.naticeapplication.MainActivity
9、點擊debugger-Attach to process
選擇我們需要調試的進程。
10、adb 執行如下命令,關聯運行的so與本地要調試的so。
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
11、此時ida卡在libc.so的位置,點擊繼續執行,彈出如下界面,關聯so到本地,選擇same。如果沒有彈出則需要通過快捷鍵ctrl+s, 打開所有已經加載的so,找到我們的libnative-lib.so
12、此時就會自動進入斷點。
使用ida pro進行調試
ida pro 常用調試快捷鍵
- F2下斷點
- F7單步步入
- F8單步步過
- F9執行到下個斷點
- G調到函數地址
- Debugger-debugger windows-locals 查看變量
進行調試
簡單分析反匯編代碼,我們發現返回值是v5,通過f8,執行到return的上一行。打開locals, 獲取所有變量的值。
復制bytes的地址0x7FFE2CDEB9LL,切換到代碼界面,輸入快捷鍵g,輸入地址跳轉。這樣我們便從內存中得到瞭數據結果,可以看出本次返回的值就是”Hello from c++89″
當然我們也可以在locals中直接修改值,這樣就達到瞭我們hook so動態修改數據的目的。
結束
以上就是所有文章內容,主要是為瞭給沒有接觸過so調試的同學學習,以及自己記錄。關於如何去進一步so hook,會在後面的研究後繼續分享。
到此這篇關於android so庫逆向調試的文章就介紹到這瞭,更多相關android so庫逆向調試內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 鴻蒙手機版JNI實戰案例解析(JNI開發、SO庫生成、SO庫使用)
- C語言JNI的動態註冊詳解
- Android 中的類文件和類加載器詳情
- idea下Android各目錄所代表的含義介紹
- Java中的Native方法