158 lines
3.8 KiB
Ruby
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
|
|
|