public MYP(MythicPackage package, Stream stream) { _stream = stream; Package = package; BinaryReader reader = new BinaryReader(stream); Header = new MYPHeader(); Header.Load(reader); MFTTables.Add(new MFTHeader() { Length = Header.EntriesPerMFT, NextMFTOffset = Header.MFTOffset }); var mftOffset = Header.MFTOffset; var mftEntryCount = Header.EntriesPerMFT; reader.BaseStream.Position = mftOffset; while (mftOffset > 0) { reader.BaseStream.Position = mftOffset; MFT = new MFTHeader(); MFT.Offset = reader.BaseStream.Position; MFT.Load(reader); MFTTables.Add(MFT); mftOffset = MFT.NextMFTOffset; int entryIndex = 0; while (entryIndex < mftEntryCount) { var entry = new MFTEntry(); entry.Changed = false; entry.Load(this, reader, entryIndex); if (entry.Hash != 0) { Enteries[entry.Hash] = entry; } entryIndex++; } mftEntryCount = MFT.Length; } }
public void UpdateFile(long hash, byte[] data) { if (Enteries.ContainsKey(hash)) { Enteries[hash].Changed = true; Enteries[hash].Data = data; } else { Enteries[hash] = new MFTEntry() { Changed = true, Data = data, Compressed = 1, Hash = hash }; } }
public byte[] ReadFile(MFTEntry entry) { if (entry.Compressed == 1) { byte[] output_buffer = new byte[entry.UnCompressedSize]; _stream.Position = (long)(entry.Offset + entry.HeaderSize + 2); MemoryStream ms = new MemoryStream(output_buffer); using (DeflateStream decompressionStream = new DeflateStream(_stream, CompressionMode.Decompress, true)) decompressionStream.Read(output_buffer, 0, output_buffer.Length); return(output_buffer); } else { byte[] output_buffer = new byte[entry.CompressedSize]; _stream.Position = (long)(entry.Offset + entry.HeaderSize); _stream.Read(output_buffer, 0, (int)entry.CompressedSize); return(output_buffer); } }
public void AddEntries(List <Tuple <string, byte[]> > files) { _stream.Position = 0x18; BinaryWriter writer = new BinaryWriter(_stream); //update total file count in myp header writer.Write((uint)Enteries.Count + files.Count); //update last MFT entry to point to next if (MFTTables.Count > 0) { _stream.Position = MFTTables.Last().Offset + 4; writer.Write((ulong)writer.BaseStream.Length); } //move to end of the archive and add new MFT entry writer.BaseStream.Position = writer.BaseStream.Length; var packed = 0; var toPack = new List <MFTEntry>(); int remaining = files.Count; long nextMftPos = 0; while (remaining > 0) { writer.Write((uint)1000); //1000 entries per mft if (files.Count - packed > 1000) //another MFT entry after this? { nextMftPos = _stream.Position; writer.Write((long)0); //next mft position } else { writer.Write((long)0); } for (int i = 0; i < 1000; i++) { //every 1000 files, write out MFT header, and dump files after it if (packed < files.Count) { remaining--; var entry = new MFTEntry(); MemoryStream ms = new MemoryStream(); using (DeflateStream compressStream = new DeflateStream(ms, CompressionMode.Compress, true)) { compressStream.Write(files[packed].Item2, 0, files[packed].Item2.Length); } entry.Data = new byte[ms.Length + 2]; entry.Data[0] = 0x78; entry.Data[1] = 0x9C; Buffer.BlockCopy(ms.ToArray(), 0, entry.Data, 2, (int)ms.Length); entry.CompressedSize = (uint)entry.Data.Length; entry.Hash = HashWAR(files[packed].Item1); entry.CRC32 = CRC32.ComputeChecksum(files[packed].Item2); entry.Compressed = 1; entry.UnCompressedSize = (uint)files[packed].Item2.Length; entry.MFTEntryOffset = _stream.Position; writer.Write((long)0); //will determine data offset on second pass writer.Write((uint)entry.HeaderSize); writer.Write((uint)entry.CompressedSize); //compressed size writer.Write((uint)entry.UnCompressedSize); //uncompressed size writer.Write((long)entry.Hash); writer.Write((uint)entry.CRC32); //CRC writer.Write((byte)entry.Compressed); //compress writer.Write((byte)0); //unknown toPack.Add(entry); packed++; } else { writer.Write((long)0); //offset writer.Write((uint)0); //headersize writer.Write((uint)0); //compressed size writer.Write((uint)0); //uncompressed size writer.Write((long)0); //hash writer.Write((uint)0); //CRC writer.Write((byte)0); //compression writer.Write((byte)0); //unknown } } int packing = 0; foreach (var entry in toPack) { var pos = _stream.Position; _stream.Position = entry.MFTEntryOffset; writer.Write((long)pos); _stream.Position = pos; byte[] data = entry.Data; _stream.Write(data, 0, data.Length); if (entry.Compressed == 1) { var output_buffer = new byte[entry.UnCompressedSize]; MemoryStream ms = new MemoryStream(data); ms.Position = (long)(entry.HeaderSize + 2); using (DeflateStream decompressionStream = new DeflateStream(ms, CompressionMode.Decompress, true)) { decompressionStream.Read(output_buffer, 0, output_buffer.Length); } } packing++; } if (packed < files.Count) { var lastPos = _stream.Position; _stream.Position = nextMftPos; writer.Write((long)lastPos); //next mft position _stream.Position = lastPos; } toPack.Clear(); } }