Методи перехоплення API-викликів у Win32 - Банк рефератів, творів, доповідей, курсових і
Ігор В. Філімонов
Перехоплення системних функцій операційної системи – прийом, відомий давно. Зазвичай перехоплюється деяка системна функція з моніторингу чи зміни її поведінки. За часів DOS програмісти перехоплювали програмні переривання (int 21h, int 16h, int 10h). З приходом Win16 були потрібні кошти для перехоплення API-функцій. І, нарешті, з появою Win32 засоби перехоплення ще раз еволюціонували, підлаштовуючись під нову систему. Операційні системи сімейства Windows ніколи не містили вбудованих засобів, спеціально призначених для перехоплення системних функцій. І зрозуміло чому – таки це трохи хакерський прийом. Тому перехоплення зазвичай здійснюється «підручними засобами», і його реалізації потрібно чітко представляти багато глибинні аспекти пристрою та функціонування операційної системи.
У цій статті розглядаються методи реалізації перехоплення системних API-функцій у 32-розрядних операційних системах Windows. Розглядаються особливості реалізації перехоплення Win9X (Windows 95/98/98SE/ME) і WinNT (Windows NT/2000/XP/2003).
Особливості організації пам'яті у Windows
Оскільки перехоплення майже завжди пов'язані з модифікацією пам'яті (або коду функції, що перехоплюється, або таблиць імпорту/експорту), то для його здійснення необхідно враховувати особливості архітектури пам'яті WinNT і Win9X.
Адресний простір будь-якого процесу у Win9Х можна розділити на три розділи:
Молодші два гігабайти (00400000-7FFFFFFF) – код і дані режиму користувача (в діапазоні 00000000-003FFFFF розташовані розділи для виявлення нульових покажчиків і для сумісності з програмами DOS і Win16);
Третій гігабайт – для загальних файлів, що проектуютьсяв пам'ять (MMF) і системних DLL.
Четвертий гігабайт – для коду та даних режиму ядра (тут розташовується ядро операційної системи та драйвери).
Всі ці відмінності суттєво впливають на способи реалізації перехоплення функцій, розташованих у системних DLL.
Перехоплення можна розділити на два типи: локальні (перехоплення в межах одного процесу) та глобальні (у масштабах усієї системи).
Локальний перехоплення
Локальний перехоплення з використанням розділу імпорту
void CAPIHook::ReplaceIATEntryInOneMod(PCSTR pszCalleeModName,
PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller)
if (pImportDesc == NULL)
return; //Тут її немає
//Знайдемо потрібний модуль
for (; pImportDesc->Name; pImportDesc++)
PSTR pszModName = (PSTR)((PBYTE) hmodCaller + pImportDesc->Name);
if (lstrcmpiA(pszModName, pszCalleeModName) == 0)
if (pImportDesc->Name == 0)
return; //Жодна функція не імпортується
(PIMAGE_THUNK_DATA)((PBYTE) hmodCaller + pImportDesc->FirstThunk);
//Переберемо всі функції, що імпортуються
for (; pThunk->u1.Function; pThunk++)
BOOL fFound = (*ppfn == pfnCurrent); //Його шукаємо?
if (!fFound && (*ppfn > sm_pvMaxAppAddr))
// Якщо не знайшли, то пошукаємо глибше.
// Якщо ми у Win98 під відладчиком, то
PBYTE pbInFunc = (PBYTE) * ppfn;
if (pbInFunc[0] == cPushOpCode)
fFound = (*ppfn == pfnCurrent);
// Дозволимо запис до цієї сторінки
VirtualProtect(ppfn, sizeof(ppfn), PAGE_EXECUTE_READWRITE, &dwDummy);
WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,
VirtualProtect(ppfn, sizeof(ppfn), dwDummy, &dwDummy);
//Тут цієї функції не знайшлося
При реалізації цього методу слід враховувати, що виклики з бібліотеки DllMain, в якій знаходиться функція, що перехоплюється, перехопити не вдасться. Це пов'язано з тим, що перехоплення може бути здійснено тільки після закінчення LoadLibrary, а до цього часу DllMain вже буде викликана. Звичайно, можна написати свій варіант LoadLibrary (приклади завантаження DLL «вручну» існують) і здійснювати перехоплення між завантаженням DLL та викликом DllMain, але це дуже ускладнює завдання.
Основною перевагою даного методу є те, що він однаково реалізується як Win9X, так і WinNT.
У Windows NT функції Module32First і Module32Next не реалізовані, і для перерахування модулів процесу замість них доведеться скористатися функціями PSAPI.dll.
Локальне перехоплення за допомогою зміни функції, що перехоплюється (тільки WinNT)
Існує безліч прикладів цього методу. Я розгляну метод, який пропонує Microsoft – Detours library.
Detours – це перша офіційна бібліотека, призначена для перехоплення функцій (не лише системних, а й будь-яких інших). До основних понять Detours відносяться:
цільова функція (target function) - функція, перехоплення якої здійснюється;
функція-перехоплювач (detour function) - функція, що заміщає перехоплювану;
функція-трамплін (trampoline function) – функція, що складається із заголовка цільової функції та команди переходу до решти коду цільової функції.
Trampoline у перекладі з англійської - "батут", проте словосполучення "функція-трамплін" більш точно передає логіку її роботи.
Таким чином, якщо цільова функція має наступний заголовок: