标题:frida:hook所有方法
在Android逆向工程中,Frida是一个强大的动态代码插桩工具,能够帮助我们实时hook和调试目标应用的方法。本文将通过一个实际案例,探讨在使用Frida Hook测试应用中的Utils类时遇到的一个JavaScript作用域问题,并提供解决方案。
首先,让我们来看看这段用于Hook Utils类所有方法的Frida脚本:
Java.perform(function() {var utils = Java.use("con.xiaojianbang.hook.Utils");var methods = utils.class.getDeclaredMethods();for (let k = 0; k < methods.length; k++) {var methodName = methods[k].getName();var overloadArr = utils[methodName].overloads;console.log("fun : ", methodName);for (let i = 0; i < overloadArr.length; i++) {overloadArr[i].implementation = function() {var params = "";for (let j = 0; j < arguments.length; j++) {params += arguments[j] + "";}console.log("utils." + methodName + " is called! params is : ", params);return this[methodName].apply(this, arguments);};}}
});test();
注入这段代码后,我们成功获取到了Utils类中的各个方法名,但当尝试在原始方法的基础上进行Hook并调用时,却发现无论调用哪个方法,其参数总是被传递给verifyStoragePermissions
方法。经过排查,发现问题并非出在Frida框架本身,而是JavaScript中关于变量作用域的理解与运用。
关键在于代码第6行的var
关键字,这里应当使用let
替代。在JavaScript中,var
声明的变量会在其所在函数作用域内有效,而在for循环内部使用var
声明的变量会因循环迭代导致变量值在循环体外部共享同一个作用域。因此,在上述代码中,每次循环迭代时methodName
的值会被更新,但在implementation
回调函数中引用的却是最后一次循环结束后的methodName
值。
将var
修改为let
后,代码如下:
for (let k = 0; k < methods.length; k++) {// ...
}// 在for循环内部及实施Hook的匿名函数中均使用let声明变量
for (let i = 0; i < overloadArr.length; i++) {overloadArr[i].implementation = function() {// ...};
}
这样修改后,methodName
和params
等变量就会在各自的for循环块内拥有独立的作用域,从而保证了在回调函数中正确地引用到相应方法的信息。最终,所有Utils类的方法都能被正确Hook并输出调用参数。通过这次实践,我们再次认识到在JavaScript编程中准确理解作用域规则的重要性,这对于利用Frida等工具进行动态调试和Hook至关重要。