2005-07-09 21:18:49 +00:00
|
|
|
require 'msf/core'
|
|
|
|
require 'msf/base'
|
|
|
|
require 'msf/ui'
|
2005-07-16 08:12:58 +00:00
|
|
|
require 'msf/ui/console/framework_event_manager'
|
2005-07-09 21:18:49 +00:00
|
|
|
require 'msf/ui/console/command_dispatcher'
|
|
|
|
require 'msf/ui/console/table'
|
2005-07-12 05:39:44 +00:00
|
|
|
require 'find'
|
2005-07-07 06:14:58 +00:00
|
|
|
|
2005-05-22 19:39:21 +00:00
|
|
|
module Msf
|
|
|
|
module Ui
|
|
|
|
module Console
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# This class implements a user interface driver on a console interface.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
class Driver < Msf::Ui::Driver
|
|
|
|
|
2005-10-02 03:21:26 +00:00
|
|
|
ConfigCore = "framework/core"
|
2005-07-15 22:30:04 +00:00
|
|
|
ConfigGroup = "framework/ui/console"
|
|
|
|
|
2009-11-10 07:12:56 +00:00
|
|
|
DefaultPrompt = "%undmsf%clr"
|
|
|
|
DefaultPromptChar = "%clr>"
|
2005-11-28 16:36:06 +00:00
|
|
|
|
2005-07-16 08:12:58 +00:00
|
|
|
#
|
|
|
|
# The console driver processes various framework notified events.
|
|
|
|
#
|
|
|
|
include FrameworkEventManager
|
|
|
|
|
|
|
|
#
|
|
|
|
# The console driver is a command shell.
|
|
|
|
#
|
2005-07-18 05:13:21 +00:00
|
|
|
include Rex::Ui::Text::DispatcherShell
|
2005-05-22 19:39:21 +00:00
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
|
|
|
# Initializes a console driver instance with the supplied prompt string and
|
2005-11-28 16:36:06 +00:00
|
|
|
# prompt character. The optional hash can take extra values that will
|
|
|
|
# serve to initialize the console driver.
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
2005-12-07 03:06:31 +00:00
|
|
|
# The optional hash values can include:
|
|
|
|
#
|
|
|
|
# AllowCommandPassthru
|
|
|
|
#
|
|
|
|
# Whether or not unknown commands should be passed through and executed by
|
|
|
|
# the local system.
|
|
|
|
#
|
2009-10-02 14:17:03 +00:00
|
|
|
# RealReadline
|
|
|
|
#
|
|
|
|
# Whether or to use the system Readline or the RBReadline (default)
|
2009-11-26 02:18:02 +00:00
|
|
|
#
|
|
|
|
# HistFile
|
|
|
|
#
|
|
|
|
# Name of a file to store command history
|
2009-10-02 14:17:03 +00:00
|
|
|
#
|
2005-11-28 16:36:06 +00:00
|
|
|
def initialize(prompt = DefaultPrompt, prompt_char = DefaultPromptChar, opts = {})
|
2009-10-02 14:17:03 +00:00
|
|
|
|
|
|
|
# Choose a readline library before calling the parent
|
|
|
|
rl = false
|
2009-12-29 21:54:03 +00:00
|
|
|
rl_err = nil
|
2009-10-02 14:17:03 +00:00
|
|
|
begin
|
|
|
|
if(opts['RealReadline'])
|
|
|
|
require 'readline'
|
|
|
|
rl = true
|
|
|
|
end
|
|
|
|
rescue ::LoadError
|
2009-12-29 21:54:03 +00:00
|
|
|
rl_err = $!
|
2006-06-08 20:53:15 +00:00
|
|
|
end
|
2009-10-02 14:17:03 +00:00
|
|
|
|
|
|
|
# Default to the RbReadline wrapper
|
|
|
|
require 'readline_compatible' if(not rl)
|
|
|
|
|
2009-11-26 02:18:02 +00:00
|
|
|
histfile = opts['HistFile'] || Msf::Config.history_file
|
2006-06-08 20:53:15 +00:00
|
|
|
|
2005-07-18 05:13:21 +00:00
|
|
|
# Call the parent
|
2009-11-26 02:18:02 +00:00
|
|
|
super(prompt, prompt_char, histfile)
|
2005-07-18 05:13:21 +00:00
|
|
|
|
2005-10-30 23:40:27 +00:00
|
|
|
# Temporarily disable output
|
|
|
|
self.disable_output = true
|
|
|
|
|
|
|
|
# Load pre-configuration
|
|
|
|
load_preconfig
|
|
|
|
|
2005-05-22 19:39:21 +00:00
|
|
|
# Initialize attributes
|
2005-11-28 16:36:06 +00:00
|
|
|
self.framework = opts['Framework'] || Msf::Simple::Framework.create
|
2009-10-02 14:17:03 +00:00
|
|
|
|
2005-11-28 16:36:06 +00:00
|
|
|
# Initialize the user interface to use a different input and output
|
|
|
|
# handle if one is supplied
|
|
|
|
if (opts['LocalInput'] or opts['LocalOutput'])
|
|
|
|
init_ui(
|
|
|
|
opts['LocalInput'],
|
|
|
|
opts['LocalOutput'])
|
|
|
|
end
|
2005-05-22 19:39:21 +00:00
|
|
|
|
|
|
|
# Add the core command dispatcher as the root of the dispatcher
|
|
|
|
# stack
|
|
|
|
enstack_dispatcher(CommandDispatcher::Core)
|
2009-03-28 21:42:30 +00:00
|
|
|
|
2009-12-29 21:54:03 +00:00
|
|
|
# Report readline error if there was one..
|
|
|
|
if not rl_err.nil?
|
|
|
|
print_error("***")
|
|
|
|
print_error("* WARNING: Unable to load readline: #{rl_err}")
|
|
|
|
print_error("* Falling back to RbReadLine")
|
|
|
|
print_error("***")
|
|
|
|
end
|
|
|
|
|
2009-03-28 21:42:30 +00:00
|
|
|
# Add the database dispatcher if it is usable
|
|
|
|
if(framework.db.usable)
|
|
|
|
require 'msf/ui/console/command_dispatcher/db'
|
|
|
|
enstack_dispatcher(CommandDispatcher::Db)
|
2009-06-03 16:28:28 +00:00
|
|
|
else
|
|
|
|
print_error("***")
|
|
|
|
print_error("* WARNING: No database support: #{framework.db.error.class} #{framework.db.error}")
|
|
|
|
print_error("***")
|
2009-03-28 21:42:30 +00:00
|
|
|
end
|
2005-05-22 19:39:21 +00:00
|
|
|
|
2009-07-23 13:28:47 +00:00
|
|
|
|
|
|
|
begin
|
|
|
|
require 'openssl'
|
|
|
|
rescue ::LoadError
|
|
|
|
print_error("***")
|
|
|
|
print_error("* WARNING: No OpenSSL support. This is required by meterpreter payloads and many exploits")
|
|
|
|
print_error("* Please install the ruby-openssl package (apt-get install libopenssl-ruby on Debian/Ubuntu")
|
|
|
|
print_error("***")
|
|
|
|
end
|
|
|
|
|
2005-07-16 08:12:58 +00:00
|
|
|
# Register event handlers
|
|
|
|
register_event_handlers
|
2005-10-01 21:51:45 +00:00
|
|
|
|
2005-07-15 22:30:04 +00:00
|
|
|
# Load console-specific configuration
|
2006-04-02 16:28:02 +00:00
|
|
|
load_config(opts['Config'])
|
2005-10-02 03:21:26 +00:00
|
|
|
|
|
|
|
# Re-enable output
|
|
|
|
self.disable_output = false
|
|
|
|
|
2007-02-24 05:29:05 +00:00
|
|
|
# Load additional modules as necessary
|
|
|
|
self.framework.modules.add_module_path(opts['ModulePath'], false) if opts['ModulePath']
|
|
|
|
|
2005-12-07 03:06:31 +00:00
|
|
|
# Whether or not command passthru should be allowed
|
|
|
|
self.command_passthru = (opts['AllowCommandPassthru'] == false) ? false : true
|
2007-01-30 04:48:35 +00:00
|
|
|
|
|
|
|
# Disables "dangerous" functionality of the console
|
|
|
|
@defanged = opts['Defanged'] == true
|
|
|
|
|
|
|
|
# If we're defanged, then command passthru should be disabled
|
|
|
|
if @defanged
|
|
|
|
self.command_passthru = false
|
|
|
|
end
|
2009-11-10 03:27:48 +00:00
|
|
|
|
|
|
|
# Process things before we actually display the prompt and get rocking
|
|
|
|
on_startup
|
|
|
|
|
|
|
|
# Process the resource script
|
2010-02-02 23:13:42 +00:00
|
|
|
if opts['Resource'] and opts['Resource'].kind_of? Array
|
|
|
|
opts['Resource'].each { |r|
|
|
|
|
load_resource(r)
|
|
|
|
}
|
|
|
|
else
|
|
|
|
# If the opt is nil here, we load ~/.msf3/msfconsole.rc
|
|
|
|
load_resource(opts['Resource'])
|
|
|
|
end
|
2005-07-15 22:30:04 +00:00
|
|
|
end
|
|
|
|
|
2005-10-30 23:40:27 +00:00
|
|
|
#
|
|
|
|
# Loads configuration that needs to be analyzed before the framework
|
|
|
|
# instance is created.
|
|
|
|
#
|
|
|
|
def load_preconfig
|
|
|
|
begin
|
|
|
|
conf = Msf::Config.load
|
|
|
|
rescue
|
|
|
|
wlog("Failed to load configuration: #{$!}")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
if (conf.group?(ConfigCore))
|
|
|
|
conf[ConfigCore].each_pair { |k, v|
|
|
|
|
on_variable_set(true, k, v)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-07-15 22:30:04 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Loads configuration for the console.
|
2005-07-15 22:30:04 +00:00
|
|
|
#
|
2006-04-02 16:28:02 +00:00
|
|
|
def load_config(path=nil)
|
2005-07-15 22:30:04 +00:00
|
|
|
begin
|
2006-04-02 16:28:02 +00:00
|
|
|
conf = Msf::Config.load(path)
|
2005-07-15 22:30:04 +00:00
|
|
|
rescue
|
|
|
|
wlog("Failed to load configuration: #{$!}")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
# If we have configuration, process it
|
|
|
|
if (conf.group?(ConfigGroup))
|
|
|
|
conf[ConfigGroup].each_pair { |k, v|
|
2005-10-02 03:21:26 +00:00
|
|
|
case k.downcase
|
|
|
|
when "activemodule"
|
2005-07-15 22:30:04 +00:00
|
|
|
run_single("use #{v}")
|
|
|
|
end
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Saves configuration for the console.
|
2005-07-15 22:30:04 +00:00
|
|
|
#
|
|
|
|
def save_config
|
|
|
|
# Build out the console config group
|
|
|
|
group = {}
|
|
|
|
|
|
|
|
if (active_module)
|
|
|
|
group['ActiveModule'] = active_module.fullname
|
|
|
|
end
|
|
|
|
|
|
|
|
# Save it
|
|
|
|
begin
|
2009-03-08 07:41:28 +00:00
|
|
|
Msf::Config.save(ConfigGroup => group)
|
|
|
|
rescue ::Exception
|
|
|
|
print_error("Failed to save console config: #{$!}")
|
2005-07-15 22:30:04 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Processes the resource script file for the console.
|
2005-07-15 22:30:04 +00:00
|
|
|
#
|
2006-04-02 16:28:02 +00:00
|
|
|
def load_resource(path=nil)
|
|
|
|
path ||= File.join(Msf::Config.config_directory, 'msfconsole.rc')
|
|
|
|
return if not File.readable?(path)
|
|
|
|
|
|
|
|
rcfd = File.open(path, 'r')
|
|
|
|
rcfd.each_line do |line|
|
2008-04-26 18:28:41 +00:00
|
|
|
line.strip!
|
|
|
|
next if line.length == 0
|
|
|
|
next if line =~ /^#/
|
2010-02-02 23:13:42 +00:00
|
|
|
print_line("resource (#{path})> #{line}")
|
2008-04-26 18:28:41 +00:00
|
|
|
run_single(line)
|
2006-04-02 16:28:02 +00:00
|
|
|
end
|
|
|
|
rcfd.close
|
2005-07-14 07:13:01 +00:00
|
|
|
end
|
|
|
|
|
2006-04-02 16:28:02 +00:00
|
|
|
#
|
|
|
|
# Creates the resource script file for the console.
|
|
|
|
#
|
|
|
|
def save_resource(data, path=nil)
|
|
|
|
path ||= File.join(Msf::Config.config_directory, 'msfconsole.rc')
|
|
|
|
|
|
|
|
begin
|
|
|
|
rcfd = File.open(path, 'w')
|
|
|
|
rcfd.write(data)
|
|
|
|
rcfd.close
|
2008-11-11 06:00:54 +00:00
|
|
|
rescue ::Exception
|
2006-04-02 16:28:02 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-07-14 07:13:01 +00:00
|
|
|
#
|
|
|
|
# Called before things actually get rolling such that banners can be
|
|
|
|
# displayed, scripts can be processed, and other fun can be had.
|
|
|
|
#
|
2008-12-26 07:13:08 +00:00
|
|
|
def on_startup
|
2006-09-16 06:27:14 +00:00
|
|
|
# Check for modules that failed to load
|
|
|
|
if (framework.modules.failed.length > 0)
|
|
|
|
print("[*] WARNING! The following modules could not be loaded!\n\n")
|
|
|
|
framework.modules.failed.each_pair do |file, err|
|
2008-12-19 07:11:08 +00:00
|
|
|
print("\t#{file}: #{err}\n\n")
|
2006-09-16 06:27:14 +00:00
|
|
|
end
|
|
|
|
print("\n")
|
|
|
|
end
|
2009-12-22 18:52:48 +00:00
|
|
|
framework.events.on_ui_start(Msf::Framework::Revision)
|
2006-09-16 06:27:14 +00:00
|
|
|
|
2005-07-14 07:13:01 +00:00
|
|
|
# Build the banner message
|
2008-12-26 07:13:08 +00:00
|
|
|
run_single("banner")
|
2010-01-06 05:06:12 +00:00
|
|
|
self.on_command_proc = Proc.new { |command| framework.events.on_ui_command(command) }
|
2005-05-22 19:39:21 +00:00
|
|
|
end
|
|
|
|
|
2005-10-01 21:51:45 +00:00
|
|
|
#
|
|
|
|
# Called when a variable is set to a specific value. This allows the
|
|
|
|
# console to do extra processing, such as enabling logging or doing
|
|
|
|
# some other kind of task. If this routine returns false it will indicate
|
|
|
|
# that the variable is not being set to a valid value.
|
|
|
|
#
|
2005-10-02 03:21:26 +00:00
|
|
|
def on_variable_set(glob, var, val)
|
2005-10-01 21:51:45 +00:00
|
|
|
case var.downcase
|
|
|
|
when "payload"
|
2005-11-24 03:53:45 +00:00
|
|
|
|
|
|
|
if (framework and framework.modules.valid?(val) == false)
|
2005-10-01 21:51:45 +00:00
|
|
|
return false
|
2006-01-16 21:34:36 +00:00
|
|
|
elsif (active_module)
|
2005-12-31 20:26:17 +00:00
|
|
|
active_module.datastore.clear_non_user_defined
|
2006-01-16 21:36:17 +00:00
|
|
|
elsif (framework)
|
2006-01-16 21:34:36 +00:00
|
|
|
framework.datastore.clear_non_user_defined
|
2005-10-01 21:51:45 +00:00
|
|
|
end
|
2005-10-02 03:21:26 +00:00
|
|
|
when "sessionlogging"
|
|
|
|
handle_session_logging(val) if (glob)
|
2005-10-02 04:05:17 +00:00
|
|
|
when "consolelogging"
|
|
|
|
handle_console_logging(val) if (glob)
|
2005-10-30 23:40:27 +00:00
|
|
|
when "loglevel"
|
|
|
|
handle_loglevel(val) if (glob)
|
2005-10-01 21:51:45 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
#
|
2005-10-02 03:21:26 +00:00
|
|
|
def on_variable_unset(glob, var)
|
|
|
|
case var.downcase
|
|
|
|
when "sessionlogging"
|
|
|
|
handle_session_logging('0') if (glob)
|
2005-10-02 04:05:17 +00:00
|
|
|
when "consolelogging"
|
|
|
|
handle_console_logging('0') if (glob)
|
2005-10-30 23:40:27 +00:00
|
|
|
when "loglevel"
|
|
|
|
handle_loglevel(nil) if (glob)
|
2005-10-02 03:21:26 +00:00
|
|
|
end
|
2005-10-01 21:51:45 +00:00
|
|
|
end
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
|
|
|
# The framework instance associated with this driver.
|
|
|
|
#
|
2005-07-18 05:13:21 +00:00
|
|
|
attr_reader :framework
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
2005-12-07 03:06:31 +00:00
|
|
|
# Whether or not commands can be passed through.
|
|
|
|
#
|
|
|
|
attr_reader :command_passthru
|
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# The active module associated with the driver.
|
|
|
|
#
|
2005-07-14 06:34:58 +00:00
|
|
|
attr_accessor :active_module
|
2007-02-18 22:35:07 +00:00
|
|
|
#
|
|
|
|
# The active session associated with the driver.
|
|
|
|
#
|
|
|
|
attr_accessor :active_session
|
|
|
|
|
2007-01-30 04:48:35 +00:00
|
|
|
#
|
|
|
|
# If defanged is true, dangerous functionality, such as exploitation, irb,
|
|
|
|
# and command shell passthru is disabled. In this case, an exception is
|
|
|
|
# raised.
|
|
|
|
#
|
|
|
|
def defanged?
|
|
|
|
if @defanged
|
|
|
|
raise DefangedException
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-12-22 18:52:48 +00:00
|
|
|
def stop
|
|
|
|
framework.events.on_ui_stop()
|
|
|
|
super
|
|
|
|
end
|
|
|
|
|
2005-05-22 19:39:21 +00:00
|
|
|
protected
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
attr_writer :framework # :nodoc:
|
2005-12-07 03:06:31 +00:00
|
|
|
attr_writer :command_passthru # :nodoc:
|
|
|
|
|
|
|
|
#
|
|
|
|
# If an unknown command was passed, try to see if it's a valid local
|
|
|
|
# executable. This is only allowed if command passthru has been permitted
|
|
|
|
#
|
|
|
|
def unknown_command(method, line)
|
2007-12-31 02:03:13 +00:00
|
|
|
|
|
|
|
[method, method+".exe"].each do |cmd|
|
|
|
|
if (command_passthru == true and Rex::FileUtils.find_full_path(cmd))
|
|
|
|
|
|
|
|
print_status("exec: #{line}")
|
|
|
|
print_line('')
|
|
|
|
|
2008-01-21 02:10:27 +00:00
|
|
|
self.busy = true
|
2009-12-03 08:17:14 +00:00
|
|
|
begin
|
|
|
|
io = ::IO.popen(line, "r")
|
|
|
|
io.each_line do |data|
|
|
|
|
print(data)
|
|
|
|
end
|
|
|
|
io.close
|
|
|
|
rescue ::Errno::EACCES, ::Errno::ENOENT
|
|
|
|
print_error("Permission denied exec: #{line}")
|
2007-12-31 02:03:13 +00:00
|
|
|
end
|
2008-01-21 02:10:27 +00:00
|
|
|
self.busy = false
|
2007-12-31 02:03:13 +00:00
|
|
|
return
|
2007-01-22 06:57:07 +00:00
|
|
|
end
|
2005-12-07 03:06:31 +00:00
|
|
|
end
|
2007-12-31 02:03:13 +00:00
|
|
|
|
|
|
|
super
|
2005-12-07 03:06:31 +00:00
|
|
|
end
|
2005-10-02 03:21:26 +00:00
|
|
|
|
|
|
|
##
|
|
|
|
#
|
|
|
|
# Handlers for various global configuration values
|
|
|
|
#
|
|
|
|
##
|
2005-05-22 19:39:21 +00:00
|
|
|
|
2005-10-02 03:21:26 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# SessionLogging.
|
2005-10-02 03:21:26 +00:00
|
|
|
#
|
|
|
|
def handle_session_logging(val)
|
2009-01-07 02:50:10 +00:00
|
|
|
if (val =~ /^(y|t|1)/i)
|
2005-10-02 03:21:26 +00:00
|
|
|
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
|
2005-10-02 04:05:17 +00:00
|
|
|
|
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# ConsoleLogging.
|
2005-10-02 04:05:17 +00:00
|
|
|
#
|
|
|
|
def handle_console_logging(val)
|
2009-01-07 02:50:10 +00:00
|
|
|
if (val =~ /^(y|t|1)/i)
|
2005-10-02 04:05:17 +00:00
|
|
|
Msf::Logging.enable_log_source('console')
|
|
|
|
print_line("Console logging is now enabled.")
|
|
|
|
|
|
|
|
set_log_source('console')
|
|
|
|
|
|
|
|
rlog("\n[*] Console logging started: #{Time.now}\n\n", 'console')
|
|
|
|
else
|
|
|
|
rlog("\n[*] Console logging stopped: #{Time.now}\n\n", 'console')
|
|
|
|
|
|
|
|
unset_log_source
|
|
|
|
|
|
|
|
Msf::Logging.disable_log_source('console')
|
|
|
|
print_line("Console logging is now disabled.")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-10-30 23:40:27 +00:00
|
|
|
#
|
|
|
|
# This method handles adjusting the global log level threshold.
|
|
|
|
#
|
|
|
|
def handle_loglevel(val)
|
|
|
|
set_log_level(Rex::LogSource, val)
|
|
|
|
set_log_level(Msf::LogSource, val)
|
|
|
|
end
|
|
|
|
|
2005-05-22 19:39:21 +00:00
|
|
|
end
|
|
|
|
|
2007-01-30 04:48:35 +00:00
|
|
|
#
|
|
|
|
# This exception is used to indicate that functionality is disabled due to
|
|
|
|
# defanged being true
|
|
|
|
#
|
|
|
|
class DefangedException < ::Exception
|
|
|
|
def to_s
|
|
|
|
"This functionality is currently disabled (defanged mode)"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-05-22 19:39:21 +00:00
|
|
|
end
|
|
|
|
end
|
2008-11-11 06:00:54 +00:00
|
|
|
end
|