Пример #1
0
        public void Apply(ExeFS exefs, List <Tuple <string, uint> > symbols)
        {
            long patchAddr = Address.GetAddress(exefs, symbols);

            byte[] buffer = new byte[0];

            switch (PatchType)
            {
            case PatchTypeEnum.ptr:
                buffer = BitConverter.GetBytes(((MemAddress)Data).GetAddress(exefs, symbols));
                break;

            case PatchTypeEnum.bl:
                long blHookAddr = ((MemAddress)Data).GetAddress(exefs, symbols);
                buffer = ArmUtils.Armv8Encode_bl((uint)(blHookAddr - patchAddr));
                break;

            case PatchTypeEnum.b:
                long bHookAddr = ((MemAddress)Data).GetAddress(exefs, symbols);
                buffer = ArmUtils.Armv8Encode_b((uint)(bHookAddr - patchAddr));
                break;

            case PatchTypeEnum.data:
                buffer = (byte[])Data;
                break;

            default:
                throw new Exception($"Invalid Patch Type : {PatchType}");
            }

            exefs.WriteExeFs(patchAddr, buffer);
        }
Пример #2
0
        static void AddSdk(ExeFS exefs, Nso custom)
        {
            Nso sdk = exefs.GetNso(NsoTypeEnum.sdk);

            exefs.SetNso(sdk, NsoTypeEnum.subsdk0);
            exefs.SetNso(custom, NsoTypeEnum.sdk);
        }
Пример #3
0
        private void ExtractExeFS(Stream output, NCCHRegion region, Keyslot secondaryKeyslot, bool close = true)
        {
            if (secondaryKeyslot == Keyslot.NCCH)
            {
                //if the secondary keyslot is also the original 0x2C NCCH Keyslot, don't bother decrypting anything in parts, and just shove the entire ExeFS through a CryptoStream
                Tools.CryptFileStreamPart(this.NCCHMemoryMappedFile, output, new AesCtrCryptoTransform(this.Cryptor.NormalKey[(int)Keyslot.NCCH], region.CTR), region.Offset, region.Size, close);
                return;
            }

            //here we go, i don't like this part

            byte[] header = new byte[0x200];

            using (MemoryMappedViewStream headerViewStream = this.NCCHMemoryMappedFile.CreateViewStream(region.Offset, 0x200))
            {
                header = Tools.CryptBytes(headerViewStream.ReadBytes(0x200), new AesCtrCryptoTransform(this.Cryptor.NormalKey[0x2C], region.CTR));
            }

            output.Write(header);

            //create dummy ExeFS class instance to figure out the locations of each file in the ExeFS
            ExeFS exefs = new ExeFS(header);

            //write decrypted header to output file
            foreach (ExeFSEntry entry in exefs.Entries)
            {
                byte[] CTR = (region.CTRInt + (entry.Offset / 16)).ToCTRBytes();

                AesCtrCryptoTransform transform = (NormalCryptoExeFSFiles.Contains(entry.Name)) ? new AesCtrCryptoTransform(this.Cryptor.NormalKey[(int)Keyslot.NCCH], CTR) : new AesCtrCryptoTransform(this.Cryptor.NormalKey[(int)secondaryKeyslot], CTR);

                using (MemoryMappedViewStream fileViewStream = this.NCCHMemoryMappedFile.CreateViewStream(region.Offset + entry.Offset, entry.Size))
                {
                    CryptoStream cs = new CryptoStream(output, transform, CryptoStreamMode.Write);

                    output.Seek(entry.Offset, SeekOrigin.Begin);

                    fileViewStream.CopyTo(cs);

                    cs.FlushFinalBlock();
                }
            }

            //sneaky way to make it gm9-like

            if (!(output.GetType() == typeof(MemoryMappedViewStream)))
            {
                output.SetLength(Tools.RoundUp(output.Length, 0x200));
            }

            if (close)
            {
                output.Dispose();
            }
        }
Пример #4
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!");
        }
Пример #5
0
 public long GetAddress(ExeFS exefs, List <Tuple <string, uint> > symbols)
 {
     if (IsSymbol)
     {
         foreach (var sym in symbols)
         {
             if (sym.Item1 == Symbol)
             {
                 return(exefs.GetNsoAddress(NsoTypeEnum.sdk) + sym.Item2);
             }
         }
         throw new PatchConfigException($"Could not find symbol : {Symbol}");
     }
     else
     {
         NsoTypeEnum type = NsoType;
         if (type == NsoTypeEnum.sdk)
         {
             type = NsoTypeEnum.subsdk0;
         }
         return(exefs.GetNsoAddress(type) + Offset);
     }
 }
Пример #6
0
        static void ApplyPatches(ExeFS exefs, string lstFile, string configfile)
        {
            var patches = PatchConfig.GetHooks(configfile);
            var symbols = ListingFile.GetSymbols(lstFile);

            foreach (var patch in patches)
            {
                Console.WriteLine($"{patch}");
                patch.Apply(exefs, symbols);
            }
            return;

            /* we don't need this anymore
             *
             * Console.WriteLine("Patching NPDM...");
             * //patch ndpm to be able to access sd card
             * using (var ms = new MemoryStream(exefs.Npdm))
             * {
             *  BinaryReader br = new BinaryReader(ms);
             *  BinaryWriter bw = new BinaryWriter(ms);
             *  br.BaseStream.Position = 0x70;
             *  var aci0Off = br.ReadUInt32(); //ACI0 offset
             *  br.BaseStream.Position = 0x78;
             *  var acidOff = br.ReadUInt32(); //ACID offset
             *
             *  br.BaseStream.Position = aci0Off+0x20; //FS Access Header offset
             *  var fsAccessHeaderOff = aci0Off + br.ReadUInt32();
             *  br.BaseStream.Position = acidOff + 0x220; //FS Access Control offset
             *  var fsAccessControlOff = acidOff + br.ReadUInt32();
             *
             *  bw.BaseStream.Position = fsAccessHeaderOff + 4;
             *  bw.Write(0x4000000000a92131); //full fs access
             *  bw.BaseStream.Position = fsAccessControlOff + 4;
             *  bw.Write(0x4000000000a92131); //full fs access
             * }
             */
        }
Пример #7
0
        public NCCH(Stream input)
        {
            _stream = input;
            using (var br = new BinaryReaderX(input, true))
            {
                //NCCH Header
                ncchHeader = br.ReadStruct <Header>();

                if (ncchHeader.ncchSize != input.Length / mediaUnitSize)
                {
                    throw new Exception("Size in header is not the same as the file.");
                }

                //ExtHeader
                if (ncchHeader.exHeaderSize != 0)
                {
                    var exHeaderOffset = br.BaseStream.Position;
                    exHeader = br.ReadStruct <ExHeader>();

                    Files.Add(new ArchiveFileInfo
                    {
                        State    = ArchiveFileState.Archived,
                        FileName = "ExHeader.bin",
                        FileData = new SubStream(br.BaseStream, exHeaderOffset, ncchHeader.exHeaderSize * 2)
                    });
                }

                //Plain Region
                if (ncchHeader.plainRegionOffset != 0 && ncchHeader.plainRegionSize != 0)
                {
                    br.BaseStream.Position = ncchHeader.plainRegionOffset * mediaUnitSize;
                    plainRegion            = br.ReadBytes(ncchHeader.plainRegionSize * mediaUnitSize);

                    Files.Add(new ArchiveFileInfo
                    {
                        State    = ArchiveFileState.Archived,
                        FileName = "PlainRegion.bin",
                        FileData = new SubStream(br.BaseStream, ncchHeader.plainRegionOffset * mediaUnitSize, ncchHeader.plainRegionSize * mediaUnitSize)
                    });
                }

                //Logo Region
                if (ncchHeader.logoRegionOffset != 0 && ncchHeader.logoRegionSize != 0)
                {
                    br.BaseStream.Position = ncchHeader.logoRegionOffset * mediaUnitSize;
                    logoRegion             = br.ReadBytes(ncchHeader.logoRegionSize * mediaUnitSize);

                    Files.Add(new ArchiveFileInfo
                    {
                        State    = ArchiveFileState.Archived,
                        FileName = "Logo.icn",
                        FileData = new SubStream(br.BaseStream, ncchHeader.logoRegionOffset * mediaUnitSize, ncchHeader.logoRegionSize * mediaUnitSize)
                    });
                }

                //ExeFS
                int exeFSHeaderSize = 0x200;
                if (ncchHeader.exeFSOffset != 0 && ncchHeader.exeFSSize != 0)
                {
                    br.BaseStream.Position = ncchHeader.exeFSOffset * mediaUnitSize;
                    exeFS = new ExeFS(br.BaseStream);

                    foreach (var exeFsFile in exeFS.fileHeader)
                    {
                        if (exeFsFile.offset == 0 && exeFsFile.size == 0)
                        {
                            break;
                        }
                        Files.Add(new ExeFSFileInfo
                        {
                            State      = ArchiveFileState.Archived,
                            FileName   = "ExeFS\\" + exeFsFile.name,
                            FileData   = new SubStream(br.BaseStream, ncchHeader.exeFSOffset * mediaUnitSize + exeFSHeaderSize + exeFsFile.offset, exeFsFile.size),
                            compressed = exeFsFile.name == ".code" && (exHeader.sci.flag & 0x1) == 1
                        });
                    }
                }

                //RomFS
                if (ncchHeader.romFSOffset != 0 && ncchHeader.romFSSize != 0)
                {
                    br.BaseStream.Position = ncchHeader.romFSOffset * mediaUnitSize;
                    romFS = new RomFS(br.BaseStream);
                    foreach (var romFSFile in romFS.files)
                    {
                        Files.Add(new ArchiveFileInfo
                        {
                            State    = ArchiveFileState.Archived,
                            FileName = "RomFS" + romFSFile.fileName,
                            FileData = new SubStream(br.BaseStream, romFSFile.fileOffset, romFSFile.fileSize)
                        });
                    }
                }
            }
        }