美文网首页
frida使用转载

frida使用转载

作者: le_du | 来源:发表于2022-10-20 16:23 被阅读0次

    转的ling 大佬的

    /*
    首先进行初始化,初始化一些函数地址
    hook功能
    1. java层hook
        a. hookOneMethod yes
        b. hookOneClass yes
        c. hookAllMethod
        d. hookAllMethod2
        e. hook_loadLibrary0
    
    2. jni层hook
        a. hook_JNIRegisterNatives
        b. hook_JNI_OnLoad
    
    3. native层hook
        a. hook_dlopen
        b. hook_libc_kill_exit
        c. hook_system_property
        d. hook_android_log_print
        e. hook_call_function
        f. hook_call_array
        g. hook_ArtMethod_Invoke  yes
        h. hook_ArtInterpreterToInterpreterBridge yes
        h. hook_ArtInterpreterToCompiledCodeBridge  yes
    
    4. objection的一些功能函数
        a. objection_getCurrentActivity yes
        b. objection_getActivities yes
    
    5. 脱壳
        a. dexdump_DefineClass 
        b. dexdump_DexCache yes
        c. dexdump_Dex
        d. dexdump_LoadMethod
    
    6. find功能
        a. find yes
        b. find2
        c. findClasses
    
    7. 莫名其妙的崩溃原因
        1. 添加了native的backtrace
    
    */
    //需要根据情况修改
    var is_spawn = 0
    var is_print_java_stackTrace = 1
    var hook_java_enter = 0; // 默认java 调用完之后输出log,如果方法调用完之前崩溃,是看不到输出日志的。要在调用前输出日志,设置为1.
    var is_print_native_stackTrace = 0
    var is_print_args = 1; // print args
    var is_print_retval = 1; // print retval
    
    var run_env_num = 1;
    
    var run_env = null;
    if (run_env_num == 1) {
        run_env = "arm"
    } else if (run_env_num == 2) {
        run_env = "arm64"
    } else if (run_env_num == 3) {
        run_env = "x86"
    }
    ////////////////////////////////
    //不需要修改
    var is_hooked = false;
    var context = null;
    var currentApplication = null;
    var StringClass = null;
    var Base64Class = null;
    var ins_all = [];
    var last_ins = null;
    var frida_major_version = null;
    var android_sdk_version = null;
    
    var has_save_permission = false;
    
    var module_libart = null;
    var DefineClass_addr = null;
    var LoadMethod_addr = null;
    var PrettyMethod_addr = null;
    var ArtMethodRegisterNative_addr = null;
    var JNIRegisterNatives_addr = null
    var is_print_art_param = 1; // 配置hook_ArtInterpreterToInterpreterBridge的参数和返回值,如果设置为0可以快速的查看函数调用
    var is_print_art_retval = 1;
    var ArtMethodInvoke_addr = null;
    var ArtInterpreterToCompiledCodeBridge_addr = null;
    var ArtInterpreterToInterpreterBridge_addr = null;
    var artQuickToInterpreterBridge_addr = null;
    var artQuickGenericJniTrampoline_addr = null;
    
    // 打印native的参数
    function print_native_log(user_log_list, tag) {
        if (tag == undefined) {
            tag = ""
        }
        var num = 20
        var start_symbol = "="
        var end_symbol = "-"
        var now = get_now()
        user_log_list.unshift(now)
        var log_start = new Array(num).join(start_symbol) + "[ThreadId:" + Process.getCurrentThreadId() + "]" + tag + " start!!!" + new Array(num).join(start_symbol)
        user_log_list.unshift(log_start)
        if (is_print_native_stackTrace) {
            // user_log_list.push(console.log('called from:\n'+Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
        }
        var log_end = new Array(num).join(end_symbol) + "[ThreadId:" + Process.getCurrentThreadId() + "]" + tag + " end!!!" + new Array(num).join(end_symbol)
        user_log_list.push(log_end)
        console.log(user_log_list.join("\n"));
    }
    
    function get_native_value(value_address, valuetype, index) {
        if (valuetype == undefined) {
            return "(" + valuetype + ")arg[" + index + "]";
        }
        valuetype = valuetype.replaceAll(" ", "")
        var name = "(" + valuetype + ")arg[" + index + "]";
        switch (valuetype) {
            case "int":
                name = name + ptr(value_address) + "=>" + value_address.readUInt()
                break
            case "long":
                name = name + ptr(value_address) + "=>" + value_address.readLong()
                break
            case "byte":
                name = name + ptr(value_address) + "=>" + value_address.readU8()
                break
            case "byte[]":
                if (value_address.readUInt() == 0x0) {
                    // 空指针
                    name = name + ptr(value_address) + "=>" + "bytes0x0:null"
                } else {
                    var tmp_value_address = ptr(value_address.readUInt()).add(0xc)
                    var byte_length = ptr(value_address.readUInt()).add(0x8).readUInt()
                    // var result = tmp_value_address.readByteArray(byte_length)
                    // name = name + ptr(value_address) + "=> byte_length:" +byte_length+"---result:"+hexdump(tmp_value_address,{length:byte_length})
                    var array = []
                    if (byte_length > 100) {
                        var print_byte_length = 100
                    } else {
                        var print_byte_length = byte_length
                    }
    
                    for (var i = 0; i < print_byte_length; i++) {
                        array.push(tmp_value_address.add(i).readU8())
                    }
                    var canToString = checkByteArrayFromString(array);
                    if (canToString) {
                        var param = Java.use("java.lang.String").$new(array)
                        var result = "[string]:" + param
                    } else {
                        var param_hex = bytesToHex(array);
                        var result = "[hex]:0x" + param_hex
                    }
                    name = name + ptr(value_address) + "=> byte_length:" + byte_length + "---result:" + result
                    // name = name + ptr(value_address) + "=> byte_length:" +byte_length+"---result:"+result+"\r\n"+hexdump(tmp_value_address)
                }
                break
            case "char":
                name = name + ptr(value_address) + "=>" + value_address.readU8()
                break
            case "float":
                // console.log(hexdump(value_address))
                name = name + ptr(value_address) + "=>" + value_address.readFloat()
                break
            case "boolean":
                name = name + ptr(value_address) + "=>" + value_address.readPointer()
                break
            case "java.lang.String":
                // try {
                // if (ptr(value_address).readU32() != 0x0) {
                //     var string_len = ptr(ptr(value_address).readU32()).add(0x8).readUInt() / 2
                //     console.log("String != 0x0"+"\r\n"+hexdump(value_address)+"\r\n"+hexdump(ptr(ptr(value_address).readU32()))+"\r\n"+hexdump(ptr(ptr(ptr(value_address).readU32()).readU32()))+"---len:"+string_len)
                //     name = name + ptr(value_address) + "=>" + ptr(ptr(value_address).readU32()).add(0x10).readCString(string_len)
                // } else if (ptr(value_address).readU32() == 0x8) {
                //     console.log("String == 0x8")
                //     name = name + ptr(value_address) + "=>" + ptr(value_address).add(0x10).readCString()
                // } else {
                // name = name + ptr(value_address) + "=>" + value_address
                // }
                // } catch (e) {
                //     console.log("error=======>" + e + " value_address=>" + value_address + "\r\n" + hexdump(value_address))
                // name = name + ptr(value_address) + "=>" + value_address
                // }
                
                try {
                    if (ptr(value_address).readU32() == 0x0) {
                        // console.log("String == 0x8")
                        // console.log(hexdump(value_address))
                        // var string_len = ptr(ptr(value_address).readU32()).add(0x8).readUInt() / 2
                        // name = name + ptr(value_address) + "=>" + ptr(value_address).add(0x10).readCString()
                        name = name + ptr(value_address) + "=>string0x0:null"
                    } else if (ptr(value_address).readU32() == 0x8) {
                        name = name + ptr(value_address) + "=>string0x8:" + "\r\n" + hexdump((value_address)) + "\r\n"
                    }
                    else if (ptr(value_address).readU32() != 0x0) {
                        // console.log(hexdump(ptr(ptr(value_address).readU32())))
                        var string_len = ptr(ptr(value_address).readU32()).add(0x8).readUInt() / 2
                        name = name + ptr(value_address) + "=>" + ptr(ptr(value_address).readU32()).add(0x10).readCString(string_len)
                    } else {
                        // name = name + ptr(value_address) + "=>stringothers:" + value_address + "\r\n" + hexdump(ptr(ptr(value_address).readU32()))
                        name = name + ptr(value_address) + "=>stringothers:" + hexdump(value_address)
                    }
                } catch (e) {
                    console.log("error=======>" + value_address + "\r\n" + e + "   " + ptr(value_address.readUInt()) + "\r\n" + hexdump(value_address) + "\r\n")
                    name = name + ptr(value_address) + "=>" + value_address
                }
                // name = name + ptr(value_address) + "=>" + "\r\n" + hexdump(value_address) + "\r\n" + "ptr(value_address).readU32()" + ptr(value_address).readU32()
                break
            case "void":
                break
            default:
                name = name + ptr(value_address) + "=>" + value_address
        }
        return name
    }
    
    // 获取当前时间
    function get_now() {
        var date = new Date()
        var year = date.getFullYear()
        var month = date.getMonth()
        var day = date.getDate()
        var hour = date.getHours()
        var min = date.getMinutes()
        var seconds = date.getSeconds()
        var millsec = date.getMilliseconds()
        var result1 = [year, month, day]
        var result2 = [hour, min, seconds, millsec]
        return "[CurrentTime]" + result1.join("-") + " " + result2.join(":")
    }
    // 将java的参数和返回值组装打印
    function print_java_log(user_log_list, tag) {
        Java.performNow(function () {
            if (tag == undefined) {
                tag = ""
            }
            var num = 20
            var start_symbol = "="
            var end_symbol = "-"
            var now = get_now()
            user_log_list.unshift(now)
            var log_start = new Array(num).join(start_symbol) + "[ThreadId:" + Process.getCurrentThreadId() + "]" + tag + " start!!!" + new Array(num).join(start_symbol)
            user_log_list.unshift(log_start)
            if (is_print_java_stackTrace) {
                user_log_list.push(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()))
            }
            var log_end = new Array(num).join(end_symbol) + "[ThreadId:" + Process.getCurrentThreadId() + "]" + tag + " end!!!" + new Array(num).join(end_symbol)
            user_log_list.push(log_end)
            console.log(user_log_list.join("\n"));
        })
    }
    function get_java_value(param, paramType, i) {
        var result = ""
        var name = null;
        if (i == undefined) {
            name = "(" + paramType + ")retval";
        } else {
            name = "(" + paramType + ")arg[" + i + "]";
        }
        if (param == null) {
            return name + " = null"
        }
        switch (paramType) {
            case "[C"://TODO
            case "[B":
                var canToString = checkByteArrayFromString(param);
                if (canToString) {
                    result = name + " _bytearray= " + StringClass.$new(param)
                } else {
                    var param_hex = bytesToHex(param);
                    result = name + "_hex = " + param_hex
                }
                break;
            case "[I":
                result = name + "=" + JSON.stringify(param)
                // var canToString = checkByteArrayFromString(param);
                // if (canToString) {
                //     result = name + " _bytearray= " + StringClass.$new(param)
                // } else {
                //     var param_hex = bytesToHex(param);
                //     result = name + "_hex = " + param_hex
                // }
                break;
            case "java.util.Map":
            case "Ljava/util/Map;":
                var keys = param.keySet().toArray()
                var obj = {}
                for (var j = 0; j < keys.length; j++) {
                    var value = param.get(keys[j])
                    obj[keys[j]] = value.toString()
                }
                result = name + "=" + JSON.stringify(obj)
                break;
            case "java.util.List":
                var list = []
                for(var i = 0;i<param.length;i++){
                    list.push(param[i])
                }
                result = name + "=" + new Array(list).join(",")
                break
            case "java.security.Key":
                var param_bytearray = param.getEncoded();
                var canToString = checkByteArrayFromString(param_bytearray);
                if (canToString) {
                    result = name + "_key_str= " + StringClass.$new(param_bytearray)
                } else {
                    var param_hex = bytesToHex(param_bytearray);
                    result = name + "_key_hex = " + param_hex
                }
                break;
            case "java.security.spec.AlgorithmParameterSpec":
            case "Ljavax/crypto/spec/IvParameterSpec;":
                var IVClass = Java.use("javax.crypto.spec.IvParameterSpec");
                var ivObject = Java.cast(param, IVClass);
                var ivByte = ivObject.getIV();
                var canToString = checkByteArrayFromString(ivByte);
                if (canToString) {
                    result = name + "_iv_str= " + StringClass.$new(ivByte)
                } else {
                    var param_hex = bytesToHex(ivByte);
                    result = name + "_iv_hex = " + param_hex
                }
                break;
            case "Ljavax/crypto/spec/SecretKeySpec;":
                var keyByte = param.getEncoded();
                var canToString = checkByteArrayFromString(keyByte);
                if (canToString) {
                    result = name + "_key_str= " + StringClass.$new(keyByte)
                } else {
                    var param_hex = bytesToHex(keyByte);
                    result = name + "_key_hex = " + param_hex
                }
                break
            case "okio.BufferedSink":
            // result = name + "=" + param.buffer().readUtf8()
            // break
            default:
                result = name + "=" + param
                break;
        }
        return result
    }
    function isVisible(value) {
        if (value >= 32 && value <= 126) {
            return true;
        }
        return false;
    }
    function checkByteArrayFromString(bytearray) {
        var bytearray0 = Java.array("byte", bytearray);
        for (var i = 0; i < bytearray0.length; i++) {
            if (isVisible(bytearray[i]) == false) {
                return false;
            }
        }
        return true;
    }
    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;
    }
    /*
    hook一个方法,根据正则,过滤重载
    hookOneMethod("java.net.URL.$init")
    hookOneMethod("android.util.Base64.encodeToString")
    hookOneMethod("javax.crypto.Cipher.doFinal","[B")
    */
    function hookOneMethod(fullMethodName, overloadFilter) {
        /*
            hookOneMethod("java.net.URL.$init") // trace all method of $init
            hookOneMethod("java.net.URL.$init","java.lang.String") 
            hookOneMethod("java.net.URL.$init","java.net.URL,java.lang.String")
        */
        var split_length = fullMethodName.split(".").length;
        var method = fullMethodName.split(".")[split_length - 1];
        var classname = fullMethodName.slice(0, fullMethodName.length - method.length - 1); // -1是为了去掉那个点
        Java.performNow(function () {
            var tmpClass = Java.use(classname);
            if (tmpClass[method] == undefined) {
            } else {
                tmpClass[method].overloads.forEach(function (m) {
                    var argumentTypes = m.argumentTypes;
                    var returnType = m.returnType.name;
                    var parameterStrArray = [];
                    for (var tmpArg of argumentTypes) {
                        parameterStrArray.push(tmpArg["className"]);
                    }
                    if (overloadFilter != undefined && overloadFilter != parameterStrArray.join(",")) {
                        // console.log("your overloadFilter do not match")
                        return true
                    } else {
                        console.log("hooking " + classname + "." + method + "(" + parameterStrArray.join(",") + ")");
                        m.implementation = function () {
                            var user_log_list = []
                            var user_log_list = ["called " + classname + "." + method + "(" + parameterStrArray.join(",") + ")"]
                            for (var i = 0; i < arguments.length; i++) {
                                if (is_print_args) {
                                    // if (arguments[i] == null) continue
                                    var tmp_java_value = get_java_value(arguments[i], parameterStrArray[i], i);
                                    user_log_list.push(tmp_java_value)
                                }
                            }
                            if (hook_java_enter) {
                                // user_log_list.push("java called before hook!")
                                print_java_log(user_log_list, classname)
                            }
                            var retval = m.apply(this, arguments);
                            if (is_print_retval) {
                                var tmp_java_value = get_java_value(retval, returnType);
                                user_log_list.push(tmp_java_value)
                            }
                            if (!hook_java_enter) {
                                // user_log_list.push("java called over hook!")
                                print_java_log(user_log_list, classname)
                            }
    
                            return retval;
                        };
                    }
                });
            }
        });
    }
    
    /*
    hook一个类,根据正则,过滤方法名和重载
    hookOneClass("javax.crypto.Cipher")
    hookOneClass("javax.crypto.Cipher","doFinal")
    hookOneClass("javax.crypto.Cipher","doFinal","[B")
    */
    function hookOneClass(fullClassName, methodFilter, overloadFilter) {
        Java.performNow(function () {
            var toBeHookingMethods = []
            var tmpClass = Java.use(fullClassName)
            var method_init_all = tmpClass.class.getDeclaredConstructors();
            if (method_init_all.length > 0) {
    
                if (methodFilter == undefined) {
                    toBeHookingMethods.push(fullClassName + ".$init")
                } else if (methodFilter != undefined && methodFilter == "$init") {
                    toBeHookingMethods.push(fullClassName + "." + "$init")
                }
            }
            var method_all = tmpClass.class.getDeclaredMethods()
            for (var i = 0; i < method_all.length; i++) {
                var tmpMethod = method_all[i]
                var tmpMethodName = tmpMethod.getName()
                if (methodFilter != undefined && tmpMethodName.indexOf(methodFilter) != -1) {
                    toBeHookingMethods.push(fullClassName + "." + tmpMethodName)
                } else if (methodFilter == undefined) {
                    toBeHookingMethods.push(fullClassName + "." + tmpMethodName)
                }
            }
            toBeHookingMethods = Array.from(new Set(toBeHookingMethods))
            console.log("[traceOneClass]toBeHookingMethods.length=", toBeHookingMethods.length)
            for (var i = 0; i < toBeHookingMethods.length; i++) {
                var method = toBeHookingMethods[i]
                hookOneMethod(method, overloadFilter)
            }
        })
    }
    function query(classname, method) {
        // query("Base64")
        // query("Cipher","doFinal")
        if (frida_major_version < 14) {
            console.log("frida major version must >= 14")
            return
        }
        var filterPattern = "*Base64*!*encode*";
        var groups = null;
        if (classname == undefined && method == undefined) {
            console.log("please enter classname or method");
            return groups;
        }
        if (!classname) {
            classname = "*";
        }
        if (!method) {
            method = "*";
        }
        var filterPattern = "*" + classname + "*" + "!" + "*" + method + "*";
        Java.performNow(function () {
            groups = Java.enumerateMethods(filterPattern);
        });
        return groups;
    }
    
    function find(classname, method) {
        /*
            find("*.Cipher") // find all classes endswith .Cipher
            find("","doFinal") // find all methods equal doFinal
            find("*Base64*","*encode*") // find all classes match Base64 and methods match encode
        */
        var groups = query(classname, method)
        if (groups != "") {
            for (var group of groups) {
                var classes = group["classes"];
                for (var cls of classes) {
                    var classname = cls["name"];
                    var methods = cls["methods"];
                    console.log("found class => " + classname);
                    for (var method of methods) {
                        console.log("found method => " + classname + "." + method);
                    }
                    console.log("found " + methods.length + " methods");
                }
            }
            console.log("search finished");
        } else {
            console.log("search finished and found 0 method");
        }
    }
    function hookAllMethod(classnameFilter, methodFilter, overloadFilter) {
        /*
            hookAllMethod2("Base64")  // trace all class match Base64
            hookAllMethod2("","encode","[B,int") // trace all class and method equals encode and overload equals [B,int
            hookAllMethod2("Base64","encode","[B,int") // trace  class match Base64 and method match encode and overload equals [B,int
        */
        var groups = query(classnameFilter, methodFilter)
        if (groups != "") {
            for (var group of groups) {
                var classes = group["classes"];
                for (var cls of classes) {
                    var classname = cls["name"];
                    var methods = cls["methods"];
                    for (var method of methods) {
                        var fullMethodName = classname + "." + method
                        console.log("string=>" + fullMethodName.toString())
                        try {
                            hookOneMethod(fullMethodName.toString(), overloadFilter);
                        } catch (e) {
    
                        }
                    }
                }
            }
        } else {
            console.log("search finished and found 0 method");
        }
    }
    
    // objection的获取当前Activity
    
    function R(name, type) {
        // const context = getApplicationContext();
        return context.getResources().getIdentifier(name, type, context.getPackageName());
    }
    function objection_getCurrentActivity() {
        Java.performNow(function () {
            const activityThread = Java.use("android.app.ActivityThread");
            const activity = Java.use("android.app.Activity");
            const activityClientRecord = Java.use("android.app.ActivityThread$ActivityClientRecord");
    
            const currentActivityThread = activityThread.currentActivityThread();
            const activityRecords = currentActivityThread.mActivities.value.values().toArray();
            let currentActivity;
    
            for (const i of activityRecords) {
                const activityRecord = Java.cast(i, activityClientRecord);
                if (!activityRecord.paused.value) {
                    currentActivity = Java.cast(Java.cast(activityRecord, activityClientRecord).activity.value, activity);
                    break;
                }
            }
    
            if (currentActivity) {
                console.log(currentActivity.$className)
                const fm = currentActivity.getFragmentManager();
                const fragment = fm.findFragmentById(R("content_frame", "id"));
                console.log(fragment.$className)
            }
        })
    }
    
    // objection的获取所有的Activities
    function objection_getActivities() {
        Java.performNow(function () {
            const packageManager = Java.use("android.content.pm.PackageManager");
            const GET_ACTIVITIES = packageManager.GET_ACTIVITIES.value;
            var ActivityThreadClass = Java.use("android.app.ActivityThread");
            var context = ActivityThreadClass.currentActivityThread().getApplication().getApplicationContext()
    
            context.getPackageManager().getPackageInfo(context.getPackageName(), GET_ACTIVITIES).activities.value.map((activityInfo) => {
                console.log(activityInfo.name.value)
            })
        })
    }
    // objection的获取所有的Services
    function objection_getServices() {
        Java.performNow(function () {
            var ActivityThreadClass = Java.use("android.app.ActivityThread");
            var ArrayMapClass = Java.use("android.util.ArrayMap");
            var PackageManagerClass = Java.use("android.content.pm.PackageManager");
            var GET_SERVICES = PackageManagerClass.GET_SERVICES.value;
            var currentApplication = ActivityThreadClass.currentApplication(); // not using the helper as we need other variables too
            var context = currentApplication.getApplicationContext();
            var services = [];
            currentApplication.mLoadedApk.value.mServices.value.values().toArray().map(function (potentialServices) {
                Java.cast(potentialServices, ArrayMapClass).keySet().toArray().map(function (service) {
                    services.push(service.$className);
                });
            });
            services = services.concat(context.getPackageManager().getPackageInfo(context.getPackageName(), GET_SERVICES).services.value.map(function (activityInfo) {
                console.log("find Service => " + activityInfo.name.value)
                return activityInfo.name.value;
            }));
        })
    }
    // objection的跳转Activity界面
    function objection_startActivity(activityName) {
        // https://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_NEW_TASK
        Java.performNow(function () {
            var FLAG_ACTIVITY_NEW_TASK = 0x10000000; // starts an Android activity
            var IntentClass = Java.use("android.content.Intent"); // Get the Activity class's .class
            var newActivity = Java.use(activityName);
            var newIntent = IntentClass.$new(context, newActivity.class);
            newIntent.setFlags(FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(newIntent);
        })
    }
    // objection的启动Service
    function objection_startService(serviceName) {
        // https://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_NEW_TASK
        Java.performNow(function () {
            var FLAG_ACTIVITY_NEW_TASK = 0x10000000; // starts an Android activity
            var IntentClass = Java.use("android.content.Intent"); // Get the Activity class's .class
            var newService = Java.use(serviceName);
            console.log(newService.$className)
            var newIntent = IntentClass.$new(context, newService.class);
            newIntent.setFlags(FLAG_ACTIVITY_NEW_TASK);
            context.startService(newIntent);
        })
    }
    
    /*
    sslpinning 仅对系统的checkServerTrusted以及标准ok3的check进行hook,无法对抗混淆的以及其它的
    */
    function objection_sslpinning_disable_all() {
        sslpinning_disable_system()
        sslpinning_disable_okhttp3()
    }
    
    function sslpinning_disable_system() {
        Java.performNow(function () {
            var PlatformClass = Java.use("com.android.org.conscrypt.Platform")
            var targetMethodName = "checkServerTrusted"
            var overloadsLength = PlatformClass[targetMethodName].overloads.length;
            for (var i = 0; i < overloadsLength; ++i) {
                PlatformClass[targetMethodName].overloads[i].implementation = function () {
                    console.log("com.android.org.conscrypt.Platform.checkServerTrusted->i=" + i + " arguments=" + JSON.stringify(arguments))
                }
            }
        })
    }
    
    function sslpinning_disable_okhttp3() {
        Java.performNow(function () {
            var CertificatePinnerClass = Java.use("okhttp3.CertificatePinner")
            var targetMethodName = "check"
            var overloadsLength = CertificatePinnerClass[targetMethodName].overloads.length;
            for (var i = 0; i < overloadsLength; ++i) {
                CertificatePinnerClass[targetMethodName].overloads[i].implementation = function () {
                    console.log("okhttp3.CertificatePinner.check->i=" + i + " arguments=" + JSON.stringify(arguments))
                }
            }
        })
    }
    /*
    hook root检测,但是仍然不全
    */
    function objection_root_disable_all() {
        root_disable_testKeysCheck()
        root_disable_execSuCheck()
        root_disable_fileExistsCheck()
    }
    
    function root_disable_testKeysCheck() {
        Java.performNow(function () {
            var JavaString = Java.use("java.lang.String");
            JavaString.contains.implementation = function (name) {
                //这个太局限了
                if (name !== "test-keys") {
                    return this.contains.call(this, name);
                } else {
                    return false
                }
            };
        })
    }
    
    function root_disable_execSuCheck() {
        Java.performNow(function () {
            var JavaRuntime = Java.use("java.lang.Runtime");
            var iOException = Java.use("java.io.IOException");
            JavaRuntime.exec.overload("java.lang.String").implementation = function (command) {
                if (command.endsWith("su")) {
                    console.log("called endsWith su")
                } // call the original method
                if (command.indexOf("su") != -1) {
                    console.log("called indexOf su")
                }
                return this.exec.overload("java.lang.String").call(this, command);
            };
        })
    }
    
    function root_disable_fileExistsCheck() {
        Java.performNow(function () {
            var commonPaths = ["/data/local/bin/su", "/data/local/su", "/data/local/xbin/su", "/dev/com.koushikdutta.superuser.daemon/", "/sbin/su", "/system/app/Superuser.apk", "/system/bin/failsafe/su", "/system/bin/su", "/system/etc/init.d/99SuperSUDaemon", "/system/sd/xbin/su", "/system/xbin/busybox", "/system/xbin/daemonsu", "/system/xbin/su"];
            var JavaFile = Java.use("java.io.File");
            JavaFile.exists.implementation = function () {
                var filename = this.getAbsolutePath();
                if (commonPaths.indexOf(filename) >= 0) {
                    console.log("called JavaFile exists =>" + filename)
                }
                return this.exists.call(this);
            }
        })
    }
    
    // 获取当前app的包名
    function getPackageName() {
        var packageName = null;
        Java.performNow(function () {
            if (is_spawn) {
                packageName = get_self_process_name();
            } else {
                packageName = context.getPackageName()
                var packageName1 = context.getBasePackageName()
                console.log("context.getBasePackageName()=", packageName1)
            }
        })
        return packageName
    }
    
    //对一个jni函数进行demangle
    function demangle(name) {
        // demangle("_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi")
        // extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*);
        var __cxa_demangle = DebugSymbol.fromName("__cxa_demangle").address;
        var func_demangle = new NativeFunction(__cxa_demangle, "pointer", ["pointer", "pointer", "pointer", "pointer"])
        // var str = Memory.allocUtf8String("_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi");
        var str = Memory.allocUtf8String(name);
        var result = func_demangle(new NativePointer(ptr(str)), ptr(0), ptr(0), ptr(0));
        // console.log((result).readCString())
        return result.readCString()
        // console.log(JSON.stringify(Module.enumerateSymbols("libart.so")))
    }
    
    //模仿wallbreaker的dumpClass
    function LookupClass(classFullName) {
        Java.performNow(function () {
            var tmpClass = Java.use(classFullName)
            var packageName = tmpClass.class.getPackage().getName()
            var field_all = tmpClass.class.getDeclaredFields();
            var Modifier = Java.use("java.lang.reflect.Modifier");
            var user_log_list = []
            var classObj = {
                "static_fileds": [],
                "ins_fields": [],
                "contructor_methods": [],
                "static_methods": [],
                "methods": []
            }
            for (var i = 0; i < field_all.length; i++) {
                var field = field_all[i]
                var fieldType = field.getType().getName();
                var fieldName = field.getName();
                var isStatic = Modifier.isStatic(field.getModifiers())
                if (isStatic) {
                    var fieldValue = tmpClass[fieldName].value;
                    classObj["static_fileds"].push({
                        "key": fieldType + " " + fieldName,
                        // "key": field,
                        "value": fieldValue
                    })
                } else {
                    classObj["ins_fields"].push({
                        "key": fieldType + " " + fieldName,
                        "value": null
                    })
                }
            }
            var method_init_all = tmpClass.class.getDeclaredConstructors();
            for (var i = 0; i < method_init_all.length; i++) {
                var method_init = method_init_all[i]
                var method_init_str = method_init.toString().split("throws")[0].trim()
                // var method_init_ReturnType = method_init.getReturnType()
                var method_init_ParameterTypes = method_init.getParameterTypes()
                var method_init_ParameterTypesStr = getParameterTypesToString(method_init_ParameterTypes)
                var method_init_str = "$init(" + method_init_ParameterTypesStr + ")"
                // var methodName = method.getName()
                classObj["contructor_methods"].push(method_init_str)
            }
            var method_all = tmpClass.class.getDeclaredMethods();
            for (var i = 0; i < method_all.length; i++) {
                var method = method_all[i]
                var methodStr = method.toString().split("throws")[0].trim()
                var methodReturnType = method.getReturnType().getName()
                var methodName = method.getName()
                var methodParameterTypes = method.getParameterTypes()
                var method_ParameterTypesStr = getParameterTypesToString(methodParameterTypes)
                var method_str = methodReturnType + " " + methodName + " (" + method_ParameterTypesStr + ")"
                var isStatic = Modifier.isStatic(method.getModifiers())
                if (isStatic) {
                    // classObj["static_methods"].push("(" + methodReturnType + ") " + methodName+" ("+methodParameterTypes)
                    classObj["static_methods"].push(method_str)
                } else {
                    // console.log("ins value=",fieldName,ins[fieldName].value)
                    classObj["methods"].push(method_str)
                }
            }
            //开始打印classObj
            var user_log_list = []
            var tab = new Array(8).join(" ")
            user_log_list.push("package " + packageName + ";")
            console.log(classFullName.slice(classFullName.indexOf(packageName)))
            user_log_list.push("class " + classFullName.slice(packageName.length + 1) + " {")
            user_log_list.push("")
            user_log_list.push(tab + "/* static fields */")
            var static_fileds = classObj["static_fileds"]
            for (var i = 0; i < static_fileds.length; i++) {
                var tmpField = static_fileds[i]
                var tmpFieldName = tmpField["key"]
                var tmpFieldValue = tmpField["value"]
                user_log_list.push(tab + tmpFieldName + " => " + tmpFieldValue)
            }
            user_log_list.push("")
            user_log_list.push(tab + "/* instance fields */")
            var ins_fields = classObj["ins_fields"]
            for (var i = 0; i < ins_fields.length; i++) {
                var tmpField = ins_fields[i]
                var tmpFieldName = tmpField["key"]
                var tmpFieldValue = tmpField["value"]
                user_log_list.push(tab + tmpFieldName + " => " + tmpFieldValue)
            }
            user_log_list.push("")
            user_log_list.push(tab + "/* constructor methods */")
            var contructor_methods = classObj["contructor_methods"]
            for (var i = 0; i < contructor_methods.length; i++) {
                var contructor_method = contructor_methods[i]
                user_log_list.push(tab + contructor_method)
            }
            user_log_list.push("")
            user_log_list.push(tab + "/* static methods */")
            var static_methods = classObj["static_methods"]
            for (var i = 0; i < static_methods.length; i++) {
                var static_method = static_methods[i]
                user_log_list.push(tab + static_method)
            }
            user_log_list.push("")
            user_log_list.push(tab + "/* methods */")
            var methods = classObj["methods"]
            for (var i = 0; i < methods.length; i++) {
                var method = methods[i]
                user_log_list.push(tab + method)
            }
            user_log_list.push("}")
            print_java_log(user_log_list, classFullName)
        })
    }
    
    function getParameterTypesToString(parameterTypes) {
        var result = []
        for (var i = 0; i < parameterTypes.length; i++) {
            var tmpType = parameterTypes[i]
            var typeName = tmpType.getName()
            result.push(typeName)
        }
        return result.join(", ")
    }
    
    function get_self_process_name() {
        var openPtr = Module.getExportByName('libc.so', 'open');
        var open = new NativeFunction(openPtr, 'int', ['pointer', 'int']);
        var readPtr = Module.getExportByName("libc.so", "read");
        var read = new NativeFunction(readPtr, "int", ["int", "pointer", "int"]);
        var closePtr = Module.getExportByName('libc.so', 'close');
        var close = new NativeFunction(closePtr, 'int', ['int']);
        var path = Memory.allocUtf8String("/proc/self/cmdline");
        var fd = open(path, 0);
        if (fd != -1) {
            var buffer = Memory.alloc(0x1000);
            var result = read(fd, buffer, 0x1000);
            close(fd);
            result = ptr(buffer).readCString();
            return result;
        }
        return "-1";
    }
    
    function mkdir(path) {
        var mkdirPtr = Module.getExportByName('libc.so', 'mkdir');
        var mkdir = new NativeFunction(mkdirPtr, 'int', ['pointer', 'int']);
        var opendirPtr = Module.getExportByName('libc.so', 'opendir');
        var opendir = new NativeFunction(opendirPtr, 'pointer', ['pointer']);
        var closedirPtr = Module.getExportByName('libc.so', 'closedir');
        var closedir = new NativeFunction(closedirPtr, 'int', ['pointer']);
        var cPath = Memory.allocUtf8String(path);
        var dir = opendir(cPath);
        if (dir != 0) {
            closedir(dir);
            return 0;
        }
        mkdir(cPath, 755);
        chmod(path);
    }
    
    function chmod(path) {
        var chmodPtr = Module.getExportByName('libc.so', 'chmod');
        var chmod = new NativeFunction(chmodPtr, 'int', ['pointer', 'int']);
        var cPath = Memory.allocUtf8String(path);
        chmod(cPath, 755);
    }
    
    function save_permission() {
        var save_permission = false
        try {
            var dex_path = "/sdcard/lingzhiyi_test.txt";
            // var dex_path = "/data/data/"+getPackageName()+"/lingzhiyi_test.txt";
            var fd = new File(dex_path, "wb");
            fd.write("hello");
            fd.flush();
            fd.close()
            save_permission = true;
        } catch (e) {
            // console.log(e)
        }
        return save_permission
    }
    
    function dexdump_DexCache() {
        Java.performNow(function () {
            var dex_count = 1;
            Java.choose("java.lang.DexCache", {
                onMatch: function (ins) {
                    var name = "" // 不过滤
                    // var name = get_self_process_name() // 开启,只在包含当前包名的路劲过滤
                    if (ins.location.value.indexOf(name) != -1) {
                        var save_name = ins.location.value.replaceAll("/", "_").replaceAll(".", "_").replaceAll(":", "_").replaceAll("!", "_").replaceAll("-", "_")
                        var dex_file = ins.dexFile.value
                        var base = ptr(dex_file).add(Process.pointerSize).readPointer();
                        var size = ptr(dex_file).add(Process.pointerSize + Process.pointerSize).readUInt();
                        var magic = ptr(base).readCString();
                        if (magic.indexOf("dex") == 0) {
                            var process_name = get_self_process_name();
                            if (process_name != "-1") {
                                if (has_save_permission) {
                                    var dex_dir_path = "/sdcard/" + "dumpdex_" + process_name;
                                    mkdir(dex_dir_path);
                                }
                                else {
                                    var dex_dir_path = "/data/data/" + process_name; // no save permission
                                }
                                var dex_path = dex_dir_path + "/dumpdex_" + save_name + "_DexCache.dex";
                                var fd = new File(dex_path, "wb");
                                if (fd && fd != null) {
                                    dex_count++;
                                    var dex_buffer = ptr(base).readByteArray(size);
                                    fd.write(dex_buffer);
                                    fd.flush();
                                    fd.close();
                                    console.log("[dump dex]:", dex_path);
                                }
                            }
                        }
                    }
                },
                onComplete: function () { }
            })
        })
    }
    
    function dexdump_Frida() {
        Process.enumerateRanges("r--").forEach(range => {
            // {"base":"0x70e67000","size":2707456,"protection":"r-x","file":{"path":"/system/framework/arm64/boot.oat","offset":757760,"size":0}}
            if (range.file && range.file.path && (range.file.path.startsWith("/system/") || range.file.path.startsWith("/data/dalvik-cache") || range.file.path.startsWith("/dev/kg"))) {
                return
            } else {
                // console.log(JSON.stringify(range))
            }
            try {
                Memory.scanSync(range.base, range.size, "64 65 78 0a 30 ?? ?? 00").forEach(function (match) {
                    var base = match.address
                    var size = base.add(0x20).readUInt()
                    var buffer = ptr(base).readByteArray(size)
                    var path = range.file.path.replaceAll("/", "_").replaceAll("-", "_").replaceAll("=", "_").replaceAll(".", "_")
                    if (has_save_permission) {
                        var savepath = "/sdcard/" + "dumpdex_" + get_self_process_name();
                        mkdir(savepath);
                    }
                    else {
                        var savepath = "/data/data/" + get_self_process_name(); // no save permission
                    }
                    var dex_file_name = savepath + "/dumpdex_" + path + "_frida.dex"
                    var file = new File(dex_file_name, "wb")
                    file.write(buffer)
                    file.flush()
                    file.close()
                    console.log("dump=>" + dex_file_name)
                })
            }
            catch (e) {
                console.log(e)
            }
        })
        console.log("dumpdex_frida finished~")
    }
    
    function readStdString(str) {
        const isTiny = (str.readU8() & 1) == 0;
        if (isTiny) {
            return str.add(1).readUtf8String();
        }
        return str.add(2 * Process.pointerSize).readPointer().readUtf8String();
    }
    
    function callprettymethod_x86(artmethodptr) {
        var ArtMethodPrettyMethodaddr = Module.findExportByName("libart.so", "_ZN3art12PrettyMethodEPNS_9ArtMethodEb");
        var ArtMethodPrettyMethodfunc = new NativeFunction(ArtMethodPrettyMethodaddr, "pointer", ["pointer", "pointer", "bool"]);
        var strptr = Memory.alloc(64);
        var ArtMethodName = null;
        if (strptr != null) {
            ArtMethodPrettyMethodfunc(ptr(strptr), ptr(artmethodptr), 1);
            ArtMethodName = readStdString(strptr);
            return ArtMethodName;
        }
        return null;
    }
    
    function callPrettyMethod_new(ArtMethodptr) {
        var PrettyMethodfunc = new NativeFunction(PrettyMethod_addr, ["pointer", "pointer", "pointer"], ["pointer", "int"]);
        var result = PrettyMethodfunc(ArtMethodptr, 1);
        var stdstring = Memory.alloc(3 * Process.pointerSize);
        ptr(stdstring).writePointer(result[0]);
        ptr(stdstring).add(1 * Process.pointerSize).writePointer(result[1]);
        ptr(stdstring).add(2 * Process.pointerSize).writePointer(result[2]);
        var result = readStdString(stdstring)
        // console.log("ArtMethodptr="+ArtMethodptr+"----result="+result)
        return result
    }
    
    // 同时安卓7的artMethod没有PrettyMethod
    function callPrettyMethod_arm32(artmethodptr) {
        var ArtMethodPrettyMethodfunc = new NativeFunction(PrettyMethod_addr, "pointer", ["pointer", "pointer", "pointer"]);
        var strptr = Memory.alloc(256);
        var ArtMethodName = null;
        if (strptr != null) {
            ArtMethodPrettyMethodfunc(ptr(strptr), ptr(artmethodptr), ptr(1));
            ArtMethodName = readStdString(strptr);
            return ArtMethodName;
        }
        return null;
    }
    var method_name_all = []
    // var method_name_all_set  = Array.from(new Set(method_name_all)) // 通过该方法去重获取都调用了哪些方法
    function ArtMethodInvoke_filter(methodname) {
        if (methodname == null) {
            return methodname
        }
        method_name_all.push(methodname)
        var method_filter_all = ["android.view", "java.lang.ref", "android.content.res.Configuration", "android.os.BinderProxy", "java.lang.String.intern", "java.util.Locale", "android.os.Binder", "android.graphics", "android.system", "java.lang.ClassNotFoundException", "java.lang.NoSuchFieldError", "android.widget", "dalvik.system.VMStack", "java.lang.System", "java.lang.StringBuilder.append", "java.lang.Object.<init>", "java.net.InetAddress", "android.hardware"]
    
        var filter = false
        for (var i = 0; i < method_filter_all.length; i++) {
            if (methodname.indexOf(method_filter_all[i]) != -1) {
                filter = true
                break
            }
        }
        // filter = false
        if (!filter) {
            // console.log("enter InvokeWithArgArray callded methodname->" + methodname)
            return "enter InvokeWithArgArray callded methodname->" + methodname
        }
        return null;
    }
    
    function hook_ArtMethod_Invoke() {
        if (Process.arch == "ia32") {
            ArtMethodInvoke_addr = DebugSymbol.fromName("_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc").address;
        }
        // void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result, const char* shorty)
        Interceptor.attach(ArtMethodInvoke_addr, {
            onEnter: function (args) {
                this.user_log_list = []
                this.called_method = args[0]
                this.vregs_ = args[2]
                this.result = args[4]
                var keep = 1
                var filter_methodname = "SharedPreferences"
                // this.user_log_list.push("onEnter ArtMethodInvoke [this.method_args_size]=" + this.method_args_size)
                if (Process.arch == "ia32") {
                    // 模拟器安卓7.0
                    this.methodname = callprettymethod_x86((this.called_method));
                } else {
                    this.methodname = callPrettyMethod_new((this.called_method));
                }
                if (is_print_native_stackTrace) {
                    this.user_log_list.push(('called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
                }
                this.flag = (keep && (this.methodname.indexOf(filter_methodname) != -1)) || (!keep)
                // try {
                if (this.flag) {
                    this.user_log_list.push("current_called->" + this.methodname)
                    // print_native_log(this.user_log_list,"ArtInterpreterToInterpreterBridge")
                    // console.log("enter ArtInterpreterToInterpreterBridge=>access_flags_value:"+access_flags_value_+"---called:"+prettymethod_name+"---number_of_vregs_:"+number_of_vregs_.readUInt())
                }
                // } catch (e) {
                //     console.log("ArtMethodInvoke_addr error=======>", e, called_method)
                // }
    
                // 在此处进行休眠附加调试
                if (this.methodname.indexOf("._ts_getRequestHeader") != -1) {
                    console.log("正在调用_ts_getRequestHeader函数,休眠60s 尽快ida或者gdb去附加调试")
                    // sleep(60)
                }
            }, onLeave: function (retval) {
                if (is_print_art_param) {
                    if (this.flag) {
                        var access_flags = ptr(this.called_method).add(0x4)
                        var access_flags_value = access_flags.readU16()
                        var access_flags_value_ = get_access_flag(access_flags_value)
    
                        if (access_flags_value_ != access_flags_value) {
                            var args_list_str = this.methodname.split("(")[1].split(")")[0]
                            if (args_list_str.length == 0) {
                                var args_len = 0
                            } else {
                                var args_list_name = args_list_str.split(",")
                                var args_len = args_list_name.length
                            }
                            var origin_len = args_len
                            var start_index = 0
                            var is_not_static = 0
                            if (access_flags_value_.indexOf("static") != -1) {
                                // 说明是静态方法
                                this.user_log_list.push("is static")
                            } else {
                                // 非静态,是实例方法,第一个参数
                                start_index += 1
                                is_not_static = 1
                                args_len += 1
                                this.user_log_list.push("is instance")
                            }
                            var offset = 0
                            if (origin_len == 0x0) {
                                // 说明参数个数为0
                                // this.user_log_list.push("参数个数为0")
                            } else {
                                // this.user_log_list.push("参数个数为"+args_len+"   origin_len="+origin_len)
                                for (; start_index < args_len; start_index++) {
                                    var arg_name = args_list_name[start_index - is_not_static]
                                    var address = ptr(this.vregs_).add(4 * start_index + offset)
                                    var print_name = get_native_value(address, arg_name, start_index - is_not_static)
                                    this.user_log_list.push(print_name)
                                    if (arg_name.indexOf("long") != -1) {
                                        offset += 4
                                    }
                                }
                            }
                        } else {
                            //todo
                        }
                        this.user_log_list.push("called_access_flags_value:" + access_flags_value_.toString(16))
                        this.user_log_list.push("called:" + this.methodname)
                    }
                }
    
                if (this.flag) {
                    if (is_print_art_retval) {
                        this.return_type = this.methodname.split(" ")[0]
                        if (this.return_type != "void") {
                            var print_name = get_native_value(this.result, this.return_type, "return")
                            if (print_name != null) {
                                this.user_log_list.push(print_name)
                            }
                        }
                    }
                    print_native_log(this.user_log_list, "onLeave [libart.so => ArtMethodInvoke]=" + ArtMethodInvoke_addr)
                }
            }
        })
    }
    
    function hook_ArtMethod_RegisterNative() {
        // var ArtMethodRegisterNative_addr = Module.findExportByName("libart.so", "_ZN3art9ArtMethod14RegisterNativeEPKvb");
        // console.log("ArtMethodRegisterNative_addr=",ArtMethodRegisterNative_addr)
        Interceptor.attach(ArtMethodRegisterNative_addr, {
            onEnter: function (args) {
                this.artmethod = args[0];
                var methodname = callPrettyMethod_new(ptr(this.artmethod));
                if (methodname.indexOf("MainActivity.onCreate") != -1) {
                    console.log("find MainActivity.onCreate ready to sleep 60s")
                    // sleep(60)
                }
                // var methodname = (ptr(this.artmethod));
                var address = args[1];
                this.dex_method_index_ = ptr(this.artmethod).add(12).readU32();
                var current_module = Process.getModuleByAddress(address)
                var modulename = current_module.name
                var base = current_module.base
                var offset = address.sub(base)
                console.log("go into ArtMethodRegisterNative---" + "artmethodptr:" + ptr(this.artmethod) + "---methodidx:" + this.dex_method_index_ + "--addr:" + address + "----name:" + methodname + "---modulename:" + modulename + "---offset:" + offset);
            }, onLeave: function (retval) {
            }
        })
    }
    
    function is_java_func_static(java_func_name) {
        if (java_func_name.indexOf("<") != -1) {
            return false
        }
        var result = false
        Java.performNow(function () {
            var java_func_name_split = java_func_name.split(".")
            var classname_array = []
            var java_func_short_name = java_func_name_split[java_func_name_split.length - 1]
            for (var i = 0; i < java_func_name_split.length - 1; i++) {
                classname_array.push(java_func_name_split[i])
            }
            var classname = classname_array.join(".")
            var tmpClass = Java.use(classname)
            var Modifier = Java.use("java.lang.reflect.Modifier");
            var method_all = tmpClass.class.getDeclaredMethods();
            for (var i = 0; i < method_all.length; i++) {
                var method = method_all[i]
                var methodName = method.getName()
                if (methodName == java_func_short_name) {
                    var isStatic = Modifier.isStatic(method.getModifiers())
                    result = isStatic
                }
            }
        })
        return result
    }
    
    function can_hexdump(addr) {
        var range = Process.findRangeByAddress(addr)
        if (range != null) {
            return hexdump(addr) + "\r\n"
        } else {
            return addr + "\r\n"
        }
    }
    
    /*
    so加载后会执行init,initarray以及JNI_OnLoad,动态注册一般会放在JNI_OnLoad中
    */
    function hook_JNI_OnLoad() {
        // jint JNI_OnLoad(JavaVM *vm, void *reserved)
        // var JNI_Onload_addr = DebugSymbol.fromName("JNI_OnLoad").address;
        var JNI_Onload_addr = Module.findExportByName("libmedia_jni.so", "JNI_OnLoad");
        // var JNI_Onload_addr = Module.findExportByName(null,"JNI_OnLoad");
        console.log("JNI_Onload_addr=", JNI_Onload_addr)
        Interceptor.attach(JNI_Onload_addr, {
            onEnter: function (args) {
                // console.log("enter JNI_Onload_addr")
            },
            onLeave: function (retval) {
                // console.log("leave JNI_Onload_addr")
            }
        })
    }
    /*
    对动态加载的dex,可以在这里进行hook,或者是更底层
    */
    function hook_loadLibrary0() {
        Java.performNow(function () {
            Java.use("java.lang.Runtime").loadLibrary0.implementation = function (classloader, sopath) {
                // hook_InvokeWithArgArray_x86()
                var result = this.loadLibrary0(classloader, sopath);
                var user_log_list = []
                user_log_list.push("[classloader]=" + classloader)
                user_log_list.push("[sopath]=" + sopath)
                print_log(user_log_list, "java.lang.Runtime.loadLibrary0")
                // try{
                //     if(classloader.findClass("com.taobao.wireless.security.adapter.JNICLibrary")!=-1){
                //         Java.classFactory.loader = classloader
                //         // hookOneClass("com.taobao.wireless.security.adapter.JNICLibrary")
                //         hookOneMethod("com.taobao.wireless.security.adapter.JNICLibrary.doCommandNative")
                //     }
                // }catch(e){
                // }
                return result;
            }
        })
    }
    
    function get_access_flag(i) {
        // var j = parseInt(i)
        var result = i
        var dict = {
            0x1: "public",
            0x2: "private",
            0x4: "protected",
            0x8: "static",
            0x9: "public static",
            0xa: "private static",
            0x10: "final",
            0x11: "public final",
            0x12: "private final",
            0x19: "public final static",
            0x1a: "private final static",
            0x101: "public native",
            0x102: "private native",
            0x109: "public static native",
            0x10a: "private static native",
            0x111: "public final native",
            0x112: "private final native",
            0x119: "public final static native",// 0x1 0x10 0x8 0x100
            0x11a: "private final static native",// 0x2 0x10 0x8 0x100
            0x1008: "Synthetic static ",// 0x8 0x1000
        }
        if (dict[i] != undefined) {
            var result = dict[i]
        }
        return result
    }
    
    function hook_ArtInterpreterToInterpreterBridge() {
        // var ArtInterpreterToInterpreterBridge_addr = Module.findExportByName("libart.so", "_ZN3art11interpreter33ArtInterpreterToInterpreterBridgeEPNS_6ThreadEPKNS_7DexFile8CodeItemEPNS_11ShadowFrameEPNS_6JValueE")
        Interceptor.attach(ArtInterpreterToInterpreterBridge_addr, {
            onEnter: function (args) {
                // try {
                this.keep = 1
                var filter_name = "android.app.SharedPreferencesImpl.getString"
                this.user_log_list = []
                var codeitem = args[1]
                // this.user_log_list.push(hexdump(codeitem)) 
                this.callee_frame = args[2]
                this.JValue_result = args[3]
                if (is_print_native_stackTrace) {
                    // this.user_log_list.push(('called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
                }
                var callee_frame = this.callee_frame
                var called_method = ptr(callee_frame).add(Process.pointerSize).readPointer();
                var prettymethod_name = callPrettyMethod_new(called_method)
                // console.log("ArtInterpreterToInterpreterBridge->"+prettymethod_name)
                // return 
                this.prettymethod_name = prettymethod_name
                this.flag = (this.keep && prettymethod_name.indexOf(filter_name) != -1) || (!this.keep)
                this.return_type = prettymethod_name.split(" ")[0]
                if (this.flag) {
                    this.user_log_list.push("current_called->" + prettymethod_name)
                }
                if (is_print_art_param) {
                    if (this.flag) {
                        var access_flags = ptr(called_method).add(0x4)
                        var access_flags_value = access_flags.readU16()
                        var access_flags_value_ = get_access_flag(access_flags_value)
                        // console.log(called_method,hexdump(callee_frame),"\r\n",hexdump(called_method))
                        var number_of_vregs_ = ptr(callee_frame).add(Process.pointerSize * 6);
                        var vregs_ = ptr(callee_frame).add(Process.pointerSize * 6).add(12)
                        if (access_flags_value_ != access_flags_value) {
                            var args_list_str = prettymethod_name.split("(")[1].split(")")[0]
                            if (args_list_str.length == 0) {
                                var args_len = 0
                            } else {
                                var args_list_name = args_list_str.split(",")
                                var args_len = args_list_name.length
                            }
                            var origin_len = args_len
                            var start_index = 0
                            var is_static = 0
                            if (access_flags_value_.indexOf("static") != -1) {
                                // 说明是静态方法
                                this.user_log_list.push("is static~~~")
                            } else {
                                // 非静态,是实例方法,第一个参数
                                start_index += 1
                                is_static = 1
                                args_len += 1
                                this.user_log_list.push("is instance~~~")
                            }
                            var offset = 0
                            if (origin_len == 0x0) {
                                // 说明参数个数为0
                                // this.user_log_list.push("参数个数为0")
                            } else {
                                // this.user_log_list.push("参数个数为"+args_len+"   origin_len="+origin_len)
                                for (; start_index < args_len; start_index++) {
                                    var arg_name = args_list_name[start_index - is_static]
                                    var address = ptr(vregs_).add(4 * start_index + offset)
                                    var print_name = get_native_value(address, arg_name, start_index - is_static)
                                    this.user_log_list.push(print_name)
                                    if (arg_name.indexOf("long") != -1) {
                                        offset += 4
                                    }
                                }
                            }
                        } else {
                            //todo
                        }
                        this.user_log_list.push("called_access_flags_value:" + access_flags_value_.toString(16))
                        this.user_log_list.push("called:" + prettymethod_name)
                        // print_native_log(this.user_log_list, "ArtInterpreterToInterpreterBridge")
                        // console.log("enter ArtInterpreterToInterpreterBridge=>access_flags_value:"+access_flags_value_+"---called:"+prettymethod_name+"---number_of_vregs_:"+number_of_vregs_.readUInt())
                    }
                }
    
                // } catch (e) {
                //     console.log("ArtInterpreterToInterpreterBridge error=======>", e, called_method)
                // }
            },
            onLeave: function (retval) {
                if (this.flag) {
                    if (is_print_art_retval) {
                        if (this.return_type != "void") {
                            var print_name = get_native_value(this.JValue_result, this.return_type, "return")
                            if (print_name != null) {
                                this.user_log_list.push(print_name)
                            }
                        }
                        // if (this.JValue_result != 0x0) {
                        //     this.user_log_list.push("this.JValue_result=")
                        //     this.user_log_list.push(hexdump(this.JValue_result))
                        //     // console.log("this.JValue_result=",hexdump(this.JValue_result))
                        // }
                    }
                    print_native_log(this.user_log_list, "ArtInterpreterToInterpreterBridge")
                }
    
            }
        })
    
    }
    
    function hook_ArtInterpreterToCompiledCodeBridge() {
        Interceptor.attach(ArtInterpreterToCompiledCodeBridge_addr, {
            onEnter: function (args) {
                // try {
                var keep = 1
                var filter_name = "android.app.SharedPreferencesImpl"
                this.caller_method = args[1]
                this.callee_frame = args[2]
                this.JValue_result = args[4]
                this.user_log_list = []
                if (is_print_native_stackTrace) {
                    // 崩溃的原因是这个
                    // this.user_log_list.push(('called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
                }
                var caller_method = this.caller_method // caller_method可能是0x0
                var callee_frame = this.callee_frame
                var called_method = ptr(callee_frame).add(Process.pointerSize).readPointer();
                var prettymethod_name = callPrettyMethod_new(called_method)
                // console.log("ArtInterpreterToCompiledCodeBridge->"+prettymethod_name)
                // return 0
    
                if (caller_method != 0x0) {
                    var prettymethod_name_caller = callPrettyMethod_new(caller_method)
                }
                this.flag = (keep && ((prettymethod_name.indexOf(filter_name) != -1) || (caller_method != 0x0 && prettymethod_name_caller.indexOf(filter_name) != -1))) || (!keep)
                if (this.flag) {
                    // java_init()
                    // java_hook_wrapper()
                    // console.log("args=",args[0],args[1],args[2],args[3],args[4])
                    this.user_log_list.push("current_called->" + prettymethod_name)
                }
                this.return_type = prettymethod_name.split(" ")[0]
                if (is_print_art_param) {
                    if (this.flag) {
                        if (caller_method != 0x0) {
                            var caller_access_flags = ptr(caller_method).add(0x4)
                            var caller_access_flags_value = caller_access_flags.readU16()
                            var caller_access_flags_value_ = get_access_flag(caller_access_flags_value)
                        }
                        var called_access_flags = ptr(called_method).add(0x4)
                        var called_access_flags_value = called_access_flags.readU16()
                        var called_access_flags_value_ = get_access_flag(called_access_flags_value)
                        var number_of_vregs_ = ptr(callee_frame).add(Process.pointerSize * 6);
                        var vregs_ = ptr(callee_frame).add(Process.pointerSize * 6).add(12)
    
    
                        if (called_access_flags_value != called_access_flags_value_) {
                            var args_list_str = prettymethod_name.split("(")[1].split(")")[0]
                            if (args_list_str.length == 0) {
                                var args_len = 0
                            } else {
                                var args_list_name = args_list_str.split(",")
                                var args_len = args_list_name.length
                            }
                            var origin_len = args_len
                            var start_index = 0
                            var is_not_static = 0
                            if (called_access_flags_value_.indexOf("static") != -1) {
                                // 说明是静态方法
                                this.user_log_list.push("is static!!!!")
                            } else {
                                // 非静态,是实例方法,第一个参数
                                start_index += 1
                                is_not_static = 1
                                args_len += 1
                                this.user_log_list.push("is instance!!!!")
                            }
                            var offset = 0
                            if (origin_len == 0x0) {
                                // 说明参数个数为0
                                // this.user_log_list.push("参数个数为0")
                            } else {
                                // this.user_log_list.push("参数个数为"+args_len+"   origin_len="+origin_len)
                                for (; start_index < args_len; start_index++) {
                                    var arg_name = args_list_name[start_index - is_not_static]
                                    var address = ptr(vregs_).add(4 * start_index + offset)
                                    var print_name = get_native_value(address, arg_name, start_index - is_not_static)
                                    this.user_log_list.push(print_name)
                                    if (arg_name.indexOf("long") != -1) {
                                        offset += 4
                                    }
                                }
                            }
                        } else {
                            //todo
                        }
                        if (caller_method != 0x0) {
                            this.user_log_list.push("caller_access_flags_value:" + caller_access_flags_value_.toString(16))
                            this.user_log_list.push("caller:" + prettymethod_name_caller)
                        } else {
                            this.user_log_list.push("caller:" + "0x0")
                        }
                        this.user_log_list.push("called_access_flags_value:" + called_access_flags_value_.toString(16))
                        this.user_log_list.push("called:" + prettymethod_name)
                        // print_native_log(this.user_log_list, "ArtInterpreterToCompiledCodeBridge")
                    }
                }
                // } catch (e) {
                //     console.log("ArtInterpreterToCompiledCodeBridge error=======>", e, caller_method, called_method)
                // }
            },
            onLeave: function (retval) {
                if (this.flag) {
                    if (is_print_art_retval) {
                        // if(this.return_type!="void" && this.JValue_result != 0x0){
                        // console.log(this.return_type)
                        // console.log(this.JValue_result)
                        if (this.return_type != "void") {
                            var print_name = get_native_value(this.JValue_result, this.return_type, "return")
                            if (print_name != null) {
                                this.user_log_list.push(print_name)
                            }
                        }
    
                        //     this.user_log_list.push(print_name)
                        // console.log(print_name)
                        // if (this.JValue_result != 0x0) {
                        //     this.user_log_list.push("this.JValue_result=")
                        //     this.user_log_list.push(hexdump(this.JValue_result))
                        // }
                        // }
                    }
                    print_native_log(this.user_log_list, "ArtInterpreterToCompiledCodeBridge")
                }
            }
        })
    }
    
    function hook_Art_Interpreter_Invoke() {
        // 总共有四种情况的执行方法
        /*
            1. 机器码->机器码
            2. 机器码->解释执行
            3. 解释执行->解释执行
            4. 解释执行->机器码
        */
        // 1. 机器码->机器码
        // extern "C" TwoWordReturn artQuickGenericJniTrampoline(Thread* self, ArtMethod** sp)
        Interceptor.attach(artQuickGenericJniTrampoline_addr, {
            onEnter: function (args) {
                // try {
                this.keep = 0
                var filter_name = "Request"
                this.user_log_list = []
                // this.callee_frame = args[2]
                // this.JValue_result = args[3]
                if (is_print_native_stackTrace) {
                    this.user_log_list.push(('called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
                }
                // var callee_frame = this.callee_frame
                var called_method = args[1].readPointer()
                var prettymethod_name = callPrettyMethod_new(called_method)
                // console.log("ArtInterpreterToInterpreterBridge->"+prettymethod_name)
                // return 
                this.prettymethod_name = prettymethod_name
                this.flag = (this.keep && prettymethod_name.indexOf(filter_name) != -1) || (!this.keep)
                this.return_type = prettymethod_name.split(" ")[0]
                if (this.flag) {
                    this.user_log_list.push("current_called->" + prettymethod_name)
                }
                if (is_print_art_param) {
                    return
                    if (this.flag) {
                        var access_flags = ptr(called_method).add(0x4)
                        var access_flags_value = access_flags.readU16()
                        var access_flags_value_ = get_access_flag(access_flags_value)
                        // console.log(called_method,hexdump(callee_frame),"\r\n",hexdump(called_method))
                        var number_of_vregs_ = ptr(callee_frame).add(Process.pointerSize * 6);
                        var vregs_ = ptr(callee_frame).add(Process.pointerSize * 6).add(12)
                        if (access_flags_value_ != access_flags_value) {
                            var args_list_str = prettymethod_name.split("(")[1].split(")")[0]
                            if (args_list_str.length == 0) {
                                var args_len = 0
                            } else {
                                var args_list_name = args_list_str.split(",")
                                var args_len = args_list_name.length
                            }
                            var origin_len = args_len
                            var start_index = 0
                            var is_static = 0
                            if (access_flags_value_.indexOf("static") != -1) {
                                // 说明是静态方法
                                this.user_log_list.push("is static~~~")
                            } else {
                                // 非静态,是实例方法,第一个参数
                                start_index += 1
                                is_static = 1
                                args_len += 1
                                this.user_log_list.push("is instance~~~")
                            }
                            var offset = 0
                            if (origin_len == 0x0) {
                                // 说明参数个数为0
                                // this.user_log_list.push("参数个数为0")
                            } else {
                                // this.user_log_list.push("参数个数为"+args_len+"   origin_len="+origin_len)
                                for (; start_index < args_len; start_index++) {
                                    var arg_name = args_list_name[start_index - is_static]
                                    var address = ptr(vregs_).add(4 * start_index + offset)
                                    var print_name = get_native_value(address, arg_name, start_index - is_static)
                                    this.user_log_list.push(print_name)
                                    if (arg_name.indexOf("long") != -1) {
                                        offset += 4
                                    }
                                }
                            }
                        } else {
                            //todo
                        }
                        this.user_log_list.push("called_access_flags_value:" + access_flags_value_.toString(16))
                        this.user_log_list.push("called:" + prettymethod_name)
                        // print_native_log(this.user_log_list, "ArtInterpreterToInterpreterBridge")
                        // console.log("enter ArtInterpreterToInterpreterBridge=>access_flags_value:"+access_flags_value_+"---called:"+prettymethod_name+"---number_of_vregs_:"+number_of_vregs_.readUInt())
                    }
                }
    
                // } catch (e) {
                //     console.log("ArtInterpreterToInterpreterBridge error=======>", e, called_method)
                // }
            },
            onLeave: function (retval) {
                if (this.flag) {
                    print_native_log(this.user_log_list, "artQuickGenericJniTrampoline")
                }
    
            }
        })
    
        // 2. 机器码->解释执行
        // extern "C" uint64_t artQuickToInterpreterBridge(ArtMethod* method, Thread* self, ArtMethod** sp)
        Interceptor.attach(artQuickToInterpreterBridge_addr, {
            onEnter: function (args) {
                // try {
                var keep = 0
                var filter_name = "get2"
                this.caller_method = args[2].readPointer()
                // this.callee_frame = args[2]
                // this.JValue_result = args[4]
                this.user_log_list = []
                if (is_print_native_stackTrace) {
                    // 崩溃的原因是这个
                    this.user_log_list.push(('called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
                }
                var caller_method = this.caller_method // caller_method可能是0x0
                // var callee_frame = this.callee_frame
                var called_method = args[0]
                var prettymethod_name = callPrettyMethod_new(called_method)
                // console.log("ArtInterpreterToCompiledCodeBridge->"+prettymethod_name)
                // return 0
    
                if (caller_method != 0x0) {
                    var prettymethod_name_caller = callPrettyMethod_new(caller_method)
                }
                this.flag = (keep && ((prettymethod_name.indexOf(filter_name) != -1) || (caller_method != 0x0 && prettymethod_name_caller.indexOf(filter_name) != -1))) || (!keep)
                if (this.flag) {
                    // console.log("args=",args[0],args[1],args[2],args[3],args[4])
                    this.user_log_list.push("current_called->" + prettymethod_name)
                }
                this.return_type = prettymethod_name.split(" ")[0]
                if (is_print_art_param) {
                    if (this.flag) {
                        return
                        if (caller_method != 0x0) {
                            var caller_access_flags = ptr(caller_method).add(0x4)
                            var caller_access_flags_value = caller_access_flags.readU16()
                            var caller_access_flags_value_ = get_access_flag(caller_access_flags_value)
                        }
                        var called_access_flags = ptr(called_method).add(0x4)
                        var called_access_flags_value = called_access_flags.readU16()
                        var called_access_flags_value_ = get_access_flag(called_access_flags_value)
                        var number_of_vregs_ = ptr(callee_frame).add(Process.pointerSize * 6);
                        var vregs_ = ptr(callee_frame).add(Process.pointerSize * 6).add(12)
    
    
                        if (called_access_flags_value != called_access_flags_value_) {
                            var args_list_str = prettymethod_name.split("(")[1].split(")")[0]
                            if (args_list_str.length == 0) {
                                var args_len = 0
                            } else {
                                var args_list_name = args_list_str.split(",")
                                var args_len = args_list_name.length
                            }
                            var origin_len = args_len
    
                            var start_index = 0
                            var is_not_static = 0
                            if (called_access_flags_value_.indexOf("static") != -1) {
                                // 说明是静态方法
                                this.user_log_list.push("is static!!!!")
                            } else {
                                // 非静态,是实例方法,第一个参数
                                start_index += 1
                                is_not_static = 1
                                args_len += 1
                                this.user_log_list.push("is instance!!!!")
                            }
                            var offset = 0
                            if (origin_len == 0x0) {
                                // 说明参数个数为0
                                // this.user_log_list.push("参数个数为0")
                            } else {
                                // this.user_log_list.push("参数个数为"+args_len+"   origin_len="+origin_len)
                                for (; start_index < args_len; start_index++) {
                                    var arg_name = args_list_name[start_index - is_not_static]
                                    var address = ptr(vregs_).add(4 * start_index + offset)
                                    var print_name = get_native_value(address, arg_name, start_index - is_not_static)
                                    this.user_log_list.push(print_name)
                                    if (arg_name.indexOf("long") != -1) {
                                        offset += 4
                                    }
                                }
                            }
                        } else {
                            //todo
                        }
                        if (caller_method != 0x0) {
                            this.user_log_list.push("caller_access_flags_value:" + caller_access_flags_value_.toString(16))
                            this.user_log_list.push("caller:" + prettymethod_name_caller)
                        } else {
                            this.user_log_list.push("caller:" + "0x0")
                        }
                        this.user_log_list.push("called_access_flags_value:" + called_access_flags_value_.toString(16))
                        this.user_log_list.push("called:" + prettymethod_name)
                        // print_native_log(this.user_log_list, "ArtInterpreterToCompiledCodeBridge")
                    }
                }
                // } catch (e) {
                //     console.log("ArtInterpreterToCompiledCodeBridge error=======>", e, caller_method, called_method)
                // }
            },
            onLeave: function (retval) {
                if (this.flag) {
                    print_native_log(this.user_log_list, "artQuickToInterpreterBridge")
                }
            }
        })
    
        // return 
        // 3. 解释执行->解释执行
        Interceptor.attach(ArtInterpreterToInterpreterBridge_addr, {
            onEnter: function (args) {
                // try {
                this.keep = 0
                var filter_name = "Request"
                this.user_log_list = []
                this.callee_frame = args[2]
                this.JValue_result = args[3]
                if (is_print_native_stackTrace) {
                    this.user_log_list.push(('called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
                }
                var callee_frame = this.callee_frame
                var called_method = ptr(callee_frame).add(Process.pointerSize).readPointer();
                var prettymethod_name = callPrettyMethod_new(called_method)
                // console.log("ArtInterpreterToInterpreterBridge->"+prettymethod_name)
                // return 
                this.prettymethod_name = prettymethod_name
                this.flag = (this.keep && prettymethod_name.indexOf(filter_name) != -1) || (!this.keep)
                this.return_type = prettymethod_name.split(" ")[0]
                if (this.flag) {
                    this.user_log_list.push("current_called->" + prettymethod_name)
                }
                if (is_print_art_param) {
                    if (this.flag) {
                        var access_flags = ptr(called_method).add(0x4)
                        var access_flags_value = access_flags.readU16()
                        var access_flags_value_ = get_access_flag(access_flags_value)
                        // console.log(called_method,hexdump(callee_frame),"\r\n",hexdump(called_method))
                        var number_of_vregs_ = ptr(callee_frame).add(Process.pointerSize * 6);
                        var vregs_ = ptr(callee_frame).add(Process.pointerSize * 6).add(12)
                        if (access_flags_value_ != access_flags_value) {
                            var args_list_str = prettymethod_name.split("(")[1].split(")")[0]
                            if (args_list_str.length == 0) {
                                var args_len = 0
                            } else {
                                var args_list_name = args_list_str.split(",")
                                var args_len = args_list_name.length
                            }
                            var origin_len = args_len
                            var start_index = 0
                            var is_static = 0
                            if (access_flags_value_.indexOf("static") != -1) {
                                // 说明是静态方法
                                this.user_log_list.push("is static~~~")
                            } else {
                                // 非静态,是实例方法,第一个参数
                                start_index += 1
                                is_static = 1
                                args_len += 1
                                this.user_log_list.push("is instance~~~")
                            }
                            var offset = 0
                            if (origin_len == 0x0) {
                                // 说明参数个数为0
                                // this.user_log_list.push("参数个数为0")
                            } else {
                                // this.user_log_list.push("参数个数为"+args_len+"   origin_len="+origin_len)
                                for (; start_index < args_len; start_index++) {
                                    var arg_name = args_list_name[start_index - is_static]
                                    var address = ptr(vregs_).add(4 * start_index + offset)
                                    var print_name = get_native_value(address, arg_name, start_index - is_static)
                                    this.user_log_list.push(print_name)
                                    if (arg_name.indexOf("long") != -1) {
                                        offset += 4
                                    }
                                }
                            }
                        } else {
                            //todo
                        }
                        this.user_log_list.push("called_access_flags_value:" + access_flags_value_.toString(16))
                        this.user_log_list.push("called:" + prettymethod_name)
                        // print_native_log(this.user_log_list, "ArtInterpreterToInterpreterBridge")
                        // console.log("enter ArtInterpreterToInterpreterBridge=>access_flags_value:"+access_flags_value_+"---called:"+prettymethod_name+"---number_of_vregs_:"+number_of_vregs_.readUInt())
                    }
                }
    
                // } catch (e) {
                //     console.log("ArtInterpreterToInterpreterBridge error=======>", e, called_method)
                // }
            },
            onLeave: function (retval) {
                if (this.flag) {
                    if (is_print_art_retval) {
                        if (this.return_type != "void") {
                            var print_name = get_native_value(this.JValue_result, this.return_type, "return")
                            if (print_name != null) {
                                this.user_log_list.push(print_name)
                            }
                        }
                        // if (this.JValue_result != 0x0) {
                        //     this.user_log_list.push("this.JValue_result=")
                        //     this.user_log_list.push(hexdump(this.JValue_result))
                        //     // console.log("this.JValue_result=",hexdump(this.JValue_result))
                        // }
                    }
                    print_native_log(this.user_log_list, "ArtInterpreterToInterpreterBridge")
                }
    
            }
        })
    
        // 4. 解释执行->机器码
        Interceptor.attach(ArtInterpreterToCompiledCodeBridge_addr, {
            onEnter: function (args) {
                // try {
                var keep = 0
                var filter_name = "get2"
                this.caller_method = args[1]
                this.callee_frame = args[2]
                this.JValue_result = args[4]
                this.user_log_list = []
                if (is_print_native_stackTrace) {
                    // 崩溃的原因是这个
                    this.user_log_list.push(('called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
                }
                var caller_method = this.caller_method // caller_method可能是0x0
                var callee_frame = this.callee_frame
                var called_method = ptr(callee_frame).add(Process.pointerSize).readPointer();
                var prettymethod_name = callPrettyMethod_new(called_method)
                // console.log("ArtInterpreterToCompiledCodeBridge->"+prettymethod_name)
                // return 0
    
                if (caller_method != 0x0) {
                    var prettymethod_name_caller = callPrettyMethod_new(caller_method)
                }
                this.flag = (keep && ((prettymethod_name.indexOf(filter_name) != -1) || (caller_method != 0x0 && prettymethod_name_caller.indexOf(filter_name) != -1))) || (!keep)
                if (this.flag) {
                    // console.log("args=",args[0],args[1],args[2],args[3],args[4])
                    this.user_log_list.push("current_called->" + prettymethod_name)
                }
                this.return_type = prettymethod_name.split(" ")[0]
                if (is_print_art_param) {
                    if (this.flag) {
                        if (caller_method != 0x0) {
                            var caller_access_flags = ptr(caller_method).add(0x4)
                            var caller_access_flags_value = caller_access_flags.readU16()
                            var caller_access_flags_value_ = get_access_flag(caller_access_flags_value)
                        }
                        var called_access_flags = ptr(called_method).add(0x4)
                        var called_access_flags_value = called_access_flags.readU16()
                        var called_access_flags_value_ = get_access_flag(called_access_flags_value)
                        var number_of_vregs_ = ptr(callee_frame).add(Process.pointerSize * 6);
                        var vregs_ = ptr(callee_frame).add(Process.pointerSize * 6).add(12)
    
    
                        if (called_access_flags_value != called_access_flags_value_) {
                            var args_list_str = prettymethod_name.split("(")[1].split(")")[0]
                            if (args_list_str.length == 0) {
                                var args_len = 0
                            } else {
                                var args_list_name = args_list_str.split(",")
                                var args_len = args_list_name.length
                            }
                            var origin_len = args_len
    
                            var start_index = 0
                            var is_not_static = 0
                            if (called_access_flags_value_.indexOf("static") != -1) {
                                // 说明是静态方法
                                this.user_log_list.push("is static!!!!")
                            } else {
                                // 非静态,是实例方法,第一个参数
                                start_index += 1
                                is_not_static = 1
                                args_len += 1
                                this.user_log_list.push("is instance!!!!")
                            }
                            var offset = 0
                            if (origin_len == 0x0) {
                                // 说明参数个数为0
                                // this.user_log_list.push("参数个数为0")
                            } else {
                                // this.user_log_list.push("参数个数为"+args_len+"   origin_len="+origin_len)
                                for (; start_index < args_len; start_index++) {
                                    var arg_name = args_list_name[start_index - is_not_static]
                                    var address = ptr(vregs_).add(4 * start_index + offset)
                                    var print_name = get_native_value(address, arg_name, start_index - is_not_static)
                                    this.user_log_list.push(print_name)
                                    if (arg_name.indexOf("long") != -1) {
                                        offset += 4
                                    }
                                }
                            }
                        } else {
                            //todo
                        }
                        if (caller_method != 0x0) {
                            this.user_log_list.push("caller_access_flags_value:" + caller_access_flags_value_.toString(16))
                            this.user_log_list.push("caller:" + prettymethod_name_caller)
                        } else {
                            this.user_log_list.push("caller:" + "0x0")
                        }
                        this.user_log_list.push("called_access_flags_value:" + called_access_flags_value_.toString(16))
                        this.user_log_list.push("called:" + prettymethod_name)
                        // print_native_log(this.user_log_list, "ArtInterpreterToCompiledCodeBridge")
                    }
                }
                // } catch (e) {
                //     console.log("ArtInterpreterToCompiledCodeBridge error=======>", e, caller_method, called_method)
                // }
            },
            onLeave: function (retval) {
                if (this.flag) {
                    if (is_print_art_retval) {
                        if (this.return_type != "void") {
                            var print_name = get_native_value(this.JValue_result, this.return_type, "return")
                            if (print_name != null) {
                                this.user_log_list.push(print_name)
                            }
                        }
                    }
                    print_native_log(this.user_log_list, "ArtInterpreterToCompiledCodeBridge")
                }
            }
        })
    
        // hook_ArtMethod_Invoke()
    
    }
    
    // 初始化java的一些函数和变量
    function java_init() {
        Java.performNow(function () {
            StringClass = Java.use("java.lang.String");
            Base64Class = Java.use("android.util.Base64");
            frida_major_version = Frida.version.split(".")[0];
            android_sdk_version = Java.use("android.os.Build$VERSION").SDK_INT.value;
            has_save_permission = save_permission();
            console.log("java_init finished~" + new Array(20).join("-"))
        })
    }
    
    // 初始化native层的一些函数和变量
    function native_init() {
        var temp_print = 0
        module_libart = Process.findModuleByName("libart.so");
        var module_libart_symbols = module_libart.enumerateSymbols()
        for (var index = 0; index < module_libart_symbols.length; index++) {
            var symbol = module_libart_symbols[index];
            var symbol_name = symbol.name;
            //这个DefineClass的函数签名是Android9的
            //_ZN3art11ClassLinker11DefineClassEPNS_6ThreadEPKcmNS_6HandleINS_6mirror11ClassLoaderEEERKNS_7DexFileERKNS9_8ClassDefE
            if (symbol_name.indexOf("ClassLinker") >= 0 && symbol_name.indexOf("DefineClass") >= 0 && symbol_name.indexOf("Thread") >= 0 && symbol_name.indexOf("DexFile") >= 0) {
                DefineClass_addr = symbol.address;
                if (temp_print) {
                    console.log("DefineClass_addr=", DefineClass_addr)
                }
            }
            // if (symbol.name.indexOf("ClassLinker") >= 0 && symbol.name.indexOf("LoadMethod") >= 0 && symbol.name.indexOf("DexFile") >= 0 && symbol.name.indexOf("ClassDataItemIterator") >= 0 && symbol.name.indexOf("ArtMethod") >= 0) {}
            if (symbol.name.indexOf("ClassLinker") >= 0 && symbol.name.indexOf("LoadMethod") >= 0 && symbol.name.indexOf("DexFile") >= 0 && symbol.name.indexOf("ArtMethod") >= 0) {
                LoadMethod_addr = symbol.address;
                if (temp_print) {
                    console.log("LoadMethod_addr=", LoadMethod_addr)
                }
            }
    
            if (symbol.name.indexOf("PrettyMethod") != -1 && symbol.name.indexOf("ArtMethod") != -1 && symbol.name.indexOf("art") != -1) {
                PrettyMethod_addr = symbol.address;
                if (temp_print) {
                    console.log("PrettyMethod_addr=", PrettyMethod_addr)
                }
            }
            if (symbol.name.indexOf("RegisterNativeMethod") == -1 && symbol.name.indexOf("ArtMethod") != -1 && symbol.name.indexOf("RegisterNative") != -1) {
                ArtMethodRegisterNative_addr = symbol.address;
                if (temp_print) {
                    console.log("ArtMethodRegisterNative_addr=", ArtMethodRegisterNative_addr)
                }
            }
            // _ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc 安卓8.1.0,安卓7.1.2
            if (symbol.name.indexOf("Invoke") != -1 && symbol.name.indexOf("_ZN3art9ArtMethod") != -1 && symbol.name.indexOf("Thread") != -1 && symbol.name.indexOf("JValue") != -1) {
                // console.log("func_name="+symbol.name,"demangle_name="+demangle(symbol.name))
                ArtMethodInvoke_addr = symbol.address;
                if (temp_print) {
                    console.log("ArtMethodInvoke_addr=", ArtMethodInvoke_addr)
                }
            }
            // _ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi
            if (symbol.name.indexOf("RegisterNatives") != -1 && symbol.name.indexOf("_ZN3art3JNI") != -1) {
                // console.log("func_name="+symbol.name,"demangle_name="+demangle(symbol.name))
                JNIRegisterNatives_addr = symbol.address;
                if (temp_print) {
                    console.log("JNIRegisterNatives_addr=", JNIRegisterNatives_addr)
                }
            }
            if (symbol.name.indexOf("ArtInterpreterToCompiledCodeBridge") != -1) {
                // console.log("func_name="+symbol.name,"demangle_name="+demangle(symbol.name))
                ArtInterpreterToCompiledCodeBridge_addr = symbol.address;
                if (temp_print) {
                    console.log("ArtInterpreterToCompiledCodeBridge_addr=", ArtInterpreterToCompiledCodeBridge_addr)
                }
            }
            if (symbol.name.indexOf("ArtInterpreterToInterpreterBridge") != -1) {
                // console.log("func_name="+symbol.name,"demangle_name="+demangle(symbol.name))
                ArtInterpreterToInterpreterBridge_addr = symbol.address;
                if (temp_print) {
                    console.log("ArtInterpreterToInterpreterBridge_addr=", ArtInterpreterToInterpreterBridge_addr)
                }
            }
            if (symbol.name.indexOf("artQuickToInterpreterBridge") != -1) {
                // console.log("func_name="+symbol.name,"demangle_name="+demangle(symbol.name))
                artQuickToInterpreterBridge_addr = symbol.address;
                if (temp_print) {
                    console.log("artQuickToInterpreterBridge_addr=", artQuickToInterpreterBridge_addr)
                }
            }
    
            if (symbol.name.indexOf("artQuickGenericJniTrampoline") != -1) {
                // console.log("func_name="+symbol.name,"demangle_name="+demangle(symbol.name))
                artQuickGenericJniTrampoline_addr = symbol.address;
                if (temp_print) {
                    console.log("artQuickGenericJniTrampoline_addr=", artQuickGenericJniTrampoline_addr)
                }
            }
        }
        console.log("native_init finished~" + new Array(20).join("-"))
    
    }
    
    function java_hook_wrapper() {
        Java.performNow(function () {
            var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
            if (currentApplication != null) {
                context = currentApplication.getApplicationContext();
                hook_java_user()
            } else {
                Java.use("android.app.ActivityThread").handleBindApplication.implementation = function (appBindData) {
                    var result = this.handleBindApplication(appBindData)
                    var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
                    context = currentApplication.getApplicationContext();
                    console.log("entered handleBindApplication")
                    hook_java_user()
                    return result
                }
                // Java.use("android.app.Activity").onCreate.overload('android.os.Bundle').implementation = function (bundle) {
                //     var result = this.onCreate(bundle)
                //     var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
                //     context = currentApplication.getApplicationContext();
                //     if (!is_hooked) {
                //         hook_java_user()
                //         is_hooked = true
                //     }
                //     return result
                // }
                // Java.use("android.content.ContextWrapper").attachBaseContext.implementation = function(context_){
                //     console.log("enter android.content.ContextWrapper.attachBaseContext")
                //     var result = this.attachBaseContext(context_)
                //     context = context_
                //     if(!is_hooked){
                //         hook_java_user()
                //         is_hooked=true
                //     }
                //     return result;
                // }
            }
            hook_java_system()
        })
    }
    
    function main() {
        java_init();
        java_hook_wrapper()
        native_init();
        native_hook(); // 去这里写native代码
    }
    
    //在这里写java的hook代码,不需要再包一层Java.perform了
    function java_hook_real() {
        // console.log(Java.use("android.app.ActivityThread").class.getClassLoader())
        // console.log(Java.enumerateClassLoadersSync())
    
    }
    
    
    
    function jstring2Str(jstring) {
        var ret;
        Java.perform(function () {
            var String = Java.use("java.lang.String");
            ret = Java.cast(jstring, String);
        });
        return ret;
    }
    
    function jbyteArray2Array(jbyteArray) {
        var ret;
        Java.perform(function () {
            var b = Java.use('[B');
            var buffer = Java.cast(jbyteArray, b);
            ret = Java.array('byte', buffer);
        });
        return ret;
    }
    
    // 在这里写native的hook代码
    function native_hook() {
        // hook_ArtMethod_RegisterNative()
        // hook_ArtMethod_Invoke()
        // hook_ArtInterpreterToInterpreterBridge()
        // hook_ArtInterpreterToCompiledCodeBridge()
    }
    
    // 在这里写java的hook代码
    function hook_java_user() {
        dexdump_DexCache()
        // hookOneMethod("com.yaotong.crackme.MainActivity.onCreate")
    }
    
    function hook_java_system() {
        // hookOneMethod("android.app.Application.attach")
        // hookOneMethod("java.io.File.$init")
        // hookOneClass("android.app.ActivityThread")
        // hookOneMethod("android.content.ContextWrapper.attachBaseContext")
        // hookOneMethod("android.app.Activity.attachBaseContext")
        // hookOneMethod("java.io.File.exists")
        // hookOneMethod("java.lang.Runtime.exec")
    }
    
    setImmediate(main)
    // 普通attach
    // frida -UF -l v20220603_hook.js  -o out.log
    // 普通spawn启动,需要修改包名
    // frida -U -f com.lingzhiyi.temp -l v20220603_hook.js -o out.log --no-pause
    // frida -U -f com.yaotong.crackme -l v20220603_hook.js -o out.log --no-pause
    // frida -U -f com.vnpay.t2p -l v20220603_hook.js -o out.log --no-pause
    // 使用ip加端口进行attach
    // frida -H 192.168.3.30:27043 -l v20220603_hook.js -o out.log
    // 使用ip加端口进行spawn,需要修改包名
    // frida -H 192.168.3.30:27043 -f com.lingzhiyi.learnencryptedsp -l v20220603_hook.js -o out.log --no-pause
    // 使用gadget模式,使用ip加端口的方式 安卓7直接在sdcard创建包名以加载gadget
    // frida -H 192.168.3.32:27043 -n Lingzhiyi -l v20220603_hook.js -o out.log
    // frida -H 127.0.0.1:27043 -f com.xingin.xhs --no-pause 
    

    相关文章

      网友评论

          本文标题:frida使用转载

          本文链接:https://www.haomeiwen.com/subject/zxmuzrtx.html