Example #1
0
        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;
        }
Example #2
0
 internal CLRDataDirectory(IMAGE_DATA_DIRECTORY dataDirectory)
 {
     data_dir = dataDirectory;
 }