ARM Assembly Diline Giriş

Temmuz 22, 2018

ARM Exploit geliştirmeye başlamadan önce, biraz arka plan bilgisi gerektiren Assembly dili programlamasının temellerini anlamaya ihtiyacımız var. Şimdi kafamızda şöyle bir soru olabilir: Neden ARM Assembly dilini öğrenmeye ihtiyacımız var, exploitlerimizi python vb. normal bir programlama dilinde yazmak yeterli değil mi? Tersine mühendislik yapmak istiyorsak ve ARM binary program akışlarını anlamak istiyorsak, kendi ARM kabuk kodumuzu oluşturmak, ARM ROP zincirlerini oluşturmak ve ARM uygulamalarında hata ayıklamak istiyorsak, ARM Assembly dilini bilmemiz gerekiyor. Tersine Mühendislik yapmak ve exploit geliştirmek için Assembly dilinin her küçük detayını bilmeniz gerekmiyor, bunun bir kısmı daha büyük resmi anlamak için gereklidir. Bu eğitim dizisinde temel bilgiler ele alınacaktır. Daha fazla bilgi edinmek isterseniz, bu yazımın sonunda paylaştığım linkleri ziyaret ederek daha detaylı öğrenebilirsiniz.

Assembly dili, makine kodunun üzerinde, bilgisayarlarımızın anladığı ikili gösterimlerle (makine kodu) kodlanmış talimatlardan oluşan ince bir sözdizim katmanıdır. Böyle bir dil varsa neden sadece makine kodunda program yazmıyoruz diye sorabilirsiniz. Makine dilinde kod yazmak gerçekten zahmetli ve takip edilmesi zordur. Bu sebeple, insanların anlayabilmesi için çok daha kolay olan ARM Assembly dili kullanıyoruz. Bilgisayarımız makine koduna ihtiyaç duyduğundan, Assembly kodunu kendi başına çalıştıramaz. Assembly kodunu makine koduna bağlamak için kullanacağımız araç, *.s uzantısına sahip kaynak dosyalar ile çalışan “as” adlı GNU Binutils isimli GNU Assembler’dır. Derleme dosyanızı *.s uzantısıyla yazdıktan sonra, ld ile bağlantı kurup bağlamanız gerekiyor, aşağıda bunu nasıl yapacağımıza ilişkin komutları görebilirsiniz:

$ as program.s -o program.o

$ ld program.o -o program

En düşük seviyede, elektrik sinyallerini devrelerin içerisinde tutarız. Sinyaller, elektrik voltajını iki seviyeden birine geçirerek oluşturulur, örneğin 0 volt (kapalı) veya 5 volt (açık). Bu sinyaller, 0 ve 1 ikili sistemin rakamlarıdır. Daha sonra bir bilgisayar işlemcisinin en küçük çalışma birimi olan bir makine kodu talimatı oluşturmak için 0 ve 1 sırasını gruplandırırız. Böylelikle makine dili oluşur.

0011 1001 1110 0010 0000 1100 0110 0001 0011 …….

Yukarıda verdiğim 0 ve 1’lerden oluşan bu komut dizilerinin her birinin ne anlama geldiğini hatırlayamayız. Bu nedenle, her bir makine kodu talimatının bir isim verildiği bu ikili kalıpları hatırlamamıza yardımcı olacak kısaltmalar kullanıyoruz. Bu anımsatmalar genellikle üç harfden oluşur, ancak her zaman üç harften oluşacak diye bir zorunluluk bulunmamaktadır. Bu anımsatıcıları (mnemonic) kullanarak bir program yazabiliriz. Bu program bir Assembly dili programı olarak adlandırılır ve bilgisayarın makine kodunu temsil etmek için kullanılan anımsatma kümesine bu bilgisayarın Assembly dili denir. Bu nedenle, Assembly dili, bir bilgisayar programlamak için insanlar tarafından kullanılan en düşük düzeydir. Bunu aşağıdaki bir örnekle açıklayabiliriz.

1110 0001 1010 0000 0010 0000 0000 0001 ==> MOV R2, R1

Artık bir Assembly programının mnemonik (mnemonic) olarak adlandırılan metinsel bilgilerden oluştuğunu biliyoruz, onu makine koduna dönüştürmemiz gerekiyor. Yukarıda belirttiğim gibi, (ARM) Assembly dilinden (ARM) makine koduna dönüştürmek için GNU Binutils ile bize “as” adı verilen bu aracı kullanacağız.

1) Örnek Program : Sayı Ekleme

Basit bir örnek kullanarak ilk programımızı yazmaya başlayalım. Sayıları 1’den 10’a eklemek istediğimizi düşünelim. Bunu aşağıdaki şekilde C kodu kullanarak yapabiliriz.

     int total;
     int i;

     total = 0;
     for (i = 10; i > 0; i--) {
     total += i;
     }

Yukarıdaki C kodu derlediğimiz ARM’ın anlayacağı ARM Assembly koduna çevirdiğimizde aşağıdaki gibi bir komut seti oluşur.

          MOV R0, #0          ; R0 Toplamı Biriktirir
          MOV R1, #10         ; R1, 10'dan 1'e kadar sayar
Tekrar    ADD R0, R0, R1
          SUBS R1, R1, #1
          BNE Tekrar
Dur       B Dur               ; sonsuz döngüdeki hesaplamayı durdurmak için yazılan komut

Assembly dili programında yukarıdaki gibi R0 ve R1 ifadelerini görüyoruz. Bunlar, hesaplama sırasında veri depolamak için bir işlemcide bulunan kayıtlar için referanslardır. ARM işlemcisi, R0 ile R15 arasında numaralandırılmış 16 kolay erişilebilir yazmacı içerir. Her biri tek bir 32 bitlik sayı depolama kapasitesine sahiptir. Şimdi bugün öğrendiklerimizi toparlayacak olursak, neden assembly diline ihtiyacımız olduğunu ve bilgisayarların neden bu dili kullandığını anladık. Basit bir sayı ekleme assembly programının nasıl yazıldığını inceledik. (ARM) Assembly dilinden (ARM) makine koduna dönüştürmek için GNU Binutils ile bize “as” adı verilen bu aracın varlığından kullanımından bahsettik. Daha detaylı bilgiler için aşağıda paylaştığım web sitelerini ziyaret ederek öğrenebilirsiniz.

1. Whirlwind Tour of ARM Assembly.
https://www.coranac.com/tonc/text/asm.htm

2. ARM assembler in Raspberry Pi.
http://thinkingeek.com/arm-assembler-raspberry-pi/

3. ARM Reference Manual.
http://infocenter.arm.com/help/topic/com.arm.doc.dui0068b/index.html

4. Assembler User Guide.
http://www.keil.com/support/man/docs/armasm/default.htm

Yazı Etiketleri:
·
Yazı Kategorileri:
ARM · Eğitimler · Endüstriyel Siber Güvenlik

Yorumunuz

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

5846 Sayılı Fikir ve Sanat Eserleri Kanunu gereğince içeriğin kopyalanması yasaktır.
1 Paylaşımlar
Paylaş1
Paylaş
Tweetle
+1