Пример #1
0
        public void LoadNsp(string nspFile)
        {
            FileStream file = new FileStream(nspFile, FileMode.Open, FileAccess.Read);

            Pfs nsp = new Pfs(file);

            PfsFileEntry ticketFile = nsp.Files.FirstOrDefault(x => x.Name.EndsWith(".tik"));

            // Load title key from the NSP's ticket in case the user doesn't have a title key file
            if (ticketFile != null)
            {
                Ticket ticket = new Ticket(nsp.OpenFile(ticketFile));

                KeySet.TitleKeys[ticket.RightsId] = ticket.GetTitleKey(KeySet);
            }

            Nca mainNca    = null;
            Nca controlNca = null;

            foreach (PfsFileEntry ncaFile in nsp.Files.Where(x => x.Name.EndsWith(".nca")))
            {
                Nca nca = new Nca(KeySet, nsp.OpenFile(ncaFile), true);

                if (nca.Header.ContentType == ContentType.Program)
                {
                    mainNca = nca;
                }
                else if (nca.Header.ContentType == ContentType.Control)
                {
                    controlNca = nca;
                }
            }

            if (mainNca != null)
            {
                LoadNca(mainNca, controlNca);

                return;
            }

            Logger.PrintError(LogClass.Loader, "Could not find an Application NCA in the provided NSP file");
        }
Пример #2
0
        private void ImportTitleKeysFromNsp(Pfs nsp, Keyset keySet)
        {
            foreach (PfsFileEntry ticketEntry in nsp.Files.Where(x => x.Name.EndsWith(".tik")))
            {
                Ticket ticket = new Ticket(nsp.OpenFile(ticketEntry).AsStream());

                if (!keySet.TitleKeys.ContainsKey(ticket.RightsId))
                {
                    keySet.TitleKeys.Add(ticket.RightsId, ticket.GetTitleKey(keySet));
                }
            }
        }
Пример #3
0
        public void Load(System.IO.Stream stream)
        {
            var Keys = Forms.SwitchKeySelectionForm.ShowKeySelector();

            if (Keys == null)
            {
                throw new Exception("Failed to get keys. Please select valid paths!");
            }

            Xci xci     = new Xci(Keys, stream.AsStorage());
            var CnmtNca = new Nca(Keys, xci.SecurePartition.OpenFile(
                                      xci.SecurePartition.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false);
            var CnmtPfs = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None, true));
            var Cnmt    = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]).AsStream());

            foreach (var entry in Cnmt.ContentEntries)
            {
                if (entry.Type == CnmtContentType.Program)
                {
                    var    Program     = entry;
                    string ncaFileName = $"{Program.NcaId.ToHexString().ToLower()}.nca";

                    Stream Input = xci.SecurePartition.OpenFile(ncaFileName).AsStream();
                    var    Nca   = new Nca(Keys, Input.AsStorage(), true);

                    string root = Nca.Header.TitleId.ToString("X");

                    Romfs romfs = new Romfs(
                        Nca.OpenSection(Nca.Sections.FirstOrDefault
                                            (s => s?.Type == SectionType.Romfs || s?.Type == SectionType.Bktr)
                                        .SectionNum, false, IntegrityCheckLevel.None, true));

                    if (Nca.CanOpenSection((int)ProgramPartitionType.Code))
                    {
                        var exefs = new Pfs(Nca.OpenSection((int)ProgramPartitionType.Code,
                                                            false, IntegrityCheckLevel.None, true));

                        foreach (var file in exefs.Files)
                        {
                            files.Add(new NSP.ExefsEntry(exefs, file, root));
                        }
                    }

                    for (int i = 0; i < romfs.Files.Count; i++)
                    {
                        files.Add(new NSP.FileEntry(romfs, romfs.Files[i], root));
                    }
                }
            }
        }
Пример #4
0
        private long OpenFileSystemFromInternalFile(ServiceCtx Context, string FullPath)
        {
            DirectoryInfo ArchivePath = new DirectoryInfo(FullPath).Parent;

            while (string.IsNullOrWhiteSpace(ArchivePath.Extension))
            {
                ArchivePath = ArchivePath.Parent;
            }

            if (ArchivePath.Extension == ".nsp" && File.Exists(ArchivePath.FullName))
            {
                FileStream PfsFile = new FileStream(
                    ArchivePath.FullName.TrimEnd(Path.DirectorySeparatorChar),
                    FileMode.Open,
                    FileAccess.Read);

                Pfs          Nsp        = new Pfs(PfsFile);
                PfsFileEntry TicketFile = Nsp.Files.FirstOrDefault(x => x.Name.EndsWith(".tik"));

                if (TicketFile != null)
                {
                    Ticket Ticket = new Ticket(Nsp.OpenFile(TicketFile));

                    Context.Device.System.KeySet.TitleKeys[Ticket.RightsId] =
                        Ticket.GetTitleKey(Context.Device.System.KeySet);
                }

                string Filename = FullPath.Replace(ArchivePath.FullName, string.Empty).TrimStart('\\');

                if (Nsp.FileExists(Filename))
                {
                    return(OpenNcaFs(Context, FullPath, Nsp.OpenFile(Filename)));
                }
            }

            return(MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist));
        }
Пример #5
0
        private long OpenFileSystemFromInternalFile(ServiceCtx context, string fullPath)
        {
            DirectoryInfo archivePath = new DirectoryInfo(fullPath).Parent;

            while (string.IsNullOrWhiteSpace(archivePath.Extension))
            {
                archivePath = archivePath.Parent;
            }

            if (archivePath.Extension == ".nsp" && File.Exists(archivePath.FullName))
            {
                FileStream pfsFile = new FileStream(
                    archivePath.FullName.TrimEnd(Path.DirectorySeparatorChar),
                    FileMode.Open,
                    FileAccess.Read);

                Pfs          nsp        = new Pfs(pfsFile);
                PfsFileEntry ticketFile = nsp.Files.FirstOrDefault(x => x.Name.EndsWith(".tik"));

                if (ticketFile != null)
                {
                    Ticket ticket = new Ticket(nsp.OpenFile(ticketFile));

                    context.Device.System.KeySet.TitleKeys[ticket.RightsId] =
                        ticket.GetTitleKey(context.Device.System.KeySet);
                }

                string filename = fullPath.Replace(archivePath.FullName, string.Empty).TrimStart('\\');

                if (nsp.FileExists(filename))
                {
                    return(OpenNcaFs(context, fullPath, nsp.OpenFile(filename)));
                }
            }

            return(MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist));
        }
Пример #6
0
        public void Load(System.IO.Stream stream)
        {
            Text = FileName;

            string homeFolder   = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
            string KeyFile      = Path.Combine(homeFolder, ".switch", "prod.keys");
            string TitleKeyFile = Path.Combine(homeFolder, ".switch", "title.keys");

            var Keys = ExternalKeys.ReadKeyFile(KeyFile, TitleKeyFile);

            Stream Input;

            var Pfs       = new Pfs(stream.AsStorage());
            var CnmtNca   = new Nca(Keys, Pfs.OpenFile(Pfs.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false);
            var CnmtPfs   = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None, true));
            var Cnmt      = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]).AsStream());
            var Program   = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program);
            var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control);

            if (CtrlEntry != null)
            {
                Control = new Nca(Keys, Pfs.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false);
            }
            Input = Pfs.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca").AsStream();

            var Nca = new Nca(Keys, Input.AsStorage(), true);

            Romfs romfs = new Romfs(
                Nca.OpenSection(Nca.Sections.FirstOrDefault
                                    (s => s?.Type == SectionType.Romfs || s?.Type == SectionType.Bktr)
                                .SectionNum, false, IntegrityCheckLevel.None, true));

            romfsWrapper       = new RomfsNodeWrapper();
            romfsWrapper.romfs = romfs;
            romfsWrapper.FillTreeNodes(Nodes, romfs.RootDir);
        }
Пример #7
0
        public long OpenFile(string Name, out IFile FileInterface)
        {
            Name = Name.TrimStart('/');

            if (Pfs.FileExists(Name))
            {
                Stream Stream = Pfs.OpenFile(Name);
                FileInterface = new IFile(Stream, Name);

                return(0);
            }

            FileInterface = null;

            return(MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist));
        }
Пример #8
0
        public long OpenFile(string name, out IFile fileInterface)
        {
            name = name.TrimStart('/');

            if (_pfs.FileExists(name))
            {
                Stream stream = _pfs.OpenFile(name).AsStream();
                fileInterface = new IFile(stream, name);

                return(0);
            }

            fileInterface = null;

            return(MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist));
        }
Пример #9
0
        public void Load(System.IO.Stream stream)
        {
            var Keys = Forms.SwitchKeySelectionForm.ShowKeySelector();

            if (Keys == null)
            {
                throw new Exception("Failed to get keys. Please select valid paths!");
            }

            Stream Input;

            var Pfs       = new Pfs(stream.AsStorage());
            var CnmtNca   = new Nca(Keys, Pfs.OpenFile(Pfs.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false);
            var CnmtPfs   = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None, true));
            var Cnmt      = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]).AsStream());
            var Program   = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program);
            var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control);

            if (CtrlEntry != null)
            {
                Control = new Nca(Keys, Pfs.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false);
            }
            Input = Pfs.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca").AsStream();

            var Nca = new Nca(Keys, Input.AsStorage(), true);

            Romfs romfs = new Romfs(
                Nca.OpenSection(Nca.Sections.FirstOrDefault
                                    (s => s?.Type == SectionType.Romfs || s?.Type == SectionType.Bktr)
                                .SectionNum, false, IntegrityCheckLevel.None, true));

            if (Nca.CanOpenSection((int)ProgramPartitionType.Code))
            {
                var exefs = new Pfs(Nca.OpenSection((int)ProgramPartitionType.Code,
                                                    false, IntegrityCheckLevel.None, true));

                foreach (var file in exefs.Files)
                {
                    files.Add(new ExefsEntry(exefs, file));
                }
            }

            for (int i = 0; i < romfs.Files.Count; i++)
            {
                files.Add(new FileEntry(romfs, romfs.Files[i]));
            }
        }
