OS X平臺的Dylib劫持技術(上)

wyzsk發表於2020-08-19
作者: vvun91e0n · 2015/10/04 10:33

原文:https://www.virusbtn.com/virusbulletin/archive/2015/03/vb201503-dylib-hijacking

作者:Patrick Wardleku

翻譯水平有限,請理解請指正

DLL劫持是一項廣為人知的攻擊技術,一直以來被認為只會影響到Windows系統。然而本文將會介紹OS X系統同樣存在著動態連結庫劫持。透過利用OS X動態庫loader的未文件化的技術和幾種特性,攻擊者將精心製作的包含惡意程式碼的動態連結庫載入進存在漏洞的程式中。透過這種方法,攻擊者可以實現多種惡意行為,包括:隱秘駐留,程式載入時注入,繞過安全防護軟體,當然還包括Gatekeeper的繞過(提供遠端注入的機會)。因為攻擊者利用的是作業系統提供的合法函式呼叫,所以只能盡力防禦,不可能被完全修補。本文將要提供用於發現存在漏洞二進位制檔案的技術和工具,同時也可以用來探測是否有劫持已經發生。

0x01 背景


在介紹OS X平臺下的dynamic library(dylib)劫持攻擊細節之前,我們先介紹下Windows平臺下的dynamic link library(DLL)劫持。因為這兩種攻擊在概念上很相似。透過學習成熟的Windows平臺攻擊方法可以幫助理解OS X平臺下的方法。

微軟給出的DLL劫持定義是: “當一個程式動態載入一個DLL時,如果沒有給出完整的路徑,Windows系統會試著在預設的一些目錄下搜尋該DLL。如果一個攻擊者獲得了其中一個目錄的控制權,他就可以讓程式載入一個惡意的DLL檔案來代替原來的DLL。”【1】

需要指出的是,Windows載入器的預設搜尋路徑先搜尋一些特定目錄(如程式所在目錄或當前工作目錄),再搜尋Windows系統目錄。這種處理策略導致了漏洞的產生。比如,一個程式試圖載入一個沒有完整路徑的系統庫,只給出了名字。在這時,一個攻擊者在之前的搜尋目錄中植入了一個惡意同名DLL。這樣Windows載入器會先發現惡意的DLL而不是原來的合法DLL,並且將其載入到漏洞程式中。

下面的圖1和圖2進行了說明,一個存在漏洞的程式被一個惡意DLL劫持了。該惡意DLL放在當前工作目錄中。

圖1  載入正常系統DLL

圖2 載入攻擊者的惡意DLL

DLL劫持攻擊最初形成廣泛影響是在2010年,然後迅速的得到了媒體和駭客的關注。起了一些如“二進位制植入”,“不安全庫載入”,“DLL預製攻擊”等名字。發現該漏洞的人被廣泛認為是H.D.Moore【2】,【3】。然而NSA是最先發現這個漏洞的,早在Moore發現的12年前,1998年,在NSA的非機密檔案‘Windows NT Security Guidelines'中,NSA就描述DLL劫持漏洞並提出了警告:

'攻擊者無法插入一個虛假的同名DLL在搜尋器搜尋到合法的DLL之前,這是非常重要的’【4】

對於一個攻擊者來說,DLL劫持可以使用於多種場合。比如,攻擊者可以讓惡意庫安靜的啟動載入(不改變任何註冊資訊和其他系統元件),許可權可以得到提升,甚至進行遠端感染。

惡意軟體作者迅速的認識到了DLL劫持的優勢。在一篇部落格文章”What the fxsst?“【5】裡面,Mandiant公司的研究者描述了他們怎麼發現了大量不同不相關的惡意軟體樣本都叫‘fxsst.dll’。透過進一步的研究,他們發現這些樣本都是利用了一個存在於Windows shell(Explorer.exe)裡面的DLL劫持漏洞。該漏洞提供了一個隱秘駐留系統的方法。具體原因是,因為Explorer.exe是安裝在C:\Windows目錄下,在這個目錄下植入一個名為fxsst.dll的惡意動態庫檔案,將會成功讓惡意dll駐留在系統,因為載入器會在搜尋真正fxsst.dll存在的系統目錄之前搜尋這個程式目錄。

