Goo*_*ies 3 memory assembly gdb memory-management
这应该是一个非常简单、非常快速的问题。这些是 CI 中编写的程序的前 3 行:
Dump of assembler code for function main:
0x0804844d <+0>: push ebp
0x0804844e <+1>: mov ebp,esp
0x08048450 <+3>: and esp,0xfffffff0
... ... ... ... ... ... ...
Run Code Online (Sandbox Code Playgroud)
什么是0x0804844d和?它不受 ASLR 的影响。它仍然是内存地址,还是文件的相对点?0x0804844e0x08048450
如果您查看英特尔开发人员手册指令集参考,您可以看到0x0804846d <+32>: eb 15 jmp 0x8048484编码相对地址。即它是jmp rel8短编码。即使在与位置无关的代码中,这也适用,即在任何地址映射/加载时可以运行的代码。
ASLR 意味着每次将文件加载到内存中时,可执行文件中的堆栈(以及可选的代码+数据)地址都可以更改。显然,一旦程序被加载,地址就不会再改变,直到再次加载。因此,如果您在运行时知道该地址,则可以定位它,但您无法假设固定地址来编写漏洞利用程序。
GDB 在任何 ASLR 之后向您显示进程虚拟内存空间中的代码地址。(顺便说一句,GDB 默认情况下禁用 ASLR: set disable-randomization on|off进行切换。)
对于可执行文件,通常只有堆栈指针是ASLRed,而代码是位置相关的并且加载到固定地址,因此代码和静态数据地址是链接时常量,因此像push OFFSET .LC0/这样的代码call puts可以工作,硬编码将字符串常量的地址转换为push imm32.
无论如何,库通常需要与位置无关,因此 ASLR 可以将它们加载到随机地址。
但是可执行文件的 ASLR 是可能的,并且变得更加常见,可以通过制作与位置无关的可执行文件(Linux),或者通过让操作系统在将可执行文件加载到与编译时不同的地址时修复每个硬编码地址(视窗)。
地址仅在同一段内的相对意义上与文件内的位置具有 1:1 关系。即代码的下一个字节是文件的下一个字节。可执行文件的标头描述了文件的哪些区域是什么(以及操作系统的程序加载器应将它们映射到何处)。