parent
8e7dd1b658
commit
04541ac724
|
@ -1,30 +1,7 @@
|
|||
require 'rails'
|
||||
require File.expand_path('../boot', __FILE__)
|
||||
|
||||
# only the parts of 'rails/all' that metasploit-framework actually uses
|
||||
begin
|
||||
require 'active_record/railtie'
|
||||
rescue LoadError
|
||||
warn "activerecord not in the bundle, so database support will be disabled."
|
||||
warn "Bundle installed '--without #{Bundler.settings.without.join(' ')}'"
|
||||
warn "To clear the without option do `bundle install --without ''` " \
|
||||
"(the --without flag with an empty string) or " \
|
||||
"`rm -rf .bundle` to remove the .bundle/config manually and " \
|
||||
"then `bundle install`"
|
||||
end
|
||||
|
||||
all_environments = [
|
||||
:development,
|
||||
:production,
|
||||
:test
|
||||
]
|
||||
|
||||
Bundler.require(
|
||||
*Rails.groups(
|
||||
db: all_environments,
|
||||
pcap: all_environments
|
||||
)
|
||||
)
|
||||
Bundler.require(*Rails.groups)
|
||||
|
||||
#
|
||||
# Project
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
#
|
||||
# Gems
|
||||
#
|
||||
|
||||
# have to be exact so minimum is loaded prior to parsing arguments which could influence loading.
|
||||
require 'active_support/dependencies/autoload'
|
||||
|
||||
# @note Must use the nested declaration of the {Metasploit::Framework::Command} namespace because commands need to be
|
||||
# able to be required directly without any other part of metasploit-framework besides config/boot so that the commands
|
||||
# can parse arguments, setup RAILS_ENV, and load config/application.rb correctly.
|
||||
module Metasploit
|
||||
module Framework
|
||||
module Command
|
||||
# Namespace for commands for metasploit-framework. There are corresponding classes in the
|
||||
# {Metasploit::Framework::ParsedOptions} namespace, which handle for parsing the options for each command.
|
||||
extend ActiveSupport::Autoload
|
||||
|
||||
autoload :Base
|
||||
autoload :Console
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,117 @@
|
|||
#
|
||||
# Gems
|
||||
#
|
||||
|
||||
require 'active_support/core_ext/module/introspection'
|
||||
|
||||
#
|
||||
# Project
|
||||
#
|
||||
|
||||
require 'metasploit/framework/command'
|
||||
require 'metasploit/framework/parsed_options'
|
||||
|
||||
# Based on pattern used for lib/rails/commands in the railties gem.
|
||||
class Metasploit::Framework::Command::Base
|
||||
#
|
||||
# Attributes
|
||||
#
|
||||
|
||||
# @!attribute [r] application
|
||||
# The Rails application for metasploit-framework.
|
||||
#
|
||||
# @return [Metasploit::Framework::Application]
|
||||
attr_reader :application
|
||||
|
||||
# @!attribute [r] parsed_options
|
||||
# The parsed options from the command line.
|
||||
#
|
||||
# @return (see parsed_options)
|
||||
attr_reader :parsed_options
|
||||
|
||||
#
|
||||
# Class Methods
|
||||
#
|
||||
|
||||
# @note {require_environment!} should be called to load `config/application.rb` to so that the RAILS_ENV can be set
|
||||
# from the command line options in `ARGV` prior to `Rails.env` being set.
|
||||
# @note After returning, `Rails.application` will be defined and configured.
|
||||
#
|
||||
# Parses `ARGV` for command line arguments to configure the `Rails.application`.
|
||||
#
|
||||
# @return (see parsed_options)
|
||||
def self.require_environment!
|
||||
parsed_options = self.parsed_options
|
||||
# RAILS_ENV must be set before requiring 'config/application.rb'
|
||||
parsed_options.environment!
|
||||
ARGV.replace(parsed_options.positional)
|
||||
|
||||
# @see https://github.com/rails/rails/blob/v3.2.17/railties/lib/rails/commands.rb#L39-L40
|
||||
require Pathname.new(__FILE__).parent.parent.parent.parent.parent.join('config', 'application')
|
||||
|
||||
# have to configure before requiring environment because config/environment.rb calls initialize! and the initializers
|
||||
# will use the configuration from the parsed options.
|
||||
parsed_options.configure(Rails.application)
|
||||
|
||||
# support disabling the database
|
||||
unless parsed_options.options.database.disable
|
||||
begin
|
||||
require 'active_record/railtie'
|
||||
rescue LoadError
|
||||
warn "activerecord not in the bundle, so database support will be disabled."
|
||||
warn "Bundle installed '--without #{Bundler.settings.without.join(' ')}'"
|
||||
warn "To clear the without option do `bundle install --without ''` " \
|
||||
"(the --without flag with an empty string) or " \
|
||||
"`rm -rf .bundle` to remove the .bundle/config manually and " \
|
||||
"then `bundle install`"
|
||||
end
|
||||
|
||||
ENV['RAILS_GROUP'] = 'db,pcap'
|
||||
end
|
||||
|
||||
Rails.application.require_environment!
|
||||
|
||||
parsed_options
|
||||
end
|
||||
|
||||
def self.parsed_options
|
||||
parsed_options_class.new
|
||||
end
|
||||
|
||||
def self.parsed_options_class
|
||||
@parsed_options_class ||= parsed_options_class_name.constantize
|
||||
end
|
||||
|
||||
def self.parsed_options_class_name
|
||||
@parsed_options_class_name ||= "#{parent.parent}::ParsedOptions::#{name.demodulize}"
|
||||
end
|
||||
|
||||
def self.start
|
||||
parsed_options = require_environment!
|
||||
new(application: Rails.application, parsed_options: parsed_options).start
|
||||
end
|
||||
|
||||
#
|
||||
# Instance Methods
|
||||
#
|
||||
|
||||
# @param attributes [Hash{Symbol => ActiveSupport::OrderedOptions,Rails::Application}]
|
||||
# @option attributes [Rails::Application] :application
|
||||
# @option attributes [ActiveSupport::OrderedOptions] :parsed_options
|
||||
# @raise [KeyError] if :application is not given
|
||||
# @raise [KeyError] if :parsed_options is not given
|
||||
def initialize(attributes={})
|
||||
@application = attributes.fetch(:application)
|
||||
@parsed_options = attributes.fetch(:parsed_options)
|
||||
end
|
||||
|
||||
# @abstract Use {#application} to start this command.
|
||||
#
|
||||
# Starts this command.
|
||||
#
|
||||
# @return [void]
|
||||
# @raise [NotImplementedError]
|
||||
def start
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
|
@ -0,0 +1,58 @@
|
|||
#
|
||||
# Project
|
||||
#
|
||||
|
||||
require 'metasploit/framework/command'
|
||||
require 'metasploit/framework/command/base'
|
||||
|
||||
# Based on pattern used for lib/rails/commands in the railties gem.
|
||||
class Metasploit::Framework::Command::Console < Metasploit::Framework::Command::Base
|
||||
def start
|
||||
driver.run
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# The console UI driver.
|
||||
#
|
||||
# @return [Msf::Ui::Console::Driver]
|
||||
def driver
|
||||
unless @driver
|
||||
# require here so minimum loading is done before {start} is called.
|
||||
require 'msf/ui'
|
||||
|
||||
@driver = Msf::Ui::Console::Driver.new(
|
||||
Msf::Ui::Console::Driver::DefaultPrompt,
|
||||
Msf::Ui::Console::Driver::DefaultPromptChar,
|
||||
driver_options
|
||||
)
|
||||
end
|
||||
|
||||
@driver
|
||||
end
|
||||
|
||||
def driver_options
|
||||
unless @driver_options
|
||||
options = parsed_options.options
|
||||
|
||||
driver_options = {}
|
||||
driver_options['Config'] = options.framework.config
|
||||
driver_options['DatabaseEnv'] = options.environment
|
||||
driver_options['DatabaseMigrationPaths'] = options.database.migrations_paths
|
||||
driver_options['DatabaseYAML'] = options.database.config
|
||||
driver_options['Defanged'] = options.console.defanged
|
||||
driver_options['DisableBanner'] = options.console.quiet
|
||||
driver_options['DisableDatabase'] = options.database.disable
|
||||
driver_options['LocalOutput'] = options.console.local_output
|
||||
driver_options['ModulePath'] = options.modules.path
|
||||
driver_options['Plugins'] = options.console.plugins
|
||||
driver_options['RealReadline'] = options.console.real_readline
|
||||
driver_options['Resource'] = options.console.resource
|
||||
driver_options['XCommands'] = options.console.commands
|
||||
|
||||
@driver_options = driver_options
|
||||
end
|
||||
|
||||
@driver_options
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
#
|
||||
# Gems
|
||||
#
|
||||
|
||||
require 'active_support/dependencies/autoload'
|
||||
|
||||
# # @note Must use the nested declaration of the {Metasploit::Framework::ParsedOptions} namespace because commands,
|
||||
# which use parsed options, need to be able to be required directly without any other part of metasploit-framework
|
||||
# besides config/boot so that the commands can parse arguments, setup RAILS_ENV, and load config/application.rb
|
||||
# correctly.
|
||||
module Metasploit
|
||||
module Framework
|
||||
# Namespace for parsed options for {Metasploit::Framework::Command commands}. The names of `Class`es in this
|
||||
# namespace correspond to the name of the `Class` in the {Metasploit::Framework::Command} namespace for which this
|
||||
# namespace's `Class` parses options.
|
||||
module ParsedOptions
|
||||
extend ActiveSupport::Autoload
|
||||
|
||||
autoload :Base
|
||||
autoload :Console
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
#
|
||||
# Standard Library
|
||||
#
|
||||
|
||||
require 'optparse'
|
||||
|
||||
#
|
||||
# Gems
|
||||
#
|
||||
|
||||
require 'active_support/ordered_options'
|
||||
|
||||
#
|
||||
# Project
|
||||
#
|
||||
|
||||
require 'metasploit/framework/parsed_options'
|
||||
require 'msf/base/config'
|
||||
|
||||
# Options parsed from the command line that can be used to change the `Metasploit::Framework::Application.config` and
|
||||
# `Rails.env`
|
||||
class Metasploit::Framework::ParsedOptions::Base
|
||||
#
|
||||
# CONSTANTS
|
||||
#
|
||||
|
||||
# msfconsole boots in production mode instead of the normal rails default of development.
|
||||
DEFAULT_ENVIRONMENT = 'production'
|
||||
|
||||
#
|
||||
# Attributes
|
||||
#
|
||||
|
||||
attr_reader :positional
|
||||
|
||||
#
|
||||
# Instance Methods
|
||||
#
|
||||
|
||||
def initialize(arguments=ARGV)
|
||||
@positional = option_parser.parse(arguments)
|
||||
end
|
||||
|
||||
# Translates {#options} to the `application`'s config
|
||||
#
|
||||
# @param application [Rails::Application]
|
||||
# @return [void]
|
||||
def configure(application)
|
||||
application.config['config/database'] = options.database.config
|
||||
end
|
||||
|
||||
# Sets the `RAILS_ENV` environment variable.
|
||||
#
|
||||
# 1. If the -E/--environment option is given, then its value is used.
|
||||
# 2. The default value, 'production', is used.
|
||||
#
|
||||
# @return [void]
|
||||
def environment!
|
||||
if defined?(Rails) && Rails.instance_variable_defined?(:@_env)
|
||||
raise "#{self.class}##{__method__} called too late to set RAILS_ENV: Rails.env already memoized"
|
||||
end
|
||||
|
||||
ENV['RAILS_ENV'] = options.environment
|
||||
end
|
||||
|
||||
# Options parsed from
|
||||
#
|
||||
# @return [ActiveSupport::OrderedOptions]
|
||||
def options
|
||||
unless @options
|
||||
options = ActiveSupport::OrderedOptions.new
|
||||
|
||||
options.database = ActiveSupport::OrderedOptions.new
|
||||
|
||||
user_config_root = Pathname.new(Msf::Config.get_config_root)
|
||||
user_database_yaml = user_config_root.join('database.yml')
|
||||
|
||||
if user_database_yaml.exist?
|
||||
options.database.config = [user_database_yaml.to_path]
|
||||
else
|
||||
options.database.config = ['config/database.yml']
|
||||
end
|
||||
|
||||
options.database.disable = false
|
||||
options.database.migrations_paths = []
|
||||
|
||||
options.framework = ActiveSupport::OrderedOptions.new
|
||||
options.framework.config = nil
|
||||
|
||||
options.modules = ActiveSupport::OrderedOptions.new
|
||||
options.modules.path = nil
|
||||
|
||||
options.environment = DEFAULT_ENVIRONMENT
|
||||
|
||||
@options = options
|
||||
end
|
||||
|
||||
@options
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Parses arguments into {#options}.
|
||||
#
|
||||
# @return [OptionParser]
|
||||
def option_parser
|
||||
@option_parser ||= OptionParser.new { |option_parser|
|
||||
option_parser.separator ''
|
||||
option_parser.separator 'Common options'
|
||||
|
||||
option_parser.on(
|
||||
'-E',
|
||||
'--environment ENVIRONMENT',
|
||||
%w{development production test},
|
||||
"The Rails environment. Will use RAIL_ENV environment variable if that is set. " \
|
||||
"Defaults to production if neither option not RAILS_ENV environment variable is set."
|
||||
) do |environment|
|
||||
options.environment = environment
|
||||
end
|
||||
|
||||
option_parser.separator ''
|
||||
option_parser.separator 'Database options'
|
||||
|
||||
option_parser.on(
|
||||
'-M',
|
||||
'--migration-path DIRECTORY',
|
||||
'Specify a directory containing additional DB migrations'
|
||||
) do |directory|
|
||||
options.database.migrations_paths << directory
|
||||
end
|
||||
|
||||
option_parser.on('-n', '--no-database', 'Disable database support') do
|
||||
options.database.disable = true
|
||||
end
|
||||
|
||||
option_parser.on(
|
||||
'-y',
|
||||
'--yaml PATH',
|
||||
'Specify a YAML file containing database settings'
|
||||
) do |path|
|
||||
options.database.config = path
|
||||
end
|
||||
|
||||
option_parser.separator ''
|
||||
option_parser.separator 'Framework options'
|
||||
|
||||
|
||||
option_parser.on('-c', '-c FILE', 'Load the specified configuration file') do |file|
|
||||
options.framework.config = file
|
||||
end
|
||||
|
||||
option_parser.on(
|
||||
'-v',
|
||||
'--version',
|
||||
'Show version'
|
||||
) do
|
||||
options.subcommand = :version
|
||||
end
|
||||
|
||||
option_parser.separator ''
|
||||
option_parser.separator 'Module options'
|
||||
|
||||
option_parser.on(
|
||||
'-m',
|
||||
'--module-path DIRECTORY',
|
||||
'An additional module path'
|
||||
) do |directory|
|
||||
options.modules.path = directory
|
||||
end
|
||||
|
||||
#
|
||||
# Tail
|
||||
#
|
||||
|
||||
option_parser.separator ''
|
||||
option_parser.on_tail('-h', '--help', 'Show this message') do
|
||||
puts option_parser
|
||||
exit
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
|
@ -0,0 +1,73 @@
|
|||
# Parsed options for {Metasploit::Framework::Command::Console}
|
||||
class Metasploit::Framework::ParsedOptions::Console < Metasploit::Framework::ParsedOptions::Base
|
||||
# Options parsed from msfconsole command-line.
|
||||
#
|
||||
# @return [ActiveSupport::OrderedOptions]
|
||||
def options
|
||||
unless @options
|
||||
super.tap { |options|
|
||||
options.console = ActiveSupport::OrderedOptions.new
|
||||
|
||||
options.console.commands = []
|
||||
options.console.defanged = false
|
||||
options.console.local_output = nil
|
||||
options.console.plugins = []
|
||||
options.console.quiet = false
|
||||
options.console.real_readline = false
|
||||
options.console.resources = []
|
||||
}
|
||||
end
|
||||
|
||||
@options
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Parses msfconsole arguments into {#options}.
|
||||
#
|
||||
# @return [OptionParser]
|
||||
def option_parser
|
||||
unless @option_parser
|
||||
super.tap { |option_parser|
|
||||
option_parser.banner = "Usage: #{option_parser.program_name} [options]"
|
||||
|
||||
option_parser.separator ''
|
||||
option_parser.separator 'Console options:'
|
||||
|
||||
option_parser.on('-d', '--defanged', 'Execute the console as defanged') do
|
||||
options.console.defanged = true
|
||||
end
|
||||
|
||||
option_parser.on('-L', '--real-readline', 'Use the system Readline library instead of RbReadline') do
|
||||
options.console.real_readline = true
|
||||
end
|
||||
|
||||
option_parser.on('-o', '--output FILE', 'Output to the specified file') do |file|
|
||||
options.console.local_output = file
|
||||
end
|
||||
|
||||
option_parser.on('-p', '--plugin PLUGIN', 'Load a plugin on startup') do |plugin|
|
||||
options.console.plugins << plugin
|
||||
end
|
||||
|
||||
option_parser.on('-q', '--quiet', 'Do not print the banner on start up') do
|
||||
options.console.quiet = true
|
||||
end
|
||||
|
||||
option_parser.on('-r', '--resource FILE', 'Execute the specified resource file') do |file|
|
||||
options.console.resources << file
|
||||
end
|
||||
|
||||
option_parser.on(
|
||||
'-x',
|
||||
'--execute-command COMMAND',
|
||||
'Execute the specified string as console commands (use ; for multiples)'
|
||||
) do |commands|
|
||||
options.console.commands += commands.split(/\s*;\s*/)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
@option_parser
|
||||
end
|
||||
end
|
150
msfconsole
150
msfconsole
|
@ -9,146 +9,18 @@
|
|||
# $Revision$
|
||||
#
|
||||
|
||||
msfbase = __FILE__
|
||||
while File.symlink?(msfbase)
|
||||
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
|
||||
end
|
||||
|
||||
@msfbase_dir = File.expand_path(File.dirname(msfbase))
|
||||
|
||||
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib')))
|
||||
require 'fastlib'
|
||||
require 'msfenv'
|
||||
|
||||
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
|
||||
|
||||
require 'optparse'
|
||||
|
||||
if(RUBY_PLATFORM =~ /mswin32/)
|
||||
$stderr.puts "[*] The msfconsole interface is not supported on the native Windows Ruby\n"
|
||||
$stderr.puts " interpreter. Things will break, exploits will fail, payloads will not\n"
|
||||
$stderr.puts " be handled correctly. Please install Cygwin or use Linux in VMWare.\n\n"
|
||||
end
|
||||
|
||||
class OptsConsole
|
||||
#
|
||||
# Return a hash describing the options.
|
||||
#
|
||||
def self.parse(args)
|
||||
options = {
|
||||
'DeferModuleLoads' => true
|
||||
}
|
||||
|
||||
opts = OptionParser.new do |opts|
|
||||
opts.banner = "Usage: msfconsole [options]"
|
||||
|
||||
opts.separator ""
|
||||
opts.separator "Specific options:"
|
||||
|
||||
opts.on("-d", "-d", "Execute the console as defanged") do
|
||||
options['Defanged'] = true
|
||||
end
|
||||
|
||||
opts.on("-r", "-r <filename>", "Execute the specified resource file") do |r|
|
||||
options['Resource'] ||= []
|
||||
options['Resource'] << r
|
||||
end
|
||||
|
||||
opts.on("-o", "-o <filename>", "Output to the specified file") do |o|
|
||||
options['LocalOutput'] = o
|
||||
end
|
||||
|
||||
opts.on("-c", "-c <filename>", "Load the specified configuration file") do |c|
|
||||
options['Config'] = c
|
||||
end
|
||||
|
||||
opts.on("-m", "-m <directory>", "Specifies an additional module search path") do |m|
|
||||
options['ModulePath'] = m
|
||||
end
|
||||
|
||||
opts.on("-p", "-p <plugin>", "Load a plugin on startup") do |p|
|
||||
options['Plugins'] ||= []
|
||||
options['Plugins'] << p
|
||||
end
|
||||
|
||||
opts.on("-y", "--yaml <database.yml>", "Specify a YAML file containing database settings") do |m|
|
||||
options['DatabaseYAML'] = m
|
||||
end
|
||||
|
||||
opts.on("-M", "--migration-path <dir>", "Specify a directory containing additional DB migrations") do |m|
|
||||
options['DatabaseMigrationPaths'] ||= []
|
||||
options['DatabaseMigrationPaths'] << m
|
||||
end
|
||||
|
||||
opts.on("-e", "--environment <production|development>", "Specify the database environment to load from the YAML") do |m|
|
||||
options['DatabaseEnv'] = m
|
||||
end
|
||||
|
||||
# Boolean switches
|
||||
opts.on("-v", "--version", "Show version") do |v|
|
||||
options['Version'] = true
|
||||
end
|
||||
|
||||
opts.on("-L", "--real-readline", "Use the system Readline library instead of RbReadline") do |v|
|
||||
options['RealReadline'] = true
|
||||
end
|
||||
|
||||
opts.on("-n", "--no-database", "Disable database support") do |v|
|
||||
options['DisableDatabase'] = true
|
||||
end
|
||||
|
||||
opts.on("-q", "--quiet", "Do not print the banner on start up") do |v|
|
||||
options['DisableBanner'] = true
|
||||
end
|
||||
|
||||
opts.on("-x", "-x <command>", "Execute the specified string as console commands (use ; for multiples)") do |s|
|
||||
options['XCommands'] ||= []
|
||||
options['XCommands'] += s.split(/\s*;\s*/)
|
||||
end
|
||||
|
||||
opts.separator ""
|
||||
opts.separator "Common options:"
|
||||
|
||||
opts.on_tail("-h", "--help", "Show this message") do
|
||||
puts opts
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
opts.parse!(args)
|
||||
rescue OptionParser::InvalidOption
|
||||
puts "Invalid option, try -h for usage"
|
||||
exit
|
||||
end
|
||||
|
||||
options
|
||||
end
|
||||
end
|
||||
|
||||
options = OptsConsole.parse(ARGV)
|
||||
|
||||
#
|
||||
# NOTE: we don't require this until down here since we may not need it
|
||||
# when processing certain options (currently only -h)
|
||||
#
|
||||
require 'rex'
|
||||
require 'msf/ui'
|
||||
|
||||
#
|
||||
# Everything below this line requires the framework.
|
||||
# Standard Library
|
||||
#
|
||||
|
||||
if (options['Version'])
|
||||
$stderr.puts 'Framework Version: ' + Msf::Framework::Version
|
||||
exit
|
||||
end
|
||||
require 'pathname'
|
||||
|
||||
begin
|
||||
Msf::Ui::Console::Driver.new(
|
||||
Msf::Ui::Console::Driver::DefaultPrompt,
|
||||
Msf::Ui::Console::Driver::DefaultPromptChar,
|
||||
options
|
||||
).run
|
||||
rescue Interrupt
|
||||
end
|
||||
#
|
||||
# Project
|
||||
#
|
||||
|
||||
# @see https://github.com/rails/rails/blob/v3.2.17/railties/lib/rails/generators/rails/app/templates/script/rails#L3-L5
|
||||
require Pathname.new(__FILE__).expand_path.parent.join('config', 'boot')
|
||||
require 'metasploit/framework/command/console'
|
||||
|
||||
Metasploit::Framework::Command::Console.start
|
||||
|
|
Loading…
Reference in New Issue