NX - Non Executable

NX, che sta per "Non-executable data", è una mitigazione presente su molti processori moderni, e previene l'esecuzione di regioni di memoria su cui ci sono scritti dei dati come se fossero codice eseguibile. Infatti, una delle tecniche più usate per sfruttare ad esempio un buffer overflow sullo stack era quella di scrivere del codice macchina all'interno del buffer, e scrivere l'indirizzo dello stack corrispondente all'inizio nel valore di ritorno.

Quando la funzione eseguiva l'istruzione ret, il processore saltava all'interno dello stack, eseguendo proprio le istruzioni che erano state inserite dall'utente. Infatti, il processore non ha nessun modo di discernere da quello che è codice e dati, perché entrambi sono memorizzati in RAM.

Grazie al supporto hardware del processore e del gestore della memoria, è possibile marcare le pagine di memoria virtuale con dei permessi, in particolare permessi di lettura, scrittura ed esecuzione. Se il processore prova a eseguire delle istruzioni da una memoria che non ha permessi di esecuzione, emetterà una eccezione, che risulterà molto probabilmente in un segmentation fault. Il codice viene mappato con i permessi di lettura e di esecuzione, mentre i segmenti che contengono dati, come lo stack e lo heap, vengono mappati con permessi di lettura e scrittura, ma non di esecuzione. In particolare, l'esempio sopra non potrà più funzionare, perché quando il processore proverà a eseguire la prima istruzione sullo stack, lancerà una eccezione.

Questa mitigazione può essere aggirata tramite una tecnica che si chiama Return Oriented Programming (ROP), che si basa sul non eseguire direttamente codice arbitrario, ma utilizzare "gadgets" già esistenti all'interno del binario e concatenarli per ottenere esecuzione di codice arbitrario.