1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-08-28 23:26:18 +02:00

remove old struct2 code in favour of gem

use the new rex-struct2 gem and remove the code form it's old location

MS-1782
This commit is contained in:
David Maloney 2016-07-15 16:01:21 -05:00
parent b13d0f879a
commit 20d7e9a7a7
No known key found for this signature in database
GPG Key ID: DEDBA9DC3A913DB2
12 changed files with 7 additions and 606 deletions

View File

@ -34,6 +34,7 @@ PATH
rex-powershell
rex-random_identifier
rex-registry
rex-struct2
rex-text
rex-zip
robots
@ -218,12 +219,13 @@ GEM
nokogiri
redcarpet (3.3.4)
rex-java (0.1.2)
rex-powershell (0.1.0)
rex-powershell (0.1.1)
rex-random_identifier
rex-text
rex-random_identifier (0.1.0)
rex-text
rex-registry (0.1.0)
rex-struct2 (0.1.0)
rex-text (0.1.1)
rex-zip (0.1.0)
rex-text

View File

@ -53,6 +53,8 @@ require 'rex/zip'
require 'rex/registry'
# Library for parsing Java serialized streams
require 'rex/java'
# Library for creating C-style Structs
require 'rex/struct2'
# Generic classes
require 'rex/constants'

View File

@ -1,5 +0,0 @@
# -*- coding: binary -*-
# just a shim to load all of the Struct2 libraries
require 'rex/struct2/c_struct_template'

View File

@ -1,181 +0,0 @@
# -*- coding: binary -*-
# Rex::Struct2
module Rex
module Struct2
require 'rex/struct2/s_struct'
class CStruct_Values
def initialize(obj)
@obj = obj
end
def [](*args)
o = @obj[*args]
return if !o
return o.value
end
def []=(*args)
o = @obj[*args[0 .. -2]]
return if !o
o.value = args[-1]
end
# this one is for HD, the whiniest girl around...
# allow for like v.field = whatever
def method_missing(sym, *args)
if sym.to_s[-1] == "="[0]
return self[sym.to_s[0 .. -2]] = args[0]
else
return self[sym.to_s]
end
end
end
class CStruct < SStruct
require 'rex/struct2/element'
require 'rex/struct2/generic'
require 'rex/struct2/s_string'
require 'rex/struct2/c_struct_template'
require 'rex/struct2/restraint'
include Rex::Struct2::Element
attr_reader :v
@@dt_table = {
'int8' => proc { |*a| Rex::Struct2::Generic.new('C', true, *a) },
'uint8' => proc { |*a| Rex::Struct2::Generic.new('C', false, *a) },
'int16v' => proc { |*a| Rex::Struct2::Generic.new('v', true, *a) },
'uint16v' => proc { |*a| Rex::Struct2::Generic.new('v', false, *a) },
'int32v' => proc { |*a| Rex::Struct2::Generic.new('V', true, *a) },
'uint32v' => proc { |*a| Rex::Struct2::Generic.new('V', false, *a) },
'int64v' => proc { |*a| Rex::Struct2::Generic.new('q', true, *a) },
'uint64v' => proc { |*a| Rex::Struct2::Generic.new('Q', false, *a) },
'int16n' => proc { |*a| Rex::Struct2::Generic.new('n', true, *a) },
'uint16n' => proc { |*a| Rex::Struct2::Generic.new('n', false, *a) },
'int32n' => proc { |*a| Rex::Struct2::Generic.new('N', true, *a) },
'uint32n' => proc { |*a| Rex::Struct2::Generic.new('N', false, *a) },
'string' => proc { |*a| Rex::Struct2::SString.new(*a) },
'sstruct' => proc { |*a| Rex::Struct2::SStruct.new(*a) },
'object' => proc { |o| o },
'template' => proc { |o| o.make_struct },
}
# CStruct.typedef(name, factory, ... )
def CStruct.typedef(*args)
while args.length >= 2
name = args.shift
factory = args.shift
@@dt_table[name] = factory
end
end
def initialize(*dts)
super()
@name_table = [ ]
@v = Rex::Struct2::CStruct_Values.new(self)
return self.add_from_dt(*dts)
end
def add_from_dt(*dts)
dts.each { | dt |
return if !dt.kind_of?(Array) || dt.length < 2
type = dt[0]
name = dt[1]
factory = @@dt_table[type]
return if !factory
# call with the arguments passed in
obj = factory.call(*(dt[2 .. -1]))
self.add_object(name, obj)
}
return dts.length
end
def add_object(*objs)
while objs.length >= 2
@name_table << objs.shift
self << objs.shift
end
end
# apply_restraint( name, restraint, name2, restraint2 ... )
def apply_restraint(*ress)
while ress.length >= 2
name = ress.shift
res = ress.shift
self[name].restraint = res
# update the restrainted object, so it will update the value
# of the restrainter, with the initial size. If you don't
# want this behavior, um, you'll have to be careful with what
# you supply as default values...
self[name].update_restraint
end
return self
end
# create_restraints( [ name, stuff_to_restraint_constructor ] ... )
def create_restraints(*ress)
ress.each { |r|
# make a copy before we modify...
r = r.dup
# resolve names into objects
r[1] = self[r[1]] if r[1]
r[2] = self[r[2]] if r[2]
# build and apply the restraint
self.apply_restraint(r[0], Rex::Struct2::Restraint.new(*r[1 .. -1]))
}
return self
end
# ya ya, I know, these are weird. I'm not sure why I even bothered
# to inherit from array...
def [](index, *other)
if index.kind_of?(String)
i = @name_table.index(index)
return if !i
return super(i)
else
return super(index, *other)
end
end
def []=(index, *other)
if index.kind_of?(String)
i = @name_table.index(index)
return if !i
return super(i, *other)
else
return super(index, *other)
end
end
# Produce a list of field names
def keys
@name_table
end
# Iterate through all fields and values
def each_pair(&block)
@name_table.each do |k|
block.call(k, self.v[k])
end
end
end
# end Rex::Struct2
end
end

View File

@ -1,39 +0,0 @@
# -*- coding: binary -*-
# Rex::Struct2
module Rex
module Struct2
class CStructTemplate
require 'rex/struct2/c_struct'
attr_reader :template, :template_create_restraints, :template_apply_restraint
attr_writer :template, :template_create_restraints, :template_apply_restraint
def initialize(*tem)
self.template = tem
self.template_create_restraints = [ ]
self.template_apply_restraint = [ ]
end
def create_restraints(*ress)
self.template_create_restraints = ress
return self
end
def apply_restraint(*ress)
self.template_apply_restraint = ress
return self
end
def make_struct
Rex::Struct2::CStruct.new(*self.template).
create_restraints(*self.template_create_restraints).
apply_restraint(*self.template_apply_restraint)
end
end
# end Rex::Struct2
end
end

View File

@ -1,26 +0,0 @@
# -*- coding: binary -*-
# Rex::Struct2
module Rex
module Struct2
# this is a "constant" element. It's not actually constant, you can set it
# via the constructor and value. It doesn't do from_s/to_s, etc.
# what use is it? Well it's useful for doing constant restraints (like fix
# sized arrays), and probably not a ton more.
class Constant
require 'rex/struct2/element'
include Rex::Struct2::Element
def initialize(value)
self.value = value
end
end
# end Rex::Struct2
end
end

View File

@ -1,44 +0,0 @@
# -*- coding: binary -*-
# Rex::Struct2
module Rex
module Struct2
module Element
# elements should have to_s, but we don't define it here because
# it will just overlap with inheritence and cause issues
attr_reader :value, :restraint, :container
attr_writer :restraint, :container
# update the restraints on any value change
def value=(newval)
@value = newval
self.update_restraint
end
# avoid conflicting with normal namespace length()
def slength
to_s().length()
end
def update_restraint
if self.restraint
# Sort of a hack, but remove the restraint before we update, so we aren't using
# the old restraint during calculating the restraint update value
old_restraint, self.restraint = self.restraint, nil
old_restraint.update(self.slength)
self.restraint = old_restraint
end
if self.container
self.container.update_restraint
end
end
end
# end Rex::Struct2
end
end

View File

@ -1,73 +0,0 @@
# -*- coding: binary -*-
# Rex::Struct2
module Rex
module Struct2
class Generic
require 'rex/struct2/element'
include Rex::Struct2::Element
attr_reader :default
attr_writer :default
attr_accessor :mask, :check_mask
def initialize(packspec, signed=false, default=nil)
@packspec = packspec
@default = default
bytelen = [ -1 ].pack(@packspec).length
self.mask = (1 << (8 * bytelen)) - 1
if signed
self.check_mask = 1 << (8 * bytelen - 1)
else
self.check_mask = 0
end
reset()
end
def reset
self.value = @default
end
def to_s
# I realize this will bomb out if this isn't an integer, for
# example if it is nil. That should only happen for a user
# error so that's what I want it to do...
string = [ @value ].pack(@packspec)
if restraint && restraint.max
return string.slice(0, restraint.max)
else
return string
end
# what to do for restraint.min?!?
end
def from_s(bytes)
value = bytes.unpack(@packspec)[0]
# return nil on unpack error
return if !value
len = slength()
# error on any restraint issues
return if restraint && restraint.max && len > restraint.max
return if restraint && restraint.min && len < restraint.min
# else set our value and return length used for this element
if (value & check_mask) != 0
value = -((~value & mask) + 1)
end
self.value = value
return(len)
end
end
# end Rex::Struct2
end
end

View File

