Class: Msf::RPC::RPC_Module

Inherits:
RPC_Base show all
Defined in:
lib/msf/core/rpc/v10/rpc_module.rb

Instance Attribute Summary

Attributes inherited from RPC_Base

#framework, #job_status_tracker, #service, #tokens, #users

Instance Method Summary collapse

Methods inherited from RPC_Base

#error, #initialize

Constructor Details

This class inherits a constructor from Msf::RPC::RPC_Base

Instance Method Details

#module_short_info(m) ⇒ Object


280
281
282
283
284
285
286
287
288
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 280

def module_short_info(m)
  res = {}
  res['type'] = m.type
  res['name'] = m.name
  res['fullname'] = m.fullname
  res['rank'] = RankingName[m.rank].to_s
  res['disclosuredate'] = m.disclosure_date.nil? ? "" : m.disclosure_date.strftime("%Y-%m-%d")
  res
end

#rpc_ack(uuid) ⇒ Object


558
559
560
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 558

def rpc_ack(uuid)
  {"success" => !!self.job_status_tracker.ack(uuid)}
end

#rpc_architecturesArray<String>

Returns a list of architecture names.

Examples:

Here's how you would use this from the client:

rpc.call('module.architectures')

Returns:

  • (Array<String>)

    A list of architecture names, for example: ["x64"]


605
606
607
608
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 605

def rpc_architectures
  supported_archs = ARCH_ALL.dup
  supported_archs.sort
end

#rpc_auxiliaryHash

Returns a list of auxiliary module names. The 'auxiliary/' prefix will not be included.

Examples:

Here's how you would use this from the client:

rpc.call('module.auxiliary')

Returns:

  • (Hash)

    A list of auxiliary module names. It contains the following key:

    • 'modules' [Array<string>] Auxiliary module names, for example: ['vsploit/pii/web_pii']


37
38
39
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 37

def rpc_auxiliary
  { "modules" => self.framework.auxiliary.keys }
end

#rpc_check(mtype, mname, opts) ⇒ Object

Runs the check method of a module.

Parameters:

  • mtype (String)

    Module type. Supported types include (case-sensitive):

    • exploit

    • auxiliary

  • mname (String)

    Module name. For example: 'windows/smb/ms08_067_netapi'.

  • opts (Hash)

    Options for the module (such as datastore options).

Returns:

Raises:


520
521
522
523
524
525
526
527
528
529
530
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 520

def rpc_check(mtype, mname, opts)
  mod = _find_module(mtype,mname)
  case mtype
  when 'exploit'
    _check_exploit(mod, opts)
  when 'auxiliary'
    _check_auxiliary(mod, opts)
  else
    error(500, "Invalid Module Type: #{mtype}")
  end
end

#rpc_compatible_evasion_payloads(mname) ⇒ Hash

Returns the compatible payloads for a specific evasion module.

Examples:

Here's how you would use this from the client:

rpc.call('module.compatible_evasion_payloads', 'windows/windows_defender_exe')

Parameters:

  • mname (String)

    Evasion module name. For example: 'windows/windows_defender_exe'

Returns:

  • (Hash)

    The evasion module's compatible payloads. It contains the following key:

    • 'payloads' [Array<String>] A list of payloads.

Raises:


328
329
330
331
332
333
334
335
336
337
338
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 328

def rpc_compatible_evasion_payloads(mname)
  m = _find_module('evasion', mname)
  res = {}
  res['payloads'] = []

  m.compatible_payloads.each do |k|
    res['payloads'] << k[0]
  end

  res
end

#rpc_compatible_payloads(mname) ⇒ Hash Also known as: rpc_compatible_exploit_payloads

Returns the compatible payloads for a specific exploit.

Examples:

Here's how you would use this from the client:

rpc.call('module.compatible_payloads', 'windows/smb/ms08_067_netapi')

Parameters:

  • mname (String)

    Exploit module name. For example: 'windows/smb/ms08_067_netapi'.

Returns:

  • (Hash)

    The exploit's compatible payloads. It contains the following key:

    • 'payloads' [Array<string>] A list of payloads. For example: ['generic/custom']

Raises:


306
307
308
309
310
311
312
313
314
315
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 306

def rpc_compatible_payloads(mname)
  m   = _find_module('exploit',mname)
  res = {}
  res['payloads'] = []
  m.compatible_payloads.each do |k|
    res['payloads'] << k[0]
  end

  res
end

#rpc_compatible_sessions(mname) ⇒ Hash

Returns the compatible sessions for a specific post module.

Examples:

Here's how you would use this from the client:

rpc.call('module.compatible_sessions', 'windows/wlan/wlan_profile')

Parameters:

  • mname (String)

    Post module name. For example: 'windows/wlan/wlan_profile'.

Returns:

  • (Hash)

    The post module's compatible sessions. It contains the following key:

    • 'sessions' [Array<Integer>] A list of session IDs.

Raises:


349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 349

def rpc_compatible_sessions(mname)
  if mname.start_with? 'exploit/'
    m = _find_module('exploit',mname)
  else
    m = _find_module('post',mname)
  end

  unless m.respond_to? :compatible_sessions
    error(500, "Cannot determine compatible sessions for non-local module: #{mname}")
  end

  res = {}
  res['sessions'] = m.compatible_sessions

  res
end

#rpc_encode(data, encoder, options) ⇒ Object

Encodes data with an encoder.

Examples:

Here's how you would use this from the client:

# This will encode 'AAAA' with shikata_ga_nai, and prints the following:
# unsigned char buf[] =
# "\xba\x9e\xb5\x91\x66\xdb\xd2\xd9\x74\x24\xf4\x5f\x29\xc9\xb1"
# "\x01\x31\x57\x15\x03\x57\x15\x83\xc7\x04\xe2\x6b\xf4\xd0\x27";
result = rpc.call('module.encode', 'AAAA', 'x86/shikata_ga_nai', {'format'=>'c'})
puts result['encoded']

Parameters:

  • data (String)

    Data to encode.

  • encoder (encoder)

    Encoder module name. For example: 'x86/single_byte'.

  • options (Hash)

    Encoding options, such as:

Options Hash (options):

  • 'format' (String)

    Encoding format.

  • 'badchars' (String)

    Bad characters.

  • 'platform' (String)

    Platform.

  • 'arch' (String)

    Architecture.

  • 'ecount' (Integer)

    Number of times to encode.

  • 'inject' (TrueClass)

    To enable injection.

  • 'template' (String)

    The template file (an executable).

  • 'template_path' (String)

    Template path.

  • 'addshellcode' (String)

    Custom shellcode.

Returns:

  • The encoded data. It contains the following key:

    • 'encoded' [String] The encoded data in the format you specify.

Raises:

  • (Msf::RPC::Exception)

    Error could be one of these:

    • 500 Invalid format

    • 500 Failure to encode


647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 647

def rpc_encode(data, encoder, options)
  # Load supported formats
  supported_formats = Msf::Simple::Buffer.transform_formats + Msf::Util::EXE.to_executable_fmt_formats

  if (fmt = options['format'])
    if not supported_formats.include?(fmt)
      error(500, "Invalid Format: #{fmt}")
    end
  end

  badchars = ''
  if options['badchars']
    badchars = options['badchars']
  end

  platform = nil
  if options['platform']
    platform = Msf::Module::PlatformList.transform(options['platform'])
  end

  arch = nil
  if options['arch']
    arch = options['arch']
  end

  ecount = 1
  if options['ecount']
    ecount = options['ecount'].to_i
  end

  exeopts = {
    :inject => options['inject'],
    :template => options['altexe'],
    :template_path => options['exedir']
  }

  # If we were given addshellcode for a win32 payload,
  # create a double-payload; one running in one thread, one running in the other
  if options['addshellcode']
    buf = Msf::Util::EXE.win32_rwx_exec_thread(buf,0,'end')
    file = ::File.new(options['addshellcode'])
    file.binmode
    buf << file.read
    file.close
  end

  enc = self.framework.encoders.create(encoder)

  begin
    # Imports options
    enc.datastore.update(options)

    raw  = data.unpack("C*").pack("C*")

    1.upto(ecount) do |iteration|
      # Encode it up
      raw = enc.encode(raw, badchars, nil, platform)
    end

    output = Msf::Util::EXE.to_executable_fmt(self.framework, arch, platform, raw, fmt, exeopts)

    if not output
      fmt ||= "ruby"
      output = Msf::Simple::Buffer.transform(raw, fmt)
    end

    # How to warn?
    #if exeopts[:fellback]
    #  $stderr.puts(OutError + "Warning: Falling back to default template: #{exeopts[:fellback]}")
    #end

    { "encoded" => output.to_s }
  rescue => e
    error(500, "#{enc.refname} failed: #{e} #{e.backtrace}")
  end
end

#rpc_encode_formatsArray<String>

Returns a list of encoding formats.

Examples:

Here's how you would use this from the client:

rpc.call('module.encode_formats')

Returns:

  • (Array<String>)

    Encoding formats.


615
616
617
618
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 615

def rpc_encode_formats
  # Supported formats
  Msf::Simple::Buffer.transform_formats + Msf::Util::EXE.to_executable_fmt_formats
end

#rpc_encoders(module_info = nil, arch = nil) ⇒ Hash

Returns a list of encoder module names or a hash with encoder module names as keys to hashes that contain the module information fields requested. The 'encoder/' prefix will not be included.

If this is nil, then only module names are returned. Default: nil the module must support. The module need only support one of the architectures to be included, not all architectures. Default: nil

If module_info is not nil, encoder module names as keys to hashes that contain the requested module information fields. It contains the following key:

* 'modules' [Hash] for example:
  {"x86/unicode_upper"=>{"name"=>"Alpha2 Alphanumeric Unicode Uppercase Encoder", "rank"=>"Manual"}}

Examples:

Here's how you would use this from the client:

rpc.call('module.encoders')

Parameters:

  • module_info (String) (defaults to: nil)

    Comma-separated list of module information field names.

  • arch (String) (defaults to: nil)

    Comma-separated list of one or more architectures that

Returns:

  • (Hash)

    If module_info is nil, a list of encoder module names. It contains the following key:

    • 'modules' [Array<String>] Encoder module names, for example: ['x86/unicode_upper']


116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 116

def rpc_encoders(module_info = nil, arch = nil)
  unless module_info.nil?
    module_info = module_info.strip.split(',').map(&:strip)
    module_info.map!(&:to_sym)
  end

  unless arch.nil?
    arch = arch.strip.split(',').map(&:strip)
  end

  data = module_info.nil? ? [] : {}
  arch_filter = !arch.nil? && !arch.empty? ? arch : nil
  self.framework.encoders.each_module('Arch' => arch_filter) do |name, mod|
    if module_info.nil?
      data << name
    else
      tmp_mod_info = ::JSON.parse(Msf::Serializer::Json.dump_module(mod.new), symbolize_names: true)
      data[name] = tmp_mod_info.select { |k,v| module_info.include?(k) }
    end
  end

  { "modules" => data }
end

#rpc_encryption_formatsArray<String>

Returns a list of encryption format names.

Examples:

Here's how you would use this from the client:

rpc.call('module.encryption_formats')

Returns:

  • (Array<String>)

    A list of encryption format names, for example: ["aes256"]


585
586
587
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 585

def rpc_encryption_formats
  ::Msf::Simple::Buffer.encryption_formats
end

#rpc_evasionHash

Returns a list of evasion module names. The 'evasion/' prefix will not be included.

Examples:

Here's how you would use this from the client:

rpc.call('module.evasion')

Returns:

  • (Hash)

    A list of evasion module names. It contains the following key:

    • 'modules' [Array<string>] Evasion names, for example: ['windows/windows_defender_exe']


26
27
28
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 26

def rpc_evasion
  { "modules" => self.framework.evasion.keys }
end

#rpc_executable_formatsArray<String>

Returns a list of executable format names.

Examples:

Here's how you would use this from the client:

rpc.call('module.executable_formats')

Returns:

  • (Array<String>)

    A list of executable format names, for example: ["exe"]


567
568
569
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 567

def rpc_executable_formats
  ::Msf::Util::EXE.to_executable_fmt_formats
end

#rpc_execute(mtype, mname, opts) ⇒ Hash

Note:

If you get exploit sessions via the RPC service, know that only the RPC clients have access to those sessions. Framework msfconsole will not be able to use or even see these sessions, because it belongs to a different framework instance. However, this restriction does not apply to the database.

Executes a module.

Examples:

Here's how you would use this from the client:

# Starts a windows/meterpreter/reverse_tcp on port 6669
opts = {'LHOST' => '0.0.0.0', 'LPORT'=>6669, 'PAYLOAD'=>'windows/meterpreter/reverse_tcp'}
rpc.call('module.execute', 'exploit', 'multi/handler', opts)

Parameters:

  • mtype (String)

    Module type. Supported types include (case-sensitive):

    • exploit

    • auxiliary

    • post

    • payload

    • evasion

  • mname (String)

    Module name. For example: 'windows/smb/ms08_067_netapi'.

  • opts (Hash)

    Options for the module (such as datastore options).

Returns:

  • (Hash)

    It contains the following keys:

    • 'job_id' [Integer] Job ID.

    • 'uuid' [String] UUID.

Raises:


493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 493

def rpc_execute(mtype, mname, opts)
  mod = _find_module(mtype,mname)

  case mtype
    when 'exploit'
      _run_exploit(mod, opts)
    when 'auxiliary'
      _run_auxiliary(mod, opts)
    when 'payload'
      _run_payload(mod, opts)
    when 'post'
      _run_post(mod, opts)
    when 'evasion'
      _run_evasion(mod, opts)
  end

end

#rpc_exploitsHash

Returns a list of exploit names. The 'exploit/' prefix will not be included.

Examples:

Here's how you would use this from the client:

rpc.call('module.exploits')

Returns:

  • (Hash)

    A list of exploit names. It contains the following key:

    • 'modules' [Array<string>] Exploit names, for example: ['windows/wins/ms04_045_wins']


15
16
17
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 15

def rpc_exploits
  { "modules" => self.framework.exploits.keys }
end

#rpc_info(mtype, mname) ⇒ Hash

Returns the metadata for a module.

Examples:

Here's how you would use this from the client:

# This gives us the metadata of ms08_067_netapi
rpc.call('module.info', 'exploit', 'windows/smb/ms08_067_netapi')

Parameters:

  • mtype (String)

    Module type. Supported types include (case-sensitive):

    • exploit

    • auxiliary

    • post

    • nop

    • payload

  • mname (String)

    Module name. For example: 'windows/wlan/wlan_profile'.

Returns:

  • (Hash)

    The module's metadata. The exact keys you will get depends on the module.

Raises:


217
218
219
220
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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 217

