private unsafe DiscoveredAssembly DiscoverAssembly(string assemblyPath)
        {
            var  fileInfo = new FileInfo(assemblyPath);
            long length   = fileInfo.Length;
            var  mapName  = fileInfo.Name;
            var  mode     = FileMode.Open;
            var  access   = MemoryMappedFileAccess.Read;

            using (var file = MemoryMappedFile.CreateFromFile(assemblyPath, mode, mapName, length, access))
            {
                using (var stream = file.CreateViewStream(0x0, length, access))
                {
                    var headers = new PEHeaders(stream);
                    var start   = (byte *)0;
                    stream.SafeMemoryMappedViewHandle.AcquirePointer(ref start);
                    var size   = headers.MetadataSize;
                    var reader = new MetadataReader(start + headers.MetadataStartOffset, size, default(MetadataReaderOptions), null);
                    return(new DiscoveredAssembly(assemblyPath, reader));
                }
            }
        }
        void GetStorageInfoFromTemporaryStorage(FileKey moduleFileKey, out ITemporaryStreamStorage storage, out Stream stream, out IntPtr pImage)
        {
            int size;

            using (var copyStream = SerializableBytes.CreateWritableStream()) {
                // open a file and let it go as soon as possible
                using (var fileStream = FileUtilities.OpenRead(moduleFileKey.FullPath)) {
                    var headers = new PEHeaders(fileStream);

                    var offset = headers.MetadataStartOffset;
                    size = headers.MetadataSize;

                    // given metadata contains no metadata info.
                    // throw bad image format exception so that we can show right diagnostic to user.
                    if (size <= 0)
                    {
                        throw new BadImageFormatException();
                    }

                    StreamCopy(fileStream, copyStream, offset, size);
                }

                // copy over the data to temp storage and let pooled stream go
                storage = _temporaryStorageService.CreateTemporaryStreamStorage(CancellationToken.None);

                copyStream.Position = 0;
                storage.WriteStream(copyStream);
            }

            // get stream that owns direct access memory
            stream = storage.ReadStream(CancellationToken.None);

            // stream size must be same as what metadata reader said the size should be.
            Contract.ThrowIfFalse(stream.Length == size);

            // under VS host, direct access should be supported
            var directAccess = (ISupportDirectMemoryAccess)stream;

            pImage = directAccess.GetPointer();
        }
Beispiel #3
0
        internal PeParser(byte[] dllBytes)
        {
            using (var peReader = new PEReader(new MemoryStream(dllBytes)))
            {
                DebugData = peReader.ReadCodeViewDebugDirectoryData(peReader.ReadDebugDirectory()[0]);

                PeHeaders = peReader.PEHeaders;
            }

            var peBufferHandle = GCHandle.Alloc(dllBytes, GCHandleType.Pinned);

            _peBuffer = peBufferHandle.AddrOfPinnedObject();

            BaseRelocations = GetBaseRelocations();

            ExportedFunctions = GetExportedFunctions();

            ImportedFunctions = GetImportedFunctions();

            TlsCallbacks = GetTlsCallbacks();

            peBufferHandle.Free();
        }
Beispiel #4
0
 internal BaseRelocationDirectory(PEHeaders headers, Memory <byte> imageBuffer) : base(headers, imageBuffer)
 {
     BaseRelocations = ReadBaseRelocations();
 }
Beispiel #5
0
 internal static bool Requires64Bits(this PEHeaders headers)
 {
     return(headers.PEHeader != null && headers.PEHeader.Magic == PEMagic.PE32Plus ||
            headers.CoffHeader.Machine == Machine.Amd64 ||
            headers.CoffHeader.Machine == Machine.IA64);
 }
Beispiel #6
0
        protected DataDirectory(ReadOnlyMemory <byte> peBytes, PEHeaders peHeaders)
        {
            PeBytes = peBytes;

            PeHeaders = peHeaders;
        }
Beispiel #7
0
 internal LoadConfigDirectory(PEHeaders headers, Memory <byte> imageBytes) : base(headers.PEHeader !.LoadConfigTableDirectory, headers, imageBytes)
Beispiel #8
0
 internal ExportDirectory(ReadOnlyMemory <byte> peBytes, PEHeaders peHeaders) : base(peBytes, peHeaders)
 {
     ExportedFunctions = ReadExportedFunctions().ToImmutableArray();
 }
