ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

r2pipe2 协议 RFC 解读:radare2 下一代 JSON 管道通信协议的设计草案

r2pipe2 协议 RFC 解读:radare2 下一代 JSON 管道通信协议的设计草案 r2pipe2 协议 RFC 解读radare2 下一代 JSON 管道通信协议的设计草案【免费下载链接】radare2UNIX-like reverse engineering framework and command-line toolset项目地址: https://gitcode.com/gh_mirrors/ra/radare2radare2 的 r2pipe 机制r2pipe1通过管道、环境变量文件描述符或 HTTP 通道让外部程序向 radare2 实例发送命令并取回输出。doc/r2pipe2.md是维护者 pancake 撰写的一份 RFC 草案提出以 JSON 为载体的下一代协议 r2pipe2以解决阻塞式执行、stderr/日志不可捕获、无返回码、难以扩展元数据等既有限制。本文以该草案为核心逐条解读其需求、握手与命令执行设计并结合仓库中 r2pipe1 的实际实现源码进行对照帮助读者理解这套协议演进的动机、报文格式与迁移思路。背景r2pipe1 的现状与局限在进入草案之前先明确 r2pipe1 在仓库中的真实形态这有助于理解 r2pipe2 为什么要重新设计。r2pipe1 的核心实现位于 libr/socket/r2pipe.c对外 API 声明在 libr/include/r_socket.h其中保留了r2p_cmd、r2p_open、r2p_close等旧名宏以兼容 yara-r2 等历史调用方。其通信模型建立在fork 匿名管道之上r2pipe_open创建两组管道input[2]与output[2]通过R2PIPE_IN/R2PIPE_OUT两个环境变量把文件描述符编号传给子进程然后子进程把 stdin/stdout 重定向到这两个 fd 上执行目标命令env (R2PIPE_IN, r2p-input[0]); env (R2PIPE_OUT, r2p-output[1]); ... dup2 (r2p-input[0], 0); dup2 (r2p-output[1], 1); rc r_sandbox_system (cmd, 1);见 libr/socket/r2pipe.c。发送命令时r2pipe_write会在命令尾部追加换行符\n读取时r2pipe_read逐字节阻塞读入直到遇到 NUL 字节或管道结束libr/socket/r2pipe.c。这种发送一行、阻塞等待、读到 NUL 结束的模式正是草案中所说的well known communication channels。与此配套的还有几个关键设施链接模式radare2 可被直接以r2p名字调用读取R2PIPE_IN/R2PIPE_OUT环境变量并逐条执行参数命令binr/radare2/radare2.c用法如r2 -c !*r2p xIO 插件r2pipe://URI 插件把管道另一端当成一个可读写 seek 的 IO 设备其__system已经用PJradare2 的 JSON 构造器发送{op:system,cmd:...}之类的 JSON 报文libr/io/p/io_r2pipe.c测试客户端libr/io/p/io_r2pipe-test.js 演示了 Node.js 侧如何从R2PIPE_IN/R2PIPE_OUT读取 JSON 请求并以\x00结尾写回响应HTTP 模式r2pipe_open对http://、https://、r2web://前缀会走r_socket_http_post通道libr/socket/r2pipe.c配合 doc/r2pipe.html 所示的 Web 前端r2.cmd()回调用法。在这些机制上草案明确指出当前协议r2pipe1的痛点命令执行是阻塞式的无法并发发起多条命令stderr 消息无法捕获诊断信息会丢失或混入 stdout日志无法捕获内部 logging 与命令输出混杂没有与命令绑定的返回码调用方难以判断成功失败协议不可扩展元数据任何附加信息都没有标准位置安放。设计目标五条硬性需求r2pipe2 草案开门见山地列出新协议必须满足的需求这也是评估后续设计的验收标准非阻塞命令执行non-blocking command execution捕获 stderr 消息捕获日志logging关联返回码return code associated可扩展元数据extensible with metadata。可以看到这五条全部指向把通道从纯字节流升级为结构化、可寻址的消息流——只有报文自带命令标识、输出分类字段和元数据槽位才能同时满足非阻塞、分流 stderr/日志、携带返回码与扩展信息。总体方案JSON 报文 复用既有通道草案的提议非常务实定义一套基于 JSON 的新协议但继续使用既有的通信通道管道、HTTP 等来收发命令与输出。这样无需引入新的传输层已有的连接建立、文件描述符传递、Web 部署方式都可以直接复用。协议版本探测则通过首字节完成。r2pipe1 在连接建立后第一个字符是 NUL 字节\x00如 libr/io/p/io_r2pipe-test.js 中响应以\x00结尾所对应的历史约定r2pipe2 规定第一个字节改为左花括号{JSON 对象的起始符。这样一来旧的 r2pipe1 客户端可以识别到{而知道对面是 r2pipe2 实例新客户端也能判断对面是否支持 r2pipe2从而自动选择协议版本向后兼容得以在协议层天然解决无需额外的协商开关。握手Handshake协议版本与对端信息连接建立后双方先进行一次握手交换协议标识与对端信息。草案给出了客户端与服务端的完整示例。客户端表示发往服务端方向发送{ protocol: r2pipe, version: 2.0 }服务端表示返回给客户端应答{ protocol: r2pipe, peer: { name: radare2, version: 5.9.0 } }握手报文结构解读字段位置含义protocol顶层固定为r2pipe标识协议族version顶层请求客户端声明的协议版本示例为2.0peer顶层应答对端服务端的标识对象peer.name应答服务端程序名示例为radare2peer.version应答服务端版本号示例为5.9.0peer对象的设计为后续扩展留出了空间——服务端可以在此补充架构、能力列表capabilities等元数据而不会破坏既有字段的解析。运行命令请求、响应与 seqid握手完成后的命令交互采用请求-响应模式。客户端请求示例{ command: ij, expect: text/json, seqid: 1 }请求字段说明command要执行的 radare2 命令字符串示例为ij输出 JSON 格式的文件信息expect期望的输出类型示例text/json表示希望以 JSON 文档而非字符串形式接收输出seqid序列号sequence id由客户端自增分配用于把响应与请求一一对应。草案特别强调当客户端请求了 JSON 响应时输出会被内嵌进返回文档structured output而不是以字符串整体返回——这是 r2pipe2 与 r2pipe1 在响应形态上的根本差异之一。服务端响应示例{ responses: [{ seqid: 1, command: ij, time: 3824, logs: , stderr: invalid file, output: { core: { type: Executable file, file: /bin/ls, fd: 4, size: 9488 }, bin: { arch: arm, baddr: 4294967296, binsz: 88816, bintype: mach0, bits: 64, canary: true } } }] }原草案中logs: 缺一个引号、peer内version前缺逗号本文按 JSON 语法修正语义不变。响应报文是一个数组容器responses其中的每个元素代表一条命令的执行结果字段设计恰好一一对应五项需求字段对应需求说明seqid非阻塞执行与请求中的序列号对应客户端据此在并发场景下匹配响应command关联性回显触发该响应的命令原文time元数据命令执行耗时示例为毫秒级数值 3824logs捕获日志独立字段承载内部日志输出stderr捕获 stderr独立字段承载标准错误输出示例中为 invalid fileoutput结构化输出请求expect为 JSON 时内嵌结构化结果示例展示了core与bin两个子对象对应ij命令输出的文件类型、路径、fd、大小以及架构、加载基址、二进制类型mach0、位宽64、canary 等分析信息seqid 如何实现非阻塞草案用一段话点明了seqid的核心价值在后台运行命令时客户端不必阻塞等待可以连续发送多条命令之后根据返回的seqid判断哪条响应属于哪条命令。由于响应是请求-响应对理论上还可以实现乱序返回——慢命令晚回、快命令先回各就各位地按seqid归队。相比 r2pipe1 中r2pipe_cmd一次写一行、阻塞读到 NUL 的同步模型libr/socket/r2pipe.c这是吞吐与并发的根本性改进。对比 r2pipe1从字符串往返到文档往返把草案的请求/响应与 r2pipe1 的现有实现对照差异非常直观请求方向r2pipe1 直接发送命令字符串由r2pipe_write追加\nr2pipe2 发送 JSON 对象命令被包进command字段并附带expect、seqid等控制元数据响应方向r2pipe1 以 NUL 结尾的字符串整体返回stderr/日志混在 stdout 中无返回码r2pipe2 以 JSON 文档返回output、logs、stderr、time各归其位出错处理r2pipe1 中调用方只能靠r2pipe_read返回 NULL 感知失败libr/socket/r2pipe.cr2pipe2 中返回码可作为一个显式字段随响应下发调用方按码判定。值得一提的是r2pipe1 生态中已经出现用 JSON 包裹命令的先例——IO 插件的__system用PJ构造{op:system,cmd:...}报文libr/io/p/io_r2pipe.c__read/__write也发送{op:read,address:...,count:...}并解析result与data字段。这说明社区早已在实践中验证了JSON over pipe的可行性r2pipe2 草案正是把这种自发实践正式化、协议化并补上seqid、expect、logs、stderr、返回码等缺失维度。兼容性与迁移路径根据草案的表述可以梳理出清晰的兼容策略首字节即版本信号NUL 表示 r2pipe1、{表示 r2pipe2两端通过读取首个字节即可分派到正确的解析器协议可以并存传输层不变forkpipe、R2PIPE_IN/R2PIPE_OUT环境变量、HTTP/r2web POST 等通道继续沿用只是报文内容从裸文本变为 JSON 文档响应容器化所有响应统一放进responses数组即便单条命令也返回数组示例中只有一个元素这为未来批量命令、流式/分帧输出预留了结构元数据可扩展peer、responses元素都允许追加新字段老客户端忽略未知字段即可新字段不需要变更协议版本号。需要说明的是doc/r2pipe2.md明确是RFC 草案draft并非已落地的实现仓库中目前不存在protocol: r2pipe、version: 2.0握手逻辑的代码。文中的协议细节以草案为准实现在未来版本中可能依据 RFC 反馈而调整。读者如果希望动手验证既有 r2pipe1 的报文形态可参考 libr/io/p/io_r2pipe-test.jsNode.js 端读取R2PIPE_IN/R2PIPE_OUT的完整示例与 binr/radare2/radare2.cr2p链接模式入口。总结doc/r2pipe2.md为 radare2 的进程间通信协议勾勒了一幅清晰的演进蓝图以 JSON 为报文格式、复用既有管道与 HTTP 通道、用首字节{替代 NUL 完成版本探测、以seqid支撑非阻塞并发并通过output/logs/stderr/time等字段分别承接结构化输出、日志、错误与执行元数据同时为返回码与任意扩展信息预留位置。这一设计直接回应了 r2pipe1 在 libr/socket/r2pipe.c 中所体现的一行命令 阻塞读 NUL 结尾模型的全部短板也为 r2pipe 协议后续的工程化落地提供了可供评审与实现的基础。【免费下载链接】radare2UNIX-like reverse engineering framework and command-line toolset项目地址: https://gitcode.com/gh_mirrors/ra/radare2创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表