Многофункциональный DDoS-троянец под Linux

В феврале 2014 года на популярном российском ИТ-ресурсе появилась статья, с очень интересным заголовком — «Исследуем Linux Botnet «BillGates». В ней описывался троянец с довольно богатым функционалом для осуществления DDoS-атак. Особенно нас заинтересовала его способность проведения атаки типа DNS Amplification. Да и вообще, исходя из статьи, троянец имел сложную многомодульную архитектуру, чего до сих пор мы не наблюдали в мире Linux-зловредов.

Кроме того в статье имелась ссылка, откуда все файлы троянца (полученные прямиком с зараженной машины) можно было скачать. Что мы и сделали.

Скачанный архив содержал следующие файлы, которые, по словам автора статьи, являлись модулями одного троянца:

atddd; cupsdd; cupsddh; ksapdd; kysapdd; skysapdd; xfsdxd. В данный момент файлы cupsdd и cupsddh детектируются продуктами «Лаборатории Касперского» как Backdoor.Linux.Ganiw.a; atddd и остальные — как Backdoor.Linux.Mayday.f.

В архиве с файлами присутствует также файл конфигурации cron — планировщика задач в Linux. В данном случае утилита используется как средство закрепления троянца в системе. С помощью cron троянец выполняет следующие задачи:

Раз в минуту завершает процессы всех приложений, которые могут помещать его (троянца) работе:.IptabLes, nfsd4, profild.key, nfsd, DDosl, lengchao32, b26, codelove, node24; Примерно раз в полтора часа завершает работу всех своих процессов: kysapd, atdd, skysapd, xfsdx, ksapd; Примерно раз в два часа скачивает в папку /etc с адреса http://www.dgnfd564sdf.com:8080/[module_name] все свои компоненты (module_name = имя модуля, например, cupsdd), предварительно удалив эти файлы из /etc Раз в полтора часа заново запускает все свои модули Каждую минуту затирает системные логи, историю команд bash и выполняет chmod 7777 [module_name] При последующем анализе файлов мы не обнаружили кода, отвечающего за запись конфига cron. Скорее всего, конфиг был вручную загружен злоумышленником после получения удаленного доступа к системе.

Backdoor.Linux.Mayday.f (atddd) Файл atddd представляет собой бэкдор, содержащий функционал для осуществления различных типов DDoS-атак на указанные сервера, и, напомним, детектируется нами как Backdoor.Linux.Mayday.f. Файлы kysapdd, skysapdd, xfsdxd, ksapdd являются практически полными копиями atddd за одним исключением, о котором ниже.

Вначале своей работы бэкдор вызывает функцию daemon (1, 0), таким образом продолжая свое выполнение в фоновом режиме и перенаправляя стандартный ввод, вывод и ошибки в /dev/null

Затем atddd собирает необходимую информацию о системе, а именно:

версию системы (вызов uname ()) количество ядер процессора и их частоту (из /proc/cpuinfo) загруженность процессора (из /proc/stat) загруженность сети (из /proc/net/dev для интерфейсов с префиксом «eth») Эта информация помещается в структуру g_statBase.

После этого бэкдор расшифровывает строки, содержащие IP-адрес и порт C&C сервера. Алгоритм шифрования очень простой: зашифрованная строка посимвольно перебирается и если номер символа нечетный, то к его ASCII коду добавляется 1, если четный — вычитается 1. Таким образом из строки »3/3–2/4–269–85» получается IP-адрес »202.103.178.76», а из »2/:82» порт »10991».

Далее atddd читает файл конфигурации fwke.cfg, находящийся в той же директории, что и сам зловред. Полученная информация помещается в структуру g_fakeCfg. Если файл не существует, то бэкдор пытается создать его и записать внутрь следующую информацию:

1-ая строка: 0          //флаг, если 1 — то начать атаку, если 0 — остановить атаку

2-ая строка: 127.0.0.1:127.0.0.1          //диапазон исходящих IP-адресов

3-я строка: 10000:60000          //диапазон исходящих портов для атаки

4-ая строка: пустая строка          //доменное имя в случае с DNS-флудом (см. ниже)

Эта информация в дальнейшем передается C&C серверу и может обновляться при помощи команды от C&C.

Далее бэкдор запускает новый поток CThreadTaskManager: ProcessMain (), в котором команды на начало атаки и остановку атаки ставятся в очередь на выполнение. Следом запускается новый поток CThreadHostStatus: ProcessMain (). В нем каждую секунду обновляются данные о загруженности процессора и CPU, которые впоследствии могут отправляться C&C серверу при запросе.

