DLL劫持漏洞解析
黑客手中的全新武器
艾瑞2012年初發(fā)布的中國2011年下半年個人網(wǎng)絡(luò)安全報(bào)告中,包含這么一個數(shù)據(jù):2011年下半年十大熱點(diǎn)木馬中,其中5個是利用DLL劫持漏洞來對系統(tǒng)進(jìn)行破壞的。DLL劫持漏洞到底是何方神圣,竟然占領(lǐng)了木馬技術(shù)的半壁江山?

圖1 艾瑞安全報(bào)告中利用DLL劫持技術(shù)的熱門木馬截圖
DLL(Dynamic Link Library),全稱動態(tài)鏈接庫,是Windows系統(tǒng)上程序正常運(yùn)行必不可少的功能模塊,是實(shí)現(xiàn)代碼重用的具體形式。簡單的說,可以把DLL理解成幫助程序完成各種功能的組件。
DLL劫持漏洞(DLL Hijacking Exploit),這個名字緣起微軟在2010年8月23日發(fā)布的2269637號安全公告。這個漏洞是通過一些手段來劫持或者替換正常的DLL,欺騙正常程序加載預(yù)先準(zhǔn)備好的惡意DLL的一類漏洞的統(tǒng)稱。利用DLL劫持漏洞,病毒木馬可以隨著文檔的打開(或者其他一些程序正常行為)而激活自身,進(jìn)而獲得系統(tǒng)的控制權(quán)。
我們來看看DLL劫持漏洞到底是何方神圣。#p#
高危害利用形式的爆發(fā)
DLL劫持漏洞伴隨著Windows而存在,但是一直并未得到大家的足夠重視。
直到2010年8月份,有黑客在安全論壇上公布了一種危害極高的DLL劫持漏洞的利用形式,迅速引起強(qiáng)烈的反應(yīng)。隨后,著名安全組織exploit-db公布了一系列存在DLL劫持漏洞的軟件列表,其中可以發(fā)現(xiàn)大家十分熟悉的應(yīng)用軟件,包括:AutoCAD 2007、Daemon Tools、Winamp、Media Player Classic、Mozilla Thunderbird、Microsoft Office、Adobe Photoshop、Adobe Dreamweaver CS5、Skype、Snagit10、Safari、WinDVD、Opera、Firefox等等。

