Найти в Дзене
Под капотом ПО

🔍 Магия хукинга: Перехватываем функции через таблицы и деторисы

Ключевая идея: Хуки позволяют перехватывать вызовы функций, изменять их поведение и создавать мощные инструменты для анализа и модификации ПО - от отладчиков до игровых модов. Хук (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, cons
Оглавление

Ключевая идея:

Хуки позволяют перехватывать вызовы функций, изменять их поведение и создавать мощные инструменты для анализа и модификации ПО - от отладчиков до игровых модов.

🧩 Что такое хук функции?

Хук (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" и логируйте все открываемые файлы. Делитесь результатами в комментариях!