1
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:
Matt Miller 2005-10-10 00:30:14 +00:00
parent a2297845d3
commit 7cdf02d8da
6 changed files with 119 additions and 10 deletions

View File

@ -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

View File

@ -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
#

View File

@ -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

View File

@ -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

View File

@ -45,6 +45,10 @@ module ModuleCommandDispatcher
return driver.active_module
end
def mod=(m)
self.driver.active_module = m
end
end
end end end

View File

@ -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