Thick Client Sızma Testi: DLL Hijacking

Modern Windows uygulamaları, fonksiyonelliklerini modüler hale getirmek için Dynamic Link Library (DLL) dosyalarına güvenir. Ancak bu güven ilişkisi, kütüphane arama hiyerarşisindeki mantıksal hatalarla birleştiğinde Red Team operasyonlarında yetki yükseltme ve kalıcılık sağlayan kritik bir DLL Hijacking zafiyetine dönüşür.

Bu yazıda, DLL Hijacking zafiyetini, Windows’un kütüphane arama hiyerarşisini ve bu zafiyetin tespit-doğrulama-exploit sürecini teknik ayrıntılarıyla ele alıyoruz.


1. DLL Hijacking Nedir?

DLL Hijacking, bir uygulamanın ihtiyaç duyduğu orijinal (benign) kütüphaneyi (.dll) ararken arama hiyerarşisindeki bir dizine, saldırganın zararlı bir dosyayı yerleştirmesi işlemidir. Uygulama, kütüphanenin tam yolunu (absolute path) bilmediği durumlarda Windows Loader’ın arama algoritmasına güvenir.

Eğer saldırgan, loader sistem dizinine bakmadan önce kütüphaneyi bulabileceği bir konuma (örneğin uygulamanın kendi dizinine) yazma yetkisine sahipse, uygulama orijinal (benign) kütüphane yerine saldırganın kodunu belleğe yükler ve execute eder.


2. Windows DLL Arama Sırası (Search Order)

Windows, bir DLL çağrılırken belirli bir hiyerarşiyi takip eder. Standart (Safe) arama sırası şu şekildedir:

  1. Uygulamanın Yüklendiği Dizin: Uygulamanın .exe dosyasının bulunduğu klasör.
  2. Sistem Dizini: C:\Windows\System32
  3. 16-bit Sistem Dizini: C:\Windows\System
  4. Windows Dizini: C:\Windows
  5. Mevcut Çalışma Dizini (Current Directory)
  6. PATH Ortam Değişkenindeki Dizinler

Kritik Nokta: Zafiyet genellikle uygulamanın 1. sırada bulamadığı bir dosyayı 2. sıradaki sistem dizininde araması, ancak saldırganın 1. sıradaki dizine müdahale edebilmesiyle (yazma yetkisi) ortaya çıkar.


3. Tespit ve Analiz Süreci

Bu teorik yapıyı somutlaştırmak için DVTA (Damn Vulnerable Thick Client Application) örneği üzerinden metodolojiyi inceleyelim.

3.1 Process Monitor ile Filtreleme

Exploit öncesi tespit aşamasında uygulama çalışırken Process Monitor (ProcMon) üzerinde gürültüyü azaltacak şu filtreler sırasıyla uygulanır:

Görsel 1 - Process Name Filtresi (DVTA.exe)

Görsel 2 - Path Filtresi (ends with .dll)

Görsel 3 - Result Filtresi (NAME NOT FOUND)

3.2 “NAME NOT FOUND” Hatalarının Analizi

Filtreleme sonucunda, uygulamanın arama hiyerarşisi içerisinde bulamadığı tüm dosyalar listelenir. Fakat bizim için kritik olan, uygulamanın çalıştığı dizini (Application Directory) hedefleyen başarısız sorgulardır.

Görsel 4 - NAME NOT FOUND Listesi

Görsel 4’te görüldüğü üzere, DVTA.exe süreci çalışma dizini içerisinde ncrypt.dll dosyasını sorgulamakta fakat “NAME NOT FOUND” yanıtı almaktadır. Bu durum, Windows Loader’ın arama hiyerarşisinde sistem dizinlerine geçmeden hemen önce, uygulama dizini seviyesinde bir DLL Hijacking manipülasyonuna imkan tanımaktadır.

3.3 icacls ile Exploit Edilebilirliğin Doğrulanması

Tespit edilen boşluğun exploit edilebilir olması için saldırganın o dizine dosya yazabilmesi gerekir.

Görsel 5 - icacls Çıktısı (student kullanıcısı F yetkisi)

