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



133
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
# File 'lib/msf/core/payload_generator.rb', line 133

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



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

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



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

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



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

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



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

def cli
  @cli
end

#datastoreHash

Returns The datastore to apply to the payload module.

Returns:

  • (Hash)

    The datastore to apply to the payload module



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

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



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

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



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

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.



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

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)



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

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



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

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



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

def format
  @format
end

#frameworkMsf::Framework

Returns The framework instance to use for generation.

Returns:



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

def framework
  @framework
end

#iterationsInteger

Returns The number of iterations to run the encoder.

Returns:

  • (Integer)

    The number of iterations to run the encoder



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

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



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

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



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

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



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

def padnops
  @padnops
end

#payloadString

Returns The refname of the payload to generate.

Returns:

  • (String)

    The refname of the payload to generate



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

def payload
  @payload
end

#payload_moduleModule

Returns The payload module object if applicable.

Returns:

  • (Module)

    The payload module object if applicable



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

def payload_module
  @payload_module
end

#platformString

Returns The platform to build the payload for.

Returns:

  • (String)

    The platform to build the payload for



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

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



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

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



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

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



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

def smallest
  @smallest
end

#spaceInteger

Returns The maximum size in bytes of the payload.

Returns:

  • (Integer)

    The maximum size in bytes of the payload



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

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



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

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.



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

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



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

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



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

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



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

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



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

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:



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

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



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
302
303
304
# File 'lib/msf/core/payload_generator.rb', line 269

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



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

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



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
359
360
361
# File 'lib/msf/core/payload_generator.rb', line 332

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:



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

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



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
448
449
450
# File 'lib/msf/core/payload_generator.rb', line 397

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:



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
484
485
486
# File 'lib/msf/core/payload_generator.rb', line 458

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



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
527
528
529
# File 'lib/msf/core/payload_generator.rb', line 491

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



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

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])
    unless encoder_mod
      cli_print "#{encoder_opt[0]} not found continuing..."
      next
    end
    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:



533
534
535
536
537
538
539
540
541
542
543
544
# File 'lib/msf/core/payload_generator.rb', line 533

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



550
551
552
553
554
555
556
557
558
559
560
561
562
563
# File 'lib/msf/core/payload_generator.rb', line 550

def prepend_nops(shellcode)
  return shellcode unless 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

  shellcode
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:



570
571
572
573
574
575
576
577
578
579
# File 'lib/msf/core/payload_generator.rb', line 570

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