Class: Msf::PayloadGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/msf/core/payload_generator.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ PayloadGenerator

Returns a new instance of PayloadGenerator.

Parameters:

  • opts (Hash) (defaults to: {})

    The options hash

Options Hash (opts):

  • :payload (String) — default: see #payload
  • :format (String) — default: see #format
  • :encoder (String) — default: see #encoder
  • :secname (String) — default: see #secname
  • :iterations (Integer) — default: see #iterations
  • :arch (String) — default: see #arch
  • :platform (String) — default: see #platform
  • :badchars (String) — default: see #badchars
  • :template (String) — default: see #template
  • :space (Integer) — default: see #space
  • :encoder_space (Integer) — default: see #encoder_space
  • :nops (Integer) — default: see #nops
  • :padnops (Boolean) — default: see #padnops
  • :add_code (String) — default: see #add_code
  • :keep (Boolean) — default: see #keep
  • :datastore (Hash) — default: see #datastore
  • :framework (Msf::Framework) — default: see #framework
  • :cli (Boolean) — default: see #cli
  • :smallest (Boolean) — default: see #smallest

Raises:

  • (KeyError)

    if framework is not provided in the options hash


134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/msf/core/payload_generator.rb', line 134

def initialize(opts={})
  @add_code   = opts.fetch(:add_code, '')
  @arch       = opts.fetch(:arch, '')
  @badchars   = opts.fetch(:badchars, '')
  @cli        = opts.fetch(:cli, false)
  @datastore  = opts.fetch(:datastore, {})
  @encoder    = opts.fetch(:encoder, '')
  @secname    = opts.fetch(:secname, '')
  @servicename = opts.fetch(:servicename, '')
  @sub_method = opts.fetch(:sub_method, false)
  @format     = opts.fetch(:format, 'raw')
  @iterations = opts.fetch(:iterations, 1)
  @keep       = opts.fetch(:keep, false)
  @nops       = opts.fetch(:nops, 0)
  @padnops    = opts.fetch(:padnops, false)
  @payload    = opts.fetch(:payload, '')
  @platform   = opts.fetch(:platform, '')
  @space      = opts.fetch(:space, 1.gigabyte)
  @stdin      = opts.fetch(:stdin, nil)
  @template   = opts.fetch(:template, '')
  @var_name   = opts.fetch(:var_name, 'buf')
  @smallest   = opts.fetch(:smallest, false)
  @encoder_space = opts.fetch(:encoder_space, @space)
  @encryption_format = opts.fetch(:encryption_format, nil)
  @encryption_key = opts.fetch(:encryption_key, nil)
  @encryption_iv = opts.fetch(:encryption_iv, nil)

  @framework  = opts.fetch(:framework)

  raise InvalidFormat, "invalid format: #{format}"  unless format_is_valid?
  raise ArgumentError, "invalid payload: #{payload}" unless payload_is_valid?

  # A side-effecto of running framework.payloads.create is that
  # framework.payloads.keys gets pruned of unloadable payloads. So, we do it
  # after checking payload_is_valid?, which refers to the cached keys.
  @payload_module = framework.payloads.create(@payload)
  raise ArgumentError, "unloadable payload: #{payload}" unless payload_module || @payload == 'stdin'

  # In smallest mode, override the payload @space & @encoder_space settings
  if @smallest
    @space = 0
    @encoder_space = 1.gigabyte
  end

end

Instance Attribute Details

#add_codeString

Returns The path to a shellcode file to execute in a separate thread.

Returns:

  • (String)

    The path to a shellcode file to execute in a separate thread


32
33
34
# File 'lib/msf/core/payload_generator.rb', line 32

def add_code
  @add_code
end

#archString

Returns The CPU architecture to build the payload for.

Returns:

  • (String)

    The CPU architecture to build the payload for


35
36
37
# File 'lib/msf/core/payload_generator.rb', line 35

def arch
  @arch
end

#badcharsString

Returns The bad characters that can't be in the payload.

Returns:

  • (String)

    The bad characters that can't be in the payload


38
39
40
# File 'lib/msf/core/payload_generator.rb', line 38

def badchars
  @badchars
end

#cliBoolean

Returns Whether this is being run by a CLI script.

Returns:

  • (Boolean)

    Whether this is being run by a CLI script


41
42
43
# File 'lib/msf/core/payload_generator.rb', line 41

def cli
  @cli
end

#datastoreHash

Returns The datastore to apply to the payload module.

Returns:

  • (Hash)

    The datastore to apply to the payload module


44
45
46
# File 'lib/msf/core/payload_generator.rb', line 44

def datastore
  @datastore
end

#encoderString

Returns The encoder(s) you want applied to the payload.

Returns:

  • (String)

    The encoder(s) you want applied to the payload


47
48
49
# File 'lib/msf/core/payload_generator.rb', line 47

def encoder
  @encoder
end

#encoder_spaceInteger

Returns The maximum size in bytes of the encoded payload.

Returns:

  • (Integer)

    The maximum size in bytes of the encoded payload


92
93
94
# File 'lib/msf/core/payload_generator.rb', line 92

def encoder_space
  @encoder_space
end

#encryption_formatString

Returns The encryption format to use for the shellcode.

Returns:

  • (String)

    The encryption format to use for the shellcode.


104
105
106
# File 'lib/msf/core/payload_generator.rb', line 104

def encryption_format
  @encryption_format
end

#encryption_ivString

Returns The initialization vector for the encryption (not all apply).

Returns:

  • (String)

    The initialization vector for the encryption (not all apply)


110
111
112
# File 'lib/msf/core/payload_generator.rb', line 110

def encryption_iv
  @encryption_iv
end

#encryption_keyString

Returns The key to use for the encryption.

Returns:

  • (String)

    The key to use for the encryption


107
108
109
# File 'lib/msf/core/payload_generator.rb', line 107

def encryption_key
  @encryption_key
end

#formatString

Returns The format you want the payload returned in.

Returns:

  • (String)

    The format you want the payload returned in


59
60
61
# File 'lib/msf/core/payload_generator.rb', line 59

def format
  @format
end

#frameworkMsf::Framework

Returns The framework instance to use for generation.

Returns:


62
63
64
# File 'lib/msf/core/payload_generator.rb', line 62

def framework
  @framework
end

#iterationsInteger

Returns The number of iterations to run the encoder.

Returns:

  • (Integer)

    The number of iterations to run the encoder


65
66
67
# File 'lib/msf/core/payload_generator.rb', line 65

def iterations
  @iterations
end

#keepBoolean

Returns Whether or not to preserve the original functionality of the template.

Returns:

  • (Boolean)

    Whether or not to preserve the original functionality of the template


68
69
70
# File 'lib/msf/core/payload_generator.rb', line 68

def keep
  @keep
end

#nopsInteger

Returns The size in bytes of NOP sled to prepend the payload with.

Returns:

  • (Integer)

    The size in bytes of NOP sled to prepend the payload with


71
72
73
# File 'lib/msf/core/payload_generator.rb', line 71

def nops
  @nops
end

#padnopsBoolean

Returns Whether to use @!attribute nops as the total payload size.

Returns:

  • (Boolean)

    Whether to use @!attribute nops as the total payload size


74
75
76
# File 'lib/msf/core/payload_generator.rb', line 74

def padnops
  @padnops
end

#payloadString

Returns The refname of the payload to generate.

Returns:

  • (String)

    The refname of the payload to generate


77
78
79
# File 'lib/msf/core/payload_generator.rb', line 77

def payload
  @payload
end

#payload_moduleModule

Returns The payload module object if applicable.

Returns:

  • (Module)

    The payload module object if applicable


80
81
82
# File 'lib/msf/core/payload_generator.rb', line 80

def payload_module
  @payload_module
end

#platformString

Returns The platform to build the payload for.

Returns:

  • (String)

    The platform to build the payload for


83
84
85
# File 'lib/msf/core/payload_generator.rb', line 83

def platform
  @platform
end

#secnameString

Returns The name of the new section within the generated Windows binary.

Returns:

  • (String)

    The name of the new section within the generated Windows binary


50
51
52
# File 'lib/msf/core/payload_generator.rb', line 50

def secname
  @secname
end

#servicenameString

Returns The name of the service to be associated with the generated Windows binary.

Returns:

  • (String)

    The name of the service to be associated with the generated Windows binary


53
54
55
# File 'lib/msf/core/payload_generator.rb', line 53

def servicename
  @servicename
end

#smallestBoolean

Returns Whether or not to find the smallest possible output.

Returns:

  • (Boolean)

    Whether or not to find the smallest possible output


86
87
88
# File 'lib/msf/core/payload_generator.rb', line 86

