11# -*- coding: binary -*-
2-
32# Concerns reloading modules
3+
44module Msf ::ModuleManager ::Reloading
55 # Reloads the module specified in mod. This can either be an instance of a module or a module class.
66 #
@@ -10,110 +10,103 @@ def reload_module(mod)
1010 # if it's an instance, then get its class
1111 if mod . is_a? Msf ::Module
1212 metasploit_class = mod . class
13- original_instance = mod
1413 else
1514 metasploit_class = mod
16- original_instance = nil
1715 end
1816
19- # Handle aliases cleanup
20- if ( aliased_as = inv_aliases [ metasploit_class . fullname ] )
17+ if aliased_as = self . inv_aliases [ metasploit_class . fullname ]
2118 aliased_as . each do |a |
22- aliases . delete a
19+ self . aliases . delete a
2320 end
24- inv_aliases . delete metasploit_class . fullname
21+ self . inv_aliases . delete metasploit_class . fullname
2522 end
2623
27- # Special handling for payload modules
28- if mod &.payload?
29- return reload_payload_module ( metasploit_class , original_instance )
24+ if mod . payload?
25+ return reload_payload_module ( mod )
3026 end
31-
32- # Standard module reloading for non-payloads
27+
3328 namespace_module = metasploit_class . module_parent
34-
29+
3530 # Check if the namespace module has a loader
3631 unless namespace_module . respond_to? ( :loader )
37- raise "Module #{ metasploit_class . fullname } namespace does not have a loader"
32+ elog ( "Module does not have loader" )
33+ return mod
3834 end
3935
4036 loader = namespace_module . loader
4137 loader . reload_module ( mod )
4238 end
43-
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 )
39+ # 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.
40+ # @param [Msf::Module, Class] mod either an instance of a module or a module class
41+ # @return (see Msf::Modules::Loader::Base#reload_module)
42+ def reload_payload_module ( mod )
43+ if mod . is_a? Msf ::Module
44+ metasploit_class = mod . class
45+ original_instance = mod
46+ else
47+ metasploit_class = mod
48+ original_instance = nil
49+ end
50+ if ( module_set = self . module_set_by_type . fetch ( metasploit_class . type , nil ) )
51+ module_set . delete ( metasploit_class . refname )
6752 end
6853
69- # Step 3: Get the module's parent directory path.
70- module_info = module_info_by_path [ file_path ]
54+ module_info = self . module_info_by_path [ metasploit_class . file_path ]
7155 unless module_info && ( parent_path = module_info [ :parent_path ] )
72- raise Msf ::LoadError , "Could not find cached module information for path: #{ file_path } "
56+ elog ( "Failed to get parent_path from module object" )
57+ return mod
7358 end
7459
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 )
60+ case original_instance &.payload_type
61+ when Msf ::Payload ::Type ::Single
62+ prepend_path = 'singles'
63+ when Msf ::Payload ::Type ::Stager
64+ prepend_path = 'stagers'
65+ when Msf ::Payload ::Type ::Stage
66+ prepend_path = 'stages'
67+ when Msf ::Payload ::Type ::Adapter
68+ prepend_path = 'adapters'
69+ end
70+
71+ full_reference_name = File . join ( prepend_path , module_info [ :reference_name ] )
72+ self . loaders . each { |loader | loader . load_module ( parent_path , module_info [ :type ] , full_reference_name , { :force => true } ) }
73+
7874
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 )
75+ # Get reloaded module
76+ new_instance = framework . modules . create ( metasploit_class . fullname )
8277
8378 if new_instance . blank?
84- raise Msf ::LoadError , "Failed to create a new instance of #{ fullname } after reloading. The module file may be broken."
79+ elog ( "Failed create new instance" )
80+ return mod
8581 end
8682
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
83+ # Restore the datastore
84+ new_instance . datastore . merge! ( original_instance . datastore )
85+
9286
9387 # Return the new instance, which the framework will make the active module.
9488 return new_instance
9589 rescue StandardError => e
96- elog ( "Failed to reload payload #{ fullname } " , error : e )
97- raise Msf :: LoadError , e . message
90+ elog ( "Failed to reload payload #{ fullname } : #{ e . message } " )
91+ return mod
9892 end
9993
100- public
101-
10294 # Reloads modules from all module paths
10395 #
10496 # @return (see Msf::ModuleManager::Loading#load_modules)
10597 def reload_modules
106- enablement_by_type . each_key do |type |
98+ self . enablement_by_type . each_key do |type |
10799 module_set_by_type [ type ] . clear
108100 init_module_set ( type )
109101 end
110-
111- aliases . clear
112- inv_aliases . clear
102+ self . aliases . clear
103+ self . inv_aliases . clear
113104
114105 # default the count to zero the first time a type is accessed
115106 count_by_type = Hash . new ( 0 )
116107
108+ framework . init_module_paths unless framework . module_paths_inited
109+
117110 module_paths . each do |path |
118111 path_count_by_type = load_modules ( path , force : true )
119112
@@ -124,6 +117,7 @@ def reload_modules
124117 end
125118
126119 refresh_cache_from_module_files
120+
127121 count_by_type
128122 end
129123end
0 commit comments