Ejemplo n.º 1
0
        static void AddSdk(ExeFS exefs, Nso custom)
        {
            Nso sdk = exefs.GetNso(NsoTypeEnum.sdk);

            exefs.SetNso(sdk, NsoTypeEnum.subsdk0);
            exefs.SetNso(custom, NsoTypeEnum.sdk);
        }
Ejemplo n.º 2
0
        public void LoadCart(string ExeFsDir, string RomFsFile = null)
        {
            if (RomFsFile != null)
            {
                Ns.VFs.LoadRomFs(RomFsFile);
            }

            Process MainProcess = MakeProcess();

            void LoadNso(string FileName)
            {
                foreach (string File in Directory.GetFiles(ExeFsDir, FileName))
                {
                    if (Path.GetExtension(File) != string.Empty)
                    {
                        continue;
                    }

                    Ns.Log.PrintInfo(LogClass.Loader, $"Loading {Path.GetFileNameWithoutExtension(File)}...");

                    using (FileStream Input = new FileStream(File, FileMode.Open))
                    {
                        string Name = Path.GetFileNameWithoutExtension(File);

                        Nso Program = new Nso(Input, Name);

                        MainProcess.LoadProgram(Program);
                    }
                }
            }

            void LoadNpdm(string FileName)
            {
                string File = Directory.GetFiles(ExeFsDir, FileName)[0];

                Ns.Log.PrintInfo(LogClass.Loader, "Loading Title Metadata...");

                using (FileStream Input = new FileStream(File, FileMode.Open))
                {
                    MainProcess.Metadata = new Npdm(Input);
                }
            }

            LoadNpdm("*.npdm");

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

            LoadNso("rtld");

            MainProcess.SetEmptyArgs();

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

            MainProcess.Run();
        }
Ejemplo n.º 3
0
        static void Main(string[] args)
        {
            "Starting load...".Print();
            var recompiler = new Recompiler();

            args.ForEach(fn =>
                         recompiler.Load(Nso.Read(fn, File.OpenRead(fn))));
            "Loaded".Print();
            recompiler.Run();
        }
Ejemplo n.º 4
0
        private void ProcessNsoSet(List <IFile> list)
        {
            if (list.Count == 0)
            {
                return;
            }

            var nsos = new List <(Nso nso, IFile file)>();

            foreach (IFile file in list)
            {
                var nso = new Nso(file.AsStorage());
                nsos.Add((nso, file));
            }

            var nsoInfos = new List <NsoInfo>();

            foreach ((Nso nso, IFile file)nso in nsos)
            {
                try
                {
                    nsoInfos.Add(GetNsoInfo(nso));
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Error processing {nso.nso.BuildId.ToHexString()}");
                    Console.WriteLine(ex);
                }
            }

            var set = new NsoSet();

            set.Nsos.AddRange(nsoInfos);
            NsoSets.Add(set);

            Version maxVersion = set.Nsos.Where(x => x.Version != null).Select(x => x.Version).Max();

            if (maxVersion != null)
            {
                NsoInfo maxInfo = set.Nsos.First(x => x.Version == maxVersion);

                set.Version       = maxVersion;
                set.MaxVersionNso = maxInfo;
            }

            foreach (NsoInfo info in nsoInfos)
            {
                info.Sets.Add(set);
            }
        }
Ejemplo n.º 5
0
        private void ProcessNso(string nsoPath)
        {
            FsClient.OpenFile(out FileHandle nsoHandle, nsoPath, OpenMode.Read).ThrowIfFailure();

            using (nsoHandle)
                using (var nsoStorage = new FileHandleStorage(nsoHandle, true))
                    using (var nsoFile = new StorageFile(nsoStorage, OpenMode.Read))
                    {
                        var     nso  = new Nso(nsoStorage);
                        NsoInfo info = GetNsoInfo((nso, nsoFile));

                        ParseNsoName(nsoPath, info);
                    }
        }
Ejemplo n.º 6
0
        public void LoadCart(string ExeFsDir, string RomFsFile = null)
        {
            if (RomFsFile != null)
            {
                Ns.VFs.LoadRomFs(RomFsFile);
            }

            int ProcessId = IdGen.GenerateId();

            Process MainProcess = new Process(Ns, Allocator, ProcessId);

            void LoadNso(string FileName)
            {
                foreach (string File in Directory.GetFiles(ExeFsDir, FileName))
                {
                    if (Path.GetExtension(File) != string.Empty)
                    {
                        continue;
                    }

                    Logging.Info($"Loading {Path.GetFileNameWithoutExtension(File)}...");

                    using (FileStream Input = new FileStream(File, FileMode.Open))
                    {
                        Nso Program = new Nso(Input);

                        MainProcess.LoadProgram(Program);
                    }
                }
            }

            LoadNso("rtld");

            MainProcess.SetEmptyArgs();

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

            MainProcess.InitializeHeap();
            MainProcess.Run();

            Processes.TryAdd(ProcessId, MainProcess);
        }
Ejemplo n.º 7
0
        static void Main(string[] args)
        {
            if (args.Length != 5)
            {
                Console.WriteLine($"Invalid Arg Nb ({args.Length})");
                ShowInfo();
                return;
            }

            string indir      = args[0];
            string subsdkPath = args[1];
            string outdir     = args[2];
            string lstFile    = args[3];
            string configFile = args[4];

            Console.WriteLine($"Current dir : {Environment.CurrentDirectory}");

            if (!Directory.Exists(indir) || !File.Exists(subsdkPath) || !Directory.Exists(outdir) || !File.Exists(lstFile) || !File.Exists(configFile))
            {
                Console.WriteLine($"Invalid Args :");
                foreach (var arg in args)
                {
                    Console.WriteLine(arg);
                }

                ShowInfo();
                return;
            }


            ExeFS exefs  = new ExeFS(indir);
            Nso   custom = new Nso(subsdkPath);

            //allocate 0x100 bytes at the end of .bss for the module_object
            AllocModObj(custom);
            AddSdk(exefs, custom);

            ApplyPatches(exefs, lstFile, configFile);

            Console.WriteLine("Exporting...");
            exefs.ExportAsDir(outdir);
            Console.WriteLine("Done!");
        }
Ejemplo n.º 8
0
        public void LoadCart(string ExeFsDir, string RomFsFile = null)
        {
            if (RomFsFile != null)
            {
                Ns.VFs.LoadRomFs(RomFsFile);
            }

            Process MainProcess = MakeProcess();

            void LoadNso(string FileName)
            {
                foreach (string File in Directory.GetFiles(ExeFsDir, FileName))
                {
                    if (Path.GetExtension(File) != string.Empty)
                    {
                        continue;
                    }

                    Ns.Log.PrintInfo(LogClass.Loader, $"Loading {Path.GetFileNameWithoutExtension(File)}...");

                    using (FileStream Input = new FileStream(File, FileMode.Open))
                    {
                        string Name = Path.GetFileNameWithoutExtension(File);

                        Nso Program = new Nso(Input, Name);

                        MainProcess.LoadProgram(Program);
                    }
                }
            }

            LoadNso("rtld");

            MainProcess.SetEmptyArgs();

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

            MainProcess.Run();
        }
Ejemplo n.º 9
0
        static void Main(string[] args)
        {
            if (args.Length != 4)
            {
                Console.WriteLine("Usage: IPSwitch-PatchMaker.exe [name of patch] [unpatched NSO] [patched NSO] [save location]");
                return;
            }

            string patchname = args[0];

            FileInfo unpatchednsoPath = new FileInfo(args[1]),
                     patchednsoPath   = new FileInfo(args[2]),
                     save             = new FileInfo(args[3]);

            using (var patchedstream = File.OpenRead(patchednsoPath.FullName))
                using (var unpatchedstream = File.OpenRead(unpatchednsoPath.FullName))
                {
                    var unpatchedNso = new Nso(unpatchedstream.AsStorage());
                    var patchedNso   = new Nso(patchedstream.AsStorage());

                    if (patchedNso.Sections.Length != unpatchedNso.Sections.Length)
                    {
                        Console.WriteLine("The NSO section lengths do not match (NSO comes from a diffrent application?)");
                        return;
                    }

                    List <string> patcharraylist = new List <string>
                    {
                        $"//{patchname}",
                        "@enabled"
                    };

                    string patch, offset = string.Empty;

                    for (int i = 0; i < unpatchedNso.Sections.Length; i++)
                    {
                        NsoSection unpatchedSection = unpatchedNso.Sections[i],
                                   patchedSection   = patchedNso.Sections[i];

                        byte[] unpatchedData = unpatchedSection.DecompressSection(),
                        patchedData = patchedSection.DecompressSection();

                        for (int index = 0; index < patchedData.Length; index++)
                        {
                            if (patchedData[index] != unpatchedData[index])
                            {
                                offset = $"{index:X8}";
                                patch  = $"{patchedData[index]:X2}";
                                patcharraylist.Add($"{offset} {patch}");
                            }
                            else
                            {
                                Console.WriteLine("No diffrences found.");
                                break;
                            }
                        }
                    }
                    File.WriteAllLines(save.FullName, patcharraylist);
                    Console.WriteLine($"Done, {patcharraylist.Count - 2} were different.");
                }
        }
