Metehan Kalkan tarafından yazılmıştır.
Reversing, reverse engineering veyahut Türkçesi ile tersine mühendislik; bir sistemin, yazılımın
veya bir cihazın işleyişini, yapısını anlayabilmek için yapılan analiz işlemine denir. 2 tür reverse engineering çeşiti vardır; dinamik ve statik.
Statik reverse engineering, binary’i herhangi bir debugger vasıtasıyla veya direkt olarak çalıştırmaktan ziyade çeşitli disassembler araçları kullanarak, assembly kodundan çeşitli varsayımlar çıkarmak ve
uygulamanın nasıl çalıştığına dair tahminlerde bulunabilmeyi kapsar.
Dinamik analiz ise, debugger kullanarak, adım adım uygulamanın verdiği response’lar
ölçüsünde uygulamanın nasıl çalıştığını anlamaktır.
Cracking ise, binary’yi reversing teknikleri ile istenilenin dışında davrandırarak veya verdiği
response’lar üzerinden çıkarımlar yaparak istenilen yönde hareket ettirmektir.
Ben bugün seçtiğim x86-64(64 bit) mimarisi için compile edilmiş ve c/c++ ile yazılmış bir
linux binary’sini adım adım crack edebilmeyi göstereceğim. İndirdiğim binary linki: https://crackmes.one/crackme/60957b9a33c5d458ce0ec88e
Zip şifresi:crackmes.one
Önce Statik Analiz
[1] Zipten çıkardığımızda karşımızda EZwan isimli bir çalıştırılabilir dosya duruyor. İlk önce strings
komutu ile binary’e herhangi bir packing işlemi uygulanıp uygulanmadığını kontrol
ediyoruz, tabiki aradığımız şey stringlerde de bulunabilir.
[2] Uygulamayı çalıştırdığımız zaman, bizden bir argüman istediğini farkediyoruz. Denediğimizde
ise yanlış şifre yazdığımız ve tekrar denememiz konusunda bir uyarı alıyoruz.(Burada tabiki
buffer overflow kontrolü yapabiliriz fakat bugünlük konumuz reversing )
[3] Hemen ghidra ile binary’yi disassemble edip kodlara bakmaya başlıyoruz.(ghidra open
source bir disassembler’dır, https://github.com/NationalSecurityAgency/ghidra)
[4] Function bölümünden gördüğümüz üzere bir tek main fonksiyonu tanımlanmış. Kod
bölümünde ise çeşitli if statementları görüyoruz. Tabiki kodu okuyup ona göre bir çıkarım
yapabiliriz fakat ben direkt debugger ile takip edip, tahminim olan registerlardaki value’lar ile
aradığımız şifreyi bulabileceğimizi düşünüyorum.
Hemen gdb ile binary’i açalım ve main fonksiyonunu disassemble edelim.
Disassemble edilmiş fonksiyonu gördüğümüz zaman ilk if bloğu gözüme
çarpıyor(main+58). Boldlanmış instructiondan önce görüldüğü üzere birşeyler 2 ile compare
ediliyor. Compare işleminin sonucu direkt eax registerına yazılır ve jne(jump not equal) ile
check ediliyor. Eğer 2 den farklı ise direkt fonksiyonun sonlarına doğru gidiyor.
[5] İkinci if bloğunu görmemiz zor olmamıştır diye düşünüyorum. For döngüsünde ise if
bloğunun 8 defa tekrarlanacağını görüyoruz. Buradan şu anlamı çıkarabiliriz, bizden 8
karakterli bir şifre bekliyor. Nitekim cl, al comparison işlemi de birer byte karşılaştırdığını
söylüyor. Ecx 32 bitlik bir registerdır ve 16 bit hali cx’dir, cx ise ch, cl olarak iki tane 8 bitlik
registerlara ayrılabilir(8 bit=1 byte=1 karakter). Aynı şekilde al registerı da eax registerının 8
bitlik çeşitlerinden biridir.
Bizim assembly kodumuz intel mimarisine göre disassemble edilmiştir. Yani compare
instruction’unda şöyle bir kural vardır: cmp dest,src
Buradan şunu anlayabiliriz; al register’ında bizim yazdığımız değer var ve bu değer cl
register’ında ki değer ile karşılaştırılıyor. Bu işlem 8 defa yapılacak, bunu unutmayalım.
[6] Artık ikinci if bloğunun bir üstündeki compare işlemine breakpoint koyarak cracking’e
başlayalım
[7] Breakpoint koyduk ve 8 karakterli bir string yazıp programı run ettik. Programın akışı devam
etti ve bizim breakpoint hit edildi.Şimdi ise registerdaki değerlere bir göz atalım.
Hmm, ilginç
hemen ascii tablosundan eax ve ecx registerlarındaki değerlerin string
karşılığına bakalım.
0x6d = m
0x4e = N
[8] Hemen ecx registerındaki değeri bir yere kaydedip, eax registerındaki değeri ise 0x4e
yapalım.
[9] Programı devam ettirelim ve döngünün devam ettiğini tekrardan aynı if bloğuyla
karşılaştığımızı görelim.
[10] Register değerlerini kontrol edelim ve ecx registerında bu sefer başka bir değer olduğunu
görelim.
[11] Tekrardan aynı işlemleri yapalım ve ecx’deki değerleri bir kenara yazalım.
Bu işlemler 8 defa tekrarlandıktan sonra şifrenin doğru olduğuna dair bir mesaj göreceğiz.
Ascii değerlerini bir kenara yazmamızı istemiştim çünkü onları şimdi stringe çevirip gerçek şifreyi göreceğiz.
4e 69 63 65 44 75 64 65 = NiceDude
Teşekkür ederim
[TR] Reversing Nedir? Bir Linux Binary’si Nasıl Cracklenir?
Reversing, reverse engineering veyahut Türkçesi ile tersine mühendislik; bir sistemin, yazılımın
veya bir cihazın işleyişini, yapısını anlayabilmek için yapılan analiz işlemine denir. 2 tür reverse engineering çeşiti vardır; dinamik ve statik.
Statik reverse engineering, binary’i herhangi bir debugger vasıtasıyla veya direkt olarak çalıştırmaktan ziyade çeşitli disassembler araçları kullanarak, assembly kodundan çeşitli varsayımlar çıkarmak ve
uygulamanın nasıl çalıştığına dair tahminlerde bulunabilmeyi kapsar.
Dinamik analiz ise, debugger kullanarak, adım adım uygulamanın verdiği response’lar
ölçüsünde uygulamanın nasıl çalıştığını anlamaktır.
Cracking ise, binary’yi reversing teknikleri ile istenilenin dışında davrandırarak veya verdiği
response’lar üzerinden çıkarımlar yaparak istenilen yönde hareket ettirmektir.
X86-64 Linux Binary Cracking
Ben bugün seçtiğim x86-64(64 bit) mimarisi için compile edilmiş ve c/c++ ile yazılmış bir
linux binary’sini adım adım crack edebilmeyi göstereceğim. İndirdiğim binary linki: https://crackmes.one/crackme/60957b9a33c5d458ce0ec88e
Zip şifresi:crackmes.one
Önce Statik Analiz
[1] Zipten çıkardığımızda karşımızda EZwan isimli bir çalıştırılabilir dosya duruyor. İlk önce strings
komutu ile binary’e herhangi bir packing işlemi uygulanıp uygulanmadığını kontrol
ediyoruz, tabiki aradığımız şey stringlerde de bulunabilir.
[2] Uygulamayı çalıştırdığımız zaman, bizden bir argüman istediğini farkediyoruz. Denediğimizde
ise yanlış şifre yazdığımız ve tekrar denememiz konusunda bir uyarı alıyoruz.(Burada tabiki
buffer overflow kontrolü yapabiliriz fakat bugünlük konumuz reversing )
[3] Hemen ghidra ile binary’yi disassemble edip kodlara bakmaya başlıyoruz.(ghidra open
source bir disassembler’dır, https://github.com/NationalSecurityAgency/ghidra)
[4] Function bölümünden gördüğümüz üzere bir tek main fonksiyonu tanımlanmış. Kod
bölümünde ise çeşitli if statementları görüyoruz. Tabiki kodu okuyup ona göre bir çıkarım
yapabiliriz fakat ben direkt debugger ile takip edip, tahminim olan registerlardaki value’lar ile
aradığımız şifreyi bulabileceğimizi düşünüyorum.
Hemen gdb ile binary’i açalım ve main fonksiyonunu disassemble edelim.
Disassemble edilmiş fonksiyonu gördüğümüz zaman ilk if bloğu gözüme
çarpıyor(main+58). Boldlanmış instructiondan önce görüldüğü üzere birşeyler 2 ile compare
ediliyor. Compare işleminin sonucu direkt eax registerına yazılır ve jne(jump not equal) ile
check ediliyor. Eğer 2 den farklı ise direkt fonksiyonun sonlarına doğru gidiyor.
[5] İkinci if bloğunu görmemiz zor olmamıştır diye düşünüyorum. For döngüsünde ise if
bloğunun 8 defa tekrarlanacağını görüyoruz. Buradan şu anlamı çıkarabiliriz, bizden 8
karakterli bir şifre bekliyor. Nitekim cl, al comparison işlemi de birer byte karşılaştırdığını
söylüyor. Ecx 32 bitlik bir registerdır ve 16 bit hali cx’dir, cx ise ch, cl olarak iki tane 8 bitlik
registerlara ayrılabilir(8 bit=1 byte=1 karakter). Aynı şekilde al registerı da eax registerının 8
bitlik çeşitlerinden biridir.
Bizim assembly kodumuz intel mimarisine göre disassemble edilmiştir. Yani compare
instruction’unda şöyle bir kural vardır: cmp dest,src
Buradan şunu anlayabiliriz; al register’ında bizim yazdığımız değer var ve bu değer cl
register’ında ki değer ile karşılaştırılıyor. Bu işlem 8 defa yapılacak, bunu unutmayalım.
Sıra Dinamik Analizde
[6] Artık ikinci if bloğunun bir üstündeki compare işlemine breakpoint koyarak cracking’e
başlayalım
[7] Breakpoint koyduk ve 8 karakterli bir string yazıp programı run ettik. Programın akışı devam
etti ve bizim breakpoint hit edildi.Şimdi ise registerdaki değerlere bir göz atalım.
Hmm, ilginç
karşılığına bakalım.
0x6d = m
0x4e = N
[8] Hemen ecx registerındaki değeri bir yere kaydedip, eax registerındaki değeri ise 0x4e
yapalım.
[9] Programı devam ettirelim ve döngünün devam ettiğini tekrardan aynı if bloğuyla
karşılaştığımızı görelim.
[10] Register değerlerini kontrol edelim ve ecx registerında bu sefer başka bir değer olduğunu
görelim.
[11] Tekrardan aynı işlemleri yapalım ve ecx’deki değerleri bir kenara yazalım.
Bu işlemler 8 defa tekrarlandıktan sonra şifrenin doğru olduğuna dair bir mesaj göreceğiz.
Ascii değerlerini bir kenara yazmamızı istemiştim çünkü onları şimdi stringe çevirip gerçek şifreyi göreceğiz.
4e 69 63 65 44 75 64 65 = NiceDude
Teşekkür ederim
Moderatör tarafında düzenlendi: