Arkadaşlar yeniden merhaba. Bir red team senaryosu kurguladınız diyelim. Kodunuz çalışıyor, test ortamında mükemmel. Ama hedef sistemde tetiklediğiniz anda ekran kararıyor, process öldürülüyor ve SIEM'e alarm düşüyor. Peki ne oldu neden böyle oldu? tabiki EDR devreye girdi. Endpoint Detection and Response sistemleri, modern siber güvenliğin en güçlü savunma katmanlarından biridir. Peki bu sistemler nasıl çalışıyor? Neyi görüyor, neyi görmüyor? Kör noktaları nerede? Bu yazımda EDR bypass teorisini, savunma mekanizmalarının anatomisini ve saldırganların bu mekanizmaları teorik olarak nasıl analiz ettiğini detaylıca anlatacağım. İyi okumalar.
EDR Nedir ve Ne Görür?
EDR (Endpoint Detection and Response), uç nokta cihazlarında gerçek zamanlı olarak davranışları izleyen, şüpheli aktiviteleri tespit eden ve otomatik müdahale yapabilen güvenlik yazılımı. Crowdstrike Falcon, Microsoft Defender for Endpoint, SentinelOne, Carbon Black, Elastic EDR bunların en yaygın örnekleri.
Geleneksel antivirüs ile EDR arasındaki fark kritik. Antivirüs imzaya bakar: "Bu dosyanın hash'i bilinen zararlı yazılımların listesinde mi?" sorusunu sorar. Bu yaklaşım yıllarca işe yaradı ama saldırganlar çok basit tekniklerle dosyayı değiştirmeye, hash'i farklılaştırmaya başladı. EDR ise dosyaya değil davranışa bakıyor: "Bu process ne yapıyor? Hangi API'ları çağırıyor? Hangi bellek bölgelerine yazıyor? Hangi dosyalara dokunuyor? Ağda kiminle konuşuyor?" sorularını soruyor.
EDR'in veri toplama noktaları şunlar. Userland API Hooking: Windows API fonksiyonlarının başına kendi kodu enjekte ediyor, her çağrıyı izliyor. Kernel Callback'ler: Windows çekirdeğinin sağladığı bildirim mekanizmalarına kayıt oluyor; process oluşturma, thread oluşturma, image yükleme gibi olayları kernel seviyesinde alıyor. ETW (Event Tracing for Windows): Microsoft'un yerleşik telemetri sistemi; kernel olaylarını, ağ olaylarını ve uygulama davranışlarını yüksek performanslı şekilde akıtıyor. Minifilter Sürücüleri: Dosya sistemi operasyonlarını kernel katmanında izliyor. Bu dört veri kaynağının tamamını kesen bir EDR son derece geniş görüş alanına sahip.
Userland Hooking — EDR'in Gözleri
EDR'in en yaygın izleme yöntemi userland hooking, yani kullanıcı alanındaki API kancalaması. Bunu anlamak için Windows'un API çağrı zincirini bilmek gerekiyor.
Bir uygulama VirtualAlloc gibi bir Windows API fonksiyonunu çağırdığında şu zincir işliyor: uygulama → kernel32.dll → ntdll.dll → sistem çağrısı (syscall) → Windows Kernel. Bu zincirin en alt katmanı ntdll.dll, çünkü burası kullanıcı alanından kernel'e geçişin yapıldığı son durak. EDR çoğunlukla ntdll.dll içindeki fonksiyonların başına kendi kodunu yerleştiriyor. Bu koda hook (kanca) deniyor.
Teknik olarak şöyle çalışıyor: ntdll.dll belleğe yüklendiğinde fonksiyonların başındaki birkaç byte EDR tarafından değiştiriliyor. Oraya bir JMP (Jump) talimatı ekleniyor. Bu JMP, kontrolü EDR'in kendi analiz fonksiyonuna gönderiyor. EDR parametreleri inceliyor, davranış şüpheliyse engelleme yapıyor, değilse asıl API'ya devam ediyor. Bu süreç uygulamadan tamamen gizli; uygulama API'yı çağırdığını zannediyor ama aslında önce EDR'in denetimine giriyor.
Unhooking — Hook Temizleme Teorisi
Userland hook'un bir zayıflığı var: EDR kancayı yalnızca belleğe yüklenmiş ntdll.dll kopyasına ekliyor. Disk üzerindeki orijinal ntdll.dll dosyasına dokunamıyor. Bu, bypass teorisinin temel taşı olan unhooking kavramının doğduğu nokta.
Teorik çalışma mantığı şöyle: disk üzerindeki temiz ntdll.dll dosyasını oku, yani hiç belleğe yüklenmemiş orijinal dosyayı. Şu an bellekte hook'lanmış olan fonksiyonların orijinal byte'larını bu dosyadan al. Hook edilen byte'ların üzerine orijinal byte'ları yaz. Artık bellekteki ntdll.dll temiz, EDR'in kancaları yok.
Bu tekniğin birkaç varyantı var. Full DLL Unhooking: ntdll.dll'in tamamını diskten okuyup bellekteki kopyayla değiştirmek. Selective Unhooking: Yalnızca ihtiyaç duyulan fonksiyonların hook'larını temizlemek; daha az gürültülü. Indirect Syscall: ntdll.dll'e hiç dokunmadan, doğrudan kernel'e sistem çağrısı yapmak. Bu üçüncü yaklaşım en temiz ve en az tespit edilebilir olanı.
Ama hemen belirtmeliyim: modern EDR'ler bu tekniklere karşı da gelişti. Kernel callback'leri userland hook'lardan bağımsız çalışıyor. Bellekteki ntdll kopyasını değiştirmeye çalışan bir işlem bile kendi başına şüpheli bir davranış olarak işaretlenebiliyor.
Kernel Callback'ler — EDR'in Derinlerdeki Gözleri
Userland hook'ların aşılabildiğini gören EDR üreticileri çok daha derin bir katmana indi: Windows kernel'in kendi bildirim mekanizmaları. Kernel callback sistemi, Microsoft'un güvenlik yazılımlarına sağladığı resmi bir API. EDR sürücüsü bu callback'lere kaydolduğunda, kernel her kritik olay gerçekleştiğinde EDR'i doğrudan bilgilendiriyor.
En önemli kernel callback türleri şunlar. PsSetCreateProcessNotifyRoutineEx: Her yeni process oluşturulduğunda tetikleniyor. Hangi process hangi kullanıcı bağlamında kim tarafından oluşturuldu, başlangıç parametreleri neler — hepsi burada. PsSetCreateThreadNotifyRoutine: Her thread oluşturulduğunda tetikleniyor. Remote thread enjeksiyonu bu callback'le tespit ediliyor. PsSetLoadImageNotifyRoutine: Bir DLL veya çalıştırılabilir dosya belleğe yüklendiğinde tetikleniyor. CmRegisterCallback: Registry okuma ve yazma işlemlerini izliyor. ObRegisterCallbacks: Process ve thread handle'larına yapılan erişimleri izliyor; LSASS gibi korunan process'lere handle açma girişimlerini yakalar.
Kernel callback'lerin userland hook'lardan farkı şu: bunlar kernel içinde çalışıyor ve kullanıcı alanındaki herhangi bir manipülasyondan etkilenmiyor. ntdll hook'larını tamamen temizlemiş olsanız bile yeni bir process oluştururken PsSetCreateProcessNotifyRoutineEx tetiklenecek ve EDR sizi görecek.
ETW Patching — Telemetri Köreltme Teorisi
ETW (Event Tracing for Windows), Microsoft'un işletim sistemine gömülü yüksek performanslı telemetri sistemi. Kernel olayları, ağ bağlantıları, process davranışları, PowerShell komutları — hepsi ETW kanalları üzerinden akıyor. EDR'lerin büyük çoğunluğu ETW'ye abone olarak bu veri akışını dinliyor.
ETW'nin özellikle kritik bir kanalı var: Microsoft-Windows-Threat-Intelligence (TI) provider. Bu kanal process injection, LSASS belleği okuma ve kod enjeksiyonu gibi tehlikeli davranışları kernel seviyesinde raporluyor. Normal ETW kanallarının aksine bu kanal yalnızca PPL (Protected Process Light) yetkisiyle çalışan süreçler tarafından okunabiliyor; yani EDR'in sürücüsü bu yetkiye sahip.
ETW patching teorisi ne? ntdll.dll içindeki ETW olaylarını üreten fonksiyon olan EtwEventWrite ve EtwEventWriteFull fonksiyonlarının başına bir RET (return) talimatı yerleştirilirse, fonksiyon çağrıldığında hiçbir şey yapmadan geri dönüyor. Telemetri üretilmiyor, EDR'e veri gitmiyor.
Ama bu yaklaşımın da modern EDR'ler tarafından izlendiğini belirtmeliyim. EtwEventWrite fonksiyonuna yazma girişimi kendi başına şüpheli bir davranış. Ayrıca kernel-mode ETW kanalları bu manipülasyondan etkilenmiyor; yalnızca userland ETW provider'ları susturuluyor.
AMSI Bypass — Script Motorlarının Kalkanını Aşmak
AMSI (Antimalware Scan Interface), Microsoft'un PowerShell, VBScript, JScript ve WMI gibi script motorlarına entegre ettiği tarama arayüzü. Script çalıştırılmadan hemen önce AMSI devreye giriyor, içeriği EDR'e (veya antivirüse) gönderiyor ve yanıt bekliyor. Zararlı içerik tespit edilirse script çalıştırılmıyor.
Bu neden bu kadar önemli? Fileless malware, PowerShell tabanlı saldırılar ve living-off-the-land teknikleri disk üzerine hiçbir şey yazmıyor; doğrudan bellekte çalışıyor. Geleneksel dosya taraması bunları yakalamıyor. AMSI bu boşluğu kapatıyor.
AMSI bypass teorisi userland hooking mantığının bir varyantı. amsi.dll içindeki AmsiScanBuffer ve AmsiScanString fonksiyonları, script motorlarının içerikleri EDR'e göndermek için çağırdığı fonksiyonlar. Bu fonksiyonların başına bir patch eklenirse veya dönüş değeri her zaman "temiz" döndürülürse, EDR gerçek içeriği hiç görmüyor.
Peki bu bypass yöntemleri neden çalışmaya devam edebiliyor? Çünkü AMSI temelde bir userland mekanizması. Kernel seviyesinde zorunlu değil, script motorlarının isteğe bağlı olarak çağırdığı bir arayüz. Bu yapısal sınırlama AMSI'nin en önemli zayıflığı. Microsoft bu zayıflığı fark ediyor ve her Windows güncellemesiyle bilinen bypass pattern'lerini tespit eden yeni imzalar ekliyor.
Process Injection Teknikleri — Başkasının Kimliğiyle Çalışmak
Process Injection (Süreç Enjeksiyonu), zararlı kodun başka bir process'in bellek alanında çalıştırılması. Neden yapılıyor? Çünkü zararlı process kendi başına çalışırsa EDR onu çok daha kolay tanıyor. Ama kod meşru bir process içinde çalışıyorsa, örneğin explorer.exe veya svchost.exe içinde, tespiti çok daha güç.
Teorik olarak en yaygın enjeksiyon yöntemleri şunlar. Classic DLL Injection: Hedef process'e OpenProcess ile handle aç, VirtualAllocEx ile bellek ayır, WriteProcessMemory ile DLL yolunu yaz, CreateRemoteThread ile LoadLibrary'yi çağır. Bu yöntem çok iyi biliniyor ve EDR'ler tarafından neredeyse kesin olarak tespit ediliyor.
Process Hollowing: Meşru bir process'i askıya alınmış modda başlat, belleğini temizle, yerine zararlı PE dosyasını yerleştir, process'i devam ettir. İşletim sistemi meşru process adını görüyor ama içinde farklı bir kod çalışıyor.
Thread Hijacking: Hedef process içindeki mevcut bir thread'i askıya al, instruction pointer'ını değiştir, thread'i devam ettir. Yeni thread veya DLL oluşturulmadığı için bazı tespitlerden kaçınılabiliyor.
Module Stomping: Hedef process'e meşru bir DLL yükle, ardından o DLL'in belleğini zararlı kodla değiştir. Bellekte yüklü görünen DLL meşru ama içeriği değiştirilmiş.
Modern EDR'ler bu tekniklerin tamamı için özel tespit mekanizmaları geliştirdi. Çağrı yığını (call stack) analizi burada kritik: meşru bir DLL'den gelen bir OpenProcess çağrısı ile hiçbir DLL'e ait olmayan bellek alanından gelen çağrı çok farklı görünüyor.
PPL ve Kernel Sürücü Açıkları — Derinlere İniş
Userland bypass teknikleri hâlâ kernel callback'lere çarpıyor. Kernel callback'lerini devre dışı bırakmak için ise kernel'e girmek gerekiyor. Bu noktada saldırı teorisi çok daha tehlikeli bir alana giriyor: kötü amaçlı kernel sürücüleri.
Windows 64-bit sistemlerde Kernel-Mode Code Signing zorunluluğu var. Bir sürücü yüklemek için Microsoft tarafından imzalanmış olması gerekiyor. Saldırganlar bunu aşmak için iki yol izliyor.
Birincisi BYOVD (Bring Your Own Vulnerable Driver) yani kendi zafiyetli sürücünü getir. Meşru ve imzalı ama güvenlik açığı barındıran bir sürücü sisteme yükleniyor. Bu sürücüdeki açık istismar edilerek kernel'de kod çalıştırılıyor. Microsoft bu tekniğe karşı Windows Defender Application Control ve sürücü engelleme listeleri geliştirdi ama yeni zafiyetli sürücüler sürekli keşfediliyor.
İkincisi Test Mode veya Secure Boot'u devre dışı bırakmak. Fiziksel erişim gerekiyor ama bu seçenek test ortamlarında ve bazı kurumsal sistemlerde mümkün.
Kernel'e girildikten sonra EDR callback'leri kaldırmak teorik olarak mümkün. PsSetCreateProcessNotifyRoutineEx ile kayıt olunan callback'lerin listesi kernel yapılarında tutuluyor. Bu yapılar değiştirilebilirse EDR'in gözleri kör ediliyor. Ama modern güvenli sistemlerde bu yapılar da korumalı.
EDR'in Kör Noktaları ve Blue Team Perspektifi
Bu noktaya kadar saldırı teorisini anlattım. Ama asıl mesaj bu değil. Bu tekniklerin tamamını anlayan bir blue team, savunmasını çok daha doğru konumlandırabiliyor.
EDR'lerin hâlâ zorlandığı noktalar var. Living-off-the-Land (LotL): Sistemin kendi araçlarını kullanan saldırılar. certutil, bitsadmin, regsvr32, mshta — bunlar Windows'un meşru araçları ama sıklıkla kötüye kullanılıyor. EDR bu araçları engelleyemez çünkü yöneticiler de kullanıyor; ancak anomali tespiti ile şüpheli kullanım pattern'leri yakalanabiliyor.
In-Memory Only Saldırılar: Diske hiçbir şey yazmayan, yalnızca bellekte çalışan saldırılar. ETW ve AMSI bu boşluğu kapatmaya çalışıyor ama tam kapsama hâlâ zor.
Supply Chain Saldırıları: Meşru, imzalı yazılım güncellemeleri üzerinden yapılan saldırılar. SolarWinds buna en iyi örnek. EDR imzalı ve güvenilen bir süreçten gelen komutları engellemekte zorlanıyor.
Blue team'in bu tabloya cevabı şu olmalı: Tek bir EDR'e güvenme. Loglama katmanını çoğalt; SIEM ile davranış analizi, ağ katmanında NDR, uç nokta dışında da görünürlük. Threat hunting proaktif olarak yürüt; EDR alert'lerini bekleme, anomali peşinde koş. Ve en önemlisi, saldırı tekniklerini kendi test ortamında dene, EDR'inin gerçekte ne gördüğünü ve ne görmediğini öğren.
Kısa Özet
EDR, modern siber güvenliğin en kritik savunma katmanı. Userland hook'lar ile API çağrılarını izliyor, kernel callback'ler ile process ve thread oluşturma olaylarını kernel seviyesinde alıyor, ETW ile yüksek performanslı sistem telemetrisi topluyor, AMSI ile script tabanlı saldırıları çalıştırılmadan önce tarıyor. Saldırı teorisi açısından unhooking ve direct syscall userland hook'ları devre dışı bırakmayı hedefliyor; ETW patching telemetriyi kesmeyi; AMSI bypass script motorlarının kör edilmesini; process injection başkasının kimliğine bürünmeyi; BYOVD ise kernel'e inerek tüm mekanizmaları devre dışı bırakmayı hedefliyor. Ama her bypass tekniğine karşı EDR de evrildi. Kernel callback'ler userland bypass'tan etkilenmiyor, call stack analizi injection tespitini güçlendirdi, HVCI zafiyetli sürücü yüklemeyi zorlaştırdı. Bu silahlanma yarışında kazanan taraf daha iyi anlayan taraf. Bu yazıyı okuma motivasyonunuz hangi taraf olursa olsun, karşı tarafın tekniklerini bilmek sizi daha iyi yapıyor.
Önemli Hatırlatma: Bu yazımda ele alınan tüm teknikler savunma amaçlı güvenlik araştırması, red team metodolojisi ve eğitim kapsamında paylaşılmıştır. Yetkisiz sistemlerde bu tekniklerin uygulanması TCK Madde 243 ve uluslararası siber suç mevzuatı kapsamında ağır suç teşkil eder. Denemeyiniz efendim.
EDR Nedir ve Ne Görür?
EDR (Endpoint Detection and Response), uç nokta cihazlarında gerçek zamanlı olarak davranışları izleyen, şüpheli aktiviteleri tespit eden ve otomatik müdahale yapabilen güvenlik yazılımı. Crowdstrike Falcon, Microsoft Defender for Endpoint, SentinelOne, Carbon Black, Elastic EDR bunların en yaygın örnekleri.
Geleneksel antivirüs ile EDR arasındaki fark kritik. Antivirüs imzaya bakar: "Bu dosyanın hash'i bilinen zararlı yazılımların listesinde mi?" sorusunu sorar. Bu yaklaşım yıllarca işe yaradı ama saldırganlar çok basit tekniklerle dosyayı değiştirmeye, hash'i farklılaştırmaya başladı. EDR ise dosyaya değil davranışa bakıyor: "Bu process ne yapıyor? Hangi API'ları çağırıyor? Hangi bellek bölgelerine yazıyor? Hangi dosyalara dokunuyor? Ağda kiminle konuşuyor?" sorularını soruyor.
EDR'in veri toplama noktaları şunlar. Userland API Hooking: Windows API fonksiyonlarının başına kendi kodu enjekte ediyor, her çağrıyı izliyor. Kernel Callback'ler: Windows çekirdeğinin sağladığı bildirim mekanizmalarına kayıt oluyor; process oluşturma, thread oluşturma, image yükleme gibi olayları kernel seviyesinde alıyor. ETW (Event Tracing for Windows): Microsoft'un yerleşik telemetri sistemi; kernel olaylarını, ağ olaylarını ve uygulama davranışlarını yüksek performanslı şekilde akıtıyor. Minifilter Sürücüleri: Dosya sistemi operasyonlarını kernel katmanında izliyor. Bu dört veri kaynağının tamamını kesen bir EDR son derece geniş görüş alanına sahip.
Userland Hooking — EDR'in Gözleri
EDR'in en yaygın izleme yöntemi userland hooking, yani kullanıcı alanındaki API kancalaması. Bunu anlamak için Windows'un API çağrı zincirini bilmek gerekiyor.
Bir uygulama VirtualAlloc gibi bir Windows API fonksiyonunu çağırdığında şu zincir işliyor: uygulama → kernel32.dll → ntdll.dll → sistem çağrısı (syscall) → Windows Kernel. Bu zincirin en alt katmanı ntdll.dll, çünkü burası kullanıcı alanından kernel'e geçişin yapıldığı son durak. EDR çoğunlukla ntdll.dll içindeki fonksiyonların başına kendi kodunu yerleştiriyor. Bu koda hook (kanca) deniyor.
Teknik olarak şöyle çalışıyor: ntdll.dll belleğe yüklendiğinde fonksiyonların başındaki birkaç byte EDR tarafından değiştiriliyor. Oraya bir JMP (Jump) talimatı ekleniyor. Bu JMP, kontrolü EDR'in kendi analiz fonksiyonuna gönderiyor. EDR parametreleri inceliyor, davranış şüpheliyse engelleme yapıyor, değilse asıl API'ya devam ediyor. Bu süreç uygulamadan tamamen gizli; uygulama API'yı çağırdığını zannediyor ama aslında önce EDR'in denetimine giriyor.
Kod:
# Userland Hook Anatomisi — ntdll.dll üzerinden örnek
# Hook OLMADAN NtAllocateVirtualMemory'nin başındaki byte'lar:
# 4C 8B D1 mov r10, rcx
# B8 18 00 00 00 mov eax, 0x18 ← syscall numarası
# 0F 05 syscall ← kernel'e geç
# C3 ret
# EDR Hook KURULDUKTAN SONRA (aynı adres):
# E9 XX XX XX XX jmp <EDR_analiz_fonksiyonu> ← EDR kancası
# 00 00 00 00 00 (geri kalan byte'lar)
# EDR'in analiz fonksiyonu şunu yapıyor:
# 1. Parametreleri incele (bellek boyutu, koruma bayrakları vs.)
# 2. Çağrı yığınını (call stack) analiz et — kim çağırdı?
# 3. Şüpheliyse engelle ve alert üret
# 4. Şüpheli değilse orijinal syscall'a devam et
# Hook tespiti için basit kontrol:
import ctypes
ntdll = ctypes.windll.ntdll
# NtAllocateVirtualMemory'nin adresini al
func_addr = ctypes.cast(ntdll.NtAllocateVirtualMemory, ctypes.c_void_p).value
# İlk byte'ı oku
first_byte = ctypes.string_at(func_addr, 1)
if first_byte == b'\xe9': # JMP talimatı
print("HOOK TESPİT EDİLDİ — EDR aktif")
else:
print("Hook yok — orijinal ntdll")
Unhooking — Hook Temizleme Teorisi
Userland hook'un bir zayıflığı var: EDR kancayı yalnızca belleğe yüklenmiş ntdll.dll kopyasına ekliyor. Disk üzerindeki orijinal ntdll.dll dosyasına dokunamıyor. Bu, bypass teorisinin temel taşı olan unhooking kavramının doğduğu nokta.
Teorik çalışma mantığı şöyle: disk üzerindeki temiz ntdll.dll dosyasını oku, yani hiç belleğe yüklenmemiş orijinal dosyayı. Şu an bellekte hook'lanmış olan fonksiyonların orijinal byte'larını bu dosyadan al. Hook edilen byte'ların üzerine orijinal byte'ları yaz. Artık bellekteki ntdll.dll temiz, EDR'in kancaları yok.
Bu tekniğin birkaç varyantı var. Full DLL Unhooking: ntdll.dll'in tamamını diskten okuyup bellekteki kopyayla değiştirmek. Selective Unhooking: Yalnızca ihtiyaç duyulan fonksiyonların hook'larını temizlemek; daha az gürültülü. Indirect Syscall: ntdll.dll'e hiç dokunmadan, doğrudan kernel'e sistem çağrısı yapmak. Bu üçüncü yaklaşım en temiz ve en az tespit edilebilir olanı.
Ama hemen belirtmeliyim: modern EDR'ler bu tekniklere karşı da gelişti. Kernel callback'leri userland hook'lardan bağımsız çalışıyor. Bellekteki ntdll kopyasını değiştirmeye çalışan bir işlem bile kendi başına şüpheli bir davranış olarak işaretlenebiliyor.
Kod:
# Unhooking Teorisi — Disk'ten Temiz DLL Okuma
# (Eğitim ve red team araştırması amaçlı)
import ctypes
import ctypes.wintypes as wintypes
def get_clean_ntdll():
# Disk'teki orijinal ntdll.dll'i aç — hook YOK burada
ntdll_path = "C:\\Windows\\System32\\ntdll.dll"
# Dosyayı bellekte haritala (memory map)
hFile = ctypes.windll.kernel32.CreateFileW(
ntdll_path, 0x80000000, 0x03, None, 3, 0x80, None)
hMapping = ctypes.windll.kernel32.CreateFileMappingW(
hFile, None, 0x02, 0, 0, None)
# Diskteki temiz kopyayı belleğe map et
pNtdll = ctypes.windll.kernel32.MapViewOfFile(
hMapping, 0x04, 0, 0, 0)
return pNtdll # Bu adres hook'suz orijinal ntdll
# Direct Syscall yaklaşımı — ntdll'e hiç dokunma
# Syscall numarasını kendin belirle ve doğrudan kernel'e git
# NtAllocateVirtualMemory için syscall ID: 0x18 (Windows 10)
# Bu ID Windows sürümleri arasında değişiyor — dikkat
# Assembly ile direct syscall (teorik):
# mov r10, rcx
# mov eax, 0x18 ← NtAllocateVirtualMemory syscall ID
# syscall ← ntdll bypass, direkt kernel
# ret
# Bu yaklaşımda userland hook tamamen devre dışı
# Ama kernel callback'ler yine de tetiklenebilir
Kernel Callback'ler — EDR'in Derinlerdeki Gözleri
Userland hook'ların aşılabildiğini gören EDR üreticileri çok daha derin bir katmana indi: Windows kernel'in kendi bildirim mekanizmaları. Kernel callback sistemi, Microsoft'un güvenlik yazılımlarına sağladığı resmi bir API. EDR sürücüsü bu callback'lere kaydolduğunda, kernel her kritik olay gerçekleştiğinde EDR'i doğrudan bilgilendiriyor.
En önemli kernel callback türleri şunlar. PsSetCreateProcessNotifyRoutineEx: Her yeni process oluşturulduğunda tetikleniyor. Hangi process hangi kullanıcı bağlamında kim tarafından oluşturuldu, başlangıç parametreleri neler — hepsi burada. PsSetCreateThreadNotifyRoutine: Her thread oluşturulduğunda tetikleniyor. Remote thread enjeksiyonu bu callback'le tespit ediliyor. PsSetLoadImageNotifyRoutine: Bir DLL veya çalıştırılabilir dosya belleğe yüklendiğinde tetikleniyor. CmRegisterCallback: Registry okuma ve yazma işlemlerini izliyor. ObRegisterCallbacks: Process ve thread handle'larına yapılan erişimleri izliyor; LSASS gibi korunan process'lere handle açma girişimlerini yakalar.
Kernel callback'lerin userland hook'lardan farkı şu: bunlar kernel içinde çalışıyor ve kullanıcı alanındaki herhangi bir manipülasyondan etkilenmiyor. ntdll hook'larını tamamen temizlemiş olsanız bile yeni bir process oluştururken PsSetCreateProcessNotifyRoutineEx tetiklenecek ve EDR sizi görecek.
Kod:
# Kernel Callback Kayıt Örneği — EDR Sürücüsü Perspektifi
# (Windows Kernel Driver geliştirme — eğitim amaçlı)
#include <ntddk.h>
// Process oluşturma callback — EDR bu şekilde kayıt oluyor
VOID ProcessNotifyCallback(
PEPROCESS Process,
HANDLE ProcessId,
PPS_CREATE_NOTIFY_INFO CreateInfo)
{
if (CreateInfo) {
// Yeni process oluşturuldu
PUNICODE_STRING imageName = CreateInfo->ImageFileName;
PUNICODE_STRING commandLine = CreateInfo->CommandLine;
// Şüpheli pattern kontrolü
if (wcsstr(commandLine->Buffer, L"powershell") &&
wcsstr(commandLine->Buffer, L"-enc")) {
// Encode edilmiş PowerShell — şüpheli
// EDR burada bloklama kararı verebilir
CreateInfo->CreationStatus = STATUS_ACCESS_DENIED;
}
}
}
// Sürücü başlatılırken callback'i kaydet
DriverEntry(...)
{
PsSetCreateProcessNotifyRoutineEx(ProcessNotifyCallback, FALSE);
// Artık her process oluşturulduğunda EDR bildirilecek
// Userland hook'lar temizlense bile bu çalışmaya devam eder
}
ETW Patching — Telemetri Köreltme Teorisi
ETW (Event Tracing for Windows), Microsoft'un işletim sistemine gömülü yüksek performanslı telemetri sistemi. Kernel olayları, ağ bağlantıları, process davranışları, PowerShell komutları — hepsi ETW kanalları üzerinden akıyor. EDR'lerin büyük çoğunluğu ETW'ye abone olarak bu veri akışını dinliyor.
ETW'nin özellikle kritik bir kanalı var: Microsoft-Windows-Threat-Intelligence (TI) provider. Bu kanal process injection, LSASS belleği okuma ve kod enjeksiyonu gibi tehlikeli davranışları kernel seviyesinde raporluyor. Normal ETW kanallarının aksine bu kanal yalnızca PPL (Protected Process Light) yetkisiyle çalışan süreçler tarafından okunabiliyor; yani EDR'in sürücüsü bu yetkiye sahip.
ETW patching teorisi ne? ntdll.dll içindeki ETW olaylarını üreten fonksiyon olan EtwEventWrite ve EtwEventWriteFull fonksiyonlarının başına bir RET (return) talimatı yerleştirilirse, fonksiyon çağrıldığında hiçbir şey yapmadan geri dönüyor. Telemetri üretilmiyor, EDR'e veri gitmiyor.
Ama bu yaklaşımın da modern EDR'ler tarafından izlendiğini belirtmeliyim. EtwEventWrite fonksiyonuna yazma girişimi kendi başına şüpheli bir davranış. Ayrıca kernel-mode ETW kanalları bu manipülasyondan etkilenmiyor; yalnızca userland ETW provider'ları susturuluyor.
Kod:
# ETW Patching Teorisi
# (Eğitim amaçlı — bu teknik modern EDR'ler tarafından izleniyor)
import ctypes
def patch_etw():
ntdll = ctypes.windll.ntdll
# EtwEventWrite adresini bul
etw_write = ctypes.cast(
ctypes.windll.kernel32.GetProcAddress(
ctypes.windll.kernel32.GetModuleHandleA(b"ntdll.dll"),
b"EtwEventWrite"),
ctypes.c_void_p).value
# Bellek korumasını değiştir (yazılabilir yap)
old_protect = ctypes.c_ulong(0)
ctypes.windll.kernel32.VirtualProtect(
etw_write, 1, 0x40, ctypes.byref(old_protect))
# RET talimatı yaz — fonksiyon anında geri dönecek
# 0xC3 = RET (x64)
ctypes.memset(etw_write, 0xC3, 1)
# Korumayı geri al
ctypes.windll.kernel32.VirtualProtect(
etw_write, 1, old_protect, ctypes.byref(old_protect))
# NOT: Bu işlem kendisi de EDR tarafından izlenebilir
# VirtualProtect + memset kombinasyonu şüpheli davranış
# Kernel ETW kanalları bu patch'ten etkilenmiyor
AMSI Bypass — Script Motorlarının Kalkanını Aşmak
AMSI (Antimalware Scan Interface), Microsoft'un PowerShell, VBScript, JScript ve WMI gibi script motorlarına entegre ettiği tarama arayüzü. Script çalıştırılmadan hemen önce AMSI devreye giriyor, içeriği EDR'e (veya antivirüse) gönderiyor ve yanıt bekliyor. Zararlı içerik tespit edilirse script çalıştırılmıyor.
Bu neden bu kadar önemli? Fileless malware, PowerShell tabanlı saldırılar ve living-off-the-land teknikleri disk üzerine hiçbir şey yazmıyor; doğrudan bellekte çalışıyor. Geleneksel dosya taraması bunları yakalamıyor. AMSI bu boşluğu kapatıyor.
AMSI bypass teorisi userland hooking mantığının bir varyantı. amsi.dll içindeki AmsiScanBuffer ve AmsiScanString fonksiyonları, script motorlarının içerikleri EDR'e göndermek için çağırdığı fonksiyonlar. Bu fonksiyonların başına bir patch eklenirse veya dönüş değeri her zaman "temiz" döndürülürse, EDR gerçek içeriği hiç görmüyor.
Peki bu bypass yöntemleri neden çalışmaya devam edebiliyor? Çünkü AMSI temelde bir userland mekanizması. Kernel seviyesinde zorunlu değil, script motorlarının isteğe bağlı olarak çağırdığı bir arayüz. Bu yapısal sınırlama AMSI'nin en önemli zayıflığı. Microsoft bu zayıflığı fark ediyor ve her Windows güncellemesiyle bilinen bypass pattern'lerini tespit eden yeni imzalar ekliyor.
Kod:
# AMSI Bypass Teorisi — Farklı Yaklaşımlar
# (Eğitim amaçlı)
# Yaklaşım 1: AmsiScanBuffer fonksiyonunu patch'le
# amsi.dll'i belleğe yükle, fonksiyon adresini bul
# Fonksiyonun başına AMSI_RESULT_CLEAN döndüren kod yaz
# Yaklaşım 2: AmsiContext bozulması
# AmsiScanBuffer ilk parametre olarak AmsiContext alıyor
# Context'i NULL veya geçersiz bir değerle değiştirirsen
# fonksiyon hata döndürüyor ve tarama yapılmıyor
# PowerShell'de kavramsal örnek (tespit edilir, eğitim amaçlı):
# [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')
# Yaklaşım 3: COM Server üzerinden AMSI bypass
# AMSI COM arayüzü üzerinden çalıştırılıyor
# COM kaydını manipüle ederek bypass
# Yaklaşım 4: Process içi reflection
# Yeni bir PowerShell runspace oluştur
# Bu runspace AMSI başlatma adımını atlıyor
# Tespit: EDR'ler artık şu pattern'leri arıyor:
# - amsi.dll içindeki fonksiyonlara yazma girişimi
# - AmsiScanBuffer'ın patch edildiğini gösteren byte değişimleri
# - AMSI initialize etmeden PowerShell runspace oluşturma
Process Injection Teknikleri — Başkasının Kimliğiyle Çalışmak
Process Injection (Süreç Enjeksiyonu), zararlı kodun başka bir process'in bellek alanında çalıştırılması. Neden yapılıyor? Çünkü zararlı process kendi başına çalışırsa EDR onu çok daha kolay tanıyor. Ama kod meşru bir process içinde çalışıyorsa, örneğin explorer.exe veya svchost.exe içinde, tespiti çok daha güç.
Teorik olarak en yaygın enjeksiyon yöntemleri şunlar. Classic DLL Injection: Hedef process'e OpenProcess ile handle aç, VirtualAllocEx ile bellek ayır, WriteProcessMemory ile DLL yolunu yaz, CreateRemoteThread ile LoadLibrary'yi çağır. Bu yöntem çok iyi biliniyor ve EDR'ler tarafından neredeyse kesin olarak tespit ediliyor.
Process Hollowing: Meşru bir process'i askıya alınmış modda başlat, belleğini temizle, yerine zararlı PE dosyasını yerleştir, process'i devam ettir. İşletim sistemi meşru process adını görüyor ama içinde farklı bir kod çalışıyor.
Thread Hijacking: Hedef process içindeki mevcut bir thread'i askıya al, instruction pointer'ını değiştir, thread'i devam ettir. Yeni thread veya DLL oluşturulmadığı için bazı tespitlerden kaçınılabiliyor.
Module Stomping: Hedef process'e meşru bir DLL yükle, ardından o DLL'in belleğini zararlı kodla değiştir. Bellekte yüklü görünen DLL meşru ama içeriği değiştirilmiş.
Modern EDR'ler bu tekniklerin tamamı için özel tespit mekanizmaları geliştirdi. Çağrı yığını (call stack) analizi burada kritik: meşru bir DLL'den gelen bir OpenProcess çağrısı ile hiçbir DLL'e ait olmayan bellek alanından gelen çağrı çok farklı görünüyor.
Kod:
# Process Injection Teknikleri — Teorik Karşılaştırma
# (Eğitim amaçlı)
# Classic DLL Injection — API çağrıları zinciri:
# 1. OpenProcess(PROCESS_ALL_ACCESS, ..., target_pid)
# 2. VirtualAllocEx(hProcess, NULL, size, MEM_COMMIT, PAGE_READWRITE)
# 3. WriteProcessMemory(hProcess, remote_addr, dll_path, size, NULL)
# 4. CreateRemoteThread(hProcess, NULL, 0, LoadLibraryA, remote_addr, ...)
# EDR tespiti: Thread create callback + suspicious call stack
# Process Hollowing — adım adım:
# 1. CreateProcess(..., CREATE_SUSPENDED, ...) → askıya alınmış process
# 2. NtUnmapViewOfSection(hProcess, imageBase) → belleği boşalt
# 3. VirtualAllocEx → NtWriteVirtualMemory → PE yükle
# 4. SetThreadContext → ResumeThread → çalıştır
# EDR tespiti: Image base ile on-disk PE uyuşmazlığı
# Shellcode Injection + Direct Syscall kombinasyonu:
# OpenProcess → NtOpenProcess (syscall ID: 0x26)
# VirtualAllocEx → NtAllocateVirtualMemory (syscall ID: 0x18)
# WriteProcess → NtWriteVirtualMemory (syscall ID: 0x3A)
# CreateThread → NtCreateThreadEx (syscall ID: 0xC2)
# Userland hook bypass — ama kernel callback hâlâ tetikleniyor
# Call Stack analizi — EDR'in şüphe işareti:
# Meşru: kernel32.dll → ntdll.dll → kernel
# Şüpheli: [RWX bellek bölgesi] → ntdll.dll → kernel
# "Returnless" call stack — bilinen modüle ait olmayan return adresi
PPL ve Kernel Sürücü Açıkları — Derinlere İniş
Userland bypass teknikleri hâlâ kernel callback'lere çarpıyor. Kernel callback'lerini devre dışı bırakmak için ise kernel'e girmek gerekiyor. Bu noktada saldırı teorisi çok daha tehlikeli bir alana giriyor: kötü amaçlı kernel sürücüleri.
Windows 64-bit sistemlerde Kernel-Mode Code Signing zorunluluğu var. Bir sürücü yüklemek için Microsoft tarafından imzalanmış olması gerekiyor. Saldırganlar bunu aşmak için iki yol izliyor.
Birincisi BYOVD (Bring Your Own Vulnerable Driver) yani kendi zafiyetli sürücünü getir. Meşru ve imzalı ama güvenlik açığı barındıran bir sürücü sisteme yükleniyor. Bu sürücüdeki açık istismar edilerek kernel'de kod çalıştırılıyor. Microsoft bu tekniğe karşı Windows Defender Application Control ve sürücü engelleme listeleri geliştirdi ama yeni zafiyetli sürücüler sürekli keşfediliyor.
İkincisi Test Mode veya Secure Boot'u devre dışı bırakmak. Fiziksel erişim gerekiyor ama bu seçenek test ortamlarında ve bazı kurumsal sistemlerde mümkün.
Kernel'e girildikten sonra EDR callback'leri kaldırmak teorik olarak mümkün. PsSetCreateProcessNotifyRoutineEx ile kayıt olunan callback'lerin listesi kernel yapılarında tutuluyor. Bu yapılar değiştirilebilirse EDR'in gözleri kör ediliyor. Ama modern güvenli sistemlerde bu yapılar da korumalı.
Kod:
# BYOVD Saldırı Teorisi
# (Eğitim amaçlı — CVE referanslarla)
# Bilinen zafiyetli sürücü örnekleri:
# CVE-2021-21551 — Dell DBUtil sürücüsü (yaygın olarak kullanıldı)
# CVE-2019-16098 — RTCore64.sys (MSI Afterburner sürücüsü)
# CVE-2023-32233 — Windows Kernel (Netfilter)
# BYOVD saldırı akışı:
# 1. Zafiyetli ama imzalı sürücüyü yükle
# sc create VulnDriver binpath=C:\vuln_driver.sys type=kernel
# sc start VulnDriver
# 2. Sürücüdeki açığı exploit et
# Arbitrary kernel memory read/write yetkisi elde et
# 3. EDR callback listesini bul ve temizle
# PspCreateProcessNotifyRoutine dizisini bul
# EDR'in callback fonksiyon adresini NULL ile değiştir
# 4. EDR artık process oluşturma olaylarını görmüyor
# 5. Payload çalıştır — kernel callback yok, userland hook yok
# Microsoft'un savunması:
# Windows Defender Application Control (WDAC)
# Microsoft Vulnerable Driver Blocklist
# Hypervisor-Protected Code Integrity (HVCI)
# Bu üç katman birlikte zafiyetli sürücü yüklemeyi çok zorlaştırıyor
EDR'in Kör Noktaları ve Blue Team Perspektifi
Bu noktaya kadar saldırı teorisini anlattım. Ama asıl mesaj bu değil. Bu tekniklerin tamamını anlayan bir blue team, savunmasını çok daha doğru konumlandırabiliyor.
EDR'lerin hâlâ zorlandığı noktalar var. Living-off-the-Land (LotL): Sistemin kendi araçlarını kullanan saldırılar. certutil, bitsadmin, regsvr32, mshta — bunlar Windows'un meşru araçları ama sıklıkla kötüye kullanılıyor. EDR bu araçları engelleyemez çünkü yöneticiler de kullanıyor; ancak anomali tespiti ile şüpheli kullanım pattern'leri yakalanabiliyor.
In-Memory Only Saldırılar: Diske hiçbir şey yazmayan, yalnızca bellekte çalışan saldırılar. ETW ve AMSI bu boşluğu kapatmaya çalışıyor ama tam kapsama hâlâ zor.
Supply Chain Saldırıları: Meşru, imzalı yazılım güncellemeleri üzerinden yapılan saldırılar. SolarWinds buna en iyi örnek. EDR imzalı ve güvenilen bir süreçten gelen komutları engellemekte zorlanıyor.
Blue team'in bu tabloya cevabı şu olmalı: Tek bir EDR'e güvenme. Loglama katmanını çoğalt; SIEM ile davranış analizi, ağ katmanında NDR, uç nokta dışında da görünürlük. Threat hunting proaktif olarak yürüt; EDR alert'lerini bekleme, anomali peşinde koş. Ve en önemlisi, saldırı tekniklerini kendi test ortamında dene, EDR'inin gerçekte ne gördüğünü ve ne görmediğini öğren.
Kod:
# Blue Team Kontrol Listesi — EDR Görünürlük Doğrulama
# 1. Atomic Red Team ile EDR testi
# https://github.com/redcanaryco/atomic-red-team
# MITRE ATT&CK tekniklerini kendi ortamında çalıştır
# EDR hangisini yakalıyor, hangisini kaçırıyor?
Invoke-AtomicTest T1055 -TestNumbers 1 # Process injection
Invoke-AtomicTest T1562.001 # EDR disable girişimi
# 2. Sysmon ile ek görünürlük katmanı
# EDR loglarına ek olarak Sysmon detaylı event toplar
# Event ID 8: CreateRemoteThread — injection tespiti
# Event ID 10: ProcessAccess — LSASS erişimi
# Event ID 25: ProcessTampering — process hollowing işareti
# 3. LSASS koruması
# Credential Guard aktif mi?
reg query HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard /v EnableVirtualizationBasedSecurity
# 4. Zafiyetli sürücü kontrolü
# Sistemde bilinen BYOVD sürücüleri var mı?
# https://www.loldrivers.io — bilinen zafiyetli sürücü listesi
Get-WmiObject Win32_SystemDriver | Select-Object Name, PathName | `
Where-Object { $_.PathName -ne "" }
# 5. Call stack anomali kontrolü — SIEM sorgusu (Elastic örneği)
# process.thread.Ext.call_stack.callsite_leading_bytes: ?E9????
# Hook bypass girişiminin işareti
Kısa Özet
EDR, modern siber güvenliğin en kritik savunma katmanı. Userland hook'lar ile API çağrılarını izliyor, kernel callback'ler ile process ve thread oluşturma olaylarını kernel seviyesinde alıyor, ETW ile yüksek performanslı sistem telemetrisi topluyor, AMSI ile script tabanlı saldırıları çalıştırılmadan önce tarıyor. Saldırı teorisi açısından unhooking ve direct syscall userland hook'ları devre dışı bırakmayı hedefliyor; ETW patching telemetriyi kesmeyi; AMSI bypass script motorlarının kör edilmesini; process injection başkasının kimliğine bürünmeyi; BYOVD ise kernel'e inerek tüm mekanizmaları devre dışı bırakmayı hedefliyor. Ama her bypass tekniğine karşı EDR de evrildi. Kernel callback'ler userland bypass'tan etkilenmiyor, call stack analizi injection tespitini güçlendirdi, HVCI zafiyetli sürücü yüklemeyi zorlaştırdı. Bu silahlanma yarışında kazanan taraf daha iyi anlayan taraf. Bu yazıyı okuma motivasyonunuz hangi taraf olursa olsun, karşı tarafın tekniklerini bilmek sizi daha iyi yapıyor.
Önemli Hatırlatma: Bu yazımda ele alınan tüm teknikler savunma amaçlı güvenlik araştırması, red team metodolojisi ve eğitim kapsamında paylaşılmıştır. Yetkisiz sistemlerde bu tekniklerin uygulanması TCK Madde 243 ve uluslararası siber suç mevzuatı kapsamında ağır suç teşkil eder. Denemeyiniz efendim.

