En son File Header alanındaki verilere ulaşmıştık, şimdi ise Optional Header alanı içerisindeki verilerden söz edeceğiz.
Öncelikle bu alan içerisinde önemli verilerin tutulduğu alanlardan birisidir. Optional Header içerisinde işletim sistemi sürümü ve programın entry pointi gibi verileri bulundurur. bu alanın bilgilerini almak için kullanacağımız yapı IMAGE_OPTIONAL_HEADER yapısıdır.
Bu alan içerisinde ikiye ayrılır. standart kısmı executable dosyaların ortak kullandığı Ortak Nesne Dosya Biçimi (COFF) için ortak alanlardır. Bu alanlar içerisinde en önemli olanı AddressOfEntryPoint değerini bu değer bir programın ilk nereden çalıştırılmaya başlayacağını gösterir.
Ek alanlar ise yazmış olduğumuz executable dosyalara ek özellikler kazandırmayı sağlar buradaki değerleri biraz açıklayacak olursak bunların önemini daha iyi anlayabiliriz.
Bu alan bildiğimiz gibi dosyanın memory üzerinde yükleneceği adresi belirtir ve default değer olarak 0x00400000 alır.
Bu değer dosyamızdaki section boyutlarının tutarak bellek üzerinde fazla yer ayrılıp gereksiz performans kaybı yaşanmasını engeller.
İşletim sisteminin majör versiyonunu gösterir.
İşlerim sisteminin minör versiyonunu gösterir.
Majör ve minör versiyonlar kullanılarak bir işletim sisteminin versiyonu belirlenebilir. Örnek olarak 6.3.9600 olarak gösterilen bir işletim sistemi versiyonunda majör id 6, minor id 3, ve build id 9600 olarak gösterilebilir. Aşağıdaki tablodan ise bu sistemin bir windows 8.1 olduğunu görebiliriz.
Bu değer PE dosyasının mermory üzerindeki kapladığı alan boyutunu tutar.
Bu alanda PE file header, Optional header gibi header ile ilgili bölümler bulunur.
Hangi işletim sistemi üzerinde çalışacağını belirtir.
Bu değer program içerisinde kullanılmak üzre import edilen DLL dosyalarının başlangıç ve bitiş adreslerini tutar.
Bu flag değerleri dosyanın debug,default yada break olarak hangi amaç ile yükleneceğini belirtir.
Bu alan bizim için oldukça önemlidir. Executable dosyalar için import edilen önemli dosya bileşenlerin import yolunu gösterir. PE dosyamız dışarıdan bir dosyaya erişmek istediğin de bu yollar üzerinden ulaşır. bu alanın içerisindeki bilgilere erişmek için IMAGE_DATA_DIRECTORY yapısı kullanılabilir.
Bu alan aslında bir dizi şeklinde sıralanmıştır. İçerisindeki verilere erişim için indekslerini kullanmamız gerekmektedir. Bu indeks sayısı IMAGE_NUMBEROF_DIRECTORY_ENRIES olarak tanımlanır. ve indekse karşılık gelen veri yolu aşağıdaki gibidir.
Bu alanın önemini yeterince anladıysak kodlama kısmında bu alanların ansıl elde edildiğine bakalım öncelikle Optional Header bilgilerini elde etmemiz gerekiyor bunun için aşağıdaki kodu kullanabiliriz.
IMAGE_OPTIONAL_HEADER optionalHeader = (IMAGE_OPTIONAL_HEADER)ntheader->OptionalHeader;
optionalHeaderWriter(optionalHeader);
Burada tanımladığımız optionalHeaderWriter fonksiyonu gerekli bilgileri ekrana yazmak için kullanıyoruz. Bu fonksiyon içeriği aşağıdaki gibidir.
void optionalHeaderWriter(IMAGE_OPTIONAL_HEADER optionalHeader) {
cout << endl << "______PIMAGE_OPTIONAL_HEADER______" << endl;
cout << "Magic : " << hex << optionalHeader.Magic << endl;
cout << "MajorLinkerVersion : " << hex << setw(2) << setfill('0') << (int)optionalHeader.MajorLinkerVersion << endl;
cout << "MinorLinkerVersion : " << hex << setw(2) << setfill('0') << (int)optionalHeader.MinorLinkerVersion << endl;
cout << "SizeOfCode : " << hex << optionalHeader.SizeOfCode << endl;
cout << "SizeOfInitializedData : " << hex << optionalHeader.SizeOfInitializedData << endl;
cout << "SizeOfUninitializedData : " << hex << optionalHeader.SizeOfUninitializedData << endl;
cout << "AddressOfEntryPoint : " << hex << optionalHeader.AddressOfEntryPoint << endl;
cout << "BaseOfCode : " << hex << optionalHeader.BaseOfCode << endl;
cout << "BaseOfData : " << hex << optionalHeader.BaseOfData << endl;
cout << "--------------------------------" << endl;
cout << "ImageBase : " << hex << optionalHeader.ImageBase << endl;
cout << "SectionAlignment : " << hex << optionalHeader.SectionAlignment << endl;
cout << "MajorOperatingSystemVersion : " << hex << optionalHeader.MajorOperatingSystemVersion << endl;
cout << "MinorOperatingSystemVersion : " << hex << optionalHeader.MinorOperatingSystemVersion << endl;
cout << "MajorImageVersion : " << hex << optionalHeader.MajorImageVersion << endl;
cout << "MinorImageVersion : " << hex << optionalHeader.MinorImageVersion << endl;
cout << "MajorSubsystemVersion : " << hex << optionalHeader.MajorSubsystemVersion << endl;
cout << "MinorSubsystemVersion : " << hex << optionalHeader.MinorSubsystemVersion << endl;
cout << "Win32VersionValue : " << hex << optionalHeader.Win32VersionValue << endl;
cout << "SizeOfImage : " << hex << optionalHeader.SizeOfImage << endl;
cout << "SizeOfHeaders : " << hex << optionalHeader.SizeOfHeaders << endl;
cout << "CheckSum : " << hex << optionalHeader.CheckSum << endl;
cout << "Subsystem : " << hex << optionalHeader.Subsystem << endl;
cout << "DllCharacteristics : " << hex << optionalHeader.DllCharacteristics << endl;
cout << "SizeOfStackReserve : " << hex << optionalHeader.SizeOfStackReserve << endl;
cout << "SizeOfStackCommit : " << hex << optionalHeader.SizeOfStackCommit << endl;
cout << "SizeOfHeapReserve : " << hex << optionalHeader.SizeOfHeapReserve << endl;
cout << "SizeOfHeapCommit : " << hex << optionalHeader.SizeOfHeapCommit << endl;
cout << "LoaderFlags : " << hex << optionalHeader.LoaderFlags << endl;
cout << "NumberOfRvaAndSizes : " << hex << optionalHeader.NumberOfRvaAndSizes << endl;
cout << "--------------------------------" << endl;
for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
IMAGE_DATA_DIRECTORY dataDirectory = (IMAGE_DATA_DIRECTORY)optionalHeader.DataDirectory[i];
int size = dataDirectory.Size;
if (size != 0) {
cout << "-------" << i << "------------" << endl;
cout << "VirtualAddress : " << hex << dataDirectory.VirtualAddress << endl;
cout << "Size : " << hex << dataDirectory.Size << endl << endl;
}
}
cout << endl << endl << endl;
}
Bu fonksiyonda MajorLinkerVersion ve MinorLinkerVersion veri tipleri byte olduğu için bazı eklemeler yapmam gerekti ve bu eklemeleri kullanabilmek için iomanip kütüphanesini projeme dahil ettim. Bu fonksiyon içerisinde dahil edilen dosya yollarının bulunduğu değerleri indeks değeri ile birlikte yazdırmış olduk. Bu programı çalıştırıp çıktısına bakacak olursak aşağıdaki gibi olacaktır.