Пример #10
0
        private long OpenNsp(ServiceCtx Context, string PfsPath)
        {
            FileStream   PfsFile    = new FileStream(PfsPath, FileMode.Open, FileAccess.Read);
            Pfs          Nsp        = new Pfs(PfsFile);
            PfsFileEntry TicketFile = Nsp.Files.FirstOrDefault(x => x.Name.EndsWith(".tik"));

            if (TicketFile != null)
            {
                Ticket Ticket = new Ticket(Nsp.OpenFile(TicketFile));

                Context.Device.System.KeySet.TitleKeys[Ticket.RightsId] =
                    Ticket.GetTitleKey(Context.Device.System.KeySet);
            }

            IFileSystem NspFileSystem = new IFileSystem(PfsPath, new PFsProvider(Nsp));

            MakeObject(Context, NspFileSystem);

            return(0);
        }
Пример #11
0
        private long OpenNsp(ServiceCtx context, string pfsPath)
        {
            FileStream   pfsFile    = new FileStream(pfsPath, FileMode.Open, FileAccess.Read);
            Pfs          nsp        = new Pfs(pfsFile);
            PfsFileEntry ticketFile = nsp.Files.FirstOrDefault(x => x.Name.EndsWith(".tik"));

            if (ticketFile != null)
            {
                Ticket ticket = new Ticket(nsp.OpenFile(ticketFile));

                context.Device.System.KeySet.TitleKeys[ticket.RightsId] =
                    ticket.GetTitleKey(context.Device.System.KeySet);
            }

            IFileSystem nspFileSystem = new IFileSystem(pfsPath, new PFsProvider(nsp));

            MakeObject(context, nspFileSystem);

            return(0);
        }
Пример #12
0
        static void Main(string[] args)
        {
            Console.WriteLine("Nintendo Switch NSP Verifier v1.00");
            Console.WriteLine("Copyright 2018 CaitSith2");
            Console.WriteLine("");

            _path = args.Length >= 1
                ? string.Join(" ", args)
                : Environment.CurrentDirectory;

            if (new[] { "--help", "-h" }.Any(x => x.Equals(_path, StringComparison.InvariantCultureIgnoreCase)))
            {
                Console.WriteLine("Usage: NSPVerify [path to NSP directory]");
                Console.WriteLine("");
                Console.WriteLine("If the tool is run without specifying a path, it will look for NSPs in the current directory and ALL sub-directories of current directory");
                return;
            }



            if (!Directory.Exists(_path))
            {
                Console.WriteLine("ERROR: Specified directory does not exist.  specify --help for usage information.");
                return;
            }

            var fs = new FileSystem(_path);

            var keys = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".switch", "prod.keys");

            if (File.Exists("keys.txt"))
            {
                keys = "keys.txt";
            }

            if (!File.Exists(keys))
            {
                Console.WriteLine($"Cannot verify NSPs without keys.txt. Either put it in the same directory as this tool,");
                Console.WriteLine($"or place it in \"{Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".switch")}\" named as prod.keys");
                PressAnyKey();
                return;
            }

            var keyset        = ExternalKeys.ReadKeyFile(keys);
            var badlist       = new List <string>();
            var exceptionlist = new List <string>();

            var files = fs.GetFileSystemEntries("", "*.nsp", SearchOption.AllDirectories).ToList();

            files.AddRange(fs.GetFileSystemEntries("", "*.nsx", SearchOption.AllDirectories));

            if (files.Count == 0)
            {
                Console.WriteLine("Error: No NSP/NSX files in specified directory");
                PressAnyKey();
                return;
            }

            foreach (var file in files)
            {
                var filename         = Path.GetFileName(file);
                var relativefilename = Util.GetRelativePath(file, Path.GetFullPath(_path));
                Console.Write($"Checking {filename}: ");
                try
                {
                    bool ok = true;
                    using (var nspfile = fs.OpenFile(file, FileMode.Open, FileAccess.Read))
                    {
                        var nspdata  = new Pfs(nspfile);
                        var cnmtfile = nspdata.Files.FirstOrDefault(x => x.Name.ToLowerInvariant().EndsWith(".cnmt.nca"));
                        if (cnmtfile == null)
                        {
                            Console.WriteLine($"\rChecking {filename}: No cnmt.nca file present");
                            badlist.Add(relativefilename);
                            continue;
                        }

                        var  cnmtdata = nspdata.OpenFile(cnmtfile);
                        Cnmt cnmt;
                        using (var sr = new BinaryReader(cnmtdata))
                        {
                            var cnmthash = SHA256.Create().ComputeHash(sr.ReadBytes((int)cnmtdata.Length));
                            if (!cnmtfile.Name.ToLowerInvariant().Contains(cnmthash.Take(16).ToArray().ToHexString()))
                            {
                                //Put failure here
                                Console.WriteLine($"\rChecking {filename}: cnmt.nca file is corrupted");
                                badlist.Add(relativefilename);
                                cnmtdata.Dispose();
                                continue;
                            }

                            cnmtdata.Position = 0;
                            var cnmtnca    = new Nca(keyset, cnmtdata, false);
                            var section    = cnmtnca.OpenSection(0, false);
                            var sectionpfs = new Pfs(section);
                            cnmt = new Cnmt(sectionpfs.OpenFile(sectionpfs.Files[0]));
                        }

                        foreach (var entry in cnmt.ContentEntries)
                        {
                            var entryfile = nspdata.Files.FirstOrDefault(x => x.Name.ToLowerInvariant().EndsWith(entry.NcaId.ToHexString() + ".nca"));
                            if (entryfile == null)
                            {
                                if (entry.Type != CnmtContentType.UpdatePatch)
                                {
                                    //Put failure here
                                    Console.WriteLine($"\rChecking {filename}: one of the entries required by the cnmt.nca is missing.");
                                    badlist.Add(relativefilename);
                                    break;
                                }

                                continue;
                            }

                            using (var entrynca = nspdata.OpenFile(entryfile))
                            {
                                var hash = SHA256.Create();

                                using (var sr = new BinaryReader(entrynca))
                                {
                                    while (entrynca.Length != entrynca.Position)
                                    {
                                        var entryncadata = sr.ReadBytes(0x100000);
                                        hash.TransformBlock(entryncadata, 0, entryncadata.Length, entryncadata, 0);
                                        Console.Write($"\rChecking {filename}: {((entrynca.Position * 100.0) / entrynca.Length):0.0}%");
                                    }

                                    hash.TransformFinalBlock(new byte[0], 0, 0);
                                }

                                if (hash.Hash.ToHexString().Equals(entry.Hash.ToHexString()))
                                {
                                    Console.Write($"\rChecking {filename}: {100:0.0}%");
                                    continue;
                                }

                                //Put failure here
                                Console.WriteLine($"\rChecking {filename}: one of the entries required by the cnmt.nca is corrupted");
                                badlist.Add(relativefilename);
                                ok = false;
                                break;
                            }
                        }

                        if (ok)
                        {
                            Console.WriteLine($"\rChecking {filename}: OK        ");
                        }
                        //Put Success here
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.WriteLine(ex.StackTrace);
                    exceptionlist.Add($"{relativefilename}{Environment.NewLine}Exception: \"{ex.GetType()}\" {ex.Message}{Environment.NewLine}Stack Trace: {ex.StackTrace}{Environment.NewLine}");
                }
            }

            badlist.Insert(0, badlist.Count == 0
                ? "None of the files are corrupted. :)"
                : "The following NSP/NSX files are corrupted:");

            exceptionlist.Insert(0, exceptionlist.Count == 0
                ? "No exceptions to log. :)"
                : "Exceptions caused while parsing the following NSP/NSX files:");

            try
            {
                File.WriteAllText("Corrupted NSPs.txt", string.Join(Environment.NewLine, badlist));
                File.WriteAllText("Exception Log.txt", string.Join(Environment.NewLine, exceptionlist));
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Could not write the output files \"Corrupted NSPs.txt\" and \"Exception Log.txt\" due to the following exception.");
                Console.WriteLine($"Exception: \"{ex.GetType()}\" {ex.Message}");
                Console.WriteLine($"Stack Trace: {ex.StackTrace}{Environment.NewLine}");

                Console.WriteLine(string.Join(Environment.NewLine, badlist));
                Console.WriteLine();
                Console.WriteLine(string.Join(Environment.NewLine, exceptionlist));
                Console.WriteLine();
            }

            Console.WriteLine("Done.");
            PressAnyKey();
        }
