class Rex::OLE::DirEntry

This class serves as the base class for SubStorage, Stream, and Directory head

Attributes

_sidChild[RW]
_sidLeftSib[RW]
_sidRightSib[RW]
sid[RW]

Public Class Methods

new(stg) click to toggle source
# File lib/rex/ole/direntry.rb, line 18
def initialize(stg)
  @stg = stg

  # default to a root entry :)
  @sid = 0
  @_ab = "Root Entry"
  @_cb = nil              # NOTE: this is not used until pack
  @_mse = STGTY_ROOT
  @_bflags = 0
  @_sidLeftSib = SECT_FREE
  @_sidRightSib = SECT_FREE
  @_sidChild = SECT_FREE
  @_clsId = CLSID.new
  @_dwUserFlags = 0
  @_ctime = "\x00" * 8
  @_mtime = "\x00" * 8
  @_sectStart = SECT_END
  @_ulSize = 0

  # keep track of logical children (in a tree)
  @children = []
end

Public Instance Methods

<<(expr) click to toggle source
# File lib/rex/ole/direntry.rb, line 46
def <<(expr)
  @children << expr
end
each() { |de| ... } click to toggle source
# File lib/rex/ole/direntry.rb, line 50
def each
  @children.each { |de|
    yield de
  }
end
find_by_sid(sid, de=self) click to toggle source
# File lib/rex/ole/direntry.rb, line 93
def find_by_sid(sid, de=self)
  if (de.sid == sid)
    return de
  end
  @children.each { |cde|
    ret = find_by_sid(cde, sid)
    if (ret)
      return ret
    end
  }
  nil
end
find_stream_by_name_and_type(name, type) click to toggle source

NOTE: this will not look at children

# File lib/rex/ole/direntry.rb, line 81
def find_stream_by_name_and_type(name, type)
  @children.each { |de|
    next if (de.type != type)

    if (de.name == name)
      return de
    end
  }
  nil
end
from_s(sid, buf) click to toggle source

low-level functions

# File lib/rex/ole/direntry.rb, line 110
def from_s(sid, buf)
  @sid = sid
  @_ab           = Util.getUnicodeString(buf[0x00,64])
  @_cb           = Util.get16(buf, 0x40)

  # too big?
  if (@_cb > 0x40)
    raise RuntimeError, 'Invalid directory entry name length %#x' % @_cb
  end

  # mismatch?
  if (@_ab.length > 0)
    declen = ((@_cb) / 2) - 1
    if (declen != @_ab.length)
      raise RuntimeError, 'Directory entry name and length mismatch (%d != %d)' % [declen, @_ab.length]
    end
  end

  @_mse          = Util.get8(buf, 0x42)
  @_bflags       = Util.get8(buf, 0x43)
  @_sidLeftSib   = Util.get32(buf, 0x44)
  @_sidRightSib  = Util.get32(buf, 0x48)
  @_sidChild     = Util.get32(buf, 0x4c)

  # only used for storages..
  @_clsId = CLSID.new(buf[0x50,16])
  @_dwUserFlags  = Util.get32(buf, 0x60)
  @_ctime        = buf[0x64,8]
  @_mtime        = buf[0x6c,8]

  # only used for streams...
  @_sectStart    = Util.get32(buf, 0x74)
  if (@stg.header._uMajorVersion == 4)
    @_ulSize       = Util.get64(buf, 0x78)
  else
    @_ulSize       = Util.get32(buf, 0x78)
  end

  # ignore _dptPropType and pad
end
length() click to toggle source
# File lib/rex/ole/direntry.rb, line 42
def length
  @_ulSize
end
name() click to toggle source
# File lib/rex/ole/direntry.rb, line 64
def name
  @_ab
end
name=(arg) click to toggle source
# File lib/rex/ole/direntry.rb, line 67
def name=(arg)
  # XXX: validate?
  @_ab = arg
