Exemple #1
0
        internal static async Task <ExceptionTable> GetAsync(PortableExecutableImage image, DataDirectory dataDirectory, Location location)
        {
            var calc   = image.GetCalculator();
            var stream = image.GetStream();
            var offset = calc.RVAToOffset(dataDirectory.VirtualAddress);
            var rva    = dataDirectory.VirtualAddress;

            stream.Seek(offset.ToInt64(), SeekOrigin.Begin);

            var entrySize = Utils.SizeOf <IMAGE_RUNTIME_FUNCTION_64>();
            var entries   = new List <ExceptionTableEntry>();

            while (true)
            {
                var entryData = await stream.ReadStructAsync <IMAGE_RUNTIME_FUNCTION_64>(entrySize).ConfigureAwait(false);

                if (entryData.StartAddress == 0 && entryData.EndAddress == 0)
                {
                    break;
                }

                var entryLocation = new Location(image, offset, rva, image.NTHeaders.OptionalHeader.ImageBase + rva, entrySize.ToUInt32(), entrySize.ToUInt32());
                var entry         = new ExceptionTableEntry64(image, entryLocation, entryData);

                entries.Add(entry);

                offset += entrySize.ToUInt32();
                rva    += entrySize.ToUInt32();
            }

            var table = new ExceptionTable64(image, dataDirectory, location, entries.ToArray());

            return(table);
        }
Exemple #2
0
        private Section GetSection(uint pageRVA)
        {
            var calc    = _image.GetCalculator();
            var section = calc.RVAToSection(pageRVA);

            return(section);
        }
Exemple #3
0
        public static async Task <CLR> GetAsync(PortableExecutableImage image)
        {
            if (!image.NTHeaders.DataDirectories.Exists(DataDirectoryType.CLRRuntimeHeader))
            {
                return(null);
            }

            var dataDirectory = image.NTHeaders.DataDirectories[DataDirectoryType.CLRRuntimeHeader];

            if (DataDirectory.IsNullOrEmpty(dataDirectory))
            {
                return(null);
            }

            var calc       = image.GetCalculator();
            var section    = calc.RVAToSection(dataDirectory.VirtualAddress);
            var fileOffset = calc.RVAToOffset(section, dataDirectory.VirtualAddress);
            var imageBase  = image.NTHeaders.OptionalHeader.ImageBase;
            var location   = new Location(image, fileOffset, dataDirectory.VirtualAddress, imageBase + dataDirectory.VirtualAddress, dataDirectory.Size, dataDirectory.Size, section);
            var header     = await CLRHeader.GetAsync(image, location).ConfigureAwait(false);

            var metaData = await CLRMetaData.GetAsync(image, header).ConfigureAwait(false);

            return(new CLR(image, dataDirectory, location, header, metaData));
        }
Exemple #4
0
        public static async Task <CLRMetaDataStreamTable> LoadAsync(PortableExecutableImage image, CLRMetaDataHeader header)
        {
            try
            {
                var calc      = image.GetCalculator();
                var imageBase = image.NTHeaders.OptionalHeader.ImageBase;
                var offset    = header.Location.FileOffset + header.Location.FileSize;
                var rva       = calc.OffsetToRVA(offset);
                var va        = imageBase + rva;
                var entries   = await LoadTableAsync(image, header, offset, imageBase).ConfigureAwait(false);

                ulong size = 0;

                foreach (var strm in entries)
                {
                    size += strm.Location.FileSize;
                }

                var section  = calc.RVAToSection(rva);
                var location = new Location(image, offset, rva, va, size, size, section);

                return(new CLRMetaDataStreamTable(image, location, entries));
            }
            catch (Exception ex)
            {
                throw new PortableExecutableImageException(image, "Could not read CLR meta-data streams table from stream.", ex);
            }
        }
Exemple #5
0
        public static async Task <ExceptionTable> GetAsync(PortableExecutableImage image)
        {
            if (!image.NTHeaders.DataDirectories.Exists(DataDirectoryType.ExceptionTable))
            {
                return(null);
            }

            var dataDirectory = image.NTHeaders.DataDirectories[DataDirectoryType.ExceptionTable];

            if (DataDirectory.IsNullOrEmpty(dataDirectory))
            {
                return(null);
            }

            var            calc       = image.GetCalculator();
            var            section    = calc.RVAToSection(dataDirectory.VirtualAddress);
            var            fileOffset = calc.RVAToOffset(section, dataDirectory.VirtualAddress);
            var            imageBase  = image.NTHeaders.OptionalHeader.ImageBase;
            var            location   = new Location(image, fileOffset, dataDirectory.VirtualAddress, imageBase + dataDirectory.VirtualAddress, dataDirectory.Size, dataDirectory.Size, section);
            ExceptionTable table;

            if (image.Is64Bit)
            {
                table = await ExceptionTable64.GetAsync(image, dataDirectory, location).ConfigureAwait(false);
            }
            else
            {
                table = await ExceptionTable32.GetAsync(image, dataDirectory, location).ConfigureAwait(false);
            }

            return(table);
        }
Exemple #6
0
        public static async Task <ResourceDirectory> GetAsync(PortableExecutableImage image)
        {
            if (!image.NTHeaders.DataDirectories.Exists(DataDirectoryType.ResourceTable))
            {
                return(null);
            }

            var dataDirectory = image.NTHeaders.DataDirectories[DataDirectoryType.ResourceTable];

            if (DataDirectory.IsNullOrEmpty(dataDirectory))
            {
                return(null);
            }

            var calc      = image.GetCalculator();
            var rva       = dataDirectory.VirtualAddress;
            var va        = image.NTHeaders.OptionalHeader.ImageBase + rva;
            var offset    = calc.RVAToOffset(rva);
            var size      = Utils.SizeOf <IMAGE_RESOURCE_DIRECTORY>().ToUInt32();
            var section   = calc.RVAToSection(rva);
            var location  = new Location(image, offset, rva, va, size, size, section);
            var directory = new ResourceDirectory(image, dataDirectory, location, null);

            await directory.LoadAsync().ConfigureAwait(false);

            return(directory);
        }
Exemple #7
0
        public static async Task <TLSDirectory> GetAsync(PortableExecutableImage image)
        {
            if (!image.NTHeaders.DataDirectories.Exists(DataDirectoryType.TLSTable))
            {
                return(null);
            }

            var dataDirectory = image.NTHeaders.DataDirectories[DataDirectoryType.TLSTable];

            if (DataDirectory.IsNullOrEmpty(dataDirectory))
            {
                return(null);
            }

            var calc       = image.GetCalculator();
            var section    = calc.RVAToSection(dataDirectory.VirtualAddress);
            var fileOffset = calc.RVAToOffset(section, dataDirectory.VirtualAddress);
            var imageBase  = image.NTHeaders.OptionalHeader.ImageBase;
            var location   = new Location(image, fileOffset, dataDirectory.VirtualAddress, imageBase + dataDirectory.VirtualAddress, dataDirectory.Size, dataDirectory.Size, section);
            var stream     = image.GetStream();

            stream.Seek(fileOffset.ToInt64(), SeekOrigin.Begin);

            TLSDirectory directory = null;

            if (image.Is32Bit)
            {
                IMAGE_TLS_DIRECTORY32 config;

                try
                {
                    config = await stream.ReadStructAsync <IMAGE_TLS_DIRECTORY32>().ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    throw new PortableExecutableImageException(image, "Could not load TLS Directory from stream.", ex);
                }

                directory = new TLSDirectory(image, dataDirectory, location, config);
            }
            else
            {
                IMAGE_TLS_DIRECTORY64 config;

                try
                {
                    config = await stream.ReadStructAsync <IMAGE_TLS_DIRECTORY64>().ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    throw new PortableExecutableImageException(image, "Could not load TLS Directory from stream.", ex);
                }

                directory = new TLSDirectory(image, dataDirectory, location, config);
            }

            return(directory);
        }
Exemple #8
0
        public static async Task <Exports> GetAsync(PortableExecutableImage image, ExportDirectory directory, ExportTable <uint> functionAddresses, ExportTable <uint> nameAddresses, ExportTable <ushort> ordinals)
        {
            var calc           = image.GetCalculator();
            var stream         = image.GetStream();
            var dataDirectory  = image.NTHeaders.DataDirectories[DataDirectoryType.ExportTable];
            var infos          = new List <ExportInfo>();
            var currentOrdinal = directory.Base;

            foreach (var address in functionAddresses)
            {
                var info = new ExportInfo()
                {
                    Address = address,
                    Ordinal = currentOrdinal
                };

                if (address >= dataDirectory.VirtualAddress && address <= (dataDirectory.VirtualAddress + dataDirectory.Size))
                {
                    var offset = calc.RVAToOffset(address).ToInt64();

                    info.ForwardName = await GetStringAsync(stream, offset).ConfigureAwait(false);
                }

                infos.Add(info);

                currentOrdinal++;
            }

            for (var i = 0; i < nameAddresses.Count; i++)
            {
                var nameAddress = nameAddresses[i];
                var ordinal     = ordinals[i];
                var offset      = calc.RVAToOffset(nameAddress).ToInt64();
                var info        = infos[ordinal];

                info.NameAddress = nameAddress;
                info.Name        = await GetStringAsync(stream, offset);
            }

            var exports = new List <Export>(infos.Count);

            foreach (var info in infos)
            {
                var export = new Export(info.Address, info.Name, info.Ordinal, info.ForwardName);

                exports.Add(export);
            }

            var result = new Exports(exports.OrderBy(e => e.Ordinal), directory, functionAddresses, nameAddresses, ordinals);

            return(result);
        }
Exemple #9
0
        internal CLRMetaDataStream(PortableExecutableImage image, Location mdLocation, ulong imageBase, CLRMetaDataStreamTableEntry tableEntry)
        {
            _image = image;

            var calc   = image.GetCalculator();
            var offset = mdLocation.FileOffset + tableEntry.Offset;
            var rva    = calc.OffsetToRVA(offset);
            var va     = imageBase + rva;

            Location   = new Location(image, offset, rva, va, tableEntry.Size, tableEntry.Size);
            TableEntry = tableEntry;
            Name       = tableEntry.Name;
        }
Exemple #10
0
        protected internal ImportHintNameEntryBase(PortableExecutableImage image, ulong offset, uint size, ushort entryHint, string entryName, bool isPadded, bool isDelayed)
        {
            _image = image;

            var calc = image.GetCalculator();
            var rva  = calc.OffsetToRVA(offset);
            var va   = image.NTHeaders.OptionalHeader.ImageBase + rva;

            Location  = new Location(image, offset, rva, va, size, size);
            Hint      = entryHint;
            Name      = entryName;
            IsPadded  = isPadded;
            IsDelayed = isDelayed;
        }
Exemple #11
0
        protected internal ImportAddressTableBase(PortableExecutableImage image, uint rva, ulong[] entries, ImportDirectoryEntryBase directoryEntry, bool isDelayed)
        {
            var calc      = image.GetCalculator();
            var imageBase = image.NTHeaders.OptionalHeader.ImageBase;
            var va        = imageBase + rva;
            var offset    = calc.RVAToOffset(rva);
            var size      = (entries.Length * (image.Is64Bit ? sizeof(ulong) : sizeof(uint))).ToUInt64();
            var section   = calc.RVAToSection(rva);

            _image   = image;
            _entries = BuildEntries(image, offset, entries);

            Location       = new Location(image, offset, rva, va, size, size, section);
            Count          = _entries.Length;
            DirectoryEntry = directoryEntry;
            IsDelayed      = isDelayed;
        }
        protected internal ImportAddressTableEntryBase(PortableExecutableImage image, ulong entryOffset, ulong entryValue, uint entryAddress, ushort entryOrdinal, bool isOrdinal, bool isDelayed)
        {
            _image = image;

            var calc      = image.GetCalculator();
            var rva       = calc.OffsetToRVA(entryOffset);
            var imageBase = image.NTHeaders.OptionalHeader.ImageBase;
            var va        = imageBase + rva;
            var size      = (image.Is64Bit ? sizeof(ulong) : sizeof(uint)).ToUInt64();

            Location  = new Location(image, entryOffset, rva, va, size, size);
            Value     = entryValue;
            Address   = entryAddress;
            Ordinal   = entryOrdinal;
            IsOrdinal = isOrdinal;
            IsDelayed = isDelayed;
        }
Exemple #13
0
        public static async Task <DebugDirectory> GetAsync(PortableExecutableImage image)
        {
            if (!image.NTHeaders.DataDirectories.Exists(DataDirectoryType.Debug))
            {
                return(null);
            }

            var dataDirectory = image.NTHeaders.DataDirectories[DataDirectoryType.Debug];

            if (DataDirectory.IsNullOrEmpty(dataDirectory))
            {
                return(null);
            }

            try
            {
                var calc       = image.GetCalculator();
                var section    = calc.RVAToSection(dataDirectory.VirtualAddress);
                var fileOffset = calc.RVAToOffset(section, dataDirectory.VirtualAddress);
                var imageBase  = image.NTHeaders.OptionalHeader.ImageBase;
                var location   = new Location(image, fileOffset, dataDirectory.VirtualAddress, imageBase + dataDirectory.VirtualAddress, dataDirectory.Size, dataDirectory.Size, section);
                var stream     = image.GetStream();

                stream.Seek(fileOffset.ToInt32(), SeekOrigin.Begin);

                var entrySize  = Utils.SizeOf <IMAGE_DEBUG_DIRECTORY>();
                var entryCount = dataDirectory.Size / entrySize;
                var entries    = new Tuple <ulong, IMAGE_DEBUG_DIRECTORY> [entryCount];

                for (var i = 0; i < entryCount; i++)
                {
                    var entry = await stream.ReadStructAsync <IMAGE_DEBUG_DIRECTORY>(entrySize).ConfigureAwait(false);

                    entries[i] = new Tuple <ulong, IMAGE_DEBUG_DIRECTORY>(fileOffset, entry);
                }

                var directoryEntries = LoadEntries(image, entrySize, entries);
                var directory        = new DebugDirectory(image, dataDirectory, location, directoryEntries);

                return(directory);
            }
            catch (Exception ex)
            {
                throw new PortableExecutableImageException(image, "Could not read debug directory from stream.", ex);
            }
        }
