
栈迁移
Le7栈迁移:一种精巧的栈空间操控技术
栈迁移是什么?
想象一下你的程序正在执行,突然发现当前的“工作台”(栈空间)太小了,放不下需要的工具和数据。这时候,栈迁移就像是为程序搬了个新家——把执行环境整体搬迁到更宽敞的地方,无论是bss段还是栈的其他区域都可以成为新的落脚点。
为什么需要栈迁移?
应用场景分析
当你遇到这两种情况时,栈迁移就派上用场了:
- 空间严重不足:溢出的长度只够覆盖ebp,连返回地址都碰不到
- 刚好但不够用:虽然能覆盖返回地址,但后面的参数区域太短,payload塞不进去
简单来说,就是原来的栈空间不够发挥,需要换个场地大展拳脚。
技术核心
理解关键指令
栈迁移的魔法主要依靠leave;ret这个指令组合的两次精彩演出。
leave指令分解:
1 | mov esp, ebp ; 让栈顶指针指向当前栈底 |
这个过程相当于先确定新的工作基准点,然后更新基址指针。
ret指令作用:
1 | pop eip ; 将栈顶内容作为下一条指令地址 |
这是程序执行流的转向器,决定了接下来要去哪里。
栈迁移实战解析
第一阶段:
首先通过溢出漏洞,我们做了两件关键事:
- 把ebp的内容替换成目标迁移地址
- 将返回地址覆盖为
leave;ret的地址
此时main函数结束
第二阶段:
第一次leave;ret
- leave执行:
mov esp, ebp让两个指针汇合,接着pop ebp时出现了转折——ebp被我们预设的迁移地址填充 - ret执行:
pop eip将我们准备好的leave;ret地址装入,为第二次迁移做准备
为什么需要两次leave;ret?
因为main函数正常结束只会执行一次leave;ret,我们要实现完美迁移,就必须再来一次!
第三阶段:
第二次执行leave时,真正的迁移发生了:
mov esp, ebp:此时esp指向了我们设定的新地址pop ebp:更新ebp,同时esp自动下移一个单元
最后,当ret执行时,栈顶的system函数地址被弹入eip,成功GetShell!
技术要点总结
栈迁移的精髓可以概括为:
- 第一次leave;ret:把ebp“骗”到目标位置
- 第二次leave;ret:让esp跟上脚步,同时为system调用铺好道路
Related Articles
Comment
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果




