Описание вредоносного ПО

Пиратка дороже золота: новый бэкдор для macOS крадет криптокошельки

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

Этап 1. Activator.app

Найденные нами образцы запускаются в macOS 13.6 и выше. Можно сделать вывод, что на данном этапе злоумышленники нацелены только на пользователей новых операционных систем, причем как на устройствах под управлением процессоров Intel, так и на устройствах с Apple Silicon. Скомпрометированные образы дисков содержат так называемый «Активатор» и само искомое приложение. Запустив (смонтировав) образ диска, пользователь видит окно с инструкцией:

Окно с инструкцией по установке

Окно с инструкцией по установке

В инструкции указано скопировать приложения в папку /Applications/ и затем запустить «Активатор». Внешне он выглядит довольно просто: в нем есть только одна кнопка «PATCH», после нажатия которой система запрашивает у пользователя пароль.

Окно активатора и форма ввода пароля

Окно активатора и форма ввода пароля

Заглянув «под капот» этого «Активатора», мы можем сразу отметить интересный факт: приложение в папке Resources зачем-то хранит установочный пакет Python 3.9.6 и дополнительный Mach-O-файл с именем tool. Основной файл типа Fat Mach-O, носящий говорящее имя GUI, фактически реализует ту самую кнопку «PATСH», по нажатии которой происходят два события:

  • установочный пакет Python копируется в директорию /tmp/ с временными файлами;
  • исполняемый файл tool из папки с ресурсами запускается с правами администратора. Для этого «Активатор» использует уже устаревшую функцию AuthorizationExecuteWithPrivileges, вызывающую окно для ввода пароля администратора.

После запуска tool в первую очередь проверяет наличие в системе установленного Python3 и, если его нет, устанавливает из ранее скопированного в /tmp/ пакета. Далее происходит непосредственно «патчинг» скачанного приложения: tool сравнивает первые 16 байт модифицируемого исполняемого файла с последовательностью, зашитой в коде «Активатора», и убирает их, если они совпали:

Проверка первых 16 байт исполняемого файла

Проверка первых 16 байт исполняемого файла

Забавно, что после этого приложение становится рабочим и, более того, оно действительно оказывается «взломано». Дело в том, что злоумышленники использовали уже взломанные версии приложений, а чтобы вынудить пользователя запустить «Активатор», добавляли несколько байт в начало исполняемого файла, делая его таким образом нерабочим.

Этап 2. Загрузчик

После завершения «патчинга» выполняется основная вредоносная нагрузка, а именно: образец связывается с C2 и загружает зашифрованный скрипт. Чтобы получить адрес сервера, программа собирает URL из двух списков слов, зашитых в ее коде, добавляя в качестве домена третьего уровня случайную последовательность из 5 букв. Получив адрес, образец выполняет запрос к DNS-серверу в попытке получить TXT-запись этого домена. Это достаточно интересный и необычный способ связи с командным центром и сокрытия активности в трафике, практически полностью гарантирующий, что вредоносная нагрузка будет загружена, ведь сообщение возвращает DNS-сервер. TXT-записи могут содержать различную информацию о домене, необходимую приложению, поэтому сам по себе запрос на получение такой записи выглядит абсолютно нормальным.

Перебрав возможные комбинации зашитых в коде слов — для всех изученных образцов они одинаковы, — получаем, что из всех доменов второго уровня рабочим оказывается только один: imohub[.]net. Какой при этом используется домен третьего уровня, в данном случае не играет роли, главное — чтобы он присутствовал в запросе. Полученный ответ от DNS-сервера содержит три TXT-записи, которые программа впоследствии обрабатывает и собирает в полное сообщение. Каждая запись представляет собой закодированную в Base64 часть шифротекста, где первый байт содержит порядковый номер, который при сборке удаляется. Полученный шифротекст зашифрован алгоритмом AES в режиме CBC. Расшифрованное сообщение представляет собой следующий Python-скрипт:

Расшифрованный скрипт

Расшифрованный скрипт

Перед его запуском tool выполняет следующие действия:

  • Вычисляет хэш скрипта и проверяет, не был ли он ранее запущен. Для этого он ищет в переменных среды ключ lastExecutedScriptHash и, если он есть, сравнивает полученный хэш с данными, хранящимися по этому ключу. Если хэши совпали, то скрипт не запускается. Если они различаются, tool запускает скрипт и заменяет хэш в переменной. Если же ключа в переменных среды нет, tool создает его и сохраняет в нем хэш текущего скрипта.
  • Заменяет «_g_» в ссылке в коде скрипта на случайную последовательность из 64 символов, напоминающую хэш-сумму.
  • Записывает по пути /var/root/Library/Caches/<uuid>.py скрипт, который будет 10 раз в секунду завершать все процессы NotificationCenter, отвечающие за уведомления в системе:
    Завершение процессов NotificationCenter

    Завершение процессов NotificationCenter

  • Записывает по пути /Library/LaunchAgents/launched.<uuid>.plist два агента, отвечающих за автозапуск скриптов после перезапуска системы:
    Код агента автозапуска

    Код агента автозапуска

Как видно из кода расшифрованного скрипта, он раз в 30 секунд обращается по адресу apple-health[.]org и пытается загрузить и выполнить следующий скрипт. На его выполнение отводится 14 400 секунд, после чего процесс завершится и будет загружена новая версия скрипта.

Этап 3. Бэкдор

Изначально мы подумали, что скачиваемый Python-скрипт устарел, так как C2-сервер apple-health[.]org не отвечал на наши запросы. Однако спустя некоторое время нам все же удалось получить от него вредоносную нагрузку в виде еще одного Python-скрипта. Он, наконец, раскрывает цели, которые преследуют злоумышленники: основное его назначение — выполнение произвольных команд, получаемых с сервера. Судя по коду, отвечающему за обработку команд, они также будут представлять собой Python-скрипты, закодированные в Base64.

Участок кода, отвечающий за выполнение полученных команд

Участок кода, отвечающий за выполнение полученных команд

Помимо выполнения команд скрипт собирает и отправляет на сервер следующую информацию.

  • Версию операционной системы
  • Список директорий в /Users/
  • Пустое поле av, предположительно, будет заполняться информацией о наличии антивирусного ПО в следующих версиях
  • Список установленных приложений
  • Тип процессора
  • Внешний IP-адрес устройства
  • Пустое поле ver, которое, предположительно, будет использоваться для отправки информации о версии вредоносной нагрузки

Примечательно, что на момент исследования сервер не возвращал никаких команд, а через некоторое время вообще переставал отвечать. Поэтому мы скачали заново Python-скрипт третьего этапа и обнаружили, что в новой версии есть изменения. В частности, поменялись так называемые метаданные, которые хранятся в начале программы и в которых указаны IP-адрес и домен C2-сервера, GUID и версия программы. Судя по всему, эти данные обновляются в скрипте автоматически, как только IP-адрес сервера меняется (приблизительно раз в 10–20 минут). Однако были и изменения непосредственно в функциональной части кода, которые не могли возникнуть без участия человека, например:

Сравнение трех версий скрипта (слева направо: первая версия 18c564a5cc4b7414df8345a8bdce7418, и две последующие: f4282d7e32c7e8ab4e075c572ac43803, 352f0d288e612e4f66c50aaf9214a81d)

Сравнение трех версий скрипта (слева направо: первая версия 18c564a5cc4b7414df8345a8bdce7418, и две последующие: f4282d7e32c7e8ab4e075c572ac43803, 352f0d288e612e4f66c50aaf9214a81d)

Это говорит о том, что вредоносная кампания все еще находится на стадии разработки. Возможно, нам не удалось получить команды от сервера как раз по той причине, что злоумышленники банально не успели их написать.

Этап 4. Старый добрый криптостилер

Помимо вышеперечисленных возможностей в коде скрипта есть еще две интересные функции: check_exodus_and_hash() и check_btccore_and_hash():

Участок кода, отвечающий за загрузку зараженного кошелька Exodus

Участок кода, отвечающий за загрузку зараженного кошелька Exodus

В обеих функциях фигурирует домен apple-analyser[.]com, который служит хостом для дополнительных загрузок. Задачи функций похожи: проверить, есть ли на устройстве приложение соответствующего криптокошелька, и, если оно есть, заменить его на загружаемое с apple-analyser[.]com приложение. Помимо самого приложения там также хранится чистая версия фреймворка Electron для того, чтобы запускать «новую» версию Exodus, а также упомянутый в коде на скриншоте выше Exodus.scpt — скомпилированный сценарий AppleScript, который нужен только для того, чтобы при запуске Exodus.app выполнялась следующая Shell-команда:

Неужели злоумышленники настолько заботливы, что в качестве «компенсации» морального вреда решили помочь своим жертвам с обновлением приложений кошельков до актуальных версий? Увы, вера в лучшее была напрасной: оба кошелька оказались вредоносными.

В приложение Exodus злоумышленники вставили свое творчество в самое начало — в файл main/index.js, который первым запускается при старте приложения.

Фрагмент файла main/index.js с вредоносным дополнением

Фрагмент файла main/index.js с вредоносным дополнением

Из кода, представленного на скриншоте, мы понимаем, что где-то в приложении в канал с именем 334b4425988b47a5b67c92518f9815c6 должны передаваться данные, которые дальше будут отправлены на 22[.]imohub[.]workers[.]dev. Что ж, нам остается только найти место, где выполняется отправка данных в этот канал, и это (барабанная дробь!) файл wallet/index.js. Поскольку в коде файла отсутствуют переносы строк и отступы, приводим его к нормальному виду, а затем смотрим, что в нем происходит:

Содержимое файла wallet/index.js

Содержимое файла wallet/index.js

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

Bitcoin-Qt — это уже не JavaScript-файл, а полноценный Mach-O. Поискав в коде C2-сервер из приложения Exodus, мы довольно быстро приходим к выводу, что принцип работы Bitcoin-Qt аналогичен: приложение крадет пароль, используемый для разблокировки кошелька, а заодно и сам кошелек, его имя и баланс.

Фрагменты кода, отвечающего за отправку данных на C2

Фрагменты кода, отвечающего за отправку данных на C2

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

Заключение

Для злоумышленников «крякнутые» версии приложений — один из самых простых способов получить доступ к компьютеру жертвы. Для повышения привилегий им достаточно всего лишь запросить пароль, что при установке программы обычно не вызывает у пользователей подозрений. Стоит, однако, отметить, что авторы описанной вредоносной кампании проявили неординарную изобретательность, в частности, поместив Python-скрипт в TXT-запись домена на DNS-сервере. Этот скрипт в дальнейшем добавляется в список агентов для автозапуска и в бесконечном цикле загружает и выполняет полезную нагрузку следующего этапа, благодаря чему злоумышленники могут доставлять на зараженное устройство обновления. Финальная полезная нагрузка представляет собой бэкдор с возможностью выполнять любые скрипты с правами администратора, а также подменять установленные на устройстве приложения криптокошельков Exodus и Bitcoin на зараженные версии, которые воруют введенные секретные фразы в момент разблокировки кошелька.

Индикаторы компрометации

MD5

