/awesomeFrida

frida代码汇总

Primary LanguageJavaScript

说明:配合 ADBGUI 工具,更加高效快捷。

安装配置

注入方式

// spawn方式
frida -U --no-pause -f com.abc.xxx -l xxx.js

// attach方式
frida -U pid -l xxx.js

常用代码

打印堆栈

console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));//java打印堆栈

console.log(' called from:\n' +Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n');//SO打印堆栈
// 打印jni函数参数
function hook_native_function(addr) {
    Interceptor.attach(addr, {
        onEnter: function (args) {
            var module = Process.findModuleByAddress(addr);
            this.args0 = args[0];
            this.args1 = args[1];
            this.args2 = args[2];
            this.args3 = args[3];
            this.args4 = args[4];
            this.logs = []
            this.logs.push("call " + module.name + "!" + ptr(addr).sub(module.base) + "\r\n");
            this.logs.push("this.args0: " + print_arg(this.args0));
            this.logs.push("this.args1: " + print_arg(this.args1));
            this.logs.push("this.args2: " + print_arg(this.args2));
            this.logs.push("this.args3: " + print_arg(this.args3));
            this.logs.push("this.args4: " + print_arg(this.args4));
        }, onLeave: function (ret) {
            this.logs.push("this.args0: onLeave: " + print_arg(this.args0));
            this.logs.push("this.args1: onLeave: " + print_arg(this.args1));
            this.logs.push("this.args2: onLeave: " + print_arg(this.args2));
            this.logs.push("this.args3: onLeave: " + print_arg(this.args3));
            this.logs.push("this.args4: onLeave: " + print_arg(this.args4));
            this.logs.push("retValue: " + print_arg(ret));
            console.log(this.logs)
        }
    })
}

function print_arg(addr){
    var range = Process.findRangeByAddress(addr);
    if(range!=null){
        return hexdump(addr)+"\r\n";
    }else{
        return ptr(addr)+"\r\n";
    }
}

function main() {
    // hook_14E20()
    var baseAddr = Module.findBaseAddress("libnative-lib.so")
    hook_native_function(baseAddr.add(0x12c0c));
    // hook_native_function(baseAddr.add(0xf6e0));  free
    hook_native_function(baseAddr.add(0x5796c));
    hook_native_function(baseAddr.add(0x103a4));
    hook_native_function(baseAddr.add(0x13e18));
    hook_native_function(baseAddr.add(0x157fc));
    // hook_native_function(baseAddr.add(0xf670));  malloc
    hook_native_function(baseAddr.add(0x5971c));
    hook_native_function(baseAddr.add(0x59670));
    hook_native_function(baseAddr.add(0x177f8));
    hook_native_function(baseAddr.add(0x19a84));
    hook_native_function(baseAddr.add(0x57bec));
    // hook_native_function(baseAddr.add(0xf310));     new
    // hook_native_function(baseAddr.add(0xf580));      delete
    hook_native_function(baseAddr.add(0x16a94));
    // hook_native_function(baseAddr.add(0xf6a0));       memset
    hook_native_function(baseAddr.add(0xff10));
    hook_native_function(baseAddr.add(0x16514));
    hook_native_function(baseAddr.add(0x151a4));
    hook_native_function(baseAddr.add(0xfcac));
    hook_native_function(baseAddr.add(0x18024));
    // hook_native_function(baseAddr.add(0xf680));         memcpy
    hook_native_function(baseAddr.add(0x57514));
    // hook_native_function(baseAddr.add(0xf630));     strlen
    hook_native_function(baseAddr.add(0x167c0));
    hook_native_function(baseAddr.add(0x12580));
    hook_native_function(baseAddr.add(0x17ce8));
    hook_native_function(baseAddr.add(0x18540));
}

setImmediate(main)

fopen

Interceptor.attach(Module.findExportByName("libc.so" , "open"),{
    onEnter:function (args){
        var name = Memory.readUtf8String(args[0]);
        if(name.indexOf("xxx.xxx")!=-1){
            console.log(
                "open(" +
                "path=\"" + name + "\"" +
                ", flag=" + args[1] +
                ")"
            );
            console.log('called from:\n' +Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n');	
        }
    }
});

拦截模块加载并hook

var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");
if(android_dlopen_ext != null){
    Interceptor.attach(android_dlopen_ext,{
        onEnter: function(args){
            var soName = args[0].readCString();
            if(soName.indexOf("libgame.so") != -1){//libcocos2dlua.so
                console.log("android_dlopen_ext: " + soName);
                this.hook = true;
            }
        },
        onLeave: function(retval){
            if(this.hook) {
                dlopentodo();
                console.log("hook ok");
            };
        }
    });
}

获取模块基址

// 获取基地址
var baseAddr = Module.findBaseAddress("libnative-lib.so")

调用jni函数

// 调用jni函数
function invoke(str){
    Java.perform(function (){
        var javaString = Java.use('java.lang.String').$new(str)
        var result = Java.use("com.xxx.yyy.MainActivity").encodeFromJni_70(javaString);
        console.log("result is => ",result)
    })
}

保存数据到文件

// 字节序列保存到文件中
function save2File(filename, byteArr){
	console.log("save file to: " + filename);
	var file = new File(filename, "w");
	file.write(byteArr);
	file.flush();
	file.close();
}

luaL_loadbuffer

//luaL_loadbuffer 加载lua文件函数 libcocos2dlua.so
var addr = Module.findExportByName('libgame.so', "luaL_loadbuffer");
console.log("luaL_loadbuffer: " + addr);
if(addr!=null){
    Interceptor.attach(addr,{
        onEnter:function (args){
            var name = Memory.readCString(args[3]);
            if(name=="xxxx"){	//测试使用,具体dump时可以去掉
                var buff = Memory.readCString(args[1]);
                var size = args[2].toInt32();
                //console.log("lual_loadbuffer, name: " + name + " size: ", size);
                //console.log(buff);
                var byteArr = Memory.readByteArray(args[1], size);
                printDataHexStr(byteArr);

                if(!name.endsWith(".lua")){name=name+".lua";}
                var filename = "/data/user/0/" + PACKAGENAME + "/" + SAVEDIR + "/" + name.split("/").join(".");
                save2File(filename, byteArr);
            }
        }
    });
}

// 字节序列保存到文件中
function save2File(filename, byteArr){
	console.log("save file to: " + filename);
	var file = new File(filename, "w");
	file.write(byteArr);
	file.flush();
	file.close();
}

// 输出显示十六进制数据
function printDataHexStr(byteArr, size){
	var len = size;
	if(len==undefined){len=0x40;}
	console.log(byteArr);
}

获取模块所有导出函数

// 获取所有导出函数
var symbols = Module.enumerateSymbolsSync("libart.so");
symbols.forEach(function (item) {
	console.log(JSON.stringify( item))
})

实时跟踪cpu指令

// 实时跟踪cpu指令

"use strict"
console.log("Hello world");
const mainThread = Process.enumerateThreads()[0];

Stalker.follow(mainThread.id, {
events: {
    call: true, // 调用指令

    // 其他事件:
    ret: false, // 返回指令
    exec: false, // 全部指令:不推荐, 因为数据量过大
    block: false, // 已计算的块: 粗略执行轨迹
    compile: false // 已编译的块: 对覆盖率很有用
  },

 onReceive: function (events) {
   var parsedEvent = Stalker.parse(events);
   //console.log("buring"+parsedEvent);
 },

 transform: function (iterator) {
   let instruction = iterator.next();
   do {
     console.log("instruction:"+instruction);
     iterator.keep();
   } while ((instruction = iterator.next()) !== null);
 }
})

输出类所有方法名

function enumMethods(targetClass) {
    var ret;
    Java.perform(function() {
            var hook = Java.use(targetClass);
            var ret = hook.class.getDeclaredMethods();
            ret.forEach(function(s) {
                console.log(s);
            })
    })
    return ret;
}

HOOK所有重载函数

function hookAllOverloads(targetClass, targetMethod) {
    Java.perform(function () {
         var targetClassMethod = targetClass + '.' + targetMethod;
         var hook = Java.use(targetClass);
         var overloadCount = hook[targetMethod].overloads.length;
         for (var i = 0; i < overloadCount; i++) {
                hook[targetMethod].overloads[i].implementation = function() {
                     var retval = this[targetMethod].apply(this, arguments);
                     //这里可以打印结果和参数
                     return retval;
                 }
              }
   });
 }

获取方法名

function getMethodName() {
    var ret;
    Java.perform(function() {
        var Thread = Java.use("java.lang.Thread")
        ret = Thread.currentThread().getStackTrace()[2].getMethodName();
    });
    return ret;
}

免写参数

var xx = Java.use("xx.xx.xx");
xx.yy.implementation = function() {
    var ret = this.yy.apply(this, arguments);
    return ret;
}

Java对象、byte[]输出

function jobj2Str(jobject) {
    var ret = JSON.stringify(jobject);
    return ret;
}

jstring、jbytearray 输出

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

dump数据

function dumpAddr(address, length) {
    length = length || 1024;
    console.log(hexdump(address, {
        offset: 0,
        length: length,
        header: true,
        ansi: false
    }));
}

参考