Пишем руткит нового поколения Иван Скляров Хакер, номер #096, стр. 096-120-5 Вспомним, что файловая система /proc содержит по одному каталогу для каждого выполняющегося процесса. Именем каталога является идентификатор процесса. Каталоги появляются и исчезают по мере запуска и завершения процессов. В каждом каталоге имеются файлы, содержащие различную информацию о процессе. Таким образом, если скрыть каталог в файловой системе /proc с именем нужного нам процесса, то он не будет отображаться командой ps, top и пр. Именно поэтому метод скрытия каталогов одновременно позволяет нам скрывать процессы в системе. Разумеется, этот метод позволяет скрывать не только каталоги, но и любые другие файлы, в том числе устройства. Чтобы получить указатель на структуру file необходимо открыть файл (каталог, устройство). В ядре открытие файла осуществляется с помощью функции filp_open(). Удобнее открывать корневой каталог для последующего скрытия в нем нужных файлов (каталогов, устройств). Для указания корневого каталога в нашем модуле введена константа DIRECTORY_ROOT. Для сокрытия каталогов в файловой системе /proc нужно присвоить константе имя «/proc», а для сокрытия файлов вне системы /proc указываем корневой каталог. Причина, по которой требуется указывать разные корневые каталоги, заключается в том, что /proc является особой файловой системой, которая хранится в памяти компьютера и не связана с жестким диском. Поэтому если открыть корневой каталог, то мы не сможем прятать каталоги в файловой системе /proc, и наоборот. В модуле мы подменяем не только указатель на функцию readdir(), но и указатель на filldir-функцию, который стоит третьим аргументом в функции readdir(). В подменной filldir-функции мы делаем проверку на имя каталога, который требуется скрыть, и, как только он будет обнаружен, filldir-функция вернет 0, в результате чего readdir() пропустит этот каталог. Имя обычного файла, каталога или устройства для скрытия указывается в определении DIRECTORY_HIDE. В ходе экспериментов я выяснил, что имена каталогов хранятся в системе как строки без оканчивающего нулевого символа, в то время как имена обычных файлов хранятся с оканчивающим нулевым символом. Поэтому мы для сравнения строк в модуле задействуем функцию strncmp(), которая осуществляет проверку только n-первых символов. Соответственно, нам под силу передавать строки без завершающего нулевого символа. Скрытие работающего снифера Чтобы подавить флаг PROMISC, можно просто подменить системный вызов ioctl(), в котором будем выполнять проверку на установленный флаг, и менять его значение на обратное: int new_ioctl(int fd, int request, unsigned long arg) { ... if (request == SIOCGIFFLAGS) { if (promisc) ifr->ifr_flags |= IFF_PROMISC; else ifr->ifr_flags &= ~IFF_PROMISC; } return 0; } Скрытие информации от утилиты netstat Утилита netstat читает информацию из файлов /proc/net/{tcp,udp} и других файлов (их список можно увидеть в man netstat). Поэтому если скрыть нужные строки с информацией о соединении и об открытых портах при чтении из этих файлов, то netstat не будет отображать их на экране. |