Land #5156 - module ranking properly handles nil
commit
8f5d222e53
|
@ -315,21 +315,40 @@ class Msf::ModuleSet < Hash
|
|||
# @return [Array<Array<String, Class>>] Array of arrays where the inner array is a pair of the module reference name
|
||||
# and the module class.
|
||||
def rank_modules
|
||||
self.mod_ranked = self.sort { |a, b|
|
||||
a_name, a_mod = a
|
||||
b_name, b_mod = b
|
||||
|
||||
# Dynamically loads the module if needed
|
||||
a_mod = create(a_name) if a_mod == Msf::SymbolicModule
|
||||
b_mod = create(b_name) if b_mod == Msf::SymbolicModule
|
||||
|
||||
# Extract the ranking between the two modules
|
||||
a_rank = a_mod.const_defined?('Rank') ? a_mod.const_get('Rank') : Msf::NormalRanking
|
||||
b_rank = b_mod.const_defined?('Rank') ? b_mod.const_get('Rank') : Msf::NormalRanking
|
||||
self.mod_ranked = self.sort { |a_pair, b_pair|
|
||||
a_rank = module_rank(*a_pair)
|
||||
b_rank = module_rank(*b_pair)
|
||||
|
||||
# Compare their relevant rankings. Since we want highest to lowest,
|
||||
# we compare b_rank to a_rank in terms of higher/lower precedence
|
||||
b_rank <=> a_rank
|
||||
}
|
||||
end
|
||||
|
||||
# Retrieves the rank from a loaded, not-yet-loaded, or unloadable Metasploit Module.
|
||||
#
|
||||
# @param reference_name [String] The reference name of the Metasploit Module
|
||||
# @param metasploit_module_class [Class<Msf::Module>, Msf::SymbolicModule] The loaded `Class` for the Metasploit
|
||||
# Module, or {Msf::SymbolicModule} if the Metasploit Module is not loaded yet.
|
||||
# @return [Integer] an `Msf::*Ranking`. `Msf::ManualRanking` if `metasploit_module_class` is `nil` or
|
||||
# {Msf::SymbolicModule} and it could not be loaded by {#create}. Otherwise, the `Rank` constant of the
|
||||
# `metasploit_module_class` or {Msf::NormalRanking} if `metasploit_module_class` does not define `Rank`.
|
||||
def module_rank(reference_name, metasploit_module_class)
|
||||
if metasploit_module_class.nil?
|
||||
Msf::ManualRanking
|
||||
elsif metasploit_module_class == Msf::SymbolicModule
|
||||
# TODO don't create an instance just to get the Class.
|
||||
created_metasploit_module_instance = create(reference_name)
|
||||
|
||||
if created_metasploit_module_instance.nil?
|
||||
module_rank(reference_name, nil)
|
||||
else
|
||||
module_rank(reference_name, created_metasploit_module_instance.class)
|
||||
end
|
||||
elsif metasploit_module_class.const_defined? :Rank
|
||||
metasploit_module_class.const_get :Rank
|
||||
else
|
||||
Msf::NormalRanking
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Msf::ModuleSet do
|
||||
subject(:module_set) {
|
||||
described_class.new(module_type)
|
||||
}
|
||||
|
||||
let(:module_type) {
|
||||
FactoryGirl.generate :mdm_module_detail_mtype
|
||||
}
|
||||
|
||||
context '#rank_modules' do
|
||||
subject(:rank_modules) {
|
||||
module_set.send(:rank_modules)
|
||||
}
|
||||
|
||||
context 'with Msf::SymbolicModule' do
|
||||
before(:each) do
|
||||
module_set['a'] = Msf::SymbolicModule
|
||||
module_set['b'] = Msf::SymbolicModule
|
||||
module_set['c'] = Msf::SymbolicModule
|
||||
end
|
||||
|
||||
context 'create' do
|
||||
#
|
||||
# lets
|
||||
#
|
||||
|
||||
let(:b_class) {
|
||||
Class.new
|
||||
}
|
||||
|
||||
let(:c_class) {
|
||||
Class.new
|
||||
}
|
||||
|
||||
context 'returns nil' do
|
||||
before(:each) do
|
||||
hide_const('A::Rank')
|
||||
allow(module_set).to receive(:create).with('a').and_return(nil)
|
||||
|
||||
stub_const('B', b_class)
|
||||
stub_const('B::Rank', Msf::LowRanking)
|
||||
allow(module_set).to receive(:create).with('b').and_return(b_class.new)
|
||||
|
||||
stub_const('C', c_class)
|
||||
stub_const('C::Rank', Msf::AverageRanking)
|
||||
allow(module_set).to receive(:create).with('c').and_return(c_class.new)
|
||||
end
|
||||
|
||||
specify {
|
||||
expect {
|
||||
rank_modules
|
||||
}.not_to raise_error
|
||||
}
|
||||
|
||||
it 'is ranked as Manual' do
|
||||
expect(rank_modules).to eq(
|
||||
[
|
||||
['c', Msf::SymbolicModule],
|
||||
['b', Msf::SymbolicModule],
|
||||
['a', Msf::SymbolicModule]
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'does not return nil' do
|
||||
#
|
||||
# lets
|
||||
#
|
||||
|
||||
let(:a_class) {
|
||||
Class.new
|
||||
}
|
||||
|
||||
#
|
||||
# Callbacks
|
||||
#
|
||||
|
||||
before(:each) do
|
||||
allow(module_set).to receive(:create).with('a').and_return(a_class.new)
|
||||
allow(module_set).to receive(:create).with('b').and_return(b_class.new)
|
||||
allow(module_set).to receive(:create).with('c').and_return(c_class.new)
|
||||
end
|
||||
|
||||
context 'with Rank' do
|
||||
before(:each) do
|
||||
stub_const('A', a_class)
|
||||
stub_const('A::Rank', Msf::LowRanking)
|
||||
|
||||
stub_const('B', b_class)
|
||||
stub_const('B::Rank', Msf::AverageRanking)
|
||||
|
||||
stub_const('C', c_class)
|
||||
stub_const('C::Rank', Msf::GoodRanking)
|
||||
end
|
||||
|
||||
it 'is ranked using Rank' do
|
||||
expect(rank_modules).to eq(
|
||||
[
|
||||
['c', Msf::SymbolicModule],
|
||||
['b', Msf::SymbolicModule],
|
||||
['a', Msf::SymbolicModule]
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'without Rank' do
|
||||
before(:each) do
|
||||
stub_const('A', a_class)
|
||||
hide_const('A::Rank')
|
||||
|
||||
stub_const('B', b_class)
|
||||
stub_const('B::Rank', Msf::AverageRanking)
|
||||
|
||||
stub_const('C', c_class)
|
||||
stub_const('C::Rank', Msf::GoodRanking)
|
||||
end
|
||||
|
||||
it 'is ranked as Normal' do
|
||||
expect(rank_modules).to eq(
|
||||
[
|
||||
['c', Msf::SymbolicModule],
|
||||
['a', Msf::SymbolicModule],
|
||||
['b', Msf::SymbolicModule]
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without Msf::SymbolicModule' do
|
||||
#
|
||||
# lets
|
||||
#
|
||||
|
||||
let(:a_class) {
|
||||
Class.new
|
||||
}
|
||||
|
||||
let(:b_class) {
|
||||
Class.new
|
||||
}
|
||||
|
||||
let(:c_class) {
|
||||
Class.new
|
||||
}
|
||||
|
||||
#
|
||||
# Callbacks
|
||||
#
|
||||
|
||||
before(:each) do
|
||||
module_set['a'] = a_class
|
||||
module_set['b'] = b_class
|
||||
module_set['c'] = c_class
|
||||
end
|
||||
|
||||
context 'with Rank' do
|
||||
before(:each) do
|
||||
stub_const('A', a_class)
|
||||
stub_const('A::Rank', Msf::LowRanking)
|
||||
|
||||
stub_const('B', b_class)
|
||||
stub_const('B::Rank', Msf::AverageRanking)
|
||||
|
||||
stub_const('C', c_class)
|
||||
stub_const('C::Rank', Msf::GoodRanking)
|
||||
end
|
||||
|
||||
it 'is ranked using Rank' do
|
||||
expect(rank_modules).to eq(
|
||||
[
|
||||
['c', c_class],
|
||||
['b', b_class],
|
||||
['a', a_class]
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'without Rank' do
|
||||
before(:each) do
|
||||
stub_const('A', a_class)
|
||||
hide_const('A::Rank')
|
||||
|
||||
stub_const('B', b_class)
|
||||
stub_const('B::Rank', Msf::AverageRanking)
|
||||
|
||||
stub_const('C', c_class)
|
||||
stub_const('C::Rank', Msf::GoodRanking)
|
||||
end
|
||||
|
||||
it 'is ranked as Normal' do
|
||||
expect(rank_modules).to eq(
|
||||
[
|
||||
['c', c_class],
|
||||
['a', a_class],
|
||||
['b', b_class]
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue