秦煥青, 劉 敏, 馬劉杰
(1.上海航天計算機技術研究所,上海200050;2.中遠海運科技股份有限公司,上海200135;3.中天安泰(北京)信息技術有限公司,北京100040)
隨著計算機技術和信息技術的快速發展,信息網絡遭受到的攻擊越來越多,計算機安全問題越來越來突出。近30 a來,對內存進行攻擊的手段(包括內存溢出、內存破壞和內存重用等)層出不窮,其中內存溢出已是軟件開發方面的難題,是黑客攻擊企業網絡的重要手段。據統計[1],有將近50%的安全漏洞都是由內存溢出引起的。在內存破壞類攻擊中,最主要的是HOOK類動態內存破壞攻擊,攻擊者通過在內存中執行代碼段進行掛鉤注入shellcode,從而使計算機在執行被修改的代碼時執行惡意代碼,達到攻擊目標的目的,該類攻擊已成為攻擊操作系統的重要手段。
為應對內存攻擊問題,相關人員研究出多種防御手段。例如:針對內存溢出類攻擊[2],一般采用“在非運行時檢測緩沖區溢出漏洞,在運行時檢測是否發生溢出漏洞”的方式,但在非運行時無法檢測到所有可能的溢出漏洞,在運行時采用的被動防護(插入canary值、存儲Retaddr值、指針前后加guardzone、低脂指針等)和主動防護(更換動態鏈接庫、加密指針型數據、隨機化內存地址、去堆棧布局等)方式都沒有從根本上解決問題;針對內存破壞類攻擊,只能被動地采用運行時防護的方式,一般的防護措施包括控制數據防護和非控制數據防護[3],該方式也沒有從根本上解決問題。
實質上,無論是內存溢出類攻擊還是內存破壞類攻擊,在本質上都是通過中央處理器(Central Processing Unit,CPU)中的內存操作指令對本來不允許操作和修改的內存進行操作和修改。例如:內存溢出類攻擊是通過修改非本函數能修改的堆棧內存進行內存修改;內存破壞類攻擊是通過直接或間接修改內存進行內存修改。因此,若能實時獲取針對內存操作和修改的指令,并對指令操作數進行分析,即可有效解決上述內存攻擊問題。
基于上述分析,本文提出一種新的解決辦法,利用“操作系統運行時會將內存提交到CPU執行,從而在提交前對提交的內存指令進行分析”的理念,分析相關操作是否有對關鍵內存進行篡改。通過試驗驗證本文提出的方法和機制對內存破壞和內存溢出行為進行防護的有效性,從而大大提高計算機的安全性。
本文提出的關鍵內存防護機制總體架構和基本設計思路見圖1。
首先根據系統的運行情況構建程序的關鍵內存保護區域,其程序運行分別包括但不限于PE文件的映射加載和映射卸載、可執行代碼區域的分配和釋放、操作系統和應用程序關鍵內存區域的構建等,將關鍵內存擴展到可執行內存、系統和程序對外接口位置、操作
系統和程序的關鍵數據區域等,從而構建一個完整的關鍵內存保護區域,并根據系統的運行和程序的啟動與關閉自動改變關鍵內存的保護區域。
同時,對將要執行的代碼(準備提交給CPU執行的代碼)進行動態的二進制翻譯,從而得到所有將要執行的指令,并獲取讀寫內存的指令和出棧入棧指令等關鍵指令。出棧入棧指令用來更新關鍵內存中的棧保護區域,隨時刷新關鍵內存的保護范圍,從而為防止棧溢出做準備。
當準備提交的指令為寫內存的指令時,判斷準備寫的內存地址是否在關鍵內存區域內。若所要寫的指令在棧關鍵內存區域內,則代表發生棧溢出攻擊;若所要寫的指令在其他關鍵內存區域內,則代表發生內存破壞(篡改)行為,此時通過修正將要執行的代碼,在CPU執行內存溢出和內存破壞行為之前阻止此類行為發生。

圖1 關鍵內存防護機制總體架構和基本設計思路
1.2.1 動態二進制翻譯與優化技術
林洋扎根農場十個春秋,攻堅克難,大膽改革,銳意進取,帶領云城乳業實現了轉型發展。多年來,他先后多次受到山西省農墾局、大同市國資委的表彰,并當選大同市第十四屆人大代表和大同市第十五屆政協委員。
動態二進制翻譯技術是一種對即將提交到CPU的指令進行即時反編譯和重新編譯的技術[4-5],用來獲取即將執行的代碼塊中的讀寫指令和出棧入棧指令。
動態二進制翻譯技術需構建翻譯引擎和執行引擎。首先由翻譯引擎獲取將要執行的代碼塊,通過反編譯將其解碼成指令,利用翻譯出來的指令獲取指令、指令操作數及待分析的讀寫內存指令,并將編譯后的分析代碼加入到解碼后的指令塊中,從而形成新的指令塊。隨后將新的指令塊提交給CPU執行,從而執行翻譯和編譯后的代碼,當準備提交下一個指令塊時,判斷新的指令塊是否為尚未翻譯的模塊,若是尚未翻譯的模塊,則進行翻譯、分析指令插入和編譯,從而形成新的指令塊并進行分析。此外,若新的已被翻譯的指令被頻繁執行,則對其進行優化。如此發展,即可使所有的指令均被翻譯、實時分析和優化。
動態二進制翻譯可參照DigitalBridge設計方法[6]來設計,但本文僅在翻譯X86指令之后加入分析指令,且分析指令多為查表指令,因此效率更高。圖2為動態二進制翻譯設計思路。

