public override ISearchData CreateSearchData(IEnumerable <uint> values) { return(Buffer32.CreateSearchData(values.Select(a => new ValueTuple <byte, byte, byte, byte>( (byte)((a >> 24) & 0xFF), (byte)((a >> 16) & 0xFF), (byte)((a >> 8) & 0xFF), (byte)(a & 0xFF))).ToArray())); }
private Result ReadSegmentImpl(ref NsoHeader.SegmentHeader segment, uint fileSize, Buffer32 fileHash, bool isCompressed, bool checkHash, Span <byte> buffer) { // Select read size based on compression. if (!isCompressed) { fileSize = segment.Size; } // Validate size. if (fileSize > segment.Size) { return(ResultLoader.InvalidNso.Log()); } // Load data from file. uint loadAddress = isCompressed ? (uint)buffer.Length - fileSize : 0; Result rc = NsoFile.Read(out long bytesRead, segment.FileOffset, buffer.Slice((int)loadAddress), ReadOption.None); if (rc.IsFailure()) { return(rc); } if (bytesRead != fileSize) { return(ResultLoader.InvalidNso.Log()); } // Uncompress if necessary. if (isCompressed) { // todo: Fix in-place decompression // Lz4.Decompress(buffer.Slice((int)loadAddress), buffer); byte[] decomp = Lz4.Decompress(buffer.Slice((int)loadAddress).ToArray(), buffer.Length); decomp.CopyTo(buffer); } // Check hash if necessary. if (checkHash) { Buffer32 hash = default; Crypto.Sha256.GenerateSha256Hash(buffer.Slice(0, (int)segment.Size), hash.Bytes); if (hash.Bytes.SequenceCompareTo(fileHash.Bytes) != 0) { return(ResultLoader.InvalidNso.Log()); } } return(Result.Success); }
/// <summary> /// Verifies the hashes of all the payloads in the metadata. /// </summary> /// <returns>The <see cref="Result"/> of the operation. /// <see cref="Result.Success"/> if all the hashes are valid.</returns> public Result VerifyPayloads() { using (var buffer = new RentedArray <byte>(0x10000)) { byte[] array = buffer.Array; var hashBuffer = new Buffer32(); var sha = new Sha256Generator(); // Verify hashes match for all payloads. for (int i = 0; i < Package2Header.PayloadCount; i++) { if (_header.Meta.PayloadSizes[i] == 0) { continue; } int offset = _header.Meta.GetPayloadFileOffset(i); int size = (int)_header.Meta.PayloadSizes[i]; var payloadSubStorage = new SubStorage(_storage, offset, size); offset = 0; sha.Initialize(); while (size > 0) { int toRead = Math.Min(array.Length, size); Span <byte> span = array.AsSpan(0, toRead); Result rc = payloadSubStorage.Read(offset, span); if (rc.IsFailure()) { return(rc); } sha.Update(span); offset += toRead; size -= toRead; } sha.GetHash(hashBuffer); if (!CryptoUtil.IsSameBytes(hashBuffer, _header.Meta.PayloadHashes[i], 0x20)) { return(ResultLibHac.InvalidPackage2PayloadCorrupted.Log()); } } } return(Result.Success); }
public NsoExecutable(IStorage inStorage, string name = null) { NsoReader reader = new NsoReader(); reader.Initialize(inStorage.AsFile(OpenMode.Read)).ThrowIfFailure(); TextOffset = (int)reader.Header.Segments[0].MemoryOffset; RoOffset = (int)reader.Header.Segments[1].MemoryOffset; DataOffset = (int)reader.Header.Segments[2].MemoryOffset; BssSize = (int)reader.Header.BssSize; reader.GetSegmentSize(NsoReader.SegmentType.Data, out uint uncompressedSize).ThrowIfFailure(); Program = new byte[DataOffset + uncompressedSize]; TextSize = DecompressSection(reader, NsoReader.SegmentType.Text, TextOffset, Program); RoSize = DecompressSection(reader, NsoReader.SegmentType.Ro, RoOffset, Program); DataSize = DecompressSection(reader, NsoReader.SegmentType.Data, DataOffset, Program); Name = name; BuildId = reader.Header.ModuleId; }
public void MoveIn32(short bar, long barOffset, int[] data, int numToRead) { // A buffer takes priority over individual memory values if (Buffer32.ContainsKey(barOffset)) { int[] contents = Buffer32[barOffset]; Array.Copy(contents, data, Math.Min(contents.Length, numToRead)); } else { // return individual memory values that fall in the range long finalOffset = barOffset + (numToRead - 1) * sizeof(int); foreach (var key in mMemory.Keys) { if (barOffset <= key && key <= finalOffset) { int index = (int)(key - barOffset) / sizeof(int); data[index] = mMemory[key]; } } } }
public long FindBackward(long start, ValueTuple <byte, byte, byte, byte>[] values) { return(FindBackward(start, Buffer32.CreateSearchData(values))); }