def smallest
  @smallest
end

#spaceInteger

Returns The maximum size in bytes of the payload.

Returns:

  • (Integer)

    The maximum size in bytes of the payload


89
90
91
# File 'lib/msf/core/payload_generator.rb', line 89

def space
  @space
end

#stdinString

Returns The raw bytes of a payload taken from STDIN.

Returns:

  • (String)

    The raw bytes of a payload taken from STDIN


95
96
97
# File 'lib/msf/core/payload_generator.rb', line 95

def stdin
  @stdin
end

#sub_methodBoolean

Returns Whether or not this binary needs the x86 sub_method applied or not.

Returns:

  • (Boolean)

    Whether or not this binary needs the x86 sub_method applied or not.


56
57
58
# File 'lib/msf/core/payload_generator.rb', line 56

def sub_method
  @sub_method
end

#templateString

Returns The path to an executable template to use.

Returns:

  • (String)

    The path to an executable template to use


98
99
100
# File 'lib/msf/core/payload_generator.rb', line 98

def template
  @template
end

#var_nameString

Returns The custom variable string for certain output formats.

Returns:

  • (String)

    The custom variable string for certain output formats


101
102
103
# File 'lib/msf/core/payload_generator.rb', line 101

def var_name
  @var_name
end

Instance Method Details

#add_shellcode(shellcode) ⇒ String

This method takes the shellcode generated so far and adds shellcode from a supplied file. The added shellcode is executed in a separate thread from the main payload.

Parameters:

  • shellcode (String)

    The shellcode to add to

Returns:

  • (String)

    the combined shellcode which executes the added code in a separate thread


185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/msf/core/payload_generator.rb', line 185

def add_shellcode(shellcode)
  if add_code.present? and platform_list.platforms.include? Msf::Module::Platform::Windows and arch == ARCH_X86
    cli_print "Adding shellcode from #{add_code} to the payload"
    shellcode_file = File.open(add_code)
    shellcode_file.binmode
    added_code = shellcode_file.read
    shellcode_file.close
    shellcode = ::Msf::Util::EXE.win32_rwx_exec_thread(shellcode,0,'end')
    shellcode << added_code
  else
    shellcode.dup
  end
end

#choose_arch(mod) ⇒ String, Nil

This method takes a payload module and tries to reconcile a chosen arch with the arches supported by the module.

Parameters:

  • mod (Msf::Payload)

    The module class to choose an arch for

Returns:

  • (String)

    String form of the arch if a valid arch found

  • (Nil)

    if no valid arch found


204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/msf/core/payload_generator.rb', line 204

def choose_arch(mod)
  if arch.blank?
    @arch = mod.arch.first
    cli_print "[-] No arch selected, selecting arch: #{arch} from the payload"
    datastore['ARCH'] = arch if mod.kind_of?(Msf::Payload::Generic)
    return mod.arch.first
  elsif mod.arch.include? arch
    datastore['ARCH'] = arch if mod.kind_of?(Msf::Payload::Generic)
    return arch
  else
    return nil
  end
end

#choose_platform(mod) ⇒ Msf::Module::PlatformList

This method takes a payload module and tries to reconcile a chosen platform with the platforms supported by the module.

Parameters:

  • mod (Msf::Payload)

    The module class to choose a platform for

Returns:


222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/msf/core/payload_generator.rb', line 222

def choose_platform(mod)
  # By default, platform_list will at least return Msf::Module::Platform
  # if there is absolutely no pre-configured platform info at all
  chosen_platform = platform_list

  if chosen_platform.platforms.empty?
    chosen_platform = mod.platform
    cli_print "[-] No platform was selected, choosing #{chosen_platform.platforms.first} from the payload"
    @platform = mod.platform.platforms.first.to_s.split("::").last
  elsif (chosen_platform & mod.platform).empty?
    chosen_platform = Msf::Module::PlatformList.new
  end

  begin
    platform_object = Msf::Module::Platform.find_platform(platform)
  rescue ArgumentError
    platform_object = nil
  end

  if mod.kind_of?(Msf::Payload::Generic) && mod.send(:module_info)['Platform'].empty? && platform_object
    datastore['PLATFORM'] = platform
  end

  chosen_platform
end

#encode_payload(shellcode) ⇒ String

This method takes the shellcode generated so far and iterates through the chosen or compatible encoders. It attempts to encode the payload with each encoder until it finds one that works.

Parameters:

  • shellcode (String)

    The shellcode to encode

Returns:

  • (String)

    The encoded shellcode


266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/msf/core/payload_generator.rb', line 266

def encode_payload(shellcode)
  shellcode = shellcode.dup
  encoder_list = get_encoders(shellcode)
  if encoder_list.empty?
    cli_print "No encoder specified, outputting raw payload"
    return shellcode
  end

  results = {}

  cli_print "Found #{encoder_list.count} compatible encoders"
  encoder_list.each do |encoder_mod|
    cli_print "Attempting to encode payload with #{iterations} iterations of #{encoder_mod.refname}"
    begin
      encoder_mod.available_space = @encoder_space unless @smallest
      results[encoder_mod.refname] = run_encoder(encoder_mod, shellcode.dup)
      break unless @smallest
    rescue ::Msf::EncoderSpaceViolation => e
      cli_print "#{encoder_mod.refname} failed with #{e.message}"
      next
    rescue ::Msf::EncodingError => e
      cli_print "#{encoder_mod.refname} failed with #{e.message}"
      next
    end
  end

  if results.keys.length == 0
    raise ::Msf::EncodingError, "No Encoder Succeeded"
  end

  # Return the shortest encoding of the payload
  chosen_encoder = results.keys.sort{|a,b| results[a].length <=> results[b].length}.first
  cli_print "#{chosen_encoder} chosen with final size #{results[chosen_encoder].length}"

  results[chosen_encoder]
end

#exe_optionsHash

This returns a hash for the exe format generation of payloads

Returns:

  • (Hash)

    The hash needed for generating an executable format


305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
# File 'lib/msf/core/payload_generator.rb', line 305

def exe_options
  opts = { inject: keep }
  unless template.blank?
    opts[:template_path] = File.dirname(template)
    opts[:template]      = File.basename(template)
  end
  unless secname.blank?
    opts[:secname]       = secname
  end
  unless servicename.blank?
    opts[:servicename] = servicename
  end
  if sub_method.nil?
    opts[:sub_method] = false
  else
    opts[:sub_method] = sub_method
  end
  opts
end

#format_payload(shellcode) ⇒ String

This method takes the payload shellcode and formats it appropriately based on the selected output format.

Parameters:

  • shellcode (String)

    the processed shellcode to be formatted

Returns:

  • (String)

    The final formatted form of the payload


329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
# File 'lib/msf/core/payload_generator.rb', line 329

def format_payload(shellcode)
  encryption_opts = {}
  encryption_opts[:format] = encryption_format if encryption_format
  encryption_opts[:iv] = encryption_iv if encryption_iv
  encryption_opts[:key] = encryption_key if encryption_key

  if Msf::Util::EXE.elf?(shellcode) && format.downcase != 'elf'
    # TODO: force generation from stager/stage if available
    raise InvalidFormat, 'selected payload can only generate ELF files'
  end
  if Msf::Util::EXE.macho?(shellcode) && format.downcase != 'macho'
    # TODO: force generation from stager/stage if available
    raise InvalidFormat, 'selected payload can only generate MACHO files'
  end

  case format.downcase
    when "js_be"
      if Rex::Arch.endian(arch) != ENDIAN_BIG
        raise IncompatibleEndianess, "Big endian format selected for a non big endian payload"
      else
        ::Msf::Simple::Buffer.transform(shellcode, format, @var_name, encryption_opts)
      end
    when *::Msf::Simple::Buffer.transform_formats
      ::Msf::Simple::Buffer.transform(shellcode, format, @var_name, encryption_opts)
    when *::Msf::Util::EXE.to_executable_fmt_formats
      ::Msf::Util::EXE.to_executable_fmt(framework, arch, platform_list, shellcode, format, exe_options)
    else
      raise InvalidFormat, "you have selected an invalid payload format"
  end
end

#generate_java_payloadString

This method generates Java payloads which are a special case. They can be generated in raw or war formats, which respectively produce a JAR or WAR file for the java payload.

Returns:

  • (String)

    Java payload as a JAR or WAR file

Raises:


364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
# File 'lib/msf/core/payload_generator.rb', line 364

def generate_java_payload
  raise PayloadGeneratorError, "A payload module was not selected" if payload_module.nil?
  payload_module.datastore.import_options_from_hash(datastore)
  case format
  when "raw", "jar"
    if payload_module.respond_to? :generate_jar
      payload_module.generate_jar.pack
    else
      payload_module.generate
    end
  when "war"
    if payload_module.respond_to? :generate_war
      payload_module.generate_war.pack
    else
      raise InvalidFormat, "#{payload} is not a Java payload"
    end
  when "axis2"
    if payload_module.respond_to? :generate_axis2
      payload_module.generate_axis2.pack
    else
      raise InvalidFormat, "#{payload} is not a Java payload"
    end
  else
    raise InvalidFormat, "#{format} is not a valid format for Java payloads"
  end
end

#generate_payloadString

This method is a wrapper around all of the other methods. It calls the correct methods in order based on the supplied options and returns the finished payload.

Returns:

  • (String)

    A string containing the bytes of the payload in the format selected


394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
# File 'lib/msf/core/payload_generator.rb', line 394

def generate_payload
  if payload.include?("pingback") and framework.db.active == false
    cli_print "[-] WARNING: UUID cannot be saved because database is inactive."
  end

  if platform == "java" or arch == "java" or payload.start_with? "java/"
    raw_payload = generate_java_payload
    encoded_payload = raw_payload
    gen_payload = raw_payload
  elsif payload.start_with? "android/" and not template.blank?
    if payload.start_with? "android/meterpreter_"
      raise PayloadGeneratorError, "Stageless Android payloads (e.g #{payload}) are not compatible with injection (-x)"
    end
    cli_print "Using APK template: #{template}"
    apk_backdoor = ::Msf::Payload::Apk.new
    raw_payload = apk_backdoor.backdoor_apk(template, generate_raw_payload)
    gen_payload = raw_payload
  else
    if payload_module.is_a?(Msf::Payload::Windows::PayloadDBConf)
      payload_module.datastore.import_options_from_hash(datastore)
      ds_opt = payload_module.datastore
      cli_print("[!] Database is not active! Payload key and nonce must be manually set when creating handler") unless framework.db.active
      cli_print("[-] Please ensure payload key and nonce match when setting up handler: #{ds_opt['ChachaKey']} - #{ds_opt['ChachaNonce']}")
    end

    raw_payload = generate_raw_payload
    raw_payload = add_shellcode(raw_payload)

    if encoder != nil and encoder.start_with?("@")
      raw_payload = multiple_encode_payload(raw_payload)
    else
      raw_payload = encode_payload(raw_payload)
    end
    if padnops
      @nops = nops - raw_payload.length
    end
    raw_payload = prepend_nops(raw_payload)
    gen_payload = format_payload(raw_payload)
  end

  cli_print "Payload size: #{raw_payload.length} bytes"

  if gen_payload.nil?
    raise PayloadGeneratorError, 'The payload could not be generated, check options'
  elsif raw_payload.length > @space and not @smallest
    raise PayloadSpaceViolation, 'The payload exceeds the specified space'
  else
    if format.to_s != 'raw'
      cli_print "Final size of #{format} file: #{gen_payload.length} bytes"
    end

    gen_payload
  end
end

#generate_raw_payloadString

This method generates the raw form of the payload as generated by the payload module itself.

Returns:

  • (String)

    the raw bytes of the payload to be generated

Raises:


455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
# File 'lib/msf/core/payload_generator.rb', line 455

def generate_raw_payload
  if payload == 'stdin'
    if arch.blank?
      raise IncompatibleArch, "You must select an arch for a custom payload"
    elsif platform.blank?
      raise IncompatiblePlatform, "You must select a platform for a custom payload"
    end
    stdin
  else
    raise PayloadGeneratorError, "A payload module was not selected" if payload_module.nil?
    chosen_platform = choose_platform(payload_module)
    if chosen_platform.platforms.empty?
      raise IncompatiblePlatform, "The selected platform is incompatible with the payload"
    end

    chosen_arch = choose_arch(payload_module)
    unless chosen_arch
      raise IncompatibleArch, "The selected arch is incompatible with the payload"
    end

    payload_module.generate_simple(
        'Format'      => 'raw',
        'Options'     => datastore,
        'Encoder'     => nil,
        'MaxSize'     => @space,
        'DisableNops' => true
    )
  end
end

#get_encoders(buf) ⇒ Array<Msf::Encoder>

This method returns an array of encoders that either match the encoders selected by the user, or match the arch selected.

Returns:

  • (Array<Msf::Encoder>)

    An array of potential encoders to use


488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
# File 'lib/msf/core/payload_generator.rb', line 488

def get_encoders(buf)
  encoders = []
  if encoder.present?
    # Allow comma separated list of encoders so users can choose several
    encoder.split(',').each do |chosen_encoder|
      e = framework.encoders.create(chosen_encoder)
      if e.nil?
        cli_print "[-] Skipping invalid encoder #{chosen_encoder}"
        next
      end
      e.datastore.import_options_from_hash(datastore)
      encoders << e if e
    end
    if encoders.empty?
      cli_print "[!] Couldn't find encoder to use"
      return encoders
    end
    encoders.sort_by { |my_encoder| my_encoder.rank }.reverse
  elsif !badchars.empty? && !badchars.nil?
    badchars_present = false
    badchars.each_byte do |bad|
      badchars_present = true if buf.index(bad.chr(Encoding::ASCII_8BIT))
    end

    unless badchars_present
      cli_print "No badchars present in payload, skipping automatic encoding"
      return []
    end

    framework.encoders.each_module_ranked('Arch' => [arch], 'Platform' => platform_list) do |name, mod|
      e = framework.encoders.create(name)
      e.datastore.import_options_from_hash(datastore)
      encoders << e if e
    end
    encoders.select{ |my_encoder| my_encoder.rank != ManualRanking }.sort_by { |my_encoder| my_encoder.rank }.reverse
  else
    encoders
  end
end

#multiple_encode_payload(shellcode) ⇒ Object


248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/msf/core/payload_generator.rb', line 248

def multiple_encode_payload(shellcode)
  encoder_str = encoder[1..-1]
  encoder_str.scan(/([^:, ]+):?([^,]+)?/).map do |encoder_opt|
    @iterations = (encoder_opt[1] || 1).to_i
    @iterations = 1 if iterations < 1

    encoder_mod = framework.encoders.create(encoder_opt[0])
    encoder_mod.datastore.import_options_from_hash(datastore)
    shellcode = run_encoder(encoder_mod, shellcode)
  end
  shellcode
end

#platform_listMsf::Module::PlatformList

Returns a PlatformList object based on the platform string given at creation.

Returns:


530
531
532
533
534
535
536
537
538
539
540
541
# File 'lib/msf/core/payload_generator.rb', line 530

def platform_list
  if platform.blank?
    list = Msf::Module::PlatformList.new
  else
    begin
      list = ::Msf::Module::PlatformList.transform(platform)
    rescue
      list = Msf::Module::PlatformList.new
    end
  end
  list
end

#prepend_nops(shellcode) ⇒ String

This method takes an encoded payload and prepends a NOP Sled to it with a size based on the nops value given to the generator.

Parameters:

  • shellcode (String)

    The shellcode to prepend the NOPs to

Returns:

  • (String)

    the shellcode with the appropriate nopsled affixed


547
548
549
550
551
552
553
554
555
556
557
558
559
560
# File 'lib/msf/core/payload_generator.rb', line 547

def prepend_nops(shellcode)
  if nops > 0
    framework.nops.each_module_ranked('Arch' => [arch]) do |name, mod|
      nop = framework.nops.create(name)
      raw = nop.generate_sled(nops, {'BadChars' => badchars, 'SaveRegisters' => [ 'esp', 'ebp', 'esi', 'edi' ] })
      if raw
        cli_print "Successfully added NOP sled of size #{raw.length} from #{name}"
        return raw + shellcode
     end
    end
  else
    shellcode
  end
end

#run_encoder(encoder_module, shellcode) ⇒ String

This method runs a specified encoder, for a number of defined iterations against the shellcode.

Parameters:

  • encoder_module (Msf::Encoder)

    The Encoder to run against the shellcode

  • shellcode (String)

    The shellcode to be encoded

Returns:

  • (String)

    The encoded shellcode

Raises:


567
568
569
570
571
572
573
574
575
576
# File 'lib/msf/core/payload_generator.rb', line 567

def run_encoder(encoder_module, shellcode)
  iterations.times do |x|
    shellcode = encoder_module.encode(shellcode.dup, badchars, nil, platform_list)
    cli_print "#{encoder_module.refname} succeeded with size #{shellcode.length} (iteration=#{x})"
    if shellcode.length > encoder_space
      raise EncoderSpaceViolation, "encoder has made a buffer that is too big"
    end
  end
  shellcode
end