當前位置:
首頁 > 新聞 > 使用超長文件名讓Windows API崩潰

使用超長文件名讓Windows API崩潰

Windows API就是Windows應用程序介面,是針對microsoft Windows操作系統家族的系統編程介面,這樣的系統包括Windows 8.1,Windows 8,Windows 7,Windows Vista、Windows XP、Windows Server 2012、Windows 2008 R2 、Windows Server 2003、Windows 2000、Windows 95、Windows 98、Windows Me(Millennium Editon)和Windows CE等幾乎所有版本。

其中32位Windows操作系統的編程介面稱為Win32 API,以便與以前16位版本Windows編程介面(16位Windows API)區別開來。

當WINDOWS操作系統開始佔據主導地位的時候,開發WINDOWS平台下的應用程序成為人們的需要。而在WINDOWS程序設計領域處於發展的初期,WINDOWS程序員所能使用的編程工具唯有API函數,這些函數是WINDOWS提供給應用程序與操作系統的介面,它們猶如「積木塊」一樣,可以搭建出各種界面豐富,功能靈活的應用程序。所以可以認為API函數是構築整個WINDOWS框架的基石,在它的下面是WINDOWS的操作系統核心,而它的上面則是所有的華麗的WINDOWS應用程序。

程序員想編寫具有Windows風格的軟體,必須藉助API,API也因此被賦予至高無上的地位。但是,如若沒有合適的Windows編程平台,那麼Windows開發是一項很複雜的工作。在可視化編程環境出來之前,那時的WINDOWS程序開發還是比較複雜的工作,程序員必須熟記一大堆常用的API函數,而且還得對WINDOWS操作系統有深入的了解。然而由於這些優秀可視化編程環境操作簡單、界面友好(諸如VB、VC++、DELPHI等),在這些工具中提供了大量的類庫和各種控制項,它們替代了API的神秘功能。不過這些類庫和控制項都是構架在WIN32 API函數基礎之上的,是封裝了的API函數的集合。它們把常用的API函數的組合在一起成為一個控制項或類庫,並賦予其方便的使用方法,所以極大的加速了WINDOWS應用程序開發的過程。

總而言之,雖然Windows API陳舊,但卻非常可靠,即使程序崩潰,系統也足夠聰明,可以清理所有那些未被正確釋放的句柄、內存分配,並以一種適當的方式處理任何其他錯誤。這種對系統清理的信任創建了一個安全生態系統,在這個生態系統中,許多程序僅僅依靠操作系統來修復程序員的錯誤。

不過當某些類型的Windows API調用失敗時,則意味著一個更嚴重的問題,即底層系統可能已經非常不穩定了。忘了是哪位編程界的大蝦說過:「API不要去學,在需要的時候去查API幫助就足夠了」。這句話背後的意思是,我們對待API函數不必刻意去研究每一個函數的用法,那也是不現實的,目前能用得到的API函數有幾千個。但由於許多API函數令人難以理解,易於誤用,還會導致出錯。所以幾十年來,許多編程書籍,論壇等都使用了現成的樣本代碼片段,沒有幾個人願意檢查這些API調用的實際結果,他們都假設調用不會失敗。這個想法非常危險,也就是說,過去30年中編寫的許多程序都包含許多這樣的API調用,且假設默認情況下它們100%可信,按樣本那樣工作,沒有人檢查錯誤或預期結果......

不過隨著技術的發展,對底層系統的攻擊不再那麼容易了,所以攻擊者的目標就集中在了依靠系統的Windows API。由於這些舊代碼片段的代碼量是巨大且複雜的,並且不宜更新和修復,所以許多至今還存在於Windows API中。

目前許多軟體開發人員仍在使用一些所謂的「非常好」的錯誤代碼樣本,比如依靠環境變數來確定%systemroot%(系統中的一個變數,表示的是windows系統啟動文件夾位置)或其他路徑實際上是一個非常糟糕的想法,儘管在許多編程論壇上,這種方法已被作為標準的行業慣例,但問題是用戶可以在運行應用程序之前通過操縱它們來控制這些變數,並強迫程序以不可預期的方式運行。

另一個例子是文件系統和文件處理增強功能的出現,前幾天我提到Windows 10中引入了一些新的應用機制,允許API在處理文件名時超出最大路徑長度限制。這對於那些老的應用程序來說是一個嚴重的問題,因為這個新機制可能會讓它們無法使用一些具有新特性的文件。這就會影響許多日常運行,比如逆向工程,沙箱等。由於此類新機制不可能兼容以前的特性,這些情況就會得不到相應的解決,甚至還可能被攻擊者利用。有趣的是,超長文件名的問題還不是Windows API的新問題,它已經存在很久了。

如果你想進行簡單的測試,請嘗試重命名你的收藏夾。以下這些文件名都是用於測試的應用程序的.exe(記得刪除換行符):

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789

0123456789.exe

當你嘗試打開重命名後的應用時,你可能會看到「拒絕訪問」的提示,這可能是因為系統或你的程序shell排斥它。不過有時,重命名後的應用也可以運行,但也可能經常會發生崩潰。以下是一個簡單的sysmon崩潰樣本,是把應用程序重命名為如此長的文件名後,然後執行時的情況。

