Skip to content

Commit

Permalink
started hacking on payload stuff
Browse files Browse the repository at this point in the history
git-svn-id: file:///home/svn/incoming/trunk@2679 4d416f70-5f16-0410-b530-b9f4589650da
  • Loading branch information
Matt Miller committed Jul 9, 2005
1 parent 19e0a60 commit 40e3636
Show file tree
Hide file tree
Showing 12 changed files with 590 additions and 8 deletions.
1 change: 1 addition & 0 deletions lib/msf/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@
require 'Msf/Core/Encoder'
require 'Msf/Core/Exploit'
require 'Msf/Core/Nop'
require 'Msf/Core/Payload'
require 'Msf/Core/Recon'
49 changes: 48 additions & 1 deletion lib/msf/core/module.rb
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,60 @@ def merge_info(info, opts)
if (self.respond_to?("merge_info_#{name.downcase}"))
eval("merge_info_#{name.downcase}(info, val)")
else
# merge it cool style
# If the info hash already has an entry for this name
if (info[name])
# If it's not an array, convert it to an array and merge the
# two
if (info[name].kind_of?(Array) == false)
curr = info[name]
info[name] = [ curr, val ]
# Otherwise, just append this item to the array entry
else
info[name] << val
end
# Otherwise, just set the value equal if no current value
# exists
else
info[name] = val
end
end
}

return info
end

#
# Merge aliases with an underscore delimiter
#
def merge_info_alias(info, val)
merge_info_string(info, 'Alias', val, '_')
end

#
# Merges the module name
#
def merge_info_name(info, val)
merge_info_string(info, 'Name', val)
end

#
# Merges the module description
#
def merge_info_description(info, val)
merge_info_string(info, 'Description', val)
end

#
# Merges a given key in the info hash with a delimiter
#
def merge_info_string(info, key, val, delim = ', ')
if (info[key])
info[key] = val + delim + info[key]
else
info[key] = val
end
end

#
# Merges options
#
Expand Down
4 changes: 4 additions & 0 deletions lib/msf/core/module/platform_list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ def initialize(*args)
from_a(args) if (args.length)
end

def empty?
return platforms.empty?
end

def from_a(ary)
ary.each { |a|
if a.kind_of?(String)
Expand Down
45 changes: 38 additions & 7 deletions lib/msf/core/module_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ def each_module(opts = {}, &block)
}
end

# Dummy placeholder to relcalculate aliases and other fun things
def recalculate
end

attr_reader :module_type, :full_names

protected
Expand Down Expand Up @@ -110,14 +114,23 @@ def add_module(short_name, full_name, module_class)
###
class ModuleManager < ModuleSet

require 'Msf/Core/PayloadSet'

def initialize()
self.module_paths = []
self.module_history = {}
self.module_history_mtime = {}
self.module_sets = {}

MODULE_TYPES.each { |type|
self.module_sets[type] = ModuleSet.new(type)
case type
when MODULE_PAYLOAD
instance = PayloadSet.new(self)
else
instance = ModuleSet.new(type)
end

self.module_sets[type] = instance
}

super
Expand Down Expand Up @@ -176,6 +189,7 @@ def remove_module_path(path)
# module type)
def load_modules(path)
loaded = {}
recalc = {}

Find.find(path) { |file|

Expand All @@ -200,13 +214,12 @@ def load_modules(path)
# Use the de-pluralized version of the type as necessary
type = md[1].sub(/s$/, '').downcase

# Extract the module namespace
md = path_base.match(/^(.*)#{File::SEPARATOR}(.*?)$/)

next if (!md)

# Prefix Msf to the namespace
namespace = 'Msf::' + md[1].sub(File::SEPARATOR, "::")
namespace = 'Msf::' + md[1].gsub(File::SEPARATOR, "::")

dlog("Loading #{type} module from #{path_base}...", 'core', LEV_1)

Expand Down Expand Up @@ -263,6 +276,9 @@ def load_modules(path)
# right associations
on_module_load(type, added)

# Set this module type as needing recalculation
recalc[type] = true

# Append the added module to the hash of file->module
loaded[file] = added
}
Expand All @@ -275,6 +291,12 @@ def load_modules(path)
# Cache the loaded file module associations
module_history.update(loaded)

# Perform any required recalculations for the individual module types
# that actually had load changes
recalc.each_key { |key|
module_sets[key].recalculate
}

return loaded.values
end

Expand Down Expand Up @@ -314,10 +336,19 @@ def on_module_load(type, mod)
mod_short_name = md[2]
end

# Add the module class to the list of modules and add it to the
# type separated set of module classes
add_module(mod_short_name, mod_full_name, mod)

# Payload modules require custom loading as the individual files
# may not directly contain a logical payload that a user would
# reference, such as would be the case with a payload stager or
# stage. As such, when payload modules are loaded they are handed
# off to a special payload set. The payload set, in turn, will
# automatically create all the permutations after all the payload
# modules have been loaded.
if (type != MODULE_PAYLOAD)
# Add the module class to the list of modules and add it to the
# type separated set of module classes
add_module(mod_short_name, mod_full_name, mod)
end

module_sets[type].add_module(mod_short_name, mod_full_name, mod)
end

Expand Down
153 changes: 153 additions & 0 deletions lib/msf/core/payload.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
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'

# 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 ((p = generate())) ? p.length : 0
end

# Returns the raw payload that has not had variable substitution occur.
def payload
return module_info['Payload']
end

# Returns the offsets to variables that must be substitute, if any.
def offsets
return module_info['Offsets']
end

# Return the connection associated with this payload, or none if there
# isn't one.
def connection
return module_info['Connection'] || "None"
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))

# Now it's our turn...
if ((val = datastore[name]))
if (pack == 'ADDR')
val = Socket.resolv_nbo(host)
elsif (pack == 'RAW')
# Just use the raw value...
else
val = [ val ].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 nil
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
20 changes: 20 additions & 0 deletions lib/msf/core/payload/single.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'Msf/Core'

###
#
# Single
# ------
#
# Base mixin interface for use by single payloads. Single
# payloads are differentiated from stagers and stages by the
# fact that they run as part of the first stage and have
# no subsequent stages.
#
###
module Msf::Payload::Single

def payload_type
return Msf::Payload::Type::Single
end

end
Loading

0 comments on commit 40e3636

Please sign in to comment.