Недавно специалисты PT ESC обнаружили документ формата Publisher с названием «Приглашение 29–30 ноября 2018.pub» (1edd5b6a02ec82cec381c1a1ec74a67e). В этом материале мы расскажем, как обычный с виду документ превращается в троян, позволяющий злоумышленнику захватывать изображение с веб-камер, записывать звук по команде или при обнаружении окна Skype, запускать PowerShell-скрипты, делать скриншоты экрана, копировать файлы с медиаустройств.

Итак, при открытии документа появляется окно с размытым документом-заглушкой и просьбой включить скрипт Microsoft Publisher.



После того как пользователь его включит, исполнится встроенный в документ сценарий на JavaScript. Выглядит он так:



Результатом работы скрипта будет раскодирование двух файлов, PDF и EXE, из Base64. Оба файла будут записаны по адресу C:\Users\{Username}\AppData\Roaming\DBFUpdate. Соответственно, оба файла исполнятся, и пользователь увидит на экране документа такую заглушку:



Treasure Hunter RAT


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

Особенности кода:

  1. Целиком написан на С++ с большим количеством STL-конструкций, которые используются внутри.
  2. Применение библиотеки boost, в частности JSON и Archive.
  3. Отладочные функции (подробнее в секции, посвященной stager).

Основной троян


Основной троян закрепляется на машине жертвы и представляет из себя платформу, на которую загружаются из С2 вредоносные модули.

Сначала stager инициализирует рабочую директорию, в которой впоследствии будут храниться собранная модулями информация, утилиты, необходимые для работы модулей, и т. п.



Ниже — инициализация путей для создания рабочей директории:



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

Троян интересуется такими данными:

  • идентификатором версии ОС, на которой запущен основной троян;
  • установленным по умолчанию языком интерфейса;
  • старшим номером версии Service Pack ОС;
  • именем компьютера и идентификатором машины (подробнее о получении идентификатора машины — в разделе, посвященном сетевому протоколу).

Так происходит сбор информации о зараженной машине:



Далее основной троян закрепляется на зараженной машине через модификацию значения в реестре по адресу HKCU\Environment\UserInitMprLogonScript. Здесь прописывается имя исполняемого файла, которое было выделено при инициализации рабочей директории, в этом случае оно равно «DCTHOST.exe». Данный способ описан в блоге Hexacorn, a также использовался APT28 и группой Cobalt в их ComDLLDroper.



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

После того как основной троян инициализирован, осуществляется подготовка к приему команд. В cписок запущенных модулей добавляется модуль Core, коим и является основной троян. Далее запускается команда из модуля Core c идентификатором 0. Реализация данной команды в основном модуле отсутствует, вместо нее просто заглушка. Конструктор объекта модуля Core представлен ниже.



В конце происходит запуск двух потоков. Один из потоков запускает таймер, который просыпается по умолчанию каждую секунду и пытается запросить команду у С2.



Второй поток осуществляет загрузку дополнительных библиотек и стандартных модулей. Библиотеки, как и модули, имеют идентификатор, но в отличие от модулей идентификаторы библиотек отрицательные, начинаются с –1, растут в сторону меньших чисел. Ниже — список библиотек, загружаемых с С2.



Отладочные функции основного трояна


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



Сетевой протокол


Обмен между ПО и С2 происходит с помощью самописного бинарного протокола. Каждое сообщение описывается с помощью BinPackage (название взято из RTTI). Каждый BinPackage по своей сути является оберткой над std::vector, который хранит в себе набор PackageRecord (название выдумано). PackageRecord является минимальной единицей для хранения данных.

struct PackageRecord
{
_DWORD dataId; 
_DWORD datatype; 
_DWORD szData;
  char[] data;
};

Подробнее о полях этой структуры:

  • dataId — указывает на тип записи. Либо запись является идентификатором модуля, либо идентификатором команды, либо полезной нагрузкой.
  • szData — размер данных, хранимых в записи.
  • datatype — тип данных.

