非常詳細(xì)的android so庫逆向調(diào)試教程
好久沒有寫博客了,最近的精力全放在逆向上面。目前也只是略懂皮毛。
android java層的逆向比較簡單,主要就是脫殼 、反編譯源碼,通過xposed進(jìn)行hook。
接下來介紹一下,如何去調(diào)試hook native層的源碼,也就是hook so文件。
應(yīng)用環(huán)境準(zhǔn)備首先,為了方便學(xué)習(xí),一上來就hook第三方app難度極大,因此我們自己來創(chuàng)建一個native的項(xiàng)目,自己來hook自己的項(xiàng)目作為學(xué)習(xí)的練手點(diǎn)。
創(chuàng)建默認(rèn)的native application打開as,選擇File -> new project -> naive c++ 創(chuàng)建包含c++的原生工程。
默認(rèn)的native工程,幫我們實(shí)現(xiàn)了stringFromJNI方法,那我們就來探索如何hook這個stringFromJNI,并修改他的值。
修改stringFromJNI方法,便于調(diào)試as默認(rèn)實(shí)現(xiàn)的stringFromJNI只有在Activity onCreate的時候調(diào)用,為了便于調(diào)試,我們增加一個點(diǎn)擊事件,每次點(diǎn)擊重新調(diào)用,并且返回一個隨機(jī)的值。
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 JNICALLJava_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; elseresult = num2; return result;}
修改的代碼很簡單,相信不會 c++ 的同學(xué)也看得懂,就是隨機(jī)輸入兩個數(shù),取其中小的那一位拼接在“Hello from C++”后面,并返回。主要目的是讓我們每次點(diǎn)擊的時候,返回內(nèi)容可以動態(tài)。
修改androidManifest文件在application中增加下面兩行代碼:
android:extractNativeLibs='true' android:debuggable='true'
android:debuggable: 讓我們可以對apk進(jìn)行調(diào)試,如果是第三方已經(jīng)打包好了app,我們需要對其manifest文件進(jìn)行修改,增加這行代碼,然后進(jìn)行重打包,否則無法進(jìn)行so的調(diào)試。
android:extractNativeLibs: 很多人在進(jìn)行調(diào)試的時候發(fā)現(xiàn)ida pro一切正常,但是卻一直沒有加載我們的libnative-lib.so, 是因?yàn)槿鄙龠@行代碼。如果不加,可能會使so直接自身的base.apk進(jìn)行加載,導(dǎo)致ida pro無法識別。
修改CMakeLists.txt在cmakelists中增加下面代碼。so文件生成路徑,這樣編譯之后就可以在main-cpp-jniLibs目錄下找到生產(chǎn)的so文件。
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/jniLibs/${ANDROID_ABI})編譯運(yùn)行,獲取so
上述工作做好之后,直接編譯運(yùn)行,同時會生成4個so文件,我們?nèi)∈謾C(jī)運(yùn)行時對應(yīng)使用的那個so進(jìn)行hook。我這邊使用的是arm64-v8a目錄下的libnative-lib.so。
1、首先找到ida pro的dbgsrv文件夾,里面有很多server文件
64代表的含義是64位,否則就是32位,我們根據(jù)我們需要調(diào)試的so的指令集進(jìn)行選擇。因?yàn)槲疫@邊調(diào)試的是arm64-v8a,這里我們就選擇android_server64的文件。連接真機(jī)后,打開cmd,輸入以下指令:
adb push 'MacHomeDesktopIDA PRO 7.5 (x86, x64, ARM, ARM64)dbgsrvandroid_server64' /data/local/tmp
2、如果是真機(jī),則需要輸入su,模擬器不需要
#真機(jī) su
3、修改權(quán)限
chmod 777 /data/local/tmp/android_server64
4、運(yùn)行
/data/local/tmp/android_server64
5、新打開一個cmd,在本地執(zhí)行adb 做端口轉(zhuǎn)發(fā)
adb forward tcp:23946 tcp:23946ida pro的工作準(zhǔn)備
1、打開ida pro,因?yàn)槲覀兊膕o是64位的,所以打開ida64.exe。點(diǎn)擊new,選擇libnative-lib.so。
2、選擇debugger-select debugger
3、選擇Remote ARM Linux/Android debugger
4、點(diǎn)擊debugger-Debugger options
勾選Suspend on process entry point ,也就是在斷點(diǎn)處進(jìn)行掛起暫停
5、點(diǎn)擊debugger-Process options
填寫hostname為localhost
6、找到exports標(biāo)簽,ctrl+f,搜索java關(guān)鍵字,找到我們要hook的函數(shù)。
7、雙擊打開,按F5,進(jìn)行反匯編操作。這樣就可以看到反匯編之后的c ++代碼了。然后我們隨便加上斷點(diǎn)進(jìn)行調(diào)試。
8、執(zhí)行adb命令,進(jìn)入調(diào)試狀態(tài),也就是打開我們要調(diào)試的app的啟動activity,我這邊如下:
adb shell am start -D -n com.noober.naticeapplication/com.noober.naticeapplication.MainActivity
9、點(diǎn)擊debugger-Attach to process
選擇我們需要調(diào)試的進(jìn)程。
10、adb 執(zhí)行如下命令,關(guān)聯(lián)運(yùn)行的so與本地要調(diào)試的so。
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
11、此時ida卡在libc.so的位置,點(diǎn)擊繼續(xù)執(zhí)行,彈出如下界面,關(guān)聯(lián)so到本地,選擇same。如果沒有彈出則需要通過快捷鍵ctrl+s, 打開所有已經(jīng)加載的so,找到我們的libnative-lib.so
12、此時就會自動進(jìn)入斷點(diǎn)。
ida pro 常用調(diào)試快捷鍵
F2下斷點(diǎn) F7單步步入 F8單步步過 F9執(zhí)行到下個斷點(diǎn) G調(diào)到函數(shù)地址 Debugger-debugger windows-locals 查看變量進(jìn)行調(diào)試簡單分析反匯編代碼,我們發(fā)現(xiàn)返回值是v5,通過f8,執(zhí)行到return的上一行。打開locals, 獲取所有變量的值。
復(fù)制bytes的地址0x7FFE2CDEB9LL,切換到代碼界面,輸入快捷鍵g,輸入地址跳轉(zhuǎn)。這樣我們便從內(nèi)存中得到了數(shù)據(jù)結(jié)果,可以看出本次返回的值就是'Hello from c++89'
當(dāng)然我們也可以在locals中直接修改值,這樣就達(dá)到了我們hook so動態(tài)修改數(shù)據(jù)的目的。
結(jié)束以上就是所有文章內(nèi)容,主要是為了給沒有接觸過so調(diào)試的同學(xué)學(xué)習(xí),以及自己記錄。關(guān)于如何去進(jìn)一步so hook,會在后面的研究后繼續(xù)分享。
到此這篇關(guān)于android so庫逆向調(diào)試的文章就介紹到這了,更多相關(guān)android so庫逆向調(diào)試內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. Android 實(shí)現(xiàn)徹底退出自己APP 并殺掉所有相關(guān)的進(jìn)程2. Vue實(shí)現(xiàn)仿iPhone懸浮球的示例代碼3. vue使用moment如何將時間戳轉(zhuǎn)為標(biāo)準(zhǔn)日期時間格式4. 一個 2 年 Android 開發(fā)者的 18 條忠告5. js select支持手動輸入功能實(shí)現(xiàn)代碼6. Spring的異常重試框架Spring Retry簡單配置操作7. Android studio 解決logcat無過濾工具欄的操作8. 什么是Python變量作用域9. PHP正則表達(dá)式函數(shù)preg_replace用法實(shí)例分析10. vue-drag-chart 拖動/縮放圖表組件的實(shí)例代碼
