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

为何POP寄存器操作会改变IP指针?ROP技术相关疑问

理解POP指令如何改变ROP中的代码流差异

咱们一步一步拆解这两个场景的执行流程,就能搞清楚为什么pop ax会改变代码走向了:

正常call + ret的执行逻辑

当你在main里执行call func时,CPU会做两件事:

  1. 把当前EIP寄存器里的下一条指令地址(也就是call执行完后本该回到的位置)压入栈中;
  2. 把EIP的值改成func的地址,跳转到func执行。

进入func后只执行ret指令,ret的作用很直接:把栈顶的数值弹出到EIP里。这时候栈顶正好是刚才call压入的返回地址,所以EIP会被设置回原地址,程序就正常回到main继续执行了。

带pop ax的ROP场景执行逻辑

再看你调试的这个ROP示例:

  1. 先执行push 0x44:把0x44压入栈,此时栈指针ESP指向这个0x44;
  2. 然后执行call func:和之前一样,CPU把当前的返回地址压入栈,ESP会向下移动(栈是向下增长的),现在栈顶是这个返回地址,下面紧跟着刚才push的0x44;
  3. 进入func后先执行pop ax:这个指令会把当前栈顶的返回地址弹出并赋值给AX寄存器,同时ESP向上移动(相当于把栈顶的元素“移除”),此时栈顶就变成了之前push的0x44;
  4. 接下来执行ret:ret读取当前栈顶的0x44,把它赋值给EIP——这就导致CPU直接跳转到0x44地址执行,完全偏离了原本的返回流程,这就是ROP技术利用的核心逻辑:通过调整栈的内容,让ret指令跳转到我们指定的地址。

两者的核心差异点

  • 正常ret场景:call压入的返回地址始终在栈顶,ret直接复用这个地址回到原流程;
  • 带pop ax的场景:pop ax主动“消耗”了call压入的返回地址(把它转移到AX里),让栈顶变成了我们预先push的0x44,后续ret就会加载这个自定义地址到EIP,从而实现代码流劫持。

另外你问到的pop ax的作用:没错,它确实会把栈顶的数值赋值给AX寄存器,同时调整栈指针ESP的位置,让栈顶指向栈中的下一个元素。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:03:07