private protected DataDirectoryBase(DirectoryEntry directory, PEHeaders headers, Memory <byte> imageBytes) { headers.TryGetDirectoryOffset(directory, out var directoryOffset); DirectoryOffset = directoryOffset; Headers = headers; ImageBytes = imageBytes; IsValid = directoryOffset != -1; }
private (RawDirectoryEntry, IEnumerable <StreamRange>) GetHashableRanges( PEHeaders headers ) { var snDir = headers.CorHeader.StrongNameSignatureDirectory; RawDirectoryEntry rawSNDir; return(snDir.Size > 0 && headers.TryGetDirectoryOffset(snDir, out var snOffset) ? (rawSNDir = new RawDirectoryEntry(snOffset, snDir.Size), this.CalculateRangesWithValidSNDir(headers, rawSNDir)) :
private protected DataDirectory(PEHeaders headers, Memory <byte> imageBytes, DirectoryEntry directory) { IsValid = headers.TryGetDirectoryOffset(directory, out var directoryOffset); DirectoryOffset = directoryOffset; Headers = headers; ImageBytes = imageBytes; }
private protected PEDataDirectory(PEHeaders headers, Memory <byte> imageData, DirectoryEntry directory) { if (headers == null || headers.PEHeader == null) { throw new ArgumentException("Attempted to initialize a PE data directory with null headers"); } IsValid = headers.TryGetDirectoryOffset(directory, out var directoryOffset); DirectoryOffset = directoryOffset; Headers = headers; ImageData = imageData; }
private static bool TestChecksumAndAuthenticodeSignature(Stream peStream, byte[] privateKeyOpt = null) { var peHeaders = new PEHeaders(peStream); bool is32bit = peHeaders.PEHeader.Magic == PEMagic.PE32; uint expectedChecksum = peHeaders.PEHeader.CheckSum; int peHeadersSize = peHeaders.PEHeaderStartOffset + PEHeader.Size(is32bit) + SectionHeader.Size * peHeaders.SectionHeaders.Length; peStream.Position = 0; if (expectedChecksum == 0) { // not signed return(false); } int peSize = (int)peStream.Length; var peImage = new BlobBuilder(peSize); Assert.Equal(peSize, peImage.TryWriteBytes(peStream, peSize)); var buffer = peImage.GetBlobs().Single().Buffer; var checksumBlob = new Blob(buffer, peHeaders.PEHeaderStartOffset + PEHeader.OffsetOfChecksum, sizeof(uint)); uint checksum = PEBuilder.CalculateChecksum(peImage, checksumBlob); Assert.Equal(expectedChecksum, checksum); // validate signature: if (privateKeyOpt != null) { // signature is calculated with checksum zeroed: new BlobWriter(checksumBlob).WriteUInt32(0); int snOffset; Assert.True(peHeaders.TryGetDirectoryOffset(peHeaders.CorHeader.StrongNameSignatureDirectory, out snOffset)); var snBlob = new Blob(buffer, snOffset, peHeaders.CorHeader.StrongNameSignatureDirectory.Size); var expectedSignature = snBlob.GetBytes().ToArray(); var signature = SigningUtilities.CalculateRsaSignature(PEBuilder.GetContentToSign(peImage, peHeadersSize, peHeaders.PEHeader.FileAlignment, snBlob), privateKeyOpt); AssertEx.Equal(expectedSignature, signature); } return(true); }
/// <summary> /// Validates that the given stream is marked as signed, the signature matches /// the public key, and the header checksum is correct. /// </summary> public static bool IsStreamFullSigned(Stream moduleContents) { var savedPosition = moduleContents.Position; try { moduleContents.Position = 0; var peHeaders = new PEHeaders(moduleContents); moduleContents.Position = 0; using (var metadata = ModuleMetadata.CreateFromStream(moduleContents, leaveOpen: true)) { var metadataReader = metadata.MetadataReader; var peReader = metadata.Module.PEReaderOpt; var flags = peHeaders.CorHeader.Flags; if (CorFlags.StrongNameSigned != (flags & CorFlags.StrongNameSigned)) { return(false); } var snDirectory = peReader.PEHeaders.CorHeader.StrongNameSignatureDirectory; if (!peHeaders.TryGetDirectoryOffset(snDirectory, out int snOffset)) { return(false); } moduleContents.Position = 0; int peSize; try { peSize = checked ((int)moduleContents.Length); } catch { return(false); } var peImage = new BlobBuilder(peSize); if (peSize != peImage.TryWriteBytes(moduleContents, peSize)) { return(false); } byte[] buffer = GetBlobBuffer(peImage.GetBlobs().Single()); uint expectedChecksum = peHeaders.PEHeader.CheckSum; Blob checksumBlob = MakeBlob(buffer, peHeaders.PEHeaderStartOffset + ChecksumOffset, sizeof(uint)); if (expectedChecksum != PeWriter.CalculateChecksum(peImage, checksumBlob)) { return(false); } int snSize = snDirectory.Size; byte[] hash = ComputeSigningHash(peImage, peHeaders, checksumBlob, snOffset, snSize); ImmutableArray <byte> publicKeyBlob = metadataReader.GetBlobContent(metadataReader.GetAssemblyDefinition().PublicKey); // RSA parameters start after the public key offset byte[] publicKeyParams = new byte[publicKeyBlob.Length - CryptoBlobParser.s_publicKeyHeaderSize]; publicKeyBlob.CopyTo(CryptoBlobParser.s_publicKeyHeaderSize, publicKeyParams, 0, publicKeyParams.Length); var snKey = publicKeyParams.ToRSAParameters(includePrivateParameters: false); using (var rsa = RSA.Create()) { rsa.ImportParameters(snKey); var reversedSignature = peReader.GetSectionData(snDirectory.RelativeVirtualAddress).GetContent(0, snSize).ToArray(); // Unknown why the signature is reversed, but this matches the behavior of the CLR // signing implementation. Array.Reverse(reversedSignature); if (!rsa.VerifyHash(hash, reversedSignature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1)) { return(false); } } return(true); } } finally { moduleContents.Position = savedPosition; } }
private static bool TestChecksumAndAuthenticodeSignature(Stream peStream, byte[] privateKeyOpt = null) { var peHeaders = new PEHeaders(peStream); bool is32bit = peHeaders.PEHeader.Magic == PEMagic.PE32; uint expectedChecksum = peHeaders.PEHeader.CheckSum; int peHeadersSize = peHeaders.PEHeaderStartOffset + PEHeader.Size(is32bit) + SectionHeader.Size * peHeaders.SectionHeaders.Length; peStream.Position = 0; if (expectedChecksum == 0) { // not signed return false; } int peSize = (int)peStream.Length; var peImage = new BlobBuilder(peSize); Assert.Equal(peSize, peImage.TryWriteBytes(peStream, peSize)); var buffer = peImage.GetBlobs().Single().Buffer; var checksumBlob = new Blob(buffer, peHeaders.PEHeaderStartOffset + PEHeader.OffsetOfChecksum, sizeof(uint)); uint checksum = PEBuilder.CalculateChecksum(peImage, checksumBlob); Assert.Equal(expectedChecksum, checksum); // validate signature: if (privateKeyOpt != null) { // signature is calculated with checksum zeroed: new BlobWriter(checksumBlob).WriteUInt32(0); int snOffset; Assert.True(peHeaders.TryGetDirectoryOffset(peHeaders.CorHeader.StrongNameSignatureDirectory, out snOffset)); var snBlob = new Blob(buffer, snOffset, peHeaders.CorHeader.StrongNameSignatureDirectory.Size); var expectedSignature = snBlob.GetBytes().ToArray(); var signature = SigningUtilities.CalculateRsaSignature(PEBuilder.GetContentToSign(peImage, peHeadersSize, peHeaders.PEHeader.FileAlignment, snBlob), privateKeyOpt); AssertEx.Equal(expectedSignature, signature); } return true; }