fb266d5eb9
[#36737359] Refactor the behavior of loading symbolic modules from cache by renaming methods so it's clearer what they do and ensure that cached modules from Fastlibs and directories can both be loaded, which was not previously possible since the demand_load_module only called load_module_from_file.
129 lines
3.8 KiB
Ruby
129 lines
3.8 KiB
Ruby
#
|
|
# Gems
|
|
#
|
|
require 'active_support/concern'
|
|
|
|
# Concerns the module cache maintained by the {Msf::ModuleManager}.
|
|
module Msf::ModuleManager::Cache
|
|
extend ActiveSupport::Concern
|
|
|
|
# Returns whether the cache is empty
|
|
#
|
|
# @return [true] if the cache has no entries.
|
|
# @return [false] if the cache has any entries.
|
|
def cache_empty?
|
|
module_info_by_path.empty?
|
|
end
|
|
|
|
# Forces loading of the module with the given type and module reference name from the cache.
|
|
#
|
|
# @param [String] type the type of the module.
|
|
# @param [String] reference_name the module reference name.
|
|
# @return [false] if a module with the given type and reference name does not exist in the cache.
|
|
# @return (see Msf::Modules::Loader::Base#load_module)
|
|
def load_cached_module(type, reference_name)
|
|
loaded = false
|
|
|
|
module_info = self.module_info_by_path.values.find { |module_info|
|
|
module_info[:type] == type and module_info[:reference_name] == reference_name
|
|
}
|
|
|
|
if module_info
|
|
parent_path = module_info[:parent_path]
|
|
|
|
loaders.each do |loader|
|
|
if loader.loadable?(parent_path)
|
|
type = module_info[:type]
|
|
reference_name = module_info[:reference_name]
|
|
|
|
loaded = loader.load_module(parent_path, type, reference_name, :force => true)
|
|
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
loaded
|
|
end
|
|
|
|
# Rebuild the cache for the module set
|
|
#
|
|
# @return [void]
|
|
def refresh_cache_from_module_files(mod = nil)
|
|
if framework_migrated?
|
|
if mod
|
|
framework.db.update_module_details(mod)
|
|
else
|
|
framework.db.update_all_module_details
|
|
end
|
|
|
|
refresh_cache_from_database
|
|
end
|
|
end
|
|
|
|
# Reset the module cache
|
|
#
|
|
# @return [void]
|
|
def refresh_cache_from_database
|
|
self.module_info_by_path_from_database!
|
|
end
|
|
|
|
protected
|
|
|
|
# Returns whether the framework migrations have been run already.
|
|
#
|
|
# @return [true] if migrations have been run
|
|
# @return [false] otherwise
|
|
def framework_migrated?
|
|
if framework.db and framework.db.migrated
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
|
|
# @!attribute [rw] module_info_by_path
|
|
# @return (see #module_info_by_path_from_database!)
|
|
attr_accessor :module_info_by_path
|
|
|
|
# Return a module info from Mdm::ModuleDetails in database.
|
|
#
|
|
# @note Also sets module_set(module_type)[module_reference_name] to Msf::SymbolicModule if it is not already set.
|
|
#
|
|
# @return [Hash{String => Hash{Symbol => Object}}] Maps path (Mdm::ModuleDetail#file) to module information. Module
|
|
# information is a Hash derived from Mdm::ModuleDetail. It includes :modification_time, :parent_path, :type,
|
|
# :reference_name.
|
|
def module_info_by_path_from_database!
|
|
self.module_info_by_path = {}
|
|
|
|
if framework_migrated?
|
|
# TODO record module parent_path in {Mdm::ModuleDetail} so it does not need to be derived from file.
|
|
::Mdm::ModuleDetail.find(:all).each do |module_detail|
|
|
path = module_detail.file
|
|
type = module_detail.mtype
|
|
reference_name = module_detail.refname
|
|
|
|
typed_path = Msf::Modules::Loader::Base.typed_path(type, reference_name)
|
|
escaped_typed_path = Regexp.escape(typed_path)
|
|
parent_path = path.gsub(/#{escaped_typed_path}$/, '')
|
|
|
|
module_info_by_path[path] = {
|
|
:reference_name => reference_name,
|
|
:type => type,
|
|
:parent_path => parent_path,
|
|
:modification_time => module_detail.mtime
|
|
}
|
|
|
|
typed_module_set = module_set(type)
|
|
|
|
# Don't want to trigger as {Msf::ModuleSet#create} so check for key instead of using ||= which would call
|
|
# {Msf::ModuleSet#[]} which would potentially call {Msf::ModuleSet#create}.
|
|
unless typed_module_set.has_key? reference_name
|
|
typed_module_set[reference_name] = Msf::SymbolicModule
|
|
end
|
|
end
|
|
end
|
|
|
|
self.module_info_by_path
|
|
end
|
|
end |