2
votes

I need to launch a PowerShell script when a certain event happens, and I am using WMI classes to get persistence. I can get it working only partially, and need some help to make it fully working. So, here is what works and what doesn't...

The following code works, and will launch PowerShell in background when calc.exe is launched (I selected this event for simplicity just for testing purposes).

$fname = "testFilter"
$cname="testConsumer"
$exePath="C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
$query="SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name='calc.exe'"
$WMIEventFilter=Set-WmiInstance -Class __EventFilter -Namespace "root\subscription" -Arguments @{Name=$fname;EventNameSpace="root\cimv2";QueryLanguage="WQL";Query=$query}
$WMIEventConsumer=Set-WmiInstance -Class CommandLineEventConsumer -Namespace "root\subscription" -Arguments @{Name=$cname;ExecutablePath=$exePath}
Set-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer} | out-null

However, if I modify the $exePath variable to pass arguments to powershell.exe then it doesn't work anymore (no powershell process gets created).

I also tried to replace CommandLineEventConsumer with ActiveScriptEventConsumer, and use a VBScript to launch powershell. Here is the modified code (only line 3 and 5 are different):

$fname = "testFilter"
$cname="testConsumer"
$scriptPath="D:\Work\LaunchPowerShell.vbs"
$query="SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name='calc.exe'"
$WMIEventFilter=Set-WmiInstance -Class __EventFilter -Namespace "root\subscription" -Arguments @{Name=$fname;EventNameSpace="root\cimv2";QueryLanguage="WQL";Query=$query}
$WMIEventConsumer=Set-WmiInstance -Class ActiveScriptEventConsumer -Namespace "root\subscription" -Arguments @{Name=$cname;ScriptFileName=$scriptPath;ScriptingEngine="VBScript"}
Set-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer} | out-null

And the LaunchPowerShell.vbs:

Dim objShell : Set objShell = WScript.CreateObject("WScript.shell")
objShell.run("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe D:\Work\MyScript.ps1")

The VB script works as intended when launched from a command prompt (cmd.exe), but no luck to get powershell running when the event is being triggered (that is, when calc.exe is launched). It won't run even if I remove my script from the powershell arguments, so not sure what the problem is.

If anyone can help that would be much appreciated. Thanks!!!

1
I think you want to look at the CommandLineTemplate property of the CommandLineEventConsumer class. You specify what the command line would be. - Shawn Esterman

1 Answers

3
votes

If you specify the CommandLineTemplate instead of the ExecutablePath you can add arguments to your string.

$fname = "testFilter"
$cname = "testConsumer"
$CommandLineTemplate = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -File D:\Work\MyScript.ps1"
$ExecutablePath = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
$query = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name='calc.exe'"

$WMIEventFilter = Set-WmiInstance -Class __EventFilter -Namespace "root\subscription" -Arguments @{Name=$fname;EventNameSpace="root\cimv2";QueryLanguage="WQL";Query=$query}
$WMIEventConsumer = Set-WmiInstance -Class CommandLineEventConsumer -Namespace "root\subscription" -Arguments @{Name=$cname;CommandLineTemplate=$CommandLineTemplate;ExecutablePath=$ExecutablePath }

Set-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer} | out-null

Source:

CommandLineTemplate

Data type: string

Access type: Read-only

Standard string template that specifies the process to be started. This property can be NULL, and the ExecutablePath property is used as the command line.