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);
        }
Beispiel #2
0
        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;
        }
Beispiel #3
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;
        }