每个程序的堆栈在内存中的哪里开始?

3
每个程序的堆栈从哪里开始?
我知道有一个随机地址空间选项,可以随机选择地址。如果禁用该选项,每个程序是否都从相同的地址开始?
如果我们打开两个终端并同时运行两个程序,系统会使用相同的起始地址来存储这两个程序的堆栈吗(在上下文切换期间将前一个程序的堆栈覆盖并加载当前程序的堆栈到同一位置)?
如果我通过调用 exec()-family函数来运行程序,例如以下示例,该程序和“易受攻击”的程序是否有不同的堆栈?还是易受攻击的程序只是在调用程序的堆栈顶部有一个不同的堆栈帧?
int main(int argc, char *argv[]) {
  char *buff, *ptr;
  int i;
  bsize  = atoi(argv[1]);

  if (!(buff = malloc(bsize))) {
    printf("Can't allocate memory.\n");
    exit(0);
  }
  for (i = 0; i < bsize; i+=4)
    buff[i] = '0';

  execl("/home/amulya/Desktop/CMPE209/HWs/HW2/vulnerable","vulnerable", buff, NULL);
  return(-1);
}

1
在哪个平台上?Windows?Unix?哪个Unix? - John Saunders
2个回答

6
你需要学习虚拟内存。是的,如果操作系统没有地址空间布局随机化(ASLR),所有程序很可能会在相同的虚拟地址上拥有它们的堆栈。但这并不意味着操作系统必须移动先前程序的堆栈才能切换到另一个程序,因为通过虚拟内存,它只需要确保两个程序具有相同的基本虚拟地址,但每个虚拟地址可以有不同的物理位置。(整个段落完全取决于操作系统)
至于你的第二个问题,execve用要执行的程序替换当前正在运行的程序,包括替换当前的文本/数据段以及堆栈,因此执行的程序将看不到先前程序的堆栈。

2
答案实际上取决于您使用的操作系统和架构。看起来您正在使用*nix变体,很可能是Linux。
对于Linux,在随机化成为标准之前,默认设置略低于内核空间的位置。在我的x86系统上,如果ASLR被禁用,则用于堆栈的区域默认为:bffea000 - c0000000 注意:我提供的值并不一定适用于所有系统,但这就是我的系统的情况。
在现代Linux系统中,堆栈将位于一个相当随机的地址。您可以通过连续运行以下命令来验证:
cat /proc/self/maps | grep "\[stack\]"

如果选项被禁用,我期望所有程序堆栈都默认为相同位置(用户空间的末尾)。
使用exec运行程序替换你的地址空间为新程序的地址空间; 这将包括堆栈,因此它将与运行的任何其他程序位于相同位置。想一想:你的shell程序必须执行fork/exec来运行程序,就像你的程序也会这样做...

谢谢回复。我今天做了一些实验,发现易受攻击的程序堆栈建立在调用程序的堆栈之上(即假设顶部朝向较低地址)。我这样说是因为易受攻击程序中分配给变量的内存地址(易受攻击程序只有一个变量,因此其框架不可能比调用程序的框架大)低于调用程序的ESP。 - user183766

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接