static void Main(string[] args) { using (var es = new PEStream(new FileStream(@"C:\Windows\System32\KERNELBASE.dll", FileMode.Open, FileAccess.Read), AddressMode.File)) { var nameBuffer = new byte[4096]; foreach (var descriptor in es.ReadImportDescriptors()) { es.SeekVirtualAddress(descriptor.Name); Console.WriteLine(es.ReadString(nameBuffer, 0)); foreach (var thunk in es.ReadImportLocationTable(descriptor)) { if ((thunk & H.IMAGE_ORDINAL_FLAG32) != 0) { Console.WriteLine(" #{0}", thunk & 0xFFFF); } else { es.SeekVirtualAddress(thunk + 2); Console.WriteLine(" {0}", es.ReadString(nameBuffer, 0)); } } } } Console.Read(); }
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); } }