summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIru Cai <mytbk920423@gmail.com>2019-05-12 00:34:29 +0800
committerIru Cai <mytbk920423@gmail.com>2019-05-12 00:34:29 +0800
commitcc9cb9a141de42cee0e2637a5f53fdd3e4f24bb8 (patch)
treeea993fda514f3ba73043cb8a58e3929008b134e0
parent48ba0474d11608869717c7bc1a9b9fe4e1196977 (diff)
downloaddissertation-cc9cb9a141de42cee0e2637a5f53fdd3e4f24bb8.tar.xz
upd
-rw-r--r--chap/chap4.tex95
1 files changed, 67 insertions, 28 deletions
diff --git a/chap/chap4.tex b/chap/chap4.tex
index 6c058f1..e2de2f7 100644
--- a/chap/chap4.tex
+++ b/chap/chap4.tex
@@ -22,8 +22,6 @@ Spectre-RSB 攻击,此方法可以扩展至 Spectre-STL 攻击。攻击者在
\section{基于动态信息流追踪的Spectre检测方法}
-\Todo: 这一节是否可以写到3页?
-
动态信息流追踪(Dynamic Information Flow Tracking)\supercite{dift}是
一种硬件安全策略,通过识别可疑的信息流,并限制可疑信息的使用,保护程序
的安全。它最早用于防止攻击者利用缓冲区溢出攻击执行恶意代码,也可以用于
@@ -37,10 +35,19 @@ CSF\supercite{context-sensitive-fencing} 中的译码级信息流追踪框架 DI
断是否需要插入 fence 微码。OISA\supercite{oisa} 在指令系统的定义中即包
含了 DIFT 技术,用于追踪一个数据是否为秘密数据。
-以图\ref{lst:spectre_v1}的 Spectre v1 组件代码为例,这段代码产生
-图\ref{lst:spectre_v1_asm}所示的指令。
+在本文的工作中,DIFT 的作用是在运行时动态识别可能泄露秘密数据的指令。
+以图\ref{lst:spectre_v1}的 Spectre v1 组件代码为例。攻击者希望通过 Spectre
+攻击泄露 \verb|array1[x]| 的值,方法是让处理器在分支的推测式执行中,访问 \verb|array2[array1[x] * 4096]|,
+从而将一个依赖于 \verb|array1[x]| 的地址处的数据写入了缓存中。使用了基于 DIFT 的检测手段后,
+可以识别出 \verb|array2[array1[x] * 4096]| 的地址依赖于 \verb|array1[x]| 的值,
+从而处理器可以阻止对这个地址的访问。
-\begin{figure}[htbp]
+为了达到这个目的,我们为所有的物理寄存器都添加一个标记,用于表示它的值
+是否来源于推测式执行中,从内存中读出的值。在上述例子中,有一条将内
+存 \verb|array1[x]| 读取至寄存器的指令,该指令的目的寄存器的标记将会被
+设为1.
+
+\begin{figure}
\begin{minted}[frame=single,linenos=true]{nasm}
xor eax, eax
cmp qword [rip + 0x2b157f], rdi
@@ -57,7 +64,10 @@ CSF\supercite{context-sensitive-fencing} 中的译码级信息流追踪框架 DI
\label{lst:spectre_v1_asm}
\end{figure}
-这些指令中,在分支后执行的指令,DIFT 的行为如表\ref{tab:spectre_dift}所示。
+上述 Spectre v1 的组件代码可以产生图\ref{lst:spectre_v1_asm}所示的指令。
+我们用表\ref{tab:spectre_dift}展示 DIFT 在推测式执行分支中的指令的行为,
+其中 T 表示寄存器的标记,在分支推测式执行前,所有寄存器的标记为0,为了
+描述方便,这里用体系结构寄存器进行描述,实现中为物理寄存器的标记。
\begin{table}
\begin{tabular}{|c|c|c|}
@@ -86,31 +96,52 @@ lea rdx, {[}rip + 0x2b425d{]} & rdx <- rip + 0x2b425d & T{[}rdx{]} <- T{[}rip{]}
\label{tab:spectre_dift}
\end{table}
-本文使用 DIFT 检测 Spectre 组件中泄露数据的 load 指令。详细设计如下:
-
\Todo: 解释为什么使用这种方法,和其他相似方法(DLIFT, TPBuf, SG(Full))的比较
\Todo: 增加结构示意图和代码描述
-\Todo: 使用更加详细的描述
+以下描述这个检测方法的具体细节。
+
+标记的设置:在推测式执行时,对于所有从内存读取数据的指令,将其所有目的
+寄存器的标记设为1.
+
+标记的传播:标记的传播在处理器的执行阶段进行,在这个阶段,处理器在读源
+寄存器的同时,将它们对应的标记读出。对于不同类型的指令,标记传播的方式
+如下:
\begin{itemize}
-\item 为每个物理寄存器添加一位标记,表示这个寄存器的数据是否来自于推测
- 式执行中从内存读取的数据
-\item 如果在推测式执行中,一条指令从内存中读取了数据,则设置这条指令的
- 目的寄存器的标志为1
-\item 对于非访存指令,如果存在标记为1的源寄存器,则设置这条指令的目的
- 寄存器标志为1,否则设置标志为0
-\item 当一条指令之前所有分支指令执行完成,确认推测式执行正确后,设置这
- 条指令的目的寄存器标志为0
-\item 在推测式执行的过程中执行 load 指令时,如果存在标记为1的源寄存器,
- 则这条指令为不安全的 load
+\item 对于算术类指令,它的源操作数均来源于寄存器,其目的寄存器的标记设
+ 为所有源寄存器标记做或运算的结果。
+\item 对于装载类指令,它从内存中读取数据,这是标记设置的基本条件,因此
+ 目的寄存器的标志设为1.
+\item 对于存储类指令,它没有目的寄存器。和一般的 DIFT 实现不同,我们不
+ 对任何内存进行标记。因为要使用存入内存中的数据,需要有一套指令将其重
+ 新从内存中读出,这个操作会设置这条指令目的寄存器的标记。
+\item 对于转移类指令,我们为每个指令添加一位标记,如果源寄存器中有标记
+ 为1的指令,则设置这个指令的标记为1,否则设置为0.转移指令的的标记将在
+ 下文描述。
\end{itemize}
-以上 DIFT 实现只考虑了泄露的 load 指令和读取秘密数据的 load 指令存在数
-据相关,此外还要考虑控制相关的情形,如以下例子\supercite{msvc}:
+标记的清除:当一条指令不再处于推测式执行的状态,即该指令此前的所有分支
+都执行完成并通过验证,则要将这条指令所有目的寄存器的标记重置为0.对于转
+移类指令,则清除该转移指令的标记。
-\begin{minted}{C}
+寄存器中的标记可以处理读取内存中数据的指令,和泄露内存中数据的指令,存
+在直接或间接数据相关的情形。读取内存的指令使得存放它的寄存器被标记,此
+后和它存在直接或间接数据相关的指令,会将这个标记传播至这些指令的目的寄
+存器。
+
+考虑攻击者在 Spectre 攻击中利用缓存侧信道泄露内存中的数据,则
+在 Spectre 的组件代码中,泄露数据的指令为装载指令,该装载指令的地址直接
+或间接依赖于内存中的数据。在加入上述的 DIFT 检测机制后,由于该装载指令
+依赖于内存中的数据,它必定有一个被标记的源寄存器,从而处理器可以得知该
+指令不安全。
+
+转移指令的标记用于处理可能泄露数据的指令,和内存中数据的值存在控制相关
+的情形,如图\ref{lst:victim_v10}的例子\supercite{msvc}:
+
+\begin{figure}[htbp]
+\begin{minted}{C}[frame=single,linenos=true]
void victim(size_t x, uint8_t k) {
if (x < array1_size) {
if (array1[x] == k)
@@ -118,14 +149,22 @@ void victim(size_t x, uint8_t k) {
}
}
\end{minted}
+\caption{泄露数据的指令和内存中的数据存在控制相关的情形}
+\label{lst:victim_v10}
+\end{figure}
这个例子读取的 \verb|array1[x]| 和攻击者猜测的值 \verb|k| 进行比较,如
-果两个值相等,则会访问 \verb|array2[0]|,即访问 \verb|array2[0]| 的指
-令和访问 \verb|array1[x]| 的指令存在控制相关,对 \verb|array2[0]| 的访
-问可能泄露 \verb|array1[x]| 的数据。因此,如果一条控制指令依赖于被标记
-的寄存器,则对它进行标记,其后的所有 load 指令都认为不安全。
-
-\Todo: 解释怎样处理以上的情形
+果两个值相等,则会访问 \verb|array2[0]|,即访问 \verb|array2[0]| 的指令
+和访问 \verb|array1[x]| 的指令存在控制相关,攻击者可以通过探
+测\verb|array2[0]| 是否在缓存中,判断 \verb|array1[x]| 的值是否
+和\verb|k| 相等。只使用寄存器的标记,并不能检测出读取 \verb|array2[0]|
+的指令和 \verb|array1[x]| 的值存在依赖关系。
+
+因此我们需要转移指令中的标记。如果一条指令在被标记的转移指令之后执行,
+则该指令和一个被标记的数据存在依赖关系,如果指令为装载指令,由于它改变
+了缓存的状态,攻击者可以通过缓存信道得知该指令被执行过,推测出被标记转
+移指令的执行结果,从而推测出内存中秘密数据的值,因此这样的装载指令也是
+不安全的指令。
\section{使用推测式执行缓冲区}