86 lines
3.3 KiB
Ruby
86 lines
3.3 KiB
Ruby
|
#!/usr/bin/env ruby
|
||
|
|
||
|
# Reads untest payload modules from log/untested-payloads.log (which can be produced by running `rake spec`) and prints
|
||
|
# the statements that need to be added to `spec/modules/payloads_spec.rb`. **Note: this script depends on the payload
|
||
|
# being loadable, so if module is not loadable, then the developer must manually determine which single needs to be tested
|
||
|
# or which combinations of stages and stagers need to be tested.**
|
||
|
|
||
|
msfbase = __FILE__
|
||
|
while File.symlink?(msfbase)
|
||
|
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
|
||
|
end
|
||
|
|
||
|
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', 'lib')))
|
||
|
require 'msfenv'
|
||
|
require 'msf/core'
|
||
|
require 'msf/base'
|
||
|
|
||
|
framework = Msf::Simple::Framework.create()
|
||
|
|
||
|
options_set_by_ancestor_reference_name = Hash.new { |hash, ancestor_reference_name|
|
||
|
hash[ancestor_reference_name] = Set.new
|
||
|
}
|
||
|
|
||
|
framework.payloads.each { |reference_name, payload_class|
|
||
|
module_ancestors = payload_class.ancestors.select { |ancestor|
|
||
|
# need to use try because name may be nil for anonymous Modules
|
||
|
ancestor.name.try(:start_with?, 'Msf::Modules::')
|
||
|
}
|
||
|
ancestor_reference_names = module_ancestors.map { |module_ancestor|
|
||
|
unpacked_module_ancestor_full_name = module_ancestor.name.sub(/^Msf::Modules::Mod/, '')
|
||
|
.sub(/::Metasploit\d+/, '')
|
||
|
module_ancestor_full_name = [unpacked_module_ancestor_full_name].pack("H*")
|
||
|
module_ancestor_full_name.sub(%r{^payload/}, '')
|
||
|
}
|
||
|
|
||
|
options = {
|
||
|
reference_name: reference_name,
|
||
|
ancestor_reference_names: ancestor_reference_names
|
||
|
}
|
||
|
|
||
|
# record for both ancestor_reference_names as which is untested is not known here
|
||
|
ancestor_reference_names.each do |ancestor_reference_name|
|
||
|
options_set_by_ancestor_reference_name[ancestor_reference_name].add options
|
||
|
end
|
||
|
}
|
||
|
|
||
|
tested_options = Set.new
|
||
|
|
||
|
$stderr.puts "Add the following context to `spec/modules/payloads_spec.rb` by inserting them in lexical order between the pre-existing contexts:"
|
||
|
|
||
|
File.open('log/untested-payloads.log') { |f|
|
||
|
f.each_line do |line|
|
||
|
ancestor_reference_name = line.strip
|
||
|
|
||
|
options_set = options_set_by_ancestor_reference_name[ancestor_reference_name]
|
||
|
|
||
|
options_set.each do |options|
|
||
|
# don't print a needed test twice
|
||
|
unless tested_options.include? options
|
||
|
reference_name = options[:reference_name]
|
||
|
|
||
|
$stderr.puts
|
||
|
$stderr.puts " context '#{reference_name}' do\n" \
|
||
|
" it_should_behave_like 'payload can be instantiated',\n" \
|
||
|
" ancestor_reference_name: ["
|
||
|
|
||
|
ancestor_reference_names = options[:ancestor_reference_names]
|
||
|
|
||
|
if ancestor_reference_names.length == 1
|
||
|
$stderr.puts " '#{ancestor_reference_names[0]}'"
|
||
|
else
|
||
|
$stderr.puts " '#{ancestor_reference_names[0]}',"
|
||
|
$stderr.puts " '#{ancestor_reference_names[1]}'"
|
||
|
end
|
||
|
|
||
|
$stderr.puts " ],\n" \
|
||
|
" modules_pathname: modules_pathname,\n" \
|
||
|
" reference_name: '#{reference_name}'\n" \
|
||
|
" end"
|
||
|
|
||
|
tested_options.add options
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
}
|