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