metasploit-framework/lib/msf/core/payload.rb

159 lines
3.4 KiB
Ruby

require 'msf/core'
module Msf
###
#
# Payload
# -------
#
# This class represents the base class for a logical payload. The framework
# automatically generates payload combinations at runtime which are all
# extended for this Payload as a base class.
#
###
class Payload < Msf::Module
require 'msf/core/payload/single'
require 'msf/core/payload/stager'
# Platform specific includes
require 'msf/core/payload/windows'
# Payload types
module Type
Single = (1 << 0)
Stager = (1 << 1)
Stage = (1 << 2)
end
##
#
# Accessors
#
##
# This module is a payload.
def type
return MODULE_PAYLOAD
end
# Returns the string of bad characters for this payload, if any.
def badchars
return self.module_info['BadChars']
end
# Returns the type of payload, either single or staged. Stage is
# the default because singles and stagers are encouraged to include
# the Single and Stager mixin which override the payload_type.
def payload_type
return Type::Stage
end
# Returns the payload's size. If the payload is staged, the size of the
# first stage is returned.
def size
return (generate() || '').length
end
# Returns the raw payload that has not had variable substitution occur.
def payload
return module_info['Payload']['Payload']
end
# Returns the offsets to variables that must be substitute, if any.
def offsets
return module_info['Payload']['Offsets']
end
# Return the connection associated with this payload, or none if there
# isn't one.
def handler
return module_info['Handler']
end
##
#
# Generation & variable substitution
#
##
# Generates the payload and return the raw buffer
def generate
raw = payload
# If the payload is generated and there are offsets to substitute,
# do that now.
if (raw and offsets)
substitute_vars(raw, offsets)
end
return raw
end
# Substitutes variables with values from the module's datastore in the
# supplied raw buffer for a given set of named offsets. For instance,
# RHOST is substituted with the RHOST value from the datastore which will
# have been populated by the framework.
def substitute_vars(raw, offsets)
offsets.each_pair { |name, info|
offset, pack = info
# Give the derived class a chance to substitute this variable
next if (replace_var(raw, name, offset, pack) == true)
# Now it's our turn...
if ((val = datastore[name]))
if (pack == 'ADDR')
val = Rex::Socket.resolv_nbo(val)
elsif (pack == 'RAW')
# Just use the raw value...
else
# NOTE:
# Packing assumes integer format at this point, should fix...
val = [ val.to_i ].pack(pack)
end
# Substitute it
raw[offset, val.length] = val
else
wlog("Missing value for payload offset #{name}, skipping.",
'core', LEV_1)
end
}
end
# Replaces an individual variable in the supplied buffer at an offset
# using the given pack type. This is here to allow derived payloads
# the opportunity to replace advanced variables.
def replace_var(raw, name, offset, pack)
return false
end
# Payload prepending and appending for various situations
attr_accessor :prepend, :append, :prepend_encoder
protected
##
#
# Custom merge operations for payloads
#
##
#
# Merge the name to prefix the existing one and separate them
# with a comma
#
def merge_name(info, val)
if (info['Name'])
info['Name'] = val + ',' + info['Name']
else
info['Name'] = val
end
end
end
end