private ExecutableImage(Stream sourceStream, bool ownStream) { _disposed = false; _stream = sourceStream; _own_stream = ownStream; _calc = null; _dos_header = null; _dos_stub = null; _nt_headers = null; _section_table = null; _sections = null; _is_32bit = false; _is_64bit = false; _is_clr = false; _is_signed = false; Load(); }
private ExeReader(Stream sourceStream, bool ownStream) { if (!sourceStream.CanRead) throw new IOException("Cannot read from stream."); if (!sourceStream.CanSeek) throw new IOException("Cannot seek in stream."); _disposed = false; _stream = sourceStream; _own_stream = ownStream; _dos_header = null; _dos_stub = null; _nt_headers = null; _section_table = null; _sections = null; is_32bit = false; is_64bit = false; is_clr = false; }
private void Load() { string error_message = String.Empty; PreloadedInformation preload_info = TryPreload(_stream,out error_message); if (preload_info == null) throw new ExecutableImageException(error_message); ulong image_base = 0; if (preload_info.OptHeader32 != null) image_base = preload_info.OptHeader32.Value.ImageBase; if (preload_info.OptHeader64 != null) image_base = preload_info.OptHeader64.Value.ImageBase; _dos_header = new DOSHeader(this,preload_info.DOSHeader,image_base); _dos_stub = new DOSStub(this,preload_info.StubOffset,preload_info.StubSize,image_base); FileHeader file_header = new FileHeader(this,preload_info.FileHeader,_dos_stub.Location.FileOffset + _dos_stub.Location.FileSize + 4,image_base); OptionalHeader opt_header; if (preload_info.Is32Bit) { opt_header = new OptionalHeader32(this,preload_info.OptHeader32.Value,file_header.Location.FileOffset + file_header.Location.FileSize,image_base); } else { opt_header = new OptionalHeader64(this,preload_info.OptHeader64.Value,file_header.Location.FileOffset + file_header.Location.FileSize,image_base); } DataDirectoryCollection data_dirs = new DataDirectoryCollection(this,opt_header,preload_info.DataDirectories); _nt_headers = new NTHeaders(this,file_header.Location.FileOffset - 4,image_base,file_header,opt_header,data_dirs); _section_table = new SectionTable(this,preload_info.SectionHeaders,_nt_headers.Location.FileOffset + _nt_headers.Location.FileSize,image_base); _sections = new Sections(_section_table); _is_32bit = preload_info.Is32Bit; _is_64bit = preload_info.Is64Bit; _is_clr = preload_info.IsCLR; _is_signed = preload_info.IsSigned; }
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); }
private FileHeader LoadFileHeader(DOSHeader dosHeader) { IMAGE_FILE_HEADER native_file_header = Utils.Read<IMAGE_FILE_HEADER>(_stream,FileHeader.Size); StreamLocation location = new StreamLocation(dosHeader.FileAddressNewHeader + 4,FileHeader.Size); return new FileHeader(this,native_file_header,location); }
private void LoadDOSHeader() { _stream.Seek(0,SeekOrigin.Begin); IMAGE_DOS_HEADER native_dos_header = Utils.Read<IMAGE_DOS_HEADER>(_stream,DOSHeader.Size); if (native_dos_header.e_magic != DOSHeader.DOS_MAGIC_MZ) throw new ExeReaderException("Incorrect magic number specified in MS-DOS header."); if (native_dos_header.e_lfanew == 0) throw new ExeReaderException("No new header location specified in MS-DOS header, most likely a 16-bit executable."); if (native_dos_header.e_lfanew >= (256 * (1024 * 1024))) throw new ExeReaderException("New header location specified in MS-DOS header is beyond 256mb boundary (see RtlImageNtHeaderEx)."); if (native_dos_header.e_lfanew % 4 != 0) throw new ExeReaderException("New header location specified in MS-DOS header is not properly aligned."); if (native_dos_header.e_lfanew < DOSHeader.Size) throw new ExeReaderException("New header location specified is invalid."); StreamLocation location = new StreamLocation(0,DOSHeader.Size); _dos_header = new DOSHeader(this,native_dos_header,location); }