我一直在阅读有关 ASLR 的信息,并且有几个问题。我几乎没有编程经验,但我对它背后的理论很感兴趣。
我知道它会随机化 DLL、堆栈和堆在虚拟地址空间中的位置,以便恶意代码不知道它们的位置,但是实际程序在需要它们时如何知道它们的位置?
如果合法进程可以找到它们,那么是什么阻止了恶意代码做同样的事情呢?
最后,ASLR 试图阻止的恶意代码是否在它正在攻击的进程的用户空间中运行?
谢谢
作为背景,ASLR 旨在使代码注入攻击复杂化,其中攻击者试图利用您的溢出错误来欺骗您的应用程序运行攻击者的代码。例如,在成功的堆栈缓冲区溢出攻击中,攻击者将他们的代码压入堆栈并修改调用帧的返回指针以指向堆栈上的代码。
大多数代码注入攻击都要求攻击者知道进程内存布局某些部分的绝对地址。对于堆栈缓冲区溢出攻击,他们需要知道易受攻击的函数调用的堆栈帧的地址,以便他们可以将函数返回指针设置为指向堆栈。对于其他攻击,这可能是堆变量、异常表等的地址......
另一个重要的背景事实:与编程语言不同,机器代码中包含绝对地址。虽然您的程序可能会调用函数foo()
,但机器代码会调用地址0x12345678
。
但是实际程序如何在需要它们时知道它们的位置?
这是由负责将磁盘上的可执行文件转换为内存进程的动态链接器和其他操作系统功能建立的。这涉及用对 的引用替换对foo
的引用0x12345678
。
如果合法进程可以找到它们,那么是什么阻止了恶意代码做同样的事情呢?
合法进程知道地址在哪里,因为动态链接器会创建进程,以便将实际地址硬连接到进程中。所以这个过程本身并没有找到它们。到过程开始时,地址都被计算出来并插入到代码中。攻击者无法利用这一点,因为他们的代码没有被动态链接器修改。
考虑攻击者拥有他们试图攻击的相同可执行文件的副本的场景。他们可以在他们的机器上运行可执行文件,检查它,并找到所有相关的地址。如果没有 ASLR,当您运行可执行文件时,这些地址在您的机器上很有可能是相同的。ASLR 将这些地址随机化,这意味着攻击者无法(轻松)找到这些地址。
最后,ASLR 试图阻止的恶意代码是否在它正在攻击的进程的用户空间中运行?
除非存在内核注入漏洞(这可能非常糟糕并导致您的操作系统供应商提供补丁),是的,它在用户空间中运行。更具体地说,它可能位于堆栈或堆上,因为这是存储用户输入的地方。使用数据执行预防也将有助于防止成功的注入攻击。