Skip to content

Commit 9445bb3

Browse files
committed
Fixing payload reloading
1 parent 8bf1c40 commit 9445bb3

File tree

1 file changed

+58
-60
lines changed

1 file changed

+58
-60
lines changed
Lines changed: 58 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,119 +1,116 @@
11
# -*- coding: binary -*-
2-
32
# Concerns reloading modules
3+
require 'pry'
4+
require 'pry-byebug'
45
module Msf::ModuleManager::Reloading
56
# Reloads the module specified in mod. This can either be an instance of a module or a module class.
67
#
78
# @param [Msf::Module, Class] mod either an instance of a module or a module class
89
# @return (see Msf::Modules::Loader::Base#reload_module)
910
def reload_module(mod)
1011
# if it's an instance, then get its class
12+
binding.pry
1113
if mod.is_a? Msf::Module
1214
metasploit_class = mod.class
13-
original_instance = mod
1415
else
1516
metasploit_class = mod
16-
original_instance = nil
1717
end
1818

19-
# Handle aliases cleanup
20-
if (aliased_as = inv_aliases[metasploit_class.fullname])
19+
if aliased_as = self.inv_aliases[metasploit_class.fullname]
2120
aliased_as.each do |a|
22-
aliases.delete a
21+
self.aliases.delete a
2322
end
24-
inv_aliases.delete metasploit_class.fullname
23+
self.inv_aliases.delete metasploit_class.fullname
2524
end
2625

27-
# Special handling for payload modules
28-
if mod&.payload?
29-
return reload_payload_module(metasploit_class, original_instance)
26+
if mod.payload?
27+
return reload_payload_module(mod)
3028
end
31-
32-
# Standard module reloading for non-payloads
29+
3330
namespace_module = metasploit_class.module_parent
34-
31+
3532
# Check if the namespace module has a loader
3633
unless namespace_module.respond_to?(:loader)
37-
raise "Module #{metasploit_class.fullname} namespace does not have a loader"
34+
elog("Module does not have loader")
35+
return mod
3836
end
3937

4038
loader = namespace_module.loader
4139
loader.reload_module(mod)
4240
end
41+
# 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.
42+
# @param [Msf::Module, Class] mod either an instance of a module or a module class
43+
# @return (see Msf::Modules::Loader::Base#reload_module)
44+
def reload_payload_module(mod)
45+
if mod.is_a? Msf::Module
46+
metasploit_class = mod.class
47+
original_instance = mod
48+
else
49+
metasploit_class = mod
50+
original_instance = nil
51+
end
52+
binding.pry
4353

44-
private
45-
46-
# Reloads a payload module. This must be done by reloading the entire parent
47-
# directory to ensure the framework's complex payload "stitching" process
48-
# (combining stages, stagers, and mixins) is correctly executed. This is slower
49-
# but guarantees a fully-functional reloaded module.
50-
def reload_payload_module(metasploit_class, original_instance = nil)
51-
# Step 1: Get all necessary identifiers from the original module class.
52-
fullname = metasploit_class.fullname
53-
refname = metasploit_class.refname
54-
type = metasploit_class.type
55-
file_path = metasploit_class.file_path
56-
57-
# Get a reference to the original datastore now, but do not copy it yet.
58-
original_datastore = original_instance&.datastore
59-
60-
# Step 2: Manually purge the old module from the framework's caches.
61-
if (module_set = module_set_by_type.fetch(type, nil))
62-
module_set.delete(refname)
63-
end
64-
if (aliases_for_fullname = inv_aliases[fullname])
65-
aliases_for_fullname.each { |a| aliases.delete(a) }
66-
inv_aliases.delete(fullname)
54+
if (module_set = self.module_set_by_type.fetch(metasploit_class.type, nil))
55+
module_set.delete(metasploit_class.refname)
6756
end
6857

69-
# Step 3: Get the module's parent directory path.
70-
module_info = module_info_by_path[file_path]
58+
module_info = self.module_info_by_path[metasploit_class.file_path]
7159
unless module_info && (parent_path = module_info[:parent_path])
72-
raise Msf::LoadError, "Could not find cached module information for path: #{file_path}"
60+
elog("Failed to get parent_path from module object")
61+
return mod
62+
end
63+
64+
case original_instance&.payload_type
65+
when Msf::Payload::Type::Single
66+
prepend_path = 'singles'
67+
when Msf::Payload::Type::Stager
68+
prepend_path = 'stagers'
69+
when Msf::Payload::Type::Stage
70+
prepend_path = 'stages'
71+
when Msf::Payload::Type::Adapter
72+
prepend_path = 'adapters'
7373
end
7474

75-
# Step 4: Use the core framework loader to reload the entire parent directory.
76-
# This is the only way to reliably trigger the payload stitching logic.
77-
load_modules(parent_path, force: true)
75+
full_reference_name = File.join(prepend_path, module_info[:reference_name])
76+
self.loaders.each { |loader| loader.load_module(parent_path,module_info[:type], full_reference_name, {:force => true}) }
77+
7878

79-
# Step 5: Now that the framework has completed its full reload process,
80-
# use the public API to get a new instance of our reloaded module.
81-
new_instance = framework.modules.create(fullname)
79+
# Get reloaded module
80+
new_instance = framework.modules.create(metasploit_class.fullname)
8281

8382
if new_instance.blank?
84-
raise Msf::LoadError, "Failed to create a new instance of #{fullname} after reloading. The module file may be broken."
83+
elog("Failed create new instance")
84+
return mod
8585
end
8686

87-
# Step 6: Restore the datastore to the new, fully-functional instance.
88-
# Now we perform the copy, which is a method on the new datastore's merge function.
89-
if original_datastore
90-
new_instance.datastore.merge!(original_datastore)
91-
end
87+
# Restore the datastore
88+
new_instance.datastore.merge!(original_instance.datastore)
89+
9290

9391
# Return the new instance, which the framework will make the active module.
9492
return new_instance
9593
rescue StandardError => e
96-
elog("Failed to reload payload #{fullname}", error: e)
97-
raise Msf::LoadError, e.message
94+
elog("Failed to reload payload #{fullname}: #{e.message}")
95+
return mod
9896
end
9997

100-
public
101-
10298
# Reloads modules from all module paths
10399
#
104100
# @return (see Msf::ModuleManager::Loading#load_modules)
105101
def reload_modules
106-
enablement_by_type.each_key do |type|
102+
self.enablement_by_type.each_key do |type|
107103
module_set_by_type[type].clear
108104
init_module_set(type)
109105
end
110-
111-
aliases.clear
112-
inv_aliases.clear
106+
self.aliases.clear
107+
self.inv_aliases.clear
113108

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

112+
framework.init_module_paths unless framework.module_paths_inited
113+
117114
module_paths.each do |path|
118115
path_count_by_type = load_modules(path, force: true)
119116

@@ -124,6 +121,7 @@ def reload_modules
124121
end
125122

126123
refresh_cache_from_module_files
124+
127125
count_by_type
128126
end
129127
end

0 commit comments

Comments
 (0)