首页 > 其他分享 >常用frida hook

常用frida hook

时间:2022-12-01 15:12:56浏览次数:44  
标签:function 常用 Java log use console hook var frida

frida hook

1、hook system.loadLibrary调用的so文件

function HookApp(str){
    Java.perform(function () {
        var Class = Java.use('com.App.name');
        var Method = "getString2";
        var result = Class[Method](str);
        console.log(result);
    })
}
setImmediate(HookApp);

2、hook 函数入参和结果

function hook_Method() {
    Java.perform(function () {
        var Class = Java.use('com.App.name');
        var Method = "a";
        # overload参数类型和个数
        Class[Method].overload('android.content.Context', 'java.lang.String'
        ).implementation = function () {
            var result = this[Method]['apply'](this, arguments);
            console.log('----------------------');
            console.log('arg1:' + arguments[0]);
            console.log('arg2:' + arguments[1]);
            console.log('result:' + result);
            console.log('----------------------');
            return result;
        }
    })
}
setImmediate(hook_Method);

3、hook类的构造函数

function main() {
    Java.perform(function () {
        Java.use("com.App.name").$init.overload("java.lang.String", "java.lang.String").implementation =
            function (args1, args2) {
                // 调用原函数
                var result = this.$init(args1, args2);
                // 打印参数
                console.log("args1, args12: ", args1, args2);
                return result;
            };
    });
}

setImmediate(main);

4、hook修改类/实例参数

function main() {
    Java.perform(function () {
        Java.choose("com.App.name", {
            onMatch: function (instance) {
                console.log("instance.mProjectId", instance.args1.value);
                console.log("instance.mUrlScheme", instance.args2.value);
                instance.args1.value = "args1";
                instance.args2.value = "args2";
            },
            onComplete: function () {
            },
        });
    });
}

setImmediate(main);

5、构造数组

function main() {
    Java.perform(function () {
        // 构造byte数组
        var byteArray = Java.array("byte", [0x46, 0x72, 0x69, 0x64, 0x61]);
        // 输出为: Frida
        console.log(Java.use("java.lang.String").$new(byteArray));

        // 构造char数组
        var charArray = Java.array("char", ["F", "r", "i", "d", "a"]);
        console.log(Java.use("java.lang.String").$new(charArray));
    });
}

setImmediate(main);

6、静态函数主动调用

function main() {
    Java.perform(function () {
        // setWebContentsDebuggingEnabled 需要在主线程调用
        Java.scheduleOnMainThread(function () {
            console.log("isMainThread", Java.isMainThread());
            // 主动触发静态函数调用, 允许WebView调试
            Java.use("android.webkit.WebView").setWebContentsDebuggingEnabled(true);
        });
    });
}

setImmediate(main);

7、动态函数主动调用

function main() {
    Java.perform(function () {
        Java.choose("com.App.name", {
            onMatch: function (instance) {
                // 主动触发动态函数调用
                console.log("instance.isDebugEnabled: ", instance.isDebugEnabled());
                console.log("instance.getChannel: ", instance.getChannel());
            },
            onComplete: function () {
            },
        });
    });
}

8、定义一个类

function main() {
    Java.perform(function () {
        var TestRunnable = Java.registerClass({
            name: "com.example.TestRunnable",
            // 实现接口
            implements: [Java.use("java.lang.Runnable")],
            // 成员变量
            fields: {
                testFields: "java.lang.String",
            },
            methods: {
                // 构造函数
                $init: [
                    {
                        returnType: "void",
                        argumentTypes: ["java.lang.String"],
                        implementation: function (testFields) {
                            // 调用父类构造函数
                            this.$super.$init();
                            // 给成员变量赋值
                            this.testFields.value = testFields;
                            console.log("$init: ", this.testFields.value);
                        },
                    },
                ],
                // 方法
                run: [
                    {
                        returnType: "void",
                        implementation: function () {
                            console.log(
                                "testFields: ",
                                this.testFields.value
                            );
                        },
                    },
                ],
            },
        });

        TestRunnable.$new("simple test").run();
    });
}

