masaüstü uygulaması çalışırken EXE dosyasının yanında çeşitli kütüphaneleri kullanır. kütüphanelerden biri beklenmeyen konumdan yüklenirse uygulama, geliştiricinin amaçladığından farklı kod çalıştırabilir. DLL yüklemelerini incelerken yüzden iki soruya bakarız: Hangi DLL yükleniyor dosyayı kim değiştirebiliyor?
Önce uygulama DLL arasındaki ilişkiye Windows’un DLL arama sırasına bakalım. Ardından örnek uygulamanın yükleme kayıtları üzerinden DLL hijacking davranışını inceleyip geliştirici tarafında alınabilecek önlemlere geçelim.
Uygulama DLL Arasındaki İlişki Nasıl Kurulur?raporlama uygulaması düşünelim. Kullanıcı arayüzü RaporApp.exe içinde, rapor biçimlendirme işlevleri ise RaporMotoru.dll içinde bulunuyor olsun. Kullanıcı rapor istediğinde uygulama kütüphanenin sunduğu fonksiyonları çağırarak sonucu alabilir.
Windows, native DLL’yi uygulamanın sanal adres alanına eşler. Uygulama, DLL’nin dışa aktardığı fonksiyonları çağırır, parametreleri iletir dönüş değerlerini kullanır. DLL kodu onu çağıran sürecin iş parçacığının bağlamında çalışır.
Uygulama DLL’ye iki şekilde bağlanabilir. Yükleme zamanında bağlamada gerekli bağımlılıklar uygulama açılırken çözülür. Çalışma zamanında bağlamada ise uygulama, ihtiyaç duyduğu anda LoadLibrary veya LoadLibraryEx kütüphaneyi yükler GetProcAddress ilgili fonksiyonun adresini. Microsoft iki yöntemi DLL çalışma modeli belgesinde açıklar.
Şekil 1: Uygulama, kendi adres alanına yüklenen DLL’nin fonksiyonlarını çağırır.
Burada Windows’un native DLL yükleme davranışını inceliyoruz.NET assembly çözümlemesi farklı kurallara sahiptir.NET uygulamasının native bağımlılıkları ise ayrıca değerlendirilmelidir.
DLL Hijacking Nedir?DLL hijacking, uygulamanın beklediği kütüphane yerine saldırganın kontrol ettiği aynı adlı kütüphaneyi yüklemesidir. Tam yol belirtilmemesi, aramanın gereğinden fazla dizini kapsaması veya DLL’nin bulunduğu konuma standart kullanıcının yazabilmesi soruna yol açabilir.
Raporlama uygulaması örneğine dönersek geliştirici, ürünle birlikte dağıttığı RaporMotoru.dll dosyasının kullanılmasını bekler. Dosya adının eşleşmesi bunu garanti etmez. Yüklenen dosyanın, uygulamanın güvendiği koruduğu konumdan gelmesi gerekir.
Yüklenen DLL, uygulamayla aynı güvenlik bağlamında dosyalara, ağ kaynaklarına işletim sistemi nesnelerine erişebilir. Standart kullanıcıyla çalışan uygulamada etki, kullanıcının yetkileriyle kod çalıştırılmasıdır. Uygulama daha yüksek yetkiyle çalışıyor düşük yetkili kullanıcı yüklenen DLL’yi değiştirebiliyorsa yerel yetki yükseltme söz konusu olabilir.
DLL injection DLL hijacking sıkça karıştırılır. Injection, başka sürece kod yükletmeyi hedefler. Hijacking örneğimizde ise uygulama, kendi yükleme çağrısı sırasında yanlış DLL’yi seçer.
DLL Search Order: Windows DLL’yi Nerede Arar?DLL search order, yalnızca modül adı verildiğinde Windows’un DLL’yi bulmak için izlediği sıradır. dizinlerin sırayla aranmasını basitçe gösteriyor. Ayrıntılarda Safe DLL Search Mode açıkken standart arama davranışını kullanan paketsiz uygulamaları esas alıyoruz. Kullanılan yükleme yöntemi uygulamanın ayarları sırayı değiştirebilir.
Şekil 2: DLL aramasının genel mantığı. Arama sırasının ayrıntıları aşağıda. Yükleyici, dizinlerde aramaya geçmeden önce DLL redirection, API sets, Side-by-side (SxS) manifest yönlendirmesi, önceden yüklenmiş modüller KnownDLLs gibi mekanizmaları kontrol. Windows 11 sürüm 21H2 sonrasında paket bağımlılık grafiği sırada yer.
Ardından uygulamanın dizini, sistem dizini, 16 bit sistem dizini, Windows dizini, geçerli çalışma dizini PATH dizinleri değerlendirilir. Uygulamanın dizini EXE dosyasının bulunduğu konumdur. Geçerli çalışma dizini ise sürecin anda kullandığı çalışma konumudur. iki yol aynı olmak zorunda değildir.
Safe DLL Search Mode çalışma dizinini sırada geriye taşır ancak tamamen kaldırmaz. Paketli uygulamalar, manifestler, SetDllDirectory, AddDllDirectory LOAD_LIBRARY_SEARCH_* bayrakları davranışı değiştirebilir. Ana DLL’nin tam yolla yüklenmesi bağımlı DLL’lerin otomatik olarak aynı güvenceyle çözüleceği anlamına gelmez. Güncel ayrıntılar Microsoft’un DLL arama sırası belgesinde bulunabilir.
Arama sırasını bilmek, yükleme kayıtlarını yorumlamayı kolaylaştırır. İncelemede yine DLL’nin hangi yoldan yüklendiğine bakarız. Geliştirici tarafında ise uygulamanın kod yükleyebileceği konumları sınırlamak gerekir.
DLL Yükleme Ne Zaman Güvensiz Hâle Gelir?Yalnızca DLL adının kullanıldığı çağrıya bakarak zafiyet kararı veremeyiz. Aranan konumların izinlerini uygulamanın hangi dosyayı yüklediğini incelemek gerekir.
Koşulİncelenecek soruOlası sonuçDLL tam yol olmadan isteniyorYükleyici hangi konumları değerlendiriyor?Aynı adlı farklı dosya seçilebilirAranan konumlardan biri yazılabilirStandart kullanıcı DLL ekleyebilir veya değiştirebilir ?Dosyanın kaynağı saldırgan kontrolüne geçebilirUygulama ilgili DLL’yi gerçekten yüklüyorBaşarılı yükleme hangi tam yoldan gerçekleşti?Kontrol edilen dosya süreç içine alınabilirDLL kodu süreç içinde çalışıyorKodun çalıştığını gösteren çıktı var ?Uygulamanın yetkileriyle kod çalıştırılmasıUygulama daha yüksek yetkiye sahipBaşlangıç sonuç kimlikleri gerçekten farklı ?Koşullar uygunsa yerel yetki yükseltmeNAME NOT FOUND kaydı, dosya erişiminin başarısız olduğunu gösterir. Uygulama daha sonra başka konumdan beklenen DLL’yi yüklemiş olabilir. Yazılabilir klasör bulduğumuzda uygulamanın konumdaki dosyayı seçip seçmediğini kodun çalışıp çalışmadığını kontrol ederiz.
Güvenli DLL Yükleme ÖrneğiÖnce DllLoadingDemo.exe üzerinden güvenli yükleme örneğine bakalım. Uygulama, Windows sistem dizinindeki dbghelp.dll dosyasını tam yol LOAD_LIBRARY_SEARCH_SYSTEM32 seçeneğiyle yükledi.
SafiyeMonitor kaydında çağrının başarılı olduğu DLL’nin C:\Windows\System32\dbghelp.dll yolundan geldiği görüldü.
Şekil 3: SafiyeMonitor kaydında DLL adı, kullanılan API, işlem sonucu tam yükleme yolu görülüyor. Dosyanın sistem dizinindeki konumu Windows Gezgini’nde görülebiliyor.
Şekil 4: Yükleme kaydındaki dbghelp.dll dosyasının System32 içindeki konumu. örnekte kayıt dosyanın konumu örtüşüyor. Uygulama, beklenen DLL’yi sistem dizininden yüklüyor.
Laboratuvarda DLL HijackingYükleme davranışını görmek için VulnerableLoader.exe ReportPlugin.dll dosyalarından oluşan laboratuvar kullandık.
- VulnerableLoader.exe, DLL’yi yalnızca ReportPlugin.dll adıyla yükledi.
- ReportPlugin.dll, PowerShell penceresi açıp whoami komutunu çalıştırdı.
- EXE DLL, standart kullanıcının yazabildiği aynı geçici laboratuvar klasöründeydi.
- Uygulama standart kullanıcı yetkileriyle çalıştırıldı.
örnekte DLL kodu, uygulamayı başlatan standart kullanıcının yetkileriyle çalıştı.
Zafiyetli çağrıÖrnekteki yükleme çağrısı şöyle:
LoadLibraryW("ReportPlugin.dll")Çağrı yalnızca dosya adını verir. Yükleyici dosyanın kaynağını süreç için geçerli arama kurallarına göre belirler. Laboratuvarda EXE’nin bulunduğu yazılabilir klasöre aynı adlı DLL yerleştirildiğinde uygulama dosyayı seçti.
Şekil 5: LoadLibraryW çağrısında DLL’nin tam yolu belirtilmemiş. Örnek DLL’nin içeriği DLL’nin dışa aktardığı RunLab fonksiyonu, yeni PowerShell penceresi. pencerede profil yüklemesi kapalıydı yalnızca whoami komutu çalıştı.
Şekil 6: PowerShell penceresinde whoami komutunu çalıştıran örnek. Yüklenen DLL’nin doğrulanması SafiyeMonitor kaydında LoadLibraryW çağrısının başarılı olduğu görüldü. Kayıt, ReportPlugin.dll dosyasının sürece yüklendiğini gösteriyor.
Şekil 7: ReportPlugin.dll için başarılı yükleme kaydı. Kodun çalıştığını görmek DLL içindeki fonksiyon çağrıldığında PowerShell penceresi açıldı whoami çıktısı alındı. Çıktıdaki kullanıcı, uygulamayı başlatan standart kullanıcıyla aynıydı.
Şekil 8: DLL’nin açtığı PowerShell penceresinde kullanıcı kimliği. sonuç, DLL kodunun çalıştığını gösteriyor. Uygulama standart kullanıcı yetkileriyle çalıştığı için testte yetki yükseltme gerçekleşmedi.
Kayıtlar bize ne söylüyor? GözlemKanıtladığıTek başına kanıtlamadığıDLL adı çağrıda görülüyorUygulama modülü çözmeye çalışıyorDosyanın yüklendiğiYazılabilir klasör bulunduStandart kullanıcı buraya dosya koyabiliyorUygulamanın dosyayı seçeceğiBaşarılı yükleme kaydı alındıBelirli DLL süreç içine yüklendiFonksiyonun çalıştırıldığıwhoami çıktısı alındıDLL içeriği uygulama bağlamında çalıştıYetki yükseltme gerçekleştiğiBaşlangıç sonuç kimliği farklıBir güven sınırı aşılmış olabilirFarkın DLL yüklemesinden kaynaklandığıRaporda yükleme kaydını, kodun çalıştığını gösteren çıktıyı varsa yetki değişimini ayrı ayrı açıklamak gerekir.
Güvenlik İncelemesinde Nelere Bakılır? Test ortamı uygulamanın yetkileriUygulamanın sürümünü, EXE yolunu, kullanıcı kimliğini, bütünlük düzeyini (integrity level), süreç mimarisini test edilen işlevi kaydetmek gerekir. Analiz aracının yönetici olarak çalışması, incelenen uygulamanın aynı yetkiye sahip olduğu anlamına gelmez.
DLL yükleme kayıtlarıProcess Monitor veya eşdeğer çalışma zamanı gözlem aracıyla hedef sürecin DLL hareketleri izlenebilir. CreateFile dosya erişim girişimini, başarılı Load Image ise modülün süreç içine eşlendiğini gösterir.
Yalnızca hata satırlarına bakmak yanıltıcı olabilir. Aynı DLL adına ait sonraki başarılı yüklemeler tam dosya yolları incelenmelidir. Süreç, DLL’yi kısa süreliğine yükleyip kaldırıyorsa anlık modül listesi bunu kaçırabilir. Olayları zaman sırasıyla tutan kayıtlar durumda daha kullanışlıdır.
Dosya dizin izinleriDLL’nin tam yolu belirlendikten sonra dosyanın üst dizinlerinin izinlerine bakılır. Standart kullanıcının dosya oluşturma, değiştirme, silme yeniden adlandırma hakları, grup üyelikleriyle devralınan izinlerle birlikte değerlendirilmelidir.
Kurulum dizini, eklenti dizini, güncelleme alanı, geçici klasörler çalışma dizini farklı izinlere sahip olabilir. İzinler, test edilen kullanıcının erişim belirteciyle (access token) kontrol edilmelidir.
DLL Hijacking Nasıl Önlenir? Tam yolu güvenilir kaynaktan oluşturmakÖrnekteki çağrı yalnızca modül adını kullanıyordu:
module = LoadLibraryW("ReportPlugin.dll")Tam yolu uygulamanın korunan kurulum bilgisinden oluşturup bağımlılık aramasını gerekli dizinlerle sınırlayabiliriz:
trustedFullPath = "C:\Program Files\OrnekUygulama\bin\ReportPlugin.dll"flags = LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR |LOAD_LIBRARY_SEARCH_SYSTEM32 module = LoadLibraryExW(trustedFullPath, null, flags)
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR ana DLL’nin dizinini yalnızca onun bağımlılıkları için aramaya ekler tam yol gerektirir. LOAD_LIBRARY_SEARCH_SYSTEM32 sistem dizinini kapsar. çağrı çalışma dizini genel PATH dizinlerini ilgili yüklemenin bağımlılık aramasından çıkarır. Bayrakların güncel davranışı LoadLibraryExW belgesinde tanımlanır.
yol kullanıcı girdisinden, geçerli çalışma dizininden veya kullanıcının değiştirebildiği yapılandırma değerinden türetilmemelidir. Yükleme başarısız olduğunda uygulama, güvenilirliği belirsiz başka konumlarda aramaya devam etmemelidir.
Süreç genelindeki arama kapsamını daraltmakBirden fazla bileşen DLL yüklüyorsa SetDefaultDllDirectories süreç genelindeki varsayılan arama kapsamı belirlenebilir. Gerekli ek dizinler AddDllDirectory açıkça eklenebilir. LOAD_LIBRARY_SEARCH_USER_DIRS ifadesindeki user, kullanıcının bütün profil klasörlerini değil, uygulamanın API’lerle açıkça eklediği dizinleri anlatır.
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS, uygulama dizinini, sistem dizinini API’lerle eklenen dizinleri kapsar. Microsoft, varsayılan aramanın kapsamla sınırlandırılmasını önerir. Ayrıntılar SetDefaultDllDirectories belgesinde bulunabilir.
Kod veri dizinlerini ayırmakEXE DLL dosyaları, standart kullanıcıların değiştiremediği kurulum dizinlerinde tutulmalıdır. Raporlar, günlükler, önbellekler kullanıcı ayarları ayrı veri dizinlerine yazılmalıdır. Bağlantı veya güncelleme sorununu çözmek için uygulamanın tüm klasörüne yazma izni vermek, kullanıcının çalıştırılacak kodu değiştirebilmesine yol.
Kurulum güncelleme araçları izinleri korumalıdır. Güncelleme sırasında dosyalar geçici konumdan kurulum dizinine güvenli biçimde taşınmalı, işlem sonunda yürütülebilir bileşenler dizin izinleri yeniden kontrol edilmelidir.
Eksik bağımlılıkta güvenli davranmakZorunlu DLL güvenilir konumda bulunamıyorsa ilgili işlev, anlaşılır hata mesajıyla durmalıdır. İsteğe bağlı bileşen eksikse yalnızca ona bağlı özellik devre dışı bırakılabilir. Uygulama, çalışmaya devam etmek için çalışma dizininde veya rastgele PATH konumlarında alternatif kopya aramamalıdır.
Düzeltmenin DoğrulanmasıDüzeltmeden önceki sonraki sürümler, aynı kullanıcıyla aynı işlev akışı izlenerek karşılaştırılmalıdır. Her iki sürümün kayıtlarında süreç kimliği tam yükleme yolu görünmelidir.
KontrolBeklenen davranışUygulamanın normal kullanımıİşlev beklenen şekilde tamamlanırYüklenen modülün yoluKorunan tanımlanmış konumla eşleşirKod dizininin izinleriStandart kullanıcı değiştirme hakkına sahip değildirZorunlu bağımlılığın eksikliğiİlgili işlev anlaşılır hata mesajıyla dururİsteğe bağlı bağımlılığın eksikliğiYalnızca ilgili özellik devre dışı kalırGüncelleme sonrası durumYükleme politikası dosya izinleri korunurSon kontrolde, beklenen DLL’nin korunan konumdan yüklendiğini uygulamanın normal işlevlerinin çalıştığını görmeliyiz. Daha önce kullanılan yazılabilir konumun arama kapsamından çıkarıldığını yükleme kayıtlarından doğrulamalıyız.
konuyla ilgili forum tartışmaları- Windows 11 domainde ıma bağlanma sorunu ?
- Şifre olmadan Win 11 kullanmak mümkün mü ?
- Farklı Ağlarda Tek Yazıcı Kullanımı
- Başvuru hesabı anda kilitlenmiş buna oturum açılamayabilir
- Host dosyası sorunu
- Windows 11 Credential unutma