frida java端高级使用
第一个重点:frida动态加载第三方dex文件
注意:为什么需要动态加载第三方dex文件 因为我们可以将我们需要的工具函数打包到这个dex文件中 方便我们使用其中的工具函数 进行值的计算和返回校验,
这个dex文件中可以写任意的工具函数。
实现方式:
1.在android studio中编写我们的工具函数,然后进行编译打包,在目录下build\intermediates\javac\debug\classes\com\example\dynamicloaddex\HmacSHA256.class 找到我们打包的工具函数的class文件
2.在目录build\intermediates\javac\debug\classes下使用java命令jar -cvf HmacSHA256.jar com/example/dynamicloaddex/HmacSHA256.class 将class文件打包成jar包文件
3.使用sdk的dx文件将jar文件打包成dex文件
dx文件在目录:Android/Sdk/build-tools/30.0.2/dx.bat 下
使用命令 dx.bat --dex --output=HmacSHA256.dex HmacSHA256.jar
这里需要注意一个坑:需要将dx.bat 的最后一句修改为 call "%java_exe%" %javaOpts% --class-path="%frameworkdir%" -jar "%jarpath%" %params%
第二个重点:frida hook 静态函数和非静态函数
hook 静态函数:
var FridaActivity2Path = "com.example.androiddemo.Activity.FridaActivity2";
var FridaActivity2 = Java.use(FridaActivity2Path);
FridaActivity2.setStatic_bool_var(); // setStatic_bool_var()为FridaActivity2类下的静态函数
hook 非静态函数:
var FridaActivity2Path = "com.example.androiddemo.Activity.FridaActivity2"; // frida hook非静态函数 需要主动调用 使用choose api接口
Java.choose(FridaActivity2Path, {
onMatch:function(ins){
ins.setBool_var(); // 调用非静态函数 setBool_var()为FridaActivity2类下的非静态函数
},
onComplete: function(){}
})
第三个重点:frida hook 静态参数和非静态参数以及当参数名和函数名同名时应该怎么处理
hook 静态参数
var FridaActivity3Path = "com.example.androiddemo.Activity.FridaActivity3";
var FridaActivity3 = Java.use(FridaActivity3Path);
FridaActivity3.static_bool_var.value = true; // frida hook 静态参数
hook 非静态参数
var FridaActivity3Path = "com.example.androiddemo.Activity.FridaActivity3";
Java.choose(FridaActivity3Path, {
onMatch: function(ins){
ins.bool_var.value = true; // frida hook非静态函数
ins._same_name_bool_var.value = true; // frida hook 参数和函数名 同名
},
onComplete: function(){}
})
第四个重点:frida hook 内部类
hook 内部类
var InnerClassesPath = "com.example.androiddemo.Activity.FridaActivity4$InnerClasses"; // InnerClasses 为FridaActivity4的内部类
var InnerClasses = Java.use(InnerClassesPath);
var all_methods = InnerClasses.class.getDeclaredMethods(); // getDeclaredMethods函数的作用是获取一个类下面的所以方法
for (var i = 0; i < all_methods.length; i++) {
var method = (all_methods[i]);
var methodStr = method.toString();
var substring = methodStr.substr(methodStr.indexOf(InnerClassesPath) + InnerClassesPath.length + 1);
var methodname = substring.substr(0, substring.indexOf("("));
console.log(methodname);
InnerClasses[methodname].implementation = function () {
console.log("hook_mul_function:", this);
return true;
}
}
第五个重点:frida hook java动态加载的dex
hook java端动态加载的dex
var FridaActivity5 = Java.use("com.example.androiddemo.Activity.FridaActivity5");
Java.choose("com.example.androiddemo.Activity.FridaActivity5", {
onMatch: function (instance) {
console.log(instance.getDynamicDexCheck().$className); // 获取动态加载的dex的类名 获取了类目就可以操作类
}, onComplete: function () {
}
});
//hook 动态加载的dex enumerateClassLoaders函数的作用是获取当前环境下的所有类加载器
Java.enumerateClassLoaders({
onMatch: function (loader) {
try {
if (loader.findClass("com.example.androiddemo.Dynamic.DynamicCheck")) {
console.log(loader);
Java.classFactory.loader = loader; //切换classloader
}
} catch (error) {
}
}, onComplete: function () {
}
});
// 切换当前类加载器后 就可以操作当前类 hook类下面的方法
var DynamicCheck = Java.use("com.example.androiddemo.Dynamic.DynamicCheck");
console.log(DynamicCheck);
DynamicCheck.check.implementation = function () {
console.log("DynamicCheck.check");
return true;
}
第六个重点:frida hook 类下所有函数
frida hook 类下所有函数
// enumerateLoadedClasses函数的作用是 获取当前环境下加载的所有类 有两个参数
Java.enumerateLoadedClasses({
onMatch: function (name, handle) {
// 参数name 是类的名字
if (name.indexOf("com.example.androiddemo.Activity.Frida6") >= 0) {
console.log(name);
var fridaclass6 = Java.use(name); // 获取到类后就可以进行hook操作
fridaclass6.check.implementation = function () {
console.log("frida 6 check:", this);
return true;
};
}
}, onComplete: function () {
}
})