private static void VerifyFileHash(IProgressReporter progressReporter, IFile file, int bufferSize, IReadOnlyCollection <byte> expectedNcaHash, CancellationToken cancellationToken, out bool hashValid)
        {
            if (file.GetSize(out var fileSize) != Result.Success)
            {
                fileSize = 0;
            }

            var sha256 = SHA256.Create();

            var ncaStream = file.AsStream();
            var buffer    = new byte[bufferSize];

            decimal totalRead = 0;
            int     read;

            while ((read = ncaStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                cancellationToken.ThrowIfCancellationRequested();

                sha256.TransformBlock(buffer, 0, read, null, 0);
                totalRead += read;
                progressReporter.SetPercentage(fileSize == 0 ? 0.0 : (double)(totalRead / fileSize));
            }

            sha256.TransformFinalBlock(Array.Empty <byte>(), 0, 0);
            var currentNcaHash = sha256.Hash !;

            hashValid = IsHashEqual(currentNcaHash, expectedNcaHash);
        }
Esempio n. 2
0
        public static void ExtractRomFS(string inFile, string outDirPath, Keyset keyset, Output Out)
        {
            using (var file = new FileStream(inFile, FileMode.Open, FileAccess.Read))
            {
                var         pfs        = new PartitionFileSystem(file.AsStorage());
                var         OutDirFs   = new LocalFileSystem(outDirPath);
                IDirectory  sourceRoot = pfs.OpenDirectory("/", OpenDirectoryMode.All);
                IFileSystem sourceFs   = sourceRoot.ParentFileSystem;
                Out.Log(pfs.Print());

                foreach (var entry in FileIterator(sourceRoot))
                {
                    if (entry.Name.EndsWith(".nca"))
                    {
                        var fullOutDirPath = $"{outDirPath}/{entry.Name}";
                        Out.Log($"Extracting {entry.Name}...\r\n");
                        using (IFile srcFile = sourceFs.OpenFile(entry.Name, OpenMode.Read))
                        {
                            ProcessNca.Extract(srcFile.AsStream(), fullOutDirPath, true, keyset, Out);
                        }
                    }
                    else if (entry.Name.EndsWith(".nca.nsz"))
                    {
                        var fullOutDirPath = $"{outDirPath}/{entry.Name}";
                        Out.Log($"Extracting {entry.Name}...\r\n");
                        using (IFile srcFile = sourceFs.OpenFile(entry.Name, OpenMode.Read))
                            using (var decompressedFile = new DecompressionStorage(srcFile))
                            {
                                ProcessNca.Extract(decompressedFile.AsStream(), fullOutDirPath, true, keyset, Out, true);

                                // Header can't be patched for now due to OpenSection
                                // and ValidateMasterHash needs to know if AesCtrEx
                                // so Nca.cs was patched and now accepts isDecryptedNca
                                // as constructor argument which disables decryption

                                /*
                                 * var DecryptedHeader = new byte[0xC00];
                                 * decompressedFile.AsStream().Read(DecryptedHeader, 0, 0xC00);
                                 * DecryptedHeader[1028] = (int)NcaEncryptionType.None;
                                 * DecryptedHeader[1540] = (int)NcaEncryptionType.None;
                                 * DecryptedHeader[2052] = (int)NcaEncryptionType.None;
                                 * DecryptedHeader[2564] = (int)NcaEncryptionType.None;
                                 * var HeaderKey1 = new byte[16];
                                 * var HeaderKey2 = new byte[16];
                                 * Buffer.BlockCopy(keyset.HeaderKey, 0, HeaderKey1, 0, 16);
                                 * Buffer.BlockCopy(keyset.HeaderKey, 16, HeaderKey2, 0, 16);
                                 * var headerEncrypted = CryptoInitialisers.AES_XTS(HeaderKey1, HeaderKey2, 0x200, DecryptedHeader, 0);
                                 * var ncaStorageList = new List<IStorage>() { new MemoryStorage(headerEncrypted), decompressedFile.Slice(0xC00) };
                                 * var cleanDecryptedNca = new ConcatenationStorage(ncaStorageList, true);
                                 * ProcessNca.Extract(cleanDecryptedNca.AsStream(), fullOutDirPath, true, keyset, Out);
                                 */
                            }
                    }
                }
            }
        }
Esempio n. 3
0
        public void ReadControlData(Nca controlNca)
        {
            IFileSystem controlFs = controlNca.OpenFileSystem(NcaSectionType.Data, FsIntegrityCheckLevel);

            IFile controlFile = controlFs.OpenFile("/control.nacp", OpenMode.Read);

            ControlData = new Nacp(controlFile.AsStream());

            TitleName = CurrentTitle = ControlData.Descriptions[(int)State.DesiredTitleLanguage].Title;
        }
Esempio n. 4
0
 public BdatFile(IFile bdat, string fileName)
 {
     using (var reader = new BinaryReader(bdat.AsStream()))
     {
         var tableCount = reader.ReadInt32();
         var fileLength = reader.ReadInt32();
         for (int i = 0; i < tableCount; i++)
         {
             reader.BaseStream.Position = 8 + (4 * i);
             reader.BaseStream.Position = reader.ReadInt32();
             Tables.Add(new BdatTable(reader, fileName));
         }
     }
 }
Esempio n. 5
0
        private void ReadTitles()
        {
            foreach (SwitchFsNca nca in Ncas.Values.Where(x => x.Nca.Header.ContentType == ContentType.Meta))
            {
                try
                {
                    var title = new Title();

                    IFileSystem fs       = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
                    string      cnmtPath = fs.EnumerateEntries("*.cnmt").Single().FullPath;

                    IFile file = fs.OpenFile(cnmtPath, OpenMode.Read);

                    var metadata = new Cnmt(file.AsStream());
                    title.Id       = metadata.TitleId;
                    title.Version  = metadata.TitleVersion;
                    title.Metadata = metadata;
                    title.MetaNca  = nca;
                    title.Ncas.Add(nca);

                    foreach (CnmtContentEntry content in metadata.ContentEntries)
                    {
                        string ncaId = content.NcaId.ToHexString();

                        if (Ncas.TryGetValue(ncaId, out SwitchFsNca contentNca))
                        {
                            title.Ncas.Add(contentNca);
                        }

                        switch (content.Type)
                        {
                        case CnmtContentType.Program:
                        case CnmtContentType.Data:
                            title.MainNca = contentNca;
                            break;

                        case CnmtContentType.Control:
                            title.ControlNca = contentNca;
                            break;
                        }
                    }

                    Titles[title.Id] = title;
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"{ex.Message} File: {nca.Filename}");
                }
            }
        }
