Quando aggiungi l'argomento /gs
al compilatore di microsoft, inserisce una copia di args sotto la variabile buffer.
Quindi, qual è il punto di tenere una copia di arg?
L'opzione / GS è una protezione euristica contro l'overflow del buffer: alcuni tipi di buffer trabocca e solo se trabocca nel "solito modo". Visual C suppone che qualsiasi variabile che "appare come una matrice" possa essere soggetta a un trattamento di tipo array e, quindi, possibilmente esagerare. Vuole rilevare se si è verificato un overflow e farlo prima di tornare dalla funzione, perché i buffer overflow tradizionali cercano di sovrascrivere indirizzo di ritorno . Per rilevare tale occorrenza, il compilatore scrive un valore "cookie" tra la variabile potenzialmente overflow e l'indirizzo di ritorno; e il codice controlla che il cookie sia ancora lì quando sta per uscire dalla funzione.
Il compilatore lo farà per tutte le "variabili locali" e gli argomenti sono tali variabili locali. Il sistema di rilevamento funziona solo fino a quando il cookie si trova tra l'indirizzo di ritorno e la variabile , quindi questo può implicare lo spostamento delle cose, che è ciò di cui parli.
Considera questo:
struct foo { int a; int b; int c; int d; };
void f(struct foo arg)
{
char buf[20];
// ...
}
In questa funzione, sia buf
che arg
sono considerati "array-like" ( arg
è considerato array-like perché è maggiore di 8 byte). Ricorda che quando si passa una struct
a una funzione C (la struct
stessa, non un puntatore a una struct
), allora la funzione riceve una copia della struttura con cui giocare. In pila, troverai cose come questa:
buf
return address
arg
(aumento degli indirizzi nell'ordine dall'alto verso il basso, lo stack x86 cresce verso indirizzi bassi, quindi "su" nello schema sopra).
Il codice "/ GS" vorrà aggiungere un cookie e mettere quel cookie tra qualsiasi variabile di tipo array e l'indirizzo di ritorno. Poiché i byte oltre (sotto) l'indirizzo di ritorno appartengono al chiamante, la funzione non può giocare con loro quanto vorrebbe, quindi deve fare il suo lavoro nello spazio di stack libero. Pertanto, il codice vorrà questo:
buf
arg (copy of the received structure)
cookie
return address
arg (structure passed as parameter by the caller)
Ciò comporta la copia della struttura arg
al momento dell'inserimento della funzione. Dato che la struttura è, semanticamente, già una copia, che la funzione può giocare a piacere, la copia non cambia il comportamento osservabile della funzione. Con questa copia, qualsiasi overflow "normale" su arg
colpirà il cookie prima che sovrascriva l'indirizzo di ritorno, e quindi sarà (si spera) rilevato quando la funzione termina.
Devo naturalmente sottolineare che tale protezione è efficace solo se tutte le seguenti affermazioni sono vere:
Quindi non dovresti dare troppo credito all'efficacia di un sistema del genere.
Leggi altre domande sui tag windows compiler buffer-overflow