2012-06-29 05:18:28 +00:00
|
|
|
# -*- coding: binary -*-
|
2005-07-09 21:18:49 +00:00
|
|
|
require 'msf/core'
|
2011-11-21 21:58:19 +00:00
|
|
|
require 'fastlib'
|
2011-01-29 03:34:48 +00:00
|
|
|
require 'pathname'
|
2005-05-22 07:14:16 +00:00
|
|
|
|
|
|
|
module Msf
|
|
|
|
|
2006-02-21 03:10:58 +00:00
|
|
|
#
|
|
|
|
# Define used for a place-holder module that is used to indicate that the
|
2008-10-02 05:23:59 +00:00
|
|
|
# module has not yet been demand-loaded. Soon to go away.
|
2006-02-21 03:10:58 +00:00
|
|
|
#
|
|
|
|
SymbolicModule = "__SYMBOLIC__"
|
|
|
|
|
2008-10-02 05:23:59 +00:00
|
|
|
|
2005-05-22 07:14:16 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# A module set contains zero or more named module classes of an arbitrary
|
|
|
|
# type.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
class ModuleSet < Hash
|
2005-07-13 18:06:12 +00:00
|
|
|
|
|
|
|
include Framework::Offspring
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
|
|
|
# Initializes a module set that will contain modules of a specific type and
|
|
|
|
# expose the mechanism necessary to create instances of them.
|
|
|
|
#
|
2005-05-22 07:58:02 +00:00
|
|
|
def initialize(type = nil)
|
2005-05-22 07:46:41 +00:00
|
|
|
self.module_type = type
|
|
|
|
|
|
|
|
# Hashes that convey the supported architectures and platforms for a
|
|
|
|
# given module
|
|
|
|
self.mod_arch_hash = {}
|
|
|
|
self.mod_platform_hash = {}
|
2005-07-11 05:15:30 +00:00
|
|
|
self.mod_sorted = nil
|
2005-07-13 18:06:12 +00:00
|
|
|
self.mod_ranked = nil
|
2005-07-14 06:34:58 +00:00
|
|
|
self.mod_extensions = []
|
2005-07-14 20:05:41 +00:00
|
|
|
self.mod_ambiguous = {}
|
2005-05-22 07:14:16 +00:00
|
|
|
end
|
|
|
|
|
2006-02-21 03:10:58 +00:00
|
|
|
#
|
|
|
|
# Wrapper that detects if a symbolic module is in use. If it is, it
|
|
|
|
# creates an instance to demand load the module and then returns the
|
|
|
|
# now-loaded class afterwords.
|
|
|
|
#
|
|
|
|
def [](name)
|
|
|
|
if (get_hash_val(name) == SymbolicModule)
|
|
|
|
create(name)
|
|
|
|
end
|
|
|
|
|
|
|
|
get_hash_val(name)
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Returns the hash value associated with the supplied module name without
|
|
|
|
# throwing an exception.
|
|
|
|
#
|
|
|
|
def get_hash_val(name)
|
2009-06-25 17:59:51 +00:00
|
|
|
fetch(name) if has_key?(name)
|
2006-02-21 03:10:58 +00:00
|
|
|
end
|
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-05-22 07:14:16 +00:00
|
|
|
# Create an instance of the supplied module by its name
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-05-22 07:14:16 +00:00
|
|
|
def create(name)
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2006-02-21 03:10:58 +00:00
|
|
|
klass = get_hash_val(name)
|
2005-07-14 06:34:58 +00:00
|
|
|
instance = nil
|
|
|
|
|
2006-02-21 03:10:58 +00:00
|
|
|
# If there is no module associated with this class, then try to demand
|
|
|
|
# load it.
|
|
|
|
if (klass.nil? or klass == SymbolicModule)
|
|
|
|
# If we are the root module set, then we need to try each module
|
|
|
|
# type's demand loading until we find one that works for us.
|
|
|
|
if (module_type.nil?)
|
|
|
|
MODULE_TYPES.each { |type|
|
2012-06-16 19:51:09 +00:00
|
|
|
framework.modules.demand_load_module(type, name)
|
2006-02-21 03:10:58 +00:00
|
|
|
}
|
|
|
|
else
|
2012-06-16 19:51:09 +00:00
|
|
|
framework.modules.demand_load_module(module_type, name)
|
2006-02-21 03:10:58 +00:00
|
|
|
end
|
|
|
|
|
2012-06-16 19:51:09 +00:00
|
|
|
recalculate
|
|
|
|
|
2006-02-21 03:10:58 +00:00
|
|
|
klass = get_hash_val(name)
|
|
|
|
end
|
|
|
|
|
2012-06-16 19:51:09 +00:00
|
|
|
|
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
# If the klass is valid for this name, try to create it
|
2006-02-21 03:10:58 +00:00
|
|
|
if (klass and klass != SymbolicModule)
|
2005-07-14 06:34:58 +00:00
|
|
|
instance = klass.new
|
|
|
|
end
|
|
|
|
|
|
|
|
# Notify any general subscribers of the creation event
|
|
|
|
if (instance)
|
|
|
|
self.framework.events.on_module_created(instance)
|
|
|
|
end
|
|
|
|
|
|
|
|
return instance
|
2005-05-22 07:14:16 +00:00
|
|
|
end
|
|
|
|
|
2005-10-01 21:51:45 +00:00
|
|
|
#
|
|
|
|
# Checks to see if the supplied module name is valid.
|
|
|
|
#
|
|
|
|
def valid?(name)
|
2012-06-16 19:51:09 +00:00
|
|
|
create(name)
|
2005-10-01 21:51:45 +00:00
|
|
|
(self[name]) ? true : false
|
|
|
|
end
|
|
|
|
|
2011-04-30 04:59:27 +00:00
|
|
|
#
|
|
|
|
# Overrides the builtin 'each' operator to avoid the following exception on Ruby 1.9.2+
|
|
|
|
# "can't add a new key into hash during iteration"
|
|
|
|
#
|
|
|
|
def each(&block)
|
|
|
|
list = []
|
|
|
|
self.keys.sort.each do |sidx|
|
|
|
|
list << [sidx, self[sidx]]
|
|
|
|
end
|
|
|
|
list.each(&block)
|
|
|
|
end
|
2011-06-25 01:40:16 +00:00
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Enumerates each module class in the set.
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-05-22 07:46:41 +00:00
|
|
|
def each_module(opts = {}, &block)
|
2006-02-21 03:10:58 +00:00
|
|
|
demand_load_modules
|
|
|
|
|
2012-06-16 19:51:09 +00:00
|
|
|
self.mod_sorted = self.sort
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2005-07-13 18:06:12 +00:00
|
|
|
each_module_list(mod_sorted, opts, &block)
|
|
|
|
end
|
|
|
|
|
2005-10-01 21:51:45 +00:00
|
|
|
#
|
|
|
|
# Enumerates each module class in the set based on their relative ranking
|
|
|
|
# to one another. Modules that are ranked higher are shown first.
|
|
|
|
#
|
2005-07-13 18:06:12 +00:00
|
|
|
def each_module_ranked(opts = {}, &block)
|
2006-02-21 03:10:58 +00:00
|
|
|
demand_load_modules
|
|
|
|
|
2012-06-16 19:51:09 +00:00
|
|
|
self.mod_ranked = rank_modules
|
2005-07-13 18:06:12 +00:00
|
|
|
|
|
|
|
each_module_list(mod_ranked, opts, &block)
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Custom each_module filtering if an advanced set supports doing extended
|
|
|
|
# filtering. Returns true if the entry should be filtered.
|
|
|
|
#
|
|
|
|
def each_module_filter(opts, name, entry)
|
|
|
|
return false
|
|
|
|
end
|
2005-07-11 05:15:30 +00:00
|
|
|
|
2005-07-13 18:06:12 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Dummy placeholder to relcalculate aliases and other fun things.
|
2005-07-13 18:06:12 +00:00
|
|
|
#
|
|
|
|
def recalculate
|
|
|
|
end
|
|
|
|
|
2007-08-11 00:37:50 +00:00
|
|
|
#
|
|
|
|
# Gives the module set an opportunity to handle a module reload event
|
|
|
|
#
|
|
|
|
def on_module_reload(mod)
|
|
|
|
end
|
|
|
|
|
2007-06-16 05:04:03 +00:00
|
|
|
#
|
|
|
|
# Forces all modules in this set to be loaded.
|
|
|
|
#
|
|
|
|
def force_load_set
|
2011-03-20 22:22:07 +00:00
|
|
|
each_module { |name, mod| }
|
2007-06-16 05:04:03 +00:00
|
|
|
end
|
|
|
|
|
2005-07-13 18:06:12 +00:00
|
|
|
attr_reader :module_type
|
|
|
|
|
2006-02-21 03:10:58 +00:00
|
|
|
#
|
|
|
|
# Whether or not recalculations should be postponed. This is used from the
|
|
|
|
# context of the each_module_list handler in order to prevent the demand
|
|
|
|
# loader from calling recalc for each module if it's possible that more
|
|
|
|
# than one module may be loaded. This field is not initialized until used.
|
|
|
|
#
|
|
|
|
attr_accessor :postpone_recalc
|
|
|
|
|
2005-07-13 18:06:12 +00:00
|
|
|
protected
|
|
|
|
|
2006-02-21 03:10:58 +00:00
|
|
|
#
|
|
|
|
# Load all modules that are marked as being symbolic.
|
|
|
|
#
|
|
|
|
def demand_load_modules
|
|
|
|
# Pre-scan the module list for any symbolic modules
|
|
|
|
self.each_pair { |name, mod|
|
|
|
|
if (mod == SymbolicModule)
|
|
|
|
self.postpone_recalc = true
|
|
|
|
|
|
|
|
mod = create(name)
|
|
|
|
|
|
|
|
next if (mod.nil?)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
# If we found any symbolic modules, then recalculate.
|
|
|
|
if (self.postpone_recalc)
|
|
|
|
self.postpone_recalc = false
|
|
|
|
|
|
|
|
recalculate
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-07-13 18:06:12 +00:00
|
|
|
#
|
|
|
|
# Enumerates the modules in the supplied array with possible limiting
|
|
|
|
# factors.
|
|
|
|
#
|
|
|
|
def each_module_list(ary, opts, &block)
|
|
|
|
ary.each { |entry|
|
2005-07-11 05:15:30 +00:00
|
|
|
name, mod = entry
|
|
|
|
|
2006-02-21 03:10:58 +00:00
|
|
|
# Skip any lingering symbolic modules.
|
|
|
|
next if (mod == SymbolicModule)
|
|
|
|
|
2005-05-22 07:46:41 +00:00
|
|
|
# Filter out incompatible architectures
|
2005-07-13 18:06:12 +00:00
|
|
|
if (opts['Arch'])
|
2005-05-22 07:46:41 +00:00
|
|
|
if (!mod_arch_hash[mod])
|
|
|
|
mod_arch_hash[mod] = mod.new.arch
|
|
|
|
end
|
|
|
|
|
2005-07-13 18:06:12 +00:00
|
|
|
next if ((mod_arch_hash[mod] & opts['Arch']).empty? == true)
|
2011-01-26 03:13:40 +00:00
|
|
|
end
|
2005-05-22 07:46:41 +00:00
|
|
|
|
|
|
|
# Filter out incompatible platforms
|
2005-07-13 18:06:12 +00:00
|
|
|
if (opts['Platform'])
|
2005-05-22 07:46:41 +00:00
|
|
|
if (!mod_platform_hash[mod])
|
|
|
|
mod_platform_hash[mod] = mod.new.platform
|
|
|
|
end
|
|
|
|
|
2005-07-13 18:06:12 +00:00
|
|
|
next if ((mod_platform_hash[mod] & opts['Platform']).empty? == true)
|
2005-05-22 07:46:41 +00:00
|
|
|
end
|
|
|
|
|
2005-07-12 05:39:44 +00:00
|
|
|
# Custom filtering
|
|
|
|
next if (each_module_filter(opts, name, entry) == true)
|
|
|
|
|
2005-07-10 00:49:12 +00:00
|
|
|
block.call(name, mod)
|
2005-05-22 07:46:41 +00:00
|
|
|
}
|
2005-05-22 07:14:16 +00:00
|
|
|
end
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2005-05-22 07:14:16 +00:00
|
|
|
|
2005-07-12 05:39:44 +00:00
|
|
|
#
|
2005-07-13 18:06:12 +00:00
|
|
|
# Ranks modules based on their constant rank value, if they have one.
|
2005-07-12 05:39:44 +00:00
|
|
|
#
|
2005-07-13 18:06:12 +00:00
|
|
|
def rank_modules
|
2009-12-13 23:41:25 +00:00
|
|
|
self.mod_ranked = self.sort { |a, b|
|
2005-07-13 18:06:12 +00:00
|
|
|
a_name, a_mod = a
|
|
|
|
b_name, b_mod = b
|
|
|
|
|
2009-12-13 23:41:25 +00:00
|
|
|
# Dynamically loads the module if needed
|
2009-12-15 13:14:01 +00:00
|
|
|
a_mod = create(a_name) if a_mod == SymbolicModule
|
|
|
|
b_mod = create(b_name) if b_mod == SymbolicModule
|
2009-12-13 23:41:25 +00:00
|
|
|
|
2005-07-13 18:06:12 +00:00
|
|
|
# Extract the ranking between the two modules
|
2009-12-13 23:41:25 +00:00
|
|
|
a_rank = a_mod.const_defined?('Rank') ? a_mod.const_get('Rank') : NormalRanking
|
|
|
|
b_rank = b_mod.const_defined?('Rank') ? b_mod.const_get('Rank') : NormalRanking
|
2005-07-13 18:06:12 +00:00
|
|
|
|
|
|
|
# Compare their relevant rankings. Since we want highest to lowest,
|
|
|
|
# we compare b_rank to a_rank in terms of higher/lower precedence
|
2011-01-26 03:13:40 +00:00
|
|
|
b_rank <=> a_rank
|
2005-07-13 18:06:12 +00:00
|
|
|
}
|
2005-07-12 05:39:44 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Adds a module with a the supplied name.
|
2005-07-13 18:06:12 +00:00
|
|
|
#
|
2009-05-29 13:46:12 +00:00
|
|
|
def add_module(mod, name, modinfo = nil)
|
|
|
|
|
2005-07-13 18:06:12 +00:00
|
|
|
|
2005-07-10 19:21:40 +00:00
|
|
|
# Set the module's name so that it can be referenced when
|
|
|
|
# instances are created.
|
2009-05-29 13:46:12 +00:00
|
|
|
mod.framework = framework
|
|
|
|
mod.refname = name
|
|
|
|
mod.file_path = ((modinfo and modinfo['files']) ? modinfo['files'][0] : nil)
|
|
|
|
mod.orig_cls = mod
|
2005-07-10 19:21:40 +00:00
|
|
|
|
2006-02-21 03:10:58 +00:00
|
|
|
if (get_hash_val(name) and get_hash_val(name) != SymbolicModule)
|
2005-07-14 20:05:41 +00:00
|
|
|
mod_ambiguous[name] = true
|
|
|
|
|
2009-05-29 13:46:12 +00:00
|
|
|
wlog("The module #{mod.refname} is ambiguous with #{self[name].refname}.")
|
2005-07-14 20:05:41 +00:00
|
|
|
else
|
2009-05-29 13:46:12 +00:00
|
|
|
self[name] = mod
|
2005-07-14 20:05:41 +00:00
|
|
|
end
|
2006-02-21 03:10:58 +00:00
|
|
|
|
2009-05-29 13:46:12 +00:00
|
|
|
mod
|
2005-07-13 18:06:12 +00:00
|
|
|
end
|
|
|
|
|
2005-07-09 19:35:29 +00:00
|
|
|
attr_writer :module_type
|
2005-05-22 07:46:41 +00:00
|
|
|
attr_accessor :mod_arch_hash, :mod_platform_hash
|
2005-07-13 18:06:12 +00:00
|
|
|
attr_accessor :mod_sorted, :mod_ranked
|
2005-07-14 20:05:41 +00:00
|
|
|
attr_accessor :mod_extensions, :mod_ambiguous
|
2012-06-28 16:39:14 +00:00
|
|
|
attr_accessor :module_history
|
2005-05-22 07:14:16 +00:00
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# Upper management decided to throw in some middle management
|
|
|
|
# because the modules were getting out of hand. This bad boy
|
2011-01-26 03:13:40 +00:00
|
|
|
# takes care of the work of managing the interaction with
|
2005-05-22 07:14:16 +00:00
|
|
|
# modules in terms of loading and instantiation.
|
|
|
|
#
|
2005-05-22 07:23:25 +00:00
|
|
|
# TODO:
|
|
|
|
#
|
|
|
|
# - add unload support
|
|
|
|
#
|
2005-05-22 07:14:16 +00:00
|
|
|
###
|
2005-05-22 07:58:02 +00:00
|
|
|
class ModuleManager < ModuleSet
|
2005-05-22 07:14:16 +00:00
|
|
|
|
2005-07-09 21:18:49 +00:00
|
|
|
require 'msf/core/payload_set'
|
2005-07-09 00:24:02 +00:00
|
|
|
|
2005-07-13 18:06:12 +00:00
|
|
|
include Framework::Offspring
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
|
|
|
# Initializes an instance of the overall module manager using the supplied
|
2009-01-02 07:29:56 +00:00
|
|
|
# framework instance. The types parameter can be used to only load specific
|
|
|
|
# module types on initialization
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
2009-01-02 07:29:56 +00:00
|
|
|
def initialize(framework,types=MODULE_TYPES)
|
2005-05-22 07:14:16 +00:00
|
|
|
self.module_paths = []
|
2005-05-22 07:58:02 +00:00
|
|
|
self.module_sets = {}
|
2006-09-16 06:27:14 +00:00
|
|
|
self.module_failed = {}
|
2009-01-02 07:29:56 +00:00
|
|
|
self.enabled_types = {}
|
2005-07-14 06:34:58 +00:00
|
|
|
self.framework = framework
|
2012-06-16 19:51:09 +00:00
|
|
|
self.cache = {}
|
2005-05-22 07:14:16 +00:00
|
|
|
|
2009-01-02 07:29:56 +00:00
|
|
|
types.each { |type|
|
2011-01-26 00:07:34 +00:00
|
|
|
init_module_set(type)
|
2005-05-22 07:14:16 +00:00
|
|
|
}
|
2005-05-22 07:58:02 +00:00
|
|
|
|
2006-02-21 03:10:58 +00:00
|
|
|
super(nil)
|
2005-05-22 07:14:16 +00:00
|
|
|
end
|
|
|
|
|
2011-01-26 00:07:34 +00:00
|
|
|
def init_module_set(type)
|
|
|
|
self.enabled_types[type] = true
|
|
|
|
case type
|
|
|
|
when MODULE_PAYLOAD
|
|
|
|
instance = PayloadSet.new(self)
|
|
|
|
else
|
|
|
|
instance = ModuleSet.new(type)
|
|
|
|
end
|
|
|
|
|
|
|
|
self.module_sets[type] = instance
|
|
|
|
|
|
|
|
# Set the module set's framework reference
|
|
|
|
instance.framework = self.framework
|
|
|
|
end
|
|
|
|
|
2005-07-14 20:05:41 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Creates a module using the supplied name.
|
2005-07-14 20:05:41 +00:00
|
|
|
#
|
|
|
|
def create(name)
|
|
|
|
# Check to see if it has a module type prefix. If it does,
|
|
|
|
# try to load it from the specific module set for that type.
|
|
|
|
if (md = name.match(/^(#{MODULE_TYPES.join('|')})\/(.*)$/))
|
|
|
|
module_sets[md[1]].create(md[2])
|
|
|
|
# Otherwise, just try to load it by name.
|
|
|
|
else
|
|
|
|
super
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-05-22 07:23:25 +00:00
|
|
|
#
|
|
|
|
# Accessors by module type
|
|
|
|
#
|
|
|
|
|
2011-01-26 00:07:34 +00:00
|
|
|
#
|
|
|
|
# Returns all of the modules of the specified type
|
|
|
|
#
|
|
|
|
def module_set(type)
|
2011-01-27 00:13:13 +00:00
|
|
|
module_sets[type]
|
2011-01-26 00:07:34 +00:00
|
|
|
end
|
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Returns the set of loaded encoder module classes.
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-05-22 07:14:16 +00:00
|
|
|
def encoders
|
2011-01-26 00:07:34 +00:00
|
|
|
module_set(MODULE_ENCODER)
|
2005-05-22 07:14:16 +00:00
|
|
|
end
|
|
|
|
|
2011-01-26 00:07:34 +00:00
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Returns the set of loaded exploit module classes.
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-05-22 07:14:16 +00:00
|
|
|
def exploits
|
2011-01-26 00:07:34 +00:00
|
|
|
module_set(MODULE_EXPLOIT)
|
2005-05-22 07:14:16 +00:00
|
|
|
end
|
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Returns the set of loaded nop module classes.
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-05-22 07:25:15 +00:00
|
|
|
def nops
|
2011-01-26 00:07:34 +00:00
|
|
|
module_set(MODULE_NOP)
|
2005-05-22 07:25:15 +00:00
|
|
|
end
|
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Returns the set of loaded payload module classes.
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-05-22 07:23:25 +00:00
|
|
|
def payloads
|
2011-01-26 00:07:34 +00:00
|
|
|
module_set(MODULE_PAYLOAD)
|
2005-05-22 07:23:25 +00:00
|
|
|
end
|
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2006-01-24 03:59:44 +00:00
|
|
|
# Returns the set of loaded auxiliary module classes.
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2006-01-24 03:59:44 +00:00
|
|
|
def auxiliary
|
2011-01-26 00:07:34 +00:00
|
|
|
module_set(MODULE_AUX)
|
2005-05-22 07:14:16 +00:00
|
|
|
end
|
|
|
|
|
2010-12-27 17:46:42 +00:00
|
|
|
#
|
|
|
|
# Returns the set of loaded auxiliary module classes.
|
|
|
|
#
|
|
|
|
def post
|
2011-01-26 00:07:34 +00:00
|
|
|
module_set(MODULE_POST)
|
2010-12-27 17:46:42 +00:00
|
|
|
end
|
|
|
|
|
2006-09-16 06:27:14 +00:00
|
|
|
#
|
|
|
|
# Returns the set of modules that failed to load.
|
|
|
|
#
|
|
|
|
def failed
|
|
|
|
return module_failed
|
|
|
|
end
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
##
|
2005-05-22 07:14:16 +00:00
|
|
|
#
|
|
|
|
# Module path management
|
|
|
|
#
|
2005-07-14 06:34:58 +00:00
|
|
|
##
|
2005-05-22 07:14:16 +00:00
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2012-06-16 19:51:09 +00:00
|
|
|
# Adds a path to be searched for new modules.
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2012-06-16 19:51:09 +00:00
|
|
|
def add_module_path(path)
|
|
|
|
npaths = []
|
|
|
|
|
2011-11-21 21:58:19 +00:00
|
|
|
if path =~ /\.fastlib$/
|
|
|
|
unless ::File.exist?(path)
|
2011-11-29 04:24:27 +00:00
|
|
|
raise RuntimeError, "The path supplied does not exist", caller
|
2011-11-21 21:58:19 +00:00
|
|
|
end
|
2012-06-16 19:51:09 +00:00
|
|
|
npaths << ::File.expand_path(path)
|
2011-11-21 21:58:19 +00:00
|
|
|
else
|
|
|
|
path.sub!(/#{File::SEPARATOR}$/, '')
|
2012-05-24 22:28:20 +00:00
|
|
|
|
2011-11-21 21:58:19 +00:00
|
|
|
# Make the path completely canonical
|
|
|
|
path = Pathname.new(File.expand_path(path))
|
|
|
|
|
2012-06-16 19:51:09 +00:00
|
|
|
# Make sure the path is a valid directory
|
2011-11-29 04:24:27 +00:00
|
|
|
unless path.directory?
|
2011-11-21 21:58:19 +00:00
|
|
|
raise RuntimeError, "The path supplied is not a valid directory.", caller
|
|
|
|
end
|
2011-01-29 03:34:48 +00:00
|
|
|
|
2011-11-21 21:58:19 +00:00
|
|
|
# Now that we've confirmed it exists, get the full, cononical path
|
2012-06-16 19:51:09 +00:00
|
|
|
path = ::File.expand_path(path)
|
|
|
|
npaths << path
|
2011-11-29 04:24:27 +00:00
|
|
|
|
|
|
|
# Identify any fastlib archives inside of this path
|
|
|
|
Dir["#{path}/**/*.fastlib"].each do |fp|
|
2012-06-16 19:51:09 +00:00
|
|
|
npaths << fp
|
2011-11-29 04:24:27 +00:00
|
|
|
end
|
2005-07-14 06:34:58 +00:00
|
|
|
end
|
|
|
|
|
2012-06-16 19:51:09 +00:00
|
|
|
# Update the module paths appropriately
|
|
|
|
self.module_paths = (module_paths + npaths).flatten.uniq
|
|
|
|
|
|
|
|
# Load all of the modules from the new paths
|
|
|
|
counts = nil
|
|
|
|
npaths.each { |d|
|
|
|
|
counts = load_modules(d, false)
|
|
|
|
}
|
|
|
|
|
2006-02-21 03:10:58 +00:00
|
|
|
return counts
|
2005-05-22 07:14:16 +00:00
|
|
|
end
|
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Removes a path from which to search for modules.
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-05-22 07:14:16 +00:00
|
|
|
def remove_module_path(path)
|
|
|
|
module_paths.delete(path)
|
2012-06-16 19:51:09 +00:00
|
|
|
module_paths.delete(::File.expand_path(path))
|
2005-05-22 07:14:16 +00:00
|
|
|
end
|
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
def register_type_extension(type, ext)
|
|
|
|
end
|
2011-06-25 01:40:16 +00:00
|
|
|
|
2011-03-20 22:22:07 +00:00
|
|
|
#
|
|
|
|
# Reloads modules from all module paths
|
|
|
|
#
|
|
|
|
def reload_modules
|
|
|
|
|
|
|
|
self.module_history = {}
|
|
|
|
self.clear
|
2011-06-25 01:40:16 +00:00
|
|
|
|
2011-03-20 22:22:07 +00:00
|
|
|
self.enabled_types.each_key do |type|
|
|
|
|
module_sets[type].clear
|
|
|
|
init_module_set(type)
|
|
|
|
end
|
2011-06-25 01:40:16 +00:00
|
|
|
|
2012-06-28 16:43:33 +00:00
|
|
|
# The number of loaded modules in the following categories:
|
2012-06-28 16:39:14 +00:00
|
|
|
# auxiliary/encoder/exploit/nop/payload/post
|
2012-06-28 16:43:33 +00:00
|
|
|
count = 0
|
2011-03-20 22:22:07 +00:00
|
|
|
module_paths.each do |path|
|
2012-06-28 16:39:14 +00:00
|
|
|
mods = load_modules(path, true)
|
2012-06-28 16:43:33 +00:00
|
|
|
mods.each_value {|c| count += c}
|
2011-03-20 22:22:07 +00:00
|
|
|
end
|
2011-06-25 01:40:16 +00:00
|
|
|
|
2012-06-16 19:51:09 +00:00
|
|
|
rebuild_cache
|
2012-06-28 16:39:14 +00:00
|
|
|
|
2012-06-28 16:43:33 +00:00
|
|
|
count
|
2011-03-20 22:22:07 +00:00
|
|
|
end
|
2011-11-20 01:10:08 +00:00
|
|
|
|
2005-10-10 00:30:14 +00:00
|
|
|
#
|
|
|
|
# Reloads the module specified in mod. This can either be an instance of a
|
|
|
|
# module or a module class.
|
|
|
|
#
|
|
|
|
def reload_module(mod)
|
2012-07-04 00:49:16 +00:00
|
|
|
omod = mod
|
2005-10-10 00:30:14 +00:00
|
|
|
refname = mod.refname
|
2010-07-01 22:02:46 +00:00
|
|
|
ds = mod.datastore
|
2005-10-10 00:30:14 +00:00
|
|
|
|
|
|
|
dlog("Reloading module #{refname}...", 'core')
|
|
|
|
|
2008-10-02 05:23:59 +00:00
|
|
|
# Set the target file
|
|
|
|
file = mod.file_path
|
2009-09-15 13:50:32 +00:00
|
|
|
wrap = ::Module.new
|
2008-10-02 05:23:59 +00:00
|
|
|
|
|
|
|
# Load the module into a new Module wrapper
|
|
|
|
begin
|
2011-12-13 15:47:37 +00:00
|
|
|
wrap.module_eval(load_module_source(file), file)
|
2009-09-15 13:50:32 +00:00
|
|
|
if(wrap.const_defined?(:RequiredVersions))
|
|
|
|
mins = wrap.const_get(:RequiredVersions)
|
2011-01-26 03:13:40 +00:00
|
|
|
if( mins[0] > ::Msf::Framework::VersionCore or
|
2009-09-15 13:50:32 +00:00
|
|
|
mins[1] > ::Msf::Framework::VersionAPI
|
|
|
|
)
|
|
|
|
errmsg = "Failed to load module from #{file} due to version check (requires Core:#{mins[0]} API:#{mins[1]})"
|
|
|
|
elog(errmsg)
|
|
|
|
self.module_failed[mod.file_path] = errmsg
|
|
|
|
return false
|
|
|
|
end
|
2011-01-26 03:13:40 +00:00
|
|
|
end
|
2008-10-02 05:23:59 +00:00
|
|
|
rescue ::Exception => e
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2009-09-15 13:50:32 +00:00
|
|
|
# Hide eval errors when the module version is not compatible
|
|
|
|
if(wrap.const_defined?(:RequiredVersions))
|
|
|
|
mins = wrap.const_get(:RequiredVersions)
|
2011-01-26 03:13:40 +00:00
|
|
|
if( mins[0] > ::Msf::Framework::VersionCore or
|
2009-09-15 13:50:32 +00:00
|
|
|
mins[1] > ::Msf::Framework::VersionAPI
|
|
|
|
)
|
2009-09-20 20:25:08 +00:00
|
|
|
errmsg = "Failed to reload module from #{file} due to version check (requires Core:#{mins[0]} API:#{mins[1]})"
|
|
|
|
elog(errmsg)
|
|
|
|
self.module_failed[mod.file_path] = errmsg
|
2009-09-15 13:50:32 +00:00
|
|
|
return
|
2011-01-26 03:13:40 +00:00
|
|
|
end
|
2009-09-15 13:50:32 +00:00
|
|
|
end
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2009-09-20 20:25:08 +00:00
|
|
|
errmsg = "Failed to reload module from #{file}: #{e.class} #{e}"
|
|
|
|
elog(errmsg)
|
|
|
|
self.module_failed[mod.file_path] = errmsg
|
2009-09-15 13:50:32 +00:00
|
|
|
return
|
2005-10-10 00:30:14 +00:00
|
|
|
end
|
|
|
|
|
2011-06-25 04:57:01 +00:00
|
|
|
added = nil
|
2011-06-25 01:40:16 +00:00
|
|
|
::Msf::Framework::Major.downto(1) do |major|
|
|
|
|
if wrap.const_defined?("Metasploit#{major}")
|
|
|
|
added = wrap.const_get("Metasploit#{major}")
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if not added
|
2009-09-20 20:25:08 +00:00
|
|
|
errmsg = "Reloaded file did not contain a valid module (#{file})."
|
|
|
|
elog(errmsg)
|
|
|
|
self.module_failed[mod.file_path] = errmsg
|
2008-10-02 05:23:59 +00:00
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
|
|
|
self.module_failed.delete(mod.file_path)
|
|
|
|
|
2005-10-10 00:30:14 +00:00
|
|
|
# Remove the original reference to this module
|
|
|
|
self.delete(mod.refname)
|
|
|
|
|
|
|
|
# Indicate that the module is being loaded again so that any necessary
|
|
|
|
# steps can be taken to extend it properly.
|
2008-10-02 05:23:59 +00:00
|
|
|
on_module_load(added, mod.type, refname, {
|
2006-02-24 15:47:10 +00:00
|
|
|
'files' => [ mod.file_path ],
|
|
|
|
'noup' => true})
|
2005-10-10 00:30:14 +00:00
|
|
|
|
|
|
|
# Create a new instance of the module
|
|
|
|
if (mod = create(refname))
|
|
|
|
mod.datastore.update(ds)
|
|
|
|
else
|
|
|
|
elog("Failed to create instance of #{refname} after reload.", 'core')
|
2012-07-04 00:49:16 +00:00
|
|
|
# Return the old module instance to avoid a strace trace
|
|
|
|
return omod
|
2005-10-10 00:30:14 +00:00
|
|
|
end
|
|
|
|
|
2007-08-11 00:37:50 +00:00
|
|
|
# Let the specific module sets have an opportunity to handle the fact
|
2012-06-16 19:51:09 +00:00
|
|
|
# that this module was reloaded.
|
2007-08-11 00:37:50 +00:00
|
|
|
module_sets[mod.type].on_module_reload(mod)
|
|
|
|
|
2012-06-16 19:51:09 +00:00
|
|
|
# Rebuild the cache for just this module
|
|
|
|
rebuild_cache(mod)
|
|
|
|
|
2005-10-10 00:30:14 +00:00
|
|
|
mod
|
|
|
|
end
|
|
|
|
|
2005-10-31 15:56:59 +00:00
|
|
|
#
|
|
|
|
# Overrides the module set method for adding a module so that some extra
|
|
|
|
# steps can be taken to subscribe the module and notify the event
|
|
|
|
# dispatcher.
|
|
|
|
#
|
2006-02-21 03:10:58 +00:00
|
|
|
def add_module(mod, name, file_paths)
|
2005-10-31 15:56:59 +00:00
|
|
|
# Call the module set implementation of add_module
|
|
|
|
dup = super
|
|
|
|
|
|
|
|
# Automatically subscribe a wrapper around this module to the necessary
|
|
|
|
# event providers based on whatever events it wishes to receive. We
|
|
|
|
# only do this if we are the module manager instance, as individual
|
|
|
|
# module sets need not subscribe.
|
|
|
|
auto_subscribe_module(dup)
|
|
|
|
|
|
|
|
# Notify the framework that a module was loaded
|
|
|
|
framework.events.on_module_load(name, dup)
|
|
|
|
end
|
|
|
|
|
2006-07-30 22:28:47 +00:00
|
|
|
#
|
|
|
|
# Provide a list of the types of modules in the set
|
|
|
|
#
|
|
|
|
def module_types
|
|
|
|
module_sets.keys.dup
|
|
|
|
end
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2006-07-30 22:28:47 +00:00
|
|
|
#
|
|
|
|
# Provide a list of module names of a specific type
|
|
|
|
#
|
|
|
|
def module_names(set)
|
|
|
|
module_sets[set] ? module_sets[set].keys.dup : []
|
2011-01-26 03:13:40 +00:00
|
|
|
end
|
2006-07-30 22:28:47 +00:00
|
|
|
|
2011-11-12 20:48:11 +00:00
|
|
|
#
|
|
|
|
# Read the module code from the file on disk
|
|
|
|
#
|
|
|
|
def load_module_source(file)
|
|
|
|
::File.read(file, ::File.size(file))
|
|
|
|
end
|
|
|
|
|
2012-06-16 19:51:09 +00:00
|
|
|
#
|
|
|
|
# Rebuild the cache for the module set
|
|
|
|
#
|
|
|
|
def rebuild_cache(mod = nil)
|
|
|
|
return if not (framework.db and framework.db.migrated)
|
|
|
|
if mod
|
|
|
|
framework.db.update_module_details(mod)
|
|
|
|
else
|
|
|
|
framework.db.update_all_module_details
|
|
|
|
end
|
|
|
|
refresh_cache
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Return a listing of all cached modules
|
|
|
|
#
|
|
|
|
def cache_entries
|
|
|
|
return {} if not (framework.db and framework.db.migrated)
|
|
|
|
res = {}
|
|
|
|
::Mdm::ModuleDetail.find(:all).each do |m|
|
|
|
|
res[m.file] = { :mtype => m.mtype, :refname => m.refname, :file => m.file, :mtime => m.mtime }
|
|
|
|
unless module_set(m.mtype).has_key?(m.refname)
|
|
|
|
module_set(m.mtype)[m.refname] = SymbolicModule
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
res
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Reset the module cache
|
|
|
|
#
|
|
|
|
def refresh_cache
|
|
|
|
self.cache = cache_entries
|
|
|
|
end
|
|
|
|
|
|
|
|
def has_module_file_changed?(file)
|
|
|
|
begin
|
|
|
|
cfile = self.cache[file]
|
|
|
|
return true if not cfile
|
|
|
|
|
|
|
|
# Payloads can't be cached due to stage/stager matching
|
|
|
|
return true if cfile[:mtype] == "payload"
|
2012-06-16 20:41:37 +00:00
|
|
|
return cfile[:mtime].to_i != ::File.mtime(file).to_i
|
2012-06-16 19:51:09 +00:00
|
|
|
rescue ::Errno::ENOENT
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def has_archive_file_changed?(arch, file)
|
|
|
|
begin
|
|
|
|
cfile = self.cache[file]
|
|
|
|
return true if not cfile
|
|
|
|
|
|
|
|
# Payloads can't be cached due to stage/stager matching
|
|
|
|
return true if cfile[:mtype] == "payload"
|
|
|
|
|
2012-06-16 20:41:37 +00:00
|
|
|
return cfile[:mtime].to_i != ::File.mtime(file).to_i
|
2012-06-16 19:51:09 +00:00
|
|
|
rescue ::Errno::ENOENT
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def demand_load_module(mtype, mname)
|
|
|
|
n = self.cache.keys.select { |k|
|
|
|
|
self.cache[k][:mtype] == mtype and
|
|
|
|
self.cache[k][:refname] == mname
|
|
|
|
}.first
|
|
|
|
|
|
|
|
return nil unless n
|
|
|
|
m = self.cache[n]
|
|
|
|
|
|
|
|
path = nil
|
|
|
|
if m[:file] =~ /^(.*)\/#{m[:mtype]}s?\//
|
|
|
|
path = $1
|
|
|
|
load_module_from_file(path, m[:file], nil, nil, nil, true)
|
|
|
|
else
|
|
|
|
dlog("Could not demand load module #{mtype}/#{mname} (unknown base name in #{m[:file]})", 'core', LEV_2)
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-06-16 20:41:37 +00:00
|
|
|
attr_accessor :cache # :nodoc:
|
2012-06-16 19:51:09 +00:00
|
|
|
|
2005-05-22 07:14:16 +00:00
|
|
|
protected
|
|
|
|
|
2011-11-21 21:58:19 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Load all of the modules from the supplied directory or archive
|
|
|
|
#
|
|
|
|
def load_modules(bpath, demand = false)
|
2012-05-24 22:28:20 +00:00
|
|
|
( bpath =~ /\.fastlib$/ ) ?
|
|
|
|
load_modules_from_archive(bpath, demand) :
|
2011-11-21 21:58:19 +00:00
|
|
|
load_modules_from_directory(bpath, demand)
|
|
|
|
end
|
2012-05-24 22:28:20 +00:00
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-05-22 07:14:16 +00:00
|
|
|
# Load all of the modules from the supplied module path (independent of
|
2005-11-15 15:11:43 +00:00
|
|
|
# module type).
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2011-11-21 21:58:19 +00:00
|
|
|
def load_modules_from_directory(bpath, demand = false)
|
2005-05-22 07:14:16 +00:00
|
|
|
loaded = {}
|
2005-07-09 00:24:02 +00:00
|
|
|
recalc = {}
|
2005-07-14 06:34:58 +00:00
|
|
|
counts = {}
|
2005-08-22 01:42:13 +00:00
|
|
|
delay = {}
|
|
|
|
ks = true
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2011-11-21 21:58:19 +00:00
|
|
|
dbase = ::Dir.new(bpath)
|
2009-01-02 07:29:56 +00:00
|
|
|
dbase.entries.each do |ent|
|
2009-03-28 20:45:46 +00:00
|
|
|
next if ent.downcase == '.svn'
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2011-11-21 21:58:19 +00:00
|
|
|
path = ::File.join(bpath, ent)
|
2009-01-02 07:29:56 +00:00
|
|
|
mtype = ent.gsub(/s$/, '')
|
2009-03-28 20:45:46 +00:00
|
|
|
|
2011-11-21 21:58:19 +00:00
|
|
|
next if not ::File.directory?(path)
|
2009-01-02 07:29:56 +00:00
|
|
|
next if not MODULE_TYPES.include?(mtype)
|
|
|
|
next if not enabled_types[mtype]
|
2005-05-22 07:14:16 +00:00
|
|
|
|
2009-01-02 07:29:56 +00:00
|
|
|
# Try to load modules from all the files in the supplied path
|
|
|
|
Rex::Find.find(path) do |file|
|
2006-08-28 00:24:34 +00:00
|
|
|
|
2009-01-02 07:29:56 +00:00
|
|
|
# Skip non-ruby files
|
2009-03-28 20:45:46 +00:00
|
|
|
next if file[-3,3] != ".rb"
|
2007-03-25 07:38:11 +00:00
|
|
|
|
2009-01-02 07:29:56 +00:00
|
|
|
# Skip unit test files
|
|
|
|
next if (file =~ /rb\.(ut|ts)\.rb$/)
|
|
|
|
|
|
|
|
# Skip files with a leading period
|
2012-06-16 19:51:09 +00:00
|
|
|
next if file[0,1] == "."
|
2009-01-02 07:29:56 +00:00
|
|
|
|
2009-03-28 20:45:46 +00:00
|
|
|
load_module_from_file(bpath, file, loaded, recalc, counts, demand)
|
2005-05-22 07:14:16 +00:00
|
|
|
end
|
2009-01-02 07:29:56 +00:00
|
|
|
end
|
2005-05-22 07:14:16 +00:00
|
|
|
|
2012-06-16 19:51:09 +00:00
|
|
|
recalc.each_key do |mtype|
|
|
|
|
module_set(mtype).recalculate
|
|
|
|
end
|
2005-07-09 00:24:02 +00:00
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
# Return per-module loaded counts
|
|
|
|
return counts
|
2005-05-22 07:14:16 +00:00
|
|
|
end
|
|
|
|
|
2011-11-21 21:58:19 +00:00
|
|
|
|
|
|
|
#
|
2012-05-24 22:28:20 +00:00
|
|
|
# Load all of the modules from the supplied fastlib archive
|
2011-11-21 21:58:19 +00:00
|
|
|
#
|
|
|
|
def load_modules_from_archive(bpath, demand = false)
|
|
|
|
loaded = {}
|
|
|
|
recalc = {}
|
|
|
|
counts = {}
|
|
|
|
delay = {}
|
|
|
|
ks = true
|
|
|
|
|
|
|
|
::FastLib.list(bpath).each do |ent|
|
2012-05-24 22:28:20 +00:00
|
|
|
|
2011-11-21 21:58:19 +00:00
|
|
|
next if ent.index(".svn/")
|
2012-05-24 22:28:20 +00:00
|
|
|
|
2011-11-21 21:58:19 +00:00
|
|
|
mtype, path = ent.split("/", 2)
|
|
|
|
mtype.sub!(/s$/, '')
|
|
|
|
|
|
|
|
next if not MODULE_TYPES.include?(mtype)
|
|
|
|
next if not enabled_types[mtype]
|
|
|
|
|
|
|
|
# Skip non-ruby files
|
|
|
|
next if ent[-3,3] != ".rb"
|
|
|
|
|
|
|
|
# Skip unit test files
|
|
|
|
next if (ent =~ /rb\.(ut|ts)\.rb$/)
|
|
|
|
|
|
|
|
# Skip files with a leading period
|
2012-06-16 19:51:09 +00:00
|
|
|
next if ent[0,1] == "."
|
2011-11-21 21:58:19 +00:00
|
|
|
|
|
|
|
load_module_from_archive(bpath, ent, loaded, recalc, counts, demand)
|
|
|
|
end
|
|
|
|
|
2012-06-16 19:51:09 +00:00
|
|
|
recalc.each_key do |mtype|
|
|
|
|
module_set(mtype).recalculate
|
|
|
|
end
|
2011-11-21 21:58:19 +00:00
|
|
|
|
|
|
|
# Return per-module loaded counts
|
|
|
|
return counts
|
|
|
|
end
|
2012-05-24 22:28:20 +00:00
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
2005-08-22 01:42:13 +00:00
|
|
|
# Loads a module from the supplied file.
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
2006-02-21 03:10:58 +00:00
|
|
|
def load_module_from_file(path, file, loaded, recalc, counts, demand = false)
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2012-06-16 19:51:09 +00:00
|
|
|
if not ( demand or has_module_file_changed?(file))
|
2007-03-25 07:38:11 +00:00
|
|
|
dlog("Cached module from file #{file} has not changed.", 'core', LEV_2)
|
2006-02-21 17:17:25 +00:00
|
|
|
return false
|
2005-08-22 01:42:13 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# Substitute the base path
|
|
|
|
path_base = file.sub(path + File::SEPARATOR, '')
|
|
|
|
|
|
|
|
# Derive the name from the path with the exclusion of the .rb
|
|
|
|
name = path_base.match(/^(.+?)#{File::SEPARATOR}(.*)(.rb?)$/)[2]
|
|
|
|
|
|
|
|
# Chop off the file name
|
|
|
|
path_base.sub!(/(.+)(#{File::SEPARATOR}.+)(.rb?)$/, '\1')
|
|
|
|
|
2011-01-26 03:13:40 +00:00
|
|
|
if (m = path_base.match(/^(.+?)#{File::SEPARATOR}+?/))
|
2005-11-28 23:49:48 +00:00
|
|
|
type = m[1]
|
|
|
|
else
|
|
|
|
type = path_base
|
|
|
|
end
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2005-11-28 23:49:48 +00:00
|
|
|
type.sub!(/s$/, '')
|
2005-08-22 01:42:13 +00:00
|
|
|
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2008-10-02 05:23:59 +00:00
|
|
|
added = nil
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2012-09-27 17:52:09 +00:00
|
|
|
wrap = self.class.wrapper_module(name)
|
|
|
|
|
2005-08-22 01:42:13 +00:00
|
|
|
begin
|
2011-12-13 15:47:37 +00:00
|
|
|
wrap.module_eval(load_module_source(file), file)
|
2009-09-15 13:50:32 +00:00
|
|
|
if(wrap.const_defined?(:RequiredVersions))
|
|
|
|
mins = wrap.const_get(:RequiredVersions)
|
2011-01-26 03:13:40 +00:00
|
|
|
if( mins[0] > ::Msf::Framework::VersionCore or
|
2009-09-15 13:50:32 +00:00
|
|
|
mins[1] > ::Msf::Framework::VersionAPI
|
|
|
|
)
|
|
|
|
errmsg = "Failed to load module from #{file} due to version check (requires Core:#{mins[0]} API:#{mins[1]})"
|
|
|
|
elog(errmsg)
|
|
|
|
self.module_failed[file] = errmsg
|
|
|
|
return false
|
|
|
|
end
|
2011-01-26 03:13:40 +00:00
|
|
|
end
|
2009-03-28 20:45:46 +00:00
|
|
|
rescue ::Interrupt
|
|
|
|
raise $!
|
Merged revisions 5366-5377 via svnmerge from
svn+ssh://metasploit.com/home/svn/framework3/branches/framework-3.1
........
r5366 | hdm | 2008-01-26 20:30:53 -0600 (Sat, 26 Jan 2008) | 2 lines
Update version information
........
r5367 | hdm | 2008-01-26 21:10:57 -0600 (Sat, 26 Jan 2008) | 3 lines
Updated for version 3.1
........
r5369 | hdm | 2008-01-26 21:13:31 -0600 (Sat, 26 Jan 2008) | 3 lines
Wipe the private directories from the branch.
........
r5371 | hdm | 2008-01-27 17:24:24 -0600 (Sun, 27 Jan 2008) | 5 lines
Timeout options added for dcerpc connect and read times. Addition of novell netware as a supported target platform. Inclusion of the serverprotect exploit (still works on the latest version). Addition of the first remote netware kernel exploit that leads to a shell, addition of netware stager and shell, and first draft of the release notes for 3.1
........
r5372 | hdm | 2008-01-27 17:30:08 -0600 (Sun, 27 Jan 2008) | 3 lines
Formatting, indentation, fixed the static IP embedded in the request
........
r5373 | hdm | 2008-01-27 20:02:48 -0600 (Sun, 27 Jan 2008) | 3 lines
Correctly trap exploit errors in a way that works with all of the UIs
........
r5374 | hdm | 2008-01-27 20:23:25 -0600 (Sun, 27 Jan 2008) | 3 lines
More last-minute bug fixes
........
r5375 | hdm | 2008-01-27 20:37:43 -0600 (Sun, 27 Jan 2008) | 3 lines
Force multi-bind off in netware, correct label display in gtk gui labels
........
r5376 | hdm | 2008-01-27 20:50:03 -0600 (Sun, 27 Jan 2008) | 3 lines
More exception handling fun
........
git-svn-id: file:///home/svn/framework3/trunk@5378 4d416f70-5f16-0410-b530-b9f4589650da
2008-01-28 03:06:31 +00:00
|
|
|
rescue ::Exception => e
|
2009-09-15 13:50:32 +00:00
|
|
|
# Hide eval errors when the module version is not compatible
|
|
|
|
if(wrap.const_defined?(:RequiredVersions))
|
|
|
|
mins = wrap.const_get(:RequiredVersions)
|
2011-01-26 03:13:40 +00:00
|
|
|
if( mins[0] > ::Msf::Framework::VersionCore or
|
2009-09-15 13:50:32 +00:00
|
|
|
mins[1] > ::Msf::Framework::VersionAPI
|
|
|
|
)
|
|
|
|
errmsg = "Failed to load module from #{file} due to error and failed version check (requires Core:#{mins[0]} API:#{mins[1]})"
|
|
|
|
elog(errmsg)
|
|
|
|
self.module_failed[file] = errmsg
|
|
|
|
return false
|
2011-01-26 03:13:40 +00:00
|
|
|
end
|
2009-09-15 13:50:32 +00:00
|
|
|
end
|
2010-05-24 23:07:52 +00:00
|
|
|
errmsg = "#{e.class} #{e}"
|
2008-10-02 05:23:59 +00:00
|
|
|
self.module_failed[file] = errmsg
|
|
|
|
elog(errmsg)
|
Merged revisions 5366-5377 via svnmerge from
svn+ssh://metasploit.com/home/svn/framework3/branches/framework-3.1
........
r5366 | hdm | 2008-01-26 20:30:53 -0600 (Sat, 26 Jan 2008) | 2 lines
Update version information
........
r5367 | hdm | 2008-01-26 21:10:57 -0600 (Sat, 26 Jan 2008) | 3 lines
Updated for version 3.1
........
r5369 | hdm | 2008-01-26 21:13:31 -0600 (Sat, 26 Jan 2008) | 3 lines
Wipe the private directories from the branch.
........
r5371 | hdm | 2008-01-27 17:24:24 -0600 (Sun, 27 Jan 2008) | 5 lines
Timeout options added for dcerpc connect and read times. Addition of novell netware as a supported target platform. Inclusion of the serverprotect exploit (still works on the latest version). Addition of the first remote netware kernel exploit that leads to a shell, addition of netware stager and shell, and first draft of the release notes for 3.1
........
r5372 | hdm | 2008-01-27 17:30:08 -0600 (Sun, 27 Jan 2008) | 3 lines
Formatting, indentation, fixed the static IP embedded in the request
........
r5373 | hdm | 2008-01-27 20:02:48 -0600 (Sun, 27 Jan 2008) | 3 lines
Correctly trap exploit errors in a way that works with all of the UIs
........
r5374 | hdm | 2008-01-27 20:23:25 -0600 (Sun, 27 Jan 2008) | 3 lines
More last-minute bug fixes
........
r5375 | hdm | 2008-01-27 20:37:43 -0600 (Sun, 27 Jan 2008) | 3 lines
Force multi-bind off in netware, correct label display in gtk gui labels
........
r5376 | hdm | 2008-01-27 20:50:03 -0600 (Sun, 27 Jan 2008) | 3 lines
More exception handling fun
........
git-svn-id: file:///home/svn/framework3/trunk@5378 4d416f70-5f16-0410-b530-b9f4589650da
2008-01-28 03:06:31 +00:00
|
|
|
return false
|
2005-08-22 01:42:13 +00:00
|
|
|
end
|
|
|
|
|
2011-06-25 01:40:16 +00:00
|
|
|
::Msf::Framework::Major.downto(1) do |major|
|
|
|
|
if wrap.const_defined?("Metasploit#{major}")
|
|
|
|
added = wrap.const_get("Metasploit#{major}")
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if not added
|
|
|
|
errmsg = "Missing Metasploit class constant"
|
2008-10-02 05:23:59 +00:00
|
|
|
self.module_failed[file] = errmsg
|
|
|
|
elog(errmsg)
|
2006-02-21 03:10:58 +00:00
|
|
|
return false
|
2005-08-22 01:42:13 +00:00
|
|
|
end
|
|
|
|
|
2011-01-26 03:13:40 +00:00
|
|
|
# If the module indicates that it is not usable on this system, then we
|
2005-11-02 14:18:50 +00:00
|
|
|
# will not try to use it.
|
|
|
|
usable = false
|
|
|
|
|
|
|
|
begin
|
2009-06-25 17:59:51 +00:00
|
|
|
usable = respond_to?(:is_usable) ? added.is_usable : true
|
2005-11-02 14:18:50 +00:00
|
|
|
rescue
|
|
|
|
elog("Exception caught during is_usable check: #{$!}")
|
|
|
|
end
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2005-11-02 14:18:50 +00:00
|
|
|
if (usable == false)
|
2008-10-02 05:23:59 +00:00
|
|
|
ilog("Skipping module in #{file} because is_usable returned false.", 'core', LEV_1)
|
2006-02-21 03:10:58 +00:00
|
|
|
return false
|
2005-11-02 14:18:50 +00:00
|
|
|
end
|
|
|
|
|
2005-11-02 00:27:59 +00:00
|
|
|
ilog("Loaded #{type} module #{added} from #{file}.", 'core', LEV_2)
|
2006-09-16 06:27:14 +00:00
|
|
|
self.module_failed.delete(file)
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2005-08-22 01:42:13 +00:00
|
|
|
# Do some processing on the loaded module to get it into the
|
|
|
|
# right associations
|
2006-02-21 03:10:58 +00:00
|
|
|
on_module_load(added, type, name, {
|
|
|
|
'files' => [ file ],
|
|
|
|
'paths' => [ path ],
|
|
|
|
'type' => type })
|
2005-08-22 01:42:13 +00:00
|
|
|
|
|
|
|
# Set this module type as needing recalculation
|
2006-02-21 03:10:58 +00:00
|
|
|
recalc[type] = true if (recalc)
|
2005-08-22 01:42:13 +00:00
|
|
|
|
|
|
|
# Append the added module to the hash of file->module
|
2006-02-21 03:10:58 +00:00
|
|
|
loaded[file] = added if (loaded)
|
2011-01-26 03:13:40 +00:00
|
|
|
|
2005-08-22 01:42:13 +00:00
|
|
|
# The number of loaded modules this round
|
2006-02-21 03:10:58 +00:00
|
|
|
if (counts)
|
|
|
|
counts[type] = (counts[type]) ? (counts[type] + 1) : 1
|
|
|
|
end
|
|
|
|
|
|
|
|
return true
|
2005-08-22 01:42:13 +00:00
|
|
|
end
|
|
|
|
|
2011-11-21 21:58:19 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Loads a module from the supplied archive path
|
|
|
|
#
|
|
|
|
def load_module_from_archive(path, file, loaded, recalc, counts, demand = false)
|
2012-06-16 19:51:09 +00:00
|
|
|
|
|
|
|
if not ( demand or has_archive_module_file_changed?(file))
|
|
|
|
dlog("Cached module from file #{file} has not changed.", 'core', LEV_2)
|
|
|
|
return false
|
|
|
|
end
|
2012-05-24 22:28:20 +00:00
|
|
|
|
2011-11-21 21:58:19 +00:00
|
|
|
# Derive the name from the path with the exclusion of the .rb
|
|
|
|
name = file.match(/^(.+?)#{File::SEPARATOR}(.*)(.rb?)$/)[2]
|
|
|
|
|
|
|
|
# Chop off the file name
|
|
|
|
base = file.sub(/(.+)(#{File::SEPARATOR}.+)(.rb?)$/, '\1')
|
|
|
|
|
|
|
|
if (m = base.match(/^(.+?)#{File::SEPARATOR}+?/))
|
|
|
|
type = m[1]
|
|
|
|
else
|
|
|
|
type = base
|
|
|
|
end
|
|
|
|
|
|
|
|
type.sub!(/s$/, '')
|
|
|
|
|
|
|
|
added = nil
|
|
|
|
|
|
|
|
begin
|
|
|
|
wrap = ::Module.new
|
2011-12-13 15:47:37 +00:00
|
|
|
wrap.module_eval( ::FastLib.load(path, file), file )
|
2011-11-21 21:58:19 +00:00
|
|
|
if(wrap.const_defined?(:RequiredVersions))
|
|
|
|
mins = wrap.const_get(:RequiredVersions)
|
|
|
|
if( mins[0] > ::Msf::Framework::VersionCore or
|
|
|
|
mins[1] > ::Msf::Framework::VersionAPI
|
|
|
|
)
|
|
|
|
errmsg = "Failed to load module from #{path}::#{file} due to version check (requires Core:#{mins[0]} API:#{mins[1]})"
|
|
|
|
elog(errmsg)
|
|
|
|
self.module_failed[file] = errmsg
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
rescue ::Interrupt
|
|
|
|
raise $!
|
|
|
|
rescue ::Exception => e
|
|
|
|
# Hide eval errors when the module version is not compatible
|
|
|
|
if(wrap.const_defined?(:RequiredVersions))
|
|
|
|
mins = wrap.const_get(:RequiredVersions)
|
|
|
|
if( mins[0] > ::Msf::Framework::VersionCore or
|
|
|
|
mins[1] > ::Msf::Framework::VersionAPI
|
|
|
|
)
|
|
|
|
errmsg = "Failed to load module from #{path}::#{file}due to error and failed version check (requires Core:#{mins[0]} API:#{mins[1]})"
|
|
|
|
elog(errmsg)
|
|
|
|
self.module_failed[file] = errmsg
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
errmsg = "#{e.class} #{e}"
|
|
|
|
self.module_failed[file] = errmsg
|
|
|
|
elog(errmsg)
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
::Msf::Framework::Major.downto(1) do |major|
|
|
|
|
if wrap.const_defined?("Metasploit#{major}")
|
|
|
|
added = wrap.const_get("Metasploit#{major}")
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if not added
|
|
|
|
errmsg = "Missing Metasploit class constant"
|
|
|
|
self.module_failed[file] = errmsg
|
|
|
|
elog(errmsg)
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
# If the module indicates that it is not usable on this system, then we
|
|
|
|
# will not try to use it.
|
|
|
|
usable = false
|
|
|
|
|
|
|
|
begin
|
|
|
|
usable = respond_to?(:is_usable) ? added.is_usable : true
|
|
|
|
rescue
|
|
|
|
elog("Exception caught during is_usable check: #{$!}")
|
|
|
|
end
|
|
|
|
|
|
|
|
if (usable == false)
|
|
|
|
ilog("Skipping module in #{path}::#{file} because is_usable returned false.", 'core', LEV_1)
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
ilog("Loaded #{type} module #{added} from #{path}::#{file}.", 'core', LEV_2)
|
|
|
|
self.module_failed.delete(file)
|
|
|
|
|
|
|
|
# Do some processing on the loaded module to get it into the
|
|
|
|
# right associations
|
|
|
|
on_module_load(added, type, name, {
|
|
|
|
'files' => [ file ],
|
|
|
|
'paths' => [ path ],
|
|
|
|
'type' => type })
|
|
|
|
|
|
|
|
# Set this module type as needing recalculation
|
|
|
|
recalc[type] = true if (recalc)
|
|
|
|
|
|
|
|
# Append the added module to the hash of file->module
|
|
|
|
loaded[file] = added if (loaded)
|
|
|
|
|
|
|
|
# The number of loaded modules this round
|
|
|
|
if (counts)
|
|
|
|
counts[type] = (counts[type]) ? (counts[type] + 1) : 1
|
|
|
|
end
|
|
|
|
|
|
|
|
return true
|
|
|
|
end
|
2012-05-24 22:28:20 +00:00
|
|
|
|
2005-05-22 07:14:16 +00:00
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-05-22 07:14:16 +00:00
|
|
|
# Called when a module is initially loaded such that it can be
|
2005-11-15 15:11:43 +00:00
|
|
|
# categorized accordingly.
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2006-02-21 03:10:58 +00:00
|
|
|
def on_module_load(mod, type, name, modinfo)
|
2005-07-09 00:24:02 +00:00
|
|
|
# Payload modules require custom loading as the individual files
|
2011-01-26 03:13:40 +00:00
|
|
|
# may not directly contain a logical payload that a user would
|
|
|
|
# reference, such as would be the case with a payload stager or
|
2005-07-09 00:24:02 +00:00
|
|
|
# stage. As such, when payload modules are loaded they are handed
|
|
|
|
# off to a special payload set. The payload set, in turn, will
|
|
|
|
# automatically create all the permutations after all the payload
|
|
|
|
# modules have been loaded.
|
2012-06-16 19:51:09 +00:00
|
|
|
|
2005-07-09 00:24:02 +00:00
|
|
|
if (type != MODULE_PAYLOAD)
|
|
|
|
# Add the module class to the list of modules and add it to the
|
|
|
|
# type separated set of module classes
|
2006-02-21 03:10:58 +00:00
|
|
|
add_module(mod, name, modinfo)
|
2005-07-09 00:24:02 +00:00
|
|
|
end
|
2005-07-11 05:15:30 +00:00
|
|
|
|
2006-02-21 03:10:58 +00:00
|
|
|
module_sets[type].add_module(mod, name, modinfo)
|
2005-05-22 07:14:16 +00:00
|
|
|
end
|
|
|
|
|
2005-10-31 15:56:59 +00:00
|
|
|
#
|
|
|
|
# This method automatically subscribes a module to whatever event providers
|
|
|
|
# it wishes to monitor. This can be used to allow modules to automatically
|
|
|
|
# execute or perform other tasks when certain events occur. For instance,
|
2006-01-24 03:59:44 +00:00
|
|
|
# when a new host is detected, other aux modules may wish to run such
|
2005-10-31 15:56:59 +00:00
|
|
|
# that they can collect more information about the host that was detected.
|
|
|
|
#
|
|
|
|
def auto_subscribe_module(mod)
|
|
|
|
# If auto-subscribe has been disabled
|
|
|
|
if (framework.datastore['DisableAutoSubscribe'] and
|
|
|
|
framework.datastore['DisableAutoSubscribe'] =~ /^(y|1|t)/)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
# If auto-subscription is enabled (which it is by default), figure out
|
|
|
|
# if it subscribes to any particular interfaces.
|
|
|
|
inst = nil
|
|
|
|
|
|
|
|
#
|
|
|
|
# Exploit event subscriber check
|
|
|
|
#
|
|
|
|
if (mod.include?(ExploitEvent) == true)
|
|
|
|
framework.events.add_exploit_subscriber((inst) ? inst : (inst = mod.new))
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Session event subscriber check
|
|
|
|
#
|
|
|
|
if (mod.include?(SessionEvent) == true)
|
|
|
|
framework.events.add_session_subscriber((inst) ? inst : (inst = mod.new))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
attr_accessor :modules, :module_sets # :nodoc:
|
|
|
|
attr_accessor :module_paths # :nodoc:
|
2006-09-16 06:27:14 +00:00
|
|
|
attr_accessor :module_failed # :nodoc:
|
2009-01-02 07:29:56 +00:00
|
|
|
attr_accessor :enabled_types # :nodoc:
|
2005-05-22 07:14:16 +00:00
|
|
|
|
2012-09-27 17:52:09 +00:00
|
|
|
# Returns a nested module to wrap the Metasploit(1|2|3) class so that it doesn't overwrite other (metasploit) module's
|
|
|
|
# classes. The wrapper module must be named so that active_support's autoloading code doesn't break when searching
|
|
|
|
# constants from inside the Metasploit(1|2|3) class.
|
|
|
|
#
|
|
|
|
# @return [Module] Msf::Modules::<name>
|
|
|
|
def self.wrapper_module(name)
|
|
|
|
relative_module_name = name.camelize
|
|
|
|
fully_qualified_module_name = "#{parent.name}::Modules::#{relative_module_name}"
|
|
|
|
|
|
|
|
wrapper_module = Object
|
|
|
|
module_names = fully_qualified_module_name.split('::')
|
|
|
|
|
|
|
|
until module_names.empty?
|
|
|
|
parent = wrapper_module
|
|
|
|
child_name = module_names.shift
|
|
|
|
|
|
|
|
# constant names can't contain a leading digit or any non-alphanumeric characters, so convert to hexcode with
|
|
|
|
# 'X' prefix.
|
|
|
|
child_name = child_name.gsub(/^[0-9]|[^A-Za-z0-9]/) do |invalid_constant_name_character|
|
|
|
|
unpacked = invalid_constant_name_character.unpack('H*')
|
|
|
|
# unpack always returns an array, so get first value to get character's encoding
|
|
|
|
hex_code = unpacked[0]
|
|
|
|
|
|
|
|
# as a convention start each hex-code with X so that it'll make a valid constant name since constants can't
|
|
|
|
# start with digits.
|
|
|
|
"X#{hex_code}"
|
|
|
|
end
|
|
|
|
|
|
|
|
# don't look for constants in ancestors since the namespace modules should be defined directly on the parent and
|
|
|
|
# previously by this same method.
|
|
|
|
inherit = false
|
|
|
|
|
|
|
|
if module_names.empty? and parent.const_defined?(child_name, inherit)
|
|
|
|
ilog("Removing #{child_name} constant from #{parent.name} so it can be reloaded", 'core', LEV_1)
|
|
|
|
# if this is the leaf module name then it needs to be destroyed and recreated if it already exists as this is
|
|
|
|
# a reload
|
|
|
|
# remove_const is private, so invoke in instance context
|
|
|
|
parent.instance_eval do
|
|
|
|
remove_const child_name
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if parent.const_defined?(child_name, inherit)
|
|
|
|
wrapper_module = parent.const_get(child_name)
|
|
|
|
else
|
|
|
|
# stub module to represent namespace
|
|
|
|
# use ruby Module, not Msf::Module
|
|
|
|
namespace_module = ::Module.new
|
|
|
|
|
|
|
|
ilog("Adding #{child_name} constant to #{parent.name} as a namespace Module", 'core', LEV_1)
|
|
|
|
# once it's assigned to a constant, then wrapper_module.name will work.
|
|
|
|
wrapper_module = parent.const_set(child_name, namespace_module)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
wrapper_module
|
|
|
|
end
|
2005-05-22 07:14:16 +00:00
|
|
|
end
|
|
|
|
|
2008-11-16 19:26:59 +00:00
|
|
|
end
|
2011-06-25 01:40:16 +00:00
|
|
|
|