棧的保護 windows和linux

2021-08-25 01:30:34 字數 2392 閱讀 1499

上面提到的兩種方式中,安全cookie提供了更大的保護,而不可執行棧在遇到溢位**放到堆的時候就很難奏效了,先看看安全cookie是怎麼一回事。 在傳統的函式呼叫時,棧自下而上是:引數-->返回位址-->老的棧底指標-->區域性變數-->...如果區域性變數發生向下溢 出,覆蓋了函式的返回位址,那麼程式一點脾氣也沒有,乖乖聽任你的擺布,但是這種錯誤的行為是在被調函式返回的時候發生的,如果被調函式有漏洞,那麼我們希望的是在它返回的時候,也就是出了它的控制範圍的時候主動地報出錯誤,而不是將錯就錯,那麼就需要一種有效的方式來檢測到錯誤的發生,於是安全 cookie就臨危受命了,它實際上就是在引數-->返回位址-->老的棧底指標-->區域性變數-->...中間插入了乙個 cookie,使得這個結構變為了引數-->返回位址-->老的棧底指標-->cookie-->區域性變數-->...這 個cookie是每個程式映像都有的乙個數值,最好就是乙個隨機值,當函式呼叫的時候,編譯器自動插入(編譯的時候編譯器知道何時進行函式呼叫,比如 call)乙個cookie,這個cookie在程式啟動的時候被初始化為隨機值(如果不是隨機值,我們考慮最極端的情況,比如就是1,那麼攻擊者就知道 把kookie的位置覆蓋為1就不會導致cookie檢查失敗了),當程式返回的時候系統會檢查堆疊的cookie和程式的cookie是否一致,如果不 一致,那麼就報錯。

以上的方式很不錯嗎?考慮一下以下的問題:如果攻擊者知道程式的cookie所存放的位置,那麼他就會知道cookie的值,於是他就知道應該將堆疊中 cookie位置的值覆蓋成什麼,即使你將cookie的存放位置設為不可讀也不好,因為攻擊者總能通過各種淫亂的手段達到目的,試問你是保護 cookie函式保護函式返回值?另外乙個問題:當cookie檢查失敗,該怎麼辦?就算cookie檢查失敗,緩衝區確實溢位,但是此時作業系統核心並 不知道發生的一切(前提是只要別溢位到核心空間),於是想讓系統在檢查失敗時就自動陷入核心是不可能的,一切必須手動進行,在使用者空間進行,如果想讓核心幫忙處理,就要手動進行陷入(x86種int指令),如果不需要核心處理就在使用者空間了斷,不管哪種方式,都要在檢查失敗後跳到一段**,我們姑且把它叫做異常處理**,那麼問題來了,如果攻擊者將這段異常處理**攻擊了怎麼辦,這不成了個怪圈了嗎?是的,這是個怪圈,緩衝區溢位錯誤既然發生,你就誰也別 怪,錯就錯在你的**寫的不嚴密有漏洞,指望緩衝區溢位檢查機制無論怎樣結果都是不可信的,記住,計算機系統中只有一種可信的軟體,就是作業系統核心(存在核心的前提下,當然不包括裸奔的微控制器),而使用者空間的緩衝區溢位又沒有嚴重到核心必須接管的地步(它可沒有缺頁異常嚴重),既然使用者空間的任何機制都 不可信,那麼你還指望所謂嚴密的緩衝區溢位檢查機制嗎?

對於cookie的保護,我倒是有個想法,但是還沒有實現,先說說。就是不再使用每個程式乙個的cookie,而是在函式呼叫的時候通過函式名,引數,參 數個數等資訊通過乙個單向的簽名演算法生成乙個cookie,等函式返回的時候,再通過上述資訊通過同乙個演算法生成cookie,然後比較兩個 cookie,如果相等,放行,不相等,節哀...對於異常處理的保護,根本就沒有什麼辦法,唯一的辦法就是書寫安全無漏洞的**。

下面談談第二種棧保護機制,就是使棧不可執行,實際上在x86上有兩種實現方式,基於段的實現和基於頁的實現。這種保護僅僅對於防止攻擊**在堆疊上的攻擊方式有效,而對於堆溢位攻擊則一籌莫展。

在linux2.4核心中,並沒與在發布核心實現棧的不可執行,棧的不可執行是通過補丁實現的,我們來看乙個簡單的實現,它是基於段的:linux使用平 坦的段,就是不管**段還是資料段都使用0作為起始位址,4g作為界限,這樣的話,堆疊段其實是資料,資料段和**段都是可以執行的,這個不可執行棧的補丁就是將**段縮減,如何縮減呢?在x86機器上,棧是向下伸展的,對於linux,棧低就是0xc0000000,然後向低位址伸展,而且linux的 棧可以在執行中按需通過缺頁中斷動態增加大小,如果限制死linux堆疊的大小,比如256m(夠大了),那麼就可以把**段縮減到以0為起始位址,界限為2.9g多,那麼一旦執行棧裡的資料,便會產生通用保護異常,這種方式具體就是重設user_cs的值,但是2.4的核心的訊號處理機制中,在訊號處理 函式返回的時候需要呼叫sigreturn,2.4核心的setup_frame就是在棧上放置int 0x80執行碼來進入sys_sigreturn的,而棧在補丁的作用下已經不可執行,那麼訊號返回的時候就會有通用保護異常發生,於是為了訊號處理可以正常進行,通用保護異常處理中必須過濾訊號處理的棧執行,這種方式相當笨拙,起碼我是這樣認為的,段機制既然已經是乙個闌尾,為何還要在那上面大做文章 呢?於是2.6核心的基於頁的棧不可執行保護給人展示了一種更好的方式。

程序位址空間是由vma組成的,而棧也是位址空間的一部分,實際上它就是乙個vma,這個vma可以按需通過缺頁異常動態增長,如果將這個vma的標誌設 置為不可執行(setup_arg_pages),那麼這個標誌在缺頁後分配頁面的時候將直接體現在頁表項的可執行位上(do_page_fault) ,而任何資料(包括**和資料)的訪問最終都將通過頁表項進行,於是我們只需要在頁表項上這麼一卡,棧自然就不可執行了,這樣,通過vma的標誌就搞定了 這一切,通用保護異常處理也就不需要過濾任何情況了。

程序間通訊方式總結(windows 和linux)

windows程序間同步方式有 1.互斥量 mutex 2.訊號量 semaphore 3.事件 event 4.臨界區 critical section 5.互鎖函式 臨界區和互鎖函式沒有相應的核心物件因而不能跨程序 linux程序同步方式有 互斥量 讀寫鎖 條件變數 linux核心同步方法 原子...

程序間通訊方式總結(windows 和linux)

一般我們寫的程式都是以單個程序的方式來執行的,比較少涉及到多程序。特別是在windows下,因為windows是按照執行緒來分配cpu時間片的,執行緒是最小的排程單位,所以在windows下更多的用到多執行緒,在同乙個程序裡建立多個執行緒來執行不同的任務,達到充分利用cpu的目的。執行緒之間可以共享...

Canary保護機制(棧保護)的開啟與關閉

這個選項表示棧保護功能有沒有開啟。棧溢位保護是一種緩衝區溢位攻擊緩解手段,當函式存在緩衝區溢位攻擊漏洞時,攻擊者可以覆蓋棧上的返回位址來讓shellcode能夠得到執行。當啟用棧保護後,函式開始執行的時候會先往棧裡插入cookie資訊,當函式真正返回的時候會驗證cookie資訊是否合法,如果不合法就...