PWN菜鸡入门之函数调用栈与栈溢出的联系

一、函数调用栈过程总结

Fig 1. 函数调用发生和结束时调用栈的变化

Fig 2. 将被调用函数的参数压入栈内

Fig 3. 将被调用函数的返回地址压入栈内

Fig 4. 将调用函数的基地址(ebp)压入栈内,并将当前栈顶地址传到 ebp 寄存器内

Fig 5. 将被调用函数的局部变量压入栈内

二、函数调用栈实例说明

首先我们来看看以下程序调用栈的过程:

int sum(int a,int b)
{
    int temp = 0;
    temp = a+b;
    return temp;
}
int main()
{
    int a = 10;
    int b = 20;
    int ret = 0;
    ret = sum(a,b);
    cout<<ret<<endl;
​
    return 0;
}

如下调用过程:

每个函数在调用前都会做一件事情。

(1)把调用方的ebp入到自己的栈里去

(2)用esp指向新的栈顶位置,把esp的值赋给ebp,产生新的ebp

(3)开辟空间,初始0XCCCCCCCC。 ebp入栈,实参入栈,形参入栈,调用call指令。call有两步,把下一行指令的地址入栈,跳转到调用的函数执行。形参内存主调方开辟,主调方释放。

main函数栈帧

开辟sum函数栈帧

sum函数内存布局

 

三、函数调用栈在栈溢出中的难点

栈溢出的shellcode中经常会出现:

payload : padding1 + address of shellcode + padding2 + shellcode

payload: padding1 + address of system() + padding2 + address of “/bin/sh”

这几种payload,很多教程对于padding2这个没有解释的很清楚,ctf wiki上是这样说的 :“如果是正常调用 system 函数,我们调用的时候会有一个对应的返回地址

因为不用考虑相应的getshell的结束,我们可以从之前的介绍得知这是main函数调用后的下一条指令的地址,也就是return完system后我们将要继续执行的指令,也就是说如果我们还想继续调用的话这个padding2可以放下一个要执行的地址。

猜你喜欢

转载自www.cnblogs.com/pwn2web/p/10349971.html