另一個惡意軟體利用DLL劫持技術的例子可以在洩露的銀行木馬‘Carberp’]【6】中找到。原始碼顯示該惡意軟體是透過sysprep.exe(圖3)的DLL劫持來繞過UAC的。這個程式是一個自動提權的程式,即不需要任何UAC請求就可以獲得更高的許可權。不幸的是,它存在著DLL劫持漏洞,被攻擊者利用來載入惡意的DLL(cryptbase.dll)【7】。

圖3 Carberp利用DLL劫持來繞過UAC

最近,DLL劫持在Windows平臺上已經很少見了。微軟迅速採取應對攻擊,修補易受攻擊的應用程式,並詳細說明如何避免這個問題(例如,對需要載入的DLL指定一個絕對路徑)【8】。然而,作業系統級的防禦措施還是需要的,比如透過safedllsearchmode或cwdillegalindllsearch登錄檔項啟用,防止大多數DLL劫持。

0x02 Dylib劫持


曾經以為動態庫劫持只一個Windows平臺獨有的問題。但是,在2010年,一個機敏的StackOverflow使用者指出來,‘任何允許動態連結外部庫的作業系統在理論上都是有漏洞的’【9】。直到2015年他才證明了這個觀點的正確性。本文將揭示在OS X平臺下具有毀滅性的動態庫劫持攻擊技術。

本文研究的目的是揭示OS X平臺是否存在動態庫攻擊的漏洞。進一步說就是,本研究需要回答如下的問題:在OS X平臺下,是否攻擊者可以植入一個可以自動被載入器載入到漏洞程式的惡意動態庫。假設OS X平臺下的劫持攻擊可以和Windows平臺下的DLL劫持一樣,能夠讓攻擊者實現大量的攻擊目的。比如:隱秘駐留,載入時注入,安全軟體繞過,也許還有可以遠端感染。

需要指出的是,本研究是基於一些限制條件的。第一,成功被限制在不允許對系統做出任何修改情況下,除了建立檔案(或者是資料夾)。換一個方式說,本研究忽略了那些要求對特殊二進位制檔案進行修改(例如補丁)或修改系統配置檔案(比如‘auto-run’plists等)的攻擊環境要求。這樣的攻擊都被廣為人知,容易去防止和探測,所以被忽略掉。本研究試圖尋找到一個獨立於使用者環境的劫持方法。OS X也提供了各種合法的方式載入動態庫,可以讓載入器強制自動載入惡意庫到目標程式。這些方法,比如設定DYLD_INSERT_LIBRARIES環境變數,是使用者特定的,也是眾所周知的,容易被檢測到。所以我們也不進行研究,直接忽略了。

本研究從研究分析OS X的動態聯結器和載入器開始:dyld。這個二進位制檔案在/usr/bin目錄下,提供標準的載入器和聯結器的功能,尋找,載入,連線動態庫。

因為蘋果公司曾讓dyld開源過【10】,所以分析起來就很簡單直接。比如,透過閱讀原始碼可以很好的理解dyld作為一個可執行程式被載入的過程,包括它所依賴的庫載入和連線的過程。下面幾點簡要的總結了dyld開始的步驟(主要關注與本文研究的相關的)

  1. 當任何一個新的程式開始時,核心設定使用者模式的入口點到__dyld_start(dyldStartup.s)。該函式簡單的設定stack然後跳轉到dyldbootstrap::start(),又跳轉到載入器的_main()。
  2. Dyld的_main()函式(dyld.cpp)呼叫link(),link()然後呼叫一個ImageLoader物件的link()方法來啟動主程式的連線程式。
  3. ImageLoader類(ImageLoader.cpp)中可以發現很多由dyld呼叫來實現二進位制載入邏輯的函式。比如,該類中包含link()方法。當被呼叫時這個方法又呼叫物件的recursiveLoadLibraries()方法來進行了所有需求動態庫的載入。
  4. ImageLoader的recursiveLoadLibraries()方法確定所有需要的庫,然後呼叫context.loadLibrary()來逐個載入。context物件是一個簡單的結構體,包含了在方法和函式之間傳遞的函式指標。這個結構體的loadLibrary成員在libraryLocator()函式(dyld.cpp)中初始化,它完成的功能也只是簡單的呼叫load()函式。
  5. load()函式(dyld.cpp)呼叫各種幫助函式,loadPhase0()到loadPhase5()。每一個函式都負責載入程式工作的一個具體任務。比如,解析路徑或者處理會影響載入程式的環境變數。
  6. 在loadPhase5()之後,loadPhase6()函式從檔案系統載入需求的dylib到記憶體中。然後呼叫一個ImageLoaderMachO類的例項物件。來完成每個dylib物件Mach O檔案具體的載入和連線邏輯。

