Quantcast
Channel: Bilgi Güvenliği AKADEMİSİ
Viewing all articles
Browse latest Browse all 331

Exploit Gelistirme - Program Akisini Degistirme

$
0
0
Bu yazida 1996'da yilinda Aleph1 tarafindan yazilan "smashing the stack for fun and profit" baslikli yazisinda gecen ornek ele alinarak, program akisinin nasil degistirilebileceginden bahsedilecektir. Aleph1'in ilgisi makalesine http://insecure.org/stf/smashstack.html adresinden erisim saglanabilir.

Exploit gelistirmenin ilk adimi olarak sayilan "stack based overflow" yontemi icin temel olusturacak asagidaki ornek ile stack nasil calisiri anlamak dahada mumkun olacaktir. Buradaki amac kisaca program akisinin nasil degistirilebilecegini gostermek ve sonrasinda yazilim akisinin istenildigi gibi degistirilmesini saglamaktir.

# include <stdio.h>

void deneme()
{
    char buf[6];
    int *a;

    a = buf + 14;
    (*a) += 12;
}


int main ()
{
     printf("1\n");
     deneme();
     printf("2\n");
     printf("3\n");

     return 0;
}

Kod deneme.c ismiyle kaydedilmis ve ardindan asagidaki derleme secenekleri ile derlenmistir.

# gcc -g -o deneme deneme.c

deneme isimli fonksiyonun iceriginin asagidaki gibi oldugu varsayildiginda

void deneme()
{
    char buf[6];
    int *a;

}

kod derlendiginde ve calistirildiginda asagidaki ciktiyi  verecektir.
1
2
3
Ancak denem isimli fonksiyonun icerigi asagidaki sekilde duzenlendiginde ise
void deneme()
{
    char buf[6];
    int *a;

    a = buf + 14;
    (*a) += 12;
}
1

programin ciktisi asagidaki sekilde olacaktir. Peki deneme isimli fonksiyonun icerisinde belirtilen
a = buf + 14;
(*a) += 12;
satirlar ile ne saglanmaktadir.  int *a ile tanimlamasi gerceklestirilen a degiskeni ile once buf karakter dizisinden 14 byte uzakliktaki adrese konumlanilmis. Ardindanda bu adresin icerigi 12 byte otelenerek fonksiyon sonlandirilmistir. Bu sekilde fonksiyon akisinin ekran ciktisinda 1 2 3 olmasi gerekirken, 1 3 olarak tamamlanmis olmaktadir. Kod gdb ile disassemble edildiginde asagidaki gibi bir gorunum alacaktir.
# gdb -q deneme
(gdb) list
5        char buf[6];
6        int *a;
7   
8        a = buf + 14;
9        (*a) += 12;
10    }
11   
12    int main ()
13    {
14         printf("1\n");
(gdb)
15         deneme();
16         printf("2\n");
17         printf("3\n");
18   
19         return 0;
20    }
(gdb) disassemble main
Dump of assembler code for function main:
   0x080483d2 <+0>:    push   ebp
   0x080483d3 <+1>:    mov    ebp,esp
   0x080483d5 <+3>:    sub    esp,0x4
   0x080483d8 <+6>:    mov    DWORD PTR [esp],0x80484d4
   0x080483df <+13>:    call   0x80482f0 <puts@plt>
   0x080483e4 <+18>:    call   0x80483b4 <deneme>
   0x080483e9 <+23>:    mov    DWORD PTR [esp],0x80484d6
   0x080483f0 <+30>:    call   0x80482f0 <puts@plt>
   0x080483f5 <+35>:    mov    DWORD PTR [esp],0x80484d8
   0x080483fc <+42>:    call   0x80482f0 <puts@plt>
   0x08048401 <+47>:    mov    eax,0x0
   0x08048406 <+52>:    leave 
   0x08048407 <+53>:    ret   
End of assembler dump.
(gdb)

main+18 satirinda deneme isimli fonksiyon cagrisinin gerceklestirildigi gorulmektedir. deneme isimli fonksiyonun cagrilmasindan hemen onceki satirda ise ekrana 1 ciktisini gostermek icin yazilmis printf("1\n") cagrimi gorulmektedir. Normal sartlar altinda deneme isimli fonksiyonun ardindan main+30 satirinda bulunan ve ekrana 2 ciktisini gostermek uzere kullanilacak printf("2\n") cagrim bilgisi gerceklestirilecekken bunun yerine main+42 satirinda bulunan ve ekrana 3 ciktisini gostermek uzere kullanilacak printf("3\n") cagrim bilgisine gecis saglanmistir. 

a = buf + 14; ifadesi ile, a degiskenin eip register degerininin adresine konuslanmasi saglanmaktadir.  deneme isimli fonksiyon cagrimi gerceklestirildiginde stack gorunumu kabaca asagidaki gibi olmaktadir. derleyici tarafindan hem guvenlik hemde optimiazasyon amackli eklenen padding degerleri ve buf karakter dizisinin uzunlugu goz onune alindiginda, a = buf + 14 ifadesi ile eip register degerinin adresine konuslanilmaktadir.

    buf     ebp   eip 
[        ][    ][    ]


Ardindan kabaca bir hesap ile ikiadres arasindaki mesafe 12 byte uzunlugunda olmaktadir. Yani (*a) += 12; ifadesi ile printf("2\n") ifadesi es gecilmis yerine printf("3\n") ifadesi calistirilarak program akisi degistirilmistir.

Kisaca burada deneme isimli fonksiyon icerisinden oncelikle eip register degerine erisim saglanmis ve hemen ardindan bu register degerinin icerigi degistirilerek program akisi istenildigi gibi degistirilmistir. 

Bu yazida stack nedir, nasil calisir ve herhangi bir fonksiyon cagrildiginda stack icerisinde neler olur sorularina deginilmeden kabaca program akisinin degistirilebilecegi gosterilmistir. Bu sorularin cevablarina ise daha sonraki yazilarda ayrintili olarak deginilecektir.


Viewing all articles
Browse latest Browse all 331

Trending Articles


Mide ağrısı için


Alessandra Torre - Karanlık Yalanlar


Şekilli süslü hazır floodlar


Flatcast Güneş ve Ay Flood Şekilleri


Gone Are the Days (2018) (ENG) (1080p)


Yildiz yükseltme


yc82


!!!!!!!!!! Amın !!!!!!!!!


Celp At Nalı (Sahih Tılsım)


SCCM 2012 Client Installation issue