Exemple #14
0
        public static async Task <ExportDirectory> GetAsync(PortableExecutableImage image)
        {
            if (!image.NTHeaders.DataDirectories.Exists(DataDirectoryType.ExportTable))
            {
                return(null);
            }

            var dataDirectory = image.NTHeaders.DataDirectories[DataDirectoryType.ExportTable];

            if (DataDirectory.IsNullOrEmpty(dataDirectory))
            {
                return(null);
            }

            try
            {
                var calc      = image.GetCalculator();
                var rva       = dataDirectory.VirtualAddress;
                var imageBase = image.NTHeaders.OptionalHeader.ImageBase;
                var va        = imageBase + rva;
                var section   = calc.RVAToSection(rva);
                var offset    = calc.RVAToOffset(section, rva);
                var size      = Utils.SizeOf <IMAGE_EXPORT_DIRECTORY>();
                var location  = new Location(image, offset, rva, va, size.ToUInt32(), size.ToUInt32(), section);
                var stream    = image.GetStream();

                stream.Seek(offset.ToInt64(), SeekOrigin.Begin);

                var exportDirectory = await stream.ReadStructAsync <IMAGE_EXPORT_DIRECTORY>(size).ConfigureAwait(false);

                var name = await BuildNameAsync(calc, stream, exportDirectory).ConfigureAwait(false);

                var functionAddresses = await BuildFunctionAddressesAsync(calc, stream, exportDirectory).ConfigureAwait(false);

                var functionNameAddresses = await BuildFunctionNameAddressesAsync(calc, stream, exportDirectory).ConfigureAwait(false);

                var functionOrdinals = await BuildFunctionOrdinalsAsync(calc, stream, exportDirectory).ConfigureAwait(false);

                return(new ExportDirectory(image, dataDirectory, location, exportDirectory, name, functionAddresses, functionNameAddresses, functionOrdinals));
            }
            catch (Exception ex)
            {
                throw new PortableExecutableImageException(image, "Could not read export directory from stream.", ex);
            }
        }
Exemple #15
0
        private static DebugDirectoryEntry[] LoadEntries(PortableExecutableImage image, int entrySize, Tuple <ulong, IMAGE_DEBUG_DIRECTORY>[] entries)
        {
            var calc      = image.GetCalculator();
            var imageBase = image.NTHeaders.OptionalHeader.ImageBase;
            var results   = new DebugDirectoryEntry[entries.Length];

            for (var i = 0; i < entries.Length; i++)
            {
                var tuple    = entries[i];
                var rva      = calc.OffsetToRVA(tuple.Item1);
                var va       = imageBase + rva;
                var location = new Location(image, tuple.Item1, rva, va, entrySize.ToUInt32(), entrySize.ToUInt32());
                var entry    = new DebugDirectoryEntry(image, location, tuple.Item2);

                results[i] = entry;
            }

            return(results);
        }
Exemple #16
0
        public DebugData GetData()
        {
            if (_data == null)
            {
                if (PointerToRawData == 0 && SizeOfData == 0)
                {
                    return(null);
                }

                var calc      = _image.GetCalculator();
                var rva       = AddressOfRawData;
                var imageBase = _image.NTHeaders.OptionalHeader.ImageBase;
                var location  = new Location(_image, PointerToRawData, rva, imageBase + rva, SizeOfData, SizeOfData);

                _data = new DebugData(_image, location, this);
            }

            return(_data);
        }
