private static PreloadedInformation TryPreload(Stream stream, out string errorMessage) { errorMessage = String.Empty; if (!stream.CanSeek) { errorMessage = "Cannot seek in stream."; return null; } if (!stream.CanRead) { errorMessage = "Cannot read from stream."; return null; } stream.Seek(0,SeekOrigin.Begin); IMAGE_DOS_HEADER dos_header = Utils.Read<IMAGE_DOS_HEADER>(stream,DOSHeader.Size); if (dos_header.e_magic != DOSHeader.DOS_MAGIC_MZ) { errorMessage = "Incorrect magic number specified in MS-DOS header."; return null; } if (dos_header.e_lfanew == 0) { errorMessage = "No new header location specified in MS-DOS header, most likely a 16-bit executable."; return null; } if (dos_header.e_lfanew >= (256 * (1024 * 1024))) { errorMessage = "New header location specified in MS-DOS header is beyond 256mb boundary (see RtlImageNtHeaderEx)."; return null; } if (dos_header.e_lfanew % 4 != 0) { errorMessage = "New header location specified in MS-DOS header is not properly aligned."; return null; } if (dos_header.e_lfanew < DOSHeader.Size) { errorMessage = "New header location specified is invalid."; return null; } long stub_offset = DOSHeader.Size; int stub_size = dos_header.e_lfanew - DOSHeader.Size; if ((stub_offset + stub_size) > stream.Length) { errorMessage = "Cannot read beyond end of stream."; return null; } stream.Seek(dos_header.e_lfanew,SeekOrigin.Begin); uint pe_sig = Utils.ReadUInt32(stream); if (pe_sig != NTHeaders.PE_MAGIC_MZ) { errorMessage = "Incorrect PE signature found in NT Header."; return null; } if ((stream.Position + FileHeader.Size) > stream.Length) { errorMessage = "Cannot read beyond end of stream."; return null; } IMAGE_FILE_HEADER file_header = Utils.Read<IMAGE_FILE_HEADER>(stream,FileHeader.Size); ushort magic = 0; long position = stream.Position; try { magic = Utils.ReadUInt16(stream); } finally { stream.Seek(position, SeekOrigin.Begin); } bool is_32bit = (magic == (ushort)MagicType.PE32); bool is_64bit = (magic == (ushort)MagicType.PE32plus); if (!is_32bit && !is_64bit) throw new ExecutableImageException("Unknown PE type."); if ((stream.Position + file_header.SizeOfOptionalHeader) > stream.Length) { errorMessage = "Cannot read beyond end of stream."; return null; } IMAGE_OPTIONAL_HEADER32 opt_header_32 = new IMAGE_OPTIONAL_HEADER32(); IMAGE_OPTIONAL_HEADER64 opt_header_64 = new IMAGE_OPTIONAL_HEADER64(); int data_dir_count = 0; if (!is_64bit) { opt_header_32 = Utils.Read<IMAGE_OPTIONAL_HEADER32>(stream,OptionalHeader.Size32); data_dir_count = Convert.ToInt32(opt_header_32.NumberOfRvaAndSizes); } else { opt_header_64 = Utils.Read<IMAGE_OPTIONAL_HEADER64>(stream,OptionalHeader.Size64); data_dir_count = Convert.ToInt32(opt_header_64.NumberOfRvaAndSizes); } IMAGE_DATA_DIRECTORY[] data_directories = new IMAGE_DATA_DIRECTORY[data_dir_count]; for(int i = 0; i < data_dir_count; i++) data_directories[i] = Utils.Read<IMAGE_DATA_DIRECTORY>(stream,Utils.SizeOf<IMAGE_DATA_DIRECTORY>()); long section_table_size = Utils.SizeOf<IMAGE_SECTION_HEADER>() * file_header.NumberOfSections; if ((stream.Position + section_table_size) > stream.Length) { errorMessage = "Cannot read beyond end of stream."; return null; } IMAGE_SECTION_HEADER[] section_table_headers = new IMAGE_SECTION_HEADER[file_header.NumberOfSections]; for(int i = 0; i < file_header.NumberOfSections; i++) section_table_headers[i] = Utils.Read<IMAGE_SECTION_HEADER>(stream,Utils.SizeOf<IMAGE_SECTION_HEADER>()); foreach(IMAGE_SECTION_HEADER section_header in section_table_headers) { if ((section_header.PointerToRawData + section_header.SizeOfRawData) > stream.Length) { errorMessage = "Section data is beyond end of stream."; return null; } stream.Seek(section_header.PointerToRawData,SeekOrigin.Begin); } bool is_clr = false; int clr_dir_index = (int)DataDirectoryType.CLRRuntimeHeader; if (clr_dir_index >= 0 && clr_dir_index <= (data_directories.Length - 1)) { IMAGE_DATA_DIRECTORY clr_dir = data_directories[clr_dir_index]; if (clr_dir.VirtualAddress > 0 && clr_dir.Size > 0) is_clr = true; } bool is_signed = false; int cert_dir_index = (int)DataDirectoryType.CertificateTable; if (cert_dir_index >= 0 && cert_dir_index <= (data_directories.Length - 1)) { IMAGE_DATA_DIRECTORY cert_dir = data_directories[cert_dir_index]; if (cert_dir.VirtualAddress > 0 && cert_dir.Size > 0) is_signed = true; } PreloadedInformation info = new PreloadedInformation() { DOSHeader = dos_header, StubOffset = Convert.ToUInt64(stub_offset), StubSize = Convert.ToUInt32(stub_size), FileHeader = file_header, OptHeader32 = opt_header_32, OptHeader64 = opt_header_64, DataDirectories = data_directories, SectionHeaders = section_table_headers, Is32Bit = is_32bit, Is64Bit = is_64bit, IsCLR = is_clr, IsSigned = is_signed }; return info; }
internal OptionalHeader32(ExecutableImage exeReader, IMAGE_OPTIONAL_HEADER32 optHeader, ulong headerOffset, ulong imageBase) : base(exeReader,headerOffset,Convert.ToUInt32(OptionalHeader.Size32),imageBase) { header = optHeader; }
private static bool Validate(Stream stream, out string errorMessage) { errorMessage = String.Empty; if (!stream.CanSeek) { errorMessage = "Cannot seek in stream."; return false; } if (!stream.CanRead) { errorMessage = "Cannot read from stream."; return false; } stream.Seek(0,SeekOrigin.Begin); IMAGE_DOS_HEADER dos_header = Utils.Read<IMAGE_DOS_HEADER>(stream,DOSHeader.Size); if (dos_header.e_magic != DOSHeader.DOS_MAGIC_MZ) { errorMessage = "Incorrect magic number specified in MS-DOS header."; return false; } if (dos_header.e_lfanew == 0) { errorMessage = "No new header location specified in MS-DOS header, most likely a 16-bit executable."; return false; } if (dos_header.e_lfanew >= (256 * (1024 * 1024))) { errorMessage = "New header location specified in MS-DOS header is beyond 256mb boundary (see RtlImageNtHeaderEx)."; return false; } if (dos_header.e_lfanew % 4 != 0) { errorMessage = "New header location specified in MS-DOS header is not properly aligned."; return false; } if (dos_header.e_lfanew < DOSHeader.Size) { errorMessage = "New header location specified is invalid."; return false; } long stub_offset = DOSHeader.Size; int stub_size = dos_header.e_lfanew - DOSHeader.Size; if ((stub_offset + stub_size) > stream.Length) { errorMessage = "Cannot read beyond end of stream."; return false; } stream.Seek(dos_header.e_lfanew,SeekOrigin.Begin); uint pe_sig = Utils.ReadUInt32(stream); if (pe_sig != NTHeaders.PE_MAGIC_MZ) { errorMessage = "Incorrect PE signature found in NT Header."; return false; } if ((stream.Position + FileHeader.Size) > stream.Length) { errorMessage = "Cannot read beyond end of stream."; return false; } IMAGE_FILE_HEADER file_header = Utils.Read<IMAGE_FILE_HEADER>(stream,FileHeader.Size); CharacteristicsType characteristics = (CharacteristicsType)file_header.Characteristics; bool is_32bit = ((characteristics & CharacteristicsType.Supports32Bit) == CharacteristicsType.Supports32Bit); bool is_64bit = !is_32bit; if ((stream.Position + file_header.SizeOfOptionalHeader) > stream.Length) { errorMessage = "Cannot read beyond end of stream."; return false; } IMAGE_OPTIONAL_HEADER32 opt_header_32 = new IMAGE_OPTIONAL_HEADER32(); IMAGE_OPTIONAL_HEADER64 opt_header_64 = new IMAGE_OPTIONAL_HEADER64(); if (!is_64bit) { opt_header_32 = Utils.Read<IMAGE_OPTIONAL_HEADER32>(stream,OptionalHeader.Size32); } else { opt_header_64 = Utils.Read<IMAGE_OPTIONAL_HEADER64>(stream,OptionalHeader.Size64); } long section_table_size = SectionTableEntry.Size * file_header.NumberOfSections; if ((stream.Position + section_table_size) > stream.Length) { errorMessage = "Cannot read beyond end of stream."; return false; } List<IMAGE_SECTION_HEADER> section_table_headers = new List<IMAGE_SECTION_HEADER>(); for(int i = 0; i < file_header.NumberOfSections; i++) { IMAGE_SECTION_HEADER header = Utils.Read<IMAGE_SECTION_HEADER>(stream,SectionTableEntry.Size); section_table_headers.Add(header); } foreach(IMAGE_SECTION_HEADER section_header in section_table_headers) { if ((section_header.PointerToRawData + section_header.SizeOfRawData) > stream.Length) { StringBuilder builder = new StringBuilder(); foreach(char c in section_header.Name) { if (c == '\0') break; builder.Append(c); } errorMessage = String.Format("Section {0} data is beyond end of stream.",builder.ToString()); return false; } stream.Seek(section_header.PointerToRawData,SeekOrigin.Begin); } return true; }
internal OptionalHeader32(ExeReader exeReader, IMAGE_OPTIONAL_HEADER32 optHeader, StreamLocation streamLoc) : base(exeReader,streamLoc) { header = optHeader; List<DataDirectory> dirs = new List<DataDirectory>(); dirs.AddRange(new DataDirectory[] { new DataDirectory(DataDirectoryType.ExportTable,header.ExportTable), new DataDirectory(DataDirectoryType.ImportTable,header.ImportTable), new DataDirectory(DataDirectoryType.ResourceTable,header.ResourceTable), new DataDirectory(DataDirectoryType.ExceptionTable,header.ExceptionTable), new DataDirectory(DataDirectoryType.CertificateTable,header.CertificateTable), new DataDirectory(DataDirectoryType.BaseRelocationTable,header.BaseRelocationTable), new DataDirectory(DataDirectoryType.Debug,header.Debug), new DataDirectory(DataDirectoryType.Architecture,header.Architecture), new DataDirectory(DataDirectoryType.GlobalPtr,header.GlobalPtr), new DataDirectory(DataDirectoryType.TLSTable,header.TLSTable), new DataDirectory(DataDirectoryType.LoadConfigTable,header.LoadConfigTable), new DataDirectory(DataDirectoryType.BoundImport,header.BoundImport), new DataDirectory(DataDirectoryType.ImportAddressTable,header.IAT), new DataDirectory(DataDirectoryType.DelayImportDescriptor,header.DelayImportDescriptor), new DataDirectory(DataDirectoryType.CLRRuntimeHeader,header.CLRRuntimeHeader) }); long dir_size = 16 * DataDirectories.EntrySize; StreamLocation location = new StreamLocation((streamLoc.Offset + streamLoc.Size) - dir_size,dir_size); data_dirs = new DataDirectories(this,location,dirs.Where(dir => dir.DirectoryType != DataDirectoryType.None).ToDictionary(dir => dir.DirectoryType)); }
private OptionalHeader LoadOptionalHeader(FileHeader fileHeader) { CharacteristicsType characteristics = fileHeader.GetCharacteristics(); bool is_x64 = !((characteristics & CharacteristicsType.Supports32Bit) == CharacteristicsType.Supports32Bit); IMAGE_OPTIONAL_HEADER32 opt_header_32 = new IMAGE_OPTIONAL_HEADER32(); IMAGE_OPTIONAL_HEADER64 opt_header_64 = new IMAGE_OPTIONAL_HEADER64(); StreamLocation location = null; OptionalHeader opt_header = null; if (!is_x64) { opt_header_32 = Utils.Read<IMAGE_OPTIONAL_HEADER32>(_stream,OptionalHeader.Size32); location = new StreamLocation(fileHeader.Location.Offset + fileHeader.Location.Size,OptionalHeader.Size32); opt_header = new OptionalHeader32(this,opt_header_32,location); } else { opt_header_64 = Utils.Read<IMAGE_OPTIONAL_HEADER64>(_stream,OptionalHeader.Size64); location = new StreamLocation(fileHeader.Location.Offset + fileHeader.Location.Size,OptionalHeader.Size64); opt_header = new OptionalHeader64(this,opt_header_64,location); } return opt_header; }