def rpc_info(mtype, mname)
  m = _find_module(mtype,mname)
  res = module_short_info(m)
  res['description'] = Rex::Text.compress(m.description)
  res['license'] = m.license
  res['filepath'] = m.file_path
  res['arch'] = m.arch.map { |x| x.to_s }
  res['platform'] = m.platform.platforms.map { |x| x.to_s }
  res['authors'] = m.author.map { |a| a.to_s }
  res['privileged'] = m.privileged?

  res['references'] = []
  m.references.each do |r|
    res['references'] << [r.ctx_id, r.ctx_val]
  end

  if m.type == 'exploit' || m.type == 'evasion'
    res['targets'] = {}
    m.targets.each_index do |i|
      res['targets'][i] = m.targets[i].name
    end

    if (m.default_target)
      res['default_target'] = m.default_target
    end

    # Some modules are a combination, which means they are actually aggressive
    res['stance'] = m.stance.to_s.index('aggressive') ? 'aggressive' : 'passive'
  end

  if m.type == 'auxiliary' || m.type == 'post'
    res['actions'] = {}
    m.actions.each_index do |i|
      res['actions'][i] = m.actions[i].name
    end

    if m.default_action
      res['default_action'] = m.default_action
    end

    if m.type == 'auxiliary'
      res['stance'] = m.passive? ? 'passive' : 'aggressive'
    end
  end

  opts = {}
  m.options.each_key do |k|
    o = m.options[k]
    opts[k] = {
      'type'     => o.type,
      'required' => o.required,
      'advanced' => o.advanced,
      'desc'     => o.desc
    }

    opts[k]['default'] = o.default unless o.default.nil?
    opts[k]['enums'] = o.enums if o.enums.length > 1
  end
  res['options'] = opts

  res
end

#rpc_info_html(mtype, mname) ⇒ String

Returns detailed information about a module in HTML.

Examples:

Here's how you would use this from the client:

rpc.call('module.info_html', 'exploit', 'windows/smb/ms08_067_netapi')

Returns:

  • (String)

    HTML file.


197
198
199
200
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 197

def rpc_info_html(mtype, mname)
  m = _find_module(mtype, mname)
  Msf::Util::DocumentGenerator.get_module_document(m)
end

#rpc_nops(module_info = nil, arch = nil) ⇒ Hash

Returns a list of NOP module names or a hash with NOP module names as keys to hashes that contain the module information fields requested. The 'nop/' prefix will not be included.

If this is nil, then only module names are returned. Default: nil the module must support. The module need only support one of the architectures to be included, not all architectures. Default: nil

If module_info is not nil, NOP module names as keys to hashes that contain the requested module information fields. It contains the following key:

* 'modules' [Hash] for example:
  {"x86/single_byte"=>{"name"=>"Single Byte", "rank"=>"Normal"}}

Examples:

Here's how you would use this from the client:

rpc.call('module.nops')

Parameters:

  • module_info (String) (defaults to: nil)

    Comma-separated list of module information field names.

  • arch (String) (defaults to: nil)

    Comma-separated list of one or more architectures that

Returns:

  • (Hash)

    If module_info is nil, a list of NOP module names. It contains the following key:

    • 'modules' [Array<String>] NOP module names, for example: ['x86/single_byte']


157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 157

def rpc_nops(module_info = nil, arch = nil)
  unless module_info.nil?
    module_info = module_info.strip.split(',').map(&:strip)
    module_info.map!(&:to_sym)
  end

  unless arch.nil?
    arch = arch.strip.split(',').map(&:strip)
  end

  data = module_info.nil? ? [] : {}
  arch_filter = !arch.nil? && !arch.empty? ? arch : nil
  self.framework.nops.each_module('Arch' => arch_filter) do |name, mod|
    if module_info.nil?
      data << name
    else
      tmp_mod_info = ::JSON.parse(Msf::Serializer::Json.dump_module(mod.new), symbolize_names: true)
      data[name] = tmp_mod_info.select { |k,v| module_info.include?(k) }
    end
  end

  { "modules" => data }
end

#rpc_options(mtype, mname) ⇒ Hash

Returns the module's datastore options.

Examples:

Here's how you would use this from the client:

rpc.call('module.options', 'exploit', 'windows/smb/ms08_067_netapi')

Parameters:

  • mtype (String)

    Module type. Supported types include (case-sensitive):

    • exploit

    • auxiliary

    • post

    • nop

    • payload

  • mname (String)

    Module name. For example: 'windows/wlan/wlan_profile'.

Returns:

  • (Hash)

    The module's datastore options. This will actually give you each option's data type, requirement state, basic/advanced type, description, default value, etc.

Raises:


444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 444

