Part 1: Tersinden Tersine Mühendisliğe Giriş


Selamlar.
Stajdı, Hacktrick'ti, okuldu falan derken uzun zamandır yazamadım kusura bakmayın. Hoş gerçi okuyucu kitlem falan da yok ama Google spider'larına ayıp olmasın diye arada yazıyorum birşeyler. Tabi birde öğrendiklerimi pekiştirmek maksadıyla yazıyorum

Üniversitenizde bilgisayar ile alakalı bir bölümde okumaya başladınız. 1 veya 2. sınıftasınız. Java idi, C# idi veya başka bir dil, hepsinin de cicili bicili yapıları önünüze hazır konmuş sizin kullanmanızı bekliyor. Alem buysa kral benim diye düşünüyor olabilirsiniz. Ama durun, dahası var!

İki yazıdan oluşmasını planladığım bu yazı dizisinde sizi, adını duyunca yüzünüzü buruşturduğunuz Assembly (hemide bold) gerçeğiyle yüzleştirmeyi amaçlıyorum

İlk yazıda Assembly'den ziyade daha çok giriş konseptinde konuları anlatıp kazığı sivrilteceğim :P
İkinci yazımda ise programlamada kullandığımız yapıların Assembly'deki karşılıklarını gösterip açıklamaya çalışacağım. Böylece Assembly'nin aslında ne kadar kazma bir dil olduğunu göreceksiniz.

Herneyse.. Let's go!

0x00: Registerlar

Herşeyden önce şayet ilk defa Assembly'e girişecekseniz sizi bu yazımı okumaya davet ediyorum. Böylece işlemcinin instruction cycle'ı hakkında basitçe bir fikriniz olur. Herneyse..

Öncelikle işlemcinin yapısına hızlıca bir göz atalım.

Şekil biraz kafanızı karıştırıyor olabilir. Aslında bakarsanız burada yazanların bazılarını ben de bilmiyorum :P
Şimdilik "General Registers", "Internal Registers" ve "Flag register" yazan kısımların üzerinde duracağız. Tabi önce registerların ne olduğundan bahsetsek daha iyi olacak.

Register'lar, işlemcinin içerisinde yer alan özel bellek alanlarıdır. 32-bit işlemcilerde bu registerların her birinin boyutu 32 bittir (surprise madafaka). Bu registerların her biri özel amaçlı verileri tutmada kullanılır. Direkt olarak işlemcinin içerisinde bulunduklarından bu registerlarda tutulan verilere erişim çok daha hızlı olmaktadır.

0x01: Register'ların yapısı

Google'dan bulup arakladığım şu görsel registerların yapısını en güzel şekilde size açıklayacaktır.

Günümüz 32-bit registerları - yanlış hatırlamıyorsam - Intel 8086 işlemcilerinde kullanılan 16-bit'lik registerların boyutunun 32-bit'e genişletilmiş halidir. Başlarındaki 'E' harfide "genişletilmiş" manasına gelen Extended kelimesinin kısaltmasıdır.

Görsel buradan alınmıştır.




 Bu görselde Registerları daha güzelce sınıflandırılmış bir şekilde görebiliyorsunuz. Şimdi bu registerların türlerini ve kendilerini inceleyelim.

0x02: Data Registers

Bu register sınıfında - 16 ve 8 bitlik alt kısımlarını saymazsak - 4 tane register bulunur; EAX, EBX, ECX ve EDX.

    EAX: Akümülatör - o da ne demekse artık - registeri. Genelde aritmetik işlemler sırasında sayıları depo etmek amacıyla kullanılır. Ayrıca syscall sırasında - ileride değineceğim - call id'yi tutan registerdır.
    EBX: Base registeri. Örneğin bir dizinin içerisinde iterasyon yapılacaksa dizinin başlangıç adresi bu registerda tutulur, dizinin elemanlarına EBX+1, EBX+2 vs.. şeklinde erişilir. Ayrıca syscall sırasında ilk parametreyi tutan registerdır.
    ECX: Counter registeri. Isminden anlaşılacağı üzere döngü işlemlerinde sayaç olarak kullanılır. Ayrıca syscall sırasında -varsa- 2. parametreyi tutar.
    EDX: Data registeri. I/O işlemlerinde kullanılır. Ayrıca syscall sırasında -varsa- 3. parametreyi tutar.

0x03: Pointer Registers