Exemple #17
0
        internal static async Task <CLRMetaData> GetAsync(PortableExecutableImage image, CLRHeader header)
        {
            var calc           = image.GetCalculator();
            var imageBase      = image.NTHeaders.OptionalHeader.ImageBase;
            var rva            = header.MetaDataAddress;
            var va             = imageBase + rva;
            var offset         = calc.RVAToOffset(rva);
            var size           = header.MetaDataSize;
            var section        = calc.RVAToSection(rva);
            var location       = new Location(image, offset, rva, va, size, size, section);
            var metaDataHeader = await CLRMetaDataHeader.LoadAsync(image, location).ConfigureAwait(false);

            var metaDataStreamTable = await CLRMetaDataStreamTable.LoadAsync(image, metaDataHeader).ConfigureAwait(false);

            var metaDataStreams = await CLRMetaDataStreams.LoadAsync(image, location, metaDataStreamTable).ConfigureAwait(false);

            var metaData = new CLRMetaData(image, location, metaDataHeader, metaDataStreamTable, metaDataStreams);

            return(metaData);
        }
Exemple #18
0
        internal ExceptionUnwindInfo(PortableExecutableImage image, uint rva, byte versionFlags, byte sizeOfProlog, byte countOfCodes, byte frameRegisterOffset, ushort[] codes,
                                     uint handlerAddress, ExceptionChainedUnwindInfo chainedInfo)
        {
            _image = image;

            Version       = Convert.ToByte(versionFlags & ((1 << 3) - 1));
            Flags         = Convert.ToByte(versionFlags >> 3 & ((1 << 5) - 1));
            SizeOfProlog  = sizeOfProlog;
            CountOfCodes  = countOfCodes;
            FrameRegister = Convert.ToByte(versionFlags & ((1 << 4) - 1));
            FrameOffset   = Convert.ToByte(versionFlags >> 4 & ((1 << 4) - 1));
            UnwindCodes   = codes.Select(code => new ExceptionUnwindInfoCode(code)).ToArray();

            var calc   = image.GetCalculator();
            var offset = calc.RVAToOffset(rva);
            var va     = image.NTHeaders.OptionalHeader.ImageBase + rva;
            var size   = sizeof(uint) + (sizeof(ushort) * CountOfCodes);

            if (CountOfCodes % 2 != 0)
            {
                size += sizeof(ushort);
            }

            var flags = GetFlags();

            if ((flags & ExceptionUnwindInfoFlags.ExceptionHandler) == ExceptionUnwindInfoFlags.ExceptionHandler || (flags & ExceptionUnwindInfoFlags.UnwindHandler) == ExceptionUnwindInfoFlags.UnwindHandler)
            {
                AddressOfHandler = handlerAddress;

                size += sizeof(uint);
            }

            if ((flags & ExceptionUnwindInfoFlags.ChainHandler) == ExceptionUnwindInfoFlags.ChainHandler)
            {
                ChainedUnwindInfo = chainedInfo;

                size += (sizeof(uint) * 3);
            }

            Location = new Location(image, offset, rva, va, size.ToUInt32(), size.ToUInt32());
        }
