安卓逆向|020 Android之so文件动态调试
文章目录
-
- 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
【安卓逆向|020 Android之so文件动态调试】[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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
调用这条命令应用以32位在64位终端环境下运行。然后就可以愉快的调试32位arm汇编了。
流程终于跑通了,但是运行的是64位的程序,需要看64位的arm汇编,对新手来说太不友好了。想要调试32位的汇编需要强制应用以32位运行,并且使用32位的idaserver,然后使用32位的ida进行附加。
推荐阅读
- CVE-2020-16898|CVE-2020-16898 TCP/IP远程代码执行漏洞
- 2020-04-07vue中Axios的封装和API接口的管理
- 2020-10-18|2020-10-18 致各位慢友
- 愉悦的周末(134)2020-9-20
- “沉溺”疫情
- 感恩日记第111篇2020.02.06
- 2020-12(完成事项)
- 「按键精灵安卓版」关于全分辨率脚本的一些理解(非游戏app)
- 清闲
- 学员+3组杨子涓+202002RIA训练营W3D2+苏格拉底提问法