Görsel 5’te yapılan sorgulama, düşük yetkili kullanıcının (student) ilgili dizin üzerinde (F) yani Full Access yetkisine sahip olduğunu gösterir. Ancak gerçek dünya senaryolarında sadece (F) değil, şu izin kombinasyonları da exploit için yeterlidir:

  • (F) - Full Access: Dizin üzerinde dosya oluşturma, silme ve izinleri değiştirme dahil her türlü yetkiyi verir.
  • (M) - Modify: Dosya oluşturma ve silme yetkisi verir. DLL Hijacking için en yaygın exploit noktasıdır.
  • (W) - Write: Dizin içine yeni dosya yazılmasına izin verir. Mevcut dosyaları silemeseniz bile “eksik” olan DLL’i buraya koymanızı sağlar.
  • (AD) - Append Data: Mevcut veriyi değiştiremese bile yeni dosya/veri eklenmesine olanak tanır.
  • (OI)(CI): “Object Inherit” ve “Container Inherit” anlamına gelir; bu izinlerin alt dosya ve klasörlere otomatik olarak miras kaldığını kanıtlar.

4. Exploit Aşaması: DLL Hazırlama

İzinler doğrulandıktan sonra, eksik olan ncrypt.dll (veya hedef DLL) dosyasının yerine geçecek bir payload hazırlamamız gerekir.

Saldırı senaryosunu gerçekleştirmek için Custom DLL Payloads (msfvenom veya özel kaynak kodları) ile hazırlanan zararlı ncrypt.dll dosyası, uygulamanın arama yaptığı dizine yerleştirilir. Uygulama bir sonraki açılışında, Windows Loader mekanizması sistem dizininden (System32) önce uygulamanın kendi dizinine bakacağı için orijinal kütüphane yerine bizim yerleştirdiğimiz zararlı kütüphaneyi yükler. Böylece payload’ımız hedef uygulamanın yetkileriyle çalıştırılmış olur.

Hazır Exploit Dosyaları: Bu analizde kullanılan exploit kaynak kodlarına ve derlenmiş hazır exploit dosyalarına (x86/x64) GitHub Repomdan (DLL-Hijacking-PoC) ulaşabilirsiniz. Testlerinizde zaman kazanmak için bin/ klasöründeki hazır DLL’leri kullanabilirsiniz.

4.1 Mimari Uyumu (x86 vs x64)

Sızma testlerinde en sık yapılan hata mimari uyuşmazlığıdır. Windows Loader, 64-bit bir sürecin içine 32-bit bir DLL (veya tam tersi) yükleyemez.

  • Hedef uygulama 32-bit ise -> exploit32.dll
  • Hedef uygulama 64-bit ise -> exploit64.dll

4.2 Payload Mantığı

Repodaki DLL’in çalışma mantığı oldukça basittir. DLL_PROCESS_ATTACH olayı tetiklendiğinde (yani uygulama DLL’i yüklediği anda) kanıt olması amacıyla calc.exe (Hesap Makinesi) çalıştırılır.

Örnek C kodu:

#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hModule,
                      DWORD  ul_reason_for_call,
                      LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        WinExec("calc.exe", SW_SHOW);
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Bu yapı, zafiyetin başarılı bir şekilde tetiklendiğini doğrulamak için yeterlidir.

Önemli Metodoloji Notu

Analiz sürecinde unutulmaması gereken en kritik nokta şudur: Her “NAME NOT FOUND” hatası bir zafiyet değildir. Bir uygulamanın eksik bir DLL araması potansiyel bir fırsat olsa da, bu durum icacls ile dosya sistemi izinleri seviyesinde doğrulanmadığı sürece sadece bir log kaydıdır. Gerçek bir zafiyet, “eksik dosya” ile “yetersiz izinlerin” kesiştiği noktada oluşur.


5. Savunma ve Önleme

Zafiyeti önlemek için geliştiricilerin ve sistem yöneticilerinin alabileceği temel önlemler:

  • Absolute Path: LoadLibrary çağrılarında DLL’in tam yolu belirtilmelidir.
  • İzin Yönetimi: Uygulama dizinlerinde Users grubuna sadece Read & Execute yetkisi verilmeli, yazma yetkisi kesinlikle kısıtlanmalıdır.
  • API Kısıtlamaları: SetDefaultDllDirectories kullanılarak arama dizinleri sadece güvenli yollarla sınırlandırılmalıdır.

Görsel Referansları

Bu yazıdaki teknik süreci görselleştirmek amacıyla kullanılan materyaller aşağıdaki kaynaklardan alınmıştır: