缓冲区溢出期间EIP值不正确

时间:2012-06-20 07:35:37

标签: c 32bit-64bit buffer-overflow

我正在使用ubuntu 12.04和64位机器。我正在阅读一本关于缓冲区溢出的好书,在玩一个例子的时候发现了一个奇怪的时刻。

我有这个非常简单的C代码:

 void getInput (void){ 
    char array[8];    
    gets (array); 
    printf("%s\n", array); 

 }   
 main() { 
    getInput();    
    return 0;    
 }
文件overflow.c中的

我用32位标志编译它导致书中假设32位机器的所有例子,我这​​样做

 gcc -fno-stack-protector -g -m32 -o ./overflow ./overflow.c

在代码中,char数组只有8个字节,但是看看反汇编我发现该数组从堆栈上保存的EBP开始16个字节,所以我执行了这一行:

 printf "aaaaaaaaaaaaaaaaaaaa\x10\x10\x10\x20" | ./overflow

得到了:

 aaaaaaaaaaaaaaaaaaaa 
 Segmentation fault (core dumped)

然后我打开了核心文件:

 gdb ./overflow core
 #0  0x20101010 in ?? ()
 (gdb) info registers
 eax            0x19    25
 ecx            0xffffffff  -1
 edx            0xf77118b8  -143583048
 ebx            0xf770fff4  -143589388
 esp            0xffef6370  0xffef6370
 ebp            0x61616161  0x61616161
 esi            0x0 0
 edi            0x0 0
 eip            0x20101010  0x20101010

正如您所见,EIP实际上获得了我想要的新价值。但是,当我想放一些有用的值,如0x08048410

 printf "aaaaaaaaaaaaaaaaaaaa\x10\x84\x04\x08" | ./overflow

程序像往常一样崩溃但是当我试图观察EIP寄存器中的值时发生了一些奇怪的事情:

 #0  0xf765be1f in ?? () from /lib/i386-linux-gnu/libc.so.6
 (gdb) info registers
 eax            0x61616151  1633771857
 ecx            0xf77828c4  -143120188
 edx            0x1 1
 ebx            0xf7780ff4  -143126540
 esp            0xff92dffc  0xff92dffc
 ebp            0x61616161  0x61616161
 esi            0x0 0
 edi            0x0 0
 eip            0xf765be1f  0xf765be1f

突然EIP开始看起来像这个0xf765be1f,它看起来不像0x08048410。实际上我注意到,从0开始放置任何十六进制值就足以得到这个崩溃的EIP值。你知道为什么会这样吗?是因为我在64位机器上吗?

UPD

评论中的好人要求提供更多信息,这里是getInput函数的反汇编:

 (gdb) disas getInput
 Dump of assembler code for function getInput:
    0x08048404 <+0>:    push   %ebp
    0x08048405 <+1>:    mov    %esp,%ebp
    0x08048407 <+3>:    sub    $0x28,%esp
    0x0804840a <+6>:    lea    -0x10(%ebp),%eax
    0x0804840d <+9>:    mov    %eax,(%esp)
    0x08048410 <+12>:   call   0x8048310 <gets@plt>
    0x08048415 <+17>:   lea    -0x10(%ebp),%eax
    0x08048418 <+20>:   mov    %eax,(%esp)
    0x0804841b <+23>:   call   0x8048320 <puts@plt>
    0x08048420 <+28>:   leave  
    0x08048421 <+29>:   ret 

3 个答案:

答案 0 :(得分:3)

也许0x08048410处的代码已执行,并跳转到0xf765be1f区域。

这个地址是什么?我想这是一个函数(libC?),所以你可以检查它的汇编代码,看看它会做什么。

另请注意,在成功运行中,您设法超出了EBP,而不是EIP。 EBP包含0x61616161aaaa,EIP包含0x20101010\n\n\n。似乎腐败的EBP间接导致EIP腐败 尝试使溢出4个字节更长,然后它也应该超出返回地址。

答案 1 :(得分:1)

这可能是因为现代操作系统(Linux至少,我不知道Windows)和现代libc have mechanisms不允许执行堆栈中的代码执行。

答案 2 :(得分:0)

缓冲区溢出正在调用未定义的行为,因此任何事情都可能发生。理论化可能发生的事情是徒劳的。