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 CLRDataDirectory(IMAGE_DATA_DIRECTORY dataDirectory) { data_dir = dataDirectory; }