2014-02-16 37 views
1

我目前正在嘗試開發對IA32體系結構中程序集的理解。我曾經想過我理解了堆棧結構,直到我運行了一些緩衝區溢出攻擊代碼,這些代碼將返回地址壓入堆棧頂部並返回。然後,這個程序讓我驚訝地回到了我已經推入堆棧的地址。我最初以爲基指針會用於返回,因爲它位於返回地址的旁邊。但是,我沒有觸及基指針。那麼,大會如何知道在哪裏返回?程序集如何知道在哪裏返回?

謝謝。

+1

大會是一種語言。它不會「知道」任何東西。 –

+1

CALL將EIP寄存器值壓入堆棧。 RET恢復它。如果你沒有解釋這個,很基本的東西,找一本書。 –

+0

返回時不使用EBP基址指針。返回地址是堆棧頂部的任何值。 EBP只是子程序可以用來幫助查找參數和本地棧變量的'幫助' – pscs

回答

3

ret指令只是彈出堆棧頂部的任何內容並將其用作返回地址。沒有任何幻想在發生。如果您沒有跟蹤堆棧大小,並且在錯誤的時間(在棧頂不是正確的返回地址的情況下)執行ret,則會出現錯誤。

1

x86有幾種方法可以返回。

最簡單的是RET指令。這將從棧中獲取當前地址,並將其放入EIP中,然後瞧。

因爲x86架構是一個CISC,所以它也具有擴展功能,所以你有一個帶有大小參數的RET。這一個用來運行添加到堆棧後返回後,以取代基本RET指令:

RET 16 
-- becomes 
RET 
ADD 16, esp 

這可以讓你寫一個指令,在你回到同​​一時間取消您的參數變量。調用約定在這種情況下非常重要,因爲調用者負責在堆棧中添加參數變量,並且被調用者將它們從堆棧中移除!

因爲x86處理器帶有所謂的段,所以有一條RET指令可以從堆棧中檢索段和IP地址。您現在不需要每天在常規程序中使用此指令,因爲內存模型足夠大以避免它,但它是可用的。這被稱爲FAR RET。

而且英特爾處理器支持4個級別的保護,這樣可以將內核保護(而不是由用戶的程序訪問)和驅動程序也可以駐留在保護的一個單獨的水平,以避免驅動器內核變質。 RET指令也可用於在這些級別之間切換。信息再次在堆棧中找到。

最後,對於中斷處理程序也有一個特例。在一個標準的程序中,你永遠不會看到那些僅在內核中使用的程序。只要處理器產生中斷,就會調用一個特殊的處理程序。該處理程序必須使用特殊的IRET指令(中斷返回)返回。那個也從堆棧中獲取數據,但它有更多的信息保存在那裏,例如寄存器和狀態標誌。

ESP -> +-------+ 
     | ... | <-- local variables 
EBP -> | ... | <-- previous frame pointer (EBP) 
     | ... | <-- registers that cannot be modified are saved here 
     | EIP | <-- IP address saved by CALL instruction 
     | ... | 
     | ... | <-- parameters to your function 
     +-------+ 
     | ... | <-- local variables of caller 
EBP -> | ... | <-- previous frame pointer (EBP) 
     ......... 
相關問題