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