private void ReopenFileView() { if (!pkg.CheckEkpfs(ekpfs)) { return; } if (va != null) { return; } try { va = pkgFile.CreateViewAccessor((long)pkg.Header.pfs_image_offset, (long)pkg.Header.pfs_image_size); var outerPfs = new PfsReader(va, pkg.Header.pfs_flags, ekpfs); var inner = new PfsReader(new PFSCReader(outerPfs.GetFile("pfs_image.dat").GetView())); var view = new FileView(inner); view.Dock = DockStyle.Fill; filesTab.Controls.Clear(); filesTab.Controls.Add(view); } catch (Exception) { va?.Dispose(); va = null; } }
private static void ExtractInParallel(PfsReader inner, string outPath, bool verbose) { Console.WriteLine("Extracting in parallel..."); Parallel.ForEach( inner.GetAllFiles(), () => new byte[0x10000], (f, _, buf) => { var size = f.size; var pos = 0; var view = f.GetView(); var fullName = f.FullName; var path = Path.Combine(outPath, fullName.Replace('/', Path.DirectorySeparatorChar).Substring(1)); var dir = path.Substring(0, path.LastIndexOf(Path.DirectorySeparatorChar)); if (verbose) { Console.WriteLine($"{fullName} -> {path}"); } Directory.CreateDirectory(dir); using (var file = File.OpenWrite(path)) { file.SetLength(size); while (size > 0) { var toRead = (int)Math.Min(size, buf.Length); view.Read(pos, buf, 0, toRead); file.Write(buf, 0, toRead); pos += toRead; size -= toRead; } } return(buf); }, x => { }); }
public void AddRoot(PfsReader p, string name) { var superroot = p.GetSuperRoot(); var root = new TreeNode(name) { Tag = superroot }; directoryTreeView.Nodes.Add(root); root.Nodes.Add("Loading", "Loading...", 0); ExpandNode(root); directoryTreeView.SelectedNode = root.Nodes[0]; }
public static void OpenPkgFilesystem(System.IO.Stream pkgStream, Action <PfsReader> innerPfsAction) { Pkg pkg; pkg = new PkgReader(pkgStream).ReadPkg(); var ekpfs = LibOrbisPkg.Util.Crypto.ComputeKeys(pkg.Header.content_id, "00000000000000000000000000000000", 1); var outerPfsOffset = (long)pkg.Header.pfs_image_offset; using (var acc = new LibOrbisPkg.Util.StreamReader(pkgStream, outerPfsOffset)) { var outerPfs = new PfsReader(acc, pkg.Header.pfs_flags, ekpfs); var inner = new PfsReader(new PFSCReader(outerPfs.GetFile("pfs_image.dat").GetView())); // Check that the sce_sys directory exists innerPfsAction(inner); } }
public PFSView(string filename) { InitializeComponent(); pfsFile = MemoryMappedFile.CreateFromFile(filename, System.IO.FileMode.Open, "pfsFile" + idx++, 0, MemoryMappedFileAccess.Read); va = pfsFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); va.Read(0, out int val); if (val == PFSCReader.Magic) { reader = new PfsReader(new PFSCReader(va)); } else { reader = new PfsReader(va); } fileView1.AddRoot(reader, filename); }
// Helper for checking the internal files of a PKG private static void OpenPkgFilesystem(string pkgPath, Action <PfsReader> innerPfsAction) { Pkg pkg; using (var mmf = MemoryMappedFile.CreateFromFile(pkgPath)) { using (var s = mmf.CreateViewStream()) { pkg = new PkgReader(s).ReadPkg(); } var ekpfs = LibOrbisPkg.Util.Crypto.ComputeKeys(pkg.Header.content_id, "00000000000000000000000000000000", 1); var outerPfsOffset = (long)pkg.Header.pfs_image_offset; using (var acc = mmf.CreateViewAccessor(outerPfsOffset, (long)pkg.Header.pfs_image_size)) { var outerPfs = new PfsReader(acc, ekpfs); var inner = new PfsReader(new PFSCReader(outerPfs.GetFile("pfs_image.dat").GetView())); // Check that the sce_sys directory exists innerPfsAction(inner); } } }
public void TestTweakDataKeys() { var pfsProperties = new PfsProperties { BlockSize = 0x10000, EKPFS = new byte[32], Encrypt = true, FileTime = 1, root = TestHelper.MakeRoot(), Seed = new byte[16], Sign = true, }; using (var pfsImg = new MemoryStream()) { new PfsBuilder(pfsProperties).WriteImage(pfsImg); var streamReader = new LibOrbisPkg.Util.StreamReader(pfsImg); var reader1 = new PfsReader(streamReader, 0, ekpfs: new byte[32]); var(tweak, data) = Crypto.PfsGenEncKey(new byte[32], new byte[16]); var reader2 = new PfsReader(streamReader, 0, data: data, tweak: tweak); } }
public PFSView(string filename) { InitializeComponent(); pfsFile = MemoryMappedFile.CreateFromFile(filename, System.IO.FileMode.Open, mapName: null, 0, MemoryMappedFileAccess.Read); va = pfsFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); va.Read(0, out int val); if (val == PFSCReader.Magic) { reader = new PfsReader(new PFSCReader(va)); } else { PfsHeader header; using (var h = pfsFile.CreateViewStream(0, 0x600, MemoryMappedFileAccess.Read)) { header = PfsHeader.ReadFromStream(h); } byte[] tweak = null, data = null; if (header.Mode.HasFlag(PfsMode.Encrypted)) { var passcode = new PasscodeEntry("Please enter data key", 32); passcode.Text = "PFS is encrypted"; passcode.ShowDialog(); data = passcode.Passcode.FromHexCompact(); passcode = new PasscodeEntry("Please enter tweak key", 32); passcode.Text = "PFS is encrypted"; passcode.ShowDialog(); data = passcode.Passcode.FromHexCompact(); reader = new PfsReader(va, data: data, tweak: tweak); } else { reader = new PfsReader(va); } } fileView1.AddRoot(reader, filename); }
public FileView(PfsReader p = null) { reader = p; InitializeComponent(); InitializeTree(); }
public static void CreateProjectFromPKG(string outputDir, MemoryMappedFile pkgFile, string passcode = null) { Directory.CreateDirectory(outputDir); Pkg pkg; using (var f = pkgFile.CreateViewStream(0, 0, MemoryMappedFileAccess.Read)) pkg = new PkgReader(f).ReadPkg(); passcode = passcode ?? "00000000000000000000000000000000"; // Initialize project parameters var project = Gp4Project.Create(ContentTypeToVolumeType(pkg.Header.content_type)); project.volume.Package.Passcode = passcode; project.volume.Package.ContentId = pkg.Header.content_id; project.volume.Package.AppType = project.volume.Type == VolumeType.pkg_ps4_app ? "full" : null; project.volume.Package.StorageType = project.volume.Type == VolumeType.pkg_ps4_app ? "digital50" : null; if (pkg.Header.content_type == ContentType.AC || pkg.Header.content_type == ContentType.AL) { pkg.LicenseDat.DecryptSecretWithDebugKey(); var entitlementKey = new byte[16]; Buffer.BlockCopy(pkg.LicenseDat.Secret, 0x70, entitlementKey, 0, 16); pkg.LicenseDat.EncryptSecretWithDebugKey(); project.volume.Package.EntitlementKey = entitlementKey.ToHexCompact(); } // Extract entry filesystem var sys_dir = Path.Combine(outputDir, "sce_sys"); var sys_projdir = project.AddDir(null, "sce_sys"); Directory.CreateDirectory(sys_dir); foreach (var meta in pkg.Metas.Metas) { // Skip entries that are auto-generated or that we don't know the filenames for if (GeneratedEntries.Contains(meta.id)) { continue; } if (!EntryNames.IdToName.ContainsKey(meta.id)) { continue; } var entryName = EntryNames.IdToName[meta.id]; var filename = Path.Combine(sys_dir, entryName); // Create directories for entries within directories if (entryName.Contains('/')) { var entryDir = entryName.Substring(0, entryName.LastIndexOf('/')); Directory.CreateDirectory(Path.Combine(sys_dir, entryDir)); Dir d = sys_projdir; foreach (var breadcrumb in entryDir.Split('/')) { d = project.AddDir(d, breadcrumb); } } // Add the entry to the project project.files.Items.Add(new Gp4File() { OrigPath = "sce_sys/" + entryName, TargetPath = "sce_sys/" + entryName }); // Save to the filesystem using (var s = pkgFile.CreateViewStream(meta.DataOffset, meta.DataSize, MemoryMappedFileAccess.Read)) using (var entryFile = File.Create(filename)) { s.CopyTo(entryFile); } } // Fixup the param.sfo using (var f = File.Open(Path.Combine(outputDir, "sce_sys/param.sfo"), FileMode.Open)) { var sfo = SFO.ParamSfo.FromStream(f); var pubtoolinfo = (sfo["PUBTOOLINFO"] as SFO.Utf8Value).Value; var c_date = ""; var c_time = ""; foreach (var info in pubtoolinfo.Split(',')) { var info2 = info.Split('='); switch (info2[0]) { case "c_date": c_date = info2[1].Substring(0, 4) + "-" + info2[1].Substring(4, 2) + "-" + info2[1].Substring(6, 2); break; case "c_time": c_time = " " + info2[1].Substring(0, 2) + ":" + info2[1].Substring(2, 2) + ":" + info2[1].Substring(4, 2); break; } } project.volume.Package.CreationDate = c_date + c_time; sfo["PUBTOOLVER"] = null; sfo["PUBTOOLINFO"] = null; sfo.Write(f); } // Extract files from the PFS filesystem byte[] ekpfs; if (pkg.CheckPasscode(passcode)) { ekpfs = Crypto.ComputeKeys(pkg.Header.content_id, passcode, 1); } else { ekpfs = pkg.GetEkpfs(); } using (var va = pkgFile.CreateViewAccessor((long)pkg.Header.pfs_image_offset, (long)pkg.Header.pfs_image_size, MemoryMappedFileAccess.Read)) { var outerPfs = new PfsReader(va, pkg.Header.pfs_flags, ekpfs); var inner = new PfsReader(new PFSCReader(outerPfs.GetFile("pfs_image.dat").GetView())); // Convert PFS image timestamp from UNIX time and save it in the project project.volume.TimeStamp = new DateTime(1970, 1, 1) .AddSeconds(inner.Header.InodeBlockSig.Time1_sec); var uroot = inner.GetURoot(); Dir dir = null; var projectDirs = new Queue <Dir>(); var pfsDirs = new Queue <PfsReader.Dir>(); pfsDirs.Enqueue(uroot); projectDirs.Enqueue(dir); while (pfsDirs.Count > 0) { dir = projectDirs.Dequeue(); if (dir != null) { Directory.CreateDirectory(Path.Combine(outputDir, dir.Path)); } foreach (var f in pfsDirs.Dequeue().children) { if (f is PfsReader.Dir d) { pfsDirs.Enqueue(d); projectDirs.Enqueue(project.AddDir(dir, d.name)); } else if (f is PfsReader.File file) { // Remove "/uroot/" var path = file.FullName.Substring(7); project.files.Items.Add(new Gp4File() { OrigPath = path, TargetPath = path }); file.Save(Path.Combine(outputDir, path)); } } } } // Last step: save the project file using (var f = File.Create(Path.Combine(outputDir, "Project.gp4"))) { Gp4Project.WriteTo(project, f); } }