Skip to content

We can modify the IAT table in order to modify the original address of the target function and specify our hook function.

Code

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

#pragma comment(lib, "user32.lib")
#pragma comment (lib, "dbghelp.lib")

// pointer to original MessageBox
int (WINAPI * pOrigMessageBox)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) = MessageBox;

// Hooking function
int HookedMessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) {

    printf("HookedMessageBox() called!\n");
    pOrigMessageBox(hWnd, "TESTING WITH HOOKS", "RTNOTES", uType);
    return IDOK;
}

// Set hooks on MessageBox
BOOL Hookem(char * dll, char * origFunc, PROC hookingFunc) {

    ULONG size;
    DWORD i;
    BOOL found = FALSE;

    // get a HANDLE to a main module == BaseImage
    HANDLE baseAddress = GetModuleHandle(NULL);         

    // get Import Table of main module
    PIMAGE_IMPORT_DESCRIPTOR importTbl = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToDataEx( baseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size, NULL);

    // find imports for target dll 
    for (i = 0; i < size ; i++){
        char * importName = (char *)((PBYTE) baseAddress + importTbl[i].Name);
        if (_stricmp(importName, dll) == 0) {
                found = TRUE;
                break;
        }
    }
    if (!found)
        return FALSE;

    // Optimization: get original address of function to hook 
    // and use it as a reference when searching through IAT directly
    PROC origFuncAddr = (PROC) GetProcAddress(GetModuleHandle(dll), origFunc);

    // Search IAT
    PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA) ((PBYTE) baseAddress + importTbl[i].FirstThunk);
    while (thunk->u1.Function) {
        PROC * currentFuncAddr = (PROC *) &thunk->u1.Function;

        // found
        if (*currentFuncAddr == origFuncAddr) {

            // make sure memory is writable
            DWORD oldProtect = 0;
            VirtualProtect((LPVOID) currentFuncAddr, 4096, PAGE_READWRITE, &oldProtect);

            // set the hook
            *currentFuncAddr = (PROC)hookingFunc;

            // revert protection setting back
            VirtualProtect((LPVOID) currentFuncAddr, 4096, oldProtect, &oldProtect);

            printf("IAT function %s() hooked!\n", origFunc);
            return TRUE;
        }
    thunk++;
    }

    return FALSE;
}


BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) {

    switch (dwReason)  {
        case DLL_PROCESS_ATTACH:
            Hookem("user32.dll", "MessageBoxA", (PROC) HookedMessageBox);
            break;
        case DLL_THREAD_ATTACH:
            break;
        case DLL_THREAD_DETACH:
            break;
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}