x86,32位中为什么要做栈平衡。

本文探讨了32位系统中通过栈进行参数传递的过程,并详细分析了正常函数调用与栈溢出调用的区别。重点介绍了如何在栈溢出的情况下实现正确的栈平衡,以确保程序的稳定运行。

在32位中是通过栈进行参数传递,正常函数的调用,栈中要先压入返回地址,再压入ebp。但通过溢出执行相关函数时,只压入ebp,并不压入返回地址,因此函数正常返回时,先后执行,leave,ret,就会多出栈一次,因此,需要做栈平衡

正常调用溢出调用
leave(mov esp,ebp;pop ebp)ebpebp
ret(pop eip)返回地址栈平衡
esp

通过代码调试代码如下:

#include <stdio.h>
int add(int a,int b,int c)
{
        int sum;
        sum=a+b+c;
}
void main()
{
// char t[32];
// scanf("%s",t);
//printf("%s\n",t);
int a=1,b=2,c=3;
int sum;
sum=add(1,2,3);
printf("sum=%d\n",sum);
}

gcc编译后,通过gdb调试

 EBP  0xffffd5bc —▸ 0xffffd5e8 ◂— 0x0
 ESP  0xffffd5bc —▸ 0xffffd5e8 ◂— 0x0
 EIP  0x804840e (add+3) ◂— sub    esp, 0x10
─────────────────────────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────────────────────────
   0x8048421 <add+22>    nop    
   0x8048422 <add+23>    leave  
   0x8048423 <add+24>    ret    
    ↓
   0x804840b <add>       push   ebp
   0x804840c <add+1>     mov    ebp, esp
 ► 0x804840e <add+3>     sub    esp, 0x10
   0x8048411 <add+6>     mov    edx, dword ptr [ebp + 8]
   0x8048414 <add+9>     mov    eax, dword ptr [ebp + 0xc]
   0x8048417 <add+12>    add    edx, eax
   0x8048419 <add+14>    mov    eax, dword ptr [ebp + 0x10]
   0x804841c <add+17>    add    eax, edx
──────────────────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────────────────
00:0000│ ebp esp  0xffffd5bc —▸ 0xffffd5e8 ◂— 0x0
01:0004│          0xffffd5c0 —▸ 0x8048455 (main+49) ◂— add    esp, 0xc
02:0008│          0xffffd5c4 ◂— 0x1
03:000c│          0xffffd5c8 ◂— 0x2
04:0010│          0xffffd5cc ◂— 0x3
05:0014│          0xffffd5d0 ◂— 0x1
06:0018│          0xffffd5d4 ◂— 0x2
07:001c│          0xffffd5d8 ◂— 0x3

进入add函数后,如上所示,add函数的地址为0x804840b,在栈中压入了,返回地址与ebp

00:0000│ ebp esp  0xffffd5bc —▸ 0xffffd5e8 ◂— 0x0
01:0004│          0xffffd5c0 —▸ 0x8048455 (main+49) ◂— add    esp, 0xc

修改栈顶为“aaaa”,返回地址为add函数的地址,在此次add函数结束后,再次调用add函数,如下所示:

00:0000│ ebp esp  0xffffd5bc —▸ 0x804b008 ◂— 'aaaa'
01:0004│          0xffffd5c0 —▸ 0x804840b (add) ◂— push   ebp
02:0008│          0xffffd5c4 ◂— 0x1
03:000c│          0xffffd5c8 ◂— 0x2
04:0010│          0xffffd5cc ◂— 0x3
05:0014│          0xffffd5d0 ◂— 0x1
06:0018│          0xffffd5d4 ◂— 0x2
07:001c│          0xffffd5d8 ◂— 0x3

等再次进入add函数如下所示,没有压入返回地址

EBP  0x804b008 ◂— 'aaaa'
 ESP  0xffffd5c4 ◂— 0x1
 EIP  0x804840b (add) ◂— push   ebp
─────────────────────────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────────────────────────
   0x804841c <add+17>    add    eax, edx
   0x804841e <add+19>    mov    dword ptr [ebp - 4], eax
   0x8048421 <add+22>    nop    
   0x8048422 <add+23>    leave  
   0x8048423 <add+24>    ret    
    ↓
 ► 0x804840b <add>       push   ebp
   0x804840c <add+1>     mov    ebp, esp
   0x804840e <add+3>     sub    esp, 0x10
   0x8048411 <add+6>     mov    edx, dword ptr [ebp + 8]
   0x8048414 <add+9>     mov    eax, dword ptr [ebp + 0xc]
   0x8048417 <add+12>    add    edx, eax
──────────────────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────────────────
00:0000│ esp  0xffffd5c4 ◂— 0x1
01:0004│      0xffffd5c8 ◂— 0x2
02:0008│      0xffffd5cc ◂— 0x3
03:000c│      0xffffd5d0 ◂— 0x1
04:0010│      0xffffd5d4 ◂— 0x2
05:0014│      0xffffd5d8 ◂— 0x3
06:0018│      0xffffd5dc —▸ 0x80484a1 (__libc_csu_init+33) ◂— lea    eax, [ebx - 0xf8]
07:001c│      0xffffd5e0 —▸ 0xf7fb43dc (__exit_funcs) —▸ 0xf7fb51e0 (initial) ◂— 0x0

继续执行,压入ebp

EBP  0xffffd5c0 —▸ 0x804b008 ◂— 'aaaa'
 ESP  0xffffd5c0 —▸ 0x804b008 ◂— 'aaaa'
 EIP  0x804840e (add+3) ◂— sub    esp, 0x10
─────────────────────────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────────────────────────
   0x8048421 <add+22>    nop    
   0x8048422 <add+23>    leave  
   0x8048423 <add+24>    ret    
    ↓
   0x804840b <add>       push   ebp
   0x804840c <add+1>     mov    ebp, esp
 ► 0x804840e <add+3>     sub    esp, 0x10
   0x8048411 <add+6>     mov    edx, dword ptr [ebp + 8]
   0x8048414 <add+9>     mov    eax, dword ptr [ebp + 0xc]
   0x8048417 <add+12>    add    edx, eax
   0x8048419 <add+14>    mov    eax, dword ptr [ebp + 0x10]
   0x804841c <add+17>    add    eax, edx
──────────────────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────────────────
00:0000│ ebp esp  0xffffd5c0 —▸ 0x804b008 ◂— 'aaaa'
stack
01:0004│          0xffffd5c4 ◂— 0x1
02:0008│          0xffffd5c8 ◂— 0x2
03:000c│          0xffffd5cc ◂— 0x3
04:0010│          0xffffd5d0 ◂— 0x1
05:0014│          0xffffd5d4 ◂— 0x2
06:0018│          0xffffd5d8 ◂— 0x3
07:001c│          0xffffd5dc —▸ 0x80484a1 (__libc_csu_init+33) ◂— lea    eax, [ebx - 0xf8]

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值