Light mode

Hellhounds: операция Lahat

18 минут
  • #Атаки
  • #ВПО

Все мы знаем, что идеальных преступлений не существует — злоумышленники всегда оставляют следы. Так, в октябре 2023 г. команда PT ESC CSIRT обнаружила признаки компрометации российской энергетической компании с использованием бэкдора Decoy Dog. За инцидентом стояла ранее неизвестная группировка Hellhounds.

В ходе расследования мы узнали и о других жертвах хакеров. Hellhounds успешно атакуют отечественные организации по меньшей мере с 2021 г., а разработку ВПО ведут как минимум с 2019-го. В этой статье мы расскажем об инструментарии и методах маскировки группы.

Атаки на Linux

Ранее о Decoy Dog рассказывали НКЦКИ, Infoblox, CyberSquatting и Solar 4RAYS. Однако образец, обнаруженный нами на хосте жертвы, представлял собой новую модификацию бэкдора: злоумышленники доработали его, чтобы усложнить обнаружение и анализ ВПО.

First Stage (Decoy Dog Loader)

Во время расследования мы обнаружили исполняемый файл /usr/bin/dcrond размером 9 КБ (см. рис. 1).

Рис_1.png
Рисунок 1. Обнаруженный исполняемый файл

Он был защищен модифицированной версией упаковщика UPX с измененной сигнатурой 37 13 03 00 вместо UPX!. На момент расследования только один антивирусный движок детектировал пакер, а некоторые образцы и вовсе ничем не детектировались. Для обнаружения модифицированного UPX можно использовать публичное YARA-правило из исследования JPCERT/CC.

Рис_2.png
Рисунок 2. Вердикты антивирусных движков

В отличие от обычного UPX эта модификация распаковывает не исполняемый файл, а шеллкод, полностью написанный на языке ассемблера и использующий только системные вызовы Linux. После модифицированного UPX-заголовка расположена зашифрованная конфигурация (хранит путь до зашифрованного файла с основной нагрузкой), следом за которой идет сжатый шеллкод (см. рис. 3).

Рисунок 3.png
Рисунок 3. Фрагмент Decoy Dog Loader

Загрузчик работает в системе и маскируется под легитимный сервис cron. Также мы обнаружили образцы, маскирующиеся под легитимный сервис irqbalance и библиотеку lib7.so.

[Unit]

Description=Daemon to execute scheduled commands

Documentation=man:dcrond(8)

[Service]

Type=forking

ExecStart=/usr/bin/dcrond

Restart=always

В атаках 2022 г. злоумышленники маскировали образцы первых версий ВПО под сервисы atd и systemd-readahead-stop.service. Образцы размещались в директориях /usr/bin/atd или /usr/bin/container:

[Unit]

Description=Deferred execution scheduler

Documentation=man:atd(8)

[Service]

Type=forking

ExecStart=/usr/bin/atd

Restart=always

[Install]

WantedBy=multi-user.target

Сперва загрузчик проверяет, не находится ли он под отладкой. Для этого он читает /proc/self/status и проверяет, что TracerPid равен 0. Если же TracerPid отличен от 0, он подменяет себя на /bin/sh с помощью системного вызова execve.

Убедившись, что он не находится под отладкой, загрузчик пытается по порядку прочитать идентификаторы скомпрометированного хоста из следующих файлов:

  • /etc/machine-id;
  • /var/lib/dbus/machine-id;
  • /var/db/dbus/machine-id;
  • /usr/local/etc/machine-id;
  • /sys/class/dmi/id/product_uuid;
  • /sys/class/dmi/id/board_serial;
  • /etc/hostid;
  • /proc/self/cgroup.

Загрузчик считает MD5-хеш первого существующего в файловой системе файла и использует полученный хеш как ключ для расшифровки конфигурации и основной нагрузки, которые зашифрованы криптографическим алгоритмом CLEFIA с 128-битным ключом.

Рисунок_4.png
Рисунок 4. Алгоритм CLEFIA

На этом этапе исследования стало понятно, что образец ориентирован на работу на конкретном хосте. При этом злоумышленники заранее получили доступ к хосту для получения идентификатора и добавления его в конфигурацию.

Second Stage (Decoy Dog)

Основная нагрузка исследуемого образца расположена в файловой системе по пути /usr/share/misc/pcie.cache. Расшифрованная нагрузка является модифицированной версией Pupy RAT, которую исследователи называют Decoy Dog.

Основные отличия Decoy Dog от Pupy RAT:

  • Клиент обновлен с устаревшего Python 2.7 до Python 3.8
  • Добавлен ряд новых функций, связанных с внедрением кода в виртуальную машину Java
  • Добавлены новые транспорты: BOSH, lc4, lws4, ws4, dfws4
  • Добавлена возможность загружать динамический конфигурационный файл и сохранять его на диске в зашифрованном виде
  • Добавлен новый канал соединения (launcher) под названием special (локальное соединение с помощью IP-адреса и порта или файлового сокета)
  • Повышена отказоустойчивость при помощи DGA и резервных управляющих серверов с указанием конкретных доменов

Исследуемый образец использовал управляющий сервер z-uid.lez2yae2.dynamic-dns[.]net, который находился в конфигурации, встроенной в исполняемый файл. Фрагмент конфигурации представлен на рис. 5.

Рис_5.png
Рисунок 5. Фрагмент конфигурации Decoy Dog RAT

Кроме того, троянская программа получает динамическую (актуальную) конфигурацию из файла /var/lib/misc/mpci.bin. Он зашифрован криптографическим алгоритмом AES в режиме счетчика (CTR) со 128-битным ключом (который, в свою очередь, зашифрован на эллиптической кривой brainpoolP384r1) и содержит новые управляющие серверы:

  • m-srv.daily-share.ns3[.]name;
  • f-share.duckdns[.]org.

Открытый ключ для расшифровки ключа AES хранится в конфигурации внутри исполняемого файла. Также в конфигурации исследуемого образца содержится скриплет, который запускается при каждом запуске бэкдора. Он называется telemetry и служит для отправки телеметрии (информации о зараженной системе) в социальную сеть mindly.social (на основе открытого движка Mastodon) через API сервиса. Содержимое телеметрии:

{

'cid': <идентификатор бэкдора из конфигурации>,

'user': <имя пользователя>,

'hostname': <имя хоста>,

'node': <MAC-адрес в виде 48-битного числа>,

'platform': <платформа>,

'node': <MAC-адрес в виде 48-битного числа>,

'pid': <идентификатор процесса бэкдора>,

'ppid': <идентификатор родительского процесса бэкдора>,

'cwd': <рабочая директория>,

'proc_arch': <архитектура запущенного процесса бэкдора>,

'exec_path': <путь к запущенному процессу бэкдора>,

'uac_lvl': <уровень защиты UAC>,

'intgty_lvl': <уровень целостности процесса бэкдора>,

'machine_key': <MD5-хеш от идентификатора системы>,

'proxy': <строка подключения к прокси-серверу по умолчанию>,

'external_ip': <внешний IP-адрес в виде 32-битного числа>,

'internal_ip': <внутренний IP-адрес в виде 32-битного числа>,

'boottime': <дата и время запуска машины (Unix time)>

}

Передаваемые данные шифруются таким же образом, как и файл динамической конфигурации, — с использованием того же открытого ключа. Поэтому даже при перехвате переданных данных их невозможно расшифровать без закрытого ключа.

Отправка данных осуществляется с помощью API-ключа, который хранится в коде в открытом виде. Но злоумышленники ограничили область доступа к нему только записью данных. Таким образом, даже при наличии API-ключа прочитать данные не получится.

Рисунок_6.png
Рисунок 6. Фрагмент кода Decoy Dog RAT

Однако нам все же удалось установить, что телеметрия с зараженных хостов отправляется в аккаунт с юзернеймом @lahat, в честь которого мы и назвали исследование.

Рис_7.png
Рисунок 7. Страница пользователя @lahat в mindly.social

В Decoy Dog предусмотрен механизм генерации DGA-имен при потере связи по основному каналу управления.

Если в конфигурации включена опция bootstrap-domains (см. рис. 8), для генерации используется один из основных доменов. В противном случае генерируется поддомен для одного из указанных в конфигурации доменов верхнего уровня или домен для одной из указанных зон (по умолчанию используется домен верхнего уровня dynamic-dns.net). В конфигурации исследуемого образца были выбраны домены duckdns.org и dynamic-dns.net.

Рисунок_8.png
Рисунок 8. Bootstrap domains (DGA)

Резервный домен генерируется как первая половина шестнадцатеричного представления MD5-хеша от строки с текущей датой в формате <год><месяц><день> и открытого ключа, используемого при шифровании коммуникации с управляющим сервером.

Затем от получившегося домена (или одного из основных, если включена опция bootstrap-domains) считается MD5-хеш. После этого от первой половины шестнадцатеричного представления берется по два символа и дописывается слева к домену. В итоге получается набор из девяти доменов, к которым пытается подключиться ВПО. Например, для домена m-srv.daily-share.ns3[.]name получается восемь дополнительных доменов:

  • 6cm-srv.daily-share.ns3[.]name
  • 78m-srv.daily-share.ns3[.]name
  • 7fm-srv.daily-share.ns3[.]name
  • b1m-srv.daily-share.ns3[.]name
  • 98m-srv.daily-share.ns3[.]name
  • d5m-srv.daily-share.ns3[.]name
  • 2fm-srv.daily-share.ns3[.]name
  • 08m-srv.daily-share.ns3[.]name

Домены генерируются следующим кодом:

import datetime, hashlib

WELL_KNOWN_ZONES = ('dynamic-dns.net', )

def make_emergency_related_domains(domain):

domain_bytes = domain

if isinstance(domain_bytes, bytes):

domain = domain.decode()

else:

domain_bytes = domain.encode()

prefix_hash = hashlib.md5(domain_bytes).hexdigest()[:16]