Ejemplo n.º 10
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));
        }
Ejemplo n.º 11
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();
        }
Ejemplo n.º 12
0
        public void LoadCart(string ExeFsDir, string RomFsFile = null)
        {
            if (RomFsFile != null)
            {
                Device.FileSystem.LoadRomFs(RomFsFile);
            }

            string NpdmFileName = Path.Combine(ExeFsDir, "main.npdm");

            Npdm MetaData = null;

            if (File.Exists(NpdmFileName))
            {
                Logger.PrintInfo(LogClass.Loader, $"Loading main.npdm...");

                using (FileStream Input = new FileStream(NpdmFileName, FileMode.Open))
                {
                    MetaData = new Npdm(Input);
                }
            }
            else
            {
                Logger.PrintWarning(LogClass.Loader, $"NPDM file not found, using default values!");
            }

            Process MainProcess = MakeProcess(MetaData);

            void LoadNso(string FileName)
            {
                foreach (string File in Directory.GetFiles(ExeFsDir, FileName))
                {
                    if (Path.GetExtension(File) != string.Empty)
                    {
                        continue;
                    }

                    Logger.PrintInfo(LogClass.Loader, $"Loading {Path.GetFileNameWithoutExtension(File)}...");

                    using (FileStream Input = new FileStream(File, FileMode.Open))
                    {
                        string Name = Path.GetFileNameWithoutExtension(File);

                        Nso Program = new Nso(Input, Name);

                        MainProcess.LoadProgram(Program);
                    }
                }
            }

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

            CurrentTitle = MainProcess.MetaData.ACI0.TitleId.ToString("x16");

            LoadNso("rtld");

            MainProcess.SetEmptyArgs();

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

            MainProcess.Run();
        }