@ -1,54 +0,0 @@
# -*- coding: binary -*-
# Rex::Struct2
module Rex
module Struct2
class Restraint
attr_reader :max_object, :min_object, :should_update,
:max_transform, :min_transform, :max_inv_transform, :min_inv_transform
attr_writer :max_object, :min_object, :should_update,
:max_transform, :min_transform, :max_inv_transform, :min_inv_transform
def initialize(
max_object=nil, min_object=nil, should_update=false,
max_transform=nil, min_transform=nil,
max_inv_transform=nil, min_inv_transform=nil
)
@max_object = max_object
@min_object = min_object
@should_update = should_update
def_trans = proc {|i| i}
@max_transform = max_transform == nil ? def_trans : max_transform
@min_transform = min_transform == nil ? def_trans : min_transform
@max_inv_transform = max_inv_transform == nil ? def_trans : max_inv_transform
@min_inv_transform = min_inv_transform == nil ? def_trans : min_inv_transform
end
def min
return if !min_object
return min_object.value
end
def max
return if !max_object
return max_object.value
end
# update values if request (ie string set field to its length)
def update(value)
return if !@should_update
max_object.value = max_inv_transform.call(value) if max_object
min_object.value = min_inv_transform.call(value) if min_object
end
end
# end Rex::Struct2
end
end

View File

@ -1,72 +0,0 @@
# -*- coding: binary -*-
# Rex::Struct2
module Rex
module Struct2
class SString
require 'rex/struct2/element'
require 'rex/struct2/constant'
include Rex::Struct2::Element
attr_reader :size, :default, :pad
attr_writer :default, :pad
def initialize(size=nil, default=nil, pad=nil)
self.size = size
@default = default
@pad = pad
reset()
end
def size=(newsize)
if !newsize
self.restraint = nil
else
res = Rex::Struct2::Constant.new(newsize)
self.restraint = Rex::Struct2::Restraint.new(res, res, false)
end
end
def reset
self.value = @default
end
def to_s
string = self.value
return if !string
# pad if short
if restraint && restraint.min && self.pad && restraint.min > string.length
string += self.pad * (restraint.min - string.length)
end
# truncate if long
if restraint && restraint.max
string = string.slice(0, restraint.max)
end
return string
end
def from_s(bytes)
# we don't have enough bytes to satisfy our minimum
if restraint && restraint.min && bytes.length < restraint.min
return
end
if restraint && restraint.max
self.value = bytes.slice(0, restraint.max)
else
self.value = bytes.dup
end
return(self.slength)
end
end
# end Rex::Struct2
end
end

View File

@ -1,111 +0,0 @@
# -*- coding: binary -*-
# Rex::Struct2
module Rex
module Struct2
class SStruct
require 'rex/struct2/element'
include Rex::Struct2::Element
attr_reader :leftover, :elements
attr_writer :leftover, :elements
private :elements, :elements=
# watch out!, leftover returns our copy of the string! so don't do
# anything stupid like struct.leftover.slice! !!
def initialize(*opts)
self.elements = [ ]
self.add_element(*opts)
end
def reset
elements.each {|e| e.reset}
return self
end
def add_element(*objs)
objs.each { |o|
elements << o
o.container = self
}
return self
end
def <<(obj)
self.add_element(obj)
end
def to_s
# !!! what do we do on mix restraint issues? just fail?
# maybe throw an exception, because that is most likely
# a usage error
buff = ""
elements.each do |e|
buff << e.to_s
end
if restraint && restraint.max
return buff.slice(0, restraint.max)
else
return buff
end
end
def length
return elements.length
end
def [](obj)
return elements[obj]
end
def each(&block)
return elements.each(&block)
end
def from_s(obytes)
# make my own copy so I can chop it up
bytes = obytes.dup
length = 0
# I don't think we should call update_restraint here, but
# I could have mis thought or something
# if we have a restraint (and if there is a val) truncate
if restraint
max = restraint.max
bytes = bytes.slice(0, max) if max
end
elements.each { |e|
used = e.from_s(bytes)
return if !used
bytes.slice!(0, used)
length += used
}
# make sure we matched out min restraint, else return failure
if restraint
min = restraint.min
return if min && length < min
end
# I guess this is me getting "set", so I should have a value
# and I should update my restraints on set
self.value = obytes.slice(0, length)
self.leftover = bytes
return(length)
end
end
# end Rex::Struct2
end
end

View File

@ -118,6 +118,8 @@ Gem::Specification.new do |spec|
spec.add_runtime_dependency 'rex-registry'
# Library for parsing Java serialized streams
spec.add_runtime_dependency 'rex-java'
# Library for C-style structs
spec.add_runtime_dependency 'rex-struct2'
# rb-readline doesn't work with Ruby Installer due to error with Fiddle:
# NoMethodError undefined method `dlopen' for Fiddle:Module