21 Ekim 2017 Cumartesi

Windows Sürücü Programlama Ve Hata Ayıklama

Fikir Sahibi Olmak İçin
Windows çekirdek (Kernel) programlamaya başlamadan önce, öğrenildiğinde ne gibi faydalar sağlayabileceği ve neler yapabileceğimiz ile ilgili kernelturk bloğunda bulunan blog yazısının okunması faydalı olabilir.

Gereksinimler
Windows çekirdek programlamaya başlamadan önce, C programlama dilini fonksiyon pointer'larını, callback fonksiyonları vs anlamak gerekiyor.Eğer bir user mod sürücüsü geliştireceksek C++ ve COM teknolojisini anlamak gerekiyor.

Programlama İçin Gerekli Araçlar
İlk olarak çalışma ortamını sağlamak adına, sanal makina(Virtual Box) içerisine bir windows işletim sistemi kuruyorsunuz.Tercihen windows 10 kurulabilir.Yine aynı sanal makina içerisine Visual studio, SDK, WDK ve OSR driver Loader yazılımlarını indirip kuruyorsunuz.Yakın zamanda Visual Studio 2017'nin driver geliştirme desteği bulunmuyordu.Visual Studio 2017 için driver geliştirme desteği yeni eklenmiş diyebilirim.Şuan için önerim sırayla Visual Studio Community 2015, SDK, WDK araçlarını araçlarını indirip kurmanızdır.

Sanal makina içerisine gerekli yazılımlar kurulduktan sonra, bu sanal makina içerisindeki işletim sistemini, işletim sisteminin çekirdeğinde (kernel) çalışan yazılımların(sürücü) doğru çalışıp çalışmadığını kontrol etmek, hata ayıklama yapabilmek için aynı zamanda ana makinamıza'da SDK araçlarını kuruyoruz.
Kurduğumuz SDK içerisinde yer alan windbg.exe ile sanal makinayı debug edeceğiz.
WinDbg programı C:\Program Files (x86)\Windows Kits\10\Debuggers\x64 veya C:\Program Files (x86)\Windows Kits\10\Debuggers\x86 klasörleri altında bulunabilir.
Buraya kadar geldiysek programlama yapabilmek için gerekli araçları sağlamış oluyoruz.


Ayarların Yapılması
WinDbg ile sanal makina üzerinde hata ayıklama yapabilmek için kurduğumuz sanal makina ayarlarında bulunan Seri Bağlantı Noktalarını aşağıda görüldüğü gibi aktifleştiriyoruz.





Yol/Adres bilgisini WinDbg ile sanal makinayı debug ederken kullanacağız.


Nihayet Sürücü Geliştirmeye Başlamak

Artık Visual studio ile sürücü geliştirmeye ve geliştireceğimiz sürücüyü sanal makinaya yüklemeye ve debug etmeye hazırız.
File -> New -> Project -> Kernel Mode Driver, Empty (KMDF) ile yeni bir proje açıyoruz.


Projeye mydriver.c isminde yeni bir kaynak kod dosyası ekliyoruz.(Add -> New Item)


Proje ayarlarındaki Driver Settings bölümünde bulunan değerler aşağıdaki olmalıdır.
Target OS Version = Windows 10
Target Platform = Desktop 

Projeyi derlediğinizde aşağıdaki gibi bir hata mesajı alırsanız;
Error C2220 warning treated as error - no 'object' file generated KMDFDriver1 

Projenin özelliklerinden Linker bölümünden "Treat Linker Warning As Error" değerini "No (/WX:NO)" olarak ve  C/C++ "Warning Level" değerini "Level1 (/W1)" olarak değiştirmeniz gerekecek.


Proje başarılı bir şekilde derlendiğinde aşağıdaki gibi bir derleyici çıktı mesajı alacağız.

Yukarıdaki mesajlardan projenin başarılı bir şekilde derlediğini ve Visual studio'nun otomatik olarak bir test sertifikası oluşturup bu sertifikayı bilgisayardaki sertifika deposuna eklediğini ve sonrasında da bu sertifika ile KMDFDriver1.sys PE formatında ki dosyayı imzaladığını anlıyoruz.


Oluşan sertifika ve sürücü dosyası aşağıdaki gibi olacaktır.Buradaki KMDFDriver1.sys dosyasına sağ tıklayıp özellikler Digital Signatures kısmından KMDFDriver1.cer test sertifikası ile imzalandığını görmek mümkündür.

Yukarıda derleme çıktısında bize oluşturulan test sertifikasının bilgisayardaki sertifika deposuna eklendiğini söylemişti.Kontrol etmek için komut satırından certmgr komutunu çalıştırarak, açılan sertifika deposundan kontrol edebiliriz.Visual studio içersinden oluşturulan bu test sertifikaları test için oluşturulmuş kod imzalama sertifikalarıdır.

Bu sertifikalar sadece test ortamında kullanılmak için oluşturulmuş olup, yazılan sürücüleri gerçek ortamda kullanabilmek için kod imzalama sertifikası üreten firmalardan bir tane satın alıp onunla imzalamak gerekiyor.

Proje ayarlarından Driver Signing bölümünden test ve gerçek ortam sertifika seçimleri yapılabilinir.


Bu sertifikalar sadece test ortamında kullanılmak için oluşturulmuş olup, yazılan sürücüleri gerçek ortamda kullanabilmek için kod imzalama sertifikası üreten firmalardan bir tane satın alıp onunla imzalamak gerekiyor.Proje ayarlarından Driver Signing bölümünden test ve gerçek ortam sertifika seçimleri yapılabilinir.

Sürücü Yükleme Ve Hata Ayıklama

Şimdi elimizde gerçek bir sertifika olmadığına göre mevcut test sertifikası ile imzalanmış driver dosyasını nasıl sanal makinaya yükleyip çalıştıracağız onu görelim.
Driver dosyasını (KMDFDriver1.sys) sisteme yükleme yapabilmek için yukarıda bahsettiğim OSR Driver Loader programını kullanacağız.

OSRLOADER.exe'yi çalıştırıp driver dosyasını (KMDFDriver1.sys) seçip sırayla Register Service ve Start Service butonları ile driver'ı yükleme işlemi gerçekleştirilir.Fakat sürücü imzalanmış olsa bile eğer bilgisayar Test Mod'da değilse Start Service butonuna tıkladığınızda aşağıdaki gibi bir hata mesajı alacaksınız.


[Window Title]
Program Compatibility Assistant
[Main Instruction]
A digitally signed driver is required
[Close]
---------------------------
OSRLOADER
---------------------------
Windows cannot verify the digital signature for this file. 
A recent hardware or software change might have installed a file that is signed incorrectly or damaged, 
or that might be malicious software from an unknown source.
---------------------------
OK   
---------------------------
Yapmamız gereken burada bahsedildiği gibi komut satırını yönetici olarak çalıştırıp, sonrasında aşağıdaki komutu çalıştırıp sanal makinayı yeniden başlatmak olacaktır.
bcdedit /set TESTSIGNING ON
Bu aşamadan sonra tekrar OSRLOADER.exe ile sürücüyü yüklemeyi deneyebilirsiniz.

Yazıda gördüğünüz eksik ya da yanlışları haber ederseniz sevinirim.

2 Haziran 2016 Perşembe

Polymorphism ve Pointer ilişkisi

OOP programlamanın özelliklerinden biri olan Polymorphism mekanizmasının nasıl çalıştığını incelemeye çalışacağız.Wiki sayfasında görüleceği üzere Polymorphism'in farklı şekilleri mevcut.
Bizim inceleyeceğimiz türü ise Subtyping Polymorphism.


Subtyping Polymorphism'in implementasyonundaki ilüzyon ise şu şekilde açıklanabilir; 
Derleyici virtual method (yada diğer adıyla function) tanımlı bir sınıf tespit ettiğinde, sınıfın içerisine fonksiyonların pointer(adres) bilgilerini tutacağı gizli bir array, diğer adıyla virtual method table(VMT) yerleştirmekte ve daha sonra bu array içerisindeki pointerlara (adreslere), alt sınıfta ki fonksiyonların pointer bilgisini set etmektedir.
Fonksiyon pointer'larının çalışma zamanında set edilmesi veya değiştirilmesinin diğer adı "run time method binding" yada late binding olarak ifade edilmektedir.


Kod üzerinden mekanizmanın nasıl çalıştığını anlamaya çalışalım.
C++
Delphi

Yukarıda ki C++ kod bloğunda Calculation sınıfında Calc ismine sahip bir pure virtual function ve yine 
Calculation sınıfından miras alan CalculationSum ve CalculationDiv sınıflarını görmekteyiz.

Kodu çalıştırıp, inceleyecek olursak; 
Calculation sınıfı içersinde ki Calc fonksiyonunun,CalculationSum(Sub Class) içinde ki Calc fonksiyonuna yönlendirildiği,diğer adıyla method binding işleminin gerçekleştiğini görebiliriz.


calculation ve CalculationSum içersinde vftable array'lerin, ilk elemanlarında ki Calc fonksiyonlarına ait adreslerin(
Sarı ile çizili) aynı olduğu görebiliriz.

Class,virtual function olmasaydı,yada method binding işlemini biz yapmak isteseydik basit olarak nasıl yapabilirdik ?

C++
Delphi

Son olarak bu konuyu araştırmamı salık veren Tuğrul Beye teşekkür etmeden geçmek olmaz.  :)