Наша команда аналитиков Threat Intelligence из PT Expert Security Center на протяжении полугода следит за активностью киберпреступников из TA505. Сфера интересов злоумышленников — финансовая, а цели расположены в десятках стран на разных континентах.
Чем известна группировка TA505
У этой группы атакующих богатая история: с 2014 года в их арсенале числятся банковский троян Dridex, ботнет Neutrino, а также целая серия шифровальщиков — Locky, Jaff, GlobeImposter и др.
Активность группировки фиксировалась по всему миру — от Северной Америки до Средней Азии. Заметим: мы фиксировали единичные случаи вредоносных рассылок группировки TA505 на территории России, однако есть все основания полагать, что целей на территории нашей страны у злоумышленников не было, а рассылки носили случайный характер.
Несмотря на преимущественно финансовую мотивацию группировки, среди ее целей в последние полгода встречались исследовательские институты, организации энергетической промышленности, здравоохранения, авиационные компании и даже государственный сектор.
Ниже пример фишингового письма, содержащего разработанный группировкой вредоносный софт и нацеленного, судя по адресу электронной почты, на министерство иностранных дел Великобритании.
С весны 2018 года группа использует Remote Access Tool FlawedAmmyy, а с конца года применяет новый бэкдор ServHelper. TA505 — одни из немногих, кто может похвастаться активной деятельностью на протяжении долгого времени. Кроме того, с каждой новой волной атак они привносят интересные изменения в свои инструменты.
Конечно, такая бурная деятельность не остается незамеченной: существует немало публикаций наших коллег из Proofpoint, Trend Micro, Yoroi и не только — о техниках и вредоносном ПО злоумышленников. Однако множество любопытных деталей остается без внимания:
- идентифицирующий группу PE-пакер;
- вариация бэкдора ServHelper, в которой сделан акцент не на собственную функциональность, а на уже готовую и известную реализацию NetsupportManager;
- сетевая инфраструктура: характерные регистраторы, хостеры, в том числе пересечения с инфраструктурой группировки Buhtrap;
- прочее ВПО группы, не описанное ранее.
Эта статья — первая в серии наших постов о группе TA505.
Часть первая. Встречают по одежке паковке
В середине июня 2019 года мы обратили внимание, что очередные загрузчики ВПО FlawedAmmy существенно отличаются от предыдущих версий: например, визуальное представление программного кода в шестнадцатеричном редакторе изменилось, и даже стало чем-то характерным для нескольких взятых образцов:
Беглый анализ кода показал, что перед нами ранее неизвестный упаковщик исполняемых файлов. Позднее выяснилось, что данным пакером накрывались не только вышеупомянутые загрузчики, но и прочие образцы ВПО группы, в том числе и полезная нагрузка. Тогда мы решили детально изучить логику распаковки, чтобы автоматически извлекать целевой объект.
Слой 1. Крученый XOR
Ключевой части распаковщика предшествует обилие бесполезных инструкций. Вирусописатели часто прибегают к такой технике, чтобы сбить с толку эмуляторы антивирусных продуктов. Все интересное начинается с выделением памяти под буфер размером 0xD20 с помощью WinAPI-функции VirtualAllocEx. Память выделяется с правами PAGE_EXECUTE_READWRITE, что позволяет записать и выполнить код.
В секции данных исследуемого файла содержится массив с данными, который проходит процедуру расшифровки, а результат записывается в выделенную память. Алгоритм расшифровки:
- интерпретировать 4 байта как целочисленное,
- вычесть порядковый номер,
- выполнить операцию XOR с заданной константой,
- выполнить циклический побитовый сдвиг влево на 7 единиц,
- снова выполнить операцию XOR с заданной константой.
Обозначим данный алгоритм аббревиатурой SUB-XOR-ROL7-XOR, чтобы сослаться на него позднее. После процедуры расшифровки происходит последовательная инициализация переменных. Это можно представить как заполнение структуры на языке C в следующем формате:
struct ZOZ { HMODULE hkernel32; void *aEncodedBlob; unsigned int nEncodedBlobSize; unsigned int nBlobMagic; unsigned int nBlobSize; };
где:
- hkernel32 — дескриптор библиотеки kernel32.dll;
- aEncodedBlob — указатель закодированного блока данных, именно его мы упомянули, когда ссылались на визуальное сходство образцов выше;
- nEncodedBlobSize — 4-байтовый размер закодированного блока данных;
- nBlobMagic — 4-байтовая константа впереди блока с данными, к которой мы вернемся позже;
- nBlobSize — 4-байтовый размер декодированного блока данных;
Мы назвали структуру ZOZ (это «505» на leetspeak).
В результате описанных действий выполнение кода будет перенаправлено на расшифрованный буфер (теперь нет сомнений, что расшифрованные данные — это исполняемый код), а указатель заполненной структуры будет передан как параметр функции:
Слой 2. Чем меньше, тем лучше
После передачи управления на расшифрованный кусок кода первым делом происходит определение адресов WinAPI-функций GetProcAddress, VirtualQuery, VirtualAlloc, VirtualProtect, VirtualFree и LoadLibraryA. Этот перечень часто встречается в работе шелл-кодов: ведь им необходимо подготовить и правильно заполнить память для последующего запуска полезной нагрузки.
По завершении предварительных процедур переданный закодированный блок данных усекается: из каждых пяти байтов первые два отбрасываются, а оставшиеся три сохраняются:
Затем выполняется процедуры расшифровки, которую мы назвали SUB-XOR-ROL7-XOR. В этом случае в качестве константы для операции XOR используется другое значение nBlobMagic, которое и было передано в структуре ZOZ.
После этого полученный массив передается в функцию, в которой происходит серия более сложных преобразований. По характерным значениям констант несложно установить, что это реализация популярного PE-упаковщика FSG (Fast Small Good). Любопытно, что оригинальная версия пакера FSG сжимает PE по секциям, а реализация алгоритма в нашем случае работает с PE целиком, «как есть».
На этом этапе в памяти находится готовый для дальнейшего анализа распакованный целевой PE-файл. Оставшаяся часть шелл-кода перезапишет оригинальный PE в адресном пространстве распакованной версией и корректно его запустит. Интересно отметить, что в процессе корректировки точки входа загруженного модуля происходят манипуляции со структурами в PEB. Почему злоумышленники решили пробрасывать дескриптор kernel32 из логики первого слоя вместо его получения с помощью тех же структур PEB — неизвестно.
Заключение
Итак, алгоритм распаковки полезной нагрузки:
- декодирование шелл-кода с помощью SUB-XOR-ROL7-XOR,
- заполнение структуры ZOZ и вызов шелл-кода,
- редукция полезной нагрузки «пять к трем»,
- декодирование полезной нагрузки с помощью SUB-XOR-ROL7-XOR,
- декомпрессия упаковщиком FSG.
В процессе эволюции ВПО логика менялась: например, количество циклических сдвигов алгоритма SUB-XOR-ROL7-XOR (в рассмотренном случае — семь) изменялось на пять, девять, выпускалась версия упаковщика под платформу x64 и т. д. Уникальный пакер киберпреступной группировки — отличный эпиграф к будущим повествованиям об инструментах и особенностях TA505.
В следующих статьях мы расскажем о том, как развивались и изменялись инструменты TA505 в ходе последних атак, о взаимодействии участников с другими кибергруппировками, изучим не рассмотренные ранее образцы ВПО.
Авторы: Алексей Вишняков и Станислав Раковский, Positive Technologies
IOCs
b635c11efdf4dc2119fa002f73a9df7b
— упакованный загрузчик FlawedAmmyy
71b183a44f755ca170fc2e29b05b64d5
— распакованный загрузчик FlawedAmmyy