def rpc_options(mtype, mname)
  m = _find_module(mtype,mname)
  res = {}

  m.options.each_key do |k|
    o = m.options[k]
    res[k] = {
      'type'     => o.type,
      'required' => o.required,
      'advanced' => o.advanced,
      'evasion'  => o.evasion,
      'desc'     => o.desc
    }

    if(not o.default.nil?)
      res[k]['default'] = o.default
    end

    if(o.enums.length > 1)
      res[k]['enums'] = o.enums
    end
  end

  res
end

#rpc_payloads(module_info = nil, arch = nil) ⇒ Hash

Returns a list of payload module names or a hash with payload module names as keys to hashes that contain the module information fields requested. The 'payload/' prefix will not be included.

If this is nil, then only module names are returned. Default: nil the module must support. The module need only support one of the architectures to be included, not all architectures. Default: nil

If module_info is not nil, payload module names as keys to hashes that contain the requested module information fields. It contains the following key:

* 'modules' [Hash] for example:
  {"windows/x64/shell_reverse_tcp"=>{"name"=>"Windows x64 Command Shell, Reverse TCP Inline"}

Examples:

Here's how you would use this from the client:

rpc.call('module.payloads')

Parameters:

  • module_info (String) (defaults to: nil)

    Comma-separated list of module information field names.

  • arch (String) (defaults to: nil)

    Comma-separated list of one or more architectures that

Returns:

  • (Hash)

    If module_info is nil, a list of payload module names. It contains the following key:

    • 'modules' [Array<String>] Payload module names, for example: ['windows/x64/shell_reverse_tcp']


59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 59

def rpc_payloads(module_info = nil, arch = nil)
  module_info_contains_size = false

  unless module_info.nil?
    module_info = module_info.strip.split(',').map(&:strip)
    module_info.map!(&:to_sym)
    module_info_contains_size = module_info.include?(:size)
  end

  unless arch.nil?
    arch = arch.strip.split(',').map(&:strip)
  end

  data = module_info.nil? ? [] : {}
  arch_filter = !arch.nil? && !arch.empty? ? arch : nil
  self.framework.payloads.each_module('Arch' => arch_filter) do |name, mod|
    if module_info.nil?
      data << name
    else
      module_instance = mod.new
      if !module_info_contains_size && mod.method_defined?(:generate)
        # Unless the size field is specified in module_info, modify the generate
        # method for the module instance in order to skip payload generation when
        # the size method is called by Msf::Serializer::Json.dump_module, thus
        # reducing the processing time.
        class << module_instance
          def generate
            ''
          end
        end
      end

      tmp_mod_info = ::JSON.parse(Msf::Serializer::Json.dump_module(module_instance), symbolize_names: true)
      data[name] = tmp_mod_info.select { |k,v| module_info.include?(k) }
    end
  end

  { "modules" => data }
end

#rpc_platformsArray<String>

Returns a list of platform names.

Examples:

Here's how you would use this from the client:

rpc.call('module.platforms')

Returns:

  • (Array<String>)

    A list of platform names, for example: ["linux"]


594
595
596
597
598
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 594

def rpc_platforms
  supported_platforms = []
  Msf::Module::Platform.subclasses.each { |c| supported_platforms << c.realname.downcase }
  supported_platforms.sort
end

#rpc_postHash

Returns a list of post module names. The 'post/' prefix will not be included.

Examples:

Here's how you would use this from the client:

rpc.call('module.post')

Returns:

  • (Hash)

    A list of post module names. It contains the following key:

    • 'modules' [Array<string>] Post module names, for example: ['windows/wlan/wlan_profile']


187
188
189
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 187

def rpc_post
  { "modules" => self.framework.post.keys }
end

#rpc_results(uuid) ⇒ Object

TODO: expand these to take a list of UUIDs or stream with event data if required for performance


534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 534

def rpc_results(uuid)
  if (r = self.job_status_tracker.result(uuid))
    if r[:error]
      {"status" => "errored", "error" => r[:error]}
    else
      if r[:result].length == 1
        # A hash of one IP => result
        # TODO: make hashes of IP => result the normal case
        {"status" => "completed", "result" => r[:result].values.first}
      else
        # Either singular check code or multiple hosts
        # TODO: combine underlying code so that nothing returns a bare CheckCode anymore
        {"status" => "completed", "result" => r[:result]}
      end
    end
  elsif self.job_status_tracker.running? uuid
    {"status" => "running"}
  elsif self.job_status_tracker.waiting? uuid
    {"status" => "ready"}
  else
    error(404, "Results not found for module instance #{uuid}")
  end
end

#rpc_running_statsHash

Returns the currently running module stats in each state.

@exampleHere's how you would use this from the client:

rpc.call('module.running_stats')

Returns:

  • (Hash)

    Running module stats that contain the following keys:

    • 'waiting' [Array<string>] The uuids of modules waiting to be kicked off.

    • 'running' [Array<string>] The uuids of modules currently in progress.

    • 'results' [Array<string>] The uuids of module run/check results.


421
422
423
424
425
426
427
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 421

def rpc_running_stats
  {
      "waiting" => self.job_status_tracker.waiting_ids,
      "running" => self.job_status_tracker.running_ids,
      "results" => self.job_status_tracker.result_ids
  }
end

#rpc_search(match) ⇒ Object


290
291
292
293
294
295
296
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 290

def rpc_search(match)
  matches = []
  self.framework.search(match).each do |m|
    matches << module_short_info(m)
  end
  matches
end

#rpc_target_compatible_evasion_payloads(mname, target) ⇒ Hash

Returns the compatible target-specific payloads for an evasion module.

Examples:

Here's how you would use this from the client:

rpc.call('module.target_compatible_evasion_payloads', 'windows/windows_defender_exe')

Parameters:

  • mname (String)

    Evasion module name. For example: windows/windows_defender_exe

  • target (Integer)

    A specific target the evasion module provides.

Returns:

  • (Hash)

    The evasion module's target-specific payloads. It contains the following key:

    • 'payloads' [Array<String>] A list of payloads.

Raises:


401
402
403
404
405
406
407
408
409
410
411
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 401

def rpc_target_compatible_evasion_payloads(mname, target)
  m   = _find_module('evasion',mname)
  res = {}
  res['payloads'] = []
  m.datastore['TARGET'] = target.to_i
  m.compatible_payloads.each do |k|
    res['payloads'] << k[0]
  end

  res
end

#rpc_target_compatible_payloads(mname, target) ⇒ Hash Also known as: rpc_target_compatible_exploit_payloads

Returns the compatible target-specific payloads for an exploit.

Examples:

Here's how you would use this from the client:

# Find all the compatible payloads for target 1 (Windows 2000 Universal)
rpc.call('module.target_compatible_payloads', 'windows/smb/ms08_067_netapi', 1)

Parameters:

  • mname (String)

    Exploit module name. For example: 'windows/smb/ms08_067_netapi'

  • target (Integer)

    A specific target the exploit module provides.

Returns:

  • (Hash)

    The exploit's target-specific payloads. It contains the following key:

    • 'payloads' [Array<string>] A list of payloads.

Raises:


377
378
379
380
381
382
383
384
385
386
387
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 377

def rpc_target_compatible_payloads(mname, target)
  m   = _find_module('exploit',mname)
  res = {}
  res['payloads'] = []
  m.datastore['TARGET'] = target.to_i
  m.compatible_payloads.each do |k|
    res['payloads'] << k[0]
  end

  res
end

#rpc_transform_formatsArray<String>

Returns a list of transform format names.

Examples:

Here's how you would use this from the client:

rpc.call('module.transform_formats')

Returns:

  • (Array<String>)

    A list of transform format names, for example: ["powershell"]


576
577
578
# File 'lib/msf/core/rpc/v10/rpc_module.rb', line 576

def rpc_transform_formats
  ::Msf::Simple::Buffer.transform_formats
end