Windows ortamlarında güvenlik olaylarını takip etmek, bir sistem yöneticisinin günlük rutininin en kritik parçalarından biridir. Event Viewer’ı açıp elle log taramak bazen işe yarasa da, özellikle birden fazla sunucuyu yönetiyorsanız bu yaklaşım hızla yetersiz kalır. İşte tam bu noktada WMI (Windows Management Instrumentation) devreye giriyor. WMI, Windows’un derinliklerine programatik olarak erişmenizi sağlayan güçlü bir altyapıdır ve güvenlik olaylarını sorgulamak için son derece esnek bir yol sunar. Bu yazıda WMI ile güvenlik olaylarını nasıl sorgulayacağınızı, pratik senaryolar üzerinden ele alacağız.
WMI Nedir ve Neden Güvenlik İçin Kullanılır?
WMI, Microsoft’un Windows işletim sistemi üzerine inşa ettiği bir yönetim altyapısıdır. Temelde WBEM (Web-Based Enterprise Management) standardının Microsoft implementasyonudur. Sistem bilgilerinden süreç yönetimine, ağ konfigürasyonundan olay günlüklerine kadar neredeyse her şeye WMI üzerinden erişebilirsiniz.
Güvenlik perspektifinden bakıldığında WMI’ın avantajları şunlardır:
- Merkezi sorgulama: Tek bir noktadan uzak makinelerin güvenlik olaylarını sorgulayabilirsiniz
- WQL desteği: SQL’e benzer bir sorgu diliyle esnek filtreleme yapabilirsiniz
- Otomasyon dostu: PowerShell, Python veya VBScript ile kolayca entegre edilebilir
- Real-time izleme: WMI event subscription ile anlık olay yakalama mümkündür
Ancak şunu da belirtmek gerekir: WMI güçlü bir araçtır ama kötüye kullanımı da yaygındır. Saldırganlar da WMI’ı persistence mekanizması olarak kullanır, dolayısıyla WMI aktivitelerini izlemek de başlı başına bir güvenlik gerekliliğidir.
Temel WMI Güvenlik Sorguları
Win32_NTLogEvent ile Başlamak
En temel yaklaşım Win32_NTLogEvent sınıfını kullanmaktır. Bu sınıf, Windows olay günlüklerindeki kayıtlara doğrudan erişim sağlar.
# PowerShell ile temel güvenlik log sorgulama
Get-WmiObject -Class Win32_NTLogEvent `
-Filter "LogFile='Security' AND EventCode=4624" `
-ComputerName "SERVER01" |
Select-Object TimeGenerated, EventCode, Message, User |
Format-List
Bu komut, EVENT ID 4624 yani başarılı oturum açma olaylarını listeler. ComputerName parametresini kendi sunucunuzun adıyla değiştirmeniz yeterli. Uzak makineye bağlanmak için WinRM veya DCOM’un açık olması gerektiğini unutmayın.
Sık Kullanılan Güvenlik Event ID’leri
Hangi event ID’lerine odaklanmanız gerektiğini bilmek, sorguları anlamlı kılar:
- 4624: Başarılı oturum açma
- 4625: Başarısız oturum açma girişimi
- 4648: Açık kimlik bilgileriyle oturum açma (pass-the-hash için kritik)
- 4672: Ayrıcalıklı oturum açma (admin hesapları)
- 4688: Yeni süreç oluşturma
- 4698: Zamanlanmış görev oluşturma
- 4720: Yeni kullanıcı hesabı oluşturma
- 4732: Güvenlik grubuna üye ekleme
- 4771: Kerberos ön kimlik doğrulama başarısız
- 7045: Yeni servis kurulumu
Başarısız Giriş Denemelerini Sorgulama
Bir sisteme brute force saldırısı yapılıp yapılmadığını anlamak için 4625 event ID’sini sorgulamak temel başlangıç noktasıdır:
# Son 24 saat içindeki başarısız giriş denemelerini listele
$zaman = (Get-Date).AddHours(-24)
$zamanWMI = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime($zaman)
Get-WmiObject -Class Win32_NTLogEvent -Filter `
"LogFile='Security' AND EventCode=4625 AND TimeGenerated >= '$zamanWMI'" |
Select-Object @{N='Zaman';E={[System.Management.ManagementDateTimeConverter]::ToDateTime($_.TimeGenerated)}},
User, ComputerName, Message |
Sort-Object Zaman -Descending
Burada dikkat edilmesi gereken nokta, WMI’ın tarih formatının standart .NET datetime formatından farklı olmasıdır. ManagementDateTimeConverter sınıfı bu dönüşümü halleder.
Uzak Sistemleri Sorgulamak
Credential ile Uzak WMI Bağlantısı
Production ortamında genellikle birden fazla sunucuyu sorgulamanız gerekir. Bunu güvenli şekilde yapmak için:
# Kimlik bilgilerini güvenli şekilde al ve uzak sistemi sorgula
$credential = Get-Credential -Message "WMI bağlantısı için kimlik bilgisi girin"
$wmiParams = @{
Class = "Win32_NTLogEvent"
Filter = "LogFile='Security' AND EventCode=4720"
ComputerName = "DC01", "DC02", "FILESERVER01"
Credential = $credential
}
Get-WmiObject @wmiParams |
Select-Object ComputerName,
@{N='Zaman';E={[System.Management.ManagementDateTimeConverter]::ToDateTime($_.TimeGenerated)}},
Message |
Where-Object { $_.Zaman -gt (Get-Date).AddDays(-7) } |
Export-Csv -Path "C:Raporlaryeni_kullanicilar.csv" -NoTypeInformation -Encoding UTF8
Bu örnekte birden fazla sunucudan yeni kullanıcı oluşturma olaylarını tek seferde çekip CSV’ye kaydediyoruz. Domain ortamında haftalık rutin kontroller için harika bir başlangıç noktası.
CIM ile Daha Modern Yaklaşım
PowerShell 3.0 ile birlikte gelen Get-CimInstance komutu, WMI’ın modern versiyonu olan CIM (Common Information Model) üzerinden çalışır. WS-Man protokolünü kullandığı için daha güvenli ve firewall dostu kabul edilir:
# CIM Session ile çoklu sunucu sorgulama
$sunucular = @("DC01", "DC02", "APP01", "FILESERVER01")
$cimOptions = New-CimSessionOption -Protocol Wsman
$cimSession = New-CimSession -ComputerName $sunucular `
-SessionOption $cimOptions `
-Credential (Get-Credential)
# Ayrıcalıklı oturum açmaları sorgula
$olaylar = Get-CimInstance -ClassName Win32_NTLogEvent `
-Filter "LogFile='Security' AND EventCode=4672" `
-CimSession $cimSession
$olaylar | Group-Object PSComputerName | ForEach-Object {
Write-Host "=== $($_.Name) ===" -ForegroundColor Yellow
$_.Group | Select-Object -First 5 |
Select-Object @{N='Zaman';E={$_.TimeGenerated}}, Message |
Format-List
}
Remove-CimSession $cimSession
CIM session’ları işiniz bittikten sonra mutlaka kapatın. Açık bırakılan session’lar kaynak tüketimine yol açar.
Gerçek Dünya Senaryosu 1: Şüpheli Hesap Aktivitesi
Diyelim ki güvenlik ekibiniz bir uyarı gönderdi: “domain admin hesabı çalışma saatleri dışında aktif görünüyor.” Bu durumu WMI ile nasıl araştırırsınız?
# Belirli bir kullanıcının giriş saatlerini analiz et
$hedefKullanici = "domainadmin_ahmet"
$baslangic = (Get-Date).AddDays(-30)
$baslangicWMI = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime($baslangic)
$girisler = Get-WmiObject -Class Win32_NTLogEvent `
-Filter "LogFile='Security' AND EventCode=4624 AND TimeGenerated >= '$baslangicWMI'" `
-ComputerName "DC01" |
Where-Object { $_.InsertionStrings -contains $hedefKullanici.Split('')[1] } |
ForEach-Object {
$zaman = [System.Management.ManagementDateTimeConverter]::ToDateTime($_.TimeGenerated)
[PSCustomObject]@{
Tarih = $zaman.ToString("yyyy-MM-dd")
Saat = $zaman.Hour
DakLe = $zaman.Minute
GunTipi = if($zaman.DayOfWeek -in 'Saturday','Sunday') { "Hafta Sonu" } else { "Hafta Ici" }
Kaynak = $_.ComputerName
}
}
# Mesai disi girisler (18:00 - 08:00 arasi)
$mesaiDisi = $girisler | Where-Object { $_.Saat -lt 8 -or $_.Saat -ge 18 -or $_.GunTipi -eq "Hafta Sonu" }
Write-Host "Toplam giris: $($girisler.Count)" -ForegroundColor Cyan
Write-Host "Mesai disi giris: $($mesaiDisi.Count)" -ForegroundColor Red
$mesaiDisi | Sort-Object Tarih, Saat | Format-Table -AutoSize
Bu script ile 30 günlük giriş geçmişini analiz edip mesai dışı aktiviteleri hızla tespit edebilirsiniz. Çıktı şüpheli görünüyorsa IR (Incident Response) sürecini başlatmanız gerekebilir.
Gerçek Dünya Senaryosu 2: Servis Kurulum Tespiti
Kötü amaçlı yazılımlar sıklıkla persistence için servis kurulumu (event 7045) kullanır. Bu olayı WMI ile izleyebilirsiniz:
# Yeni servis kurulumlarını tespit et ve analiz et
$sonBirHafta = (Get-Date).AddDays(-7)
$sonBirHaftaWMI = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime($sonBirHafta)
$yeniServisler = Get-WmiObject -Class Win32_NTLogEvent `
-Filter "LogFile='System' AND EventCode=7045 AND TimeGenerated >= '$sonBirHaftaWMI'" |
ForEach-Object {
$strings = $_.InsertionStrings
[PSCustomObject]@{
Zaman = [System.Management.ManagementDateTimeConverter]::ToDateTime($_.TimeGenerated)
ServisAdi = $strings[0]
DosyaYolu = $strings[1]
BaslatmaTipi = $strings[2]
HesapAdi = $strings[4]
}
}
# Supheli yollardan yuklenen servisleri filtrele
$supheliYollar = @("temp", "appdata", "public", "downloads", "tmp")
$supheliServisler = $yeniServisler | Where-Object {
$yol = $_.DosyaYolu.ToLower()
$supheliYollar | Where-Object { $yol -like "*$_*" }
}
if ($supheliServisler) {
Write-Host "UYARI: Supheli konumlardan yuklenen servisler tespit edildi!" -ForegroundColor Red
$supheliServisler | Format-List
} else {
Write-Host "Supheli servis kurulumu bulunamadi." -ForegroundColor Green
}
Temp dizinleri veya kullanıcı profili altından kurulan servisler her zaman kırmızı bayraktır. Bu script’i haftalık otomatik çalışacak şekilde zamanlanmış görev olarak ayarlayabilirsiniz.
WMI Event Subscription ile Gerçek Zamanlı İzleme
WMI’ın en güçlü özelliklerinden biri, olay aboneliği (event subscription) ile gerçek zamanlı bildirim yapabilmesidir:
# WMI event subscription ile anlık yeni kullanici tespiti
# (Bu script calismaya devam eder, Ctrl+C ile durdurun)
$sorgu = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_NTLogEvent' AND TargetInstance.EventCode = 4720 AND TargetInstance.LogFile = 'Security'"
$watcher = New-Object System.Management.ManagementEventWatcher
$watcher.Query = New-Object System.Management.WqlEventQuery($sorgu)
$watcher.Scope = New-Object System.Management.ManagementScope("\.rootcimv2")
Write-Host "Yeni kullanici olusturma olaylari izleniyor..." -ForegroundColor Yellow
Write-Host "Durdurmak icin Ctrl+C'ye basin" -ForegroundColor Gray
try {
while ($true) {
$olay = $watcher.WaitForNextEvent()
$hedef = $olay.TargetInstance
$zaman = [System.Management.ManagementDateTimeConverter]::ToDateTime($hedef.TimeGenerated)
Write-Host "`n[ALERT] $($zaman.ToString('HH:mm:ss')) - Yeni kullanici hesabi olusturuldu!" -ForegroundColor Red
Write-Host "Makine: $($hedef.ComputerName)" -ForegroundColor Cyan
Write-Host "Mesaj: $($hedef.Message.Substring(0, [Math]::Min(200, $hedef.Message.Length)))" -ForegroundColor White
}
}
finally {
$watcher.Dispose()
Write-Host "WMI watcher kapatildi." -ForegroundColor Gray
}
Bu yaklaşımın production’da kullanımı için dikkat edilmesi gereken noktalar:
- WITHIN 5: 5 saniyelik polling aralığını temsil eder, düşürmek CPU kullanımını artırır
- Permanent subscription: Uzun vadeli izleme için
__EventFilter,__EventConsumerve__FilterToConsumerBindingnesneleri kullanılarak kalıcı subscription oluşturulabilir - Kalıcı WMI subscription’lar aynı zamanda bir saldırı vektörüdür, bu yüzden bunları da izlemeniz gerekir
WMI Güvenliği ve Audit İzleri
WMI’ın kendisi de bir saldırı yüzeyi oluşturduğundan, WMI aktivitelerini loglamak kritik önem taşır. Bunun için önce audit policy’nin doğru yapılandırıldığından emin olun:
# Mevcut audit policy ayarlarini kontrol et
auditpol /get /category:"Object Access" /r
# WMI aktivite loglamasini etkinlestir (admin yetkisi gerekir)
auditpol /set /subcategory:"Other Object Access Events" /success:enable /failure:enable
# WMI ile mevcut audit ayarlarini sorgula
Get-WmiObject -Namespace rootSecurityCenter2 -Class AntiVirusProduct |
Select-Object displayName, productState, pathToSignedProductExe
WMI logları Microsoft-Windows-WMI-Activity/Operational kanalında tutulur. Bu kanalı da izleme kapsamınıza dahil etmelisiniz.
Toplu Analiz için Script Örneği
Birden fazla sunucudan güvenlik verisi toplayıp özet rapor oluşturan kapsamlı bir örnek:
# Cok sunuculu guvenlik olay raporu
param(
[string[]]$Sunucular = @("DC01", "DC02", "APP01"),
[int]$SonKacSaat = 24,
[string]$RaporYolu = "C:Raporlarguvenlik_raporu_$(Get-Date -Format 'yyyyMMdd_HHmm').html"
)
$baslangic = (Get-Date).AddHours(-$SonKacSaat)
$baslangicWMI = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime($baslangic)
$izlenecekOlaylar = @{
4625 = "Basarisiz Giris"
4720 = "Kullanici Olusturma"
4732 = "Gruba Uye Ekleme"
7045 = "Servis Kurulumu"
4698 = "Zamanlanmis Gorev"
}
$tumOlaylar = @()
foreach ($sunucu in $Sunucular) {
Write-Host "Sorgulanıyor: $sunucu" -ForegroundColor Cyan
foreach ($eventKod in $izlenecekOlaylar.Keys) {
$logDosyasi = if ($eventKod -eq 7045) { "System" } else { "Security" }
try {
$olaylar = Get-WmiObject -Class Win32_NTLogEvent `
-Filter "LogFile='$logDosyasi' AND EventCode=$eventKod AND TimeGenerated >= '$baslangicWMI'" `
-ComputerName $sunucu `
-ErrorAction Stop
foreach ($olay in $olaylar) {
$tumOlaylar += [PSCustomObject]@{
Sunucu = $sunucu
EventKod = $eventKod
OlayTipi = $izlenecekOlaylar[$eventKod]
Zaman = [System.Management.ManagementDateTimeConverter]::ToDateTime($olay.TimeGenerated)
Kullanici = $olay.User
}
}
}
catch {
Write-Warning "$sunucu - $eventKod sorgulanirken hata: $_"
}
}
}
# Ozet istatistikler
Write-Host "`n=== OZET RAPOR ===" -ForegroundColor Yellow
$tumOlaylar | Group-Object OlayTipi | ForEach-Object {
Write-Host "$($_.Name): $($_.Count) olay" -ForegroundColor White
}
$tumOlaylar | Export-Csv -Path ($RaporYolu -replace '.html', '.csv') `
-NoTypeInformation -Encoding UTF8
Write-Host "`nRapor kaydedildi: $RaporYolu" -ForegroundColor Green
Performans ve En İyi Uygulamalar
WMI sorguları yanlış kullanıldığında ciddi performans sorunlarına yol açabilir. Şu kurallara uymaya özen gösterin:
- Filter’ı WMI tarafında kullanın:
Get-WmiObject -Filter "..."yerine ardındanWhere-Objectile filtrelemek çok daha yavaştır. Filtreyi her zaman-Filterparametresinde belirtin - Zaman aralığını sınırlayın: Tarih filtresi olmadan büyük log dosyalarını sorgulamak hem yavaş hem de kaynak yoğundur
- Sadece ihtiyaç duyduğunuz özellikleri çekin:
Select-Objectile gereksiz alanları sorgu düzeyinde değil, aktarım sonrasında elden geçirin - Bağlantı havuzu kullanın: Çok sayıda sunucuya bağlanırken CimSession kullanmak bağlantı overhead’ini azaltır
- Hata yönetimini ihmal etmeyin: Uzak bağlantılar her zaman başarıyla sonuçlanmaz, try-catch bloklarını kullanın
- WMI namespace’lerini tanıyın: Güvenlik logları
rootcimv2altındadır ama bazı özel sorgular içinrootSecurityCenter2veyarootMicrosoftDNSgibi farklı namespace’ler gerekebilir
Sık Karşılaşılan Sorunlar
Sahada WMI ile güvenlik sorgularken en çok şu sorunlarla karşılaşırsınız:
- “RPC server is unavailable” hatası: Hedef makinede Windows Firewall WMI trafiğini bloke ediyor olabilir.
netsh advfirewall firewall set rule group="Windows Management Instrumentation (WMI)" new enable=yeskomutu ile açabilirsiniz - “Access Denied” hatası: WMI namespace izinlerini veya DCOM izinlerini kontrol edin.
wmimgmt.mscile grafik arayüzden ayarlayabilirsiniz - Yavaş sorgular: Zaman filtresi olmadan büyük security loglarını sorgulamak dakikalar sürebilir. Her zaman tarih aralığı belirtin
- Encoding sorunları:
Messagealanındaki özel karakterler bazen bozuk gelir. Çıktıyı CSV’ye kaydederken-Encoding UTF8parametresini kullanın - Win32_NTLogEvent vs Get-WinEvent: Modern sistemlerde
Get-WinEventdaha hızlı ve yeteneklidir. WMI tabanlı çözümler özellikle eski sistemlerle uyumluluk veya uzaktan programatik erişim gerektiğinde tercih edilmelidir
Sonuç
WMI, Windows güvenlik olaylarını sorgulamak için olgun ve güçlü bir araçtır. Özellikle heterojen ortamlarda, eski PowerShell sürümlerinin bulunduğu sistemlerde veya programatik entegrasyon gerektiren durumlarda değerini kanıtlar. Ancak modern Windows ortamlarında Get-WinEvent ve CIM cmdlet’lerini tercih etmek genellikle daha iyi performans ve daha az baş ağrısı anlamına gelir. WMI’ı iyi anlamak, hem savunma hem de tehdit avcılığı açısından sysadmin’lerin elinde bulundurması gereken bir beceridir. Bu yazıdaki örnekleri kendi ortamınıza uyarlayarak başlayın, zamanla bu sorguları otomatik raporlama sistemlerinize entegre edin. Güvenlik izleme reaktif değil proaktif bir aktivite olmalı ve WMI bu proaktif yaklaşımın önemli yapı taşlarından birini oluşturuyor.