frida-android系统相关

监听点击事件

var jclazz = null;
var jobj = null;

function getObjClassName(obj) {
    if (!jclazz) {
        var jclazz = Java.use("java.lang.Class");
    }
    if (!jobj) {
        var jobj = Java.use("java.lang.Object");
    }
    return jclazz.getName.call(jobj.getClass.call(obj));
}

function watch(obj, mtdName) {
    var listener_name = getObjClassName(obj);
    var target = Java.use(listener_name);
    if (!target || !mtdName in target) {
        return;
    }
    // send("[WatchEvent] hooking " + mtdName + ": " + listener_name);
    target[mtdName].overloads.forEach(function (overload) {
        overload.implementation = function () {
            //send("[WatchEvent] " + mtdName + ": " + getObjClassName(this));
            console.log("[WatchEvent] " + mtdName + ": " + getObjClassName(this))
            return this[mtdName].apply(this, arguments);
        };
    })
}

function OnClickListener() {
    Java.perform(function () {

        //以spawn启动进程的模式来attach的话
        Java.use("android.view.View").setOnClickListener.implementation = function (listener) {
            if (listener != null) {
                watch(listener, 'onClick');
            }
            return this.setOnClickListener(listener);
        };

        //如果frida以attach的模式进行attch的话
        Java.choose("android.view.View$ListenerInfo", {
            onMatch: function (instance) {
                instance = instance.mOnClickListener.value;
                if (instance) {
                    console.log("mOnClickListener name is :" + getObjClassName(instance));
                    watch(instance, 'onClick');
                }
            },
            onComplete: function () {
            }
        })
    })
}

获取app运行时信息

获取系统信息:hook android.os.Build ,Hook android 4大组件,File类等:例子

Java.perform(function () {
    var Activity = Java.use("android.app.Activity");
    Activity.startActivity.overload('android.content.Intent').implementation=function(p1){
        console.log("Hooking android.app.Activity.startActivity(p1) successfully,p1="+p1);
        console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
        // 查看Intent 携带的内容,大多数时候Bundle才放了数据,还是自己解析Bundle
        console.log(decodeURIComponent(p1.toUri(256)));
        this.startActivity(p1);
    }
    Activity.startActivity.overload('android.content.Intent', 'android.os.Bundle').implementation=function(p1,p2){
        console.log("Hooking android.app.Activity.startActivity(p1,p2) successfully,p1="+p1+",p2="+p2);
        console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
        console.log(decodeURIComponent(p1.toUri(256)));
        this.startActivity(p1,p2);
    }
    Activity.startService.overload('android.content.Intent').implementation=function(p1){
        console.log("Hooking android.app.Activity.startService(p1) successfully,p1="+p1);
        console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
        console.log(decodeURIComponent(p1.toUri(256)));
        this.startService(p1);
    }
})

补充:
1、frida的objection框架,在hook一个类时,并没有hook类的 i n i t 方 法 , 可 以 自 己 在 o b j e c t i o n 源 码 中 自 己 添 加 可 以 手 动 h o o k init方法,可以自己在objection源码中自己添加 可以手动hook initobjectionhookinit类:android hooking watch class_methoid java.io.File.$init --dump-args
2、frida snippets : android-file-system-access-hook 基本上把android文件读写的内容都hook了

hook 网络框架

主流的框架:URLHTTPConnection和OKHTTP(3)
代码apk看看使用了那个框架,hook框架,打印调用栈,定位到业务代码

frida反调试 antiFrida

java api ,native api,syscall(绕过libc.so)
github frida-detection-demo 可以看这个项目

void *detect_frida_loop(void *) {
    struct sockaddr_in sa;
    memset(&sa, 0, sizeof(sa));
    sa.sin_family = AF_INET;
    inet_aton("0.0.0.0", &(sa.sin_addr));
    int sock;
    int i;
    int ret;
    char res[7];
    while(1){
        /*
         * 1:Frida Server Detection
         */
        //LOGI("entering frida server detect loop started");
        for(i=20000;i<30000;i++){
            sock = socket(AF_INET,SOCK_STREAM,0);
            sa.sin_port = htons(i);
            LOGI("entering frida server detect loop started,now i is %d",i);

            if (connect(sock , (struct sockaddr*)&sa , sizeof sa) != -1) {
                memset(res, 0 , 7);
                send(sock, "\x00", 1, NULL);
                send(sock, "AUTH\r\n", 6, NULL);
                usleep(500); // Give it some time to answer
                if ((ret = recv(sock, res, 6, MSG_DONTWAIT)) != -1) {
                    if (strcmp(res, "REJECT") == 0) {
                        LOGI("FOUND FRIDA SERVER: %s,FRIDA DETECTED [1] - frida server running on port %d!",APPNAME,i);
                    }else{
                        LOGI("not FOUND FRIDA SERVER");
                    }
                }
            }
            close(sock);
        }
    }
}

