本發(fā)明涉及rop攻擊防護(hù)技術(shù)領(lǐng)域,具體涉及基于模擬棧和線(xiàn)程注入的一種rop攻擊棧溢出防護(hù)方法。
背景技術(shù):
rop(return-orientedprogramming)是一種基于代碼復(fù)用技術(shù)的新型攻擊,攻擊者供已有的庫(kù)或可執(zhí)行文件中提取指令片段、構(gòu)建惡意代碼。
seh(structuredexceptionhandling)seh("structuredexceptionha-ndling"),即結(jié)構(gòu)化異常處理是(windows)操作系統(tǒng)提供給程序設(shè)計(jì)者的強(qiáng)有力的處理程序錯(cuò)誤或異常的武器。
sehop(sehoverwriteprotection)sehop的全稱(chēng)是structuredexcept-ionhandleroverwriteprotection(結(jié)構(gòu)化異常處理覆蓋保護(hù)),seh攻擊是指通過(guò)棧溢出或者其他漏洞,使用精心構(gòu)造的數(shù)據(jù)覆蓋結(jié)構(gòu)化異常處理鏈表上面的某個(gè)節(jié)點(diǎn)或者多個(gè)節(jié)點(diǎn),從而控制eip(控制程序執(zhí)行流程)。而sehop則是是微軟針對(duì)這種攻擊提出的一種安全防護(hù)方案。
在操作系統(tǒng)和編譯器的保護(hù)下,程序的棧是不可運(yùn)行的、棧的位置是隨機(jī)的,增大了棧溢出攻擊的難度。但如果程序的加載位置是固定的或者程序中存在加載到固定位置的可執(zhí)行代碼,攻擊者就可以利用這些固定位置上的代碼來(lái)實(shí)施他的攻擊,rop惡意代碼不包含任何指令,將自己的惡意代碼隱藏在正常代碼中。因而,它可以繞過(guò)傳統(tǒng)的棧溢出防御技術(shù)。
技術(shù)實(shí)現(xiàn)要素:
針對(duì)上述現(xiàn)有技術(shù),本發(fā)明目的在于提供基于模擬棧和線(xiàn)程注入的一種rop攻擊棧溢出防護(hù)方法,解決了現(xiàn)有技術(shù)由于程序加載位置固定導(dǎo)致不具有指令的rop惡意代碼能夠繞過(guò)棧溢出防護(hù)技術(shù)問(wèn)題,以及解決了在利用模擬棧監(jiān)控目標(biāo)進(jìn)程時(shí)所使用的遠(yuǎn)程線(xiàn)程注入造成目標(biāo)進(jìn)程中出現(xiàn)棧溢出的技術(shù)問(wèn)題。
為達(dá)到上述目的,本發(fā)明采用的技術(shù)方案如下:
本方案主要利用線(xiàn)程注入到目標(biāo)進(jìn)程(所保護(hù)的進(jìn)程),開(kāi)辟一個(gè)模擬??臻g,監(jiān)控模擬目標(biāo)進(jìn)程的指令流程,通過(guò)獲取rop攻擊的call和ret指令間的有效代碼串連,在模擬棧上執(zhí)行,再使用傳統(tǒng)的溢出防護(hù)機(jī)制(如windows的緩沖區(qū)安全監(jiān)測(cè)機(jī)制,gs)檢測(cè)模擬棧上是否存在棧溢出,從而對(duì)rop攻擊棧溢出漏洞的防護(hù)。
基于模擬棧和線(xiàn)程注入的一種rop攻擊棧溢出防護(hù)方法,包括以下步驟:
步驟1、對(duì)目標(biāo)進(jìn)程注入遠(yuǎn)程線(xiàn)程,通過(guò)遠(yuǎn)程線(xiàn)程獲得目標(biāo)進(jìn)程的指令流;
步驟2、通過(guò)目標(biāo)進(jìn)程函數(shù)的調(diào)用特征提取算法將指令流與受信的特征數(shù)據(jù)庫(kù)進(jìn)行比對(duì),獲得存在異常調(diào)用的指令序列;
步驟3、構(gòu)建模擬棧并完成指令序列的拼接,然后在模擬棧中壓入拼接的指令序列和金絲雀值,再利用函數(shù)進(jìn)行模擬棧的指令調(diào)用,在函數(shù)進(jìn)行返回前檢測(cè)指令調(diào)用過(guò)程中金絲雀值,獲得檢測(cè)結(jié)果;
步驟4、根據(jù)檢測(cè)結(jié)果通過(guò)遠(yuǎn)程線(xiàn)程回調(diào)控制目標(biāo)進(jìn)程的啟停,并由檢測(cè)結(jié)果選擇地輸出模擬棧上rop攻擊代碼和溢出點(diǎn)。
上述方法中,所述的步驟1,還包括以下步驟:
步驟1.1、獲得目標(biāo)進(jìn)程的句柄,用遠(yuǎn)程進(jìn)程根據(jù)句柄索引出目標(biāo)進(jìn)程;
步驟1.2、在遠(yuǎn)程進(jìn)程中開(kāi)辟出一段內(nèi)存并根據(jù)目標(biāo)進(jìn)程動(dòng)態(tài)鏈接庫(kù)名稱(chēng)長(zhǎng)度確定內(nèi)存區(qū)間,在該內(nèi)存中寫(xiě)入動(dòng)態(tài)鏈接庫(kù)的名稱(chēng);
步驟1.3、使用庫(kù)加載函數(shù)和遠(yuǎn)程線(xiàn)程創(chuàng)建函數(shù)根據(jù)動(dòng)態(tài)鏈接庫(kù)的名稱(chēng)創(chuàng)建出遠(yuǎn)程線(xiàn)程;
步驟1.4、關(guān)閉目標(biāo)進(jìn)程的句柄,再通過(guò)遠(yuǎn)程線(xiàn)程獲得目標(biāo)進(jìn)程的指令流。
上述方法中,所述的步驟2,其中,對(duì)call指令和ret指令之間的指令流進(jìn)行比對(duì)。
上述方法中,所述的步驟1.3,注入遠(yuǎn)程線(xiàn)程時(shí),結(jié)合遠(yuǎn)程線(xiàn)程創(chuàng)建函數(shù)參數(shù)使用/stack開(kāi)關(guān)指明已提交的堆棧大小值,重載向堆棧所提交地址空間的內(nèi)存數(shù)量,實(shí)質(zhì)并顯著地避免了所使用的遠(yuǎn)程線(xiàn)程注入造成目標(biāo)進(jìn)程中出現(xiàn)棧溢出。
上述方法中,所述的步驟1.3,注入遠(yuǎn)程線(xiàn)程時(shí),將遞歸類(lèi)函數(shù)去除遞歸特征并將局部對(duì)象改為靜態(tài)局部對(duì)象,實(shí)質(zhì)并顯著地避免了所使用的遠(yuǎn)程線(xiàn)程注入造成目標(biāo)進(jìn)程中出現(xiàn)棧溢出。
上述方法中,所述的步驟4,啟停操作,已知目標(biāo)進(jìn)程名或進(jìn)程id的情況下,linux下可以直接通過(guò)調(diào)用system函數(shù)運(yùn)行kill進(jìn)程id命令停止目標(biāo)進(jìn)程,windows下可使用powershell,原理類(lèi)似;已知目標(biāo)進(jìn)程可執(zhí)行文件位置的情況下,linux下可以直接通過(guò)system函數(shù)運(yùn)行./file_position啟動(dòng)目標(biāo)進(jìn)程,windows下可使用powershell,原理類(lèi)似。
與現(xiàn)有技術(shù)相比,本發(fā)明的有益效果:
利用線(xiàn)程注入到目標(biāo)進(jìn)程(要保護(hù)的進(jìn)程),開(kāi)辟一個(gè)模擬??臻g,監(jiān)控模擬目標(biāo)進(jìn)程的指令流程,通過(guò)獲取rop攻擊的call和ret指令間的有效代碼串連,在模擬棧上執(zhí)行,再使用傳統(tǒng)的溢出防護(hù)機(jī)制,從而達(dá)到檢測(cè)rop攻擊的目的,而本領(lǐng)域技術(shù)中,不同程序模塊之間(特別是共享函數(shù)庫(kù)的模塊)數(shù)據(jù)的結(jié)構(gòu)是相同的,在不破壞數(shù)據(jù)情況下不能對(duì)一個(gè)結(jié)構(gòu)中的數(shù)據(jù)進(jìn)行重新排布,緩沖后在一個(gè)結(jié)構(gòu)中的任何數(shù)據(jù)是不可能使用金絲雀值檢測(cè)的方法進(jìn)行防護(hù)的,因此本發(fā)明通過(guò)模擬棧重新排布數(shù)據(jù)并加入金絲雀值,從而克服了現(xiàn)有技術(shù)由于數(shù)據(jù)結(jié)構(gòu)限制而不能對(duì)結(jié)構(gòu)中數(shù)據(jù)的棧溢出進(jìn)行防護(hù)的技術(shù)壁壘;
本發(fā)明不影響原程序的最終構(gòu)成,以外部線(xiàn)程注入監(jiān)控目標(biāo)程序的運(yùn)行,不用改變現(xiàn)有的棧溢出防護(hù)機(jī)制;
本發(fā)明具有較好的準(zhǔn)確性,模擬棧的設(shè)計(jì)可充分利用現(xiàn)有的多種棧溢出檢測(cè)機(jī)制,從而提高準(zhǔn)確性;
本發(fā)明具有較大的適用性,程序的防護(hù)和程序的運(yùn)行具有較大的獨(dú)立性,因而可適用于多種類(lèi)型的軟件程序。
附圖說(shuō)明
圖1為本發(fā)明的模塊示意圖;
圖2為寄存器指向堆棧示意圖;
圖3為函數(shù)調(diào)用源碼示意圖;
圖4為堆棧結(jié)構(gòu)示意圖;
圖5為監(jiān)控窗口示意圖;
圖6為執(zhí)行strcpy后的監(jiān)控窗口示意圖。
具體實(shí)施方式
本說(shuō)明書(shū)中公開(kāi)的所有特征,或公開(kāi)的所有方法或過(guò)程中的步驟,除了互相排斥的特征和/或步驟以外,均可以以任何方式組合。
下面結(jié)合附圖對(duì)本發(fā)明做進(jìn)一步說(shuō)明:
棧溢出漏洞的原理
1)關(guān)于棧,程序的堆棧是由處理器直接支持,在interx86的系統(tǒng)中,堆棧在內(nèi)存中是從高地址向低地址擴(kuò)展,如圖2:
與堆棧操作相關(guān)的兩個(gè)寄存器是ebp和esp,esp總是指向堆棧棧頂,push時(shí),esp-4,然后拷貝數(shù)據(jù)到esp指向的地址,pop時(shí)先把esp指向的數(shù)據(jù)拷貝到內(nèi)存地址或寄存器,然后esp+4,棧中存儲(chǔ)了函數(shù)的參數(shù),函數(shù)的局部變量,調(diào)用函數(shù)前寄存器的值,函數(shù)的返回地址以及用于結(jié)構(gòu)化異常處理的數(shù)據(jù),ebp寄存器用于訪(fǎng)問(wèn)堆棧中的數(shù)據(jù),函數(shù)的參數(shù)地址比ebp的值高,函數(shù)局部變量的地址比ebp的值低,因而可通過(guò)ebp與偏移地址來(lái)訪(fǎng)問(wèn),下面是一組函數(shù)調(diào)用和它的堆棧結(jié)構(gòu)圖;
ebp寄存器的值總是指向先前的ebp,這樣就形成了一個(gè)函數(shù)調(diào)用鏈,調(diào)試器正是利用這個(gè)跟蹤函數(shù)堆棧調(diào)用順序。
2)棧溢出攻擊
實(shí)際情景中,攻擊者可以使用待定的腳本語(yǔ)言,通過(guò)網(wǎng)絡(luò)遠(yuǎn)程向?qū)ν馓峁I(yè)務(wù)的服務(wù)器進(jìn)行攻擊,利用對(duì)棧中數(shù)據(jù)的填充越界,也就是常說(shuō)的shellcode,實(shí)現(xiàn)有效的漏洞攻擊;
下面以一個(gè)例子簡(jiǎn)要說(shuō)明棧溢出攻擊:
a.漏洞源碼:
b.源碼說(shuō)明:在verify_password中,直接將字符串password復(fù)制到buffer中,而沒(méi)有檢測(cè)password的長(zhǎng)度是否超過(guò)buffer的大小,因而數(shù)據(jù)越界可覆蓋返回地址,造成棧溢出攻擊;
c.調(diào)試跟蹤查看驗(yàn)證:strcpy執(zhí)行前的返回地址為0x004109e8,strcpy執(zhí)行后,返回地址被password變量超出的部分覆蓋為0x77d456f7(jmpesp的地址),而jmpesp后正是注入的功能代碼,此處作演示目的彈出一個(gè)messagebox。
3)現(xiàn)有的棧溢出防護(hù)機(jī)制
棧溢出典型的攻擊行為主要有以下三種:
a.修改相鄰數(shù)據(jù)
b.修改函數(shù)返回地址
c.修改seh(structuredexceptionhandling)
現(xiàn)有棧溢出防護(hù)機(jī)制:
a.棧不可執(zhí)行機(jī)制:操作系統(tǒng)利用cpu硬件的特性,將棧段代碼設(shè)置為不可執(zhí)行;
b.windows的緩沖區(qū)安全監(jiān)測(cè)機(jī)制(gs):gs會(huì)在函數(shù)調(diào)用前往函數(shù)棧幀內(nèi)壓入一個(gè)隨機(jī)數(shù)(canary),然后等函數(shù)返回前,會(huì)對(duì)canary進(jìn)行核查,判斷canary是否被修改,因?yàn)閏anary的地址是(前棧幀ebp-4),所以如果溢出攻擊想要覆蓋返回地址或者異常處理句柄的話(huà),就會(huì)路過(guò)canary,系統(tǒng)檢測(cè)到canary被修改之后,在函數(shù)返回前就會(huì)直接終止程序;
c.內(nèi)存布局隨機(jī)化機(jī)制
內(nèi)存布局隨機(jī)化就是將程序的加載位置、堆棧位置以及動(dòng)態(tài)鏈接庫(kù)的映射位置隨機(jī)化,這樣攻擊者就無(wú)法知道程序的運(yùn)行代碼和堆棧上變量的地址。
本發(fā)明利用線(xiàn)程注入到目標(biāo)進(jìn)程(要保護(hù)的進(jìn)程),開(kāi)辟一個(gè)模擬??臻g,監(jiān)控模擬目標(biāo)進(jìn)程的指令流程,通過(guò)獲取rop攻擊的call和ret指令間的有效代碼串連,在模擬棧上執(zhí)行,再使用傳統(tǒng)的溢出防護(hù)機(jī)制,從而達(dá)到檢測(cè)rop攻擊的目的。
實(shí)施例1
1.rop攻擊防護(hù)系統(tǒng)利用遠(yuǎn)程線(xiàn)程注入到目標(biāo)進(jìn)程
使用dll遠(yuǎn)程注入技術(shù):
1)openprocess獲得要注入進(jìn)程的句柄;
2)virtualallocex在遠(yuǎn)程進(jìn)程中開(kāi)辟出一段內(nèi)存,長(zhǎng)度為strlen(dllname)+1;
3)writeprocessmemory將dll的名字寫(xiě)入第二步開(kāi)辟出的內(nèi)存中;
4)createremotethread將loadlibrarya作為線(xiàn)程函數(shù),參數(shù)為dll的名稱(chēng),創(chuàng)建新線(xiàn)程;
5)closehandle關(guān)閉線(xiàn)程句柄。
2.監(jiān)控目標(biāo)進(jìn)程的指令流程獲取call和ret間的指令
注入的線(xiàn)程可模仿ollydbg附加監(jiān)控目標(biāo)進(jìn)程,從而獲取程序執(zhí)行指令。
3.比對(duì)正常函數(shù)調(diào)用的特征指令,提取疑似異常的指令序列
設(shè)計(jì)特征提取算法,建立正常函數(shù)調(diào)用的特征數(shù)據(jù)庫(kù),比對(duì)獲取的異常調(diào)用間的指令序列。
4.模擬棧嘗試指令序列的多種拼接方案,試運(yùn)行,嘗試拼接,開(kāi)啟試運(yùn)行線(xiàn)程,可能的匯編實(shí)現(xiàn):
__asm{
leaeax,simulation_stack//模擬棧首地址
pusheax
ret//將simulation_stack的地址pop到eip,從而執(zhí)行模擬棧的可疑指令序列
}。
5.傳統(tǒng)檢測(cè)機(jī)制檢測(cè)模擬棧的運(yùn)行情況
這里可借鑒windows的緩沖區(qū)安全監(jiān)測(cè)機(jī)制(gs),往模擬棧壓入一個(gè)canary,然后等函數(shù)返回前,會(huì)對(duì)canary進(jìn)行核查,判斷canary是否被修改,從而判斷是否發(fā)生rop攻擊。
6.根據(jù)檢測(cè)結(jié)果回調(diào)控制目標(biāo)進(jìn)程的啟停,并輸出模擬棧上的rop攻擊代碼與溢出點(diǎn)。
以上所述,僅為本發(fā)明的具體實(shí)施方式,但本發(fā)明的保護(hù)范圍并不局限于此,任何屬于本技術(shù)領(lǐng)域的技術(shù)人員在本發(fā)明揭露的技術(shù)范圍內(nèi),可輕易想到的變化或替換,都應(yīng)涵蓋在本發(fā)明的保護(hù)范圍之內(nèi)。