session logging support
git-svn-id: file:///home/svn/incoming/trunk@2938 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
parent
fd38a7e39f
commit
db40a55547
|
@ -26,8 +26,8 @@ X - meta information
|
||||||
X - stager/stage calling conventions
|
X - stager/stage calling conventions
|
||||||
X - stack requirements
|
X - stack requirements
|
||||||
X - make payload prepend target specific
|
X - make payload prepend target specific
|
||||||
- sessions
|
X - sessions
|
||||||
- logging session activity
|
X - logging session activity
|
||||||
- handler sharing
|
- handler sharing
|
||||||
- exploits using the same payload/handler can share (ref count)
|
- exploits using the same payload/handler can share (ref count)
|
||||||
- modules needing ports (above other modules)
|
- modules needing ports (above other modules)
|
||||||
|
|
|
@ -27,12 +27,61 @@ class Logging
|
||||||
[
|
[
|
||||||
'rex',
|
'rex',
|
||||||
'core',
|
'core',
|
||||||
|
'base',
|
||||||
].each { |src|
|
].each { |src|
|
||||||
register_log_source(src, f)
|
register_log_source(src, f)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Enables a log source.
|
||||||
|
#
|
||||||
|
def self.enable_log_source(src)
|
||||||
|
f = Rex::Logging::Sinks::Flatfile.new(
|
||||||
|
Msf::Config.log_directory + File::SEPARATOR + "#{src}.log")
|
||||||
|
|
||||||
|
register_log_source(src, f)
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Stops logging for a given log source.
|
||||||
|
#
|
||||||
|
def self.disable_log_source(src)
|
||||||
|
deregister_log_source(src)
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Sets whether or not session logging is to be enabled.
|
||||||
|
#
|
||||||
|
def self.enable_session_logging(tf)
|
||||||
|
@session_logging = tf
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Returns whether or not session logging is enabled.
|
||||||
|
#
|
||||||
|
def self.session_logging_enabled?
|
||||||
|
@session_logging || false
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Starts logging for a given session.
|
||||||
|
#
|
||||||
|
def self.start_session_log(session)
|
||||||
|
f = Rex::Logging::Sinks::Flatfile.new(
|
||||||
|
Msf::Config.session_log_directory + File::SEPARATOR + "#{session.log_file_name}.log")
|
||||||
|
|
||||||
|
register_log_source(session.log_source, f)
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Stops logging for a given session.
|
||||||
|
#
|
||||||
|
def self.stop_session_log(session)
|
||||||
|
deregister_log_source(session.log_source)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -66,12 +66,14 @@ class Meterpreter < Rex::Post::Meterpreter::Client
|
||||||
#
|
#
|
||||||
def init_ui(input, output)
|
def init_ui(input, output)
|
||||||
console.init_ui(input, output)
|
console.init_ui(input, output)
|
||||||
|
console.set_log_source(log_source)
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Resets the console's I/O handles
|
# Resets the console's I/O handles
|
||||||
#
|
#
|
||||||
def reset_ui
|
def reset_ui
|
||||||
|
console.unset_log_source
|
||||||
console.reset_ui
|
console.reset_ui
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,38 @@ module Session
|
||||||
"#{(tunnel_local || '??').to_s} -> #{(tunnel_peer || '??').to_s}"
|
"#{(tunnel_local || '??').to_s} -> #{(tunnel_peer || '??').to_s}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
#
|
||||||
|
# Logging
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
#
|
||||||
|
# Returns the suggested name of the log file for this session.
|
||||||
|
#
|
||||||
|
def log_file_name
|
||||||
|
dt = Time.now
|
||||||
|
|
||||||
|
dstr = sprintf("%.4d%.2d%.2d", dt.year, dt.mon, dt.mday)
|
||||||
|
|
||||||
|
("#{dstr}_" + tunnel_to_s + "_#{name.to_s}_#{(type || 'unknown').downcase}").gsub(/\s/, '_').gsub(/->/, 'to')
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Returns the log source that should be used for this session.
|
||||||
|
#
|
||||||
|
def log_source
|
||||||
|
"session_#{name.to_s}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def log_from_remote(buf)
|
||||||
|
rlog(buf, log_source)
|
||||||
|
end
|
||||||
|
|
||||||
|
def log_from_local(buf)
|
||||||
|
rlog(buf, log_source)
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
# Core interface
|
# Core interface
|
||||||
|
|
|
@ -354,7 +354,7 @@ class Core
|
||||||
value = args[1]
|
value = args[1]
|
||||||
|
|
||||||
# If the driver indicates that the value is not valid, bust out.
|
# If the driver indicates that the value is not valid, bust out.
|
||||||
if (driver.on_variable_set(name, value) == false)
|
if (driver.on_variable_set(global, name, value) == false)
|
||||||
print_error("The value specified for #{name} is not valid.")
|
print_error("The value specified for #{name} is not valid.")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
@ -446,7 +446,7 @@ class Core
|
||||||
end
|
end
|
||||||
|
|
||||||
while ((val = args.shift))
|
while ((val = args.shift))
|
||||||
if (driver.on_variable_unset(val) == false)
|
if (driver.on_variable_unset(global, val) == false)
|
||||||
print_error("The variable #{val} cannot be unset at this time.")
|
print_error("The variable #{val} cannot be unset at this time.")
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,6 +21,7 @@ module Console
|
||||||
###
|
###
|
||||||
class Driver < Msf::Ui::Driver
|
class Driver < Msf::Ui::Driver
|
||||||
|
|
||||||
|
ConfigCore = "framework/core"
|
||||||
ConfigGroup = "framework/ui/console"
|
ConfigGroup = "framework/ui/console"
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -47,11 +48,17 @@ class Driver < Msf::Ui::Driver
|
||||||
# Register event handlers
|
# Register event handlers
|
||||||
register_event_handlers
|
register_event_handlers
|
||||||
|
|
||||||
# Process things before we actually display the prompt and get rocking
|
# Temporarily disable output
|
||||||
on_startup
|
self.disable_output = true
|
||||||
|
|
||||||
# Load console-specific configuration
|
# Load console-specific configuration
|
||||||
load_config
|
load_config
|
||||||
|
|
||||||
|
# Re-enable output
|
||||||
|
self.disable_output = false
|
||||||
|
|
||||||
|
# Process things before we actually display the prompt and get rocking
|
||||||
|
on_startup
|
||||||
|
|
||||||
# Process the resource script
|
# Process the resource script
|
||||||
process_rc_file
|
process_rc_file
|
||||||
|
@ -71,12 +78,21 @@ class Driver < Msf::Ui::Driver
|
||||||
# If we have configuration, process it
|
# If we have configuration, process it
|
||||||
if (conf.group?(ConfigGroup))
|
if (conf.group?(ConfigGroup))
|
||||||
conf[ConfigGroup].each_pair { |k, v|
|
conf[ConfigGroup].each_pair { |k, v|
|
||||||
case k
|
case k.downcase
|
||||||
when "ActiveModule"
|
when "activemodule"
|
||||||
run_single("use #{v}")
|
run_single("use #{v}")
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if (conf.group?(ConfigCore))
|
||||||
|
conf[ConfigCore].each_pair { |k, v|
|
||||||
|
case k.downcase
|
||||||
|
when "sessionlogging"
|
||||||
|
handle_session_logging(v)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -125,12 +141,14 @@ class Driver < Msf::Ui::Driver
|
||||||
# some other kind of task. If this routine returns false it will indicate
|
# some other kind of task. If this routine returns false it will indicate
|
||||||
# that the variable is not being set to a valid value.
|
# that the variable is not being set to a valid value.
|
||||||
#
|
#
|
||||||
def on_variable_set(var, val)
|
def on_variable_set(glob, var, val)
|
||||||
case var.downcase
|
case var.downcase
|
||||||
when "payload"
|
when "payload"
|
||||||
if (framework.modules.valid?(val) == false)
|
if (framework.modules.valid?(val) == false)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
when "sessionlogging"
|
||||||
|
handle_session_logging(val) if (glob)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -138,7 +156,11 @@ class Driver < Msf::Ui::Driver
|
||||||
# Called when a variable is unset. If this routine returns false it is an
|
# Called when a variable is unset. If this routine returns false it is an
|
||||||
# indication that the variable should not be allowed to be unset.
|
# indication that the variable should not be allowed to be unset.
|
||||||
#
|
#
|
||||||
def on_variable_unset(var)
|
def on_variable_unset(glob, var)
|
||||||
|
case var.downcase
|
||||||
|
when "sessionlogging"
|
||||||
|
handle_session_logging('0') if (glob)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :framework
|
attr_reader :framework
|
||||||
|
@ -147,7 +169,25 @@ class Driver < Msf::Ui::Driver
|
||||||
protected
|
protected
|
||||||
|
|
||||||
attr_writer :framework
|
attr_writer :framework
|
||||||
|
|
||||||
|
##
|
||||||
|
#
|
||||||
|
# Handlers for various global configuration values
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
#
|
||||||
|
# SessionLogging
|
||||||
|
#
|
||||||
|
def handle_session_logging(val)
|
||||||
|
if (val =~ /^(yes|y|true|t|1)/i)
|
||||||
|
Msf::Logging.enable_session_logging(true)
|
||||||
|
print_line("Session logging will be enabled for future sessions.")
|
||||||
|
else
|
||||||
|
Msf::Logging.enable_session_logging(false)
|
||||||
|
print_line("Session logging will be disabled for future sessions.")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -33,6 +33,12 @@ module FrameworkEventManager
|
||||||
#
|
#
|
||||||
def on_session_open(session)
|
def on_session_open(session)
|
||||||
output.print_status("#{session.desc} session #{session.name} opened (#{session.tunnel_to_s})")
|
output.print_status("#{session.desc} session #{session.name} opened (#{session.tunnel_to_s})")
|
||||||
|
|
||||||
|
if (Msf::Logging.session_logging_enabled? == true)
|
||||||
|
Msf::Logging.start_session_log(session)
|
||||||
|
|
||||||
|
output.print_status("Started logging session interaction.")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -43,6 +49,9 @@ module FrameworkEventManager
|
||||||
output.print_line
|
output.print_line
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# If logging had been enabled for this session, stop it now.
|
||||||
|
Msf::Logging::stop_session_log(session)
|
||||||
|
|
||||||
output.print_status("#{session.desc} session #{session.name} closed.")
|
output.print_status("#{session.desc} session #{session.name} closed.")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ def register_log_source(src, sink)
|
||||||
$dispatcher[src] = sink
|
$dispatcher[src] = sink
|
||||||
end
|
end
|
||||||
|
|
||||||
def deregister_log_source(src, sink)
|
def deregister_log_source(src)
|
||||||
$dispatcher.delete(src)
|
$dispatcher.delete(src)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@ class Output::Buffer < Rex::Ui::Text::Output
|
||||||
|
|
||||||
def print(msg = '')
|
def print(msg = '')
|
||||||
self.buf += msg || ''
|
self.buf += msg || ''
|
||||||
|
|
||||||
|
msg
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset
|
def reset
|
||||||
|
|
|
@ -17,6 +17,8 @@ class Output::Stdio < Rex::Ui::Text::Output
|
||||||
def print(msg = '')
|
def print(msg = '')
|
||||||
$stdout.print(msg)
|
$stdout.print(msg)
|
||||||
$stdout.flush
|
$stdout.flush
|
||||||
|
|
||||||
|
msg
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ module Shell
|
||||||
attr_accessor :prompt, :output
|
attr_accessor :prompt, :output
|
||||||
|
|
||||||
def pgets
|
def pgets
|
||||||
output.print(prompt)
|
_print_prompt(prompt)
|
||||||
gets
|
gets
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -79,6 +79,20 @@ module Shell
|
||||||
init_ui
|
init_ui
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Sets the log source that should be used for logging input and output.
|
||||||
|
#
|
||||||
|
def set_log_source(log_source)
|
||||||
|
self.log_source = log_source
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Unsets the log source so that logging becomes disabled.
|
||||||
|
#
|
||||||
|
def unset_log_source
|
||||||
|
set_log_source(nil)
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Performs tab completion on the supplied string
|
# Performs tab completion on the supplied string
|
||||||
#
|
#
|
||||||
|
@ -93,6 +107,8 @@ module Shell
|
||||||
stop_flag = false
|
stop_flag = false
|
||||||
|
|
||||||
while ((line = input.pgets))
|
while ((line = input.pgets))
|
||||||
|
log_output(input.prompt)
|
||||||
|
|
||||||
# If a block was passed in, pass the line to it. If it returns true,
|
# If a block was passed in, pass the line to it. If it returns true,
|
||||||
# break out of the shell loop.
|
# break out of the shell loop.
|
||||||
if (block)
|
if (block)
|
||||||
|
@ -177,6 +193,13 @@ module Shell
|
||||||
def colorize(*color)
|
def colorize(*color)
|
||||||
# This check is busted atm...
|
# This check is busted atm...
|
||||||
#return (supports_color? == false) ? '' : Rex::Ui::Text::Color.ansi(color)
|
#return (supports_color? == false) ? '' : Rex::Ui::Text::Color.ansi(color)
|
||||||
|
return do_colorize(*color)
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Colorize regardless of terminal support
|
||||||
|
#
|
||||||
|
def do_colorize(*color)
|
||||||
return Rex::Ui::Text::Color.ansi(*color)
|
return Rex::Ui::Text::Color.ansi(*color)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -186,25 +209,25 @@ module Shell
|
||||||
|
|
||||||
def print_error(msg)
|
def print_error(msg)
|
||||||
# Errors are not subject to disabled output
|
# Errors are not subject to disabled output
|
||||||
output.print_error(msg)
|
log_output(output.print_error(msg))
|
||||||
end
|
end
|
||||||
|
|
||||||
def print_status(msg)
|
def print_status(msg)
|
||||||
return if (disable_output == true)
|
return if (disable_output == true)
|
||||||
|
|
||||||
output.print_status(msg)
|
log_output(output.print_status(msg))
|
||||||
end
|
end
|
||||||
|
|
||||||
def print_line(msg)
|
def print_line(msg)
|
||||||
return if (disable_output == true)
|
return if (disable_output == true)
|
||||||
|
|
||||||
output.print_line(msg)
|
log_output(output.print_line(msg))
|
||||||
end
|
end
|
||||||
|
|
||||||
def print(msg)
|
def print(msg)
|
||||||
return if (disable_output == true)
|
return if (disable_output == true)
|
||||||
|
|
||||||
output.print(msg)
|
log_output(output.print(msg))
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_accessor :disable_output
|
attr_accessor :disable_output
|
||||||
|
@ -216,6 +239,8 @@ protected
|
||||||
# Parse a line into an array of arguments
|
# Parse a line into an array of arguments
|
||||||
#
|
#
|
||||||
def parse_line(line)
|
def parse_line(line)
|
||||||
|
log_input(line)
|
||||||
|
|
||||||
line.gsub!(/(\r|\n)/, '')
|
line.gsub!(/(\r|\n)/, '')
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
@ -227,10 +252,31 @@ protected
|
||||||
return []
|
return []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Print the prompt, but do not log it.
|
||||||
|
#
|
||||||
|
def _print_prompt(prompt)
|
||||||
|
output.print(prompt)
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Writes the supplied input to the log source if one has been registered.
|
||||||
|
#
|
||||||
|
def log_input(buf)
|
||||||
|
rlog(do_colorize("red") + buf + do_colorize("clear"), log_source) if (log_source)
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Writes the supplied output to the log source if one has been registered.
|
||||||
|
#
|
||||||
|
def log_output(buf)
|
||||||
|
rlog(do_colorize("blue") + buf + do_colorize("clear"), log_source) if (log_source)
|
||||||
|
end
|
||||||
|
|
||||||
attr_writer :input, :output
|
attr_writer :input, :output
|
||||||
attr_accessor :stop_flag, :init_prompt
|
attr_accessor :stop_flag, :init_prompt
|
||||||
attr_accessor :prompt_char, :tab_complete_proc
|
attr_accessor :prompt_char, :tab_complete_proc
|
||||||
|
attr_accessor :log_source
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue