Ci sono diversi problemi nel codice:
Il primo è che il target username è più corto del source msg e che quindi un lungo msg può causare un overflow di username . Ma dato il codice questo si traduce solo nel fluire in msg , cioè nessun arresto.
Più interessante è la seguente parte:
int i;
...
i = read(STDIN_FILENO, msg, sizeof(msg)-1);
memcpy( username, msg+2, i-2);
Se int i è 0 o 1, ciò causerà i-2 come ultimo argomento di memcpy da essere negativo (ad esempio -2 o -1). Poiché il tipo dell'ultimo argomento è size_t , che di solito non è firmato, questo valore con segno negativo verrà trattato come un valore senza segno enorme. In effetti, il codice diventa su piattaforme con 64 bit size_t quando i è 1:
memcpy(username, msg+2, 0xffffffffffffffff)
In questo modo la copia raggiungerà rapidamente le aree di memoria che non appartengono al processo in modo che si verifichi un errore di segmentazione.
I valori necessari per i possono essere raggiunti semplicemente chiudendo l'input ( i=0 ) o fornendo esattamente un byte di input ( i=1 , cioè senza nuove righe aggiuntive o simili) con, ad esempio,
echo -n "u" | ./crashme