for x in range(len(prefix_hash) // 2):

yield prefix_hash[x * 2:x * 2 + 2] + domain

class EmergencyDomains(object):

__slots__ = ('key', 'zones', 'beacon_domains', '_zone_id', '_emergency_loop')

def __init__(self, key, beacon_domains=None, zones=None):

self.key = key

self.zones = zones or WELL_KNOWN_ZONES

if not isinstance(self.zones, (list, tuple, set)):

self.zones = tuple((self.zones,))

self.beacon_domains = beacon_domains

self._zone_id = 0

self._emergency_loop = self._emergency_loop_generator()

def _emergency_loop_generator(self):

if self.beacon_domains:

for domain in self.beacon_domains:

yield domain

yield self._domain_of_the_day()

def iterate(self):

try:

while True:

yield next(self._emergency_loop)

except StopIteration:

self._emergency_loop = self._emergency_loop_generator()

def _domain_of_the_day(self):

now = datetime.datetime.utcnow()

ts_formatted = now.strftime('%Y%m%d')

if not isinstance(ts_formatted, bytes):

ts_formatted = ts_formatted.encode()

formatted_key = self.key

if not isinstance(formatted_key, bytes):

formatted_key = formatted_key.encode()

domain_hash = hashlib.md5()

domain_hash.update(ts_formatted)

domain_hash.update(formatted_key)

domain_part = domain_hash.hexdigest()[:16]

zone = self.zones[self._zone_id]

self._zone_id = (self._zone_id + 1) % len(self.zones)

return domain_part + '.' + zone

Рисунок 9.svg
Рисунок 9. Схема работы Decoy Dog

Атаки на Windows

В процессе реагирования на инцидент в российской транспортной компании команде PT ESC CSIRT также удалось обнаружить следы успешной атаки на Windows-инфраструктуру, о которых не было известно ранее.

First Stage (Decoy Dog Loader for Windows)

Получив доступ в систему, атакующие устанавливали сервис с именем Microsoft Account Service или Microsoft Viewer Service, который запускал исполняемый PE-файл с именем AccSrvX64__STABLE__2016-11-10.exe или R_TARIF.VIEWS_X86.EXE. Пример:

{

"Name": "Microsoft Account Service",

"Caption": "Microsoft Account Service",

"Description": "",

"DisplayName": "Microsoft Account Service",

"PathName": "C:\\[REDACTED]\\accounts64\\AccSrvX64__STABLE__2016-11-10.exe",

"ProcessId": 5092,

"Started": true,

"State": "Running",

"SystemName": "[REDACTED]",

"TimeLine": "2024-01-02T21:14:53.132165Z",

"ModuleName": "Win32_Service"

}

{

"Name": "Microsoft Viewer Service",

"Caption": "Microsoft Viewer Service",

"Description": "",

"DisplayName": "Microsoft Viewer Service",

"PathName": "C:\\[REDACTED] \\R_TARIF.VIEWS_X86.EXE",

"ProcessId": 5548,

"Started": true,

"State": "Running",

"SystemName": "[REDACTED]",

"TimeLine": "2024-01-03T22:04:30.5586058Z",

"ModuleName": "Win32_Service"

}

Интересно, что злоумышленники начали предпринимать активные действия в инфраструктуре скомпрометированной организации в новогодние праздники — второго и третьего января.

Размер исполняемого файла составляет 17 КБ. После успешного запуска сервиса образец расшифровывает список доменов, которые содержатся в секции .rdata, и пытается резолвить полученные доменные имена.

Каждый зашифрованный домен начинается с байта FF. Используется простой алгоритм шифрования на основе операций Xor и вычитания. В расшифровке участвует номер символа в строке и номер строки (символы в строках нумеруются с нуля).

Рис_10.png
Рисунок 10. Алгоритм шифрования

Домены имеют следующий формат:

[-][!][!][...]<domain>

Параметр «-» означает, что успешно резолвить домен необязательно. Если его не удалось разрезолвить, загрузчик переходит к следующему домену из списка. Параметр «!» используется только совместно с параметром «-» и показывает количество попыток резолвов, после которых домен будет пропущен. Оно рассчитывается по формуле 2^n, где n — это количество указанных подряд «!». Если параметр не задан, будет сделана всего одна попытка резолва.

Домены из конфигурации используются при получении одной из частей ключа для расшифровки полезной нагрузки. Они также могут применяться для создания схожего с легитимным трафика и обхода песочниц.

В результате поверхностного динамического анализа образца можно подумать, что домены, которые используются на этом этапе, являются управляющими серверами. Но детальный анализ показывает, что домены и полученные впоследствии IP-адреса применяются не только для генерации ключа, но и, предположительно, для маскировки под легитимные утилиты. Кроме того, ВПО может использовать несуществующие поддомены на реально существующих доменах (например, mp0.ptsecurity.com). Это позволяет создавать видимость легитимности, при этом поддомен гарантированно не будет разрезолвен.

Обычно домен с параметром «-» используется только для создания трафика — не для генерации ключа. Такой домен не должен резолвиться, или же он будет разрезолвен после нужного домена. При этом один из доменов обязательно должен резолвиться и иметь фиксированный IP-адрес — он и будет использован для генерации ключа. Примечательно, что эту особенность злоумышленники могут использовать как kill-switch-механизм для прекращения функционирования ВПО в целевой системе.

После расшифровки и резолва всех доменов в конфигурации загрузчик расшифровывает следующий блок в секции .rdata (см. рис. 11).

Рисунок_11.png
Рисунок 11. Блок в секции .rdata

Этот блок имеет фиксированный размер 256 байт и зашифрован алгоритмом CLEFIA в режиме сцепления блоков (CBC). Он содержит путь к основному бэкдору. Ключ формируется следующим образом: имя исполняемого файла без завершающего нуля приводится к верхнему регистру, затем к нему добавляется IP-адрес в байтовом представлении. После этого от получившейся байтовой строки считается 256-байтовый хеш SHA-3, первые 16 байт которого используются как ключ, а байты с 5-го по 20-ый используются в качестве вектора инициализации. Пример формирования ключа представлен на рис. 12.

Рисунок_12.png
Рисунок 12. Алгоритм расшифровки пути Second Stage (Decoy Dog for Windows)

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

В бэкдоре сигнатура MZ заменена на сигнатуру HE, а сигнатура PE перезаписывается в виде случайной 4-байтной последовательности.

Рисунок_13.png
Рисунок 13. Фрагмент Decoy Dog

Злоумышленники прикладывали много усилий, чтобы замаскировать свою активность на скомпрометированных узлах. К примеру, мимикрировали под MaxPatrol SIEM и сервисы Microsoft.

Рисунок_14.png
Рисунок 14. Информация о файлах Decoy Dog Loader for Windows

Примечательно, что образцы под Linux фактически не работали, если не проходили проверку идентификатора machine-id. То есть воспроизвести запуск ВПО без корректного идентификатора невозможно. При этом в образцах под Windows эта проверка отсутствует, зато имеется проверка имени исполняемого файла, которое никогда не совпадает с original filename из метаданных (это более слабая проверка). В случае изменения IP-адреса исследователи могут воспользоваться PDNS-сервисами (Passive DNS).

Second Stage (Decoy Dog for Windows)

Расшифрованная нагрузка практически не отличается от рассмотренной ранее версии Decoy Dog под Linux. Бэкдор основан на open-source-проекте Pupy RAT. Все образцы, которые нам удалось обнаружить, имели управляющий сервер net-sensors[.]net и DGA-домен dynamic-dns[.]net. Динамическая конфигурация отсутствовала во всех образцах.

Пример конфигурации:

{'debug': False, 'launcher': 'dnscnc', 'launcher_args': ['--domain', 'net-sensors.net', '-E', 'dynamic-dns.net'], 'delays': [(10, 5, 10), (50, 30, 50), (-1, 150, 300)] [REDACTED] 'cid': 61336226}

Рисунок 15.svg
Рисунок 15. Детальная схема работы Decoy Dog (Windows)

В ходе исследования мы выявили образцы под Windows, самый старый из которых был скомпилирован 29.11.2019, а самый свежий — 03.01.2024. Помимо Decoy Dog, злоумышленники использовали хорошо известный фреймворк Sliver с управляющим сервером 31.184.204[.]42 (ns2.maxpatrol[.]net). Детальный разбор аналогичных образцов смотрите в материале «Импланты Sliver под микроскопом: извлечение конфигурации и других полезных данных». В табл. 1 представлены все полученные нами образцы под ОС Windows.

DateDescriptionSHA-256NamePayload pathDomains
29.11.2019First Stage (Decoy Dog Loader for Windows) — test version9a977571296ae1548c32df94be75eec2a414798bee7064b0bf44859e886a0cfatestvec.exeazure.microsoft.com
14.07.2022First Stage (Decoy Dog Loader for Windows)4d30fd05c3bdac792e0a011892e2cad02818436484e81b6de6a02928149bc92dMaxPatrol SIEM Agent.exefwtsqmfilefrwimp0.ignorelist.com
-mp0.ptsecurity.com
30.11.2022First Stage (Decoy Dog Loader for Windows)e27d1bab901c1bb414d0849c5c132faa8c7c6a61357d9627a7d2785270034793Microsoft.exeexmimeL5rq
29.01.2023First Stage (Decoy Dog Loader for Windows)31b21de71f2162e8da1be8483f3a5d019b0c817832bc11a9f307b6b36821ca54act0.microsoft.com
dns.msftncsi.com
16.04.2023First Stage (Decoy Dog Loader for Windows)18d4a3a92b24b2ad75115a44fe2727081316eca346499a4aa00aa13713cf00cb− act0.microsoft.com
dns.msftncsi.com
06.05.2023First Stage (Decoy Dog Loader for Windows)9a96c7b0595f628027c4f4caeece475ef742c420adf2fde8df934c6ce6481fb5− act0.microsoft.com
dns.msftncsi.com
16.08.2023First Stage (Decoy Dog Loader for Windows)d9a8151aff9d1c061826a9812ed9a6600805c74a519df333513fd4a79d2d4e61NtpService.exeC:\Users\Public\JProf\JProf.hbin− act0.microsoft.com
dns.msftncsi.com
06.11.2023First Stage (Decoy Dog Loader for Windows)07fe71b256c1c913b0f3e3fa67e53d21a3d1f499beb4e550597f5743797a77c4Apache ActiveMQ.exeact0.microsoft.com
mvs05.zyns.com
08.11.2023Second Stage (Decoy Dog for Windows)e19dc185e99cfdc0c25f18fb34ffabff2a4877d6d5843e4c67c05ce182f9780eNPipeX64_32.dllC2: net-sensors.net
DGA domains: dynamic-dns.net
08.11.2023Second Stage (Decoy Dog for Windows)106436a4fafe00112b19b1374456c1746b988950b71d700680088d74494e4936r_tarif.dll2QurC2: net-sensors.net
DGA domains: dynamic-dns.net
27.12.2023Sliver510da6d88ae4dd51d62796023a18b39db08a016ee4ee7178b1afdc91c58f9e1eC2: 31.184.204.42
27.12.2023Sliver6cb2979aa1fddd42df2ba596f705ce9bbdb2ec246649218d598d779769857c21C2: 31.184.204.42
02.01.2024First Stage (Decoy Dog Loader for Windows)1b8b4be020d3350d025c7a245eb0d7166ff2c329dc92af175ef0499cba583071AccSrvX64__STABLE__2016-11-10.exeC:\ [REDACTED]\accounts64\NPipeX64_32.dll− act0.microsoft.com
dns.msftncsi.com
03.01.2024First Stage (Decoy Dog Loader for Windows)a03e2ca143e867a99e2bc73bd4e5c2dd078a9f671aa0a4ce9611a8bc39a769e2R_TARIF.VIEWS_X86.EXEC:\ [REDACTED]\rtarif\r_tarif.dll2Qur− act0.microsoft.com
dns.msftncsi.com
Таблица 1. Образцы под Windows

Примечательно, что большинство образцов содержат в конфигурации домен dns.msftncsi.com, который является тестовым сервером компонента индикатора состояния сетевого подключения (Network Connectivity Status Indicator, NCSI) в Windows.

Изучив конфигурации всех полученных образцов, мы выявили SSL-сертификаты, которые используются в бэкдоре для шифрования соединений с удаленными узлами. Сертификаты содержали самый ранний параметр notBefore от 26.12.2021 (21:51:52), а самый свежий параметр — от 08.11.2023 (13:48:36). Исходя из этого, можно предположить, что кампания началась как минимум в конце 2021 г. Сертификаты выпускались на один и три года с момента генерации образцов: подобный алгоритм реализован в публичном проекте Pupy RAT.

Рисунок_16.png
Рисунок 16. Примеры сертификатов

Initial Access

В двух инцидентах атакующим удалось проникнуть в инфраструктуру жертв через подрядчика. Скомпрометировав учетные данные для входа по протоколу SSH, злоумышленники установили жертвам Decoy Dog.

Нам также удалось получить содержимое с управляющего сервера net-sensor[.]net и обнаружить, что злоумышленники маскировали образцы Decoy Dog под ISO-образы сервиса iMind, который используется для проведения видеоконференций и вебинаров (см. рис. 17). К сожалению, нам не удалось выяснить, как злоумышленники вынуждали жертв запускать ISO-образы. При этом в сентябре 2023 г. НКЦКИ уведомляли об участившихся компьютерных инцидентах, связанных с эксплуатацией уязвимости в iMind, и рекомендовали обновиться до версии 3.19.

Рисунок 17.png
Рисунок 17. Листинг папок на C2, содержимое папки imind и ISO-образы, которые содержат Decoy Dog

Жертвы

По нашим данным, как минимум 48 российских организаций были скомпрометированы с использованием Decoy Dog. Мы не знаем конечных целей атакующих, но в одном из инцидентов злоумышленники вывели из строя ряд сервисов крупного телеком-оператора (об этом рассказывали исследователи из Solar 4RAYS).

Анализ показывает, что злоумышленники фокусируются не только на госсекторе, но и активно атакуют российские ИТ-компании, большинство из которых являются подрядчиками критически важных организаций. Можно предположить, что хакеры нацелены на проведение атак типа Trusted Relationship. Распределение жертв по отраслям выглядит следующим образом (см. рис. 18).

Рисунок 18.jpg
Рисунок 18. Распределение жертв по отраслям

Мы дěлаем Positive Research → для ИБ-экспертов, бизнеса и всех, кто интересуется ✽ {кибербезопасностью}