1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-10-29 18:07:27 +01:00
metasploit-framework/msfcli
sinn3r 0035f2ee64 Speed up msfcli help
If the user only wants to see help, then no point to load things
that will actually never be used by msfcli.  Only rex is needed.
2013-07-22 23:26:44 -05:00

263 lines
7.6 KiB
Ruby
Executable File

#!/usr/bin/env ruby
# -*- coding: binary -*-
#
# $Id$
#
# This user interface allows users to interact with the framework through a
# command line interface (CLI) rather than having to use a prompting console
# or web-based interface.
#
# $Revision$
#
msfbase = __FILE__
while File.symlink?(msfbase)
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
end
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib')))
require 'rex'
Indent = ' '
def usage (str = nil, extra = nil)
tbl = Rex::Ui::Text::Table.new(
'Header' => "Usage: #{$0} <exploit_name> <option=value> [mode]",
'Indent' => 4,
'Columns' => ['Mode', 'Description']
)
tbl << ['(H)elp', "You're looking at it baby!"]
tbl << ['(S)ummary', 'Show information about this module']
tbl << ['(O)ptions', 'Show available options for this module']
tbl << ['(A)dvanced', 'Show available advanced options for this module']
tbl << ['(I)DS Evasion', 'Show available ids evasion options for this module']
tbl << ['(P)ayloads', 'Show available payloads for this module']
tbl << ['(T)argets', 'Show available targets for this exploit module']
tbl << ['(AC)tions', 'Show available actions for this auxiliary module']
tbl << ['(C)heck', 'Run the check routine of the selected module']
tbl << ['(E)xecute', 'Execute the selected module']
$stdout.puts "Error: #{str}\n\n" if str
$stdout.puts tbl.to_s + "\n"
$stdout.puts extra + "\n" if extra
exit
end
# Handle the help option before loading modules
exploit_name = ARGV.shift
exploit = nil
module_class = "exploit"
if(exploit_name == "-h")
usage()
else
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
require 'fastlib'
require 'msfenv'
require 'msf/ui'
require 'msf/base'
end
# Initialize the simplified framework instance.
$stderr.puts "[*] Please wait while we load the module tree..."
$framework = Msf::Simple::Framework.create
if ($framework.modules.module_load_error_by_path.length > 0)
print("Warning: The following modules could not be loaded!\n\n")
$framework.modules.module_load_error_by_path.each do |path, error|
print("\t#{path}: #{error}\n\n")
end
end
if (not exploit_name)
ext = ''
tbl = Rex::Ui::Text::Table.new(
'Header' => 'Exploits',
'Indent' => 4,
'Columns' => [ 'Name', 'Description' ])
$framework.exploits.each_module { |name, mod|
tbl << [ 'exploit/' + name, mod.new.name ]
}
ext << tbl.to_s + "\n"
tbl = Rex::Ui::Text::Table.new(
'Header' => 'Auxiliary',
'Indent' => 4,
'Columns' => [ 'Name', 'Description' ])
$framework.auxiliary.each_module { |name, mod|
tbl << [ 'auxiliary/' + name, mod.new.name ]
}
ext << tbl.to_s + "\n"
usage(nil, ext)
end
# Process special var/val pairs...
Msf::Ui::Common.process_cli_arguments($framework, ARGV)
# Determine what type of module it is
case exploit_name
when /exploit\/(.*)/
exploit = $framework.exploits.create($1)
module_class = 'exploit'
when /auxiliary\/(.*)/
exploit = $framework.auxiliary.create($1)
module_class = 'auxiliary'
else
exploit = $framework.exploits.create(exploit_name)
if exploit == nil
# Try falling back on aux modules
exploit = $framework.auxiliary.create(exploit_name)
module_class = 'auxiliary'
end
end
if (exploit == nil)
usage("Invalid module: #{exploit_name}")
end
exploit.init_ui(
Rex::Ui::Text::Input::Stdio.new,
Rex::Ui::Text::Output::Stdio.new
)
# Evalulate the command (default to "help")
mode = ARGV.pop || 'h'
# Import options
begin
exploit.datastore.import_options_from_s(ARGV.join('_|_'), '_|_')
rescue Rex::ArgumentParseError => e
puts "[!] Error: #{e.message}\n\n"
exit
end
# Initialize associated modules
payload = nil
encoder = nil
nop = nil
if (exploit.datastore['PAYLOAD'])
payload = $framework.payloads.create(exploit.datastore['PAYLOAD'])
if (payload != nil)
payload.datastore.import_options_from_s(ARGV.join('_|_'), '_|_')
end
end
if (exploit.datastore['ENCODER'])
encoder = $framework.encoders.create(exploit.datastore['ENCODER'])
if (encoder != nil)
encoder.datastore.import_options_from_s(ARGV.join('_|_'), '_|_')
end
end
if (exploit.datastore['NOP'])
nop = $framework.nops.create(exploit.datastore['NOP'])
if (nop != nil)
nop.datastore.import_options_from_s(ARGV.join('_|_'), '_|_')
end
end
case mode.downcase
when 'h'
usage
when "s"
$stdout.puts("\n" + Msf::Serializer::ReadableText.dump_module(exploit, Indent))
$stdout.puts("\n" + Msf::Serializer::ReadableText.dump_module(payload, Indent)) if payload
$stdout.puts("\n" + Msf::Serializer::ReadableText.dump_module(encoder, Indent)) if encoder
$stdout.puts("\n" + Msf::Serializer::ReadableText.dump_module(nop, Indent)) if nop
when "o"
$stdout.puts("\n" + Msf::Serializer::ReadableText.dump_options(exploit, Indent))
$stdout.puts("\nPayload:\n\n" + Msf::Serializer::ReadableText.dump_options(payload, Indent)) if payload
$stdout.puts("\nEncoder:\n\n" + Msf::Serializer::ReadableText.dump_options(encoder, Indent)) if encoder
$stdout.puts("\nNOP\n\n" + Msf::Serializer::ReadableText.dump_options(nop, Indent)) if nop
when "a"
$stdout.puts("\n" + Msf::Serializer::ReadableText.dump_advanced_options(exploit, Indent))
$stdout.puts("\nPayload:\n\n" + Msf::Serializer::ReadableText.dump_advanced_options(payload, Indent)) if payload
$stdout.puts("\nEncoder:\n\n" + Msf::Serializer::ReadableText.dump_advanced_options(encoder, Indent)) if encoder
$stdout.puts("\nNOP:\n\n" + Msf::Serializer::ReadableText.dump_advanced_options(nop, Indent)) if nop
when "i"
$stdout.puts("\n" + Msf::Serializer::ReadableText.dump_evasion_options(exploit, Indent))
$stdout.puts("\nPayload:\n\n" + Msf::Serializer::ReadableText.dump_evasion_options(payload, Indent)) if payload
$stdout.puts("\nEncoder:\n\n" + Msf::Serializer::ReadableText.dump_evasion_options(encoder, Indent)) if encoder
$stdout.puts("\nNOP:\n\n" + Msf::Serializer::ReadableText.dump_evasion_options(nop, Indent)) if nop
when "p"
if (module_class == 'exploit')
$stdout.puts("\n" + Msf::Serializer::ReadableText.dump_compatible_payloads(exploit, Indent, "Compatible payloads"))
else
$stdout.puts("\nError: This type of module does not support payloads")
end
when "t"
if (module_class == 'exploit')
$stdout.puts("\n" + Msf::Serializer::ReadableText.dump_exploit_targets(exploit, Indent))
else
$stdout.puts("\nError: This type of module does not support targets")
end
when "ac"
if (module_class == 'auxiliary')
$stdout.puts("\n" + Msf::Serializer::ReadableText.dump_auxiliary_actions(exploit, Indent))
else
$stdout.puts("\nError: This type of module does not support actions")
end
when "c"
if (module_class == 'exploit')
begin
if (code = exploit.check_simple(
'LocalInput' => Rex::Ui::Text::Input::Stdio.new,
'LocalOutput' => Rex::Ui::Text::Output::Stdio.new))
stat = (code == Msf::Exploit::CheckCode::Vulnerable) ? '[+]' : '[*]'
$stdout.puts("#{stat} #{code[1]}")
else
$stderr.puts("Check failed: The state could not be determined.")
end
rescue
$stderr.puts("Check failed: #{$!}")
end
else
$stdout.puts("\nError: This type of module does not support the check feature")
end
when "e"
con = Msf::Ui::Console::Driver.new(
Msf::Ui::Console::Driver::DefaultPrompt,
Msf::Ui::Console::Driver::DefaultPromptChar,
{
'Framework' => $framework
}
)
con.run_single("use #{module_class}/#{exploit.refname}")
ARGV.each do |arg|
k,v = arg.split("=", 2)
con.run_single("set #{k} #{v}")
end
con.run_single("exploit")
# If we have sessions or jobs, keep running
if $framework.sessions.length > 0 or $framework.jobs.length > 0
con.run
else
con.run_single("quit")
end
else
usage("Invalid mode #{mode}")
end
$stdout.puts