İsmine münhasır bir şekilde bu register sınıfında işaretçi türünde registerlar bulunur.

    EBP & ESP: Bu iki register, programın ve fonksiyonların stack frame'inin adreslerini tutarlar. EBP, stack'in taban -base- adresini, ESP ise tavan -stack- adresini tutar. İlerde hafıza yapıları konusundan bahsettiğimde bu registerların işlevini daha iyi anlayacağınızı umuyorum..
    EIP: Instruction pointer adıyla bilinen bu register, code segmentinde çalıştırılacak olan bir sonraki yönergenin adresini tutar. Bazı memory corruption zafiyetlerinde bu registerın içindeki değer dolaylı yoldan değiştirilerek programın akışı isteğe göre şekillendirilebilir.

0x04: Index Registers

    ESI & EDI: Source Index ve Destination Index registerları bazı string fonksiyonları tarafından kaynak ve hedef işaretçisi olarak kullanılırlar.

0x05: Ek olarak EFLAGS Registeri

Özel bir register olan EFLAGS registerının her bir bit'i ayrı bir flag'i temsil eder. Google'dan arakladığım diğer bir görselde bütün bu flag'lerin bit pozisyonlarını görebilirsiniz.


Bu flaglerden mühim gördüğüm birkaç tanesinin işlevini belirtmek istiyorum.

    Interrupt Enable Flag (IF): Bu flag kernel'in INTR'lara yanıt verip vermeyeceğini belirler. Eğer bit'in değeri 1 ise kernel INTR'lara yanıt verir.
    Trap Flag (TF): Eğer bu bit'in değeri 1 olursa işlemci instruction'ları single-step mod da çalıştırmaya başlar. Debuggerlar tarafından programı adım adım çalıştırmak için kullanılan bir flagdir.
    Carry Flag (CF): Bir aritmetik işlem sonucunda elde kalan bir değer varmı onu öğrenmek için kullanılır. Örneğin bir sayı tek mi çift mi anlamak için önce sayı bir adım sağa kaydırılır, şayet sayı tek ise sayının son biti 1 olacağından bir adım sağa kaydırıldığında elde 1 kalacaktır ve CF aktif olacaktır. Bu ve buna benzer kullanımları vardır.
    Parity Flag (PF): Bir binary sayının içindeki 1'lerin sayısı çift ise bu bit 1 değerini alır.
    Zero Flag (ZF): Bir aritmetik işlemin sonucu 0 ise bu bit 1 değerini alır. Karşılaştırma işlemleri için sıkça kullanılır.
   

0x10: Memory Layout of a Process

Bunu sağlıklı bir şekilde Türkçe'ye çevirmeye benim İngilizcem ye(t)medi :P Çevirebilecek bir arkadaş varsa yoruma yazsın önerilere açığım. Şimdi bir programı çalıştırdığımızda hafızada nasıl gözüküyor onu inceleyelim.

0x11: Masaüstünde Durduğu gibi Durmuyor!

Başka bir görselle yazımıza devam ediyoruz.

Bir programın hafızadaki görünümü tam olarakta bu şekildedir. Her biri ayrı renk ile renklendirilmiş segmentlerden her birini inceleyelim bakalım.

0x12: Text Segment a.k.a. Code Segment

Text segment, veya diğer adıyla Code segment hafızada program kodlarının bulunduğu alandır. Tabi bu kodların makine kodu olduğunu belirtmekte fayda var. Genellikle Read-Only olarak işaretlidir.

0x13: Data Segment

Data segment bizim program içerisinde kullandığımız sabitler için idealdir.
int i = 300;
char text[] = "Merhaba Dunya!";

Yukarıdaki iki değişken de Data segmenti içerisinde depolanır. Bu segmentin boyutu programın derlenmesi sırasında derleyici tarafından belirlenir ve çalışma esnasında bir daha değişmez. Bu değişkenlerin değeri program içerisinde sonradan değiştirilebileceği için Data segmenti Read-Write olarak işaretlidir.

0x14: BSS Segment

Bu segmentte değeri henüz belirlenmemiş olan static değişkenler yer alır. Değeri belirlenene kadar bu alanın içerisi 0'lar ile doludur yani bir nevi boştur. Bu tür değişkenlerin değeri ise programın çalışma sırasında belirlenir.
static int i;

0x20: Asagı Tükürsen Heap, Yukarı Tükürsen Stack

