initial support for compat filtering, may be buggy
git-svn-id: file:///home/svn/incoming/trunk@2971 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
be7c2d129d
commit
b06a2ca030
|
@ -38,6 +38,18 @@ end
|
|||
###
|
||||
class Exploit < Msf::Module
|
||||
|
||||
module CompatDefaults
|
||||
#
|
||||
# Default compatibility specifications for payloads
|
||||
#
|
||||
Payload =
|
||||
{
|
||||
# Support reverse, bind, find, and noconn connection types
|
||||
# for all exploits unless expressly disabled.
|
||||
'ConnectionType' => 'reverse bind find noconn',
|
||||
}
|
||||
end
|
||||
|
||||
#
|
||||
# The various check codes that can be returned from the ``check'' routine.
|
||||
#
|
||||
|
@ -327,6 +339,10 @@ class Exploit < Msf::Module
|
|||
next
|
||||
end
|
||||
|
||||
# Are we compatible in terms of conventions and connections and
|
||||
# what not?
|
||||
next if (compatible?(framework.payloads.instance(name)) == false)
|
||||
|
||||
# This one be compatible!
|
||||
payloads << [ name, mod ]
|
||||
}
|
||||
|
@ -569,6 +585,23 @@ protected
|
|||
attr_writer :default_target
|
||||
attr_writer :payload_info
|
||||
|
||||
#
|
||||
# Overrides the base class method and serves to initialize default
|
||||
# compatibilities for exploits
|
||||
#
|
||||
def init_compat
|
||||
super
|
||||
|
||||
#
|
||||
# Merge in payload compatible defaults
|
||||
#
|
||||
p = module_info['Compat']['Payload']
|
||||
|
||||
CompatDefaults::Payload.each_pair { |k,v|
|
||||
(p[k]) ? p[k] << v : p[k] = v
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -45,6 +45,13 @@ module Handler
|
|||
return "none"
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the transport-independent handler type.
|
||||
#
|
||||
def self.general_handler_type
|
||||
"none"
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the handler's name, if any.
|
||||
#
|
||||
|
|
|
@ -21,6 +21,10 @@ module BindTcp
|
|||
return "bind_tcp"
|
||||
end
|
||||
|
||||
def self.general_handler_type
|
||||
"bind"
|
||||
end
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
||||
|
|
|
@ -17,6 +17,10 @@ module FindPort
|
|||
return "find_port"
|
||||
end
|
||||
|
||||
def self.general_handler_type
|
||||
"find"
|
||||
end
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
||||
|
|
|
@ -19,6 +19,10 @@ module FindTag
|
|||
return "find_tag"
|
||||
end
|
||||
|
||||
def self.general_handler_type
|
||||
"find"
|
||||
end
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
||||
|
|
|
@ -18,6 +18,10 @@ module None
|
|||
def self.handler_type
|
||||
return "none"
|
||||
end
|
||||
|
||||
def self.general_handler_type
|
||||
return "none"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -22,6 +22,10 @@ module ReverseTcp
|
|||
return "reverse_tcp"
|
||||
end
|
||||
|
||||
def self.general_handler_type
|
||||
"reverse"
|
||||
end
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
||||
|
|
|
@ -89,6 +89,9 @@ class Module
|
|||
|
||||
set_defaults
|
||||
|
||||
# Initialize module compatibility hashes
|
||||
init_compat
|
||||
|
||||
# Transform some of the fields to arrays as necessary
|
||||
self.author = Author.transform(module_info['Author'])
|
||||
self.arch = Rex::Transformer.transform(module_info['Arch'], Array,
|
||||
|
@ -154,7 +157,7 @@ class Module
|
|||
# Return the module's name
|
||||
#
|
||||
def name
|
||||
return module_info['Name']
|
||||
module_info['Name']
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -162,21 +165,77 @@ class Module
|
|||
# name is returned.
|
||||
#
|
||||
def alias
|
||||
return module_info['Alias']
|
||||
module_info['Alias']
|
||||
end
|
||||
|
||||
#
|
||||
# Return the module's description
|
||||
#
|
||||
def description
|
||||
return module_info['Description']
|
||||
module_info['Description']
|
||||
end
|
||||
|
||||
#
|
||||
# Return the module's version information
|
||||
#
|
||||
def version
|
||||
return module_info['Version']
|
||||
module_info['Version']
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the hash that describes this module's compatibilities
|
||||
#
|
||||
def compat
|
||||
module_info['Compat'] || {}
|
||||
end
|
||||
|
||||
#
|
||||
# Returns whether or not this module is compatible with the supplied
|
||||
# module.
|
||||
#
|
||||
def compatible?(mod)
|
||||
ch = nil
|
||||
|
||||
# Invalid module? Shoot, we can't compare that.
|
||||
return true if (mod == nil)
|
||||
|
||||
# Determine which hash to used based on the supplied module type
|
||||
if (mod.type == MODULE_ENCODER)
|
||||
ch = self.compat['Encoder']
|
||||
elsif (mod.type == MODULE_NOP)
|
||||
ch = self.compat['Nop']
|
||||
elsif (mod.type == MODULE_PAYLOAD)
|
||||
ch = self.compat['Payload']
|
||||
else
|
||||
return true
|
||||
end
|
||||
|
||||
# Enumerate each compatibility item in our hash to find out
|
||||
# if we're compatible with this sucker.
|
||||
ch.each_pair { |k,v|
|
||||
|
||||
# Get the value of the current key from the module, such as
|
||||
# the ConnectionType for a stager (ws2ord, for instance).
|
||||
mval = mod.module_info[k]
|
||||
|
||||
# Skip zee nils that the module has.
|
||||
next if (mval == nil or v == nil)
|
||||
|
||||
# If the supplied module's value is not contained within the supported
|
||||
# values for the this module or this module indicated a negation of
|
||||
# the value stated by the supplied module, then we have detected
|
||||
# ourselves a bit of an incompatibility and we just can't have that.
|
||||
if (!(v =~ /#{mval}/) or
|
||||
(v =~ /-#{mval}/))
|
||||
dlog("Module #{mod.refname} is incompatible with #{self.refname} for #{k}: limiter was #{v}, value was #{mval}",
|
||||
'core', LEV_1)
|
||||
|
||||
return false
|
||||
end
|
||||
}
|
||||
|
||||
# If we get here, we're compatible.
|
||||
return true
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -302,6 +361,34 @@ protected
|
|||
}.update(self.module_info)
|
||||
end
|
||||
|
||||
#
|
||||
# This method initializes the module's compatibility hashes by normalizing
|
||||
# them into one single hash. As it stands, modules can define
|
||||
# compatibility in their supplied info hash through:
|
||||
#
|
||||
# Compat - direct compat definitions
|
||||
# PayloadCompat - payload compatibilities
|
||||
# EncoderCompat - encoder compatibilities
|
||||
# NopCompat - nop compatibilities
|
||||
#
|
||||
# In the end, the module specific compatibilities are merged as sub-hashes
|
||||
# of the primary Compat hash key to make checks more uniform.
|
||||
#
|
||||
def init_compat
|
||||
c = module_info['Compat'] = Hash.new if (module_info['Compat'] == nil)
|
||||
|
||||
# Initialize the module sub compatibilities
|
||||
c['Payload'] = Hash.new if (c['Payload'] == nil)
|
||||
c['Encoder'] = Hash.new if (c['Encoder'] == nil)
|
||||
c['Nop'] = Hash.new if (c['Nop'] == nil)
|
||||
|
||||
# Update the compat-derived module specific compatibilities from
|
||||
# the specific ones to make a uniform view of compatibilities
|
||||
c['Payload'].update(module_info['PayloadCompat'] || {})
|
||||
c['Encoder'].update(module_info['EncoderCompat'] || {})
|
||||
c['Nop'].update(module_info['NopCompat'] || {})
|
||||
end
|
||||
|
||||
#
|
||||
# Register options with a specific owning class
|
||||
#
|
||||
|
|
|
@ -31,6 +31,11 @@ class Payload < Msf::Module
|
|||
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
||||
# Update the module info hash with the connection type
|
||||
# that is derived from the handler for this payload. This is
|
||||
# used for compatibility filtering purposes.
|
||||
self.module_info['ConnectionType'] = connection_type
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -106,6 +111,21 @@ class Payload < Msf::Module
|
|||
module_info['Convention']
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the module's connection type, such as reverse, bind, noconn,
|
||||
# or whatever else the case may be.
|
||||
#
|
||||
def connection_type
|
||||
handler_klass.general_handler_type
|
||||
end
|
||||
|
||||
#
|
||||
# The method used to resolve symbols by the payload.
|
||||
#
|
||||
def symbol_lookup
|
||||
module_info['SymbolLookup']
|
||||
end
|
||||
|
||||
#
|
||||
# Checks to see if the supplied convention is compatible with this
|
||||
# payload's convention.
|
||||
|
@ -133,7 +153,7 @@ class Payload < Msf::Module
|
|||
# Return the connection associated with this payload, or none if there
|
||||
# isn't one.
|
||||
#
|
||||
def handler
|
||||
def handler_klass
|
||||
return module_info['Handler'] || Msf::Handler::None
|
||||
end
|
||||
|
||||
|
|
|
@ -50,6 +50,10 @@ class PayloadSet < ModuleSet
|
|||
|
||||
# Hash that caches the sizes of payloads
|
||||
self.sizes = {}
|
||||
|
||||
# Single instance cache of modules for use with doing quick referencing
|
||||
# of attributes that would require an instance.
|
||||
self._instances = {}
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -91,11 +95,11 @@ class PayloadSet < ModuleSet
|
|||
|
||||
# Recalculate stagers and stages
|
||||
_stagers.each_pair { |stager_name, p|
|
||||
stager_mod, handler, stager_platform, stager_arch, stager_conv = p
|
||||
stager_mod, handler, stager_platform, stager_arch, stager_inst = p
|
||||
|
||||
# Walk the array of stages
|
||||
_stages.each_pair { |stage_name, p|
|
||||
stage_mod, junk, stage_platform, stage_arch, stage_conv = p
|
||||
stage_mod, junk, stage_platform, stage_arch, stage_inst = p
|
||||
|
||||
# No intersection between architectures on the payloads?
|
||||
if ((stager_arch) and
|
||||
|
@ -121,12 +125,10 @@ class PayloadSet < ModuleSet
|
|||
|
||||
# If the stage has a convention, make sure it's compatible with
|
||||
# the stager's
|
||||
if ((stage_conv) and
|
||||
(stager_conv != stage_conv))
|
||||
dlog("Stager #{stager_name} and stage #{stage_name} have incompatible conventions:",
|
||||
if ((stage_inst) and
|
||||
(stage_inst.compatible?(stager_inst) == false))
|
||||
dlog("Stager #{stager_name} and stage #{stage_name} are incompatible.",
|
||||
'core', LEV_3)
|
||||
dlog(" Stager: #{stager_conv}.", 'core', LEV_3)
|
||||
dlog(" Stage: #{stage_conv}.", 'core', LEV_3)
|
||||
next
|
||||
end
|
||||
|
||||
|
@ -182,10 +184,10 @@ class PayloadSet < ModuleSet
|
|||
pinfo =
|
||||
[
|
||||
pmodule,
|
||||
instance.handler,
|
||||
instance.handler_klass,
|
||||
instance.platform,
|
||||
instance.arch,
|
||||
instance.convention,
|
||||
instance,
|
||||
file_path
|
||||
]
|
||||
|
||||
|
@ -201,8 +203,8 @@ class PayloadSet < ModuleSet
|
|||
# connection, then it can also be staged. Insert it into
|
||||
# the staged list.
|
||||
if ((instance.payload_type == Payload::Type::Single) and
|
||||
((instance.handler == Msf::Handler::None) or
|
||||
(instance.handler == nil)))
|
||||
((instance.handler_klass == Msf::Handler::None) or
|
||||
(instance.handler_klass == nil)))
|
||||
payload_type_modules[Payload::Type::Stage][name] = pinfo
|
||||
end
|
||||
end
|
||||
|
@ -248,6 +250,20 @@ class PayloadSet < ModuleSet
|
|||
dlog("Built staged payload #{full_name}.", 'core', LEV_1)
|
||||
end
|
||||
|
||||
#
|
||||
# Returns a single read-only instance of the supplied payload name such
|
||||
# that specific attributes, like compatibility, can be evaluated. The
|
||||
# payload instance returned should NOT be used for anything other than
|
||||
# reading.
|
||||
#
|
||||
def instance(name)
|
||||
if (self._instances[name] == nil)
|
||||
self._instances[name] = create(name)
|
||||
end
|
||||
|
||||
self._instances[name]
|
||||
end
|
||||
|
||||
attr_reader :stages, :singles, :sizes
|
||||
|
||||
protected
|
||||
|
@ -292,6 +308,7 @@ protected
|
|||
|
||||
attr_accessor :manager, :payload_type_modules
|
||||
attr_writer :stages, :singles, :sizes
|
||||
attr_accessor :_instances
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ module FindTagOrdinalTcp
|
|||
'Arch' => ARCH_X86,
|
||||
'Handler' => Msf::Handler::FindTag,
|
||||
'Convention' => 'sockedi',
|
||||
'SymbolLookup' => 'ws2ord',
|
||||
'Stager' =>
|
||||
{
|
||||
'Offsets' =>
|
||||
|
|
|
@ -25,6 +25,7 @@ module ReverseOrdinalTcp
|
|||
'Arch' => ARCH_X86,
|
||||
'Handler' => Msf::Handler::ReverseTcp,
|
||||
'Convention' => 'sockedi',
|
||||
'SymbolLookup' => 'ws2ord',
|
||||
'Stager' =>
|
||||
{
|
||||
'Offsets' =>
|
||||
|
|
|
@ -29,7 +29,10 @@ module DllInject
|
|||
],
|
||||
'Platform' => 'win',
|
||||
'Arch' => ARCH_X86,
|
||||
'Convention' => 'sockedi',
|
||||
'PayloadCompat' =>
|
||||
{
|
||||
'Convention' => 'sockedi'
|
||||
},
|
||||
'Stage' =>
|
||||
{
|
||||
'Offsets' =>
|
||||
|
|
|
@ -18,6 +18,10 @@ module Shell
|
|||
'Platform' => 'win',
|
||||
'Arch' => ARCH_X86,
|
||||
'Session' => Msf::Sessions::CommandShell,
|
||||
'PayloadCompat' =>
|
||||
{
|
||||
'Convention' => 'sockedi'
|
||||
},
|
||||
'Stage' =>
|
||||
{
|
||||
'Offsets' =>
|
||||
|
|
Loading…
Reference in New Issue