113 lines
3.0 KiB
Ruby
113 lines
3.0 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)
|
|
# Payload modules require custom loading as the individual files
|
|
# may not directly contain a logical payload that a user would
|
|
# reference, such as would be the case with a payload stager or
|
|
# 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.
|
|
|
|
if (type != Msf::MODULE_PAYLOAD)
|
|
# Add the module class to the list of modules and add it to the
|
|
# type separated set of module classes
|
|
add_module(mod, name, modinfo)
|
|
end
|
|
|
|
module_set_by_type[type].add_module(mod, name, modinfo)
|
|
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
|