Skip to content

Commit 3e5bdda

Browse files
authored
Land #20359, fixes payload reloading
Fix payload module reloading functionality
2 parents 74cce35 + b643c62 commit 3e5bdda

File tree

1 file changed

+85
-8
lines changed

1 file changed

+85
-8
lines changed

lib/msf/core/module_manager/reloading.rb

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,117 @@
11
# -*- coding: binary -*-
2-
# Concerns reloading modules
2+
3+
# Msf::ModuleManager::Reloading
4+
#
5+
# Provides methods for reloading Metasploit modules (including payloads,
6+
# stagers, adapters, stages, etc.), clearing out old aliases, and
7+
# refreshing the module cache.
38
module Msf::ModuleManager::Reloading
49
# Reloads the module specified in mod. This can either be an instance of a module or a module class.
510
#
611
# @param [Msf::Module, Class] mod either an instance of a module or a module class
712
# @return (see Msf::Modules::Loader::Base#reload_module)
813
def reload_module(mod)
9-
# if it's can instance, then get its class
14+
# if it's an instance, then get its class
1015
if mod.is_a? Msf::Module
1116
metasploit_class = mod.class
1217
else
1318
metasploit_class = mod
1419
end
1520

16-
if aliased_as = self.inv_aliases[metasploit_class.fullname]
21+
if (aliased_as = inv_aliases[metasploit_class.fullname])
22+
aliased_as.each do |a|
23+
aliases.delete a
24+
end
25+
inv_aliases.delete metasploit_class.fullname
26+
end
27+
28+
if mod.payload?
29+
return reload_payload_module(mod)
30+
end
31+
32+
if (aliased_as = inv_aliases[metasploit_class.fullname])
1733
aliased_as.each do |a|
18-
self.aliases.delete a
34+
aliases.delete a
1935
end
20-
self.inv_aliases.delete metasploit_class.fullname
36+
inv_aliases.delete metasploit_class.fullname
2137
end
2238

2339
namespace_module = metasploit_class.module_parent
40+
41+
# Check if the namespace module has a loader
42+
unless namespace_module.respond_to?(:loader)
43+
elog('Module does not have loader')
44+
return mod
45+
end
46+
2447
loader = namespace_module.loader
2548
loader.reload_module(mod)
2649
end
2750

51+
def manual_reload(parent_path, type, ref_name)
52+
loaders.each { |loader| loader.load_module(parent_path, type, ref_name, { force: true }) }
53+
end
54+
55+
# 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.
56+
# @param [Msf::Module, Class] mod either an instance of a module or a module class
57+
# @return (see Msf::Modules::Loader::Base#reload_module)
58+
def reload_payload_module(mod)
59+
if mod.is_a? Msf::Module
60+
metasploit_class = mod.class
61+
original_instance = mod
62+
else
63+
metasploit_class = mod
64+
original_instance = nil
65+
end
66+
if (module_set = module_set_by_type.fetch(metasploit_class.type, nil))
67+
module_set.delete(metasploit_class.refname)
68+
end
69+
module_info = module_info_by_path[metasploit_class.file_path]
70+
unless module_info && (parent_path = module_info[:parent_path])
71+
elog('Failed to get parent_path from module object')
72+
return mod
73+
end
74+
75+
# reload adapters if any
76+
manual_reload(parent_path, module_info[:type], File.join('adapters', mod.adapter_refname)) if mod.adapter_refname
77+
78+
# reload stagers if any
79+
manual_reload(parent_path, module_info[:type], File.join('stagers', mod.stager_refname)) if mod.stager_refname
80+
81+
# reload stages if any
82+
manual_reload(parent_path, module_info[:type], File.join('stages', mod.stage_refname)) if mod.stage_refname
83+
84+
# reload single if any
85+
manual_reload(parent_path, module_info[:type], File.join('singles', module_info[:reference_name])) if original_instance.payload_type == Msf::Payload::Type::Single
86+
87+
# Get reloaded module
88+
new_instance = framework.modules.create(metasploit_class.fullname)
89+
90+
if new_instance.blank?
91+
elog('Failed create new instance')
92+
return mod
93+
end
94+
95+
# Restore the datastore
96+
new_instance.datastore.merge!(original_instance.datastore)
97+
98+
# Return the new instance, which the framework will make the active module.
99+
return new_instance
100+
rescue StandardError => e
101+
elog("Failed to reload payload #{fullname}: #{e.message}")
102+
return mod
103+
end
104+
28105
# Reloads modules from all module paths
29106
#
30107
# @return (see Msf::ModuleManager::Loading#load_modules)
31108
def reload_modules
32-
self.enablement_by_type.each_key do |type|
109+
enablement_by_type.each_key do |type|
33110
module_set_by_type[type].clear
34111
init_module_set(type)
35112
end
36-
self.aliases.clear
37-
self.inv_aliases.clear
113+
aliases.clear
114+
inv_aliases.clear
38115

39116
# default the count to zero the first time a type is accessed
40117
count_by_type = Hash.new(0)

0 commit comments

Comments
 (0)