Contents

[汇编pwn基础]栈帧的学习

栈帧

栈帧:

  • 栈帧是一块因函数运行而临时开辟的空间。

  • 每调用一次函数便会创建一个独立栈帧

  • 栈帧中存放的是函数中的必要信息,如局部变量函数传参返回值等。

  • 当函数运行完毕栈帧将会销毁。

栈帧的创建

先看一个汇编的main函数头部

00611800  push        ebp  ;把ebp压入(保存ebp)
00611801  mov         ebp,esp  ;ebp=esp
00611803  sub         esp,0D8h  ;开栈(这片空间拿来放局部变量)
00611809  push        ebx  
0061180A  push        esi  
0061180B  push        edi  
0061180C  lea         edi,[ebp-18h]  ;EDI=ebp-18
0061180F  mov         ecx,6  ;重复次数
00611814  mov         eax,0CCCCCCCCh  ;eax=0xccccc
00611819  rep stos    dword ptr es:[edi]  ;重复以上指令,edi减小4;循环ecx次,eax放入edi中

局部变量放在开栈的区域 https://s2.loli.net/2023/08/27/xRfrldWpj98H5Ma.png 这个为上面函数的步骤 这边引用一下其他大哥的GIF https://s2.loli.net/2023/08/27/2aBSxKAPXGWd6jZ.gif 可以很清晰的看到过程 32位是通过栈来传参 64位是通过寄存器传参 函数返回时会销毁栈帧并复原栈

00A81835  pop         edi  
00A81836  pop         esi  
00A81837  pop         ebx  
00A81845  mov         esp,ebp  ;恢复原来的栈
00A81847  pop         ebp  
00A81848  ret  ;相当于pop eip

https://s2.loli.net/2023/08/27/tK5gOplr3dmvf8G.png 顺便附上一张调用栈的图 https://s2.loli.net/2023/08/27/oRZzTgqs6wO4AyJ.png

我们继续看 函数参数的传递

int sub(int a,int b) {
    return a - b;
}
int main()
{
    int a=1;
    int b = 123;
    sub(a, b);
    return 0;
}

我们可以看到sub 汇编代码为

00AC1E70  push        ebp  
00AC1E71  mov         ebp,esp  
00AC1E73  sub         esp,0C0h  
00AC1E79  push        ebx  
00AC1E7A  push        esi  
00AC1E7B  push        edi  
00AC1E7C  mov         edi,ebp  
00AC1E7E  xor         ecx,ecx  
00AC1E80  mov         eax,0CCCCCCCCh  
00AC1E85  rep stos    dword ptr es:[edi]  ;这边同上面main函数一样是创建栈帧开辟空间
00AC1E87  mov         ecx,offset _F767AB1E_ASMtest@cpp (0ACC066h)  
00AC1E8C  call        @__CheckForDebuggerJustMyCode@4 (0AC130Ch)  
00AC1E91  mov         eax,dword ptr [a]  ;这边直接是VS的原因 应该是ebp-08h
00AC1E94  sub         eax,dword ptr [b]