資源描述:
《堆棧溢出技術(shù)從入門到精通》由會員上傳分享,免費在線閱讀,更多相關(guān)內(nèi)容在行業(yè)資料-天天文庫。
1、堆棧溢出技術(shù)從入門到精通本講的預備知識:首先你應該了解intel匯編語言,熟悉寄存器的組成和功能。你必須有堆棧和存儲分配方面的基礎知識,有關(guān)這方面的計算機書籍很多,我將只是簡單闡述原理,著重在應用。其次,你應該了解linux,本講中我們的例子將在linux上開發(fā)。1:首先復習一下基礎知識。從物理上講,堆棧是就是一段連續(xù)分配的內(nèi)存空間。在一個程序中,會聲明各種變量。靜態(tài)全局變量是位于數(shù)據(jù)段并且在程序開始運行的時候被加載。而程序的動態(tài)的局部變量則分配在堆棧里面。從操作上來講,堆棧是一個先入后出的隊列。他的生長方向與內(nèi)存的生長方向正好相反。我們規(guī)定內(nèi)存的生長方向為向上,則棧的生長方向
2、為向下。壓棧的操作push=ESP-4,出棧的操作是pop=ESP+4.換句話說,堆棧中老的值,其內(nèi)存地址,反而比新的值要大。請牢牢記住這一點,因為這是堆棧溢出的基本理論依據(jù)。在一次函數(shù)調(diào)用中,堆棧中將被依次壓入:參數(shù),返回地址,EBP。如果函數(shù)有局部變量,接下來,就在堆棧中開辟相應的空間以構(gòu)造變量。函數(shù)執(zhí)行結(jié)束,這些局部變量的內(nèi)容將被丟失。但是不被清除。在函數(shù)返回的時候,彈出EBP,恢復堆棧到函數(shù)調(diào)用的地址,彈出返回地址到EIP以繼續(xù)執(zhí)行程序。在C語言程序中,參數(shù)的壓棧順序是反向的。比如func(a,b,c)。在參數(shù)入棧的時候,是:先壓c,再壓b,最后a.在取參數(shù)的時候,由于
3、棧的先入后出,先取棧頂?shù)腶,再取b,最后取c。(PS:如果你看不懂上面這段概述,請你去看以看關(guān)于堆棧的書籍,一般的匯編語言書籍都會詳細的討論堆棧,必須弄懂它,你才能進行下面的學習)2:好了,繼續(xù),讓我們來看一看什么是堆棧溢出。2.1:運行時的堆棧分配堆棧溢出就是不顧堆棧中分配的局部數(shù)據(jù)塊大小,向該數(shù)據(jù)塊寫入了過多的數(shù)據(jù),導致數(shù)據(jù)越界。結(jié)果覆蓋了老的堆棧數(shù)據(jù)。比如有下面一段程序:程序一:#includeintmain(){charname[8];printf("Pleasetypeyourname:");gets(name);printf("Hello,%s!"
4、,name);return0;}編譯并且執(zhí)行,我們輸入ipxodi,就會輸出Hello,ipxodi!。程序運行中,堆棧是怎么操作的呢?在main函數(shù)開始運行的時候,堆棧里面將被依次放入返回地址,EBP。我們用gcc-S來獲得匯編語言輸出,可以看到main函數(shù)的開頭部分對應如下語句:pushl%ebpmovl%esp,%ebpsubl$8,%esp首先他把EBP保存下來,,然后EBP等于現(xiàn)在的ESP,這樣EBP就可以用來訪問本函數(shù)的局部變量。之后ESP減8,就是堆棧向上增長8個字節(jié),用來存放name[]數(shù)組。現(xiàn)在堆棧的布局如下:內(nèi)存底部內(nèi)存頂部nameEBPret<------
5、[][][]^&name棧頂部堆棧底部執(zhí)行完gets(name)之后,堆棧如下:內(nèi)存底部內(nèi)存頂部nameEBPret<------[ipxodi