Exemplo n.º 1
0
        private ResultCode 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(ResultCode.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(ResultCode.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(ResultCode.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(ResultCode.Success);
            }

            info.NroMappedAddress = targetAddress;
            nroMappedAddress      = targetAddress;

            return(ResultCode.Success);
        }
Exemplo n.º 2
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.MaxNro);
            }
            else if (nroSize == 0 || nroAddress + nroSize <= nroAddress || (nroSize & 0xFFF) != 0)
            {
                return(ResultCode.BadSize);
            }
            else if (bssSize != 0 && bssAddress + bssSize <= bssAddress)
            {
                return(ResultCode.BadSize);
            }
            else if ((nroAddress & 0xFFF) != 0)
            {
                return(ResultCode.UnalignedAddress);
            }

            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.NroHashNotPresent);
            }

            if (IsNroLoaded(nroHash))
            {
                return(ResultCode.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(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);
        }