Один пример того, как ошибка может создать возможность для эксплойта:
Допустим, у вас есть подпрограмма в программе, которая изменяет данные в виде массива символов. Допустим, он также содержит ошибку, заключающуюся в том, что когда массив имеет определенный размер или массив содержит определенные символы, подпрограмма непреднамеренно записывает после конца массива символов.
Само по себе это не кажется большой возможностью, но в зависимости от того, как выполнение достигает подпрограммы и других артефактов того, как оно реализовано и скомпилировано, оно может использоваться в качестве плацдарма для выполнения произвольного кода.
В традиционном программировании (C, C ++) символьные массивы (буферы) часто хранятся в программном стеке. Стек очень быстрый и простой в распределении памяти для небольших временных данных.
Другая вещь, которая хранится в стеке, это адрес возврата вызова функции - какой кодовый адрес возвращать при выходе из этой функции.
Теперь у вас есть все части, необходимые для создания катастрофы: если вы можете передать только правильные данные в эту подпрограмму, чтобы она перезаписывала стек, и перезаписывала его настолько, чтобы перезаписать адрес возврата функции, который также находится в стеке недалеко из буфера данных, у вас есть возможность изменить, куда вернется выполнение программы при выходе из функции. Вместо того, чтобы возвращаться к вызывающей стороне, можно было бы сделать так, чтобы она «возвращалась» (действительно, переход) в Halt () или Format () или PhoneHome (). Любая функция в любой библиотеке или DLL, на которую ссылается текущий процесс, доступна в данный момент.
Это всего лишь один из примеров произвольного выполнения эксплойта. Есть десятки таких моделей.
Самый простой способ помешать этому конкретному эксплойту - убедиться, что ваш код соблюдает границы ваших буферов данных. Для большинства компиляторов это означает включение проверки диапазона или аналогичных проверок во время выполнения. Компилятор выдаст код для проверки того, что значение индекса массива находится в диапазоне, прежде чем получить доступ к ячейке памяти в массиве.