Per espandere ciò che ha detto vonbrand (correttamente, +1), ci sono due parti nella protezione dello stack di Linux.
Impila canarini
I canary dello stack sono la funzionalità applicata dal compilatore a cui fa riferimento vonbrand. Questi non possono essere disabilitati senza una ricompilazione.
Per dimostrarlo a te stesso 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 questo (gcc -fstack-protector -masm=intel -S test.c
) in qualcosa di gnu che sarebbe felice di assemblare e leggere l'output. Il punto importante è quello in uscita dal mybadfunction
function, 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, si tratta di prendere uno stack cookie da [ebp-12]
e confrontandolo con il valore in gs:20
. Non corrisponde? Quindi chiama una funzione __stack_chk_fail
in glibc che uccide il tuo programma proprio lì.
Ci sono modi per ovviare a questo in termini di scrittura di exploit, ma il modo più semplice in termini di creazione di un test case shellcode è compilare il programma con -fno-stack-protector
.
Pagine non eseguibili
Ci sono alcune altre considerazioni sui moderni sistemi Linux. Se prendi il solito stub di test dello shellcode:
char buffer[] = {...};
typedef void (* func)(void);
int main(int argc, char** argv)
{
func f = (func) buffer;
f();
return 0;
}
il moderno GCC/Linux mapperà il .rodata
sezione del file PE di sola lettura senza autorizzazioni di esecuzione. Devi disattivarlo, operazione che può essere eseguita utilizzando l'esempio di codice di questo post del blog. Idea di base:usi mprotect
per aggiungere i permessi desiderati alle pagine in cui risiedono i dati dello shellcode.
Stack non eseguibili
Se hai intenzione di testare uno scenario di exploit tradizionale, ad es. il mio cattivo codice sopra, con il tuo shellcode 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 interrogarlo e controllarlo con execstack. Per abilitare uno stack eseguibile, esegui
execstack -s /path/to/myprog
Questo può essere fatto su programmi arbitrari senza bisogno di una ricompilazione, ma non disabiliterà automaticamente i canary dello stack in quanto questi vengono integrati durante la compilazione.
Bonus aggiunto:aslr:
Per disattivarlo, echo 0 > /proc/sys/kernel/randomize_va_space
.
Hai appena detto a qualcuno come sfruttare il mio prezioso pinguino?
No. Qualsiasi exploit deve aggirare i canary dello stack (molto non banali) e trovare un programma con execstack
set, o set it (il che significa che può già eseguire comunque comandi arbitrari) oppure utilizzare tecniche più difficili, come il ritorno alla programmazione orientata al ritorno a libc/return.
La protezione dello stack viene eseguita dal compilatore (aggiungi alcuni dati extra allo stack e nascondine alcuni su chiamata, controlla la sanità mentale al ritorno). Non è possibile disabilitarlo senza ricompilare. Fa parte del punto, davvero...