Ejemplo n.º 13
0
        private void OnNandFound()
        {
            Nand nand = NANDService.NAND;

            // stream package2 to memory
            IStorage pkg2nand = nand.OpenPackage2(0); // 0 -> BCPKG2-1-Normal-Main

            byte[] pkg2raw = new byte[0x7FC000];      // maximum size of pkg2
            pkg2nand.Read(0x4000, pkg2raw);

            MemoryStorage pkg2memory = new MemoryStorage(pkg2raw);

            HACGUIKeyset.RootTempFolderInfo.Create();

            // copy to file for end user
            using (FileStream pkg2file = HACGUIKeyset.TempPkg2FileInfo.Create())
                pkg2memory.CopyToStream(pkg2file);

            Package2 pkg2 = new Package2(HACGUIKeyset.Keyset, pkg2memory);

            HACGUIKeyset.RootTempPkg2FolderInfo.Create(); // make sure it exists
            using (FileStream kernelstream = HACGUIKeyset.TempKernelFileInfo.Create())
                pkg2.OpenKernel().CopyToStream(kernelstream);
            using (FileStream INI1stream = HACGUIKeyset.TempINI1FileInfo.Create())
                pkg2.OpenIni1().CopyToStream(INI1stream);

            Ini1 INI1 = new Ini1(pkg2.OpenIni1());
            List <HashSearchEntry> hashes = new List <HashSearchEntry>();

            HACGUIKeyset.RootTempINI1FolderInfo.Create();
            foreach (Kip kip in INI1.Kips)
            {
                using (Stream rodatastream = new MemoryStream(kip.DecompressSection(1)))
                    switch (kip.Header.Name)
                    {
                    case "FS":
                        hashes.Add(new HashSearchEntry(
                                       NintendoKeys.KeyAreaKeyApplicationSourceHash,
                                       () => HACGUIKeyset.Keyset.KeyAreaKeyApplicationSource,
                                       0x10));
                        hashes.Add(new HashSearchEntry(
                                       NintendoKeys.KeyAreaKeyOceanSourceHash,
                                       () => HACGUIKeyset.Keyset.KeyAreaKeyOceanSource,
                                       0x10));
                        hashes.Add(new HashSearchEntry(
                                       NintendoKeys.KeyAreaKeySystemSourceHash,
                                       () => HACGUIKeyset.Keyset.KeyAreaKeySystemSource,
                                       0x10));
                        hashes.Add(new HashSearchEntry(
                                       NintendoKeys.HeaderKekSourceHash,
                                       () => HACGUIKeyset.Keyset.HeaderKekSource,
                                       0x10));
                        hashes.Add(new HashSearchEntry(
                                       NintendoKeys.SaveMacKekSourceHash,
                                       () => HACGUIKeyset.Keyset.SaveMacKekSource,
                                       0x10));
                        hashes.Add(new HashSearchEntry(
                                       NintendoKeys.SaveMacKeySourceHash,
                                       () => HACGUIKeyset.Keyset.SaveMacKeySource,
                                       0x10));

                        rodatastream.FindKeysViaHash(hashes, new SHA256Managed(), 0x10);

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

                        bool sdWarn = false;

                        hashes.Add(new HashSearchEntry(NintendoKeys.SDCardKekSourceHash, () => HACGUIKeyset.Keyset.SdCardKekSource,
                                                       0x10));
                        try
                        {
                            rodatastream.FindKeysViaHash(hashes, new SHA256Managed(), 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,
                                           () => HACGUIKeyset.Keyset.SdCardKeySources[0],
                                           0x20));
                            hashes.Add(new HashSearchEntry(
                                           NintendoKeys.SDCardNcaKeySourceHash,
                                           () => HACGUIKeyset.Keyset.SdCardKeySources[1],
                                           0x20));
                            rodatastream.FindKeysViaHash(hashes, new SHA256Managed(), 0x20);
                        }

                        hashes.Clear();

                        hashes.Add(new HashSearchEntry(
                                       NintendoKeys.HeaderKeySourceHash,
                                       () => HACGUIKeyset.Keyset.HeaderKeySource,
                                       0x20));

                        using (Stream datastream = new MemoryStream(kip.DecompressSection(2)))
                            datastream.FindKeysViaHash(hashes, new SHA256Managed(), 0x20);

                        hashes.Clear();

                        break;

                    case "spl":
                        hashes.Clear();

                        hashes.Add(new HashSearchEntry(
                                       NintendoKeys.AesKeyGenerationSourceHash,
                                       () => HACGUIKeyset.Keyset.AesKeyGenerationSource,
                                       0x10));

                        rodatastream.FindKeysViaHash(hashes, new SHA256Managed(), 0x10);
                        break;
                    }

                using (FileStream kipstream = HACGUIKeyset.RootTempINI1FolderInfo.GetFile(kip.Header.Name + ".kip").Create())
                    kip.OpenRawFile().CopyToStream(kipstream);
            }

            HACGUIKeyset.Keyset.DeriveKeys();

            SwitchFs fs = SwitchFs.OpenNandPartition(HACGUIKeyset.Keyset, nand.OpenSystemPartition());

            NintendoKeys.KekSeeds[1].XOR(NintendoKeys.KekMasks[0], out byte[] RsaPrivateKekGenerationSource);

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

            foreach (Nca nca in fs.Ncas.Values.Select(n => n.Nca))
            {
                ulong titleId = nca.Header.TitleId;

                if (!new ulong[] {      // check if title ID is one that needs to be processed before opening it
                    0x0100000000000033, // es
                    0x0100000000000024, // ssl
                }.Contains(titleId))
                {
                    continue;
                }

                // mainly to check if the NCA can be decrypted
                if (!nca.CanOpenSection(0))
                {
                    continue;
                }

                if (nca.Header.ContentType != NcaContentType.Program)
                {
                    continue;
                }

                IFileSystem pfs = nca.OpenFileSystem(NcaSectionType.Code, IntegrityCheckLevel.ErrorOnInvalid);
                pfs.OpenFile(out IFile nsoFile, "main".ToU8Span(), OpenMode.Read);
                Nso        nso     = new Nso(new FileStorage(nsoFile));
                NsoSection section = nso.Sections[1];
                Stream     data    = new MemoryStream(section.DecompressSection());
                byte[]     key1;
                byte[]     key2;
                switch (titleId)
                {
                case 0x0100000000000033:     // es
                    hashes.Clear();

                    byte[] EticketRsaKekSource   = new byte[0x10];
                    byte[] EticketRsaKekekSource = new byte[0x10];
                    hashes.Add(new HashSearchEntry(
                                   NintendoKeys.EticketRsaKekSourceHash,
                                   () => EticketRsaKekSource,
                                   0x10));
                    hashes.Add(new HashSearchEntry(
                                   NintendoKeys.EticketRsaKekekSourceHash,
                                   () => EticketRsaKekekSource,
                                   0x10));
                    data.FindKeysViaHash(hashes, new SHA256Managed(), 0x10, data.Length);

                    key1 = new byte[0x10];
                    new AesEcbDecryptor(HACGUIKeyset.Keyset.MasterKeys[0]).Transform(RsaOaepKekGenerationSource, key1);
                    key2 = new byte[0x10];
                    new AesEcbDecryptor(key1).Transform(EticketRsaKekekSource, key2);
                    new AesEcbDecryptor(key2).Transform(EticketRsaKekSource, HACGUIKeyset.Keyset.EticketRsaKek);
                    break;

                case 0x0100000000000024:     // ssl
                    hashes.Clear();

                    byte[] SslAesKeyX = new byte[0x10];
                    byte[] SslRsaKeyY = new byte[0x10];
                    hashes.Add(new HashSearchEntry(
                                   NintendoKeys.SslAesKeyXHash,
                                   () => SslAesKeyX,
                                   0x10));
                    hashes.Add(new HashSearchEntry(
                                   NintendoKeys.SslRsaKeyYHash,
                                   () => SslRsaKeyY,
                                   0x10));
                    data.FindKeysViaHash(hashes, new SHA256Managed(), 0x10, data.Length);

                    key1 = new byte[0x10];
                    new AesEcbDecryptor(HACGUIKeyset.Keyset.MasterKeys[0]).Transform(RsaPrivateKekGenerationSource, key1);
                    key2 = new byte[0x10];
                    new AesEcbDecryptor(key1).Transform(SslAesKeyX, key2);
                    new AesEcbDecryptor(key2).Transform(SslRsaKeyY, HACGUIKeyset.Keyset.SslRsaKek);
                    break;
                }
            }

            // save PRODINFO to file, then derive eticket_ext_key_rsa
            if (!TryDumpCert(nand: nand))
            {
                MessageBox.Show($"Failed to parse decrypted certificate. If you are using Incognito, select your PRODINFO backup now.");
                Dispatcher.Invoke(() => // dispatcher is required, otherwise a deadlock occurs. probably some threading issue
                {
                    while (true)
                    {
                        FileInfo info = RequestOpenFileFromUser(".bin", "PRODINFO backup (.bin)|*.bin", "Select a valid PRODINFO backup...", "PRODINFO.bin");
                        if (info != null)
                        {
                            if (TryDumpCert(info))
                            {
                                break;
                            }
                        }
                        else
                        {
                            MessageBox.Show("Failed to parse provided PRODINFO. You must have a valid PRODINFO backup.");
                        }
                    }
                });
            }

            // get tickets
            new DecryptTicketsTask(PickConsolePage.ConsoleName).CreateTask().RunSynchronously();

            FatFileSystemProvider system = NANDService.NAND.OpenSystemPartition();

            system.OpenFile(out IFile nsAppmanFile, "save\\8000000000000043".ToU8Span(), OpenMode.Read);
            IStorage           nsAppmanStorage = nsAppmanFile.AsStorage();
            SaveDataFileSystem nsAppmanSave    = new SaveDataFileSystem(HACGUIKeyset.Keyset, nsAppmanStorage, IntegrityCheckLevel.ErrorOnInvalid, false);

            nsAppmanSave.OpenFile(out IFile privateFile, "/private".ToU8Span(), OpenMode.Read);

            byte[] sdIdenitifer = new byte[0x10];
            byte[] sdSeed       = new byte[0x10];

            using (nsAppmanFile)
                using (nsAppmanSave)
                    using (privateFile)
                    {
                        IStorage privateStorage = privateFile.AsStorage();
                        privateStorage.Read(0, sdIdenitifer); // stored on SD and NAND, used to uniquely idenitfy the SD/NAND
                        privateStorage.Read(0x10, sdSeed);
                    }
            HACGUIKeyset.Keyset.SetSdSeed(sdSeed);
            Preferences.Current.SdIdentifiers[sdIdenitifer.ToHexString()] = sdSeed.ToHexString();

            NANDService.Stop();

            DirectoryInfo oldKeysDirectory = HACGUIKeyset.RootFolderInfo.GetDirectory("keys");

            if (oldKeysDirectory.Exists)
            {
                oldKeysDirectory.Delete(true); // fix old versions after restructure of directory
            }
            // write all keys to file
            new SaveKeysetTask(PickConsolePage.ConsoleName).CreateTask().RunSynchronously();

            Preferences.Current.DefaultConsoleName = PickConsolePage.ConsoleName;
            Preferences.Current.Write();
        }
