
بروتوكولات اكتشاف الوقت في Active Directory للفرق الحمراء. استخراج خفي عبر Kerberos، SMB، NTLM، وCLDAP.

skewrun هو مجموعة أدوات لاكتشاف وقت Active Directory للفرق الحمراء. يقوم بحل وقت وحدة التحكم بالمجال ديناميكيًا عبر بروتوكولات الشبكة (CLDAP، SMB، NTP، Kerberos، NTLM) وينفذ الأوامر عبر libfaketime (LD_PRELOAD)، مما يخدع الثنائي المنفذ لاستخدام وقت وحدة التحكم بالمجال تمامًا.
هذا يحل خطأ Kerberos KRB_AP_ERR_SKEW (فرق الساعة كبير جدًا)، مما يسمح لك بتشغيل أدوات مثل Impacket أو NetExec من جهاز Linux للهجوم تكون ساعته غير متزامنة بشدة مع مجال Windows الهدف، دون الحاجة إلى صلاحيات الجذر لتغيير وقت النظام.
بدءًا من v0.9.0، تم بناء Skewrun كهندسة المكتبة أولاً:
ad-time: صندوق مكتبة Rust نقية تستخرج الوقت من بروتوكولات AD بشكل خفي. يمكن تضمينها أصلاً في عمليات زرع أو أدوات Rust أخرى.skewrun: ثنائي CLI ينظم مكتبة ad-time ويغلف العمليات الهدف بـ libfaketime.# ثنائي ثابت مسبق البناء (لا حاجة لسلسلة أدوات Rust)
wget https://github.com/JVBotelho/skewrun/releases/latest/download/skewrun-x86_64-linux-musl
chmod +x skewrun-x86_64-linux-musl
sudo mv skewrun-x86_64-linux-musl /usr/local/bin/skewrun
# من crates.io
cargo install skewrun
# من المصدر
git clone https://github.com/JVBotelho/skewrun && cd skewrun && cargo build --release
ملاحظة: يجب أن يكون libfaketime مثبتًا على نظامك (مثلًا apt-get install libfaketime).
# السلوك الافتراضي (يحاول CLDAP -> SMB -> NTP)
skewrun 10.10.10.100 -- impacket-getTGT -dc-ip 10.10.10.100 domain.local/user:pass
# فرض طرق معينة
skewrun 10.10.10.100 -m cldap,ntlm,kerberos -- netexec smb 10.10.10.100
# فقط طباعة الإزاحة (مفيدة لتطوير النصوص البرمجية)
skewrun 10.10.10.100 --print-offset
# وضع دون اتصال: توفير إزاحة معروفة يدويًا
skewrun --offset "+3.450s" -- impacket-getTGT ...
# ضبط التشتت بين الطرق (الافتراضي: sigma=0.4, base=8000ms; sigma=0 يلغي التشتت)
skewrun 10.10.10.100 --jitter-sigma 0.2 --jitter-base-ms 5000 -- impacket-getTGT ...
use ad_time::protocols::cldap::CldapSource;
use ad_time::time_src::TimeSource;
use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let src = CldapSource;
let addr = "10.10.10.100:389".parse()?;
let offset_us = src.fetch(addr, Duration::from_secs(3))?;
println!("DC offset: {} µs", offset_us);
Ok(())
}
كل وحدة بروتوكول (kerberos، ntlm، cldap، smb، ntp) مستقلة وقابلة للاستخراج لاستخدامها في أدوات الفريق الأحمر المخصصة.
يقوم Skewrun بالاستعلام عن وحدة التحكم بالمجال لحساب الإزاحة الدقيقة بالميكروثانية (DC_Time - Local_Time). ثم يقوم بتعيين متغير البيئة FAKETIME وحقن libfaketime في الأمر الهدف باستخدام LD_PRELOAD.
يعتمد LD_PRELOAD على اعتراض استدعاءات libc المرتبطة ديناميكيًا (مثل clock_gettime). إذا حاولت استخدام skewrun على ثنائي مُجمَّع ثابت (مثل العديد من أدوات Go أو Rust)، فإن libfaketime سيفشل بصمت في ربط دوال الوقت. سيقوم Skewrun بتحذيرك إذا اكتشف أنك تحاول تشغيل ثنائي ثابت.
الهدف هو الاندماج مع حركة شبكة Windows القياسية وتقليل البصمة الجنائية على وحدة التحكم بالمجال.
بغض النظر عن الطريقة المستخدمة: كل مقبس خارجي يضبط TTL=128 ويفعل Nagle (TCP_NODELAY=0) قبل المصافحة TCP، مطابقًا لبصمة مكدس شبكة عميل Windows بدلاً من الإعدادات الافتراضية Linux (TTL=64، Nagle معطل) التي سيميزها مراقب سلبي (p0f، Zeek conn.log). التأخيرات بين الطرق تستخدم تشتت لوغاريتمي طبيعي مدعوم بـ CSPRNG (ليس نطاقًا عشوائيًا مسطحًا) مع تراجع أسي على الفشل المتكرر، متجنبًا التوقيع الزمني المنتظم الذي يتركه نطاق التشتت الثابت في سجلات الاتصال — راجع --jitter-sigma و --jitter-base-ms أعلاه.
cargo test # اختبارات الوحدة + الخاصية
cargo +nightly fuzz run fuzz_parse_krb_error # Linux/macOS only
جميع محللات الواجهة الشبكية (parse_krb_error، parse_cldap_search_response، parse_ntlm_type2،
parse_negotiate_response، parse_ntp_timestamp) تم اختبارها بالخاصية لسلامة الذعر باستخدام
proptest واختبار التشويش في CI.
ترميز BER الصحيح يتم التحقق منه لأدنى DER وصحة الإشارة عبر نطاق i32 الكامل،
تغطية قيم etype السالبة وفقًا لـ RFC 4120.
أهداف التشويش والمجموعة موجودة في fuzz/.
مرخّص بموجب ترخيص مزدوج MIT أو Apache 2.0 حسب اختيارك.
| الطريقة | البروتوكول | المنفذ | ملاحظات OPSEC (رؤية EDR/NDR) |
|---|
| cldap (افتراضي) | CLDAP | UDP/389 | خفي جدًا. مسموح به عالميًا. يرسل استعلام تشخيص LDAP rootDSE قياسي (بحث أساس objectClass=*)، مطابقًا لخط الأساس لـ ldapsearch، وأوامر PowerShell AD، وأدوات المراقبة. يخفف قائمة السمات بسمات إدارية شائعة ويوزع ترتيب السمات عشوائيًا لكل طلب لكسر توقيعات NDR الثابتة. |
| smb (افتراضي) | SMB2 | TCP/445 | خفي. يستخرج الوقت من استجابة SMB2 NEGOTIATE. يتفاوض SMB 3.1.1 مع PREAUTH_INTEGRITY_CAPABILITIES (SHA-512)، مطابقًا لسلوك عميل Windows 10/11. |
| ntp (افتراضي) | SNTP | UDP/123 | قياسي. RFC 4330 أصلي. حركة مرور متوقعة جدًا من أي عميل. |
| ntlm | SMB2 | TCP/445 | خفي. يستغل SMB2 SESSION_SETUP للحصول على تحدي NTLM من النوع 2 يحتوي على MsvAvTimestamp. يفصل TCP قبل النوع 3، مما يعني عدم إنشاء Event ID 4625 (فشل تسجيل الدخول). يحاكي أعلام Windows 10/11. |
| kerberos | Kerberos | TCP/88 | صاخب. يرسل AS-REQ لمستخدم غير موجود. يشفر sname ذو مكونين صحيحين، يدور cname (أخطاء مطبعية مثل admnistrator)، يضبط till على ثابت Windows المشفر 20370913024805Z (ليس حساب الساعة المحلية — انظر ADR-0002)، يوزع nonce عشوائيًا. دائمًا يولد Event 4768/0x6 (فشل ما قبل المصادقة لجهة غير معروفة) والذي يتم تصديره إلى SIEM بغض النظر عن سياسة المراجعة. قد يطلق تنبيهات حسابات العسل إذا تطابق cname مع مفخخة مهيأة. |