frida 高级 api 食用方法(一)
1. 前提准备
本文章是对看雪教程的简单总结,可快速了解 frida hook api
的使用方法
这里提供下参考文档及其注意事项
2. frida 的使用
2.1. hook 一个 Java 层函数
这是登录方法,需要 hook a
函数得到对应 obj
参数时的结果与输入的 obj2
参数一致。
对应的 frida
代码如下:
2.2. 修改函数返回值或参数
搜索 check Failed
后查看用例或从上一步点击进入都可以。需要将 a
函数返回固定值 R4jsLL...
即可。
对应的 frida
代码如下:
2.3. 调用静态函数和非静态函数
需要 static_bool_var
和 bool_var
为 true
即可,即调用对应参数赋值的两个方法即可。
对应的 frida
代码如下:
2.4. 设置成员变量
同样,设置 static_bool_var
, bool_var
和 same_name_bool_var
为 true
即可走下一逻辑。
设置和函数名相同的成员变量,其 frida
代码如下:
2.5. hook 内部类,枚举类的函数
不再解释,将涉及的内部类方法全都 hook
返回固定值 true
即可。
对应的 frida
代码如下:注意 $
符号
2.6. 查找接口,hook 动态加载 dex
frida
不能直接用 use
来获取接口,需要先找到对应的接口名。
| # 找到接口对应名称的代码如下:
function hook_dyn_dex() {
Java.perform(function (){
var FridaActivity5 = Java.use("com.example.androiddemo.Activity.FridaActivity5");
Java.choose("com.example.androiddemo.Activity.FridaActivity5", {
onMatch: function (instance) {
console.log(instance.getDynamicDexCheck().$className);
}, onComplete: function () {
}
})
})
}
|
找到接口名后即可 hook
,frida
代码如下:
2.7. 枚举 class
需要将多个 class
的 check
方法 hook
返回固定值 true
。
对应的 frida
代码如下:
3. 总结及补充
这里补上对应的 frida js hook
脚本:
| function hook_java() {
Java.perform(function () {
var LoginActivity = Java.use("com.example.androiddemo.Activity.LoginActivity");
console.log(LoginActivity);
LoginActivity.a.overload('java.lang.String', 'java.lang.String').implementation = function (str, str2) {
var result = this.a(str, str2); //调用原来的函数
console.log("LoginActivity.a:", str, str2, result);
return result;
};
var FridaActivity1 = Java.use("com.example.androiddemo.Activity.FridaActivity1");
console.log(FridaActivity1);
//hook函数,没有调用原来的函数,直接返回值
FridaActivity1.a.implementation = function (barr) {
console.log("FridaActivity1.a");
return "R4jSLLLLLLLLLLOrLE7/5B+Z6fsl65yj6BgC6YWz66gO6g2t65Pk6a+P65NK44NNROl0wNOLLLL=";
};
console.log("hook_java");
});
}
function call_FridaActivity2() {
//主动调用函数
Java.perform(function () {
var FridaActivity2 = Java.use("com.example.androiddemo.Activity.FridaActivity2");
FridaActivity2.setStatic_bool_var(); //调用静态函数
Java.choose("com.example.androiddemo.Activity.FridaActivity2", {
onMatch: function (instance) {
instance.setBool_var();
},
onComplete: function () {
}
});
});
}
function call_FridaActivity3() {
Java.perform(function () {
var FridaActivity3 = Java.use("com.example.androiddemo.Activity.FridaActivity3");
FridaActivity3.static_bool_var.value = true; //设置静态成员变量
console.log(FridaActivity3.static_bool_var.value);
Java.choose("com.example.androiddemo.Activity.FridaActivity3", {
onMatch: function (instance) {
//设置非静态成员变量的值
instance.bool_var.value = true;
//设置有相同函数名的成员变量的值
instance._same_name_bool_var.value = true;
console.log(instance.bool_var.value, instance._same_name_bool_var.value);
},
onComplete: function () {
}
});
});
}
function hook_InnerClasses() {
Java.perform(function () {
//hook内部类
var InnerClasses = Java.use("com.example.androiddemo.Activity.FridaActivity4$InnerClasses");
console.log(InnerClasses);
InnerClasses.check1.implementation = function () {
return true;
};
InnerClasses.check2.implementation = function () {
return true;
};
InnerClasses.check3.implementation = function () {
return true;
};
InnerClasses.check4.implementation = function () {
return true;
};
InnerClasses.check5.implementation = function () {
return true;
};
InnerClasses.check6.implementation = function () {
return true;
};
});
}
function hook_mul_function() {
Java.perform(function () {
//hook 类的多个函数
var class_name = "com.example.androiddemo.Activity.FridaActivity4$InnerClasses";
var InnerClasses = Java.use(class_name);
var all_methods = InnerClasses.class.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(class_name) + class_name.length + 1);
var methodname = substring.substr(0, substring.indexOf("("));
console.log(methodname);
InnerClasses[methodname].implementation = function () {
console.log("hook_mul_function:", this);
return true;
}
}
});
}
function hook_dyn_dex() {
Java.perform(function () {
var FridaActivity5 = Java.use("com.example.androiddemo.Activity.FridaActivity5");
Java.choose("com.example.androiddemo.Activity.FridaActivity5", {
onMatch: function (instance) {
console.log(instance.getDynamicDexCheck().$className);
}, onComplete: function () {
}
});
//hook 动态加载的dex
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 () {
}
});
var DynamicCheck = Java.use("com.example.androiddemo.Dynamic.DynamicCheck");
console.log(DynamicCheck);
DynamicCheck.check.implementation = function () {
console.log("DynamicCheck.check");
return true;
}
});
}
function hook_FridaActivity6() {
Java.perform(function () {
var Frida6Class0 = Java.use("com.example.androiddemo.Activity.Frida6.Frida6Class0");
Frida6Class0.check.implementation = function () {
return true;
};
var Frida6Class1 = Java.use("com.example.androiddemo.Activity.Frida6.Frida6Class1");
Frida6Class1.check.implementation = function () {
return true;
};
var Frida6Class2 = Java.use("com.example.androiddemo.Activity.Frida6.Frida6Class2");
Frida6Class2.check.implementation = function () {
return true;
};
});
}
function hook_mul_class() {
Java.perform(function () {
Java.enumerateLoadedClasses({
onMatch: function (name, handle) {
if (name.indexOf("com.example.androiddemo.Activity.Frida6") >= 0) {
console.log(name);
var fridaclass6 = Java.use(name);
fridaclass6.check.implementation = function () {
console.log("frida 6 check:", this);
return true;
};
}
}, onComplete: function () {
}
})
});
}
function main() {
hook_java();
}
setImmediate(main);
|