frida native hook

1、替换参数
2、修改返回值
3、打印native层堆栈
4、native层函数,主动调用
5、native层函数替换(或者不执行)

function hook_nativelib(){
    var native_lib_addr = Module.findBaseAddress("libnative-lib.so");
    var myfirstjniJNI = Module.findExportByName("libnative-lib.so", "Java_com_example_demoso1_MainActivity_myfirstjniJNI");
    var myfirstjniJNI_invoke = new NativeFunction(myfirstjniJNI,"pointer",["pointer","pointer","pointer"])

    Interceptor.attach(myfirstjniJNI,{
        onEnter:function(args){
            console.log("Interceptor.attach myfirstjniJNI args:",args[0],args[1],args[2]);
            console.log("args2 jstring is ",Java.vm.getEnv().getStringUtfChars( args[2],null).readCString())
            console.log("myfirstjniJNI_invoke  result => ",myfirstjniJNI_invoke(args[0],args[1],args[2]))
            // 1
            var newArgs2 = Java.vm.getEnv().newStringUtf("new args2 from frida");
            args[2] = newArgs2;

        },onLeave:function(retval){
            console.log("Interceptor.attach myfirstjniJNI retval => ",retval)
            console.log("retval jstring is ",Java.vm.getEnv().getStringUtfChars( retval,null).readCString())
            var newRetval = Java.vm.getEnv().newStringUtf("new Retval from frida");
            // 2
            retval.replace(newRetval);
        }
    })
}

function hookandinvoke_add(){
    var native_lib_addr = Module.findBaseAddress("libnative-lib.so");
    var r0add_addr = Module.findExportByName("libnative-lib.so", "_Z5r0addii");
    Interceptor.attach(r0add_addr,{
        onEnter:function(args){
            console.log("x=>",args[0],"  y=>",args[1]);
            // 3
            console.log('CCCryptorCreate called from:\n' +
        Thread.backtrace(this.context, Backtracer.FUZZY).map(DebugSymbol.fromAddress).join('\n') + '\n');
        },onLeave:function(retval){
            console.log("retval is => ",retval);
        }
    })
	
	// 4
    var r0add = new NativeFunction(r0add_addr,"int",["int","int"]);
    var r0add_result = r0add(50,1);
    console.log("invoke result is => ",r0add_result);
}

function hook_replace(){
    var native_lib_addr = Module.findBaseAddress("libnative-lib.so");
    console.log("native_lib_addr => ",native_lib_addr);

    var myfirstjniJNI = Module.findExportByName("libnative-lib.so", "Java_com_example_demoso1_MainActivity_myfirstjniJNI");
    console.log("myfirstjniJNI addr => ",myfirstjniJNI);

    var myfirstjniJNI_invoke = new NativeFunction(myfirstjniJNI,"pointer",["pointer","pointer","pointer"])
	// 5
    Interceptor.replace(myfirstjniJNI,new NativeCallback(function(args0,args1,args2){
        console.log("Interceptor.replace myfirstjniJNI args:",args0,args1,args2);
        //var result = myfirstjniJNI_invoke(args0,args1,args2)
        return Java.vm.getEnv().newStringUtf("new Retval from frida");;
    },"pointer",["pointer","pointer","pointer"]))
}

function EnumerateAllExports(){
    var modules = Process.enumerateModules();
    //console.log("Process.enumerateModules => ",JSON.stringify(modules))
    for(var i=0;i<modules.length;i++){
        var module = modules[i];
        var module_name = modules[i].name;
        var exports = module.enumerateExports();
        console.log("module_name=>",module_name,"  module.enumerateExports = > ",JSON.stringify(exports))
    }
}

其他代码

