Месяцем ранее мы обнаружили распространяющиеся на сайтах с пиратским ПО приложения, зараженные прокси-троянцем. Тогда злоумышленники собирали уже взломанные приложения в 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 байт модифицируемого исполняемого файла с последовательностью, зашитой в коде «Активатора», и убирает их, если они совпали:
Забавно, что после этого приложение становится рабочим и, более того, оно действительно оказывается «взломано». Дело в том, что злоумышленники использовали уже взломанные версии приложений, а чтобы вынудить пользователя запустить «Активатор», добавляли несколько байт в начало исполняемого файла, делая его таким образом нерабочим.
Этап 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, отвечающие за уведомления в системе:
- Записывает по пути /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 минут). Однако были и изменения непосредственно в функциональной части кода, которые не могли возникнуть без участия человека, например:
Это говорит о том, что вредоносная кампания все еще находится на стадии разработки. Возможно, нам не удалось получить команды от сервера как раз по той причине, что злоумышленники банально не успели их написать.
Этап 4. Старый добрый криптостилер
Помимо вышеперечисленных возможностей в коде скрипта есть еще две интересные функции: check_exodus_and_hash() и check_btccore_and_hash():
В обеих функциях фигурирует домен apple-analyser[.]com, который служит хостом для дополнительных загрузок. Задачи функций похожи: проверить, есть ли на устройстве приложение соответствующего криптокошелька, и, если оно есть, заменить его на загружаемое с apple-analyser[.]com приложение. Помимо самого приложения там также хранится чистая версия фреймворка Electron для того, чтобы запускать «новую» версию Exodus, а также упомянутый в коде на скриншоте выше Exodus.scpt — скомпилированный сценарий AppleScript, который нужен только для того, чтобы при запуске Exodus.app выполнялась следующая Shell-команда:
1 2 |
do shell script "~/electron/Electron.app/Contents/MacOS/Electron ~/exodus" quit |
Неужели злоумышленники настолько заботливы, что в качестве «компенсации» морального вреда решили помочь своим жертвам с обновлением приложений кошельков до актуальных версий? Увы, вера в лучшее была напрасной: оба кошелька оказались вредоносными.
В приложение Exodus злоумышленники вставили свое творчество в самое начало — в файл main/index.js, который первым запускается при старте приложения.
Из кода, представленного на скриншоте, мы понимаем, что где-то в приложении в канал с именем 334b4425988b47a5b67c92518f9815c6 должны передаваться данные, которые дальше будут отправлены на 22[.]imohub[.]workers[.]dev. Что ж, нам остается только найти место, где выполняется отправка данных в этот канал, и это (барабанная дробь!) файл wallet/index.js. Поскольку в коде файла отсутствуют переносы строк и отступы, приводим его к нормальному виду, а затем смотрим, что в нем происходит:
В обработчик, отвечающий за разблокировку кошелька, злоумышленники добавили вызов функции, которая просто отправляет введенную seed-фразу в канал, из которого она затем передается на C2-сервер. Больше никаких нововведений.
Bitcoin-Qt — это уже не JavaScript-файл, а полноценный Mach-O. Поискав в коде C2-сервер из приложения Exodus, мы довольно быстро приходим к выводу, что принцип работы Bitcoin-Qt аналогичен: приложение крадет пароль, используемый для разблокировки кошелька, а заодно и сам кошелек, его имя и баланс.
Таким образом, даже не получая команд от управляющего сервера, программа все равно может нанести существенный вред пользователю, воруя его криптокошельки.
Заключение
Для злоумышленников «крякнутые» версии приложений — один из самых простых способов получить доступ к компьютеру жертвы. Для повышения привилегий им достаточно всего лишь запросить пароль, что при установке программы обычно не вызывает у пользователей подозрений. Стоит, однако, отметить, что авторы описанной вредоносной кампании проявили неординарную изобретательность, в частности, поместив Python-скрипт в TXT-запись домена на DNS-сервере. Этот скрипт в дальнейшем добавляется в список агентов для автозапуска и в бесконечном цикле загружает и выполняет полезную нагрузку следующего этапа, благодаря чему злоумышленники могут доставлять на зараженное устройство обновления. Финальная полезная нагрузка представляет собой бэкдор с возможностью выполнять любые скрипты с правами администратора, а также подменять установленные на устройстве приложения криптокошельков Exodus и Bitcoin на зараженные версии, которые воруют введенные секретные фразы в момент разблокировки кошелька.
Индикаторы компрометации
MD5
Адреса С2
imohub[.]net
22[.]imohub[.]workers[.]dev
apple-analyser[.]com
apple-health[.]org
Пиратка дороже золота: новый бэкдор для macOS крадет криптокошельки