Esempio n. 6
0
        private static Ticket[] GetTickets(Keyset keyset, Nand nand, IProgressReport logger = null)
        {
            var tickets = new List <Ticket>();
            FatFileSystemProvider system = nand.OpenSystemPartition();

            IFile saveE1File = system.OpenFile("/save/80000000000000E1", OpenMode.Read);

            tickets.AddRange(ReadTickets(keyset, saveE1File.AsStream()));

            IFile saveE2 = system.OpenFile("/save/80000000000000E2", OpenMode.Read);

            tickets.AddRange(ReadTickets(keyset, saveE2.AsStream()));

            logger?.LogMessage($"Found {tickets.Count} tickets");

            return(tickets.ToArray());
        }
Esempio n. 7
0
        private void ReadTitles()
        {
            foreach (Nca nca in Ncas.Values.Where(x => x.Header.ContentType == ContentType.Meta))
            {
                var title = new Title();

                // Meta contents always have 1 Partition FS section with 1 file in it
                IStorage sect = nca.OpenSection(0, false, IntegrityCheckLevel.ErrorOnInvalid, true);
                var      pfs0 = new PartitionFileSystem(sect);
                IFile    file = pfs0.OpenFile(pfs0.Files[0], OpenMode.Read);

                var metadata = new Cnmt(file.AsStream());
                title.Id       = metadata.TitleId;
                title.Version  = metadata.TitleVersion;
                title.Metadata = metadata;
                title.MetaNca  = nca;
                title.Ncas.Add(nca);

                foreach (CnmtContentEntry content in metadata.ContentEntries)
                {
                    string ncaId = content.NcaId.ToHexString();

                    if (Ncas.TryGetValue(ncaId, out Nca contentNca))
                    {
                        title.Ncas.Add(contentNca);
                    }

                    switch (content.Type)
                    {
                    case CnmtContentType.Program:
                    case CnmtContentType.Data:
                        title.MainNca = contentNca;
                        break;

                    case CnmtContentType.Control:
                        title.ControlNca = contentNca;
                        break;
                    }
                }

                Titles[title.Id] = title;
            }
        }
Esempio n. 8
0
        private void ReadControls()
        {
            foreach (Title title in Titles.Values.Where(x => x.ControlNca != null))
            {
                var   romfs   = new RomFsFileSystem(title.ControlNca.OpenSection(0, false, IntegrityCheckLevel.ErrorOnInvalid, true));
                IFile control = romfs.OpenFile("control.nacp", OpenMode.Read);

                title.Control = new Nacp(control.AsStream());

                foreach (NacpDescription desc in title.Control.Descriptions)
                {
                    if (!string.IsNullOrWhiteSpace(desc.Title))
                    {
                        title.Name = desc.Title;
                        break;
                    }
                }
            }
        }
Esempio n. 9
0
        private static Validity VerifySignature2(this Nca nca)
        {
            if (nca.Header.ContentType != ContentType.Program)
            {
                return(Validity.Unchecked);
            }

            IFileSystem pfs = nca.OpenFileSystem(NcaSectionType.Code, IntegrityCheckLevel.ErrorOnInvalid);

            if (!pfs.FileExists("main.npdm"))
            {
                return(Validity.Unchecked);
            }

            IFile npdmStorage = pfs.OpenFile("main.npdm", OpenMode.Read);
            var   npdm        = new NpdmBinary(npdmStorage.AsStream());

            return(nca.Header.VerifySignature2(npdm.AciD.Rsa2048Modulus));
        }
Esempio n. 10
0
 public static void Encrypt(IFileSystem sourceFs, IFileSystem destFs, bool verifyEncrypted, Keyset keyset,
                            Output Out)
 {
     foreach (var decryptedNcaEntry in sourceFs.EnumerateEntries().Where(item => item.Name.EndsWith(".nca")))
     {
         Out.Log($"Input: {decryptedNcaEntry.Name}\r\n");
         using (var decryptedNca = sourceFs.OpenFile(decryptedNcaEntry.FullPath, OpenMode.Read))
         {
             if (destFs != null)
             {
                 Out.Log("Opened NCA for writing...\r\n");
                 using (IFile outputFile = FolderTools.CreateAndOpen(decryptedNcaEntry, destFs, decryptedNcaEntry.Name, decryptedNca.GetSize()))
                 {
                     EncryptFunct(decryptedNca.AsStream(), outputFile.AsStream(), decryptedNcaEntry.Name, verifyEncrypted, keyset, Out);
                 }
             }
             else
             {
                 EncryptFunct(decryptedNca.AsStream(), null, decryptedNcaEntry.Name, verifyEncrypted, keyset, Out);
             }
         }
     }
 }
Esempio n. 11
0
 public static void Process(IFile inFile, IFile outFile, bool verifyBeforeDecrypting, Keyset keyset, Output Out)
 {
     using (var file = new StreamStorage(inFile.AsStream(), false))
     {
         var nca = new Nca(keyset, file, false);
         Out.Log(nca.Print());
         if (verifyBeforeDecrypting)
         {
             Out.Log($"ValidateMasterHashes...\r\n");
             nca.ValidateMasterHashes();
             //nca.ParseNpdm();
             for (var i = 0; i < 3; ++i)
             {
                 if (nca.Sections[i] != null)
                 {
                     nca.VerifySection(i, Out);
                 }
             }
         }
         Out.Log($"Decripting...\r\n");
         nca.OpenDecryptedNca().CopyToStream(outFile.AsStream());
     }
 }
Esempio n. 12
0
        public DecompressionStorage(IFile inputFile)
        {
            var inputFileStream     = inputFile.AsStream();
            var nsZipMagic          = new byte[] { 0x6e, 0x73, 0x5a, 0x69, 0x70 };
            var nsZipMagicEncrypted = new byte[5];

            inputFileStream.Read(nsZipMagicEncrypted, 0, 5);
            var nsZipMagicRandomKey = new byte[5];

            inputFileStream.Read(nsZipMagicRandomKey, 0, 5);
            Util.XorArrays(nsZipMagicEncrypted, nsZipMagicRandomKey);
            if (!Util.ArraysEqual(nsZipMagicEncrypted, nsZipMagic))
            {
                throw new InvalidDataException($"Invalid nsZip magic!\r\n");
            }

            var version = inputFileStream.ReadByte();
            var type    = inputFileStream.ReadByte();
            var bsArray = new byte[5];

            inputFileStream.Read(bsArray, 0, 5);
            long bsReal = (bsArray[0] << 32)
                          + (bsArray[1] << 24)
                          + (bsArray[2] << 16)
                          + (bsArray[3] << 8)
                          + bsArray[4];

            if (bsReal > int.MaxValue)
            {
                throw new NotImplementedException("Block sizes above 2 GB aren't supported yet!");
            }

            bs = (int)bsReal;
            var amountOfBlocksArray = new byte[4];

            inputFileStream.Read(amountOfBlocksArray, 0, 4);
            amountOfBlocks = (amountOfBlocksArray[0] << 24)
                             + (amountOfBlocksArray[1] << 16)
                             + (amountOfBlocksArray[2] << 8)
                             + amountOfBlocksArray[3];
            var sizeOfSize         = (int)Math.Ceiling(Math.Log(bs, 2) / 8);
            var perBlockHeaderSize = sizeOfSize + 1;

            decompressBuff       = new byte[bs];
            compressionAlgorithm = new int[amountOfBlocks];
            var  compressedBlockSize   = new int[amountOfBlocks];
            var  compressedBlockOffset = new long[amountOfBlocks];
            long currentOffset         = 0;

            for (var currentBlockID = 0; currentBlockID < amountOfBlocks; ++currentBlockID)
            {
                compressedBlockOffset[currentBlockID] = currentOffset;
                compressionAlgorithm[currentBlockID]  = inputFileStream.ReadByte();
                compressedBlockSize[currentBlockID]   = 0;
                for (var j = 0; j < sizeOfSize; ++j)
                {
                    compressedBlockSize[currentBlockID] += inputFileStream.ReadByte() << ((sizeOfSize - j - 1) * 8);
                }

                currentOffset += compressedBlockSize[currentBlockID];
            }

            compressedBlocks = new IStorage[amountOfBlocks];
            var compressedData = new FileStorage(inputFile).Slice(inputFileStream.Position);

            for (int i = 0; i < amountOfBlocks; ++i)
            {
                compressedBlocks[i] = compressedData.Slice(compressedBlockOffset[i], compressedBlockSize[i]);
            }

            // Cast to long is VERY important or files larger than 2 GB will have a negative size!
            lastBlockSize = getSizeOfLastBlock();
            length        = ((long)(amountOfBlocks - 1) * bs) + lastBlockSize;
            Console.WriteLine($"length={length} lastBlockSize={lastBlockSize}");
        }
Esempio n. 13
0
        public static void Init(List <string> AppDirs, Keyset keySet, SystemState.TitleLanguage desiredTitleLanguage)
        {
            KeySet = keySet;
            DesiredTitleLanguage = desiredTitleLanguage;

            // Loads the default application Icons
            RyujinxNspIcon = GetResourceBytes("Ryujinx.Ui.assets.ryujinxNSPIcon.png");
            RyujinxXciIcon = GetResourceBytes("Ryujinx.Ui.assets.ryujinxXCIIcon.png");
            RyujinxNcaIcon = GetResourceBytes("Ryujinx.Ui.assets.ryujinxNCAIcon.png");
            RyujinxNroIcon = GetResourceBytes("Ryujinx.Ui.assets.ryujinxNROIcon.png");
            RyujinxNsoIcon = GetResourceBytes("Ryujinx.Ui.assets.ryujinxNSOIcon.png");

            // Builds the applications list with paths to found applications
            List <string> applications = new List <string>();

            foreach (string appDir in AppDirs)
            {
                if (Directory.Exists(appDir) == false)
                {
                    Logger.PrintWarning(LogClass.Application, $"The \"game_dirs\" section in \"Config.json\" contains an invalid directory: \"{appDir}\"");

                    continue;
                }

                DirectoryInfo AppDirInfo = new DirectoryInfo(appDir);
                foreach (FileInfo App in AppDirInfo.GetFiles())
                {
                    if ((Path.GetExtension(App.ToString()) == ".xci") ||
                        (Path.GetExtension(App.ToString()) == ".nca") ||
                        (Path.GetExtension(App.ToString()) == ".nsp") ||
                        (Path.GetExtension(App.ToString()) == ".pfs0") ||
                        (Path.GetExtension(App.ToString()) == ".nro") ||
                        (Path.GetExtension(App.ToString()) == ".nso"))
                    {
                        applications.Add(App.ToString());
                    }
                }
            }

            // Loops through applications list, creating a struct for each application and then adding the struct to a list of structs
            ApplicationLibraryData = new List <ApplicationData>();
            foreach (string applicationPath in applications)
            {
                double filesize        = new FileInfo(applicationPath).Length * 0.000000000931;
                string titleName       = null;
                string titleId         = null;
                string developer       = null;
                string version         = null;
                byte[] applicationIcon = null;

                using (FileStream file = new FileStream(applicationPath, FileMode.Open, FileAccess.Read))
                {
                    if ((Path.GetExtension(applicationPath) == ".nsp") ||
                        (Path.GetExtension(applicationPath) == ".pfs0") ||
                        (Path.GetExtension(applicationPath) == ".xci"))
                    {
                        try
                        {
                            IFileSystem controlFs = null;

                            // Store the ControlFS in variable called controlFs
                            if (Path.GetExtension(applicationPath) == ".xci")
                            {
                                Xci xci = new Xci(KeySet, file.AsStorage());

                                controlFs = GetControlFs(xci.OpenPartition(XciPartitionType.Secure));
                            }
                            else
                            {
                                controlFs = GetControlFs(new PartitionFileSystem(file.AsStorage()));
                            }

                            // Creates NACP class from the NACP file
                            IFile controlNacp = controlFs.OpenFile("/control.nacp", OpenMode.Read);
                            Nacp  controlData = new Nacp(controlNacp.AsStream());

                            // Get the title name, title ID, developer name and version number from the NACP
                            version = controlData.DisplayVersion;

                            titleName = controlData.Descriptions[(int)DesiredTitleLanguage].Title;

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

                            titleId = controlData.PresenceGroupId.ToString("x16");

                            if (string.IsNullOrWhiteSpace(titleId))
                            {
                                titleId = controlData.SaveDataOwnerId.ToString("x16");
                            }

                            if (string.IsNullOrWhiteSpace(titleId))
                            {
                                titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16");
                            }

                            developer = controlData.Descriptions[(int)DesiredTitleLanguage].Developer;

                            if (string.IsNullOrWhiteSpace(developer))
                            {
                                developer = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Developer)).Developer;
                            }

                            // Read the icon from the ControlFS and store it as a byte array
                            try
                            {
                                IFile icon = controlFs.OpenFile($"/icon_{DesiredTitleLanguage}.dat", OpenMode.Read);
                                using (MemoryStream stream = new MemoryStream())
                                {
                                    icon.AsStream().CopyTo(stream);
                                    applicationIcon = stream.ToArray();
                                }
                            }
                            catch (HorizonResultException)
                            {
                                IDirectory controlDir = controlFs.OpenDirectory("./", OpenDirectoryMode.All);
                                foreach (DirectoryEntry entry in controlDir.Read())
                                {
                                    if (entry.Name == "control.nacp")
                                    {
                                        continue;
                                    }

                                    IFile icon = controlFs.OpenFile(entry.FullPath, OpenMode.Read);
                                    using (MemoryStream stream = new MemoryStream())
                                    {
                                        icon.AsStream().CopyTo(stream);
                                        applicationIcon = stream.ToArray();
                                    }

                                    if (applicationIcon != null)
                                    {
                                        break;
                                    }
                                }

                                if (applicationIcon == null)
                                {
                                    applicationIcon = NspOrXciIcon(applicationPath);
                                }
                            }
                        }
                        catch (MissingKeyException exception)
                        {
                            titleName       = "Unknown";
                            titleId         = "Unknown";
                            developer       = "Unknown";
                            version         = "?";
                            applicationIcon = NspOrXciIcon(applicationPath);

                            Logger.PrintWarning(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}");
                        }
                        catch (InvalidDataException)
                        {
                            titleName       = "Unknown";
                            titleId         = "Unknown";
                            developer       = "Unknown";
                            version         = "?";
                            applicationIcon = NspOrXciIcon(applicationPath);

                            Logger.PrintWarning(LogClass.Application, $"The file is not an NCA file or the header key is incorrect. Errored File: {applicationPath}");
                        }
                        catch (Exception exception)
                        {
                            Logger.PrintWarning(LogClass.Application, $"This warning usualy means that you have a DLC in one of you game directories\n{exception}");

                            continue;
                        }
                    }
                    else if (Path.GetExtension(applicationPath) == ".nro")
                    {
                        BinaryReader reader = new BinaryReader(file);

                        byte[] Read(long Position, int Size)
                        {
                            file.Seek(Position, SeekOrigin.Begin);

                            return(reader.ReadBytes(Size));
                        }

                        file.Seek(24, SeekOrigin.Begin);
                        int AssetOffset = reader.ReadInt32();

                        if (Encoding.ASCII.GetString(Read(AssetOffset, 4)) == "ASET")
                        {
                            byte[] IconSectionInfo = Read(AssetOffset + 8, 0x10);

                            long iconOffset = BitConverter.ToInt64(IconSectionInfo, 0);
                            long iconSize   = BitConverter.ToInt64(IconSectionInfo, 8);

                            ulong nacpOffset = reader.ReadUInt64();
                            ulong nacpSize   = reader.ReadUInt64();

                            // Reads and stores game icon as byte array
                            applicationIcon = Read(AssetOffset + iconOffset, (int)iconSize);

                            // Creates memory stream out of byte array which is the NACP
                            using (MemoryStream stream = new MemoryStream(Read(AssetOffset + (int)nacpOffset, (int)nacpSize)))
                            {
                                // Creates NACP class from the memory stream
                                Nacp controlData = new Nacp(stream);

                                // Get the title name, title ID, developer name and version number from the NACP
                                version = controlData.DisplayVersion;

                                titleName = controlData.Descriptions[(int)DesiredTitleLanguage].Title;

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

                                titleId = controlData.PresenceGroupId.ToString("x16");

                                if (string.IsNullOrWhiteSpace(titleId))
                                {
                                    titleId = controlData.SaveDataOwnerId.ToString("x16");
                                }

                                if (string.IsNullOrWhiteSpace(titleId))
                                {
                                    titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16");
                                }

                                developer = controlData.Descriptions[(int)DesiredTitleLanguage].Developer;

                                if (string.IsNullOrWhiteSpace(developer))
                                {
                                    developer = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Developer)).Developer;
                                }
                            }
                        }
                        else
                        {
                            applicationIcon = RyujinxNroIcon;
                            titleName       = "Application";
                            titleId         = "0000000000000000";
                            developer       = "Unknown";
                            version         = "?";
                        }
                    }
                    // If its an NCA or NSO we just set defaults
                    else if ((Path.GetExtension(applicationPath) == ".nca") || (Path.GetExtension(applicationPath) == ".nso"))
                    {
                        if (Path.GetExtension(applicationPath) == ".nca")
                        {
                            applicationIcon = RyujinxNcaIcon;
                        }
                        else if (Path.GetExtension(applicationPath) == ".nso")
                        {
                            applicationIcon = RyujinxNsoIcon;
                        }

                        string fileName = Path.GetFileName(applicationPath);
                        string fileExt  = Path.GetExtension(applicationPath);

                        StringBuilder titlename = new StringBuilder();
                        titlename.Append(fileName);
                        titlename.Remove(fileName.Length - fileExt.Length, fileExt.Length);

                        titleName = titlename.ToString();
                        titleId   = "0000000000000000";
                        version   = "?";
                        developer = "Unknown";
                    }
                }

                string[] playedData = GetPlayedData(titleId, "00000000000000000000000000000001");

                ApplicationData data = new ApplicationData()
                {
                    Icon       = applicationIcon,
                    TitleName  = titleName,
                    TitleId    = titleId,
                    Developer  = developer,
                    Version    = version,
                    TimePlayed = playedData[0],
                    LastPlayed = playedData[1],
                    FileExt    = Path.GetExtension(applicationPath).ToUpper().Remove(0, 1),
                    FileSize   = (filesize < 1) ? (filesize * 1024).ToString("0.##") + "MB" : filesize.ToString("0.##") + "GB",
                    Path       = applicationPath,
                };

                ApplicationLibraryData.Add(data);
            }
        }
Esempio n. 14
0
        static void Main(string[] args)
        {
            Console.Title = "XCIRepacker v0.1 by Ac_K";

            Console.WriteLine(Environment.NewLine +
                              " XCIRepacker v0.1 by Ac_K" +
                              Environment.NewLine +
                              Environment.NewLine +
                              " Provide with the courtesy of the mob." +
                              Environment.NewLine +
                              Environment.NewLine +
                              "---------------------------------------" +
                              Environment.NewLine);

            if (args.Length == 1)
            {
                Keyset keySet = OpenKeyset();

                if (keySet != null)
                {
                    if (File.Exists(args[0]))
                    {
                        try
                        {
                            Xci xciFile = new Xci(keySet, new LocalStorage(args[0], FileAccess.Read));

                            if (xciFile.HasPartition(XciPartitionType.Secure))
                            {
                                XciPartition xciPartition = xciFile.OpenPartition(XciPartitionType.Root);

                                IFile ncaStorage = xciPartition.OpenFile("secure", OpenMode.Read);

                                string outputPath = Path.GetDirectoryName(args[0]) + Path.GetFileNameWithoutExtension(args[0]) + ".nsp";

                                Console.WriteLine($" Input  File Path: {args[0]}");
                                Console.WriteLine($" Output File Path: {outputPath}" + Environment.NewLine);

                                using (Stream dataInput = ncaStorage.AsStream())
                                    using (FileStream fileOutput = new FileStream(outputPath, FileMode.Create, FileAccess.ReadWrite))
                                        using (BinaryReader reader = new BinaryReader(fileOutput))
                                            using (BinaryWriter writer = new BinaryWriter(fileOutput))
                                            {
                                                int  bytesRead  = -1;
                                                long totalReads = 0;
                                                long totalBytes = dataInput.Length;

                                                byte[] bytes = new byte[_bufferSize];

                                                Console.WriteLine(" Extracting Secure partition..." + Environment.NewLine);

                                                while ((bytesRead = dataInput.Read(bytes, 0, _bufferSize)) > 0)
                                                {
                                                    fileOutput.Write(bytes, 0, bytesRead);
                                                    totalReads += bytesRead;

                                                    DrawTextProgressBar(totalReads, totalBytes);
                                                }

                                                Console.WriteLine(Environment.NewLine +
                                                                  Environment.NewLine +
                                                                  " Secure partition extracted!" +
                                                                  Environment.NewLine +
                                                                  Environment.NewLine +
                                                                  "---------------------------------------" +
                                                                  Environment.NewLine);

                                                Console.Write(" Patching HFS0 Header to PFS0...");

                                                fileOutput.Position = 0;

                                                string Magic = Encoding.ASCII.GetString(reader.ReadBytes(0x04));

                                                if (Magic == "HFS0")
                                                {
                                                    fileOutput.Seek(0x00, SeekOrigin.Begin);

                                                    writer.Write(new byte[] { 0x50, 0x46, 0x53, 0x30 }); // PFS0

                                                    int filesNumber    = reader.ReadInt32();             // Skip write files number because is at same offset
                                                    int filesNamesSize = reader.ReadInt32();

                                                    reader.ReadInt32(); // Skip reserved

                                                    long HFS0HeaderSize = filesNamesSize + 0x10;

                                                    for (int i = 0; i < filesNumber; i++)
                                                    {
                                                        fileOutput.Seek((i * 0x40) + 0x10, SeekOrigin.Begin);

                                                        long fileOffset     = reader.ReadInt64();
                                                        long fileSize       = reader.ReadInt64();
                                                        int  fileNameOffset = reader.ReadInt32();
                                                        int  hashedSize     = reader.ReadInt32();

                                                        reader.ReadInt64(); // reserved

                                                        reader.ReadBytes(0x20);

                                                        HFS0HeaderSize += 0x40;

                                                        fileOutput.Seek((i * 0x18) + 0x10, SeekOrigin.Begin);

                                                        writer.Write(fileOffset);
                                                        writer.Write(fileSize);
                                                        writer.Write(fileNameOffset);
                                                        writer.Write(0x00); // reserved
                                                    }

                                                    long endPatchedHeader = fileOutput.Position;

                                                    fileOutput.Seek((4 * 0x40) + 0x10, SeekOrigin.Begin);

                                                    byte[] filesNamesTable = reader.ReadBytes(filesNamesSize);

                                                    fileOutput.Seek(endPatchedHeader, SeekOrigin.Begin);

                                                    writer.Write(filesNamesTable);

                                                    int shiftSize = (int)(HFS0HeaderSize - fileOutput.Position);

                                                    writer.Write(new byte[shiftSize]);

                                                    fileOutput.Seek(0x08, SeekOrigin.Begin);

                                                    writer.Write(filesNamesSize + shiftSize);

                                                    Console.WriteLine(" Done!");
                                                }
                                                else
                                                {
                                                    Console.WriteLine(" ERROR: Extracted file isn't HFS0!");
                                                }
                                            }
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine($" ERROR: {ex.Message}");
                        }
                    }
                    else
                    {
                        Console.WriteLine(" ERROR: XCI file not found!");
                    }
                }
                else
                {
                    Console.WriteLine(" ERROR: Keys file not found!");
                }
            }
            else
            {
                Console.WriteLine(" USAGE: XCIRepacker.exe \"PathOfFile.xci\"");
            }

            Console.ReadKey();
        }
Esempio n. 15
0
        public void LoadNca(Nca mainNca, Nca patchNca, Nca controlNca)
        {
            if (mainNca.Header.ContentType != ContentType.Program)
            {
                Logger.PrintError(LogClass.Loader, "Selected NCA is not a \"Program\" NCA");

                return;
            }

            IStorage    dataStorage = null;
            IFileSystem codeFs      = null;

            if (patchNca == null)
            {
                if (mainNca.CanOpenSection(NcaSectionType.Data))
                {
                    dataStorage = mainNca.OpenStorage(NcaSectionType.Data, FsIntegrityCheckLevel);
                }

                if (mainNca.CanOpenSection(NcaSectionType.Code))
                {
                    codeFs = mainNca.OpenFileSystem(NcaSectionType.Code, FsIntegrityCheckLevel);
                }
            }
            else
            {
                if (patchNca.CanOpenSection(NcaSectionType.Data))
                {
                    dataStorage = mainNca.OpenStorageWithPatch(patchNca, NcaSectionType.Data, FsIntegrityCheckLevel);
                }

                if (patchNca.CanOpenSection(NcaSectionType.Code))
                {
                    codeFs = mainNca.OpenFileSystemWithPatch(patchNca, NcaSectionType.Code, FsIntegrityCheckLevel);
                }
            }

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

                return;
            }

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

            LoadExeFs(codeFs, out Npdm metaData);

            Nacp ReadControlData()
            {
                IFileSystem controlRomfs = controlNca.OpenFileSystem(NcaSectionType.Data, FsIntegrityCheckLevel);

                IFile controlFile = controlRomfs.OpenFile("/control.nacp", OpenMode.Read);

                Nacp controlData = new Nacp(controlFile.AsStream());

                TitleName = CurrentTitle = controlData.Descriptions[(int)State.DesiredTitleLanguage].Title;
                TitleID   = metaData.Aci0.TitleId.ToString("x16");

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

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

                return(controlData);
            }

            if (controlNca != null)
            {
                ReadControlData();
            }
            else
            {
                TitleID = CurrentTitle = metaData.Aci0.TitleId.ToString("x16");
            }
        }
Esempio n. 16
0
        private void ImportGameDataClicked(object sender, RoutedEventArgs arg)
        {
            string filter = @"
                Any game data (*.xci,*.nca,*.nsp)|*.xci;*.nca;*.nsp|
                NX Card Image (*.xci)|*.xci|
                Nintendo Content Archive (*.nca)|*.nca|
                Nintendo Installable Package (*.nsp)|*.nsp
            ".FilterMultilineString();

            FileInfo[] files = RequestOpenFilesFromUser(".*", filter, "Select game data...");

            if (files == null)
            {
                return;
            }

            TaskManagerPage.Current.Queue.Submit(new RunTask("Processing imported game data...", new Task(() =>
            {
                IEnumerable <FileInfo> ncas = files.Where((f) =>
                {
                    try
                    {
                        new Nca(HACGUIKeyset.Keyset, new LocalFile(f.FullName, OpenMode.Read).AsStorage());
                        return(true);
                    }
                    catch (Exception)
                    {
                        return(false);
                    }
                });
                IEnumerable <FileInfo> xcis = files.Except(ncas).Where((f) =>
                {
                    try
                    {
                        new Xci(HACGUIKeyset.Keyset, new LocalFile(f.FullName, OpenMode.Read).AsStorage());
                        return(true);
                    }
                    catch (Exception)
                    {
                        return(false);
                    }
                });
                IEnumerable <FileInfo> nsp = files.Except(ncas).Except(xcis).Where((f) =>
                {
                    try
                    {
                        new PartitionFileSystem(new LocalFile(f.FullName, OpenMode.Read).AsStorage());
                        return(true);
                    }
                    catch (Exception)
                    {
                        return(false);
                    }
                });

                List <SwitchFs> switchFilesystems = new List <SwitchFs>();
                if (ncas.Any())
                {
                    switchFilesystems.Add(SwitchFs.OpenNcaDirectory(HACGUIKeyset.Keyset, ncas.MakeFs()));
                }

                foreach (FileInfo file in xcis)
                {
                    Xci xci = new Xci(HACGUIKeyset.Keyset, new LocalFile(file.FullName, OpenMode.Read).AsStorage());
                    switchFilesystems.Add(SwitchFs.OpenNcaDirectory(HACGUIKeyset.Keyset, xci.OpenPartition(XciPartitionType.Secure)));
                }

                bool foundTicket = true;
                foreach (FileInfo file in nsp)
                {
                    PartitionFileSystem fs = new PartitionFileSystem(new LocalFile(file.FullName, OpenMode.Read).AsStorage());
                    foreach (DirectoryEntry d in fs.EnumerateEntries().Where(e => e.Type == DirectoryEntryType.File && e.Name.EndsWith(".tik")))
                    {
                        using (IFile tikFile = fs.OpenFile(d.FullPath, OpenMode.Read)) {
                            Ticket t = new Ticket(new BinaryReader(tikFile.AsStream()));
                            try
                            {
                                HACGUIKeyset.Keyset.TitleKeys[t.RightsId] = t.GetTitleKey(HACGUIKeyset.Keyset);
                                foundTicket = true;
                            } catch (Exception e)
                            {
                                MessageBox.Show("Failed to import .tik file included in NSP.");
                            }
                        }
                    }
                    switchFilesystems.Add(SwitchFs.OpenNcaDirectory(HACGUIKeyset.Keyset, fs));
                }

                if (foundTicket)
                {
                    TaskManagerPage.Current.Queue.Submit(new SaveKeysetTask(Preferences.Current.DefaultConsoleName));
                }

                foreach (SwitchFs fs in switchFilesystems)
                {
                    DeviceService.FsView.LoadFileSystemAsync("Opening imported data...", () => fs, FSView.TitleSource.Imported, false);
                }
            })));
        }
