4624'ten DCSync’e: bir lateral movement avcısı inşa etmek
crabwalk: MITRE ATT&CK’e maplenen, ground-truth corpus’a karşı doğrulanmış açık kaynak bir DFIR aracı
İçindekiler
- Problem: lateral movement triyajı neden zor?
- Mevcut araçlardan farkı
- Nasıl çalışıyor: dört aşamalı bir hat
- 1) parse — gürültüyü at, normalize et
- 2) sessions — asıl zekâ burada
- 3) hunt — kural motoru
- 4) report + layer — çıktıyı insana sun
- Rigor: doğrulama olmadan bu bir oyuncak olurdu
- Tasarım kararları ve öğrendiklerim
- Denemek isterseniz
- Kapanış
Bir kuruma sızıldıktan sonra her SOC ve DFIR ekibi aynı soruyu sorar: Saldırgan ilk nereye düştü, oradan nereye gitti?
Bu sorunun cevabı tek bir logda yatmaz. 4624/4672 logon desenlerini, RDP oturum zincirlerini, uzaktan kurulan servisleri, zamanlanmış görevleri ve host’lar arası WinRM/WMI çalıştırmalarını üst üste koyup birleştirmeniz gerekir. Onlarca makinenin Windows Event Log’unu elle tarayıp bu ipuçlarını zihninizde bir zaman çizelgesine dizmek, olay müdahalesinin en yavaş ve en hataya açık kısmıdır.
crabwalk tam bu triyaj adımını otomatikleştirmek için yazdığım bir araç. Windows EVTX loglarını parse ediyor; logon, servis, zamanlanmış görev ve PowerShell aktivitesini tek bir saldırı zaman çizelgesinde korele ediyor; ve bulduğu her şeyi MITRE ATT&CK tekniklerine haritalıyor. Adı da buradan geliyor: yengeçler yana yürür — saldırganlar da lateral (yanal) hareket eder.
Bu yazıda aracı neden bu şekilde tasarladığımı, mevcut araçlardan nerede ayrıldığını ve iç mimarisini adım adım anlatacağım.
(Repo: https://github.com/IlkerUnver00/crabwalk — MIT lisanslı, Python.)
Problem: lateral movement triyajı neden zor?
Modern bir saldırıda ilk erişim çoğu zaman sadece başlangıçtır. Asıl hasar, saldırganın ağ içinde yatay olarak ilerleyip ayrıcalık yükseltmesiyle oluşur. Bu hareketin izi Windows olay loglarına dağınık halde düşer:
- Logon desenleri — 4624 (başarılı logon), tipi (network, RDP, batch), 4672 (ayrıcalıklı logon), 4648 (açık kimlik bilgisiyle logon).
- Uzaktan çalıştırma — 7045/4697 (servis kurulumu, PsExec deseni), 4698/4702 (zamanlanmış görev), WMI ve WinRM aktivitesi.
- Kimlik bilgisi kötüye kullanımı — pass-the-hash, Kerberoasting, DCSync.
Sorun şu ki bu olayların hiçbiri tek başına anlam ifade etmez. “Bir servis kuruldu” tek başına gürültüdür; ama uzak bir oturumdan hemen sonra kurulan bir servis PsExec ile lateral movement demektir. Anlam, olayların aralarındaki ilişkide ve sıralamasında gizlidir. İşte bu yüzden per-event (olay bazlı) bakış bu problemi tam çözmez.
Mevcut araçlardan farkı
Bu alanda güçlü araçlar zaten var — Chainsaw ve Hayabusa gibi. Bunlar EVTX üzerinde genel Sigma kurallarını olay bazında çalıştırır: her olayı ayrı ayrı bir imzayla eşleştirirler. Son derece işe yarar, ama tek bir olaya bakarlar.
crabwalk daha dar ama daha derin bir şey yapıyor: imza eşleştirmesi değil, durum bilgili (stateful), host’lar arası korelasyon. Yani tek tek olayları değil, olayların oluşturduğu oturum zincirlerini takip ediyor. “A host’undan B’ye geçildi, B’de ayrıcalık yükseltildi, oradan C’ye bir servis kuruldu” gibi bir hikâyeyi, olayları birbirine bağlayarak kuruyor.
Bu ayrımı aklımda hep şöyle tuttum: Chainsaw “bu olay şüpheli mi?” sorusunu sorar; crabwalk “bu olaylar birlikte bir lateral movement anlatıyor mu?” sorusunu sorar.
Nasıl çalışıyor: dört aşamalı bir hat
crabwalk bir boru hattı (pipeline) olarak tasarlandı. Dört CLI komutu, ham logdan okunabilir bir rapora kadar akışı taşıyor:
crabwalk parse C:\evidence\logs --out timeline.jsonl
crabwalk sessions C:\evidence\logs --out sessions.json
crabwalk hunt C:\evidence\logs --out findings.json
crabwalk hunt C:\evidence\logs --report report.html --layer navigator.json
1) parse — gürültüyü at, normalize et
İlk adım EVTX dosyalarını (tek dosya ya da tüm klasör) parse edip zamana göre sıralı, normalize bir olay akışına dönüştürmek. Burada bilinçli bir tercih yaptım: varsayılan olarak her şeyi değil, sadece lateral movement için anlamlı olayları tutuyorum — 10 farklı log kanalında ~45 olay ID’lik özenle seçilmiş bir katalog. (--all, --event-id, --channel ile bu davranışı ezebilirsiniz.) Böylece 37 bin kayıtlık bir corpus, önemli olan birkaç yüz olaya iniyor.
2) sessions — asıl zekâ burada
crabwalk’un kalbi oturum takip modeli. Her host için LogonId yaşam döngülerini yeniden kuruyorum: bir oturum ne zaman açıldı, hangi tip logon’du, ne zaman kapandı. Ardından bu oturumların üzerine kenarları (edge) çiziyorum:
- Inbound uzak logon kenarları — 4624/RDP ile “dışarıdan bu host’a girildi”.
- Outbound açık-kimlik kenarları — 4648 ile “bu host’tan başka bir host’a kimlik bilgisiyle gidildi”.
- Ayrıcalık backfill — 4672’den gelen ayrıcalık bilgisini ilgili oturuma geri işliyorum.
Sonuç, host’tan host’a hareket haritası:
sessions : 20 total | 12 remote | 3 privileged+remote
edges : 13 shown (2 machine-account edges hidden, --include-machine)
HOST-TO-HOST MOVEMENT
2019-03-18 11:27:23Z EXAMPLE.CORP\administrator PC01 -> WIN-77LTAPHIQ1R explicit-credentials
2019-03-19 00:02:04Z EXAMPLE\Administrator 10.0.2.17 -> WIN-77LTAPHIQ1R network priv
Bu tablo tek başına bile bir analistin dakikalarını saniyeye indiriyor: kim, ne zaman, nereden nereye gitti — hepsi tek bakışta.
3) hunt — kural motoru
Oturum ve kenar durumunun üzerine 11 tespit kuralı çalıştırıyorum. Her bulgu tekilleştiriliyor (dedup), önem sırasına göre sıralanıyor ve ATT&CK teknik ID’leriyle etiketleniyor:
| Kural | Başlık | ATT&CK |
|---|---|---|
| CW-001 | Uzak logon sonrası servis kurulumu | T1021.002, T1543.003 |
| CW-002 | Host’lar arası RDP zinciri | T1021.001 |
| CW-003 | Pass-the-hash göstergeleri | T1550.002 |
| CW-004 | Uzak oturumdan zamanlanmış görev | T1053.005 |
| CW-005 | Yönetimsel paylaşımda çalıştırılabilir | T1021.002, T1570 |
| CW-006 | WMI üzerinden process başlatma | T1047 |
| CW-007 | WinRM üzerinden uzaktan çalıştırma | T1021.006 |
| CW-008 | Şüpheli PowerShell script block | T1059.001 |
| CW-009 | Olay logu temizlenmesi | T1070.001 |
| CW-010 | Kerberoasting (RC4 servis bileti) | T1558.003 |
| CW-011 | DCSync (dizin replikasyonu) | T1003.006 |
Kuralların çoğu tek bir olaya değil, bir olay + bir duruma bakıyor. Örneğin CW-001, bir servis kurulumunu ancak uzak bir oturumla ilişkilendirebiliyorsa PsExec deseni olarak işaretliyor; bilinen araç servis adlarını gördüğünde önemi “critical”a çekiyor. CW-006 ise WmiPrvSE’nin çocuğu olan process’leri takip ediyor — bir shell doğduğunda alarm veriyor:
[HIGH] 2019-08-30 12:54:08Z CW-006 Process spawned via WMI
host: MSEDGEWIN10 user: MSEDGEWIN10\IEUser ATT&CK: T1047
WmiPrvSE.exe (WMI) spawned 'rundll32 ...comsvcs.dll, MiniDump 4868 ...'
Bu tek bulguda hem WMI ile uzaktan çalıştırma (T1047) hem de comsvcs.dll MiniDump ile LSASS dump girişimi yakalanıyor — klasik bir credential access hamlesi.
4) report + layer — çıktıyı insana sun
Son aşama iki çıktı üretiyor. --layer ile bulguları tekniğe göre skorlayan bir ATT&CK Navigator layer dosyası çıkıyor; bunu Navigator’da açtığınızda saldırının ATT&CK üzerindeki ısı haritasını görüyorsunuz.
--report ile de tek dosyalık, kendi kendine yeten bir HTML raporu üretiliyor: istatistik kutuları, önem (severity) çubuğu, ATT&CK tablosu, host başına swimlane zaman çizelgesi (satır içi SVG), hareket tablosu ve sıralı bulgu kartları. Dış bağımlılık yok, tek dosya, açık/koyu temaya duyarlı.

Bu “tek dosya, dış asset yok” kararı estetik değil, pratik: DFIR iş istasyonları çoğu zaman izole ve internetsizdir. Raporu bir USB’ye atıp başka bir makinede açabilmelisiniz.
Rigor: doğrulama olmadan bu bir oyuncak olurdu
Bir tespit aracının en tehlikeli hali, ne kaçırdığını bilmeden “çalışıyor gibi görünmesidir”. Bu yüzden crabwalk’u bir ground-truth corpus’a karşı regresyon testine bağladım: EVTX-ATTACK-SAMPLES.
Bu corpus’un güzelliği şu: her örnek dosyanın adı, gösterdiği tekniği söylüyor — LM_renamed_psexecsvc_5145.evtx (T1021.002), sysmon_10_1_memdump_comsvcs_minidump.evtx (T1047), DE_1102_security_log_cleared.evtx (T1070.001) gibi. Test de basitçe şunu doğruluyor: crabwalk bu dosyayı doğru tekniğe maplemek zorunda. Ayrı bir smoke test ise tüm corpus’u (156 dosya, 37 binden fazla kayıt) parse ediyor ve tek bir parse edilemeyen kayıtta bile başarısız oluyor.
Tüm corpus üzerinde crabwalk 9 teknikte 47 bulgu üretiyor — wmiexec’in cmd.exe /Q /c ... 1> \\127.0.0.1\ADMIN$\... imzası, sekurlsa::pth logon’ları ve WMI üzerinden başlatılan bir LSASS dump’ı dahil.
Bu doğrulama süreci bana bedava iki bug da hediye etti: null kayıt zaman damgaları ve #attributes iç içe geçme problemi. İkisini de düzelttim ve olay seviyesinde dedup ekledim. Testler olmasa bu hataları hiç fark etmeyecektim — projenin bana öğrettiği en net ders bu oldu.
Tasarım kararları ve öğrendiklerim
Kod satırlarından çok, birkaç prensip bu aracın karakterini belirledi:
Minimum bağımlılık. DFIR iş istasyonları sıklıkla çevrimdışıdır; pip install’ın internete gitmesini bekleyemezsiniz. Bu yüzden tek çalışma-zamanı bağımlılığı Rust tabanlı evtx parser’ı. Sadelik, burada bir özellik.
Kirli girdi normaldir. Gerçek dünya logları bozuktur. Parse edilemeyen kayıtlar sayılıyor ve raporlanıyor ama asla programı öldürmüyor. Bir olay kanıtını tek bozuk kayıt yüzünden komple kaybetmek kabul edilemez.
Her yerde UTC. Zaman damgaları parse anında UTC’ye normalize ediliyor. Host’lar arası korelasyon yapan bir araçta saat dilimi karmaşası, sessizce yanlış zaman çizelgeleri üretir — bu da en kötü hata türüdür, çünkü doğru görünür.
Denemek isterseniz
pip install -e .
crabwalk hunt C:\evidence\logs --report report.html --layer navigator.json
Corpus’a karşı çalıştırmak için:
git clone --depth 1 https://github.com/sbousseaden/EVTX-ATTACK-SAMPLES.git samples/EVTX-ATTACK-SAMPLES
pytest tests/test_corpus.py -v
Proje MIT lisanslı ve GitHub Actions CI ile Python 3.10–3.12 üzerinde test ediliyor. Kod, açık uçlar ve geri bildirime açık:
👉 https://github.com/IlkerUnver00/crabwalk
Kapanış
crabwalk’u yazma amacım sadece bir araç üretmek değildi; lateral movement’ın Windows loglarına nasıl yansıdığını elimle öğrenmekti. Bir saldırının izini olay olay değil, oturum oturum takip etmek, DFIR’a bambaşka bir açıdan bakmamı sağladı.
Eğer siz de blue team / threat hunting tarafında çalışıyorsanız, bir tespit fikrini alıp ground-truth veriye karşı doğrulayana kadar götürmenin ne kadar öğretici olduğunu tavsiye ederim. Geri bildirimlerinizi, yeni kural fikirlerinizi ve kaçırdığım desenleri duymak isterim — repo’da issue açmaktan çekinmeyin.
Yengeçler yana yürür. Saldırganlar da. Umarım crabwalk onları bir adım önce yakalamanıza yardımcı olur.