setImmediate(main);

9、打印函数调用堆栈

function main() {
    Java.perform(function () {
        Java.use(
            "com.growingio.android.sdk.autotrack.click.ViewClickInjector"
        ).viewOnClick.overload(
            "android.view.View$OnClickListener",
            "android.view.View"
        ).implementation = function (listener, view) {
            // 打印当前调用堆栈信息
            console.log(
                Java.use("android.util.Log").getStackTraceString(
                    Java.use("java.lang.Throwable").$new()
                )
            );
            return this.viewOnClick(listener, view);
        };
    });
}

setImmediate(main);

10、枚举classLoader

function main() {
    Java.perform(function () {
        Java.enumerateClassLoaders({
            onMatch: function (loader) {
                try {
                    // 判断该loader中是否存在我们需要hook的类
                    if (loader.findClass("com.growingio.android.sdk.CoreConfiguration")) {
                        console.log("found loader:", loader);
                        Java.classFactory.loader = loader;
                    }
                } catch (error) {
                    console.log("found error: ", error);
                    console.log("failed loader: ", loader);
                }
            },
            onComplete: function () {
                console.log("enum completed!");
            },
        });
        console.log(
            Java.use("com.growingio.android.sdk.CoreConfiguration").$className
        );
    });
}

setImmediate(main);

11、枚举类

function main() {
    Java.perform(function () {
        Java.enumerateLoadedClasses({
            onMatch: function (name, handle) {
                // 判断是否是我们要查找的类
                if (name.toString() == "com.growingio.android.sdk.CoreConfiguration") {
                    console.log("name, handle", name, handle);
                    Java.use(name).isDebugEnabled.implementation = function () {
                        return true;
                    };
                }
            },
            onComplete: function () {
            },
        });
    });
}

setImmediate(main);

12、hook so 文件函数 - 导出符号

var native_func = Module.findExportByName("${so file name}", "${so export function name}");

Interceptor.attach(native_func, {
    // 函数开始
    onEnter: function (args) {},
    // 函数结束
    onLeave: function (return_val) {}
});

13、hook so 文件函数 - 偏移地址

var native_func_addr = Module.findBaseAddress("${so file name}");
var native_addr = native_func_addr.add(${so 函数偏移地址});

Interceptor.attach(native_addr, {
    // 函数开始
    onEnter: function (args) {
        // 读取 r0 的数据
        this.context.r0.readCString()
    },
    // 函数结束
    onLeave: function (return_val) {}
});

14、获取 android context

var currentApplication = Java.use('android.app.ActivityThread').currentApplication();
var context = currentApplication.getApplicationContext();

15、调用 JNIEnv 函数

// 获取 JNIEnv
var env = Java.vm.getEnv();
var jstring = env.newStringUtf('maple');

16、byte array to string

// 方法一
var JavaString = Java.use("java.lang.String");
JavaString.$new('byte array').toString();

// 方法二
var ByteString = Java.use("com.android.okhttp.okio.ByteString");
// 转成 hex 在转 string
ByteString.of('byte array').hex();

17、java 类型转换

// 使用 Java.cast 把 java byet 转成 java Object
var javaBytes = Java.use('java.lang.String').$new("aaaaa").getBytes();
var javaBytesClass = Java.cast(javaBytes, Java.use('java.lang.Object')).getClass();

// 使用 Java.array 把 js array 转成 java Object array
var params = [
    Java.use('java.lang.String').$new('str1'),
    Java.use('java.lang.String').$new('str2'),
    Java.use('java.lang.Boolean').$new(false),
    Java.use('java.lang.Integer').$new(0)
];
var ps = Java.array('Ljava.lang.Object;', params);

18、注册 java 类

