You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86二进制ROP攻击栈未对齐问题:为何添加4字节padding才生效?

问题解释:ROP调用system时的栈结构问题

你遇到的核心问题是x86 cdecl调用约定下,直接跳转函数与call指令的栈结构差异,和栈对齐无关,具体拆解如下:

1. 直接跳转system时的栈要求

正常用call system调用函数时,CPU会自动把下一条指令的地址(返回地址)压入栈,再跳转到system。此时system内部的栈结构是:

[参数]
[返回地址]  <-- ESP指向这里(call执行后)

system函数执行第一步会做栈帧初始化:

push ebp
mov ebp, esp

之后它会通过ebp+8获取第一个参数(ebp+4是返回地址,ebp是旧栈基址)。

但你是通过ROP直接覆盖EIP为system_addr,相当于直接跳转到system,没有经过call指令,CPU不会自动压入返回地址,此时栈的结构完全由你的payload决定。

2. 第一个payload的问题

第一个payload构造后,栈在EIP被覆盖后的结构是:

[44字节填充]
system_addr  <-- EIP指向这里
bincat_addr  <-- ESP指向这里(CPU跳转到system时)

当system执行栈帧初始化后,ebp等于当前ESP(即bincat_addr的地址),此时:

  • ebp+4 = bincat_addr(被system当成返回地址)
  • ebp+8 = 栈中bincat_addr之后的内容(超出payload范围,是无效内存)

system会尝试读取ebp+8作为第一个参数,访问无效地址导致程序崩溃。

3. 第二个payload为什么生效

添加4字节padding后,栈结构变成:

[44字节填充]
system_addr  <-- EIP指向这里
CCCC         <-- ESP指向这里(跳转后)
bincat_addr

system执行栈帧初始化后:

  • ebp+4 = CCCC(被当成返回地址,虽然无效,但system执行完cat操作后才会跳转到这里,不影响我们要的核心操作)
  • ebp+8 = bincat_addr(正好是我们要传的参数)

此时system能正确拿到/bin/cat flag.txt的地址作为参数,执行后完成命令,即使最后跳转到CCCC崩溃也无关紧要。

为什么你之前的理解错误

你以为会执行system("CCCC"),是混淆了ESP指向的内容和函数参数的位置。system的第一个参数不是ESP指向的内容,而是ebp+8——也就是返回地址占位的4字节之后的内容,所以CCCC只是占了返回地址的位置,真正的参数是后面的bincat_addr。

内容的提问来源于stack exchange,提问作者IRP_HANDLER

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 22:32:35