diff --git a/lib/msf/base/simple/payload.rb b/lib/msf/base/simple/payload.rb index 2a0ffb76ff2c..aa3ea537ac7c 100644 --- a/lib/msf/base/simple/payload.rb +++ b/lib/msf/base/simple/payload.rb @@ -53,6 +53,7 @@ def self.generate_simple(payload, opts, &block) e = EncodedPayload.create(payload, 'BadChars' => opts['BadChars'], 'MinNops' => opts['NopSledSize'], + 'PadNops' => opts['PadNops'], 'Encoder' => opts['Encoder'], 'Iterations' => opts['Iterations'], 'ForceEncode' => opts['ForceEncode'], @@ -64,7 +65,8 @@ def self.generate_simple(payload, opts, &block) exeopts = { :inject => opts['KeepTemplateWorking'], :template => opts['Template'], - :template_path => opts['ExeDir'] + :template_path => opts['ExeDir'], + :secname => opts['SecName'] } arch = payload.arch diff --git a/lib/msf/core/encoded_payload.rb b/lib/msf/core/encoded_payload.rb index 7b16e686654b..f07fc5ca7360 100644 --- a/lib/msf/core/encoded_payload.rb +++ b/lib/msf/core/encoded_payload.rb @@ -290,6 +290,7 @@ def encode def generate_sled min = reqs['MinNops'] || 0 space = reqs['Space'] + pad_nops = reqs['PadNops'] self.nop_sled_size = min @@ -310,6 +311,9 @@ def generate_sled # Check for the DisableNops setting self.nop_sled_size = 0 if reqs['DisableNops'] + # Check for the PadNops setting + self.nop_sled_size = (pad_nops - self.encoded.length) if reqs['PadNops'] + # Now construct the actual sled if (self.nop_sled_size > 0) nops = pinst.compatible_nops @@ -338,7 +342,6 @@ def generate_sled begin nop.copy_ui(pinst) - self.nop_sled = nop.generate_sled(self.nop_sled_size, 'BadChars' => reqs['BadChars'], 'SaveRegisters' => save_regs) diff --git a/lib/msf/core/exe/segment_appender.rb b/lib/msf/core/exe/segment_appender.rb index e0cb4a280bb1..7f061534500f 100644 --- a/lib/msf/core/exe/segment_appender.rb +++ b/lib/msf/core/exe/segment_appender.rb @@ -32,7 +32,11 @@ def generate_pe # Create a new section s = Metasm::PE::Section.new - s.name = '.' + Rex::Text.rand_text_alpha_lower(4) + if secname.blank? + s.name = '.' + Rex::Text.rand_text_alpha_lower(4) + else + s.name = '.' + secname.downcase + end s.encoded = payload_stub prefix s.characteristics = %w[MEM_READ MEM_WRITE MEM_EXECUTE] diff --git a/lib/msf/core/exe/segment_injector.rb b/lib/msf/core/exe/segment_injector.rb index 2e57eac157ea..84b971914988 100644 --- a/lib/msf/core/exe/segment_injector.rb +++ b/lib/msf/core/exe/segment_injector.rb @@ -10,13 +10,14 @@ class SegmentInjector attr_accessor :template attr_accessor :arch attr_accessor :buffer_register + attr_accessor :secname def initialize(opts = {}) @payload = opts[:payload] @template = opts[:template] @arch = opts[:arch] || :x86 @buffer_register = opts[:buffer_register] - + @secname = opts[:secname] x86_regs = %w{eax ecx edx ebx edi esi} x64_regs = %w{rax rcx rdx rbx rdi rsi} + (8..15).map{|n| "r#{n}" } diff --git a/lib/msf/core/payload_generator.rb b/lib/msf/core/payload_generator.rb index 213f8dbe4827..98b0ac660c08 100644 --- a/lib/msf/core/payload_generator.rb +++ b/lib/msf/core/payload_generator.rb @@ -44,6 +44,9 @@ class PayloadGenerator # @!attribute encoder # @return [String] The encoder(s) you want applied to the payload attr_accessor :encoder + # @!attribute secname + # @return [String] The name of the new section within the generated Windows binary + attr_accessor :secname # @!attribute format # @return [String] The format you want the payload returned in attr_accessor :format @@ -101,6 +104,7 @@ class PayloadGenerator # @option opts [String] :payload (see #payload) # @option opts [String] :format (see #format) # @option opts [String] :encoder (see #encoder) + # @option opts [String] :secname (see #secname) # @option opts [Integer] :iterations (see #iterations) # @option opts [String] :arch (see #arch) # @option opts [String] :platform (see #platform) @@ -124,6 +128,7 @@ def initialize(opts={}) @cli = opts.fetch(:cli, false) @datastore = opts.fetch(:datastore, {}) @encoder = opts.fetch(:encoder, '') + @secname = opts.fetch(:secname, '') @format = opts.fetch(:format, 'raw') @iterations = opts.fetch(:iterations, 1) @keep = opts.fetch(:keep, false) @@ -285,6 +290,9 @@ def exe_options opts[:template_path] = File.dirname(template) opts[:template] = File.basename(template) end + unless secname.blank? + opts[:secname] = secname + end opts end diff --git a/lib/msf/ui/console/command_dispatcher/payload.rb b/lib/msf/ui/console/command_dispatcher/payload.rb index 11b27b2e6f6c..9a94236745eb 100644 --- a/lib/msf/ui/console/command_dispatcher/payload.rb +++ b/lib/msf/ui/console/command_dispatcher/payload.rb @@ -24,6 +24,8 @@ class Payload "-E" => [ false, "Force encoding" ], "-e" => [ true, "The encoder to use" ], "-s" => [ true, "NOP sled length." ], + "-P" => [ true, "Total desired payload size, auto-produce approproate NOPsled length"], + "-S" => [ true, "The new section name to use when generating (large) Windows binaries"], "-b" => [ true, "The list of characters to avoid example: '\\x00\\xff'" ], "-i" => [ true, "The number of times to encode the payload" ], "-x" => [ true, "Specify a custom executable file to use as a template" ], @@ -82,6 +84,8 @@ def cmd_generate(*args) # Parse the arguments encoder_name = nil sled_size = nil + pad_nops = nil + sec_name = nil option_str = nil badchars = nil format = "ruby" @@ -102,6 +106,10 @@ def cmd_generate(*args) force = true when '-n' sled_size = val.to_i + when '-P' + pad_nops = val.to_i + when '-S' + sec_name = val when '-f' format = val when '-o' @@ -146,6 +154,8 @@ def cmd_generate(*args) 'Encoder' => encoder_name, 'Format' => format, 'NopSledSize' => sled_size, + 'PadNops' => pad_nops, + 'SecName' => sec_name, 'OptionStr' => option_str, 'ForceEncode' => force, 'Template' => template, @@ -178,6 +188,8 @@ def cmd_generate_tabs(str, words) '-h' => [ nil ], '-o' => [ true ], '-s' => [ true ], + '-P' => [ true ], + '-S' => [ true ], '-f' => [ :file ], '-t' => [ @@supported_formats ], '-p' => [ true ], diff --git a/lib/msf/util/exe.rb b/lib/msf/util/exe.rb index 44777e6ffca1..87709982b846 100644 --- a/lib/msf/util/exe.rb +++ b/lib/msf/util/exe.rb @@ -249,7 +249,8 @@ def self.to_win32pe(framework, code, opts = {}) injector = Msf::Exe::SegmentInjector.new({ :payload => code, :template => opts[:template], - :arch => :x86 + :arch => :x86, + :secname => opts[:secname] }) return injector.generate_pe end @@ -270,7 +271,8 @@ def self.to_win32pe(framework, code, opts = {}) appender = Msf::Exe::SegmentAppender.new({ :payload => code, :template => opts[:template], - :arch => :x86 + :arch => :x86, + :secname => opts[:secname] }) return appender.generate_pe end @@ -603,7 +605,8 @@ def self.to_win64pe(framework, code, opts = {}) injector = Msf::Exe::SegmentInjector.new({ :payload => code, :template => opts[:template], - :arch => :x64 + :arch => :x64, + :secname => opts[:secname] }) return injector.generate_pe end @@ -612,7 +615,8 @@ def self.to_win64pe(framework, code, opts = {}) appender = Msf::Exe::SegmentAppender.new({ :payload => code, :template => opts[:template], - :arch => :x64 + :arch => :x64, + :secname => opts[:secname] }) return appender.generate_pe end diff --git a/msfvenom b/msfvenom index 44cd8c6bfebb..96ce04538a32 100755 --- a/msfvenom +++ b/msfvenom @@ -97,6 +97,10 @@ def parse_args(args) opts[:encoder] = e end + opt.on('--sec-name ', String, 'The new section name to use when generating large Windows binaries. Default: random 4-character alpha string') do |s| + opts[:secname] = s + end + opt.on('--smallest', 'Generate the smallest possible payload using all available encoders') do opts[:smallest] = true end @@ -134,7 +138,7 @@ def parse_args(args) opts[:nops] = n.to_i end - opt.on('--pad-nops', 'Use nopsled size specified by -n as the total payload size, thus performing a subtraction to prepend a nopsled of quantity (nops minus payload length)') do + opt.on('--pad-nops', 'Use nopsled size specified by -n as the total payload size, auto-prepending a nopsled of quantity (nops minus payload length)') do opts[:padnops] = true end