SHA1:
c38a04fe3c18f03c1ab910cc8c9b180102413c8e (i686, неупакованный)
7feb14146ac938e5989cc0c9eda001540ef5d760 (i686, упакованный)
fc9651f35a50aa5139bd4877b900b922463117c6 (arm, упакованный)
1d5c88b1027ffa0874015b7546f144cf8ab5b5e1 (mips, упакованный)
be4b4f732e26d32a8d02504a252a1ab4832f2cce (mipsel, упакованный)
Троянская программа, предназначенная для заражения устройств, работающих под управлением ОС семейства Linux. В данной версии троянца упор сделан не на эксплуатацию уязвимостей (как в версии Linux.PNScan.1), а на использование стандартных паролей для несанкционированного доступа к устройствам.
Троянец собран с применением статической линковки, а отладочная информация и таблица секций удалены. В процессе линковки были использованы библиотеки libcurl, libssh2, libevent, openssl и janson. Все бинарные файлы вредоносной программы снабжены подписью ECDSA с использованием эллиптической кривой "prime192v1".
Троянец решает четыре практические задачи:
- взлом устройства и загрузка на них своих файлов (троянец распространяется комплектом из четырех файлов, собранных под архитектуры i686, ARM, MIPS и MIPSEL);
- открытие портов 9000 и 1337 на взломанных устройствах;
- обслуживание запросов на этих портах;
- обеспечение связи с управляющим сервером.
Инфицирование устройств
Инфицирование осуществляется методом подбора пары login:password по словарю для доступа с использованием протокола SSH по порту 22. В процессе заражения устройств троянец генерирует файл "list2", представляющий собой список IP-адресов в диапазоне "a.b.*.*", где a и b – случайные числа.
Также создается файл "login2" с тремя парами login:password:
root;root;
admin;admin;
ubnt;ubnt;
Затем троянец последовательно перебирает все IP-адреса из файла "list2" и пытается авторизоваться на каждом ресурсе по протоколу SSH с использованием одной из пар login:password из файла "login2". Сведения обо всех успешных попытках записываются в файл с именем "good2".
В случае успешной авторизации троянец проверяет, заражено ли устройство. Для этого он отправляет на него запрос "IP:9000/check", и, если оно заражено, то в ответ поступает JSON:
{"status":1}
Если устройство не заражено, троянец помещает в папку "/tmp/.xs/" атакованного устройства набор своих файлов, проверив корректность их цифровой подписи (в зависимости от модели скомпрометированного устройства существуют наборы файлов для архитектур ARM, MIPS, MIPSEL и x86) и запускает их.
Как только проверены все IP-адреса из сгенерированного диапазона, троянец делает паузу, после чего выполняет повторный проход по всем адресам из файла "good2" и проверяет, чтобы все устройства были заражены. Если вдруг на любом из устройств троянец по каким-то причинам не ответил на запрос (IP:9000/check), то туда заново загружается копия вредоносной программы. После этого троянец повторяет атаку на удаленные устройства, начиная с этапа генерации IP-адресов.
Обработка команд
Троянец открывает порт 9000, на который принимает входящие запросы. Может обрабатывать следующие команды:
/check
- используется для проверки факта заражения устройства. Если устройство заражено и троянец работает, то в ответ на запрос отправляется JSON:
{"status":1}
/upload
- загрузка файлов на устройство. Полезной нагрузкой POST-запроса должен быть JSON, содержащий информацию о загружаемом файле (имя, архитектура, данные в кодировке base64):
{
"upload":
{
"name" : file_name
"data" : file_data_in_base64
"arch" : file_arch
}
}
Перед сохранением файла троянец проверяет наличие у него цифровой подписи. Если проверка прошла успешно, файлы помещаются в директорию "/tmp/.xs/files/" с указанным в принятом JSON именем, а отправителю запроса отвечает следующим JSON:
{"status":1}
/<filename>&ver=3422792789
высылает содержимое файла "/tmp/.xs/files/<filename>" при условии, что у троянца версия этого файла не новее указанной в параметре "ver".
Поиск управляющих серверов
Поиск адресов управляющих серверов осуществляется следующим образом:
- Случайным образом выбирается домен из списка: "google.com", "twitter.com", "microsoft.com" и на него отправляется GET-запрос по https-протоколу.
- В полученном ответе извлекается значение поля Date из заголовков и на основе этой даты при помощи специального алгоритма генерируется три имени. В процессе генерации троянец использует зашитый в его тело список строк:
- Троянец отправляет запрос по протоколу HTTPS на один из 4 удаленных узлов:
- https://twitter.com/search?f=realtime&q=%s
- https://twitter.com/%s
- https://my.mail.ru/mail/%s/
- https://reddit.com/search?q=%s
где вместо %s подставляется одно из сгенерированных на этапе № 2 имен. Постепенно перебираются все комбинации доменов и сгенерированных имен. Если управляющий сервер не был найден, поиск повторяется через 5 минут.
- Искомое сообщение на странице находится между сгенерированным на этапе № 1 именем и символом «@».
- Сообщение закодировано в base64 и зашифровано с использованием операции XOR со сгенерированным на этапе № 1 именем в качестве ключа.
- Полученные данные имеют вид:
- offset 0: message
- offset n-5: version
- offset n-1: opcode
- offset n: ECDSA_r
- offset n+sizeof(ECDSA_r): ECDSA_s
Для полученных данных проверяется цифровая подпись по алгоритму ECSDA. При проверке подписи используется хэш-функция SHA1. Публичный ключ зашит в теле троянца.
- Если проверка подлинности прошла успешно, данные сохраняются в файл "files/srv_cc".
На основе алгоритмов генерации имени можно сделать вывод, что предполагается использование управляющих серверов с разным сроком службы – один день, одна неделя, один месяц.
Протокол связи с управляющим сервером
Ответы управляющего сервера на любые корректные запросы, поступающие с зараженной машины, подписаны, троянец всегда проверяет подпись.
Пример файла srv_cc, который содержит IP управляющего сервера:
Данный файл имеет следующую структуру:
struct srv_cc
{
_BYTE cnclist_len;
_DWORD cnclist[cnclist_len];
_BYTE opcode;
_DWORD version;
_BYTE signature[0x30];
}
, где cnclist - список IP-адресов управляющих серверов в шестнадцатеричном представлении.
Затем троянец перебирает все IP-адреса из списка, начиная со случайно выбранного, и отправляет запрос вида "cnc_ip:9000/i686?ver=0". Ответ сохраняет в файл "files/i686" (при наличии правильной подписи у файла). Причем вместо i686 может быть подставлено mips, mipsel, arm в соответствии с архитектурой работающего на устройстве троянца. Далее на управляющий сервер отправляется запрос "cnc_ip:9000/srv_report?ver=0". Ответ сохраняется в файл "files/srv_report".
Пример файла srv_report:
Данный файл содержит один или несколько адресов (URL), на которые троянец будет отправлять данные о зараженном устройстве и с которых будет получать команды злоумышленников. Файл имеет структуру:
struct srv_report
{
char cnc_report_urls[];
_BYTE opcode;
_DWORD version;
_BYTE signature[0x30];
}
Список адресов управляющих серверов cnc_report_urls может содержать несколько ссылок, разделенных значением '\n'.
На каждый из адресов управляющих серверов троянец отправляет запрос. Для этого вредоносная программа формирует JSON с данными о зараженной системе и самом троянце:
{
"os":
{
"uname":
{
"machine" : utsbuf.machine,
"nodename" : utsbuf.nodename,
"release" : utsbuf.release,
"sysname" : utsbuf.sysname,
"version" : utsbuf.version,
}
"localaddr" : localddr,
"lip" : local_ip,
"hwaddr" : mac_addr,
"cpuinfo" : cpuinfo,
"osversion" : osver,
}
"bid" : bid,
"arch" : arch,
"ver" : version,
"ip" : extip,
"auth" :
{
"good" : good2,
"timescan" : timescan,
"timecheck" : timecheck,
"timerecheck" : timerecheck,
"countcheck" : countcheck,
"countrecheck" : countrecheck,
"countscan" : countscan,
"countcheckgood" : countcheckgood,
"countrecheckgood" : countrecheckgood,
}
}
где поля в секции "auth" - данные о взломанных узлах, которые удалось инфицировать (содержимое файла good2), количество зараженных устройств, количество проверенных устройств и т. д.;
extip - внешний IP-адрес, проверяется через "checkip.dyndns.org";
bid - уникальный идентификатор троянца. Формируется следующим образом:
sha1_init(&sha1_ctx);
sha1_update(&sha1_ctx, macaddr, strlen(macaddr));
sha1_update(&sha1_ctx, utsbuf.machine, strlen(utsbuf.machine));
sha1_update(&sha1_ctx, utsbuf.nodename, strlen(utsbuf.nodename));
sha1_update(&sha1_ctx, utsbuf.release, strlen(utsbuf.release));
sha1_update(&sha1_ctx, utsbuf.sysname, strlen(utsbuf.sysname));
sha1_update(&sha1_ctx, utsbuf.version, strlen(utsbuf.version));
sha1_final(&hash, &sha1_ctx);
HexToStr(&hash, 16, outbid);
JSON отправляется POST-запросом в зашифрованном виде. Первые 4 байта запроса – контрольная сумма CRC32 JSON-а, далее следует JSON, зашифрованный RC4, где ключ шифрования - контрольная сумма CRC32 JSON-а.
Ответ сервера также зашифрован RC4, первые 4 байта в нем являются одновременно ключом шифрования и контрольной суммой сообщения. Если данные были успешно расшифрованы и у них имеется корректная подпись, они сохраняются в файл "config".
Пришедший от сервера конфигурационный блок данных имеет формат JSON:
{
"bid": bid
{
"upload":
{
"name" : file_name
"data" : file_data_in_base64
"arch" : file_arch
}
"exec":
{
"cmd" : cmd
}
"download":
{
"path" : path
}
}
}
Троянец выполняет указанные в конфигурации команды, в том числе на загрузку файла на зараженное устройство, на загрузку файла с устройства на сервер или выполнение произвольного скрипта и отправляет отчет в виде JSON:
{
"upload":
{
"name" : file_name
"status" : status
}
"exec":
{
"cmd" : cmd
"result" : result
"status" : status
}
"download":
{
"path" : path
"result" : result
"status" : status
}
}
Количество полей определяется количеством команд, поступивших от сервера.
При получении команды upload проверяется наличие правильной цифровой подписи файла, а команды "cmd" и "download" не содержат никакой проверки подлинности.