Beispiel #9
0
 internal RelocationDirectory(PEHeaders headers, Memory <byte> imageBytes) : base(headers.PEHeader !.BaseRelocationTableDirectory, headers, imageBytes)
 internal ResourceDirectory(PEHeaders headers, Memory <byte> imageBytes) : base(headers.PEHeader !.ResourceTableDirectory, headers, imageBytes)
 public PELoadConfigDirectory(PEHeaders headers, Memory <byte> imageData) : base(headers, imageData, headers.PEHeader.LoadConfigTableDirectory)
 {
 }
Beispiel #12
0
 public DataDirectoryEntry(PEHeaders headers, string name, DirectoryEntry entry)
     : this(name, entry.RelativeVirtualAddress, entry.Size, (headers.GetContainingSectionIndex(entry.RelativeVirtualAddress) >= 0) ? headers.SectionHeaders[headers.GetContainingSectionIndex(entry.RelativeVirtualAddress)].Name : "")
 {
 }
Beispiel #13
0
        internal LoadConfigDirectory(PEHeaders headers, Memory <byte> imageBlock) : base(headers, imageBlock)
        {
            SecurityCookie = ReadSecurityCookie();

            SehTable = ReadSehTable();
        }
Beispiel #14
0
 internal BaseRelocationDirectory(ReadOnlyMemory <byte> peBytes, PEHeaders peHeaders) : base(peBytes, peHeaders)
 {
     BaseRelocations = ReadBaseRelocations().ToImmutableArray();
 }
 public PETlsDirectory(PEHeaders headers, Memory<byte> imageData) : base(headers, imageData, headers.PEHeader.ThreadLocalStorageTableDirectory) { }
        protected DataDirectory(PEHeaders headers, Memory <byte> imageBlock)
        {
            Headers = headers;

            ImageBlock = imageBlock;
        }
 public PEImportDirectory(PEHeaders headers, Memory <byte> imageData) : base(headers, imageData, headers.PEHeader.ImportTableDirectory)
 {
 }
Beispiel #18
0
 internal TlsDirectory(PEHeaders headers, Memory <byte> imageBytes) : base(headers, imageBytes, headers.PEHeader !.ThreadLocalStorageTableDirectory)
 internal ImportDirectory(PEHeaders headers, Memory <byte> imageBlock) : base(headers, imageBlock)
 {
     ImportDescriptors = ReadImportDescriptors();
 }
