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; }
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; } }