https://github.com/aprz512/Android-Crack/blob/master/practice/p14/frida_example_1.1.apk
首先使用jadx打开apk,看看大致的信息:
有两个值得注意的地方。
安装app,看看是什么样子:
这里我们打开对应界面的反编译代码:
发现,登录失败是走到了中间的 else if 逻辑里面,我们需要想办法让逻辑走到最后的 else 里面才行。
LoginActivity.a 方法返回了一个字符串,obj2 是第二个输入框的字符串。
所以这里是使用了第一个输入框的字符串做了一些变化,然后与第二个输入框的字符串比较。
那么我们可以直接 hook a方法,让它固定返回 bbb,我们在第二个输入框里面输入 bbb 就可以了,代码如下:
function login() {
Java.perform(function () {
const loginActivityClass = Java.use('com.example.androiddemo.Activity.LoginActivity');
loginActivityClass.a.overload('java.lang.String', 'java.lang.String').implementation = function(s1, s2) {
console.log("s1 = ", s1);
console.log("s2 = ", s2);
return Java.use('java.lang.String').$new('bbb');
}
});
}
看反编译代码:
继承了一个类:
就封装了一个点击逻辑,没啥别的。
核心逻辑在 FridaActivity1 的 onCheck 方法里面,我们得让 a(b("请输入密码:"))
这个玩意的结果返回后面那一长串字符即可。
代码如下:
function frida1() {
Java.perform(function () {
Java.use("com.example.androiddemo.Activity.FridaActivity1").a.implementation = function (bArr) {
return Java.use('java.lang.String').$new("R4jSLLLLLLLLLLOrLE7/5B+Z6fsl65yj6BgC6YWz66gO6g2t65Pk6a+P65NK44NNROl0wNOLLLL=");
}
})
}
需要我们改变两个变量的值即可,代码如下:
function frida2() {
Java.perform(function () {
const fridaAct2Handler = Java.use("com.example.androiddemo.Activity.FridaActivity2")
fridaAct2Handler.static_bool_var.value = true;
Java.choose('com.example.androiddemo.Activity.FridaActivity2', {
onMatch(instance) {
instance.bool_var.value = true;
}, onComplete() { }
})
})
}
依然是改变3个变量的值。嗯?!!看来上一关用了非正规的解法,上一关考研的是方法的调用,那这一关就不贴代码了,和上一贯差不过。
需要我们hook所有内部类的方法。
一般情况下,可能会直接写 6 个 hook函数,但是其实可以使用反射加循环来完成。
代码如下:
function frida4() {
Java.perform(function () {
var className = 'com.example.androiddemo.Activity.FridaActivity4$InnerClasses'
var innerClassHandler = Java.use(className);
var innerClass = innerClassHandler.class;
var allMethods = innerClass.getDeclaredMethods();
for (var i = 0; i < allMethods.length; i++) {
var method = allMethods[i];
var fullMethodName = method.toString();
var tempName = fullMethodName.substr(fullMethodName.indexOf(className) + className.length + 1);
var methodName = tempName.substr(0, tempName.indexOf("("));
innerClassHandler[methodName].implementation = function () { return true };
}
})
}
去插件里面加载了一个类,我们需要 hook 这个类的方法。
frida api 文档里面特别说明了,使用 Java.use 来 load 类的时候,可以指定 loader:
Uses the app’s class loader by default, but you may customize this by assigning a different loader instance to
Java.classFactory.loader
.
我们先找下有哪些 loader,然后尝试用 loader 来找这个类:
function frida5() {
Java.perform(function () {
Java.enumerateClassLoaders({
onMatch: function (loader) {
try {
if (loader.findClass("com.example.androiddemo.Dynamic.DynamicCheck")) {
console.log("Successfully found loader")
Java.classFactory.loader = loader;
}
} catch (error) {
console.log("find error:" + error)
}
}, onComplete: function () { }
})
var DynamicCheck = Java.use("com.example.androiddemo.Dynamic.DynamicCheck");
console.log(DynamicCheck);
DynamicCheck.check.implementation = function () { return true };
})
}
需要 hook 3个类的 check 方法,同样的,我们写个统一的代码,使用类枚举:
function frida6() {
Java.perform(function () {
// 注意这里有优化,因为Frida6Class0 固定返回了 false,所以导致 Frida6Class1 没有被加载,所以还是一个个的写比较好
Java.enumerateLoadedClasses({
onMatch: function (name, handle) {
// console.log("found class = " + name);
if (name.indexOf("com.example.androiddemo.Activity.Frida6") >= 0) {
console.log("found class = " + name);
Java.use(name).check.implementation = function () { return true }
}
}, onComplete: function () { }
})
})
}