美文网首页
FRIDA 实用手册

FRIDA 实用手册

作者: 阿里云云栖号 | 来源:发表于2019-02-14 16:54 被阅读89次

FRIDA 实用手册

本文目的是作为工具类文章,收集整理了一些 FRIDA 的使用技巧和用例,方便同学们在开发使用过程中开袋即食。

frida 的基础教程可以直接参看官网说明

Python 部分

JS 中文支持

使用 codecs.open(scriptpath, "r", "utf-8") 打开文件读取 js 即可。

获取指定 UID 设备

device = frida.get_device_manager().get_device("094fdb0a0b0df7f8")

获取远程设备

mgr = frida.get_device_manager()device = mgr.add_remote_device("30.137.25.128:13355")

启动调试进程

pid = device.spawn([packename])process = device.attach(pid)script = process.create_script(jscode)script.on('message', on_message)script.load()device.resume(pid)

python 与 js 交互的官方示例

from__future__importprint_functionimportfridaimportsyssession = frida.attach("hello")script = session.create_script("""

Interceptor.attach(ptr("%s"), {

    onEnter: function(args) {

        send(args[0].toString());

        var op = recv('input', function(value) {

            args[0] = ptr(value.payload);

        });

        op.wait();

    }

});

"""% int(sys.argv[1],16))defon_message(message, data):print(message)    val = int(message['payload'],16)    script.post({'type':'input','payload': str(val *2)})script.on('message', on_message)script.load()sys.stdin.read()

从 bytecode 加载脚本

# -*- coding: utf-8 -*-from__future__importprint_functionimportfridasystem_session = frida.attach(0)bytecode = system_session.compile_script(name="bytecode-example", source="""\

'use strict';

rpc.exports = {

  listThreads: function () {

    return Process.enumerateThreadsSync();

  }

};

