堆栈上的局部变量

时间:2015-02-07 18:53:12

标签: 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

现在,我的问题:

  • 我认为草图是正确的。那么,那么第一个局部变量"有效"必须获得比第二个变量更高的内存地址"缓冲区",对吧?

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

1 个答案:

答案 0 :(得分:4)

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

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

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

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

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

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