From 5d99eda74b1bf04f638929e03ddeea8889af42c2 Mon Sep 17 00:00:00 2001 From: kalba-security Date: Tue, 29 Sep 2020 18:35:08 -0400 Subject: [PATCH 1/7] Add and command --- lib/msf/base/config.rb | 14 ++ .../ui/console/command_dispatcher/modules.rb | 130 +++++++++++++++++- 2 files changed, 142 insertions(+), 2 deletions(-) diff --git a/lib/msf/base/config.rb b/lib/msf/base/config.rb index 00c9dc1c00c5..92b0614c4cc5 100644 --- a/lib/msf/base/config.rb +++ b/lib/msf/base/config.rb @@ -202,6 +202,13 @@ def self.history_file self.new.history_file end + # Returns the full path to the fav_modules file. + # + # @return [String] path the fav_modules file. + def self.fav_modules_file + self.new.fav_modules_file + end + # Returns the full path to the handler file. # # @return [String] path the handler file. @@ -293,6 +300,13 @@ def history_file config_directory + FileSep + "history" end + # Returns the full path to the fav_modules file. + # + # @return [String] path the fav_modules file. + def fav_modules_file + config_directory + FileSep + "fav_modules" + end + # Returns the full path to the handler file. # # @return [String] path the handler file. diff --git a/lib/msf/ui/console/command_dispatcher/modules.rb b/lib/msf/ui/console/command_dispatcher/modules.rb index db633868b221..dc2525838025 100644 --- a/lib/msf/ui/console/command_dispatcher/modules.rb +++ b/lib/msf/ui/console/command_dispatcher/modules.rb @@ -45,6 +45,7 @@ def commands "search" => "Searches module names and descriptions", "show" => "Displays modules of a given type, or all modules", "use" => "Interact with a module by name or search term/index", + "favorite" => "Add current modules to the list of favorite modules", } end @@ -58,6 +59,7 @@ def initialize(driver) @previous_module = nil @module_name_stack = [] @module_search_results = [] + @module_show_results = [] @@payload_show_results = [] @dangerzone_map = nil end @@ -501,7 +503,7 @@ def cmd_search_tabs(str, words) end def cmd_show_help - global_opts = %w{all encoders nops exploits payloads auxiliary post plugins info options} + global_opts = %w{all encoders nops exploits payloads auxiliary post plugins info options favorites} print_status("Valid parameters for the \"show\" command are: #{global_opts.join(", ")}") module_opts = %w{ missing advanced evasion targets actions } @@ -545,6 +547,8 @@ def cmd_show(*args) show_auxiliary when 'post' show_post + when 'favorites' + show_favorites when 'info' cmd_info(*args[1, args.length]) when 'options' @@ -611,7 +615,7 @@ def cmd_show(*args) def cmd_show_tabs(str, words) return [] if words.length > 1 - res = %w{all encoders nops exploits payloads auxiliary post plugins options} + res = %w{all encoders nops exploits payloads auxiliary post plugins options favorites} if (active_module) res.concat %w{missing advanced evasion targets actions info} if (active_module.respond_to? :compatible_sessions) @@ -971,6 +975,106 @@ def cmd_back(*args) driver.destack_dispatcher end end + + def cmd_favorite_help + print_line 'Usage: favorite [mod1 mod2 ...]' + print_line + print_line 'Add current module to the list of favorite modules' + print_line + print_line "OPTIONS:" + print_line " -d Delete the provided module(s) from the fav_modules file" + print_line " -D Delete the fav_modules file" + end + + # + # Helper method for cmd_favorite that writes modules to the fav_modules_file + # + def cmd_favorite_process(mod, del) + favs_file = Msf::Config.fav_modules_file + if File.exists?(favs_file) + unless File.readable?(favs_file) + print_error("Unable to read #{favs_file}") + return false + end + + contents = File.read(favs_file) + if contents.include?(mod.fullname) + unless del + print_warning("Module #{mod.fullname} has already been favorited and will not be added to #{favs_file}") + return + end + + # remove module from contents (deletion happens below) + contents = contents.split("\n") + contents.delete(mod.fullname) + + else + return if del #do nothing if fav_modules does not contain the module we need to delete + end + else + return if del + end + + # finally, start adding/deleting stuff + begin + if del + write_mode = 'w' + contents = contents.join("\n") + message = "Removed #{mod.fullname} from #{favs_file}" + else + write_mode = 'a+' + contents = mod.fullname + message = "Added #{mod.fullname} to #{favs_file}" + end + File.open(favs_file, write_mode) do |file| + file.puts(contents) + end + rescue Errno::EACCES => e + print_error("Unable to write to #{favs_file}") + return false + end + print_status("#{message}") + return true + end + + # + # Add modules to the fav_modules file + # + def cmd_favorite(*args) + favs_file = Msf::Config.fav_modules_file + del = false + + if args.include?('-D') + args.delete('-D') + print_status("Removing #{favs_file} if it exists") + File.delete(favs_file) if File.exist?(favs_file) + return + end + + if args.include?('-d') + args.delete('-d') + del = true + end + + if args.empty? + if (active_module) + cmd_favorite_process(active_module, del) + else + print_error('No module active') + return false + end + end + + args.each { |name| + mod = framework.modules.create(name) + + if (mod == nil) + print_error("Invalid module: #{name}") + else + cmd_favorite_process(mod, del) + end + } + end # # Tab complete module names @@ -1106,6 +1210,28 @@ def show_post(regex = nil, minrank = nil, opts = nil) # :nodoc: show_module_set("Post", framework.post, regex, minrank, opts) end + def show_favorites(regex = nil, minrank = nil, opts = nil) # :nodoc: + favs_file = Msf::Config.fav_modules_file + unless File.exists?(favs_file) && !File.zero?(favs_file) + print_error("#{favs_file} does not exist or is empty") + return + end + + unless File.readable?(favs_file) + print_error("Unable to read from #{favs_file}") + return + end + + # create module set using the saved modules + fav_modules = {} + saved_favs = File.readlines(favs_file) + saved_favs.each do |mod| + module_name = mod.strip + fav_modules[module_name] = framework.modules[module_name] + end + show_module_set("Favorites", fav_modules, regex, minrank, opts) + end + def show_missing(mod) # :nodoc: mod_opt = Serializer::ReadableText.dump_options(mod, ' ', true) print("\nModule options (#{mod.fullname}):\n\n#{mod_opt}\n") if (mod_opt and mod_opt.length > 0) From 26f113d1545184f5793e673be88654c6e8ff07dc Mon Sep 17 00:00:00 2001 From: kalba-security Date: Wed, 30 Sep 2020 08:36:44 -0400 Subject: [PATCH 2/7] Fix help message for the favorite command --- lib/msf/ui/console/command_dispatcher/modules.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/modules.rb b/lib/msf/ui/console/command_dispatcher/modules.rb index dc2525838025..d6b6d3baa0f0 100644 --- a/lib/msf/ui/console/command_dispatcher/modules.rb +++ b/lib/msf/ui/console/command_dispatcher/modules.rb @@ -979,11 +979,12 @@ def cmd_back(*args) def cmd_favorite_help print_line 'Usage: favorite [mod1 mod2 ...]' print_line - print_line 'Add current module to the list of favorite modules' + print_line 'Add one or multiple modules to the list of favorite modules stored in the fav_modules file' + print_line 'If no module name is specified, the command will add the active module if there is one' print_line - print_line "OPTIONS:" - print_line " -d Delete the provided module(s) from the fav_modules file" - print_line " -D Delete the fav_modules file" + print_line 'OPTIONS:' + print_line ' -d Delete the provided module(s) or the active module from the fav_modules file' + print_line ' -D Delete the fav_modules file' end # From 997fc4c7cc01c620420b536d95fb5de13af91b6a Mon Sep 17 00:00:00 2001 From: kalba-security Date: Thu, 1 Oct 2020 14:31:16 -0400 Subject: [PATCH 3/7] Use split without specifying newlines --- lib/msf/ui/console/command_dispatcher/modules.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/ui/console/command_dispatcher/modules.rb b/lib/msf/ui/console/command_dispatcher/modules.rb index d6b6d3baa0f0..34c5f4e9cb17 100644 --- a/lib/msf/ui/console/command_dispatcher/modules.rb +++ b/lib/msf/ui/console/command_dispatcher/modules.rb @@ -1006,7 +1006,7 @@ def cmd_favorite_process(mod, del) end # remove module from contents (deletion happens below) - contents = contents.split("\n") + contents = contents.split contents.delete(mod.fullname) else From ba6dd776f3d807e8a16c8471e34357c6e42193f6 Mon Sep 17 00:00:00 2001 From: kalba-security Date: Tue, 15 Dec 2020 12:22:35 -0500 Subject: [PATCH 4/7] Separate logic for adding and deleting favorite modules into separate functions; improve syntax and error handling --- .../ui/console/command_dispatcher/modules.rb | 147 +++++++++++------- 1 file changed, 91 insertions(+), 56 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/modules.rb b/lib/msf/ui/console/command_dispatcher/modules.rb index 34c5f4e9cb17..86e76809195d 100644 --- a/lib/msf/ui/console/command_dispatcher/modules.rb +++ b/lib/msf/ui/console/command_dispatcher/modules.rb @@ -990,52 +990,71 @@ def cmd_favorite_help # # Helper method for cmd_favorite that writes modules to the fav_modules_file # - def cmd_favorite_process(mod, del) - favs_file = Msf::Config.fav_modules_file - if File.exists?(favs_file) - unless File.readable?(favs_file) - print_error("Unable to read #{favs_file}") - return false + def cmd_favorite_add(modules, favs_file, contents) + modules = modules.uniq # prevent modules from being added more than once + modules.each do |name| + mod = framework.modules.create(name) + if (mod == nil) + print_error("Invalid module: #{name}") + next end - - contents = File.read(favs_file) - if contents.include?(mod.fullname) - unless del - print_warning("Module #{mod.fullname} has already been favorited and will not be added to #{favs_file}") - return - end - # remove module from contents (deletion happens below) - contents = contents.split - contents.delete(mod.fullname) + if contents && contents.include?(mod.fullname) + print_warning("Module #{mod.fullname} has already been favorited and will not be added to #{favs_file}") + next + end - else - return if del #do nothing if fav_modules does not contain the module we need to delete + begin + File.open(favs_file, 'a+') { |file| file.puts(mod.fullname) } + rescue Errno::EACCES => e + print_error("Unable to write to #{favs_file}"). + return end - else - return if del + print_status("Added #{mod.fullname} to #{favs_file}") end + end - # finally, start adding/deleting stuff - begin - if del - write_mode = 'w' - contents = contents.join("\n") - message = "Removed #{mod.fullname} from #{favs_file}" - else - write_mode = 'a+' - contents = mod.fullname - message = "Added #{mod.fullname} to #{favs_file}" + # + # Helper method for cmd_favorite that deletes modules from the fav_modules_file, or deletes the file altogether + # + def cmd_favorite_del(modules, delete_all, favs_file, contents) + if delete_all + print_status("Removing #{favs_file} if it exists") + File.delete(favs_file) if File.exist?(favs_file) + return + end + + modules = modules.uniq # prevent modules from being deleted more than once + contents = contents.split + modules.each do |name| + mod = framework.modules.create(name) + if (mod == nil) + print_error("Invalid module: #{name}") + next end - File.open(favs_file, write_mode) do |file| - file.puts(contents) + + unless contents.include?(mod.fullname) + print_warning("Module #{mod.fullname} cannot be deleted because it is not in #{favs_file}") + next + end + + # remove module from contents + contents.delete(mod.fullname) + print_status("Removing #{mod.fullname} from #{favs_file}") + end + + begin + # delete fav_modules file if removing the module(s) makes it empty + if contents.length == 0 + File.delete(favs_file) + print_status("Removing #{favs_file} since it is empty now") + return end + File.open(favs_file, 'w') { |file| file.puts(contents.join("\n")) } rescue Errno::EACCES => e - print_error("Unable to write to #{favs_file}") - return false + print_error("Unable to write to #{favs_file}"). + return end - print_status("#{message}") - return true end # @@ -1043,38 +1062,54 @@ def cmd_favorite_process(mod, del) # def cmd_favorite(*args) favs_file = Msf::Config.fav_modules_file - del = false - + contents = nil if args.include?('-D') args.delete('-D') - print_status("Removing #{favs_file} if it exists") - File.delete(favs_file) if File.exist?(favs_file) + unless args.empty? + print_error('The -D flag cannot be used with additional arguments') + return + end + cmd_favorite_del(args, true, favs_file, contents) return end - if args.include?('-d') - args.delete('-d') - del = true + # if we want to add or delete individual modules, we need to read the contents of the fav_modules file if it exists + if File.exists?(favs_file) + unless File.readable?(favs_file) + print_error("Unable to read #{favs_file}") + return + end + contents = File.read(favs_file) + else + if args.include?('-d') + print_error("Unable to delete modules from #{favs_file} because the file does not exist") + return + end end if args.empty? - if (active_module) - cmd_favorite_process(active_module, del) - else - print_error('No module active') - return false + unless active_module + print_error('No module has been provided to favorite') + return end + args = [active_module.fullname] + cmd_favorite_add(args, favs_file, contents) + return end - args.each { |name| - mod = framework.modules.create(name) - - if (mod == nil) - print_error("Invalid module: #{name}") - else - cmd_favorite_process(mod, del) + if args.include?('-d') + args.delete('-d') + if args.empty? + unless active_module + print_error('No module has been provided to delete') + return + end + args = [active_module.fullname] end - } + cmd_favorite_del(args, false, favs_file, contents) + return + end + cmd_favorite_add(args, favs_file, contents) end # From 6c14f57057ab7acc815b6418cfb1ebc86ec1bdd3 Mon Sep 17 00:00:00 2001 From: kalba-security Date: Sat, 9 Jan 2021 13:01:33 -0500 Subject: [PATCH 5/7] Use Rex::Parser::Arguments to process options and arguments, change '-D' delete file to '-c' for clearing the contents, change helper method names, add helper method 'favorite_check_fav_modules' --- .../ui/console/command_dispatcher/modules.rb | 174 ++++++++++++------ 1 file changed, 117 insertions(+), 57 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/modules.rb b/lib/msf/ui/console/command_dispatcher/modules.rb index 86e76809195d..66a31da1826d 100644 --- a/lib/msf/ui/console/command_dispatcher/modules.rb +++ b/lib/msf/ui/console/command_dispatcher/modules.rb @@ -29,6 +29,12 @@ class Modules '-u' => [false, 'Use module if there is one result'] ) + @@favorite_opts = Rex::Parser::Arguments.new( + '-h' => [false, 'Help banner'], + '-c' => [false, "Clear the contents of #{Msf::Config.fav_modules_file}"], + '-d' => [false, "Delete module(s) or the current active module from #{Msf::Config.fav_modules_file}"] + ) + def commands { "back" => "Move back from the current context", @@ -979,18 +985,15 @@ def cmd_back(*args) def cmd_favorite_help print_line 'Usage: favorite [mod1 mod2 ...]' print_line - print_line 'Add one or multiple modules to the list of favorite modules stored in the fav_modules file' + print_line "Add one or multiple modules to the list of favorite modules stored in #{Msf::Config.fav_modules_file}" print_line 'If no module name is specified, the command will add the active module if there is one' - print_line - print_line 'OPTIONS:' - print_line ' -d Delete the provided module(s) or the active module from the fav_modules file' - print_line ' -D Delete the fav_modules file' + print @@favorite_opts.usage end # # Helper method for cmd_favorite that writes modules to the fav_modules_file # - def cmd_favorite_add(modules, favs_file, contents) + def favorite_add(modules, favs_file, contents) modules = modules.uniq # prevent modules from being added more than once modules.each do |name| mod = framework.modules.create(name) @@ -1004,23 +1007,19 @@ def cmd_favorite_add(modules, favs_file, contents) next end - begin - File.open(favs_file, 'a+') { |file| file.puts(mod.fullname) } - rescue Errno::EACCES => e - print_error("Unable to write to #{favs_file}"). - return - end + File.open(favs_file, 'a+') { |file| file.puts(mod.fullname) } print_status("Added #{mod.fullname} to #{favs_file}") end + return end # # Helper method for cmd_favorite that deletes modules from the fav_modules_file, or deletes the file altogether # - def cmd_favorite_del(modules, delete_all, favs_file, contents) + def favorite_del(modules, delete_all, favs_file, contents) if delete_all - print_status("Removing #{favs_file} if it exists") - File.delete(favs_file) if File.exist?(favs_file) + print_status("Clearing the contents of #{favs_file}") + File.write(favs_file, '') return end @@ -1043,73 +1042,134 @@ def cmd_favorite_del(modules, delete_all, favs_file, contents) print_status("Removing #{mod.fullname} from #{favs_file}") end - begin - # delete fav_modules file if removing the module(s) makes it empty - if contents.length == 0 - File.delete(favs_file) - print_status("Removing #{favs_file} since it is empty now") - return - end - File.open(favs_file, 'w') { |file| file.puts(contents.join("\n")) } - rescue Errno::EACCES => e - print_error("Unable to write to #{favs_file}"). + # clear the contents of the fav_modules file if removing the module(s) makes it empty + if contents.length == 0 + print_status("Clearing the contents of #{favs_file} because there are no modules left") + File.write(favs_file, '') return end + File.open(favs_file, 'w') { |file| file.puts(contents.join("\n")) } + end + + # + # Helper method for cmd_favorite that checks if the fav_modules file exists and is readable / writable + # + def favorite_check_fav_modules(favs_file) + exists = false + writable = false + readable = false + contents = '' + return_array = [exists, writable, readable, contents] + + return return_array unless File.exists?(favs_file) + + exists = true + + if File.writable?(favs_file) + writable = true + end + + if File.readable?(favs_file) + readable = true + contents = File.read(favs_file) + end + + return_array = [exists, writable, readable, contents] + return return_array end # - # Add modules to the fav_modules file + # Add modules to or delete modules from the fav_modules file # def cmd_favorite(*args) favs_file = Msf::Config.fav_modules_file - contents = nil - if args.include?('-D') - args.delete('-D') - unless args.empty? - print_error('The -D flag cannot be used with additional arguments') - return - end - cmd_favorite_del(args, true, favs_file, contents) + + # always display the help banner if -h is provided or if multiple options are provided + if args.include?('-h') || (args.include?('-c') && args.include?('-d')) + cmd_favorite_help return end - # if we want to add or delete individual modules, we need to read the contents of the fav_modules file if it exists - if File.exists?(favs_file) - unless File.readable?(favs_file) - print_error("Unable to read #{favs_file}") + # obtain useful info about the fav_modules file + exists, writable, readable, contents = favorite_check_fav_modules(favs_file) + + # parse options if any were provided + @@favorite_opts.parse(args) do |opt, i, val| + case opt + when '-c' + args.delete('-c') + unless args.empty? + print_error('Option `-c` does not support arguments. Run `favorite` with `-h` for usage information') + return + end + + case # check file permissions + when !exists + print_warning("#{favs_file} does not exist") + return + when !writable + print_error("Unable to clear #{favs_file} because it is not writable") + return + when contents.empty? + print_warning("#{favs_file} is already empty") + return + end + + favorite_del(args, true, favs_file, contents) return - end - contents = File.read(favs_file) - else - if args.include?('-d') - print_error("Unable to delete modules from #{favs_file} because the file does not exist") + + when '-d' + args.delete('-d') + if args.empty? + unless active_module + print_error('No module has been provided to delete') + return + end + args = [active_module.fullname] + end + + case # check file permissions + when !exists + print_warning("#{favs_file} does not exist") + return + when !writable + print_error("Unable to delete module(s) from #{favs_file} because it is not writable") + return + when !readable + print_error("Unable to delete module(s) from #{favs_file} because it is not readable") + return + when contents.empty? + print_warning("#{favs_file} is empty") + return + end + + favorite_del(args, false, favs_file, contents) return end end + # if we are here, no options were provided and we need to save the active module or the provided module(s) if args.empty? unless active_module - print_error('No module has been provided to favorite') + print_error('No module has been provided to favorite. Run `favorite` with `-h` for usage information') return end args = [active_module.fullname] - cmd_favorite_add(args, favs_file, contents) - return end - if args.include?('-d') - args.delete('-d') - if args.empty? - unless active_module - print_error('No module has been provided to delete') - return - end - args = [active_module.fullname] + # if the fav_modules file exists, check the file permissions + if exists + case + when !writable + print_error("Unable to save module(s) to #{favs_file} because it is not writable") + return + when !readable + print_error("Unable to save module(s) to #{favs_file} because it is not readable") + return end - cmd_favorite_del(args, false, favs_file, contents) - return end - cmd_favorite_add(args, favs_file, contents) + + favorite_add(args, favs_file, contents) end # From f3eb7089852694faa2c8602f1755a8fd719a3fe5 Mon Sep 17 00:00:00 2001 From: kalba-security Date: Mon, 18 Jan 2021 08:38:42 -0500 Subject: [PATCH 6/7] move file permissions checks to favorite_add and favorite_del, print help banner when user input is invalid, do not use parse --- .../ui/console/command_dispatcher/modules.rb | 154 +++++++++--------- 1 file changed, 81 insertions(+), 73 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/modules.rb b/lib/msf/ui/console/command_dispatcher/modules.rb index 66a31da1826d..16e1204838a7 100644 --- a/lib/msf/ui/console/command_dispatcher/modules.rb +++ b/lib/msf/ui/console/command_dispatcher/modules.rb @@ -31,9 +31,9 @@ class Modules @@favorite_opts = Rex::Parser::Arguments.new( '-h' => [false, 'Help banner'], - '-c' => [false, "Clear the contents of #{Msf::Config.fav_modules_file}"], - '-d' => [false, "Delete module(s) or the current active module from #{Msf::Config.fav_modules_file}"] - ) + '-c' => [false, 'Clear the contents of the favorite modules file'], + '-d' => [false, 'Delete module(s) or the current active module from the favorite modules file'] + ) def commands { @@ -51,7 +51,7 @@ def commands "search" => "Searches module names and descriptions", "show" => "Displays modules of a given type, or all modules", "use" => "Interact with a module by name or search term/index", - "favorite" => "Add current modules to the list of favorite modules", + "favorite" => "Add module(s) to the list of favorite modules", } end @@ -993,7 +993,22 @@ def cmd_favorite_help # # Helper method for cmd_favorite that writes modules to the fav_modules_file # - def favorite_add(modules, favs_file, contents) + def favorite_add(modules, favs_file) + # obtain useful info about the fav_modules file + exists, writable, readable, contents = favorite_check_fav_modules(favs_file) + + # if the fav_modules file exists, check the file permissions + if exists + case + when !writable + print_error("Unable to save module(s) to #{favs_file} because it is not writable") + return + when !readable + print_error("Unable to save module(s) to #{favs_file} because it is not readable") + return + end + end + modules = modules.uniq # prevent modules from being added more than once modules.each do |name| mod = framework.modules.create(name) @@ -1014,9 +1029,35 @@ def favorite_add(modules, favs_file, contents) end # - # Helper method for cmd_favorite that deletes modules from the fav_modules_file, or deletes the file altogether + # Helper method for cmd_favorite that deletes modules from the fav_modules_file # - def favorite_del(modules, delete_all, favs_file, contents) + def favorite_del(modules, delete_all, favs_file) + # obtain useful info about the fav_modules file + exists, writable, readable, contents = favorite_check_fav_modules(favs_file) + + if delete_all + custom_message = 'clear the contents of' + else + custom_message = 'delete module(s) from' + end + + case # error handling based on the existence / permissions of the fav_modules file + when !exists + print_warning("Unable to #{custom_message} #{favs_file} because it does not exist") + return + when !writable + print_error("Unable to #{custom_message} #{favs_file} because it is not writable") + return + when !readable + unless delete_all + print_error("Unable to #{custom_message} #{favs_file} because it is not readable") + return + end + when contents.empty? + print_warning("Unable to #{custom_message} #{favs_file} because it is already empty") + return + end + if delete_all print_status("Clearing the contents of #{favs_file}") File.write(favs_file, '') @@ -1090,86 +1131,53 @@ def cmd_favorite(*args) return end - # obtain useful info about the fav_modules file - exists, writable, readable, contents = favorite_check_fav_modules(favs_file) - - # parse options if any were provided - @@favorite_opts.parse(args) do |opt, i, val| - case opt - when '-c' - args.delete('-c') - unless args.empty? - print_error('Option `-c` does not support arguments. Run `favorite` with `-h` for usage information') - return - end + # if no arguments were provided, check if there is an active module to add + if args.empty? + unless active_module + print_error('No module has been provided to favorite.') + cmd_favorite_help + return + end - case # check file permissions - when !exists - print_warning("#{favs_file} does not exist") - return - when !writable - print_error("Unable to clear #{favs_file} because it is not writable") - return - when contents.empty? - print_warning("#{favs_file} is already empty") - return - end + args = [active_module.fullname] + favorite_add(args, favs_file) + return + end - favorite_del(args, true, favs_file, contents) + case args[0] + when '-c' + args.delete('-c') + unless args.empty? + print_error('Option `-c` does not support arguments.') + cmd_favorite_help return + end - when '-d' - args.delete('-d') - if args.empty? - unless active_module - print_error('No module has been provided to delete') - return - end - args = [active_module.fullname] - end + favorite_del(args, true, favs_file) - case # check file permissions - when !exists - print_warning("#{favs_file} does not exist") - return - when !writable - print_error("Unable to delete module(s) from #{favs_file} because it is not writable") - return - when !readable - print_error("Unable to delete module(s) from #{favs_file} because it is not readable") - return - when contents.empty? - print_warning("#{favs_file} is empty") + when '-d' + args.delete('-d') + if args.empty? + unless active_module + print_error('No module has been provided to delete.') + cmd_favorite_help return end - favorite_del(args, false, favs_file, contents) - return + args = [active_module.fullname] end - end - # if we are here, no options were provided and we need to save the active module or the provided module(s) - if args.empty? - unless active_module - print_error('No module has been provided to favorite. Run `favorite` with `-h` for usage information') - return - end - args = [active_module.fullname] - end + favorite_del(args, false, favs_file) - # if the fav_modules file exists, check the file permissions - if exists - case - when !writable - print_error("Unable to save module(s) to #{favs_file} because it is not writable") - return - when !readable - print_error("Unable to save module(s) to #{favs_file} because it is not readable") + else # no valid options, but there are arguments + if args[0].start_with?('-') + print_error('Invalid option provided') + cmd_favorite_help return end - end - favorite_add(args, favs_file, contents) + favorite_add(args, favs_file) + end end # From 8ba02f4c9730cd1c0eef6210b87524987e1db37f Mon Sep 17 00:00:00 2001 From: Shelby Pace Date: Tue, 2 Mar 2021 16:26:01 -0600 Subject: [PATCH 7/7] add module limit, other minor changes --- .../ui/console/command_dispatcher/modules.rb | 60 +++++++++++-------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/modules.rb b/lib/msf/ui/console/command_dispatcher/modules.rb index 16e1204838a7..87fb0981e037 100644 --- a/lib/msf/ui/console/command_dispatcher/modules.rb +++ b/lib/msf/ui/console/command_dispatcher/modules.rb @@ -65,7 +65,6 @@ def initialize(driver) @previous_module = nil @module_name_stack = [] @module_search_results = [] - @module_show_results = [] @@payload_show_results = [] @dangerzone_map = nil end @@ -994,6 +993,7 @@ def cmd_favorite_help # Helper method for cmd_favorite that writes modules to the fav_modules_file # def favorite_add(modules, favs_file) + fav_limit = 50 # obtain useful info about the fav_modules file exists, writable, readable, contents = favorite_check_fav_modules(favs_file) @@ -1001,14 +1001,19 @@ def favorite_add(modules, favs_file) if exists case when !writable - print_error("Unable to save module(s) to #{favs_file} because it is not writable") + print_error("Unable to save module(s) to the favorite modules file because it is not writable") return when !readable - print_error("Unable to save module(s) to #{favs_file} because it is not readable") + print_error("Unable to save module(s) to the favorite modules file because it is not readable") return end end + fav_count = 0 + if contents + fav_count = contents.split.size + end + modules = modules.uniq # prevent modules from being added more than once modules.each do |name| mod = framework.modules.create(name) @@ -1018,12 +1023,18 @@ def favorite_add(modules, favs_file) end if contents && contents.include?(mod.fullname) - print_warning("Module #{mod.fullname} has already been favorited and will not be added to #{favs_file}") + print_warning("Module #{mod.fullname} has already been favorited and will not be added to the favorite modules file") next end + if fav_count >= fav_limit + print_error("Favorite module limit (#{fav_limit}) exceeded. No more modules will be added.") + return + end + File.open(favs_file, 'a+') { |file| file.puts(mod.fullname) } - print_status("Added #{mod.fullname} to #{favs_file}") + print_good("Added #{mod.fullname} to the favorite modules file") + fav_count += 1 end return end @@ -1043,24 +1054,24 @@ def favorite_del(modules, delete_all, favs_file) case # error handling based on the existence / permissions of the fav_modules file when !exists - print_warning("Unable to #{custom_message} #{favs_file} because it does not exist") + print_warning("Unable to #{custom_message} the favorite modules file because it does not exist") return when !writable - print_error("Unable to #{custom_message} #{favs_file} because it is not writable") + print_error("Unable to #{custom_message} the favorite modules file because it is not writable") return when !readable unless delete_all - print_error("Unable to #{custom_message} #{favs_file} because it is not readable") + print_error("Unable to #{custom_message} the favorite modules file because it is not readable") return end when contents.empty? - print_warning("Unable to #{custom_message} #{favs_file} because it is already empty") + print_warning("Unable to #{custom_message} the favorite modules file because it is already empty") return end if delete_all - print_status("Clearing the contents of #{favs_file}") File.write(favs_file, '') + print_good("Favorite modules file cleared") return end @@ -1074,21 +1085,20 @@ def favorite_del(modules, delete_all, favs_file) end unless contents.include?(mod.fullname) - print_warning("Module #{mod.fullname} cannot be deleted because it is not in #{favs_file}") + print_warning("Module #{mod.fullname} cannot be deleted because it is not in the favorite modules file") next end - # remove module from contents contents.delete(mod.fullname) - print_status("Removing #{mod.fullname} from #{favs_file}") + print_status("Removing #{mod.fullname} from the favorite modules file") end # clear the contents of the fav_modules file if removing the module(s) makes it empty if contents.length == 0 - print_status("Clearing the contents of #{favs_file} because there are no modules left") File.write(favs_file, '') return end + File.open(favs_file, 'w') { |file| file.puts(contents.join("\n")) } end @@ -1100,11 +1110,10 @@ def favorite_check_fav_modules(favs_file) writable = false readable = false contents = '' - return_array = [exists, writable, readable, contents] - return return_array unless File.exists?(favs_file) - - exists = true + if File.exists?(favs_file) + exists = true + end if File.writable?(favs_file) writable = true @@ -1115,8 +1124,7 @@ def favorite_check_fav_modules(favs_file) contents = File.read(favs_file) end - return_array = [exists, writable, readable, contents] - return return_array + return exists, writable, readable, contents end # @@ -1154,7 +1162,6 @@ def cmd_favorite(*args) end favorite_del(args, true, favs_file) - when '-d' args.delete('-d') if args.empty? @@ -1168,7 +1175,6 @@ def cmd_favorite(*args) end favorite_del(args, false, favs_file) - else # no valid options, but there are arguments if args[0].start_with?('-') print_error('Invalid option provided') @@ -1316,8 +1322,14 @@ def show_post(regex = nil, minrank = nil, opts = nil) # :nodoc: def show_favorites(regex = nil, minrank = nil, opts = nil) # :nodoc: favs_file = Msf::Config.fav_modules_file - unless File.exists?(favs_file) && !File.zero?(favs_file) - print_error("#{favs_file} does not exist or is empty") + + unless File.exists?(favs_file) + print_error("The favorite modules file does not exist") + return + end + + if File.zero?(favs_file) + print_warning("The favorite modules file is empty") return end