I've been trying to parse/display the information in the Import Address Table (IAT) of a process after it is loaded and running. I understand API calls in programs jump to the relevant point in the IAT, which then jumps to the actual function in the loaded DLL's.
Is it correct that the IAT can be found by reading the PE header and following the OptionalHeader.DataDirectory[1] pointer, to the array of IMAGE_IMPORT_DESCRIPTORs. Then following the FirstThunk pointers. Whereas the OriginalFirstThunk pointers here, will give you the original Import Table (IT)?
I have also tried following the OptionalHeader.DataDirectory[12] pointer in the PE header, but this was even less successful.
I've been testing this by trying to parse this structure for notepad.exe (32bit), using ReadProcessMemory from another process.
Here's the rough C-psuedocode for what I'm doing:
char buf[128];
// get first import descriptor
readMemory(&import, procImgBase + DataDirectory[1].VirtualAddress, sizeof(IMAGE_IMPORT_DESCRIPTOR));
// get dll name
readMemory(buf, import.Name + procImgBase, 127);
printf("libname: %s\n", buf);
// get first function name
DWORD iltAddress = 0;
readMemory(&iltAddress, import.FirstThunk + procImgBase, 4);
readMemory(buf, iltAddress + procImgBase, 127);
printf("fname: %s\n", libName + 2); // <-- the +2 for the 2byte 'hint' of import lookup table entries
If, on the 3rd to last line, i replace it with import.OriginalFirstThunk instead of FirstThunk, it will print everything as expected. I must be missing something conceptually, and so I was wondering if anyone could clarify what this is, for me?
Many thanks!
It looks like you're heading the right direction. Some notes:
Since your executable is running, the IAT should contain the actual address of the function rather than an RVA to a name entry.
You could do something like this instead:
DWORD rva_to_name_of_function = 0;
DWORD address_of_function = 0;
// get the RVA of the IMAGE_IMPORT_BY_NAME entry
readMemory(&rva_to_name, import.OriginalFirstThunk + procImgBase, 4);
// copy the name of the import
readMemory(buf, rva_to_name + procImgBase + 2, 127);
// get the actual address that was filled in by the loader
readMemory(&address_of_function, import.FirstThunk + procImgBase, 4);
printf("fname: %s address: %X", buf, address_of_function);
Take a look at this article for some helpful details: http://msdn.microsoft.com/en-us/magazine/cc301808.aspx