support for generic payloads
git-svn-id: file:///home/svn/framework3/trunk@3843 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
190922400e
commit
ea06abe5bb
|
@ -11,10 +11,6 @@ module Msf
|
|||
###
|
||||
module Exception
|
||||
include Rex::Exception
|
||||
|
||||
def to_s
|
||||
"A framework exception occurred."
|
||||
end
|
||||
end
|
||||
|
||||
###
|
||||
|
@ -231,6 +227,10 @@ class IncompatiblePayloadError < ArgumentError
|
|||
attr_reader :pname
|
||||
end
|
||||
|
||||
class NoCompatiblePayloadError < ArgumentError
|
||||
include Exception
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
# NOP exceptions
|
||||
|
|
|
@ -353,7 +353,7 @@ class Exploit < Msf::Module
|
|||
# This method generates a non-cached payload which is typically useful for
|
||||
# passive exploits that will have more than one client.
|
||||
#
|
||||
def generate_single_payload(pinst = nil)
|
||||
def generate_single_payload(pinst = nil, platform = nil, arch = nil)
|
||||
if (target == nil)
|
||||
raise MissingTargetError, "No target has been specified.",
|
||||
caller
|
||||
|
@ -368,6 +368,28 @@ class Exploit < Msf::Module
|
|||
caller
|
||||
end
|
||||
|
||||
# If this is a generic payload, then we should specify the platform
|
||||
# and architecture so that it knows how to pass things on.
|
||||
if real_payload.kind_of?(Msf::Payload::Generic)
|
||||
# Convert the architecture specified into an array.
|
||||
if arch and arch.kind_of?(String)
|
||||
arch = [ arch ]
|
||||
end
|
||||
|
||||
# Define the explicit platform and architecture information only if
|
||||
# it's been specified.
|
||||
if platform
|
||||
real_payload.explicit_platform = Msf::Module::PlatformList.transform(platform)
|
||||
end
|
||||
|
||||
if arch
|
||||
real_payload.explicit_arch = arch
|
||||
end
|
||||
|
||||
# Force it to reset so that it will find updated information.
|
||||
real_payload.reset
|
||||
end
|
||||
|
||||
# Duplicate the exploit payload requirements
|
||||
reqs = self.payload_info.dup
|
||||
|
||||
|
@ -389,10 +411,11 @@ class Exploit < Msf::Module
|
|||
|
||||
#
|
||||
# Re-generates an encoded payload, typically called after something in the
|
||||
# datastore has changed.
|
||||
# datastore has changed. An optional platform and architecture can be
|
||||
# supplied as well.
|
||||
#
|
||||
def regenerate_payload
|
||||
generate_single_payload
|
||||
def regenerate_payload(platform = nil, arch = nil)
|
||||
generate_single_payload(nil, platform, arch)
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -489,6 +512,21 @@ class Exploit < Msf::Module
|
|||
return (target_idx) ? targets[target_idx.to_i] : nil
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the target's platform, or the one assigned to the module itself.
|
||||
#
|
||||
def target_platform
|
||||
(target and target.platform) ? target.platform : platform
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the target's architecture, or the one assigned to the module
|
||||
# itself.
|
||||
#
|
||||
def target_arch
|
||||
(target and target.arch) ? target.arch : (arch == []) ? nil : arch
|
||||
end
|
||||
|
||||
#
|
||||
# Returns a list of compatible payloads based on platform, architecture,
|
||||
# and size requirements.
|
||||
|
|
|
@ -157,6 +157,14 @@ module Handler
|
|||
#
|
||||
attr_accessor :exploit_config
|
||||
|
||||
#
|
||||
# This will be non-nil if the handler has a parent payload that it
|
||||
# was spawned from. Right now, this is only the case with generic
|
||||
# payloads. The parent payload is used to create a session
|
||||
# rather than using the instance itself.
|
||||
#
|
||||
attr_accessor :parent_payload
|
||||
|
||||
protected
|
||||
|
||||
#
|
||||
|
@ -165,6 +173,9 @@ protected
|
|||
# associated session.
|
||||
#
|
||||
def create_session(conn)
|
||||
# If there is a parent payload, then use that in preference.
|
||||
return parent_payload.create_session(conn) if (parent_payload)
|
||||
|
||||
# If the payload we merged in with has an associated session factory,
|
||||
# allocate a new session.
|
||||
if (self.session)
|
||||
|
|
|
@ -0,0 +1,253 @@
|
|||
require 'msf/core'
|
||||
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# The generic payloads are used to define a generalized payload type that
|
||||
# is both architecture and platform independent. Under the hood, generic
|
||||
# payloads seek out the correct payload for the appropriate architecture
|
||||
# and platform that is being targeted.
|
||||
#
|
||||
###
|
||||
module Payload::Generic
|
||||
|
||||
#
|
||||
# Registers options that are common to all generic payloads, such as
|
||||
# platform and arch.
|
||||
#
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
'Arch' => ARCH_ALL,
|
||||
'Platform' => ''))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('PLATFORM',
|
||||
[
|
||||
false,
|
||||
"The platform that is being targeted",
|
||||
nil
|
||||
]),
|
||||
OptString.new('ARCH',
|
||||
[
|
||||
false,
|
||||
"The architecture that is being targeted",
|
||||
nil
|
||||
])
|
||||
], Msf::Payload::Generic)
|
||||
end
|
||||
|
||||
#
|
||||
# Reset's the generic payload's internal state so that it can find a new
|
||||
# actual payload.
|
||||
#
|
||||
def reset
|
||||
self.explicit_arch = nil
|
||||
self.explicit_platform = nil
|
||||
self.actual_payload = nil
|
||||
end
|
||||
|
||||
#
|
||||
# Generate is different from other methods -- it will try to re-detect
|
||||
# the actual payload in case settings have changed. Other methods will
|
||||
# use the cached version if possible.
|
||||
#
|
||||
def generate
|
||||
reset
|
||||
|
||||
redirect_to_actual(:generate)
|
||||
end
|
||||
|
||||
#
|
||||
# Overrides -- we have to redirect all potential payload methods
|
||||
# to the actual payload so that they get handled appropriately, cuz
|
||||
# we're like a proxy and stuff. We can't use method_undefined
|
||||
# because all of these methods are actually defined.
|
||||
#
|
||||
|
||||
def payload
|
||||
redirect_to_actual(:payload)
|
||||
end
|
||||
|
||||
def offsets
|
||||
redirect_to_actual(:offsets)
|
||||
end
|
||||
|
||||
def substitute_vars(*args)
|
||||
redirect_to_actual(:substitute_vars, *args)
|
||||
end
|
||||
|
||||
def replace_var(*args)
|
||||
redirect_to_actual(:replace_var, *args)
|
||||
end
|
||||
|
||||
def compatible_encoders
|
||||
redirect_to_actual(:compatible_encoders)
|
||||
end
|
||||
|
||||
def compatible_nops
|
||||
redirect_to_actual(:compatible_nops)
|
||||
end
|
||||
|
||||
def handle_connection(*args)
|
||||
redirect_to_actual(:handle_connection, *args)
|
||||
end
|
||||
|
||||
def on_session(*args)
|
||||
redirect_to_actual(:on_session, *args)
|
||||
end
|
||||
|
||||
#
|
||||
# Stager overrides
|
||||
#
|
||||
|
||||
def stage_payload
|
||||
redirect_to_actual(:stage_payload)
|
||||
end
|
||||
|
||||
def stage_offsets
|
||||
redirect_to_actual(:stage_offsets)
|
||||
end
|
||||
|
||||
def stager_payload
|
||||
redirect_to_actual(:stager_payload)
|
||||
end
|
||||
|
||||
def stager_offsets
|
||||
redirect_to_actual(:stager_offsets)
|
||||
end
|
||||
|
||||
def stage_over_connection?
|
||||
redirect_to_actual(:stage_over_connection?)
|
||||
end
|
||||
|
||||
def generate_stage
|
||||
redirect_to_actual(:generate_stage)
|
||||
end
|
||||
|
||||
def handle_connection_stage(*args)
|
||||
redirect_to_actual(:handle_connection_stage, *args)
|
||||
end
|
||||
|
||||
def handle_intermediate_stage(*args)
|
||||
redirect_to_actual(:handle_intermediate_stage, *args)
|
||||
end
|
||||
|
||||
def stage_prefix
|
||||
redirect_to_actual(:stage_prefix)
|
||||
end
|
||||
|
||||
def stage_prefix=(*args)
|
||||
redirect_to_actual(:stage_prefix=, *args)
|
||||
end
|
||||
|
||||
#
|
||||
# First, find the underlying payload and then pass all methods onto it.
|
||||
#
|
||||
def redirect_to_actual(name, *args)
|
||||
find_actual_payload
|
||||
|
||||
actual_payload.send(name, *args)
|
||||
end
|
||||
|
||||
#
|
||||
# Accessor that makes it possible to define an explicit platform. This is
|
||||
# used for things like payload regeneration.
|
||||
#
|
||||
attr_accessor :explicit_platform
|
||||
#
|
||||
# Accessor that makes it possible to define an explicit architecture. This
|
||||
# is used for things like payload regeneration.
|
||||
#
|
||||
attr_accessor :explicit_arch
|
||||
|
||||
protected
|
||||
|
||||
#
|
||||
# The actual underlying platform/arch-specific payload instance that should
|
||||
# be used.
|
||||
#
|
||||
attr_accessor :actual_payload
|
||||
|
||||
#
|
||||
# Returns the actual platform that should be used for the payload.
|
||||
#
|
||||
def actual_platform
|
||||
platform = nil
|
||||
|
||||
if explicit_platform.nil? == false
|
||||
platform = explicit_platform
|
||||
elsif datastore['PLATFORM']
|
||||
platform = datastore['PLATFORM']
|
||||
elsif assoc_exploit
|
||||
platform = assoc_exploit.target_platform
|
||||
end
|
||||
|
||||
# If we still have an invalid platform, then we suck.
|
||||
if platform.nil?
|
||||
raise NoCompatiblePayloadError, "A platform could not be determined by the generic payload"
|
||||
elsif platform.kind_of?(String)
|
||||
platform = Msf::Module::PlatformList.transform(platform)
|
||||
end
|
||||
|
||||
return platform
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the actual architecture that should be used for the payload.
|
||||
#
|
||||
def actual_arch
|
||||
arch = nil
|
||||
|
||||
if explicit_arch.nil? == false
|
||||
arch = explicit_arch
|
||||
elsif datastore['ARCH']
|
||||
arch = datastore['ARCH']
|
||||
elsif assoc_exploit
|
||||
arch = assoc_exploit.target_arch
|
||||
end
|
||||
|
||||
# If we still have an invalid architecture, then we suck.
|
||||
if arch.nil?
|
||||
raise NoCompatiblePayloadError, "An architecture could not be determined by the generic payload"
|
||||
elsif arch.kind_of?(String)
|
||||
arch = [ arch ]
|
||||
end
|
||||
|
||||
return arch
|
||||
end
|
||||
|
||||
def find_actual_payload
|
||||
if actual_payload.nil?
|
||||
self.actual_payload = framework.payloads.find_payload(
|
||||
actual_platform,
|
||||
actual_arch,
|
||||
handler_klass,
|
||||
session,
|
||||
payload_type)
|
||||
|
||||
dlog("Selected payload #{actual_payload.refname} from generic payload #{refname}", 'core', LEV_2)
|
||||
|
||||
if actual_payload.nil?
|
||||
raise NoCompatiblePayloadError, "Could not locate a compatible payload for #{actual_platform}/#{actual_arch}"
|
||||
else
|
||||
# Share our datastore with the actual payload so that it has the
|
||||
# appropriate values to substitute ad so on.
|
||||
self.actual_payload.share_datastore(self.datastore)
|
||||
|
||||
# Set the associated exploit for the payload.
|
||||
self.actual_payload.assoc_exploit = self.assoc_exploit
|
||||
|
||||
# Set the parent payload to this payload so that we can handle
|
||||
# things like session creation (so that event notifications will
|
||||
# work properly)
|
||||
self.actual_payload.parent_payload = self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -94,7 +94,12 @@ class PayloadSet < ModuleSet
|
|||
add_single(p, name, op[5])
|
||||
|
||||
# Cache the payload's size
|
||||
sizes[name] = p.new.size
|
||||
begin
|
||||
sizes[name] = p.new.size
|
||||
|
||||
# Don't cache generic payload sizes.
|
||||
rescue NoCompatiblePayloadError
|
||||
end
|
||||
}
|
||||
|
||||
# Recalculate stagers and stages
|
||||
|
@ -197,7 +202,7 @@ class PayloadSet < ModuleSet
|
|||
# also convey other information about the module, such as
|
||||
# the platforms and architectures it supports
|
||||
payload_type_modules[instance.payload_type][name] = pinfo
|
||||
|
||||
|
||||
# If the payload happens to be a single, but has no defined
|
||||
# connection, then it can also be staged. Insert it into
|
||||
# the staged list.
|
||||
|
@ -208,6 +213,36 @@ class PayloadSet < ModuleSet
|
|||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Looks for a payload that matches the specified requirements and
|
||||
# returns an instance of that payload.
|
||||
#
|
||||
def find_payload(platform, arch, handler, session, payload_type)
|
||||
# Pre-filter based on platform and architecture.
|
||||
each_module(
|
||||
'Platform' => platform,
|
||||
'Arch' => arch) { |name, mod|
|
||||
|
||||
p = mod.new
|
||||
|
||||
# We can't substitute one generic with another one.
|
||||
next if (p.kind_of?(Msf::Payload::Generic))
|
||||
|
||||
# Check to see if the handler classes match.
|
||||
next if (handler and p.handler_klass != handler)
|
||||
|
||||
# Check to see if the session classes match.
|
||||
next if (session and p.session != session)
|
||||
|
||||
# Check for matching payload types
|
||||
next if (payload_type and p.payload_type != payload_type)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
#
|
||||
# This method adds a single payload to the set and adds it to the singles
|
||||
# hash.
|
||||
|
|
|
@ -14,6 +14,7 @@ class Exploits::Test::Multi::Aggressive < Msf::Exploit::Remote
|
|||
'Author' => 'skape',
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'Arch' => 'x86',
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1000,
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
require 'msf/core'
|
||||
require 'msf/core/payload/generic'
|
||||
require 'msf/core/handler/bind_tcp'
|
||||
|
||||
module Msf
|
||||
module Payloads
|
||||
module Singles
|
||||
module Generic
|
||||
|
||||
module ShellBindTcp
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Generic
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
'Name' => 'Generic Command Shell, Bind TCP Inline',
|
||||
'Version' => '$Revision: 3425 $',
|
||||
'Description' => 'Listen for a connection and spawn a command shell',
|
||||
'Author' => 'skape',
|
||||
'License' => MSF_LICENSE,
|
||||
'Handler' => Msf::Handler::BindTcp,
|
||||
'Session' => Msf::Sessions::CommandShell
|
||||
))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end end end end
|
|
@ -0,0 +1,29 @@
|
|||
require 'msf/core'
|
||||
require 'msf/core/payload/generic'
|
||||
require 'msf/core/handler/reverse_tcp'
|
||||
|
||||
module Msf
|
||||
module Payloads
|
||||
module Singles
|
||||
module Generic
|
||||
|
||||
module ShellReverseTcp
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Generic
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
'Name' => 'Generic Command Shell, Reverse TCP Inline',
|
||||
'Version' => '$Revision: 3425 $',
|
||||
'Description' => 'Connect back to attacker and spawn a command shell',
|
||||
'Author' => 'skape',
|
||||
'License' => MSF_LICENSE,
|
||||
'Handler' => Msf::Handler::ReverseTcp,
|
||||
'Session' => Msf::Sessions::CommandShell
|
||||
))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end end end end
|
Loading…
Reference in New Issue