如何通过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
相关产品推荐
相关产品推荐

