天天看點

棧溢出攻擊c語言_棧溢出攻擊

我們先來看下面的一個例子:

~~~

#include

int main(){

char str[10] = {0};

gets(str);

printf("str: %s\n", str);

return 0;

}

~~~

在 main() 函數内部定義一個字元數組,并通過 gets() 為它指派。

在VS2010 Debug模式下運作程式,當輸入的字元不超過10個時,可以正确輸出,但是當輸入的字元過多時,就會出現運作時錯誤。例如輸入"12345678901234567890",就會出現下面的錯誤:

![](https://box.kancloud.cn/9d939f22fab553d3bf701939f3c78ac8_623x154.png)

這是為什麼呢?我們不妨先來看一下 main() 函數的棧:

![](https://box.kancloud.cn/94fc205f6aa42915645de5807db261e8_181x300.png)

局部數組也是在棧上配置設定記憶體,當輸入"12345678901234567890" 時,會發生數組溢出,占用“4位元組空白記憶體”、“old ebp”和“傳回位址”所在的記憶體,并将原有的資料覆寫掉,這樣當 main() 函數執行完成後,會取得一個錯誤的傳回位址,該位址上的指令是不确定的,或者根本就沒有指令,是以程式在傳回時出錯。

C語言不會對數組溢出做檢測,這是一個典型的由于數組溢出導緻覆寫了函數傳回位址的例子,我們将這樣的錯誤稱為“棧溢出錯誤”。

> 注意:這裡所說的“棧溢出”是指棧上的某個資料過大,覆寫了其他的資料

局部數組在棧上配置設定記憶體,并且不對數組溢出做檢測,這是導緻棧溢出的根源。除了上面講到的 gets() 函數,strcpy()、scanf() 等能夠向數組寫入資料的函數都有導緻棧溢出的風險。

下面是使用 strcpy() 函數導緻棧溢出的例子:

~~~

#include

#include

int main(){

char *str1 = "sfsdffffffffaeggggggg3r4t4nihfgi23ufhbu4bgui3beugb";

char str2[6] = {0};

strcpy(str2, str1);

printf("str: %s\n", str2);

return 0;

}

~~~

将 str1 複制到 str2,顯然超出了 str2 的接受範圍,會發生溢出,覆寫傳回位址,導緻 main() 函數傳回時出錯。

棧溢出一般不會産生嚴重的後果,但是如果有使用者精心構造棧溢出,讓傳回位址指向惡意代碼,那就比較危險了,這就是常說的棧溢出攻擊