f1691c5470
git-svn-id: file:///home/svn/incoming/trunk@2744 4d416f70-5f16-0410-b530-b9f4589650da
186 lines
4.3 KiB
Ruby
186 lines
4.3 KiB
Ruby
require 'msf/core'
|
|
|
|
module Msf
|
|
|
|
###
|
|
#
|
|
# ExploitDriver
|
|
# -------------
|
|
#
|
|
# 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
|
|
|
|
def initialize(framework)
|
|
self.payloads = {}
|
|
self.payload = nil
|
|
self.exploit = nil
|
|
self.target = nil
|
|
end
|
|
|
|
#
|
|
# Stores the supplied exploit as the active exploit and filters compatible
|
|
# payloads and architectures based on the exploit's target platform
|
|
# information.
|
|
#
|
|
def exploit=(exploit)
|
|
@exploit = exploit
|
|
|
|
filter_payloads
|
|
end
|
|
|
|
#
|
|
# Specification of the exploit target index
|
|
#
|
|
def target_idx=(target_idx)
|
|
# Make sure the target index is valid
|
|
if (target_idx >= exploit.targets.length)
|
|
raise Rex::ArgumentError, "Invalid target index.", caller
|
|
end
|
|
|
|
# Set the active target
|
|
target = exploit.targets[target_idx]
|
|
end
|
|
|
|
#
|
|
# Sets the active target instance for the specified exploit module. This
|
|
# causes the driver to filter payloads again.
|
|
#
|
|
def target=(target)
|
|
@target = target
|
|
|
|
filter_payloads
|
|
end
|
|
|
|
#
|
|
# Sets the active payload and performs one last sanity check
|
|
#
|
|
def payload=(payload)
|
|
# Don't allow payload selection to occur until a target has been
|
|
# specified.
|
|
if (target == nil)
|
|
raise MissingTargetError,
|
|
"A payload cannot be selected until a target is specified.",
|
|
caller
|
|
end
|
|
|
|
# Make sure the payload is compatible after all
|
|
if (compatible_payload?(payload) == false)
|
|
raise IncompatiblePayloadError.new(payload.refname),
|
|
"Incompatible payload", caller
|
|
end
|
|
|
|
@payload = payload
|
|
end
|
|
|
|
#
|
|
# Checks to see if the supplied payload is compatible with the
|
|
# current exploit.
|
|
#
|
|
def compatible_payload?(payload)
|
|
return ((payload.platform & exploit.platform).empty? == false)
|
|
end
|
|
|
|
##
|
|
#
|
|
# Exploit execution
|
|
#
|
|
##
|
|
|
|
#
|
|
# 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
|
|
if (target == nil)
|
|
raise MissingTargetError,
|
|
"A payload cannot be selected until a target is specified.",
|
|
caller
|
|
end
|
|
|
|
# Next, validate that a payload has been selected
|
|
if (payload == nil)
|
|
raise MissingPayloadError,
|
|
"A payload has not been selected.", caller
|
|
end
|
|
|
|
# Finally, validate options on the exploit module to ensure that things
|
|
# are ready to operate as they should.
|
|
exploit.options.validate()
|
|
|
|
return true
|
|
end
|
|
|
|
#
|
|
# 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()
|
|
|
|
# After validation has occurred, it's time to set some values on the
|
|
# exploit instance and begin preparing the payload
|
|
exploit.target = target
|
|
|
|
# Generate the encoded version of the supplied payload on the exploit
|
|
# module instance
|
|
exploit.generate_payload(payload)
|
|
end
|
|
|
|
attr_reader :exploit
|
|
attr_reader :target
|
|
attr_reader :payloads
|
|
attr_reader :payload
|
|
|
|
protected
|
|
|
|
#
|
|
# Filters out compatible payloads based on the current
|
|
#
|
|
def filter_payloads
|
|
payloads = {}
|
|
|
|
# Enumerate each target for this exploit
|
|
exploit.targets.each { |curr_target|
|
|
# If there's an active target, then skip all other targets
|
|
next if (target && target != curr_target)
|
|
|
|
# Enumerate each payload module, intersecting the supported platforms
|
|
# to see if there is any match at all. If so, the payload name is
|
|
# added to the list of acceptable payloads.
|
|
framework.payloads.each_module(
|
|
'Platform' => target.platforms) { |name, pmod|
|
|
|
|
# If the payload's size is larger than the amount of available space,
|
|
# then we can't allow it
|
|
if (exploit.payload_space > 0 and
|
|
exploit.payload_space < framework.payloads.sizes[name])
|
|
dlog("Payload #{name} is too big for exploit #{exploit.refname} (#{exploit.payload_space} < #{framework.payloads.sizes[name]})",
|
|
'core', LEV_2)
|
|
next
|
|
end
|
|
|
|
payloads[name] = pmod
|
|
}
|
|
}
|
|
end
|
|
|
|
attr_writer :payloads
|
|
|
|
end
|
|
|
|
end
|