配置RPC和开发姿势
Frida是一款基于Python和JavaScript的进程级Hook框架,其中JavaScript语言承担了Hook的主要工作,而Python语言则相当于提供给外界的绑定接口,使用者可以通过Python语言将JavaScript脚本注入进程中,官方也在下方仓库中提供了Python远程调用JavaScript中函数的方式:
https://github.com/frida/frida-python
下面简单介绍下通过Python实现Frida注入的基本方式。
0x00 开发环境准备
工欲善其事,必先利其器。编写 frida js 时让 IDE 智能提示【使用 IDE 编写 frida js 时智能提示】
方法一
- git clone https://github.com/oleavr/frida-agent-example.git
- **cd frida-agent-example/**,执行命令 npm install
- 然后使用 VSCode、pycharm、idea 等 IDE 打开此工程,在 agent 目录下编写 JavaScript 代码时就会有智能提示。
JS单步调试
https://bbs.pediy.com/thread-265160.htm
能愉快的单步调试 frida 的 js 脚本,可以方便不少。首先运行 frida 脚本
frida -l </Users/name/path/test.js> --debug --runtime=v8 <port/name> |
或者:
session = dev.attach(app.pid) |
启动后会回显 Inspector 正在监听 9229 默认端口
Chrome Inspector server listening on port 9229 |
chrome
打开 chrome://inspect, 点击 Open dedicated DevTools for Node。
此时 debug 已经连接,切换至 Sources
,按 Command + P
加载要调试的脚本,即可下断调试了。
pycharm
首先安装 Node.js 插件,重启。添加调试器 Attaching to Node.js/Chrome
,端口默认即可。Attach to
应选择 Node.js < 8 started with --debug
, 下面的自动重连选项可选可不选。
触发断点需要在 debug 窗口切换到 script 选项卡,右键要调试的脚本,选择 Open Actual Source,在新打开的 Actual Source 窗口设置好断点后,需要再取消/启用一次所有断点作为激活,发现断点上打上对勾才真正可用了。
接下来就可以正常调试了
优缺点
- 用 Chrome 调试支持的更为顺滑,调试脚本自动重加载,断点也能正确响应。
- 用 PyCharm 调试断点有时需要手动激活有点麻烦,但可以使用PyCharm 的Debug 窗口和快捷键。
- PyCharm 使用 ts 环境调试时,可以直接在ts文件上下断,也不需要手动激活断点。
方法二
https://bbs.pediy.com/thread-258513.htm
基础Frida代码完成
frida 代码提示插件。如果你安装了 Frida, 不管你熟不熟悉 nodejs 的生态, 肯定已经安装好了
npm install @types/frida-gum |
你需要在你编写注入 js 文件的目录下运行 ( 可以不事先创建 package.json,只是会出现一条警告 )
然后使用可以TypeScript代码完成功能的编辑器 ( 比如 vscode、pycharm、idea ) 打开js文件即刻。
“基础 frida 代码完成“ 就可以补全 frida js 代码,如果想要 类成员函数及成员变量的类型等功能,可以安装插件 frida-tsplugin
下载并安装插件 frida-tsplugin
在任意目录下:git clone https://github.com/tacesrever/frida-tsplugin ,然后在 frida-tsplugin 目录下运行
npm install |
Frida-tsplugin 特性
- 可以识别 Java.use 和 Java.cast
- 可以追踪变量赋值传递
- 可以识别并追踪类成员函数及成员变量的类型
- 可以根据重载函数的参数类型识别对应的重载函数
- 可以识别
someJavaFunction[.overload(...)].implementation = function(...) {...}
函数块中的参数类型和this类型
ps. 对于未能追踪到的类型, 可以使用 Java.cast 来为其做一个声明
0x01 简单介绍
获取设备
import frida |
注入进程
import frida |
注入脚本
import frida |
文件方式注入进程
with open("LuoHook.js", encoding="UTF-8") as f: |
调用函数
import frida |
备注
script.on
在 Frida 的脚本中使用 script.on
方法是为了设置一个事件监听器,它允许你捕获并处理脚本中发出的消息。这通常用于以下两种情况:
- 接收脚本中的输出:脚本可以通过
send
方法发送消息到附加的进程(例如,打印调试信息或者返回结果)。 - 处理脚本中的异常:如果脚本中发生错误,Frida 会自动发送一个包含错误信息的消息。
以下是 script.on
方法的基本用法:
script.on('message', function(message, data) { |
这里 message
对象通常具有以下属性:
type
:消息类型,可以是'send'
、'error'
或'console'
。payload
:当消息类型是'send'
时,这是脚本发送的实际数据。description
:当消息类型是'error'
时,这是错误描述。
data
参数通常是一个包含原始数据(例如,缓冲区)的对象,它仅在消息类型是 'send'
时有意义。
使用 script.on
方法,你可以确保在脚本运行时能够接收和处理任何重要的通知或数据,从而实现与脚本的交互。这在调试和与脚本进行通信时非常有用。
rpc.exports
rpc.exports
是在 Frida 脚本中使用的一个属性,它用于定义可以从外部通过 RPC(远程过程调用)调用的函数。通过这种方式,你可以将 Frida 脚本中的某些功能暴露给外部程序,使得外部程序可以远程执行这些功能。
以下是如何使用 rpc.exports
的基本步骤:
第一种方式,函数直接嵌套在RPC导出中,直接导出。
test.js代码:
rpc.exports = { |
python代码:
import frida |
第二种方式,先写函数在 RPC ,然后导出。
test.js 代码
function hello() { |
python代码:
import frida |
0x02 ARIDA-管理PRC脚本&自动生成 http 接口的工具
下载地址:GitHub - tcc0lin/arida: 基于FastAPI实现的Frida-RPC工具,自动解析JavaScript文件生成对应API接口
实现原理
Python
执行PyexecJs
通过Js的AST树
结构获取Frida-Js
脚本中rpc.exports
的方法以及对应方法的参数个数,根据方法名和参数个数通过types.FunctionDef
从Python AST字节码
来动态生成新的Function对象
,并且结合pydantic
的create_model
自动生成的参数模型注册到FastAPI的路由系统
中,实现Frida-RPC
的功能。
工作流程
核心功能
- 管理
JavaScript
文件,具备APP-文件
的映射关系 - 自动针对现有的
JavaScript
方法生成相应的API
方法 - 自动生成
Open API
文档
安装&使用
参考上面官方地址
效果展示
0x03 send/recv/wait
FRIDA RPC - 奋斗的安卓勇士Blog (linqi.net.cn)
介绍
1、send
send()
函数用于从Frida脚本向主机控制台发送消息。- 这个函数可以用来传递任何可以被序列化的数据,包括基本数据类型、对象和数组。
- 使用示例:
send('Hello from Frida script!'); |
2、recv():
recv()
函数用于在脚本中设置一个回调函数,该函数将在主机控制台发送消息时被调用。- 你可以使用这个函数来处理从主机控制台接收到的命令或数据。
- 使用示例:
recv(function onData(data) { |
3、wait():
wait()
函数用于暂停脚本的执行,直到主机控制台调用resume()
。- 这可以用于同步操作,尤其是在你需要等待某个外部事件或条件时。
wait(); |
案例
要实现的功能是,我们不仅仅可以在kali
主机上调用安卓app
里的函数。我们还可以把数据从安卓app
里传递到kali
主机上,在主机上进行修改,再传递回安卓app
里面去。
编写这样一个app
,其中最核心的地方在于判断用户是否为admin
,如果是,则直接返回错误,禁止登陆。如果不是,则把用户和密码上传到服务器上进行验证。
package com.roysue.demo04; |
最终程序运行之后,效果如下:
我们的目标就是在kali
主机上“得到”输入框输入的内容,并且修改其输入的内容,并且“传输”给安卓机器,使其通过验证。也就是说,我们哪怕输入admin
的账户和密码,也可以绕过本地校验,进行登陆的操作。
所以最终安卓端的js
代码的逻辑就是,截取输入,传输给kali
主机,暂停执行,得到kali
主机传回的数据之后,继续执行。形成代码如下:
Java.perform(function () { |
kali
主机端的流程就是,将接受到的JSON
数据解析,提取出其中的密码部分,然后将用户名替换成admin
,这样就实现了将admin
和pw
发送给“服务器”的结果。
import time |
我们只要输入任意用户名(非admin)+密码,非admin的用户名可以绕过compareTo
校验,然后frida
会帮助我们将用户名改成admin
,最终就是admin:pw
的组合发送到服务器。
$ python loader4.py |
动态修改输入内容就这样实现了。