refactor for more dry, more compartmentalized code
parent
4ac11d4e70
commit
3e41db6994
|
@ -4,67 +4,36 @@ require 'msf/core/modules/metadata'
|
|||
# Provides search operations on the module metadata cache.
|
||||
#
|
||||
module Msf::Modules::Metadata::Search
|
||||
#
|
||||
# Searches the module metadata using the passed search string.
|
||||
#
|
||||
def find(search_string)
|
||||
search_results = []
|
||||
|
||||
params = parse_search_string(search_string)
|
||||
VALID_PARAMS =
|
||||
%w[app author authors arch cve bid edb date disclosure_date description full_name fullname mod_time name
|
||||
os platform path port rport rank ref ref_name reference references target targets text type]
|
||||
|
||||
#
|
||||
# Searches the module metadata using the passed hash of search params
|
||||
#
|
||||
def find(params, fields={})
|
||||
return [] if params.empty? || VALID_PARAMS.none? { |k| params.key?(k) }
|
||||
search_results = []
|
||||
|
||||
get_metadata.each { |module_metadata|
|
||||
if is_match(params, module_metadata)
|
||||
unless fields.empty?
|
||||
module_metadata = get_fields(module_metadata, fields)
|
||||
end
|
||||
search_results << module_metadata
|
||||
end
|
||||
}
|
||||
|
||||
return search_results
|
||||
end
|
||||
|
||||
# Helper method for private `is_match`
|
||||
def matches(params, module_metadata)
|
||||
is_match(params, module_metadata)
|
||||
end
|
||||
|
||||
#######
|
||||
private
|
||||
#######
|
||||
|
||||
def parse_search_string(search_string)
|
||||
# Split search terms by space, but allow quoted strings
|
||||
terms = search_string.split(/\"/).collect{|term| term.strip==term ? term : term.split(' ')}.flatten
|
||||
terms.delete('')
|
||||
|
||||
# All terms are either included or excluded
|
||||
res = {}
|
||||
|
||||
terms.each do |term|
|
||||
keyword, search_term = term.split(":", 2)
|
||||
unless search_term
|
||||
search_term = keyword
|
||||
keyword = 'text'
|
||||
end
|
||||
next if search_term.length == 0
|
||||
keyword.downcase!
|
||||
search_term.downcase!
|
||||
res[keyword] ||=[ [], [] ]
|
||||
if search_term[0,1] == "-"
|
||||
next if search_term.length == 1
|
||||
res[keyword][1] << search_term[1,search_term.length-1]
|
||||
else
|
||||
res[keyword][0] << search_term
|
||||
end
|
||||
end
|
||||
res
|
||||
end
|
||||
|
||||
def is_match(params, module_metadata)
|
||||
valid_params =
|
||||
%w[app author authors arch cve bid edb date disclosure_date description full_name fullname mod_time name
|
||||
os platform path port rport rank ref ref_name reference references target targets text type]
|
||||
|
||||
return false if params.empty? || valid_params.none? { |k| params.key?(k) }
|
||||
|
||||
param_hash = params
|
||||
|
||||
[0,1].each do |mode|
|
||||
|
@ -174,5 +143,32 @@ module Msf::Modules::Metadata::Search
|
|||
|
||||
true
|
||||
end
|
||||
|
||||
def get_fields(module_metadata, fields)
|
||||
selected_fields = {}
|
||||
|
||||
aliases = {
|
||||
:cve => 'references',
|
||||
:edb => 'references',
|
||||
:bid => 'references',
|
||||
:fullname => 'full_name',
|
||||
:os => 'platform',
|
||||
:port => 'rport',
|
||||
:reference => 'references',
|
||||
:ref => 'ref_name',
|
||||
:target => 'targets',
|
||||
:authors => 'author'
|
||||
}
|
||||
|
||||
fields.each do | field |
|
||||
field = aliases[field.to_sym] if aliases[field.to_sym]
|
||||
if module_metadata.respond_to?(field)
|
||||
selected_fields[field] = module_metadata.send(field)
|
||||
end
|
||||
end
|
||||
selected_fields
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -2,15 +2,9 @@ module Msf::WebServices::ModuleSearch
|
|||
|
||||
def search_modules(opts)
|
||||
raise ::ArgumentError, "At least one search parameter must be provided." if opts.except(:fields).empty?
|
||||
search_results = []
|
||||
metadata = Msf::Modules::Metadata::Cache.instance.get_metadata
|
||||
params = parse_params(opts)
|
||||
metadata.each do | module_metadata |
|
||||
if Msf::Modules::Metadata::Cache.instance.matches(params, module_metadata)
|
||||
search_results << get_fields(opts, module_metadata)
|
||||
end
|
||||
end
|
||||
search_results
|
||||
fields = parse_fields(opts)
|
||||
Msf::Modules::Metadata::Cache.instance.find(params, fields)
|
||||
end
|
||||
|
||||
#######
|
||||
|
@ -39,34 +33,15 @@ module Msf::WebServices::ModuleSearch
|
|||
params
|
||||
end
|
||||
|
||||
def get_fields(opts, module_metadata)
|
||||
selected_fields = {}
|
||||
|
||||
aliases = {
|
||||
:cve => 'references',
|
||||
:edb => 'references',
|
||||
:bid => 'references',
|
||||
:fullname => 'full_name',
|
||||
:os => 'platform',
|
||||
:port => 'rport',
|
||||
:reference => 'references',
|
||||
:ref => 'ref_name',
|
||||
:target => 'targets',
|
||||
:authors => 'author'
|
||||
}
|
||||
|
||||
def parse_fields(opts)
|
||||
fields = []
|
||||
if opts.key? :fields
|
||||
fields = opts[:fields].split(',')
|
||||
fields.each do | field |
|
||||
field.strip!
|
||||
field = aliases[field.to_sym] if aliases[field.to_sym]
|
||||
if module_metadata.respond_to?(field)
|
||||
selected_fields[field] = module_metadata.send(field)
|
||||
end
|
||||
end
|
||||
end
|
||||
selected_fields.empty? ? module_metadata : selected_fields
|
||||
fields
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
|
@ -389,7 +389,8 @@ module Msf
|
|||
|
||||
# Display the table of matches
|
||||
tbl = generate_module_table("Matching Modules", search_term)
|
||||
Msf::Modules::Metadata::Cache.instance.find(match).each do |m|
|
||||
search_params = parse_search_string(match)
|
||||
Msf::Modules::Metadata::Cache.instance.find(search_params).each do |m|
|
||||
tbl << [
|
||||
m.full_name,
|
||||
m.disclosure_date.nil? ? '' : m.disclosure_date.strftime("%Y-%m-%d"),
|
||||
|
@ -409,6 +410,42 @@ module Msf
|
|||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Parses command line search string into a hash
|
||||
#
|
||||
# Resulting Hash Example:
|
||||
# {"platform"=>[["android"], []]} will match modules targeting the android platform
|
||||
# {"platform"=>[[], ["android"]]} will exclude modules targeting the android platform
|
||||
#
|
||||
def parse_search_string(search_string)
|
||||
# Split search terms by space, but allow quoted strings
|
||||
terms = search_string.split(/\"/).collect{|term| term.strip==term ? term : term.split(' ')}.flatten
|
||||
terms.delete('')
|
||||
|
||||
# All terms are either included or excluded
|
||||
res = {}
|
||||
|
||||
terms.each do |term|
|
||||
keyword, search_term = term.split(":", 2)
|
||||
unless search_term
|
||||
search_term = keyword
|
||||
keyword = 'text'
|
||||
end
|
||||
next if search_term.length == 0
|
||||
keyword.downcase!
|
||||
search_term.downcase!
|
||||
res[keyword] ||=[ [], [] ]
|
||||
if search_term[0,1] == "-"
|
||||
next if search_term.length == 1
|
||||
res[keyword][1] << search_term[1,search_term.length-1]
|
||||
else
|
||||
res[keyword][0] << search_term
|
||||
end
|
||||
end
|
||||
res
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Tab completion for the search command
|
||||
#
|
||||
|
|
Loading…
Reference in New Issue