3
3
#
4
4
require 'msf/core/modules/loader'
5
5
require 'msf/core/modules/namespace'
6
+ require 'msf/core/modules/version_compatibility_error'
6
7
7
8
# Responsible for loading modules for {Msf::ModuleManager}.
8
9
#
@@ -77,7 +78,6 @@ def loadable?(path)
77
78
raise ::NotImplementedError
78
79
end
79
80
80
-
81
81
# Loads a module from the supplied path and module_reference_name.
82
82
#
83
83
# @param [String] parent_path The path under which the module exists. This is not necessarily the same path as passed
@@ -104,14 +104,18 @@ def load_module(parent_path, type, module_reference_name, options={})
104
104
force = options [ :force ] || false
105
105
reload = options [ :reload ] || false
106
106
107
- unless force or module_manager . file_changed? ( parent_path )
108
- dlog ( "Cached module from #{ parent_path } has not changed." , 'core' , LEV_2 )
107
+ module_path = self . module_path ( parent_path , type , module_reference_name )
108
+ file_changed = module_manager . file_changed? ( module_path )
109
+
110
+ unless force or file_changed
111
+ dlog ( "Cached module from #{ module_path } has not changed." , 'core' , LEV_2 )
109
112
110
113
return false
111
114
end
112
115
116
+ reload ||= force || file_changed
117
+
113
118
metasploit_class = nil
114
- module_path = self . module_path ( parent_path , type , module_reference_name )
115
119
116
120
loaded = namespace_module_transaction ( type + "/" + module_reference_name , :reload => reload ) { |namespace_module |
117
121
# set the parent_path so that the module can be reloaded with #load_module
@@ -121,7 +125,7 @@ def load_module(parent_path, type, module_reference_name, options={})
121
125
122
126
begin
123
127
namespace_module . module_eval_with_lexical_scope ( module_content , module_path )
124
- # handle interrupts as pass-throughs unlike other Exceptions
128
+ # handle interrupts as pass-throughs unlike other Exceptions so users can bail with Ctrl+C
125
129
rescue ::Interrupt
126
130
raise
127
131
rescue ::Exception => error
@@ -191,6 +195,11 @@ def load_module(parent_path, type, module_reference_name, options={})
191
195
# not trigger an ambiguous name warning, which would cause the reloaded module to not be stored in the
192
196
# ModuleManager.
193
197
module_manager . delete ( module_reference_name )
198
+
199
+ # Delete the original copy of the module in the type-specific module set stores the reloaded module and doesn't
200
+ # trigger an ambiguous name warning
201
+ module_set = module_manager . module_set ( type )
202
+ module_set . delete ( module_reference_name )
194
203
end
195
204
196
205
# Do some processing on the loaded module to get it into the right associations
@@ -290,7 +299,6 @@ def reload_module(original_metasploit_class_or_instance)
290
299
291
300
dlog ( "Reloading module #{ module_reference_name } ..." , 'core' )
292
301
293
-
294
302
if load_module ( parent_path , type , module_reference_name , :force => true , :reload => true )
295
303
# Create a new instance of the module
296
304
reloaded_module_instance = module_manager . create ( module_reference_name )
@@ -486,20 +494,18 @@ def namespace_module_transaction(uniq_module_reference_name, options={}, &block)
486
494
elog ( "Reloading namespace_module #{ previous_namespace_module } when :reload => false" )
487
495
end
488
496
497
+ relative_name = namespace_module_names . last
498
+
489
499
if previous_namespace_module
490
500
parent_module = previous_namespace_module . parent
491
- relative_name = namespace_module_names . last
492
-
493
- # remove_const is private, so invoke in instance context
494
- parent_module . instance_eval do
495
- remove_const relative_name
496
- end
497
- else
498
- parent_module = nil
499
- relative_name = namespace_module_names . last
501
+ # remove_const is private, so use send to bypass
502
+ parent_module . send ( :remove_const , relative_name )
500
503
end
501
504
502
505
namespace_module = create_namespace_module ( namespace_module_names )
506
+ # Get the parent module from the created module so that restore_namespace_module can remove namespace_module's
507
+ # constant if needed.
508
+ parent_module = namespace_module . parent
503
509
504
510
begin
505
511
loaded = block . call ( namespace_module )
@@ -534,19 +540,29 @@ def read_module_content(parent_path, type, module_reference_name)
534
540
#
535
541
# @param [Module] parent_module The .parent of namespace_module before it was removed from the constant tree.
536
542
# @param [String] relative_name The name of the constant under parent_module where namespace_module was attached.
537
- # @param [Module] namespace_module The previous namespace module containing the old module content.
543
+ # @param [Module, nil] namespace_module The previous namespace module containing the old module content. If `nil`,
544
+ # then the relative_name constant is removed from parent_module, but nothing is set as the new constant.
538
545
# @return [void]
539
546
def restore_namespace_module ( parent_module , relative_name , namespace_module )
540
- if parent_module and namespace_module
541
- # the const may have been redefined by {#create_namespace_module}, in which case that new namespace_module needs
542
- # to be removed so the original can replace it.
543
- if parent_module . const_defined? relative_name
544
- parent_module . instance_eval do
545
- remove_const relative_name
546
- end
547
+ if parent_module
548
+ # If there is a current module with relative_name
549
+ if parent_module . const_defined? ( relative_name )
550
+ # if the current value isn't the value to be restored.
551
+ if parent_module . const_get ( relative_name ) != namespace_module
552
+ # remove_const is private, so use send to bypass
553
+ parent_module . send ( :remove_const , relative_name )
554
+
555
+ # if there was a previous module, not set it to the name
556
+ if namespace_module
557
+ parent_module . const_set ( relative_name , namespace_module )
558
+ end
559
+ end
560
+ else
561
+ # if there was a previous module, but there isn't a current module, then restore the previous module
562
+ if namespace_module
563
+ parent_module . const_set ( relative_name , namespace_module )
564
+ end
547
565
end
548
-
549
- parent_module . const_set ( relative_name , namespace_module )
550
566
end
551
567
end
552
568
0 commit comments