137 lines
3.5 KiB
Ruby
137 lines
3.5 KiB
Ruby
# -*- coding: binary -*-
|
|
require 'msf/core'
|
|
|
|
module Msf
|
|
|
|
class EvasionDriver
|
|
|
|
#
|
|
# Initializes the evasion driver using the supplied framework instance.
|
|
#
|
|
def initialize(framework)
|
|
self.payload = nil
|
|
self.evasion = nil
|
|
self.use_job = false
|
|
self.job_id = nil
|
|
self.force_wait_for_session = false
|
|
self.semaphore = Mutex.new
|
|
end
|
|
|
|
def target_idx=(target_idx)
|
|
if (target_idx)
|
|
# Make sure the target index is valid
|
|
if (target_idx >= evasion.targets.length)
|
|
raise Rex::ArgumentError, "Invalid target index.", caller
|
|
end
|
|
end
|
|
|
|
# Set the active target
|
|
@target_idx = target_idx
|
|
end
|
|
|
|
def target_idx
|
|
@target_idx
|
|
end
|
|
|
|
|
|
#
|
|
# Checks to see if the supplied payload is compatible with the
|
|
# current evasion module. Assumes that target_idx is valid.
|
|
#
|
|
def compatible_payload?(payload)
|
|
evasion_platform = evasion.targets[target_idx].platform || evasion.platform
|
|
return ((payload.platform & evasion_platform).empty? == false)
|
|
end
|
|
|
|
def validate
|
|
if (payload == nil)
|
|
raise MissingPayloadError, "A payload has not been selected.", caller
|
|
end
|
|
|
|
# Make sure the payload is compatible after all
|
|
if (compatible_payload?(payload) == false)
|
|
raise IncompatiblePayloadError.new(payload.refname), "Incompatible payload", caller
|
|
end
|
|
|
|
# Associate the payload instance with the evasion
|
|
payload.assoc_exploit = evasion
|
|
|
|
# Finally, validate options on the evasion module to ensure that things
|
|
# are ready to operate as they should.
|
|
evasion.options.validate(evasion.datastore)
|
|
|
|
# Validate the payload's options. The payload's datastore is
|
|
# most likely shared against the evasion's datastore, but in case it
|
|
# isn't.
|
|
payload.options.validate(payload.datastore)
|
|
|
|
return true
|
|
end
|
|
|
|
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()
|
|
|
|
# Explicitly clear the module's job_id in case it was set in a previous
|
|
# run
|
|
evasion.job_id = nil
|
|
|
|
# Generate the encoded version of the supplied payload on the
|
|
# evasion module instance
|
|
evasion.generate_payload(payload)
|
|
|
|
# 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 = [ evasion, payload ]
|
|
|
|
job_run_proc(ctx)
|
|
job_cleanup_proc(ctx)
|
|
|
|
end
|
|
|
|
attr_accessor :evasion # :nodoc:
|
|
attr_accessor :payload # :nodoc:
|
|
attr_accessor :use_job # :nodoc:
|
|
#
|
|
# The identifier of the job this evasion module is launched as, if it's run as a
|
|
# job.
|
|
#
|
|
attr_accessor :job_id
|
|
attr_accessor :force_wait_for_session # :nodoc:
|
|
attr_accessor :session # :nodoc:
|
|
|
|
# To synchronize threads cleaning up the evasion
|
|
attr_accessor :semaphore
|
|
|
|
protected
|
|
|
|
#
|
|
# Job run proc, sets up the eevasion and kicks it off.
|
|
#
|
|
def job_run_proc(ctx)
|
|
evasion, payload = ctx
|
|
evasion.setup
|
|
evasion.framework.events.on_module_run(evasion)
|
|
|
|
# Launch the evasion module
|
|
evasion.run
|
|
end
|
|
|
|
#
|
|
# Clean up the evasion after the job completes.
|
|
#
|
|
def job_cleanup_proc(ctx)
|
|
evasion, payload = ctx
|
|
evasion.framework.events.on_module_complete(evasion)
|
|
semaphore.synchronize { evasion.cleanup }
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|