Ejemplo n.º 14
0
 static void AllocModObj(Nso nso)
 {
     nso.RwdataSegment.BssOrAlign += 0x100;
     ModHeader.CreateModHeader(nso, nso.GetModAddr(), nso.ModSection.DynamicAddr, nso.ModSection.EhStartAddr, nso.ModSection.EhEndAddr, nso.ModSection.BssEndAddr);
 }
Ejemplo n.º 15
0
        private void OnNandFound()
        {
            Nand nand = NANDService.NAND;

            FileStream pkg2file = HACGUIKeyset.TempPkg2FileInfo.Create();
            IStorage   pkg2nand = nand.OpenPackage2(0);

            byte[] pkg2raw = new byte[0x7FC000];
            pkg2nand.Read(pkg2raw, 0x4000);
            MemoryStorage pkg2memory = new MemoryStorage(pkg2raw);

            pkg2memory.CopyToStream(pkg2file);

            Package2 pkg2 = new Package2(HACGUIKeyset.Keyset, pkg2memory);

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

            pkg2.OpenKernel().CopyToStream(kernelstream);
            pkg2.OpenIni1().CopyToStream(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().CopyToStream(kipstream);
                kipstream.Close();
            }

            pkg2file.Close();
            INI1stream.Close();

            HACGUIKeyset.Keyset.DeriveKeys();

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

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

                if (nca.CanOpenSection(0)) // mainly a check if the NCA can be decrypted
                {
                    switch (nca.Header.TitleId)
                    {
                    case 0x0100000000000033:     // es
                        switch (nca.Header.ContentType)
                        {
                        case ContentType.Program:
                            NcaSection          exefsSection = nca.Sections.FirstOrDefault(x => x?.Type == SectionType.Pfs0);
                            IStorage            pfsStorage   = nca.OpenSection(exefsSection.SectionNum, false, IntegrityCheckLevel.ErrorOnInvalid, false);
                            PartitionFileSystem pfs          = new PartitionFileSystem(pfsStorage);
                            Nso        nso     = new Nso(new FileStorage(pfs.OpenFile("main", OpenMode.Read)));
                            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);
                            Crypto.DecryptEcb(key2, EticketRsaKekSource, HACGUIKeyset.Keyset.EticketRsaKek, 0x10);
                            break;
                        }
                        break;

                    case 0x0100000000000024:     // ssl
                        switch (nca.Header.ContentType)
                        {
                        case ContentType.Program:
                            NcaSection          exefsSection = nca.Sections.FirstOrDefault(x => x?.Type == SectionType.Pfs0);
                            IStorage            pfsStorage   = nca.OpenSection(exefsSection.SectionNum, false, IntegrityCheckLevel.ErrorOnInvalid, false);
                            PartitionFileSystem pfs          = new PartitionFileSystem(pfsStorage);
                            Nso        nso     = new Nso(new FileStorage(pfs.OpenFile("main", OpenMode.Read)));
                            NsoSection section = nso.Sections[1];
                            Stream     data    = new MemoryStream(section.DecompressSection());
                            hashes.Clear();

                            hashes.Add(new HashSearchEntry(NintendoKeys.SslAesKeyXHash, 0x10));
                            hashes.Add(new HashSearchEntry(NintendoKeys.SslRsaKeyYHash, 0x10));
                            keys = data.FindKeyViaHash(hashes, new SHA256Managed(), 0x10, data.Length);
                            byte[] SslAesKeyX = new byte[0x10];
                            byte[] SslRsaKeyY = new byte[0x10];
                            Array.Copy(keys[NintendoKeys.SslAesKeyXHash], SslAesKeyX, 0x10);
                            Array.Copy(keys[NintendoKeys.SslRsaKeyYHash], SslRsaKeyY, 0x10);

                            byte[] RsaPrivateKekGenerationSource;
                            XOR(NintendoKeys.KekMasks[0], NintendoKeys.KekSeeds[1], out RsaPrivateKekGenerationSource);

                            byte[] key1 = new byte[0x10];
                            Crypto.DecryptEcb(HACGUIKeyset.Keyset.MasterKeys[0], RsaPrivateKekGenerationSource, key1, 0x10);
                            byte[] key2 = new byte[0x10];
                            Crypto.DecryptEcb(key1, SslAesKeyX, key2, 0x10);
                            Crypto.DecryptEcb(key2, SslRsaKeyY, HACGUIKeyset.Keyset.SslRsaKek, 0x10);
                            break;
                        }
                        break;
                    }
                }
            }

            // save PRODINFO to file, then derive eticket_ext_key_rsa
            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);

            // get client certificate
            prodinfo.Seek(0x0AD0, SeekOrigin.Begin);
            byte[] buffer;
            buffer = new byte[0x4];
            prodinfo.Read(buffer, 0, buffer.Length); // read cert length
            uint certLength = BitConverter.ToUInt32(buffer, 0);

            buffer = new byte[certLength];
            prodinfo.Seek(0x0AE0, SeekOrigin.Begin); // should be redundant?
            prodinfo.Read(buffer, 0, buffer.Length); // read actual cert

            byte[] counter = cal0.SslExtKey.Take(0x10).ToArray();
            byte[] key     = cal0.SslExtKey.Skip(0x10).ToArray();                               // bit strange structure but it works

            new Aes128CtrTransform(HACGUIKeyset.Keyset.SslRsaKek, counter).TransformBlock(key); // decrypt private key

            X509Certificate2 certificate = new X509Certificate2();

            certificate.Import(buffer);
            certificate.ImportPrivateKey(key);

            byte[] pfx       = certificate.Export(X509ContentType.Pkcs12, "switch");
            Stream pfxStream = HACGUIKeyset.GetClientCertificateByName(PickConsolePage.ConsoleName).Create();

            pfxStream.Write(pfx, 0, pfx.Length);
            pfxStream.Close();
            prodinfoFile.Close();

            // get tickets
            List <Ticket>         tickets    = new List <Ticket>();
            FatFileSystemProvider system     = nand.OpenSystemPartition();
            const string          e1FileName = "save\\80000000000000E1";
            const string          e2FileName = "save\\80000000000000E2";

            if (system.FileExists(e1FileName))
            {
                IFile    e1File    = system.OpenFile(e1FileName, OpenMode.Read);
                IStorage e1Storage = new FileStorage(e1File);
                tickets.AddRange(DumpTickets(HACGUIKeyset.Keyset, e1Storage, PickConsolePage.ConsoleName));
            }

            if (system.FileExists(e2FileName))
            {
                IFile    e2File    = system.OpenFile(e2FileName, OpenMode.Read);
                IStorage e2Storage = new FileStorage(e2File);
                tickets.AddRange(DumpTickets(HACGUIKeyset.Keyset, e2Storage, PickConsolePage.ConsoleName));
            }

            IStorage           nsAppmanStorage = new FileStorage(system.OpenFile("save\\8000000000000043", OpenMode.Read));
            SaveDataFileSystem save            = new SaveDataFileSystem(HACGUIKeyset.Keyset, nsAppmanStorage, IntegrityCheckLevel.ErrorOnInvalid, false);
            IStorage           privateStorage  = new FileStorage(save.OpenFile("/private", OpenMode.Read));

            byte[] sdSeed = new byte[0x10];
            privateStorage.Read(sdSeed, 0x10);
            HACGUIKeyset.Keyset.SetSdSeed(sdSeed);

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

            NANDService.Stop();

            DirectoryInfo oldKeysDirectory = HACGUIKeyset.RootFolderInfo.GetDirectory("keys");

            if (oldKeysDirectory.Exists)
            {
                oldKeysDirectory.Delete(true); // fix old versions after restructure of directory
            }

            // write all keys to file
            new SaveKeysetTask(PickConsolePage.ConsoleName).CreateTask().RunSynchronously();

            Preferences.Current.DefaultConsoleName = PickConsolePage.ConsoleName;
            Preferences.Current.Write();
        }