tools/missing-payload-tests.rb
MSP-11145 **NOTE: Failing specs** Add a tool for reading `log/untested-payload.log` and `framework.payloads` to determine `context`s to add `spec/modules/payloads_spec.rb` to test the untested payloads.bug/bundler_fix
parent
1df82ea273
commit
c84febea5f
|
@ -44,13 +44,12 @@ module Metasploit
|
|||
untested_payloads_pathname = Pathname.new 'log/untested-payloads.log'
|
||||
|
||||
if untested_payloads_pathname.exist?
|
||||
$stderr.puts "Untested payload detected. Add tests to spec/modules/payload_spec.rb for payloads classes composed of the following payload modules:"
|
||||
tool_path = 'tools/missing-payload-tests.rb'
|
||||
|
||||
untested_payloads_pathname.open do |f|
|
||||
f.each_line do |line|
|
||||
$stderr.write " #{line}"
|
||||
end
|
||||
end
|
||||
$stderr.puts "Untested payload detected. Running `#{tool_path}` to see contexts to add to " \
|
||||
"`spec/modules/payloads_spec.rb` to test those payload ancestor reference names."
|
||||
|
||||
system(tool_path)
|
||||
|
||||
exit 1
|
||||
end
|
||||
|
|
|
@ -31,75 +31,75 @@ describe 'modules/payloads' do
|
|||
modules_pathname: modules_pathname,
|
||||
reference_name: 'aix/ppc/shell_interact'
|
||||
end
|
||||
|
||||
context 'aix/ppc/shell_reverse_tcp' do
|
||||
it_should_behave_like 'payload can be instantiated',
|
||||
ancestor_reference_names: [
|
||||
'singles/aix/ppc/shell_reverse_tcp'
|
||||
],
|
||||
modules_pathname: modules_pathname,
|
||||
reference_name: 'aix/ppc/shell_reverse_tcp'
|
||||
end
|
||||
|
||||
context 'android/meterpreter/reverse_http' do
|
||||
it_should_behave_like 'payload can be instantiated',
|
||||
ancestor_reference_names: [
|
||||
'stagers/android/reverse_http',
|
||||
'stages/android/meterpreter'
|
||||
],
|
||||
modules_pathname: modules_pathname,
|
||||
reference_name: 'android/meterpreter/reverse_http'
|
||||
end
|
||||
|
||||
context 'android/meterpreter/reverse_https' do
|
||||
it_should_behave_like 'payload can be instantiated',
|
||||
ancestor_reference_names: [
|
||||
'stagers/android/reverse_https',
|
||||
'stages/android/meterpreter'
|
||||
],
|
||||
modules_pathname: modules_pathname,
|
||||
reference_name: 'android/meterpreter/reverse_https'
|
||||
end
|
||||
|
||||
context 'android/meterpreter/reverse_tcp' do
|
||||
it_should_behave_like 'payload can be instantiated',
|
||||
ancestor_reference_names: [
|
||||
'stagers/android/reverse_tcp',
|
||||
'stages/android/meterpreter'
|
||||
],
|
||||
modules_pathname: modules_pathname,
|
||||
reference_name: 'android/meterpreter/reverse_tcp'
|
||||
end
|
||||
|
||||
context 'android/shell/reverse_http' do
|
||||
it_should_behave_like 'payload can be instantiated',
|
||||
ancestor_reference_names: [
|
||||
'stagers/android/reverse_http',
|
||||
'stages/android/shell'
|
||||
],
|
||||
modules_pathname: modules_pathname,
|
||||
reference_name: 'android/shell/reverse_http'
|
||||
end
|
||||
|
||||
context 'android/shell/reverse_https' do
|
||||
it_should_behave_like 'payload can be instantiated',
|
||||
ancestor_reference_names: [
|
||||
'stagers/android/reverse_https',
|
||||
'stages/android/shell'
|
||||
],
|
||||
modules_pathname: modules_pathname,
|
||||
reference_name: 'android/shell/reverse_https'
|
||||
end
|
||||
|
||||
context 'android/shell/reverse_tcp' do
|
||||
it_should_behave_like 'payload can be instantiated',
|
||||
ancestor_reference_names: [
|
||||
'stagers/android/reverse_tcp',
|
||||
'stages/android/shell'
|
||||
],
|
||||
modules_pathname: modules_pathname,
|
||||
reference_name: 'android/shell/reverse_tcp'
|
||||
end
|
||||
#
|
||||
# context 'aix/ppc/shell_reverse_tcp' do
|
||||
# it_should_behave_like 'payload can be instantiated',
|
||||
# ancestor_reference_names: [
|
||||
# 'singles/aix/ppc/shell_reverse_tcp'
|
||||
# ],
|
||||
# modules_pathname: modules_pathname,
|
||||
# reference_name: 'aix/ppc/shell_reverse_tcp'
|
||||
# end
|
||||
#
|
||||
# context 'android/meterpreter/reverse_http' do
|
||||
# it_should_behave_like 'payload can be instantiated',
|
||||
# ancestor_reference_names: [
|
||||
# 'stagers/android/reverse_http',
|
||||
# 'stages/android/meterpreter'
|
||||
# ],
|
||||
# modules_pathname: modules_pathname,
|
||||
# reference_name: 'android/meterpreter/reverse_http'
|
||||
# end
|
||||
#
|
||||
# context 'android/meterpreter/reverse_https' do
|
||||
# it_should_behave_like 'payload can be instantiated',
|
||||
# ancestor_reference_names: [
|
||||
# 'stagers/android/reverse_https',
|
||||
# 'stages/android/meterpreter'
|
||||
# ],
|
||||
# modules_pathname: modules_pathname,
|
||||
# reference_name: 'android/meterpreter/reverse_https'
|
||||
# end
|
||||
#
|
||||
# context 'android/meterpreter/reverse_tcp' do
|
||||
# it_should_behave_like 'payload can be instantiated',
|
||||
# ancestor_reference_names: [
|
||||
# 'stagers/android/reverse_tcp',
|
||||
# 'stages/android/meterpreter'
|
||||
# ],
|
||||
# modules_pathname: modules_pathname,
|
||||
# reference_name: 'android/meterpreter/reverse_tcp'
|
||||
# end
|
||||
#
|
||||
# context 'android/shell/reverse_http' do
|
||||
# it_should_behave_like 'payload can be instantiated',
|
||||
# ancestor_reference_names: [
|
||||
# 'stagers/android/reverse_http',
|
||||
# 'stages/android/shell'
|
||||
# ],
|
||||
# modules_pathname: modules_pathname,
|
||||
# reference_name: 'android/shell/reverse_http'
|
||||
# end
|
||||
#
|
||||
# context 'android/shell/reverse_https' do
|
||||
# it_should_behave_like 'payload can be instantiated',
|
||||
# ancestor_reference_names: [
|
||||
# 'stagers/android/reverse_https',
|
||||
# 'stages/android/shell'
|
||||
# ],
|
||||
# modules_pathname: modules_pathname,
|
||||
# reference_name: 'android/shell/reverse_https'
|
||||
# end
|
||||
#
|
||||
# context 'android/shell/reverse_tcp' do
|
||||
# it_should_behave_like 'payload can be instantiated',
|
||||
# ancestor_reference_names: [
|
||||
# 'stagers/android/reverse_tcp',
|
||||
# 'stages/android/shell'
|
||||
# ],
|
||||
# modules_pathname: modules_pathname,
|
||||
# reference_name: 'android/shell/reverse_tcp'
|
||||
# end
|
||||
|
||||
context 'bsd/sparc/shell_bind_tcp' do
|
||||
it_should_behave_like 'payload can be instantiated',
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
#!/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
|
||||
}
|
Loading…
Reference in New Issue