Heap Spray:高危漏洞的墊腳石

網絡***已經成爲當今網絡世界裏最大的危害,而它們的散播源,則來自各個知名或不知名的網站,經由網頁瀏覽器破窗而入,悄悄地在受害者的系統裏紮根潛伏,最終給受害者帶來一定的損失,這是一種幾乎無法完全防禦的瘟疫。

裝上金山網盾以後,小茹突然發現網絡世界是多麼的危險。僅在短短十分鐘的時間裏,金山網盾就已經彈出了三十幾次網頁***報警窗口。最令她奇怪的是,她剛纔只不過是查了一些有關會計的數據資料而已,而且那些網站看起來也都很正常。
因此,小茹也沒有過於在意,將報警窗口關閉後就繼續做自己的事情了。
幾天過後,小茹已經對時不時彈出來的***攔截警告框見怪不怪了。但是一個頻繁出現的詞語卻還是在她心裏留下了深刻印象。在***攔截警告裏經常會出現“發現iexplore.exe試圖觸發Heap Spray漏洞,已被成功阻止!”的字樣。
什麼是“Heap Spray”?小茹查了很多網站,卻只找到一些已經被公開了技術細節的過時網頁***源代碼,一番搜索下來,這個詞組反而越發神祕了……我們可以通過詞典查到“Heap”是“堆”的意思。那麼,“堆”是什麼呢?“Heap Spray”又到底是什麼呢?
“堆”(Heap)經常與“棧”(Stack)同時出現,很多技術人員也都習慣於將這兩者連起來讀作“堆棧”,實際上它們卻是兩種不同的概念。在信息安全和編程方面,除非特別指明是代表“數據結構”,否則大家提到的“堆”和“棧”,實際上都是指操作系統對內存管理實現的兩種不同分配形式。
 

棧:後進先出

heap spray無論是數據結構領域還是內存分配方面,對於“棧”(Stack)的結構描述和用法都是很類似的。它是一種只能在某一端插入和刪除數據的特殊線性表。你可以把棧想象成筒裝“品客”薯片,這個長筒一端封口一端開口,當這個長筒裏沒有數據時,我們稱之爲“空棧”。長筒在流水線上被一片片的薯片填滿的過程稱爲“進棧”(PUSH),在操作系統裏,表示將一定的數據填進棧結構裏。從這樣的結構裏我們不難看出,當你要從棧裏取數據時,你是隻能從最後一片薯片開始取的,而不能一開始就指定了要取位於筒底的第一片薯片,你也不能任意打亂它們的排列順序,而只能老老實實的從最後一片開始取到最早放進去的那一片,這就是“後進先出”,而取數據的過程,被稱爲“退棧”(POP)。
棧在系統裏通常由操作系統自己分配,用於儲存局部變量、函數所需的參數等。在Windows系統裏,最常見的棧操作就是各種系統API函數的調用。
 

堆:按需索取

堆在數據結構和內存分配方面的工作方式並不相同,在數據結構中堆是一種特殊的二叉樹,而我們平時提及的堆是一種內存分配的類型,它是一種類似於鏈表的結構。
操作系統自身定義了許多鏈表,其中一個鏈表專門用於記錄當前尚未使用的內存地址,當一個程序申請一塊空閒內存的時候,它就是在請求一個堆。系統在空閒內存地址鏈表中尋找一個足夠大小的內存空間並將它標註出來,之後再進行分配。
堆被用於存儲動態數據變量,你也許會想,前面提到的棧結構不也是用於存儲數據嗎?它們的確都是用於數據存儲,但是,棧是由系統分配的、預定義了大小的內存區塊,系統是在嚴格的控制下對棧進行管理的。棧的大小由操作系統決定,在Windows系統下這個大小爲1MB或2MB,這樣的設置對於存放更新頻繁的臨時變量十分合適,但是它不能對程序在運行中另外需要分配的未知數據進行預設,這時候就要用到堆了。
因此,堆一般被用於存放事先不知道數量和大小的數據變量,以及佔用內存空間超過棧大小的大尺寸對象等。操作系統默認在每個程序執行時都預先給它分配一個堆用於存放進程初始數據,程序在運行時還可以根據需要另行申請別的堆。堆在使用結束後系統並不會自動清空,只能由開發人員自行調用指令刪除使用過的堆。如果開發人員沒有對被用過的堆進行處理,它就會一直駐留在內存空間浪費資源。當內存裏能用的空間都被消耗殆盡時,程序乃至系統自身都會發生異常甚至系統崩潰。但是,如果程序被關閉,系統將會自動釋放所有與這個進程有關的內存。
 

