Windows 8 ASLR Internals ASLR stands for Address Space Layout Randomization. It is a security mechanism which involves randomization of the virtual memory
addresses of various data structures, which may be attacked. It is difficult to predict where the target structure is located in the memory, and thus an attacker has small chances to succeed. ASLR 代表“地址空间布局随机化”。它是一个涉及各种数据结构(可能会被攻击)的虚拟内存地址随机化的安全机制。要预测目标数据结构在
内存中的定位会变得很困难,因此攻击者很少有机会成功。
ASLR implementation on Windows is closely related to the image relocation mechanism. In fact, relocation allows a PE file to be loaded
not only at the fixed preferred image base. The PE file relocation section is a key structure for the relocating process. It describes how to modify certain code and data elements of the executable to ensure its proper functioning at another image base. Windows 上的 ASLR 实现与映像重定位机制密切相关。事实上,重定位能够允许一个 PE 文件不仅是被加载到一个固定的首选映像基址。PE 文件的重定位节是重定位过程中的一个关键结构。它描述了如何修改可执行文件的某些代码和数据元素,以确保它被加载到另一个映像基址时能够正常工作。
The key part of ASLR is a random number generator subsystem and a couple of stub functions that modify the image base of a PE file,
which is going to be loaded. ASLR 的关键环节是一个随机数生成器子系统,以及数个修改将被加载的 PE 文件映像基址的存根函数。
Windows 8 ASRL relies on a random number generator, which is actually a Lagged Fibonacci Generator with parameters j=24 and k=55 and which is seeded at Windows startup in the winload.exe module. Winload.exe gathers entropy at boot time and has different sources:
registry keys, TPM, Time, ACPI, and a new rdrand CPU instruction. Windows kernel random number generator and its initialization are described in detail in [1]. Windows 8 的 ASRL 依赖于一个随机数生成器,这实际上是一个参数为 j=24,K=55 的“滞后斐波那契数生成器”,它由 winload.exe 模块
(Windows 启动加载器)在 Windows 启动时“种下”。Winload.exe 在启动阶段从不同的来源收集熵:注册表键,TPM,Time,ACPI,以及一个新的 CPU 指令:rdrand 。
(译注:熵的概念起源于热力学,用于度量一个封闭系统的无序性,作者引用此术语来指代无序的随机性)
有关 Windows 内核随机数生成器及其初始化请参考
[1] [Chris Valasek, Tarjei Mandt. Windows 8 Heap Internals. 2012.]
We would like to give a small note about the new rdrand CPU instruction. The Ivy Bridge architecture of Intel processors has introduced the Intel Secure Key technology for generating high-quality pseudo-random numbers. It consists of a hardware digital random number
generator (DRNG) and a new instruction rdrand, which is used to retrieve values from DRNG programmatically. 关于新的 rdrand CPU 指令,需注意一些事项。Ivy Bridge 架构(第三代 i3~i7)的 Intel 处理器引入了“Intel Secure Key”技术,用于生成高质量的伪随机数。它包括一个硬件数字(digital)随机数生成器(DRNG),以及一个新的指令 rdrand,该指令用于以编程方式从 DRNG 获取值。
As a hardware unit, DRNG is a separate module on a processor chip. It operates asynchronously with the main processor cores at the frequency of 3 GHz. DRNG uses thermal noise as an entropy source. It also has a built-in testing system performing a series of tests to ensure high quality output. If one of these tests fails, DRNG refuses to generate random numbers at all. 作为一个硬件单元,DRNG 是处理器芯片上的一个独立模块。它使用主处理器核的 3 GHz 时钟频率异步运行。DRNG 使用热噪声作为一个熵源。它还具有一个内置的测试系统,可以进行一系列的测试,以确保高质量输出。假设这些测试的其中一个失败,则 DRNG 拒绝生成一切随机数。
The RDRAND instruction is used to retrieve random numbers from DRNG. The documentation states that theoretically DRNG can return nulls instead of random number sequence due to health test failure or if a generated random number queue is empty. However,
we were unable to drain the DRNG in practice.
Intel Secure Key is a really powerful random number generator producing high quality random numbers at a very high speed. Unlike other entropy sources, it is practically impossible to guess the initial RNG state initialized with rdrand instruction. RDRAND 指令用于从 DRNG 处获取随机数。Intel 的相关文档指出:从理论上而言,由于健康性测试失败,或者如果生成的随机数队列为空,那么 DRNG 可以返回空值,而不是随机数序列。然而在实践中,我们无法用尽它生成的所有随机数(即队列为空的情况)。
Intel Secure Key 是一个非常强大的随机数生成器,能够以非常高的速度产生高质量的随机数。与其它的熵源不同,几乎不可能猜测出通过 rdrand 指令初始化的初始随机数生成器(RNG)的状态。
The internal RNG interface function is ExGenRandom(). It also has an exported wrapper function RtlRandomEx(). Windows 8 ASLR uses this function as opposed to the previous version that relied on the rdtsc instruction. The rdtsc instruction is used for retrieving a timestamp counter on a CPU, which changes linearly so that it cannot be considered a secure random number generator. 内部的 RNG 接口函数为 ExGenRandom() 。还有一个导出的包装函数(封装了 ExGenRandom())叫做 RtlRandomEx() 。
Windows 8 的 ASLR 使用了该函数。 而在此之前的 Windows 版本中,MiInitializeRelocations() 例程会执行一个 CPU 指令 rdtsc ,它将获取的 CPU 时间戳计数器
(TSC,由于它的值仅会线性地改变,也就是可预测,因此不被视为一种安全的随机数生成器。)
(译注:在 Windows vista[NT 6.0 内核] 的 MiInitializeRelocations() 例程中,会执行 rdtsc 指令 ,它将获取的 CPU 时间戳计数器保存在内核变量 MiImageBias 中,MiSelectImageBase() 例程随机加载 DLL 时,就会将 MiImageBias 作为 RtlFindClearBits() 函数的参数,在
MiImageBitMap 位图中随机查找并设置可用的比特位来标识 DLL 在进程地址空间中的加载基址,
MiSelectImageBase() 例程随机加载可执行文件(EXE)时,会调用 ReadTimeStampCounter() 例程,后者也通过 rdtsc 指令取得 CPU 时间戳计数器,然后将该值进行一系列算术运算并保存到一个叫做 Delta 的变量中,从 PE 文件可选头的首选映像基址减去这个 Delta 值,就得出新的加载基址。
在 Windows 7 [NT 6.1 内核] 的 MiInitializeRelocations() 例程中, 也依赖于 rdtsc 指令来初始化 MiImageBias,并且它同样被 MiSelectImageBase() 例程随机化 DLL 的加载基址时使用,仅有的区别在于,MiSelectImageBase() 例程随机加载可执行文件时,计算 Delta 值的
方式不同,关于 Win7 和 Vista 的 ASLR 源码实现可以参考下面这篇文章:http://bbs.pediy.com/showthread.php?t=206911
正如原文所述,由于 rdtsc 指令生成的随机数有一定的规律,带来了安全隐患,所以在 Windows 8 中,MiInitializeRelocations() 通过新的 ExGenRandom() 例程及 rdrand 指令初始化 MiImageBias,如下代码所示:
The core function of the ASLR mechanism is MiSelectImageBase. It has the following pseudocode on Windows 8. ASLR 机制的核心函数是 MiSelectImageBase(),它在 Windows 8 中的伪代码如下所示:
As we can see, there are three different image bitmaps. The first one is for 32-bit executables, the second is for x64, and the third is for x64 with the image base above 4GB, which grants them a high-entropy virtual address. 正如我们所见, Windows 8 使用了三种不同的映像位图。第一个用于 32 位可执行文件(MiImageBitMap),第二个用于 x64
(MiImageBitMap64Low),第三个用于 4 GB 以上的 x64 映像基址(MiImageBitMap64High,它给予这些映像一个高熵的虚拟地址)。
The executables are randomized by a direct modification of the image base. As for the DLLs, ASLR is a part of relocation, and the random part of the image base selection process is ImageBias. It is a value that is initialized during the system startup. 源码中通过直接修改可执行文件的映像基址来对其进行随机化。至于 DLL,ASLR 属于其重定位的一部分,并且,映像基址选择过程的随机部分就是 ImageBias(它保存了三种内核全局变量之一:MiImageBias 或 MiImageBias64Low ,或 MiImageBias64High )。它的值在系统启动期间被初始化,请参考上面给出的 MiInitializeRelocations() 例程源码。
Image bitmaps represent the address space of the running user processes. Once an executable image is loaded, it will have the same address for all the processes that reference it. It is natural because of efficiency and memory usage optimization, since executables use
the copy-on-write mechanism.
ASLR implemented on Windows 8 can now force images, which are not ASLR aware, to be loaded at a random virtual address. The table below demonstrates the loader's behavior with different combinations of ASLR-relevant linker flags. 映像位图表示正在运行的用户进程的地址空间。一旦一个可执行映像被加载,对于所有引用它的进程都会有相同的地址。这是很自然的,因为考量到了引用效率和内存使用率优化,以及配合可执行文件使用的“写时复制”机制。
Windows 8 实现的 ASLR 能够对没有显式参与 ASLR 的映像,强制启用 ASLR,这样就能够加载到随机的虚拟地址。下表给出当使用不同的 ASLR 相关链接器标志组合时,映像加载器的 ASLR 相关行为:(绿色表示指定了该链接器标志,红色则表示没有指定)
*Cannot be built with MSVS because the /DYNAMICBASE option also implies /FIXED:NO, which generates a relocation section in an executable. 如果仅指定了 /DYNAMICBASE 链接器标志,它就隐含了 /FIXED:NO 链接器选项(这会在可执行文件中生成一个重定位节),然而,这样加载基址不会随机化,只有同时指定三个标志,或者至少前 2 个,才能随机化。
We can spot that the loader's behavior changed in Windows 8 — if a relocation section is available in the PE file, it will be loaded anyway. It also proves that ASLR and the relocation mechanism are really interconnected. 从上表可以发现,Windows 8 的映像加载器行为有所改变——如果 PE 文件中存在一个重定位节,那么无论如何,它都会被加载。这也证明了 ASLR 与重定位机制确实是相互关联的。
Generally we can say that implementation of the new ASLR features on Windows 8 doesn't much influence the code logic, that is why
it is difficult to find any profitable vulnerabilities in it. Entropy increase for randomizing various objects is in fact a substitution of a constant expression in a code. The code graphs also show that the code review has been done. 通常我们认为:Windows 8 实现的 ASLR 新功能并没有对代码逻辑构成太大的影响,这就是为什么要在其中找出任何有利可图的漏洞比较困难。为了随机化各种对象而增加的熵实际上是作为旧版 ASLR 代码中的常量表达式的一种替代。