122b34c703
the block objects weren't being transitioned over from the class methods properly, so the callback blocks were never getting processed.
201 lines
4.7 KiB
Ruby
201 lines
4.7 KiB
Ruby
require 'msf/base'
|
|
|
|
module Msf
|
|
module Simple
|
|
|
|
###
|
|
#
|
|
# A simplified exploit wrapper.
|
|
#
|
|
###
|
|
module Exploit
|
|
|
|
include Module
|
|
|
|
#
|
|
# Wraps the exploitation process in a simple single method. The options
|
|
# hash can have the following values passed in it:
|
|
#
|
|
# Encoder
|
|
#
|
|
# The encoder module that should be used.
|
|
#
|
|
# Payload
|
|
#
|
|
# The payload module name that should be used.
|
|
#
|
|
# Target
|
|
#
|
|
# The selected target index.
|
|
#
|
|
# Nop
|
|
#
|
|
# The NOP generator that should be used in preference.
|
|
#
|
|
# OptionStr
|
|
#
|
|
# A string of comma separated option values that should be imported into
|
|
# the datastore.
|
|
#
|
|
# Options
|
|
#
|
|
# A hash of values to be imported directly into the datastore.
|
|
#
|
|
# LocalInput
|
|
#
|
|
# The local input handle that data can be read in from.
|
|
#
|
|
# LocalOutput
|
|
#
|
|
# The local output through which data can be displayed.
|
|
#
|
|
# RunAsJob
|
|
#
|
|
# Whether or not the exploit should be run in the context of a background
|
|
# job.
|
|
#
|
|
def self.exploit_simple(oexploit, opts, &block)
|
|
# Trap and print errors here (makes them UI-independent)
|
|
begin
|
|
|
|
# Clone the module to prevent changes to the original instance
|
|
exploit = oexploit.replicant
|
|
Msf::Simple::Framework.simplify_module( exploit, false )
|
|
yield(exploit) if block_given?
|
|
|
|
# Import options from the OptionStr or Option hash.
|
|
exploit._import_extra_options(opts)
|
|
|
|
# Make sure parameters are valid.
|
|
if (opts['Payload'] == nil)
|
|
raise MissingPayloadError,
|
|
"You must specify a payload.", caller
|
|
end
|
|
|
|
# Verify the options
|
|
exploit.options.validate(exploit.datastore)
|
|
|
|
# Start it up
|
|
driver = ExploitDriver.new(exploit.framework)
|
|
|
|
# Initialize the driver instance
|
|
driver.exploit = exploit
|
|
driver.payload = exploit.framework.modules.create(opts['Payload'])
|
|
|
|
# Set the force wait for session flag if the caller requested force
|
|
# blocking. This is so that passive exploits can be blocked on from
|
|
# things like the cli.
|
|
driver.force_wait_for_session = true if (opts['ForceBlocking'] == true)
|
|
|
|
# Was the payload valid?
|
|
if (driver.payload == nil)
|
|
raise MissingPayloadError,
|
|
"You specified an invalid payload: #{opts['Payload']}", caller
|
|
end
|
|
|
|
# Use the supplied encoder, if any. If one was not specified, then
|
|
# nil will be assigned causing the exploit to default to picking the
|
|
# best encoder.
|
|
exploit.datastore['ENCODER'] = opts['Encoder'] if opts['Encoder']
|
|
|
|
# Force the payload to share the exploit's datastore
|
|
driver.payload.share_datastore(driver.exploit.datastore)
|
|
|
|
# Verify the payload options
|
|
driver.payload.options.validate(driver.payload.datastore)
|
|
|
|
# If we still have no target index, try to use the datastore's index
|
|
target_idx = opts['Target'] || exploit.default_target
|
|
|
|
# Convert it to an integer if it's valid
|
|
if (target_idx)
|
|
target_idx = target_idx.to_i
|
|
end
|
|
|
|
if (target_idx == nil or target_idx < 0)
|
|
raise MissingTargetError,
|
|
"You must select a target.", caller
|
|
end
|
|
|
|
driver.target_idx = target_idx
|
|
|
|
# Set the payload and exploit's subscriber values
|
|
if ! opts['Quiet']
|
|
driver.exploit.init_ui(opts['LocalInput'] || exploit.user_input, opts['LocalOutput'] || exploit.user_output)
|
|
driver.payload.init_ui(opts['LocalInput'] || exploit.user_input, opts['LocalOutput'] || exploit.user_output)
|
|
else
|
|
driver.exploit.init_ui(nil, nil)
|
|
driver.payload.init_ui(nil, nil)
|
|
end
|
|
|
|
if (opts['RunAsJob'])
|
|
driver.use_job = true
|
|
end
|
|
|
|
# Let's rock this party
|
|
driver.run
|
|
|
|
# Save the job identifier this exploit is running as
|
|
exploit.job_id = driver.job_id
|
|
|
|
# Propagate this back to the caller for console mgmt
|
|
oexploit.job_id = exploit.job_id
|
|
rescue ::Interrupt
|
|
exploit.error = $!
|
|
raise $!
|
|
rescue ::Exception => e
|
|
exploit.error = e
|
|
exploit.print_error("Exploit failed: #{e}")
|
|
elog("Exploit failed (#{exploit.refname}): #{e}", 'core', LEV_0)
|
|
dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3)
|
|
end
|
|
|
|
return driver.session if driver
|
|
nil
|
|
end
|
|
|
|
#
|
|
# Calls the class method.
|
|
#
|
|
def exploit_simple(opts, &block)
|
|
Msf::Simple::Exploit.exploit_simple(self, opts, &block)
|
|
end
|
|
|
|
#
|
|
# Initiates a check, setting up the exploit to be used. The following
|
|
# options can be specified:
|
|
#
|
|
# LocalInput
|
|
#
|
|
# The local input handle that data can be read in from.
|
|
#
|
|
# LocalOutput
|
|
#
|
|
# The local output through which data can be displayed.
|
|
#
|
|
def self.check_simple(mod, opts)
|
|
if opts['LocalInput']
|
|
mod.init_ui(opts['LocalInput'], opts['LocalOutput'])
|
|
end
|
|
|
|
# Validate the option container state so that options will
|
|
# be normalized
|
|
mod.validate
|
|
|
|
# Run check
|
|
mod.check
|
|
end
|
|
|
|
#
|
|
# Calls the class method.
|
|
#
|
|
def check_simple(opts)
|
|
Msf::Simple::Exploit.check_simple(self, opts)
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
end
|
|
|