Всего было зафиксировано использование трех типов данных:
  • Значение «0» — означает, что данные, хранимые в записи, необходимо интерпретировать как DWORD.
  • Значение «1» — данные, хранимые в записи, необходимо интерпретировать как ASCIIZ-строку.
  • Значение «2» — данные, хранимые в записи, необходимо интерпретировать как зашифрованные данные/raw buffer.


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



Перед отправкой все записи, хранящиеся в BinPackage, собираются последовательно в единый буфер и подвергаются шифрованию. Для шифрования используется библиотека WinAES, а конкретно AES-128-CBC.

С помощью CryptoAPI Windows генерируются два псевдослучайных массива размером 16 байт. Один для IV, другой для ключа. Выполняется шифрование, и зашифрованные данные складываются обратно в BinPackage, который содержит зашифрованный пакет и состоит из трех записей:

  • запись с ID 0x777 — содержит в себе ключ, использованный для шифрования;
  • запись с ID 0x555 — содержит в себе IV, использованный для шифрования;
  • запись с ID 0x999 — содержит в себе зашифрованные данные (в общем виде запись с таким ID обозначает полезную нагрузку и используется не только для хранения зашифрованных данных).

После окончания процесса шифрования сформированный BinPackage опять собирается в единый буфер и отправляется через HTTP POST-запрос на управляющий сервер 151.80.237.222.



Ниже — пример пакета, содержащего информацию о машине:



А это пример зашифрованного пакета с информацией о системе:



Модули


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

Пример пакета, запрашивающего модуль:



Ответ на запрос модуля:



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



Далее названия модулей даны в том виде, в котором они присутствуют в RTTI как имена классов.

Модуль CCore


Данный модуль представляет базовую функциональность и встроен непосредственно в основной троян. Его конструктор можно увидеть в таблице ниже:
ID модуля ID команды Описание
0 0 В основном трояне вместо команды заглушка, и точное ее назначение установить не удалось
1 Изменить конфигурацию модуля
2 Запросить информацию о компьютере
3 Скачать утилиту с контрольного сервера
4 Запросить листинг директории, содержащей утилиты
5 Загрузить модуль и выполнить его

Модуль CShell


Данный модуль предоставляет удаленный шелл на зараженную машину. При инициализации модуля создается процесс cmd.exe, к которому прикрепляются два пайпа: один для стандартного ввода и один для стандартного вывода, через которые осуществляются прием и передача команд от контрольного сервера и обратно. Также в этот момент запускается поток, который автоматически забирает весь вывод и отправляет его на контрольный сервер. На рисунке — инициализация модуля СShell.


ID модуля ID команды Описание
2 0 Послать команду в шелл
1 Вывести файл. Читается файл, путь до которого передается с контрольного сервера, и содержимое этого файла загружается на контрольный сервер
2 Получить список всех дисков, существующих в системе. Данные отправляются на контрольный сервер в формате JSON
3 Загрузить файл с контрольного сервера. Путь, куда сохранить файл, и данные получаются с контрольного сервера

Модуль CFileSystemBrowser


Это пассивный модуль, который по запросу позволяет получать информацию о структуре файловой системы. Так происходит инициализация модуля CFileSystemBrowser:


ID модуля ID команды Описание
3 0 Получить список всех дисков, существующих в системе. Данные отправляются на С2 в формате JSON
1 Получить листинг директории. Листинг формируется в формате JSON
2 Вывести файл. Читается файл, путь до которого передается с С2, и содержимое этого файла загружается на С2
3 Удалить файл. Путь до файла передается с С2

Модуль CScreenShot


Данный модуль позволяет создавать скриншоты экрана или захватывать изображение с веб-камеры. Может это делать как по запросу, так и с определенным периодом по таймеру.

