020 Android之so文件动态调试
文章目錄
- ELF文件格式查看工具
- so文件加載時(shí)的函數(shù)執(zhí)行順序
- so文件動(dòng)態(tài)調(diào)試
- so文件調(diào)試技巧
- 使用ida動(dòng)態(tài)調(diào)試的那些坑
- 進(jìn)程顯示不全
- illegal segment bitness
- more than one special register present
- adb安裝強(qiáng)制應(yīng)用App以32位運(yùn)行
ELF文件格式查看工具
和PE文件類似,比PE文件簡單,我們可以用NDK中提供的一個(gè)工具readelf去查看ELF文件主要表信息
目錄:
D:\Android\sdk\ndk-bundle\toolchains\x86-4.9\prebuilt\windows-x86_64\bin[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-1s7iWskx-1633180160882)(020 Android之so文件動(dòng)態(tài)調(diào)試.assets/1632204382649.png)]
常見命令:
-h 查看頭文件 -S 查看Section header Table -l 查看程序頭表Program Header Table -s 查看符號(hào)表 -d 查看動(dòng)態(tài)加載信息查看頭信息
查看區(qū)段信息
so文件加載時(shí)的函數(shù)執(zhí)行順序
想要調(diào)試so文件,首先需要弄清楚so文件加載時(shí)的函數(shù)執(zhí)行順序,先看下面的代碼
extern "C" void _init(void){__android_log_print(ANDROID_LOG_DEBUG,"init","_init"); }void __attribute__((constructor)) init1(void){__android_log_print(ANDROID_LOG_DEBUG,"init","init1"); }void __attribute__((constructor)) init2(void){__android_log_print(ANDROID_LOG_DEBUG,"init","init2"); }void __attribute__((constructor)) init3(void){__android_log_print(ANDROID_LOG_DEBUG,"init","init3"); }extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm,void *reseverd){__android_log_print(ANDROID_LOG_DEBUG,"init","JNI_Onload");JNIEnv* env;jint ret=vm->GetEnv((void **)&env,JNI_VERSION_1_6);if (ret!=JNI_OK){return 0;}return JNI_VERSION_1_6; }接著執(zhí)行代碼
so文件第一個(gè)執(zhí)行的函數(shù)是**_init函數(shù),接著執(zhí)行的是init數(shù)組中的函數(shù),分別是init1,init2和init3,這個(gè)數(shù)組中的函數(shù)可以自定義,只需要符合對(duì)應(yīng)的格式即可,最后再執(zhí)行JNI_OnLoad**
**so文件分析流程:**當(dāng)我們分析so文件時(shí),首先需要分析_init函數(shù),接著分析init_array數(shù)組,最后分析JNI_OnLoad函數(shù)
接著我們用readelf工具查看動(dòng)態(tài)加載信息,可以看到init和init_array的地址
接著用IDA跳轉(zhuǎn)到init_arrray的地址,可以找到三個(gè)init函數(shù)。
so文件動(dòng)態(tài)調(diào)試
將IDA目錄下的android_server上傳到android機(jī)器中(注意android_server需要和目標(biāo)系統(tǒng)架構(gòu)和位數(shù)一致)
adb push .\android_server /data/local/tmp/ands修改文件權(quán)限
接著測(cè)試運(yùn)行
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-CzT5wPlV-1633180160896)(020 Android之so文件動(dòng)態(tài)調(diào)試.assets/1632212563278.png)]
這里提示當(dāng)前正在監(jiān)聽23946端口,這個(gè)是IDA服務(wù)默認(rèn)監(jiān)聽的端口
用-p參數(shù)可以指定端口
以調(diào)試方式啟動(dòng)進(jìn)程后
在monitor可以看到一個(gè)紅色的小蟲
端口號(hào)要和啟動(dòng)service時(shí)監(jiān)聽的端口一致
最后啟動(dòng)ida附加調(diào)試端口
輸入hostname和port
選擇需要調(diào)試的進(jìn)程
接著就可以愉快的開始debug了
如果需要讓java層代碼跑起來則需要執(zhí)行下面一條命令:
jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8700so文件調(diào)試技巧
在Debugger Option中將模塊加載和線程加載時(shí)斷下的復(fù)選框勾上
打開模塊窗口,找到需要調(diào)試的so文件,雙擊進(jìn)入
這里可以看到模塊的導(dǎo)出函數(shù)
接著找到需要調(diào)試的函數(shù),比如_init
F2進(jìn)行下斷即可。
使用ida動(dòng)態(tài)調(diào)試的那些坑
so文件動(dòng)態(tài)調(diào)試,看起來簡單,實(shí)際操作過程中總會(huì)遇到各種問題,這里記錄一下遇到的各種坑和解決方案
進(jìn)程顯示不全
當(dāng)我用真機(jī)接入adb進(jìn)行so文件調(diào)試時(shí),發(fā)現(xiàn)在IDA中的進(jìn)程顯示不全。
解決方案:這個(gè)是因?yàn)闆]有用管理員權(quán)限啟動(dòng)idaserver,如果在命令行中使用su沒反應(yīng),需要使用Magisk對(duì)手機(jī)進(jìn)行root獲取管理員權(quán)限后,再用管理員權(quán)限啟動(dòng)idaserver,問題即可解決
illegal segment bitness
64位的系統(tǒng) 默認(rèn)安裝app是64的,出現(xiàn)這個(gè)錯(cuò)誤是因?yàn)閍ndroid_server與需要調(diào)試的app位數(shù)不一樣,例如64位的手機(jī)使用32位的android_server。
我調(diào)試的手機(jī)是64位的,使用的是android_server進(jìn)行調(diào)試。后來換成了android_server64就解決了。
more than one special register present
接著我又遇到了第三個(gè)問題
這個(gè)問題出現(xiàn)的原因是由于IDA版本不匹配導(dǎo)致的,我使用的是64位的手機(jī),需要啟動(dòng)64位的idaserver,然后用ida x64。如果使用x86版本的ida就會(huì)出現(xiàn)上面的問題
adb安裝強(qiáng)制應(yīng)用App以32位運(yùn)行
之前的流程終于跑通了,但是運(yùn)行的是64位的程序,需要看64位的arm匯編,對(duì)新手來說太不友好了。想要調(diào)試32位的匯編需要強(qiáng)制應(yīng)用以32位運(yùn)行,并且使用32位的idaserver,然后使用32位的ida進(jìn)行附加。
直接上命令格式
adb install --abi armeabi-v7a <path to apk>調(diào)用這條命令應(yīng)用以32位在64位終端環(huán)境下運(yùn)行。然后就可以愉快的調(diào)試32位arm匯編了。
流程終于跑通了,但是運(yùn)行的是64位的程序,需要看64位的arm匯編,對(duì)新手來說太不友好了。想要調(diào)試32位的匯編需要強(qiáng)制應(yīng)用以32位運(yùn)行,并且使用32位的idaserver,然后使用32位的ida進(jìn)行附加。
總結(jié)
以上是生活随笔為你收集整理的020 Android之so文件动态调试的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 018 Android加固之实现dex加
- 下一篇: VMP分析之VM解码循环与基本架构(一)