FRIDA 实用手册

栏目: Python · 发布时间: 6年前

内容简介:FRIDA 实用手册本文目的是作为工具类文章,收集整理了一些 FRIDA 的使用技巧和用例,方便同学们在开发使用过程中开袋即食。frida 的基础教程可以直接参看官网说明。

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 import print_function

import frida

import sys

session = 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))

def on_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 import print_function

import frida

system_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

function hook_sms() {

var SmsManager = 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 间隔循环执行

var id_ = setInterval(funcB, 15000);

clearInterval(id_); // 终止

bin array 转字符串

function bin2String(array) {

if (null == array) {
    return "null";
}
var result = "";
try {
    var String_java = Java.use('java.lang.String');
    result = String_java.$new(array);
}
catch (e) {
    dmLogout("== use bin2String_2 ==");
    result = bin2String_2(array);
}

return result;

}

function bin2String_2(array) {

var result = "";
try {
    var tmp = 0;
    for (var i = 0; i < array.length; i++) {
        tmp = parseInt(array[i]);
        if ( tmp == 0xc0
            || (tmp < 32 && tmp != 10)
            || tmp > 126 )  {
            return result;
        }  // 不是可见字符就返回了, 换行符除外
        result += String.fromCharCode(parseInt(array[i].toString(2), 2));
    }
}
catch (e) {
    console.log(e);
}
return result;

}

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

function getFormatDate() {

var date = new Date();
var month = date.getMonth() + 1;
var strDate = date.getDate();
if (month >= 1 && month <= 9) {
    month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
    strDate = "0" + strDate;
}
var currentDate = date.getFullYear() + "-" + month + "-" + strDate
        + " " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
return currentDate;

}

function dmLogout(str) {

var threadid = Process.getCurrentThreadId();
console.log("["+threadid+"][" + getFormatDate() + "]" + str);

}

打印 Android Java 层堆栈

var showStacks = function () {

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

}

TracerPid fgets 反调试

var anti_fgets = function () {

dmLogout("anti_fgets");
var fgetsPtr = Module.findExportByName("libc.so", "fgets");
var fgets = new NativeFunction(fgetsPtr, 'pointer', ['pointer', 'int', 'pointer']);
Interceptor.replace(fgetsPtr, new NativeCallback(function (buffer, size, fp) {
    var retval = fgets(buffer, size, fp);
    var bufstr = Memory.readUtf8String(buffer);
    if (bufstr.indexOf("TracerPid:") > -1) {
        Memory.writeUtf8String(buffer, "TracerPid:\t0");
        // dmLogout("tracerpid replaced: " + Memory.readUtf8String(buffer));
    }
    return retval;
}, 'pointer', ['pointer', 'int', 'pointer']));

};

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

var anti_antiDebug = function() {

var funcPtr = null;

 funcPtr = Module.findExportByName("xxxx.so", "p57F7418DCD0C22CD8909F9B22F0991D3");

dmLogout("anti_antiDebug " + funcPtr);
Interceptor.replace(funcPtr, new NativeCallback(function (pathPtr, flags) {
    dmLogout("anti ddddddddddddddebug LR: " + this.context.lr);
    return 0;
}, 'int', ['int', 'int']));

};

hook JNI API NewStringUTF

function hook_native_newString() {

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

}

hook JNI API GetStringUTFChars

function hook_native_GetStringUTFChars() {

var env = Java.vm.getEnv();
var handlePointer = Memory.readPointer(env.handle);
dmLogout("env handle: " + handlePointer);
var GetStringUTFCharsPtr = Memory.readPointer(handlePointer.add(0x2A4));
dmLogout("GetStringUTFCharsPtr addr: " + GetStringUTFCharsPtr);
Interceptor.attach(GetStringUTFCharsPtr, {
    onEnter: function (args) {
        var str = "";
        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 (var i = 0; i < args.length; i ++) {
        dmLogout("strcat args[" + i + "](" + ptr(args[i]) + "): " + Memory.readUtf8String(args[i]));
    }
}

});

hook Android URI 打印堆栈

var hook_uri = function() {

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

    dmLogout("uri: " + a1);
    showStacks();
    return this.parseURI(a1, a2);
}

}

hook KXmlSerializer 拼装内容

function hook_xml() {

var xmlSerializer = Java.use('org.kxml2.io.KXmlSerializer');    // org.xmlpull.v1.XmlSerializer
xmlSerializer.text.overload('java.lang.String').implementation = function (text) {
    dmLogout("xtext: " + text);
    if ("GPRS" == text) {
        dmLogout("======>>> found GPRS");
        showStacks();
    }
    return this.text(text);
}

}

hook Android Log 输出

function hook_log() {

dmLogout(TAG, "do hook log");
var Log = 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 主动调用

var friendlyFunctionName = new NativeFunction(friendlyFunctionPtr, 'void', ['pointer', 'pointer']);

var returnValue = Memory.alloc(sizeOfLargeObject);

friendlyFunctionName(returnValue, param1);

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

本文作者:星均

阅读原文

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


以上所述就是小编给大家介绍的《FRIDA 实用手册》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Mastering Regular Expressions, Second Edition

Mastering Regular Expressions, Second Edition

Jeffrey E F Friedl / O'Reilly Media / 2002-07-15 / USD 39.95

Regular expressions are an extremely powerful tool for manipulating text and data. They have spread like wildfire in recent years, now offered as standard features in Perl, Java, VB.NET and C# (and an......一起来看看 《Mastering Regular Expressions, Second Edition》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码