""")session = frida.attach("Twitter")script = session.create_script_from_bytes(bytecode)script.load()api = script.exports# 这里的 list_threads 是 listThreads 驼峰命名法自动转换后的结果,由 rpc exports 功能导出给 python 调用print("api.list_threads() =>", api.list_threads())

JS 部分

hook Android 短信发送 SendDataMessage

functionhook_sms(){varSmsManager = Java.use('android.telephony.SmsManager');    SmsManager.sendDataMessage.implementation =function(        destinationAddress, scAddress, destinationPort, data, sentIntent, deliveryIntent){console.log("sendDataMessage destinationAddress: "+ destinationAddress +" port: "+ destinationPort);        showStacks();this.sendDataMessage(destinationAddress, scAddress, destinationPort, data, sentIntent, deliveryIntent);    }}

定时执行函数

setTimeout 延迟执行一次

setTimeout(funcA,15000);

setInterval 间隔循环执行

varid_ = setInterval(funcB,15000);clearInterval(id_);// 终止

bin array 转字符串

functionbin2String(array){if(null== array) {return"null";    }varresult ="";try{varString_java = Java.use('java.lang.String');        result = String_java.$new(array);    }catch(e) {        dmLogout("== use bin2String_2 ==");        result = bin2String_2(array);    }returnresult;}functionbin2String_2(array){varresult ="";try{vartmp =0;for(vari =0; i < array.length; i++) {            tmp =parseInt(array[i]);if( tmp ==0xc0|| (tmp <32&& tmp !=10)                || tmp >126)  {returnresult;            }// 不是可见字符就返回了, 换行符除外result +=String.fromCharCode(parseInt(array[i].toString(2),2));        }    }catch(e) {console.log(e);    }returnresult;}

自己封装输出函数加入线程ID 和时间

functiongetFormatDate(){vardate =newDate();varmonth = date.getMonth() +1;varstrDate = date.getDate();if(month >=1&& month <=9) {        month ="0"+ month;    }if(strDate >=0&& strDate <=9) {        strDate ="0"+ strDate;    }varcurrentDate = date.getFullYear() +"-"+ month +"-"+ strDate            +" "+ date.getHours() +":"+ date.getMinutes() +":"+ date.getSeconds();returncurrentDate;}functiondmLogout(str){varthreadid = Process.getCurrentThreadId();console.log("["+threadid+"]["+ getFormatDate() +"]"+ str);}

打印 Android Java 层堆栈

varshowStacks =function(){    Java.perform(function(){        dmLogout(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()));// 打印堆栈});}

TracerPid fgets 反调试

varanti_fgets =function(){    dmLogout("anti_fgets");varfgetsPtr = Module.findExportByName("libc.so","fgets");varfgets =newNativeFunction(fgetsPtr,'pointer', ['pointer','int','pointer']);    Interceptor.replace(fgetsPtr,newNativeCallback(function(buffer, size, fp){varretval = fgets(buffer, size, fp);varbufstr = Memory.readUtf8String(buffer);if(bufstr.indexOf("TracerPid:") >-1) {            Memory.writeUtf8String(buffer,"TracerPid:\t0");// dmLogout("tracerpid replaced: " + Memory.readUtf8String(buffer));}returnretval;    },'pointer', ['pointer','int','pointer']));};

反调试时读取 LR 寄存器溯源

varanti_antiDebug =function(){varfuncPtr =null;    funcPtr = Module.findExportByName("xxxx.so","p57F7418DCD0C22CD8909F9B22F0991D3");    dmLogout("anti_antiDebug "+ funcPtr);    Interceptor.replace(funcPtr,newNativeCallback(function(pathPtr, flags){        dmLogout("anti ddddddddddddddebug LR: "+this.context.lr);return0;    },'int', ['int','int']));};

hook JNI API NewStringUTF

functionhook_native_newString(){varenv = Java.vm.getEnv();varhandlePointer = Memory.readPointer(env.handle);    dmLogout("env handle: "+ handlePointer);varNewStringUTFPtr = Memory.readPointer(handlePointer.add(0x29C));    dmLogout("NewStringUTFPtr addr: "+ NewStringUTFPtr);    Interceptor.attach(NewStringUTFPtr, {        onEnter:function(args){            ...        }    });}

hook JNI API GetStringUTFChars

functionhook_native_GetStringUTFChars(){varenv = Java.vm.getEnv();varhandlePointer = Memory.readPointer(env.handle);    dmLogout("env handle: "+ handlePointer);varGetStringUTFCharsPtr = Memory.readPointer(handlePointer.add(0x2A4));    dmLogout("GetStringUTFCharsPtr addr: "+ GetStringUTFCharsPtr);    Interceptor.attach(GetStringUTFCharsPtr, {        onEnter:function(args){varstr ="";            Java.perform(function(){                str = Java.cast(args[1], Java.use('java.lang.String'));            });            dmLogout("GetStringUTFChars: "+ str);if(str.indexOf("linkData:") >-1) {// 设置过滤条件dmLogout("========== found linkData LR: "+this.context.lr +"  ==========");            }        }    });};

循环输出参数的值

Interceptor.attach(Module.findExportByName("libc.so","strcat"), {    onEnter:function(args){for(vari =0; i < args.length; i ++) {            dmLogout("strcat args["+ i +"]("+ ptr(args[i]) +"): "+ Memory.readUtf8String(args[i]));        }    }});

hook Android URI 打印堆栈

varhook_uri =function(){// coord: (7520,0,19) | addr: Ljava/net/URI;->parseURI(Ljava/lang/String;Z)V | loc: ?varuri = Java.use('java.net.URI');    uri.parseURI.implementation =function(a1, a2){        a1 = a1.replace("xxxx.com","yyyy.com");        dmLogout("uri: "+ a1);        showStacks();returnthis.parseURI(a1, a2);    }}

hook KXmlSerializer 拼装内容

functionhook_xml(){varxmlSerializer = Java.use('org.kxml2.io.KXmlSerializer');// org.xmlpull.v1.XmlSerializerxmlSerializer.text.overload('java.lang.String').implementation =function(text){        dmLogout("xtext: "+ text);if("GPRS"== text) {            dmLogout("======>>> found GPRS");            showStacks();        }returnthis.text(text);    }}

hook Android Log 输出

functionhook_log(){    dmLogout(TAG,"do hook log");varLog = Java.use('android.util.Log');    Log.v.overload('java.lang.String','java.lang.String').implementation =function(tag, content){        dmLogout(tag +" v", content);    };    Log.d.overload('java.lang.String','java.lang.String').implementation =function(tag, content){        dmLogout(tag +" d", content);    };    Log.w.overload('java.lang.String','java.lang.String').implementation =function(tag, content){        dmLogout(tag +" w", content);    };    Log.i.overload('java.lang.String','java.lang.String').implementation =function(tag, content){        dmLogout(tag +" i", content);    };    Log.e.overload('java.lang.String','java.lang.String').implementation =function(tag, content){        dmLogout(tag +" e", content);    };}

native 主动调用

varfriendlyFunctionName =newNativeFunction(friendlyFunctionPtr,'void', ['pointer','pointer']);varreturnValue = Memory.alloc(sizeOfLargeObject);friendlyFunctionName(returnValue, param1);

就先整理这么多,日后再追加。欢迎大佬们追加分享和指正错误。

本文作者:星均

阅读原文

本文为云栖社区原创内容,未经允许不得转载。

相关文章

网友评论

      本文标题:FRIDA 实用手册

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