end
pack() click to toggle source
# File lib/rex/ole/direntry.rb, line 152
def pack
  @_sectStart ||= SECT_END
  @_cb = (@_ab.length + 1) * 2

  data = ""
  data << Util.putUnicodeString(@_ab) # gets padded/truncated to 0x40 bytes
  data << Util.pack16(@_cb)
  data << Util.pack8(@_mse)
  data << Util.pack8(@_bflags)
  data << Util.pack32(@_sidLeftSib)
  data << Util.pack32(@_sidRightSib)
  data << Util.pack32(@_sidChild)
  data << @_clsId.pack
  data << Util.pack32(@_dwUserFlags)
  data << @_ctime
  data << @_mtime
  data << Util.pack32(@_sectStart)
  data << Util.pack64(@_ulSize)
  data
end
start_sector() click to toggle source
# File lib/rex/ole/direntry.rb, line 72
def start_sector
  @_sectStart
end
start_sector=(expr) click to toggle source
# File lib/rex/ole/direntry.rb, line 75
def start_sector=(expr)
  @_sectStart = expr
end
to_s(extra_spaces=0) click to toggle source
# File lib/rex/ole/direntry.rb, line 174
def to_s(extra_spaces=0)
  @_sectStart ||= SECT_END
  @_cb = (@_ab.length + 1) * 2

  spstr = " " * extra_spaces

  ret = "%s{\n" % spstr
  ret << "%s  sid => 0x%x" % [spstr, @sid]
  ret << ",\n"
  ret << "%s  _ab => \"%s\"" % [spstr, Util.Printable(@_ab)]
  ret << ",\n"
  ret << "%s  _cb => 0x%04x" % [spstr, @_cb]
  ret << ",\n"
  ret << "%s  _mse => 0x%02x" % [spstr, @_mse]
  ret << ",\n"
  ret << "%s  _bflags => 0x%02x" % [spstr, @_bflags]
  ret << ",\n"
  ret << "%s  _sidLeftSib => 0x%08x" % [spstr, @_sidLeftSib]
  ret << ",\n"
  ret << "%s  _sidRightSib => 0x%08x" % [spstr, @_sidRightSib]
  ret << ",\n"
  ret << "%s  _sidChild => 0x%08x" % [spstr, @_sidChild]
  ret << ",\n"
  ret << "%s  _clsId => %s" % [spstr, @_clsId.to_s]
  ret << ",\n"
  ret << "%s  _dwUserFlags => 0x%08x" % [spstr, @_dwUserFlags]
  ret << ",\n"
  ret << "%s  _ctime => %s" % [spstr, Rex::Text.to_hex_dump(@_ctime).strip]
  ret << "\n"
  ret << "%s  _mtime => %s" % [spstr, Rex::Text.to_hex_dump(@_mtime).strip]
  ret << "\n"
  ret << "%s  _sectStart => 0x%08x" % [spstr, @_sectStart]
  ret << ",\n"
  ret << "%s  _ulSize => 0x%016x" % [spstr, @_ulSize]
  if (@_mse == STGTY_STREAM)
    ret << ",\n"
    ret << "%s  data =>\n" % spstr
    if (@data)
      #ret << Util.Printable(@data)
      ret << Rex::Text.to_hex_dump(@data).strip
    else
      if (@_ulSize > 0)
        ret << "--NOT OPENED YET--"
      end
    end
  elsif (@_mse == STGTY_STORAGE) or (@_mse == STGTY_ROOT)
    if (@children.length > 0)
      ret << ",\n"
      ret << "%s  *children* =>\n" % spstr
      @children.each { |de|
        ret << de.to_s(extra_spaces+2)
        ret << "\n"
      }
    end
  end
  ret << "\n"
  ret << "%s}" % spstr
end
type() click to toggle source
# File lib/rex/ole/direntry.rb, line 57
def type
  @_mse
end
type=(arg) click to toggle source
# File lib/rex/ole/direntry.rb, line 60
def type=(arg)
  @_mse = arg
end