秦?zé)ㄇ啵?劉 敏, 馬劉杰
(1.上海航天計算機技術(shù)研究所,上海200050;2.中遠海運科技股份有限公司,上海200135;3.中天安泰(北京)信息技術(shù)有限公司,北京100040)
隨著計算機技術(shù)和信息技術(shù)的快速發(fā)展,信息網(wǎng)絡(luò)遭受到的攻擊越來越多,計算機安全問題越來越來突出。近30 a來,對內(nèi)存進行攻擊的手段(包括內(nèi)存溢出、內(nèi)存破壞和內(nèi)存重用等)層出不窮,其中內(nèi)存溢出已是軟件開發(fā)方面的難題,是黑客攻擊企業(yè)網(wǎng)絡(luò)的重要手段。據(jù)統(tǒng)計[1],有將近50%的安全漏洞都是由內(nèi)存溢出引起的。在內(nèi)存破壞類攻擊中,最主要的是HOOK類動態(tài)內(nèi)存破壞攻擊,攻擊者通過在內(nèi)存中執(zhí)行代碼段進行掛鉤注入shellcode,從而使計算機在執(zhí)行被修改的代碼時執(zhí)行惡意代碼,達到攻擊目標(biāo)的目的,該類攻擊已成為攻擊操作系統(tǒng)的重要手段。
為應(yīng)對內(nèi)存攻擊問題,相關(guān)人員研究出多種防御手段。例如:針對內(nèi)存溢出類攻擊[2],一般采用“在非運行時檢測緩沖區(qū)溢出漏洞,在運行時檢測是否發(fā)生溢出漏洞”的方式,但在非運行時無法檢測到所有可能的溢出漏洞,在運行時采用的被動防護(插入canary值、存儲Retaddr值、指針前后加guardzone、低脂指針等)和主動防護(更換動態(tài)鏈接庫、加密指針型數(shù)據(jù)、隨機化內(nèi)存地址、去堆棧布局等)方式都沒有從根本上解決問題;針對內(nèi)存破壞類攻擊,只能被動地采用運行時防護的方式,一般的防護措施包括控制數(shù)據(jù)防護和非控制數(shù)據(jù)防護[3],該方式也沒有從根本上解決問題。
實質(zhì)上,無論是內(nèi)存溢出類攻擊還是內(nèi)存破壞類攻擊,在本質(zhì)上都是通過中央處理器(Central Processing Unit,CPU)中的內(nèi)存操作指令對本來不允許操作和修改的內(nèi)存進行操作和修改。例如:內(nèi)存溢出類攻擊是通過修改非本函數(shù)能修改的堆棧內(nèi)存進行內(nèi)存修改;內(nèi)存破壞類攻擊是通過直接或間接修改內(nèi)存進行內(nèi)存修改。因此,若能實時獲取針對內(nèi)存操作和修改的指令,并對指令操作數(shù)進行分析,即可有效解決上述內(nèi)存攻擊問題。
基于上述分析,本文提出一種新的解決辦法,利用“操作系統(tǒng)運行時會將內(nèi)存提交到CPU執(zhí)行,從而在提交前對提交的內(nèi)存指令進行分析”的理念,分析相關(guān)操作是否有對關(guān)鍵內(nèi)存進行篡改。通過試驗驗證本文提出的方法和機制對內(nèi)存破壞和內(nèi)存溢出行為進行防護的有效性,從而大大提高計算機的安全性。
本文提出的關(guān)鍵內(nèi)存防護機制總體架構(gòu)和基本設(shè)計思路見圖1。
首先根據(jù)系統(tǒng)的運行情況構(gòu)建程序的關(guān)鍵內(nèi)存保護區(qū)域,其程序運行分別包括但不限于PE文件的映射加載和映射卸載、可執(zhí)行代碼區(qū)域的分配和釋放、操作系統(tǒng)和應(yīng)用程序關(guān)鍵內(nèi)存區(qū)域的構(gòu)建等,將關(guān)鍵內(nèi)存擴展到可執(zhí)行內(nèi)存、系統(tǒng)和程序?qū)ν饨涌谖恢?、操?/p>
系統(tǒng)和程序的關(guān)鍵數(shù)據(jù)區(qū)域等,從而構(gòu)建一個完整的關(guān)鍵內(nèi)存保護區(qū)域,并根據(jù)系統(tǒng)的運行和程序的啟動與關(guān)閉自動改變關(guān)鍵內(nèi)存的保護區(qū)域。
同時,對將要執(zhí)行的代碼(準備提交給CPU執(zhí)行的代碼)進行動態(tài)的二進制翻譯,從而得到所有將要執(zhí)行的指令,并獲取讀寫內(nèi)存的指令和出棧入棧指令等關(guān)鍵指令。出棧入棧指令用來更新關(guān)鍵內(nèi)存中的棧保護區(qū)域,隨時刷新關(guān)鍵內(nèi)存的保護范圍,從而為防止棧溢出做準備。
當(dāng)準備提交的指令為寫內(nèi)存的指令時,判斷準備寫的內(nèi)存地址是否在關(guān)鍵內(nèi)存區(qū)域內(nèi)。若所要寫的指令在棧關(guān)鍵內(nèi)存區(qū)域內(nèi),則代表發(fā)生棧溢出攻擊;若所要寫的指令在其他關(guān)鍵內(nèi)存區(qū)域內(nèi),則代表發(fā)生內(nèi)存破壞(篡改)行為,此時通過修正將要執(zhí)行的代碼,在CPU執(zhí)行內(nèi)存溢出和內(nèi)存破壞行為之前阻止此類行為發(fā)生。
圖1 關(guān)鍵內(nèi)存防護機制總體架構(gòu)和基本設(shè)計思路
1.2.1 動態(tài)二進制翻譯與優(yōu)化技術(shù)
林洋扎根農(nóng)場十個春秋,攻堅克難,大膽改革,銳意進取,帶領(lǐng)云城乳業(yè)實現(xiàn)了轉(zhuǎn)型發(fā)展。多年來,他先后多次受到山西省農(nóng)墾局、大同市國資委的表彰,并當(dāng)選大同市第十四屆人大代表和大同市第十五屆政協(xié)委員。
動態(tài)二進制翻譯技術(shù)是一種對即將提交到CPU的指令進行即時反編譯和重新編譯的技術(shù)[4-5],用來獲取即將執(zhí)行的代碼塊中的讀寫指令和出棧入棧指令。
動態(tài)二進制翻譯技術(shù)需構(gòu)建翻譯引擎和執(zhí)行引擎。首先由翻譯引擎獲取將要執(zhí)行的代碼塊,通過反編譯將其解碼成指令,利用翻譯出來的指令獲取指令、指令操作數(shù)及待分析的讀寫內(nèi)存指令,并將編譯后的分析代碼加入到解碼后的指令塊中,從而形成新的指令塊。隨后將新的指令塊提交給CPU執(zhí)行,從而執(zhí)行翻譯和編譯后的代碼,當(dāng)準備提交下一個指令塊時,判斷新的指令塊是否為尚未翻譯的模塊,若是尚未翻譯的模塊,則進行翻譯、分析指令插入和編譯,從而形成新的指令塊并進行分析。此外,若新的已被翻譯的指令被頻繁執(zhí)行,則對其進行優(yōu)化。如此發(fā)展,即可使所有的指令均被翻譯、實時分析和優(yōu)化。
動態(tài)二進制翻譯可參照DigitalBridge設(shè)計方法[6]來設(shè)計,但本文僅在翻譯X86指令之后加入分析指令,且分析指令多為查表指令,因此效率更高。圖2為動態(tài)二進制翻譯設(shè)計思路。
圖2 動態(tài)二進制翻譯設(shè)計思路
1.2.2 關(guān)鍵內(nèi)存區(qū)域獲取技術(shù)
關(guān)鍵內(nèi)存區(qū)域獲取技術(shù)是指獲取要防護的關(guān)鍵內(nèi)存的技術(shù),本文主要依據(jù)可執(zhí)行文件加載到內(nèi)存中形成的映像得到關(guān)鍵內(nèi)存區(qū)域。首先獲取操作系統(tǒng)所有可執(zhí)行文件的加載過程和可執(zhí)行文件在內(nèi)存中的映像位置;隨后從映像中獲取導(dǎo)出代碼位置和可執(zhí)行的代碼,從而獲取到可執(zhí)行文件的內(nèi)存區(qū)域;同時,還需獲取操作系統(tǒng)卸載映像,并在卸載映像時準確獲取卸載的映像位置及對應(yīng)的區(qū)域,從而在關(guān)鍵內(nèi)存區(qū)域摘除該區(qū)域。
本文重點對Windows映像進行研究。在Windows操作系統(tǒng)中,可執(zhí)行文件是遵循Windows操作系統(tǒng)可執(zhí)行文件的格式存儲的。在計算機運行過程中,可執(zhí)行文件的映像根據(jù)需要進行加載,可通過二進制翻譯或其他方式獲取文件的映像加載。文件加載到內(nèi)存映像之后是線性連續(xù)的,加載的映像按照操作系統(tǒng)的頁表進行連續(xù)分配,在分配過程中確保可執(zhí)行代碼頁和數(shù)據(jù)頁是分離的。此時可對可執(zhí)行代碼頁和數(shù)據(jù)頁進行優(yōu)化,即在頁表中將可執(zhí)行代碼頁標(biāo)準化,確??蓤?zhí)行代碼能實時獲??;同時,獲取數(shù)據(jù)頁中關(guān)鍵內(nèi)存的存放區(qū)域,構(gòu)建關(guān)鍵內(nèi)存的區(qū)域存放,供后期檢查時獲取。通過二進制翻譯或其他方式,在內(nèi)存映像卸載時實時獲取,確保文件卸載之后關(guān)鍵區(qū)域也能實時變化,從而使后期的判斷不會失誤。具體方法見圖3。
圖3 關(guān)鍵內(nèi)存區(qū)域獲取設(shè)計基礎(chǔ)
1.2.3 棧內(nèi)存區(qū)域獲取技術(shù)
棧內(nèi)存區(qū)域獲取技術(shù)的主要設(shè)計思路是在動態(tài)二進制翻譯過程中獲取到實時棧區(qū)域的關(guān)鍵技術(shù)和睡眠線程棧獲取技術(shù)。該技術(shù)的主要實現(xiàn)方法是在動態(tài)二進制翻譯過程中獲取導(dǎo)致出棧入棧的指令,并通過在CPU中的棧頂和棧底位置獲取實時棧的位置及對棧頂位置進行標(biāo)記,使下次入棧時能實時獲取到上次的入棧位置及出棧后的返回位置,同時在每次入棧過程中和代碼指令執(zhí)行過程中不會出現(xiàn)修改此次入棧深度以外的棧數(shù)據(jù)的現(xiàn)象和在出棧過程中不會出現(xiàn)出棧改變的現(xiàn)象,因為出現(xiàn)這些現(xiàn)象代表發(fā)生棧溢出獲取棧偏移現(xiàn)象,因此通過該設(shè)計能使棧溢出或棧偏移時實時被捕捉和獲取。
為驗證上述設(shè)計思路的有效性,本文通過在Windows XP中的內(nèi)核上開展試驗,驗證通過動態(tài)二進制翻譯對關(guān)鍵內(nèi)存進行防護的有效性;同時,通過對二進制翻譯和關(guān)鍵內(nèi)存區(qū)域進行合理分配及對算法進行優(yōu)化,使整體思路對系統(tǒng)的影響保持在30%以內(nèi)。此外,通過病毒測試證明該方案對內(nèi)存溢出和內(nèi)存破壞攻擊具有很好的防護效果。試驗結(jié)果表明,該方案的設(shè)計思路可得到實現(xiàn)和推廣。
1.3.1 有效性評估
為驗證有效性,設(shè)置自主設(shè)計的棧溢出和內(nèi)存破壞類病毒、metasploit中的棧溢出和內(nèi)存破壞類病毒、學(xué)校病毒庫中的相關(guān)病毒及其他有好單位的病毒庫中的相關(guān)病毒進行測試。測試結(jié)果表明,可檢測到溢出和破壞類病毒的比例達到90%以上,可有效實時阻止的病毒也達到60%以上,且大部分病毒得以阻止是由于檢測之后因阻止病毒而造成系統(tǒng)奔潰。
1.3.2 性能評估
該方案的設(shè)計開銷主要在動態(tài)二進制翻譯和大量的內(nèi)存區(qū)域比較上,通常動態(tài)二進制并加入分析代碼會造成效率降低5%~15%,內(nèi)存區(qū)域比較會造成效率降低約15%,因此可通過對動態(tài)二進制翻譯作進一步優(yōu)化,或直接在CPU內(nèi)進行分析,使損失效率降到5%左右,甚至在2%以內(nèi)(該損失效率是在與相關(guān)CPU設(shè)計人員和設(shè)計單位討論損失后得出的)。比較效率若能通過算法進行優(yōu)化(例如利用特征值比較等),亦能得到一定的提高。此外,若能對內(nèi)存的分配處理進行優(yōu)化,確保關(guān)鍵內(nèi)存區(qū)域的物理連續(xù)性,將能帶來飛躍級別的性能提升,但該方法需在能對源碼進行控制的操作系統(tǒng)上實現(xiàn)。
本文通過對內(nèi)存溢出和內(nèi)存破壞的本質(zhì)原因進行深入分析和研究,提出一種新的關(guān)鍵內(nèi)存防護思路和方法。通過對操作內(nèi)存的指令進行分析,辨別出針對內(nèi)存溢出和關(guān)鍵內(nèi)存破壞的指令并對其進行修改,從而阻止內(nèi)存溢出和內(nèi)存破壞的發(fā)生。同時,在Windows操作系統(tǒng)上對該方案進行測試,結(jié)果表明,本文設(shè)計的方案能有效識別和阻止相關(guān)類型的病毒攻擊,具有較高的實用價值。