GDB'地址'。这些是什么?

时间:2014-01-15 09:24:25

标签: memory memory-management assembly gdb

这应该是一个非常简单,非常快速的qustion。这些是C编写的程序的前3行:

Dump of assembler code for function main:
   0x0804844d <+0>: push   ebp
   0x0804844e <+1>: mov    ebp,esp
   0x08048450 <+3>: and    esp,0xfffffff0
   ... ... ... ... ... ... ...

什么是0x0804844d0x0804844e以及0x08048450?它不受ASLR的影响。它仍然是内存地址,还是文件的相对点?

2 个答案:

答案 0 :(得分:4)

如果您查看Intel Developer Manual instruction-set reference,可以看到0x0804846d <+32>: eb 15 jmp 0x8048484相对地址进行编码。即它是jmp rel8短编码。这甚至可以在与位置无关的代码中工作,即在任何地址映射/加载时都可以运行的代码。

ASLR意味着每次将文件加载到内存时,可执行文件中的堆栈地址(以及可选的代码+数据)都会发生变化。 显然,一旦程序加载,地址将不再更改,直到再次加载。因此,如果您在运行时知道地址,则可以将其作为目标,但是假设固定地址,则无法编写漏洞。

在任何ASLR之后,GDB会向您显示进程虚拟内存空间中的代码地址。 (顺便说一下,GDB默认禁用ASLR:set disable-randomization on|off来切换。)


对于可执行文件,通常只有堆栈指针是ASLRed,而代码是位置相关的并且加载在固定地址,因此代码和静态数据地址是链接时常量,因此代码如{ {1}} / push OFFSET .LC0可以工作,将字符串常量的地址硬编码为call puts

无论如何,库通常需要与位置无关,因此ASLR可以在随机地址加载它们。

但可执行文件的ASLR是可能的,并且变得更加常见,可以通过making position-independent executables(Linux),也可以让操作系统修复每个硬编码的地址,当它在不同的地址加载可执行文件时编译为(Windows)。

地址仅与相同段内的相对意义上的文件中的位置具有1:1的关系。即代码的下一个字节是文件的下一个字节。可执行文件的标题描述了文件的哪些区域是什么(以及它们应该由OS的程序加载器映射到何处)。

答案 1 :(得分:3)

所示地址的含义在三种情况下有所不同:

  • 对于可执行文件
  • 对于DLL(Windows)或共享对象(.so,Linux和Un * x-like)
  • 对象文件

对于可执行文件:

可执行文件通常无法加载到内存中的任何地址。在Windows中,可以向可执行文件添加“重定位表”(非常旧的Windows版本需要);如果不存在(通常是使用GCC时的情况),则无法将文件加载到另一个内存位置。在Linux中,永远不可能将可执行文件加载到另一个位置。

您可以尝试这样的事情:

static int a;
printf("%X\n", &a);

执行程序100次时,您会看到a的地址始终相同,因此不会对可执行文件本身进行ASLR。

objdump转储的地址是绝对地址。

对于DLLs / .so文件:

地址是相对于DLL的基地址(在Linux下)或它们是绝对地址(在Windows下),当DLL加载到另一个内存区域时它们会发生变化。

对于目标文件:

转储目标文件时,地址与当前显示的部分相关。如果文件中有多个“.text”部分,则每个部分的地址将从0开始。