SSDT(System Service Descriptor Table)Hook
Serinin 1.Partında user tarafındaydık bugün kernele iniyoruz.Driver geliştirme ve rootkitler hakkında bilgilerimiz burada devreye giriyor.
System Service Descriptor Table
Sistem çağrılarının bulunduğu tablodur.4 tane SST(System Service Table) içerir.
Mesela NtOpenProcess API’si çağrıldığında işlenecek fonksiyon bu tablolara bakılarak
bulunur.SSDT Hook edilmesi ise NtOpenProcess API‘si çağrıldığından gerçek fonksiyonu değil tanımladığımız fonksiyonun çağrılmasıdır.Kendi fonksiyonumuzu tanımlamak için aynı prototipte bir fonksiyon adresi ile yer değiştirilmesi gerekir.”Ntoskrnl” Windows_NT_Operation_Kernel‘ in kısaltılmışıdır.Kernel Image olarak bilinir.Proses ve bellek yönetimi gibi çeşitli hizmetlerden sorumludur.
SSDT Hook sadece Rootkit’ler tarafından değil Anti-Virus üreticileri tarafından sistemin işleyişini kontrol etmek için kullanılır.
Hooking’den önce ve sonrası
SSDT yapısı aşağıdaki gibi tanımlanıyor.
SSDT Hooking’e başlamadan önce bir durum daha var.Tablonun bulunduğu alan yazmaya karşı korulmalıdır.Nasıl kaldırılacağını araştırdıktan sonra bir kaç yöntem gördüm.
CR0 yazmacının WP bitini değiştirmek
MDL(Memory Descriptor List) kullanmak
CR0 yani Control Register 0 işlemcinin çalışmasını düzenleyebilen flaglere sahiptir.WP(WriteProtect) 0 set edildiğinde işlemci read-only alanların yazılmasına izin vermez.WP bitini bozduğumuzda bu korumayı atlatmış oluruz.
SSDT Hook’da amacımız tabloda bulunan bir fonksiyonun adresini alıp, aynı prototipde bir fonksiyon yaratıp o adrese yerleştirmek.
SSDT yapısını tanımladıktan sonra servis numaralarını almak için GetServiceNumber‘ı tanımladık.
Orjinal adreslerin yerine koyacağımız fonksiyonları tanımladık..Hedeflediğimiz
proses(calc.exe) ismini almak için ZwQueryInformationProcess fonksiyonundan
yararlanıyoruz.
NTTerminateProcess ve NtLoadDriver fonksiyonlarının orjinal adreslerini depolamak için değişkenler tanımladık.
NtTerminateProcess orjinal fonksiyonun yerine koyacağımız aynı prototipte bir fonksiyon yaratıyoruz.Amacımız prosesler içinde calc.exe’yi bulup görev yöneticisinde işlemi sonlandırmaya çalışırken bunun engellemesi.Bu oluşturduğumuz fonksiyonu
NtTerminateProcess’in orjinal adresine yerleştireceğiz.
HookNtLoadDriver fonksiyonunda ise sürücümüzü DebugView’de görüntülemek için
oluşturduk.
Yukarıda main bölümünde(DriverEntry)Orjinal fonksiyonların adreslerini almak için ilk önce servis numaralarını alıyoruz.Sonra wp bitini bozuyoruz yani read-only moddan çıkartıyoruz.Aldığımız servis numaraları sayesinde fonksiyonların adreslerini alıyoruz ve bunu dizide saklıyoruz.Bu orjinal adresleri değişkenlere aktarıyoruz.Orjinal adreslerin tutulduğu SSDTAddress dizisine sırayla yarattığımız aynı prototipteki fonksiyonları yerleştiriyoruz ve tekrar wp bitini read-only konumuna getiriyoruz.
Kaynak kodumuzu yazdığımıza göre test etmeye geldi sıra.
Visual Studio 2015 üzerinde geliştirdim ve test edeceğim Windows sürümü olarak
Windows7’yi seçtim.
Yazdığımız hook çalıştı.Kernel’de fonksiyonların tutulduğu tablodan, hedeflediğimiz fonksiyonu alıp yerine istediğimiz işlemleri yapacak bir fonksiyon oluşturup yerleştirdik ve kernel seviyesinde bir müdahale ettik.
Kaynak kodu github adresimde paylaştım.