对于家庭作业,我正在执行一系列缓冲区溢出攻击。我得到了一个程序来反汇编,C中的源代码用于不正确地调用gets()
的函数,以及我应该强制程序调用的其他几个函数的源代码。对于其中一项任务,我必须:
在确定返回的位置时,我不明白程序在堆栈中的位置。存储在堆栈中的方法的返回地址在哪里?
该程序是为x86编译的。
答案 0 :(得分:13)
您需要了解的内容:
调用函数时,参数然后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地址较低的地址较低)