В борьбе с журнальными бестиями Иван Скляров (www.sklyaroff.ru) Хакер, номер #078, стр. 078-100-4 В заголовочный файл я включаю файл lastlog.h "#include <lastlog.h>". Но как я говорил ранее, в системе Linux он не обязателен, ибо является ссылкой на utmp.h. Также я на всякий случай определяю пути к лог-файлам (хотя обычно UTMP_FILE и WTMP_FILE определены в utmp.h): #define UTMP_FILE "/var/run/utmp" #define WTMP_FILE "/var/log/wtmp" #define LASTLOG_FILE "/var/log/lastlog" В программе мной создано две основных функции: dead_uwtmp() предназначена для очистки файлов utmp и wtmp, а функция dead_lastlog() очищает lastlog. Поиск в логах структуры для очистки производится по имени пользователя. В полноценной утилите также неплохо сделать поиск по названию удаленного хоста и имени терминала. Основным кодом в функции dead_uwtmp() является следующий участок: while (read(fd, &pos, dist) == dist) { if (!strncmp(pos.ut_name, name_arg, sizeof(pos.ut_name))) { bzero(&pos, dist); if (lseek(fd, -dist, SEEK_CUR) != -1) write (fd, &pos, dist); } } Где pos определено как struct utmp pos, а dist = sizeof(struct utmp). Здесь последовательно считываются структуры из файла с помощью read(), и как только обнаруживается совпадение с именем пользователя (ut_name), подготавливается чистая структура, целиком заполненная нулями при помощи bzero(). Чистая структура записывается на место существующей функцией write(), для чего на начало модифицируемой структуры предварительно устанавливается файловый указатель с помощью lseek(). В структуре lastlog отсутствует поле с именем пользователя, поэтому для модификации этого лога нужен другой подход, отличный от utmp и wtmp. В решении задачи поможет следующий момент — все записи в файле lastlog отсортированы по UID. Поэтому в функции dead_lastlog() по имени пользователя определяется его UID с помощью стандартной функции getpwnam(). Затем производится очистка найденной структуры в файле lastlog с помощью следующих строк (в OpenBSD второй аргумент lseek() следует приводить к типу off_t — прим. ред.): lseek(fd, (long)pwd->pw_uid * dist, 0); bzero((char *)&pos, dist); write(fd, (char *)&pos, dist); Как видишь, программа довольно проста и в совокупности занимает всего около 80 строк. В одном архиве с этим клинером я положил пример еще одного самодельного клинера, который скрывает хакера от утилит w, who и last, но при этом не затирает нулями структуру utmp. Я заметил, что достаточно поменять тип записи ut_type с USER_PROCESS на DEAD_PROCESS, как администраторские утилиты перестанут отображать такую запись на экране. Этот способ хорош тем, что затрудняет обнаружение изменений с помощью различных IDS. К сожалению, не во всех системах структура utmp имеет поле ut_type, но в Linux (в отличие от FreeBSD) она точно есть. |