当前位置: 首页 > news >正文

关于 JNI 函数逆向(从 Java 到 native)

一、JNI基础概念

JNI(Java Native Interface) 是 Java 调用 native 层 C/C++ 函数的桥梁。

在 Android 中,Java 使用 System.loadLibrary("xxx") 加载 so 文件,然后通过 native 方法声明调用底层函数。

public class Test {static {System.loadLibrary("native-lib"); // 加载 native-lib.so}public native String getToken(String userId); // Java 调用 native 函数
}

native 层实现(C/C++):

JNIEXPORT jstring JNICALL Java_com_example_Test_getToken(JNIEnv *env, jobject thiz, jstring userId) {const char* id = (*env)->GetStringUTFChars(env, userId, 0);// 加密处理逻辑……return (*env)->NewStringUTF(env, "encrypt_result");
}

二、逆向场景目标:追到 so 里具体函数、算法

目标是:

  • 找出 Java 中调用的 native 函数对应哪个 .so 文件;

  • 分析 .so 中的函数逻辑(加密/校验);

  • 使用 Frida 或手动还原算法。


三、逆向流程分解(Java → JNI → native)

步骤 1:找到 native 函数调用点

使用 jadx 打开 APK,搜索 native 关键字或 System.loadLibrary,例如:

public native String encrypt(String input);

这会生成一个 JNI 函数名:

Java_包名_类名_方法名(JNIEnv *env, jobject obj, jstring input)

如:

Java_com_example_Test_encrypt

也可能是动态注册(没有 Java_ 开头),用 RegisterNatives 注册的。

步骤 2:定位对应的 .so 文件

  • System.loadLibrary("xxx") 表示会加载 libxxx.so

  • 找出 libxxx.so,用 IDA Ghidra 打开分析

步骤 3:分析 JNI 函数(导出函数 / 动态注册)

>静态注册

在 so 中能看到类似函数名:

Java_com_example_Test_encrypt

可以直接反汇编分析。

>动态注册(更常见)

在 IDA 中搜索 RegisterNatives,找到注册表:

(*env)->RegisterNatives(env, clazz, methods, methodCount);

其中 methods 是一个结构体数组,包含 Java 方法名、签名、函数指针。

static JNINativeMethod methods[] = {{"encrypt", "(Ljava/lang/String;)Ljava/lang/String;", (void *)encrypt_impl},
};

就能定位 encrypt_impl 函数地址。

步骤 4:分析 native 函数核心逻辑

打开 IDA,进入函数逻辑:

JNIEXPORT jstring JNICALL encrypt_impl(JNIEnv *env, jobject thiz, jstring input) {const char *str = (*env)->GetStringUTFChars(env, input, 0);// --> 加密、混淆、MD5/SHA/AES/RSA/自定义算法分析return (*env)->NewStringUTF(env, result);
}

此时可以使用 Frida 或静态还原分析算法。

步骤 5:恢复 Java ↔ native 参数结构

常见类型映射如下:

Java 类型JNI C/C++ 类型
intjint(int32)
longjlong(int64)
Stringjstring
byte[]jbyteArray
Objectjobject

对应使用:

const char *nativeStr = (*env)->GetStringUTFChars(env, jstringObj, NULL);

四、结合 Frida Hook 的动态分析

可以使用 Frida 动态 Hook JNI 函数,更直观分析逻辑:

Interceptor.attach(Module.findExportByName("libnative-lib.so", "Java_com_example_Test_encrypt"), {onEnter: function(args) {console.log("Hook encrypt input: " + Java.vm.getEnv().getStringUtfChars(args[2], null).readCString());},onLeave: function(retval) {console.log("encrypt result: " + Java.vm.getEnv().getStringUtfChars(retval, null).readCString());}
});

或在 Java 层用 Frida 的 Java.perform Hook:

Java.perform(function() {var cls = Java.use("com.example.Test");cls.encrypt.implementation = function(arg) {console.log("encrypt arg = " + arg);var ret = this.encrypt(arg);console.log("encrypt ret = " + ret);return ret;}
});

五、JNI 函数逆向常见技巧

技巧说明
搜索 RegisterNatives确定动态注册函数表位置
搜索 GetStringUTFChars找到参数获取代码
xrefs 查找调用链IDA 中右键 Xrefs to
使用 Frida trace so快速获得运行时行为
使用 frida-trace -n 自动生成 hook 模板减少手工工作
strings 命令提取字符串线索看是否有 base64、json、AES等加密关键词

六、示例实战流程

  • 用 jadx 找到 native 方法如 getToken(String uid)

  • 找到 System.loadLibrary("encrypt") → 分析 libencrypt.so

  • 用 IDA 找到 Java_..._getToken 或通过 RegisterNativesgetToken

  • 分析内部处理逻辑,比如:

    • 先 base64 解码

    • 再 SHA1 加密

    • 拼接签名参数返回

  • 用 Frida Hook 输出中间值验证你的推测是否正确

  • 成功提取 native 加密算法,Python 重写绕过


七、总结

JNI 函数逆向的核心是从 Java native 方法 → 找到 so 文件函数实现 → 分析参数/返回值结构 → 动静结合还原算法。

http://www.lryc.cn/news/581348.html

相关文章:

  • WebAssembly国际化多语种支持
  • .NET9 实现斐波那契数列(FibonacciSequence)性能测试
  • 闲庭信步使用SV搭建图像测试平台:第三十二课——系列结篇语
  • 力扣 hot100 Day35
  • 详解存储单位、内存寻址及数据存储方式
  • stm32达到什么程度叫精通?
  • jxWebUI--前端联动计算
  • Linux内核深度解析:IPv4策略路由的核心实现与fib_rules.c源码剖析
  • Spring boot之身份验证和访问控制
  • Day52 神经网络调参指南
  • Policy Gradient【强化学习的数学原理】
  • elementui表格增加搜索功能
  • 供应链管理学习笔记4-供应链网络设计
  • 【MySQL进阶】错误日志,二进制日志,mysql系统库
  • 每日算法刷题Day42 7.5:leetcode前缀和3道题,用时2h
  • Android PNG/JPG图ARGB_8888/RGB_565‌解码形成Bitmap在物理内存占用大小的简单计算
  • WPF学习笔记(25)MVVM框架与项目实例
  • Kali Linux Wifi 伪造热点
  • LLM:位置编码详解与实现
  • 通过 Windows 共享文件夹 + 手机访问(SMB协议)如何实现
  • Git 版本控制完全指南:从入门到精通
  • 2025年3月青少年电子学会等级考试 中小学生python编程等级考试三级真题答案解析(判断题)
  • 如何解决Spring Boot中@Valid对List校验失效问题
  • Kafka消息积压的多维度解决方案:超越简单扩容的完整策略
  • 南山科技园的步行
  • LangChain:向量存储和检索器(入门篇三)
  • 利用已有的 PostgreSQL 和 ZooKeeper 服务,启动dolphinscheduler-standalone-server3.1.9 镜像
  • CppCon 2018 学习:Standard Library Compatibility Guidelines (SD-8)
  • 【Elasticsearch】检索排序 分页
  • 大数据学习1:Hadoop单机版环境搭建