Поиграем с туксом в прятки Крис Касперски ака мыщъх Хакер, номер #077, стр. 077-102-1 Обзор методик стелсирования на уровне ядра Сегодня я расскажу, как спрятать свои файлы, процессы и сетевые соединения в Linux дистрибутиве с ядрами версий 2.4 и 2.6, обобщая опыт хакерских атак нескольких последних лет. Это не руководство по настройке adore, которых пруд пруди в сети, это самоучитель по созданию собственных rootkit'ов, намного более крутых, надежных и неуловимых, чем adore и knark вместе взятых. [введение] Проникнуть на атакуемую машину это еще не все. Необходимо закрепиться в системе, спрятать свои файлы, процессы и сетевые соединения, иначе придет админ и разрулит ситуацию. Этим занимается adore, knark и другие rootkit'ы, которые легко найти в сети, правда не все из них работают. К тому же против любого широко распространенного rootkit'а, каким бы хитроумным он ни был, разработаны специальные методы борьбы. Настоящий хакер тем и отличается от жалкого подобия своих подражателей, что разрабатывает весь необходимый инструментарий самостоятельно или, в крайнем случае, адаптирует уже существующий. Хочешь узнать, как это сделать? Тогда читай эту статью до конца. [модуль раз, модуль два] Подавляющее большинство методик стелсирования работает на уровне ядра, пристыковываясь к нему в виде загружаемого модуля (Loadable Kernel Module или сокращенно LKM). В программировании модулей нет ничего сложного, особенно для старых ядер с версией 2.4. Исходный текст простейшего модуля выглядит так: Скелет простейшего модуля для ядер с версией 2.4 // сообщаем компилятору, что это модуль режима ядра #define MODULE #define __KERNEL__ // подключаем заголовочный файл для модулей #include <linux/module.h> // на многопроцессорных машинах подключаем еще и smp_lock #ifdef __SMP__ #include <linux/smp_lock.h> #endif // функция, выполняющая при загрузке модуля int init_module(void) { // мяукнем что-нибудь printk("\nOur module has been loaded!\n"); // успешная инициализация return(0); } // функция, выполняющаяся при выгрузке модуля void cleanup_module(void) { // мяукнем что-нибудь printk("\nOur module has been unloaded\n"); } // пристыковываем лицензию, по которой распространяется // данный файл, если этого не сделать, модуль успешно // загрузится, но операционная система выдаст warning, // сохраняющийся в логах и привлекающий внимание админов MODULE_LICENSE("GPL"); Начиная с версии 2.6, в ядре произошли значительные изменения, и теперь программировать приходится так: Скелет простейшего модуля для ядер с версией 2.6 #ifdef LINUX26 static int __init my_init() #else int init_module() #endif #ifdef LINUX26 static void __exit my_cleanup() #else int cleanup_module() #endif #ifdef LINUX26 module_init(my_init); module_exit(my_cleanup); #endif За подробностями обращайся к справочным страницам ("man –k module"), официальной документации (/usr/src/linux/Documentation/modules.txt) и книге "Linux kernel internals", которую легко найти в Осле. Как бы там ни было, только что написанный модуль необходимо откомпилировать: $ gcc –c my_module.c –o my_module.o Настоятельно рекомендуется задействовать оптимизацию, добавив ключ –O2 или -O3, а затем загрузить внутрь ядра: |