Ключевая идея:
Хуки позволяют перехватывать вызовы функций, изменять их поведение и создавать мощные инструменты для анализа и модификации ПО - от отладчиков до игровых модов.
🧩 Что такое хук функции?
Хук (hook) - это техника перехвата вызова функции с целью:
- Изменить аргументы или возвращаемое значение
- Заменить выполнение своей функцией
- Проанализировать параметры (логирование)
- Обойти защиту или расширить функционал
Примеры применения:
- Читы для игр (бессмертие, бесконечные патроны)
- Антивирусы (сканирование вызовов API)
- Отладчики (трассировка вызовов)
- Модификации ПО (добавление функций)
📚 Основные техники хукинга
1. IAT Hooking (Таблица импорта)
Каждая Windows-программа содержит IAT (Import Address Table) - таблицу адресов импортируемых функций (например, из kernel32.dll).
Как работает:
1. Находим IAT целевой программы
2. Заменяем адрес MessageBoxA на адрес нашей функции
3. При вызове MessageBoxA управление передается нам
// Пример: Поиск IAT в памяти процесса
IMAGE_IMPORT_DESCRIPTOR* GetIAT(HMODULE hModule, const char* dllName) {
ULONG size;
return (IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToData(
hModule, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size);
}
2. Inline Hooking
Прямая модификация кода целевой функции:
1. Перезаписываем первые байты функции JMP-инструкцией
2. В хуке выполняем свой код
3. Вызываем оригинальную функцию (опционально)
asm
; Оригинальная функция:
775F0100: 6A 00 push 0
775F0102: 68 00 10 00 00 push 1000h
; После хука:
775F0100: E9 00 10 00 00 jmp my_hook ; Переход на наш хук
775F0105: 90 nop ; Выравнивание
3. Detours (Библиотека Microsoft)
Microsoft Detours - популярная библиотека для перехвата функций. Автоматически создает "трамплин" для перехода.
#include <detours.h>
// Оригинальная функция
static int (WINAPI *Real_MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT) = MessageBoxA;
// Наша функция-хук
int WINAPI Hooked_MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {
// Меняем текст сообщения
return Real_MessageBoxA(hWnd, " HOOKED! ", lpCaption, uType);
}
// Установка хука
void InstallHook() {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)Real_MessageBoxA, Hooked_MessageBoxA);
DetourTransactionCommit();
}
🔧 Практический пример: Хук MessageBoxA
Шаг 1: Создаем DLL-проект в Visual Studio
Шаг 2: Реализуем хук в DllMain
#include "pch.h"
#include <Windows.h>
#include <detours.h>
// Указатель на оригинальную функцию
static int (WINAPI* Original_MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT) = MessageBoxA;
// Наша функция-хук
int WINAPI Hooked_MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {
// Изменяем параметры
const char* newText = "Хук сработал!\n";
char modifiedText[256];
strcpy_s(modifiedText, newText);
strcat_s(modifiedText, lpText);
// Вызываем оригинальную функцию
return Original_MessageBoxA(hWnd, modifiedText, lpCaption, uType);
}
// Точка входа DLL
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved) {
if (reason == DLL_PROCESS_ATTACH) {
// Устанавливаем хук
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)Original_MessageBoxA, Hooked_MessageBoxA);
DetourTransactionCommit();
}
else if (reason == DLL_PROCESS_DETACH) {
// Удаляем хук
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)Original_MessageBoxA, Hooked_MessageBoxA);
DetourTransactionCommit();
}
return TRUE;
}
Шаг 3: Инжектируем DLL в целевой процесс
// Инжектор (отдельное приложение)
void InjectDLL(DWORD pid, const char* dllPath) {
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
LPVOID pDllPath = VirtualAllocEx(hProcess, NULL, strlen(dllPath) + 1,
MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, pDllPath, dllPath, strlen(dllPath) + 1, NULL);
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"),
pDllPath, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
VirtualFreeEx(hProcess, pDllPath, 0, MEM_RELEASE);
CloseHandle(hProcess);
}
⚠️ Важные предостережения
1. Стабильность: Любая ошибка в хуке может привести к крашу программы
2. Античиты: Современные игры детектят хуки (сканирование памяти, проверка контрольных сумм)
3. Многопоточность: Хуки должны быть потокобезопасными
4. Восстановление: Всегда удаляйте хуки перед выгрузкой DLL
5. Законность: Модификация ПО может нарушать лицензионные соглашения
Обход детектов:
// Пример: Скрытие DLL от детекторов
void HideDLL(HMODULE hModule) {
// Удаляем запись из PEB->Ldr
PPEB pPeb = (PPEB)__readgsqword(0x60);
LIST_ENTRY* pList = &pPeb->Ldr->InMemoryOrderModuleList;
for (LIST_ENTRY* pEntry = pList->Flink; pEntry != pList; pEntry = pEntry->Flink) {
PLDR_DATA_TABLE_ENTRY pEntryData = CONTAINING_RECORD(
pEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
if (pEntryData->DllBase == hModule) {
pEntry->Blink->Flink = pEntry->Flink;
pEntry->Flink->Blink = pEntry->Blink;
break;
}
}
}
🧪 Альтернативные инструменты
1. MinHook: Легковесная альтернатива Detours
2. Frida: Кроссплатформенный фреймворк для динамического анализа
3. DLL Proxying: Подмена оригинальной DLL
4. VMT Hooking: Перехват вызовов в C++ виртуальных таблицах
Пример MinHook:
#include <MinHook.h>
MH_Initialize();
MH_CreateHook(&MessageBoxA, &Hooked_MessageBoxA, (LPVOID*)&Original_MessageBoxA);
MH_EnableHook(&MessageBoxA);
🎓 Заключение: Когда использовать хуки
1. Отладка сложных систем: Анализ вызовов между компонентами
2. Создание модификаций: Добавление функций в закрытое ПО
3. Анализ безопасности: Исследование вредоносного ПО
4. Разработка инструментов: Профилировщики, трейсеры
💡Золотое правило:
"Хуки должны быть последним средством, когда другие методы недоступны"
P.S. Для экспериментов используйте тестовые приложения и виртуальные машины. Нарушение работы лицензионного ПО может быть незаконным!
🧠 Контрольный чеклист хукинга
Прежде чем внедрять хук:
- Понимаете ли вы API функции?
- Учли ли вы соглашение вызова (cdecl, stdcall)?
- Проверили ли многопоточную безопасность?
- Есть ли план восстановления оригинальной функции?
- Проверили ли на детектирование античит-системами?
Помните: С большой силой приходит большая ответственность! Используйте знания во благо 😊
P.S. Попробуйте создать хук для функции "CreateFileA" и логируйте все открываемые файлы. Делитесь результатами в комментариях!