Перехоплення api функцій

Привіт, Delphi'сти і їм співчуваючі. Вітаємо мою чергову статтю для чайників. Сьогодні я вам розповім, як треба перехоплювати API функції. Перехоплюючи API функції, ми збільшуємо наші можливості і кордон їм тільки наша уява. Для прочитання цієї статті з максимальною користю обов'язкові хоч початкові знання низкоуровневого програмування і знання архітектури роботи Windows.

Сьогодні я вам розповім найбільш дієву методику перехоплення API функцій - сплайсинг. Сплайсинг це підміна коду функції. Звичайно, є інший метод перехоплення це редагування таблиці імпорту програми. Розповідати буду по порядку.

Коли ви пишете в своєму додатку так

А при виконанні функції відбувається так Push. push. call dword ptr $ 00405F56

Якщо трохи переробити цю формулу, то вона буде виглядати так

Тепер при кожному виклику цільової функції, завжди буде передаватися управління нашому обробнику. А як тепер викликати оригінальну функцію. При установці перехоплення нам треба зберігати перші 5 байт функції. Для виклику оригіналу треба відновлювати всі функції і викликати її, потім знову встановлювати перехоплення. Оголосимо структуру в якій будемо зберігати перші 5 байт функції:

Поле Address фактично в цій структурі не потрібен (він просто ні до чого), але, тим не менш, так зручніше знімати перехоплення, потім самі зрозумієте, навіщо це поле потрібно. Назвемо цю структуру "міст" до старої функції.

Тепер напишемо функцію, яка буде встановлювати перехоплення:

Ми спочатку встановлює атрибути доступу до коду функції, так щоб можна було його переписувати. Потім обчислюємо значення для стрибка. Спочатку зберігаємо початок функції в запис, потім переписуємо початок функції. В кінці встановлюємо старі атрибути доступу. Тепер напишемо функцію яка буде знімати перехоплення:

Тепер напишемо функцію, яка буде встановлювати перехоплення на ім'я функції. Я думаю що вона теж не дуже складна.

Йдемо далі. Описані вище функції можуть перехоплювати функції тільки в поточному процесі. А як нам перехоплювати функції в інших процесах. Найбільш простий метод це засунути перехоплювач функції в DLL і в коді бібліотечної функції встановлювати перехоплення, якщо DLL завантажується в процес і знімати перехоплення, якщо вона вивантажується. Тут ще одна проблема: як змусити інший процес завантажити нашу DLL'ку. Найбільш просте рішення це створення віддалених потоків. Тепер все по порядку.

Віддалений потік створюється функцією CreateRemoteThread.

Функція потоку повинна мати такі атрибути

По ходу напевно WINAPI позначає stdcall це не важливо, що вона позначає, все одно вона повинна бути оголошена як stdcall. У функції тільки один параметр це звичайний покажчик. Тепер проаналізуємо ситуацію: Думаємо: мізкувати: Функція LoadLibraryA має такі ж атрибути. Вона приймає покажчик на перший символ імені файлу DLL (рядок повинен закінчуватися символом # 0). Отже, функція LoadLibraryA повністю підходить для того, що б вона могла виступати в якості функції потоку. Так як вона приймає покажчик на рядок в своєму процесі, нам треба буде записати в пам'ять чужого процесу нашу рядок і ім'ям файлу DLL. Це робиться функцією WriteProcessMemory. Ось її опис

Таким чином, ми завантажили свою DLL в чужій процес. Взагалі - то впровадження свого коду це зовсім інша історія і вимагає написання окремої статті. Іноді процесу не дозволяється зміна пам'яті системних процесів, таких як winlogon.exe, lsass.exe, smss.exe, csrss.exe і ін. Для цього потрібна привілей SeDebugPrivilege в исходник модуля для перехоплення API функцій є функція EnableDebugPrivilege яка включає цей привілей для поточного процесу.

Щоб встановити перехоплення на API функції у всіх процесах (у всіх GUI процесах) досить просто завантажити нашу DLL. Достатньо написати ось такий код:

В архіві з кодами є модуль з функціями перехоплення API там є всі функції, які я сьогодні використовував і описував.

Ось, мабуть, і все на сьогодні. В архіві так само є приклад приховування процесу lsass.exe.

Схожі статті