lkamxmk 发表于 2019-9-19 20:02:46

Android逆向系列之动态调试(六)–IDA调试so文件

## 一、前奏
> **1.demo.apk、IDA6.6以上、adb等工具**
>
> demo.apk的主逻辑代码如下:
>
>
>
> **2.什么是so文件?**
>
> so文件是unix的动态连接库,我们知道Android系统是类linux,所以这里也沿用其动态链接库so,一般用c语言实现,是二进制文件,作用相当于windows下的.dll文件,在Android中调用动态库文件(*.so)都是通过jni的方式。
>
> Android中加载so文件的提供的API: void System.load(String pathName);
>
> Android系统目前支持以下七种不同的CPU架构:ARMv5,ARMv7 (从2010年起),x86 (从2011年起),MIPS (从2012年起),ARMv8,MIPS64和x86_64 (从2014年起),每一种都关联着一个相应的ABI。我们将apk解压后,在/lib目录下可以看到不同cpu架构的文件夹,其中的so文件是功能相同的,只是实现的指令等细节不同,主流是ARM架构,所以这里我们也是重点分析arm下的so文件。
>
> **3.分析so文件**
>
> 一般逆向so文件,光动态分析仍旧是不够的,一般我们需要先静态简单分析一下,再结合动态调试,这样才能事半功倍。
>
> 我们直接将libencrypt.so文件拖进IDA,如下图:
>
>
>
> 这里我们找到 Java_类名_方法名 的函数,重点分析这个函数(当然有时候并没有java开头,这时可以借助jd-gui等工具找出函数名)
>
> 我们简单分析下arm代码,BLX调用函数,然后有一个判断跳转,再使用BL调用 get_encrypt_str函数,然后有一常量字符串,再调用strcmp进行比较
> (这里为了演示,相对逻辑简单,当然静态分析就可以了,但这并不是目的)
>
> 强大的F5,如果ARM指令看着费劲,可以使用F5查看对应的c语言
> Shirt+F12快捷键,速度打开so中所有的字符串内容窗口
>
>
>
> 具体就不分析了C语言你们比我厉害多了。
>
> 问题分析:这里我们看一下划线处,是不是觉得有点奇葩。
>
> 解决方法:
>
> 还原JNI函数方法名,一般JNI函数方法名首先是一个指针加上一个数字,比如v3+676。然后将这个地址作为一个方法指针进行方法调用,并且第一个参数就是指针自己,比如(v3+676)(v3…)。这实际上就是我们在JNI里经常用到的JNIEnv方法。因为Ida并不会自动的对这些方法进行识别,所以当我们对so文件进行调试的时候经常会见到却搞不清楚这个函数究竟在干什么,因为这个函数实在是太抽象了。解决方法非常简单,只需要对JNIEnv指针做一个类型转换即可。
> 选中a1变量,然后按一下y键,输入:JNIEnv*,确定即可。
>
## 二、准备调试
> **1.调试准备**
>
> 在IDA目录下的dbgsrv目录下找到android_server,是不是有点眼熟,是的,没错!有点类似gdbserver,操作也是类似,具体可查看上一篇文章;
>
> adb remount
>
> adb push android_server /system/bin
>
> adb shell chmod 755 /system/bin/android_server
>
> adb shell android_server
>
> adb forward tcp:23946 tcp:23946
>
> **2.IDA-attach**
>
> 模拟器里启动要调试的APP
>
> 启动IDA,打开debugger->attach->remote Armlinux/andoid debugger
>
> 填写hostname为127.0.0.1或localhost(推荐),端口确定为23946或你自定义转发的端口,其他默认,点击确定
>
> 弹出Choose process to attach to窗口,找到app的进程名,点击ok,等待分析后即可进入调试界面
>
>
>
> 问题分析:为什么会断在libc.so中
>
> 问题解决:
>
> android系统中libc是c层中最基本的函数库,libc中封装了io、文件、socket等基本系统调用。所有上层的调用都需要经过libc封装层。所以libc.so是最基本的,所以会断在这里,而且我们还需要知道一些常用的系统so,比如linker;这个linker是用于加载so文件的模块,如何在.init_array处下断点;还有一个就是libdvm.so文件,他包含了DVM中所有的底层加载dex的一些方法
>
> **3.定位函数**
>
>使用快捷键Ctrl+s打开segment窗口,选择so文件,这里可以使用Ctrl+f进行搜索;同时这里需要记下so文件的起始地址(A8924000)
>
> 用另一个IDA打开so文件,找到对应函数的便宜位置,在上面的图可以看到偏移为:00000E9C
>
> 绝对地址=基址+偏移地址=A8924000+00000E9C=A8924E9C
>
> 按下快捷键G,输入A8924E9C即可跳转到正确的函数。然后使用F2或者点击前面的小圆点 下一个断点
>
>
>
> 问题分析:窗口里有多个so文件怎么办?应该选择哪一个?
>
> 问题解决:
>
> 其实这里并不是多个so文件,而是so文件对应的不同Segement信息被映射到内存中,包括代码段,数据段等,很明显,代码段会有执行权限的特点,所以我们选择带有X属性的so文件,即是我们想要调试的so文件。
>
>
>
> **4.调试**
>
> 按F9或点击绿色三角形按钮运行程序
>
> 触发断点:这里是点击程序的按钮,具体视应用不同而不同
>
> 接着就是F7/F8调试的常规步骤了!!
>
> **5.调试步骤小结**
>
> (1)调试步骤:
>
>\1. adb shell am start -D -n {pkgname}/{Activity}
>
> \2. ida android_server放到手机,以root身份运行,PC端idapro远程连接、 attach、下断点
>
> \3. adb forward tcp:8700 jdwp:{pid}
>
> \4. jdb -connect “com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700”
>
> (2)调试步骤:
>
> \1. adb shell am start -D -n {pkgname}/{Activity}
>
> \2. adb forward tcp:23946 tcp:23946
>
> \3. ida android_server放到手机,以root身份运行,PC端idapro远程连接、 attach、下断点
>
>\4. 打开DDMS,查看端口
>
> \5. jdb -connect “com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700”
>
> 参考资料: http://blog.csdn.net/jiangwei0910410003/article/details/51500328


页: [1]
查看完整版本: Android逆向系列之动态调试(六)–IDA调试so文件