Мой код переполнения не работает - PullRequest
2 голосов
/ 06 декабря 2011

Код ниже взят из известной статьи Уничтожение стека ради удовольствия и прибыли .

void function(int a, int b, int c) {
  char buffer1[5];
  char buffer2[10];
  int *ret;
  ret = buffer1 + 12;
  (*ret)+=8;
}

void main() {
  int x;
  x=0;
  function(1,2,3);
  x=1;
  printf("%d\n",x);
}

Я думаю, что должен объяснить свою цель этого кода.Модель стека приведена ниже.Число под словом - это количество байтов переменной в стеке.Итак, если я хочу переписать RET, чтобы пропустить нужный мне оператор, я вычисляю смещение от buffer1 до RET 8 + 4 = 12.Поскольку архитектура Linux x86.

buffer2 buffer1 BSP RET   a    b    c
(12)    (8)     (4) (4)   (4)  (4)  (4)

Я хочу пропустить оператор x=1; и разрешить printf() выводить 0 на экране.

Я компилирую код с помощью:

gcc  stack2.c  -g

и запустить его в GDB:

gdb ./a.out

GDB дает мне такой результат:

Program received signal SIGSEGV, Segmentation fault.
main () at stack2.c:17
17  x = 1;

Я думаю, что Linux использует какой-то механизм для защиты отпереполнение стека.Может быть, Linux хранит адрес RET в другом месте и сравнивает адрес RET в стеке, прежде чем функции возвращаются.

А как обстоят дела с механизмом?Как мне переписать код, чтобы программа вывела 0?

ОК, код дизассемблирования приведен ниже. Он поставляется с вывода gdb, так как я думаю, что его легче читать. И любой можетподскажите, как вставить длинную последовательность кода? Копирование и вставка по очереди приводит к усталости ...

Dump of assembler code for function main:
0x08048402 <+0>:    push   %ebp
0x08048403 <+1>:    mov    %esp,%ebp
0x08048405 <+3>:    sub    $0x10,%esp
0x08048408 <+6>:    movl   $0x0,-0x4(%ebp)
0x0804840f <+13>:   movl   $0x3,0x8(%esp)
0x08048417 <+21>:   movl   $0x2,0x4(%esp)
0x0804841f <+29>:   movl   $0x1,(%esp)
0x08048426 <+36>:   call   0x80483e4 <function>
0x0804842b <+41>:   movl   $0x1,-0x4(%ebp)
0x08048432 <+48>:   mov    $0x8048520,%eax
0x08048437 <+53>:   mov    -0x4(%ebp),%edx
0x0804843a <+56>:   mov    %edx,0x4(%esp)
0x0804843e <+60>:   mov    %eax,(%esp)
0x08048441 <+63>:   call   0x804831c <printf@plt>
0x08048446 <+68>:   mov    $0x0,%eax
0x0804844b <+73>:   leave
0x0804844c <+74>:   ret


Dump of assembler code for function function:
0x080483e4 <+0>:    push   %ebp
0x080483e5 <+1>:    mov    %esp,%ebp
0x080483e7 <+3>:    sub    $0x14,%esp
0x080483ea <+6>:    lea    -0x9(%ebp),%eax
0x080483ed <+9>:    add    $0x3,%eax
0x080483f0 <+12>:   mov    %eax,-0x4(%ebp)
0x080483f3 <+15>:   mov    -0x4(%ebp),%eax
0x080483f6 <+18>:   mov    (%eax),%eax
0x080483f8 <+20>:   lea    0x8(%eax),%edx
0x080483fb <+23>:   mov    -0x4(%ebp),%eax
0x080483fe <+26>:   mov    %edx,(%eax)
0x08048400 <+28>:   leave
0x08048401 <+29>:   ret

Я проверяю код сборки и нахожу ошибку в моей программе, и я переписал *От 1032 * до (*ret)+=7, поскольку 0x08048432 <+48> минус 0x0804842b <+41> равно 7.

Ответы [ 3 ]

2 голосов
/ 06 декабря 2011

Поскольку эта статья написана в 1996 году, а допущения неверны.

См. "Разрушение современного стека ради удовольствия и прибыли"

http://www.ethicalhacker.net/content/view/122/24/

Изссылка выше:

Однако компилятор GNU C (gcc) развился с 1998 года, и в результате многие люди задаются вопросом, почему они не могут заставить примеры работать на них, илиесли они действительно заставляют код работать, почему они должны были сделать изменения, которые они сделали.

0 голосов
/ 06 декабря 2011

Попробуйте ret = buffer1 + 3;

Объяснение: ret - целочисленный указатель; увеличение его на 1 добавляет 4 байта к адресу на 32-битных машинах.

0 голосов
/ 06 декабря 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...