Esempio n. 17
0
        private static void Process(string inputFilePath, string outDirPath, XciTaskType taskType, Keyset keyset, Output Out, bool verifyBeforeDecrypting = true)
        {
            using (var inputFile = File.Open(inputFilePath, FileMode.Open, FileAccess.Read).AsStorage())
                using (var outputFile = File.Open($"{outDirPath}/xciMeta.dat", FileMode.Create))
                {
                    var         OutDirFs = new LocalFileSystem(outDirPath);
                    IDirectory  destRoot = OutDirFs.OpenDirectory("/", OpenDirectoryMode.All);
                    IFileSystem destFs   = destRoot.ParentFileSystem;

                    var header = new byte[] { 0x6e, 0x73, 0x5a, 0x69, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x58, 0x43, 0x49, 0x00 };
                    outputFile.Write(header, 0, header.Length);

                    var xci           = new Xci(keyset, inputFile);
                    var xciHeaderData = new byte[0x200];
                    var xciCertData   = new byte[0x200];
                    inputFile.Read(xciHeaderData, 0);
                    inputFile.Read(xciCertData, 0x7000);
                    outputFile.Write(xciHeaderData, 0, 0x200);
                    outputFile.Write(xciCertData, 0, 0x200);

                    Out.Log(Print.PrintXci(xci));

                    var root = xci.OpenPartition(XciPartitionType.Root);
                    if (root == null)
                    {
                        throw new InvalidDataException("Could not find root partition");
                    }

                    ProcessXci.GetTitleKeys(xci, keyset, Out);
                    foreach (var sub in root.Files)
                    {
                        outputFile.WriteByte(0x0A);
                        outputFile.WriteByte(0x0A);
                        var subDirNameChar = Encoding.ASCII.GetBytes(sub.Name);
                        outputFile.Write(subDirNameChar, 0, subDirNameChar.Length);
                        var subPfs = new PartitionFileSystem(new FileStorage(root.OpenFile(sub, OpenMode.Read)));
                        foreach (var subPfsFile in subPfs.Files)
                        {
                            outputFile.WriteByte(0x0A);
                            var subPfsFileNameChar = Encoding.ASCII.GetBytes(subPfsFile.Name);
                            outputFile.Write(subPfsFileNameChar, 0, subPfsFileNameChar.Length);
                            using (IFile srcFile = subPfs.OpenFile(subPfsFile.Name, OpenMode.Read))
                            {
                                if (taskType == XciTaskType.extractRomFS && subPfsFile.Name.EndsWith(".nca"))
                                {
                                    var fullOutDirPath = $"{outDirPath}/{sub.Name}/{subPfsFile.Name}";
                                    Out.Log($"Extracting {subPfsFile.Name}...\r\n");
                                    ProcessNca.Extract(srcFile.AsStream(), fullOutDirPath, verifyBeforeDecrypting, keyset, Out);
                                }
                                else
                                {
                                    var destFileName = Path.Combine(sub.Name, subPfsFile.Name);
                                    if (!destFs.DirectoryExists(sub.Name))
                                    {
                                        destFs.CreateDirectory(sub.Name);
                                    }
                                    destFs.CreateFile(destFileName, subPfsFile.Size, CreateFileOptions.None);
                                    using (IFile dstFile = destFs.OpenFile(destFileName, OpenMode.Write))
                                    {
                                        if (taskType == XciTaskType.decrypt && subPfsFile.Name.EndsWith(".nca"))
                                        {
                                            ProcessNca.Process(srcFile, dstFile, verifyBeforeDecrypting, keyset, Out);
                                        }
                                        else
                                        {
                                            srcFile.CopyTo(dstFile);
                                        }
                                    }
                                }
                            }
                        }
                    }

                    outputFile.WriteByte(0x0A);
                    outputFile.Dispose();
                }
        }
