FRIDA 实用手册

12次阅读

共计 6749 个字符,预计需要花费 17 分钟才能阅读完成。

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_functionimport fridaimport 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 短信发送 SendDataMessagefunction 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 NewStringUTFfunction 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 GetStringUTFCharsfunction 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); 就先整理这么多,日后再追加。欢迎大佬们追加分享和指正错误。
本文作者:星均
阅读原文
本文为云栖社区原创内容,未经允许不得转载。

正文完
 0