on_message() 消息回调
📥 Python 端与设备端通信的核心回调,所有抓包数据的「总汇」。
📎 源码在线查看:
r0capture.py#L278-L336(on_message)
通信模型
Frida 的通信模型:设备端 send(message, data) → Python 端 on_message(message, data) 收到。
message:dict,含type/payloaddata:ArrayBuffer,原始字节
script.js 每次 hook 到 SSL_read/write,就 send 一次元数据+明文字节,这里统一接收、分流处理。
分流逻辑
python
def on_message(message, data):
# 1. 脚本异常 -> 强制终止
if message["type"] == "error":
logger.info(f"{message}")
os.kill(os.getpid(), signal.SIGTERM)
return
# 2. frida17 桥接请求
payload = message.get("payload")
if isinstance(payload, dict) and payload.get("type") == "frida:load-bridge":
serve_bridge(payload.get("name"), script)
return
# 3. 事件通知 (data 长度==1)
if data is not None and len(data) == 1:
logger.info(f'{message["payload"]["function"]}')
logger.info(f'{message["payload"]["stack"]}')
return
# 4. 正常流量
p = message["payload"]
if verbose:
# 打印五元组 + hexdump + stack
...
if pcap:
log_pcap(pcap_file, p["ssl_session_id"], p["function"], ...)四个分支
1. error:脚本异常
设备端脚本抛异常会以 error 消息上来,直接终止整个抓包进程,避免静默失败。
2. frida:load-bridge:桥接加载
frida 17 下首次访问 Java 时,设备端发 {type:"frida:load-bridge", name:"Java"},这里调 serve_bridge 把桥接源码 post 回去。
3. 事件通知(data 长度 == 1)
script.js 在证书导出 / pinning 定位等非流量事件时,send 一个 1 字节占位 data(Memory.alloc(1))。据此区分:事件只打印 function + stack,不走流量打印 / pcap 逻辑。
4. 正常流量
打印五元组 + hexdump(verbose 时)+ 写 pcap(指定 -p 时)。
IP 还原
设备端把 IP 转成 uint32(网络序)传过来,这里反操作:
python
src_addr = socket.inet_ntop(socket.AF_INET, struct.pack(">I", p["src_addr"]))struct.pack(">I", n):整数变回 4 字节大端二进制socket.inet_ntop:转成"1.2.3.4"可读字符串
hexdump 渲染
python
gen = hexdump.hexdump(data, result="generator", only_str=True)
str_gen = ''.join(gen)
logger.info(f"{str_gen}")result="generator":拿生成器,处理大流量省内存only_str=True:只取 ASCII 栏