Пример #13
0
        public void LoadNca(Nca mainNca, Nca controlNca)
        {
            if (mainNca.Header.ContentType != ContentType.Program)
            {
                Logger.PrintError(LogClass.Loader, "Selected NCA is not a \"Program\" NCA");

                return;
            }

            Stream romfsStream = mainNca.OpenSection(ProgramPartitionType.Data, false, FsIntegrityCheckLevel);
            Stream exefsStream = mainNca.OpenSection(ProgramPartitionType.Code, false, FsIntegrityCheckLevel);

            if (exefsStream == null)
            {
                Logger.PrintError(LogClass.Loader, "No ExeFS found in NCA");

                return;
            }

            if (romfsStream == null)
            {
                Logger.PrintWarning(LogClass.Loader, "No RomFS found in NCA");
            }
            else
            {
                Device.FileSystem.SetRomFs(romfsStream);
            }

            Pfs exefs = new Pfs(exefsStream);

            Npdm metaData = null;

            if (exefs.FileExists("main.npdm"))
            {
                Logger.PrintInfo(LogClass.Loader, "Loading main.npdm...");

                metaData = new Npdm(exefs.OpenFile("main.npdm"));
            }
            else
            {
                Logger.PrintWarning(LogClass.Loader, $"NPDM file not found, using default values!");

                metaData = GetDefaultNpdm();
            }

            List <IExecutable> staticObjects = new List <IExecutable>();

            void LoadNso(string filename)
            {
                foreach (PfsFileEntry file in exefs.Files.Where(x => x.Name.StartsWith(filename)))
                {
                    if (Path.GetExtension(file.Name) != string.Empty)
                    {
                        continue;
                    }

                    Logger.PrintInfo(LogClass.Loader, $"Loading {filename}...");

                    NxStaticObject staticObject = new NxStaticObject(exefs.OpenFile(file));

                    staticObjects.Add(staticObject);
                }
            }

            Nacp ReadControlData()
            {
                Romfs controlRomfs = new Romfs(controlNca.OpenSection(0, false, FsIntegrityCheckLevel));

                byte[] controlFile = controlRomfs.GetFile("/control.nacp");

                BinaryReader reader = new BinaryReader(new MemoryStream(controlFile));

                Nacp controlData = new Nacp(reader);

                CurrentTitle = controlData.Languages[(int)State.DesiredTitleLanguage].Title;

                if (string.IsNullOrWhiteSpace(CurrentTitle))
                {
                    CurrentTitle = controlData.Languages.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title;
                }

                return(controlData);
            }

            if (controlNca != null)
            {
                ReadControlData();
            }
            else
            {
                CurrentTitle = metaData.Aci0.TitleId.ToString("x16");
            }

            if (!metaData.Is64Bits)
            {
                throw new NotImplementedException("32-bit titles are not supported!");
            }

            LoadNso("rtld");
            LoadNso("main");
            LoadNso("subsdk");
            LoadNso("sdk");

            ContentManager.LoadEntries();

            ProgramLoader.LoadStaticObjects(this, metaData, staticObjects.ToArray());
        }
Пример #14
0
        public void LoadNsp(string nspFile)
        {
            FileStream file = new FileStream(nspFile, FileMode.Open, FileAccess.Read);

            Pfs nsp = new Pfs(file.AsStorage(false));

            foreach (PfsFileEntry ticketEntry in nsp.Files.Where(x => x.Name.EndsWith(".tik")))
            {
                Ticket ticket = new Ticket(nsp.OpenFile(ticketEntry).AsStream());

                if (!KeySet.TitleKeys.ContainsKey(ticket.RightsId))
                {
                    KeySet.TitleKeys.Add(ticket.RightsId, ticket.GetTitleKey(KeySet));
                }
            }

            Nca mainNca    = null;
            Nca controlNca = null;

            foreach (PfsFileEntry ncaFile in nsp.Files.Where(x => x.Name.EndsWith(".nca")))
            {
                Nca nca = new Nca(KeySet, nsp.OpenFile(ncaFile), true);

                if (nca.Header.ContentType == ContentType.Program)
                {
                    mainNca = nca;
                }
                else if (nca.Header.ContentType == ContentType.Control)
                {
                    controlNca = nca;
                }
            }

            if (mainNca != null)
            {
                LoadNca(mainNca, controlNca);

                return;
            }

            // This is not a normal NSP, it's actually a ExeFS as a NSP
            Npdm metaData = null;

            PfsFileEntry npdmFile = nsp.Files.FirstOrDefault(x => x.Name.Equals("main.npdm"));

            if (npdmFile != null)
            {
                Logger.PrintInfo(LogClass.Loader, $"Loading main.npdm...");

                metaData = new Npdm(nsp.OpenFile(npdmFile).AsStream());
            }
            else
            {
                Logger.PrintWarning(LogClass.Loader, $"NPDM file not found, using default values!");

                metaData = GetDefaultNpdm();
            }

            List <IExecutable> staticObjects = new List <IExecutable>();

            void LoadNso(string searchPattern)
            {
                PfsFileEntry entry = nsp.Files.FirstOrDefault(x => x.Name.Equals(searchPattern));

                if (entry != null)
                {
                    Logger.PrintInfo(LogClass.Loader, $"Loading {entry.Name}...");

                    NxStaticObject staticObject = new NxStaticObject(nsp.OpenFile(entry).AsStream());

                    staticObjects.Add(staticObject);
                }
            }

            CurrentTitle = metaData.Aci0.TitleId.ToString("x16");

            LoadNso("rtld");
            LoadNso("main");
            LoadNso("subsdk*");
            LoadNso("sdk");

            ContentManager.LoadEntries();

            if (staticObjects.Count == 0)
            {
                Logger.PrintError(LogClass.Loader, "Could not find an Application NCA in the provided NSP file");
            }
            else
            {
                ProgramLoader.LoadStaticObjects(this, metaData, staticObjects.ToArray());
            }
        }
