六层锁机分析

本章来通过一个案例更深层次的去了解frida,在各种情境下怎么去修改函数的返回值

先使用objection大致了解一下apk
objection附加到app
objection -g com.example.androiddemo explore
先看一下它的activity

- 这个Activity都能直接跳过登陆界面跳过去,这种直接能跳过登陆界面的在现在的app上基本都不存在了。
接下来开始按正常流程开始分析
登陆

- 点击
SIGN IN
按钮会有一个Login failed的Toast
接下来用jadx打开apk搜索这个字符串

进入

- 这里调用
a方法
传入了两个相同的obj然后将返回的结果与obj2作比较 - 接下来查看这个两个str参数的重载
a方法
- hook这个a方法拿到返回的结果输入比较一下
写hook脚本拿到a()的返回结果
function main(){
Java.perform(function(){
Java.use("com.example.androiddemo.Activity.LoginActivity").a.overload('java.lang.String', 'java.lang.String').implementation = function(x, y){
var result = this.a(x, y);
console.log("x, y, result", x, y, result);
return result;
}
})
}
setImmediate(main)

将result的值粘贴进去试一下(使用
input
命令也可以粘贴进去)


第一关

- 点击屏幕上的按钮有Check Failed的弹窗,跟前面一样搜索这个弹窗

- 发现这里有个
CheckSuccess()
按X查找它的用例

看第一关的用例

- 这里只要修改
a方法
的返回值就可以通过了

- 用这个脚本hook这个类中的
a方法
让返回值等于R4jSLLLLLLLLLLOrLE7/5B+Z6fsl65yj6BgC6YWz66gO6g2t65Pk6a+P65NK44NNROl0wNOLLLL=
就通过了
第二关


第二关只需要这两个返回值为
true
就通过了这两个方法一个是静态一个是动态
静态直接调用就可以了
动态需要找到实例才能调用

- 写完直接保存一下,或者重新运行一下。这样就通过了
第三关

修改这三个变量为
true
就通过第一个变量为静态布尔类型
第二个变量为动态布尔类型
第三个为同名布尔变量
脚本
function third(){
Java.perform(function(){
Java.use("com.example.androiddemo.Activity.FridaActivity3").static_bool_var.value = true;
Java.choose("com.example.androiddemo.Activity.FridaActivity3", {
onMatch:function(instance){
console.log("found instance: ", instance);
instance.bool_var.value = true;
instance._same_name_bool_var.value = true;
}, onComplete:function(){}
})
})
}
- 注意修改同名变量的时候要在变量名前面加上下划线,不然会修改失败
第四关


- 这里我们看怎么修改静态内部类中静态函数的返回值为
true
脚本
function fourth(){
Java.perform(function(){
Java.use("com.example.androiddemo.Activity.FridaActivity4$InnerClasses").check1.implementation = function(){return true};
Java.use("com.example.androiddemo.Activity.FridaActivity4$InnerClasses").check2.implementation = function(){return true};
Java.use("com.example.androiddemo.Activity.FridaActivity4$InnerClasses").check3.implementation = function(){return true};
Java.use("com.example.androiddemo.Activity.FridaActivity4$InnerClasses").check4.implementation = function(){return true};
Java.use("com.example.androiddemo.Activity.FridaActivity4$InnerClasses").check5.implementation = function(){return true};
Java.use("com.example.androiddemo.Activity.FridaActivity4$InnerClasses").check6.implementation = function(){return true};
})
}
这样我们就可以通过验证进入下一关
但是这里有一个点需要注意一下
怎么准确的拿到这个类名:
可以通过
objection
去附加然后搜索拿到准确的类名另外就是像这种需要修改多个返回值的,一个一个修改如果量太多是比较麻烦的。所以可以通过java的反射来枚举所有的方法去修改(反射机制允许在运行时动态获取和使用类的信息,包括类的字段、方法、构造函数等)
通过枚举的方式批量修改返回值脚本
function fourth_2() {
Java.perform(function () {
var innerClass = Java.use("com.example.androiddemo.Activity.FridaActivity4$InnerClasses");
// 获取内部类的所有方法
var methods = innerClass.class.getDeclaredMethods();
// 遍历方法数组
for (var i = 0; i < methods.length; i++) {
var methodName = methods[i].getName();
var finalMethodString = methodName.toString();
// console.log(finalMethodString);
// hook修改返回值
innerClass[finalMethodString].implementation = function(){return true};
}
});
}
第五关
第五关的代码使用jadx反编译失败了

