news 2026/8/22 13:25:13

为什么内存扫描挡不住Voidgate?从加密Shellcode到逐条解密执行的原理全景

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
为什么内存扫描挡不住Voidgate?从加密Shellcode到逐条解密执行的原理全景

为什么内存扫描挡不住Voidgate?从加密Shellcode到逐条解密执行的原理全景

【免费下载链接】VoidgateA technique that can be used to bypass AV/EDR memory scanners. This can be used to hide well-known and detected shellcodes (such as msfvenom) by performing on-the-fly decryption of individual encrypted assembly instructions, thus rendering memory scanners useless for that specific memory page.项目地址: https://gitcode.com/gh_mirrors/vo/Voidgate

Voidgate 是一种针对 Windows 平台的内存扫描绕过技术:它通过将已知的 Shellcode(如 msfvenom 生成的载荷)整体 XOR 加密后驻留在内存中,再借助硬件断点(HWBP)与向量异常处理程序(VEH)实现"执行到哪条指令才解密哪条指令"的逐条解密执行机制,让 AV/EDR 的内存扫描器在那一页内存里永远只能看到一堆密文。对于想理解"单步执行 + 异常驱动解密"这类反检测思路的安全学习者来说,这是一个麻雀虽小、五脏俱全的典型样本。

一、先搞懂问题:内存扫描为什么"一抓一个准"

传统的恶意载荷在内存中展开后,会有一段明文的可执行字节码。AV/EDR 的内存扫描器做的事情很简单——定期遍历进程的内存页,把每一段内容拿去和已知 Shellcode 特征(YARA 规则、哈希、相似度)做比对。

这就带来一个尴尬的现实:

  • 🔍特征比对只看静态字节:只要明文完整躺在内存里,哪怕你只执行过 1%,扫描器照样能匹配上;
  • 📦msfvenom 等工具生成的载荷被"背板":这些载荷在攻防圈流传极广,其字节特征早已被各大厂商收录;
  • ⏱️扫描周期短:内存驻留时间越长,被扫到的概率越高。

一句话总结:传统做法是"整段解密 → 整段驻留明文",而内存扫描的前提恰好就是"整段明文"。要破局,就必须打破这个前提。

二、Voidgate 的核心思路:内存里永远只有一条明文指令

Voidgate 的答案非常巧妙:永远不要同时存在两条明文指令。

它的运作模型可以概括为:

  1. 加密后的 Shellcode 整体存放在一块PAGE_EXECUTE_READWRITE内存区域中,前后填充 NOP 字节作为"海绵"区域;
  2. 程序启动时,Shellcode 的入口地址被设置为硬件断点(Hardware Breakpoint)
  3. 程序安装一个向量异常处理程序(VEH),充当"软件调试器";
  4. 每执行完一条指令,CPU 触发单步异常 → VEH 介入 →解密当前指令、重新加密上一条刚用过的指令→ 继续执行。

在任意一个瞬间,整个内存页中只有一条 15 字节以内的明文汇编指令(x64 单条指令的最大长度)。对于内存扫描器来说,这一页内容看起来就是一串无意义的密文加一段 NOP——没有任何可匹配的特征。

💡 打个比方:传统做法像把整本密码本摊开在桌上,Voidgate 则像只翻开当前要读的那一行,读完立刻合上,再翻下一行。

三、原理拆解:硬件断点 + VEH 的组合拳

这套机制由三个 Windows 底层机制配合完成,源码集中在 Voidgate.cpp 与 main.cpp 中。

3.1 硬件断点(HWBP):逐条执行的"发令枪"

硬件断点利用 CPU 的调试寄存器(Dr0~Dr3)实现,当 RIP 命中断点地址时,硬件直接产生异常——它不需要修改任何内存字节,对扫描器完全不可见(软断点改写内存为0xCC,反而容易暴露)。

Voidgate 在SetHardwareBreakpoint()中将 Dr0 指向 Shellcode 入口,并配置 Dr7 启用全局断点。这是整个"单步循环"的第一推动力。

3.2 VEH:解密器的真正载体

AddVectoredExceptionHandler()安装的 VEH 回调VehDecryptHeapAsm()是整个项目的灵魂,它每次被调用时做四件事:

  • 🧹清理:清除 Dr0 上的入口断点(只在入口需要一次);
  • 🔓解密:读取当前 RIP 指向的地址,用 XOR 密钥解密接下来的 16 字节(覆盖 x64 最长指令长度);
  • 🔒回填加密:把上一条解密过的指令(地址记录在全局变量last_decrypted_asm中)重新加密,恢复密文状态;
  • ▶️续跑:设置 EFlags 中的TRAP 标志,保证下一条指令执行完时再次触发单步异常。

其中 XOR 密钥的起点位置由GetXorKeyIndexForAsm()计算——用"当前指令地址与载荷基址的差值对密钥长度取模",这样无需记录每条指令的位置,VEH 就能随时算出该用密钥的哪一段去加解密。

3.3 一个容易被忽略的细节:边界检查

VEH 里有一处边界判断:如果当前 RIP 不在载荷的上下界之内(比如 Shellcode 调用了 kernel32.dll 的函数),就直接放行、不做任何加解密。这保证了解密器只"看守"自己的内存页,不干扰系统函数的正常执行。

四、完整执行流程:从加密 Shellcode 到逐条解密执行

把上面三个部件串起来,Voidgate 的完整生命周期如下:

阶段动作关键点
① 准备XOR 加密工具对 Shellcode 做整体加密,输出字节数组密钥在加密端与执行端必须一致
② 分配VirtualAlloc申请 RWX 内存,前后填充0x90(NOP)加密载荷拷入中间区域
③ 布防入口地址设置硬件断点,安装 VEH此时内存中全是密文
④ 点火主线程跳转到载荷入口HWBP 触发,VEH 接管
⑤ 循环每条指令:解密当前 → 加密上一条 → 置 TRAP 标志内存中恒为"单条明文"
⑥ 收尾载荷执行完毕,释放内存全程无整段明文驻留

整个过程中,执行速度会明显下降——每条指令背后 VEH 至少要额外执行 300 条左右的汇编指令来完成加解密与恢复现场。一个以体积优先优化的 msfvenom 载荷,跑完可能要 15 秒以上,这是"用速度换隐蔽"的典型代价。

五、POC 复现:四步跑通加密Shellcode逐条解密

⚠️ 本项目仅供学术研究与教学使用,请仅在自有环境中测试。

克隆仓库:

git clone https://gitcode.com/gh_mirrors/vo/Voidgate

Step 1 · 生成载荷:用 msfvenom 生成 x64 反弹 Shell 并输出为原始二进制文件;

Step 2 · XOR 加密:用仓库自带的加密工具处理该文件,它会按密钥循环异或并直接打印出 C 字节数组;

Step 3 · 填入项目:将打印出的字节数组替换 main.cpp 中的payload变量,并确认加密端与执行端的密钥(key)完全一致;

Step 4 · 监听并运行:在接收端起好监听,然后编译并运行 Voidgate.exe,观察载荷被逐条解密执行、监听端成功收到连接的过程(见上方演示动图)。

📌 提示:由于逐条解密开销大,运行后请耐心等待十几秒到几十秒,这不是程序卡死。

六、局限与边界:哪些场景下 Voidgate 会失效

了解局限与理解原理同样重要,项目 README 中明确列出了三大限制:

  1. ⚡ 速度惩罚:每条指令都要过一遍 VEH,指令越多、循环越密的载荷,执行越慢;
  2. 🧵 单线程假设:如果载荷通过NtCreateThread等新线程执行且入口在 Shellcode 内部,新线程没有安装 HWBP,VEH 不会为它工作(作者标记为进行中);
  3. 📄 载荷内嵌数据不能自引用:若 Shellcode 把自己内部的字符串/数值当作数据(通过固定偏移引用),这段数据会一直处于加密状态而无法被正确读取。用汇编指令(如push立即数)压栈传参则不受影响。

此外,它不适合反射加载器等复杂载荷,最理想的定位是:作为初始访问(Initial Access)的小型第一阶段的载荷,或用于从 C2 服务器拉取后续载荷的"引导器"。

七、项目结构与核心文件速览

项目结构非常精简,适合通读源码:

  • 📁 voidgate-master/Voidgate/ —— 核心工程
    • Voidgate.h:常量定义(填充长度、x64 最大指令长度 15 字节)与函数声明
    • Voidgate.cpp:VEH 解密回调、硬件断点设置、XOR 密钥索引计算
    • main.cpp:内存分配、NOP 填充、载荷植入与执行入口
  • 📁 voidgate-master/XorEncryptPayload/ —— 配套 XOR 加密工具
    • XorEncryptPayload.cpp:读取二进制载荷,循环异或后输出 C 数组
  • 🖼️ poc.gif —— 完整 POC 演示动图
  • 📄 README.md —— 原理说明、限制与使用说明

总结

Voidgate 用三个"教科书级"的底层机制——硬件断点、VEH、TRAP 标志——组合出了一套优雅的内存扫描对抗方案:XOR 加密 + 逐条解密执行,让目标内存页在任何被扫描的瞬间都只暴露一条明文指令。它的价值不仅在于"绕过"本身,更在于展示了一种思维方式:当防御方依赖"静态字节特征"时,攻击方可以把明文的生命周期压缩到单条指令的长度

对于安全学习者,这个不到千行代码的小项目是一份极佳的学习材料——读懂它,你就同时理解了调试器工作原理、Windows 异常分发机制和内存扫描对抗的基本面。

【免费下载链接】VoidgateA technique that can be used to bypass AV/EDR memory scanners. This can be used to hide well-known and detected shellcodes (such as msfvenom) by performing on-the-fly decryption of individual encrypted assembly instructions, thus rendering memory scanners useless for that specific memory page.项目地址: https://gitcode.com/gh_mirrors/vo/Voidgate

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/22 13:24:30

LinkSwift:免费解析网盘直链,一键拿到真实下载地址

LinkSwift:免费解析网盘直链,一键拿到真实下载地址 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘…

作者头像 李华
网站建设 2026/8/22 13:24:17

NCM 转 MP3 只需 3 分钟:用免费 ncmdumpGUI 拿回网易云音乐

NCM 转 MP3 只需 3 分钟:用免费 ncmdumpGUI 拿回网易云音乐 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换,Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 你在网易云音乐里买下的歌,…

作者头像 李华
网站建设 2026/8/22 13:21:32

安卓15_ROM修改定制化_____修改设置选项的默认值 自定义settings默认值

修改设置默认值是ROM定制中的基础操作。合理预设默认值能让用户免去手动调整的麻烦,实现开箱即用。比如自动启用深色模式、默认禁用自动亮度调节、预设更高屏幕刷新率等配置。本文将全面解析不同设置项的默认值修改方法,通过掌握核心原理与操作步骤,帮助您轻松定制自定义ROM…

作者头像 李华
网站建设 2026/8/22 13:19:47

NOC快速入门

目录:NOC入门第一阶段1.传统bus2.NOC核心理论第二阶段:1.三架马车:2.核心组件:3.性能问题:第三阶段:1.实现虫洞router第四阶段:1.实现NINOC入门 第一阶段 1.传统bus 传统bus 2.NOC核心理论 …

作者头像 李华