上一篇介绍了Windows地址空间布局随机化防御机制分析(上)。本文介绍了在Windows上实现的地址空间空间布局随机化的一些历史,并探讨了Windows实现的一些特性和局限性。将32位程序重新编译为64位程序,使地址空间布局随机化更有效尽管64位版本的Windows已成为主流十多年,但32位版本仍被广泛使用。有些程序确实需要保持与第三方插件的兼容性,例如网络浏览器。有时开发团队决定程序需要的内存远远少于4GB,因此32位代码可以节省空间。在支持构建64位应用程序之后,甚至VisualStudio也支持了一段时间的32位应用程序。事实上,从32位代码切换到64位代码会产生很小但可以观察到的安全优势。原因是随机化32位地址的能力是有限的。至于具体原因,请观察图1中32位x86内存地址是如何分解的,详见“物理地址扩展”。内存地址被分成多个组件,只有其中一些可以在运行时轻松随机化操作系统不能简单地随机化地址的任意位,随机化页面部分中的偏移量(位0到11)会破坏程序的数据对齐能力假设。页目录指针(第30位和第31位)也不能更改,因为第31位是为内核保留的,而第30位被物理地址扩展用作存储区交换技术来寻址超过2GB的RAM,这使得1432位地址的位不能被随机化。事实上,Windows只尝试随机化32位地址的8位。这些是从16到23的位,只影响地址的页目录条目和页表条目部分。因此,在暴力破解的情况下,攻击者可能只需猜测256次就可以猜出EXE的基地址。将ASLR应用于64位二进制文??件时,Windows能够随机化地址的第17-19位(取决于它是DLL还是EXE)。图2显示了64位代码的可能基地址数量以及相应的暴力猜测数量如何显着增加,这可以让端点保护程序或系统管理员在攻击发生之前检测到它们。将32位代码重新编译为64位大大增加了可供地址空间布局随机化选择的基地址数量总结起来:1.必须处理不可信数据的软件应始终编译为64位,即使它确实如此不需要使用大量内存也可以利用地址空间布局随机化。在暴力攻击中,地址空间布局随机化使得攻击64位程序的难度至少是攻击完全相同程序的32位版本的512倍。2.即使是64位的ASLR也容易受到暴力攻击,防御者必须专注于检测暴力攻击,或者避免暴力攻击可行的情况。假设攻击者每秒可以对易受攻击的系统进行十次暴力尝试。在通常情况下,由于多个实例正在运行并且目标进程保持在同一地址,因此攻击者可以在不到一分钟的时间内发现32位程序的基地址,并在数小时内发现64位程序的基地址。64位暴力破解攻击更具侵入性,但管理员或安全软件需要注意并采取措施。除了使用64位程序来提高地址空间布局随机化的效率外,系统还应避免重新生成崩溃的程序,以免让攻击者发现基地址。最好强制重启以防万一,所以要保证进程崩溃后地址空间会刷新几次。3.开发针对32位和64位版本程序的概念验证攻击的研究人员应首先关注32位,因为针对32位程序变体的概念验证攻击可能更容易开发只要32位程序仍然有效。由此产生的攻击可能更加可行和令人信服,从而导致供应商更快地修补。Windows10将比Windows7更频繁地重用随机基地址,这可能使其在某些情况下容易受到攻击请注意,即使是Windows系统也必须确保DLL或EXE的多个实例都在同一基地址上系统不需要跟踪卸载DLL或EXE的最后一个实例时的基地址。如果再次加载DLL或EXE,它可以获得新的基地址,这是我们在使用Windows7时观察到的行为。Windows10的工作方式不同,即使在卸载DLL或EXE的最后一个实例之后,它也可能至少在短时间内保持相同的基地址,EXE比DLL更是如此。在多进程调试器下重复启动命令行程序时可以观察到这一点。但是,如果程序被复制到一个新的文件名然后启动,它将收到一个新的基址。此外,如果经过了足够长的时间,程序将加载到不同的基地址。当然,重新启动会为所有DLL和EXE生成新的基地址。总结一下:除了每次启动随机化之外,不要对WindowsASLR保证做出任何假设。特别是,不要依赖Windows7的行为在加载给定EXE或DLL的第一个实例时随机分配新地址空间。不要假设Windows以任何方式天生就免疫针对地址空间布局随机化的暴力攻击,尤其是对于32位进程,暴力攻击可能需要256次或更少的猜测。Windows10更加积极地利用地址空间布局随机化,可以有效地防范与地址空间布局随机化不兼容的exe和dll,这可能使地址空间布局随机化的应用更加广泛WindowsVista和Windows7是第一个系统为了支持地址空间布局随机化,所以地址空间布局随机化在设计之初就在兼容性方面做了一些取舍。具体来说,这些较旧的实现不会将地址空间布局随机化应用于未标记为与地址空间布局随机化兼容的图像,也不允许地址空间布局随机化将地址推送到4GB边界之外。如果图像没有选择地址空间布局随机化,这些Windows版本将继续使用首选基地址。Windows7可以使用Microsoft的增强缓解体验工具包(通常称为EMET)进一步强化,以更积极地将地址空间布局随机化应用于甚至未标记为与其兼容的图像。Windows8引入了更多功能,可将ASLR应用于与地址空间布局随机化不兼容的图像,更好地随机化堆分配,并增加64位图像的熵位数。总结一下:1.确保您的程序项目使用正确的链接器标志来选择最积极的地址空间布局随机化实现,并且不使用任何削弱地址空间布局随机化的链接器标志。如下表所示,链接器标志会影响地址空间布局随机化应用于图像的方式。请注意,对于VisualStudio2012及更高版本,“+”标志已默认启用,只要不使用“-”标志,则使用最佳地址空间布局随机化实现。使用VisualStudio2010或更早版本(可能出于兼容性原因)的开发人员需要检查链接器支持哪些标志,哪些标志默认启用。链接器标志可能会影响ASLR应用于图像2的方式。为了启用强制地址空间布局随机化和自下而上随机化,Windows8和Windows10包括一些可用的可选功能空间布局随机化在兼容图像上强制执行并随机化虚拟内存分配,以便重新定位图像获得随机基地址。这在EXE与ASLR兼容但它使用的其中一个dll不兼容时很有用。防御者应该启用这些功能以实现更广泛的ADR应用,重要的是,它有助于发现任何剩余的ADR不兼容程序,以便可以升级或替换它们。ASLR将整个可执行映像重新定位到一个单元中ASLR通过选择一个随机偏移并将其应用于映像中相对于其基地址的所有地址来重新定位可执行映像。也意味着:如果EXE中的两个函数位于地址0x401000和0x401100,那么即使在重新定位图像后,它们之间仍然存在0x100字节的距离。显然,这很重要,因为相对调用和jmp指令在x86代码中无处不在。同样,位于0x401000的函数将与图像的基地址相距0x1000字节,无论它位于何处。同样,如果两个静态或全局变量在图像中相邻,则在应用地址空间布局随机化后它们将保持相邻。相反,堆栈和堆变量以及内存映射文件不是映像的一部分,可以随意随机分配,而不管选择的基地址如何。总结一下:1.可执行映像中仅仅一个指针的泄漏就可以暴露整个映像的随机地址。ASLR最大的限制和烦人的事情是一些看似无害的功能,如调试日志消息或堆栈跟踪,可能会泄漏图像中的指针,从而成为漏洞。如果攻击者拥有相同程序或DLL的副本,并且可以触发它产生相同的泄漏,他们可以计算地址空间布局随机化与地址空间布局随机化之前的指针之间的差异,以确定随机化前后的偏移量.然后,攻击者可以将此偏移量应用于其攻击负载中的每个指针,以绕过地址空间布局随机化。防御者应就指针暴露漏洞对软件开发人员进行教育,以便他们认识到此漏洞的严重性,并在软件开发生命周期中定期评估软件是否存在这些漏洞。2.某些类型的内存损坏漏洞超出了ASLR的防护范围。并非所有的内存损坏漏洞都需要直接实现远程代码执行。例如,有这样一个程序,它包含一个用于接收来自网络的不可信数据的缓冲区变量,以及一个标志变量,它位于内存中的下面。flags变量包含指定用户是否登录以及用户是否是管理员的位。如果程序在接收缓冲区的末尾写入数据,“标志变量将被覆盖,攻击者可以设置已登录标志和is-admin标志。由于攻击者不需要知道或写入任何内存地址,地址空间布局是随机的更改不会阻止攻击。只有在另一种强化技术(例如编译器强化标志)重新排序变量,或者更好的是让变量独立于它们在程序中的位置移动时,才能防止这种攻击。总结地址空间布局随机化是抵御内存损坏漏洞的核心防御措施,本文介绍了在Windows上实现的地址空间布局随机化的一些历史,并探讨了Windows实现的一些特性和局限性。通过阅读本文,防御者可以熟悉如何构建程序以更好地利用地址空间布局随机化和Windows中提供的其他功能。然而,地址空间布局随机化的防御机制并不完善。攻击者可以利用地址空间布局随机化的局限性,例如只在每次重启时应用地址空间随机化,将整个图像重新定位为一个单元随机化,从而使用暴力破解和指针泄漏攻击来绕过地址空间的保护随机化。本文翻译自:https://www.fireeye.com/blog/threat-research/2020/03/six-facts-about-address-space-layout-randomization-on-windows.html如有转载请注明原文地址。
