Frida 玩转 JNI:方法地址追踪 + 指令反汇编 + Patch 注入

版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/

Frida 反汇编

Frida 提供了反汇编 API,主要用于对目标进程的代码进行动态分析,例如:

  • 获取函数的机器代码并将其反汇编为汇编指令。

  • 分析内存中的指令流。

这些功能在 Frida 的 Instruction 类中实现,基于 Capstone 实现的反汇编功能。

https://frida.re/docs/javascript-api/#instruction

word/media/image1.png

比如,可以通过 Instruction.parse 方法反汇编指定地址的汇编信息

[Remote::AndroidExample]-> Instruction.parse(ptr("0x7e7acdb9a0"));
{
    "address": "0x7e7acdb9a0",
    "groups": [],
    "mnemonic": "sub",
    "next": "0x7e7acdb9a4",
    "opStr": "sp, sp, #0x10",
    "operands": [
        {
            "type": "reg",
            "value": "sp"
        },
        {
            "type": "reg",
            "value": "sp"
        },
        {
            "type": "imm",
            "value": "16"
        }
    ],
    "regsRead": [],
    "regsWritten": [],
    "size": 4
}

Android 示例代码

定义一个 native 函数 add,计算 1+ 1 + 1 并返回结果。

把 add 函数动态注册到 com.cyrus.example.frida.disassemble.FridaDisassembleActivity#add。

#include <jni.h>
#include <android/log.h>

#define LOG_TAG "FridaDisassemble"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)

// 实现 add 方法:计算 1 + 1 + 1
jint native_add(JNIEnv *env, jobject obj) {
    return 1 + 1 + 1;
}

// 定义 JNI 方法映射
static const JNINativeMethod methods[] = {
        {"add", "()I", (void *)native_add} // 方法名, 方法签名, C++函数指针
};

// 动态注册 JNI 方法
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env;
    if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }

    // 获取 Java 类
    jclass clazz = env->FindClass("com/cyrus/example/frida/disassemble/FridaDisassembleActivity");
    if (clazz == nullptr) {
        LOGD("[-] Failed to find class FridaDisassembleActivity");
        return JNI_ERR;
    }

    // 注册 native 方法
    if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
        LOGD("[-] Failed to register native methods");
        return JNI_ERR;
    }

    LOGD("[+] Successfully registered native methods");
    return JNI_VERSION_1_6;
}

在 kotlin 层调用 add 函数并 toast 结果。

// 调用 native 方法
val result = add()
// 显示 Toast
Toast.makeText(this, "add() returned: $result", Toast.LENGTH_LONG).show()

当点击按钮可以看到返回结果 3。

word/media/image2.png

接下来通过 Frida 实现:

  1. 找到 add 函数动态注册的地址

  2. 反汇编 add 函数机器码

  3. patch add 函数汇编指令修改返回结果

JNI 方法地址跟踪

1. 启动 Frida Server

# 启用超级管理员
adb root

# 进入命令行
adb shell 

# 启动frida-server,并指定端口
/data/local/tmp/fs -l 0.0.0.0:1234

# 端口转发到本地
adb forward tcp:1234 tcp:1234

Frida 的详细使用参考这篇文章:

Frida是一款免费的,基于Python和JavaScript来实现的,面向开发人员、逆向工程师和安全研究人员的动态检测工具包。 Frida拥有一套全面的测试套件,不但调试效率极高,而且在广泛的使用中经历了多年严格的测试。 尤其是,移动应用安全测试和服务巨头NowSecure对齐钟爱有加,在NowSecure内部,安全人员通过Frida这个工具套装,已经完成对大量的移动应用程序大规模深度的安全分析测试。目前依然在该公司的安全测试中扮演重要的角色。 基于Python和JavaScript的Frida,天生就是跨平台的动态调试工具,不但可以运行在Windows、Linux、macOS之上,而且还可以调试Windows应用程序、Linux应用程序,macOS、iOS、Andriod和QNX等几乎全平台的应用程序。可以说,一旦掌握Frida这套工具,就可以在全平台,对全平台的应用程序进行动态调试和分析。 Frida使用极其方便,在使用过程中,只需将你编写的JavaScript脚本通过Frida自身的工具注入到目标进程中,就可以HOOK任何功能,其中包括但不限于监视加密API或跟踪应用程序关键代码等。在使用过程中,无需知道被“研究”程序的源代码。 尤其是可以一边编辑JavaScript脚本,一边运行JavaScript脚本的功能对于调试分析来说极为友好。只需“保存”正在编辑的JavaScript脚本,就立即就能看到该脚本执行的结果,全称无需其它人工介入,也无需重新启动被“研究”的应用程序,极大地简化了分析流程,同时也极大地提高了工作效率。因此,得到了众多安全分析人士的青睐。 本课程从最基本的调试环境搭建开始,基于经典的Windows“扫雷”游戏的动态调试分析,编码等,循序渐进演示Firda在分析调试Windows应用程序中基本使用方法和技巧。拥有这些知识储备之后,在加上官方的参考文档,你就可以轻松地将这些知识“迁移”至分析和调试其他平台的应用程序。 课程资料,请看第一课中github链接。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值