Files
metasploit-gs/lib/msf/base/simple/exploit.rb
T
wchen-r7 a16a10aaf6 Fix #6371, being able to report an exception in #job_run_proc
Fix #6371

When a browser fails to bind (probably due to an invalid port or
server IP), the module actually fails to report this exception from
exception, the method calls exploit.handle_exception(e). But since
handle_exception is not a valid method for that object, it is unable
to do so, and as a result the module fails to properly terminate
the module, or show any error on the console. For the user, this will
make it look like the module has started, the payload listener is up,
but there is no exploit job.

Rex::BindFailed actually isn't the only error that could be raised
by #job_run_proc. As far as I can tell registering the same resource
again could, too. With this patch, the user should be able to see this
error too.

Since the exploit object does not have access to the methods in
Msf::Simple::Exploit, plus there is no other code using
handle_exception and setup_fail_detail_from_exception, I decided
to move these to lib/msf/core/exploit.rb so they are actually
callable.
2015-12-22 16:35:29 -06:00

203 lines
5.0 KiB
Ruby

# -*- coding: binary -*-
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.new, 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.payloads.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
mod.setup
# Run check
mod.check
end
#
# Calls the class method.
#
def check_simple(opts)
Msf::Simple::Exploit.check_simple(self, opts)
end
end
end
end