keremmisik/freertos-ghidra
GitHub: keremmisik/freertos-ghidra
一个 Ghidra 脚本/扩展,能够从任意二进制文件中自动恢复 FreeRTOS 任务元数据、重命名入口函数并注入核心数据类型,实现 FreeRTOS 感知的静态逆向分析。
Stars: 1 | Forks: 0
# freertos-ghidra
一个 Ghidra 脚本,可为任何二进制文件带来 **FreeRTOS 感知的静态分析** —— 无论是否被 strip。它能从 `xTaskCreate` 调用处恢复任务元数据,重命名入口函数,定义核心的 FreeRTOS 数据类型,并通过单次运行标注每一个创建调用。
## 功能
| 功能 | 详情 |
|---|---|
| **任务恢复** | 从每个 `xTaskCreate` / `xTaskCreateStatic` 调用处提取任务名称、入口地址、栈深度和优先级 |
| **自动重命名** | 为每个解析出的入口函数将 `sub_XXXXXXXX` 重命名为 `task_` |
| **Wrapper 检测** | 通过第二次分析,查找通过用户自定义 helper(例如 `create_task()`)创建的任务 |
| **调用点注释** | 在每个创建调用处添加包含完整任务元数据的行末注释 |
| **数据类型注入** | 在 Data Type Manager 的 `/FreeRTOS` 类别下定义 `TCB_t`、`List_t`、`ListItem_t` |
| **Headless 支持** | 完全兼容 `analyzeHeadless` 流水线,适用于自动化固件分析 |
## 工作原理
Ghidra 的反编译器将每个 `xTaskCreate` 调用表示为高层 PCode `CALL` 操作,其输入直接映射到 C 语言参数:
```
CALL , pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, ...
input[0] input[1] input[2] input[3] input[4] input[5]
```
脚本会读取每个输入的 varnode,并通过 `COPY` / `CAST` / `INT_ZEXT` 链将其追溯到其底层的常量(`resolveConstant`)。
当找到指向 `pcName` 的常量指针时,它会直接从程序内存中读取以 null 结尾的字符串。
**两次分析**确保了广泛的覆盖率:
1. **直接分析** —— 分析所有引用 `xTaskCreate` 且使用编译时常量任务名称的调用点。
2. **Wrapper 分析** —— 检测将非常量名称转发给 `xTaskCreate` 的 helper 函数(即它们从*自己的*调用者那里接收名称)。
随后分析这些调用者以恢复原始的字面名称。
在运行时构建的动态任务名称(例如通过 `snprintf`)将被记录为 `(unnamed)` —— 这是静态分析的预期限制。
## 验证过的测试场景
该脚本已针对一个专门构建的涵盖五种真实世界模式的二进制文件进行了验证。所有十一个静态可解析的任务均被成功恢复。
| 场景 | 模式 | 结果 |
|---|---|---|
| 直接字面量 | `xTaskCreate(fn, "wifi", ...)` | 已恢复 |
| `const` 全局指针 | `static const char NAME[] = "..."` | 已恢复 |
| 运行时构建的名称 | `snprintf(buf, ...); xTaskCreate(fn, buf, ...)` | `(unnamed)` — 预期结果 |
| 条件创建 | `xTaskCreate` 位于 `if` 块内 | 两个分支均已恢复 |
| 多任务,单一函数 | 连续四次 `xTaskCreate` 调用 | 全部恢复 |
| 用户 wrapper | `create_task(fn, "name", stack, prio)` 调用 `xTaskCreate` | 通过第 2 次分析恢复 |
## 支持的目标平台
Ghidra 反编译器支持的任何架构都可以开箱即用:
- ARM Cortex-M (32-bit)
- ARM64 / AArch64
- x86 / x86-64
- RISC-V 32/64
- MIPS
## 安装说明
### 选项 1 — 脚本(推荐,无需构建)
将 `FreeRTOSScript.java` 复制到你的 Ghidra 脚本目录中:
```
# Linux / macOS
cp ghidra_scripts/FreeRTOSScript.java ~/ghidra_scripts/
# Windows
copy ghidra_scripts\FreeRTOSScript.java %USERPROFILE%\ghidra_scripts\
```
然后在 Ghidra 中:
```
Window -> Script Manager -> [refresh] -> search "FreeRTOS" -> Run
```
### 选项 2 — Headless(CI / 自动化流水线)
```
$GHIDRA_INSTALL_DIR/support/analyzeHeadless \
/tmp/myproject MyProject \
-import firmware.elf \
-postScript FreeRTOSScript.java \
-scriptPath ./ghidra_scripts
```
### 选项 3 — Ghidra 扩展(完整的 analyzer 集成)
构建并安装为一个原生的 Ghidra 扩展,它将出现在 *Analysis -> Auto Analyze* 中:
```
export GHIDRA_INSTALL_DIR=/path/to/ghidra_PUBLIC
gradle buildExtension
# 生成 dist/freertos-ghidra.zip
```
然后在 Ghidra 中:`File -> Install Extensions -> [+] -> freertos-ghidra.zip`,重启并在 Auto Analyze 对话框中启用 **FreeRTOS Analyzer**。
## 示例输出
```
[FreeRTOS] Starting analysis on: firmware.elf
[FreeRTOS] Detected. Found: [xTaskCreate, vTaskDelay, vTaskStartScheduler]
[FreeRTOS] Defined types: ListItem_t, List_t, TCB_t
[FreeRTOS] Found symbol: xTaskCreate @ 001014af
[FreeRTOS] [2] 'data_logger' -> 001011b5 stack=1024
[FreeRTOS] Renamed -> task_data_logger
[FreeRTOS] [4] 'sys_monitor' -> 001011cb stack=768
[FreeRTOS] Renamed -> task_sys_monitor
[FreeRTOS] [5] 'wifi_primary' -> 00101189 stack=2048
[FreeRTOS] Renamed -> task_wifi_primary
[FreeRTOS] Wrapper: create_task -> analyzing call sites...
[FreeRTOS] [5] 'wifi_manager' -> 00101189 stack=2048
[FreeRTOS] Renamed -> task_wifi_manager
[FreeRTOS] [3] 'sensor_read' -> 0010119f stack=512
[FreeRTOS] Renamed -> task_sensor_read
[FreeRTOS] Done. 11 task(s) processed.
```
## 构建测试二进制文件
要在本地重现已验证的结果:
```
git clone https://github.com/keremmisik/freertos-ghidra.git
cd freertos-ghidra/test
make
# 生成 freertos_hard (包含 symbols) 和 freertos_hard_stripped
```
将任意一个二进制文件导入 Ghidra,运行脚本,并将输出与上表进行对比。
或者,构建带有调试符号的官方 FreeRTOS demo:
```
git clone https://github.com/FreeRTOS/FreeRTOS
cd FreeRTOS/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC
make
# -> build/RTOSDemo.axf (已知 tasks: IDLE, Tmr Svc 等)
```
## 已知限制
| 限制 | 原因 |
|---|---|
| 运行时任务名称 | 任何静态分析工具都无法解析使用 `snprintf` 构建的名称 |
| 深度嵌套的 wrapper | 在 wrapper 分析中仅跟踪一层间接引用 |
| 非典型的 wrapper 签名 | 优先级检测假定顺序为 `(fn, name, stack, prio)`;不同的参数排列可能会漏掉优先级字段 |
| 内联的 `xTaskCreate` | 如果编译器将 FreeRTOS 调用完全内联,则不存在可跟踪的符号引用 |
## 项目结构
```
freertos-ghidra/
├── ghidra_scripts/
│ └── FreeRTOSScript.java # Standalone script — no build needed
├── src/main/java/freertosghidra/
│ ├── FreeRTOSAnalyzer.java # AbstractAnalyzer extension
│ └── TaskInfo.java # Value object
├── test/
│ ├── freertos_app.c # Test binary source (5 scenarios)
│ └── Makefile
├── build.gradle
├── extension.properties
├── Module.manifest
├── LICENSE
└── README.md
```
## 许可证
[MIT](LICENSE) — Copyright (c) 2026 Kerem Işık
标签:FreeRTOS, Ghidra, Hakrawler, JS文件枚举, 云安全监控, 云资产清单, 代码恢复, 后台面板检测, 固件分析, 域名枚举, 逆向工程, 静态分析