欢迎光临
我们一直在努力

APK Hook 实战

目录

一、Hook 基本原理(一句话懂)

二、环境准备(Windows/macOS + 安卓真机 / 模拟器)

1. 电脑端(安装 Frida)

2. 手机 / 模拟器端(frida-server)

3. 必备工具

三、实战目标(准备一个测试 APK)

四、第一步:用 jadx 定位目标类和方法

五、第二步:编写 Frida Hook 脚本(encrypt_hook.js)

六、第三步:注入脚本并运行

1. 查看手机进程

2. 注入脚本

3. 操作 APP,触发 encrypt 方法

七、进阶:Hook 重载方法 / 多参数

八、常见问题 & 避坑

九、扩展:Native 层 Hook(so 库)

十、总结


下面我用一个完整、可复现、手把手的 APK Hook 实战,从原理、环境、工具、样本分析、脚本编写、注入、调试到常见坑,全部讲透。本次实战选用Frida(最主流、上手快、免 root 也能玩),目标是:Hook 一个 APK 的 Java 加密方法,篡改参数、返回值并打印调用栈。


一、Hook 基本原理(一句话懂)

Hook = 在不修改原 APK 的前提下,拦截目标方法的执行,先跑你的代码,再决定要不要跑原方法。

  • Java 层:Hook 类的方法(如登录、加密、支付)
  • Native 层:Hook so 里的函数(如 JNI 加密、签名校验) 主流框架:Frida(推荐)、Xposed/LSPosed、Magisk + 模块。

二、环境准备(Windows/macOS + 安卓真机 / 模拟器)

1. 电脑端(安装 Frida)

# 安装 Frida 核心
pip install frida-tools

# 验证
frida –version

2. 手机 / 模拟器端(frida-server)

  • 确定手机架构:adb shell getprop ro.product.cpu.abi(一般是 arm64-v8a)
  • 下载对应版本的 frida-server(官网或 GitHub)
  • 推到手机并授权:
  • adb push frida-server-15.2.2-android-arm64 /data/local/tmp/
    adb shell
    cd /data/local/tmp
    chmod 755 frida-server-*
    ./frida-server-* & # 后台运行

    3. 必备工具

    • jadx-gui:反编译 APK,找类和方法
    • Android Studio / 模拟器:调试用
    • adb:连接手机

    三、实战目标(准备一个测试 APK)

    我用一个简单 Demo APK(你可以自己写一个,或用任意带加密方法的 APK):

    // 包名:com.example.crypto
    // 类名:MainActivity
    // 方法:encrypt(String data) —— 对字符串做简单加密
    package com.example.crypto;
    public class MainActivity {
    private String encrypt(String data) {
    // 原逻辑:return Base64.encode(data)
    return "ENCRYPTED:" + data;
    }
    }

    我们要:

  • 拦截 encrypt 方法
  • 打印传入参数和原返回值
  • 篡改返回值为 "HACKED_DATA"
  • 打印调用栈(看谁调用了这个方法)

  • 四、第一步:用 jadx 定位目标类和方法

  • 打开 jadx-gui → 拖入 APK → 等待反编译
  • 搜索包名 / 类名:com.example.crypto.MainActivity
  • 找到目标方法:private String encrypt(String data) 记录:
    • 全类名:com.example.crypto.MainActivity
    • 方法名:encrypt
    • 参数类型:String
    • 返回值类型:String

    五、第二步:编写 Frida Hook 脚本(encrypt_hook.js)

    Java.perform(function () {
    console.log("[*] 开始 Hook 加密方法");

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

    // 2. Hook 目标方法(参数类型必须匹配)
    MainActivity.encrypt.implementation=function (data) {
    // ———- 进入方法前:打印参数 ———-
    console.log("\\n[+] encrypt 被调用");
    console.log("[+] 传入参数:" + data);

    // ———- 打印调用栈(关键!) ———-
    console.log("[+] 调用栈:");
    console.log(Java.backtrace().join("\\n"));

    // ———- 调用原方法,获取原返回值 ———-
    var originalResult=this.encrypt(data);
    console.log("[+] 原方法返回:" + originalResult);

    // ———- 篡改返回值 ———-
    var fakeResult = "HACKED_DATA";
    console.log("[+] 返回篡改值:" + fakeResult);

    // 返回篡改后的值
    return fakeResult;
    };
    });

    保存为 encrypt_hook.js。


    六、第三步:注入脚本并运行

    1. 查看手机进程

    adb shell ps | grep crypto # 找到包名对应的进程ID
    # 或
    frida-ps -U # -U 表示USB设备,直接显示进程名

    2. 注入脚本

    frida -U -n com.example.crypto -l encrypt_hook.js
    # -U:USB设备
    # -n:进程名
    # -l:加载脚本

    3. 操作 APP,触发 encrypt 方法

    打开 APP → 点击加密按钮 → 观察电脑终端输出:

    [*] 开始 Hook 加密方法

    [+] encrypt 被调用
    [+] 传入参数:test123
    [+] 调用栈:
    com.example.crypto.MainActivity.encrypt(Native Method)
    com.example.crypto.MainActivity.onCreate(MainActivity.java:45)

    [+] 原方法返回:ENCRYPTED:test123
    [+] 返回篡改值:HACKED_DATA

    APP 界面显示的加密结果变成了 HACKED_DATA,Hook 成功!

    七、进阶:Hook 重载方法 / 多参数

    如果方法是重载的(多个同名不同参数),要指定参数签名:

    // 例:Hook encrypt(String, int)
    MainActivity.encrypt.overload("java.lang.String", "int").implementation=function (data, num) {
    console.log("参数1:" + data + " 参数2:" + num);
    return "HACK";
    };


    八、常见问题 & 避坑

  • 类找不到(ClassNotFound)
    • 包名 / 类名写错(jadx 里复制全类名)
    • 类在其他 dex(多 dex)→ 用 Java.enumerateClasses() 遍历
  • 方法找不到
    • 方法是 private/protected → Frida 无视修饰符,直接 use
    • 参数类型不匹配(如 int 写成 Integer)→ 严格按 jadx 签名
  • 注入失败:device not found
    • 手机未开 USB 调试
    • frida-server 没运行
    • 电脑 / 手机 Frida 版本不匹配
  • APP 崩溃 / 反调试
    • 检测到 Frida → 用 frida-obfuscator 加密脚本
    • 检测 root → 用 Magisk 隐藏 root

  • 九、扩展:Native 层 Hook(so 库)

    如果加密在 libxxx.so 里,用 Frida 直接 Hook 原生函数:

    // Hook libnative.so 里的 Java_com_example_crypto_encrypt
    var lib=Module.load("libnative.so");
    var encrypt=lib.findExportByName("Java_com_example_crypto_encrypt");

    Interceptor.attach(encrypt, {
    onEnter: function (args) {
    console.log("Native 加密参数:" + args[0].readCString());
    },
    onLeave: function (retval) {
    console.log("Native 返回:" + retval.readCString());
    retval.writeUtf8String("NATIVE_HACK");
    }
    });


    十、总结

    这次实战完整走了 Frida Hook Java 方法 的全流程:

  • 环境:电脑 Frida + 手机 frida-server
  • 分析:jadx 找类和方法
  • 脚本:Java.perform → use → implementation
  • 注入:frida -U -n 包名 -l 脚本.js
  • 效果:拦截参数、改返回值、打印调用栈
  • 赞(0)
    未经允许不得转载:171主机测评 » APK Hook 实战
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址