c - 栈上的局部变量

标签 c stack local-variables

为了理解堆栈帧的概念,我自己编写了一个小程序。首先,我将向您展示代码、一些关于它的草图,然后我将提出我的问题:

所以,程序:

int check_pw(char *password){
    int valid = 0;
    char buffer[10]; 

    strcpy(buffer, password);

    if(strcmp(buffer, "a") == 0){
       valid = 1;
    }

    return valid;
}

int main(int argc, char *argv[]){
   if(check_pw(argv[1])){
        printf("OK\n");
   }
   else{
        printf("Wrong password\n");
   }
}

我将密码作为命令行参数给出。如果它等于'a',那么就可以了。所以,我想事情已经很清楚了。

现在绘制一下函数 check_pw 的堆栈帧的样子:

               -------------------------         LOW
               |    buffer             |
               -------------------------
               |    valid              |
               -------------------------
               |    old EBP            |
               -------------------------
               |      RET              |
               -------------------------
               |      password         |
               -------------------------        HIGH

现在,我的问题:

  • 我认为草图是正确的。那么,第一个局部变量“valid”必须获得比第二个变量“buffer”更高的内存地址,对吧?

  • 但是当我使用 gdb 作为调试器时(我使用 Ubuntu Lucid Lynx),请在正确的位置设置断点并输入以下内容:x/x &validx/x &buffer 然后我得到“有效”的地址 0xbffff388 和“缓冲区”的地址 0xbffff38c 所以,很明显“buffer”有更高的地址,但为什么呢?

最佳答案

为了防止缓冲区溢出(例如,可以通过 strcpy 使用来利用缓冲区溢出),有一种技术,它包括在堆栈上分配的所有数组的末尾写入预定义的值。当函数返回时,将验证该值(通常称为金丝雀),如果该值发生更改,程序将中止。

函数完成后程序必须跳转回的地址被压入堆栈。常见的攻击是覆盖该值,使程序执行攻击者注入(inject)的代码。如果受损的缓冲区和指针存在金丝雀值,攻击者就必须猜测金丝雀值才能获得对程序执行的控制。

您可以在维基百科上了解更多信息:http://en.wikipedia.org/wiki/Buffer_overflow_protection#A_canary_example

您可以在 gcc 上禁用它。如果您像这样编译代码(假设您的程序文件名为login.c):

gcc -g -fno-stack-protector login.c

您会注意到变量不再重新排列。

关于c - 栈上的局部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28386038/

相关文章:

c - 生成文件错误 :/usr/bin/ld: cannot find -llibname and makedepend

c - 需要有关 PVoid 的帮助

java - 从用户输入读取堆栈的整数

c++ - 使用堆在堆栈中设置值

google-sheets - 我可以在 Google 电子表格公式中定义本地值(或变量)吗?

c++ - 在 C++ 中返回局部变量

c - 现场程序错误但不在代码块上

c - 如何在C中将int打印到char类型的数组变量中?

c++ - 在派生类中覆盖 C++ 模板函数

Java - 源代码中的本地变量与字节代码之间的双射映射