adds debug command with spec tests
This commit is contained in:
parent
39a5c6aa37
commit
babaee8c8e
|
@ -7,6 +7,7 @@ end
|
|||
require 'rex/ui'
|
||||
require 'msf/ui/banner'
|
||||
require 'msf/ui/tip'
|
||||
require 'msf/ui/debug'
|
||||
require 'msf/ui/driver'
|
||||
require 'msf/ui/common'
|
||||
require 'msf/ui/console'
|
||||
|
|
|
@ -72,6 +72,14 @@ class Core
|
|||
@@tip_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner." ])
|
||||
|
||||
@@debug_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner." ],
|
||||
"-d" => [ false, "Display the Datastore Information." ],
|
||||
"-c" => [ false, "Display command history." ],
|
||||
"-e" => [ false, "Display the most recent Error and Stack Trace." ],
|
||||
"-l" => [ false, "Display the most recent logs." ],
|
||||
"-v" => [ false, "Display versions and install info." ])
|
||||
|
||||
@@connect_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner." ],
|
||||
"-p" => [ true, "List of proxies to use." ],
|
||||
|
@ -103,6 +111,7 @@ class Core
|
|||
"cd" => "Change the current working directory",
|
||||
"connect" => "Communicate with a host",
|
||||
"color" => "Toggle color",
|
||||
"debug" => "Display information useful for debugging",
|
||||
"exit" => "Exit the console",
|
||||
"get" => "Gets the value of a context-specific variable",
|
||||
"getg" => "Gets the value of a global variable",
|
||||
|
@ -291,6 +300,54 @@ class Core
|
|||
|
||||
alias cmd_tip cmd_tips
|
||||
|
||||
|
||||
def cmd_debug_help
|
||||
print_line "Usage: debug [options]"
|
||||
print_line
|
||||
print_line("Print a set of information in a Markdown format to be included when opening an Issue on Github. " +
|
||||
"This information helps us fix problems you encounter and should be included when you open a new issue: " +
|
||||
Debug.issue_link)
|
||||
print @@debug_opts.usage
|
||||
end
|
||||
|
||||
#
|
||||
# Display information useful for debugging errors.
|
||||
#
|
||||
def cmd_debug(*args)
|
||||
if args.empty?
|
||||
print_line Debug.all(framework, driver)
|
||||
return
|
||||
end
|
||||
|
||||
if args.include?("-h")
|
||||
cmd_debug_help
|
||||
else
|
||||
output = ""
|
||||
@@debug_opts.parse(args) do |opt|
|
||||
case opt
|
||||
when '-d'
|
||||
output << Debug.datastore(framework, driver)
|
||||
when '-c'
|
||||
output << Debug.history(driver)
|
||||
when '-e'
|
||||
output << Debug.errors
|
||||
when '-l'
|
||||
output << Debug.logs
|
||||
when '-v'
|
||||
output << Debug.versions(framework)
|
||||
end
|
||||
end
|
||||
|
||||
if output.empty?
|
||||
print_line("Valid argument was not given.")
|
||||
cmd_debug_help
|
||||
else
|
||||
output = Debug.preamble + output
|
||||
print_line output
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_connect_help
|
||||
print_line "Usage: connect [options] <host> <port>"
|
||||
print_line
|
||||
|
|
|
@ -285,9 +285,9 @@ class Driver < Msf::Ui::Driver
|
|||
end
|
||||
|
||||
#
|
||||
# Saves configuration for the console.
|
||||
# Generate configuration for the console.
|
||||
#
|
||||
def save_config
|
||||
def get_config
|
||||
# Build out the console config group
|
||||
group = {}
|
||||
|
||||
|
@ -301,9 +301,23 @@ class Driver < Msf::Ui::Driver
|
|||
end
|
||||
end
|
||||
|
||||
# Save it
|
||||
group
|
||||
end
|
||||
|
||||
def get_config_core
|
||||
ConfigCore
|
||||
end
|
||||
|
||||
def get_config_group
|
||||
ConfigGroup
|
||||
end
|
||||
|
||||
#
|
||||
# Saves configuration for the console.
|
||||
#
|
||||
def save_config
|
||||
begin
|
||||
Msf::Config.save(ConfigGroup => group)
|
||||
Msf::Config.save(ConfigGroup => get_config)
|
||||
rescue ::Exception
|
||||
print_error("Failed to save console config: #{$!}")
|
||||
end
|
||||
|
|
|
@ -0,0 +1,287 @@
|
|||
# -*- coding: binary -*-
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Msf
|
||||
module Ui
|
||||
###
|
||||
#
|
||||
# Displays Metasploit information useful for Debugging.
|
||||
#
|
||||
###
|
||||
module Debug
|
||||
COMMAND_HISTORY_TOTAL = 50
|
||||
ERROR_TOTAL = 10
|
||||
LOG_LINE_TOTAL = 50
|
||||
ISSUE_LINK = 'https://github.com/rapid7/metasploit-framework/issues/new/choose'
|
||||
PREAMBLE = <<~PREMABLE
|
||||
Please provide the below information in any Github issues you open. New issues can be opened here #{ISSUE_LINK.dup}
|
||||
%red%undENSURE YOU HAVE REMOVED ANY SENSITIVE INFORMATION BEFORE SUBMITTING!%clr
|
||||
|
||||
===8<=== CUT AND PASTE EVERYTHING BELOW THIS LINE ===8<===
|
||||
|
||||
|
||||
PREMABLE
|
||||
|
||||
def self.issue_link
|
||||
return ISSUE_LINK.dup
|
||||
end
|
||||
|
||||
def self.preamble
|
||||
return PREAMBLE.dup
|
||||
end
|
||||
|
||||
def self.all(framework, driver)
|
||||
all_information = preamble
|
||||
all_information << datastore(framework, driver)
|
||||
all_information << history(driver)
|
||||
all_information << errors
|
||||
all_information << logs
|
||||
all_information << versions(framework)
|
||||
|
||||
all_information
|
||||
end
|
||||
|
||||
def self.datastore(framework, driver)
|
||||
|
||||
# Generate an ini with the existing config file
|
||||
ini = Rex::Parser::Ini.new(Msf::Config.config_file)
|
||||
|
||||
# Delete all groups from the config ini that potentially have more up to date information
|
||||
ini.keys.each do |key|
|
||||
unless key =~ %r{^framework/database}
|
||||
ini.delete(k)
|
||||
end
|
||||
end
|
||||
|
||||
# Retrieve and add more up to date information
|
||||
add_hash_to_ini_group(ini, framework.datastore, driver.get_config_core)
|
||||
add_hash_to_ini_group(ini, driver.get_config, driver.get_config_group)
|
||||
|
||||
if driver.active_module
|
||||
add_hash_to_ini_group(ini, driver.active_module.datastore.dup, driver.active_module.refname)
|
||||
end
|
||||
|
||||
# Filter credentials
|
||||
ini.each do |key, value|
|
||||
if key =~ %r{^framework/database/}
|
||||
value.transform_values! { '[Filtered]' }
|
||||
end
|
||||
end
|
||||
|
||||
if ini.to_s.empty?
|
||||
content = 'The local config file is empty, no global variables are set, and there is no active module.'
|
||||
else
|
||||
content = ini.to_s
|
||||
end
|
||||
|
||||
build_section(
|
||||
'Module/Datastore',
|
||||
'The following global/module datastore, and database setup was configured before the issue occurred:',
|
||||
content
|
||||
)
|
||||
rescue StandardError => e
|
||||
section_build_error('Failed to extract Datastore', e)
|
||||
end
|
||||
|
||||
def self.history(driver)
|
||||
end_pos = Readline::HISTORY.length - 1
|
||||
start_pos = end_pos - COMMAND_HISTORY_TOTAL > driver.hist_last_saved ? end_pos - (COMMAND_HISTORY_TOTAL - 1) : driver.hist_last_saved
|
||||
|
||||
commands = ''
|
||||
while start_pos <= end_pos
|
||||
# Formats command position in history to 6 characters in length
|
||||
commands += "#{'%-6.6s' % start_pos.to_s} #{Readline::HISTORY[start_pos]}\n"
|
||||
start_pos += 1
|
||||
end
|
||||
|
||||
build_section(
|
||||
'History',
|
||||
'The following commands were ran during the session and before this issue occurred:',
|
||||
commands
|
||||
)
|
||||
rescue StandardError => e
|
||||
section_build_error('Failed to extract History', e)
|
||||
end
|
||||
|
||||
def self.errors
|
||||
|
||||
errors = File.read(File.join(Msf::Config.log_directory, 'framework.log'))
|
||||
|
||||
# Returns any error logs in framework.log file as an array
|
||||
# "[mm/dd/yyyy hh:mm:ss] [e([ANY_NUMBER])]" Indicates the start of an error message
|
||||
# The end of an error message is indicated by the start of the next log message [mm/dd/yyyy hh:mm:ss] [[ANY_LETTER]([ANY_NUMBER])]
|
||||
#
|
||||
#
|
||||
# The below example framework.log will only return three separate errors, and their accompanying traces:
|
||||
#
|
||||
# [05/15/2020 14:13:38] [e(0)] core: [-] Error during IRB: undefined method `[]' for nil:NilClass
|
||||
#
|
||||
# [06/19/2020 12:05:02] [i(0)] core: Trying to continue despite failed database creation: could not connect to server: Connection refused
|
||||
# Is the server running on host "127.0.0.1" and accepting
|
||||
# TCP/IP connections on port 5433?
|
||||
#
|
||||
# [05/15/2020 14:19:20] [e(0)] core: [-] Error while running command debug: can't modify frozen String
|
||||
# Call stack:
|
||||
# /Users/Shared/Relocated_Items/Security/rapid7/metasploit-framework/lib/msf/ui/debug.rb:33:in `get_all'
|
||||
# /Users/Shared/Relocated_Items/Security/rapid7/metasploit-framework/lib/msf/ui/console/command_dispatcher/core.rb:318:in `cmd_debug'
|
||||
# /Users/Shared/Relocated_Items/Security/rapid7/metasploit-framework/lib/rex/ui/text/dispatcher_shell.rb:523:in `run_command'
|
||||
# /Users/Shared/Relocated_Items/Security/rapid7/metasploit-framework/lib/rex/ui/text/dispatcher_shell.rb:474:in `block in run_single'
|
||||
# /Users/Shared/Relocated_Items/Security/rapid7/metasploit-framework/lib/rex/ui/text/dispatcher_shell.rb:468:in `each'
|
||||
# /Users/Shared/Relocated_Items/Security/rapid7/metasploit-framework/lib/rex/ui/text/dispatcher_shell.rb:468:in `run_single'
|
||||
# /Users/Shared/Relocated_Items/Security/rapid7/metasploit-framework/lib/rex/ui/text/shell.rb:158:in `run'
|
||||
# /Users/Shared/Relocated_Items/Security/rapid7/metasploit-framework/lib/metasploit/framework/command/console.rb:48:in `start'
|
||||
# /Users/Shared/Relocated_Items/Security/rapid7/metasploit-framework/lib/metasploit/framework/command/base.rb:82:in `start'
|
||||
#
|
||||
# [06/19/2020 11:51:44] [d(2)] core: Stager osx/armle/reverse_tcp and stage osx/x64/meterpreter have incompatible architectures: armle - x64
|
||||
#
|
||||
# [05/15/2020 14:23:55] [e(0)] core: [-] Error during IRB: undefined method `[]' for nil:NilClass
|
||||
res = errors.scan(%r|\[\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}\] \[e\(\d+\)\] (?:(?!\[\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}\] \[[A-Za-z]\(\d+\)\]).)+|m)
|
||||
|
||||
if res.empty?
|
||||
return build_section(
|
||||
'Errors',
|
||||
'The following errors occurred before the issue occurred:',
|
||||
'The error log file was empty'
|
||||
)
|
||||
end
|
||||
|
||||
# Scan returns each error as a single item array
|
||||
res.flatten!
|
||||
|
||||
errors_str = concat_str_array_from_last_idx(res, ERROR_TOTAL)
|
||||
build_section(
|
||||
'Errors',
|
||||
'The following errors occurred before the issue occurred:',
|
||||
errors_str
|
||||
)
|
||||
rescue StandardError => e
|
||||
section_build_error('Failed to extract Errors', e)
|
||||
|
||||
end
|
||||
|
||||
def self.logs
|
||||
|
||||
log_lines = File.readlines(File.join(Msf::Config.log_directory, 'framework.log'))
|
||||
|
||||
logs_str = concat_str_array_from_last_idx(log_lines, LOG_LINE_TOTAL)
|
||||
|
||||
build_section(
|
||||
'Logs',
|
||||
'The following logs were recorded before the issue occurred:',
|
||||
logs_str
|
||||
)
|
||||
rescue StandardError => e
|
||||
section_build_error('Failed to extract Logs', e)
|
||||
|
||||
end
|
||||
|
||||
def self.versions(framework)
|
||||
|
||||
str = <<~VERSIONS
|
||||
Framework: #{framework.version}
|
||||
Ruby: #{RUBY_DESCRIPTION}
|
||||
Install Root: #{Msf::Config.install_root}
|
||||
Session Type: #{db_connection_info(framework)}
|
||||
Install Method: #{installation_method}
|
||||
VERSIONS
|
||||
|
||||
build_section('Version/Install', 'The versions and install method of your Metasploit setup:', str)
|
||||
rescue StandardError => e
|
||||
section_build_error('Failed to extract Versions', e)
|
||||
end
|
||||
|
||||
class << self
|
||||
|
||||
private
|
||||
|
||||
def add_hash_to_ini_group(ini, hash, group_name)
|
||||
if hash.empty?
|
||||
return
|
||||
end
|
||||
|
||||
unless ini.group?(group_name)
|
||||
ini.add_group(group_name)
|
||||
end
|
||||
|
||||
hash.each_pair do |k, v|
|
||||
ini[group_name][k] = v
|
||||
end
|
||||
end
|
||||
|
||||
def concat_str_array_from_last_idx(array, concat_total)
|
||||
start_pos = array.length > concat_total ? array.length - concat_total : 0
|
||||
end_pos = array.length - 1
|
||||
|
||||
str = array[start_pos..end_pos].join('')
|
||||
|
||||
str.strip
|
||||
end
|
||||
|
||||
# Copy pasta of the print_connection_info method in console/command_dispatcher/db.rb
|
||||
def db_connection_info(framework)
|
||||
unless framework.db.connection_established?
|
||||
return "#{framework.db.driver} selected, no connection"
|
||||
end
|
||||
|
||||
cdb = ''
|
||||
if framework.db.driver == 'http'
|
||||
cdb = framework.db.name
|
||||
else
|
||||
::ActiveRecord::Base.connection_pool.with_connection do |conn|
|
||||
if conn.respond_to?(:current_database)
|
||||
cdb = conn.current_database
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if cdb.empty?
|
||||
output = "Connected Database Name could not be extracted. DB Connection type: #{framework.db.driver}."
|
||||
else
|
||||
output = "Connected to #{cdb}. Connection type: #{framework.db.driver}."
|
||||
end
|
||||
|
||||
output += " Connection name: #{framework.db.get_data_service}." if framework.db.get_data_service
|
||||
|
||||
output
|
||||
end
|
||||
|
||||
def build_section(header_name, blurb, content)
|
||||
<<~SECTION
|
||||
## %grn#{header_name.strip}%clr
|
||||
|
||||
#{blurb.strip}
|
||||
#{with_collapsible_wrapper(content.strip)}
|
||||
|
||||
SECTION
|
||||
end
|
||||
|
||||
def with_collapsible_wrapper(content)
|
||||
<<~WRAPPER
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
#{content}
|
||||
```
|
||||
|
||||
</details>
|
||||
WRAPPER
|
||||
end
|
||||
|
||||
def installation_method
|
||||
if File.exist?(File.join(Msf::Config.install_root, 'version.yml'))
|
||||
'Omnibus Installer'
|
||||
elsif File.directory?(File.join(Msf::Config.install_root, '.git'))
|
||||
'Git Clone'
|
||||
else
|
||||
'Other - Please specify'
|
||||
end
|
||||
end
|
||||
|
||||
def section_build_error(msg, error)
|
||||
"#{msg}: #{error.class} - #{error.message} \n Call stack:\n#{error.backtrace.join("\n")}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -290,8 +290,9 @@ module Shell
|
|||
attr_accessor :on_command_proc
|
||||
attr_accessor :on_print_proc
|
||||
attr_accessor :framework
|
||||
attr_accessor :hist_last_saved # the number of history lines when last saved/loaded
|
||||
|
||||
protected
|
||||
protected
|
||||
|
||||
def supports_color?
|
||||
true
|
||||
|
@ -481,7 +482,6 @@ protected
|
|||
attr_accessor :stop_flag, :cont_prompt # :nodoc:
|
||||
attr_accessor :tab_complete_proc # :nodoc:
|
||||
attr_accessor :histfile # :nodoc:
|
||||
attr_accessor :hist_last_saved # the number of history lines when last saved/loaded
|
||||
attr_accessor :log_source, :stop_count # :nodoc:
|
||||
attr_accessor :local_hostname, :local_username # :nodoc:
|
||||
attr_reader :cont_flag # :nodoc:
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
[framework/database/1]
|
||||
key10=val10
|
||||
key11=val11
|
||||
|
||||
[framework/database/2]
|
||||
key12=val12
|
||||
key13=val13
|
|
@ -0,0 +1,16 @@
|
|||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 1
|
||||
|
||||
[11/11/1111 11:11:11] [e(0)] core: [-] Error 2
|
||||
Call stack:
|
||||
Stack_Trace
|
||||
stack trace
|
||||
STACK-TRACE
|
||||
|
||||
[99/99/9999 99:99:99] [d(0)] NOT_AN_ERROR_TO_BE_IGNORED
|
||||
|
||||
[99/99/9999 99:99:99] [d(0)] NOT_AN_ERROR_TO_BE_IGNORED
|
||||
[99/99/9999 99:99:99] [d(0)] NOT_AN_ERROR_TO_BE_IGNORED
|
||||
[99/99/9999 99:99:99] [d(0)] NOT_AN_ERROR_TO_BE_IGNORED
|
||||
|
||||
|
||||
[22/22/2222 22:22:22] [e(0)] core: [-] Error 3
|
|
@ -0,0 +1,39 @@
|
|||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 1
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 2
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 3
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 4
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 5
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 6
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 7
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 8
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 9
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 10
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 11
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 12
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 13
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 14
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 15
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 16
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 17
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 18
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 19
|
||||
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 20
|
|
@ -0,0 +1,50 @@
|
|||
[00/00/0000 00:00:00] [e(0)] core: Log Line 1
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 2
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 3
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 4
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 5
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 6
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 7
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 8
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 9
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 10
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 11
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 12
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 13
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 14
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 15
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 16
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 17
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 18
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 19
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 20
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 21
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 22
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 23
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 24
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 25
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 26
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 27
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 28
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 29
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 30
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 31
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 32
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 33
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 34
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 35
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 36
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 37
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 38
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 39
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 40
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 41
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 42
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 43
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 44
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 45
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 46
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 47
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 48
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 49
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 50
|
|
@ -0,0 +1,100 @@
|
|||
[00/00/0000 00:00:00] [e(0)] core: Log Line 1
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 2
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 3
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 4
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 5
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 6
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 7
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 8
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 9
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 10
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 11
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 12
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 13
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 14
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 15
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 16
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 17
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 18
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 19
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 20
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 21
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 22
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 23
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 24
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 25
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 26
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 27
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 28
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 29
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 30
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 31
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 32
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 33
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 34
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 35
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 36
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 37
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 38
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 39
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 40
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 41
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 42
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 43
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 44
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 45
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 46
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 47
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 48
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 49
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 50
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 51
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 52
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 53
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 54
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 55
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 56
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 57
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 58
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 59
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 60
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 61
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 62
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 63
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 64
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 65
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 66
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 67
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 68
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 69
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 70
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 71
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 72
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 73
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 74
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 75
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 76
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 77
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 78
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 79
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 80
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 81
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 82
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 83
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 84
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 85
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 86
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 87
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 88
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 89
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 90
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 91
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 92
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 93
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 94
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 95
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 96
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 97
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 98
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 99
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 100
|
|
@ -0,0 +1,30 @@
|
|||
[00/00/0000 00:00:00] [e(0)] core: Log Line 1
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 2
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 3
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 4
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 5
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 6
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 7
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 8
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 9
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 10
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 11
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 12
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 13
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 14
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 15
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 16
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 17
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 18
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 19
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 20
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 21
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 22
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 23
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 24
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 25
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 26
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 27
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 28
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 29
|
||||
[00/00/0000 00:00:00] [e(0)] core: Log Line 30
|
|
@ -0,0 +1,830 @@
|
|||
require 'spec_helper'
|
||||
require 'msf/ui/debug'
|
||||
require 'msf/base/config'
|
||||
require 'msf/ui/console/driver'
|
||||
|
||||
RSpec.describe Msf::Ui::Debug do
|
||||
let(:file_fixtures_path) { File.join(Msf::Config.install_root, 'spec', 'file_fixtures') }
|
||||
|
||||
it 'correctly parses an error log' do
|
||||
allow(::Msf::Config).to receive(:log_directory).and_return(File.join(file_fixtures_path, 'debug', 'error_logs', 'basic'))
|
||||
|
||||
error_log_output = <<~LOG
|
||||
## %grnErrors%clr
|
||||
|
||||
The following errors occurred before the issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
[00/00/0000 00:00:00] [e(0)] core: [-] Error 1
|
||||
|
||||
[11/11/1111 11:11:11] [e(0)] core: [-] Error 2
|
||||
Call stack:
|
||||
Stack_Trace
|
||||
stack trace
|
||||
STACK-TRACE
|
||||
|
||||
[22/22/2222 22:22:22] [e(0)] core: [-] Error 3
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
LOG
|
||||
|
||||
expect(subject.errors).to eql(error_log_output)
|
||||
end
|
||||
|
||||
it 'correctly parses an error log file larger than the log line total' do
|
||||
allow(::Msf::Config).to receive(:log_directory).and_return(File.join(file_fixtures_path, 'debug', 'error_logs', 'long'))
|
||||
|
||||
logs = ''
|
||||
digits = 11..20
|
||||
|
||||
digits.each do |d|
|
||||
logs += "[00/00/0000 00:00:00] [e(0)] core: [-] Error #{d}\n\n"
|
||||
end
|
||||
|
||||
error_log_output = <<~LOG
|
||||
## %grnErrors%clr
|
||||
|
||||
The following errors occurred before the issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
#{logs.strip}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
LOG
|
||||
|
||||
expect(subject.errors).to eql(error_log_output)
|
||||
end
|
||||
|
||||
it 'correctly parses an empty error log file' do
|
||||
allow(::Msf::Config).to receive(:log_directory).and_return(File.join(file_fixtures_path, 'debug', 'error_logs', 'empty'))
|
||||
|
||||
error_log_output = <<~EMPTY
|
||||
## %grnErrors%clr
|
||||
|
||||
The following errors occurred before the issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
The error log file was empty
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
EMPTY
|
||||
|
||||
expect(subject.errors).to eql(error_log_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves and parses a command history shorter than the command total' do
|
||||
stub_const('Readline::HISTORY', Array.new(4) { |i| "Command #{i + 1}" })
|
||||
|
||||
driver = instance_double(
|
||||
Msf::Ui::Console::Driver,
|
||||
hist_last_saved: 0
|
||||
)
|
||||
|
||||
stub_const('Msf::Ui::Debug::COMMAND_HISTORY_TOTAL', 10)
|
||||
|
||||
history_output = <<~E_LOG
|
||||
## %grnHistory%clr
|
||||
|
||||
The following commands were ran during the session and before this issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
0 Command 1
|
||||
1 Command 2
|
||||
2 Command 3
|
||||
3 Command 4
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
E_LOG
|
||||
|
||||
expect(subject.history(driver)).to eql(history_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves and parses a command history equal in length to the command total' do
|
||||
driver = instance_double(
|
||||
::Msf::Ui::Console::Driver,
|
||||
hist_last_saved: 0
|
||||
)
|
||||
|
||||
stub_const('Msf::Ui::Debug::COMMAND_HISTORY_TOTAL', 10)
|
||||
|
||||
stub_const('Readline::HISTORY', Array.new(10) { |i| "Command #{i + 1}" })
|
||||
|
||||
history_output = <<~E_LOG
|
||||
## %grnHistory%clr
|
||||
|
||||
The following commands were ran during the session and before this issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
0 Command 1
|
||||
1 Command 2
|
||||
2 Command 3
|
||||
3 Command 4
|
||||
4 Command 5
|
||||
5 Command 6
|
||||
6 Command 7
|
||||
7 Command 8
|
||||
8 Command 9
|
||||
9 Command 10
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
E_LOG
|
||||
|
||||
expect(subject.history(driver)).to eql(history_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves and parses a command history larger than the command total' do
|
||||
driver = instance_double(
|
||||
::Msf::Ui::Console::Driver,
|
||||
hist_last_saved: 0
|
||||
)
|
||||
|
||||
stub_const('Msf::Ui::Debug::COMMAND_HISTORY_TOTAL', 10)
|
||||
stub_const('Readline::HISTORY', Array.new(15) { |i| "Command #{i + 1}" })
|
||||
|
||||
history_output = <<~E_LOG
|
||||
## %grnHistory%clr
|
||||
|
||||
The following commands were ran during the session and before this issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
5 Command 6
|
||||
6 Command 7
|
||||
7 Command 8
|
||||
8 Command 9
|
||||
9 Command 10
|
||||
10 Command 11
|
||||
11 Command 12
|
||||
12 Command 13
|
||||
13 Command 14
|
||||
14 Command 15
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
E_LOG
|
||||
|
||||
expect(subject.history(driver)).to eql(history_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves and parses a command history larger than the command total and a session command count smaller than the command total' do
|
||||
driver = instance_double(
|
||||
::Msf::Ui::Console::Driver,
|
||||
hist_last_saved: 10
|
||||
)
|
||||
|
||||
stub_const('Msf::Ui::Debug::COMMAND_HISTORY_TOTAL', 10)
|
||||
stub_const('Readline::HISTORY', Array.new(15) { |i| "Command #{i + 1}" })
|
||||
|
||||
history_output = <<~E_LOG
|
||||
## %grnHistory%clr
|
||||
|
||||
The following commands were ran during the session and before this issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
10 Command 11
|
||||
11 Command 12
|
||||
12 Command 13
|
||||
13 Command 14
|
||||
14 Command 15
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
E_LOG
|
||||
|
||||
expect(subject.history(driver)).to eql(history_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves and parses an empty config file and datastore' do
|
||||
allow(::Msf::Config).to receive(:config_file).and_return(File.join(file_fixtures_path, 'debug', 'config_files', 'empty.ini'))
|
||||
|
||||
framework = instance_double(
|
||||
::Msf::Framework,
|
||||
datastore: {}
|
||||
)
|
||||
|
||||
driver = instance_double(
|
||||
::Msf::Ui::Console::Driver,
|
||||
get_config_core: 'config_core',
|
||||
get_config: {},
|
||||
get_config_group: 'config_group',
|
||||
active_module: nil
|
||||
)
|
||||
|
||||
expected_output = <<~OUTPUT
|
||||
## %grnModule/Datastore%clr
|
||||
|
||||
The following global/module datastore, and database setup was configured before the issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
The local config file is empty, no global variables are set, and there is no active module.
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
OUTPUT
|
||||
|
||||
expect(subject.datastore(framework, driver)).to eql(expected_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves and parses a populated global datastore' do
|
||||
allow(::Msf::Config).to receive(:config_file).and_return(File.join(file_fixtures_path, 'debug', 'config_files', 'empty.ini'))
|
||||
|
||||
framework = instance_double(
|
||||
::Msf::Framework,
|
||||
datastore: {
|
||||
'key1' => 'val1',
|
||||
'key2' => 'val2',
|
||||
'key3' => 'val3'
|
||||
}
|
||||
)
|
||||
|
||||
driver = instance_double(
|
||||
::Msf::Ui::Console::Driver,
|
||||
get_config_core: 'group/name/1',
|
||||
get_config: {},
|
||||
get_config_group: 'config_group',
|
||||
active_module: nil
|
||||
)
|
||||
|
||||
expected_output = <<~OUTPUT
|
||||
## %grnModule/Datastore%clr
|
||||
|
||||
The following global/module datastore, and database setup was configured before the issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
[group/name/1]
|
||||
key1=val1
|
||||
key2=val2
|
||||
key3=val3
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
OUTPUT
|
||||
|
||||
expect(subject.datastore(framework, driver)).to eql(expected_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves and parses a populated global datastore and current module' do
|
||||
allow(::Msf::Config).to receive(:config_file).and_return(File.join(file_fixtures_path, 'debug', 'config_files', 'empty.ini'))
|
||||
|
||||
framework = instance_double(
|
||||
::Msf::Framework,
|
||||
datastore: {
|
||||
'key1' => 'val1',
|
||||
'key2' => 'val2',
|
||||
'key3' => 'val3'
|
||||
}
|
||||
)
|
||||
|
||||
driver = instance_double(
|
||||
::Msf::Ui::Console::Driver,
|
||||
get_config_core: 'group/name/1',
|
||||
get_config: {
|
||||
'key4' => 'val4',
|
||||
'key5' => 'val5',
|
||||
'key6' => 'val6'
|
||||
},
|
||||
get_config_group: 'group/name/2',
|
||||
active_module: nil
|
||||
)
|
||||
|
||||
expected_output = <<~OUTPUT
|
||||
## %grnModule/Datastore%clr
|
||||
|
||||
The following global/module datastore, and database setup was configured before the issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
[group/name/1]
|
||||
key1=val1
|
||||
key2=val2
|
||||
key3=val3
|
||||
|
||||
[group/name/2]
|
||||
key4=val4
|
||||
key5=val5
|
||||
key6=val6
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
OUTPUT
|
||||
|
||||
expect(subject.datastore(framework, driver)).to eql(expected_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves and parses active module variables ' do
|
||||
allow(::Msf::Config).to receive(:config_file).and_return(File.join(file_fixtures_path, 'debug', 'config_files', 'empty.ini'))
|
||||
|
||||
framework = instance_double(
|
||||
::Msf::Framework,
|
||||
datastore: {}
|
||||
)
|
||||
|
||||
active_module = instance_double(
|
||||
Msf::Module,
|
||||
datastore: {
|
||||
'key7' => 'val7',
|
||||
'key8' => 'default_val8',
|
||||
'key9' => 'val9'
|
||||
},
|
||||
refname: 'active/module/variables'
|
||||
)
|
||||
|
||||
driver = instance_double(
|
||||
::Msf::Ui::Console::Driver,
|
||||
get_config_core: 'group/name/1',
|
||||
get_config: {},
|
||||
get_config_group: 'config_group',
|
||||
active_module: active_module
|
||||
)
|
||||
|
||||
expected_output = <<~OUTPUT
|
||||
## %grnModule/Datastore%clr
|
||||
|
||||
The following global/module datastore, and database setup was configured before the issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
[active/module/variables]
|
||||
key7=val7
|
||||
key8=default_val8
|
||||
key9=val9
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
OUTPUT
|
||||
|
||||
expect(subject.datastore(framework, driver)).to eql(expected_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves and parses Database information' do
|
||||
allow(::Msf::Config).to receive(:config_file).and_return(File.join(file_fixtures_path, 'debug', 'config_files', 'db.ini'))
|
||||
|
||||
framework = instance_double(
|
||||
::Msf::Framework,
|
||||
datastore: {}
|
||||
)
|
||||
|
||||
driver = instance_double(
|
||||
::Msf::Ui::Console::Driver,
|
||||
get_config_core: 'group/name/1',
|
||||
get_config: {},
|
||||
get_config_group: 'group/name/2',
|
||||
active_module: nil
|
||||
)
|
||||
|
||||
expected_output = <<~OUTPUT
|
||||
## %grnModule/Datastore%clr
|
||||
|
||||
The following global/module datastore, and database setup was configured before the issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
[framework/database/1]
|
||||
key10=[Filtered]
|
||||
key11=[Filtered]
|
||||
|
||||
[framework/database/2]
|
||||
key12=[Filtered]
|
||||
key13=[Filtered]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
OUTPUT
|
||||
|
||||
expect(subject.datastore(framework, driver)).to eql(expected_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves and parses logs shorter than the log line total' do
|
||||
range = 1..30
|
||||
logs = ''
|
||||
range.each do |i|
|
||||
logs += "[00/00/0000 00:00:00] [e(0)] core: Log Line #{i}\n"
|
||||
end
|
||||
|
||||
allow(::Msf::Config).to receive(:log_directory).and_return(File.join(file_fixtures_path, 'debug', 'framework_logs', 'short'))
|
||||
|
||||
error_log_output = <<~E_LOG
|
||||
## %grnLogs%clr
|
||||
|
||||
The following logs were recorded before the issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
#{logs.strip}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
E_LOG
|
||||
|
||||
expect(subject.logs).to eql(error_log_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves and parses logs equal to the log line total' do
|
||||
range = 1..50
|
||||
logs = ''
|
||||
range.each do |i|
|
||||
logs += "[00/00/0000 00:00:00] [e(0)] core: Log Line #{i}\n"
|
||||
end
|
||||
|
||||
allow(::Msf::Config).to receive(:log_directory).and_return(File.join(file_fixtures_path, 'debug', 'framework_logs', 'equal'))
|
||||
|
||||
error_log_output = <<~E_LOG
|
||||
## %grnLogs%clr
|
||||
|
||||
The following logs were recorded before the issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
#{logs.strip}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
E_LOG
|
||||
|
||||
expect(subject.logs).to eql(error_log_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves and parses logs larger than the log line total' do
|
||||
range = 51..100
|
||||
logs = ''
|
||||
range.each do |i|
|
||||
logs += "[00/00/0000 00:00:00] [e(0)] core: Log Line #{i}\n"
|
||||
end
|
||||
|
||||
allow(::Msf::Config).to receive(:log_directory).and_return(File.join(file_fixtures_path, 'debug', 'framework_logs', 'long'))
|
||||
|
||||
error_log_output = <<~E_LOG
|
||||
## %grnLogs%clr
|
||||
|
||||
The following logs were recorded before the issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
#{logs.strip}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
E_LOG
|
||||
|
||||
expect(subject.logs).to eql(error_log_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves and parses an empty log file' do
|
||||
allow(::Msf::Config).to receive(:log_directory).and_return(File.join(file_fixtures_path, 'debug', 'framework_logs', 'empty'))
|
||||
|
||||
error_log_output = <<~E_LOG
|
||||
## %grnLogs%clr
|
||||
|
||||
The following logs were recorded before the issue occurred:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
E_LOG
|
||||
|
||||
expect(subject.logs).to eql(error_log_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves version information with no connected DB' do
|
||||
db = instance_double(
|
||||
Msf::DBManager,
|
||||
connection_established?: false,
|
||||
driver: 'driver'
|
||||
)
|
||||
|
||||
framework = instance_double(
|
||||
::Msf::Framework,
|
||||
version: 'VERSION',
|
||||
db: db
|
||||
)
|
||||
|
||||
allow(::Msf::Config).to receive(:install_root).and_return('bad/path')
|
||||
|
||||
expected_output = <<~OUTPUT
|
||||
## %grnVersion/Install%clr
|
||||
|
||||
The versions and install method of your Metasploit setup:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
Framework: VERSION
|
||||
Ruby: #{RUBY_DESCRIPTION}
|
||||
Install Root: bad/path
|
||||
Session Type: driver selected, no connection
|
||||
Install Method: Other - Please specify
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
OUTPUT
|
||||
|
||||
expect(subject.versions(framework)).to eql(expected_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves version information with DB connected via http' do
|
||||
db = double(
|
||||
'Metasploit::Framework::DataService::DataProxy',
|
||||
name: 'db_name',
|
||||
driver: 'http',
|
||||
connection_established?: true,
|
||||
get_data_service: 'db_data_service'
|
||||
)
|
||||
|
||||
framework = instance_double(
|
||||
::Msf::Framework,
|
||||
version: 'VERSION',
|
||||
db: db
|
||||
)
|
||||
|
||||
allow(::Msf::Config).to receive(:install_root).and_return('bad/path')
|
||||
|
||||
expected_output = <<~OUTPUT
|
||||
## %grnVersion/Install%clr
|
||||
|
||||
The versions and install method of your Metasploit setup:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
Framework: VERSION
|
||||
Ruby: #{RUBY_DESCRIPTION}
|
||||
Install Root: bad/path
|
||||
Session Type: Connected to db_name. Connection type: http. Connection name: db_data_service.
|
||||
Install Method: Other - Please specify
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
OUTPUT
|
||||
|
||||
expect(subject.versions(framework)).to eql(expected_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves version information with DB connected via local connection' do
|
||||
db = double(
|
||||
'Metasploit::Framework::DataService::DataProxy',
|
||||
connection_established?: true,
|
||||
driver: 'local',
|
||||
get_data_service: 'db_data_service'
|
||||
)
|
||||
|
||||
framework = instance_double(
|
||||
::Msf::Framework,
|
||||
version: 'VERSION',
|
||||
db: db
|
||||
)
|
||||
|
||||
connection_pool = instance_double(ActiveRecord::ConnectionAdapters::ConnectionPool)
|
||||
connection = double(
|
||||
'connection',
|
||||
current_database: 'current_db_connection',
|
||||
respond_to?: true
|
||||
)
|
||||
allow(connection_pool).to receive(:with_connection).and_yield(connection)
|
||||
|
||||
allow(::ActiveRecord::Base).to receive(:connection_pool).and_return(connection_pool)
|
||||
allow(::Msf::Config).to receive(:install_root).and_return('bad/path')
|
||||
|
||||
expected_output = <<~OUTPUT
|
||||
## %grnVersion/Install%clr
|
||||
|
||||
The versions and install method of your Metasploit setup:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
Framework: VERSION
|
||||
Ruby: #{RUBY_DESCRIPTION}
|
||||
Install Root: bad/path
|
||||
Session Type: Connected to current_db_connection. Connection type: local. Connection name: db_data_service.
|
||||
Install Method: Other - Please specify
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
OUTPUT
|
||||
|
||||
expect(subject.versions(framework)).to eql(expected_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves version information with no connected DB and a Kali Install' do
|
||||
db = instance_double(
|
||||
Msf::DBManager,
|
||||
connection_established?: false,
|
||||
driver: 'driver'
|
||||
)
|
||||
|
||||
framework = instance_double(
|
||||
::Msf::Framework,
|
||||
version: 'VERSION',
|
||||
db: db
|
||||
)
|
||||
|
||||
allow(::Msf::Config).to receive(:install_root).and_return(File.join(File::SEPARATOR, 'usr', 'share', 'metasploit-framework'))
|
||||
|
||||
expected_output = <<~OUTPUT
|
||||
## %grnVersion/Install%clr
|
||||
|
||||
The versions and install method of your Metasploit setup:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
Framework: VERSION
|
||||
Ruby: #{RUBY_DESCRIPTION}
|
||||
Install Root: #{File.join(File::SEPARATOR, 'usr', 'share', 'metasploit-framework')}
|
||||
Session Type: driver selected, no connection
|
||||
Install Method: Other - Please specify
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
OUTPUT
|
||||
|
||||
expect(subject.versions(framework)).to eql(expected_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves version information with no connected DB and an Omnibus Install' do
|
||||
db = instance_double(
|
||||
Msf::DBManager,
|
||||
connection_established?: false,
|
||||
driver: 'driver'
|
||||
)
|
||||
|
||||
framework = instance_double(
|
||||
::Msf::Framework,
|
||||
version: 'VERSION',
|
||||
db: db
|
||||
)
|
||||
|
||||
allow(::Msf::Config).to receive(:install_root).and_return(File.join(file_fixtures_path, 'debug', 'installs', 'omnibus'))
|
||||
|
||||
expected_output = <<~OUTPUT
|
||||
## %grnVersion/Install%clr
|
||||
|
||||
The versions and install method of your Metasploit setup:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
Framework: VERSION
|
||||
Ruby: #{RUBY_DESCRIPTION}
|
||||
Install Root: #{File.join(file_fixtures_path, 'debug', 'installs', 'omnibus')}
|
||||
Session Type: driver selected, no connection
|
||||
Install Method: Omnibus Installer
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
OUTPUT
|
||||
|
||||
expect(subject.versions(framework)).to eql(expected_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves version information with no connected DB and a Git Clone' do
|
||||
db = instance_double(
|
||||
Msf::DBManager,
|
||||
connection_established?: false,
|
||||
driver: 'driver'
|
||||
)
|
||||
|
||||
framework = instance_double(
|
||||
::Msf::Framework,
|
||||
version: 'VERSION',
|
||||
db: db
|
||||
)
|
||||
|
||||
allow(::Msf::Config).to receive(:install_root).and_return(File.join(file_fixtures_path, 'debug', 'installs'))
|
||||
allow(File).to receive(:directory?).with(File.join(Msf::Config.install_root, '.git')).and_return(true)
|
||||
|
||||
expected_output = <<~OUTPUT
|
||||
## %grnVersion/Install%clr
|
||||
|
||||
The versions and install method of your Metasploit setup:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
Framework: VERSION
|
||||
Ruby: #{RUBY_DESCRIPTION}
|
||||
Install Root: #{File.join(file_fixtures_path, 'debug', 'installs')}
|
||||
Session Type: driver selected, no connection
|
||||
Install Method: Git Clone
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
OUTPUT
|
||||
|
||||
expect(subject.versions(framework)).to eql(expected_output)
|
||||
end
|
||||
|
||||
it 'correctly retrieves version information with no connected DB and a Arch Pacman install' do
|
||||
db = instance_double(
|
||||
Msf::DBManager,
|
||||
connection_established?: false,
|
||||
driver: 'driver'
|
||||
)
|
||||
|
||||
framework = instance_double(
|
||||
::Msf::Framework,
|
||||
version: 'VERSION',
|
||||
db: db
|
||||
)
|
||||
|
||||
allow(::Msf::Config).to receive(:install_root).times.and_return(File.join(File::SEPARATOR, 'opt', 'metasploit'))
|
||||
|
||||
expected_output = <<~OUTPUT
|
||||
## %grnVersion/Install%clr
|
||||
|
||||
The versions and install method of your Metasploit setup:
|
||||
<details>
|
||||
<summary>Collapse</summary>
|
||||
|
||||
```
|
||||
Framework: VERSION
|
||||
Ruby: #{RUBY_DESCRIPTION}
|
||||
Install Root: #{File.join(File::SEPARATOR, 'opt', 'metasploit')}
|
||||
Session Type: driver selected, no connection
|
||||
Install Method: Other - Please specify
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
OUTPUT
|
||||
|
||||
expect(subject.versions(framework)).to eql(expected_output)
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue