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


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

0.实验环境

  • 攻击机:Kali Linux 虚拟机(IP: 192.168.61.129)
  • 目标机:Windows 10 虚拟机(运行于物理宿主机上,网络模式为 NAT,IP: 192.168.61.137)
  • 杀毒软件:Windows Defender(反恶意软件客户端版本 4.18.26090.9,防病毒引擎版本 1.461.96.0)

1.基础知识

1.1 现代杀毒软件的多层检测机制

现代杀毒软件(如 Windows Defender)早已不再依赖单一的文件哈希比对,而是构建了一套静态与动态结合的多层防御体系:

  1. 特征码静态检测:杀软会提取文件中的特定字节序列、字符串片段或计算整个文件的哈希值。只要文件里有一丁点与病毒库中已知恶意代码匹配的“指纹”,就会立即被查杀。这种方法速度极快,但无法防御未知变种。
  2. 启发式静态扫描:为了解决未知病毒,杀软会分析文件的结构。例如,正常的软件很少会申请“可读可写可执行”的内存权限,也很少会使用某些高危的底层 API。如果文件包含了这种异常特征,或者文件的熵值(混乱度)极高(说明被加密或压缩了),就会被判定为“形迹可疑”。
  3. EDR 动态行为监控:这是现代杀软最核心的防线。程序在运行时,杀软的底层内核驱动会实时监控进程的所有敏感操作,比如是否试图修改其他进程、是否在内存中解压执行代码、是否发起了异常的网络连接。一旦发现,直接切断进程。

1.2 Windows 底层内存操作与敏感 API

为了让自制的 Shellcode 在内存中运行,我们编写的 C 语言加载器(Loader)必须要调用 Windows 的核心 API,而这些正是 EDR 监控的重点:

  • VirtualAlloc:用于在进程的虚拟地址空间里申请一块内存。如果申请时的权限标志位包含 PAGE_EXECUTE_READWRITE(即 RWX,可读可写可执行),极易引起杀软警觉,因为绝大多数正常程序不会在运行时动态申请这种权限的内存。
  • memcpy:将加密后的 Shellcode 密文从数据段复制到刚刚申请的那块内存中。
  • VirtualProtect:用于修改内存页的访问保护属性。很多高级免杀代码会先申请 PAGE_READWRITE 权限(避免引起怀疑),等写入代码后,再通过这个函数将内存改为 PAGE_EXECUTE_READ,从而执行里面的机器码。
  • 函数指针:C 语言中无法直接执行内存里的数据,必须将这块内存的地址强制转换为函数指针 ((void(*)())exec)();,让 CPU 的指令寄存器跳转到该地址去执行。

1.3 PE 文件结构与 UPX 加壳原理

  • PE 结构:Windows 下的可执行文件(如 exe、dll)遵循 PE 格式。它包含了文件头以及多个节区,如存放代码的 .text 段。杀软静态扫描时,会重点检查这些节区的内容。
  • UPX 加壳:加壳工具 UPX 会把原始 PE 文件中的代码段进行压缩,并附加一段解压代码(Stub)。程序运行时,Stub 首先获得控制权,在内存中把原本的代码解压还原,再跳转执行。加壳后,原来的节区结构改变,恶意特征码被隐藏,从而绕过静态扫描。但高强度的压缩会导致文件熵值变高,容易触发启发式查杀。

1.4 异或(XOR)加密原理

异或运算有两个特性:一是消除特征,将 MSF 生成的 Shellcode 与固定密钥(如 0xAA)异或,其恶意机器码特征会被破坏,变成无害的十六进制数组;二是解密可逆,假设原始代码为 A,密钥为 B,加密得到 C = A ^ B。程序运行时,只需用 C ^ B 就能还原出 A。这让 C 语言可以通过简单的循环在内存中动态解密,无需在硬盘暴露原始代码。

