# -*- coding: binary -*- ## # $Id$ # Version: $Revision$ ## ## # Rex::OLE - an OLE implementation # written in 2010 by Joshua J. Drake ## 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