簡體   English   中英

調用堆棧內存架構

[英]Call stack memory architecture

昨天收到我的問題后 ,我嘗試進一步了解有關調用堆棧的體系結構。 在線搜索和SO搜索都沒有找到我想要的答案,這可能是因為我不知道該使用哪個關鍵字。 無論如何,我確定這里有人可以幫助我...

首先,讓我們從Wikipedia的條目摘錄中獲取堆棧緩沖區溢出

在軟件中,當程序在預期的數據結構之外寫入程序的調用堆棧上的內存地址時,就會發生堆棧緩沖區溢出。 通常是固定長度的緩沖區。

一位同事告訴我,他記得曾經學過的知識,在Linux上,堆棧位於進程的虛擬內存的最后,並根據需要向后增長-因此它不是“固定長度緩沖區”。 但是,我無法確認這一點。 所以我的問題是:

  1. 在Windows和Linux上,調用堆棧是否始終是固定大小的緩沖區? 如果沒有,它將如何增長? 它如何管理與堆共享虛擬內存?
  2. 堆棧的體系結構是否取決於所使用的編譯語言? 在操作系統上? 在硬件上?
  3. 堆棧的大小是在編譯時確定的還是可以事后更改?
  4. 如何以及在哪里分配各個線程的調用堆棧?

堆棧緩沖區溢出

堆棧緩沖區溢出是指程序意外或惡意地在堆棧上某個特定數據項的范圍之外(例如c字符串)寫入數據的情況。 這具有修改堆棧(而不是堆)上附近的控件或數據結構的值的效果,這可能導致不良的程序行為,例如崩潰,錯誤或更改控制流。

通常,這不是指在堆棧本身范圍之外進行寫操作,而堆棧范圍通常受保護頁保護,以防止意外超載或不足。

| start of stack |
| data           |
| parameters     |
| return address |
| data           |
| parameters     |
| return address |
| parameters     |
| return address | <- might overflow into this region or above
| string data    | <- writes to this region ... (look up)
 stack head
  |
  V direction of growth for pushes
 ...
| end of stack   |
| guard page     | <- writes to this region cause a segfault
 ...
| heap           |

Linux上的調用棧

調用堆棧是固定大小的,實際堆棧本身會在此限制內根據需要增長和縮小。

堆和堆棧不重疊也不共享內存-它們通常在虛擬地址空間的不同區域中進行管理。

進程主堆棧的大小由程序運行時所在的環境確定。 有關設置此功能的c函數,請參見man 3 ulimit並從bash查看/設置它,有關詳細信息,請參見ulimit -s

> ulimit -s
8192

如果創建自己的線程,則可以承擔創建其堆棧的責任(請參閱man pthread_attr ),可以使用系統建議的大小或設置自己的大小。

對於Windows:

  1. 對於用戶模式應用程序,默認情況下,堆棧的內存最初保留為1 MB。 保留表示地址范圍不能用於任何其他目的,但實際上並未分配內存。 這允許堆棧在內存中是連續的,但不需要默認分配所有堆棧(即使大多數堆棧將不使用)。 在實際提交的堆棧的末尾有一個保護頁-每當訪問該頁時,Windows就會為堆棧分配更多的內存。 如果嘗試使用超出為堆棧保留的空間,則會出現堆棧溢出異常。 VirtualAlloc的MSDN頁面會詳細介紹保留與提交。

  2. x86對堆棧提出了一些嚴格的要求(例如,必須向下擴展)。 其他架構更加靈活。 幾乎所有基於x86的OS都類似地使用堆棧。 可以使用其他堆棧體系結構。 您無法使用任何x86的堆棧支持,都必須自己手動執行,但是在調用任何OS API時都必須轉換為傳統堆棧。

  3. 該信息存儲在.exe中。 您可以使用鏈接器標志進行調整。 另外, CreateThread API允許您更改堆棧大小。

  4. 使用.exe中的默認值或從對CreateThread的調用中指定的值在創建線程時創建線程的堆棧。

當您溢出存儲在堆棧上的固定長度緩沖區並覆蓋堆棧上的其他控制數據(如返回地址)時,就會發生堆棧緩沖區溢出。

例如,假設您調用函數,它有一個16字節大小的本地緩沖區。 調用堆棧可能看起來像這樣(為清楚起見,省略了其他詳細信息:

0x1000 - Return address
0x990 - Buffer

如果您的代碼有錯誤,並在0x990處溢出緩沖區,則將覆蓋返回地址。 如果攻擊者可能導致緩沖區溢出,則他們可以將一些代碼放入緩沖區,然后覆蓋返回地址以指向返回的代碼。 函數返回時,它會跳轉到攻擊者的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM