导语:上篇我们搭好了实验环境,跑通了一个基础shellcode加载器——不出意外,它立刻就被Defender检测到了。本篇我们要做的是:依次突破静态签名检测、IAT/API监控、动态行为检测,三层防护逐个击破,最终让一个携带已知特征码的Meterpreter payload在Defender眼皮底下落地、执行、上线。
一、XOR加密:让静态特征码失效
上一篇文章里,用msfvenom生成的shellcode是明文形态,Defender直接通过已知IOC(危害指标)匹配到了它。
XOR加密的思路很简单:用一次性密钥把shellcode的原始字节全部打乱,只要加密后的数据与原始特征码没有任何字节对应,签名检测就失效。
实现步骤:
- 使用Github仓库中的
myEncoder3.py脚本 - 第一次传入原始shellcode文件,查看十六进制明文
- 第二次传入shellcode文件 + 自定义密钥(如
ukbf),输出加密后的十六进制字符串 - 将加密后的shellcode和密钥一起写入C++代码,运行时解密

OPSEC提示:加密后的shellcode在磁盘上处于加密状态,运行时在内存中解密——这对Windows Defender足够了,但现代EDR可以读取进程内存并检测到已解密的payload。如需对抗高级EDR,可参考Ekko等内存加密方案。
新增代码要点(对比injectBasic.cpp):
- 新增
key[]数组存放XOR密钥(每次编译务必更换) - 新增
encryptedShellcode[]数组存放加密后的shellcode - 添加运行时XOR解密逻辑
将生成的SecondExample.exe放到排除目录——应该能正常上线Meterpreter了。把它复制到没有排除策略的普通目录试试……
什么?仍然无法落地?
二、IAT监控与Win32 API监控:两个隐形墙
Import Address Table(导入地址表)
IAT是PE可执行文件中的数据结构,存放着程序动态链接时所引用的所有系统API信息。杀软通过静态分析IAT,可以直接判断程序是否调用了CreateFile()、ReadFile()、WriteProcessMemory()或VirtualAlloc()等敏感函数——这些都是恶意软件的常见行为特征。
Win32 API监控
杀软的另一层防护是实时跟踪应用程序调用的Win32 API。传统杀软通过hook这些高层API来感知”恶意行为”,属于动态检测范畴。
那有没有一种技术能同时绕过这两层?直接系统调用(Direct Syscalls)。
三、直接系统调用:一把钥匙开两把锁
什么是Syscall
在Windows系统中,用户态程序调用系统内核服务(如创建进程、分配内存)时,并非直接和内核对话,而是通过一层API抽象——Win32 API。这正是杀软hook的着力点。
直接系统调用则绕过这层抽象,直接通过内核系统服务号与内核通信。杀软的hook点在Win32 API层,直接系统调用根本不走这条路。
如何绕过IAT检测
IAT检测依赖于识别程序导入了哪些函数。直接系统调用不依赖任何导入函数——它直接用系统服务号(System Service Number)访问内核,这些编号根本不会出现在IAT里。
实现方案:SysWhispers2
SysWhispers2是当前最流行的直接系统调用生成工具,它能根据函数名自动生成对应的syscall stub,完全不需要依赖Win32 API。

编译配置步骤:
- 生成syscall头文件和汇编stub:
python.exe .syswhispers.py --preset common -o syscalls_common
- 将以下四个文件加入Visual Studio项目:
syscalls_common.hinjectSyscall-LocalProcess.cppsyscalls_common.csyscalls_common_stubs.std.x64.asm
- 启用MASM汇编编译器:
- 项目 → 生成自定义 → 勾选
masm(.targets, .props)→ 确定 - 右键
.asm文件 → 属性 → 项类型 → 设为”Microsoft Macro Assembler” - 生成 → 重新生成解决方案

关键代码逻辑(对比injectXOR.cpp):
- 引入
#include "syscalls_common.h"(SysWhispers2生成的头文件) - 使用
malloc在堆上分配解码缓冲区(应对大payload),用完后free防止内存泄漏 - 计算payload大小时减1——因为编译器会自动在字符串字面量末尾添加
终止符。若不减1,解密循环会把(0x00)也纳入XOR运算,而”任何数据XOR 0等于自身”,导致该字节始终保持加密状态,shellcode被破坏
核心注入步骤(全部使用Nt系列函数,不走Win32 API):
NtAllocateVirtualMemory():在目标进程分配内存NtWriteVirtualMemory():将shellcode写入已分配内存NtProtectVirtualMemory():将内存页改为可执行NtCreateThreadEx():创建线程执行shellcodeWaitForSingleObject():等待线程完成CloseHandle():优雅关闭句柄VirtualFree():清理分配的内存
运行新生成的SecondExample.exe——放到排除目录正常上线,复制到普通目录……磁盘落地成功,但仍被动态检测拦截。
四、动态行为检测:calc.exe测试与远程进程注入
第一步:用calc.exe确认问题所在
既然磁盘落地已过静态检测,执行时被拦截,问题就出在shellcode的行为本身。我们把shellcode换成启动calc.exe(无害程序),重新加密后落地执行——成功了。
结论毫无争议:Defender不拦截加载器,拦截的是shellcode的行为——也就是Meterpreter的网络通信和命令执行活动。
第二步:远程进程注入
问题很可能是:我们的shellcode需要联网回连攻击者,而Defender认为当前进程的联网行为可疑。
解决方案:把shellcode注入到一个本身就有网络授权的正常进程中。选择7-Zip的文件管理器7zFM.exe,因为它需要访问网络共享和检查软件更新,天然具备网络权限。

关键代码变更(对比injectSyscall-LocalProcess.cpp):
- 不再使用
GetCurrentProcess()获取当前进程句柄 - 改用
NtOpenProcess()配合自定义getHandle()函数,获取远程进程7zFM.exe的句柄 - shellcode的内存分配和写入逻辑保持不变,只是目标从”当前进程”换成”远程7-Zip进程”

运行FinalExample.exe:
- 放到排除目录 → 正常上线Meterpreter ✓
- 复制到桌面 → 无检测,放行 ✓
- 运行(前提是
7zFM.exe已在运行)→ 成功上线 ✓
五、总结:叠加的艺术
本文展示的技术并非什么神秘黑科技——都是已知手法的组合。但关键在于逐层叠加:
| 阶段 | 技术 | 解决的问题 |
|---|---|---|
| 磁盘静态 | XOR加密shellcode | 绕过杀软对msfvenom特征码的签名匹配 |
| IAT静态 | 直接系统调用(SysWhispers2) | 不再在导入表中暴露敏感API |
| API动态 | 直接系统调用(SysWhispers2) | 绕过Win32 API监控的hook点 |
| 行为动态 | 远程进程注入(7zFM.exe) | 借用合法进程的网络权限执行shellcode |
四层技术叠加,最终让一个携带最知名特征码的Meterpreter payload在完全更新的Windows Defender下畅通无阻。
权限提升(获取Administrator或SYSTEM级别)将是下一篇的主题。
出处:Hackmosphere — Windows Defender antivirus bypass in 2025 (Part 2)














暂无评论内容