为什么每次关闭ASLR时ESP寄存器的值都一样?
因为操作系统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值现在不同了