Windows C++ / IAT Hooking
Author | Unprotect |
Platform | Windows |
Language | C++ |
Technique | IAT Hooking |
Description:
Original source code: https://www.ired.team/offensive-security/code-injection-process-injection/import-adress-table-iat-hooking
Code
#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;
}
Created
June 19, 2022
Last Revised
April 22, 2024