最近很多人在討論 REA(Reverse Engineer Anything)。它在 2026 年 4 月開源,半年累積了十萬多顆星,10 月初還衝上 GitHub 趨勢榜第一。1 它的宣傳很直接:看到別人 App 裡喜歡的功能,叫你的智慧體(agent)去拆,告訴你它怎麼做的、證據在哪,再幫你做一個。2 這篇我想看的是它的架構:一個 MCP 伺服器,憑什麼讓智慧體完成過去要資深逆向工程師才做得了的事。
逆向工程缺的是調查者
逆向工程的工具早就存在。最常用的是三個分析軟體:IDA 是比利時 Hex-Rays 公司的商業軟體,也是業界標準;Ghidra 是美國國安局(NSA)開發、2019 年開源的免費工具;Hopper 是 Mac 和 Linux 上價格較親民的商業軟體。它們做的事差不多:把編譯好的執行檔反組譯(disassemble)成組合語言,再反編譯(decompile)成類似 C 的偽代碼(pseudocode),並列出程式裡的字串、函式名稱,以及哪個函式呼叫了哪個函式。偽代碼比組合語言好讀,但原本的變數名稱和結構在編譯時已經遺失,它是工具推測出來的版本。網頁和 Electron App 這一側,瀏覽器的開發者工具能看到每一支腳本和每一個網路請求。難的是把這些工具串起來:從一個看得見的行為出發,猜它可能在哪個函式,去找字串、追呼叫者、讀偽代碼,發現猜錯了再回頭。這是調查,靠的是經驗和判斷,工具本身不會替你決定下一步。
LLM 剛好擅長這種「讀一堆片段,猜下一步去哪」的工作,也很會把偽代碼改寫成乾淨的程式。它的問題是會把猜測講得跟事實一樣肯定。逆向工程最怕這個,偽代碼本來就是推出來的,再疊一層模型的推論,很容易得到一份讀起來合理、實際上錯的解釋。
REA 的設計就是針對這兩點:把分析引擎變成智慧體能呼叫的工具,讓它負責調查;同時規定每個工具回傳的結論都要帶著證據和可信程度,讓它沒辦法把推論偷渡成事實。
一個入口,接上既有的分析引擎
REA 本身不寫反編譯器。它的做法是當轉接層:原生執行檔交給使用者已經有的 Hopper、Ghidra 或 IDA,Android 交給 JADX 和 Apktool,韌體交給 Binwalk,JavaScript 的模組還原交給 Wakaru。2 這些都是逆向圈用了很多年的工具,REA 只負責把它們包成一致的介面。
包法很講究。以 Hopper 為例,REA 在 Hopper 啟動時注入一支 Python 橋接腳本,透過 Unix socket 和一組隨機 token 跟 REA 溝通,所有 Hopper API 都留在 Hopper 自己的 Python 執行緒上呼叫,因為換到別的執行緒會讓 Hopper 卡死。3 Ghidra 用暫時的資料庫跑無頭分析,IDA 只讀不寫,都不會改動被分析的檔案。4 每個分析目標在一次工作階段裡只綁定一個深度分析引擎,選擇規則是固定的,也沒有自動退回別的引擎。5 這樣同一個問題問兩次,得到的答案來自同一個來源,智慧體比對前後結果時才有意義。
程式分層也照這個思路走。最內層是不碰外部世界的 domain,定義證據、比對和應用程式圖;外面是 schema、共用流程,再外面才是各引擎的轉接器,最外層是 CLI 和 MCP 兩個入口。5 兩個入口走同一套流程,所以人在終端機跑的結果和智慧體透過 MCP 拿到的結果一樣,人可以直接重跑智慧體的調查來檢查。
證據模型:觀察、推導、推論、未知
我認為 REA 能成立,關鍵在證據模型。每一筆證據記錄三件事:它從哪裡來、它有多可信、它指向哪裡。6
「從哪裡來」分成五種權威:出貨的成品本身、受控的重播、歷史參考、外部服務,以及分析者的推論。「多可信」分成三級:直接觀察到的、從觀察推導出來的、推論的。「指向哪裡」是位址、檔案偏移量或路徑,加上目標檔案的 SHA-256。同一個函式,「它呼叫了 memcpy」是觀察,「它在複製封包標頭」是推論,兩者在資料結構上就分開了。
最重要的一條規則是:沒檢查到的範圍算「未知」,不算「沒有」。4 一個工具回報「找不到呼叫者」時,要分清楚是真的沒有,還是只掃了一部分;輸出被截斷時,不會當成完整的觀察來解析。7 目標檔案在分析途中被改過,REA 會回報檔案已變更,停止給出對不上原檔的位址。
這些規則看起來瑣碎,對智慧體卻是決定性的。LLM 最常見的錯,就是把「沒看到」說成「不存在」,把「大概是」說成「就是」。REA 把這兩種錯在工具層擋掉,智慧體拿到的每個結論都附上它的權威和可信度,它要往上疊推論,也只能標成推論。
工具照分析者的問題設計
REA 的 MCP 工具很多,設計文件定了一條原則:從分析者想問的問題出發。8 工具大致分成六種形狀:檢視一個目標、搜尋候選、追蹤關係、比對兩個版本、組合成一個工作流程,以及觀察執行期行為。能擴充現有工具就不新增,新增的工具名稱不綁定特定引擎,各引擎能涵蓋到哪裡,另外照實回報。
另一條原則是限制要有真實的理由。分頁、截斷這類上限,只能來自格式、協定、權限或實際量測到的資源;「怕塞爆智慧體的 context」不算理由。8 這跟很多 MCP 伺服器的做法相反,它們常為了省 token 先砍結果。REA 的考量是,結果被砍掉卻沒說,智慧體就會在不完整的資料上下結論,代價比多花一些 token 大得多。
重建要過驗證才算數
拆完之後要「做一個」,REA 也有對應的機制,叫重建義務帳本(reconstruction obligation ledger)。靜態分析得到的事實會產生一份「重建必須做到什麼」的清單,每一項要有唯一的負責實作、需要的測試案例,以及一個權威層級跟原始觀察相當的驗證器實際跑過並通過,才算關閉。9 有矛盾、有殘留的未知、缺了相依項目,這一項就保持開著或判為失敗。專案自己的整體檢查也是同一個態度:失敗、未知、不支援、被截斷、被略過,任何一個都不會被彙總成「通過」。10
官方案例展示了這個流程的效果。DX-Ball 那個案例從一個音效呼叫追到計算左右聲道的函式,把不完整的偽代碼改寫成 C,重建結果通過 3,205 個用原始 x86 程式產生的測試案例,編譯出來的 63 個位元組也跟原版一致。2 智慧體寫出來的東西有沒有對,在這裡是可以驗證的,不用靠讀起來像不像。
靜態分析之外:JavaScript 與執行期
現在很多桌面 App 是 Electron 做的,這部分 REA 不需要反組譯引擎。它直接讀解開的 App 目錄或 ASAR 檔,靜態分析出模組、import 關係,以及 Electron 裡渲染程序、preload 和主程序之間的邊界;整個過程不執行目標的程式碼。211 Notion 的案例就是從畫面上的剪貼簿功能,一路追過 preload 和 IPC,找到主程序處理富文字格式的地方。
靜態分析看不到的行為,就交給執行期觀察。REA 可以透過 Chrome DevTools Protocol 和 Playwright 看瀏覽器與 Electron 實際跑了哪些腳本、發了哪些請求,也能讀既有的 HAR 和 mitmproxy 紀錄。2 這些觀察在證據模型裡另外標記,跟靜態推出來的結論分開,兩者對不上時,矛盾會被保留下來,不會被其中一方蓋掉。
限制
這篇看的是架構,實際用起來有幾件事要知道。
第一是法律。README 寫明只支援合法的逆向研究,取得授權、遵守法律是使用者的責任。2 「拆別人的功能來做自己的版本」會碰到著作權和許多軟體授權條款禁止逆向的規定,這不是工具能替你處理的問題。
第二是資料去向。分析在本機執行,但結果會送進智慧體背後的模型,模型供應商怎麼處理這些資料,要看它自己的政策。2 拆的是公司內部或客戶的軟體時,這一點比工具本身的安全性更要緊。
第三是涵蓋範圍不平均。各平台的支援程度差很多,有些流程在更新紀錄裡就寫明還沒在真實的 Windows 主機上驗證過。12 「什麼都能拆」比較像目標,用之前先看自己的目標屬於哪一類。
REA 值得參考的地方,在於它沒有假設模型夠聰明就好。它把調查交給模型,把「什麼算知道」交給工具和驗證器,模型能做的推論,最後都要回到一筆有出處的證據上。
Footnotes
-
GitHub 星數取自 2026-10-12 的 GitHub API;趨勢榜排名見 GitTrend。 ↩