初步認識棧溢出漏洞


初步認識棧溢出漏洞

  1. 什么是棧?

棧是一種機制,計算機用它來將參數傳遞給函數,也可以用於放入局部函數變量,函數返回地址,它的目的是賦予程序一個方便的途徑來訪問特定函數的局部數據,並從函數調用者那邊傳遞信息。棧的作用如同一個緩沖區,保存着函數所需的所有信息。在函數的開始時候產生棧,並在函數的結束時候釋放它。棧一般是靜態的,也意味着一旦在函數的開始創建一個棧,那么棧就是不可以改變的。棧所有保存的數據是可以改變的,但是棧的本身一般是不可以改變的。

  1. 緩沖溢出分為兩種,一種是棧溢出,一種是堆溢出。
  2. 如何找到棧?

EIP:擴展指令指針。在調用函數時,這個指針被存儲在棧中,用於后面的使用。在函數返回時,這個被存儲的地址被用於決定下一個將被執行的指令的地址。

ESP:擴展棧指針。這個寄存器指向棧的當前位置,並允許通過使用push和pop操縱或者直接的指針操作來對棧中的內容進行添加和移除。

EBP:擴展基指針。這個寄存器在函數的執行過程中通常是保持不變的。它作為一個靜態指針使用,用於只想基本棧的信息,例如,使用了偏移量的函數的數據和變量。這個指針通常指向函數使用棧底部。

  1. 通過實踐來進行處理

     首先演示一下棧的形成:下面是以下代碼;

#include<stdio.h>
int main() { _asm { push 0x12345678 pop eax } }

      我們可以在VC++6.0 進行調試來觀察一下esp和eip以及ebp的狀態變化;

      我們F11來進行跟進下,就會發現esp棧頂指針會跟隨變化,因為我們向棧中壓人了12345678這樣四個字節的數據,指針會減小4個字節的。

 

      而我們pop的時候就會發現棧頂指針就變大成為了原來的樣子。這就告訴我們一個道理棧中壓人數據的時候棧頂指針是變小的,而彈出棧的時候棧頂指針是變大的。也就是棧底地址高於棧頂地址。

      接下來演示函數內棧的調用過程。

     首先沒有進入到overflow函數里面的的時候ebp和esp都是有值得,說明外面的main函數也有棧的實現。我們反匯編看一下具體棧的實現。F11單步走一下就會發現一個跳轉jmp跳轉到函數overflow。

     這時候后我們單步運行F11。

00401020 push ebp 00401021 mov ebp,esp 00401023 sub esp,44h 00401026 push ebx 00401027 push esi 00401028 push edi 00401029   lea         edi,[ebp-44h] 0040102C mov ecx,11h 00401031 mov eax,0CCCCCCCCh 00401036 rep stos dword ptr [edi] 5:        int our=0; 00401038   mov         dword ptr [ebp-4],0
6:        return;

     就會看到如上代碼,這時候我們來進一步分析一下。首先它將ebp指針壓人棧內,將當前的esp指向的地址給了ebp,這時候esp減小了44h,這時候在堆棧中又開辟了一個長度為44h的一個新的棧空間。從我們分析可以得出dword ptr[ebp-4],0這個局部變量是存放在新的棧空間里面的。ebp-4遠遠小於44h空間大小。局部變量是存放在棧中的。

     通過這個例子我們可以得出一個結論就是:

棧中存放的數據是什么?

      如果程序要調用某個函數,那么計算機就會自動將函數返回后執行的指令地址先壓入棧里,等函數調用完之后再從中取出,跳轉到該處執行。

溢出的原因?

      正式因為先放入棧的地址在前,而后放入棧的數據一旦過長,就會覆蓋到前面的地址這就會導致程序發生錯誤。

     下面來看一下如下的例子來演示棧溢出現象;

#include<stdio.h> #include<string.h> #include<windows.h>
void overflow(char *buf) { char des[5]=""; strcpy(des,buf); return; } void main(int argc,char *argc[]) { LoadLibrary("user32.dll"); char longbuf[100]="aaaaaaaaaaaabbbbcccccccccccc"; overflow(longbuf); return; }

程序一運行就會停止工作:

     下面我們來但不跟蹤一下程序:

    首先先把函數下一個地址以及參數壓入棧中:

     這時候但不運行到了strcopy這里:這是我們會發現將參數的值出來放在寄存器edx里面了,請看下面圖:48 FF 18 00

    這時候將程序運行到了ret的時候發現程序被strcopy給覆蓋了。

     返回地址變成了62626262;

     這是返回地址是錯誤的所以就會爆出該內存不可讀之類的錯誤提示。

     接下來的操作就是將溢出的地址跳轉到一個地方然后對讓它執行我們要執行的操作,執行完之后再跳轉回真實的返回地址就達到了我們想要的目的。

     我們分兩個環節來講。上面講述的是棧溢出的原理,下面的一個章節用來將棧溢出的利用。

 下一篇文章地址:(棧溢出的利用)http://www.cnblogs.com/dwlsxj/p/StackOverflow_1.html

如果有地方寫錯了還望各位大牛指正,小丁改正。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM