Grey Energy惡意軟體脫殼
最近我偶然發現了一個惡意軟體樣本,它是針對烏克蘭能源基礎設施攻擊行動中Gray Energy惡意軟體的一部分。我在virutotal 上運行了該文件,許多反病毒軟體標記為Gray Energy。我試圖在互聯網上搜尋更多相關研究,但沒有找到。因為沒有帖子分析這個樣本,所以我決定寫一個。
在本文中你會學到以下內容:
1.如何調試Windows服務應用程序DLL
2.了解如何使用EBFE調試技術
3.DLL二進位文件脫殼
4.如何轉儲內存中脫殼的可執行文件
一、識別惡意軟體
使用一些基本的靜態分析工具,可以知道它是一個64位Windows DLL。
因為它是一個DLL,我們需要看到導出表。導出函數只有一個ServiceMain。這種方法通常由Windows服務應用程序DL導出。這是在向Windows服務應用程序發出請求時調用的函數。
檢查導入部分,可以看到導入了以下DLL。但是當我們進一步的分析時,發現並非所有導入的DLL都在使用。
二、Windows服務應用程序簡介
如果已經了解Windows Service,那麼建議跳過本節。我將從惡意軟體作者的角度描述有關Windows服務的所有必要內容,但如果有興趣了解它,那麼可以參考本文末尾參考部分中的鏈接。
什麼是Windows服務?
Windows服務應用程序用於創建長時間運行的後台應用程序,可以在系統引導/重新引導時自動啟動它並且沒有用戶界面。可以將服務置於各種狀態,如啟動、停止、暫停、恢復和重新啟動,所有這些都由Windows服務控制器(services.exe)管理。這些功能使其成為惡意軟體的理想選擇,可以在後台運行任何惡意軟體,並且在重啟時也可以長時間運行。服務的實際用例類似於Web伺服器service,記錄機器性能指標,如CPU、RAM等。服務可執行文件是具有已定義入口點的DLL。
可以編寫一個服務作為獨立進程或作為服務控制管理器(svchost.exe)進程的一部分運行(它為每個服務創建一個線程,並允許該服務創建更多線程)。如果服務在SC中運行,則SC為服務創建線程,然後載入其DLL,並調用服務入口點以將服務移動到其狀態(首先啟動,然後最終停止)。從svchost.exe進程(系統服務)創建線程,可為其提供危險的系統許可權,但可以在用戶帳戶的特定安全上下文中運行DLL,該安全上下文因登錄用戶而異。
服務應用程序需要以下項:
要創建服務DLL,需要滿足特定要求,如下所示:
1.Main Entry point: 這是通過調用StartServiceCtrlDispatcher註冊服務所必需的,是DLL入口點。
2.Service Entry point: 這是DLL導出項中的ServiceMain,此功能的任務如下:
·初始化從DLL入口點延遲的任何必要項。註冊服務控制處理程序,它將處理服務停止、暫停、繼續、關閉等控制命令。
·將服務狀態設置為SERVICE_PENDING,然後設置為SERVICE_RUNNING。在出錯和退出時將狀態設置為SERVICE_STOPPED。
·執行啟動任務。就像創建線程/事件/互斥/ IPC /等一樣。
3.Service Control Handler: 服務控制處理程序已在ServiceMain入口點中註冊。每個服務都必須有一個處理程序來處理來自SCM的控制請求。此處理程序將在SCM的上下文中調用,並將保持SCM,直到它從處理程序返回。Service Handler在各種事件上調用,如start、stop、paused等,它們作為參數傳遞給處理函數。
三、基本靜態分析
我們首先對Dll入口點進行靜態分析,這是第一個甚至可能在ServiceMain之前執行的函數。下面是Dll入口點的反彙編。
進一步查看反彙編,發現有一些內存分配和內存操作。還有一個有趣的函數是在地址0x2c0202bc處找到的,這個函數是在分配內存之後調用的,它似乎像解密函數,或者至少準備好解密。以下是此函數的反彙編。
由於存在一些XOR運算,其值從寄存器rsp + 0x68中選取,之後將某些操作數據寫入[rbx + rsi * 2]轉換為相同的地址。我們可以在動態分析中驗證這一點。由於IDA和radare2分析都沒有識別出很多函數,所以我確信可執行文件被加殼。
讓我們看一下ServiceMain的反彙編代碼。
這些指示似乎沒有任何意義。這進一步證實了我們對可執行文件加殼的懷疑。我們可以使用radare2熵計算函數來檢查執行中每個段的熵。如果存在任何具有高熵的段,則意味著該段保存加密數據。我們可以使用radare2 iS entropy命令來計算每個段的熵,下面是該命令的結果。
可以清楚地看到.text段與其他段相比具有非常高的熵。這證實了我們對可執行文件加殼的懷疑。在接下來章節中,我們將嘗試為服務應用程序設置調試環境,因為它不像其他Windows應用程序那樣直接,並使用動態分析提取加殼的可執行文件。
四、如何調試服務應用程序DLL
如果這是一個普通的DLL,我們可以使用Immunity調試器來進行調試,但服務應用程序DLL是不同的,因為它們必須自己註冊並在執行的最初幾秒內聲明其狀態,在運行主入口點之前服務控制管理器(SCM)應該知道服務將要運行,並且DLL僅在SCM的上下文中運行。
因此,挑戰在於我們無法通過ad調試器獲取DLL入口點。如果可以設法在SCM運行DLL時暫停執行DLL入口點,就能克服此限制。
在做了一些研究後,我看到了一種名為EBFE的技術,可以在此鏈接(link)上閱讀更多相關信息。在該技術中,我們在要插入斷點處插入一個無限循環,一旦線程執行此指令,它就會將其置於無限循環中。 EBFE是一個指向自身的跳轉指令代碼,這將使執行線程處於無限循環中,然後我們一直將調試器連接到進程並開始調試。
接下來的問題是,如果我們將調試器附加到SCM,我們如何知道SCM生成的子進程?實際上非常簡單,一旦CPU執行無限循環指令,CPU消耗值將上升到非常高的值,例如90-100%。我們可以使用一個系統內部工具process explorer來獲取進程的ID號。
正如在上圖中看到的,一旦CPU執行EBFE指令,它就會進入無限循環,這會將CPU消耗增加到95-100%,這表明我們的進程已準備好連接。
現在我們已經弄清楚如何將調試器附加到_Service Application _,接下來我們必須將此指令放在將被執行的點上,即DLL的入口點。有兩個點,可以放置EBFE,即ServiceMain(服務入口點)和DllEntry(DLL入口點)。我們將EBFE指令放在這兩個函數上。在替換雙位元組指令之前,必須記下要替換的原始兩個位元組。一旦命中無限循環,我們將用原始位元組替換它並繼續調試。
五、動態脫殼
讓我們從分析Dll入口點開始,因為在這兩個函數中只有這個函數有一些合理的代碼。
首先,內存是根據原始可執行文件的大小分配的,它分配內存的方式很奇怪,它指定了想要分配的內存塊的基地址,如果失敗那麼它以10000h的間隔值從100000h處開始試圖分配內存。我們將不得不關閉此地址,因為脫殼的可執行文件位於此地址。
然後它更改分配的內存的內存許可權,並將每個段(.text,.rdata)複製到新分配的內存。
然後它使用去殼代碼中的Dll入口點函數修補當前DLL入口點。在修補內存地址之前,它會將內存許可權更改為寫入,然後將其還原為「讀取」和「執行」。
然後它循環脫殼DLL的導入地址表(IAT),並載入IAT中存在的DLL並解析導入函數並將其添加到表中。
這是代碼脫殼階段,之後解碼IAT,然後代碼跳轉到原始的Dll入口點以便執行。
六、轉儲脫殼的代碼
我們之前在脫殼可執行文件的地址中記錄的內存地址,如下面的轉儲中所示。
我們將使用內置在X64-dbg中的Scylla插件來轉儲可執行文件。必須指定可執行文件的基地址以及要用於恢復PE的內存大小,可以從地址列旁邊的內存面板和調試器的大小(在我們的示例中為23000)中查看並單擊dump PE保存可執行文件。
七、脫殼的二進位文件
脫殼後的二進位文件基本信息如下所示:
已脫殼二進位文件的導入表部分。
更多導入部分顯示二進位文件使用HTTP與C&C進行通信。
我們可以看到在ServiceMain函數中通過調用RegisterServiceCtrlHandleW和SetServiceStatus註冊服務,這意味著我們可以確定它確實是服務應用程序。
八、總結
我們設法對服務應用程序DLL進行脫殼,這個殼是專門設計的DLL,我們觀察到二進位文件的脫殼,然後將Dll入口點修補到原始代碼。它不是一種特殊的反調試技術,這使得它非常簡單,對初學者來說很有用。我們還學習了如何在此過程中轉儲內存中的二進位文件。
※NodeJS應用程序身份驗證繞過漏洞分析
※土耳其出現與MuddyWater Tools非常相似的PowerShell後門
TAG:嘶吼RoarTalk |