8 Kasım 2011 Salı

Buffer Overflow Üretecek Programcı Nasıl Yetiştirilir


Yukarıdaki örnek "Bilgisayar Programlama I" dersinde "dizi" kavramının anlatıldığı kısımde yer alan örneklerden birisi. Ancak deneyimli programcılar bu kodun hatalı olduğunu ve istenmeyen sonuçlar ortaya çıkartacağını fark etmişlerdir.Bu durumu fark etmeyenler için bu eğlenceli hata hakkında bir şeyler yazmak istiyorum...



Şimdi yukarıdaki kodu yazalım ve derleyelim. Ben sizin yerinize yazdığım için siz aşağıdan kopyala yapıştır yaparak kullanabilirsiniz :)


#include <stdio.h>
int a[10],i,j;
main(){
    /* dizi elemanları giriliyor*/
    for(i=0;i<=10;i++){
        printf("\n%d. sayıyı giriniz:",i);
        scanf("%d",&a[i]);
        if(a[i]==0) break;
        j=i;
    }
    /*dizi elemanları yazdırılıyor*/
    for(i=0;i<=j;i++)
        printf("%d\n",a[i]);
}

Yukarıdaki kodları ornek2.c adıyla kaydettikten sonra, Linux ortamı için aşağıdaki gibi bir komutla derleyelim. Windows ortamında derlemek için Dev-C++ kullanabilirsiniz...


seker@seker-N53SN:~$ gcc -fno-stack-protector -o ornek2 ornek2.c 


Şimdi kodumuzu derlediğimize göre çalıştıralım ve neler olduğuna bir bakalım. ornek2 programımız, belirttiğimiz i sayacı 10 değerinden küçük yada eşit olduğu  sürece bizden sayı girmemizi isteyecektir.



Yukarıdaki ekran çıktısına bakarsanız döngünün 10 adımdan fazla sürdüğünü görebilirsiniz.

Sağ kenarda kocaman 1 rakamıyla gösterdiğim döngü adımında girilen değerden sonra bir terslik olduğunu ve döngünün uzadığını fark etmiş olmalısınız. Aynı durum 2, 3 ve 4 olarak işaretlediğim adımlarda da gerçekleşiyor...

Peki ne oluyor da böyle oluyor?

1, 2, 3 ve 4 ile gösterdiğim adımlarda girilen değerin, döngü sayacını değiştirdiğini ve böylece döngünün uzayıp gittiğini görebilirsiniz. Bu adımda ekranda "10. sayıyı giriniz" yazıyor olsa bile gerçekte okuduğumuz 11. sayı olur. Bu durumda int a[10] diyerek hafızda ayırdığımız 10 birimlik alana 11 birim veri yazmış oluruz. Yani bir tür bellek taşması durumu oluşur. Taşan kısım hafızada i değişkeninin bulunduğu alana yazılır ve i değişkeni değiştiği için for döngüsü olması gereken farklı bir yere atlar...

Bu durumu yanda görülen bellek şeması üzerinde daha kolay anlayabiliriz. Yeşil olarak gösterilen bellek alanları a[10] dizisi için ayrılan alanlardır. Hemen ardından ise kırmızı ile göstermekte olduğum i değişkeni için ayrılan alan yer alır. Bir sonraki mavi alan ise j değişkeni için bellekte ayrılan alanı temsil etmektedir...
For döngümüz normalde 10 sayı okumak zorundadır ancak küçük(!) bir programlama hatası sonucunda for döngüsü 11 kez çalışmakta ve 11 sayı okumatadır. Bu nedenle en son okunan değer hafızada i değişkeni için ayrılan kırmızı renkli hafıza alanına taşmaktadır...

For döngüsü döngünün hangi adımda olduğunu kırmızı renkli alana, yani i değişkeninin değerine bakarak takip ettiği için meydana gelen bu taşma i değişkeninin değerini, dolayısı ile for döngüsünün akışını değiştirmektedir...

Bu nedenle taşma olduğu anda 10 değerinden daha küçük bir değer girilmesi durumunda döngü başa sarmakta ve sayı okumaya devam etmektedir. Bu aşamada negatif değerler girmek suretiyle programın olması gerekenden çok farklı bellek adreslerine yazmaya çalışması ve "Segmentation Fault" vermesi sağlanabilir...

Bellek taşması durumu her zaman bu kadar masum sonuçlar ortaya çıkartmaz. Bazı durumlarda özel olarak hazırlanan ve shellcode olarak isimlendirilen özel kod parçacıkları taşan bellek alanına yazılır ve bilgisayarın bir şekilde bu kodu çalıştırması sağlanır. Sonuç olarak çalışmakta olan yazılım üzerine vazife olmayan bir iş yaparak sistemin kırılmasına neden olur. Ancak bu durum genellikle öğrencilere anlatılmaz yada bu durumu anlatabilecek yetkinlikte hoca bulunamaz. Bu nedenle okulda programlama öğrenen ve yalnızca okulda öğrendikleriyle yetinen kişilerin yazdıkları uygulamalar kırılıp dökülmeye başlar... :(

İyi de bu kadar laf salatasını neden yaptım? Öğrencilere temel programlama becerisini kazandırmayı amaçlayan bir C kitabında yer alması için şahane bir örnek. Ben 2005 yılında bu hatalı örneği keşfettiğimden beri hala orada durduğunu görünce yazasım geldi... Buraya yazdım.. :)

2 yorum:

  1. Harun Abi Çok Güzel Bir Yazı Paylaşmıssın :) Ve düşünüyorumda daha önce niye dikkat etmedik hadi biz yeni öğrendik diyelim, Öğretmenlerin belki çocukların kafası karışır diye mi söylemiyorlar yoksa, dikkat etmediklerinden(kitabı yazan kişi hata yapmaz düşüncesinde) mi ?, yoksa bilmediklerinden mi ? Bu en basit hataymış, ve dediğin gibi tehlikeli sonuçlar doğurabilir :)

    Bende hata olmaz diye düşünürdüm ama bundan sonra her komutun üzerinden belli testler yapacağım ne olur ne olmaz :)

    YanıtlaSil
  2. Gerçekten harika bilgilendirme için teşekkürler

    YanıtlaSil