require 'msf/core'
require 'msf/core/module'

module Msf

###
#
# This module exposes an interface that is used when wanting to receive
# notifications about events pertaining to exploitation.
#
###
module ExploitEvent

	#
	# This method is called when an exploit succeeds.
	#
	def on_exploit_success(exploit, session)
	end

end

###
#
# The exploit class acts as the base class for all exploit modules.  It
# provides a common interface for interacting with exploits at the most basic
# level.
#
###
class Exploit < Msf::Module

	##
	#
	# Default compatibility settings for exploit modules.
	#
	##
	module CompatDefaults
		#
		# Default compatibility specifications for payloads
		#
		Payload =
			{
				# Support reverse, bind, and noconn connection types
				# for all exploits unless expressly disabled.
				'ConnectionType' => 'reverse bind noconn none tunnel',
			}
	end

	##
	#
	# The various check codes that can be returned from the ``check'' routine.
	#
	##
	module CheckCode

		#
		# Can't tell if the target is exploitable or not.
		#
		Unknown     = [-1, "Cannot reliably check exploitability."]

		#
		# The target is safe and is therefore not exploitable.
		#
		Safe        = [ 0, "The target is not exploitable." ]

		#
		# The target is running the service in question but may not be
		# exploitable.
		#
		Detected    = [ 1, "The target service is running, but could not be validated." ]

		#
		# The target appears to be vulnerable.
		#
		Appears     = [ 2, "The target appears to be vulnerable." ]

		#
		# The target is vulnerable.
		#
		Vulnerable  = [ 3, "The target is vulnerable." ]

		#
		# The exploit does not support the check method.
		#
		Unsupported = [ 4, "This exploit does not support check." ]
	end

	#
	# The various basic types of exploits
	#
	module Type

		#
		# Indicates that the exploit is a remote exploit.
		#
		Remote  = "remote"

		#
		# Indicates that the exploit is a local exploit.
		#
		Local   = "local"

		#
		# Indicates that the exploit can work anywhere it damn pleases.
		#
		Omni    = "omnipresent"
	end

	#
	# The types of stances an exploit can take, such as passive or aggressive.
	# Stances indicate whether or not the exploit triggers the exploit without
	# waiting for one or more conditions to be met (aggressive) or whether it
	# must wait for certain conditions to be satisfied before the exploit can
	# be initiated (passive)
	#
	module Stance

		#
		# Used to indicate that an exploit takes an aggressive stance.  This
		# means that the exploit proactively triggers a vulnerability.
		#
		Aggressive = "aggressive"

		#
		# Used to indicate that an exploit takes a passive stance.  This means
		# that the exploit waits for interaction from a client or other entity
		# before being able to trigger the vulnerability.
		#
		Passive    = "passive"
	end

	###
	#
	# The local exploit class is a specialization of the exploit module class that
	# is geared toward exploits that are performed locally.  Locally, in this
	# case, is defined as an exploit that is realized by means other than network
	# communication.
	#
	###
	class Local < Exploit

		#
		# Returns the fact that this exploit is a local exploit.
		#
		def exploit_type
			Exploit::Type::Local
		end
	end

	###
	#
	# The remote exploit class is a specialization of the exploit module class
	# that is geared toward exploits that are performed against targets other than
	# the local machine.  This typically implies exploiting other machines via a
	# network connection, though it is not limited to this scope.
	#
	###
	class Remote < Exploit

		#
		# Initializes the socket array.
		#
		def initialize(info)
			super

			self.sockets = Array.new
		end

		#
		# Returns the fact that this exploit is a remote exploit.
		#
		def exploit_type
			Exploit::Type::Remote
		end

		#
		# Adds a socket to the list of sockets opened by this exploit.
		#
		def add_socket(sock)
			self.sockets << sock
		end

		#
		# Removes a socket from the list of sockets.
		#
		def remove_socket(sock)
			self.sockets.delete(sock)
		end

		#
		# This method is called once a new session has been created on behalf of
		# this exploit instance and all socket connections created by this
		# exploit should be closed.
		#
		def abort_sockets
			sockets.delete_if { |sock|
				if (sock.respond_to?('abortive_close='))
					sock.abortive_close = true
				end

				begin
					sock.close
				rescue ::Exception
				end
				true
			}
		end

	protected

		#
		# The list of sockets established by this exploit.
		#
		attr_accessor :sockets

	end

	#
	# Load all of the exploit mixins
	#
	require 'msf/core/exploit/mixins'

	#
	# Returns an array of all of the exploit mixins.  Lame algorithm right now.
	# We search the Msf::Exploit namespace for all modules that do not have any
	# constants in them.  In the future we can replace this with a better
	# algorithm.  It's just important that it returns an array of all of the
	# mixin modules.
	#
	def self.mixins
		mixins  = []
		wl      = [ Msf::Exploit ]
		visited = {}

		until wl.length == 0
			wl.delete_if { |mod|
				mod.constants.each { |const|
					child = mod.const_get(const)

					next if child.to_s !~ /^Msf::Exploit/

					next if visited[child]

					next if child.kind_of?(::Module) == false

					visited[child] = true

					if child.constants.length > 0
						wl << child
					else
						mixins << child
					end
				}

				true
			}
		end

		return mixins
	end

	#
	# Creates an instance of the exploit module.  Mad skillz.
	#
	def initialize(info = {})

		# Ghetto compat mirroring for payload compatibilities.  This mirrors
		#
		# Payload => Compat => xyz
		#
		# to
		#
		# Compat => Payload => xyz
		if (info['Payload'] and info['Payload']['Compat'])
			info['Compat'] = Hash.new if (info['Compat'] == nil)
			info['Compat']['Payload'] = Hash.new if (info['Compat']['Payload'] == nil)
			info['Compat']['Payload'].update(info['Payload']['Compat'])
		end

		# Call the parent constructor after making any necessary modifications
		# to the information hash.
		super(info)

		self.targets = Rex::Transformer.transform(info['Targets'], Array,
				[ Target ], 'Targets')
		self.default_target = info['DefaultTarget']
		self.payload_info = info['Payload'] || {}
		self.session_count = 0
		self.active_timeout = 120

		if (info['Payload'] and info['Payload']['ActiveTimeout'])
			self.active_timeout = info['Payload']['ActiveTimeout'].to_i
		end

		# All exploits can increase the delay when waiting for a session.
		# However, this only applies to aggressive exploits.
		if aggressive?
			register_advanced_options(
				[
					OptInt.new('WfsDelay', [ false, "Additional delay when waiting for a session", 0 ])
				], Msf::Exploit)
		end

		# Allow all exploits to leverage context keyed encoding
		register_advanced_options(
			[
				OptBool.new('EnableContextEncoding', [ false, "Use transient context when encoding payloads", false ]),
				OptPath.new('ContextInformationFile', [ false, "The information file that contains context information", nil ])
			], Msf::Exploit)

		# Allow all exploits to disable their payload handlers
		register_advanced_options(
			[
				OptBool.new('DisablePayloadHandler', [ false, "Disable the handler code for the selected payload", false ])
			], Msf::Exploit)
	end

	##
	#
	# Core exploit interface
	#
	# These are the methods that exploits will override to perform various
	# tasks, such as checking a target to see if it's vulnerable, automatically
	# selecting a target, or performing an exploit.
	#
	##

	#
	# Checks to see if the target is vulnerable, returning unsupported if it's
	# not supported.
	#
	# This method is designed to be overriden by exploit modules.
	#
	def check
		CheckCode::Unsupported
	end

	#
	# Kicks off the actual exploit.  Prior to this call, the framework will
	# have validated the data store using the options associated with this
	# exploit module.  It will also pre-generate the desired payload, though
	# exploits can re-generate the payload if necessary.
	#
	# This method is designed to be overriden by exploit modules.
	#
	def exploit
	end

	#
	# Performs last-minute sanity checking of auxiliary parameters. This method
	# is called during automated exploitation attempts and allows an
	# auxiliary module to filter bad attempts, obtain more information, and choose
	# better parameters based on the available data. Returning anything that
	# evaluates to "false" will cause this specific auxiliary attempt to
	# be skipped. This method can and will change datastore values and
	# may interact with the backend database.
	#
	def autofilter
		true
	end

	#
	# Provides a list of ports that can be used for matching this module
	# against target systems.
	#
	def autofilter_ports
		@autofilter_ports || []
	end

	#
	# Provides a list of services that can be used for matching this module
	# against target systems.
	#
	def autofilter_services
		@autofilter_services || []
	end

	#
	# Adds a port into the list of ports
	#
	def register_autofilter_ports(ports=[])
		@autofilter_ports ||= []
		@autofilter_ports << ports
		@autofilter_ports.flatten!
		@autofilter_ports.uniq!
	end

	def register_autofilter_services(services=[])
		@autofilter_services ||= []
		@autofilter_services << services
		@autofilter_services.flatten!
		@autofilter_services.uniq!
	end

	#
	# Prepares the module for exploitation, initializes any state, and starts
	# the payload handler.
	#
	def setup
		# Reset the session counts to zero.
		reset_session_counts

		return if not payload_instance
		return if not handler_enabled?

		# Configure the payload handler
		payload_instance.exploit_config = {
			'active_timeout' => self.active_timeout
		}

		# Set up the payload handlers
		payload_instance.setup_handler

		# Start the payload handler
		payload_instance.start_handler

	end

	#
	# Performs any cleanup that may be necessary, such as disconnecting
	# connections and any other such fun things.  If a payload is active then
	# its handler cleanup routines are called as well.
	#
	def cleanup
		if (payload_instance and handler_enabled?)
			payload_instance.cleanup_handler
		end
		self.abort_sockets if self.respond_to?('abort_sockets')
	end

	#
	# Generates the encoded version of the supplied payload using the payload
	# requirements specific to this exploit.  The encoded instance is returned
	# to the caller.  This method is exposed in the manner that it is such
	# that passive exploits and re-generate an encoded payload on the fly
	# rather than having to use the pre-generated one.
	#
	# The return value is an EncodedPayload instance.
	#
	def generate_payload(pinst = nil)
		# Set the encoded payload to the result of the encoding process
		self.payload = generate_single_payload(pinst)

		# Save the payload instance
		self.payload_instance = (pinst) ? pinst : self.payload_instance

		return self.payload
	end

	#
	# Allows arbitrary shellcode to be encoded from within an exploit
	#
	def encode_shellcode_stub(code, badchars=payload_badchars)
		platform = self.platform
		if(self.payload_instance)
			self.payload_instance.platform
		end
		compatible_encoders.each do |name, mod|
			begin
				enc = framework.encoders.create(name)
				raw = enc.encode(code, badchars, nil, platform)
				return raw if raw
			rescue ::Exception
			end
		end
		nil
	end

	#
	# Allows the payload handler to spawn a new monitor
	#
	def add_handler(opts={})
		return if not payload_instance
		return if not handler_enabled?
		payload_instance.add_handler(opts)
	end

	#
	# This method generates a non-cached payload which is typically useful for
	# passive exploits that will have more than one client.
	#
	def generate_single_payload(pinst = nil, platform = nil, arch = nil, explicit_target = nil)
		explicit_target ||= target

		if (explicit_target == nil)
			raise MissingTargetError, "No target has been specified.",
				caller
		end

		# If a payload instance was supplied, use it, otherwise
		# use the active payload instance
		real_payload = (pinst) ? pinst : self.payload_instance

		if (real_payload == nil)
			raise MissingPayloadError, "No payload has been selected.",
				caller
		end

		# If this is a generic payload, then we should specify the platform
		# and architecture so that it knows how to pass things on.
		if real_payload.kind_of?(Msf::Payload::Generic)
			# Convert the architecture specified into an array.
			if arch and arch.kind_of?(String)
				arch = [ arch ]
			end

			# Define the explicit platform and architecture information only if
			# it's been specified.
			if platform
				real_payload.explicit_platform = Msf::Module::PlatformList.transform(platform)
			end

			if arch
				real_payload.explicit_arch = arch
			end

			# Force it to reset so that it will find updated information.
			real_payload.reset
		end

		# Duplicate the exploit payload requirements
		reqs = self.payload_info.dup

		# Pass save register requirements to the NOP generator
		reqs['Space']           = payload_space(explicit_target)
		reqs['SaveRegisters']   = nop_save_registers(explicit_target)
		reqs['Prepend']         = payload_prepend(explicit_target)
		reqs['PrependEncoder']  = payload_prepend_encoder(explicit_target)
		reqs['BadChars']        = payload_badchars(explicit_target)
		reqs['Append']          = payload_append(explicit_target)
		reqs['MaxNops']         = payload_max_nops(explicit_target)
		reqs['MinNops']         = payload_min_nops(explicit_target)
		reqs['Encoder']         = datastore['ENCODER']
		reqs['Nop']             = datastore['NOP']
		reqs['EncoderType']     = payload_encoder_type(explicit_target)
		reqs['EncoderOptions']  = payload_encoder_options(explicit_target)
		reqs['ExtendedOptions'] = payload_extended_options(explicit_target)

		# Pass along the encoder don't fall through flag
		reqs['EncoderDontFallThrough'] = datastore['EncoderDontFallThrough']

		# Incorporate any context encoding requirements that are needed
		define_context_encoding_reqs(reqs)

		# Call the encode begin routine.
		encode_begin(real_payload, reqs)

		# Generate the encoded payload.
		encoded = EncodedPayload.create(real_payload, reqs)

		# Call the encode end routine which is expected to return the actual
		# encoded payload instance.
		return encode_end(real_payload, reqs, encoded)
	end

	#
	# Re-generates an encoded payload, typically called after something in the
	# datastore has changed.  An optional platform and architecture can be
	# supplied as well.
	#
	def regenerate_payload(platform = nil, arch = nil, explicit_target = nil)
		generate_single_payload(nil, platform, arch, explicit_target)
	end

	#
	# Called prior to encoding a payload.
	#
	def encode_begin(real_payload, reqs)
	end

	#
	# Called after an encoded payload has been generated.  This gives exploits
	# or mixins a chance to alter the encoded payload.
	#
	def encode_end(real_payload, reqs, encoded)
		encoded
	end

	##
	#
	# Feature detection
	#
	# These methods check to see if there is a derived implementation of
	# various methods as a way of inferring whether or not a given exploit
	# supports the feature.
	#
	##

	#
	# Returns true if the exploit module supports the check method.
	#
	def supports_check?
		derived_implementor?(Msf::Exploit, 'check')
	end

	#
	# Returns true if the exploit module supports the exploit method.
	#
	def supports_exploit?
		derived_implementor?(Msf::Exploit, 'exploit')
	end

	#
	# Returns a hash of the capabilities this exploit module has support for,
	# such as whether or not it supports check and exploit.
	#
	def capabilities
		{
			'check'       => supports_check?,
			'exploit'     => supports_exploit?
		}
	end

	##
	#
	# Getters/Setters
	#
	# Querying and set interfaces for some of the exploit's attributes.
	#
	##

	#
	# Returns MODULE_EXPLOIT to indicate that this is an exploit module.
	#
	def self.type
		MODULE_EXPLOIT
	end

	#
	# Returns MODULE_EXPLOIT to indicate that this is an exploit module.
	#
	def type
		MODULE_EXPLOIT
	end

	#
	# If we don't know the exploit type, then I guess it's omnipresent!
	#
	def exploit_type
		Type::Omni
	end

	#
	# Generally, all exploits take an aggressive stance.
	#
	def stance
		module_info['Stance'] || Stance::Aggressive
	end

	#
	# Returns true if the exploit has an aggressive stance.
	#
	def aggressive?
		(stance == Stance::Aggressive)
	end

	#
	# Returns if the exploit has a passive stance.
	#
	def passive?
		(stance == Stance::Passive)
	end

	#
	# Returns the active target for this exploit.  If not target has been
	# defined, nil is returned.  If no target was defined but there is a
	# default target, that one will be automatically used.
	#
	def target
		target_idx = target_index

		return (target_idx) ? targets[target_idx.to_i] : nil
	end

	#
	# The target index that has been selected.
	#
	def target_index
		target_idx = datastore['TARGET']

		# Use the default target if one was not supplied.
		if (target_idx == nil and default_target and default_target >= 0)
			target_idx = default_target
		end
		return (target_idx) ? target_idx.to_i : nil
	end

	#
	# Returns the target's platform, or the one assigned to the module itself.
	#
	def target_platform
		(target and target.platform) ? target.platform : platform
	end

	#
	# Returns the target's architecture, or the one assigned to the module
	# itself.
	#
	def target_arch
		(target and target.arch) ? target.arch : (arch == []) ? nil : arch
	end

	#
	# Returns a list of compatible payloads based on platform, architecture,
	# and size requirements.
	#
	def compatible_payloads
		payloads = []


		c_platform = (target and target.platform) ? target.platform : platform
		c_arch     = (target and target.arch)     ? target.arch     : (arch == []) ? nil : arch
		c_arch   ||= [ ARCH_X86 ]

		framework.payloads.each_module(
			'Platform' => c_platform,
			'Arch'     => c_arch ) { |name, mod|

			# Skip over payloads that are too big
			if ((payload_space) and
			    (framework.payloads.sizes[name]) and
			    (framework.payloads.sizes[name] > payload_space))
				dlog("#{refname}: Skipping payload #{name} for being too large", 'core',
					LEV_1)
				next
			end

			# Are we compatible in terms of conventions and connections and
			# what not?
			next if (compatible?(framework.payloads.instance(name)) == false)

			# If the payload is privileged but the exploit does not give
			# privileged access, then fail it.
			next if (self.privileged == false and framework.payloads.instance(name).privileged == true)

			# This one be compatible!
			payloads << [ name, mod ]
		}

		return payloads;
	end

	#
	# Returns a list of compatible encoders based on architecture
	#
	def compatible_encoders
		encoders = []

		c_platform = (target and target.platform) ? target.platform : platform
		c_arch     = (target and target.arch)     ? target.arch     : (arch == []) ? nil : arch

		framework.encoders.each_module_ranked(
			'Arch' => c_arch) { |name, mod|

			encoders << [ name, mod ]
		}

		return encoders;
	end

	#
	# This method returns the number of bytes that should be adjusted to the
	# stack pointer prior to executing any code.  The number of bytes to adjust
	# is indicated to the routine through the payload 'StackAdjustment'
	# attribute or through a target's payload 'StackAdjustment' attribute.
	#
	def stack_adjustment
		if (target and target.payload_stack_adjustment)
			adj = target.payload_stack_adjustment
		else
			adj = payload_info['StackAdjustment']
		end

		# Get the architecture for the current target or use the one specific to
		# this exploit
		arch = (target and target.arch) ? target.arch : self.arch

		# Default to x86 if we can't find a list of architectures
		if (arch and arch.empty? == false)
			arch = arch.join(", ")
		else
			arch = 'x86'
		end

		(adj != nil) ? Rex::Arch::adjust_stack_pointer(arch, adj) || '' : ''
	end

	#
	# Return any text that should be prepended to the payload.  The payload
	# module is passed so that the exploit can take a guess at architecture
	# and platform if it's a multi exploit.  This automatically takes into
	# account any require stack adjustments.
	#
	def payload_prepend(explicit_target = nil)
		explicit_target ||= target

		if (explicit_target and explicit_target.payload_prepend)
			p = explicit_target.payload_prepend
		else
			p = payload_info['Prepend'] || ''
		end

		stack_adjustment + p
	end

	#
	# Return any text that should be appended to the payload.  The payload
	# module is passed so that the exploit can take a guess at architecture
	# and platform if it's a multi exploit.
	#
	def payload_append(explicit_target = nil)
		explicit_target ||= target

		if (explicit_target and explicit_target.payload_append)
			explicit_target.payload_append
		else
			payload_info['Append'] || ''
		end
	end

	#
	# Return any text that should be prepended to the encoder of the payload.
	# The payload module is passed so that the exploit can take a guess
	# at architecture and platform if it's a multi exploit.
	#
	def payload_prepend_encoder(explicit_target = nil)
		explicit_target ||= target

		if (explicit_target and explicit_target.payload_prepend_encoder)
			p = explicit_target.payload_prepend_encoder
		else
			p = payload_info['PrependEncoder'] || ''
		end

		p
	end

	#
	# Maximum number of nops to use as a hint to the framework.
	# Nil signifies that the framework should decide.
	#
	def payload_max_nops(explicit_target = nil)
		explicit_target ||= target

		if (explicit_target and explicit_target.payload_max_nops)
			explicit_target.payload_max_nops
		else
			payload_info['MaxNops'] || nil
		end
	end

	#
	# Minimum number of nops to use as a hint to the framework.
	# Nil snigifies that the framework should decide.
	#
	def payload_min_nops(explicit_target = nil)
		explicit_target ||= target

		if (explicit_target and explicit_target.payload_min_nops)
			explicit_target.payload_min_nops
		else
			payload_info['MinNops'] || nil
		end
	end

	#
	# Returns the maximum amount of room the exploit has for a payload.
	#
	def payload_space(explicit_target = nil)
		explicit_target ||= target

		if (explicit_target and explicit_target.payload_space)
			explicit_target.payload_space
		elsif (payload_info['Space'])
			payload_info['Space'].to_i
		else
			nil
		end
	end

	#
	# Returns the bad characters that cannot be in any payload used by this
	# exploit.
	#
	def payload_badchars(explicit_target = nil)
		explicit_target ||= target

		if (explicit_target and explicit_target.payload_badchars)
			explicit_target.payload_badchars
		else
			payload_info['BadChars']
		end
	end

	#
	# Returns the payload encoder type that is associated with either the
	# current target of the exploit in general.
	#
	def payload_encoder_type(explicit_target = nil)
		explicit_target ||= target

		if (explicit_target and explicit_target.payload_encoder_type)
			explicit_target.payload_encoder_type
		else
			payload_info['EncoderType']
		end
	end

	#
	# Returns the payload encoder option hash that is used to initialize the
	# datastore of the encoder that is selected when generating an encoded
	# payload.
	#
	def payload_encoder_options(explicit_target = nil)
		explicit_target ||= target

		if (explicit_target and explicit_target.payload_encoder_options)
			explicit_target.payload_encoder_options
		else
			payload_info['EncoderOptions']
		end
	end

	#
	# Returns the payload extended options hash which is used to provide
	# a location to store extended information that may be useful to
	# a particular type of payload or mixin.
	#
	def payload_extended_options(explicit_target = nil)
		explicit_target ||= target

		if explicit_target and explicit_target.payload_extended_options
			explicit_target.payload_extended_options
		else
			payload_info['ExtendedOptions']
		end
	end

	##
	#
	# NOP requirements
	#
	# Hints to the nop generator on how it should perform if it's used.
	#
	##

	#
	# Returns the list of registers that the NOP generator should save,
	# if any.  It will use the current target's save registers in precedence
	# over those defined globally for the exploit module.
	#
	# If there are no save registers, nil is returned.
	#
	def nop_save_registers(explicit_target = nil)
		explicit_target ||= target

		if (explicit_target and explicit_target.save_registers)
			return explicit_target.save_registers
		else
			return module_info['SaveRegisters']
		end
	end

	#
	# Returns the first compatible NOP generator for this exploit's payload
	# instance.
	#
	def nop_generator
		return nil if (!payload_instance)

		payload_instance.compatible_nops.each { |nopname, nopmod|
			return nopmod.new
		}
	end

	#
	# Generates a nop sled of a supplied length and returns it to the caller.
	#
	def make_nops(count)
		# If we're debugging, then make_nops will return a safe sled.  We
		# currently assume x86.
		if debugging?
			return "\x90" * count
		end

		nop_sled = nil

		# If there is no payload instance then we can't succeed.
		return nil if (!payload_instance)

		payload_instance.compatible_nops.each { |nopname, nopmod|
			# Create an instance of the nop module
			nop = nopmod.new

			# The list of save registers
			save_regs = nop_save_registers || []

			if (save_regs.empty? == true)
				save_regs = nil
			end

			begin
				nop.copy_ui(self)

				nop_sled = nop.generate_sled(count,
					'BadChars'      => payload_badchars || '',
					'SaveRegisters' => save_regs)
			rescue
				wlog("#{self.refname}: Nop generator #{nop.refname} failed to generate sled for exploit: #{$!}",
					'core', LEV_0)
			end

			break
		}

		nop_sled
	end

	##
	#
	# Utility methods for generating random text that implicitly uses the
	# exploit's bad character set.
	#
	##

	#
	# Generate random text characters avoiding the exploit's bad
	# characters.
	#
	def rand_text(length, bad=payload_badchars)
		if debugging?
			"A" * length
		else
			Rex::Text.rand_text(length, bad)
		end
	end

	#
	# Generate random english-like avoiding the exploit's bad
	# characters.
	#
	def rand_text_english(length, bad=payload_badchars)
		if debugging?
			"A" * length
		else
			Rex::Text.rand_text_english(length, bad)
		end
	end

	#
	# Generate random high ascii characters avoiding the exploit's bad
	# characters.
	#
	def rand_text_highascii(length, bad=payload_badchars)
		if debugging?
			"A" * length
		else
			Rex::Text.rand_text_highascii(length, bad)
		end
	end

	#
	# Generate random alpha characters avoiding the exploit's bad
	# characters.
	#
	def rand_text_alpha(length, bad=payload_badchars)
		if debugging?
			"A" * length
		else
			Rex::Text.rand_text_alpha(length, bad)
		end
	end

	#
	# Generate random alpha upper characters avoiding the exploit's bad
	# characters.
	#
	def rand_text_alpha_upper(length, bad=payload_badchars)
		if debugging?
			"A" * length
		else
			Rex::Text.rand_text_alpha_upper(length, bad)
		end
	end

	#
	# Generate random alphan lower characters avoiding the exploit's bad
	# characters.
	#
	def rand_text_alpha_lower(length, bad=payload_badchars)
		if debugging?
			"a" * length
		else
			Rex::Text.rand_text_alpha_lower(length, bad)
		end
	end

	#
	# Generate random alphanumeric characters avoiding the exploit's bad
	# characters.
	#
	def rand_text_alphanumeric(length, bad=payload_badchars)
		if debugging?
			"A" * length
		else
			Rex::Text.rand_text_alphanumeric(length, bad)
		end
	end

	#
	# Generate random numeric characters avoiding the exploit's bad
	# characters.
	#
	def rand_text_numeric(length, bad=payload_badchars)
		if debugging?
			"0" * length
		else
			Rex::Text.rand_text_numeric(length, bad)
		end
	end

	#
	# Generate a random character avoiding the exploit's bad
	# characters.
	#
	def rand_char(bad=payload_badchars)
		if debugging?
			"A"
		else
			Rex::Text.rand_char(bad)
		end
	end

	#
	# Generate a non-repeating static random string
	#
	def pattern_create(length, sets = nil)
		Rex::Text.pattern_create(length, sets)
	end

	#
	# The default "wait for session" delay is zero for all exploits.
	#
	def wfs_delay
		(datastore['WfsDelay'] || 0).to_i
	end

	#
	# Allow the user to disable the payload handler
	#
	def handler_enabled?
		not datastore['DisablePayloadHandler']
	end

	##
	#
	# Handler interaction
	#
	##

	#
	# Passes the connection to the associated payload handler to see if the
	# exploit succeeded and a connection has been established.  The return
	# value can be one of the Handler::constants.
	#
	def handler(*args)
		return if not payload_instance
		return if not handler_enabled?
		return payload_instance.handler(*args)
	end

	##
	#
	# Session tracking
	#
	##

	#
	# This is called by the payload when a new session is created
	#
	def on_new_session(session)
		self.session_count += 1
	end

	#
	# A boolean for whether a session has been created yet
	#
	def session_created?
		(self.session_count > 0) ? true : false
	end

	#
	# Reset the session counter to zero (which occurs during set up of the
	# exploit prior to calling exploit).
	#
	def reset_session_counts
		self.session_count = 0
	end

	##
	#
	# Aliases
	#
	# These allow access to methods inside this class, even if exploits use mixins that
	# override them.
	#
	##

	alias :exploit_regenerate_payload :regenerate_payload


	##
	#
	# Attributes
	#
	##

	#
	# The list of targets.
	#
	attr_reader   :targets
	#
	# The default target.
	#
	attr_reader   :default_target
	#
	# The payload requirement hash.
	#
	attr_reader   :payload_info
	#
	# The active payload instance.
	#
	attr_accessor :payload_instance
	#
	# The encoded payload instance.  An instance of an
	# EncodedPayload object.
	#
	attr_accessor :payload

	#
	# The number of active sessions created by this instance
	#
	attr_reader  :session_count

