示例#1
0
文件: PE.cs 项目: blinds52/binskim
        public PE(string fileName)
        {
            FileName = Path.GetFullPath(fileName);
            Uri = new Uri(FileName);
            IsPEFile = false;
            try
            {
                _fs = File.OpenRead(FileName);

                byte byteRead = (byte)_fs.ReadByte();
                if (byteRead != 'M') { return; }

                byteRead = (byte)_fs.ReadByte();
                if (byteRead != 'Z') { return; }
                _fs.Seek(0, SeekOrigin.Begin);

                _peReader = new PEReader(_fs);
                PEHeaders = _peReader.PEHeaders;
                IsPEFile = true;
            }
            catch (IOException e) { LoadException = e; }
            catch (BadImageFormatException e) { LoadException = e; }
            catch (UnauthorizedAccessException e) { LoadException = e; }

            if (IsPEFile)
            {
                m_pImage = new SafePointer(_peReader.GetEntireImage().GetContent().ToBuilder().ToArray());

                if (IsManaged)
                {
                    _metadataReader = _peReader.GetMetadataReader();
                }
            }
        }
示例#2
0
        /// <summary>
        /// Reads the data pointed to by the specified Debug Directory entry and interprets them as PDB Checksum entry.
        /// </summary>
        /// <exception cref="ArgumentException"><paramref name="entry"/> is not a PDB Checksum entry.</exception>
        /// <exception cref="BadImageFormatException">Bad format of the data.</exception>
        /// <exception cref="IOException">IO error while reading from the underlying stream.</exception>
        /// <exception cref="InvalidOperationException">PE image not available.</exception>
        internal static PdbChecksumDebugDirectoryData ReadPdbChecksumDebugDirectoryData(this PEReader peReader, DebugDirectoryEntry entry)
        {
            if (entry.Type != PdbChecksumEntryType)
            {
                throw new ArgumentException("Unexpected debug directory entry type", nameof(entry));
            }

            var peImage = peReader.GetEntireImage();

            int dataOffset = peReader.IsLoadedImage ? entry.DataRelativeVirtualAddress : entry.DataPointer;
            var reader     = peImage.GetReader(dataOffset, entry.DataSize);

            int nameLength = reader.IndexOf(0);

            if (nameLength <= 0)
            {
                throw new BadImageFormatException("Invalid PDB Checksum data format");
            }

            string algorithmName = reader.ReadUTF8(nameLength);

            // NUL
            reader.Offset += 1;

            var checksum = reader.ReadBytes(reader.RemainingBytes).ToImmutableArray();

            if (checksum.Length == 0)
            {
                throw new BadImageFormatException("Invalid PDB Checksum data format");
            }

            return(new PdbChecksumDebugDirectoryData(algorithmName, checksum));
        }
示例#3
0
        private static unsafe byte[] GetEmbeddedResourceContents(PEReader peReader, ManifestResource resource)
        {
            if (!resource.Implementation.IsNil)
            {
                throw new ArgumentException("Resource is not embedded in the PE file.", "resource");
            }

            checked // arithmetic overflow here could cause AV
            {
                // Locate start and end of PE image in unmanaged memory.
                var block = peReader.GetEntireImage();
                int peImageSize = block.Length;
                byte* peImageStart = block.Pointer;
                byte* peImageEnd = peImageStart + peImageSize;
                Debug.Assert(peImageStart != null && peImageSize > 0);

                // Locate offset to resources within PE image.
                int offsetToResources;
                if (!peReader.PEHeaders.TryGetDirectoryOffset(peReader.PEHeaders.CorHeader.ResourcesDirectory, out offsetToResources))
                {
                    throw new InvalidDataException("Failed to get offset to resources in PE file.");
                }
                Debug.Assert(offsetToResources > 0);
                byte* resourceStart = peImageStart + offsetToResources + resource.Offset;

                // Get the length of the the resource from the first 4 bytes.
                if (resourceStart >= peImageEnd - sizeof(int))
                {
                    throw new InvalidDataException("resource offset out of bounds.");
                }
                int resourceLength = *(int*)(resourceStart);
                resourceStart += sizeof(int);
                if (resourceLength < 0 || resourceStart >= peImageEnd - resourceLength)
                {
                    throw new InvalidDataException("resource offset or length out of bounds.");
                }

                // TODO: Use UmanagedMemoryStream when available on core clr
                var buffer = new byte[resourceLength];
                for (int i = 0; i < resourceLength; i++)
                {
                    buffer[i] = *(resourceStart + i);
                }

                return buffer;
            }
        }
示例#4
0
 public void EntireImage_EagerLoad()
 {
     var peStream = new MemoryStream(TestResources.Misc.Members);
     using (var reader = new PEReader(peStream, PEStreamOptions.LeaveOpen | PEStreamOptions.PrefetchMetadata | PEStreamOptions.PrefetchEntireImage))
     {
         Assert.Equal(4608, reader.GetEntireImage().Length);
     }
 }
示例#5
0
        public void Metadata_EagerLoad()
        {
            var peStream = new MemoryStream(TestResources.Misc.Members);
            using (var reader = new PEReader(peStream, PEStreamOptions.LeaveOpen | PEStreamOptions.PrefetchMetadata))
            {
                var md = reader.GetMetadataReader();
                var method = md.GetMethodDefinition(MetadataTokens.MethodDefinitionHandle(1));
                Assert.Equal("MC1", md.GetString(method.Name));

                Assert.Throws<InvalidOperationException>(() => reader.GetEntireImage());
                Assert.Throws<InvalidOperationException>(() => reader.GetMethodBody(method.RelativeVirtualAddress));
            }
        }
