2017-04-03 67 views
0

我只是想知道,因为我有这样的C代码:关闭堆栈保护

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

int fillBuffer(int argc, char *argv[]) { 
    char bufferA[4] = "aaa"; 
    char bufferB[4] = "bbb"; 

    if(argc > 1) 
    strcpy(bufferB, argv[1]); 

    printf("bufferA: %s\n", bufferA); 
    printf("bufferB: %s\n", bufferB); 

    return 0; 
} 

int main(int argc, char *argv[]) { 
    fillBuffer(argc, argv); 
    return 0; 
} 

,我试图通过关闭堆栈保护:-fno-堆栈保护

当我尝试做运行它:./program(escape)键5F,节目输出到:

缓冲液A:F

bufferB:FFFFF

我只是不确定bufferA是如何变成f的。任何人都可以向我解释这个吗?

+0

你确定'argv [1]'是'3'个字符吗?... – LPs

+1

未定义的行为,任何事情都可能发生。这只是一种可能性。 –

+0

c代码刚刚给我们作为例子 –

回答

0

您的strcpy调用是不安全的,如果argv [1]包含多于3个字符(加上一个用于空终止字符),将会损坏您的堆栈。别打逃跑,只是空间和5F,你会得到正确的输出:

scott> a.out 5f 
bufferA: aaa 
bufferB: 5f 

当你打逃脱,外壳可以添加额外字符的字符串参数,因为你的strcpy是不安全的(不检查长度),它会超出缓冲区的末端并损坏堆栈。您的缓冲区只有4个字符长,所以如果输入的参数长度超过3个字符,程序将损坏堆栈。

为了解决这个问题,从4增加缓冲区大小,以更合理像60,并使用strncpy()函数,以确保您不会超过缓冲区如果参数过长:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

#define MAX_PARM_LEN 60 

int fillBuffer(int argc, char *argv[]) { 
    char bufferA[MAX_PARM_LEN] = "aaa"; 
    char bufferB[MAX_PARM_LEN] = "bbb"; 

    if(argc > 1) 
    strncpy(bufferB, argv[1], MAX_PARM_LEN); 

    printf("bufferA: %s\n", bufferA); 
    printf("bufferB: %s\n", bufferB); 

    return 0; 
} 

int main(int argc, char *argv[]) { 
    fillBuffer(argc, argv); 
    return 0; 
} 

最后一点:不要关闭堆栈保护。

1

本地缓冲区A和B在您的堆栈上以相反顺序存储。因此,在内存中你有8个字节,起始缓冲区B然后缓冲区A.

当你strcpy你的5“f”到缓冲区B时,前4个进入缓冲区B,最后一个结束字符串'\ 0'缓冲区A.

然后当你printf你的缓冲区时,缓冲区A包含1“f”和字符串终止符。这就是它的来源。