2017-04-03 66 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」和字符串終止符。這就是它的來源。