1. Введення Rootkit (руткит, від англ. Root kit, тобто «набір root'а») - програма або набір програм для приховування слідів присутності зловмисника або шкідливої програми в системі. Термін Rootkit історично прийшов зі світу UNIX, і під цим терміном розуміється набір утиліт або спеціальний модуль ядра, які зломщик встановлює на зламаній їм комп'ютерній системі відразу після отримання прав суперкористувача. Цей набір, як правило, включає в себе різноманітні утиліти для «замітання слідів» вторгнення в систему, сніфери, сканери, кейлоггери, троянські програми, які заміщають основні утиліти UNIX (в разі неядерного руткита). Rootkit дозволяє зломщикові закріпитися у зламаній системі і приховати сліди своєї діяльності шляхом приховування файлів, процесів, а також самої присутності руткита в системі. Говорячи про руткіти, неодмінно згадують етимологію терміна rootkit: "root" - привілейований адміністратор UNIX-системи, "kit" - набір інструментів, rootkit - набір утиліт для забезпечення «привілейованого» доступу зловмисника до системи непомітно для справжнього адміністратора. Такі утиліти для UNIX з'явилися на початку 90-х рр. і існують досі, але практично не розвиваються. У Windows-руткітів був ближчий за функціоналом попередник, ніж UNIX-руткіти - а саме, стелс-віруси для DOS. Стелс-віруси з'явилися близько 1990 року. На відміну від UNIX-руткітів, основне завдання яких - впустити зловмисника в систему і маскувати його дії, стелс-віруси DOS, заражаючи файли, просто приховували себе від користувача і антивірусних програм. Windows-руткіти з'явилися десятьма роками пізніше стелс-вірусів, і те, що їх назвали саме руткитами, а не стелс-вірусами, заслуга виключно Грега Хогланда (Greg Hoglund). Він був одним з перших, хто реалізував техніку обходу системних механізмів захисту Windows в формі утиліти, націленої на приховування інформації в системі. Результати його роботи були опубліковані в електронному журналі PHRACK. Утиліта, названа автором NT Rootkit, згодом була застосована в багатьох шкідливих програмах і по сей день надихає дослідників і руткітостроітелей. Стаття Хогланда датована 1999 роком. У ній він спирається на дослідження ядра Windows, опубліковані роком раніше в форумах Usenet програмістом з Шрі-Ланки. Ще раніше, починаючи з 1995 року, Джефрі Ріхтер (Jeffrey Richter) в своїй книзі «Advanced Windows» і четвертому її виданні «Programming Applications for Microsoft Windows» розкриває технології перехоплення системних викликів на рівні користувача, які будуть згодом використані в багатьох руткітів з точністю до наведеного в книзі вихідного коду. Техніки перехоплення системних викликів на рівні ядра загальнодоступним розкриті в двох інших класичних книгах з програмування: С. Шрайбер «Недокументовані можливості Windows 2000», 2001 р (Sven Schreiber Undocumented Windows 2000 secrets) і П. Дабак і ін. «Недокументовані можливості Windows NT », 1999 р (P. Dabak et al Undocumented Windows NT). Дослідження системних механізмів захисту Windows продовжилися, і слідом за NT Rootkit було випущено ще кілька утиліт, що дозволяють приховувати об'єкти в операційній системі. У 2000 році з'явився he4hook - проект російського програміста. Утиліта не несла в собі шкідливого функціоналу, але була інструментом для приховування файлів і працювала в режимі ядра. Крім цього, утиліта самим автором не позначалася як руткіт. У 2002 році на світ з'явився Hacker Defender (HacDef). Це також лише інструмент, але вже більш потужний - за допомогою нього можна приховати будь-який файл, процес або ключ реєстру, параметри гнучко налаштовуються у файлі конфігурації. Працює переважно в режимі користувача. У 2003 році з'явилися Vanquish і Haxdoor (він же A-311 Death і в модифікованому варіанті Nuclear Grabber). Vanquish - інструмент, що працює в режимі користувача і дозволяє приховувати файли, директорії, а також ключі реєстру. Крім того, в ньому вже передбачена шкідлива функція - логгірованіе паролів. Haxdoor - це вже повноцінний бекдор, що працює в режимі ядра і використовує руткіт-технології для самомаскіровкі. У 2004 році випущена FU - утиліта для приховування процесів, яка реалізувала принципово нову технологію, засновану на зміні самих системних структур, а не шляхів доступу до них. Всі перераховані руткіти є ключовими в історії Windows-руткітів. Особливо варто відзначити HacDef, Haxdoor і FU, широко розповсюджувалися "в дикому вигляді" в зв'язці з шкідливими програмами. Руткіти цього періоду (2000-2004) чітко вписуються в загальноприйняту, але застарілу класифікацію: руткит може функціонувати на рівні користувача (user level) або на рівні ядра (kernel level), на основі модифікації ланцюжка системних викликів (Execution Path Modification) або на основі прямого зміни системних даних (Direct Kernel Objects Manipulation). В середині 2000-х близько 80% всіх руткітів доводилося на HacDef і Haxdoor. Першими серед вже існуючих шкідливих програм, куди почали вбудовуватися руткит-технології, були багатофункціональні бекдори Rbot і SdBot. Трохи пізніше - близько 2006 року - руткит-технології почали вбудовувати в популярні e-mail-черви (Bagle) і троянці-шпигуни (Goldun), ще пізніше з'явився Mailbot (Rustock), який опинився серйозним викликом для антивірусних продуктів. Після тривалого затишшя на початку 2008 року з'явилася нова шкідлива програма, що заражає завантажувальний сектор диска. У антивірусних базах різних виробників вона називається Sinowal, Mebroot, StealthMBR. Цей руткит, більше відомий як «буткіт» в силу своєї «завантажувальної» специфіки, заснований на коді концептуальної розробки eEye Bootroot (трохи зміненому) і являє собою не стільки самостійну шкідливу програму, скільки інструмент для приховування будь-якого троянця. За рівнем привілеїв Рівня користувача (user-mode) Рівня ядра (kernel-mode) За принципом дії змінюють алгоритми виконання системних функцій (Modify execution path) змінюють системні структури даних (Direct kernel object manupulation) Мал. 1. Класифікація руткітів 4 Методи перехоплення API функцій в режимі користувача (user mode) Описи методик перехоплення функцій забезпечені схемами їх роботи, при цьому червона пунктирна стрілка показує втручання RootKit в процес роботи програми, червоні стрілки показують відхилення в логіці роботи, викликані втручанням RootKit. Перехоплення функцій дозволяє RootKit модифікувати результати їх роботи - наприклад, перехоплення функції пошуку файлу на диску дозволяє виключити з результатів пошуку маскуються файли, а перехоплення функцій типу ntdll.ZwQuerySystemInformation дозволяє замаскувати запущені процеси і завантажені бібліотеки. 4.1 Принцип виклику API функції Перед розглядом принципів роботи RootKit призначеного для користувача режиму необхідно коротко і спрощено розглянути принцип виклику функцій, розміщених в DLL. Відомо два базових способу: 1.Ранньої зв'язування (статично імпортовані функції). Цей метод заснований на тому, компілятору відомий перелік імпортованих програмою функцій. Спираючись на цю інформацію, компілятор формує так звану таблицю імпорту EXE файлу. Таблиця імпорту - це особлива структура (її розташування і розмір описуються в заголовку EXE файлу), яка містить список використовуваних програмою бібліотек і список імпортованих з кожної бібліотеки функцій. Для кожної функції в таблиці є поле для зберігання адреси, але на стадії компіляції адреса не відомий. У процесі завантаження EXE файлу система аналізує його таблицю імпорту, завантажує всі перераховані в ній DLL і виробляє занесення в таблицю імпорту реальних адрес функцій цих DLL. У раннього зв'язування є істотний плюс - на момент запуску програми всі необхідні DLL виявляються завантаженими, таблиця імпорту заповнена - і все це робиться системою, без участі програми. Але відсутність в процесі завантаження зазначеної в його таблиці імпорту DLL (або відсутність в DLL необхідної функції) призведе до помилки завантаження програми. Крім того, дуже часто немає необхідності завантажувати всі використовувані програмою DLL в момент запуску програми. На малюнку показаний процес раннього зв'язування - в момент завантаження відбувається заповнення адрес в таблиці імпорту (крок 1), в момент виклику функції з таблиці імпорту береться адреса функції (крок 2) і відбувається власне виклик функції (крок 3); Рис.2 Раннє зв'язування 2.Позднее зв'язування. Відрізняється від раннього зв'язування тим, що завантаження DLL проводиться динамічно за допомогою функції API LoadLibrary. Ця функція знаходиться в kernel32.dll, тому якщо не вдаватися до хакерських прийомів, то kernel32.dll доведеться завантажувати статично. За допомогою LoadLibrary програма може завантажити потрібну її бібліотеку в будь-який момент часу. Відповідно для отримання адреси функції застосовується функція kernel32.dll GetProcAddress. На малюнку крок 4 відповідає завантаженні бібліотеки за допомогою LoadLibrary і визначенню адрес за допомогою GetProcAddress. Далі можна викликати функції DLL (крок 5), але природно при цьому таблиця імпорту не потрібна. Щоб не викликати GetProcAddress перед кожним виклику функції з DLL програміст може одноразово визначити адреси цікавих йому функцій і зберегти їх в масиві або деяких змінних. Незалежно від методу зв'язування системі необхідно знати, які функції експортує DLL. Для цього у кожної DLL є таблиця експорту - таблиця, в якій перераховані експортовані DLL функції, їх номери (ордіналов) і відносні адреси функцій (RVA). 4.2 Модифікація машинного коду прикладної програми. В цьому випадку модифікується машинний код, який відповідає в прикладній програмі за виклик тієї чи іншої функції API. Це методика складна в реалізації, тому що існує безліч мов програмування, версій компіляторів і програміст може реалізувати виклик API функцій різними методиками. Але теоретично таке можливе за умови, що впровадження буде йти в заздалегідь задану програму відомої версії. В цьому випадку можна проаналізувати її машинний код і розробити перехоплювач. Рис.3 Модифікація машинного коду прикладної програми 4.3 Модифікація таблиці імпорту Дана методика описана в книзі Ріхтера і є однією з класичних. Ідея методу проста - RootKit знаходить в пам'яті таблицю імпорту програми і виправляє адреси цікавих йому функцій на адреси своїх перехоплювачів (природно, він попередньо десь у себе запам'ятовує правильні адреси). У момент виклику API функції програма зчитує її адресу з таблиці імпорту і передає за цією адресою управління. Методика універсальна, але у неї є істотний недолік (і його добре видно на схемі) - перехоплюються тільки статично імпортовані функції. Але є і плюс - методика дуже проста в реалізації і є маса прикладів, які демонструють її реалізацію. Пошук таблиці імпорту в пам'яті не представляє особливої складності, оскільки для цього існують спеціалізовані API функції, що дозволяють працювати з образом програми в пам'яті. Оригінальний текст такого перехоплювача на мові C займає кілька аркушів друкованого тексту; Мал. 4 Модифікація таблиці імпорту 4.4 Перехоплення функцій LoadLibrary і GetProcAddress Перехоплення функцій LoadLibrary і GetProcAddress може бути здійснене будь-яким методом, в класичній реалізації застосовується методика 2 - модифікація таблиці імпорту. Ідея методики проста - якщо перехопити GetProcAddress, то при запиті адреси можна видавати програмі не реальні адреси цікавлять її функцій, а адреси своїх перехоплювачів. Як і в методі 2 програма «не відчує» різниці. При виклику GetProcAddress вона отримує адресу і виконує виклик функції. У даного методу є мінус - він не дозволяє перехопити статично імпортовані функції; Мал. 5 Перехоплення функцій LoadLibrary і GetProcAddress 4.5 Метод, що поєднує методику 2 і 3 У даній методиці модифікується таблиця імпорту, причому в обов'язковому порядку перехоплюються функції LoadLibrary і GetProcAddress бібліотеки kernel32.dll. В цьому випадку при виклику статично імпортованих функцій спотворені адреси беруться з таблиці імпорту, при динамічному визначенні адреси викликається перехоплена функція GetProcAddress, яка повертає адреси функцій-перехоплювачів. В результаті у програми не залишається шансів дізнатися правильну адресу функції. Мал. 6 Метод поєднує Перехоплення функцій LoadLibrary і GetProcAddress і модифікацію таблиці імпорту 4.6 Модифікація програмного коду API функції. Дані метод складніше в реалізації, ніж підміна адреси. Методика полягає в тому, що RootKit знаходить в пам'яті машинний код цікавлять його функцій API і модифікує його. При такому методі перехоплення функції вже немає потреби в модифікації таблиці імпорту запущених програм і передачі програм перекручених адрес при виклику GetProcAddress. З точки зору виклику функції все залишається «як є» за одним винятком - тепер уже по «правильному» адресою всередині «правильної» DLL знаходиться машинний код RootKit. Рис.7. Модифікація програмного коду API функції. Найчастіше втручання в машинний код перехоплюваних функцій мінімально. На початку функції розміщується не більше 2-3 машинних команд, що передають управління основної функції-перехоплювачі. Щоб здійснити дзвінок модифікованих функцій RootKit повинен зберегти вихідний машинний код для кожної модифікованої їм функції (природно, зберігається не весь машинний код функції, а змінені під час перехоплення байти). Саме така методика перехоплення реалізована в широко відомому HackerDefender і бібліотеці AFX Rootkit (www.rootkit.com). 4.7. Модифікація бібліотек DLL на диску Дана методика полягає в тому, що системна бібліотека модифікується на диску. Методи модифікації аналогічні описаним вище, тільки зміни виробляються не в пам'яті, а на диску. Подібна методика не отримала широкого розповсюдження. 5 Перехоплення функцій в режимі ядра (kernel mode) Рис.8 Перехоплення функцій в режимі ядра Для розуміння типовий для методики перехоплення функцій в режимі ядра слід розглянути принципи взаємодії бібліотек користувацького режиму і ядра. Розглянемо це взаємодія на спрощеній схемі: Основна взаємодія з ядром проводиться через ntdll.dll, більшість функцій якої є перехідниками, які звертаються до ядра через переривання INT 2Eh (слід зауважити, що прикладній програмі ніщо не заважає безпосередньо викликати INT 2Eh). Подальше звернення до функцій ядра заснована на структурі, іменованої KeServiceDescriptorTable (або скорочено SDT), розташованої в ntoskrnl.exe. SDT - це таблиця, яка містить адреси точок входу сервісів ядра NT. Опис функцій і методик перехоплення можна знайти в книзі Свена Шрайбера «Недокументовані можливості Windows 2000», там же наведена схема взаємодії, яка послужила прототипом для наведеної тут схеми. Спрощено можна сказати, що для перехоплення функцій необхідно написати драйвер, який зробить модифікацію таблиці SDT. Перед модифікацією драйверу необхідно зберегти адреси перехоплюваних функцій і записати в таблицю SDT адреси своїх обробників. Даний метод чимось нагадує перехоплення переривань в MSDOS або описану вище методику 2. Цей метод часто називають перехопленням Native API і природно він працює тільки в NT (і відповідно W2K, XP, W2003). Слід зазначити, що перехоплення Native API здійснюють не тільки руткіти - існує маса корисних програм, перехоплюючих функції за допомогою редагування SDT - як приклад можуть служити популярна утиліта RegMon від SysInternals або програма Process Guard. Слід зазначити, що описаний метод є найбільш простим, але далеко не єдиним. Існує ще ряд способів, зокрема створення драйвера-фільтра. Драйвер-фільтр може застосовуватися як для вирішення завдань моніторингу (класичний приклад - утиліта FileMon від SysInternals), так і для активного втручання в роботу системи. Зокрема, драйвер-фільтр може застосовуватися для маскування файлів і папок на диску. Принцип роботи такого драйвера заснований на маніпуляціях з пакетами запиту вводу-виводу (IRP). Ситуація в UNIX дуже нагадує ситуацію в світі Windows. Атакуючий встановлює rootkit на комп'ютер після того, як був отриманий привілейований доступ - root. Права root, необхідні для інсталяції переважної більшості rootkit, можна отримати за допомогою використання відомих вразливостей, якщо зловмисник має доступ в систему з правами звичайного користувача. У цьому випадку він може використовувати локальний експлойт або утиліти для злому бази з паролями. Якщо зловмисник не має відповідних прав, то для проникнення в систему він може використовувати віддалений експлойт або, наприклад, сниффер для перехоплення паролів. Подібний перехоплення паролів можливий для цілого ряду служб (ftp, telnet та ін.) У зв'язку з тим, що вони здійснюють передачу паролів по мережі у відкритому вигляді. Залежно від можливостей, що надаються rootkit може містити різні шкідливі програми (Trojan-DDoS, Backdoor і інші), які встановлюються на зламаний комп'ютер і очікують команд від атакуючого. Крім того, rootkit можуть містити заплатки, які закривають уразливості в захисті системи з метою запобігання повторного проникнення з боку іншого атакуючого. Також як і в Windows, в UNIX є і rootkit рівня додатків, і rootkit рівня ядра. Розглянемо рівень Додатків. Як правило, подібні rootkit складаються з «троянізірованних» версій звичайних програм, що приховують присутність своїх компонент в системі, і бекдора, що надає прихований доступ в систему. Прикладами rootkit рівня додатків є lkr, trOn, ark і ін. Продемонструємо роботу rootkit рівня додатків на прикладі tr0n. Для приховування своєї присутності в системі даний rootkit виконує цілий ряд дій: в момент інсталяції він зупиняє syslogd-демон, потім підмінює своїми троянськими версіями наступні системні утиліти du, find, ifconfig, login, ls, netstat, ps, top, sz. Крім того, в систему додається троянська версія sshd-демона. На завершення, у фоновому режимі запускається sniffer, в inetd.conf додається запуск telnetd-, rsh-, finger-демонів, перезапускается inetd і знову стартує syslogd. Зазвичай tr0n розташовується в /usr/src/.puta, але завдяки встановленій раніше троянської версії утиліти ls, цей каталог невидимий. Перейдемо до rootkit рівня ядра. Rootkit цього типу надають всі можливості попереднього типу, але на більш низькому рівні - rootkit рівня додатків повинні модифікувати окремі бінарні файли, rootkit рівня ядра повинні змінити лише ядро, що значно збільшує «якість» приховування інформації. Існує кілька способів впровадження rootkit в ядро системи UNIX: Використання LKM. Ядро linux, як і ядра багатьох інших ОС, здатні завантажувати модулі (або драйвери пристроїв) «на льоту», що дозволяє зловмисникові змінити системні виклики ядра і тим самим видавати некоректну інформацію (наприклад, виправлений список файлів). Використання подібного прийому можна запобігти, якщо скомпілювати монолітне ядро без підтримки LKM, але таке рішення має істотний недолік - необхідність включення в ядро всіх потрібних драйверів. Запис в / dev / kmem, який надає доступ до зайнятої ядром області пам'яті. Запис в / dev / kmem переписує ядро «на льоту». Таким чином, для зміни ядра необхідно лише знайти потрібне місце в пам'яті, але це розв'язувана проблема. Існує виправлення, яке забороняє записувати в / dev / kmem безпосередньо. Також це можна зробити через mmap. Зараження існуючих модулів. Відмінність від першого способу полягає в тому, що rootkit не містить свого окремого модуля і використовує впровадження в уже існуючі. Застосування даного підходу дозволяє зробити rootkit стійким до перезавантаження, оскільки найчастіше заражаються модулі, які будуть завантажені ОС в будь-якому випадку (наприклад, драйвер файлової системи). 7 Методики виявлення RootKit в системі Розглянемо базові методики пошуку RootKit: Порівняння двох «знімків» системи (наприклад, списку файлів на диску). Перший знімок робиться на перевіреній системі, другий - після завантаження з CD або підключення досліджуваного HDD до свідомо чистому комп'ютера. Подібна методика гарантовано дозволить виявити будь-RootKit, який маскує на диску свої файли. Порівняння даних, що повертаються API функціями різного рівня і (або) одержуваних низькорівневими методами (наприклад, прямим читанням диска і аналізом файлів реєстру). Дана методика не вимагає перезавантаження досліджуваного ПК і реалізована в безкоштовній утиліті RootkitRevealer від SysInternals (http://www.sysinternals.com). Іншим прикладом може злучити утиліта KLister (www.rootkit.com) для побудови списку запущених процесів, яка складається з драйвера і консольної програми, що використовує цей драйвер; Аналіз в пам'яті функцій основних бібліотек на предмет наявності змін їх машинного коду. Даний метод найбільш ефективний для боротьби з RootKit в призначеному для користувача режимі. Подібна методика дозволяє не тільки виявити перехоплення функцій, але і відновити нормальну роботу пошкоджених функцій. Крім того, порівняння «знімків» системи, отриманих до і після відновлення функцій API в багатьох випадках дозволяє виявити маскуються процеси, сервіси та драйвери. Дана методика не вимагає перезавантаження і один з варіантів реалізований в моїй утиліті AVZ; Аналіз і відновлення ServiceDescriptorTable. Дана методика дозволяє боротися з рядом перехоплювачів, які працюють в режимі ядра (власне, з перехоплювачами, заснованими на виправлення SDT). Практична реалізація - утиліта SDTRestore (http://www.security.org.sg/code/sdtrestore.html). Однак відновлення SDT вплине на роботу всієї системи і може призвести до дуже неприємних наслідків (в найпростішому випадку - повне зависання системи з виходом на BSoD, в гіршому - непередбачуване порушення нормальної роботи додатків, перехоплюючих NativeAPI для реалізації своїх функцій). Описані вище базові методики перехоплення функцій пояснюють основні принципи роботи RootKit. Однак слід пам'ятати, що розробники RootKit-технологій не стоять на місці, в результаті постійно з'являються нові розробки, підходи і методи. Практика показує, що розробники шкідливих програм (вірусів, троянських програм, шпигунського ПЗ) все частіше починають використовувати RootKit-технології, що істотно ускладнює виявлення і видалення створених ними шкідливих програм. Найчастіше застосовуються методики перехоплення функцій в режимі користувача, але останнім часом з'явилися досить ефективні реалізації із застосуванням драйверів. У цьому плані за моєю статистикою найбільш «знаменитий» Backdoor.Win32.Haxdoor, який встановлює в систему кілька драйверів, що дозволяє йому досить ефективно маскуватися від виявлення користувачем. Можливості rootkit і боротьба з ними http://www.cybersecurity.ru/manuals/crypto/law/5734.html Windows під прицілом http://www.securitylab.ru/contest/212106.php Невидимі LKM-атаки на Windows NT: куховарська книга руткітмейкера http://www.xakep.ru/post/40549/default.asp Для підготовки даної роботи були використані матеріали з сайту http://referat.ru/ Дата додавання: 20.01.2010