甚至像Total Commander這樣的調試器和程序也無法找到這樣的文件,Total Commander,簡稱TC,原名Windows Commander,功能強大的全能文件管理器。

所以我認為這其中必然有著很大的漏洞,但目前還沒有搞清楚是什麼?不過還有更多有趣的API和「代碼模式」可供查找。

在上一篇文章中,我提到有時編碼人員不會遵守確切的API規範,比如MSDN,因此他們可能會在自己開發的程序中引入一些限制,而這些限制可能會被濫用。

如果要獲取當前進程已載入模塊的文件的完整路徑,GetModuleFileName函數必須由當前進程載入。如果想要獲取另一個已載入模塊的文件路徑,可以使用GetModuleFileNameEx函數。而這些無辜的函數會被很多應用使用,包括安全工具。如果了解MSDN,就知道如果路徑的緩衝區太小,該函數將截斷路徑以使其完全填充緩衝區,進而將最後一個字元包含ASCIIZ並返回ERROR_INSUFFICIENT_BUFFER。

注意,此時操作系統將截斷路徑以使其填充緩衝區。為什麼操作系統會這樣做,而不是堅持返回錯誤?我真的不知道......

不幸的是,由於許多編碼人員都誤認為他們的緩衝區足夠大,而其實典型的分配緩衝區只能擠出260個字元大小的空間,並且它是一個靜止在堆棧上分配的緩衝區,並不會動態變化。由於編碼人員很少檢查這種錯誤(不檢查緩衝區是否太小,是否使用本地分配的緩衝區),實際上這種錯誤很常見,包括MSDN上的許多樣本。

如果你想知道為什麼程序只分配260個字元,那你就要知道API名稱其實是一段代碼。這段代碼指的就是模塊文件名,但返回的數據實際上是一個完全限定的路徑。雖然文件名的長度明顯受限,但完整路徑可能比260個字元長得多。

讓我們設想一個簡單的場景,假如你設備里的一個可信程序正在使用GetModuleFileName獲取最大路徑(128個字元)。假如這時有惡意用戶發現GetModuleFileName正在獲取路徑並將程序重命名為140個字元,這樣可信API會將模塊文件路徑截斷為指向另一個可能是惡意文件的路徑。如果這樣的程序使用獲得的信息將自己的二進位文件複製到目標文件夾中(許多應用程序都這樣做),那麼由於這個截斷,複製的路徑函數將指向另一個惡意的文件。事實證明,一旦GetModuleFileName檢索到這種不合邏輯的路徑,合法程序實際上可能會根據文件名(假定為正確的)將文件複製到目標目錄。通過操縱文件名和路徑長度,攻擊者可以強制受信任程序運行惡意文件。

換句話說,攻擊者正式通過利用實際的API返回值沒有被正確地測試或處理的疏忽來下手的,通過修改程序的邏輯就可以使得程序按著他們的預期運行。

以下我會使用一個較短的路徑作為解讀樣本,假設c:foldergood.exe就是一個用於攻擊的長文件名,此時程序在執行過程中會將自己的文件複製到預期的目標目錄,但由於程序分配了一個非常小的緩衝區(15個字元而不是19個字元)來檢索其完整路徑,因此會導致截斷的路徑指向不同的文件名:

c:foldergood.exe:程序預期的實際路徑,但由於緩衝區太小(比預期的19個字元少了4個字元),實際路徑會被截斷;

c:foldergood:由於截斷而導致程序代碼複製「good文件」而不是「good.exe」,這就會使程序預期的實際路徑發生重定向。

下圖顯示了其中的工作原理:第一個調用會將完整路徑複製到19個字元長的緩衝區,第二個調用會將程序的文件名部分複製,並返回被許多應用程序忽略的錯誤。

我承認我有點過度關注文件複製,但錯誤的代碼可能在很多其他方面被濫用。例如,如果應用程序使用返回的路徑作為其他API函數的輸入,則這些函數可能會最終讀取錯誤的文件,在用戶界面上顯示不正確的信息,而系統則將不正確的信息寫入日誌等。

目前已經有許多API以類似的方式被濫用,我不是第一個發現它的人,許多研究人員至少關注這一領域20年了。有些人則以非常系統的方式進行了研究,他們發現了許多程序(包括操作系統)在使用註冊表API時不檢查註冊表數據類型,這通常會導致類型混淆漏洞,這個漏洞可能會被濫用。讀了本文,你會發現如果可以將路徑或文件名更改的足夠長,則至少可以使某些應用程序崩潰;如果你可以將路徑或文件名更改為足夠長的路徑或文件名,並且應用程序編碼的安全檢查很差,那麼使用獲取的名稱就可以影響程序的運行結果。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 嘶吼RoarTalk 的精彩文章:

GZipDe惡意軟體分析
CSS2018:洞見全球安全新趨勢 零距離對話全球大咖

TAG:嘶吼RoarTalk |