Служби windows зсередини
Тут описується програмування служб
в ОС Windows (я також буду вживати термін
"Сервіс", що рівнозначно терміну "служба"),
наводиться приклад використання для
завантаження драйверів або руткітів.
При старті ОС запускається менеджер служб (SCM
Manager) .Счітивая дані з реєстру (ім'я
сервісу, яким чином будуть завантажуватися, тип драйвера і т.д.),
він становить базу даних для управління
службами. Я опишу деякі функції, з
допомогою яких можна управляти сервісами.
Спочатку потрібно створити зв'язок з цією
базою даних (SCM database), потім передати
покажчик баз даних деяких функцій,
керуючими сервісами.
Як я вже сказав, перш за все потрібно
створити зв'язок з базою даних SCM. Для цього
служить функція OpenSCManager.
SC_HANDLE OpenSCManager (LPCTSTR lpMachineName, LPCTSTR
lpDatabaseName, DWORD dwDesiredAccess);
LPCTSTR lpMachineName - покажчик на рядок,
завершується нулем, яка вказує на ім'я
локального комп'ютера. цей параметр
можна встановити в NULL.
LPCTSTR lpDatabaseName- покажчик на рядок,
завершується нулем, яка містить в собі ім'я
відкривається бази данних.Етот параметр
також слудует встановити в NULL.
DWORD dwDesiredAccess - цей параметр містить в собі
прапори, означає права доступу до бази
данних.Я не перераховуватиму все прапори, в
даній статті я розглядаю тільки ті
можливості програмування служб, потрібні
для завантаження руткітів.
SC_MANAGER_ALL_ACCESS - стандартні права доступу до БД.
SC_MANAGER_CONNECT - дозволяє з'єднуватися з БД SCM.
SC_MANAGER_CREATE_SERVICE- дозволяє створення нових
сервісів.
Створивши зв'язок з БД SCM, ви можете управляти
сервісами.
Функція OpenService служить для отримання
описателя служби. Врахуйте, що вона не буде
створює службу, для створення служби є
CreateService, а відкриває вже створену раніше
службу.
SC_HANDLE OpenService (SC_HANDLE hSCManager, LPCTSTR
lpServiceName, DWORD dwDesiredAccess);
SC_HANDLE hSCManager - покажчик, повернутий
функцією OpenSCManager.
LPCTSTR lpServiceName - ім'я відкривається сервісу.
DWORD dwDesiredAccess- права з якими ми можемо
відкрити службу. Ось деякі з них:
SERVICE_ALL_ACCESS- це стандартні права доступу.
SERVICE_START-дозволяє запуск роботи сервісу.
SERVICE_STOP-дозволяє зупинку роботи сервісу.
Ця функція повертає покажчик
відкривається служби. Отримавши його ми можемо
керувати службою відповідно до
заданими правами.
Ця функція потрібна для створення сервісу (служби).
SC_HANDLE CreateService (SC_HANDLE hSCManager, LPCTSTR
lpServiceName, LPCTSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType,
DWORD dwStartType, DWORD dwErrorControl, LPCTSTR lpBinaryPathName, LPCTSTR
lpLoadOrderGroup, LPDWORD lpdwTagId, LPCTSTR lpDependencies, LPCTSTR
lpServiceStartName, LPCTSTR lpPassword);
Перший параметр (hSCManager) вказує на
покажчик, повернутий функцією OpenSCManager.
Наступні два параметри вказують на
рядки, що містять ім'я створюваної служби та
ім'я, яке буде використано
призначеним для користувача інтерфейсом. наступний
параметр містить в собі прапори,
що визначають права доступу до служби. тут
використовуються ті ж прапори, що і в функції
OpenService. У більшості випадків знадобиться
установка цього прапора в SERVICE_ALL_ACCESS. параметр
dwServiceType визначає тип створюваного
сервісу. В даному випадку потрібно встановити
його в SERVICE_KERNEL_DRIVER, що в свою чергу
означає, що сервіс буде керувати
драйвером рівня ядра. Інші ж значення
означають, що це буде драйвер файлової
системи і т.д. Параметр dwStartType дуже важливий, тому що
визначає спосіб старту служби. В нашому
І тут його треба встановити в
SERVICE_BOOT_START або SERVICE_AUTO_START, що означає
практично одне і теж - запуск служби у
час запуску самої операційної системи.
Параметр dwErrorControl вказує на спосіб
обробки виникають помилок, в нашому
І тут його треба встановити в SERVICE_ERROR_NORMAL.
Наступний параметр - lpBinaryPathName - покажчик на
завершується нулем рядок, що вказує на
повний шлях до драйвера (в нашому випадку
руткітів), яким управлятиме служба.
Наступні пать параметрів слід
встановити в NULL, тому що вони не важливі в даному
випадку.
Для запуску служби існує функція
StartService.
BOOL StartService (SC_HANDLE hService, DWORD
dwNumServiceArgs, LPCTSTR * lpServiceArgVectors);
SC_HANDLE hService - покажчик служби, повернутий
функцією CreateService або OpenService. параметр
dwNumServiceArgs містить в собі число параметрів,
зазначених в масиві lpServiceArgVectors. В цьому
масиві вказуються параметри, які
будуть передані службі. Врахуйте, що сервіси
драйверів не використовують цей параметр,
тому два останніх параметра в нашому
випадку потрібно встановити в NULL. якщо функція
виконалася успішно, то вона повертає
нульове значення. Функції для зупинки
служби немає, але її можна легко написати з
використанням функції ControlService:
BOOL ControlService (SC_HANDLE hService, DWORD dwControl,
LPSERVICE_STATUS lpServiceStatus);
Параметр dwControl містить прапори, за допомогою
яких ви задаєте, що потрібно зробити з
службою. Якщо вам потрібно зупинити роботу
служби, то можете встановити її в
SERVICE_CONTROL_STOP. За допомогою цієї функції можна і
більш зручно зупиняти і запускати
службу. Наприклад, щоб призупинити роботи сервісу,
встановіть параметр dwControl в SERVICE_CONTROL_PAUSE, а
для продовження роботи в SERVICE_CONTROL_CONTINUE.
Параметр lpServiceStatus - покажчик на структуру
SERVICE_STATUS, куди заноситься поточний статус
служби. Встановіть його в NULL, якщо вам не
важливий поточний статус роботи служби. ця
функція повертає нульове значення при
успішне виконання.
Я перерахував всі необхідні функції для
завантаження руткітів (драйверів) .Для закриття
структури DT SCM використовуйте функцію
CloseServiceHandle. Вона приймає єдиний
параметр - DT SCM, тобто опис, повернутий
функцією OpenSCManager.
Всіх цих функцій цілком достатньо для
завантаження і виконання руткітів. нижче я
приведу приклад використання цих функцій.
#define rootkitname "myrootkit" //
задаємо ім'я нашого руткита
BOOL StopRootkit (SC_HANDLE hService) // Оголошуємо
функції зупинки і старту роботи служби
BOOL StartRootkit (SC_HANDLE hService) //
int main ()
SC_HANDLE hManager, hService; // описатели
SCM бази і служби
LPVTSTR rootkpath = "C: \ myrootkit.sys"; //
повний шлях до нашого руткіта
hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); // створюємо
зв'язок з БД SCM
if (hManager) // якщо все в порядку
hService = CreateService (hManager, rootkitname, rootkitname, SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER, SERVICE_BOOT_START, SERVICE_ERROR_NORMAL, \ rootkpath,
NULL, NULL, NULL, NULL, NULL, NULL); // створюємо
службу, що управляє нашим руткітом
if (hService) // все в порядку?
StartService (hService, NULL, NULL); // запускаємо
створену службу, тим самим запускаючи наш
руткит
>
if (StopRootkit (hService)) // якщо
зупинка пройшла успішно,
StartRootkit (hService); // то заново
запускаємо її
>;
CloseServiceHandle (hManager); // закриваємо
DT SCM (БД SCM).
>
BOOL StopRootkit (SC_HANDLE hService)
BOOL ok = true;
if (hService)
ok = ControlService (hService, SERVICE_CONROL_STOP, NULL); // викликаємо
функцію ControlService з прапором SERVCE_CONTROL_STOP, тим
if (! ok) // самим зупиняючи
роботу сервісу
ok = false;
>;
>;
return ok;
>
BOOL StartRootkit (SC_HANDLE hService)
BOOL ok = true;
if (hService)
ok = ControlService (hService, SERVICE_CONTROL_START, NULL); // викликаємо
функцію ControlService з прапором SERVCE_CONTROL_START, тим
if (! ok) // з амим запускаючи службу
ok = false;
>;
>;
return ok;
>
Цей приклад просто демонструє те, про що я
писав вище. Ви можете додати
додаткові перевірки для
запобігання можливих помилок.
Покажи цю статтю друзям: