【iOS安全】越狱iOS安装Frida | 安装指定版本Frida | Frida使用
越狱iPhone安装Frida
本文的方法适用于已越狱的iPhone手机
打开Cydia,软件源,编辑(右上角),添加(左上角):https://build.frida.re
然后搜索Frida,点击安装
参考:https://blog.csdn.net/boildoctor/article/details/122769942
安装指定版本Frida
iOS上的Frida版本需要和PC上的Frida版本保持一致,所以有时候需要安装指定版本Frida
下载指定版本deb包:
https://github.com/frida/frida/releases
例如:frida_15.2.2_iphoneos-arm.deb
通过XFTP将deb拷贝至手机/private/var/tmp目录(也就是/tmp目录)
ssh进入手机 /tmp目录,执行安装:
dpkg -i xx.deb
参考:https://cloud.tencent.com/developer/article/2160543
使用Frida
在iPhone上启动Frida-server后,将iPhone通过USB连接至PC
PC上安装Frida,通过命令行输入命令 或 运行脚本
frida-ls-devices 查看电脑连接的iOS设备信息
frida-ps -Ua 查看正在运行的应用
frida hook 类函数
- 函数名以”+”开头的,如:“+ URLWithString:”,可以直接通过类名调用方法,相当于java中的static函数
#coding=utf-8 import frida, sys jscode = """ if(ObjC.available){ console.log('\\n[*] Starting Hooking'); var _className = "JDJR_HackersInfo"; var _methodName = "+ judgementJailbreak"; var hooking = ObjC.classes[_className][_methodName]; console.log('className is: ' + _className + ' and methodName is: ' + _methodName); Interceptor.attach(hooking.implementation,{ onEnter: function(args) { //args[0]:self //args[1]:The selector //args[2]:第一个参数 console.log(' hook success ') this._className = ObjC.Object(args[0]).toString(); this._methodName = ObjC.selectorAsString(args[1]); // console.log('Detected call to: '); // console.log('[-] Detected call to: ' + this._className + ' --> ' + this._methodName); // console.log('\\n----------------' + this._methodName + '----------------'); // console.log('arg2:\\n' + ObjC.Object(args[2]).toString()); //console.log('called from:\\n' + Thread.backtrace(this.context,Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\\n') + '\\n'); //print_arguments(args); }, //onLeave.function(returnValue)被拦截函数调用之后回调 其中returnValue表示原始函数的返回值 onLeave:function(returnValue){ // console.log('Return value of: '); // console.log(' ' + this._className + ' --> ' + this._methodName); // var typeValue = Object.prototype.toString.call(returnValue); // console.log("\\t Type of return value: " + typeValue); // console.log("\\t Return Value: " + returnValue); console.log("old Return Value: " + ObjC.Object(returnValue)); var newRet = ObjC.classes.NSString.stringWithString_("1"); returnValue.replace(newRet); console.log("new Return Value: " + ObjC.Object(returnValue)); } }); } """ bundle = 'xxx.xxx.xxx' device = frida.get_usb_device() #连接usb设备 参数:超时时长 pid = device.spawn([bundle]) #启动指定bundleId的app session = device.attach(pid) #附加到app script = session.create_script(jscode) #创建frida javaScript脚本 script.load() #load脚本到app进程中 这样即注入成功 device.resume(pid) #恢复app运行 sys.stdin.read()#读取打印日志
frida hook 实例函数
- 函数名以“-”开头的需要找到一个实例化的对象,然后再调用方法
- 如果内存中没有这样的对象
这种情况需要手动生成一个实例,用法为ObjC.classes.类名.alloc()
- 如果内存中存在实例化后的对象
这种情况需要先找出一个类的实例,使用var tmp=ObjC.chooseSync(ObjC.classes.类名),例如:
ObjC.chooseSync(ObjC.classes.PARSHealthPedometer10thHomeViewController)[0]
其中[0]表示取找到的实例中的第一个实例,可根据实际情况换成其他的实例。
#coding=utf-8 import frida, sys jscode = """ if(ObjC.available){ console.log('\\n[*] Starting Hooking'); // setToken: 有内容 var _className = "WLRequestInfo"; var _methodName = "- setToken:"; // var hookingclass = ObjC.chooseSync(ObjC.classes[_className])[0]; //如果内存中存在实例化后的对象,需要先找出一个类的实例 var hookingclass = ObjC.classes[_className].alloc(); //如果内存中没有实例化后的对象,手动实例化 var hooking = hookingclass[_methodName]; console.log('className is: ' + _className + ' and methodName is: ' + _methodName); Interceptor.attach(hooking.implementation,{ onEnter: function(args) { //args[0]:self //args[1]:The selector //args[2]:第一个参数 // console.log(' hook success ') this._className = ObjC.Object(args[0]).toString(); this._methodName = ObjC.selectorAsString(args[1]); // console.log('Detected call to: '); // console.log('[-] Detected call to: ' + this._className + ' --> ' + this._methodName); // console.log('\\n[-]' + this._className + ' --> ' + this._methodName + ' : '); console.log('\\n----------------' + this._methodName + '----------------'); console.log('arg2:\\n' + ObjC.Object(args[2])); console.log('called from:\\n' + Thread.backtrace(this.context,Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\\n') + '\\n'); //print_arguments(args); }, //onLeave.function(returnValue)被拦截函数调用之后回调 其中returnValue表示原始函数的返回值 onLeave:function(returnValue){ // console.log('Return value of: '); // console.log(' ' + this._className + ' --> ' + this._methodName); // var typeValue = Object.prototype.toString.call(returnValue); // console.log("Type of return value: " + typeValue); // console.log("Return Value: " + returnValue); console.log("Return Value: \\n" + ObjC.Object(returnValue)); } }); } """ bundle = 'cn.gov.pbc.dcep' device = frida.get_usb_device() #连接usb设备 参数:超时时长 pid = device.spawn([bundle]) #启动指定bundleId的app session = device.attach(pid) #附加到app script = session.create_script(jscode) #创建frida javaScript脚本 script.load() #load脚本到app进程中 这样即注入成功 device.resume(pid) #恢复app运行 sys.stdin.read()#读取打印日志
参考:https://mabin004.github.io/2018/08/24/%E5%9C%A8iOS%E4%B8%8A%E4%BD%BF%E7%94%A8Frida/
- 如果内存中没有这样的对象
- 函数名以“-”开头的需要找到一个实例化的对象,然后再调用方法