function hook_JNI(){

    var GetStringUTFChars_addr = null;
    var symbols = Process.findModuleByName("libart.so").enumerateSymbols()
    //console.log(JSON.stringify(symbols))
    for(var i = 0;i<symbols.length;i++){
        var symbol = symbols[i].name;
        if((symbol.indexOf("CheckJNI")==-1)&&(symbol.indexOf("JNI")>=0)){
            if(symbol.indexOf("GetStringUTFChars")>=0){
                console.log("finally found GetStringUTFChars name :",symbol);
                GetStringUTFChars_addr =symbols[i].address ;
                console.log("finally found GetStringUTFChars address :",GetStringUTFChars_addr);
            }
        }
    }
    Interceptor.attach(GetStringUTFChars_addr,{
        onEnter:function(args){
            console.log("art::JNI::GetStringUTFChars(_JNIEnv*, _jstring*, unsigned char*)=>",args[0],Java.vm.getEnv().getStringUtfChars( args[1],null).readCString(),args[2]);
        },onLeave:function(retval){
            console.log("retval is => ",retval.readCString());
        }
    })
}

function replace_JNI(){
    var NewStringUTF_addr = null;
    var symbols = Process.findModuleByName("libart.so").enumerateSymbols()
    //console.log(JSON.stringify(symbols))
    for(var i = 0;i<symbols.length;i++){
        var symbol = symbols[i].name;
        if((symbol.indexOf("CheckJNI")==-1)&&(symbol.indexOf("JNI")>=0)){
            if(symbol.indexOf("NewStringUTF")>=0){
                console.log("finally found NewStringUTF_name :",symbol);
                NewStringUTF_addr =symbols[i].address ;
                console.log("finally found NewStringUTF_addr :",NewStringUTF_addr);
            }
        }
    }
    var NewStringUTF = new NativeFunction(NewStringUTF_addr,"pointer",["pointer","pointer"])
    Interceptor.replace(NewStringUTF_addr,
        new NativeCallback(function(parg1,parg2){
            console.log("parg1,parg2=>",parg1,parg2.readCString());
            var newPARG2 = Memory.allocUtf8String("newPARG2")
            var result = NewStringUTF(parg1,newPARG2);
            return result;
        },"pointer",
        ["pointer","pointer"]))
}

function hook_RegisterNatives(){
    var RegisterNatives_addr = null;
    var symbols = Process.findModuleByName("libart.so").enumerateSymbols()
    //console.log(JSON.stringify(symbols))
    for(var i = 0;i<symbols.length;i++){
        var symbol = symbols[i].name;
        if((symbol.indexOf("CheckJNI")==-1)&&(symbol.indexOf("JNI")>=0)){
            if(symbol.indexOf("RegisterNatives")>=0){
                console.log("finally found RegisterNatives_name :",symbol);
                RegisterNatives_addr =symbols[i].address ;
                console.log("finally found RegisterNatives_addr :",RegisterNatives_addr);
            }
        }
    }

    if(RegisterNatives_addr!=null){
        Interceptor.attach(RegisterNatives_addr,{
            onEnter:function(args){
                console.log("[RegisterNatives]method counts :",args[3]);
                var env = args[0];
                var jclass = args[1];
                var class_name = Java.vm.tryGetEnv().getClassName(jclass);
                var methods_ptr = ptr(args[2]);
                var method_count = parseInt(args[3]);
                for (var i = 0; i < method_count; i++) {
                    var name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
                    var sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
                    var fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));
                    var name = Memory.readCString(name_ptr);
                    var sig = Memory.readCString(sig_ptr);
                    var find_module = Process.findModuleByAddress(fnPtr_ptr);
                    console.log("[RegisterNatives] java_class:", class_name, "name:", name, "sig:", sig, "fnPtr:", fnPtr_ptr, "module_name:", find_module.name, "module_base:", find_module.base, "offset:", ptr(fnPtr_ptr).sub(find_module.base));
                }
            },onLeave:function(retval){
            }
        })
    }else{
        console.log("didn`t found RegisterNatives address")
    }
}
setImmediate(hook_RegisterNatives);
function hook_pthread(){

    var pthread_create_addr = Module.findExportByName("libc.so", "pthread_create");
    var time_addr = Module.findExportByName("libc.so", "time");
    console.log("pthread_create_addr=>",pthread_create_addr)

    Interceptor.attach(pthread_create_addr,{
        onEnter:function(args){
            console.log("args=>",args[0],args[1],args[2],args[4])
            var libnativebaseaddress = Module.findBaseAddress("libnative-lib.so")
            if(libnativebaseaddress!=null){
                console.log("libnativebaseaddress=>",libnativebaseaddress);
                //var detect_frida_loop_addr = args[2]-libnativebaseaddress;
                //console.log("detect_frida_loop offset is =>",detect_frida_loop_addr)
                if(args[2]-libnativebaseaddress == 64900){
                    console.log("found anti frida loop!,excute time_addr=>",time_addr);
                    args[2]=time_addr;
                }
            }
        },onLeave:function(retval){
            console.log("retval is =>",retval)
        }
    })
}

