IAT hooking is a way to run malicious code by modifying the Import Address Table of a specific executable. Consisting of replacing one legitimate function from imported DLL by a malicious one.
IAT hooking and inline hooking are generally known as userland rootkits. IAT hooking is a technique that malware uses to change the import address table. When a legitimate application calls an API located in a DLL, the replaced function is executed instead of the original one. In contrast, with inline hooking, malware modifies the API function itself.

IAT hooking and inline hooking are generally known as userland rootkits. IAT hooking is a technique that malware uses to change the import address table. When a legitimate application calls an API located in a DLL, the replaced function is executed instead of the original one. In contrast, with inline hooking, malware modifies the API function itself.

C++:
#include <iostream>
#include <Windows.h>
#include <winternl.h>
// define MessageBoxA prototype
using PrototypeMessageBox = int (WINAPI *)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
// remember memory address of the original MessageBoxA routine
PrototypeMessageBox originalMsgBox = MessageBoxA;
// hooked function with malicious code that eventually calls the original MessageBoxA
int hookedMessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
MessageBoxW(NULL, L"Ola Hooked from a Rogue Senor .o.", L"Ola Senor o/", 0);
// execute the original NessageBoxA
return originalMsgBox(hWnd, lpText, lpCaption, uType);
}
int main()
{
// message box before IAT unhooking
MessageBoxA(NULL, "Hello Before Hooking", "Hello Before Hooking", 0);
LPVOID imageBase = GetModuleHandleA(NULL);
PIMAGE_DOS_HEADER dosHeaders = (PIMAGE_DOS_HEADER)imageBase;
PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)imageBase + dosHeaders->e_lfanew);
PIMAGE_IMPORT_DESCRIPTOR importDescriptor = NULL;
IMAGE_DATA_DIRECTORY importsDirectory = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(importsDirectory.VirtualAddress + (DWORD_PTR)imageBase);
LPCSTR libraryName = NULL;
HMODULE library = NULL;
PIMAGE_IMPORT_BY_NAME functionName = NULL;
while (importDescriptor->Name != NULL)
{
libraryName = (LPCSTR)importDescriptor->Name + (DWORD_PTR)imageBase;
library = LoadLibraryA(libraryName);
if (library)
{
PIMAGE_THUNK_DATA originalFirstThunk = NULL, firstThunk = NULL;
originalFirstThunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)imageBase + importDescriptor->OriginalFirstThunk);
firstThunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)imageBase + importDescriptor->FirstThunk);
while (originalFirstThunk->u1.AddressOfData != NULL)
{
functionName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)imageBase + originalFirstThunk->u1.AddressOfData);
// find MessageBoxA address
if (std::string(functionName->Name).compare("MessageBoxA") == 0)
{
SIZE_T bytesWritten = 0;
DWORD oldProtect = 0;
VirtualProtect((LPVOID)(&firstThunk->u1.Function), 8, PAGE_READWRITE, &oldProtect);
// swap MessageBoxA address with address of hookedMessageBox
firstThunk->u1.Function = (DWORD_PTR)hookedMessageBox;
}
++originalFirstThunk;
++firstThunk;
}
}
importDescriptor++;
}
// message box after IAT hooking
MessageBoxA(NULL, "Hello after Hooking", "Hello after Hooking", 0);
return 0;
}