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, 云安全监控, 云资产清单, 固件安全, 域名收集, 无后门, 请求拦截, 逆向工具, 逆向工程, 静态分析