一、進程使用的內存都可以按照功能大致分為以下4個部分:
代碼區、數據區、堆區、棧區
______________________________________________________________________
二、棧溢出
ESP: 系統棧最上面一個棧幀的棧頂
EBP:系統棧最上面一個棧幀的底部
EIP: 指向下一條等待執行的指令地址
- 在函數棧幀中,一般包含以下幾類重要信息:
局部變量:為函數局部變量開辟的內存空間
棧幀狀態值:保存前棧幀的頂部和底部(實際只保存底部,頂部通過堆棧平衡得到)
函數返回地址:保存當前函數調用前的“斷點”
- 函數調用步驟:
參數入棧:從左到右
返回地址入棧:將代碼區調用指令的下一條指令地址壓入棧中
代碼區跳轉:從當前代碼區跳轉到被調用函數的入口
棧幀調整:保存當前棧幀狀態,以備后面恢復本棧幀時使用(EBP入棧)-> 把當前棧幀切換到新棧幀(ESP裝入EBP)-> 給新棧幀分配空間(ESP減去所需空間大小,抬高棧頂)
push arg3; push arg2; push arg1; call 函數地址;(1.保存返回地址<push address;> 2.jmp 入口地址;) push ebp; mov ebp esp; sub esp xxx; |
- 函數返回步驟:
保存返回值:通常將函數的返回值保存在EAX中
彈出當前棧,恢復上一棧幀。具體包括:在堆棧平衡的基礎上,給ESP加上棧幀的大小,降低棧頂,回收當前棧幀的空間;將當前棧幀底部保存的前棧幀EBP值彈入EBP寄存器,恢復上一個棧幀;將函數的返回地址彈給EIP寄存器;
pop ebp;將上一棧幀底部恢復到EBP; retn;(1.彈出棧頂,即返回地址<棧幀恢復完成>; 2.處理器跳轉到返回地址) |
- 修改鄰接變量的原理
函數的局部變量在棧中一個挨着一個排列,如果這些局部變量中有數組之類的緩沖區,並且程序中存在數組越界的缺陷,那么越界的數組元素就有可能破壞棧中相鄰變量的值,甚至破壞棧中所保存的EBP、返回地址等重要數據。(注意:數組地址增長方式:頭在低地址,尾在高地址)
“內存數據”中的DWORD和我們邏輯上使用的“數值數據”是按照字節逆序過的