khiem-nguyen-ict/Binary-Vulnerability-Detection-PoC
GitHub: khiem-nguyen-ict/Binary-Vulnerability-Detection-PoC
一款基于 Ghidra 反汇编和特征相似度匹配的嵌入式二进制漏洞检测工具,用于在 ARM 和 x86_64 二进制文件中发现已知 CVE 风险组件。
Stars: 1 | Forks: 0
# 二进制漏洞检测 PoC
通过 Ghidra 反汇编和基于特征的相似度匹配,检测 ARM + x86_64 嵌入式二进制文件中存在 CVE 漏洞的 OSS 组件。
## 本地测试前置条件
### 选项 A:Docker(推荐)
- Docker Desktop
- Docker Compose 插件
- 至少 4GB RAM 和 10GB 磁盘空间用于 Ghidra
### 选项 B:纯本地(无 Docker)
- Python 3.11+
- 已安装并配置 Ghidra 12.1.2+(`GHIDRA_HOME` 环境变量)
- Java 21+(用于 Ghidra)
- `gcc` 和 `aarch64-linux-gnu-gcc`(用于构建样本指纹)
- `file` 命令(用于架构自动检测)
- `nm` 和 `otool`(用于二进制导入 / Mach-O 符号提取)
## 快速开始(Docker)
```
# 构建并启动
docker compose up --build
# 打开浏览器
open http://localhost:8000
```
前端直接由 FastAPI 提供服务。上传二进制文件以查看汇编代码,然后点击“运行 CVE 检测”查看结果。
## 快速开始(无 Docker 的本地测试)
```
# 1. 创建虚拟环境
python3 -m venv .venv
source .venv/bin/activate
# 2. 安装 Python 依赖
pip install -r backend/requirements.txt
# 3. 设置 Ghidra 路径
export GHIDRA_HOME=/Applications/ghidra_12.1.2_PUBLIC
# 4. 运行服务器
cd backend && uvicorn main:app --reload --port 8000
```
然后打开 `http://localhost:8000`。
## 构建指纹(本地)
```
# 编译示例漏洞代码并生成 fingerprint DB
python3 scripts/build_fingerprints.py
# 输出:data/fingerprints/fingerprints.json
```
这会为 x86_64 和 ARM 编译三个小型易受攻击的样本(libpng `strcpy`、nginx `sprintf`、openssl `gets`),然后通过 Ghidra 提取其汇编特征。有关易受攻击样本的定义,请参见 `scripts/vulnerable_samples.py`。
## 更新和扩展指纹
`scripts/similarity_matcher.py` 中的检测引擎使用指纹数据库来识别易受攻击的代码。更多的指纹可以直接提高检测覆盖率。
### 自动化:通过易受攻击的样本添加
要添加新的指纹,请向 `scripts/vulnerable_samples.py` 追加一个新条目,包含:
- `cve_id`:CVE 标识符
- `component`:库/组件名称
- `version`:易受攻击的版本范围
- `source`:触发危险 API 调用的 C 代码
然后重建数据库:
```
python3 scripts/build_fingerprints.py
```
构建器使用 `gcc` (x86_64) 和 `aarch64-linux-gnu-gcc` (ARM) 编译每个样本,使用 Ghidra 对其进行分析,并将所有指纹写入 `data/fingerprints/fingerprints.json`。
### 手动:编辑指纹 JSON
要直接编辑指纹,请修改 `data/fingerprints/fingerprints.json`。每个指纹条目需要:
```
{
"cve_id": "CVE-XXXX-XXXXX",
"component": "component_name",
"version": "vulnerable_version",
"architecture": "x86_64",
"mnemonic_histogram": { "mov": 10, "call": 2, "push": 1 },
"dangerous_calls": ["strcpy"]
}
```
`mnemonic_histogram` 字段将规范化的指令助记符映射到它们的出现次数。匹配引擎使用余弦相似度比较这些直方图。`dangerous_calls` 字段列出了函数中存在的危险 API,这锚定了相似度匹配以减少误报。
### 支持的危险 API
检测器将这些 API 识别为风险信号:
- `strcpy`, `sprintf`, `gets`, `strcat`, `memcpy`, `sscanf`, `scanf`, `printf`
这些是从 Ghidra 指令操作数和二进制导入(`nm` / `otool`)中检测出来的。
### 使用外部二进制数据集
像 [CveBinarySheet](https://github.com/xmoezzz/CveBinarySheet) 这样的数据集提供了预构建的易受攻击二进制文件,可以将其转换为指纹:
- **兼容**:`x86-64` 二进制文件匹配此项目的 `x86_64` 指纹格式。
- **不兼容**:`armv7` 二进制文件是 32 位 ARM,而此项目的 ARM 指纹针对 `aarch64`(64 位)。指令集架构(ISA)不同,因此指纹不能通用。
要使用 CveBinarySheet 或类似数据集:
1. 下载目标 CVE 和架构的预构建二进制文件。
2. 使用 Ghidra 对其进行分析(与 `build_fingerprints.py` 使用的 pipeline 相同)。
3. 通过 `feature_extractor.py` 提取助记符直方图和危险调用。
4. 将生成的指纹追加到 `data/fingerprints/fingerprints.json`。
其优势在于规模:CveBinarySheet 包含 1334 个带有已知易受攻击函数的 CVE 条目,从而能够建立比当前演示集大得多的指纹数据库。
## 构建用于测试的样本二进制文件
```
chmod +x scripts/compile_samples.sh
./scripts/compile_samples.sh
# 输出:
# data/samples/vulnerable_sample_x86_64
# data/samples/vulnerable_sample_arm
You can use these built binaries to test the API endpoints below.
```
## API 参考
### `POST /api/upload`
上传二进制文件进行反汇编。
### `POST /api/detect`
上传二进制文件,运行反汇编 + CVE 检测,并返回结果。
有关包括构建指纹流程和比较算法在内的详细架构文档,请参见 [ARCHITECTURE.md](ARCHITECTURE.md)。
```
curl -X POST "http://localhost:8000/api/detect" \
-F "file=@data/samples/vulnerable_sample_x86_64"
```
响应:
```
{
"binary_id": "abc123...",
"architecture": "x86_64",
"functions": [...],
"cves": [
{
"cve_id": "CVE-2019-17418",
"component": "libpng",
"score": 0.87,
"matched_function": "vulnerable_copy",
"matched_address": "0x1000"
}
],
"sbom": {
"bomFormat": "CycloneDX",
"specVersion": "1.7",
"version": 1,
"binary_id": "abc123...",
"serialNumber": "urn:uuid:abc123...",
"metadata": {
"timestamp": "2026-07-02T07:38:58Z",
"tools": [{"name": "rd-detect-code-quality"}],
"component": {
"type": "file",
"name": "vulnerable_sample_x86_64",
"size": 12345
}
},
"components": [
{
"type": "library",
"name": "libpng",
"version": "<=1.6.37",
"cves": ["CVE-2019-17418"],
"architecture": "x86_64",
"dangerous_calls": ["strcpy", "memcpy"],
"properties": [
{"name": "matched_function", "value": "vulnerable_copy"},
{"name": "matched_address", "value": "0x1000"},
{"name": "score", "value": "0.87"}
]
}
],
"vulnerabilities": [
{
"id": "CVE-2019-17418",
"source": {"name": "NVD", "url": "https://nvd.nist.gov/vuln/detail/CVE-2019-17418"},
"ratings": [{"method": "other", "score": 0.87, "severity": "medium"}],
"analysis": {"state": "flagged", "justification": "similarity_match"},
"affects": [{"ref": "libpng-<=1.6.37"}],
"description": "Matched by similarity score 0.87 in function vulnerable_copy (0x1000)"
}
]
}
}
```
### `GET /api/sbom/{binary_id}`
检索之前生成的 SBOM。
```
curl "http://localhost:8000/api/sbom/abc123..."
```
### `GET /health`
健康检查。
```
curl "http://localhost:8000/health"
```
## 算法:基于特征的相似度匹配
此工具使用**带有可选 ONNX 模型增强的静态分析**,通过将汇编特征与指纹数据库进行比较来检测已知漏洞。
### ONNX 模型集成
检测 pipeline 使用 `models/binary_similarity.onnx` 进行相似度推断。该模型接受混合输入:
- `target_histogram`:规范化的助记符计数(向量)
- `fp_histogram`:参考指纹直方图(向量)
- `dangerous_call_overlap`:二进制重叠信号(标量)
- `structural_proxy`:循环/间接调用计数(标量)
当 ONNX runtime 不可用时,系统回退到具有相同行为的 `feature_extractor.cosine_similarity()`。
### 工作原理
每个函数的汇编指令都被转换为助记符直方图,然后使用余弦相似度与已知的易受攻击模式进行比较。相似度比较仅使用直方图;其他特征(如 `instruction_count`)会被提取,但不属于向量比较的一部分。
### 示例:将函数与已知指纹进行匹配
**已知指纹(libpng 中的 CVE-2019-17418):**
```
{
"cve_id": "CVE-2019-17418",
"component": "libpng",
"architecture": "arm",
"mnemonic_histogram": {"mov": 12, "bl": 3, "str": 2, "ldr": 5, "cmp": 2, "b": 4},
"dangerous_calls": ["strcpy"]
}
```
**正在分析的函数(从输入二进制文件中提取):**
```
{
"name": "png_set_text_1_6_35",
"instructions": [
{"mnemonic": "mov"}, {"mnemonic": "mov"}, {"mnemonic": "mov"},
{"mnemonic": "bl"}, {"mnemonic": "bl"},
{"mnemonic": "cmp"}, {"mnemonic": "b"},
{"mnemonic": "ldr"}, {"mnemonic": "str"}
]
}
```
**特征提取结果:**
```
{
"instruction_count": 9,
"mnemonic_histogram": {"mov": 3, "bl": 2, "cmp": 1, "b": 1, "ldr": 1, "str": 1},
"dangerous_calls": []
}
```
注意:`dangerous_calls` 需要带有命名为该 API 的操作数数据的调用指令。
**余弦相似度计算:**
- 点积:(3×12) + (2×3) + (1×2) + (1×4) + (1×5) + (1×2) = 55
- 提取特征的模长:√(3² + 2² + 1² + 1² + 1² + 1²) ≈ 4.12
- 指纹的模长:√(12² + 3² + 2² + 4² + 5² + 2²) ≈ 14.21
- 相似度得分:55 / (4.12 × 14.21) ≈ **0.94**
由于 `0.94 > 0.85`(默认阈值),此函数被标记为与 CVE-2019-17418 匹配。
### 检测方法
1. **助记符直方图相似度**:使用余弦相似度针对经过架构过滤的指纹(`x86_64` 或 `arm`)比较指令计数模式。仅使用 `mnemonic_histogram`;`instruction_count` 和其他字段会被提取,但不属于向量比较的一部分。
2. **危险调用模式匹配**:标记包含 `strcpy`、`sprintf`、`gets` 或 `strcat` 的函数,并将它们与指纹进行交叉引用。危险 API 可从 Ghidra 指令操作数**以及**二进制导入(用于 Mach-O 的 `nm` / `otool -Iv`)中检测出来。
## 项目结构
```
├── backend/
│ ├── main.py # FastAPI app
│ ├── requirements.txt
│ └── __init__.py
├── frontend/
│ ├── index.html
│ ├── styles.css
│ └── app.js
├── scripts/
│ ├── BinaryAnalyzer.java # Ghidra headless post-script
│ ├── AnalysisScript.java # Ghidra analysis script with CFG extraction
│ ├── GhidraAnalyzer.java # Alternative Ghidra analyzer
│ ├── feature_extractor.py # Instruction histogram + dangerous calls
│ ├── model_loader.py # ONNX model loading + histogram conversion
│ ├── similarity_matcher.py # ONNX model + CVE matching
│ ├── train_similarity_model.py # Generate ONNX cosine model
│ ├── build_fingerprints.py # Compile vulnerable samples → fingerprint DB
│ └── compile_samples.sh # Build sample ARM + x86_64 binaries
├── models/
│ └── binary_similarity.onnx # ONNX similarity model
├── data/
│ ├── fingerprints/
│ │ └── fingerprints.json # Fingerprint database (ARM + x86_64)
│ └── samples/
│ ├── vulnerable_sample.c # Sample vulnerable source
│ ├── clean.c # Sample clean source
│ ├── vulnerable_sample_x86_64
│ ├── vulnerable.bin
│ └── clean.bin
├── docker/
│ ├── Dockerfile.backend
│ └── docker-compose.yml
├── ARCHITECTURE.md # Detailed architecture docs
└── README.md
```
## 当前局限性(PoC)
- **架构**:仅限 ARM + x86_64。第一阶段排除了 MIPS/RISC-V。
- **指纹数据库**:硬编码的演示数据。运行 `build_fingerprints.py` 以生成真实指纹。
- **相似度**:通过 ONNX 使用简单的助记符直方图 + 余弦相似度,可扩展至 ML 训练。
- **CVE 覆盖范围**:仅有 3 个演示 CVE(libpng、nginx、openssl)。生产环境需要链接 NVD 的数据库。
- **模拟**:无 Unicorn/模拟。仅限静态分析。
- **文件大小**:没有硬性限制。大二进制文件可能会耗尽内存。
## 故障排除
**Ghidra 失败并提示“processor not found”**:
确保架构为 `arm` 或 `x86_64`。未知架构默认为 `x86_64`。
**指纹构建器崩溃**:
`build_fingerprints.py` 要求在本地安装 Ghidra 并设置 `GHIDRA_HOME`。如果不进行修改,它无法在 Docker 内运行。
**端口 8000 已被占用**:
更改 `docker/docker-compose.yml` 中的端口映射,或者将 `--port 8001` 传递给 uvicorn。
**Mach-O 二进制文件返回 0 个 CVE**:
确保代码更新后已重启后端。检测现在使用 `otool -Iv` 进行 Mach-O 符号提取和特定于架构的指纹。如果问题仍然存在,请验证 `GHIDRA_HOME` 是否指向有效的 Ghidra 12.1.2+ 安装。
标签:AV绕过, CNCF毕业项目, FastAPI, Ghidra, JS文件枚举, Python, 云安全监控, 云资产清单, 固件安全, 域名收集, 无后门, 请求拦截, 逆向工具, 逆向工程, 静态分析