官术网_书友最值得收藏!

2.6.5 棧探測儀

棧探測儀(canary)是另一種用來檢測和阻止棧溢出攻擊的機制。探測儀用于保護棧上的返回地址免遭通過內存的連續寫操作(例如,調用strcpy()所導致的結果),而不是執行一般化的邊界檢查。探測儀由一個被寫入被保護棧的節地址前面的“難以插入”或“難以偽造”的值構成。為了進入受保護區域,一個連續的寫操作將需要覆蓋這個值。探測儀在返回地址被保存后立即被初始化,并且在返回地址被訪問之前立即被檢測。例如,探測儀可以由4種不同的終止字符組成(CR、LF、NULL和-1)。例如,這些終止字符可以保護由于越界strcpy()調用所產生的緩沖區溢出,因為攻擊者需要在他的緩沖區中包含一個空字節。探測儀可以保護由于字符串操作所產生的緩沖區溢出,但不能保護由于內存復制操作而造成的緩沖區溢出。“難以偽造”或隨機的探測儀由一個32位的秘密隨機數組成,每次隨著程序執行它都會發生改變。在探測儀確實保密的情況下,這種方式能夠很好地工作。

StackGuard、GCC的棧溢出保護器(Stack-Smashing Protector也被稱為ProPolice),以及微軟的Visual C++ .NET編譯器中作為緩沖區溢出檢測能力的那部分,都實現了探測儀。

棧緩沖區溢出檢測(stack buffer overrun detection)能力在Visual Studio.NET 2002中被引入C/C++編譯器,并已在后續版本更新。/GS編譯器開關指示編譯器添加啟動代碼和函數結尾和開始代碼以生成和檢查被放置在一個函數棧中的一個隨機數。如果這個值被損壞,就調用一個處理程序函數來終止應用程序,從而減少試圖利用緩沖區溢出的shellcode正確執行的機會。

注意Visual C++2005(及更高版本)對棧上的數據重新排序,也使那些數據難以預見地破壞。例子包括:

·把緩沖區移動到比nonbuffers更高的內存。這一步驟可以幫助保護駐留在棧中的函數指針。

·在運行時把指針和緩沖區參數移動到較低的內存,以減輕各種緩沖區溢出攻擊。

Visual C++2010中包括對/GS的增強,它擴展了用來確定何時對一個函數應該啟用/GS以及何時可以安全地將/GS優化掉的啟發式。

當使用Visual C++2005的Service Pack1或更高版本時,若要充分利用增強的/GS啟發式,需要在常用的頭文件中加入以下指令以增加被/GS保護的函數的數量:


#pragma strict_gs_check
(on
)

在Visual C++2010中,確定哪些函數需要/GS保護的規則比它們在編譯器的早期版本中的表現更積極,但strict_gs_check規則比Visual C++2010的規則更積極。即使Visual C++2010達到了很好的平衡,但在面向Internet的產品中應使用strict_gs_check。

要使用Microsoft Visual Studio中的棧緩沖區溢出檢測,你應該遵循下面的要求:

·用最新版本的編譯器編譯代碼。在寫作的時候,這個版本是VC++2010(cl.exe版本16.00)。

·若使用比VC++2010早的VC++版本時,需要在常用的頭文件中添加#pragma string_gs_check(on)。

·若使用VC++2010及更高版本,需要在面向互聯網的產品中添加#pragma string_gs_check(on)。

·使用/GS標志進行編譯。

·與用/GS編譯的庫進行鏈接。

按照目前的實現,探測儀僅用來阻止那些對“通過從棧中的緩沖區溢出來覆寫棧返回地址”的漏洞利用。探測儀無法保護程序免受修改變量、對象指針或函數指針的漏洞利用,也不能阻止發生于任何位置(包括棧段在內)的緩沖區溢出。它們只有在這些緩沖區溢出事件發生后才能檢測到其中某些事件。

不管是終結符探測儀還是隨機探測儀都無法抵御通過直接覆寫返回地址位置字節的漏洞利用[Bulba 2000]。為了解決這些直接訪問的漏洞利用,StackGuard加入隨機異或探測儀(Random XOR canaries)[Wagle 2003],將返回地址與該探測儀進行異或計算。當然,這種方法也只有在探測儀保持秘密的情況下才能有效保護返回地址。總之,探測儀提供了弱的運行時保護。

主站蜘蛛池模板: 桓台县| 广安市| 乐清市| 安陆市| 利辛县| 崇明县| 元氏县| 乌鲁木齐县| 河西区| 凤翔县| 北流市| 荣成市| 杭州市| 越西县| 达拉特旗| 图木舒克市| 沂水县| 都安| 铜川市| 福安市| 鄯善县| 清水河县| 岳阳县| 略阳县| 泽库县| 长子县| 商河县| 鱼台县| 宁陕县| 马公市| 和田县| 普兰县| 当雄县| 察哈| 乐都县| 敦煌市| 湟中县| 资阳市| 遵义县| 越西县| 集贤县|