如何使用缓冲区溢出攻击替换堆栈上的返回地址

时间:2012-11-01 08:03:25

标签: assembly x86 buffer-overflow

对于家庭作业,我正在执行一系列缓冲区溢出攻击。我得到了一个程序来反汇编,C中的源代码用于不正确地调用gets()的函数,以及我应该强制程序调用的其他几个函数的源代码。对于其中一项任务,我必须:

  • 注入一些更改值的代码,然后
  • 返回上述方法之一

在确定返回的位置时,我不明白程序在堆栈中的位置。存储在堆栈中的方法的返回地址在哪里?

该程序是为x86编译的。

1 个答案:

答案 0 :(得分:13)

您需要了解的内容:

  • EIP是一个指向下一条执行指令的寄存器。
  • 调用函数时,参数然后EIP(所以被调用函数知道返回的位置)保存在堆栈中。

  • 当编译器被告知(显式或隐式)使用帧指针时,它会将帧指针(在EBP寄存器中)保存在堆栈上(因此它可以稍后将帧指针恢复为值)在调用函数上),然后将帧指针设置为指向堆栈的当前顶部。这允许从已知的参考点(帧指针)轻松访问参数和局部变量,并大大简化调试。

  • 然后,为局部变量保留空间,并执行该函数。
  • 从函数返回时,前一帧指针和指令指针将被恢复。

x86上的函数调用类似于:

                                        ...
int main()                              add  $-0x8,%esp ; alignment
{                                       push $0x2       ; arg 2
        ...                             push $0x1       ; arg 1
        func(1, 2);                     call func       ; function call
        ...                             add  $0x10,%esp ; pop args from stack
}                                       ...

被调用的函数看起来像:

void func(int arg1, int arg2)           push %ebp       ;\
{                                       mov  %esp,%ebp  ;/ create stack frame
        int local1;                     sub  $0x18,%esp ; reserves space
        ...                             ...
}                                       mov  %ebp,%esp  ;\
                                        pop  %ebp       ;/ destroys frame
                                        ret             ; returns

因此,堆栈看起来类似于:

          :           :
          +-----------+
          : alignment :
          +-----------+
12(%ebp)  |   arg2    |
          +-----------+
 8(%ebp)  |   arg1    |
          +-----------+
 4(%ebp)  |    ret    | -----> return address
          +-----------+
  (%ebp)  |    ebp    | -----> previous ebp
          +-----------+
-4(%ebp)  |  local1   | -----> local vars
          +-----------+
          : alignment :
          +-----------+
          :           :

(ASCII地址较低的地址较低)