Как переполнения буфера используются для эксплуатации компьютеров? - PullRequest
19 голосов
/ 20 января 2009

Как переполнения буфера используются для эксплуатации компьютеров?

Как можно выполнить произвольный код, просто вызвав переполнение stack или heap ?

Я понимаю, что части памяти программ перезаписываются, что не должно быть, но я не понимаю, как это приводит к тому, что кто-то выполняет свой собственный код. Кроме того, должен ли злонамеренный код сторонних разработчиков быть написан на языке ассемблера целевых процессоров?

Ответы [ 5 ]

16 голосов
/ 20 января 2009

Это наиболее широко известный документ по этому вопросу: Разбивая стек ради удовольствия и прибыли

Однако «переполнение стека» не имеет ничего общего с переполнением буфера. Переполнение стека, как правило, является просто ошибкой в ​​плохом коде, который не может быть использован ни для чего, кроме сбоя (DoS).

Редактировать: Вы также спрашивали о переполнении кучи. Это хороший документ на эту тему: http://www.w00w00.org/files/articles/heaptut.txt

8 голосов
/ 20 января 2009

Стек содержит как данные, так и адрес возврата при переходе в подпрограмму. Если вам удастся поместить конкретный адрес в стек, где находится адрес возврата, вы можете заставить ЦП перейти в определенную область памяти, куда вы положили свой собственный код. Это для переполнения буфера. Переполнение кучи немного отличается и его сложнее использовать.

Переполнения стека являются просто признаком того, что вы исчерпали пространство стека (которое обычно более ограничено, особенно в ядре).

7 голосов
/ 20 января 2009

Представьте себе два дома на улице. Один - это дом твоего друга, а другой - дом его злого параноика, соседа, на три двери вниз. Злой параноидальный сосед никогда не входит и не уходит, и его место плотно заперто.

Теперь, ваш друг такой хороший, доверчивый друг, что он позволит вам хранить что угодно на своем месте, ставя коробки один за другим, начиная с одной стены. На самом деле, он такой хороший друг, что будет продолжать класть ящики один за другим, не проверяя, ударился ли он о стену, пока они не продолжат идти в воздухе и, наконец, пройдут прямо через два других дома на улице и в дом злого параноика соседа. Но твой друг верит, что ты не будешь этого делать, потому что ты ему нравишься (и он немного наивен).

Таким образом, у вас есть возможность положить что-то в дом злого параноидального соседа, используя своего доброго доверчивого друга.


Замените следующие термины, и вы увидите аналогию с атакой переполнения буфера:

  • "дом вашего друга" -> "часть программы, которая не проверяет переполнение буфера"
  • "Дом его злого параноидального соседа" -> "другая часть программы, которая должна быть безопасной"
  • «коробки» -> «аргументы / параметры для программы, которая не проверяет переполнение буфера»

Это успешно, только если кто-то выяснит, где находится безопасная область памяти, и что нужно будет передать в качестве аргумента рассматриваемой программе, которая в конечном итоге окажется в безопасной области, чтобы получить желаемый эффект. (будь то данные или код, вызывающий выполнение кода эксплуататора)

5 голосов
/ 20 января 2009

Практически все современные процессоры при вызове подпрограммы возвращают адрес возврата в ту же область, что и локальные данные (стек). Для подпрограмм, которые не проверяют верхний предел переменной (в частности, функцию strcpy), может произойти перенаправление адреса инструкции (переполнение буфера).

void make(char *me)
{
    char sandwich[4]; // local data, this is in stack.  the buffer for data is too small
    strcpy(sandwich, me);
    puts(sandwich);

    // implicit "return;" the return instruction(RET on Intel) instructs the processor to implicitly pop an address from stack then resume execution on that address
}

void main()
{
    // calling a subroutine (CALL on Intel) implicitly instructs the processor to push the next instruction's address(getchar line) on stack before jumping to make.
    make("Love Not War"); 
    getchar();

    puts("This will not execute.  The address to next instruction(getchar) gets overwritten with Not War");

}

"Кроме того, должен ли злонамеренный код стороннего разработчика быть написан на языке ассемблера целевых процессоров?" Да

Переполнение стека может произойти из нормально работающей программы, например, рекурсивные подпрограммы (функция, которая вызывает себя) с пропущенным завершающим условием. Область стека будет заполнена многочисленными локальными переменными в стеке плюс возвращаемые адреса.

1 голос
/ 20 января 2009

Обычный подход заключается в том, что у вас есть где-то в памяти вредоносный код. Затем вы создаете переполнение буфера: волшебство здесь состоит не в том, чтобы просто переполнить его, а в том, что вы уже упоминали, что некоторые части памяти программы перезаписываются. Так как в стеке содержатся не только переменные, но также и когда функция называется адресом возврата, вы пытаетесь перезаписать ее адресом вашего вредоносного кода. Когда функция с переполнением буфера возвращается к своему вызывающему, функция не возвращается к своему исходному вызывающему, а вместо этого к вредоносной подпрограмме. Поскольку теперь исполняемый код обычно имеет привилегии вызывающего кода, каждый пытается найти / создать это переполнение в коде, который имеет более высокое разрешение, чем злой код (иначе вы можете сделать это, напрямую вызвав злую подпрограмму).

...