4

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

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

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

该程序是为 x86 编译的。

4

1 回答 1

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-art 上较低)

于 2012-11-01T09:43:18.153 回答