Öncelikle, derlenmiş bir kod, bağlandığında ne değişir buna bakmak lazım.
Çalişabilen dosya disk üzerinde bazı section denilen bölümlerden oluşuyor. Örnek, .text genelde kod kısmı, .data data kısmı, .bss ilk değer verilmemiş statik nesneler, .stack stack filan.
İşte bir derlenmiş dosyada, içindeki kod veya verilerin kodun bağlanması esnasında nereye yazılacağı bellidir. .text den sonra gelenler, kod, .data dan sonra gelenler data bölümüne yazılmalıdır.
Senin yapman gereken de şu, öncelikle bir dosya da section sayısı kadar yer ayıracaksın. sonra bu yerlere, derlenmiş modüllerde bulunan dataları yazacaksın. Bu dataların adresleri elinde olmalı, örneğin derlenmiş modülde _main, _degisken, _asdf gibi bulunan tüm etiketler, bağlama aşamasında adrese çevirilecek. Tabi ki disk üzerinde adrese değil, belleğe genişletildikten sonraki adrese.
Bu noktada çalışabilen dosyanın başlık kısmını iyi bilmen gerekiyor. Burada örneğin .text bölümünün disk üzerinde nerden başlayıp nereye kadar olduğu ve belleğe yüklendiğinde hangi adreesten başlayıp ne kadar uzun olduğu yazıyor.
Özetle senin yapman gereken, tüm derlenmiş modüllerde data bölümündekileri, tek bir dosyada data bölümüne, kod bölümündekileri kod bölümüne, bss bölümündekileri bss bölümüne yazmak ve, etiket isimleri olarak görünen yerlere gerçek adresleri yazmak.
Tabi o datanın dosya içindeki yerinden bahsetmiyorum, belleğe yüklendikten sonraki adresinden bahsediyorum, bu adresi de demin söylediğim gibi başlık kısmı sayesinde öğrenebilirsin.
İşin belki de en zor kısmı şu, dinamik kütüphane fonksiyonlarına bağlanmak. Bu fonksiyonların adresi bağlama sırasında bilinmediğinden, bunun yerine örneğin .text tablosunun sonunda bir jmp table yaratılır, dinamik kütüphane içindeki fonksiyonun adresi yerine, bu jmp tabledeki bir elemanın adresi yazılır. Tabi ki belleğe yüklenirken bu jmp table de gerçek fonksiyon adresleri vardır. (biz aslında import tablosundan çekiyoruz atlayacağımız adresi, loader ise import tablosuna gerçek fonksiyon adreslerini yazdığından biz herhangi bir fonksiyona bu jmp table ile atlayabiliyoruz)
Örnek bir jmp table.
http://img530.imageshack.us/img530/6958/jmp.png
Fonksiyonların gerçek adresleri o sisteme özgü bir yöntemle alınır. Örneğin windows da
#include <stdio.h>
#include <windows.h>
int main(){
printf("\n%X",GetProcAddress(LoadLibrary("user32.dll"),"MessageBoxA"));
getchar();
return 0;
}
Bu kod ile tüm fonksiyonların adresini alabilirsiniz. Dahası, doğrudan adresi ile bu fonksiyonları çağıra da bilirsiniz, hiç jmp table yada import table olmadan, trojan yazarken çok işe yarar :) Tabi bu loaderin işi, fazla karışmayalım.
Özetle
- verilen derlenmiş modülerde, kod bölümündeki baytları, son dosyada kod bölümüne, data dakileri dataya vs. verilen sırada yaz.
- başlık kısmını ayarla ve hangi bölümün bellekte hangi adresten başlayıp kaç bayt uzunluğunda olduğunu belirle.
- bundan sonra, fonksiyon ve global nesne etiketleri yerine bu adresleri yerleştir.
- dinamik bağlanacak fonksiyonların isimlerini dosya da ayrı bir yere yaz (import table) bu yerin de adresini başlık kısmına yaz.
- kod kısmının sonunda, bir jmp tablosu oluştur ve her dinamik bağlantı için bir jmp olsun. Bu jmp lar import tablosundaki belli bir yerdeki adrese atlayacak ör: jmp [ds:1958] gibi, sonra bu ds:1958 kısmına tabiki işletim sistemi loaderi gerçek adresi yazacaktır.
Son olarak bir not. Daha önce ceviz de de bir kaç kez söylemiştim, çalışabilen dosya , aslında direkt main fonksiyonundan başlamaz. Derleyici kodundan başlar, ve derleyici kodunda sonlanır.
Peki bu kod nerden geliyor, nasıl bağlanıp bizim programımızın gerçek başlangıç noktası oluyor.
İşte bu derleyici kodu, genelde cr0.o , cr2.o ya da .obj gibi, derlenmiş ama bağlanmamış modüllerdir. Siz isteseniz de istemesenizde yazdığınız her porgramda, bağlayıcı aynı zamanda bu derlenmiş modülleri de sizin kodunuzla birlikte bağlar.
Tabi ld de başka bir fonksiyonu -e asd şeklinde giriş noktası belirleyebiliriz, kod içinde main fonksiyonu yoksa sorun olmaz, program gerçekten asd fonksiyonundan başlar, derleyici kodu eklenmez.
Özetle bunların hepsini düşünmek zorundasın ancak derleyiciden 10.000 kat daha kolay bir program olduğunu rahatlıkla söyleyebilirim.
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]