Frida + Android Hook 完整指南

Frida + Android Hook 完整指南

    • [Frida 原理与架构](#Frida 原理与架构)
    • 环境搭建
    • 手机端准备(adb+frida-server)
    • App脱壳
    • [Java 层 Hook(最常用)](#Java 层 Hook(最常用))
      • [1. 静态分析找目标(jadx)](#1. 静态分析找目标(jadx))
      • [2. 编写 Frida JS 脚本(hook_java.js)](#2. 编写 Frida JS 脚本(hook_java.js))
      • [3. 运行脚本](#3. 运行脚本)
    • [Native 层 Hook(so 库)](#Native 层 Hook(so 库))
      • [1. 场景](#1. 场景)
      • [2. 脚本模板(hook_native.js)](#2. 脚本模板(hook_native.js))
    • [常用 Hook 脚本模板](#常用 Hook 脚本模板)
      • [1. 打印方法调用栈](#1. 打印方法调用栈)
      • [2. Hook 构造方法](#2. Hook 构造方法)
      • [3. 枚举所有类 / 方法](#3. 枚举所有类 / 方法)
    • 总结

Frida 原理与架构

包含:环境搭建、Java 层 Hook、Native 层 Hook、常用脚本模板、常见坑与排查。内容偏实操,直接能用

Frida 是动态插桩框架,可以在不修改 APK、不重启设备的情况下,向运行中的 App 注入 JS 脚本,Hook Java 或 Native 函数。

架构:PC 客户端(frida) + 手机端服务端(frida-server)

语言:PC 端 Python,注入脚本 JavaScript

支持:Android、iOS、Windows、macOS、Linux

环境搭建

bash 复制代码
# 安装frida 16.x 稳定兼容版
pip install frida==16.2.1 frida-tools==12.3.0
# 验证:
frida --version
# 列出手机进程
frida-ps -U  

frida-ps -U 之前需启动模拟器

手机端准备(adb+frida-server)

必须 Root(真机或模拟器,推荐雷电 / Genymotion)

如果连 adb.exe 都没有,需要先下载 Android SDK Platform Tools:
adb-SDK下载

把压缩包解压到一个固定目录,比如 D:\platform-tools

把这个目录添加到系统环境变量 Path 里

重启 CMD,输入 adb --version 验证是否成功

进入adb shell 查看架构,根据架构下载对应的firda-server,这里x86_64

bash 复制代码
getprop ro.product.cpu.abi

frida-server下载:https://github.com/frida/frida/releases/

这里的server版本跟之前的frida版本保持一致,防止出错

在 Assets 列表里,往下翻找到 frida-server-16.2.1-android-x86_64.xz

直达地址:https://github.com/frida/frida/releases/download/16.2.1/frida-server-16.2.1-android-x86_64.xz

(注意:不是 frida-core-devkit,文件名里必须有 frida-server)

解压 .xz 文件,得到 frida-server-16.2.1-android-x86_64;

将 frida-server推送到模拟器里:

bash 复制代码
# 推送到手机或模拟器(选择/data/local/tmp 目录,因为其它目录有的不可写,可能会写入失败)
adb push frida-server-17.9.10-android-x86_64 /data/local/tmp/
# 进入adb shell
adb shell
# 管理员
su
# 加执行权限
chmod 755 /data/local/tmp/frida-server-17.9.10-android-x86_64
# 启动server
/data/local/tmp/frida-server-17.9.10-android-x86_64 &


App脱壳

逆向 hook之前先查看app基本信息,是否加壳,如果有安装firda-dexdump进行脱壳导出.dex文件

bash 复制代码
# 安装对应的版本2.0.1
pip install frida-dexdump==2.0.1

frida-dexdump 2.0.1 是 2024 年 4 月发布,实测与 Frida 16.x(含 16.2.1)完全兼容。

它不强制绑定特定 Frida 小版本,只要 Frida ≥12 基本都能用,但16.2.1 + 2.0.1 是最稳组合。

配套的 frida-server 也要用 16.2.1(与客户端一致)

安装完成后进adb shell,启动frida-server,然后运frida-dexdump -U -f com.app.pkgname导出指定包名的应用的dex文件

导出后得到dex包,对他们使用d2j-dex2jar.bat转换为jar包,然后用jadx-gui查看源码

至于未加固的apk可直接拖入jadx-jui中查看

Java 层 Hook(最常用)

1. 静态分析找目标(jadx)

用 jadx-gui 打开 APK(.dex文件),找到要 Hook 的类和方法,例如:

java 复制代码
package com.example.crypto;
public class MainActivity {
    private String encrypt(String data) { ... }
}
  • 类名:com.example.crypto.MainActivity
  • 方法:encrypt(String)

2. 编写 Frida JS 脚本(hook_java.js)

js 复制代码
Java.perform(function () {
    console.log("[*] 开始 Hook Java 方法");

    // 1. 获取目标类
    var MainActivity = Java.use("com.example.crypto.MainActivity");

    // 2. Hook 方法(参数类型要匹配)
    MainActivity.encrypt.implementation = function (data) {
        console.log("[+] 原方法被调用,参数:" + data);

        // 调用原方法
        var result = this.encrypt(data);

        console.log("[+] 原方法返回值:" + result);

        // 可篡改返回值
        // return "fake_data";
        return result;
    };
});

3. 运行脚本

将frida-server端口转发到本地

bash 复制代码
# frida-server 默认端口为 27042
adb forward tcp:27042 tcp:27042

用脚本去frida app

bash 复制代码
# 方式1:spaw模式注入App(app未启动时注入,自动启动app)
frida -U -f <包名> -l hook_java.js

# 方式2:启动App后并注入
frida -U -p <pid> -l hook_java.js

jadx 反编译 APK,定位目标类 / 方法

选中相应的函数复制为frida代码片段

构造的hook 代码

Frida 注入脚本,观察日志 / 篡改返回值

bash 复制代码
frida -U -f com.example.crypto -l hook_java.js

有时候,-f(spawn 模式)会在 App 刚启动时注入,容易触发崩溃,改用附加模式:

  • 先在模拟器里手动打开 App,让它运行起来
  • 用 frida-ps -U 查看进程 PID
  • 用附加模式注入脚本:
bash 复制代码
frida -U -p <pid> -l hook.js

Native 层 Hook(so 库)

1. 场景

App 用 so 库(libxxx.so)做加密 / 校验,需要 Hook JNI 函数或导出函数。

2. 脚本模板(hook_native.js)

js 复制代码
setImmediate(function () {
    Java.perform(function () {
        console.log("[*] 等待 libxxx.so 加载...");
        // 监听 so 加载
        var System = Java.use("java.lang.System");
        System.loadLibrary.implementation = function (libname) {
            this.loadLibrary(libname);
            if (libname === "xxx") { // libxxx.so
                console.log("[+] libxxx.so 已加载,开始 Hook");
                hookNativeFunc();
            }
        };
    });
});

function hookNativeFunc() {
    // 1. 找导出函数地址
    var funcPtr = Module.findExportByName("libxxx.so", "Java_com_example_crypto_MainActivity_nativeEncrypt");
    if (!funcPtr) {
        console.log("[-] 未找到函数");
        return;
    }
    console.log("[*] 函数地址:" + funcPtr);

    // 2. Hook
    Interceptor.attach(funcPtr, {
        onEnter: function (args) {
            console.log("[+] Native 方法进入");
            // args[0] = JNIEnv*, args[1] = jobject, args[2] = 参数1
            // 读取字符串参数
            var data = Java.vm.getEnv().getStringUtfChars(args[2], null);
            console.log("[+] 参数:" + data.readCString());
        },
        onLeave: function (retval) {
            console.log("[+] Native 返回值:" + retval);
            // 篡改返回值
            // retval.replace(0);
        }
    });
}

常用 Hook 脚本模板

1. 打印方法调用栈

js 复制代码
Java.perform(function () {
    var stackTrace = Java.use("android.util.Log").getStackTraceString;
    Java.use("java.lang.Throwable").$init.implementation = function () {
        this.$init();
        console.log("[+] 调用栈:\n" + stackTrace(this));
    };
});

2. Hook 构造方法

js 复制代码
Java.perform(function () {
    var Clazz = Java.use("com.example.crypto.CoinMoney");
    Clazz.$init.overload("java.lang.String", "int").implementation = function (a, b) {
        console.log("[+] 构造方法参数:" + a + ", " + b);
        return this.$init(a, b);
    };
});

3. 枚举所有类 / 方法

javascript 复制代码
Java.perform(function () {
    var classFactory = Java.classFactory;
    var classes = classFactory.enumerateClasses();
    for (var i = 0; i < classes.length; i++) {
        console.log(classes[i].getName());
    }
});

总结

  • 装 Frida PC 端 + 手机端 frida-server
  • adx 反编译 APK,定位目标类 / 方法
  • 写 JS 脚本 Hook Java/Native 方法
  • Frida 注入脚本,观察日志 / 篡改返回值
  • 处理反调试 / Frida 检测
相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui