From f0001eb9e64308dc77f12a10f6ecb600fa607a47 Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Mon, 3 Nov 2014 08:59:06 -0600 Subject: [PATCH] Extract 'Msf::Simple::Framework#modules loading' MSP-11130 'Msf::Simple::Framework#modules loading' defines `#load_and_create_module`, which takes the :ancestor_reference_names, :modules_path, :module_type, and :reference_name of the module whose ancestors to load and the reference name to create. A default modules path, the first 'modules' path for the Rails application is available in in the `#modules_path` let. --- spec/lib/msf/core/encoded_payload_spec.rb | 37 ++------ .../msf/simple/framework/modules/loading.rb | 94 +++++++++++++++++++ 2 files changed, 101 insertions(+), 30 deletions(-) create mode 100644 spec/support/shared/contexts/msf/simple/framework/modules/loading.rb diff --git a/spec/lib/msf/core/encoded_payload_spec.rb b/spec/lib/msf/core/encoded_payload_spec.rb index 0d9b7b7f19..4e33c39b9d 100644 --- a/spec/lib/msf/core/encoded_payload_spec.rb +++ b/spec/lib/msf/core/encoded_payload_spec.rb @@ -2,30 +2,12 @@ require 'spec_helper' require 'msf/core/encoded_payload' describe Msf::EncodedPayload do - include_context 'Msf::Simple::Framework' - include_context 'Metasploit::Framework::Spec::Constants cleaner' + include_context 'Msf::Simple::Framework#modules loading' let(:ancestor_reference_names) { %w{singles/linux/x86/shell_reverse_tcp} } - let(:loader) { - loader = framework.modules.send(:loaders).find { |loader| - loader.loadable?(modules_path) - } - - # Override load_error so that rspec will print it instead of going to framework log - def loader.load_error(module_path, error) - raise error - end - - loader - } - - let(:modules_path) { - Rails.application.paths['modules'].expanded.first - } - let(:module_type) { 'payload' } @@ -34,18 +16,13 @@ describe Msf::EncodedPayload do 'linux/x86/shell_reverse_tcp' } - let(:module_set) { - framework.modules.module_set(module_type) - } - let(:payload) { - ancestor_reference_names.each do |ancestor_reference_name| - loaded = loader.load_module(modules_path, module_type, ancestor_reference_name) - - expect(loaded).to eq(true), "#{ancestor_reference_name} failed to load from #{modules_path}" - end - - module_set.create(reference_name) + load_and_create_module( + ancestor_reference_names: ancestor_reference_names, + modules_path: modules_path, + module_type: module_type, + reference_name: reference_name + ) } subject(:encoded_payload) do diff --git a/spec/support/shared/contexts/msf/simple/framework/modules/loading.rb b/spec/support/shared/contexts/msf/simple/framework/modules/loading.rb new file mode 100644 index 0000000000..1b0d3ae3cb --- /dev/null +++ b/spec/support/shared/contexts/msf/simple/framework/modules/loading.rb @@ -0,0 +1,94 @@ +shared_context 'Msf::Simple::Framework#modules loading' do + include_context 'Metasploit::Framework::Spec::Constants cleaner' + include_context 'Msf::Simple::Framework' + + # + # Methods + # + + # @param modules_path [String] path to `modules` directory from which to load ancestor reference names. + def loader_for_modules_path(modules_path) + loader = framework.modules.send(:loaders).find { |loader| + loader.loadable?(modules_path) + } + + # Override load_error so that rspec will print it instead of going to framework log + def loader.load_error(module_path, error) + raise error + end + + loader + end + + def expect_to_load_module_ancestor(options={}) + options.assert_valid_keys(:ancestor_reference_name, :modules_path, :module_type) + + ancestor_reference_name = options.fetch(:ancestor_reference_name) + modules_path = options.fetch(:modules_path) + module_type = options.fetch(:module_type) + + loader = loader_for_modules_path(modules_path) + loaded = loader.load_module(modules_path, module_type, ancestor_reference_name) + + expect(loaded).to eq(true), "#{ancestor_reference_name} failed to load from #{modules_path}" + end + + def expect_to_load_module_ancestors(options={}) + options.assert_valid_keys(:ancestor_reference_names, :modules_path, :module_type) + + ancestor_references_names = options.fetch(:ancestor_reference_names) + + ancestor_references_names.each do |ancestor_reference_name| + expect_to_load_module_ancestor( + ancestor_reference_name: ancestor_reference_name, + modules_path: options[:modules_path], + module_type: options[:module_type] + ) + end + end + + # Loads module ancestors with `:module_type` and `:ancestor_reference_names` from `:module_path` and then creates + # module instance with `:module_type` and `:reference_name`. + # + # @param options [Hash{Symbol => Array,}] + # @option options [Array] :ancestor_reference_names the reference names of the ancestor modules for the module + # to be created. Only staged payloads have two ancestors; all other modules, including single payloads, have one + # ancestor. + # @option options [String] :modules_path path to the `modules` directory from which to load + # `:ancestor_reference_names`. + # @option options [String] :module_type the type of module + # @return [Msf::Module] + def load_and_create_module(options={}) + options.assert_valid_keys(:ancestor_reference_names, :modules_path, :module_type, :reference_name) + + ancestor_reference_names = options.fetch(:ancestor_reference_names) + module_type = options.fetch(:module_type) + reference_name = options.fetch(:reference_name) + + expect_to_load_module_ancestors( + options.except(:reference_name) + ) + + module_set = module_set_for_type(module_type) + + module_instance = module_set.create(reference_name) + expect(module_instance).not_to( + be_nil, + "Could not create #{module_type}/#{reference_name} after loading #{ancestor_reference_names.sort.to_sentence}" + ) + + module_instance + end + + def module_set_for_type(module_type) + framework.modules.module_set(module_type) + end + + # + # lets + # + + let(:modules_path) { + Rails.application.paths['modules'].expanded.first + } +end \ No newline at end of file