同LLDB+Debugserver一样,Frida能hook函数、修改函数的传入参数、修改函数的返回值等
1. SSH登录到手机设备端,开启frida-server服务,我的frida-server是放在手机根目录下面的,没有改名,用的是12.10.4版本:
iPhone-3:/ root# ./frida-server-12.10.4-ios-arm64
2. Mac端调试:
xxxMacBook-Pro:Downloads xxx$ frida -U -f com.miniclip.8ballpoolmult -l __handlers__/block.js
其中block.js就是借助frida的js文档编写的相关hook测试代码。
罗列几个关键的使用方法:
利用frida的拦截器Interceptor.replace
2.1 hook形如sub_xxx的函数
//此函数在module模块中寻找地址为offset的sub_xxx
function get_func_addr(module, offset) {
var base_addr = Module.findBaseAddress(module);
// console.log("base_addr: " + base_addr);
// console.log(hexdump(ptr(base_addr), {
// length: 16,
// header: true,
// ansi: true
// }))
var func_addr = base_addr.add(offset);
if (Process.arch == 'arm')
return func_addr.add(1); //如果是32位地址+1
else
return func_addr;
}
对sub_xxx函数完全替换:【Interceptor.replace】
//替换abcKit.dylib模块中,hopper中的地址为0xeba6c处的sub_xxx函数
var func_addr_replace_eba6c = get_func_addr('abcKit.dylib', 0xeba6c);
var add_replace_eba6c = new NativeFunction(func_addr_replace_eba6c, 'void', []);
// 进行替换
Interceptor.replace(add_replace_eba6c, new NativeCallback(function() {
console.log('替换eba6c函数');
}, 'void', []));
修改sub_xxx函数的传入参数或是返回值:【与frida-trace同效】
//对主程序CrackMe中的0x6684处的sub_xxx函数
var func_addr = get_func_addr('CrackMe', 0x6684);
Interceptor.attach(ptr(func_addr), {
onEnter: function(args) {
console.log("onEnter");
var num1 = args[0];
var num2 = args[1];
console.log("num1: " + num1);
console.log("num2: " + num2);
},
onLeave: function(retval) {
console.log("onLeave");
retval.replace(3); //返回值替换成3
}
});
2.2 拦截系统的函数,比如 open 、exit函数【Interceptor.replace】
//拦截open函数
var openPtr = Module.getExportByName(null, 'open');
var open = new NativeFunction(openPtr, 'int', ['pointer', 'int']);
Interceptor.replace(openPtr, new NativeCallback(function (pathPtr, flags) {
var path = pathPtr.readUtf8String();
console.log('Opening "' + path + '"');
var fd = open(pathPtr, flags);
console.log('Got fd: ' + fd);
return fd;
}, 'int', ['pointer', 'int']));
//拦截exit函数
var openPtr = Module.getExportByName(null, 'exit');
var open = new NativeFunction(openPtr, 'void', ['int']);
Interceptor.replace(openPtr, new NativeCallback(function (flags) {
console.log('Got fd: ');
}, 'void', ['int']));
2.3 拦截Object-C函数
//完全替换
var method = ObjC.classes.NSURL['+ URLWithString:'];
var origImp = method.implementation;
method.implementation = ObjC.implement(method, function (self, sel, url){
//console.log("+ [NSURL URLWithString:]");
var urlString = ObjC.Object(url);
var url = urlString.toString();
if (url.indexOf("tont") != -1 || url.indexOf("tpan") != -1) {
console.log("阻止url: " + url);
}else {
return origImp(self, sel, url); //调用原方法,如果不调用则原方法得不到执行
}
//替换参数,将 URL 替换成 http://www.ioshacker.net
//var newUrl = ObjC.classes.NSString.stringWithString_("http://www.ioshacker.net");
//return origImp(self, sel, newUrl);
});
//hook修改
Interceptor.attach(hook.implementation, {
onLeave: function(retval) {
console.log("[*] Class Name: " + className);
console.log("[*] Method Name: " + funcName);
console.log('startWithOptions--111-----');
console.log("\t[-] Type of return value: " + typeof retval);
console.log("\t[-] Original Return Value: " + retval.readUtf8String());
var string = Memory.allocUtf8String("4567fsdfdesdfs89"); //分配内存
retval.replace(string); //替换
console.log("\t[-] New Return Value: " + retval.readUtf8String());
},
onEnter: function(args){
console.log('startWithOptions----enter---');
var className = ObjC.Object(args[0]);
var methodName = args[1];
var urlString = ObjC.Object(args[2]);
console.log("className: " + className.toString());
console.log("methodName: " + methodName.readUtf8String());
console.log("urlString: " + urlString.toString());
console.log("-----------------------------------------");
urlString = ObjC.classes.NSString.stringWithString_("http://www.baidu.com")
console.log("newUrlString: " + urlString.toString());
console.log("-----------------------------------------");
}
});
参考:https://bbs.pediy.com/thread-259875.htm
https://bbs.pediy.com/thread-259424.htm
更多参考frida官方文档:https://frida.re/docs/javascript-api/#objc