2014-03-12 109 views
1

下面是C代碼緩衝區溢出不溢出返回地址

#include <stdio.h> 
void read_input() 
{ 
    char input[512]; 
    int c = 0; 
    while (read(0, input + c++,1) == 1); 
} 
int main() 
{ 
    read_input(); 
    printf("Done !\n"); 
    return 0; 
} 

在上面的代碼中,應該有陣列「輸入」的緩衝區溢出。我們給它的文件將包含超過600個字符,全部爲2(例如2222222 ...)(btw,ascii of 2是32)。但是,在用該文件執行代碼時,不會引發段錯誤,這意味着程序計數器寄存器不變。下面是在gdb輸入陣列的存儲的屏幕截圖,突出顯示在EBP(程序計數器)的地址寄存器,其清楚地表明它被跳過寫入時:

LINK

字符的書寫在程序計數器之後繼續,這也許是爲什麼段錯誤沒有顯示。請解釋爲什麼會發生這種情況,以及如何使程序計數器溢出。

回答

0

這很棘手! input[]c都是堆棧,c跟在input[]的512個字節之後。在閱讀第513個字節之前,請閱讀c=0x00000201(513)。但由於input[]已結束,所以您正在讀取0x32(50)到c,讀取結果爲c=0x00000232(562):實際上,這是小端,最不顯着的字節首先在內存中(如果這是一個大端架構,它是c=0x32000201 - 而且它確實會發生段錯誤)。

所以你實際上跳過562 - 513 = 49 bytes。比存在++,他們是50.其實你有沒有與0x32正好覆蓋50個字節(再次... 0x3232ab64是小端。如果您是不是字節雙字的顯示內存,您將看到0x640xab0x320x32)。

所以你寫在未分配的堆棧區域。它不會出現段錯誤,因爲它處於流程合法的空間(達到規定的限制),並且不會覆蓋任何重要的信息。

很好的例子,說明事物如果不爆炸就會發生嚴重錯誤!這是一個真實的例子還是一個任務?

啊是的...對於第二個問題,嘗試在input[]c之前宣佈c爲靜態...以便不覆蓋它。