Android SO精要调试
今天在这里简介一下IDA调试SO中init的方法
init是什么
init()函数是Android系统给SO的一次启动时优先执行指令的机会。类似于windows平台的TLS回调。
如果你的SO定义了该函数,或者更准确的说是在Dynamic表中存在表示DT_INIT的表项,系统就会尝试调用该表项所指地址。
工具
IDA,Android手机or平板一台(非深度订制系统,如小米etc.)简称“设备”。
流程
1.Root设备
Root权限下才能快乐调试。
使用市面上的各种Root师傅工具。
2.连接设备
将设备打开调试模式在开发者选项里。
将IDA安装目录中dbgsrv文件夹下的android_server推送到设备系统目录并赋可执行权限。在高于IDA6.6版本才能调试高版本android,此时调试低版本Android SO时,需要使用的是android_nonpipe。
在PC端输入命令:
adb shell su
adb shell android_server的路径/android_server
保持上面窗口,在命令行窗口进行端口转发:
adb forward tcp:23946 tcp:23946
为什么是23946呢,IDA和push进设备的android_server默认用都用23946端口进行通讯。当然可以修改。
3.打开IDA
附加或者启动进程的过程不再多言。
4.定位INIT函数
比较便捷的方法是找一份与设备同系统版本号的android源码。解析执行SO文件的地方在linker.c(cpp)中。
因为不同版本有差异,我就不上图了。
高版本时在do_dlopen()下的CallConstructors()里面,但是编译系统时往往将其和find_library融合在其父函数中,查找时需注意。一个简便方法是源码中搜索“INIT”四个字.
先将设备中的linker pull出来用IDA分析来确定调用INIT的具体位置。
因为linker在Android进程中加载非常早,所以它在IDA中的地址可以不用修正直接拿来用。
5.下断在INIT
下断点后,执行Apk中触发加载该SO的功能。
正常情况下就能停在该SO的INIT前了。
经验分享
在调试中某些情况下单步会偶发异常,用IDA 的F4即执行到功能可以尽力避免此种情况。