Land #8511, console search options

lands sempervictus' console search command
enahncements and bug fixes
bug/bundler_fix
David Maloney 2017-06-22 12:07:10 -05:00
commit 3a445655ae
No known key found for this signature in database
GPG Key ID: DEDBA9DC3A913DB2
7 changed files with 150 additions and 73 deletions

View File

@ -51,6 +51,7 @@ class Core
"-r" => [ false, "Reset the ring buffer for the session given with -i, or all" ],
"-u" => [ true, "Upgrade a shell to a meterpreter session on many platforms" ],
"-t" => [ true, "Set a response timeout (default: 15)" ],
"-S" => [ true, "Row search filter." ],
"-x" => [ false, "Show extended information in the session table" ])
@@threads_opts = Rex::Parser::Arguments.new(
@ -85,6 +86,10 @@ class Core
"-k" => [ true, "Keep (include) arg lines at start of output." ],
"-c" => [ false, "Only print a count of matching lines." ])
@@search_opts = Rex::Parser::Arguments.new(
"-h" => [ false, "Help banner." ],
"-S" => [ true, "Row search filter." ])
@@history_opts = Rex::Parser::Arguments.new(
"-h" => [ false, "Help banner." ],
"-a" => [ false, "Show all commands in history." ],
@ -95,7 +100,6 @@ class Core
"-h" => [ false, "Help banner." ],
"-e" => [ true, "Expression to evaluate." ])
# Returns the list of commands supported by this command dispatcher
def commands
{
@ -171,9 +175,6 @@ class Core
driver.update_prompt
end
def cmd_cd_help
print_line "Usage: cd <directory>"
print_line
@ -869,10 +870,12 @@ class Core
when "add", "remove", "del"
subnet = args.shift
netmask = nil
if subnet
subnet, cidr_mask = subnet.split("/")
netmask = Rex::Socket.addr_ctoa(cidr_mask.to_i) if cidr_mask
subnet,cidr_mask = subnet.split("/")
if Rex::Socket.is_ipv4?(args.first)
netmask = args.shift
else
cidr_mask = '32' if cidr_mask.nil?
netmask = Rex::Socket.addr_ctoa(cidr_mask.to_i)
end
netmask = args.shift if netmask.nil?
@ -1074,7 +1077,6 @@ class Core
print_line("Saved configuration to: #{Msf::Config.config_file}")
end
def cmd_spool_help
print_line "Usage: spool <off>|<filename>"
print_line
@ -1139,6 +1141,7 @@ class Core
script = nil
reset_ring = false
response_timeout = 15
search_term = nil
# any arguments that don't correspond to an option or option arg will
# be put in here
@ -1151,53 +1154,58 @@ class Core
# Parse the command options
@@sessions_opts.parse(args) do |opt, idx, val|
case opt
when '-q'
when "-q"
quiet = true
# Run a command on all sessions, or the session given with -i
when '-c'
when "-c"
method = 'cmd'
cmds << val if val
when '-C'
when "-C"
method = 'meterp-cmd'
cmds << val if val
when '-x'
when "-x"
show_extended = true
when '-v'
when "-v"
verbose = true
# Do something with the supplied session identifier instead of
# all sessions.
when '-i'
when "-i"
sid = val
# Display the list of active sessions
when '-l'
when "-l"
method = 'list'
when '-k'
when "-k"
method = 'kill'
sid = val || false
when '-K'
when "-K"
method = 'killall'
# Run a script on all meterpreter sessions
when '-s'
when "-s"
unless script
method = 'scriptall'
script = val
end
# Upload and exec to the specific command session
when '-u'
when "-u"
method = 'upexec'
sid = val || false
# Search for specific session
when "-S", "--search"
search_term = val
# Reset the ring buffer read pointer
when '-r'
when "-r"
reset_ring = true
method = 'reset_ring'
# Display help banner
when '-h'
when "-h"
cmd_sessions_help
return false
when '-t'
when "-t"
if val.to_s =~ /^\d+$/
response_timeout = val.to_i
end
when "-S", "--search"
search_term = val
else
extra << val
end
@ -1463,7 +1471,7 @@ class Core
end
when 'list',nil
print_line
print(Serializer::ReadableText.dump_sessions(framework, :show_extended => show_extended, :verbose => verbose))
print(Serializer::ReadableText.dump_sessions(framework, :show_extended => show_extended, :verbose => verbose, :search_term => search_term))
print_line
end
@ -1952,7 +1960,6 @@ class Core
alias cmd_unsetg_help cmd_unset_help
#
# Returns the revision of the framework and console library
#
@ -2411,7 +2418,6 @@ class Core
return binary_paths.include? Msf::Config.install_root
end
#
# Returns an array of lines at the provided line number plus any before and/or after lines requested
# from all_lines by supplying the +before+ and/or +after+ parameters which are always positive

View File

@ -15,7 +15,7 @@ class Creds
include Msf::Ui::Console::CommandDispatcher
include Metasploit::Credential::Creation
include Msf::Ui::Console::CommandDispatcher::Common
#
# The dispatcher's name.
#
@ -31,11 +31,11 @@ class Creds
"creds" => "List all credentials in the database"
}
end
def allowed_cred_types
%w(password ntlm hash)
end
#
# Returns true if the db is connected, prints an error and returns
# false if not.
@ -51,22 +51,55 @@ class Creds
end
true
end
#
# Miscellaneous option helpers
#
# Parse +arg+ into a {Rex::Socket::RangeWalker} and append the result into +host_ranges+
#
# @note This modifies +host_ranges+ in place
#
# @param arg [String] The thing to turn into a RangeWalker
# @param host_ranges [Array] The array of ranges to append
# @param required [Boolean] Whether an empty +arg+ should be an error
# @return [Boolean] true if parsing was successful or false otherwise
def arg_host_range(arg, host_ranges, required=false)
if (!arg and required)
print_error("Missing required host argument")
return false
end
begin
rw = Rex::Socket::RangeWalker.new(arg)
rescue
print_error("Invalid host parameter, #{arg}.")
return false
end
if rw.valid?
host_ranges << rw
else
print_error("Invalid host parameter, #{arg}.")
return false
end
return true
end
#
# Can return return active or all, on a certain host or range, on a
# certain port or range, and/or on a service name.
#
def cmd_creds(*args)
return unless active?
# Short-circuit help
if args.delete "-h"
cmd_creds_help
return
end
subcommand = args.shift
case subcommand
when 'help'
cmd_creds_help
@ -79,7 +112,7 @@ class Creds
end
end
#
# TODO: this needs to be cleaned up to use the new syntax
#
@ -126,7 +159,7 @@ class Creds
print_line " creds add user:other hash:d19c32489b870735b5f587d76b934283"
print_line " # Add a NonReplayableHash"
print_line " creds add hash:d19c32489b870735b5f587d76b934283"
print_line
print_line "General options"
print_line " -h,--help Show this help information"
@ -156,7 +189,7 @@ class Creds
print_line " creds -d -s smb"
print_line
end
# @param private_type [Symbol] See `Metasploit::Credential::Creation#create_credential`
# @param username [String]
# @param password [String]
@ -168,35 +201,35 @@ class Creds
hsh[opt[0]] = opt[1..-1].join(':') # everything before the first : is the key, reasembling everything after the colon. why ntlm hashes
hsh
end
begin
params.assert_valid_keys('user','password','realm','realm-type','ntlm','ssh-key','hash','address','port','protocol', 'service-name')
rescue ArgumentError => e
print_error(e.message)
end
# Verify we only have one type of private
if params.slice('password','ntlm','ssh-key','hash').length > 1
private_keys = params.slice('password','ntlm','ssh-key','hash').keys
print_error("You can only specify a single Private type. Private types given: #{private_keys.join(', ')}")
return
end
login_keys = params.slice('address','port','protocol','service-name')
if login_keys.any? and login_keys.length < 3
missing_login_keys = ['host','port','proto','service-name'] - login_keys.keys
print_error("Creating a login requires a address, a port, and a protocol. Missing params: #{missing_login_keys}")
return
end
data = {
workspace_id: framework.db.workspace,
origin_type: :import,
filename: 'msfconsole'
}
data[:username] = params['user'] if params.key? 'user'
if params.key? 'realm'
if params.key? 'realm-type'
if Metasploit::Model::Realm::Key::SHORT_NAMES.key? params['realm-type']
@ -235,7 +268,7 @@ class Creds
data[:private_type] = :nonreplayable_hash
data[:private_data] = params['hash']
end
begin
if login_keys.any?
data[:address] = params['address']
@ -250,7 +283,7 @@ class Creds
print_error("Failed to add #{data['private_type']}: #{e}")
end
end
def creds_search(*args)
host_ranges = []
origin_ranges = []
@ -264,6 +297,7 @@ class Creds
cred_table_columns = [ 'host', 'origin' , 'service', 'public', 'private', 'realm', 'private_type' ]
user = nil
delete_count = 0
search_term = nil
while (arg = args.shift)
case arg
@ -314,6 +348,8 @@ class Creds
return
end
arg_host_range(hosts, origin_ranges)
when '-S', '--search-term'
search_term = args.shift
else
# Anything that wasn't an option is a host to search for
unless (arg_host_range(arg, host_ranges))
@ -343,7 +379,8 @@ class Creds
svcs.flatten!
tbl_opts = {
'Header' => "Credentials",
'Columns' => cred_table_columns
'Columns' => cred_table_columns,
'SearchTerm' => search_term
}
tbl = Rex::Text::Table.new(tbl_opts)
@ -481,8 +518,8 @@ class Creds
end
return tabs
end
end
end end end end

View File

@ -15,7 +15,7 @@ class Db
include Msf::Ui::Console::CommandDispatcher
include Msf::Ui::Console::CommandDispatcher::Common
#
# The dispatcher's name.
#
@ -93,7 +93,9 @@ class Db
def cmd_workspace(*args)
return unless active?
search_term = nil
::ActiveRecord::Base.connection_pool.with_connection {
search_term = nil
while (arg = args.shift)
case arg
when '-h','--help'
@ -107,8 +109,10 @@ class Db
delete_all = true
when '-r','--rename'
renaming = true
when '-v'
when '-v','--verbose'
verbose = true
when '-S', '--search'
search_term = args.shift
else
names ||= []
names << arg
@ -178,19 +182,26 @@ class Db
workspace = framework.db.workspace
unless verbose
framework.db.workspaces.each do |ws|
pad = (ws == workspace) ? '* ' : ' '
print_line("#{pad}#{ws.name}")
current = nil
framework.db.workspaces.sort_by {|s| s.name}.each do |s|
if s.name == workspace.name
current = s.name
else
print_line(" #{s.name}")
end
end
print_line("%red* #{current}%clr") unless current.nil?
return
end
workspace = framework.db.workspace
col_names = %w{current name hosts services vulns creds loots notes}
tbl = Rex::Text::Table.new(
'Header' => 'Workspaces',
'Columns' => col_names,
'SortIndex' => -1
'Header' => 'Workspaces',
'Columns' => col_names,
'SortIndex' => -1,
'SearchTerm' => search_term
)
# List workspaces
@ -455,11 +466,16 @@ class Db
return
end
cp_hsh = {}
col_names.map do |col|
cp_hsh[col] = { 'MaxChar' => 52 }
end
# If we got here, we're searching. Delete implies search
tbl = Rex::Text::Table.new(
{
'Header' => "Hosts",
'Columns' => col_names,
'Header' => "Hosts",
'Columns' => col_names,
'ColProps' => cp_hsh,
'SortIndex' => order_by
})
@ -526,7 +542,12 @@ class Db
rhosts << addr
end
if mode == [:delete]
host.destroy
begin
host.destroy
rescue # refs suck
print_error("Forcibly deleting #{host.address}")
host.delete
end
delete_count += 1
end
end
@ -1488,6 +1509,8 @@ class Db
print_status("Usage: db_nmap [--save | [--help | -h]] [nmap options]")
return
end
save = false
arguments = []
while (arg = args.shift)
case arg
@ -1590,7 +1613,7 @@ class Db
print_error(err_line.strip)
end
tabs
return tabs
end
#

View File

@ -34,7 +34,8 @@ module Msf
"-K" => [ false, "Terminate all running jobs." ],
"-i" => [ true, "Lists detailed information about a running job."],
"-l" => [ false, "List all running jobs." ],
"-v" => [ false, "Print more detailed info. Use with -i and -l" ]
"-v" => [ false, "Print more detailed info. Use with -i and -l" ],
"-S" => [ true, "Row search filter." ],
)
def commands
@ -151,6 +152,9 @@ module Msf
# so we can check for the verbose flag.
dump_info = true
job_id = val
when "-S", "--search"
search_term = val
dump_list = true
when "-h"
cmd_jobs_help
return false

View File

@ -22,7 +22,8 @@ module Msf
DISCLOSURE_DATE_FORMAT = "%Y-%m-%d"
@@search_opts = Rex::Parser::Arguments.new(
"-h" => [ false, "Help banner."]
"-h" => [ false, "Help banner."],
"-S" => [ true, "Row search filter."],
)
def commands
@ -381,15 +382,20 @@ module Msf
#
def cmd_search(*args)
match = ''
search_term = nil
@@search_opts.parse(args) { |opt, idx, val|
case opt
when "-t"
print_error("Deprecated option. Use type:#{val} instead")
cmd_search_help
return
when "-S", "--search"
search_term = val
when "-h"
cmd_search_help
return
when "-S"
search_term = val
else
match += val + " "
end
@ -397,7 +403,7 @@ module Msf
if framework.db
if framework.db.migrated && framework.db.modules_cached
search_modules_sql(match)
search_modules_sql(match, search_term)
return
else
print_warning("Module database cache not built yet, using slow search")
@ -406,7 +412,7 @@ module Msf
print_warning("Database not connected, using slow search")
end
tbl = generate_module_table("Matching Modules")
tbl = generate_module_table("Matching Modules", search_term)
[
framework.exploits,
framework.auxiliary,
@ -434,8 +440,8 @@ module Msf
#
# @param (see Msf::DBManager#search_modules)
# @return [void]
def search_modules_sql(search_string)
tbl = generate_module_table("Matching Modules")
def search_modules_sql(search_string, search_term = nil)
tbl = generate_module_table("Matching Modules", search_term)
framework.db.search_modules(search_string).each do |o|
tbl << [ o.fullname, o.disclosure_date.nil? ? "" : o.disclosure_date.strftime(DISCLOSURE_DATE_FORMAT), RankingName[o.rank].to_s, o.name ]
end
@ -1157,13 +1163,14 @@ module Msf
print(tbl.to_s)
end
def generate_module_table(type) # :nodoc:
def generate_module_table(type, search_term = nil) # :nodoc:
Table.new(
Table::Style::Default,
'Header' => type,
'Prefix' => "\n",
'Postfix' => "\n",
'Columns' => [ 'Name', 'Disclosure Date', 'Rank', 'Description' ]
'Header' => type,
'Prefix' => "\n",
'Postfix' => "\n",
'Columns' => [ 'Name', 'Disclosure Date', 'Rank', 'Description' ],
'SearchTerm' => search_term
)
end

View File

@ -288,7 +288,7 @@ RSpec.describe Msf::Ui::Console::CommandDispatcher::Db do
it "should list default workspace" do
db.cmd_workspace
expect(@output).to match_array [
"* default"
"%red* default%clr"
]
end
@ -298,7 +298,7 @@ RSpec.describe Msf::Ui::Console::CommandDispatcher::Db do
db.cmd_workspace
expect(@output).to match_array [
" default",
"* foo"
"%red* foo%clr"
]
end
end

View File

@ -22,7 +22,7 @@ RSpec.describe Msf::Ui::Console::CommandDispatcher::Modules do
end
it 'should generate Matching Modules table' do
expect(core).to receive(:generate_module_table).with('Matching Modules').and_call_original
expect(core).to receive(:generate_module_table).with('Matching Modules', nil).and_call_original
search_modules_sql
end