Пример #15
0
        private static (string, string) processCnmtNca(Nca nca, ref Title title, bool cnmtContent = true)
        {
            string biggestNca = null, controlNca = null;

            log?.WriteLine("Processing CNMT NCA");

            try
            {
                Pfs ncaPfs = new Pfs(nca.OpenSection(0, false, IntegrityCheckLevel.ErrorOnInvalid, true));

                PfsFileEntry[] ncaFileEntries = ncaPfs.Files;
                foreach (PfsFileEntry pfsEntry in ncaFileEntries)
                {
                    Cnmt cnmt = new Cnmt(ncaPfs.OpenFile(pfsEntry).AsStream());

                    if (title.version == unchecked ((uint)-1) || cnmt.TitleVersion?.Version > title.version)
                    {
                        title.type = cnmt.Type;

                        title.titleID     = String.Format("{0:X16}", cnmt.TitleId);
                        title.baseTitleID = String.Format("{0:X16}", cnmt.ApplicationTitleId);
                        title.version     = cnmt.TitleVersion?.Version ?? title.version;

                        title.systemVersion      = cnmt.MinimumSystemVersion?.Version ?? unchecked ((uint)-1);
                        title.applicationVersion = cnmt.MinimumApplicationVersion?.Version ?? unchecked ((uint)-1);

                        if (cnmtContent)
                        {
                            CnmtContentEntry[] contentEntries = cnmt.ContentEntries;
                            foreach (CnmtContentEntry contentEntry in contentEntries)
                            {
                                if (title.type == TitleType.Application || title.type == TitleType.Patch)
                                {
                                    if (contentEntry.Type == CnmtContentType.Program)
                                    {
                                        biggestNca = BitConverter.ToString(contentEntry.NcaId).Replace("-", "").ToLower() + ".nca";

                                        log?.WriteLine("Found Biggest NCA {0}", biggestNca);
                                    }
                                    else if (contentEntry.Type == CnmtContentType.Control)
                                    {
                                        controlNca = BitConverter.ToString(contentEntry.NcaId).Replace("-", "").ToLower() + ".nca";

                                        log?.WriteLine("Found Control NCA {0}", controlNca);
                                    }
                                }
                                else if (title.type == TitleType.AddOnContent)
                                {
                                    if (contentEntry.Type == CnmtContentType.Data)
                                    {
                                        biggestNca = BitConverter.ToString(contentEntry.NcaId).Replace("-", "").ToLower() + ".nca";

                                        log?.WriteLine("Found Biggest NCA {0}", biggestNca);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (MissingKeyException ex)
            {
                title.error = String.Format("Missing {0}: {1}", ex.Type == KeyType.Title ? "Title Key" : "Key", ex.Name.Replace("key_area_key_application", "master_key"));

                log?.WriteLine(title.error);
            }
            catch (FileNotFoundException) { }

            return(biggestNca, controlNca);
        }
Пример #16
0
        public static Title processNsp(string filename)
        {
            Title title = new Title();

            using (var filestream = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                Pfs    pfs;
                string biggestNca = null, controlNca = null;

                try
                {
                    pfs = new Pfs(filestream.AsStorage());

                    title.distribution = Title.Distribution.Digital;

                    log?.WriteLine("Processing NSP {0}", filename);

                    PfsFileEntry[] fileEntries = pfs.Files;
                    foreach (PfsFileEntry entry in fileEntries)
                    {
                        if (entry.Name.EndsWith(".cnmt.xml"))
                        {
                            try
                            {
                                using (var cnmtXml = pfs.OpenFile(entry))
                                {
                                    (biggestNca, controlNca) = processCnmtXml(cnmtXml, ref title);
                                }
                            }
                            catch (FileNotFoundException) { }

                            title.structure.Add(Title.Structure.CnmtXml);
                        }
                        else if (entry.Name.EndsWith(".cnmt.nca"))
                        {
                            try
                            {
                                using (var cnmtNca = pfs.OpenFile(entry))
                                {
                                    var nca = processCnmtNca(cnmtNca, ref title);
                                    if (nca.Item1 != null && (nca.Item2 != null || title.type == TitleType.AddOnContent))
                                    {
                                        (biggestNca, controlNca) = nca;
                                    }
                                }
                            }
                            catch (FileNotFoundException)
                            {
                                if (pfs.FileExists(entry.Name.Replace(".nca", ".ncz")))
                                {
                                    title.error = "Unsupported Format: Compressed NCA";
                                }
                            }

                            title.structure.Add(Title.Structure.CnmtNca);
                        }
                        else if (entry.Name.EndsWith(".cert"))
                        {
                            title.structure.Add(Title.Structure.Cert);
                        }
                        else if (entry.Name.EndsWith(".tik"))
                        {
                            try
                            {
                                using (var tik = pfs.OpenFile(entry))
                                {
                                    if (entry.Name.Split('.')[0].TryToBytes(out byte[] rightsId))
                                    {
                                        processTik(tik, rightsId, ref keyset, out byte[] titleKey);

                                        title.titleKey = BitConverter.ToString(titleKey).Replace("-", "").ToUpper();
                                    }
                                }
                            }
                            catch (FileNotFoundException)
                            {
                                if (pfs.FileExists(entry.Name.Replace(".nca", ".ncz")))
                                {
                                    title.error = "Unsupported Format: Compressed NCA";
                                }
                            }

                            title.structure.Add(Title.Structure.Tik);
                        }
                        else if (entry.Name.EndsWith(".legalinfo.xml"))
                        {
                            title.structure.Add(Title.Structure.LegalinfoXml);
                        }
                        else if (entry.Name.EndsWith(".nacp.xml"))
                        {
                            try
                            {
                                using (var nacpXml = pfs.OpenFile(entry))
                                {
                                    processNacpXml(nacpXml, ref title);
                                }
                            }
                            catch (FileNotFoundException) { }

                            title.structure.Add(Title.Structure.NacpXml);
                        }
                        else if (entry.Name.EndsWith(".programinfo.xml"))
                        {
                            title.structure.Add(Title.Structure.PrograminfoXml);
                        }
                        else if (entry.Name.Equals("cardspec.xml"))
                        {
                            title.structure.Add(Title.Structure.CardspecXml);
                        }
                        else if (entry.Name.Equals("authoringtoolinfo.xml"))
                        {
                            title.structure.Add(Title.Structure.AuthoringtoolinfoXml);
                        }
                    }

                    if (!String.IsNullOrEmpty(biggestNca))
                    {
                        try
                        {
                            using (var biggest = pfs.OpenFile(biggestNca))
                            {
                                processBiggestNca(biggest, ref title);
                            }
                        }
                        catch (FileNotFoundException)
                        {
                            if (pfs.FileExists(biggestNca.Replace(".nca", ".ncz")))
                            {
                                title.error = "Unsupported Format: Compressed NCA";
                            }
                        }
                    }

                    if (!String.IsNullOrEmpty(controlNca))
                    {
                        try
                        {
                            using (var control = pfs.OpenFile(controlNca))
                            {
                                processControlNca(control, ref title);
                            }
                        }
                        catch (FileNotFoundException)
                        {
                            if (pfs.FileExists(controlNca.Replace(".nca", ".ncz")))
                            {
                                title.error = "Unsupported Format: Compressed NCA";
                            }
                        }
                    }
                }
                catch (InvalidDataException)
                {
                    return(null);
                }
            }

            if (title.type == TitleType.Application || title.type == TitleType.Patch)
            {
                if (versionList.TryGetValue(title.baseTitleID, out uint version))
                {
                    title.latestVersion = version;
                }
            }

            log?.WriteLine("NSP information for {0}: [{1}] {2}", filename, title.titleID, title.titleName);

            return(title);
        }
Пример #17
0
        private static void Main(string[] args)
        {
            var keyFile       = Environment.ExpandEnvironmentVariables("%USERPROFILE%/.switch/prod.keys");
            var keysInUserDir = true;

            var getDeltasOnly = false;

            #region Pre-execution checks
            if (!File.Exists(keyFile))
            {
                if (!File.Exists("prod.keys"))
                {
                    Console.Error.WriteLine("Error: prod.keys is missing!");
                    return;
                }
                else
                {
                    keysInUserDir = false;
                }
            }

            if (!File.Exists("edge.token"))
            {
                Console.Error.WriteLine("Error: Please add an edge token to a file named \"edge.token\".");
                return;
            }

            if (!File.Exists("device.id"))
            {
                Console.Error.WriteLine("Error: Please add your device ID in hexadecimal text form to a file named \"device.id\".");
                return;
            }

            if (!File.Exists("nx_tls_client_cert.pfx"))
            {
                Console.Error.WriteLine("Error: Please add your Switch certificate to a file named \"nx_tls_client_cert.pfx\".");
                return;
            }
            #endregion

            var deviceID = Convert.ToInt64(File.ReadAllText("device.id"), 16);
            var keys     = ExternalKeys.ReadKeyFile(keysInUserDir ? keyFile : "prod.keys");

            var sysID = "0100000000000816";

            // To-do: Clean up
            if (args[0] == "-s" || args[0] == sysID)
            {
                var JSON    = (string)GET(deviceID, SunUrl, true);
                var Version = args.Length > 1 ? args[1] : (string)JObject.Parse(JSON)["system_update_metas"][0]["title_version"];
                HEAD(deviceID, nMetaURL('s', sysID, Version, deviceID));
                var contentID = HEAD(deviceID, nMetaURL('s', sysID, Version, deviceID));

                using (var meta = (HttpWebResponse)GET(deviceID, nContentURL('s', contentID), false))
                    using (var rd = new BinaryReader(meta.GetResponseStream()))
                        using (var strm = new MemoryStorage(rd.ReadBytes((int)meta.ContentLength)))
                        {
                            Directory.CreateDirectory(sysID);
                            strm.WriteAllBytes($"{sysID}/{contentID}.cnmt.nca");
                            using (var nca = new Nca(keys, strm, false).OpenSection(0, false, IntegrityCheckLevel.None, false))
                            {
                                var pfs  = new Pfs(nca);
                                var cnmt = new Cnmt(pfs.OpenFile(pfs.Files[0]).AsStream());
                                foreach (var entry in cnmt.MetaEntries)
                                {
                                    var tid = $"{entry.TitleId:x16}";
                                    HEAD(deviceID, nMetaURL('a', tid, $"{entry.Version.Version}", deviceID));
                                    var cID = HEAD(deviceID, nMetaURL('a', tid, $"{entry.Version.Version}", deviceID));

                                    using (var met2 = (HttpWebResponse)GET(deviceID, nContentURL('a', cID), false))
                                        using (var rdr = new BinaryReader(met2.GetResponseStream()))
                                            using (var strm2 = new MemoryStorage(rdr.ReadBytes((int)meta.ContentLength)))
                                            {
                                                Directory.CreateDirectory($"{sysID}/{tid}");
                                                strm2.WriteAllBytes($"{sysID}/{tid}/{cID}.cnmt.nca");
                                                using (var nca2 = new Nca(keys, strm2, false).OpenSection(0, false, IntegrityCheckLevel.None, false))
                                                {
                                                    var pfs2  = new Pfs(nca2);
                                                    var cnmt2 = new Cnmt(pfs2.OpenFile(pfs2.Files[0]).AsStream());
                                                    foreach (var entry2 in cnmt2.ContentEntries)
                                                    {
                                                        string NCAID = entry2.NcaId.ToHexString().ToLower();
                                                        using (var Req = (HttpWebResponse)GET(deviceID, nContentURL('c', NCAID), false))
                                                            using (var Output = File.OpenWrite($"{sysID}/{tid}/{NCAID}.nca"))
                                                                Req.GetResponseStream().CopyTo(Output);
                                                    }
                                                }
                                            }
                                }
                            }
                        }

                return;
            }

            string id          = null,
                   idFirstReq  = null,
                   idSecondReq = null;

            List <string> tidTargets   = new List <string>(),
                          verTargets   = new List <string>(),
                          entryTargets = new List <string>();

            var numOfListings = 0;

            if (args.Length == 2)
            {
                if (args[1] == "-d")
                {
                    getDeltasOnly = true;
                }
                else if (args[0] == "-t")
                {
                    var rightsID = args[1];
                    using (var tikReq = (HttpWebResponse)GET(deviceID, CETKURL(rightsID), false))
                        using (var strm = tikReq.GetResponseStream())
                            using (var rd = new BinaryReader(strm))
                            {
                                File.WriteAllBytes($"{rightsID}.tik", rd.ReadBytes(0x2C0));
                                File.WriteAllBytes($"{rightsID}.cert", rd.ReadBytes(0x700));
                            }

                    return;
                }
            }

            GET(deviceID, Aqua(deviceID), false);

            if (args.Length == 3)
            {
                numOfListings = 2;
                if (args[0].Substring(13, 3) != "000" && args[0].Substring(13, 3) != "800")
                {
                    tidTargets.Add(null);
                    tidTargets.Add(args[0]);
                }
                else
                {
                    tidTargets.Add(null);
                    tidTargets.Add($"{args[0].Substring(0, 13)}800");
                }
                verTargets.Add(null);
                verTargets.Add(args[2]);
            }
            else
            {
                var Streq = (string)GET(deviceID, Superfly(GetBaseTID(args[0])), true);
                if (args[0].Substring(13, 3) == "000")
                {
                    foreach (JToken Listing in JArray.Parse(Streq))
                    {
                        if ((string)Listing["title_type"] != "AddOnContent")
                        {
                            numOfListings++;
                            tidTargets.Add(Listing["title_id"].ToString());
                            verTargets.Add(Listing["version"].ToString());
                        }
                    }
                }
                else
                {
                    foreach (JToken Listing in JArray.Parse(Streq))
                    {
                        if ((string)Listing["title_id"] == args[0])
                        {
                            numOfListings++;
                            tidTargets.Add(Listing["title_id"].ToString());
                            verTargets.Add(Listing["version"].ToString());
                        }
                    }
                }
            }

            if (args.Length == 1)
            {
                id = HEAD(deviceID, MetaURL('a', tidTargets[0], verTargets[0], deviceID));
            }

            if (args.Length == 1 && id != null)
            {
                GET(deviceID, ContentURL('a', id), true);
            }

            if (numOfListings >= 2)
            {
                idFirstReq = HEAD(deviceID, MetaURL('a', tidTargets[1], verTargets[1], deviceID));
            }

            if (args.Length == 1 && numOfListings >= 2)
            {
                GET(deviceID, ContentURL('a', idFirstReq), true);
            }

            if (numOfListings >= 2)
            {
                idSecondReq = HEAD(deviceID, MetaURL('a', tidTargets[1], verTargets[1], deviceID));
            }

            if (numOfListings >= 2)
            {
                GET(deviceID, ContentURL('a', idSecondReq), true);
            }

            if (args.Length == 1)
            {
                using (var meta = (HttpWebResponse)GET(deviceID, ContentURL('a', id), false))
                    using (var rd = new BinaryReader(meta.GetResponseStream()))
                        using (var strm = new MemoryStorage(rd.ReadBytes((int)meta.ContentLength)))
                        {
                            Directory.CreateDirectory(tidTargets[0]);
                            strm.WriteAllBytes($"{tidTargets[0]}/{id}.cnmt.nca");
                            using (var nca = new Nca(keys, strm, false).OpenSection(0, false, IntegrityCheckLevel.None, false))
                            {
                                var pfs  = new Pfs(nca);
                                var cnmt = new Cnmt(pfs.OpenFile(pfs.Files[0]).AsStream());
                                foreach (var entry in cnmt.ContentEntries)
                                {
                                    string NCAID = entry.NcaId.ToHexString().ToLower();
                                    using (var Req = (HttpWebResponse)GET(deviceID, ContentURL('c', NCAID), false))
                                        using (var Output = File.OpenWrite($"{tidTargets[0]}/{NCAID}.nca"))
                                            Req.GetResponseStream().CopyTo(Output);
                                }
                            }
                        }
            }

            if (numOfListings >= 2)
            {
                using (var meta = (HttpWebResponse)GET(deviceID, ContentURL('a', idSecondReq), false))
                    using (var read = new BinaryReader(meta.GetResponseStream()))
                        using (var metastrm = new MemoryStorage(read.ReadBytes((int)meta.ContentLength)))
                        {
                            Directory.CreateDirectory(tidTargets[1]);
                            metastrm.WriteAllBytes($"{tidTargets[1]}/{idSecondReq}.cnmt.nca");
                            using (var nca = new Nca(keys, metastrm, false).OpenSection(0, false, IntegrityCheckLevel.None, false))
                            {
                                var pfs  = new Pfs(nca);
                                var cnmt = new Cnmt(pfs.OpenFile(pfs.Files[0]).AsStream());
                                foreach (var entry in getDeltasOnly ?
                                         cnmt.ContentEntries.Where(e => e.Type == CnmtContentType.DeltaFragment) :
                                         cnmt.ContentEntries)
                                {
                                    var ncaID = entry.NcaId.ToHexString().ToLower();
                                    using (var request = (HttpWebResponse)GET(deviceID, ContentURL('c', ncaID), false))
                                        using (var output = File.OpenWrite($"{tidTargets[1]}/{ncaID}.nca"))
                                            request.GetResponseStream().CopyTo(output);

                                    if (entry.Type == CnmtContentType.Program)
                                    {
                                        var rightsID = new Nca(keys, new StreamStorage
                                                                   (File.OpenRead($"{tidTargets[1]}/{ncaID}.nca"), false), false)
                                                       .Header.RightsId.ToHexString().ToLower();

                                        using (var tikReq = (HttpWebResponse)GET(deviceID, CETKURL(rightsID), false))
                                            using (var strm = tikReq.GetResponseStream())
                                                using (var rd = new BinaryReader(strm))
                                                {
                                                    File.WriteAllBytes($"{tidTargets[1]}/{rightsID}.tik", rd.ReadBytes(0x2C0));
                                                    File.WriteAllBytes($"{tidTargets[1]}/{rightsID}.cert", rd.ReadBytes(0x700));
                                                }
                                    }
                                }
                            }
                        }
            }
        }
Пример #18
0
        private void OnNandFound()
        {
            Nand   nand       = NANDService.NAND;
            Stream NANDSource = NANDService.NANDSource;

            NANDSource.Seek(0x804000, SeekOrigin.Begin); // BCPKG2-1-Normal-Main offset + length of BootConfig
            FileStream pkg2stream = HACGUIKeyset.TempPkg2FileInfo.Create();

            NANDSource.CopyToNew(pkg2stream, 0x7FC000); // rest of BCPPKG2-Normal-Main partition
            pkg2stream.Seek(0, SeekOrigin.Begin);
            byte[] pkg2raw = new byte[pkg2stream.Length];
            pkg2stream.Read(pkg2raw, 0, pkg2raw.Length);

            Package2 pkg2 = new Package2(HACGUIKeyset.Keyset, new MemoryStream(pkg2raw));

            HACGUIKeyset.RootTempPkg2FolderInfo.Create();
            FileStream kernelstream = HACGUIKeyset.TempKernelFileInfo.Create();
            FileStream INI1stream   = HACGUIKeyset.TempINI1FileInfo.Create();

            pkg2.OpenKernel().CopyTo(kernelstream);
            pkg2.OpenIni1().CopyTo(INI1stream);
            kernelstream.Close();
            INI1stream.Close();

            Ini1 INI1 = new Ini1(pkg2.OpenIni1());
            List <HashSearchEntry>      hashes = new List <HashSearchEntry>();
            Dictionary <byte[], byte[]> keys   = new Dictionary <byte[], byte[]>();

            HACGUIKeyset.RootTempINI1Folder.Create();
            foreach (Kip kip in INI1.Kips)
            {
                Stream rodatastream, datastream;
                switch (kip.Header.Name)
                {
                case "FS":
                    hashes.Add(new HashSearchEntry(NintendoKeys.KeyAreaKeyApplicationSourceHash, 0x10));
                    hashes.Add(new HashSearchEntry(NintendoKeys.KeyAreaKeyOceanSourceHash, 0x10));
                    hashes.Add(new HashSearchEntry(NintendoKeys.KeyAreaKeySystemSourceHash, 0x10));
                    hashes.Add(new HashSearchEntry(NintendoKeys.HeaderKekSourceHash, 0x10));
                    hashes.Add(new HashSearchEntry(NintendoKeys.SaveMacKekSourceHash, 0x10));
                    hashes.Add(new HashSearchEntry(NintendoKeys.SaveMacKeySourceHash, 0x10));

                    rodatastream = new MemoryStream(kip.DecompressSection(1));
                    keys         = rodatastream.FindKeyViaHash(hashes, new SHA256Managed(), 0x10);
                    Array.Copy(keys[NintendoKeys.KeyAreaKeyApplicationSourceHash], HACGUIKeyset.Keyset.KeyAreaKeyApplicationSource, 0x10);
                    Array.Copy(keys[NintendoKeys.KeyAreaKeyOceanSourceHash], HACGUIKeyset.Keyset.KeyAreaKeyOceanSource, 0x10);
                    Array.Copy(keys[NintendoKeys.KeyAreaKeySystemSourceHash], HACGUIKeyset.Keyset.KeyAreaKeySystemSource, 0x10);
                    Array.Copy(keys[NintendoKeys.HeaderKekSourceHash], HACGUIKeyset.Keyset.HeaderKekSource, 0x10);
                    Array.Copy(keys[NintendoKeys.SaveMacKekSourceHash], HACGUIKeyset.Keyset.SaveMacKekSource, 0x10);
                    Array.Copy(keys[NintendoKeys.SaveMacKeySourceHash], HACGUIKeyset.Keyset.SaveMacKeySource, 0x10);

                    hashes.Clear();
                    rodatastream.Seek(0, SeekOrigin.Begin);

                    bool sdWarn = false;

                    hashes.Add(new HashSearchEntry(NintendoKeys.SDCardKekSourceHash, 0x10));
                    try
                    {
                        keys = rodatastream.FindKeyViaHash(hashes, new SHA256Managed(), 0x10);
                        Array.Copy(keys[NintendoKeys.SDCardKekSourceHash], HACGUIKeyset.Keyset.SdCardKekSource, 0x10);
                    }
                    catch (EndOfStreamException)
                    {
                        MessageBox.Show("Failed to find SD card kek source! The NAND is probably from 1.0.0.");
                        sdWarn = true;
                    }

                    if (!sdWarn)     // don't try to find the rest of the keys if the other one couldn't be found
                    {
                        hashes.Clear();
                        rodatastream.Seek(0, SeekOrigin.Begin);
                        hashes.Add(new HashSearchEntry(NintendoKeys.SDCardSaveKeySourceHash, 0x20));
                        hashes.Add(new HashSearchEntry(NintendoKeys.SDCardNcaKeySourceHash, 0x20));
                        keys = rodatastream.FindKeyViaHash(hashes, new SHA256Managed(), 0x20);
                        Array.Copy(keys[NintendoKeys.SDCardSaveKeySourceHash], HACGUIKeyset.Keyset.SdCardKeySources[0], 0x20);
                        Array.Copy(keys[NintendoKeys.SDCardNcaKeySourceHash], HACGUIKeyset.Keyset.SdCardKeySources[1], 0x20);
                    }

                    hashes.Clear();
                    rodatastream.Close();

                    hashes.Add(new HashSearchEntry(NintendoKeys.HeaderKeySourceHash, 0x20));
                    datastream = new MemoryStream(kip.DecompressSection(2));
                    keys       = datastream.FindKeyViaHash(hashes, new SHA256Managed(), 0x20);
                    Array.Copy(keys[NintendoKeys.HeaderKeySourceHash], HACGUIKeyset.Keyset.HeaderKeySource, 0x20);

                    datastream.Close();
                    hashes.Clear();

                    break;

                case "spl":
                    hashes.Add(new HashSearchEntry(NintendoKeys.AesKeyGenerationSourceHash, 0x10));

                    rodatastream = new MemoryStream(kip.DecompressSection(1));
                    keys         = rodatastream.FindKeyViaHash(hashes, new SHA256Managed(), 0x10);
                    Array.Copy(keys[NintendoKeys.AesKeyGenerationSourceHash], HACGUIKeyset.Keyset.AesKeyGenerationSource, 0x10);

                    rodatastream.Close();
                    hashes.Clear();
                    break;
                }

                FileStream kipstream = HACGUIKeyset.RootTempINI1Folder.GetFile(kip.Header.Name + ".kip").Create();
                kip.OpenRawFile().CopyTo(kipstream);
                kipstream.Close();
            }

            pkg2stream.Close();
            INI1stream.Close();

            HACGUIKeyset.Keyset.DeriveKeys();

            SwitchFs fs = new SwitchFs(HACGUIKeyset.Keyset, NANDService.NAND.OpenSystemPartition());

            foreach (KeyValuePair <string, Nca> kv in fs.Ncas)
            {
                Nca nca = kv.Value;

                switch (nca.Header.TitleId)
                {
                case 0x0100000000000033:     // es
                    switch (nca.Header.ContentType)
                    {
                    case ContentType.Program:
                        NcaSection exefsSection = nca.Sections.FirstOrDefault(x => x?.Type == SectionType.Pfs0);
                        Stream     pfsStream    = nca.OpenSection(exefsSection.SectionNum, false, false);
                        Pfs        pfs          = new Pfs(pfsStream);
                        Nso        nso          = new Nso(pfs.OpenFile("main"));
                        NsoSection section      = nso.Sections[1];
                        Stream     data         = new MemoryStream(section.DecompressSection());
                        hashes.Clear();

                        hashes.Add(new HashSearchEntry(NintendoKeys.EticketRsaKekSourceHash, 0x10));
                        hashes.Add(new HashSearchEntry(NintendoKeys.EticketRsaKekekSourceHash, 0x10));
                        keys = data.FindKeyViaHash(hashes, new SHA256Managed(), 0x10, data.Length);
                        byte[] EticketRsaKekSource   = new byte[0x10];
                        byte[] EticketRsaKekekSource = new byte[0x10];
                        Array.Copy(keys[NintendoKeys.EticketRsaKekSourceHash], EticketRsaKekSource, 0x10);
                        Array.Copy(keys[NintendoKeys.EticketRsaKekekSourceHash], EticketRsaKekekSource, 0x10);

                        byte[] RsaOaepKekGenerationSource;
                        XOR(NintendoKeys.KekMasks[0], NintendoKeys.KekSeeds[3], out RsaOaepKekGenerationSource);

                        byte[] key1 = new byte[0x10];
                        Crypto.DecryptEcb(HACGUIKeyset.Keyset.MasterKeys[0], RsaOaepKekGenerationSource, key1, 0x10);
                        byte[] key2 = new byte[0x10];
                        Crypto.DecryptEcb(key1, EticketRsaKekekSource, key2, 0x10);
                        byte[] key3 = new byte[0x10];
                        Crypto.DecryptEcb(key2, EticketRsaKekSource, HACGUIKeyset.Keyset.EticketRsaKek, 0x10);
                        break;
                    }
                    break;
                }
            }

            Stream prodinfo     = nand.OpenProdInfo();
            Stream prodinfoFile = HACGUIKeyset.TempPRODINFOFileInfo.Create();

            prodinfo.CopyTo(prodinfoFile);
            prodinfo.Close();
            prodinfoFile.Seek(0, SeekOrigin.Begin);
            Calibration cal0 = new Calibration(prodinfoFile);

            HACGUIKeyset.Keyset.EticketExtKeyRsa = Crypto.DecryptRsaKey(cal0.EticketExtKeyRsa, HACGUIKeyset.Keyset.EticketRsaKek);
            prodinfoFile.Close();

            List <Ticket> tickets = new List <Ticket>();
            NandPartition system  = nand.OpenSystemPartition();

            Stream e1Stream = system.OpenFile("save\\80000000000000E1", FileMode.Open, FileAccess.Read);

            tickets.AddRange(ReadTickets(HACGUIKeyset.Keyset, e1Stream));

            Stream e2Stream = system.OpenFile("save\\80000000000000E2", FileMode.Open, FileAccess.Read);

            tickets.AddRange(ReadTickets(HACGUIKeyset.Keyset, e2Stream));

            Stream   nsAppmanStream = system.OpenFile("save\\8000000000000043", FileMode.Open, FileAccess.Read);
            Savefile save           = new Savefile(HACGUIKeyset.Keyset, nsAppmanStream, false);
            Stream   privateStream  = save.OpenFile("/private");

            byte[] sdSeed = new byte[0x10];
            privateStream.Read(sdSeed, 0, 0x10); // Seek doesn't work so i just read twice
            privateStream.Read(sdSeed, 0, 0x10);
            HACGUIKeyset.Keyset.SetSdSeed(sdSeed);

            foreach (Ticket ticket in tickets)
            {
                HACGUIKeyset.Keyset.TitleKeys[ticket.RightsId] = new byte[0x10];
                Array.Copy(ticket.TitleKeyBlock, HACGUIKeyset.Keyset.TitleKeys[ticket.RightsId], 0x10);
            }
            NANDService.Stop();

            HACGUIKeyset.ProductionKeysFileInfo.Create().WriteString(HACGUIKeyset.PrintCommonKeys(HACGUIKeyset.Keyset, true));
            HACGUIKeyset.ExtraKeysFileInfo.Create().WriteString(HACGUIKeyset.PrintCommonWithoutFriendlyKeys(HACGUIKeyset.Keyset));
            HACGUIKeyset.ConsoleKeysFileInfo.Create().WriteString(ExternalKeys.PrintUniqueKeys(HACGUIKeyset.Keyset));
            HACGUIKeyset.GetConsoleKeysFileInfoByName(PickConsole.ConsoleName).Create().WriteString(ExternalKeys.PrintUniqueKeys(HACGUIKeyset.Keyset));
            HACGUIKeyset.TitleKeysFileInfo.Create().WriteString(ExternalKeys.PrintTitleKeys(HACGUIKeyset.Keyset));
        }
Пример #19
0
        public void LoadNca(Nca MainNca, Nca ControlNca)
        {
            NcaSection RomfsSection = MainNca.Sections.FirstOrDefault(x => x?.Type == SectionType.Romfs || x?.Type == SectionType.Bktr);
            NcaSection ExefsSection = MainNca.Sections.FirstOrDefault(x => x?.IsExefs == true);

            if (ExefsSection == null)
            {
                Logger.PrintError(LogClass.Loader, "No ExeFS found in NCA");

                return;
            }

            if (RomfsSection == null)
            {
                Logger.PrintWarning(LogClass.Loader, "No RomFS found in NCA");
            }
            else
            {
                Stream RomfsStream = MainNca.OpenSection(RomfsSection.SectionNum, false, EnableFsIntegrityChecks);

                Device.FileSystem.SetRomFs(RomfsStream);
            }

            Stream ExefsStream = MainNca.OpenSection(ExefsSection.SectionNum, false, EnableFsIntegrityChecks);

            Pfs Exefs = new Pfs(ExefsStream);

            Npdm MetaData = null;

            if (Exefs.FileExists("main.npdm"))
            {
                Logger.PrintInfo(LogClass.Loader, "Loading main.npdm...");

                MetaData = new Npdm(Exefs.OpenFile("main.npdm"));
            }
            else
            {
                Logger.PrintWarning(LogClass.Loader, $"NPDM file not found, using default values!");
            }

            Process MainProcess = MakeProcess(MetaData);

            void LoadNso(string Filename)
            {
                foreach (PfsFileEntry File in Exefs.Files.Where(x => x.Name.StartsWith(Filename)))
                {
                    if (Path.GetExtension(File.Name) != string.Empty)
                    {
                        continue;
                    }

                    Logger.PrintInfo(LogClass.Loader, $"Loading {Filename}...");

                    string Name = Path.GetFileNameWithoutExtension(File.Name);

                    Nso Program = new Nso(Exefs.OpenFile(File), Name);

                    MainProcess.LoadProgram(Program);
                }
            }

            Nacp ReadControlData()
            {
                Romfs ControlRomfs = new Romfs(ControlNca.OpenSection(0, false, EnableFsIntegrityChecks));

                byte[] ControlFile = ControlRomfs.GetFile("/control.nacp");

                BinaryReader Reader = new BinaryReader(new MemoryStream(ControlFile));

                Nacp ControlData = new Nacp(Reader);

                CurrentTitle = ControlData.Languages[(int)State.DesiredTitleLanguage].Title;

                if (string.IsNullOrWhiteSpace(CurrentTitle))
                {
                    CurrentTitle = ControlData.Languages.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title;
                }

                return(ControlData);
            }

            if (ControlNca != null)
            {
                MainProcess.ControlData = ReadControlData();
            }
            else
            {
                CurrentTitle = MainProcess.MetaData.ACI0.TitleId.ToString("x16");
            }

            if (!MainProcess.MetaData.Is64Bits)
            {
                throw new NotImplementedException("32-bit titles are unsupported!");
            }

            LoadNso("rtld");

            MainProcess.SetEmptyArgs();

            LoadNso("main");
            LoadNso("subsdk");
            LoadNso("sdk");

            MainProcess.Run();
        }
Пример #20
0
        static void Main(string[] args)
        {
            var path = args.Length >= 1
                ? args[0]
                : Environment.CurrentDirectory;

            var fs = new FileSystem(path);

            if (!File.Exists("keys.txt"))
            {
                Console.WriteLine("Cannot verify NSPs without keys.txt");
                Console.WriteLine();
                Console.WriteLine("Press any key to continue");
                Console.ReadKey();
                return;
            }

            var keyset        = ExternalKeys.ReadKeyFile("keys.txt");
            var badlist       = new List <string>();
            var exceptionlist = new List <string>();



            foreach (var file in fs.GetFileSystemEntries("", "*.nsp", SearchOption.AllDirectories))
            {
                var filename = Path.GetFileName(file);
                var progress = $"Checking {filename}: ";
                Console.Write(progress);
                try
                {
                    bool ok = true;
                    using (var nspfile = fs.OpenFile(file, FileMode.Open, FileAccess.Read))
                    {
                        var nspdata  = new Pfs(nspfile);
                        var cnmtfile = nspdata.Files.FirstOrDefault(x => x.Name.ToLowerInvariant().EndsWith(".cnmt.nca"));
                        if (cnmtfile == null)
                        {
                            Console.WriteLine($"\rChecking {filename}: No cnmt.nca file present");
                            badlist.Add(filename);
                            continue;
                        }

                        var  cnmtdata = nspdata.OpenFile(cnmtfile);
                        Cnmt cnmt;
                        using (var sr = new BinaryReader(cnmtdata))
                        {
                            var cnmthash = SHA256.Create().ComputeHash(sr.ReadBytes((int)cnmtdata.Length));
                            if (!cnmtfile.Name.ToLowerInvariant().Contains(cnmthash.Take(16).ToArray().ToHexString()))
                            {
                                //Put failure here
                                Console.WriteLine($"\rChecking {filename}: cnmt.nca file is corrupted");
                                badlist.Add(filename);
                                cnmtdata.Dispose();
                                continue;
                            }

                            cnmtdata.Position = 0;
                            var cnmtnca    = new Nca(keyset, cnmtdata, false);
                            var section    = cnmtnca.OpenSection(0, false);
                            var sectionpfs = new Pfs(section);
                            cnmt = new Cnmt(sectionpfs.OpenFile(sectionpfs.Files[0]));
                        }

                        foreach (var entry in cnmt.ContentEntries)
                        {
                            var entryfile = nspdata.Files.FirstOrDefault(x => x.Name.ToLowerInvariant().EndsWith(entry.NcaId.ToHexString() + ".nca"));
                            if (entryfile == null)
                            {
                                if (entry.Type != CnmtContentType.UpdatePatch)
                                {
                                    //Put failure here
                                    Console.WriteLine($"\rChecking {filename}: one of the entries required by the cnmt.nca is missing.");
                                    badlist.Add(filename);
                                    break;
                                }

                                continue;
                            }

                            using (var entrynca = nspdata.OpenFile(entryfile))
                            {
                                var hash = SHA256.Create();

                                using (var sr = new BinaryReader(entrynca))
                                {
                                    while (entrynca.Length != entrynca.Position)
                                    {
                                        var entryncadata = sr.ReadBytes(0x100000);
                                        hash.TransformBlock(entryncadata, 0, entryncadata.Length, entryncadata, 0);
                                        Console.Write($"\rChecking {filename}: {((entrynca.Position * 100.0) / entrynca.Length):0.0}%");
                                    }

                                    hash.TransformFinalBlock(new byte[0], 0, 0);
                                }

                                if (hash.Hash.ToHexString().Equals(entry.Hash.ToHexString()))
                                {
                                    Console.Write($"\rChecking {filename}: {100:0.0}%");
                                    continue;
                                }

                                //Put failure here
                                Console.WriteLine($"\rChecking {filename}: one of the entries required by the cnmt.nca is corrupted");
                                badlist.Add(filename);
                                ok = false;
                                break;
                            }
                        }

                        if (ok)
                        {
                            Console.WriteLine($"\rChecking {filename}: OK        ");
                        }
                        //Put Success here
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.WriteLine(ex.StackTrace);
                    exceptionlist.Add($"{filename}{Environment.NewLine}Exception: {ex.Message}{Environment.NewLine}Stack Trace: {ex.StackTrace}{Environment.NewLine}");
                }
            }

            File.WriteAllText("Corrupted NSPs.txt", string.Join(Environment.NewLine, badlist));
            File.WriteAllText("Exception Log.txt", string.Join(Environment.NewLine, exceptionlist));

            Console.WriteLine();
            Console.WriteLine("Press any key to continue");
            Console.ReadKey();
        }
Пример #21
0
        public static Title processNsp(string filename)
        {
            Title title = new Title();

            using (var filestream = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                Pfs    pfs;
                string biggestNca = null, controlNca = null;

                try
                {
                    pfs = new Pfs(filestream.AsStorage());

                    title.distribution = Title.Distribution.Digital;
                }
                catch (InvalidDataException)
                {
                    return(null);
                }

                log?.WriteLine("Processing NSP {0}", filename);

                PfsFileEntry[] fileEntries = pfs.Files;
                foreach (PfsFileEntry entry in fileEntries)
                {
                    if (entry.Name.EndsWith(".cnmt.xml"))
                    {
                        using (var cnmtXml = pfs.OpenFile(entry))
                        {
                            (biggestNca, controlNca) = processCnmtXml(cnmtXml, ref title);
                        }

                        title.structure.Add(Title.Structure.CnmtXml);
                    }
                    else if (entry.Name.EndsWith(".cnmt.nca"))
                    {
                        using (var cnmtNca = pfs.OpenFile(entry))
                        {
                            var nca = processCnmtNca(cnmtNca, ref title);
                            if (nca.Item1 != null && (nca.Item2 != null || title.type == TitleType.AddOnContent))
                            {
                                (biggestNca, controlNca) = nca;
                            }
                        }

                        title.structure.Add(Title.Structure.CnmtNca);
                    }
                    else if (entry.Name.EndsWith(".cert"))
                    {
                        title.structure.Add(Title.Structure.Cert);
                    }
                    else if (entry.Name.EndsWith(".tik"))
                    {
                        title.structure.Add(Title.Structure.Tik);
                    }
                    else if (entry.Name.EndsWith(".legalinfo.xml"))
                    {
                        title.structure.Add(Title.Structure.LegalinfoXml);
                    }
                    else if (entry.Name.EndsWith(".nacp.xml"))
                    {
                        using (var nacpXml = pfs.OpenFile(entry))
                        {
                            processNacpXml(nacpXml, ref title);
                        }

                        title.structure.Add(Title.Structure.NacpXml);
                    }
                    else if (entry.Name.EndsWith(".programinfo.xml"))
                    {
                        title.structure.Add(Title.Structure.PrograminfoXml);
                    }
                    else if (entry.Name.Equals("cardspec.xml"))
                    {
                        title.structure.Add(Title.Structure.CardspecXml);
                    }
                    else if (entry.Name.Equals("authoringtoolinfo.xml"))
                    {
                        title.structure.Add(Title.Structure.AuthoringtoolinfoXml);
                    }
                }

                if (!String.IsNullOrEmpty(biggestNca))
                {
                    using (var biggest = pfs.OpenFile(biggestNca))
                    {
                        processBiggestNca(biggest, ref title);
                    }
                }

                if (!String.IsNullOrEmpty(controlNca))
                {
                    using (var control = pfs.OpenFile(controlNca))
                    {
                        processControlNca(control, ref title);
                    }
                }
            }

            if (title.type == TitleType.Application || title.type == TitleType.Patch)
            {
                if (versionList.TryGetValue(title.titleIDApplication, out uint version))
                {
                    title.latestVersion = version;
                }
            }

            log?.WriteLine("NSP information for {0}: [{1}] {2}", filename, title.titleID, title.titleName);

            return(title);
        }
Пример #22
0
        //Open update only
        private void Open_NSP_Update(object sender, EventArgs e)
        {
            var Dialog = openFileDialog1.ShowDialog();

            if (Dialog != DialogResult.Cancel)
            {
                Console.WriteLine("LOADING.");
                label8.Visible = true;
                this.Update();
                treeView1.Nodes.Clear();

                string FileToOpen = null;

                if (Program.FileArg != null)
                {
                    FileToOpen = Program.FileArg;
                }
                else
                {
                    FileToOpen = openFileDialog1.FileName;
                }

                Program.FileArg = null;
                Stream Input = null;

                try
                {
                    string ExpEnv(string In) => Environment.ExpandEnvironmentVariables(In);

                    var ProdKeys  = ExpEnv(@"%USERPROFILE%\.switch\prod.keys");
                    var TitleKeys = ExpEnv(@"%USERPROFILE%\.switch\title.keys");
                    Console.WriteLine(FileToOpen);

                    var Keys = ExternalKeys.ReadKeyFile(ProdKeys, TitleKeys);

                    var Ext = (new FileInfo(FileToOpen).Extension);
                    if (Ext == ".nsp")
                    {
                        var InputPFS  = File.OpenRead(FileToOpen);
                        var Pfs       = new Pfs(InputPFS.AsStorage());
                        var CnmtNca   = new Nca(Keys, Pfs.OpenFile(Pfs.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false);
                        var CnmtPfs   = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None, true));
                        var Cnmt      = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]).AsStream());
                        var Program   = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program);
                        var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control);
                        if (CtrlEntry != null)
                        {
                            Control = new Nca(Keys, Pfs.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false);
                        }
                        Input = Pfs.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca").AsStream();
                    }
                    else
                    {
                        Input = File.OpenRead(FileToOpen);
                    }

                    try
                    {
                        Nca = new Nca(Keys, Input.AsStorage(), true);

                        if (Nca.HasRightsId && !Keys.TitleKeys.Keys.Any(k => k.SequenceEqual(Nca.Header.RightsId)))
                        {
                            MessageBox.Show($"Error: the titlekey for {Nca.Header.RightsId.ToHexString().ToLower()} is not present in your key file.");
                        }
                        else
                        {
                            var isUpdateNca = false;

                            if (Nca.Sections.Any(s => s?.Type == SectionType.Bktr))
                            {
                                isUpdateNca = true;
                            }

                            if (isUpdateNca)
                            {
                                var InputPFS  = File.OpenRead(FileToOpen);
                                var Pfs       = new Pfs(InputPFS.AsStorage());
                                var CnmtNca   = new Nca(Keys, Pfs.OpenFile(Pfs.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false);
                                var CnmtPfs   = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None, true));
                                var Cnmt      = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]).AsStream());
                                var Program   = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program);
                                var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control);
                                if (CtrlEntry != null)
                                {
                                    Control = new Nca(Keys, Pfs.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false);
                                }
                                Input = Pfs.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca").AsStream();

                                var Input2 = Pfs.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca").AsStream();
                                Patch = new Nca(Keys, Input2.AsStorage(), true);
                                Nca.SetBaseNca(Patch);
                            }

                            new Thread
                                (() =>
                            {
                                Thread.CurrentThread.IsBackground = true;
                                var Info = GetTitleMeta($"{Nca.Header.TitleId:x16}");
                                label2.Invoke(new Action(() => { label2.Text = Info[0]; label3.Text = Info[1]; }));
                            }).Start();

                            Rom = new Romfs(
                                Nca.OpenSection(Nca.Sections.FirstOrDefault
                                                    (s => s?.Type == SectionType.Romfs || s?.Type == SectionType.Bktr)
                                                .SectionNum, false, IntegrityCheckLevel.None, true)
                                );

                            IO.PopulateTreeView(treeView1.Nodes, Rom.RootDir);

                            Console.WriteLine("DONE.");
                            fileToolStripMenuItem.Text = "File / Explore";
                            label8.Visible             = false;
                            this.Update();
                        }
                    }
                    catch
                    {
                        MessageBox.Show("There was an error reading the NCA. Are you sure the correct keys are present in your keyfiles?");
                    }
                }
                catch (ArgumentNullException) { MessageBox.Show("Error: key files are missing!"); }
            }
        }
Пример #23
0
        private void Open()
        {
            treeView1.Nodes.Clear();

            string FileToOpen = null;

            if (Program.FileArg != null)
            {
                FileToOpen = Program.FileArg;
            }
            else
            {
                FileToOpen = openFileDialog1.FileName;
            }

            Program.FileArg = null;
            Stream Input = null;

            try
            {
                string ExpEnv(string In) => Environment.ExpandEnvironmentVariables(In);

                var ProdKeys  = ExpEnv(@"%USERPROFILE%\.switch\prod.keys");
                var TitleKeys = ExpEnv(@"%USERPROFILE%\.switch\title.keys");

                var Keys = ExternalKeys.ReadKeyFile(ProdKeys, TitleKeys);

                var Ext = (new FileInfo(FileToOpen).Extension);

                if (Ext == ".nsp")
                {
                    var InputPFS  = File.OpenRead(FileToOpen);
                    var Pfs       = new Pfs(InputPFS);
                    var CnmtNca   = new Nca(Keys, Pfs.OpenFile(Pfs.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false);
                    var CnmtPfs   = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None));
                    var Cnmt      = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]));
                    var Program   = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program);
                    var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control);
                    if (CtrlEntry != null)
                    {
                        Control = new Nca(Keys, Pfs.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false);
                    }
                    Input = Pfs.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca");
                }
                else if (Ext == ".xci")
                {
                    var InputPFS  = File.OpenRead(FileToOpen);
                    var Xci       = new Xci(Keys, InputPFS);
                    var CnmtNca   = new Nca(Keys, Xci.SecurePartition.OpenFile(Xci.SecurePartition.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false);
                    var CnmtPfs   = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None));
                    var Cnmt      = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]));
                    var Program   = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program);
                    var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control);
                    if (CtrlEntry != null)
                    {
                        Control = new Nca(Keys, Xci.SecurePartition.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false);
                    }
                    Input = Xci.SecurePartition.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca");
                }
                else if (FileToOpen.Split('.')[1] == "cnmt" && Ext == ".nca")
                {
                    var TargetFile = File.OpenRead(FileToOpen);
                    var CnmtNca    = new Nca(Keys, TargetFile, false);
                    var CnmtPfs    = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None));
                    var Cnmt       = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]));
                    var Program    = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program);
                    var CtrlEntry  = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control);
                    if (CtrlEntry != null)
                    {
                        Control = new Nca(Keys, File.OpenRead($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false);
                    }
                    Input = File.OpenRead($"{Program.NcaId.ToHexString().ToLower()}.nca");
                }
                else
                {
                    Input = File.OpenRead(FileToOpen);
                }

                try
                {
                    Nca = new Nca(Keys, Input, true);

                    if (Nca.HasRightsId && !Keys.TitleKeys.Keys.Any(k => k.SequenceEqual(Nca.Header.RightsId)))
                    {
                        MessageBox.Show($"Error: the titlekey for {Nca.Header.RightsId.ToHexString().ToLower()} is not present in your key file.");
                    }
                    else
                    {
                        bool isUpdateNca = false;

                        if (Nca.Sections.Any(s => s?.Type == SectionType.Bktr))
                        {
                            isUpdateNca = true;
                        }

                        if (isUpdateNca)
                        {
                            openFileDialog1.Title = "Select base Nca";
                            openFileDialog1.ShowDialog();
                            var Input2 = File.OpenRead(openFileDialog1.FileName);
                            Patch = new Nca(Keys, Input2, true);
                            Nca.SetBaseNca(Patch);
                        }

                        new Thread
                        (
                            () =>
                        {
                            Thread.CurrentThread.IsBackground = true;
                            var Info = GetTitleMeta($"{Nca.Header.TitleId:x16}");

                            label2.Invoke(new Action(() => { label2.Text = Info[0]; label3.Text = Info[1]; }));
                        }
                        )
                        .Start();

                        Rom = new Romfs
                              (
                            Nca.OpenSection
                            (
                                Nca.Sections.FirstOrDefault
                                    (s => s?.Type == SectionType.Romfs || s?.Type == SectionType.Bktr)
                                .SectionNum,
                                false,
                                IntegrityCheckLevel.None
                            )
                              );

                        IO.PopulateTreeView(treeView1.Nodes, Rom.RootDir);
                    }
                }
                catch
                {
                    MessageBox.Show("There was an error reading the NCA. Are you sure the correct keys are present in your keyfiles?");
                }
            }
            catch (ArgumentNullException)
            {
                MessageBox.Show("Error: key files are missing!");
            }
        }
