文章目錄
- ELF檔案格式查看工具
- so檔案加載時的函式執行順序
- so檔案動態除錯
- so檔案除錯技巧
- 使用ida動態除錯的那些坑
- 行程顯示不全
- illegal segment bitness
- more than one special register present
- adb安裝強制應用App以32位運行
ELF檔案格式查看工具
和PE檔案類似,比PE檔案簡單,我們可以用NDK中提供的一個工具readelf去查看ELF檔案主要表資訊
目錄:
D:\Android\sdk\ndk-bundle\toolchains\x86-4.9\prebuilt\windows-x86_64\bin
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-1s7iWskx-1633180160882)(020 Android之so檔案動態除錯.assets/1632204382649.png)]
常見命令:
-h 查看頭檔案
-S 查看Section header Table
-l 查看程式頭表Program Header Table
-s 查看符號表
-d 查看動態加載資訊

查看頭資訊

查看區段資訊
so檔案加載時的函式執行順序
想要除錯so檔案,首先需要弄清楚so檔案加載時的函式執行順序,先看下面的代碼
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;
}
接著執行代碼

so檔案第一個執行的函式是**_init函式,接著執行的是init陣列中的函式,分別是init1,init2和init3,這個陣列中的函式可以自定義,只需要符合對應的格式即可,最后再執行JNI_OnLoad**
**so檔案分析流程:**當我們分析so檔案時,首先需要分析_init函式,接著分析init_array陣列,最后分析JNI_OnLoad函式

接著我們用readelf工具查看動態加載資訊,可以看到init和init_array的地址

接著用IDA跳轉到init_arrray的地址,可以找到三個init函式,
so檔案動態除錯
- 上傳IDA除錯服務端

將IDA目錄下的android_server上傳到android機器中(注意android_server需要和目標系統架構和位數一致)
adb push .\android_server /data/local/tmp/ands

修改檔案權限

接著測驗運行
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-CzT5wPlV-1633180160896)(020 Android之so檔案動態除錯.assets/1632212563278.png)]
這里提示當前正在監聽23946埠,這個是IDA服務默認監聽的埠

用-p引數可以指定埠
- 以除錯方式啟動apk
adb shell am start -D -n 包名/入口類名

以除錯方式啟動行程后

在monitor可以看到一個紅色的小蟲
- 設定埠轉發
adb forward tcp:23456 tcp:23456
埠號要和啟動service時監聽的埠一致
- 啟動ida附加,如果是arm架構選擇
ARMLinux/Android debugger,如果是夜神模擬器,選擇linux debugger

最后啟動ida附加除錯埠

輸入hostname和port

選擇需要除錯的行程

接著就可以愉快的開始debug了
如果需要讓java層代碼跑起來則需要執行下面一條命令:
jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8700
so檔案除錯技巧

在Debugger Option中將模塊加載和執行緒加載時斷下的復選框勾上

打開模塊視窗,找到需要除錯的so檔案,雙擊進入

這里可以看到模塊的匯出函式

接著找到需要除錯的函式,比如_init

F2進行下斷即可,
使用ida動態除錯的那些坑
so檔案動態除錯,看起來簡單,實際操作程序中總會遇到各種問題,這里記錄一下遇到的各種坑和解決方案
行程顯示不全

當我用真機接入adb進行so檔案除錯時,發現在IDA中的行程顯示不全,

解決方案:這個是因為沒有用管理員權限啟動idaserver,如果在命令列中使用su沒反應,需要使用Magisk對手機進行root獲取管理員權限后,再用管理員權限啟動idaserver,問題即可解決
illegal segment bitness

64位的系統 默認安裝app是64的,出現這個錯誤是因為android_server與需要除錯的app位數不一樣,例如64位的手機使用32位的android_server,
我除錯的手機是64位的,使用的是android_server進行除錯,后來換成了android_server64就解決了,
more than one special register present
接著我又遇到了第三個問題

這個問題出現的原因是由于IDA版本不匹配導致的,我使用的是64位的手機,需要啟動64位的idaserver,然后用ida x64,如果使用x86版本的ida就會出現上面的問題
adb安裝強制應用App以32位運行
之前的流程終于跑通了,但是運行的是64位的程式,需要看64位的arm匯編,對新手來說太不友好了,想要除錯32位的匯編需要強制應用以32位運行,并且使用32位的idaserver,然后使用32位的ida進行附加,
直接上命令格式
adb install --abi armeabi-v7a <path to apk>
呼叫這條命令應用以32位在64位終端環境下運行,然后就可以愉快的除錯32位arm匯編了,
流程終于跑通了,但是運行的是64位的程式,需要看64位的arm匯編,對新手來說太不友好了,想要除錯32位的匯編需要強制應用以32位運行,并且使用32位的idaserver,然后使用32位的ida進行附加,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/304961.html
標籤:其他
