2015-02-07 51 views
2

为了理解堆栈框架的概念,我为自己编写了一个小程序。首先,我会告诉你的代码,它有点草图,然后我会提出我的问题:堆栈上的局部变量

因此,该程序:

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的清醒山猫),在适当的地方设置我的断点,然后键入以下内容:X/X &有效X/X &缓冲然后我得到地址0xbffff388为“有效”,0xbffff38c为“缓冲区” 因此,显然“缓冲区”有更高的地址,但为什么?

+3

编译器可以根据需要在堆栈框架中布局局部变量。 – 2015-02-07 19:01:55

+1

[堆栈上的局部变量分配顺序]的可能重复(http://stackoverflow.com/questions/1102049/order-of-local-variable-allocation-on-the-stack) - 似乎有其他类似的问题在右侧的相关侧栏 – 2015-02-07 19:02:57

+0

它是否也可以成为抵御诸如“缓冲区溢出”之类的漏洞的保护机制?因为那样我就没有机会溢出“有效”变量。 – user3097712 2015-02-07 19:06:07

回答

4

为了防止缓冲区溢出(如可能通过你的strcpy用被利用,比如一个),有这个技术,它包括对所有阵列分配结束写一个预先定义的值在堆栈上。当函数返回时,该值(通常称为canary)会被验证,如果该值发生更改,程序将中止。

函数完成后,程序必须跳回到的地址被压入堆栈。常见的攻击是覆盖该值,使程序执行由atacker注入的代码。如果有一个危险的缓冲区和指针,攻击者将不得不猜测Canary的值,以获得程序执行的控制权。

您可以了解更多关于它的维基百科:http://en.wikipedia.org/wiki/Buffer_overflow_protection#A_canary_example

您可以禁用在海湾合作委员会。如果您编译代码,像这样(假设你的程序的文件名是login.c的):

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

你会发现这两个变量不再重新排列。

+0

金丝雀?像在煤矿中担任煤气警报的金丝雀一样? – Quentin 2015-02-08 01:13:34

+0

我怀疑应该是这个词的起源,但我不知道它的词源:P – 2015-02-08 01:16:36

+0

感谢您使用“-fno-stack-protector”技巧的答案....我不知道 – user3097712 2015-02-09 16:39:54