Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/msf/core/exploit.rb
Views: 11780
# -*- coding: binary -*-1module Msf2345###6#7# The exploit class acts as the base class for all exploit modules. It8# provides a common interface for interacting with exploits at the most basic9# level.10#11###12class Exploit < Msf::Module1314##15# Exceptions16##1718# Indicate that the exploit should abort because it has completed19class Complete < RuntimeError20end2122# Indicate that the exploit should abort because it has failed23class Failed < RuntimeError24end252627##28#29# Default compatibility settings for exploit modules.30#31##32module CompatDefaults33#34# Default compatibility specifications for payloads35#36Payload =37{38# Support reverse, bind, and noconn connection types39# for all exploits unless expressly disabled.40'ConnectionType' => 'reverse bind noconn none tunnel',41}42end4344##45#46# The various check codes that can be returned from the ``check'' routine.47# Please read the following wiki to learn how these codes are used:48# https://docs.metasploit.com/docs/development/developing-modules/guides/how-to-write-a-check-method.html49#50##51class CheckCode < Struct.new(:code, :message, :reason, :details)52# Do customization here because we need class constants and special53# optional values and the block mode of Struct.new does not support that.54#55#56# NOTE: This class relies on the array-like interface of Struct classes to57# provide a backwards-compatible interface for the old CheckCode58# representation of `['code', 'message']`. Any change to the order or59# meaning of fields will need to be evaluated for how it affects the rest60# of the codebase.6162class << self63def Unknown(reason = nil, details: {})64self.new('unknown', reason, details: details)65end6667def Safe(reason = nil, details: {})68self.new('safe', reason, details: details)69end7071def Detected(reason = nil, details: {})72self.new('detected', reason, details: details)73end7475def Appears(reason = nil, details: {})76self.new('appears', reason, details: details)77end7879def Vulnerable(reason = nil, details: {})80self.new('vulnerable', reason, details: details)81end8283def Unsupported(reason = nil, details: {})84self.new('unsupported', reason, details: details)85end86end8788# Deprecated, should use #===89#90# If you need to determine whether a CheckCode has the same code and91# message as another one, {Struct#eql?} is the way to go.92def ==(other)93self === other94end9596# Checks to see whether the other object is also a {CheckCode} and if so,97# whether it shares the same code as this one.98def ===(other)99other.is_a?(self.class) && self.code == other.code100end101102def initialize(code, reason, details: {})103msg = case code104when 'unknown'; 'Cannot reliably check exploitability.'105when 'safe'; 'The target is not exploitable.'106when 'detected'; 'The service is running, but could not be validated.'107when 'appears'; 'The target appears to be vulnerable.'108when 'vulnerable'; 'The target is vulnerable.'109when 'unsupported'; 'This module does not support check.'110else111''112end113super(code, "#{msg} #{reason}".strip, reason, details)114end115116#117# Can't tell if the target is exploitable or not. This is recommended if the module fails to118# retrieve enough information from the target machine, such as due to a timeout.119#120Unknown = self.Unknown()121122#123# The target is safe and is therefore not exploitable. This is recommended after the check124# fails to trigger the vulnerability, or even detect the service.125#126Safe = self.Safe()127128#129# The target is running the service in question, but the check fails to determine whether130# the target is vulnerable or not.131#132Detected = self.Detected()133134#135# The target appears to be vulnerable. This is recommended if the vulnerability is determined136# based on passive reconnaissance. For example: version, banner grabbing, or having the resource137# that's known to be vulnerable.138#139Appears = self.Appears()140141#142# The target is vulnerable. Only used if the check is able to actually take advantage of the143# bug, and obtain hard evidence. For example: executing a command on the target machine, and144# retrieve the output.145#146Vulnerable = self.Vulnerable()147148#149# The module does not support the check method.150#151Unsupported = self.Unsupported()152end153154#155# The various basic types of exploits156#157module Type158159#160# Indicates that the exploit is a remote exploit.161#162Remote = "remote"163164#165# Indicates that the exploit is a local exploit.166#167Local = "local"168169#170# Indicates that the exploit can work anywhere it damn pleases.171#172Omni = "omnipresent"173end174175#176# The types of stances an exploit can take, such as passive or aggressive.177# Stances indicate whether or not the exploit triggers the exploit without178# waiting for one or more conditions to be met (aggressive) or whether it179# must wait for certain conditions to be satisfied before the exploit can180# be initiated (passive)181#182module Stance183184#185# Used to indicate that an exploit takes an aggressive stance. This186# means that the exploit proactively triggers a vulnerability.187#188Aggressive = "aggressive"189190#191# Used to indicate that an exploit takes a passive stance. This means192# that the exploit waits for interaction from a client or other entity193# before being able to trigger the vulnerability.194#195Passive = "passive"196end197198199#200# Load all of the exploit mixins201#202203#204# Returns an array of all of the exploit mixins. Lame algorithm right now.205# We search the Msf::Exploit namespace for all modules that do not have any206# constants in them. In the future we can replace this with a better207# algorithm. It's just important that it returns an array of all of the208# mixin modules.209#210# @return [Array]211def self.mixins212mixins = []213wl = [ Msf::Exploit ]214visited = {}215216until wl.length == 0217wl.delete_if { |mod|218mod.constants.each { |const|219child = mod.const_get(const)220221next if child.to_s !~ /^Msf::Exploit/222223next if visited[child]224225next if child.kind_of?(::Module) == false226227visited[child] = true228229if child.constants.length > 0230wl << child231else232mixins << child233end234}235236true237}238end239240return mixins241end242243attr_accessor :needs_cleanup244245#246# Creates an instance of the exploit module. Mad skillz.247#248def initialize(info = {})249250# Ghetto compat mirroring for payload compatibilities. This mirrors251#252# Payload => Compat => xyz253#254# to255#256# Compat => Payload => xyz257if (info['Payload'] and info['Payload']['Compat'])258info['Compat'] = Hash.new if (info['Compat'] == nil)259info['Compat']['Payload'] = Hash.new if (info['Compat']['Payload'] == nil)260info['Compat']['Payload'].update(info['Payload']['Compat'])261end262263# Call the parent constructor after making any necessary modifications264# to the information hash.265super(info)266267if info.key? 'DefaultTarget'268self.default_target = info['DefaultTarget']269else270self.default_target = 0271# Add an auto-target to the exploit if it doesn't have one272if info['Targets'] && info['Targets'].count > 1 && !has_auto_target?(info['Targets'])273# Finally, only add the target if there is a remote host option274if self.respond_to?(:rhost) && self.respond_to?(:auto_targeted_index)275auto = ["Automatic", {'AutoGenerated' => true}.merge(info['Targets'][self.default_target][1])]276info['Targets'].unshift(auto)277end278end279end280281self.targets = Rex::Transformer.transform(info['Targets'], Array, [ Target ], 'Targets')282self.payload_info = info['Payload'] || {}283self.successful = false284self.session_count = 0285self.active_timeout = 120286self.fail_reason = Msf::Exploit::Failure::None287288if (info['Payload'] and info['Payload']['ActiveTimeout'])289self.active_timeout = info['Payload']['ActiveTimeout'].to_i290end291292# Initialize exploit datastore with target information293import_target_defaults294295# All exploits can increase the delay when waiting for a session.296# However, this only applies to aggressive exploits.297if aggressive?298register_advanced_options(299[300OptInt.new('WfsDelay', [ false, "Additional delay in seconds to wait for a session", 2 ])301], Msf::Exploit)302end303304register_advanced_options(305[306# Allow all exploits to leverage context keyed encoding307OptBool.new('EnableContextEncoding', [ false, "Use transient context when encoding payloads", false ]),308OptPath.new('ContextInformationFile', [ false, "The information file that contains context information", nil ]),309# Allow all exploits to disable their payload handlers310OptBool.new('DisablePayloadHandler', [ false, "Disable the handler code for the selected payload", false ])311], Msf::Exploit)312end313314def has_auto_target?(targets=[])315target_names = targets.collect { |target| target.first}316target_names.each do |target|317return true if target =~ /Automatic/318end319return false320end321322##323#324# Core exploit interface325#326# These are the methods that exploits will override to perform various327# tasks, such as checking a target to see if it's vulnerable, automatically328# selecting a target, or performing an exploit.329#330##331332#333# Kicks off the actual exploit. Prior to this call, the framework will334# have validated the data store using the options associated with this335# exploit module. It will also pre-generate the desired payload, though336# exploits can re-generate the payload if necessary.337#338# This method is designed to be overridden by exploit modules.339#340def exploit341end342343#344# Performs last-minute sanity checking of exploit parameters. This method345# is called during automated exploitation attempts and allows an346# exploit to filter bad targets, obtain more information, and choose347# better targets based on the available data. Returning anything that348# evaluates to "false" will cause this specific exploit attempt to349# be skipped. This method can and will change datastore values and350# may interact with the backend database.351#352def autofilter353true354end355356#357# Provides a list of ports that can be used for matching this module358# against target systems.359#360def autofilter_ports361@autofilter_ports || []362end363364#365# Provides a list of services that can be used for matching this module366# against target systems.367#368def autofilter_services369@autofilter_services || []370end371372#373# Adds a port into the list of ports374#375def register_autofilter_ports(ports=[])376@autofilter_ports ||= []377@autofilter_ports << ports378@autofilter_ports.flatten!379@autofilter_ports.uniq!380end381382def register_autofilter_services(services=[])383@autofilter_services ||= []384@autofilter_services << services385@autofilter_services.flatten!386@autofilter_services.uniq!387end388389#390# Prepares the module for exploitation, initializes any state, and starts391# the payload handler.392#393def setup394alert_user395396# Reset the session counts to zero.397reset_session_counts398399return if not payload_instance400return if not handler_enabled?401402# Configure the payload handler403payload_instance.exploit_config = {404'active_timeout' => self.active_timeout405}406407# Set up the payload handlers408payload_instance.setup_handler409410# Defer starting bind handlers until after exploit completion411return if handler_bind?412413# Start the payload handler414payload_instance.start_handler415end416417#418# Performs any cleanup that may be necessary, such as disconnecting419# connections and any other such fun things. If a payload is active then420# its handler cleanup routines are called as well.421#422def cleanup423if (payload_instance and handler_enabled?)424payload_instance.cleanup_handler425end426self.abort_sockets if self.respond_to?(:abort_sockets)427end428429#430# Generates the encoded version of the supplied payload using the payload431# requirements specific to this exploit. The encoded instance is returned432# to the caller. This method is exposed in the manner that it is such433# that passive exploits and re-generate an encoded payload on the fly434# rather than having to use the pre-generated one.435#436# The return value is an EncodedPayload instance.437#438def generate_payload(pinst = nil)439# Set the encoded payload to the result of the encoding process440self.payload = generate_single_payload(pinst)441442# Save the payload instance443self.payload_instance = (pinst) ? pinst : self.payload_instance444445return self.payload446end447448#449# Allows arbitrary shellcode to be encoded from within an exploit450#451def encode_shellcode_stub(code, badchars=payload_badchars)452platform = self.platform453if(self.payload_instance)454self.payload_instance.platform455end456compatible_encoders.each do |name, mod|457begin458enc = framework.encoders.create(name)459raw = enc.encode(code, badchars, nil, platform)460return raw if raw461rescue ::Exception462end463end464nil465end466467#468# Allows the payload handler to spawn a new monitor469#470def add_handler(opts={})471return if not payload_instance472return if not handler_enabled?473payload_instance.add_handler(opts)474end475476#477# This method generates a non-cached payload which is typically useful for478# passive exploits that will have more than one client.479#480def generate_single_payload(pinst = nil, platform = nil, arch = nil, explicit_target = nil)481explicit_target ||= target482483if (explicit_target == nil)484raise MissingTargetError, "No target has been specified.",485caller486end487488# If a payload instance was supplied, use it, otherwise489# use the active payload instance490real_payload = (pinst) ? pinst : self.payload_instance491492if (real_payload == nil)493raise MissingPayloadError, "No payload has been selected.",494caller495end496497# If this is a generic payload, then we should specify the platform498# and architecture so that it knows how to pass things on.499if real_payload.kind_of?(Msf::Payload::Generic)500# Convert the architecture specified into an array.501if arch and arch.kind_of?(String)502arch = [ arch ]503end504505# Define the explicit platform and architecture information only if506# it's been specified.507if platform508real_payload.explicit_platform = Msf::Module::PlatformList.transform(platform)509end510511if arch512real_payload.explicit_arch = arch513end514515# Force it to reset so that it will find updated information.516real_payload.reset517end518519# Duplicate the exploit payload requirements520reqs = self.payload_info.dup521522# Pass save register requirements to the NOP generator523reqs['Space'] = payload_space(explicit_target)524reqs['SaveRegisters'] = nop_save_registers(explicit_target)525reqs['Prepend'] = payload_prepend(explicit_target)526reqs['PrependEncoder'] = payload_prepend_encoder(explicit_target)527reqs['BadChars'] = payload_badchars(explicit_target)528reqs['Append'] = payload_append(explicit_target)529reqs['AppendEncoder'] = payload_append_encoder(explicit_target)530reqs['DisableNops'] = payload_disable_nops(explicit_target)531reqs['MaxNops'] = payload_max_nops(explicit_target)532reqs['MinNops'] = payload_min_nops(explicit_target)533reqs['Encoder'] = datastore['ENCODER'] || payload_encoder(explicit_target)534reqs['Nop'] = datastore['NOP'] || payload_nop(explicit_target)535reqs['EncoderType'] = payload_encoder_type(explicit_target)536reqs['EncoderOptions'] = payload_encoder_options(explicit_target)537reqs['ExtendedOptions'] = payload_extended_options(explicit_target)538reqs['Exploit'] = self539540# Pass along the encoder don't fall through flag541reqs['EncoderDontFallThrough'] = datastore['EncoderDontFallThrough']542543# Incorporate any context encoding requirements that are needed544define_context_encoding_reqs(reqs)545546# Call the encode begin routine.547encode_begin(real_payload, reqs)548549# Generate the encoded payload.550encoded = EncodedPayload.create(real_payload, reqs)551552# Call the encode end routine which is expected to return the actual553# encoded payload instance.554return encode_end(real_payload, reqs, encoded)555end556557#558# Re-generates an encoded payload, typically called after something in the559# datastore has changed. An optional platform and architecture can be560# supplied as well.561#562def regenerate_payload(platform = nil, arch = nil, explicit_target = nil)563generate_single_payload(nil, platform, arch, explicit_target)564end565566#567# Called prior to encoding a payload.568#569def encode_begin(real_payload, reqs)570end571572#573# Called after an encoded payload has been generated. This gives exploits574# or mixins a chance to alter the encoded payload.575#576def encode_end(real_payload, reqs, encoded)577encoded578end579580##581#582# Getters/Setters583#584# Querying and set interfaces for some of the exploit's attributes.585#586##587588#589# Returns MODULE_EXPLOIT to indicate that this is an exploit module.590#591def self.type592Msf::MODULE_EXPLOIT593end594595#596# Returns MODULE_EXPLOIT to indicate that this is an exploit module.597#598def type599Msf::MODULE_EXPLOIT600end601602#603# If we don't know the exploit type, then I guess it's omnipresent!604#605def exploit_type606Type::Omni607end608609#610# Generally, all exploits take an aggressive stance.611#612def stance613module_info['Stance'] || Stance::Aggressive614end615616#617# Returns true if the exploit has an aggressive stance.618#619def aggressive?620stance.include?(Stance::Aggressive)621end622623#624# Returns if the exploit has a passive stance. Aggressive exploits are always aggressive.625#626def passive?627stance.include?(Stance::Passive) && !stance.include?(Stance::Aggressive)628end629630#631# Returns the active target for this exploit. If not target has been632# defined, nil is returned. If no target was defined but there is a633# default target, that one will be automatically used.634#635def target636if self.respond_to?(:auto_targeted_index)637if auto_target?638auto_idx = auto_targeted_index639if auto_idx.present?640datastore['TARGET'] = auto_idx641else642# If our inserted Automatic Target was selected but we failed to643# find a suitable target, we just grab the original first target.644datastore['TARGET'] = 1645end646end647end648649target_idx = target_index650return (target_idx) ? targets[target_idx.to_i] : nil651end652653#654# The target index that has been selected.655#656def target_index657target_idx =658begin659Integer(datastore['TARGET'])660rescue TypeError, ArgumentError661datastore['TARGET']662end663664default_idx = default_target || 0665# Use the default target if one was not supplied.666if (target_idx == nil and default_idx and default_idx >= 0)667target_idx = default_idx668elsif target_idx.is_a?(String)669target_idx = targets.index { |target| target.name == target_idx }670end671672return (target_idx) ? target_idx.to_i : nil673end674675#676# Returns the target's platform, or the one assigned to the module itself.677#678def target_platform679(target and target.platform) ? target.platform : platform680end681682#683# Returns the target's architecture, or the one assigned to the module684# itself.685#686def target_arch687(target and target.arch) ? target.arch : (arch == []) ? nil : arch688end689690def normalize_platform_arch691c_platform = (target && target.platform) ? target.platform : platform692c_arch = (target && target.arch) ? target.arch : (arch == []) ? nil : arch693c_arch ||= [ ARCH_X86 ]694return c_platform, c_arch695end696697#698# Returns whether the requested payload is compatible with the module.699#700# @param name [String] The payload name701# @return [Boolean] True if the payload is compatible, False if it is not.702#703def is_payload_compatible?(name)704p = framework.payloads[name]705return false unless p706707# Skip over payloads that are too big708return false if payload_space && p.cached_size && p.cached_size > payload_space709710begin711pi = p.new712rescue ::Exception, ::LoadError => e713wlog("Module #{name} failed to initialize payload when checking exploit compatibility: #{e}", 'core', LEV_0)714return false715end716717# Are we compatible in terms of conventions and connections and718# what not?719return false if !compatible?(pi)720721# If the payload is privileged but the exploit does not give722# privileged access, then fail it.723return false if !self.privileged && pi.privileged724725return true726end727728# Returns a list of compatible payloads based on platform, architecture,729# and size requirements.730def compatible_payloads(excluded_platforms: [], excluded_archs: [])731payloads = []732733c_platform, c_arch = normalize_platform_arch734735# The "All" platform name represents generic payloads736results = Msf::Modules::Metadata::Cache.instance.find(737'type' => [['payload'], []],738'platform' => [[*c_platform.names, 'All'], excluded_platforms],739'arch' => [c_arch, excluded_archs]740)741742results.each do |res|743if is_payload_compatible?(res.ref_name)744payloads << [res.ref_name, framework.payloads[res.ref_name]]745end746end747748payloads749end750751#752# Returns a list of compatible encoders based on architecture753#754def compatible_encoders755encoders = []756757c_platform, c_arch = normalize_platform_arch758759framework.encoders.each_module_ranked(760'Arch' => c_arch, 'Platform' => c_platform) { |name, mod|761encoders << [ name, mod ]762}763764return encoders;765end766767#768# This method returns the encoded instruction(s) required to adjust the769# stack pointer prior to executing any code. The number of bytes to adjust770# is indicated to the routine through the payload 'StackAdjustment'771# attribute or through a target's payload 'StackAdjustment' attribute.772#773def stack_adjustment774if target && target.payload_stack_adjustment775adj = target.payload_stack_adjustment776else777adj = payload_info['StackAdjustment']778end779780return '' unless adj781782# Get the architecture for the current target or use the one specific to783# this exploit784arch = (target && target.arch) ? target.arch : self.arch785786# Default to x86 if we can't find a list of architectures787if arch && !arch.empty?788arch = [arch].flatten.join(', ')789else790arch = 'x86'791end792793Rex::Arch::adjust_stack_pointer(arch, adj) || ''794end795796#797# Return any text that should be prepended to the payload. The payload798# module is passed so that the exploit can take a guess at architecture799# and platform if it's a multi exploit. This automatically takes into800# account any require stack adjustments.801#802def payload_prepend(explicit_target = nil)803explicit_target ||= target804805if (explicit_target and explicit_target.payload_prepend)806p = explicit_target.payload_prepend807else808p = payload_info['Prepend'] || ''809end810811stack_adjustment + p812end813814#815# Return any text that should be appended to the payload. The payload816# module is passed so that the exploit can take a guess at architecture817# and platform if it's a multi exploit.818#819def payload_append(explicit_target = nil)820explicit_target ||= target821822if (explicit_target and explicit_target.payload_append)823explicit_target.payload_append824else825payload_info['Append'] || ''826end827end828829#830# Return any text that should be prepended to the encoder of the payload.831# The payload module is passed so that the exploit can take a guess832# at architecture and platform if it's a multi exploit.833#834def payload_prepend_encoder(explicit_target = nil)835explicit_target ||= target836837if (explicit_target and explicit_target.payload_prepend_encoder)838p = explicit_target.payload_prepend_encoder839else840p = payload_info['PrependEncoder'] || ''841end842843p844end845846#847# Return any text that should be appended to the encoder of the payload.848# The payload module is passed so that the exploit can take a guess849# at architecture and platform if it's a multi exploit.850#851def payload_append_encoder(explicit_target = nil)852explicit_target ||= target853854if (explicit_target and explicit_target.payload_append_encoder)855p = explicit_target.payload_append_encoder856else857p = payload_info['AppendEncoder'] || ''858end859860p861end862863#864# Whether NOP generation should be enabled or disabled865#866def payload_disable_nops(explicit_target = nil)867explicit_target ||= target868869if (explicit_target and explicit_target.payload_disable_nops)870explicit_target.payload_disable_nops871else872payload_info['DisableNops']873end874end875876#877# Maximum number of nops to use as a hint to the framework.878# Nil signifies that the framework should decide.879#880def payload_max_nops(explicit_target = nil)881explicit_target ||= target882883if (explicit_target and explicit_target.payload_max_nops)884explicit_target.payload_max_nops885else886payload_info['MaxNops'] || nil887end888end889890#891# Minimum number of nops to use as a hint to the framework.892# Nil signifies that the framework should decide.893#894def payload_min_nops(explicit_target = nil)895explicit_target ||= target896897if (explicit_target and explicit_target.payload_min_nops)898explicit_target.payload_min_nops899else900payload_info['MinNops'] || nil901end902end903904#905# Returns the maximum amount of room the exploit has for a payload.906#907def payload_space(explicit_target = nil)908explicit_target ||= target909910if (explicit_target and explicit_target.payload_space)911explicit_target.payload_space912elsif (payload_info['Space'])913payload_info['Space'].to_i914else915nil916end917end918919#920# Returns the bad characters that cannot be in any payload used by this921# exploit.922#923def payload_badchars(explicit_target = nil)924explicit_target ||= target925926if (explicit_target and explicit_target.payload_badchars)927explicit_target.payload_badchars928else929payload_info['BadChars']930end931end932933#934# Returns the payload encoder that is associated with either the935# current target or the exploit in general.936#937def payload_encoder(explicit_target = nil)938explicit_target ||= target939940if (explicit_target and explicit_target.payload_encoder)941explicit_target.payload_encoder942else943payload_info['Encoder']944end945end946947#948# Returns the payload NOP generator that is associated with either the949# current target or the exploit in general.950#951def payload_nop(explicit_target = nil)952explicit_target ||= target953954if (explicit_target and explicit_target.payload_nop)955explicit_target.payload_nop956else957payload_info['Nop']958end959end960961#962# Returns the payload encoder type that is associated with either the963# current target or the exploit in general.964#965def payload_encoder_type(explicit_target = nil)966explicit_target ||= target967968if (explicit_target and explicit_target.payload_encoder_type)969explicit_target.payload_encoder_type970else971payload_info['EncoderType']972end973end974975#976# Returns the payload encoder option hash that is used to initialize the977# datastore of the encoder that is selected when generating an encoded978# payload.979#980def payload_encoder_options(explicit_target = nil)981explicit_target ||= target982983if (explicit_target and explicit_target.payload_encoder_options)984explicit_target.payload_encoder_options985else986payload_info['EncoderOptions']987end988end989990#991# Returns the payload extended options hash which is used to provide992# a location to store extended information that may be useful to993# a particular type of payload or mixin.994#995def payload_extended_options(explicit_target = nil)996explicit_target ||= target997998if explicit_target and explicit_target.payload_extended_options999explicit_target.payload_extended_options1000else1001payload_info['ExtendedOptions']1002end1003end10041005##1006#1007# NOP requirements1008#1009# Hints to the nop generator on how it should perform if it's used.1010#1011##10121013#1014# Returns the list of registers that the NOP generator should save,1015# if any. It will use the current target's save registers in precedence1016# over those defined globally for the exploit module.1017#1018# If there are no save registers, nil is returned.1019#1020def nop_save_registers(explicit_target = nil)1021explicit_target ||= target10221023if (explicit_target and explicit_target.save_registers)1024return explicit_target.save_registers1025else1026return module_info['SaveRegisters']1027end1028end10291030#1031# Returns the first compatible NOP generator for this exploit's payload1032# instance.1033#1034def nop_generator1035return nil if (!payload_instance)10361037payload_instance.compatible_nops.each { |nopname, nopmod|1038return nopmod.new1039}1040end104110421043#1044# Generates a NOP sled using the #make_nops method.1045# The difference between this and #make_nops is this method is much faster, good for exploit1046# developers that actually want huge chunks of NOPs. The downside of using this is the NOP sled1047# is less randomized.1048#1049# @param count [String] Number of NOPs to return.1050# @return [String] NOPs1051#1052def make_fast_nops(count)1053max_nop_chunk_size = 10010541055if count < max_nop_chunk_size1056return make_nops(count)1057end10581059nops = make_nops(max_nop_chunk_size)1060nops += nops while nops.length < count10611062nops[0, count]1063end106410651066#1067# Generates a nop sled of a supplied length and returns it to the caller.1068#1069def make_nops(count)1070# If we're debugging, then make_nops will return a safe sled. We1071# currently assume x86.1072if debugging?1073return "\x90" * count1074end10751076nop_sled = nil10771078# If there is no payload instance then we can't succeed.1079return nil if (!payload_instance)10801081payload_instance.compatible_nops.each { |nopname, nopmod|1082# Create an instance of the nop module1083nop = nopmod.new10841085# The list of save registers1086save_regs = nop_save_registers || []10871088if (save_regs.empty? == true)1089save_regs = nil1090end10911092begin1093nop.copy_ui(self)10941095nop_sled = nop.generate_sled(count,1096'BadChars' => payload_badchars || '',1097'SaveRegisters' => save_regs)10981099if nop_sled && nop_sled.length == count1100break1101else1102wlog("#{self.refname}: Nop generator #{nop.refname} failed to generate sled for exploit", 'core', LEV_0)1103end1104rescue1105wlog("#{self.refname}: Nop generator #{nop.refname} failed to generate sled for exploit: #{$!}",1106'core', LEV_0)1107end1108}11091110nop_sled1111end11121113##1114#1115# Utility methods for generating random text that implicitly uses the1116# exploit's bad character set.1117#1118##11191120def rand_text_debug(length, char = 'A')1121char * (length.kind_of?(Range) ? length.first : length)1122end11231124#1125# Generate random text characters avoiding the exploit's bad1126# characters.1127#1128def rand_text(length, bad=payload_badchars)1129if debugging?1130rand_text_debug(length)1131else1132Rex::Text.rand_text(length, bad)1133end1134end11351136#1137# Generate random english-like avoiding the exploit's bad1138# characters.1139#1140def rand_text_english(length, bad=payload_badchars)1141if debugging?1142rand_text_debug(length)1143else1144Rex::Text.rand_text_english(length, bad)1145end1146end11471148#1149# Generate random high ascii characters avoiding the exploit's bad1150# characters.1151#1152def rand_text_highascii(length, bad=payload_badchars)1153if debugging?1154rand_text_debug(length)1155else1156Rex::Text.rand_text_highascii(length, bad)1157end1158end11591160#1161# Generate random alpha characters avoiding the exploit's bad1162# characters.1163#1164def rand_text_alpha(length, bad=payload_badchars)1165if debugging?1166rand_text_debug(length)1167else1168Rex::Text.rand_text_alpha(length, bad)1169end1170end11711172#1173# Generate random alpha upper characters avoiding the exploit's bad1174# characters.1175#1176def rand_text_alpha_upper(length, bad=payload_badchars)1177if debugging?1178rand_text_debug(length)1179else1180Rex::Text.rand_text_alpha_upper(length, bad)1181end1182end11831184#1185# Generate random alpha lower characters avoiding the exploit's bad1186# characters.1187#1188def rand_text_alpha_lower(length, bad=payload_badchars)1189if debugging?1190rand_text_debug(length, 'a')1191else1192Rex::Text.rand_text_alpha_lower(length, bad)1193end1194end11951196#1197# Generate random alphanumeric characters avoiding the exploit's bad1198# characters.1199#1200def rand_text_alphanumeric(length, bad=payload_badchars)1201if debugging?1202rand_text_debug(length)1203else1204Rex::Text.rand_text_alphanumeric(length, bad)1205end1206end12071208#1209# Generate random numeric characters avoiding the exploit's bad1210# characters.1211#1212def rand_text_numeric(length, bad=payload_badchars)1213if debugging?1214rand_text_debug(length, '0')1215else1216Rex::Text.rand_text_numeric(length, bad)1217end1218end12191220#1221# Generate random hexadecimal characters avoiding the exploit's bad1222# characters.1223#1224def rand_text_hex(length, bad=payload_badchars)1225if debugging?1226rand_text_debug(length, '0')1227else1228Rex::Text.rand_text_hex(length, bad)1229end1230end12311232#1233# Generate a random character avoiding the exploit's bad1234# characters.1235#1236def rand_char(bad=payload_badchars)1237if debugging?1238"A"1239else1240Rex::Text.rand_char(bad)1241end1242end12431244#1245# Generate a non-repeating static random string1246#1247def pattern_create(length, sets = nil)1248Rex::Text.pattern_create(length, sets)1249end12501251#1252# The minimum "wait for session" delay is 3 seconds for all exploits, the1253# WfsDelay configuration option is added on top of this. The delay allows time1254# for the session handler to perform any session verification.1255#1256def wfs_delay1257(datastore['WfsDelay'] || 0).to_i + 31258end12591260#1261# Allow the user to disable the payload handler1262#1263def handler_enabled?1264!datastore['DisablePayloadHandler']1265end12661267#1268# If the payload uses a bind handler1269#1270def handler_bind?1271payload_instance && payload_instance.connection_type == 'bind'1272end12731274##1275#1276# Handler interaction1277#1278##12791280#1281# Passes the connection to the associated payload handler to see if the1282# exploit succeeded and a connection has been established. The return1283# value can be one of the Handler::constants.1284#1285def handler(*args)1286if payload_instance && handler_enabled?1287payload_instance.handler(*args)1288end1289end12901291def interrupt_handler1292if payload_instance && handler_enabled? && payload_instance.respond_to?(:interrupt_wait_for_session)1293payload_instance.interrupt_wait_for_session()1294end1295end12961297##1298#1299# Session tracking1300#1301##13021303#1304# This is called by the payload when a new session is created1305#1306def on_new_session(session)1307self.session_count += 11308self.successful = true1309end13101311#1312# A boolean for whether a session has been created yet1313#1314def session_created?1315# Start bind handlers before checking session creation1316payload_instance.start_handler if handler_bind?13171318(self.session_count > 0) ? true : false1319end13201321#1322# Reset the session counter to zero (which occurs during set up of the1323# exploit prior to calling exploit).1324#1325def reset_session_counts1326self.session_count = 01327end132813291330##1331# Failure tracking1332##13331334# Raises a Msf::Exploit::Failed exception. It overrides the fail_with method1335# in lib/msf/core/module.rb1336#1337# @param reason [String] A constant from Msf::Module::Failure.1338# If the reason does not come from there, then it will default to1339# Msf::Module::Failure::Unknown.1340# @param msg [String] (Optional) A message about the failure.1341# @raise [Msf::Exploit::Failed] A custom Msf::Exploit::Failed exception.1342# @return [void]1343# @see Msf::Module::Failure1344# @see Msf::Module#fail_with1345# @example1346# fail_with(Msf::Module::Failure::NoAccess, 'Unable to login to upload payload')1347def fail_with(reason,msg=nil)1348# The reason being registered here will be used later on, so it's important we don't actually1349# provide a made-up one.1350allowed_values = Msf::Module::Failure.constants.collect {|e| Msf::Module::Failure.const_get(e)}1351if allowed_values.include?(reason)1352self.fail_reason = reason1353else1354self.fail_reason = Msf::Module::Failure::Unknown1355end13561357self.fail_detail = msg1358raise Msf::Exploit::Failed, (msg || "No failure message given")1359end13601361def setup_fail_detail_from_exception e1362# Build a user-friendly error message1363msg = "#{e}"1364unless e.class == Msf::Exploit::Failed1365msg = "#{e.class} #{e}"1366end13671368self.error = e13691370# Record the detailed reason1371self.fail_detail ||= e.to_s1372msg1373end13741375#1376# Handle the exception1377#1378def handle_exception e1379msg = setup_fail_detail_from_exception e13801381case e1382when Msf::Exploit::Complete1383# Nothing to show in this case1384return13851386when Msf::OptionValidateError1387self.fail_reason = Msf::Exploit::Failure::BadConfig1388::Msf::Ui::Formatter::OptionValidateError.print_error(self, e)1389elog("Exploit failed (#{self.refname}): #{msg}", error: e)13901391when Msf::Exploit::Failed1392self.print_error("Exploit aborted due to failure: #{self.fail_reason}: #{msg}")13931394# The caller should have already set self.fail_reason1395if self.fail_reason == Msf::Exploit::Failure::None1396self.fail_reason = Msf::Exploit::Failure::Unknown1397end13981399when Rex::ConnectionError1400self.fail_reason = Msf::Exploit::Failure::Unreachable1401self.print_error("Exploit failed [#{self.fail_reason}]: #{msg}")1402elog("Exploit failed (#{self.refname}): #{msg}", error: e)14031404when Rex::BindFailed1405self.fail_reason = Msf::Exploit::Failure::BadConfig1406self.print_error("Exploit failed [#{self.fail_reason}]: #{msg}")1407elog("Exploit failed (#{self.refname}): #{msg}", error: e)14081409when Timeout::Error1410self.fail_reason = Msf::Exploit::Failure::TimeoutExpired1411self.print_error("Exploit failed [#{self.fail_reason}]: #{msg}")1412elog("Exploit failed (#{self.refname}): #{msg}", error: e)14131414when ::Interrupt1415self.fail_reason = Msf::Exploit::Failure::UserInterrupt1416self.print_error("Exploit failed [#{self.fail_reason}]: #{msg}")1417elog("Exploit failed (#{self.refname}): #{msg}", error: e)1418else14191420# Compare as a string since not all error classes may be loaded1421case msg1422when /access.denied|Login Failed/i # Covers SMB as well as some generic errors1423self.fail_reason = Msf::Exploit::Failure::NoAccess1424when /connection reset/i1425self.fail_reason = Msf::Exploit::Failure::Disconnected1426when /connection timed out|SSL_connect|unreachable|connection was refused/i1427self.fail_reason = Msf::Exploit::Failure::Unreachable1428when /unable.*target/i1429self.fail_reason = Msf::Exploit::Failure::NoTarget1430when /execution expired/i1431self.fail_reason = Msf::Exploit::Failure::TimeoutExpired1432when /(doesn.t|not).*vulnerable|may.*patched/i1433self.fail_reason = Msf::Exploit::Failure::NotVulnerable1434end14351436# The caller should have already set self.fail_reason1437if self.fail_reason == Msf::Exploit::Failure::None1438self.fail_reason = Msf::Exploit::Failure::Unknown1439end14401441if self.fail_reason == Msf::Exploit::Failure::Unknown1442self.print_error("Exploit failed: #{msg}")1443else1444self.print_error("Exploit failed [#{self.fail_reason}]: #{msg}")1445end14461447elog("Exploit failed (#{self.refname}): #{msg}", error: e)1448end14491450# Record the error to various places1451self.framework.events.on_module_error(self, msg)14521453# Report the failure (and attempt) in the database1454self.report_failure14551456# Interrupt any session waiters in the handler1457self.interrupt_handler14581459return self.fail_reason1460end14611462def report_failure1463return unless framework.db and framework.db.active14641465info = {1466:timestamp => Time.now.utc,1467:workspace => framework.db.find_workspace(self.workspace),1468:module => self.fullname,1469:fail_reason => self.fail_reason,1470:fail_detail => self.fail_detail,1471:target_name => self.target.name,1472:username => self.owner,1473:refs => self.references,1474:run_id => self.datastore['RUN_ID']1475}14761477if self.datastore['RHOST'] and self.options['RHOST']1478info[:host] = self.datastore['RHOST']1479end14801481if self.datastore['RPORT'] and self.options['RPORT']1482info[:port] = self.datastore['RPORT']1483if self.class.ancestors.include?(Msf::Exploit::Remote::Tcp)1484info[:proto] = 'tcp'1485end1486end14871488framework.db.report_exploit_failure(info)1489end14901491##1492#1493# Aliases1494#1495# These allow access to methods inside this class, even if exploits use mixins that1496# override them.1497#1498##14991500# Give exploits the ability to use the original +regenerate_payload+ so1501# they can avoid needing additional arguments added by overridden versions.1502# Used specifically by things that include +TcpServer+ (or a descendant)1503# but which are active exploits.1504alias :exploit_regenerate_payload :regenerate_payload150515061507##1508#1509# Attributes1510#1511##15121513#1514# The reason why the exploit was not successful (one of Msf::Module::Failure)1515#1516attr_accessor :fail_reason15171518#1519# Detailed exception string indicating why the exploit was not successful1520#1521attr_accessor :fail_detail15221523#1524# The list of targets.1525#1526attr_reader :targets1527#1528# The default target.1529#1530attr_reader :default_target1531#1532# The payload requirement hash.1533#1534attr_reader :payload_info1535#1536# The active payload instance.1537#1538attr_accessor :payload_instance1539#1540# The encoded payload instance. An instance of an1541# EncodedPayload object.1542#1543attr_accessor :payload15441545#1546# The number of active sessions created by this instance1547#1548attr_reader :session_count15491550#1551# The boolean indicating whether the exploit succeeded1552#1553attr_reader :successful155415551556protected15571558#1559# Writable copy of the list of targets.1560#1561attr_writer :targets1562#1563# Writable copy of the default target.1564#1565attr_writer :default_target1566#1567# Writable copy of the payload requirement hash.1568#1569attr_writer :payload_info1570#1571# Number of sessions created by this exploit instance.1572#1573attr_writer :session_count1574#1575# Maximum number of seconds for active handlers1576#1577attr_accessor :active_timeout15781579#1580# Boolean indicating whether the exploit succeeded1581#1582attr_writer :successful158315841585#1586# Overrides the base class method and serves to initialize default1587# compatibilities for exploits1588#1589def init_compat1590super15911592#1593# Merge in payload compatible defaults1594#1595p = module_info['Compat']['Payload']15961597CompatDefaults::Payload.each_pair { |k,v|1598(p[k]) ? p[k] << " #{v}" : p[k] = v1599}16001601#1602# Set the default save registers if none have been explicitly1603# specified.1604#1605if (module_info['SaveRegisters'] == nil)1606module_info['SaveRegisters'] = [ 'esp', 'ebp' ]1607end1608end16091610#1611# Gets the memory map file and other context information that is1612# required when wanting to support context keyed encoding1613#1614def define_context_encoding_reqs(reqs)1615return unless datastore['EnableContextEncoding']16161617# At present, we don't support any automatic methods of obtaining1618# context information. In the future, we might support obtaining1619# temporal information remotely.16201621# Pass along the information specified in our exploit datastore as1622# encoder options1623reqs['EncoderOptions'] = {} if reqs['EncoderOptions'].nil?1624reqs['EncoderOptions']['EnableContextEncoding'] = datastore['EnableContextEncoding']1625reqs['EncoderOptions']['ContextInformationFile'] = datastore['ContextInformationFile']1626end16271628end16291630end163116321633