它是原生应用程序的 Greasemonkey,或者,用更专业的术语来说,它是一个动态代码检测工具包。它允许您将 JavaScript 片段或您自己的库注入到 Windows、macOS、GNU/Linux、iOS、Android 和 QNX 上的本机应用程序中。Frida 还为您提供了一些基于 Frida API 构建的简单工具。这些可以按原样使用,根据您的需要进行调整,或者作为如何使用 API 的示例。
推荐 python 3.xbrew install python
pip install frida-tools
Frida 的核心是用 C 语言编写的,并将QuickJS 注入到目标进程中,您的 JS 在执行时可以完全访问内存、挂钩函数,甚至在进程内调用本机函数。有一个双向通信通道,用于在您的应用程序和目标进程内运行的 JS 之间进行通信。
使用 Python 和 JS 可以使用无风险的 API 进行快速开发。Frida 可以帮助您轻松捕获 JS 中的错误,并为您提供异常而不是崩溃。
支持多个语言绑定
例如 Node.js、 Python、 Swift、 .NET、 Qml等。为其他语言和环境构建额外的绑定非常容易.
JavaScript 与 TypeScript 的区别
TypeScript 是 JavaScript 的超集,扩展了 JavaScript 的语法,因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改,TypeScript 通过类型注解提供编译时的静态类型检查。
什么是TypeSctipt?
TypeScript 可处理已有的 JavaScript 代码,并只对其中的 TypeScript 代码进行编译。
大部分情况下,我们都是附加到一个已经运行到进程,或者是在程序启动到时候进行劫持,然后再在目标进程中运行我们的代码逻辑。这种方式是Frida最常用的使用方式。注入模式的大致实现思路是这样的,带有GumJS的Frida核心引擎被打包成一个动态连接库,然后把这个动态连接库注入到目标进程中,同时提供了一个双向通信通道,这样控制端就可以和注入的模块进行通信了,在不需要的时候,还可以在目标进程中把这个注入的模块给卸载掉。
针对没root过的设备Frida提供了一个动态连接库组件 frida-gadget, 可以把这个动态库集成到程序里面来使用Frida的动态执行功能。一旦集成了gadget,就可以和程序使用Frida进行交互。
自动加载Js文件。
frida-ls-devices
用于获取可用的设备列表,在多设备交互的情况下会非常有用
frida-ps
用于获取进程列表信息
参数 | 描述 |
---|---|
-U | 连接到USB设备 |
-D | 如果当前有多台USB设备,可以使用该参数指定设备的UDID(frida-ls-devices 列出的那些 id) |
-R/-H | 连接到远程 frida-server,主要用于远程调试 |
-a | 仅显示正在运行的应用 |
-i | 显示所有已安装的应用(包括 AppStore安装的应用和系统应用) |
举例:
连接到USB设备查看进程列表frida-ps -U
连接到USB设备查看正在运行的应用frida-ps -U -a
连接到USB设备查看所有安装的应用frida-ps -U -a -i
连接到指定的USB设备查看正在运行的应用frida-ps -D d007dc58edd70caad950ff01b41ebf73cfa49fbe -a
frida-kill
用来结束设备上的指定进程
frida-trace
参数 | 描述 |
---|---|
-i | 包含的C函数 |
-x | 排除某个C函数 |
-m | hook匹配 OC |
-M | 忽略匹配的OC |
-j | 跟踪某个java函数 |
-J | 排除某个java函数 |
-h | 其他参考帮助文档 |
1 | console.log('\tBacktrace:\n\t' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n\t')); |
获取目标类
1 | var targetClass = ObjC.classes.PDNetworkAccessManager; |
获取目标方法
1 | var targetMethod = |
监听目标方法
1 | Interceptor.attach(targetMethod.implementation, { |
接受方法参数的OC对象:
1 | var param = ObjC.Object(args[2]); |
接受Int类型参数:
1 | var value32 = args[3].toInt32(); |
打印对象类型:
1 | console.log('Param类型:' + param.$className); |
接受Block参数:
1 | var finishBlock = new ObjC.Block(args[4]); |
打印Block结构签名:
1 | console.log('blockTypes:' + finishBlock.types); |
修改基本类型参数:
1 | args[2] = ptr(123); |
nil
赋值:
1 | args[3] = ptr("0x0"); |
ObjC.available
: 一个布尔值,指定当前进程是否加载了Objective-C运行时。ObjC除非是这种情况,否则不要调用任何其他属性或方法。
ObjC.api
: 将函数名称映射到NativeFunction实例的对象,用于直接访问大部分Objective-C运行时 API。
ObjC.classesObjC.Object
:为每个当前注册的类映射类名到 JavaScript 绑定的对象。您可以通过使用点表示法并用下划线替换冒号来与对象交互,即: [NSString stringWithString:@"Hello World"]
变成 const { NSString } = ObjC.classes; NSString.stringWithString_("Hello World");
. 注意方法名称后面的下划线。
ObjC.protocols
: 一个对象映射协议名称到ObjC.Protocol 每个当前注册协议的 JavaScript 绑定。
ObjC.mainQueue
:主线程的GCD队列
ObjC.schedule(queue, work)work
: 在 .指定的 GCD 队列上调度 JavaScript 函数queue。AnNSAutoreleasePool
在调用之前创建work,并在返回时清理。
直接见LinXunFeng大牛写好的代码:Github
https://frida.re/docs/javascript-api/
Mac测试需要关闭安全模式
iPhone使用Frida一般需要越狱,如果不越狱使用,可以参考文档