После этого запускаются 20 потоков, которые читают информацию из очереди заданий и, соответственно, начинают атаку или останавливают ее. Однако в атаке могут быть задействованы не все потоки, если команда от C&C приходит с соответствующим параметром (количеством используемых потоков).

Далее зловред входит в бесконечный цикл обработки сообщений от C&C. Сначала устанавливается соединение с C&C и каждые 30 секунд отправляется информация о версии системы и тактовой частоте процессора, а также данные из структуры g_fakeCfg.

В ответ сервер должен отправить 4 байта, первый из которых является порядковым номером команды — от 1 до 4.

Далее, если команда имеет параметры, то C&C отправляет еще 4 байта, содержащие размер данных (параметров). После этого отправляются сами параметры, размер которых должен совпадать с числом из предыдущего ответа С&С.

Подробнее о каждой из команд:

0×01. Команда запуска атаки, в параметрах передаются тип атаки, а также количество используемых потоков. Тип атаки представляет из себя байт со значением от 0×80 до 0×84. Таким образом возможны 5 видов атак: 0×80 — TCP флуд. Порт назначение передается в ответе C&C в качестве параметра. Дипазон портов отправления задан в fwke.cfg. Каждый новый запрос отправляется с нового порта в заданном диапазоне, по порядку. IP-адрес назначения так же задается в параметрах. 0×81 — UDP флуд. Тоже самое, что и 0×80, только, в качестве протокола транспортного уровня, используется UDP. 0×82 — ICMP флуд. Аналогично предыдущим, только через ICMP. 0×83, 0×84 — две атаки с использованием DNS флуда. Отличаются только доменным именем в DNS-запросе. В первом случае оно генерируется случайным образом, во втором — задается в параметре (4-ая строка в fwke.cfg). По сути обе похожи на 0×81, только в качестве порта назначения используется 53 порт (порт DNS службы по умолчанию). 0×02. Команда остановки атаки. Значение в первой строке fwke.cfg изменяется на 0 и атака прекращается. 0×03. Команда на обновление файла fwke.cfg. В ответе также приходит структура, аналогичная g_fakeCfg, из которой записывается файл fwke.cfg. 0×04. Команда для отправки статуса выполнения текущей команды С&C серверу. Помимо этого бэкдор содержит несколько пустых (без кода внутри) методов с интересными названиями: CThreadAttack: EmptyConnectionAtk, CThreadAttack: FakeUserAtk, CThreadAttack: HttpAtk. Видимо, автор планировал расширить функционал зловреда и эта версия является не окончательной, а скорее тестовой. И файл cupsdd, о котором мы расскажем ниже, является этому подтверждением.

Файлы kysapdd, skysapdd, xfsdxd, ksapdd являются практически полными копиями atddd, но содержат другие адреса C&C серверов: 112.90.252.76:10991, 112.90.22.197:10991, 116.10.189.246:10991 и 121.12.110.96:10991 соответственно. Также отличаются имена файла конфигурации: fsfe.cfg, btgw.cfg, fake.cfg, xcke.cfg соответственно.

Таким образом, вопреки нашим ожиданиям, файлы atddd, kysapdd, skysapdd, xfsdxd, ksapdd являются не модулями чего-то целого, а отдельными экземплярами троянца, каждый из которых работает со своим C&C сервером. Но самое интересное еще впереди.

Backdoor.Linux.Ganiw.a (cupsdd) Так же, как и описанные выше файлы, этот является бэкдором с функционалом для осуществления различных DDoS-атак. Но функционал cupsdd значительно богаче и сложнее, чем у его «коллег», хотя его код в некоторых местах очень похож на код файла atddd.

В начале работы бэкдор инициализирует необходимые ему переменные из строки »116.10.189.246:30000:1:1: h:578856:579372:579888» (разделитель — »:»), которую предварительно расшифровывает при помощи алгоритма RSA. Строка распределяется по переменным следующим образом:

g_strConnTgt=116.10.189.246 — IP-адрес С&C сервера

g_iGatsPort=30000 — порт С&C сервера

g_iGatsIsFx=1 и g_iIsService=1 — флаги, используемые в дальнейшем

g_strBillTail=h — постфикс для имени файла, который будет дропнут (см. ниже)

g_strCryptStart=578856, g_strDStart=579372, g_strNStart=579888 — указатели на RSA-данные (зашифрованная строка и ключ)

Далее зловред дропает и запускает файл, находящийся изначально по смещению 0xb1728 от начала файла и имеющий размер 335872 байта, если он еще не запущен. Проверка запущен ли этот файл происходит при помощи попытки забиндить сокет 127.0.0.1:10808. Если это сделать удалось, значит файл не запущен и нужно его дропнуть и запустить.

Если же файл уже запущен, то его процесс, PID которого находится в файле /tmp/bill.lock, принудительно завершается (kill (pid, 9)). И потом файл все равно дропается, заменяя собой уже существующий.

Имя дропнутого файла формируется из имени текущего запущенного файла + постфикс из переменной g_strBillTail. В нашем случае файл назывался cupsddh и находился в той же директории, что и дроппер.

Далее текущий процесс форкается и в дочернем процессе происходит вызов функции system (»/path/to/cupsddh»), которая запускает дропнутый файл.

После этого вызывается функция daemon (1, 0), имеющая тот же смысл что и в предыдущем сэмпле (atddd).

Потом обрабатывается ситуация, если cupsdd был запущен ранее и активен в данный момент. Для этого проверяется, существует ли файл /tmp/gates.lock. Если он существует, то текущий процесс завершается (exit (0)). Если же нет, то он (/tmp/gates.lock) создается и в него помещается pid текущего процесса.

Далее, если флаг g_iIsService == 1, то бэкдор прописывает себя в автозагрузку при помощи создания скрипта в /etc/init.d/ с именем DbSecuritySpt следующего содержания:

#!/bin/bash

/path/to/cupsdd

И создает символьные ссылки на него в /etc/rc[1–5].1/S97DbSecuritySpt

Читает файл конфигурации conf.n (если он существует) из той же директории, что и cupsdd. Первые 4 байта файла — это размер данных идущих далее. Все данные помещаются в структуру g_cnfgDoing.

Читает файл с командами — cmd.n. Формат такой же как и в conf.n. Данные попадают в структуру g_cmdDoing.

Далее получает необходимую информацию о системе, а именно:

Имя системы и версию ядра (напр., Linux 3.11.0–15-generic), при помощи вызова uname () Тактовую частоту процессора, из /proc/cpuinfo Количество ядер процессора из /proc/cpuinfo и загруженность процессора из /proc/stat Загруженность сети из /proc/net/dev Размер жесткого диска в мегабайтах из /proc/meminfo Информацию о сетевых интерфейсах из /proc/net/dev Все данные помещаются в структуру g_statBase.

Далее создается новый поток CThreadTaskGates: ProcessMain, в котором обрабатываются следующие команды:

0×03. DoConfigCommand (). Обновить файл конфигурации conf.n. 0×05. DoUpdateCommand (). Запускает новый поток CThreadUpdate: ProcessMain, в котором обновляет один из своих компонентов. В качестве параметра команда принимает число от 1 до 3, которое ассоциируется с одной из следующей строк:1 — «Alib» — файл /usr/lib/libamplify.so2 — «Bill» — дропнутый модуль cupsddh3 — «Gates» — дроппер cupsdd

В зависимости от параметра обновляется один из компонетов зловреда. Обновление происходит при помощи отправки C&C серверу 6 байт, содержащих строку «EF76#^». Вслед за этим отправляется одна из строк, описанных выше (в зависимости от параметра).

В ответ приходят 4 байта, содержащие длину файла (в байтах), который будет передан далее. Затем С&C передает сам файл пакетами по 1024 байта.

Сначала файл сохраняется в директории /tmp со случайным именем, состоящим из цифр. Затем, в зависимости от того что за файл был получен, заменяет уже существующий файл cupsdd (или cupsddh) или копируется в /usr/lib/libamplify.so

Далее временный файл из /tmp удаляется, а на итоговый устанавливаются права 755 с помощью команды chmod. После чего, в случае обновления cupsddh, уже запущенный процесс завершается, а новый файл запускается. В случае обновления cupsdd, завершающий этап (начиная с копирования их /tmp) осуществляет cupsddh, которому отдается соответствующая команда.

0×07. DoCommandCommand (). Записывает новую команду в cmd.n. 0×02. StopUpdate (). Закрывает текущее соединение, установленное для обновления модулей. После этого бэкдор cupsdd запускает несколько потоков, в которых одновременно выполняет несколько вспомогательных действий:

CThreadClientStatus каждую секунду обновляет данные о загруженности процессора и сети в структуре g_statBase. CThreadRecycle удаляет из очереди заданий уже завершенные.  — CThreadConnSender читает команды из очереди и передает их модулю cupsddh через TCP-соединение с 127.0.0.1 на порт 10808. В ответ принимает статус их выполнения. CThreadMonBill каждую минуту проверяет запущен ли модуль cupsddh и если нет, то заново дропает и запускает его. CThreadLoopCmd читает команды из g_cmdDoing (файл cmd.n) и выполняет их через вызов system (cmd). Далее основной поток входит в цикл приема и обработки команд от C&C сервера. Тут в зависимости от флага g_iGatsIsFx возможны два варианта:

Если флаг установлен (==1), то зловред, как и в предыдущем сэмпле (atddd), в новом потоке просто отправдяет информацию о системе и текущую конфигурацию из g_cnfgDoing и ожидает поступления в ответ команд; Если флаг не установлен, то инициатором сеанса связи выступает C&C. То есть зловред ожидает подключения от C&C и только когда соединение будет установлено начинает передавать указанные выше данные.

Команды, поступающие от C&C распределяются в одну из двух очередей: либо на исполнение в текущем модуле (в потоке CThreadTaskGates, описанном выше), либо на передачу модулю cupsddh (поток CThreadConnSender).

Backdoor.Linux.Ganiw.a (cupsddh) Файл упакован UPX’ом, после распаковки вызывает daemon (1,0). Создает файл /tmp/bill.lock, в который помещает PID текущего процесса. cupsddh заполняет данными о системе структуру g_statBase, точно такую же как в cupsdd.

Далее заполняет структуру g_provinceDns IP-адресами DNS-серверов приведенными к двоичному коду в сетевом порядке расположения байт функцией inet_addr (), из массива строк g_sProvinceDns (смещение в распакованном файле: 0×8f44с, размер 4608 байт).

cupsddh выполняет команду «insmod /usr/lib/xpacket.ko», пытаясь таким образом загрузить модуль ядра в ядро. Однако такой файл отсутствует на «чистой» системе, и зловред не предпринимает никаких попыток скачать его или получить каким либо еще способом.

Далее данные из файла /usr/libamplify.so (оказывается, это не библиотека, а очередной конфиг) загружаются в структуру g_AmpResource. Формат файла: 1-ый dword — это количество dword’ов, идущих следом. Судя по всему, содержит список IP-адресов актуальных на данный момент DNS-серверов, подходящих для DDoS-атаки типа DNS Amplification.

После этого запускает два потока: CThreadTask и CThreadRecycle. Первый выполняет команды из очереди, сформированной из пришедших от модуля cupsdd команд. Второй удаляет выполненные команды. Затем основной поток биндит сокет на 127.0.0.1:10808 и в бесконечном цикле начинает принимать команды от модуля cupsdd, которые заносятся в вышеуказанную очередь.

Возможны следующие команды:

0×01. Начинает атаку в соответствии с полученными параметрами. Подробнее ниже. 0×02. Останавливает текущую атаку, устанавляивая соответствующий флаг. 0×03. Обновляет текущую конфигурацию в структуре g_cnfgDoing, которую использует при атаке. Так же обновляет текущий локальный мак-адрес и мак и ip адреса текущего используемого гейта (шлюза) в структуре g_statBase. 0×05. Завершающий этап обновления модуля cupsdd (описан выше).

Возможны два основных режима атаки: в нормальном режиме и режиме ядра.

Режим ядра Для этого режима используется встроенный в Linux генератор пакетов уровня ядра pktgen. Его преимущество для злоумышленника состоит в том, что трафик генерируется с максимальной возможной для данного сетевого интерфейса скоростью. И сгенерированные таким образом пакеты нельзя увидеть с помощью обычных снифферов, например, стандартного tcpdump, т. к. пакеты генерируются на уровне ядра.

Управляется генератор пакетов при помощи набора скриптов/конфигов в директории /proc/net/pktgen. Но перед этим необходимо загрузить модуль pktgen в ядро при помощи вызова команды «modprobe pktgen». Однако подобные вызовы мною обнаружены не были. Судя по всему, вместо них используется вызов «insmod /usr/lib/xpacket.ko», но, как и было сказано ранее, такой файл по умолчанию отсутствует в системе. Соответственно, в данной версии зловреда режим ядра не функционирует.

