예제 #1
0
        public static async Task <DelayedImports> GetAsync(PortableExecutableImage image)
        {
            var directory = await DelayedImportDirectory.GetAsync(image).ConfigureAwait(false);

            if (directory == null)
            {
                return(null);
            }

            var ilt = await DelayedImportAddressTables.GetLookupTableAsync(image, directory).ConfigureAwait(false);

            if (ilt == null)
            {
                return(null);
            }

            var hnt = await DelayedImportHintNameTable.GetAsync(image, directory).ConfigureAwait(false);

            if (hnt == null)
            {
                return(null);
            }

            return(await GetAsync(image, ilt, hnt).ConfigureAwait(false));
        }
예제 #2
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);
        }
예제 #3
0
        private static async Task <DelayedImportAddressTables> GetTableAsync(PortableExecutableImage image, DelayedImportDirectory directory, Func <DelayedImportDirectoryEntry, uint> thunkHandler)
        {
            if (directory == null)
            {
                directory = await DelayedImportDirectory.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 + 1) * (!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 DelayedImportAddressTables(image, directory.DataDirectory, location, tables.ToArray());

            return(result);
        }
예제 #4
0
        public static async Task <DelayedImportHintNameTable> GetAsync(PortableExecutableImage image, DelayedImportDirectory directory = null)
        {
            if (directory == null)
            {
                directory = await DelayedImportDirectory.GetAsync(image).ConfigureAwait(false);
            }

            var entries = new Dictionary <uint, Tuple <ulong, uint, ushort, string, bool> >();
            var ilt     = await DelayedImportAddressTables.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 DelayedImportHintNameTable(image, directory.DataDirectory, location, entries.Values.ToArray());

            return(result);
        }
예제 #5
0
 public static async Task <DelayedImportAddressTables> GetAddressTableAsync(PortableExecutableImage image, DelayedImportDirectory directory = null)
 {
     return(await GetTableAsync(image, directory, (entry) => entry.DelayAddressTable).ConfigureAwait(false));
 }