# 警報一直響，原始碼卻不見了：Ghidra 如何幫接手的人找到修改線索？

- 網址：https://blog.valenvan.uk/posts/nationalsecurityagency-ghidra.html
- 發布日期：2026-10-22
- 測試設備：Mac mini M4 Pro（12 核、64GB）
- 專案：NationalSecurityAgency/ghidra（https://github.com/NationalSecurityAgency/ghidra），Apache-2.0 授權
- 測試版本：Ghidra 12.1.4 PUBLIC；Temurin JDK 21.0.12.1；沿用2026-10-21原測
- 實測影片：https://www.youtube.com/shorts/eo3enl8ZD0Q

## 重點摘要

- 自製警報程式兩種編譯版本都讀回大於27觸發的條件；原始名稱與註解未恢復。
- 保留28度門檻的重建版，與O0、O2舊版各比較100個整數輸入，兩組各100／100一致。
- 另寫的30度門檻重建版，在28、29度不響，30度響；原執行檔未修改。
- 新版僅以圖示解說既有測試，沒有測真實設備或刷寫韌體。
- **結論：** Ghidra在此範例提供重建判斷線索；修改需要另寫重建版並驗證。
- **適合：** 會寫程式且要接手缺原始碼舊工具的維護者
- **不適合：** 期待一鍵修好硬體、直接拿反編譯文字當原始碼的人

| 實測項目 | 結果 |
|---|---|
| 原行為比對 | O0與O2各100／100一致；-20到79 |
| 28、29度 | 舊版響；重建修改版不響 |
| 30度 | 兩者都響 |
| 分析加匯出 | O0約3.989秒；O2約4.022秒 |
| 本輪 | 重新編劇、Edge配音、全圖示動畫；未重跑受測專案 |

假設你會寫程式，剛接手店裡的溫度警報。舊程式一到二十八度就提醒，店長希望改成三十度，免得天一熱就一直打斷工作。你原以為改個數字就好，卻發現資料夾只剩能直接執行的程式成品，沒有當年撰寫的原始碼。這時真正的問題是：判斷藏在哪裡？不知道原因，就無從修改。

這是解釋用途的假設情境，不是真實店家維修案例。我們用自製小程式演示整條路：先看舊行為，從執行檔找回判斷線索，另外寫重建版，驗證後再改門檻。影片全用圖示動畫表達，動畫上的數字來自既有真實測試，並非拍到實際警報器。

## 為什麼不能直接把成品當原始碼改？

原始碼像食譜，執行檔像做好的菜。Ghidra 的反編譯能協助從成品推回部分做法，卻不保證原食譜逐字回來。本次移除符號的兩種編譯版本，都讀回 `return 0x1b < param_1;`。0x1b 換成十進位是 27；輸入整數溫度時，大於 27 就從 28 開始觸發。早響的原因因此有了線索。

原本的函式名稱、變數名稱和註解沒有回來，匯出內容也含推測型別，不能整份當原始碼直接編譯。工具幫接手者找到重建方向，理解與重寫仍需要人處理。

![原測結果圖解：讀回大於27觸發，解釋28度就響的原因](https://blog.valenvan.uk/img/nationalsecurityagency-ghidra-article_1.png)

## 怎麼知道重建沒有順便改壞？

先寫一份仍然二十八度就響的重建版，不要同時改需求。從 -20 到 79，共 100 個整數輸入，分別比對兩種編譯舊版的輸出，各有 100／100 筆一致。這只支持已測範圍，不能推論任意程式或所有輸入都能還原。

確認這一段後，才將重建版門檻改為三十度，再測邊界：

| 輸入溫度 | 舊版 | 重建修改版 |
|---|---|---|
| 27 | 不響 | 不響 |
| 28 | 響 | 不響 |
| 29 | 響 | 不響 |
| 30 | 響 | 響 |

![原測結果圖解：28、29度不響，30度才響](https://blog.valenvan.uk/img/nationalsecurityagency-ghidra-article_2.png)

這才把「找到判斷」接到「達成修改需求」。修改的是另外撰寫的重建程式；原執行檔兩版的雜湊前後一致，沒有直接修補原檔，也沒有刷進任何硬體。

## 測試如何做，曾在哪裡卡住？

測試設備：Mac mini M4 Pro（12 核、64GB）。受測版本為 Ghidra 12.1.4 PUBLIC、Temurin JDK 21.0.12.1。本次沿用 2026-10-21 的錄影、分析日誌與驗證結果，沒有重新執行受測專案。2026-10-22 的新版只重做敘事、免費 Edge 配音與圖示動畫；原始錄影及文字證據仍保存在 evidence 目錄。

原測用自寫 DumpLogic.java 匯出分析結果，指令如下：

```bash
/opt/ghidra_12.1.4_PUBLIC/support/analyzeHeadless \
  /work/trial/projects alarm_O2 \
  -import /work/trial/controller_O2 \
  -scriptPath /work/trial/scripts \
  -postScript DumpLogic.java /work/trial/decompiled_O2.c
```

第一次日誌顯示分析成功，卻匯出零個函式。補建對應反編譯元件後才拿到結果；只看到「成功」兩字並不足以驗收。原測補建約 41.02 秒，不含下載與其他準備：

```bash
cd /opt/ghidra_12.1.4_PUBLIC/support/gradle
./gradlew buildNatives --max-workers=3
```

之後兩版分析加匯出分別約 3.989、4.022 秒，只代表本次小樣本。這些是原測的重現指令，不是本輪新增實測。

我的結論是：會寫程式、要接手缺原始碼的舊工具時，Ghidra 值得用來找修改線索。做法是先重建並比對原行為，再改需求、再驗證。本次未測真實設備、韌體刷寫或混淆程式；若只是要一鍵修好家電，這份結果不能支持那個期待。

專案：[NationalSecurityAgency/ghidra](https://github.com/NationalSecurityAgency/ghidra)。主體採 Apache License 2.0；第三方元件依套件 LICENSE、NOTICE 與 licenses 目錄。
