public static MBFileRecord[] ReadMBDB(string BackupPath, bool dump, bool checks)
        {
            try
            {
                MBFileRecord[] files;
                MBFileRecord rec = new MBFileRecord();
                byte[] signature = new byte[6];                     // buffer signature
                byte[] buf = new byte[26];                          // buffer for .mbdx record
                StringBuilder sb = new StringBuilder(40);           // stringbuilder for the Key
                byte[] data = new byte[40];                         // buffer for the fixed part of .mbdb record

                System.DateTime unixEpoch = new System.DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);

                // open the index
                FileStream mbdx = new FileStream(Path.Combine(BackupPath, "Manifest.mbdx"), FileMode.Open, FileAccess.Read);

                // skip signature
                mbdx.Read(signature, 0, 6);
                if (BitConverter.ToString(signature, 0) != "6D-62-64-78-02-00")     // "mbdx\2\0"
                {
                    throw new Exception("bad .mbdx file");
                }

                // open the database
                FileStream mbdb = new FileStream(Path.Combine(BackupPath, "Manifest.mbdb"), FileMode.Open, FileAccess.Read);

                // skip signature
                mbdb.Read(signature, 0, 6);
                if (BitConverter.ToString(signature, 0) != "6D-62-64-62-05-00")     // "mbdb\5\0"
                {
                    throw new Exception("bad .mbdb file");
                }

                // number of records in .mbdx
                if (mbdx.Read(buf, 0, 4) != 4)
                {
                    throw new Exception("altered .mbdx file");
                }
                int records = BigEndianBitConverter.ToInt32(buf, 0);
                files = new MBFileRecord[records];

                // loop through the records
                for (int i = 0; i < records; ++i)
                {
                    // get the fixed size .mbdx record
                    if (mbdx.Read(buf, 0, 26) != 26)
                        break;

                    // convert key to text, it's the filename in the backup directory
                    // in previous versions of iTunes, it was the file part of .mddata/.mdinfo
                    sb.Clear();
                    for (int j = 0; j < 20; ++j)
                    {
                        byte b = buf[j];
                        sb.Append(toHexLow(b >> 4));
                        sb.Append(toHexLow(b & 15));
                    }

                    rec.key = sb.ToString();
                    rec.offset = BigEndianBitConverter.ToInt32(buf, 20);
                    rec.Mode = BigEndianBitConverter.ToUInt16(buf, 24);

                    // read the record in the .mbdb
                    mbdb.Seek(6 + rec.offset, SeekOrigin.Begin);

                    rec.Domain = getS(mbdb);
                    rec.Path = getS(mbdb);
                    rec.LinkTarget = getS(mbdb);
                    rec.DataHash = getD(mbdb);
                    rec.alwaysNA = getD(mbdb);

                    mbdb.Read(data, 0, 40);

                    rec.data = toHex(data, 2, 4, 4, 4, 4, 4, 4, 4, 8, 1, 1);

                    //rec.ModeBis = BigEndianBitConverter.ToUInt16(data, 0);
                    rec.alwaysZero = BigEndianBitConverter.ToInt32(data, 2);
                    rec.unknown = BigEndianBitConverter.ToInt32(data, 6);
                    rec.UserId = BigEndianBitConverter.ToInt32(data, 10);       // or maybe GroupId (don't care...)
                    rec.GroupId = BigEndianBitConverter.ToInt32(data, 14);      // or maybe UserId

                    rec.aTime = unixEpoch.AddSeconds(BigEndianBitConverter.ToUInt32(data, 18));
                    rec.bTime = unixEpoch.AddSeconds(BigEndianBitConverter.ToUInt32(data, 22));
                    rec.cTime = unixEpoch.AddSeconds(BigEndianBitConverter.ToUInt32(data, 26));

                    rec.FileLength = BigEndianBitConverter.ToInt64(data, 30);

                    rec.flag = data[38];
                    rec.PropertyCount = data[39];

                    rec.Properties = new MBFileRecord.Property[rec.PropertyCount];
                    for (int j = 0; j < rec.PropertyCount; ++j)
                    {
                        rec.Properties[j].Name = getS(mbdb);
                        rec.Properties[j].Value = getD(mbdb);
                    }

                    files[i] = rec;

                    // debug print
                    if (dump)
                    {
                        Console.WriteLine("");
                        Console.WriteLine("record {0} (mbdb offset {1})", i, rec.offset + 6);

                        Console.WriteLine("  key    {0}", rec.key);
                        Console.WriteLine("  domain {0}", rec.Domain);
                        Console.WriteLine("  path   {0}", rec.Path);
                        if (rec.LinkTarget != "n/a") Console.WriteLine("  target {0}", rec.LinkTarget);
                        if (rec.DataHash != "n/a") Console.WriteLine("  hash   {0}", rec.DataHash);
                        if (rec.alwaysNA != "n/a") Console.WriteLine("  unk3   {0}", rec.alwaysNA);

                        string l = "?";
                        switch ((rec.Mode & 0xF000) >> 12)
                        {
                            case 0xA: l = "link"; break;
                            case 0x4: l = "dir"; break;
                            case 0x8: l = "file"; break;
                        }
                        Console.WriteLine("  mode   {1} ({0})", rec.Mode & 0xFFF, l);

                        Console.WriteLine("  time   {0}", rec.aTime);

                        // length is unsignificant if link or dir
                        if ((rec.Mode & 0xF000) == 0x8000) Console.WriteLine("  length {0}", rec.FileLength);

                        Console.WriteLine("  data   {0}", rec.data);
                        for (int j = 0; j < rec.PropertyCount; ++j)
                        {
                            Console.WriteLine("  pn[{0}]  {1}", j, rec.Properties[j].Name);
                            Console.WriteLine("  pv[{0}]  {1}", j, rec.Properties[j].Value);
                        }
                    }

                    // some assertions...
                    if (checks)
                    {
                        //Debug.Assert(rec.Mode == rec.ModeBis);
                        Debug.Assert(rec.alwaysZero == 0);
                        if (rec.LinkTarget != "n/a") Debug.Assert((rec.Mode & 0xF000) == 0xA000);
                        if (rec.DataHash != "n/a") Debug.Assert(rec.DataHash.Length == 40);
                        Debug.Assert(rec.alwaysNA == "n/a");
                        if (rec.Domain.StartsWith("AppDomain-")) Debug.Assert(rec.GroupId == 501 && rec.UserId == 501);
                        if (rec.FileLength != 0) Debug.Assert((rec.Mode & 0xF000) == 0x8000);
                        if ((rec.Mode & 0xF000) == 0x8000) Debug.Assert(rec.flag != 0);
                        if ((rec.Mode & 0xF000) == 0xA000) Debug.Assert(rec.flag == 0 && rec.FileLength == 0);
                        if ((rec.Mode & 0xF000) == 0x4000) Debug.Assert(rec.flag == 0 && rec.FileLength == 0);
                    }

                }

                return files;
            }
            catch (Exception e)
            {
                Console.WriteLine("exception: {0}", e.Message);
            }

            return null;
        }
Ejemplo n.º 2
0
        public static List<MBFileRecord> ReadMBDB(string BackupPath)
        {
            try
            {
                List<MBFileRecord> files;
                byte[] signature = new byte[6];                     // buffer signature
                byte[] buf = new byte[26];                          // buffer for .mbdx record
                StringBuilder sb = new StringBuilder(40);           // stringbuilder for the Key
                byte[] data = new byte[40];                         // buffer for the fixed part of .mbdb record
                SHA1CryptoServiceProvider hasher = new SHA1CryptoServiceProvider();

                System.DateTime unixEpoch = new System.DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);


                // open the database
                FileStream mbdb = new FileStream(Path.Combine(BackupPath, "Manifest.mbdb"), FileMode.Open, FileAccess.Read);

                // skip signature
                mbdb.Read(signature, 0, 6);
                if (BitConverter.ToString(signature, 0) != "6D-62-64-62-05-00")     // "mbdb\5\0"
                {
                    throw new Exception("bad .mbdb file");
                }

                files = new List<MBFileRecord>();

                // loop through the records
                for (int i = 0; mbdb.Position < mbdb.Length ; ++i)
                {
                    MBFileRecord rec = new MBFileRecord();

                    rec.Domain = getS(mbdb);
                    rec.Path = getS(mbdb);
                    rec.LinkTarget = getS(mbdb);
                    rec.DataHash = getD(mbdb);
                    rec.alwaysNull = getD(mbdb);

                    mbdb.Read(data, 0, 40);

                    rec.data = toHex(data, 2, 4, 4, 4, 4, 4, 4, 4, 8, 1, 1);

                    rec.Mode = BigEndianBitConverter.ToUInt16(data, 0);
                    rec.alwaysZero = BigEndianBitConverter.ToInt32(data, 2);
                    rec.inode = BigEndianBitConverter.ToUInt32(data, 6);
                    rec.UserId = BigEndianBitConverter.ToUInt32(data, 10);      // or maybe GroupId (don't care...)
                    rec.GroupId = BigEndianBitConverter.ToUInt32(data, 14);     // or maybe UserId

                    rec.aTime = unixEpoch.AddSeconds(BigEndianBitConverter.ToUInt32(data, 18));
                    rec.bTime = unixEpoch.AddSeconds(BigEndianBitConverter.ToUInt32(data, 22));
                    rec.cTime = unixEpoch.AddSeconds(BigEndianBitConverter.ToUInt32(data, 26));

                    rec.FileLength = BigEndianBitConverter.ToInt64(data, 30);

                    rec.flag = data[38];
                    rec.PropertyCount = data[39];

                    rec.Properties = new MBFileRecord.Property[rec.PropertyCount];
                    for (int j = 0; j < rec.PropertyCount; ++j)
                    {
                        rec.Properties[j].Name = getS(mbdb);
                        rec.Properties[j].Value = getD(mbdb);
                    }

                    StringBuilder fileName = new StringBuilder();
                    byte[] fb = hasher.ComputeHash(ASCIIEncoding.UTF8.GetBytes(rec.Domain + "-" + rec.Path));
                    for (int k = 0; k < fb.Length; k++)
                    {
                        fileName.Append(fb[k].ToString("x2"));
                    }

                    rec.key = fileName.ToString();

                    files.Add(rec);
                }

                return files;
            }
            catch (Exception e)
            {
                Console.WriteLine("exception: {0}", e.Message);
            }

            return null;
        }
Ejemplo n.º 3
0
        public static List <MBFileRecord> ReadMBDB(string BackupPath)
        {
            try
            {
                List <MBFileRecord> files;
                byte[]                    signature = new byte[6];           // buffer signature
                byte[]                    buf       = new byte[26];          // buffer for .mbdx record
                StringBuilder             sb        = new StringBuilder(40); // stringbuilder for the Key
                byte[]                    data      = new byte[40];          // buffer for the fixed part of .mbdb record
                SHA1CryptoServiceProvider hasher    = new SHA1CryptoServiceProvider();

                System.DateTime unixEpoch = new System.DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);


                // open the database
                FileStream mbdb = new FileStream(Path.Combine(BackupPath, "Manifest.mbdb"), FileMode.Open, FileAccess.Read);

                // skip signature
                mbdb.Read(signature, 0, 6);
                if (BitConverter.ToString(signature, 0) != "6D-62-64-62-05-00")     // "mbdb\5\0"
                {
                    throw new Exception("bad .mbdb file");
                }

                files = new List <MBFileRecord>();

                // loop through the records
                for (int i = 0; mbdb.Position < mbdb.Length; ++i)
                {
                    MBFileRecord rec = new MBFileRecord();

                    rec.Domain     = getS(mbdb);
                    rec.Path       = getS(mbdb);
                    rec.LinkTarget = getS(mbdb);
                    rec.DataHash   = getD(mbdb);
                    rec.alwaysNull = getD(mbdb);

                    mbdb.Read(data, 0, 40);

                    rec.data = toHex(data, 2, 4, 4, 4, 4, 4, 4, 4, 8, 1, 1);

                    rec.Mode       = BigEndianBitConverter.ToUInt16(data, 0);
                    rec.alwaysZero = BigEndianBitConverter.ToInt32(data, 2);
                    rec.inode      = BigEndianBitConverter.ToUInt32(data, 6);
                    rec.UserId     = BigEndianBitConverter.ToUInt32(data, 10);  // or maybe GroupId (don't care...)
                    rec.GroupId    = BigEndianBitConverter.ToUInt32(data, 14);  // or maybe UserId

                    rec.aTime = unixEpoch.AddSeconds(BigEndianBitConverter.ToUInt32(data, 18));
                    rec.bTime = unixEpoch.AddSeconds(BigEndianBitConverter.ToUInt32(data, 22));
                    rec.cTime = unixEpoch.AddSeconds(BigEndianBitConverter.ToUInt32(data, 26));

                    rec.FileLength = BigEndianBitConverter.ToInt64(data, 30);

                    rec.flag          = data[38];
                    rec.PropertyCount = data[39];

                    rec.Properties = new MBFileRecord.Property[rec.PropertyCount];
                    for (int j = 0; j < rec.PropertyCount; ++j)
                    {
                        rec.Properties[j].Name  = getS(mbdb);
                        rec.Properties[j].Value = getD(mbdb);
                    }

                    StringBuilder fileName = new StringBuilder();
                    byte[]        fb       = hasher.ComputeHash(ASCIIEncoding.UTF8.GetBytes(rec.Domain + "-" + rec.Path));
                    for (int k = 0; k < fb.Length; k++)
                    {
                        fileName.Append(fb[k].ToString("x2"));
                    }

                    rec.key = fileName.ToString();

                    files.Add(rec);
                }

                return(files);
            }
            catch (Exception e)
            {
                Console.WriteLine("exception: {0}", e.Message);
            }

            return(null);
        }