Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/msf/core/exploit_driver.rb
Views: 11780
# -*- coding: binary -*-12module Msf34###5#6# This class drives the exploitation process from start to finish for a given7# exploit module instance. It's responsible for payload generation, encoding,8# and padding as well as initialization handlers and finally launching the9# exploit.10#11###12class ExploitDriver1314#15# Initializes the exploit driver using the supplied framework instance.16#17def initialize(framework)18self.payload = nil19self.exploit = nil20self.use_job = false21self.job_id = nil22self.force_wait_for_session = false23self.keep_handler = false24self.semaphore = Mutex.new25end2627#28# Specification of the exploit target index.29#30def target_idx=(target_idx)31if (target_idx)32# Make sure the target index is valid33if (target_idx >= exploit.targets.length)34raise Rex::ArgumentError, "Invalid target index.", caller35end36end3738# Set the active target39@target_idx = target_idx40end4142#43# This method returns the currently selected target index.44#45def target_idx46@target_idx47end4849#50# Checks to see if the supplied payload is compatible with the51# current exploit. Assumes that target_idx is valid.52#53def compatible_payload?(payload)54!exploit.compatible_payloads.find { |refname, _| refname == payload.refname }.nil?55end5657##58#59# Exploit execution60#61##6263#64# Makes sure everything's in tip-top condition prior to launching the65# exploit. For things that aren't good to go, an exception is thrown.66#67def validate68# First, validate that a target has been selected69if (target_idx == nil)70raise MissingTargetError,71"A payload cannot be selected until a target is specified.",72caller73end7475# Next, validate that a payload has been selected76if (payload == nil)77raise MissingPayloadError,78"A payload has not been selected.", caller79end8081# Make sure the payload is compatible after all82unless compatible_payload?(payload)83raise IncompatiblePayloadError.new(payload.refname), "#{payload.refname} is not a compatible payload.", caller84end8586unless exploit.respond_to?(:allow_no_cleanup) && exploit.allow_no_cleanup87# Being able to cleanup requires a session to be created from a handler, and for that88# session to be able to be able to clean up files89can_cleanup = payload.handler_klass != Msf::Handler::None && payload&.session&.can_cleanup_files90if exploit.needs_cleanup && !can_cleanup91raise IncompatiblePayloadError.new(payload.refname), "#{payload.refname} cannot cleanup files created during exploit. To run anyway, set AllowNoCleanup to true"92end9394if exploit.needs_cleanup && !exploit.handler_enabled?95raise ValidationError.new('Cannot cleanup files created during exploit if payload handler is disabled. To run anyway, set AllowNoCleanup to true')96end97end9899# Associate the payload instance with the exploit100payload.assoc_exploit = exploit101102# Finally, validate options on the exploit module to ensure that things103# are ready to operate as they should.104exploit.options.validate(exploit.datastore)105106# Validate the payload's options. The payload's datastore is107# most likely shared against the exploit's datastore, but in case it108# isn't.109payload.options.validate(payload.datastore)110111return true112end113114#115# Kicks off an exploitation attempt and performs the following four major116# operations:117#118# - Generates the payload119# - Initializes & monitors the handler120# - Launches the exploit121# - Cleans up the handler122#123def run124# First thing's first -- validate the state. Make sure all requirement125# parameters are set, including those that are derived from the126# datastore.127validate()128129# After validation has occurred, it's time to set some values on the130# exploit instance and begin preparing the payload131exploit.datastore['TARGET'] = target_idx132133# Default the session to nil134self.session = nil135136# Explicitly clear the module's job_id in case it was set in a previous137# run138exploit.job_id = nil139140# If we are being instructed to run as a job then let's create that job141# like a good person.142if (use_job or exploit.passive?)143# Since references to the exploit and payload will hang around for144# awhile in the job, make sure we copy them so further changes to145# the datastore don't alter settings in existing jobs146e = exploit.replicant147p = payload.replicant148149# Assign the correct exploit instance to the payload150p.assoc_exploit = e151152# Generate the encoded version of the supplied payload for the153# newly copied exploit module instance154e.generate_payload(p)155ctx = [ e, p ]156157e.job_id = e.framework.jobs.start_bg_job(158"Exploit: #{e.refname}",159ctx,160Proc.new { |ctx_| job_run_proc(ctx_) },161Proc.new { |ctx_| job_cleanup_proc(ctx_) }162)163self.job_id = e.job_id164else165# Generate the encoded version of the supplied payload on the166# exploit module instance167exploit.generate_payload(payload)168169# No need to copy since we aren't creating a job. We wait until170# they're finished running to do anything else with them, so171# nothing should be able to modify their datastore or other172# settings until after they're done.173ctx = [ exploit, payload ]174175begin176job_run_proc(ctx)177rescue ::Interrupt178job_cleanup_proc(ctx)179raise $!180ensure181# For multi exploit targets.182# Keep the payload handler until last target or interrupt183job_cleanup_proc(ctx) unless keep_handler184end185end186187return session188end189190attr_accessor :exploit # :nodoc:191attr_accessor :payload # :nodoc:192attr_accessor :use_job # :nodoc:193#194# The identifier of the job this exploit is launched as, if it's run as a195# job.196#197attr_accessor :job_id198attr_accessor :force_wait_for_session # :nodoc:199attr_accessor :session # :nodoc:200attr_accessor :keep_handler # :nodoc:201202# To synchronize threads cleaning up the exploit and the handler203attr_accessor :semaphore204205protected206207#208# Job run proc, sets up the exploit and kicks it off.209#210def job_run_proc(ctx)211begin212exploit, payload = ctx213# Default session wait time..214delay = payload.wfs_delay + exploit.wfs_delay215delay = nil if exploit.passive?216217# Set the exploit up the bomb218exploit.setup219220exploit.framework.events.on_module_run(exploit)221222# Launch the exploit223exploit.exploit224225rescue ::Exception => e226if [::RuntimeError, ::Interrupt].include?(e.class)227# Wait for session, but don't wait long.228delay = 0.01229end230231fail_reason = exploit.handle_exception(e)232end233234# Start bind handlers after exploit completion235payload.start_handler if exploit.handler_bind?236237# Wait the payload to acquire a session if this isn't a passive-style238# exploit.239return if not delay240241if (force_wait_for_session == true) or242(exploit.passive? == false and exploit.handler_enabled?)243begin244self.session = payload.wait_for_session(delay)245rescue ::Interrupt246# Don't let interrupt pass upward247end248end249250return self.session if self.session251252if exploit.fail_reason == Msf::Exploit::Failure::None253exploit.fail_reason = Msf::Exploit::Failure::PayloadFailed254exploit.fail_detail = "No session created"255exploit.report_failure256end257258if fail_reason && fail_reason == Msf::Exploit::Failure::UserInterrupt259raise ::Interrupt260end261end262263#264# Clean up the exploit and the handler after the job completes.265#266def job_cleanup_proc(ctx)267exploit, payload = ctx268269# Ensure that, no matter what, clean up of the handler occurs270semaphore.synchronize { payload.stop_handler }271272exploit.framework.events.on_module_complete(exploit)273274# Allow the exploit to cleanup after itself, that messy bugger.275semaphore.synchronize { exploit.cleanup }276end277278end279280end281282283284