1
1
# -*- coding: binary -*-
2
-
3
2
# Concerns reloading modules
3
+
4
4
module Msf ::ModuleManager ::Reloading
5
5
# Reloads the module specified in mod. This can either be an instance of a module or a module class.
6
6
#
@@ -10,110 +10,103 @@ def reload_module(mod)
10
10
# if it's an instance, then get its class
11
11
if mod . is_a? Msf ::Module
12
12
metasploit_class = mod . class
13
- original_instance = mod
14
13
else
15
14
metasploit_class = mod
16
- original_instance = nil
17
15
end
18
16
19
- # Handle aliases cleanup
20
- if ( aliased_as = inv_aliases [ metasploit_class . fullname ] )
17
+ if aliased_as = self . inv_aliases [ metasploit_class . fullname ]
21
18
aliased_as . each do |a |
22
- aliases . delete a
19
+ self . aliases . delete a
23
20
end
24
- inv_aliases . delete metasploit_class . fullname
21
+ self . inv_aliases . delete metasploit_class . fullname
25
22
end
26
23
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 )
30
26
end
31
-
32
- # Standard module reloading for non-payloads
27
+
33
28
namespace_module = metasploit_class . module_parent
34
-
29
+
35
30
# Check if the namespace module has a loader
36
31
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
38
34
end
39
35
40
36
loader = namespace_module . loader
41
37
loader . reload_module ( mod )
42
38
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 )
67
52
end
68
53
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 ]
71
55
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
73
58
end
74
59
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
+
78
74
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 )
82
77
83
78
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
85
81
end
86
82
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
+
92
86
93
87
# Return the new instance, which the framework will make the active module.
94
88
return new_instance
95
89
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
98
92
end
99
93
100
- public
101
-
102
94
# Reloads modules from all module paths
103
95
#
104
96
# @return (see Msf::ModuleManager::Loading#load_modules)
105
97
def reload_modules
106
- enablement_by_type . each_key do |type |
98
+ self . enablement_by_type . each_key do |type |
107
99
module_set_by_type [ type ] . clear
108
100
init_module_set ( type )
109
101
end
110
-
111
- aliases . clear
112
- inv_aliases . clear
102
+ self . aliases . clear
103
+ self . inv_aliases . clear
113
104
114
105
# default the count to zero the first time a type is accessed
115
106
count_by_type = Hash . new ( 0 )
116
107
108
+ framework . init_module_paths unless framework . module_paths_inited
109
+
117
110
module_paths . each do |path |
118
111
path_count_by_type = load_modules ( path , force : true )
119
112
@@ -124,6 +117,7 @@ def reload_modules
124
117
end
125
118
126
119
refresh_cache_from_module_files
120
+
127
121
count_by_type
128
122
end
129
123
end
0 commit comments