Data Execution Prevention (DEP)¶
DEP/NX, data page'lerini (stack, heap) non-executable işaretler; control flow bu page'lerden enjekte edilmiş shellcode'u çalıştırmaya kalkarsa CPU fault üretir — yani W^X'i enforce eder.
Mechanism¶
Bug class / invariant
DEP, W^X ("write XOR execute") invariant'ını enforce eder: bir page ya writable ya da executable olabilir, ama ikisi birden olamaz. CPU'nun page başına tuttuğu NX/XD bit'i data bölgelerini (stack, heap, code olmayan çoğu mapping) non-executable işaretler. Bozulmuş bir control-flow transfer'i execution'ı böyle bir bölgeye yönlendirirse — klasik "shellcode'u stack/heap'e enjekte et ve oraya jump et" saldırısı — processor bir fault üretir ve OS process'i öldürür. DEP böylece doğrudan code injection'ı etkisiz hale getirir. Tam da bu varlığı, attacker'ları enjekte edilmiş byte'lar yerine mevcut executable code'u çalıştıran code-reuse tekniklerine (ROP/JOP) itmiştir.
Donanım seviyesinde bu, page-table entry'sindeki bir bit'tir; vendor'lar aynı özelliği
farklı adlandırır: AMD NX (No-eXecute), Intel XD (eXecute Disable), ARM XN
(eXecute Never) ve MIPS XI (eXecute Inhibit). x86-64'te (long mode / PAE paging)
bu, page-table entry'sinin en anlamlı bit'i olan bit 63'tür: 0 ise page executable,
1 ise o page'den yapılan instruction fetch'ler fault'lar. Microsoft bunu userspace'e
DEP olarak sunar (Windows XP SP2'den beri default), Linux/BSD'ler ise CPU NX sunduğu
her yerde eşdeğer non-executable stack/heap mapping'lerini zorunlu kılar.
Walkthrough¶
Üst seviye, kavramsal (iyi belgelenmiş platform davranışı):
- OS, data page'lerini (stack/heap) NX set edilmiş olarak map'ler; yalnızca meşru code section'ları executable'dır.
- Bir memory-corruption bug'ı, attacker'ın bir data buffer'a shellcode yazmasına ve instruction pointer'ı ona doğru hijack etmesine izin verir.
- CPU bir NX page'ten execute etmeye çalışır.
- Bir no-execute fault üretilir; OS process'i sonlandırır — enjekte edilen shellcode asla çalışmaz.
- Bypass için attacker'lar code-reuse'a geçer: mevcut executable gadget'ları zincirler
(return-oriented programming) ya da bir page'i
executable yapmak için ROP üzerinden
VirtualProtect/mprotectçağırır (VirtualProtect/mprotect via ROP).
Bir Linux binary'sinin stack'inin NX-protected olup olmadığını GNU_STACK program
header'ından kontrol edebilirsin (RWE executable, RW NX-protected demektir):
Beklenen çıktı (NX-protected stack)
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
RW (RWE değil) flag'i kernel'e stack'i execute permission'ı olmadan map etmesini
söyler. gcc -z execstack ile derlenen bir binary RWE gösterir ve eski
enjekte-shellcode saldırı yüzeyini yeniden tanıtır.
Warning
DEP tek başına ROP/JOP'u ya da data-only saldırıları durdurmaz. Etkili olması için forward/backward-edge CFI ve ASLR ile birlikte kullanılmalıdır.
Detection¶
- Data page'lerinde no-execute / access-violation crash'leri — untrusted-input işleme sırasında tekrarlayan DEP fault'ları code-injection denemelerine işaret eder.
- WER / Exploit Protection event'leri; DEP-enabled process'lerde EDR crash telemetry'si.
- Page'leri RX'e çeviren şüpheli runtime
VirtualProtect/mprotectçağrıları (yaygın bir DEP-bypass belirtisi), özellikle JIT olmayan process'lerden.
Mitigation¶
- DEP/NX'in system-wide ve process başına enabled olduğundan emin ol (modern OS'lerde default'tur; legacy app'ler için opt-out'tan kaçın).
- ASLR, Control Flow Guard ve CET shadow stacks ile birleştir.
- RWX mapping'lerini minimize et; executable bellek'in dinamik olarak oluşturulmasını/değiştirilmesini yasaklamak için Arbitrary Code Guard kullan.