lib/msf/core/rpc/v10/rpc_module.rb
# -*- coding: binary -*-
require 'json'
module Msf
module RPC
class RPC_Module < RPC_Base
# Returns a list of exploit names. The 'exploit/' prefix will not be included.
#
# @return [Hash] A list of exploit names. It contains the following key:
# * 'modules' [Array<string>] Exploit names, for example: ['windows/wins/ms04_045_wins']
# @example Here's how you would use this from the client:
# rpc.call('module.exploits')
def rpc_exploits
{ "modules" => self.framework.exploits.module_refnames }
end
# Returns a list of evasion module names. The 'evasion/' prefix will not be included.
#
# @return [Hash] A list of evasion module names. It contains the following key:
# * 'modules' [Array<string>] Evasion names, for example: ['windows/windows_defender_exe']
# @example Here's how you would use this from the client:
# rpc.call('module.evasion')
def rpc_evasion
{ "modules" => self.framework.evasion.module_refnames }
end
# Returns a list of auxiliary module names. The 'auxiliary/' prefix will not be included.
#
# @return [Hash] A list of auxiliary module names. It contains the following key:
# * 'modules' [Array<string>] Auxiliary module names, for example: ['vsploit/pii/web_pii']
# @example Here's how you would use this from the client:
# rpc.call('module.auxiliary')
def rpc_auxiliary
{ "modules" => self.framework.auxiliary.module_refnames }
end
# 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.
#
# @param module_info [String] Comma-separated list of module information field names.
# If this is nil, then only module names are returned. Default: nil
# @param arch [String] Comma-separated list of one or more architectures that
# the module must support. The module need only support one of the architectures
# to be included, not all architectures. Default: nil
#
# @return [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']
# 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"}
# @example Here's how you would use this from the client:
# rpc.call('module.payloads')
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
# 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.
#
# @param module_info [String] Comma-separated list of module information field names.
# If this is nil, then only module names are returned. Default: nil
# @param arch [String] Comma-separated list of one or more architectures that
# the module must support. The module need only support one of the architectures
# to be included, not all architectures. Default: nil
#
# @return [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']
# 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"}}
# @example Here's how you would use this from the client:
# rpc.call('module.encoders')
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
# 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.
#
# @param module_info [String] Comma-separated list of module information field names.
# If this is nil, then only module names are returned. Default: nil
# @param arch [String] Comma-separated list of one or more architectures that
# the module must support. The module need only support one of the architectures
# to be included, not all architectures. Default: nil
#
# @return [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']
# 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"}}
# @example Here's how you would use this from the client:
# rpc.call('module.nops')
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
# Returns a list of post module names. The 'post/' prefix will not be included.
#
# @return [Hash] A list of post module names. It contains the following key:
# * 'modules' [Array<string>] Post module names, for example: ['windows/wlan/wlan_profile']
# @example Here's how you would use this from the client:
# rpc.call('module.post')
def rpc_post
{ "modules" => self.framework.post.module_refnames }
end
# Returns detailed information about a module in HTML.
#
# @return [String] HTML file.
# @example Here's how you would use this from the client:
# rpc.call('module.info_html', 'exploit', 'windows/smb/ms08_067_netapi')
def rpc_info_html(mtype, mname)
m = _find_module(mtype, mname)
Msf::Util::DocumentGenerator.get_module_document(m)
end
# Returns the metadata for a module.
#
# @param [String] mtype Module type. Supported types include (case-sensitive):
# * exploit
# * auxiliary
# * post
# * nop
# * payload
# @param [String] mname Module name. For example: 'windows/wlan/wlan_profile'.
# @raise [Msf::RPC::Exception] Module not found (either the wrong type or name).
# @return [Hash] The module's metadata. The exact keys you will get depends on the module.
# @example 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')
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['check'] = m.has_check?
res['default_options'] = m.default_options
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
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
def rpc_search(match)
matches = []
self.framework.search(match).each do |m|
matches << module_short_info(m)
end
matches
end
# Returns the compatible payloads for a specific exploit.
#
# @param [String] mname Exploit module name. For example: 'windows/smb/ms08_067_netapi'.
# @raise [Msf::RPC::Exception] Module not found (wrong name).
# @return [Hash] The exploit's compatible payloads. It contains the following key:
# * 'payloads' [Array<string>] A list of payloads. For example: ['generic/custom']
# @example Here's how you would use this from the client:
# rpc.call('module.compatible_payloads', 'windows/smb/ms08_067_netapi')
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
alias :rpc_compatible_exploit_payloads :rpc_compatible_payloads
# Returns the compatible payloads for a specific evasion module.
#
# @param [String] mname Evasion module name. For example: 'windows/windows_defender_exe'
# @raise [Msf::RPC::Exception] Module not found (wrong name).
# @return [Hash] The evasion module's compatible payloads. It contains the following key:
# * 'payloads' [Array<String>] A list of payloads.
# @example Here's how you would use this from the client:
# rpc.call('module.compatible_evasion_payloads', 'windows/windows_defender_exe')
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
# Returns the compatible sessions for a specific post module.
#
# @param [String] mname Post module name. For example: 'windows/wlan/wlan_profile'.
# @raise [Msf::RPC::Exception] Module not found (wrong name).
# @return [Hash] The post module's compatible sessions. It contains the following key:
# * 'sessions' [Array<Integer>] A list of session IDs.
# @example Here's how you would use this from the client:
# rpc.call('module.compatible_sessions', 'windows/wlan/wlan_profile')
def rpc_compatible_sessions(mname)
if mname.start_with? 'exploit/'
m = _find_module('exploit',mname)
elsif mname.start_with? 'auxiliary/'
m = _find_module('auxiliary', 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
# Returns the compatible target-specific payloads for an exploit.
#
# @param [String] mname Exploit module name. For example: 'windows/smb/ms08_067_netapi'
# @param [Integer] target A specific target the exploit module provides.
# @raise [Msf::RPC::Exception] Module not found (wrong name).
# @return [Hash] The exploit's target-specific payloads. It contains the following key:
# * 'payloads' [Array<string>] A list of payloads.
# @example 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)
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
alias :rpc_target_compatible_exploit_payloads :rpc_target_compatible_payloads
# Returns the compatible target-specific payloads for an evasion module.
#
# @param [String] mname Evasion module name. For example: windows/windows_defender_exe
# @param [Integer] target A specific target the evasion module provides.
# @raise [Msf::RPC::Exception] Module not found (wrong name)
# @return [Hash] The evasion module's target-specific payloads. It contains the following key:
# * 'payloads' [Array<String>] A list of payloads.
# @example Here's how you would use this from the client:
# rpc.call('module.target_compatible_evasion_payloads', 'windows/windows_defender_exe')
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
# Returns the currently running module stats in each state.
#
# @return [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.
# @exampleHere's how you would use this from the client:
# rpc.call('module.running_stats')
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
# Returns the module's datastore options.
#
# @param [String] mtype Module type. Supported types include (case-sensitive):
# * exploit
# * auxiliary
# * post
# * nop
# * payload
# @param [String] mname Module name. For example: 'windows/wlan/wlan_profile'.
# @raise [Msf::RPC::Exception] Module not found (either wrong type or name).
# @return [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.
# @example Here's how you would use this from the client:
# rpc.call('module.options', 'exploit', 'windows/smb/ms08_067_netapi')
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
# Executes a module.
#
# @param [String] mtype Module type. Supported types include (case-sensitive):
# * exploit
# * auxiliary
# * post
# * payload
# * evasion
# @param [String] mname Module name. For example: 'windows/smb/ms08_067_netapi'.
# @param [Hash] opts Options for the module (such as datastore options).
# @raise [Msf::RPC::Exception] Module not found (either wrong type or name).
# @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.
# @return [Hash] It contains the following keys:
# * 'job_id' [Integer] Job ID.
# * 'uuid' [String] UUID.
# @example 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)
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
# Runs the check method of a module.
#
# @param [String] mtype Module type. Supported types include (case-sensitive):
# * exploit
# * auxiliary
# @param [String] mname Module name. For example: 'windows/smb/ms08_067_netapi'.
# @param [Hash] opts Options for the module (such as datastore options).
# @raise [Msf::RPC::Exception] Module not found (either wrong type or name).
# @return
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
# TODO: expand these to take a list of UUIDs or stream with event data if
# required for performance
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
def rpc_ack(uuid)
{"success" => !!self.job_status_tracker.ack(uuid)}
end
# Returns a list of executable format names.
#
# @return [Array<String>] A list of executable format names, for example: ["exe"]
# @example Here's how you would use this from the client:
# rpc.call('module.executable_formats')
def rpc_executable_formats
::Msf::Util::EXE.to_executable_fmt_formats
end
# Returns a list of transform format names.
#
# @return [Array<String>] A list of transform format names, for example: ["powershell"]
# @example Here's how you would use this from the client:
# rpc.call('module.transform_formats')
def rpc_transform_formats
::Msf::Simple::Buffer.transform_formats
end
# Returns a list of encryption format names.
#
# @return [Array<String>] A list of encryption format names, for example: ["aes256"]
# @example Here's how you would use this from the client:
# rpc.call('module.encryption_formats')
def rpc_encryption_formats
::Msf::Simple::Buffer.encryption_formats
end
# Returns a list of platform names.
#
# @return [Array<String>] A list of platform names, for example: ["linux"]
# @example Here's how you would use this from the client:
# rpc.call('module.platforms')
def rpc_platforms
supported_platforms = []
Msf::Module::Platform.subclasses.each { |c| supported_platforms << c.realname.downcase }
supported_platforms.sort
end
# Returns a list of architecture names.
#
# @return [Array<String>] A list of architecture names, for example: ["x64"]
# @example Here's how you would use this from the client:
# rpc.call('module.architectures')
def rpc_architectures
supported_archs = ARCH_ALL.dup
supported_archs.sort
end
# Returns a list of encoding formats.
#
# @return [Array<String>] Encoding formats.
# @example Here's how you would use this from the client:
# rpc.call('module.encode_formats')
def rpc_encode_formats
# Supported formats
Msf::Simple::Buffer.transform_formats + Msf::Util::EXE.to_executable_fmt_formats
end
# Encodes data with an encoder.
#
# @param [String] data Data to encode.
# @param [encoder] encoder Encoder module name. For example: 'x86/single_byte'.
# @param [Hash] options Encoding options, such as:
# @option options [String] 'format' Encoding format.
# @option options [String] 'badchars' Bad characters.
# @option options [String] 'platform' Platform.
# @option options [String] 'arch' Architecture.
# @option options [Integer] 'ecount' Number of times to encode.
# @option options [TrueClass] 'inject' To enable injection.
# @option options [String] 'template' The template file (an executable).
# @option options [String] 'template_path' Template path.
# @option options [String] 'addshellcode' Custom shellcode.
# @raise [Msf::RPC::Exception] Error could be one of these:
# * 500 Invalid format
# * 500 Failure to encode
# @return The encoded data. It contains the following key:
# * 'encoded' [String] The encoded data in the format you specify.
# @example 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']
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
private
# @param [String] mtype The module type
# @param [String] mname The module name
# @return [Msf::Module] The module if found
# @raise [Msf::RPC::Exception] An exception is raised if the module is not found
def _find_module(mtype,mname)
if mname !~ /^(exploit|payload|nop|encoder|auxiliary|post|evasion)\//
mname = mtype + "/" + mname
elsif !mname.start_with?(mtype)
error(400, "Client provided module type '#{mtype}' did not match expected type for '#{mname}'")
end
mod = self.framework.modules.create(mname)
error(500, "Invalid Module") unless mod
mod
end
def _run_exploit(mod, opts)
if opts['PAYLOAD'].blank?
opts['PAYLOAD'] = Msf::Payload.choose_payload(mod)
end
s = Msf::Simple::Exploit.exploit_simple(mod, {
'Payload' => opts['PAYLOAD'],
'Target' => opts['TARGET'],
'RunAsJob' => true,
'Options' => opts
})
{
"job_id" => mod.job_id,
"uuid" => mod.uuid
}
end
def _run_auxiliary(mod, opts)
uuid, job = Msf::Simple::Auxiliary.run_simple(mod,{
'Action' => opts['ACTION'],
'RunAsJob' => true,
'Options' => opts
}, job_listener: self.job_status_tracker)
{
"job_id" => job,
"uuid" => uuid
}
end
def _check_exploit(mod, opts)
uuid, job = Msf::Simple::Exploit.check_simple(mod,{
'RunAsJob' => true,
'Options' => opts
}, job_listener: self.job_status_tracker)
{
"job_id" => job,
"uuid" => uuid
}
end
def _check_auxiliary(mod, opts)
uuid, job = Msf::Simple::Auxiliary.check_simple(mod,{
'Action' => opts['ACTION'],
'RunAsJob' => true,
'Options' => opts
}, job_listener: self.job_status_tracker)
{
"job_id" => job,
"uuid" => uuid
}
end
def _run_post(mod, opts)
Msf::Simple::Post.run_simple(mod, {
'RunAsJob' => true,
'Options' => opts
})
{
"job_id" => mod.job_id,
"uuid" => mod.uuid
}
end
def _run_evasion(mod, opts)
Msf::Simple::Evasion.run_simple(mod, {
'Payload' => opts['PAYLOAD'],
'Target' => opts['TARGET'],
'RunAsJob' => true,
'Options' => opts
})
{
'job_id' => mod.job_id,
'uuid' => mod.uuid
}
end
def _run_payload(mod, opts)
badchars = opts['BadChars'] || ''
fmt = opts['Format'] || 'raw'
force = opts['ForceEncode'] || false
template = opts['Template'] || nil
plat = opts['Platform'] || nil
keep = opts['KeepTemplateWorking'] || false
force = opts['ForceEncode'] || false
sled_size = opts['NopSledSize'].to_i || 0
iter = opts['Iterations'].to_i || 0
begin
res = Msf::Simple::Payload.generate_simple(mod, {
'BadChars' => badchars,
'Encoder' => opts['Encoder'],
'Format' => fmt,
'NoComment' => true,
'NopSledSize' => sled_size,
'Options' => opts,
'ForceEncode' => force,
'Template' => template,
'Platform' => plat,
'KeepTemplateWorking' => keep,
'Iterations' => iter
})
{ "payload" => res }
rescue ::Exception => e
error(500, "failed to generate: #{e.message}")
end
end
end
end
end