【问题标题】:Why can't I overflow a global variable?为什么我不能溢出全局变量?
【发布时间】:2012-10-27 16:11:06
【问题描述】:

我有以下代码:

char buffer[10];      

void main(int argc, char *argv[]) {

   strcpy(buffer, argv[1]);
   printf("value of buffer %s\n",buffer);
}

我知道将缓冲区变量放在主函数中可能会使堆栈溢出,但是通过将其声明为全局变量,无论我从命令行输入多少 ascii 字符,都不会发生任何事情。我期待一个分段错误,但它似乎打印了我输入的所有字符。怎么会?

我还有一个与该主题相关的问题,如果程序存在缓冲区溢出漏洞,例如堆栈溢出,我是否可以在易受攻击的变量中输入任意大小的代码,或者如果代码超出为用户程序分配的内存边界,SO 是否会抛出分段默认异常?

【问题讨论】:

  • 你是用-Wall编译的吗?
  • 这有什么帮助? @shiplu.mokadd.im
  • 好的,OP 缺少 printf()strcpy() 的原型,是的。
  • @alk 我的错误。我虽然它会显示一些警告!但不是。它没有。

标签: c


【解决方案1】:

此代码会导致未定义的行为,您不能指望分段错误。任何事情都有可能发生。

【讨论】:

  • 并且“表现得像变量被声明为char buffer[9999]”是一种有效的“任何东西”。
  • @HenningMakholm 任何东西都是有效的。
  • 语言律师回答,技术上正确,但可能更有帮助。 C 标准没有解释为什么越过局部变量的末尾与越界全局变量不同,所以让我们超越标准。
【解决方案2】:

试试下面的模组看看有什么副作用:

char buffer[10];      
char buffer1[10] = "123456789";      

void main(int argc, char *argv[]) {

   strcpy(buffer, argv[1]);
   printf("value of buffer %s\n",buffer);
   printf("value of buffer1 %s\n",buffer1);
}

【讨论】:

    【解决方案3】:

    你溢出了你的全局变量,只是没有(显然)因为它而发生任何不好的事情。尝试将您的代码更改为如下所示:

    char before[20];
    char buffer[10];
    char after[20];
    

    根据您的工具链布局内存的方式,您应该能够在beforeafter 中看到溢出buffer 的后果。

    您没有获得 SEGV 的具体原因是,只有当您尝试存储的位置位于操作系统分配给您的进程的区域之外时,才会发生这种情况。此分配是在 4k 单元(通常)上完成的,通常是其中几个单元,因此您可能必须溢出 global 至少 4kB,并且可能要溢出 1MB 或更多才能触发 SEGV。

    【讨论】:

    • 我尝试了 memsetting buffer memset ( buffer, 'a', 4000 ); 并没有发生任何事情。然后我把它改成了memset (buffer, 'a', 5000),我得到了一个SEGV
    【解决方案4】:

    全局变量不存储在堆栈中。它们存储在 .data/.bss 中,并向更高的地址空间增长。堆栈变量向较低的地址空间增长。程序指令(在 .text 中)低于 .data,因此溢出全局不会覆盖它们所以你不会看到任何明显的事情发生(比如 seg 错误)。

    反正在 linux 上。

    【讨论】:

      【解决方案5】:

      正如其他答案所解释的,语言规范让您无权期望对缓冲区溢出(无论是全局变量还是局部变量)有任何特殊反应。

      实际发生的情况是,某些未保留用于buffer 的内存确实会被覆盖。但是,由于您的程序在您的printf 之后立即退出,因此很可能使用该内存的任何东西都没有机会注意到应该存在的值不再存在。也有可能链接器在buffer 之后分配了一堆未使用 空间,例如,如果它将可写数据段的大小四舍五入为4096 的倍数或其他一些方便的块大小。

      【讨论】:

        【解决方案6】:

        尝试使用更大的输入缓冲区,例如:

         ./tst $(perl -e "print 'A'x10000")
        

        你可能最终会遇到段错误。

        正如一些人在他们的答案中提到的那样,对象是未定义的行为,任何事情都可能发生。

        此外,虽然 C 不涉及堆栈或堆,但文件范围变量(如程序中的 buffer)通常不存储在堆栈中。

        当缓冲区在堆栈中时,您会很快(即,不需要非常大的输入)缓冲区用一些随机地址覆盖函数的返回地址,这就是函数返回时出现段错误的原因.

        【讨论】:

          猜你喜欢
          • 2023-03-25
          • 1970-01-01
          • 2019-05-04
          • 2021-01-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-12
          相关资源
          最近更新 更多