黃樺烽,蘇璞睿,楊軼,賈相堃
(1.中國科學(xué)院軟件研究所可信計(jì)算與信息保障實(shí)驗(yàn)室,北京 100190;2.中國科學(xué)院大學(xué)計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院,北京 100190)
隨著人工智能技術(shù)在安全漏洞領(lǐng)域的應(yīng)用[1],漏洞研究的自動(dòng)化技術(shù)迅速發(fā)展。漏洞自動(dòng)利用是探尋漏洞可能的利用方法,進(jìn)而評估漏洞危害、防御漏洞利用攻擊的重要手段。自2016 年美國DARPA CGC[2](cyber grand challenge)比賽以來,漏洞自動(dòng)利用已成為網(wǎng)絡(luò)安全領(lǐng)域的研究熱點(diǎn)。早期的APEG[3]、AEG[4-5]、Mayhem[6]、PolyAEG[7]等在該領(lǐng)域進(jìn)行了眾多嘗試,主要針對明確的控制流劫持類漏洞,并僅在簡單的程序上進(jìn)行了驗(yàn)證,缺乏針對大規(guī)模軟件、復(fù)雜漏洞類型的分析能力。
內(nèi)存破壞漏洞是常見的漏洞類型。除了根據(jù)漏洞類型分類之外,從漏洞破壞能力刻畫漏洞更有利于漏洞利用。內(nèi)存破壞漏洞除了可能造成直接的控制流劫持外,也會表現(xiàn)為內(nèi)存訪問異常、段異常等,漏洞的終極破壞能力表現(xiàn)為任意代碼執(zhí)行。其中,可控內(nèi)存寫漏洞盡管起初可能只是造成程序崩潰,但具有很大的潛力轉(zhuǎn)化為控制流劫持,最終造成任意代碼執(zhí)行。造成可控內(nèi)存寫漏洞的原因存在多種可能,包括數(shù)組索引邊界檢查缺陷、緩沖區(qū)溢出覆蓋數(shù)據(jù)指針、UAF(use after free)造成指針誤用、格式化字符串漏洞等情況;可控內(nèi)存寫漏洞的利用方式具有多樣性,包括覆蓋函數(shù)指針構(gòu)造控制流劫持、覆蓋權(quán)限變量實(shí)現(xiàn)提權(quán)、覆蓋邏輯變量觸發(fā)邏輯錯(cuò)誤、覆蓋讀內(nèi)存指針實(shí)現(xiàn)信息泄露等。實(shí)際上,模糊測試產(chǎn)生的大量PoC(proof of concept)樣本并不能直接造成控制流劫持或任意代碼執(zhí)行。在模糊測試發(fā)現(xiàn)的可控寫錯(cuò)誤PoC 的基礎(chǔ)上,分析并構(gòu)造控制流劫持路徑,對提高漏洞的自動(dòng)利用能力,提升模糊測試漏洞挖掘結(jié)果的評估能力具有重要價(jià)值。
由于內(nèi)存屬性、復(fù)雜輸入依賴關(guān)系及環(huán)境約束限制等因素,從可控內(nèi)存寫漏洞到控制流劫持、再到任意代碼執(zhí)行的漏洞利用仍是一個(gè)困難問題,當(dāng)前仍沒有完整的自動(dòng)化方法。為此,本文提出了一種可控內(nèi)存寫漏洞自動(dòng)利用生成方法,從可控內(nèi)存寫漏洞的判定、利用要素的自動(dòng)化搜索、攻擊鏈的自動(dòng)構(gòu)造方面展開研究,基于可控內(nèi)存寫漏洞的利用模式,設(shè)計(jì)并實(shí)現(xiàn)了可控內(nèi)存寫漏洞的利用自動(dòng)生成原型系統(tǒng),驗(yàn)證了本文方法的有效性,主要貢獻(xiàn)和創(chuàng)新點(diǎn)如下。
1)從漏洞破壞能力的維度建立了內(nèi)存破壞漏洞利用能力的層次等級分類,包括崩潰異常、可控內(nèi)存寫、控制流劫持、任意代碼執(zhí)行4 個(gè)層次的能力等級。
2)提出了面向內(nèi)存地址控制力度的動(dòng)態(tài)污點(diǎn)分析方法,通過對指令控制力度的規(guī)則和語義分析,設(shè)計(jì)了面向內(nèi)存地址控制力度的污點(diǎn)傳播規(guī)則,提升了可控內(nèi)存寫漏洞判定的準(zhǔn)確度,形成了可控內(nèi)存寫漏洞判定能力。
3)分析總結(jié)了可控內(nèi)存寫漏洞的利用模式及利用要素,從代碼、數(shù)據(jù)、函數(shù)指針等多個(gè)維度,分析了可控內(nèi)存寫漏洞利用的不同方式,實(shí)現(xiàn)了函數(shù)指針要素的自動(dòng)搜索。
4)實(shí)現(xiàn)了可控內(nèi)存寫漏洞自動(dòng)生成控制流劫持利用的原型系統(tǒng),針對測試集構(gòu)造利用樣本達(dá)到控制流劫持能力的數(shù)量比模糊測試提升54%,顯著提升了模糊測試結(jié)果的可利用性評估能力。
漏洞利用攻擊是指攻擊者利用程序缺陷構(gòu)造輸入,使程序在執(zhí)行過程中執(zhí)行了滿足攻擊者意圖的代碼。針對內(nèi)存破壞漏洞,從漏洞破壞能力等級角度可將其分為崩潰異常、可控內(nèi)存寫、控制流劫持、任意代碼執(zhí)行4 個(gè)層次。崩潰異常是指非預(yù)期地覆蓋了其他變量導(dǎo)致內(nèi)存非法訪問異常;可控內(nèi)存寫是指程序?qū)憙?nèi)存的地址和內(nèi)容可被輸入所控制,如指令mov [edi],eax 中的edi 和eax 都受到輸入控制;控制流劫持是指程序跳轉(zhuǎn)的位置可以被輸入修改和控制,如call 指令的參數(shù)被輸入所控制;任意代碼執(zhí)行是指程序執(zhí)行的指令可以被修改為攻擊者注入的攻擊代碼。這4 種類型的能力從破壞程序運(yùn)行到獲得遠(yuǎn)程控制權(quán)逐層遞進(jìn),通常能夠獲得的漏洞PoC 屬于崩潰異常,而漏洞利用以達(dá)到任意代碼執(zhí)行為目標(biāo),來獲得最大攻擊收益。
根據(jù)內(nèi)存破壞漏洞不同的初始利用能力,內(nèi)存破壞漏洞利用步驟可以進(jìn)行分解和復(fù)用,如圖1 所示。左側(cè)表示漏洞利用能力,中間是漏洞利用方法和步驟,右側(cè)是漏洞利用緩解機(jī)制,箭頭上的字母序號標(biāo)注了該流程可能遭遇對應(yīng)的漏洞利用緩解機(jī)制的對抗攔截。
漏洞利用生成需要對觸發(fā)程序崩潰的PoC 進(jìn)行分析,動(dòng)態(tài)監(jiān)控程序解析PoC 的過程,分析內(nèi)存破壞漏洞初始的漏洞能力,結(jié)果如圖1 所示。進(jìn)一步,根據(jù)不同漏洞能力的特點(diǎn),選擇不同的利用方法實(shí)施利用。內(nèi)存破壞漏洞利用步驟總結(jié)如下。
圖1 內(nèi)存破壞漏洞利用步驟
1)具備初始內(nèi)存破壞能力條件下,嘗試構(gòu)造破壞內(nèi)存中的數(shù)據(jù)指針變量,破壞的數(shù)據(jù)指針變量作為漏洞利用生成后續(xù)步驟的前提條件。
2)修改被破壞內(nèi)存中指針包括2 種情況,第一種情況是該指針是函數(shù)指針,或者函數(shù)的返回地址,通過修改指針的內(nèi)容,可以實(shí)現(xiàn)控制流劫持。針對此類指針的修改,操作系統(tǒng)的 RELRO(relocation read-only)等寫保護(hù)機(jī)制會對該過程形成對抗。第二種情況是該指針是數(shù)據(jù)指針,通過修改指針內(nèi)容,可嘗試構(gòu)造可控地址內(nèi)存寫。操作系統(tǒng)部署了Meta Data、Canary、Safe Unlink、Heap Cookie 等防御機(jī)制,導(dǎo)致利用邏輯復(fù)雜、難度更高,本文研究針對數(shù)據(jù)指針的情況展開。
3)在能夠構(gòu)造可控地址內(nèi)存寫的條件下,嘗試定位并修改函數(shù)地址指針或者返回地址,如果該函數(shù)指針或返回地址在后續(xù)執(zhí)行中被使用,則可構(gòu)造控制流劫持。此部分需要從內(nèi)存屬性篩選出未受寫保護(hù)的函數(shù)指針,避開RELRO 寫保護(hù)安全機(jī)制的影響。
4)函數(shù)指針被覆蓋到被引用觸發(fā)控制流劫持過程中,中間可能受到CFI(control-flow integrity)、Stack Cookie 等安全機(jī)制的影響,需要搜索控制流完整性和數(shù)據(jù)流完整性檢驗(yàn)的缺陷和繞過空間。
5)為了形成可用的控制流劫持,需要在內(nèi)存中放置并定位ShellCode,以確定控制流劫持方向。該過程可能受到PIE(position independent executable)和ASLR(address space layout randomization)等內(nèi)存地址隨機(jī)化影響,通過寄存器指針、??臻g數(shù)據(jù)指針?biāo)阉骺蓢L試找出指向污點(diǎn)數(shù)據(jù)的指針,作為定位ShellCode 位置的變量元素,此外,還可通過堆噴、信息泄露等方式提高ShellCode 代碼定位的成功率。
6)ShellCode 定位完成之后,結(jié)合控制流劫持可實(shí)現(xiàn)最終目標(biāo),即任意代碼執(zhí)行。但該過程可能受到DEP(data execution prevention)和NX(no execute)數(shù)據(jù)執(zhí)行保護(hù)的影響,目前存在ROP(return-oriented programming)、JOP(jump-oriented programming)、Ret2Lib(return-to-library)等代碼重用的方式繞過數(shù)據(jù)執(zhí)行保護(hù),而代碼重用過程中需要先定位出模塊代碼位置,這一過程采用的策略包括使用未隨機(jī)化的代碼模塊、信息泄露模塊地址,從這些模塊搜索ROP Gadgets 的代碼片段,串接ROP 功能實(shí)現(xiàn)利用,或者通過代碼功能修改內(nèi)存屬性為可執(zhí)行實(shí)現(xiàn)任意代碼執(zhí)行的效果。
以上闡述了內(nèi)存破壞漏洞根據(jù)不同利用能力的漏洞利用生成方法和步驟,同時(shí)也闡述了相應(yīng)過程可能遇到的安全機(jī)制限制,漏洞自動(dòng)利用嘗試將這些生成方法和步驟自動(dòng)化實(shí)現(xiàn)。當(dāng)前的研究工作僅實(shí)現(xiàn)了其中一部分環(huán)節(jié)的自動(dòng)化,APEG[3]是基于補(bǔ)丁自動(dòng)生成 Crash 的 PoC;AEG[4-5]、Mayhem[6]、PolyAEG[7]、CRAX[8]針對的是控制流劫持條件下的構(gòu)造任意代碼執(zhí)行的漏洞自動(dòng)利用;HCSIFTER[9]、Revery[10]、FUZE[11]針對的是堆類型漏洞,且只針對漏洞利用中的特定環(huán)節(jié)實(shí)現(xiàn)自動(dòng)化;R2dlAEG[12]、FlowStitch[13]、DOP[14]、BOP[15]、Q[16]則是針對漏洞利用過程中的特定安全機(jī)制繞過環(huán)節(jié)實(shí)現(xiàn)了自動(dòng)化。相關(guān)工作對應(yīng)的漏洞自動(dòng)利用生成環(huán)節(jié)如表1 所示,序號含義為:①構(gòu)造崩潰異常;②基于崩潰構(gòu)造可控內(nèi)存寫;③基于崩潰構(gòu)造控制流劫持;④基于可控內(nèi)存寫構(gòu)造控制流劫持;⑤基于控制流劫持構(gòu)造任意代碼執(zhí)行;⑥D(zhuǎn)EP 安全機(jī)制繞過;⑦CFI安全機(jī)制繞過;⑧可利用性評估。
表1 相關(guān)工作對應(yīng)的漏洞自動(dòng)利用生成環(huán)節(jié)
數(shù)據(jù)顯示,現(xiàn)有研究還缺少可控內(nèi)存寫到控制流劫持利用階段的自動(dòng)化生成,同時(shí)該過程主要存在三方面的難點(diǎn)與挑戰(zhàn)。
1)在可控內(nèi)存寫漏洞的判定方面,依賴于動(dòng)態(tài)污點(diǎn)分析對逐條指令的內(nèi)存寫操作進(jìn)行分析,檢測指令尋址寄存器是否受到輸入控制,并且需要考慮控制的力度能否達(dá)到任意地址寫的程度,寫范圍的限度是判斷漏洞是否真實(shí)存在的難點(diǎn)。
2)在可控內(nèi)存寫漏洞利用要素搜索方面,需要同時(shí)考慮函數(shù)指針或返回地址的定位,內(nèi)存屬性是否可寫,以及函數(shù)指針是否能被引用的情況,即需要搜索出同時(shí)滿足地址可定位、內(nèi)存可寫、會被調(diào)用這3 個(gè)條件的函數(shù)指針。
3)在控制流劫持觸發(fā)方面,CFI、SHE(safe exception handler table)等安全機(jī)制的引入,可能導(dǎo)致被修改后的函數(shù)指針或者返回地址無法被調(diào)用執(zhí)行,對虛函數(shù)表、SEH 表的完整性檢查,以及Stack Cookie 對棧溢出的檢測都有可能攔截被破壞的函數(shù)指針及返回地址被引用,從而阻止控制流劫持,這些因素給可控內(nèi)存寫漏洞自動(dòng)利用生成控制流劫持帶來了諸多的挑戰(zhàn)。
針對可控內(nèi)存寫漏洞自動(dòng)判定的難點(diǎn)問題,動(dòng)態(tài)污點(diǎn)分析是檢測可控內(nèi)存寫漏洞的基本思路。其原理是標(biāo)記用戶可控的輸入為污點(diǎn),動(dòng)態(tài)跟蹤污點(diǎn)數(shù)據(jù)在程序運(yùn)行過程中的傳播過程,檢測內(nèi)存寫入的指令參數(shù)是否受到輸入控制進(jìn)行該類型漏洞的判定。設(shè)計(jì)使用中涉及污點(diǎn)傳播規(guī)則、檢測規(guī)則和約束條件三方面。
在污點(diǎn)傳播規(guī)則方面,基于傳統(tǒng)污點(diǎn)分析的初步檢測,本文發(fā)現(xiàn)其存在大量誤報(bào),通過對傳播過程進(jìn)行回溯分析得到傳播路徑,發(fā)現(xiàn)誤報(bào)主要包括以下情況。
1)污點(diǎn)數(shù)據(jù)作為堆分配大小,影響了下一個(gè)堆分配的位置,下一個(gè)堆的數(shù)據(jù)訪問指針因受到污點(diǎn)數(shù)據(jù)影響導(dǎo)致誤報(bào)。
2)污點(diǎn)數(shù)據(jù)影響到內(nèi)存訪問地址,但只是部分的地址位,多次移位運(yùn)算之后指針的多個(gè)比特位不受污點(diǎn)控制,并且污染的位置只是影響,達(dá)不到目標(biāo)內(nèi)存值任意控制的能力。
3)數(shù)組訪問的偏移索引雖然受到污點(diǎn)數(shù)據(jù)影響,但是其有前置約束條件,雖然實(shí)際情況是被污染,但達(dá)不到任意地址寫破壞的效果。
總體而言是由于傳統(tǒng)污點(diǎn)傳播規(guī)則未區(qū)分控制計(jì)算和影響計(jì)算的程度,而地址計(jì)算依賴于嚴(yán)格的控制計(jì)算。雖然符號執(zhí)行理論上可用于地址寫控制范圍的求解,但消耗大量的計(jì)算資源。針對這些問題,本文提出了面向內(nèi)存地址控制力度的動(dòng)態(tài)污點(diǎn)分析方法,通過對不同力度的計(jì)算指令污點(diǎn)傳播規(guī)則進(jìn)行改進(jìn),以適用于可控內(nèi)存寫漏洞的檢測。
計(jì)算指令通常分為算術(shù)運(yùn)算、邏輯運(yùn)算、位運(yùn)算等類型,地址計(jì)算涉及更多的是加減法運(yùn)算,數(shù)組地址偏移量需要乘法運(yùn)算支持多字節(jié)一組的單元尋址,但有時(shí)通過左移實(shí)現(xiàn)冪次倍的乘法運(yùn)算,另外地址對齊也會進(jìn)行移位或者與運(yùn)算將低比特位抹零處理。針對這些特性,本文對相關(guān)指令的污點(diǎn)傳播規(guī)則進(jìn)行了策略修改,傳播規(guī)則修改策略如表2 所示。
表2 傳播規(guī)則修改策略
在檢測規(guī)則方面,可控地址寫的檢測需要指針4 byte 受到控制才具備任意地址寫的能力,考慮到偏移地址受控情況可能低2 byte 被控制即可實(shí)現(xiàn)破壞,本文檢測低2 byte 受污染對可控內(nèi)存寫進(jìn)行判定。比如mov [edx],eax 指令,需要edx 的低2 byte受到污點(diǎn)控制,發(fā)現(xiàn)誤報(bào)的案例中地址指針的低字節(jié)并不受污點(diǎn)控制,其中大量使用了shl 左移指令計(jì)算內(nèi)存頁地址,地址訪問只是影響了所在內(nèi)存頁,低地址不受污染,并不具備控制地址寫能力。
在約束條件方面,本文針對cmp 比較指令進(jìn)行了記錄,如果指針引用前做了邊界檢測將進(jìn)行記錄,根據(jù)上下文可以判定出警告的可控地址寫指針是否有安全邊界檢測,如果邊界檢測的點(diǎn)與可控地址寫的告警點(diǎn)位于同一個(gè)函數(shù)上下文,且相關(guān)變量污點(diǎn)源相同,可初步判斷告警是誤報(bào)情況。
針對當(dāng)前可控內(nèi)存寫漏洞構(gòu)造控制流劫持利用的難點(diǎn)與挑戰(zhàn),本文設(shè)計(jì)實(shí)現(xiàn)了可控內(nèi)存寫漏洞自動(dòng)利用生成方法,其流程如圖2 所示。
圖2 可控內(nèi)存寫漏洞自動(dòng)利用生成方法流程
首先,基于可控力度污點(diǎn)分析,判定其是否達(dá)到可控內(nèi)存寫漏洞的利用能力;然后,基于靜態(tài)分析和動(dòng)態(tài)分析,提取出程序中的函數(shù)表,包括導(dǎo)入表、虛函數(shù)表、回調(diào)函數(shù)表等,篩選出其中具備寫權(quán)限的部分,并以動(dòng)態(tài)運(yùn)行的方式篩選出可控內(nèi)存寫觸發(fā)點(diǎn)之后潛在調(diào)用執(zhí)行的點(diǎn);最后,提取備選覆蓋的內(nèi)存寫入地址,及覆蓋內(nèi)存的約束條件和內(nèi)容,由輸入求解引擎進(jìn)行約束條件求解,生成漏洞利用樣本。
本文實(shí)現(xiàn)了可控內(nèi)存寫漏洞的自動(dòng)利用原型系統(tǒng),原型系統(tǒng)框架如圖3 所示,包含基于QEMU實(shí)現(xiàn)動(dòng)態(tài)插樁提取指令記錄和污點(diǎn)源,基于Udis86反匯編和可控內(nèi)存力度污點(diǎn)傳播規(guī)則實(shí)現(xiàn)可控內(nèi)存寫漏洞的自動(dòng)檢測,基于指令記錄分析和靜態(tài)分析提取代碼、數(shù)據(jù)、函數(shù)指針、數(shù)據(jù)指針、內(nèi)存屬性的利用要素,基于利用模式提取利用約束并采用Z3 求解引擎對輸入進(jìn)行求解。
圖3 原型系統(tǒng)框架
本節(jié)從可控內(nèi)存寫漏洞的判定、可控內(nèi)存寫漏洞利用模式及要素自動(dòng)搜索、可控內(nèi)存寫漏洞利用自動(dòng)生成三方面對本文系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)進(jìn)行詳細(xì)介紹。
可控內(nèi)存寫漏洞的判定使用了文獻(xiàn)[17]提出的Weak-Tainted 程序動(dòng)態(tài)運(yùn)行時(shí)漏洞檢測模型,基于該模型對脆弱點(diǎn)和污點(diǎn)屬性進(jìn)行定義,可控內(nèi)存寫漏洞檢測模型如圖4 所示,脆弱點(diǎn)集合包含2 種類型:Weak-INS 和Weak-PC。Weak-INS 是指可能引起可控內(nèi)存寫能力的指令模式,例如mov [edi]、eax、rep movsd 等;Weak-PC 是指潛在可控內(nèi)存寫能力的函數(shù)地址集合,通過靜態(tài)分析提取敏感脆弱函數(shù)地址,例如提取memcpy、strcpy、scanf、sprintf、read 等具備寫內(nèi)存能力的函數(shù),通過靜態(tài)解析libc庫的導(dǎo)出函數(shù)表獲得函數(shù)偏移地址,結(jié)合模塊基地址計(jì)算得到運(yùn)行過程的函數(shù)地址。污點(diǎn)屬性需要給脆弱點(diǎn)集合的每個(gè)脆弱點(diǎn)定義污點(diǎn)檢測規(guī)則,檢測相應(yīng)寄存器等變量是否受輸入污染。不同脆弱點(diǎn)都有對應(yīng)的存儲單元檢測規(guī)則,當(dāng)脆弱點(diǎn)定義的檢測變量受到輸入污染,則可篩選出具備可控地址寫能力的脆弱點(diǎn)。
圖4 可控內(nèi)存寫漏洞檢測模型
與控制流劫持檢測相比,可控內(nèi)存寫的檢測資源消耗會更高。從指令的層面分析,控制流劫持檢測只需要檢測轉(zhuǎn)移跳轉(zhuǎn)指令,而可控內(nèi)存寫的檢測需要檢測所有內(nèi)存寫操作的指令,這類指令所占比例更高,所需消耗的計(jì)算資源更多。但在動(dòng)態(tài)污點(diǎn)分析過程中,本身就需要對指令進(jìn)行反匯編,提取操作數(shù)類型,計(jì)算操作數(shù)地址,這些過程的結(jié)果可以直接復(fù)用在可控內(nèi)存寫檢測當(dāng)中,從而減輕額外的計(jì)算資源開銷。
本文基于內(nèi)存地址控制力度的動(dòng)態(tài)污點(diǎn)分析方法,將文件、網(wǎng)絡(luò)、鍵盤等輸入標(biāo)記為污點(diǎn)源,并賦予每個(gè)輸入字節(jié)不同的標(biāo)簽,動(dòng)態(tài)跟蹤解析執(zhí)行的每條指令,分析指令對“污點(diǎn)數(shù)據(jù)”的“傳播”和“清除”過程,動(dòng)態(tài)更新寄存器和內(nèi)存的污點(diǎn)狀態(tài)及其對應(yīng)的污點(diǎn)標(biāo)簽。
可控內(nèi)存寫漏洞檢測流程如圖5 所示。1)將二進(jìn)制程序和PoC 輸入置入QEMU 中動(dòng)態(tài)加載運(yùn)行,通過QEMU 對進(jìn)程實(shí)現(xiàn)動(dòng)態(tài)插樁,根據(jù)指令及API參數(shù)判定是否引入新的污點(diǎn)源,如果引入新的污點(diǎn)源,則更新記錄污點(diǎn)狀態(tài)的結(jié)構(gòu)Taint Map;2)對指令進(jìn)行反匯編解析,根據(jù)指令語義解析進(jìn)行動(dòng)態(tài)污點(diǎn)傳播分析,檢索源操作數(shù)的污點(diǎn)狀態(tài),更新目標(biāo)操作數(shù)的污點(diǎn)狀態(tài)及計(jì)算新的污點(diǎn)標(biāo)簽;3)在動(dòng)態(tài)污點(diǎn)分析計(jì)算指令操作地址過程中,分析操作數(shù)類型,當(dāng)目的操作數(shù)的類型為內(nèi)存時(shí),進(jìn)入可控內(nèi)存寫檢測流程,否則進(jìn)入下一步;4)當(dāng)指令寫操作數(shù)的地址為內(nèi)存時(shí),如果是立即數(shù)尋址則可直接跳過,如果是寄存器尋址則檢測直接尋址和間接尋址的寄存器是否為污點(diǎn),如果為污點(diǎn)再檢測數(shù)據(jù)源是否為污點(diǎn),兩者同時(shí)為污點(diǎn)的情況下則具備了可控內(nèi)存寫可控內(nèi)容的能力;5)針對具備可控內(nèi)存寫能力的潛在點(diǎn),記錄輸出報(bào)告信息,內(nèi)容包括指令地址、指令內(nèi)容、尋址寄存器(地址指針)、尋址寄存器的污點(diǎn)源、源數(shù)據(jù)、源數(shù)據(jù)對應(yīng)污點(diǎn)源;6)循環(huán)分析下一條指令。
圖5 可控內(nèi)存寫漏洞檢測流程
可控內(nèi)存寫漏洞具有較強(qiáng)的破壞能力,單指令層面的可控內(nèi)存寫具備篡改單字節(jié)、雙字節(jié)、四字節(jié)或八字節(jié)的能力,例如mov [edi]、al、ax、eax、rax;函數(shù)層面的可控內(nèi)存寫具備篡改更多長度字節(jié)的能力,例如read(dst,fd,size)、memcpy(dst,src,size)等。攻擊者在獲得可控內(nèi)存寫漏洞能力的前提下,可以肆意破壞內(nèi)存,篡改包括指令、數(shù)據(jù)、指針、函數(shù)等類型的變量。與控制流劫持漏洞相比,可控內(nèi)存寫漏洞利用模式更加豐富,如圖6 所示。
圖6 可控內(nèi)存寫漏洞利用模式
篡改指令可以直接誘發(fā)任意代碼執(zhí)行,但正常情況下指令所在內(nèi)存處于不可寫狀態(tài),不排除SMC等動(dòng)態(tài)代碼的情況;篡改數(shù)據(jù)需要根據(jù)數(shù)據(jù)類型而定,例如篡改權(quán)限標(biāo)記變量可達(dá)到提升權(quán)限能力,篡改邏輯變量可觸發(fā)邏輯錯(cuò)誤執(zhí)行本不具備權(quán)限的代碼,篡改system 等敏感函數(shù)參數(shù)可觸發(fā)命令注入執(zhí)行;篡改數(shù)據(jù)指針可誘發(fā)二次的可控內(nèi)存讀寫,構(gòu)造更多的數(shù)據(jù)破壞;篡改函數(shù)指針可觸發(fā)控制流劫持,構(gòu)造任意代碼執(zhí)行的漏洞利用。
基于可控內(nèi)存寫漏洞利用模式,本文設(shè)計(jì)實(shí)現(xiàn)了其中通過劫持函數(shù)表和函數(shù)指針實(shí)現(xiàn)控制流劫持的利用生成方式,具體包括內(nèi)存讀寫屬性的提取、函數(shù)表地址的動(dòng)態(tài)提取與靜態(tài)提取、潛在利用可能函數(shù)表的篩選。
內(nèi)存的讀寫執(zhí)行權(quán)限屬性是極關(guān)鍵的前提要素,可控內(nèi)存寫需要寫入的內(nèi)存地址具備寫權(quán)限。由于現(xiàn)代操作系統(tǒng)增強(qiáng)了內(nèi)存的安全管理,在進(jìn)程初始化完成之后對進(jìn)程空間的代碼區(qū)域、動(dòng)態(tài)庫導(dǎo)入表等敏感內(nèi)存位置,設(shè)置了只讀屬性,這些內(nèi)存區(qū)域在可控內(nèi)存寫利用生成過程中無法作為被寫入的內(nèi)存區(qū)域。因此在漏洞利用生成過程中,需要通過內(nèi)存讀寫屬性的分析,篩選其中具備寫權(quán)限的內(nèi)存,再篩選滿足其他條件的利用要素。
內(nèi)存權(quán)限屬性的提取可以通過內(nèi)存頁屬性查詢進(jìn)行解析,Windows 系統(tǒng)提供了VirtualQueryEx內(nèi)存屬性查詢接口,輸入?yún)?shù)包括句柄HANDLE、查詢的內(nèi)存地址、接收返回值的結(jié)構(gòu)地址和大小,輸出為MEMORY_BASIC_INFORMATION 結(jié)構(gòu)體信息,其中BaseAddress 為查詢地址所在內(nèi)存塊的基地址,RegionSize 為內(nèi)存區(qū)塊大小,Protect 為權(quán)限屬性,通過循環(huán)解析可以獲取整個(gè)進(jìn)程空間的內(nèi)存屬性,進(jìn)程空間內(nèi)存可寫權(quán)限屬性提取偽代碼如算法1 所示。
函數(shù)指針及函數(shù)表的覆蓋是構(gòu)造控制流劫持的關(guān)鍵步驟,傳統(tǒng)漏洞是基于緩沖區(qū)溢出覆蓋函數(shù)表或者函數(shù)返回地址,溢出覆蓋函數(shù)表依賴于緩沖區(qū)與函數(shù)表位于同一結(jié)構(gòu)體或者臨近的結(jié)構(gòu)體??煽貎?nèi)存寫漏洞則可以選擇性地覆蓋備選的函數(shù)指針或者函數(shù)返回地址,但由于函數(shù)返回地址所處??臻g基本隨機(jī),難以直接定位。函數(shù)表或者函數(shù)指針的地址可定位能力相對較強(qiáng),除了函數(shù)導(dǎo)入導(dǎo)出表可供選擇之外,虛函數(shù)表、回調(diào)函數(shù)指針、跳轉(zhuǎn)表也都是備選的覆蓋項(xiàng)。
備選覆蓋函數(shù)指針的篩選依據(jù)包括函數(shù)表所在內(nèi)存可寫、函數(shù)指針在觸發(fā)可控寫內(nèi)存漏洞之后會被調(diào)用、函數(shù)表地址可定位。為了統(tǒng)計(jì)出滿足條件的函數(shù)或者跳轉(zhuǎn)表,本文基于動(dòng)態(tài)指令分析收集備選的函數(shù)表利用要素。
首先基于動(dòng)態(tài)插樁獲取執(zhí)行的指令記錄,反匯編篩選其中的函數(shù)調(diào)用指令call 和跳轉(zhuǎn)指令jmp 進(jìn)行分析。call/jmp 指令的跳轉(zhuǎn)方式包括間接跳轉(zhuǎn)和直接跳轉(zhuǎn),直接跳轉(zhuǎn)是通過指令地址的相對偏移實(shí)施跳轉(zhuǎn),由于不存在可變參數(shù),不會出現(xiàn)劫持情況。間接跳轉(zhuǎn)是通過尋址方式計(jì)算獲得跳轉(zhuǎn)地址,其潛在跳轉(zhuǎn)地址被劫持可能,同時(shí)也包括寄存器跳轉(zhuǎn)call/jmp eax 和內(nèi)存地址跳轉(zhuǎn)call/jmp [eax+0x20]2 種情況。調(diào)用寄存器的情況需要分析目標(biāo)寄存器源自的內(nèi)存地址,調(diào)用寄存器代碼示例如圖7 所示,0x000187A6 處的 call ecx 往上分析追溯到0x00018794 處的mov ecx,[eax+0xc],如果可控內(nèi)存寫漏洞對內(nèi)存[eax+0xc]進(jìn)行了覆蓋,會導(dǎo)致call ecx 位置出現(xiàn)控制流劫持。
圖7 調(diào)用寄存器代碼示例
因此,針對調(diào)用寄存器的情況,需要逆向分析出寄存器來源的內(nèi)存地址作為可控內(nèi)存寫的利用備選地址,而類似call [0x6583138c]、call[eax+0x20]這類的指令可直接獲取內(nèi)存地址作為備選地址。
為了解決寄存器作為調(diào)用參數(shù)的內(nèi)存源地址追溯問題,傳統(tǒng)思路是針對寄存器做逆向切片分析,本文采用了短距離的動(dòng)態(tài)污點(diǎn)分析,在基于污點(diǎn)分析檢測可控內(nèi)存地址寫的過程當(dāng)中,針對內(nèi)存數(shù)據(jù)到寄存器的拷貝過程,記錄了寄存器來源的內(nèi)存地址,并作為污點(diǎn)標(biāo)簽在短距離內(nèi)進(jìn)行計(jì)算傳播,短距離污點(diǎn)傳播偽代碼如算法2 所示。之所以稱為短距離是因?yàn)榧拇嫫鞯母骂l率非常高,當(dāng)采用新的內(nèi)存數(shù)據(jù)對寄存器進(jìn)行覆蓋時(shí),立即更新寄存器的污點(diǎn)標(biāo)簽為新的內(nèi)存地址標(biāo)簽,同時(shí)忽略寄存器到內(nèi)存、內(nèi)存到內(nèi)存直接的傳播,只是為了滿足寄存器溯源內(nèi)存而提出的微縮版的動(dòng)態(tài)污點(diǎn)分析方案。
另外,存在一類函數(shù)調(diào)用的函數(shù)指針無法通過指令記錄分析獲得,但是這類函數(shù)卻具有被調(diào)用的可能。該類型普遍用于自定義hook 庫函數(shù)接口的結(jié)構(gòu)指針變量,初始值為0,如果被賦值為非0 則會被調(diào)用,包括lib_hook_malloc、lib_hook_free 等,遺漏函數(shù)模式代碼示意如圖8 所示。指令記錄中,由于函數(shù)指針變量未被覆蓋,不會觸發(fā)調(diào)用該函數(shù)指針的代碼,上述代碼中的lib_hook_func 函數(shù)不會被調(diào)用,相應(yīng)的匯編指令call eax 也不會被執(zhí)行。
圖8 遺漏函數(shù)模式代碼示意
針對這種情況,本文采用靜態(tài)模式匹配的方式,基于libc 庫中存在該模式的函數(shù)提取特征,在二進(jìn)制程序中搜索匹配相應(yīng)的函數(shù),識別函數(shù)之后提取函數(shù)表的全局變量地址。
潛在調(diào)用點(diǎn)函數(shù)通過其在指令記錄中的出現(xiàn)頻度和出現(xiàn)順序進(jìn)行排序篩選,通過構(gòu)造一個(gè)不觸發(fā)崩潰的樣本,在檢測出的可控內(nèi)存寫之后的點(diǎn)分析被引用的函數(shù)表或函數(shù)指針,以及選擇調(diào)用頻度高的函數(shù)指針作為備選的劫持點(diǎn)。
可控內(nèi)存寫漏洞利用的自動(dòng)生成依據(jù)漏洞判定給出的漏洞點(diǎn)和輸入依賴字節(jié),結(jié)合漏洞利用模式及利用要素的自動(dòng)提取篩選出備選的內(nèi)存寫入點(diǎn),構(gòu)造出覆蓋函數(shù)指針的約束求解條件。約束條件主要包括2 個(gè):1)漏洞點(diǎn)寫入的內(nèi)存地址約束其等于備選利用方式需要寫入的內(nèi)存地址;2)漏洞點(diǎn)寫入的內(nèi)容約束其等于備選利用方式預(yù)期的內(nèi)存值。
針對指令檢測出的可控內(nèi)存寫,其利用生成的約束條件是清晰且明確的。針對函數(shù)層面的檢測出的可控內(nèi)存寫,其利用生成的約束條件依據(jù)函數(shù)的復(fù)雜程度而定,類似memcpy、strcpy、strncpy 這類寫入內(nèi)存地址和內(nèi)容參數(shù)變量明確的情況,其約束條件也是清晰明確的。但是,類似sprintf、fprintf、printf 這類格式化字符串函數(shù),當(dāng)格式化參數(shù)format受到控制時(shí),通過控制棧上的指針和格式化參數(shù)同樣可以構(gòu)造可控內(nèi)存寫,但是其約束條件的構(gòu)造則比較復(fù)雜。
格式化字符串漏洞在可控內(nèi)存寫利用能力構(gòu)造的約束條件生成利用了格式字符%n 的功能,該功能是向棧指針指向的內(nèi)存地址寫入前序輸出的字符數(shù)量。以32 bit 程序?yàn)槔?n 是寫入4 byte 內(nèi)存,%hn是寫入2 byte 內(nèi)存,%hhn 是寫入1 byte 內(nèi)存。此外,格式化字符串的單次輸出字符串?dāng)?shù)量上限是65 535,因此如果要寫入4 byte 的地址空間,需要拆成2 次的2 byte 寫入,即使用%hn 的格式字符進(jìn)行寫入。同時(shí),寫入的內(nèi)存地址是通過棧上的變量指針進(jìn)行尋址,因此需要在棧上搜索出2 個(gè)4 byte 被污點(diǎn)輸入控制的變量,約束這2 個(gè)變量為寫入目標(biāo)內(nèi)存的地址addr_for_write 和addr_for_write+2。如圖9 所示,格式化字符串函數(shù)printf的format參數(shù)被輸入控制,利用目標(biāo)是向addr_for_write 寫入4 byte 的value,利用過程如下。
圖9 格式化字符串的可控內(nèi)存寫生成
1)先將value 分解成低高2 個(gè)word 字段n=value&0xffff 和m=(value>>16)&0xffff,需分別往addr_for_write 和addr_for_write+2 寫入n和m,由于輸出字符數(shù)量是遞增,因此2 次寫入的字節(jié)只能先寫入小值,再寫入大值。
2)在棧上搜索出2 個(gè)4 byte 被污點(diǎn)輸入控制的變量,計(jì)算與format 指針參數(shù)的位置距離,距離單位是參數(shù)個(gè)數(shù),因此N=[taint_addr-point_addr]/4,圖9 中2 個(gè)變量是連續(xù)的,因此分別為N和N+1。
3)構(gòu)造格式化參數(shù),m>n則構(gòu)造格式化字符串“%[n]x%[N]$hn%[m-n]x%[N+1]$hn”(方括號內(nèi)的值需要寫入實(shí)際計(jì)算得到的10 進(jìn)制數(shù)值),m<n則構(gòu)造“%[m]x%[N+1]$hn%[n-m]x%[N]$hn”。
4)根據(jù)實(shí)際情況整合約束條件,如m>n的情況下得到約束條件,最后根據(jù)約束求解方法對約束條件函數(shù)進(jìn)行求解,函數(shù)公式中format 簡寫為fmt。
對約束條件的求解,除了約束條件還需要有約束表達(dá)式,本文通過動(dòng)態(tài)污點(diǎn)分析已經(jīng)能夠提取漏洞點(diǎn)約束條件中的輸入相關(guān)變量,在此基礎(chǔ)上,將約束條件相關(guān)的變量符號化,重新解析動(dòng)態(tài)插樁過程提取的指令記錄,根據(jù)初始的符號化變量,采用Z3 的語法規(guī)則生成計(jì)算表達(dá)式,并自動(dòng)提取python格式的表達(dá)式計(jì)算過程,自動(dòng)生成對約束條件的求解腳本,最后執(zhí)行Z3 求解腳本生成利用的exp 樣本。
本文選取了2018 年Defcon China CTF 比賽中的50 道Linux 題目和Windows 系統(tǒng)下的PLC WinNT、Media Player Classic、DirectShow Player GUI、WINWORD、VUPlayer、Float Ftp 作為測試集。選取的真實(shí)程序包括了工控程序、辦公軟件、多媒體軟件和網(wǎng)絡(luò)傳輸工具等,并根據(jù)PoC 要求選擇了軟件版本,其中PLC WinNT 是SCADA 工業(yè)控制軟件代表CODESYS 中的重要組件??紤]到不同版本軟件在功能和復(fù)雜度上處于相同量級,且相關(guān)版本軟件仍在廣泛使用,本文選取的程序具有一定的代表性。
本文實(shí)現(xiàn)的可控內(nèi)存寫檢測基于動(dòng)態(tài)污點(diǎn)分析實(shí)現(xiàn),針對CTF 測試用例,將標(biāo)準(zhǔn)輸入stdin 標(biāo)記為污點(diǎn),采用qemu 的用戶態(tài)模式進(jìn)行指令插樁,基于UDIS86 反匯編引擎解析指令實(shí)現(xiàn)動(dòng)態(tài)污點(diǎn)傳播規(guī)則,針對寫內(nèi)存的指令檢測內(nèi)存寫入地址的尋址寄存器是否為污點(diǎn)判定是否潛在可控內(nèi)存寫。
CTF 賽題測試集的PoC 輸入是通過AFL++模糊測試引擎獲得的,選擇能夠觸發(fā)可控內(nèi)存寫或控制流劫持的PoC 作為測試本模塊的數(shù)據(jù)用例。測試結(jié)果如表3 所示,50 個(gè)用例中有22 個(gè)樣本的利用能力達(dá)到控制流劫持,16 個(gè)達(dá)到可控內(nèi)存寫;另外pwn12 的數(shù)據(jù)傳播方式通過控制字段編碼,污點(diǎn)分析傳播會斷層判定失敗,pwn32 是命令注入類型漏洞,不屬于內(nèi)存破壞漏洞,另外幾個(gè)用例Fuzz 得到的PoC 未能觸發(fā)這2 種狀態(tài)。
表3 測試結(jié)果
此外還有7 個(gè)樣例是格式化字符串漏洞,無法通過指令層面進(jìn)行判定,即使格式化字符串漏洞的PoC 注入了%n 的可控地址寫功能,也無法通過mov[taint],taint 污點(diǎn)模式進(jìn)行判定,這是由于其寫入的值是前序輸出的字符數(shù)量,該參數(shù)不具備taint 屬性,而只能是mov [taint],value 模式。針對該問題,本文通過檢測函數(shù)的格式化參數(shù)污點(diǎn)屬性及棧指針污點(diǎn)屬性,實(shí)現(xiàn)了基于函數(shù)層面的可控內(nèi)存寫漏洞利用能力判定。函數(shù)級格式字符串漏洞識別情況如表4 所示,均能準(zhǔn)確識別出格式化字符串漏洞。
表4 函數(shù)級格式字符串漏洞識別情況
同時(shí),函數(shù)層面的可控內(nèi)存寫判定還考慮read函數(shù),該函數(shù)直接調(diào)用系統(tǒng)調(diào)用將數(shù)據(jù)讀入指定的內(nèi)存緩沖區(qū),如果指定內(nèi)存的指針受到輸入控制同樣會觸發(fā)可控內(nèi)存寫。
另外,針對現(xiàn)實(shí)場景的應(yīng)用程序,本文選取的PLC WinNT、Media Player Classic、DirectShow Player GUI 是存在可控內(nèi)存寫漏洞的實(shí)例程序,給予其觸發(fā)可控地址寫的PoC 作為測試輸入,測試本文方法能否檢測出崩潰點(diǎn)存在可控地址寫的能力;WinWord、VUPlayer、Float Ftp 程序是測試控制流劫持漏洞的樣本,評估在具備檢測控制流劫持條件下是否有可控內(nèi)存寫的誤報(bào)情況。
基于內(nèi)存地址控制力度的動(dòng)態(tài)污點(diǎn)分析方法,實(shí)驗(yàn)測試了6 款軟件,實(shí)例程序可控內(nèi)存寫檢測情況如表5 所示。從表5 可知,能夠有效檢測出6 款軟件的漏洞PoC 其中3 款具備可控內(nèi)存寫,3 款具備控制流劫持的情況,同只出現(xiàn)了PLC WinNT 的一處誤報(bào),該誤報(bào)符合文中所述的指針?biāo)饕m被污染但受約束情況,能夠被有效發(fā)現(xiàn)是誤報(bào),同時(shí)未出現(xiàn)漏報(bào)情況。
表5 實(shí)例程序可控內(nèi)存寫檢測情況
本節(jié)實(shí)驗(yàn)驗(yàn)證了基于污點(diǎn)分析進(jìn)行可控內(nèi)存寫漏洞檢測的有效性,針對CTF 類型的小程序只需采用傳統(tǒng)的污點(diǎn)傳播規(guī)則,針對真實(shí)的復(fù)雜程序傳統(tǒng)的污點(diǎn)傳播規(guī)則會出現(xiàn)誤報(bào),本文提出的內(nèi)存地址控制力度動(dòng)態(tài)污點(diǎn)分析方法能夠有效消除誤報(bào),同時(shí)結(jié)合上下文約束條件能夠有效發(fā)現(xiàn)誤報(bào)情況。
本文實(shí)現(xiàn)了可控內(nèi)存寫漏洞函數(shù)指針及函數(shù)表利用要素的字段搜索和篩選。基于動(dòng)態(tài)內(nèi)存頁分析提取內(nèi)存頁讀寫執(zhí)行權(quán)限屬性,基于動(dòng)態(tài)指令分析監(jiān)測函數(shù)指針及跳轉(zhuǎn)表的引用情況,統(tǒng)計(jì)出其中潛在引用可能的函數(shù)表屬性情況,包括函數(shù)表不可寫數(shù)量、函數(shù)表可寫數(shù)量、函數(shù)表地址未隨機(jī)且可寫的數(shù)量。
結(jié)合靜態(tài)分析提取malloc 和free 函數(shù)中潛在的hook 函數(shù)指針作為注入點(diǎn),搜索統(tǒng)計(jì)了50 個(gè)測試用例的函數(shù)表要素情況。CTF 測試集函數(shù)指針利用要素統(tǒng)計(jì)情況如圖10 所示,48 個(gè)用例都存在函數(shù)指針利用要素,僅pwn34 和pwn45 這2 個(gè)測試用例未發(fā)現(xiàn)函數(shù)指針利用要素。
圖10 CTF 測試集函數(shù)指針利用要素統(tǒng)計(jì)情況
本文搜索統(tǒng)計(jì)了6 款實(shí)例程序漏洞利用函數(shù)表要素提取情況,如表6 所示。其中,UW 表示不可寫函數(shù)表數(shù)量,AW 表示可寫函數(shù)表數(shù)量,UAW 表示地址未隨機(jī)且可寫的函數(shù)表數(shù)量。通過統(tǒng)計(jì)可以發(fā)現(xiàn),大型程序中函數(shù)表的使用很普遍,其中可改寫的函數(shù)表也占用了一定比例,這是由于C++程序使用虛函數(shù)指針,是不可避免的,地址隨機(jī)化一定程度上緩解了函數(shù)指針被定位的問題,但是通過本文的搜索發(fā)現(xiàn)仍然有很多程序和模塊未使用地址隨機(jī)化對程序進(jìn)行保護(hù),因此本文仍能在測試用例中搜索出未隨機(jī)化的可改寫的函數(shù)表。
表6 實(shí)例程序漏洞利用函數(shù)表要素提取情況
此外,通過實(shí)驗(yàn)統(tǒng)計(jì)的原始數(shù)據(jù),本文還發(fā)現(xiàn)同一位置指令存在多次執(zhí)行的情況,多次執(zhí)行引用的內(nèi)存表地址可能相同也可能不同,例如call [ebp+0x8]指令,多次執(zhí)行到該位置時(shí),由于ebp 值的差異使引用的函數(shù)表位置不一致。針對引用相同位置的情況,統(tǒng)計(jì)進(jìn)行了去重;針對引用不同位置的情況,統(tǒng)計(jì)進(jìn)行了累加計(jì)算。另外,如果是不同位置引用了同一位置的函數(shù)表,統(tǒng)計(jì)也按照去重的方式進(jìn)行處理,這是因?yàn)楸疚囊允占瘮?shù)表利用要素為導(dǎo)向,相同位置的函數(shù)表只能作為利用要素的一個(gè)原子。
針對50 個(gè)測試用例中通過指令或函數(shù)判定為存在可控內(nèi)存寫能力漏洞的20 個(gè)測試用例,本文基于函數(shù)利用要素的搜索獲得需要寫入的地址,通過可控內(nèi)存寫判定時(shí)的污點(diǎn)數(shù)據(jù)關(guān)系自動(dòng)生成約束求解條件,并進(jìn)行約束求解。可控內(nèi)碼寫漏洞利用生成情況如表7 所示。
表7 可控內(nèi)存寫漏洞利用生成情況
利用點(diǎn)標(biāo)記了生成過程中選取的寫入內(nèi)存地址,構(gòu)造情況記錄了利用生成達(dá)到的效果。表7 中的利用生成存在1 個(gè)ret 劫持,這是通過控制地址的棧偏移指針,構(gòu)造覆蓋函數(shù)返回地址實(shí)現(xiàn)ret 控制流劫持;11 個(gè)call 劫持有9 個(gè)是通過絕對地址進(jìn)行定位覆蓋free 函數(shù)的hook 點(diǎn)構(gòu)造控制流劫持,剩下的2 個(gè)(pwn39,pwn46)是覆蓋了程序自定義的函數(shù)指針實(shí)現(xiàn)劫持。構(gòu)造失敗的用例情況包括:1)可控內(nèi)存寫指令每次只覆蓋1 byte,需要多次構(gòu)造可控內(nèi)存寫,自動(dòng)化構(gòu)造失?。?)需要輸入負(fù)整數(shù)經(jīng)atoi 變換后溢出,自動(dòng)求解失敗;3)程序是多進(jìn)程,分析框架支持能力受限。
另外,針對PLC WinNT 實(shí)例程序中的81 個(gè)可寫函數(shù)表,本文搜索篩選出了觸發(fā)可控內(nèi)存寫后潛在的42 個(gè)引用點(diǎn),其中38 個(gè)是通過call 內(nèi)存模式,包括call [IMM]類型和call [eax+IMM]類型,4 個(gè)是通過jmp 內(nèi)存模式,均為jmp [IMM]模式(IMM 指立即數(shù)常量);同時(shí),本文檢測出這些函數(shù)表和跳轉(zhuǎn)表是具備內(nèi)存寫權(quán)限的,能夠基于可控內(nèi)存寫的方式對其進(jìn)行篡改,從而構(gòu)造控制流劫持。通過利用生成,針對其中的35 個(gè)利用點(diǎn),成功觸發(fā)了控制流劫持,另外7 個(gè)未能觸發(fā)控制流劫持是由于地址是隨機(jī)的,無法在實(shí)際運(yùn)行過程定位絕對地址。
實(shí)驗(yàn)表明,本文提出的可控內(nèi)存寫漏洞自動(dòng)利用方法能夠有效基于可控地址寫構(gòu)造控制流劫持漏洞利用能力,50 個(gè)測試用例中,基于AFL 模糊測試挖掘的漏洞僅有22 個(gè)達(dá)到控制流劫持狀態(tài),通過本文方法增加了12 個(gè)達(dá)到控制流劫持狀態(tài),提升了54%。同時(shí),針對PLC WinNT 的可控地址寫漏洞,構(gòu)造了35 個(gè)不同位置的控制流劫持,驗(yàn)證了本文方法在實(shí)際漏洞程序中的有效性。
本文提出的可控內(nèi)存寫漏洞自動(dòng)利用生成方法針對觸發(fā)可控內(nèi)存寫漏洞樣本,構(gòu)造能夠觸發(fā)控制流劫持的PoC,進(jìn)一步提升驗(yàn)證了漏洞的破壞能力。而Mayhem 與PolyAEG 的相關(guān)工作僅支持控制流劫持類型的漏洞,在PoC 未達(dá)到控制流劫持狀態(tài)情況下是失效的。本文方法利用通過可控內(nèi)存寫漏洞的自動(dòng)判定、漏洞利用要素的自動(dòng)搜索和約束條件的自動(dòng)提取與求解實(shí)現(xiàn)利用樣本自動(dòng)生成,補(bǔ)充了現(xiàn)有AEG 方案的不足。
本文提出了內(nèi)存地址控制力度的動(dòng)態(tài)污點(diǎn)分析方法,與libdft、Triton、Decaf 等污點(diǎn)分析方法相比,對污點(diǎn)傳播規(guī)則進(jìn)行了適配性的優(yōu)化改進(jìn),消除了可控內(nèi)存寫漏洞判定的大量誤報(bào)情況,而傳統(tǒng)的污點(diǎn)傳播規(guī)則帶來的大量誤報(bào)會導(dǎo)致指令級的檢測無法正常使用。同時(shí),本文方法也具備多標(biāo)簽污點(diǎn)標(biāo)記能力,能夠直接定位出輸入關(guān)聯(lián)的字節(jié)位置,服務(wù)于控制流劫持樣本的自動(dòng)構(gòu)造。
另外,本文總結(jié)了可控內(nèi)存寫漏洞利用的多種模式及相關(guān)要素,針對構(gòu)造控制流劫持的模式實(shí)現(xiàn)了漏洞利用函數(shù)表要素的自動(dòng)化搜索,通過指令記錄結(jié)合短距離污點(diǎn)分析的方式提取潛在可利用的函數(shù)表,同時(shí)基于內(nèi)存讀寫屬性篩選出其中可被改寫的函數(shù)表,又結(jié)合模塊地址隨機(jī)化屬性提取出其中的地址固定的部分,有效篩選出真正可被利用的函數(shù)表。針對指令記錄無法獲取的函數(shù)表,本文針對已知?jiǎng)討B(tài)庫中的代碼特征模式進(jìn)行特征搜索,提取了其中的一部分。但是,這類函數(shù)表的搜索提取并不完整,結(jié)合模糊測試挖掘更多的潛在路徑、提取更完整的利用要素將是后續(xù)的研究點(diǎn)。
本文提出的可控內(nèi)存寫漏洞自動(dòng)利用生成方法僅針對Linux 和Windows 用戶態(tài)程序?qū)崿F(xiàn)了原型系統(tǒng),研究表明可控內(nèi)存寫漏洞在內(nèi)核漏洞中頻繁出現(xiàn),且具有很強(qiáng)的破壞能力,本文方法在內(nèi)核漏洞的應(yīng)用和推廣也將作為后續(xù)的研究點(diǎn)。
本文提出了一種可控內(nèi)存寫漏洞的自動(dòng)利用生成方法,基于內(nèi)存地址控制力度的動(dòng)態(tài)污點(diǎn)分析方法從指令和函數(shù)層面識別判定可控內(nèi)存寫漏洞,結(jié)合動(dòng)態(tài)插樁分析提取構(gòu)造控制流劫持漏洞利用的要素,通過污點(diǎn)分析關(guān)聯(lián)的漏洞點(diǎn)自動(dòng)提取漏洞利用生成的約束條件,最后自動(dòng)進(jìn)行約束求解生成利用樣本。通過對50 個(gè)測試用例和PLC等實(shí)例程序進(jìn)行測試評估,驗(yàn)證了本文方法的有效性,生成利用樣本達(dá)到控制流劫持能力的數(shù)量比模糊測試提升了54%,提升了漏洞的可利用性評估能力。