跳转至

frida 高级 api 食用方法(一)

1. 前提准备

本文章是对看雪教程的简单总结,可快速了解 frida hook api 的使用方法

这里提供下参考文档及其注意事项

2. frida 的使用

2.1. hook 一个 Java 层函数

这是登录方法,需要 hook a 函数得到对应 obj 参数时的结果与输入的 obj2 参数一致。

image-20220427214916572

对应的 frida 代码如下:

image-20220427183239700

2.2. 修改函数返回值或参数

搜索 check Failed 后查看用例或从上一步点击进入都可以。需要将 a 函数返回固定值 R4jsLL... 即可。

image-20220427215816871

对应的 frida 代码如下:

image-20220427183319070

2.3. 调用静态函数和非静态函数

需要 static_bool_varbool_vartrue 即可,即调用对应参数赋值的两个方法即可。

image-20220427220310198

对应的 frida 代码如下:

image-20220427183341127

2.4. 设置成员变量

同样,设置 static_bool_var, bool_varsame_name_bool_vartrue 即可走下一逻辑。

image-20220427220718804

设置和函数名相同的成员变量,其 frida 代码如下:

image-20220427183433469

2.5. hook 内部类,枚举类的函数

不再解释,将涉及的内部类方法全都 hook 返回固定值 true 即可。

image-20220427221127895

对应的 frida 代码如下:注意 $ 符号

image-20220427183608385

2.6. 查找接口,hook 动态加载 dex

frida 不能直接用 use 来获取接口,需要先找到对应的接口名。

image-20220427221941771

image-20220427222008744

# 找到接口对应名称的代码如下
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 () {

            }
        })
    })
}

找到接口名后即可 hookfrida 代码如下:

image-20220427183628573

2.7. 枚举 class

需要将多个 classcheck 方法 hook 返回固定值 true

image-20220427223135628

对应的 frida 代码如下:

image-20220427183643121

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);

评论

回到页面顶部