前言
在逆向的时候,有些应用有一大堆的so,而且都是提前加载好,有的so甚至做了处理,很难看出函数名。本文讲述的方法可以快速定位:
- native方法的实现在哪个so中
- 在so中的哪个位置
原理
我们知道,在使用native方法之前,需要先load对应的so。 在load so的时候,其实就是dlopen该so。 不管你是否主动注册了方法映射,系统都是通过dlsys来获取对应的实现函数,并将其和java层的method关联起来,具体参见Dalvik虚拟机原理及Xposed hook原理
在调用native方法时,通过桥接的方式来调用:
DalvikBridgeFunc bridge = gDvmJni.useCheckJni ? dvmCheckCallJNIMethod : dvmCallJNIMethod;
其实就是dvmCallJNIMethod
。
ok,在这个函数中,我们可以将方法名和对应的底层函数地址打印出来即可:
ALOGI("invoke native method %s, addr:%p", method->name, method->insns);
日志如下:

就这么简单。
但是还有几个地方得说一下:
- 这个
addr
是运行时候的虚拟地址,如何知道是哪个so呢?
这就需要使用ida调试一下,当断点断下来时,按G
跳转到这个地址,你将会在左侧看出是加载了哪个so,将这个地址减去这个so的加载基地址,就可以获取到函数在so中的地址了。
还有另外一种获取基址且不需要调试的方法,直接查看/proc/$pid/maps映射
- 如何添加打印的代码?
两种选择:编译源码和native hook。
编译源码见ubuntu14.04编译Android4.4源码
native hook见Android Inline Hook 详解
如果觉得我的文章对你有帮助,想要打赏我,请扫下面的微信(吐槽下简书的打赏提现略坑)

网友评论
特意翻了elf文档,动态链接器在链接时,会加载依赖项,具体如下:
3.8.3.4 共享目标的依赖关系
在链接编辑器处理某个归档库时,它会从库中提取成员并将它们复制到输出目标文 件中。这些静态链接的服务都是在执行中可用的,不需要动态链接器的参与。共享目标
© 北京大学信息科学技术学院操作系统实验室 第 26 页 共 38 页
PKU/SSDB-03-TR-005 20 03 年 5 月
所提供的服务则必须由动态链接器附加到进程映像中。因此可执行文件和共享目标文件 描述了它们的特定的依赖关系。 在动态链接器为某个目标文件创建内存段时,依赖关系(记录于动态结构的 DT_NEEDED 表项中)能够提供需要哪些目标来提供程序服务的信息。通过不断地将 被引用的共享目标与他们的依赖之间建立连接,动态链接器构造出完整的进程映像。在 解析符号引用时,动态链接程序使用宽度优先算法检查符号表。 就是说首先检查可执行程序自身的符号表,然后检查 DT_NEEDED 条目(按顺序) 的符号表,接着在第二级 DT_NEEDED 条目上搜索。共享目标文件必须对进程而言可 读,不需要其他权限。 即使某个共享目标在依赖表中出现多次,动态链接器也仅会对其连接一次。 存在于依赖表中的名称或者是 DT_SONAME 字符串的副本,或者是用来构造目标 文件的共享目标的路径名称。例如,如果连接编辑器在构造某个可执行文件时使用的一 个共享目标中包含 lib1 的 DT_SONAME 项,并且使用了路径名为 /usr/llib/lib2 的共 享目标库,那么可执行文件将在其依赖表中包含 lib1 和 /usr/lib/lib2。 如