Пример #24
0
        private void Open()
        {
            treeView1.Nodes.Clear();

            string FileToOpen = null;

            if (Program.FileArg != null)
            {
                FileToOpen = Program.FileArg;
            }
            else
            {
                FileToOpen = openFileDialog1.FileName;
            }

            Program.FileArg = null;

            Stream Input = null;

            try
            {
                string ExpEnv(string In)
                {
                    return(Environment.ExpandEnvironmentVariables(In));
                }

                var ProdKeys  = ExpEnv(@"%USERPROFILE%\.switch\prod.keys");
                var TitleKeys = ExpEnv(@"%USERPROFILE%\.switch\title.keys");

                var Keys = ExternalKeys.ReadKeyFile(ProdKeys, TitleKeys);

                var Ext = (new FileInfo(FileToOpen).Extension);

                if (Ext == ".nsp")
                {
                    var InputPFS = File.OpenRead(FileToOpen);
                    var Pfs      = new Pfs(InputPFS);

                    Input = Pfs.OpenFile
                            (
                        Pfs.Files.OrderByDescending(s => s.Size)
                        .FirstOrDefault()
                            );
                }
                else if (Ext == ".xci")
                {
                    var InputPFS = File.OpenRead(FileToOpen);
                    var Xci      = new Xci(Keys, InputPFS);

                    Input = Xci.SecurePartition.OpenFile
                            (
                        Xci.SecurePartition.Files
                        .OrderByDescending(s => s.Size)
                        .FirstOrDefault()
                            );
                }
                else
                {
                    Input = File.OpenRead(FileToOpen);
                }

                try
                {
                    Nca = new Nca(Keys, Input, true);

                    if (Nca.HasRightsId)
                    {
                        if (!Keys.TitleKeys.Keys.Contains(Nca.Header.RightsId))
                        {
                            MessageBox.Show($"Error: the titlekey for {Nca.Header.RightsId.ToHexString()} is not present in your key file.");
                        }
                    }

                    bool IsUpdateNca = false;

                    foreach (var Section in Nca.Sections)
                    {
                        if (Section?.Type == SectionType.Bktr)
                        {
                            IsUpdateNca = true;
                        }
                    }

                    if (IsUpdateNca)
                    {
                        openFileDialog1.Title = "Select base Nca";
                        openFileDialog1.ShowDialog();
                        var Input2 = File.OpenRead(openFileDialog1.FileName);
                        Patch = new Nca(Keys, Input2, true);
                        Nca.SetBaseNca(Patch);
                    }

                    new Thread
                    (
                        () =>
                    {
                        Thread.CurrentThread.IsBackground = true;
                        var Info = GetTitleMeta($"{Nca.Header.TitleId:x16}");

                        label2.Invoke
                        (
                            new Action
                            (
                                () => { label2.Text = Info[0]; }
                            )
                        );

                        label3.Invoke
                        (
                            new Action
                            (
                                () => { label3.Text = Info[1]; }
                            )
                        );
                    }
                    )
                    .Start();

                    Rom = new Romfs
                          (
                        Nca.OpenSection
                        (
                            Nca.Sections.FirstOrDefault
                                (s => s?.Type == SectionType.Romfs || s?.Type == SectionType.Bktr)
                            .SectionNum,
                            false,
                            false
                        )
                          );

                    IO.PopulateTreeView(treeView1.Nodes, Rom.RootDir);
                }
                catch (Exception)
                {
                    MessageBox.Show("There was an error reading the NCA. Are you sure the correct keys are present in your keyfiles?");
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Error: key files are missing!");
            }
        }