棧中的守護天使--gs,亦稱作stack canary / cookie,從vs2003起開始啟用(也就說,gs機制是由編譯器決定的,跟作業系統無關),是堆疊溢位中最令人頭疼的一道關卡
gs機制分三個步驟:計算隨機種子 --> canary寫入棧幀 --> gs校驗
[1]程式啟動時,讀取.data的第乙個dword作為基數,然後和各種元素(時間戳,程序id,執行緒id,計數器等等)進行xor加密
[2]然後將加密後的種子再次寫入.data的第乙個dword
[3]函式在執行前,把加密後的種子取出,與當前esp進行異或計算,結果存入ebp的前面
[4函式主體正常執行。
[5]函式返回前(retn前一點),把cookie取出與esp異或計算後,呼叫__security_check_cookie函式進行檢查,與.data節裡的種子進行比較,
如果校驗通過,則返回原函式繼續執行;如果校驗失敗,則程式終止。
然而,估計大家也發現了,為何buff和cookie之間還有些空隙?其實......在舊版本的編譯器裡,區域性變數是隨機擺放的(指標,int,字串位置隨機),
所以這裡就還存在一絲安全隱患->_->那就是buff可能在不壓過cookie的情況下覆蓋一些區域性變數,
所以,後期的編譯器就推出了--變數重排技術(vs2005之後的優化編譯選項)
在編譯時根據區域性變數的型別對變數在棧幀中的位置進行調整,將字串變數移動到
棧幀的高位址。這樣可以防止該字串溢位時破壞其他的區域性變數。
同時還會將指標引數和字串引數複製到記憶體中低位址(如圖中的arg),防止函式引數被破壞
繞過方法一:攻擊s.e.h
gs 機制並沒有對 s.e.h 提供保護,即異常處理函式的位址在cookie之前。
我們首先通過超長字串覆蓋掉異常處理函式指標,然後想辦法觸發乙個異常,程式就會轉入異常處理,由於異常處理函式指標已經被我們覆蓋,
那麼我們就可以通過劫持s.e.h來控制程式的後續流程......
這種繞過技術雖然簡單且有效,但隨後推出的safeseh以及sehop,都會將此方法**
繞過方法二:leak canary
可以通過printf(格式化字串漏洞)洩露,但要注意,cookie一般從00開始,而printf會00截斷,
所以用此方法時要越過前兩位
繞過方法三:overwrite cnary
即同時覆蓋棧中的cookie及.data
中的cookie,額......這種思路是好,但實際上幾乎不可能,因為cookie存在
tls(即執行緒區域性儲存)中,而tls位址是被隨機化,故除非一些特定場景,很難實現
綜上所述,gs機制繞過是艱難的,必須結合實際場景運用不同的方法,其中第二種方法用的比較多,
大家可以多多研究,之後有新思路推出時,我再及時更新^_^
祝大家生活愉快~~
白話C 之第三話
本節內容主要是對陣列與集合的闡述.1.一維陣列的定義 格式 型別 變數名 new 型別 元素個數 比如 string str new string 5 注意 當在new 型別的時候,如果在後邊初始化其值時,可以不定義元素的個數。但是如果不為其初始化值的話,那麼一定要書寫元素的個數如 new stri...
第三章 堆疊
1.基礎知識 堆疊可以實現很多的應用,遞迴的問題轉化成非遞迴形式,在本質上也是堆疊的問題.它是一種 filo 操作的資料結構,一般也有兩種儲存方式 陣列跟鍊錶實現形式,這裡我給出了鍊錶形式的堆疊模板,裡面包括了基本的堆疊所有的操作,還有兩個比較著名的應用例子,時間倉促,精力比較有限,關於迷宮老鼠還沒...
Java第三課 堆疊
1.堆與棧 物件生存空間堆 堆 方法呼叫及變數的生存空間 棧 呼叫某一方法時,該方法會被放在呼叫棧的棧頂 duck d new duck 24 物件引用變數d在棧上,物件duck始終在堆上 例項變數 宣告在類中方法之外的地方 堆上,存在於物件所屬的堆空間上 區域性變數 宣告在方法或方法的引數上 棧上...