function replace_pthread(){
    var pthread_create_addr = Module.findExportByName("libc.so", "pthread_create");
    console.log("pthread_create_addr=>",pthread_create_addr)
    var pthread_create = new NativeFunction(pthread_create_addr,"int",["pointer","pointer","pointer","pointer"])
    Interceptor.replace(pthread_create_addr,
        new NativeCallback(function(parg1,parg2,parg3,parg4){
            console.log(parg1,parg2,parg3,parg4)     
            var libnativebaseaddress = Module.findBaseAddress("libnative-lib.so")
            if(libnativebaseaddress!=null){
                console.log("libnativebaseaddress=>",libnativebaseaddress);
                if(parg3-libnativebaseaddress == 64900){
                    return null;
                }
            }      
            return pthread_create(parg1,parg2,parg3,parg4)
        },"int",["pointer","pointer","pointer","pointer"]))
}

function writeSomething(path,contents){
    var fopen_addr = Module.findExportByName("libc.so", "fopen");
    var fputs_addr = Module.findExportByName("libc.so", "fputs");
    var fclose_addr = Module.findExportByName("libc.so", "fclose");

    //console.log("fopen=>",fopen_addr,"  fputs=>",fputs_addr,"  fclose=>",fclose_addr);

    var fopen = new NativeFunction(fopen_addr,"pointer",["pointer","pointer"])
    var fputs = new NativeFunction(fputs_addr,"int",["pointer","pointer"])
    var fclose = new NativeFunction(fclose_addr,"int",["pointer"])

    console.log(path,contents)

    var fileName = Memory.allocUtf8String(path);
    var mode = Memory.allocUtf8String("a+");

    var fp = fopen(fileName,mode);

    var contentHello = Memory.allocUtf8String(contents);
    var ret = fputs(contentHello,fp)
    
    fclose(fp);
}

function EnumerateAllExports(){
    /*
    var packageName = null 
    Java.perform(function(){
        packageName = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext().getPackageName();
        console.log("package name is :",packageName)
    })
    */

    var modules = Process.enumerateModules();
    //console.log("Process.enumerateModules => ",JSON.stringify(modules))
    for(var i=0;i<modules.length;i++){
        var module = modules[i];
        var module_name = modules[i].name;
        //var exports = module.enumerateExports();
        var exports = module.enumerateSymbols();
        console.log("module_name=>",module_name,"  module.enumerateExports = > ",JSON.stringify(exports))
        for(var m =0; m<exports.length;m++){
            console.log("m=>",m)
            //writeSomething("/sdcard/"+packageName+"/"+module_name+".txt", "type:"+exports[m].type+ " name:"+ exports[m].name+" address:"+exports[m].address+"\n")
            writeSomething("/sdcard/settings/"+module_name+".txt", "type:"+exports[m].type+ " name:"+ exports[m].name+" address:"+exports[m].address+"\n")
        }
    }
}
//应用以32位在64位终端环境下运行
//adb install --abi armeabi-v7a <path to apk>
function EnumerateAllExports() {
    var linker = Process.getModuleByName("linker")
    //console.log("exports=>",JSON.stringify(linker.enumerateSymbols()))
    var call_function_addr = null;
    var exports = linker.enumerateSymbols();
    //console.log("module_name=>",module_name,"  module.enumerateExports = > ",JSON.stringify(exports))
    for (var m = 0; m < exports.length; m++) {
        //console.log("m=>",m)
        //writeSomething("/sdcard/"+packageName+"/"+module_name+".txt", "type:"+exports[m].type+ " name:"+ exports[m].name+" address:"+exports[m].address+"\n")
        //writeSomething("/sdcard/settings/"+module_name+".txt", "type:"+exports[m].type+ " name:"+ exports[m].name+" address:"+exports[m].address+"\n")
        if (exports[m].name == "__dl__ZL13call_functionPKcPFviPPcS2_ES0_") {
            call_function_addr = exports[m].address;
            console.log("found call_function_addr => ", call_function_addr)
            hook_call_function(call_function_addr)
        }
    }
}

frida一些好用的框架脚本

frida_fuzzer_based_on_Stalker :
用于分析ollvm执行流 : Hooah-Trace
frida_hook_libart
jnitrace

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值