棧溢出和堆溢出

一個被申請了的指定大小的內存空間,無論是堆還是棧,都被統稱爲“緩衝區”(Buf fer)。因爲系統要求這個空間必須大於實際數據需要的大小,也就是一個貼着“最大可裝100片”的筒裝薯片裏往往不可能真的裝滿100片薯片。但是如果有人刻意往標註了“最大可裝100片”的筒子裏塞了200片薯片呢?毫無疑問,多出來的100片將會在流水線上散落得到處都是,甚至還會掉到其他的薯片筒裏去,這個現象就是“溢出”。
heap
在內存空間裏發生的溢出往往會讓情況變得很複雜,因爲內存裏各個指令和數據的地址是相當緊湊的,並沒有多少空閒內存剛好可以接納這些超額的數據,那麼數據會往哪裏去呢?它可能會恰好覆蓋到另一個API的棧數據,從而成爲別人的參數,也可能覆蓋到自己的下一個指令,導致CPU執行一個無法執行的指令,最終造成內存異常。在早期的Win98系統裏,這個問題將會直接導致藍屏出現。而在內存管理機制相當完善和嚴謹的NT架構系統裏,這種內存異常只要不是發生在內核領域,就能順利觸發系統的異常處理機制,令系統強行中止發生異常的程序,於是我們能看到由溢出引發的程序崩潰。而這個運行機制就引出了我們今天的主角——Heap Spray技術。
 

Heap Spray:溢出漏洞的墊腳石

雖然前面將溢出解釋得十分簡單,但是實際環境裏要實現真正有用的溢出並不容易。不過我們可以用下面這個簡單的實驗來再現溢出。在Windows XP中選擇“開始  | 運行”,輸入“cmd”後回車打開命令行輸入窗口,在裏邊輸入“dir \ \?\AAAAA……”(超過四行的A),由於命令行輸入窗口裏用於複製字符串的API忽略了長度檢查,就導致了棧溢出,溢出的字符串數據在內存中編碼爲“00 41”(A的Unicode編碼),因爲“41”是沒有對應任何彙編指令的,所以溢出發生後很多進程的內存空間受到波及,最直接的一個影響就是將CPU下一步執行的指令覆蓋成了不可被解析執行的“41 00”。這會觸發了程序異常處理機制SEH(Structured Exception Handling,結構化異常處理),而由於SHE運行需要的內存空間也已經被同樣的“41  00”覆蓋了,最終預置的異常處理機制都無法執行了出現崩潰退出的情況。
如果將溢出用的“A”換作“q”,這個過程又會不一樣了,因爲“q”的Unicode編碼是“00  71”,在發生溢出後,CPU執行的指令將會是“7 1”,這對應着彙編指令“JNO”(不溢出跳轉)。這個溢出的內容被執行後,緊隨在“71”之後的“00”會被視爲跳轉地址,於是這個指令最終的意思是“NOP”(空指令,不跳轉到任何地方)。此時,因爲剩下來執行到的指令全都是“空”,CPU不會遇到無法執行指令而退出的情況,因此用戶很難發現異常。但是如果這個溢出是由***運行的,執行的就可能是一個***指令了。
溢出的難點在於尋找它的溢出根源、溢出類型以及相關地址,並不是隨便在某個程序界面裏胡亂輸入一些字符就能實現有效溢出的。而“程序異常處理機制”(SEH)的存在更是爲溢出增加了一定難度,有時候雖然***者構造的惡意執行指令(Shellcode)已經成功觸發了溢出,但是隨之被觸發的SHE會將程序跳轉到SEH指定的異常處理過程中去,這會使***者構造的指令只能引發一個錯誤提示或程序崩潰的結果。
因此,***者就必須想辦法在溢出發生時把SHE跳轉用另外一個地址給覆蓋掉,這樣一來就控制了程序在遭遇異常後執行的代碼流向,一旦CPU被成功帶到***者放置了***代碼的位置,***者的意圖就達到了。
爲了實現有效的溢出***,***者使用特定大小的Shellcode內容來重複申請堆,並將Shellcode數據填充進去,這段數據塊一定要足夠大才能確保溢出後能實現它真正的功能。由於目前Shellcode在網頁***中使用的機會較多,它們必須依賴於JavaScript執行,而如果用戶當前打開的網頁較多的話JavaScript申請到的內存就不一定還能出現在預期的範圍內,所以***者通過重複填充一塊又一塊內存空間的手段來提高命中率。通常申請堆的步驟在觸發溢出之前就已經做好,只要成功觸發了溢出通常就能使SHE失效並實現惡意代碼執行。這個手段的統稱,就是“Heap Spray”。
如果用戶對網絡安全有興趣並學習了一些溢出教程,會發現這些教程大部分會告訴用戶要設法將惡意指令寫到“0x0C0C0C0C”這個內存位置上,這是由JavaScript自身特性決定的。JavaScript解釋器在請求堆的時候是從“0x00000000”的位置開始申請內存塊的,如果***者只請求了一個堆,就無法讓溢出後的程序跳轉到指定指令所在的內存位置。因此***者需要構造至少幾百個堆,每個堆裏的內容都是一樣的,最終會有一個堆剛好分配到“0x0C0C0C0C”內存位置上,這個過程就是“Heap Spraying”。
 

***:訪問網頁即中招

下面我們以今年七月份爆發的最新0day漏洞“MPEG-2 ActiveX Remote Buf fer Over f low  Exploi t”爲例,介紹一下Head Spray是怎麼讓惡意代碼被成功執行的。
這個漏洞的根源在於MPEG2視頻組件的msvidctl.dll模塊裏有個方法調用的系統函數ReadFile被傳遞了錯誤的參數類型。在大家都是“乖寶寶”的情況下,這個隱患不會被暴露出來,然而,又有人不按規矩出牌了。
首先,***者編寫一段Shellcode(惡意指令),這段代碼要小於溢出時能構造的有效溢出代碼的空間。然後使用總共佔據0x30000個字節的空指令NOP加上末尾的Shellcode代碼,最終構造出0x040404大小的數據塊。通過反覆申請300個堆將這數據塊內容填充進去,這樣就能保證至少最後一塊內存位置是0x0C0C0C0C。
如果有人觀察過多種漏洞溢出利用代碼的示範樣本就會發現,它們幾乎都是以大量的空指令打頭陣的,爲什麼不直接乾脆用Shel lcode自身來反覆填充內存位置呢?這是因爲JavaScript解釋器可能會由於用戶瀏覽了多個網頁而不能從最低地址開始申請堆,所以它申請到的內存位置可能會與***者設想的起始處有偏差。這樣會導致Shellcode到0x0C0C0C0C位置的時候只有部分指令被溢出,也就是JavaScript申請到的堆並沒有按照***者設想的那樣剛好把代碼開始的第一個字節填充到0x0C0C0C0C這個位置上,這樣一來當溢出發生時CPU執行到這裏的代碼就會由於缺少了一部分指令而導致溢出失敗。而如果***者在Shellcode代碼的前面以大量空指令填充呢?由於代碼前部是空指令,它們被截斷成多少份也不會影響到後面實際代碼的執行。即使一段惡意指令被覆蓋到0x0C0C0C0C位置時前面少了很多空指令,它仍然能被執行。
當然,有時候即使用了大量空指令做鋪墊,也會出現溢出失敗的情況。
那是因爲***者的代碼構造不合理或Shellcode只有一部分進入了0x0C0C0C0C位置。因此要想讓溢出成功機率更大些,計算一個合適大小的Shellcode數據塊是相當重要的。
回到前邊提到的MPEG-2漏洞,當***者以適當長度的空指令和Shel lcode代碼反覆填充了多個內存地址後,0x0C0C0C0C位置也被這段代碼所佔據,然後溢出代碼調用MPEG-2組件加載一個精心構造了錯誤內容的GIF文件,這個文件第14個字節開始的內容導致了ReadFile函數發生溢出。溢出數據裏的0xFFFFFFFF和0x0C0C0C0C剛好將SEH地址覆蓋,於是SHE的跳轉地址變爲0x0C0C0C0C。這時候又由於前邊發生了溢出而啓動了異常處理機制,程序代碼會執行SHE。在正常情況下,這一步後應該會導致程序崩潰或執行自身預置的異常處理過程,例如彈出錯誤消息提示等。但是現在,跳轉地址被改寫爲0x0C0C0C0C,於是CPU就跳轉到0x0C0C0C0C位置去執行***者預先編寫的Shellcode了。
雖然堆是由程序員自己控制的,但是這並不意味着我們可以隨心所欲地指定程序在某個內存位置去新建一個堆,但是我們能控制每個堆的大小以及數量,而且堆的初始位置是可以被預測的。因此利用大量重複數據生成堆的Heap Spray技術成了控制溢出代碼位置的最流行手段。雖然實際上我們仍然無法真正控制代碼被填充到指定內存位置,但是通過大量的循環,總能有一段代碼被成功填充到指定位置上,這樣就能被視爲控制成功了。
“Heap Spray”還具備跨平臺跨瀏覽器的能力,特別是在基於JavaScript的***方面,無論用戶是使用漏洞很多的IE瀏覽器還是宣稱安全性較強的Firefox,***者總能找出一個適合它們的***手法,再結合Heap Spray溢出***總有機會實現。
因此,“Heap Spray”並不是指某一種漏洞或***手段,它自身是一種合理存在的技術手段罷了,只不過被大量用於溢出Shellcode,成爲惡意***得以順利執行的墊腳石。
 

