RegisterNativesAndroidJNI
RegisterNatives 定位思路:JNI 动态注册别只看 OnLoad,要把绑定表掏出来
很多人知道动态注册要看 JNI_OnLoad,但问题是:看见 OnLoad 只是开始,不是结束。真正值钱的是把注册表里的类名、方法名、签名、函数地址一一拉出来,重新把 Java 和 native 对上。
先说结论:动态注册的核心不是找到 OnLoad,而是恢复绑定关系
你最终真正需要的不是“这里调用了 RegisterNatives”,而是:
- 注册了哪个类
- 注册了哪些方法
- 每个方法签名是什么
- 它们对应哪一个 native 地址
OnLoad 是入口,绑定表才是产出。只找到入口不把表掏出来,等于只走了一半。
第一步:先找 RegisterNatives 调用点
常见路径有两类:
- 直接在 JNI_OnLoad 里调
- JNI_OnLoad 再跳到一个初始化函数里间接调
所以不要死盯 OnLoad 本体,调用链往下一跳、两跳很常见。
第二步:识别 JNINativeMethod 数组
RegisterNatives 最值钱的对象通常就是那张表。它一般包含三列:
- Java 方法名
- 方法签名
- native 函数指针
一旦这张表被识别出来,动态注册就不再神秘,native 函数也能立刻被批量命名。
第三步:别忽略类名解析和多表注册
真实项目经常不是一张表、一把梭,而是:
- 多个类分别注册
- 按模块拆成几段初始化
- 类名先解密/拼装再传给 FindClass
如果你只抓到一张表就收工,很容易漏一半。
第四步:把 Java 声明、签名、native 地址三者对齐
这一步特别重要。因为只有对齐了:
- 你才知道哪个 Java 方法最终落到哪个 native 函数
- 你才知道参数类型到底怎么解释
- 你后面做 hook、重命名、调用链分析才会顺
最容易犯的错误
- 只找到 JNI_OnLoad 就以为任务完成
- 只盯函数名,不把签名一起恢复
- 漏掉多个注册表或间接注册路径
- native 地址找到了,却没回填到 Java 语义上
我更推荐的恢复顺序
- 找 RegisterNatives 调用点
- 识别并导出 JNINativeMethod 表
- 恢复类名、方法名、签名、地址四元组
- 批量回填到静态分析环境里
这样做的好处是:JNI 动态注册会从“看起来很绕”变成一张很清楚的映射表。
结尾
RegisterNatives 真正值钱的地方,不在它“隐藏了符号”,而在它把绑定关系藏进了运行时表。只要你把这张表掏出来,很多 native 黑盒都会瞬间少掉一大半雾。