Şubat 2020

5 Şubat 2020 Çarşamba

Tersine Mühendislik (Reverse Engineering)









Tersine mühendislik basitçe derlenmiş bir binary veya bir exe uzantılıi yani çalıştırılabilir bir dosyanın nasıl çalıştığını anlamaya yönelik uygulanan sürece denir.
Tersine mühendislik bir sistemin daha yüksek bir soyutlama seviyesinde temsilini yaratmak için analiz edilmesi işlemidir.
Programcı programı genellikle yüksek seviyeli dillerde (c ,c++, visual basic v.b.) yazmaktadır. Bu yazılan kodlar insanlar tarafından anlaşılmaktadır fakat kod derlendikten sonra makinanın anlayabileceği dile çevrilir çevirildikten sonra ise insanlar tarafından çok zor anlaşılır duruma gelir.

Tersine Mühendislikle Neler Yapılabilir

-         Açık kaynak kodlu olmayan yazılımın kaynak kodlarını ortaya çıkarma
-         Malware analiz edebilme olanağı
-         Programların lisans korumasını atlatma (Cracking)
-         Yazılımlarda zafiyet aramak (Yazılımların sağlamlığını kontrol etme)
-         Yazılımlara ek özelikler getirme (patching)
-         Oyun hileleri

Reversing (Analiz) çeşitleri:
·        Statik analiz
·        Dinamik analiz


Statik Analiz: statik program analizi execute etmeden yani programı çalıştırmadan yapılan yazılım analizidir.

Dinamik Analiz: dinamik program analizi ise o an sanal veya gerçek bir process üzerinde execute olan programa yapılan analizidir.

Tersine Mühendislikte en çok kullanılan programlar:
·        Disassemblerlar
·        Debuggerlar
·        PE Editörleri
·        Hex-Resource Editörler
·        Sistem izleme araçları


Disassembler: bu yazılımlar, programı disassembly işleminden geçirerek programın assembly kodu şeklindeki halini gösterir.  Bu olay bize programda çağrılan fonksiyonları, string değerleri vs. görüp incelememize olanak sağlar.
En yaygın olarak kullanılan disassembler IDA dır.

Debugger: debuggerlar ile programın çalışmasını satır satır izleyebiliriz.  Disassembler gibi çalışırlar fakat ek olarak işlemleri izleme imkanımız olur.
Çoğu zaman cracking, malware analizi, exploit geliştirme aşamalarında kullanılırlar.
Bir debugger ile programın çalışması esnasında değişiklik yapılabilir.
En yaygın olarak kullanılan debuggerlar:
-         ImmunitlyDebugger
-         OllyDbg
-         WinDbg

Hex- Resource Editörleri:
Diğerlerine göre çok yaygın olarak kullanılmaz. Basit string düzenlemeleri. Bayt değiştirmeleri. Hızlı kod analizi yapabilir.
Birçok hex-resource editör mevcut;
-         HxD
-         Hes Workshop
-         ResEdit
























 

Assembly Programlama Dili Nedir ve Temel Bilinmesi Gereken Assembly Kodları ?










Assembly:
Assembly dili, kısa kelimelerde oluşan komutlar kullanılarak makine dilinde kod yazmaya yarayan programlama dilidir.




Assembly in sağladıkları;
-          Bize işlemcimiz üzerindeki her komuta aracısız erişim sağladı. Yani kod yazarken muhatabımız işlemci ve üzerinde çalışmakta olduğu işletim sistemidir. Bu bize oluşturacağımız programın kodlanması esnasında çok yüksek bir kod hakimiyeti sağlar.
-          Yazdığımız her satır kod 1 ila 4 byte civarında olup çok az yer kaplar. Diğer dillerde yazılan kodlar aynı işi yapsa dahi bizimle aramızda derleyici bulunmaktadır ve programın işleyişini sağlama almak amacıyla komutlar arasında ek bilgiler girmekte ve programımızın boyutu büyümektedir. Ayrıca diğer dillerdeki komutlar işlemci üzerindeki komutlarla uyuşmaz ise derleyici bunu dolambaçlı bir şekilde işlemciye anlatır ve yazılan tek bir komut makina dilinde yüzlerce komuta karşılık gelebilir. Herhangi bir dilde yazılan basit bir program assemblly diline göre 6- 7 kat daha fazla boyuttadır.
-          Yazdığımız programlar (eğer bir algoritma hatası yoksa ) diğer dillerdeki şekillerine göre her zaman daha az yer kaplar. Programın daha az yer kaplaması çalışırken daha az bellek tüketilmesi, işlemler daha az kod ile anlatıldığından daha kısa sürede işlemin bitmesi, yani programımız daha hızlı çalışması anlamına gelir.
Avantajları:
-          İşlemcinin gücünü en iyi şekilde ortaya koyabilen tek programlama dili
-          Az yer kapladığından malware yazılımında kullanılır.
-          Çok hızlı çalıştıklarından işletim sisteminin arka planında kernel ve donanım sürücülerin programlanmasında kısaca hız gerektiren kritik sistemlerin kodlanmasında kullanılır.
-          İyi bildiğiniz bir programlama dilde karşılaşılan büyük problemlerin basit assembly ile basit çözümleri olduğu görülür.
-          Her program derlendiğinde makine diline dönüşür. Bunlar assembly diline de dönüştürülebilir. Buna disassembly olayı denir bunu yapan programlar ise disassembler’lar dır.

Dezavantajları:
-          Dilin öğrenilmesi uzun zaman ve emek ister.
-          Yazılan programlar diğer diller göre daha çok satırdan oluşur.
-          İşlemciye birebir bağımlıdır. Yani işlemcisi intel olarak kodlanmışsa AMD işlemcilerde geçersizdir.       

