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

栈缓冲区溢出利用如何避免崩溃?VC6+WinXP场景技术问题

问题解答

1. strcpy场景利用失败、memcpy场景利用成功的原因

核心原因来自两个函数的实现逻辑差异,以及payload特性的适配问题:

  • strcpy的核心特性是遇到源数据中的\x00(空字节)就会终止复制,同时会在目标缓冲区末尾自动追加一个\x00;而memcpy完全按照传入的长度参数复制数据,不会对内容做任何校验和截断。你构造的payload中jmp_esp的地址如果包含空字节,strcpy复制到该位置就会直接截断,后续的shellcode根本不会被复制到栈上,自然无法执行;而memcpy不受空字节影响,会把完整payload复制到栈中,所以可以正常执行。
  • 代码中strcpy后会调用puts(msg):使用strcpy时你生成的是经过编码的无空字节shellcode,puts会尝试打印整个缓冲区直到遇到空字节,这个调用过程中会在栈上压入参数、生成临时栈帧,大概率会覆盖栈中存储的shellcode内容,导致shellcode执行失败;而memcpy场景下你用的未编码shellcode本身包含空字节,puts遇到空字节就停止打印,执行过程中不会破坏后续的shellcode内容。
  • shikata_ga_nai编码的shellcode需要在栈上完成自解码,解码过程依赖栈寄存器的准确值,如果strcpy额外追加的\x00或者puts调用修改了栈上的关键数据,会直接导致解码失败,shellcode无法正常执行。
  • 额外补充:你的payload填充长度存在偏差,1024个A仅能填满msg数组,接下来的4字节会覆盖ebp寄存器的值而非返回地址,这种偏差在strcpy的截断影响下更容易导致利用失败,而memcpy场景下复制数据完整,即使有微小偏差也可能命中可执行地址,这也是两者成功率不同的原因之一。

2. 避免程序崩溃、维持栈平衡的方案

可以通过以下几种方式实现:

  • 寄存器上下文保存恢复:在shellcode的开头先执行pushad、pushfd指令保存所有通用寄存器和标志寄存器的状态,等shellcode核心逻辑(弹出计算器)执行完成后,再执行popfd、popad恢复所有寄存器的原始状态,避免寄存器值异常导致后续代码执行出错。
  • 栈帧修复:提前获取原程序正常执行时deal_msg函数的ebp值、以及调用deal_msg后的返回地址,在shellcode执行完成后手动把栈上被覆盖的ebp、返回地址恢复为原始值,再调整栈指针esp到函数返回时的正确偏移,最后执行ret指令就能回到main函数的正常执行流,程序可以继续正常运行。
  • 进程/线程隔离:如果不需要原程序继续运行后续逻辑,可以在shellcode执行完弹出计算器的逻辑后,调用ExitThread函数退出当前处理请求的线程,不会影响整个进程的运行;如果需要更彻底的隔离,可以用CreateProcess创建计算器进程后直接结束当前线程,完全不修改原进程的核心执行逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 09:18:04