Как работает DarkGate: подробный технический анализ
Сразу после запуска будет показано отладочное сообщение external debugg
. Этим можно маркировать начало работы самой полезной нагрузки.
DarkGate подгружает для своей работы следующий набор библиотек:
kernel32.dll
Urlmon.dll
user32.dll
Advapi32.dll
Shell32.dll
ntdll.dll
Причем в случае с последней он делает это, читая файл ntdll.dll
и самостоятельно загружая его в память.
Этап подгрузки библиотек заканчивается отладочным сообщением external debugg 2
.
Далее идет проверка имени пользователя (используется функция GetUserNameA
), от которого запущен DarkGate.
Если имя пользователя — SYSTEM
, то выставляется глобальная переменная, отвечающая за работу с системными привилегиями, а также проверяется наличие файла C:\temp\ssy
. Если такой файл существует, то DarkGate завершает свою работу.
Если имя пользователя SafeMode
, то выставляется глобальная переменная, отвечающая за работу от имени пользователя SafeMode
.
После проверки имени пользователя загружается конфигурация DarkGate. Пример конфигурации с описанием каждого параметра следует ниже:
0=80 //Порт, который будет использоваться для подключения к C2
1=No //Производить базовую проверку комплектующих компьютера
2=No //Пытаться повышать привилегии
3=No //Проверять, работает ли DarkGate в VMWare. Завершать работу, если проверка положительная
5=No //Проверять минимальное количество свободной памяти на диске C:\
4=100 //Минимальное требуемое количество свободной памяти на диске C:\ в гигабайтах
6=No //Проверять, работает ли DarkGate в Hyper-V. Завершать работу, если проверка положительная
8=No //Проверять минимальное количество оперативной памяти
7=4096 //Минимальное количество оперативной памяти в мегабайтах
9=No //Проверять, работает ли DarkGate в Qemu. Завершать работу, если проверка положительная
10=txtMut //Внутренний мьютекс или соль для MD5-хеша
11=Yes //Поставка DarkGate происходила с помощью AU3
12=No //Поставка DarkGate происходила с помощью DLL
13=No //Поставка DarkGate происходила иным способом
14=4 //Не используется
15=XiOwgXyDLNDEpj //ID для биндера
16=4 //Время между получением команд в секундах
17=No //Не используется
18=Yes //Не используется
19=Yes //Не используется
22=8080 //Не используется
23=A11111 //Маленький HWID (используется исключительно в команде 1051)
24=No //Используется в главном цикле
25=1 //Время между получением команд в минутах (с портом 8080)
26=Yes //Не используется
27=No //Записывать свой ID в %APPDATA%
28=No //Не используется
29=Yes //Не используется
После установки конфигурации происходит получение информации об агенте (компьютер, на котором выполняется DarkGate), формируются ID агента и ключ шифрования обмена сообщениями с C2. Подробнее об этом в описании функции GetAgentInformation
.
После выполнения этой функции, если DarkGate запущен от имени системы или пользователя SafeUser
, выключаются параметры [1], [2] и [18]. Если условия не выполняются, то ВПО считает, что запуск является первым. Далее будут описаны операции, которые происходят при первом запуске.
Если параметр конфигурации [1] выставлен в значение Yes, то проводятся проверки компьютера, на котором запущен DarkGate. Проверки проходят в зависимости от выставленных в конфигурации параметров:
- Проверяется, запущен ли DarkGate в Hyper-V. Если в ключе реестра
HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0\ProcessorNameString
присутствует строкаvirtual
или в имени видеокарты (достается с использованием функцииEnumDisplayDevices
параметрDeviceString
из структурыDISPLAY_DEVICEA
) присутствуют подстрокиmicrosoft hyper-v video
,standard vga graphics adapter
илиmicrosoft basic display adapter
, исполнение прекращается. - Проверяется, запущен ли DarkGate в Qemu. Если в имени процессора (получается аналогично предыдущему пункту) присутствует подстрока
xeon
, исполнение прекращается. - Проверяется, запущен ли DarkGate в VMWare, если в имени видеокарты присутствуют подстроки
virtual
,vmware
,Microsoft Hyper-V Video
(case-sensitive), то исполнение прекращается. - Проверяется достаточность физической памяти. Если количество физической памяти (с использованием функции
GlobalMemoryStatusEx
достается параметрullTotalPhys
из структурыMEMORYSTATUSEX
) в мегабайтах (количество делится на 1 048 576) меньше значения параметра [7] конфигурации, то исполнение прекращается. - Проверяется достаточность свободного места на диске
C:\
. Если количество свободного места на дискеC:\
(достается с использованием функцииGetDiskFreeSpaceExA
) в гигабайтах (третий аргумент функции делится на0×40000000
) меньше значения параметра [4] конфигурации, то исполнение прекращается.
После проверок в файл по пути C:\temp\<GenerateId("e")>
записывается четыре случайных символа, а если существует файл C:\temp\t.txt
и DarkGate запущен от имени администратора, то в файл C:\temp\d.txt
также записывается четыре случайных символа.
Далее происходит проверка на наличие некоторых файлов:
C:\temp\<GenerateId("update")>
(далее —%%update%%
). Если этот файл существует, он удаляется.C:\temp\<GenerateId("a")>
(далее —%%a%%
). Если файл существует, он удаляется. После этого идет задержка на 100 миллисекунд.%TEMP%\<GenerateId("uninstall")>
(далее —%%uninstall%%
). Если файл существует, он удаляется.
Также генерируются строки <GenerateId("m1")>
и <GenerateId("m2")>
. Они будут использоваться позднее.
Следом идут попытки обнаружения антивирусного ПО. Эта функция в силу ее громоздкости вынесена в отдельный раздел «Обнаружение антивирусов».
Если был найден Avast, то запускается поток, который в десктопе avdesk
каждые 2–3 секунды закрывает окно со случайным дескриптором от 1000 до 99999. Главный поток в это время находится в состоянии sleep на 40 секунд. Если в системе есть ESET NOD32, Norton или Symantec то DarkGate останавливает свою работу.
На этом инициализация заканчивается и начинается главный цикл работы.
Функция собирает следующую информацию о компьютере:
- Версия операционной системы. Используются ключи
ProductName
,CSDVersion
иCurrentBuildNumber
, которые находятся в реестре по путиHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
. Также узнается битность процессора (x86/x64). В зависимости от этих значений делается вывод, достаточно ли новая версия операционной системы. Выводы могут быть такие:- номер сборки Windows >= 22000 (Windows 11);
- Windows 10, 8.1, 8, 7, Vista;
- Windows XP и старше.
ProductId
из того же пути, что и версия операционной системы.- Модель процессора и количество ядер.
- Имя пользователя, от имени которого запущен DarkGate.
- Сетевое имя компьютера.
После сбора информации конкатенируются строки 4, 5, 2, 3 (результат выполнения пунктов выше) и от конечной строки берется модифицированный MD5-хеш.
После получения хеша от него снова берется уже обычный MD5, и получается HEX-строка.
Эта HEX-строка будет ключом для шифрования трафика между клиентом и сервером, ниже расскажем об этом подробнее. Для удобства эту строку назовем ComputerNameHash
.
Далее создается строка, имя которой потом будет играть отдельную роль. Генерация этой строки будет выделена в отдельную функцию, поскольку она выполняется часто. Она будет называться GenerateID
.
После этого происходит генерация Base64-чарсета, с помощью которого будет реализовано общение DarkGate с управляющим сервером. Оно происходит так:
- Считается сумма символов HEX-строки, сгенерированной в начале функции, это будет сид рандома.
- Берется встроенный чарсет Base64, и происходит его перемешивание.
Таким образом, каждый раз, когда клиент хочет послать серверу какие-то данные, он кодирует их в этот (случайный) Base64-чарсет и отправляет. Получается своего рода защищенный канал.
Функция имеет один аргумент: строка, для которой необходимо создать уникальный идентификатор. К этой строке добавляется [10], ComputerNameHash
, эта строка хешируется обычным MD5, переводится в HEX, и берутся первые семь символов. Например, в случае со строкой str
, ComputerNameHash=abcdef
, [10]=txtMut
получится fDcKfBA
.
Здесь описаны механизмы детекта антивирусных ПО.
С самого начала функции DarkGate получает список процессов (классический метод через CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0)
и итерация через Process32First/Process32Next
). После этого выносится вердикт о наличии ПО:
- BitDefender — cуществует директория
C:\ProgramData\Bitdefender
илиC:\Program Files\Bitdefender
. - Avast — существует директория
C:\ProgramData\AVAST
илиC:\Program Files\AVAST Software
. - AVG — существует директория
C:\ProgramData\AVG
илиC:\Program Files\AVG
. - Kaspersky — существует директория
C:\Program Files (x86)\Kaspersky Lab
, но не найден Kaspersky Endpoint Secutiry. - Kaspersky Endpoint Security — в директории
C:\Program Files (x86)\Kaspersky Lab
существует файл, в названии которого есть подстрока KES. - Nod32 — существует процесс, который начинается с
egui
. - Avira — существует директория
C:\ProgramData\McAfee
илиC:\Program Files (x86)\Avira
. - Norton — существует директория
C:\Program Files\Norton Security
, или существует процесс, который называетсяns.exe
, или в нем есть подстрокаnortonsecurity.exe
. - Symantec — существует процесс
smc.exe
. - Trend Micro — существует процесс, в котором есть подстрока
uiseagnt.exe
. - SUPER AntiSpyware — существует процесс, в котором есть подстрока
superantispyware.exe
. - MalwareBytes — существует директория
C:\ProgramFiles\Malwarebytes
или существует процесс, который называетсяmbam.exe
. - Comodo — существует процесс, в котором есть подстрока
vkise.exe
или который начинается сcis.exe
. - ByteFence — существует процесс, в котором есть подстрока
bytefence.exe
. - Search & Destroy — существует процесс, в котором есть подстрока
sdscan.exe
. - 360 Total Security — существует процесс, в котором есть подстрока
qhsafetray.exe
. - Total AV — существует процесс, в котором есть подстрока
totalav.exe
. - IOBit Malware Fighter — существует директория
C:\Program Files (x86)\IOBit
. Дополнительно при обнаружении запускается отдельный поток, который каждые 100 миллисекунд убивает процессыmonitor.exe
иsmBootTime.exe
. - Panda Security — существует процесс, в котором есть подстрока
psuaservice.exe
. - Emsisoft — существует директория
C:\ProgramData\Emsisoft
. - Quick Heal — существует директория
C:\Program Files\Quick Heal
. - F-Secure — существует директория
C:\Program Files (x86)\F-Secure
. - Sophos — существует директория
C:\Program Files(x86)\Sophos
. - G DATA — существует директория
C:\ProgramData\G DATA
.
Если не выполнено ни одно из условий, антивирусное ПО ставится в Unknown. Если найден Eset, [2] ставится в No. Функция возвращает название найденного антивирусного ПО. Такое ПО может быть только одно, поэтому оно проверяется по порядку списка выше.
В самом начале выполнения в глобальные переменные помещаются следующие значения:
- Версия DarkGate (в рассматриваемом экземпляре было 5.2.8).
- Список доменов С2, разделенных символом | (Pipe) в Base64 со словарем
zLAxuU0kQKf3sWE7ePRO2imyg9GSpVoYC6rhlX48ZHnvjJDBNFtMd1I5acwbqT+=
.
ВПО производит ряд проверок, среди которых:
- Как был доставлен семпл (DLL, или AU3, или иным способом).
- Установлен ли антивирус BitDefender (если установлен, то выводится
MessageBox
со случайным тайтлом и содержанием на 2 миллисекунды).
Затем назначается порт для общения с С2. Для того чтобы выполнение выглядело легитимно, DarkGate выводит фейковое сообщение (MessageBox
) об отсутствии какой-либо библиотеки.
ВПО создает директории и файлы по следующим путям:
C:\ProgramData\<GenerateId("mainfolder")>
(далее —%%mainfolder%%
). Если такой папки не существует, то делаются начальные проверки на ВМ и комплектующие.%%mainfolder%%\<GenerateId("logsfolder")>
(далее —%%logsfolder%%
). Папка будет создана, если ее не существует.%%logsfolder%%\<GenerateId("settings")>
(далее —%%settings%%
).%%logsfolder%%\<GenerateId("resources")>
(далее —%%resources%%
).%%logsfolder%%\<GenerateId("binder")>
(далее —%%binder%%
).%%logsfolder%%\<GenerateId("minercpu2")>
(далее —%%minercpu2%%
).%TEMP%\<GenerateId("supertemp")>
(далее —%%supertemp%%
). Папка будет создана, если ее не существует.%%supertemp%%\notepad.exe
.
ВПО ищет файл AutoIt3.exe
в текущей директории, в директории %%mainfolder%%
и в C:\temp
. Если файл найден, то ВПО его считывает и помещает содержимое в глобальную переменную. Кроме того, ВПО проверяет, существует ли файл %%settings%%
, и если файл найден, то он расшифровывается и считывается. Этот файл является детальным конфигом ВПО и содержит следующие переменные:
domains
— эти домены будут являться адресами C2 вместо тех, что были установлены статически в конфигурации по умолчанию (ранее).notifications
— уведомления.monero
— настройки майнера.minerconfig
— настройки майнера.epoch
— время первого запуска (если запускается в первый раз, то будет равноNow()
).gldelay
— принимает значение от1600000
до96000000
. Не используется.version
— не используется.puerto
— не используется.vepoch
— время последнего подключения к С2.paranoic
— может быть 0 или 1. Не используется.
После этого текущая конфигурация пишется в %%settings%%
, предварительно зашифрованная случайным Base64. Туда попадают следующие поля:
domains
,notifications
,epoch
,puetro
— это порт подключения (или же [0]). Довольно странно, потому что при чтении конфигурации это значение записывается не в ту глобальную переменную.
ВПО ищет файлы *.au3
, считывает и разбивает на части с делимитером AU3!EA06
. Вторая часть получившейся строки является пейлоадом DarkGate, она зашифрована с помощью XOR, ключом от которого являются первые 8 байт этой же строки. Это интересный факт, потому что существует высокая вероятность, что DarkGate к этому моменту уже запущен. Таким образом, автор DarkGate предусмотрел своего рода резервирование.
Перед тем как произвести инжект, ВПО производит ряд проверок:
- Версия Windows должна быть выше XP.
- Полный путь исполняемого файла содержит
autoit3.exe
, илиappdata\local\temp
, или%TEMP%
, а если не содержит любое из них, не должен содержать:\windows
,\appdata\
или:\program files
. - В системе нет
QuickHeal
или существует файл%%mainfolder%%\<GenerateId("au3file")>.au3
.
В случае если проверки завершились успешно, производится инжект расшифрованного шелл-кода из найденного на предыдущем шаге файла AU3. Подробнее об используемых техниках инжектов — в разделе «Типы инжектов». Выбор техники инжекта зависит от найденного в ОС антивируса:
В случае если проверки завершились успешно, производится инжект расшифрованного шелл-кода из найденного на предыдущем шаге файла AU3. Подробнее об используемых техниках инжектов — в разделе «Типы инжектов». Выбор техники инжекта зависит от найденного в ОС антивируса:
- Если есть Kaspersky или Kaspersky Endpoint Security, то выполняется инжект первого типа.
- Если есть Avast или AVG, то выполняется инжект второго типа.
- Если есть BitDefender, то выполняется инжект третьего типа.
- Во всех остальных случаях выполняется инжект четвертого типа.
Затем, если существует файл C:\tess\Autoit3.exe
, он удаляется. Если существует файл C:\tess\Autoit3.exe
, то удаляется файл C:\tess\mytest.au3
(вероятнее всего, это баг, потому что это условие не может быть выполнено из-за того, что проверяемый файл удаляется на предыдущем этапе). В дополнение к этому стоит отметить название папки tess
, а не test
, как должно быть.
Дальше главный цикл работы DarkGate разделяется на два потока. Первый поток будет общаться с C2, используя порт из первоначальной конфигурации. Другой поток будет получать команды от C2, используя порт 8080. Однако остальная коммуникация будет проходить через порт из первоначальной конфигурации. Задержка между получением команды в первом потоке будет 16 секунд, в то время как во втором потоке — 25 минут.
В продолжении основного потока выводится отладочное сообщение external debugg 10
и проверяется наличие файла C:\temp\t.txt
. Если файл существует, он вместе с C:\temp\p.txt
удаляется, в файл C:\temp\d.txt
записывается случайная строка из четырех символов. И если пользователь, от имени которого запущен DarkGate, является администратором, на сервер отправляется сообщение Elevation completed
, а параметр конфигурации [2] выставляется в No
.
После этого выводится отладочное сообщение external debugg 11
. И если существует файл C:\temp\crash.txt
, то на сервер отправляется текст DarkGate has recovered from a Critical error
и этот файл удаляется.
Затем в очередной раз проверяется наличие папки C:\temp
и установление на нее атрибута FILE_ATTRIBUTE_HIDDEN
. И если не было найдено антивирусное ПО, [24] и не существует файла %%mainfolder%%\<GenerateId("au3file")>.au3
, запускается поток, который делает запрос на сервер (команда 1344, подробнее — в разделе «Общение с сервером»), расшифровывает случайным Base64 и XOR-ключом, который равен хешу компьютера, после чего инжектит эти данные в cmd.exe
, используя первый тип.
DarkGate делает попытку записи себя в автозагрузку. Есть несколько вариантов, как может быть реализован автозапуск:
- Создание ссылки
%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\<GenerateId(ProcessorInformation)>.lnk
на файл%%mainfolder%%\<GenerateId(ProcessorInformation)>.exe
, являющийся DarkGate. - Создание ссылки
%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\<GenerateId(ProcessorInformation)>.lnk
на файл%%mainfolder%%\Autoit3.exe
с аргументом%%mainfolder%%\<GenerateId("au3file")>.au3
. Происходит, если нет BitDefender и Sophos и доставка ВПО произошла с помощью AutoIt. - Запись в реестр ключа
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\GenerateId(ProcessorInformation)
со значением%%mainfolder%%\Autoit3.exe %%mainfolder%%\<GenerateId("au3file")>.au3
. Этот способ требует перезагрузки, которая в штатном режиме произойти не может, т. к. для ее выполнения ВПО создает взаимоисключающие условия. Так, для штатной перезагрузки по условиям в ОС должны быть одновременно установлены Kaspersky и BitDefender. Если условия не соблюдаются, вызываетсяNtRaiseHardError
с ошибкой0xc0000350
и происходитBSOD
, что равноценно перезагрузке. - Аналогично третьему варианту, но без перезагрузки. Это техника используется в остальных случаях, когда не был создан LNK-файл и в системе установлены Sophos или BitDefender.
После записи в автозагрузку запускается поток с кейлогером (подробнее — в разделе «Кейлогер»). После этого стартует общение с сервером с задержкой в 16 секунд.
Общение с сервером осуществляется через HTTP (может быть нестандартный порт). На / отправляется POST-запрос с заголовками User-Agent:Mozilla/4.0(compatible; Synapse), Content-Type:Application/octet-stream
. В теле запроса находятся хеш компьютера и тело, которое зашифровано случайным Base64 (хеш компьютера передается как раз для того, чтобы создать Base64-ключ для расшифровки тела). В теле первые четыре символа — всегда номер ответа (или в некоторых случаях номер запроса), далее идет сам ответ (запрос). Например, при отправке самого первого сообщения для получения команды (код 1000) запрос выглядит так:
POST / HTTP/1.0
Host: localhost
Keep-Alive: 300
Connection: keep-alive
User-Agent: Mozilla/4.0 (compatible; Synapse)
Content-Type: Application/octet-stream
Content-Length: 591
CKDbbdBGbeFb<REDACTED>9n2V9gXc9g2<REDACTED>
Здесь CKDbbdBGbeFb<REDACTED>
— это хеш компьютера, 9n2V9gXc9g2<REDACTED>
— тело запроса. Более подробно о том, что отправляется и что получается, — в разделе «Команды».
Первый тип является одним из самых сложных в техническом исполнении (наряду с пятым типом). По большей части это полная реализация загрузки PE-файла в процесс, который будет запущен. Из интересных и довольно уникальных моментов:
- WinApi используется, только чтобы запустить процесс и подождать его код ошибки (
CreateProcessA
иWaitForSingleObject
). Для записи в его память, запуска и т. д. напрямую используются системные вызовы, номер которых достается изntdll.dll
. Используются такие системные вызовы, как:NtGetContextThread
NtReadVirtualMemory
NtUnmapViewOfSection
NtAllocateVirtualMemory
NtWriteVirtualMemory
NtProtectVirtualMemory
NtFlushInstructionCache
NtSetContextThread
NtResumеThread
NtFreeVirtualMemory
NtTerminateProcess
- Функция, которая обрабатывает процесс инжекта, принимает в качестве аргумента путь до исполняемого файла для инжекта в него и аргументы, с которыми этот процесс будет запущен. По умолчанию путь и аргументы у процесса —
cmd.exe
иcmd /c ping 127.0.0.1
соответственно. - Делается восемь попыток инжекта. Первые шесть попыток действия просто повторяются, на седьмой раз выбирается
vbc.exe
(версии v2.0.50727, v4.0.30319) или, если он отсутствует,systeminfo.exe
. На восьмой раз, в зависимости от одного из аргументов, идет попытка инжекта в случайное запущенное приложение. Это пятый тип инжекта, о нем можно почитать ниже.
Этот тип довольно простой. Если не указано иначе, выбирается один из существующих путей по порядку:
C:\Program Files (x86)\Google\Update\GoogleUpdate.exe
C:\Program Files (x86)\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exe
C:\Program Files (x86)\BraveSoftware\Update\BraveUpdate.exe
C:\Program Files (x86)\Common Files\Microsoft Shared\ink\TabTip32.exe
cmd.exe
Он работает по классической схеме (CreateProcessA (CREATE_SUSPENDED)
+ WriteProcessMemory
+ ResumeThread
), но с одним отличием: полезная нагрузка не инжектится в процесс сразу, а шифруется случайным XOR-ключом размером 8 байт и записывается вместе с ним по пути C:\temp\a
. В процесс же инжектится шелл-код-лоадер, который читает файл C:\temp\a
, расшифровывает полезную нагрузку и грузит в память, резолвя все импорты.
В принципе, то же самое, что и второй тип, но путь приложения выбирается из случайного запущенного процесса. Либо, если такой нельзя найти, берется любой исполняемый X86GUI-файл из C:\Program Files (x86)
.
Работает как третий тип. Однако, поскольку именно этот тип используется в случае отсутствия антивируса, применяется очень грязный прием. Его суть в том, что сначала выбирается случайный запущенный процесс, и он превращается в родительский процесс нового процесса, в который произошел инжект (более подробно описано на WinProgger).
Почти как четвертый тип, кроме того, что рассчитан больше на DLL-файлы, чем на EXE. Совершает релокации, грузит библиотеки в пространстве запущенного процесса, заполняет таблицу импортов и запускает EntryPoint
.
У майнера есть две собственные конфигурации, которые существуют обособленно от основной конфигурации ВПО. Первая из них содержит список URL-адресов майнинг-пулов, которые впоследствии конкатенируются в формате -o <URL>:3340
. Вторая, которая будет рассмотрена, — основная конфигурация, от которой зависит работа майнера.
В рассматриваемой версии ВПО эта конфигурация не может быть записана напрямую в %%settings%%
, однако у DarkGate есть другой способ записи в файл. Сам конфиг очень похож на основной, имеет тот же формат, то есть <ключ>=<значение>
(параметры хранятся в StringList
в текстовом формате). Примера такой конфигурации найти не получилось, потому что она не поставляется вместе с DarkGate. Сама конфигурация включает в себе следующие ключи:
- 1 — число от 0 до 4. Означает тип алгоритма, который нужно майнить (0 и 4 —
ETCHASH
, 1 —KASPA
, 2 —NEXA
, 3 —AUTOLYKOS2
). - 2 — число от 0 до 10. 10 означает «не использовать CPU», 0 означает «использовать все ядра» (каждый шаг от 0 до 10 уменьшает количество ядер на 10%).
- 3 — булевое значение: если
False
, то ВПО будет майнить на GPU. - 5 — минимальное время в миллисекундах, которое должен прождать DarkGate с момента последнего ввода пользователя.
- 6 — нужна ли дополнительная задержка.
- 7 — время дополнительной задержки.
- 8 — проверять, запущен ли диспетчер задач.
- 10 — число от 0 до 5, означает приоритет, который подается XMRig (0 — 4, 1 — 3, 2 — 2, 3 — 1, 4 и 5 — 0, так же как и
PriorityClass
, который будет выставлен процессу). - 13 — выполнять
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED)
. - 14 — проверять, больше ли в системе физической памяти, чем 6666 мегабайт.
- 15 — проверять, работает ли DarkGate в VMWare.
Скачивание майнера
Майнер изначально отсутствует в комплекте DarkGate и скачивается отдельно. Проверяется наличие файла %%minercpu2%%
. Отдельно проверяется, содержится ли в этом файле строка nominear
. И если это так, то майнер работать не будет ни при каких обстоятельствах (записывается туда командой 1040
). Размер этого файла в ином случае должен быть больше или равен 1 048 576 байт. Если размер меньше указанного, то файл удаляется. Во всех случаях, когда файла майнера нет или он удален, он скачивается с сервера. Таким образом:
- если в конфигурации майнера переменная [2] не равна 10, то будет майниться CPU с помощью XMRig;
- если в конфигурации майнера переменная [3] не равна 1, то будет майниться GPU с помощью T-Rex.
При этом поддерживается CPU+GPU, если оба условия выполнены. Сам исполняемый файл XMRig скачивается с сервера следующими запросами:
3033
— GPU T-Rex.3026
— CPU XMRig.3040
— CPU+GPU XMRig + T-Rex.
Размер скачанного файла должен быть больше 3 000 000 байт (если меньше 1 000 000 байт, то DarkGate ждет случайное время от 10 до 20 секунд). На сервер же при этом будет отправлено сообщение Stub: Miner has been Downloaded -> Installing Miner <тип майнера> / Elapsed: <время получения файла в секундах> Seconds / Bytes: <размер полученного файла>
. После этого данные записываются в файл %%minercpu2%%
.
Операции перед запуском майнера
Сначала DarkGate проверяет наличие файла C:\temp\id.txt
. Читает оттуда PID, если файл существует, и проверяет, существует ли этот PID (если он есть, то майнер не будет запускаться второй раз). Далее проверяется наличие директории C:\darkgateminertest
, и если она есть, то на сервер могут быть отправлены отладочные сообщения. После этого на сервер отправляется отладочное сообщение Stub: darkminertest! TimeToIDLE:<[5]>
.
После ряда проверок, если майнер не был запущен ранее, он запускается (о том, как он запускается, в следующем разделе), на сервер отправляется отладочное сообщение Stub: Miner injected at Defrag.exe
, а этот поток будет ждать, пока не появится процесс.
Другой цикл также будет проверять ввод пользователя и отправлять на сервер отладочные сообщения в формате Miner is waiting IDLE <время с последнего ввода пользователя> / <[5]>
.
Запуск майнера
В потоке запуска проверяется наличие файла %%minercpu2%%
, и если его нет и майнер запущен командой 1134
, то на сервер отправляется отладочное сообщение Stub: %%minercpu2%% not exists
и поток завершает свою работу.
Далее этот файл читается, и его контент разделяется строкой _padoru_
(если этой подстроки в файле нет, то на сервер отправляется строка Stub: Corrupted miner FilesDelimiter is missing, will redownload miner soon | Retry <количество уже сделанных попыток>)
. Эти части будут описаны далее.
После разделения контента файла происходят следующие действия:
- Проверяется первая часть, что это действительно PE-файл. Если это не так, то на сервер отправляется строка
Stub: Corrupted miner MZ, will redownload miner soon | Retry <количество уже сделанных попыток>
. - Если есть третья часть и количество потоков не 0 (зависит от переменной [2] в конфигурации майнера), то создается строка
<адреса> —cpu-priority=<приоритет в зависимости от [10]> —threads=<количество потоков>
, шифруется XOR-ключом, который равен первым восьми символам хеша компьютера, и записывается вместе с ним в файлC:\temp\xmr.txt
, а в файлC:\temp\xmr
записывается третья часть в форматеXOR(arg[2]+RandStr(RandInt(10, 100)*100), key)+key
. - Если есть четвертая часть, то создается строка
<адреса с заменой ’-o’ на ’-p ’ и ’:3340 ′ на ’:9000 -u 0xDark ’> -a <алгоритм из [1]>
. Если майнер запущен командой1134
, то эта строка записывается вC:\temp\testgpudec.txt
. Эта строка шифруется XOR аналогично предыдущему пункту и записывается в файлC:\temp\etc.txt
, а сама четвертая часть записывается в файлC:\temp\etc
. - Выставляются настройки XMRig и T-Rex.
- Файл
C:\temp\id.txt
удаляется, если он есть, вторая часть инжектится вcmd.exe /c ping 127.0.0.1
. - Спит от 100 до 200 миллисекунд, пока не появится файл
C:\temp\id.txt
. - Этот файл читается, и этому PID выставляется
PriorityClass
в зависимости от переменной [10] в конфигурации майнера.
Помимо AnyDesk, в DarkGate есть своя реализация удаленного управления компьютером с использованием чистого WinAPI. Протокол основан на таком же HTTP-общении с сервером, где клиент в виде DarkGate отправляет информацию о текущем состоянии мониторов и изображение рабочего стола, а сервер отвечает действием, которое должен выполнить DarkGate.
При условии, что есть только один монитор, отправляются следующие данные:
<скриншот экрана в BMP формате>_padoru_<HORZRES>_padoru_<VERTRES>_padoru_0
Если экранов несколько, то отправляются данные в следующем формате:
_monitor_<скриншот экрана в BMP формате><... на каждый из экранов ...>_monitor_padoru_<имя экрана>|<HORZRES этого экрана>|<VERTRES этого экрана><... на каждый из экранов ...>
При этом стоит отметить: есть вероятность, что скриншот сжимается либо конвертируется в другой формат (самой функции сжатия в DarkGate нет, он получает ее с сервера).
DarkGate же принимает следующие данные от сервера:
- Команда от сервера (четыре цифры как команда).
- Неизвестное значение (изначально 0).
- Неизвестное значение (изначально 0).
- Неизвестное значение, вероятно, качество JPEG (изначально 40).
- X-координата, куда переместить мышь.
- Y-координата, куда переместить мышь.
- Команда VNC.
- Текст для набора.
- 1, если использовать StretchBlt, или 0, если использовать BitBlt для копирования изображения.
Команды VNC
0 — нажатие ЛКМ
Требуется X и Y, после чего на эти координаты будет вызвана функция SetCursorPos
и произойдет моментальное нажатие с помощью функции mouse_event(MOUSEEVENTF_LEFTDOWN)
и mouse_event(MOUSEEVENTF_LEFTUP)
.
3 — нажатие ПКМ
Работает так же, как и 0, но с правой кнопкой мыши.
4 — двойное нажатие ЛКМ
Работает как 0, но нажатие происходит два раза с задержкой в 100 миллисекунд.
5 — набор текста на клавиатуре
Использует текст для набора из команды. Формат этой строки совпадает с форматом строки в кейлогере. Набор будет происходить с помощью функции keybd_event
.
6 — набор текста с помощью буфера обмена
Вариант работы команды 5, но для набора текста будут использованы буфер обмена и нажатие сочетания клавиш Ctrl+V. При этом предыдущие данные буфера сохраняются и будут возвращены после вставки.
9 — отправить скриншот на сервер
Отправляет на сервер сообщение RSActionSendHQScreenshot
, делает скриншот и отправляет его на сервер.
Кейлогер имеет несколько возможностей:
- обычное логирование символов, набранных на клавиатуре;
- логирование имен окон при фокусе на другое окно;
- дамп информации из буфера обмена при фокусе на другое окно.
При этом при запуске кейлогера запускается еще два потока:
- Тикер — поток, который считает, сколько времени прошло с последней записи в кейлог.
- Чекер — проверяет, что с последнего ввода прошло не более 4 секунд и в имени окна фокуса нет подстрок:
process hacker
,process exporer
,administrador de tareas
,taskmanager
,task manager
.
Когда данные записываются в кейлог, они шифруются случайным Base64. Кейлог имеет имя DD-MM-YYYY.log
и сохраняется в папке %%logsfolder%%
. Имена окон записываются в UTF-16 в HEX-формате. Каждая смена окна записывается с временем, когда это произошло. При некоторых условиях имя окна отправляется на сервер с кодом 3023.
№ команды | Действие | Аргументы | Дополнительные инструменты | Действия с файлами и процессами |
---|---|---|---|---|
1111 | Тихий перезапуск | — | — | Запись в |
1001 | Получить информацию о компьютере жертвы | — | — | — |
1003 | Остановка майнера и завершение работы | — | — | Остановка всех процессов с именем |
1004 | Получить все логи кейлогера | — | — | Чтение |
1008 | Кража паролей браузеров из WebBrowserPassView | Содержание для следующих файлов:
| Запись и удаление файлов:
Инжект первого типа в | |
1009 | Кража паролей почты из | Исполняемый файл | Инжект первого типа в | |
1010 | Получить cookie Firefox | — | — | Чтение файлов по маске |
1011 | Получить данные из Skype в HTML-формате | Неизвестный исполняемый файл | Неизвестно | Запись и чтение |
1012 | Получить данные из Skype в TXT-формате | Неизвестный исполняемый файл | Неизвестно | Запись и чтение |
1013 | Получить данные FileZilla | — | — | Чтение файлов:
|
1014 | Получить cookie Google Chrome | — | ChromeCookiesView (запрос 1485) | — |
1015 | Получить cookie Edge | — | ChromeCookiesView (запрос 1485) | — |
1021 | Получение базовой информации о файловой системе пользователя | — | — | Чтение папки Получение информации о файлах в папке Получение списка дисков |
1022 | Получение файлов в директории | Glob, который нужно развернуть | — | Получение информации о файлах, удовлетворяющих аргументу |
1023 | Прочитать файл | Путь к файлу | — | Чтение файла по пути аргумента |
1025 | Изменить задержку для общения между жертвой и сервером | Новая задержка в миллисекундах | — | — |
1026 | Удалить точки восстановления, если запущен от имени администратора | — | — | Запуск команды |
1027 | Выключить все мониторы | — | — | — |
1028 | Удаление всех cookie всех браузеров | — | — | Выполнение команд:
Остановка процессов:
Рекурсивное удаление файлов в папке |
1029 | Выключение компьютера | — | — | Выполнение команды |
1030 | Перезагрузка компьютера | — | — | Выполнение команды |
1031 | Запуск приложения без аргументов | Путь к приложению | — | Запуск исполняемого файла из аргумента |
1033 | Запустить полученный от сервера бинарь в десктопе | Исполняемый файл | — | В десктопе с именем |
1034 | Инжект | Исполняемый файл | — | Поиск файлов:
Инжект первого типа в выбранный из вышеперечисленных файлов |
1035 | Запустить что-то через | Путь, куда записать файл Контент файла | — | Записывает данные по пути, представленном в аргументе Запуск файла по пути с использованием |
1036 | Запустить бинарь в памяти DarkGate | Исполняемый файл | — | — |
1037 | Странный инжект | Аргумент для запуска Исполняемый файл | — | Поиск файлов:
Инжект первого типа в выбранный из вышеперечисленных файлов |
1038 | Переустановить майнер | — | — | Остановка всех процессов с именем |
1040 | Удалить майнер | — | — | Запись в файл по пути майнера |
1041 | Выключить майнер | — | — | См. 1038 |
1043 | Выполнить команду через | Путь к файлу, который нужно запустить | — | Исполнение файла по пути аргумента |
1045 | Записать данные в файл | Путь к файлу Контент файла | — | Запись в файл по пути аргумента |
1046 | Сделать RAR-архив файла или директории и отправить его на сервер | Путь к файлу или директории, которые надо архивировать | WinRar (запрос 1504 или локально) | Удаление файлов Поиск файлов:
Запись в файл Чтение файлов Выполнение команды |
1047 | Перезапустить майнер | — | — | См. 1038 |
1048 | Выполнить команду | Команда | — | Выполняет команду |
1049 | Получить токены Discord | — | — | Открытие процесса с именем Чтение его виртуальной памяти |
1050 | Запустить файл в пространстве Wow64-процесса | Исполняемый файл | — | Открытие процессов Wow64, в имени которых нет Поиск файла Удаление файла Инжект пятого типа |
1051 | Получить информацию о боте | — | — | — |
1052 | Удалить все логи кейлогера | — | — | Удаление файлов |
1053 | Полное удаление | — | — | Запись в файлы:
Удаление LNK-файла, прописанного при автозагрузке Останавливаются процессы с именем Выполняет команду |
1060 | Удалить все теневые копии (FORCE) | — | — | См. 1026 |
1070 | Запуск бинаря в своей памяти | Исполняемый файл | — | Открытие/создание десктопа |
1071 | Запустить файл в пространстве Wow64-процесса с фоллбэком к 1070 | Исполняемый файл | — | См. 1050 и 1070 |
1072 | Убить все процессы WinRar (остановить архивирование 1046) | — | — | — |
1073 | Поиск файлов в папке (рекурсивно) | Папка для старта поиска Подстрока, которая должна быть в названии файла | — | Поиск файлов по аргументам |
1075 | Инжект первого типа с записью в файл | Ключ шифрования исполняемого файла Исполняемый файл | — | Запись в файл Инжект первого типа |
1076 | Удалить файл или папку ( | Путь к файлу или папке | — | Удаление файла или папки по аргументу |
1078 | Остановить процесс 1073 | — | — | — |
1079 | Запуск самописного VNC-сервера | — | — | — |
1082 | Остановка VNC сервера | — | — | — |
1091 | Получить список процессов | — | — | Открывает процессы с правами |
1092 | Получить тип (архитектуру) исполняемого файла | Путь до файла | — | Чтение файла по аргументу |
1096 | Инжект первого типа | Путь к исполняемому файлу (жертве) Исполняемый файл | — | Запуск приложения по пути Инжект первого типа в запущенный файл |
1099 | Инжект пятого типа | Путь к исполняемому файлу (жертве) Исполняемый файл | — | Запуск приложения по пути Запуск случайного приложения Инжект пятого типа в запущенный файл (с PPID случайного приложения) |
1102 | Инжект в конкретный процесс (по PID) | PID процесса Исполняемый файл | — | Инжект пятого типа в процесс с PID аргумента |
1103 | Инжект с использованием | Путь к исполняемому файлу (жертве) Исполняемый файл | — | Запуск приложения по пути |
1104 | Так же, как 1103, но процесс не запускать (взять по PID) | PID процесса Исполняемый файл | — |
|
1105 | Получить список процессов | — | — | См. 1091 |
1106 | Остановить процесс по PID | PID процесса | — | Остановка процесса по PID |
1107 | Показать | Текст сообщения Название окна Тип сообщения | — | — |
1108 | Выставить параметры прокси-сервера | Настройки прокси | — | Запись в реестр по путям:
|
1109 | Удалить параметры прокси-сервера | — | — | Запись в реестр по пути |
1469 | Запуск PowerShell для реверс-шелла (убить активный) | — | — | Запуск |
1452 | Перезапуск AnyDesk | — | Останавливаются процессы с именем Запуск приложения | |
1453 | Удалять креды из cmdkey | — | — | Выполняются команды:
|
1454 | Попытка подняться до прав системы | — | Запись в файлы Поиск файлов:
Выполнение команды | |
1457 | Сделать RAR-архив файла или директории и отправить его на сервер | Путь к файлу или директории, которые надо архивировать | WinRar (запрос 1504 или локально) | Копирование таргет-файла или папки в См. 1046 |
1466 | Запуск PowerShell для реверс-шелла (игнорировать уже запущенный) | — | — | См. 1469 |
1467 | Отправить команду PowerShell | — | — | — |
1450 | Перезапуск AnyDesk (позиционирует себя как перезапуск от имени администратора) | — | См. 1452 | |
1446 | Отключить AnyDesk, удалить пользователя SafeMode | — | — | Останавливаются процессы с именем Выполнение команды |
1448 | Перезапуск DarkGate в другом пространстве hAnyDesk | — | — | Проверяется наличие файлов:
Выполняется команда |
1449 | Запустить приложение | Путь до приложения Аргументы | — | Запуск приложения по пути аргумента |
1443 | Установка hAnyDesk + rdpwrap, создание пользователя | Исполняемый файл Данные, которые будут записаны в Не используется Данные, которые будут записаны в Некоторая команда | Запись в файлы:
Выполнение команд:
Запись в реестр по пути Проверяется наличие директории | |
1342 | Непонятно, зачем она нужна, но она переименовывает папки | — | — | Переименование трех папок:
|
1344 | Инжект какого-то бинаря с сервера | — | Исполняемый файл (запрос 1344) | Инжект первого типа в |
1345 | Получить привилегии администратора | — | Исполняемый файл (запрос 1345) | Поиск файлов:
Удаление файлов:
Запись в файлы:
|
1337 | Включить дополнительные логи майнера | — | — | — |
1134 | Запуск майнера | — | — | См. 1047 |
1335 | Выставляет глобальную переменную в 1. Пока неизвестно, для чего она нужна | — | — | — |
1336 |
| — | — | — |
1131 | Прочитать много файлов сразу | Список файлов для прочтения | — | Чтение файлов из аргумента |
1127 | Восстановить нормальную задержку между ответами | — | — | — |
1128 | Удалить ресурсы | — | — | Удаление файла |
1129 | Невыясненная функциональность | — | — | — |
1126 | Невыясненная функциональность | — | — | — |
1114 | Получение писем из Gmail из Chrome | — | Поиск файлов:
Копирование файлов из Остановка всех процессов в десктопе Выполнение команды | |
1118 | Получить cookie Edge | См. 1014 | См. 1014 | См. 1014 |
1119 | Получить cookie Brave | См. 1014 | См. 1014 | См. 1014 |
1120 | Получить cookie Opera/OperaGX | См. 1014 | См. 1014 | См. 1014 |
1122 | Убить Brave, MS Edge, Chrome и Firefox | — | — | Останавливаются процессы:
|
1124 | Получение писем из Gmail из Brave | — | ||
1125 | Получение писем из Gmail из Edge | — | См. 1114 | |
1500 | Получить cookie другого браузера | Путь до файла с cookie | См. 1014 | См. 1014 |
1470 | Остановить реверс-шелл в PowerShell | — | — | Остановка процесса |
1480 | Выполнение команды PowerShell в цикле | — | Неизвестно (запрос 1489) | Поиск и удаление файла |
1482 | Скриншот в десктопе | — | — | Запуск процесса Запись в файл |
1487 | Перезапуск | — | — | Поиск файлов Запись в файлы:
|
1490 | То же самое, что и 1480 | — | См. 1480 | См. 1480 |
1491 | Убить процесс по PID | PID процесса | — | Остановка процесса из аргумента |
1492 | Остановить (suspend) процесс по PID | PID процесса | — |
|
1493 | Продолжить (resume) процесс по PID | PID процесса | — |
|
1494 | Перезапустить процесс | Путь к исполняемому файлу PID процесса | — | Остановка процесса из аргумента Запуск процесса из аргумента через |
1495 | Убить все процессы по имени | Имя процесса | — | Остановка всех процессов по имени |
1496 | Получить cookie Chrome | — | См. 1014 | См. 1014 Поиск файлов:
|
1497 | Получить cookie Brave | — | — | См. 1496 |
1498 | Получить cookie Edge | — | — | См. 1496 |
1499 | Получить cookie другого браузера | См. 1500 | См. 1500 | См. 1500 |
2002 | Установить обновление | Исполняемый файл (новая версия DarkGate) | — | Удаление файла Запись в файл |
1511 | Установка NetPass и кража кредов оттуда | Исполняемый файл NetPass Данные для записи в | Запись в файл Запись в файл Удаление файла | |
2000 | Обновление с использованием AutoIt | AU3-файл (новая версия DarkGate) | — | Запись в файл |
2001 | Обновление с использованием AutoIt | См. 2000 | См. 2000 | См. 2000 |
1507 | Исполнение бинарника с параметрами | Путь к файлу для инжекта Исполняемый файл Параметры запуска | — | Инжект первого типа |
1501 | Получение cookie других браузеров | См. 1500 | См. 1500 | См. 1500 |
1506 | Инжект шелл-кода с параметрами | См. 1507 (вместо исполняемого файла — шелл-код) | — | См. 1507 |
3041 | Запуск через | Название файла Контент файла | — | Запись в файл Запуск файла с использованием |
6666 | Не используется | — | — | — |
3017 | Обновление конфигурации | — | — | — |
2003 | Обновление | См. 2002 | См. 2002 | См. 2002 |
2004 | Удаление файла ресурсов | — | — | Удаление файла |
2005 | Удаление файла ресурсов | — | — | Удаление файла |