VirtualAlloc免杀技术原理解读

5 人参与

在最近一次红队演练中,笔者意外捕获到一段运行在VirtualAlloc分配区域的 shellcode,恰恰说明了这种“内存免杀”手法仍在活跃。若不清楚其底层机制,防御方往往只能盲目拦截,导致误报频发。

VirtualAlloc 在内存分配中的角色

Windows 内核提供的 VirtualAlloc 能在进程地址空间中预留、提交或保护一块连续内存。与 HeapAlloc 不同,它不依赖任何特定堆结构,因而常被用作“裸露”代码的落脚点。攻击者只需一次 API 调用即可得到 RWX(可读写可执行)的页面,随后把解密后的 payload 写入并跳转执行。

免杀实现的核心路径

典型流程大致如下:
1)调用 VirtualAlloc 申请 RWX 页面;
2)将加密的 shellcode 通过 WriteProcessMemory 或直接 memcpy 写入;
3)利用 CreateThreadNtCreateThreadEx 或 APC 触发执行。加密手段从单纯 XOR 到多轮 AES 再到自定义混淆层层叠加,目的在于让静态扫描工具只能看到一段随机数据。

检测思路的技术细分

  • 基于 StackWalkEx 的线程栈回溯:遍历每条线程的调用帧,定位 PC 落在 VirtualAlloc 返回的内存区域。
  • 页面属性监控:实时拦截 VirtualProtect 将 PAGE_READWRITE 改为 PAGE_EXECUTE 的行为。
  • 加密解密行为关联:检测短时间内连续出现的 VirtualAlloc → memcpy → CreateThread 调用链。
  • 异常 PE 结构:无文件映射的代码通常缺失 MZ/PE 标记,或出现 “NOIMAGE” 区段,可作为二次过滤。

误报与防御的平衡点

不少合法软件(尤其是自带脚本引擎的游戏或数据分析工具)同样会使用 VirtualAlloc 动态生成代码。完全阻断会导致业务中断,因而实际部署时往往结合行为阈值:若同一进程在短时间内多次申请 RWX 页面并立即启动线程,才触发告警。这样既降低了误报,又保留了对真正免杀木马的捕获能力。

参与讨论

5 条评论
  • TrailBlazer

    这套路确实常见,防御要跟上。

    回复
  • 风语之森

    看到作者把加密层拆得这么清楚,感觉像在看现场拆弹,真是让人心跳加速😅,期待更多细节。

    回复
  • 软糖猫

    VirtualAlloc 能直接拿到 RWX 页面,确实是免杀的好选手。

    回复
  • LoopyLlama

    其实可以通过监控 NtAllocateVirtualMemory 的调用频率来进一步降低误报。

    回复
  • 花野

    这种加密方式在 macOS 上有对应的实现吗?

    回复