Анализ упакованного образца Agent Tesla

28.05.2021
by VirLab team

Для анализа был предоставлен следующий файл:

  • OUTSTANDING STATEMENT.xlz.exe

A24BF02CE43A846463532E46211962EC7E883E682ABBDE61F922FCD46FC301BC

Общее описание

В декабре 2020 года вредоносное программное обеспечение было направлено на корпоративную почту АО «Центр развития трудовых ресурсов», которая является нашим клиентом и использует систему tLab. Данное вредоносное ПО не обнаруживалось антивирусным программным обеспечением на статическом, сигнатурном уровне, однако наша система tLab обнаружила данную угрозу на поведенческом и эвристическом уровнях.

По результатам первичной оценки, в рамках технической поддержки системы tLab, данный образец был предоставлен нам для глубокого ручного анализа (reverse engineering) в недрах нашей вирусной лаборатории.

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

Позже данный факт был опубликован в АО «Центр развития трудовых ресурсов»

Мы провели динамический и статический анализ данного образца в системе tLab. Анализ показал, что образец является шпионским ПО и отвечает за сбор конфиденциальных данных пользователя (жертвы), таких как: аутентификационные данные веб ресурсов (браузера), vpn, ftp и email клиентов. Исходя из характера данной атаки (не массовость), ее можно отнести к целевой.

В ходе ручного анализа мы также нашли много схожих характеристик с вредоносным ПО AgentTesla.

Agent Tesla — это вредоносное ПО, используемое для шпионажа. Agent Tesla был известен с 2014 года и в последние два три года наблюдается рост количества заражений. Обычно распространяется с помощью фишинговых писем.

Общая схема работы образца OUTSTANDING STATEMENT.xlz.exe

На первой стадии, исследуемый образец распаковывает ресурс под именем dx, который является url-encoded base64 строкой. В результате получается PE файл.

Во второй стадии, библиотека использует второй ресурс под именем hLuPu.png, преобразовывает его в массив байт. Далее выполняется операция xor с заранее известным ключом и в результате получается gzip архив, который содержит вредоносную нагрузку.

На третьей стадии происходит внедрение вредоносного кода в целевой процесс.

Анализ

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

Образец содержит несколько визуальных форм, с помощью которых злоумышленники маскировали наличие вредоносного функционала

При запуске программы, в методе Main(), создается форма StudentScores

Управление передается на функцию инициализации формы

Далее вызывается функция wx() c основным вредоносным функционалом

Функция wx() раскодирует файл с именем dx из ресурсов и выполняет метод Buta.

Всего, в ресурсах вредоносного ПО находится три файла

dx - это URL-encoded строка в формате Base 64

Остальные два файла имеют расширение png и содержат закодированную информацию. Файл с именем q

Файл с именем hLuPu

Данный способ кодирования информации в графических изображениях называется - стеганография. С помощью алгоритма в коде вредоносного ПО мы раскодировали файл dx. В результате, он представляет из себя PE файл.
Быстро определить формат файла можно по первым нескольким байтам, в нашем случае байты 4D 5A сигнализирует о том, что файл имеет формат PE

Данный PE файл является динамической библиотекой написанной на C#. Библиотека обфусцирована с помощью Deep Sea 4.1. В ней мы находим вызываемый метод Buta

В метод Buta передается объект, в качестве аргумента

SoapDate это класс, с двумя строками, одна из которых совпадает с именем png файла в ресурсах первого файла

Код метода Buta

Алгоритм работы метода Buta:

  • В начале выполняется sleep на 41.5 секунд
  • Ресурс hLuPu превращается в Bitmap объект

  • Bitmap декодируется в массив байтов. Данный способ декодирования полезной нагрузки описан в статье Commodity .NET Packers use Embedded Images to Hide Payloads следуя которой мы можем однозначно идентифицировать, что данный образец использует упаковщик “Cyax”. Суть алгоритма в использовании RGB модели PNG изображения и формирование соответствующего ей байтового массива.

  • Получившийся в результате массив байтов декодируется функцией xor, ключом wNspdaa

  • Получившийся архив распаковывается алгоритмом gzip и в результате получается конечная полезная нагрузка

  • В полезной нагрузке запускается функция, которая является входной точкой

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