2.实验内容

  1. 测试 MSF 编码器、Jar 文件格式以及 UPX 加壳的实际免杀效果。
  2. 使用 Python 脚本对纯二进制 Shellcode 进行 0xAA 异或加密。
  3. 编写 C 语言加载器(Loader),在内存中解密并执行 Shellcode。
  4. 在开启 Windows Defender 的 Windows 10 虚拟机上验证静态查杀与动态运行效果,并记录杀软版本信息。

3.实验过程

3.1 传统工具与编码器测试

【方案简介】:直接使用 msfvenom 生成原始载荷、多次编码载荷及 Jar 格式文件,验证传统特征码修改手段在现代杀软面前的存活率。

操作步骤:使用 msfvenom 生成原始 exe、经过 5 次编码的 exe 以及 jar 格式文件。
测试结果:传入 Win10 虚拟机后,Defender 瞬间弹窗并删除了文件。在 VirScan 平台上,原始木马与编码木马的检出率均为 16/48,Jar 文件为 15/48。

【Defender查杀raw弹窗截图】
image

【Defender查杀encoded弹窗截图】
image

【Defender查杀jar弹窗截图】
image

【VirScan raw 16/48截图】
image

【VirScan encoded 16/48截图】
image

【VirScan jar 15/48截图】
image

结论:MSF 自带的编码器只是增加了一个解码外壳,而解码器的机器码早已被各大杀软记录,因此单纯修改特征码或更换文件格式无法实现免杀。

3.2 C + Shellcode 加密编程与加壳

【方案简介】:采用组件分离的思路,提取原始机器码进行异或加密,利用 C 语言编写 Loader 在内存中解密执行,最后用 UPX 加壳改变文件结构以绕过静态扫描。

操作步骤:

  1. 提取原始机器码,用 Python 进行 0xAA 异或加密,转为 C 语言数组格式。
  2. 编写 C 语言加载器,实现内存申请、密文拷贝、循环解密与执行。
  3. 编译生成 loader_20242323.exe 并进行 UPX 加壳。
  4. 上传至 VirScan 平台验证。

测试结果:加壳后的 loader_upx_20242323.exe 在 VirScan 上的检出率降至 5/48。报毒的 5 个引擎触发的多为 packed(加壳)规则,说明恶意特征码已被成功抹除。

【VirScan loader_upx 5/48截图】
image

关于替代 Veil-Evasion 的说明:
在实验初期,我尝试按照指导书执行 git clone https://github.com/Veil-Framework/Veil.git 并运行 sudo ./setup.sh -c 安装 Veil 框架。但由于该框架依赖的 Python 环境较老,与当前 Kali 系统存在严重兼容性问题,多次运行后报错无法正常加载模块。鉴于其固定模板特征早已被现代杀软广泛查杀,我决定放弃该工具,转而采用更底层的手写 C 语言 Loader 方案。

3.3 实机测试与回连验证

【方案简介】:在开启 Defender 的 Win10 虚拟机上验证加密 Loader 的静态查杀与动态运行情况,并进行反弹回连测试。

  1. 静态查杀测试:保持 Defender 实时保护全开,将 loader_upx_20242323.exe 下载至 Win10。文件成功落地且未被删除,实现了静态免杀。

【Win10 Defender全开,文件存活截图】
image

  1. 动态拦截现象:双击运行文件时,系统弹窗提示“无法成功完成操作,因为文件包含病毒或潜在的垃圾软件”。这说明程序运行时申请内存、执行解密代码的底层行为,触发了 Defender 的 EDR 行为监控,导致进程被阻断。

【双击运行被拦截报错截图】
image

  1. 回连验证测试与反思:
    为了确认自身编写的 C 语言代码(解密逻辑、网络连接)完全正确,而非代码 Bug 导致无法上线,我暂时关闭了 Defender 的实时保护进行了测试。再次双击运行后,成功回连到 Kali,执行 sysinfo 获取到了目标信息。

这证明我的免杀代码逻辑是可行的,之前的拦截纯粹是杀软动态行为监控在起作用。本次实操虽然未能用纯手写的本地数组 Loader 绕过 Defender 内核层的 EDR 拦截,但让我深刻认识到:要对抗现代顶级的动态防御,必须采用远程拉取 Shellcode 或间接 API 调用等更高级的分离加载技术。

