135 lines
4.3 KiB
Ruby
135 lines
4.3 KiB
Ruby
# -*- coding: binary -*-
|
|
|
|
# Msf::ModuleManager::Reloading
|
|
#
|
|
# Provides methods for reloading Metasploit modules (including payloads,
|
|
# stagers, adapters, stages, etc.), clearing out old aliases, and
|
|
# refreshing the module cache.
|
|
module Msf::ModuleManager::Reloading
|
|
# Reloads the module specified in mod. This can either be an instance of a module or a module class.
|
|
#
|
|
# @param [Msf::Module, Class] mod either an instance of a module or a module class
|
|
# @return (see Msf::Modules::Loader::Base#reload_module)
|
|
def reload_module(mod)
|
|
# if it's an instance, then get its class
|
|
if mod.is_a? Msf::Module
|
|
metasploit_class = mod.class
|
|
else
|
|
metasploit_class = mod
|
|
end
|
|
|
|
if (aliased_as = inv_aliases[metasploit_class.fullname])
|
|
aliased_as.each do |a|
|
|
aliases.delete a
|
|
end
|
|
inv_aliases.delete metasploit_class.fullname
|
|
end
|
|
|
|
if mod.payload?
|
|
return reload_payload_module(mod)
|
|
end
|
|
|
|
if (aliased_as = inv_aliases[metasploit_class.fullname])
|
|
aliased_as.each do |a|
|
|
aliases.delete a
|
|
end
|
|
inv_aliases.delete metasploit_class.fullname
|
|
end
|
|
|
|
namespace_module = metasploit_class.module_parent
|
|
|
|
# Check if the namespace module has a loader
|
|
unless namespace_module.respond_to?(:loader)
|
|
elog('Module does not have loader')
|
|
return mod
|
|
end
|
|
|
|
loader = namespace_module.loader
|
|
loader.reload_module(mod)
|
|
end
|
|
|
|
def manual_reload(parent_path, type, ref_name)
|
|
loaders.each { |loader| loader.load_module(parent_path, type, ref_name, { force: true }) }
|
|
end
|
|
|
|
# Reload payload module, separately from other categories. This is due to complexity of payload module and due to the fact they don't follow class structure as rest of the modules.
|
|
# @param [Msf::Module, Class] mod either an instance of a module or a module class
|
|
# @return (see Msf::Modules::Loader::Base#reload_module)
|
|
def reload_payload_module(mod)
|
|
if mod.is_a? Msf::Module
|
|
metasploit_class = mod.class
|
|
original_instance = mod
|
|
else
|
|
metasploit_class = mod
|
|
original_instance = nil
|
|
end
|
|
if (module_set = module_set_by_type.fetch(metasploit_class.type, nil))
|
|
module_set.delete(metasploit_class.refname)
|
|
end
|
|
module_info = module_info_by_path[metasploit_class.file_path]
|
|
unless module_info && (parent_path = module_info[:parent_path])
|
|
elog('Failed to get parent_path from module object')
|
|
return mod
|
|
end
|
|
|
|
# reload adapters if any
|
|
manual_reload(parent_path, module_info[:type], File.join('adapters', mod.adapter_refname)) if mod.adapter_refname
|
|
|
|
# reload stagers if any
|
|
manual_reload(parent_path, module_info[:type], File.join('stagers', mod.stager_refname)) if mod.stager_refname
|
|
|
|
# reload stages if any
|
|
manual_reload(parent_path, module_info[:type], File.join('stages', mod.stage_refname)) if mod.stage_refname
|
|
|
|
# reload single if any
|
|
manual_reload(parent_path, module_info[:type], File.join('singles', module_info[:reference_name])) if original_instance.payload_type == Msf::Payload::Type::Single
|
|
|
|
# Get reloaded module
|
|
new_instance = framework.modules.create(metasploit_class.fullname)
|
|
|
|
if new_instance.blank?
|
|
elog('Failed create new instance')
|
|
return mod
|
|
end
|
|
|
|
# Restore the datastore
|
|
new_instance.datastore.merge!(original_instance.datastore)
|
|
|
|
# Return the new instance, which the framework will make the active module.
|
|
return new_instance
|
|
rescue StandardError => e
|
|
elog("Failed to reload payload #{fullname}: #{e.message}")
|
|
return mod
|
|
end
|
|
|
|
# Reloads modules from all module paths
|
|
#
|
|
# @return (see Msf::ModuleManager::Loading#load_modules)
|
|
def reload_modules
|
|
enablement_by_type.each_key do |type|
|
|
module_set_by_type[type].clear
|
|
init_module_set(type)
|
|
end
|
|
aliases.clear
|
|
inv_aliases.clear
|
|
|
|
# default the count to zero the first time a type is accessed
|
|
count_by_type = Hash.new(0)
|
|
|
|
framework.init_module_paths unless framework.module_paths_inited
|
|
|
|
module_paths.each do |path|
|
|
path_count_by_type = load_modules(path, force: true)
|
|
|
|
# merge count with count from other paths
|
|
path_count_by_type.each do |type, count|
|
|
count_by_type[type] += count
|
|
end
|
|
end
|
|
|
|
refresh_cache_from_module_files
|
|
|
|
count_by_type
|
|
end
|
|
end
|