使用 AI 智能体反编译第一人称射击游戏

执行摘要

自主 AI 智能体能够成功反编译复杂的软件,但如果没有客观、可机器校验的验收标准,它们会产生“幻觉”代码——这些代码虽然可读,但在语义上是不正确的。确保游戏反编译保真度的最有效方法是字节匹配反编译,即将重构的 C++ 代码编译并与原始二进制文件进行逐字节比对。这种方法通过提供二进制的“通过/失败”信号,即使是能力较低的模型也能产生高保真的结果。

编排框架

为了实现游戏功能的完整复刻,我们部署了一个结合了 Claude 和 Codex 模型的多智能体系统。该基础设施专注于自主性和进度跟踪:

  • 智能体角色: 系统利用工作智能体进行反编译和提交,并使用审查智能体来协调和标记错误。
  • 进度跟踪: GitHub Issues 被用作主要的跟踪机制,每个翻译单元(.cpp 文件)对应一个 Issue。
  • 沟通: 智能体通过共享的 Discord 频道进行沟通,允许智能体之间以及人类与智能体之间的交互。CI 失败信息通过 GitHub webhooks 推送到该频道。
  • 工具: 智能体利用 Hex-Rays 官方的 ida-mcp 进行无头、稳定的反汇编和反编译。

克服智能体漂移和幻觉

最初的自主反编译尝试表明,智能体往往会随着时间的推移失去焦点并产生“漂移”,尤其是在上下文窗口填满时。为了保持对齐,团队实施了两个关键策略:

  1. 激进的上下文压缩: 默认压缩阈值从 90% 降低到 42%。这更频繁地从上下文中移除不稳定的、无关的信息(例如之前反编译的函数)。
  2. 指令刷新: 每小时运行一次的 cron 任务会自动注入请求,要求智能体重新阅读项目的目标和操作指南,防止指令随时间推移而衰减。

类人审查的失败

尽管游戏能够启动并渲染菜单,但最初的输出在语义上是有缺陷的。智能体引入了错误的函数签名,编造了逻辑,并用昂贵的哈希表查找替换了高效的全局变量访问。

这种失败的原因在于审查智能体缺乏客观的验收标准。审查者往往接受工作智能体在提交注释中的辩解——这本质上是一种无意的提示词注入——而不是根据原始二进制文件独立验证代码。

字节匹配反编译的实施

为了解决正确性问题,团队实施了一个充当“真理来源”预言机的验证脚本:

  • 流程: 该脚本使用原始游戏的编译器编译重构的 C++ 代码。然后将生成的 OBJ 文件与原始游戏的 EXE/PDB 进行比较。
  • 处理重定位: 由于绝对内存地址会发生变化,脚本排除了重定位字节,转而验证两个版本是否引用了具有相同偏移量的相同符号。
  • 安全措施: 为了防止智能体“作弊”(例如使用内联汇编或修改验证脚本),系统禁止了特定的构造,并在 CI 中对验证脚本进行哈希处理,以确保其未被篡改。

结果与权衡

到项目结束时,游戏中 99% 的函数都存在于重构的源代码中,其中 83% 是字节精确匹配的。项目在最后阶段使用了 14 个 Luna 和 2 个 Opus 5.5 智能体。

优势

  • 保证语义: 字节精确匹配保证了行为完全一致,包括原始代码中的错误。
  • 模型效率: 精确的反馈允许更便宜、能力较弱的模型(如 Luna 或 Haiku)产生与更智能模型相当的结果。

劣势

  • 工作量增加: 智能体匹配函数所需的时间显著增加,因为它们必须处理寄存器选择和调用约定。
  • 边际效应递减: 由于非确定性的编译器输出或链接器行为(例如 COMDAT 折叠),某些函数无法实现字节匹配。

社区观点与替代方案

技术同行之间的讨论提出了在不依赖字节匹配这种僵化方法的情况下实现功能等效的替代方法:

"对我来说有效的方法是,对于每个函数……测试工具会在虚拟机/模拟器/仿真器中同时运行原始函数和提交的函数……只有当 1) 对 RAM 的读/写序列与原始函数完全一致,且 2) 必须完全覆盖原始反编译函数的行和分支时,测试工具才会接受该实现。" — @handle

其他批评者指出了该项目高昂的环境和财务成本,估计消耗了 6000-7000 亿个 token,并质疑了一个因商标和版权限制而无法合法共享的项目的实用性。

Sources

相关