Как использовать переполнение буфера для выполнения инструкций в стеке - PullRequest
4 голосов
/ 13 апреля 2019

Я начинаю возиться с переполнением буфера и написал следующую программу:

#include <unistd.h>

void g() {
  execve("/bin/sh", NULL, NULL);
}

void f() {
  long *return_address;
  char instructions[] = "\xb8\x01\x00\x00\x00\xcd\x80"; // exit(1)

  return_address = (long*) (&return_address + 2);
  *return_address = (long)&g; // or (long)instructions
}

int main() {
  f();
}

Она делает то, что от меня ожидают: return_address перезаписывает адрес возврата f с помощьюадрес g, который открывает оболочку.Однако, если я установил адрес возврата на instructions, я получил ошибку сегментации, и ни одна из инструкций в instructions не была выполнена.

Я компилирую с GCC, используя -fno-stack-protector.

Как можно предотвратить возникновение этой ошибки сегментации?

1 Ответ

2 голосов
/ 13 апреля 2019

По крайней мере одна проблема не связана с переполнением буфера.

execve("/bin/sh", NULL, NULL);

Этот первый NULL становится argv запускаемого вами процесса.argv должен быть массивом строк, который оканчивается значением NULL.Таким образом, segfault может произойти, когда /bin/sh запускается, пытается прочитать argv[0] и разыменовывает NULL.

void g(void) {
    char *argv[] = { "/bin/sh", NULL };
    execve(argv[0], argv, NULL);
}

Вы также можете добавить -z execstack в командную строку gcc, которая сообщит компоновщикуразрешить исполняемый стек.Вы также должны убедиться, что у вас есть инструкции, которые exit(1) компилирует в вашей системе, если вы получили их где-то из руководства.

...