Merhaba arkadaşlar!

Biliyoruz ki C dili dizi referansları üzerinde sınır kontrolü yapmıyor ve yerel değişkenler yığıt(stack) üzerinde o anki durum bilgisini oluşturan dönüş adresi ve frame göstericisiyle birlikte tutuluyor. Bu iki durumun birleşmesi yanlış ellerde ciddi hataların oluşmasına sebep olabilir. Öncelikle kütüphane fonksiyonu olan gets() nasıl çalışıyor bir göstermemiz gerekiyor.

char *gets(char *s){ 
int c; 
char *dest = s; 
while ((c = getchar()) != ’\n’ && c != EOF) 
*dest++ = c;
*dest++ = ’\0’; /* Terminate String */ 
if (c == EOF) 
    return NULL; 
return s; }

Görüldüğü üzere gets fonksiyonu '\n' (yeni satır) veya EOF görene kadar standart inputtan girdiyi alarak s ile gösterilen yere girdiyi kopyalar, sonuna da "null" karakterini koyar. Bu sırada hiç bir sınır kontrolü yapmıyor. Şimdi gets() fonksiyonunu çağıran bergi fonksiyonunu inceleyelim.

void bergi() { 
char buf[4]; 
printf(“3 karakterden uzun bir string girmeyiniz:)”); 
gets(buf); 
puts(buf); }

Bufferımız 4'lük olduğu için en fazla 4 karakter girebiliriz gibi görünüyor en başta. Ancak gets'in sona eklediği null karakterini de hesaba katarsak en fazla 3 karakter girebiliriz. Peki 3 karakterden fazla karakter girersek ne olacak? İşte bu durumu incelememiz gerekiyor. Yukardan aşağıya doğru adresin azaldığını düşünelim. Öncelikle kullanıcıdan alınan girdinin “123” olduğu durumu değerlendirelim. Yığıtın o anki durumu aşağıdaki gibi olacaktır. (1den 9 a kadar olan sayılar için ascii tablosunda verilen onaltılık tabandaki değerler 0x31 ile 0x39 arasındadır.)

Eğer girdi “1234567” olursa buffer 1234 ile dolacak , frame göstericisi ise 567 ve null karakterleriyle dolacaktır ve yığıt şu halde olacaktır.

Yani buf[4] 'ten buf[7] ' ye kadar olan tüm yazmalar frame göstericisinin (pointerının) değerini değiştirecektir. bergi fonksiyonun işi bittiğinde ve çağrıldığı fonksiyona dönülmek istendiğinde frame göstericisinin değerleri değiştiği için (az bir ihtimal kullanıcı frame göstericisi %ebp'nin değeri ile aynı değeri verecek karakterleri girseydi sorun olmayacaktı), yanlış bir çerçeve içinde bergi fonksiyonu kaldığı yerden çalışmaya devam edecekti ve fonksiyon içinde kullanılan tüm referanslar geçersiz olacaktı.

Son olarak da “123456789” girildiğini düşünelim. Bu durumda yığıttaki buffer, %ebp ve dönüş adres kısımları ekrandan girilen girdiyle dolacak ve değerleri değişecekti. Yanlış bir çerçeveye geçilecek ve dönüş adresi de değiştiği için bergi fonksiyonunu çağıran fonksiyonda kalındığı yerden devam edilemeyecekti. Yüksek olasılıkla segmentation fault hatası alınacaktı.

Şimdi gelelim exploit kod nedir sorusunun cevabına. Fark edilebileceği üzere kullanıcının girdiği değerler frame göstericisini ve dönüş adresini belirleyebildiği için, işini bilen bir kişi bunları kullanarak sistemin güvenliğine saldırabilir. Hatta bu yöntem network üzerinden bir sitemin güvenliğine saldırmanın en yaygın yollarından biridir. Program bir çalıştırılabilir kodun byte kodlarıyla beslenir ve dönüş adresinin değeri için de bu kodun başlangıç adresi olan değer verilir. Bu stringe exploit kod denir. ret talimatı uygulandığında dönüş adres değeri verilen exploit kodun adresi olduğu için bu değere dönüş yapılır ve byte kodu girilen talimatlar sırasıyla yapılmaya başlanır. Programın akışı bu yolla tamamen değiştirilebilir.