圖2 PCHOME針對DLL劫持漏洞的新聞截圖
簡單的講,安裝了上述軟件的電腦,當(dāng)用戶在打開一個圖片、音樂、視頻、BT種子、網(wǎng)頁文件都有可能感染病毒。當(dāng)攻擊者利用DLL劫持漏洞構(gòu)造一個特殊的DLL文件,將這個DLL文件和一些JPG、PPT、MP3、MPG、HTML文件共同打包,用戶解壓后雙擊打開這些文檔,病毒即被立即觸發(fā)。也就是說,不需要其他漏洞,不需要可執(zhí)行文件,只需要鼠標(biāo)雙擊打開別人發(fā)給你的音樂、視頻或者圖片文件,就可能感染病毒!難怪國外安全公司authentium在官方博客中描述DLL劫持漏洞時(shí),甚至用"The world is going to end!"做標(biāo)題。
不過此次風(fēng)波,隨著網(wǎng)民們的關(guān)注和各個產(chǎn)品漏洞的逐步修復(fù),逐漸平息下去。#p#
演變和進(jìn)化
DLL劫持漏洞的生命力絕不僅限于打開文件這種觸發(fā)這種形式。通過這種形式的啟發(fā),黑客們逐漸找到了DLL劫持漏洞的更大活力。二年之后的今天,當(dāng)我們再看這個漏洞時(shí),它已搖身一變更具威脅了。
了解客戶端安全的同學(xué)應(yīng)該都知道,現(xiàn)在的安全軟件大都會采取白名單機(jī)制,把一些大公司的程序放在安全軟件的白名單中,白名單中的程序不會進(jìn)行監(jiān)控并默認(rèn)信任,以減少誤報(bào)率。
都說安全性和易用性是相悖的。白名單這個特性是使安全軟件和受信任程序的使用都方便了不少,但是,同時(shí)也更加方便了廣大黑客。我們都知道,軟件工作時(shí)都需要這樣那樣的DLL功能組件,那么在安全軟件白名單信任策略支持下,即使“安全軟件”要加載的DLL是被替換掉的惡意DLL,安全軟件都會被認(rèn)為是合法、正常的行為。因此,黑客們就開始利用各大公司軟件中存在的DLL劫持漏洞,堂而皇之的在安全軟件眼皮底下加載早已準(zhǔn)備好的惡意代碼,入侵用戶的計(jì)算機(jī)。至此,更具“劫持”特性的廣義DLL劫持漏洞正式誕生。
本文開頭艾瑞報(bào)告中提到的那5個DLL劫持木馬,都屬于這種漏洞形式。是的,你沒有聽錯,就是它,占領(lǐng)木馬激活技術(shù)的半壁江山。由于效果極好,是黑客們殺人放火,打家劫舍的必備大殺傷性武器。#p#
刨根到底看原理
DLL劫持漏洞之所以被稱為漏洞,還要從負(fù)責(zé)加載DLL的系統(tǒng)API LoadLibrary來看。熟悉Windows代碼的同學(xué)都知道,調(diào)用LoadLibrary時(shí)可以使用DLL的相對路徑。這時(shí),系統(tǒng)會按照特定的順序搜索一些目錄,以確定DLL的完整路徑。根據(jù)MSDN文檔的約定,在使用相對路徑調(diào)用LoadLibrary(同樣適用于其他同類DLL LoadLibraryEx,ShellExecuteEx等)時(shí),系統(tǒng)會依次從以下6個位置去查找所需要的DLL文件(會根據(jù)SafeDllSearchMode配置而稍有不同)。
1. 程序所在目錄;
2. 系統(tǒng)目錄;
3. 16位系統(tǒng)目錄;
4. Windows目錄;
5. 當(dāng)前目錄;
6. PATH環(huán)境變量中的各個目錄。
而所謂的劫持的,就發(fā)生在系統(tǒng)按照順序搜索這些特定目錄時(shí)。只要黑客能夠?qū)阂獾腄LL放在優(yōu)先于正常DLL所在的目錄,就能夠欺騙系統(tǒng)優(yōu)先加載惡意DLL,來實(shí)現(xiàn)“劫持”。
微軟的“設(shè)計(jì)缺陷”?
從上面的原理來看,LoadLibrary API并不會去檢查即將要加載進(jìn)來的DLL是好人還是壞人,不管是李逵還是李鬼都有酒喝、有肉吃。這點(diǎn)我們能理解,畢竟判斷DLL是好是壞不是系統(tǒng)的事情,而是安全軟件的事情。
同時(shí),當(dāng)使用相對路徑調(diào)用這個API加載DLL時(shí),就會觸發(fā)上一節(jié)所述的神奇的動態(tài)鏈接庫搜索邏輯。由于系統(tǒng)搜索的位置非常多,而且其中的許多位置都能輕易被黑客劫持和控制,給了DLL劫持漏洞很大的利用空間。
但是,微軟認(rèn)為以上這些屬于系統(tǒng)特性,不屬于安全漏洞而不做修改,微軟官方的介紹及安全建議請參考這里:Dynamic-Link Library Search Order,Dynamic-Link Library Security。
比較有意思的是,從Windows 7的KB2533623補(bǔ)丁開始,微軟給我們帶來了三個解決DLL劫持問題的新API:SetDefaultDllDirectories,AddDllDirectory,RemoveDllDirectory。這幾個API配合使用,可以有效的規(guī)避DLL劫持問題??上У氖牵@些API只能在打了KB2533623補(bǔ)丁的Windows7,2008上使用。#p#
Satellite DLL Hijacking
微軟從VS2003/MFC7.0開始就提供對Satellite DLL的增強(qiáng)支持,主要用于創(chuàng)建針對多種語言進(jìn)行本地化的應(yīng)用程序。Satellite DLL屬于純資源DLL,它包含應(yīng)用程序針對特定語言進(jìn)行本地化的資源。當(dāng)應(yīng)用程序開始執(zhí)行時(shí),MFC會自動加載最適合于當(dāng)前運(yùn)行環(huán)境的本地化資源,比如在中文系統(tǒng)上,應(yīng)用程序會優(yōu)先使用中文資源,若是英文系統(tǒng),則使用英文資源。Satellite DLL的命名規(guī)范為ApplicationNameXXX.dll,其中ApplicationName是使用MFC的*.EXE或者*.DLL的名稱,而XXX為由資源語言的三個字母組成,比如中文為CHS,英文為ENU。由于經(jīng)MFC編譯的應(yīng)用程序會自動加載相應(yīng)語言的本地化資源(即Satellite DLL),且對加載的資源文件的合法性未作有效檢測,因此可能被惡意程序利用DLL劫持來實(shí)現(xiàn)任意代碼執(zhí)行。
MFC主要按照以下順序加載每種語言的資源DLL,找到一個后將停止加載下面的其它DLL:
1. 當(dāng)前用戶的默認(rèn)界面語言(UI Language)(適用于 Windows 2000 或更高版本),該語言從 GetUserDefaultUILanguage() Win32 API 返回;
2. 當(dāng)前用戶的默認(rèn)界面語言(適用于Windows 2000 或更高版本),沒有任何特定子語言(即 ENC [加拿大英語] 變成 ENU [美國英語]);
3.系統(tǒng)的默認(rèn)界面語言(適用于Windows 2000 或更高版本),這是從 GetSystemDefaultUILanguage() API 返回的語言。 在其他平臺上,這是操作系統(tǒng)本身的語言;
4. 系統(tǒng)的默認(rèn)界面語言,沒有任何特定的子語言;
5. 具有 3 個字母代碼 LOC 的“虛設(shè)”語言。
比如使用MFC的應(yīng)用程序Example.exe,系統(tǒng)的用戶界面語言是ENU(美國英語),而當(dāng)前用戶的用戶界面語言為FRC(加拿大法語),那么MFC將按照以下順序查找資源DLL文件:
1. ExampleFRC.dll(當(dāng)前用戶的界面語言,此例為加拿大法語);
2. ExampleFRA.dll(當(dāng)前用戶的界面語言,不包含子語言,此例為法語(法國));
3. ExampleENU.dll(系統(tǒng)默認(rèn)的用戶界面語言,此例為美國英語);
4. ExampleLOC.dll。
如果未找到上面DLL中任何一個,則MFC會使用Example.exe自帶的資源。當(dāng)應(yīng)用程序自帶有界面語言資源DLL文件時(shí),它也會按照上述順序來加載。比如在Win7簡體中文系統(tǒng)上,應(yīng)用程序Example.exe擁有自己的UI資源文件MainUI.dll,那么就會首先去加載MainUICHS.dll。
因此,惡意程序如果在程序相當(dāng)目錄下,比如上面MainUI.dll所在目錄下,再放置一個包含惡意代碼的MainUICHS.dll后,打開主程序Example.exe后,就會優(yōu)先加載包含惡意代碼的MainUICHS.dll,而非MainUI.dll,從而執(zhí)行任意代碼,如下圖所示:

由于多數(shù)MFC程序默認(rèn)會動態(tài)鏈接mfc70.dll、mfc80.dll、mfc90.dll等dll文件(具體文件名與MFC版本號相關(guān)),因此在中文系統(tǒng)下,如果在相應(yīng)的程序目錄下放置mfc**chs.dll或者mfc**loc.dll都有可能達(dá)到DLL劫持的目的。#p#
DLL加載安全之道
首先,對于會打開圖片、音樂等各種類型文件的程序,分為以下三種情況處理:
A. 對于外部第三方DLL和自己的DLL:
1. 使用LoadLibrary API加載DLL時(shí)使用絕對路徑,類似的情況還包括其他API如LoadLibraryEx, CreateProcess, ShellExecute等;
2. 將所有需要使用到的DLL放在應(yīng)用程序所在的目錄,不放到系統(tǒng)目錄或者其他目錄。
B. 對于系統(tǒng)共享的DLL(如user32.dll, mfc80loc.dll等),不能放到程序目錄下時(shí),應(yīng)該:
1. 使用絕對路徑加載;
2. 對于無法準(zhǔn)確預(yù)測絕對路徑的情況,可以使用相對路徑加載。
C. 程序啟動時(shí)調(diào)用API SetDllDirectory(L"")將當(dāng)前目錄從DLL加載順序中移除.
其次,對于廣義DLL劫持漏洞,我們只有一種有效的處理辦法:加載任何DLL前先校驗(yàn)文件的簽名,簽名沒有問題的才能加載。
檢測方案
DLL劫持漏洞的檢測比較簡單,可以在虛擬環(huán)境將程序運(yùn)行起來,對其中的DLL加載操作進(jìn)行審計(jì),找出加載順序中可能被劫持的點(diǎn);還可以為程序構(gòu)建一個“劫持現(xiàn)場”(自己做一個劫持并轉(zhuǎn)發(fā)給正常DLL的DLL文件看是否執(zhí)行其中代碼),并檢查程序能否真正規(guī)避DLL劫持的威脅。