Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/tools/modules/missing_payload_tests.rb
Views: 11767
#!/usr/bin/env ruby12##3# This module requires Metasploit: https://metasploit.com/download4# Current source: https://github.com/rapid7/metasploit-framework5##67#8# Reads untest payload modules from log/untested-payloads.log (which can be produced by running `rake spec`) and prints9# the statements that need to be added to `spec/modules/payloads_spec.rb`. **Note: this script depends on the payload10# being loadable, so if module is not loadable, then the developer must manually determine which single needs to be tested11# or which combinations of stages and stagers need to be tested.**12#1314msfbase = __FILE__15while File.symlink?(msfbase)16msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))17end1819$:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib')))20require 'msfenv'2122framework = Msf::Simple::Framework.create()2324options_set_by_ancestor_reference_name = Hash.new { |hash, ancestor_reference_name|25hash[ancestor_reference_name] = Set.new26}2728framework.payloads.each_module { |reference_name, payload_class|29next unless payload_class30module_ancestors = payload_class.ancestors.select { |ancestor|31# need to use try because name may be nil for anonymous Modules32ancestor.name.try(:start_with?, 'Msf::Modules::')33}34ancestor_reference_names = module_ancestors.map { |module_ancestor|35unpacked_module_ancestor_full_name = module_ancestor.name.sub(/^Msf::Modules::Mod/, '')36.sub(/::MetasploitModule/, '')37module_ancestor_full_name = [unpacked_module_ancestor_full_name].pack("H*")38module_ancestor_full_name.sub(%r{^payload/}, '')39}4041options = {42reference_name: reference_name,43ancestor_reference_names: ancestor_reference_names44}4546# record for both ancestor_reference_names as which is untested is not known here47ancestor_reference_names.each do |ancestor_reference_name|48options_set_by_ancestor_reference_name[ancestor_reference_name].add options49end50}5152tested_options = Set.new5354$stderr.puts "Add the following context to `spec/modules/payloads_spec.rb` by inserting them in lexical order between the pre-existing contexts:"5556File.open('log/untested-payloads.log') { |f|57f.each_line do |line|58ancestor_reference_name = line.strip5960options_set = options_set_by_ancestor_reference_name[ancestor_reference_name]6162options_set.each do |options|63# don't print a needed test twice64unless tested_options.include? options65reference_name = options[:reference_name]6667$stdout.puts68$stdout.puts " context '#{reference_name}' do\n" \69" it_should_behave_like 'payload cached size is consistent',\n" \70" ancestor_reference_names: ["7172ancestor_reference_names = options[:ancestor_reference_names]7374if ancestor_reference_names.length == 175$stdout.puts " '#{ancestor_reference_names[0]}'"76else77$stdout.puts " '#{ancestor_reference_names[1]}',"78$stdout.puts " '#{ancestor_reference_names[0]}'"79end8081$stdout.puts " ],\n" \82" dynamic_size: false,\n" \83" modules_pathname: modules_pathname,\n" \84" reference_name: '#{reference_name}'\n" \85" end"8687tested_options.add options88end89end90end91}929394