【Kali 成功回连并执行 sysinfo 截图】
image

  1. 杀软版本记录:Windows Defender,反恶意软件客户端版本 4.18.26090.9,防病毒引擎版本 1.461.96.0。

【Windows 安全中心版本信息截图】
image

4.问题及解决方案

问题1:在编写 C 语言 Loader 时,第一次编译出来的程序双击运行后一闪而过,Kali 端 msfconsole 显示 Meterpreter session 1 opened 但紧接着提示 Reason: Died(会话死亡断开)。
解决方案:通过排查代码逻辑发现,C 语言主函数在调用执行 Shellcode 后立刻执行了 return 0;。主线程一退出,整个进程就被系统回收,导致内存中的木马程序也被强制终止。后来我在代码末尾添加了 while(1) { Sleep(1000); } 的死循环,让主进程保持挂起状态,成功解决了会话掉线的问题。

问题2:在提取加密 Shellcode 数组并粘贴到 C 代码中时,编译一直报错,或者生成的程序运行后内存报错崩溃。
解决方案:由于 msfvenom 生成出来的十六进制代码带有引号和换行符,手动复制极其容易漏掉字符或引入非法字符。后来我改用 Python 脚本,读取原始的二进制文件(raw),自动进行异或加密,并严格按照 C 语言数组的格式 0xXX, 0xXX 输出。通过脚本自动化处理,彻底解决了格式错误和偏移量计算错误的问题。

问题3:用浏览器直接通过 HTTP 下载生成的 loader_upx_20242323.exe 时,一直被 Edge 浏览器的 SmartScreen 拦截,提示文件不安全无法下载。
解决方案:为了绕过浏览器的信誉检查,我使用了 Windows 下的 ncat.exe 工具,在 Kali 端监听端口并输入文件内容,在 Windows 端使用 ncat.exe > 文件名 的重定向方式。通过这种底层的 TCP 数据流传输,成功将免杀文件传入了目标机。

5.学习感悟、思考等

这次实验让我对免杀技术有了更加具体的认识。

一开始,我以为使用 MSF 编码器多次编码就能绕过杀软,但在本地测试时,发现文件依然被瞬间查杀。后来,我通过手写 C 语言代码、使用异或加密和 UPX 加壳,成功将 VirScan 上的检出率降到了 5/48,并且文件能够在开启 Defender 的桌面上存活,这让我觉得静态免杀已经起作用了。

但在双击运行被拦截的那一刻,我意识到免杀是一个需要不断更新的过程。单纯修改文件特征已经不足以绕过现代杀软的防御,程序在内存中的运行行为同样会被监控。虽然这次回连测试是在关闭防护的情况下完成的,但这让我确认了我的代码逻辑没有问题。这次实验让我明白了,要对抗现代的安全机制,仅仅改变文件表面是不够的,还需要深入学习更底层的加载和执行技术,比如分离式加载或远程拉取,这也是我以后需要继续摸索的方向。

6.回答问题

(1)杀软是如何检测出恶意代码的?
主要通过三种方式:一是特征码检测,通过比对文件中的特定字节或哈希值;二是启发式检测,通过分析文件的结构、是否加壳或调用了敏感函数来判断;三是行为监控,在程序运行时监控其是否执行了恶意操作,如内存注入等。

(2)免杀是做什么?
免杀就是对恶意代码进行处理,使其在静态文件扫描、启发式分析或运行时行为监控中,不被杀毒软件发现,从而能够顺利执行。

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

  1. 修改特征码:如使用 MSF 编码器、添加花指令。
  2. 加壳与混淆:使用 UPX 等工具改变文件结构和熵值。
  3. 组件分离与内存加载:自己编写加载器,将加密的 Shellcode 分离存放,运行时在内存中解密执行。
  4. 无文件攻击:利用脚本语言在内存中直接执行代码。

参考资料

posted @ 2026-10-24 19:58  zzzlg  阅读(5)  评论(0)    收藏  举报