IAT hook

This tool , in its simplest form , hooks an API entry address (Function pointer) in an IAT , and overwrites it with a custom implementation . Technically , this code must be compiled in a DLL , then injected in address space of process (e.g with SetWindowsHookEx( ) ), which is employed to locate the RVA of the import table (DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress) and eventually gets the entry in FirstThunk linked list to change the value of u1.Function to the hooking function. For all practical purposes , IAT hooking comes handy in variety of situations : - During unpacking phase (e.g : hooking ExitProcess() ) . - Malwares often take advantage of it to hide their presence in the system. - Intercepting API calls and parameters. - Avoids anti-malware detection mechanism .


#include "main.h"
#include 
#include 
#include 
#include 

// a sample exported function


inline void  WINAPI trampoline()
{

    fprintf(stdout,"%s \n ","Hooked !! ");

}

void HookIAT (const char  * api , DWORD  HookFuncAddr )
{

    IMAGE_DOS_HEADER * idh = NULL ;
    HMODULE CurrentExe = GetModuleHandle(NULL);
    DWORD Protect = 0;
    IMAGE_NT_HEADERS * inh = NULL ;
    DWORD t = 0 ;
    IMAGE_THUNK_DATA * itd ;
    int j = -1, i  = 0;
    IMAGE_THUNK_DATA * itdf ;
    idh = (IMAGE_DOS_HEADER * )CurrentExe ;


    if(idh->e_magic != 0x5a4d )
    {
        ExitProcess(-1) ;
    }
    inh = (IMAGE_NT_HEADERS * )((DWORD)CurrentExe  + (DWORD)idh->e_lfanew ) ;

    if(inh->Signature != 0x4550 )
    {
        ExitProcess(-1);
    }
    // Get the Virtaul address of import adress table !!
    IMAGE_IMPORT_DESCRIPTOR * va_import = (IMAGE_IMPORT_DESCRIPTOR * )((DWORD)inh->OptionalHeader.ImageBase + (DWORD)inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress );

     itd = (IMAGE_THUNK_DATA * )( (DWORD)CurrentExe + va_import[0].OriginalFirstThunk );
    // contains the adresses of the imported APIs
     itdf = (IMAGE_THUNK_DATA * )( (DWORD)CurrentExe + va_import[0].FirstThunk ) ;


    while(va_import[i].Characteristics != 0)
    {

        j = -1 ;

        while(itd[++j].u1.Function != 0)
        {

            if(strcmp((const char *)api , (const char * )((DWORD) CurrentExe + (DWORD)(itd[j].u1.ForwarderString + 2)) ) == 0)
            {

                if(!VirtualProtect(&itdf[j].u1.Function, sizeof(LPVOID), PAGE_READWRITE, &Protect) )
                {
                    ExitProcess(-1) ;
                }

                 itdf[j].u1.Function = (DWORD )HookFuncAddr;


                if(!VirtualProtect(&itdf[j].u1.Function, sizeof(LPVOID), Protect, &t) )
                {
                    ExitProcess(-1) ;
                }

            }
        }

        i++ ;
        itd = (IMAGE_THUNK_DATA * )((DWORD)CurrentExe + va_import[i].OriginalFirstThunk );

        itdf = (IMAGE_THUNK_DATA * )((DWORD)CurrentExe + va_import[i].FirstThunk );
    }
}



extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {

    case DLL_PROCESS_ATTACH:
        // attach to process
        // return FALSE to fail DLL load

        HookIAT("MessageBoxA",(DWORD  )trampoline) ;

 /// the following api will be hooked and the trampoline() function will be executed instead !!

        MessageBoxA(NULL,"L0phtTn","HookMe",0);

        break;

    case DLL_PROCESS_DETACH:
        // detach from process
        break;

    case DLL_THREAD_ATTACH:
        // attach to thread
        break;

    case DLL_THREAD_DETACH:
        // detach from thread
        break;

    }
    return TRUE; // succesful
}