01 十月的一个晚上,我把 EXE 交给了 Codex
和很多人一样,我是在资讯推送里发现 REA 的。我看了几段 YouTube 演示,带着开发者惯有的怀疑:这些年见过太多号称无所不能的革命性工具,唯独放到自己的项目上就不行。终于,在十月一个漫长的晚上,我让 Codex 安装所需工具,并准备好 REA。
最初的问题很简单:“这个按钮是怎样工作的?”“右下角那段文字对应什么?”我主要想知道,它究竟能不能真正分析应用,还是只会为自己没有理解的东西编出一段非常可信的解释。随后,我几乎是带着试探的心态提出:“你能不能把这个应用重新做出来,保持功能等价,然后用你选择的语言编译?”
五个多小时后,它告诉我第一版已经完成,列出了尚待处理的部分,并给出一个可执行文件供我测试。我启动程序。在我尝试的界面和操作路径中,感觉就像回到了原来的应用。这不是一段说明,也不是一个设计稿,而是确实能运行的程序。我真的被震住了。
接着,我又研究了另一个更难分析、保护措施更多的项目。结果仍然让我惊讶。我不会在这里公开软件名称,也不会介绍其保护机制:本文的重点不在于此。我当时的第一反应很夸张,却完全真诚:“桌面软件完了。编译后的软件现在都成了开源软件。”冷静一点后,我会换一种表达。真正受到冲击的,是“只交付可执行文件、不交付源码,就能让软件长期保持不可理解的黑箱状态”这种想法。
02 用一个丢失说明书的玩具解释 REA
想象一列用积木搭成的小火车。火车还在,说明书却丢了。你可以观察轮子怎样转动、按哪个按钮会亮灯,以及零件之间似乎如何连接。一个足够有耐心的人,就可能重新写出一份说明书,搭出行为相近的火车。但这不一定是原来的说明书,也不一定采用完全相同的零件布局。
软件的道理很接近。可执行文件就是已经搭好的火车。逆向工程工具用于检查内部机制。REA 让 AI 智能体能够有组织地使用这些工具。智能体收集证据、提出解释,然后可以编写并测试新的实现。编译步骤再把这份实现变成可在目标设备上运行的程序。[1][2]
这是简化解释:新的说明书不一定等于原始说明书。
即使采用这种给孩子听的解释,也有一个关键点:丢失的说明书不会自动恢复。目标是尽可能理解其工作方式,再重新编写说明。开发者的注释、被移除的变量名,以及某些设计意图,不会因为有 AI 参与就自然重新出现。
03 技术背后:REA 不是独自完成一切
REA 是 Reverse Engineer Anything 的缩写。项目提供 MCP 服务器、命令行接口等能力,把智能体与已有的分析工具连接起来;它不是凭空出现的万能反编译器。对于原生二进制文件,REA 可以根据配置和可用能力使用 Ghidra、Hopper 或 IDA 等分析引擎。例如,Ghidra 本来就具备反汇编、反编译和分析图谱等功能。[1][3]
MCP,即 Model Context Protocol,在这里承担智能体与工具之间的接口角色。智能体不必让我手工复制一页又一页分析结果,而可以直接调用分析函数并获取返回值。Codex 支持连接 MCP 服务器,因此 REA 为它提供的是一个调查环境,不是对所有软件的神奇全知能力。[4][5]
| 组成部分 | 负责什么 |
|---|---|
| 智能体,这里是 Codex | 组织调查、提出假设并编写重建实现。 |
| REA | 提供工具,返回观察结果及其限制。 |
| Ghidra、Hopper 或 IDA | 检查二进制中的指令、函数、引用和伪代码。 |
| 编译器 | 为指定平台生成新的可执行程序。 |
| 测试 | 验证重建程序实际做了什么。 |
调查可以从屏幕上一段文字开始,找到引用它的函数,沿着调用关系继续分析,再与实际点击时的行为比较。REA 的文档描述了这类定向分析。但代码中存在某种关联,并不代表对应场景已经实际运行过:必须区分静态分析与运行时观察。[2]
因此,整个过程是一个循环:观察、理解、实现、编译、运行、比较、修正。真正让我印象深刻的是这些步骤被串联起来。逆向工程远早于 AI 智能体;对我的日常工作而言,变化在于从“对二进制提出问题”到“获得可修改版本”的速度。
官方文档提供的入门方式之一是 npx rea-agents setup。配置向导会先展示集成项和拟执行的修改,再请求批准。这并不意味着无需准备合适的分析引擎,也不意味着可以忽视其许可证。为了复现实验,最好同时记录 REA 版本、分析引擎和模型,而不只是保存提示词。[6]
04 为什么我反复强调“原生运行”
我的目的不只是让旧游戏启动,而是得到一个为当前设备构建的程序。这与把原始可执行文件放进兼容环境或模拟器中运行,是不同的目标。
| 路径 | 希望得到什么 |
|---|---|
| 兼容层 | 通过调整运行环境,让原程序继续工作。 |
| 模拟 | 重现另一台机器或部分硬件组件的行为。 |
| 重建与原生移植 | 为目标平台编译一份新的实现。 |
这不代表模拟方案更差。模拟器依然非常有价值,我之前尝试过的兼容层也帮过不少忙。我只是有不同的需求:能够修改程序本身,调整显示、手柄输入或联网行为。
这里要澄清一个技术问题:在提示词里写“原生运行”,并不会在逻辑上强制完整重写所有代码。这是一项结果要求。具体方案可能混合重建代码、兼容库或部分程序翻译。所以必须检查实际构建了什么、运行了什么,而不只是相信智能体使用的术语。为不同目标编译,也需要相应的库和构建环境。[8]
让旧程序继续运行
原始二进制
↓
兼容环境或被模拟的机器
↓
在调整后的环境里保留原有行为
为目标平台重新构建
观察结果 + 重建实现
↓
针对各个平台分别编译
↓
Windows x64 / Linux ARM64 / macOS ARM64
同为一种 CPU 架构还不够:操作系统、库和测试仍需分别适配。
05 Cluedo:回到外婆的 Pentium III 前
我也在慢慢变老。有些游戏让我想重玩,并不是因为它们拥有今天最先进的画面,而是它们能把我立刻带回某个年代。1998 年版《Cluedo》就是其中之一。我仿佛又坐在外婆的 Pentium III 电脑前,在 2000 年代初花着完全合理的时间寻找凶手。当然,是按照我自己的标准来说“合理”。
于是,我重新翻看那些通常被归入“abandonware”的旧游戏目录。这个词方便人们寻找某个年代的作品,但它不是下载或重新分发目录中一切内容的法律许可。后面还会说到,因为这是整个话题的重要部分。[12][14]
在我研究的那份 Cluedo 副本中,我的排查涉及一个 32 位程序和一个旧的 16 位组件。这里说的是我在具体副本中的判断,不是对所有版本的统一结论。普遍性的兼容问题则有官方依据:Windows x64 不提供用于运行旧 16 位 Windows 应用的 NTVDM。因此,一个游戏的主程序即使是 32 位,也可能被更老的辅助组件卡住。[7]
我给 Codex 的要求很明确:利用 REA 工具,生成一个能在现代 x64 Windows 上原生运行的版本,并使用较高的推理强度。经过几个小时和必要的迭代,我得到了可以玩的版本。特别让我震撼的是,起点并不是游戏的源码仓库,而是它当年分发的文件。
06 既然已经做了,那就加上 16:9,再上 Raspberry Pi
游戏运行后,我马上遇到了一个很现代的问题:家里已经没有 4:3 显示器了。所以我要求把界面适配到 16:9。我不想只是拉伸画面,让角色都变成略微压扁的自己,而是希望显示内容能合理适应新屏幕。
这类修改必须考虑元素布局、点击坐标和资源比例。画面看上去可能已经正确,交互区域却还留在旧位置。因此需要测试的是一组行为,而不是只修改某个文件里的分辨率数字。
然后我继续加码:“现在,我要它在 Raspberry Pi 4 的 ARM64 系统上原生运行。”最后,我得到了可以在 Pi 上使用的版本。小时候在外婆的 PC 上认识的游戏,如今运行在这台小机器上,那种感觉很奇妙。
我随后玩了几局,没有遇到 bug。我有意这样表述:几局游戏中没有碰到 bug,不等于证明程序不存在 bug。但对我的使用方式和已经尝试的路径而言,这不再是一个只能展示菜单的演示程序。我确实可以玩。
07 Daytona USA Deluxe:宽屏与 Xbox 手柄
Cluedo 之后,我继续尝试 1997 年的 PC 版 Daytona USA Deluxe。目标没有变:让它在 Raspberry Pi 上运行,适配 16:9,不必为了玩游戏维持一整套老旧环境。
完成这一步后,我提出了一个非常实际的要求:使用现在的 Xbox 手柄。不想为了情怀再找一只 Saturn 手柄,也不想整个晚上折腾键盘映射。模拟器往往可以提供自己的映射功能;但在这个项目里,我希望把手柄支持加入重建版本。因此,修改针对的是这个版本的输入处理,我也用这套配置玩到了游戏。
从这里开始,实验的性质变了。我不再只是保留原来的行为,而是在让程序继续演进。旧二进制提供理解的起点;重建版本则成为一个能够继续开发的项目。
对于这种移植,我倾向于 C++ 和可控的依赖。这不意味着性能自动得到保证:糟糕的算法即使用 C++ 编译,依然是糟糕的算法。但在 Raspberry Pi 上,我更愿意采用能够理解其成本的架构,而不是因为智能体提议了某些组件,就把一层又一层东西堆起来。
08 Destruction Derby:再加个局域网联机?
1995 年推出的 Destruction Derby,是我 PlayStation 时代另一个深刻记忆。到了 2026 年,它已经超过三十岁了。第三次实验仍采用相同目标:16:9、ARM64、Xbox 手柄。随后,我开始想,能不能再进一步,和家里的其他电脑一起玩?
于是我要求加入网络多人模式。在自己的重建项目中,我得到了支持局域网游戏的版本,并有适用于 Windows、Mac Apple Silicon 和 Raspberry Pi ARM64 的构建。这里讲的是我的项目与测试结果,不是官方移植,也不是对所有设备的兼容承诺。
增加多人功能,显然不是把两个“开始游戏”按钮连接起来。需要确定交换哪些信息、由谁决定游戏状态,以及不同机器在不同时间收到数据时怎么办。位置、碰撞和同步都会变成独立的开发问题。这些内容用来解释需要处理的工作,并不意味着我在本文公开了自己版本的确切网络协议。
还要补充一个架构问题:Mac Apple Silicon 与 Raspberry Pi 都可以是 ARM64,但不代表它们运行同一个可执行文件。操作系统、库和工具链都不同。真正有价值的是一份可以适配多个目标的代码库,而不是一个到处复制就能运行的万能文件。[8]
09 看起来像黑魔法,但并不是一个“转换”按钮
讲起这些经历时,我很愿意用“黑魔法”来形容。起点与结果之间的反差,足够让我在喝咖啡时这样感叹。但技术上仍要区分几个过程:分析原程序、重建行为、可能复用部分资源,以及编写新功能。
图像、音乐、视频、文本和关卡,不会突然变成可以自由复用的 C++ 代码。重建程序可能仍需要原版游戏的数据文件。如果没有清晰的资源清单,就无法判断哪些是新代码、哪些依赖原副本,以及哪些内容可以分享。REA 项目本身也强调,分析输出不会赋予使用者原软件的权利。[14]
要认真评估一个结果,我期待的不只是打开一个窗口,还包括可复现的编译、关键操作路径、能够正确载入的存档、实际使用的控制方式,以及目标机器上的测试。游戏时长、未覆盖场景和回归问题同样重要。智能体宣布“完成”,不等于验证工作已经完成。
正因为如此,这些实验可以很有价值,却不应被包装成普遍承诺。我不是说所有二十年前的应用都能在五小时内重写。我说的是,在自己试过的某些项目里,预想投入与实际结果之间的差距,确实让我惊讶。
10 编译后的软件已经变成开源了吗?
我最初的反应是:“现在一切都是开源了。”这很像一个受到冲击的开发者会说的话,却不是准确的定义。开源不仅意味着能看到代码,还涉及授予使用、修改和重新分发权利的许可证。重建出一个程序,并不会自动改变原软件的许可证。[11]
我看到的真正变化是经济和技术层面的。如果理解并重建行为所需的人力减少了,软件商就不能再像以前那样,仅凭交付不透明二进制文件来维持壁垒。但它的价值并不会因此消失:支持服务、质量、更新、数据、保障和生态,并不等同于一个 EXE。
杀毒软件就是一个例子:重建部分客户端,并不会自动复制威胁研究、持续更新和配套服务。对于 IDE,理解某种行为与移除许可证检查,同样是不同目标。不能把分析能力误认为免费使用整个产品的权利。[14]
这也不代表所有受保护代码立刻变得透明。受组件、加密、混淆、依赖以及实际可获得信息的影响,分析仍可能不完整。REA 明确描述了观察结果的局限;智能体不应该把缺失的信息替换成写得很好看的肯定结论。[2][14]
所以,对我而言,桌面软件没有死。它甚至可能迎来第二次生命:在技术和法律允许的前提下,更容易移植、修复和适配。真正受到打击的,是“源码没了,所以什么都做不了”这种宿命感。
11 CPC464 上的 Chrome,以及 PS2 的各种承诺
到了这个阶段,想象力当然会开始失控:“给我的 Amstrad CPC464 做个现代 Chrome 怎么样?再焊点内存就搞定了。”😄 这个玩笑很能体现当时的兴奋。但多加 RAM 并不会把那台机器变成现代电脑。真正可讨论的会是大幅裁剪的适配、demake,或远程渲染,而不是毫无妥协地搬过去同一个完整浏览器。
对 PlayStation 2 也应保持同样的谨慎。工具能够分析部分指令或某些二进制文件,并不意味着能自动把任意游戏重建成 ARM64 原生版本。分析引擎、文件格式、平台特有组件与测试依然决定结果。在为本文查阅的公开文档中,我没有找到关于 PS2 原生移植的普遍保证,因此不会宣布它“肯定会在文章发布前实现”。[1][15]
这并不削弱这个方向的吸引力,只是避免把对快速发展技术的热情,变成凭空编造的交付时间表。
12 面对 SaaS,拼图缺了一部分
前面的故事都有一个重要优势:程序的相当一部分内容存在于我能拿到的文件里。但 SaaS 应用不同。浏览器不一定会收到业务引擎,它收到的是显示页面和与服务器通信所需的内容。
REA 文档介绍了如何观察授权环境中可访问的页面、脚本和网络交互。这些线索可以帮助理解界面、参数以及部分行为,但不会自动揭示服务器源码。看见一条 API 响应,并不等于拿到了生成它的函数。[9][10]
客户端:授权范围内可以观察
收到的界面和脚本
发出的请求与收到的响应
服务器:不会交付给浏览器
业务代码与未观察到的规则
数据、内部任务和基础设施
同一条响应可能来自多种不同实现。
以发票为例,前端可能提交一个金额,收到一个状态。而服务器内部可能执行十五条规则:权限、公司、日期、客户类型、合同例外或连续审批。如果我只观察到一个案例,就不知道另外十四种情况。多种不同实现,都可能产生我看到的同一条响应。
基于规范、授权场景和测试,仍然可以开发替代实现。只是业务专家马上又变得不可或缺。已经关服的游戏同样如此:理解客户端可能有助于设计兼容服务器,却不会神奇地恢复历史数据、基础设施或从未观察到的规则。
13 那么,从法律上说合法吗?
我最初想写:“当然不合法。”这和“AI 重写了,所以我拥有全部权利”一样不准确。在欧洲法律框架下,有权使用软件的人对其运行进行观察,受到具体规则约束。为实现互操作性而必需的反编译,也存在附带严格条件的例外;这不是任意克隆产品的普遍权利。[12]
还必须区分功能与程序的表达形式。在 SAS Institute 对 World Programming 一案中,欧盟法院指出,功能本身不是软件著作权所保护的表达形式。这不意味着可以自由复制代码、说明文档或应用中的全部创作性内容。独立重新实现与复制受保护内容,不是同一件事。[13]
“Abandonware”这个称呼、游戏年代久远,或发行商关闭,本身都不会产生重新使用许可。同样,拿到一份由 AI 新生成的源码,并没有自动解决来源与权利问题。分析、修改、运行、公开和分发是不同的行为,需要分别判断。[12][14]
因此,我保留这份惊叹,但把问题分开。适用法律还取决于国家、合同和计划用途;这里提供的是欧洲背景下的参考,不是个性化法律意见。把挽救软件的技术可能性,误认为可以占有其全部组成内容,反而会辜负这项技术的价值。
14 这对业务软件意味着什么
除了游戏,我还想到那些只能保存在虚拟机里的程序,因为没人知道怎样替换它。依赖旧版 Windows 的财务工具。厂商已经消失的工业软件。只有三个人理解、其中两人已经退休的文件格式。
在获得授权的范围内,价值可以远早于完整重写出现:记录行为、识别一个计算过程、理解文件格式、隔离依赖并建立基准测试。这已经非常有用。也可以只现代化其中一部分,而不是一开始就让智能体重做整个世界。
但业务软件不会因为界面长得像旧版本就获得验证。舍入规则、历史记录、业务流程和例外情况,有时恰恰是它真正的价值所在。智能体产出代码越快,业务样例、可追溯性与对照测试就越重要。我不会仅仅因为窗口漂亮而且编译通过,就把财务结账交给它。
15 软件的终结,还是保存软件的新方式?
短短几年,我的工作先被 AI 助手改变,又被开发智能体改变。REA 的实验再加上了一块拼图:我不必把旧可执行文件看作永远冻结的东西。我可以开始向它提问,理解其中一些部分,并考虑过去大概不会启动的重建项目。
标题是有意挑衅的。我不认为软件将会消失,也不认为一句提示词能取消作者的权利。但我认为,我们与软件依赖之间的关系正在变化。当人们能够亲自实验时,保存、可修复性和互操作性就不再只是抽象口号。
还有一个远远超出 Raspberry Pi 的问题:怎样保存软件中的知识,同时尊重创造这些知识的人?认为知识应当流通,并不需要否定作者的劳动。它也可以促使我们更认真地安排许可证、源码交接,以及产品结束支持后的生命周期。
在解决整个哲学问题之前,我还有一件重要的事:继续玩完这局 Cluedo。在 Raspberry Pi 上。用 16:9。这个结果,我之前是真的没想到。
资料来源与参考
- REA — 官方仓库、架构与范围
- REA — 原生二进制分析
- Ghidra — 官方仓库
- Model Context Protocol — 架构概述
- OpenAI — Codex 与 MCP
- REA — 安装与配置
- Microsoft Learn — NTVDM 与 16 位应用支持
- LLVM / Clang — 交叉编译
- REA — 使用 CDP 观察网站
- REA — 网络交互捕获
- Open Source Initiative — 开源定义
- 欧盟指令 2009/24/EC,第 1、4、5、6、8 条 — 官方公报(PDF,英文)
- 欧盟法院 — SAS Institute / World Programming,C-406/10,2012 年 5 月 2 日新闻稿(PDF,法文)
- REA — 负责任使用、分析输出与相关权利
- REA — 官方更新记录
本文基于个人实验,并参考截至 2026 年 10 月 27 日查阅的公开资料。文中游戏与重建程序未经独立审计。法律说明仅提供欧洲框架下的参考,不构成个性化意见。本文不分发游戏可执行文件、受保护资源或绕过保护的操作流程。




评论
0 条评论暂无已发布评论,欢迎率先参与。