Ejemplo n.º 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;
        }
Ejemplo n.º 2
0
 internal OptionalHeader32(ExecutableImage exeReader, IMAGE_OPTIONAL_HEADER32 optHeader, ulong headerOffset, ulong imageBase)
     : base(exeReader,headerOffset,Convert.ToUInt32(OptionalHeader.Size32),imageBase)
 {
     header = optHeader;
 }
Ejemplo n.º 3
0
        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;
        }
Ejemplo n.º 4
0
        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));
        }
Ejemplo n.º 5
0
        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;
        }