1、前言
最近在再看《程序員的自我修養》這本書,對程序的鏈接、裝載與庫有了更深入的認識。關于這本書的評價可以去豆瓣看看http://book.douban.com/subject/3652388/,強烈推薦給每一位程序員哈。今天看了第十章內存,主要講的是棧和堆的管理。主要問題是:函數在棧中是如何布局的,如何通過緩沖區溢出來調用另外一個函數,即堆棧溢出攻擊。
2、基本概念
棧(stack):我第一次接觸棧是從數據結構中,此時的棧是一種基本數據結構,棧的基本屬性是先進后出(FILO)。
在計算機系統中,棧是一個具有先進后出屬性的動態內存區域。程序可以將數據壓入棧,也可以將數據從棧頂彈出。棧的增長方向是向下增長,即由高地址向低地址方向。在i386下,esp寄存器定位棧頂,ebp寄存器定位棧底(棧指針)。esp始終指向棧頂,隨著函數的執行,esp不斷的變化,而ebp固定在棧底位置不變。
3、棧的作用
用于維護函數調用的上下文,離開了棧函數調用沒法實現。棧中保存了一個函數調用所需要的維護信息,通常稱為堆棧幀或活動記錄。
堆棧棧包括的內容:
(1)函數的返回地址和參數
(2)臨時變量
(3)保存的上下文,例如函數調用前后保持不變的寄存器。
4、函數調用過程
(1)把所有的參數壓入棧
(2)把當前指令的下一條指令的地址壓入棧中(函數的返回地址)[可以實現堆棧溢出攻擊]
(3)跳轉到函數體執行
其中(2)(3)由指令call一起執行的。
例如下圖所示的程序:
匯編代碼如下圖所示:
5、堆棧溢出攻擊
通過堆棧溢出改變函數的返回地址,調用另外一個過程。例如下面的程序:
匯編程序如下所示:
程序輸出結果如下所示:
文章列表