Тем не менее, зловред пытается записать несколько файлов в директорию /proc/net/pktgen, а именно:

файл — /proc/net/pktgen/kpktgend_%d — для каждого ядра процессора, где %d — номер ядра, начиная с 0. Содержание файла: rem_device_alladd_device eth%dmax_before_softirq 10000

файл — /proc/net/pktgen/eth%d — для каждого ядра процессора, где %d — номер ядра, начиная с 0. Содержание файла: count 0clone_skb 0delay 0TXSIZE_RNDmin_pkt_size %dmax_pkt_size %dIPSRC_RNDsrc_min %ssrc_max %sUDPSRC_RNDudp_src_min %dudp_src_max %ddst %sudp_dst_min %dudp_dst_max %ddst_mac %02x:%02x:%02x:%02x:%02x:%02x     //мак-адрес шлюза из g_statBaseis_multi %dmulti_dst %s     //если адресов для атаки несколько (т. е. значение в предыдущей строке не равно 0), то они задаются в этих строках, количество которых соответствует предыдущему параметруpkt_type %ddns_domain %ssyn_flag %dis_dns_random %ddns_type %dis_edns %dedns_len %dis_edns_sec %dЗначения большинства параметров pktgen передаются через параметры команды от cupsdd. файл — /proc/net/pktgen/pgctrl, содержащий строку «start». Нормальный режим атаки Как и в atddd нормальный режим атаки работает через сокеты (raw sockets).Здесь возможны следующие типы атак:

CAttackSyn — TCP-SYN флуд. CAttackUdp — UDP флуд. (как и в atddd) CAttackDns — DNS флуд. (как и в atddd) CAttackIcmp — ICMP флуд. (как и в atddd) CAttackCc — HTTP-флуд. CAttackAmp — DNS Amplification. Особенность последней заключается в том, что пакеты отправляются к уязвимым DNS-серверам с указанием адреса цели атаки в качестве IP-адреса отправителя. Таким образом, злоумышленник отправляет небольшой пакет с DNS-запросом, а DNS-сервер отвечает цели атаки значительно большим по объему пакетом. Список уязвимых DNS-серверов хранится в файле libamplify.so, который записывается после получения соответствующей команды от C&C.

Post Scriptum. BillGates v1.5 Данная версия троянца появилась несколько позднее и на данный момент, вероятно, является последней. По сути, это все тот же cupsdd, только «доведенный до ума». Код в целом стал более логичен, плюс появилась пара новых функций.

Наиболее существенные изменения произошли в модуле «Gates», т.е. в файле cupsdd. Теперь у него есть три режима работы. Выбор режима работы осуществляется на основании того откуда был запущен файл. Конкретнее, если файл запущен из /usr/bin/pojie, то выбирается режим мониторинга, иначе — режим установки и обновления, который в дальнейшем переходит в режим управления модулем «Bill».

Режим установки и обновлений. Сначала завершает процесс свой процесс, работающий в режиме мониторинга, если таковой имеется. Его PID храниться в файле /tmp/moni.lock

Далее переустанавливает и перезапускает модуль «Bill».

Затем, если существует процесс работающий в режиме управления модулем «Bill», то он завершается. Его PID хранится в файле /tmp/gates.lock

Если установлен флаг g_iIsService (получется тем же образом, что и предыдущей версии) то прописывает себя в автозагрузку тем же способом, что и ранее (в предыдущей версии).

Далее записывает путь до себя в файл /tmp/notify.file и самокопируется в файл /usr/bin/pojie. После чего запускает свою копию, которая, очевидно, будет работать уже в режиме мониторинга, а сам переходит в режим управления модулем «Bill».

Режим мониторинга. Записывает PID текущего процесса в файл /tmp/moni.lock.Далее запускат два потока для мониторинга модуля «Bill» и модуля «Gates» в режиме управления. И если один из этих процессов на данный момент не запущен, то нужный файл заново создается и запускется.

Режим управления модулем «Bill». Этот режим полностью соответствует тому, что происходило в прошлой версии после установки модуля «Bill» и инициализации необходимых переменных и структур троянца.

Таким образом, в новой версии трояна авторы добавили ему немного «живучести», но основной функционал остался без существенных изменений.

Стоит также отметить, что прописанный в коде IP-адрес C&C сервера остался прежним (116.10.189.246), однако изменился номер порта — 36008 вместо прежнего 30000.

Полный текст статьи читайте на Лаборатория Касперского