## # $Id: header.rb 10394 2010-09-20 08:06:27Z jduck $ # Version: $Revision: 10394 $ ## ## # Rex::OLE - an OLE implementation # written in 2010 by Joshua J. Drake ## # # Should we support major == 4 && sectorshift == 0xc ? # module Rex module OLE require 'rex/ole/util' class Header attr_accessor :_csectFat, :_sectFat attr_accessor :_csectMiniFat, :_sectMiniFatStart attr_accessor :_ulMiniSectorCutoff, :_uMiniSectorShift attr_accessor :_csectDif, :_sectDifStart attr_accessor :_sectDirStart attr_accessor :_uMajorVersion attr_accessor :sector_size, :idx_per_sect attr_accessor :mini_sector_size def initialize set_defaults # calculate some numbers (save a little math) @sector_size = 1 << @_uSectorShift @mini_sector_size = 1 << @_uMiniSectorShift @idx_per_sect = @sector_size / 4 end def set_defaults @_abSig = SIG @_clid = CLSID.new @_uByteOrder = LITTLE_ENDIAN @_uMinorVersion = 0x3e @_uMajorVersion = 0x03 @_uSectorShift = 9 # 512 byte sectors @_uMiniSectorShift = 6 # 64 byte mini-sectors @_csectDir = nil # TBD (v4 only, 1 required) @_csectFat = nil # TBD (one required) @_sectDirStart = nil # TBD (one required) @_signature = 0 # no transactions support @_ulMiniSectorCutoff = 0x1000 # 4k @_sectMiniFatStart = SECT_END # TBD @_csectMiniFat = 0 # TBD @_sectDifStart = SECT_END # TBD (default to none) @_csectDif = 0 # TBD (default to none) @_sectFat = [] # TBD end def to_s ret = "{\n" ret << " _abSig => \"%s\"" % Util.Printable(@_abSig) ret << ",\n" ret << " _clid => %s" % @_clid.to_s ret << ",\n" ret << " _uMinorVersion => 0x%04x" % @_uMinorVersion ret << ",\n" ret << " _uMajorVersion => 0x%04x" % @_uMajorVersion ret << ",\n" ret << " _uByteOrder => 0x%04x" % @_uByteOrder ret << ",\n" ret << " _uSectorShift => 0x%04x" % @_uSectorShift ret << ",\n" ret << " _uMiniSectorShift => 0x%04x" % @_uMiniSectorShift ret << ",\n" if (@_csectDir) ret << " _csectDir => 0x%08x" % @_csectDir else ret << " _csectDir => UNALLOCATED" % @_csectDir end ret << ",\n" if (@_csectFat) ret << " _csectFat => 0x%08x" % @_csectFat else ret << " _csectFat => UNALLOCATED" end ret << ",\n" if (@_sectDirStart) ret << " _sectDirStart => 0x%08x" % @_sectDirStart else ret << " _sectDirStart => UNALLOCATED" end ret << ",\n" ret << " _signature => 0x%08x" % @_signature ret << ",\n" ret << " _uMiniSectorCutoff => 0x%08x" % @_ulMiniSectorCutoff ret << ",\n" ret << " _sectMiniFatStart => 0x%08x" % @_sectMiniFatStart ret << ",\n" ret << " _csectMiniFat => 0x%08x" % @_csectMiniFat ret << ",\n" ret << " _sectDifStart => 0x%08x" % @_sectDifStart ret << ",\n" ret << " _csectDif => 0x%08x" % @_csectDif #ret << ",\n" #ret << " _sectFat => " #ret << Rex::Text.to_hex_dump32array(@_sectFat) ret << "\n}" ret end # # low-level functions # def read(fd) buf = fd.read(HDR_SZ) @_abSig = buf[0x00,8] if (@_abSig != SIG) and (@_abSig != SIG_BETA) raise RuntimeError, 'Invalid signature for OLE file' end @_clid = CLSID.new(buf[0x08,16]) @_uByteOrder = Util.get16(buf, 0x1c) Util.set_endian(@_uByteOrder) @_uMinorVersion = Util.get16(buf, 0x18) @_uMajorVersion = Util.get16(buf, 0x1a) @_uSectorShift = Util.get16(buf, 0x1e) @_uMiniSectorShift = Util.get16(buf, 0x20) # ignore reserved bytes @_csectDir = Util.get32(buf, 0x28) # NOTE: only for v4 files @_csectFat = Util.get32(buf, 0x2c) @_sectDirStart = Util.get32(buf, 0x30) @_signature = Util.get32(buf, 0x34) @_ulMiniSectorCutoff = Util.get32(buf, 0x38) @_sectMiniFatStart = Util.get32(buf, 0x3c) @_csectMiniFat = Util.get32(buf, 0x40) @_sectDifStart = Util.get32(buf, 0x44) @_csectDif = Util.get32(buf, 0x48) @_sectFat = Util.get32array(buf[0x4c, (109 * 4)]) end def write(fd) hdr = "" hdr << @_abSig hdr << @_clid.pack hdr << Util.pack16(@_uMinorVersion) hdr << Util.pack16(@_uMajorVersion) hdr << Util.pack16(@_uByteOrder) hdr << Util.pack16(@_uSectorShift) hdr << Util.pack16(@_uMiniSectorShift) if (@_uMajorVersion == 0x04) hdr << "\x00" * 6 # reserved bytes hdr << Util.pack32(@_csectDir) else hdr << "\x00" * 10 # reserved bytes end fs_count = @_csectFat fs_count ||= 0 hdr << Util.pack32(fs_count) dir_start = @_sectDirStart dir_start ||= SECT_END hdr << Util.pack32(dir_start) hdr << Util.pack32(@_signature) hdr << Util.pack32(@_ulMiniSectorCutoff) hdr << Util.pack32(@_sectMiniFatStart) hdr << Util.pack32(@_csectMiniFat) hdr << Util.pack32(@_sectDifStart) hdr << Util.pack32(@_csectDif) hdr << Util.pack32array(@_sectFat) fd.seek(0, ::IO::SEEK_SET) fd.write(hdr) end end end end