ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

编译后的界面如何变成可追溯的连接图:REA Interface Builder 解码器完整拆解

编译后的界面如何变成可追溯的连接图:REA Interface Builder 解码器完整拆解

编译后的界面如何变成可追溯的连接图:REA Interface Builder 解码器完整拆解

【免费下载链接】reaReverse engineer anything with agents, from app behavior down to native binaries.项目地址: https://gitcode.com/GitHub_Trending/rea2/rea

REA(Reverse Engineer Anything)提供了一组 Interface Builder 解码器,能把 macOS / iOS 应用包(.app)里编译后的storyboard与.nib 归档静态还原为视图层级、outlet(出口)、**action(动作)**与segue(跳转)的连接图。全程不执行任何代码、不依赖 Apple 官方工具(如 ibtool)、不加载任何 UI 类,甚至可以在 Linux 上运行。输入只有一个.app包路径,输出是一张只读 JSON 图:每个节点与边都携带归档路径和 SHA-256,可逐条追溯。

为什么编译后的界面变成了"二进制流"

你在 Xcode 里拖控件画界面,但编译产物并不是可读的 XML,而是 Apple 的私有序列化格式:

源文件编译产物格式特点
Main.storyboardMain.storyboardc/objects.nib二进制 plist(bplist00)
Settings.xibSettings.nibNIBArchive 二进制流

这两种文件都是"对象表 + 编号互引"的结构:控件、视图控制器、连接各是一个条目,条目之间用数字编号互相指向。没有解码器,十六进制编辑器里看到的只有乱码。这个解码器做的事,就是把这份"乱码"翻译回你能读的界面结构——只靠读字节完成,不运行应用里的一行代码。

一条命令完成解码

安装 REA 后(npx rea-agents setup注册到你的 Agent,或直接使用 CLI),对任意.app包运行:

rea decode-interface-builder MyApp.app

对应 MCP 工具名为decode_interface_builder。命令带三个限流参数:--max-documents(最多 64 个归档)、--max-objects(最多 2 万个图对象)、--max-connections(最多 4 万条连接),默认值即上限。命令定义见 artifactCommands.ts,分析入口是 InterfaceBuilderAnalysis.ts 的analyzeInterfaceBuilderBundle:它遍历包内所有.nib与storyboardc/objects.nib,按文件头NIBArchive/bplist00自动分派解码路径。

从二进制流到连接图的三步

第一步:头判定与四表解析。NibArchive.ts 的decodeNibArchive校验NIBArchive魔数与格式版本,依次读出对象表、键表、值表、类表。对象间的引用以$nib_object_ref编号原样保留,不展开、不实例化任何 UI 类。

第二步:引用展开与循环保护。归档里天然存在循环引用(视图 ↔ 父视图),盲目内联展开会无限递归。REA 的策略是:引用最多解析为字符串或桩节点;层级遍历(subviews/contentView/childViewControllers,见 NibViewHierarchy.ts)限制深度 32 层、每个对象只访问一次。同时把NSClassSwapper/UIClassSwapper解析为真实类名,你在输出里看到的是实际类而不是"交换器"占位符。

第三步:统一图投影。interfaceBuilderGraph.ts 的buildInterfaceBuilderAnalysis把每个文档投影为节点 + 边:根节点是scene或storyboard;对象节点自动分类为view_controller、view、control、constraint、layout_guide等;边分四种关系——contains(层级包含)、outlet_to(出口指向)、target_action(动作目标)、segue_to(场景跳转)。它同时识别 AppKit 的NSNibOutletConnector与 UIKit 的UIRuntime*Connection两套连接对象命名约定,后者还会还原出ui_event_mask(触摸、长按等事件类型)。

输出字段该看哪里

结果是只读 JSON 图,重点看四处:

  1. documents:每个.nib一条,含document_kind(nib或storyboard_scene)、object_count、connection_count、hierarchy_complete(层级是否完整);
  2. graph.nodes / graph.edges:每个 outlet 从哪个视图控制器连到哪个控件,每个 action 的 selector 名与目标——目标为nil时即 First Responder。无法解析的边会被标记resolution: unresolved并附原因,而不是静默丢弃;
  3. graph.coverage:objects / connections / hierarchy / classes 四个维度的complete或partial状态,附omitted计数与原因,告诉你结果里"缺了什么、为什么缺";
  4. limitations:明确的证据边界声明,例如"selector 只是 Interface Builder 层面的观察,不证明二进制中存在对应实现"。

完整场景的测试样例可参考 MacFixture.storyboard:一个按钮同时带 outlet 与 action 的用例。

它能做什么,不能做什么

  • 🔍适用:iOS / macOS 应用的界面结构取证、控件与 outlet 命名习惯审计、segue 跳转路径梳理
  • ⚠️边界:不解约束的运行时求解、不推断像素几何、不识别未收录的私有归档字段;归档输入总量限 32 MiB、解码表示限 256 MiB,超限归档会被记录为 omitted 而非报错
  • 📁延伸:Apple 应用分析总览 docs/apple-application-analysis.md,端到端验证脚本 interface-builder.mjs,归档解析测试 interfaceBuilderUIKitKeyedArchive.test.ts

掌握decode-interface-builder,你就不必再对着十六进制编辑器猜界面——storyboard 里的每个控件、每条出口、每个按钮背后的 selector,都会摊在一张可追溯、且明确标注自身证据边界的图上。

【免费下载链接】reaReverse engineer anything with agents, from app behavior down to native binaries.项目地址: https://gitcode.com/GitHub_Trending/rea2/rea

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进