Bir önceki çalışmamızda aşağıdaki çıktıyı inceliyorduk :

Şimdi dikkat edersek EIP’nin içerdiği hafıza adresi programın main fonksiyonununda bir talimata ( instruction ) işaret ediyor.

İşaret ettiği kısım yukarıda gösterilmiştir.

Ondan önceki 5 talimat genel olarak fonksiyon açılışı (function prologue) olarak bilinir ve hafızayı main fonksiyonun geri kalan yerel değişkenleri için hazırlamak amacıyla compiler tarafından oluşturulur. C içerisinde değişkenlerin bildirilmesinin bir deneni de bu kodun inşasına yardımcı olmaktır.

Debugger’ımız GDB kodun bu kısmının otomatik olarak oluşturulduğunu anlayıp o kısmı atlayacak kadar akıllıdır.

Fonksiyon açılışları hakkında daha sonra tekrar konuşacağız.


Examine Metodu


GDB debugger’ı belleği incelemek üzere direk bir metod içerir x, examine’nin kısaltılmışıdır. Belleği bu şekilde incelemek kritik bir yetenektir. Bu açıklar bir ilüzyon gibi olağanüstü ve sihirli gözükür. Fakat hem sihirbazlık numaralarında hem de burada eğer doğru noktaya bakacak olursanız numara açıkca görülecektir. Bir sihirbaz asla aynı numarayı iki kere yapmasa da GDB gibi bir debugger sayesinde program işleyişinin her kısmı taranır, durdurulur, adım adım çalıştırılır ve istenildiği kadar tekrarlanır. Sonuçta çalışan bir program çoğunlukla işlemci ve bellek(memory) segmentlerinden başka bir şey değildir ve bu nedenle memory examination neler olduğuna yakından bakmanın ilk yoludur.

  • o octal
  • x hexadecimal
  • u işaretsiz (unsigned) standart 10 tabanında ondalık sayı
  • t binary

Examine komutu ile kesin hafıza adresini incelemek için bu argümanlardan herhangi biri kullanılabilir.
Devamında gelecek olan örnekte EIP register’ının adresi kullanılmıştır.
Kısaltmalar GDB içerisinde sıkça kullanılır.
“info register eip” için yalnızca “i r eip” yazmamız yeterlidir.

EIP registerının işaret ettiği hafıza alanı EIP içerisinde tutulan adresle examine ediliyor.
Debugger registerlerı referans vermemize olanak sağlıyor. Direk $eip diyerek işaret ettiği yeri gösterebiliriz.

Bendeki çıktı şu şekilde :

Hedef adresteki birden fazla birimi(unit) görmek için Examine komutuna bir numara da eklenenebilir:

Tek bir birimin default boyutu word(kelime) denen 4-byte’lık birimdir. Examine komutu için ekran birimleri format için girdiğimiz harfden sonra boyut için gireceğimiz ikinci bir harfle değiştirilebilir.

  • b tek byte
  • h halfword, 2 byte uzunluğunda
  • w kelime (word), 4 byte uzunluğunda
  • g dev (giant), 8 byte uzunluğunda

Anlaması biraz zor olabilir çünkü bazen word(kelime) terimi bazen 2byte değerlere de karşılık gelir.
Bu durum için Double Word yani DWORD 4 byte lık bir değeri gösteriyor. Bu notlarda word ve DWORD ikisi de 4 byte değerleri göstermektedir.
Eğer 2-byte bir değer hakkında konuşacaksak short veya halfword diyeceğiz.

Devam eden GDB çıktısı farklı boyutlarda belleği görüntülüyor:

Eğer yakından bakacak olursanız yukarıdaki verilerde bir gariplik olduğunu görürsünüz.
İlk examine komutu bize ilk 8 byte’ı gösteriyor. Doğal olarak daha fazla veri görüntülemek için daha büyük birimler kullanacağız.

Bununla birlikte ilk examine komutunun çıktısında ilk iki byte 0xc7 ve 0x45 olacak.

Fakat aynı hafıza adresine halfword ile examine edildiğinde 0x45c7 değeri byteları tersine çevrilmiş olarak görülür.

Aynı byte çevirme efekti 4-byte word 0x00fc45c7’de de görülüyor. Fakat eğer ilk 4 byte, byte by byte bölünürse 0xc7, 0x45, 0xfc, and 0x00 düzenindedir.

Bunun sebebi x86 işlemci değerlerinin little-endian byte düzeninde olmasıdır. Bu düzende ilk olarak least significant byte saklanır. Örneğin 4 byte lık bir değer tek bir değer olarak görüntülenmek istenirse bytelar ters sıralamada olacaktır.

GDB debugger bu değerlerin nasıl saklandığını bilecek kadar akıllıdır ve bir word ya da halfword examine edildiği zaman, bytelar doğru hexadecimal değeri ekrana yansıtacak şekilde ters çevrilir. Bu değerleri hexadecimal ve unsigned decimal olarak görüntülemek karışıklığı önler.

Yukarıda ilk 4 byte, birinci olarak hex ve ardından unsigned decimal olarak görüntülenmiş.

Komut satırı hesap makinesi programı bc kullanılarak değerler yanlış sıralamada olurlarsa 3343252480 yanlış değerine ulaşılır. Verilen mimarinin byte düzeni farkında olmamız gereken önemli bir ayrıntıdır. Debugging tools ve compiler’ların büyük bir kısmı byte düzeninin detaylarını otomatik olarak alır.

GDB dönüştürme işlemlerini examine komutu aracılığıyla yapar. GDB‘nin makine dili talimatlarını insanlar tarafından okunabilecek assembly’e çevirebileceğini görmüştük. GDB içerisindeki Examine komutu instruction’un kısaltması i harfi ile beraber kullanılırsa assembly talimatlarını da görüntüleyebilir.

Yukarıdaki çıktıda a.out programı GDB içerisinde main()’e bırakılmış bir breakpoint ile çalışmakta.
EIP (RIP) registerı makina dili talimatlarını içeren bir hafızaya işaret etmekte. Hoş biçimde diassemble oluyorlar.
Daha önceki objdump disassembly’miz yedi byte EIP’nin makine koduna uyan assembly talimatı olduğunu doğruluyor.

Bu assembly talimatı 0 değerini EBP registerının değerine taşıyacak eksi 4. Burası C değişkeni i nin hafızada tutulduğu yer.

i integer olarak tanımlanmış x86 işlemci yani üzerinde 4 byte yer tutuyor. Basitçe bu komut i değerini döngü için sıfırlıyor. Eğer bu noktada hafıza incelenek olsa bir anlam ifade etmeyen rastgele çöp olacaktı.

Bu konumdaki hafıza  birden fazla yöntemle examine edilebilir.