Windows API resolves IAT address

Complete code

#include <stdio.h>
#include <windows.h>

int main(int argc,char* argv[]){
    /*
    typedef struct _IMAGE_IMPORT_DESCRIPTOR {
        union{
            DWORD   Characteristics;
            DWORD   OriginalFirstThunk;
        };
        DWORD   TimeDateStamp;
        DWORD   ForwarderChain;      
        DWORD   Name; // DLL RVA offset for name
        DWORD   FirstThunk; // IAT RVA offset of real address
    }IMAGE_IMPORT_DESCRIPTOR;
    */

    /*
    typedef struct _IMAGE_THUNK_DATA32{
        union{
            DWORD ForwarderString;
            DWORD Function;
            DWORD Ordinal;
            DWORD AddressOfData; // RVA Point to image import by name 
        }u1;
    }IMAGE_THUNK_DATA32;
    */

    /*
   typedef struct _IMAGE_IMPORT_BY_NAME{
        WORD    Hint;
        BYTE    Name[1];
    }IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
    */
    HMODULE hmod;
    PIMAGE_DOS_HEADER pdos;
    PIMAGE_NT_HEADERS pnt;
    PIMAGE_OPTIONAL_HEADER popt;
    PIMAGE_IMPORT_DESCRIPTOR piid;
    PIMAGE_THUNK_DATA pfuncname_addr,pfunc_addr;
    
    hmod = GetModuleHandle(NULL); // HMODULE type cannot be directly involved in the operation. It should be cast to byte stream
    pdos = (PIMAGE_DOS_HEADER)hmod;
    pnt = (PIMAGE_NT_HEADERS)((BYTE *)hmod + pdos->e_lfanew); // NT_offset = dos.e_lfanew
    popt = (PIMAGE_OPTIONAL_HEADER)(&(pnt->OptionalHeader));
    piid = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE *)hmod+popt->DataDirectory[1].VirtualAddress); // Base_addr + RVA_addr
    while(piid->FirstThunk){
        pfuncname_addr = (PIMAGE_THUNK_DATA)((BYTE *)hmod + piid->OriginalFirstThunk);
        pfunc_addr = (PIMAGE_THUNK_DATA)((BYTE *)hmod + piid->FirstThunk);
        char* pdll_name = (char *)((BYTE *)hmod + piid->Name);
        printf("DLL:%s\n",pdll_name);
        printf("|\n");
        while(pfuncname_addr->u1.Function){
            char* func_name = (char *)((BYTE *)hmod + pfuncname_addr->u1.AddressOfData+2);
            DWORD lpAddr = pfunc_addr->u1.AddressOfData;
            printf("Func_Name:%s\t",func_name); // OriginalFirstThunk corresponds to an array of structs, which are the names of each function
            printf("Addr:0x%04x\n",lpAddr); // First thunk corresponds to an array of structs, which starts with the same as original first thunk, and then fills in the real address of the function
            pfuncname_addr++;
            pfunc_addr++;
        }
        printf("\n");
        piid++; // Each DLL corresponds to an IID item
    }
    getchar();
    return 0;
}

Simple explanation
Get the module handle of this process to locate the memory area of file loading! Then use e﹤ lfanew of DOS header to offset to NT header, and use NT header to find Optional header. The first index entry of Optional DataDirectory corresponds to the first IID entry, and then locate to OriginalFirstThunk and FirstThunk through IID. Cycle to get the name and memory address of each function! And then outer loop every DLL! Finally print out the IAT function name and memory address of all DLLs!

Operation result


Be careful
u1.AddressOfData pointed by OriginalFirstThunk is the structure of Hint/Name
u1.AddressOfData pointed by FirstThunk is now filled with the real address of the function in memory

END

Keywords: C Windows

Added by turboprop on Fri, 13 Dec 2019 19:04:23 +0200