26 Mart 2015 Perşembe

Win x86 Reverse Engineering

Bu yazımızda "ringzer0" ctf'de "Binaries" kategorisinde sorulmuş "Windows x86 reversing is cool" başlıklı sorunun çözümünü anlatacağız.

Sorudan da anlaşıldığı gibi elimizde bir Winx86 exe var ve bunu reverse ederek flag'i elde etmeye çalışacağız.

Exe'yi ilk çalıştırdığımızda ve Key değerini girdiğimizde ekran görüntüsü şu şekilde olmaktadır:


gördüğünüz gibi keyi yanlış girdiğimiz için "Wrong Key!" demekte.

Önce exe üzerinde string'leri vs. kontrol ettik ancak Flag yoktu. Geriye tek bir çare kaldı, dinamik debug yapmak.

Exe'yi Ollydbg ile açtık.


Tabi exe'yi açınca bi yığın işimize yaramayacak asm koduyla karşılaştık. Biz direk Key kontrol kısmına geçeceğiz. Bunun için önce sağ tıklıyoruz, daha sonra "Search for" kısmına oradan da "All referenced strings" e tıklıyoruz.

Açılan menü şu şekilde;


Burada "Wrong Key!" uyarısını görüyoruz ve ona çift tıklıyoruz.


Gördüğünüz gibi keyin alındığı yere ve kontrolü tamamlandıktan sonra hatanın verildiği yere geldik.
Şimdi uygun bir nokta bulup Breakpoint koyacağız(F2 ile). Bu sayede baştan sona adım adım gitmemize gerek kalmayacak, direk bu noktadan debug etmeye başlayacağız.


Biz "scanf" in çağrıldığı, yani key'in bizden istendiği noktaya breakpoint koyduk.

Şimdi yukarıdan "Debug-> Run" diyeceğiz.


Gördüğünüz gibi exe'miz çalıştı ve bizden key istiyor, ancak henüz key giremeyiz çünkü "scanf" fonksiyonu daha tamamlanmadı. Adım adım ilerlemek için F8'e basıyoruz.

Bu arada F8 step over manasına gelir, yani diğer bir deyişle, çağrılan alt fonksiyonlara girmemek şartıyla bi adım aşağı iner, F7 ise çağrılan bir alt fonksiyon varsa onun da içine girer(step into).

Key değerini girebilene kadar F8 e basılı tutuyoruz.

Sonra key değerini giriyoruz;


Exemiz arkada dursun, debuggera geri dönüyoruz;

Mümkün olduğunca okuduğumuz asm kodlarını anlayarak F8'e bastıkça ilerliyoruz.


"Wrong key!" uyarısına girdik. Burada dikkat ettiyseniz "strlen" fonksiyonu çağrılıyor ve

CMP EAX,6  (EAX 6 mı, 6 ise Zero Flag'i Set(1) Et)

komutu uygulanmış, ve daha sonra JE(jump if equal) şartını sağlamadığı için dallanmayıp bi alt satıra inmiş.

Bu bize key hakkındaki ilk bilgiyi veriyor, keyimiz 6 haneli.

Şimdi durup düşündüğümüzde, stringler arasında flag yoktu gördüğünüz gibi, flag, key doğru girildiğinde dinamik olarak üretilip ekrana basılacak.

Flag uzun olduğu için, flag'i değil, keyi bulmak daha mantıklı. Bu yüzden biz keyi bulmaya çalışacağız. Bi sonraki adımımızda 6 haneli bir değer girip ilk kontrolü geçtiğimizde programın ne yapacağını kontrol edeceğiz.

Debug'ı "Restart" ediyoruz ve 6 haneli bir key giriyoruz.


İlk kontrolü geçip dallandıktan sonra geldiğimiz nokta burası. Adım adım ilerliyoruz.




Burada okla gösterilen nokta, strlen değeri ile EBX register'ını karşılaştırmakta. Dikkat ettiyseniz EBX register "0". Buradan şunu anlayabildik. EBX muhtemelen sayaç ve her ne işlem yapılacaksa, bu işlem 6 kez yapılacak. Yani key döngüde byte byte karşılaştırılacak.

Buradan her döngü tekrarlandığında keyi byte byte okuma ihtimalimiz var, neyse biz devam edelim debug işlemine.


Esas kontrol mekanizmasının gerçekleştiği kod bloğuna dallandık ve dikkat ettiyseniz en altta

CMP DL,AL
JE blablabla
"Wrong Key" olan satır

Yani bu şu manaya geliyor, bu işlem yapıldıktan sonra DL değeri ile AL değeri eşit değilse, key hatalıdır.

Devam edelim(F8);


Dikkat ettiyseniz DL ye attığı yeni değer, bizim key olarak girdiğimiz 6 karakterin ilk harfi.
Yani burada DL registerı bizim girdiğimiz değeri harf harf temsil ediyor.

Devam ediyoruz;


Şimdi bizim girdiğimiz keyin harfini, FFFFFFD3 ile xor'ladı.
Ancak burada DX'i xorladı.
Bizim girdiğimiz değer, DL de olduğu için DH kısmı bizi ilgilendirmiyor.
Kısaca bizim değerimiz
FFD3 ile xor'landı.

Devam edelim;



Şimdi
CMP DL,AL

Komutunu çağırdı. Register'ların o anki değerleri aşağıdaki okla gösterilen yerde yazmakta.
Eğer bu şart sağlanmıyorsa bi alt satırdaki JE çalışmayacak ve döngüden çıkacak.

Şimdi biz burada şunu öğrenmiş olduk.

AL = 97
DL = A0 
imiş. Bu değerler tabi hexadecimal.

DL miz neydi peki?
Girdiğimiz 's' karakterinin  "FFD3" ile xorlanmış hali.

Yani bu şu manaya gelmekte, bizim girdiğimiz değerin "FFD3" ile xorlanmış hali, bize 0x97 yi vermeliydi.

Bu logic işlemi kendimiz gerçekleştirirsek;
0xFFD311111111 11010011
bizi burada D3 kısmı ilgilendiriyor, çünkü harfimiz 1 byte

11010011 ile neyi xorlarsak, sonuç 10010111(0x97) olur?

Cevap:
01000100 (ascii "D" harfi)

Şimdi biz bu işlemi her 6 karakter kontrol edilirken AL registerı hangi değerdeyse onun için tekrarlayacağız. Ancak ilk karakteri yanlış girdiğimiz için AL'ye eşitlik şartını sağlamadığı için döngüden çıkacak ve "Wrong key!" hatasını verecek. Bu kadar zahmetten sonra baştan başlamamak için kodu biraz aşağıdaki gibi editliyoruz.


JE olan komutu, JNE olarak değiştirdik. Yani eşitse değil, eşit değilse dallan.
Aynı döngüye tekrar girdiğimizde 2. karakteri de
00110011  yani
ascii "3" olarak bulduk.

Bu şekilde tüm 6 karakteri çekiyoruz. Sonuç:


Bu sorumuzu da böyle çözmüş olduk.

Bu arada ctf'den bahsedecek olursak;

Yarışmada aklınıza gelebilecek her alandan toplam 169 soru mevcut. Çoğu kaliteli sorular(misal bu çözdüğümüz 3 puanlık soruydu, bu alanda en yüksek 15 puanlık soru var, düşünün gerisini).

Yarışmada süre kısıtlaması yok, zaten admin zaman buldukça yeni sorular ekliyor. Bir şeyler öğrenmek, ctf ufkunu açmak isteyenlere tavsiye ederiz.

Özellikle SQL injection adlı bir kategori var ve sorular hayvan gibi, daha yeni ancak 22/23 yapabildik son soru hala duruyor. Soruları çözmeye çalıştığınızda niye öyle olduğunu anlayacaksınız ;)

Şu anki durumumuza gelecek olursak da 108 / 169 soru çözdük, sıralama ve puan durumu ise aşağıdaki gibi;


Huyumuzu bilenler bilir, nasılsa süre kısıtlaması yok, 1. liğe kadar kasmaya devam edeceğiz ;)

3 Mart 2015 Salı

Temel Bof 2

Yasir kardeşim temel bof konusuna giriş yapmış bende bir şeyler yazacağım. Benim anlatacağım biraz daha düşük seviyede. Aynı CTF'de farklı bir BOF sorusu üzerinden gideceğiz.

1 Mart 2015 Pazar

Temel BOF

Hackmetu yazımızda bundan sonra biraz da reverse eng. konularına yöneleceğimizi söylemiştik. Geçenlerde bir ctf nin sorularını çözerken bi bof sorusuyla karşılaştık. Soru temel buffer overflow mantığına dayalı. Çözmüşken anlatalım dedik;