理解了基礎的dyld初始載入邏輯,研究重心就轉移到尋找可以進行dylib劫持的邏輯上來了。特別的,研究組感興趣的是載入器在有沒有在沒有找到一個dylib時,卻沒有報錯的程式碼,還包括在多個位置尋找dylib的程式碼。如果任何一個場景在載入器中發現了,我們就有希望來進行OS X的dylib劫持攻擊。

我們先研究了第一個方案,在此方案中,我們假設,一個載入器可以處理dylib沒有找到的情況,一個攻擊者(可以發現這種情況)可以在該位置放置一個惡意的dylib。從而,載入器就會找到放置的dylib並且不經檢驗的載入攻擊者的惡意程式碼。

回顧之前,載入器呼叫ImageLoader類的recursiveLoadLibraries()方法來尋找和載入所有的需求的庫。如圖4所示,載入程式碼中處理dylib載入失敗的程式碼是被try/catch塊包含的。

圖4 dyilb載入失敗時的處理邏輯

不出所料,處理邏輯會在載入庫失敗的時候丟擲一個異常(含有一條資訊)。有趣的是,這隻有當一個名叫‘required’的變數被設定為true時,才會丟擲異常。此外,原始碼的註釋中說明了在載入‘weak’庫失敗是可以的。這就說明在一些情況下,載入器載入不了一些庫也是會繼續正常工作的---||太棒了!

深入分析載入器程式的原始碼,找到是在哪裡進行‘required’變數的設定。得到結果為,ImageLoaderMacho類的doGetDependentLibraries()方法對載入命令(下面會進行描述)進行語法解析,並且透過載入命令的LC_LOAD_WEAK_DYLIB標識位來給該變數進行賦值。

載入命令是Mach-O檔案格式(OS X的原生二進位制檔案格式)必有的組成部分。在檔案中緊接著Mach-O頭,它提供了不同的命令給載入器。例如,載入命令可以用來說明二進位制文

圖5 設定required變數

件在記憶體中的佈局形式,主執行緒的初始執行狀態,和所需動態庫的具體資訊。可以透過工具檢視編譯好二進位制檔案的載入命令資訊。比如MachOView【11】,或者/usr/bin/otool(使用-l引數)。(參見圖6)

圖5中的程式碼顯示了載入器依次處理所有載入命令的過程,尋找所有宣告倒入的動態庫。這些載入命令的定義可以在mach-o/loader.h檔案中找到。

圖6 透過MachOView檢視Calculator.app的載入命令

圖7 LC_LOAD_*載入命令的格式

對應可執行程式需要每個動態連結庫,程式頭都包含一個LC_LOAD_*載入命令(LC_LOAD_DYLIB,LC_LOAD_WEAK_DYLIB等)。像圖4,圖5中載入程式碼顯示的一樣,LC_LOAD_DYLIB載入命令宣告瞭一個所需的動態庫,透過LC_LOAD_WEAK_DYLIB宣告的庫就是可選的(weak)。前面一種情況(LC_LOAD_DYLIB),如果所需庫沒有被找到就會丟擲一個異常,載入器就會放棄並結束該程式。但是如果是後面的情況(LC_LOAD_WEAK_DYLIB),動態庫是可選的,如果沒有發現也並沒有宣告影響。主程式將會繼續執行。

圖8 嘗試載入弱(weak)庫

該載入器邏輯上滿足了第一個假設劫持場景的條件,因此,可以對OS X平臺進行動態庫劫持攻擊。換句話說,如圖9所示,如果一個宣告的弱引用庫沒有找到,攻擊者就可以在該位置上放置一個惡意的動態庫檔案。然後,載入器就會找到攻擊者的動態庫並且載入惡意程式碼到漏洞程式的程式空間。

圖9 透過惡意的‘weak’動態庫進行劫持

此前說的另外一種劫持攻擊是假設一個載入器在多個地方尋找動態庫。在這種情況下,假設攻擊者可以將一個惡意動態庫放置在其中一個搜尋目錄(合法的動態庫在其他地方)。讓載入器先找到攻擊者的惡意動態庫,並且不經檢查直接載入攻擊者的惡意動態庫。

在OS X平臺上,像LC_LOAD_DYLIB之類的載入命令總是將動態庫的路徑給出(而Windows平臺只是給出動態庫的名字)。正因為給出了路徑,dyld載入器就不需要搜尋不同的目錄來尋找動態庫,而是直接到指定的目錄載入dylib。然而在對dyld原始碼進行分析之後發現,dyld在其中一種情況下並沒有進行如此的處理。

如圖10所示,在dyld.cpp中的loadPhase3()函式中,有一些有趣的處理邏輯。

圖10 載入依賴‘rpath’的庫

Dyld會迴圈迭代rp->paths向量來動態構建路徑(存貯在‘newpath’變數中),之後呼叫loadPhase4()函式。這樣的做法就滿足了第二種劫持場景的要求(dyld在多個位置尋找同一dylib),當然還需要進行一下路徑順序檢查。

圖10中,[email protected]果文件,這是一個特別的載入關鍵字(在OS X 105,Leopard中有介紹),用來定義一個動態庫為‘run-path-dependent library’【12】。蘋果解釋run-path-denpendent library是一種在建立時完整安裝路徑並不知道的依賴庫。其他文件【13】和【14】等提供了更多的細節,解釋了這種庫所起到的作用,[email protected]:‘frameworks and dynamic libraries to finally be built only once and be used for both system-wide installation and embedding without changes to their install names, and allowing applications to provide alternate locations for a given library, or even override the location specified for a deeply embedded library’【14】。

透過這種特性,軟體開發者可以更為簡單的部署複雜的程式,但同時也為動態庫劫持提供了方便。一個可執行程式為了使用run-path-dependent library,需要提供給載入器執行時搜尋路徑列表,載入器在載入時再來尋找這些庫【12】。在dyld的程式碼的很多地方都發現了這樣的程式碼。包括圖10裡面給出的程式碼片段。

因為run-path-dependent library是相對新的概念,有些不為人所知,提供一個例子來說明應該是很有必要的,例子包含了run-path-dependent library和使用該庫的例子程式。

一個run-path-dependent [email protected]ylib。如圖11所示,在Xcode中建立這樣一個動態庫只需簡單的將dylib的安[email protected]

圖11 建立一個 run-path-dependent library 

當run-path-dependent library編譯成功之後,檢查LC_ID_DYLIB(包含了該dylib的標識資訊)載入命令顯示的dylib執行時路徑。特別是,LC_ID_DYLIB載入命令中‘name’項,顯示了該dylib的檔名(rpathLib.framework/ Versions/A/rpathLib)[email protected]

[email protected]

構建一個載入run-path-dependent library的程式也是非常直接簡單的。首先,將run-path-dependent library新增到Xcode的Libraries列表裡面。然後,將run-path搜尋路徑新增到‘Runpath Search Paths’列表。最後,這些搜尋目錄將會在動態載入器載入庫時被搜尋到,以確定run-path-dependent library的具體目錄。

圖13 @rpath庫的連結設定和宣告run path搜尋路徑

一旦應用程式被建立,dumping該程式的載入命令會顯示一些與run-path依賴庫相關的各種命令。一個標準的LC_LOAD_DYLIB載入命令會為需要載入的run-path-dependent dylib的關聯依賴提供資訊,如圖14所示。

圖14 @rpath庫的依賴資訊

在圖14中,注意到安裝名name項指向run-path-dependent [email protected],並和圖12中的run-path-dependent dylib的LC_ID_DYLIB命令的name值是一樣的。該程式包含的與run-path-dependent dylib相關的LC_LOAD_DYLIB載入命令告訴載入器:‘我需要rapthLib dylib,但是在組建時,我不知道它的具體安裝位置。請用我包含的run-path搜尋路徑找到並載入它。’

我們之前在Xcode中將run-path搜尋路徑新增進‘Runpath Search Paths’表單中。這些搜尋路徑會在程式中生成LC_RPATH載入命令,每條路徑對應一個載入命令。檢視編譯好的程式可以發現包含的LC_RPATH載入命令,如圖15所示。

圖15 載入命令中的run-path搜尋路徑

透過對run-path-dependent dylib和載入它的程式的理解,我們就可以更加簡單的去理解dyld的原始碼中負責載入動態庫的那部分程式碼。

當一個程式啟動時,dyld將會解析程式的LC_LOAD_*載入命令,載入和連線所有依賴的dylib。針對處理run-path-dependent libraries,dyld分為兩個步驟完成:先提取所有包含的run-path搜尋路徑,然後再透過搜尋列表裡的路徑來尋找和載入所有的run-path-dependent libraries。

為了提取所有的run-path搜尋路徑,dyld呼叫ImageLoader類的getRpaths()方法。該方法(被recursiveLoadLibraries()方法呼叫)簡單的解析程式中所有的LC_RPATH載入命令。對應每個這種載入命令,dyld提取出run-path搜尋路徑並新增到一個向量中(例如:一個表),如圖16所示。

圖16 提取並儲存所有內建的run-path搜尋路徑

有了run-path搜尋路徑列表,dyld就可以找到所有依賴的run-path-dependent libraries了。這部分邏輯程式碼在dyld.cpp的loadPhase3()函式中。如圖17所示,[email protected]字。如果有,dyld就迴圈迭代run-path搜尋表,[email protected],然後嘗試從新生成的路徑載入dylib。

圖17 搜尋run-path搜尋目錄,[email protected]

重要的一點是dyld搜尋的路徑順序是確定的,是符合LC_RPATH載入命令的順序的。如圖17中顯示的程式碼片段顯示,搜尋迴圈會不停尋找,直到找到目標dylib或者是所有的路徑都搜尋了。

圖18,圖解了搜尋過程。可以看到dyld搜尋了不同的run-path搜尋路徑,為了找到需要的run-path-denpendent dylib。注意在這個例子中,目標dylib是在第二個搜尋目錄中找到的。

圖18 Dyld搜尋多個run-path搜尋目錄