Makine Dili: Bilgisayar işlemcisi (CPU) yalnızca makine dili ile yazılmış talimatları yerine getirebilir. Öte yandan programcıların makine dilini kullanarak kod yazmalarına gerek yoktur ve hatta karmaşık işler için çoğu zaman imkansızdır.
Assembly dili, makine dilinden kaynaklanan zorlukları gidermek için geliştirilmiş bir programlama dilidir. Assembly dilinde ikili (binary) sistem kullanarak program yazmak yerine kısa kelimelerden oluşan komutlardan (mnemonics) yararlanılmaktadır.
Assembly dili, makine dili ile kod yazmanın daha kolay ve anlaşılabilir kısa yoludur.

Assembly örnek kodu;
mov r0, #1
mov r1, #2
add r2,r1,r0

yukarıda verilen kodun yaptığı iş r0 ‘a 1 r1 2 ‘yi  atar son adımda ise r0 ve r1 in toplamlarını r2 ye yazmıştır.



Assembler:
Assembly dilinde yazılmış bir programı makine diline çeviren programa assembler denir.









Her cpu firamsının kendine özgü makine dili dolayısıyla assembly dili ve assember yazılımı vardır.




mov: bu komuttan bir yazmaçktan bir yazmaca kopyalama yapılabileceği gibi bir yazmaca sabit bir değer yazılabilir
ör:
mov    ah,5
moh    al,bh

birincisine ah yazmacina 5 yazilir. ikisinde ise bh yazmacindaki veri al yazmacina kopyalanır.
Mov komutuyla yanlizca esit kapasitedeki yazmaçlar arasinda kopyalama yapilabilir
yani sonu x ile bitenler arasinda veya sonu h veya i ile bitenler arasina kopyalama yapilabilir.


inv:
Bir yazmactaki degeri bir artirir.

inc   al

burada al in önceki degeri 5 sayarsak artik al nin degeri 6 olur.

mul:
Belirtilen yazmaçktaki degerle al yazmacindaki deger çarpilip sonuç ax yamacina konur.

mul   cl

burada al yazmacindaki degerle cl yazmacindaki deger çarpilip sonuç ax yazmacina konur.

add:
Herhangi bir yazmaçtaki degerle herhangi sabit bir deger veya yazmaçtaki degeri toplayip sonuç ilk belirtilen yazmacina koyulur.

add al,1
add al,cl

add    ax,cl    -> hatali bir kodtur çünkü esit kapasiteli degildir.

sub:
Herhangi bir yazmaçtan sabit bir degeri ya da baska bir yazmaçtaki degeri çikarir.

sub    al,10
sub    ax,cx

Birincisinde al yazmacindaki deger 10 eksilir. ikincisinde de ax yazmacindaki deger cx'teki deger kadar eksilir. sub komutu da tipki
add gibi esit kapasiteli yazmaçlar islme yapar.


loop: Komutun argümanindaki ofset adresi ile loop komutunun bulundugu satir arasinda cx in degeri kadar gidip gelinir.
yani bir döngü kurulmus olur.


örnek:

14f7:100 mov    cx,5
14f7:103 inc    al
14f7:105 add    dlial
14F7:107 loop   103
14F7:109 int    20

Burada 5 kere 103.ofset ile 107.ofsfset arasında gidip gelinir. Bütün yazmaçların ilk değerine 0 sayarsak sonuçta al’nin değeri 5.di’nin değeride f olur. Burada şunu gözden

Offset: Bir verinin bulundugu segmentten kac byte otede oldugunu soler. degiskenin offset degerini dondurur.


Cmp:
iki yazmaçtaki degeri ya da bir yazmakçtaki değerle sabit bir değeri kıyaslar. Tek başlarına bir işe yaramaz.

14F7:100 cmp   al,bl
14F7:102 cmp   bl,5
14F7:104 cmp   5,bl
14F7:106 cmp   ax,bl

Bu komutlardan ilk ikisi çalışacak. Son ikisiyse çalışmayacak. Çünkü üçüncüsüde ilk argüman sabit bir değer. Sonucunda farklı boyutlardaki yazmaçlar kıyaslanmış.

Jg,vjl, je, jge, jle:
Kendisinden hemen önce gelen cmp komutuna göre programın akışını belirli bir ofsete yönlendirirler.

Jg à büyüktür
Jl à küçüktür
Je à eşittir.
Jge à büyük eşittir.
Jle à küçük eşittir.

Ör
14f7:100 cmp    al,bl
14f7:102 jl          10e
Burada eğer al’deki değer bi den küçükse akış 10e offsetine yönlendirilecektir. Değilse program normal şekilde akışına devam edecektir. 



Jmp:
Belirli bir offsete atlamaya yarar.

PUSH ve POP komutları:
Push ve pop komutları stack memory (yığın hafıza bçlgesi) ile ilgili işlemler kullanılır. Yığın hafıza bölgesi bize .exe tipi program hazırlanırken. Stact dedektifi ile belirliyoruz işte bu bölge genellikle programdaki dallanma veya altrutinlerin çalışması sırasında, dönüş adreslerinin ve bayrak kaydedicisinin durumlarını saklamak için kullanılır.
Push komutu bu yığın olarak adlandırılan hafıza bölgesine verileri iterken, pop komutunda bu bölgeden veri almada kullanılır.  



LAHF ve SHAF Komutları:
Bu komutlar bayrakları AH kaydedicisine yükler veya AH’a yüklenen bayrak kaydedivilerinin durumlarını kayar nokta kaydedicisine (floating point register) yükler. Bu komutlar 8086 zamamında kalma ve günümüzde assembly programlarında pek kullanılmamakta.