Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/rex/parser/apple_backup_manifestdb.rb
Views: 11777
# -*- coding: binary -*-1#2# This is a Ruby port of the Python manifest parsing code posted to:3# http://stackoverflow.com/questions/3085153/how-to-parse-the-manifest-mbdb-file-in-an-ios-4-0-itunes-backup/3130860#31308604#56module Rex7module Parser8class AppleBackupManifestDB910attr_accessor :entry_offsets11attr_accessor :entries12attr_accessor :mbdb, :mbdx13attr_accessor :mbdb_data, :mbdx_data14attr_accessor :mbdb_offset, :mbdx_offset1516def initialize(mbdb_data, mbdx_data)17self.entries = {}18self.entry_offsets = {}19self.mbdb_data = mbdb_data20self.mbdx_data = mbdx_data21parse_mbdb22parse_mbdx23end2425def self.from_files(mbdb_file, mbdx_file)26mbdb_data = ""27::File.open(mbdb_file, "rb") {|fd| mbdb_data = fd.read(fd.stat.size) }28mbdx_data = ""29::File.open(mbdx_file, "rb") {|fd| mbdx_data = fd.read(fd.stat.size) }3031self.new(mbdb_data, mbdx_data)32end3334def parse_mbdb35raise ArgumentError, "Not valid MBDB data" if self.mbdb_data[0,4] != "mbdb"36self.mbdb_offset = 437self.mbdb_offset = self.mbdb_offset + 2 # Maps to \x05 \x00 (unknown)3839while self.mbdb_offset < self.mbdb_data.length40info = {}41info[:start_offset] = self.mbdb_offset42info[:domain] = mbdb_read_string43info[:filename] = mbdb_read_string44info[:linktarget] = mbdb_read_string45info[:datahash] = mbdb_read_string46info[:unknown1] = mbdb_read_string47info[:mode] = mbdb_read_int(2)48info[:unknown2] = mbdb_read_int(4)49info[:unknown3] = mbdb_read_int(4)50info[:uid] = mbdb_read_int(4)51info[:gid] = mbdb_read_int(4)52info[:mtime] = ::Time.at(mbdb_read_int(4))53info[:atime] = ::Time.at(mbdb_read_int(4))54info[:ctime] = ::Time.at(mbdb_read_int(4))55info[:length] = mbdb_read_int(8)56info[:flag] = mbdb_read_int(1)57property_count = mbdb_read_int(1)58info[:properties] = {}591.upto(property_count) do |i|60k = mbdb_read_string61v = mbdb_read_string62info[:properties][k] = v63end64self.entry_offsets[ info[:start_offset] ] = info65end66self.mbdb_data = ""67end6869def parse_mbdx70raise ArgumentError, "Not a valid MBDX file" if self.mbdx_data[0,4] != "mbdx"7172self.mbdx_offset = 473self.mbdx_offset = self.mbdx_offset + 2 # Maps to \x02 \x00 (unknown)7475file_count = mbdx_read_int(4)7677while self.mbdx_offset < self.mbdx_data.length78file_id = self.mbdx_data[self.mbdx_offset, 20].unpack("C*").map{|c| "%02x" % c}.join79self.mbdx_offset += 2080entry_offset = mbdx_read_int(4) + 681mode = mbdx_read_int(2)82entry = entry_offsets[ entry_offset ]83# May be corrupted if there is no matching entry, but what to do about it?84next if not entry85self.entries[file_id] = entry.merge({:mbdx_mode => mode, :file_id => file_id})86end87self.mbdx_data = ""88end8990def mbdb_read_string91raise RuntimeError, "Corrupted MBDB file" if self.mbdb_offset > self.mbdb_data.length92len = self.mbdb_data[self.mbdb_offset, 2].unpack("n")[0]93self.mbdb_offset += 294return '' if len == 6553595val = self.mbdb_data[self.mbdb_offset, len]96self.mbdb_offset += len97return val98end99100def mbdb_read_int(size)101val = 0102size.downto(1) do |i|103val = (val << 8) + self.mbdb_data[self.mbdb_offset, 1].unpack("C")[0]104self.mbdb_offset += 1105end106val107end108109def mbdx_read_string110raise RuntimeError, "Corrupted MBDX file" if self.mbdx_offset > self.mbdx_data.length111len = self.mbdx_data[self.mbdx_offset, 2].unpack("n")[0]112self.mbdx_offset += 2113return '' if len == 65535114val = self.mbdx_data[self.mbdx_offset, len]115self.mbdx_offset += len116return val117end118119def mbdx_read_int(size)120val = 0121size.downto(1) do |i|122val = (val << 8) + self.mbdx_data[self.mbdx_offset, 1].unpack("C")[0]123self.mbdx_offset += 1124end125val126end127end128129130end131end132133134