HendrikDeCoster/MLScan-Showcase
GitHub: HendrikDeCoster/MLScan-Showcase
一款静态二进制扫描器,用于在编译后的软件中检测 ML-KEM 与 ML-DSA 后量子密码学实现并生成 CycloneDX 1.6 CBOM 文档。
Stars: 0 | Forks: 0
# 后量子密码学 (PQC) 资产检测器
[](pyproject.toml)
[](src/mlscan/cbom.py)
[](src/mlscan/core/disassembler.py)
[](src/mlscan/analyzers/mnemonic/inference/engine.py)
[](https://docs.astral.sh/uv/)
这是一款静态二进制分析和密码学发现扫描器,旨在识别已编译二进制软件中的后量子密码学 (PQC) 实现。该工具专门用于在未剥离、已剥离以及向量化机器码二进制文件中,识别 **ML-KEM** (FIPS 203 / Kyber) 和 **ML-DSA** (FIPS 204 / Dilithium) 的标准和草案实现。
发现的资产会被盘点并导出为符合 **OWASP CycloneDX 1.6 密码学物料清单 (CBOM)** 标准的 JSON 文档,并附带严格的 `cryptographic-asset` 属性。
## 核心功能
* **多引擎发现架构:** 结合了快速静态 OID/字符串扫描、即时操作数反汇编、静态 NTT 矩阵模式匹配以及基于控制流的机器学习。
* **Stripped 二进制恢复:** 对于没有符号表的 stripped 二进制文件,通过解析运行时展开结构来重建函数边界:Linux ELF 中 `.eh_frame` 内的 DWARF 调用帧信息 (CFI) FDE,以及 Windows PE 可执行文件中 `.pdata` 内的结构化异常处理 (SEH) 表。
* **全面的容器支持:** 原生支持 ELF(可重定位 `.o`、已链接二进制文件、共享对象 `.so`)、Windows COFF / BigObj (`.obj`)、Windows PE (`.exe`/`.dll`) 以及 Unix 静态库 (`.a` / `.lib`)。
* **AVX2 SIMD 和向量数学支持:** 专用的特征提取器可捕获 AVX2/AVX-512 优化二进制文件中的向量化 Montgomery 和 Barrett 归约模式,在这些文件中标量常数会消失。
* **并发安全扫描核心:** 线程隔离的 Capstone 引擎工厂、线程安全的 LRU 缓存,以及由 `ProcessPoolExecutor` 支持的归档成员并行扫描。
* **严格的 CBOM 1.6 合规性:** 生成经过验证的 CycloneDX 1.6 CBOM 输出,包含精确的参数集、量子安全级别 (1–5)、经典安全性等价物以及确切的证据位置。
* **完全可复现的环境:** `uv.lock` 和 `.python-version` 通过哈希值锁定解释器和每一个传递依赖;只需一个 `uv sync --frozen` 即可重现生成结果时的确切环境。
## 高级架构
```
┌─────────────────────────────────────────────────────────┐
│ Target Binary (.a, .o, .so, COFF, PE, Executable, etc.) │
└────────────────────────────┬────────────────────────────┘
│
▼
┌─────────────────────────────────┐
│ BinaryAnalysisPipeline (Core) │
└────────────────┬────────────────┘
│
┌────────────────────────────┼────────────────────────────┐
▼ ▼ ▼
┌───────────────────────┐ ┌────────────────────────┐ ┌────────────────────────┐
│ String & OID Analyzer │ │ Constant Analyzer │ │ Mnemonic ML Engine │
│ (YARA + OID Tables) │ │ (NTT Tables + Immeds) │ │ (CFG + XGBoost 2-Stg) │
└───────────┬───────────┘ └────────────┬───────────┘ └────────────┬───────────┘
│ │ │
└────────────────────────────┼────────────────────────────┘
│
▼
┌─────────────────────────┐
│ DetectionResult │
└────────────┬────────────┘
│
▼
┌─────────────────────────┐
│ CycloneDX 1.6 Emitter │
└────────────┬────────────┘
│
▼
┌─────────────────────────┐
│ CBOM JSON Document │
└─────────────────────────┘
```
### 详细架构与代码库映射
## 安装与设置
依赖项、虚拟环境和 Python 解释器本身由 [`uv`](https://docs.astral.sh/uv/) 管理。无需手动安装任何其他内容。
### 前置条件
| 要求 | 说明 |
| :--- | :--- |
| **`uv`** ≥ 0.5 | `curl -LsSf https://astral.sh/uv/install.sh \| sh` (或 `pip install uv`)。 |
| **Python 3.12** | 无需提前准备 — `uv` 会根据 `.python-version` 下载并锁定确切的解释器。 |
| **C/C++ 工具链** | *可选。* 仅集成测试需要,用于在运行时编译测试用二进制文件,以及重建数据集。 |
### 设置步骤
```
# 1. Clone the repository
git clone https://github.com/HendrikDeCoster/MLScan.git
cd MLScan
# 2. Reproduce the exact locked environment
# --frozen 禁止重新解析:uv.lock 将被原样使用,否则命令失败
uv sync --frozen
# 3. Verify the installation end to end
uv run pytest tests/test_basic.py
uv run mlscan --help
```
### 安装配置
运行时扫描器不需要机器学习训练栈。请选择与任务匹配的配置:
| 配置 | 命令 | 内容 |
| :--- | :--- | :--- |
| 仅运行时 | `uv sync --frozen --no-dev` | 扫描器 + CLI。占用空间最小,适用于部署。 |
| 默认 | `uv sync --frozen` | 运行时 + 测试和 lint 工具 (`pytest`, `ruff`, `deptry`, `vulture`)。 |
| 训练 | `uv sync --frozen --extra training` | 添加 scikit-learn, SHAP, matplotlib/seaborn, joblib, parquet 栈。 |
| 性能分析 | `uv sync --frozen --group profiling` | 添加 `scalene` 和 `snakeviz`。 |
| 全部 | `uv sync --frozen --all-extras --all-groups` | 完整的开发环境。 |
## CLI 用法
使用 `uv run mlscan` 运行扫描:
```
# 扫描二进制文件并输出 CBOM JSON 到标准输出 (stdout)
uv run mlscan /path/to/target_binary
# 扫描二进制文件并将 CBOM JSON 写入特定输出文件
uv run mlscan /path/to/libcrypto.so -o cbom.json
# 运行单个检测引擎
uv run mlscan /path/to/binary -e constant
# 扫描静态存档;每个成员对象都作为独立单元进行分析
uv run mlscan data/archives/static/gcc/-O2/liboqs.a -o liboqs.cbom.json
```
### CLI 命令参数
| 参数 | 类型 | 必填 | 描述 |
| :--- | :--- | :--- | :--- |
| `file_path` | 位置参数 | **是** | 目标二进制文件、目标文件 (`.o`)、共享库 (`.so`)、静态库 (`.a`/`.lib`) 或 PE 可执行文件 (`.exe`/`.dll`)。 |
| `-o`, `--output` | 选项 | 否 | 用于保存 CBOM JSON 文档的文件路径。如果省略,结果将直接打印到控制台 (`stdout`)。 |
| `-e`, `--engine` | 选项 | 否 | 将分析限制为特定的发现引擎 (`string`、`constant` 或 `mnemonic`)。如果省略,则运行所有引擎。 |
诊断信息会写入 `stderr`,CBOM 会写入 `stdout`,因此输出可以直接通过管道传递给其他工具:
```
uv run mlscan ./build/my_app | jq -r '.components[].name'
```
日志级别从 `ScannerSettings.log_level` 读取。由于设置基于 `pydantic-settings`,因此无需更改代码即可通过环境变量覆盖每个字段。扫描完成时进程退出代码为 `0`,如果 pipeline 抛出异常则为 `1`。
## 特征提取与模型训练
`training/` pipeline 从已编译的归档/可执行文件中提取特征,并训练 2 阶段级联分类器。请先安装训练栈:
```
uv sync --frozen --extra training
```
### 1. 特征提取
从位于 `data/archives/` 的二进制文件中提取结构化汇编特征:
```
uv run -m training.scripts.extract_features
```
### 2. 训练分类器
运行 Leave-One-Group-Out (LOGO) 交叉验证,训练生产级 2 阶段级联分类器,并导出训练好的模型产物:
```
uv run -m training.scripts.train_classifier
```
### 导出的模型产物
导出器会将四个文件写入 `src/mlscan/analyzers/mnemonic/resources/`。`MnemonicInferenceEngine.load_pipeline()` 需要全部四个文件,如果缺少任何一个,就会引发 `FileNotFoundError` 并指明缺失的文件名 —— 如果 mnemonic 引擎报告缺少资源,说明模型尚未导出,同时在此期间 `-e string` / `-e constant` 扫描仍可完全正常使用。
| 产物 | 用途 |
| :--- | :--- |
| `classifier.json` | 原生 JSON 格式的 XGBoost 级联,由 `XGBoostModelAdapter` 加载。 |
| `model_meta.json` | 有序的 `feature_names` 和每个类别的 `best_thresholds`。 |
| `scaler.json` | 特征标准化参数。 |
| `calibrator.json` | 概率校准层。 |
每次预测时都会根据提取的 DataFrame 验证 `model_meta.json["feature_names"]`。如果不匹配,会引发显式的*结构特征漂移*错误,而不是在对齐错误的列上默默进行评分 —— 因此对提取器的任何更改都需要重新训练和重新导出。
## 扩展工具
### 添加新的发现引擎
1. 创建 `src/mlscan/analyzers//analyzer.py`,并继承 `analyzers/base.py` 中的 `BaseAnalyzer`(对于基于规则的引擎则继承 `BaseYaraAnalyzer`)。
2. 实现 `scan_units(units)` 以使用 `ScannableUnit` 对象并返回由 `Signal` 组成的 `DetectionResult` 对象。构造函数接收设置对象:`Analyzer(config=settings)`。
3. 在 `analyzers/registry.py` 中注册该类。注册表键会自动成为 CLI 的 `-e/--engine` 标志的有效值,因为其 `choices` 派生自 `ANALYZER_REGISTRY.keys()`。
4. 将任何 `rules.yar` 放在 `analyzer.py` 旁边;构建时会强制将 `analyzers/**/*.yar` 包含在 wheel 中。
5. 在 `tests/unit/analyzers/` 下添加测试,使用 `tests/fixtures/binaries.py` 中的合成构建器,而不是提交样本二进制文件。
### 添加新算法或变体
1. `crypto_constants.py` — 在字节级别识别该算法的命名整数常量和模数。
2. `crypto_definitions.py` — 新变体的参数集、OID 和标识符。
3. `crypto_registry.py` — 通过 `CryptoRegistry` 将其公开,分析器和 `cbom.py` 在命名组件和填充 `cryptoProperties` 时都会查询它。
然后将与 `string` 和/或 `constant` 引擎匹配的 YARA 规则添加进去。
### 扩展数据集
向数据集添加新库需要更改 **三个**地方:
1. **`src/mlscan/core/archive.py` → `_LIBRARY_PATH_KEYWORDS`**
添加一个 `关键字 → 库名称` 条目。这就是为每个提取的样本提供其 `library` 特征的方式。例如,`data/archives/static/gcc/-O0/libopenssl_crypto.a` 包含关键字 `openssl_crypto`,因此会获得值 `openssl`。
2. **`training/config/datasets.py` → `EXCLUDED_KEYWORDS`**
在此处添加关键字(或完整文件名)可在提取过程中跳过这些归档。这是在迭代过程中缩小数据集的最快方法。
3. **`training/config/datasets.py` → `TARGET_LIBS`**
添加在第 1 步中定义的库名称,以将其包含在 **Leave-One-Group-Out** 轮换中。LOGO 每折保留一个库,这就是该项目衡量对未知实现的泛化能力,而不是对单个代码库进行记忆的方式。
重建并验证数据集:
```
uv run bash scripts/download_dependencies.sh # fetch library sources
uv run bash scripts/build_archives.sh # compile the -O0..-O3 archive matrix
uv run python scripts/verify_optimizations.py # verify the optimization matrix is complete
uv run python make_manifest.py # hash the dataset into a manifest
```
## 测试与验证
使用 `uv` 运行完整的 pytest 套件(607 个测试,串行执行大约需要 2.5 分钟):
```
uv run pytest -n auto --dist worksteal
```
### 定向测试执行
```
# 环境冒烟测试:安装、entry point、打包规则、原生库
uv run pytest tests/test_basic.py
# 仅 Unit tests
uv run pytest tests/unit -n auto --dist worksteal
# Pipeline 集成测试(要求 PATH 上有 C 工具链)
uv run pytest tests/integration
# 除编译器相关测试外的所有内容
uv run pytest -m "not integration" -n auto --dist worksteal
# 严格的 OWASP CycloneDX 1.6 JSON Schema 验证
uv run pytest tests/test_cbom_validation.py
# Coverage 报告
uv run pytest -m "not integration" --cov --cov-report=term-missing
```
已注册的标记(`pyproject.toml`,由 `--strict-markers` 强制执行):`integration`, `slow`, `requires_dataset`, `requires_model`。
### 静态质量门禁
```
uv run ruff check . # lint
uv run ruff format . # format
uv run deptry . # unused, undeclared and transitive dependency detection
uv run vulture # dead code detection
uv lock --check # verify uv.lock still matches pyproject.toml
```
## 基准测试
基准测试脚本用于衡量已编译二进制文件的扫描性能、执行持续时间和检测吞吐量:
```
uv run python benchmark/run_benchmark.py
```
## 可复现性
本项目产生的每一个结果都可以追溯到确切的环境和确切的数据集。
| 产物 | 保证 |
| :--- | :--- |
| `.python-version` | 锁定解释器版本;由 `uv` 自动获取。 |
| `uv.lock` | 使用哈希值锁定每个直接和传递依赖项,适用于所有受支持的平台。 |
| `uv sync --frozen` | 严格按照 lockfile 安装;如果失败也不会静默重新解析。 |
| `uv lock --check` | 验证 lockfile 是否仍然与 `pyproject.toml` 匹配 —— 适合作为 CI 门禁。 |
| `make_manifest.py` | 对数据集进行哈希处理,以便将训练运行与确切的输入绑定。 |
| `scripts/verify_optimizations.py` | 在提取之前确认 `-O0`–`-O3` 编译矩阵是否完整。 |
要在全新的机器上重现环境:
```
uv sync --frozen --all-extras # exact dependency set
```
## Make 目标
`Makefile` 封装了上述命令。运行 `make help` 获取完整列表。
| 目标 | 操作 |
| :--- | :--- |
| `make install` | `uv sync --frozen` — 锁定的默认环境。 |
| `make install-all` | 包含训练和性能分析栈的锁定环境。 |
| `make lock` | `uv lock --check`:验证 lockfile 是否与 `pyproject.toml` 匹配。 |
| `make relock` | 重新解析依赖项并更新 `uv.lock`。 |
| `make test` | 完整套件,并行执行。 |
| `make test-unit` | 仅运行 `tests/unit`。 |
| `make test-int` | 仅运行集成测试。 |
| `make test-smoke` | `tests/test_basic.py` — 确认检出正常的最快方法。 |
| `make cov` | 覆盖率报告。 |
| `make lint` / `make fmt` | Ruff 检查 / 自动格式化和自动修复。 |
| `make audit` | `deptry` 和 `vulture`。 |
| `make check` Lockfile + lint + 快速测试。提交前/交付前的门禁。 |
| `make scan TARGET=` | 扫描二进制文件,CBOM 输出到 stdout。 |
| `make cbom TARGET= OUT=` | 扫描二进制文件,CBOM 输出到文件。 |
| `make extract` / `make train` | 特征提取 / 分类器训练。 |
| `make bench` | 基准测试套件。 |
| `make clean` / `make distclean` | 删除缓存和产物 / 同时删除 `.venv`。 |
标签:Apex, Python, XGBoost, 云安全监控, 云资产清单, 后量子密码学, 密码资产管理, 无后门, 机器学习, 逆向工具, 逆向工程, 静态分析