public byte[] UncompressedData() { using (MemoryMappedFile file = MemoryMappedFile.CreateFromFile(Bundle.FileName, FileMode.Open)) { using (MemoryMappedViewStream viewstream = file.CreateViewStream(PageOFfset, ZSize, MemoryMappedFileAccess.Read)) { switch (CompressionType) { case "None": { using (MemoryStream destination = new MemoryStream()) { viewstream.CopyTo(destination); return(destination.ToArray()); } } case "Lz4": { var buffer = new byte[ZSize]; var c = viewstream.Read(buffer, 0, buffer.Length); var uncompressed = LZ4Codec.Decode(buffer, 0, c, (int)Size); return(uncompressed); } case "Snappy": { var buffer = new byte[ZSize]; var c = viewstream.Read(buffer, 0, buffer.Length); var uncompressed = SnappyCodec.Uncompress(buffer); return(uncompressed); } case "Doboz": { var buffer = new byte[ZSize]; var c = viewstream.Read(buffer, 0, buffer.Length); var uncompressed = DobozCodec.Decode(buffer, 0, c); return(uncompressed); } case "Zlib": { using (MemoryStream destination = new MemoryStream()) { var zlib = new ZlibStream(viewstream, CompressionMode.Decompress); zlib.CopyTo(destination); return(destination.ToArray()); } } default: throw new MissingCompressionException("Unhandled compression algorithm.") { Compression = Compression }; } } } }
public static void WriteToFile(this MemoryMappedFile mem, string path, long size) { Directory.CreateDirectory(Path.GetDirectoryName(path) ?? throw new InvalidOperationException("Path cannot be null.")); using (var file = new FileStream(path, FileMode.Create, FileAccess.Write)) { MemoryMappedViewStream m = mem.CreateViewStream(0, size); m.CopyTo(file); } }
private void ExtractExeFS(Stream output, NCCHRegion region, Keyslot secondaryKeyslot, bool close = true) { if (secondaryKeyslot == Keyslot.NCCH) { //if the secondary keyslot is also the original 0x2C NCCH Keyslot, don't bother decrypting anything in parts, and just shove the entire ExeFS through a CryptoStream Tools.CryptFileStreamPart(this.NCCHMemoryMappedFile, output, new AesCtrCryptoTransform(this.Cryptor.NormalKey[(int)Keyslot.NCCH], region.CTR), region.Offset, region.Size, close); return; } //here we go, i don't like this part byte[] header = new byte[0x200]; using (MemoryMappedViewStream headerViewStream = this.NCCHMemoryMappedFile.CreateViewStream(region.Offset, 0x200)) { header = Tools.CryptBytes(headerViewStream.ReadBytes(0x200), new AesCtrCryptoTransform(this.Cryptor.NormalKey[0x2C], region.CTR)); } output.Write(header); //create dummy ExeFS class instance to figure out the locations of each file in the ExeFS ExeFS exefs = new ExeFS(header); //write decrypted header to output file foreach (ExeFSEntry entry in exefs.Entries) { byte[] CTR = (region.CTRInt + (entry.Offset / 16)).ToCTRBytes(); AesCtrCryptoTransform transform = (NormalCryptoExeFSFiles.Contains(entry.Name)) ? new AesCtrCryptoTransform(this.Cryptor.NormalKey[(int)Keyslot.NCCH], CTR) : new AesCtrCryptoTransform(this.Cryptor.NormalKey[(int)secondaryKeyslot], CTR); using (MemoryMappedViewStream fileViewStream = this.NCCHMemoryMappedFile.CreateViewStream(region.Offset + entry.Offset, entry.Size)) { CryptoStream cs = new CryptoStream(output, transform, CryptoStreamMode.Write); output.Seek(entry.Offset, SeekOrigin.Begin); fileViewStream.CopyTo(cs); cs.FlushFinalBlock(); } } //sneaky way to make it gm9-like if (!(output.GetType() == typeof(MemoryMappedViewStream))) { output.SetLength(Tools.RoundUp(output.Length, 0x200)); } if (close) { output.Dispose(); } }
public static void ExtractFileStreamPart(MemoryMappedFile input, Stream output, long offset, long size, bool close = true) { using (MemoryMappedViewStream viewStream = input.CreateViewStream(offset, size)) { viewStream.CopyTo(output); if (close) { output.Dispose(); } } }
public static void CryptFileStreamPart(MemoryMappedFile input, Stream output, ICryptoTransform transform, long offset, long size, bool closeOutputStream = true) { using (MemoryMappedViewStream viewStream = input.CreateViewStream(offset, size)) { CryptoStream cs = new CryptoStream(output, transform, CryptoStreamMode.Write); viewStream.CopyTo(cs); cs.FlushFinalBlock(); } if (closeOutputStream) { output.Dispose(); } }
public void Decrypt(FileStream outputStream, bool trim = true) { if (this.Cryptor == null || this.SeedDatabase == null) { throw new ArgumentException("Cannot decrypt without seed database or crypto engine."); } long size; if (!trim) { outputStream.SetLength(this.Info.ImageSize); } else { size = this.Info.Partitions[0].Offset; foreach (NCSDPartition partition in this.Info.Partitions) { size += partition.Size; } outputStream.SetLength(size); } outputStream.Seek(0, SeekOrigin.Begin); MemoryMappedFile outputFile = Tools.LoadFileMapped(outputStream); using (MemoryMappedViewStream srcHeaderViewStream = this.NCSDMemoryMappedFile.CreateViewStream(0x0, this.Info.Partitions[0].Offset)) { using (MemoryMappedViewStream destHeaderViewStream = outputFile.CreateViewStream(0x0, this.Info.Partitions[0].Offset)) { srcHeaderViewStream.CopyTo(destHeaderViewStream); } } foreach (NCSDPartition partition in this.Info.Partitions) { using (MemoryMappedViewStream destPartitionViewStream = outputFile.CreateViewStream(partition.Offset, partition.Size)) { NCCH ncch = new NCCH(this.NCSDMemoryMappedFile, partition.Offset, this.Cryptor, this.SeedDatabase); ncch.Decrypt(outputFile); } } if (!trim) { NCSDPartition lastPartition = this.Info.Partitions.Last(); long lastPosition = lastPartition.Offset + lastPartition.Size; using (MemoryMappedViewStream viewStream = outputFile.CreateViewStream(lastPosition, this.Info.ImageSize - lastPosition)) { while (viewStream.Position / 64 < viewStream.Length / 64) { byte[] buffer = new byte[64]; for (int i = 0; i < buffer.Length; i++) { buffer[i] = 0xFF; } viewStream.Write(buffer, 0, buffer.Length); } } } }