20242411 2026-2027-1 《网络与系统攻防技术》实验三实验报告
20242411 2026-2027-1 《网络与系统攻防技术》实验三实验报告
1.基础知识
1. 免杀的概念与本质
免杀是指通过改变程序的代码特征、文件组织形式或执行方式,使其在特定条件下未被安全软件识别或拦截。它改变的是程序被检测到的情况,不代表程序本身变得安全。
本次实验涉及 PowerShell 脚本、Veil 生成样本以及 C 语言加载器。它们主要改变载荷的表示形式和加载过程。
免杀具有环境依赖性和时效性。同一个文件在不同安全软件、规则版本或运行阶段中,可能得到不同的检测结果。
2. 静态检测与动态检测
2.1 静态检测
静态检测是在不执行程序的情况下分析文件,检查对象包括文件哈希、字节序列、字符串、文件结构、导入函数和代码模式等。
文件哈希能够准确标识某一份文件,但文件内容改变后,哈希通常也会改变。因此,安全软件不会只依靠哈希判断恶意性,还会识别多个样本共有的特征。
本次实验中的编码、XML 封装和加载器与载荷分离,都改变了文件的静态表现,但这些变化不保证能够消除可识别特征。
2.2 动态检测
动态检测是在程序执行过程中观察其行为,例如文件修改、进程操作、内存权限变化和网络连接等。
某个系统接口也可能被合法软件使用,安全软件通常需要结合调用顺序、操作对象和上下文进行判断。因此,“调用的是正常系统接口”不能证明程序安全,也不能保证不会触发告警。
静态检测与动态检测相互补充:文件扫描未报警,程序运行后仍可能被拦截;程序短时间内成功运行,后续扫描也可能发现异常。
3. 特征检测、启发式分析与行为监控
特征检测通过已知恶意代码的特征识别样本,通常适合发现已知威胁及其相近变种。
启发式分析根据代码结构、指令模式和文件异常等信息判断风险,不一定要求文件与某个已知样本完全一致。因此,修改文件名或重新编译后,程序仍可能被识别。
行为监控关注程序实际做了什么。例如,程序读取外部数据后将其作为代码执行,或者修改启动位置,都会产生可供分析的行为记录。安全软件可以根据多个事件之间的联系判断风险。
这说明免杀不能只关注文件是否“长得不一样”,还需要理解安全软件如何观察执行过程。
4. Shellcode、载荷与加载器
载荷是实现某项功能的代码。在本次实验中,载荷用于建立实验环境中的反向连接。
Shellcode 是机器指令的字节序列,可以作为载荷的一种形式。它通常不像普通可执行文件那样具有完整的文件结构,需要合适的运行环境才能执行。
加载器负责将载荷放入能够执行的环境。C 语言实验中的加载器从外部文件读取 Shellcode,并在自身进程中加载执行。
加载器与载荷分离后,可执行文件本身不直接包含完整载荷,改变了静态分析对象。但运行时载荷仍会进入内存,其内容和执行行为仍可能被检测。分离存放不等于无文件执行,也不等于没有恶意特征。
5. 进程、线程与内存权限
进程是程序运行时的资源容器,具有自己的虚拟地址空间、句柄和权限信息。线程是进程内执行指令的基本单元,同一进程中的线程共享该进程的地址空间。
内存页通常具有读、写、执行等权限。数据被复制到内存,并不意味着处理器可以直接执行它;内存权限和代码架构等条件也必须适合执行。
6. 内存检测的作用
内存检测关注程序运行后的内存内容和状态,可以发现磁盘文件中未直接呈现的代码或数据。例如,编码内容在运行时还原后,可能重新暴露出可识别特征。
内存检测与行为监控的关注点有所不同:前者重点分析内存中的内容和区域属性,后者重点分析程序发生了哪些操作。实际产品可能将两者结合使用。
本次实验后续出现的内存防护告警说明,首次成功建立连接并不代表载荷能够持续不被发现。
7. x86、x64 与架构匹配
x86 和 x64 是不同的指令架构,在指令、寄存器和地址宽度等方面存在差异。Shellcode 的架构必须与实际执行它的进程相匹配。
64 位 Windows 通常能够通过兼容机制运行受支持的 32 位程序,因此“操作系统是 64 位”不代表只能运行 64 位程序。真正需要核对的是载荷与承载进程是否匹配,以及系统是否支持该程序。
交叉编译是指在一种环境中生成面向另一种环境的程序。本次实验使用 Linux 环境中的编译工具生成 Windows 可执行文件。
8. PowerShell、.NET 与 MSBuild
PowerShell 既是命令行环境,也支持脚本执行,并能够使用 .NET 功能和部分系统接口。因此,它可以用于正常管理任务,也可能被用于加载和执行恶意代码。
MSBuild 是构建工具,可以读取 XML 格式的项目文件。实验参考方案利用其任务机制调用相关代码,改变了脚本的承载方式。
使用系统自带工具并不意味着执行内容可信。安全软件仍可以分析脚本内容、任务结构、进程关系及后续行为。XML 文件也不一定只是普通配置数据,其含义取决于读取它的程序。
9. Veil 与自动生成样本
Veil 可以通过不同语言和模板生成安全测试样本。本次实验选择了 Go 语言模块,并生成可执行文件。
更换实现语言会影响编译结果和文件结构,但不必然改变载荷功能,也不保证清除已知模板或行为特征。
2.实验内容
本次实验围绕恶意代码检测与免杀原理,分别进行了 PowerShell 加载 Shellcode、Veil 生成样本和 C 语言加载器三种尝试,并结合本地安全日志与 VirusTotal 检测结果分析其效果。
1. PowerShell 加载 Shellcode
生成 PowerShell 实验脚本,参考 Base64 编码和 XML 封装方式改变脚本的存放及加载形式,并进行检测。结果显示,XML 样本被 14/61 个引擎检出,PowerShell 脚本被 28/61 个引擎检出,且脚本在本地下载过程中被安全软件识别并删除。
2. Veil 生成实验样本
完成 Veil 环境配置,选择 Go 语言模块生成可执行样本,并启动对应监听。Windows 端下载样本时,安全软件将其识别为 Backdoor/GO.Meterpreter.a 并删除。
3. C 语言加载外部 Shellcode
编写并交叉编译 C 语言加载器,将加载器与外部载荷文件分开存放。在 Windows 测试环境运行后,成功建立实验会话,并通过进程 PID 核对载荷运行于加载器进程中。
多引擎检测中,加载器检出结果为 13/71,外部载荷为 1/61。
3.实验过程
3.1PowerShell 加载 Shellcode 的免杀尝试
一、实验原理
本次实验参考了通过 MSBuild 加载 XML 内联任务,并在其中调用 PowerShell 执行脚本的思路。
PowerShell 脚本中包含 Shellcode 字节数组及内存操作相关接口,其基本过程是在进程内分配内存、复制代码并创建线程执行。
Base64 属于编码方式,不属于加密。它能够改变内容的文本表示形式,但不会消除脚本原有的恶意功能,也不保证能够规避安全软件检测。
二、实验过程与现象
- 生成 PowerShell 实验样本
在 Kali 环境中生成用于实验的 PowerShell 脚本 shell.ps1。终端输出显示,生成的载荷架构为 x86,载荷大小为 355 字节,输出脚本大小为 2467 字节。

图 1 PowerShell 实验样本生成结果
- 查看和编辑脚本
使用文本编辑器查看生成的脚本。脚本中可以看到内存分配、字节数组复制及线程创建等内容,体现了在进程内加载并执行 Shellcode 的基本结构。

图 2 PowerShell 脚本内容与编辑记录
- 对脚本进行 Base64 编码
对 shell.ps1 进行 Base64 编码,得到对应的编码文本,用于参考方案中的 XML 封装。

图 3 脚本 Base64 编码结果
- 检测 XML 样本
将 shell.xml 提交至 VirusTotal 进行检测。截图显示,共有 61 个检测引擎参与分析,其中 14 个将该文件标记为恶意,检出比例约为 23.0%。
检测标签中出现了 PowerShell、MSProj 和 Meterpreter 等相关名称,说明该文件仍能被部分引擎识别。

图 4 shell.xml 多引擎检测结果:14/61
- 观察本地安全软件的拦截情况
在 Windows 端下载 shell.ps1 时,安全软件产生了病毒防护日志,将其识别为 Trojan/Injector.pd,并显示已处理、删除文件。

图 5 脚本下载请求与本地安全软件拦截记录
- 检测 PowerShell 脚本样本
将 shell.ps1 提交至 VirusTotal 检测。截图显示,61 个检测引擎中有 28 个将其标记为恶意,检出比例约为 45.9%。
与 shell.xml 的 14/61 相比,shell.ps1 在本次截图记录中的检出引擎数量更多。

图 6 shell.ps1 多引擎检测结果:28/61
3.2 Veil 生成样本及安全软件检测实验
一、实验原理简述
Veil 是用于安全测试的载荷生成框架,可通过不同语言和封装方式生成实验样本,以评估安全软件的检测能力。本次尝试使用 Go 语言的 Meterpreter 反向 TCP 模块生成 Windows 可执行文件,并观察其在下载过程中是否被安全软件识别。
改变程序的实现语言和文件特征并不意味着能够成功免杀,生成的样本仍可能被特征检测、启发式分析或行为监控识别。
二、实验过程
1. 完成 Veil 环境配置
在 Kali 中完成 Veil 的配置和环境检查。终端显示已写入配置文件,并检查输出目录及相关目录的权限,最后提示环境检查完成。

图 1:Veil 环境配置与检查完成
2. 查看并选择实验模块
进入 Veil-Evasion,查看可用模块列表。本次选择 Go 语言实现的 Meterpreter 反向 TCP 模块,用于生成后续检测所需的实验样本。

图 2:Veil 模块列表与模块选择
3. 配置实验参数
进入所选模块后,配置实验环境中的回连地址和端口,并查看参数列表,确认相关设置。

图 3:实验模块参数配置与确认
4. 生成实验样本
完成参数配置后生成样本,并将输出名称设为 20242411。终端显示已生成可执行文件 20242411.exe,同时输出对应的 Go 源代码和 Metasploit 资源配置文件。

图 4:可执行样本及配套文件生成结果
5. 启动监听端
使用生成的资源配置文件启动 Metasploit。终端显示反向 TCP 监听已经启动,准备接收实验样本的连接。

图 5:监听端启动
6. 下载样本并观察检测结果
在 Kali 端提供实验样本的 HTTP 下载服务,并在 Windows 端通过浏览器请求该文件。服务端日志显示收到了样本下载请求,返回状态为 200。
与此同时,Windows 端安全软件的文件实时监控将下载过程中的临时文件识别为 Backdoor/GO.Meterpreter.a,并显示已处理、删除文件。
因此,本次生成的样本在下载过程中即被检测和删除,未实现该环节的免杀。

图 6:样本下载记录与安全软件检测、删除结果
3.3 C 语言 Shellcode 加载器实验
一、实验原理简述
本次实验采用加载器与载荷文件分离的方式:C 语言程序负责读取外部 Shellcode 文件,在当前进程内加载并执行,由载荷尝试建立反向连接。
这种方式使加载器和载荷分别存放,但不代表能够完全规避检测。安全软件仍可能通过文件特征、内存扫描和运行行为识别威胁。因此,本次实验分别观察程序运行、会话建立、多引擎扫描及本地安全防护情况。
二、实验过程
1. 编写并编译加载器
在 Kali 中编辑 C 语言加载器源文件。截图中的程序包含外部文件读取、内存分配、内存权限调整及线程执行等逻辑,属于在当前进程内加载外部 Shellcode 的方式。
随后使用交叉编译工具生成 Windows x64 可执行文件 shellcode_launcher_20242411.exe。

图 1:C 语言加载器源代码

图 2:加载器编译操作
2. 生成外部载荷文件
生成用于 Windows x64 实验环境的载荷,并保存为 shellcode_20242411.raw。

图 3:载荷生成结果
3. 准备文件传输并在测试端运行
在 Kali 端启动临时 HTTP 文件服务,用于向 Windows 测试环境提供实验文件。
Windows 端截图显示,在桌面目录中启动加载器,并指定外部载荷文件。

图 4:临时 HTTP 文件服务启动操作

图 5:Windows 测试端启动加载器
4. 观察反向连接结果
Kali 端监听记录显示,Windows 测试主机与监听端建立了 Meterpreter 会话,并出现交互提示符,说明该次测试中的载荷成功运行并建立连接。

图 6:监听端成功建立实验会话
5. 核对测试主机和进程信息
在已建立的会话中查看系统、用户及网络信息。结果显示,测试端为 Windows 10 x64,网络地址与连接记录中的测试主机一致。
随后查询会话所在进程,得到 PID 为 5600。Windows 任务管理器中的 shellcode_launcher_20242411.exe 同样显示 PID 为 5600,两者相互对应,支持载荷运行于加载器进程内的判断。

图 7:测试主机系统、用户和网络信息

图 8:会话所在进程 PID

图 9:加载器进程及安全软件防护开关状态
该时刻截图显示安全软件相关防护开关处于开启状态,加载器进程仍在运行。
6. 进行多引擎检测
分别对加载器和外部载荷文件进行 VirusTotal 检测。
截图显示,shellcode_launcher_20242411.exe 被 70 个引擎中的 24 个标记为恶意;shellcode_20242411.raw 被 61 个引擎中的 1 个标记为恶意。
两个文件的格式及参与检测的引擎数量不同,结果应分别记录。原始载荷文件检出数量较少,并不意味着加载后的运行行为不会被检测。

图 11:加载器多引擎检测结果,24/70

图 12:外部载荷多引擎检测结果,1/61
7. 后续尝试(提权,自启动)
经过多次尝试,这个方法只能实现部分不触及内存或者行为检测的远程连接,不论是想要进一步获取权限还是想要自启动,不断向kali的ip发起连接,这些行为均被火绒检测出来了。
如果能进一步混淆行为和内存的特征或许可以绕过火绒

图 13:在运行设计内存读写行为的指令时火绒内存的检测
4.问题及解决方案
一、PowerShell 加载 Shellcode 的尝试
1. 脚本编辑时换行格式存在问题
问题: 编辑截图中,循环语句包含字面形式的“\n”,没有形成实际换行,可能导致脚本解析或执行异常。
解决方案: 检查脚本文本格式,区分转义字符与实际换行,并通过语法检查确认文件格式正确。
二、C 语言 Shellcode 加载器的尝试
1. 源码获取遇到网络问题
问题: 从代码仓库获取源码时发生连接超时。
解决方案: 文档记录后续改为本地编写加载器,并完成编译。
2. 初次运行未建立连接
问题: 32位载荷指令架构与实际承载进程不匹配。
解决方案: 核对加载器、载荷和承载进程的架构,并结合运行错误及日志定位原因。后续 x64 方案成功建立会话。
5.学习感悟、思考等
在看到尝试在物理机上实现免杀的时候,我最开始认为在所有防护都开启的情况下很困难。实际实践的情况也确实如此,大多数的程序连下载都被火绒禁止,有些在关闭火绒后传输到物理机上,但是再开启火绒然后尝试运行实现回显,大部分都失败了。
后续借鉴了github上6年前的bypassantivirus这个项目,先尝试powershell加载shellcode免杀,失败;第二个尝试Veil免杀,还是失败(不够值得一提的是veil在十多年前估计还是很好用的,当时根本没有这么强的杀毒软件);
最后尝试C、C++加载shellcode免杀,成功部分实现免杀,只是在涉及敏感操作和内存读写的时候还是会被发现。基本原理:将加载程序和 Shellcode 分开存放:C、C++ 编写的程序负责读取外部载荷文件,再将其加载到自身进程的内存中执行。
这种方式改变了文件的组织形式,使加载器本身不直接包含完整载荷,可能减少部分静态特征的暴露。如果安全软件当时没有识别或阻止相关内存内容及执行行为,载荷就能够运行,表现为该次测试中实现了免杀。本次成功建立连接说明载荷在当时的环境中运行成功,但后续出现了内存防护告警,因此不能认为该方法能够持续绕过检测。通过实验的全过程,我体会到了人们在尝试免杀做出的千奇百怪的尝试,也只有不断的攻击和防御,才能不断提高物理机的安全性,不过现阶段最实用的还是不要随意点击不明链接,执行未知程序,下载第三方盗版软件。
6.回答问题
- 问题1:杀软是如何检测出恶意代码的?
杀毒软件通常结合静态分析、动态分析和云端分析等技术检测恶意代码,主要包括以下方式:
-
特征码检测
将文件中的代码片段、哈希值等与已知恶意软件特征库进行比对。该方法能够快速识别已知恶意代码,但对新型或经过变形处理的恶意代码检测能力有限。 -
启发式检测
分析程序的代码结构、指令和文件格式,检查异常入口点、自修改代码等可疑特征,从而识别潜在的恶意代码,但可能产生误报。 -
行为检测
监控程序运行时的操作,如进程注入、批量加密文件、修改系统关键配置等,结合行为上下文判断程序是否具有恶意性。 -
沙箱检测
在隔离的虚拟环境中运行可疑程序,观察其文件操作、系统修改和网络通信等行为,判断是否存在恶意功能。 -
机器学习与云端分析
利用机器学习模型分析文件及行为特征,并结合云端威胁情报和文件信誉,识别未知或可疑的恶意程序。
实际应用中,杀毒软件通常综合多种检测结果进行判断,以提高检测率并降低误报率。
- 问题2:免杀是做什么?
免杀是指通过改变程序的代码特征、文件结构或运行方式,使其不被杀毒软件识别或拦截。其本质是规避安全软件的检测,并不意味着程序本身没有恶意行为。
在网络攻防实验中,研究免杀主要用于了解安全软件的检测原理、评估其检测能力,并分析不同检测机制的局限性,为改进防护措施提供依据。
- 问题3:免杀的基本方法有哪些?
免杀的基本思路是改变程序的静态特征或运行行为,常见方法包括:
-
代码混淆
调整代码结构、指令表达或控制流程,在保持原有功能的同时改变代码特征。 -
编码与加密
对字符串、配置或部分代码进行编码或加密,减少敏感内容在文件中的直接暴露。运行时还原后,仍可能被检测。 -
加壳与压缩
对程序进行封装或压缩,改变文件结构和静态特征。但加壳本身也可能成为可疑特征。 -
修改与重新编译
修改源代码、资源或编译选项,改变程序的二进制内容。单纯修改文件哈希通常无法规避其他检测机制。 -
调整加载与执行方式
改变代码加载和执行的过程,减少某些静态特征的暴露,但仍可能被内存扫描或行为监控发现。 -
反分析技术
识别调试器、虚拟机或沙箱环境,并改变程序行为,以干扰自动化分析。
浙公网安备 33010602011771号