Skip to content

on_message() 消息回调 ​

📥 Python 端与设备端通信的核心回调,所有抓包数据的「总汇」。

📎 源码在线查看:r0capture.py#L278-L336(on_message)

通信模型 ​

Frida 的通信模型:设备端 send(message, data) → Python 端 on_message(message, data) 收到。

  • message:dict,含 type / payload
  • data: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 栏

相关文档 ​

基于 VitePress 构建 · 教学用途