Exemple #19
0
        public static async Task <ExportTable <uint> > GetNameAddressTableAsync(PortableExecutableImage image, ExportDirectory directory = null)
        {
            if (directory == null)
            {
                directory = await ExportDirectory.GetAsync(image).ConfigureAwait(false);
            }

            var calc       = image.GetCalculator();
            var section    = calc.RVAToSection(directory.AddressOfNames);
            var fileOffset = calc.RVAToOffset(section, directory.AddressOfNames);
            var imageBase  = image.NTHeaders.OptionalHeader.ImageBase;
            var size       = directory.NumberOfNames * sizeof(uint);
            var location   = new Location(image, fileOffset, directory.AddressOfNames, imageBase + directory.AddressOfNames, size, size, section);
            var stream     = image.GetStream();

            stream.Seek(fileOffset.ToInt64(), SeekOrigin.Begin);

            var addresses = new uint[directory.NumberOfNames];

            try
            {
                for (var i = 0; i < directory.NumberOfNames; i++)
                {
                    addresses[i] = await stream.ReadUInt32Async().ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                throw new PortableExecutableImageException(image, "Could not read address of name from stream.", ex);
            }


            var dataDirectory = image.NTHeaders.DataDirectories[DataDirectoryType.ExportTable];
            var table         = new ExportTable <uint>(image, dataDirectory, location, directory, addresses);

            return(table);
        }
Exemple #20
0
        private static async Task <ImportAddressTables> GetTableAsync(PortableExecutableImage image, ImportDirectory directory, Func <ImportDirectoryEntry, uint> thunkHandler)
        {
            if (directory == null)
            {
                directory = await ImportDirectory.GetAsync(image).ConfigureAwait(false);
            }

            var calc   = image.GetCalculator();
            var stream = image.GetStream();
            var tables = new List <Tuple <uint, ulong[], ImportDirectoryEntryBase> >();

            foreach (var dirEntry in directory)
            {
                var thunk = thunkHandler(dirEntry);

                if (thunk == 0)
                {
                    continue;
                }

                var entries = new List <ulong>();
                var offset  = calc.RVAToOffset(thunk);

                stream.Seek(offset.ToInt64(), SeekOrigin.Begin);

                while (true)
                {
                    var entry = (!image.Is64Bit ? await stream.ReadUInt32Async().ConfigureAwait(false) : await stream.ReadUInt64Async().ConfigureAwait(false));

                    entries.Add(entry);

                    if (entry == 0)
                    {
                        break;
                    }
                }

                var table = new Tuple <uint, ulong[], ImportDirectoryEntryBase>(thunk, entries.ToArray(), dirEntry);

                tables.Add(table);
            }

            var rva = 0u;

            if (tables.Count > 0)
            {
                rva = tables.MinBy(table => table.Item1).Item1;
            }

            var imageBase  = image.NTHeaders.OptionalHeader.ImageBase;
            var va         = imageBase + rva;
            var fileOffset = calc.RVAToOffset(rva);
            var fileSize   = 0ul;

            foreach (var table in tables)
            {
                var size = table.Item2.Length * (!image.Is64Bit ? sizeof(uint) : sizeof(ulong));

                fileSize += size.ToUInt32();
            }

            var section  = calc.RVAToSection(rva);
            var location = new Location(image, fileOffset, rva, va, fileSize, fileSize, section);
            var result   = new ImportAddressTables(image, directory.DataDirectory, location, tables.ToArray());

            return(result);
        }
Exemple #21
0
        public static async Task <ImportHintNameTable> GetAsync(PortableExecutableImage image, ImportDirectory directory = null)
        {
            if (directory == null)
            {
                directory = await ImportDirectory.GetAsync(image).ConfigureAwait(false);
            }

            var entries = new Dictionary <uint, Tuple <ulong, uint, ushort, string, bool> >();
            var ilt     = await ImportAddressTables.GetLookupTableAsync(image, directory).ConfigureAwait(false);

            var calc   = image.GetCalculator();
            var stream = image.GetStream();

            foreach (var table in ilt)
            {
                foreach (var entry in table)
                {
                    if (entry.Address == 0)
                    {
                        continue;
                    }

                    if (entries.ContainsKey(entry.Address))
                    {
                        continue;
                    }

                    if (!entry.IsOrdinal)
                    {
                        var    offset   = calc.RVAToOffset(entry.Address);
                        var    size     = 0u;
                        var    isPadded = false;
                        ushort hint     = 0;
                        var    name     = new StringBuilder(256);

                        stream.Seek(offset.ToInt64(), SeekOrigin.Begin);

                        hint = await stream.ReadUInt16Async().ConfigureAwait(false);

                        size += sizeof(ushort);

                        while (true)
                        {
                            var b = await stream.ReadByteAsync().ConfigureAwait(false);

                            size++;

                            if (b <= 0)
                            {
                                break;
                            }

                            name.Append((char)b);
                        }

                        if (size % 2 != 0)
                        {
                            isPadded = true;
                            size++;
                        }

                        var tuple = new Tuple <ulong, uint, ushort, string, bool>(offset, size, hint, name.ToString(), isPadded);

                        entries.Add(entry.Address, tuple);
                    }
                }
            }

            Location location;

            if (entries.Count > 0)
            {
                var firstEntry   = entries.Values.MinBy(tuple => tuple.Item1);
                var lastEntry    = entries.Values.MaxBy(tuple => tuple.Item1);
                var tableOffset  = firstEntry.Item1;
                var tableSize    = ((lastEntry.Item1 + lastEntry.Item2) - tableOffset).ToUInt32();
                var tableRVA     = calc.OffsetToRVA(tableOffset);
                var tableVA      = image.NTHeaders.OptionalHeader.ImageBase + tableRVA;
                var tableSection = calc.RVAToSection(tableRVA);

                location = new Location(image, tableOffset, tableRVA, tableVA, tableSize, tableSize, tableSection);
            }
            else
            {
                location = new Location(image, 0, 0, 0, 0, 0, null);
            }

            var result = new ImportHintNameTable(image, directory.DataDirectory, location, entries.Values.ToArray());

            return(result);
        }
Exemple #22
0
        public static async Task <DelayedImports> GetAsync(PortableExecutableImage image, DelayedImportAddressTables ilt, DelayedImportHintNameTable hnt)
        {
            var libraries = new List <DelayedImportLibrary>();
            var calc      = image.GetCalculator();
            var stream    = image.GetStream();

            foreach (var table in ilt)
            {
                var builder = new StringBuilder(256);
                var offset  = calc.RVAToOffset(table.DirectoryEntry.Name);

                stream.Seek(offset.ToInt64(), SeekOrigin.Begin);

                while (true)
                {
                    var b = await stream.ReadByteAsync().ConfigureAwait(false);

                    if (b <= 0)
                    {
                        break;
                    }

                    builder.Append((char)b);
                }

                var name      = builder.ToString();
                var functions = new List <ImportLibraryFunction>(table.Count);

                foreach (var entry in table)
                {
                    ImportLibraryFunction function = null;

                    if (entry.IsOrdinal)
                    {
                        function = new ImportLibraryOrdinalFunction(entry, entry.Ordinal);
                    }
                    else
                    {
                        var hintEntry = hnt.FirstOrDefault(e => e.Location.RelativeVirtualAddress == entry.Address);

                        if (hintEntry != null)
                        {
                            function = new ImportLibraryNamedFunction(entry, hintEntry);
                        }
                    }

                    if (function != null)
                    {
                        functions.Add(function);
                    }
                }

                var library = new DelayedImportLibrary(functions.ToArray(), name);

                libraries.Add(library);
            }

            var imports = new DelayedImports(libraries.ToArray());

            return(imports);
        }
Exemple #23
0
        public static async Task <RelocationTable> GetAsync(PortableExecutableImage image)
        {
            if (!image.NTHeaders.DataDirectories.Exists(DataDirectoryType.BaseRelocationTable))
            {
                return(null);
            }

            var dataDirectory = image.NTHeaders.DataDirectories[DataDirectoryType.BaseRelocationTable];

            if (DataDirectory.IsNullOrEmpty(dataDirectory))
            {
                return(null);
            }

            var calc       = image.GetCalculator();
            var section    = calc.RVAToSection(dataDirectory.VirtualAddress);
            var fileOffset = calc.RVAToOffset(section, dataDirectory.VirtualAddress);
            var imageBase  = image.NTHeaders.OptionalHeader.ImageBase;
            var location   = new Location(image, fileOffset, dataDirectory.VirtualAddress, imageBase + dataDirectory.VirtualAddress, dataDirectory.Size, dataDirectory.Size, section);
            var stream     = image.GetStream();

            stream.Seek(fileOffset.ToInt64(), SeekOrigin.Begin);

            var blockOffset = fileOffset;
            var blockSize   = 0u;
            var blocks      = new List <RelocationBlock>();

            while (true)
            {
                IMAGE_BASE_RELOCATION baseRelocation;

                try
                {
                    baseRelocation = await stream.ReadStructAsync <IMAGE_BASE_RELOCATION>().ConfigureAwait(false);

                    blockSize += sizeof(ulong);
                }
                catch (Exception ex)
                {
                    throw new PortableExecutableImageException(image, "Could not read base relocation block from stream.", ex);
                }

                var count           = (baseRelocation.SizeOfBlock - sizeof(ulong)) / sizeof(ushort);
                var baseRelocations = new ushort[count];

                for (var i = 0; i < count; i++)
                {
                    try
                    {
                        baseRelocations[i] = await stream.ReadUInt16Async().ConfigureAwait(false);

                        blockSize += sizeof(ushort);
                    }
                    catch (Exception ex)
                    {
                        throw new PortableExecutableImageException(image, "Could not read base relocation from stream.", ex);
                    }
                }

                var blockRVA      = calc.OffsetToRVA(blockOffset);
                var blockLocation = new Location(image, blockOffset, blockRVA, imageBase + blockRVA, blockSize, blockSize);
                var block         = new RelocationBlock(image, blockLocation, baseRelocation.VirtualAddress, baseRelocation.SizeOfBlock, baseRelocations);

                blocks.Add(block);

                if (blockSize >= dataDirectory.Size)
                {
                    break;
                }

                blockOffset += sizeof(ulong);
                blockOffset += sizeof(ushort) * count;
            }

            return(new RelocationTable(image, dataDirectory, location, blocks.ToArray()));
        }
Exemple #24
0
        public static async Task <DelayedImportDirectory> GetAsync(PortableExecutableImage image)
        {
            if (!image.NTHeaders.DataDirectories.Exists(DataDirectoryType.DelayImportDescriptor))
            {
                return(null);
            }

            var dataDirectory = image.NTHeaders.DataDirectories[DataDirectoryType.DelayImportDescriptor];

            if (DataDirectory.IsNullOrEmpty(dataDirectory))
            {
                return(null);
            }

            var calc       = image.GetCalculator();
            var section    = calc.RVAToSection(dataDirectory.VirtualAddress);
            var fileOffset = calc.RVAToOffset(section, dataDirectory.VirtualAddress);
            var stream     = image.GetStream();

            stream.Seek(fileOffset.ToInt64(), SeekOrigin.Begin);

            var size        = Utils.SizeOf <IMAGE_DELAY_IMPORT_DESCRIPTOR>();
            var descriptors = new List <Tuple <ulong, IMAGE_DELAY_IMPORT_DESCRIPTOR> >();

            try
            {
                ulong offset = 0;

                while (true)
                {
                    var descriptor = await stream.ReadStructAsync <IMAGE_DELAY_IMPORT_DESCRIPTOR>(size).ConfigureAwait(false);

                    if (descriptor.Name == 0 && descriptor.ModuleHandle == 0)
                    {
                        break;
                    }

                    var tuple = new Tuple <ulong, IMAGE_DELAY_IMPORT_DESCRIPTOR>(offset, descriptor);

                    offset += size.ToUInt32();

                    descriptors.Add(tuple);
                }
            }
            catch (Exception ex)
            {
                throw new PortableExecutableImageException(image, "Could not read delay import descriptor from stream.", ex);
            }

            var imageBase = image.NTHeaders.OptionalHeader.ImageBase;
            var totalSize = (descriptors.Count + 1) * size;
            var location  = new Location(image, fileOffset, dataDirectory.VirtualAddress, imageBase + dataDirectory.VirtualAddress, totalSize.ToUInt32(), totalSize.ToUInt32(), section);
            var entries   = new DelayedImportDirectoryEntry[descriptors.Count];

            for (var i = 0; i < descriptors.Count; i++)
            {
                try
                {
                    var entryOffset   = fileOffset + descriptors[i].Item1;
                    var entryRVA      = calc.OffsetToRVA(entryOffset);
                    var entryVA       = imageBase + entryRVA;
                    var entryLocation = new Location(image, entryOffset, entryRVA, entryVA, size.ToUInt32(), size.ToUInt32());
                    var name          = await GetNameAsync(calc, stream, descriptors[i].Item2.Name).ConfigureAwait(false);

                    entries[i] = new DelayedImportDirectoryEntry(image, entryLocation, descriptors[i].Item2, name);
                }
                catch (Exception ex)
                {
                    throw new PortableExecutableImageException(image, "Could not read delay import library name from stream.", ex);
                }
            }

            var result = new DelayedImportDirectory(image, dataDirectory, location, entries);

            return(result);
        }
Exemple #25
0
        private static async Task <CLRMetaDataStreamTableEntry[]> LoadTableAsync(PortableExecutableImage image, CLRMetaDataHeader header, ulong baseOffset, ulong imageBase)
        {
            var stream = image.GetStream();

            stream.Seek(baseOffset.ToInt64(), SeekOrigin.Begin);

            var entries = new List <CLRMetaDataStreamTableEntry>();
            var offset  = baseOffset;

            for (var i = 0; i < header.Streams; i++)
            {
                var size         = 0U;
                var streamOffset = await stream.ReadUInt32Async().ConfigureAwait(false);

                size += sizeof(uint);

                var streamSize = await stream.ReadUInt32Async().ConfigureAwait(false);

                size += sizeof(uint);

                var streamName = new StringBuilder(256);

                while (true)
                {
                    var b = await stream.ReadByteAsync().ConfigureAwait(false);

                    size += 1;

                    if (b <= 0)
                    {
                        break;
                    }

                    streamName.Append((char)b);
                }

                while (true)
                {
                    if (stream.Position % 4 != 0)
                    {
                        await stream.ReadByteAsync().ConfigureAwait(false);

                        size += 1;
                    }
                    else
                    {
                        break;
                    }
                }

                var calc     = image.GetCalculator();
                var rva      = calc.OffsetToRVA(offset);
                var va       = imageBase + rva;
                var section  = calc.RVAToSection(rva);
                var location = new Location(image, offset, rva, va, size, size, section);
                var entry    = new CLRMetaDataStreamTableEntry(image, location, streamOffset, streamSize, streamName.ToString());

                entries.Add(entry);

                offset += size;
            }

            return(entries.ToArray());
        }
Exemple #26
0
 public void SetUp()
 {
     _image = PortableExecutableImage.FromStream(TestingUtils.GetFileFromResources("nativetest.x64.dll"));
     _calc  = _image.GetCalculator();
 }