網上關于棧溢出後用jmp esp執行shellcode的文章有很多,感覺分析的都沒有戳到點,是以想結合自己調試的經曆寫下自己的想法。
正常情況下,函數棧分布圖如下:
---->棧記憶體由低向高方向----->
|------------棧變量----------|----ebp----|------傳回位址------|函數形參|
發生溢出後,以上棧空間的内容被覆寫,可能從上面的布局變成這樣:
---->棧記憶體由低向高方向----->
|------------x90x90x90x90x90|x90x90x90..|shellcode緩存區的位址|x90x90.|
即,傳回位址被改為一段緩存區的位址。當函數執行結束,從棧中取傳回位址準備執行時,取到的是shellcode的位址,最終跳進shellcode執行。這段shellcode的位址一般被寫死為某個位址,這個位址可以存在于程式空間的任何地方,隻要有執行權限。
就像寫代碼時用絕對路徑讀取配置檔案的内容,偶爾會出錯一樣,為了解決這種錯誤,可能會用相對程式運作時的路徑去擷取配置檔案的内容。寫死shellcode的位址也會出錯,于是先人提出一種相對定位shellcode位址的方法,這就是jmp esp。
這用到了棧指針esp的一個特性:當函數執行ret指令後,Eip寄存器發生了跳轉,但Esp還指向函數形參在棧中的位址。如示意圖:
ret傳回前 esp的位置:
---->棧記憶體由低向高方向----->
|------------棧變量----------|----ebp----|------傳回位址------|函數形參|
^
|
esp指向這個位置
ret傳回後 esp的位置
---->棧記憶體由低向高方向----->
|------------棧變量----------|----ebp----|------傳回位址------|函數形參|
^
|
esp指向這個位置