沒有棧就沒有函數(shù),沒有局部變量,傳統(tǒng)上其是一個特殊的容器,用戶將數(shù)據(jù)壓入棧中,也可以將數(shù)據(jù)彈出,遵循先入后出的原則。
也就是說是一個動態(tài)的內(nèi)存區(qū)域,壓棧增大了棧,出棧減少了棧。
通常esp寄存器定位棧頂部,壓棧使得棧頂?shù)刂纷冃?,彈出反之增大,因為從高地址開始。
減少esp等于在棧上開辟空間,反之就是回收空間。
棧在程序運行時,保存了函數(shù)所需要的維護信息,也就是堆棧幀,或者說活動記錄,里面包含了函數(shù)的返回地址和參數(shù),臨時變量,包括非靜態(tài)的局部變量,和編譯器自動生成的其他臨時變量。還保存了上下文,還由函數(shù)調(diào)用前后需要保持不變的寄存器。
一般就是esp和ebp兩個寄存器,esp指向棧頂部,ebp指向了函數(shù)活動記錄的一個固定的位置,也叫做幀指針。
一般來說一個函數(shù)的匯編代碼開頭應(yīng)該是:
push ebp;把ebp(old ebp)壓入棧
move ebp ,esp;這時候ebp指向棧頂,這時候棧頂是old ebp,也就是保存了舊的棧頂置針
返回的時候再把ebp給esp,從而獲得初始入棧的時候的函數(shù)信息。
一些函數(shù)前幾個字節(jié)會預(yù)留一些空字節(jié),這樣就可以動態(tài)的插入一個jmp指令,從而跳轉(zhuǎn)到另外一個函數(shù),那么我們就可實現(xiàn)一個簡單hook