◆陳煒昊 于子洋
針對(duì)Windows下閉源二進(jìn)制可執(zhí)行文件熱補(bǔ)丁的研究
◆陳煒昊 于子洋
(中國(guó)礦業(yè)大學(xué) 計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院 江蘇 221116)
隨著計(jì)算機(jī)科學(xué)技術(shù)的飛速發(fā)展,越來(lái)越多的廠商與作者為保護(hù)程序算法知識(shí)產(chǎn)權(quán),選擇將自己的代碼程序以閉源的形式發(fā)布,導(dǎo)致很多閉源軟件存在不同程度的安全問(wèn)題。如何對(duì)已經(jīng)產(chǎn)生安全事件的閉源二進(jìn)制文件進(jìn)行修復(fù)已逐漸成了安全應(yīng)用的重要課題,本文就此問(wèn)題進(jìn)行探討,以Windows x86架構(gòu)為框架,詳細(xì)分析了文件靜態(tài)補(bǔ)丁技術(shù)的可行性,并給出了針對(duì)此問(wèn)題的基本解決方案,最終達(dá)到在無(wú)源碼的情況下對(duì)文件漏洞修復(fù)的目的。
Windows x86;相對(duì)虛擬地址;動(dòng)態(tài)鏈接庫(kù)
隨著計(jì)算機(jī)信息技術(shù)的快速發(fā)展,各行各業(yè)的人都加入了軟件開(kāi)發(fā)的行列,他們會(huì)將自己的專(zhuān)業(yè)知識(shí)封裝成各種各樣的軟件,供有需求的人們?nèi)ナ褂?。開(kāi)發(fā)出來(lái)的軟件主要分為兩種:開(kāi)源軟件與閉源軟件。閉源軟件無(wú)法在源代碼的層級(jí)上對(duì)程序進(jìn)行修改,刪除,更新等操作。由于開(kāi)發(fā)人員沒(méi)有接觸過(guò)系統(tǒng)的安全教育以及如何進(jìn)行底層CVE的發(fā)掘,導(dǎo)致大多數(shù)的閉源軟件都存在安全隱患。主要包括危險(xiǎn)函數(shù)的誤用導(dǎo)致的棧溢出、內(nèi)存管理釋放部分缺失導(dǎo)致的堆溢出等隱患。
本文主要是對(duì)Windows下閉源二進(jìn)制可執(zhí)行文件的修補(bǔ)方法進(jìn)行研究,目的是修復(fù)無(wú)人維護(hù)的閉源軟件的安全問(wèn)題和在官方未發(fā)布補(bǔ)丁時(shí)的1Day漏洞。
Windows自帶的的可執(zhí)行文件格式是PE文件格式。PE文件中的內(nèi)容會(huì)被劃分成一個(gè)個(gè)小塊,這一個(gè)個(gè)小塊就是Section(節(jié))。Windows可執(zhí)行程序擁有一個(gè)獨(dú)特的機(jī)制--導(dǎo)入表與導(dǎo)出表。導(dǎo)入表與導(dǎo)出表中保存了PE文件中調(diào)用的所有動(dòng)態(tài)鏈接庫(kù)的函數(shù),以及這些函數(shù)來(lái)自哪些動(dòng)態(tài)鏈接庫(kù)。Windows加載器在運(yùn)行PE時(shí)會(huì)將導(dǎo)入表中聲明的動(dòng)態(tài)鏈接庫(kù)一并加載到進(jìn)程的地址空間,并修正指令代碼中調(diào)用的函數(shù)地址。這個(gè)機(jī)制的存在保證了PE文件中的函數(shù)可以被重復(fù)調(diào)用。導(dǎo)入表與導(dǎo)出表機(jī)制決定了本小節(jié)需要分為以下兩種情況加以討論。
PE文件的導(dǎo)入表與導(dǎo)出表中存在相應(yīng)函數(shù),可以直接對(duì)函數(shù)進(jìn)行調(diào)用,對(duì)更加安全的函數(shù)進(jìn)行重復(fù)調(diào)用。在可執(zhí)行文件調(diào)用了危險(xiǎn)函數(shù)時(shí),可以直接在原text段進(jìn)行匯編的修改從而達(dá)到修復(fù)程序的目的。由于不同的函數(shù)有不同的參數(shù)個(gè)數(shù)種類(lèi)等獨(dú)特的用法,所以一般情況下需要對(duì)函數(shù)前后的調(diào)用進(jìn)行部分調(diào)整。比如程序中調(diào)用了一個(gè)gets函數(shù),這個(gè)函數(shù)會(huì)導(dǎo)致堆棧的溢出,為程序帶來(lái)不可控的風(fēng)險(xiǎn)。而程序?qū)氡砼c導(dǎo)出表中加載了read函數(shù),此時(shí)需要使用read函數(shù)替換gets函數(shù)。對(duì)比兩個(gè)函數(shù)原型,可知兩個(gè)函數(shù)的調(diào)用參數(shù)不同,所以不可以直接進(jìn)行簡(jiǎn)單的替換,需要對(duì)函數(shù)傳遞進(jìn)行適當(dāng)?shù)恼{(diào)整。在調(diào)整部分參數(shù)后,才可以使用read函數(shù)對(duì)gets函數(shù)進(jìn)行整體替換。
對(duì)于導(dǎo)入表和導(dǎo)出表未加載同類(lèi)型可替換的函數(shù),一般在不借助其他方法的情況下,只能進(jìn)行小修小改。危險(xiǎn)函數(shù)在沒(méi)有同等功能的其他函數(shù)可以進(jìn)行替換的情況下,只能對(duì)本身已有函數(shù)的參數(shù)進(jìn)行修改,使其盡可能安全可靠。比如printf函數(shù)沒(méi)有使用規(guī)范的格式化字符會(huì)導(dǎo)致格式化字符串的漏洞,從而泄露棧中敏感信息。修復(fù)printf漏洞時(shí)可以在參數(shù)傳遞處加入相應(yīng)的格式化字符參數(shù),以提高整體程序的穩(wěn)定性。相似的漏洞還有read函數(shù)造成的單字節(jié)溢出等漏洞。
本小節(jié)主要針對(duì)一些特定的函數(shù)修復(fù),這些函數(shù)通常自身存在一些安全隱患,但是功能比較簡(jiǎn)單,一般可以直接通過(guò)幾條簡(jiǎn)單的匯編語(yǔ)言函數(shù)功能重現(xiàn)。比如stcopy函數(shù),它在程序中很容易產(chǎn)生棧溢出漏洞,本節(jié)就將以它作為例子簡(jiǎn)述函數(shù)的匯編代碼重寫(xiě)方法。雖然Microsoft提供了更安全的strcpy_s()函數(shù)供編程人員調(diào)用,但是一些老舊程序并沒(méi)有載入這個(gè)函數(shù),所以不能采取上節(jié)中的方法對(duì)stcopy函數(shù)進(jìn)行直接替換。所以為了讓程序正常工作并不引發(fā)錯(cuò)誤,需要對(duì)函數(shù)進(jìn)行重寫(xiě)以實(shí)現(xiàn)拷貝的功能??截惡瘮?shù)重寫(xiě)如圖1。
圖1 拷貝函數(shù)重寫(xiě)
重寫(xiě)函數(shù)匯編字節(jié)碼字節(jié)數(shù)往往會(huì)多于原函數(shù),額外空間的獲取就成了研究的關(guān)鍵。本節(jié)主要探討兩種獲取額外空間的方法,通過(guò)同義指令替換獲得額外空間與額外添加新段區(qū)。
由于編譯器的原因,每一個(gè)PE文件都會(huì)出現(xiàn)一些不那么簡(jiǎn)潔的匯編指令。如moveax,0等需要傳遞常數(shù)的匯編指令,這類(lèi)指令一般可以被簡(jiǎn)化修改為xoreax,eax,進(jìn)而為整個(gè)二進(jìn)制文件節(jié)省出空間以便于插入補(bǔ)丁。
在所需空間很大的情況下,可以考慮為程序添加新的段區(qū)。新添段區(qū)的一般需要三步,首先需要PE頭部增添塊頭,其次為添加的區(qū)塊頭添加數(shù)據(jù)段,最后修正映像文件即可。這種方法可以為PE文件快速創(chuàng)建一個(gè)空的區(qū)塊段,以便填入補(bǔ)丁代碼,更改程序流程。
當(dāng)補(bǔ)丁代碼過(guò)于復(fù)雜時(shí),可以通過(guò)編寫(xiě)第三方dll并將動(dòng)態(tài)鏈接庫(kù)注入二進(jìn)制文件中的方式來(lái)替換危險(xiǎn)函數(shù)?;咀⑷肓鞒倘鐖D2所示。
程序調(diào)用動(dòng)態(tài)鏈接庫(kù)需要先使用LoadLibrary函數(shù)對(duì)指定的動(dòng)態(tài)鏈接庫(kù)進(jìn)行加載,然后再使用GetProcAddress獲取目標(biāo)鏈接庫(kù)中相關(guān)函數(shù)的地址。這兩個(gè)函數(shù)存在于Kernel32.dll中,絕大多數(shù)Windows程序都會(huì)加載ntdll.dll和kernel32.dll,故我們首先獲取kernel32.dll的基址,相關(guān)匯編代碼如圖3所示。
圖2 基本注入流程
圖3 相關(guān)匯編代碼
圖4 完成函數(shù)的調(diào)用
由于函數(shù)名字換算成ASCII碼后會(huì)占用比較大的空間,這里采用hash的方式對(duì)目標(biāo)函數(shù)進(jìn)行查找,在成功加載動(dòng)態(tài)鏈接庫(kù)并獲取函數(shù)的地址后,就可以直接對(duì)函數(shù)進(jìn)行調(diào)用了。在目標(biāo)調(diào)用處插入調(diào)用代碼,即可完成函數(shù)的調(diào)用,如圖4。
將上述匯編編譯成二進(jìn)制字節(jié)碼后,就可對(duì)目標(biāo)程序進(jìn)行注入,方法與第二三小節(jié)基本相同,在函數(shù)擁有足夠的空間時(shí),可選擇在源碼處進(jìn)行動(dòng)態(tài)鏈接庫(kù)的加載和函數(shù)的調(diào)用,空間不足時(shí),可為程序添加必要的段區(qū)。
本文主要探討了有關(guān)閉源二進(jìn)制可執(zhí)行文件的靜態(tài)補(bǔ)丁的基本理論方法,主要應(yīng)用于未加密Windows x86的可執(zhí)行文件。對(duì)于動(dòng)態(tài)加密,程序的自校驗(yàn)程序還需要做進(jìn)一步的研究。
[1]何迎生,段明秀. 32位Windows系統(tǒng)下的PE文件結(jié)構(gòu)及其應(yīng)用[J]. 吉首大學(xué)學(xué)報(bào)(自然科學(xué)版),2003(01).
[2]劉科. 計(jì)算機(jī)科學(xué)技術(shù)的發(fā)展現(xiàn)狀及發(fā)展趨勢(shì)展望 [J]. 信息記錄材料,2020,21(07).
[3]昝道廣. 計(jì)算機(jī)科學(xué)技術(shù)的應(yīng)用現(xiàn)狀及其發(fā)展前景探析 [J]. 通訊世界,2017(6):133.
[4]李晨燕. 計(jì)算機(jī)網(wǎng)絡(luò)信息安全問(wèn)題策略探討[J]. 電子世界,2020(24).
[5]王眾魁. 探索計(jì)算機(jī)信息網(wǎng)絡(luò)安全技術(shù)及發(fā)展方向[J].電腦知識(shí)與技術(shù),2021,17(08).
網(wǎng)絡(luò)安全技術(shù)與應(yīng)用2021年10期