erickcestari/SMT-TLB-side-channel-attack
GitHub: erickcestari/SMT-TLB-side-channel-attack
该项目是一个基于 Rust 的 SMT 跨线程 TLB 侧信道攻击概念验证演示,通过 Prime+Probe 计时测量和 k-means 分类从共享 L2 TLB 中恢复密钥。
Stars: 0 | Forks: 0
# SMT TLB 侧信道演示
这是一个在 SMT(超线程)CPU 核心上进行**跨线程 TLB 侧信道**攻击的概念验证教学示例。两个进程运行在同一个物理核心的两个硬件线程上;攻击者仅通过自身的计时测量,就能恢复受害者持有的密钥。
这是 [TLBleed] 和 [PortSmash] (CVE-2018-5407) 系列漏洞背后的攻击类别:SMT 兄弟线程共享微架构资源,因此一个线程的内存行为会泄漏给另一个线程。
## 工作原理
在 Intel 核心上,两个 SMT 线程**共享 L2 TLB (STLB)**。这个共享的有限资源就是泄漏点。
- **受害者**(子进程)每个时间槽处理一位密钥:
- bit 为 `1`:遍历一个大缓冲区,触及数千个不同的页面,从而淹没共享的 STLB;
- bit 为 `0`:仅触及单个页面(TLB 占用可忽略不计)。
- **攻击者**(父进程)保留一小部分驻留页面,并在每个时间槽测量访问它们所需的时间(PRIME+PROBE)。当受害者的 `1` 位操作驱逐了攻击者的 TLB 条目时,攻击者的探测将引发页表遍历,导致运行速度大大降低。
慢速时间槽 → 猜测为 `1`,快速时间槽 → 猜测为 `0`。攻击者使用无监督的一维 k-means 算法对其延迟进行分类,因此它永远不会直接查看密钥。
```
CPU 0 (victim) ─┐ ┌─ touches 4096 pages if bit==1
├─ shared L2 TLB (STLB) ──┤
CPU 1 (attacker)┘ └─ probe of 96 pages slows down
```
## 两种模式
同一个 TLB 信道有两种驱动方式:
### `synced`(默认)
受害者和攻击者通过 `mmap(MAP_SHARED)` 内存中的双方反向感应**屏障** 每次处理一位密钥时进行同步,并且攻击者使用 `slot_done` 标志发出时间槽结束信号。每一位都会产生恰好一次干净的 64 次中位数测量。这**并不符合实际**(真正的攻击者无法让受害者等待),但它隔离了原始信道,并最清晰地展示了其机制。
```
cargo run --release # 64-bit key
cargo run --release -- 128 # any length, up to 512
```
在 12 代 Intel Core (i5-12500H) 上的典型输出:
```
recovered 64/64 bits (100.0% accuracy)
latency threshold : 739 cycles
avg latency, secret 0 : 259 cycles
avg latency, secret 1 : 1220 cycles
```
`0` 和 `1` 时间槽之间约 5 倍的延迟差距就是侧信道。
### `free-run`(`--free-run`)
这才是现实世界中真正的跨线程攻击的样子:**没有屏障,没有共享内存,没有信号传递**。受害者完全根据自己的时钟运行,每位密钥花费固定数量的 TSC 周期,并且从不与任何进程协调。攻击者在紧凑的循环中进行探测,为每次测量打上时间戳并记录为连续的轨迹,然后从轨迹中*离线*恢复密钥:
1. **阈值过滤**:使用相同的 k-means 分割将所有延迟划分为高/低。
2. **相位恢复** —— 攻击者不知道消息是何时开始的。受害者在前面加上一个已知的**前导码**(8 个 1,然后 4 个 0);攻击者在轨迹上滑动该模板(匹配滤波器),并锁定最佳匹配的偏移量。
3. **滑动窗口多数投票** —— 从恢复的相位开始,每个位窗口通过对其内部包含的数百个样本进行多数投票来解码。
这里假设位*速率*是已知的(真正的攻击者会事先对目标算法进行性能分析);这里只需恢复*相位*。
```
cargo run --release -- --free-run 64
```
```
recovered 64/64 bits (100.0% accuracy)
captured samples : 231435
samples per bit : 485.8
latency threshold : 394 cycles
recovered phase : 13650000 cycles into trace
preamble lock quality : 0.86 (1.0 = perfect)
```
`preamble lock quality` 接近 1.0 表示相位已被干净利落地找到;较低的值表示解码可能未对齐。这种模式本质上比 `synced` 更嘈杂,并且对后台负载和频率缩放更加敏感。
## 环境要求与注意事项
- Linux,x86-64,**启用 SMT/超线程**。程序会从 `/sys/.../topology/thread_siblings_list` 自动检测兄弟线程对;如果不存在,它会发出警告,且信道会很弱。
- 在混合架构 CPU 上,它会自动选择一对支持超线程的 **P-core** 组合。
- 结果本质上存在噪声。CPU 频率缩放、`cpufreq` 调度策略 以及后台负载都会降低准确性。将调度策略固定为 `performance` 会有所帮助。
- 现实中的攻击(例如 TLBleed 恢复 EdDSA 密钥)还需要针对细粒度 STLB *集合*的定向攻击和训练有素的分类器;此演示故意使用了一种极其显眼的、针对整个 TLB 的破坏性信道,以使该机制直观可见。
## 文件说明
| 文件 | 作用 |
|------|------|
| `src/main.rs` | 参数解析、CPU 绑定、fork 以及模式调度 |
| `src/probe.rs` | TLB 信道原语:`ProbeSet` 和 `VictimBuf` |
| `src/synced.rs` | 屏障同步的受害者 + 攻击者及恢复逻辑 |
| `src/freerun.rs` | 自由运行的受害者、轨迹捕获及离线解码 |
| `src/classify.rs` | k-means 阈值过滤及结果评分 |
| `src/shared.rs` | 共享内存屏障及每槽样本(仅限 synced 模式) |
| `src/timer.rs` | 带有内存屏障的 `rdtsc`/`rdtscp` 周期计时 |
| `src/topology.rs` | SMT 兄弟线程检测及亲和性绑定 |
## 缓解措施
在不受信任的混合租户环境中禁用 SMT,使用核心调度 / cgroup 隔离,确保互不信任的工作负载永远不会共享同一个核心,并编写具有独立于密钥的内存访问模式的恒定时间加密算法。
这种共享资源泄漏正是 **OpenBSD 默认禁用 SMT** 的主要原因([hw.smt=0],Mark Kettenis,2018 年 6 月)。提交信息清楚地说明了此演示所利用的信道:
此代码仅用于学习和防御性研究。
标签:CPU架构, Rust, 侧信道攻击, 可视化界面, 密码学, 手动系统调用, 硬件安全, 网络流量审计, 通知系统