Suppongo che ci sia una cronologia, ma perché lo stack cresce al ribasso?
Mi sembra che un sovraccarico del buffer sarebbe un lotto più difficile da sfruttare se lo stack crescesse verso l'alto ...
I credo viene dai primissimi giorni dell'informatica, quando la memoria era molto limitata, e non era saggio pre-allocare una grossa porzione di memoria ad uso esclusivo dello stack. Quindi, allocando la memoria heap dall'indirizzo zero verso l'alto e impilando la memoria dalla fine della memoria verso il basso, è possibile che l'heap e lo stack condividano la stessa area di memoria.
Se avessi bisogno di un po 'più di heap, potresti stare attento con l'utilizzo dello stack; se avessi bisogno di più stack, potresti provare a liberare memoria heap. Il risultato è stato, ovviamente, soprattutto, arresti anomali spettacolari, poiché lo stack avrebbe sovrascritto occasionalmente l'heap e viceversa.
In quei giorni non c'erano interwebz, quindi non c'era alcun problema di sfruttamento eccessivo del buffer. (O almeno nella misura in cui esisteva l'interwebz, era tutto all'interno delle strutture di sicurezza del dipartimento di difesa degli Stati Uniti, quindi la possibilità di dati dannosi non aveva bisogno di essere presa in considerazione).
In seguito, con la maggior parte delle architetture si trattava solo di mantenere la compatibilità con le versioni precedenti della stessa architettura. Ecco perché gli stack sottosopra sono ancora con noi oggi.
la memoria di programma è tradizionalmente impostata come
code
constants
heap (growing up)
...
stack (growing down)
heap e stack possono essere scambiati
ma i buffer overflow possono ancora essere sfruttati se lo stack è andato nell'altro modo
prendendo come esempio il classico strcpy
foo(char* in){
char[100] buff;
strcpy(buff,in);
}
con memoria dello stack come
ret foo
arg in
buff array
ret strcpy
buf pointer
in
questo significherebbe che quando viene eseguita la copia l'indirizzo di ritorno per strcpy
è dopo il buffer (anziché l'indirizzo di ritorno di foo
) e può essere sovrascritto da qualsiasi cosa sia in in
Alcuni componenti hardware hanno l'heap che inizia con una memoria alta, che cresce a dismisura, mentre lo stack inizia con una memoria insufficiente.
L'hardware PA-RISC di HP, tra gli altri, fa questo: link
Il venerabile sistema operativo Multics funzionava su hardware che aveva (uno dei possibili) stack in crescita: vedi link , fine della sezione 2.3.2:
Third, stacks on the Multics processors grew in the positive direction, rather than the negative direction. This meant that if you actually accomplished a buffer overflow, you would be overwriting unused stack frames, rather than your own return pointer, making exploitation much more difficult.
Questa è una dichiarazione piuttosto interessante. I buffer overflow sono diventati un problema così grande solo a causa della procedura "consueta", chiamata call-stack-frame? Inoltre, quanto della reputazione di Multics come Totalmente Invulnerabile era solo un colpo di design dell'hardware?