文章來源:blog.seclibs.com/基於數組越界的緩衝區溢…程序員
上一篇文章說了函數調用時候的堆棧變化,這裏就基於這個內容來驗證一下基於數組越界的緩衝區溢出。數組
在c語言中,數組必須是靜態的,也就是在定義的時候必須明確數組的大小,在根本上來講,這個是堆棧提高的緣由,只有在數組的大小肯定的時候,才能明確堆棧到底要提高多少,若是數組的大小是動態變化的,就極容易發生緩衝區溢出;並且c語言也不具有Java等語言中靜態分析的功能,不會去檢測數組是否有上溢或者下溢,其邊界的檢驗是有程序員負責的,因此這就形成了一些問題,咱們能夠經過數組越界來改變一些內容。函數
首先來看一下此次的實驗程序3d
正常來講,test1函數並無被調用,因此是不會打印出12345的,而實際的狀況卻不是這樣的cdn
形成這樣的狀況,就是因爲數組越界而形成的緩衝區溢出,這其中還有一個編譯器的坑,在後面再解釋。blog
咱們直接在數組處下斷點,前面的提高堆棧等操做就不細說了,前一篇文章已經走過一邊流程了,這裏直接給出到這一步的堆棧圖。get
而後咱們看一下編譯器是如何處理數組賦值的內容的編譯器
通過這段賦值操做,此時堆棧已經變成了下圖,這裏單獨從中拎出來10行方便觀看。博客
經過堆棧圖咱們能夠很清晰的看到,明明只有8個數,它確是從ebp-24h開始排的,也就是說ebp-4的位置是沒有使用的,這個也就是前面所說的坑,通過查詢資料,發現從vs2010開始,ebp-4就都沒有使用,具體是用來作什麼的,暫時還不清楚,因此若是這裏你使用的是vc6.0的話,這裏就是從ebp-4開始排的。it
好了說了上面那個坑,接着回來講堆棧圖,在上一篇文章裏咱們已經很清楚函數在調用的時候會先把call語句的下一行地址壓入棧中,因此圖中b[10]的位置也就表明了ret返回地址的位置,在vc6.0中此處應該是b[9],若是咱們將這個地址替換爲咱們想讓程序到達的位置,也就能夠控制程序的運行軌跡了。
在後面的操做就是將test1函數的地址賦給了b[10],也就代替了以前函數的返回地址,這個函數在執行完成後便會返回test1函數的位置081137Ah。
也就達到了緩衝區溢出的效果。
文章首發公衆號和我的博客
公衆號:無意的夢囈(wuxinmengyi)