Я припускаю, що тут є історія, але чому стек зростає вниз?
Мені здається, що переповнення буфера було б набагато важче експлуатувати, якби стек виріс вгору ...
Я припускаю, що тут є історія, але чому стек зростає вниз?
Мені здається, що переповнення буфера було б набагато важче експлуатувати, якби стек виріс вгору ...
Відповіді:
Я вважаю, що це відбувається з перших днів обчислень, коли пам'ять була дуже обмеженою, і не було розумно заздалегідь виділяти великий шматок пам'яті для виключного використання стеком. Таким чином, розподіляючи пам'ять купи від нульової адреси вгору і стекуючи пам'ять з кінця пам'яті вниз, ви могли б і купу, і стек розділяти одну і ту ж область пам'яті.
Якщо вам знадобилося трохи більше купи, ви можете бути обережними з використанням стеку; якщо вам знадобиться більше стека, ви можете спробувати звільнити деяку купу пам’яті. Результатом, звичайно, були вражаючі збої, оскільки стек час від часу перезаписує купу та навпаки.
Ще в ті часи не було інтервебз, тому не було питання про експлуатацію буфера. (Або принаймні настільки, що існувало інтервебз, все це знаходилось в об'єктах високої безпеки Міністерства оборони Сполучених Штатів, тому про можливість зловмисних даних не потрібно було думати багато.)
Після цього для більшості архітектур було вирішено підтримувати сумісність із попередніми версіями тієї ж архітектури. Тому перевернуті стеки все ще є з нами сьогодні.
пам'ять програми традиційно встановлюється як
code
constants
heap (growing up)
...
stack (growing down)
купу і стек можна обміняти
але переповнення буфера все ще можна експлуатувати, якщо стек пішов іншим шляхом
беручи класичний strcpy
за приклад
foo(char* in){
char[100] buff;
strcpy(buff,in);
}
з стеком пам'яті як
ret foo
arg in
buff array
ret strcpy
buf pointer
in
це означало б, що коли копіювання завершено, повернення для адреси strcpy
знаходиться після буфера (замість foo
зворотної адреси) і може бути перезаписане тим, що знаходиться вin
Деяке обладнання має купу, починаючи з високої пам'яті, зростаючи, в той час як стек починається з низьким обсягом пам’яті.
Програмне забезпечення HP-PA-RISC, зокрема, робить це: http://www.embeddedrelated.com/usenet/embedded/show/68749-1.php
Поважна операційна система Multics працювала на апаратному забезпеченні, яке виростало (один із можливо багатьох) стеків: див. Http://www.acsac.org/2002/papers/classic-multics.pdf , кінець розділу 2.3.2:
По-третє, стеки на процесорах Multics зростали в позитивному, а не в негативному напрямку. Це означало, що якщо ви фактично виконали переповнення буфера, ви замінювали б невикористані кадри стека, а не власний покажчик повернення, що ускладнює експлуатацію значно складніше.
Це досить цікаве твердження. Чи переповнення буфера стали такою величезною проблемою лише через "звичну" процедуру "call-stack-frame"? Крім того, наскільки репутація Multics як "Повністю невразливої" була лише тріском апаратного дизайну?