Поиграем с туксом в прятки Крис Касперски ака мыщъх Хакер, номер #077, стр. 077-102-4 // для процессоров с одинаковым "весом" используем поле prev if (weight > c) { c = weight; next = p; } p = p->next_run; } if (!c) { // все процессы выработали свои кванты, начинаем новую эпоху // хорошее место, чтобы добавить передачу управления на замаскированный процесс ... } Процедура внедрения в планировщик осуществляется по стандартной схеме: сохраняем затираемые инструкции в стеке; вставляем команду перехода на нашу функцию, распределяющую процессорные кванты нулевого процесса среди скрытых процессов; выполняем ранее сохраненные инструкции; возвращаем управление функции-носителю. Поскольку машинное представление планировщика зависит не только он версии ядра, но и от ключей компиляции, атаковать произвольную систему практически нереально. Предварительно необходимо скопировать ядро на свою машину и дизассемблировать его, а после разработать подходящую стратегию внедрения. Если атакуемая машина использует штатное ядро, мы можем попробовать опознать его версию по сигнатуре, используя заранее подготовленную стратегию внедрения. Далеко не все админы перекомпилируют свои ядра, поэтому такая тактика успешно работает. Впервые она была представлена на европейской конференции Black Hat в 2004 году, электронная презентация которой находится в файле www.blackhat.com/presentations/bh-europe-04/bh-eu-04-butler.pdf. По этому принципу работают многие rootkit'ы и, в частности, Phantasmagoria. [перехват системных вызовов] Помнишь MS-DOS? Там стелстирование осуществлялось путем подмены прерываний INT 13h/INT 21h. В Linux для той же цели используется перехват системных вызовов (system call или сокращенно syscall). Для сокрытия процессов и файлов достаточно перехватить всего один низ них — getdents, на которую опирается всем известная readdir, которая, в полном согласии со своим именем, читает содержимое директорий (и директории /proc в том числе!). Другого легального способа просмотра списка процессов под Linux, в общем-то, и нет. Функция-перехватчик садится поверх getdents и просматривает возвращенный ею результат, выкусывая из него все "лишнее", то есть работает как фильтр. Сетевые соединения стелсируется аналогичным образом (они монтируются на /proc/net). Чтобы замаскировать сниффер, необходимо перехватить системный вызов ioctl, подавляя PROMISC-флаг. А перехват системного вызова get_kernel_symbols позволяет замаскировать LKM-модуль так, что его никто не найдет. Звучит заманчиво. Остается только реализовать это на практике. Ядро экспортирует переменную extern void sys_call_table, содержащую массив указателей на syscall'ы, каждая ячейка которого содержит либо действительный указатель на соответствующий syscall, либо NULL, свидетельствующий о том, что данный системный вызов не реализован. Просто объяви в своем модуле переменную *sys_call_table[], и тогда все системные вызовы окажутся в твоих руках. Имена известных syscall'ов перечислены в файле /usr/include/sys/syscall.h. В частности, sys_call_table[SYS_getdents] возвращает указатель на getdents. |