unidbg 加载 so 并调用 so 中函数¶
1. 前提准备¶
本文前需要以下准备:
jadx: 主要用于查看目标app的native的部分,也可不用ida: 用于分析目标app的so文件idea: 用于编写和调试unidbg脚本jdk: 环境需要- 肉丝 unidbg 知乎教程系列
- unidbg 官方文档
- unidbg github 地址
unidbg 也一直在维护和更新中,一切请以 unidbg 官网最新 api 为准。
1.1. 环境配置¶
将上步骤的 jdk 等环境配置即可,然后 git 克隆 unidbg 的项目,会自动下载依赖。如果能跑通 unidbg 中的 看雪 和 Github 等示例即可。都很简单,不再赘述!
1.2. unidbg 新建项目¶
根据目标 app 的包名信息创建项目
那么,为什么要以目标 app 的包名创建项目呢?
简单来说,就是 unidbg 在符号调用 so 的函数时需要包名信息来确定要调用的方法所在的 java 类。

2. 调用过程¶
unidbg 执行 so 函数可以使用符号调用或地址调用,以下会使用这两类方式进行演示:
2.1.加载 so,并调用 init 以及 init_array 中的函数¶
init 对应的 app 中 cpp 的内容大致如下:

也可以在 ida 中反编译 so 文件后查看 init_array 的信息:将 so 文件拖入 ida 中分析,ctrl + s 查看 init_array 中有两个函数:go into myConstructor1 和 go into myConstructor2

go into myConstructor1 如下:

go into myConstructor2 如下:

unidbg 在加载 so 时就完成了 init 的相关调用
对应 uniodbg 的输出信息为:

2.2. 调用 so 中的普通函数¶
2.2.1. 调用 add(int, int) 函数:¶

对应的导出函数名为 _Z3addii,具体如下:
则调用 add(int, int) 函数的示例为:
2.2.2. 调用 add_six(int,int,int,int,int,int) 函数¶
ida 查看对应的导出函数名为 _Z7add_sixiiiiii,具体如下:
则调用 add_six(int,int,int,int,int,int) 函数的示例为:
2.2.3. 调用 getstringlength(char const*) 函数¶
getstringlength(char const*) 对应的导出函数为 _Z15getstringlengthPKc,至于怎么得到这个结论不再演示。
则调用示例为:
2.2.4. 调用 getstringlength2(char const*,char const*) 函数¶
这个函数就比 2.2.2 多个同是指针的参数,老版 unidbg 记得申请内存地址两次即可,新版也只要添加个同样的参数而已,不再赘述。
3. 调用 JNI_OnLoad函数¶
直接执行 unidbg 的 JNI_OnLoad 函数就可以了
执行结果为:

4. 调用 jni 函数¶
根据 3 的执行结果,可以知道 b35 地址对应的为 stringFromJNI2 函数信息。在 ida 中按快捷键 G 输入 b35 跳转到对应代码内容。
4.1. 调用静态注册的 stringFromJNI1 函数¶
我们先调用在 ida 的 Exports 中可以查看到的 stringFromJNI1 函数,ida 中查看代码为:

unidbg 调用示例如下:
4.2. 调用动态注册的 stringFromJNI2 函数¶
在 ida 中按快捷键 G 输入 b35 跳转到对应代码内容如下:

在上面和下面的 unidbg 日志可知,动态注册的函数名称为 stringFromJNI2:
则调用示例为: