Stack Based Overflows #4

INSTRUCTION: JMP ESP

Simge Karahan
3 min readDec 24, 2020

Bir önceki yazıda Stack’te EIP’i bulma konusuna değinmiştik çünkü EIP, program akışında çalıştırılacak bir sonraki komutun adresini tutar. Ve bizim amacımız da programda istediğimiz kodu çalıştırmak olduğu için önce EIP’e ulaştık. EIP’e ulaştıktan sonra ESP’ye ihtiyacımız var çünkü ESP, zararlı kodlarımızı çalıştırdığımız yerdir. Bu yazıda da ESP ile ilgileneceğiz. ESP’ye çalıştırılmak istenen shellcode’lar yazılır ve EIP’e ESP’ye gitmesi için komut verilir.

Yeni koda baktığımızda:

  • Junk değeri EIP’e kadar A harfi yazmak için kullanıldı.
  • Eip değeri EIP’e ulaştığımızın kanıtı olarak B yazmak için kullanıldı.
  • EIP’den sonra preshellcode değeri ile 4 karakter eklendi çünkü ESP, adres konumlarına bakıldığında EIP’den sonra 5.karakterden başlamaktadır.
  • Burada bir shellcode değeri ile herhangi bir shellcode çalıştırılmamaktadır çünkü amacımız sisteme zarar vermek değil sistemde nasıl zararlı kod çalıştırılır bunu öğrenmektir. Bu yüzden temsili olarak değişkene “shellcode” ismi verilmiştir.

Oluşan “test.m3u” dosyasını sisteme atıp Immunity Debugger’dan registerları incelediğimizde EIP’i 424242 yani BBBB olarak ve ESP’yi de shellcode değeri olarak görmekteyiz:

Immunity Debugger’da adresleri incelediğimizde ise,

  • EIP=BBBB
  • Pre_shellcode=XXXX
  • Az önce bahsedilen 5. karakter olayını burada görebiliriz EIP’den sonra ve shellcode’dan önce neden preshellcode koyduğumuz açıkça gözükmektedir.
  • Ve ESP’ye yazdığımız shellcode verisi (1ABCDEFGHIJK2ABCDEFGHIJK…) gözükmektedir.

EIP Stack’te çalıştırılacak bir sonraki komutun adresini tutuyor demiştik. ESP ise Stack’in başlangıç noktasını gösteriyor. O zaman EIP’e ESP’nin adresini yazmayı başarırsak program artık shellcode’umuzu çalıştırır. Çünkü bir sonraki çalışacak komut EIP’deki adresteki komuttur ve oraya shellcode’un adresini göstererek program akışını zararlı komutlara çevirmiş oluruz.

Bazen ESP’nin adresine tam denk gelemediği durumlar olabilir. Bu gibi durumlarda hiçbir şey yapma anlamında olan NOP (no operation) komutları eklenebilir. Bu sayede jmp edilen yerde nop yazdığı için hiçbir işlem yapılmadan alt satırlara geçerek shellcode’a kadar gidilir.

Peki ESP’ye nasıl gideceğiz?

JMP ESP komutunun adresini bulmamız gerekiyor. EIP’e bu adresi yazdırdığımızda komut çalışacak ve ESP’ye gidecek. Bu komutun adresini nasıl bulacağız sorusunda ise işin içine dll’leri incelemek giriyor.

NOT: DLL(Dynamic Link Library) Windows’daki programlar için fonksiyon dosyalarıdır. Ve bizim ihtiyacımız olan JMP ESP komutu MSRMCcodec02.dll içindedir. Immunity Debugger’da “executable modules” ekranından bulup açtım:

Dll’in içine girip sağ tıklayarak command araması yapabiliriz, şu şekilde:

Bu arama işleminden sonra JMP ESP komutuna ait adresin 01A9F23A olduğunu bulduk:

Kodda EIP değerine JMP ESP instruction’ın adresini(01A9F23A) yazalım. Assembly’de bunu gören program için JMP ESP komutu çalıştırılacak ve ESP’ye geçilecek.

Bu sayede ESP’ye geçildi. EIP’de jmp komutunun adresini(01A9F23A) sonra no operation( \x90) anlamında olan preshell komutunu ve ESP’yi görebiliriz:

JMP ESP dışında nasıl ESP’ye gidebiliriz?

Jump(or call): Jump ya da call ile istediğimiz adrese doğrudan atlayabiliyoruz, bu bizim incelediğimiz durum. Dll içerisinde JMP ESP yerine CALL ESP arayıp bulduğumuz adresi kullanarak da gerçekleştirebiliriz.

Pop return : Direkt shellcode’un gösterilmediği, Stack’te adresin belirtildiği durumda kullanılır. Gerekirse pop pop return, pop pop pop return olarak kullanılır. Dll’lerde pop ve ardından ret komutlarının olduğu adres aranır.

Push return: Hedef adres Stack’e atılıp return edildiğinde Stack’e en son gelen değer çalıştırılacağı için hedefe ulaşılmış olunur. Yani dll’lerde push ve ardından ret komutlarının olduğu adres aranır.

Jmp(reg+offset): dll’lerde jmp [reg]+[offset] durumu aranır.

Kaynak: https://www.corelan.be/

--

--