我正在 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 实际上获得了我想要的新值(value)。但是当我想输入一些有用的值时,例如 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

最佳答案

可能是执行了 0x08048410 处的代码,跳转到了 0xf765be1f 区域。

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

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

关于c - 缓冲区溢出期间 EIP 值不正确,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11114863/

10-11 04:29