The import address table is the part of the Windows module (executable or dynamic link library) which records the addresses of functions imported from other DLLs. It is important to be able to parse it in order to do some techniques such as IAT Hooking.
Here we can see and example of the IAT entries off a binary with PE-Bear.exe
.
To parse the IAT we need:
- Get the base address of the module (PE - Portable Executable).
HMODULE hModule = GetModuleHandle(NULL);
- Analyze the PE structure to locate the import table.
PIMAGE_DOS_HEADER
: DOS header
PIMAGE_NT_HEADERS
: NT header which contains the IAT
IMAGE_DATA_DIRECTORY importDirectory = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
PIMAGE_IMPORT_DESCRIPTOR importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(baseAddress + importDirectory.VirtualAddress);
- Iterate on the import entries (IMAGE_IMPORT_DESCRIPTOR).
The imported DLLs are read with importDescriptor->Name
.
The imported functions are iterated from the OriginalFirstThunk
.
- Obtain the addresses of the imported functions.
Code
#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "user32.lib")
int main(void) {
MessageBoxA(NULL,"Test", "Tet",MB_OK);
HMODULE hModule = GetModuleHandle(NULL);
PBYTE baseAddress = (PBYTE)hModule;
printf("baseAddress -> 0x%p\n", baseAddress);
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)baseAddress;
PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(baseAddress + dosHeader->e_lfanew);
IMAGE_DATA_DIRECTORY importDirectory = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
if (importDirectory.VirtualAddress == 0) {
printf("[-] IAT not found.\n");
}
PIMAGE_IMPORT_DESCRIPTOR importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(baseAddress + importDirectory.VirtualAddress);
while (importDescriptor->Name != 0) {
char* dllName = (char *)(baseAddress + importDescriptor->Name);
printf("%s\n", dllName);
PIMAGE_THUNK_DATA thunkILT = (PIMAGE_THUNK_DATA)(baseAddress + importDescriptor->OriginalFirstThunk);
PIMAGE_THUNK_DATA thunkIAT = (PIMAGE_THUNK_DATA)(baseAddress + importDescriptor->FirstThunk);
while (thunkILT->u1.AddressOfData != 0) {
if (!(thunkILT->u1.Ordinal & IMAGE_ORDINAL_FLAG)) {
PIMAGE_IMPORT_BY_NAME importByName = (PIMAGE_IMPORT_BY_NAME)(baseAddress + thunkILT->u1.AddressOfData);
printf("\t%s", importByName->Name);
}
printf("\t0x%p\n",thunkIAT->u1.Function);
thunkILT++;
thunkIAT++;
}
importDescriptor++;
}
return 0;
}