using System;
using System.Drawing;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Text;

namespace Outstanding
{
   
class Program
   {
       
static void Main(string[] args)
       {
           Bitmap bitmap = (Bitmap) Bitmap.FromFile(@
"hLuPu.png");
           byte[] bitmap_arr = smethod_0(bitmap);
           byte[] bitmap_decoded = decode(bitmap_arr,
"wNspdaa");
           byte[] payload = getPayload(bitmap_decoded);
           File.WriteAllBytes(
"payload", bitmap_decoded);
       }

       
public static byte[] getPayload(byte[] bitmap_decoded)
       {
           byte[] result;
           
using (MemoryStream memoryStream = new MemoryStream(bitmap_decoded))
           {
               byte[]
array = new byte[4];
               memoryStream.Read(
array, 0, 4);
               
int num = BitConverter.ToInt32(array, 0);
               
using (GZipStream gzipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
               {
                   byte[] array2 =
new byte[num];
                   gzipStream.Read(array2,
0, num);
                   result = array2;
               }
           }
           
return result;
       }

       
private static byte[] smethod_0(Bitmap bitmap_0)
       {
           List<byte>
list = new List<byte>();
           checked
           {
               
int num = bitmap_0.Width - 1;
               
for (int i = 0; i <= num; i++)
               {
                   
int num2 = bitmap_0.Height - 1;
                   
for (int j = 0; j <= num2; j++)
                   {
                       Color pixel = bitmap_0.GetPixel(i, j);
                       
if (pixel != Color.FromArgb(0, 0, 0, 0))
                       {
                           
list.InsertRange(list.Count, new byte[]
                           {
                               pixel.R,
                               pixel.G,
                               pixel.B
                           });
                       }
                   }
               }
               
return (byte[])list.ToArray();
           }
       }

       
public static byte[] decode(byte[] bitmap_arr, string key)
       {
           byte[] bytes = Encoding.ASCII.GetBytes(key);
           
int num = (int)(bitmap_arr[bitmap_arr.Length - 1] ^ 112);
           byte[]
array = new byte[bitmap_arr.Length + 1];
           
int num2 = 0;
           
for (int i = 0; i <= bitmap_arr.Length - 1; i++)
           {
               
array[i] = (byte)((int)bitmap_arr[i] ^ num ^ (int)bytes[num2]);
               
if (num2 == key.Length - 1)
               {
                   num2 =
0;
               }
               
else
               {
                   num2++;
               }
           }
           Array.Resize<byte>(ref
array, bitmap_arr.Length - 1);
           
return array;
       }
   }
}


SHA256 полезной нагрузки:

DE87F049D9DC99A60D457FDAC61C332BB88F5BCFF042AA395F55BCEE4A3C17E8

Полезная нагрузка также написана на C# и содержит набор функция для внедрения кода в процесс. Для внедрения кода используется техника Process Hollowing.

Первым шагом является создание процесса RegSvcs.exe, с параметром CREATE_SUSPENDED (константа 0x00000004)

Далее, с помощью функции GetThreadContext и взятия 41 байта из результата, идет получение структуры PEB целевого процесса, которая содержит информацию о процессе.

После получения структуры PEB, происходит чтение базового адреса (ImageBaseAddress) процесса RegSvcs.exe

Перед выделением памяти в процессе, он подготавливается функцией NtUnmapViewOfSection

Функция VirtualAllocEx выделяет память для вредоносного кода внутри процесса RegSvcs.exe

Запись вредоносного кода в процесс функцией WriteProcessMemory

Запуск процесса RegSvcs.exe функцией ResumeThread

Сохранив массив байтов, который используется в качестве аргумента WriteProcessMemory, мы получим еще один PE. Функционал данного образца схож с функционалом файла описанного в статье New Agent Tesla Variant Spreading by Phishing и мы предполагаем, что он тоже является вариантом AgentTesla. Образец является стилером, написанном на C#.

SHA256 образца:

E701BED0853C2F782B0710F7895D7DCE22A58DBB0042DB56A7D9509929C8F05E

Выполнение образца AgentTesla начинается с функции D(), которая проверяет запущен ли уже стилер, чтобы предотвратить повторный запуск

Далее мусорный код, в котором несколько раз выполняется Sleep. Количество раз зависит от переданного заранее предопределенного параметра в функцию A.b.A(). Данная функция в коде встречается повсеместно

Получение имени пользователя (в данном случае имя пользователя - john)

Образец AgentTesla не использует методы закрепления в системе. Все собранные данные отправляются на сервер злоумышленников. Данное вредоносное ПО также следит за изменением буфера обмена

Получение текущего ip адреса

Основной функционал представлен в виде подобных функций

Все имена закодированы и после раскодирования мы можем увидеть пути к данным различных браузеров

Алгоритм кодирования строк находится в классе DF7A7911_002D5159_002D4174_002D9C8D_002D344C41F0E4CF. В нем определен массив байт из 12005 элементов

В конструкторе класса происходит декодирование массива, через операцию xor с его порядковым номером и ключом 0xAA

Основная функция в этом классе возвращает строку, которая конструируется переданными аргументами

Настоящие строковые значения получаются путём вызова множества схожих функций

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

В итоге мы получим файл со всеми декодированными строками

Еще один фрагмент кода по декодированию строк связанных с FTP клиентами

В системе tLab мы также можем увидеть установленное интернет соединение

T&T security предоставляет своим клиентам yara правила для каждого вредоносного файла. Yara правило для образца A24BF02CE43A846463532E46211962EC7E883E682ABBDE61F922FCD46FC301BC:

Идентификация по Yara в системе tLab

Yara правило для образца C88A66CBF00B12C88E2B970B8BC220E970E8465E56098CED24E97D42BE901B94:

Идентификация по Yara в системе tLab

Yara правило для образца DE87F049D9DC99A60D457FDAC61C332BB88F5BCFF042AA395F55BCEE4A3C17E8:

Идентификация по Yara в системе tLab

Yara правило для образца E701BED0853C2F782B0710F7895D7DCE22A58DBB0042DB56A7D9509929C8F05E:

Идентификация по Yara в системе tLab

Был обнаружен еще один образец похожий на ранее проанализированный. Данный образец использует встроенный ресурс под именем Wids, который также является картинкой с закодированными данными

Ресурс попиксельно раскодируется и превращается в байтовый массив:

В результате получается PE файл, в котором вызывается определенный метод, куда передаются ключи для дальнейшего декодирования:

Метод “aI” предназначен для декодирования следующей вредоносной нагрузки:

Алгоритм работы метода “aI”:

  • Главный поток засыпает от 65 до 78 секунд

  • Декодируется строка "436F6D70617469626C654672616D65776F726B734D65746164617461456E7472794669656C644964" следующим алгоритмом

    В результате получается строка “CompatibleFrameworksMetadataEntryFieldId”.


  • Ресурс под этим именем превращается в Bitmap объект


  • Происходит декодирование ресурса

  • В результате получается еще один PE файл

Данный PE файл имеет строку с параметрами

В зависимости от первого параметра, происходит внедрение в один из легитимных процессов. В данном случае в процесс RegSvcs.exe

Создание процесса:

Происходит декодирование еще одного ресурса, который внедряется в процесс

Конечная вредоносная нагрузка полностью совпадает с ранее обнаруженным образцом.

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

YARA правила для нового образца и детектирование по ним в tLab:

import "pe"

rule win_spy_misterhook_755E_cyax_agent_tesla_tlab {

        meta:
              author =
"T&T security"
              date =
"2021-02-23"
              description =
"C# Agent Tesla packed by Cyax packer"
              hash =
"755EA48BC49FAD06DA579A292D2A917A8D31699FBD7E70E19D8BB58BC3F92C60"

        strings:
       
              $unpack_func = {
6f [4] 13 04 12 04 28 [4] 17 daa 0d 16 0c 38 [4] 03 6f [4] 13 04 12 0428 [4] 17} /* decode pixels */

              $encoded_png_1 = {
89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 00 00 00 55 00 00 00 55 08 06 00 00 00 38 F5 A8 5A 00 00 00 04 67 41 4D 41 00 00 B1 8F 0B FC 61 05 00 00 00 09 70 48 59 73 00 00 0E C3 00 00 0E} /* part of the sequence of bytes that represents a resource with an encoded image */

        condition:
              uint16(
0) == 0x5a4d
             
             
and pe.imports("mscoree.dll")

             
and $unpack_func

             
and $encoded_png_1
}

rule win_spy_ai_D357_cyax_agent_tesla_tlab {

        meta:
              author =
"T&T security"
              date =
"2021-02-23"
              description =
"C# encoded payload inside Agent Tesla"
              hash =
"D357B9EFB6E7729B3AD31599DA973860A740B18270F10CBF4D798DE14D160F0C"

        strings:
       
              $decode_func = {
28 [4] 28 [4] 00 02 28 [4] 04 28 [4] 0b 07 28 [4] 03 28 [4] 28 [4] 0c}

        condition:
              uint16(
0) == 0x5a4d
             
             
and pe.imports("mscoree.dll")

             
and $decode_func
}

rule win_spy_positivesign_8AF7_cyax_agent_tesla_tlab {

        meta:
              author =
"T&T security"
              date =
"2021-02-23"
              description =
"C# injector Agent Tesla"
              hash =
"8AF7CECBB5576942BF2EAF4B3F2D6BA3B19684065C0651082425DFAEC107750D"

        strings:
       
              $f1 = {
28 [4] 20 [4] 28 [4] 28 [4] 0a 38 [4] 00}

              $res1 = {
40 A8 A5 48 4B 26 38 32 85 03 28 18 65 D4 F8 F2 7B B5 72 27 1C 50 38 32 81 38 28 6E DD 6C 97 A6 F8 EF E2 27 24 50 4E 75 82 57 7C 18 22 93 97 9D 40 99 A5 60 4B 04 38 75 C2 57 47 18 54 D4 D0 F2}

              $res2 = {
78 6D 6C 20 76 65 72 73 69 6F 6E 3D 22 31 2E 30 22 20 65 6E 63 6F 64 69 6E 67 3D 22 55 54 46 2D 31 36 22 3F 3E 0D 0A 3C 54 61 73 6B 20 76 65 72 73 69 6F 6E 3D 22 31 2E 32 22 20}

        condition:
              uint16(
0) == 0x5a4d
             
             
and pe.imports("mscoree.dll")

             
and all of them
}

rule win_spy_agent_E701_cyax_agent_tesla_tlab {

        meta:
              author =
"T&T security"
              date =
"2021-01-05"
              description =
"C# Agent Tesla"
              hash =
"E701BED0853C2F782B0710F7895D7DCE22A58DBB0042DB56A7D9509929C8F05E"

        strings:
       
              $encoded_str_array = {
9F 9B 99 99 D7 D6 D5 D4 8F EE ED 8C C2 C3 84 ED F2 81 D5 D4 84 CC CF C4 CB CA C9 EE FB FA EB D1 EE D4 C0 C1 D1 E2 E1 D2 F1 F0 BC E3 F4 B9 B8 ED E8 A5 D7 FB F4 FA}

              $xor_algo = {
7E [4] 06 7E [4] 06 91 06 61 20 [4] 61 D2 9C 06 17 58 0A}

        condition:
              uint16(
0) == 0x5a4d
             
             
and pe.imports("mscoree.dll")

             
and $encoded_str_array

             
and $xor_algo
}

Обнаружения в tLab:

Заключение

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