jetnoir/metis
GitHub: jetnoir/metis
一款跨平台自动化二进制漏洞分类流水线,结合谱异常检测、模板匹配、符号污点分析与设备端动态验证,帮助安全研究员快速从大量目标中筛选并确认漏洞。
Stars: 0 | Forks: 0
# Metis — 漏洞研究流水线
适用于 macOS、Linux 和 Windows 目标的自动化二进制漏洞分类。
流水线阶段:谱调用图筛选 (C2)、具有完整 SSA 内存污点的模板数据流匹配 (C3)、符号污点分析 (C6) 以及设备端动态验证 (C7)。
C1 在 C6 的符号执行循环内部提供硬度感知的路径排名,使用 SAT 骨干分数来推迟相变附近的路径。
## 流水线阶段
| 阶段 | 文件 | 功能描述 |
|-------|------|-------------|
| C1 | `exploration_technique.py` | 骨干分数路径优先级排序器(内置于 C6) |
| C2 | `c2_rmt.py` | 随机矩阵理论调用图筛选 —— 谱异常检测 |
| C3 | `c3_templates.py` | 具有完整 SSA 内存污点的模板数据流匹配 (v2) |
| C6 | `c6_taint.py` | 符号污点分析 + 通过 angr + Z3 进行 PoC 合成 |
| C7 | `c7_dynamic.py` | 设备端验证:SUBPROCESS / LLDB / DTrace (v2) |
## C1 的作用
当 angr 探索具有多个分支路径的二进制文件时,它通常使用 DFS/BFS,而不会感知每条路径约束的求解难度。
C1 添加了一个 **硬度探针**,通过测量有多少符号输入位被强制(骨干)与自由位来评估每个活跃状态的分数。
- **高骨干** = 大部分输入位被强制 = 刚性约束 = 困难路径 → 推迟
- **低骨干** = 多个自由位 = 灵活约束 = 简单路径 → 优先探索
结果:在混合难度的二进制文件上,**活跃状态峰值减少了 60%**,困难/陷阱路径被自动推迟。
## 架构
```
metis/
├── c2_rmt.py ← C2: C2RMTAnalysis — spectral call graph screen
├── c3_templates.py ← C3: C3TemplateAnalysis — template matching (v2: full SSA)
├── c6_taint.py ← C6: C6TaintTechnique / C6Analysis — symbolic taint
├── c7_dynamic.py ← C7: C7Analysis — dynamic validation (v2)
├── exploration_technique.py ← C1: HardnessExplorationTechnique — backbone path ranking
├── semantic_backbone.py ← Production backbone path: Z3 assumption probing (32ms)
├── dimacs_converter.py ← Legacy: claripy → Z3 bit-blast → DIMACS CNF
├── backbone_probe.py ← Legacy: pysat Glucose3 backbone detection
├── offline_analysis.py ← Full chi-squared analysis pipeline
├── test_pipeline.py ← Unit tests (5/5 passing)
├── benchmark_crackme.py ← Benchmark harness
└── crackme_mixed.c ← Test binary with mixed-difficulty paths
```
## 快速开始 — 完整流水线
```
import angr, archinfo
from metis.c2_rmt import C2RMTAnalysis
from metis.c3_templates import C3TemplateAnalysis
from metis.c6_taint import C6Analysis
from metis.c7_dynamic import C7Analysis, extract_poc_from_c6, C7DeliveryMode
from metis.exploration_technique import HardnessExplorationTechnique
BINARY = '/usr/sbin/smbd'
proj = angr.Project(BINARY, auto_load_libs=False,
main_opts={'arch': archinfo.arch_from_id('aarch64')})
# C2 — 结构化筛选
c2_result = C2RMTAnalysis.from_project(proj).run()
c2_result.print_report() # z_radius, z_energy, z_entropy
# C3 — 排名前 20 的函数上的 template match
c3_result = C3TemplateAnalysis(proj).analyse_functions(
c2_result.top_function_addrs[:20])
c3_result.print_report() # template hits + confidence
# C6 — 针对高置信度 C3 匹配结果的 symbolic taint
for addr in c3_result.top_function_addrs[:5]:
result = C6Analysis(proj).run(
proj.factory.call_state(addr), max_steps=800,
extra_techniques=[HardnessExplorationTechnique(threshold=0.75)])
if result.findings:
# C7 — on-device validation
poc = extract_poc_from_c6(result.findings[0], proj=proj)
evidence = C7Analysis(binary=BINARY).validate(
poc, mode=C7DeliveryMode.DTRACE, timeout_s=60)
evidence.write(f'/tmp/c7_{hex(addr)}')
print(evidence.asb_text) # paste into Apple ASB / MSRC / Chrome VRP
```
## 快速开始 — C1(仅骨干优先级排序器)
```
import angr
from metis.exploration_technique import HardnessExplorationTechnique
proj = angr.Project('./binary', auto_load_libs=False)
state = proj.factory.entry_state()
simgr = proj.factory.simgr(state)
simgr.use_technique(HardnessExplorationTechnique(
threshold=0.75, # defer top 25% hardest (adaptive percentile)
probe_timeout_s=0.05, # 50ms budget per state
max_score_per_step=16, # cap scoring for large state counts
))
simgr.run()
```
## 独立骨干分析
```
import claripy
from metis.semantic_backbone import semantic_backbone_claripy
sym = claripy.BVS('input', 64)
constraints = [sym[7:0] == 0x41, sym > 0x4141414141414141]
result = semantic_backbone_claripy(constraints)
print(f"backbone: {result.backbone_fraction:.2f}") # 0.12
print(f"forced: {result.n_forced}/{result.n_semantic_bits}")
print(f"time: {result.probe_time_s*1000:.0f}ms")
```
## 性能表现
### C1 骨干探测(语义路径与遗留版本)
| 指标 | DIMACS 路径(遗留版本) | 语义路径(当前版本) |
|--------|---------------------|------------------------|
| `a == 0x42` 骨干 | 0.02 (错误) | 1.00 (正确) |
| `x > 0` 骨干 | 0.06 (有噪声) | 0.00 (正确) |
| 5×64位,19个约束 | 338 毫秒 | 32 毫秒 |
| Tseitin 稀释 | 是 | 无 |
### C1 状态减少
| 二进制文件 | 原版峰值状态数 | 硬度感知峰值状态数 | 提升 |
|--------|-------------------|--------------------|-------------|
| 线性 crackme | 3 | 3 | — (无路径爆炸) |
| 指数爆炸 (2^N) | 256 | 256 | — (均匀难度,正确地无操作) |
| **混合难度** | **20** | **8** | **减少 60%** |
### 流水线各阶段耗时
| 阶段 | 典型时间 | 备注 |
|-------|-------------|-------|
| C2 — 单个 macOS 二进制文件 (~1 MB) | ~30 秒 | CFGFast + 50 次 null 重复 |
| C2 — 批量 300 个二进制文件,8 个 worker | ~15 分钟 | `batch_screen.py` |
| C3 — 前 20 个函数 | ~60 秒 | 寄存器 + 内存 SSA 污点 |
| C6 — 简单函数 | 2–5 分钟 | 紧密的路径约束 |
| C6 — 复杂函数 | 10–30 分钟 | 大量分支 |
| C7 — DTrace 确认 | 5–15 秒 | Attach + sink 探针 |
| C7 — LLDB 崩溃捕获 | 15–60 秒 | LLDB 启动 + 崩溃等待 |
## 理论
基于随机 3-SAT 相变的经验性 P vs NP 研究:
- 骨干分数与 CDCL 求解器难度相关(Spearman ρ = +0.43,p = 0.012)
- 这是边缘 χ²/nv(变量冻结)的代理指标,而 Survey Propagation 解析计算的就是这一指标
- 这种相关性是特定于计算类的:3-SAT 呈现单调上升,而 3-XORSAT(多项式时间)在阈值前保持平缓
## 依赖项
```
pip install angr z3-solver numpy scipy
# pysat:仅 legacy backbone_probe.py 路径需要(非生产环境)
```
**C7 运行时依赖项**(无需 pip install —— 均为系统工具):
| 工具 | 模式 | macOS 可用性 |
|------|------|--------------------|
| `lldb` | LLDB 模式 | 随 Xcode / CLT 附带 |
| `dtrace` | DTRACE 模式 | 随 macOS 附带(需要禁用 SIP 或具有授权) |
| `subprocess` | SUBPROCESS 模式 | stdlib — 始终可用 |
**注意:** 不支持 Python 3.12(angr 兼容性问题)。请使用 Python 3.11 或 3.13。
## 测试
```
python3 -m pytest metis/test_pipeline.py -v # 5/5 expected
python3 -m metis.benchmark_crackme
```
标签:angr, Conpot, DTrace, LLDB, macOS安全, Maven, PoC合成, SAT求解, Windows安全, Z3求解器, 二进制分析, 云安全监控, 云安全运维, 内存污点, 情报收集, 控制流分析, 漏洞研究, 漏洞验证, 符号执行, 约束求解, 自动化漏洞分类, 路径修剪, 逆向工具, 随机矩阵理论, 静态分析