Многофункциональный DDoS-троянец под Linux – MEFISTO13 — я.ру
статья с очень интересным заголовком – «Исследуем 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/%5Bmodule_name%5D все свои компоненты (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(). В нем каждую секунду обновляются
данные о загруженности процессора и сети, которые впоследствии могут
отправляться 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.so
2 — «Bill» — дропнутый модуль cupsddh
3 — «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 (смещение в
распакованном файле: 0x8f44с, размер 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_all
add_device eth%d
max_before_softirq 10000
2. файл — /proc/net/pktgen/eth%d — для каждого ядра процессора, где %d — номер ядра, начиная с 0. Содержание файла:
count 0
clone_skb 0
delay 0
TXSIZE_RND
min_pkt_size %d
max_pkt_size %d
IPSRC_RND
src_min %s
src_max %s
UDPSRC_RND
udp_src_min %d
udp_src_max %d
dst %s
udp_dst_min %d
udp_dst_max %d
dst_mac %02x:%02x:%02x:%02x:%02x:%02x //MAC-адрес шлюза из g_statBase
is_multi %d
multi_dst %s //если адресов для атаки несколько (т. е. значение в
предыдущей строке не равно 0), то они задаются в этих строках,
количество которых соответствует предыдущему параметру
pkt_type %d
dns_domain %s
syn_flag %d
is_dns_random %d
dns_type %d
is_edns %d
edns_len %d
is_edns_sec %d
Значения большинства параметров pktgen передаются через параметры команды от cupsdd.
3.файл — /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».
1. Режим установки и обновлений.
Сначала завершает свой процесс, работающий в режиме мониторинга, если таковой имеется. Его PID храниться в файле /tmp/moni.lock
Далее переустанавливает и перезапускает модуль «Bill».
Затем, если существует процесс работающий в режиме управления модулем
«Bill», то он завершается. Его PID хранится в файле /tmp/gates.lock
Если установлен флаг g_iIsService (получается тем же образом, что и
предыдущей версии) то прописывает себя в автозагрузку тем же способом,
что и ранее (в предыдущей версии).
Далее записывает путь до себя в файл /tmp/notify.file и
самокопируется в файл /usr/bin/pojie. После чего запускает свою копию,
которая, очевидно, будет работать уже в режиме мониторинга, а сам
переходит в режим управления модулем «Bill».
2. Режим мониторинга.
Записывает PID текущего процесса в файл /tmp/moni.lock. Далее запускает
два потока для мониторинга модуля «Bill» и мониторинга модуля «Gates»,
работающего в режиме управления. И если один из этих процессов на данный
момент не запущен, то нужный файл заново создается и запускается.
3. Режим управления модулем «Bill».
Действия, совершаемые модулем Gates в этом режиме, полностью
соответствуют действиям, которые совершал этот же модуль в предыдущей
версии троянца (после установки модуля Bill и инициализации необходимых
ему переменных и структур).
Таким образом, в новой версии троянца авторы добавили ему немного
«живучести», но основной функционал остался без существенных изменений.
Стоит также отметить, что прописанный в коде IP-адрес C&C сервера
остался прежним (116.10.189.246), однако изменился номер порта – 36008
вместо прежнего 30000.