Skip to content

Last review: Sept 15,2025

Imports

A program uses functions from external libraries.

The loader then needs to load each of these libraries into its memory space and find the address of each function used by the executable we want to load. Once found, the addresses are stored in the so-called "Import Address Table (IAT)" for future use.

The names of the libraries and the functions used are listed in the PE file through the so-called import section, which can be located using the IMAGE_DIRECTORY_ENTRY_IMPORT directory in the NT header.

This section has the following structure:

CPP
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
	union {
		DWORD	Characteristics; /* 0 for terminating null import descriptor  */
		DWORD	OriginalFirstThunk;	/* RVA to original unbound IAT */
	} DUMMYUNIONNAME;
	DWORD	TimeDateStamp;
	DWORD	ForwarderChain;	/* -1 if no forwarders */
	DWORD	Name;
	DWORD	FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;

Three fields are interesting in this structure:

  • Name is an offset from @BASE that points to the library name as a string.

  • OriginalFirstThunk can be viewed as a pointer to a table of functions that our executable wants to use.

  • FirstThunk can be viewed as a pointer in the IAT to store the address of each function.

At a high level, this section can be represented as follows:

OriginalFirstThunk

In more detail, OriginalFirstThunk is an offset from @BASE that points to a table of functions. Each entry in this table has the following structure:

CPP
typedef struct _IMAGE_THUNK_DATA64 {
	union {
		ULONGLONG ForwarderString;
		ULONGLONG Function;
		ULONGLONG Ordinal;
		ULONGLONG AddressOfData;
	} u1;
} IMAGE_THUNK_DATA64,*PIMAGE_THUNK_DATA64;
typedef IMAGE_THUNK_DATA64              IMAGE_THUNK_DATA;
typedef PIMAGE_THUNK_DATA64             PIMAGE_THUNK_DATA;

Either the Ordinal field or AddressOfData is used (but not both at the same time).

  • AddressOfData is an offset from @BASE that points to an IMAGE_IMPORT_BY_NAME structure containing the function name in the library. One can then use GetProcAddress() to retrieve the function's address.
  • Ordinal is used when the function has no name. This field represents the function's index in the export table of the library's PE file. The export table then provides the function's address.

FirstThunk

Similar to OriginalFirstThunk, FirstThunk is an offset from @BASE that points to an IMAGE_THUNK_DATA structure. However, this time, only the Function field is used. This field contains the address of the function.

When first encountered, this field is uninitialized. FirstThunk is related to the IAT (Import Address Table).


delayed imports

There is another, less commonly used type of import: delayed imports. These include functions that are expected to be loaded later than those found in the import section.

The section related to this type of import can be located using the IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT directory in the NT header, similar to the standard import section. This section is a table where each entry is represented by the following structure:

CPP
typedef struct _IMAGE_DELAYLOAD_DESCRIPTOR {
    union {
        DWORD AllAttributes;
        struct {
            DWORD RvaBased : 1;             // Delay load version 2
            DWORD ReservedAttributes : 31;
        };
    } Attributes;

    DWORD DllNameRVA;                       // RVA to the name of the target library (NULL-terminate ASCII string)
    DWORD ModuleHandleRVA;                  // RVA to the HMODULE caching location (PHMODULE)
    DWORD ImportAddressTableRVA;            // RVA to the start of the IAT (PIMAGE_THUNK_DATA)
    DWORD ImportNameTableRVA;               // RVA to the start of the name table (PIMAGE_THUNK_DATA::AddressOfData)
    DWORD BoundImportAddressTableRVA;       // RVA to an optional bound IAT
    DWORD UnloadInformationTableRVA;        // RVA to an optional unload info table
    DWORD TimeDateStamp;                    // 0 if not bound,
                                            // Otherwise, date/time of the target DLL

} IMAGE_DELAYLOAD_DESCRIPTOR, *PIMAGE_DELAYLOAD_DESCRIPTOR;

Here are the most interesting fields of this structure:

  • DllNameRVA: An offset from @BASE that points to the name of the library.
  • ImportAddressTableRVA: An offset from @BASE to a table of addresses to be updated. Each entry in this table is equivalent to the Function field in an IMAGE_THUNK_DATA structure for the standard import section.
  • ImportNameTableRVA: Equivalent to OriginalFirstThunk