示例#1
0
        private long MapNro(ServiceCtx Context, NroInfo Info, out long NroMappedAddress)
        {
            NroMappedAddress = 0;
            long TargetAddress = Context.Process.MemoryManager.AddrSpaceStart;

            long HeapRegionStart = Context.Process.MemoryManager.HeapRegionStart;
            long HeapRegionEnd   = Context.Process.MemoryManager.HeapRegionEnd;

            long MapRegionStart = Context.Process.MemoryManager.MapRegionStart;
            long MapRegionEnd   = Context.Process.MemoryManager.MapRegionEnd;

            while (true)
            {
                if (TargetAddress + Info.TotalSize >= Context.Process.MemoryManager.AddrSpaceEnd)
                {
                    return(MakeError(ErrorModule.Loader, LoaderErr.InvalidMemoryState));
                }

                bool IsValidAddress = !(HeapRegionStart > 0 && HeapRegionStart <= TargetAddress + Info.TotalSize - 1 &&
                                        TargetAddress <= HeapRegionEnd - 1) &&
                                      !(MapRegionStart > 0 &&
                                        MapRegionStart <= TargetAddress + Info.TotalSize - 1 &&
                                        TargetAddress <= MapRegionEnd - 1);

                if (IsValidAddress && Context.Process.MemoryManager.HleIsUnmapped(TargetAddress, Info.TotalSize))
                {
                    break;
                }

                TargetAddress += 0x1000;
            }

            Context.Process.LoadProgram(Info.Executable, TargetAddress);

            Info.NroMappedAddress = TargetAddress;
            NroMappedAddress      = TargetAddress;

            return(0);
        }
