Помните MS-DOS? Там стелстирование осуществлялось путем подмены прерываний int13h/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.
Простейший пример перехвата выглядит так (за более подробной информацией обращайтесь к статье "Weakening the Linux Kernel", опубликованной в 52 номере PHRACK'а):
// указатель на таблицу системных вызовов
extern void *sys_call_table[];
// указатели на старые системные вызовы
int (*o_getdents) (uint, struct dirent *, uint);
// перехват!
int init_module(void)
{
// получаем указатель на оригинальный