Example #1
0
        private (Nca Main, Nca patch, Nca Control) GetXciGameData(Xci xci)
        {
            if (!xci.HasPartition(XciPartitionType.Secure))
            {
                throw new InvalidDataException("Could not find XCI secure partition");
            }

            Nca mainNca    = null;
            Nca patchNca   = null;
            Nca controlNca = null;

            XciPartition securePartition = xci.OpenPartition(XciPartitionType.Secure);

            foreach (DirectoryEntry ticketEntry in securePartition.EnumerateEntries("*.tik"))
            {
                Ticket ticket = new Ticket(securePartition.OpenFile(ticketEntry.FullPath, OpenMode.Read).AsStream());

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

            foreach (DirectoryEntry fileEntry in securePartition.EnumerateEntries("*.nca"))
            {
                IStorage ncaStorage = securePartition.OpenFile(fileEntry.FullPath, OpenMode.Read).AsStorage();

                Nca nca = new Nca(KeySet, ncaStorage);

                if (nca.Header.ContentType == ContentType.Program)
                {
                    int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, ContentType.Program);

                    if (nca.Header.GetFsHeader(dataIndex).IsPatchSection())
                    {
                        patchNca = nca;
                    }
                    else
                    {
                        mainNca = nca;
                    }
                }
                else if (nca.Header.ContentType == ContentType.Control)
                {
                    controlNca = nca;
                }
            }

            if (mainNca == null)
            {
                Logger.PrintError(LogClass.Loader, "Could not find an Application NCA in the provided XCI file");
            }

            if (controlNca != null)
            {
                ReadControlData(controlNca);
            }

            return(mainNca, patchNca, controlNca);
        }
Example #2
0
        private static Nca GetXciMainNca(Xci xci, Context ctx)
        {
            XciPartition partition = xci.OpenPartition(XciPartitionType.Secure);

            if (partition == null)
            {
                ctx.Logger.LogMessage("Could not find secure partition");
                return(null);
            }

            Nca mainNca = null;

            foreach (PartitionFileEntry fileEntry in partition.Files.Where(x => x.Name.EndsWith(".nca")))
            {
                IStorage ncaStorage = partition.OpenFile(fileEntry, OpenMode.Read).AsStorage();
                var      nca        = new Nca(ctx.Keyset, ncaStorage);

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

            return(mainNca);
        }
Example #3
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();
        }
Example #4
0
        public static void Process(Context ctx)
        {
            using (var file = new FileStream(ctx.Options.InFile, FileMode.Open, FileAccess.Read))
            {
                var xci = new Xci(ctx.Keyset, file.AsStorage());

                ctx.Logger.LogMessage(xci.Print());

                if (ctx.Options.RootDir != null)
                {
                    xci.RootPartition?.Extract(ctx.Options.RootDir, ctx.Logger);
                }

                if (ctx.Options.UpdateDir != null)
                {
                    xci.UpdatePartition?.Extract(ctx.Options.UpdateDir, ctx.Logger);
                }

                if (ctx.Options.NormalDir != null)
                {
                    xci.NormalPartition?.Extract(ctx.Options.NormalDir, ctx.Logger);
                }

                if (ctx.Options.SecureDir != null)
                {
                    xci.SecurePartition?.Extract(ctx.Options.SecureDir, ctx.Logger);
                }

                if (ctx.Options.LogoDir != null)
                {
                    xci.LogoPartition?.Extract(ctx.Options.LogoDir, ctx.Logger);
                }

                if (ctx.Options.OutDir != null && xci.RootPartition != null)
                {
                    XciPartition root = xci.RootPartition;
                    if (root == null)
                    {
                        ctx.Logger.LogMessage("Could not find root partition");
                        return;
                    }

                    foreach (PfsFileEntry sub in root.Files)
                    {
                        var    subPfs = new Pfs(root.OpenFile(sub));
                        string subDir = Path.Combine(ctx.Options.OutDir, sub.Name);

                        subPfs.Extract(subDir, ctx.Logger);
                    }
                }

                if (ctx.Options.ExefsOutDir != null || ctx.Options.ExefsOut != null)
                {
                    Nca mainNca = GetXciMainNca(xci, ctx);

                    if (mainNca == null)
                    {
                        ctx.Logger.LogMessage("Could not find Program NCA");
                        return;
                    }

                    NcaSection exefsSection = mainNca.Sections[(int)ProgramPartitionType.Code];

                    if (exefsSection == null)
                    {
                        ctx.Logger.LogMessage("NCA has no ExeFS section");
                        return;
                    }

                    if (ctx.Options.ExefsOutDir != null)
                    {
                        mainNca.ExtractSection(exefsSection.SectionNum, ctx.Options.ExefsOutDir, ctx.Options.IntegrityLevel, ctx.Logger);
                    }

                    if (ctx.Options.ExefsOut != null)
                    {
                        mainNca.ExportSection(exefsSection.SectionNum, ctx.Options.ExefsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger);
                    }
                }

                if (ctx.Options.RomfsOutDir != null || ctx.Options.RomfsOut != null)
                {
                    Nca mainNca = GetXciMainNca(xci, ctx);

                    if (mainNca == null)
                    {
                        ctx.Logger.LogMessage("Could not find Program NCA");
                        return;
                    }

                    NcaSection romfsSection = mainNca.Sections.FirstOrDefault(x => x.Type == SectionType.Romfs);

                    if (romfsSection == null)
                    {
                        ctx.Logger.LogMessage("NCA has no RomFS section");
                        return;
                    }

                    if (ctx.Options.RomfsOutDir != null)
                    {
                        var romfs = new Romfs(mainNca.OpenSection(romfsSection.SectionNum, false, ctx.Options.IntegrityLevel, true));
                        romfs.Extract(ctx.Options.RomfsOutDir, ctx.Logger);
                    }

                    if (ctx.Options.RomfsOut != null)
                    {
                        mainNca.ExportSection(romfsSection.SectionNum, ctx.Options.RomfsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger);
                    }
                }
            }
        }
Example #5
0
        public static void Process(Context ctx)
        {
            using (var file = new LocalStorage(ctx.Options.InFile, FileAccess.Read))
            {
                var xci = new Xci(ctx.Keyset, file);

                ctx.Logger.LogMessage(xci.Print());

                if (ctx.Options.RootDir != null)
                {
                    xci.OpenPartition(XciPartitionType.Root).Extract(ctx.Options.RootDir, ctx.Logger);
                }

                if (ctx.Options.UpdateDir != null && xci.HasPartition(XciPartitionType.Update))
                {
                    xci.OpenPartition(XciPartitionType.Update).Extract(ctx.Options.UpdateDir, ctx.Logger);
                }

                if (ctx.Options.NormalDir != null && xci.HasPartition(XciPartitionType.Normal))
                {
                    xci.OpenPartition(XciPartitionType.Normal).Extract(ctx.Options.NormalDir, ctx.Logger);
                }

                if (ctx.Options.SecureDir != null && xci.HasPartition(XciPartitionType.Secure))
                {
                    xci.OpenPartition(XciPartitionType.Secure).Extract(ctx.Options.SecureDir, ctx.Logger);
                }

                if (ctx.Options.LogoDir != null && xci.HasPartition(XciPartitionType.Logo))
                {
                    xci.OpenPartition(XciPartitionType.Logo).Extract(ctx.Options.LogoDir, ctx.Logger);
                }

                if (ctx.Options.OutDir != null)
                {
                    XciPartition root = xci.OpenPartition(XciPartitionType.Root);
                    if (root == null)
                    {
                        ctx.Logger.LogMessage("Could not find root partition");
                        return;
                    }

                    foreach (PartitionFileEntry sub in root.Files)
                    {
                        var    subPfs = new PartitionFileSystem(root.OpenFile(sub, OpenMode.Read).AsStorage());
                        string subDir = Path.Combine(ctx.Options.OutDir, sub.Name);

                        subPfs.Extract(subDir, ctx.Logger);
                    }
                }

                if (ctx.Options.ExefsOutDir != null || ctx.Options.ExefsOut != null)
                {
                    Nca mainNca = GetXciMainNca(xci, ctx);

                    if (mainNca == null)
                    {
                        ctx.Logger.LogMessage("Could not find Program NCA");
                        return;
                    }

                    if (!mainNca.SectionExists(NcaSectionType.Code))
                    {
                        ctx.Logger.LogMessage("NCA has no ExeFS section");
                        return;
                    }

                    if (ctx.Options.ExefsOutDir != null)
                    {
                        mainNca.ExtractSection(NcaSectionType.Code, ctx.Options.ExefsOutDir, ctx.Options.IntegrityLevel, ctx.Logger);
                    }

                    if (ctx.Options.ExefsOut != null)
                    {
                        mainNca.ExportSection(NcaSectionType.Code, ctx.Options.ExefsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger);
                    }
                }

                if (ctx.Options.RomfsOutDir != null || ctx.Options.RomfsOut != null || ctx.Options.ListRomFs)
                {
                    Nca mainNca = GetXciMainNca(xci, ctx);

                    if (mainNca == null)
                    {
                        ctx.Logger.LogMessage("Could not find Program NCA");
                        return;
                    }

                    if (!mainNca.SectionExists(NcaSectionType.Data))
                    {
                        ctx.Logger.LogMessage("NCA has no RomFS section");
                        return;
                    }

                    ProcessRomfs.Process(ctx, mainNca.OpenStorage(NcaSectionType.Data, ctx.Options.IntegrityLevel, false));
                }
            }
        }