Fix Msf::PayloadGenerator spec constant leaks

MSP-11130

Remove the constant PAYLOAD_FRAMEWORK as it leads to a
Msf::Simple::Framework instance that is not cleaned up and loads modules
prior to the beginning of the suite run.
bug/bundler_fix
Luke Imhoff 2014-11-04 09:48:02 -06:00
parent ff0391cdc7
commit 78ea93044b
No known key found for this signature in database
GPG Key ID: 5B1FB01FB33356F8
1 changed files with 136 additions and 55 deletions

View File

@ -2,12 +2,7 @@ require 'spec_helper'
require 'msf/core/payload_generator' require 'msf/core/payload_generator'
describe Msf::PayloadGenerator do describe Msf::PayloadGenerator do
include_context 'Msf::Simple::Framework#modules loading'
PAYLOAD_FRAMEWORK = Msf::Simple::Framework.create(
:module_types => [ ::Msf::MODULE_PAYLOAD, ::Msf::MODULE_ENCODER, ::Msf::MODULE_NOP],
'DisableDatabase' => true,
'DisableLogging' => true
)
let(:lhost) { "192.168.172.1"} let(:lhost) { "192.168.172.1"}
let(:lport) { "8443" } let(:lport) { "8443" }
@ -15,13 +10,18 @@ describe Msf::PayloadGenerator do
let(:add_code) { false } let(:add_code) { false }
let(:arch) { "x86" } let(:arch) { "x86" }
let(:badchars) { "\x20\x0D\x0A" } let(:badchars) { "\x20\x0D\x0A" }
let(:encoder) { 'x86/shikata_ga_nai' } let(:encoder_reference_name) {
# use encoder_module to ensure it is loaded prior to passing to generator
encoder_module.refname
}
let(:format) { "raw" } let(:format) { "raw" }
let(:framework) { PAYLOAD_FRAMEWORK }
let(:iterations) { 1 } let(:iterations) { 1 }
let(:keep) { false } let(:keep) { false }
let(:nops) { 0 } let(:nops) { 0 }
let(:payload) { "windows/meterpreter/reverse_tcp"} let(:payload_reference_name) {
# use payload_module to ensure it is loaded prior to passing to generator
payload_module.refname
}
let(:platform) { "Windows" } let(:platform) { "Windows" }
let(:space) { 1073741824 } let(:space) { 1073741824 }
let(:stdin) { nil } let(:stdin) { nil }
@ -31,25 +31,41 @@ describe Msf::PayloadGenerator do
add_code: add_code, add_code: add_code,
arch: arch, arch: arch,
badchars: badchars, badchars: badchars,
encoder: encoder, encoder: encoder_reference_name,
datastore: datastore, datastore: datastore,
format: format, format: format,
framework: framework, framework: framework,
iterations: iterations, iterations: iterations,
keep: keep, keep: keep,
nops: nops, nops: nops,
payload: payload, payload: payload_reference_name,
platform: platform, platform: platform,
space: space, space: space,
stdin: stdin, stdin: stdin,
template: template template: template
} }
} }
let(:payload_module) { framework.payloads.create(payload)} let(:payload_module) {
load_and_create_module(
ancestor_reference_names: %w{
stagers/windows/reverse_tcp
stages/windows/meterpreter
},
module_type: 'payload',
reference_name: 'windows/meterpreter/reverse_tcp'
)
}
let(:shellcode) { "\x50\x51\x58\x59" } let(:shellcode) { "\x50\x51\x58\x59" }
let(:encoder_module) { framework.encoders.create('x86/shikata_ga_nai') } let(:encoder_module) {
load_and_create_module(
module_type: 'encoder',
reference_name: 'x86/shikata_ga_nai'
)
}
subject(:payload_generator) { described_class.new(generator_opts) } subject(:payload_generator) {
described_class.new(generator_opts)
}
it { should respond_to :add_code } it { should respond_to :add_code }
it { should respond_to :arch } it { should respond_to :arch }
@ -77,13 +93,13 @@ describe Msf::PayloadGenerator do
add_code: add_code, add_code: add_code,
arch: arch, arch: arch,
badchars: badchars, badchars: badchars,
encoder: encoder, encoder: encoder_reference_name,
datastore: datastore, datastore: datastore,
format: format, format: format,
iterations: iterations, iterations: iterations,
keep: keep, keep: keep,
nops: nops, nops: nops,
payload: payload, payload: payload_reference_name,
platform: platform, platform: platform,
space: space, space: space,
stdin: stdin, stdin: stdin,
@ -95,19 +111,19 @@ describe Msf::PayloadGenerator do
end end
context 'when not given a payload' do context 'when not given a payload' do
let(:payload) { nil } let(:payload_reference_name) { nil }
it { should raise_error(ArgumentError, "Invalid Payload Selected") } it { should raise_error(ArgumentError, "Invalid Payload Selected") }
end end
context 'when given an invalid payload' do context 'when given an invalid payload' do
let(:payload) { "beos/meterpreter/reverse_gopher" } let(:payload_reference_name) { "beos/meterpreter/reverse_gopher" }
it { should raise_error(ArgumentError, "Invalid Payload Selected") } it { should raise_error(ArgumentError, "Invalid Payload Selected") }
end end
context 'when given a payload through stdin' do context 'when given a payload through stdin' do
let(:payload) { "stdin" } let(:payload_reference_name) { "stdin" }
it { should_not raise_error } it { should_not raise_error }
end end
@ -230,7 +246,7 @@ describe Msf::PayloadGenerator do
context 'when passing a payload through stdin' do context 'when passing a payload through stdin' do
let(:stdin) { "\x90\x90\x90"} let(:stdin) { "\x90\x90\x90"}
let(:payload) { "stdin" } let(:payload_reference_name) { "stdin" }
context 'when no arch has been selected' do context 'when no arch has been selected' do
let(:arch) { '' } let(:arch) { '' }
@ -330,6 +346,13 @@ describe Msf::PayloadGenerator do
end end
context '#prepend_nops' do context '#prepend_nops' do
before(:each) do
load_and_create_module(
module_type: 'nop',
reference_name: 'x86/opty2'
)
end
context 'when nops are set to 0' do context 'when nops are set to 0' do
it 'returns the unmodified shellcode' do it 'returns the unmodified shellcode' do
expect(payload_generator.prepend_nops(shellcode)).to eq shellcode expect(payload_generator.prepend_nops(shellcode)).to eq shellcode
@ -367,15 +390,41 @@ describe Msf::PayloadGenerator do
end end
context 'when multiple encoders are selected' do context 'when multiple encoders are selected' do
let(:encoder) { "x86/shikata_ga_nai,x86/alpha_mixed"} #
# lets
#
let(:encoder_reference_name) {
encoder_reference_names.join(',')
}
let(:encoder_reference_names) {
%w{
x86/shikata_ga_nai
x86/alpha_mixed
}
}
#
# Callbacks
#
before(:each) do
encoder_reference_names.each do |reference_name|
load_and_create_module(
module_type: 'encoder',
reference_name: reference_name
)
end
end
it 'returns an array of the right size' do it 'returns an array of the right size' do
expect(payload_generator.get_encoders.count).to eq 2 expect(payload_generator.get_encoders.count).to eq 2
end end
it 'returns each of the selected encoders in the array' do it 'returns each of the selected encoders in the array' do
payload_generator.get_encoders.each do |my_encoder| payload_generator.get_encoders.each do |msf_encoder|
expect(encoder_names).to include my_encoder.name expect(encoder_names).to include msf_encoder.name
end end
end end
@ -385,17 +434,17 @@ describe Msf::PayloadGenerator do
end end
context 'when no encoder is selected but badchars are present' do context 'when no encoder is selected but badchars are present' do
let(:encoder) { '' } let(:encoder_reference_name) { '' }
it 'returns an array of all encoders with a compatible arch' do it 'returns an array of all encoders with a compatible arch' do
payload_generator.get_encoders.each do |my_encoder| payload_generator.get_encoders.each do |my_encoder|
expect(my_encoder.arch).to include arch expect(encoder_module.arch).to include arch
end end
end end
end end
context 'when no encoder or badchars are selected' do context 'when no encoder or badchars are selected' do
let(:encoder) { '' } let(:encoder_reference_name) { '' }
let(:badchars) { '' } let(:badchars) { '' }
it 'returns an empty array' do it 'returns an empty array' do
@ -407,9 +456,8 @@ describe Msf::PayloadGenerator do
context '#run_encoder' do context '#run_encoder' do
it 'should call the encoder a number of times equal to the iterations' do it 'should call the encoder a number of times equal to the iterations' do
my_encoder = encoder_module encoder_module.should_receive(:encode).exactly(iterations).times.and_return(shellcode)
my_encoder.should_receive(:encode).exactly(iterations).times.and_return(shellcode) payload_generator.run_encoder(encoder_module, shellcode)
payload_generator.run_encoder(my_encoder, shellcode)
end end
context 'when the encoder makes a buffer too large' do context 'when the encoder makes a buffer too large' do
@ -454,12 +502,21 @@ describe Msf::PayloadGenerator do
let(:format) { 'war' } let(:format) { 'war' }
context 'if the payload is a valid java payload' do context 'if the payload is a valid java payload' do
let(:payload) { "java/meterpreter/reverse_tcp"} let(:payload_module) {
load_and_create_module(
ancestor_reference_names: %w{
stagers/java/reverse_tcp
stages/java/meterpreter
},
module_type: 'payload',
reference_name: 'java/meterpreter/reverse_tcp'
)
}
it 'calls the generate_war on the payload' do it 'calls the generate_war on the payload' do
java_payload = framework.payloads.create("java/meterpreter/reverse_tcp") framework.stub_chain(:payloads, :keys).and_return [payload_reference_name]
framework.stub_chain(:payloads, :keys).and_return ["java/meterpreter/reverse_tcp"] framework.stub_chain(:payloads, :create).and_return(payload_module)
framework.stub_chain(:payloads, :create).and_return(java_payload) payload_module.should_receive(:generate_war).and_call_original
java_payload.should_receive(:generate_war).and_call_original
payload_generator.generate_java_payload payload_generator.generate_java_payload
end end
end end
@ -473,23 +530,40 @@ describe Msf::PayloadGenerator do
let(:format) { 'raw' } let(:format) { 'raw' }
context 'if the payload responds to generate_jar' do context 'if the payload responds to generate_jar' do
let(:payload) { "java/meterpreter/reverse_tcp"} let(:payload_module) {
load_and_create_module(
ancestor_reference_names: %w{
stagers/java/reverse_tcp
stages/java/meterpreter
},
module_type: 'payload',
reference_name: 'java/meterpreter/reverse_tcp'
)
}
it 'calls the generate_jar on the payload' do it 'calls the generate_jar on the payload' do
java_payload = framework.payloads.create("java/meterpreter/reverse_tcp") framework.stub_chain(:payloads, :keys).and_return [payload_reference_name]
framework.stub_chain(:payloads, :keys).and_return ["java/meterpreter/reverse_tcp"] framework.stub_chain(:payloads, :create).and_return(payload_module)
framework.stub_chain(:payloads, :create).and_return(java_payload) payload_module.should_receive(:generate_jar).and_call_original
java_payload.should_receive(:generate_jar).and_call_original
payload_generator.generate_java_payload payload_generator.generate_java_payload
end end
end end
context 'if the payload does not respond to generate_jar' do context 'if the payload does not respond to generate_jar' do
let(:payload) { "java/jsp_shell_reverse_tcp"} let(:payload_module) {
load_and_create_module(
ancestor_reference_names: %w{
singles/java/jsp_shell_reverse_tcp
},
module_type: 'payload',
reference_name: 'java/jsp_shell_reverse_tcp'
)
}
it 'calls #generate' do it 'calls #generate' do
java_payload = framework.payloads.create("java/jsp_shell_reverse_tcp") framework.stub_chain(:payloads, :keys).and_return [payload_reference_name]
framework.stub_chain(:payloads, :keys).and_return ["java/jsp_shell_reverse_tcp"] framework.stub_chain(:payloads, :create).and_return(payload_module)
framework.stub_chain(:payloads, :create).and_return(java_payload) payload_module.should_receive(:generate).and_call_original
java_payload.should_receive(:generate).and_call_original
payload_generator.generate_java_payload payload_generator.generate_java_payload
end end
end end
@ -510,22 +584,29 @@ describe Msf::PayloadGenerator do
context '#generate_payload' do context '#generate_payload' do
it 'calls each step of the process' do it 'calls each step of the process' do
my_generator = payload_generator payload_generator.should_receive(:generate_raw_payload).and_call_original
my_generator.should_receive(:generate_raw_payload).and_call_original payload_generator.should_receive(:add_shellcode).and_call_original
my_generator.should_receive(:add_shellcode).and_call_original payload_generator.should_receive(:encode_payload).and_call_original
my_generator.should_receive(:encode_payload).and_call_original payload_generator.should_receive(:prepend_nops).and_call_original
my_generator.should_receive(:prepend_nops).and_call_original payload_generator.should_receive(:format_payload).and_call_original
my_generator.should_receive(:format_payload).and_call_original payload_generator.generate_payload
my_generator.generate_payload
end end
context 'when the payload is java' do context 'when the payload is java' do
let(:payload) { "java/meterpreter/reverse_tcp" } let(:payload_module) {
load_and_create_module(
ancestor_reference_names: %w{
stagers/java/reverse_tcp
stages/java/meterpreter
},
module_type: 'payload',
reference_name: 'java/meterpreter/reverse_tcp'
)
}
it 'calls generate_java_payload' do it 'calls generate_java_payload' do
my_generator = payload_generator payload_generator.should_receive(:generate_java_payload)
my_generator.should_receive(:generate_java_payload) payload_generator.generate_payload
my_generator.generate_payload
end end
end end
end end