MD5 Тип Название/описание
c88c28149387ccf52ca3869442533fd9 Fat Mach-O GUI
a5924fff42d60a732853da167a743182 Fat Mach-O GUI
9c0e8d45cbf5cae428bef90b5824e5b1 Fat Mach-O GUI
a9231044dd45a85a0bf45e01584bf213 Fat Mach-O GUI
2ed32d3df8b4a2ef891b44a6397cf6ea Fat Mach-O GUI
7fd9a401fd0d7901cf4494333d1896cb Fat Mach-O GUI
e12566cd9d72a9b56d5e53f00b7d2d53 Fat Mach-O GUI
4c2ec35d13c5f44000caf658e40e444c Fat Mach-O GUI
4886a687ada61fc7f53b41f6020e76cc Fat Mach-O GUI
c7178d08c13f3e49a6ebefe23d1fedff Fat Mach-O GUI
cad3081fc6174ca4a4c18b8f73b3fe59 Fat Mach-O GUI
3a89719527d51e7c60854704e9f49a32 Fat Mach-O tool
5bab5ba8c509a9baa5db246d932a099f Fat Mach-O tool
948c1bdc9edf3e57758b677a0a449f34 Fat Mach-O tool
e64773b03ad1eae52180c2b58907f1f6 Fat Mach-O tool
3f89644dfc394e888a741f6c09638d98 Fat Mach-O tool
29a35e0e65bba727a97747acdf921c09 Fat Mach-O tool
3b357b8d65537d40e87599c5329d2a3d Fat Mach-O tool
adede572ad9599e331592103f9eea2a2 Fat Mach-O tool
a386380e03097055c24b0f35263d5492 Fat Mach-O tool
67e1f194c37968bb2edaf469bf40b837 Mach-O Bitcoin-Qt
005fb6dee90eeefa89d6400f7a06d058 JavaScript Main/index.js
ba41c9f6d89671b729eafbe6d5f1c85e JavaScript Wallet/index.js
95c86de53ad9ca116f8c6eb2e6a152f5 DMG Aiseesoft Blu-ray Player 6.6.38.dmg
be7e6e625d15d30ff47e34ebb1ee4511 DMG Bike 1.18.0.dmg
2ebfe93a39ce3fcecca883b5f182029e DMG Final Draft 12.0.10.dmg
e5f12e92b1fa956d02d35d6224abdbc8 DMG Keep It 2.3.7.dmg
3af3d6ba3c80b7bf5d67deddb2971c61 DMG OmniReader Pro 2.6.8.dmg
29b1ba90407a93400e062fb65dc9b667 DMG SimpleMind Pro 2.3.0.dmg
a33b6c5905cefced329fa89f5eebb481 DMG SyncBird Pro 4.0.8.dmg
71eefe83f836ebceadc9f68ff0e37d3b DMG xScope 4.7.0.dmg
d1177ed07dddb09415c175a205143eb6 DMG Swinsian 3.0.dmg
b2d519d13125c29832b132e927fd141b DMG Infuse Pro 7.6.6.dmg
609596d15e684f4a8ea80b7ee4b8c6a8 DMG Fix My iPhone 2.4.9.dmg
bbe4c19f3b675705073ba3e8a560b768 DMG Omni Toolbox 1.5.1.dmg
9124843fdbf27e7b31d2f883042021a9 Python script Второй этап
ff608ab027db4d1e076c1d8098e8dc8a Python script Второй этап (инструмент для отключения уведомлений)
f4282d7e32c7e8ab4e075c572ac43803 Python script Третий этап
09ab22fcf21385cc5702ec52ac4eca02 Python script Третий этап
352f0d288e612e4f66c50aaf9214a81d Python script Третий этап
948a90b43ade9dbc559fd27be404f9f0 Python script Третий этап
18c564a5cc4b7414df8345a8bdce7418 Python script Третий этап
3422f0cefa0c4612d18643bbf07a4a98 Zip Bitcoin-Qt
fb050f4c29a166480ff2f5a1fa8b9800 Zip Bitcoin-QtIntel
5abe156cb33b18a46c7279d9c52b1c64 Zip App.zip
38e4ef0d9221b25510cc50bcc8f4b4e8 AppleScript script Exodus.scpt

Адреса С2

imohub[.]net
22[.]imohub[.]workers[.]dev
apple-analyser[.]com
apple-health[.]org

Пиратка дороже золота: новый бэкдор для macOS крадет криптокошельки

Ваш e-mail не будет опубликован. Обязательные поля помечены *

 

Отчеты

CloudSorcerer: новая APT-угроза, нацеленная на российские государственные организации

«Лаборатория Касперского» обнаружила новую APT-угрозу CloudSorcerer, нацеленную на российские государственные организации и использующую облачные службы в качестве командных серверов аналогично APT CloudWizard.

StripedFly: двуликий и незаметный

Разбираем фреймворк StripedFly для целевых атак, использовавший собственную версию эксплойта EternalBlue и успешно прикрывавшийся майнером.

Подпишитесь на еженедельную рассылку

Самая актуальная аналитика – в вашем почтовом ящике