ID модуля ID команды Описание
4 0 Сделать скриншот и отправить его на контрольный сервер
1 Запустить таймер, после срабатывания которого осуществляется снятие скриншота с экрана машины. Полученные скриншоты упаковываются в BinPackage и сохраняются в папку logs. Имена для файлов генерируются с помощью API GetTempFileName с префиксом «MS_».
2 Получить видео устройств, доступных на зараженной машине
3 Захватить кадр с веб-камеры и отправить его на контрольный сервер

Модуль CSender


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



Модуль CKeylogger


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



Модуль CDictaphone


Данный модуль осуществляет запись звука по команде или при обнаружении окна Skype. При запуске запускает поток, который перечисляет все окна и их дочерние окна в системе и ищет среди классов окно, имя класса у которого равно TLiveConversation или TCallMonitorControl. Если такое окно было найдено, начинается запись. Ниже — инициализация модуля CDictaphone:



И поиск окна Skype



Запись осуществляется через MCI путем отправки специальных команд. Так выглядит цикл записи модуля CDictaphone:



После закрытия окна или поступления команды на завершение записи полученные данные сохраняются во временную папку, после чего кодируются MP3-кодировщиком lame (он считается утилитой и должен быть уже загружен, заполучить его с контрольного сервера не удалось). Закодированный файл сохраняется в папку logs. Генерация имени папки аналогична генерации имен для скриншотов.
ID модуля ID команды Описание
7 0 Начать запись и завершить ее по прошествии 15 минут
1 Остановить запись
2 Проверить статус: ведется ли сейчас запись

Модуль CProcessesManager


Это пассивный модуль, по запросу способный вернуть список процессов или завершить по переданному ему PID.


ID модуля ID команды Описание
8 0 Возвращает список процессов: их имена, PID и имя пользователя который является владельцем процесса.
1 Завершение процесса по PID

Модуль CDownloader


Модуль предназначен для загрузки больших файлов на контрольный сервер. Осуществляет передачу данных чанками, размер которых устанавливается его конфигурацией. Модуль читает данные из файла, путь до которого он получает с контрольного сервера, а чанки упаковывает в BinPackage. К каждому BinPackage, содержащему чанк, добавляется запись с идентификатором 0x888, включающая путь до файла. После передачи каждого чанка осуществляется sleep на 5 секунд.

ID модуля ID команды Описание
9 0 Заглушка, точное значение установить не удалось
1 Осуществляет передачу большого объема данных (0x500000 байт), после чего замеряет время, потраченное на передачу, и отправляет это значение на С2
2 Осуществляет загрузку файла с машины

Модуль CPS


Данный модуль позволяет запускать PowerShell-скрипты.


ID модуля ID команды Описание
10 0 Получает с С2 PowerShell-скрипт и выполняет его

Модуль CDeviceMonitor


Пассивный модуль, который осуществляет мониторинг подключаемых медиаустройств и копирует с них файлы. Для обнаружения подключения устройств использует широковещательные сообщения WM_DEVICECHANGE. После подключения устройства на контрольный сервер отправляется информация о том, когда было подключено устройство, его метка тома и путь до устройства. Код, используемый для получения пути до устройства, очень похож на этот. Все файлы копируются в папку logs. Имена генерируются так же, как для скриншотов. Отдельно создается файл fsIndex.dat, в котором находится сериализованный с помощью boost::archive словарь. Этот словарь хранит оригинальные пути до файлов, которые были скопированы, и их MD5-хеши. Ниже — получение DevicePath:



В качестве эпилога несколько рекомендаций:

  • Не надо открывать вложения в письмах от неизвестных адресатов и тем более включать скрипт Microsoft Publisher.
  • Не менее опасно кликать по ссылкам в письмах неизвестных отправителей. На сайте, куда вы перейдете, может размещаться вредоносное ПО, которое автоматически загрузится на ваш ПК.
  • Необходимо регулярно обновлять ПО, особенно Microsoft Windows и Microsoft Office, что позволит закрыть доступ для широкого спектра вредоносного ПО.

