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

如何通过Frida改写Android方法以打印调用堆栈追踪?

解决Frida Hook时打印堆栈追踪的错误问题

我来帮你搞定这个问题!你遇到的Error: Not allowed outside Java.perform() callback错误,核心原因是在implementation函数内部调用Java.use()时,虽然函数定义在Java.perform()里,但Frida的执行上下文可能出现了微妙的切换,导致这些调用不在安全的Java执行环境中。另外,你的代码还漏掉了调用原方法,这会破坏目标方法的原有逻辑,甚至导致应用崩溃。

修正方案1:提前获取Java类引用(推荐)

我们可以在Java.perform()的直接作用域内提前获取需要用到的Log、Exception和目标类的引用,然后在implementation函数中直接使用,这样既能避免上下文错误,也能提升代码效率:

setImmediate(function() {
    console.log("[*] Starting script");
    Java.perform(function () {
        // 提前在Java.perform内部获取所有需要的类引用
        const MyClass = Java.use("com.package.MyClass");
        const AndroidLog = Java.use("android.util.Log");
        const JavaException = Java.use("java.lang.Exception");

        // Hook目标方法
        MyClass.getUpdates.overload('boolean', 'java.lang.String', 'java.lang.String').implementation = function (v1, v2, v3) {
            // 打印参数
            console.log("v1: " + v1);
            console.log("v2: " + v2);
            console.log("v3: " + v3);
            
            // 生成并打印堆栈追踪
            const stackTrace = AndroidLog.getStackTraceString(JavaException.$new());
            console.log("\n[*] Call stack:");
            console.log(stackTrace);
            
            // 必须调用原方法,否则会中断原有业务逻辑
            return this.getUpdates(v1, v2, v3);
        };
    });
})

修正方案2:使用Frida原生API打印堆栈(更通用)

如果你不想依赖Android的Log类,还可以用Frida自带的Thread.backtrace()方法,它不需要额外的Java类依赖,兼容性更好:

setImmediate(function() {
    console.log("[*] Starting script");
    Java.perform(function () {
        const MyClass = Java.use("com.package.MyClass");

        MyClass.getUpdates.overload('boolean', 'java.lang.String', 'java.lang.String').implementation = function (v1, v2, v3) {
            console.log("v1: " + v1);
            console.log("v2: " + v2);
            console.log("v3: " + v3);
            
            // 使用Frida原生API生成堆栈
            console.log("\n[*] Call stack:");
            const stack = Thread.backtrace(this.context, Backtracer.ACCURATE)
                .map(DebugSymbol.fromAddress)
                .join("\n");
            console.log(stack);
            
            // 调用原方法
            return this.getUpdates(v1, v2, v3);
        };
    });
})

关键注意事项

  • 必须调用原方法:如果你的implementation函数没有return this.getUpdates(...),目标方法的原有逻辑会完全失效,大概率会导致应用出现异常甚至崩溃。
  • 重载匹配要准确:确保overload()中的参数类型和目标方法完全一致,否则Frida会找不到对应的方法,Hook失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:49:16