總結一下到此的發現:一個OS X系統是可以被劫持攻擊的,只要任何程式存在以下的任意條件: 1,包含一個LC_LOAD_WEAK_DYLIB載入命令,但是相關的dylib並不存在。 2,同時包含一個LC_LOAD*_DYLIB載入命令指向一個run-path-denpendent library([email protected]')和多個LC_RPATH載入命令。並且run-path-denpendent library沒有在第一個run-path搜尋目錄中。

本文的餘下部分會先講述一個完整的dylib劫持攻擊,然後給出幾個不同的攻擊(駐留,載入時劫持,遠端注入等),最後總結下如何防禦此類攻擊。

為了幫助讀者更好的理解dylib劫持攻擊,我們會盡量給出劫持攻擊的細節,包括嘗試攻擊,遇到的錯誤,到最後的成功。有了這些知識的幫助,就可以更容易的理解自動攻擊,攻擊場景識別,和如何防禦。

回顧之前描述的例子程式('rPathApp.app')。我們用來解釋連線run-path-denpendent dylib的。這個程式將會是我們劫持攻擊的目標。

dylib劫持攻擊的物件只能是存在漏洞的程式(滿足前面講述的兩個劫持條件之一的程式)。因為本例子程式(rPathApp.app)需要連線一個run-path-dependent dylib,它也許就滿足上面第二個條件。最簡單的檢測方式就是開啟載入器的debug logging功能,然後在命令列簡單的執行該程式。為了開啟這種logging,需要設定DYLD_PRINT_[email protected][email protected]現漏洞(例如:第一個擴充套件指向了不存在的dylib)如圖20所示。

圖20 存在漏洞的測試程式rPathApp

圖20展示了載入器第一次尋找目標dylib時,在指定位置沒有發現。和圖19中顯示的一樣,在這種情況下,攻擊者可以部署一個惡意的dylib到剛才第一次搜尋的路徑,之後載入器會載入惡意庫。

我們建立了一個簡單的dylib來扮演惡意的劫持庫。為了能夠在載入時自動執行,該dylib實現了一個建構函式。該建構函式在dylib成功載入後會自動執行。這是一個很好的特性,因為一般的dylib程式碼不會執行,直到主程式呼叫它的某個匯出函式。

圖21 一個dylib的建構函式將會自動執行

編譯組建完成後,將dylib重新命名,改成目標庫的名字:rpathlib。接下來,建立需要的目錄結構(Library/One/rpathLib.framework/Versions/A/)並將惡意的dylib複製進該目錄。這就保證了無論何時程式啟動,dyld在搜尋run-path-denpendent dylib時會找到劫持dylib。

圖22 惡意dylib被放置在第一個run-path搜尋目錄中

不幸的是,這一次劫持嘗試失敗了。程式意外的崩潰了。見圖23。

圖23 成功解析路徑,然後崩潰

雖然失敗了,但是好訊息就是,載入器找到了並嘗試載入劫持dylib(看圖23中的'RPATH successful expansion…'日誌訊息)。雖然程式崩潰了,但是載入器還是丟擲了一條詳細的異常資訊。這條異常看起來是自解釋的:劫持庫的版本和要求的版本不同。重新研究載入器的原始碼,找到了丟擲這條異常的程式碼。見圖24。

圖24 Dyld提取和比較合適的版本號

可以看到,載入器會呼叫doGetLibraryInfo()方法從被載入庫中的LC_ID_DYLIB載入命令中提取相容和當前的版本號。提取出來的相容版本號('minVersion')然後在和程式要求的版本進行對比。如果版本號太低,一個不相容的異常就會被丟擲。

解決此相容問題也不難,只需要透過在Xcode中更新版本號,重新編譯下就行。見圖25。

圖25 設定相容和當前版本號

檢查重新編譯的劫持dylib的LC_ID_DYLIB載入命令。確認已經更新版本號。見圖26

圖26 相容版本號和當前版本號

更新版本號後的劫持dylib又被複製程式序的第一個run-path搜尋目錄。重啟漏洞程式,顯示載入器找到了劫持dylib並且嘗試載入。可是雖然現在dylib版本相容。但是一個新的異常被丟擲,程式又一次崩潰。見圖27。

圖27 ‘符號沒有找到’異常

又一次,異常給出的解釋清晰說明了載入器為什麼丟擲異常。程式連線動態庫的目的就是獲得動態庫匯出的功能(比如:函式,物件等)。一旦被需求的dylib被載入進記憶體,載入器就會嘗試解析(透過匯出符號)依賴庫試圖匯出的功能物件。如果功能物件未發現就會連線失敗,連線程式就會終止,導致主程式崩潰。

有幾種方法可以確保劫持dylib匯出正確的符號表,這樣才能完整的進行連線。一個簡單的方法就是劫持dylib直接仿造目標dylib的匯出資訊。也許這樣就可以成功了,看起來有點複雜並且不同的dylib各有特點(比如,攻擊另外一個dylib需要另外的匯出資訊)。一個更優雅的辦法是簡單的讓聯結器去別的地方尋則它要求的符號。當然別的地方就是指合法的dylib。在這個場景中,劫持dylib將簡單的扮演一個代理或者是一個‘re-exporter’dylib,載入器將會跟隨它的重匯出指令,沒有連線錯誤會被丟擲。

圖28 重匯出合法的dylib

需要付出一些努力,才能讓重匯出的庫完美工作。第一步是回到Xcode,新增多個連結的flags到劫持dylib專案。這些flags包括“-Xlinker ',' reexport_library ',然後還有到包含漏洞程式真正需要匯出介面的目標庫的路徑。

圖29 要求的連結flag,來實現re-exporting

這些連結flags會生成一個內建的LC_REEXPORT_DYLIB載入命令。其中包含到目標dylib的路徑。見圖30。

圖30 內建的LC_REEXPORT_DYLIB載入命令

然而,事情並非如此簡單。因為劫持dylib重匯出目標是一個run-path-denpendent library。LC_REEXPORT_DYLIB(從合法的dylib的LC_ID_DYLIB載入命令中匯出)[email protected],因為不像LC_LOAD*_DYLIB載入命令,dyld不會解析LC_REEXPORT_DYLIB載入命令中的run-path-denpendent路徑。換句話說,[email protected][email protected]的。

[email protected],提供目標庫的完整路徑給LC_REEXPORT_DYLIB載入命令。這需要藉助一款蘋果開發者工具:install_name_tool。來更新LC_REEXPORT_DYLIB載入命令中的install name。這個工具執行時,用-change選項,隨後是現存的name(LC_REEXPORT_DYLIB中的),新的name,劫持dylib的路徑。見圖31。

圖31 使用installl_tool_name來更新內建的name

在LC_REEXPORT_DYLIB載入命令正確更新後,劫持dylib被重新複製到主程式的第一個run-path搜尋目錄,重啟程式。如圖32,最終成功執行。

圖32 成功劫持又漏洞的程式

總結一下:因為rPathApp程式連線一個run-path-denpendent庫,而這個庫在第一個run-path搜尋目錄中沒有找到,所有存在了dylib劫持漏洞。植入一個特殊相容的惡意dylib在第一個搜尋目錄中會導致在每一次程式執行時,載入器都會盲目的載入這個惡意dylib。因為這個惡意dylib擁有正確的版本資訊,同時重匯出了合法目標dylib的所有符號,所有需要的符號都能解決,因此保證了程式的功能不會受損。

0x03 參考


  1. Secure loading of libraries to prevent DLL preloading attacks. http://blogs.technet.com/cfs-file.ashx/__key/CommunityServer-Components-PostAttachments/00-03-35-14-21/Secure-loading-of-libraries-to-prevent-DLL-Preloading.docx.
  2. DLL hijacking. http://en.wikipedia.org/wiki/Dynamic-link_library#DLL_hijacking.
  3. Dynamic-Link Library Hijacking. http://www.exploit-db.com/wp-content/themes/exploit/docs/31687.pdf.
  4. Windows NT Security Guidelines. http://www.autistici.org/loa/pasky/NSAGuideV2.PDF.
  5. What the fxsst? https://www.mandiant.com/blog/fxsst/.
  6. Leaked Carberp source code. https://github.com/hzeroo/Carberp.
  7. Windows 7 UAC whitelist: Proof-of-concept source code. http://www.pretentiousname.com/misc/W7E_Source/win7_uac_poc_details.html.
  8. Microsoft Security Advisory 2269637; Insecure Library Loading Could Allow Remote Code Execution. https://technet.microsoft.com/en-us/library/security/2269637.aspx.
  9. What is dll hijacking? http://stackoverflow.com/a/3623571/3854841.
  10. OS X loader (dyld) source code. http://www.opensource.apple.com/source/dyld.
  11. MachOView. http://sourceforge.net/projects/machoview/.
  12. Run-Path Dependent Libraries. https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/RunpathDependentLibraries.html.
  13. Using @rpath: Why and How. http://www.dribin.org/dave/blog/archives/2009/11/15/rpath/.
  14. Friday Q&A 2012-11-09: dyld: Dynamic Linking On OS X. https://www.mikeash.com/pyblog/friday-qa-2012-11-09-dyld-dynamic-linking-on-os-x.html.
本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章