Beispiel #20
0
        static internal Microsoft.Cci.ResourceSection ReadWin32ResourcesFromCOFF(Stream stream)
        {
            var peHeaders = new PEHeaders(stream);
            var rsrc1     = new SectionHeader();
            var rsrc2     = new SectionHeader();

            int foundCount = 0;

            foreach (var sectionHeader in peHeaders.SectionHeaders)
            {
                if (sectionHeader.Name == ".rsrc$01")
                {
                    rsrc1 = sectionHeader;
                    foundCount++;
                }
                else if (sectionHeader.Name == ".rsrc$02")
                {
                    rsrc2 = sectionHeader;
                    foundCount++;
                }
            }

            if (foundCount != 2)
            {
                throw new ResourceException(CodeAnalysisResources.CoffResourceMissingSection);
            }

            ConfirmSectionValues(rsrc1, stream.Length);
            ConfirmSectionValues(rsrc2, stream.Length);

            //This will be the final resource section bytes without a header. It contains the concatenation
            //of .rsrc$02 on to the end of .rsrc$01.
            var imageResourceSectionBytes = new byte[checked (rsrc1.SizeOfRawData + rsrc2.SizeOfRawData)];

            stream.Seek(rsrc1.PointerToRawData, SeekOrigin.Begin);
            stream.TryReadAll(imageResourceSectionBytes, 0, rsrc1.SizeOfRawData);                   // ConfirmSectionValues ensured that data are available
            stream.Seek(rsrc2.PointerToRawData, SeekOrigin.Begin);
            stream.TryReadAll(imageResourceSectionBytes, rsrc1.SizeOfRawData, rsrc2.SizeOfRawData); // ConfirmSectionValues ensured that data are available

            const int SizeOfRelocationEntry = 10;

            try
            {
                var relocLastAddress = checked (rsrc1.PointerToRelocations + (rsrc1.NumberOfRelocations * SizeOfRelocationEntry));

                if (relocLastAddress > stream.Length)
                {
                    throw new ResourceException(CodeAnalysisResources.CoffResourceInvalidRelocation);
                }
            }
            catch (OverflowException)
            {
                throw new ResourceException(CodeAnalysisResources.CoffResourceInvalidRelocation);
            }

            //.rsrc$01 contains the directory tree. .rsrc$02 contains the raw resource data.
            //.rsrc$01 has references to spots in .rsrc$02. Those spots are expressed as relocations.
            //These will need to be fixed up when the RVA of the .rsrc section in the final image is known.
            var relocationOffsets = new uint[rsrc1.NumberOfRelocations];    //offsets into .rsrc$01

            var relocationSymbolIndices = new uint[rsrc1.NumberOfRelocations];

            var reader = new BinaryReader(stream, Encoding.Unicode);

            stream.Position = rsrc1.PointerToRelocations;

            for (int i = 0; i < rsrc1.NumberOfRelocations; i++)
            {
                relocationOffsets[i] = reader.ReadUInt32();
                //What is being read and stored is the reloc's "Value"
                //This is the symbol's index.
                relocationSymbolIndices[i] = reader.ReadUInt32();
                reader.ReadUInt16(); //we do nothing with the "Type"
            }

            //now that symbol indices are gathered, begin indexing the symbols
            stream.Position = peHeaders.CoffHeader.PointerToSymbolTable;
            const uint ImageSizeOfSymbol = 18;

            try
            {
                var lastSymAddress = checked (peHeaders.CoffHeader.PointerToSymbolTable + peHeaders.CoffHeader.NumberOfSymbols * ImageSizeOfSymbol);

                if (lastSymAddress > stream.Length)
                {
                    throw new ResourceException(CodeAnalysisResources.CoffResourceInvalidSymbol);
                }
            }
            catch (OverflowException)
            {
                throw new ResourceException(CodeAnalysisResources.CoffResourceInvalidSymbol);
            }

            var outputStream = new MemoryStream(imageResourceSectionBytes);
            var writer       = new BinaryWriter(outputStream); //encoding shouldn't matter. There are no strings being written.

            for (int i = 0; i < relocationSymbolIndices.Length; i++)
            {
                if (relocationSymbolIndices[i] > peHeaders.CoffHeader.NumberOfSymbols)
                {
                    throw new ResourceException(CodeAnalysisResources.CoffResourceInvalidRelocation);
                }

                var offsetOfSymbol = peHeaders.CoffHeader.PointerToSymbolTable + relocationSymbolIndices[i] * ImageSizeOfSymbol;

                stream.Position  = offsetOfSymbol;
                stream.Position += 8; //skip over symbol name
                var symValue   = reader.ReadUInt32();
                var symSection = reader.ReadInt16();
                var symType    = reader.ReadUInt16();
                //ignore the rest of the fields.

                const ushort IMAGE_SYM_TYPE_NULL = 0x0000;

                if (symType != IMAGE_SYM_TYPE_NULL ||
                    symSection != 3)  //3rd section is .rsrc$02
                {
                    throw new ResourceException(CodeAnalysisResources.CoffResourceInvalidSymbol);
                }

                //perform relocation. We are concatenating the contents of .rsrc$02 (the raw resource data)
                //on to the end of .rsrc$01 (the directory tree) to yield the final resource section for the image.
                //The directory tree has references into the raw resource data. These references are expressed
                //in the final image as file positions, not positions relative to the beginning of the section.
                //First make the resources be relative to the beginning of the section by adding the size
                //of .rsrc$01 to them. They will ultimately need the RVA of the final image resource section added
                //to them. We don't know that yet. That is why the array of offsets is preserved.

                outputStream.Position = relocationOffsets[i];
                writer.Write((uint)(symValue + rsrc1.SizeOfRawData));
            }

            return(new Cci.ResourceSection(imageResourceSectionBytes, relocationOffsets));
        }
Beispiel #21
0
 internal ImportDirectory(ReadOnlyMemory <byte> peBytes, PEHeaders peHeaders) : base(peBytes, peHeaders)
 {
     ImportDescriptors = ReadImportDescriptors().ToImmutableArray();
 }
Beispiel #22
0
 internal ExportDirectory(PEHeaders headers, Memory <byte> imageBuffer) : base(headers, imageBuffer)
 {
     ExportedFunctions = ReadExportedFunctions();
 }
Beispiel #23
0
 internal DelayImportDirectory(PEHeaders headers, Memory <byte> imageBuffer) : base(headers, imageBuffer)
 {
     DelayLoadImportDescriptors = ReadDelayLoadImportDescriptors();
 }
Beispiel #24
0
 internal ExportDirectory(PEHeaders headers, Memory <byte> imageBytes) : base(headers.PEHeader !.ExportTableDirectory, headers, imageBytes)
Beispiel #25
0
 internal TlsDirectory(ReadOnlyMemory <byte> peBytes, PEHeaders peHeaders) : base(peBytes, peHeaders)
 {
     TlsCallbackOffsets = ReadTlsCallbackOffsets().ToImmutableArray();
 }
Beispiel #26
0
 internal static bool RequiresAmdInstructionSet(this PEHeaders headers)
 {
     return(headers.CoffHeader.Machine == Machine.Amd64);
 }
Beispiel #27
0
        /// <summary>
        /// Copy PE headers into a PEHeaderBuilder used by PEBuilder.
        /// </summary>
        /// <param name="peHeaders">Headers to copy</param>
        /// <param name="target">Target architecture to set in the header</param>
        public static PEHeaderBuilder Copy(PEHeaders peHeaders, TargetDetails target)
        {
            bool is64BitTarget = target.PointerSize == sizeof(long);

            Characteristics imageCharacteristics = peHeaders.CoffHeader.Characteristics;

            if (is64BitTarget)
            {
                imageCharacteristics &= ~Characteristics.Bit32Machine;
                imageCharacteristics |= Characteristics.LargeAddressAware;
            }

            int fileAlignment = 0x200;

            if (!target.IsWindows && !is64BitTarget)
            {
                // To minimize wasted VA space on 32 bit systems align file to page bounaries (presumed to be 4K).
                fileAlignment = 0x1000;
            }

            int sectionAlignment = 0x1000;

            if (!target.IsWindows && is64BitTarget)
            {
                // On Linux, we must match the bottom 12 bits of section RVA's to their file offsets. For this reason
                // we need the same alignment for both.
                sectionAlignment = fileAlignment;
            }

            DllCharacteristics dllCharacteristics = DllCharacteristics.DynamicBase | DllCharacteristics.NxCompatible;

            if (!is64BitTarget)
            {
                dllCharacteristics |= DllCharacteristics.NoSeh;
            }

            // Copy over selected DLL characteristics bits from IL image
            dllCharacteristics |= peHeaders.PEHeader.DllCharacteristics &
                                  (DllCharacteristics.TerminalServerAware | DllCharacteristics.AppContainer);

            if (is64BitTarget)
            {
                dllCharacteristics |= DllCharacteristics.HighEntropyVirtualAddressSpace;
            }

            return(new PEHeaderBuilder(
                       machine: target.MachineFromTarget(),
                       sectionAlignment: sectionAlignment,
                       fileAlignment: fileAlignment,
                       imageBase: peHeaders.PEHeader.ImageBase,
                       majorLinkerVersion: 11,
                       minorLinkerVersion: 0,
                       majorOperatingSystemVersion: 5,
                       // Win2k = 5.0 for 32-bit images, Win2003 = 5.2 for 64-bit images
                       minorOperatingSystemVersion: is64BitTarget ? (ushort)2 : (ushort)0,
                       majorImageVersion: peHeaders.PEHeader.MajorImageVersion,
                       minorImageVersion: peHeaders.PEHeader.MinorImageVersion,
                       majorSubsystemVersion: peHeaders.PEHeader.MajorSubsystemVersion,
                       minorSubsystemVersion: peHeaders.PEHeader.MinorSubsystemVersion,
                       subsystem: peHeaders.PEHeader.Subsystem,
                       dllCharacteristics: dllCharacteristics,
                       imageCharacteristics: imageCharacteristics,
                       sizeOfStackReserve: peHeaders.PEHeader.SizeOfStackReserve,
                       sizeOfStackCommit: peHeaders.PEHeader.SizeOfStackCommit,
                       sizeOfHeapReserve: 0,
                       sizeOfHeapCommit: 0));
        }
Beispiel #28
0
 internal TlsDirectory(PEHeaders headers, Memory <byte> imageBuffer) : base(headers, imageBuffer)
 {
     TlsCallBacks = ReadTlsCallBacks();
 }
Beispiel #29
0
 internal LoadConfigDirectory(ReadOnlyMemory <byte> peBytes, PEHeaders peHeaders) : base(peBytes, peHeaders)
 {
     SecurityCookieOffset = ReadSecurityCookieOffset();
 }
Beispiel #30
0
        /// <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;
            }
        }
Beispiel #31
0
        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;
        }