專利名稱:一種防止緩沖區(qū)溢出攻擊的動(dòng)態(tài)堆棧內(nèi)存管理方法
技術(shù)領(lǐng)域:
本發(fā)明涉及動(dòng)態(tài)堆棧內(nèi)存管理方法,防止緩沖區(qū)溢出是一種常見(jiàn)的對(duì)計(jì)算機(jī)系統(tǒng)進(jìn)行攻擊的方法。本發(fā)明提出了一種動(dòng)態(tài)堆棧內(nèi)存管理方法,它可以有效地阻止緩沖區(qū)溢出攻擊。
二.技術(shù)背景緩沖區(qū)是程序運(yùn)行時(shí)候在計(jì)算機(jī)內(nèi)存中存放數(shù)據(jù)的地方。當(dāng)程序試圖將一段數(shù)據(jù)寫到某一段內(nèi)存緩沖區(qū)中時(shí),如果數(shù)據(jù)的長(zhǎng)度超過(guò)緩沖區(qū)的長(zhǎng)度,就會(huì)發(fā)生緩沖區(qū)溢出。攻擊者可以利用這一弱點(diǎn)對(duì)計(jì)算機(jī)進(jìn)行攻擊(參見(jiàn)[1]E.Spafford.The Internet Worm ProgramAnalysis.Computer Communication Review,January 1989)。攻擊者把一個(gè)超過(guò)緩沖區(qū)長(zhǎng)度的字符串寫入到緩沖區(qū)。由于寫入的超長(zhǎng)的字符串覆蓋了相鄰的存儲(chǔ)單元,常常會(huì)導(dǎo)致兩種結(jié)果。一是引起程序運(yùn)行失敗,嚴(yán)重的可導(dǎo)致系統(tǒng)崩潰;另外一種結(jié)果就是利用這種漏洞執(zhí)行惡意指令。如果被攻擊的程序在超級(jí)用戶權(quán)限上執(zhí)行,那么攻擊者也可以獲得系統(tǒng)超級(jí)用戶的權(quán)限。結(jié)果是一個(gè)匿名的因特網(wǎng)攻擊者往往有機(jī)會(huì)獲得一臺(tái)主機(jī)的部分或全部的控制權(quán)。緩沖區(qū)溢出攻擊已經(jīng)成為操作系統(tǒng)、數(shù)據(jù)庫(kù),萬(wàn)維網(wǎng)服務(wù)器等大型應(yīng)用程序最普遍的漏洞之一。
現(xiàn)有的解決辦法針對(duì)上述的問(wèn)題,目前為止已經(jīng)存在多種解決辦法。和本發(fā)明較為接近的主要有兩種技術(shù)。一是美國(guó)IMMUNIX公司的StackGuard技術(shù)(參見(jiàn)[2]Crispin Cowan,Steve Beattie,RyarFinnin Day,Calton Pu,Perry Wagle,and Eric Walthinsen,Protecting systems from stacksmashing attacks with StackGuard.Linux Expohttp//www.cse.ogi.edu//~crispin/,May 1999),另一個(gè)是日本IBM研究院的Proplice技術(shù)(參見(jiàn)[3]Hiroaki Etoh,Gcc extension for protectingapplications from stack smashing attacks,http//www.trl.ibm.com/projects/security/ssp,June2000)。這兩種技術(shù)都是通過(guò)修改C語(yǔ)言的編譯器,在生成的目標(biāo)代碼中附加上緩沖區(qū)溢出檢測(cè)功能。其優(yōu)點(diǎn)是在原來(lái)的程序在不需要任何的改動(dòng)。拿StackGuard技術(shù)來(lái)說(shuō),為了探測(cè)是否有攻擊者對(duì)返回地址進(jìn)行攻擊,當(dāng)一個(gè)新的函數(shù)被調(diào)用時(shí),它將一個(gè)″canary″值(一個(gè)單字)放到返回地址的前面。如果當(dāng)函數(shù)返回時(shí),發(fā)現(xiàn)這個(gè)canary的值被改變了,就證明可能有人正在試圖進(jìn)行緩沖區(qū)溢出攻擊。程序會(huì)立刻響應(yīng),并將被攻擊的進(jìn)程的相關(guān)信息記錄下來(lái),然后終止被攻擊的進(jìn)程。日本IBM研究院的Proplice技術(shù)在借鑒了stackguard技術(shù)的基礎(chǔ)上,重新安排了局部變量的順序。這樣當(dāng)字符串變量被寫入超長(zhǎng)的字符串時(shí),別的類型的局部變量的值不會(huì)遭到破壞,從而把攻擊的危害減少到最小程度。
但是通過(guò)分析源程序或分析使用這兩種技術(shù)編譯后的目標(biāo)程序,攻擊者可以確定運(yùn)行時(shí)堆棧具體結(jié)構(gòu)。即攻擊者通過(guò)分析代碼可以確切獲得返回地址和分配的局部變量之間的相對(duì)偏移。攻擊者可以根據(jù)運(yùn)行時(shí)候的堆棧結(jié)構(gòu)來(lái)改變返回地址的值,但同時(shí)并不改變″canary″的值(參見(jiàn)[4]Bulba and Kil3r.Bypassing StackGuard and StackShield,Phrack Magazine56http//www.phrack.org/phrack/56/p56-0x05,May 2000)。從而繞過(guò)stackguard技術(shù)和Proplice技術(shù)對(duì)返回地址的保護(hù),有效地實(shí)行緩沖區(qū)攻擊。
三.
發(fā)明內(nèi)容
本發(fā)明為了防止攻擊者通過(guò)分析原程序或者分析編譯后的目標(biāo)程序,確定運(yùn)行時(shí)堆棧結(jié)構(gòu),對(duì)計(jì)算機(jī)系統(tǒng)實(shí)行攻擊,提出了一種新的堆棧內(nèi)存管理方法。從而使攻擊者無(wú)法準(zhǔn)確確定返回地址的位置,無(wú)法通過(guò)改寫返回地址來(lái)進(jìn)行緩沖區(qū)溢出攻擊。
本發(fā)明提出的動(dòng)態(tài)內(nèi)存管理方法是這樣的在計(jì)算機(jī)程序執(zhí)行時(shí),每次子過(guò)程被調(diào)用并分配當(dāng)前過(guò)程的堆??臻g時(shí),象正常情況一樣保存調(diào)用參數(shù),返回地址。但是保存幀指針和分配局部變量的時(shí)候,在幀指針和局部變量起始地址之間分配一段額外內(nèi)存空間或者在返回地址和幀指針之間額外分配一段額外內(nèi)存空間。此額外空間的大小在程序執(zhí)行的時(shí)候隨機(jī)決定。這樣堆棧內(nèi)存中返回地址和局部變量的相對(duì)位置無(wú)法通過(guò)分析源程序或編譯后的目標(biāo)程序得到,可以有效地防止利用堆棧緩沖區(qū)溢出來(lái)對(duì)計(jì)算機(jī)系統(tǒng)進(jìn)行攻擊。
在分配局部參數(shù)內(nèi)存空間時(shí),在幀指針和局部變量起始地址之間多分配一段內(nèi)存空間或者在返回地址和幀指針之間多分配一段內(nèi)存空間。這樣局部變量和返回地址之間的相對(duì)偏移就增加了一段額外的長(zhǎng)度;這段額外長(zhǎng)度的具體大小在每次運(yùn)行開始時(shí)通過(guò)產(chǎn)生一個(gè)隨機(jī)數(shù)獲得。
本發(fā)明方法中額外長(zhǎng)度的內(nèi)存緩沖區(qū)中也可以放入類似StackGuard技術(shù)中的″canary″值,從而檢測(cè)出當(dāng)前執(zhí)行程序是否正在被攻擊。
如圖1所示,本技術(shù)在分配局部參數(shù)的內(nèi)存空間的時(shí)候,會(huì)在基址寄存器和局部變量之間多分配一段內(nèi)存空間。這樣局部變量和返回地址之間的相對(duì)偏移就增加了一段額外的長(zhǎng)度。為了保證攻擊者無(wú)法通過(guò)分析原程序或編譯后的目標(biāo)程序來(lái)推測(cè)出這段額外長(zhǎng)度,本技術(shù)要求這段額外長(zhǎng)度在靜態(tài)分析編譯后的目標(biāo)代碼時(shí)是未知的。額外長(zhǎng)度的具體大小在每次運(yùn)行的時(shí)候通過(guò)產(chǎn)生一個(gè)隨機(jī)數(shù)獲得。因此即使是同一個(gè)程序,每次執(zhí)行的時(shí)候這段額外長(zhǎng)度的值都會(huì)不一樣。
由于攻擊者無(wú)法準(zhǔn)確預(yù)測(cè)出局部變量和返回地址間的相對(duì)偏移,無(wú)法準(zhǔn)確將返回地址的值改向自己的惡意攻擊程序。從而很難實(shí)施有效地緩沖區(qū)溢出攻擊。
本發(fā)明的額外長(zhǎng)度由隨機(jī)函數(shù)發(fā)生器子程序來(lái)實(shí)現(xiàn)。
利用本發(fā)明編譯完成的計(jì)算機(jī)目標(biāo)程序執(zhí)行時(shí)具有上述特征。相應(yīng)的編譯器能產(chǎn)生上述特征的目標(biāo)程序。
本發(fā)明的優(yōu)點(diǎn)本發(fā)明提出的一種新的對(duì)返回地址進(jìn)行保護(hù)的方法,它可以同時(shí)檢測(cè)出當(dāng)前執(zhí)行程序是否正在被攻擊并可以防止被攻擊。它的特點(diǎn)是無(wú)法通過(guò)靜態(tài)地分析源程序或目標(biāo)程序來(lái)推測(cè)獲得返回地址和分配的局部變量之間的相對(duì)偏移。由于產(chǎn)生的額外的長(zhǎng)度是隨機(jī)的,即使使用動(dòng)態(tài)跟蹤工具跟蹤執(zhí)行目標(biāo)程序,也無(wú)法確定下次執(zhí)行時(shí)返回地址和分配的局部變量之間的相對(duì)偏移。攻擊者由于無(wú)法事先知道返回地址的準(zhǔn)確位置,無(wú)法修改返回地址,從而有效地防止了攻擊者利用堆棧緩沖區(qū)溢出進(jìn)行攻擊。
四
圖1傳統(tǒng)程序運(yùn)行時(shí)堆棧內(nèi)存結(jié)構(gòu)和使用本技術(shù)編譯后的程序運(yùn)行時(shí)堆棧內(nèi)存結(jié)構(gòu)(局部變量和返回地址之間增加了一段隨即的長(zhǎng)度)的示意2普通的程序執(zhí)行時(shí)的堆棧內(nèi)存結(jié)構(gòu)圖3使用緩沖區(qū)攻擊后的程序執(zhí)行時(shí)的堆棧內(nèi)存結(jié)構(gòu)圖4使用本發(fā)明后堆棧調(diào)用時(shí)的結(jié)構(gòu)圖5一個(gè)C程序在啟動(dòng)保護(hù)功能前和啟動(dòng)保護(hù)功能后編譯執(zhí)行的結(jié)果如圖5所示一個(gè)C程序在啟動(dòng)保護(hù)功能前和啟動(dòng)保護(hù)功能后編譯執(zhí)行后的結(jié)果。我們使用的編譯器是公開原碼的LINUX GCC。為了觀察方便,在每次進(jìn)入和退出子過(guò)程時(shí)打印出分配和釋放的額外動(dòng)態(tài)空間。在啟動(dòng)堆棧保護(hù)后,在程序每次啟動(dòng)執(zhí)行時(shí)產(chǎn)生一個(gè)隨機(jī)數(shù)。隨機(jī)數(shù)的值每次執(zhí)行時(shí)都不一樣大。每次進(jìn)入子過(guò)程時(shí)分配這段額外空間,而退出子過(guò)程時(shí)釋放這段額外空間。當(dāng)然在實(shí)際應(yīng)用中額外空間的分配和釋放都是在后臺(tái)進(jìn)行的,沒(méi)有必要顯示出來(lái)。
五具體實(shí)施例方式
上面是本發(fā)明的基本原理,可以有多種實(shí)現(xiàn)方式。比如可以使用特別的內(nèi)存設(shè)備(包括軟件設(shè)備和硬件設(shè)備)來(lái)實(shí)現(xiàn)。也可以使用特別的計(jì)算機(jī)系統(tǒng)來(lái)實(shí)現(xiàn)。也可以改寫編譯器來(lái)生成具有上述功能的目標(biāo)程序。總之本原理精神范圍內(nèi)的各種各樣的實(shí)現(xiàn)方式都應(yīng)該包括進(jìn)來(lái)。下面舉出一個(gè)示例來(lái)具體說(shuō)明使用本方法的程序的執(zhí)行過(guò)程。
I.正常程序的執(zhí)行過(guò)程我們以圖2為例來(lái)說(shuō)明正常的程序執(zhí)行流程。我們使用函數(shù)foo被函數(shù)bar調(diào)用的例子來(lái)加以說(shuō)明。假設(shè)函數(shù)被調(diào)用時(shí)堆棧幀從高地址向低地址方向增長(zhǎng)。圖2中函數(shù)foo把環(huán)境變量ENV_STR的內(nèi)容使用C語(yǔ)言的庫(kù)函數(shù)getenv得到后,使用C語(yǔ)言的庫(kù)函數(shù)strcpy拷貝到大小為128字節(jié)的字符串?dāng)?shù)組buffer中。foo被調(diào)用后,為了保存foo的動(dòng)態(tài)執(zhí)行環(huán)境,下面的信息被保存在堆棧中。
我們下面使用SP來(lái)代表堆棧指針,使用FP來(lái)代表幀指針,使用RA來(lái)代表返回地址。
●函數(shù)foo被調(diào)用前函數(shù)foo被調(diào)用前,堆棧指針(SP)指向堆棧幀的最底部,幀指針(FP)指向bar的前一堆棧幀的幀指針變量(FP)。從幀指針(FP)的下一個(gè)地址到堆棧指針(SP)之間存放了函數(shù)bar的局部變量。
●函數(shù)foo被調(diào)用后首先在堆棧中保存了foo的調(diào)用參數(shù),然后保存了返回bar的返回地址。然后保存了前一幀指針(FP)。最后分配了foo的局部參數(shù)。此時(shí)堆棧指針(SP)指向最下位。函數(shù)foo便可以開始執(zhí)行了。
●函數(shù)foo執(zhí)行后函數(shù)foo執(zhí)行終了后,按照上記的相反的順序,堆棧指針(SP)和幀指針(FP)也回到了函數(shù)foo被調(diào)用前的值。然后返回到foo的返回地址RA指向的程序,繼續(xù)執(zhí)行bar部分的程序。
II.典型的緩沖區(qū)溢出攻擊方式函數(shù)foo的堆棧構(gòu)造很容易從foo的源程序和編譯后的目標(biāo)程序中分析出來(lái)。然后按照分析的結(jié)果來(lái)對(duì)執(zhí)行的程序進(jìn)行攻擊。我們以圖3來(lái)對(duì)攻擊過(guò)程進(jìn)行說(shuō)明。假設(shè)攻擊者已經(jīng)改寫了環(huán)境變量,在字符串拷貝的時(shí)候,返回地址被ADDR_X給覆蓋了,而局部變量的內(nèi)容被惡意攻擊代碼覆蓋了。并且ADDR_X指向這段攻擊代碼。比如函數(shù)foo被調(diào)用后,會(huì)執(zhí)行strcpy。由于strcpy一般不會(huì)檢查輸入字符串的大小,這樣從局部變量一直到RA返回地址部分都被改寫。函數(shù)foo執(zhí)行結(jié)束后,沒(méi)有返回到bar程序中繼續(xù)執(zhí)行,而是返回到了那段惡意攻擊代碼處。這樣惡意攻擊程序就掌握了主動(dòng)權(quán)并開始執(zhí)行。而且由于前幀指針也被改寫了,返回到bar時(shí)正確的幀指針也無(wú)法正確得到。這樣可能會(huì)發(fā)生不可預(yù)測(cè)的執(zhí)行錯(cuò)誤。
III.利用動(dòng)態(tài)堆棧內(nèi)存管理技術(shù)來(lái)防止緩沖區(qū)溢出攻擊我們結(jié)合圖4以函數(shù)foo被調(diào)用執(zhí)行時(shí)候的堆棧構(gòu)造過(guò)程為例來(lái)說(shuō)明。首先目標(biāo)程序象正常情況一樣保存了調(diào)用參數(shù),返回地址和幀指針,但是在分配局部變量的時(shí)候,本方法會(huì)動(dòng)
III.利用動(dòng)態(tài)堆棧內(nèi)存管理技術(shù)來(lái)防止緩沖區(qū)溢出攻擊我們結(jié)合圖4以函數(shù)foo被調(diào)用執(zhí)行時(shí)候的堆棧構(gòu)造過(guò)程為例來(lái)說(shuō)明。首先目標(biāo)程序象正常情況一樣保存了調(diào)用參數(shù),返回地址和幀指針,但是在分配局部變量的時(shí)候,本方法會(huì)動(dòng)態(tài)地分配比正常的局部變量需要的空間更大的內(nèi)存空間。比如在圖4中分配大小為alpha空間。alpha的具體大小在運(yùn)行的時(shí)候隨機(jī)動(dòng)態(tài)地決定。(這個(gè)大小為alpha的緩沖區(qū)也可以被用做它用)。
在增加alpha大小的緩沖區(qū)后,幀指針的值可以指向圖中虛線,也可以指向圖中實(shí)線的位置。程序?qū)㈦S之使用不同的辦法來(lái)查找調(diào)用參數(shù)和局部變量。使用本發(fā)明的堆棧內(nèi)存管理方法,即使是同一段程序,每次執(zhí)行的時(shí)候局部變量部分分配的額外空間大小可能都不一樣。通過(guò)分析源程序和編譯后的程序無(wú)法檢測(cè)出返回地址的準(zhǔn)確位置。因此很難有效地實(shí)施堆棧攻擊。
可以使用隨機(jī)函數(shù)發(fā)生器來(lái)產(chǎn)生隨機(jī)大小的額外緩沖區(qū)長(zhǎng)度一個(gè)具體的隨機(jī)函數(shù)發(fā)生器的例子如下所示。
<pre listing-type="program-listing"><![CDATA[ static int randval=0; RandomGenerator() { if(randval==0) { srand(time(0)); randval=rand()%100+10; } return randval; }]]></pre>
權(quán)利要求
1.一種新型的動(dòng)態(tài)堆棧內(nèi)存管理方法。其特征是在計(jì)算機(jī)程序執(zhí)行時(shí),每次子過(guò)程被調(diào)用并分配當(dāng)前過(guò)程的堆??臻g時(shí),象正常情況一樣保存調(diào)用參數(shù),返回地址。但是保存幀指針和分配局部變量的時(shí)候,在幀指針和局部變量起始地址之間分配一段額外內(nèi)存空間或者在返回地址和幀指針之間額外分配一段額外內(nèi)存空間。此額外空間的大小在程序執(zhí)行的時(shí)候隨機(jī)決定。這樣堆棧內(nèi)存中返回地址和局部變量的相對(duì)位置無(wú)法通過(guò)分析源程序或編譯后的目標(biāo)程序得到,可以有效地防止利用堆棧緩沖區(qū)溢出來(lái)對(duì)計(jì)算機(jī)系統(tǒng)進(jìn)行攻擊。
2.由權(quán)利要求1所述的一種新型的動(dòng)態(tài)堆棧內(nèi)存管理方法,其特征是在分配局部參數(shù)內(nèi)存空間時(shí),在幀指針和局部變量起始地址之間多分配一段內(nèi)存空間或者在返回地址和幀指針之間多分配一段內(nèi)存空間。這樣局部變量和返回地址之間的相對(duì)偏移就增加了一段額外的長(zhǎng)度;這段額外長(zhǎng)度的具體大小在每次運(yùn)行的時(shí)候通過(guò)產(chǎn)生一個(gè)隨機(jī)數(shù)獲得。
3.由權(quán)利要求1所述的一種新型的動(dòng)態(tài)堆棧內(nèi)存管理方法,其特征是其中額外長(zhǎng)度的內(nèi)存緩沖區(qū)中也可以放入類似StackGuard技術(shù)中的″canary″值,從而檢測(cè)出當(dāng)前執(zhí)行程序是否正在被攻擊。
4.由權(quán)利要求1所述的一種新型的動(dòng)態(tài)堆棧內(nèi)存管理方法,其特征是權(quán)利要求1中所述的額外長(zhǎng)度由隨機(jī)函數(shù)發(fā)生器子程序來(lái)實(shí)現(xiàn)。
5.由權(quán)利要求1所述的一種新型的動(dòng)態(tài)堆棧內(nèi)存管理方法,其特征是計(jì)算機(jī)目標(biāo)程序執(zhí)行時(shí)具有上述權(quán)利要求1的特征。
6.由權(quán)利要求1所述的一種新型的動(dòng)態(tài)堆棧內(nèi)存管理方法,其特征是相應(yīng)的編譯器能產(chǎn)生權(quán)利要求1的特征的目標(biāo)程序。
全文摘要
本發(fā)明公開了一種防止緩沖區(qū)溢出攻擊的動(dòng)態(tài)堆棧內(nèi)存管理方法。在計(jì)算機(jī)程序執(zhí)行的時(shí)候,由于返回地址和局部變量之間的相對(duì)位置隨機(jī)動(dòng)態(tài)地改變,無(wú)法改寫返回地址,從而可以有效地防止利用緩沖區(qū)溢出來(lái)對(duì)計(jì)算機(jī)系統(tǒng)進(jìn)行攻擊。本發(fā)明包括以下
權(quán)利要求
動(dòng)態(tài)堆棧內(nèi)存管理方法,具有此動(dòng)態(tài)堆棧內(nèi)存管理特征的目標(biāo)程序和能產(chǎn)生這種目標(biāo)程序的編譯器,具有此動(dòng)態(tài)堆棧內(nèi)存管理特征的內(nèi)存設(shè)備(硬件設(shè)備或軟件設(shè)備),具有此動(dòng)態(tài)堆棧內(nèi)存管理特征的計(jì)算機(jī)系統(tǒng)。
文檔編號(hào)G06F1/00GK1564098SQ200410014600
公開日2005年1月12日 申請(qǐng)日期2004年4月9日 優(yōu)先權(quán)日2004年4月9日
發(fā)明者龔如賓, 潘金貴 申請(qǐng)人:南京大學(xué)