Simplifying Imports

Making quick work of the IDT, INT, and IAT


Note: We will skip over the Bound Imports for now.

The Import Directory Table1 holds all of the DLLs need by the PE, which also subsequently holds the functions within those DLLs that are used.

For example each entry into the IDT is a structure

// 20 bytes in size
struct IDT {
    DWORD OriginalFirstThunk,
    DWORD TimeDateStamp, // ignore
    DWORD ForwarderChain, // ignore
    DWORD Name,
    DWORD FirstThunk
}

OriginalFirstThunk: If imported by name this holds the RVA of a structure. Essentially the IMAGE_IMPORT_BY_NAME2 structure is a way to describe the function well enough for the Windows loader to find the function address (different on each PC) and insert it into the IAT. If imported by ordinal, it simply holds an ordinal value with the most significant bit being set to 8 indicating that it's an ordinal: 0x80001234. This array of structures and/or ordinals is what's know as the Import Name Table or Import Library Table.

// roughly visualized some function names in MSVCR90.dll
IMAGE_IMPORT_BY_NAME function[26]; // 27 functions

// CB 00 5F 5F 70 5F 5F 63 6F 6D 6D 6F 64 65 00 00
function[0].hint = 0xCB;
function[0].name = "__p__commode";
...
// CC 04 65 78 69 74 00 00
function[19].hint = 0x4CC;
function[19].name = "exit";

Notice how they're padded by two bytes (0x00, 0x00) at the end. Visualizing it this way helped me wrap my mind around it a bit easier.

Name: This holds an RVA to the ascii name of a DLL e.g User32.dll which is conveniently located near the end of where the ascii function names are located for that specific DLL. e.g.

// RVA for User32.dll: 0x22AE
0040229C    F8 01 4D 65 73 73 61 67 65 42 6F 78         øMessageBox
004022AC    41 00 55 53 45 52 33 32 2E 64 6C 6C00 00   A.USER32.dll..

Also padded by 2 bytes.

FirstThunk: This is an RVA to a pointer in the array of function addresses that will be filled in by the Windows loader. In memory it looks like this:

00402000 >80 2B 3D 75 F0 38 3D 75 80 A3 3C 75 20 FF 3C 75  €+=uð8=u€£<u ÿ<u
00402010 >00 39 3D 75 60 EF 3C 75 20 2E 3D 75 00 00 3D 75  .9=u`ï<u .=u..=u
00402020 >B0 23 3D 75 70 17 3D 75 40 5E 3C 75 B0 1A 3D 75  °#=up=u@^<u°=u
00402030 >10 3D 3C 75 F0 5E 3E 75 00 00 00 00 99 2A DA 6D  =<uð^>u....™*Úm
00402040 >CE 2A DA 6D 82 35 DA 6D E0 1B DA 6D 7B BE DD 6D  Î*Úm‚5ÚmàÚm{¾Ým
00402050 >16 2E DA 6D 18 C6 E1 6D FA 2E DA 6D 5A CE DE 6D  .ÚmÆámú.ÚmZÎÞm
00402060 >07 36 DA 6D 50 18 DF 6D 33 CB DE 6D 5B A9 DF 6D  6ÚmPßm3ËÞm[©ßm
00402070 >61 16 DF 6D FF 1B DA 6D 51 DF DE 6D 11 22 DA 6D  aßmÿÚmQßÞm"Úm
00402080 >EE 21 DA 6D 2C BA E1 6D 55 24 DA 6D E0 04 DC 6D  î!Úm,ºámU$ÚmàÜm
00402090 >88 CF DE 6D 70 24 DA 6D 8B 24 DA 6D 93 27 DA 6D  ˆÏÞmp$Úm‹$Úm“'Úm
004020A0 >57 21 DA 6D B7 CE DE 6D 00 00 00 00 70 22 70 76  W!Úm·ÎÞm....p"pv
004020B0  00 00 00 00 00 00 00 00                          ........

It looks hectic, but this is what the Import Address Table looks like when the Windows loader has filled in the proper function addresses. This is also what the start of the .rdata section looks like.

Another simplified visual of it all in graph form might look something like this: [Import_Directory_Table.svg]