示例#1
0
        public static bool LoadNsos(KernelContext context, out ProcessTamperInfo tamperInfo, Npdm metaData, byte[] arguments = null, params IExecutable[] executables)
        {
            ulong argsStart = 0;
            uint  argsSize  = 0;
            ulong codeStart = metaData.Is64Bit ? 0x8000000UL : 0x200000UL;
            uint  codeSize  = 0;

            var buildIds = executables.Select(e => (e switch
            {
                NsoExecutable nso => BitConverter.ToString(nso.BuildId.Bytes.ToArray()),
                NroExecutable nro => BitConverter.ToString(nro.Header.BuildId),
                _ => ""
            }).Replace("-", "").ToUpper());
示例#2
0
 public NroInfo(
     NroExecutable executable,
     byte[]              hash,
     ulong nroAddress,
     ulong nroSize,
     ulong bssAddress,
     ulong bssSize,
     ulong totalSize)
 {
     Executable = executable;
     Hash       = hash;
     NroAddress = nroAddress;
     NroSize    = nroSize;
     BssAddress = bssAddress;
     BssSize    = bssSize;
     TotalSize  = totalSize;
 }
示例#3
0
        public ResultCode ParseNro(out NroInfo res, ServiceCtx context, ulong nroAddress, ulong nroSize, ulong bssAddress, ulong bssSize)
        {
            res = null;

            if (_nroInfos.Count >= MaxNro)
            {
                return(ResultCode.TooManyNro);
            }
            else if (nroSize == 0 || nroAddress + nroSize <= nroAddress || (nroSize & 0xFFF) != 0)
            {
                return(ResultCode.InvalidSize);
            }
            else if (bssSize != 0 && bssAddress + bssSize <= bssAddress)
            {
                return(ResultCode.InvalidSize);
            }
            else if ((nroAddress & 0xFFF) != 0)
            {
                return(ResultCode.InvalidAddress);
            }

            uint magic       = _owner.CpuMemory.Read <uint>(nroAddress + 0x10);
            uint nroFileSize = _owner.CpuMemory.Read <uint>(nroAddress + 0x18);

            if (magic != NroMagic || nroSize != nroFileSize)
            {
                return(ResultCode.InvalidNro);
            }

            byte[] nroData = new byte[nroSize];

            _owner.CpuMemory.Read(nroAddress, nroData);

            byte[] nroHash = null;

            MemoryStream stream = new MemoryStream(nroData);

            using (SHA256 hasher = SHA256.Create())
            {
                nroHash = hasher.ComputeHash(stream);
            }

            if (!IsNroHashPresent(nroHash))
            {
                return(ResultCode.NotRegistered);
            }

            if (IsNroLoaded(nroHash))
            {
                return(ResultCode.AlreadyLoaded);
            }

            stream.Position = 0;

            NroExecutable nro = new NroExecutable(stream.AsStorage(), nroAddress, bssAddress);

            // Check if everything is page align.
            if ((nro.Text.Length & 0xFFF) != 0 || (nro.Ro.Length & 0xFFF) != 0 ||
                (nro.Data.Length & 0xFFF) != 0 || (nro.BssSize & 0xFFF) != 0)
            {
                return(ResultCode.InvalidNro);
            }

            // Check if everything is contiguous.
            if (nro.RoOffset != nro.TextOffset + nro.Text.Length ||
                nro.DataOffset != nro.RoOffset + nro.Ro.Length ||
                nroFileSize != nro.DataOffset + nro.Data.Length)
            {
                return(ResultCode.InvalidNro);
            }

            // Check the bss size match.
            if ((ulong)nro.BssSize != bssSize)
            {
                return(ResultCode.InvalidNro);
            }

            uint totalSize = (uint)nro.Text.Length + (uint)nro.Ro.Length + (uint)nro.Data.Length + nro.BssSize;

            // Apply patches
            context.Device.FileSystem.ModLoader.ApplyNroPatches(nro);

            res = new NroInfo(
                nro,
                nroHash,
                nroAddress,
                nroSize,
                bssAddress,
                bssSize,
                (ulong)totalSize);

            return(ResultCode.Success);
        }
示例#4
0
        public ResultCode ParseNro(out NroInfo res, ServiceCtx context, ulong nroAddress, ulong nroSize, ulong bssAddress, ulong bssSize)
        {
            res = null;

            if (_nroInfos.Count >= MaxNro)
            {
                return(ResultCode.TooManyNro);
            }
            else if (nroSize == 0 || nroAddress + nroSize <= nroAddress || (nroSize & 0xFFF) != 0)
            {
                return(ResultCode.InvalidSize);
            }
            else if (bssSize != 0 && bssAddress + bssSize <= bssAddress)
            {
                return(ResultCode.InvalidSize);
            }
            else if ((nroAddress & 0xFFF) != 0)
            {
                return(ResultCode.InvalidAddress);
            }

            uint magic       = context.Memory.ReadUInt32((long)nroAddress + 0x10);
            uint nroFileSize = context.Memory.ReadUInt32((long)nroAddress + 0x18);

            if (magic != NroMagic || nroSize != nroFileSize)
            {
                return(ResultCode.InvalidNro);
            }

            byte[] nroData = context.Memory.ReadBytes((long)nroAddress, (long)nroSize);
            byte[] nroHash = null;

            MemoryStream stream = new MemoryStream(nroData);

            using (SHA256 hasher = SHA256.Create())
            {
                nroHash = hasher.ComputeHash(stream);
            }

            if (!IsNroHashPresent(nroHash))
            {
                return(ResultCode.NotRegistered);
            }

            if (IsNroLoaded(nroHash))
            {
                return(ResultCode.AlreadyLoaded);
            }

            stream.Position = 0;

            NroExecutable executable = new NroExecutable(stream, nroAddress, bssAddress);

            // check if everything is page align.
            if ((executable.Text.Length & 0xFFF) != 0 || (executable.Ro.Length & 0xFFF) != 0 ||
                (executable.Data.Length & 0xFFF) != 0 || (executable.BssSize & 0xFFF) != 0)
            {
                return(ResultCode.InvalidNro);
            }

            // check if everything is contiguous.
            if (executable.RoOffset != executable.TextOffset + executable.Text.Length ||
                executable.DataOffset != executable.RoOffset + executable.Ro.Length ||
                nroFileSize != executable.DataOffset + executable.Data.Length)
            {
                return(ResultCode.InvalidNro);
            }

            // finally check the bss size match.
            if ((ulong)executable.BssSize != bssSize)
            {
                return(ResultCode.InvalidNro);
            }

            int totalSize = executable.Text.Length + executable.Ro.Length + executable.Data.Length + executable.BssSize;

            res = new NroInfo(
                executable,
                nroHash,
                nroAddress,
                nroSize,
                bssAddress,
                bssSize,
                (ulong)totalSize);

            return(ResultCode.Success);
        }
示例#5
0
        public void LoadProgram(string filePath)
        {
            Npdm metaData = GetDefaultNpdm();

            bool isNro = Path.GetExtension(filePath).ToLower() == ".nro";


            IExecutable staticObject;

            if (isNro)
            {
                FileStream    input = new FileStream(filePath, FileMode.Open);
                NroExecutable obj   = new NroExecutable(input);
                staticObject = obj;

                // homebrew NRO can actually have some data after the actual NRO
                if (input.Length > obj.FileSize)
                {
                    input.Position = obj.FileSize;

                    BinaryReader reader = new BinaryReader(input);

                    uint asetMagic = reader.ReadUInt32();

                    if (asetMagic == 0x54455341)
                    {
                        uint asetVersion = reader.ReadUInt32();
                        if (asetVersion == 0)
                        {
                            ulong iconOffset = reader.ReadUInt64();
                            ulong iconSize   = reader.ReadUInt64();

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

                            ulong romfsOffset = reader.ReadUInt64();
                            ulong romfsSize   = reader.ReadUInt64();

                            if (romfsSize != 0)
                            {
                                Device.FileSystem.SetRomFs(new HomebrewRomFsStream(input, obj.FileSize + (long)romfsOffset));
                            }

                            if (nacpSize != 0)
                            {
                                input.Seek(obj.FileSize + (long)nacpOffset, SeekOrigin.Begin);

                                reader.Read(ControlData.ByteSpan);

                                ref ApplicationControlProperty nacp = ref ControlData.Value;

                                metaData.TitleName = nacp.Titles[(int)State.DesiredTitleLanguage].Name.ToString();

                                if (string.IsNullOrWhiteSpace(metaData.TitleName))
                                {
                                    metaData.TitleName = nacp.Titles.ToArray().FirstOrDefault(x => x.Name[0] != 0).Name.ToString();
                                }

                                if (nacp.PresenceGroupId != 0)
                                {
                                    metaData.Aci0.TitleId = nacp.PresenceGroupId;
                                }
                                else if (nacp.SaveDataOwnerId.Value != 0)
                                {
                                    metaData.Aci0.TitleId = nacp.SaveDataOwnerId.Value;
                                }
                                else if (nacp.AddOnContentBaseId != 0)
                                {
                                    metaData.Aci0.TitleId = nacp.AddOnContentBaseId - 0x1000;
                                }
                                else
                                {
                                    metaData.Aci0.TitleId = 0000000000000000;
                                }
                            }
                        }
                        else
                        {
                            Logger.PrintWarning(LogClass.Loader, $"Unsupported ASET header version found \"{asetVersion}\"");
                        }
                    }
                }
            }