class Rex::Parser::AppleBackupManifestDB

Attributes

entries[RW]
entry_offsets[RW]
mbdb[RW]
mbdb_data[RW]
mbdb_offset[RW]
mbdx[RW]
mbdx_data[RW]
mbdx_offset[RW]

Public Class Methods

from_files(mbdb_file, mbdx_file) click to toggle source
# File lib/rex/parser/apple_backup_manifestdb.rb, line 25
def self.from_files(mbdb_file, mbdx_file)
  mbdb_data = ""
  ::File.open(mbdb_file, "rb") {|fd| mbdb_data = fd.read(fd.stat.size) }
  mbdx_data = ""
  ::File.open(mbdx_file, "rb") {|fd| mbdx_data = fd.read(fd.stat.size) }

  self.new(mbdb_data, mbdx_data)
end
new(mbdb_data, mbdx_data) click to toggle source
# File lib/rex/parser/apple_backup_manifestdb.rb, line 16
def initialize(mbdb_data, mbdx_data)
  self.entries = {}
  self.entry_offsets = {}
  self.mbdb_data = mbdb_data
  self.mbdx_data = mbdx_data
  parse_mbdb
  parse_mbdx
end

Public Instance Methods

mbdb_read_int(size) click to toggle source
# File lib/rex/parser/apple_backup_manifestdb.rb, line 100
def mbdb_read_int(size)
  val = 0
  size.downto(1) do |i|
    val = (val << 8) + self.mbdb_data[self.mbdb_offset, 1].unpack("C")[0]
    self.mbdb_offset += 1
  end
  val
end
mbdb_read_string() click to toggle source
# File lib/rex/parser/apple_backup_manifestdb.rb, line 90
def mbdb_read_string
  raise RuntimeError, "Corrupted MBDB file" if self.mbdb_offset > self.mbdb_data.length
  len = self.mbdb_data[self.mbdb_offset, 2].unpack("n")[0]
  self.mbdb_offset += 2
  return '' if len == 65535
  val = self.mbdb_data[self.mbdb_offset, len]
  self.mbdb_offset += len
  return val
end
mbdx_read_int(size) click to toggle source
# File lib/rex/parser/apple_backup_manifestdb.rb, line 119
def mbdx_read_int(size)
  val = 0
  size.downto(1) do |i|
    val = (val << 8) + self.mbdx_data[self.mbdx_offset, 1].unpack("C")[0]
    self.mbdx_offset += 1
  end
              val
end
mbdx_read_string() click to toggle source
# File lib/rex/parser/apple_backup_manifestdb.rb, line 109
def mbdx_read_string
  raise RuntimeError, "Corrupted MBDX file" if self.mbdx_offset > self.mbdx_data.length
  len = self.mbdx_data[self.mbdx_offset, 2].unpack("n")[0]
  self.mbdx_offset += 2
  return '' if len == 65535
  val = self.mbdx_data[self.mbdx_offset, len]
  self.mbdx_offset += len
  return val
end
parse_mbdb() click to toggle source
# File lib/rex/parser/apple_backup_manifestdb.rb, line 34
def parse_mbdb
  raise ArgumentError, "Not valid MBDB data" if self.mbdb_data[0,4] != "mbdb"
  self.mbdb_offset = 4
  self.mbdb_offset = self.mbdb_offset + 2 # Maps to \x05 \x00 (unknown)

  while self.mbdb_offset < self.mbdb_data.length
    info = {}
    info[:start_offset] = self.mbdb_offset
    info[:domain]       = mbdb_read_string
    info[:filename]     = mbdb_read_string
    info[:linktarget]   = mbdb_read_string
    info[:datahash]     = mbdb_read_string
    info[:unknown1]     = mbdb_read_string
    info[:mode]         = mbdb_read_int(2)
    info[:unknown2]     = mbdb_read_int(4)
    info[:unknown3]     = mbdb_read_int(4)
    info[:uid]          = mbdb_read_int(4)
    info[:gid]          = mbdb_read_int(4)
    info[:mtime]        = Time.at(mbdb_read_int(4))
    info[:atime]        = Time.at(mbdb_read_int(4))
    info[:ctime]        = Time.at(mbdb_read_int(4))
    info[:length]       = mbdb_read_int(8)
    info[:flag]         = mbdb_read_int(1)
    property_count      = mbdb_read_int(1)
    info[:properties]   = {}
    1.upto(property_count) do |i|
      k = mbdb_read_string
      v = mbdb_read_string
      info[:properties][k] = v
    end
    self.entry_offsets[ info[:start_offset] ] = info
  end
  self.mbdb_data = ""
end
parse_mbdx() click to toggle source
# File lib/rex/parser/apple_backup_manifestdb.rb, line 69
def parse_mbdx
  raise ArgumentError, "Not a valid MBDX file" if self.mbdx_data[0,4] != "mbdx"

  self.mbdx_offset = 4
  self.mbdx_offset = self.mbdx_offset + 2 # Maps to \x02 \x00 (unknown)

  file_count = mbdx_read_int(4)

  while self.mbdx_offset < self.mbdx_data.length
    file_id = self.mbdx_data[self.mbdx_offset, 20].unpack("C*").map{|c| "%02x" % c}.join
    self.mbdx_offset += 20
    entry_offset = mbdx_read_int(4) + 6
    mode = mbdx_read_int(2)
    entry = entry_offsets[ entry_offset ]
    # May be corrupted if there is no matching entry, but what to do about it?
    next if not entry
    self.entries[file_id] = entry.merge({:mbdx_mode => mode, :file_id => file_id})
  end
  self.mbdx_data = ""
end