146 lines
2.1 KiB
Ruby
146 lines
2.1 KiB
Ruby
# -*- coding: binary -*-
|
|
##
|
|
# $Id$
|
|
# Version: $Revision$
|
|
##
|
|
|
|
##
|
|
# Rex::OLE - an OLE implementation
|
|
# written in 2010 by Joshua J. Drake <jduck [at] metasploit.com>
|
|
##
|
|
|
|
module Rex
|
|
module OLE
|
|
|
|
class Property
|
|
|
|
def initialize(id, type, data)
|
|
@id = id
|
|
@type = type
|
|
@data = data
|
|
end
|
|
|
|
def pack_pio(off = 0)
|
|
[ @id, off ].pack('V*')
|
|
end
|
|
|
|
def pack_data
|
|
buf = [ @type ].pack('V')
|
|
case @type
|
|
when VT_BLOB
|
|
buf << [ @data.length ].pack('V')
|
|
when VT_CF
|
|
buf << [ 4 + @data.length, -1 ].pack('V*')
|
|
end
|
|
buf << @data
|
|
buf
|
|
end
|
|
|
|
def to_s
|
|
"Rex::OLE::Property - to_s unimplemented"
|
|
end
|
|
|
|
end
|
|
|
|
class PropertySet
|
|
|
|
def initialize(fmtid = nil)
|
|
@fmtid = CLSID.new(fmtid)
|
|
@properties = []
|
|
end
|
|
|
|
def <<(val)
|
|
@properties << val
|
|
end
|
|
|
|
def pack_fno(off = 0)
|
|
@fmtid.pack + [ off ].pack('V')
|
|
end
|
|
|
|
def pack_data
|
|
# Pack all the property data
|
|
data = []
|
|
dlen = 0
|
|
@properties.each { |p|
|
|
dat = p.pack_data
|
|
dlen += dat.length
|
|
data << dat
|
|
}
|
|
|
|
buf = ''
|
|
# First the header
|
|
off = 8 + (@properties.length * 8)
|
|
buf << [ off + dlen, @properties.length ].pack('V*')
|
|
# Now, the Property Id and Offset for each
|
|
@properties.each_with_index { |p,x|
|
|
buf << p.pack_pio(off)
|
|
off += data[x].length
|
|
}
|
|
# Finally, all the data
|
|
buf << data.join
|
|
buf
|
|
end
|
|
|
|
def to_s
|
|
"Rex::OLE::PropertySet - to_s unimplemented"
|
|
end
|
|
|
|
end
|
|
|
|
class PropertySetStream
|
|
|
|
def initialize
|
|
@byte_order = 0xfffe
|
|
@ole_version = 0
|
|
@os_version = 1
|
|
@os_platform = 2
|
|
@clsid = CLSID.new
|
|
|
|
@propsets = []
|
|
end
|
|
|
|
def <<(ps)
|
|
@propsets << ps
|
|
end
|
|
|
|
def pack
|
|
buf = ''
|
|
|
|
# First, add the header
|
|
buf << [
|
|
@byte_order,
|
|
@ole_version,
|
|
@os_version,
|
|
@os_platform
|
|
].pack('vvvv')
|
|
buf << @clsid.pack
|
|
buf << [@propsets.length].pack('V')
|
|
|
|
# Pack all the PropertySet children
|
|
data = []
|
|
@propsets.each { |p|
|
|
data << p.pack_data
|
|
}
|
|
|
|
# Next, add all the FMTID and Offset headers
|
|
off = buf.length + (20 * @propsets.length)
|
|
@propsets.each_with_index { |ps,x|
|
|
buf << ps.pack_fno(off)
|
|
off += data[x].length
|
|
}
|
|
|
|
# Finally, add all the data
|
|
buf << data.join
|
|
buf
|
|
end
|
|
|
|
def to_s
|
|
"Rex::OLE::PropertySetStream - to_s unimplemented"
|
|
end
|
|
|
|
end
|
|
|
|
|
|
end
|
|
end
|