You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android平台使用Frida Stalker追踪Java函数的问题及可行性咨询

问题描述

我尝试使用Frida追踪Android应用中调用的所有Java函数,但遇到了一些问题:

  • 此前通过class.function.implementation = function(...parameters) {}的方式hook所有函数来追踪,但在中型应用中扩展性差,难以实施。
  • 了解到Frida的Stalker API可用于追踪Native函数,于是尝试了以下代码:
var threads = Process.enumerateThreadsSync();
threads.forEach(function (thread) {
    Stalker.follow(thread.id,{
        events: { call: true },
        onReceive: function (events) {
            var calls = Stalker.parse(events, { annotate: false });
            calls.forEach(function (event) {
                var location = event[0];
                var target = event[1];
                var locationName = DebugSymbol.fromAddress(location).name;
                var targetName = DebugSymbol.fromAddress(target).name;
                console.log(locationName + " " + targetName);
            });
        }
    });
});

但遇到两个问题:

  1. 应用启动后不久崩溃(怀疑是追踪了所有线程,包括Frida运行的线程);
  2. 没有Java方法日志被记录。

核心疑问:使用Frida的Stalker API通常无法追踪Java函数,还是我的方法存在疏漏?


解答

核心结论

Stalker API本身是针对Native层指令级别的追踪工具,默认无法直接捕获Java方法调用——因为Java方法的执行是由ART虚拟机通过Native代码调度的,Stalker只能看到Native层面的调用链,无法直接解析出上层Java方法的符号信息。你的问题既有使用方式的疏漏,也有对Stalker适用场景的误解。

问题分析与修复

1. 应用崩溃问题

你确实踩了全线程追踪的坑:Stalker会对目标线程的指令做动态插桩,追踪所有线程(包括Frida自身的注入线程、ART虚拟机的后台系统线程)会导致系统资源耗尽、线程死锁,直接触发应用崩溃。

修复方式:过滤线程范围,只追踪目标应用的业务线程,比如排除包含"frida"、"zygote"等关键字的系统/工具线程:

var threads = Process.enumerateThreadsSync();
threads.forEach(function (thread) {
    if (!thread.name.includes("frida") && !thread.name.includes("zygote")) {
        Stalker.follow(thread.id, {
            events: { call: true },
            bufferSize: 4 * 1024 * 1024, // 增大缓冲减少IO压力
            onReceive: function (events) {
                var calls = Stalker.parse(events, { annotate: false });
                calls.forEach(function (event) {
                    var location = event[0];
                    var target = event[1];
                    // 处理无法解析符号的情况
                    var locationName = DebugSymbol.fromAddress(location).name || `0x${location.toString(16)}`;
                    var targetName = DebugSymbol.fromAddress(target).name || `0x${target.toString(16)}`;
                    console.log(`${locationName} -> ${targetName}`);
                });
            },
            onError: function (reason) {
                console.log(`Stalker错误: ${reason}`);
            }
        });
    }
});

2. 无Java方法日志问题

Stalker捕获的是Native内存地址,DebugSymbol.fromAddress只能解析Native函数的符号(比如ART虚拟机的art::interpreter::Execute),而Java方法本身并没有对应的Native符号——它们的执行逻辑是在ART虚拟机内部调度的,所以自然打不出Java方法名。

正确追踪Java函数的方案

优先使用Frida的Java层API做范围过滤的hook,这是最高效且易用的方式,完全可以解决中型应用的扩展性问题:

Java.perform(() => {
    // 只hook目标应用包名下的类,避免无差别hook系统类
    const targetPackage = "com.your.app.package";
    const loadedClasses = Java.enumerateLoadedClassesSync();
    
    loadedClasses.forEach(className => {
        if (className.startsWith(targetPackage)) {
            try {
                const cls = Java.use(className);
                // 遍历类的所有方法
                cls.$methods.forEach(method => {
                    const methodName = method.name;
                    // 跳过构造方法或已有实现的hook(可选)
                    if (methodName !== "<init>") {
                        cls[methodName].implementation = function(...args) {
                            console.log(`[Java调用] ${className}.${methodName}`);
                            // 执行原方法并返回结果
                            return this[methodName](...args);
                        };
                    }
                });
            } catch (e) {
                // 跳过无法hook的类(比如抽象类、系统核心类)
                console.log(`跳过hook类: ${className}, 原因: ${e.message}`);
            }
        }
    });
});

如果确实需要结合Stalker追踪Java方法(比如要关联Native调用栈),需要额外解析ART虚拟机的参数:当Stalker捕获到art::Method::Invoke这类Native函数时,通过其参数拿到Java方法的指针,再调用Frida的Java.vm.getEnv()相关API解析出Java方法名,但这种方式实现复杂、性能开销大,仅适合特定场景。


内容的提问来源于stack exchange,提问作者philipp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 21:40:55