圖2 動態二進制翻譯設計思路
1.2.2 關鍵內存區域獲取技術
關鍵內存區域獲取技術是指獲取要防護的關鍵內存的技術,本文主要依據可執行文件加載到內存中形成的映像得到關鍵內存區域。首先獲取操作系統所有可執行文件的加載過程和可執行文件在內存中的映像位置;隨后從映像中獲取導出代碼位置和可執行的代碼,從而獲取到可執行文件的內存區域;同時,還需獲取操作系統卸載映像,并在卸載映像時準確獲取卸載的映像位置及對應的區域,從而在關鍵內存區域摘除該區域。
本文重點對Windows映像進行研究。在Windows操作系統中,可執行文件是遵循Windows操作系統可執行文件的格式存儲的。在計算機運行過程中,可執行文件的映像根據需要進行加載,可通過二進制翻譯或其他方式獲取文件的映像加載。文件加載到內存映像之后是線性連續的,加載的映像按照操作系統的頁表進行連續分配,在分配過程中確保可執行代碼頁和數據頁是分離的。此時可對可執行代碼頁和數據頁進行優化,即在頁表中將可執行代碼頁標準化,確保可執行代碼能實時獲取;同時,獲取數據頁中關鍵內存的存放區域,構建關鍵內存的區域存放,供后期檢查時獲取。通過二進制翻譯或其他方式,在內存映像卸載時實時獲取,確保文件卸載之后關鍵區域也能實時變化,從而使后期的判斷不會失誤。具體方法見圖3。

圖3 關鍵內存區域獲取設計基礎
1.2.3 棧內存區域獲取技術
棧內存區域獲取技術的主要設計思路是在動態二進制翻譯過程中獲取到實時棧區域的關鍵技術和睡眠線程棧獲取技術。該技術的主要實現方法是在動態二進制翻譯過程中獲取導致出棧入棧的指令,并通過在CPU中的棧頂和棧底位置獲取實時棧的位置及對棧頂位置進行標記,使下次入棧時能實時獲取到上次的入棧位置及出棧后的返回位置,同時在每次入棧過程中和代碼指令執行過程中不會出現修改此次入棧深度以外的棧數據的現象和在出棧過程中不會出現出棧改變的現象,因為出現這些現象代表發生棧溢出獲取棧偏移現象,因此通過該設計能使棧溢出或棧偏移時實時被捕捉和獲取。
為驗證上述設計思路的有效性,本文通過在Windows XP中的內核上開展試驗,驗證通過動態二進制翻譯對關鍵內存進行防護的有效性;同時,通過對二進制翻譯和關鍵內存區域進行合理分配及對算法進行優化,使整體思路對系統的影響保持在30%以內。此外,通過病毒測試證明該方案對內存溢出和內存破壞攻擊具有很好的防護效果。試驗結果表明,該方案的設計思路可得到實現和推廣。
1.3.1 有效性評估
為驗證有效性,設置自主設計的棧溢出和內存破壞類病毒、metasploit中的棧溢出和內存破壞類病毒、學校病毒庫中的相關病毒及其他有好單位的病毒庫中的相關病毒進行測試。測試結果表明,可檢測到溢出和破壞類病毒的比例達到90%以上,可有效實時阻止的病毒也達到60%以上,且大部分病毒得以阻止是由于檢測之后因阻止病毒而造成系統奔潰。
1.3.2 性能評估
該方案的設計開銷主要在動態二進制翻譯和大量的內存區域比較上,通常動態二進制并加入分析代碼會造成效率降低5%~15%,內存區域比較會造成效率降低約15%,因此可通過對動態二進制翻譯作進一步優化,或直接在CPU內進行分析,使損失效率降到5%左右,甚至在2%以內(該損失效率是在與相關CPU設計人員和設計單位討論損失后得出的)。比較效率若能通過算法進行優化(例如利用特征值比較等),亦能得到一定的提高。此外,若能對內存的分配處理進行優化,確保關鍵內存區域的物理連續性,將能帶來飛躍級別的性能提升,但該方法需在能對源碼進行控制的操作系統上實現。
本文通過對內存溢出和內存破壞的本質原因進行深入分析和研究,提出一種新的關鍵內存防護思路和方法。通過對操作內存的指令進行分析,辨別出針對內存溢出和關鍵內存破壞的指令并對其進行修改,從而阻止內存溢出和內存破壞的發生。同時,在Windows操作系統上對該方案進行測試,結果表明,本文設計的方案能有效識別和阻止相關類型的病毒攻擊,具有較高的實用價值。