else
            {
                outFile.WriteUInt32(1);
                outFile.WriteChars(container.Type.ToCharArray());
                outFile.WriteUInt64(container.TotalLength);
            }

            foreach (var obj in container.Children)
            {
                if (obj is ContainerAtom)
                {
                    SaveContainer(inFile, outFile, (ContainerAtom)obj);
                }
                else
                {
                    SaveAtom(inFile, outFile, (LeafAtom)obj);
                }
            }
        }

        private void SaveAtom(InputFile inFile, OutputFile outFile, LeafAtom leaf)
        {
            if (leaf.HeaderLength == 8)
            {
                outFile.WriteUInt32((UInt32)leaf.TotalLength);
                outFile.WriteChars(leaf.Type.ToCharArray());
            }
            else
            {
                outFile.WriteUInt32(1);
                outFile.WriteUInt64(leaf.TotalLength);
            }

            if (leaf.PayloadData != null)
            {
                outFile.WriteBytes(leaf.PayloadData);
            }
            else
            {
                if (leaf.OriginalPayloadFileOffset > 0)
                {
                    outFile.WriteFromInput(inFile, leaf.OriginalPayloadFileOffset, leaf.PayloadLength);
                }
                else
                {
                    outFile.WriteFromInput(inFile, leaf.PayloadFileOffset, leaf.PayloadLength);
                }
            }
        }
    }
}
        public ArrayList ParseFile(InputFile file)
        {
            ArrayList atoms = new ArrayList();
            UInt64 position = 0;

            while (position < file.Length)
            {
                string type = GetAtomType(file, position);
                Atom atom = null;

                if (IsContainer(type))
                {
                    atom = new ContainerAtom(type);
                    ParseContainer(file, position, (ContainerAtom)atom);
                }
                else if (IsAtom(type))
                {
                    atom = new LeafAtom(type);
                    ParseAtom(file, position, atom);
                }
                else
                {
                    throw new Exception("Invalid atom at pos 0x" + position.ToString("X16"));
                }

                atoms.Add(atom);
                position += atom.TotalLength;
            }

            return atoms;
        }
        private void ParseAtom(InputFile file, ulong position, Atom atom)
        {
            file.Seek(position);
            UInt64 length = file.ReadUInt32(position);

            if (length == 0)
            {
                atom.TotalLength = file.Length - position;
                atom.HeaderLength = 8;
            }
            else if (length == 1)
            {
                atom.TotalLength = file.ReadUInt64(position + 8);
                atom.HeaderLength = 16;
            }
            else
            {
                atom.TotalLength = length;
                atom.HeaderLength = 8;
            }

            if (atom.Type == "mdat")
            {
                if (!IsAtom(GetAtomType(file, position + atom.TotalLength)))
                {
                    EOSMovieFixer.Log("      Buggy [mdat] section (32 bit overflow detected)...");
                    EOSMovieFixer.Log("        Probing [mdat] end...");

                    /* try to find end of mdat by probing next atom */
                    EOSMovieFixer.Log("        length 0x" + atom.TotalLength.ToString("X16"));
                    while (!IsAtom(GetAtomType(file, position + atom.TotalLength)) && ((position + atom.TotalLength) < file.Length))
                    {
                        atom.TotalLength += 0x0100000000;
                        EOSMovieFixer.Log("        length 0x" + atom.TotalLength.ToString("X16"));
                    }

                    if (!IsAtom(GetAtomType(file, position + atom.TotalLength)))
                    {
                        throw new Exception("Could not find 'mdat' end");
                    }
                    else
                    {
                        EOSMovieFixer.Log("      Real atom end found successfully");
                    }
                }
            }

            atom.HeaderFileOffset = position;

            /* save original length for rewriting purposes */
            atom.OriginalPayloadLength = atom.PayloadLength;
            atom.OriginalPayloadFileOffset = atom.PayloadFileOffset;

            atom.ParsePayload(file, position);
        }
                }
                else
                {
                    SaveAtom(inFile, outFile, (LeafAtom)obj);
                }
            }
        }

        private void SaveContainer(InputFile inFile, OutputFile outFile, ContainerAtom container)
        {
            if (container.HeaderLength == 8)
            {
                outFile.WriteUInt32((UInt32)container.TotalLength);
                outFile.WriteChars(container.Type.ToCharArray());
        private string GetAtomType(InputFile file, ulong position)
        {
            string type = "";
            byte[] buffer = new byte[4];

            file.ReadBytes(position + 4, buffer, 4);

            for (int pos = 0; pos < 4; pos++)
            {
                type += (char)buffer[pos];
            }

            return type;
        }
Exemple #7
0
        internal void WriteFromInput(InputFile inFile, ulong position, ulong length)
        {
            ulong blockSize = 8 * 1024 * 1024;
            ulong remaining = length;

            while(remaining>0)
            {
                byte[] buf = new byte[Math.Min(remaining, blockSize)];
                inFile.ReadBytes(position, buf, buf.Length);
                writer.Write(buf);

                remaining -= (ulong)buf.Length;
                position += (ulong)buf.Length;
            }
        }
        private void btnLoad_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();

            if(dlg.ShowDialog() == DialogResult.OK)
            {
                txtLog.Clear();
                treeStructure.Nodes.Clear();

                Log("[i] Loading file...");

                try
                {
                    InFile = new InputFile(dlg.FileName);
                    Log("      Size: 0x" + InFile.Length.ToString("X8"));
                    AtomParser parser = new AtomParser();
                    Atoms = parser.ParseFile(InFile);
                    Log("      Atoms in root: " + Atoms.Count);

                    DisplayTree(Atoms);
                }
                catch (Exception ex)
                {
                    Log("");
                    Log("[E] " + ex.ToString());
                    InFile.Close();

                    btnLoad.Enabled = true;
                    btnPatch.Enabled = false;
                    btnSave.Enabled = false;
                    return;
                }

                btnLoad.Enabled = false;
                btnPatch.Enabled = true;
                btnSave.Enabled = false;
                Log("");
                Log("--------------------------------");
            }
        }
        private void ParseContainer(InputFile file, ulong position, ContainerAtom container)
        {
            ParseAtom(file, position, container);

            ArrayList atoms = new ArrayList();
            UInt64 offset = container.HeaderLength;

            while (offset < container.TotalLength)
            {
                string type = GetAtomType(file, position + offset);
                Atom atom = null;

                if (IsContainer(type))
                {
                    atom = new ContainerAtom(type);
                    ParseContainer(file, position + offset, (ContainerAtom)atom);
                }
                else
                {
                    atom = new LeafAtom(type);
                    ParseAtom(file, position + offset, atom);
                }

                container.Children.Add(atom);
                offset += atom.TotalLength;
            }
        }