mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-11-05 14:57:30 +01:00
support for module reloading
git-svn-id: file:///home/svn/incoming/trunk@2956 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
parent
a2297845d3
commit
7cdf02d8da
@ -18,7 +18,7 @@ X - base64
|
||||
X - consider extending String
|
||||
- framework-core
|
||||
- modules
|
||||
- reloading
|
||||
X - reloading
|
||||
- compatibility filtering (keys)
|
||||
X - description sanitation (strip lines/etc)
|
||||
- payloads
|
||||
|
@ -58,6 +58,18 @@ class Module
|
||||
# or derived from the path that the module is loaded from.
|
||||
#
|
||||
attr_accessor :refname
|
||||
|
||||
#
|
||||
# This attribute holds the non-duplicated copy of the module
|
||||
# implementation. This attribute is used for reloading purposes so that
|
||||
# it can be re-duplicated.
|
||||
#
|
||||
attr_accessor :orig_cls
|
||||
|
||||
#
|
||||
# The path from which the module was loaded.
|
||||
#
|
||||
attr_accessor :file_path
|
||||
end
|
||||
|
||||
#
|
||||
@ -124,6 +136,20 @@ class Module
|
||||
return self.class.refname
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the unduplicated class associated with this module.
|
||||
#
|
||||
def orig_cls
|
||||
return self.class.orig_cls
|
||||
end
|
||||
|
||||
#
|
||||
# The path to the file in which the module can be loaded from.
|
||||
#
|
||||
def file_path
|
||||
self.class.file_path
|
||||
end
|
||||
|
||||
#
|
||||
# Return the module's name
|
||||
#
|
||||
|
@ -152,7 +152,7 @@ protected
|
||||
#
|
||||
# Adds a module with a the supplied name
|
||||
#
|
||||
def add_module(module_class, name)
|
||||
def add_module(module_class, name, file_path = nil)
|
||||
# Duplicate the module class so that we can operate on a
|
||||
# framework-specific copy of it.
|
||||
dup = module_class.dup
|
||||
@ -161,6 +161,8 @@ protected
|
||||
# instances are created.
|
||||
dup.framework = framework
|
||||
dup.refname = name
|
||||
dup.file_path = file_path
|
||||
dup.orig_cls = module_class
|
||||
|
||||
if (self[name])
|
||||
mod_ambiguous[name] = true
|
||||
@ -325,6 +327,46 @@ class ModuleManager < ModuleSet
|
||||
def register_type_extension(type, ext)
|
||||
end
|
||||
|
||||
#
|
||||
# Reloads the module specified in mod. This can either be an instance of a
|
||||
# module or a module class.
|
||||
#
|
||||
def reload_module(mod)
|
||||
refname = mod.refname
|
||||
ds = mod.datastore.dup
|
||||
|
||||
dlog("Reloading module #{refname}...", 'core')
|
||||
|
||||
if (mod.file_path)
|
||||
begin
|
||||
if (!load(mod.file_path))
|
||||
elog("Failed to load module from #{mod.file_path}")
|
||||
return nil
|
||||
end
|
||||
|
||||
rescue
|
||||
elog("Failed to reload module #{mod} from #{mod.file_path}: #{$!}")
|
||||
raise $!
|
||||
end
|
||||
end
|
||||
|
||||
# Remove the original reference to this module
|
||||
self.delete(mod.refname)
|
||||
|
||||
# Indicate that the module is being loaded again so that any necessary
|
||||
# steps can be taken to extend it properly.
|
||||
on_module_load(mod.orig_cls, mod.type, refname, mod.file_path)
|
||||
|
||||
# Create a new instance of the module
|
||||
if (mod = create(refname))
|
||||
mod.datastore.update(ds)
|
||||
else
|
||||
elog("Failed to create instance of #{refname} after reload.", 'core')
|
||||
end
|
||||
|
||||
mod
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
#
|
||||
@ -476,7 +518,7 @@ protected
|
||||
|
||||
# Do some processing on the loaded module to get it into the
|
||||
# right associations
|
||||
on_module_load(added, type, name)
|
||||
on_module_load(added, type, name, file)
|
||||
|
||||
# Set this module type as needing recalculation
|
||||
recalc[type] = true
|
||||
@ -522,7 +564,7 @@ protected
|
||||
# Called when a module is initially loaded such that it can be
|
||||
# categorized accordingly
|
||||
#
|
||||
def on_module_load(mod, type, name)
|
||||
def on_module_load(mod, type, name, file_path)
|
||||
# Payload modules require custom loading as the individual files
|
||||
# may not directly contain a logical payload that a user would
|
||||
# reference, such as would be the case with a payload stager or
|
||||
@ -533,10 +575,10 @@ protected
|
||||
if (type != MODULE_PAYLOAD)
|
||||
# Add the module class to the list of modules and add it to the
|
||||
# type separated set of module classes
|
||||
add_module(mod, name)
|
||||
add_module(mod, name, file_path)
|
||||
end
|
||||
|
||||
module_sets[type].add_module(mod, name)
|
||||
module_sets[type].add_module(mod, name, file_path)
|
||||
end
|
||||
|
||||
attr_accessor :modules, :module_sets
|
||||
|
@ -167,7 +167,7 @@ class PayloadSet < ModuleSet
|
||||
# out if it's a single, stager, or stage. Depending on which it is, we
|
||||
# add it to the appropriate list
|
||||
#
|
||||
def add_module(pmodule, name)
|
||||
def add_module(pmodule, name, file_path = nil)
|
||||
if (md = name.match(/^(singles|stagers|stages)#{File::SEPARATOR}(.*)$/))
|
||||
name = md[2]
|
||||
end
|
||||
@ -185,7 +185,8 @@ class PayloadSet < ModuleSet
|
||||
instance.handler,
|
||||
instance.platform,
|
||||
instance.arch,
|
||||
instance.convention
|
||||
instance.convention,
|
||||
file_path
|
||||
]
|
||||
|
||||
# Use the module's preferred alias if it has one
|
||||
|
@ -45,6 +45,10 @@ module ModuleCommandDispatcher
|
||||
return driver.active_module
|
||||
end
|
||||
|
||||
def mod=(m)
|
||||
self.driver.active_module = m
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end end end
|
||||
|
@ -19,8 +19,10 @@ class Exploit
|
||||
|
||||
def commands
|
||||
{
|
||||
"check" => "Check to see if a target is vulnerable",
|
||||
"exploit" => "Launch an exploit attempt",
|
||||
"check" => "Check to see if a target is vulnerable",
|
||||
"exploit" => "Launch an exploit attempt",
|
||||
"rcheck" => "Reloads the module and checks if the target is vulnerable",
|
||||
"rexploit" => "Reloads the module and launches an exploit attempt",
|
||||
}
|
||||
end
|
||||
|
||||
@ -33,6 +35,10 @@ class Exploit
|
||||
#
|
||||
def cmd_check(*args)
|
||||
begin
|
||||
mod.init_ui(
|
||||
driver.input,
|
||||
driver.output)
|
||||
|
||||
code = mod.check
|
||||
|
||||
if (code)
|
||||
@ -49,6 +55,8 @@ class Exploit
|
||||
end
|
||||
rescue
|
||||
log_error("Check failed: #{$!}.")
|
||||
ensure
|
||||
mod.reset_ui
|
||||
end
|
||||
end
|
||||
|
||||
@ -64,6 +72,8 @@ class Exploit
|
||||
bg = false
|
||||
jobify = false
|
||||
|
||||
puts "using mod #{mod}"
|
||||
|
||||
# Always run passive exploits in the background
|
||||
if (mod.passive?)
|
||||
jobify = true
|
||||
@ -134,6 +144,32 @@ class Exploit
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Reloads an exploit module and checks the target to see if it's vulnerable
|
||||
#
|
||||
def cmd_rcheck(*args)
|
||||
begin
|
||||
self.mod = framework.modules.reload_module(mod)
|
||||
|
||||
cmd_check(*args)
|
||||
rescue
|
||||
log_error("Failed to rcheck: #{$!}")
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Reloads an exploit module and launches an exploit
|
||||
#
|
||||
def cmd_rexploit(*args)
|
||||
begin
|
||||
self.mod = framework.modules.reload_module(mod)
|
||||
|
||||
cmd_exploit(*args)
|
||||
rescue
|
||||
log_error("Failed to rexploit: #{$!}")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end end end end
|
||||
|
Loading…
Reference in New Issue
Block a user