示例#2
0
        private long MapNro(ServiceCtx context, NroInfo info, out ulong nroMappedAddress)
        {
            nroMappedAddress = 0;

            KMemoryManager memMgr = context.Process.MemoryManager;

            ulong targetAddress = memMgr.GetAddrSpaceBaseAddr();

            while (true)
            {
                if (targetAddress + info.TotalSize >= memMgr.AddrSpaceEnd)
                {
                    return(MakeError(ErrorModule.Loader, LoaderErr.InvalidMemoryState));
                }

                KMemoryInfo memInfo = memMgr.QueryMemory(targetAddress);

                if (memInfo.State == MemoryState.Unmapped && memInfo.Size >= info.TotalSize)
                {
                    if (!memMgr.InsideHeapRegion(targetAddress, info.TotalSize) &&
                        !memMgr.InsideAliasRegion(targetAddress, info.TotalSize))
                    {
                        break;
                    }
                }

                targetAddress += memInfo.Size;
            }

            KernelResult result = memMgr.MapProcessCodeMemory(targetAddress, info.NroAddress, info.NroSize);

            if (result != KernelResult.Success)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.InvalidMemoryState));
            }

            ulong bssTargetAddress = targetAddress + info.NroSize;

            if (info.BssSize != 0)
            {
                result = memMgr.MapProcessCodeMemory(bssTargetAddress, info.BssAddress, info.BssSize);

                if (result != KernelResult.Success)
                {
                    memMgr.UnmapProcessCodeMemory(targetAddress, info.NroAddress, info.NroSize);

                    return(MakeError(ErrorModule.Loader, LoaderErr.InvalidMemoryState));
                }
            }

            result = LoadNroIntoMemory(context.Process, info.Executable, targetAddress);

            if (result != KernelResult.Success)
            {
                memMgr.UnmapProcessCodeMemory(targetAddress, info.NroAddress, info.NroSize);

                if (info.BssSize != 0)
                {
                    memMgr.UnmapProcessCodeMemory(bssTargetAddress, info.BssAddress, info.BssSize);
                }

                return(0);
            }

            info.NroMappedAddress = targetAddress;
            nroMappedAddress      = targetAddress;

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

            if (_nroInfos.Count >= MaxNro)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.MaxNro));
            }
            else if (nroSize == 0 || nroAddress + nroSize <= nroAddress || (nroSize & 0xFFF) != 0)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.BadSize));
            }
            else if (bssSize != 0 && bssAddress + bssSize <= bssAddress)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.BadSize));
            }
            else if ((nroAddress & 0xFFF) != 0)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.UnalignedAddress));
            }

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

            if (magic != NroMagic || nroSize != nroFileSize)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.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(MakeError(ErrorModule.Loader, LoaderErr.NroHashNotPresent));
            }

            if (IsNroLoaded(nroHash))
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.NroAlreadyLoaded));
            }

            stream.Position = 0;

            NxRelocatableObject executable = new NxRelocatableObject(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(MakeError(ErrorModule.Loader, LoaderErr.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(MakeError(ErrorModule.Loader, LoaderErr.InvalidNro));
            }

            // finally check the bss size match.
            if ((ulong)executable.BssSize != bssSize)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.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(0);
        }
示例#4
0
        private long MapNro(ServiceCtx Context, NroInfo Info, out ulong NroMappedAddress)
        {
            NroMappedAddress = 0;

            KMemoryManager MemMgr = Context.Process.MemoryManager;

            ulong TargetAddress = MemMgr.GetAddrSpaceBaseAddr();

            while (true)
            {
                if (TargetAddress + Info.TotalSize >= MemMgr.AddrSpaceEnd)
                {
                    return(MakeError(ErrorModule.Loader, LoaderErr.InvalidMemoryState));
                }

                KMemoryInfo MemInfo = MemMgr.QueryMemory(TargetAddress);

                if (MemInfo.State == MemoryState.Unmapped && MemInfo.Size >= Info.TotalSize)
                {
                    if (!MemMgr.InsideHeapRegion(TargetAddress, Info.TotalSize) &&
                        !MemMgr.InsideAliasRegion(TargetAddress, Info.TotalSize))
                    {
                        break;
                    }
                }

                TargetAddress += MemInfo.Size;
            }

            KernelResult Result = MemMgr.MapProcessCodeMemory(TargetAddress, Info.NroAddress, Info.NroSize);

            if (Result != KernelResult.Success)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.InvalidMemoryState));
            }

            ulong BssTargetAddress = TargetAddress + Info.NroSize;

            if (Info.BssSize != 0)
            {
                Result = MemMgr.MapProcessCodeMemory(BssTargetAddress, Info.BssAddress, Info.BssSize);

                if (Result != KernelResult.Success)
                {
                    MemMgr.UnmapProcessCodeMemory(TargetAddress, Info.NroAddress, Info.NroSize);

                    return(MakeError(ErrorModule.Loader, LoaderErr.InvalidMemoryState));
                }
            }

            Result = LoadNroIntoMemory(Context.Process, Info.Executable, TargetAddress);

            if (Result != KernelResult.Success)
            {
                MemMgr.UnmapProcessCodeMemory(TargetAddress, Info.NroAddress, Info.NroSize);

                if (Info.BssSize != 0)
                {
                    MemMgr.UnmapProcessCodeMemory(BssTargetAddress, Info.BssAddress, Info.BssSize);
                }

                return(0);
            }

            Info.NroMappedAddress = TargetAddress;
            NroMappedAddress      = TargetAddress;

            return(0);
        }
示例#5
0
        public long ParseNro(out NroInfo Res, ServiceCtx Context, ulong NroAddress, ulong NroSize, ulong BssAddress, ulong BssSize)
        {
            Res = null;

            if (NroInfos.Count >= MaxNro)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.MaxNro));
            }
            else if (NroSize == 0 || NroAddress + NroSize <= NroAddress || (NroSize & 0xFFF) != 0)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.BadSize));
            }
            else if (BssSize != 0 && BssAddress + BssSize <= BssAddress)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.BadSize));
            }
            else if ((NroAddress & 0xFFF) != 0)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.UnalignedAddress));
            }

            uint Magic       = Context.Memory.ReadUInt32((long)NroAddress + 0x10);
            uint NroFileSize = Context.Memory.ReadUInt32((long)NroAddress + 0x18);

            if (Magic != NroMagic || NroSize != NroFileSize)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.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(MakeError(ErrorModule.Loader, LoaderErr.NroHashNotPresent));
            }

            if (IsNroLoaded(NroHash))
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.NroAlreadyLoaded));
            }

            Stream.Position = 0;

            NxRelocatableObject Executable = new NxRelocatableObject(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(MakeError(ErrorModule.Loader, LoaderErr.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(MakeError(ErrorModule.Loader, LoaderErr.InvalidNro));
            }

            // finally check the bss size match.
            if ((ulong)Executable.BssSize != BssSize)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.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(0);
        }