Всех приветствую. Сегодня разбираем DragonForce - группировку, которая за последние полтора года наделала шума больше, чем заслуживает по качеству своего тулкита. Давайте сначала в цифрах, а потом полезем внутрь бинаря и посмотрим, что там реально за "суперлокер".
По данным на июль 2026:
- 622 подтверждённых жертвы в 64 странах
- Первая жертва: 13 декабря 2023
- Последняя: буквально 3 часа назд от написания статьи
- Средняя задержка между атакой и публикацией: 19.8 дней
- 16.1% жертв имеют засвеченные доменные креды в инфостилерных логах (читай: initial access через купленные логи)
- +36% атак за последний месяц vs предыдущий
В апреле-мае 2025 именно DragonForce стояла за атаками на Marks & Spencer, Co-op и Harrods, крупнейших британских ритейлеров. M&S потерял более £300 миллионов, были слиты персональные данные клиентов. В 2025 году группировка ребрендилась в "ransomware cartel", по факту это white-label RaaS-платформа с 80/20 split в пользу аффилиатов. Рекламировались некоторое время на уже посмертном рампе, он и был их основной дислокацией.
SHA-256:
1ccf8baf11427fae273ffed587b41c857fa2d8f3d3c6c0ddaa1fe4835f665ebaMD5:
3a6e2c775c9c1060c54a9a94e80d923aSHA-1:
8f31f69f88a75d5faab4f94cfc2ec8a649fe1a24Скачал, распаковал из ZIP:
$ file *.exe
PE32 executable (GUI) Intel 80386, for MS Windows
$ stat --format="%s bytes" *.exe
428552 bytes
PE32, GUI, i386, 418 КБ. Для нативного C++ локера вполне стандартный размер. Важно: он не упакован packer'ом уровня UPX/VMProtect, то есть PE-структура, секции и таблица импортов читаются нормально. Но это не значит что обфускации нет вообще: строки и часть API-резолва спрятаны через ADVobfuscator/MurmurHash2A, до этого дойдём ниже. Subsystem GUI значит без консольного окна, типичный выбор для рансомвари, работающей в фоне. На VirusTotal 60+ детектов, popular threat label:
ransomware.dragonforce/conti. Microsoft детектит как Ransom:Win32/DragonForce.D, ESET как Win32/Filecoder.DragonForce.A.
asInvoker, бинарь НЕ просит UAC. Зачем, если можно украсть SYSTEM-токен? Об этом позже.Секции:
.text RawSize: 0x52000 VSize: 0x51F2C Entropy: 6.59 (код)
.rdata RawSize: 0xEE00 VSize: 0xEC38 Entropy: 5.48 (read-only данные, импорты)
.data RawSize: 0x2A00 VSize: 0x5C84 Entropy: 5.19 (данные, конфиг, RSA-ключ)
.rsrc RawSize: 0x200 VSize: 0x1E0 Entropy: 4.71 (ресурсы, манифест)
.reloc RawSize: 0x2600 VSize: 0x2558 Entropy: 6.53 (релокации)
Энтропия .text - 6.59, не упакован. Если бы использовался UPX или VMProtect, было бы 7.5+. Тут чистый нативный код, можно анализировать строками и дизассемблером напрямую. Отдельно после секции .reloc лежит 9736-байтный оверлей (данные за пределами PE-секций) с энтропией 7.98. Забегая вперёд, это не зашифрованный конфиг (как можно подумать по энтропии), а zlib-сжатые обои и иконка (на скрине выше). Типичная ошибка начинающих, увидел высокую энтропию ~> решил что шифрование. Нет, это просто PNG. В манифесте стоит
asInvoker. Это значит: бинарь не просит UAC-elevation, не показывает пользователю окошко "разрешить запуск от администратора?" и стартует с теми правами, которые уже есть у процесса/сессии. Для обычного легитимного софта это просто режим "не трогай UAC". Для локера это способ не шуметь на старте. Но ему всё равно нужны жирные права: останавливать сервисы, грузить драйвер, трогать Shadow Copies, ковырять ACL. Поэтому он идёт не через красивую UAC-кнопку, а через токены. В импортах есть OpenProcessToken, GetTokenInformation, LookupAccountSidW и CreateProcessW. Сценарий классический: пройтись по процессам, найти токен SYSTEM-процесса, проверить SID, и запустить себя/дочерний процесс уже с нужными правами. То есть asInvoker не значит "прав не нужно". Это значит "UAC не просим, работаем с тем что есть, а если нужно выше - ищем токен". В корпоративной сети после горизонтальной эскалации это часто не проблема: локер запускают уже из-под DA сессии, PsExec, scheduled task или сервиса. Поэтому окно UAC ему только мешало бы.На форуме про этот билд писали примерно так: "почему ваш супер-пупер шифровальщик который юзает драйвер использует API-функции из advapi32.dll для шифрования? неужели настолько лень было свой алгоритм писать?". И следом закономерный вопрос: "а разве у EDR нет хуков на эти функции? как он тогда вообще работает?". Разбираем.
Из ADVAPI32 импортируется:
CryptAcquireContextA - получить хендл CSP (криптопровайдера)
CryptImportKey - импортировать RSA-ключ из блоба
CryptEncrypt - зашифровать буфер (RSA-обёртка per-file ключа)
CryptGenRandom - сгенерировать рандомные байты (per-file ключ + IV)
OpenProcessToken - открыть токен процесса
GetTokenInformation - получить SID из токена
LookupAccountSidW - сопоставить SID с именем аккаунта
OpenSCManagerW - подключиться к SCM
OpenServiceW - открыть сервис
ControlService - остановить сервис
DeleteService - удалить сервис
QueryServiceStatus - проверить статус сервиса
RegOpenKeyExW - открыть ключ реестра
RegCreateKeyExW - создать ключ реестра
RegSetValueExW - записать значение
RegEnumKeyExW - перечислить подключи
RegQueryInfoKeyW - информация о ключе
RegCloseKey - закрыть ключ
InitializeSecurityDescriptor - инициализировать SD
SetSecurityDescriptorDacl - установить DACL (обнулить ACL на файлах)
Из криптографического всего четыре функции:
CryptAcquireContextA, CryptImportKey, CryptEncrypt, CryptGenRandom. Это стандартный Windows CryptoAPI, legacy-интерфейс из 1996 года. Работает через CSP (Cryptographic Service Provider), по дефолту Microsoft Enhanced RSA and AES Provider. Конкретно здесь CryptoAPI используется только для RSA-обёртки per-file ключей и генерации рандома. Само файловое шифрование это у них ChaCha8. И теперь главный вопрос, это дерьмо или нет?
CryptGenRandom под капотом дёргает BCryptGenRandom из CNG и RDRAND - CSPRNG нормальный, претензий нет. CryptEncrypt для RSA-4096 математика та же что и в OpenSSL. Но CryptoAPI - это документированный, хукабельный интерфейс. Любой EDR может поставить inline-хук на CryptEncrypt и перехватить per-file ключ в момент RSA-обёртки. ETW-провайдер CryptoAPI логирует вызовы. Максимум что сделали, зарезолвили крипто-функцию через GetProcAddress с шифрованной строкой, но в таблице импортов всё равно торчит остальное. "Стоп, так как он вообще работает на защищённых сетях если EDR может перехватить ключи?" - а вот так:
- Драйвер убивает EDR ДО начала шифрования.
DeviceIoControlс IOCTL0x22E044~> TrueSight.sys ~>ZwTerminateProcessиз ядра. Процесс EDR мёртв - хукать некому. - Не у всех жертв вообще стоит EDR. Малый и средний бизнес часто сидит на голом Windows Defender, который CryptoAPI-вызовы не перехватывает.
- Гарантии подавления антивируса нет. Может быть такое что драйвер загрузить просто не получится (HVCI, blocklist). И тогда, да, локер голый.
- Не запаривались над защитой от хуков - "кто хукать-то будет, если просто некому это делать" (с). Вся ставка на BYOVD.
По факту это осознанный компромисс: зачем писать свою криптографию, если драйвер убьёт всё что может помешать? Ленивый подход, но работает, пока жертвы сидят на Windows Server 2016/2019 без HVCI. Для сравнения: LockBit не использует CryptoAPI вообще. У них свой curve25519 + AES-NI в коде, без единого вызова в advapi32. Нет API-вызова - нечего хукать, даже если EDR жив. DragonForce же просто взял готовое из Conti, где криптосхема была написана в 2020-2021 году, когда CryptoAPI-мониторинг ещё не был стандартом. И не стал переписывать.
Гибридная схема:
- Per-file:
CryptGenRandomгенерирует 256-бит ключ + 64-бит nonce - Файл шифруется ChaCha8 (8 раундов, не 20) - быстрее в 2.5 раза
- Ключ+nonce оборачиваются RSA-4096 через
CryptImportKey+CryptEncrypt - 512-байтный RSA-блоб дописывается в конец файла
RSA-4096 публичный ключ вкомпилен в .data секцию:
Offset: 0x61CE0
Format: PUBLICKEYBLOB (Microsoft CryptoAPI)
bType: 0x06 (PUBLICKEYBLOB)
bVersion: 0x02
aiKeyAlg: 0x0000A400 (CALG_RSA_KEYX)
Magic: RSA1
BitLen: 4096
PubExp: 65537 (0x10001)
Modulus: 576cba469fc4bda4...1da93bf7 (512 bytes)
Приватный ключ только у оператора. Без него файлы не расшифровать, математически невозможно факторизовать 4096-битный модуль. Вся эта схема абсолютная копипаста из Conti V3. Один в один. ChaCha8 вместо ChaCha20, RSA через CryptoAPI,
CryptGenRandom для рандома. Ни строчки оригинального крипто-кода. Они просто используют слитый в 2022 году исходник Conti, где всё это уже было написано за них.
Теперь про "драйвер который убивает EDR". В импортах есть
DeviceIoControl, функция для отправки IOCTL-запросов к драйверам ядра. Нашли константу 0x22E044 по смещению 0x1E620 в секции .text:IOCTL 0x22E044 - TrueSight.sys (RogueKiller Antirootkit Driver)
Это техника BYOVD (Bring Your Own Vulnerable Driver). Работает так: малварь притаскивает легитимный подписанный драйвер с известной уязвимостью, загружает его как сервис через SCManager, и через IOCTL отправляет команду "убей процесс X". Драйвер работает в ядре, поэтому может убить даже Protected Process Light (PPL), - то есть Windows Defender, CrowdStrike, SentinelOne.
НО. И вот тут важный момент, который обычно опускают в хайп-постах:
- Драйвер НЕ должен быть встроен в этот же EXE.
- Драйвер должен быть доставлен отдельно. Либо дропается на этапе post-exploitation, либо скачивается с C2, либо уже лежит на диске.
- Загрузка драйвера требует привилегий SYSTEM или SeLoadDriverPrivilege. Без предварительного LPE, ничего не работает.
- Windows 11 с HVCI (Hypervisor-protected Code Integrity) блокирует загрузку известных уязвимых драйверов через blocklist. Microsoft обновляет список регулярно.
То есть "неубиваемый EDR-киллер через драйвер" - это: а) не работает без предварительной эскалации, б) не работает на обновлённых Windows 11 с HVCI, в) палится при загрузке. В реальных атаках DragonForce это работает потому что жертвы сидят на Windows Server 2016/2019 без HVCI, а не потому что техника гениальная.
Stream 1 @ offset 0: ICO, 64x64, 32bpp (16958 bytes после декомпрессии)
Stream 2 @ offset 2340: PNG, 2048x1080, RGBA (17828 bytes после декомпрессии)
PNG - это обои, которые ставятся после шифрования через
SystemParametersInfoW. 2048x1080 разрешение под стандартный Full HD. Обои не зашифрованы, просто сжаты, потому что в PE нет смысла хранить 17 КБ несжатого PNG.
В бинаре практически нет читаемых строк, связанных с поведением малвари. Никаких имён процессов, никаких расширений, никаких путей. Только CRT-мусор, RTTI-дескрипторы (
.?AVlogic_error@std@@ и подобные) и импортированные имена функций. Обфускация строк это ADVobfuscator (compile-time XOR, строки собираются на стеке по байту через mov byte ptr). За резолв API отвечает MurmurHash2A (10 вхождений константы 0x5BD1E995 в .text). Один в один как в оригинальном Conti V3. Ничего нового. И вот тут, ключевой момент для критики. ADVobfuscator скрывает строки от strings, но НЕ от динамического анализа. В рантайме строки расшифровываются на стеке, если поставить hardware breakpoint на доступ к стеку или просто снять дамп памяти после инициализации, все строки видны открытым текстом. MurmurHash2A скрывает имена API, но 125 функций из KERNEL32 лежат прямо в IAT (Import Address Table). То есть бóльшая часть API не скрыта вообще. DeviceIoControl, CryptEncrypt, TerminateProcess, NetShareEnum, всё прямо в импортах. Для сравнения: у LockBit вся таблица импортов состоит из 2-3 функций (GetProcAddress, LoadLibraryA, VirtualAlloc), а остальные ~200 API резолвятся динамически через хеши. У DragonForce же в IAT лежат 180+ функций, по ним можно восстановить 80% поведения вообще без запуска. Что мы, собственно, и сделали.
KERNEL32.dll - 125 функций (файлы, процессы, потоки, память, IOCP)
ADVAPI32.dll - 21 функция (крипто, токены, реестр, сервисы)
WS2_32.dll - 15 функций (сокеты, сетевое сканирование)
RstrtMgr.DLL - 5 функций (разблокировка файлов)
ole32.dll - 5 функций (COM/WMI для удаления теневых копий)
OLEAUT32.dll - 4 функции (автоматизация COM)
USER32.dll - 2 функции (смена обоев)
NETAPI32.dll - 2 функции (перечисление SMB-шар)
SHLWAPI.dll - 2 функции (поиск подстрок)
SHELL32.dll - 1 функция (парсинг командной строки)
IPHLPAPI.DLL - 1 функция (ARP-таблица)
Первый блок - файловая система и параллельное шифрование.
GetLogicalDriveStringsW даёт список дисков, FindFirstFileW / FindNextFileW обходят каталоги, ReadFile / WriteFile работают с содержимым. Но шифровать по одному файлу в одном потоке - это для школьных поделок. Здесь импортированы CreateIoCompletionPort, GetQueuedCompletionStatus и PostQueuedCompletionStatus - I/O Completion Ports. Это та же модель, которую использовал Conti: один поток накидывает задания, воркеры забирают их из очереди и параллельно шифруют файлы. Количество воркеров считается через GetNativeSystemInfo, то есть по числу ядер. Второй блок - зачистка процессов и сервисов перед шифрованием. CreateToolhelp32Snapshot + Process32FirstW / Process32NextW перечисляют процессы, OpenProcess открывает хендл, TerminateProcess убивает из user-mode. Для сервисов используется Service Control Manager: OpenSCManagerW, OpenServiceW, ControlService, DeleteService. То есть SQL, Exchange, Veeam, бэкапы и офисные приложения можно остановить до того, как они успеют удержать файлы открытыми. Если файл всё равно залочен, подключается Restart Manager: RmStartSession, RmRegisterResources, RmGetList, RmShutdown. Это нормальный Windows API, который показывает какой процесс держит конкретный файл. Локер регистрирует файл, получает список блокирующих процессов и прибивает именно их. Не надо убивать всё подряд - можно точечно снять блокировку с базы, PST или документа. Третий блок - привилегии. OpenProcessToken, GetTokenInformation и LookupAccountSidW нужны для поиска SYSTEM-токена. Манифест у бинаря asInvoker, UAC он не просит. Логика простая: найти процесс с SYSTEM-токеном, украсть/использовать его и перезапустить себя через CreateProcessW уже с более жирными правами. Для загрузки драйвера и ковыряния сервисов это критично. Четвёртый блок - сеть. GetIpNetTable из IPHLPAPI читает ARP-таблицу: там уже есть машины, с которыми хост общался в локалке. Не нужно громко сканировать подсети - можно взять готовый список соседей из ARP-кэша. Дальше NetShareEnum перечисляет SMB-шары, а WS2_32 (WSASocketW, WSAIoctl, WSAAddressToStringW) даёт сетевые подключения и конвертацию адресов. Так локер добирается не только до локальных дисков, но и до сетевых шар. Пятый блок - anti-recovery. Через ole32 импортированы CoInitializeEx, CoCreateInstance, CoSetProxyBlanket - это COM/WMI-обвязка для работы с Shadow Copies. Вместо тупого запуска vssadmin.exe, который палится с полпинка, можно ходить через WMI-интерфейсы. SetFileAttributesW сбрасывает readonly/hidden/system-атрибуты, а InitializeSecurityDescriptor и SetSecurityDescriptorDacl позволяют играться с ACL, фактически обнуляя доступы на нужных объектах.
LIMB