防範:如何阻止Heap Spray

heap
在這個網頁***滿天飛的時代裏,“裸奔”(不在電腦裏安裝任何信息安全工具)已經成了瘋狂的代名詞,你永遠無法保證今天還正常瀏覽的網站是否明天就會被******並放上了一個網頁***。而也許這個***恰巧可以***你電腦上尚未修補的漏洞。因此在電腦中安裝殺毒軟件是非常必要的。但是這樣還不夠,殺毒軟件通常只能在病毒***已經被下載或執行時進行補救,它並不能預防或阻止溢出的發生,而這個觸發的溢出很可能存在針對殺毒軟件***代碼,這些代碼可以關掉殺毒軟件,此時系統也就毫無安全性可言了。因此僅僅安裝殺毒軟件並不能百分之百地防範針對漏洞的***,用戶還必須選擇一款網絡安全防護工具。
目前許多廠商都推出了能夠檢測瀏覽器和網絡行爲的監控工具,如金山網盾、趨勢雲安全、×××等。
那麼監控工具是如何發現Heap Spray嫌疑代碼的呢?首先,它將自身監控模塊注入瀏覽器進程,或者直接將自身作爲瀏覽器的一個BHO對象讓瀏覽器主動加載。隨後,當瀏覽器的腳本解釋器開始重複申請堆的時候,監控模塊記錄堆的大小、內容和數量,當判斷這些重複的堆請求到達了一個閥值或覆蓋了指定的地址時,監控模塊會阻止這個腳本執行過程並彈出警告,由於腳本執行被中斷,後面的溢出也就無法實現了。於是一般情況下瀏覽器不會發生異常,就像用戶剛纔根本沒有被惡意網頁糾纏過。
然而,監控工具也仍然可能會存在問題,例如一種新的針對監控工具的溢出代碼,就有可能會令它們的模塊失效,最終用戶還是被******。雖然當前還沒有發生這種***,但是當***者們將監控工具研究透以後,他們總能找到繞過的方法。因此,有經驗的用戶最好能在使用監控工具的基礎上繼續安裝一款主動防禦類工具,如SSM等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章