Как работает DarkGate: подробный технический анализ
Сразу после запуска будет показано отладочное сообщение external debugg. Этим можно маркировать начало работы самой полезной нагрузки.
DarkGate подгружает для своей работы следующий набор библиотек:
kernel32.dllUrlmon.dlluser32.dllAdvapi32.dllShell32.dllntdll.dll
Причем в случае с последней он делает это, читая файл ntdll.dll и самостоятельно загружая его в память.
Этап подгрузки библиотек заканчивается отладочным сообщением external debugg 2.
Далее идет проверка имени пользователя (используется функция GetUserNameA), от которого запущен DarkGate.
Если имя пользователя — SYSTEM, то выставляется глобальная переменная, отвечающая за работу с системными привилегиями, а также проверяется наличие файла C:\temp\ssy. Если такой файл существует, то DarkGate завершает свою работу.
Если имя пользователя SafeMode, то выставляется глобальная переменная, отвечающая за работу от имени пользователя SafeMode.
После проверки имени пользователя загружается конфигурация DarkGate. Пример конфигурации с описанием каждого параметра следует ниже:
0=80 //Порт, который будет использоваться для подключения к C21=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 происходила с помощью AU312=No //Поставка DarkGate происходила с помощью DLL13=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. Используются такие системные вызовы, как:NtGetContextThreadNtReadVirtualMemoryNtUnmapViewOfSectionNtAllocateVirtualMemoryNtWriteVirtualMemoryNtProtectVirtualMemoryNtFlushInstructionCacheNtSetContextThreadNtResumеThreadNtFreeVirtualMemoryNtTerminateProcess
- Функция, которая обрабатывает процесс инжекта, принимает в качестве аргумента путь до исполняемого файла для инжекта в него и аргументы, с которыми этот процесс будет запущен. По умолчанию путь и аргументы у процесса —
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.exeC:\Program Files (x86)\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exeC:\Program Files (x86)\BraveSoftware\Update\BraveUpdate.exeC:\Program Files (x86)\Common Files\Microsoft Shared\ink\TabTip32.execmd.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 | Удаление файла ресурсов | — | — | Удаление файла |