Red Team Notes logo Red Team Notes

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:

HMODULE hModule = GetModuleHandle(NULL);

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);

The imported DLLs are read with importDescriptor->Name. The imported functions are iterated from the OriginalFirstThunk.

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;
}