Tersine mühendislik sadece bir programın nasıl çalıştığını anlamakla ilgili değildir; bir sistemin güvenlik açıklarını ve altında yatan mantığı ortaya çıkarma sanatıdır. Çoğu geliştirici yalnızca yazılımın kaynak kodu düzeyinde nasıl çalıştığıyla ilgilenir, ancak gerçek bir sistem mühendisinin derleyicinin bu kodu nasıl optimize ettiğini de anlaması gerekir.
Neden Assembly Öğrenmeliyiz?
Derleyiciler, üst düzey kodumuzu makine diline çevirirken sayısız optimizasyon gerçekleştirir. Bu katmanı anlamadan, güvenli yazılım geliştirmek veya analiz etmek neredeyse imkansızdır. Bir fonksiyon çağrıldığında yığın işaretçisi (SP) ve taban işaretçisi (BP) bellekte nasıl hareket eder? Argümanlar yazmaçlara (RDI, RSI, RDX…) nasıl yerleştirilir?
Ghidra ile İlk Adımlar
NSA tarafından açık kaynaklı hale getirilen Ghidra, statik analiz için gerçekten güçlü bir araçtır. Bir .exe veya .elf dosyasını Ghidra'ya yüklediğinizde, sadece makine kodunu parçalamakla kalmaz, aynı zamanda C'ye benzeyen bir çıktı üreten oldukça yetenekli bir decompiler (geri derleyici) sunar.
// Example of a simple password-check mechanism decompiled by Ghidra
int check_password(char* input) {
if (strcmp(input, "super_secret_key") == 0) {
return 1;
}
return 0;
}Yukarıdaki kodu assembly seviyesinde incelersek, strcmp çağrısından hemen önce bir CMP ve bir JNZ (Jump If Not Zero) komutu görürüz. Tersine mühendislikte yazılımı manipüle etmek, genellikle o "JNZ" komutunu "JZ (Jump If Zero)" ile değiştirmek kadar basit bir işleme indirgenir.
Sonuç Yerine
Sistem düzeyinde düşünmek sizi sıradan bir programcıdan bir sistem mimarına dönüştürür. Belleğin nasıl tahsis edildiğini ve işlemcinin komutları nasıl yürüttüğünü anlamak, bence her yazılım geliştiricisinin arka cebinde bulunması gereken bir beceridir.