資源描述:
《防止緩沖區(qū)溢出杜絕如今最常見(jiàn)的程序缺陷方案》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在行業(yè)資料-天天文庫(kù)。
1、防止緩沖區(qū)溢出杜絕如今最常見(jiàn)的程序缺陷方案什么是緩沖區(qū)溢出? 緩沖區(qū)以前可能被定義為“包含相同數(shù)據(jù)類型的實(shí)例的一個(gè)連續(xù)計(jì)算機(jī)內(nèi)存塊”。在C和C++中,緩沖區(qū)通常是使用數(shù)組和諸如malloc()和new這樣的內(nèi)存分配例程來(lái)實(shí)現(xiàn)的。極其常見(jiàn)的緩沖區(qū)種類是簡(jiǎn)單的字符數(shù)組。溢出是指數(shù)據(jù)被添加到分配給該緩沖區(qū)的內(nèi)存塊之外?! ∪绻粽吣軌?qū)е戮彌_區(qū)溢出,那么它就能控制程序中的其他值。雖然存在許多利用緩沖區(qū)溢出的方法,不過(guò)最常見(jiàn)的方法還是“stack-smashing”攻擊。EliasLevy(又名為AlephOne)的一篇經(jīng)典文章“SmashingtheStackfor
2、FunandProfit”解釋了stack-smashing攻擊,EliasLevy是Bugtraq郵件列表(請(qǐng)參閱參考資料以獲得相關(guān)鏈接)的前任主持人?! 榱死斫鈙tack-smashing攻擊(或其他任何緩沖區(qū)攻擊)是如何進(jìn)行的,您需要了解一些關(guān)于計(jì)算機(jī)在機(jī)器語(yǔ)言級(jí)實(shí)際如何工作的知識(shí)。在類UNIX系統(tǒng)上,每個(gè)進(jìn)程都可以劃分為三個(gè)主要區(qū)域:文本、數(shù)據(jù)和堆棧。文本區(qū)域包括代碼和只讀數(shù)據(jù),通常不能對(duì)它執(zhí)行寫入操作。數(shù)據(jù)區(qū)域同時(shí)包括靜態(tài)分配的內(nèi)存(比如全局和靜態(tài)數(shù)據(jù))和動(dòng)態(tài)分配的內(nèi)存(通常稱為堆)。堆棧區(qū)域用于允許函數(shù)/方法調(diào)用;它用于記錄函數(shù)完成之后的返回位置,存
3、儲(chǔ)函數(shù)中使用的本地變量,向函數(shù)傳遞參數(shù),以及從函數(shù)返回值。每當(dāng)調(diào)用一個(gè)函數(shù),就會(huì)使用一個(gè)新的堆棧幀來(lái)支持該調(diào)用。了解這些之后,讓我們來(lái)考察一個(gè)簡(jiǎn)單的程序?! ∏鍐?.一個(gè)簡(jiǎn)單的程序 voidfunction1(inta,intb,intc){ charbuffer1[5]; gets(buffer1);/*DON'TDOTHIS*/ } voidmain(){ function(1,2,3); } 假設(shè)使用gcc來(lái)編譯清單1中的簡(jiǎn)單程序,在X86上的Linux中運(yùn)行,并且緊跟在對(duì)gets()的調(diào)用之后中止。此時(shí)的內(nèi)存內(nèi)容看起來(lái)像什
4、么樣子呢?答案是它看起來(lái)類似圖1,其中展示了從左邊的低位地址到右邊的高位地址排序的內(nèi)存布局?! ?nèi)存的底部 內(nèi)存的頂部 buffer1 sfp ret a b c <---增長(zhǎng)--- [] [] [] [] [] [] ... 堆棧的頂部 堆棧的底部 許多計(jì)算機(jī)處理器,包括所有x86處理器,都支持從高位地址向低位地址“倒”增長(zhǎng)堆棧。因此,每當(dāng)一個(gè)函數(shù)調(diào)用另一個(gè)函數(shù),更多的數(shù)據(jù)將被添加到左邊(低位地址),直至系統(tǒng)的堆棧空間耗盡。在這個(gè)例子中,當(dāng)main()調(diào)用function1()時(shí),它將c的值壓入堆棧,然后壓入b的值,最后壓入a的值
5、。之后它壓入return(ret)值,這個(gè)值在function1()完成時(shí)告訴function1()返回到main()中的何處。它還把所謂的“已保存的幀指針(savedframepointer,sfp)”記錄到堆棧上;這并不是必須保存的內(nèi)容,此處我們不需要理解它。在任何情況下,function1()在啟動(dòng)以后,它會(huì)為buffer1()預(yù)留空間,這在圖1中顯示為具有一個(gè)低地址位置?! ‖F(xiàn)在假設(shè)攻擊者發(fā)送了超過(guò)buffer1()所能處理的數(shù)據(jù)。接下來(lái)會(huì)發(fā)生什么情況呢?當(dāng)然,C和C++程序員不會(huì)自動(dòng)檢查這個(gè)問(wèn)題,因此除非程序員明確地阻止它,否則下一個(gè)值將進(jìn)入內(nèi)存中的“下
6、一個(gè)”位置。那意味著攻擊者能夠改寫sfp(即已保存的幀指針),然后改寫ret(返回地址)。之后,當(dāng)function1()完成時(shí),它將“返回”——不過(guò)不是返回到main(),而是返回到攻擊者想要運(yùn)行的任何代碼?! ⊥ǔ9粽邥?huì)使用它想要運(yùn)行的惡意代碼來(lái)使緩沖區(qū)溢出,然后攻擊者會(huì)更改返回值以指向它們已發(fā)送的惡意代碼。這意味著攻擊者本質(zhì)上能夠在一個(gè)操作中完成整個(gè)攻擊!AlephOn的文章(請(qǐng)參閱參考資料)詳細(xì)介紹了這樣的攻擊代碼是如何創(chuàng)建的。例如,將一個(gè)ASCII0字符壓入緩沖區(qū)通常是很困難的,而該文介紹了攻擊者一般如何能夠解決這個(gè)問(wèn)題?! 〕藄mashing-s
7、tack和更改返回地址外,還存在利用緩沖區(qū)溢出缺陷的其他途徑。與改寫返回地址不同,攻擊者可以smashing-stack(使堆棧上的緩沖區(qū)溢出),然后改寫局部變量以利用緩沖區(qū)溢出缺陷。緩沖區(qū)根本就不必在堆棧上——它可以是堆中動(dòng)態(tài)分配的內(nèi)存(也稱為“malloc”或“new”區(qū)域),或者在某些靜態(tài)分配的內(nèi)存中(比如“global”或“static”內(nèi)存)?;旧?,如果攻擊者能夠溢出緩沖區(qū)的邊界,麻煩或許就會(huì)找上你了。然而,最危險(xiǎn)的緩沖區(qū)溢出攻擊就是stack-smashing攻擊,因?yàn)槿绻绦驅(qū)粽吆艽嗳酰粽攉@得整個(gè)機(jī)器的控制權(quán)就特別容易。