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); }
private Section GetSection(uint pageRVA) { var calc = _image.GetCalculator(); var section = calc.RVAToSection(pageRVA); return(section); }
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)); }
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); } }
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); }
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); }
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); }
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); }
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; }
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; }
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; }
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); } }
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); } }
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); }
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); }
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); }
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()); }
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); }
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); }
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); }
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); }
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())); }
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); }
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()); }
public void SetUp() { _image = PortableExecutableImage.FromStream(TestingUtils.GetFileFromResources("nativetest.x64.dll")); _calc = _image.GetCalculator(); }