Laboratuvarlar / uygulama
"Bir bellek alanının izin değişimini gözlemlemek"
Anonim belleği RW’den RX’e geçir. İzin değişiminin neyi kanıtladığını gör.
Bu laboratuvar, anonim bir bellek eşlemesinin yazılabilir (RW) durumdan çalıştırılabilir (RX) duruma geçişini (W^X prensibinin dinamik ihlali) inceler. Örnek bilerek bellekte kod çalıştırmaz; böylece bir bellek alanına çalıştırma izni verilmiş olmasının, orada kesinlikle kod yürütüldüğü anlamına gelmediğini somut olarak kanıtlar.
1. Ön Koşullar ve Hazırlık#
Laboratuvar için standart bir Linux sistemi, GCC veya Clang derleyicisi ve strace aracı gereklidir.
Geçici bir çalışma klasöründe izin.c dosyasını oluşturun:
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
int main(void) {
long page = sysconf(_SC_PAGESIZE);
if (page <= 0) return 1;
size_t size = (size_t)page;
// 1. Anonim bellek ayır (Yazılabilir ve Okunabilir: RW)
void *area = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (area == MAP_FAILED) { perror("mmap"); return 1; }
// Belleğe bayt yaz (RW iznini sına)
((unsigned char *)area)[0] = 0x90; // NOP baytı
printf("pid=%ld area=%p size=%zu (Durum: RW)\n", (long)getpid(), area, size);
fflush(stdout);
// /proc/<pid>/maps dosyasını incelemek için 5 saniye bekle
sleep(5);
// 2. Bellek izinlerini Okunabilir ve Çalıştırılabilir (RX) yap
if (mprotect(area, size, PROT_READ | PROT_EXEC) == -1) {
perror("mprotect");
munmap(area, size);
return 1;
}
puts("Izin mprotect ile RX oldu; bu alanda hic kod calistirilmiyor!");
fflush(stdout);
// maps dosyasındaki değişimi incelemek için 5 saniye daha bekle
sleep(5);
// 3. Belleği serbest bırak
if (munmap(area, size) == -1) { perror("munmap"); return 1; }
return 0;
}
2. Derleme ve Sistem Çağrılarını İzleme (strace)#
Programı hata ayıklama sembolleriyle derleyin ve sistem çağrılarını filtreleyerek çalıştırın:
gcc -Wall -Wextra -O0 -g izin.c -o izin
strace -e trace=mmap,mprotect,munmap ./izin
Beklenen strace çıktısı:
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa289c00000
pid=25410 area=0x7fa289c00000 size=4096 (Durum: RW)
mprotect(0x7fa289c00000, 4096, PROT_READ|PROT_EXEC) = 0
Izin mprotect ile RX oldu; bu alanda hic kod calistirilmiyor!
munmap(0x7fa289c00000, 4096) = 0
+++ exited with 0 +++
[!NOTE] Dinamik bağlayıcının (
ld-linux.so) program başlarken kütüphaneleri yüklemek için yaptığı dahilimmapvemprotectçağrıları da çıktıda görünecektir. Programın kendi yazdırdığıareaadresiyle eşleşen satırlara odaklanın.
3. İkinci Bir Terminalden /proc/PID/maps Gözlemi#
Program sleep(5) aşamasındayken ikinci bir terminal açarak yazdırılan PID numarasıyla bellek haritasını kontrol edin:
İlk 5 Saniyede (RW Aşaması):#
grep "7fa289c00000" /proc/25410/maps
Çıktı:
7fa289c00000-7fa289c01000 rw-p 00000000 00:00 0 [anon]
Sonraki 5 Saniyede (mprotect Sonrası RX Aşaması):#
grep "7fa289c00000" /proc/25410/maps
Çıktı:
7fa289c00000-7fa289c01000 r-xp 00000000 00:00 0 [anon]
Sayfa izinleri rw-p durumundan r-xp durumuna geçmiştir. Dosya yolu alanında hiçbir dosya adı bulunmamakta ([anon]) yani sayfa tamamen bellekte oluşturulmuş bir çalıştırılabilir kod sayfası görüntüsü sergilemektedir.
4. Analiz ve Hipotez Doğrulama#
Bu deney neyi kanıtlamıştır?
- İzin Değişimi != Kod Yürütme: Hedef alanda hiçbir makine komutu çalıştırılmamıştır (
RIPyazmacı bu alana hiç yönlendirilmemiştir). Bu nedenle yalnızca bir sayfanınr-xpolduğunu görmek "bellek içi zararlı kod çalıştı" sonucuna varmak için yetersizdir. - eBPF ve Perf ile Doğrulama:
perf record -e cyclesile izleme yapıldığında bu adrese ait hiçbir donanımsal örnek (sample) düşmez. - Güvenlik Politikası (W^X / PaX / SELinux): Bazı kurumsal Linux dağıtımlarında anonim bir belleğe
PROT_EXECverilmesi çekirdek güvenlik politikaları (SELinuxexecmem) tarafından engellenebilir vemprotectişlemiEPERMveyaEACCEShatasıyla başarısız olabilir.
İncelemeyi Derinleştir#
Bellek izinlerini değiştiren özel yükleyicilerin ve paketleyicilerin çalışma mimarisini öğrenmek için Özel yükleyiciler rehberine geçin. Dinamik kütüphane fonksiyonlarının çağrı hedeflerini LD_PRELOAD ile değiştirmeyi denemek için Sembol seçimi laboratuvarı uygulamasına geçin.