Esempio n. 18
0
        public override Task CreateTask()
        {
            return(new Task(() =>
            {
                FatFileSystemProvider system = NANDService.NAND.OpenSystemPartition();
                string accountSaveFileName = "/save/8000000000000010";
                if (system.FileExists(accountSaveFileName))
                {
                    IFile accountSaveFile = system.OpenFile(accountSaveFileName, OpenMode.Read);
                    SaveDataFileSystem accountSaveFilesystem = new SaveDataFileSystem(HACGUIKeyset.Keyset, accountSaveFile.AsStorage(), IntegrityCheckLevel.ErrorOnInvalid, false);

                    HACGUIKeyset.AccountsFolderInfo.Create(); // make sure folder exists

                    IDirectory avatorsDirectory = accountSaveFilesystem.OpenDirectory("/su/avators/", OpenDirectoryMode.Files);

                    IEnumerable <DirectoryEntry> files = avatorsDirectory.Read();

                    DirectoryEntry profileEntry = files.FirstOrDefault(e => e.Name == "profiles.dat");
                    if (profileEntry != null)
                    {
                        if (profileEntry.Size == 0x650)
                        {
                            IFile profileFile = accountSaveFilesystem.OpenFile(profileEntry.FullPath, OpenMode.Read);
                            Stream profileData = profileFile.AsStream();
                            profileData.Position += 0x10; // skip header
                            for (int i = 0; i < 8; i++)
                            {
                                byte[] data = new byte[0xC8];
                                profileData.Read(data, 0, data.Length);

                                byte[] uidBytes = new byte[0x10];
                                byte[] nameBytes = new byte[32];

                                Array.Copy(data, uidBytes, uidBytes.Length);
                                Array.Copy(data, 0x28, nameBytes, 0, nameBytes.Length);

                                char[] nameChars = Encoding.UTF8.GetChars(nameBytes);
                                int length = Array.IndexOf(nameChars, '\0');
                                string name = new string(nameChars.Take(length).ToArray());

                                Guid uid = Guid.Parse(uidBytes.ToHexString()); // ignores endianness, which is what i want
                                if (!string.IsNullOrEmpty(name))
                                {
                                    Preferences.Current.UserIds[uid.ToString()] = name;
                                }
                            }
                            Preferences.Current.Write();
                        }
                        else
                        {
                            MessageBox.Show("Invalid profiles.dat size! Something seems to be corrupt...");
                        }
                    }

                    foreach (DirectoryEntry entry in files.Where(e => e.Name != "profiles.dat"))
                    {
                        FileInfo localFile = HACGUIKeyset.AccountsFolderInfo.GetFile(entry.Name);
                        IFile saveFile = accountSaveFilesystem.OpenFile(entry.FullPath, OpenMode.Read);
                        using (Stream localStream = localFile.Open(FileMode.Create))
                            saveFile.AsStorage().CopyToStream(localStream, saveFile.GetSize());
                    }
                }
            }));
        }