转载

JIT引擎触发RowHammer可行性研究

2015 年 3 月 Google Project Zero 发表文章 Exploiting the DRAM rowhammer bug to gain kernel privileges。由于文中提到的缺陷比较难以修复,需要更新 BIOS 来提 高内存刷新的速度,引起了人们的担忧。然而由于 RowHammer 的运行需要在目 标主机上运行特定的汇编代码,实施攻击存在很大的难度。

本文旨在研究能否通过 Javascript 等脚本语言的动态执行触发 RowHammer, 如果能够成功将极大增加 RowHammer 的攻击性。为了验证该思路,本文分析了 Java Hotspot、Chrome V8、.NET CoreCLR 以及 Firefox SpiderMonkey 的实现机制并 给出了可行性分析。

遗憾的是我们在这几个程序中,没有找到最优的利用方式。要么不存在相关 的指令,要么指令无法达到 RowHammer 要求,要么需要有额外的操作更改执行 环境才能触发,缺乏实际的攻击意义。

0x01 RowHammer

本节将简要回顾 RowHammer 存在的原理,其触发的机制,已经在利用时将 面临到的一些挑战。

1.1 What`s RowHammer?

RowHammer 是 DDR3 内存中存在的问题,通过频繁的访问内存中的一行(row) 数据,会导致临近行(row)的数据发生位反转。如图 1.1(a)所示,内存是由一系列 内存单元构成的二维数组。如图 1.1(b)所示每一个内存单元由一个晶体管和一个 电容组成,晶体管与 wordline 相连,电容负责存储数据。DRAM 的每一行(row) 有自己的 wordline,wordline 需要置高电压,特定行(row)的数据才能够访问。当 某一行的 wordline 置高电压时,该行的数据就会进入 row-buffer。当wordline 频 繁的充放电时,就可能会导致附近 row 的存储单元中的电容放电,如果在其被刷 新之前,损失过多的电压就会导致内存中的数据发生变化。

图 1.2 所示是一块内存,其中一个 row 为 64kb(8KB)大小, 32k 个 row 组成一 个 Bank, 8 个 Bank 组成一个 Rank, 该 Rank 为 2G。此处需要注意不同的 Bank 有 专用的 row-buffer,访问不同 Bank 中的 row 不会导致 wordline 的充放电。

内存中的电压是不能长期保存的,需要不停的对其进行刷新,刷新的速度为 64ms,所以必须在 64ms 内完成 RowHammer 操作。

JIT引擎触发RowHammer可行性研究 JIT引擎触发RowHammer可行性研究

1.2 RowHammer 触发的方法

表 1.1 所示为 Google Project Zero 所给出的可以触发 RowHammer 的代码段。

表 1.1

code1a:

mov (X), %eax // Read from address X

mov (Y), %ebx // Read from address Y

clflush (X) // Flush cache for address X

clflush (Y) // Flush cache for address Y

jmp code1a

其中 x, y 地址的选择非常重要,x, y 必须要在同一个 Bank,不同的 row 中。

因为不同的 Bank 有专用的 row-buffer。如果 x, y 在同一个 row 中就不会对 wordline 进行频繁的充放电,也就不会触发 RowHammer。

上述代码只是一种有效的测试方法,但并不是惟一的,归根到底我们所需要 的就是在 64ms 内让一个 wordline 频繁的充放电。

1.3 触发 RowHammer 指令

为了频繁的使 wordline 充放电,必须考虑 CPU 的 Cache, 如果当前地址在Cache 里面就不会访问内存,也就不会导致 wordline 的充放电情况。

表 1.2

指令

作用

CLFLUSH

将数据从 Cache 中擦除

PREFETCH

从内存中读取数据并存放在 Cache 中

MOVNT*

不经过 Cache 直接操作数据

表 1.2 中的指令都可以用来频繁的访问一个内存地址,并使相应的 wordline 充放电,如果要触发RowHammer, 需要上述指令的配合才能完成。

(注: 这些指令并不是惟一的触发方法,比如通过分析物理地址和 L3 Cache 的映射关系算法(不同的 CPU 架构实现可能不同),找到映射到同一个 Cache set 的一系列地址,通过重复访问这一系列的地址即可触发 RowHammer。)

0x02 脚本层面触发 RowHammer

Google Project Zero 给出的 POC 是直接以汇编的方式来运行,可以用来验证 内存是否存在安全问题。当前脚本语言大都存在 JIT 引擎,如果能够通过脚本控 制 JIT 引擎直接触发RowHammer,将会具有更大的攻击意义。为了分析其可行性,本节研究了 Java Hotspot、Chrome V8 等执行引擎的运行机制。

2.1 Java Hotspot

Hotspot 是 Oracle JDK 官方的默认虚拟机,主要用来解释执行 Java 字节码,其 源码位于 Openjdk 下 hotspot 目录,可以独立编译。Java 字节码是堆栈式指令集, 指令数量少,共有 256 条指令,完成了数据传送、类型转换、程序控制、对象操 作、运算和函数调用等功能。Java 字节码存储在 class 文件中,作为 Hotspot 虚 拟机的输入,其在一定程序上是用户可控的。那么能否通过构造 class 文件,使 得 Hotspot 在执行时完成 RowHammer 呢?

Java Hotspot 默认对字节码进行解释执行,当某方法被频繁调用,并且达到一定的阈值,即会调用内置的 JIT 编译器对其进行编译,在下次执行时直接调用编 译生成的代码。

Java 字节码解释器有两个实现,分别为模版解释器和 C++解释器,Hotspot 默 认使用模版解释器。Java 的 JIT 编译器有三个实现,分别为客户端编译器(C1 编 译器)、服务器端编译器(C2 编译器)以及 Shark 编译器(基于 LLVM)的编译 器。

图 2.1 所示为 Java 在不同平台下使用的虚拟机。

JIT引擎触发RowHammer可行性研究 JIT引擎触发RowHammer可行性研究

2.1.1 模版解释器触发 RowHammer?

a) 模版解释器工作原理

模版解释器是一种比较靠近底层的解释器实现,每一个字节码对应一个模版, 所有的模版组合在一起构成一个模板表。每一个模版实质上都是一段汇编代码, 在虚拟机创建阶段进行初始化。在执行 class 文件的时候,遍历字节码,每检测 到一个字节码就调用相应的汇编代码块进行执行,从而完成对于字节码的解释执 行。

[1]  [2] [3]  下一页

正文到此结束
Loading...