示例#6
0
        public void FileShareDeleteCompatibility_Xplat()
        {
            var bytes = TestResources.MetadataTests.InterfaceAndClass.CSClasses01;
            var mvid = ReadMvid(new MemoryStream(bytes));

            var dir = Temp.CreateDirectory();
            var libSrc = dir.CreateFile("Lib.cs").WriteAllText("class C { }");
            var libDll = dir.CreateFile("Lib.dll").WriteAllBytes(bytes);
            var libPdb = dir.CreateFile("Lib.pdb").WriteAllBytes(bytes);

            var fsDll = new FileStream(libDll.Path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete);
            var fsPdb = new FileStream(libPdb.Path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete);

            var peDll = new PEReader(fsDll);
            var pePdb = new PEReader(fsPdb);

            // creates memory map view:
            var imageDll = peDll.GetEntireImage();
            var imagePdb = pePdb.GetEntireImage();

            var output = ProcessUtilities.RunAndGetOutput(s_CSharpCompilerExecutable, $"/target:library /debug:portable {libSrc.Path}", startFolder: dir.ToString());
            AssertEx.AssertEqualToleratingWhitespaceDifferences($@"
Microsoft (R) Visual C# Compiler version {s_compilerVersion}
Copyright (C) Microsoft Corporation. All rights reserved.", output);

            // reading original content from the memory map: 
            Assert.Equal(mvid, ReadMvid(new MemoryStream(imageDll.GetContent().ToArray())));
            Assert.Equal(mvid, ReadMvid(new MemoryStream(imagePdb.GetContent().ToArray())));
            
            // reading original content directly from the streams: 
            fsDll.Position = 0;
            fsPdb.Position = 0;
            Assert.Equal(mvid, ReadMvid(fsDll));
            Assert.Equal(mvid, ReadMvid(fsPdb));

            // reading new content from the file:
            using (var fsNewDll = File.OpenRead(libDll.Path))
            {
                Assert.NotEqual(mvid, ReadMvid(fsNewDll));
            }

            // Portable PDB metadata signature:
            AssertEx.Equal(new[] { (byte)'B', (byte)'S', (byte)'J', (byte)'B' }, ReadBytes(libPdb.Path, 4));

            // dispose PEReaders (they dispose the underlying file streams)
            peDll.Dispose();
            pePdb.Dispose();

            AssertEx.Equal(new[] { "Lib.cs", "Lib.dll", "Lib.pdb" }, Directory.GetFiles(dir.Path).Select(p => Path.GetFileName(p)).Order());

            // files can be deleted now:
            File.Delete(libSrc.Path);
            File.Delete(libDll.Path);
            File.Delete(libPdb.Path);

            // directory can be deleted (should be empty):
            Directory.Delete(dir.Path, recursive: false);
        }
        public static DynamicAnalysisDataReader TryCreateFromPE(PEReader peReader, string resourceName)
        {
            // TODO: review all range checks, better error messages

            var mdReader = peReader.GetMetadataReader();
            long offset = -1;
            foreach (var resourceHandle in mdReader.ManifestResources)
            {
                var resource = mdReader.GetManifestResource(resourceHandle);
                if (resource.Implementation.IsNil &&
                    resource.Attributes == ManifestResourceAttributes.Private &&
                    mdReader.StringComparer.Equals(resource.Name, resourceName))
                {
                    offset = resource.Offset;
                }
            }

            if (offset < 0)
            {
                return null;
            }

            var resourcesDir = peReader.PEHeaders.CorHeader.ResourcesDirectory;
            if (resourcesDir.Size < 0)
            {
                throw new BadImageFormatException();
            }

            int start;
            if (!peReader.PEHeaders.TryGetDirectoryOffset(resourcesDir, out start))
            {
                return null;
            }

            var peImage = peReader.GetEntireImage();
            if (start >= peImage.Length - resourcesDir.Size)
            {
                throw new BadImageFormatException();
            }

            byte* resourceStart = peImage.Pointer + start;
            int resourceSize = *(int*)resourceStart;
            if (resourceSize > resourcesDir.Size - sizeof(int))
            {
                throw new BadImageFormatException();
            }

            return new DynamicAnalysisDataReader(resourceStart + sizeof(int), resourceSize);
        }
示例#8
0
        /// <summary>
        /// </summary>
        /// <param name="relativeVirtualAddress">
        /// </param>
        /// <param name="peReader">
        /// </param>
        /// <returns>
        /// </returns>
        public byte[] GetFieldBody(int relativeVirtualAddress, PEReader peReader)
        {
            var peHeaders = peReader.PEHeaders;

            var containingSectionIndex = peHeaders.GetContainingSectionIndex(relativeVirtualAddress);
            if (containingSectionIndex < 0)
            {
                return null;
            }

            var num = relativeVirtualAddress - peHeaders.SectionHeaders[containingSectionIndex].VirtualAddress;
            var length = peHeaders.SectionHeaders[containingSectionIndex].VirtualSize - num;

            IntPtr pointer;
            int size;
            peReader.GetEntireImage(out pointer, out size);

            var reader = new BlobReader(pointer + peHeaders.SectionHeaders[containingSectionIndex].PointerToRawData + num, length);
            var bytes = reader.ReadBytes(length);

            return bytes;
        }