为什么每次关闭ASLR时ESP寄存器的值都一样?

逆向工程 拆卸 记忆 开发
2021-06-15 15:56:31

系统上运行着许多函数,它们也需要ESP 寄存器(x86)。因此,如果它的值变得恒定(通过​​关闭ASLR),那么每个函数怎么可能具有相同的 ESP 值?

3个回答

因为操作系统ESP总是以相同的值初始化(并且您查看的程序的执行是确定性的)。

ASLR(地址空间布局随机化)用于堆栈随机化的方式非常简单。在程序启动时,操作系统在初始化ESP寄存器时,会为其添加一个随机值。

当您禁用 ASLR 时,将跳过此添加并始终以相同的值开始。

例如,在 Linux ( arch/x86/kernel/process.c) 中,我们有:

unsigned long arch_align_stack(unsigned long sp)
{
    if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
            sp -= get_random_int() % 8192;
    return sp & ~0xf;
}

如您所见,堆栈指针 ( ESP) 被添加到一个随机值以对其原始值进行混洗。并且,如果条件中的条件之一不为真,它将被忽略。

所有其他操作系统的行为大致相同(据我所知)。

打开/关闭 ASLR 会影响堆栈指针初始值。每当调用函数时,它都会通过从堆栈指针中减去来保留所需的堆栈量。当这个函数调用另一个函数时,它将把它的参数压入堆栈(这会进一步减少堆栈指针),然后调用另一个函数。

如果您多次运行同一个程序,关闭aslr并使用完全相同的输入,从而保证相同的程序流程,您的函数每次都会获得相同的堆栈指针。但它不是初始堆栈指针;它是初始堆栈指针减去先前函数所需的所有堆栈帧。

如果您运行同一程序几次,ASLR翻,并用完全相同的输入,从而保证相同的程序流程,你的函数每次都会得到不同的堆栈指针。但是,初始堆栈指针(调用 main() 时)与您的函数获得的指针之间的差异将是相同的。

当然,这假设堆栈向下增长,这是 x86/x64 和大多数其他当前处理器的情况,但存在堆栈增长的体系结构。在这些架构上,将“减去”替换为“添加”。

编辑:

我的水晶球只是告诉我,“系统上运行了许多功能,而且它们需要 esp”,你想说“系统上同时运行许多进程,每个进程都需要一个堆栈;怎么能“如果关闭 ASLR 并且它们具有相同的堆栈指针,它们会共存吗?它们不会覆盖彼此的堆栈吗?”

这就是虚拟内存的意义所在。互联网上有很多资源比我用几行代码更好地解释了虚拟内存;所以就这样:对于不同的进程,相同的虚拟地址被映射到不同的物理地址。

但是,这不再与逆向工程有太大关系。

好吧,即使关闭ASLR,它也不会对每个函数都固定,简单的例子是函数A调用函数B

A:
...
...
...
call B ---> (1)
[next instruction]
...

(1) 这条汇编指令会将[下一条指令]的地址压入堆栈作为返回地址,这会增加ESP的值,这意味着函数B的ESP值现在不同了