2005-07-09 21:18:49 +00:00
|
|
|
require 'msf/core'
|
2005-05-21 17:57:00 +00:00
|
|
|
|
|
|
|
module Msf
|
|
|
|
|
2005-06-04 18:55:20 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# ExploitEvents
|
|
|
|
# -------------
|
|
|
|
#
|
|
|
|
# Event notifications that affect exploits.
|
|
|
|
#
|
|
|
|
###
|
2005-05-21 17:57:00 +00:00
|
|
|
module ExploitEvents
|
|
|
|
|
2005-06-05 00:03:23 +00:00
|
|
|
#
|
|
|
|
# Notified when an exploit is successful
|
|
|
|
#
|
|
|
|
def on_exploit_success(exploit)
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|
|
|
|
|
2005-06-05 00:03:23 +00:00
|
|
|
#
|
|
|
|
# Notified when an exploit is unsuccessful
|
|
|
|
#
|
|
|
|
def on_exploit_failure(exploit, reason)
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
2005-06-04 18:55:20 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# Exploit
|
|
|
|
# -------
|
|
|
|
#
|
|
|
|
# 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
|
|
|
|
|
2005-06-04 22:26:42 +00:00
|
|
|
#
|
|
|
|
# The various check codes that can be returned from the ``check'' routine.
|
|
|
|
#
|
|
|
|
module CheckCode
|
|
|
|
Safe = [ 0, "The target is not exploitable." ]
|
|
|
|
Detected = [ 1, "The target service is running, but could not be validated." ]
|
|
|
|
Appears = [ 2, "The target appears to be vulnerable." ]
|
|
|
|
Vulnerable = [ 3, "The target is vulnerable." ]
|
2005-06-05 00:03:23 +00:00
|
|
|
Unsupported = [ 4, "This exploit does not support check." ]
|
2005-06-04 22:26:42 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# The various basic types of exploits
|
|
|
|
#
|
|
|
|
module Type
|
|
|
|
Remote = "remote"
|
|
|
|
Local = "local"
|
|
|
|
Omni = "omnipresent"
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
2005-06-04 22:39:12 +00:00
|
|
|
# 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)
|
2005-06-04 22:26:42 +00:00
|
|
|
#
|
|
|
|
module Stance
|
|
|
|
Aggressive = "aggresive"
|
2005-06-04 22:39:12 +00:00
|
|
|
Passive = "passive"
|
2005-06-04 22:26:42 +00:00
|
|
|
end
|
|
|
|
|
2005-07-12 22:33:46 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# Local
|
|
|
|
# -----
|
|
|
|
#
|
|
|
|
# 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
|
|
|
|
def exploit_type
|
|
|
|
Exploit::Type::Local
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# Remote
|
|
|
|
# ------
|
|
|
|
#
|
|
|
|
# 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
|
|
|
|
def exploit_type
|
|
|
|
Exploit::Type::Remote
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-07-12 23:06:27 +00:00
|
|
|
require 'msf/core/exploit/brute'
|
|
|
|
require 'msf/core/exploit/tcp'
|
|
|
|
require 'msf/core/exploit/dcerpc'
|
|
|
|
|
2005-06-05 00:03:23 +00:00
|
|
|
#
|
|
|
|
# Constructo the clown! Watch as he kills small children with balloons.
|
|
|
|
#
|
|
|
|
def initialize(info = {})
|
|
|
|
super(info)
|
2005-06-05 04:27:57 +00:00
|
|
|
|
|
|
|
self.targets = Rex::Transformer.transform(info['Targets'], Array,
|
|
|
|
[ Target ], 'Targets')
|
2005-07-11 15:34:31 +00:00
|
|
|
self.default_target = info['DefaultTarget']
|
2005-07-15 23:46:05 +00:00
|
|
|
self.payload_info = info['Payload'] || {}
|
2005-06-05 00:03:23 +00:00
|
|
|
end
|
|
|
|
|
2005-06-04 22:26:42 +00:00
|
|
|
##
|
|
|
|
#
|
2005-06-05 00:03:23 +00:00
|
|
|
# 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.
|
2005-06-04 22:26:42 +00:00
|
|
|
#
|
|
|
|
##
|
|
|
|
|
|
|
|
#
|
|
|
|
# Checks to see if the target is vulnerable, returning unsupported if it's
|
|
|
|
# not supported.
|
|
|
|
#
|
|
|
|
def check
|
|
|
|
CheckCode::Unsupported
|
|
|
|
end
|
|
|
|
|
2005-06-04 22:39:12 +00:00
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
#
|
|
|
|
def exploit
|
|
|
|
end
|
|
|
|
|
2005-07-15 23:46:05 +00:00
|
|
|
#
|
|
|
|
# Prepares the module for exploitation, initializes any state, and starts
|
|
|
|
# the payload handler.
|
|
|
|
#
|
|
|
|
def setup
|
|
|
|
if (payload_instance)
|
|
|
|
# Set up the payload handlers
|
|
|
|
payload_instance.setup_handler
|
|
|
|
|
|
|
|
# Start the payload handler
|
|
|
|
payload_instance.start_handler
|
|
|
|
end
|
|
|
|
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)
|
|
|
|
payload_instance.cleanup_handler
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-07-13 18:06:12 +00:00
|
|
|
#
|
|
|
|
# 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)
|
2005-09-22 03:24:32 +00:00
|
|
|
# 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
|
|
|
|
|
|
|
|
#
|
|
|
|
# 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)
|
2005-07-13 18:06:12 +00:00
|
|
|
if (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
|
2005-07-15 23:46:05 +00:00
|
|
|
real_payload = (pinst) ? pinst : self.payload_instance
|
2005-07-13 18:06:12 +00:00
|
|
|
|
|
|
|
if (real_payload == nil)
|
|
|
|
raise MissingPayloadError, "No payload has been selected.",
|
|
|
|
caller
|
|
|
|
end
|
|
|
|
|
|
|
|
# Duplicate the exploit payload requirements
|
2005-07-15 23:46:05 +00:00
|
|
|
reqs = self.payload_info
|
2005-07-13 18:06:12 +00:00
|
|
|
|
|
|
|
# Pass save register requirements to the NOP generator
|
|
|
|
reqs['SaveRegisters'] = nop_save_registers
|
|
|
|
|
2005-09-22 03:24:32 +00:00
|
|
|
return EncodedPayload.create(real_payload, reqs)
|
2005-07-13 18:06:12 +00:00
|
|
|
end
|
|
|
|
|
2005-09-24 19:37:27 +00:00
|
|
|
#
|
|
|
|
# Re-generates an encoded payload, typically called after something in the
|
|
|
|
# datastore has changed.
|
|
|
|
#
|
|
|
|
def regenerate_payload
|
|
|
|
generate_single_payload
|
|
|
|
end
|
|
|
|
|
2005-06-04 22:26:42 +00:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Feature detection
|
2005-06-05 00:03:23 +00:00
|
|
|
# -----------------
|
2005-06-04 22:26:42 +00:00
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
#
|
|
|
|
##
|
|
|
|
|
|
|
|
def supports_check?
|
|
|
|
derived_implementor?(Msf::Exploit, 'check')
|
|
|
|
end
|
|
|
|
|
2005-06-04 22:39:12 +00:00
|
|
|
def supports_exploit?
|
|
|
|
derived_implementor?(Msf::Exploit, 'exploit')
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Returns a hash of the capabilities this exploit module has
|
|
|
|
#
|
|
|
|
def capabilities
|
|
|
|
{
|
|
|
|
'check' => supports_check?,
|
|
|
|
'exploit' => supports_exploit?
|
|
|
|
}
|
|
|
|
end
|
2005-06-04 22:26:42 +00:00
|
|
|
|
|
|
|
##
|
|
|
|
#
|
2005-07-12 22:33:46 +00:00
|
|
|
# Getters/Setters
|
|
|
|
# ---------------
|
|
|
|
#
|
|
|
|
# Querying and set interfaces for some of the exploit's attributes.
|
2005-06-04 22:26:42 +00:00
|
|
|
#
|
|
|
|
##
|
|
|
|
|
2005-06-05 00:03:23 +00:00
|
|
|
#
|
|
|
|
# The module's type
|
|
|
|
#
|
2005-07-14 20:05:41 +00:00
|
|
|
def self.type
|
|
|
|
MODULE_EXPLOIT
|
|
|
|
end
|
|
|
|
|
2005-06-05 00:03:23 +00:00
|
|
|
def type
|
|
|
|
MODULE_EXPLOIT
|
|
|
|
end
|
|
|
|
|
2005-06-04 22:26:42 +00:00
|
|
|
#
|
|
|
|
# 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
|
2005-07-11 15:34:31 +00:00
|
|
|
module_info['Stance'] || Stance::Aggressive
|
2005-06-04 22:39:12 +00:00
|
|
|
end
|
|
|
|
|
2005-09-22 04:53:46 +00:00
|
|
|
#
|
|
|
|
# Returns if the exploit has a passive stance
|
|
|
|
#
|
|
|
|
def passive?
|
|
|
|
(stance == Stance::Passive)
|
|
|
|
end
|
|
|
|
|
2005-07-14 14:46:18 +00:00
|
|
|
#
|
|
|
|
# Returns the active target for this exploit
|
|
|
|
#
|
|
|
|
def target
|
|
|
|
target_idx = datastore['TARGET']
|
|
|
|
|
|
|
|
return (target_idx) ? targets[target_idx.to_i] : nil
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Returns a list of compatible payloads based on platform, architecture,
|
|
|
|
# and size requirements.
|
|
|
|
#
|
|
|
|
def compatible_payloads
|
|
|
|
payloads = []
|
|
|
|
|
|
|
|
framework.payloads.each_module(
|
|
|
|
'Platform' => target ? target.platform : nil,
|
|
|
|
'Arch' => target ? target.arch : nil) { |name, mod|
|
|
|
|
|
|
|
|
# Skip over payloads that are too big
|
|
|
|
if ((payload_space) and
|
|
|
|
(framework.payloads.sizes[name] > payload_space))
|
|
|
|
dlog("#{refname}: Skipping payload #{name} for being too large", 'core',
|
|
|
|
LEV_1)
|
|
|
|
next
|
|
|
|
end
|
|
|
|
|
|
|
|
# This one be compatible!
|
|
|
|
payloads << [ name, mod ]
|
|
|
|
}
|
|
|
|
|
|
|
|
return payloads;
|
|
|
|
end
|
|
|
|
|
2005-07-11 15:34:31 +00:00
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
#
|
|
|
|
def payload_prepend(payload_module)
|
2005-09-30 07:12:32 +00:00
|
|
|
if (target and target['PayloadPrepend'])
|
|
|
|
target['PayloadPrepend']
|
|
|
|
else
|
|
|
|
payload_info['Prepend'] || ''
|
|
|
|
end
|
2005-07-11 15:34:31 +00:00
|
|
|
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(payload_module)
|
2005-09-30 07:12:32 +00:00
|
|
|
if (target and target['PayloadAppend'])
|
|
|
|
target['PayloadAppend']
|
|
|
|
else
|
|
|
|
payload_info['Append'] || ''
|
|
|
|
end
|
2005-07-11 15:34:31 +00:00
|
|
|
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(payload_module)
|
2005-09-30 07:12:32 +00:00
|
|
|
if (target and target['PayloadEncoder'])
|
|
|
|
target['PayloadEncoder']
|
|
|
|
else
|
|
|
|
payload_info['PrependEncoder'] || ''
|
|
|
|
end
|
2005-07-11 15:34:31 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
2005-07-12 22:33:46 +00:00
|
|
|
# Maximum number of nops to use as a hint to the framework.
|
|
|
|
# Nil signifies that the framework should decide.
|
2005-07-11 15:34:31 +00:00
|
|
|
#
|
2005-07-12 22:33:46 +00:00
|
|
|
def payload_max_nops
|
2005-09-30 07:12:32 +00:00
|
|
|
if (target and target['PayloadMaxNops'])
|
|
|
|
target['PayloadMaxNops']
|
|
|
|
else
|
|
|
|
payload_info['MaxNops'] || nil
|
|
|
|
end
|
2005-07-12 22:33:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Minimum number of nops to use as a hint to the framework.
|
|
|
|
# Nil snigifies that the framework should decide.
|
|
|
|
#
|
|
|
|
def payload_min_nops
|
2005-09-30 07:12:32 +00:00
|
|
|
if (target and target['PayloadMinNops'])
|
|
|
|
target['PayloadMinNops']
|
|
|
|
else
|
|
|
|
payload_info['MinNops'] || nil
|
|
|
|
end
|
2005-07-12 22:33:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Returns the maximum amount of room the exploit has for a payload.
|
2005-07-11 15:34:31 +00:00
|
|
|
#
|
|
|
|
def payload_space
|
2005-09-30 07:12:32 +00:00
|
|
|
if (target and target['PayloadSpace'])
|
|
|
|
target['PayloadSpace']
|
|
|
|
elsif (payload_info['Space'])
|
2005-07-15 23:46:05 +00:00
|
|
|
payload_info['Space'].to_i
|
2005-07-14 07:32:11 +00:00
|
|
|
else
|
|
|
|
nil
|
|
|
|
end
|
2005-07-11 15:34:31 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Returns the bad characters that cannot be in any payload used by this
|
|
|
|
# exploit.
|
2005-06-04 22:39:12 +00:00
|
|
|
#
|
2005-07-11 15:34:31 +00:00
|
|
|
def payload_badchars
|
2005-07-15 23:46:05 +00:00
|
|
|
payload_info['BadChars']
|
2005-07-11 15:34:31 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
#
|
2005-07-12 22:33:46 +00:00
|
|
|
# NOP requirements
|
|
|
|
# ----------------
|
|
|
|
#
|
|
|
|
# Hints to the nop generator on how it should perform if it's used.
|
2005-07-11 15:34:31 +00:00
|
|
|
#
|
|
|
|
##
|
|
|
|
|
|
|
|
#
|
|
|
|
# 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.
|
2005-06-04 22:39:12 +00:00
|
|
|
#
|
2005-07-11 15:34:31 +00:00
|
|
|
def nop_save_registers
|
2005-07-12 22:42:58 +00:00
|
|
|
if (target and target.save_registers)
|
|
|
|
return target.save_registers
|
2005-07-11 15:34:31 +00:00
|
|
|
else
|
2005-07-12 22:42:58 +00:00
|
|
|
return module_info['SaveRegisters']
|
2005-07-11 15:34:31 +00:00
|
|
|
end
|
2005-06-04 22:26:42 +00:00
|
|
|
end
|
|
|
|
|
2005-09-24 18:02:24 +00:00
|
|
|
#
|
|
|
|
# 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
|
|
|
|
|
2005-09-22 03:24:32 +00:00
|
|
|
#
|
|
|
|
# Generates a nop sled of a supplied length and returns it to the caller.
|
|
|
|
#
|
|
|
|
def make_nops(count)
|
|
|
|
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_sled = nop.generate_sled(count,
|
|
|
|
'BadChars' => payload_badchars || '',
|
|
|
|
'SaveRegisters' => save_regs)
|
|
|
|
rescue
|
|
|
|
dlog("#{self.refname}: Nop generator #{nop.refname} failed to generate sled for exploit: #{$!}",
|
|
|
|
'core', LEV_1)
|
|
|
|
end
|
|
|
|
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
nop_sled
|
|
|
|
end
|
|
|
|
|
2005-07-15 23:46:05 +00:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# 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 self.payload_instance.handler(*args) if (self.payload_instance)
|
|
|
|
end
|
|
|
|
|
2005-07-12 22:33:46 +00:00
|
|
|
##
|
2005-07-11 15:34:31 +00:00
|
|
|
#
|
|
|
|
# Attributes
|
|
|
|
#
|
2005-07-12 22:33:46 +00:00
|
|
|
##
|
|
|
|
|
2005-07-11 15:34:31 +00:00
|
|
|
#
|
2005-07-12 22:33:46 +00:00
|
|
|
# The list of targets.
|
2005-07-11 15:34:31 +00:00
|
|
|
#
|
2005-07-12 22:33:46 +00:00
|
|
|
attr_reader :targets
|
2005-07-11 15:34:31 +00:00
|
|
|
#
|
2005-07-12 22:33:46 +00:00
|
|
|
# The default target.
|
2005-07-11 15:34:31 +00:00
|
|
|
#
|
2005-07-12 22:33:46 +00:00
|
|
|
attr_reader :default_target
|
|
|
|
#
|
2005-07-13 18:06:12 +00:00
|
|
|
# The payload requirement hash.
|
2005-07-12 22:33:46 +00:00
|
|
|
#
|
2005-07-15 23:46:05 +00:00
|
|
|
attr_reader :payload_info
|
2005-07-13 18:06:12 +00:00
|
|
|
#
|
|
|
|
# The active payload instance.
|
|
|
|
#
|
2005-07-15 23:46:05 +00:00
|
|
|
attr_accessor :payload_instance
|
2005-07-13 18:06:12 +00:00
|
|
|
#
|
2005-07-15 23:46:05 +00:00
|
|
|
# The encoded payload instance. An instance of an
|
|
|
|
# EncodedPayload object.
|
2005-07-13 18:06:12 +00:00
|
|
|
#
|
2005-07-15 23:46:05 +00:00
|
|
|
attr_accessor :payload
|
2005-07-11 15:34:31 +00:00
|
|
|
|
|
|
|
protected
|
2005-06-04 22:26:42 +00:00
|
|
|
|
2005-07-12 22:33:46 +00:00
|
|
|
attr_writer :targets
|
2005-07-11 15:34:31 +00:00
|
|
|
attr_writer :default_target
|
2005-07-15 23:46:05 +00:00
|
|
|
attr_writer :payload_info
|
2005-06-04 22:26:42 +00:00
|
|
|
|
|
|
|
end
|
|
|
|
|
2005-06-04 18:55:20 +00:00
|
|
|
end
|