metasploit-framework/lib/msf/base/simple/post.rb

158 lines
3.8 KiB
Ruby

# -*- coding: binary -*-
module Msf
module Simple
###
#
# A simplified post-exploitation module wrapper.
#
###
module Post
include Module
#
# Wraps the post-exploitation module running process in a simple single
# method. The options hash can have the following values passed in it:
#
# OptionStr
#
# A string of comma separated option values that should be imported into
# the datastore.
#
# Options
#
# A hash of values to be imported directly into the datastore.
#
# LocalInput
#
# The local input handle that data can be read in from.
#
# LocalOutput
#
# The local output through which data can be displayed.
#
# RunAsJob
#
# Whether or not the module should be run in the context of a background
# job.
#
def self.run_simple(omod, opts = {}, &block)
# Clone the module to prevent changes to the original instance
mod = omod.replicant
Msf::Simple::Framework.simplify_module( mod, false )
yield(mod) if block_given?
# Import options from the OptionStr or Option hash.
mod._import_extra_options(opts)
# Verify the options
mod.options.validate(mod.datastore)
# Initialize user interaction
if ! opts['Quiet']
mod.init_ui(opts['LocalInput'] || mod.user_input, opts['LocalOutput'] || mod.user_output)
else
mod.init_ui(nil, nil)
end
#
# Disable this until we can test background stuff a little better
#
if(mod.passive? or opts['RunAsJob'])
ctx = [ mod.replicant ]
mod.job_id = mod.framework.jobs.start_bg_job(
"Post: #{mod.refname}",
ctx,
Proc.new { |ctx_| self.job_run_proc(ctx_) },
Proc.new { |ctx_| self.job_cleanup_proc(ctx_) }
)
# Propagate this back to the caller for console mgmt
omod.job_id = mod.job_id
else
ctx = [ mod ]
self.job_run_proc(ctx)
self.job_cleanup_proc(ctx)
end
end
#
# Calls the class method.
#
def run_simple(opts = {}, &block)
Msf::Simple::Post.run_simple(self, opts, &block)
end
protected
#
# Job run proc, sets up the module and kicks it off.
#
# XXX: Mostly Copy/pasted from simple/auxiliary.rb
#
def self.job_run_proc(ctx)
mod = ctx[0]
begin
mod.setup
mod.framework.events.on_module_run(mod)
# Grab the session object since we need to fire an event for not
# only the normal module_run event that all module types have to
# report, but a specific event for sessions as well.
s = mod.framework.sessions.get(mod.datastore["SESSION"])
if s
mod.framework.events.on_session_module_run(s, mod)
mod.run
else
mod.print_error("Session not found")
mod.cleanup
return
end
rescue ::Timeout::Error => e
mod.error = e
mod.print_error("Post triggered a timeout exception")
mod.cleanup
return
rescue ::Interrupt => e
mod.error = e
mod.print_error("Post interrupted by the console user")
mod.cleanup
return
rescue ::Exception => e
mod.error = e
mod.print_error("Post failed: #{e.class} #{e}")
if(e.class.to_s != 'Msf::OptionValidateError')
mod.print_error("Call stack:")
e.backtrace.each do |line|
break if line =~ /lib.msf.base.simple.post.rb/
mod.print_error(" #{line}")
end
end
elog("Post failed: #{e.class} #{e}", 'core', LEV_0)
dlog("Call stack:\n#{$@.join("\n")}", 'core', LEV_3)
mod.cleanup
return
end
end
#
# Clean up the module after the job completes.
#
# Copy/pasted from simple/auxiliary.rb
#
def self.job_cleanup_proc(ctx)
mod = ctx[0]
mod.framework.events.on_module_complete(mod)
# Allow the exploit to cleanup after itself, that messy bugger.
mod.cleanup
end
end
end
end