Комментарии (11)


  1. Mur81
    05.12.2018 16:47

    Всё это конечно интересно, но если мы говорим о корпоративном секторе, то там этого не должно было случится как минимум потому что:

    при открытии документа появляется окно с размытым документом-заглушкой и просьбой включить скрипт Microsoft Publisher.

    Исполнение скриптов в MS Office должно быть отключено через GPO. И должна быть заблокирована возможность включить это.
    Результатом работы скрипта будет раскодирование двух файлов, PDF и EXE, из Base64. Оба файла будут записаны по адресу C:\Users\{Username}\AppData\Roaming\DBFUpdate. Соответственно, оба файла исполнятся

    Исполнение файлов непонятно откуда (тем более из профиля) должно быть заблокировано с помощью SRP или AppLocker.


    1. ianzag
      05.12.2018 17:06
      -1

      Далеко не все корпорации следуют указанным правилам. А в некоторых случаях это слабо применимо. Например если жертва это девелупер. Обрежь ему права по самые помидоры — он потом как без рук. А и на старуху бывает проруха.


      1. Mur81
        05.12.2018 17:09

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


        1. teecat
          06.12.2018 11:03

          Угу. Постоянно когда рассказываю почему антивирус будет пропускать — это просто разрыв шаблонов. А если еще и спрашиваешь — а есть ли у вас защита от неизвестных вредоносных программ…
          Всегда поражает, что с одной стороны — «ну да, обновления же запаздывают», а с другой «антивирус должен ловить 100% на входе, он же в тестах победитель». Оба эти знания уживаются одновременно в голове, но пересекаются очень редко


      1. dimaaan
        05.12.2018 18:22

        Например если жертва это девелупер

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


        1. roscomtheend
          06.12.2018 12:52

          Сначала нанимают «девелуперов», а потом удивляются что те открывают всё подряд. Права, наверное, «обменистратор» назначает.


  1. namikiri
    05.12.2018 17:41

    Прошу прощения, но код текстом это теперь не модно?


    1. sbh
      06.12.2018 07:09

      Можете пояснить, для чего вам необходим код текстом?


      1. namikiri
        06.12.2018 11:18

        Хотя-бы для эстетического удовлетворения, чтобы весь код выглядел однородно. Если бы у меня и впрямь был злой умысел, я бы в любом случае либо написал что-то своё, либо не поленился бы перепечатать со скриншотов.


  1. DemonSinusa
    06.12.2018 13:59

    Вахахаха! Браво!
    Только яб к сбору инфы о машине добавил dlload правильного кернела, далее поиск функций без лишнего импортирования их- по адресам попрет(ни один анвирь не просечет такой активности) далее через импортированые кернелфункшонс грузим длл винсоцка, и через простую обертку на PHP удаленном сервере(грузим методом html get|post иликактам чтоб лишних либ не таскать) тащим риал троян, который ранится сервисом от имени пользователя и тем же журбеллом работает(неявно) с сетью, которого уже ждет полезный сервер на хорошей машине, для полного доступа к удаленному ПК_или_еще_чего_там.
    Но всеравно БраавО за «Если вы видите плохо, нажмие- будет хорошо!»


    1. lostpassword
      06.12.2018 21:54
      +1

      Но всеравно БраавО за «Если вы видите плохо, нажмие- будет хорошо!»
      Да, кажется смешным… Но я как-то раз видел документ, который настолько качественно был сделан, с настолько безупречным призывом нажать на кнопочку, что я даже не сразу подумал, что это вредонос. Прямо глазам не поверил, когда зашёл в макросы. Просто шедевральное исполнение (значительно лучше, чем в скриншоте из статьи).
      Хотя так сильно, конечно, мало кто заморачивается. Зачем стараться, когда можно просто кинуть ста пользователям что-то более простое — ведь кто-то всё равно кликнет.