2012-06-29 00:18:28 -05:00
# -*- coding: binary -*-
2005-07-13 18:06:12 +00:00
module Msf
###
#
# This class drives the exploitation process from start to finish for a given
# exploit module instance. It's responsible for payload generation, encoding,
# and padding as well as initialization handlers and finally launching the
# exploit.
#
###
class ExploitDriver
2005-11-15 15:11:43 +00:00
#
# Initializes the exploit driver using the supplied framework instance.
#
2005-07-13 18:06:12 +00:00
def initialize ( framework )
2005-10-02 05:48:05 +00:00
self . payload = nil
self . exploit = nil
self . use_job = false
2007-04-04 02:49:08 +00:00
self . job_id = nil
2005-10-02 05:48:05 +00:00
self . force_wait_for_session = false
2018-09-25 11:28:59 +08:00
self . keep_handler = false
2015-07-20 16:09:13 -05:00
self . semaphore = Mutex . new
2005-07-13 18:06:12 +00:00
end
2013-08-30 16:28:33 -05:00
2005-07-13 18:06:12 +00:00
#
2005-11-15 15:11:43 +00:00
# Specification of the exploit target index.
2005-07-13 18:06:12 +00:00
#
def target_idx = ( target_idx )
2005-07-15 22:30:04 +00:00
if ( target_idx )
# Make sure the target index is valid
if ( target_idx > = exploit . targets . length )
raise Rex :: ArgumentError , " Invalid target index. " , caller
end
2005-07-13 18:06:12 +00:00
end
2013-08-30 16:28:33 -05:00
2005-07-13 18:06:12 +00:00
# Set the active target
2005-07-15 22:30:04 +00:00
@target_idx = target_idx
2005-07-13 18:06:12 +00:00
end
2013-08-30 16:28:33 -05:00
2005-11-11 01:49:02 +00:00
#
2005-11-15 15:11:43 +00:00
# This method returns the currently selected target index.
2005-11-11 01:49:02 +00:00
#
def target_idx
@target_idx
end
2013-08-30 16:28:33 -05:00
2005-07-13 18:06:12 +00:00
#
# Checks to see if the supplied payload is compatible with the
2005-07-15 22:30:04 +00:00
# current exploit. Assumes that target_idx is valid.
2005-07-13 18:06:12 +00:00
#
def compatible_payload? ( payload )
2005-12-14 00:43:18 +00:00
# Try to use the target's platform in preference of the exploit's
exp_platform = exploit . targets [ target_idx ] . platform || exploit . platform
2013-08-30 16:28:33 -05:00
2005-12-14 00:43:18 +00:00
return ( ( payload . platform & exp_platform ) . empty? == false )
2005-07-13 18:06:12 +00:00
end
2013-08-30 16:28:33 -05:00
2005-07-13 18:06:12 +00:00
##
#
# Exploit execution
#
##
2013-08-30 16:28:33 -05:00
2005-07-13 18:06:12 +00:00
#
# Makes sure everything's in tip-top condition prior to launching the
# exploit. For things that aren't good to go, an exception is thrown.
#
def validate
# First, validate that a target has been selected
2005-07-15 22:30:04 +00:00
if ( target_idx == nil )
2009-11-16 15:08:58 +00:00
raise MissingTargetError ,
2005-07-13 18:06:12 +00:00
" A payload cannot be selected until a target is specified. " ,
caller
end
2013-08-30 16:28:33 -05:00
2005-07-13 18:06:12 +00:00
# Next, validate that a payload has been selected
if ( payload == nil )
2009-11-16 15:08:58 +00:00
raise MissingPayloadError ,
2005-07-13 18:06:12 +00:00
" A payload has not been selected. " , caller
end
2013-08-30 16:28:33 -05:00
2005-07-15 22:30:04 +00:00
# Make sure the payload is compatible after all
if ( compatible_payload? ( payload ) == false )
2009-11-16 15:08:58 +00:00
raise IncompatiblePayloadError . new ( payload . refname ) ,
2020-05-05 19:20:34 +01:00
" #{ payload . refname } is not a compatible payload. " , caller
2005-07-15 22:30:04 +00:00
end
2022-08-08 01:40:15 +01:00
2021-11-17 15:24:38 +11:00
unless exploit . respond_to? ( :allow_no_cleanup ) && exploit . allow_no_cleanup
# Being able to cleanup requires a session to be created from a handler, and for that
# session to be able to be able to clean up files
2021-12-01 09:53:26 +11:00
can_cleanup = payload . handler_klass != Msf :: Handler :: None && payload & . session & . can_cleanup_files
2021-11-17 15:24:38 +11:00
if exploit . needs_cleanup && ! can_cleanup
raise IncompatiblePayloadError . new ( payload . refname ) , " #{ payload . refname } cannot cleanup files created during exploit. To run anyway, set AllowNoCleanup to true "
end
if exploit . needs_cleanup && ! exploit . handler_enabled?
raise ValidationError . new ( 'Cannot cleanup files created during exploit if payload handler is disabled. To run anyway, set AllowNoCleanup to true' )
end
end
2013-08-30 16:28:33 -05:00
2005-11-15 21:25:23 +00:00
# Associate the payload instance with the exploit
payload . assoc_exploit = exploit
2013-08-30 16:28:33 -05:00
2005-07-13 18:06:12 +00:00
# Finally, validate options on the exploit module to ensure that things
# are ready to operate as they should.
2005-07-15 22:30:04 +00:00
exploit . options . validate ( exploit . datastore )
2013-08-30 16:28:33 -05:00
2005-07-18 02:01:36 +00:00
# Validate the payload's options. The payload's datastore is
# most likely shared against the exploit's datastore, but in case it
# isn't.
payload . options . validate ( payload . datastore )
2013-08-30 16:28:33 -05:00
2005-07-13 18:06:12 +00:00
return true
end
2013-08-30 16:28:33 -05:00
2005-07-13 18:06:12 +00:00
#
# Kicks off an exploitation attempt and performs the following four major
# operations:
#
# - Generates the payload
# - Initializes & monitors the handler
# - Launches the exploit
# - Cleans up the handler
#
def run
# First thing's first -- validate the state. Make sure all requirement
# parameters are set, including those that are derived from the
# datastore.
validate ( )
2013-08-30 16:28:33 -05:00
2005-07-13 18:06:12 +00:00
# After validation has occurred, it's time to set some values on the
# exploit instance and begin preparing the payload
2005-11-11 01:49:02 +00:00
exploit . datastore [ 'TARGET' ] = target_idx
2013-08-30 16:28:33 -05:00
2005-07-16 07:32:11 +00:00
# Default the session to nil
2005-09-22 04:53:46 +00:00
self . session = nil
2013-08-30 16:28:33 -05:00
2010-07-16 21:47:00 +00:00
# Explicitly clear the module's job_id in case it was set in a previous
# run
exploit . job_id = nil
2013-08-30 16:28:33 -05:00
2005-09-22 04:53:46 +00:00
# If we are being instructed to run as a job then let's create that job
# like a good person.
2018-04-05 18:56:19 -05:00
if ( use_job or exploit . passive? )
2010-07-01 22:02:46 +00:00
# Since references to the exploit and payload will hang around for
# awhile in the job, make sure we copy them so further changes to
2010-07-07 16:37:23 +00:00
# the datastore don't alter settings in existing jobs
2010-07-06 21:09:53 +00:00
e = exploit . replicant
p = payload . replicant
2013-08-30 16:28:33 -05:00
2011-03-22 03:19:56 +00:00
# Assign the correct exploit instance to the payload
p . assoc_exploit = e
2013-08-30 16:28:33 -05:00
2010-07-07 16:37:23 +00:00
# Generate the encoded version of the supplied payload for the
# newly copied exploit module instance
e . generate_payload ( p )
2010-07-06 21:09:53 +00:00
ctx = [ e , p ]
2013-08-30 16:28:33 -05:00
2010-07-07 16:37:23 +00:00
e . job_id = e . framework . jobs . start_bg_job (
" Exploit: #{ e . refname } " ,
2008-11-17 19:51:09 +00:00
ctx ,
2009-10-25 17:18:23 +00:00
Proc . new { | ctx_ | job_run_proc ( ctx_ ) } ,
Proc . new { | ctx_ | job_cleanup_proc ( ctx_ ) }
2009-11-16 15:08:58 +00:00
)
2010-07-07 16:37:23 +00:00
self . job_id = e . job_id
2005-09-22 04:53:46 +00:00
else
2010-07-07 16:37:23 +00:00
# Generate the encoded version of the supplied payload on the
# exploit module instance
exploit . generate_payload ( payload )
2013-08-30 16:28:33 -05:00
2010-07-01 22:02:46 +00:00
# No need to copy since we aren't creating a job. We wait until
# they're finished running to do anything else with them, so
# nothing should be able to modify their datastore or other
# settings until after they're done.
ctx = [ exploit , payload ]
2015-09-09 11:51:18 -05:00
2018-09-25 11:28:59 +08:00
begin
job_run_proc ( ctx )
rescue :: Interrupt
job_cleanup_proc ( ctx )
raise $!
2021-03-15 17:09:48 -05:00
ensure
# For multi exploit targets.
# Keep the payload handler until last target or interrupt
job_cleanup_proc ( ctx ) unless keep_handler
2018-09-25 11:28:59 +08:00
end
2005-07-15 23:46:05 +00:00
end
2013-08-30 16:28:33 -05:00
2005-07-16 07:32:11 +00:00
return session
2005-07-13 18:06:12 +00:00
end
2013-08-30 16:28:33 -05:00
2005-10-19 03:20:20 +00:00
attr_accessor :exploit # :nodoc:
attr_accessor :payload # :nodoc:
attr_accessor :use_job # :nodoc:
2007-04-04 02:49:08 +00:00
#
# The identifier of the job this exploit is launched as, if it's run as a
# job.
#
2009-11-16 15:08:58 +00:00
attr_accessor :job_id
2005-10-19 03:20:20 +00:00
attr_accessor :force_wait_for_session # :nodoc:
2010-07-15 21:28:21 +00:00
attr_accessor :session # :nodoc:
2018-09-25 11:28:59 +08:00
attr_accessor :keep_handler # :nodoc:
2005-09-22 04:53:46 +00:00
2015-07-20 16:09:13 -05:00
# To synchronize threads cleaning up the exploit and the handler
attr_accessor :semaphore
2005-09-22 04:53:46 +00:00
protected
#
# Job run proc, sets up the exploit and kicks it off.
#
def job_run_proc ( ctx )
begin
exploit , payload = ctx
2015-09-09 11:51:18 -05:00
# Default session wait time..
delay = payload . wfs_delay + exploit . wfs_delay
delay = nil if exploit . passive?
2009-11-16 15:08:58 +00:00
2005-09-22 04:53:46 +00:00
# Set the exploit up the bomb
exploit . setup
2013-08-30 16:28:33 -05:00
2010-01-15 00:32:48 +00:00
exploit . framework . events . on_module_run ( exploit )
2013-08-30 16:28:33 -05:00
2005-09-22 04:53:46 +00:00
# Launch the exploit
exploit . exploit
2005-10-02 05:48:05 +00:00
2010-07-16 19:58:41 +00:00
rescue :: Exception = > e
2010-07-21 23:25:20 +00:00
if [ :: RuntimeError , :: Interrupt ] . include? ( e . class )
# Wait for session, but don't wait long.
delay = 0 . 01
2010-07-15 21:28:21 +00:00
end
2015-09-14 12:18:47 -05:00
2018-09-25 11:28:59 +08:00
fail_reason = exploit . handle_exception ( e )
2010-07-21 23:25:20 +00:00
end
2013-08-30 16:28:33 -05:00
2018-07-12 10:16:48 -05:00
# Start bind handlers after exploit completion
payload . start_handler if exploit . handler_bind?
2018-07-06 14:03:12 -05:00
2010-07-21 23:25:20 +00:00
# Wait the payload to acquire a session if this isn't a passive-style
# exploit.
2011-05-17 17:16:47 +00:00
return if not delay
2013-08-30 16:28:33 -05:00
2010-12-13 23:34:43 +00:00
if ( force_wait_for_session == true ) or
( exploit . passive? == false and exploit . handler_enabled? )
2010-07-21 23:25:20 +00:00
begin
self . session = payload . wait_for_session ( delay )
rescue :: Interrupt
# Don't let interrupt pass upward
end
2005-09-22 04:53:46 +00:00
end
2013-08-30 16:28:33 -05:00
2012-06-19 00:48:39 -05:00
return self . session if self . session
2013-08-30 16:28:33 -05:00
2012-07-10 19:55:30 -05:00
if exploit . fail_reason == Msf :: Exploit :: Failure :: None
2012-06-19 00:48:39 -05:00
exploit . fail_reason = Msf :: Exploit :: Failure :: PayloadFailed
exploit . fail_detail = " No session created "
exploit . report_failure
end
2018-09-25 11:28:59 +08:00
if fail_reason && fail_reason == Msf :: Exploit :: Failure :: UserInterrupt
raise :: Interrupt
end
2005-09-22 04:53:46 +00:00
end
2013-08-30 16:28:33 -05:00
2005-09-22 04:53:46 +00:00
#
# Clean up the exploit and the handler after the job completes.
#
def job_cleanup_proc ( ctx )
exploit , payload = ctx
2013-08-30 16:28:33 -05:00
2005-09-22 04:53:46 +00:00
# Ensure that, no matter what, clean up of the handler occurs
2015-07-20 16:09:13 -05:00
semaphore . synchronize { payload . stop_handler }
2013-08-30 16:28:33 -05:00
2010-03-16 19:32:54 +00:00
exploit . framework . events . on_module_complete ( exploit )
2013-08-30 16:28:33 -05:00
2005-09-22 04:53:46 +00:00
# Allow the exploit to cleanup after itself, that messy bugger.
2015-07-20 16:09:13 -05:00
semaphore . synchronize { exploit . cleanup }
2005-09-22 04:53:46 +00:00
end
2005-07-13 18:06:12 +00:00
end
2008-11-17 19:51:09 +00:00
end
2015-01-24 02:44:29 -06:00