可以换GDA编译试试

反编译ok,可以看到它加载了
DynamicPlugin.dex
文件中的com.example.androiddemo.Dynamic.DynamicCheck
类但是我们在这里找不到
chech()
的实现,解压apk找一下这个文件- 找到之后我们可以来hook这个
check()
- 找到之后我们可以来hook这个
第五关有点奇怪,试了几种方法都找不到这个类:
enumerateClassLoaders
Java.choose
加载外部dex再进行hook
这个dex文件也在

function fifth(){
Java.perform(function(){
// Java.use("com.example.androiddemo.Dynamic.DynamicCheck").check.implementation = function(){return true};
Java.enumerateClassLoaders({
onMatch:function(loader){
try {
if(loader.loadClass("com.example.androiddemo.Dynamic.DynamicCheck")){
Java.classFactory.loader = loader;
var b = Java.use(loader);
console.log(b);
}
} catch (error) {
console.log("loadClass error: "+error)
}
try {
if(loader.findClass("com.example.androiddemo.Dynamic.DynamicCheck")){
console.log("Succefully found loader!",loader);
Java.classFactory.loader = loader;
}
} catch (error) {
console.log("found error "+error)
}
},
onComplete:function(){"enum completed fifth!"}
})
})
}
function fifth_1() {
Java.perform(function () {
Java.choose("com.example.androiddemo.Dynamic.DynamicCheck", {
onMatch: function (instance) {
console.log("Found instance:", instance);
try {
instance.check.implementation = function () {
console.log("DynamicCheck.check() is hooked!");
return true;
};
} catch (error) {
console.log("Error:", error);
}
},
onComplete: function () {
console.log("Enumeration completed!");
}
});
});
}
- 先记录下来后续再搞
- 类在文件中但是加载不上
报错
Error: java.lang.ClassNotFoundException: Didn't find class "com.example.androiddemo.Dynamic.DynamicCheck" on path: DexPathList[[zip file "/data/app/com.example.androiddemo-1/base.apk"],nativeLibraryDirectories=[/data/app/com.example.androiddemo-1/lib/arm64, /data/app/com.example.androiddemo-1/base.apk!/lib/arm64-v8a, /system/lib64, /vendor/lib64]]
at frida/node_modules/frida-java-bridge/lib/env.js:122
at ensureClass (frida/node_modules/frida-java-bridge/lib/class-factory.js:380)
at frida/node_modules/frida-java-bridge/lib/class-factory.js:102
at /lesson6.js:158
at frida/node_modules/frida-java-bridge/lib/vm.js:11
at frida/node_modules/frida-java-bridge/index.js:279
at searchClass (/lesson6.js:159)
at frida/runtime/core.js:55
- 报错提示在
/data/app/com.example.androiddemo-1/base.apk
下找不到类名 - 我们dex的类名是在
/data/data/com.example.androiddemo/files/DynamicPlugin.dex
文件中
尝试使用objection搜索

- 只能找到接口类名,找不到
check()
的实现类名
把pixel XL从7.1刷到了8.1也还是一样
- 暂时先放下,回头有时间可以再试试其它系统或者frida版本
- 这个应该是环境的问题,因为类名只要加载了使用
Java.use
肯定是可以hook到的,但是现在就是没有加载上哪里都找不到
第六关


- 还是修改这几个返回值为
true
直接通过java.use
修改就可以
function sixth(){
Java.perform(function(){
Java.use("com.example.androiddemo.Activity.Frida6.Frida6Class0").check.implementation = function(){return true};
Java.use("com.example.androiddemo.Activity.Frida6.Frida6Class1").check.implementation = function(){return true};
Java.use("com.example.androiddemo.Activity.Frida6.Frida6Class2").check.implementation = function(){return true};
})
}
同样的我们也可以把这个脚本修改为枚举的方式,方便批量修改
枚举HOOK脚本
Java.perform(function(){
Java.enumerateLoadedClasses({
onMatch:function(name, handle){
if(name.toString().indexOf("com.example.androiddemo.Activity.Frida6") >= 0){
// console.log("name", name);
Java.use(name).check.implementation = function(){return true}
}
},onComplete(){}
})
})
最后第七关没有东西

附件:
hook脚本
- 标题: 六层锁机分析
- 作者: xiaoeryu
- 创建于 : 2023-11-22 13:37:50
- 更新于 : 2023-11-25 10:15:09
- 链接: https://github.com/xiaoeryu/2023/11/22/六层锁机分析/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。