protected

	#
	# Writable copy of the list of targets.
	#
	attr_writer :targets
	#
	# Writable copy of the default target.
	#
	attr_writer :default_target
	#
	# Writable copy of the payload requirement hash.
	#
	attr_writer :payload_info
	#
	#  Number of sessions created by this exploit instance.
	#
	attr_writer :session_count
	#
	#  Maximum number of seconds for active handlers
	#
	attr_accessor :active_timeout

	#
	# Overrides the base class method and serves to initialize default
	# compatibilities for exploits
	#
	def init_compat
		super

		#
		# Merge in payload compatible defaults
		#
		p = module_info['Compat']['Payload']

		CompatDefaults::Payload.each_pair { |k,v|
			(p[k]) ? p[k] << " #{v}" : p[k] = v
		}

		#
		# Set the default save registers if none have been explicitly
		# specified.
		#
		if (module_info['SaveRegisters'] == nil)
			module_info['SaveRegisters'] = [ 'esp', 'ebp' ]
		end
	end

	#
	# Gets the memory map file and other context information that is
	# required when wanting to support context keyed encoding
	#
	def define_context_encoding_reqs(reqs)
		return if datastore['EnableContextEncoding'] != true

		# At present, we don't support any automatic methods of obtaining
		# context information.  In the future, we might support obtaining
		# temporal information remotely.

		# Pass along the information specified in our exploit datastore as
		# encoder options
		reqs['EncoderOptions'] = {} if reqs['EncoderOptions'].nil?
		reqs['EncoderOptions']['EnableContextEncoding']  = datastore['EnableContextEncoding']
		reqs['EncoderOptions']['ContextInformationFile'] = datastore['ContextInformationFile']
	end

end

end

