Files
metasploit-gs/lib/msf/core/module_manager/loading.rb
T
James Lee f4476cb1b7 Really fix payload recalculation
Instead of deleting all non-symbolics before the re-adding phase of
PayloadSet#recalculate, store a list of old module names, populate a
list of new ones during the re-adding phase, and finally remove any
non-symbolic module that was in the old list but wasn't in the new list.

Also includes a minor refactoring to make ModuleManager its own thing
instead of being an awkard subclass of ModuleSet. Now PayloadSet doesn't
need to know about the existence of framework.modules, which makes the
separation a little more natural.

[FixRM #7037]
2012-12-03 22:23:40 -06:00

108 lines
2.6 KiB
Ruby

#
# Gems
#
require 'active_support/concern'
#
# Project
#
require 'msf/core/modules/loader/archive'
require 'msf/core/modules/loader/directory'
# Deals with loading modules for the {Msf::ModuleManager}
module Msf::ModuleManager::Loading
extend ActiveSupport::Concern
#
# CONSTANTS
#
# Classes that can be used to load modules.
LOADER_CLASSES = [
Msf::Modules::Loader::Archive,
Msf::Modules::Loader::Directory
]
def file_changed?(path)
changed = false
module_info = self.module_info_by_path[path]
# if uncached then it counts as changed
# Payloads can't be cached due to stage/stager matching
if module_info.nil? or module_info[:type] == Msf::MODULE_PAYLOAD
changed = true
else
begin
current_modification_time = ::File.mtime(path).to_i
rescue ::Errno::ENOENT
# if the file does not exist now, that's a change
changed = true
else
cached_modification_time = module_info[:modification_time].to_i
# if the file's modification time's different from the cache, then it's changed
if current_modification_time != cached_modification_time
changed = true
end
end
end
changed
end
attr_accessor :module_load_error_by_path
# Called when a module is initially loaded such that it can be
# categorized accordingly.
#
def on_module_load(mod, type, name, modinfo)
dup = module_set_by_type[type].add_module(mod, name, modinfo)
# Automatically subscribe a wrapper around this module to the necessary
# event providers based on whatever events it wishes to receive.
auto_subscribe_module(dup)
# Notify the framework that a module was loaded
framework.events.on_module_load(name, dup)
dup
end
protected
# Return list of {LOADER_CLASSES} instances that load modules into this module manager
def loaders
unless instance_variable_defined? :@loaders
@loaders = LOADER_CLASSES.collect { |klass|
klass.new(self)
}
end
@loaders
end
# Load all of the modules from the supplied directory or archive
#
# @param [String] path Path to a directory or Fastlib archive
# @param [Hash] options
# @option options [Boolean] :force Whether the force loading the modules even if they are unchanged and already
# loaded.
# @return [Hash{String => Integer}] Maps module type to number of modules loaded
def load_modules(path, options={})
options.assert_valid_keys(:force)
count_by_type = {}
loaders.each do |loader|
if loader.loadable?(path)
count_by_type = loader.load_modules(path, options)
break
end
end
count_by_type
end
end