Bir önceki başlıkta bir programın çalıştırıldığında hafızada ne şekil aldığını gördük. Orada atladığım iki segment'i ayrı bir başlıkta anlatmak istiyorum zira bunlar bizim en güzide segmentlerimiz oluyor. 
Değeri sabit olan değişkenler için data segmentini kullanan programlarımız, diğer türlü değişkenler için iki adet veri yapısından faydalanırlar; Stack ve Linked-List. E Heap bunun neresinde demeyin çünkü Heap'in sadece adı Heap, yani Heap'in veri yapısı olan Heap ile bir alakası olmamakla beraber kendisi aslında bir bağlantılı liste yapısındadır. Peki bunlara neden ihtiyaç duyulmuş? Onu da hemen anlatayım...

0x21: Stack Region

Stack bölgesi, adından mütevellit, verilerin üst üste yığılacağı bir hafıza alanından başka birşey değildir. Bu hafıza alanını üst üste istif edilmiş bir tabak yığını gibi düşünün. Tek yapabileceğiniz bu yığının üzerine bir tabak daha koymak (push) veya bu yığının en tepesindeki tabağı kaldırmak (pop) olacaktır. Stack'in çalışma mantığı da tam anlamıyla bu şekildedir. Ve stack'in boyutu, içerisinde bulunan verilerin toplamı (yani yığındaki tabak sayısı) kadardır.
Pekii bu hafıza alanı nerede yer alıyor? Register'lar başlığına bir saniyeliğine geri dönelim. Orada stack çerçevesinin (yani o fonksiyonun kullandığı stack alanının) taban ve tavan adreslerini tutan EBP & ESP registerlarından söz etmiştik. İşte stack alanının yerini tam olarakta bu register'lar belirler.
Fonksiyonun başlangıcında stack'in taban adresi belirlenir ve EBP registerinda tutulur. Ardından ESP nin değeri EBP'ye eşitlenir (stack içerisinde henüz hiç veri olmadığından bu alanın boyutu 0 olacaktır, dolayısıyla EBP ve ESP aynı adresi gösterecektir). Ardından o fonksiyonun sahip olduğu lokal değişkenlerin boyutlarının toplamı ESP'nin tuttuğu adresten çıkarılarak stack çerçevesi oluşturulmuş olacaktır.

örn:
void myfunction( void ) {
int sayi;
char text[20]; 
}

Yukarıdaki fonksiyonun sahip olduğu lokal değişkenler için stack'ten; sizeof(sayi) + sizeof(text), yani 4 + 20 = 24 byte alan ayırılmış olacaktır.
Gördüğünüz üzere Stack alanının boyutu fonksiyon başlangıcında belli olur ve programın çalışma süresince bir daha değişmez.

Stack alanınıda bu şekilde açıkladıktan sonra geçelim sıradaki segmente; Heap.

0x22: Heap Region

Yazılımcıların "Bu dinamik boyutlu değişkenler nerede duracaklar??!" isyanından kısa bir süre sonra Heap alanı kullanılmaya başlandı ve yazılımcılar belli fonksiyonlar aracılığıyla program çalışırken bellekten yer ayırabilmeye başladılar. Bu da değişken boyutlu değişkenlerin (hö?) kullanılabilmesine olanak sağladı.

malloc(), calloc(), realloc(), free(). Bu fonksiyonlar size tanıdık geliyorsa muhtemelen bir zamanlar kabuslarıma giren C'de dinamik bellek yönetimi konusuyla haşır neşir oldunuz.
Heap basitçe, bağlantılı liste yapısında bulunan birkaç dizi hafıza bloklarından ibarettir. Siz malloc veya türevi bir fonksiyon ile bellekten yer ayırdığınızda bu hafıza bloklarından o anda müsait olanları size tahsis edilir. Sizde böylece programın istediğiniz yerinde, istediğiniz miktarda hafıza alanını kullanabilirsiniz.

Part 1'in sonuna geldik. "aga ben şunu anlamadım" dediğiniz birşey varsa Google'da araştırın benana. Yazımın size bir faydası olursa ne ala. Part 2'yi ne zaman yazarım onuda bilmiyorum. Hayırlısı bu işler..

Herneyse, kalın sağlıcakla.

Yorumlar

Yorum Gönder

Bu blogdaki popüler yayınlar

DKHOS - Rev300 Çözümü

Bir Güvenlikçi, Virüs ile Karşılaşırsa