public static IEnumerable <ImageImportDescriptor> ReadImportDescriptors(this PEStream stream) { var entry = stream.OptionalHeader.DataDirectories[H.IMAGE_DIRECTORY_ENTRY_IMPORT]; var buffer = new byte[ImageImportDescriptor.Size]; if (entry.Size == 0) { yield break; } var descriptorOffset = 0U; while (true) { stream.SeekVirtualAddress(entry.VirtualAddress + descriptorOffset); stream.FullRead(buffer, 0, buffer.Length); var descriptor = WindowsStructConverter.ToImageImportDescriptor(buffer, 0); if (descriptor.Name == 0 && descriptor.FirstThunkRva == 0 && descriptor.OriginalFirstThunk == 0) { break; } descriptorOffset += ImageImportDescriptor.Size; yield return(descriptor); } }
public static IEnumerable <uint> ReadImportLocationTable(this PEStream stream, ImageImportDescriptor descriptor) { // The thunk processing is the same for PE32 and PE32+, however the size of the thunks differ to support 64-bit addresses // when translating the ImportAddressTable (IAT). Luckily only 32-bits of the 64 are actually required in both // PE32 and PE32+ for the ImportLookupTable (ILT) so we can just normalize the data into a DWORD and avoid having to create // two *almost* identical methods. var is32Bit = stream.OptionalHeader.Magic == H.IMAGE_NT_OPTIONAL_HDR32_MAGIC; var thunkSize = (uint)(is32Bit ? sizeof(uint) : sizeof(ulong)); var buffer = new byte[thunkSize]; var thunkOffset = 0U; var thunk = 0U; while (true) { stream.SeekVirtualAddress(descriptor.OriginalFirstThunk + thunkOffset); stream.FullRead(buffer, 0, buffer.Length); if (is32Bit) { thunk = BitConverter.ToUInt32(buffer, 0); } else { var thunk64 = BitConverter.ToUInt64(buffer, 0); thunk = (uint)((thunk64 & 0x7FFFFFFF) | ((thunk64 >> 32) & 0x80000000)); } if (thunk == 0) { break; } thunkOffset += thunkSize; yield return(thunk); } }