01
Kas
2020

STMCTF2020 Counter-Strike Reverse Challange Writeup

CTF’in yarısında falan geldi bu soru. 2nci gelen Reverse sorusuydu. Soruda gelen arşivi açtığımızda karşımıza bir exe ve iki dll geliyordu. DLL’lerle ilgili bir işimiz yok. Uygulamanın çalışması için her ihtimale karşı soruya koymuşlar ki iyi de düşünmüşler.

İlk iş statik analize başlıyoruz. İlk olarak PEiD ile dosyayı inceliyorum.

Burada iki konuya dikkat ediyoruz. EP Section: UPX1 Subsystem ise Win32. Yani öncelikle UPX’i açmamız lazım sonrasında da incelemizi 32 bit esaslarına göre yapacağız. Öncelikle UPX ile açalım dosyayı.

Şimdi tekrar bir PEiD ile kontrol edip başka bir koruma yapılmış mı bakmak lazım. Statik analize devam edeceğim. Disassembler olarak IDA’ya uygulamayı veriyorum.

İlk iş View–>Subview–>Strings seçerek bir stringleri kontrol edelim.

Burada bir kaç kritik şey dikkatimizi çekiyor. Flag formatında olduğu belli olan %s ‘li ifade. “iaminposition”, “enemyspotted”, “need backup” ve aşağıya geldiğimizde “Firstly” diye başlayan cümle. Gerçekci olalım uygulamayı çalıştırmadan gitmeyiz bu noktada. Zaten malware değil. Uygulamayı komut satırında hiç bir parametre vermeden çalıştırdığımızda bu firstly ile başlayan cümleyi görüyoruz.

“Find the keyword and 3 numbers… at the same time decrypt the cryptex.. so you will need a keyword and 4 keys.”

Evet uygulamaya 1 keyword ve 4 anahtar vermemiz gerekiyormuş. Şimdi uygulamanın bizi ilgilendiren başlama noktası demek ki bu yazıyı gördüğümüz yer. Yukardaki bahsettiğimiz strings ekranında bu stringe çift tıklıyoruz. Açılan pencereden bunun cross referancelarına bakıp ilgili yerine gitmek için CTRL+X tuşuna basıyoruz. Bir yerde kullanılmış. OK Tuşuna basarak devam ediyoruz.

Şimdi geldik ağaç görünümüne.

Bakın burada bu cümle gelmeden önceki son duruma bakalım.

cmp [ebp+argc], 6
jnz short loc_401A1A

Yani uygulamaya verilen arguman sayısını 6 ile karşılaştır. Zero flag set edilmezse bu gördüğümüz mesaj kısmına gönder. Şimdi tekrar komut satırına dönüp uygulamayı çalıştırın. Bu sefer “Counter-Strike.exe 1 2 3 4 5” yazın. Artık hata mesajı değil “need backup” yazısını göreceğiz. Bilmeyen arkadaşlar için söyleyeyim. Uygulamalar uygulama adını da parametre olarak alıyor dosyasıyla 5’e kadar gittiğimizde 6 arguman vermiş oluyoruz.

Şimdi 6 vererek gideceğimiz yola bakıyoruz. IDA’da devam ediyoruz. Bi strcat işlemi var sonrasında bir fonksiyon çağırıyor. Adı da defuseTheBomb. Tam istediğimiz fonksiyona benziyor. Hala yukardaki ekrandayız. Burada defuseTheBomb’a çift tıklıyoruz. Aşağıdaki ekrana geliyoruz.

Şimdi burada ki bazı değerleri bastığını görebiliyoruz. Şimdilik bunlarla uğraşmayacağım. Biraz aşağıda gelince ilk dallanmayı görüyoruz.

Bu tarz crackme soruları için keywordlerden birisi. “strcmp” Burada bir string karşılaştırma yapılmış. Soruyu hazırlayan arkadaş burada bizi çok zorlamamak istememiş. İlk etapta strings ekranında gördüğümüz “iaminposition” stringini açıkca görebiliyoruz. Zero flagi set edilirse devam edeceğiz. O zaman ilk argumanımız iamintheposition. Burada yanlız ezbere gitmemek lazım. Bir kaç satır yukarı çıkarsanız neden ilk parametrenin alındığını göreceksiniz. Öncelikle EAX’e ebp+arg_0’ın değeri gönderiliyor. Sonra buna 4 ekleniyor. Yani ilk parametrenin bulunduğu satıra geçiliyor. mov eax, [eax] ile de EAX’e artık adres değil de adresin değeri atanıyor. Bu şekilde girdiğiniz ilk parametre artık EAX değerinde. Debugger ile gittiğimizde anlayacaksınız. Burayı anladık umarım. Şimdi devam ediyoruz. Bir dallanma daha var.

Biraz önce eax’a 4 eklemişti. Gördünüz mü burada da 8 eklemiş. 2’nci parametreye gidiyoruz. Burada atoi fonksiyonu kullanılmış. Typecasting yapmak için kullanılıyor. Malum girdiğimiz parametre string olarak geliyor. Bunu inte çevirmek için kullanılıyor. Daha sonra da bunu 58h ile kıyasladığını görebiliyoruz. 58h h harfinden anlyabileceğiniz üzere hexadecimal değeri. Decimal değerini hesaplayabileceğiniz gibi üzerine tıklayıp h tuşuna basarsanız IDA otomatik convert edecekt. Değerimiz 88 çıktı. Kontrol ne burada jz. O zaman 2nci parametremiz de 88 olacak.

Artık bazı şeyleri anladık daha hızlı geçeceğim. 23h (35) ile compara etmiş. Bu sefer jg var ama. Bu ne demek jump greater o zaman gireceğimiz değer bundan büyük bir değer olmalı. 36 girelim. Üçüncü parametremiz de 36 olabilir..

Devam ettik yine bir cmp var. 2Ch(44) yazıyor. Kontrol sonrası jle var. Yani less or equal ise jump et demek. Küçük veya eşit bir değer girebiliriz. O zaman dördüncü parametremiz de 44 olabilir mi acaba? Olamaz. Burada challangeda güzel bir trick var. Bakın ne demiştik hangi parametreyi alacağını belirtmek için yolunu belirtiyor diye. Burada eax ‘e ne eklemiş 0C şimdi hemen yazıyı biraz yukarı çek. Orada ne eklemiş yine 0C yani bu parametre de 3üncü degere bakıyor. Pseudo olarak kodunu yazalım dersek şöyle bir şey var.

if (argc[3] > 36)
   {
       if (argc[3] <=44) 
       {...}
}

O zaman 3üncü değerimizde bir problem yok.

Devam ettik yine aynı senaryo. Bu sefer 62h(98) ile karşılaştırıyoruz. Yine jg kullanılmış. O zaman dördüncü değerimiz 99 olabilir.

Devam ettik bakın yine eax’e eklenen değer bir öncekiyle aynı demek ki yine dördüncü değerimiz için jle yani 999’a eşit veya küçük olma şartımız var. O zaman 99 olmasında sıkıntı yok.

Şimdi farklı bir noktaya geldik. Aşağıdan yukarı gidelim. Bir strcmp var. Demek ki bir string kıyaslanacak. Üste bakıyoruz arg_0 dan sonra eax’e 14h eklemiş demekki 5nci ve son değerimizi alıp bir string kıyaslamasına sokacak. Hemen üstünde breakTheCryptex fonksiyonunun çağrıldığını görüyoruz ondan sonra da esp’ye yDOYH diye bir string atanmış. Hemen jetonu düşürüp aşağıya indiğimizde bakın strcmp nasıl bir fonksiyon iki parametre alan bir fonksiyon. Üstünde ne var edx ve eax’i esp’ye atan bir değer var. eax’de girdiğimiz değer var biliyoruz demek ki bu fonksiyonla edx’e bir string gelmesi muhtemel. Şimdi hemen breakTheCryptex’e çift tıklayıp ne yapıyormuş bakalım.

Şimdi gerek şekilden gerek sol alttaki add 1 satırından burada bir döngü olduğunu anlayabiliyoruz. Evet burası biraz karışık gelebilir. Maalesef doğru anlatacak kadar bilgim yok. Elimden geldiğince anlatayım. sub eax 3 diyerek eax’den 3 çıkartıyor. daha sonra ecx’e atıyor. ecx’i de aşağıda görüyorsunuz 20 ile xor işlemine sokuyor. En sondaki döngü için kullandığı +1 değerini tekrar başa çıkınca eax’e ekliyor. Dolayısıyla her tur karakteri de bir yana almış oluyor. kelime[i] yani aslında olay. Şimdi buraya giren kelime neydi yDOYH. Hexadecimal karşılığını hemen online bir tool veya python ile bakalım. 79 44 4f 59 48. Her değerden 3 çıkartıp 20 ile XOR lıyalım. Ufak bir python scripti yazabilir, elle yapabilir veya online bir tool kullanabilirsiniz. Hesapladığımızda 56 61 6c 76 65 çıkıyor. Bunu da texte çevirdiğimizde Valve yazısıyla karşılaşıyoruz.

Deneyelim artık. Çünkü 5 değer de çıktı. Counter-Strike.exe iaminposition 88 36 99 Valve

Yine bize hüsran yine bize hasret var 🙂 Meğer devamı varmış. Bakmamış mıydık. En son döngü de kaldıysanız geri tuşuna basın.

Evet bakın bir fonksiyona daha call atmış. _safeVault. Soruyu hazırlayan arkadaş temel ama güzel challangelarla zorladıkça zorluyor. safevault’a çift tıklayıp gidiyoruz. Evet gözümüz korktu bu sahneyi görmek istiyoruz 🙂

Graph Overview

Sol alttaki graph overview’e bakınca bile sanki yeni bir soru çıktı karşımıza. Bi duralım sakince şöyle tüm kodu değil de işimize yarayan kısımları anlamaya çalışalım. Şimdi en üstteki blokta şöyle güzel bir şey var. Enter a password yazısını görüyoruz. String penceresine dönerseniz veya hatırlarsanız burada 5 karakterlik bir parola istiyor bizden. ve sonrasında koşulsuz devam ediyor. Alttaki blokta ikiye dallanmayı görüyoruz. Ancak bakarsanız bloklardan birisi tekrar ona dönüyor.

Yakaladık mı olayı. Bak yine add 1 var ve şekilden de anlaşıldığı üzere bir döngü var burada. Şimdi yukardaki bölüm döngü devam edecek mi buna bakıyor. Edecekse soldaki bloğa giriyoruz. EDX’e ebp+var_12’deki değeri atıyor bu ney biraz önce scanf ile bizden aldığı değer olmalı. Bunu %100 açıklayamıyorum maalesef yanlış anlatmaktan korkuyorum. Sonrasında 2 bakın sadece byte ı çekip 2 ekliyor. Yani bir karakteri. Bu döngü böyle dönüyor. Ne anlıyoruz. Girdiğimiz değerin her karakterine 2 ekliyor. Döngü bitince sağdaki bloğa giriyor. Burada da yine bir scanf çağrısı var. Bizden bir değer daha isteyecek. Sonrasında TEST AL, AL sorgusuna göre bir değer çıkacak. Emin değilim ama bu değerler set edilmiş gibi bir kontrol gibi. https://reverseengineering.stackexchange.com/a/25189 Ben de bu linke baktım şahsen. Şu an ne aşamadayız. 2 değer gireceğiz 1 inin her karakterine 2 ekleyeceğiz. Sonra bir karakter daha gireceğiz. Alta indiğimizde karşımıza çıkan blok artık basit bir şey 🙂

uzunluk 5’den büyük mü diye bakıyor.

Demek ki ikinci değer de 5 karakterden büyük olmayacak. Büyük değilse aşağıdaki düğüme ulaşıyoruz.

Evet buradan anladığımız şu eğer strncmp sonucu patlarsak Safe coult not identify password diyecek. Diğer uzun olan kısım da sanırım artık bize flagi verecektir. O zaman buraya yoğunlaşıyoruz. Buradaki comparison strncmp olarak yapılmış. int strncmp(const char *str1, const char *str2, size_t n) kullanımı ise bu şekilde. Yani bu fonksiyonu çağırırken 3 değer pushlamamız gerek. Üst bloktayız kaçırmayın 🙂 Bakın strncmp öncesi üç adet mov var. birisi size_t diğer ikisi char * yollamış. fonksiyonumuzun girdileri bunlar. Şimdi bakalım tekrar size 5 demiş üçüncü paramtere tamam. Diğer parametre neymiş eax’i almış. Öncesinde eax’e ebp+var_1E ‘yi vermiş. lea’nın açıklamasına giremiyorum bu noktada mov gibi düşünün. ebp+var_1E ve ebp+var_18’deki değerleri 5 karakterlik olarak karşılaştıracağız. IDA’da sevdiğim bir özellik var bu noktaya kadar geldiyseniz benimle aynı işlemi yapın. ebp+var_18 yazısındaki var_18’e tıklayın sararacak yazı.

Bak tüm var_18’ler sarardı. scanf’de aldığımız değer değil mi bu 🙂 Bir de var_1E’ye tıklayalım. Biraz önceki döngünün içinde çıktı birşeyler. Tam 2 ekliyorduk ya hani her bir karaktere.

Demek ki girdiğimiz değerlere 2 ekleyecek sonra da girdiğimiz değerle kıyaslayacak. Sonrasında flagi görmeyi ümit ediyoruz 🙂

Baştan hatırlayacak olursak; Counter-Strike.exe iaminposition 88 36 99 Valve parametreleriyle uygulamayı çalıştır. Locked safe için istediği yere ABCDE (veya istediğin bir şey gir) Şimdi enter the safe key diyecek. Neydi bir öncekinin 2 karakter arttırılmış hali o zaman CDEFG girelim buna da. Veeee bingo!!! Counter-Terorist win 😛

Bu aslında write up’ın öğretici versiyonu oldu. Umarım anlamışsınızdır. Sadece statik analiz kullanarak aslında çok zor görünen ama aslında temel konuları içeren bir crackme’yi nasıl geçebiliriz. Dinamik analiz ile çok daha hızlı sonuca ulaşabiliriz. Onu da size bir video ile anlatacağım. Başka bir gün altına eklerim artık.

Not: Uzman değilim. Anlatımda yanlışlarım hatalarım olmuş olabilir. Affola.

Ollydbg ile dinamik analiz ile çözümü de aşağıdaki videoda.

Share

You may also like...

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir