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

为什么x86 shellcode执行DLL卸载成功后会触发执行位置访问违反异常?

问题解答

该异常的直接诱因是unload函数的shellcode返回地址计算错误,ret指令跳转到了已被VirtualFree释放的不可执行内存页,具体问题和修复方案如下:

核心问题点

  • 硬编码偏移不可靠:你为unload shellcode写死的返回偏移0x2AF和编译环境强绑定,VS开启调试模式、/GS安全检查、增量编译、优化等级调整都会改变函数体的指令长度,你计算的偏移和实际需要的返回地址不匹配。异常提示的非法地址0x9269D814就是你之前分配的shellcode内存页地址,执行完shellcode后你立刻调用VirtualFree释放了该页,跳转过去自然触发执行访问违规。
  • 栈平衡存在隐患:你调用的LoadLibraryA、GetModuleHandleA、FreeLibrary均为WINAPI(__stdcall调用约定),被调用方会自动清理栈上的参数,你在调用后额外执行add esp,8属于多余操作,虽然load函数碰巧未触发问题,但unload的shellcode多了两次push操作,栈平衡偏移不匹配进一步放大了返回地址错误的问题。
  • 返回逻辑设计不合理:调用shellcode时,编译器生成的call指令已经自动把后续执行VirtualFree的指令地址压入栈,你不需要手动push返回地址绕开默认返回逻辑,这种设计本身容错率极低。

修复方案

  1. 优先移除硬编码偏移逻辑:如果仅做本地shellcode功能测试,直接删除shellcode开头手动push返回地址的逻辑,用默认的ret返回即可,无需自行计算跳转偏移。
  2. 修正栈平衡代码:调用WINAPI后只需要清理你自己push的函数地址,将add esp,8改为add esp,4即可,不要额外清理参数占用的栈空间。
  3. 调整内存释放时机:如果确实需要自定义返回地址,不要在shellcode执行完立刻调用VirtualFree,等原函数执行完后续逻辑后再释放内存,避免返回地址落到已释放的内存页。
  4. 若必须保留硬编码偏移(比如为远程注入场景做测试),编译时需要关闭优化、关闭/GS安全检查、关闭增量编译,每次修改代码后重新用反汇编工具校验返回地址的偏移值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 09:57:03