Java.openClassFile('/data/local/tmp/androidAsync-2.2.1.dex').load();
const HttpServerRequestCallback = Java.use('com.koushikdutta.async.http.server.HttpServerRequestCallback');

// 构建一个默认请求
const RequestTestCallback = Java.registerClass({
    name: "RequestTestCallback",
    implements: [HttpServerRequestCallback],
    methods: {
        onRequest: function (request, response) {
            // 主动调用代码直接写这里
            response.send(JSON.stringify({
                "code": 0,
                "message": " 服务已经注册成功, 默认端口8181"
            }));
        }
    }
});

19、hook 动态 dex 切换 classLoader

// 方法一
var className = 'com.taobao.wireless.security.adapter.JNICLibrary';
Java.enumerateClassLoaders({
    onMatch: function (loader) {
        try {
            if (loader.findClass(className)) {
                Java.classFactory.loader = loader;
            }
        } catch (error) {}
    },
    onComplete: function () {}
})

// 方法二
var classApplication = Java.use('android.app.Application');
classApplication.onCreate.implementation = function () {
    Java.enumerateClassLoadersSync().forEach(function (loader) {
        try {
            if (loader.loadClass(className)) {
                Java.classFactory.loader = loader;
            }
        } catch (error) {}
    });
}

20、map 转 js json

function getMapData(mapSet) {
    try {
        var result = {};
        var key_set = mapSet.keySet();
        var it = key_set.iterator();
        while (it.hasNext()) {
            var key_str = it.next().toString();
            result[key_str] = mapSet.get(key_str).toString();
        }
        return result
    } catch (error) {
        return mapSet
    }
}

21、bytes to hex

function bytes2Hex(arrBytes){
    var str = "";
    for (var i = 0; i < arrBytes.length; i++) {
        var tmp;
        var num = arrBytes[i];
        if (num < 0) {
            //此处填坑,当byte因为符合位导致数值为负时候,需要对数据进行处理
            tmp = (255 + num + 1).toString(16);
        } else {
            tmp = num.toString(16);
        }
        if (tmp.length == 1) {
            tmp = "0" + tmp;
        }
        if(i>0){
            str += " "+tmp;
        }else{
            str += tmp;
        }
    }
    return str;
}

22、string to bytes

function string2Bytes(str) {
    var bytes = new Array();
    var len, c;
    len = str.length;
    for(var i = 0; i < len; i++) {
        c = str.charCodeAt(i);
        if(c >= 0x010000 && c <= 0x10FFFF) {
            bytes.push(((c >> 18) & 0x07) | 0xF0);
            bytes.push(((c >> 12) & 0x3F) | 0x80);
            bytes.push(((c >> 6) & 0x3F) | 0x80);
            bytes.push((c & 0x3F) | 0x80);
        } else if(c >= 0x000800 && c <= 0x00FFFF) {
            bytes.push(((c >> 12) & 0x0F) | 0xE0);
            bytes.push(((c >> 6) & 0x3F) | 0x80);
            bytes.push((c & 0x3F) | 0x80);
        } else if(c >= 0x000080 && c <= 0x0007FF) {
            bytes.push(((c >> 6) & 0x1F) | 0xC0);
            bytes.push((c & 0x3F) | 0x80);
        } else {
            bytes.push(c & 0xFF);
        }
    }
    return bytes;
}

23、bytes to string

function bytes2String(arr) {
    if(typeof arr === 'string') {
        return arr;
    }
    var str = '',
        _arr = arr;
    for(var i = 0; i < _arr.length; i++) {
        var one = _arr[i].toString(2),
            v = one.match(/^1+?(?=0)/);
        if(v && one.length == 8) {
            var bytesLength = v[0].length;
            var store = _arr[i].toString(2).slice(7 - bytesLength);
            for(var st = 1; st < bytesLength; st++) {
                store += _arr[st + i].toString(2).slice(2);
            }
            try {
                str += String.fromCharCode(parseInt(store, 2));
            } catch (error) {
                str += parseInt(store, 2).toString(); 
                console.log(error);
            }
            i += bytesLength - 1;
        } else {
            try {
                str += String.fromCharCode(_arr[i]);
            } catch (error) {
                str += parseInt(store, 2).toString(); 
                console.log(error);
            }
        }
    }
    return str;
}

24、bytes to base64

function hookLoggerAllMethod() {
    const cls = Java.use('com.virjar.sekiro.business.api.log.SekiroLogger');
    const mhd_array = cls.class.getDeclaredMethods();

    // hook 类所有方法 (所有重载方法也要hook)
    for (var i = 0; i < mhd_array.length; i++) {
        // 当前方法签名
        const mhd_cur = mhd_array[i];
        // 当前方法名
        const str_mhd_name = mhd_cur.getName();

        // 当前方法重载方法的个数
        const n_overload_cnt = cls[str_mhd_name].overloads.length;
        console.log('n_overload_cnt: ', n_overload_cnt);

        for (var index = 0; index < n_overload_cnt; index++) {
            cls[str_mhd_name].overloads[index].implementation = function () {
                // 参数个数
                var n_arg_cnt = arguments.length;
                for (var idx_arg = 0; idx_arg < n_arg_cnt; n_arg_cnt++) {
                    console.log(arguments[idx_arg]);
                }
                console.log(str_mhd_name + ' --- ' + n_arg_cnt);
                return this[str_mhd_name].apply(this, arguments);
            }
        }
    }
}

25、hook class 的所有方法

function hookLoggerAllMethod() {
    const cls = Java.use('com.virjar.sekiro.business.api.log.SekiroLogger');
    const mhd_array = cls.class.getDeclaredMethods();

    // hook 类所有方法 (所有重载方法也要hook)
    for (var i = 0; i < mhd_array.length; i++) {
        // 当前方法签名
        const mhd_cur = mhd_array[i];
        // 当前方法名
        const str_mhd_name = mhd_cur.getName();

        // 当前方法重载方法的个数
        const n_overload_cnt = cls[str_mhd_name].overloads.length;
        console.log('n_overload_cnt: ', n_overload_cnt);

        for (var index = 0; index < n_overload_cnt; index++) {
            cls[str_mhd_name].overloads[index].implementation = function () {
                // 参数个数
                var n_arg_cnt = arguments.length;
                for (var idx_arg = 0; idx_arg < n_arg_cnt; n_arg_cnt++) {
                    console.log(arguments[idx_arg]);
                }
                console.log(str_mhd_name + ' --- ' + n_arg_cnt);
                return this[str_mhd_name].apply(this, arguments);
            }
        }
    }
}

26、js sleep

function sleep(numberMillis) {
    var now = new Date();
    var exitTime = now.getTime() + numberMillis;
    while (true) {
        now = new Date();
        if (now.getTime() > exitTime)
            return;
    }
}

// 毫秒级别
sleep(1000)

27、hook 常见加密算法

Java.perform(function () {
    var ByteString = Java.use("com.android.okhttp.okio.ByteString");
    var MessageDigest = Java.use('java.security.MessageDigest');
    var StringClass = Java.use("java.lang.String");

    // hook md5
    md.getInstance.overload("java.lang.String").implementation = function (str) {
        return this.getInstance(str)
    }
    md.update.overload('[B').implementation = function (a) {
        var result = this.update(a);
        return result;
    }
    md.digest.overload().implementation = function () {
        var result = this.digest();
        return result;
    }

    // hook aes
    var secretKeySpec = Java.use('javax.crypto.spec.SecretKeySpec');
    var iv = Java.use("javax.crypto.spec.IvParameterSpec");
    var cipher = Java.use("javax.crypto.Cipher");
    // hook aes key
    secretKeySpec.$init.overload('[B', 'java.lang.String').implementation = function (a, b) {
        console.log("secretKeySpec.$init - UTF8密钥: " + StringClass.$new(a));
        console.log("secretKeySpec.$init - hex密钥 : " + ByteString.of(a).hex());
        console.log("secretKeySpec.$init - 算法类型: " + b);
        var result = this.$init(a, b);
        return result;
    }
    // hook aes 偏移
    iv.$init.overload('[B').implementation = function (a) {
        console.log("IvParameterSpec.$init - 向量偏移量utf8: ", StringClass.$new(a));
        console.log("IvParameterSpec.$init - 向量偏移量hex: ", bytes2Hex(a))
        var result = this.$init(a);
        return result;
    }
    // hook aes 加密模式
    cipher.getInstance.overload('java.lang.String').implementation = function (a) {
        console.log("cipher.getInstance - 加密模式、填充类型: ", a)
        var result = this.getInstance(a);
        return result;
    }
    cipher.doFinal.overload('[B').implementation = function (a) {
        console.log("Cipher.doFinal - 待加密字符串: ", bytes2Hex(a))
        var result = this.doFinal(a);
        console.log("Cipher.doFinal - 加密后字符串: ", bytes2Hex(result))
        return result;
    }
})

标签:function,常用,Java,log,use,console,hook,var,frida
From: https://www.cnblogs.com/angelyan/p/16941444.html

相关文章

  • Linux常用命令
    1命令分类用于实现某一类功能的指令或程序命令的执行依赖于解释器程序(例如:/bin/bash)内部命令:属于Shell解释器的一部分外部命令:独立于Shell解释器之外的程序文件2命令......
  • GIT 常用命令,常见问题
    全局设置用户信息Gitglobalsetupgitconfig--globaluser.name"xxx"gitconfig--globaluser.email"[email protected]" 创建新仓储 Createanewrepositorygi......
  • 常用表格联查系统WPS、表格函数使用
    1,使用表格化管理系统是更轻量的解决方案之一低人工成本、甚至免费使用表格自带的功能,就可能完成管理系统,普通办公人员就可以构建,操作简单容易实现增删改查的基本功能;付......
  • windows常用命令
    1.打开命令行窗口:cmd2.打开计算器:calc3.打开控制面板:control4.打开卸载程序页面:appwiz.cpl5.打开防火墙:firewall.cpl5.远程桌面连接:mstsc6.打开服务配置:services.msc......
  • PPT 常用快捷键
    鼠标+键盘Shift+拖动:水平、竖直移动不偏移Shift+拖拽形形状:等比例缩小、放大Shift+旋转:每次旋转15度Ctrl+鼠标滚轮:快速放大缩小Ctrl+鼠标移动:移动复制......
  • redis集群之分片集群的原理和常用代理环境部署
    上篇文章刚刚介绍完redis的主从复制集群,但主从复制集群主要是为了解决redis集群的单点故障问题,通过整合哨兵能实现集群的高可用;但是却无法解决数据容量以及单节点的压力问......
  • Oracle常用的创建表语句
    Oracle常用的创建表语句Oracle常用的创建表语句指定字段的创建--指定字段的创建createtabletable_name(test_1(字段名1)varchar2(50),(类型)test_2(字段名2)in......
  • 常用代码模板2——数据结构
    常用代码模板2——数据结构单链表//head存储链表头节点的下标,e[]存储节点的值,ne[]存储节点的next指针,idx表示当前可以用的最新的点的下标inthead,e[N],ne[N],idx;......
  • 常用代码模板5——动态规划
    动态规划模型例题dp分析法状态表示集合描述:所有满足条件1、条件2、……的元素的集合(其中每个条件对应状态表示的每一维、元素意义对应求解的量)集合属性:最大值,最小值,......
  • 常用代码模板6——贪心
    贪心夹逼定理(若a>=b,b>=a,则a==b)证明用当前方法得到的结果就等于最优解区间问题可以尝试的突破口:排序(按左端点或右端点或双关键字排序)常用证明方法:基本......