我试图了解 Flush + Reload 缓存侧通道攻击。据我所知,攻击利用了可以将非特权数据加载到缓存中的事实(利用分支预测、推测执行等)。然后,攻击者使用探针阵列来访问内存,快速加载的内存被假定在缓存中(秘密数据的一部分)。
我发现不清楚的一件事是攻击者如何能够遍历作为非特权内存的虚拟内存?例如 - 迭代内核虚拟内存或其他进程的内存。
我试图了解 Flush + Reload 缓存侧通道攻击。据我所知,攻击利用了可以将非特权数据加载到缓存中的事实(利用分支预测、推测执行等)。然后,攻击者使用探针阵列来访问内存,快速加载的内存被假定在缓存中(秘密数据的一部分)。
我发现不清楚的一件事是攻击者如何能够遍历作为非特权内存的虚拟内存?例如 - 迭代内核虚拟内存或其他进程的内存。
首先,您应该看看我对为什么查找表不能在恒定时间内运行的描述,因为我有关于缓存和标记如何工作的图片。
缓存位于MMU和 CPU 之间,而 MMU 是创建虚拟内存的对象;因此缓存攻击实际上是虚拟内存的一个独立功能。它们是强制刷新缓存的功能,然后选择如何重新加载缓存,因为您正在寻找时间信息。缓存之间的外部获取是泄漏信息的原因。(注意,这基本上是一个 x86 问题,因为它不允许缓存锁定,这与 1990 年以来的大多数 CPU 不同。另一个警告是我只为非 x86 架构制造了硬件,所以如果我对缓存有误,请告诉我锁定关键数据)。
作为一个通用示例,我们有一个 1k 字节的缓存,我们将使用 AES s-box 作为查找表,因此有 256 个条目。
现在是我们攻击虚拟内存的 MMU 版本。如果您查看我链接的答案,您会看到有缓存标签。现在让我们假设一个简单的例子,我有两个 20 位的进程(1MiB 的地址空间)。MMU 使这两个进程具有相同的虚拟表,从 0xYYY00000 开始,其中 YYY 是内存中的实际前缀。如果我知道 MMU 是如何映射数据的,我可以基于内存重叠的方式在缓存中创建的标记信息创建结构化攻击。
在Bernstein 对 AES 的缓存定时攻击中,有更多关于如何在软件方面构建这些攻击的详细信息 。
There are different cache side channel attacks. There's many variants, but it seems you are confusing two: Prime + Probe and Flush + Reload. Because this is a question about Flush + Reload, I'll stick to that.
Flush + Reload works by abusing shared code/data combined with how the clflush (cache flush instruction) works, at least on x86. There's variants for other architectures. The victim and attacker must share at least 1 page of data physically. When the attacker uses the clflush command with an address pointing to this shared data, it's completely flushed from the cache hierarchy. Because the data is shared, the attacker is allowed to hit on this data in cache. So, the attacker repeatedly flushes shared data with the victim, then allows/waits for the victim to run, then reloads the data. If the attacker has a cache miss, the victim didn't access the data (didn't bring it back to cache). If it's a hit, the victim did (at least probably). The attacker can tell cache hits from misses because the timing of the memory access is very different.
How can the attacker and victim share data if they are different processes? You need to know a little bit about modern OS. Typically, shared libraries are only loaded once physically in memory. As an example, the standard c library is only loaded once, but separate applications access the same data (physically) because their page tables point to the same physical address, because the OS sets it up this way.
Some OS are more aggressive and scan phyiscal memory to find pages which have the exact same data. In this case, they "merge" the pages by changing the page tables so that all processes which use this data point to the new single physical page, instead of having two physical copies. Unfortunately, this allows Flush + Reload to happen even among non shared libraries - if you know the code of the victim, and you want to monitor it, you can just load it into your address space (mmap it) and the OS will happily deduplicate memory, giving you access to their data. As long as you both just read the data, it's fine; if you try to write the data, then the OS will be forced to unmerge the pages. However, this is fine for FLUSH + RELOAD: you are only interested in reading anyway!