Hoşgeldin Misafir

Cracking Ders #1

İliya Norton

2 Şub 2018
24 Mesaj

Aktiflik

Seviye

Deneyim

TIM / GÖREV:
İlk cracking Dersi için seçtiğim uygulama aslında “crack me” değil de “keygen me” olarak adlandırılabilir. Ancak seri halinde gelecek çözümlerden bu yazının konusunu ilgilendiren “hey dostum iki bit değiştirdim kırdım” durumunu yaşamak.-



Kıracağımız Dosya : http://www.woodmann.com/IDArchive/ID-RIP/database/idcrackme.zip


Crack Aracımız (OllyDbg)  :  http://www.ollydbg.de/

Amaç: İlk açılışta çıkan uyarı mesajını engellemek ve programda “Generate” butonuna basınca “BadBoy” harici pozitif bir yanıt almak.-

Uygulamayı indirip sadece inceleyelim. Davranışlarını not alalım.-


bBbaon.png
-


-1: Uygulama çalışınca “Rules” başlığına sahip içerisinde “KeygenMe and delete this window good luck !!!” metni bulunan bir MessageBox açılıyor. Onaylayıp geçiyoruz--


-
A1JvW7.png
-
-



--2. Tipik bir kullanıcı adı ve serial no kontrolu yapan form ile karşılaşıyoruz. İki textbox alanını da boş bırakıyoruz, sadece isim giriyoruz, sadece serial giriyoruz, uzun isim-serial giriyoruz, kısa giriyoruz ve gelen hata mesajlarını inceliyoruz.-
-
-

 -

Kullanım analizi sonrası anladığımız kadarıyla program bir isim ve serial no’yu şart koşuyor. Eksiklerinde duruma uygun hata mesajları gösteriyor. Eğer ikisine de sallama bir şeyler girersek “BadBoy” hata mesajını alıyoruz. “BadBoy” ve “GoodBoy” crackme uygulamalarında sık karşılaşacağımız mesajlardan.-

Sanırım düşmanın dış görünüşünü, hedefini ve motivasyonlarını çıkardık. Bu bilgiler yeterli mi? Bir kaç soluk tahmin yapmak için evet ama hareket tarzını, dövüş tekniğini, savunma ve saldırı özelliklerini anlamak için güvenebileceğimiz bir ön yargı değil. O zaman içine bakalım bir de.-

 -
--OllyDBG ile programımızı açıyoruz. İlk açtığımızda önümüze şöyle bir ekran geliyor:---



oO7aD2.png
-


-File -> Open ya da standart sarı dosya simgesine tıklayarak uygulamamızı Olly’ye yüklüyoruz.--

0EDaO9.png
-


-Disassembly penceremiz şu şekilde hazırlanıp, uygulama suspend edilmiş halde önümüze geliyor. Gördüğünüz gibi adres kolonunda siyah labelın durduğu yerde <ModuleEntrypoint> yazıyor. Uygulamanın başlangıç noktasındayız. Bizi ilk noktada asıl ilgilendiren, Olly’nin bizim için analiz ettiği 0040821c ile 0040822A adreslerinin arası. Windows’un User32.dll kütüphanesinde bulunan MessageBoxA fonksiyonu, parametreleri önce stacke eklendikten sonra çağırılıyor. Hadi burada  biraz dökümantasyona bakalım çünkü bir şeyin daha net oturması için göstermem gereken noktalar var.-
-

 -

MessageBoxA, Windows’ta User32.Dll kütüphanesinde bir fonksiyon. User32.dll de “Windows USER”  denilen kullanıcı etkileşimlerinin genelinin yönetilmesini sağlayan fonskiyonların bulunduğu kütüphane. Pencere yaratmak, kapatmak, windows mesajlarının yönetimi vb… Öyleyse, MessageBoxA fonksiyonunu sahibine soralım. Yani Microsoft’a.-

http://msdn.microsoft.com/en-us/library/windows/desktop/ms645505(v=vs.85).aspx-




-Ne diyor MSDN? Bir sistem simgesi, buton seti, durum, bilgilendirme ya da hata gibi uygulama bazlı mesajların gösterildiği bir dialog penceresi açan fonksiyon. Kullanıcının etkileşimine göre (Evet. Hayır. Tamam. İptal vb…) bir integer değer döner.--


-int WINAPI MessageBox(
 _In_opt_  HWND hWnd,
 _In_opt_  LPCTSTR lpText,
 _In_opt_  LPCTSTR lpCaption,
 _In_      UINT uType
-
-




--Görüldüğü gibi fonksiyon 4 parametre alıyor. MessageBox’ın sahibi olan pencerenin handle değeri, içinde barındırdığı metin, başlığı ve de stili. Stili UINT tipinden değer alıyor. Neler olduğu işaret ettiğim MSDN sayfasında anlatılmış.-
-
-

Olly’nin bu fonksiyonu çağırması ile MSDN’de yazan arasındaki farkı görüyor musunuz?-

0040821C . 6A 40 PUSH 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
0040821E . 68 4C824000 PUSH Crackme_.0040824C ; |Title = "Rules"
00408223 . 68 54824000 PUSH Crackme_.00408254 ; |Text = "KeygenMe and delete this window good luck !!!"
00408228 . 6A 00 PUSH 0 ; |hOwner = NULL
0040822A . E8 41C4FFFF CALL &lt;JMP.&amp;user32.MessageBoxA&gt; ; \MessageBoxA


Evet! Farkettiğiniz gibi fonksiyonu çağırmadan önce argümanları hafızaya(Stack) atarken ters sırayı kullanıyor. Çünkü ne demiştik? “Son giren ilk çıkar”. Böylece 0040822A adresindeki fonksiyonun çağırıldığı instruction çalıştığında, en üstte handle, onun altında metin değişkenleri olacak. Böylece istenen sırada fonksiyon argümanlarına erişmiş olacak. Bunu göstermek istemiştim. Umarım bu örnekle birlikte stackin çalışma prensibi konusunda bir adım daha ileriye gidebilmişizdir.-

Hazır “stack”, “hafızaya atmak” demişken bir de argümanların atandığı instructionları inceleyelim.-

0040821E . 68 4C824000 PUSH Crackme_.0040824C ; |Title = "Rules"

İkinci kolonda byte code var. “68 4C824000” yanındaki kolondo da assembly hali “PUSH Crackme_.0040824C“. Buradan 68′in PUSH’un opcode hali olduğunu anlamak zor değil. Dilimize çevirirsek burada ne diyor? “Dump’taki 0040824C adresindeki 32bit değeri al, stackin(yığının) en tepesine koy”. Olly’de o anda dumpta o adrese bakarsanız “Rules” yazısını göreceksiniz. Yani orada kocaman “Rules” yazısını değil sadece “Rules” yazısının hafızadaki yerini stack’e atıyoruz. Çünkü uygulamanın doğrudan eriştiği hafıza adresleri stacktedir. Dump dediğin çöplük gibidir. Düzensizce atılmış.-

Diğer değişkenleri de bu şekilde çağırdıktan sonra zaten hali hazırda hafızada bulunan ve uygulamamızın erişim yetkisi olduğu user32 modulünden MessageBoxA’yı çağırıyoruz.-

0040822A . E8 41C4FFFF CALL &lt;JMP.&amp;user32.MessageBoxA&gt; ; \MessageBoxA

Onun da erişilebilir(Aslında shared memory alanı. Ayrı konu yazısı bu) adresi “41C4FFFF” oluyor.-

 -

Demek ki bir uygulamada, arka planda MessageBox penceresi bu şekilde çağırılabiliyormuş. İlk amacımız da bu pencerenin görünmesini engellemekti. Peki neler yapabiliriz?-

  • Stil eklediğimiz yere jump koyabiliriz.
  • MessageBoxA fonksiyonunu çağırmayabiliriz. Yani oradaki tüm byte kodların değerini NOP değeri(90)  ile değiştirebiliriz.
 -
--Yazımızın konusu “Yaldır yaldır cracking” olduğu için oradaki 4 instructionın değerini de NOP yapıyoruz. Nasıl mı? Önce assembly penceresinde o alanları mouse ile seçiyoruz(sürükle, ctrl ile tek tek, shift ile sınırları belirtip. Yol çok.) daha sonra da farenin sağ tuşuyla açılan pencereden Binary -> Sonra da “Fill With NOPs” seçeneği ile.---



-
jynDzm.png
-
-



--F9′a basıp programımızı çalıştırıyoruz. TA-DAM! Baştaki “beni kaldır” diyen mazoşist pencere çıkmadan doğrudan form ekrana geldi. İyi iyi. İlk aşamayı atlattık. O zaman sol üstteki dosya simgesinin yanındaki sol doğru iki kırmızı ok gösteren düğmeye basarak uygulamamızı hafızaya baştan yükleyelim.-
-
-

Yüklediniz mi? Hehe ama değişiklikler gitti. Çünkü biz uygulamanın az önce hafızaya yüklenmiş halinde değişiklik yaptık, kaydetmedik. Yani bir uygulamanın diskteki hali ile hafızadaki hali  birbirinden ayrı şeylerdir. İşte bu noktada Disassembler ve Debugger farkına geldik.-

Disassembler elindeki raw datada bulunan byte kodları geri assembly koduna çevirir. Makine kodundan assembly koduna. Şimdiye kadar “Makine Kodu = Assembly” diye biliyorsanız artık öyle bilmeyin. Debugger da aynı işlemi yapar ancak programın debug da edilebilir yapıda olması için bunu hafızada canlı canlı yapar. Hafızadaki değer işlemciye gitmeden önce de o vardır, döndüğünde de o var. Eli kolu her yerdedir. Debugger için “Dinamik Disassembler”, ” disassembler için de “Statik Disassembler” diyebiliriz. (Burası editlenebilir) -

Yani, debugger uygulamanın hafızaya yüklenmiş haliyle uğraştığı için yaptığımız değişiklikleri dosyanın diskteki statik haline de uygulamamız gerekiyor. Bunun için de bir hex editör ile dosyayı açıp, söz konusu değişiklikleri byte byte statik dosyaya işliyoruz. Yok lan şaka yaptım. Aslında önce yapalım diyecektim de komedisi az, çilesi büyük bir şaka olacaktı. Bu iş için de Olly kardeşimizi kullanabiliyoruz.-

Değişiklik yaptığımız yerleri seçip, sağ tıkla ulaşılan aynı menüden “Copy To Executable” -> “Selection” yolunu seçiyoruz. Statik dosyamızın bulunduğu pencere geliyor. Çıkan mesaj pencereye onay verince yine aynı değişiklikler uygulanıyor. Orada da sağ click ile “Save File” diyerek dosyamızın yeni halini kaydedebiliyoruz. Mesela “cracked1.exe” diyerek kaydettim ben.-

Eğer bu süreçte bir hata yapmadıysak, cracked1.exe uygulamasını çalıştırınca rahatsız edici mesaj penceresi gelmeden doğrudan form gelmeli. Test ettim bende öyle geliyor.-

Öyleyse Olly’e yeni exemizi yükleyerek devam edelim. ModuleEntryPoint’te aşağı doğru giderseniz fazla gidemediğiniz görürsünüz. Programın Main bölümü 50-60 instructiondan oluşuyor ama kendi çapında bir sürü işlem yapıyor. Demek ki bir yerlerde asıl işi yapan fonksiyonlara çağrı var. Assemblyde o an işlenen adresi değiştirmenin yollarından birisi de “Call” komutudur. EIP registerı her zaman bir sonraki işlenecek adresi tutar. Böylece EIP’in tuttuğu değeri manipüle edebilen her komut programın yönelimini değiştirebilir. Elbette “Call”dan başka komutlar da var ama sırayla.-

“Call” dedik, “EIP’i belirtilen adresi gösterecek şekilde manipüle eder”. Güzel. Gitmek dert değil. Peki geri dönüş? Çağırdığı fonksiyondaki iş bitince bir aşağı döneceğini gariban EIP nasıl anlayacak? Onu da şimdi görelim.-

Main bölümü dedik çok az ama daha önce kaldırdığımız MessageBoxA fonksiyonun altında iki tane “Call” komutu var. O zaman ilkine girerek bakalım neler oluyor.-

00408240                 .  E8 53C4FFFF   CALL cracked1.00404698

 -

Bunun için çalışma anında “adım adım” giderken F7′e basmanız ya da suspend bir anda o instructionın üzerine çift tıklamanız yeterli. Adrese çift tıklayarak breakpoint de koyabilirsiniz. Haydi işaret edilen 00404698adresine gidelim.-

00404698     /$  55            PUSH EBP
00404699     |.  8BEC          MOV EBP,ESP
0040469B     |.  53            PUSH EBX
0040469C     |.  6A 00         PUSH 0                             ; /lParam = NULL
0040469E     |.  8B5D 08       MOV EBX,DWORD PTR [EBP+8]          ; |
004046A1     |.  53            PUSH EBX                           ; |DlgProc
004046A2     |.  51            PUSH ECX                           ; |hOwner
004046A3     |.  52            PUSH EDX                           ; |pTemplate
004046A4     |.  50            PUSH EAX                           ; |hInst
004046A5     |.  E8 96FFFFFF   CALL <JMP.&user32.DialogBoxParamA> ; \DialogBoxParamA
004046AA     |.  5B            POP EBX
004046AB     |.  5D            POP EBP
004046AC     \.  C2 0400       RET 4


Gördüğünüz gibi ufak bir fonksiyon ile karşı karşıyayız. Baştaki ilk üç instruction standarttır. Eğer bu gidişi debug aşamasında yaptıysanız ve de acele etmediyseniz “Call” instructionı çalışır çalışmaz stacke;
“0018FF60 00408245 RETURN to cracked1.00408245 from cracked1.00404698″
gibi bir değer atıldığını göreceksiniz. İşte bu bizim geri dönüş çıpamız. Şu an RET(return, dönüş) komutu çalışsa stackte ilk eriştiği adrese dönmeye çalışır. Stack işte. Ne yapsın. : )-


Eski hafıza frame pointerını stacke atıyor. O an stackte bulunan yeri yeni frame pointer noktası yapıyor. Böylece fonksiyonun lokal değişkenleri ile elin çocuğu karışmıyor. Devam ettiğimizde gördüğümüzMessageBoxAfonksiyonunun çağrısına benziyor.-

http://msdn.microsoft.com/en-us/library/windows/desktop/ms645465(v=vs.85).aspx-

argümanların ne işe yaradığına MSDN’den bakabilirsiniz.-

Ana formumuzun açıldığı, buton eventlerinin işlendiği yani bize geçiş izni verilen ya da verilmeyen bütün kontroller burada. O kadar kontrolün 5-10 satırda olması saçma mı geldi? İşte o zaman tıklamadığınız şu üstteki linke bu sefer tıklayın ve dördüncü argümanın(DlgProc – DialogProc) ne yaptığını iyi okuyun. Ona atanan değeri de (00407F04) değeri de not alın.-

Bu sefer okuduğunuzu var sayarak devam ediyorum. EBX registerındaki değeri argüman olarak alıyor. EBX registerına, o değeri de daha bu program içindeki mini fonksiyon gelmeden önce atıyoruz. Haydi o zaman geri dönüp oraya bakın ama orada işaret edilen “Dump” adresinde de açık seçik bir şey yok. Eh demek ki Dump’tan ya da Stackten bir değişken atılmıyor oraya. Zaten linke tıklayıp bahsettiğim yeri okuduğunuz için(okudunuz di mi lan?” oradaki durumun farkındasınız.-

Zaten olay da debuggerda satır, satır gezmekle olmuyor. Olly’nin güzelliklerinin birisi de program içindeki statik stringleri arayabilmek. Elimizde mis gibi “BaD Boy” mesajı var. O zaman onu arayarak başlayalım.-

Assembly penceresine sağ tıklayıp “Search For” -> “All referenced text strings” yolunu seçiyoruz. Bu bize uygulamanın içinde hafızaya yüklenen ve çalışma esnasında çağrılacak stringlerin listesini veriyor.-

 -
--Açılan pencerede de sağ tıklayıp “Search for text” seçeneği ile içinde arama yapabiliyoruz. ---


---Burada bir uyarıda bulunmam gerekiyor. Sürekli aşağı doğru arama yapıyor Olly. Yani arama yapmadan önce listedeki en üst kayda gidip tıklamanız sağlıklı sonuç alabilmek için önemli.-
-
-
-

Listede “BaD Boy” mesajını Case Insensitive olarak arayalım.-

Aha buldu:-

 -

0040808D    PUSH cracked1.00408194    ASCII "BaD BoY"

0040808D adresinde dumpta “BaD Boy” stringini tutan adres stacke atılıyor. Ve de koca programda sadece bir kere. Haydi gidelim oraya.-

Ooo karşımızda normal için kısa ama bu crackme için gayet uzun bir fonksiyon çıktı. Sağolsun Olly başlangıç ve b itiş noktalarını bize işaretliyor.-




Makalenin devamı için yer yemiyor arkadaşlar Devamı Burada ——>> http://www.turkhacks.com/konu-1-makalenin-devami.html