В один прекрасный день ты поставил себе
Linux, а может, порутил какой-то сервер,
стоящий под Linux - не важно, главное, что у
тебя появился твой собственный LinuxBox. И
захотелось тебе поизвращаться над ядром. Ну
хорошо: сорцы в зубы, gcc в руки, и вперед. Что,
сложновато? Есть способ проще - научиться
писать LKM.
Что такое LKMs?
LKMs расшифровывается как Loadable Kernel Modules (Загружаемые
Ядерные, они же Ядреные, Модули :). Только
представь, что для обвешивания ядра разными
фичами тебе не нужно перекомпиливать все
ядро - LKM загружаются динамически! И если ты,
глядя на консоль, ностальгируешь по
временам DOS, когда ты мог творить чудеса с
помощью TSR (Terminate and Stay Resident) программ, то LKMs
для тебя. С помощью LKM ты - как и с помощью DOS
TSR - сможешь перехватывать системные
функции (в Linux они называются systemcalls).
Для твоего общего развития: в MS Windows 9x есть
что-то загадочное, обзываемое VxD. Это и есть
аналог LKM (хотя и имеется и много различий).
Что нужно шизику-ядерщику для счастья?
Совсем немного: gcc (GNU C Compiler) и права root'а на
системе, куда ты собираешься запихнуть свой
модуль. Если модуль предназначен твоему
личному Linux'у, то, скорее всего, не будет
проблем ни с gcc, ни с правами. Если же ты
собираешься внедрять модуль на чужом
сервере, то тебе придется сначала этот
сервер порутить (хотя обычно необходимость
внедрения модулей возникает после захвата
системы). Имей в виду, что на чужом сервере
может не оказаться gcc и вообще, тебя будут
подстерегать всяческие трудности, если ты
захочешь что-нибудь откомпилировать. Умные
админы из соображений безопасности делают
все, чтобы взломщик не смог собрать на их
машине свои хакерские штучки. Хотя кто тебе
запрещает сделать модуль у себя и
перекачать на захваченную систему, если
админ забыл или не захотел убрать с сервера
ftp, lynx, telnet, другие программы, позволяющие
переписать что-нибудь на этот компьютер с
другого или любой язык программирования,
поддерживающий сокеты? Но лучше всего
доставлять модуль (и не только модуль - что
угодно) на место назначения через буфер
обмена: в иксах открываешь
транспортируемый объект в любом текстовом
редакторе, выделяешь все мышкой, а там, куда
нужно вставить (например, в окошко
терминала с root shell, где ты предварительно
набрал cat > evil_module.o) кликаешь одновременно
на обе кнопки мыши - таким образом ты
оставляешь минимум следов.
Hello World!
Если ты только что поставил Linux и в глаза
не видел программ на Си - не беда. Специально
для таких как ты Mixter написал "A quick introduction
to C - learn programming in one day". Беда, если ты не
знаешь английского. А доку можно взять
здесь:
http://mixter.warrior2k.com/C-intro.tar.gz
http://mixter.void.ru/C-intro.tar.gz
Теперь приступим к написанию первого
модуля. Как ты уже, наверное, знаешь, любая
обычная прога на Си должна содержать
функцию main(), которая исполняется при
запуске программы. Модуль же должен
содержать как минимум две функции:
int init_module(void) { ...
} /*
инициализация модуля */
void cleanup_module(void) { ... } /* корректное
завершение модуля */
Вот пример простейшего модуля, который при
загрузке пишет "Hello World!", а при
завершении - "Bye, Bye":
#define MODULE
#include <linux/module.h>
int init_module(void)
{
printk("Hello World!\n");
return 0;
}
void cleanup_module(void)
{
printk("Bye, Bye\n");
}
Обрати внимание, что вместо printf()
используется printk() - ядреный кодинг
отличается от кодинга обычных программ, и
большинство функций, которые ты
использовал в user space, не будут работать в kernel
space. Теперь надо бы этот модуль откомпилить.
Для этого нужно набрать:
# gcc -c -O3 helloworld.c
-c : Откомпилировать исходник, но не
линковать. В итоге получается helloworld.o
-O3 : Использовать максимальную оптимизацию
Теперь, залогинившись root'ом, набери:
# insmod helloworld.o
Если ты увидел надпись "Hello World" и
никаких сообщений о глюках, считай, что тебе
повезло. А бывает, что дистрибутив собирают
не руками, а каким-то другим местом, и тогда
появляется сообщение вроде этого:
helloworld.o: kernel-module version mismatch
helloworld.o was compiled for kernel version ???
while this kernel is version ???.
В таком случае можно попробовать править
файлы /usr/include/linux/=ersion*.h (не забудь сделать
резервные копии). Если это не помогло, можно
попытаться получить рабочий модуль таким
способом (такие действия также полезны,
если на взломанном сервере стоит ядро,
отличное от ядра твоей домашней системы):
# gcc -S helloworld.c
Теперь у тебя есть файл, ассемблерный
исходник этого модуля. В нем находишь
строчку:
.string "kernel_version=???"
Прописав здесь нужную версию ядра, находишь
строку:
.size __module_kernel_version,???
Тут нужно поправить размер строчки, которую
ты только что изменил. Для этого подсчитай
количество буковок в в измененной строчке и
добавь 1 (для завершающего нуля). После этого:
# gcc -c helloworld.s
# insmod helloworld.o
Если и это не помогло, задумайся, чего ты
больше хочешь: писать LKM или продолжать
пользоваться своим дистрибутивом.
Ну допустим, у тебя все получилось, ты
написал свой первый модуль и благополучно
загрузил его. Как же узнать, что твой модуль
действительно висит в памяти и работает?
Просто:
# lsmod
Module Size Used by
helloworld 156 0 (unused)
Поле 'Size' показывает размер, занимаемый
модулем в памяти, иногда размер измеряется
в страницах - Pages, а поле 'Used by' - сколько
раз модуль используется системой. Если этот
счетчик равен 0, модуль может быть удален:
# rmmod helloworld
Bye, Bye
Если ты уже вышел из детского сада
Любая ОС имеет функции, встроенные в ядро.
Функции, используемые Linux, называются systemcalls
(системные вызовы). Когда в системе
открывается файл, выполняется sys_open systemcall.
Полный список системных вызовов, доступных
на твоей системе, ты можешь найти в /usr/include/sys/syscall.h.
Если systemcalls не определены непосредственно в
этом файле - смотри, какие библиотеки там
подключаются, и ищи список в них (у меня это
asm/unistd.h и bits/syscall.h).
Каждый systemcall имеет свой уникальный номер.
Когда необходимо сделать вызов, вызывается
прерывание 0x80, а аргументы распихиваются по
регистрам (например, номер вызова - в eax).
Номер системного вызова является индексом
массива sys_call_table[], то есть вызов происходит
по sys_call_table[SyscallNumber].
Проще простого подменить какой-нибудь
системный вызов своим. Например: за
создание директорий отвечает SYS_mkdir; если
заменить оригинальный SYS_mkdir своим, который
не будет ничего делать, то никто в системе
не сможет создавать директорий. Вот модуль,
который демонстрирует данную фишку:
#define MODULE
#define __KERNEL__
#include <linux/module.h>
#include <linux/kernel.h>
#include <sys/syscall.h>
// Попробуй раскомментировать по одной
строчке,
// если модуль не компилируется
//#include <asm/unistd.h>
//#include <sys/types.h>
//#include <asm/fcntl.h>
//#include <asm/errno.h>
//#include <linux/types.h>
//#include <linux/dirent.h>
//#include <sys/mman.h>
//#include <linux/string.h>
// Раскомментируй в последнюю очередь!
//#include <linux/fs.h>
//#include <linux/malloc.h>
extern void* sys_call_table[];
// Теперь есть доступ к sys_call_table
int (*orig_mkdir)(const char *path);
// Оригинальный системный вызов
int hacked_mkdir(const char *path)
{
return 0;
// Как будто, все хорошо, но на самом деле
ничего не происходит
}
int init_module(void)
{
orig_mkdir = sys_call_table[SYS_mkdir];
sys_call_table[SYS_mkdir] = hacked_mkdir;
return 0;
}
void cleanup_module(void)
{
sys_call_table[SYS_mkdir] = orig_mkdir;
// Восстанавливаем оригинальный системный
вызов
}
Для начала тебе хватит этих знаний, но
если ты хочешь стать настоящим шизиком-ядерщиком,
то не ленись и почитай "(nearly) Complete Linux Loadable
Kernel Modules - the defenetive guide for hackers, virus coders and syste
administrators", написанный pragmatic/THC. Прочитав
этот гайд, ты узнаешь:
- Как скрывать файлы
- Как скрывать части файлов
- Как вести мониторинг файловых операций
- Как скрыть любой процесс
- Как контролировать операции с сокетами
- Как писать вирусы с LKM
- Как сделать LKM невидимыми и неудаляемыми
Еще там содержится море другой полезной
информации и исходников модулей. А берется
этот замечательный гайд по адресу:
http://www.digibel.org/~tompy/hacking/LKM_HACKING.html
|