internal DataDirectory(PortableExecutableImage image, DataDirectories dataDirs, DataDirectoryType dirType, IMAGE_DATA_DIRECTORY dataDirectory, ulong imageBase) { _image = image; _type = dirType; _header = dataDirectory; _imageBase = imageBase; _sectionName = new Lazy <string>(DoGetSectionName); _section = new Lazy <Section>(DoGetSection); Directories = dataDirs; }
internal NTHeaders(PortableExecutableImage image, ulong headerOffset, ulong imageBase, FileHeader fileHeader, OptionalHeader optHeader, DataDirectories dataDirs) { _image = image; var size = (4U + fileHeader.Location.FileSize + optHeader.Location.FileSize + dataDirs.Location.FileSize).ToUInt32(); Location = new Location(image, headerOffset, headerOffset.ToUInt32(), imageBase + headerOffset, size, size); FileHeader = fileHeader; OptionalHeader = optHeader; DataDirectories = dataDirs; }
private async Task LoadAsync() { if (!_stream.CanSeek) { throw new PortableExecutableImageException(this, "Cannot seek in stream."); } if (!_stream.CanRead) { throw new PortableExecutableImageException(this, "Cannot read from stream."); } IMAGE_DOS_HEADER dosHeader; try { dosHeader = await _stream.ReadStructAsync <IMAGE_DOS_HEADER>(DOSHeader.Size).ConfigureAwait(false); } catch (Exception ex) { throw new PortableExecutableImageException(this, "Cannot read DOS header from stream.", ex); } if (dosHeader.e_magic != DOSHeader.DOS_MAGIC_MZ) { throw new PortableExecutableImageException(this, "Incorrect magic number specified in DOS header."); } if (dosHeader.e_lfanew == 0) { throw new PortableExecutableImageException(this, "No new header location specified in DOS header, most likely a 16-bit executable."); } if (dosHeader.e_lfanew >= (256 * (1024 * 1024))) { throw new PortableExecutableImageException(this, "New header location specified in MS-DOS header is beyond 256mb boundary (see RtlImageNtHeaderEx)."); } if (dosHeader.e_lfanew % 4 != 0) { throw new PortableExecutableImageException(this, "New header location specified in MS-DOS header is not properly aligned."); } if (dosHeader.e_lfanew < DOSHeader.Size) { throw new PortableExecutableImageException(this, "New header location specified is invalid."); } var stubOffset = DOSHeader.Size; var stubSize = dosHeader.e_lfanew - DOSHeader.Size; var stubRead = await _stream.SkipBytesAsync(stubSize).ConfigureAwait(false); if (stubRead < stubSize) { throw new PortableExecutableImageException(this, "Could not read DOS stub from stream."); } _stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); var ntOffset = _stream.Position; uint peSig; try { peSig = await _stream.ReadUInt32Async().ConfigureAwait(false); } catch (Exception ex) { throw new PortableExecutableImageException(this, "Could not read PE signature from stream.", ex); } if (peSig != NTHeaders.PE_MAGIC_MZ) { throw new PortableExecutableImageException(this, "Incorrect PE signature found in NT Header."); } IMAGE_FILE_HEADER fileHdr; try { fileHdr = await _stream.ReadStructAsync <IMAGE_FILE_HEADER>(FileHeader.Size).ConfigureAwait(false); } catch (Exception ex) { throw new PortableExecutableImageException(this, "Could not read NT Header from stream.", ex); } ushort magic = 0; try { magic = await _stream.ReadUInt16Async().ConfigureAwait(false); } catch (Exception ex) { throw new PortableExecutableImageException(this, "Could not read Optional Header magic number from stream.", ex); } Is32Bit = (magic == (ushort)MagicType.PE32); Is64Bit = (magic == (ushort)MagicType.PE32plus); if (!Is32Bit && !Is64Bit) { throw new PortableExecutableImageException(this, "Unknown PE type."); } byte[] optionalHeaderBytes; try { var optionalHeaderSize = (Is32Bit ? Utils.SizeOf <IMAGE_OPTIONAL_HEADER32>() : Utils.SizeOf <IMAGE_OPTIONAL_HEADER64>()); optionalHeaderBytes = await _stream.ReadBytesAsync(optionalHeaderSize).ConfigureAwait(false); } catch (Exception ex) { throw new PortableExecutableImageException(this, "Could not read Optional Header from stream.", ex); } IMAGE_OPTIONAL_HEADER32 optionalHeader32 = new IMAGE_OPTIONAL_HEADER32(); IMAGE_OPTIONAL_HEADER64 optionalHeader64 = new IMAGE_OPTIONAL_HEADER64(); var dirCount = 0; if (Is32Bit) { optionalHeader32 = Utils.Read <IMAGE_OPTIONAL_HEADER32>(optionalHeaderBytes); dirCount = optionalHeader32.NumberOfRvaAndSizes.ToInt32(); } else { optionalHeader64 = Utils.Read <IMAGE_OPTIONAL_HEADER64>(optionalHeaderBytes); dirCount = optionalHeader64.NumberOfRvaAndSizes.ToInt32(); } var dataDirs = new IMAGE_DATA_DIRECTORY[dirCount]; var dataDirSize = Utils.SizeOf <IMAGE_DATA_DIRECTORY>(); for (var i = 0; i < dirCount; i++) { try { dataDirs[i] = await _stream.ReadStructAsync <IMAGE_DATA_DIRECTORY>(dataDirSize).ConfigureAwait(false); } catch (Exception ex) { throw new PortableExecutableImageException(this, "Could not read data directory from stream.", ex); } } var sectionTableEntrySize = Utils.SizeOf <IMAGE_SECTION_HEADER>(); var sectionTable = new IMAGE_SECTION_HEADER[fileHdr.NumberOfSections]; for (var i = 0; i < fileHdr.NumberOfSections; i++) { try { sectionTable[i] = await _stream.ReadStructAsync <IMAGE_SECTION_HEADER>(sectionTableEntrySize).ConfigureAwait(false); } catch (Exception ex) { throw new PortableExecutableImageException(this, "Could not read section table entry from stream.", ex); } } IsCLR = false; var clrIndex = (int)DataDirectoryType.CLRRuntimeHeader; if (clrIndex >= 0 && clrIndex <= (dataDirs.Length - 1)) { var clrDirectory = dataDirs[clrIndex]; if (clrDirectory.VirtualAddress > 0 && clrDirectory.Size > 0) { IsCLR = true; } } IsSigned = false; var certIndex = (int)DataDirectoryType.CertificateTable; if (certIndex >= 0 && certIndex <= (dataDirs.Length - 1)) { var certDirectory = dataDirs[certIndex]; if (certDirectory.VirtualAddress > 0 && certDirectory.Size > 0) { IsSigned = true; } } var imageBase = (Is32Bit ? optionalHeader32.ImageBase : optionalHeader64.ImageBase); DOSHeader = new DOSHeader(this, dosHeader, imageBase); DOSStub = new DOSStub(this, stubOffset.ToUInt64(), stubSize.ToUInt32(), imageBase); var fileHeader = new FileHeader(this, fileHdr, DOSStub.Location.FileOffset + DOSStub.Location.FileSize + 4, imageBase); OptionalHeader optionalHeader; if (Is32Bit) { optionalHeader = new OptionalHeader32(this, optionalHeader32, fileHeader.Location.FileOffset + fileHeader.Location.FileSize, imageBase, magic); } else { optionalHeader = new OptionalHeader64(this, optionalHeader64, fileHeader.Location.FileOffset + fileHeader.Location.FileSize, imageBase, magic); } var dataDirectories = new DataDirectories(this, optionalHeader, dataDirs); NTHeaders = new NTHeaders(this, ntOffset.ToUInt64(), imageBase, fileHeader, optionalHeader, dataDirectories); SectionTable = new SectionTable(this, sectionTable, NTHeaders.Location.FileOffset + NTHeaders.Location.FileSize, imageBase); Sections = new Sections(this, SectionTable); }