HTB: OpTinselTrace-5 Writeup

OpTinselTrace-5 - HackTheBox Writeup

Machine Information

AttributeDetails
NameOpTinselTrace-5
CategoryDigital Forensics & Incident Response (HTB Sherlock)
OSWindows Server (Domain Controller — offline KAPE triage image)
DifficultyHard
PointsN/A
Release DateN/A
IP AddressN/A (static forensic artifact bundle, no live host)
Authord3vn0mi

Machine Rating

⭐⭐⭐⭐☆ (4/5)

Difficulty Assessment:

  • Enumeration: ⭐⭐⭐⭐☆
  • Real-world: ⭐⭐⭐⭐⭐
  • CVE: ⭐⭐⭐☆☆
  • CTF-like: ⭐⭐⭐☆☆

Summary

OpTinselTrace-5 (HTB Sherlock #582) is a DFIR case built around a KAPE triage collection from DC01.northpole.local — a domain controller purchased second-hand from an MSSP whose previous tenant was forela.local. The scenario tasks the investigator with proving that Christmas is, in fact, doomed: attackers popped the DC via Zerologon (CVE-2020-1472), planted a literally-named vulnerable_to_zerologon service, pivoted through a compromised bytesparkle account to install a VNC backdoor as a scheduled task, and finished by deploying a NotPetya-flavored XOR “ransomware” DLL (splunk_svc.dll) sideloaded via rundll32.exe. The case is deliberately noisy: a legitimate Domain Admins addition and two leftover scheduled tasks from the server’s previous forela.local life are planted as decoys that have to be manually ruled out. The hardest question — identifying the actual encrypting process — can’t be answered from Sysmon or 4688 (neither covers the relevant window), forcing a pivot into the rarely-used Microsoft-Windows-UAC-FileVirtualization/Operational log to recover the PID from tagged file-write events.

TL;DR: Zerologon (CVE-2020-1472) resets the DC01$ machine account password from an anonymous session → attacker authenticates and installs a rogue service (hAvbdksT.exe) → bytesparkle account is used to register a VNC-backdoor scheduled task (svc_vnc) → a XOR-based ransomware DLL (splunk_svc.dll, key EncryptingC4Fun!) is loaded via rundll32.exe (PID 5828) and encrypts files to .xmax → decrypting OperationStarLightJourney.pdf.xmax reveals the sleigh is pulled by enchanted unicorns.


Reconnaissance

Case Intake & Artifact Recovery

The Sherlock’s bundled evidence file, DC01.northpole.local-KAPE.zip, was delivered as a 0-byte file — a broken download rather than a puzzle. Rather than treat this as unsolvable, I went straight to the HTB v4 API to re-pull the real artifact bundle for Sherlock ID 582:

# Pull sherlock metadata/tasks and the real download link directly from the HTB API
import lib.htb_api as h
c = h.HTBClient()
info = c.sherlock_info(582)
tasks = c.sherlock_tasks(582)
dl = c.sherlock_download_link(582)['url']
# Stream the real (non-zero-byte) archive down
r = c.session.get(dl, stream=True, timeout=900)
with open('dl.zip', 'wb') as f:
for chunk in r.iter_content(1 << 20):
f.write(chunk)

The archive is protected with two layers of password:

Terminal window
# Outer archive password
7z x -y -phacktheblue -oex dl.zip
cat ex/DANGER.txt # reveals the inner malware-zip password
# -> ZPD8LhraU1hx
# Inner "handle with care" zip holding the suspicious binary
7z x -y -pZPD8LhraU1hx -osus ex/encrypted_files_suspicious_file.zip

Extraction produced two evidence sets:

  • kape/DC01.northpole.local-KAPE/uploads/auto/C%3A/... — a full KAPE triage collection off the domain controller, including Windows/System32/winevt/Logs (all .evtx files) and Windows/System32/Tasks (scheduled task XML definitions).
  • sus/encrypted_files_suspicious_file/ — the “suspicious file” package: splunk_svc.dll, a README.txt ransom note, and a set of .xmax-extension files that were the ransomware’s encrypted output, plus the DANGER.txt-referenced malware sample.

Service Enumeration

Parsing the .evtx files required a Python-native EVTX reader since no live host was available to query:

# Minimal EVTX -> (timestamp, event_id, data_dict) extraction helper
from evtx import PyEvtxParser
import re, json
def recs(path, eids=None):
parser = PyEvtxParser(path)
for r in parser.records_json():
data = json.loads(r['data'])
eid = data['Event']['System']['EventID']
if eids and eid not in eids:
continue
yield r['timestamp'], eid, data

I ran this against System.evtx and Security.evtx, filtering for the event IDs most relevant to a domain-controller compromise: 7045 (service installed), 4742 (computer account changed), 4624/4625 (logon/failed logon), 4648 (explicit credentials), 4724/4728/4737/4738 (account/group management), and 4688 (process creation, where present).

Vulnerability Assessment

Two findings stood out immediately from System.evtx:

  • A service install (EID 7045) literally named vulnerable_to_zerologon, with an image path of %systemroot%\hAvbdksT.exe — an unmissable, deliberately obvious IOC.
  • The corresponding Security.evtx EID 4742** entry showing the **DC01$** machine account's password attribute changed by **ANONYMOUS LOGON`, sourced from an internal jump-host IP — the textbook fingerprint of a Netlogon (Zerologon) machine-account password reset.

This confirmed the initial access vector as CVE-2020-1472 (Zerologon) before any further timeline work was done.


Initial Foothold

Exploitation Path — Zerologon (CVE-2020-1472)

Zerologon abuses a flaw in Microsoft’s implementation of AES-CFB8 within the Netlogon Remote Protocol (MS-NRPC): the IV used to encrypt the NetrServerAuthenticate3 credential exchange is always a fixed all-zero block instead of a random value. Because AES-CFB8 with an all-zero IV and an all-zero plaintext has roughly a 1-in-256 chance of producing an all-zero ciphertext, an attacker can brute-force a valid “authenticated” Netlogon session against a domain controller in a few thousand attempts — with zero credentials — and then use that session to reset the DC’s own machine account (DC01$) password to an empty string via NetrServerPasswordSet2. Once the DC’s own AD computer account is compromised, the attacker effectively has domain-admin-equivalent access via DCSync or by relaying that trust further.

I reconstructed the timeline directly from the two event log artifacts:

# Cross-reference System.evtx (service install) against Security.evtx (4742 password reset)
# on the same UTC timestamp window to nail down the exploit time
for ts, eid, d in sorted(system_records):
if eid == 7045:
print(ts, d['Event']['EventData'])
# -> ServiceName: vulnerable_to_zerologon
# -> ImagePath: %systemroot%\hAvbdksT.exe

Results:

EvidenceTimestamp (UTC)Source
Zerologon exploit / DC01$ account password reset (EID 4742, actor ANONYMOUS LOGON)2023-12-13 09:24:23Security.evtx
Malicious service vulnerable_to_zerologon → hAvbdksT.exe installed (EID 7045)2023-12-13 09:24:24System.evtx

The one-second gap between the account-password reset and the rogue service installation is exactly what you’d expect from an automated Zerologon exploit chain (e.g., the classic zerologon_tester.py → DCSync/secretsdump → service-based command execution workflow): reset the trust, immediately abuse it to push a service.

Post-Exploitation — Persistence & Lateral Activity

With the DC’s machine trust broken, the accounts observed being used across the timeline were Administrator and Bytesparkle. The bytesparkle account was used to register a scheduled task at:

\Microsoft\svc_vnc
Action: C:\Users\bytesparkle\Downloads\svc\svchost.exe

This is a classic masquerading trick — naming a dropped binary svchost.exe and burying it under a user’s Downloads folder to blend into process-listing noise, while the task path (\Microsoft\svc_vnc) hides among legitimate-looking Microsoft task folders. Functionally, this is a VNC-based remote-access backdoor persistence mechanism.

Terminal window
# Inspecting the Tasks folder pulled by KAPE
T="kape/DC01.northpole.local-KAPE/uploads/auto/C%3A/Windows/System32/Tasks"
for f in "$T/Microsoft/svc_vnc" "$T/lamod.exe" "$T/npcapwatchdog"; do
echo "=== $f"; ls -la "$f"
done

That same command surfaced two decoys: scheduled tasks named lamod.exe and npcapwatchdog sitting outside the Microsoft folder tree. Cross-referencing their creation timestamps and registering SIDs against the account-management events showed they predated the Zerologon compromise entirely — leftover artifacts from the server’s prior life on forela.local before it was sold second-hand to Northpole. A second potential decoy — Snowdrop being added to Domain Admins at 09:19:52 — also checked out as legitimate: it traced back to bytesparkle’s own interactive console session from the evening before the attack, not to attacker activity.


Privilege Escalation

Note: as a DFIR Sherlock rather than a live-exploitation box, there is no traditional “privesc” step post-Zerologon — the attacker already holds domain-controller-equivalent trust from the initial foothold. The work here is reconstructing impact (ransomware deployment) and recovering the executing process despite missing telemetry.

Ransomware Analysis — splunk_svc.dll

The splunk_svc.dll sample pulled from the “suspicious file” package strongly resembles a NotPetya-style loader:

Terminal window
strings -n 6 splunk_svc.dll | head -80

The strings dump revealed a very telling PDB debug path — Not_Petya_XOR_Dll — immediately flagging this as a XOR-based file-encryption payload rather than a real cryptographic ransomware. Critically, the same strings pass also leaked the plaintext repeating-key XOR key:

EncryptingC4Fun!

Sloppy operational security by the “Grinch” threat actor — no key management, no obfuscation, key sitting in cleartext inside the DLL. I wrote a small decryptor and ran it against every .xmax file recovered from the evidence package:

# Repeating-key XOR decryption of the ransomware's .xmax output files
k = b'EncryptingC4Fun!'
import glob, os
os.makedirs('/tmp/dec', exist_ok=True)
for f in glob.glob('*.xmax'):
data = open(f, 'rb').read()
out = bytes(b ^ k[i % len(k)] for i, b in enumerate(data))
open(f'/tmp/dec/{os.path.basename(f)[:-5]}', 'wb').write(out)
# strips the trailing .xmax extension the ransomware appended

One of the recovered documents, OperationStarLightJourney.pdf, decrypted cleanly:

Terminal window
pip install pdfminer.six
python3 -c "
from pdfminer.high_level import extract_text
print(extract_text('OperationStarLightJourney.pdf'))
"

The recovered text described the Celestial Carriage as being “powered by a team of enchanted unicorns” — answering the case’s lore/flavor question about the sleigh creature.

Recovering the Encrypting Process — PID 5828

The hardest question in the case is identifying which running process actually performed the file encryption. Standard telemetry didn’t help:

  • No Sysmon was installed/collected on this host.
  • Windows Security auditing’s 4688 (process creation) events only covered the boot window, well before the ransomware ran.

Rather than give up, I searched the full KAPE bundle for any other operational log that might tag process execution against file activity, and found Microsoft-Windows-UAC-FileVirtualization/Operational — a log most investigators skip, normally used to track legacy UAC file-virtualization redirects (writes into protected directories by non-elevated processes getting silently redirected to a per-user virtual store):

Terminal window
find . -iname '*UAC-FileVirtualization*'

Parsing that log for events tied to the .xmax extension surfaced 46 file-write events, every single one tagged with the same execution metadata:

System/Execution/@ProcessID = 5828
Image = rundll32.exe

Because splunk_svc.dll is a DLL (not a standalone EXE), the attacker executed it via rundll32.exe splunk_svc.dll,<entrypoint> — a classic LOLBin technique to run arbitrary DLL code under a trusted Microsoft binary’s process name, evading naive process-name allowlisting. The UAC-FileVirtualization log incidentally captured this because the encryption routine’s file writes into what the OS treated as a UAC-virtualized path were logged with the originating process ID attached — giving up the PID that no other available log source could provide.


Attack Chain Summary

0-byte provided KAPE.zip → re-pulled real bundle via HTB v4 API (7z: hacktheblue → ZPD8LhraU1hx)
↓
Zerologon (CVE-2020-1472): DC01$ machine account password reset by ANONYMOUS LOGON [2023-12-13 09:24:23]
↓
Rogue service "vulnerable_to_zerologon" → hAvbdksT.exe installed on DC01 [2023-12-13 09:24:24]
↓
Attacker operates as Administrator / bytesparkle
↓
Persistence: scheduled task \Microsoft\svc_vnc → svc\svchost.exe (VNC backdoor)
↓
Ransomware deployment: rundll32.exe (PID 5828) loads splunk_svc.dll ("Not_Petya_XOR_Dll")
↓
Files XOR-encrypted with key "EncryptingC4Fun!" → .xmax extension
↓
Decryption reveals lore doc: sleigh powered by enchanted Unicorns
↓
(Decoys ruled out: legitimate Snowdrop DA addition; leftover forela.local tasks lamod.exe / npcapwatchdog)

Tools Used

ToolPurpose
Custom HTB v4 API client (Python)Re-downloading the corrupted 0-byte evidence bundle directly from HTB
7zExtracting the double-password-protected evidence archives
evtx (PyEvtxParser, Python)Parsing System.evtx / Security.evtx into structured JSON records
stringsRecovering the malware’s PDB debug path and plaintext XOR key from splunk_svc.dll
Custom Python XOR decryptorReversing the ransomware’s repeating-key XOR encryption on .xmax files
pdfminer.six / pdftotextExtracting text from the decrypted OperationStarLightJourney.pdf
Manual .evtx/Tasks folder reviewRuling out decoys (leftover forela.local scheduled tasks, legitimate DA addition)
Microsoft-Windows-UAC-FileVirtualization/Operational logRecovering the encrypting process’s PID (5828) when Sysmon/4688 were unavailable

Key Learnings

Techniques Practiced

  • Reconstructing a Zerologon (CVE-2020-1472) compromise timeline purely from System.evtx (EID 7045) and Security.evtx (EID 4742) artifacts, without a live network capture.
  • Recovering a ransomware payload’s XOR key via static strings analysis before attempting any deeper reverse engineering.
  • Writing a minimal, self-contained decryptor to reverse a repeating-key XOR “ransomware” and recover victim documents.
  • Identifying LOLBin abuse (rundll32.exe sideloading a malicious DLL) from indirect evidence when direct process-creation telemetry (Sysmon, 4688) is unavailable.
  • Using an unconventional Windows operational log (UAC-FileVirtualization) as a substitute source of process-tagged file activity.
  • Distinguishing genuine decoy/noise artifacts (legacy scheduled tasks from a previous domain tenant, legitimate administrative actions) from real attacker TTPs in a deliberately noisy case.

Lessons Learned

  1. A DC’s own machine account (<hostname>$) having its password reset by ANONYMOUS LOGON (EID 4742) is one of the highest-confidence single indicators of Zerologon exploitation — it should be an automatic, non-negotiable hunt query on any DC.
  2. Malware authors frequently leave debug artifacts — PDB paths, and in this case the entire symmetric key — sitting in plaintext inside the binary. Running strings before any disassembly or dynamic analysis can shortcut hours of reverse engineering.
  3. When primary process-creation telemetry (Sysmon, 4688) doesn’t cover the incident window, secondary/operational logs that happen to tag ProcessID against unrelated activity (here, legacy UAC file virtualization) can still recover attribution — it’s worth enumerating every .evtx in a KAPE bundle, not just the “usual suspects.”
  4. Second-hand/repurposed infrastructure (this DC was previously on forela.local before being sold to Northpole) can carry forward stale artifacts — old scheduled tasks, leftover binaries — that look suspicious but predate the actual incident and must be timeline-correlated out rather than assumed malicious.
  5. If a provided evidence bundle is corrupted (e.g., a 0-byte zip), don’t treat that as a dead end — go back to the platform’s API to re-pull the artifact before concluding the case is unsolvable.

Proof of Ownership

Sherlock: OpTinselTrace-5 (#582)
Tasks Completed: 9/9 (100%)
Final Flag: <redacted>