Thursday, December 12, 2013

Portable Executable (PE) and IAT

The first 40 bytes contains the MSDOS header defined by IMAGE_DOS_HEADER structure.  Following the header is a stub program which displays "This program cannot be run in DOS mode" message.  The MSDOS header contains a magic number "MZ" in the first 2 bytes.  MZ is initials for Mark Zbikowski which develop the DOS format.  The last field of the header contains the RVA (relative virtual address) of the PE file header.

RVA signifies the offset from the base address of the PE module, return by GetModuleHandle().  The PE header is defined by IMAGE_PE_HEADER structure:

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;  // magic number "PE\0\0"
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADER32, *PIMAGE_NT_HEADER32;

IMAGE_FILE_HEADER stores a number of file attributes such as number of sections, date/time stamp, Characteristics that indicate if this is a DLL (1) or EXE (0) based on the value in the 14th bit.

IMAGE_OPTIONAL_HEADER32 contains an array of 16 IMAGE_DATA_DIRECTORY structures.  The 16 entries can be referenced individually using an integer macro:

IMAGE_DIRECTORY_ENTRY_EXPORT = 0
IMAGE_DIRECTORY_ENTRY_IMPORT = 1 which corresponds to the IAT
IMAGE_DIRECTORY_ENTRY_RESOURCE = 2

typedef struct _IMAGE_DATA_DIRECTORU {
    DWORD VirtualAddress;  //RVA of data
    DWORD Size;  // size in bytes
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

For the IMPORT DIRECTORY, the RVA points to the start of an array of IMAGE_IMPORT_DESCRIPTOR, one for each DLL imported by the module.

typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
        DWORD Characteristics;  //0 for the last descriptor
        DWORD OriginalFirstThunk;  //RVA of the IMPORT Lookup Table (ILT)
    };
    DWORD TineDateStamp;
    DWORD ForwarderChain;  // -1 if no forwarders
    DWORD Name;  //RVA of the DLL name terminated by \0
    DWORD FirstThunk;  //RVA to IAT
} IMAGE_IMPORT_DESCRIPTOR;

Both FirstThunk and OriginalFirstThunk points to the an array of IMAGE_THUNK_DATA structure:

typedef struct _IMAGE_THUNK_DATA {
    union {
        PBYTE ForwarderString;
        PDWORD Function;  //address of the imported routine stored in IAT
        DWORD Ordinal;
        PIMAGE_IMPORT_BY_NAME AddressOfData;  //size and string name of the imported routine stored in ILT
    } u1;
} IMAGE_THUNK_DATA32;

The ordinal field indicate if the function is imported by name or by its cardinal number.

In summary, the structures are linked:

IMAGE_DOS_HEADER -> IMAGE_NT_HEADERS {IMAGE_OPTIONAL_HEADER32} -> IMAGE_DATA_DESCRITPOR -> IMAGE_IMPORT_DESCRIPTOR -> ILT and IAT

No comments: