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