Risposte:
La protezione dello stack viene eseguita dal compilatore (aggiungi alcuni dati extra allo stack e metti da parte alcuni al momento della chiamata, controlla l'integrità al ritorno). Non è possibile disabilitarlo senza ricompilare. Fa parte del punto, davvero ...
Per espandere ciò che vonbrand ha detto (correttamente, +1), ci sono due parti nella protezione dello stack di Linux.
I canarini di stack sono la funzionalità applicata dal compilatore a cui vonbrand fa riferimento. Questi non possono essere disabilitati senza una ricompilazione.
Per provarlo e vedere come funzionano, prendi il seguente codice:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
int mybadfunction(char* a_bad_idea)
{
char what[100];
strcpy(what, a_bad_idea);
printf("You passed %s\n", what);
}
int main(int argc, char** argv)
{
printf("Tralalalaala\n");
mybadfunction(argv[1]);
}
Ora compila quello ( gcc -fstack-protector -masm=intel -S test.c
) in qualcosa di gnu come sarebbe felice di assemblare e leggere l'output. Il punto importante è che all'uscita dalla mybadfunction
funzione, c'è questo piccolo pezzo di codice:
mov edx, DWORD PTR [ebp-12]
xor edx, DWORD PTR gs:20
je .L2
call __stack_chk_fail
Come puoi immaginare, è prendere un cookie dello stack [ebp-12]
e confrontarlo con il valore a gs:20
. Non corrisponde? Quindi chiama una funzione __stack_chk_fail
in glibc che uccide il tuo programma proprio lì.
Esistono modi per aggirare questo problema in termini di scrittura di exploit, ma il modo più semplice in termini di creazione di un caso di test shellcode è compilare il programma -fno-stack-protector
.
Ci sono alcune altre considerazioni sui moderni sistemi Linux. Se prendi il solito stub di test shellcode:
char buffer[] = {...};
typedef void (* func)(void);
int main(int argc, char** argv)
{
func f = (func) buffer;
f();
return 0;
}
GCC / Linux moderno mapperà la .rodata
sezione del file PE in sola lettura senza permessi di esecuzione. Devi disattivarlo, cosa che puoi fare usando l'esempio di codice di questo post sul blog . Idea di base: utilizzate mprotect
per aggiungere le autorizzazioni desiderate alle pagine in cui risiedono i dati del codice shell.
Se hai intenzione di testare uno scenario di exploit tradizionale, ad esempio il mio codice errato sopra, con il tuo codice shell, devi anche assicurarti che lo stack sia eseguibile per i casi semplici. Il formato del file PE contiene un campo per determinare se lo stack è eseguibile: puoi eseguirlo e controllarlo con execstack . Per abilitare uno stack eseguibile, eseguire
execstack -s /path/to/myprog
Questo può essere fatto su programmi arbitrari senza la necessità di una ricompilazione, ma non disabiliterà automaticamente stack canarini poiché questi sono inseriti nella compilazione.
Per spegnerlo, echo 0 > /proc/sys/kernel/randomize_va_space
.
No. Qualsiasi exploit deve aggirare i canarini di stack (molto non banali) e trovare un programma con execstack
set, oppure impostarlo (nel senso che può già eseguire comandi arbitrari) oppure utilizzare tecniche più difficili, come il ritorno a libc / return programmazione orientata.
È possibile disabilitare alcune protezioni (rilevamento dello smashing dello stack e rendere eseguibile lo stack) con queste opzioni.
--z execstack
-f no-stack-protector
Puoi anche disattivare ASLR (randomizzazione del layout dello spazio degli indirizzi) con Bash con il comando:
echo 0 > /proc/sys/kernel/randomize_va_space