• fridahookjava


    Frida 启动

    attach 启动

    直接附加到指定包名的应用中

    BASH
    frida -U com.kevin.android -l hook.js --no-pause
    

    直接附加到当前应用中

    BASH
    frida -UF -l hook.js --no-pause
    import sys
    import time
    import frida
    
    def on_message(message,data):
        print("message",message)
        print("data",data)
    
    device = frida.get_usb_device()
    session = device.attach("com.kevin.demo1")
    
    with open("./demo1.js","r") as f:
        script = session.create_script(f.read())
    
    script.on("message",on_message)
    script.load()
    sys.stdin.read()
    

    spawn 启动

    BASH
    frida -U -f com.kevin.android -l demo1.js --no-pause
    import sys
    import time
    import frida
    
    def on_message(message,data):
        print("message",message)
        print("data",data)
    
    device = frida.get_usb_device()
    pid = device.spawn(["com.kevin.demo1"])
    device.resume(pid)
    session = device.attach(pid)
    
    with open("./rpc_demo.js",'r') as f:
        script = session.create_script(f.read())
    
    script.on("message",on_message)
    script.load()
    
    sys.stdin.read()
    

    frida-server 自定义端口

    frida server

    更改 frida server 默认端口: 27042 并开启远程连接

    BASH
    adb shell
    su -
    cd /data/local/tmp
    
    # 输入 wifiadb 对应的 ip 和自定义端口
    ./frida-server -l 192.168.0.1:6666
    
    # 也可以使用默认端口启动
    ./frida-server -l 192.168.0.1
    

    frida

    frida 远程连接自定义端口

    BASH
    # 连接指定 6666 端口
    frida -H 192.168.0.1:6666 com.demo1.app -l demo1.js
    
    # 默认使用端口 27042
    frida -H 192.168.0.1 -l demo1.js
    

    python

    PYTHON
    # -*- coding: UTF-8 -*-
    
    import frida, sys
    
    jsCode = """
    console.log("test");
    """
    
    def message(message, data):
        if message['type'] == 'send':
            print(f"[*] {message['payload']}")
    		else:
    				print(message)
    # ./fs120800 -l "0.0.0.0:6666"
    # adb wifi 10.0.0.23
    process = frida.get_device_manager().add_remote_device('127.0.0.1:6666').attach('com.kevin.app')
    script = process.create_script(jsCode)
    script.on("message",message)
    script.load()
    input()
    

    Frida rpc 远程调用

    python

    PYTHON
    import frida
    import json
    from flask import Flask, jsonify, request
    
    def message(message, data):
    	if message['type'] == 'send':
    		print(f"[*] {message['payload']}")
    	else:
    		print(message)
    
    # ./fs120800 -l "0.0.0.0:6666"
    # adb wifi 10.0.0.123
    # 远程 frida-server 路径 adb wifi 的 ip : frida-server 启动的端口
    session = frida.get_device_manager().add_remote_device('10.0.0.123:6666').attach('com.example.demoso1')
    with open("/Users/zhangyang/codes/fridaProject/rpcDemo/hook.js") as f:
        jsCode = f.read()
    
    # print("加载代码", jsCode)
    script = session.create_script(jsCode)
    script.on("message",message)
    script.load()
    
    # print("加密","1213")
    # encodeResult = script.exports.invokemethod01("123")
    # decodeResult = script.exports.invokemethod02(encodeResult)
    # print(decodeResult)
    
    app = Flask(__name__)
    
    @app.route('/encrypt', methods=['POST'])#data解密
    def decrypt_class():
        data = request.get_data()
        json_data = json.loads(data.decode("utf-8"))
        postdata = json_data.get("data")
        res = script.exports.invokemethod01(postdata)
        return res
     
     
    @app.route('/decrypt', methods=['POST'])#url加密
    def encrypt_class():
        data = request.get_data()
        json_data = json.loads(data.decode("utf-8"))
        postdata = json_data.get("data")
        print(postdata)
        res = script.exports.invokemethod02(postdata)
        return res
    
    if __name__ == "__main__":
    	app.run()
    

    js

    JSX
    ///<reference path='/Users/zhangyang/node_modules/@types/frida-gum/index.d.ts'/>
    
    // 先 hook 方法 method01
    // function hookmethod1(){
    //     Java.perform(function(){
    //         var targetClass = Java.use("com.example.demoso1.MainActivity");
    //         targetClass.method01.implementation = function(str){
    //             console.log("str is ", str);
    //             var result = this.method01(str);
    //             console.log("result is ", result);
    //             return result;
    //         }
    //     })
    // };
    
    // 主动调用
    function fridamethod01(inputStr){
        var result = null;
        Java.perform(function(){
            var targetClass = Java.use("com.example.demoso1.MainActivity");
            result = targetClass.method01(inputStr);
        });
        return result;
    }
    
    function fridamethod02(inputStr){
        var result = null;
        // public native String method02(String str);
        Java.perform(function(){
            Java.choose("com.example.demoso1.MainActivity",{
                onMatch: function(ins){
                    result = ins.method02(inputStr);
                },
                onComplete: function(){}
            })
        });
        return result;
    }
    
    // 优先测试 js 中的主动调用
    // function main(){
    //     console.log("你好 -> 结果为:", fridamethod01("你好"));
    //     console.log("27cae29a0913f6791705ca10be31a3e0 -> 结果为", fridamethod02("27cae29a0913f6791705ca10be31a3e0"))
        
    // }
    // setImmediate(main);
    
    // 基于主动调用设置 rpc
    rpc.exports = {
        invokemethod01: fridamethod01,
        invokemethod02: fridamethod02,
    }
    

    压力测试

    tmp.json

    JSON{"data": "62feb9a98a01945ab06c0dd7823adc57"}
    

    命令

    BASHsiege -c30 -r1 "<http://127.0.0.1:5000/encrypt> POST < tmp.json"
    

    nps 进行内网穿透

    1. nps server 启动

      mac: sudo nps start

    2. 新建客户端

      https://kevinspider-1258012111.cos.ap-shanghai.myqcloud.com/2021-01-14-032324.png

      安卓手机连接客户端 ./npc -server=10.0.0.124:8024 -vkey=hm40rtjpf2j3c1up -type=tcp

    3. 给客户端添加和 frida server 的端口映射

      安卓手机启动 frida-server: ./fs12800 -l 0.0.0.0:6666

      https://kevinspider-1258012111.cos.ap-shanghai.myqcloud.com/2021-01-14-032703.png

      将目标 frida-server 的端口映射到 56666 端口上

    4. python 脚本更改和 frida-server 的连接

      PYTHONsession = frida.get_device_manager().add_remote_device('10.0.0.124:56666').attach('com.example.demoso1')
      

      此时就可以将 frida-server 开放到公网了;

    Hook 普通方法

    JSfunction main(){    Java.perform(function(){        var UtilsClass = Java.use("com.kevin.app.Utils");        UtilsClass.getCalc.implementation = function (a,b){        	// 打印信息	        console.log('a:' + a + ' ' + 'b:' + b);    	    // 调用原方法获取结果        	var value = this.getCalc(a, b);	        console.log('result:',value);            // 修改返回值    	    return 123456;            }    })}setImmediate(main);
    

    Hook 重载方法

    JSfunction main(){    Java.perform(function(){        var UtilsClass = Java.use("com.kevin.app.Utils");        // 重载无参方法        UtilsClass.test.overload().implementation = function () {            console.log("hook overload no args");            return this.test();        }                // 重载有参方法 - 基础数据类型		UtilsClass.test.overload('int').implementation = function(num){            console.log("hook overload int args");            var myNum = 9999;            var oriResult = this.test(num);            console.log("oriResult is :" + oriResult);            return this.test(myNum);        }                // 重载有参方法 - 引用数据类型        UtilsClass.test.overload('com.kevin.app.Money').implementation = function(money){            console.log("hook Money args");            return this.test(money);        }                // hook 指定方法的所有重载        var ClassName = Java.use("com.xiaojianbang.app.Utils");        var overloadsLength = ClassName.test.overloads.length;        for (var i = 0; i < overloadsLength; i++){            ClassName.test.overloads[i].implementation = function () {                // 遍历打印 arguments                 for (var a = 0; a < arguments.length; a++){                    console.log(a + " : " + arguments[a]);                }                // 调用原方法                return this.test.apply(this,arguments);            }        }    })}setImmediate(main);
    

    Hook 构造方法

    JSfunction main(){    Java.perform(function (){        // hook 构造方法 $init        var MoneyClass = Java.use("com.kevin.app.Money");        MoneyClass.$init.overload().implementation = function(){            console.log("hook Money $init");            this.$init();        }    })}setImmediate(main);
    

    Hook 对象

    JSfunction main(){    Java.perform(function(){        // hook instance        Java.choose("com.xiaojianbang.app.Money",{            onMatch : function(instance){                console.log("find it!!", instance.getInfo());                // something to do...            },                        onComplete: function(){                console.log("compelete!!!");            }        })    })}setImmediate(main);
    

    Hook 动静态成员属性

    JSfunction main(){    Java.perform(function(){        var MoneyClass = Java.use("com.xiaojianbang.app.Money");                // get static properties        // need to use .value        var ori_property = MoneyClass.flag.value;        console.log("ori_property: ", ori_property);                // change static properties         MoneyClass.flag.value = "change the value";        console.log("change to : ", MoneyClass.flag.value);                // get dynamic properties         Java.choose("com.xiaojianbang.app.Money",{            onMatch: function(instance){                instance.num.value = 50000;                // 当对象的成员属性和成员方法名重复时,成员属性前加`_`,进行区分                instance._name.value = "ouyuan";                 console.log(instance._name.value, instance.num.value, instance.flag.value);            },                        onComplete: function(){                console.log("complete!!")            }        })    })}setImmediate(main);
    

    Hook 内部类

    JSfunction main(){    Java.perfor(function(){        // hook 内部类        // 内部类使用$进行分隔 不使用.        var InnerClass = Java.use("com.xiaojianbang.app.Money$innerClass");        // 重写内部类的 $init 方法        InnerClass.$init.overload("java.lang.String","int").implementation = function(x,y){            console.log("x: ",x);            console.log("y: ",y);            this.$init(x,y);        }    })}setImmediate(main)
    

    Hook 匿名类

    JS// 接口, 抽象类, 不可以被new// 接口, 抽象类 要使用必须要实例化, 实例化不是通过new, 而是通过实现接口方法, 继承抽象类等方式// new __接口__{} 可以理解成 new 了一个实现接口的匿名类, 在匿名类的内部(花括号内),实现了这个接口function main(){    Java.perform(function(){        // hook 匿名类        // 匿名类在 smail中以 $1, $2 等方式存在, 需要通过 java 行号去 smail 找到准确的匿名类名称         var NiMingClass = Java.use("com.xiaojianbang.app.MainActivity$1");        NiMingClass.getInfo.implementation = function (){            return "kevin change 匿名类";        }    })}setImmediate(main)
    

    Hook 类的所有方法

    • Java.enumerateLoadedClasses()
    JSfunction main(){    Java.perform(function(){        Java.enumerateLoadedClasses({            onMatch: function(name,handle){                if (name.indexOf("com.xiaojianbang.app.Money") != -1){                    console.log(name,handle);                    // 利用反射 获取类中的所有方法                    var TargetClass = Java.use(name);                    // return Method Object List                    var methodsList = TargetClass.class.getDeclaredMethods();                     for (var i = 0; i < methodsList.length; i++){                        // Method Objection getName()                        console.log(methodsList[i].getName());                    }                }            },                        onComplete: function(){                console.log("complete!!!")            }        })    })}
    
    • Java.enumerateLoadedClassesSync()
    JSfunction main(){    Java.perform(function(){        // return String[] class name        var classList = Java.enumerateLoadedClassesSync();        for (var i=0; i < classList.length; i++){            var targetClass = classList[i];            if (targetClass.indexOf("com.xiaojianbang.app.Money") != -1){				console.log("hook the class: ", targetClass);    	        var TargetClass = Java.use(targetClass);                // 利用反射获取类中的所有方法        	    var methodsList = TargetClass.class.getDeclaredMethods();            	for (var k=0; k < methodsList.length; k++){                	console.log(methodsList[k].getName());            	}                           }        }    })}setImmediate(main)
    

    Hook 类的所有方法及重载

    JSfunction main(){    Java.perform(function(){        // hook md5 class in app        // 1. iterate classes        var classList = Java.enumerateLoadedClassesSync();        for (var i = 0; i < classList.length; i++){            // 筛选过滤 只遍历 MD5 下面的方法            if (classList[i].indexOf("com.xiaojianbang.app.MD5") != -1){                var className = classList[i];                console.log("class name is :", className);                // 2. get methods of the class                // 返回一个 Methods对象的数组                var methodsList = Java.use(className).class.getDeclaredMethods();                for (var k=0; k<methodsList.length; k++){                                        // console.log("method is :",methodsList[k],typeof(methodsList[k]));                                        // 3. Method object.getName() --> methodName and class[methodName] to hook method                    var methodName = methodsList[k].getName(); //                                         // console.log('methodName',methodName);                    // 4. use apply and arguments to implementation                    var hookClass = Java.use(className);                    // 5. overloads                    for (var o = 0; o< hookClass[methodName].overloads.length; o++){                        hookClass[methodName].overloads[o].implementation = function(){                            for (var a=0; a<arguments.length; a++){                                console.log('argument ',a,arguments[a]);                            }                            // return this[methodName].apply(this,arguments);                            return "fucking the md5"                        }                    }                }            }        }    })}
    

    Hook 动态加载的 dex

    JSfunction main(){    Java.perform(function(){        Java.enumerateClassLoaders({            onMatch : function(loader){                try {                    // loadClass or findClass                    if (loader.loadClass("com.xiaojianbang.app.Dynamic")){                        Java.classFactory.loader = loader;                        var hookClass = Java.use("com.xiaojianbang.app.Dynamic");                        console.log("success hook it :", hookClass);                        // something to do;                    }                } catch (error) {                    // pass                }            },                        onComplete: function () {                console.log("complete !!! ")            }        })    })}setImmediate(main);
    

    经常在加壳的 app 中, 没办法正确找到正常加载 app 类的 classloader, 可以使用以下代码:

    JSfunction hook() {    Java.perform(function () {        Java.enumerateClassLoadersSync().forEach(function (classloader) {            try {                console.log("classloader", classloader);                classloader.loadClass("com.kanxue.encrypt01.MainActivity");                Java.classFactory.loader = classloader;                var mainActivityClass = Java.use("com.kanxue.encrypt01.MainActivity");                console.log("mainActivityClass", mainActivityClass);            } catch (error) {                console.log("error", error);            }        });    })}
    

    Hook 主动构造数组

    JSfunction mainArray(){    Java.perform(function(){        var myCharList = Java.array("char",['一','去','二','三','里']);        var myStringList = Java.array("java.lang.String",["一","二","三"]);        var ArrayClass = Java.use("java.util.Arrays");        console.log(ArrayClass.toString(myCharList));        console.log(ArrayClass.toString(myStringList));    })}
    

    Hook cast 强制类型转换

    JS// Java.cast() 子类可以强转成父类, 父类不能转成子类// 可以使用Java.cast()将子类强转成父类, 再调用父类的动态方法function castDemo(){    Java.perform(function(){        var JuiceHandle = null; // 用来存储内存中找到的Juice对象        var WaterClass = Java.use("com.r0ysue.a0526printout.Water");                Java.choose("com.r0ysue.a0526printout.Juice",{			onComplete: function(){},            onMatch: function(instance){                JuiceHandle = instance;                console.log("instance:", instance);                // 调用Juice对象的方法                console.log(JuiceHandle.fillEnergy());                // 子类Juice转父类Water 并调用父类的动态方法                var WaterInstance = Java.cast(JuiceHandle,WaterClass);                console.log(WaterInstance.still(WaterInstance));            }        })    })}
    

    Hook 打印类实现的接口

    JSfunction searchInterface(){    Java.perform(function(){        Java.enumerateLoadedClasses({            onComplete: function(){},            onMatch: function(name,handle){                if (name.indexOf("com.r0ysue.a0526printout") > -1) { // 使用包名进行过滤                    console.log("find class");                    var targetClass = Java.use(name);                    var interfaceList = targetClass.class.getInterfaces(); // 使用反射获取类实现的接口数组                    if (interfaceList.length > 0) {                        console.log(name) // 打印类名                        for (var i in interfaceList) {                            console.log("	", interfaceList[i].toString()); // 直接打印接口名称                        }                    }                }            }        })    })}
    

    Hook enum 枚举

    JSfunction enumPrint(){    Java.perform(function(){        Java.choose("com.r0ysue.a0526printout.Signal",{            onComplete: function(){},            onMatch: function(instance){                console.log('find it ,',instance);                console.log(instance.class.getName());            }        })    })}
    

    Hook 获取 context

    JSfunction getContext(){    Java.perform(function(){        var currentApplication = Java.use("android.app.ActivityThread").currentApplication();        console.log(currentApplication);        var context = currentApplication.getApplicationContext();        console.log(context);        var packageName = context.getPackageName();        console.log(packageName);        console.log(currentApplication.getPackageName());    })}
    

    Hook 主动调用构造方法

    JSfunction main(){    Java.perform(function(){        var StringClass = Java.use("java.lang.String");		var MoneyClass = Java.use("com.xiaojianbang.app.Money");        MoneyClass.$init.overload('java.lang.String','int').implementation = function(x,y){            console.log('hook Money init');            var myX = StringClass.new("Hello World!");            var myY = 9999;            this.$init(myX,myY);        }    })}setImmediate(main);
    

    Hook 主动调用静态方法

    JSfunction main_rsa(){    Java.perform(function(){        var RSA = Java.use("com.xiaojianbang.app.RSA");        var StringClass = Java.use("java.lang.String");        var base64Class = Java.use("android.util.Base64");        var myBytes = StringClass.$new("Hello World").getBytes();        var result = RSA.encrypt(myBytes);        console.log("result is :", result);        console.log("json result is: ",JSON.stringify(result));        console.log("base64 result is :", base64Class.encodeToString(result,0));        // console.log("new String is : ", StringClass.$new(result)); // 加密之后的内容有很多不可见字符, 不能直接 new String()    })}setImmediate(main_rsa);
    

    Hook 主动调用动态方法

    JS// 非静态方法的主动调用 自定义instance 并调用 非静态方法function main_getInfo(){    Java.perform(function(){        var instance = Java.use("com.xiaojianbang.app.Money").$new("日元",300000);        console.log(instance.getInfo());    })}// 遍历所有的对象并调用 需要进行过滤function main_instance_getInfo(){    Java.perform(function(){        Java.choose("com.xiaojianbang.app.Money",{            onComplete: function(){},            onMatch: function(instance){                console.log(instance.getInfo());            }        })    })}
    

    Hook frida 和 python 交互

    CODEfrida 传递参数function main(){    Java.perform(function () {        console.log("enter perform");        // 获取要hook的类        var TextViewClass = Java.use("android.widget.TextView");        // 要hook的方法        TextViewClass.setText.overload('java.lang.CharSequence').implementation = function (ori_input) {            console.log('enter', 'java.lang.CharSequence');            console.log('ori_input',ori_input.toString());            // 定义用于接受python传参的data            var receive_data;            // 将原参数传递给python 在python中进行处理            send(ori_input.toString());            // recv 从python接收传递的内容 默认传过来的是个json对象            recv(function (json_data) {                console.log('data from python ' + json_data.data);                receive_data = json_data.data;                console.log(typeof (receive_data));            }).wait(); //wait() 等待python处理 阻塞            // 转java字符串            receive_data = Java.use("java.lang.String").$new(receive_data);            this.setText(receive_data);        };    })}setImmediate(main);python 处理收到的参数# -*- coding: utf-8 -*-__author__ = "K"__time__ = "2020-08-06 09:48"import sysimport timeimport base64import fridafrom loguru import loggerdef on_message(message,data):    logger.info(str(message)) # dict    logger.info(str(data) if data else "None")    if message['type'] == 'error':        logger.error('error:' + str(message['description']))        logger.error('stack: ' + str(message['stack']))    if message['type'] == 'send':        logger.info('get message [*] --> ' + message['payload'])        payload = message['payload']        # 处理逻辑 sending to the server: YWFhOmJiYg==        tmp = payload.split(':')        sts = tmp[0]        need_to_db64 = tmp[1]        user_pass = base64.b64decode(need_to_db64.encode()).decode()        mine_str = 'admin' + ':' + user_pass.split(':')[-1]        mine_b64_str = base64.b64encode(mine_str.encode()).decode()        mine_b64_str = sts + mine_b64_str        logger.info(mine_b64_str)        # python返回数据给js script.post        script.post({'data':mine_b64_str})        logger.info('python complete')device = frida.get_usb_device()# pid = device.spawn(['com.kevin.demo04'])# time.sleep(1)session = device.attach('com.kevin.demo02')with open('./hulianhutong.js','r') as f:    script = session.create_script(f.read())script.on("message",on_message)script.load()input()
    

    Hook 打印 char

    JS// 打印char字符, 直接调用java.lang.Character toString()即可function main(){    Java.perform(function(){        var CharClass = Java.use("java.lang.Character");        CharClass.toString.overload("char").implementation = function(inputChar){            var result = this.toString(inputChar);            console.log("inputChar, result: ", inputChar, result);            return result;        }    })}
    

    Hook 打印 char 数组

    JS// 1. 使用 java.util.Arrays 的 toString 方法 打印 [C // 2. 使用 js 的 JSON.stringify 打印 [Cfunction printCharArray(){    Java.perform(function(){        var ArrayClass = Java.use("java.util.Arrays");        ArrayClass.toString.overload('[C').implementation = function(charArray){            // 1. java.util.Arrays.toString()            var result = this.toString(charArray);            // 2. javascript JSON.stringify()            var result1 = JSON.stringify(charArray);            console.log('charArray, result : ', charArray, result);            console.log('charArray, result :', charArray, result1);        }    })}
    

    Hook 打印和修改 HashMap

    CODE遍历打印function main(){	Java.perform(function(){        var targetClass = Java.use("com.xiaojianbang.app.ShufferMap");        targetClass.show.implementation = function(map){            // 遍历 map        	var result = "";	        var it = map.keySet().iterator();    	    while (it.hasNext()){        	    var keyStr = it.next();            	var valueStr = map.get(keyStr);                result += valueStr;	        }            console.log("result :", result);                        // 修改 map            map.put("pass","fxxk");            map.put("code","Hello World");            console.log(JSON.stringify(map));            this.show(map);                        return this.show(map);        }    })    }setImmediate(main);cast打印 HashMapfunction main(){    Java.perform(function(){        var HashMapNode = Java.use("java.util.HashMap$Node");        var targetClass = Java.use("com.xiaojianbang.app.ShufferMap");                var targetClass.show.implementation = function(map){            var result = "";            var iterator = map.entrySet().iterator();            while (iterator.hasNext()) {                console.log("entry", iterator.next());                var entry = Java.cast(iterator.next(), HashMapNode);                console.log(entry.getKey());                console.log(entry.getValue());                return += entry.getValue();            }                        console.log("result is :", result);        }    })}setImmediate(main);
    

    toString()打印

    JSfunction main(){    Java.perform(function(){        var targetClass = Java.use("com.xiaojianbang.app.ShufferMap");        targetClass.show.implementation = function(map){            // 直接调用 toString()            console.log("打印hashmap: -> " + map.toString());            return this.show.apply(this,arguments);        }    })}setImmediate(main);function printHashMap(flag, param_hm) {    Java.perform(function () {        var HashMap = Java.use('java.util.HashMap');        var args_map = Java.cast(param_hm, HashMap);        send(flag +":" + args_map.toString());    })}
    

    Hook 打印 byte 数组

    CODE方法 1function main(){    Java.perform(function(){            var StringClass = Java.use("java.lang.String");            var byteArray = StringClass.$new("Hello World").getBytes();                        // load r0gson	        // openClassFile 返回 dex对象, dex对象.load()加载dex文件内容            Java.openClassFile("/data/local/tmp/r0gson.dex").load();            var gson = Java.use("com.r0ysue.gson.Gson");            console.log(gson.$new().toJson(byteArray));            // // console byte[]            // var ByteString = Java.use("com.android.okhttp.okio.ByteString");            // console.log(ByteString.of(byteArray).hex()); // byte转16进制字符串            // // 创建自定义Java数组 并打印            // var MyArray = Java.array("byte",[13,4,4,2]);            // console.log(gson.$new().toJson(MyArray));            var TargetClass = Java.use("com.xiaojianbang.app.ShufferMap");            TargetClass.show.implementation =  function(map){                console.log(gson.$new().toJson(map));                return this.show(map);            }    })}setImmediate(main);方法 2// 1. 使用 java.util.Arrays.toString() 打印 [B// 2. 使用 javascript JSON.stringify() 打印 [Bfunction printByteArray(){    Java.perform(function(){        var ArrayClass = Java.use("java.util.Arrays");        ArrayClass.toString.overload('[B').implementation = function(byteArray){			// 1. 使用 java.util.Arrays.toString() 打印 [B            var result = this.toString(byteArray);			// 2. 使用 javascript JSON.stringify() 打印 [B            var result1 = JSON.stringify(byteArray);                        console.log('byteArray,result: ', byteArray, result);            console.log('byteArray,result1 :', byteArray, result1);            return result        }    })}方法 3function printByteArray(byteArray){	Java.perform(function(){		var ByteString = Java.use("com.android.okhttp.okio.ByteString");		console.log(ByteString.of(byteArray).hex())	})}
    

    Hook 打印调用栈

    JSfunction printStacks(name){    console.log("====== printStacks start ====== " + name + "==============================")        // sample 1    var throwable = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new());    console.log(throwable);    // sample 2    var exception = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new());    console.log(exception);        console.log("====== printStacks end ======== " + name + "==============================")}
    

    Hook gson 打印

    JSfunction main(){    Java.perform(function(){            var StringClass = Java.use("java.lang.String");            var byteArray = StringClass.$new("Hello World").getBytes();                        // load r0gson	        // openClassFile 返回 dex对象, dex对象.load()加载dex文件内容            Java.openClassFile("/data/local/tmp/r0gson.dex").load();            var gson = Java.use("com.r0ysue.gson.Gson");            console.log(gson.$new().toJson(byteArray));            // // console byte[]            // var ByteString = Java.use("com.android.okhttp.okio.ByteString");            // console.log(ByteString.of(byteArray).hex()); // byte转16进制字符串            // // 创建自定义Java数组 并打印            // var MyArray = Java.array("byte",[13,4,4,2]);            // console.log(gson.$new().toJson(MyArray));            var TargetClass = Java.use("com.xiaojianbang.app.ShufferMap");            TargetClass.show.implementation =  function(map){                console.log(gson.$new().toJson(map));                return this.show(map);            }    })}setImmediate(main);
    

    Hook 打印 non-ascii 和特殊字符

    一些特殊字符和不可见字符, 可以先通过编码再解码的方式进行 hook

    JAVAint ֏(int x) {        return x + 100;    }
    

    针对上面的֏, 直接用js编码, 在通过类名[js解码的方法名]进行implementation

    JSJava.perform(        function x() {            var targetClass = "com.example.hooktest.MainActivity";            var hookCls = Java.use(targetClass);            var methods = hookCls.class.getDeclaredMethods();            for (var i in methods) {                console.log(methods[i].toString());                console.log(encodeURIComponent(methods[i].toString().replace(/^.*?.([^s.()]+)(.*?$/, "$1")));            }            hookCls[decodeURIComponent("%D6%8F")]                .implementation = function (x) {                    console.log("original call: fun(" + x + ")");                    var result = this[decodeURIComponent("%D6%8F")](900);                    return result;                }        }    )
    

    简易 wallbreaker 内存打印

    内存漫游, 打印实例的字段和方法

    JSfunction main(){    Java.perform(function(){        var Class = Java.use("java.lang.Class");              	function inspectObject(obj){            var obj_class = Java.cast(obj.getClass(), Class);            var fields = obj_class.getDeclaredFields();            var methods = obj_class.getMethods();            console.log("Inspectiong " + obj.getClass().toString());            console.log("	 Fields:")            for (var i in fields){                console.log("		" + fields[i].toString());            }            console.log("	 Methods:")            for (var i in methods){                console.log("		" + methods[i].toString())            }        }        Java.choose("com.baidu.lbs.waimai.WaimaiActivity",{            onComplete: function(){                console.log("complete!");                            },            onMatch: function(instance){                console.log("find instance", instance);                inspectObject(instance);            }        })    })}setImmediate(main)
    

    hook frida 实现 runnable

    JSJava.perform(function() {   // https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_SECURE   var FLAG_SECURE = 0x2000;   var Runnable = Java.use("java.lang.Runnable");   var DisableSecureRunnable = Java.registerClass({      name: "me.bhamza.DisableSecureRunnable",      implements: [Runnable],      fields: {          activity: "android.app.Activity",       },       methods: {          $init: [{             returnType: "void",             argumentTypes: ["android.app.Activity"],             implementation: function (activity) {                this.activity.value = activity;             }          }],          run: function() {             var flags = this.activity.value.getWindow().getAttributes().flags.value; // get current value             flags &= ~FLAG_SECURE; // toggle it             this.activity.value.getWindow().setFlags(flags, FLAG_SECURE); // disable it!             console.log("Done disabling SECURE flag...");          }       }    });    Java.choose("com.example.app.FlagSecureTestActivity", {       "onMatch": function (instance) {          var runnable = DisableSecureRunnable.$new(instance);          instance.runOnUiThread(runnable);       },       "onComplete": function () {}    }); });
    

    Hook 监控控件 onClick

    JSvar jclazz = null;var jobj = null;function getObjClassName(obj) {    if (!jclazz) {        var jclazz = Java.use("java.lang.Class");    }    if (!jobj) {        var jobj = Java.use("java.lang.Object");    }    return jclazz.getName.call(jobj.getClass.call(obj));}function watch(obj, mtdName) {    var listener_name = getObjClassName(obj);    var target = Java.use(listener_name);    if (!target || !mtdName in target) {        return;    }    // send("[WatchEvent] hooking " + mtdName + ": " + listener_name);    target[mtdName].overloads.forEach(function (overload) {        overload.implementation = function () {            //send("[WatchEvent] " + mtdName + ": " + getObjClassName(this));            console.log("[WatchEvent] " + mtdName + ": " + getObjClassName(this))            return this[mtdName].apply(this, arguments);        };    })}function OnClickListener() {    Java.perform(function () {        //以spawn启动进程的模式来attach的话        Java.use("android.view.View").setOnClickListener.implementation = function (listener) {            if (listener != null) {                watch(listener, 'onClick');            }            return this.setOnClickListener(listener);        };        //如果frida以attach的模式进行attch的话        Java.choose("android.view.View$ListenerInfo", {            onMatch: function (instance) {                instance = instance.mOnClickListener.value;                if (instance) {                    console.log("mOnClickListener name is :" + getObjClassName(instance));                    watch(instance, 'onClick');                }            },            onComplete: function () {            }        })    })}setImmediate(OnClickListener);
    

    Hook startActivity

    JSJava.perform(function () {    var Activity = Java.use("android.app.Activity");    //console.log(Object.getOwnPropertyNames(Activity));    Activity.startActivity.overload('android.content.Intent').implementation=function(p1){        console.log("Hooking android.app.Activity.startActivity(p1) successfully,p1="+p1);        console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));        console.log(decodeURIComponent(p1.toUri(256)));        this.startActivity(p1);    }    Activity.startActivity.overload('android.content.Intent', 'android.os.Bundle').implementation=function(p1,p2){        console.log("Hooking android.app.Activity.startActivity(p1,p2) successfully,p1="+p1+",p2="+p2);        console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));        console.log(decodeURIComponent(p1.toUri(256)));        this.startActivity(p1,p2);    }    Activity.startService.overload('android.content.Intent').implementation=function(p1){        console.log("Hooking android.app.Activity.startService(p1) successfully,p1="+p1);        console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));        console.log(decodeURIComponent(p1.toUri(256)));        this.startService(p1);    }})
    

    Hook frida 绕过 root 检测

    JS// $ frida -l antiroot.js -U -f com.example.app --no-pause// CHANGELOG by Pichaya Morimoto (p.morimoto@sth.sh): //  - I added extra whitelisted items to deal with the latest versions // 						of RootBeer/Cordova iRoot as of August 6, 2019//  - The original one just fucked up (kill itself) if Magisk is installed lol// Credit & Originally written by: https://codeshare.frida.re/@dzonerzy/fridantiroot/// If this isn't working in the future, check console logs, rootbeer src, or libtool-checker.soJava.perform(function() {    var RootPackages = ["com.noshufou.android.su", "com.noshufou.android.su.elite", "eu.chainfire.supersu",        "com.koushikdutta.superuser", "com.thirdparty.superuser", "com.yellowes.su", "com.koushikdutta.rommanager",        "com.koushikdutta.rommanager.license", "com.dimonvideo.luckypatcher", "com.chelpus.lackypatch",        "com.ramdroid.appquarantine", "com.ramdroid.appquarantinepro", "com.devadvance.rootcloak", "com.devadvance.rootcloakplus",        "de.robv.android.xposed.installer", "com.saurik.substrate", "com.zachspong.temprootremovejb", "com.amphoras.hidemyroot",        "com.amphoras.hidemyrootadfree", "com.formyhm.hiderootPremium", "com.formyhm.hideroot", "me.phh.superuser",        "eu.chainfire.supersu.pro", "com.kingouser.com", "com.android.vending.billing.InAppBillingService.COIN","com.topjohnwu.magisk"    ];    var RootBinaries = ["su", "busybox", "supersu", "Superuser.apk", "KingoUser.apk", "SuperSu.apk","magisk"];    var RootProperties = {        "ro.build.selinux": "1",        "ro.debuggable": "0",        "service.adb.root": "0",        "ro.secure": "1"    };    var RootPropertiesKeys = [];    for (var k in RootProperties) RootPropertiesKeys.push(k);    var PackageManager = Java.use("android.app.ApplicationPackageManager");    var Runtime = Java.use('java.lang.Runtime');    var NativeFile = Java.use('java.io.File');    var String = Java.use('java.lang.String');    var SystemProperties = Java.use('android.os.SystemProperties');    var BufferedReader = Java.use('java.io.BufferedReader');    var ProcessBuilder = Java.use('java.lang.ProcessBuilder');    var StringBuffer = Java.use('java.lang.StringBuffer');    var loaded_classes = Java.enumerateLoadedClassesSync();    send("Loaded " + loaded_classes.length + " classes!");    var useKeyInfo = false;    var useProcessManager = false;    send("loaded: " + loaded_classes.indexOf('java.lang.ProcessManager'));    if (loaded_classes.indexOf('java.lang.ProcessManager') != -1) {        try {            //useProcessManager = true;            //var ProcessManager = Java.use('java.lang.ProcessManager');        } catch (err) {            send("ProcessManager Hook failed: " + err);        }    } else {        send("ProcessManager hook not loaded");    }    var KeyInfo = null;    if (loaded_classes.indexOf('android.security.keystore.KeyInfo') != -1) {        try {            //useKeyInfo = true;            //var KeyInfo = Java.use('android.security.keystore.KeyInfo');        } catch (err) {            send("KeyInfo Hook failed: " + err);        }    } else {        send("KeyInfo hook not loaded");    }    PackageManager.getPackageInfo.overload('java.lang.String', 'int').implementation = function(pname, flags) {        var shouldFakePackage = (RootPackages.indexOf(pname) > -1);        if (shouldFakePackage) {            send("Bypass root check for package: " + pname);            pname = "set.package.name.to.a.fake.one.so.we.can.bypass.it";        }        return this.getPackageInfo.call(this, pname, flags);    };    NativeFile.exists.implementation = function() {        var name = NativeFile.getName.call(this);        var shouldFakeReturn = (RootBinaries.indexOf(name) > -1);        if (shouldFakeReturn) {            send("Bypass return value for binary: " + name);            return false;        } else {            return this.exists.call(this);        }    };    var exec = Runtime.exec.overload('[Ljava.lang.String;');    var exec1 = Runtime.exec.overload('java.lang.String');    var exec2 = Runtime.exec.overload('java.lang.String', '[Ljava.lang.String;');    var exec3 = Runtime.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;');    var exec4 = Runtime.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;', 'java.io.File');    var exec5 = Runtime.exec.overload('java.lang.String', '[Ljava.lang.String;', 'java.io.File');    exec5.implementation = function(cmd, env, dir) {        if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id" || cmd == "sh") {            var fakeCmd = "grep";            send("Bypass " + cmd + " command");            return exec1.call(this, fakeCmd);        }        if (cmd == "su") {            var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled";            send("Bypass " + cmd + " command");            return exec1.call(this, fakeCmd);        }        if (cmd == "which") {            var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled";            send("Bypass which command");            return exec1.call(this, fakeCmd);        }        return exec5.call(this, cmd, env, dir);    };    exec4.implementation = function(cmdarr, env, file) {        for (var i = 0; i < cmdarr.length; i = i + 1) {            var tmp_cmd = cmdarr[i];            if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id" || tmp_cmd == "sh") {                var fakeCmd = "grep";                send("Bypass " + cmdarr + " command");                return exec1.call(this, fakeCmd);            }            if (tmp_cmd == "su") {                var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled";                send("Bypass " + cmdarr + " command");                return exec1.call(this, fakeCmd);            }        }        return exec4.call(this, cmdarr, env, file);    };    exec3.implementation = function(cmdarr, envp) {        for (var i = 0; i < cmdarr.length; i = i + 1) {            var tmp_cmd = cmdarr[i];            if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id" || tmp_cmd == "sh") {                var fakeCmd = "grep";                send("Bypass " + cmdarr + " command");                return exec1.call(this, fakeCmd);            }            if (tmp_cmd == "su") {                var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled";                send("Bypass " + cmdarr + " command");                return exec1.call(this, fakeCmd);            }        }        return exec3.call(this, cmdarr, envp);    };    exec2.implementation = function(cmd, env) {        if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id" || cmd == "sh") {            var fakeCmd = "grep";            send("Bypass " + cmd + " command");            return exec1.call(this, fakeCmd);        }        if (cmd == "su") {            var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled";            send("Bypass " + cmd + " command");            return exec1.call(this, fakeCmd);        }        return exec2.call(this, cmd, env);    };    exec.implementation = function(cmd) {        for (var i = 0; i < cmd.length; i = i + 1) {            var tmp_cmd = cmd[i];            if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id" || tmp_cmd == "sh") {                var fakeCmd = "grep";                send("Bypass " + cmd + " command");                return exec1.call(this, fakeCmd);            }            if (tmp_cmd == "su") {                var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled";                send("Bypass " + cmd + " command");                return exec1.call(this, fakeCmd);            }        }        return exec.call(this, cmd);    };    exec1.implementation = function(cmd) {        if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id" || cmd == "sh") {            var fakeCmd = "grep";            send("Bypass " + cmd + " command");            return exec1.call(this, fakeCmd);        }        if (cmd == "su") {            var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled";            send("Bypass " + cmd + " command");            return exec1.call(this, fakeCmd);        }        return exec1.call(this, cmd);    };    String.contains.implementation = function(name) {        if (name == "test-keys") {            send("Bypass test-keys check");            return false;        }        return this.contains.call(this, name);    };    var get = SystemProperties.get.overload('java.lang.String');    get.implementation = function(name) {        if (RootPropertiesKeys.indexOf(name) != -1) {            send("Bypass " + name);            return RootProperties[name];        }        return this.get.call(this, name);    };    Interceptor.attach(Module.findExportByName("libc.so", "fopen"), {        onEnter: function(args) {            var path1 = Memory.readCString(args[0]);            var path = path1.split("/");            var executable = path[path.length - 1];            var shouldFakeReturn = (RootBinaries.indexOf(executable) > -1)            if (shouldFakeReturn) {                Memory.writeUtf8String(args[0], "/ggezxxx");                send("Bypass native fopen >> "+path1);            }        },        onLeave: function(retval) {        }    });    Interceptor.attach(Module.findExportByName("libc.so", "fopen"), {        onEnter: function(args) {            var path1 = Memory.readCString(args[0]);            var path = path1.split("/");            var executable = path[path.length - 1];            var shouldFakeReturn = (RootBinaries.indexOf(executable) > -1)            if (shouldFakeReturn) {                Memory.writeUtf8String(args[0], "/ggezxxx");                send("Bypass native fopen >> "+path1);            }        },        onLeave: function(retval) {        }    });    Interceptor.attach(Module.findExportByName("libc.so", "system"), {        onEnter: function(args) {            var cmd = Memory.readCString(args[0]);            send("SYSTEM CMD: " + cmd);            if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id") {                send("Bypass native system: " + cmd);                Memory.writeUtf8String(args[0], "grep");            }            if (cmd == "su") {                send("Bypass native system: " + cmd);                Memory.writeUtf8String(args[0], "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled");            }        },        onLeave: function(retval) {        }    });    /*    TO IMPLEMENT:    Exec Family    int execl(const char *path, const char *arg0, ..., const char *argn, (char *)0);    int execle(const char *path, const char *arg0, ..., const char *argn, (char *)0, char *const envp[]);    int execlp(const char *file, const char *arg0, ..., const char *argn, (char *)0);    int execlpe(const char *file, const char *arg0, ..., const char *argn, (char *)0, char *const envp[]);    int execv(const char *path, char *const argv[]);    int execve(const char *path, char *const argv[], char *const envp[]);    int execvp(const char *file, char *const argv[]);    int execvpe(const char *file, char *const argv[], char *const envp[]);    */    BufferedReader.readLine.overload().implementation = function() {        var text = this.readLine.call(this);        if (text === null) {            // just pass , i know it's ugly as hell but test != null won't work :(        } else {            var shouldFakeRead = (text.indexOf("ro.build.tags=test-keys") > -1);            if (shouldFakeRead) {                send("Bypass build.prop file read");                text = text.replace("ro.build.tags=test-keys", "ro.build.tags=release-keys");            }        }        return text;    };    var executeCommand = ProcessBuilder.command.overload('java.util.List');    ProcessBuilder.start.implementation = function() {        var cmd = this.command.call(this);        var shouldModifyCommand = false;        for (var i = 0; i < cmd.size(); i = i + 1) {            var tmp_cmd = cmd.get(i).toString();            if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd.indexOf("mount") != -1 || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd.indexOf("id") != -1) {                shouldModifyCommand = true;            }        }        if (shouldModifyCommand) {            send("Bypass ProcessBuilder " + cmd);            this.command.call(this, ["grep"]);            return this.start.call(this);        }        if (cmd.indexOf("su") != -1) {            send("Bypass ProcessBuilder " + cmd);            this.command.call(this, ["justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"]);            return this.start.call(this);        }        return this.start.call(this);    };    if (useProcessManager) {        var ProcManExec = ProcessManager.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;', 'java.io.File', 'boolean');        var ProcManExecVariant = ProcessManager.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;', 'java.lang.String', 'java.io.FileDescriptor', 'java.io.FileDescriptor', 'java.io.FileDescriptor', 'boolean');        ProcManExec.implementation = function(cmd, env, workdir, redirectstderr) {            var fake_cmd = cmd;            for (var i = 0; i < cmd.length; i = i + 1) {                var tmp_cmd = cmd[i];                if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id") {                    var fake_cmd = ["grep"];                    send("Bypass " + cmdarr + " command");                }                if (tmp_cmd == "su") {                    var fake_cmd = ["justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"];                    send("Bypass " + cmdarr + " command");                }            }            return ProcManExec.call(this, fake_cmd, env, workdir, redirectstderr);        };        ProcManExecVariant.implementation = function(cmd, env, directory, stdin, stdout, stderr, redirect) {            var fake_cmd = cmd;            for (var i = 0; i < cmd.length; i = i + 1) {                var tmp_cmd = cmd[i];                if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id") {                    var fake_cmd = ["grep"];                    send("Bypass " + cmdarr + " command");                }                if (tmp_cmd == "su") {                    var fake_cmd = ["justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"];                    send("Bypass " + cmdarr + " command");                }            }            return ProcManExecVariant.call(this, fake_cmd, env, directory, stdin, stdout, stderr, redirect);        };    }    if (useKeyInfo) {        KeyInfo.isInsideSecureHardware.implementation = function() {            send("Bypass isInsideSecureHardware");            return true;        }    }});
    

    Hook frida 强制在主线程运行

    针对使用一些方法的时候出现报错 on a thread that has not called Looper.prepare()

    强制让代码运行在主线程中

    JSJava.perform(function() {  var Toast = Java.use('android.widget.Toast');  var currentApplication = Java.use('android.app.ActivityThread').currentApplication();   var context = currentApplication.getApplicationContext();  Java.scheduleOnMainThread(function() {    Toast.makeText(context, "Hello World", Toast.LENGTH_LONG.value).show();  })})
    

    Hook frida 指定方法中过滤打印

    JSfunction hook_lnf() {    var activate = false;    Java.perform(function(){        var hashmapClass = Java.use("java.util.HashMap");        hashmapClass.put.implementation = function(key,value){            if (activate){                console.log("key:", key, "value:", value);            }            return this.put(key,value);        };    });    Java.perform(function () {        var lnfClazz = Java.use("tb.lnf");        lnfClazz.a.overload('java.util.HashMap', 'java.util.HashMap', 'java.lang.String',            'java.lang.String', 'boolean').implementation = function (hashmap, hashmap2, str, str2, z) {                printHashMap("hashmap", hashmap);                printHashMap("hashmap2", hashmap2);                console.log("str", str);                console.log("str2", str2);                console.log("boolean", z);                activate = true;                var result = this.a(hashmap, hashmap2, str, str2, z);                activate = false                printHashMap("result", result);                return result;            };    })}
    

    Hook 禁止 app 退出

    JSfunction hookExit(){    Java.perform(function(){        console.log("[*] Starting hook exit");        var exitClass = Java.use("java.lang.System");        exitClass.exit.implementation = function(){            console.log("[*] System.exit.called");        }        console.log("[*] hooking calls to System.exit");    })}setImmediate(hookExit);
    

    Hook 修改设备参数

    JS// frida hook 修改设备参数Java.perform(function() {	var TelephonyManager = Java.use("android.telephony.TelephonyManager");    //IMEI hook    TelephonyManager.getDeviceId.overload().implementation = function () {               console.log("[*]Called - getDeviceId()");               var temp = this.getDeviceId();               console.log("real IMEI: "+temp);               return "867979021642856";    };    // muti IMEI    TelephonyManager.getDeviceId.overload('int').implementation = function (p) {               console.log("[*]Called - getDeviceId(int) param is"+p);               var temp = this.getDeviceId(p);               console.log("real IMEI "+p+": "+temp);               return "867979021642856";    };    //IMSI hook	TelephonyManager.getSimSerialNumber.overload().implementation = function () {               console.log("[*]Called - getSimSerialNumber(String)");               var temp = this.getSimSerialNumber();               console.log("real IMSI: "+temp);               return "123456789";    };    //////////////////////////////////////    //ANDOID_ID hook    var Secure = Java.use("android.provider.Settings$Secure");    Secure.getString.implementation = function (p1,p2) {    	if(p2.indexOf("android_id")<0) return this.getString(p1,p2);    	console.log("[*]Called - get android_ID, param is:"+p2);    	var temp = this.getString(p1,p2);    	console.log("real Android_ID: "+temp);    	return "844de23bfcf93801";    }    //android的hidden API,需要通过反射调用    var SP = Java.use("android.os.SystemProperties");    SP.get.overload('java.lang.String').implementation = function (p1) {    	var tmp = this.get(p1);    	console.log("[*]"+p1+" : "+tmp);    	return tmp;    }    SP.get.overload('java.lang.String', 'java.lang.String').implementation = function (p1,p2) {    	    	    	var tmp = this.get(p1,p2)    	console.log("[*]"+p1+","+p2+" : "+tmp);    	return tmp;    }     // hook MAC    var wifi = Java.use("android.net.wifi.WifiInfo");    wifi.getMacAddress.implementation = function () {    	var tmp = this.getMacAddress();    	console.log("[*]real MAC: "+tmp);    	return tmp;    }	})
    

    Hook 打印请求调用栈

    JSvar class_Socket = Java.use("java.net.Socket");class_Socket.getOutputStream.overload().implementation = function(){    send("getOutputSteam");    var result = this.getOutputStream();    var bt = Java.use("android.util.Log").getStackTraceString(        Java.use("java.lang.Exception").$new();    )    console.log("Backtrace:" + bt);    send(result);    return result;}
    

    Hook UI thread 注入

    JSJava.perform(function() {  var Toast = Java.use('android.widget.Toast');  var currentApplication = Java.use('android.app.ActivityThread').currentApplication();   var context = currentApplication.getApplicationContext();  Java.scheduleOnMainThread(function() {    Toast.makeText(context, "Hello World", Toast.LENGTH_LONG.value).show();  })})
    

    常用打印转换

    JS
    //工具相关函数
    var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
        base64DecodeChars = new Array((-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), 62, (-1), (-1), (-1), 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, (-1), (-1), (-1), (-1), (-1), (-1), (-1), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, (-1), (-1), (-1), (-1), (-1), (-1), 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, (-1), (-1), (-1), (-1), (-1));
    
    function stringToBase64(e) {
        var r, a, c, h, o, t;
        for (c = e.length, a = 0, r = ''; a < c;) {
            if (h = 255 & e.charCodeAt(a++), a == c) {
                r += base64EncodeChars.charAt(h >> 2),
                    r += base64EncodeChars.charAt((3 & h) << 4),
                    r += '==';
                break
            }
            if (o = e.charCodeAt(a++), a == c) {
                r += base64EncodeChars.charAt(h >> 2),
                    r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4),
                    r += base64EncodeChars.charAt((15 & o) << 2),
                    r += '=';
                break
            }
            t = e.charCodeAt(a++),
                r += base64EncodeChars.charAt(h >> 2),
                r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4),
                r += base64EncodeChars.charAt((15 & o) << 2 | (192 & t) >> 6),
                r += base64EncodeChars.charAt(63 & t)
        }
        return r
    }
    
    function base64ToString(e) {
        var r, a, c, h, o, t, d;
        for (t = e.length, o = 0, d = ''; o < t;) {
            do
                r = base64DecodeChars[255 & e.charCodeAt(o++)];
            while (o < t && r == -1);
            if (r == -1)
                break;
            do
                a = base64DecodeChars[255 & e.charCodeAt(o++)];
            while (o < t && a == -1);
            if (a == -1)
                break;
            d += String.fromCharCode(r << 2 | (48 & a) >> 4);
            do {
                if (c = 255 & e.charCodeAt(o++), 61 == c)
                    return d;
                c = base64DecodeChars[c]
            } while (o < t && c == -1);
            if (c == -1)
                break;
            d += String.fromCharCode((15 & a) << 4 | (60 & c) >> 2);
            do {
                if (h = 255 & e.charCodeAt(o++), 61 == h)
                    return d;
                h = base64DecodeChars[h]
            } while (o < t && h == -1);
            if (h == -1)
                break;
            d += String.fromCharCode((3 & c) << 6 | h)
        }
        return d
    }
    
    function hexToBase64(str) {
        return base64Encode(String.fromCharCode.apply(null, str.replace(/
    |
    /g, "").replace(/([da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" ")));
    }
    
    function base64ToHex(str) {
        for (var i = 0, bin = base64Decode(str.replace(/[ 
    ]+$/, "")), hex = []; i < bin.length; ++i) {
            var tmp = bin.charCodeAt(i).toString(16);
            if (tmp.length === 1)
                tmp = "0" + tmp;
            hex[hex.length] = tmp;
        }
        return hex.join("");
    }
    
    function hexToBytes(str) {
        var pos = 0;
        var len = str.length;
        if (len % 2 != 0) {
            return null;
        }
        len /= 2;
        var hexA = new Array();
        for (var i = 0; i < len; i++) {
            var s = str.substr(pos, 2);
            var v = parseInt(s, 16);
            hexA.push(v);
            pos += 2;
        }
        return hexA;
    }
    
    function bytesToHex(arr) {
        var str = '';
        var k, j;
        for (var i = 0; i < arr.length; i++) {
            k = arr[i];
            j = k;
            if (k < 0) {
                j = k + 256;
            }
            if (j < 16) {
                str += "0";
            }
            str += j.toString(16);
        }
        return str;
    }
    
    function stringToHex(str) {
        var val = "";
        for (var i = 0; i < str.length; i++) {
            if (val == "")
                val = str.charCodeAt(i).toString(16);
            else
                val += str.charCodeAt(i).toString(16);
        }
        return val
    }
    
    function stringToBytes(str) {
        var ch, st, re = [];
        for (var i = 0; i < str.length; i++) {
            ch = str.charCodeAt(i);
            st = [];
            do {
                st.push(ch & 0xFF);
                ch = ch >> 8;
            }
            while (ch);
            re = re.concat(st.reverse());
        }
        return re;
    }
    
    //将byte[]转成String的方法
    function bytesToString(arr) {
        var str = '';
        arr = new Uint8Array(arr);
        for (var i in arr) {
            str += String.fromCharCode(arr[i]);
        }
        return str;
    }
    
    function bytesToBase64(e) {
        var r, a, c, h, o, t;
        for (c = e.length, a = 0, r = ''; a < c;) {
            if (h = 255 & e[a++], a == c) {
                r += base64EncodeChars.charAt(h >> 2),
                    r += base64EncodeChars.charAt((3 & h) << 4),
                    r += '==';
                break
            }
            if (o = e[a++], a == c) {
                r += base64EncodeChars.charAt(h >> 2),
                    r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4),
                    r += base64EncodeChars.charAt((15 & o) << 2),
                    r += '=';
                break
            }
            t = e[a++],
                r += base64EncodeChars.charAt(h >> 2),
                r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4),
                r += base64EncodeChars.charAt((15 & o) << 2 | (192 & t) >> 6),
                r += base64EncodeChars.charAt(63 & t)
        }
        return r
    }
    
    function base64ToBytes(e) {
        var r, a, c, h, o, t, d;
        for (t = e.length, o = 0, d = []; o < t;) {
            do
                r = base64DecodeChars[255 & e.charCodeAt(o++)];
            while (o < t && r == -1);
            if (r == -1)
                break;
            do
                a = base64DecodeChars[255 & e.charCodeAt(o++)];
            while (o < t && a == -1);
            if (a == -1)
                break;
            d.push(r << 2 | (48 & a) >> 4);
            do {
                if (c = 255 & e.charCodeAt(o++), 61 == c)
                    return d;
                c = base64DecodeChars[c]
            } while (o < t && c == -1);
            if (c == -1)
                break;
            d.push((15 & a) << 4 | (60 & c) >> 2);
            do {
                if (h = 255 & e.charCodeAt(o++), 61 == h)
                    return d;
                h = base64DecodeChars[h]
            } while (o < t && h == -1);
            if (h == -1)
                break;
            d.push((3 & c) << 6 | h)
        }
        return d
    }
    

    文章作者: Kevin
    文章链接: http://example.com/fridahookjava/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 凡墙总是门!

  • 相关阅读:
    hdu 3333 树状数组+离线处理
    poj 2352 树状数组 OR Treap
    hdu 1698 线段树
    【概率dp】D. Card Collector
    【分段哈希】H. Paint the Wall
    【置换】G. Poker 2.0
    【概率dp】C. Race to 1 Again
    【dp】D. Caesar's Legions
    【并查集】F.find the most comfortable road
    【算法系列学习】连续邮资问题
  • 原文地址:https://www.cnblogs.com/c-x-a/p/15294911.html
Copyright © 2020-2023  润新知