首款反射式PE殼<琥珀>
首款反射式PE殼<琥珀>簡介
由於操作係統內部日益增加的安全標準和惡意軟件檢測技術的快速改進,現如今的惡意軟件作者開始利用由內存執行。PE的內存執行或者無文件執行可以被定義為在內存中執行一個編譯的PE文件,手動運行OS加載程序在正常PE文件加載時應有的操作。惡意軟件的內存執行有助於混淆和反模擬技術。另外,正在使用這種方法的惡意軟件在係統上留下的痕跡更少,因為內存執行沒必要在硬盤上占有一個文件。內存執行方法和多階段注入模型組合,可以使用及其小的程序加載器將惡意軟件注入係統。加載程序的唯一目的是通過鏈接到遠程係統來加載和執行實際的惡意軟件代碼。使用小型加載器的代碼很難被安全產品檢測,因為加載器的代碼片段在合法應用程序中也普遍使用。使用這種方法的惡意軟件仍然可以通過掃描內存並檢查進程的行為來檢測,但是在安全性方麵,這些操作難以實施,因為資源使用量較高而且代價昂貴。(Ramilli, 2010[1])
目前普遍增長的趨勢是使用機器學習機製自動檢測惡意軟件,給係統提供巨大的數據集,如所有的機器學習程序一樣,這種機製可以更快更準確的吸收更多的惡意軟件樣本。這些機製可以提供大量的人類惡意軟件分析師無法處理的級別的樣本。Malware Detection Using Machine Learning[2]由BitDefender Romania Labs的 Gavriluţ Dragoş發表的這篇論文廣泛的闡述了機器學習在惡意軟件檢測中的使用的內部原理。根據Konrad Rieck的論文 Automatic Analysis of Malware Behavior using Machine Learning[3],隻要有足夠的數據和時間,假陽性的結果將趨近於0,並且惡意軟件的檢測將在新的惡意軟件樣本上產生顯著效果。
這項工作的主要目的是為PE文件開發一種新的加殼方法,可以改變將惡意軟件傳送到係統的方式。取代試圖找到新的反檢測技術來提供機器學習的數據集,通過無文件代碼注入將payload加載到係統中從而繞過絕大多數的安全機製。通過這種新的加殼方法,可以將PE文件轉化為可用於常見軟件漏洞(如緩衝區溢出)的多階段注入的payload。
已知方法
以下的技術是我們殼的靈感來源:
反射式DLL注入[4]是一個非常好的由 Stephen Fewer 開發的庫注入技術,該方法是開發這個名為琥珀的殼的主要啟發點。這種技術允許在內存執行中用反射編程的方法編寫特定的DLL。由於采用了反射編程方法,這種技術允許多階段payload的部署。除了這種技術的諸多優點之外幾乎沒有限製。第一個限製是所需的文件格式,該技術期望將惡意軟件作為DLL文件進行開發或重新編譯,不幸的是在大多數情況下,將已編譯的EXE文件轉換為DLL是不可能的,或者需要對二進製文件進行大量工作。第二個限製是需要重定位數據。反射型DLL注入技術需要重定位數據來調整內存中DLL的基址。同時,這種方法已經存在了一段時間了,這意味著最新的安全產品可以很容易的檢測到反射型DLL注入的使用。我們的新工具,琥珀將為這些限製提供解決方案。
Process Hollowing[5]是另一種廣為人知的內存執行方法,使用公開的WindowsAPI創建新的進程然後將PE文件映射進該進程。這種旨在降低惡意軟件檢測率的加密器和殼中很受歡迎。但是這個方法也有幾個缺點。由於最新的Windows操作係統中的地址空間布局隨機化(ASLR)安全措施,創建新進程時內存區域是隨機的,因為process hollowing同樣也需要實現在最新的Windows操作係統上的鏡像基址重定位。如上所述,基址重定位需要PE文件內的重定位數據。另一個缺點是由於特定文件的映射和進程創建API函數的使用有特定的順序,這種方法很容易被安全產品識別。
Hyperion[6] 是一款PE加密器,由Christian Amman 於 2012開發並發布。它解釋了運行時加密器的理論知識以及實現原理。在開發Hyperion是使用的PE解析方法和設計視角對我們的POC殼很有幫助。
技術細節
通過模仿OS的PE加載器,可以在OS內存中執行編譯的二進製文件是該殼的基本原理。在Windows上,PE加載器執行許多重要的事情,諸如將問價映射到內存並解析導入函數的地址是執行PE文件最重要的步驟。目前用於在內存中執行EXE文件的方法是使用特定的WindowsAPI函數來模擬WindowsPE加載器。通常的方法是使用NtMapViewOfSection
,MapViewOfFile
和CreateFileMapping
函數。這些函數的使用通常會造成可疑行為,增加惡意軟件檢測的可能性。開發這款殼的關鍵方麵之一就是盡量減少API函數。為了避免使用可疑文件映射API函數,我們的殼使用預先封裝的PE映像,此外,惡意軟件的執行發生在目標進程內部,不使用WindowsAPICreateProcess
函數。目標進程內執行的惡意軟件以相同的進程權限運行,因為它們共享了包含進程特權信息和配置的TEB塊。琥珀有兩種你類型的stub,其中一個用於支持ASLR,另一個用於被剝離或不具有任何重定位數據的EXE文件。ASLR stub僅使用4個Windows API,其他的stub僅使用3個大多數合法應用程序廣泛使用的API。
ASLR stub:
VirtualAlloc
CreateThread
LoadLibraryA
GetProcAddress
非ASLR stub:
VirtualProtect
LoadLibraryA
GetProcAddress
為了在運行時調用這些API,琥珀使用了Stephen Fewer的反射式DLL注入[4]方法所使用的公開的EAT解析技術。該技術簡單在內存中通過PEB來定位InMemoryOrderModulesList結構。定位該結構後,可以讀取所有加載的DLL導出表,讀取由InMemoryOrderModuleList指向的每個_LDR_DATA_TABLE_ENTRY結構。在訪問到DLL的導出表之後,將先前計算出的每個導出函數名的ROR(右移)13散列值進行比較,直到匹配。琥珀的加殼方法還提供了集中替代的WindowsAPI使用方法,其中之一是使用固定的API地址,如果使用者熟知承載琥珀的遠程進程的相關信息的話。使用固定API地址將直接繞過最新的操作係統級漏洞利用,檢查導出表地址刪除API地址查找代碼將減少總體的payload大小。另一種替代技術可用於定位所需功能的地址,例如 Josh Pitts 在 “Teaching Old Shellcode New Tricks”[7]中展示的技巧。當前版本的琥珀加殼器僅支持固定API地址和EAT解析技術,但IAT解析將在下一個版本中添加。
生成payload
為了生成實際的琥珀payload,首先加殼器創建一個惡意軟件的內存映像,生成的內存映射文件包含PE的所有部分,PE header和未使用的區段空間使用0填充。
獲取惡意軟件的映射之後,加殼器將檢查所提供的EXE的ASLR的兼容性,如果EXE是ASLR兼容加殼器將添加相關的stub,如果PE使用固定基址就不添加。此刻,琥珀的payload就完成了:
ASLR Stub的執行
執行ASLR stub需要5個步驟:
- 申請內存
- 修複導入函數
- 重定位
- FileMapping替換
- 執行
在內存申請階段,stub通過調用VirtualAlloc函數來分配惡意軟件映像大小相同的RWE內存空間,
這個內存空間將是重定位過程後惡意軟件新的基址。第二階段,琥珀的stub將解析導入函數的地址,並將地址寫入惡意軟件的導入表。
地址戒心階段與WindowsPE加載程序使用的方法非常類似,琥珀的stub將解析映射的惡意軟件映像的導入表,並通過LoadLibraryA函數加載惡意軟件的IMAGE_IMPORT_DESCRIPTOR中使用的每個DLL。
在加載完所需的DLL後,stub會保存每個DLL的句柄,並在GetProcAddressAPI的幫助下,從加載的DLL中查找導入函數的地址。IMAGE_IMPORT_DESCRIPTOR還包含一個指向名為import name表的結構指針,該結構的導入函數名與導入地址表(IAT)順序相同,在調用GetProcAddress時,stub以前加載的DLL句柄和導入函數的名稱為參數。每個返回的函數地址都將寫入(IAT),每個IAT之間由4字節填充。此過程持續到導入表解析結束,加載完所需的DLL和解析完導入表之後,第二階段完成。
在第三階段,stub將根據VirtualAlloc返回的地址開始重定位過程,這幾乎和Windows本身的PE加載器完全相同,stub首先計算當前加載基址和原始加載基址之間的偏移delta,然後將delta加上重定位白的每一個條目。在第四階段,stub將文件映射到先前分配的空間中,采用單字節移動的方式來移動內存。
最後階段,stub將通過調用CreateThread從惡意軟件的入口處創建一個新的線程。創建新線程的原因是為惡意軟件創建一個新的可擴展棧,另外在新線程中執行惡意軟件並不會映像目標進程的執行狀態。創建惡意軟件後,線程將恢複執行,返回到第一個調用者或stub,然後跳轉到一個死循環,阻塞防線線程,惡意軟件線程成功運行。
非ASLR Stub的執行
非ASLR Stub的執行需要4個步驟:
- 內存申請
- 解析IAT
- 文件映射替換
- 執行
如果惡意軟件被剝離或者沒有重定位信息,則無法將其放到首選基地址。在這種情況下,stub嚐試通過調用VirtualPtotect函數來更改目標進程的內存訪問權限,大小為惡意軟件的大小。如果出現這種情況,首選極其之和目標進程代碼段可能由重疊,並且目標進程在執行payload後將無法執行。
stub可能無法更改指定區域的訪問權限,這又多個原因,如執行的內存返回不在當前進程頁邊界內(原因最可能是ASLR),或執行的地址與stack guard重合。這是stub的主要限製,如果提供的惡意軟件沒有ASLR支持(內部沒有重定位數據),並且stub不能更改目標進程訪問權限,則無法繼續。在某些情況下,stub成功更改內存區域權限,但立即崩潰,這是由於覆蓋部分中運行著多個線程引起的。如果目標進程在fix stub執行時有多個線程,則可能會由於更改內存權限或覆蓋到正在運行的部分崩潰。然而,如果不使用具有fix stub的多級payload,則這些限製無關緊要,當前的POC封裝器可以相應的調整生成EXE文件的基址和stub payload的位置。如果內存分配結束,第一階段就完成了。第二階段與上邊ASLR stub方法相同。完成後同樣使用memcpy移動內存到先前修改的內存區域。
在最後階段,stub跳轉到惡意軟件的入口點並執行,不創建新線程。不幸的是使用非ASLR stub的程序不能繼續之前的運行狀態。
多階段程序
在不久的將來,操作係統將會采取的安全措施將會減少惡意軟件的攻擊麵。微軟已經在2017年5月2日發布了Windows 10 S[8],這個操作係統基本上是Windows10的配置了更高安全性的版本。這個操作係統采取的主要預防措施之一是不允許安裝除WindowsStore以外的程序。這種操作係統采用的白名單方法將對通過可執行文件感染係統的惡意軟件產生巨大影響。在這種情況下,多級內存執行payload將成為最有效的攻擊方法之一。由於stub位置的獨立性,它允許多階段攻擊模型,當前的POC加殼器能夠從複雜的PE文件中生成一個payload,可以從內存加載和執行,如常規的shell code注入攻擊。在這種過度限製的係統用中,琥珀的多階段兼容性允許利用基於內存的常見軟件漏洞,例如棧和堆的緩衝區溢出。
然而由於fix stub的限製,建議在執行多級感染攻擊時使用ASLR支持的EXE文件。由POC加殼器生成的階段payload與從Metasploit Framework [9]生成的小型加載器shellcode和有效載荷兼容,這也就意味著琥珀可以用於Metasploit Framework 中多級meterpreter shell code。
源碼如下,歡迎fork以及contribute!
https://github.com/EgeBalci/Amber
被檢出率
當前版本(2017.10.19)檢測率令人相當滿意,但由於這是一個公共項目,目前的檢測分數不可避免的會上升。
當沒有額外的參數傳遞(隻有文件名)加殼器生成的多級載荷使用多字節隨機密鑰執行基本的XOR加密,然後將其編譯成EXE文件,並加入少量額外的防檢測功能。生成的EXE文件在解密payload並執行所需的環境檢查之後,像常規的shell code一樣執行payload。這個特殊的例子時用12字節XOR key(./amber mimikatz.exe -ks 12
)打包的mimikatz.exe(sha256- 9369b34df04a2795de083401dda4201a2da2784d1384a6ada2d773b3a81f8dad)文件。在VirusTotal上,加殼前的mimikatz.exe文件的檢測率為51/66。在這個特殊的示例中,加殼程序使用默認方式來查找使用哈希API的Windows API地址,避免使用hash API會降低檢測率。目前加殼器支持IAT偏移的固定地址的使用,下一個版本將包括IAT解析器shellcode以獲得更多的替代API地址查找方法。
VirusTotal檢測
VirusCheckmate Result
https://viruscheckmate.com/id/1ikb99sNVrOM
NoDistribute
https://nodistribute.com/result/image/7uMa96SNOY13rtmTpW5ckBqzAv.png
未來工作
這項工作為PE文件引入了新一代的加殼方法,但不支持.NET可執行文件,未來的工作可能包括對64位PE文件和.NET文件的支持。另外,這種方法的隱秘性方麵可以有更多的改進。在使用RWE權限完成內存分配之後,根據映像對應的區段權限修改該區段對應內存的權限可能會降低檢測率。在地址解析完成後擦除PE頭可以更難檢測。該項目在未來將繼續保持開源。
參考鏈接
[1] Ramilli, Marco, and Matt Bishop. “Multi-stage delivery of malware.” Malicious and Unwanted Software (MALWARE), 2010 5th International Conference on. IEEE, 2010.
[2] Gavriluţ, Dragoş, et al. “Malware detection using machine learning.” Computer Science and Information Technology, 2009. IMCSIT’09. International Multiconference on. IEEE, 2009.
[3] Rieck, Konrad, et al. “Automatic analysis of malware behavior using machine learning.” Journal of Computer Security 19.4 (2011): 639-668.
[4] Fewer, Stephen. “Reflective DLL injection.” Harmony Security, Version 1 (2008).
[5] Leitch, John. “Process hollowing.” (2013).
[6] Ammann, Christian. “Hyperion: Implementation of a PE-Crypter.” (2012).
[7] Pitts, Josh. “Teaching Old Shellcode New Tricks” https://recon.cx/2017/brussels/resources/slides/RECON-BRX-2017 Teaching_Old_Shellcode_New_Tricks.pdf (2017)
[9] Rapid7 Inc, Metasploit Framework https://www.metasploit.com
[10] Desimone, Joe. “Hunting In Memory” https://www.endgame.com/blog/technical-blog/hunting-memory (2017)
[11] Lyda, Robert, and James Hamrock. “Using entropy analysis to find encrypted and packed malware.” IEEE Security & Privacy 5.2 (2007).
[12] Nasi, Emeric. “PE Injection Explained Advanced memory code injection technique” Creative Commons Attribution-NonCommercial-NoDerivs 3.0 License (2014)
[13] Pietrek, Matt. “Peering Inside the PE: A Tour of the Win32 Portable Executable File Format” https://msdn.microsoft.com/en-us/library/ms809762.aspx (1994)
原文鏈接https://pentest.blog/introducing-new-packing-method-first-reflective-pe-packer/
本文由看雪論壇zplusplus翻譯。
最後更新:2017-11-06 18:03:46